- Implement the grow command to make it easier for users to extend plexes

without having to understand all gvinum internals.
- Document the grow command in the manpage and update examples to use the
  command where possible.
This commit is contained in:
Ulf Lilleengen 2009-04-10 10:12:09 +00:00
parent 11e0093f28
commit 8d4311eacb
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=190884
2 changed files with 95 additions and 7 deletions

View File

@ -79,6 +79,10 @@ flag is given.
.It Ic detach Oo Fl f Oc Op Ar plex | subdisk
Detach a plex or subdisk from the volume or plex to which it is
attached.
.It Ic grow Ar plex device
Grow a plex by creating a gvinum drive and subdisk on device and attach it to
the plex.
If required by the plex organization, it will be put into the growable state.
.It Ic help
Provides a synopsis of
.Nm
@ -333,16 +337,11 @@ Then, initiate the rebuild:
The plex will go up form degraded mode after the rebuild is finished.
The plex can still be used while the rebuild is in progress, although requests
might be delayed.
For a more advanced usage and detailed explanation of gvinum, the
handbook is recommended.
.Pp
Given the configuration as in the previous example, growing a RAID-5 or STRIPED
array is accomplished by adding a new subdisk to the plex with a
.Ar description-file
similar to this:
array is accomplished by using the grow command:
.Pp
.Dl "drive newdrive device /dev/ad4"
.Dl "sd drive newdrive plex myraid5vol.p0"
.Dl "gvinum grow myraid5vol.p0 /dev/ad4"
.Pp
If everything went ok, the plex state should now be set to growable.
You can then start the growing with the
@ -355,6 +354,9 @@ As with rebuilding, you can watch the progress using the
.Ic list
command.
.Pp
For a more advanced usage and detailed explanation of gvinum, the
handbook is recommended.
.Pp
.Sh SEE ALSO
.Xr geom 4 ,
.Xr geom 8

View File

@ -61,6 +61,7 @@ void gvinum_attach(int, char **);
void gvinum_concat(int, char **);
void gvinum_create(int, char **);
void gvinum_detach(int, char **);
void gvinum_grow(int, char **);
void gvinum_help(void);
void gvinum_list(int, char **);
void gvinum_move(int, char **);
@ -690,6 +691,8 @@ gvinum_help(void)
"detach [-f] [plex | subdisk]\n"
" Detach a plex or a subdisk from the volume or plex to\n"
" which it is attached.\n"
"grow plex drive\n"
" Grow plex by creating a properly sized subdisk on drive\n"
"l | list [-r] [-v] [-V] [volume | plex | subdisk]\n"
" List information about specified objects.\n"
"ld [-r] [-v] [-V] [volume]\n"
@ -1242,6 +1245,87 @@ gvinum_stripe(int argc, char **argv)
create_volume(argc, argv, "stripe");
}
/* Grow a subdisk by adding disk backed by provider. */
void
gvinum_grow(int argc, char **argv)
{
struct gctl_req *req;
char *drive, *sdname;
char sdprefix[GV_MAXSDNAME];
struct gv_drive *d;
struct gv_sd *s;
const char *errstr;
int drives, volumes, plexes, subdisks, flags;
drives = volumes = plexes = subdisks = 0;
if (argc < 3) {
warnx("usage:\tgrow plex drive\n");
return;
}
s = gv_alloc_sd();
if (s == NULL) {
warn("unable to create subdisk");
return;
}
d = gv_alloc_drive();
if (d == NULL) {
warn("unable to create drive");
free(s);
return;
}
/* Lookup device and set an appropriate drive name. */
drive = find_drive(argv[2]);
if (drive == NULL) {
warn("unable to find an appropriate drive name");
free(s);
free(d);
return;
}
strlcpy(d->name, drive, sizeof(d->name));
if (strncmp(argv[2], "/dev/", 5) == 0)
strlcpy(d->device, (argv[2] + 5), sizeof(d->device));
else
strlcpy(d->device, argv[2], sizeof(d->device));
drives = 1;
/* We try to use the plex name as basis for the subdisk name. */
snprintf(sdprefix, sizeof(sdprefix), "%s.s", argv[1]);
sdname = find_name(sdprefix, GV_TYPE_SD, GV_MAXSDNAME);
if (sdname == NULL) {
warn("unable to find an appropriate subdisk name");
free(s);
free(d);
free(drive);
return;
}
strlcpy(s->name, sdname, sizeof(s->name));
free(sdname);
strlcpy(s->plex, argv[1], sizeof(s->plex));
strlcpy(s->drive, d->name, sizeof(s->drive));
subdisks = 1;
req = gctl_get_handle();
gctl_ro_param(req, "class", -1, "VINUM");
gctl_ro_param(req, "verb", -1, "create");
gctl_ro_param(req, "flags", sizeof(int), &flags);
gctl_ro_param(req, "volumes", sizeof(int), &volumes);
gctl_ro_param(req, "plexes", sizeof(int), &plexes);
gctl_ro_param(req, "subdisks", sizeof(int), &subdisks);
gctl_ro_param(req, "drives", sizeof(int), &drives);
gctl_ro_param(req, "drive0", sizeof(*d), d);
gctl_ro_param(req, "sd0", sizeof(*s), s);
errstr = gctl_issue(req);
free(drive);
if (errstr != NULL) {
warnx("unable to grow plex: %s", errstr);
free(s);
free(d);
return;
}
gctl_free(req);
}
void
parseline(int argc, char **argv)
{
@ -1258,6 +1342,8 @@ parseline(int argc, char **argv)
gvinum_detach(argc, argv);
else if (!strcmp(argv[0], "concat"))
gvinum_concat(argc, argv);
else if (!strcmp(argv[0], "grow"))
gvinum_grow(argc, argv);
else if (!strcmp(argv[0], "help"))
gvinum_help();
else if (!strcmp(argv[0], "list") || !strcmp(argv[0], "l"))