summaryrefslogtreecommitdiffstats
path: root/sbin/vinum/v.c
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/vinum/v.c')
-rw-r--r--sbin/vinum/v.c685
1 files changed, 0 insertions, 685 deletions
diff --git a/sbin/vinum/v.c b/sbin/vinum/v.c
deleted file mode 100644
index e00f734..0000000
--- a/sbin/vinum/v.c
+++ /dev/null
@@ -1,685 +0,0 @@
-/* vinum.c: vinum interface program */
-/*-
- * 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: v.c,v 1.38 2003/05/01 01:39:42 grog Exp $
- * $FreeBSD$
- */
-
-#include "vext.h"
-
-FILE *cf; /* config file handle */
-FILE *History; /* history file */
-char *historyfile; /* and its name */
-
-char *dateformat; /* format in which to store date */
-
-char buffer[BUFSIZE]; /* buffer to read in to */
-
-int line = 0; /* stdin line number for error messages */
-int file_line = 0; /* and line in input file (yes, this is tacky) */
-int inerror; /* set to 1 to exit after end of config file */
-
-/* flags */
-
-int debug = 0; /* debug flag, usage varies */
-int force = 0; /* set to 1 to force some dangerous ops */
-int interval = 0; /* interval in ms between init/revive */
-int vflag = 0; /* set verbose operation or verify */
-int Verbose = 0; /* set very verbose operation */
-int recurse = 0; /* set recursion */
-int sflag = 0; /* show statistics */
-int SSize = 0; /* sector size for revive */
-int dowait = 0; /* wait for completion */
-char *objectname; /* name to be passed for -n flag */
-
-/*
- * Structures to read kernel data into. These are shortened versions
- * of the kernel data structures, without the bits and pieces we
- * shouldn't be using.
- */
-struct __vinum_conf vinum_conf; /* configuration information */
-struct _volume vol;
-struct _plex plex;
-struct _sd sd;
-struct _drive drive;
-
-jmp_buf command_fail; /* return on a failed command */
-int superdev; /* vinum super device */
-gid_t gid_operator; /* group operator for chown */
-#define GROUP_OPERATOR "operator"
-#define UID_ROOT 0 /* no need to lookup... */
-
-void start_daemon(void);
-
-#define ofs(x) ((void *) (& ((struct confdata *) 0)->x)) /* offset of x in struct confdata */
-
-char *token[MAXARGS]; /* pointers to individual tokens */
-int tokens; /* number of tokens */
-
-int
-main(int argc, char *argv[], char *envp[])
-{
- struct stat histstat;
- struct group *g;
-
- if (modfind(VINUMMOD) < 0) {
- /* need to load the vinum module */
- if (kldload(VINUMMOD) < 0 || modfind(VINUMMOD) < 0) {
- perror(VINUMMOD ": Kernel module not available");
- return 1;
- }
- }
- dateformat = getenv("VINUM_DATEFORMAT");
- if (dateformat == NULL)
- dateformat = "%e %b %Y %H:%M:%S";
- historyfile = getenv("VINUM_HISTORY");
- if (historyfile == NULL)
- historyfile = DEFAULT_HISTORYFILE;
- if (stat(historyfile, &histstat) == 0) { /* history file exists */
- if ((histstat.st_mode & S_IFMT) != S_IFREG) {
- fprintf(stderr,
- "Vinum history file %s must be a regular file\n",
- historyfile);
- exit(1);
- }
- } else if ((errno != ENOENT) /* not "not there", */
- &&(errno != EROFS)) { /* and not read-only file system */
- fprintf(stderr,
- "Can't open %s: %s (%d)\n",
- historyfile,
- strerror(errno),
- errno);
- exit(1);
- }
- History = fopen(historyfile, "a+");
- if (History != NULL) {
- timestamp();
- fprintf(History, "*** " VINUMMOD " started ***\n");
- fflush(History); /* before we start the daemon */
- }
- superdev = open(VINUM_SUPERDEV_NAME, O_RDWR); /* open vinum superdevice */
- if (superdev < 0) { /* no go */
- perror("Can't open " VINUM_SUPERDEV_NAME);
- return 1;
- }
- /*
- * Check that we match the kernel version. There are a number of
- * possibilities here:
- *
- * 0: The versions are OK.
- * 1: The kernel module could be a pre-version 1 module, which
- * doesn't include this check. In that case, vinum_conf will be too
- * short, and so we'll get an EINVAL back when trying to get it. In
- * this case we'll fake a 0 in the version.
- * 2: The module versions are different. Print appropriate messages
- * and die.
- */
- if (ioctl(superdev, VINUM_GETCONFIG, &vinum_conf) < 0) {
- if (errno == EINVAL) /* wrong length, */
- vinum_conf.version = 0; /* must be the old version */
- else {
- perror("Can't get vinum config");
- return 1;
- }
- }
- if (vinum_conf.version != VINUMVERSION) {
- fprintf(stderr,
- "Version mismatch. The kernel module is version %d of Vinum,\n"
- "but this program is designed for version %d\n",
- vinum_conf.version,
- VINUMVERSION);
- if (vinum_conf.version < VINUMVERSION)
- fprintf(stderr, "Please upgrade your kernel module.\n");
- else
- fprintf(stderr, "Please upgrade vinum(8).\n");
- return 1;
- }
- /* Check if the dæmon is running. If not, start it in the
- * background */
- start_daemon();
- if ((g = getgrnam(GROUP_OPERATOR)) != NULL)
- gid_operator = g->gr_gid;
- endgrent();
-
- if (argc > 1) { /* we have a command on the line */
- if (setjmp(command_fail) != 0) /* long jumped out */
- return -1;
- parseline(argc - 1, &argv[1]); /* do it */
- } else {
- /*
- * Catch a possible race condition which could cause us to
- * longjmp() into nowhere if we receive a SIGINT in the next few
- * lines.
- */
- if (setjmp(command_fail)) /* come back here on catastrophic failure */
- return 1;
- setsigs(); /* set signal handler */
- for (;;) { /* ugh */
- char *c;
- int childstatus; /* from wait4 */
-
- if (setjmp(command_fail) == 2) /* come back here on catastrophic failure */
- fprintf(stderr, "*** interrupted ***\n"); /* interrupted */
-
- while (wait4(-1, &childstatus, WNOHANG, NULL) > 0); /* wait for all dead children */
- c = readline(VINUMMOD " -> "); /* get an input */
- if (c == NULL) { /* EOF or error */
- if (ferror(stdin)) {
- fprintf(stderr, "Can't read input: %s (%d)\n", strerror(errno), errno);
- return 1;
- } else { /* EOF */
- printf("\n");
- return 0;
- }
- } else if (*c) { /* got something there */
- add_history(c); /* save it in the history */
- strcpy(buffer, c); /* put it where we can munge it */
- free(c);
- line++; /* count the lines */
- tokens = tokenize(buffer, token, MAXARGS);
- /* got something potentially worth parsing */
- if (tokens)
- parseline(tokens, token); /* and do what he says */
- }
- if (History)
- fflush(History);
- }
- }
- return 0; /* normal completion */
-}
-
-/* stop the hard way */
-void
-vinum_quit(int argc, char *argv[], char *argv0[])
-{
- exit(0);
-}
-
-/* Set action on receiving a SIGINT */
-void
-setsigs()
-{
- struct sigaction act;
-
- act.sa_handler = catchsig;
- act.sa_flags = 0;
- sigemptyset(&act.sa_mask);
- sigaction(SIGINT, &act, NULL);
-}
-
-void
-catchsig(int ignore)
-{
- longjmp(command_fail, 2);
-}
-
-#define FUNKEY(x) { kw_##x, &vinum_##x } /* create pair "kw_foo", vinum_foo */
-#define vinum_move vinum_mv /* synonym for 'mv' */
-
-struct funkey {
- enum keyword kw;
- void (*fun) (int argc, char *argv[], char *arg0[]);
-} funkeys[] = {
-
- FUNKEY(create),
- FUNKEY(read),
- FUNKEY(debug),
- FUNKEY(modify),
- FUNKEY(list),
- FUNKEY(ld),
- FUNKEY(ls),
- FUNKEY(lp),
- FUNKEY(lv),
- FUNKEY(info),
- FUNKEY(set),
- FUNKEY(init),
- FUNKEY(resetconfig),
- FUNKEY(rm),
- FUNKEY(mv),
- FUNKEY(move),
- FUNKEY(attach),
- FUNKEY(detach),
- FUNKEY(rename),
- FUNKEY(replace),
- FUNKEY(printconfig),
- FUNKEY(saveconfig),
- FUNKEY(start),
- FUNKEY(stop),
- FUNKEY(makedev),
- FUNKEY(help),
- FUNKEY(quit),
- FUNKEY(concat),
- FUNKEY(stripe),
- FUNKEY(raid4),
- FUNKEY(raid5),
- FUNKEY(mirror),
- FUNKEY(setdaemon),
- FUNKEY(readpol),
- FUNKEY(resetstats),
- FUNKEY(setstate),
- FUNKEY(checkparity),
- FUNKEY(rebuildparity),
- FUNKEY(dumpconfig)
-};
-
-/* Take args arguments at argv and attempt to perform the operation specified */
-void
-parseline(int args, char *argv[])
-{
- int i;
- int j;
- enum keyword command; /* command to execute */
-
- if (History != NULL) { /* save the command to history file */
- timestamp();
- for (i = 0; i < args; i++) /* all args */
- fprintf(History, "%s ", argv[i]);
- fputs("\n", History);
- }
- if ((args == 0) /* empty line */
- ||(*argv[0] == '#')) /* or a comment, */
- return;
- if (args == MAXARGS) { /* too many arguments, */
- fprintf(stderr, "Too many arguments to %s, this can't be right\n", argv[0]);
- return;
- }
- command = get_keyword(argv[0], &keyword_set);
- dowait = 0; /* initialize flags */
- force = 0; /* initialize flags */
- vflag = 0; /* initialize flags */
- Verbose = 0; /* initialize flags */
- recurse = 0; /* initialize flags */
- sflag = 0; /* initialize flags */
- objectname = NULL; /* no name yet */
-
- /*
- * first handle generic options
- * We don't use getopt(3) because
- * getopt doesn't allow merging flags
- * (for example, -fr).
- */
- for (i = 1; (i < args) && (argv[i][0] == '-'); i++) { /* while we have flags */
- for (j = 1; j < strlen(argv[i]); j++)
- switch (argv[i][j]) {
- case 'd': /* -d: debug */
- debug = 1;
- break;
-
- case 'f': /* -f: force */
- force = 1;
- break;
-
- case 'i': /* interval */
- interval = 0;
- if (argv[i][j + 1] != '\0') /* operand follows, */
- interval = atoi(&argv[i][j + 1]); /* use it */
- else if (args > (i + 1)) /* another following, */
- interval = atoi(argv[++i]); /* use it */
- if (interval == 0) /* nothing valid, */
- fprintf(stderr, "-i: no interval specified\n");
- break;
-
- case 'n': /* -n: get name */
- if (i == args - 1) { /* last arg */
- fprintf(stderr, "-n requires a name parameter\n");
- return;
- }
- objectname = argv[++i]; /* pick it up */
- j = strlen(argv[i]); /* skip the next parm */
- break;
-
- case 'r': /* -r: recurse */
- recurse = 1;
- break;
-
- case 's': /* -s: show statistics */
- sflag = 1;
- break;
-
- case 'S':
- SSize = 0;
- if (argv[i][j + 1] != '\0') /* operand follows, */
- SSize = atoi(&argv[i][j + 1]); /* use it */
- else if (args > (i + 1)) /* another following, */
- SSize = atoi(argv[++i]); /* use it */
- if (SSize == 0) /* nothing valid, */
- fprintf(stderr, "-S: no size specified\n");
- break;
-
- case 'v': /* -v: verbose */
- vflag++;
- break;
-
- case 'V': /* -V: Very verbose */
- vflag++;
- Verbose++;
- break;
-
- case 'w': /* -w: wait for completion */
- dowait = 1;
- break;
-
- default:
- fprintf(stderr, "Invalid flag: %s\n", argv[i]);
- }
- }
-
- /* Pass what we have left to the command to handle it */
- for (j = 0; j < (sizeof(funkeys) / sizeof(struct funkey)); j++) {
- if (funkeys[j].kw == command) { /* found the command */
- funkeys[j].fun(args - i, &argv[i], &argv[0]);
- return;
- }
- }
- fprintf(stderr, "Unknown command: %s\n", argv[0]);
-}
-
-void
-get_drive_info(struct _drive *drive, int index)
-{
- *(int *) drive = index; /* put in drive to hand to driver */
- if (ioctl(superdev, VINUM_DRIVECONFIG, drive) < 0) {
- fprintf(stderr,
- "Can't get config for drive %d: %s\n",
- index,
- strerror(errno));
- longjmp(command_fail, -1);
- }
-}
-
-void
-get_sd_info(struct _sd *sd, int index)
-{
- *(int *) sd = index; /* put in sd to hand to driver */
- if (ioctl(superdev, VINUM_SDCONFIG, sd) < 0) {
- fprintf(stderr,
- "Can't get config for subdisk %d: %s\n",
- index,
- strerror(errno));
- longjmp(command_fail, -1);
- }
-}
-
-/* Get the contents of the sd entry for subdisk <sdno>
- * of the specified plex. */
-void
-get_plex_sd_info(struct _sd *sd, int plexno, int sdno)
-{
- ((int *) sd)[0] = plexno;
- ((int *) sd)[1] = sdno; /* pass parameters */
- if (ioctl(superdev, VINUM_PLEXSDCONFIG, sd) < 0) {
- fprintf(stderr,
- "Can't get config for subdisk %d (part of plex %d): %s\n",
- sdno,
- plexno,
- strerror(errno));
- longjmp(command_fail, -1);
- }
-}
-
-void
-get_plex_info(struct _plex *plex, int index)
-{
- *(int *) plex = index; /* put in plex to hand to driver */
- if (ioctl(superdev, VINUM_PLEXCONFIG, plex) < 0) {
- fprintf(stderr,
- "Can't get config for plex %d: %s\n",
- index,
- strerror(errno));
- longjmp(command_fail, -1);
- }
-}
-
-void
-get_volume_info(struct _volume *volume, int index)
-{
- *(int *) volume = index; /* put in volume to hand to driver */
- if (ioctl(superdev, VINUM_VOLCONFIG, volume) < 0) {
- fprintf(stderr,
- "Can't get config for volume %d: %s\n",
- index,
- strerror(errno));
- longjmp(command_fail, -1);
- }
-}
-
-struct _drive *
-find_drive_by_devname(char *name)
-{
- int driveno;
-
- if (ioctl(superdev, VINUM_GETCONFIG, &vinum_conf) < 0) {
- perror("Can't get vinum config");
- return NULL;
- }
- for (driveno = 0; driveno < vinum_conf.drives_allocated; driveno++) {
- get_drive_info(&drive, driveno);
- if ((drive.state != drive_unallocated) /* real drive */
- &&(!strcmp(drive.devicename, name))) /* and the name's right, */
- return &drive; /* found it */
- }
- return NULL; /* no drive of that name */
-}
-
-/* command line interface for the 'makedev' command */
-void
-vinum_makedev(int argc, char *argv[], char *arg0[])
-{
- fprintf(stderr, "makedev is not needed for a DEVFS-based system\n");
-}
-
-/*
- * Find the object "name". Return object type at type,
- * and the index as the return value.
- * If not found, return -1 and invalid_object.
- */
-int
-find_object(const char *name, enum objecttype *type)
-{
- int object;
-
- if (ioctl(superdev, VINUM_GETCONFIG, &vinum_conf) < 0) {
- perror("Can't get vinum config");
- *type = invalid_object;
- return -1;
- }
- /* Search the drive table */
- for (object = 0; object < vinum_conf.drives_allocated; object++) {
- get_drive_info(&drive, object);
- if (strcmp(name, drive.label.name) == 0) {
- *type = drive_object;
- return object;
- }
- }
-
- /* Search the subdisk table */
- for (object = 0; object < vinum_conf.subdisks_allocated; object++) {
- get_sd_info(&sd, object);
- if (strcmp(name, sd.name) == 0) {
- *type = sd_object;
- return object;
- }
- }
-
- /* Search the plex table */
- for (object = 0; object < vinum_conf.plexes_allocated; object++) {
- get_plex_info(&plex, object);
- if (strcmp(name, plex.name) == 0) {
- *type = plex_object;
- return object;
- }
- }
-
- /* Search the volume table */
- for (object = 0; object < vinum_conf.volumes_allocated; object++) {
- get_volume_info(&vol, object);
- if (strcmp(name, vol.name) == 0) {
- *type = volume_object;
- return object;
- }
- }
-
- /* Didn't find the name: invalid */
- *type = invalid_object;
- return -1;
-}
-
-/* Continue reviving a subdisk in the background */
-void
-continue_revive(int sdno)
-{
- struct _sd sd;
- pid_t pid;
- get_sd_info(&sd, sdno);
-
- if (dowait == 0)
- pid = fork(); /* do this in the background */
- else
- pid = 0;
- if (pid == 0) { /* we're the child */
- struct _ioctl_reply reply;
- struct vinum_ioctl_msg *message = (struct vinum_ioctl_msg *) &reply;
-
- openlog(VINUMMOD, LOG_CONS | LOG_PERROR | LOG_PID, LOG_KERN);
- syslog(LOG_INFO | LOG_KERN, "reviving %s", sd.name);
- setproctitle("reviving %s", sd.name);
-
- for (reply.error = EAGAIN; reply.error == EAGAIN;) { /* revive the subdisk */
- if (interval)
- usleep(interval * 1000); /* pause between each copy */
- message->index = sdno; /* pass sd number */
- message->type = sd_object; /* and type of object */
- message->state = object_up;
- 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) {
- syslog(LOG_ERR | LOG_KERN,
- "can't revive %s: %s",
- sd.name,
- reply.msg[0] ? reply.msg : strerror(reply.error));
- if (dowait == 0)
- exit(1);
- } else {
- get_sd_info(&sd, sdno); /* update the info */
- syslog(LOG_INFO | LOG_KERN, "%s is %s", sd.name, sd_state(sd.state));
- if (dowait == 0)
- exit(0);
- }
- } else if (pid < 0) /* couldn't fork? */
- fprintf(stderr, "Can't continue reviving %s: %s\n", sd.name, strerror(errno));
- else /* parent */
- printf("Reviving %s in the background\n", sd.name);
-}
-
-/*
- * Check if the daemon is running,
- * start it if it isn't. The check itself
- * could take a while, so we do it as a separate
- * process, which will become the daemon if one isn't
- * running already
- */
-void
-start_daemon(void)
-{
- int pid;
- int status;
- int error;
-
- pid = (int) fork();
-
- if (pid == 0) { /* We're the child, do the work */
- /*
- * We have a problem when stopping the subsystem:
- * The only way to know that we're idle is when
- * all open superdevs close. But we want the
- * daemon to clean up for us, and since we can't
- * count the opens, we need to have the main device
- * closed when we stop. We solve this conundrum
- * by getting the daemon to open a separate device.
- */
- close(superdev); /* this is the wrong device */
- superdev = open(VINUM_DAEMON_DEV_NAME, O_RDWR); /* open deamon superdevice */
- if (superdev < 0) {
- perror("Can't open " VINUM_DAEMON_DEV_NAME);
- exit(1);
- }
- error = daemon(0, 0); /* this will fork again, but who's counting? */
- if (error != 0) {
- fprintf(stderr, "Can't start daemon: %s (%d)\n", strerror(errno), errno);
- exit(1);
- }
- setproctitle(VINUMMOD " daemon"); /* show what we're doing */
- status = ioctl(superdev, VINUM_FINDDAEMON, NULL);
- if (status != 0) { /* no daemon, */
- ioctl(superdev, VINUM_DAEMON, &vflag); /* we should hang here */
- syslog(LOG_ERR | LOG_KERN, "%s", strerror(errno));
- exit(1);
- }
- exit(0); /* when told to die */
- } else if (pid < 0) /* couldn't fork */
- printf("Can't fork to check daemon\n");
-}
-
-void
-timestamp()
-{
- struct timeval now;
- struct tm *date;
- char datetext[MAXDATETEXT];
- time_t sec;
-
- if (History != NULL) {
- if (gettimeofday(&now, NULL) != 0) {
- fprintf(stderr, "Can't get time: %s\n", strerror(errno));
- return;
- }
- sec = now.tv_sec;
- date = localtime(&sec);
- strftime(datetext, MAXDATETEXT, dateformat, date),
- fprintf(History,
- "%s.%06ld ",
- datetext,
- now.tv_usec);
- }
-}
OpenPOWER on IntegriCloud