Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 2 Jul 2007 21:52:04 GMT
From:      Ulf Lilleengen <lulf@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 122746 for review
Message-ID:  <200707022152.l62Lq4RK020054@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=122746

Change 122746 by lulf@lulf_carrot on 2007/07/02 21:51:06

	- Add concat, mirror and stripe commands.
	- Create userland routines used for parsing the configuration and
	  looking for names.
	- Create kernel routines that uses the event-system to create the
	  objects that is needed, and connects them the same way that vinum
	  does.
	- Add geom_vinum_create.c that holds these routines for the kernel.
	  Perhaps moving the gv_create_* routines here as well, since they don't
	  really belong into the events source-file.
	
	The commands should work exactly the same way as in vinum. Also, there
	are alot of printouts currently, since I need them to test this a bit
	more.

Affected files ...

.. //depot/projects/soc2007/lulf/gvinum_fixup/sbin/gvinum/gvinum.c#10 edit
.. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum.c#24 edit
.. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum.h#19 edit
.. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_create.c#1 add
.. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_subr.c#15 edit
.. //depot/projects/soc2007/lulf/gvinum_fixup/sys/modules/geom/geom_vinum/Makefile#2 edit

Differences ...

==== //depot/projects/soc2007/lulf/gvinum_fixup/sbin/gvinum/gvinum.c#10 (text+ko) ====

@@ -56,11 +56,13 @@
 #include "gvinum.h"
 
 void	gvinum_attach(int, char **);
+void	gvinum_concat(int, char **);
 void	gvinum_create(int, char **);
 void	gvinum_detach(int, char **);
 void	gvinum_help(void);
 void	gvinum_list(int, char **);
 void	gvinum_move(int, char **);
+void	gvinum_mirror(int, char **);
 void	gvinum_parityop(int, char **, int);
 void	gvinum_printconfig(int, char **);
 void	gvinum_rename(int, char **);
@@ -70,9 +72,15 @@
 void	gvinum_setstate(int, char **);
 void	gvinum_start(int, char **);
 void	gvinum_stop(int, char **);
+void	gvinum_stripe(int, char **);
 void	parseline(int, char **);
 void	printconfig(FILE *, char *);
 
+char	*create_drive(char *);
+void	 create_volume(int, char **, char *);
+char	*find_name(const char *, int, int);
+char	*find_pattern(char *, char *);
+
 int
 main(int argc, char **argv)
 {
@@ -362,6 +370,223 @@
 	gctl_free(req);
 }
 
