Many files:
unix.c: Add support for calculating a progress bar if the -C0 option
is given. The function e2fsck_clear_progbar() clears the progress bar
and must be called before any message is issued. SIGUSR1 will enable
the progress bar, and SIGUSR2 will disable the progress bar. This is
used by fsck to handle parallel filesystem checks. Also, set the
device_name from the filesystem label if it is available.
e2fsck.h: Add new flags E2F_FLAG_PROG_BAR and E2F_FLAG_PROG_SUPRESS.
Add new field in the e2fsck structure which contains the last tenth of
a percent printed for the user.
message.c (print_e2fsck_message): Add call to e2fsck_clear_progbar().
pass1.c (e2fsck_pass1):
pass2.c (e2fsck_pass2):
pass3.c (e2fsck_pass3):
pass4.c (e2fsck_pass4):
pass5.c (e2fsck_pass5): Add call to e2fsck_clear_progbar when printing
the resource tracking information.
pass5.c (check_block_bitmaps, check_inode_bitmaps): If there is an
error in the bitmaps, suppress printing the progress bar using the
suppression flag for the remainder of the check, in order to clean up
the display.
diff --git a/e2fsck/ChangeLog b/e2fsck/ChangeLog
index 79bd9aa..c25e478 100644
--- a/e2fsck/ChangeLog
+++ b/e2fsck/ChangeLog
@@ -1,3 +1,34 @@
+1999-07-18 <tytso@valinux.com>
+
+ * unix.c: Add support for calculating a progress bar if the -C0
+ option is given. The function e2fsck_clear_progbar()
+ clears the progress bar and must be called before any
+ message is issued. SIGUSR1 will enable the progress bar,
+ and SIGUSR2 will disable the progress bar. This is used
+ by fsck to handle parallel filesystem checks. Also, set
+ the device_name from the filesystem label if it is
+ available.
+
+ * e2fsck.h: Add new flags E2F_FLAG_PROG_BAR and
+ E2F_FLAG_PROG_SUPRESS. Add new field in the e2fsck
+ structure which contains the last tenth of a percent
+ printed for the user.
+
+ * message.c (print_e2fsck_message): Add call to
+ e2fsck_clear_progbar().
+
+ * pass1.c (e2fsck_pass1):
+ * pass2.c (e2fsck_pass2):
+ * pass3.c (e2fsck_pass3):
+ * pass4.c (e2fsck_pass4):
+ * pass5.c (e2fsck_pass5): Add call to e2fsck_clear_progbar when
+ printing the resource tracking information.
+
+ * pass5.c (check_block_bitmaps, check_inode_bitmaps): If there is
+ an error in the bitmaps, suppress printing the progress
+ bar using the suppression flag for the remainder of the
+ check, in order to clean up the display.
+
1999-06-30 <tytso@valinux.com>
* unix.c (check_mount): Clean up the abort message displayed when
diff --git a/e2fsck/e2fsck.8.in b/e2fsck/e2fsck.8.in
index 41e6dc8..df4e6da 100644
--- a/e2fsck/e2fsck.8.in
+++ b/e2fsck/e2fsck.8.in
@@ -78,14 +78,13 @@
.B e2fsck
to write completion information to the specified file descriptor
so that the progress of the filesystem
-check can be monitored. This option is typically used by programs which are
-executing
-.BR e2fsck ,
-although -C 0 is a special case which will output a spinning
-character which can be useful for users who want to have something to watch
-while
+check can be monitored. This option is typically used by programs
+which are running
+.BR e2fsck .
+If the file descriptor specified is 0,
.B e2fsck
-goes about its business.
+will print a completion bar as it goes about its business. This requires
+that e2fsck is running on a video console or terminal.
.TP
.I -d
Print debugging output (useless unless you are debugging
@@ -186,6 +185,21 @@
.br
\ 128\ \-\ Shared library error
.br
+.SH SIGNALS
+The following signals have the following effect when sent to
+.BR e2fsck .
+.TP
+.B SIGUSR1
+This signal causes
+.B e2fsck
+to start displaying a completion bar. (See discussion of the
+.I -C
+option.)
+.TP
+.B SIGUSR2
+This signal causes
+.B e2fsck
+to stop displaying a completion bar.
.SH REPORTING BUGS
Almost any piece of software will have bugs. If you manage to find a
filesystem which causes
diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h
index 782edbc..86b411c 100644
--- a/e2fsck/e2fsck.h
+++ b/e2fsck/e2fsck.h
@@ -102,6 +102,9 @@
#define E2F_FLAG_SETJMP_OK 0x0010 /* Setjmp valid for abort */
+#define E2F_FLAG_PROG_BAR 0x0020 /* Progress bar on screen */
+#define E2F_FLAG_PROG_SUPPRESS 0x0040 /* Progress suspended */
+
/*
* Defines for indicating the e2fsck pass number
*/
@@ -196,6 +199,7 @@
*/
int progress_fd;
int progress_pos;
+ int progress_last_percent;
/* File counts */
int fs_directory_count;
@@ -299,3 +303,5 @@
#endif
extern blk_t get_backup_sb(ext2_filsys fs);
+/* unix.c */
+extern void e2fsck_clear_progbar(e2fsck_t ctx);
diff --git a/e2fsck/message.c b/e2fsck/message.c
index 1e440c5..8bb11df 100644
--- a/e2fsck/message.c
+++ b/e2fsck/message.c
@@ -385,7 +385,8 @@
ext2_filsys fs = ctx->fs;
const char * cp;
int i;
-
+
+ e2fsck_clear_progbar(ctx);
for (cp = msg; *cp; cp++) {
if (cp[0] == '@') {
cp++;
diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index 5ebd6e0..cebc82c 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -524,8 +524,10 @@
}
#ifdef RESOURCE_TRACK
- if (ctx->options & E2F_OPT_TIME2)
+ if (ctx->options & E2F_OPT_TIME2) {
+ e2fsck_clear_progbar(ctx);
print_resource_track("Pass 1", &rtrack);
+ }
#endif
}
diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c
index 38c1eda..37114e3 100644
--- a/e2fsck/pass2.c
+++ b/e2fsck/pass2.c
@@ -135,8 +135,10 @@
ctx->inode_bad_map = 0;
}
#ifdef RESOURCE_TRACK
- if (ctx->options & E2F_OPT_TIME2)
+ if (ctx->options & E2F_OPT_TIME2) {
+ e2fsck_clear_progbar(ctx);
print_resource_track("Pass 2", &rtrack);
+ }
#endif
}
diff --git a/e2fsck/pass3.c b/e2fsck/pass3.c
index a3aaa04..2e4bfe2 100644
--- a/e2fsck/pass3.c
+++ b/e2fsck/pass3.c
@@ -99,8 +99,10 @@
goto abort_exit;
}
#ifdef RESOURCE_TRACK
- if (ctx->options & E2F_OPT_TIME)
+ if (ctx->options & E2F_OPT_TIME) {
+ e2fsck_clear_progbar(ctx);
print_resource_track("Peak memory", &ctx->global_rtrack);
+ }
#endif
check_root(ctx);
@@ -137,8 +139,10 @@
if (inode_done_map)
ext2fs_free_inode_bitmap(inode_done_map);
#ifdef RESOURCE_TRACK
- if (ctx->options & E2F_OPT_TIME2)
+ if (ctx->options & E2F_OPT_TIME2) {
+ e2fsck_clear_progbar(ctx);
print_resource_track("Pass 3", &rtrack);
+ }
#endif
}
diff --git a/e2fsck/pass4.c b/e2fsck/pass4.c
index e059cc3..264b1c7 100644
--- a/e2fsck/pass4.c
+++ b/e2fsck/pass4.c
@@ -153,8 +153,10 @@
ext2fs_free_inode_bitmap(ctx->inode_bb_map);
ctx->inode_bb_map = 0;
#ifdef RESOURCE_TRACK
- if (ctx->options & E2F_OPT_TIME2)
+ if (ctx->options & E2F_OPT_TIME2) {
+ e2fsck_clear_progbar(ctx);
print_resource_track("Pass 4", &rtrack);
+ }
#endif
}
diff --git a/e2fsck/pass5.c b/e2fsck/pass5.c
index 274052e..b39b313 100644
--- a/e2fsck/pass5.c
+++ b/e2fsck/pass5.c
@@ -65,8 +65,10 @@
ctx->block_found_map = 0;
#ifdef RESOURCE_TRACK
- if (ctx->options & E2F_OPT_TIME2)
+ if (ctx->options & E2F_OPT_TIME2) {
+ e2fsck_clear_progbar(ctx);
print_resource_track("Pass 5", &rtrack);
+ }
#endif
}
@@ -142,6 +144,7 @@
}
pctx.blk = i;
fix_problem(ctx, problem, &pctx);
+ ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
had_problem++;
do_counts:
@@ -166,6 +169,8 @@
fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
else
fixit = -1;
+ ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
+
if (fixit == 1) {
ext2fs_free_block_bitmap(fs->block_map);
retval = ext2fs_copy_bitmap(ctx->block_found_map,
@@ -282,6 +287,7 @@
}
pctx.ino = i;
fix_problem(ctx, problem, &pctx);
+ ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
had_problem++;
do_counts:
@@ -312,6 +318,8 @@
fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
else
fixit = -1;
+ ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
+
if (fixit == 1) {
ext2fs_free_inode_bitmap(fs->inode_map);
retval = ext2fs_copy_bitmap(ctx->inode_used_map,
diff --git a/e2fsck/unix.c b/e2fsck/unix.c
index ed8082d..e33a814 100644
--- a/e2fsck/unix.c
+++ b/e2fsck/unix.c
@@ -18,6 +18,7 @@
#include <ctype.h>
#include <termios.h>
#include <time.h>
+#include <signal.h>
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
@@ -60,7 +61,8 @@
fprintf(stderr,
"Usage: %s [-panyrcdfvstFSV] [-b superblock] [-B blocksize]\n"
"\t\t[-I inode_buffer_blocks] [-P process_inode_size]\n"
- "\t\t[-l|-L bad_blocks_file] device\n", ctx->program_name);
+ "\t\t[-l|-L bad_blocks_file] [-C fd] device\n",
+ ctx->program_name);
exit(FSCK_USAGE);
}
@@ -165,11 +167,11 @@
#endif
if (ctx->options & E2F_OPT_READONLY) {
- printf("Warning! %s is mounted.\n", ctx->device_name);
+ printf("Warning! %s is mounted.\n", ctx->filesystem_name);
return;
}
- printf("%s is mounted. ", ctx->device_name);
+ printf("%s is mounted. ", ctx->filesystem_name);
if (!isatty(0) || !isatty(1)) {
printf("Cannot continue, aborting.\n\n");
exit(FSCK_ERROR);
@@ -225,11 +227,51 @@
/*
* For completion notice
*/
+struct percent_tbl {
+ int max_pass;
+ int table[32];
+};
+struct percent_tbl e2fsck_tbl = {
+ 5, { 0, 70, 90, 92, 95, 100 }
+};
+static int dpywidth = 50;
+static char bar[] =
+ "==============================================================="
+ "===============================================================";
+static char spaces[] =
+ " "
+ " ";
+
+static float calc_percent(struct percent_tbl *tbl, int pass, int curr,
+ int max)
+{
+ float percent;
+
+ if (pass <= 0)
+ return 0.0;
+ if (pass > tbl->max_pass)
+ return 100.0;
+ percent = ((float) curr) / ((float) max);
+ return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
+ + tbl->table[pass-1]);
+}
+
+extern void e2fsck_clear_progbar(e2fsck_t ctx)
+{
+ if (!(ctx->flags & E2F_FLAG_PROG_BAR))
+ return;
+
+ printf("%s\r", spaces + (sizeof(spaces) - 80));
+ ctx->flags &= ~E2F_FLAG_PROG_BAR;
+}
+
static int e2fsck_update_progress(e2fsck_t ctx, int pass,
unsigned long cur, unsigned long max)
{
const char spinner[] = "\\|/-";
char buf[80];
+ int i;
+ float percent;
if (pass == 0)
return 0;
@@ -238,9 +280,25 @@
sprintf(buf, "%d %lu %lu\n", pass, cur, max);
write(ctx->progress_fd, buf, strlen(buf));
} else {
+ if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
+ return 0;
ctx->progress_pos = (ctx->progress_pos+1) & 3;
- fputc(spinner[ctx->progress_pos], stdout);
- fputc('\b', stdout);
+ ctx->flags |= E2F_FLAG_PROG_BAR;
+ percent = calc_percent(&e2fsck_tbl, pass, cur, max);
+ if (ctx->progress_last_percent == (int) 1000 * percent)
+ return 0;
+ ctx->progress_last_percent = (int) 1000 * percent;
+ i = ((percent * dpywidth) + 50) / 100;
+ printf("%s: |%s%s", ctx->device_name,
+ bar + (sizeof(bar) - (i+1)),
+ spaces + (sizeof(spaces) - (dpywidth - i + 1)));
+ if (percent == 100.0)
+ fputc('|', stdout);
+ else
+ fputc(spinner[ctx->progress_pos & 3], stdout);
+ printf(" %4.1f%% \r", percent);
+ if (percent == 100.0)
+ e2fsck_clear_progbar(ctx);
fflush(stdout);
}
return 0;
@@ -266,6 +324,30 @@
close(fd);
}
+static e2fsck_t global_signal_ctx;
+
+static void signal_progress_on(int sig)
+{
+ e2fsck_t ctx = global_signal_ctx;
+
+ if (!ctx)
+ return;
+
+ ctx->progress = e2fsck_update_progress;
+ ctx->progress_fd = 0;
+}
+
+static void signal_progress_off(int sig)
+{
+ e2fsck_t ctx = global_signal_ctx;
+
+ if (!ctx)
+ return;
+
+ e2fsck_clear_progbar(ctx);
+ ctx->progress = 0;
+}
+
static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
{
int flush = 0;
@@ -276,6 +358,7 @@
char *oldpath = getenv("PATH");
e2fsck_t ctx;
errcode_t retval;
+ struct sigaction sa;
retval = e2fsck_allocate_context(&ctx);
if (retval)
@@ -407,8 +490,6 @@
!cflag && !swapfs)
ctx->options |= E2F_OPT_READONLY;
ctx->filesystem_name = argv[optind];
- if (ctx->device_name == 0)
- ctx->device_name = ctx->filesystem_name;
if (flush) {
#ifdef BLKFLSBUF
int fd = open(ctx->filesystem_name, O_RDONLY, 0);
@@ -435,6 +516,18 @@
exit(FSCK_ERROR);
}
}
+ /*
+ * Set up signal action
+ */
+ memset(&sa, 0, sizeof(struct sigaction));
+#ifdef SA_RESTART
+ sa.sa_flags = SA_RESTART;
+#endif
+ global_signal_ctx = ctx;
+ sa.sa_handler = signal_progress_on;
+ sigaction(SIGUSR1, &sa, 0);
+ sa.sa_handler = signal_progress_off;
+ sigaction(SIGUSR2, &sa, 0);
return 0;
}
@@ -594,6 +687,18 @@
"(%s)", ctx->filesystem_name);
goto get_newer;
}
+ if (ctx->device_name == 0 &&
+ (s->s_volume_name[0] != 0)) {
+ char *cp = malloc(sizeof(s->s_volume_name)+1);
+ if (cp) {
+ strncpy(cp, s->s_volume_name,
+ sizeof(s->s_volume_name));
+ cp[sizeof(s->s_volume_name)] = 0;
+ ctx->device_name = cp;
+ }
+ }
+ if (ctx->device_name == 0)
+ ctx->device_name = ctx->filesystem_name;
/*
* If the user specified a specific superblock, presumably the
@@ -653,6 +758,7 @@
}
run_result = e2fsck_run(ctx);
+ e2fsck_clear_progbar(ctx);
if (run_result == E2F_FLAG_RESTART) {
printf("Restarting e2fsck from the beginning...\n");
retval = e2fsck_reset_context(ctx);