summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsing <jsing@openbsd.org>2012-04-06 15:54:58 +0000
committerjsing <jsing@openbsd.org>2012-04-06 15:54:58 +0000
commit6406431261af96919fb0f8deae2a702549813711 (patch)
treef53ebbd80909a611b956bdf1ced60344421a6ba6
parentPut raidframe in the attic. (diff)
downloadwireguard-openbsd-6406431261af96919fb0f8deae2a702549813711.tar.xz
wireguard-openbsd-6406431261af96919fb0f8deae2a702549813711.zip
Put raidctl in the attic.
-rw-r--r--sbin/raidctl/Makefile17
-rw-r--r--sbin/raidctl/raidctl.81390
-rw-r--r--sbin/raidctl/raidctl.c1232
-rw-r--r--sbin/raidctl/rf_configure.c558
4 files changed, 0 insertions, 3197 deletions
diff --git a/sbin/raidctl/Makefile b/sbin/raidctl/Makefile
deleted file mode 100644
index 25b3c163f95..00000000000
--- a/sbin/raidctl/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-# $OpenBSD: Makefile,v 1.7 2002/06/09 08:13:09 todd Exp $
-# $NetBSD: Makefile,v 1.8 2001/01/27 19:32:47 oster Exp $
-PROG= raidctl
-SRCS= rf_configure.c raidctl.c
-MAN= raidctl.8
-
-WARNS=2
-
-LOOKHERE = ${.CURDIR}/../../sys/dev/raidframe
-
-CPPFLAGS+= -DRF_UTILITY=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
deleted file mode 100644
index 6673acc99b9..00000000000
--- a/sbin/raidctl/raidctl.8
+++ /dev/null
@@ -1,1390 +0,0 @@
-.\" $OpenBSD: raidctl.8,v 1.43 2011/10/06 22:22:10 jmc Exp $
-.\" $NetBSD: raidctl.8,v 1.24 2001/07/10 01:30:52 lukem 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.
-.\"
-.\" 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 $Mdocdate: October 6 2011 $
-.Dt RAIDCTL 8
-.Os
-.Sh NAME
-.Nm raidctl
-.Nd configuration utility for the RAIDframe disk driver
-.Sh SYNOPSIS
-.Nm raidctl
-.Bk -words
-.Op Fl BGiPpSsuv
-.Op Fl A Op yes | no | root
-.Op Fl Cc Ar config_file
-.Op Fl I Ar serial_number
-.Op Fl aFfgRr Ar component
-.Ar dev
-.Ek
-.Sh DESCRIPTION
-.Nm
-is the user-land control program for
-.Xr raid 4 ,
-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 device used by
-.Nm
-is specified by
-.Ar dev .
-.Ar dev
-may be either the full name of the device, e.g.\&
-.Pa /dev/rraid0c ,
-or just simply raid0 (for
-.Pa /dev/rraid0c ) .
-.Pp
-For several commands
-.Pq Fl BGipPsSu ,
-.Nm
-can accept the word
-.Ic all
-as the
-.Ar dev
-argument.
-If
-.Ic all
-is used,
-.Nm
-will execute the requested action for all the configured
-.Xr raid 4
-devices.
-.Pp
-The command-line options for
-.Nm
-are as follows:
-.Bl -tag -width indent
-.It Fl A Ic yes Ar dev
-Make the RAID set auto-configurable.
-The RAID set will be automatically configured at boot
-.Em before
-the root file system is
-mounted.
-Note that all components of the set must be of type RAID in the disklabel.
-.It Fl A Ic no Ar dev
-Turn off auto-configuration for the RAID set.
-.It Fl A Ic root Ar dev
-Make the RAID set auto-configurable, and also mark the set as being
-eligible to contain the root partition.
-A RAID set configured this way will
-.Em override
-the use of the boot disk as the root device.
-All components of the set must be of type RAID in the disklabel.
-Note that the kernel being booted must currently reside on a non-RAID set and,
-in order to have the root file system correctly mounted from it,
-the RAID set must have its
-.Sq a
-partition (aka raid[0..n]a) set up.
-.It Fl a Ar component Ar dev
-Add
-.Ar component
-as a hot spare for the device
-.Ar dev .
-.It Fl B Ar dev
-Initiate a copyback of reconstructed data from a spare disk to
-its original disk.
-This is performed after a component has failed,
-and the failed drive has been reconstructed onto a spare drive.
-.It Fl C Ar config_file Ar dev
-As for
-.Fl c ,
-but forces the configuration to take place.
-This is required the first time a RAID set is configured.
-.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 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 one of the mechanisms used to start the reconstruction process
-if a component does have a hardware failure.
-.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 G Ar dev
-Generate the configuration of the RAIDframe device in a format suitable for
-use with
-.Nm
-.Fl c
-or
-.Fl C .
-.It Fl g Ar component Ar dev
-Get the component label for the specified component.
-.It Fl I Ar serial_number Ar dev
-Initialize the component labels on each component of the device.
-.Ar serial_number
-is used as one of the keys in determining whether a
-particular set of components belong to the same RAID set.
-While not strictly enforced, different serial numbers should be used for
-different RAID sets.
-This step
-.Em MUST
-be performed when a new RAID set is created.
-.It Fl i Ar dev
-Initialize the RAID device.
-In particular, (re-write) the parity on the selected device.
-This
-.Em MUST
-be done for
-.Em all
-RAID sets before the RAID device is labeled and before
-file systems are created on the RAID device.
-.It Fl P Ar dev
-Check the status of the parity on the RAID set, and initialize
-(re-write) the parity if the parity is not known to be up-to-date.
-This is normally used after a system crash (and before a
-.Xr fsck 8 )
-to ensure the integrity of the parity.
-.It Fl p Ar dev
-Check the status of the parity on the RAID set.
-Displays a status message, and returns successfully if the parity
-is up-to-date.
-.It Fl R Ar component Ar dev
-Fails the specified
-.Ar component ,
-if necessary, and immediately begins a reconstruction back to
-.Ar component .
-This is useful for reconstructing back onto a component after
-it has been replaced following a failure.
-.It Fl r Ar component Ar dev
-Remove the spare disk specified by
-.Ar component
-from the set of available spare components.
-.It Fl S Ar dev
-Check the status of parity re-writing, component reconstruction, and
-component copyback.
-The output indicates the amount of progress achieved in each of these areas.
-.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.
-.It Fl v
-Be more verbose.
-For operations such as reconstructions, parity re-writing,
-and copybacks, provide a progress indicator.
-.El
-.Ss Configuration file
-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 sections.
-Each section begins with a
-.Sq START ,
-followed by
-the section name, and the configuration 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 set.
-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 although multi-dimensional arrays may be specified, they are
-.Em 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
-.Em 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 will result in data loss if the set
-is configured with the
-.Fl C
-option.
-In normal circumstances, the RAID set will not configure if only
-.Fl c
-is specified, and the components are out-of-order.
-.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 omitted.
-.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.
-The parity is the mirror.
-.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 100
-.Ed
-.Pp
-where the queuing method is specified as FIFO (First-In, First-Out),
-and the size of the per-component queue is limited to 100 requests.
-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 discussed in the
-.Sx HISTORY
-section.
-See
-.Sx EXAMPLES
-for a more complete configuration file example.
-.Sh EXAMPLES
-It is highly recommended that before using the RAID driver for real
-file systems that the system administrator(s) become quite familiar
-with the use of
-.Nm raidctl ,
-and that they understand how the component reconstruction process
-works.
-The examples in this section will focus on configuring a
-number of different RAID sets of varying degrees of redundancy.
-By working through these examples, administrators should be able to
-develop a good feel for how to configure a RAID set, and how to
-initiate reconstruction of failed components.
-.Pp
-In the following examples
-.Sq raid0
-will be used to denote the RAID device.
-.Sq Pa /dev/rraid0c
-may be used in place of
-.Sq raid0 .
-.Ss Initialization and Configuration
-The initial step in configuring a RAID set is to identify the components
-that will be used in the RAID set.
-All components should be the same size.
-Each component should have a disklabel type of
-.Dv FS_RAID ,
-and a typical disklabel entry for a RAID component might look like:
-.Bd -unfilled -offset indent
-f: 1800000 200495 RAID # (Cyl. 405*- 4041*)
-.Ed
-.Pp
-While
-.Dv FS_BSDFFS
-(e.g. 4.2BSD) will also work as the component type, the type
-.Dv FS_RAID
-(e.g. RAID) is preferred for RAIDframe use, as it is required for
-features such as auto-configuration.
-As part of the initial configuration of each RAID set, each component
-will be given a
-.Sq component label .
-A
-.Sq component label
-contains important information about the component, including a
-user-specified serial number, the row and column of that component in
-the RAID set, the redundancy level of the RAID set, a 'modification
-counter', and whether the parity information (if any) on that
-component is known to be correct.
-Component labels are an integral part of the RAID set, since they are used
-to ensure that components are configured in the correct order, and used
-to keep track of other vital information about the RAID set.
-Component labels are also required for the auto-detection and
-auto-configuration of RAID sets at boot time.
-For a component label to be considered valid, that particular component label
-must be in agreement with the other component labels in the set.
-For example, the serial number,
-.Sq modification counter ,
-number of rows and number of columns must all
-be in agreement.
-If any of these are different, then the component is not considered to be
-part of the set.
-See
-.Xr raid 4
-for more information about component labels.
-.Pp
-Once the components have been identified, and the disks have
-appropriate labels,
-.Nm
-is then used to configure the
-.Xr raid 4
-device.
-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 created in a file.
-The above configuration file specifies a RAID 5 set consisting of
-the components
-.Pa /dev/sd1e , /dev/sd2e ,
-and
-.Pa /dev/sd3e ,
-with
-.Pa /dev/sd4e
-available as a
-.Sq hot spare
-in case one of
-the three main drives should fail.
-A RAID 0 set would be specified in a similar way:
-.Bd -unfilled -offset indent
-START array
-# numRow numCol numSpare
-1 4 0
-
-START disks
-/dev/sd10e
-/dev/sd11e
-/dev/sd12e
-/dev/sd13e
-
-START layout
-# sectPerSU SUsPerParityUnit SUsPerReconUnit RAID_level_0
-64 1 1 0
-
-START queue
-fifo 100
-.Ed
-.Pp
-In this case, devices
-.Pa /dev/sd10e , /dev/sd11e , /dev/sd12e ,
-and
-.Pa /dev/sd13e
-are the components that make up this RAID set.
-Note that there are no hot spares for a RAID 0 set, since there is no way
-to recover data if any of the components fail.
-.Pp
-For a RAID 1 (mirror) set, the following configuration might be used:
-.Bd -unfilled -offset indent
-START array
-# numRow numCol numSpare
-1 2 0
-
-START disks
-/dev/sd20e
-/dev/sd21e
-
-START layout
-# sectPerSU SUsPerParityUnit SUsPerReconUnit RAID_level_1
-128 1 1 1
-
-START queue
-fifo 100
-.Ed
-.Pp
-In this case,
-.Pa /dev/sd20e
-and
-.Pa /dev/sd21e
-are the two components of the
-mirror set.
-While no hot spares have been specified in this configuration,
-they easily could be, just as they were specified in the RAID 5 case above.
-Note as well that RAID 1 sets are currently limited to only 2 components.
-At present, n-way mirroring is not possible.
-.Pp
-The first time a RAID set is configured, the
-.Fl C
-option must be used:
-.Bd -unfilled -offset indent
-# raidctl -C raid0.conf raid0
-.Ed
-.Pp
-where
-.Sq raid0.conf
-is the name of the RAID configuration file.
-The
-.Fl C
-forces the configuration to succeed, even if any of the component
-labels are incorrect.
-The
-.Fl C
-option should not be used lightly in
-situations other than initial configurations, as if
-the system is refusing to configure a RAID set, there is probably a
-very good reason for it.
-After the initial configuration is done (and appropriate component labels
-are added with the
-.Fl I
-option) then raid0 can be configured normally with:
-.Bd -unfilled -offset indent
-# raidctl -c raid0.conf raid0
-.Ed
-.Pp
-When the RAID set is configured for the first time, it is
-necessary to initialize the component labels, and to initialize the
-parity on the RAID set.
-Initializing the component labels is done with:
-.Bd -unfilled -offset indent
-# raidctl -I 112341 raid0
-.Ed
-.Pp
-where
-.Sq 112341
-is a user-specified serial number for the RAID set.
-This initialization step is
-.Em required
-for all RAID sets.
-Also, using different serial numbers between RAID sets is
-.Em strongly encouraged ,
-as using the same serial number for all RAID sets will only serve to
-decrease the usefulness of the component label checking.
-.Pp
-Initializing the RAID set is done via the
-.Fl i
-option.
-This initialization
-.Em MUST
-be done for
-.Em all
-RAID sets, since among other things it verifies that the parity (if
-any) on the RAID set is correct.
-Since this initialization may be quite time-consuming, the
-.Fl v
-option may be also used in conjunction with
-.Fl i :
-.Bd -unfilled -offset indent
-# raidctl -iv raid0
-.Ed
-.Pp
-This will give more verbose output on the
-status of the initialization:
-.Bd -unfilled -offset indent
-Initiating re-write of parity
-Parity Re-write status:
- 10% |**** | ETA: 06:03 /
-.Ed
-.Pp
-The output provides a
-.Sq Percent Complete
-in both a numeric and graphical format, as well as an estimated time
-to completion of the operation.
-.Pp
-Since it is the parity that provides the
-.Sq redundancy
-part of RAID, it is critical that the parity is correct
-as much as possible.
-If the parity is not correct, then there is no guarantee that data will not
-be lost if a component fails.
-.Pp
-Once the parity is known to be correct, it is then safe to perform
-.Xr disklabel 8 ,
-.Xr newfs 8 ,
-or
-.Xr fsck 8
-on the device or its filesystems, and then to mount the filesystems
-for use.
-.Pp
-Under certain circumstances (e.g. the additional component has not
-arrived, or data is being migrated off of a disk destined to become a
-component) it may be desirable to configure a RAID 1 set with only
-a single component.
-This can be achieved by configuring the set with a physically existing
-component (as either the first or second component) and with a
-.Sq fake
-component.
-In the following:
-.Bd -unfilled -offset indent
-START array
-# numRow numCol numSpare
-1 2 0
-
-START disks
-/dev/sd6e
-/dev/sd0e
-
-START layout
-# sectPerSU SUsPerParityUnit SUsPerReconUnit RAID_level_1
-128 1 1 1
-
-START queue
-fifo 100
-.Ed
-.Pp
-.Pa /dev/sd0e
-is the real component, and will be the second disk of a RAID 1
-set.
-The component
-.Pa /dev/sd6e ,
-which must exist, but have no physical
-device associated with it, is simply used as a placeholder.
-Configuration (using
-.Fl C
-and
-.Fl I Ar 12345
-as above) proceeds normally, but initialization of the RAID set will
-have to wait until all physical components are present.
-After configuration, this set can be used normally, but will be operating
-in degraded mode.
-Once a second physical component is obtained, it can be hot-added,
-the existing data mirrored, and normal operation resumed.
-.Ss Maintenance of the RAID set
-After the parity has been initialized for the first time, the command:
-.Bd -unfilled -offset indent
-# raidctl -p raid0
-.Ed
-.Pp
-can be used to check the current status of the parity.
-To check the parity and rebuild it necessary (for example, after an unclean
-shutdown) the command:
-.Bd -unfilled -offset indent
-# raidctl -P raid0
-.Ed
-.Pp
-is used.
-Note that re-writing the parity can be done while other operations on the
-RAID set are taking place (e.g. while doing an
-.Xr fsck 8
-on a file system on the RAID set).
-However: for maximum effectiveness of the RAID set, the parity should be
-known to be correct before any data on the set is modified.
-.Pp
-To see how the RAID set is doing, the following command can be used to
-show the RAID set's 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: spare
-Parity status: clean
-Reconstruction is 100% complete.
-Parity Re-write is 100% complete.
-Copyback is 100% complete.
-.Ed
-.Pp
-This indicates that all is well with the RAID set.
-Of importance here are the component lines which read
-.Sq optimal ,
-and the
-.Sq Parity status
-line which indicates that the parity is up-to-date.
-Note that if there are file systems open on the RAID set,
-the individual components will not be
-.Sq clean
-but the set as a whole can still be clean.
-.Pp
-The
-.Fl v
-option may be also used in conjunction with
-.Fl s :
-.Bd -unfilled -offset indent
-# raidctl -sv raid0
-.Ed
-.Pp
-In this case, the components' label information (see the
-.Fl g
-option) will be given as well:
-.Bd -unfilled -offset indent
-Components:
- /dev/sd1e: optimal
- /dev/sd2e: optimal
- /dev/sd3e: optimal
-Spares:
- /dev/sd4e: spare
-Component label for /dev/sd1e:
- Row: 0 Column: 0 Num Rows: 1 Num Columns: 3
- Version: 2 Serial Number: 13432 Mod Counter: 65
- Clean: No Status: 0
- sectPerSU: 32 SUsPerPU: 1 SUsPerRU: 1
- RAID Level: 5 blocksize: 512 numBlocks: 1799936
- Autoconfig: No
- Last configured as: raid0
-Component label for /dev/sd2e:
- Row: 0 Column: 1 Num Rows: 1 Num Columns: 3
- Version: 2 Serial Number: 13432 Mod Counter: 65
- Clean: No Status: 0
- sectPerSU: 32 SUsPerPU: 1 SUsPerRU: 1
- RAID Level: 5 blocksize: 512 numBlocks: 1799936
- Autoconfig: No
- Last configured as: raid0
-Component label for /dev/sd3e:
- Row: 0 Column: 2 Num Rows: 1 Num Columns: 3
- Version: 2 Serial Number: 13432 Mod Counter: 65
- Clean: No Status: 0
- sectPerSU: 32 SUsPerPU: 1 SUsPerRU: 1
- RAID Level: 5 blocksize: 512 numBlocks: 1799936
- Autoconfig: No
- Last configured as: raid0
-Parity status: clean
-Reconstruction is 100% complete.
-Parity Re-write is 100% complete.
-Copyback is 100% complete.
-.Ed
-.Pp
-To check the component label of /dev/sd1e, the following is used:
-.Bd -unfilled -offset indent
-# raidctl -g /dev/sd1e raid0
-.Ed
-.Pp
-The output of this command will look something like:
-.Bd -unfilled -offset indent
-Component label for /dev/sd1e:
- Row: 0 Column: 0 Num Rows: 1 Num Columns: 3
- Version: 2 Serial Number: 13432 Mod Counter: 65
- Clean: No Status: 0
- sectPerSU: 32 SUsPerPU: 1 SUsPerRU: 1
- RAID Level: 5 blocksize: 512 numBlocks: 1799936
- Autoconfig: No
- Last configured as: raid0
-.Ed
-.Ss Dealing with Component Failures
-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,
-where missing data is re-computed from existing data and the parity.
-In this case, obtaining the status of raid0 will return (in part):
-.Bd -unfilled -offset indent
-Components:
- /dev/sd1e: optimal
- /dev/sd2e: failed
- /dev/sd3e: optimal
-Spares:
- /dev/sd4e: 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:
-.Bd -unfilled -offset indent
-# raidctl -F /dev/sd2e raid0
-.Ed
-.Pp
-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: used_spare
-[...]
-Parity status: clean
-Reconstruction is 10% complete.
-Parity Re-write is 100% complete.
-Copyback is 100% complete.
-.Ed
-.Pp
-This indicates that a reconstruction is in progress.
-To find out how the reconstruction is progressing the
-.Fl S
-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: used_spare
-[...]
-Parity status: clean
-Reconstruction is 100% complete.
-Parity Re-write is 100% complete.
-Copyback is 100% complete.
-.Ed
-.Pp
-At this point there are at least two options.
-First, if
-.Pa /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 B
-option.
-In this example, this would copy the entire contents of
-.Pa /dev/sd4e
-to
-.Pa /dev/sd2e .
-Once the copyback procedure is complete, the
-status of the device would be (in part):
-.Bd -unfilled -offset indent
-Components:
- /dev/sd1e: optimal
- /dev/sd2e: optimal
- /dev/sd3e: optimal
-Spares:
- /dev/sd4e: spare
-.Ed
-.Pp
-and the system is back to normal operation.
-.Pp
-The second option after the reconstruction is to simply use
-.Pa /dev/sd4e
-in place of
-.Pa /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
-.Pa /dev/sd4e
-is completely interchangeable with
-.Pa /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
-.Em never
-be changed.
-.Pp
-If a component fails and there are no hot spares
-available on-line, the status of the RAID set might (in part) look like:
-.Bd -unfilled -offset indent
-Components:
- /dev/sd1e: optimal
- /dev/sd2e: failed
- /dev/sd3e: optimal
-No spares.
-.Ed
-.Pp
-In this case there are a number of options.
-The first option is to add a hot spare using:
-.Bd -unfilled -offset indent
-# raidctl -a /dev/sd4e raid0
-.Ed
-.Pp
-After the hot add, the status would then be:
-.Bd -unfilled -offset indent
-Components:
- /dev/sd1e: optimal
- /dev/sd2e: failed
- /dev/sd3e: optimal
-Spares:
- /dev/sd4e: spare
-.Ed
-.Pp
-Reconstruction could then take place using
-.Fl F
-as describe above.
-.Pp
-A second option is to rebuild directly onto
-.Pa /dev/sd2e .
-Once the disk containing
-.Pa /dev/sd2e
-has been replaced, one can simply use:
-.Bd -unfilled -offset indent
-# raidctl -R /dev/sd2e raid0
-.Ed
-.Pp
-to rebuild the
-.Pa /dev/sd2e
-component.
-As the rebuilding is in progress, the status will be:
-.Bd -unfilled -offset indent
-Components:
- /dev/sd1e: optimal
- /dev/sd2e: reconstructing
- /dev/sd3e: optimal
-No spares.
-.Ed
-.Pp
-and when completed, will be:
-.Bd -unfilled -offset indent
-Components:
- /dev/sd1e: optimal
- /dev/sd2e: optimal
- /dev/sd3e: optimal
-No spares.
-.Ed
-.Pp
-In circumstances where a particular component is completely
-unavailable after a reboot, a special component name will be used to
-indicate the missing component.
-For example:
-.Bd -unfilled -offset indent
-Components:
- /dev/sd2e: optimal
- component1: failed
-No spares.
-.Ed
-.Pp
-indicates that the second component of this RAID set was not detected
-at all by the auto-configuration code.
-The name
-.Sq component1
-can be used anywhere a normal component name would be used.
-For example, to add a hot spare to the above set, and rebuild to that hot
-spare, the following could be done:
-.Bd -unfilled -offset indent
-# raidctl -a /dev/sd3e raid0
-# raidctl -F component1 raid0
-.Ed
-.Pp
-at which point the data missing from
-.Sq component1
-would be reconstructed onto
-.Pa /dev/sd3e .
-.Ss RAID on RAID
-RAID sets can be layered to create more complex and much larger RAID
-sets.
-A RAID 0 set, for example, could be constructed from four RAID 5 sets.
-The following configuration file shows such a setup:
-.Bd -unfilled -offset indent
-START array
-# numRow numCol numSpare
-1 4 0
-
-START disks
-/dev/raid1e
-/dev/raid2e
-/dev/raid3e
-/dev/raid4e
-
-START layout
-# sectPerSU SUsPerParityUnit SUsPerReconUnit RAID_level_0
-128 1 1 0
-
-START queue
-fifo 100
-.Ed
-.Pp
-A similar configuration file might be used for a RAID 0 set
-constructed from components on RAID 1 sets.
-In such a configuration, the mirroring provides a high degree of redundancy,
-while the striping provides additional speed benefits.
-.Ss Auto-configuration and Root on RAID
-RAID sets can also be auto-configured at boot.
-To make a set auto-configurable, simply prepare the RAID set as above,
-and then do a:
-.Pp
-.Dl # raidctl -A yes raid0
-.Pp
-to turn on auto-configuration for that set.
-To turn off auto-configuration, use:
-.Pp
-.Dl # raidctl -A no raid0
-.Pp
-RAID sets which are auto-configurable will be configured before the
-root file system is mounted.
-These RAID sets are thus available for use as a root file system,
-or for any other file system.
-A primary advantage of using the auto-configuration is that RAID components
-become more independent of the disks they reside on.
-For example, SCSI ID's can change, but auto-configured sets will always be
-configured correctly, even if the SCSI ID's of the component disks
-have become scrambled.
-.Pp
-Having a system's root file system
-.Pq Pa /
-on a RAID set is also allowed,
-with the
-.Sq a
-partition of such a RAID set being used for
-.Pa / .
-To use raid0a as the root file system, simply use:
-.Bd -unfilled -offset indent
-# raidctl -A root raid0
-.Ed
-.Pp
-To return raid0 to be just an auto-configuring set simply use the
-.Fl A Ar yes
-arguments.
-.Pp
-.\" Note that kernels can only be directly read from RAID 1 components on
-.\" alpha and pmax architectures.
-.\" On those architectures, the
-.\" .Dv FS_RAID
-.\" file system is recognized by the bootblocks, and will properly load the
-.\" kernel directly from a RAID 1 component.
-.\" For other architectures, or
-Note that kernels can't be directly read from a RAID component.
-To support the root file system on RAID sets, some mechanism must be
-used to get a kernel booting.
-For example, a small partition containing only the secondary boot-blocks
-and an alternate kernel (or two) could be used.
-Once a kernel is booting however, and an auto-configured RAID
-set is found that is eligible to be root, then that RAID set will be
-auto-configured and its
-.Sq a
-partition (aka raid[0..n]a) will be used as the root file system.
-If two or more RAID sets claim to be root devices, then the user will be
-prompted to select the root device.
-At this time, RAID 0, 1, 4, and 5 sets are all supported as root devices.
-.Pp
-A typical RAID 1 setup with root on RAID might be as follows:
-.Bl -enum
-.It
-wd0a - a small partition, which contains a complete, bootable, basic
-.Ox
-installation.
-.It
-wd1a - also contains a complete, bootable, basic
-.Ox
-installation.
-.It
-wd0e and wd1e - a RAID 1 set, raid0, used for the root file system.
-.It
-wd0f and wd1f - a RAID 1 set, raid1, which will be used only for
-swap space.
-.It
-wd0g and wd1g - a RAID 1 set, raid2, used for
-.Pa /usr ,
-.Pa /home ,
-or other data, if desired.
-.It
-wd0h and wd1h - a RAID 1 set, raid3, if desired.
-.El
-.Pp
-RAID sets raid0, raid1, and raid2 are all marked as
-auto-configurable.
-raid0 is marked as being a root-able raid.
-When new kernels are installed, the kernel is not only copied to
-.Pa / ,
-but also to wd0a and wd1a.
-The kernel on wd0a is required, since that is the kernel the system
-boots from.
-The kernel on wd1a is also required, since that will be the kernel used
-should wd0 fail.
-The important point here is to have redundant copies of the kernel
-available, in the event that one of the drives fail.
-.Pp
-There is no requirement that the root file system be on the same disk
-as the kernel.
-For example, obtaining the kernel from wd0a, and using
-sd0e and sd1e for raid0, and the root file system, is fine.
-It
-.Em is
-critical, however, that there be multiple kernels available, in the
-event of media failure.
-.Pp
-Multi-layered RAID devices (such as a RAID 0 set made
-up of RAID 1 sets) are
-.Em not
-supported as root devices or auto-configurable devices at this point.
-(Multi-layered RAID devices
-.Em are
-supported in general, however, as mentioned earlier.)
-Note that in
-order to enable component auto-detection and auto-configuration of
-RAID devices, the line:
-.Bd -unfilled -offset indent
-option RAID_AUTOCONFIG
-.Ed
-.Pp
-must be in the kernel configuration file.
-See
-.Xr raid 4
-for more details.
-.Ss Unconfiguration
-The final operation performed by
-.Nm
-is to unconfigure a
-.Xr raid 4
-device.
-This is accomplished via a simple:
-.Pp
-.Dl # raidctl -u raid0
-.Pp
-at which point the device is ready to be reconfigured.
-.Ss Performance Tuning
-Selection of the various parameter values which result in the best
-performance can be quite tricky, and often requires a bit of
-trial-and-error to get those values most appropriate for a given system.
-A whole range of factors come into play, including:
-.Bl -enum
-.It
-Types of components (e.g. SCSI vs. IDE) and their bandwidth
-.It
-Types of controller cards and their bandwidth
-.It
-Distribution of components among controllers
-.It
-I/O bandwidth
-.It
-File system access patterns
-.It
-CPU speed
-.El
-.Pp
-As with most performance tuning, benchmarking under real-life loads
-may be the only way to measure expected performance.
-Understanding some of the underlying technology is also useful in tuning.
-The goal of this section is to provide pointers to those parameters which may
-make significant differences in performance.
-.Pp
-For a RAID 1 set, a SectPerSU value of 64 or 128 is typically sufficient.
-Since data in a RAID 1 set is arranged in a linear
-fashion on each component, selecting an appropriate stripe size is
-somewhat less critical than it is for a RAID 5 set.
-However: a stripe size that is too small will cause large I/Os to be
-broken up into a number of smaller ones, hurting performance.
-At the same time, a large stripe size may cause problems with concurrent
-accesses to stripes, which may also affect performance.
-Thus values in the range of 32 to 128 are often the most effective.
-.Pp
-Tuning RAID 5 sets is trickier.
-In the best case, I/O is presented to the RAID set one stripe at a time.
-Since the entire stripe is available at the beginning of the I/O,
-the parity of that stripe can be calculated before the stripe is written,
-and then the stripe data and parity can be written in parallel.
-When the amount of data being written is less than a full stripe worth, the
-.Sq small write
-problem occurs.
-Since a
-.Sq small write
-means only a portion of the stripe on the components is going to
-change, the data (and parity) on the components must be updated
-slightly differently.
-First, the
-.Sq old parity
-and
-.Sq old data
-must be read from the components.
-Then the new parity is constructed, using the new data to be written,
-and the old data and old parity.
-Finally, the new data and new parity are written.
-All this extra data shuffling results in a serious loss of performance,
-and is typically 2 to 4 times slower than a full stripe write (or read).
-To combat this problem in the real world, it may be useful to ensure that
-stripe sizes are small enough that a
-.Sq large I/O
-from the system will use exactly one large stripe write.
-As is seen later, there are some file system dependencies which may come
-into play here as well.
-.Pp
-Since the size of a
-.Sq large I/O
-is often (currently) only 32K or 64K, on a 5-drive RAID 5 set it may
-be desirable to select a SectPerSU value of 16 blocks (8K) or 32
-blocks (16K).
-Since there are 4 data sectors per stripe, the maximum
-data per stripe is 64 blocks (32K) or 128 blocks (64K).
-Again, empirical measurement will provide the best indicators of which
-values will yield better performance.
-.Pp
-The parameters used for the file system are also critical to good
-performance.
-For
-.Xr newfs 8 ,
-for example, increasing the block size to 32K or 64K may improve
-performance dramatically.
-Also, changing the cylinders-per-group parameter from 16 to 32 or higher
-is often not only necessary for larger file systems, but may also have
-positive performance implications.
-.Ss Summary
-Despite the length of this man-page, configuring a RAID set is a
-relatively straight-forward process.
-All that needs to be done is the following steps:
-.Bl -enum
-.It
-Use
-.Xr disklabel 8
-to create the components (of type RAID).
-.It
-Construct a RAID configuration file: e.g.\&
-.Sq raid0.conf
-.It
-Configure the RAID set with:
-.Bd -unfilled -offset indent
-# raidctl -C raid0.conf raid0
-.Ed
-.Pp
-.It
-Initialize the component labels with:
-.Bd -unfilled -offset indent
-# raidctl -I 123456 raid0
-.Ed
-.Pp
-.It
-Initialize other important parts of the set with:
-.Bd -unfilled -offset indent
-# raidctl -i raid0
-.Ed
-.Pp
-.It
-Get the default label for the RAID set:
-.Bd -unfilled -offset indent
-# disklabel raid0 > /tmp/label
-.Ed
-.Pp
-.It
-Edit the label:
-.Bd -unfilled -offset indent
-# vi /tmp/label
-.Ed
-.Pp
-.It
-Put the new label on the RAID set:
-.Bd -unfilled -offset indent
-# disklabel -R raid0 /tmp/label
-.Ed
-.Pp
-.It
-Create the file system:
-.Bd -unfilled -offset indent
-# newfs /dev/rraid0e
-.Ed
-.Pp
-.It
-Mount the file system:
-.Bd -unfilled -offset indent
-# mount /dev/raid0e /mnt
-.Ed
-.Pp
-.It
-Use:
-.Bd -unfilled -offset indent
-# raidctl -c raid0.conf raid0
-.Ed
-.Pp
-to re-configure the RAID set the next time it is needed, or put
-raid0.conf into
-.Pa /etc
-where it will automatically be started by the
-.Pa /etc/rc
-scripts.
-.El
-.Sh FILES
-.Bl -tag -width "/etc/raid[0-3].conf" -compact
-.It Pa /dev/{,r}raid*
-.Cm raid
-device special files.
-.It Pa /etc/raid[0-3].conf
-Files used by
-.Xr rc 8
-to configure arrays at startup.
-.El
-.Sh SEE ALSO
-.Xr raid 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
-from where it was ported to
-.Ox 2.5 .
-.Sh CAVEATS
-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
-.Em NOT
-a substitute for good backup practices.
-.Pp
-Recomputation of parity
-.Em 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.
-.Sh BUGS
-Hot-spare removal is currently not available.
diff --git a/sbin/raidctl/raidctl.c b/sbin/raidctl/raidctl.c
deleted file mode 100644
index 4251d81765d..00000000000
--- a/sbin/raidctl/raidctl.c
+++ /dev/null
@@ -1,1232 +0,0 @@
-/* $OpenBSD: raidctl.c,v 1.31 2010/09/24 00:11:15 deraadt Exp $ */
-/* $NetBSD: raidctl.c,v 1.27 2001/07/10 01:30:52 lukem 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.
- *
- * 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 userland interface to the RAIDframe kernel
- * driver in Net/OpenBSD.
- */
-
-#include <sys/param.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/sysctl.h>
-#ifdef NETBSD
-#include <sys/disklabel.h>
-#endif
-
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <paths.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <util.h>
-
-#include "rf_raidframe.h"
-
-extern char *__progname;
-
-typedef struct {
- int fd;
- int id;
-} fdidpair;
-
-int main(int, char *[]);
-void do_ioctl(int, u_long, void *, const char *);
-static void rf_configure(fdidpair *, char*, int);
-static const char *device_status(RF_DiskStatus_t);
-static void rf_get_device_status(fdidpair *, int);
-static void rf_output_configuration(fdidpair *, int);
-static void get_component_number(fdidpair *, char *, int *, int *);
-static void rf_fail_disk(fdidpair *, char *, int);
-static void usage(void);
-static void get_component_label(fdidpair *, char *);
-static void set_component_label(fdidpair *, char *);
-static void init_component_labels(fdidpair *, int);
-static void set_autoconfig(fdidpair *, char *);
-static void add_hot_spare(fdidpair *, char *);
-static void remove_hot_spare(fdidpair *, char *);
-static void rebuild_in_place(fdidpair *, char *);
-static void check_status(fdidpair *,int,int);
-static void check_parity(fdidpair *,int,int);
-static void do_meter(fdidpair *, int, u_long);
-static void get_bar(char *, double, int);
-static void get_time_string(char *, int);
-static int open_device(fdidpair **, char *);
-static int get_all_devices(char ***, const char *);
-
-int verbose;
-int do_all;
-
-int
-main(int argc, char *argv[])
-{
- int ch;
- int num_options;
- unsigned int action;
- char config_filename[PATH_MAX];
- char name[PATH_MAX];
- char component[PATH_MAX];
- char autoconf[10];
- int do_output;
- int do_recon;
- int do_rewrite;
- int serial_number;
- int i, nfd;
- fdidpair *fds;
- int force;
- u_long meter;
- const char *actionstr;
-
- num_options = 0;
- action = 0;
- meter = 0;
- do_output = 0;
- do_recon = 0;
- do_rewrite = 0;
- do_all = 0;
- serial_number = 0;
- force = 0;
- actionstr = NULL;
-
- while ((ch = getopt(argc, argv, "a:A:Bc:C:f:F:g:GiI:l:r:R:sSpPuv"))
- != -1)
- switch(ch) {
- case 'a':
- action = RAIDFRAME_ADD_HOT_SPARE;
- if (strlcpy(component, optarg, sizeof component) >= sizeof(component))
- errx(1, "-a arg too long");
- num_options++;
- break;
- case 'A':
- action = RAIDFRAME_SET_AUTOCONFIG;
- if (strlcpy(autoconf, optarg, sizeof(autoconf)) >= sizeof(autoconf))
- errx(1, "-A arg too long");
- num_options++;
- break;
- case 'B':
- action = RAIDFRAME_COPYBACK;
- num_options++;
- break;
- case 'c':
- action = RAIDFRAME_CONFIGURE;
- if (strlcpy(config_filename, optarg, sizeof config_filename) >=
- sizeof(config_filename))
- errx(1, "-c arg too long");
- force = 0;
- num_options++;
- break;
- case 'C':
- if (strlcpy(config_filename, optarg, sizeof config_filename) >=
- sizeof(config_filename))
- errx(1, "-C arg too long");
- action = RAIDFRAME_CONFIGURE;
- force = 1;
- num_options++;
- break;
- case 'f':
- action = RAIDFRAME_FAIL_DISK;
- if (strlcpy(component, optarg, sizeof component) >= sizeof(component))
- errx(1, "-f arg too long");
- do_recon = 0;
- num_options++;
- break;
- case 'F':
- action = RAIDFRAME_FAIL_DISK;
- if (strlcpy(component, optarg, sizeof component) >= sizeof(component))
- errx(1, "-F arg too long");
- do_recon = 1;
- num_options++;
- break;
- case 'g':
- action = RAIDFRAME_GET_COMPONENT_LABEL;
- if (strlcpy(component, optarg, sizeof component) >= sizeof(component))
- errx(1, "-g arg too long");
- num_options++;
- break;
- case 'G':
- action = RAIDFRAME_GET_INFO;
- do_output = 1;
- num_options++;
- break;
- case 'i':
- action = RAIDFRAME_REWRITEPARITY;
- num_options++;
- break;
- case 'I':
- action = RAIDFRAME_INIT_LABELS;
- serial_number = atoi(optarg);
- num_options++;
- break;
- case 'l':
- action = RAIDFRAME_SET_COMPONENT_LABEL;
- if (strlcpy(component, optarg, sizeof component) >= sizeof(component))
- errx(1, "-l arg too long");
- num_options++;
- break;
- case 'r':
- action = RAIDFRAME_REMOVE_HOT_SPARE;
- if (strlcpy(component, optarg, sizeof component) >= sizeof(component))
- errx(1, "-r arg too long");
- num_options++;
- break;
- case 'R':
- if (strlcpy(component, optarg, sizeof component) >= sizeof(component))
- errx(1, "-R arg too long");
- action = RAIDFRAME_REBUILD_IN_PLACE;
- num_options++;
- break;
- case 's':
- action = RAIDFRAME_GET_INFO;
- num_options++;
- break;
- case 'S':
- action = RAIDFRAME_CHECK_RECON_STATUS_EXT;
- num_options++;
- break;
- case 'p':
- action = RAIDFRAME_CHECK_PARITY;
- num_options++;
- break;
- case 'P':
- action = RAIDFRAME_CHECK_PARITY;
- do_rewrite = 1;
- num_options++;
- break;
- case 'u':
- action = RAIDFRAME_SHUTDOWN;
- num_options++;
- break;
- case 'v':
- verbose = 1;
- break;
- default:
- usage();
- }
- argc -= optind;
- argv += optind;
-
- if ((num_options > 1) || (argc == 0))
- usage();
-
- if (strlcpy(name, argv[0], sizeof name) >= sizeof(name))
- errx(1, "device name too long");
-
- if ((nfd = open_device(&fds, name)) < 1) {
- /* No configured raid device */
- free(fds);
- return (0);
- }
-
- if (do_all) {
- switch(action) {
- case RAIDFRAME_ADD_HOT_SPARE:
- case RAIDFRAME_REMOVE_HOT_SPARE:
- case RAIDFRAME_CONFIGURE:
- case RAIDFRAME_SET_AUTOCONFIG:
- case RAIDFRAME_FAIL_DISK:
- case RAIDFRAME_SET_COMPONENT_LABEL:
- case RAIDFRAME_GET_COMPONENT_LABEL:
- case RAIDFRAME_INIT_LABELS:
- case RAIDFRAME_REBUILD_IN_PLACE:
- errx(1,
- "This action doesn't work with the 'all' device");
- break;
- default:
- break;
- }
- }
-
- switch(action) {
- case RAIDFRAME_ADD_HOT_SPARE:
- add_hot_spare(fds, component);
- break;
- case RAIDFRAME_REMOVE_HOT_SPARE:
- remove_hot_spare(fds, component);
- break;
- case RAIDFRAME_CONFIGURE:
- rf_configure(fds, config_filename, force);
- break;
- case RAIDFRAME_SET_AUTOCONFIG:
- set_autoconfig(fds, autoconf);
- break;
- case RAIDFRAME_COPYBACK:
- i = nfd;
- while (i--) {
- do_ioctl(fds[i].fd, RAIDFRAME_COPYBACK, NULL,
- "RAIDFRAME_COPYBACK");
- }
- actionstr = "Copyback";
- meter = RAIDFRAME_CHECK_COPYBACK_STATUS_EXT;
- break;
- case RAIDFRAME_FAIL_DISK:
- rf_fail_disk(fds, component, do_recon);
- break;
- case RAIDFRAME_SET_COMPONENT_LABEL:
- set_component_label(fds, component);
- break;
- case RAIDFRAME_GET_COMPONENT_LABEL:
- get_component_label(fds, component);
- break;
- case RAIDFRAME_INIT_LABELS:
- init_component_labels(fds, serial_number);
- break;
- case RAIDFRAME_REWRITEPARITY:
- i = nfd;
- while (i--) {
- do_ioctl(fds[i].fd, RAIDFRAME_REWRITEPARITY, NULL,
- "RAIDFRAME_REWRITEPARITY");
- }
- actionstr = "Parity Re-Write";
- meter = RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT;
- break;
- case RAIDFRAME_CHECK_RECON_STATUS_EXT:
- check_status(fds, nfd, 1);
- break;
- case RAIDFRAME_GET_INFO:
- if (do_output)
- rf_output_configuration(fds, nfd);
- else
- rf_get_device_status(fds, nfd);
- break;
- case RAIDFRAME_REBUILD_IN_PLACE:
- rebuild_in_place(fds, component);
- break;
- case RAIDFRAME_CHECK_PARITY:
- check_parity(fds, nfd, do_rewrite);
- break;
- case RAIDFRAME_SHUTDOWN:
- i = nfd;
- while (i--) {
- do_ioctl(fds[i].fd, RAIDFRAME_SHUTDOWN, NULL,
- "RAIDFRAME_SHUTDOWN");
- }
- break;
- default:
- break;
- }
-
- if (verbose && meter) {
- sleep(3); /* XXX give the action a chance to start */
- printf("%s status:\n", actionstr);
- do_meter(fds, nfd, meter);
- }
-
- i = nfd;
- while (i--)
- close(fds[i].fd);
-
- free(fds);
- return (0);
-}
-
-void
-do_ioctl(int fd, unsigned long command, void *arg, const char *ioctl_name)
-{
- if (ioctl(fd, command, arg) < 0)
- errx(1, "ioctl (%s) failed", ioctl_name);
-}
-
-
-static void
-rf_configure(fdidpair *fds, char *config_file, int force)
-{
- void *generic;
- RF_Config_t cfg;
-
- if (rf_MakeConfig(config_file, &cfg) != 0)
- errx(1, "unable to create RAIDframe configuration structure");
-
- cfg.force = force;
-
- /*
- * 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(fds->fd, RAIDFRAME_CONFIGURE, &generic, "RAIDFRAME_CONFIGURE");
-}
-
-static const char *
-device_status(RF_DiskStatus_t status)
-{
-
- switch (status) {
- case rf_ds_optimal:
- return ("optimal");
- case rf_ds_failed:
- return ("failed");
- case rf_ds_reconstructing:
- return ("reconstructing");
- case rf_ds_dist_spared:
- return ("dist_spared");
- case rf_ds_spared:
- return ("spared");
- case rf_ds_spare:
- return ("spare");
- case rf_ds_used_spare:
- return ("used_spare");
- default:
- return ("UNKNOWN");
- }
- /* NOTREACHED */
-}
-
-static void
-rf_get_device_status(fdidpair *fds, int nfd)
-{
- RF_DeviceConfig_t device_config;
- void *cfg_ptr;
- int is_clean;
- int i,j;
-
- cfg_ptr = &device_config;
-
- i = nfd;
- while (i--) {
- do_ioctl(fds[i].fd, RAIDFRAME_GET_INFO, &cfg_ptr,
- "RAIDFRAME_GET_INFO");
-
- printf("raid%d Components:\n", fds[i].id);
- for (j = 0; j < device_config.ndevs; j++) {
- printf("%20s: %s\n", device_config.devs[j].devname,
- device_status(device_config.devs[j].status));
- }
- if (device_config.nspares > 0) {
- printf("Spares:\n");
- for (j = 0; j < device_config.nspares; j++) {
- printf("%20s: %s\n",
- device_config.spares[j].devname,
- device_status(device_config.spares[j].status));
- }
- } else {
- printf("No spares.\n");
- }
- if (verbose) {
- for(j=0; j < device_config.ndevs; j++) {
- if (device_config.devs[j].status ==
- rf_ds_optimal) {
- get_component_label(&fds[i],
- device_config.devs[j].devname);
- } else {
- printf("%s status is: %s. "
- "Skipping label.\n",
- device_config.devs[j].devname,
- device_status(device_config.devs[j].status));
- }
- }
-
- if (device_config.nspares > 0) {
- for(j=0; j < device_config.nspares; j++) {
- if ((device_config.spares[j].status ==
- rf_ds_optimal) ||
- (device_config.spares[j].status ==
- rf_ds_used_spare)) {
- get_component_label(&fds[i],
- device_config.spares[j].devname);
- } else {
- printf("%s status is: %s. "
- "Skipping label.\n",
- device_config.spares[j].devname,
- device_status(device_config.spares[j].status));
- }
- }
- }
- }
-
- do_ioctl(fds[i].fd, RAIDFRAME_CHECK_PARITY, &is_clean,
- "RAIDFRAME_CHECK_PARITY");
- if (is_clean) {
- printf("Parity status: clean\n");
- } else {
- printf("Parity status: DIRTY\n");
- }
- check_status(&fds[i], 1, 0);
- }
-}
-
-static void
-rf_output_configuration(fdidpair *fds, int nfd)
-{
- RF_DeviceConfig_t device_config;
- void *cfg_ptr;
- int i,j;
- RF_ComponentLabel_t component_label;
- void *label_ptr;
- int component_num;
- int num_cols;
- char name[PATH_MAX];
-
- cfg_ptr = &device_config;
-
- i = nfd;
- while (i--) {
- snprintf(name, PATH_MAX, "/dev/raid%dc", fds[i].id);
-
- printf("# raidctl config file for %s\n", name);
- printf("\n");
- do_ioctl(fds[i].fd, RAIDFRAME_GET_INFO, &cfg_ptr,
- "RAIDFRAME_GET_INFO");
-
- printf("START array\n");
- printf("# numRow numCol numSpare\n");
- printf("%d %d %d\n", device_config.rows, device_config.cols,
- device_config.nspares);
- printf("\n");
-
- printf("START disks\n");
- for(j = 0; j < device_config.ndevs; j++)
- printf("%s\n", device_config.devs[j].devname);
- printf("\n");
-
- if (device_config.nspares > 0) {
- printf("START spare\n");
- for(j = 0; j < device_config.nspares; j++)
- printf("%s\n", device_config.spares[j].devname);
- printf("\n");
- }
-
- for(j = 0; j < device_config.ndevs; j++) {
- if (device_config.devs[j].status == rf_ds_optimal)
- break;
- }
- if (j == device_config.ndevs) {
- printf("# WARNING: no optimal components; using %s\n",
- device_config.devs[0].devname);
- j = 0;
- }
- get_component_number(&fds[i], device_config.devs[j].devname,
- &component_num, &num_cols);
- memset(&component_label, 0, sizeof(RF_ComponentLabel_t));
- component_label.row = component_num / num_cols;
- component_label.column = component_num % num_cols;
- label_ptr = &component_label;
- do_ioctl(fds[i].fd, RAIDFRAME_GET_COMPONENT_LABEL, &label_ptr,
- "RAIDFRAME_GET_COMPONENT_LABEL");
-
- printf("START layout\n");
- printf(
- "# sectPerSU SUsPerParityUnit SUsPerReconUnit "
- "RAID_level_%c\n",
- (char) component_label.parityConfig);
- printf("%d %d %d %c\n",
- component_label.sectPerSU, component_label.SUsPerPU,
- component_label.SUsPerRU,
- (char) component_label.parityConfig);
- printf("\n");
-
- printf("START queue\n");
- printf("fifo %d\n", device_config.maxqdepth);
- }
-}
-
-static void
-get_component_number(fdidpair *fds, char *component_name, int *component_number,
- int *num_columns)
-{
- RF_DeviceConfig_t device_config;
- void *cfg_ptr;
- int i;
- int found;
-
- *component_number = -1;
-
- /* Assuming a full path spec... */
- cfg_ptr = &device_config;
- do_ioctl(fds->fd, RAIDFRAME_GET_INFO, &cfg_ptr, "RAIDFRAME_GET_INFO");
-
- *num_columns = device_config.cols;
-
- found = 0;
- for (i = 0; i < device_config.ndevs; i++) {
- if (strncmp(component_name, device_config.devs[i].devname,
- PATH_MAX) == 0) {
- found = 1;
- *component_number = i;
- }
- }
- if (!found) { /* maybe it's a spare? */
- for (i = 0; i < device_config.nspares; i++) {
- if (strncmp(component_name,
- device_config.spares[i].devname,
- PATH_MAX) == 0) {
- found = 1;
- *component_number = i + device_config.ndevs;
- /* the way spares are done should
- really change... */
- *num_columns = device_config.cols +
- device_config.nspares;
- }
- }
- }
-
- if (!found)
- errx(1, "%s is not a component of this device", component_name);
-}
-
-static void
-rf_fail_disk(fdidpair *fds, char *component_to_fail, int do_recon)
-{
- struct rf_recon_req recon_request;
- int component_num;
- int num_cols;
-
- get_component_number(fds, component_to_fail, &component_num, &num_cols);
-
- recon_request.row = component_num / num_cols;
- recon_request.col = component_num % num_cols;
- if (do_recon) {
- recon_request.flags = RF_FDFLAGS_RECON;
- } else {
- recon_request.flags = RF_FDFLAGS_NONE;
- }
- do_ioctl(fds->fd, RAIDFRAME_FAIL_DISK, &recon_request,
- "RAIDFRAME_FAIL_DISK");
- if (do_recon && verbose) {
- printf("Reconstruction status:\n");
- sleep(3); /* XXX give reconstruction a chance to start */
- do_meter(fds, 1, RAIDFRAME_CHECK_RECON_STATUS_EXT);
- }
-}
-
-static void
-get_component_label(fdidpair *fds, char *component)
-{
- RF_ComponentLabel_t component_label;
- void *label_ptr;
- int component_num;
- int num_cols;
-
- get_component_number(fds, component, &component_num, &num_cols);
-
- memset(&component_label, 0, sizeof(RF_ComponentLabel_t));
- component_label.row = component_num / num_cols;
- component_label.column = component_num % num_cols;
-
- label_ptr = &component_label;
- do_ioctl(fds->fd, RAIDFRAME_GET_COMPONENT_LABEL, &label_ptr,
- "RAIDFRAME_GET_COMPONENT_LABEL");
-
- printf("Component label for %s:\n", component);
-
- printf(" Row: %d, Column: %d, Num Rows: %d, Num Columns: %d\n",
- component_label.row, component_label.column,
- component_label.num_rows, component_label.num_columns);
- printf(" Version: %d, Serial Number: %d, Mod Counter: %d\n",
- component_label.version, component_label.serial_number,
- component_label.mod_counter);
- printf(" Clean: %s, Status: %d\n",
- component_label.clean ? "Yes" : "No",
- component_label.status);
- printf(" sectPerSU: %d, SUsPerPU: %d, SUsPerRU: %d\n",
- component_label.sectPerSU, component_label.SUsPerPU,
- component_label.SUsPerRU);
- printf(" Queue size: %d, blocksize: %d, numBlocks: %d\n",
- component_label.maxOutstanding, component_label.blockSize,
- component_label.numBlocks);
- printf(" RAID Level: %c\n", (char) component_label.parityConfig);
- printf(" Autoconfig: %s\n",
- component_label.autoconfigure ? "Yes" : "No");
- printf(" Root partition: %s\n",
- component_label.root_partition ? "Yes" : "No");
- printf(" Last configured as: raid%d\n", component_label.last_unit);
-}
-
-static void
-set_component_label(fdidpair *fds, char *component)
-{
- RF_ComponentLabel_t component_label;
- int component_num;
- int num_cols;
-
- get_component_number(fds, component, &component_num, &num_cols);
-
- /* XXX This is currently here for testing, and future expandability */
-
- component_label.version = 1;
- component_label.serial_number = 123456;
- component_label.mod_counter = 0;
- component_label.row = component_num / num_cols;
- component_label.column = component_num % num_cols;
- component_label.num_rows = 0;
- component_label.num_columns = 5;
- component_label.clean = 0;
- component_label.status = 1;
-
- do_ioctl(fds->fd, RAIDFRAME_SET_COMPONENT_LABEL, &component_label,
- "RAIDFRAME_SET_COMPONENT_LABEL");
-}
-
-
-static void
-init_component_labels(fdidpair *fds, int serial_number)
-{
- RF_ComponentLabel_t component_label;
-
- component_label.version = 0;
- component_label.serial_number = serial_number;
- component_label.mod_counter = 0;
- component_label.row = 0;
- component_label.column = 0;
- component_label.num_rows = 0;
- component_label.num_columns = 0;
- component_label.clean = 0;
- component_label.status = 0;
-
- do_ioctl(fds->fd, RAIDFRAME_INIT_LABELS, &component_label,
- "RAIDFRAME_SET_COMPONENT_LABEL");
-}
-
-static void
-set_autoconfig(fdidpair *fds, char *autoconf)
-{
- int auto_config;
- int root_config;
-
- auto_config = 0;
- root_config = 0;
-
- if (strncasecmp(autoconf, "root", 4) == 0) {
- root_config = 1;
- }
-
- if ((strncasecmp(autoconf, "yes", 3) == 0) ||
- root_config == 1) {
- auto_config = 1;
- }
-
- do_ioctl(fds->fd, RAIDFRAME_SET_AUTOCONFIG, &auto_config,
- "RAIDFRAME_SET_AUTOCONFIG");
-
- do_ioctl(fds->fd, RAIDFRAME_SET_ROOT, &root_config,
- "RAIDFRAME_SET_ROOT");
-
- printf("raid%d: Autoconfigure: %s\n", fds->id,
- auto_config ? "Yes" : "No");
-
- if (root_config == 1) {
- printf("raid%d: Root: %s\n", fds->id,
- auto_config ? "Yes" : "No");
- }
-}
-
-static void
-add_hot_spare(fdidpair *fds, char *component)
-{
- RF_SingleComponent_t hot_spare;
-
- hot_spare.row = 0;
- hot_spare.column = 0;
- strlcpy(hot_spare.component_name, component,
- sizeof(hot_spare.component_name));
-
- do_ioctl(fds->fd, RAIDFRAME_ADD_HOT_SPARE, &hot_spare,
- "RAIDFRAME_ADD_HOT_SPARE");
-}
-
-static void
-remove_hot_spare(fdidpair *fds, char *component)
-{
- RF_SingleComponent_t hot_spare;
- int component_num;
- int num_cols;
-
- get_component_number(fds, component, &component_num, &num_cols);
-
- hot_spare.row = component_num / num_cols;
- hot_spare.column = component_num % num_cols;
-
- strlcpy(hot_spare.component_name, component,
- sizeof(hot_spare.component_name));
-
- do_ioctl(fds->fd, RAIDFRAME_REMOVE_HOT_SPARE, &hot_spare,
- "RAIDFRAME_REMOVE_HOT_SPARE");
-}
-
-static void
-rebuild_in_place(fdidpair *fds, char *component)
-{
- RF_SingleComponent_t comp;
- int component_num;
- int num_cols;
-
- get_component_number(fds, component, &component_num, &num_cols);
-
- comp.row = 0;
- comp.column = component_num;
- strlcpy(comp.component_name, component, sizeof(comp.component_name));
-
- do_ioctl(fds->fd, RAIDFRAME_REBUILD_IN_PLACE, &comp,
- "RAIDFRAME_REBUILD_IN_PLACE");
-
- if (verbose) {
- printf("Reconstruction status:\n");
- sleep(3); /* XXX give reconstruction a chance to start */
- do_meter(fds, 1, RAIDFRAME_CHECK_RECON_STATUS_EXT);
- }
-
-}
-
-static void
-check_parity(fdidpair *fds, int nfd, int do_rewrite)
-{
- int i, is_clean, all_dirty, was_dirty;
- int percent_done;
- char dev_name[PATH_MAX];
-
- all_dirty = 0;
- i = nfd;
- while (i--) {
- is_clean = 0;
- percent_done = 0;
- snprintf(dev_name, PATH_MAX, "raid%d", fds[i].id);
-
- do_ioctl(fds[i].fd, RAIDFRAME_CHECK_PARITY, &is_clean,
- "RAIDFRAME_CHECK_PARITY");
- if (is_clean) {
- printf("%s: Parity status: clean\n", dev_name);
- } else {
- all_dirty |= 1 << fds[i].id;
- printf("%s: Parity status: DIRTY\n", dev_name);
- if (do_rewrite) {
- printf("%s: Initiating re-write of parity\n",
- dev_name);
- do_ioctl(fds[i].fd, RAIDFRAME_REWRITEPARITY,
- NULL, "RAIDFRAME_REWRITEPARITY");
- } else {
- /* parity is wrong, and is not being fixed. */
- exit(1);
- }
- }
- }
-
- if (do_all)
- strncpy(dev_name, "all raid", PATH_MAX);
-
- was_dirty = all_dirty;
- while (all_dirty) {
- sleep(3); /* wait a bit... */
- if (verbose) {
- printf("Parity Re-write status:\n");
- do_meter(fds, nfd,
- RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT);
- all_dirty = 0;
- } else {
- i = nfd;
- while (i--) {
- do_ioctl(fds[i].fd,
- RAIDFRAME_CHECK_PARITYREWRITE_STATUS,
- &percent_done,
- "RAIDFRAME_CHECK_PARITYREWRITE_STATUS"
- );
- if (percent_done == 100) {
- all_dirty &= ~(1 << fds[i].id);
- }
- }
- }
- }
- if (verbose && was_dirty)
- printf("%s: Parity Re-write complete\n", dev_name);
-}
-
-
-static void
-check_status(fdidpair *fds, int nfd, int meter)
-{
- int i;
- int recon_percent_done = 0;
- int parity_percent_done = 0;
- int copyback_percent_done = 0;
- int do_recon = 0;
- int do_parity = 0;
- int do_copyback = 0;
- u_long check = 0;
-
- i = nfd;
- while (i--) {
- if (meter) {
- printf("raid%d Status:\n", fds[i].id);
- }
- do_ioctl(fds[i].fd, RAIDFRAME_CHECK_RECON_STATUS,
- &recon_percent_done,
- "RAIDFRAME_CHECK_RECON_STATUS");
- printf("Reconstruction is %d%% complete.\n",
- recon_percent_done);
- if (recon_percent_done < 100) {
- do_recon |= 1 << fds[i].id;
- }
- do_ioctl(fds[i].fd, RAIDFRAME_CHECK_PARITYREWRITE_STATUS,
- &parity_percent_done,
- "RAIDFRAME_CHECK_PARITYREWRITE_STATUS");
- printf("Parity Re-write is %d%% complete.\n",
- parity_percent_done);
- if (parity_percent_done < 100) {
- do_parity |= 1 << fds[i].id;
- }
- do_ioctl(fds[i].fd, RAIDFRAME_CHECK_COPYBACK_STATUS,
- &copyback_percent_done,
- "RAIDFRAME_CHECK_COPYBACK_STATUS");
- printf("Copyback is %d%% complete.\n",
- copyback_percent_done);
- if (copyback_percent_done < 100) {
- do_copyback |= 1 << fds[i].id;
- }
- }
-
- if (meter && verbose) {
- /* These 3 should be mutually exclusive at this point */
- if (do_recon) {
- printf("Reconstruction status:\n");
- check = RAIDFRAME_CHECK_RECON_STATUS_EXT;
- } else if (do_parity) {
- printf("Parity Re-write status:\n");
- check = RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT;
- } else if (do_copyback) {
- printf("Copyback status:\n");
- check = RAIDFRAME_CHECK_COPYBACK_STATUS_EXT;
- }
- do_meter(fds, nfd, check);
- }
-}
-
-const char *tbits = "|/-\\";
-
-static void
-do_meter(fdidpair *fds, int nfd, u_long option)
-{
- int percent_done;
- int start_value;
- RF_ProgressInfo_t *progressInfo;
- void *pInfoPtr;
- struct timeval start_time;
- struct timeval current_time;
- double elapsed;
- int elapsed_sec;
- int elapsed_usec;
- int progress_total, progress_completed;
- int simple_eta, last_eta;
- double rate;
- int amount;
- int tbit_value;
- char buffer[1024];
- char bar_buffer[1024];
- char eta_buffer[1024];
- int not_done;
- int i;
-
- not_done = 0;
- percent_done = 0;
- tbit_value = 0;
- start_value = 0;
- last_eta = 0;
- progress_total = progress_completed = 0;
- progressInfo = calloc(nfd, sizeof(RF_ProgressInfo_t));
- if (!progressInfo)
- err(1, "calloc");
-
- if (gettimeofday(&start_time, NULL))
- err(1, "gettimeofday");
-
- current_time = start_time;
-
- i = nfd;
- while (i--) {
- pInfoPtr = &progressInfo[i];
- do_ioctl(fds[i].fd, option, &pInfoPtr, "");
- start_value += progressInfo[i].completed;
- progress_total += progressInfo[i].total;
-
- if (progressInfo[i].completed < progressInfo[i].total) {
- not_done |= 1 << i;
- }
- }
-
- while (not_done) {
- progress_completed = 0;
- percent_done = 0;
- amount = 0;
-
- i = nfd;
- while (i--) {
- pInfoPtr = &progressInfo[i];
- do_ioctl(fds[i].fd, option, &pInfoPtr, "");
- progress_completed += progressInfo[i].completed;
-
- if (progressInfo[i].completed >=
- progressInfo[i].total) {
- not_done &= ~(1 << i);
- }
- }
- percent_done = (progress_completed * 100) / progress_total;
- amount = progress_completed - start_value;
-
- get_bar(bar_buffer, percent_done, 40);
-
- elapsed_sec = current_time.tv_sec -
- start_time.tv_sec;
- elapsed_usec = current_time.tv_usec -
- start_time.tv_usec;
- if (elapsed_usec < 0) {
- elapsed_usec += 1000000;
- elapsed_sec--;
- }
-
- elapsed = (double) elapsed_sec +
- (double) elapsed_usec / 1000000.0;
-
- if (amount <= 0) { /* we don't do negatives (yet?) */
- amount = 0;
- }
-
- if (elapsed == 0)
- rate = 0.0;
- else
- rate = amount / elapsed;
-
- if (rate > 0.0) {
- simple_eta = (int)
- (((double)progress_total -
- (double) progress_completed)
- / rate);
- } else {
- simple_eta = -1;
- }
-
- if (simple_eta <= 0) {
- simple_eta = last_eta;
- } else {
- last_eta = simple_eta;
- }
-
- get_time_string(eta_buffer, simple_eta);
-
- snprintf(buffer, 1024,
- "\r\t%3d%% |%s| ETA: %s %c",
- percent_done, bar_buffer,
- eta_buffer, tbits[tbit_value]);
-
- write(fileno(stdout), buffer, strlen(buffer));
- fflush(stdout);
-
- if (++tbit_value > 3)
- tbit_value = 0;
-
- if (not_done)
- sleep(2);
-
- if (gettimeofday(&current_time, NULL))
- err(1, "gettimeofday");
- }
- free(progressInfo);
- printf("\n");
-}
-
-/* 40 '*''s per line, then 40 ' ''s line. */
-/* If you've got a screen wider than 160 characters, "tough" */
-
-#define STAR_MIDPOINT 4*40
-const char stars[] = "****************************************"
- "****************************************"
- "****************************************"
- "****************************************"
- " "
- " "
- " "
- " ";
-
-static void
-get_bar(char *string, double percent, int max_strlen)
-{
- int offset;
-
- if (max_strlen > STAR_MIDPOINT) {
- max_strlen = STAR_MIDPOINT;
- }
- offset = STAR_MIDPOINT -
- (int)((percent * max_strlen) / 100);
- if (offset < 0)
- offset = 0;
- snprintf(string, max_strlen, "%s", &stars[offset]);
-}
-
-static void
-get_time_string(char *string, int simple_time)
-{
- int minutes, seconds, hours;
- char hours_buffer[5];
- char minutes_buffer[5];
- char seconds_buffer[5];
-
- if (simple_time >= 0) {
-
- minutes = (int) simple_time / 60;
- seconds = ((int)simple_time - 60 * minutes);
- hours = minutes / 60;
- minutes = minutes - 60 * hours;
-
- if (hours > 0) {
- snprintf(hours_buffer, sizeof(hours_buffer),
- "%02d:", hours);
- } else {
- snprintf(hours_buffer, sizeof(hours_buffer), " ");
- }
-
- snprintf(minutes_buffer, sizeof(minutes_buffer),
- "%02d:", minutes);
- snprintf(seconds_buffer, sizeof(seconds_buffer),
- "%02d", seconds);
- snprintf(string, 1024, "%s%s%s",
- hours_buffer, minutes_buffer, seconds_buffer);
- } else {
- snprintf(string, 1024, " --:--");
- }
-
-}
-
-static int
-open_device(fdidpair **devfd, char *name)
-{
- int nfd, i;
- struct stat st;
- char **devname;
-
- if (strcmp(name, "all") == 0) {
- do_all = 1;
- nfd = get_all_devices(&devname, "raid");
- } else {
- nfd = 1;
- if ((devname = malloc(sizeof(void*))) == NULL)
- err(1, "malloc");
- if ((devname[0] = malloc(PATH_MAX)) == NULL)
- err(1, "malloc");
-
- if ((name[0] == '/') || (name[0] == '.')) {
- /* they've (apparently) given a full path... */
- strlcpy(devname[0], name, PATH_MAX);
- } else {
- if (name[0] == '\0')
- errx(1, "invalid device");
- if (isdigit(name[strlen(name) - 1])) {
- snprintf(devname[0], PATH_MAX, "%s%s%c",
- _PATH_DEV, name, 'a' + getrawpartition());
- } else {
- snprintf(devname[0], PATH_MAX, "%s%s",
- _PATH_DEV, name);
- }
- }
- }
-
- if ((*devfd = calloc(nfd, sizeof(fdidpair))) == NULL)
- errx(1, "malloc() error");
-
- i = nfd;
- while (i--) {
- if (((*devfd)[i].fd = open(devname[i], O_RDWR, 0640)) < 0)
- errx(1, "unable to open device file: %s", devname[i]);
- if (fstat((*devfd)[i].fd, &st) != 0)
- errx(errno, "fstat failure on: %s", devname[i]);
- if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode))
- errx(EINVAL, "invalid device: %s", devname[i]);
-
- (*devfd)[i].id = RF_DEV2RAIDID(st.st_rdev);
-
- free(devname[i]);
- }
-
- if (devname != NULL)
- free(devname);
-
- return (nfd);
-}
-
-static int
-get_all_devices(char ***diskarray, const char *genericname)
-{
- int i, numdevs, mib[2];
- size_t len;
- char *disks, *fp, *p;
-
- numdevs = 0;
-
- mib[0] = CTL_HW;
- mib[1] = HW_DISKNAMES;
- sysctl(mib, 2, NULL, &len, NULL, 0);
- if ((disks = malloc(len + 1)) == NULL)
- errx(1, "malloc() error");
- sysctl(mib, 2, disks, &len, NULL, 0);
- disks[len] = '\0';
-
- fp = disks;
- while ((fp = strstr((const char*)fp, genericname)) != NULL) {
- numdevs++;
- fp++;
- }
-
- *diskarray = (char**) calloc(numdevs, sizeof(void*));
- i = 0;
- fp = disks;
- while ((p = strsep(&fp, ",")) != NULL) {
- char *q = strchr(p, ':');
-
- if (q)
- *q = '\0';
-
- if (strstr((const char*)p, genericname) != NULL) {
- if (asprintf(&(*diskarray)[i++], "/dev/%s%c", p,
- 'a' + getrawpartition()) == -1)
- err(1, "asprintf");
- }
- }
-
- free(disks);
-
- return (numdevs);
-}
-
-static void
-usage(void)
-{
- fprintf(stderr,
- "usage: raidctl [-BGiPpSsuv] [-A [yes | no | root]] [-Cc config_file]\n");
- fprintf(stderr,
- " [-I serial_number] [-aFfgRr component] dev\n");
- exit(1);
- /* NOTREACHED */
-}
diff --git a/sbin/raidctl/rf_configure.c b/sbin/raidctl/rf_configure.c
deleted file mode 100644
index f17ae68ed5f..00000000000
--- a/sbin/raidctl/rf_configure.c
+++ /dev/null
@@ -1,558 +0,0 @@
-/* $OpenBSD: rf_configure.c,v 1.20 2007/10/22 16:45:20 chl Exp $ */
-/* $NetBSD: rf_configure.c,v 1.14 2001/02/04 21:05:42 christos 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.
- *
- **************************************************************/
-
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <strings.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include "rf_raid.h"
-#include "rf_raidframe.h"
-#include "rf_general.h"
-#include "rf_decluster.h"
-#include "rf_configure.h"
-
-/* so much for #include <ansidecl.h> */
-#ifdef __GNUCC__
-#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
-#else
-#define ATTRIBUTE_UNUSED
-#endif
-
-/*
- * 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_); \
- }
-
-int distSpareYes = 1;
-int distSpareNo = 0;
-
-/* The mapsw[] table below contains all the various RAID types that might
- be supported by the kernel. The actual supported types are found
- in sys/dev/raidframe/rf_layout.c. */
-
-static RF_LayoutSW_t mapsw[] = {
- /* parity declustering */
- {'T', "Parity declustering",
- rf_MakeLayoutSpecificDeclustered, &distSpareNo},
- /* parity declustering with distributed sparing */
- {'D', "Distributed sparing parity declustering",
- rf_MakeLayoutSpecificDeclustered, &distSpareYes},
- /* declustered P+Q */
- {'Q', "Declustered P+Q",
- rf_MakeLayoutSpecificDeclustered, &distSpareNo},
- /* RAID 5 with rotated sparing */
- {'R', "RAID Level 5 rotated sparing", rf_MakeLayoutSpecificNULL, NULL},
- /* Chained Declustering */
- {'C', "Chained Declustering", rf_MakeLayoutSpecificNULL, NULL},
- /* Interleaved Declustering */
- {'I', "Interleaved Declustering", rf_MakeLayoutSpecificNULL, NULL},
- /* RAID level 0 */
- {'0', "RAID Level 0", rf_MakeLayoutSpecificNULL, NULL},
- /* RAID level 1 */
- {'1', "RAID Level 1", rf_MakeLayoutSpecificNULL, NULL},
- /* RAID level 4 */
- {'4', "RAID Level 4", rf_MakeLayoutSpecificNULL, NULL},
- /* RAID level 5 */
- {'5', "RAID Level 5", rf_MakeLayoutSpecificNULL, NULL},
- /* Evenodd */
- {'E', "EvenOdd", rf_MakeLayoutSpecificNULL, NULL},
- /* Declustered Evenodd */
- {'e', "Declustered EvenOdd",
- rf_MakeLayoutSpecificDeclustered, &distSpareNo},
- /* parity logging */
- {'L', "Parity logging", rf_MakeLayoutSpecificNULL, NULL},
- /* end-of-list marker */
- {'\0', NULL, NULL, NULL}
-};
-RF_LayoutSW_t *
-rf_GetLayout(RF_ParityConfig_t parityConfig)
-{
- RF_LayoutSW_t *p;
-
- /* look up the specific layout */
- for (p = &mapsw[0]; p->parityConfig; p++)
- if (p->parityConfig == parityConfig)
- break;
- if (!p->parityConfig)
- return (NULL);
- RF_ASSERT(p->parityConfig == parityConfig);
- return (p);
-}
-
-int rf_search_file_for_start_of(const char *string, char *buf,
- int len, FILE * fp);
-int rf_get_next_nonblank_line(char *buf, int len, FILE *fp,
- const 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(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, sizeof(buf), 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, sizeof(buf), 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, sizeof(buf), fp)) {
- for (c=0; c < RF_MAXDBGV; c++) {
- if (rf_get_next_nonblank_line(buf, sizeof(buf), fp, NULL))
- break;
- cp = rf_find_non_white(buf);
- if (!strncmp(cp, "START", strlen("START")))
- break;
- strlcpy(&cfgPtr->debugVars[c][0], cp, RF_MAXDBGVLEN);
- }
- }
- rewind(fp);
- strlcpy(cfgPtr->diskQueueType,"fifo", sizeof(RF_DiskQueueType_t));
- cfgPtr->maxOutstandingDiskReqs = 1;
- /* scan the file for the block related to disk queues */
- if (rf_search_file_for_start_of("queue",buf,sizeof(buf),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, sizeof(buf), 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 *ch;
- bcopy(buf1, cfgPtr->diskQueueType,
- RF_MIN(sizeof(cfgPtr->diskQueueType), strlen(buf1) + 1));
- for (ch = buf1; *ch; ch++) {
- if (*ch == ' ') {
- *ch = '\0';
- break;
- }
- }
- cfgPtr->maxOutstandingDiskReqs = val;
- }
-
- rewind(fp);
-
- if (rf_search_file_for_start_of("disks",buf,sizeof(buf),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;
- }
- }
- }
-
- /* "spare" section is optional */
- rewind(fp);
- if (rf_search_file_for_start_of("spare", buf, sizeof(buf), fp))
- cfgPtr->numSpare = 0;
- for (c = 0; c < cfgPtr->numSpare; c++) {
- if (rf_get_next_nonblank_line(&cfgPtr->spare_names[c][0],
- sizeof(cfgPtr->spare_names[c]), fp, NULL)) {
- RF_ERRORMSG1("Config file error: unable to get device file for spare disk %d\n",c);
- retcode = -1;
- goto out;
- }
- }
-
- /* scan the file for the block related to layout */
- rewind(fp);
- if (rf_search_file_for_start_of("layout",buf,sizeof(buf),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, sizeof(buf), 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;
- }
-
- retcode = lp->MakeLayoutSpecific(fp, cfgPtr, lp->makeLayoutSpecificArg);
-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(FILE *fp ATTRIBUTE_UNUSED, RF_Config_t *cfgPtr,
- void *ignored ATTRIBUTE_UNUSED)
-{
- cfgPtr->layoutSpecificSize = 0;
- cfgPtr->layoutSpecific = NULL;
- return(0);
-}
-
-int
-rf_MakeLayoutSpecificDeclustered(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, sizeof(buf), configfp,
- "Can't find block design file name in config file\n"))
- return(EINVAL);
- bdfile = rf_find_non_white(buf);
- bdfile[strcspn(bdfile, "\n")] = '\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);
- }
- if (fgets(buf, sizeof(buf), fp) == NULL) {
- RF_ERRORMSG1("RAID: config error: Can't read layout from layout table file %s\n", bdfile);
- return (EINVAL);
- }
- 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, sizeof(smbuf), configfp,
- "Can't find sparemap file name in config file\n"))
- return(EINVAL);
- smname = rf_find_non_white(smbuf);
- smname[strcspn(smname, "\n")] = '\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 ((unsigned int)(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
- *
- ***************************************************************************/
-
-/* finds a non-white character in the line */
-char *
-rf_find_non_white(char *p)
-{
- for (; *p != '\0' && (*p == ' ' || *p == '\t'); p++);
- return (p);
-}
-
-/* finds a white character in the line */
-char *
-rf_find_white(char *p)
-{
- for (; *p != '\0' && (*p != ' ' && *p != '\t'); p++);
- return (p);
-}
-
-/*
- * searches a file for a line that says "START string", where string is
- * specified as a parameter
- */
-int
-rf_search_file_for_start_of(const 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(char *buf, int len, FILE *fp, const char *errmsg)
-{
- char *p;
- int i;
-
- while (fgets(buf,len,fp) != NULL) {
- for(i = strlen(buf) - 1; i >= 0 && isspace(buf[i]); i--)
- buf[i] = '\0';
- p = rf_find_non_white(buf);
- if (*p == '\n' || *p == '\0' || *p == '#')
- continue;
- return(0);
- }
-
- if (errmsg)
- RF_ERRORMSG1("%s", 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(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);
- buf[strcspn(buf, "\n")] = '\0';
-
- snprintf(targString, sizeof targString, "fdisk %d\n", req->fcol);
- snprintf(errString, sizeof 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);
-}