+/* Create a concatenated volume. */
+void
+gvinum_concat(int argc, char **argv)
+{
+
+	printf("Preparing\n");
+	if (argc < 2) {
+		warnx("usage:\tconcat [-fv] [-n name] drives\n");
+		return;
+	}
+	create_volume(argc, argv, "concat");
+}
+
+
+/* Create a drive quick and dirty. */
+char *
+create_drive(char *device)
+{
+	struct gv_drive *d;
+	struct gctl_req *req;
+	const char *errstr;
+	char *drivename;
+	int drives, volumes, subdisks, plexes;
+
+	plexes = subdisks = volumes = 0;
+	drives = 1;
+	printf("Trying to create drive on %s\n", device);
+
+	/* Strip away eventual /dev/ in front. */
+	if (strncmp(device, "/dev/", 5) == 0)
+		device += 5;
+
+	drivename = find_name("gvinumdrive", GV_TYPE_DRIVE, GV_MAXDRIVENAME);
+	if (drivename == NULL)
+		return (NULL);
+
+	fprintf(stderr, "Drivename %s is okay\n", drivename);
+	req = gctl_get_handle();
+	gctl_ro_param(req, "class", -1, "VINUM");
+	gctl_ro_param(req, "verb", -1, "create");
+	d = malloc(sizeof(struct gv_drive));
+	if (d == NULL)
+		err(1, "unable to allocate for gv_drive object");
+	memset(d, 0, sizeof(struct gv_drive));
+
+	strlcpy(d->name, drivename, GV_MAXDRIVENAME);
+	strlcpy(d->device, device, GV_MAXDRIVENAME);
+	gctl_ro_param(req, "drive0", sizeof(*d), d);
+	gctl_ro_param(req, "drives", sizeof(int), &drives);
+	gctl_ro_param(req, "volumes", sizeof(int), &volumes);
+	gctl_ro_param(req, "plexes", sizeof(int), &plexes);
+	gctl_ro_param(req, "subdisks", sizeof(int), &subdisks);
+	fprintf(stderr, "Creating drive request sent to kernel...\n");
+	errstr = gctl_issue(req);
+	if (errstr != NULL)
+		warnx("error creating drive: %s", errstr);
+	gctl_free(req);
+	printf("Done creating drive %s on %s\n", drivename, device);
+	return (drivename);
+}
+
+/* 
+ * General routine for creating a volume. Mainly for use by concat, mirror and
+ * stripe commands.
+ */
+void
+create_volume(int argc, char **argv, char *verb)
+{
+	struct gctl_req *req;
+	const char *errstr;
+	char buf[BUFSIZ], *drivename, *volname;
+	int drives, flags, i;
+
+	flags = 0;
+	drives = 0;
+	volname = NULL;
+	/* XXX: Should we check for argument length? */
+
+	req = gctl_get_handle();
+	gctl_ro_param(req, "class", -1, "VINUM");
+
+	for (i = 1; i < argc; i++) {
+		if (!strcmp(argv[i], "-f")) {
+			flags |= GV_FLAG_F;
+		} else if (!strcmp(argv[i], "-n")) {
+			volname = argv[++i];
+		} else if (!strcmp(argv[i], "-v")) {
+			flags |= GV_FLAG_V;
+		} else if (!strcmp(argv[i], "-s")) {
+			flags |= GV_FLAG_S;
+		} else {
+			/* Assume it's a drive. */
+			snprintf(buf, sizeof(buf), "drive%d", drives++);
+
+			/* First we create the drive. */
+			drivename = create_drive(argv[i]); 
+			if (drivename == NULL)
+				goto bad;
+			/* Then we add it to the request. */
+			gctl_ro_param(req, buf, -1, drivename);
+		}
+	}
+
+	/* Find a free volume name. */
+	if (volname == NULL) {
+		fprintf(stderr, "Finding name\n");
+		volname = find_name("gvinumvolume", GV_TYPE_VOL, GV_MAXVOLNAME);
+		fprintf(stderr, "Found name %s\n", volname);
+	}
+
+	/* Then we send a request to actually create the volumes. */
+	gctl_ro_param(req, "verb", -1, verb);
+	gctl_ro_param(req, "flags", sizeof(int), &flags); 
+	gctl_ro_param(req, "drives", sizeof(int), &drives);
+	gctl_ro_param(req, "name", -1, volname);
+	errstr = gctl_issue(req);
+	if (errstr != NULL)
+		warnx("creating %s volume failed: %s", verb, errstr);
+bad:
+	gctl_free(req);
+}
+
+/* Parse a line of the config, return the word after <pattern>. */
+char *
+find_pattern(char *line, char *pattern)
+{
+	char *ptr;
+
+	ptr = strsep(&line, " ");
+	while (ptr != NULL) {
+		if (!strcmp(ptr, pattern)) {
+			/* Return the next. */
+			ptr = strsep(&line, " ");
+			return (ptr);
+		}
+		ptr = strsep(&line, " ");
+	}
+	return (NULL);
+}
+
+/* Find a free name for an object given a a prefix. */
+char *
+find_name(const char *prefix, int type, int namelen)
+{
+	struct gctl_req *req;
+	char comment[1], buf[GV_CFG_LEN - 1], *name, *sname, *ptr;
+	const char *errstr;
+	int i, n, begin, len, conflict;
+	char line[1024];
+
+	comment[0] = '\0';
+
+	/* Find a name. Fetch out configuration first. */
+	printf("Fetching configuration\n");
+	req = gctl_get_handle();
+	gctl_ro_param(req, "class", -1, "VINUM");
+	gctl_ro_param(req, "verb", -1, "getconfig");
+	gctl_ro_param(req, "comment", -1, comment);
+	gctl_rw_param(req, "config", sizeof(buf), buf);
+	errstr = gctl_issue(req);
+	if (errstr != NULL) {
+		warnx("can't get configuration: %s", errstr);
+		return (NULL);
+	}
+	gctl_free(req);
+
+	printf("Got configuration:\n");
+	printf(buf);
+	begin = 0;
+	len = strlen(buf);
+	i = 0;
+	sname = malloc(namelen + 1);
+
+	/* XXX: Max object setting? */
+	for (n = 0; n < 10000; n++) {
+		snprintf(sname, namelen, "%s%d", prefix, n);
+		conflict = 0;
+		begin = 0;
+		/* Loop through the configuration line by line. */
+		for (i = 0; i < len; i++) {
+			if (buf[i] == '\n' || buf[i] == '\0') {
+				ptr = buf + begin;
+				strlcpy(line, ptr, (i - begin) + 1);
+				printf("Processing line: .%s.\n", line);
+				begin = i + 1;
+				switch (type) {
+				case GV_TYPE_DRIVE:
+					name = find_pattern(line, "drive");
+					break;
+				case GV_TYPE_VOL:
+					name = find_pattern(line, "volume");
+					break;
+				case GV_TYPE_PLEX:
+				case GV_TYPE_SD:
+					name = find_pattern(line, "name");
+					break;
+				default:
+					printf("Invalid type given\n");
+					continue;
+				}
+				if (name == NULL)
+					continue;
+				printf("Found a name: .%s.\n", name);
+				if (!strcmp(sname, name)) {
+					printf("Conflicts, try next\n");
+					conflict = 1;
+					/* XXX: Could quit the loop earlier. */
+				}
+			}
+		}
+		if (!conflict)
+			return (sname);
+	}
+	free(sname);
+	return (NULL);
+}
+
 /* Detach a plex or subdisk from its parent. */
 void
 gvinum_detach(int argc, char **argv)
