Commit d34843d0 authored by Bob Peterson's avatar Bob Peterson Committed by Steven Whitehouse

GFS2: Add "-o errors=panic|withdraw" mount options

This patch adds "-o errors=panic" and "-o errors=withdraw" to the
gfs2 mount options.  The "errors=withdraw" option is today's
current behaviour, meaning to withdraw from the file system if a
non-serious gfs2 error occurs.  The new "errors=panic" option
tells gfs2 to force a kernel panic if a non-serious gfs2 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).
Signed-off-by: default avatarBob Peterson <rpeterso@redhat.com>
Signed-off-by: default avatarSteven Whitehouse <swhiteho@redhat.com>
parent cd012075
...@@ -406,6 +406,12 @@ struct gfs2_statfs_change_host { ...@@ -406,6 +406,12 @@ struct gfs2_statfs_change_host {
#define GFS2_DATA_WRITEBACK 1 #define GFS2_DATA_WRITEBACK 1
#define GFS2_DATA_ORDERED 2 #define GFS2_DATA_ORDERED 2
#define GFS2_ERRORS_DEFAULT GFS2_ERRORS_WITHDRAW
#define GFS2_ERRORS_WITHDRAW 0
#define GFS2_ERRORS_CONTINUE 1 /* place holder for future feature */
#define GFS2_ERRORS_RO 2 /* place holder for future feature */
#define GFS2_ERRORS_PANIC 3
struct gfs2_args { struct gfs2_args {
char ar_lockproto[GFS2_LOCKNAME_LEN]; /* Name of the Lock Protocol */ char ar_lockproto[GFS2_LOCKNAME_LEN]; /* Name of the Lock Protocol */
char ar_locktable[GFS2_LOCKNAME_LEN]; /* Name of the Lock Table */ char ar_locktable[GFS2_LOCKNAME_LEN]; /* Name of the Lock Table */
...@@ -422,6 +428,7 @@ struct gfs2_args { ...@@ -422,6 +428,7 @@ struct gfs2_args {
unsigned int ar_data:2; /* ordered/writeback */ unsigned int ar_data:2; /* ordered/writeback */
unsigned int ar_meta:1; /* mount metafs */ unsigned int ar_meta:1; /* mount metafs */
unsigned int ar_discard:1; /* discard requests */ unsigned int ar_discard:1; /* discard requests */
unsigned int ar_errors:2; /* errors=withdraw | panic */
int ar_commit; /* Commit interval */ int ar_commit; /* Commit interval */
}; };
......
...@@ -1168,6 +1168,7 @@ static int fill_super(struct super_block *sb, void *data, int silent) ...@@ -1168,6 +1168,7 @@ static int fill_super(struct super_block *sb, void *data, int silent)
sdp->sd_args.ar_quota = GFS2_QUOTA_DEFAULT; sdp->sd_args.ar_quota = GFS2_QUOTA_DEFAULT;
sdp->sd_args.ar_data = GFS2_DATA_DEFAULT; sdp->sd_args.ar_data = GFS2_DATA_DEFAULT;
sdp->sd_args.ar_commit = 60; sdp->sd_args.ar_commit = 60;
sdp->sd_args.ar_errors = GFS2_ERRORS_DEFAULT;
error = gfs2_mount_args(sdp, &sdp->sd_args, data); error = gfs2_mount_args(sdp, &sdp->sd_args, data);
if (error) { if (error) {
......
...@@ -68,6 +68,8 @@ enum { ...@@ -68,6 +68,8 @@ enum {
Opt_discard, Opt_discard,
Opt_nodiscard, Opt_nodiscard,
Opt_commit, Opt_commit,
Opt_err_withdraw,
Opt_err_panic,
Opt_error, Opt_error,
}; };
...@@ -97,6 +99,8 @@ static const match_table_t tokens = { ...@@ -97,6 +99,8 @@ static const match_table_t tokens = {
{Opt_discard, "discard"}, {Opt_discard, "discard"},
{Opt_nodiscard, "nodiscard"}, {Opt_nodiscard, "nodiscard"},
{Opt_commit, "commit=%d"}, {Opt_commit, "commit=%d"},
{Opt_err_withdraw, "errors=withdraw"},
{Opt_err_panic, "errors=panic"},
{Opt_error, NULL} {Opt_error, NULL}
}; };
...@@ -152,6 +156,11 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *options) ...@@ -152,6 +156,11 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *options)
args->ar_localcaching = 1; args->ar_localcaching = 1;
break; break;
case Opt_debug: case Opt_debug:
if (args->ar_errors == GFS2_ERRORS_PANIC) {
fs_info(sdp, "-o debug and -o errors=panic "
"are mutually exclusive.\n");
return -EINVAL;
}
args->ar_debug = 1; args->ar_debug = 1;
break; break;
case Opt_nodebug: case Opt_nodebug:
...@@ -205,6 +214,17 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *options) ...@@ -205,6 +214,17 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *options)
return rv ? rv : -EINVAL; return rv ? rv : -EINVAL;
} }
break; break;
case Opt_err_withdraw:
args->ar_errors = GFS2_ERRORS_WITHDRAW;
break;
case Opt_err_panic:
if (args->ar_debug) {
fs_info(sdp, "-o debug and -o errors=panic "
"are mutually exclusive.\n");
return -EINVAL;
}
args->ar_errors = GFS2_ERRORS_PANIC;
break;
case Opt_error: case Opt_error:
default: default:
fs_info(sdp, "invalid mount option: %s\n", o); fs_info(sdp, "invalid mount option: %s\n", o);
...@@ -1226,6 +1246,22 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt) ...@@ -1226,6 +1246,22 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
lfsecs = sdp->sd_tune.gt_log_flush_secs; lfsecs = sdp->sd_tune.gt_log_flush_secs;
if (lfsecs != 60) if (lfsecs != 60)
seq_printf(s, ",commit=%d", lfsecs); seq_printf(s, ",commit=%d", lfsecs);
if (args->ar_errors != GFS2_ERRORS_DEFAULT) {
const char *state;
switch (args->ar_errors) {
case GFS2_ERRORS_WITHDRAW:
state = "withdraw";
break;
case GFS2_ERRORS_PANIC:
state = "panic";
break;
default:
state = "unknown";
break;
}
seq_printf(s, ",errors=%s", state);
}
return 0; return 0;
} }
......
...@@ -38,24 +38,30 @@ int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...) ...@@ -38,24 +38,30 @@ int gfs2_lm_withdraw(struct gfs2_sbd *sdp, char *fmt, ...)
const struct lm_lockops *lm = ls->ls_ops; const struct lm_lockops *lm = ls->ls_ops;
va_list args; va_list args;
if (test_and_set_bit(SDF_SHUTDOWN, &sdp->sd_flags)) if (sdp->sd_args.ar_errors == GFS2_ERRORS_WITHDRAW &&
test_and_set_bit(SDF_SHUTDOWN, &sdp->sd_flags))
return 0; return 0;
va_start(args, fmt); va_start(args, fmt);
vprintk(fmt, args); vprintk(fmt, args);
va_end(args); va_end(args);
fs_err(sdp, "about to withdraw this file system\n"); if (sdp->sd_args.ar_errors == GFS2_ERRORS_WITHDRAW) {
BUG_ON(sdp->sd_args.ar_debug); fs_err(sdp, "about to withdraw this file system\n");
BUG_ON(sdp->sd_args.ar_debug);
kobject_uevent(&sdp->sd_kobj, KOBJ_OFFLINE); kobject_uevent(&sdp->sd_kobj, KOBJ_OFFLINE);
if (lm->lm_unmount) { if (lm->lm_unmount) {
fs_err(sdp, "telling LM to unmount\n"); fs_err(sdp, "telling LM to unmount\n");
lm->lm_unmount(sdp); lm->lm_unmount(sdp);
}
fs_err(sdp, "withdrawn\n");
dump_stack();
} }
fs_err(sdp, "withdrawn\n");
dump_stack(); if (sdp->sd_args.ar_errors == GFS2_ERRORS_PANIC)
panic("GFS2: fsid=%s: panic requested.\n", sdp->sd_fsname);
return -1; return -1;
} }
...@@ -93,17 +99,24 @@ int gfs2_assert_warn_i(struct gfs2_sbd *sdp, char *assertion, ...@@ -93,17 +99,24 @@ int gfs2_assert_warn_i(struct gfs2_sbd *sdp, char *assertion,
gfs2_tune_get(sdp, gt_complain_secs) * HZ)) gfs2_tune_get(sdp, gt_complain_secs) * HZ))
return -2; return -2;
printk(KERN_WARNING if (sdp->sd_args.ar_errors == GFS2_ERRORS_WITHDRAW)
"GFS2: fsid=%s: warning: assertion \"%s\" failed\n" printk(KERN_WARNING
"GFS2: fsid=%s: function = %s, file = %s, line = %u\n", "GFS2: fsid=%s: warning: assertion \"%s\" failed\n"
sdp->sd_fsname, assertion, "GFS2: fsid=%s: function = %s, file = %s, line = %u\n",
sdp->sd_fsname, function, file, line); sdp->sd_fsname, assertion,
sdp->sd_fsname, function, file, line);
if (sdp->sd_args.ar_debug) if (sdp->sd_args.ar_debug)
BUG(); BUG();
else else
dump_stack(); dump_stack();
if (sdp->sd_args.ar_errors == GFS2_ERRORS_PANIC)
panic("GFS2: fsid=%s: warning: assertion \"%s\" failed\n"
"GFS2: fsid=%s: function = %s, file = %s, line = %u\n",
sdp->sd_fsname, assertion,
sdp->sd_fsname, function, file, line);
sdp->sd_last_warning = jiffies; sdp->sd_last_warning = jiffies;
return -1; return -1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment