Whamcloud - gitweb
Add SIGINT and SIGTERM handling to fsck and e2fsck. For e2fsck,
authorTheodore Ts'o <tytso@mit.edu>
Sun, 21 Jul 2002 18:14:03 +0000 (14:14 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Sun, 21 Jul 2002 18:14:03 +0000 (14:14 -0400)
make sure we gracefully clean up and only exit at safe points.
For fsck, we pass the SIGINT/SIGTERM signal to the child processes,
so they can do their own cleanup.

e2fsck/ChangeLog
e2fsck/e2fsck.8.in
e2fsck/e2fsck.h
e2fsck/pass2.c
e2fsck/pass3.c
e2fsck/pass4.c
e2fsck/unix.c
misc/ChangeLog
misc/fsck.8.in
misc/fsck.c

index aaf7763..132fcdf 100644 (file)
@@ -1,3 +1,20 @@
+2002-07-21  Theodore Ts'o  <tytso@mit.edu>
+
+       * e2fsck.8.in: Document new exit code FSCK_CANCELED
+
+       * unix.c (PRS, signal_cancel): Capture SIGINT and SIGTERM signals
+               and set a flag in the e2fsck context indicating that
+               cancellation has been requested, so that e2fsck will exit
+               only at safe points.
+               (main): Change the exit handling so that if a cancellation
+               is requested, return FSCK_CANCELED (a new exit code 32).
+               e2fsck can now return more than one exit code as part of a
+               bitmask (as had been documented in the man page).
+
+       * pass2.c (e2fsck_pass2, check_dir_block), pass3.c (e2fsck_pass3),
+               pass4.c (e2fsck_pass4): Check to see if a cancellation was
+               requested, and abort processing if necessary.
+
 2002-07-19  Theodore Ts'o  <tytso@mit.edu>
 
        * rehash.c, Makefile.in: New file which rewrites directories using
index ad517c1..57383f7 100644 (file)
@@ -214,7 +214,7 @@ is the sum of the following conditions:
 .br
 \      2\      \-\ File system errors corrected, system should
 .br
-\      \       \ \ be rebooted if file system was mounted
+\      \       \ \ be rebooted
 .br
 \      4\      \-\ File system errors left uncorrected
 .br
@@ -222,6 +222,8 @@ is the sum of the following conditions:
 .br
 \      16\     \-\ Usage or syntax error
 .br
+\      32\     \-\ E2fsck canceled by user request
+.br
 \      128\    \-\ Shared library error
 .br
 .SH SIGNALS
index d68b79c..c35bf68 100644 (file)
@@ -58,6 +58,7 @@
 #define FSCK_UNCORRECTED 4     /* File system errors left uncorrected */
 #define FSCK_ERROR       8     /* Operational error */
 #define FSCK_USAGE       16    /* Usage or syntax error */
+#define FSCK_CANCELED   32     /* Aborted with a signal or ^C */
 #define FSCK_LIBRARY     128   /* Shared library error */
 
 /*
index db23c88..1f484f4 100644 (file)
@@ -148,6 +148,8 @@ void e2fsck_pass2(e2fsck_t ctx)
 
 #ifdef ENABLE_HTREE
        for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
+               if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+                       return;
                if (dx_dir->numblocks == 0)
                        continue;
                clear_problem_context(&pctx);
@@ -565,9 +567,11 @@ static int check_dir_block(ext2_filsys fs,
        buf = cd->buf;
        ctx = cd->ctx;
 
-       if (ctx->progress)
-               if ((ctx->progress)(ctx, 2, cd->count++, cd->max))
-                       return DIRENT_ABORT;
+       if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+               return DIRENT_ABORT;
+       
+       if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
+               return DIRENT_ABORT;
        
        /*
         * Make sure the inode is still in use (could have been 
index 7fdd814..4b1f397 100644 (file)
@@ -110,9 +110,10 @@ void e2fsck_pass3(e2fsck_t ctx)
                        goto abort_exit;
        
        for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
-               if (ctx->progress)
-                       if ((ctx->progress)(ctx, 3, count++, maxdirs))
-                               goto abort_exit;
+               if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+                       goto abort_exit;
+               if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
+                       goto abort_exit;
                if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
                        if (check_directory(ctx, dir, &pctx))
                                goto abort_exit;
index 895b77a..28c0996 100644 (file)
@@ -109,6 +109,8 @@ void e2fsck_pass4(e2fsck_t ctx)
                        return;
        
        for (i=1; i <= fs->super->s_inodes_count; i++) {
+               if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+                       return;
                if ((i % fs->super->s_inodes_per_group) == 0) {
                        group++;
                        if (ctx->progress)
index 18f2b2c..7fca08c 100644 (file)
@@ -436,6 +436,16 @@ static void signal_progress_off(int sig)
        e2fsck_clear_progbar(ctx);
        ctx->progress = 0;
 }
+
+static void signal_cancel(int sig)
+{
+       e2fsck_t ctx = e2fsck_global_ctx;
+
+       if (!ctx)
+               exit(FSCK_CANCELED);
+
+       ctx->flags |= E2F_FLAG_CANCEL;
+}
 #endif
 
 static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
@@ -632,6 +642,9 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
        sigaction(SIGUSR1, &sa, 0);
        sa.sa_handler = signal_progress_off;
        sigaction(SIGUSR2, &sa, 0);
+       sa.sa_handler = signal_cancel;
+       sigaction(SIGINT, &sa, 0);
+       sigaction(SIGTERM, &sa, 0);
 #endif
 
        /* Update our PATH to include /sbin if we need to run badblocks  */
@@ -958,23 +971,26 @@ restart:
                ext2fs_close(fs);
                goto restart;
        }
