diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-01-26 17:37:47 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-01-30 02:05:21 -0500 |
commit | fccca7fc6aab4e6b519e2d606ef34632e4f50e33 (patch) | |
tree | 4d12d88039d229263a610647df6c751585f714dc | |
parent | 5b10ca19ea4859d3884d10a3eb8495de92089792 (diff) |
NFS: Fix a sillyrename race...
Ensure that readdir revalidates its data cache after blocking on
sillyrename.
Also fix a typo in nfs_do_call_unlink(): swap the ^= for an |=. The result
is the same, since we've already checked that the flag is unset, but it
makes the code more readable.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r-- | fs/nfs/dir.c | 11 | ||||
-rw-r--r-- | fs/nfs/unlink.c | 2 |
2 files changed, 6 insertions, 7 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index f697b5c74b7c..d9abdb1d6a2a 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -537,12 +537,6 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
537 | 537 | ||
538 | lock_kernel(); | 538 | lock_kernel(); |
539 | 539 | ||
540 | res = nfs_revalidate_mapping_nolock(inode, filp->f_mapping); | ||
541 | if (res < 0) { | ||
542 | unlock_kernel(); | ||
543 | return res; | ||
544 | } | ||
545 | |||
546 | /* | 540 | /* |
547 | * filp->f_pos points to the dirent entry number. | 541 | * filp->f_pos points to the dirent entry number. |
548 | * *desc->dir_cookie has the cookie for the next entry. We have | 542 | * *desc->dir_cookie has the cookie for the next entry. We have |
@@ -564,6 +558,10 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
564 | desc->entry = &my_entry; | 558 | desc->entry = &my_entry; |
565 | 559 | ||
566 | nfs_block_sillyrename(dentry); | 560 | nfs_block_sillyrename(dentry); |
561 | res = nfs_revalidate_mapping_nolock(inode, filp->f_mapping); | ||
562 | if (res < 0) | ||
563 | goto out; | ||
564 | |||
567 | while(!desc->entry->eof) { | 565 | while(!desc->entry->eof) { |
568 | res = readdir_search_pagecache(desc); | 566 | res = readdir_search_pagecache(desc); |
569 | 567 | ||
@@ -594,6 +592,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
594 | break; | 592 | break; |
595 | } | 593 | } |
596 | } | 594 | } |
595 | out: | ||
597 | nfs_unblock_sillyrename(dentry); | 596 | nfs_unblock_sillyrename(dentry); |
598 | unlock_kernel(); | 597 | unlock_kernel(); |
599 | if (res > 0) | 598 | if (res > 0) |
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index 233ad38161f9..c5fa6d8001f1 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c | |||
@@ -138,7 +138,7 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n | |||
138 | spin_lock(&alias->d_lock); | 138 | spin_lock(&alias->d_lock); |
139 | if (!(alias->d_flags & DCACHE_NFSFS_RENAMED)) { | 139 | if (!(alias->d_flags & DCACHE_NFSFS_RENAMED)) { |
140 | alias->d_fsdata = data; | 140 | alias->d_fsdata = data; |
141 | alias->d_flags ^= DCACHE_NFSFS_RENAMED; | 141 | alias->d_flags |= DCACHE_NFSFS_RENAMED; |
142 | ret = 1; | 142 | ret = 1; |
143 | } | 143 | } |
144 | spin_unlock(&alias->d_lock); | 144 | spin_unlock(&alias->d_lock); |