diff options
Diffstat (limited to 'sbin/gvinum')
-rw-r--r-- | sbin/gvinum/Makefile | 14 | ||||
-rw-r--r-- | sbin/gvinum/Makefile.depend | 18 | ||||
-rw-r--r-- | sbin/gvinum/gvinum.8 | 460 | ||||
-rw-r--r-- | sbin/gvinum/gvinum.c | 1450 | ||||
-rw-r--r-- | sbin/gvinum/gvinum.h | 41 |
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" |