-       if (run_result & E2F_FLAG_SIGNAL_MASK)
-               fatal_error(ctx, 0);
-       if (run_result & E2F_FLAG_CANCEL)
-               ext2fs_unmark_valid(fs);
+       if (run_result & E2F_FLAG_CANCEL) {
+               printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
+                      ctx->device_name : ctx->filesystem_name);
+               exit_value |= FSCK_CANCELED;
+       }
+       if (run_result & E2F_FLAG_ABORT)
+               fatal_error(ctx, _("aborted"));
 
 #ifdef MTRACE
        mtrace_print("Cleanup");
 #endif
        if (ext2fs_test_changed(fs)) {
-               exit_value = FSCK_NONDESTRUCT;
+               exit_value |= FSCK_NONDESTRUCT;
                if (!(ctx->options & E2F_OPT_PREEN))
                    printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
                               ctx->device_name);
                if (root_filesystem && !read_only_root) {
                        printf(_("%s: ***** REBOOT LINUX *****\n"),
                               ctx->device_name);
-                       exit_value = FSCK_REBOOT;
+                       exit_value |= FSCK_REBOOT;
                }
        }
        if (ext2fs_test_valid(fs))
@@ -982,12 +998,13 @@ restart:
        else {
                printf(_("\n%s: ********** WARNING: Filesystem still has "
                         "errors **********\n\n"), ctx->device_name);
-               exit_value = FSCK_UNCORRECTED;
+               exit_value |= FSCK_UNCORRECTED;
+               exit_value &= ~FSCK_NONDESTRUCT;
        }
        if (!(ctx->options & E2F_OPT_READONLY)) {
                if (ext2fs_test_valid(fs)) {
                        if (!(sb->s_state & EXT2_VALID_FS))
-                               exit_value = FSCK_NONDESTRUCT;
+                               exit_value |= FSCK_NONDESTRUCT;
                        sb->s_state = EXT2_VALID_FS;
                } else
                        sb->s_state &= ~EXT2_VALID_FS;
@@ -995,7 +1012,10 @@ restart:
                sb->s_lastcheck = time(NULL);
                ext2fs_mark_super_dirty(fs);
        }
-       show_stats(ctx);
+       if (exit_value & FSCK_CANCELED)
+               exit_value &= ~FSCK_NONDESTRUCT;
+       else
+               show_stats(ctx);
 
        e2fsck_write_bitmaps(ctx);
        
index 6de1398..0469b71 100644 (file)
@@ -1,3 +1,10 @@
+2002-07-21  Theodore Ts'o  <tytso@mit.edu>
+
+       * fsck.8.in: Document new fsck exit code, FSCK_CANCELED.
+
+       * fsck.c: Trap SIGINT and SIGTERM, and relay it to all of the
+               child fsck processes.
+
 2002-07-14  Theodore Ts'o  <tytso@mit.edu>
 
        * mke2fs.c (zap_sector): Clear the buffer *after* testing for the
