diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-08-01 14:26:51 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-08-01 14:26:51 -0400 |
commit | d65f5c5803d9cd6fa0b540a0dddf956be671bc36 (patch) | |
tree | d8b7e7197bd126ce857c9a368dd7573b531cb22f | |
parent | a8086ad803fc4d251edb9a49838bf99c7fdfb44f (diff) | |
parent | 8d66bf5481002b0960aa49aed0987c73f5d7816c (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6:
[PATCH] pass struct path * to do_add_mount()
[PATCH] switch mtd and dm-table to lookup_bdev()
[patch 3/4] vfs: remove unused nameidata argument of may_create()
[PATCH] devpts: switch to IDA
[PATCH 2/2] proc: switch inode number allocation to IDA
[PATCH 1/2] proc: fix inode number bogorithmetic
[PATCH] fix bdev leak in block_dev.c do_open()
[PATCH] fix races and leaks in vfs_quota_on() users
[PATCH] clean dup2() up a bit
[PATCH] merge locate_fd() and get_unused_fd()
[PATCH] ipv4_static_sysctl_init() should be under CONFIG_SYSCTL
Re: BUG at security/selinux/avc.c:883 (was: Re: linux-next: Tree
-rw-r--r-- | drivers/md/dm-table.c | 29 | ||||
-rw-r--r-- | drivers/mtd/mtdsuper.c | 33 | ||||
-rw-r--r-- | fs/afs/mntpt.c | 2 | ||||
-rw-r--r-- | fs/block_dev.c | 5 | ||||
-rw-r--r-- | fs/cifs/cifs_dfs_ref.c | 2 | ||||
-rw-r--r-- | fs/devpts/inode.c | 16 | ||||
-rw-r--r-- | fs/dquot.c | 33 | ||||
-rw-r--r-- | fs/ext3/super.c | 3 | ||||
-rw-r--r-- | fs/ext4/super.c | 3 | ||||
-rw-r--r-- | fs/fcntl.c | 140 | ||||
-rw-r--r-- | fs/file.c | 61 | ||||
-rw-r--r-- | fs/namei.c | 17 | ||||
-rw-r--r-- | fs/namespace.c | 16 | ||||
-rw-r--r-- | fs/nfs/namespace.c | 2 | ||||
-rw-r--r-- | fs/open.c | 56 | ||||
-rw-r--r-- | fs/proc/generic.c | 27 | ||||
-rw-r--r-- | fs/reiserfs/super.c | 16 | ||||
-rw-r--r-- | include/linux/file.h | 3 | ||||
-rw-r--r-- | include/linux/mount.h | 3 | ||||
-rw-r--r-- | include/linux/quotaops.h | 2 | ||||
-rw-r--r-- | net/ipv4/route.c | 2 |
21 files changed, 203 insertions, 268 deletions
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 798e468103b8..61f441409234 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c | |||
@@ -316,29 +316,12 @@ static inline int check_space(struct dm_table *t) | |||
316 | */ | 316 | */ |
317 | static int lookup_device(const char *path, dev_t *dev) | 317 | static int lookup_device(const char *path, dev_t *dev) |
318 | { | 318 | { |
319 | int r; | 319 | struct block_device *bdev = lookup_bdev(path); |
320 | struct nameidata nd; | 320 | if (IS_ERR(bdev)) |
321 | struct inode *inode; | 321 | return PTR_ERR(bdev); |
322 | 322 | *dev = bdev->bd_dev; | |
323 | if ((r = path_lookup(path, LOOKUP_FOLLOW, &nd))) | 323 | bdput(bdev); |
324 | return r; | 324 | return 0; |
325 | |||
326 | inode = nd.path.dentry->d_inode; | ||
327 | if (!inode) { | ||
328 | r = -ENOENT; | ||
329 | goto out; | ||
330 | } | ||
331 | |||
332 | if (!S_ISBLK(inode->i_mode)) { | ||
333 | r = -ENOTBLK; | ||
334 | goto out; | ||
335 | } | ||
336 | |||
337 | *dev = inode->i_rdev; | ||
338 | |||
339 | out: | ||
340 | path_put(&nd.path); | ||
341 | return r; | ||
342 | } | 325 | } |
343 | 326 | ||
344 | /* | 327 | /* |
diff --git a/drivers/mtd/mtdsuper.c b/drivers/mtd/mtdsuper.c index 28cc6787a800..9b6af7e74a65 100644 --- a/drivers/mtd/mtdsuper.c +++ b/drivers/mtd/mtdsuper.c | |||
@@ -125,7 +125,7 @@ int get_sb_mtd(struct file_system_type *fs_type, int flags, | |||
125 | int (*fill_super)(struct super_block *, void *, int), | 125 | int (*fill_super)(struct super_block *, void *, int), |
126 | struct vfsmount *mnt) | 126 | struct vfsmount *mnt) |
127 | { | 127 | { |
128 | struct nameidata nd; | 128 | struct block_device *bdev; |
129 | int mtdnr, ret; | 129 | int mtdnr, ret; |
130 | 130 | ||
131 | if (!dev_name) | 131 | if (!dev_name) |
@@ -181,29 +181,20 @@ int get_sb_mtd(struct file_system_type *fs_type, int flags, | |||
181 | /* try the old way - the hack where we allowed users to mount | 181 | /* try the old way - the hack where we allowed users to mount |
182 | * /dev/mtdblock$(n) but didn't actually _use_ the blockdev | 182 | * /dev/mtdblock$(n) but didn't actually _use_ the blockdev |
183 | */ | 183 | */ |
184 | ret = path_lookup(dev_name, LOOKUP_FOLLOW, &nd); | 184 | bdev = lookup_bdev(dev_name); |
185 | 185 | if (IS_ERR(bdev)) { | |
186 | DEBUG(1, "MTDSB: path_lookup() returned %d, inode %p\n", | 186 | ret = PTR_ERR(bdev); |
187 | ret, nd.path.dentry ? nd.path.dentry->d_inode : NULL); | 187 | DEBUG(1, "MTDSB: lookup_bdev() returned %d\n", ret); |
188 | |||
189 | if (ret) | ||
190 | return ret; | 188 | return ret; |
191 | |||
192 | ret = -EINVAL; | ||
193 | |||
194 | if (!S_ISBLK(nd.path.dentry->d_inode->i_mode)) | ||
195 | goto out; | ||
196 | |||
197 | if (nd.path.mnt->mnt_flags & MNT_NODEV) { | ||
198 | ret = -EACCES; | ||
199 | goto out; | ||
200 | } | 189 | } |
190 | DEBUG(1, "MTDSB: lookup_bdev() returned 0\n"); | ||
201 | 191 | ||
202 | if (imajor(nd.path.dentry->d_inode) != MTD_BLOCK_MAJOR) | 192 | ret = -EINVAL; |
193 | if (MAJOR(bdev->bd_dev) != MTD_BLOCK_MAJOR) | ||
203 | goto not_an_MTD_device; | 194 | goto not_an_MTD_device; |
204 | 195 | ||
205 | mtdnr = iminor(nd.path.dentry->d_inode); | 196 | mtdnr = MINOR(bdev->bd_dev); |
206 | path_put(&nd.path); | 197 | bdput(bdev); |
207 | 198 | ||
208 | return get_sb_mtd_nr(fs_type, flags, dev_name, data, mtdnr, fill_super, | 199 | return get_sb_mtd_nr(fs_type, flags, dev_name, data, mtdnr, fill_super, |
209 | mnt); | 200 | mnt); |
@@ -213,10 +204,8 @@ not_an_MTD_device: | |||
213 | printk(KERN_NOTICE | 204 | printk(KERN_NOTICE |
214 | "MTD: Attempt to mount non-MTD device \"%s\"\n", | 205 | "MTD: Attempt to mount non-MTD device \"%s\"\n", |
215 | dev_name); | 206 | dev_name); |
216 | out: | 207 | bdput(bdev); |
217 | path_put(&nd.path); | ||
218 | return ret; | 208 | return ret; |
219 | |||
220 | } | 209 | } |
221 | 210 | ||
222 | EXPORT_SYMBOL_GPL(get_sb_mtd); | 211 | EXPORT_SYMBOL_GPL(get_sb_mtd); |
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c index 2f5503902c37..78db4953a800 100644 --- a/fs/afs/mntpt.c +++ b/fs/afs/mntpt.c | |||
@@ -232,7 +232,7 @@ static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
232 | } | 232 | } |
233 | 233 | ||
234 | mntget(newmnt); | 234 | mntget(newmnt); |
235 | err = do_add_mount(newmnt, nd, MNT_SHRINKABLE, &afs_vfsmounts); | 235 | err = do_add_mount(newmnt, &nd->path, MNT_SHRINKABLE, &afs_vfsmounts); |
236 | switch (err) { | 236 | switch (err) { |
237 | case 0: | 237 | case 0: |
238 | path_put(&nd->path); | 238 | path_put(&nd->path); |
diff --git a/fs/block_dev.c b/fs/block_dev.c index dcf37cada369..aff54219e049 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -941,8 +941,10 @@ static int do_open(struct block_device *bdev, struct file *file, int for_part) | |||
941 | * hooks: /n/, see "layering violations". | 941 | * hooks: /n/, see "layering violations". |
942 | */ | 942 | */ |
943 | ret = devcgroup_inode_permission(bdev->bd_inode, perm); | 943 | ret = devcgroup_inode_permission(bdev->bd_inode, perm); |
944 | if (ret != 0) | 944 | if (ret != 0) { |
945 | bdput(bdev); | ||
945 | return ret; | 946 | return ret; |
947 | } | ||
946 | 948 | ||
947 | ret = -ENXIO; | 949 | ret = -ENXIO; |
948 | file->f_mapping = bdev->bd_inode->i_mapping; | 950 | file->f_mapping = bdev->bd_inode->i_mapping; |
@@ -1234,6 +1236,7 @@ fail: | |||
1234 | bdev = ERR_PTR(error); | 1236 | bdev = ERR_PTR(error); |
1235 | goto out; | 1237 | goto out; |
1236 | } | 1238 | } |
1239 | EXPORT_SYMBOL(lookup_bdev); | ||
1237 | 1240 | ||
1238 | /** | 1241 | /** |
1239 | * open_bdev_excl - open a block device by name and set it up for use | 1242 | * open_bdev_excl - open a block device by name and set it up for use |
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index d82374c9e329..d2c8eef84f3c 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c | |||
@@ -226,7 +226,7 @@ static int add_mount_helper(struct vfsmount *newmnt, struct nameidata *nd, | |||
226 | int err; | 226 | int err; |
227 | 227 | ||
228 | mntget(newmnt); | 228 | mntget(newmnt); |
229 | err = do_add_mount(newmnt, nd, nd->path.mnt->mnt_flags, mntlist); | 229 | err = do_add_mount(newmnt, &nd->path, nd->path.mnt->mnt_flags, mntlist); |
230 | switch (err) { | 230 | switch (err) { |
231 | case 0: | 231 | case 0: |
232 | path_put(&nd->path); | 232 | path_put(&nd->path); |
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index 285b64a8b06e..488eb424f662 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #define DEVPTS_DEFAULT_MODE 0600 | 29 | #define DEVPTS_DEFAULT_MODE 0600 |
30 | 30 | ||
31 | extern int pty_limit; /* Config limit on Unix98 ptys */ | 31 | extern int pty_limit; /* Config limit on Unix98 ptys */ |
32 | static DEFINE_IDR(allocated_ptys); | 32 | static DEFINE_IDA(allocated_ptys); |
33 | static DEFINE_MUTEX(allocated_ptys_lock); | 33 | static DEFINE_MUTEX(allocated_ptys_lock); |
34 | 34 | ||
35 | static struct vfsmount *devpts_mnt; | 35 | static struct vfsmount *devpts_mnt; |
@@ -180,24 +180,24 @@ static struct dentry *get_node(int num) | |||
180 | int devpts_new_index(void) | 180 | int devpts_new_index(void) |
181 | { | 181 | { |
182 | int index; | 182 | int index; |
183 | int idr_ret; | 183 | int ida_ret; |
184 | 184 | ||
185 | retry: | 185 | retry: |
186 | if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) { | 186 | if (!ida_pre_get(&allocated_ptys, GFP_KERNEL)) { |
187 | return -ENOMEM; | 187 | return -ENOMEM; |
188 | } | 188 | } |
189 | 189 | ||
190 | mutex_lock(&allocated_ptys_lock); | 190 | mutex_lock(&allocated_ptys_lock); |
191 | idr_ret = idr_get_new(&allocated_ptys, NULL, &index); | 191 | ida_ret = ida_get_new(&allocated_ptys, &index); |
192 | if (idr_ret < 0) { | 192 | if (ida_ret < 0) { |
193 | mutex_unlock(&allocated_ptys_lock); | 193 | mutex_unlock(&allocated_ptys_lock); |
194 | if (idr_ret == -EAGAIN) | 194 | if (ida_ret == -EAGAIN) |
195 | goto retry; | 195 | goto retry; |
196 | return -EIO; | 196 | return -EIO; |
197 | } | 197 | } |
198 | 198 | ||
199 | if (index >= pty_limit) { | 199 | if (index >= pty_limit) { |
200 | idr_remove(&allocated_ptys, index); | 200 | ida_remove(&allocated_ptys, index); |
201 | mutex_unlock(&allocated_ptys_lock); | 201 | mutex_unlock(&allocated_ptys_lock); |
202 | return -EIO; | 202 | return -EIO; |
203 | } | 203 | } |
@@ -208,7 +208,7 @@ retry: | |||
208 | void devpts_kill_index(int idx) | 208 | void devpts_kill_index(int idx) |
209 | { | 209 | { |
210 | mutex_lock(&allocated_ptys_lock); | 210 | mutex_lock(&allocated_ptys_lock); |
211 | idr_remove(&allocated_ptys, idx); | 211 | ida_remove(&allocated_ptys, idx); |
212 | mutex_unlock(&allocated_ptys_lock); | 212 | mutex_unlock(&allocated_ptys_lock); |
213 | } | 213 | } |
214 | 214 | ||
diff --git a/fs/dquot.c b/fs/dquot.c index 1346eebe74ce..8ec4d6cc7633 100644 --- a/fs/dquot.c +++ b/fs/dquot.c | |||
@@ -1793,6 +1793,21 @@ static int vfs_quota_on_remount(struct super_block *sb, int type) | |||
1793 | return ret; | 1793 | return ret; |
1794 | } | 1794 | } |
1795 | 1795 | ||
1796 | int vfs_quota_on_path(struct super_block *sb, int type, int format_id, | ||
1797 | struct path *path) | ||
1798 | { | ||
1799 | int error = security_quota_on(path->dentry); | ||
1800 | if (error) | ||
1801 | return error; | ||
1802 | /* Quota file not on the same filesystem? */ | ||
1803 | if (path->mnt->mnt_sb != sb) | ||
1804 | error = -EXDEV; | ||
1805 | else | ||
1806 | error = vfs_quota_on_inode(path->dentry->d_inode, type, | ||
1807 | format_id); | ||
1808 | return error; | ||
1809 | } | ||
1810 | |||
1796 | /* Actual function called from quotactl() */ | 1811 | /* Actual function called from quotactl() */ |
1797 | int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path, | 1812 | int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path, |
1798 | int remount) | 1813 | int remount) |
@@ -1804,19 +1819,10 @@ int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path, | |||
1804 | return vfs_quota_on_remount(sb, type); | 1819 | return vfs_quota_on_remount(sb, type); |
1805 | 1820 | ||
1806 | error = path_lookup(path, LOOKUP_FOLLOW, &nd); | 1821 | error = path_lookup(path, LOOKUP_FOLLOW, &nd); |
1807 | if (error < 0) | 1822 | if (!error) { |
1808 | return error; | 1823 | error = vfs_quota_on_path(sb, type, format_id, &nd.path); |
1809 | error = security_quota_on(nd.path.dentry); | 1824 | path_put(&nd.path); |
1810 | if (error) | 1825 | } |
1811 | goto out_path; | ||
1812 | /* Quota file not on the same filesystem? */ | ||
1813 | if (nd.path.mnt->mnt_sb != sb) | ||
1814 | error = -EXDEV; | ||
1815 | else | ||
1816 | error = vfs_quota_on_inode(nd.path.dentry->d_inode, type, | ||
1817 | format_id); | ||
1818 | out_path: | ||
1819 | path_put(&nd.path); | ||
1820 | return error; | 1826 | return error; |
1821 | } | 1827 | } |
1822 | 1828 | ||
@@ -2185,6 +2191,7 @@ EXPORT_SYMBOL(unregister_quota_format); | |||
2185 | EXPORT_SYMBOL(dqstats); | 2191 | EXPORT_SYMBOL(dqstats); |
2186 | EXPORT_SYMBOL(dq_data_lock); | 2192 | EXPORT_SYMBOL(dq_data_lock); |
2187 | EXPORT_SYMBOL(vfs_quota_on); | 2193 | EXPORT_SYMBOL(vfs_quota_on); |
2194 | EXPORT_SYMBOL(vfs_quota_on_path); | ||
2188 | EXPORT_SYMBOL(vfs_quota_on_mount); | 2195 | EXPORT_SYMBOL(vfs_quota_on_mount); |
2189 | EXPORT_SYMBOL(vfs_quota_off); | 2196 | EXPORT_SYMBOL(vfs_quota_off); |
2190 | EXPORT_SYMBOL(vfs_quota_sync); | 2197 | EXPORT_SYMBOL(vfs_quota_sync); |
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 8ddced384674..f38a5afc39a1 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
@@ -2810,8 +2810,9 @@ static int ext3_quota_on(struct super_block *sb, int type, int format_id, | |||
2810 | journal_unlock_updates(EXT3_SB(sb)->s_journal); | 2810 | journal_unlock_updates(EXT3_SB(sb)->s_journal); |
2811 | } | 2811 | } |
2812 | 2812 | ||
2813 | err = vfs_quota_on_path(sb, type, format_id, &nd.path); | ||
2813 | path_put(&nd.path); | 2814 | path_put(&nd.path); |
2814 | return vfs_quota_on(sb, type, format_id, path, remount); | 2815 | return err; |
2815 | } | 2816 | } |
2816 | 2817 | ||
2817 | /* Read data from quotafile - avoid pagecache and such because we cannot afford | 2818 | /* Read data from quotafile - avoid pagecache and such because we cannot afford |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index b5479b1dff14..1e69f29a8c55 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -3352,8 +3352,9 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id, | |||
3352 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); | 3352 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); |
3353 | } | 3353 | } |
3354 | 3354 | ||
3355 | err = vfs_quota_on_path(sb, type, format_id, &nd.path); | ||
3355 | path_put(&nd.path); | 3356 | path_put(&nd.path); |
3356 | return vfs_quota_on(sb, type, format_id, path, remount); | 3357 | return err; |
3357 | } | 3358 | } |
3358 | 3359 | ||
3359 | /* Read data from quotafile - avoid pagecache and such because we cannot afford | 3360 | /* Read data from quotafile - avoid pagecache and such because we cannot afford |
diff --git a/fs/fcntl.c b/fs/fcntl.c index 61d625136813..ac4f7db9f134 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c | |||
@@ -49,73 +49,6 @@ static int get_close_on_exec(unsigned int fd) | |||
49 | return res; | 49 | return res; |
50 | } | 50 | } |
51 | 51 | ||
52 | /* | ||
53 | * locate_fd finds a free file descriptor in the open_fds fdset, | ||
54 | * expanding the fd arrays if necessary. Must be called with the | ||
55 | * file_lock held for write. | ||
56 | */ | ||
57 | |||
58 | static int locate_fd(unsigned int orig_start, int cloexec) | ||
59 | { | ||
60 | struct files_struct *files = current->files; | ||
61 | unsigned int newfd; | ||
62 | unsigned int start; | ||
63 | int error; | ||
64 | struct fdtable *fdt; | ||
65 | |||
66 | spin_lock(&files->file_lock); | ||
67 | repeat: | ||
68 | fdt = files_fdtable(files); | ||
69 | /* | ||
70 | * Someone might have closed fd's in the range | ||
71 | * orig_start..fdt->next_fd | ||
72 | */ | ||
73 | start = orig_start; | ||
74 | if (start < files->next_fd) | ||
75 | start = files->next_fd; | ||
76 | |||
77 | newfd = start; | ||
78 | if (start < fdt->max_fds) | ||
79 | newfd = find_next_zero_bit(fdt->open_fds->fds_bits, | ||
80 | fdt->max_fds, start); | ||
81 | |||
82 | error = expand_files(files, newfd); | ||
83 | if (error < 0) | ||
84 | goto out; | ||
85 | |||
86 | /* | ||
87 | * If we needed to expand the fs array we | ||
88 | * might have blocked - try again. | ||
89 | */ | ||
90 | if (error) | ||
91 | goto repeat; | ||
92 | |||
93 | if (start <= files->next_fd) | ||
94 | files->next_fd = newfd + 1; | ||
95 | |||
96 | FD_SET(newfd, fdt->open_fds); | ||
97 | if (cloexec) | ||
98 | FD_SET(newfd, fdt->close_on_exec); | ||
99 | else | ||
100 | FD_CLR(newfd, fdt->close_on_exec); | ||
101 | error = newfd; | ||
102 | |||
103 | out: | ||
104 | spin_unlock(&files->file_lock); | ||
105 | return error; | ||
106 | } | ||
107 | |||
108 | static int dupfd(struct file *file, unsigned int start, int cloexec) | ||
109 | { | ||
110 | int fd = locate_fd(start, cloexec); | ||
111 | if (fd >= 0) | ||
112 | fd_install(fd, file); | ||
113 | else | ||
114 | fput(file); | ||
115 | |||
116 | return fd; | ||
117 | } | ||
118 | |||
119 | asmlinkage long sys_dup3(unsigned int oldfd, unsigned int newfd, int flags) | 52 | asmlinkage long sys_dup3(unsigned int oldfd, unsigned int newfd, int flags) |
120 | { | 53 | { |
121 | int err = -EBADF; | 54 | int err = -EBADF; |
@@ -130,31 +63,35 @@ asmlinkage long sys_dup3(unsigned int oldfd, unsigned int newfd, int flags) | |||
130 | return -EINVAL; | 63 | return -EINVAL; |
131 | 64 | ||
132 | spin_lock(&files->file_lock); | 65 | spin_lock(&files->file_lock); |
133 | if (!(file = fcheck(oldfd))) | ||
134 | goto out_unlock; | ||
135 | get_file(file); /* We are now finished with oldfd */ | ||
136 | |||
137 | err = expand_files(files, newfd); | 66 | err = expand_files(files, newfd); |
67 | file = fcheck(oldfd); | ||
68 | if (unlikely(!file)) | ||
69 | goto Ebadf; | ||
138 | if (unlikely(err < 0)) { | 70 | if (unlikely(err < 0)) { |
139 | if (err == -EMFILE) | 71 | if (err == -EMFILE) |
140 | err = -EBADF; | 72 | goto Ebadf; |
141 | goto out_fput; | 73 | goto out_unlock; |
142 | } | 74 | } |
143 | 75 | /* | |
144 | /* To avoid races with open() and dup(), we will mark the fd as | 76 | * We need to detect attempts to do dup2() over allocated but still |
145 | * in-use in the open-file bitmap throughout the entire dup2() | 77 | * not finished descriptor. NB: OpenBSD avoids that at the price of |
146 | * process. This is quite safe: do_close() uses the fd array | 78 | * extra work in their equivalent of fget() - they insert struct |
147 | * entry, not the bitmap, to decide what work needs to be | 79 | * file immediately after grabbing descriptor, mark it larval if |
148 | * done. --sct */ | 80 | * more work (e.g. actual opening) is needed and make sure that |
149 | /* Doesn't work. open() might be there first. --AV */ | 81 | * fget() treats larval files as absent. Potentially interesting, |
150 | 82 | * but while extra work in fget() is trivial, locking implications | |
151 | /* Yes. It's a race. In user space. Nothing sane to do */ | 83 | * and amount of surgery on open()-related paths in VFS are not. |
84 | * FreeBSD fails with -EBADF in the same situation, NetBSD "solution" | ||
85 | * deadlocks in rather amusing ways, AFAICS. All of that is out of | ||
86 | * scope of POSIX or SUS, since neither considers shared descriptor | ||
87 | * tables and this condition does not arise without those. | ||
88 | */ | ||
152 | err = -EBUSY; | 89 | err = -EBUSY; |
153 | fdt = files_fdtable(files); | 90 | fdt = files_fdtable(files); |
154 | tofree = fdt->fd[newfd]; | 91 | tofree = fdt->fd[newfd]; |
155 | if (!tofree && FD_ISSET(newfd, fdt->open_fds)) | 92 | if (!tofree && FD_ISSET(newfd, fdt->open_fds)) |
156 | goto out_fput; | 93 | goto out_unlock; |
157 | 94 | get_file(file); | |
158 | rcu_assign_pointer(fdt->fd[newfd], file); | 95 | rcu_assign_pointer(fdt->fd[newfd], file); |
159 | FD_SET(newfd, fdt->open_fds); | 96 | FD_SET(newfd, fdt->open_fds); |
160 | if (flags & O_CLOEXEC) | 97 | if (flags & O_CLOEXEC) |
@@ -165,17 +102,14 @@ asmlinkage long sys_dup3(unsigned int oldfd, unsigned int newfd, int flags) | |||
165 | 102 | ||
166 | if (tofree) | 103 | if (tofree) |
167 | filp_close(tofree, files); | 104 | filp_close(tofree, files); |
168 | err = newfd; | ||
169 | out: | ||
170 | return err; | ||
171 | out_unlock: | ||
172 | spin_unlock(&files->file_lock); | ||
173 | goto out; | ||
174 | 105 | ||
175 | out_fput: | 106 | return newfd; |
107 | |||
108 | Ebadf: | ||
109 | err = -EBADF; | ||
110 | out_unlock: | ||
176 | spin_unlock(&files->file_lock); | 111 | spin_unlock(&files->file_lock); |
177 | fput(file); | 112 | return err; |
178 | goto out; | ||
179 | } | 113 | } |
180 | 114 | ||
181 | asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd) | 115 | asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd) |
@@ -194,10 +128,15 @@ asmlinkage long sys_dup2(unsigned int oldfd, unsigned int newfd) | |||
194 | asmlinkage long sys_dup(unsigned int fildes) | 128 | asmlinkage long sys_dup(unsigned int fildes) |
195 | { | 129 | { |
196 | int ret = -EBADF; | 130 | int ret = -EBADF; |
197 | struct file * file = fget(fildes); | 131 | struct file *file = fget(fildes); |
198 | 132 | ||
199 | if (file) | 133 | if (file) { |
200 | ret = dupfd(file, 0, 0); | 134 | ret = get_unused_fd(); |
135 | if (ret >= 0) | ||
136 | fd_install(ret, file); | ||
137 | else | ||
138 | fput(file); | ||
139 | } | ||
201 | return ret; | 140 | return ret; |
202 | } | 141 | } |
203 | 142 | ||
@@ -322,8 +261,11 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, | |||
322 | case F_DUPFD_CLOEXEC: | 261 | case F_DUPFD_CLOEXEC: |
323 | if (arg >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) | 262 | if (arg >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) |
324 | break; | 263 | break; |
325 | get_file(filp); | 264 | err = alloc_fd(arg, cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0); |
326 | err = dupfd(filp, arg, cmd == F_DUPFD_CLOEXEC); | 265 | if (err >= 0) { |
266 | get_file(filp); | ||
267 | fd_install(err, filp); | ||
268 | } | ||
327 | break; | 269 | break; |
328 | case F_GETFD: | 270 | case F_GETFD: |
329 | err = get_close_on_exec(fd) ? FD_CLOEXEC : 0; | 271 | err = get_close_on_exec(fd) ? FD_CLOEXEC : 0; |
@@ -6,6 +6,7 @@ | |||
6 | * Manage the dynamic fd arrays in the process files_struct. | 6 | * Manage the dynamic fd arrays in the process files_struct. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/module.h> | ||
9 | #include <linux/fs.h> | 10 | #include <linux/fs.h> |
10 | #include <linux/mm.h> | 11 | #include <linux/mm.h> |
11 | #include <linux/time.h> | 12 | #include <linux/time.h> |
@@ -432,3 +433,63 @@ struct files_struct init_files = { | |||
432 | }, | 433 | }, |
433 | .file_lock = __SPIN_LOCK_UNLOCKED(init_task.file_lock), | 434 | .file_lock = __SPIN_LOCK_UNLOCKED(init_task.file_lock), |
434 | }; | 435 | }; |
436 | |||
437 | /* | ||
438 | * allocate a file descriptor, mark it busy. | ||
439 | */ | ||
440 | int alloc_fd(unsigned start, unsigned flags) | ||
441 | { | ||
442 | struct files_struct *files = current->files; | ||
443 | unsigned int fd; | ||
444 | int error; | ||
445 | struct fdtable *fdt; | ||
446 | |||
447 | spin_lock(&files->file_lock); | ||
448 | repeat: | ||
449 | fdt = files_fdtable(files); | ||
450 | fd = start; | ||
451 | if (fd < files->next_fd) | ||
452 | fd = files->next_fd; | ||
453 | |||
454 | if (fd < fdt->max_fds) | ||
455 | fd = find_next_zero_bit(fdt->open_fds->fds_bits, | ||
456 | fdt->max_fds, fd); | ||
457 | |||
458 | error = expand_files(files, fd); | ||
459 | if (error < 0) | ||
460 | goto out; | ||
461 | |||
462 | /* | ||
463 | * If we needed to expand the fs array we | ||
464 | * might have blocked - try again. | ||
465 | */ | ||
466 | if (error) | ||
467 | goto repeat; | ||
468 | |||
469 | if (start <= files->next_fd) | ||
470 | files->next_fd = fd + 1; | ||
471 | |||
472 | FD_SET(fd, fdt->open_fds); | ||
473 | if (flags & O_CLOEXEC) | ||
474 | FD_SET(fd, fdt->close_on_exec); | ||
475 | else | ||
476 | FD_CLR(fd, fdt->close_on_exec); | ||
477 | error = fd; | ||
478 | #if 1 | ||
479 | /* Sanity check */ | ||
480 | if (rcu_dereference(fdt->fd[fd]) != NULL) { | ||
481 | printk(KERN_WARNING "alloc_fd: slot %d not NULL!\n", fd); | ||
482 | rcu_assign_pointer(fdt->fd[fd], NULL); | ||
483 | } | ||
484 | #endif | ||
485 | |||
486 | out: | ||
487 | spin_unlock(&files->file_lock); | ||
488 | return error; | ||
489 | } | ||
490 | |||
491 | int get_unused_fd(void) | ||
492 | { | ||
493 | return alloc_fd(0, 0); | ||
494 | } | ||
495 | EXPORT_SYMBOL(get_unused_fd); | ||
diff --git a/fs/namei.c b/fs/namei.c index a7b0a0b80128..4ea63ed5e791 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -274,7 +274,7 @@ int inode_permission(struct inode *inode, int mask) | |||
274 | return retval; | 274 | return retval; |
275 | 275 | ||
276 | return security_inode_permission(inode, | 276 | return security_inode_permission(inode, |
277 | mask & (MAY_READ|MAY_WRITE|MAY_EXEC)); | 277 | mask & (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND)); |
278 | } | 278 | } |
279 | 279 | ||
280 | /** | 280 | /** |
@@ -1431,8 +1431,7 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir) | |||
1431 | * 3. We should have write and exec permissions on dir | 1431 | * 3. We should have write and exec permissions on dir |
1432 | * 4. We can't do it if dir is immutable (done in permission()) | 1432 | * 4. We can't do it if dir is immutable (done in permission()) |
1433 | */ | 1433 | */ |
1434 | static inline int may_create(struct inode *dir, struct dentry *child, | 1434 | static inline int may_create(struct inode *dir, struct dentry *child) |
1435 | struct nameidata *nd) | ||
1436 | { | 1435 | { |
1437 | if (child->d_inode) | 1436 | if (child->d_inode) |
1438 | return -EEXIST; | 1437 | return -EEXIST; |
@@ -1504,7 +1503,7 @@ void unlock_rename(struct dentry *p1, struct dentry *p2) | |||
1504 | int vfs_create(struct inode *dir, struct dentry *dentry, int mode, | 1503 | int vfs_create(struct inode *dir, struct dentry *dentry, int mode, |
1505 | struct nameidata *nd) | 1504 | struct nameidata *nd) |
1506 | { | 1505 | { |
1507 | int error = may_create(dir, dentry, nd); | 1506 | int error = may_create(dir, dentry); |
1508 | 1507 | ||
1509 | if (error) | 1508 | if (error) |
1510 | return error; | 1509 | return error; |
@@ -1948,7 +1947,7 @@ EXPORT_SYMBOL_GPL(lookup_create); | |||
1948 | 1947 | ||
1949 | int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) | 1948 | int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) |
1950 | { | 1949 | { |
1951 | int error = may_create(dir, dentry, NULL); | 1950 | int error = may_create(dir, dentry); |
1952 | 1951 | ||
1953 | if (error) | 1952 | if (error) |
1954 | return error; | 1953 | return error; |
@@ -2049,7 +2048,7 @@ asmlinkage long sys_mknod(const char __user *filename, int mode, unsigned dev) | |||
2049 | 2048 | ||
2050 | int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | 2049 | int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) |
2051 | { | 2050 | { |
2052 | int error = may_create(dir, dentry, NULL); | 2051 | int error = may_create(dir, dentry); |
2053 | 2052 | ||
2054 | if (error) | 2053 | if (error) |
2055 | return error; | 2054 | return error; |
@@ -2316,7 +2315,7 @@ asmlinkage long sys_unlink(const char __user *pathname) | |||
2316 | 2315 | ||
2317 | int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname) | 2316 | int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname) |
2318 | { | 2317 | { |
2319 | int error = may_create(dir, dentry, NULL); | 2318 | int error = may_create(dir, dentry); |
2320 | 2319 | ||
2321 | if (error) | 2320 | if (error) |
2322 | return error; | 2321 | return error; |
@@ -2386,7 +2385,7 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de | |||
2386 | if (!inode) | 2385 | if (!inode) |
2387 | return -ENOENT; | 2386 | return -ENOENT; |
2388 | 2387 | ||
2389 | error = may_create(dir, new_dentry, NULL); | 2388 | error = may_create(dir, new_dentry); |
2390 | if (error) | 2389 | if (error) |
2391 | return error; | 2390 | return error; |
2392 | 2391 | ||
@@ -2595,7 +2594,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
2595 | return error; | 2594 | return error; |
2596 | 2595 | ||
2597 | if (!new_dentry->d_inode) | 2596 | if (!new_dentry->d_inode) |
2598 | error = may_create(new_dir, new_dentry, NULL); | 2597 | error = may_create(new_dir, new_dentry); |
2599 | else | 2598 | else |
2600 | error = may_delete(new_dir, new_dentry, is_dir); | 2599 | error = may_delete(new_dir, new_dentry, is_dir); |
2601 | if (error) | 2600 | if (error) |
diff --git a/fs/namespace.c b/fs/namespace.c index 411728c0c8bb..6e283c93b50d 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -1667,31 +1667,31 @@ static noinline int do_new_mount(struct nameidata *nd, char *type, int flags, | |||
1667 | if (IS_ERR(mnt)) | 1667 | if (IS_ERR(mnt)) |
1668 | return PTR_ERR(mnt); | 1668 | return PTR_ERR(mnt); |
1669 | 1669 | ||
1670 | return do_add_mount(mnt, nd, mnt_flags, NULL); | 1670 | return do_add_mount(mnt, &nd->path, mnt_flags, NULL); |
1671 | } | 1671 | } |
1672 | 1672 | ||
1673 | /* | 1673 | /* |
1674 | * add a mount into a namespace's mount tree | 1674 | * add a mount into a namespace's mount tree |
1675 | * - provide the option of adding the new mount to an expiration list | 1675 | * - provide the option of adding the new mount to an expiration list |
1676 | */ | 1676 | */ |
1677 | int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd, | 1677 | int do_add_mount(struct vfsmount *newmnt, struct path *path, |
1678 | int mnt_flags, struct list_head *fslist) | 1678 | int mnt_flags, struct list_head *fslist) |
1679 | { | 1679 | { |
1680 | int err; | 1680 | int err; |
1681 | 1681 | ||
1682 | down_write(&namespace_sem); | 1682 | down_write(&namespace_sem); |
1683 | /* Something was mounted here while we slept */ | 1683 | /* Something was mounted here while we slept */ |
1684 | while (d_mountpoint(nd->path.dentry) && | 1684 | while (d_mountpoint(path->dentry) && |
1685 | follow_down(&nd->path.mnt, &nd->path.dentry)) | 1685 | follow_down(&path->mnt, &path->dentry)) |
1686 | ; | 1686 | ; |
1687 | err = -EINVAL; | 1687 | err = -EINVAL; |
1688 | if (!check_mnt(nd->path.mnt)) | 1688 | if (!check_mnt(path->mnt)) |
1689 | goto unlock; | 1689 | goto unlock; |
1690 | 1690 | ||
1691 | /* Refuse the same filesystem on the same mount point */ | 1691 | /* Refuse the same filesystem on the same mount point */ |
1692 | err = -EBUSY; | 1692 | err = -EBUSY; |
1693 | if (nd->path.mnt->mnt_sb == newmnt->mnt_sb && | 1693 | if (path->mnt->mnt_sb == newmnt->mnt_sb && |
1694 | nd->path.mnt->mnt_root == nd->path.dentry) | 1694 | path->mnt->mnt_root == path->dentry) |
1695 | goto unlock; | 1695 | goto unlock; |
1696 | 1696 | ||
1697 | err = -EINVAL; | 1697 | err = -EINVAL; |
@@ -1699,7 +1699,7 @@ int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd, | |||
1699 | goto unlock; | 1699 | goto unlock; |
1700 | 1700 | ||
1701 | newmnt->mnt_flags = mnt_flags; | 1701 | newmnt->mnt_flags = mnt_flags; |
1702 | if ((err = graft_tree(newmnt, &nd->path))) | 1702 | if ((err = graft_tree(newmnt, path))) |
1703 | goto unlock; | 1703 | goto unlock; |
1704 | 1704 | ||
1705 | if (fslist) /* add to the specified expiration list */ | 1705 | if (fslist) /* add to the specified expiration list */ |
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index 2f285ef76399..66df08dd1caf 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c | |||
@@ -129,7 +129,7 @@ static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) | |||
129 | goto out_err; | 129 | goto out_err; |
130 | 130 | ||
131 | mntget(mnt); | 131 | mntget(mnt); |
132 | err = do_add_mount(mnt, nd, nd->path.mnt->mnt_flags|MNT_SHRINKABLE, | 132 | err = do_add_mount(mnt, &nd->path, nd->path.mnt->mnt_flags|MNT_SHRINKABLE, |
133 | &nfs_automount_list); | 133 | &nfs_automount_list); |
134 | if (err < 0) { | 134 | if (err < 0) { |
135 | mntput(mnt); | 135 | mntput(mnt); |
@@ -963,62 +963,6 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) | |||
963 | } | 963 | } |
964 | EXPORT_SYMBOL(dentry_open); | 964 | EXPORT_SYMBOL(dentry_open); |
965 | 965 | ||
966 | /* | ||
967 | * Find an empty file descriptor entry, and mark it busy. | ||
968 | */ | ||
969 | int get_unused_fd_flags(int flags) | ||
970 | { | ||
971 | struct files_struct * files = current->files; | ||
972 | int fd, error; | ||
973 | struct fdtable *fdt; | ||
974 | |||
975 | spin_lock(&files->file_lock); | ||
976 | |||
977 | repeat: | ||
978 | fdt = files_fdtable(files); | ||
979 | fd = find_next_zero_bit(fdt->open_fds->fds_bits, fdt->max_fds, | ||
980 | files->next_fd); | ||
981 | |||
982 | /* Do we need to expand the fd array or fd set? */ | ||
983 | error = expand_files(files, fd); | ||
984 | if (error < 0) | ||
985 | goto out; | ||
986 | |||
987 | if (error) { | ||
988 | /* | ||
989 | * If we needed to expand the fs array we | ||
990 | * might have blocked - try again. | ||
991 | */ | ||
992 | goto repeat; | ||
993 | } | ||
994 | |||
995 | FD_SET(fd, fdt->open_fds); | ||
996 | if (flags & O_CLOEXEC) | ||
997 | FD_SET(fd, fdt->close_on_exec); | ||
998 | else | ||
999 | FD_CLR(fd, fdt->close_on_exec); | ||
1000 | files->next_fd = fd + 1; | ||
1001 | #if 1 | ||
1002 | /* Sanity check */ | ||
1003 | if (fdt->fd[fd] != NULL) { | ||
1004 | printk(KERN_WARNING "get_unused_fd: slot %d not NULL!\n", fd); | ||
1005 | fdt->fd[fd] = NULL; | ||
1006 | } | ||
1007 | #endif | ||
1008 | error = fd; | ||
1009 | |||
1010 | out: | ||
1011 | spin_unlock(&files->file_lock); | ||
1012 | return error; | ||
1013 | } | ||
1014 | |||
1015 | int get_unused_fd(void) | ||
1016 | { | ||
1017 | return get_unused_fd_flags(0); | ||
1018 | } | ||
1019 | |||
1020 | EXPORT_SYMBOL(get_unused_fd); | ||
1021 | |||
1022 | static void __put_unused_fd(struct files_struct *files, unsigned int fd) | 966 | static void __put_unused_fd(struct files_struct *files, unsigned int fd) |
1023 | { | 967 | { |
1024 | struct fdtable *fdt = files_fdtable(files); | 968 | struct fdtable *fdt = files_fdtable(files); |
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index cb4096cc3fb7..4fb81e9c94e3 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
@@ -300,10 +300,10 @@ out: | |||
300 | return rtn; | 300 | return rtn; |
301 | } | 301 | } |
302 | 302 | ||
303 | static DEFINE_IDR(proc_inum_idr); | 303 | static DEFINE_IDA(proc_inum_ida); |
304 | static DEFINE_SPINLOCK(proc_inum_lock); /* protects the above */ | 304 | static DEFINE_SPINLOCK(proc_inum_lock); /* protects the above */ |
305 | 305 | ||
306 | #define PROC_DYNAMIC_FIRST 0xF0000000UL | 306 | #define PROC_DYNAMIC_FIRST 0xF0000000U |
307 | 307 | ||
308 | /* | 308 | /* |
309 | * Return an inode number between PROC_DYNAMIC_FIRST and | 309 | * Return an inode number between PROC_DYNAMIC_FIRST and |
@@ -311,36 +311,33 @@ static DEFINE_SPINLOCK(proc_inum_lock); /* protects the above */ | |||
311 | */ | 311 | */ |
312 | static unsigned int get_inode_number(void) | 312 | static unsigned int get_inode_number(void) |
313 | { | 313 | { |
314 | int i, inum = 0; | 314 | unsigned int i; |
315 | int error; | 315 | int error; |
316 | 316 | ||
317 | retry: | 317 | retry: |
318 | if (idr_pre_get(&proc_inum_idr, GFP_KERNEL) == 0) | 318 | if (ida_pre_get(&proc_inum_ida, GFP_KERNEL) == 0) |
319 | return 0; | 319 | return 0; |
320 | 320 | ||
321 | spin_lock(&proc_inum_lock); | 321 | spin_lock(&proc_inum_lock); |
322 | error = idr_get_new(&proc_inum_idr, NULL, &i); | 322 | error = ida_get_new(&proc_inum_ida, &i); |
323 | spin_unlock(&proc_inum_lock); | 323 | spin_unlock(&proc_inum_lock); |
324 | if (error == -EAGAIN) | 324 | if (error == -EAGAIN) |
325 | goto retry; | 325 | goto retry; |
326 | else if (error) | 326 | else if (error) |
327 | return 0; | 327 | return 0; |
328 | 328 | ||
329 | inum = (i & MAX_ID_MASK) + PROC_DYNAMIC_FIRST; | 329 | if (i > UINT_MAX - PROC_DYNAMIC_FIRST) { |
330 | 330 | spin_lock(&proc_inum_lock); | |
331 | /* inum will never be more than 0xf0ffffff, so no check | 331 | ida_remove(&proc_inum_ida, i); |
332 | * for overflow. | 332 | spin_unlock(&proc_inum_lock); |
333 | */ | 333 | } |
334 | 334 | return PROC_DYNAMIC_FIRST + i; | |
335 | return inum; | ||
336 | } | 335 | } |
337 | 336 | ||
338 | static void release_inode_number(unsigned int inum) | 337 | static void release_inode_number(unsigned int inum) |
339 | { | 338 | { |
340 | int id = (inum - PROC_DYNAMIC_FIRST) | ~MAX_ID_MASK; | ||
341 | |||
342 | spin_lock(&proc_inum_lock); | 339 | spin_lock(&proc_inum_lock); |
343 | idr_remove(&proc_inum_idr, id); | 340 | ida_remove(&proc_inum_ida, inum - PROC_DYNAMIC_FIRST); |
344 | spin_unlock(&proc_inum_lock); | 341 | spin_unlock(&proc_inum_lock); |
345 | } | 342 | } |
346 | 343 | ||
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 879e54d35c2d..282a13596c70 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c | |||
@@ -2076,8 +2076,8 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id, | |||
2076 | return err; | 2076 | return err; |
2077 | /* Quotafile not on the same filesystem? */ | 2077 | /* Quotafile not on the same filesystem? */ |
2078 | if (nd.path.mnt->mnt_sb != sb) { | 2078 | if (nd.path.mnt->mnt_sb != sb) { |
2079 | path_put(&nd.path); | 2079 | err = -EXDEV; |
2080 | return -EXDEV; | 2080 | goto out; |
2081 | } | 2081 | } |
2082 | inode = nd.path.dentry->d_inode; | 2082 | inode = nd.path.dentry->d_inode; |
2083 | /* We must not pack tails for quota files on reiserfs for quota IO to work */ | 2083 | /* We must not pack tails for quota files on reiserfs for quota IO to work */ |
@@ -2087,8 +2087,8 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id, | |||
2087 | reiserfs_warning(sb, | 2087 | reiserfs_warning(sb, |
2088 | "reiserfs: Unpacking tail of quota file failed" | 2088 | "reiserfs: Unpacking tail of quota file failed" |
2089 | " (%d). Cannot turn on quotas.", err); | 2089 | " (%d). Cannot turn on quotas.", err); |
2090 | path_put(&nd.path); | 2090 | err = -EINVAL; |
2091 | return -EINVAL; | 2091 | goto out; |
2092 | } | 2092 | } |
2093 | mark_inode_dirty(inode); | 2093 | mark_inode_dirty(inode); |
2094 | } | 2094 | } |
@@ -2109,13 +2109,15 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id, | |||
2109 | /* Just start temporary transaction and finish it */ | 2109 | /* Just start temporary transaction and finish it */ |
2110 | err = journal_begin(&th, sb, 1); | 2110 | err = journal_begin(&th, sb, 1); |
2111 | if (err) | 2111 | if (err) |
2112 | return err; | 2112 | goto out; |
2113 | err = journal_end_sync(&th, sb, 1); | 2113 | err = journal_end_sync(&th, sb, 1); |
2114 | if (err) | 2114 | if (err) |
2115 | return err; | 2115 | goto out; |
2116 | } | 2116 | } |
2117 | err = vfs_quota_on_path(sb, type, format_id, &nd.path); | ||
2118 | out: | ||
2117 | path_put(&nd.path); | 2119 | path_put(&nd.path); |
2118 | return vfs_quota_on(sb, type, format_id, path, 0); | 2120 | return err; |
2119 | } | 2121 | } |
2120 | 2122 | ||
2121 | /* Read data from quotafile - avoid pagecache and such because we cannot afford | 2123 | /* Read data from quotafile - avoid pagecache and such because we cannot afford |
diff --git a/include/linux/file.h b/include/linux/file.h index 27c64bdc68c9..a20259e248a5 100644 --- a/include/linux/file.h +++ b/include/linux/file.h | |||
@@ -34,8 +34,9 @@ extern struct file *fget(unsigned int fd); | |||
34 | extern struct file *fget_light(unsigned int fd, int *fput_needed); | 34 | extern struct file *fget_light(unsigned int fd, int *fput_needed); |
35 | extern void set_close_on_exec(unsigned int fd, int flag); | 35 | extern void set_close_on_exec(unsigned int fd, int flag); |
36 | extern void put_filp(struct file *); | 36 | extern void put_filp(struct file *); |
37 | extern int alloc_fd(unsigned start, unsigned flags); | ||
37 | extern int get_unused_fd(void); | 38 | extern int get_unused_fd(void); |
38 | extern int get_unused_fd_flags(int flags); | 39 | #define get_unused_fd_flags(flags) alloc_fd(0, (flags)) |
39 | extern void put_unused_fd(unsigned int fd); | 40 | extern void put_unused_fd(unsigned int fd); |
40 | 41 | ||
41 | extern void fd_install(unsigned int fd, struct file *file); | 42 | extern void fd_install(unsigned int fd, struct file *file); |
diff --git a/include/linux/mount.h b/include/linux/mount.h index b5efaa2132ab..30a1d63b6fb5 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h | |||
@@ -105,7 +105,8 @@ extern struct vfsmount *vfs_kern_mount(struct file_system_type *type, | |||
105 | 105 | ||
106 | struct nameidata; | 106 | struct nameidata; |
107 | 107 | ||
108 | extern int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd, | 108 | struct path; |
109 | extern int do_add_mount(struct vfsmount *newmnt, struct path *path, | ||
109 | int mnt_flags, struct list_head *fslist); | 110 | int mnt_flags, struct list_head *fslist); |
110 | 111 | ||
111 | extern void mark_mounts_for_expiry(struct list_head *mounts); | 112 | extern void mark_mounts_for_expiry(struct list_head *mounts); |
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index 742187f7a05c..ca6b9b5c8d52 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h | |||
@@ -43,6 +43,8 @@ int dquot_mark_dquot_dirty(struct dquot *dquot); | |||
43 | 43 | ||
44 | int vfs_quota_on(struct super_block *sb, int type, int format_id, | 44 | int vfs_quota_on(struct super_block *sb, int type, int format_id, |
45 | char *path, int remount); | 45 | char *path, int remount); |
46 | int vfs_quota_on_path(struct super_block *sb, int type, int format_id, | ||
47 | struct path *path); | ||
46 | int vfs_quota_on_mount(struct super_block *sb, char *qf_name, | 48 | int vfs_quota_on_mount(struct super_block *sb, char *qf_name, |
47 | int format_id, int type); | 49 | int format_id, int type); |
48 | int vfs_quota_off(struct super_block *sb, int type, int remount); | 50 | int vfs_quota_off(struct super_block *sb, int type, int remount); |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 380d6474cf66..a72a5ad46ec5 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -3216,6 +3216,7 @@ int __init ip_rt_init(void) | |||
3216 | return rc; | 3216 | return rc; |
3217 | } | 3217 | } |
3218 | 3218 | ||
3219 | #ifdef CONFIG_SYSCTL | ||
3219 | /* | 3220 | /* |
3220 | * We really need to sanitize the damn ipv4 init order, then all | 3221 | * We really need to sanitize the damn ipv4 init order, then all |
3221 | * this nonsense will go away. | 3222 | * this nonsense will go away. |
@@ -3224,6 +3225,7 @@ void __init ip_static_sysctl_init(void) | |||
3224 | { | 3225 | { |
3225 | register_sysctl_paths(ipv4_route_path, ipv4_route_table); | 3226 | register_sysctl_paths(ipv4_route_path, ipv4_route_table); |
3226 | } | 3227 | } |
3228 | #endif | ||
3227 | 3229 | ||
3228 | EXPORT_SYMBOL(__ip_select_ident); | 3230 | EXPORT_SYMBOL(__ip_select_ident); |
3229 | EXPORT_SYMBOL(ip_route_input); | 3231 | EXPORT_SYMBOL(ip_route_input); |