@@ -412,6 +637,8 @@
 	    "attach plex volume [rename]\n"
 	    "attach subdisk plex [offset] [rename]\n"
 	    "        Attach a plex to a volume, or a subdisk to a plex\n"
+	    "concat [-fv] [-n name] drives\n"
+	    "        Create a concatenated volume from the specified drives.\n"
 	    "detach [-f] [plex | subdisk]\n"
 	    "        Detach a plex or a subdisk from the volume or plex to\n"
 	    "        which it is attached.\n"
@@ -425,6 +652,8 @@
 	    "        List information about plexes.\n"
 	    "lv [-r] [-v] [-V] [volume]\n"
 	    "        List information about volumes.\n"
+	    "mirror [-fsv] [-n name] drives\n"
+	    "        Create a mirrored volume from the specified drives.\n"
 	    "move | mv -f drive object ...\n"
 	    "        Move the object(s) to the specified drive.\n"
 	    "quit    Exit the vinum program when running in interactive mode."
@@ -447,6 +676,8 @@
 	    "        poses only.\n"
 	    "start [-S size] volume | plex | subdisk\n"
 	    "        Allow the system to access the objects.\n"
+	    "stripe [-fv] [-n name] drives\n"
+	    "        Create a striped volume from the specified drives.\n"
 	);
 
 	return;
@@ -572,6 +803,18 @@
 	return;
 }
 
+/* Create a mirrored volume. */
+void
+gvinum_mirror(int argc, char **argv)
+{
+
+	if (argc < 2) {
+		warnx("usage\tmirror [-fsv] [-n name] drives\n");
+		return;
+	}
+	create_volume(argc, argv, "mirror");
+}
+
 /* Note that move is currently of form '[-r] target object [...]' */
 void
 gvinum_move(int argc, char **argv)
@@ -960,6 +1203,18 @@
 	exit(0);
 }
 
