1 /* $NetBSD: raidctl.c,v 1.42 2009/11/17 18:54:26 jld Exp $ */
4 * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * This program is a re-write of the original rf_ctrl program
34 * distributed by CMU with RAIDframe 1.1.
36 * This program is the user-land interface to the RAIDframe kernel
39 #include <sys/cdefs.h>
42 __RCSID("$NetBSD: raidctl.c,v 1.42 2009/11/17 18:54:26 jld Exp $");
46 #include <sys/param.h>
47 #include <sys/ioctl.h>
49 #include <sys/disklabel.h>
61 #include <rump/rump.h>
62 #include <rump/rump_syscalls.h>
64 #include <dev/raidframe/raidframevar.h>
65 #include <dev/raidframe/raidframeio.h>
66 #include "rf_configure.h"
68 void do_ioctl(int, u_long
, void *, const char *);
69 static void rf_configure(int, char*, int);
70 static const char *device_status(RF_DiskStatus_t
);
71 static void rf_get_device_status(int);
72 static void rf_output_configuration(int, const char *);
73 static void get_component_number(int, char *, int *, int *);
74 static void rf_fail_disk(int, char *, int);
75 static void usage(void);
76 static void get_component_label(int, char *);
77 static void set_component_label(int, char *);
78 static void init_component_labels(int, int);
79 static void set_autoconfig(int, int, char *);
80 static void add_hot_spare(int, char *);
81 static void remove_hot_spare(int, char *);
82 static void rebuild_in_place(int, char *);
83 static void check_status(int,int);
84 static void check_parity(int,int, char *);
85 static void do_meter(int, u_long
);
86 static void get_bar(char *, double, int);
87 static void get_time_string(char *, int);
88 static void rf_output_pmstat(int, int);
89 static void rf_pm_configure(int, int, char *, int[]);
94 main(int argc
,char *argv
[])
99 char config_filename
[PATH_MAX
];
100 char dev_name
[PATH_MAX
];
102 char component
[PATH_MAX
];
104 char *parityconf
= NULL
;
125 openmode
= O_RDWR
; /* default to read/write */
131 while ((ch
= getopt(argc
, argv
, "a:A:Bc:C:f:F:g:GiI:l:mM:r:R:sSpPuv"))
135 action
= RAIDFRAME_ADD_HOT_SPARE
;
136 strlcpy(component
, optarg
, sizeof(component
));
140 action
= RAIDFRAME_SET_AUTOCONFIG
;
141 strlcpy(autoconf
, optarg
, sizeof(autoconf
));
145 action
= RAIDFRAME_COPYBACK
;
149 action
= RAIDFRAME_CONFIGURE
;
150 strlcpy(config_filename
, optarg
,
151 sizeof(config_filename
));
156 strlcpy(config_filename
, optarg
,
157 sizeof(config_filename
));
158 action
= RAIDFRAME_CONFIGURE
;
163 action
= RAIDFRAME_FAIL_DISK
;
164 strlcpy(component
, optarg
, sizeof(component
));
169 action
= RAIDFRAME_FAIL_DISK
;
170 strlcpy(component
, optarg
, sizeof(component
));
175 action
= RAIDFRAME_GET_COMPONENT_LABEL
;
176 strlcpy(component
, optarg
, sizeof(component
));
181 action
= RAIDFRAME_GET_INFO
;
187 action
= RAIDFRAME_REWRITEPARITY
;
191 action
= RAIDFRAME_INIT_LABELS
;
192 serial_number
= atoi(optarg
);
196 action
= RAIDFRAME_PARITYMAP_STATUS
;
201 action
= RAIDFRAME_PARITYMAP_SET_DISABLE
;
202 parityconf
= strdup(optarg
);
204 /* XXXjld: should rf_pm_configure do the atoi()s? */
206 while (i
< 3 && optind
< argc
&&
207 isdigit((int)argv
[optind
][0]))
208 parityparams
[i
++] = atoi(argv
[optind
++]);
210 parityparams
[i
++] = 0;
213 action
= RAIDFRAME_SET_COMPONENT_LABEL
;
214 strlcpy(component
, optarg
, sizeof(component
));
218 action
= RAIDFRAME_REMOVE_HOT_SPARE
;
219 strlcpy(component
, optarg
, sizeof(component
));
223 strlcpy(component
, optarg
, sizeof(component
));
224 action
= RAIDFRAME_REBUILD_IN_PLACE
;
228 action
= RAIDFRAME_GET_INFO
;
233 action
= RAIDFRAME_CHECK_RECON_STATUS_EXT
;
238 action
= RAIDFRAME_CHECK_PARITY
;
243 action
= RAIDFRAME_CHECK_PARITY
;
248 action
= RAIDFRAME_SHUTDOWN
;
253 /* Don't bump num_options, as '-v' is not
254 an option like the others */
263 if ((num_options
> 1) || (argc
== 0))
266 strlcpy(name
, argv
[0], sizeof(name
));
268 fd
= opendisk1(name
, openmode
, dev_name
, sizeof(dev_name
), 0,
271 fd
= opendisk(name
, openmode
, dev_name
, sizeof(dev_name
), 0);
274 fprintf(stderr
, "%s: unable to open device file: %s\n",
275 getprogname(), name
);
278 if (fstat(fd
, &st
) != 0) {
279 fprintf(stderr
,"%s: stat failure on: %s\n",
280 getprogname(), dev_name
);
283 if (!S_ISBLK(st
.st_mode
) && !S_ISCHR(st
.st_mode
)) {
284 fprintf(stderr
,"%s: invalid device: %s\n",
285 getprogname(), dev_name
);
289 raidID
= DISKUNIT(st
.st_rdev
);
292 case RAIDFRAME_ADD_HOT_SPARE
:
293 add_hot_spare(fd
, component
);
295 case RAIDFRAME_REMOVE_HOT_SPARE
:
296 remove_hot_spare(fd
, component
);
298 case RAIDFRAME_CONFIGURE
:
299 rf_configure(fd
, config_filename
, force
);
301 case RAIDFRAME_SET_AUTOCONFIG
:
302 set_autoconfig(fd
, raidID
, autoconf
);
304 case RAIDFRAME_COPYBACK
:
305 printf("Copyback.\n");
306 do_ioctl(fd
, RAIDFRAME_COPYBACK
, NULL
, "RAIDFRAME_COPYBACK");
308 sleep(3); /* XXX give the copyback a chance to start */
309 printf("Copyback status:\n");
310 do_meter(fd
,RAIDFRAME_CHECK_COPYBACK_STATUS_EXT
);
313 case RAIDFRAME_FAIL_DISK
:
314 rf_fail_disk(fd
, component
, do_recon
);
316 case RAIDFRAME_SET_COMPONENT_LABEL
:
317 set_component_label(fd
, component
);
319 case RAIDFRAME_GET_COMPONENT_LABEL
:
320 get_component_label(fd
, component
);
322 case RAIDFRAME_INIT_LABELS
:
323 init_component_labels(fd
, serial_number
);
325 case RAIDFRAME_REWRITEPARITY
:
326 printf("Initiating re-write of parity\n");
327 do_ioctl(fd
, RAIDFRAME_REWRITEPARITY
, NULL
,
328 "RAIDFRAME_REWRITEPARITY");
330 sleep(3); /* XXX give it time to get started */
331 printf("Parity Re-write status:\n");
332 do_meter(fd
, RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT
);
335 case RAIDFRAME_CHECK_RECON_STATUS_EXT
:
338 case RAIDFRAME_GET_INFO
:
340 rf_output_configuration(fd
, dev_name
);
342 rf_get_device_status(fd
);
344 case RAIDFRAME_PARITYMAP_STATUS
:
345 rf_output_pmstat(fd
, raidID
);
347 case RAIDFRAME_PARITYMAP_SET_DISABLE
:
348 rf_pm_configure(fd
, raidID
, parityconf
, parityparams
);
350 case RAIDFRAME_REBUILD_IN_PLACE
:
351 rebuild_in_place(fd
, component
);
353 case RAIDFRAME_CHECK_PARITY
:
354 check_parity(fd
, do_rewrite
, dev_name
);
356 case RAIDFRAME_SHUTDOWN
:
357 do_ioctl(fd
, RAIDFRAME_SHUTDOWN
, NULL
, "RAIDFRAME_SHUTDOWN");
368 do_ioctl(int fd
, unsigned long command
, void *arg
, const char *ioctl_name
)
370 if (ioctl(fd
, command
, arg
) < 0) {
371 warn("ioctl (%s) failed", ioctl_name
);
378 rf_configure(int fd
, char *config_file
, int force
)
383 if (rf_MakeConfig( config_file
, &cfg
) != 0) {
384 fprintf(stderr
,"%s: unable to create RAIDframe %s\n",
385 getprogname(), "configuration structure\n");
392 * Note the extra level of redirection needed here, since
393 * what we really want to pass in is a pointer to the pointer to
394 * the configuration structure.
397 generic
= (void *) &cfg
;
398 do_ioctl(fd
, RAIDFRAME_CONFIGURE
, &generic
, "RAIDFRAME_CONFIGURE");
402 device_status(RF_DiskStatus_t status
)
412 case rf_ds_reconstructing
:
413 return ("reconstructing");
415 case rf_ds_dist_spared
:
416 return ("dist_spared");
424 case rf_ds_used_spare
:
425 return ("used_spare");
434 rf_get_device_status(int fd
)
436 RF_DeviceConfig_t device_config
;
441 cfg_ptr
= &device_config
;
443 do_ioctl(fd
, RAIDFRAME_GET_INFO
, &cfg_ptr
, "RAIDFRAME_GET_INFO");
445 printf("Components:\n");
446 for(i
=0; i
< device_config
.ndevs
; i
++) {
447 printf("%20s: %s\n", device_config
.devs
[i
].devname
,
448 device_status(device_config
.devs
[i
].status
));
450 if (device_config
.nspares
> 0) {
452 for(i
=0; i
< device_config
.nspares
; i
++) {
454 device_config
.spares
[i
].devname
,
455 device_status(device_config
.spares
[i
].status
));
458 printf("No spares.\n");
460 for(i
=0; i
< device_config
.ndevs
; i
++) {
461 if (device_config
.devs
[i
].status
== rf_ds_optimal
) {
462 get_component_label(fd
, device_config
.devs
[i
].devname
);
464 printf("%s status is: %s. Skipping label.\n",
465 device_config
.devs
[i
].devname
,
466 device_status(device_config
.devs
[i
].status
));
470 if (device_config
.nspares
> 0) {
471 for(i
=0; i
< device_config
.nspares
; i
++) {
472 if ((device_config
.spares
[i
].status
==
474 (device_config
.spares
[i
].status
==
476 get_component_label(fd
,
477 device_config
.spares
[i
].devname
);
479 printf("%s status is: %s. Skipping label.\n",
480 device_config
.spares
[i
].devname
,
481 device_status(device_config
.spares
[i
].status
));
486 do_ioctl(fd
, RAIDFRAME_CHECK_PARITY
, &is_clean
,
487 "RAIDFRAME_CHECK_PARITY");
489 printf("Parity status: clean\n");
491 printf("Parity status: DIRTY\n");
497 rf_output_pmstat(int fd
, int raidID
)
504 do_ioctl(fd
, RAIDFRAME_PARITYMAP_STATUS
, &st
,
505 "RAIDFRAME_PARITYMAP_STATUS");
507 if (0 > humanize_number(srs
, 7, st
.region_size
* DEV_BSIZE
,
508 "B", HN_AUTOSCALE
, HN_NOSPACE
))
509 strlcpy(srs
, "???", 7);
511 printf("raid%d: parity map enabled with %u regions of %s\n",
512 raidID
, st
.params
.regions
, srs
);
513 printf("raid%d: regions marked clean after %d intervals of"
514 " %d.%03ds\n", raidID
, st
.params
.cooldown
,
515 st
.params
.tickms
/ 1000, st
.params
.tickms
% 1000);
516 printf("raid%d: write/sync/clean counters "
517 "%"PRIu64
"/%"PRIu64
"/%"PRIu64
"\n", raidID
,
518 st
.ctrs
.nwrite
, st
.ctrs
.ncachesync
, st
.ctrs
.nclearing
);
521 for (i
= 0; i
< RF_PARITYMAP_NREG
; i
++)
522 if (isset(st
.dirty
, i
))
524 printf("raid%d: %d dirty region%s\n", raidID
, dr
,
528 for (i
= 0; i
< RF_PARITYMAP_NBYTE
; i
+= 32) {
530 for (j
= i
; j
< RF_PARITYMAP_NBYTE
532 printf("%x%x", st
.dirty
[j
] & 15,
533 (st
.dirty
[j
] >> 4) & 15);
538 printf("raid%d: parity map disabled\n", raidID
);
541 do_ioctl(fd
, RAIDFRAME_PARITYMAP_GET_DISABLE
, &dis
,
542 "RAIDFRAME_PARITYMAP_GET_DISABLE");
543 printf("raid%d: parity map will %s %sabled on next configure\n",
544 raidID
, dis
== st
.enabled
? "be" : "remain", dis
? "dis" : "en");
548 rf_pm_configure(int fd
, int raidID
, char *parityconf
, int parityparams
[])
551 struct rf_pmparams params
;
553 if (strcasecmp(parityconf
, "yes") == 0)
555 else if (strcasecmp(parityconf
, "no") == 0)
557 else if (strcasecmp(parityconf
, "set") == 0) {
558 params
.cooldown
= parityparams
[0];
559 params
.tickms
= parityparams
[1];
560 params
.regions
= parityparams
[2];
562 do_ioctl(fd
, RAIDFRAME_PARITYMAP_SET_PARAMS
, ¶ms
,
563 "RAIDFRAME_PARITYMAP_SET_PARAMS");
565 if (params
.cooldown
!= 0 || params
.tickms
!= 0) {
566 printf("raid%d: parity cleaned after", raidID
);
567 if (params
.cooldown
!= 0)
568 printf(" %d", params
.cooldown
);
569 printf(" intervals");
570 if (params
.tickms
!= 0) {
571 printf(" of %d.%03ds", params
.tickms
/ 1000,
572 params
.tickms
% 1000);
576 if (params
.regions
!= 0)
577 printf("raid%d: will use %d regions on next"
578 " configuration\n", raidID
, params
.regions
);
581 /* XXX the control flow here could be prettier. */
583 fprintf(stderr
, "%s: \"%s\" is not a valid parity map command"
584 "\n", getprogname(), parityconf
);
588 do_ioctl(fd
, RAIDFRAME_PARITYMAP_SET_DISABLE
, &dis
,
589 "RAIDFRAME_PARITYMAP_SET_DISABLE");
590 printf("raid%d: parity map will be %sabled on next configure\n",
591 raidID
, dis
? "dis" : "en");
596 rf_output_configuration(int fd
, const char *name
)
598 RF_DeviceConfig_t device_config
;
601 RF_ComponentLabel_t component_label
;
606 cfg_ptr
= &device_config
;
608 printf("# raidctl config file for %s\n", name
);
610 do_ioctl(fd
, RAIDFRAME_GET_INFO
, &cfg_ptr
, "RAIDFRAME_GET_INFO");
612 printf("START array\n");
613 printf("# numRow numCol numSpare\n");
614 printf("%d %d %d\n", device_config
.rows
, device_config
.cols
,
615 device_config
.nspares
);
618 printf("START disks\n");
619 for(i
=0; i
< device_config
.ndevs
; i
++)
620 printf("%s\n", device_config
.devs
[i
].devname
);
623 if (device_config
.nspares
> 0) {
624 printf("START spare\n");
625 for(i
=0; i
< device_config
.nspares
; i
++)
626 printf("%s\n", device_config
.spares
[i
].devname
);
630 for(i
=0; i
< device_config
.ndevs
; i
++) {
631 if (device_config
.devs
[i
].status
== rf_ds_optimal
)
634 if (i
== device_config
.ndevs
) {
635 printf("# WARNING: no optimal components; using %s\n",
636 device_config
.devs
[0].devname
);
639 get_component_number(fd
, device_config
.devs
[i
].devname
,
640 &component_num
, &num_cols
);
641 memset(&component_label
, 0, sizeof(RF_ComponentLabel_t
));
642 component_label
.row
= component_num
/ num_cols
;
643 component_label
.column
= component_num
% num_cols
;
644 label_ptr
= &component_label
;
645 do_ioctl(fd
, RAIDFRAME_GET_COMPONENT_LABEL
, &label_ptr
,
646 "RAIDFRAME_GET_COMPONENT_LABEL");
648 printf("START layout\n");
650 "# sectPerSU SUsPerParityUnit SUsPerReconUnit RAID_level_%c\n",
651 (char) component_label
.parityConfig
);
652 printf("%d %d %d %c\n",
653 component_label
.sectPerSU
, component_label
.SUsPerPU
,
654 component_label
.SUsPerRU
, (char) component_label
.parityConfig
);
657 printf("START queue\n");
658 printf("fifo %d\n", device_config
.maxqdepth
);
662 get_component_number(int fd
, char *component_name
, int *component_number
,
665 RF_DeviceConfig_t device_config
;
670 *component_number
= -1;
672 /* Assuming a full path spec... */
673 cfg_ptr
= &device_config
;
674 do_ioctl(fd
, RAIDFRAME_GET_INFO
, &cfg_ptr
,
675 "RAIDFRAME_GET_INFO");
677 *num_columns
= device_config
.cols
;
680 for(i
=0; i
< device_config
.ndevs
; i
++) {
681 if (strncmp(component_name
, device_config
.devs
[i
].devname
,
684 *component_number
= i
;
687 if (!found
) { /* maybe it's a spare? */
688 for(i
=0; i
< device_config
.nspares
; i
++) {
689 if (strncmp(component_name
,
690 device_config
.spares
[i
].devname
,
693 *component_number
= i
+ device_config
.ndevs
;
694 /* the way spares are done should
696 *num_columns
= device_config
.cols
+
697 device_config
.nspares
;
703 fprintf(stderr
,"%s: %s is not a component %s", getprogname(),
704 component_name
, "of this device\n");
710 rf_fail_disk(int fd
, char *component_to_fail
, int do_recon
)
712 struct rf_recon_req recon_request
;
716 get_component_number(fd
, component_to_fail
, &component_num
, &num_cols
);
718 recon_request
.row
= component_num
/ num_cols
;
719 recon_request
.col
= component_num
% num_cols
;
721 recon_request
.flags
= RF_FDFLAGS_RECON
;
723 recon_request
.flags
= RF_FDFLAGS_NONE
;
725 do_ioctl(fd
, RAIDFRAME_FAIL_DISK
, &recon_request
,
726 "RAIDFRAME_FAIL_DISK");
727 if (do_recon
&& verbose
) {
728 printf("Reconstruction status:\n");
729 sleep(3); /* XXX give reconstruction a chance to start */
730 do_meter(fd
,RAIDFRAME_CHECK_RECON_STATUS_EXT
);
735 get_component_label(int fd
, char *component
)
737 RF_ComponentLabel_t component_label
;
742 get_component_number(fd
, component
, &component_num
, &num_cols
);
744 memset( &component_label
, 0, sizeof(RF_ComponentLabel_t
));
745 component_label
.row
= component_num
/ num_cols
;
746 component_label
.column
= component_num
% num_cols
;
748 label_ptr
= &component_label
;
749 do_ioctl( fd
, RAIDFRAME_GET_COMPONENT_LABEL
, &label_ptr
,
750 "RAIDFRAME_GET_COMPONENT_LABEL");
752 printf("Component label for %s:\n",component
);
754 printf(" Row: %d, Column: %d, Num Rows: %d, Num Columns: %d\n",
755 component_label
.row
, component_label
.column
,
756 component_label
.num_rows
, component_label
.num_columns
);
757 printf(" Version: %d, Serial Number: %d, Mod Counter: %d\n",
758 component_label
.version
, component_label
.serial_number
,
759 component_label
.mod_counter
);
760 printf(" Clean: %s, Status: %d\n",
761 component_label
.clean
? "Yes" : "No",
762 component_label
.status
);
763 printf(" sectPerSU: %d, SUsPerPU: %d, SUsPerRU: %d\n",
764 component_label
.sectPerSU
, component_label
.SUsPerPU
,
765 component_label
.SUsPerRU
);
766 printf(" Queue size: %d, blocksize: %d, numBlocks: %u\n",
767 component_label
.maxOutstanding
, component_label
.blockSize
,
768 component_label
.numBlocks
);
769 printf(" RAID Level: %c\n", (char) component_label
.parityConfig
);
770 printf(" Autoconfig: %s\n",
771 component_label
.autoconfigure
? "Yes" : "No" );
772 printf(" Root partition: %s\n",
773 component_label
.root_partition
? "Yes" : "No" );
774 printf(" Last configured as: raid%d\n", component_label
.last_unit
);
778 set_component_label(int fd
, char *component
)
780 RF_ComponentLabel_t component_label
;
784 get_component_number(fd
, component
, &component_num
, &num_cols
);
786 /* XXX This is currently here for testing, and future expandability */
788 component_label
.version
= 1;
789 component_label
.serial_number
= 123456;
790 component_label
.mod_counter
= 0;
791 component_label
.row
= component_num
/ num_cols
;
792 component_label
.column
= component_num
% num_cols
;
793 component_label
.num_rows
= 0;
794 component_label
.num_columns
= 5;
795 component_label
.clean
= 0;
796 component_label
.status
= 1;
798 do_ioctl( fd
, RAIDFRAME_SET_COMPONENT_LABEL
, &component_label
,
799 "RAIDFRAME_SET_COMPONENT_LABEL");
804 init_component_labels(int fd
, int serial_number
)
806 RF_ComponentLabel_t component_label
;
808 component_label
.version
= 0;
809 component_label
.serial_number
= serial_number
;
810 component_label
.mod_counter
= 0;
811 component_label
.row
= 0;
812 component_label
.column
= 0;
813 component_label
.num_rows
= 0;
814 component_label
.num_columns
= 0;
815 component_label
.clean
= 0;
816 component_label
.status
= 0;
818 do_ioctl( fd
, RAIDFRAME_INIT_LABELS
, &component_label
,
819 "RAIDFRAME_SET_COMPONENT_LABEL");
823 set_autoconfig(int fd
, int raidID
, char *autoconf
)
831 if (strncasecmp(autoconf
,"root", 4) == 0) {
835 if ((strncasecmp(autoconf
,"yes", 3) == 0) ||
840 do_ioctl(fd
, RAIDFRAME_SET_AUTOCONFIG
, &auto_config
,
841 "RAIDFRAME_SET_AUTOCONFIG");
843 do_ioctl(fd
, RAIDFRAME_SET_ROOT
, &root_config
,
844 "RAIDFRAME_SET_ROOT");
846 printf("raid%d: Autoconfigure: %s\n", raidID
,
847 auto_config
? "Yes" : "No");
849 if (root_config
== 1) {
850 printf("raid%d: Root: %s\n", raidID
,
851 auto_config
? "Yes" : "No");
856 add_hot_spare(int fd
, char *component
)
858 RF_SingleComponent_t hot_spare
;
861 hot_spare
.column
= 0;
862 strncpy(hot_spare
.component_name
, component
,
863 sizeof(hot_spare
.component_name
));
865 do_ioctl( fd
, RAIDFRAME_ADD_HOT_SPARE
, &hot_spare
,
866 "RAIDFRAME_ADD_HOT_SPARE");
870 remove_hot_spare(int fd
, char *component
)
872 RF_SingleComponent_t hot_spare
;
876 get_component_number(fd
, component
, &component_num
, &num_cols
);
878 hot_spare
.row
= component_num
/ num_cols
;
879 hot_spare
.column
= component_num
% num_cols
;
881 strncpy(hot_spare
.component_name
, component
,
882 sizeof(hot_spare
.component_name
));
884 do_ioctl( fd
, RAIDFRAME_REMOVE_HOT_SPARE
, &hot_spare
,
885 "RAIDFRAME_REMOVE_HOT_SPARE");
889 rebuild_in_place(int fd
, char *component
)
891 RF_SingleComponent_t comp
;
895 get_component_number(fd
, component
, &component_num
, &num_cols
);
898 comp
.column
= component_num
;
899 strncpy(comp
.component_name
, component
, sizeof(comp
.component_name
));
901 do_ioctl( fd
, RAIDFRAME_REBUILD_IN_PLACE
, &comp
,
902 "RAIDFRAME_REBUILD_IN_PLACE");
905 printf("Reconstruction status:\n");
906 sleep(3); /* XXX give reconstruction a chance to start */
907 do_meter(fd
,RAIDFRAME_CHECK_RECON_STATUS_EXT
);
913 check_parity(int fd
, int do_rewrite
, char *dev_name
)
920 do_ioctl(fd
, RAIDFRAME_CHECK_PARITY
, &is_clean
,
921 "RAIDFRAME_CHECK_PARITY");
923 printf("%s: Parity status: clean\n",dev_name
);
925 printf("%s: Parity status: DIRTY\n",dev_name
);
927 printf("%s: Initiating re-write of parity\n",
929 do_ioctl(fd
, RAIDFRAME_REWRITEPARITY
, NULL
,
930 "RAIDFRAME_REWRITEPARITY");
931 sleep(3); /* XXX give it time to
934 printf("Parity Re-write status:\n");
935 do_meter(fd
, RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT
);
938 RAIDFRAME_CHECK_PARITYREWRITE_STATUS
,
940 "RAIDFRAME_CHECK_PARITYREWRITE_STATUS"
942 while( percent_done
< 100 ) {
943 sleep(3); /* wait a bit... */
944 do_ioctl(fd
, RAIDFRAME_CHECK_PARITYREWRITE_STATUS
,
945 &percent_done
, "RAIDFRAME_CHECK_PARITYREWRITE_STATUS");
949 printf("%s: Parity Re-write complete\n",
952 /* parity is wrong, and is not being fixed.
961 check_status(int fd
, int meter
)
963 int recon_percent_done
= 0;
964 int parity_percent_done
= 0;
965 int copyback_percent_done
= 0;
967 do_ioctl(fd
, RAIDFRAME_CHECK_RECON_STATUS
, &recon_percent_done
,
968 "RAIDFRAME_CHECK_RECON_STATUS");
969 printf("Reconstruction is %d%% complete.\n", recon_percent_done
);
970 do_ioctl(fd
, RAIDFRAME_CHECK_PARITYREWRITE_STATUS
,
971 &parity_percent_done
,
972 "RAIDFRAME_CHECK_PARITYREWRITE_STATUS");
973 printf("Parity Re-write is %d%% complete.\n", parity_percent_done
);
974 do_ioctl(fd
, RAIDFRAME_CHECK_COPYBACK_STATUS
, ©back_percent_done
,
975 "RAIDFRAME_CHECK_COPYBACK_STATUS");
976 printf("Copyback is %d%% complete.\n", copyback_percent_done
);
979 /* These 3 should be mutually exclusive at this point */
980 if (recon_percent_done
< 100) {
981 printf("Reconstruction status:\n");
982 do_meter(fd
,RAIDFRAME_CHECK_RECON_STATUS_EXT
);
983 } else if (parity_percent_done
< 100) {
984 printf("Parity Re-write status:\n");
985 do_meter(fd
,RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT
);
986 } else if (copyback_percent_done
< 100) {
987 printf("Copyback status:\n");
988 do_meter(fd
,RAIDFRAME_CHECK_COPYBACK_STATUS_EXT
);
993 const char *tbits
= "|/-\\";
996 do_meter(int fd
, u_long option
)
999 RF_uint64 start_value
;
1000 RF_ProgressInfo_t progressInfo
;
1002 struct timeval start_time
;
1003 struct timeval current_time
;
1007 int simple_eta
,last_eta
;
1012 char bar_buffer
[1024];
1013 char eta_buffer
[1024];
1015 if (gettimeofday(&start_time
,NULL
)) {
1016 fprintf(stderr
,"%s: gettimeofday failed!?!?\n", getprogname());
1019 memset(&progressInfo
, 0, sizeof(RF_ProgressInfo_t
));
1020 pInfoPtr
=&progressInfo
;
1023 do_ioctl(fd
, option
, &pInfoPtr
, "");
1024 start_value
= progressInfo
.completed
;
1025 current_time
= start_time
;
1030 while(progressInfo
.completed
< progressInfo
.total
) {
1032 percent_done
= (progressInfo
.completed
* 100) /
1035 get_bar(bar_buffer
, percent_done
, 40);
1037 elapsed_sec
= current_time
.tv_sec
- start_time
.tv_sec
;
1038 elapsed_usec
= current_time
.tv_usec
- start_time
.tv_usec
;
1039 if (elapsed_usec
< 0) {
1040 elapsed_usec
-=1000000;
1044 elapsed
= (double) elapsed_sec
+
1045 (double) elapsed_usec
/ 1000000.0;
1047 amount
= progressInfo
.completed
- start_value
;
1049 if (amount
<= 0) { /* we don't do negatives (yet?) */
1056 rate
= amount
/ elapsed
;
1059 simple_eta
= (int) (((double)progressInfo
.total
-
1060 (double) progressInfo
.completed
)
1066 if (simple_eta
<=0) {
1067 simple_eta
= last_eta
;
1069 last_eta
= simple_eta
;
1072 get_time_string(eta_buffer
, simple_eta
);
1074 snprintf(buffer
,1024,"\r%3d%% |%s| ETA: %s %c",
1075 percent_done
,bar_buffer
,eta_buffer
,tbits
[tbit_value
]);
1077 write(fileno(stdout
),buffer
,strlen(buffer
));
1085 if (gettimeofday(¤t_time
,NULL
)) {
1086 fprintf(stderr
,"%s: gettimeofday failed!?!?\n",
1091 do_ioctl( fd
, option
, &pInfoPtr
, "");
1097 /* 40 '*''s per line, then 40 ' ''s line. */
1098 /* If you've got a screen wider than 160 characters, "tough" */
1100 #define STAR_MIDPOINT 4*40
1101 const char stars
[] = "****************************************"
1102 "****************************************"
1103 "****************************************"
1104 "****************************************"
1112 get_bar(char *string
, double percent
, int max_strlen
)
1116 if (max_strlen
> STAR_MIDPOINT
) {
1117 max_strlen
= STAR_MIDPOINT
;
1119 offset
= STAR_MIDPOINT
-
1120 (int)((percent
* max_strlen
)/ 100);
1123 snprintf(string
,max_strlen
,"%s",&stars
[offset
]);
1127 get_time_string(char *string
, int simple_time
)
1129 int minutes
, seconds
, hours
;
1130 char hours_buffer
[5];
1131 char minutes_buffer
[5];
1132 char seconds_buffer
[5];
1134 if (simple_time
>= 0) {
1136 minutes
= (int) simple_time
/ 60;
1137 seconds
= ((int)simple_time
- 60*minutes
);
1138 hours
= minutes
/ 60;
1139 minutes
= minutes
- 60*hours
;
1142 snprintf(hours_buffer
,5,"%02d:",hours
);
1144 snprintf(hours_buffer
,5," ");
1147 snprintf(minutes_buffer
,5,"%02d:",minutes
);
1148 snprintf(seconds_buffer
,5,"%02d",seconds
);
1149 snprintf(string
,1024,"%s%s%s",
1150 hours_buffer
, minutes_buffer
, seconds_buffer
);
1152 snprintf(string
,1024," --:--");
1160 const char *progname
= getprogname();
1162 fprintf(stderr
, "usage: %s [-v] -a component dev\n", progname
);
1163 fprintf(stderr
, " %s [-v] -A [yes | no | root] dev\n", progname
);
1164 fprintf(stderr
, " %s [-v] -B dev\n", progname
);
1165 fprintf(stderr
, " %s [-v] -c config_file dev\n", progname
);
1166 fprintf(stderr
, " %s [-v] -C config_file dev\n", progname
);
1167 fprintf(stderr
, " %s [-v] -f component dev\n", progname
);
1168 fprintf(stderr
, " %s [-v] -F component dev\n", progname
);
1169 fprintf(stderr
, " %s [-v] -g component dev\n", progname
);
1170 fprintf(stderr
, " %s [-v] -G dev\n", progname
);
1171 fprintf(stderr
, " %s [-v] -i dev\n", progname
);
1172 fprintf(stderr
, " %s [-v] -I serial_number dev\n", progname
);
1173 fprintf(stderr
, " %s [-v] -m dev\n", progname
);
1174 fprintf(stderr
, " %s [-v] -M [yes | no | set params] dev\n",
1176 fprintf(stderr
, " %s [-v] -p dev\n", progname
);
1177 fprintf(stderr
, " %s [-v] -P dev\n", progname
);
1178 fprintf(stderr
, " %s [-v] -r component dev\n", progname
);
1179 fprintf(stderr
, " %s [-v] -R component dev\n", progname
);
1180 fprintf(stderr
, " %s [-v] -s dev\n", progname
);
1181 fprintf(stderr
, " %s [-v] -S dev\n", progname
);
1182 fprintf(stderr
, " %s [-v] -u dev\n", progname
);