Commit b743d13b authored by Andrew Morton's avatar Andrew Morton Committed by David Mosberger

[PATCH] reiserfs option parser fix and ability to pass

From: Oleg Drokin <green@namesys.com>

This patch adds support for remounting taking into account all extra options
you may want to pass it.  (by Jeff Mahooney).

Also it reworks the parser to correctly deal with mutually exclusive options.
Now whatever option was specified last will take an effect.

- If you pass more than one jdev= option, the error will be reported and
  mount/remount refused.

- If you pass incorrect alloc= suboptions, the mount/remount will fail.
  (it did not before).

- nolargeio now actually looks at its argument.  Argument is expected to be
  numeric.  If it is zero, default io size is set to 128k (default setting),
  if it is non-zero, default io size is set to PAGE_SIZE.
parent b7651add
...@@ -500,8 +500,11 @@ static struct export_operations reiserfs_export_ops = { ...@@ -500,8 +500,11 @@ static struct export_operations reiserfs_export_ops = {
mount options that have values rather than being toggles. */ mount options that have values rather than being toggles. */
typedef struct { typedef struct {
char * value; char * value;
int bitmask; /* bit which is to be set in mount_options bitmask when this int setmask; /* bitmask which is to set on mount_options bitmask when this
value is found, 0 is no bits are to be set */ value is found, 0 is no bits are to be changed. */
int clrmask; /* bitmask which is to clear on mount_options bitmask when this
value is found, 0 is no bits are to be changed. This is
applied BEFORE setmask */
} arg_desc_t; } arg_desc_t;
...@@ -511,25 +514,30 @@ typedef struct { ...@@ -511,25 +514,30 @@ typedef struct {
char * option_name; char * option_name;
int arg_required; /* 0 if argument is not required, not 0 otherwise */ int arg_required; /* 0 if argument is not required, not 0 otherwise */
const arg_desc_t * values; /* list of values accepted by an option */ const arg_desc_t * values; /* list of values accepted by an option */
int bitmask; /* bit which is to be set in mount_options bitmask when this int setmask; /* bitmask which is to set on mount_options bitmask when this
option is selected, 0 is not bits are to be set */ value is found, 0 is no bits are to be changed. */
int clrmask; /* bitmask which is to clear on mount_options bitmask when this
value is found, 0 is no bits are to be changed. This is
applied BEFORE setmask */
} opt_desc_t; } opt_desc_t;
/* possible values for "-o block-allocator=" and bits which are to be set in /* possible values for "-o block-allocator=" and bits which are to be set in
s_mount_opt of reiserfs specific part of in-core super block */ s_mount_opt of reiserfs specific part of in-core super block */
static const arg_desc_t balloc[] = { static const arg_desc_t balloc[] = {
{"noborder", REISERFS_NO_BORDER}, {"noborder", 1<<REISERFS_NO_BORDER, 0},
{"no_unhashed_relocation", REISERFS_NO_UNHASHED_RELOCATION}, {"border", 0, 1<<REISERFS_NO_BORDER},
{"hashed_relocation", REISERFS_HASHED_RELOCATION}, {"no_unhashed_relocation", 1<<REISERFS_NO_UNHASHED_RELOCATION, 0},
{"test4", REISERFS_TEST4}, {"hashed_relocation", 1<<REISERFS_HASHED_RELOCATION, 0},
{NULL, -1} {"test4", 1<<REISERFS_TEST4, 0},
{"notest4", 0, 1<<REISERFS_TEST4},
{NULL, 0, 0}
}; };
static const arg_desc_t tails[] = { static const arg_desc_t tails[] = {
{"on", REISERFS_LARGETAIL}, {"on", 1<<REISERFS_LARGETAIL, 1<<REISERFS_SMALLTAIL},
{"off", -1}, {"off", 0, (1<<REISERFS_LARGETAIL)|(1<<REISERFS_SMALLTAIL)},
{"small", REISERFS_SMALLTAIL}, {"small", 1<<REISERFS_SMALLTAIL, 1<<REISERFS_LARGETAIL},
{NULL, 0} {NULL, 0, 0}
}; };
int reiserfs_default_io_size = 128 * 1024; /* Default recommended I/O size is 128k. int reiserfs_default_io_size = 128 * 1024; /* Default recommended I/O size is 128k.
...@@ -571,16 +579,21 @@ static int reiserfs_getopt ( struct super_block * s, char ** cur, opt_desc_t * o ...@@ -571,16 +579,21 @@ static int reiserfs_getopt ( struct super_block * s, char ** cur, opt_desc_t * o
/* Ugly special case, probably we should redo options parser so that /* Ugly special case, probably we should redo options parser so that
it can understand several arguments for some options, also so that it can understand several arguments for some options, also so that
it can fill several bitfields with option values. */ it can fill several bitfields with option values. */
reiserfs_parse_alloc_options( s, p + 6); if ( reiserfs_parse_alloc_options( s, p + 6) ) {
return 0; return -1;
} else {
return 0;
}
} }
/* for every option in the list */ /* for every option in the list */
for (opt = opts; opt->option_name; opt ++) { for (opt = opts; opt->option_name; opt ++) {
if (!strncmp (p, opt->option_name, strlen (opt->option_name))) { if (!strncmp (p, opt->option_name, strlen (opt->option_name))) {
if (bit_flags && opt->bitmask != -1) if (bit_flags) {
set_bit (opt->bitmask, bit_flags); *bit_flags &= ~opt->clrmask;
*bit_flags |= opt->setmask;
}
break; break;
} }
} }
...@@ -620,7 +633,7 @@ static int reiserfs_getopt ( struct super_block * s, char ** cur, opt_desc_t * o ...@@ -620,7 +633,7 @@ static int reiserfs_getopt ( struct super_block * s, char ** cur, opt_desc_t * o
} }
if (!opt->values) { if (!opt->values) {
/* *opt_arg contains pointer to argument */ /* *=NULLopt_arg contains pointer to argument */
*opt_arg = p; *opt_arg = p;
return opt->arg_required; return opt->arg_required;
} }
...@@ -628,8 +641,10 @@ static int reiserfs_getopt ( struct super_block * s, char ** cur, opt_desc_t * o ...@@ -628,8 +641,10 @@ static int reiserfs_getopt ( struct super_block * s, char ** cur, opt_desc_t * o
/* values possible for this option are listed in opt->values */ /* values possible for this option are listed in opt->values */
for (arg = opt->values; arg->value; arg ++) { for (arg = opt->values; arg->value; arg ++) {
if (!strcmp (p, arg->value)) { if (!strcmp (p, arg->value)) {
if (bit_flags && arg->bitmask != -1 ) if (bit_flags) {
set_bit (arg->bitmask, bit_flags); *bit_flags &= ~arg->clrmask;
*bit_flags |= arg->setmask;
}
return opt->arg_required; return opt->arg_required;
} }
} }
...@@ -638,7 +653,6 @@ static int reiserfs_getopt ( struct super_block * s, char ** cur, opt_desc_t * o ...@@ -638,7 +653,6 @@ static int reiserfs_getopt ( struct super_block * s, char ** cur, opt_desc_t * o
return -1; return -1;
} }
/* returns 0 if something is wrong in option string, 1 - otherwise */ /* returns 0 if something is wrong in option string, 1 - otherwise */
static int reiserfs_parse_options (struct super_block * s, char * options, /* string given via mount's -o */ static int reiserfs_parse_options (struct super_block * s, char * options, /* string given via mount's -o */
unsigned long * mount_options, unsigned long * mount_options,
...@@ -652,18 +666,18 @@ static int reiserfs_parse_options (struct super_block * s, char * options, /* st ...@@ -652,18 +666,18 @@ static int reiserfs_parse_options (struct super_block * s, char * options, /* st
char * arg = NULL; char * arg = NULL;
char * pos; char * pos;
opt_desc_t opts[] = { opt_desc_t opts[] = {
{"tails", 't', tails, -1}, {"tails", 't', tails, 0, 0}, /* Compatibility stuff, so that -o notail for old setups still work */
{"notail", 0, 0, -1}, /* Compatibility stuff, so that -o notail {"notail", 0, 0, 0, (1<<REISERFS_LARGETAIL)|(1<<REISERFS_SMALLTAIL)},
for old setups still work */ {"conv", 0, 0, 1<<REISERFS_CONVERT, 0},
{"conv", 0, 0, REISERFS_CONVERT}, {"attrs", 0, 0, 1<<REISERFS_ATTRS, 0},
{"attrs", 0, 0, REISERFS_ATTRS}, {"noattrs", 0, 0, 0, 1<<REISERFS_ATTRS},
{"nolog", 0, 0, -1}, {"nolog", 0, 0, 0, 0}, /* This is unsupported */
{"replayonly", 0, 0, REPLAYONLY}, {"replayonly", 0, 0, 1<<REPLAYONLY, 0},
{"block-allocator", 'a', balloc, -1}, {"block-allocator", 'a', balloc, 0, 0},
{"resize", 'r', 0, -1}, {"resize", 'r', 0, 0, 0},
{"jdev", 'j', 0, -1}, {"jdev", 'j', 0, 0, 0},
{"nolargeio", 'w', 0, -1}, {"nolargeio", 'w', 0, 0, 0},
{NULL, 0, 0, -1} {NULL, 0, 0, 0, 0}
}; };
*blocks = 0; *blocks = 0;
...@@ -671,9 +685,6 @@ for old setups still work */ ...@@ -671,9 +685,6 @@ for old setups still work */
/* use default configuration: create tails, journaling on, no /* use default configuration: create tails, journaling on, no
conversion to newest format */ conversion to newest format */
return 1; return 1;
else
/* Drop defaults to zeroes */
*mount_options = 0;
for (pos = options; pos; ) { for (pos = options; pos; ) {
c = reiserfs_getopt (s, &pos, opts, &arg, mount_options); c = reiserfs_getopt (s, &pos, opts, &arg, mount_options);
...@@ -695,11 +706,25 @@ for old setups still work */ ...@@ -695,11 +706,25 @@ for old setups still work */
} }
if ( c == 'w' ) { if ( c == 'w' ) {
reiserfs_default_io_size = PAGE_SIZE; char *p=0;
int val = simple_strtoul (arg, &p, 0);
if ( *p != '\0') {
printk ("reiserfs_parse_options: non-numeric value %s for nolargeio option\n", arg);
return 0;
}
if ( val )
reiserfs_default_io_size = PAGE_SIZE;
else
reiserfs_default_io_size = 128 * 1024;
} }
if (c == 'j') { if (c == 'j') {
if (arg && *arg && jdev_name) { if (arg && *arg && jdev_name) {
if ( *jdev_name ) { //Hm, already assigned?
printk("reiserfs_parse_options: journal device was already specified to be %s\n", *jdev_name);
return 0;
}
*jdev_name = arg; *jdev_name = arg;
} }
} }
...@@ -731,14 +756,28 @@ static int reiserfs_remount (struct super_block * s, int * mount_flags, char * a ...@@ -731,14 +756,28 @@ static int reiserfs_remount (struct super_block * s, int * mount_flags, char * a
struct reiserfs_super_block * rs; struct reiserfs_super_block * rs;
struct reiserfs_transaction_handle th ; struct reiserfs_transaction_handle th ;
unsigned long blocks; unsigned long blocks;
unsigned long mount_options; unsigned long mount_options = REISERFS_SB(s)->s_mount_opt;
unsigned long safe_mask = 0;
rs = SB_DISK_SUPER_BLOCK (s); rs = SB_DISK_SUPER_BLOCK (s);
if (!reiserfs_parse_options(s, arg, &mount_options, &blocks, NULL)) if (!reiserfs_parse_options(s, arg, &mount_options, &blocks, NULL))
return -EINVAL; return -EINVAL;
handle_attrs( s ); handle_attrs(s);
/* Add options that are safe here */
safe_mask |= 1 << REISERFS_SMALLTAIL;
safe_mask |= 1 << REISERFS_LARGETAIL;
safe_mask |= 1 << REISERFS_NO_BORDER;
safe_mask |= 1 << REISERFS_NO_UNHASHED_RELOCATION;
safe_mask |= 1 << REISERFS_HASHED_RELOCATION;
safe_mask |= 1 << REISERFS_TEST4;
safe_mask |= 1 << REISERFS_ATTRS;
/* Update the bitmask, taking care to keep
* the bits we're not allowed to change here */
REISERFS_SB(s)->s_mount_opt = (REISERFS_SB(s)->s_mount_opt & ~safe_mask) | (mount_options & safe_mask);
if(blocks) { if(blocks) {
int rc = reiserfs_resize(s, blocks); int rc = reiserfs_resize(s, blocks);
......
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