aboutsummaryrefslogtreecommitdiff
path: root/sbin/gvinum
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/gvinum')
-rw-r--r--sbin/gvinum/Makefile14
-rw-r--r--sbin/gvinum/Makefile.depend18
-rw-r--r--sbin/gvinum/gvinum.8460
-rw-r--r--sbin/gvinum/gvinum.c1450
-rw-r--r--sbin/gvinum/gvinum.h41
5 files changed, 0 insertions, 1983 deletions
diff --git a/sbin/gvinum/Makefile b/sbin/gvinum/Makefile
deleted file mode 100644
index 8ffabc694c31..000000000000
--- a/sbin/gvinum/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-
-PACKAGE=geom
-PROG= gvinum
-SRCS= gvinum.c gvinum.h geom_vinum_share.c
-MAN= gvinum.8
-
-WARNS?= 2
-CFLAGS+= -I${SRCTOP}/sys -I${SYSROOT:U${DESTDIR}}/${INCLUDEDIR}/edit
-
-LIBADD= edit geom
-
-.PATH: ${SRCTOP}/sys/geom/vinum
-
-.include <bsd.prog.mk>
diff --git a/sbin/gvinum/Makefile.depend b/sbin/gvinum/Makefile.depend
deleted file mode 100644
index 8d1c78126db9..000000000000
--- a/sbin/gvinum/Makefile.depend
+++ /dev/null
@@ -1,18 +0,0 @@
-# Autogenerated - do NOT edit!
-
-DIRDEPS = \
- include \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libcompiler_rt \
- lib/libedit \
- lib/libedit/readline \
- lib/libgeom \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/sbin/gvinum/gvinum.8 b/sbin/gvinum/gvinum.8
deleted file mode 100644
index 8bf2fcc92b8e..000000000000
--- a/sbin/gvinum/gvinum.8
+++ /dev/null
@@ -1,460 +0,0 @@
-.\" Copyright (c) 2005 Chris Jones
-.\" All rights reserved.
-.\"
-.\" This software was developed for the FreeBSD Project by Chris Jones
-.\" thanks to the support of Google's Summer of Code program and
-.\" mentoring by Lukas Ertl.
-.\"
-.\" 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.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``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 AUTHOR 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.
-.\"
-.Dd March 28, 2021
-.Dt GVINUM 8
-.Os
-.Sh NAME
-.Nm gvinum
-.Nd Logical Volume Manager control program
-.Sh DEPRECATION NOTICE
-.Nm
-and associated
-.Xr geom 4
-kernel support is deprecated, and may not be available in
-.Fx 14.0
-and later.
-Users are advised to migrate to
-.Xr gconcat 8 ,
-.Xr gmirror 8 ,
-.Xr gstripe 8 ,
-.Xr graid 8 ,
-or
-.Xr zfs 8 .
-More information is available at
-.Pa https://wiki.freebsd.org/DeprecationPlan/gvinum .
-.Sh SYNOPSIS
-.Nm
-.Op Ar command
-.Op Fl options
-.Sh COMMANDS
-.Bl -tag -width indent
-.It Ic attach Ar plex volume Op Cm rename
-.It Ic attach Ar subdisk plex Oo Ar offset Oc Op Cm rename
-Attach a plex to a volume, or a subdisk to a plex.
-If offset is specified, the subdisk will be attached to the given offset within
-the plex.
-If rename is specified, the subdisk or plex will change name according to the
-object it attaches to.
-.It Ic checkparity Oo Fl f Oc Ar plex
-Check the parity blocks of a RAID-5 plex.
-The parity check will start at the
-beginning of the plex if the
-.Fl f
-flag is specified, or otherwise at the location of the parity check pointer,
-the first location at which plex's parity is incorrect.
-All subdisks in the
-plex must be up for a parity check.
-.It Ic concat Oo Fl fv Oc Oo Fl n Ar name Oc Ar drives
-Create a concatenated volume from the specified drives.
-If no name is specified, a unique name will be set by
-.Ic gvinum .
-.It Ic create Oo Fl f Oc Op Ar description-file
-Create a volume as described in
-.Ar description-file .
-If no
-.Ar description-file
-provided, opens an editor and provides the current
-.Nm
-configuration for editing.
-The
-.Fl f
-flag will make gvinum ignore any errors regarding creating objects that already
-exists.
-However, in contrast to vinum, objects that are not properly named in the
-.Ar description-file
-will not be created when the
-.Fl f
-flag is given.
-.It Ic detach Oo Fl f Oc Op Ar plex | subdisk
-Detach a plex or subdisk from the volume or plex to which it is
-attached.
-.It Ic grow Ar plex device
-Grow a plex by creating a gvinum drive and subdisk on device and attach it to
-the plex.
-If required by the plex organization, it will be put into the growable state.
-.It Ic help
-Provides a synopsis of
-.Nm
-commands and arguments.
-.It Ic l | list Oo Fl rvV Oc Op Ar volume | plex | subdisk
-.It Ic ld Oo Fl rvV Oc Op Ar drive ...
-.It Ic ls Oo Fl rvV Oc Op Ar subdisk ...
-.It Ic lp Oo Fl rvV Oc Op Ar plex ...
-.It Ic lv Oo Fl rvV Oc Op Ar volume ...
-List information about the relevant object(s).
-The
-.Fl r
-flag provides recursive display, showing each object's subordinate objects in
-proper relation.
-The
-.Fl v
-and
-.Fl V
-flags provide progressively more detailed output.
-.It Ic mirror Oo Fl fsv Oc Oo Fl n Ar name Oc Ar drives
-Create a mirrored volume from the specified drives.
-It requires at least a multiple of 2 drives.
-If no name is specified, a unique name will be set by gvinum.
-If the
-.Fl s
-flag is specified, a striped mirror will be created, and thus requires a
-multiple of 4 drives.
-.It Ic move | mv Fl f Ar drive subdisk Op Ar ...
-Move the subdisk(s) to the specified drive.
-The
-.Fl f
-flag is required, as all data on the indicated subdisk(s) will be destroyed as
-part of the move.
-This can currently only be done when the subdisk is
-not being accessed.
-.Pp
-If a single subdisk is moved, and it forms a part of a RAID-5 plex, the moved
-subdisks will need to be set to the
-.Dq stale
-state, and the plex will require a
-.Ic start
-command.
-If multiple subdisk(s) is moved, and form part of a RAID-5 plex, the
-moved disk(s) will need to be set to the
-.Dq up
-state and the plex will require a
-.Ic rebuildparity
-command.
-If the subdisk(s) form part of a plex that is mirrored with other
-plexes, the plex will require restarting and will sync once restarted.
-Moving
-more than one subdisk in a RAID-5 plex or subdisks from both sides of a
-mirrored plex volume will destroy data.
-Note that parity rebuilds and syncing
-must be started manually after a move.
-.It Ic printconfig
-Write a copy of the current configuration to standard output.
-.It Ic quit
-Exit
-.Nm
-when running in interactive mode.
-Normally this would be done by entering the
-EOF character.
-.It Ic raid5 Oo Fl fv Oc Oo Fl s Ar stripesize Oc Oo Fl n Ar name Oc Ar drives
-Create a RAID-5 volume from the specified drives.
-If no name is specified, a unique name will be set by
-.Ic gvinum .
-This organization requires at least three drives.
-.It Ic rename Oo Fl r Oc Ar drive | subdisk | plex | volume newname
-Change the name of the specified object.
-The
-.Fl r
-flag will recursively rename subordinate objects.
-.Pp
-Note that device nodes will not be renamed until
-.Nm
-is restarted.
-.It Ic rebuildparity Oo Fl f Oc Ar plex
-Rebuild the parity blocks of a RAID-5 plex.
-The parity rebuild will start at
-the beginning of the plex if the
-.Fl f
-flag is specified, or otherwise at the location of the parity check pointer.
-All subdisks in the plex must be up for a parity check.
-.It Ic resetconfig Oo Fl f Oc
-Reset the complete
-.Nm
-configuration.
-.It Ic rm Oo Fl r Oc Ar volume | plex | subdisk
-Remove an object and, if
-.Fl r
-is specified, its subordinate objects.
-.It Ic saveconfig
-Save
-.Nm
-configuration to disk after configuration failures.
-.It Ic setstate Oo Fl f Oc Ar state volume | plex | subdisk | drive
-Set state without influencing other objects, for diagnostic purposes
-only.
-The
-.Fl f
-flag forces state changes regardless of whether they are legal.
-.It Ic start
-Read configuration from all vinum drives.
-.It Ic start Oo Fl S Ar size Oc Ar volume | plex | subdisk
-Allow the system to access the objects.
-If necessary, plexes will be synced and rebuilt.
-If a subdisk was added to a running RAID-5 or striped plex, gvinum will
-expand into this subdisk and grow the whole RAID-5 array.
-This can be done without unmounting your filesystem.
-The
-.Fl S
-flag is currently ignored.
-.It Ic stop Oo Fl f Oc Op Ar volume | plex | subdisk
-Terminate access to the objects, or stop
-.Nm
-if no parameters are specified.
-.It Ic stripe Oo Fl fv Oc Oo Fl n Ar name Oc Ar drives
-Create a striped volume from the specified drives.
-If no name is specified, a unique name will be set by
-.Ic gvinum .
-This organization requires at least two drives.
-.El
-.Sh DESCRIPTION
-The
-.Nm
-utility communicates with the kernel component of the GVinum logical volume
-manager.
-It is designed either for interactive use, when started without
-command line arguments, or to execute a single command if the command is
-supplied on the command line.
-In interactive mode,
-.Nm
-maintains a command line history.
-.Sh OPTIONS
-The
-.Nm
-commands may be followed by an option.
-.Bl -tag -width indent
-.It Fl f
-The
-.Fl f
-.Pq Dq force
-option overrides safety checks.
-It should be used with extreme caution.
-This
-option is required in order to use the
-.Ic move
-command.
-.It Fl r
-The
-.Fl r
-.Pq Dq recursive
-option applies the command recursively to subordinate objects.
-For example, in
-conjunction with the
-.Ic lv
-command, the
-.Fl r
-option will also show information about the plexes and subdisks belonging to
-the volume.
-It is also used by the
-.Ic rename
-command to indicate that subordinate objects such as subdisks should be renamed
-to match the object(s) specified and by the
-.Ic rm
-command to delete plexes belonging to a volume and so on.
-.It Fl v
-The
-.Fl v
-.Pq Dq verbose
-option provides more detailed output.
-.It Fl V
-The
-.Fl V
-.Pq Dq "very verbose"
-option provides even more detailed output than
-.Fl v .
-.El
-.Sh ENVIRONMENT
-.Bl -tag -width ".Ev EDITOR"
-.It Ev EDITOR
-The name of the editor to use for editing configuration files, by
-default
-.Xr vi 1
-is invoked.
-.El
-.Sh FILES
-.Bl -tag -width ".Pa /dev/gvinum/plex"
-.It Pa /dev/gvinum
-directory with device nodes for
-.Nm
-objects
-.El
-.Sh EXAMPLES
-To create a mirror on disks /dev/ada1 and /dev/ada2, create a filesystem,
-mount, unmount and then stop
-.Ic gvinum :
-.Pp
-.Dl "gvinum mirror /dev/ada1 /dev/ada2"
-.Dl "newfs /dev/gvinum/gvinumvolume0"
-.Dl "mount /dev/gvinum/gvinumvolume0 /mnt"
-.Dl "..."
-.Dl "unmount /mnt"
-.Dl "gvinum stop"
-.Pp
-To create a striped mirror on disks /dev/ada1 /dev/ada2 /dev/ada3 and
-/dev/ada4 named "data" and create a filesystem:
-.Pp
-.Dl "gvinum mirror -s -n data /dev/ada1 /dev/ada2 /dev/ada3 /dev/ada4"
-.Dl "newfs /dev/gvinum/data"
-.Pp
-To create a raid5 array on disks /dev/ada1 /dev/ada2 and /dev/ada3,
-with stripesize 493k you can use the raid5 command:
-.Pp
-.Dl "gvinum raid5 -s 493k /dev/ada1 /dev/ada2 /dev/ada3"
-.Pp
-Then the volume will be created automatically.
-Afterwards, you have to initialize the volume:
-.Pp
-.Dl "gvinum start myraid5vol"
-.Pp
-The initialization will start, and the states will be updated when it's
-finished.
-The list command will give you information about its progress.
-.Pp
-Imagine that one of the drives fails, and the output of 'printconfig' looks
-something like this:
-.Pp
-.Dl "drive gvinumdrive1 device /dev/ada2"
-.Dl "drive gvinumdrive2 device /dev/???"
-.Dl "drive gvinumdrive0 device /dev/ada1"
-.Dl "volume myraid5vol"
-.Dl "plex name myraid5vol.p0 org raid5 986s vol myraid5vol"
-.Dl "sd name myraid5vol.p0.s2 drive gvinumdrive2 len 32538s driveoffset 265s"
-.Dl "plex myraid5vol.p0 plexoffset 1972s"
-.Dl "sd name myraid5vol.p0.s1 drive gvinumdrive1 len 32538s driveoffset 265s"
-.Dl "plex myraid5vol.p0 plexoffset 986s"
-.Dl "sd name myraid5vol.p0.s0 drive gvinumdrive0 len 32538s driveoffset 265s"
-.Dl "plex myraid5vol.p0 plexoffset 0s"
-.Pp
-Create a new drive with this configuration:
-.Pp
-.Dl "drive gdrive4 device /dev/ada4"
-.Pp
-Then move the stale subdisk to the new drive:
-.Pp
-.Dl "gvinum move gdrive4 myraid5vol.p0.s2"
-.Pp
-Then, initiate the rebuild:
-.Pp
-.Dl "gvinum start myraid5vol.p0"
-.Pp
-The plex will go up form degraded mode after the rebuild is finished.
-The plex can still be used while the rebuild is in progress, although requests
-might be delayed.
-.Pp
-Given the configuration as in the previous example, growing a RAID-5 or STRIPED
-array is accomplished by using the grow command:
-.Pp
-.Dl "gvinum grow myraid5vol.p0 /dev/ada4"
-.Pp
-If everything went ok, the plex state should now be set to growable.
-You can then start the growing with the
-.Ic start
-command:
-.Pp
-.Dl "gvinum start myraid5vol.p0"
-.Pp
-As with rebuilding, you can watch the progress using the
-.Ic list
-command.
-.Pp
-For a more advanced usage and detailed explanation of gvinum, the
-handbook is recommended.
-.Sh SEE ALSO
-.Xr geom 4 ,
-.Xr geom 8
-.Sh HISTORY
-The
-.Nm
-utility first appeared in
-.Fx 5.3 .
-The
-.Nm vinum
-utility, on which
-.Nm
-is based, was written by
-.An "Greg Lehey" .
-.Pp
-The
-.Nm
-utility
-was written by
-.An "Lukas Ertl" .
-The
-.Ic move
-and
-.Ic rename
-commands and
-documentation were added by
-.An "Chris Jones"
-through the 2005 Google Summer
-of Code program.
-A partial rewrite of gvinum was done by
-.An "Lukas Ertl"
-and
-.An "Ulf Lilleengen"
-through the 2007 Google Summer of Code program.
-The documentation have been updated to reflect the new functionality.
-.Sh AUTHORS
-.An Lukas Ertl Aq Mt le@FreeBSD.org
-.An Chris Jones Aq Mt soc-cjones@FreeBSD.org
-.An Ulf Lilleengen Aq Mt lulf@FreeBSD.org
-.Sh BUGS
-Currently,
-.Nm
-does not rename devices in
-.Pa /dev/gvinum
-until reloaded.
-.Pp
-The
-.Fl S
-initsize flag to
-.Ic start
-is ignored.
-.Pp
-Moving subdisks that are not part of a mirrored or RAID-5 volume will
-destroy data.
-It is perhaps a bug to permit this.
-.Pp
-Plexes in which subdisks have been moved do not automatically sync or
-rebuild parity.
-This may leave data unprotected and is perhaps unwise.
-.Pp
-Currently,
-.Nm
-does not yet fully implement all of the functions found in
-.Nm vinum .
-Specifically, the following commands from
-.Nm vinum
-are not supported:
-.Bl -tag -width indent
-.It Ic debug
-Cause the volume manager to enter the kernel debugger.
-.It Ic debug Ar flags
-Set debugging flags.
-.It Ic dumpconfig Op Ar drive ...
-List the configuration information stored on the specified drives, or all
-drives in the system if no drive names are specified.
-.It Ic info Op Fl vV
-List information about volume manager state.
-.It Ic label Ar volume
-Create a volume label.
-.It Ic resetstats Oo Fl r Oc Op Ar volume | plex | subdisk
-Reset statistics counters for the specified objects, or for all objects if none
-are specified.
-.It Ic setdaemon Op Ar value
-Set daemon configuration.
-.El
diff --git a/sbin/gvinum/gvinum.c b/sbin/gvinum/gvinum.c
deleted file mode 100644
index c391f5d61c65..000000000000
--- a/sbin/gvinum/gvinum.c
+++ /dev/null
@@ -1,1450 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * Copyright (c) 2004 Lukas Ertl
- * Copyright (c) 2005 Chris Jones
- * Copyright (c) 2007 Ulf Lilleengen
- * All rights reserved.
- *
- * Portions of this software were developed for the FreeBSD Project
- * by Chris Jones thanks to the support of Google's Summer of Code
- * program and mentoring by Lukas Ertl.
- *
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``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 AUTHOR 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.
- */
-
-#include <sys/param.h>
-#include <sys/linker.h>
-#include <sys/lock.h>
-#include <sys/module.h>
-#include <sys/mutex.h>
-#include <sys/queue.h>
-#include <sys/utsname.h>
-
-#include <geom/vinum/geom_vinum_var.h>
-#include <geom/vinum/geom_vinum_share.h>
-
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <libgeom.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <paths.h>
-#include <readline/readline.h>
-#include <readline/history.h>
-#include <unistd.h>
-
-#include "gvinum.h"
-
-static void gvinum_attach(int, char * const *);
-static void gvinum_concat(int, char * const *);
-static void gvinum_create(int, char * const *);
-static void gvinum_detach(int, char * const *);
-static void gvinum_grow(int, char * const *);
-static void gvinum_help(void);
-static void gvinum_list(int, char * const *);
-static void gvinum_move(int, char * const *);
-static void gvinum_mirror(int, char * const *);
-static void gvinum_parityop(int, char * const * , int);
-static void gvinum_printconfig(int, char * const *);
-static void gvinum_raid5(int, char * const *);
-static void gvinum_rename(int, char * const *);
-static void gvinum_resetconfig(int, char * const *);
-static void gvinum_rm(int, char * const *);
-static void gvinum_saveconfig(void);
-static void gvinum_setstate(int, char * const *);
-static void gvinum_start(int, char * const *);
-static void gvinum_stop(int, char * const *);
-static void gvinum_stripe(int, char * const *);
-static void parseline(int, char * const *);
-static void printconfig(FILE *, const char *);
-
-static char *create_drive(const char *);
-static void create_volume(int, char * const * , const char *);
-static char *find_name(const char *, int, int);
-static const char *find_pattern(char *, const char *);
-static void copy_device(struct gv_drive *, const char *);
-#define find_drive() \
- find_name("gvinumdrive", GV_TYPE_DRIVE, GV_MAXDRIVENAME)
-
-int
-main(int argc, char **argv)
-{
- int tokens;
- char buffer[BUFSIZ], *inputline, *token[GV_MAXARGS];
-
- /* Load the module if necessary. */
- if (modfind(GVINUMMOD) < 0) {
- if (kldload(GVINUMKLD) < 0 && modfind(GVINUMMOD) < 0)
- err(1, GVINUMKLD ": Kernel module not available");
- }
-
- /* Arguments given on the command line. */
- if (argc > 1) {
- argc--;
- argv++;
- parseline(argc, argv);
-
- /* Interactive mode. */
- } else {
- for (;;) {
- inputline = readline("gvinum -> ");
- if (inputline == NULL) {
- if (ferror(stdin)) {
- err(1, "can't read input");
- } else {
- printf("\n");
- exit(0);
- }
- } else if (*inputline) {
- add_history(inputline);
- strcpy(buffer, inputline);
- free(inputline);
- tokens = gv_tokenize(buffer, token, GV_MAXARGS);
- if (tokens)
- parseline(tokens, token);
- }
- }
- }
- exit(0);
-}
-
-/* Attach a plex to a volume or a subdisk to a plex. */
-static void
-gvinum_attach(int argc, char * const *argv)
-{
- struct gctl_req *req;
- const char *errstr;
- int rename;
- off_t offset;
-
- rename = 0;
- offset = -1;
- if (argc < 3) {
- warnx("usage:\tattach <subdisk> <plex> [rename] "
- "[<plexoffset>]\n"
- "\tattach <plex> <volume> [rename]");
- return;
- }
- if (argc > 3) {
- if (!strcmp(argv[3], "rename")) {
- rename = 1;
- if (argc == 5)
- offset = strtol(argv[4], NULL, 0);
- } else
- offset = strtol(argv[3], NULL, 0);
- }
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "attach");
- gctl_ro_param(req, "child", -1, argv[1]);
- gctl_ro_param(req, "parent", -1, argv[2]);
- gctl_ro_param(req, "offset", sizeof(off_t), &offset);
- gctl_ro_param(req, "rename", sizeof(int), &rename);
- errstr = gctl_issue(req);
- if (errstr != NULL)
- warnx("attach failed: %s", errstr);
- gctl_free(req);
-}
-
-static void
-gvinum_create(int argc, char * const *argv)
-{
- struct gctl_req *req;
- struct gv_drive *d;
- struct gv_plex *p;
- struct gv_sd *s;
- struct gv_volume *v;
- FILE *tmp;
- int drives, errors, fd, flags, i, line, plexes, plex_in_volume;
- int sd_in_plex, status, subdisks, tokens, undeffd, volumes;
- const char *errstr;
- char buf[BUFSIZ], buf1[BUFSIZ], commandline[BUFSIZ], *sdname;
- const char *ed;
- char original[BUFSIZ], tmpfile[20], *token[GV_MAXARGS];
- char plex[GV_MAXPLEXNAME], volume[GV_MAXVOLNAME];
-
- tmp = NULL;
- flags = 0;
- for (i = 1; i < argc; i++) {
- /* Force flag used to ignore already created drives. */
- if (!strcmp(argv[i], "-f")) {
- flags |= GV_FLAG_F;
- /* Else it must be a file. */
- } else {
- if ((tmp = fopen(argv[i], "r")) == NULL) {
- warn("can't open '%s' for reading", argv[i]);
- return;
- }
- }
- }
-
- /* We didn't get a file. */
- if (tmp == NULL) {
- snprintf(tmpfile, sizeof(tmpfile), "/tmp/gvinum.XXXXXX");
-
- if ((fd = mkstemp(tmpfile)) == -1) {
- warn("temporary file not accessible");
- return;
- }
- if ((tmp = fdopen(fd, "w")) == NULL) {
- warn("can't open '%s' for writing", tmpfile);
- return;
- }
- printconfig(tmp, "# ");
- fclose(tmp);
-
- ed = getenv("EDITOR");
- if (ed == NULL)
- ed = _PATH_VI;
-
- snprintf(commandline, sizeof(commandline), "%s %s", ed,
- tmpfile);
- status = system(commandline);
- if (status != 0) {
- warn("couldn't exec %s; status: %d", ed, status);
- return;
- }
-
- if ((tmp = fopen(tmpfile, "r")) == NULL) {
- warn("can't open '%s' for reading", tmpfile);
- return;
- }
- }
-
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "create");
- gctl_ro_param(req, "flags", sizeof(int), &flags);
-
- drives = volumes = plexes = subdisks = 0;
- plex_in_volume = sd_in_plex = undeffd = 0;
- plex[0] = '\0';
- errors = 0;
- line = 1;
- while ((fgets(buf, BUFSIZ, tmp)) != NULL) {
-
- /* Skip empty lines and comments. */
- if (*buf == '\0' || *buf == '#') {
- line++;
- continue;
- }
-
- /* Kill off the newline. */
- buf[strlen(buf) - 1] = '\0';
-
- /*
- * Copy the original input line in case we need it for error
- * output.
- */
- strlcpy(original, buf, sizeof(original));
-
- tokens = gv_tokenize(buf, token, GV_MAXARGS);
- if (tokens <= 0) {
- line++;
- continue;
- }
-
- /* Volume definition. */
- if (!strcmp(token[0], "volume")) {
- v = gv_new_volume(tokens, token);
- if (v == NULL) {
- warnx("line %d: invalid volume definition",
- line);
- warnx("line %d: '%s'", line, original);
- errors++;
- line++;
- continue;
- }
-
- /* Reset plex count for this volume. */
- plex_in_volume = 0;
-
- /*
- * Set default volume name for following plex
- * definitions.
- */
- strlcpy(volume, v->name, sizeof(volume));
-
- snprintf(buf1, sizeof(buf1), "volume%d", volumes);
- gctl_ro_param(req, buf1, sizeof(*v), v);
- volumes++;
-
- /* Plex definition. */
- } else if (!strcmp(token[0], "plex")) {
- p = gv_new_plex(tokens, token);
- if (p == NULL) {
- warnx("line %d: invalid plex definition", line);
- warnx("line %d: '%s'", line, original);
- errors++;
- line++;
- continue;
- }
-
- /* Reset subdisk count for this plex. */
- sd_in_plex = 0;
-
- /* Default name. */
- if (strlen(p->name) == 0) {
- snprintf(p->name, sizeof(p->name), "%s.p%d",
- volume, plex_in_volume++);
- }
-
- /* Default volume. */
- if (strlen(p->volume) == 0) {
- snprintf(p->volume, sizeof(p->volume), "%s",
- volume);
- }
-
- /*
- * Set default plex name for following subdisk
- * definitions.
- */
- strlcpy(plex, p->name, sizeof(plex));
-
- snprintf(buf1, sizeof(buf1), "plex%d", plexes);
- gctl_ro_param(req, buf1, sizeof(*p), p);
- plexes++;
-
- /* Subdisk definition. */
- } else if (!strcmp(token[0], "sd")) {
- s = gv_new_sd(tokens, token);
- if (s == NULL) {
- warnx("line %d: invalid subdisk "
- "definition:", line);
- warnx("line %d: '%s'", line, original);
- errors++;
- line++;
- continue;
- }
-
- /* Default name. */
- if (strlen(s->name) == 0) {
- if (strlen(plex) == 0) {
- sdname = find_name("gvinumsubdisk.p",
- GV_TYPE_SD, GV_MAXSDNAME);
- snprintf(s->name, sizeof(s->name),
- "%s.s%d", sdname, undeffd++);
- free(sdname);
- } else {
- snprintf(s->name, sizeof(s->name),
- "%s.s%d",plex, sd_in_plex++);
- }
- }
-
- /* Default plex. */
- if (strlen(s->plex) == 0)
- snprintf(s->plex, sizeof(s->plex), "%s", plex);
-
- snprintf(buf1, sizeof(buf1), "sd%d", subdisks);
- gctl_ro_param(req, buf1, sizeof(*s), s);
- subdisks++;
-
- /* Subdisk definition. */
- } else if (!strcmp(token[0], "drive")) {
- d = gv_new_drive(tokens, token);
- if (d == NULL) {
- warnx("line %d: invalid drive definition:",
- line);
- warnx("line %d: '%s'", line, original);
- errors++;
- line++;
- continue;
- }
-
- snprintf(buf1, sizeof(buf1), "drive%d", drives);
- gctl_ro_param(req, buf1, sizeof(*d), d);
- drives++;
-
- /* Everything else is bogus. */
- } else {
- warnx("line %d: invalid definition:", line);
- warnx("line %d: '%s'", line, original);
- errors++;
- }
- line++;
- }
-
- fclose(tmp);
- unlink(tmpfile);
-
- if (!errors && (volumes || plexes || subdisks || drives)) {
- gctl_ro_param(req, "volumes", sizeof(int), &volumes);
- gctl_ro_param(req, "plexes", sizeof(int), &plexes);
- gctl_ro_param(req, "subdisks", sizeof(int), &subdisks);
- gctl_ro_param(req, "drives", sizeof(int), &drives);
- errstr = gctl_issue(req);
- if (errstr != NULL)
- warnx("create failed: %s", errstr);
- }
- gctl_free(req);
-}
-
-/* Create a concatenated volume. */
-static void
-gvinum_concat(int argc, char * const *argv)
-{
-
- if (argc < 2) {
- warnx("usage:\tconcat [-fv] [-n name] drives\n");
- return;
- }
- create_volume(argc, argv, "concat");
-}
-
-/* Create a drive quick and dirty. */
-static char *
-create_drive(const char *device)
-{
- struct gv_drive *d;
- struct gctl_req *req;
- const char *errstr;
- char *drivename, *dname;
- int drives, i, flags, volumes, subdisks, plexes;
- int found = 0;
-
- flags = plexes = subdisks = volumes = 0;
- drives = 1;
- dname = NULL;
-
- drivename = find_drive();
- if (drivename == NULL)
- return (NULL);
-
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "create");
- d = gv_alloc_drive();
- if (d == NULL)
- err(1, "unable to allocate for gv_drive object");
-
- strlcpy(d->name, drivename, sizeof(d->name));
- copy_device(d, device);
- gctl_ro_param(req, "drive0", sizeof(*d), d);
- gctl_ro_param(req, "flags", sizeof(int), &flags);
- gctl_ro_param(req, "drives", sizeof(int), &drives);
- gctl_ro_param(req, "volumes", sizeof(int), &volumes);
- gctl_ro_param(req, "plexes", sizeof(int), &plexes);
- gctl_ro_param(req, "subdisks", sizeof(int), &subdisks);
- errstr = gctl_issue(req);
- if (errstr != NULL) {
- warnx("error creating drive: %s", errstr);
- drivename = NULL;
- } else {
- /* XXX: This is needed because we have to make sure the drives
- * are created before we return. */
- /* Loop until it's in the config. */
- for (i = 0; i < 100000; i++) {
- dname = find_name("gvinumdrive", GV_TYPE_DRIVE,
- GV_MAXDRIVENAME);
- /* If we got a different name, quit. */
- if (dname == NULL)
- continue;
- if (strcmp(dname, drivename))
- found = 1;
- free(dname);
- dname = NULL;
- if (found)
- break;
- usleep(100000); /* Sleep for 0.1s */
- }
- if (found == 0) {
- warnx("error creating drive");
- drivename = NULL;
- }
- }
- gctl_free(req);
- return (drivename);
-}
-
-/*
- * General routine for creating a volume. Mainly for use by concat, mirror,
- * raid5 and stripe commands.
- */
-static void
-create_volume(int argc, char * const *argv, const char *verb)
-{
- struct gctl_req *req;
- const char *errstr;
- char buf[BUFSIZ], *drivename, *volname;
- int drives, flags, i;
- off_t stripesize;
-
- flags = 0;
- drives = 0;
- volname = NULL;
- stripesize = 262144;
-
- /* XXX: Should we check for argument length? */
-
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
-
- for (i = 1; i < argc; i++) {
- if (!strcmp(argv[i], "-f")) {
- flags |= GV_FLAG_F;
- } else if (!strcmp(argv[i], "-n")) {
- volname = argv[++i];
- } else if (!strcmp(argv[i], "-v")) {
- flags |= GV_FLAG_V;
- } else if (!strcmp(argv[i], "-s")) {
- flags |= GV_FLAG_S;
- if (!strcmp(verb, "raid5"))
- stripesize = gv_sizespec(argv[++i]);
- } else {
- /* Assume it's a drive. */
- snprintf(buf, sizeof(buf), "drive%d", drives++);
-
- /* First we create the drive. */
- drivename = create_drive(argv[i]);
- if (drivename == NULL)
- goto bad;
- /* Then we add it to the request. */
- gctl_ro_param(req, buf, -1, drivename);
- }
- }
-
- gctl_ro_param(req, "stripesize", sizeof(off_t), &stripesize);
-
- /* Find a free volume name. */
- if (volname == NULL)
- volname = find_name("gvinumvolume", GV_TYPE_VOL, GV_MAXVOLNAME);
-
- /* Then we send a request to actually create the volumes. */
- gctl_ro_param(req, "verb", -1, verb);
- gctl_ro_param(req, "flags", sizeof(int), &flags);
- gctl_ro_param(req, "drives", sizeof(int), &drives);
- gctl_ro_param(req, "name", -1, volname);
- errstr = gctl_issue(req);
- if (errstr != NULL)
- warnx("creating %s volume failed: %s", verb, errstr);
-bad:
- gctl_free(req);
-}
-
-/* Parse a line of the config, return the word after <pattern>. */
-static const char *
-find_pattern(char *line, const char *pattern)
-{
- char *ptr;
-
- ptr = strsep(&line, " ");
- while (ptr != NULL) {
- if (!strcmp(ptr, pattern)) {
- /* Return the next. */
- ptr = strsep(&line, " ");
- return (ptr);
- }
- ptr = strsep(&line, " ");
- }
- return (NULL);
-}
-
-/* Find a free name for an object given a prefix. */
-static char *
-find_name(const char *prefix, int type, int namelen)
-{
- struct gctl_req *req;
- char comment[1], buf[GV_CFG_LEN - 1], *sname, *ptr;
- const char *errstr, *name;
- int i, n, begin, len, conflict;
- char line[1024];
-
- comment[0] = '\0';
- buf[0] = '\0';
-
- /* Find a name. Fetch out configuration first. */
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "getconfig");
- gctl_ro_param(req, "comment", -1, comment);
- gctl_add_param(req, "config", sizeof(buf), buf,
- GCTL_PARAM_WR | GCTL_PARAM_ASCII);
- errstr = gctl_issue(req);
- if (errstr != NULL) {
- warnx("can't get configuration: %s", errstr);
- return (NULL);
- }
- gctl_free(req);
-
- begin = 0;
- len = strlen(buf);
- i = 0;
- sname = malloc(namelen + 1);
-
- /* XXX: Max object setting? */
- for (n = 0; n < 10000; n++) {
- snprintf(sname, namelen, "%s%d", prefix, n);
- conflict = 0;
- begin = 0;
- /* Loop through the configuration line by line. */
- for (i = 0; i < len; i++) {
- if (buf[i] == '\n' || buf[i] == '\0') {
- ptr = buf + begin;
- strlcpy(line, ptr, (i - begin) + 1);
- begin = i + 1;
- switch (type) {
- case GV_TYPE_DRIVE:
- name = find_pattern(line, "drive");
- break;
- case GV_TYPE_VOL:
- name = find_pattern(line, "volume");
- break;
- case GV_TYPE_PLEX:
- case GV_TYPE_SD:
- name = find_pattern(line, "name");
- break;
- default:
- printf("Invalid type given\n");
- continue;
- }
- if (name == NULL)
- continue;
- if (!strcmp(sname, name)) {
- conflict = 1;
- /* XXX: Could quit the loop earlier. */
- }
- }
- }
- if (!conflict)
- return (sname);
- }
- free(sname);
- return (NULL);
-}
-
-static void
-copy_device(struct gv_drive *d, const char *device)
-{
-
- if (strncmp(device, "/dev/", 5) == 0)
- strlcpy(d->device, (device + 5), sizeof(d->device));
- else
- strlcpy(d->device, device, sizeof(d->device));
-}
-
-/* Detach a plex or subdisk from its parent. */
-static void
-gvinum_detach(int argc, char * const *argv)
-{
- const char *errstr;
- struct gctl_req *req;
- int flags, i;
-
- flags = 0;
- optreset = 1;
- optind = 1;
- while ((i = getopt(argc, argv, "f")) != -1) {
- switch (i) {
- case 'f':
- flags |= GV_FLAG_F;
- break;
- default:
- warn("invalid flag: %c", i);
- return;
- }
- }
- argc -= optind;
- argv += optind;
- if (argc != 1) {
- warnx("usage: detach [-f] <subdisk> | <plex>");
- return;
- }
-
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "detach");
- gctl_ro_param(req, "object", -1, argv[0]);
- gctl_ro_param(req, "flags", sizeof(int), &flags);
-
- errstr = gctl_issue(req);
- if (errstr != NULL)
- warnx("detach failed: %s", errstr);
- gctl_free(req);
-}
-
-static void
-gvinum_help(void)
-{
-
- printf("COMMANDS\n"
- "checkparity [-f] plex\n"
- " Check the parity blocks of a RAID-5 plex.\n"
- "create [-f] description-file\n"
- " Create as per description-file or open editor.\n"
- "attach plex volume [rename]\n"
- "attach subdisk plex [offset] [rename]\n"
- " Attach a plex to a volume, or a subdisk to a plex\n"
- "concat [-fv] [-n name] drives\n"
- " Create a concatenated volume from the specified drives.\n"
- "detach [-f] [plex | subdisk]\n"
- " Detach a plex or a subdisk from the volume or plex to\n"
- " which it is attached.\n"
- "grow plex drive\n"
- " Grow plex by creating a properly sized subdisk on drive\n"
- "l | list [-r] [-v] [-V] [volume | plex | subdisk]\n"
- " List information about specified objects.\n"
- "ld [-r] [-v] [-V] [volume]\n"
- " List information about drives.\n"
- "ls [-r] [-v] [-V] [subdisk]\n"
- " List information about subdisks.\n"
- "lp [-r] [-v] [-V] [plex]\n"
- " List information about plexes.\n"
- "lv [-r] [-v] [-V] [volume]\n"
- " List information about volumes.\n"
- "mirror [-fsv] [-n name] drives\n"
- " Create a mirrored volume from the specified drives.\n"
- "move | mv -f drive object ...\n"
- " Move the object(s) to the specified drive.\n"
- "quit Exit the vinum program when running in interactive mode."
- " Nor-\n"
- " mally this would be done by entering the EOF character.\n"
- "raid5 [-fv] [-s stripesize] [-n name] drives\n"
- " Create a RAID-5 volume from the specified drives.\n"
- "rename [-r] [drive | subdisk | plex | volume] newname\n"
- " Change the name of the specified object.\n"
- "rebuildparity plex [-f]\n"
- " Rebuild the parity blocks of a RAID-5 plex.\n"
- "resetconfig [-f]\n"
- " Reset the complete gvinum configuration\n"
- "rm [-r] [-f] volume | plex | subdisk | drive\n"
- " Remove an object.\n"
- "saveconfig\n"
- " Save vinum configuration to disk after configuration"
- " failures.\n"
- "setstate [-f] state [volume | plex | subdisk | drive]\n"
- " Set state without influencing other objects, for"
- " diagnostic pur-\n"
- " poses only.\n"
- "start [-S size] volume | plex | subdisk\n"
- " Allow the system to access the objects.\n"
- "stripe [-fv] [-n name] drives\n"
- " Create a striped volume from the specified drives.\n"
- );
-}
-
-static void
-gvinum_setstate(int argc, char * const *argv)
-{
- struct gctl_req *req;
- int flags, i;
- const char *errstr;
-
- flags = 0;
-
- optreset = 1;
- optind = 1;
-
- while ((i = getopt(argc, argv, "f")) != -1) {
- switch (i) {
- case 'f':
- flags |= GV_FLAG_F;
- break;
- case '?':
- default:
- warn("invalid flag: %c", i);
- return;
- }
- }
-
- argc -= optind;
- argv += optind;
-
- if (argc != 2) {
- warnx("usage: setstate [-f] <state> <obj>");
- return;
- }
-
- /*
- * XXX: This hack is needed to avoid tripping over (now) invalid
- * 'classic' vinum states and will go away later.
- */
- if (strcmp(argv[0], "up") && strcmp(argv[0], "down") &&
- strcmp(argv[0], "stale")) {
- warnx("invalid state '%s'", argv[0]);
- return;
- }
-
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "setstate");
- gctl_ro_param(req, "state", -1, argv[0]);
- gctl_ro_param(req, "object", -1, argv[1]);
- gctl_ro_param(req, "flags", sizeof(int), &flags);
-
- errstr = gctl_issue(req);
- if (errstr != NULL)
- warnx("%s", errstr);
- gctl_free(req);
-}
-
-static void
-gvinum_list(int argc, char * const *argv)
-{
- struct gctl_req *req;
- int flags, i, j;
- const char *errstr;
- char buf[20], config[GV_CFG_LEN + 1];
- const char *cmd;
-
- flags = 0;
- cmd = "list";
-
- if (argc) {
- optreset = 1;
- optind = 1;
- cmd = argv[0];
- while ((j = getopt(argc, argv, "rsvV")) != -1) {
- switch (j) {
- case 'r':
- flags |= GV_FLAG_R;
- break;
- case 's':
- flags |= GV_FLAG_S;
- break;
- case 'v':
- flags |= GV_FLAG_V;
- break;
- case 'V':
- flags |= GV_FLAG_V;
- flags |= GV_FLAG_VV;
- break;
- case '?':
- default:
- return;
- }
- }
- argc -= optind;
- argv += optind;
-
- }
-
- config[0] = '\0';
-
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "list");
- gctl_ro_param(req, "cmd", -1, cmd);
- gctl_ro_param(req, "argc", sizeof(int), &argc);
- gctl_ro_param(req, "flags", sizeof(int), &flags);
- gctl_add_param(req, "config", sizeof(config), config,
- GCTL_PARAM_WR | GCTL_PARAM_ASCII);
- if (argc) {
- for (i = 0; i < argc; i++) {
- snprintf(buf, sizeof(buf), "argv%d", i);
- gctl_ro_param(req, buf, -1, argv[i]);
- }
- }
- errstr = gctl_issue(req);
- if (errstr != NULL) {
- warnx("can't get configuration: %s", errstr);
- gctl_free(req);
- return;
- }
-
- printf("%s", config);
- gctl_free(req);
-}
-
-/* Create a mirrored volume. */
-static void
-gvinum_mirror(int argc, char * const *argv)
-{
-
- if (argc < 2) {
- warnx("usage\tmirror [-fsv] [-n name] drives\n");
- return;
- }
- create_volume(argc, argv, "mirror");
-}
-
-/* Note that move is currently of form '[-r] target object [...]' */
-static void
-gvinum_move(int argc, char * const *argv)
-{
- struct gctl_req *req;
- const char *errstr;
- char buf[20];
- int flags, i, j;
-
- flags = 0;
- if (argc) {
- optreset = 1;
- optind = 1;
- while ((j = getopt(argc, argv, "f")) != -1) {
- switch (j) {
- case 'f':
- flags |= GV_FLAG_F;
- break;
- case '?':
- default:
- return;
- }
- }
- argc -= optind;
- argv += optind;
- }
-
- switch (argc) {
- case 0:
- warnx("no destination or object(s) to move specified");
- return;
- case 1:
- warnx("no object(s) to move specified");
- return;
- default:
- break;
- }
-
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "move");
- gctl_ro_param(req, "argc", sizeof(int), &argc);
- gctl_ro_param(req, "flags", sizeof(int), &flags);
- gctl_ro_param(req, "destination", -1, argv[0]);
- for (i = 1; i < argc; i++) {
- snprintf(buf, sizeof(buf), "argv%d", i);
- gctl_ro_param(req, buf, -1, argv[i]);
- }
- errstr = gctl_issue(req);
- if (errstr != NULL)
- warnx("can't move object(s): %s", errstr);
- gctl_free(req);
-}
-
-static void
-gvinum_printconfig(int argc __unused, char * const *argv __unused)
-{
-
- printconfig(stdout, "");
-}
-
-static void
-gvinum_parityop(int argc, char * const *argv, int rebuild)
-{
- struct gctl_req *req;
- int flags, i;
- const char *errstr;
- const char *op;
-
- if (rebuild) {
- op = "rebuildparity";
- } else {
- op = "checkparity";
- }
-
- optreset = 1;
- optind = 1;
- flags = 0;
- while ((i = getopt(argc, argv, "fv")) != -1) {
- switch (i) {
- case 'f':
- flags |= GV_FLAG_F;
- break;
- case 'v':
- flags |= GV_FLAG_V;
- break;
- default:
- warnx("invalid flag '%c'", i);
- return;
- }
- }
- argc -= optind;
- argv += optind;
-
- if (argc != 1) {
- warn("usage: %s [-f] [-v] <plex>", op);
- return;
- }
-
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, op);
- gctl_ro_param(req, "rebuild", sizeof(int), &rebuild);
- gctl_ro_param(req, "flags", sizeof(int), &flags);
- gctl_ro_param(req, "plex", -1, argv[0]);
-
- errstr = gctl_issue(req);
- if (errstr)
- warnx("%s\n", errstr);
- gctl_free(req);
-}
-
-/* Create a RAID-5 volume. */
-static void
-gvinum_raid5(int argc, char * const *argv)
-{
-
- if (argc < 2) {
- warnx("usage:\traid5 [-fv] [-s stripesize] [-n name] drives\n");
- return;
- }
- create_volume(argc, argv, "raid5");
-}
-
-static void
-gvinum_rename(int argc, char * const *argv)
-{
- struct gctl_req *req;
- const char *errstr;
- int flags, j;
-
- flags = 0;
-
- if (argc) {
- optreset = 1;
- optind = 1;
- while ((j = getopt(argc, argv, "r")) != -1) {
- switch (j) {
- case 'r':
- flags |= GV_FLAG_R;
- break;
- default:
- return;
- }
- }
- argc -= optind;
- argv += optind;
- }
-
- switch (argc) {
- case 0:
- warnx("no object to rename specified");
- return;
- case 1:
- warnx("no new name specified");
- return;
- case 2:
- break;
- default:
- warnx("more than one new name specified");
- return;
- }
-
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "rename");
- gctl_ro_param(req, "flags", sizeof(int), &flags);
- gctl_ro_param(req, "object", -1, argv[0]);
- gctl_ro_param(req, "newname", -1, argv[1]);
- errstr = gctl_issue(req);
- if (errstr != NULL)
- warnx("can't rename object: %s", errstr);
- gctl_free(req);
-}
-
-static void
-gvinum_rm(int argc, char * const *argv)
-{
- struct gctl_req *req;
- int flags, i, j;
- const char *errstr;
- char buf[20];
-
- flags = 0;
- optreset = 1;
- optind = 1;
- while ((j = getopt(argc, argv, "rf")) != -1) {
- switch (j) {
- case 'f':
- flags |= GV_FLAG_F;
- break;
- case 'r':
- flags |= GV_FLAG_R;
- break;
- default:
- return;
- }
- }
- argc -= optind;
- argv += optind;
-
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "remove");
- gctl_ro_param(req, "argc", sizeof(int), &argc);
- gctl_ro_param(req, "flags", sizeof(int), &flags);
- if (argc) {
- for (i = 0; i < argc; i++) {
- snprintf(buf, sizeof(buf), "argv%d", i);
- gctl_ro_param(req, buf, -1, argv[i]);
- }
- }
- errstr = gctl_issue(req);
- if (errstr != NULL) {
- warnx("can't remove: %s", errstr);
- gctl_free(req);
- return;
- }
- gctl_free(req);
-}
-
-static void
-gvinum_resetconfig(int argc, char * const *argv)
-{
- struct gctl_req *req;
- const char *errstr;
- char reply[32];
- int flags, i;
-
- flags = 0;
- while ((i = getopt(argc, argv, "f")) != -1) {
- switch (i) {
- case 'f':
- flags |= GV_FLAG_F;
- break;
- default:
- warn("invalid flag: %c", i);
- return;
- }
- }
- if ((flags & GV_FLAG_F) == 0) {
- if (!isatty(STDIN_FILENO)) {
- warn("Please enter this command from a tty device\n");
- return;
- }
- printf(" WARNING! This command will completely wipe out"
- " your gvinum configuration.\n"
- " All data will be lost. If you really want to do this,"
- " enter the text\n\n"
- " NO FUTURE\n"
- " Enter text -> ");
- fgets(reply, sizeof(reply), stdin);
- if (strcmp(reply, "NO FUTURE\n")) {
- printf("\n No change\n");
- return;
- }
- }
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "resetconfig");
- errstr = gctl_issue(req);
- if (errstr != NULL) {
- warnx("can't reset config: %s", errstr);
- gctl_free(req);
- return;
- }
- gctl_free(req);
- printf("gvinum configuration obliterated\n");
-}
-
-static void
-gvinum_saveconfig(void)
-{
- struct gctl_req *req;
- const char *errstr;
-
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "saveconfig");
- errstr = gctl_issue(req);
- if (errstr != NULL)
- warnx("can't save configuration: %s", errstr);
- gctl_free(req);
-}
-
-static void
-gvinum_start(int argc, char * const *argv)
-{
- struct gctl_req *req;
- int i, initsize, j;
- const char *errstr;
- char buf[20];
-
- /* 'start' with no arguments is a no-op. */
- if (argc == 1)
- return;
-
- initsize = 0;
-
- optreset = 1;
- optind = 1;
- while ((j = getopt(argc, argv, "S")) != -1) {
- switch (j) {
- case 'S':
- initsize = atoi(optarg);
- break;
- default:
- return;
- }
- }
- argc -= optind;
- argv += optind;
-
- if (!initsize)
- initsize = 512;
-
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "start");
- gctl_ro_param(req, "argc", sizeof(int), &argc);
- gctl_ro_param(req, "initsize", sizeof(int), &initsize);
- if (argc) {
- for (i = 0; i < argc; i++) {
- snprintf(buf, sizeof(buf), "argv%d", i);
- gctl_ro_param(req, buf, -1, argv[i]);
- }
- }
- errstr = gctl_issue(req);
- if (errstr != NULL) {
- warnx("can't start: %s", errstr);
- gctl_free(req);
- return;
- }
-
- gctl_free(req);
-}
-
-static void
-gvinum_stop(int argc __unused, char * const *argv __unused)
-{
- int err, fileid;
-
- fileid = kldfind(GVINUMKLD);
- if (fileid == -1) {
- if (modfind(GVINUMMOD) < 0)
- warn("cannot find " GVINUMKLD);
- return;
- }
-
- /*
- * This little hack prevents that we end up in an infinite loop in
- * g_unload_class(). gv_unload() will return EAGAIN so that the GEOM
- * event thread will be free for the g_wither_geom() call from
- * gv_unload(). It's silly, but it works.
- */
- printf("unloading " GVINUMKLD " kernel module... ");
- fflush(stdout);
- if ((err = kldunload(fileid)) != 0 && (errno == EAGAIN)) {
- sleep(1);
- err = kldunload(fileid);
- }
- if (err != 0) {
- printf(" failed!\n");
- warn("cannot unload " GVINUMKLD);
- return;
- }
-
- printf("done\n");
- exit(0);
-}
-
-/* Create a striped volume. */
-static void
-gvinum_stripe(int argc, char * const *argv)
-{
-
- if (argc < 2) {
- warnx("usage:\tstripe [-fv] [-n name] drives\n");
- return;
- }
- create_volume(argc, argv, "stripe");
-}
-
-/* Grow a subdisk by adding disk backed by provider. */
-static void
-gvinum_grow(int argc, char * const *argv)
-{
- struct gctl_req *req;
- char *drive, *sdname;
- char sdprefix[GV_MAXSDNAME];
- struct gv_drive *d;
- struct gv_sd *s;
- const char *errstr;
- int drives, volumes, plexes, subdisks, flags;
-
- flags = 0;
- drives = volumes = plexes = subdisks = 0;
- if (argc < 3) {
- warnx("usage:\tgrow plex drive\n");
- return;
- }
-
- s = gv_alloc_sd();
- if (s == NULL) {
- warn("unable to create subdisk");
- return;
- }
- d = gv_alloc_drive();
- if (d == NULL) {
- warn("unable to create drive");
- free(s);
- return;
- }
- /* Lookup device and set an appropriate drive name. */
- drive = find_drive();
- if (drive == NULL) {
- warn("unable to find an appropriate drive name");
- free(s);
- free(d);
- return;
- }
- strlcpy(d->name, drive, sizeof(d->name));
- copy_device(d, argv[2]);
-
- drives = 1;
-
- /* We try to use the plex name as basis for the subdisk name. */
- snprintf(sdprefix, sizeof(sdprefix), "%s.s", argv[1]);
- sdname = find_name(sdprefix, GV_TYPE_SD, GV_MAXSDNAME);
- if (sdname == NULL) {
- warn("unable to find an appropriate subdisk name");
- free(s);
- free(d);
- free(drive);
- return;
- }
- strlcpy(s->name, sdname, sizeof(s->name));
- free(sdname);
- strlcpy(s->plex, argv[1], sizeof(s->plex));
- strlcpy(s->drive, d->name, sizeof(s->drive));
- subdisks = 1;
-
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "create");
- gctl_ro_param(req, "flags", sizeof(int), &flags);
- gctl_ro_param(req, "volumes", sizeof(int), &volumes);
- gctl_ro_param(req, "plexes", sizeof(int), &plexes);
- gctl_ro_param(req, "subdisks", sizeof(int), &subdisks);
- gctl_ro_param(req, "drives", sizeof(int), &drives);
- gctl_ro_param(req, "drive0", sizeof(*d), d);
- gctl_ro_param(req, "sd0", sizeof(*s), s);
- errstr = gctl_issue(req);
- free(drive);
- if (errstr != NULL) {
- warnx("unable to grow plex: %s", errstr);
- free(s);
- free(d);
- return;
- }
- gctl_free(req);
-}
-
-static void
-parseline(int argc, char * const *argv)
-{
-
- if (argc <= 0)
- return;
-
- if (!strcmp(argv[0], "create"))
- gvinum_create(argc, argv);
- else if (!strcmp(argv[0], "exit") || !strcmp(argv[0], "quit"))
- exit(0);
- else if (!strcmp(argv[0], "attach"))
- gvinum_attach(argc, argv);
- else if (!strcmp(argv[0], "detach"))
- gvinum_detach(argc, argv);
- else if (!strcmp(argv[0], "concat"))
- gvinum_concat(argc, argv);
- else if (!strcmp(argv[0], "grow"))
- gvinum_grow(argc, argv);
- else if (!strcmp(argv[0], "help"))
- gvinum_help();
- else if (!strcmp(argv[0], "list") || !strcmp(argv[0], "l"))
- gvinum_list(argc, argv);
- else if (!strcmp(argv[0], "ld"))
- gvinum_list(argc, argv);
- else if (!strcmp(argv[0], "lp"))
- gvinum_list(argc, argv);
- else if (!strcmp(argv[0], "ls"))
- gvinum_list(argc, argv);
- else if (!strcmp(argv[0], "lv"))
- gvinum_list(argc, argv);
- else if (!strcmp(argv[0], "mirror"))
- gvinum_mirror(argc, argv);
- else if (!strcmp(argv[0], "move"))
- gvinum_move(argc, argv);
- else if (!strcmp(argv[0], "mv"))
- gvinum_move(argc, argv);
- else if (!strcmp(argv[0], "printconfig"))
- gvinum_printconfig(argc, argv);
- else if (!strcmp(argv[0], "raid5"))
- gvinum_raid5(argc, argv);
- else if (!strcmp(argv[0], "rename"))
- gvinum_rename(argc, argv);
- else if (!strcmp(argv[0], "resetconfig"))
- gvinum_resetconfig(argc, argv);
- else if (!strcmp(argv[0], "rm"))
- gvinum_rm(argc, argv);
- else if (!strcmp(argv[0], "saveconfig"))
- gvinum_saveconfig();
- else if (!strcmp(argv[0], "setstate"))
- gvinum_setstate(argc, argv);
- else if (!strcmp(argv[0], "start"))
- gvinum_start(argc, argv);
- else if (!strcmp(argv[0], "stop"))
- gvinum_stop(argc, argv);
- else if (!strcmp(argv[0], "stripe"))
- gvinum_stripe(argc, argv);
- else if (!strcmp(argv[0], "checkparity"))
- gvinum_parityop(argc, argv, 0);
- else if (!strcmp(argv[0], "rebuildparity"))
- gvinum_parityop(argc, argv, 1);
- else
- printf("unknown command '%s'\n", argv[0]);
-}
-
-/*
- * The guts of printconfig. This is called from gvinum_printconfig and from
- * gvinum_create when called without an argument, in order to give the user
- * something to edit.
- */
-static void
-printconfig(FILE *of, const char *comment)
-{
- struct gctl_req *req;
- struct utsname uname_s;
- const char *errstr;
- time_t now;
- char buf[GV_CFG_LEN + 1];
-
- uname(&uname_s);
- time(&now);
- buf[0] = '\0';
-
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "getconfig");
- gctl_ro_param(req, "comment", -1, comment);
- gctl_add_param(req, "config", sizeof(buf), buf,
- GCTL_PARAM_WR | GCTL_PARAM_ASCII);
- errstr = gctl_issue(req);
- if (errstr != NULL) {
- warnx("can't get configuration: %s", errstr);
- return;
- }
- gctl_free(req);
-
- fprintf(of, "# Vinum configuration of %s, saved at %s",
- uname_s.nodename,
- ctime(&now));
-
- if (*comment != '\0')
- fprintf(of, "# Current configuration:\n");
-
- fprintf(of, "%s", buf);
-}
diff --git a/sbin/gvinum/gvinum.h b/sbin/gvinum/gvinum.h
deleted file mode 100644
index f29dc4c986a4..000000000000
--- a/sbin/gvinum/gvinum.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-4-Clause
- *
- * 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.
- */
-
-
-#define GVINUMMOD "g_vinum"
-#define GVINUMKLD "geom_vinum"