aboutsummaryrefslogtreecommitdiffstats
path: root/fs/affs/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/affs/super.c')
-rw-r--r--fs/affs/super.c32
1 files changed, 23 insertions, 9 deletions
diff --git a/fs/affs/super.c b/fs/affs/super.c
index 104fdcb3a7fc..16a3e4765f68 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -17,6 +17,7 @@
17#include <linux/magic.h> 17#include <linux/magic.h>
18#include <linux/sched.h> 18#include <linux/sched.h>
19#include <linux/smp_lock.h> 19#include <linux/smp_lock.h>
20#include <linux/slab.h>
20#include "affs.h" 21#include "affs.h"
21 22
22extern struct timezone sys_tz; 23extern struct timezone sys_tz;
@@ -203,7 +204,7 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s
203 switch (token) { 204 switch (token) {
204 case Opt_bs: 205 case Opt_bs:
205 if (match_int(&args[0], &n)) 206 if (match_int(&args[0], &n))
206 return -EINVAL; 207 return 0;
207 if (n != 512 && n != 1024 && n != 2048 208 if (n != 512 && n != 1024 && n != 2048
208 && n != 4096) { 209 && n != 4096) {
209 printk ("AFFS: Invalid blocksize (512, 1024, 2048, 4096 allowed)\n"); 210 printk ("AFFS: Invalid blocksize (512, 1024, 2048, 4096 allowed)\n");
@@ -213,7 +214,7 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s
213 break; 214 break;
214 case Opt_mode: 215 case Opt_mode:
215 if (match_octal(&args[0], &option)) 216 if (match_octal(&args[0], &option))
216 return 1; 217 return 0;
217 *mode = option & 0777; 218 *mode = option & 0777;
218 *mount_opts |= SF_SETMODE; 219 *mount_opts |= SF_SETMODE;
219 break; 220 break;
@@ -221,8 +222,6 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s
221 *mount_opts |= SF_MUFS; 222 *mount_opts |= SF_MUFS;
222 break; 223 break;
223 case Opt_prefix: 224 case Opt_prefix:
224 /* Free any previous prefix */
225 kfree(*prefix);
226 *prefix = match_strdup(&args[0]); 225 *prefix = match_strdup(&args[0]);
227 if (!*prefix) 226 if (!*prefix)
228 return 0; 227 return 0;
@@ -233,21 +232,21 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s
233 break; 232 break;
234 case Opt_reserved: 233 case Opt_reserved:
235 if (match_int(&args[0], reserved)) 234 if (match_int(&args[0], reserved))
236 return 1; 235 return 0;
237 break; 236 break;
238 case Opt_root: 237 case Opt_root:
239 if (match_int(&args[0], root)) 238 if (match_int(&args[0], root))
240 return 1; 239 return 0;
241 break; 240 break;
242 case Opt_setgid: 241 case Opt_setgid:
243 if (match_int(&args[0], &option)) 242 if (match_int(&args[0], &option))
244 return 1; 243 return 0;
245 *gid = option; 244 *gid = option;
246 *mount_opts |= SF_SETGID; 245 *mount_opts |= SF_SETGID;
247 break; 246 break;
248 case Opt_setuid: 247 case Opt_setuid:
249 if (match_int(&args[0], &option)) 248 if (match_int(&args[0], &option))
250 return -EINVAL; 249 return 0;
251 *uid = option; 250 *uid = option;
252 *mount_opts |= SF_SETUID; 251 *mount_opts |= SF_SETUID;
253 break; 252 break;
@@ -311,11 +310,14 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
311 return -ENOMEM; 310 return -ENOMEM;
312 sb->s_fs_info = sbi; 311 sb->s_fs_info = sbi;
313 mutex_init(&sbi->s_bmlock); 312 mutex_init(&sbi->s_bmlock);
313 spin_lock_init(&sbi->symlink_lock);
314 314
315 if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block, 315 if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block,
316 &blocksize,&sbi->s_prefix, 316 &blocksize,&sbi->s_prefix,
317 sbi->s_volume, &mount_flags)) { 317 sbi->s_volume, &mount_flags)) {
318 printk(KERN_ERR "AFFS: Error parsing options\n"); 318 printk(KERN_ERR "AFFS: Error parsing options\n");
319 kfree(sbi->s_prefix);
320 kfree(sbi);
319 return -EINVAL; 321 return -EINVAL;
320 } 322 }
321 /* N.B. after this point s_prefix must be released */ 323 /* N.B. after this point s_prefix must be released */
@@ -516,14 +518,18 @@ affs_remount(struct super_block *sb, int *flags, char *data)
516 unsigned long mount_flags; 518 unsigned long mount_flags;
517 int res = 0; 519 int res = 0;
518 char *new_opts = kstrdup(data, GFP_KERNEL); 520 char *new_opts = kstrdup(data, GFP_KERNEL);
521 char volume[32];
522 char *prefix = NULL;
519 523
520 pr_debug("AFFS: remount(flags=0x%x,opts=\"%s\")\n",*flags,data); 524 pr_debug("AFFS: remount(flags=0x%x,opts=\"%s\")\n",*flags,data);
521 525
522 *flags |= MS_NODIRATIME; 526 *flags |= MS_NODIRATIME;
523 527
528 memcpy(volume, sbi->s_volume, 32);
524 if (!parse_options(data, &uid, &gid, &mode, &reserved, &root_block, 529 if (!parse_options(data, &uid, &gid, &mode, &reserved, &root_block,
525 &blocksize, &sbi->s_prefix, sbi->s_volume, 530 &blocksize, &prefix, volume,
526 &mount_flags)) { 531 &mount_flags)) {
532 kfree(prefix);
527 kfree(new_opts); 533 kfree(new_opts);
528 return -EINVAL; 534 return -EINVAL;
529 } 535 }
@@ -534,6 +540,14 @@ affs_remount(struct super_block *sb, int *flags, char *data)
534 sbi->s_mode = mode; 540 sbi->s_mode = mode;
535 sbi->s_uid = uid; 541 sbi->s_uid = uid;
536 sbi->s_gid = gid; 542 sbi->s_gid = gid;
543 /* protect against readers */
544 spin_lock(&sbi->symlink_lock);
545 if (prefix) {
546 kfree(sbi->s_prefix);
547 sbi->s_prefix = prefix;
548 }
549 memcpy(sbi->s_volume, volume, 32);
550 spin_unlock(&sbi->symlink_lock);
537 551
538 if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) { 552 if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) {
539 unlock_kernel(); 553 unlock_kernel();