tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: vnd.c 1.254



    Date:        Sun, 17 Jan 2016 23:42:25 +0100
    From:        Manuel Bouyer <bouyer%antioche.eu.org@localhost>
    Message-ID:  <20160117224225.GA9174%asim.lip6.fr@localhost>

Re-opening an old thread after some off list discussions ...

  | once again, I don't care. vnconfig -l in both cases lists busy and
  | free vnd devices, and from this list the user can pick a free device
  | for use. this is all what matters for the end user.

I have yet to see any evidence of any actual users actually using that
technique to find a free vnd device - it seems to be all just speculation.

The errors that you get on NetBSD 7 from vnconfig -l are because ticket
1076 didn't get pulled up.   That should happen asap (the effect is to
return vnconfig to the exact same (source) code it had on NetBSD 6 (and
earlier.))

All that said, I offer the following patch (inspired by an earlier,
simpler, one from Martin Husemann) which makes two changes to vnconfig
(also called vndconfig in current.)

First, it allows vnconfig -l dev... rather than just vnconfig -l dev
(ie: you can give more than one device to list), so if you really need
to get the status of all vnd devices in /dev, you can just do

	vn[d]config -l /dev/vnd*d

And second, it adds a -m N (N is a decimal integer) that can be used
instead of device names with -l, to specify the minimum number of vnds
vn[d]condig should list (it will list more if the kernel knows more,
and with current kernels, that always means it will list some multiple of 4.)
As a special case, -m 0 causes all output of unused vnd's to be suppressed,
and suppresses error messages (but still returns a non-zero exit code)
in the case that either there is no /dev/vnd0* existing, or the kernel
does not have the vnd driver configured.)   The default value for -m is 4
for compatibility with ancient versions of vnconfig (which typically listed
4 vnds if the kernel had the vnd driver, and /dev/vnd0d existed)

There is also a minor change in the patch below to make the first line of
the usage output fit within 80 columns - that's irrelevant to everything
else, and can be dropped if consensus is for more verbose usage, even if
it wraps on "normal" width terminals.   (It is not worth checking the
terminal width, that would just be adding bloat.)

If this method is acceptable to everyone (or perhaps most people) I will
make a patch for the man page, and submit it all to be committed.

We still need to work out what is going on in PR 50659 - I assure you
it is not caused by any changes to vnconfig (as since ticket 1076 has not
been pulled up, there have been no changes to vnconfig on the netbsd-7
branch between NetBSD 7.0 release and now).  I cannot see how the pullup
from ticket 1038 (kernel only vnd changes) can have affected it either, as
that (at least by intent) was only supposed to affect the way vnconfig -l
works (getting status of vnds) and should not in any way change what happens
when configuring a vnd, which apparently is what is happening in 50659,
- so unless there is something there I cannot see, whatever is happening
in 50659 should have been happening since 7.0 release.

kre

--- vnconfig.c.orig	2016-03-22 20:40:36.000000000 +0700
+++ vnconfig.c	2016-03-22 21:39:38.000000000 +0700
@@ -87,28 +87,36 @@
 #include <unistd.h>
 #include <util.h>
 #include <paths.h>
+#include <limits.h>
 
 #define VND_CONFIG	1
 #define VND_UNCONFIG	2
 #define VND_GET		3
 
+/* with -l we always print at least this many entries */
+#define	DUMMY_FREE	4
+
 static int	verbose = 0;
 static int	readonly = 0;
 static int	force = 0;
 static int	compressed = 0;
+static int	minimum = DUMMY_FREE;
 static char	*tabname;
 
-static int	show(int, int);
+static int	show(int, int, const char * const);
 static int	config(char *, char *, char *, int);
 static int	getgeom(struct vndgeom *, char *);
 __dead static void	usage(void);
+static void	show_unused(int);
 
 int
 main(int argc, char *argv[])
 {
 	int ch, rv, action = VND_CONFIG;
+	char *end;
+	unsigned long v;
 
-	while ((ch = getopt(argc, argv, "Fcf:lrt:uvz")) != -1) {
+	while ((ch = getopt(argc, argv, "Fcf:lm:rt:uvz")) != -1) {
 		switch (ch) {
 		case 'F':
 			force = 1;
@@ -123,6 +131,12 @@
 		case 'l':
 			action = VND_GET;
 			break;
+		case 'm':
+			v = strtoul(optarg, &end, 10);
+			if (v >= INT_MAX || end == optarg || *end != '\0')
+				usage();
+			minimum = (int)v;
+			break;
 		case 'r':
 			readonly = 1;
 			break;
@@ -163,29 +177,54 @@
 		const char *vn;
 		char path[64];
 
-		if (argc != 0 && argc != 1)
-			usage();
+		if (argc == 0) {
+			vn = "vnd0";
 
-		vn = argc ? argv[0] : "vnd0";
+			v = opendisk(vn, O_RDONLY, path, sizeof(path), 0);
+			if (v == -1) {
+				if (minimum == 0)
+					return 1;
+				err(1, "open: %s", vn);
+			}
 
-		v = opendisk(vn, O_RDONLY, path, sizeof(path), 0);
-		if (v == -1)
-			err(1, "open: %s", vn);
-
-		if (argc)
-			show(v, -1);
-		else {
-			for (n = 0; show(v, n); n++)
+			for (n = 0; show(v, n, 0); n++)
 				continue;
+			while (n < minimum)
+				show_unused(n++);
+			close(v);
+			return 0;
 		}
-		close(v);
+			
 		rv = 0;
+		while (--argc >= 0) {
+			vn = *argv++;
+
+			v = opendisk(vn, O_RDONLY, path, sizeof(path), 0);
+			if (v == -1) {
+				warn("open: %s", vn);
+				rv = 1;
+				continue;
+			}
+
+			if (!show(v, -1, vn))
+				rv = 1;
+			close(v);
+		}
 	}
 	return rv;
 }
 
+static void
+show_unused(int n)
+{
+	if (minimum == 0) 
+		return;
+
+	printf("vnd%d: not in use\n", n);
+}
+
 static int
-show(int v, int n)
+show(int v, int n, const char * const name)
 {
 	struct vnd_user vnu;
 	char *dev;
@@ -194,14 +233,17 @@
 
 	vnu.vnu_unit = n;
 	if (ioctl(v, VNDIOCGET, &vnu) == -1) {
-		if (errno != ENXIO)
-			err(1, "VNDIOCGET");
+		if (errno != ENXIO) {
+			if (n != -1)
+				err(1, "VNDIOCGET");
+			warn("%s: VNDIOCGET", name);
+		}
 		return 0;
 	}
 
 	if (vnu.vnu_ino == 0) {
-		printf("vnd%d: not in use\n", vnu.vnu_unit);
-		return 1;
+		show_unused(vnu.vnu_unit);
+		return -1;
 	}
 
 	printf("vnd%d: ", vnu.vnu_unit);
@@ -383,9 +425,9 @@
 {
 
 	(void)fprintf(stderr, "%s%s",
-	    "usage: vnconfig [-crvz] [-f disktab] [-t typename] vnode_disk"
-		" regular-file [geomspec]\n",
+	    "usage: vnconfig [-crvz] [-f dsktab] [-t type] vnode_disk"
+		" reg-file [geomspec]\n",
 	    "       vnconfig -u [-Fv] vnode_disk\n"
-	    "       vnconfig -l [vnode_disk]\n");
+	    "       vnconfig -l [-m num | vnode_disk...]\n");
 	exit(1);
 }




Home | Main Index | Thread Index | Old Index