1 /* $NetBSD: raidctl.c,v 1.40 2009/01/26 11:34:12 tron 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.40 2009/01/26 11:34:12 tron 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);
92 main(int argc
,char *argv
[])
97 char config_filename
[PATH_MAX
];
98 char dev_name
[PATH_MAX
];
100 char component
[PATH_MAX
];
121 openmode
= O_RDWR
; /* default to read/write */
127 while ((ch
= getopt(argc
, argv
, "a:A:Bc:C:f:F:g:GiI:l:r:R:sSpPuv"))
131 action
= RAIDFRAME_ADD_HOT_SPARE
;
132 strlcpy(component
, optarg
, sizeof(component
));
136 action
= RAIDFRAME_SET_AUTOCONFIG
;
137 strlcpy(autoconf
, optarg
, sizeof(autoconf
));
141 action
= RAIDFRAME_COPYBACK
;
145 action
= RAIDFRAME_CONFIGURE
;
146 strlcpy(config_filename
, optarg
,
147 sizeof(config_filename
));
152 strlcpy(config_filename
, optarg
,
153 sizeof(config_filename
));
154 action
= RAIDFRAME_CONFIGURE
;
159 action
= RAIDFRAME_FAIL_DISK
;
160 strlcpy(component
, optarg
, sizeof(component
));
165 action
= RAIDFRAME_FAIL_DISK
;
166 strlcpy(component
, optarg
, sizeof(component
));
171 action
= RAIDFRAME_GET_COMPONENT_LABEL
;
172 strlcpy(component
, optarg
, sizeof(component
));
177 action
= RAIDFRAME_GET_INFO
;
183 action
= RAIDFRAME_REWRITEPARITY
;
187 action
= RAIDFRAME_INIT_LABELS
;
188 serial_number
= atoi(optarg
);
192 action
= RAIDFRAME_SET_COMPONENT_LABEL
;
193 strlcpy(component
, optarg
, sizeof(component
));
197 action
= RAIDFRAME_REMOVE_HOT_SPARE
;
198 strlcpy(component
, optarg
, sizeof(component
));
202 strlcpy(component
, optarg
, sizeof(component
));
203 action
= RAIDFRAME_REBUILD_IN_PLACE
;
207 action
= RAIDFRAME_GET_INFO
;
212 action
= RAIDFRAME_CHECK_RECON_STATUS_EXT
;
217 action
= RAIDFRAME_CHECK_PARITY
;
222 action
= RAIDFRAME_CHECK_PARITY
;
227 action
= RAIDFRAME_SHUTDOWN
;
232 /* Don't bump num_options, as '-v' is not
233 an option like the others */
242 if ((num_options
> 1) || (argc
== 0))
245 strlcpy(name
, argv
[0], sizeof(name
));
247 fd
= opendisk1(name
, openmode
, dev_name
, sizeof(dev_name
), 0,
250 fd
= opendisk(name
, openmode
, dev_name
, sizeof(dev_name
), 0);
253 fprintf(stderr
, "%s: unable to open device file: %s\n",
254 getprogname(), name
);
257 if (fstat(fd
, &st
) != 0) {
258 fprintf(stderr
,"%s: stat failure on: %s\n",
259 getprogname(), dev_name
);
262 if (!S_ISBLK(st
.st_mode
) && !S_ISCHR(st
.st_mode
)) {
263 fprintf(stderr
,"%s: invalid device: %s\n",
264 getprogname(), dev_name
);
268 raidID
= DISKUNIT(st
.st_rdev
);
271 case RAIDFRAME_ADD_HOT_SPARE
:
272 add_hot_spare(fd
, component
);
274 case RAIDFRAME_REMOVE_HOT_SPARE
:
275 remove_hot_spare(fd
, component
);
277 case RAIDFRAME_CONFIGURE
:
278 rf_configure(fd
, config_filename
, force
);
280 case RAIDFRAME_SET_AUTOCONFIG
:
281 set_autoconfig(fd
, raidID
, autoconf
);
283 case RAIDFRAME_COPYBACK
:
284 printf("Copyback.\n");
285 do_ioctl(fd
, RAIDFRAME_COPYBACK
, NULL
, "RAIDFRAME_COPYBACK");
287 sleep(3); /* XXX give the copyback a chance to start */
288 printf("Copyback status:\n");
289 do_meter(fd
,RAIDFRAME_CHECK_COPYBACK_STATUS_EXT
);
292 case RAIDFRAME_FAIL_DISK
:
293 rf_fail_disk(fd
, component
, do_recon
);
295 case RAIDFRAME_SET_COMPONENT_LABEL
:
296 set_component_label(fd
, component
);
298 case RAIDFRAME_GET_COMPONENT_LABEL
:
299 get_component_label(fd
, component
);
301 case RAIDFRAME_INIT_LABELS
:
302 init_component_labels(fd
, serial_number
);
304 case RAIDFRAME_REWRITEPARITY
:
305 printf("Initiating re-write of parity\n");
306 do_ioctl(fd
, RAIDFRAME_REWRITEPARITY
, NULL
,
307 "RAIDFRAME_REWRITEPARITY");
309 sleep(3); /* XXX give it time to get started */
310 printf("Parity Re-write status:\n");
311 do_meter(fd
, RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT
);
314 case RAIDFRAME_CHECK_RECON_STATUS_EXT
:
317 case RAIDFRAME_GET_INFO
:
319 rf_output_configuration(fd
, dev_name
);
321 rf_get_device_status(fd
);
323 case RAIDFRAME_REBUILD_IN_PLACE
:
324 rebuild_in_place(fd
, component
);
326 case RAIDFRAME_CHECK_PARITY
:
327 check_parity(fd
, do_rewrite
, dev_name
);
329 case RAIDFRAME_SHUTDOWN
:
330 do_ioctl(fd
, RAIDFRAME_SHUTDOWN
, NULL
, "RAIDFRAME_SHUTDOWN");
341 do_ioctl(int fd
, unsigned long command
, void *arg
, const char *ioctl_name
)
343 if (ioctl(fd
, command
, arg
) < 0) {
344 warn("ioctl (%s) failed", ioctl_name
);
351 rf_configure(int fd
, char *config_file
, int force
)
356 if (rf_MakeConfig( config_file
, &cfg
) != 0) {
357 fprintf(stderr
,"%s: unable to create RAIDframe %s\n",
358 getprogname(), "configuration structure\n");
365 * Note the extra level of redirection needed here, since
366 * what we really want to pass in is a pointer to the pointer to
367 * the configuration structure.
370 generic
= (void *) &cfg
;
371 do_ioctl(fd
, RAIDFRAME_CONFIGURE
, &generic
, "RAIDFRAME_CONFIGURE");
375 device_status(RF_DiskStatus_t status
)
385 case rf_ds_reconstructing
:
386 return ("reconstructing");
388 case rf_ds_dist_spared
:
389 return ("dist_spared");
397 case rf_ds_used_spare
:
398 return ("used_spare");
407 rf_get_device_status(int fd
)
409 RF_DeviceConfig_t device_config
;
414 cfg_ptr
= &device_config
;
416 do_ioctl(fd
, RAIDFRAME_GET_INFO
, &cfg_ptr
, "RAIDFRAME_GET_INFO");
418 printf("Components:\n");
419 for(i
=0; i
< device_config
.ndevs
; i
++) {
420 printf("%20s: %s\n", device_config
.devs
[i
].devname
,
421 device_status(device_config
.devs
[i
].status
));
423 if (device_config
.nspares
> 0) {
425 for(i
=0; i
< device_config
.nspares
; i
++) {
427 device_config
.spares
[i
].devname
,
428 device_status(device_config
.spares
[i
].status
));
431 printf("No spares.\n");
433 for(i
=0; i
< device_config
.ndevs
; i
++) {
434 if (device_config
.devs
[i
].status
== rf_ds_optimal
) {
435 get_component_label(fd
, device_config
.devs
[i
].devname
);
437 printf("%s status is: %s. Skipping label.\n",
438 device_config
.devs
[i
].devname
,
439 device_status(device_config
.devs
[i
].status
));
443 if (device_config
.nspares
> 0) {
444 for(i
=0; i
< device_config
.nspares
; i
++) {
445 if ((device_config
.spares
[i
].status
==
447 (device_config
.spares
[i
].status
==
449 get_component_label(fd
,
450 device_config
.spares
[i
].devname
);
452 printf("%s status is: %s. Skipping label.\n",
453 device_config
.spares
[i
].devname
,
454 device_status(device_config
.spares
[i
].status
));
459 do_ioctl(fd
, RAIDFRAME_CHECK_PARITY
, &is_clean
,
460 "RAIDFRAME_CHECK_PARITY");
462 printf("Parity status: clean\n");
464 printf("Parity status: DIRTY\n");
470 rf_output_configuration(int fd
, const char *name
)
472 RF_DeviceConfig_t device_config
;
475 RF_ComponentLabel_t component_label
;
480 cfg_ptr
= &device_config
;
482 printf("# raidctl config file for %s\n", name
);
484 do_ioctl(fd
, RAIDFRAME_GET_INFO
, &cfg_ptr
, "RAIDFRAME_GET_INFO");
486 printf("START array\n");
487 printf("# numRow numCol numSpare\n");
488 printf("%d %d %d\n", device_config
.rows
, device_config
.cols
,
489 device_config
.nspares
);
492 printf("START disks\n");
493 for(i
=0; i
< device_config
.ndevs
; i
++)
494 printf("%s\n", device_config
.devs
[i
].devname
);
497 if (device_config
.nspares
> 0) {
498 printf("START spare\n");
499 for(i
=0; i
< device_config
.nspares
; i
++)
500 printf("%s\n", device_config
.spares
[i
].devname
);
504 for(i
=0; i
< device_config
.ndevs
; i
++) {
505 if (device_config
.devs
[i
].status
== rf_ds_optimal
)
508 if (i
== device_config
.ndevs
) {
509 printf("# WARNING: no optimal components; using %s\n",
510 device_config
.devs
[0].devname
);
513 get_component_number(fd
, device_config
.devs
[i
].devname
,
514 &component_num
, &num_cols
);
515 memset(&component_label
, 0, sizeof(RF_ComponentLabel_t
));
516 component_label
.row
= component_num
/ num_cols
;
517 component_label
.column
= component_num
% num_cols
;
518 label_ptr
= &component_label
;
519 do_ioctl(fd
, RAIDFRAME_GET_COMPONENT_LABEL
, &label_ptr
,
520 "RAIDFRAME_GET_COMPONENT_LABEL");
522 printf("START layout\n");
524 "# sectPerSU SUsPerParityUnit SUsPerReconUnit RAID_level_%c\n",
525 (char) component_label
.parityConfig
);
526 printf("%d %d %d %c\n",
527 component_label
.sectPerSU
, component_label
.SUsPerPU
,
528 component_label
.SUsPerRU
, (char) component_label
.parityConfig
);
531 printf("START queue\n");
532 printf("fifo %d\n", device_config
.maxqdepth
);
536 get_component_number(int fd
, char *component_name
, int *component_number
,
539 RF_DeviceConfig_t device_config
;
544 *component_number
= -1;
546 /* Assuming a full path spec... */
547 cfg_ptr
= &device_config
;
548 do_ioctl(fd
, RAIDFRAME_GET_INFO
, &cfg_ptr
,
549 "RAIDFRAME_GET_INFO");
551 *num_columns
= device_config
.cols
;
554 for(i
=0; i
< device_config
.ndevs
; i
++) {
555 if (strncmp(component_name
, device_config
.devs
[i
].devname
,
558 *component_number
= i
;
561 if (!found
) { /* maybe it's a spare? */
562 for(i
=0; i
< device_config
.nspares
; i
++) {
563 if (strncmp(component_name
,
564 device_config
.spares
[i
].devname
,
567 *component_number
= i
+ device_config
.ndevs
;
568 /* the way spares are done should
570 *num_columns
= device_config
.cols
+
571 device_config
.nspares
;
577 fprintf(stderr
,"%s: %s is not a component %s", getprogname(),
578 component_name
, "of this device\n");
584 rf_fail_disk(int fd
, char *component_to_fail
, int do_recon
)
586 struct rf_recon_req recon_request
;
590 get_component_number(fd
, component_to_fail
, &component_num
, &num_cols
);
592 recon_request
.row
= component_num
/ num_cols
;
593 recon_request
.col
= component_num
% num_cols
;
595 recon_request
.flags
= RF_FDFLAGS_RECON
;
597 recon_request
.flags
= RF_FDFLAGS_NONE
;
599 do_ioctl(fd
, RAIDFRAME_FAIL_DISK
, &recon_request
,
600 "RAIDFRAME_FAIL_DISK");
601 if (do_recon
&& verbose
) {
602 printf("Reconstruction status:\n");
603 sleep(3); /* XXX give reconstruction a chance to start */
604 do_meter(fd
,RAIDFRAME_CHECK_RECON_STATUS_EXT
);
609 get_component_label(int fd
, char *component
)
611 RF_ComponentLabel_t component_label
;
616 get_component_number(fd
, component
, &component_num
, &num_cols
);
618 memset( &component_label
, 0, sizeof(RF_ComponentLabel_t
));
619 component_label
.row
= component_num
/ num_cols
;
620 component_label
.column
= component_num
% num_cols
;
622 label_ptr
= &component_label
;
623 do_ioctl( fd
, RAIDFRAME_GET_COMPONENT_LABEL
, &label_ptr
,
624 "RAIDFRAME_GET_COMPONENT_LABEL");
626 printf("Component label for %s:\n",component
);
628 printf(" Row: %d, Column: %d, Num Rows: %d, Num Columns: %d\n",
629 component_label
.row
, component_label
.column
,
630 component_label
.num_rows
, component_label
.num_columns
);
631 printf(" Version: %d, Serial Number: %d, Mod Counter: %d\n",
632 component_label
.version
, component_label
.serial_number
,
633 component_label
.mod_counter
);
634 printf(" Clean: %s, Status: %d\n",
635 component_label
.clean
? "Yes" : "No",
636 component_label
.status
);
637 printf(" sectPerSU: %d, SUsPerPU: %d, SUsPerRU: %d\n",
638 component_label
.sectPerSU
, component_label
.SUsPerPU
,
639 component_label
.SUsPerRU
);
640 printf(" Queue size: %d, blocksize: %d, numBlocks: %u\n",
641 component_label
.maxOutstanding
, component_label
.blockSize
,
642 component_label
.numBlocks
);
643 printf(" RAID Level: %c\n", (char) component_label
.parityConfig
);
644 printf(" Autoconfig: %s\n",
645 component_label
.autoconfigure
? "Yes" : "No" );
646 printf(" Root partition: %s\n",
647 component_label
.root_partition
? "Yes" : "No" );
648 printf(" Last configured as: raid%d\n", component_label
.last_unit
);
652 set_component_label(int fd
, char *component
)
654 RF_ComponentLabel_t component_label
;
658 get_component_number(fd
, component
, &component_num
, &num_cols
);
660 /* XXX This is currently here for testing, and future expandability */
662 component_label
.version
= 1;
663 component_label
.serial_number
= 123456;
664 component_label
.mod_counter
= 0;
665 component_label
.row
= component_num
/ num_cols
;
666 component_label
.column
= component_num
% num_cols
;
667 component_label
.num_rows
= 0;
668 component_label
.num_columns
= 5;
669 component_label
.clean
= 0;
670 component_label
.status
= 1;
672 do_ioctl( fd
, RAIDFRAME_SET_COMPONENT_LABEL
, &component_label
,
673 "RAIDFRAME_SET_COMPONENT_LABEL");
678 init_component_labels(int fd
, int serial_number
)
680 RF_ComponentLabel_t component_label
;
682 component_label
.version
= 0;
683 component_label
.serial_number
= serial_number
;
684 component_label
.mod_counter
= 0;
685 component_label
.row
= 0;
686 component_label
.column
= 0;
687 component_label
.num_rows
= 0;
688 component_label
.num_columns
= 0;
689 component_label
.clean
= 0;
690 component_label
.status
= 0;
692 do_ioctl( fd
, RAIDFRAME_INIT_LABELS
, &component_label
,
693 "RAIDFRAME_SET_COMPONENT_LABEL");
697 set_autoconfig(int fd
, int raidID
, char *autoconf
)
705 if (strncasecmp(autoconf
,"root", 4) == 0) {
709 if ((strncasecmp(autoconf
,"yes", 3) == 0) ||
714 do_ioctl(fd
, RAIDFRAME_SET_AUTOCONFIG
, &auto_config
,
715 "RAIDFRAME_SET_AUTOCONFIG");
717 do_ioctl(fd
, RAIDFRAME_SET_ROOT
, &root_config
,
718 "RAIDFRAME_SET_ROOT");
720 printf("raid%d: Autoconfigure: %s\n", raidID
,
721 auto_config
? "Yes" : "No");
723 if (root_config
== 1) {
724 printf("raid%d: Root: %s\n", raidID
,
725 auto_config
? "Yes" : "No");
730 add_hot_spare(int fd
, char *component
)
732 RF_SingleComponent_t hot_spare
;
735 hot_spare
.column
= 0;
736 strncpy(hot_spare
.component_name
, component
,
737 sizeof(hot_spare
.component_name
));
739 do_ioctl( fd
, RAIDFRAME_ADD_HOT_SPARE
, &hot_spare
,
740 "RAIDFRAME_ADD_HOT_SPARE");
744 remove_hot_spare(int fd
, char *component
)
746 RF_SingleComponent_t hot_spare
;
750 get_component_number(fd
, component
, &component_num
, &num_cols
);
752 hot_spare
.row
= component_num
/ num_cols
;
753 hot_spare
.column
= component_num
% num_cols
;
755 strncpy(hot_spare
.component_name
, component
,
756 sizeof(hot_spare
.component_name
));
758 do_ioctl( fd
, RAIDFRAME_REMOVE_HOT_SPARE
, &hot_spare
,
759 "RAIDFRAME_REMOVE_HOT_SPARE");
763 rebuild_in_place(int fd
, char *component
)
765 RF_SingleComponent_t comp
;
769 get_component_number(fd
, component
, &component_num
, &num_cols
);
772 comp
.column
= component_num
;
773 strncpy(comp
.component_name
, component
, sizeof(comp
.component_name
));
775 do_ioctl( fd
, RAIDFRAME_REBUILD_IN_PLACE
, &comp
,
776 "RAIDFRAME_REBUILD_IN_PLACE");
779 printf("Reconstruction status:\n");
780 sleep(3); /* XXX give reconstruction a chance to start */
781 do_meter(fd
,RAIDFRAME_CHECK_RECON_STATUS_EXT
);
787 check_parity(int fd
, int do_rewrite
, char *dev_name
)
794 do_ioctl(fd
, RAIDFRAME_CHECK_PARITY
, &is_clean
,
795 "RAIDFRAME_CHECK_PARITY");
797 printf("%s: Parity status: clean\n",dev_name
);
799 printf("%s: Parity status: DIRTY\n",dev_name
);
801 printf("%s: Initiating re-write of parity\n",
803 do_ioctl(fd
, RAIDFRAME_REWRITEPARITY
, NULL
,
804 "RAIDFRAME_REWRITEPARITY");
805 sleep(3); /* XXX give it time to
808 printf("Parity Re-write status:\n");
809 do_meter(fd
, RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT
);
812 RAIDFRAME_CHECK_PARITYREWRITE_STATUS
,
814 "RAIDFRAME_CHECK_PARITYREWRITE_STATUS"
816 while( percent_done
< 100 ) {
817 sleep(3); /* wait a bit... */
818 do_ioctl(fd
, RAIDFRAME_CHECK_PARITYREWRITE_STATUS
,
819 &percent_done
, "RAIDFRAME_CHECK_PARITYREWRITE_STATUS");
823 printf("%s: Parity Re-write complete\n",
826 /* parity is wrong, and is not being fixed.
835 check_status(int fd
, int meter
)
837 int recon_percent_done
= 0;
838 int parity_percent_done
= 0;
839 int copyback_percent_done
= 0;
841 do_ioctl(fd
, RAIDFRAME_CHECK_RECON_STATUS
, &recon_percent_done
,
842 "RAIDFRAME_CHECK_RECON_STATUS");
843 printf("Reconstruction is %d%% complete.\n", recon_percent_done
);
844 do_ioctl(fd
, RAIDFRAME_CHECK_PARITYREWRITE_STATUS
,
845 &parity_percent_done
,
846 "RAIDFRAME_CHECK_PARITYREWRITE_STATUS");
847 printf("Parity Re-write is %d%% complete.\n", parity_percent_done
);
848 do_ioctl(fd
, RAIDFRAME_CHECK_COPYBACK_STATUS
, ©back_percent_done
,
849 "RAIDFRAME_CHECK_COPYBACK_STATUS");
850 printf("Copyback is %d%% complete.\n", copyback_percent_done
);
853 /* These 3 should be mutually exclusive at this point */
854 if (recon_percent_done
< 100) {
855 printf("Reconstruction status:\n");
856 do_meter(fd
,RAIDFRAME_CHECK_RECON_STATUS_EXT
);
857 } else if (parity_percent_done
< 100) {
858 printf("Parity Re-write status:\n");
859 do_meter(fd
,RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT
);
860 } else if (copyback_percent_done
< 100) {
861 printf("Copyback status:\n");
862 do_meter(fd
,RAIDFRAME_CHECK_COPYBACK_STATUS_EXT
);
867 const char *tbits
= "|/-\\";
870 do_meter(int fd
, u_long option
)
873 RF_uint64 start_value
;
874 RF_ProgressInfo_t progressInfo
;
876 struct timeval start_time
;
877 struct timeval current_time
;
881 int simple_eta
,last_eta
;
886 char bar_buffer
[1024];
887 char eta_buffer
[1024];
889 if (gettimeofday(&start_time
,NULL
)) {
890 fprintf(stderr
,"%s: gettimeofday failed!?!?\n", getprogname());
893 memset(&progressInfo
, 0, sizeof(RF_ProgressInfo_t
));
894 pInfoPtr
=&progressInfo
;
897 do_ioctl(fd
, option
, &pInfoPtr
, "");
898 start_value
= progressInfo
.completed
;
899 current_time
= start_time
;
904 while(progressInfo
.completed
< progressInfo
.total
) {
906 percent_done
= (progressInfo
.completed
* 100) /
909 get_bar(bar_buffer
, percent_done
, 40);
911 elapsed_sec
= current_time
.tv_sec
- start_time
.tv_sec
;
912 elapsed_usec
= current_time
.tv_usec
- start_time
.tv_usec
;
913 if (elapsed_usec
< 0) {
914 elapsed_usec
-=1000000;
918 elapsed
= (double) elapsed_sec
+
919 (double) elapsed_usec
/ 1000000.0;
921 amount
= progressInfo
.completed
- start_value
;
923 if (amount
<= 0) { /* we don't do negatives (yet?) */
930 rate
= amount
/ elapsed
;
933 simple_eta
= (int) (((double)progressInfo
.total
-
934 (double) progressInfo
.completed
)
940 if (simple_eta
<=0) {
941 simple_eta
= last_eta
;
943 last_eta
= simple_eta
;
946 get_time_string(eta_buffer
, simple_eta
);
948 snprintf(buffer
,1024,"\r%3d%% |%s| ETA: %s %c",
949 percent_done
,bar_buffer
,eta_buffer
,tbits
[tbit_value
]);
951 write(fileno(stdout
),buffer
,strlen(buffer
));
959 if (gettimeofday(¤t_time
,NULL
)) {
960 fprintf(stderr
,"%s: gettimeofday failed!?!?\n",
965 do_ioctl( fd
, option
, &pInfoPtr
, "");
971 /* 40 '*''s per line, then 40 ' ''s line. */
972 /* If you've got a screen wider than 160 characters, "tough" */
974 #define STAR_MIDPOINT 4*40
975 const char stars
[] = "****************************************"
976 "****************************************"
977 "****************************************"
978 "****************************************"
986 get_bar(char *string
, double percent
, int max_strlen
)
990 if (max_strlen
> STAR_MIDPOINT
) {
991 max_strlen
= STAR_MIDPOINT
;
993 offset
= STAR_MIDPOINT
-
994 (int)((percent
* max_strlen
)/ 100);
997 snprintf(string
,max_strlen
,"%s",&stars
[offset
]);
1001 get_time_string(char *string
, int simple_time
)
1003 int minutes
, seconds
, hours
;
1004 char hours_buffer
[5];
1005 char minutes_buffer
[5];
1006 char seconds_buffer
[5];
1008 if (simple_time
>= 0) {
1010 minutes
= (int) simple_time
/ 60;
1011 seconds
= ((int)simple_time
- 60*minutes
);
1012 hours
= minutes
/ 60;
1013 minutes
= minutes
- 60*hours
;
1016 snprintf(hours_buffer
,5,"%02d:",hours
);
1018 snprintf(hours_buffer
,5," ");
1021 snprintf(minutes_buffer
,5,"%02d:",minutes
);
1022 snprintf(seconds_buffer
,5,"%02d",seconds
);
1023 snprintf(string
,1024,"%s%s%s",
1024 hours_buffer
, minutes_buffer
, seconds_buffer
);
1026 snprintf(string
,1024," --:--");
1034 const char *progname
= getprogname();
1036 fprintf(stderr
, "usage: %s [-v] -a component dev\n", progname
);
1037 fprintf(stderr
, " %s [-v] -A yes | no | root dev\n", progname
);
1038 fprintf(stderr
, " %s [-v] -B dev\n", progname
);
1039 fprintf(stderr
, " %s [-v] -c config_file dev\n", progname
);
1040 fprintf(stderr
, " %s [-v] -C config_file dev\n", progname
);
1041 fprintf(stderr
, " %s [-v] -f component dev\n", progname
);
1042 fprintf(stderr
, " %s [-v] -F component dev\n", progname
);
1043 fprintf(stderr
, " %s [-v] -g component dev\n", progname
);
1044 fprintf(stderr
, " %s [-v] -G dev\n", progname
);
1045 fprintf(stderr
, " %s [-v] -i dev\n", progname
);
1046 fprintf(stderr
, " %s [-v] -I serial_number dev\n", progname
);
1047 fprintf(stderr
, " %s [-v] -p dev\n", progname
);
1048 fprintf(stderr
, " %s [-v] -P dev\n", progname
);
1049 fprintf(stderr
, " %s [-v] -r component dev\n", progname
);
1050 fprintf(stderr
, " %s [-v] -R component dev\n", progname
);
1051 fprintf(stderr
, " %s [-v] -s dev\n", progname
);
1052 fprintf(stderr
, " %s [-v] -S dev\n", progname
);
1053 fprintf(stderr
, " %s [-v] -u dev\n", progname
);