index fb20521..fd136ec 100644 (file)
@@ -49,6 +49,8 @@ is the sum of the following conditions:
 .br
 \      16\     \-\ Usage or syntax error
 .br
+\      32\     \-\ Fsck canceled by user request
+.br
 \      128\    \-\ Shared library error
 .br
 The exit code returned when all file systems are checked using the
index 8c4499e..8503eee 100644 (file)
@@ -100,6 +100,8 @@ int progress = 0;
 int force_all_parallel = 0;
 int num_running = 0;
 int max_running = 0;
+volatile int cancel_requested = 0;
+int kill_sent = 0;
 char *progname;
 char *fstype = NULL;
 struct fs_info *filesys_info;
@@ -468,6 +470,23 @@ static int execute(const char *type, char *device, char *mntpt,
 }
 
 /*
+ * Send a signal to all outstanding fsck child processes
+ */
+static int kill_all(int signal)
+{
+       struct fsck_instance *inst;
+       int     n = 0;
+
+       for (inst = instance_list; inst; inst = inst->next) {
+               if (inst->flags & FLAG_DONE)
+                       continue;
+               kill(inst->pid, signal);
+               n++;
+       }
+       return n;
+}
+
+/*
  * Wait for one child process to exit; when it does, unlink it from
  * the list of executing child processes, and return it.
  */
@@ -502,6 +521,10 @@ static struct fsck_instance *wait_one(int flags)
        
        do {
                pid = waitpid(-1, &status, flags);
+               if (cancel_requested && !kill_sent) {
+                       kill_all(SIGTERM);
+                       kill_sent++;
+               }
                if ((pid == 0) && (flags & WNOHANG))
                        return NULL;
                if (pid < 0) {
@@ -908,6 +931,8 @@ static int check_all(NOARGS)
                pass_done = 1;
 
                for (fs = filesys_info; fs; fs = fs->next) {
+                       if (cancel_requested)
+                               break;
                        if (fs->flags & FLAG_DONE)
                                continue;
                        /*
@@ -945,6 +970,8 @@ static int check_all(NOARGS)
                                break;
                        }
                }
+               if (cancel_requested)
+                       break;
                if (verbose > 1)
                        printf(_("--waiting-- (pass %d)\n"), passno);
                status |= wait_all(pass_done ? 0 : WNOHANG);
@@ -955,6 +982,10 @@ static int check_all(NOARGS)
                } else
                        not_done_yet++;
        }
+       if (cancel_requested && !kill_sent) {
+               kill_all(SIGTERM);
+               kill_sent++;
+       }
        status |= wait_all(0);
        return status;
 }
@@ -966,6 +997,13 @@ static void usage(NOARGS)
        exit(EXIT_USAGE);
 }
 
+#ifdef HAVE_SIGNAL_H
+static void signal_cancel(int sig)
+{
+       cancel_requested++;
+}
+#endif
+
 static void PRS(int argc, char *argv[])
 {
        int     i, j;
@@ -973,6 +1011,17 @@ static void PRS(int argc, char *argv[])
        char    options[128];
        int     opt = 0;
        int     opts_for_fsck = 0;
+#ifdef HAVE_SIGNAL_H
+       struct sigaction        sa;
+
+       /*
+        * Set up signal action
+        */
+       memset(&sa, 0, sizeof(struct sigaction));
+       sa.sa_handler = signal_cancel;
+       sigaction(SIGINT, &sa, 0);
+       sigaction(SIGTERM, &sa, 0);
+#endif
        
        num_devices = 0;
        num_args = 0;
@@ -1128,6 +1177,13 @@ int main(int argc, char *argv[])
                exit(EXIT_ERROR);
        }
        for (i = 0 ; i < num_devices; i++) {
+               if (cancel_requested) {
+                       if (!kill_sent) {
+                               kill_all(SIGTERM);
+                               kill_sent++;
+                       }
+                       break;
+               }
                fsck_device(devices[i], interactive);
                if (serialize || (num_running >= max_running)) {
                        struct fsck_instance *inst;