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