PERFORCE change 122746 for review
Ulf Lilleengen
lulf at FreeBSD.org
Mon Jul 2 21:52:05 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=122746
Change 122746 by lulf at 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 \
More information about the p4-projects
mailing list