diff options
author | grog <grog@FreeBSD.org> | 1999-01-21 00:45:11 +0000 |
---|---|---|
committer | grog <grog@FreeBSD.org> | 1999-01-21 00:45:11 +0000 |
commit | 216db4f79fa887ba32a505a17247f046b78b1f2c (patch) | |
tree | 049722e836280dfcdf4501d1ea87746697ffe79e | |
parent | 295e173f284e3b4b94e3f172bb8b0feac7169c31 (diff) | |
download | FreeBSD-src-216db4f79fa887ba32a505a17247f046b78b1f2c.zip FreeBSD-src-216db4f79fa887ba32a505a17247f046b78b1f2c.tar.gz |
Update to reflect major changes in vinum kernel module
-rw-r--r-- | sbin/vinum/list.c | 111 | ||||
-rw-r--r-- | sbin/vinum/v.c | 110 | ||||
-rw-r--r-- | sbin/vinum/vext.h | 50 | ||||
-rw-r--r-- | sbin/vinum/vinum.8 | 291 |
4 files changed, 431 insertions, 131 deletions
diff --git a/sbin/vinum/list.c b/sbin/vinum/list.c index 44dcc2f..94f117c 100644 --- a/sbin/vinum/list.c +++ b/sbin/vinum/list.c @@ -35,7 +35,7 @@ * otherwise) arising in any way out of the use of this software, even if * advised of the possibility of such damage. * - * $Id: list.c,v 1.6 1998/12/28 16:32:39 peter Exp $ + * $Id: list.c,v 1.17 1999/01/17 02:58:44 grog Exp grog $ */ #include <ctype.h> @@ -350,56 +350,6 @@ vinum_lpi(int plexno, int recurse) get_volume_info(&vol, plex.volno); printf("\t\tPart of volume %s\n", vol.name); } - if (plex.state == plex_reviving) { - printf("\t\tRevive pointer:\t\t%s (%d%%)\n", - roughlength(plex.revived << DEV_BSHIFT, 0), - (int) (((u_int64_t) (plex.revived * 100)) / plex.length)); - printf("\t\tRevive blocksize:\t%s\n" - "\t\tRevive interval:\t%10d seconds\n", - roughlength(plex.revive_blocksize, 0), - plex.revive_interval); - } - if (Verbose) { /* show the unmapped and defective parts */ - int re; /* freelist entry */ - struct plexregion region; - struct rerq { /* request to pass to ioctl */ - int plexno; /* plex for the request */ - int re; /* region */ - } *rerq = (struct rerq *) ®ion; - - if (plex.unmapped_regions) { - printf("\t\tPlex contains %d unmapped regions:\n\t\t Offset\t Size\n", - plex.unmapped_regions); - for (re = 0; re < plex.unmapped_regions; re++) { - rerq->plexno = plex.plexno; - rerq->re = re; - if (ioctl(superdev, VINUM_GETUNMAPPED, ®ion) < 0) { - fprintf(stderr, - "Can't get unmapped region %d: %s\n", - re, - strerror(errno)); - longjmp(command_fail, -1); - } - printf("\t\t%9qd\t%9qd\n", region.offset, region.length); - } - } - if (plex.defective_regions) { - printf("\t\tPlex contains %d defective regions:\n\t\t Offset\t Size\n", - plex.defective_regions); - for (re = 0; re < plex.defective_regions; re++) { - rerq->plexno = plex.plexno; - rerq->re = re; - if (ioctl(superdev, VINUM_GETDEFECTIVE, ®ion) < 0) { - fprintf(stderr, - "Can't get defective region %d: %s\n", - re, - strerror(errno)); - longjmp(command_fail, -1); - } - printf("\t\t%9qd\t%9qd\n", region.offset, region.length); - } - } - } } else { char *org = ""; /* organization */ @@ -438,12 +388,15 @@ vinum_lpi(int plexno, int recurse) if (plex.writes != 0) printf("\t\tAverage write:\t%16qd bytes\n", plex.bytes_written / plex.writes); - if ((plex.organization == plex_striped) - || (plex.organization == plex_raid5)) - printf("\t\tMultiblock:\t%16qd\n" - "\t\tMultistripe:\t%16qd\n", + if (((plex.reads + plex.writes) > 0) + && ((plex.organization == plex_striped) + || (plex.organization == plex_raid5))) + printf("\t\tMultiblock:\t%16qd (%d%%)\n" + "\t\tMultistripe:\t%16qd (%d%%)\n", plex.multiblock, - plex.multistripe); + (int) (plex.multiblock * 100 / (plex.reads + plex.writes)), + plex.multistripe, + (int) (plex.multistripe * 100 / (plex.reads + plex.writes))); } if (plex.subdisks > 0) { int sdno; @@ -512,10 +465,16 @@ vinum_lsi(int sdno, int recurse) if (sd.plexno >= 0) { get_plex_info(&plex, sd.plexno); printf("\t\tPlex %s", plex.name); - if (plex.organization == plex_concat) - printf(" at offset %qd\n", (long long) sd.plexoffset * DEV_BSIZE); - else - printf("\n"); + printf(" at offset %qd\n", (long long) sd.plexoffset * DEV_BSIZE); + } + if (sd.state == sd_reviving) { + printf("\t\tRevive pointer:\t\t%s (%d%%)\n", + roughlength(sd.revived << DEV_BSHIFT, 0), + (int) (((u_int64_t) (sd.revived * 100)) / sd.sectors)); + printf("\t\tRevive blocksize:\t%s\n" + "\t\tRevive interval:\t%10d seconds\n", + roughlength(sd.revive_blocksize, 0), + sd.revive_interval); } } else { printf("S %-21s State: %s\tPO: %s ", @@ -633,7 +592,7 @@ vinum_info(int argc, char *argv[], char *argv0[]) #if VINUMDEBUG struct rqinfo rq; #endif - + if (ioctl(superdev, VINUM_GETCONFIG, &vinum_conf) < 0) { perror("Can't get vinum config"); return; @@ -668,7 +627,7 @@ vinum_info(int argc, char *argv[], char *argv0[]) } #if VINUMDEBUG if (Verbose) { - printf("\nTime\t\t Event\t Buf\tSD\tDev\tOffset\tBytes\tDoffset\tGoffset\n\n"); + printf("\nTime\t\t Event\t Buf\tDev\tOffset\t\tBytes\tSD\tSDoff\tDoffset\tGoffset\n\n"); for (i = RQINFO_SIZE - 1; i >= 0; i--) { /* go through the request list in order */ *((int *) &rq) = i; if (ioctl(superdev, VINUM_RQINFO, &rq) < 0) { @@ -680,75 +639,77 @@ vinum_info(int argc, char *argv[], char *argv0[]) break; case loginfo_user_bp: /* this is the bp when strategy is called */ - printf("%s 1VS %s %p\t\t0x%x\t0x%x\t%ld\n", + printf("%s 1VS %s %p\t0x%x\t0x%-9x\t%ld\n", timetext(&rq.timestamp), rq.info.b.b_flags & B_READ ? "Read " : "Write", rq.bp, - /* no subdisk */ rq.info.b.b_dev, rq.info.b.b_blkno, rq.info.b.b_bcount); break; case loginfo_user_bpl: /* and this is the bp at launch time */ - printf("%s 2LR %s %p\t\t0x%x\t0x%x\t%ld\n", + printf("%s 2LR %s %p\t0x%x\t0x%-9x\t%ld\n", timetext(&rq.timestamp), rq.info.b.b_flags & B_READ ? "Read " : "Write", rq.bp, - /* no subdisk */ rq.info.b.b_dev, rq.info.b.b_blkno, rq.info.b.b_bcount); break; case loginfo_rqe: /* user RQE */ - printf("%s 3RQ %s %p\t%d\t0x%x\t0x%x\t%ld\t%x\t%x\n", + printf("%s 3RQ %s %p\t0x%x\t0x%-9x\t%ld\t%d\t%x\t%x\t%x\n", timetext(&rq.timestamp), rq.info.rqe.b.b_flags & B_READ ? "Read " : "Write", rq.bp, - rq.info.rqe.sdno, rq.info.rqe.b.b_dev, rq.info.rqe.b.b_blkno, rq.info.rqe.b.b_bcount, + rq.info.rqe.sdno, + rq.info.rqe.sdoffset, rq.info.rqe.dataoffset, rq.info.rqe.groupoffset); break; case loginfo_iodone: /* iodone called */ - printf("%s 4DN %s %p\t%d\t0x%x\t0x%x\t%ld\t%x\t%x\n", + printf("%s 4DN %s %p\t0x%x\t0x%-9x\t%ld\t%d\t%x\t%x\t%x\n", timetext(&rq.timestamp), rq.info.rqe.b.b_flags & B_READ ? "Read " : "Write", rq.bp, - rq.info.rqe.sdno, rq.info.rqe.b.b_dev, rq.info.rqe.b.b_blkno, rq.info.rqe.b.b_bcount, + rq.info.rqe.sdno, + rq.info.rqe.sdoffset, rq.info.rqe.dataoffset, rq.info.rqe.groupoffset); break; case loginfo_raid5_data: /* RAID-5 write data block */ - printf("%s 5RD %s %p\t%d\t0x%x\t0x%x\t%ld\t%x\t%x\n", + printf("%s 5RD %s %p\t0x%x\t0x%-9x\t%ld\t%d\t%x\t%x\t%x\n", timetext(&rq.timestamp), rq.info.rqe.b.b_flags & B_READ ? "Read " : "Write", rq.bp, - rq.info.rqe.sdno, rq.info.rqe.b.b_dev, rq.info.rqe.b.b_blkno, rq.info.rqe.b.b_bcount, + rq.info.rqe.sdno, + rq.info.rqe.sdoffset, rq.info.rqe.dataoffset, rq.info.rqe.groupoffset); break; case loginfo_raid5_parity: /* RAID-5 write parity block */ - printf("%s 6RP %s %p\t%d\t0x%x\t0x%x\t%ld\t%x\t%x\n", + printf("%s 6RP %s %p\t0x%x\t0x%-9x\t%ld\t%d\t%x\t%x\t%x\n", timetext(&rq.timestamp), rq.info.rqe.b.b_flags & B_READ ? "Read " : "Write", rq.bp, - rq.info.rqe.sdno, rq.info.rqe.b.b_dev, rq.info.rqe.b.b_blkno, rq.info.rqe.b.b_bcount, + rq.info.rqe.sdno, + rq.info.rqe.sdoffset, rq.info.rqe.dataoffset, rq.info.rqe.groupoffset); } @@ -820,7 +781,7 @@ vinum_printconfig(int argc, char *argv[], char *argv0[]) plex_state(plex.state), plex_org(plex.organization)); if ((plex.organization == plex_striped) - ) { + || (plex.organization == plex_raid5)) { fprintf(of, "%db ", (int) plex.stripesize); } if (plex.volno >= 0) { /* we have a volume */ diff --git a/sbin/vinum/v.c b/sbin/vinum/v.c index a248b9e..d9a11f2 100644 --- a/sbin/vinum/v.c +++ b/sbin/vinum/v.c @@ -36,7 +36,7 @@ * */ -/* $Id: v.c,v 1.2 1998/12/28 16:32:39 peter Exp $ */ +/* $Id: v.c,v 1.24 1999/01/17 02:53:38 grog Exp grog $ */ #include <ctype.h> #include <errno.h> @@ -57,6 +57,9 @@ #include <sys/wait.h> #include <readline/history.h> #include <readline/readline.h> +#include <sys/linker.h> +#include <sys/module.h> +#include <sys/resource.h> FILE *cf; /* config file handle */ @@ -88,6 +91,8 @@ struct drive drive; jmp_buf command_fail; /* return on a failed command */ int superdev; /* vinum super device */ +void start_daemon(void); + #define ofs(x) ((void *) (& ((struct confdata *) 0)->x)) /* offset of x in struct confdata */ /* create description-file @@ -112,6 +117,20 @@ int tokens; /* number of tokens */ int main(int argc, char *argv[]) { +#if RAID5 +#define VINUMMOD "Vinum" +#else +#define VINUMMOD "vinum" +#endif + + if (modfind(VINUMMOD) < 0) { + /* need to load the vinum module */ + if (kldload(VINUMMOD) < 0 || modfind(VINUMMOD) < 0) { + perror("vinum kernel module not available"); + return 1; + } + } + superdev = open(VINUM_SUPERDEV_NAME, O_RDWR); /* open it */ if (superdev < 0) { /* no go */ @@ -122,6 +141,10 @@ main(int argc, char *argv[]) return 1; } } + /* Check if the dæmon is running. If not, start it in the + * background */ + start_daemon(); + if (argc > 1) { /* we have a command on the line */ if (setjmp(command_fail) != 0) /* long jumped out */ return -1; @@ -156,6 +179,13 @@ main(int argc, char *argv[]) return 0; /* normal completion */ } +/* stop the hard way */ +void +vinum_quit(int argc, char *argv[], char *argv0[]) +{ + exit(0); +} + #define FUNKEY(x) { kw_##x, &vinum_##x } /* create pair "kw_foo", vinum_foo */ struct funkey { @@ -191,6 +221,10 @@ struct funkey { FUNKEY(printconfig), FUNKEY(start), FUNKEY(stop), + FUNKEY(makedev), + FUNKEY(help), + FUNKEY(quit), + FUNKEY(setdaemon), FUNKEY(resetstats) }; @@ -348,6 +382,7 @@ make_devices(void) system("mkdir -p " VINUM_DIR "/drive " /* and make them again */ VINUM_DIR "/plex " VINUM_DIR "/sd " + VINUM_DIR "/rsd " VINUM_DIR "/vol " VINUM_DIR "/rvol " VINUM_RDIR); @@ -440,10 +475,16 @@ make_devices(void) if (mknod(filename, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IFBLK, sddev) < 0) fprintf(stderr, "Can't create %s: %s\n", filename, strerror(errno)); - /* And /dev/vinum/sd/<sd> */ + /* /dev/vinum/sd/<sd> */ sprintf(filename, VINUM_DIR "/sd/%s", sd.name); if (mknod(filename, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IFBLK, sddev) < 0) fprintf(stderr, "Can't create %s: %s\n", filename, strerror(errno)); + + /* And /dev/vinum/rsd/<sd> */ + sprintf(filename, VINUM_DIR "/rsd/%s", sd.name); + sddev = VINUMCDEV(volno, plexno, sdno, VINUM_SD_TYPE); + if (mknod(filename, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IFCHR, sddev) < 0) + fprintf(stderr, "Can't create %s: %s\n", filename, strerror(errno)); } } } @@ -461,6 +502,13 @@ make_devices(void) } } +/* command line interface for the 'makedev' command */ +void +vinum_makedev(int argc, char *argv[], char *arg0[]) +{ + make_devices(); +} + /* Find the object "name". Return object type at type, * and the index as the return value. * If not found, return -1 and invalid_object. @@ -516,13 +564,13 @@ find_object(const char *name, enum objecttype *type) return -1; } -/* Continue reviving a plex in the background */ +/* Continue reviving a subdisk in the background */ void -continue_revive(int plexno) +continue_revive(int sdno) { - struct plex plex; + struct sd sd; pid_t pid; - get_plex_info(&plex, plexno); + get_sd_info(&sd, sdno); #if VINUMDEBUG if (debug) @@ -537,27 +585,59 @@ continue_revive(int plexno) struct vinum_ioctl_msg *message = (struct vinum_ioctl_msg *) &reply; openlog("vinum", LOG_CONS | LOG_PERROR | LOG_PID, LOG_KERN); - syslog(LOG_INFO | LOG_KERN, "reviving plex %s", plex.name); + syslog(LOG_INFO | LOG_KERN, "reviving %s", sd.name); for (reply.error = EAGAIN; reply.error == EAGAIN;) { - message->index = plexno; /* pass plex number */ - message->type = plex_object; /* and type of object */ + message->index = sdno; /* pass sd number */ + message->type = sd_object; /* and type of object */ message->state = object_up; ioctl(superdev, VINUM_SETSTATE, message); } if (reply.error) { syslog(LOG_ERR | LOG_KERN, - "can't revive plex %s: %s", - plex.name, + "can't revive %s: %s", + sd.name, reply.msg[0] ? reply.msg : strerror(reply.error)); exit(1); } else { - get_plex_info(&plex, plexno); /* update the info */ - syslog(LOG_INFO | LOG_KERN, "plex %s is %s", plex.name, plex_state(plex.state)); + get_sd_info(&sd, sdno); /* update the info */ + syslog(LOG_INFO | LOG_KERN, "%s is %s", sd.name, sd_state(sd.state)); exit(0); } } else if (pid < 0) /* couldn't fork? */ - fprintf(stderr, "Can't continue reviving %s: %s\n", plex.name, strerror(errno)); + fprintf(stderr, "Can't continue reviving %s: %s\n", sd.name, strerror(errno)); else - printf("Reviving %s in the background\n", plex.name); + 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 */ + 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("Vinum daemon"); /* show what we're doing */ + status = ioctl(superdev, VINUM_FINDDAEMON, NULL); + if (status != 0) { /* no daemon, */ + ioctl(superdev, VINUM_DAEMON, &verbose); /* 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"); } diff --git a/sbin/vinum/vext.h b/sbin/vinum/vext.h index 84a3e21..a446f84 100644 --- a/sbin/vinum/vext.h +++ b/sbin/vinum/vext.h @@ -1,6 +1,9 @@ -/* - * Copyright (c) 1997 Nan Yang Computer Services Limited - * All rights reserved. +/*- + * 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 @@ -12,28 +15,30 @@ * 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 for the NetBSD Project - * by Jason R. Thorpe. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. + * 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. * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.1.1.1 1998/09/16 05:57:36 grog Exp $ */ +/* $Id: vext.h,v 1.10 1999/01/12 04:31:45 grog Exp grog $ */ #define MAXARGS 64 /* maximum number of args on a line */ -#define PLEXINITSIZE MAXPHYS /* block size to write when initializing */ +#define PLEXINITSIZE 61440 /* this is what the system does somewhere */ enum { KILOBYTE = 1024, @@ -61,6 +66,10 @@ 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 reset_volume_stats(int volno, int recurse); void reset_plex_stats(int plexno, int recurse); void reset_sd_stats(int sdno, int recurse); @@ -77,6 +86,7 @@ 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 start_daemon(void); #ifdef VINUMDEBUG void vinum_debug(int argc, char *argv[], char *arg0[]); #endif diff --git a/sbin/vinum/vinum.8 b/sbin/vinum/vinum.8 index fcf35ad..d2dfdb6 100644 --- a/sbin/vinum/vinum.8 +++ b/sbin/vinum/vinum.8 @@ -1,6 +1,6 @@ .\" Hey, Emacs, edit this file in -*- nroff-fill -*- mode .\" -.Dd 11 July 1998 +.Dd 15 January 1999 .Dt vinum 8 .Os FreeBSD .Sh NAME @@ -30,9 +30,14 @@ Attach a plex to a volume, or a subdisk to a plex. .in +1i Cause the volume manager to enter the kernel debugger. .in +.Cd debug +.Ar flags +.in +1i +Set debugging flags. +.in .Cd detach .Op Ar plex | subdisk -.in +1 +.in +1i Detach a plex or subdisk from the volume or plex to which it is attached. .in .Cd info @@ -112,12 +117,21 @@ List information about volumes Remake the device nodes in .Ar /dev/vinum . .in +.Cd quit +.in +1i +Exit the +.Nm +program when running in interactive mode. Normally this would be done by +entering the +.Ar EOF +character. +.in .Cd read -.Ar disk-partition +.Ar disk Op disk... .in +1i Read the .Nm -configuration from the specified disk partition. +configuration from the specified disks. .in .Cd rename Op Fl r .Ar [ drive | subdisk | plex | volume ] @@ -164,6 +178,11 @@ XXX Set the state of the object to \fIstate\fP\| .in .. +.Cd setdaemon +.Op value +.in +1i +Set dæmon configuration. +.in .Cd start .Op volume | plex | subdisk .in +1i @@ -184,7 +203,10 @@ for more information about the volume manager. .Xr vinum 8 is designed either for interactive use, when started without a command, or to execute a single command if the command is supplied as arguments to -.Nm vinum. +.Nm vinum . +In interactive mode, +.Nm +maintains a command line history. .Ss OPTIONS .Nm commands may optionally be followed by an option. Any of the following options @@ -245,7 +267,8 @@ commands perform the following functions: .Bl -hang .It Nm attach Ar plex Ar volume .Op Nm rename -.sp -1v +.if n .sp -1v +.if t .sp -.6v .It Nm attach Ar subdisk Ar plex Ar [offset] .Op Nm rename .sp @@ -300,13 +323,49 @@ CONFIGURATION FILE below for more information. .Ar debug is used to enter the remote kernel debugger. It is only activated if .Nm -is built with the DEBUG option. This option will stop the execution of the -operating system until the kernel debugger is exited. If there is no remote +is built with the +.Ar VINUMDEBUG +option. This option will stop the execution of the operating system until the +kernel debugger is exited. If remote debugging is set and there is no remote connection for a kernel debugger, it will be necessary to reset the system and reboot in order to leave the debugger. +.It Nm debug +.Ar flags +.Pp +Set a bit mask of internal debugging flags. These will change without warning +as the product matures; to be certain, read the header file +.Pa sys/dev/vinumvar.h . +The bit mask is composed of the following values: +.Bl -hang +.It DEBUG_ADDRESSES (1) +.br +Show buffer information during requests +.It DEBUG_NUMOUTPUT (2) +.br +Show the value of +.Dv vp->v_numoutput. +.It DEBUG_RESID (4) +.br +Go into debugger in +.Fd complete_rqe. +.It DEBUG_LASTREQS (8) +.br +Keep a circular buffer of last requests. +.It DEBUG_REVIVECONFLICT (16) +.br +Print info about revive conflicts. +.It DEBUG_REMOTEGDB (256) +.br +Go into remote +.Ic gdb +when the +.Nm debug +command is issued. +.El .It Nm detach Op Fl f .Ar plex -.sp -1v +.if n .sp -1v +.if t .sp -.6v .It Nm detach Op Fl f .Ar subdisk .sp @@ -327,7 +386,7 @@ the subdisk is marked absent, and can later be replaced with the .Nm attach command. .It Nm info -.Pp +.br .Nm .Ar info displays information about @@ -335,6 +394,117 @@ displays information about memory usage. This is intended primarily for debugging. With the .Fl v option, it will give detailed information about the memory areas in use. +.Pp +With the +.Fl V +option, +.Ar info +displays information about the last up to 64 I/O requests handled by the +.Nm +driver. This information is only collected if debug flag 8 is set. The format +looks like: +.Pp +.Bd -literal +vinum -> info -V +Flags: 0x200 1 opens +Total of 38 blocks malloced, total memory: 16460 +Maximum allocs: 56, malloc table at 0xf0f72dbc + +Time Event Buf Dev Offset Bytes SD SDoff Doffset Goffset + +14:40:00.637758 1VS Write 0xf2361f40 0x5b03 0x10 16384 +14:40:00.639280 2LR Write 0xf2361f40 0x5b03 0x10 16384 +14:40:00.639294 3RQ Read 0xf2361f40 0x427 0x104109 8192 19 0 0 0 +14:40:00.639455 3RQ Read 0xf2361f40 0x417 0xd2109 8192 17 0 0 0 +14:40:00.639529 3RQ Read 0xf2361f40 0x40f 0x6e109 8192 16 0 0 0 +14:40:00.652978 4DN Read 0xf2361f40 0x427 0x104109 8192 19 0 0 0 +14:40:00.667040 4DN Read 0xf2361f40 0x40f 0x6e109 8192 16 0 0 0 +14:40:00.668556 4DN Read 0xf2361f40 0x417 0xd2109 8192 17 0 0 0 +14:40:00.669777 6RP Write 0xf2361f40 0x427 0x104109 8192 19 0 0 0 +14:40:00.685547 4DN Write 0xf2361f40 0x427 0x104109 8192 19 0 0 0 +.Ed +.Pp +The +.Ar Buf +field always contains the address of the user buffer header. This can be used +to identify the requests associated with a user request, though this is not 100% +reliable: theoretically two requests in sequence could use the same buffer +header, though this is not common. The beginning of a request can be identified +by the event +.Ar 1VS . +The example above shows the requests involved in a single user request. +.Pp +The +.Ar Event +field contains information related to the sequence of events in the request +chain. The digit +.Ar 1 +to +.Ar 6 +indicates the approximate sequence of events, and the two-letter abbreviation is +a mnemonic for the location +.Bl -hang +.It 1VS +(vinumstrategy) shows information about the user request on entry to +.Fd vinumstrategy . +The device number is the +.Nm +device, and offset and length are the user parameters. This is always the +beginning of a request sequence. +.It 2LR +(launch_requests) shows the user request just prior to launching the low-level +.Nm +requests in the function +.Fd launch_requests. +The parameters should be the same as in the +.Ar 1VS +information. +.Pp +In the following requests, +.Ar Dev +is the device number of the associated disk partition, +.Ar Offset +is the offset from the beginning of the partition, +.Ar SD +is the subdisk index in +.Dv vinum_conf , +.Ar SDoff +is the offset from the beginning of the subdisk, +.Ar Doffset +is the offset of the associated data request, and +.Ar Goffset +is the offset of the associated group request, where applicable. +.It 3RQ +(request) shows one of possibly several low-level +.Nm +requests which are launched to satisfy the high-level request. This information +is also logged in +.Fd launch_requests. +.It 4DN +(done) is called from +.Fd complete_rqe, +showing the completion of a request. This completion should match a request +launched either at stage +.Ar 4DN +from +.Fd launch_requests, +or from +.Fd complete_raid5_write +at stage +.Ar 5RD +or +.Ar 6RP . +.It 5RD +(RAID-5 data) is called from +.Fd complete_raid5_write +and represents the data written to a RAID-5 data stripe after calculating +parity. +.It 6RP +(RAID-5 parity) is called from +.Fd complete_raid5_write +and represents the data written to a RAID-5 parity stripe after calculating +parity. +.El .\" XXX .It Nm init Ar plex .Pp @@ -374,33 +544,38 @@ This command is deprecated. .Op Fl r .Op Fl V .Op volume | plex | subdisk -.sp -1 +.if n .sp -1v +.if t .sp -.6v .It Nm l .Op Fl r .Op Fl V .Op volume | plex | subdisk -.sp -1 +.if n .sp -1v +.if t .sp -.6v .It Nm ld .Op Fl r .Op Fl s .Op Fl v .Op Fl V .Op volume -.sp -1 +.if n .sp -1v +.if t .sp -.6v .It Nm ls .Op Fl r .Op Fl s .Op Fl v .Op Fl V .Op subdisk -.sp -1 +.if n .sp -1v +.if t .sp -.6v .It Nm lp .Op Fl r .Op Fl s .Op Fl v .Op Fl V .Op plex -.sp -1 +.if n .sp -1v +.if t .sp -.6v .It Nm lv .Op Fl r .Op Fl s @@ -447,18 +622,34 @@ command removes the directory /dev/vinum and recreates it with device nodes which reflect the current configuration. This command is not intended for general use, and is provided for emergency use only. .Pp +.It Nm quit +Exit the +.Nm +program when running in interactive mode. Normally this would be done by +entering the +.Ar EOF +character. .It Nm read -.Ar disk-partition +.Ar disk Op disk... .Pp The .Nm read -command reads a previously created -.Nm -configuration from the specified disk partition. +command scans the specified disks for +.Nm +partitions containing previously created configuration information. It reads +the configuration in order from the most recently updated to least recently +updated configuration. This is the normal method used to start +.Nm vinum . .Nm maintains an up-to-date copy of all configuration information on each disk -partition. You can specify any of the partitions in a configuration as the +partition. You must specify all of the partitions in a configuration as the parameter to this command. +.Nm +.Nm read +will accept the names of non-Vinum partitions, so you can specify all partitions +upon which a +.Nm +partition might be resident to this command. .It Nm rename .Op Fl r .Ar [ drive | subdisk | plex | volume ] @@ -568,6 +759,15 @@ care: it can result in total loss of data on a volume. .\"XXX .Nm This command has not yet been implemented. .. +.It Nm setdaemon +.Op value +.Pp +.Nm setdaemon +sets a variable bitmask for the +.Nm +dæmon. This command is temporary and will be replaced. Currently, the bit mask +may contain the bits 1 (log every action to syslog) and 4 (don't update +configuration). Option bit 4 can be useful for error recovery. .It Nm start .Op volume | plex | subdisk .Pp @@ -1019,14 +1219,62 @@ commands, though especially .Nm resetconfig outputs all sort of dire warnings. Don't use these commands unless you have a good reason to do so. +.It +Some state transitions are not very intuitive. In fact, it's not clear whether +this is a bug or a feature. If you find that you can't start an object in some +strange state, such as a +.Ar reborn +subdisk, try first to get it into +.Ar stopped +state, with the +.Nm stop +or +.Nm stop Ar -f +commands. If that works, you should then be able to start it. If you find +that this is the only way to get out of a position where easier methods fail, +please report the situation. +.It +If you build the kernel module with the +.Ar -DVINUMDEBUG +option, you must also build +.Nm vinum(8) +with the +.Ar -DVINUMDEBUG +option, since the size of some data objects used by both components depends on +this option. If you don't do so, commands will fail with the message +.Ar Invalid argument , +and a console message will be logged such as +.Pp +.Bd -literal +vinumioctl: invalid ioctl from process 247 (vinum): c0e44642 +.Ed +.Pp +This error may also occur if you use old versions of kld or userland program. .El .Sh BUGS +.Bl -enum +.It .Nm is currently in beta test. Many bugs can be expected. The configuration mechanism is not yet fully functional. If you have difficulties, please look at http://www.lemis.com/vinum_beta.html and http://www.lemis.com/vinum_debugging.html before reporting problems. -.Pp +.It +It is possible to unload +.Nm +with the +.Nm kldunload +command. This is buggy, and the only reason it is present at all is to make it +easier for people testing the system: the alternative is a reboot. It works +about 80% of the time: expect about one panic every five unloads. +.It +It is possible to configure +.Nm +statically, but it has never been tested in this form. Don't even bother to +report the problem if you have trouble with a static +.Nm +pseudo-device. +.It This man page tickles a bug in the .Ar doc man page macros: depending on your screen size, you may get the error message @@ -1037,6 +1285,7 @@ warning: page 6: table text block will not fit on one page This will be fixed in a later rewrite of the page, when the .Nm tbl macros will be removed. +.El .Sh FILES .Ar /dev/vinum - directory with device nodes for |