From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Message-ID: <3E8DAF03.6090901@namesys.com> Date: Fri, 04 Apr 2003 20:12:51 +0400 From: Yury Umanets Organization: NAMESYS.COM User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.3) Gecko/20030314 X-Accept-Language: en-us, en MIME-Version: 1.0 To: devel-kernel@altlinux.ru Content-Type: multipart/mixed; boundary="------------030102070903030403060609" Subject: [d-kernel] [Fwd: fixes/changes to mount options parser] Sender: devel-kernel-admin@altlinux.ru Errors-To: devel-kernel-admin@altlinux.ru X-BeenThere: devel-kernel@altlinux.ru X-Mailman-Version: 2.0.9 Precedence: bulk Reply-To: devel-kernel@altlinux.ru List-Unsubscribe: , List-Id: ALT Linux kernel packages development List-Post: List-Help: List-Subscribe: , List-Archive: Archived-At: List-Archive: List-Post: This is a multi-part message in MIME format. --------------030102070903030403060609 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit -------- Original Message -------- Subject: fixes/changes to mount options parser Date: Fri, 4 Apr 2003 20:05:03 +0400 From: Oleg Drokin To: reiserfs-list@namesys.com, jeffm@suse.com Hello! Ok, so after some silence on this front, here is 2.4 and 2.5 versions of mount options parser fixes I propose. These fixes consist of: When you pass some mount options at mount time, default mount options are not reset if what you pass does not change the defaults. (both in 2.4 and 2.5) If you are doing remount and parser detected error, remount fails (2.4 only) If you pass more than one jdev= option, parsers spits out error (2.5 only, as 2.4 does not have this yet) Remount options (better) support (2.5 did not had ability to propagate mount options at all, by Jeff Mahoney). What this patch does not do, but was supposed to do: Hans decided that conflicting mount options on one line (like tails=off,tails=small) should produce error on mount/remount. After I implemented this, it turned out this does not work with remounting. if you mount with -o tails=off, and then later do remount with -o tails=small, then the filesystem will be passed options string like "tails=off,tails=small". This seems to be a feature of mount(8). So the only option that cannot appear on command line twice is "jdev" ("resize" can be met more than once is you enlarged drive twice in a row). So I reverted to the old way of "last option takes effect". As I do not want to split the code to determine whenever this is mount or remount, this behaviour will take place in case of both mount and umount. Attached are three patches: 2.4.20_parsefix.diff is patch for 2.4.20 2.4_parsefix.diff is patch against latest Marchelo's bk tree. (2.4) 2.5_parsefix.diff is patch against latest Linus' bk tree. (2.5) This code was only tested by me, and I want to hear any opinions on ways to improve before I pass it to our tester and start to try to submit it upstream. So if you want to try the code, treat it as experimental one. (BTW, I wonder how often people do actually pass any mount options at all and how often remount is made wit hany additional options?) Bye, Oleg -- Yury Umanets --------------030102070903030403060609 Content-Type: text/plain; name="2.4.20_parsefix.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="2.4.20_parsefix.diff" --- fs/reiserfs/super.c.1 Fri Apr 4 18:39:16 2003 +++ fs/reiserfs/super.c Fri Apr 4 19:31:39 2003 @@ -402,8 +402,11 @@ mount options that have values rather than being toggles. */ typedef struct { char * value; - int bitmask; /* bit which is to be set in mount_options bitmask when this - value is found, 0 is no bits are to be set */ + int setmask; /* bitmask which is to set on mount_options bitmask when this + 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; @@ -413,37 +416,42 @@ char * option_name; int arg_required; /* 0 is argument is not required, not 0 otherwise */ 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 - option is selected, 0 is not bits are to be set */ + int setmask; /* bitmask which is to set on mount_options bitmask when this + 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; /* possible values for "-o hash=" and bits which are to be set in s_mount_opt of reiserfs specific part of in-core super block */ const arg_desc_t hash[] = { - {"rupasov", FORCE_RUPASOV_HASH}, - {"tea", FORCE_TEA_HASH}, - {"r5", FORCE_R5_HASH}, - {"detect", FORCE_HASH_DETECT}, - {NULL, 0} + {"rupasov", 1<option_name; opt ++) { if (!strncmp (p, opt->option_name, strlen (opt->option_name))) { - if (bit_flags && opt->bitmask != -1 ) - set_bit (opt->bitmask, bit_flags); + if (bit_flags) { + *bit_flags &= ~opt->clrmask; + *bit_flags |= opt->setmask; + } break; } } @@ -528,7 +538,7 @@ } if (!opt->values) { - /* *opt_arg contains pointer to argument */ + /* *=NULLopt_arg contains pointer to argument */ *opt_arg = p; return opt->arg_required; } @@ -536,8 +546,10 @@ /* values possible for this option are listed in opt->values */ for (arg = opt->values; arg->value; arg ++) { if (!strcmp (p, arg->value)) { - if (bit_flags && arg->bitmask != -1 ) - set_bit (arg->bitmask, bit_flags); + if (bit_flags) { + *bit_flags &= ~arg->clrmask; + *bit_flags |= arg->setmask; + } return opt->arg_required; } } @@ -546,7 +558,6 @@ return -1; } - /* 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 */ unsigned long * mount_options, @@ -559,18 +570,21 @@ char * arg = NULL; char * pos; opt_desc_t opts[] = { - {"tails", 't', tails, -1}, - {"notail", 0, 0, -1}, /* Compatibility stuff, so that -o notail for old setups still work */ - {"conv", 0, 0, REISERFS_CONVERT}, - {"nolog", 0, 0, -1}, - {"replayonly", 0, 0, REPLAYONLY}, + {"tails", 't', tails, 0, 0}, + /* Compatibility stuff, so that -o notail + for old setups still work */ + {"notail", 0, 0, 0, (1<u.reiserfs_sb.s_mount_opt; + unsigned long safe_mask = 0; rs = SB_DISK_SUPER_BLOCK (s); if (!reiserfs_parse_options(s, data, &mount_options, &blocks)) - return 0; + return -EINVAL; -#define SET_OPT( opt, bits, super ) \ - if( ( bits ) & ( 1 << ( opt ) ) ) \ - ( super ) -> u.reiserfs_sb.s_mount_opt |= ( 1 << ( opt ) ) - - /* set options in the super-block bitmask */ - SET_OPT( REISERFS_SMALLTAIL, mount_options, s ); - SET_OPT( REISERFS_LARGETAIL, mount_options, s ); - SET_OPT( REISERFS_NO_BORDER, mount_options, s ); - SET_OPT( REISERFS_NO_UNHASHED_RELOCATION, mount_options, s ); - SET_OPT( REISERFS_HASHED_RELOCATION, mount_options, s ); - SET_OPT( REISERFS_TEST4, mount_options, s ); - SET_OPT( REISERFS_ATTRS, mount_options, s ); -#undef SET_OPT + /* 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 */ + s->u.reiserfs_sb.s_mount_opt = (s->u.reiserfs_sb.s_mount_opt & ~safe_mask) | (mount_options & safe_mask); handle_attrs( s ); --------------030102070903030403060609 Content-Type: text/plain; name="2.4_parsefix.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="2.4_parsefix.diff" ===== fs/reiserfs/super.c 1.31 vs edited ===== --- 1.31/fs/reiserfs/super.c Thu Mar 13 14:52:15 2003 +++ edited/fs/reiserfs/super.c Fri Apr 4 19:37:42 2003 @@ -403,8 +403,11 @@ mount options that have values rather than being toggles. */ typedef struct { char * value; - int bitmask; /* bit which is to be set in mount_options bitmask when this - value is found, 0 is no bits are to be set */ + int setmask; /* bitmask which is to set on mount_options bitmask when this + 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; @@ -414,37 +417,42 @@ char * option_name; int arg_required; /* 0 is argument is not required, not 0 otherwise */ 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 - option is selected, 0 is not bits are to be set */ + int setmask; /* bitmask which is to set on mount_options bitmask when this + 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; /* possible values for "-o hash=" and bits which are to be set in s_mount_opt of reiserfs specific part of in-core super block */ static const arg_desc_t hash[] = { - {"rupasov", FORCE_RUPASOV_HASH}, - {"tea", FORCE_TEA_HASH}, - {"r5", FORCE_R5_HASH}, - {"detect", FORCE_HASH_DETECT}, - {NULL, 0} + {"rupasov", 1<option_name; opt ++) { if (!strncmp (p, opt->option_name, strlen (opt->option_name))) { - if (bit_flags && opt->bitmask != -1 ) - set_bit (opt->bitmask, bit_flags); + if (bit_flags) { + *bit_flags &= ~opt->clrmask; + *bit_flags |= opt->setmask; + } break; } } @@ -529,7 +539,7 @@ } if (!opt->values) { - /* *opt_arg contains pointer to argument */ + /* *=NULLopt_arg contains pointer to argument */ *opt_arg = p; return opt->arg_required; } @@ -537,8 +547,10 @@ /* values possible for this option are listed in opt->values */ for (arg = opt->values; arg->value; arg ++) { if (!strcmp (p, arg->value)) { - if (bit_flags && arg->bitmask != -1 ) - set_bit (arg->bitmask, bit_flags); + if (bit_flags) { + *bit_flags &= ~arg->clrmask; + *bit_flags |= arg->setmask; + } return opt->arg_required; } } @@ -547,7 +559,6 @@ return -1; } - /* 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 */ unsigned long * mount_options, @@ -560,18 +571,21 @@ char * arg = NULL; char * pos; opt_desc_t opts[] = { - {"tails", 't', tails, -1}, - {"notail", 0, 0, -1}, /* Compatibility stuff, so that -o notail for old setups still work */ - {"conv", 0, 0, REISERFS_CONVERT}, - {"nolog", 0, 0, -1}, - {"replayonly", 0, 0, REPLAYONLY}, + {"tails", 't', tails, 0, 0}, + /* Compatibility stuff, so that -o notail + for old setups still work */ + {"notail", 0, 0, 0, (1<u.reiserfs_sb.s_mount_opt; + unsigned long safe_mask = 0; rs = SB_DISK_SUPER_BLOCK (s); if (!reiserfs_parse_options(s, data, &mount_options, &blocks)) - return 0; + return -EINVAL; -#define SET_OPT( opt, bits, super ) \ - if( ( bits ) & ( 1 << ( opt ) ) ) \ - ( super ) -> u.reiserfs_sb.s_mount_opt |= ( 1 << ( opt ) ) - - /* set options in the super-block bitmask */ - SET_OPT( REISERFS_SMALLTAIL, mount_options, s ); - SET_OPT( REISERFS_LARGETAIL, mount_options, s ); - SET_OPT( REISERFS_NO_BORDER, mount_options, s ); - SET_OPT( REISERFS_NO_UNHASHED_RELOCATION, mount_options, s ); - SET_OPT( REISERFS_HASHED_RELOCATION, mount_options, s ); - SET_OPT( REISERFS_TEST4, mount_options, s ); - SET_OPT( REISERFS_ATTRS, mount_options, s ); -#undef SET_OPT + /* 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 */ + s->u.reiserfs_sb.s_mount_opt = (s->u.reiserfs_sb.s_mount_opt & ~safe_mask) | (mount_options & safe_mask); handle_attrs( s ); --------------030102070903030403060609 Content-Type: text/plain; name="2.5_parsefix.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="2.5_parsefix.diff" ===== fs/reiserfs/super.c 1.59 vs edited ===== --- 1.59/fs/reiserfs/super.c Tue Feb 25 20:45:25 2003 +++ edited/fs/reiserfs/super.c Fri Apr 4 18:15:34 2003 @@ -500,8 +500,11 @@ mount options that have values rather than being toggles. */ typedef struct { char * value; - int bitmask; /* bit which is to be set in mount_options bitmask when this - value is found, 0 is no bits are to be set */ + int setmask; /* bitmask which is to set on mount_options bitmask when this + 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; @@ -511,25 +514,30 @@ char * option_name; int arg_required; /* 0 if argument is not required, not 0 otherwise */ 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 - option is selected, 0 is not bits are to be set */ + int setmask; /* bitmask which is to set on mount_options bitmask when this + 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; /* 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 */ static const arg_desc_t balloc[] = { - {"noborder", REISERFS_NO_BORDER}, - {"no_unhashed_relocation", REISERFS_NO_UNHASHED_RELOCATION}, - {"hashed_relocation", REISERFS_HASHED_RELOCATION}, - {"test4", REISERFS_TEST4}, - {NULL, -1} + {"noborder", 1<option_name; opt ++) { if (!strncmp (p, opt->option_name, strlen (opt->option_name))) { - if (bit_flags && opt->bitmask != -1) - set_bit (opt->bitmask, bit_flags); + if (bit_flags) { + *bit_flags &= ~opt->clrmask; + *bit_flags |= opt->setmask; + } break; } } @@ -615,7 +625,7 @@ } if (!opt->values) { - /* *opt_arg contains pointer to argument */ + /* *=NULLopt_arg contains pointer to argument */ *opt_arg = p; return opt->arg_required; } @@ -623,8 +633,10 @@ /* values possible for this option are listed in opt->values */ for (arg = opt->values; arg->value; arg ++) { if (!strcmp (p, arg->value)) { - if (bit_flags && arg->bitmask != -1 ) - set_bit (arg->bitmask, bit_flags); + if (bit_flags) { + *bit_flags &= ~arg->clrmask; + *bit_flags |= arg->setmask; + } return opt->arg_required; } } @@ -633,7 +645,6 @@ return -1; } - /* 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 */ unsigned long * mount_options, @@ -647,17 +658,19 @@ char * arg = NULL; char * pos; opt_desc_t opts[] = { - {"tails", 't', tails, -1}, - {"notail", 0, 0, -1}, /* Compatibility stuff, so that -o notail -for old setups still work */ - {"conv", 0, 0, REISERFS_CONVERT}, - {"attrs", 0, 0, REISERFS_ATTRS}, - {"nolog", 0, 0, -1}, - {"replayonly", 0, 0, REPLAYONLY}, - {"block-allocator", 'a', balloc, -1}, - {"resize", 'r', 0, -1}, - {"jdev", 'j', 0, -1}, - {NULL, 0, 0, -1} + {"tails", 't', tails, 0, 0}, + /* Compatibility stuff, so that -o notail + for old setups still work */ + {"notail", 0, 0, 0, (1<s_mount_opt; + unsigned long safe_mask = 0; rs = SB_DISK_SUPER_BLOCK (s); if (!reiserfs_parse_options(s, arg, &mount_options, &blocks, NULL)) return -EINVAL; - + + /* 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) { int rc = reiserfs_resize(s, blocks); if (rc != 0) --------------030102070903030403060609--