Ups! Forgot to put "sbin" on the commit line:
Remove userland vinum(8) stuff.
This commit is contained in:
parent
a6fd48812e
commit
1072404b17
@ -94,7 +94,6 @@ SUBDIR= adjkerntz \
|
||||
sysctl \
|
||||
tunefs \
|
||||
umount \
|
||||
${_vinum}
|
||||
|
||||
.if !defined(NOATM)
|
||||
_atm= atm
|
||||
@ -122,10 +121,6 @@ _ip6fw= ip6fw
|
||||
_ping6= ping6
|
||||
.endif
|
||||
|
||||
.if !defined(NO_VINUM)
|
||||
_vinum= vinum
|
||||
.endif
|
||||
|
||||
.if ${MACHINE_ARCH} == "i386"
|
||||
.if ${MACHINE} == "i386"
|
||||
_fdisk= fdisk
|
||||
|
@ -1,15 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
PROG= vinum
|
||||
SRCS= v.c list.c vinumparser.c vinumutil.c vext.h commands.c
|
||||
MAN= vinum.8
|
||||
|
||||
CFLAGS+= -I${.CURDIR}/../../sys
|
||||
WARNS?= 0
|
||||
|
||||
DPADD= ${LIBREADLINE} ${LIBTERMCAP} ${LIBDEVSTAT} ${LIBKVM}
|
||||
LDADD= -lreadline -ltermcap -ldevstat -lkvm
|
||||
|
||||
.PATH: ${.CURDIR}/../../sys/dev/vinum
|
||||
|
||||
.include <bsd.prog.mk>
|
File diff suppressed because it is too large
Load Diff
1502
sbin/vinum/list.c
1502
sbin/vinum/list.c
File diff suppressed because it is too large
Load Diff
685
sbin/vinum/v.c
685
sbin/vinum/v.c
@ -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);
|
||||
}
|
||||
}
|
@ -1,218 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1997, 1998
|
||||
* Nan Yang Computer Services Limited. All rights reserved.
|
||||
*
|
||||
* 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: vext.h,v 1.22 2003/04/28 06:19:06 grog Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#define MAXARGS 64 /* maximum number of args on a line */
|
||||
#define PLEXINITSIZE 65536 /* init in this size chunks */
|
||||
#define MAXPLEXINITSIZE 65536 /* max chunk size to use for init */
|
||||
#define MAXDATETEXT 128 /* date text in history (far too much) */
|
||||
#define VINUMDEBUG /* for including kernel headers */
|
||||
|
||||
enum {
|
||||
KILOBYTE = 1024,
|
||||
MEGABYTE = 1048576,
|
||||
GIGABYTE = 1073741824
|
||||
};
|
||||
|
||||
#define VINUMMOD "vinum"
|
||||
|
||||
#define DEFAULT_HISTORYFILE "/var/log/vinum_history" /* default name for history stuff */
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <sys/param.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <grp.h>
|
||||
#include <netdb.h>
|
||||
#include <paths.h>
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/linker.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/resource.h>
|
||||
#include <readline/history.h>
|
||||
#include <readline/readline.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/bio.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/namei.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/queue.h>
|
||||
#include <stdarg.h>
|
||||
#include <vm/vm.h>
|
||||
#include <dev/vinum/vinumvar.h>
|
||||
#include <dev/vinum/vinumio.h>
|
||||
#include <dev/vinum/vinumkw.h>
|
||||
#include <dev/vinum/vinumutil.h>
|
||||
#include <machine/cpu.h>
|
||||
|
||||
/* Prototype declarations */
|
||||
void parseline(int c, char *args[]); /* parse a line with c parameters at args */
|
||||
void checkentry(int index);
|
||||
int haveargs(int); /* check arg, error message if not valid */
|
||||
void setsigs(void);
|
||||
void catchsig(int ignore);
|
||||
void vinum_create(int argc, char *argv[], char *arg0[]);
|
||||
void vinum_read(int argc, char *argv[], char *arg0[]);
|
||||
void vinum_modify(int argc, char *argv[], char *arg0[]);
|
||||
void vinum_volume(int argc, char *argv[], char *arg0[]);
|
||||
void vinum_plex(int argc, char *argv[], char *arg0[]);
|
||||
void vinum_sd(int argc, char *argv[], char *arg0[]);
|
||||
void vinum_drive(int argc, char *argv[], char *arg0[]);
|
||||
void vinum_list(int argc, char *argv[], char *arg0[]);
|
||||
void vinum_info(int argc, char *argv[], char *arg0[]);
|
||||
void vinum_set(int argc, char *argv[], char *arg0[]);
|
||||
void vinum_rm(int argc, char *argv[], char *arg0[]);
|
||||
void vinum_mv(int argc, char *argv[], char *arg0[]);
|
||||
void vinum_init(int argc, char *argv[], char *arg0[]);
|
||||
void listconfig(void);
|
||||
void resetstats(struct vinum_ioctl_msg *msg);
|
||||
void initvol(int volno);
|
||||
void initplex(int plexno, char *name);
|
||||
void initsd(int sdno, int dowait);
|
||||
void vinum_resetconfig(int argc, char *argv[], char *arg0[]);
|
||||
void vinum_start(int argc, char *argv[], char *arg0[]);
|
||||
void continue_revive(int plexno);
|
||||
void vinum_stop(int argc, char *argv[], char *arg0[]);
|
||||
void vinum_makedev(int argc, char *argv[], char *arg0[]);
|
||||
void vinum_help(int argc, char *argv[], char *arg0[]);
|
||||
void vinum_quit(int argc, char *argv[], char *arg0[]);
|
||||
void vinum_setdaemon(int argc, char *argv[], char *arg0[]);
|
||||
void vinum_replace(int argc, char *argv[], char *arg0[]);
|
||||
void vinum_readpol(int argc, char *argv[], char *arg0[]);
|
||||
void reset_volume_stats(int volno, int recurse);
|
||||
void reset_plex_stats(int plexno, int recurse);
|
||||
void reset_sd_stats(int sdno, int recurse);
|
||||
void reset_drive_stats(int driveno);
|
||||
void vinum_resetstats(int argc, char *argv[], char *arg0[]);
|
||||
void vinum_attach(int argc, char *argv[], char *argv0[]);
|
||||
void vinum_detach(int argc, char *argv[], char *argv0[]);
|
||||
void vinum_rename(int argc, char *argv[], char *argv0[]);
|
||||
void vinum_rename_2(char *, char *);
|
||||
void vinum_replace(int argc, char *argv[], char *argv0[]);
|
||||
void vinum_printconfig(int argc, char *argv[], char *argv0[]);
|
||||
void printconfig(FILE * of, char *comment);
|
||||
void vinum_saveconfig(int argc, char *argv[], char *argv0[]);
|
||||
int checkupdates(void);
|
||||
void genvolname(void);
|
||||
struct _drive *create_drive(char *devicename);
|
||||
void vinum_concat(int argc, char *argv[], char *argv0[]);
|
||||
void vinum_stripe(int argc, char *argv[], char *argv0[]);
|
||||
void vinum_raid4(int argc, char *argv[], char *argv0[]);
|
||||
void vinum_raid5(int argc, char *argv[], char *argv0[]);
|
||||
void vinum_mirror(int argc, char *argv[], char *argv0[]);
|
||||
void vinum_label(int argc, char *argv[], char *arg0[]);
|
||||
void vinum_ld(int argc, char *argv[], char *arg0[]);
|
||||
void vinum_ls(int argc, char *argv[], char *arg0[]);
|
||||
void vinum_lp(int argc, char *argv[], char *arg0[]);
|
||||
void vinum_lv(int argc, char *argv[], char *arg0[]);
|
||||
void vinum_setstate(int argc, char *argv[], char *argv0[]);
|
||||
void vinum_checkparity(int argc, char *argv[], char *argv0[]);
|
||||
void vinum_rebuildparity(int argc, char *argv[], char *argv0[]);
|
||||
void parityops(int argc, char *argv[], enum parityop op);
|
||||
void start_daemon(void);
|
||||
void vinum_debug(int argc, char *argv[], char *arg0[]);
|
||||
void list_defective_objects(void);
|
||||
void vinum_dumpconfig(int argc, char *argv[], char *argv0[]);
|
||||
void dumpconfig(char *part);
|
||||
int check_drive(char *devicename);
|
||||
void get_drive_info(struct _drive *drive, int index);
|
||||
void get_sd_info(struct _sd *sd, int index);
|
||||
void get_plex_sd_info(struct _sd *sd, int plexno, int sdno);
|
||||
void get_plex_info(struct _plex *plex, int index);
|
||||
void get_volume_info(struct _volume *volume, int index);
|
||||
struct _drive *find_drive_by_devname(char *name);
|
||||
int find_object(const char *name, enum objecttype *type);
|
||||
char *lltoa(int64_t l, char *s);
|
||||
void vinum_ldi(int, int);
|
||||
void vinum_lvi(int, int);
|
||||
void vinum_lpi(int, int);
|
||||
void vinum_lsi(int, int);
|
||||
int vinum_li(int object, enum objecttype type);
|
||||
char *roughlength(int64_t bytes, int);
|
||||
u_int64_t sizespec(char *spec);
|
||||
char *sd_state(enum sdstate);
|
||||
void timestamp(void);
|
||||
|
||||
extern int force; /* set to 1 to force some dangerous ops */
|
||||
extern int interval; /* interval in ms between init/revive */
|
||||
extern int vflag; /* set verbose operation or verify */
|
||||
extern int Verbose; /* very verbose operation */
|
||||
extern int recurse; /* set recursion */
|
||||
extern int sflag; /* show statistics */
|
||||
extern int SSize; /* sector size for revive */
|
||||
extern int dowait; /* wait for children to exit */
|
||||
extern char *objectname; /* name for some functions */
|
||||
|
||||
extern FILE *History; /* history file */
|
||||
|
||||
/* Structures to read kernel data into */
|
||||
extern struct __vinum_conf vinum_conf; /* configuration information */
|
||||
|
||||
extern struct _volume vol;
|
||||
extern struct _plex plex;
|
||||
extern struct _sd sd;
|
||||
extern struct _drive drive;
|
||||
|
||||
extern jmp_buf command_fail; /* return on a failed command */
|
||||
extern int superdev; /* vinum super device */
|
||||
|
||||
extern int line; /* stdin line number for error messages */
|
||||
extern int file_line; /* and line in input file (yes, this is tacky) */
|
||||
|
||||
extern char buffer[]; /* buffer to read in to */
|
||||
|
||||
#define min(a, b) a < b? a: b
|
2925
sbin/vinum/vinum.8
2925
sbin/vinum/vinum.8
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user