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: Bob Peterson <rpeterso@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
This commit is contained in:
committed by
Steven Whitehouse
parent
cd0120751d
commit
d34843d0c4
@@ -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 {
|
|||||||
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)
|
|||||||
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 {
|
|||||||
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 = {
|
|||||||
{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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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, ...)
|
|||||||
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,
|
|||||||
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;
|
||||||
|
Reference in New Issue
Block a user