summaryrefslogtreecommitdiffstats
path: root/sbin
diff options
context:
space:
mode:
authorgrog <grog@FreeBSD.org>1999-01-21 00:45:11 +0000
committergrog <grog@FreeBSD.org>1999-01-21 00:45:11 +0000
commit216db4f79fa887ba32a505a17247f046b78b1f2c (patch)
tree049722e836280dfcdf4501d1ea87746697ffe79e /sbin
parent295e173f284e3b4b94e3f172bb8b0feac7169c31 (diff)
downloadFreeBSD-src-216db4f79fa887ba32a505a17247f046b78b1f2c.zip
FreeBSD-src-216db4f79fa887ba32a505a17247f046b78b1f2c.tar.gz
Update to reflect major changes in vinum kernel module
Diffstat (limited to 'sbin')
-rw-r--r--sbin/vinum/list.c111
-rw-r--r--sbin/vinum/v.c110
-rw-r--r--sbin/vinum/vext.h50
-rw-r--r--sbin/vinum/vinum.8291
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 *) &region;
-
- 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, &region) < 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, &region) < 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
OpenPOWER on IntegriCloud