Home | History | Annotate | Line # | Download | only in raidctl
raidctl.c revision 1.39.4.1.4.1
      1  1.39.4.1.4.1     matt /*      $NetBSD: raidctl.c,v 1.39.4.1.4.1 2010/04/21 05:26:35 matt Exp $   */
      2          1.18  thorpej 
      3           1.1    oster /*-
      4           1.1    oster  * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
      5           1.1    oster  * All rights reserved.
      6           1.1    oster  *
      7           1.1    oster  * This code is derived from software contributed to The NetBSD Foundation
      8           1.1    oster  * by Greg Oster
      9           1.1    oster  *
     10           1.1    oster  * Redistribution and use in source and binary forms, with or without
     11           1.1    oster  * modification, are permitted provided that the following conditions
     12           1.1    oster  * are met:
     13           1.1    oster  * 1. Redistributions of source code must retain the above copyright
     14           1.1    oster  *    notice, this list of conditions and the following disclaimer.
     15           1.1    oster  * 2. Redistributions in binary form must reproduce the above copyright
     16           1.1    oster  *    notice, this list of conditions and the following disclaimer in the
     17           1.1    oster  *    documentation and/or other materials provided with the distribution.
     18           1.1    oster  *
     19           1.1    oster  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20           1.1    oster  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21           1.1    oster  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22           1.1    oster  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23           1.1    oster  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24           1.1    oster  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25           1.1    oster  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26           1.1    oster  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27           1.1    oster  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28           1.1    oster  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29           1.1    oster  * POSSIBILITY OF SUCH DAMAGE.
     30           1.1    oster  */
     31           1.1    oster 
     32           1.1    oster /*
     33          1.18  thorpej  * This program is a re-write of the original rf_ctrl program
     34          1.18  thorpej  * distributed by CMU with RAIDframe 1.1.
     35          1.18  thorpej  *
     36          1.18  thorpej  * This program is the user-land interface to the RAIDframe kernel
     37          1.18  thorpej  * driver in NetBSD.
     38           1.1    oster  */
     39          1.33      agc #include <sys/cdefs.h>
     40          1.33      agc 
     41          1.33      agc #ifndef lint
     42  1.39.4.1.4.1     matt __RCSID("$NetBSD: raidctl.c,v 1.39.4.1.4.1 2010/04/21 05:26:35 matt Exp $");
     43          1.33      agc #endif
     44          1.33      agc 
     45           1.1    oster 
     46           1.1    oster #include <sys/param.h>
     47           1.1    oster #include <sys/ioctl.h>
     48           1.1    oster #include <sys/stat.h>
     49          1.18  thorpej #include <sys/disklabel.h>
     50          1.18  thorpej 
     51           1.1    oster #include <ctype.h>
     52           1.1    oster #include <err.h>
     53           1.2   mjacob #include <errno.h>
     54          1.25    lukem #include <fcntl.h>
     55          1.25    lukem #include <stdio.h>
     56          1.25    lukem #include <stdlib.h>
     57           1.1    oster #include <string.h>
     58           1.3    oster #include <unistd.h>
     59          1.25    lukem #include <util.h>
     60           1.3    oster 
     61          1.29    oster #include <dev/raidframe/raidframevar.h>
     62          1.29    oster #include <dev/raidframe/raidframeio.h>
     63          1.29    oster #include "rf_configure.h"
     64           1.1    oster 
     65          1.36  xtraeme void	do_ioctl(int, u_long, void *, const char *);
     66          1.36  xtraeme static  void rf_configure(int, char*, int);
     67          1.36  xtraeme static  const char *device_status(RF_DiskStatus_t);
     68          1.36  xtraeme static  void rf_get_device_status(int);
     69          1.36  xtraeme static	void rf_output_configuration(int, const char *);
     70          1.36  xtraeme static  void get_component_number(int, char *, int *, int *);
     71          1.36  xtraeme static  void rf_fail_disk(int, char *, int);
     72          1.36  xtraeme static  void usage(void);
     73          1.36  xtraeme static  void get_component_label(int, char *);
     74          1.36  xtraeme static  void set_component_label(int, char *);
     75          1.36  xtraeme static  void init_component_labels(int, int);
     76          1.36  xtraeme static  void set_autoconfig(int, int, char *);
     77          1.36  xtraeme static  void add_hot_spare(int, char *);
     78          1.36  xtraeme static  void remove_hot_spare(int, char *);
     79          1.36  xtraeme static  void rebuild_in_place(int, char *);
     80          1.36  xtraeme static  void check_status(int,int);
     81          1.36  xtraeme static  void check_parity(int,int, char *);
     82          1.36  xtraeme static  void do_meter(int, u_long);
     83          1.36  xtraeme static  void get_bar(char *, double, int);
     84          1.36  xtraeme static  void get_time_string(char *, int);
     85  1.39.4.1.4.1     matt static  void rf_output_pmstat(int, int);
     86  1.39.4.1.4.1     matt static  void rf_pm_configure(int, int, char *, int[]);
     87          1.10    oster 
     88          1.18  thorpej int verbose;
     89           1.1    oster 
     90           1.1    oster int
     91          1.36  xtraeme main(int argc,char *argv[])
     92           1.1    oster {
     93  1.39.4.1.4.1     matt 	int ch, i;
     94           1.1    oster 	int num_options;
     95           1.1    oster 	unsigned long action;
     96           1.1    oster 	char config_filename[PATH_MAX];
     97           1.1    oster 	char dev_name[PATH_MAX];
     98           1.1    oster 	char name[PATH_MAX];
     99           1.5    oster 	char component[PATH_MAX];
    100          1.12    oster 	char autoconf[10];
    101  1.39.4.1.4.1     matt 	char *parityconf = NULL;
    102  1.39.4.1.4.1     matt 	int parityparams[3];
    103          1.27    lukem 	int do_output;
    104           1.1    oster 	int do_recon;
    105           1.7    oster 	int do_rewrite;
    106           1.7    oster 	int is_clean;
    107           1.1    oster 	int raidID;
    108           1.5    oster 	int serial_number;
    109           1.1    oster 	struct stat st;
    110           1.1    oster 	int fd;
    111           1.5    oster 	int force;
    112          1.30   simonb 	int openmode;
    113           1.1    oster 
    114           1.1    oster 	num_options = 0;
    115           1.1    oster 	action = 0;
    116          1.27    lukem 	do_output = 0;
    117           1.1    oster 	do_recon = 0;
    118           1.7    oster 	do_rewrite = 0;
    119           1.7    oster 	is_clean = 0;
    120          1.38    lukem 	serial_number = 0;
    121           1.5    oster 	force = 0;
    122          1.30   simonb 	openmode = O_RDWR;	/* default to read/write */
    123           1.1    oster 
    124  1.39.4.1.4.1     matt 	while ((ch = getopt(argc, argv, "a:A:Bc:C:f:F:g:GiI:l:mM:r:R:sSpPuv"))
    125          1.12    oster 	       != -1)
    126           1.1    oster 		switch(ch) {
    127           1.5    oster 		case 'a':
    128           1.5    oster 			action = RAIDFRAME_ADD_HOT_SPARE;
    129          1.32   itojun 			strlcpy(component, optarg, sizeof(component));
    130           1.5    oster 			num_options++;
    131           1.5    oster 			break;
    132          1.12    oster 		case 'A':
    133          1.12    oster 			action = RAIDFRAME_SET_AUTOCONFIG;
    134          1.32   itojun 			strlcpy(autoconf, optarg, sizeof(autoconf));
    135          1.12    oster 			num_options++;
    136          1.12    oster 			break;
    137           1.6    oster 		case 'B':
    138           1.6    oster 			action = RAIDFRAME_COPYBACK;
    139           1.6    oster 			num_options++;
    140           1.6    oster 			break;
    141           1.1    oster 		case 'c':
    142           1.6    oster 			action = RAIDFRAME_CONFIGURE;
    143          1.32   itojun 			strlcpy(config_filename, optarg,
    144          1.32   itojun 			    sizeof(config_filename));
    145           1.6    oster 			force = 0;
    146           1.1    oster 			num_options++;
    147           1.1    oster 			break;
    148           1.1    oster 		case 'C':
    149          1.32   itojun 			strlcpy(config_filename, optarg,
    150          1.32   itojun 			    sizeof(config_filename));
    151           1.6    oster 			action = RAIDFRAME_CONFIGURE;
    152           1.6    oster 			force = 1;
    153           1.1    oster 			num_options++;
    154           1.1    oster 			break;
    155           1.1    oster 		case 'f':
    156           1.1    oster 			action = RAIDFRAME_FAIL_DISK;
    157          1.32   itojun 			strlcpy(component, optarg, sizeof(component));
    158           1.1    oster 			do_recon = 0;
    159           1.1    oster 			num_options++;
    160           1.1    oster 			break;
    161           1.1    oster 		case 'F':
    162           1.1    oster 			action = RAIDFRAME_FAIL_DISK;
    163          1.32   itojun 			strlcpy(component, optarg, sizeof(component));
    164           1.1    oster 			do_recon = 1;
    165           1.5    oster 			num_options++;
    166           1.5    oster 			break;
    167           1.5    oster 		case 'g':
    168           1.5    oster 			action = RAIDFRAME_GET_COMPONENT_LABEL;
    169          1.32   itojun 			strlcpy(component, optarg, sizeof(component));
    170          1.30   simonb 			openmode = O_RDONLY;
    171           1.5    oster 			num_options++;
    172           1.5    oster 			break;
    173          1.27    lukem 		case 'G':
    174          1.27    lukem 			action = RAIDFRAME_GET_INFO;
    175          1.30   simonb 			openmode = O_RDONLY;
    176          1.27    lukem 			do_output = 1;
    177          1.27    lukem 			num_options++;
    178          1.27    lukem 			break;
    179           1.6    oster 		case 'i':
    180           1.6    oster 			action = RAIDFRAME_REWRITEPARITY;
    181           1.6    oster 			num_options++;
    182           1.6    oster 			break;
    183           1.5    oster 		case 'I':
    184           1.5    oster 			action = RAIDFRAME_INIT_LABELS;
    185           1.5    oster 			serial_number = atoi(optarg);
    186           1.5    oster 			num_options++;
    187           1.5    oster 			break;
    188  1.39.4.1.4.1     matt 		case 'm':
    189  1.39.4.1.4.1     matt 			action = RAIDFRAME_PARITYMAP_STATUS;
    190  1.39.4.1.4.1     matt 			openmode = O_RDONLY;
    191  1.39.4.1.4.1     matt 			num_options++;
    192  1.39.4.1.4.1     matt 			break;
    193  1.39.4.1.4.1     matt 		case 'M':
    194  1.39.4.1.4.1     matt 			action = RAIDFRAME_PARITYMAP_SET_DISABLE;
    195  1.39.4.1.4.1     matt 			parityconf = strdup(optarg);
    196  1.39.4.1.4.1     matt 			num_options++;
    197  1.39.4.1.4.1     matt 			/* XXXjld: should rf_pm_configure do the atoi()s? */
    198  1.39.4.1.4.1     matt 			i = 0;
    199  1.39.4.1.4.1     matt 			while (i < 3 && optind < argc &&
    200  1.39.4.1.4.1     matt 			    isdigit((int)argv[optind][0]))
    201  1.39.4.1.4.1     matt 				parityparams[i++] = atoi(argv[optind++]);
    202  1.39.4.1.4.1     matt 			while (i < 3)
    203  1.39.4.1.4.1     matt 				parityparams[i++] = 0;
    204  1.39.4.1.4.1     matt 			break;
    205           1.6    oster 		case 'l':
    206           1.5    oster 			action = RAIDFRAME_SET_COMPONENT_LABEL;
    207          1.32   itojun 			strlcpy(component, optarg, sizeof(component));
    208           1.1    oster 			num_options++;
    209           1.1    oster 			break;
    210           1.1    oster 		case 'r':
    211           1.6    oster 			action = RAIDFRAME_REMOVE_HOT_SPARE;
    212          1.32   itojun 			strlcpy(component, optarg, sizeof(component));
    213           1.1    oster 			num_options++;
    214           1.1    oster 			break;
    215           1.1    oster 		case 'R':
    216          1.32   itojun 			strlcpy(component, optarg, sizeof(component));
    217           1.6    oster 			action = RAIDFRAME_REBUILD_IN_PLACE;
    218           1.1    oster 			num_options++;
    219           1.1    oster 			break;
    220           1.1    oster 		case 's':
    221           1.1    oster 			action = RAIDFRAME_GET_INFO;
    222          1.30   simonb 			openmode = O_RDONLY;
    223           1.1    oster 			num_options++;
    224           1.1    oster 			break;
    225           1.6    oster 		case 'S':
    226          1.19    oster 			action = RAIDFRAME_CHECK_RECON_STATUS_EXT;
    227          1.30   simonb 			openmode = O_RDONLY;
    228           1.6    oster 			num_options++;
    229           1.6    oster 			break;
    230           1.7    oster 		case 'p':
    231           1.7    oster 			action = RAIDFRAME_CHECK_PARITY;
    232          1.30   simonb 			openmode = O_RDONLY;
    233           1.7    oster 			num_options++;
    234           1.7    oster 			break;
    235           1.7    oster 		case 'P':
    236           1.7    oster 			action = RAIDFRAME_CHECK_PARITY;
    237           1.7    oster 			do_rewrite = 1;
    238           1.7    oster 			num_options++;
    239           1.7    oster 			break;
    240           1.1    oster 		case 'u':
    241           1.1    oster 			action = RAIDFRAME_SHUTDOWN;
    242           1.1    oster 			num_options++;
    243           1.1    oster 			break;
    244          1.10    oster 		case 'v':
    245          1.10    oster 			verbose = 1;
    246          1.10    oster 			/* Don't bump num_options, as '-v' is not
    247          1.10    oster 			   an option like the others */
    248          1.10    oster 			/* num_options++; */
    249          1.10    oster 			break;
    250           1.1    oster 		default:
    251           1.1    oster 			usage();
    252           1.1    oster 		}
    253           1.1    oster 	argc -= optind;
    254           1.1    oster 	argv += optind;
    255           1.1    oster 
    256          1.34     fvdl 	if ((num_options > 1) || (argc == 0))
    257           1.1    oster 		usage();
    258           1.1    oster 
    259          1.32   itojun 	strlcpy(name, argv[0], sizeof(name));
    260          1.35    oster 	fd = opendisk(name, openmode, dev_name, sizeof(dev_name), 0);
    261          1.25    lukem 	if (fd == -1) {
    262          1.25    lukem 		fprintf(stderr, "%s: unable to open device file: %s\n",
    263          1.26      cgd 			getprogname(), name);
    264          1.25    lukem 		exit(1);
    265          1.25    lukem 	}
    266          1.25    lukem 	if (fstat(fd, &st) != 0) {
    267           1.1    oster 		fprintf(stderr,"%s: stat failure on: %s\n",
    268          1.26      cgd 			getprogname(), dev_name);
    269          1.25    lukem 		exit(1);
    270           1.1    oster 	}
    271           1.1    oster 	if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) {
    272           1.1    oster 		fprintf(stderr,"%s: invalid device: %s\n",
    273          1.26      cgd 			getprogname(), dev_name);
    274          1.25    lukem 		exit(1);
    275           1.1    oster 	}
    276           1.1    oster 
    277          1.28    oster 	raidID = DISKUNIT(st.st_rdev);
    278           1.1    oster 
    279           1.1    oster 	switch(action) {
    280           1.5    oster 	case RAIDFRAME_ADD_HOT_SPARE:
    281          1.12    oster 		add_hot_spare(fd, component);
    282           1.5    oster 		break;
    283           1.6    oster 	case RAIDFRAME_REMOVE_HOT_SPARE:
    284          1.12    oster 		remove_hot_spare(fd, component);
    285           1.6    oster 		break;
    286           1.1    oster 	case RAIDFRAME_CONFIGURE:
    287          1.12    oster 		rf_configure(fd, config_filename, force);
    288          1.12    oster 		break;
    289          1.12    oster 	case RAIDFRAME_SET_AUTOCONFIG:
    290          1.12    oster 		set_autoconfig(fd, raidID, autoconf);
    291           1.1    oster 		break;
    292           1.1    oster 	case RAIDFRAME_COPYBACK:
    293           1.1    oster 		printf("Copyback.\n");
    294           1.1    oster 		do_ioctl(fd, RAIDFRAME_COPYBACK, NULL, "RAIDFRAME_COPYBACK");
    295          1.10    oster 		if (verbose) {
    296          1.10    oster 			sleep(3); /* XXX give the copyback a chance to start */
    297          1.10    oster 			printf("Copyback status:\n");
    298          1.19    oster 			do_meter(fd,RAIDFRAME_CHECK_COPYBACK_STATUS_EXT);
    299          1.10    oster 		}
    300           1.1    oster 		break;
    301           1.1    oster 	case RAIDFRAME_FAIL_DISK:
    302          1.12    oster 		rf_fail_disk(fd, component, do_recon);
    303           1.5    oster 		break;
    304           1.5    oster 	case RAIDFRAME_SET_COMPONENT_LABEL:
    305          1.12    oster 		set_component_label(fd, component);
    306           1.5    oster 		break;
    307           1.5    oster 	case RAIDFRAME_GET_COMPONENT_LABEL:
    308          1.12    oster 		get_component_label(fd, component);
    309           1.5    oster 		break;
    310           1.5    oster 	case RAIDFRAME_INIT_LABELS:
    311          1.12    oster 		init_component_labels(fd, serial_number);
    312           1.1    oster 		break;
    313           1.1    oster 	case RAIDFRAME_REWRITEPARITY:
    314           1.1    oster 		printf("Initiating re-write of parity\n");
    315           1.1    oster 		do_ioctl(fd, RAIDFRAME_REWRITEPARITY, NULL,
    316           1.1    oster 			 "RAIDFRAME_REWRITEPARITY");
    317          1.10    oster 		if (verbose) {
    318          1.10    oster 			sleep(3); /* XXX give it time to get started */
    319          1.10    oster 			printf("Parity Re-write status:\n");
    320          1.19    oster 			do_meter(fd, RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT);
    321          1.10    oster 		}
    322           1.1    oster 		break;
    323          1.19    oster 	case RAIDFRAME_CHECK_RECON_STATUS_EXT:
    324          1.14    oster 		check_status(fd,1);
    325           1.1    oster 		break;
    326           1.1    oster 	case RAIDFRAME_GET_INFO:
    327          1.27    lukem 		if (do_output)
    328          1.27    lukem 			rf_output_configuration(fd, dev_name);
    329          1.27    lukem 		else
    330          1.27    lukem 			rf_get_device_status(fd);
    331           1.1    oster 		break;
    332  1.39.4.1.4.1     matt 	case RAIDFRAME_PARITYMAP_STATUS:
    333  1.39.4.1.4.1     matt 		rf_output_pmstat(fd, raidID);
    334  1.39.4.1.4.1     matt 		break;
    335  1.39.4.1.4.1     matt 	case RAIDFRAME_PARITYMAP_SET_DISABLE:
    336  1.39.4.1.4.1     matt 		rf_pm_configure(fd, raidID, parityconf, parityparams);
    337  1.39.4.1.4.1     matt 		break;
    338           1.6    oster 	case RAIDFRAME_REBUILD_IN_PLACE:
    339          1.12    oster 		rebuild_in_place(fd, component);
    340           1.6    oster 		break;
    341           1.7    oster 	case RAIDFRAME_CHECK_PARITY:
    342          1.12    oster 		check_parity(fd, do_rewrite, dev_name);
    343           1.7    oster 		break;
    344           1.1    oster 	case RAIDFRAME_SHUTDOWN:
    345           1.1    oster 		do_ioctl(fd, RAIDFRAME_SHUTDOWN, NULL, "RAIDFRAME_SHUTDOWN");
    346           1.1    oster 		break;
    347           1.1    oster 	default:
    348           1.1    oster 		break;
    349           1.1    oster 	}
    350           1.1    oster 
    351           1.1    oster 	close(fd);
    352           1.1    oster 	exit(0);
    353           1.1    oster }
    354           1.1    oster 
    355          1.10    oster void
    356          1.36  xtraeme do_ioctl(int fd, unsigned long command, void *arg, const char *ioctl_name)
    357           1.1    oster {
    358           1.1    oster 	if (ioctl(fd, command, arg) < 0) {
    359           1.1    oster 		warn("ioctl (%s) failed", ioctl_name);
    360           1.1    oster 		exit(1);
    361           1.1    oster 	}
    362           1.1    oster }
    363           1.1    oster 
    364           1.1    oster 
    365           1.1    oster static void
    366          1.36  xtraeme rf_configure(int fd, char *config_file, int force)
    367           1.1    oster {
    368           1.1    oster 	void *generic;
    369           1.1    oster 	RF_Config_t cfg;
    370           1.1    oster 
    371           1.9    oster 	if (rf_MakeConfig( config_file, &cfg ) != 0) {
    372           1.1    oster 		fprintf(stderr,"%s: unable to create RAIDframe %s\n",
    373          1.26      cgd 			getprogname(), "configuration structure\n");
    374           1.1    oster 		exit(1);
    375           1.1    oster 	}
    376           1.1    oster 
    377           1.6    oster 	cfg.force = force;
    378           1.6    oster 
    379           1.1    oster 	/*
    380          1.18  thorpej 	 * Note the extra level of redirection needed here, since
    381          1.18  thorpej 	 * what we really want to pass in is a pointer to the pointer to
    382          1.18  thorpej 	 * the configuration structure.
    383           1.1    oster 	 */
    384           1.1    oster 
    385           1.1    oster 	generic = (void *) &cfg;
    386           1.6    oster 	do_ioctl(fd, RAIDFRAME_CONFIGURE, &generic, "RAIDFRAME_CONFIGURE");
    387           1.1    oster }
    388           1.1    oster 
    389          1.18  thorpej static const char *
    390          1.36  xtraeme device_status(RF_DiskStatus_t status)
    391           1.1    oster {
    392           1.1    oster 
    393           1.1    oster 	switch (status) {
    394           1.1    oster 	case rf_ds_optimal:
    395          1.18  thorpej 		return ("optimal");
    396           1.1    oster 		break;
    397           1.1    oster 	case rf_ds_failed:
    398          1.18  thorpej 		return ("failed");
    399           1.1    oster 		break;
    400           1.1    oster 	case rf_ds_reconstructing:
    401          1.18  thorpej 		return ("reconstructing");
    402           1.1    oster 		break;
    403           1.1    oster 	case rf_ds_dist_spared:
    404          1.18  thorpej 		return ("dist_spared");
    405           1.1    oster 		break;
    406           1.1    oster 	case rf_ds_spared:
    407          1.18  thorpej 		return ("spared");
    408           1.1    oster 		break;
    409           1.1    oster 	case rf_ds_spare:
    410          1.18  thorpej 		return ("spare");
    411           1.1    oster 		break;
    412           1.1    oster 	case rf_ds_used_spare:
    413          1.18  thorpej 		return ("used_spare");
    414           1.1    oster 		break;
    415           1.1    oster 	default:
    416          1.18  thorpej 		return ("UNKNOWN");
    417           1.1    oster 	}
    418          1.18  thorpej 	/* NOTREACHED */
    419           1.1    oster }
    420           1.1    oster 
    421           1.1    oster static void
    422          1.36  xtraeme rf_get_device_status(int fd)
    423           1.1    oster {
    424           1.1    oster 	RF_DeviceConfig_t device_config;
    425           1.1    oster 	void *cfg_ptr;
    426           1.8    oster 	int is_clean;
    427           1.1    oster 	int i;
    428           1.1    oster 
    429           1.1    oster 	cfg_ptr = &device_config;
    430           1.1    oster 
    431           1.1    oster 	do_ioctl(fd, RAIDFRAME_GET_INFO, &cfg_ptr, "RAIDFRAME_GET_INFO");
    432           1.1    oster 
    433           1.1    oster 	printf("Components:\n");
    434           1.1    oster 	for(i=0; i < device_config.ndevs; i++) {
    435           1.1    oster 		printf("%20s: %s\n", device_config.devs[i].devname,
    436           1.1    oster 		       device_status(device_config.devs[i].status));
    437           1.1    oster 	}
    438           1.1    oster 	if (device_config.nspares > 0) {
    439           1.1    oster 		printf("Spares:\n");
    440           1.1    oster 		for(i=0; i < device_config.nspares; i++) {
    441           1.5    oster 			printf("%20s: %s\n",
    442           1.1    oster 			       device_config.spares[i].devname,
    443           1.1    oster 			       device_status(device_config.spares[i].status));
    444           1.1    oster 		}
    445           1.1    oster 	} else {
    446           1.1    oster 		printf("No spares.\n");
    447           1.8    oster 	}
    448          1.14    oster 	for(i=0; i < device_config.ndevs; i++) {
    449          1.14    oster 		if (device_config.devs[i].status == rf_ds_optimal) {
    450          1.14    oster 			get_component_label(fd, device_config.devs[i].devname);
    451          1.14    oster 		} else {
    452          1.14    oster 			printf("%s status is: %s.  Skipping label.\n",
    453          1.14    oster 			       device_config.devs[i].devname,
    454          1.14    oster 			       device_status(device_config.devs[i].status));
    455          1.14    oster 		}
    456          1.14    oster 	}
    457          1.23    oster 
    458          1.21    oster 	if (device_config.nspares > 0) {
    459          1.21    oster 		for(i=0; i < device_config.nspares; i++) {
    460          1.21    oster 			if ((device_config.spares[i].status ==
    461          1.21    oster 			     rf_ds_optimal) ||
    462          1.21    oster 			    (device_config.spares[i].status ==
    463          1.21    oster 			     rf_ds_used_spare)) {
    464          1.21    oster 				get_component_label(fd,
    465          1.21    oster 					    device_config.spares[i].devname);
    466          1.21    oster 			} else {
    467          1.21    oster 				printf("%s status is: %s.  Skipping label.\n",
    468          1.21    oster 				       device_config.spares[i].devname,
    469          1.21    oster 				       device_status(device_config.spares[i].status));
    470          1.21    oster 			}
    471          1.21    oster 		}
    472          1.21    oster 	}
    473          1.23    oster 
    474           1.8    oster 	do_ioctl(fd, RAIDFRAME_CHECK_PARITY, &is_clean,
    475           1.8    oster 		 "RAIDFRAME_CHECK_PARITY");
    476           1.8    oster 	if (is_clean) {
    477           1.8    oster 		printf("Parity status: clean\n");
    478           1.8    oster 	} else {
    479           1.8    oster 		printf("Parity status: DIRTY\n");
    480           1.1    oster 	}
    481          1.14    oster 	check_status(fd,0);
    482           1.1    oster }
    483           1.1    oster 
    484           1.1    oster static void
    485  1.39.4.1.4.1     matt rf_output_pmstat(int fd, int raidID)
    486  1.39.4.1.4.1     matt {
    487  1.39.4.1.4.1     matt 	char srs[7];
    488  1.39.4.1.4.1     matt 	int i, j, dr;
    489  1.39.4.1.4.1     matt 	int dis;
    490  1.39.4.1.4.1     matt 	struct rf_pmstat st;
    491  1.39.4.1.4.1     matt 
    492  1.39.4.1.4.1     matt 	do_ioctl(fd, RAIDFRAME_PARITYMAP_STATUS, &st,
    493  1.39.4.1.4.1     matt 	    "RAIDFRAME_PARITYMAP_STATUS");
    494  1.39.4.1.4.1     matt 	if (st.enabled) {
    495  1.39.4.1.4.1     matt 		if (0 > humanize_number(srs, 7, st.region_size * DEV_BSIZE,
    496  1.39.4.1.4.1     matt 			"B", HN_AUTOSCALE, HN_NOSPACE))
    497  1.39.4.1.4.1     matt 			strlcpy(srs, "???", 7);
    498  1.39.4.1.4.1     matt 
    499  1.39.4.1.4.1     matt 		printf("raid%d: parity map enabled with %u regions of %s\n",
    500  1.39.4.1.4.1     matt 		    raidID, st.params.regions, srs);
    501  1.39.4.1.4.1     matt 		printf("raid%d: regions marked clean after %d intervals of"
    502  1.39.4.1.4.1     matt 		    " %d.%03ds\n", raidID, st.params.cooldown,
    503  1.39.4.1.4.1     matt 		    st.params.tickms / 1000, st.params.tickms % 1000);
    504  1.39.4.1.4.1     matt 		printf("raid%d: write/sync/clean counters "
    505  1.39.4.1.4.1     matt 		    "%"PRIu64"/%"PRIu64"/%"PRIu64"\n", raidID,
    506  1.39.4.1.4.1     matt 		    st.ctrs.nwrite, st.ctrs.ncachesync, st.ctrs.nclearing);
    507  1.39.4.1.4.1     matt 
    508  1.39.4.1.4.1     matt 		dr = 0;
    509  1.39.4.1.4.1     matt 		for (i = 0; i < RF_PARITYMAP_NREG; i++)
    510  1.39.4.1.4.1     matt 			if (isset(st.dirty, i))
    511  1.39.4.1.4.1     matt 				dr++;
    512  1.39.4.1.4.1     matt 		printf("raid%d: %d dirty region%s\n", raidID, dr,
    513  1.39.4.1.4.1     matt 		    dr == 1 ? "" : "s");
    514  1.39.4.1.4.1     matt 
    515  1.39.4.1.4.1     matt 		if (verbose > 0) {
    516  1.39.4.1.4.1     matt 			for (i = 0; i < RF_PARITYMAP_NBYTE; i += 32) {
    517  1.39.4.1.4.1     matt 				printf("    ");
    518  1.39.4.1.4.1     matt 				for (j = i; j < RF_PARITYMAP_NBYTE
    519  1.39.4.1.4.1     matt 					 && j < i + 32; j++)
    520  1.39.4.1.4.1     matt 					printf("%x%x", st.dirty[j] & 15,
    521  1.39.4.1.4.1     matt 					    (st.dirty[j] >> 4) & 15);
    522  1.39.4.1.4.1     matt 				printf("\n");
    523  1.39.4.1.4.1     matt 			}
    524  1.39.4.1.4.1     matt 		}
    525  1.39.4.1.4.1     matt 	} else {
    526  1.39.4.1.4.1     matt 		printf("raid%d: parity map disabled\n", raidID);
    527  1.39.4.1.4.1     matt 	}
    528  1.39.4.1.4.1     matt 
    529  1.39.4.1.4.1     matt 	do_ioctl(fd, RAIDFRAME_PARITYMAP_GET_DISABLE, &dis,
    530  1.39.4.1.4.1     matt 	    "RAIDFRAME_PARITYMAP_GET_DISABLE");
    531  1.39.4.1.4.1     matt 	printf("raid%d: parity map will %s %sabled on next configure\n",
    532  1.39.4.1.4.1     matt 	    raidID, dis == st.enabled ? "be" : "remain", dis ? "dis" : "en");
    533  1.39.4.1.4.1     matt }
    534  1.39.4.1.4.1     matt 
    535  1.39.4.1.4.1     matt static void
    536  1.39.4.1.4.1     matt rf_pm_configure(int fd, int raidID, char *parityconf, int parityparams[])
    537  1.39.4.1.4.1     matt {
    538  1.39.4.1.4.1     matt 	int dis;
    539  1.39.4.1.4.1     matt 	struct rf_pmparams params;
    540  1.39.4.1.4.1     matt 
    541  1.39.4.1.4.1     matt 	if (strcasecmp(parityconf, "yes") == 0)
    542  1.39.4.1.4.1     matt 		dis = 0;
    543  1.39.4.1.4.1     matt 	else if (strcasecmp(parityconf, "no") == 0)
    544  1.39.4.1.4.1     matt 		dis = 1;
    545  1.39.4.1.4.1     matt 	else if (strcasecmp(parityconf, "set") == 0) {
    546  1.39.4.1.4.1     matt 		params.cooldown = parityparams[0];
    547  1.39.4.1.4.1     matt 		params.tickms = parityparams[1];
    548  1.39.4.1.4.1     matt 		params.regions = parityparams[2];
    549  1.39.4.1.4.1     matt 
    550  1.39.4.1.4.1     matt 		do_ioctl(fd, RAIDFRAME_PARITYMAP_SET_PARAMS, &params,
    551  1.39.4.1.4.1     matt 		    "RAIDFRAME_PARITYMAP_SET_PARAMS");
    552  1.39.4.1.4.1     matt 
    553  1.39.4.1.4.1     matt 		if (params.cooldown != 0 || params.tickms != 0) {
    554  1.39.4.1.4.1     matt 			printf("raid%d: parity cleaned after", raidID);
    555  1.39.4.1.4.1     matt 			if (params.cooldown != 0)
    556  1.39.4.1.4.1     matt 				printf(" %d", params.cooldown);
    557  1.39.4.1.4.1     matt 			printf(" intervals");
    558  1.39.4.1.4.1     matt 			if (params.tickms != 0) {
    559  1.39.4.1.4.1     matt 				printf(" of %d.%03ds", params.tickms / 1000,
    560  1.39.4.1.4.1     matt 				    params.tickms % 1000);
    561  1.39.4.1.4.1     matt 			}
    562  1.39.4.1.4.1     matt 			printf("\n");
    563  1.39.4.1.4.1     matt 		}
    564  1.39.4.1.4.1     matt 		if (params.regions != 0)
    565  1.39.4.1.4.1     matt 			printf("raid%d: will use %d regions on next"
    566  1.39.4.1.4.1     matt 			    " configuration\n", raidID, params.regions);
    567  1.39.4.1.4.1     matt 
    568  1.39.4.1.4.1     matt 		return;
    569  1.39.4.1.4.1     matt 		/* XXX the control flow here could be prettier. */
    570  1.39.4.1.4.1     matt 	} else {
    571  1.39.4.1.4.1     matt 		fprintf(stderr, "%s: \"%s\" is not a valid parity map command"
    572  1.39.4.1.4.1     matt 		    "\n", getprogname(), parityconf);
    573  1.39.4.1.4.1     matt 		exit(1);
    574  1.39.4.1.4.1     matt 	}
    575  1.39.4.1.4.1     matt 
    576  1.39.4.1.4.1     matt 	do_ioctl(fd, RAIDFRAME_PARITYMAP_SET_DISABLE, &dis,
    577  1.39.4.1.4.1     matt 	    "RAIDFRAME_PARITYMAP_SET_DISABLE");
    578  1.39.4.1.4.1     matt 	printf("raid%d: parity map will be %sabled on next configure\n",
    579  1.39.4.1.4.1     matt 	    raidID, dis ? "dis" : "en");
    580  1.39.4.1.4.1     matt }
    581  1.39.4.1.4.1     matt 
    582  1.39.4.1.4.1     matt 
    583  1.39.4.1.4.1     matt static void
    584          1.36  xtraeme rf_output_configuration(int fd, const char *name)
    585          1.27    lukem {
    586          1.27    lukem 	RF_DeviceConfig_t device_config;
    587          1.27    lukem 	void *cfg_ptr;
    588          1.27    lukem 	int i;
    589          1.27    lukem 	RF_ComponentLabel_t component_label;
    590          1.27    lukem 	void *label_ptr;
    591          1.27    lukem 	int component_num;
    592          1.27    lukem 	int num_cols;
    593          1.27    lukem 
    594          1.27    lukem 	cfg_ptr = &device_config;
    595          1.27    lukem 
    596          1.27    lukem 	printf("# raidctl config file for %s\n", name);
    597          1.27    lukem 	printf("\n");
    598          1.27    lukem 	do_ioctl(fd, RAIDFRAME_GET_INFO, &cfg_ptr, "RAIDFRAME_GET_INFO");
    599          1.27    lukem 
    600          1.27    lukem 	printf("START array\n");
    601          1.27    lukem 	printf("# numRow numCol numSpare\n");
    602          1.27    lukem 	printf("%d %d %d\n", device_config.rows, device_config.cols,
    603          1.27    lukem 	    device_config.nspares);
    604          1.27    lukem 	printf("\n");
    605          1.27    lukem 
    606          1.27    lukem 	printf("START disks\n");
    607          1.27    lukem 	for(i=0; i < device_config.ndevs; i++)
    608          1.27    lukem 		printf("%s\n", device_config.devs[i].devname);
    609          1.27    lukem 	printf("\n");
    610          1.27    lukem 
    611          1.27    lukem 	if (device_config.nspares > 0) {
    612          1.27    lukem 		printf("START spare\n");
    613          1.27    lukem 		for(i=0; i < device_config.nspares; i++)
    614          1.27    lukem 			printf("%s\n", device_config.spares[i].devname);
    615          1.27    lukem 		printf("\n");
    616          1.27    lukem 	}
    617          1.27    lukem 
    618          1.27    lukem 	for(i=0; i < device_config.ndevs; i++) {
    619          1.27    lukem 		if (device_config.devs[i].status == rf_ds_optimal)
    620          1.27    lukem 			break;
    621          1.27    lukem 	}
    622          1.27    lukem 	if (i == device_config.ndevs) {
    623          1.27    lukem 		printf("# WARNING: no optimal components; using %s\n",
    624          1.27    lukem 		    device_config.devs[0].devname);
    625          1.27    lukem 		i = 0;
    626          1.27    lukem 	}
    627          1.27    lukem 	get_component_number(fd, device_config.devs[i].devname,
    628          1.27    lukem 	    &component_num, &num_cols);
    629          1.27    lukem 	memset(&component_label, 0, sizeof(RF_ComponentLabel_t));
    630          1.27    lukem 	component_label.row = component_num / num_cols;
    631          1.27    lukem 	component_label.column = component_num % num_cols;
    632          1.27    lukem 	label_ptr = &component_label;
    633          1.27    lukem 	do_ioctl(fd, RAIDFRAME_GET_COMPONENT_LABEL, &label_ptr,
    634          1.27    lukem 		  "RAIDFRAME_GET_COMPONENT_LABEL");
    635          1.27    lukem 
    636          1.27    lukem 	printf("START layout\n");
    637          1.27    lukem 	printf(
    638          1.27    lukem 	    "# sectPerSU SUsPerParityUnit SUsPerReconUnit RAID_level_%c\n",
    639          1.27    lukem 	    (char) component_label.parityConfig);
    640          1.27    lukem 	printf("%d %d %d %c\n",
    641          1.27    lukem 	    component_label.sectPerSU, component_label.SUsPerPU,
    642          1.27    lukem 	    component_label.SUsPerRU, (char) component_label.parityConfig);
    643          1.27    lukem 	printf("\n");
    644          1.27    lukem 
    645          1.27    lukem 	printf("START queue\n");
    646          1.27    lukem 	printf("fifo %d\n", device_config.maxqdepth);
    647          1.27    lukem }
    648          1.27    lukem 
    649          1.27    lukem static void
    650          1.36  xtraeme get_component_number(int fd, char *component_name, int *component_number,
    651          1.36  xtraeme 		     int *num_columns)
    652           1.1    oster {
    653           1.1    oster 	RF_DeviceConfig_t device_config;
    654           1.1    oster 	void *cfg_ptr;
    655           1.1    oster 	int i;
    656           1.1    oster 	int found;
    657           1.1    oster 
    658           1.6    oster 	*component_number = -1;
    659           1.1    oster 
    660           1.1    oster 	/* Assuming a full path spec... */
    661           1.1    oster 	cfg_ptr = &device_config;
    662           1.1    oster 	do_ioctl(fd, RAIDFRAME_GET_INFO, &cfg_ptr,
    663           1.1    oster 		 "RAIDFRAME_GET_INFO");
    664           1.6    oster 
    665           1.6    oster 	*num_columns = device_config.cols;
    666           1.6    oster 
    667           1.1    oster 	found = 0;
    668           1.1    oster 	for(i=0; i < device_config.ndevs; i++) {
    669           1.6    oster 		if (strncmp(component_name, device_config.devs[i].devname,
    670           1.1    oster 			    PATH_MAX)==0) {
    671           1.1    oster 			found = 1;
    672           1.6    oster 			*component_number = i;
    673           1.1    oster 		}
    674           1.1    oster 	}
    675          1.21    oster 	if (!found) { /* maybe it's a spare? */
    676          1.21    oster 		for(i=0; i < device_config.nspares; i++) {
    677          1.21    oster 			if (strncmp(component_name,
    678          1.21    oster 				    device_config.spares[i].devname,
    679          1.21    oster 				    PATH_MAX)==0) {
    680          1.21    oster 				found = 1;
    681          1.21    oster 				*component_number = i + device_config.ndevs;
    682          1.23    oster 				/* the way spares are done should
    683          1.23    oster 				   really change... */
    684          1.23    oster 				*num_columns = device_config.cols +
    685          1.23    oster 					device_config.nspares;
    686          1.21    oster 			}
    687          1.21    oster 		}
    688          1.21    oster 	}
    689          1.21    oster 
    690           1.1    oster 	if (!found) {
    691          1.26      cgd 		fprintf(stderr,"%s: %s is not a component %s", getprogname(),
    692           1.6    oster 			component_name, "of this device\n");
    693           1.1    oster 		exit(1);
    694           1.1    oster 	}
    695           1.6    oster }
    696           1.6    oster 
    697           1.6    oster static void
    698          1.36  xtraeme rf_fail_disk(int fd, char *component_to_fail, int do_recon)
    699           1.6    oster {
    700           1.6    oster 	struct rf_recon_req recon_request;
    701           1.6    oster 	int component_num;
    702           1.6    oster 	int num_cols;
    703           1.6    oster 
    704           1.6    oster 	get_component_number(fd, component_to_fail, &component_num, &num_cols);
    705           1.1    oster 
    706           1.6    oster 	recon_request.row = component_num / num_cols;
    707           1.6    oster 	recon_request.col = component_num % num_cols;
    708           1.1    oster 	if (do_recon) {
    709           1.1    oster 		recon_request.flags = RF_FDFLAGS_RECON;
    710           1.1    oster 	} else {
    711           1.1    oster 		recon_request.flags = RF_FDFLAGS_NONE;
    712           1.1    oster 	}
    713           1.1    oster 	do_ioctl(fd, RAIDFRAME_FAIL_DISK, &recon_request,
    714           1.1    oster 		 "RAIDFRAME_FAIL_DISK");
    715          1.10    oster 	if (do_recon && verbose) {
    716          1.10    oster 		printf("Reconstruction status:\n");
    717          1.10    oster 		sleep(3); /* XXX give reconstruction a chance to start */
    718          1.19    oster 		do_meter(fd,RAIDFRAME_CHECK_RECON_STATUS_EXT);
    719          1.10    oster 	}
    720           1.1    oster }
    721           1.1    oster 
    722           1.1    oster static void
    723          1.36  xtraeme get_component_label(int fd, char *component)
    724           1.5    oster {
    725           1.5    oster 	RF_ComponentLabel_t component_label;
    726           1.5    oster 	void *label_ptr;
    727           1.5    oster 	int component_num;
    728           1.6    oster 	int num_cols;
    729           1.5    oster 
    730           1.6    oster 	get_component_number(fd, component, &component_num, &num_cols);
    731           1.5    oster 
    732           1.5    oster 	memset( &component_label, 0, sizeof(RF_ComponentLabel_t));
    733           1.6    oster 	component_label.row = component_num / num_cols;
    734           1.6    oster 	component_label.column = component_num % num_cols;
    735           1.5    oster 
    736           1.5    oster 	label_ptr = &component_label;
    737           1.5    oster 	do_ioctl( fd, RAIDFRAME_GET_COMPONENT_LABEL, &label_ptr,
    738           1.5    oster 		  "RAIDFRAME_GET_COMPONENT_LABEL");
    739           1.5    oster 
    740           1.5    oster 	printf("Component label for %s:\n",component);
    741          1.12    oster 
    742          1.25    lukem 	printf("   Row: %d, Column: %d, Num Rows: %d, Num Columns: %d\n",
    743          1.12    oster 	       component_label.row, component_label.column,
    744          1.12    oster 	       component_label.num_rows, component_label.num_columns);
    745          1.25    lukem 	printf("   Version: %d, Serial Number: %d, Mod Counter: %d\n",
    746          1.12    oster 	       component_label.version, component_label.serial_number,
    747          1.12    oster 	       component_label.mod_counter);
    748          1.25    lukem 	printf("   Clean: %s, Status: %d\n",
    749          1.12    oster 	       component_label.clean ? "Yes" : "No",
    750          1.12    oster 	       component_label.status );
    751          1.25    lukem 	printf("   sectPerSU: %d, SUsPerPU: %d, SUsPerRU: %d\n",
    752          1.12    oster 	       component_label.sectPerSU, component_label.SUsPerPU,
    753          1.12    oster 	       component_label.SUsPerRU);
    754      1.39.4.1      snj 	printf("   Queue size: %d, blocksize: %d, numBlocks: %u\n",
    755          1.25    lukem 	       component_label.maxOutstanding, component_label.blockSize,
    756          1.25    lukem 	       component_label.numBlocks);
    757          1.25    lukem 	printf("   RAID Level: %c\n", (char) component_label.parityConfig);
    758          1.12    oster 	printf("   Autoconfig: %s\n",
    759          1.12    oster 	       component_label.autoconfigure ? "Yes" : "No" );
    760          1.15    oster 	printf("   Root partition: %s\n",
    761          1.15    oster 	       component_label.root_partition ? "Yes" : "No" );
    762          1.12    oster 	printf("   Last configured as: raid%d\n", component_label.last_unit );
    763           1.5    oster }
    764           1.5    oster 
    765           1.5    oster static void
    766          1.36  xtraeme set_component_label(int fd, char *component)
    767           1.5    oster {
    768           1.5    oster 	RF_ComponentLabel_t component_label;
    769           1.5    oster 	int component_num;
    770           1.6    oster 	int num_cols;
    771           1.5    oster 
    772           1.6    oster 	get_component_number(fd, component, &component_num, &num_cols);
    773           1.6    oster 
    774           1.6    oster 	/* XXX This is currently here for testing, and future expandability */
    775           1.5    oster 
    776           1.5    oster 	component_label.version = 1;
    777           1.5    oster 	component_label.serial_number = 123456;
    778           1.5    oster 	component_label.mod_counter = 0;
    779           1.6    oster 	component_label.row = component_num / num_cols;
    780           1.6    oster 	component_label.column = component_num % num_cols;
    781           1.5    oster 	component_label.num_rows = 0;
    782           1.5    oster 	component_label.num_columns = 5;
    783           1.5    oster 	component_label.clean = 0;
    784           1.5    oster 	component_label.status = 1;
    785           1.5    oster 
    786           1.5    oster 	do_ioctl( fd, RAIDFRAME_SET_COMPONENT_LABEL, &component_label,
    787           1.5    oster 		  "RAIDFRAME_SET_COMPONENT_LABEL");
    788           1.5    oster }
    789           1.5    oster 
    790           1.5    oster 
    791           1.5    oster static void
    792          1.36  xtraeme init_component_labels(int fd, int serial_number)
    793           1.5    oster {
    794           1.5    oster 	RF_ComponentLabel_t component_label;
    795           1.5    oster 
    796           1.5    oster 	component_label.version = 0;
    797           1.5    oster 	component_label.serial_number = serial_number;
    798           1.5    oster 	component_label.mod_counter = 0;
    799           1.5    oster 	component_label.row = 0;
    800           1.5    oster 	component_label.column = 0;
    801           1.5    oster 	component_label.num_rows = 0;
    802           1.5    oster 	component_label.num_columns = 0;
    803           1.5    oster 	component_label.clean = 0;
    804           1.5    oster 	component_label.status = 0;
    805           1.5    oster 
    806           1.5    oster 	do_ioctl( fd, RAIDFRAME_INIT_LABELS, &component_label,
    807           1.5    oster 		  "RAIDFRAME_SET_COMPONENT_LABEL");
    808          1.12    oster }
    809          1.12    oster 
    810          1.12    oster static void
    811          1.36  xtraeme set_autoconfig(int fd, int raidID, char *autoconf)
    812          1.12    oster {
    813          1.12    oster 	int auto_config;
    814          1.12    oster 	int root_config;
    815          1.12    oster 
    816          1.12    oster 	auto_config = 0;
    817          1.12    oster 	root_config = 0;
    818          1.12    oster 
    819          1.12    oster 	if (strncasecmp(autoconf,"root", 4) == 0) {
    820          1.12    oster 		root_config = 1;
    821          1.12    oster 	}
    822          1.12    oster 
    823          1.12    oster 	if ((strncasecmp(autoconf,"yes", 3) == 0) ||
    824          1.12    oster 	    root_config == 1) {
    825          1.12    oster 		auto_config = 1;
    826          1.12    oster 	}
    827          1.12    oster 
    828          1.12    oster 	do_ioctl(fd, RAIDFRAME_SET_AUTOCONFIG, &auto_config,
    829          1.12    oster 		 "RAIDFRAME_SET_AUTOCONFIG");
    830          1.12    oster 
    831          1.12    oster 	do_ioctl(fd, RAIDFRAME_SET_ROOT, &root_config,
    832          1.12    oster 		 "RAIDFRAME_SET_ROOT");
    833          1.12    oster 
    834          1.12    oster 	printf("raid%d: Autoconfigure: %s\n", raidID,
    835          1.12    oster 	       auto_config ? "Yes" : "No");
    836          1.12    oster 
    837          1.12    oster 	if (root_config == 1) {
    838          1.12    oster 		printf("raid%d: Root: %s\n", raidID,
    839          1.12    oster 		       auto_config ? "Yes" : "No");
    840          1.12    oster 	}
    841           1.5    oster }
    842           1.5    oster 
    843           1.5    oster static void
    844          1.36  xtraeme add_hot_spare(int fd, char *component)
    845           1.5    oster {
    846           1.6    oster 	RF_SingleComponent_t hot_spare;
    847           1.5    oster 
    848           1.6    oster 	hot_spare.row = 0;
    849           1.6    oster 	hot_spare.column = 0;
    850           1.6    oster 	strncpy(hot_spare.component_name, component,
    851           1.6    oster 		sizeof(hot_spare.component_name));
    852           1.5    oster 
    853           1.5    oster 	do_ioctl( fd, RAIDFRAME_ADD_HOT_SPARE, &hot_spare,
    854           1.5    oster 		  "RAIDFRAME_ADD_HOT_SPARE");
    855           1.6    oster }
    856           1.6    oster 
    857           1.6    oster static void
    858          1.36  xtraeme remove_hot_spare(int fd, char *component)
    859           1.6    oster {
    860           1.6    oster 	RF_SingleComponent_t hot_spare;
    861           1.6    oster 	int component_num;
    862           1.6    oster 	int num_cols;
    863           1.5    oster 
    864           1.6    oster 	get_component_number(fd, component, &component_num, &num_cols);
    865           1.6    oster 
    866           1.6    oster 	hot_spare.row = component_num / num_cols;
    867           1.6    oster 	hot_spare.column = component_num % num_cols;
    868           1.6    oster 
    869           1.6    oster 	strncpy(hot_spare.component_name, component,
    870           1.6    oster 		sizeof(hot_spare.component_name));
    871           1.6    oster 
    872           1.6    oster 	do_ioctl( fd, RAIDFRAME_REMOVE_HOT_SPARE, &hot_spare,
    873           1.6    oster 		  "RAIDFRAME_REMOVE_HOT_SPARE");
    874           1.6    oster }
    875           1.6    oster 
    876           1.6    oster static void
    877          1.36  xtraeme rebuild_in_place(int fd, char *component)
    878           1.6    oster {
    879           1.6    oster 	RF_SingleComponent_t comp;
    880           1.6    oster 	int component_num;
    881           1.6    oster 	int num_cols;
    882           1.6    oster 
    883           1.6    oster 	get_component_number(fd, component, &component_num, &num_cols);
    884           1.6    oster 
    885           1.6    oster 	comp.row = 0;
    886           1.6    oster 	comp.column = component_num;
    887           1.6    oster 	strncpy(comp.component_name, component, sizeof(comp.component_name));
    888           1.6    oster 
    889           1.6    oster 	do_ioctl( fd, RAIDFRAME_REBUILD_IN_PLACE, &comp,
    890           1.6    oster 		  "RAIDFRAME_REBUILD_IN_PLACE");
    891          1.10    oster 
    892          1.10    oster 	if (verbose) {
    893          1.10    oster 		printf("Reconstruction status:\n");
    894          1.10    oster 		sleep(3); /* XXX give reconstruction a chance to start */
    895          1.19    oster 		do_meter(fd,RAIDFRAME_CHECK_RECON_STATUS_EXT);
    896          1.10    oster 	}
    897          1.10    oster 
    898          1.10    oster }
    899          1.10    oster 
    900          1.10    oster static void
    901          1.36  xtraeme check_parity(int fd, int do_rewrite, char *dev_name)
    902          1.10    oster {
    903          1.10    oster 	int is_clean;
    904          1.10    oster 	int percent_done;
    905          1.10    oster 
    906          1.10    oster 	is_clean = 0;
    907          1.10    oster 	percent_done = 0;
    908          1.10    oster 	do_ioctl(fd, RAIDFRAME_CHECK_PARITY, &is_clean,
    909          1.10    oster 		 "RAIDFRAME_CHECK_PARITY");
    910          1.10    oster 	if (is_clean) {
    911          1.10    oster 		printf("%s: Parity status: clean\n",dev_name);
    912          1.10    oster 	} else {
    913          1.10    oster 		printf("%s: Parity status: DIRTY\n",dev_name);
    914          1.10    oster 		if (do_rewrite) {
    915          1.10    oster 			printf("%s: Initiating re-write of parity\n",
    916          1.10    oster 			       dev_name);
    917          1.10    oster 			do_ioctl(fd, RAIDFRAME_REWRITEPARITY, NULL,
    918          1.10    oster 				 "RAIDFRAME_REWRITEPARITY");
    919          1.10    oster 			sleep(3); /* XXX give it time to
    920          1.10    oster 				     get started. */
    921          1.10    oster 			if (verbose) {
    922          1.10    oster 				printf("Parity Re-write status:\n");
    923          1.19    oster 				do_meter(fd, RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT);
    924          1.10    oster 			} else {
    925          1.10    oster 				do_ioctl(fd,
    926          1.10    oster 					 RAIDFRAME_CHECK_PARITYREWRITE_STATUS,
    927          1.10    oster 					 &percent_done,
    928          1.10    oster 					 "RAIDFRAME_CHECK_PARITYREWRITE_STATUS"
    929          1.10    oster 					 );
    930          1.10    oster 				while( percent_done < 100 ) {
    931          1.24    oster 					sleep(3); /* wait a bit... */
    932          1.10    oster 					do_ioctl(fd, RAIDFRAME_CHECK_PARITYREWRITE_STATUS,
    933          1.10    oster 						 &percent_done, "RAIDFRAME_CHECK_PARITYREWRITE_STATUS");
    934          1.10    oster 				}
    935          1.10    oster 
    936          1.10    oster 			}
    937          1.10    oster 			       printf("%s: Parity Re-write complete\n",
    938          1.10    oster 				      dev_name);
    939          1.10    oster 		} else {
    940          1.10    oster 			/* parity is wrong, and is not being fixed.
    941          1.10    oster 			   Exit w/ an error. */
    942          1.10    oster 			exit(1);
    943          1.10    oster 		}
    944          1.10    oster 	}
    945          1.10    oster }
    946          1.10    oster 
    947          1.10    oster 
    948          1.10    oster static void
    949          1.36  xtraeme check_status(int fd, int meter)
    950          1.10    oster {
    951          1.10    oster 	int recon_percent_done = 0;
    952          1.10    oster 	int parity_percent_done = 0;
    953          1.10    oster 	int copyback_percent_done = 0;
    954          1.10    oster 
    955          1.10    oster 	do_ioctl(fd, RAIDFRAME_CHECK_RECON_STATUS, &recon_percent_done,
    956          1.10    oster 		 "RAIDFRAME_CHECK_RECON_STATUS");
    957          1.10    oster 	printf("Reconstruction is %d%% complete.\n", recon_percent_done);
    958          1.10    oster 	do_ioctl(fd, RAIDFRAME_CHECK_PARITYREWRITE_STATUS,
    959          1.10    oster 		 &parity_percent_done,
    960          1.10    oster 		 "RAIDFRAME_CHECK_PARITYREWRITE_STATUS");
    961          1.10    oster 	printf("Parity Re-write is %d%% complete.\n", parity_percent_done);
    962          1.10    oster 	do_ioctl(fd, RAIDFRAME_CHECK_COPYBACK_STATUS, &copyback_percent_done,
    963          1.10    oster 		 "RAIDFRAME_CHECK_COPYBACK_STATUS");
    964          1.10    oster 	printf("Copyback is %d%% complete.\n", copyback_percent_done);
    965          1.10    oster 
    966          1.14    oster 	if (meter) {
    967          1.14    oster 		/* These 3 should be mutually exclusive at this point */
    968          1.14    oster 		if (recon_percent_done < 100) {
    969          1.14    oster 			printf("Reconstruction status:\n");
    970          1.19    oster 			do_meter(fd,RAIDFRAME_CHECK_RECON_STATUS_EXT);
    971          1.14    oster 		} else if (parity_percent_done < 100) {
    972          1.14    oster 			printf("Parity Re-write status:\n");
    973          1.19    oster 			do_meter(fd,RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT);
    974          1.14    oster 		} else if (copyback_percent_done < 100) {
    975          1.14    oster 			printf("Copyback status:\n");
    976          1.19    oster 			do_meter(fd,RAIDFRAME_CHECK_COPYBACK_STATUS_EXT);
    977          1.14    oster 		}
    978          1.10    oster 	}
    979          1.10    oster }
    980          1.10    oster 
    981          1.18  thorpej const char *tbits = "|/-\\";
    982          1.10    oster 
    983          1.10    oster static void
    984          1.36  xtraeme do_meter(int fd, u_long option)
    985          1.10    oster {
    986          1.10    oster 	int percent_done;
    987          1.37    oster 	RF_uint64 start_value;
    988          1.19    oster 	RF_ProgressInfo_t progressInfo;
    989          1.19    oster 	void *pInfoPtr;
    990          1.10    oster 	struct timeval start_time;
    991          1.10    oster 	struct timeval current_time;
    992          1.10    oster 	double elapsed;
    993          1.10    oster 	int elapsed_sec;
    994          1.10    oster 	int elapsed_usec;
    995          1.20    oster 	int simple_eta,last_eta;
    996          1.10    oster 	double rate;
    997          1.37    oster 	RF_uint64 amount;
    998          1.10    oster 	int tbit_value;
    999          1.10    oster 	char buffer[1024];
   1000          1.10    oster 	char bar_buffer[1024];
   1001          1.10    oster 	char eta_buffer[1024];
   1002          1.10    oster 
   1003          1.10    oster 	if (gettimeofday(&start_time,NULL)) {
   1004          1.26      cgd 		fprintf(stderr,"%s: gettimeofday failed!?!?\n", getprogname());
   1005          1.10    oster 		exit(errno);
   1006          1.10    oster 	}
   1007          1.19    oster 	memset(&progressInfo, 0, sizeof(RF_ProgressInfo_t));
   1008          1.19    oster 	pInfoPtr=&progressInfo;
   1009          1.19    oster 
   1010          1.10    oster 	percent_done = 0;
   1011          1.19    oster 	do_ioctl(fd, option, &pInfoPtr, "");
   1012          1.37    oster 	start_value = progressInfo.completed;
   1013          1.10    oster 	current_time = start_time;
   1014          1.38    lukem 	simple_eta = 0;
   1015          1.38    lukem 	last_eta = 0;
   1016          1.10    oster 
   1017          1.10    oster 	tbit_value = 0;
   1018          1.19    oster 	while(progressInfo.completed < progressInfo.total) {
   1019          1.10    oster 
   1020          1.19    oster 		percent_done = (progressInfo.completed * 100) /
   1021          1.19    oster 			progressInfo.total;
   1022          1.10    oster 
   1023          1.10    oster 		get_bar(bar_buffer, percent_done, 40);
   1024          1.10    oster 
   1025          1.20    oster 		elapsed_sec = current_time.tv_sec - start_time.tv_sec;
   1026          1.20    oster 		elapsed_usec = current_time.tv_usec - start_time.tv_usec;
   1027          1.10    oster 		if (elapsed_usec < 0) {
   1028          1.10    oster 			elapsed_usec-=1000000;
   1029          1.10    oster 			elapsed_sec++;
   1030          1.10    oster 		}
   1031          1.20    oster 
   1032          1.10    oster 		elapsed = (double) elapsed_sec +
   1033          1.10    oster 			(double) elapsed_usec / 1000000.0;
   1034          1.19    oster 
   1035          1.20    oster 		amount = progressInfo.completed - start_value;
   1036          1.19    oster 
   1037          1.10    oster 		if (amount <= 0) { /* we don't do negatives (yet?) */
   1038          1.10    oster 			amount = 0;
   1039          1.10    oster 		}
   1040          1.20    oster 
   1041          1.22    oster 		if (elapsed == 0)
   1042          1.22    oster 			rate = 0.0;
   1043          1.22    oster 		else
   1044          1.22    oster 			rate = amount / elapsed;
   1045          1.10    oster 
   1046          1.10    oster 		if (rate > 0.0) {
   1047          1.19    oster 			simple_eta = (int) (((double)progressInfo.total -
   1048          1.20    oster 					     (double) progressInfo.completed)
   1049          1.19    oster 					    / rate);
   1050          1.10    oster 		} else {
   1051          1.10    oster 			simple_eta = -1;
   1052          1.10    oster 		}
   1053          1.19    oster 
   1054          1.10    oster 		if (simple_eta <=0) {
   1055          1.10    oster 			simple_eta = last_eta;
   1056          1.10    oster 		} else {
   1057          1.10    oster 			last_eta = simple_eta;
   1058          1.10    oster 		}
   1059          1.10    oster 
   1060          1.20    oster 		get_time_string(eta_buffer, simple_eta);
   1061          1.10    oster 
   1062          1.10    oster 		snprintf(buffer,1024,"\r%3d%% |%s| ETA: %s %c",
   1063          1.10    oster 			 percent_done,bar_buffer,eta_buffer,tbits[tbit_value]);
   1064          1.10    oster 
   1065          1.10    oster 		write(fileno(stdout),buffer,strlen(buffer));
   1066          1.10    oster 		fflush(stdout);
   1067          1.10    oster 
   1068          1.10    oster 		if (++tbit_value>3)
   1069          1.10    oster 			tbit_value = 0;
   1070          1.10    oster 
   1071          1.10    oster 		sleep(2);
   1072          1.10    oster 
   1073          1.10    oster 		if (gettimeofday(&current_time,NULL)) {
   1074          1.10    oster 			fprintf(stderr,"%s: gettimeofday failed!?!?\n",
   1075          1.26      cgd 				getprogname());
   1076          1.10    oster 			exit(errno);
   1077          1.10    oster 		}
   1078          1.10    oster 
   1079          1.19    oster 		do_ioctl( fd, option, &pInfoPtr, "");
   1080          1.10    oster 
   1081          1.10    oster 
   1082          1.10    oster 	}
   1083          1.10    oster 	printf("\n");
   1084          1.10    oster }
   1085          1.10    oster /* 40 '*''s per line, then 40 ' ''s line. */
   1086          1.10    oster /* If you've got a screen wider than 160 characters, "tough" */
   1087          1.10    oster 
   1088          1.10    oster #define STAR_MIDPOINT 4*40
   1089          1.10    oster const char stars[] = "****************************************"
   1090          1.10    oster                      "****************************************"
   1091          1.10    oster                      "****************************************"
   1092          1.10    oster                      "****************************************"
   1093          1.10    oster                      "                                        "
   1094          1.10    oster                      "                                        "
   1095          1.10    oster                      "                                        "
   1096          1.10    oster                      "                                        "
   1097          1.10    oster                      "                                        ";
   1098          1.10    oster 
   1099          1.10    oster static void
   1100          1.36  xtraeme get_bar(char *string, double percent, int max_strlen)
   1101          1.10    oster {
   1102          1.10    oster 	int offset;
   1103          1.10    oster 
   1104          1.10    oster 	if (max_strlen > STAR_MIDPOINT) {
   1105          1.10    oster 		max_strlen = STAR_MIDPOINT;
   1106          1.10    oster 	}
   1107          1.10    oster 	offset = STAR_MIDPOINT -
   1108          1.10    oster 		(int)((percent * max_strlen)/ 100);
   1109          1.10    oster 	if (offset < 0)
   1110          1.10    oster 		offset = 0;
   1111          1.10    oster 	snprintf(string,max_strlen,"%s",&stars[offset]);
   1112          1.10    oster }
   1113          1.10    oster 
   1114          1.10    oster static void
   1115          1.36  xtraeme get_time_string(char *string, int simple_time)
   1116          1.10    oster {
   1117          1.10    oster 	int minutes, seconds, hours;
   1118          1.10    oster 	char hours_buffer[5];
   1119          1.10    oster 	char minutes_buffer[5];
   1120          1.10    oster 	char seconds_buffer[5];
   1121          1.10    oster 
   1122          1.10    oster 	if (simple_time >= 0) {
   1123          1.10    oster 
   1124          1.10    oster 		minutes = (int) simple_time / 60;
   1125          1.10    oster 		seconds = ((int)simple_time - 60*minutes);
   1126          1.10    oster 		hours = minutes / 60;
   1127          1.10    oster 		minutes = minutes - 60*hours;
   1128          1.10    oster 
   1129          1.10    oster 		if (hours > 0) {
   1130          1.10    oster 			snprintf(hours_buffer,5,"%02d:",hours);
   1131          1.10    oster 		} else {
   1132          1.10    oster 			snprintf(hours_buffer,5,"   ");
   1133          1.10    oster 		}
   1134          1.10    oster 
   1135          1.10    oster 		snprintf(minutes_buffer,5,"%02d:",minutes);
   1136          1.10    oster 		snprintf(seconds_buffer,5,"%02d",seconds);
   1137          1.10    oster 		snprintf(string,1024,"%s%s%s",
   1138          1.10    oster 			 hours_buffer, minutes_buffer, seconds_buffer);
   1139          1.10    oster 	} else {
   1140          1.10    oster 		snprintf(string,1024,"   --:--");
   1141          1.10    oster 	}
   1142          1.10    oster 
   1143           1.5    oster }
   1144           1.5    oster 
   1145           1.5    oster static void
   1146          1.36  xtraeme usage(void)
   1147           1.1    oster {
   1148          1.26      cgd 	const char *progname = getprogname();
   1149          1.26      cgd 
   1150          1.26      cgd 	fprintf(stderr, "usage: %s [-v] -a component dev\n", progname);
   1151  1.39.4.1.4.1     matt 	fprintf(stderr, "       %s [-v] -A [yes | no | root] dev\n", progname);
   1152          1.26      cgd 	fprintf(stderr, "       %s [-v] -B dev\n", progname);
   1153          1.26      cgd 	fprintf(stderr, "       %s [-v] -c config_file dev\n", progname);
   1154          1.26      cgd 	fprintf(stderr, "       %s [-v] -C config_file dev\n", progname);
   1155          1.26      cgd 	fprintf(stderr, "       %s [-v] -f component dev\n", progname);
   1156          1.26      cgd 	fprintf(stderr, "       %s [-v] -F component dev\n", progname);
   1157          1.26      cgd 	fprintf(stderr, "       %s [-v] -g component dev\n", progname);
   1158          1.27    lukem 	fprintf(stderr, "       %s [-v] -G dev\n", progname);
   1159          1.26      cgd 	fprintf(stderr, "       %s [-v] -i dev\n", progname);
   1160          1.26      cgd 	fprintf(stderr, "       %s [-v] -I serial_number dev\n", progname);
   1161  1.39.4.1.4.1     matt 	fprintf(stderr, "       %s [-v] -m dev\n", progname);
   1162  1.39.4.1.4.1     matt 	fprintf(stderr, "       %s [-v] -M [yes | no | set params] dev\n",
   1163  1.39.4.1.4.1     matt 	    progname);
   1164          1.31    oster 	fprintf(stderr, "       %s [-v] -p dev\n", progname);
   1165          1.31    oster 	fprintf(stderr, "       %s [-v] -P dev\n", progname);
   1166          1.26      cgd 	fprintf(stderr, "       %s [-v] -r component dev\n", progname);
   1167          1.26      cgd 	fprintf(stderr, "       %s [-v] -R component dev\n", progname);
   1168          1.26      cgd 	fprintf(stderr, "       %s [-v] -s dev\n", progname);
   1169          1.26      cgd 	fprintf(stderr, "       %s [-v] -S dev\n", progname);
   1170          1.26      cgd 	fprintf(stderr, "       %s [-v] -u dev\n", progname);
   1171           1.1    oster 	exit(1);
   1172           1.1    oster 	/* NOTREACHED */
   1173           1.1    oster }
   1174