commit 57f87843c7f54149d688e716fded0f08c3d7f619 Author: Bob Peterson <rpeterso@redhat.com> Date: Fri Oct 9 14:26:55 2009 -0500 GFS: New mount option: -o errors=withdraw|panic This patch adds "-o errors=panic" and "-o errors=withdraw" to the gfs mount options. The "errors=withdraw" option is today's current behaviour, meaning to withdraw from the file system if a non-serious gfs error occurs. The new "errors=panic" option tells gfs to force a kernel panic if a non-serious gfs file system error occurs. This may be useful, for example, where fabric-level fencing is used that has no way to reboot (such as fence_scsi). rhbz#517145 diff --git a/gfs-kernel/src/gfs/incore.h b/gfs-kernel/src/gfs/incore.h index fa6f539..841b852 100644 --- a/gfs-kernel/src/gfs/incore.h +++ b/gfs-kernel/src/gfs/incore.h @@ -830,6 +830,10 @@ struct gfs_trans { #define GFS_DATA_WRITEBACK 1 #define GFS_DATA_ORDERED 2 +#define GFS_ERRORS_WITHDRAW 0 +#define GFS_ERRORS_CONTINUE 1 /* place holder for future feature */ +#define GFS_ERRORS_RO 2 /* place holder for future feature */ +#define GFS_ERRORS_PANIC 3 struct gfs_args { char ar_lockproto[GFS_LOCKNAME_LEN]; /* The name of the Lock Protocol */ @@ -852,6 +856,7 @@ struct gfs_args { int ar_oopses_ok; /* Allow oopses */ int ar_debug; /* Oops on errors instead of trying to be graceful */ + int ar_errors; /* errors=default | panic */ int ar_upgrade; /* Upgrade ondisk/multihost format */ unsigned int ar_num_glockd; /* # of glock cleanup daemons to run diff --git a/gfs-kernel/src/gfs/lm.c b/gfs-kernel/src/gfs/lm.c index e16216e..acfd598 100644 --- a/gfs-kernel/src/gfs/lm.c +++ b/gfs-kernel/src/gfs/lm.c @@ -97,26 +97,30 @@ int gfs_lm_withdraw(struct gfs_sbd *sdp, char *fmt, ...) { va_list args; - if (test_and_set_bit(SDF_SHUTDOWN, &sdp->sd_flags)) + if (sdp->sd_args.ar_errors == GFS_ERRORS_WITHDRAW && + test_and_set_bit(SDF_SHUTDOWN, &sdp->sd_flags)) return 0; va_start(args, fmt); vprintk(fmt, args); va_end(args); - printk("GFS: fsid=%s: about to withdraw from the cluster\n", - sdp->sd_fsname); + if (sdp->sd_args.ar_errors == GFS_ERRORS_WITHDRAW) { + printk("GFS: fsid=%s: about to withdraw from the cluster\n", + sdp->sd_fsname); - BUG_ON(sdp->sd_args.ar_debug); + BUG_ON(sdp->sd_args.ar_debug); - printk("GFS: fsid=%s: telling LM to withdraw\n", - sdp->sd_fsname); + printk("GFS: fsid=%s: telling LM to withdraw\n", + sdp->sd_fsname); - gfs_withdraw_lockproto(&sdp->sd_lockstruct); + gfs_withdraw_lockproto(&sdp->sd_lockstruct); - printk("GFS: fsid=%s: withdrawn\n", - sdp->sd_fsname); + printk("GFS: fsid=%s: withdrawn\n", sdp->sd_fsname); + } dump_stack(); + if (sdp->sd_args.ar_errors == GFS_ERRORS_PANIC) + panic("GFS: fsid=%s: panic requested.\n", sdp->sd_fsname); return -1; } diff --git a/gfs-kernel/src/gfs/mount.c b/gfs-kernel/src/gfs/mount.c index 8dd58e8..741667a 100644 --- a/gfs-kernel/src/gfs/mount.c +++ b/gfs-kernel/src/gfs/mount.c @@ -52,6 +52,7 @@ gfs_make_args(char *data_arg, struct gfs_args *args, int remount) memset(args, 0, sizeof(struct gfs_args)); args->ar_num_glockd = GFS_GLOCKD_DEFAULT; + args->ar_errors = GFS_ERRORS_WITHDRAW; if (!remount) { /* If someone preloaded options, use those instead */ @@ -119,10 +120,21 @@ gfs_make_args(char *data_arg, struct gfs_args *args, int remount) else if (!strcmp(x, "localcaching")) args->ar_localcaching = TRUE; - else if (!strcmp(x, "oopses_ok")) + else if (!strcmp(x, "oopses_ok")) { + if (args->ar_errors == GFS_ERRORS_PANIC) { + printk("GFS: -o oopses_ok and -o errors=panic " + "are mutually exclusive.\n"); + error = -EINVAL; + break; + } args->ar_oopses_ok = TRUE; - - else if (!strcmp(x, "debug")) { + } else if (!strcmp(x, "debug")) { + if (args->ar_errors == GFS_ERRORS_PANIC) { + printk("GFS: -o debug and -o errors=panic " + "are mutually exclusive.\n"); + error = -EINVAL; + break; + } args->ar_oopses_ok = TRUE; args->ar_debug = TRUE; @@ -159,6 +171,37 @@ gfs_make_args(char *data_arg, struct gfs_args *args, int remount) else if (!strcmp(x, "gfs_noatime")) args->ar_noatime = TRUE; + else if (!strcmp(x, "errors")) { + if (!y) { + printk("GFS: need argument to errors\n"); + error = -EINVAL; + break; + } + if (!strcmp(y, "withdraw")) + args->ar_errors = GFS_ERRORS_WITHDRAW; + else if (!strcmp(y, "panic")) { + if (args->ar_debug) { + printk("GFS: -o debug and -o errors=" + "panic are mutually " + "exclusive.\n"); + error = -EINVAL; + break; + } else if (args->ar_oopses_ok) { + printk("GFS: -o oopses_ok and -o " + "errors=panic are mutually " + "exclusive.\n"); + error = -EINVAL; + break; + } + args->ar_errors = GFS_ERRORS_PANIC; + } else { + printk("GFS: errors= must be either withdraw " + "or panic.\n"); + error = -EINVAL; + break; + } + } + /* Unknown */ else { diff --git a/gfs-kernel/src/gfs/ops_super.c b/gfs-kernel/src/gfs/ops_super.c index 7f92691..7f29771 100644 --- a/gfs-kernel/src/gfs/ops_super.c +++ b/gfs-kernel/src/gfs/ops_super.c @@ -449,7 +449,11 @@ gfs_show_options(struct seq_file *s, struct vfsmount *mnt) seq_printf(s, ",noquota"); if (args->ar_suiddir) seq_printf(s, ",suiddir"); - + if (args->ar_errors) { + seq_printf(s, ",errors="); + if (args->ar_errors == GFS_ERRORS_PANIC) + seq_printf(s, "panic"); + } return 0; } diff --git a/gfs-kernel/src/gfs/util.c b/gfs-kernel/src/gfs/util.c index 3e093aa..828d427 100644 --- a/gfs-kernel/src/gfs/util.c +++ b/gfs-kernel/src/gfs/util.c @@ -23,6 +23,7 @@ #include "gfs.h" #include "glock.h" #include "lm.h" +#include "super.h" uint32_t gfs_random_number; @@ -208,7 +209,8 @@ gfs_assert_i(struct gfs_sbd *sdp, sdp->sd_fsname, function, sdp->sd_fsname, file, line, sdp->sd_fsname, get_seconds()); - BUG(); + if (sdp->sd_args.ar_errors == GFS_ERRORS_WITHDRAW) + BUG(); } dump_stack(); panic("GFS: fsid=%s: assertion \"%s\" failed\n" @@ -275,19 +277,30 @@ gfs_assert_warn_i(struct gfs_sbd *sdp, gfs_tune_get(sdp, gt_complain_secs) * HZ)) return -2; - printk("GFS: fsid=%s: warning: assertion \"%s\" failed\n" - "GFS: fsid=%s: function = %s\n" - "GFS: fsid=%s: file = %s, line = %u\n" - "GFS: fsid=%s: time = %lu\n", - sdp->sd_fsname, assertion, - sdp->sd_fsname, function, - sdp->sd_fsname, file, line, - sdp->sd_fsname, get_seconds()); + if (sdp->sd_args.ar_errors == GFS_ERRORS_WITHDRAW) + printk("GFS: fsid=%s: warning: assertion \"%s\" failed\n" + "GFS: fsid=%s: function = %s\n" + "GFS: fsid=%s: file = %s, line = %u\n" + "GFS: fsid=%s: time = %lu\n", + sdp->sd_fsname, assertion, + sdp->sd_fsname, function, + sdp->sd_fsname, file, line, + sdp->sd_fsname, get_seconds()); + if (sdp->sd_args.ar_errors != GFS_ERRORS_WITHDRAW) + dump_stack(); sdp->sd_last_warning = jiffies; if (sdp->sd_args.ar_debug) BUG(); - + if (sdp->sd_args.ar_errors == GFS_ERRORS_PANIC) + panic("GFS: fsid=%s: assertion \"%s\" failed\n" + "GFS: fsid=%s: function = %s\n" + "GFS: fsid=%s: file = %s, line = %u\n" + "GFS: fsid=%s: time = %lu\n", + sdp->sd_fsname, assertion, + sdp->sd_fsname, function, + sdp->sd_fsname, file, line, + sdp->sd_fsname, get_seconds()); return -1; }