summaryrefslogtreecommitdiffstats
path: root/sbin/vinum/commands.c
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/vinum/commands.c')
-rw-r--r--sbin/vinum/commands.c2329
1 files changed, 0 insertions, 2329 deletions
diff --git a/sbin/vinum/commands.c b/sbin/vinum/commands.c
deleted file mode 100644
index c0038e4..0000000
--- a/sbin/vinum/commands.c
+++ /dev/null
@@ -1,2329 +0,0 @@
-/* commands.c: vinum interface program, main commands */
-/*-
- * Copyright (c) 1997, 1998
- * Nan Yang Computer Services Limited. All rights reserved.
- *
- * Written by Greg Lehey
- *
- * This software is distributed under the so-called ``Berkeley
- * License'':
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Nan Yang Computer
- * Services Limited.
- * 4. Neither the name of the Company nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * This software is provided ``as is'', and any express or implied
- * warranties, including, but not limited to, the implied warranties of
- * merchantability and fitness for a particular purpose are disclaimed.
- * In no event shall the company or contributors be liable for any
- * direct, indirect, incidental, special, exemplary, or consequential
- * damages (including, but not limited to, procurement of substitute
- * goods or services; loss of use, data, or profits; or business
- * interruption) however caused and on any theory of liability, whether
- * in contract, strict liability, or tort (including negligence or
- * otherwise) arising in any way out of the use of this software, even if
- * advised of the possibility of such damage.
- *
- * $Id: commands.c,v 1.52 2003/05/08 00:33:57 grog Exp $
- * $FreeBSD$
- */
-
-#include "vext.h"
-#include <devstat.h>
-
-static void dorename(struct vinum_rename_msg *msg, const char *oldname, const char *name, int maxlen);
-
-void
-vinum_create(int argc, char *argv[], char *arg0[])
-{
- int error;
- FILE *dfd; /* file descriptor for the config file */
- char buffer[BUFSIZE]; /* read config file in here */
- char commandline[BUFSIZE]; /* issue command from here */
- struct _ioctl_reply *reply;
- int ioctltype; /* for ioctl call */
- char tempfile[PATH_MAX]; /* name of temp file for direct editing */
- char *file; /* file to read */
- FILE *tf; /* temp file */
-
- if (argc == 0) { /* no args, */
- char *editor; /* editor to start */
- int status;
-
- editor = getenv("EDITOR");
- if (editor == NULL)
- editor = _PATH_VI;
- sprintf(tempfile, "/var/tmp/" VINUMMOD ".create.%d", getpid()); /* create a temp file */
- tf = fopen(tempfile, "w"); /* open it */
- if (tf == NULL) {
- fprintf(stderr, "Can't open %s: %s\n", argv[0], strerror(errno));
- return;
- }
- printconfig(tf, "# "); /* and put the current config it */
- fclose(tf);
- sprintf(commandline, "%s %s", editor, tempfile); /* create an edit command */
- status = system(commandline); /* do it */
- if (status != 0) {
- fprintf(stderr, "Can't edit config: status %d\n", status);
- return;
- }
- file = tempfile;
- } else if (argc == 1)
- file = argv[0];
- else {
- fprintf(stderr, "Expecting 1 parameter, not %d\n", argc);
- return;
- }
- reply = (struct _ioctl_reply *) &buffer;
- dfd = fopen(file, "r");
- if (dfd == NULL) { /* no go */
- fprintf(stderr, "Can't open %s: %s\n", file, strerror(errno));
- return;
- }
- if (ioctl(superdev, VINUM_STARTCONFIG, &force)) { /* can't get config? */
- printf("Can't configure: %s (%d)\n", strerror(errno), errno);
- return;
- }
- file_line = 0; /* start with line 1 */
- /* Parse the configuration, and add it to the global configuration */
- for (;;) { /* love this style(9) */
- char *configline;
-
- configline = fgets(buffer, BUFSIZE, dfd);
- if (History)
- fprintf(History, "%s", buffer);
-
- if (configline == NULL) {
- if (ferror(dfd))
- perror("Can't read config file");
- break;
- }
- file_line++; /* count the lines */
- if (vflag)
- printf("%4d: %s", file_line, buffer);
- strcpy(commandline, buffer); /* make a copy */
- ioctl(superdev, VINUM_CREATE, buffer);
- if (reply->error != 0) { /* error in config */
- if (!vflag) /* print this line anyway */
- printf("%4d: %s", file_line, commandline);
- fprintf(stdout, "** %d %s: %s\n",
- file_line,
- reply->msg,
- strerror(reply->error));
-
- /*
- * XXX at the moment, we reset the config
- * lock on error, so try to get it again.
- * If we fail, don't cry again.
- */
- if (ioctl(superdev, VINUM_STARTCONFIG, &force)) /* can't get config? */
- return;
- }
- }
- fclose(dfd); /* done with the config file */
- ioctltype = 0; /* saveconfig after update */
- error = ioctl(superdev, VINUM_SAVECONFIG, &ioctltype); /* save the config to disk */
- if (error != 0)
- perror("Can't save Vinum config");
- listconfig();
- checkupdates(); /* make sure we're updating */
-}
-
-/* Read vinum config from a disk */
-void
-vinum_read(int argc, char *argv[], char *arg0[])
-{
- char buffer[BUFSIZE]; /* read config file in here */
- struct _ioctl_reply *reply;
- int i;
-
- reply = (struct _ioctl_reply *) &buffer;
- buffer[0] = '\0'; /* make sure we don't pass anything */
- if (argc > 0) { /* args specified, */
- for (i = 0; i < argc; i++) { /* each drive name */
- strlcat(buffer, argv[i], sizeof(buffer));
- strlcat(buffer, " ", sizeof(buffer));
- }
- }
- ioctl(superdev, VINUM_READCONFIG, &buffer);
- if (reply->error != 0) /* error in config */
- fprintf(stdout, "** %s: %s\n", reply->msg, strerror(reply->error));
- checkupdates(); /* make sure we're updating */
-}
-
-void
-vinum_debug(int argc, char *argv[], char *arg0[])
-{
- struct debuginfo info;
-
- if (vinum_conf.flags & VF_HASDEBUG) {
- if (argc > 0) {
- info.param = atoi(argv[0]);
- info.changeit = 1;
- } else {
- info.changeit = 0;
- sleep(2); /* give a chance to leave the window */
- }
- ioctl(superdev, VINUM_DEBUG, (caddr_t) & info);
- } else /* no debug in kernel module */
- fprintf(stderr, "Kernel module does not have debug support\n");
-}
-
-void
-vinum_modify(int argc, char *argv[], char *arg0[])
-{
- fprintf(stderr, "Modify command is currently not implemented\n");
- checkupdates(); /* make sure we're updating */
-}
-
-void
-vinum_set(int argc, char *argv[], char *arg0[])
-{
- fprintf(stderr, "set is not implemented yet\n");
-}
-
-void
-vinum_rm(int argc, char *argv[], char *arg0[])
-{
- int object;
- struct _ioctl_reply reply;
- struct vinum_ioctl_msg *message = (struct vinum_ioctl_msg *) &reply;
-
- if (argc == 0) /* start everything */
- fprintf(stderr, "usage: rm object [object...]\n");
- else { /* start specified objects */
- int index;
- enum objecttype type;
-
- for (index = 0; index < argc; index++) {
- object = find_object(argv[index], &type); /* look for it */
- if (type == invalid_object)
- fprintf(stderr, "Can't find object: %s\n", argv[index]);
- else {
- message->index = object; /* pass object number */
- message->type = type; /* and type of object */
- message->force = force; /* do we want to force the operation? */
- message->recurse = recurse; /* do we want to remove subordinates? */
- ioctl(superdev, VINUM_REMOVE, message);
- if (reply.error != 0) {
- fprintf(stderr,
- "Can't remove %s: %s (%d)\n",
- argv[index],
- reply.msg[0] ? reply.msg : strerror(reply.error),
- reply.error);
- } else if (vflag)
- fprintf(stderr, "%s removed\n", argv[index]);
- }
- }
- checkupdates(); /* make sure we're updating */
- /* Arguably we should be cleverer about this. */
- }
-}
-
-void
-vinum_resetconfig(int argc, char *argv[], char *arg0[])
-{
- char reply[32];
- int error;
-
- if (isatty(STDIN_FILENO)) {
- printf(" WARNING! This command will completely wipe out your vinum configuration.\n"
- " All data will be lost. If you really want to do this, enter the text\n\n"
- " NO FUTURE\n"
- " Enter text -> ");
- fgets(reply, sizeof(reply), stdin);
- if (strcmp(reply, "NO FUTURE\n")) /* changed his mind */
- printf("\n No change\n");
- else {
- error = ioctl(superdev, VINUM_RESETCONFIG, NULL); /* trash config on disk */
- if (error) {
- if (errno == EBUSY)
- fprintf(stderr, "Can't reset configuration: objects are in use\n");
- else
- perror("Can't find vinum config");
- } else {
- printf("\b Vinum configuration obliterated\n");
- start_daemon(); /* then restart the daemon */
- }
- }
- checkupdates(); /* make sure we're updating */
- } else
- fprintf(stderr, "Please enter this command from a terminal\n");
-}
-
-/* Initialize subdisks */
-void
-vinum_init(int argc, char *argv[], char *arg0[])
-{
- if (argc > 0) { /* initialize plexes */
- int objindex;
- int objno;
- enum objecttype type; /* type returned */
-
- if (History)
- fflush(History); /* don't let all the kids do it. */
- for (objindex = 0; objindex < argc; objindex++) {
- objno = find_object(argv[objindex], &type); /* find the object */
- if (objno < 0)
- printf("Can't find %s\n", argv[objindex]);
- else {
- switch (type) {
- case volume_object:
- initvol(objno);
- break;
-
- case plex_object:
- initplex(objno, argv[objindex]);
- break;
-
- case sd_object:
- initsd(objno, dowait);
- break;
-
- default:
- printf("Can't initialize %s: wrong object type\n", argv[objindex]);
- break;
- }
- }
- }
- }
- checkupdates(); /* make sure we're updating */
-}
-
-void
-initvol(int volno)
-{
- printf("Initializing volumes is not implemented yet\n");
-}
-
-void
-initplex(int plexno, char *name)
-{
- int sdno;
- int plexfh = 0; /* file handle for plex */
- pid_t pid;
- char filename[MAXPATHLEN]; /* create a file name here */
-
- /* Variables for use by children */
- int failed = 0; /* set if a child dies badly */
-
- sprintf(filename, VINUM_DIR "/plex/%s", name);
- if ((plexfh = open(filename, O_RDWR, S_IRWXU)) < 0) { /* got a plex, open it */
- /*
- * We don't actually write anything to the
- * plex. We open it to ensure that nobody
- * else tries to open it while we initialize
- * its subdisks.
- */
- fprintf(stderr, "can't open plex %s: %s\n", filename, strerror(errno));
- return;
- }
- if (dowait == 0) {
- pid = fork(); /* into the background with you */
- if (pid != 0) { /* I'm the parent, or we failed */
- if (pid < 0) /* failure */
- printf("Couldn't fork: %s", strerror(errno));
- close(plexfh); /* we don't need this any more */
- return;
- }
- }
- /*
- * If we get here, we're either the first-level
- * child (if we're not waiting) or we're going
- * to wait.
- */
- for (sdno = 0; sdno < plex.subdisks; sdno++) { /* initialize each subdisk */
- get_plex_sd_info(&sd, plexno, sdno);
- initsd(sd.sdno, 0);
- }
- /* Now wait for them to complete */
- while (1) {
- int status;
- pid = wait(&status);
- if (((int) pid == -1)
- && (errno == ECHILD)) /* all gone */
- break;
- if (WEXITSTATUS(status) != 0) { /* oh, oh */
- printf("child %d exited with status 0x%x\n", pid, WEXITSTATUS(status));
- failed++;
- }
- }
- if (failed == 0) {
- syslog(LOG_INFO | LOG_KERN, "plex %s initialized", plex.name);
- } else
- syslog(LOG_ERR | LOG_KERN, "couldn't initialize plex %s, %d processes died",
- plex.name,
- failed);
- if (dowait == 0) /* we're the waiting child, */
- exit(0); /* we've done our dash */
-}
-
-/* Initialize a subdisk. */
-void
-initsd(int sdno, int dowait)
-{
- pid_t pid;
- struct _ioctl_reply reply;
- struct vinum_ioctl_msg *message = (struct vinum_ioctl_msg *) &reply;
- char filename[MAXPATHLEN]; /* create a file name here */
-
- /* Variables for use by children */
- int sdfh; /* and for subdisk */
- int initsize; /* actual size to write */
- int64_t sdsize; /* size of subdisk */
-
- if (dowait == 0) {
- pid = fork(); /* into the background with you */
- if (pid > 0) /* I'm the parent */
- return;
- else if (pid < 0) { /* failure */
- printf("couldn't fork for subdisk %d: %s", sdno, strerror(errno));
- return;
- }
- }
- if (SSize != 0) { /* specified a size for init */
- if (SSize < 512)
- SSize <<= DEV_BSHIFT;
- initsize = min(SSize, MAXPLEXINITSIZE);
- } else
- initsize = PLEXINITSIZE;
- openlog("vinum", LOG_CONS | LOG_PERROR | LOG_PID, LOG_KERN);
- get_sd_info(&sd, sdno);
- sdsize = sd.sectors * DEV_BSIZE; /* size of subdisk in bytes */
- sprintf(filename, VINUM_DIR "/sd/%s", sd.name);
- setproctitle("initializing %s", filename); /* show what we're doing */
- syslog(LOG_INFO | LOG_KERN, "initializing subdisk %s", filename);
- if ((sdfh = open(filename, O_RDWR, S_IRWXU)) < 0) { /* no go */
- syslog(LOG_ERR | LOG_KERN,
- "can't open subdisk %s: %s",
- filename,
- strerror(errno));
- exit(1);
- }
- /* Set the subdisk in initializing state */
- message->index = sd.sdno; /* pass object number */
- message->type = sd_object; /* and type of object */
- message->state = object_initializing;
- message->verify = vflag; /* verify what we write? */
- message->force = 1; /* insist */
- ioctl(superdev, VINUM_SETSTATE, message);
- if ((SSize > 0) /* specified a size for init */
- &&(SSize < 512))
- SSize <<= DEV_BSHIFT;
- if (reply.error) {
- fprintf(stderr,
- "Can't initialize %s: %s (%d)\n",
- filename,
- strerror(reply.error),
- reply.error);
- exit(1);
- } else {
- do {
- if (interval) /* pause between copies */
- usleep(interval * 1000);
- message->index = sd.sdno; /* pass object number */
- message->type = sd_object; /* and type of object */
- message->state = object_up;
- message->verify = vflag; /* verify what we write? */
- message->blocksize = SSize;
- ioctl(superdev, VINUM_SETSTATE, message);
- }
- while (reply.error == EAGAIN); /* until we're done */
- if (reply.error) {
- fprintf(stderr,
- "Can't initialize %s: %s (%d)\n",
- filename,
- strerror(reply.error),
- reply.error);
- get_sd_info(&sd, sdno);
- if (sd.state != sd_up)
- /* Set the subdisk down */
- message->index = sd.sdno; /* pass object number */
- message->type = sd_object; /* and type of object */
- message->state = object_down;
- message->verify = vflag; /* verify what we write? */
- message->force = 1; /* insist */
- ioctl(superdev, VINUM_SETSTATE, message);
- }
- }
- printf("subdisk %s initialized\n", filename);
- if (!dowait)
- exit(0);
-}
-
-void
-vinum_start(int argc, char *argv[], char *arg0[])
-{
- int object;
- struct _ioctl_reply reply;
- struct vinum_ioctl_msg *message = (struct vinum_ioctl_msg *) &reply;
-
- if (argc == 0) /* start everything */
- /* XXX how should we do this right? */
- vinum_read(0, NULL, NULL); /* that's what vinum_read does now */
- else { /* start specified objects */
- int index;
- enum objecttype type;
-
- for (index = 0; index < argc; index++) {
- object = find_object(argv[index], &type); /* look for it */
- if (type == invalid_object)
- fprintf(stderr, "Can't find object: %s\n", argv[index]);
- else {
- int doit = 0; /* set to 1 if we pass our tests */
- switch (type) {
- case drive_object:
- if (drive.state == drive_up) /* already up */
- fprintf(stderr, "%s is already up\n", drive.label.name);
- else
- doit = 1;
- break;
-
- case sd_object:
- if (sd.state == sd_up) /* already up */
- fprintf(stderr, "%s is already up\n", sd.name);
- else
- doit = 1;
- break;
-
- case plex_object:
- if (plex.state == plex_up) /* already up */
- fprintf(stderr, "%s is already up\n", plex.name);
- else {
- int sdno;
-
- /*
- * First, see if we can bring it up
- * just by asking. This might happen
- * if somebody has used setupstate on
- * the subdisks. If we don't do this,
- * we'll return success, but the plex
- * won't have changed state. Note
- * that we don't check for errors
- * here.
- */
- message->index = plex.plexno; /* pass object number */
- message->type = plex_object; /* it's a plex */
- message->state = object_up;
- message->force = 0; /* don't force it */
- ioctl(superdev, VINUM_SETSTATE, message);
- for (sdno = 0; sdno < plex.subdisks; sdno++) {
- get_plex_sd_info(&sd, object, sdno);
- if ((sd.state >= sd_empty)
- && (sd.state <= sd_reviving)) { /* candidate for start */
- message->index = sd.sdno; /* pass object number */
- message->type = sd_object; /* it's a subdisk */
- message->state = object_up;
- message->force = force; /* don't force it, use a larger hammer */
-
- /*
- * We don't do any checking here.
- * The kernel module has a better
- * understanding of these things,
- * let it do it.
- */
- if (SSize != 0) { /* specified a size for init */
- if (SSize < 512)
- SSize <<= DEV_BSHIFT;
- message->blocksize = SSize;
- } else
- message->blocksize = DEFAULT_REVIVE_BLOCKSIZE;
- ioctl(superdev, VINUM_SETSTATE, message);
- if (reply.error != 0) {
- if (reply.error == EAGAIN) /* we're reviving */
- continue_revive(sd.sdno);
- else
- fprintf(stderr,
- "Can't start %s: %s (%d)\n",
- sd.name,
- reply.msg[0] ? reply.msg : strerror(reply.error),
- reply.error);
- }
- if (Verbose)
- vinum_lsi(sd.sdno, 0);
- }
- }
- }
- break;
-
- case volume_object:
- if (vol.state == volume_up) /* already up */
- fprintf(stderr, "%s is already up\n", vol.name);
- else
- doit = 1;
- break;
- }
-
- if (doit) {
- message->index = object; /* pass object number */
- message->type = type; /* and type of object */
- message->state = object_up;
- message->force = force; /* don't force it, use a larger hammer */
-
- /*
- * We don't do any checking here.
- * The kernel module has a better
- * understanding of these things,
- * let it do it.
- */
- if (SSize != 0) { /* specified a size for init or revive */
- if (SSize < 512)
- SSize <<= DEV_BSHIFT;
- message->blocksize = SSize;
- } else
- message->blocksize = 0;
- ioctl(superdev, VINUM_SETSTATE, message);
- if (reply.error != 0) {
- if ((reply.error == EAGAIN) /* we're reviving */
- &&(type == sd_object))
- continue_revive(object);
- else
- fprintf(stderr,
- "Can't start %s: %s (%d)\n",
- argv[index],
- reply.msg[0] ? reply.msg : strerror(reply.error),
- reply.error);
- }
- if (Verbose)
- vinum_li(object, type);
- }
- }
- }
- }
- checkupdates(); /* make sure we're updating */
-}
-
-void
-vinum_stop(int argc, char *argv[], char *arg0[])
-{
- int object;
- struct _ioctl_reply reply;
- struct vinum_ioctl_msg *message = (struct vinum_ioctl_msg *) &reply;
-
- if (checkupdates() && (!force)) /* not updating? */
- return;
- message->force = force; /* should we force the transition? */
- if (argc == 0) { /* stop vinum */
- int fileid = 0; /* ID of Vinum kld */
-
- close(superdev); /* we can't stop if we have vinum open */
- sleep(1); /* wait for the daemon to let go */
- fileid = kldfind(VINUMMOD);
- if ((fileid < 0) /* no go */
- ||(kldunload(fileid) < 0))
- perror("Can't unload " VINUMMOD);
- else {
- fprintf(stderr, VINUMMOD " unloaded\n");
- exit(0);
- }
-
- /* If we got here, the stop failed. Reopen the superdevice. */
- superdev = open(VINUM_SUPERDEV_NAME, O_RDWR); /* reopen vinum superdevice */
- if (superdev < 0) {
- perror("Can't reopen Vinum superdevice");
- exit(1);
- }
- } else { /* stop specified objects */
- int i;
- enum objecttype type;
-
- for (i = 0; i < argc; i++) {
- object = find_object(argv[i], &type); /* look for it */
- if (type == invalid_object)
- fprintf(stderr, "Can't find object: %s\n", argv[i]);
- else {
- message->index = object; /* pass object number */
- message->type = type; /* and type of object */
- message->state = object_down;
- ioctl(superdev, VINUM_SETSTATE, message);
- if (reply.error != 0)
- fprintf(stderr,
- "Can't stop %s: %s (%d)\n",
- argv[i],
- reply.msg[0] ? reply.msg : strerror(reply.error),
- reply.error);
- if (Verbose)
- vinum_li(object, type);
- }
- }
- }
-}
-
-void
-reset_volume_stats(int volno, int recurse)
-{
- struct vinum_ioctl_msg msg;
- struct _ioctl_reply *reply = (struct _ioctl_reply *) &msg;
-
- msg.index = volno;
- msg.type = volume_object;
- /* XXX get these numbers right if we ever
- * actually return errors */
- if (ioctl(superdev, VINUM_RESETSTATS, &msg) < 0) {
- fprintf(stderr, "Can't reset stats for volume %d: %s\n", volno, reply->msg);
- longjmp(command_fail, -1);
- } else if (recurse) {
- struct _volume vol;
- int plexno;
-
- get_volume_info(&vol, volno);
- for (plexno = 0; plexno < vol.plexes; plexno++)
- reset_plex_stats(vol.plex[plexno], recurse);
- }
-}
-
-void
-reset_plex_stats(int plexno, int recurse)
-{
- struct vinum_ioctl_msg msg;
- struct _ioctl_reply *reply = (struct _ioctl_reply *) &msg;
-
- msg.index = plexno;
- msg.type = plex_object;
- /* XXX get these numbers right if we ever
- * actually return errors */
- if (ioctl(superdev, VINUM_RESETSTATS, &msg) < 0) {
- fprintf(stderr, "Can't reset stats for plex %d: %s\n", plexno, reply->msg);
- longjmp(command_fail, -1);
- } else if (recurse) {
- struct _plex plex;
- struct _sd sd;
- int sdno;
-
- get_plex_info(&plex, plexno);
- for (sdno = 0; sdno < plex.subdisks; sdno++) {
- get_plex_sd_info(&sd, plex.plexno, sdno);
- reset_sd_stats(sd.sdno, recurse);
- }
- }
-}
-
-void
-reset_sd_stats(int sdno, int recurse)
-{
- struct vinum_ioctl_msg msg;
- struct _ioctl_reply *reply = (struct _ioctl_reply *) &msg;
-
- msg.index = sdno;
- msg.type = sd_object;
- /* XXX get these numbers right if we ever
- * actually return errors */
- if (ioctl(superdev, VINUM_RESETSTATS, &msg) < 0) {
- fprintf(stderr, "Can't reset stats for subdisk %d: %s\n", sdno, reply->msg);
- longjmp(command_fail, -1);
- } else if (recurse) {
- get_sd_info(&sd, sdno); /* get the info */
- reset_drive_stats(sd.driveno); /* and clear the drive */
- }
-}
-
-void
-reset_drive_stats(int driveno)
-{
- struct vinum_ioctl_msg msg;
- struct _ioctl_reply *reply = (struct _ioctl_reply *) &msg;
-
- msg.index = driveno;
- msg.type = drive_object;
- /* XXX get these numbers right if we ever
- * actually return errors */
- if (ioctl(superdev, VINUM_RESETSTATS, &msg) < 0) {
- fprintf(stderr, "Can't reset stats for drive %d: %s\n", driveno, reply->msg);
- longjmp(command_fail, -1);
- }
-}
-
-void
-vinum_resetstats(int argc, char *argv[], char *argv0[])
-{
- int i;
- int objno;
- enum objecttype type;
-
- if (ioctl(superdev, VINUM_GETCONFIG, &vinum_conf) < 0) {
- perror("Can't get vinum config");
- return;
- }
- if (argc == 0) {
- for (objno = 0; objno < vinum_conf.volumes_allocated; objno++)
- reset_volume_stats(objno, 1); /* clear everything recursively */
- } else {
- for (i = 0; i < argc; i++) {
- objno = find_object(argv[i], &type);
- if (objno >= 0) { /* not invalid */
- switch (type) {
- case drive_object:
- reset_drive_stats(objno);
- break;
-
- case sd_object:
- reset_sd_stats(objno, recurse);
- break;
-
- case plex_object:
- reset_plex_stats(objno, recurse);
- break;
-
- case volume_object:
- reset_volume_stats(objno, recurse);
- break;
-
- case invalid_object: /* can't get this */
- break;
- }
- }
- }
- }
-}
-
-/* Attach a subdisk to a plex, or a plex to a volume.
- * attach subdisk plex [offset] [rename]
- * attach plex volume [rename]
- */
-void
-vinum_attach(int argc, char *argv[], char *argv0[])
-{
- int i;
- enum objecttype supertype;
- struct vinum_ioctl_msg msg;
- struct _ioctl_reply *reply = (struct _ioctl_reply *) &msg;
- const char *objname = argv[0];
- const char *supername = argv[1];
- int sdno = -1;
- int plexno = -1;
- char oldname[MAXNAME + 8];
- char newname[MAXNAME + 8];
- int rename = 0; /* set if we want to rename the object */
-
- if ((argc < 2)
- || (argc > 4)) {
- fprintf(stderr,
- "usage: \tattach <subdisk> <plex> [rename] [<plexoffset>]\n"
- "\tattach <plex> <volume> [rename]\n");
- return;
- }
- if (ioctl(superdev, VINUM_GETCONFIG, &vinum_conf) < 0) {
- perror("Can't get vinum config");
- return;
- }
- msg.index = find_object(objname, &msg.type); /* find the object to attach */
- msg.otherobject = find_object(supername, &supertype); /* and the object to attach to */
- msg.force = force; /* did we specify the use of force? */
- msg.recurse = recurse;
- msg.offset = -1; /* and no offset */
-
- for (i = 2; i < argc; i++) {
- if (!strcmp(argv[i], "rename")) {
- rename = 1;
- msg.rename = 1; /* do renaming */
- } else if (!isdigit(argv[i][0])) { /* not an offset */
- fprintf(stderr, "Unknown attribute: %s\n", supername);
- return;
- } else
- msg.offset = sizespec(argv[i]);
- }
-
- switch (msg.type) {
- case sd_object:
- find_object(argv[1], &supertype);
- if (supertype != plex_object) { /* huh? */
- fprintf(stderr, "%s can only be attached to a plex\n", objname);
- return;
- }
- if ((plex.organization != plex_concat) /* not a cat plex, */
- &&(!force)) {
- fprintf(stderr, "Can't attach subdisks to a %s plex\n", plex_org(plex.organization));
- return;
- }
- sdno = msg.index; /* note the subdisk number for later */
- break;
-
- case plex_object:
- find_object(argv[1], &supertype);
- if (supertype != volume_object) { /* huh? */
- fprintf(stderr, "%s can only be attached to a volume\n", objname);
- return;
- }
- break;
-
- case volume_object:
- case drive_object:
- fprintf(stderr, "Can only attach subdisks and plexes\n");
- return;
-
- default:
- fprintf(stderr, "%s is not a Vinum object\n", objname);
- return;
- }
-
- ioctl(superdev, VINUM_ATTACH, &msg);
- if (reply->error != 0) {
- if (reply->error == EAGAIN) /* reviving */
- continue_revive(sdno); /* continue the revive */
- else
- fprintf(stderr,
- "Can't attach %s to %s: %s (%d)\n",
- objname,
- supername,
- reply->msg[0] ? reply->msg : strerror(reply->error),
- reply->error);
- }
- if (rename) {
- struct sd;
- struct _plex;
- struct _volume;
-
- /* we've overwritten msg with the
- * ioctl reply, start again */
- msg.index = find_object(objname, &msg.type); /* find the object to rename */
- switch (msg.type) {
- case sd_object:
- get_sd_info(&sd, msg.index);
- get_plex_info(&plex, sd.plexno);
- for (sdno = 0; sdno < plex.subdisks; sdno++) {
- if (plex.sdnos[sdno] == msg.index) /* found our subdisk */
- break;
- }
- sprintf(newname, "%s.s%d", plex.name, sdno);
- sprintf(oldname, "%s", sd.name);
- vinum_rename_2(oldname, newname);
- break;
-
- case plex_object:
- get_plex_info(&plex, msg.index);
- get_volume_info(&vol, plex.volno);
- for (plexno = 0; plexno < vol.plexes; plexno++) {
- if (vol.plex[plexno] == msg.index) /* found our subdisk */
- break;
- }
- sprintf(newname, "%s.p%d", vol.name, plexno);
- sprintf(oldname, "%s", plex.name);
- vinum_rename_2(oldname, newname); /* this may recurse */
- break;
- }
- }
- checkupdates(); /* make sure we're updating */
-}
-
-/* Detach a subdisk from a plex, or a plex from a volume.
- * detach subdisk plex [rename]
- * detach plex volume [rename]
- */
-void
-vinum_detach(int argc, char *argv[], char *argv0[])
-{
- struct vinum_ioctl_msg msg;
- struct _ioctl_reply *reply = (struct _ioctl_reply *) &msg;
-
- if ((argc < 1)
- || (argc > 2)) {
- fprintf(stderr,
- "usage: \tdetach <subdisk> [rename]\n"
- "\tdetach <plex> [rename]\n");
- return;
- }
- if (ioctl(superdev, VINUM_GETCONFIG, &vinum_conf) < 0) {
- perror("Can't get vinum config");
- return;
- }
- msg.index = find_object(argv[0], &msg.type); /* find the object to detach */
- msg.force = force; /* did we specify the use of force? */
- msg.rename = 0; /* don't specify new name */
- msg.recurse = recurse; /* but recurse if we have to */
-
- /* XXX are we going to keep this?
- * Don't document it yet, since the
- * kernel side of things doesn't
- * implement it */
- if (argc == 2) {
- if (!strcmp(argv[1], "rename"))
- msg.rename = 1; /* do renaming */
- else {
- fprintf(stderr, "Unknown attribute: %s\n", argv[1]);
- return;
- }
- }
- if ((msg.type != sd_object)
- && (msg.type != plex_object)) {
- fprintf(stderr, "Can only detach subdisks and plexes\n");
- return;
- }
- ioctl(superdev, VINUM_DETACH, &msg);
- if (reply->error != 0)
- fprintf(stderr,
- "Can't detach %s: %s (%d)\n",
- argv[0],
- reply->msg[0] ? reply->msg : strerror(reply->error),
- reply->error);
- checkupdates(); /* make sure we're updating */
-}
-
-static void
-dorename(struct vinum_rename_msg *msg, const char *oldname, const char *name, int maxlen)
-{
- struct _ioctl_reply *reply = (struct _ioctl_reply *) msg;
-
- if (strlen(name) > maxlen) {
- fprintf(stderr, "%s is too long\n", name);
- return;
- }
- strcpy(msg->newname, name);
- ioctl(superdev, VINUM_RENAME, msg);
- if (reply->error != 0)
- fprintf(stderr,
- "Can't rename %s to %s: %s (%d)\n",
- oldname,
- name,
- reply->msg[0] ? reply->msg : strerror(reply->error),
- reply->error);
-}
-
-/* Rename an object:
- * rename <object> "newname"
- */
-void
-vinum_rename_2(char *oldname, char *newname)
-{
- struct vinum_rename_msg msg;
- int volno;
- int plexno;
-
- msg.index = find_object(oldname, &msg.type); /* find the object to rename */
- msg.recurse = recurse;
-
- /* Ugh. Determine how long the name may be */
- switch (msg.type) {
- case drive_object:
- dorename(&msg, oldname, newname, MAXDRIVENAME);
- break;
-
- case sd_object:
- dorename(&msg, oldname, newname, MAXSDNAME);
- break;
-
- case plex_object:
- plexno = msg.index;
- dorename(&msg, oldname, newname, MAXPLEXNAME);
- if (recurse) {
- int sdno;
-
- get_plex_info(&plex, plexno); /* find out who we are */
- msg.type = sd_object;
- for (sdno = 0; sdno < plex.subdisks; sdno++) {
- char sdname[MAXPLEXNAME + 8];
-
- get_plex_sd_info(&sd, plex.plexno, sdno); /* get info about the subdisk */
- sprintf(sdname, "%s.s%d", newname, sdno);
- msg.index = sd.sdno; /* number of the subdisk */
- dorename(&msg, sd.name, sdname, MAXSDNAME);
- }
- }
- break;
-
- case volume_object:
- volno = msg.index;
- dorename(&msg, oldname, newname, MAXVOLNAME);
- if (recurse) {
- int sdno;
- int plexno;
-
- get_volume_info(&vol, volno); /* find out who we are */
- for (plexno = 0; plexno < vol.plexes; plexno++) {
- char plexname[MAXVOLNAME + 8];
-
- msg.type = plex_object;
- sprintf(plexname, "%s.p%d", newname, plexno);
- msg.index = vol.plex[plexno]; /* number of the plex */
- dorename(&msg, plex.name, plexname, MAXPLEXNAME);
- get_plex_info(&plex, vol.plex[plexno]); /* find out who we are */
- msg.type = sd_object;
- for (sdno = 0; sdno < plex.subdisks; sdno++) {
- char sdname[MAXPLEXNAME + 8];
-
- get_plex_sd_info(&sd, plex.plexno, sdno); /* get info about the subdisk */
- sprintf(sdname, "%s.s%d", plexname, sdno);
- msg.index = sd.sdno; /* number of the subdisk */
- dorename(&msg, sd.name, sdname, MAXSDNAME);
- }
- }
- }
- break;
-
- default:
- fprintf(stderr, "%s is not a Vinum object\n", oldname);
- return;
- }
-}
-
-void
-vinum_rename(int argc, char *argv[], char *argv0[])
-{
- if (argc != 2) {
- fprintf(stderr, "usage: \trename <object> <new name>\n");
- return;
- }
- if (ioctl(superdev, VINUM_GETCONFIG, &vinum_conf) < 0) {
- perror("Can't get vinum config");
- return;
- }
- vinum_rename_2(argv[0], argv[1]);
- checkupdates(); /* make sure we're updating */
-}
-
-/*
- * Move objects:
- *
- * mv <dest> <src> ...
- */
-void
-vinum_mv(int argc, char *argv[], char *argv0[])
-{
- int i; /* loop index */
- int srcobj;
- int destobj;
- enum objecttype srct;
- enum objecttype destt;
- int sdno;
- struct _ioctl_reply reply;
- struct vinum_ioctl_msg *msg = (struct vinum_ioctl_msg *) &reply;
-
- if (argc < 2) {
- fprintf(stderr, "usage: \tmove <dest> <src> ...\n");
- return;
- }
- /* Get current config */
- if (ioctl(superdev, VINUM_GETCONFIG, &vinum_conf) < 0) {
- perror("Cannot get vinum config\n");
- return;
- }
- /* Get our destination */
- destobj = find_object(argv[0], &destt);
- if (destobj == -1) {
- fprintf(stderr, "Can't find %s\n", argv[0]);
- return;
- }
- /* Verify that the target is a drive */
- if (destt != drive_object) {
- fprintf(stderr, "%s is not a drive\n", argv[0]);
- return;
- }
- for (i = 1; i < argc; i++) { /* for all the sources */
- srcobj = find_object(argv[i], &srct);
- if (srcobj == -1) {
- fprintf(stderr, "Can't find %s\n", argv[i]);
- continue;
- }
- msg->index = destobj;
- switch (srct) { /* Handle the source object */
- case drive_object: /* Move all subdisks on the drive to dst. */
- get_drive_info(&drive, srcobj); /* get info on drive */
- for (sdno = 0; sdno < vinum_conf.subdisks_allocated; ++sdno) {
- get_sd_info(&sd, sdno);
- if (sd.driveno == srcobj) {
- msg->index = destobj;
- msg->otherobject = sd.sdno;
- if (ioctl(superdev, VINUM_MOVE, msg) < 0)
- fprintf(stderr,
- "Can't move %s (part of %s) to %s: %s (%d)\n",
- sd.name,
- drive.label.name,
- argv[0],
- strerror(reply.error),
- reply.error);
- }
- }
- break;
-
- case sd_object:
- msg->otherobject = srcobj;
- if (ioctl(superdev, VINUM_MOVE, msg) < 0)
- fprintf(stderr,
- "Can't move %s to %s: %s (%d)\n",
- sd.name,
- argv[0],
- strerror(reply.error),
- reply.error);
- break;
-
- case plex_object:
- get_plex_info(&plex, srcobj);
- for (sdno = 0; sdno < plex.subdisks; ++sdno) {
- get_plex_sd_info(&sd, plex.plexno, sdno);
- msg->index = destobj;
- msg->otherobject = sd.sdno;
- if (ioctl(superdev, VINUM_MOVE, msg) < 0)
- fprintf(stderr,
- "Can't move %s (part of %s) to %s: %s (%d)\n",
- sd.name,
- plex.name,
- argv[0],
- strerror(reply.error),
- reply.error);
- }
- break;
-
- case volume_object:
- case invalid_object:
- default:
- fprintf(stderr, "Can't move %s (inappropriate object).\n", argv[i]);
- break;
- }
- if (reply.error)
- fprintf(stderr,
- "Can't move %s to %s: %s (%d)\n",
- argv[i],
- argv[0],
- strerror(reply.error),
- reply.error);
- }
- checkupdates(); /* make sure we're updating */
-}
-
-/*
- * Replace objects. Not implemented, may never be.
- */
-void
-vinum_replace(int argc, char *argv[], char *argv0[])
-{
- fprintf(stderr, "'replace' not implemented yet. Use 'move' instead\n");
-}
-
-/* Primitive help function */
-void
-vinum_help(int argc, char *argv[], char *argv0[])
-{
- char commands[] =
- {
- "COMMANDS\n"
- "attach plex volume [rename]\n"
- "attach subdisk plex [offset] [rename]\n"
- " Attach a plex to a volume, or a subdisk to a plex.\n"
- "checkparity plex [-f] [-v]\n"
- " Check the parity blocks of a RAID-4 or RAID-5 plex.\n"
- "concat [-f] [-n name] [-v] drives\n"
- " Create a concatenated volume from the specified drives.\n"
- "create [-f] description-file\n"
- " Create a volume as described in description-file.\n"
- "debug Cause the volume manager to enter the kernel debugger.\n"
- "debug flags\n"
- " Set debugging flags.\n"
- "detach [-f] [plex | subdisk]\n"
- " Detach a plex or subdisk from the volume or plex to which it is\n"
- " attached.\n"
- "dumpconfig [drive ...]\n"
- " List the configuration information stored on the specified\n"
- " drives, or all drives in the system if no drive names are speci-\n"
- " fied.\n"
- "info [-v] [-V]\n"
- " List information about volume manager state.\n"
- "init [-S size] [-w] plex | subdisk\n"
- " Initialize the contents of a subdisk or all the subdisks of a\n"
- " plex to all zeros.\n"
- "label volume\n"
- " Create a volume label.\n"
- "l | list [-r] [-s] [-v] [-V] [volume | plex | subdisk]\n"
- " List information about specified objects.\n"
- "ld [-r] [-s] [-v] [-V] [drive]\n"
- " List information about drives.\n"
- "ls [-r] [-s] [-v] [-V] [subdisk]\n"
- " List information about subdisks.\n"
- "lp [-r] [-s] [-v] [-V] [plex]\n"
- " List information about plexes.\n"
- "lv [-r] [-s] [-v] [-V] [volume]\n"
- " List information about volumes.\n"
- "mirror [-f] [-n name] [-s] [-v] 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"
- "printconfig [file]\n"
- " Write a copy of the current configuration to file.\n"
- "quit Exit the vinum program when running in interactive mode. Nor-\n"
- " mally this would be done by entering the EOF character.\n"
- "read disk ...\n"
- " Read the vinum configuration from the specified disks.\n"
- "rename [-r] [drive | subdisk | plex | volume] newname\n"
- " Change the name of the specified object.\n"
- "rebuildparity plex [-f] [-v] [-V]\n"
- " Rebuild the parity blocks of a RAID-4 or RAID-5 plex.\n"
- "resetconfig\n"
- " Reset the complete vinum configuration.\n"
- "resetstats [-r] [volume | plex | subdisk]\n"
- " Reset statistics counters for the specified objects, or for all\n"
- " objects if none are specified.\n"
- "rm [-f] [-r] volume | plex | subdisk\n"
- " Remove an object.\n"
- "saveconfig\n"
- " Save vinum configuration to disk after configuration failures.\n"
- "setdaemon [value]\n"
- " Set daemon configuration.\n"
- "setstate state [volume | plex | subdisk | drive]\n"
- " Set state without influencing other objects, for diagnostic pur-\n"
- " poses only.\n"
- "start Read configuration from all vinum drives.\n"
- "start [-i interval] [-S size] [-w] volume | plex | subdisk\n"
- " Allow the system to access the objects.\n"
- "stop [-f] [volume | plex | subdisk]\n"
- " Terminate access to the objects, or stop vinum if no parameters\n"
- " are specified.\n"
- "stripe [-f] [-n name] [-v] drives\n"
- " Create a striped volume from the specified drives.\n"
- };
- puts(commands);
-}
-
-/* Set daemon options.
- * XXX quick and dirty: use a bitmap, which requires
- * knowing which bit does what. FIXME */
-void
-vinum_setdaemon(int argc, char *argv[], char *argv0[])
-{
- int options;
-
- switch (argc) {
- case 0:
- if (ioctl(superdev, VINUM_GETDAEMON, &options) < 0)
- fprintf(stderr, "Can't get daemon options: %s (%d)\n", strerror(errno), errno);
- else
- printf("Options mask: %d\n", options);
- break;
-
- case 1:
- options = atoi(argv[0]);
- if (ioctl(superdev, VINUM_SETDAEMON, &options) < 0)
- fprintf(stderr, "Can't set daemon options: %s (%d)\n", strerror(errno), errno);
- break;
-
- default:
- fprintf(stderr, "usage: \tsetdaemon [<bitmask>]\n");
- }
- checkupdates(); /* make sure we're updating */
-}
-
-/* Save config info */
-void
-vinum_saveconfig(int argc, char *argv[], char *argv0[])
-{
- int ioctltype;
-
- if (argc != 0) {
- printf("usage: saveconfig\n");
- return;
- }
- ioctltype = 1; /* user saveconfig */
- if (ioctl(superdev, VINUM_SAVECONFIG, &ioctltype) < 0)
- fprintf(stderr, "Can't save configuration: %s (%d)\n", strerror(errno), errno);
- checkupdates(); /* make sure we're updating */
-}
-
-/*
- * Create a volume name for the quick and dirty
- * commands. It will be of the form "vinum#",
- * where # is a small positive number.
- */
-void
-genvolname()
-{
- int v; /* volume number */
- static char volumename[MAXVOLNAME]; /* name to create */
- enum objecttype type;
-
- objectname = volumename; /* point to it */
- for (v = 0;; v++) {
- sprintf(objectname, "vinum%d", v); /* create the name */
- if (find_object(objectname, &type) == -1) /* does it exist? */
- return; /* no, it's ours */
- }
-}
-
-/*
- * Create a drive for the quick and dirty
- * commands. The name will be of the form
- * vinumdrive#, where # is a small positive
- * number. Return the name of the drive.
- */
-struct _drive *
-create_drive(char *devicename)
-{
- int d; /* volume number */
- static char drivename[MAXDRIVENAME]; /* name to create */
- enum objecttype type;
- struct _ioctl_reply *reply;
-
- /*
- * We're never likely to get anything
- * like 10000 drives. The only reason for
- * this limit is to stop the thing
- * looping if we have a bug somewhere.
- */
- for (d = 0; d < 100000; d++) { /* look for a free drive number */
- sprintf(drivename, "vinumdrive%d", d); /* create the name */
- if (find_object(drivename, &type) == -1) { /* does it exist? */
- char command[MAXDRIVENAME * 2];
-
- sprintf(command, "drive %s device %s", drivename, devicename); /* create a create command */
- if (vflag)
- printf("drive %s device %s\n", drivename, devicename); /* create a create command */
- ioctl(superdev, VINUM_CREATE, command);
- reply = (struct _ioctl_reply *) &command;
- if (reply->error != 0) { /* error in config */
- if (reply->msg[0])
- fprintf(stderr,
- "Can't create drive %s, device %s: %s\n",
- drivename,
- devicename,
- reply->msg);
- else
- fprintf(stderr,
- "Can't create drive %s, device %s: %s (%d)\n",
- drivename,
- devicename,
- strerror(reply->error),
- reply->error);
- longjmp(command_fail, -1); /* give up */
- }
- find_object(drivename, &type);
- return &drive; /* return the name of the drive */
- }
- }
- fprintf(stderr, "Can't generate a drive name\n");
- /* NOTREACHED */
- return NULL;
-}
-
-/*
- * Create a volume with a single concatenated plex from
- * as much space as we can get on the specified drives.
- * If the drives aren't Vinum drives, make them so.
- */
-void
-vinum_concat(int argc, char *argv[], char *argv0[])
-{
- int o; /* object number */
- char buffer[BUFSIZE];
- struct _drive *drive; /* drive we're currently looking at */
- struct _ioctl_reply *reply;
- int ioctltype;
- int error;
- enum objecttype type;
-
- reply = (struct _ioctl_reply *) &buffer;
- if (ioctl(superdev, VINUM_STARTCONFIG, &force)) { /* can't get config? */
- printf("Can't configure: %s (%d)\n", strerror(errno), errno);
- return;
- }
- if (!objectname) /* we need a name for our object */
- genvolname();
- sprintf(buffer, "volume %s", objectname);
- if (vflag)
- printf("volume %s\n", objectname);
- ioctl(superdev, VINUM_CREATE, buffer); /* create the volume */
- if (reply->error != 0) { /* error in config */
- if (reply->msg[0])
- fprintf(stderr,
- "Can't create volume %s: %s\n",
- objectname,
- reply->msg);
- else
- fprintf(stderr,
- "Can't create volume %s: %s (%d)\n",
- objectname,
- strerror(reply->error),
- reply->error);
- longjmp(command_fail, -1); /* give up */
- }
- sprintf(buffer, "plex name %s.p0 org concat", objectname);
- if (vflag)
- printf(" plex name %s.p0 org concat\n", objectname);
- ioctl(superdev, VINUM_CREATE, buffer);
- if (reply->error != 0) { /* error in config */
- if (reply->msg[0])
- fprintf(stderr,
- "Can't create plex %s.p0: %s\n",
- objectname,
- reply->msg);
- else
- fprintf(stderr,
- "Can't create plex %s.p0: %s (%d)\n",
- objectname,
- strerror(reply->error),
- reply->error);
- longjmp(command_fail, -1); /* give up */
- }
- for (o = 0; o < argc; o++) {
- if ((drive = find_drive_by_devname(argv[o])) == NULL) /* doesn't exist */
- drive = create_drive(argv[o]); /* create it */
- sprintf(buffer, "sd name %s.p0.s%d drive %s size 0", objectname, o, drive->label.name);
- if (vflag)
- printf(" sd name %s.p0.s%d drive %s size 0\n", objectname, o, drive->label.name);
- ioctl(superdev, VINUM_CREATE, buffer);
- if (reply->error != 0) { /* error in config */
- if (reply->msg[0])
- fprintf(stderr,
- "Can't create subdisk %s.p0.s%d: %s\n",
- objectname,
- o,
- reply->msg);
- else
- fprintf(stderr,
- "Can't create subdisk %s.p0.s%d: %s (%d)\n",
- objectname,
- o,
- strerror(reply->error),
- reply->error);
- longjmp(command_fail, -1); /* give up */
- }
- }
-
- /* done, save the config */
- ioctltype = 0; /* saveconfig after update */
- error = ioctl(superdev, VINUM_SAVECONFIG, &ioctltype); /* save the config to disk */
- if (error != 0)
- perror("Can't save Vinum config");
- find_object(objectname, &type); /* find the index of the volume */
- if (vflag) {
- vflag--; /* XXX don't give too much detail */
- find_object(objectname, &type); /* point to the volume */
- vinum_lvi(vol.volno, 1); /* and print info about it */
- }
-}
-
-
-/*
- * Create a volume with a single striped plex from
- * as much space as we can get on the specified drives.
- * If the drives aren't Vinum drives, make them so.
- */
-void
-vinum_stripe(int argc, char *argv[], char *argv0[])
-{
- int o; /* object number */
- char buffer[BUFSIZE];
- struct _drive *drive; /* drive we're currently looking at */
- struct _ioctl_reply *reply;
- int ioctltype;
- int error;
- enum objecttype type;
- off_t maxsize;
- int fe; /* freelist entry index */
- struct drive_freelist freelist;
- struct ferq { /* request to pass to ioctl */
- int driveno;
- int fe;
- } *ferq = (struct ferq *) &freelist;
- u_int64_t bigchunk; /* biggest chunk in freelist */
-
- maxsize = QUAD_MAX;
- reply = (struct _ioctl_reply *) &buffer;
-
- /*
- * First, check our drives.
- */
- if (argc < 2) {
- fprintf(stderr, "You need at least two drives to create a striped plex\n");
- return;
- }
- if (ioctl(superdev, VINUM_STARTCONFIG, &force)) { /* can't get config? */
- printf("Can't configure: %s (%d)\n", strerror(errno), errno);
- return;
- }
- if (!objectname) /* we need a name for our object */
- genvolname();
- for (o = 0; o < argc; o++) {
- if ((drive = find_drive_by_devname(argv[o])) == NULL) /* doesn't exist */
- drive = create_drive(argv[o]); /* create it */
- /* Now find the largest chunk available on the drive */
- bigchunk = 0; /* ain't found nothin' yet */
- for (fe = 0; fe < drive->freelist_entries; fe++) {
- ferq->driveno = drive->driveno;
- ferq->fe = fe;
- if (ioctl(superdev, VINUM_GETFREELIST, &freelist) < 0) {
- fprintf(stderr,
- "Can't get free list element %d: %s\n",
- fe,
- strerror(errno));
- longjmp(command_fail, -1);
- }
- bigchunk = bigchunk > freelist.sectors ? bigchunk : freelist.sectors; /* max it */
- }
- maxsize = min(maxsize, bigchunk); /* this is as much as we can do */
- }
-
- /* Now create the volume */
- sprintf(buffer, "volume %s", objectname);
- if (vflag)
- printf("volume %s\n", objectname);
- ioctl(superdev, VINUM_CREATE, buffer); /* create the volume */
- if (reply->error != 0) { /* error in config */
- if (reply->msg[0])
- fprintf(stderr,
- "Can't create volume %s: %s\n",
- objectname,
- reply->msg);
- else
- fprintf(stderr,
- "Can't create volume %s: %s (%d)\n",
- objectname,
- strerror(reply->error),
- reply->error);
- longjmp(command_fail, -1); /* give up */
- }
- sprintf(buffer, "plex name %s.p0 org striped 279k", objectname);
- if (vflag)
- printf(" plex name %s.p0 org striped 279k\n", objectname);
- ioctl(superdev, VINUM_CREATE, buffer);
- if (reply->error != 0) { /* error in config */
- if (reply->msg[0])
- fprintf(stderr,
- "Can't create plex %s.p0: %s\n",
- objectname,
- reply->msg);
- else
- fprintf(stderr,
- "Can't create plex %s.p0: %s (%d)\n",
- objectname,
- strerror(reply->error),
- reply->error);
- longjmp(command_fail, -1); /* give up */
- }
- for (o = 0; o < argc; o++) {
- drive = find_drive_by_devname(argv[o]); /* we know it exists... */
- sprintf(buffer,
- "sd name %s.p0.s%d drive %s size %lldb",
- objectname,
- o,
- drive->label.name,
- (long long) maxsize);
- if (vflag)
- printf(" sd name %s.p0.s%d drive %s size %lldb\n",
- objectname,
- o,
- drive->label.name,
- (long long) maxsize);
- ioctl(superdev, VINUM_CREATE, buffer);
- if (reply->error != 0) { /* error in config */
- if (reply->msg[0])
- fprintf(stderr,
- "Can't create subdisk %s.p0.s%d: %s\n",
- objectname,
- o,
- reply->msg);
- else
- fprintf(stderr,
- "Can't create subdisk %s.p0.s%d: %s (%d)\n",
- objectname,
- o,
- strerror(reply->error),
- reply->error);
- longjmp(command_fail, -1); /* give up */
- }
- }
-
- /* done, save the config */
- ioctltype = 0; /* saveconfig after update */
- error = ioctl(superdev, VINUM_SAVECONFIG, &ioctltype); /* save the config to disk */
- if (error != 0)
- perror("Can't save Vinum config");
- find_object(objectname, &type); /* find the index of the volume */
- if (vflag) {
- vflag--; /* XXX don't give too much detail */
- find_object(objectname, &type); /* point to the volume */
- vinum_lvi(vol.volno, 1); /* and print info about it */
- }
-}
-
-/*
- * Create a volume with a single RAID-4 plex from
- * as much space as we can get on the specified drives.
- * If the drives aren't Vinum drives, make them so.
- */
-void
-vinum_raid4(int argc, char *argv[], char *argv0[])
-{
- int o; /* object number */
- char buffer[BUFSIZE];
- struct _drive *drive; /* drive we're currently looking at */
- struct _ioctl_reply *reply;
- int ioctltype;
- int error;
- enum objecttype type;
- off_t maxsize;
- int fe; /* freelist entry index */
- struct drive_freelist freelist;
- struct ferq { /* request to pass to ioctl */
- int driveno;
- int fe;
- } *ferq = (struct ferq *) &freelist;
- u_int64_t bigchunk; /* biggest chunk in freelist */
-
- maxsize = QUAD_MAX;
- reply = (struct _ioctl_reply *) &buffer;
-
- /*
- * First, check our drives.
- */
- if (argc < 3) {
- fprintf(stderr, "You need at least three drives to create a RAID-4 plex\n");
- return;
- }
- if (ioctl(superdev, VINUM_STARTCONFIG, &force)) { /* can't get config? */
- printf("Can't configure: %s (%d)\n", strerror(errno), errno);
- return;
- }
- if (!objectname) /* we need a name for our object */
- genvolname();
- for (o = 0; o < argc; o++) {
- if ((drive = find_drive_by_devname(argv[o])) == NULL) /* doesn't exist */
- drive = create_drive(argv[o]); /* create it */
- /* Now find the largest chunk available on the drive */
- bigchunk = 0; /* ain't found nothin' yet */
- for (fe = 0; fe < drive->freelist_entries; fe++) {
- ferq->driveno = drive->driveno;
- ferq->fe = fe;
- if (ioctl(superdev, VINUM_GETFREELIST, &freelist) < 0) {
- fprintf(stderr,
- "Can't get free list element %d: %s\n",
- fe,
- strerror(errno));
- longjmp(command_fail, -1);
- }
- bigchunk = bigchunk > freelist.sectors ? bigchunk : freelist.sectors; /* max it */
- }
- maxsize = min(maxsize, bigchunk); /* this is as much as we can do */
- }
-
- /* Now create the volume */
- sprintf(buffer, "volume %s", objectname);
- if (vflag)
- printf("volume %s\n", objectname);
- ioctl(superdev, VINUM_CREATE, buffer); /* create the volume */
- if (reply->error != 0) { /* error in config */
- if (reply->msg[0])
- fprintf(stderr,
- "Can't create volume %s: %s\n",
- objectname,
- reply->msg);
- else
- fprintf(stderr,
- "Can't create volume %s: %s (%d)\n",
- objectname,
- strerror(reply->error),
- reply->error);
- longjmp(command_fail, -1); /* give up */
- }
- sprintf(buffer, "plex name %s.p0 org raid4 279k", objectname);
- if (vflag)
- printf(" plex name %s.p0 org raid4 279k\n", objectname);
- ioctl(superdev, VINUM_CREATE, buffer);
- if (reply->error != 0) { /* error in config */
- if (reply->msg[0])
- fprintf(stderr,
- "Can't create plex %s.p0: %s\n",
- objectname,
- reply->msg);
- else
- fprintf(stderr,
- "Can't create plex %s.p0: %s (%d)\n",
- objectname,
- strerror(reply->error),
- reply->error);
- longjmp(command_fail, -1); /* give up */
- }
- for (o = 0; o < argc; o++) {
- drive = find_drive_by_devname(argv[o]); /* we know it exists... */
- sprintf(buffer,
- "sd name %s.p0.s%d drive %s size %lldb",
- objectname,
- o,
- drive->label.name,
- (long long) maxsize);
- if (vflag)
- printf(" sd name %s.p0.s%d drive %s size %lldb\n",
- objectname,
- o,
- drive->label.name,
- (long long) maxsize);
- ioctl(superdev, VINUM_CREATE, buffer);
- if (reply->error != 0) { /* error in config */
- if (reply->msg[0])
- fprintf(stderr,
- "Can't create subdisk %s.p0.s%d: %s\n",
- objectname,
- o,
- reply->msg);
- else
- fprintf(stderr,
- "Can't create subdisk %s.p0.s%d: %s (%d)\n",
- objectname,
- o,
- strerror(reply->error),
- reply->error);
- longjmp(command_fail, -1); /* give up */
- }
- }
-
- /* done, save the config */
- ioctltype = 0; /* saveconfig after update */
- error = ioctl(superdev, VINUM_SAVECONFIG, &ioctltype); /* save the config to disk */
- if (error != 0)
- perror("Can't save Vinum config");
- find_object(objectname, &type); /* find the index of the volume */
- if (vflag) {
- vflag--; /* XXX don't give too much detail */
- find_object(objectname, &type); /* point to the volume */
- vinum_lvi(vol.volno, 1); /* and print info about it */
- }
-}
-
-/*
- * Create a volume with a single RAID-4 plex from
- * as much space as we can get on the specified drives.
- * If the drives aren't Vinum drives, make them so.
- */
-void
-vinum_raid5(int argc, char *argv[], char *argv0[])
-{
- int o; /* object number */
- char buffer[BUFSIZE];
- struct _drive *drive; /* drive we're currently looking at */
- struct _ioctl_reply *reply;
- int ioctltype;
- int error;
- enum objecttype type;
- off_t maxsize;
- int fe; /* freelist entry index */
- struct drive_freelist freelist;
- struct ferq { /* request to pass to ioctl */
- int driveno;
- int fe;
- } *ferq = (struct ferq *) &freelist;
- u_int64_t bigchunk; /* biggest chunk in freelist */
-
- maxsize = QUAD_MAX;
- reply = (struct _ioctl_reply *) &buffer;
-
- /*
- * First, check our drives.
- */
- if (argc < 3) {
- fprintf(stderr, "You need at least three drives to create a RAID-5 plex\n");
- return;
- }
- if (ioctl(superdev, VINUM_STARTCONFIG, &force)) { /* can't get config? */
- printf("Can't configure: %s (%d)\n", strerror(errno), errno);
- return;
- }
- if (!objectname) /* we need a name for our object */
- genvolname();
- for (o = 0; o < argc; o++) {
- if ((drive = find_drive_by_devname(argv[o])) == NULL) /* doesn't exist */
- drive = create_drive(argv[o]); /* create it */
- /* Now find the largest chunk available on the drive */
- bigchunk = 0; /* ain't found nothin' yet */
- for (fe = 0; fe < drive->freelist_entries; fe++) {
- ferq->driveno = drive->driveno;
- ferq->fe = fe;
- if (ioctl(superdev, VINUM_GETFREELIST, &freelist) < 0) {
- fprintf(stderr,
- "Can't get free list element %d: %s\n",
- fe,
- strerror(errno));
- longjmp(command_fail, -1);
- }
- bigchunk = bigchunk > freelist.sectors ? bigchunk : freelist.sectors; /* max it */
- }
- maxsize = min(maxsize, bigchunk); /* this is as much as we can do */
- }
-
- /* Now create the volume */
- sprintf(buffer, "volume %s", objectname);
- if (vflag)
- printf("volume %s\n", objectname);
- ioctl(superdev, VINUM_CREATE, buffer); /* create the volume */
- if (reply->error != 0) { /* error in config */
- if (reply->msg[0])
- fprintf(stderr,
- "Can't create volume %s: %s\n",
- objectname,
- reply->msg);
- else
- fprintf(stderr,
- "Can't create volume %s: %s (%d)\n",
- objectname,
- strerror(reply->error),
- reply->error);
- longjmp(command_fail, -1); /* give up */
- }
- sprintf(buffer, "plex name %s.p0 org raid5 279k", objectname);
- if (vflag)
- printf(" plex name %s.p0 org raid5 279k\n", objectname);
- ioctl(superdev, VINUM_CREATE, buffer);
- if (reply->error != 0) { /* error in config */
- if (reply->msg[0])
- fprintf(stderr,
- "Can't create plex %s.p0: %s\n",
- objectname,
- reply->msg);
- else
- fprintf(stderr,
- "Can't create plex %s.p0: %s (%d)\n",
- objectname,
- strerror(reply->error),
- reply->error);
- longjmp(command_fail, -1); /* give up */
- }
- for (o = 0; o < argc; o++) {
- drive = find_drive_by_devname(argv[o]); /* we know it exists... */
- sprintf(buffer,
- "sd name %s.p0.s%d drive %s size %lldb",
- objectname,
- o,
- drive->label.name,
- (long long) maxsize);
- if (vflag)
- printf(" sd name %s.p0.s%d drive %s size %lldb\n",
- objectname,
- o,
- drive->label.name,
- (long long) maxsize);
- ioctl(superdev, VINUM_CREATE, buffer);
- if (reply->error != 0) { /* error in config */
- if (reply->msg[0])
- fprintf(stderr,
- "Can't create subdisk %s.p0.s%d: %s\n",
- objectname,
- o,
- reply->msg);
- else
- fprintf(stderr,
- "Can't create subdisk %s.p0.s%d: %s (%d)\n",
- objectname,
- o,
- strerror(reply->error),
- reply->error);
- longjmp(command_fail, -1); /* give up */
- }
- }
-
- /* done, save the config */
- ioctltype = 0; /* saveconfig after update */
- error = ioctl(superdev, VINUM_SAVECONFIG, &ioctltype); /* save the config to disk */
- if (error != 0)
- perror("Can't save Vinum config");
- find_object(objectname, &type); /* find the index of the volume */
- if (vflag) {
- vflag--; /* XXX don't give too much detail */
- find_object(objectname, &type); /* point to the volume */
- vinum_lvi(vol.volno, 1); /* and print info about it */
- }
-}
-
-/*
- * Create a volume with a two plexes from as much space
- * as we can get on the specified drives. If the
- * drives aren't Vinum drives, make them so.
- *
- * The number of drives must be even, and at least 4
- * for a striped plex. Specify striped plexes with the
- * -s flag; otherwise they will be concatenated. It's
- * possible that the two plexes may differ in length.
- */
-void
-vinum_mirror(int argc, char *argv[], char *argv0[])
-{
- int o; /* object number */
- int p; /* plex number */
- char buffer[BUFSIZE];
- struct _drive *drive; /* drive we're currently looking at */
- struct _ioctl_reply *reply;
- int ioctltype;
- int error;
- enum objecttype type;
- off_t maxsize[2]; /* maximum subdisk size for striped plexes */
- int fe; /* freelist entry index */
- struct drive_freelist freelist;
- struct ferq { /* request to pass to ioctl */
- int driveno;
- int fe;
- } *ferq = (struct ferq *) &freelist;
- u_int64_t bigchunk; /* biggest chunk in freelist */
-
- if (sflag) /* striped, */
- maxsize[0] = maxsize[1] = QUAD_MAX; /* we need to calculate sd size */
- else
- maxsize[0] = maxsize[1] = 0; /* let the kernel routines do it */
-
- reply = (struct _ioctl_reply *) &buffer;
-
- /*
- * First, check our drives.
- */
- if ((argc < 2)
- || (argc & 1)) {
- fprintf(stderr, "You need an even number of drives to create a mirrored volume\n");
- return;
- }
- if (sflag && (argc < 4)) {
- fprintf(stderr, "You need at least 4 drives to create a mirrored, striped volume\n");
- return;
- }
- if (ioctl(superdev, VINUM_STARTCONFIG, &force)) { /* can't get config? */
- printf("Can't configure: %s (%d)\n", strerror(errno), errno);
- return;
- }
- if (!objectname) /* we need a name for our object */
- genvolname();
- for (o = 0; o < argc; o++) {
- if ((drive = find_drive_by_devname(argv[o])) == NULL) /* doesn't exist */
- drive = create_drive(argv[o]); /* create it */
- if (sflag) { /* striping, */
- /* Find the largest chunk available on the drive */
- bigchunk = 0; /* ain't found nothin' yet */
- for (fe = 0; fe < drive->freelist_entries; fe++) {
- ferq->driveno = drive->driveno;
- ferq->fe = fe;
- if (ioctl(superdev, VINUM_GETFREELIST, &freelist) < 0) {
- fprintf(stderr,
- "Can't get free list element %d: %s\n",
- fe,
- strerror(errno));
- longjmp(command_fail, -1);
- }
- bigchunk = bigchunk > freelist.sectors ? bigchunk : freelist.sectors; /* max it */
- }
- maxsize[o & 1] = min(maxsize[o & 1], bigchunk); /* get the maximum size of a subdisk */
- }
- }
-
- /* Now create the volume */
- sprintf(buffer, "volume %s setupstate", objectname);
- if (vflag)
- printf("volume %s setupstate\n", objectname);
- ioctl(superdev, VINUM_CREATE, buffer); /* create the volume */
- if (reply->error != 0) { /* error in config */
- if (reply->msg[0])
- fprintf(stderr,
- "Can't create volume %s: %s\n",
- objectname,
- reply->msg);
- else
- fprintf(stderr,
- "Can't create volume %s: %s (%d)\n",
- objectname,
- strerror(reply->error),
- reply->error);
- longjmp(command_fail, -1); /* give up */
- }
- for (p = 0; p < 2; p++) { /* create each plex */
- if (sflag) {
- sprintf(buffer, "plex name %s.p%d org striped 279k", objectname, p);
- if (vflag)
- printf(" plex name %s.p%d org striped 279k\n", objectname, p);
- } else { /* concat */
- sprintf(buffer, "plex name %s.p%d org concat", objectname, p);
- if (vflag)
- printf(" plex name %s.p%d org concat\n", objectname, p);
- }
- ioctl(superdev, VINUM_CREATE, buffer);
- if (reply->error != 0) { /* error in config */
- if (reply->msg[0])
- fprintf(stderr,
- "Can't create plex %s.p%d: %s\n",
- objectname,
- p,
- reply->msg);
- else
- fprintf(stderr,
- "Can't create plex %s.p%d: %s (%d)\n",
- objectname,
- p,
- strerror(reply->error),
- reply->error);
- longjmp(command_fail, -1); /* give up */
- }
- /* Now look at the subdisks */
- for (o = p; o < argc; o += 2) { /* every second one */
- drive = find_drive_by_devname(argv[o]); /* we know it exists... */
- sprintf(buffer,
- "sd name %s.p%d.s%d drive %s size %lldb",
- objectname,
- p,
- o >> 1,
- drive->label.name,
- (long long) maxsize[p]);
- if (vflag)
- printf(" sd name %s.p%d.s%d drive %s size %lldb\n",
- objectname,
- p,
- o >> 1,
- drive->label.name,
- (long long) maxsize[p]);
- ioctl(superdev, VINUM_CREATE, buffer);
- if (reply->error != 0) { /* error in config */
- if (reply->msg[0])
- fprintf(stderr,
- "Can't create subdisk %s.p%d.s%d: %s\n",
- objectname,
- p,
- o >> 1,
- reply->msg);
- else
- fprintf(stderr,
- "Can't create subdisk %s.p%d.s%d: %s (%d)\n",
- objectname,
- p,
- o >> 1,
- strerror(reply->error),
- reply->error);
- longjmp(command_fail, -1); /* give up */
- }
- }
- }
-
- /* done, save the config */
- ioctltype = 0; /* saveconfig after update */
- error = ioctl(superdev, VINUM_SAVECONFIG, &ioctltype); /* save the config to disk */
- if (error != 0)
- perror("Can't save Vinum config");
- find_object(objectname, &type); /* find the index of the volume */
- if (vflag) {
- vflag--; /* XXX don't give too much detail */
- sflag = 0; /* no stats, please */
- find_object(objectname, &type); /* point to the volume */
- vinum_lvi(vol.volno, 1); /* and print info about it */
- }
-}
-
-void
-vinum_readpol(int argc, char *argv[], char *argv0[])
-{
- int object;
- struct _ioctl_reply reply;
- struct vinum_ioctl_msg *message = (struct vinum_ioctl_msg *) &reply;
- enum objecttype type;
- struct _plex plex;
- struct _volume vol;
- int plexno;
-
- if (argc != 2) {
- fprintf(stderr, "usage: readpol <volume> <plex> | round\n");
- return;
- }
- object = find_object(argv[0], &type); /* look for it */
- if (type != volume_object) {
- fprintf(stderr, "%s is not a volume\n", argv[0]);
- return;
- }
- get_volume_info(&vol, object);
- if (strcmp(argv[1], "round")) { /* not 'round' */
- object = find_object(argv[1], &type); /* look for it */
- if (type != plex_object) {
- fprintf(stderr, "%s is not a plex\n", argv[1]);
- return;
- }
- get_plex_info(&plex, object);
- plexno = plex.plexno;
- } else /* round */
- plexno = -1;
-
- /* Set the value */
- message->index = vol.volno;
- message->otherobject = plexno;
- ioctl(superdev, VINUM_READPOL, message);
- if (reply.error)
- fprintf(stderr,
- "Can't set read policy: %s (%d)\n",
- reply.msg[0] ? reply.msg : strerror(reply.error),
- reply.error);
- if (vflag)
- vinum_lpi(plexno, recurse);
-}
-
-/*
- * Brute force set state function. Don't look at
- * any dependencies, just do it.
- */
-void
-vinum_setstate(int argc, char *argv[], char *argv0[])
-{
- int object;
- struct _ioctl_reply reply;
- struct vinum_ioctl_msg *message = (struct vinum_ioctl_msg *) &reply;
- int index;
- enum objecttype type;
- int state;
-
- for (index = 1; index < argc; index++) {
- object = find_object(argv[index], &type); /* look for it */
- if (type == invalid_object)
- fprintf(stderr, "Can't find object: %s\n", argv[index]);
- else {
- int doit = 0; /* set to 1 if we pass our tests */
- switch (type) {
- case drive_object:
- state = DriveState(argv[0]); /* get the state */
- if (drive.state == state) /* already in that state */
- fprintf(stderr, "%s is already %s\n", drive.label.name, argv[0]);
- else
- doit = 1;
- break;
-
- case sd_object:
- state = SdState(argv[0]); /* get the state */
- if (sd.state == state) /* already in that state */
- fprintf(stderr, "%s is already %s\n", sd.name, argv[0]);
- else
- doit = 1;
- break;
-
- case plex_object:
- state = PlexState(argv[0]); /* get the state */
- if (plex.state == state) /* already in that state */
- fprintf(stderr, "%s is already %s\n", plex.name, argv[0]);
- else
- doit = 1;
- break;
-
- case volume_object:
- state = VolState(argv[0]); /* get the state */
- if (vol.state == state) /* already in that state */
- fprintf(stderr, "%s is already %s\n", vol.name, argv[0]);
- else
- doit = 1;
- break;
-
- default:
- state = 0; /* to keep the compiler happy */
- }
-
- if (state == -1)
- fprintf(stderr, "Invalid state for object: %s\n", argv[0]);
- else if (doit) {
- message->index = object; /* pass object number */
- message->type = type; /* and type of object */
- message->state = state;
- message->force = force; /* don't force it, use a larger hammer */
- ioctl(superdev, VINUM_SETSTATE_FORCE, message);
- if (reply.error != 0)
- fprintf(stderr,
- "Can't start %s: %s (%d)\n",
- argv[index],
- reply.msg[0] ? reply.msg : strerror(reply.error),
- reply.error);
- if (Verbose)
- vinum_li(object, type);
- }
- }
- }
-}
-
-void
-vinum_checkparity(int argc, char *argv[], char *argv0[])
-{
- Verbose = vflag; /* accept -v for verbose */
- if (argc == 0) /* no parameters? */
- fprintf(stderr, "usage: checkparity object [object...]\n");
- else
- parityops(argc, argv, checkparity);
-}
-
-void
-vinum_rebuildparity(int argc, char *argv[], char *argv0[])
-{
- if (argc == 0) /* no parameters? */
- fprintf(stderr, "usage: rebuildparity object [object...]\n");
- else
- parityops(argc, argv, vflag ? rebuildandcheckparity : rebuildparity);
-}
-
-/*
- * Common code for rebuildparity and checkparity.
- * We bend the meanings of some flags here:
- *
- * -v: Report incorrect parity on rebuild.
- * -V: Show running count of position being checked.
- * -f: Start from beginning of the plex.
- */
-void
-parityops(int argc, char *argv[], enum parityop op)
-{
- int object;
- struct _plex plex;
- struct _ioctl_reply reply;
- struct vinum_ioctl_msg *message = (struct vinum_ioctl_msg *) &reply;
- int index;
- enum objecttype type;
- char *msg;
- off_t block;
-
- if (op == checkparity)
- msg = "Checking";
- else
- msg = "Rebuilding";
- for (index = 0; index < argc; index++) {
- object = find_object(argv[index], &type); /* look for it */
- if (type != plex_object)
- fprintf(stderr, "%s is not a plex\n", argv[index]);
- else {
- get_plex_info(&plex, object);
- if (!isparity((&plex)))
- fprintf(stderr, "%s is not a RAID-4 or RAID-5 plex\n", argv[index]);
- else {
- do {
- message->index = object; /* pass object number */
- message->type = type; /* and type of object */
- message->op = op; /* what to do */
- if (force)
- message->offset = 0; /* start at the beginning */
- else
- message->offset = plex.checkblock; /* continue where we left off */
- force = 0; /* don't reset after the first time */
- ioctl(superdev, VINUM_PARITYOP, message);
- get_plex_info(&plex, object);
- if (Verbose) {
- block = (plex.checkblock << DEV_BSHIFT) * (plex.subdisks - 1);
- if (block != 0)
- printf("\r%s at %s (%d%%) ",
- msg,
- roughlength(block, 1),
- ((int) (block * 100 / plex.length) >> DEV_BSHIFT));
- if ((reply.error == EAGAIN)
- && (reply.msg[0])) /* got a comment back */
- fputs(reply.msg, stderr); /* show it */
- fflush(stdout);
- }
- }
- while (reply.error == EAGAIN);
- if (reply.error != 0) {
- if (reply.msg[0])
- fputs(reply.msg, stderr);
- else
- fprintf(stderr,
- "%s failed: %s\n",
- msg,
- strerror(reply.error));
- } else if (Verbose) {
- if (op == checkparity)
- fprintf(stderr, "%s has correct parity\n", argv[index]);
- else
- fprintf(stderr, "Rebuilt parity on %s\n", argv[index]);
- }
- }
- }
- }
-}
-
-/* Local Variables: */
-/* fill-column: 50 */
-/* End: */
OpenPOWER on IntegriCloud