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;
  
 

Reply via email to