aboutsummaryrefslogtreecommitdiffstats
path: root/fs/affs
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /fs/affs
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'fs/affs')
-rw-r--r--fs/affs/affs.h5
-rw-r--r--fs/affs/bitmap.c3
-rw-r--r--fs/affs/inode.c3
-rw-r--r--fs/affs/namei.c7
-rw-r--r--fs/affs/super.c32
-rw-r--r--fs/affs/symlink.c7
6 files changed, 40 insertions, 17 deletions
diff --git a/fs/affs/affs.h b/fs/affs/affs.h
index e511dc621a2e..861dae68ac12 100644
--- a/fs/affs/affs.h
+++ b/fs/affs/affs.h
@@ -106,8 +106,8 @@ struct affs_sb_info {
106 u32 s_last_bmap; 106 u32 s_last_bmap;
107 struct buffer_head *s_bmap_bh; 107 struct buffer_head *s_bmap_bh;
108 char *s_prefix; /* Prefix for volumes and assigns. */ 108 char *s_prefix; /* Prefix for volumes and assigns. */
109 int s_prefix_len; /* Length of prefix. */
110 char s_volume[32]; /* Volume prefix for absolute symlinks. */ 109 char s_volume[32]; /* Volume prefix for absolute symlinks. */
110 spinlock_t symlink_lock; /* protects the previous two */
111}; 111};
112 112
113#define SF_INTL 0x0001 /* International filesystem. */ 113#define SF_INTL 0x0001 /* International filesystem. */
@@ -175,7 +175,8 @@ extern void affs_delete_inode(struct inode *inode);
175extern void affs_clear_inode(struct inode *inode); 175extern void affs_clear_inode(struct inode *inode);
176extern struct inode *affs_iget(struct super_block *sb, 176extern struct inode *affs_iget(struct super_block *sb,
177 unsigned long ino); 177 unsigned long ino);
178extern int affs_write_inode(struct inode *inode, int); 178extern int affs_write_inode(struct inode *inode,
179 struct writeback_control *wbc);
179extern int affs_add_entry(struct inode *dir, struct inode *inode, struct dentry *dentry, s32 type); 180extern int affs_add_entry(struct inode *dir, struct inode *inode, struct dentry *dentry, s32 type);
180 181
181/* file.c */ 182/* file.c */
diff --git a/fs/affs/bitmap.c b/fs/affs/bitmap.c
index dc5ef14bdc1c..3e262711ae06 100644
--- a/fs/affs/bitmap.c
+++ b/fs/affs/bitmap.c
@@ -7,6 +7,7 @@
7 * block allocation, deallocation, calculation of free space. 7 * block allocation, deallocation, calculation of free space.
8 */ 8 */
9 9
10#include <linux/slab.h>
10#include "affs.h" 11#include "affs.h"
11 12
12/* This is, of course, shamelessly stolen from fs/minix */ 13/* This is, of course, shamelessly stolen from fs/minix */
@@ -128,7 +129,7 @@ err_range:
128/* 129/*
129 * Allocate a block in the given allocation zone. 130 * Allocate a block in the given allocation zone.
130 * Since we have to byte-swap the bitmap on little-endian 131 * Since we have to byte-swap the bitmap on little-endian
131 * machines, this is rather expensive. Therefor we will 132 * machines, this is rather expensive. Therefore we will
132 * preallocate up to 16 blocks from the same word, if 133 * preallocate up to 16 blocks from the same word, if
133 * possible. We are not doing preallocations in the 134 * possible. We are not doing preallocations in the
134 * header zone, though. 135 * header zone, though.
diff --git a/fs/affs/inode.c b/fs/affs/inode.c
index 3c4ec7d864c4..f4b2a4ee4f91 100644
--- a/fs/affs/inode.c
+++ b/fs/affs/inode.c
@@ -10,6 +10,7 @@
10 * (C) 1991 Linus Torvalds - minix filesystem 10 * (C) 1991 Linus Torvalds - minix filesystem
11 */ 11 */
12#include <linux/sched.h> 12#include <linux/sched.h>
13#include <linux/gfp.h>
13#include "affs.h" 14#include "affs.h"
14 15
15extern const struct inode_operations affs_symlink_inode_operations; 16extern const struct inode_operations affs_symlink_inode_operations;
@@ -166,7 +167,7 @@ bad_inode:
166} 167}
167 168
168int 169int
169affs_write_inode(struct inode *inode, int unused) 170affs_write_inode(struct inode *inode, struct writeback_control *wbc)
170{ 171{
171 struct super_block *sb = inode->i_sb; 172 struct super_block *sb = inode->i_sb;
172 struct buffer_head *bh; 173 struct buffer_head *bh;
diff --git a/fs/affs/namei.c b/fs/affs/namei.c
index 960d336ec694..d70bbbac6b7b 100644
--- a/fs/affs/namei.c
+++ b/fs/affs/namei.c
@@ -341,10 +341,13 @@ affs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
341 p = (char *)AFFS_HEAD(bh)->table; 341 p = (char *)AFFS_HEAD(bh)->table;
342 lc = '/'; 342 lc = '/';
343 if (*symname == '/') { 343 if (*symname == '/') {
344 struct affs_sb_info *sbi = AFFS_SB(sb);
344 while (*symname == '/') 345 while (*symname == '/')
345 symname++; 346 symname++;
346 while (AFFS_SB(sb)->s_volume[i]) /* Cannot overflow */ 347 spin_lock(&sbi->symlink_lock);
347 *p++ = AFFS_SB(sb)->s_volume[i++]; 348 while (sbi->s_volume[i]) /* Cannot overflow */
349 *p++ = sbi->s_volume[i++];
350 spin_unlock(&sbi->symlink_lock);
348 } 351 }
349 while (i < maxlen && (c = *symname++)) { 352 while (i < maxlen && (c = *symname++)) {
350 if (c == '.' && lc == '/' && *symname == '.' && symname[1] == '/') { 353 if (c == '.' && lc == '/' && *symname == '.' && symname[1] == '/') {
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();
diff --git a/fs/affs/symlink.c b/fs/affs/symlink.c
index 41782539c907..ee00f08c4f53 100644
--- a/fs/affs/symlink.c
+++ b/fs/affs/symlink.c
@@ -20,7 +20,6 @@ static int affs_symlink_readpage(struct file *file, struct page *page)
20 int i, j; 20 int i, j;
21 char c; 21 char c;
22 char lc; 22 char lc;
23 char *pf;
24 23
25 pr_debug("AFFS: follow_link(ino=%lu)\n",inode->i_ino); 24 pr_debug("AFFS: follow_link(ino=%lu)\n",inode->i_ino);
26 25
@@ -32,11 +31,15 @@ static int affs_symlink_readpage(struct file *file, struct page *page)
32 j = 0; 31 j = 0;
33 lf = (struct slink_front *)bh->b_data; 32 lf = (struct slink_front *)bh->b_data;
34 lc = 0; 33 lc = 0;
35 pf = AFFS_SB(inode->i_sb)->s_prefix ? AFFS_SB(inode->i_sb)->s_prefix : "/";
36 34
37 if (strchr(lf->symname,':')) { /* Handle assign or volume name */ 35 if (strchr(lf->symname,':')) { /* Handle assign or volume name */
36 struct affs_sb_info *sbi = AFFS_SB(inode->i_sb);
37 char *pf;
38 spin_lock(&sbi->symlink_lock);
39 pf = sbi->s_prefix ? sbi->s_prefix : "/";
38 while (i < 1023 && (c = pf[i])) 40 while (i < 1023 && (c = pf[i]))
39 link[i++] = c; 41 link[i++] = c;
42 spin_unlock(&sbi->symlink_lock);
40 while (i < 1023 && lf->symname[j] != ':') 43 while (i < 1023 && lf->symname[j] != ':')
41 link[i++] = lf->symname[j++]; 44 link[i++] = lf->symname[j++];
42 if (i < 1023) 45 if (i < 1023)