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>