summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>1999-07-19 15:27:37 +0000
committerTheodore Ts'o <tytso@mit.edu>1999-07-19 15:27:37 +0000
commit5596defa1e212242c1bf1b028139143fbb7777a0 (patch)
tree611585743f9f67fe1a42167f6094941fed54da8a
parent9f10a7b31e57288093930fc9565102409eeac6e9 (diff)
downloade2fsprogs-5596defa1e212242c1bf1b028139143fbb7777a0.tar.gz
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.
-rw-r--r--e2fsck/ChangeLog31
-rw-r--r--e2fsck/e2fsck.8.in28
-rw-r--r--e2fsck/e2fsck.h6
-rw-r--r--e2fsck/message.c3
-rw-r--r--e2fsck/pass1.c4
-rw-r--r--e2fsck/pass2.c4
-rw-r--r--e2fsck/pass3.c8
-rw-r--r--e2fsck/pass4.c4
-rw-r--r--e2fsck/pass5.c10
-rw-r--r--e2fsck/unix.c120
10 files changed, 197 insertions, 21 deletions
diff --git a/e2fsck/ChangeLog b/e2fsck/ChangeLog
index 79bd9aae..c25e478e 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 41e6dc89..df4e6da6 100644
--- a/e2fsck/e2fsck.8.in
+++ b/e2fsck/e2fsck.8.in
@@ -78,14 +78,13 @@ This option causes
.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 @@ is the sum of the following conditions:
.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 782edbc7..86b411ce 100644
--- a/e2fsck/e2fsck.h
+++ b/e2fsck/e2fsck.h
@@ -102,6 +102,9 @@ struct resource_track {
#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 @@ struct e2fsck_struct {
*/
int progress_fd;
int progress_pos;
+ int progress_last_percent;
/* File counts */
int fs_directory_count;
@@ -299,3 +303,5 @@ extern void mtrace_print(char *mesg);
#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 1e440c5c..8bb11df8 100644
--- a/e2fsck/message.c
+++ b/e2fsck/message.c
@@ -385,7 +385,8 @@ void print_e2fsck_message(e2fsck_t ctx, const char *msg,
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 5ebd6e03..cebc82c5 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -524,8 +524,10 @@ endit:
}
#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 38c1eda6..37114e31 100644
--- a/e2fsck/pass2.c
+++ b/e2fsck/pass2.c
@@ -135,8 +135,10 @@ void e2fsck_pass2(e2fsck_t ctx)
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 a3aaa04b..2e4bfe21 100644
--- a/e2fsck/pass3.c
+++ b/e2fsck/pass3.c
@@ -99,8 +99,10 @@ void e2fsck_pass3(e2fsck_t ctx)
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 @@ abort_exit:
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 e059cc34..264b1c78 100644
--- a/e2fsck/pass4.c
+++ b/e2fsck/pass4.c
@@ -153,8 +153,10 @@ void e2fsck_pass4(e2fsck_t ctx)
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 274052ec..b39b3134 100644
--- a/e2fsck/pass5.c
+++ b/e2fsck/pass5.c
@@ -65,8 +65,10 @@ void e2fsck_pass5(e2fsck_t ctx)
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 @@ redo_counts:
}
pctx.blk = i;
fix_problem(ctx, problem, &pctx);
+ ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
had_problem++;
do_counts:
@@ -166,6 +169,8 @@ redo_counts:
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 @@ redo_counts:
}
pctx.ino = i;
fix_problem(ctx, problem, &pctx);
+ ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
had_problem++;
do_counts:
@@ -312,6 +318,8 @@ do_counts:
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 ed8082d5..e33a814e 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 @@ static void usage(e2fsck_t ctx)
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 @@ static void check_mount(e2fsck_t ctx)
#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 @@ static void check_if_skip(e2fsck_t ctx)
/*
* 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 @@ static int e2fsck_update_progress(e2fsck_t ctx, int pass,
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 @@ static void reserve_stdio_fds(NOARGS)
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 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
char *oldpath = getenv("PATH");
e2fsck_t ctx;
errcode_t retval;
+ struct sigaction sa;
retval = e2fsck_allocate_context(&ctx);
if (retval)
@@ -407,8 +490,6 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
!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 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
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 @@ restart:
"(%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 @@ restart:
}
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);