+/* Create a striped volume. */
+void
+gvinum_stripe(int argc, char **argv)
+{
+
+	if (argc < 2) {
+		warnx("usage:\tstripe [-fv] [-n name] drives\n");
+		return;
+	}
+	create_volume(argc, argv, "stripe");
+}
+
 void
 parseline(int argc, char **argv)
 {
@@ -974,6 +1229,8 @@
 		gvinum_attach(argc, argv);
 	else if (!strcmp(argv[0], "detach"))
 		gvinum_detach(argc, argv);
+	else if (!strcmp(argv[0], "concat"))
+		gvinum_concat(argc, argv);
 	else if (!strcmp(argv[0], "help"))
 		gvinum_help();
 	else if (!strcmp(argv[0], "list") || !strcmp(argv[0], "l"))
@@ -986,6 +1243,8 @@
 		gvinum_list(argc, argv);
 	else if (!strcmp(argv[0], "lv"))
 		gvinum_list(argc, argv);
+	else if (!strcmp(argv[0], "mirror"))
+		gvinum_mirror(argc, argv);
 	else if (!strcmp(argv[0], "move"))
 		gvinum_move(argc, argv);
 	else if (!strcmp(argv[0], "mv"))
@@ -1006,6 +1265,8 @@
 		gvinum_start(argc, argv);
 	else if (!strcmp(argv[0], "stop"))
 		gvinum_stop(argc, argv);
+	else if (!strcmp(argv[0], "stripe"))
+		gvinum_stripe(argc, argv);
 	else if (!strcmp(argv[0], "checkparity"))
 		gvinum_parityop(argc, argv, 0);
 	else if (!strcmp(argv[0], "rebuildparity"))

==== //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum.c#24 (text+ko) ====

@@ -410,6 +410,9 @@
 	if (!strcmp(verb, "attach")) {
 		gv_attach(sc, req);
 
+	} else if (!strcmp(verb, "concat")) {
+		gv_concat(gp, req);
+
 	} else if (!strcmp(verb, "detach")) {
 		gv_detach(sc, req);
 
@@ -433,6 +436,9 @@
 	} else if (!strcmp(verb, "create")) {
 		gv_create(gp, req);
 
+	} else if (!strcmp(verb, "mirror")) {
+		gv_mirror(gp, req);
+
 	} else if (!strcmp(verb, "move")) {
 		gv_move(gp, req);
 
@@ -452,6 +458,9 @@
 	} else if (!strcmp(verb, "start")) {
 		gv_start_obj(gp, req);
 
+	} else if (!strcmp(verb, "stripe")) {
+		gv_stripe(gp, req);
+
 	} else if (!strcmp(verb, "setstate")) {
 		gv_setstate(gp, req);
 	} else

==== //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum.h#19 (text+ko) ====

@@ -29,6 +29,11 @@
 #ifndef	_GEOM_VINUM_H_
 #define	_GEOM_VINUM_H_
 
+/* geom_vinum_create.c */
+void	gv_concat(struct g_geom *gp, struct gctl_req *);
+void	gv_mirror(struct g_geom *gp, struct gctl_req *);
+void	gv_stripe(struct g_geom *gp, struct gctl_req *);
+
 /* geom_vinum_drive.c */
 void	gv_save_config(struct gv_softc *);
 

==== //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_subr.c#15 (text+ko) ====


==== //depot/projects/soc2007/lulf/gvinum_fixup/sys/modules/geom/geom_vinum/Makefile#2 (text+ko) ====

@@ -3,7 +3,7 @@
 .PATH: ${.CURDIR}/../../../geom/vinum
 
 KMOD=	geom_vinum
-SRCS=	geom_vinum.c geom_vinum_drive.c geom_vinum_plex.c \
+SRCS=	geom_vinum.c geom_vinum_create.c geom_vinum_drive.c geom_vinum_plex.c \
 	geom_vinum_volume.c geom_vinum_subr.c geom_vinum_raid5.c \
 	geom_vinum_share.c geom_vinum_list.c geom_vinum_rm.c \
 	geom_vinum_init.c geom_vinum_state.c geom_vinum_rename.c \



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200707022152.l62Lq4RK020054>