/* * General routine for creating a volume. Mainly for use by concat, mirror, * raid5 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; off_t stripesize; flags = 0; drives = 0; volname = NULL; stripesize = 262144; /* 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; if (!strcmp(verb, "raid5")) stripesize = gv_sizespec(argv[++i]); } 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); } } gctl_ro_param(req, "stripesize", sizeof(off_t), &stripesize); /* Find a free volume name. */ if (volname == NULL) volname = find_name("gvinumvolume", GV_TYPE_VOL, GV_MAXVOLNAME); /* 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); }
/* Get a new subdisk object. */ struct gv_sd * gv_new_sd(int max, char *token[]) { struct gv_sd *s; int j, errors; if (token[1] == NULL || *token[1] == '\0') return (NULL); s = gv_alloc_sd(); if (s == NULL) return (NULL); errors = 0; for (j = 1; j < max; j++) { if (!strcmp(token[j], "name")) { j++; if (j >= max) { errors++; break; } strlcpy(s->name, token[j], sizeof(s->name)); } else if (!strcmp(token[j], "drive")) { j++; if (j >= max) { errors++; break; } strlcpy(s->drive, token[j], sizeof(s->drive)); } else if (!strcmp(token[j], "plex")) { j++; if (j >= max) { errors++; break; } strlcpy(s->plex, token[j], sizeof(s->plex)); } else if (!strcmp(token[j], "state")) { j++; if (j >= max) { errors++; break; } s->state = gv_sdstatei(token[j]); } else if (!strcmp(token[j], "len") || !strcmp(token[j], "length")) { j++; if (j >= max) { errors++; break; } s->size = gv_sizespec(token[j]); if (s->size <= 0) s->size = -1; } else if (!strcmp(token[j], "driveoffset")) { j++; if (j >= max) { errors++; break; } s->drive_offset = gv_sizespec(token[j]); if (s->drive_offset != 0 && s->drive_offset < GV_DATA_START) { errors++; break; } } else if (!strcmp(token[j], "plexoffset")) { j++; if (j >= max) { errors++; break; } s->plex_offset = gv_sizespec(token[j]); if (s->plex_offset < 0) { errors++; break; } } else { errors++; break; } } if (strlen(s->drive) == 0) errors++; if (errors) { g_free(s); return (NULL); } return (s); }
/* Get a new plex object. */ struct gv_plex * gv_new_plex(int max, char *token[]) { struct gv_plex *p; int j, errors; if (token[1] == NULL || *token[1] == '\0') return (NULL); p = gv_alloc_plex(); if (p == NULL) return (NULL); errors = 0; for (j = 1; j < max; j++) { if (!strcmp(token[j], "name")) { j++; if (j >= max) { errors++; break; } strlcpy(p->name, token[j], sizeof(p->name)); } else if (!strcmp(token[j], "org")) { j++; if (j >= max) { errors++; break; } p->org = gv_plexorgi(token[j]); if ((p->org == GV_PLEX_RAID5) || (p->org == GV_PLEX_STRIPED)) { j++; if (j >= max) { errors++; break; } p->stripesize = gv_sizespec(token[j]); if (p->stripesize == 0) { errors++; break; } } } else if (!strcmp(token[j], "state")) { j++; if (j >= max) { errors++; break; } p->state = gv_plexstatei(token[j]); } else if (!strcmp(token[j], "vol") || !strcmp(token[j], "volume")) { j++; if (j >= max) { errors++; break; } strlcpy(p->volume, token[j], sizeof(p->volume)); } else { errors++; break; } } if (errors) { g_free(p); return (NULL); } return (p); }