diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1999-01-11 14:49:46 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1999-01-11 14:49:46 +0000 |
commit | 716d3f670d9a4abe5b033357cc6f14e632348acf (patch) | |
tree | 8fae0e7cac442a7c0be3b3b0f747ba1691481a49 /sbin | |
parent | 3cb3ef4a25f75d713469261851ef2cb4ac4f691e (diff) |
Control RAIDframe
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/Makefile | 6 | ||||
-rw-r--r-- | sbin/raidctl/Makefile | 17 | ||||
-rw-r--r-- | sbin/raidctl/raidctl.8 | 570 | ||||
-rw-r--r-- | sbin/raidctl/raidctl.c | 390 | ||||
-rw-r--r-- | sbin/raidctl/rf_configure.c | 610 | ||||
-rw-r--r-- | sbin/raidctl/rf_utility.c | 62 | ||||
-rw-r--r-- | sbin/raidctl/rf_utility.h | 50 |
7 files changed, 1702 insertions, 3 deletions
diff --git a/sbin/Makefile b/sbin/Makefile index f871048ff61..d15e6234f8d 100644 --- a/sbin/Makefile +++ b/sbin/Makefile @@ -1,12 +1,12 @@ -# $OpenBSD: Makefile,v 1.36 1998/12/21 03:35:14 deraadt Exp $ +# $OpenBSD: Makefile,v 1.37 1999/01/11 14:49:42 niklas Exp $ # Not ported: XNSrouted enpload scsiformat startslip # Missing: icheck SUBDIR= badsect ccdconfig disklabel dmesg fsck ifconfig init ipf ipfstat \ ipnat ipsecadm isakmpd kbd mknod modload modunload mount mountd \ - ncheck_ffs nfsd nfsiod nologin photurisd ping quotacheck reboot \ - route routed savecore scan_ffs scsi shutdown slattach startkey \ + ncheck_ffs nfsd nfsiod nologin photurisd ping quotacheck raidctl \ + reboot route routed savecore scan_ffs scsi shutdown slattach startkey \ swapon ttyflags umount # support for various file systems diff --git a/sbin/raidctl/Makefile b/sbin/raidctl/Makefile new file mode 100644 index 00000000000..e0fc9f237b7 --- /dev/null +++ b/sbin/raidctl/Makefile @@ -0,0 +1,17 @@ +# $OpenBSD: Makefile,v 1.1 1999/01/11 14:49:43 niklas Exp $ + +PROG= raidctl +SRCS= rf_configure.c rf_layout.c rf_strutils.c raidctl.c +MAN= raidctl.8 + +CFLAGS += -Wall + +LOOKHERE = ${.CURDIR}/../../sys/dev/raidframe + +CFLAGS+= -DCSRG_BASED -DNARROWPROTO -DRF_UTILITY=1 -DSIMULATE=1 -I${LOOKHERE} +.PATH: ${LOOKHERE} + +DPADD= ${LIBUTIL} +LDADD= -lutil + +.include <bsd.prog.mk> diff --git a/sbin/raidctl/raidctl.8 b/sbin/raidctl/raidctl.8 new file mode 100644 index 00000000000..f9ecb3ce602 --- /dev/null +++ b/sbin/raidctl/raidctl.8 @@ -0,0 +1,570 @@ +.\" $OpenBSD: raidctl.8,v 1.1 1999/01/11 14:49:44 niklas Exp $ +.\" +.\" +.\" Copyright (c) 1998 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Greg Oster +.\" +.\" 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 the NetBSD +.\" Foundation, Inc. and its contributors. +.\" 4. Neither the name of The NetBSD Foundation 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 BY THE NETBSD FOUNDATION, INC. 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 THE FOUNDATION 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. +.\" +.\" +.\" Copyright (c) 1995 Carnegie-Mellon University. +.\" All rights reserved. +.\" +.\" Author: Mark Holland +.\" +.\" Permission to use, copy, modify and distribute this software and +.\" its documentation is hereby granted, provided that both the copyright +.\" notice and this permission notice appear in all copies of the +.\" software, derivative works or modified versions, and any portions +.\" thereof, and that both notices appear in supporting documentation. +.\" +.\" CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" +.\" CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND +.\" FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. +.\" +.\" Carnegie Mellon requests users of this software to return to +.\" +.\" Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU +.\" School of Computer Science +.\" Carnegie Mellon University +.\" Pittsburgh PA 15213-3890 +.\" +.\" any improvements or extensions that they make and grant Carnegie the +.\" rights to redistribute these changes. +.\" +.Dd November 6, 1998 +.Dt RAIDCTL 8 +.Os +.Sh NAME +.Nm raidctl +.Nd configuration utility for the RAIDframe disk driver +.Sh SYNOPSIS +.Nm +.Fl c Ar config_file Ar dev +.Nm "" +.Fl C Ar dev +.Nm "" +.Fl f Ar component Ar dev +.Nm "" +.Fl F Ar component Ar dev +.Nm "" +.Fl r Ar dev +.Nm "" +.Fl R Ar dev +.Nm "" +.Fl s Ar dev +.Nm "" +.Fl u Ar dev +.Sh DESCRIPTION +.Nm +is the user-land control program for +.Xr raid 4 , Ns +the RAIDframe disk device. +.Nm +is primarily used to dynamically configure and unconfigure RAIDframe disk +devices. For more information about the RAIDframe disk device, see +.Xr raid 4 . +.Pp +This document assumes the reader has at least rudimentary knowledge of +RAID and RAID concepts. +.Pp +The command-line options for +.Nm +are as follows: +.Bl -tag -width indent +.It Fl c Ar config_file Ar dev +Configure the RAIDframe device +.Ar dev +according to the configuration given in +.Ar config_file . +A description of the contents of +.Ar config_file +is given later. +.It Fl C Ar dev +Initiate a copyback of reconstructed data from a spare disk to +it's original disk. This is performed after a component has failed, +and the failed drive has been reconstructed onto a spare drive. +.It Fl f Ar component Ar dev +This marks the specified +.Ar component +as having failed, but does not initiate a reconstruction of that +component. +.It Fl F Ar component Ar dev +Fails the specified +.Ar component +of the device, and immediately begin a reconstruction of the failed +disk onto an available hot spare. This is the mechanism used to start +the reconstruction process if a component does have a hardware failure. +.It Fl r Ar dev +Re-write the parity on the device. This +.Ar MUST +be done before the RAID device is labeled and before +filesystems are created on the RAID device, and is normally used after +a system crash (and before a +.Xr fsck 8 ) Ns +to ensure the integrity of the parity. +.It Fl R Ar dev +Check the status of component reconstruction. The output indicates +the amount of progress achieved in reconstructing a failed component. +.It Fl s Ar dev +Display the status of the RAIDframe device for each of the components +and spares. +.It Fl u Ar dev +Unconfigure the RAIDframe device. +.El +.Pp +The device used by +.Nm +is specified by +.Ar dev . +.Ar dev +may be either the full name of the device, e.g. /dev/rraid0d, +for the i386 architecture, and /dev/rraid0c +for all others, or just simply raid0 (for /dev/rraid0d). +.Pp +The format of the configuration file is complex, and +only an abbreviated treatment is given here. In the configuration +files, a +.Sq # +indicates the beginning of a comment. +.Pp +There are 4 required sections of a configuration file, and 2 +optional components. Each section begins with a +.Sq START , +followed by +the section name, and the confuration parameters associated with that +section. The first section is the +.Sq array +section, and it specifies +the number of rows, columns, and spare disks in the RAID array. For +example: +.Bd -unfilled -offset indent +START array +1 3 0 +.Ed +.Pp +indicates an array with 1 row, 3 columns, and 0 spare disks. Note +that allthough multi-dimenstional arrays may be specified, they are +.Ar NOT +supported in the driver. +.Pp +The second section, the +.Sq disks +section, specifies the actual +components of the device. For example: +.Bd -unfilled -offset indent +START disks +/dev/sd0e +/dev/sd1e +/dev/sd2e +.Ed +.Pp +specifies the three component disks to be used in the RAID device. If +any of the specified drives cannot be found when the RAID device is +configured, then they will be marked as +.Sq failed , +and the system will +operate in degraded mode. Note that it is +.Ar imperative +that the order of the components in the configuration file does not +change between configurations of a RAID device. Changing the order +of the components (at least at the time of this writing) will result in +data loss. +.Pp +The next section, which is the +.Sq spare +section, is optional, and, if +present, specifies the devices to be used as +.Sq hot spares +-- devices +which are on-line, but are not actively used by the RAID driver unless +one of the main components fail. A simple +.Sq spare +section might be: +.Bd -unfilled -offset indent +START spare +/dev/sd3e +.Ed +.Pp +for a configuration with a single spare component. If no spare drives +are to be used in the configuration, then the +.Sq spare +section may be ommitted. +.Pp +The next section is the +.Sq layout +section. This section describes the +general layout parameters for the RAID device, and provides such +information as sectors per stripe unit, stripe units per parity unit, +stripe units per reconstruction unit, and the parity configuration to +use. This section might look like: +.Bd -unfilled -offset indent +START layout +# sectPerSU SUsPerParityUnit SUsPerReconUnit RAID_level +32 1 1 5 +.Ed +.Pp +The sectors per stripe unit specifies, in blocks, the interleave +factor; i.e. the number of contiguous sectors to be written to each +component for a single stripe. Appropriate selection of this value +(32 in this example) is the subject of much research in RAID +architectures. The stripe units per parity unit and +stripe units per reconstruction unit are normally each set to 1. +While certain values above 1 are permitted, a discussion of valid +values and the consequences of using anything other than 1 are outside +the scope of this document. The last value in this section (5 in this +example) indicates the parity configuration desired. Valid entries +include: +.Bl -tag -width inde +.It 0 +RAID level 0. No parity, only simple striping. +.It 1 +RAID level 1. Mirroring. +.It 4 +RAID level 4. Striping across components, with parity stored on the +last component. +.It 5 +RAID level 5. Striping across components, parity distributed across +all components. +.El +.Pp +There are other valid entries here, including those for Even-Odd +parity, RAID level 5 with rotated sparing, Chained declustering, +and Interleaved declustering, but as of this writing the code for +those parity operations has not been tested with +.Ox . +.Pp +The next required section is the +.Sq queue +section. This is most often +specified as: +.Bd -unfilled -offset indent +START queue +fifo 1 +.Ed +.Pp +where the queueing method is specified as fifo (first-in, first-out), +and the size of the per-component queue is limited to 1 requests. A +value of 1 is quite conservative here, and values of 100 or more may +been used to increase the driver performance. +Other queuing methods may also be specified, but a discussion of them +is beyond the scope of this document. +.Pp +The final section, the +.Sq debug section, is optional. For more details +on this the reader is referred to the RAIDframe documentation +dissussed in the +.Sx HISTORY +section. + +See +.Sx EXAMPLES +for a more complete configuration file example. + +.Sh EXAMPLES + +The examples in this section will focus on a RAID 5 configuration. +Other RAID configurations will behave similarly. It is highly +recommended that before using the RAID driver for real filesystems +that the system administrator(s) have used +.Ar all +of the options for +.Nm , +and that they understand how the component reconstruction process +works. While this example is not created as a tutorial, the steps +shown here can be easily dupilicated using four equal-sized partitions +from any number of disks (including all four from a single disk). +.Pp +The primary uses of +.Nm +is to configure and unconfigure +.Xr raid 4 +devices. To configure the device, a configuration +file which looks something like: +.Bd -unfilled -offset indent +START array +# numRow numCol numSpare +1 3 1 + +START disks +/dev/sd1e +/dev/sd2e +/dev/sd3e + +START spare +/dev/sd4e + +START layout +# sectPerSU SUsPerParityUnit SUsPerReconUnit RAID_level_5 +32 1 1 5 + +START queue +fifo 100 +.Ed +.Pp +is first created. In short, this configuration file specifies a RAID +5 configuration consisting of the disks /dev/sd1e, /dev/sd2e, and +/dev/sd3e, with /dev/sd4e available as a +.Sq hot spare +in case one of +the three main drives should fail. If the above configuration is in a +file called +.Sq rfconfig , +raid device 0 can be configured with: +.Bd -unfilled -offset indent +raidctl -c rfconfig raid0 +.Ed +.Pp +The above is equivalent to the following: +.Bd -unfilled -offset indent +raidctl -c rfconfig /dev/rraid0d +.Ed +.Pp +on the i386 architecture. On all other architectures, /dev/rraid0c +is used in place of /dev/rraid0d. +.Pp +To see how the device is doing, the following will show the status: +.Bd -unfilled -offset indent +raidctl -s raid0 +.Ed +.Pp +The output will look something like: +.Bd -unfilled -offset indent +Components: + /dev/sd1e: optimal + /dev/sd2e: optimal + /dev/sd3e: optimal +Spares: + /dev/sd4e [0][0]: spare +.Ed +.Pp +This indicates that all is well with the RAID array. If this is the first +time this RAID array has been configured, or the system is just being +brought up after an unclean shutdown, it is necessary to +ensure that the parity values are correct. This can be done via: +.Bd -unfilled -offset indent +raidctl -r raid0 +.Ed +.Pp +Once this is done, it is then safe to perform +.Xr disklabel 8 , Ns +.Xr newfs 8 , Ns +or +.Xr fsck 8 +on the device or its filesystems. +.Pp +If for some reason +(perhaps to test reconstruction) it is necessary to pretend a drive +has failed, the following will perform that function: +.Bd -unfilled -offset indent +raidctl -f /dev/sd2e raid0 +.Ed +.Pp +The system will then be performing all operations in degraded mode, +were missing data is re-computed from existing data and the parity. +In this case, obtaining the status of raid0 will return: +.Bd -unfilled -offset indent +Components: + /dev/sd1e: optimal + /dev/sd2e: failed + /dev/sd3e: optimal +Spares: + /dev/sd4e [0][0]: spare +.Ed +.Pp +Note that with the use of +.Fl f +a reconstruction has not been started. To both fail the disk and +start a reconstruction, the +.Fl F +option must be used. (The +.Fl f +option may be used first, and then the +.Fl F +option used later, on the same disk, if desired.) +Immediately after the reconstruction is started, the status will report: +.Bd -unfilled -offset indent +Components: + /dev/sd1e: optimal + /dev/sd2e: reconstructing + /dev/sd3e: optimal +Spares: + /dev/sd4e [0][0]: used_spare +.Ed +.Pp +This indicates that a reconstruction is in progress. To find out how +the reconstruction is progressing the +.Fl R +option may be used. This will indicate the progress in terms of the +percentage of the reconstruction that is completed. When the +reconstruction is finished the +.Fl s +option will show: +.Bd -unfilled -offset indent +Components: + /dev/sd1e: optimal + /dev/sd2e: spared + /dev/sd3e: optimal +Spares: + /dev/sd4e [0][0]: used_spare +.Ed +.Pp +At this point there are at least two options. First, if /dev/sd2e is +known to be good (i.e. the failure was either caused by +.Fl f +or +.Fl F , +or the failed disk was replaced), then a copyback of the data can +be initiated with the +.Fl C +option. In this example, this would copy the entire contents of +/dev/sd4e to /dev/sd2e. Once the copyback procedure is complete, the +status of the device would be: +.Bd -unfilled -offset indent +Components: + /dev/sd1e: optimal + /dev/sd2e: optimal + /dev/sd3e: optimal +Spares: + /dev/sd4e [0][0]: spare +.Ed +.Pp +and the system is back to normal operation. +.Pp +The second option after the reconstruction is to simply use /dev/sd4e +in place of /dev/sd2e in the configuration file. For example, the +configuration file (in part) might now look like: +.Bd -unfilled -offset indent +START array +1 3 0 + +START drives +/dev/sd1e +/dev/sd4e +/dev/sd3e +.Ed +.Pp +This can be done as /dev/sd4e is completely interchangeable with +/dev/sd2e at this point. Note that extreme care must be taken when +changing the order of the drives in a configuration. This is one of +the few instances where the devices and/or their orderings can be +changed without loss of data! In general, the ordering of components +in a configuration file should +.Ar never +be changed. +.Pp +The final operation performed by +.Nm +is to unconfigure a +.Xr raid 4 +device. This is accomplished via a simple: +.Bd -unfilled -offset indent +raidctl -u raid0 +.Ed +.Pp +at which point the device is ready to be reconfigured. +.Sh WARNINGS +Certain RAID levels (1, 4, 5, 6, and others) can protect against some +data loss due to component failure. However the loss of two +components of a RAID 4 or 5 system, or the loss of a single component +of a RAID 0 system will result in the entire filesystem being lost. +RAID is +.Ar NOT +a substitute for good backup practices. +.Pp +Recomputation of parity +.Ar MUST +be performed whenever there is a chance that it may have been +compromised. This includes after system crashes, or before a RAID +device has been used for the first time. Failure to keep parity +correct will be catastrophic should a component ever fail -- it is +better to use RAID 0 and get the additional space and speed, than it +is to use parity, but not keep the parity correct. At least with RAID +0 there is no perception of increased data security. +.Pp +.Sh FILES +.Bl -tag -width /dev/XXrXraidX -compact +.It Pa /dev/{,r}raid* +.Nm +device special files. +.El +.Pp +.Sh SEE ALSO +.Xr raid 4 , +.Xr ccd 4 , +.Xr rc 8 +.Sh HISTORY +RAIDframe is a framework for rapid prototyping of RAID structures +developed by the folks at the Parallel Data Laboratory at Carnegie +Mellon University (CMU). +A more complete description of the internals and functionality of +RAIDframe is found in the paper "RAIDframe: A Rapid Prototyping Tool +for RAID Systems", by William V. Courtright II, Garth Gibson, Mark +Holland, LeAnn Neal Reilly, and Jim Zelenka, and published by the +Parallel Data Laboratory of Carnegie Mellon University. +.Pp +The +.Nm +command first appeared as a program in CMU's RAIDframe v1.1 distribution. This +version of +.Nm +is a complete re-write, and first appeared in +.Nx 1.4 . +.Sh COPYRIGHT +.Bd -unfilled + +The RAIDframe Copyright is as follows: + +Copyright (c) 1994-1996 Carnegie-Mellon University. +All rights reserved. + +Permission to use, copy, modify and distribute this software and +its documentation is hereby granted, provided that both the copyright +notice and this permission notice appear in all copies of the +software, derivative works or modified versions, and any portions +thereof, and that both notices appear in supporting documentation. + +CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" +CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND +FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + +Carnegie Mellon requests users of this software to return to + + Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + School of Computer Science + Carnegie Mellon University + Pittsburgh PA 15213-3890 + +any improvements or extensions that they make and grant Carnegie the +rights to redistribute these changes. + +.Ed diff --git a/sbin/raidctl/raidctl.c b/sbin/raidctl/raidctl.c new file mode 100644 index 00000000000..9c49a61bfbd --- /dev/null +++ b/sbin/raidctl/raidctl.c @@ -0,0 +1,390 @@ +/* $OpenBSD: raidctl.c,v 1.1 1999/01/11 14:49:44 niklas Exp $ */ + +/*- + * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Greg Oster + * + * 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 the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 BY THE NETBSD FOUNDATION, INC. 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 THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + + This program is a re-write of the original rf_ctrl program + distributed by CMU with RAIDframe 1.1. + + This program is the user-land interface to the RAIDframe kernel + driver in NetBSD. + + */ + +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <util.h> +#include <stdio.h> +#include <fcntl.h> +#include <ctype.h> +#include <err.h> +#include <sys/types.h> +#include <string.h> +#include <sys/disklabel.h> +#include <machine/disklabel.h> +#include "rf_raidframe.h" + +extern char *__progname; + +int main __P((int, char *[])); +static void do_ioctl __P((int, unsigned long, void *, char *)); +static void rf_configure __P((int, char*)); +static char *device_status __P((RF_DiskStatus_t)); +static void rf_get_device_status __P((int)); +static void rf_fail_disk __P((int, char *, int)); +static void usage __P((void)); + +int +main(argc,argv) + int argc; + char *argv[]; +{ + extern char *optarg; + extern int optind; + int ch; + int num_options; + unsigned long action; + char config_filename[PATH_MAX]; + char dev_name[PATH_MAX]; + char name[PATH_MAX]; + char component_to_fail[PATH_MAX]; + int do_recon; + int raidID; + int rawpart; + int recon_percent_done; + struct stat st; + int fd; + + num_options = 0; + action = 0; + do_recon = 0; + + while ((ch = getopt(argc, argv, "c:Cf:F:rRsu")) != -1) + switch(ch) { + case 'c': + strncpy(config_filename,optarg,PATH_MAX); + action = RAIDFRAME_CONFIGURE; + num_options++; + break; + case 'C': + action = RAIDFRAME_COPYBACK; + num_options++; + break; + case 'f': + action = RAIDFRAME_FAIL_DISK; + do_recon = 0; + strncpy(component_to_fail, optarg, PATH_MAX); + num_options++; + break; + case 'F': + action = RAIDFRAME_FAIL_DISK; + do_recon = 1; + strncpy(component_to_fail, optarg, PATH_MAX); + num_options++; + break; + case 'r': + action = RAIDFRAME_REWRITEPARITY; + num_options++; + break; + case 'R': + action = RAIDFRAME_CHECKRECON; + num_options++; + break; + case 's': + action = RAIDFRAME_GET_INFO; + num_options++; + break; + case 'u': + action = RAIDFRAME_SHUTDOWN; + num_options++; + break; + default: + usage(); + } + argc -= optind; + argv += optind; + + if ((num_options > 1) || (argc == NULL)) + usage(); + + strncpy(name,argv[0],PATH_MAX); + + if ((name[0] == '/') || (name[0] == '.')) { + /* they've (apparently) given a full path... */ + strncpy(dev_name, name, PATH_MAX); + } else { + if (isdigit(name[strlen(name)-1])) { + rawpart = getrawpartition(); + snprintf(dev_name,PATH_MAX,"/dev/%s%c",name, + 'a'+rawpart); + } else { + snprintf(dev_name,PATH_MAX,"/dev/%s",name); + } + } + + if (stat(dev_name, &st) != 0) { + fprintf(stderr,"%s: stat failure on: %s\n", + __progname,dev_name); + return (errno); + } + if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) { + fprintf(stderr,"%s: invalid device: %s\n", + __progname,dev_name); + return (EINVAL); + } + + raidID = RF_DEV2RAIDID(st.st_rdev); + + if ((fd = open( dev_name, O_RDWR, 0640)) < 0) { + fprintf(stderr, "%s: unable to open device file: %s\n", + __progname, dev_name); + exit(1); + } + + + switch(action) { + case RAIDFRAME_CONFIGURE: + rf_configure(fd, config_filename); + break; + case RAIDFRAME_COPYBACK: + printf("Copyback.\n"); + do_ioctl(fd, RAIDFRAME_COPYBACK, NULL, "RAIDFRAME_COPYBACK"); + break; + case RAIDFRAME_FAIL_DISK: + rf_fail_disk(fd,component_to_fail,do_recon); + break; + case RAIDFRAME_REWRITEPARITY: + printf("Initiating re-write of parity\n"); + do_ioctl(fd, RAIDFRAME_REWRITEPARITY, NULL, + "RAIDFRAME_REWRITEPARITY"); + break; + case RAIDFRAME_CHECKRECON: + do_ioctl(fd, RAIDFRAME_CHECKRECON, &recon_percent_done, + "RAIDFRAME_CHECKRECON"); + printf("Reconstruction is %d%% complete.\n", + recon_percent_done); + break; + case RAIDFRAME_GET_INFO: + rf_get_device_status(fd); + break; + case RAIDFRAME_SHUTDOWN: + do_ioctl(fd, RAIDFRAME_SHUTDOWN, NULL, "RAIDFRAME_SHUTDOWN"); + break; + default: + break; + } + + close(fd); + exit(0); +} + +static void +do_ioctl(fd, command, arg, ioctl_name) + int fd; + unsigned long command; + void *arg; + char *ioctl_name; +{ + if (ioctl(fd, command, arg) < 0) { + warn("ioctl (%s) failed", ioctl_name); + exit(1); + } +} + + +static void +rf_configure(fd,config_file) + int fd; + char *config_file; +{ + void *generic; + RF_Config_t cfg; + + if (rf_MakeConfig( config_file, &cfg ) < 0) { + fprintf(stderr,"%s: unable to create RAIDframe %s\n", + __progname, "configuration structure\n"); + exit(1); + } + + /* + + Note the extra level of redirection needed here, since + what we really want to pass in is a pointer to the pointer to + the configuration structure. + + */ + + generic = (void *) &cfg; + do_ioctl(fd,RAIDFRAME_CONFIGURE,&generic,"RAIDFRAME_CONFIGURE"); +#if 0 + if (ioctl(fd, RAIDFRAME_CONFIGURE, &generic) < 0) { + warn("ioctl (RAIDFRAME_CONFIGURE): failed\n"); + exit(1); + } +#endif +} + +static char * +device_status(status) + RF_DiskStatus_t status; +{ + static char status_string[256]; + + switch (status) { + case rf_ds_optimal: + strcpy(status_string,"optimal"); + break; + case rf_ds_failed: + strcpy(status_string,"failed"); + break; + case rf_ds_reconstructing: + strcpy(status_string,"reconstructing"); + break; + case rf_ds_dist_spared: + strcpy(status_string,"dist_spared"); + break; + case rf_ds_spared: + strcpy(status_string,"spared"); + break; + case rf_ds_spare: + strcpy(status_string,"spare"); + break; + case rf_ds_used_spare: + strcpy(status_string,"used_spare"); + break; + default: + strcpy(status_string,"UNKNOWN"); + break; + } + return(status_string); +} + +static void +rf_get_device_status(fd) + int fd; +{ + RF_DeviceConfig_t device_config; + void *cfg_ptr; + int i; + + cfg_ptr = &device_config; + + do_ioctl(fd, RAIDFRAME_GET_INFO, &cfg_ptr, "RAIDFRAME_GET_INFO"); + + printf("Components:\n"); + for(i=0; i < device_config.ndevs; i++) { + printf("%20s: %s\n", device_config.devs[i].devname, + device_status(device_config.devs[i].status)); + } + if (device_config.nspares > 0) { + printf("Spares:\n"); + for(i=0; i < device_config.nspares; i++) { + printf("%20s [%d][%d]: %s\n", + device_config.spares[i].devname, + device_config.spares[i].spareRow, + device_config.spares[i].spareCol, + device_status(device_config.spares[i].status)); + } + } else { + printf("No spares.\n"); + } + +} + +static void +rf_fail_disk(fd, component_to_fail, do_recon) + int fd; + char *component_to_fail; + int do_recon; +{ + struct rf_recon_req recon_request; + RF_DeviceConfig_t device_config; + void *cfg_ptr; + int i; + int found; + int component_num; + + component_num = -1; + + /* Assuming a full path spec... */ + cfg_ptr = &device_config; + do_ioctl(fd, RAIDFRAME_GET_INFO, &cfg_ptr, + "RAIDFRAME_GET_INFO"); + found = 0; + for(i=0; i < device_config.ndevs; i++) { + if (strncmp(component_to_fail, + device_config.devs[i].devname, + PATH_MAX)==0) { + found = 1; + component_num = i; + } + } + if (!found) { + fprintf(stderr,"%s: %s is not a component %s", + __progname, component_to_fail, + "of this device\n"); + exit(1); + } + + recon_request.row = component_num / device_config.cols; + recon_request.col = component_num % device_config.cols; + if (do_recon) { + recon_request.flags = RF_FDFLAGS_RECON; + } else { + recon_request.flags = RF_FDFLAGS_NONE; + } + do_ioctl(fd, RAIDFRAME_FAIL_DISK, &recon_request, + "RAIDFRAME_FAIL_DISK"); + +} + +static void +usage() +{ + fprintf(stderr, "usage: %s -c config_file dev\n", __progname); + fprintf(stderr, " %s -C dev\n", __progname); + fprintf(stderr, " %s -f component dev\n", __progname); + fprintf(stderr, " %s -F component dev\n", __progname); + fprintf(stderr, " %s -r dev\n", __progname); + fprintf(stderr, " %s -R dev\n", __progname); + fprintf(stderr, " %s -s dev\n", __progname); + fprintf(stderr, " %s -u dev\n", __progname); + exit(1); + /* NOTREACHED */ +} diff --git a/sbin/raidctl/rf_configure.c b/sbin/raidctl/rf_configure.c new file mode 100644 index 00000000000..6e0f28e6a1d --- /dev/null +++ b/sbin/raidctl/rf_configure.c @@ -0,0 +1,610 @@ +/* $OpenBSD: rf_configure.c,v 1.1 1999/01/11 14:49:44 niklas Exp $ */ + +/* + * Copyright (c) 1995 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Mark Holland + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +/*************************************************************** + * + * rf_configure.c -- code related to configuring the raidframe system + * + * configuration is complicated by the fact that we want the same + * driver to work both in the kernel and at user level. In the + * kernel, we can't read the configuration file, so we configure + * by running a user-level program that reads the config file, + * creates a data structure describing the configuration and + * passes it into the kernel via an ioctl. Since we want the config + * code to be common between the two versions of the driver, we + * configure using the same two-step process when running at + * user level. Of course, at user level, the config structure is + * passed directly to the config routine, rather than via ioctl. + * + * This file is not compiled into the kernel, so we have no + * need for KERNEL ifdefs. + * + **************************************************************/ + +/* $Locker: $ + * $Log: rf_configure.c,v $ + * Revision 1.1 1999/01/11 14:49:44 niklas + * Control RAIDframe + * + * Revision 1.1.1.2 1998/11/23 21:35:58 niklas + * NetBSD-current 981123 + * + * Revision 1.2 1998/11/23 00:18:40 mrg + * fix compile errors on the alpha. + * + * Revision 1.1 1998/11/13 04:34:02 oster + * + * RAIDframe, version 1.1, from the Parallel Data Laboratory at + * Carnegie Mellon University. Full RAID implementation, including + * levels 0, 1, 4, 5, 6, parity logging, and a few other goodies. + * Ported to NetBSD by Greg Oster. + * + * raidctl is our userland configuration tool for RAIDframe. + * + * Revision 1.42 1996/08/09 18:47:47 jimz + * major -> dev_major + * + * Revision 1.41 1996/07/29 14:05:12 jimz + * fix numPUs/numRUs confusion (everything is now numRUs) + * clean up some commenting, return values + * + * Revision 1.40 1996/07/27 23:36:08 jimz + * Solaris port of simulator + * + * Revision 1.39 1996/07/27 18:39:45 jimz + * cleanup sweep + * + * Revision 1.38 1996/07/18 22:57:14 jimz + * port simulator to AIX + * + * Revision 1.37 1996/06/19 14:58:02 jimz + * move layout-specific config parsing hooks into RF_LayoutSW_t + * table in rf_layout.c + * + * Revision 1.36 1996/06/17 14:38:33 jimz + * properly #if out RF_DEMO code + * fix bug in MakeConfig that was causing weird behavior + * in configuration routines (config was not zeroed at start) + * clean up genplot handling of stacks + * + * Revision 1.35 1996/06/05 19:38:32 jimz + * fixed up disk queueing types config + * added sstf disk queueing + * fixed exit bug on diskthreads (ref-ing bad mem) + * + * Revision 1.34 1996/06/03 23:28:26 jimz + * more bugfixes + * check in tree to sync for IPDS runs with current bugfixes + * there still may be a problem with threads in the script test + * getting I/Os stuck- not trivially reproducible (runs ~50 times + * in a row without getting stuck) + * + * Revision 1.33 1996/06/02 17:31:48 jimz + * Moved a lot of global stuff into array structure, where it belongs. + * Fixed up paritylogging, pss modules in this manner. Some general + * code cleanup. Removed lots of dead code, some dead files. + * + * Revision 1.32 1996/05/30 23:22:16 jimz + * bugfixes of serialization, timing problems + * more cleanup + * + * Revision 1.31 1996/05/30 11:29:41 jimz + * Numerous bug fixes. Stripe lock release code disagreed with the taking code + * about when stripes should be locked (I made it consistent: no parity, no lock) + * There was a lot of extra serialization of I/Os which I've removed- a lot of + * it was to calculate values for the cache code, which is no longer with us. + * More types, function, macro cleanup. Added code to properly quiesce the array + * on shutdown. Made a lot of stuff array-specific which was (bogusly) general + * before. Fixed memory allocation, freeing bugs. + * + * Revision 1.30 1996/05/27 18:56:37 jimz + * more code cleanup + * better typing + * compiles in all 3 environments + * + * Revision 1.29 1996/05/24 01:59:45 jimz + * another checkpoint in code cleanup for release + * time to sync kernel tree + * + * Revision 1.28 1996/05/18 19:51:34 jimz + * major code cleanup- fix syntax, make some types consistent, + * add prototypes, clean out dead code, et cetera + * + * Revision 1.27 1995/12/12 18:10:06 jimz + * MIN -> RF_MIN, MAX -> RF_MAX, ASSERT -> RF_ASSERT + * fix 80-column brain damage in comments + * + * Revision 1.26 1995/12/01 15:16:36 root + * added copyright info + * + */ + + +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "rf_raid.h" +#include "rf_raidframe.h" +#include "rf_utils.h" +#include "rf_general.h" +#include "rf_decluster.h" +#include "rf_configure.h" +#include "rf_sys.h" + +/* + + XXX we include this here so we don't need to drag rf_debugMem.c into + the picture... This is userland, afterall... + + */ + +/* XXX sucky hack to override the defn. of RF_Malloc as given in +rf_debugMem.c... but I *really* don't want (nor need) to link with +that file here in userland.. GO +*/ + +#undef RF_Malloc +#define RF_Malloc(_p_, _size_, _cast_) \ + { \ + _p_ = _cast_ malloc((u_long)_size_); \ + bzero((char *)_p_, _size_); \ + } + + + +#ifndef SIMULATE +static unsigned int dev_name2num(char *s); +static unsigned int osf_dev_name2num(char *s); +#endif +static int rf_search_file_for_start_of(char *string, char *buf, int len, + FILE *fp); +static int rf_get_next_nonblank_line(char *buf, int len, FILE *fp, + char *errmsg); + +/* called from user level to read the configuration file and create + * a configuration control structure. This is used in the user-level + * version of the driver, and in the user-level program that configures + * the system via ioctl. + */ +int rf_MakeConfig(configname, cfgPtr) + char *configname; + RF_Config_t *cfgPtr; +{ + int numscanned, val, r, c, retcode, aa, bb, cc; + char buf[256], buf1[256], *cp; + RF_LayoutSW_t *lp; + FILE *fp; + + bzero((char *)cfgPtr, sizeof(RF_Config_t)); + + fp = fopen(configname, "r"); + if (!fp) { + RF_ERRORMSG1("Can't open config file %s\n",configname); + return(-1); + } + + rewind(fp); + if (rf_search_file_for_start_of("array", buf, 256, fp)) { + RF_ERRORMSG1("Unable to find start of \"array\" params in config file %s\n",configname); + retcode = -1; goto out; + } + rf_get_next_nonblank_line(buf, 256, fp, "Config file error (\"array\" section): unable to get numRow and numCol\n"); + /* + * wackiness with aa, bb, cc to get around size problems on different platforms + */ + numscanned = sscanf(buf,"%d %d %d", &aa, &bb, &cc); + if (numscanned != 3) { + RF_ERRORMSG("Config file error (\"array\" section): unable to get numRow, numCol, numSpare\n"); + retcode = -1; goto out; + } + cfgPtr->numRow = (RF_RowCol_t)aa; + cfgPtr->numCol = (RF_RowCol_t)bb; + cfgPtr->numSpare = (RF_RowCol_t)cc; + + /* debug section is optional */ + for (c=0; c<RF_MAXDBGV; c++) + cfgPtr->debugVars[c][0] = '\0'; + rewind(fp); + if (!rf_search_file_for_start_of("debug", buf, 256, fp)) { + for (c=0; c < RF_MAXDBGV; c++) { + if (rf_get_next_nonblank_line(buf, 256, fp, NULL)) break; + cp = rf_find_non_white(buf); + if (!strncmp(cp, "START", strlen("START"))) break; + (void) strcpy(&cfgPtr->debugVars[c][0], cp); + } + } + + rewind(fp); + strcpy(cfgPtr->diskQueueType,"fifo"); + cfgPtr->maxOutstandingDiskReqs = 1; + /* scan the file for the block related to disk queues */ + if (rf_search_file_for_start_of("queue",buf,256,fp)) { + RF_ERRORMSG2("[No disk queue discipline specified in config file %s. Using %s.]\n",configname, cfgPtr->diskQueueType); + } else { + if (rf_get_next_nonblank_line(buf, 256, fp, NULL)) { + RF_ERRORMSG2("[No disk queue discipline specified in config file %s. Using %s.]\n",configname, cfgPtr->diskQueueType); + } + } + + /* the queue specifier line contains two entries: + * 1st char of first word specifies queue to be used + * 2nd word specifies max num reqs that can be outstanding on the disk itself (typically 1) + */ + if (sscanf(buf,"%s %d",buf1,&val)!=2) { + RF_ERRORMSG1("Can't determine queue type and/or max outstanding reqs from line: %s",buf); + RF_ERRORMSG2("Using %s-%d\n", cfgPtr->diskQueueType, cfgPtr->maxOutstandingDiskReqs); + } else { + char *c; + bcopy(buf1, cfgPtr->diskQueueType, RF_MIN(sizeof(cfgPtr->diskQueueType), strlen(buf1)+1)); + for(c=buf1;*c;c++) { + if (*c == ' ') { + *c = '\0'; + break; + } + } + cfgPtr->maxOutstandingDiskReqs = val; + } + + rewind(fp); + + + if (rf_search_file_for_start_of("disks",buf,256,fp)) { + RF_ERRORMSG1("Can't find \"disks\" section in config file %s\n",configname); + retcode = -1; goto out; + } + + for (r=0; r<cfgPtr->numRow; r++) { + for (c=0; c<cfgPtr->numCol; c++) { + if (rf_get_next_nonblank_line(&cfgPtr->devnames[r][c][0], 50, fp, NULL)) { + RF_ERRORMSG2("Config file error: unable to get device file for disk at row %d col %d\n",r,c); + retcode = -1; goto out; + } +#ifndef SIMULATE + val = dev_name2num(&cfgPtr->devnames[r][c][0]); + + if (val < 0) { + RF_ERRORMSG3("Config file error: can't get dev num (dev file '%s') for disk at row %d c %d\n", + &cfgPtr->devnames[r][c][0],r,c); + retcode = -1; goto out; + } else cfgPtr->devs[r][c] = val; +#endif /* !SIMULATE */ + } + } + + /* "spare" section is optional */ + rewind(fp); + if (rf_search_file_for_start_of("spare",buf,256,fp)) cfgPtr->numSpare =0; + for (c = 0; c < cfgPtr->numSpare; c++) { + if (rf_get_next_nonblank_line(&cfgPtr->spare_names[c][0], 256, fp, NULL)) { + RF_ERRORMSG1("Config file error: unable to get device file for spare disk %d\n",c); + retcode = -1; goto out; + } +#ifndef SIMULATE + val = dev_name2num(&cfgPtr->spare_names[c][0]); + if (val < 0) { + RF_ERRORMSG2("Config file error: can't get dev num (dev file '%s') for spare disk %d\n", + &cfgPtr->spare_names[c][0],c); + retcode = -1; goto out; + } else cfgPtr->spare_devs[c] = val; +#endif /* !SIMULATE */ + } + + /* scan the file for the block related to layout */ + rewind(fp); + if (rf_search_file_for_start_of("layout",buf,256,fp)) { + RF_ERRORMSG1("Can't find \"layout\" section in configuration file %s\n",configname); + retcode = -1; goto out; + } + if (rf_get_next_nonblank_line(buf, 256, fp, NULL)) { + RF_ERRORMSG("Config file error (\"layout\" section): unable to find common layout param line\n"); + retcode = -1; goto out; + } + c = sscanf(buf,"%d %d %d %c", &aa, &bb, &cc, &cfgPtr->parityConfig); + cfgPtr->sectPerSU = (RF_SectorNum_t)aa; + cfgPtr->SUsPerPU = (RF_StripeNum_t)bb; + cfgPtr->SUsPerRU = (RF_StripeNum_t)cc; + if (c != 4) { + RF_ERRORMSG("Unable to scan common layout line\n"); + retcode = -1; goto out; + } + lp = rf_GetLayout(cfgPtr->parityConfig); + if (lp == NULL) { + RF_ERRORMSG1("Unknown parity config '%c'\n", cfgPtr->parityConfig); + retcode = -1; + goto out; + } + + /* XXX who cares.. it's not going into the kernel, so we should ignore this... */ +#ifndef KERNEL + retcode = lp->MakeLayoutSpecific(fp, cfgPtr, lp->makeLayoutSpecificArg); +#endif +out: + fclose(fp); + if (retcode < 0) + retcode = errno = EINVAL; + else + errno = retcode; + return(retcode); +} + + +/* used in architectures such as RAID0 where there is no layout-specific + * information to be passed into the configuration code. + */ +int rf_MakeLayoutSpecificNULL(fp, cfgPtr, ignored) + FILE *fp; + RF_Config_t *cfgPtr; + void *ignored; +{ + cfgPtr->layoutSpecificSize = 0; + cfgPtr->layoutSpecific = NULL; + return(0); +} + +int rf_MakeLayoutSpecificDeclustered(configfp, cfgPtr, arg) + FILE *configfp; + RF_Config_t *cfgPtr; + void *arg; +{ + int b, v, k, r, lambda, norotate, i, val, distSpare; + char *cfgBuf, *bdfile, *p, *smname; + char buf[256], smbuf[256]; + FILE *fp; + + distSpare = *((int *)arg); + + /* get the block design file name */ + if (rf_get_next_nonblank_line(buf,256,configfp,"Can't find block design file name in config file\n")) + return(EINVAL); + bdfile = rf_find_non_white(buf); + if (bdfile[strlen(bdfile)-1] == '\n') { + /* strip newline char */ + bdfile[strlen(bdfile)-1] = '\0'; + } + + /* open bd file, check validity of configuration */ + if ((fp = fopen(bdfile,"r"))==NULL) { + RF_ERRORMSG1("RAID: config error: Can't open layout table file %s\n",bdfile); + return(EINVAL); + } + + fgets(buf,256,fp); + i = sscanf(buf,"%u %u %u %u %u %u",&b,&v,&k,&r,&lambda,&norotate); + if (i == 5) + norotate = 0; /* no-rotate flag is optional */ + else if (i != 6) { + RF_ERRORMSG("Unable to parse header line in block design file\n"); + return(EINVAL); + } + + /* set the sparemap directory. In the in-kernel version, there's a daemon + * that's responsible for finding the sparemaps + */ + if (distSpare) { + if (rf_get_next_nonblank_line(smbuf,256,configfp,"Can't find sparemap file name in config file\n")) + return(EINVAL); + smname = rf_find_non_white(smbuf); + if (smname[strlen(smname)-1] == '\n') { + /* strip newline char */ + smname[strlen(smname)-1] = '\0'; + } + } + else { + smbuf[0] = '\0'; + smname = smbuf; + } + + /* allocate a buffer to hold the configuration info */ + cfgPtr->layoutSpecificSize = RF_SPAREMAP_NAME_LEN + 6 * sizeof(int) + b * k; + /* can't use RF_Malloc here b/c debugMem module not yet init'd */ + cfgBuf = (char *) malloc(cfgPtr->layoutSpecificSize); + cfgPtr->layoutSpecific = (void *) cfgBuf; + p = cfgBuf; + + /* install name of sparemap file */ + for (i=0; smname[i]; i++) + *p++ = smname[i]; + /* pad with zeros */ + while (i<RF_SPAREMAP_NAME_LEN) { + *p++ = '\0'; + i++; + } + + /* + * fill in the buffer with the block design parameters + * and then the block design itself + */ + *( (int *) p) = b; p += sizeof(int); + *( (int *) p) = v; p += sizeof(int); + *( (int *) p) = k; p += sizeof(int); + *( (int *) p) = r; p += sizeof(int); + *( (int *) p) = lambda; p += sizeof(int); + *( (int *) p) = norotate; p += sizeof(int); + + while (fscanf(fp,"%d",&val) == 1) + *p++ = (char) val; + fclose(fp); + if (p - cfgBuf != cfgPtr->layoutSpecificSize) { + RF_ERRORMSG2("Size mismatch creating layout specific data: is %d sb %d bytes\n",(int)(p-cfgBuf),(int)(6*sizeof(int)+b*k)); + return(EINVAL); + } + return(0); +} + + +/**************************************************************************** + * + * utilities + * + ***************************************************************************/ +#ifndef SIMULATE +/* convert a device file name to a device number */ +static unsigned int dev_name2num(s) + char *s; +{ + struct stat buf; + + if (stat(s, &buf) < 0) return(osf_dev_name2num(s)); + else return(buf.st_rdev); +} + +/* converts an osf/1 style device name to a device number. We use this + * only if the stat of the device file fails. + */ +static unsigned int osf_dev_name2num(s) + char *s; +{ + int num; + char part_ch, lun_ch; + unsigned int bus, target, lun, part, dev_major; + + dev_major = RF_SCSI_DISK_MAJOR; + if (sscanf(s,"/dev/rrz%d%c", &num, &part_ch) == 2) { + bus = num>>3; + target = num & 0x7; + part = part_ch - 'a'; + lun = 0; + } else if (sscanf(s,"/dev/rrz%c%d%c", &lun_ch, &num, &part_ch) == 3) { + bus = num>>3; + target = num & 0x7; + part = part_ch - 'a'; + lun = lun_ch - 'a' + 1; + } else { + RF_ERRORMSG1("Unable to parse disk dev file name %s\n",s); + return(-1); + } + + return( (dev_major<<20) | (bus<<14) | (target<<10) | (lun<<6) | part ); +} +#endif + +/* searches a file for a line that says "START string", where string is + * specified as a parameter + */ +static int rf_search_file_for_start_of(string, buf, len, fp) + char *string; + char *buf; + int len; + FILE *fp; +{ + char *p; + + while (1) { + if (fgets(buf, len, fp) == NULL) return(-1); + p = rf_find_non_white(buf); + if (!strncmp(p, "START", strlen("START"))) { + p = rf_find_white(p); + p = rf_find_non_white(p); + if (!strncmp(p, string, strlen(string))) return(0); + } + } +} + +/* reads from file fp into buf until it finds an interesting line */ +int rf_get_next_nonblank_line(buf, len, fp, errmsg) + char *buf; + int len; + FILE *fp; + char *errmsg; +{ + char *p; + + while (fgets(buf,256,fp) != NULL) { + p = rf_find_non_white(buf); + if (*p == '\n' || *p == '\0' || *p == '#') continue; + return(0); + } + if (errmsg) RF_ERRORMSG(errmsg); + return(1); +} + +/* Allocates an array for the spare table, and initializes it from a file. + * In the user-level version, this is called when recon is initiated. + * When/if I move recon into the kernel, there'll be a daemon that does + * an ioctl into raidframe which will block until a spare table is needed. + * When it returns, it will read a spare table from the file system, + * pass it into the kernel via a different ioctl, and then block again + * on the original ioctl. + * + * This is specific to the declustered layout, but doesn't belong in + * rf_decluster.c because it uses stuff that can't be compiled into + * the kernel, and it needs to be compiled into the user-level sparemap daemon. + * + */ +void *rf_ReadSpareTable(req, fname) + RF_SparetWait_t *req; + char *fname; +{ + int i, j, numFound, linecount, tableNum, tupleNum, spareDisk, spareBlkOffset; + char buf[1024], targString[100], errString[100]; + RF_SpareTableEntry_t **table; + FILE *fp; + + /* allocate and initialize the table */ + RF_Malloc(table, req->TablesPerSpareRegion * sizeof(RF_SpareTableEntry_t *), (RF_SpareTableEntry_t **)); + for (i=0; i<req->TablesPerSpareRegion; i++) { + RF_Malloc(table[i], req->BlocksPerTable * sizeof(RF_SpareTableEntry_t), (RF_SpareTableEntry_t *)); + for (j=0; j<req->BlocksPerTable; j++) table[i][j].spareDisk = table[i][j].spareBlockOffsetInSUs = -1; + } + + /* 2. open sparemap file, sanity check */ + if ((fp = fopen(fname,"r"))==NULL) { + fprintf(stderr,"rf_ReadSpareTable: Can't open sparemap file %s\n",fname); return(NULL); + } + if (rf_get_next_nonblank_line(buf,1024,fp,"Invalid sparemap file: can't find header line\n")) + return(NULL); + if (buf[strlen(buf)-1] == '\n') + buf[strlen(buf)-1] = '\0'; + + sprintf(targString, "fdisk %d\n", req->fcol); + sprintf(errString, "Invalid sparemap file: can't find \"fdisk %d\" line\n",req->fcol); + while (1) { + rf_get_next_nonblank_line(buf,1024,fp,errString); + if (!strncmp(buf,targString,strlen(targString))) break; + } + + /* no more blank lines or comments allowed now */ + linecount = req->TablesPerSpareRegion * req->TableDepthInPUs; + for (i=0; i<linecount; i++) { + numFound = fscanf(fp," %d %d %d %d",&tableNum, &tupleNum, &spareDisk, &spareBlkOffset); + if (numFound != 4) { + fprintf(stderr,"Sparemap file prematurely exhausted after %d of %d lines\n",i,linecount); return(NULL); + } + RF_ASSERT(tableNum >= 0 && tableNum < req->TablesPerSpareRegion); + RF_ASSERT(tupleNum >= 0 && tupleNum < req->BlocksPerTable); + RF_ASSERT(spareDisk >= 0 && spareDisk < req->C); + RF_ASSERT(spareBlkOffset >= 0 && spareBlkOffset < req->SpareSpaceDepthPerRegionInSUs / req->SUsPerPU); + + table[tableNum][tupleNum].spareDisk = spareDisk; + table[tableNum][tupleNum].spareBlockOffsetInSUs = spareBlkOffset * req->SUsPerPU; + } + + fclose(fp); + return((void *) table); +} diff --git a/sbin/raidctl/rf_utility.c b/sbin/raidctl/rf_utility.c new file mode 100644 index 00000000000..f2e816ab0aa --- /dev/null +++ b/sbin/raidctl/rf_utility.c @@ -0,0 +1,62 @@ +/* $OpenBSD: rf_utility.c,v 1.1 1999/01/11 14:49:45 niklas Exp $ */ + +/* + * rf_utility.c + */ +/* + * Copyright (c) 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Jim Zelenka + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * define symbols for raidframe utils which share .c files with + * raidframe proper + */ + +#include "rf_utility.h" + +#ifdef RF_DBG_OPTION +#undef RF_DBG_OPTION +#endif /* RF_DBG_OPTION */ + +#ifdef __STDC__ +#define RF_DBG_OPTION(_option_,_defval_) long rf_##_option_ = _defval_; +#else /* __STDC__ */ +#define RF_DBG_OPTION(_option_,_defval_) long rf_/**/_option_ = _defval_; +#endif /* __STDC__ */ +#include "rf_optnames.h" + +int rf_mutex_init(m) + int *m; +{ + *m = 0; + return(0); +} + +int rf_mutex_destroy(m) + int *m; +{ + *m = 0; + return(0); +} diff --git a/sbin/raidctl/rf_utility.h b/sbin/raidctl/rf_utility.h new file mode 100644 index 00000000000..c4baca55f92 --- /dev/null +++ b/sbin/raidctl/rf_utility.h @@ -0,0 +1,50 @@ +/* $OpenBSD: rf_utility.h,v 1.1 1999/01/11 14:49:45 niklas Exp $ */ + +/* + * rf_utility.h + */ +/* + * Copyright (c) 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Jim Zelenka + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * defs for raidframe utils which share .c files with + * raidframe proper + */ + +#ifndef _RF__RF_UTILITY_H_ +#define _RF__RF_UTILITY_H_ + +#include "rf_options.h" + +#define rf_create_managed_mutex(a,b) 0 +#define rf_create_managed_cond(a,b) 0 + +#define RF_DECLARE_MUTEX(m) int m; +#define RF_DECLARE_EXTERN_MUTEX(m) extern int m; +#define RF_LOCK_MUTEX(m) +#define RF_UNLOCK_MUTEX(m) + +#endif /* !_RF__RF_UTILITY_H_ */ |