diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-08-27 17:31:44 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-08-27 17:31:44 -0400 |
commit | 5b51a7e9d84f19df4d532ebf5624dbb8ad0d6c9c (patch) | |
tree | aa8359921a8039474c7bb1544823184855e59694 /fs | |
parent | 3d87ff3e44bd2a13cbe2d2e02cc5e38953ff260f (diff) | |
parent | 4cdfe84b51420c9ac95c7133da2d4c8a191094af (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] deal with the first call of ->show() generating no output
[PATCH] fix ->llseek() for a bunch of directories
[PATCH] fix regular readdir() and friends
[PATCH] fix hpux_getdents()
[PATCH] fix osf_getdirents()
[PATCH] ntfs: use d_add_ci
[PATCH] change d_add_ci argument ordering
[PATCH] fix efs_lookup()
[PATCH] proc: inode number fixlet
Diffstat (limited to 'fs')
-rw-r--r-- | fs/9p/vfs_dir.c | 1 | ||||
-rw-r--r-- | fs/adfs/dir.c | 1 | ||||
-rw-r--r-- | fs/affs/dir.c | 1 | ||||
-rw-r--r-- | fs/autofs4/root.c | 2 | ||||
-rw-r--r-- | fs/befs/linuxvfs.c | 1 | ||||
-rw-r--r-- | fs/compat.c | 8 | ||||
-rw-r--r-- | fs/dcache.c | 2 | ||||
-rw-r--r-- | fs/efs/namei.c | 3 | ||||
-rw-r--r-- | fs/ntfs/namei.c | 89 | ||||
-rw-r--r-- | fs/proc/generic.c | 1 | ||||
-rw-r--r-- | fs/readdir.c | 8 | ||||
-rw-r--r-- | fs/seq_file.c | 11 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_file.c | 1 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_iops.c | 2 |
14 files changed, 34 insertions, 97 deletions
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index 88e3787c6ea9..e298fe194093 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c | |||
@@ -119,6 +119,7 @@ int v9fs_dir_release(struct inode *inode, struct file *filp) | |||
119 | 119 | ||
120 | const struct file_operations v9fs_dir_operations = { | 120 | const struct file_operations v9fs_dir_operations = { |
121 | .read = generic_read_dir, | 121 | .read = generic_read_dir, |
122 | .llseek = generic_file_llseek, | ||
122 | .readdir = v9fs_dir_readdir, | 123 | .readdir = v9fs_dir_readdir, |
123 | .open = v9fs_file_open, | 124 | .open = v9fs_file_open, |
124 | .release = v9fs_dir_release, | 125 | .release = v9fs_dir_release, |
diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c index fc1a8dc64d78..85a30e929800 100644 --- a/fs/adfs/dir.c +++ b/fs/adfs/dir.c | |||
@@ -197,6 +197,7 @@ out: | |||
197 | 197 | ||
198 | const struct file_operations adfs_dir_operations = { | 198 | const struct file_operations adfs_dir_operations = { |
199 | .read = generic_read_dir, | 199 | .read = generic_read_dir, |
200 | .llseek = generic_file_llseek, | ||
200 | .readdir = adfs_readdir, | 201 | .readdir = adfs_readdir, |
201 | .fsync = file_fsync, | 202 | .fsync = file_fsync, |
202 | }; | 203 | }; |
diff --git a/fs/affs/dir.c b/fs/affs/dir.c index 6e3f282424b0..7b36904dbeac 100644 --- a/fs/affs/dir.c +++ b/fs/affs/dir.c | |||
@@ -19,6 +19,7 @@ static int affs_readdir(struct file *, void *, filldir_t); | |||
19 | 19 | ||
20 | const struct file_operations affs_dir_operations = { | 20 | const struct file_operations affs_dir_operations = { |
21 | .read = generic_read_dir, | 21 | .read = generic_read_dir, |
22 | .llseek = generic_file_llseek, | ||
22 | .readdir = affs_readdir, | 23 | .readdir = affs_readdir, |
23 | .fsync = file_fsync, | 24 | .fsync = file_fsync, |
24 | }; | 25 | }; |
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index bcfb2dc0a61b..2a41c2a7fc52 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -36,6 +36,7 @@ const struct file_operations autofs4_root_operations = { | |||
36 | .release = dcache_dir_close, | 36 | .release = dcache_dir_close, |
37 | .read = generic_read_dir, | 37 | .read = generic_read_dir, |
38 | .readdir = dcache_readdir, | 38 | .readdir = dcache_readdir, |
39 | .llseek = dcache_dir_lseek, | ||
39 | .ioctl = autofs4_root_ioctl, | 40 | .ioctl = autofs4_root_ioctl, |
40 | }; | 41 | }; |
41 | 42 | ||
@@ -44,6 +45,7 @@ const struct file_operations autofs4_dir_operations = { | |||
44 | .release = dcache_dir_close, | 45 | .release = dcache_dir_close, |
45 | .read = generic_read_dir, | 46 | .read = generic_read_dir, |
46 | .readdir = dcache_readdir, | 47 | .readdir = dcache_readdir, |
48 | .llseek = dcache_dir_lseek, | ||
47 | }; | 49 | }; |
48 | 50 | ||
49 | const struct inode_operations autofs4_indirect_root_inode_operations = { | 51 | const struct inode_operations autofs4_indirect_root_inode_operations = { |
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 02c6e62b72f8..740f53672a8a 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c | |||
@@ -66,6 +66,7 @@ static struct kmem_cache *befs_inode_cachep; | |||
66 | static const struct file_operations befs_dir_operations = { | 66 | static const struct file_operations befs_dir_operations = { |
67 | .read = generic_read_dir, | 67 | .read = generic_read_dir, |
68 | .readdir = befs_readdir, | 68 | .readdir = befs_readdir, |
69 | .llseek = generic_file_llseek, | ||
69 | }; | 70 | }; |
70 | 71 | ||
71 | static const struct inode_operations befs_dir_inode_operations = { | 72 | static const struct inode_operations befs_dir_inode_operations = { |
diff --git a/fs/compat.c b/fs/compat.c index c9d1472e65c5..075d0509970d 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -792,8 +792,10 @@ static int compat_fillonedir(void *__buf, const char *name, int namlen, | |||
792 | if (buf->result) | 792 | if (buf->result) |
793 | return -EINVAL; | 793 | return -EINVAL; |
794 | d_ino = ino; | 794 | d_ino = ino; |
795 | if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) | 795 | if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) { |
796 | buf->result = -EOVERFLOW; | ||
796 | return -EOVERFLOW; | 797 | return -EOVERFLOW; |
798 | } | ||
797 | buf->result++; | 799 | buf->result++; |
798 | dirent = buf->dirent; | 800 | dirent = buf->dirent; |
799 | if (!access_ok(VERIFY_WRITE, dirent, | 801 | if (!access_ok(VERIFY_WRITE, dirent, |
@@ -862,8 +864,10 @@ static int compat_filldir(void *__buf, const char *name, int namlen, | |||
862 | if (reclen > buf->count) | 864 | if (reclen > buf->count) |
863 | return -EINVAL; | 865 | return -EINVAL; |
864 | d_ino = ino; | 866 | d_ino = ino; |
865 | if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) | 867 | if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) { |
868 | buf->error = -EOVERFLOW; | ||
866 | return -EOVERFLOW; | 869 | return -EOVERFLOW; |
870 | } | ||
867 | dirent = buf->previous; | 871 | dirent = buf->previous; |
868 | if (dirent) { | 872 | if (dirent) { |
869 | if (__put_user(offset, &dirent->d_off)) | 873 | if (__put_user(offset, &dirent->d_off)) |
diff --git a/fs/dcache.c b/fs/dcache.c index 101663d15e9f..80e93956aced 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -1236,7 +1236,7 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry) | |||
1236 | * If no entry exists with the exact case name, allocate new dentry with | 1236 | * If no entry exists with the exact case name, allocate new dentry with |
1237 | * the exact case, and return the spliced entry. | 1237 | * the exact case, and return the spliced entry. |
1238 | */ | 1238 | */ |
1239 | struct dentry *d_add_ci(struct inode *inode, struct dentry *dentry, | 1239 | struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode, |
1240 | struct qstr *name) | 1240 | struct qstr *name) |
1241 | { | 1241 | { |
1242 | int error; | 1242 | int error; |
diff --git a/fs/efs/namei.c b/fs/efs/namei.c index 3a404e7fad53..291abb11e20e 100644 --- a/fs/efs/namei.c +++ b/fs/efs/namei.c | |||
@@ -74,8 +74,7 @@ struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, struct namei | |||
74 | } | 74 | } |
75 | unlock_kernel(); | 75 | unlock_kernel(); |
76 | 76 | ||
77 | d_add(dentry, inode); | 77 | return d_splice_alias(inode, dentry); |
78 | return NULL; | ||
79 | } | 78 | } |
80 | 79 | ||
81 | static struct inode *efs_nfs_get_inode(struct super_block *sb, u64 ino, | 80 | static struct inode *efs_nfs_get_inode(struct super_block *sb, u64 ino, |
diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c index e1781c8b1650..9e8a95be7a1e 100644 --- a/fs/ntfs/namei.c +++ b/fs/ntfs/namei.c | |||
@@ -174,7 +174,6 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, | |||
174 | // TODO: Consider moving this lot to a separate function! (AIA) | 174 | // TODO: Consider moving this lot to a separate function! (AIA) |
175 | handle_name: | 175 | handle_name: |
176 | { | 176 | { |
177 | struct dentry *real_dent, *new_dent; | ||
178 | MFT_RECORD *m; | 177 | MFT_RECORD *m; |
179 | ntfs_attr_search_ctx *ctx; | 178 | ntfs_attr_search_ctx *ctx; |
180 | ntfs_inode *ni = NTFS_I(dent_inode); | 179 | ntfs_inode *ni = NTFS_I(dent_inode); |
@@ -255,93 +254,9 @@ handle_name: | |||
255 | } | 254 | } |
256 | nls_name.hash = full_name_hash(nls_name.name, nls_name.len); | 255 | nls_name.hash = full_name_hash(nls_name.name, nls_name.len); |
257 | 256 | ||
258 | /* | 257 | dent = d_add_ci(dent, dent_inode, &nls_name); |
259 | * Note: No need for dent->d_lock lock as i_mutex is held on the | ||
260 | * parent inode. | ||
261 | */ | ||
262 | |||
263 | /* Does a dentry matching the nls_name exist already? */ | ||
264 | real_dent = d_lookup(dent->d_parent, &nls_name); | ||
265 | /* If not, create it now. */ | ||
266 | if (!real_dent) { | ||
267 | real_dent = d_alloc(dent->d_parent, &nls_name); | ||
268 | kfree(nls_name.name); | ||
269 | if (!real_dent) { | ||
270 | err = -ENOMEM; | ||
271 | goto err_out; | ||
272 | } | ||
273 | new_dent = d_splice_alias(dent_inode, real_dent); | ||
274 | if (new_dent) | ||
275 | dput(real_dent); | ||
276 | else | ||
277 | new_dent = real_dent; | ||
278 | ntfs_debug("Done. (Created new dentry.)"); | ||
279 | return new_dent; | ||
280 | } | ||
281 | kfree(nls_name.name); | 258 | kfree(nls_name.name); |
282 | /* Matching dentry exists, check if it is negative. */ | 259 | return dent; |
283 | if (real_dent->d_inode) { | ||
284 | if (unlikely(real_dent->d_inode != dent_inode)) { | ||
285 | /* This can happen because bad inodes are unhashed. */ | ||
286 | BUG_ON(!is_bad_inode(dent_inode)); | ||
287 | BUG_ON(!is_bad_inode(real_dent->d_inode)); | ||
288 | } | ||
289 | /* | ||
290 | * Already have the inode and the dentry attached, decrement | ||
291 | * the reference count to balance the ntfs_iget() we did | ||
292 | * earlier on. We found the dentry using d_lookup() so it | ||
293 | * cannot be disconnected and thus we do not need to worry | ||
294 | * about any NFS/disconnectedness issues here. | ||
295 | */ | ||
296 | iput(dent_inode); | ||
297 | ntfs_debug("Done. (Already had inode and dentry.)"); | ||
298 | return real_dent; | ||
299 | } | ||
300 | /* | ||
301 | * Negative dentry: instantiate it unless the inode is a directory and | ||
302 | * has a 'disconnected' dentry (i.e. IS_ROOT and DCACHE_DISCONNECTED), | ||
303 | * in which case d_move() that in place of the found dentry. | ||
304 | */ | ||
305 | if (!S_ISDIR(dent_inode->i_mode)) { | ||
306 | /* Not a directory; everything is easy. */ | ||
307 | d_instantiate(real_dent, dent_inode); | ||
308 | ntfs_debug("Done. (Already had negative file dentry.)"); | ||
309 | return real_dent; | ||
310 | } | ||
311 | spin_lock(&dcache_lock); | ||
312 | if (list_empty(&dent_inode->i_dentry)) { | ||
313 | /* | ||
314 | * Directory without a 'disconnected' dentry; we need to do | ||
315 | * d_instantiate() by hand because it takes dcache_lock which | ||
316 | * we already hold. | ||
317 | */ | ||
318 | list_add(&real_dent->d_alias, &dent_inode->i_dentry); | ||
319 | real_dent->d_inode = dent_inode; | ||
320 | spin_unlock(&dcache_lock); | ||
321 | security_d_instantiate(real_dent, dent_inode); | ||
322 | ntfs_debug("Done. (Already had negative directory dentry.)"); | ||
323 | return real_dent; | ||
324 | } | ||
325 | /* | ||
326 | * Directory with a 'disconnected' dentry; get a reference to the | ||
327 | * 'disconnected' dentry. | ||
328 | */ | ||
329 | new_dent = list_entry(dent_inode->i_dentry.next, struct dentry, | ||
330 | d_alias); | ||
331 | dget_locked(new_dent); | ||
332 | spin_unlock(&dcache_lock); | ||
333 | /* Do security vodoo. */ | ||
334 | security_d_instantiate(real_dent, dent_inode); | ||
335 | /* Move new_dent in place of real_dent. */ | ||
336 | d_move(new_dent, real_dent); | ||
337 | /* Balance the ntfs_iget() we did above. */ | ||
338 | iput(dent_inode); | ||
339 | /* Throw away real_dent. */ | ||
340 | dput(real_dent); | ||
341 | /* Use new_dent as the actual dentry. */ | ||
342 | ntfs_debug("Done. (Already had negative, disconnected directory " | ||
343 | "dentry.)"); | ||
344 | return new_dent; | ||
345 | 260 | ||
346 | eio_err_out: | 261 | eio_err_out: |
347 | ntfs_error(vol->sb, "Illegal file name attribute. Run chkdsk."); | 262 | ntfs_error(vol->sb, "Illegal file name attribute. Run chkdsk."); |
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 4fb81e9c94e3..bca0f81eb687 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
@@ -330,6 +330,7 @@ retry: | |||
330 | spin_lock(&proc_inum_lock); | 330 | spin_lock(&proc_inum_lock); |
331 | ida_remove(&proc_inum_ida, i); | 331 | ida_remove(&proc_inum_ida, i); |
332 | spin_unlock(&proc_inum_lock); | 332 | spin_unlock(&proc_inum_lock); |
333 | return 0; | ||
333 | } | 334 | } |
334 | return PROC_DYNAMIC_FIRST + i; | 335 | return PROC_DYNAMIC_FIRST + i; |
335 | } | 336 | } |
diff --git a/fs/readdir.c b/fs/readdir.c index 4e026e5407fb..93a7559bbfd8 100644 --- a/fs/readdir.c +++ b/fs/readdir.c | |||
@@ -80,8 +80,10 @@ static int fillonedir(void * __buf, const char * name, int namlen, loff_t offset | |||
80 | if (buf->result) | 80 | if (buf->result) |
81 | return -EINVAL; | 81 | return -EINVAL; |
82 | d_ino = ino; | 82 | d_ino = ino; |
83 | if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) | 83 | if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) { |
84 | buf->result = -EOVERFLOW; | ||
84 | return -EOVERFLOW; | 85 | return -EOVERFLOW; |
86 | } | ||
85 | buf->result++; | 87 | buf->result++; |
86 | dirent = buf->dirent; | 88 | dirent = buf->dirent; |
87 | if (!access_ok(VERIFY_WRITE, dirent, | 89 | if (!access_ok(VERIFY_WRITE, dirent, |
@@ -155,8 +157,10 @@ static int filldir(void * __buf, const char * name, int namlen, loff_t offset, | |||
155 | if (reclen > buf->count) | 157 | if (reclen > buf->count) |
156 | return -EINVAL; | 158 | return -EINVAL; |
157 | d_ino = ino; | 159 | d_ino = ino; |
158 | if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) | 160 | if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) { |
161 | buf->error = -EOVERFLOW; | ||
159 | return -EOVERFLOW; | 162 | return -EOVERFLOW; |
163 | } | ||
160 | dirent = buf->previous; | 164 | dirent = buf->previous; |
161 | if (dirent) { | 165 | if (dirent) { |
162 | if (__put_user(offset, &dirent->d_off)) | 166 | if (__put_user(offset, &dirent->d_off)) |
diff --git a/fs/seq_file.c b/fs/seq_file.c index 5d54205e486b..bd20f7f5a933 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c | |||
@@ -108,9 +108,9 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) | |||
108 | goto Done; | 108 | goto Done; |
109 | } | 109 | } |
110 | /* we need at least one record in buffer */ | 110 | /* we need at least one record in buffer */ |
111 | pos = m->index; | ||
112 | p = m->op->start(m, &pos); | ||
111 | while (1) { | 113 | while (1) { |
112 | pos = m->index; | ||
113 | p = m->op->start(m, &pos); | ||
114 | err = PTR_ERR(p); | 114 | err = PTR_ERR(p); |
115 | if (!p || IS_ERR(p)) | 115 | if (!p || IS_ERR(p)) |
116 | break; | 116 | break; |
@@ -119,6 +119,11 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) | |||
119 | break; | 119 | break; |
120 | if (unlikely(err)) | 120 | if (unlikely(err)) |
121 | m->count = 0; | 121 | m->count = 0; |
122 | if (unlikely(!m->count)) { | ||
123 | p = m->op->next(m, p, &pos); | ||
124 | m->index = pos; | ||
125 | continue; | ||
126 | } | ||
122 | if (m->count < m->size) | 127 | if (m->count < m->size) |
123 | goto Fill; | 128 | goto Fill; |
124 | m->op->stop(m, p); | 129 | m->op->stop(m, p); |
@@ -128,6 +133,8 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) | |||
128 | goto Enomem; | 133 | goto Enomem; |
129 | m->count = 0; | 134 | m->count = 0; |
130 | m->version = 0; | 135 | m->version = 0; |
136 | pos = m->index; | ||
137 | p = m->op->start(m, &pos); | ||
131 | } | 138 | } |
132 | m->op->stop(m, p); | 139 | m->op->stop(m, p); |
133 | m->count = 0; | 140 | m->count = 0; |
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index 5f60363b9343..5311c1acdd40 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c | |||
@@ -475,6 +475,7 @@ const struct file_operations xfs_invis_file_operations = { | |||
475 | const struct file_operations xfs_dir_file_operations = { | 475 | const struct file_operations xfs_dir_file_operations = { |
476 | .read = generic_read_dir, | 476 | .read = generic_read_dir, |
477 | .readdir = xfs_file_readdir, | 477 | .readdir = xfs_file_readdir, |
478 | .llseek = generic_file_llseek, | ||
478 | .unlocked_ioctl = xfs_file_ioctl, | 479 | .unlocked_ioctl = xfs_file_ioctl, |
479 | #ifdef CONFIG_COMPAT | 480 | #ifdef CONFIG_COMPAT |
480 | .compat_ioctl = xfs_file_compat_ioctl, | 481 | .compat_ioctl = xfs_file_compat_ioctl, |
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 91bcd979242c..095d271f3434 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c | |||
@@ -355,7 +355,7 @@ xfs_vn_ci_lookup( | |||
355 | /* else case-insensitive match... */ | 355 | /* else case-insensitive match... */ |
356 | dname.name = ci_name.name; | 356 | dname.name = ci_name.name; |
357 | dname.len = ci_name.len; | 357 | dname.len = ci_name.len; |
358 | dentry = d_add_ci(VFS_I(ip), dentry, &dname); | 358 | dentry = d_add_ci(dentry, VFS_I(ip), &dname); |
359 | kmem_free(ci_name.name); | 359 | kmem_free(ci_name.name); |
360 | return dentry; | 360 | return dentry; |
361 | } | 361 | } |