diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/afs/mntpt.c | 2 | ||||
-rw-r--r-- | fs/block_dev.c | 5 | ||||
-rw-r--r-- | fs/buffer.c | 2 | ||||
-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/jffs2/summary.c | 40 | ||||
-rw-r--r-- | fs/jffs2/summary.h | 6 | ||||
-rw-r--r-- | fs/libfs.c | 4 | ||||
-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/omfs/bitmap.c | 6 | ||||
-rw-r--r-- | fs/omfs/dir.c | 2 | ||||
-rw-r--r-- | fs/omfs/file.c | 6 | ||||
-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-- | fs/romfs/inode.c | 37 |
23 files changed, 243 insertions, 259 deletions
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/buffer.c b/fs/buffer.c index ca12a6bb82b1..4dbe52948e8f 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -580,7 +580,7 @@ EXPORT_SYMBOL(mark_buffer_async_write); | |||
580 | /* | 580 | /* |
581 | * The buffer's backing address_space's private_lock must be held | 581 | * The buffer's backing address_space's private_lock must be held |
582 | */ | 582 | */ |
583 | static inline void __remove_assoc_queue(struct buffer_head *bh) | 583 | static void __remove_assoc_queue(struct buffer_head *bh) |
584 | { | 584 | { |
585 | list_del_init(&bh->b_assoc_buffers); | 585 | list_del_init(&bh->b_assoc_buffers); |
586 | WARN_ON(!bh->b_assoc_map); | 586 | WARN_ON(!bh->b_assoc_map); |
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/jffs2/summary.c b/fs/jffs2/summary.c index 629af01e5ade..6caf1e1ee26d 100644 --- a/fs/jffs2/summary.c +++ b/fs/jffs2/summary.c | |||
@@ -23,6 +23,8 @@ | |||
23 | 23 | ||
24 | int jffs2_sum_init(struct jffs2_sb_info *c) | 24 | int jffs2_sum_init(struct jffs2_sb_info *c) |
25 | { | 25 | { |
26 | uint32_t sum_size = max_t(uint32_t, c->sector_size, MAX_SUMMARY_SIZE); | ||
27 | |||
26 | c->summary = kzalloc(sizeof(struct jffs2_summary), GFP_KERNEL); | 28 | c->summary = kzalloc(sizeof(struct jffs2_summary), GFP_KERNEL); |
27 | 29 | ||
28 | if (!c->summary) { | 30 | if (!c->summary) { |
@@ -30,7 +32,7 @@ int jffs2_sum_init(struct jffs2_sb_info *c) | |||
30 | return -ENOMEM; | 32 | return -ENOMEM; |
31 | } | 33 | } |
32 | 34 | ||
33 | c->summary->sum_buf = vmalloc(c->sector_size); | 35 | c->summary->sum_buf = kmalloc(sum_size, GFP_KERNEL); |
34 | 36 | ||
35 | if (!c->summary->sum_buf) { | 37 | if (!c->summary->sum_buf) { |
36 | JFFS2_WARNING("Can't allocate buffer for writing out summary information!\n"); | 38 | JFFS2_WARNING("Can't allocate buffer for writing out summary information!\n"); |
@@ -49,7 +51,7 @@ void jffs2_sum_exit(struct jffs2_sb_info *c) | |||
49 | 51 | ||
50 | jffs2_sum_disable_collecting(c->summary); | 52 | jffs2_sum_disable_collecting(c->summary); |
51 | 53 | ||
52 | vfree(c->summary->sum_buf); | 54 | kfree(c->summary->sum_buf); |
53 | c->summary->sum_buf = NULL; | 55 | c->summary->sum_buf = NULL; |
54 | 56 | ||
55 | kfree(c->summary); | 57 | kfree(c->summary); |
@@ -665,7 +667,7 @@ crc_err: | |||
665 | /* Write summary data to flash - helper function for jffs2_sum_write_sumnode() */ | 667 | /* Write summary data to flash - helper function for jffs2_sum_write_sumnode() */ |
666 | 668 | ||
667 | static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | 669 | static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, |
668 | uint32_t infosize, uint32_t datasize, int padsize) | 670 | uint32_t infosize, uint32_t datasize, int padsize) |
669 | { | 671 | { |
670 | struct jffs2_raw_summary isum; | 672 | struct jffs2_raw_summary isum; |
671 | union jffs2_sum_mem *temp; | 673 | union jffs2_sum_mem *temp; |
@@ -676,6 +678,26 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock | |||
676 | int ret; | 678 | int ret; |
677 | size_t retlen; | 679 | size_t retlen; |
678 | 680 | ||
681 | if (padsize + datasize > MAX_SUMMARY_SIZE) { | ||
682 | /* It won't fit in the buffer. Abort summary for this jeb */ | ||
683 | jffs2_sum_disable_collecting(c->summary); | ||
684 | |||
685 | JFFS2_WARNING("Summary too big (%d data, %d pad) in eraseblock at %08x\n", | ||
686 | datasize, padsize, jeb->offset); | ||
687 | /* Non-fatal */ | ||
688 | return 0; | ||
689 | } | ||
690 | /* Is there enough space for summary? */ | ||
691 | if (padsize < 0) { | ||
692 | /* don't try to write out summary for this jeb */ | ||
693 | jffs2_sum_disable_collecting(c->summary); | ||
694 | |||
695 | JFFS2_WARNING("Not enough space for summary, padsize = %d\n", | ||
696 | padsize); | ||
697 | /* Non-fatal */ | ||
698 | return 0; | ||
699 | } | ||
700 | |||
679 | memset(c->summary->sum_buf, 0xff, datasize); | 701 | memset(c->summary->sum_buf, 0xff, datasize); |
680 | memset(&isum, 0, sizeof(isum)); | 702 | memset(&isum, 0, sizeof(isum)); |
681 | 703 | ||
@@ -821,7 +843,7 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) | |||
821 | { | 843 | { |
822 | int datasize, infosize, padsize; | 844 | int datasize, infosize, padsize; |
823 | struct jffs2_eraseblock *jeb; | 845 | struct jffs2_eraseblock *jeb; |
824 | int ret; | 846 | int ret = 0; |
825 | 847 | ||
826 | dbg_summary("called\n"); | 848 | dbg_summary("called\n"); |
827 | 849 | ||
@@ -841,16 +863,6 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) | |||
841 | infosize += padsize; | 863 | infosize += padsize; |
842 | datasize += padsize; | 864 | datasize += padsize; |
843 | 865 | ||
844 | /* Is there enough space for summary? */ | ||
845 | if (padsize < 0) { | ||
846 | /* don't try to write out summary for this jeb */ | ||
847 | jffs2_sum_disable_collecting(c->summary); | ||
848 | |||
849 | JFFS2_WARNING("Not enough space for summary, padsize = %d\n", padsize); | ||
850 | spin_lock(&c->erase_completion_lock); | ||
851 | return 0; | ||
852 | } | ||
853 | |||
854 | ret = jffs2_sum_write_data(c, jeb, infosize, datasize, padsize); | 866 | ret = jffs2_sum_write_data(c, jeb, infosize, datasize, padsize); |
855 | spin_lock(&c->erase_completion_lock); | 867 | spin_lock(&c->erase_completion_lock); |
856 | return ret; | 868 | return ret; |
diff --git a/fs/jffs2/summary.h b/fs/jffs2/summary.h index 8bf34f2fa5ce..60207a2ae952 100644 --- a/fs/jffs2/summary.h +++ b/fs/jffs2/summary.h | |||
@@ -13,6 +13,12 @@ | |||
13 | #ifndef JFFS2_SUMMARY_H | 13 | #ifndef JFFS2_SUMMARY_H |
14 | #define JFFS2_SUMMARY_H | 14 | #define JFFS2_SUMMARY_H |
15 | 15 | ||
16 | /* Limit summary size to 64KiB so that we can kmalloc it. If the summary | ||
17 | is larger than that, we have to just ditch it and avoid using summary | ||
18 | for the eraseblock in question... and it probably doesn't hurt us much | ||
19 | anyway. */ | ||
20 | #define MAX_SUMMARY_SIZE 65536 | ||
21 | |||
16 | #include <linux/uio.h> | 22 | #include <linux/uio.h> |
17 | #include <linux/jffs2.h> | 23 | #include <linux/jffs2.h> |
18 | 24 | ||
diff --git a/fs/libfs.c b/fs/libfs.c index baeb71ee1cde..1add676a19df 100644 --- a/fs/libfs.c +++ b/fs/libfs.c | |||
@@ -216,8 +216,8 @@ int get_sb_pseudo(struct file_system_type *fs_type, char *name, | |||
216 | 216 | ||
217 | s->s_flags = MS_NOUSER; | 217 | s->s_flags = MS_NOUSER; |
218 | s->s_maxbytes = ~0ULL; | 218 | s->s_maxbytes = ~0ULL; |
219 | s->s_blocksize = 1024; | 219 | s->s_blocksize = PAGE_SIZE; |
220 | s->s_blocksize_bits = 10; | 220 | s->s_blocksize_bits = PAGE_SHIFT; |
221 | s->s_magic = magic; | 221 | s->s_magic = magic; |
222 | s->s_op = ops ? ops : &simple_super_operations; | 222 | s->s_op = ops ? ops : &simple_super_operations; |
223 | s->s_time_gran = 1; | 223 | s->s_time_gran = 1; |
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); |
diff --git a/fs/omfs/bitmap.c b/fs/omfs/bitmap.c index dc75f22be3f2..697663b01bae 100644 --- a/fs/omfs/bitmap.c +++ b/fs/omfs/bitmap.c | |||
@@ -71,10 +71,10 @@ static int set_run(struct super_block *sb, int map, | |||
71 | } | 71 | } |
72 | if (set) { | 72 | if (set) { |
73 | set_bit(bit, sbi->s_imap[map]); | 73 | set_bit(bit, sbi->s_imap[map]); |
74 | set_bit(bit, (long *) bh->b_data); | 74 | set_bit(bit, (unsigned long *)bh->b_data); |
75 | } else { | 75 | } else { |
76 | clear_bit(bit, sbi->s_imap[map]); | 76 | clear_bit(bit, sbi->s_imap[map]); |
77 | clear_bit(bit, (long *) bh->b_data); | 77 | clear_bit(bit, (unsigned long *)bh->b_data); |
78 | } | 78 | } |
79 | } | 79 | } |
80 | mark_buffer_dirty(bh); | 80 | mark_buffer_dirty(bh); |
@@ -109,7 +109,7 @@ int omfs_allocate_block(struct super_block *sb, u64 block) | |||
109 | if (!bh) | 109 | if (!bh) |
110 | goto out; | 110 | goto out; |
111 | 111 | ||
112 | set_bit(bit, (long *) bh->b_data); | 112 | set_bit(bit, (unsigned long *)bh->b_data); |
113 | mark_buffer_dirty(bh); | 113 | mark_buffer_dirty(bh); |
114 | brelse(bh); | 114 | brelse(bh); |
115 | } | 115 | } |
diff --git a/fs/omfs/dir.c b/fs/omfs/dir.c index 05a5bc31e4bd..c0757e998876 100644 --- a/fs/omfs/dir.c +++ b/fs/omfs/dir.c | |||
@@ -104,7 +104,7 @@ int omfs_make_empty(struct inode *inode, struct super_block *sb) | |||
104 | 104 | ||
105 | oi = (struct omfs_inode *) bh->b_data; | 105 | oi = (struct omfs_inode *) bh->b_data; |
106 | oi->i_head.h_self = cpu_to_be64(inode->i_ino); | 106 | oi->i_head.h_self = cpu_to_be64(inode->i_ino); |
107 | oi->i_sibling = ~0ULL; | 107 | oi->i_sibling = ~cpu_to_be64(0ULL); |
108 | 108 | ||
109 | mark_buffer_dirty(bh); | 109 | mark_buffer_dirty(bh); |
110 | brelse(bh); | 110 | brelse(bh); |
diff --git a/fs/omfs/file.c b/fs/omfs/file.c index 66e01fae4384..7e2499053e4d 100644 --- a/fs/omfs/file.c +++ b/fs/omfs/file.c | |||
@@ -30,11 +30,11 @@ void omfs_make_empty_table(struct buffer_head *bh, int offset) | |||
30 | { | 30 | { |
31 | struct omfs_extent *oe = (struct omfs_extent *) &bh->b_data[offset]; | 31 | struct omfs_extent *oe = (struct omfs_extent *) &bh->b_data[offset]; |
32 | 32 | ||
33 | oe->e_next = ~0ULL; | 33 | oe->e_next = ~cpu_to_be64(0ULL); |
34 | oe->e_extent_count = cpu_to_be32(1), | 34 | oe->e_extent_count = cpu_to_be32(1), |
35 | oe->e_fill = cpu_to_be32(0x22), | 35 | oe->e_fill = cpu_to_be32(0x22), |
36 | oe->e_entry.e_cluster = ~0ULL; | 36 | oe->e_entry.e_cluster = ~cpu_to_be64(0ULL); |
37 | oe->e_entry.e_blocks = ~0ULL; | 37 | oe->e_entry.e_blocks = ~cpu_to_be64(0ULL); |
38 | } | 38 | } |
39 | 39 | ||
40 | int omfs_shrink_inode(struct inode *inode) | 40 | int omfs_shrink_inode(struct inode *inode) |
@@ -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/fs/romfs/inode.c b/fs/romfs/inode.c index 8e51a2aaa977..60d2f822e87b 100644 --- a/fs/romfs/inode.c +++ b/fs/romfs/inode.c | |||
@@ -418,7 +418,8 @@ static int | |||
418 | romfs_readpage(struct file *file, struct page * page) | 418 | romfs_readpage(struct file *file, struct page * page) |
419 | { | 419 | { |
420 | struct inode *inode = page->mapping->host; | 420 | struct inode *inode = page->mapping->host; |
421 | loff_t offset, avail, readlen; | 421 | loff_t offset, size; |
422 | unsigned long filled; | ||
422 | void *buf; | 423 | void *buf; |
423 | int result = -EIO; | 424 | int result = -EIO; |
424 | 425 | ||
@@ -430,21 +431,29 @@ romfs_readpage(struct file *file, struct page * page) | |||
430 | 431 | ||
431 | /* 32 bit warning -- but not for us :) */ | 432 | /* 32 bit warning -- but not for us :) */ |
432 | offset = page_offset(page); | 433 | offset = page_offset(page); |
433 | if (offset < i_size_read(inode)) { | 434 | size = i_size_read(inode); |
434 | avail = inode->i_size-offset; | 435 | filled = 0; |
435 | readlen = min_t(unsigned long, avail, PAGE_SIZE); | 436 | result = 0; |
436 | if (romfs_copyfrom(inode, buf, ROMFS_I(inode)->i_dataoffset+offset, readlen) == readlen) { | 437 | if (offset < size) { |
437 | if (readlen < PAGE_SIZE) { | 438 | unsigned long readlen; |
438 | memset(buf + readlen,0,PAGE_SIZE-readlen); | 439 | |
439 | } | 440 | size -= offset; |
440 | SetPageUptodate(page); | 441 | readlen = size > PAGE_SIZE ? PAGE_SIZE : size; |
441 | result = 0; | 442 | |
443 | filled = romfs_copyfrom(inode, buf, ROMFS_I(inode)->i_dataoffset+offset, readlen); | ||
444 | |||
445 | if (filled != readlen) { | ||
446 | SetPageError(page); | ||
447 | filled = 0; | ||
448 | result = -EIO; | ||
442 | } | 449 | } |
443 | } | 450 | } |
444 | if (result) { | 451 | |
445 | memset(buf, 0, PAGE_SIZE); | 452 | if (filled < PAGE_SIZE) |
446 | SetPageError(page); | 453 | memset(buf + filled, 0, PAGE_SIZE-filled); |
447 | } | 454 | |
455 | if (!result) | ||
456 | SetPageUptodate(page); | ||
448 | flush_dcache_page(page); | 457 | flush_dcache_page(page); |
449 | 458 | ||
450 | unlock_page(page); | 459 | unlock_page(page); |