Hello, Alan,
this patch corrects bug in fs/reiserfs/super.c:kgetopt() that caused
reiserfs to fail mounting with empty mount options string.
There are also some cleanups in the same function. Probably other
file-systems would find it useful, it's modeled after getopt(3).
Please, apply.
Nikita.
diff -rup linux/fs/reiserfs/super.c linux.patched/fs/reiserfs/super.c
--- linux/fs/reiserfs/super.c Fri Sep 21 20:11:56 2001
+++ linux.patched/fs/reiserfs/super.c Fri Sep 21 20:11:05 2001
@@ -349,79 +349,78 @@ struct super_operations reiserfs_sops =
/*
This function parses the (mount) options string passed to it.
-
-
- This function returns (*opt->requires_arg) if the option has been found,
+ This function returns (*opt->arg_char) if the option has been found,
and returns -1 in all other cases.
*/
-static int kgetopt (char * options, opt_desc_t * opts, char ** opt_arg, char ** pos,
- unsigned long ** bits)
+static int kgetopt (char * options, opt_desc_t * opts, char ** opt_arg,
+ char ** pos, unsigned long ** bits)
{
- char * ptr1, *ptr2, *ptr3;
- opt_desc_t * opt;
- arg_desc_t * arg;
- int option_exists = 0;
- int arg_exists = 0;
- int len_opt;
- int len_arg;
+ char * option_start, *arg_start, *option_end;
+ /* foo=bar,
+ ^ ^ ^
+ | | +-- option_end
+ | +-- arg_start
+ +-- option_start
+ */
+ opt_desc_t * opt;
+ arg_desc_t * arg;
+ int option_exists = 0;
+ int arg_exists = 0;
- ptr1 = (*pos ? *pos : options);
- ptr2 = NULL; /* here we will put pounter on '=' */
- ptr3 = NULL; /* here we will put pounter on ',' */
+ option_start = (*pos ? *pos : options);
+ arg_start = NULL; /* here we will put pointer on '=' */
+ option_end = NULL; /* here we will put pointer on ',' */
- if (!options)
- return -1;
- ptr3 = strchr (ptr1, ',');
- *pos = (ptr3 ? ptr3 + 1 : ptr1 + strlen (ptr1));
- ptr2 = strchr (ptr1, '=');
- if (ptr2 && (ptr2 >= *pos))
- ptr2 = NULL;
- len_opt = (ptr2 ? ptr2 - ptr1 : (ptr3 ? ptr3 : *pos) - ptr1);
- for (opt = opts; *(opt->keyword) != '0'; opt++) {
- if (strlen (opt->keyword) == len_opt && !strncmp (ptr1, opt->keyword,
len_opt)){
- option_exists = 1;
- if (opt->bitmask)
- set_bit (opt->bitmask, *bits);
- break;
- }
- }
- if (!option_exists) {
- printk ("reiserfs kgetopt: there is not option %s\n", ptr1);
- return -1;
- }
- if (ptr2) {
- if (!opt->requires_arg) {
- printk ("reiserfs kgetopt: the option %s does not require an argument \n",
opt->keyword);
- return -1;
- }
- len_arg = (ptr3 ? ptr3 - ptr2 - 1 : *pos - ptr2 - 1);
- if (!len_arg) {
- printk ("reiserfs kgetopt: bad value %s\n", ptr2 + 1);
- return -1;
+ if (!options)
+ return -1;
+ /* assume argument cannot contain commas */
+ option_end = strchr (option_start, ',');
+ *pos = (option_end ? option_end + 1 : option_start + strlen (option_start));
+ if (option_end)
+ *option_end = '\0';
+ arg_start = strchr (option_start, '=');
+ if (arg_start) {
+ *arg_start = '\0';
+ ++ arg_start;
+ }
+ for (opt = opts; opt->keyword != NULL; opt++) {
+ if (!strcmp (option_start, opt->keyword)) {
+ option_exists = 1;
+ if ( *bits && ( opt->bitmask >=0 ) )
+ set_bit (opt->bitmask, *bits);
+ break;
+ }
+ }
+ if (!option_exists) {
+ printk ("reiserfs kgetopt: unknown option %s\n", option_start);
+ return -1;
+ } else if (arg_start) {
+ if (!opt->arg_char) {
+ printk ("reiserfs kgetopt: the option %s does not require an
+argument \n", opt->keyword);
+ return -1;
+ } else if (!strlen (arg_start)) {
+ printk ("reiserfs kgetopt: empty argument for %s\n",
+option_start);
+ return -1;
+ } else if (!opt->args) {
+ *opt_arg = arg_start;
+ return opt->arg_char;
+ }
+ for (arg = opt->args; arg->keyword != NULL; arg++) {
+ if (!strcmp (arg_start, arg->keyword)) {
+ arg_exists = 1;
+ break;
+ }
+ }
+ if (!arg_exists) {
+ printk ("reiserfs kgetopt: bad value %s\n", arg_start);
+ return -1;
+ } else if ( *bits && ( arg->bitmask >= 0 ) )
+ set_bit (arg->bitmask, *bits);
+ } else if (opt->arg_char) {
+ printk ("reiserfs kgetopt: the option %s requires an argument \n",
+opt->keyword);
+ return -1;
}
- if (!opt->args) {
- *opt_arg = ptr2 + 1;
- return (opt->requires_arg);
- }
- for (arg = opt->args; *(arg->keyword) != '0'; arg++) {
- if (strlen (arg->keyword) == len_arg &&
- !strncmp (ptr2 + 1, arg->keyword, len_arg)) {
- arg_exists = 1;
- break;
- }
- }
- if (!arg_exists) {
- printk ("reiserfs kgetopt: bad value %s\n", ptr2 + 1);
- return -1;
- }
- set_bit (arg->bitmask, *bits);
- }
- else
- if (opt->requires_arg) {
- printk ("reiserfs kgetopt: the option %s requires an argument \n",
opt->keyword);
- return -1;
- }
- return (opt->requires_arg);
+ return opt->arg_char;
}
static int parse_options (
@@ -435,21 +434,21 @@ static int parse_options (
{
int c;
char * arg = NULL;
- char * pos = NULL;
+ char * pos;
char * p = NULL;
arg_desc_t hash[] = {
{"rupasov", FORCE_RUPASOV_HASH},
{"tea", FORCE_TEA_HASH},
{"r5", FORCE_R5_HASH},
- {"detect", 0},
- {"0", 0}
+ {"detect", -1},
+ {NULL, 0}
};
*blocks = 0;
if (!options)
/* use default configuration: create tails, journaling on, no
conversion to newest format */
return 1;
- do {
+ for( pos = options ; *pos ; ) {
opt_desc_t opts[] = {
{"notail", 0, 0, NOTAIL},
{"conv", 0, 0, REISERFS_CONVERT},
@@ -457,11 +456,11 @@ static int parse_options (
{"no_unhashed_relocation", 0, 0, REISERFS_NO_UNHASHED_RELOCATION},
{"hashed_relocation", 0, 0, REISERFS_HASHED_RELOCATION},
{"test4", 0, 0, REISERFS_TEST4},
- {"nolog", 0, 0, 0},
+ {"nolog", 0, 0, -1},
{"replayonly", 0, 0, REPLAYONLY},
- {"resize", 'r', 0, 0},
+ {"resize", 'r', 0, -1},
{"hash", 1, hash, FORCE_HASH_DETECT},
- {"0", 0, 0, 0}
+ {NULL, 0, 0, 0}
};
c = kgetopt (options, opts, &arg, &pos, &mount_options);
if (c == -1)
@@ -473,7 +472,7 @@ static int parse_options (
return 0;
}
}
- } while (*pos != '\0');
+ }
return 1;
}
Only in linux.patched/fs/reiserfs: super.c~
diff -rup linux/include/linux/reiserfs_fs.h linux.patched/include/linux/reiserfs_fs.h
--- linux/include/linux/reiserfs_fs.h Fri Sep 21 20:11:56 2001
+++ linux.patched/include/linux/reiserfs_fs.h Fri Sep 21 20:08:29 2001
@@ -156,7 +156,7 @@ typedef __u32 unp_t;
/* this struct is used in kgetopt() for containing the value for those mount
options that have values rather than being toggles. */
- typedef struct {
+typedef struct {
char * keyword;
int bitmask;
} arg_desc_t;
@@ -164,10 +164,10 @@ typedef __u32 unp_t;
/* this struct is used in kgetopt() for describing the set of reiserfs
mount options */
typedef struct {
- char * keyword;
- int requires_arg;
+ char *keyword;
+ int arg_char;
arg_desc_t *args;
- int bitmask;
+ int bitmask;
} opt_desc_t;