aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2008-01-26 17:37:47 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-01-30 02:05:21 -0500
commitfccca7fc6aab4e6b519e2d606ef34632e4f50e33 (patch)
tree4d12d88039d229263a610647df6c751585f714dc
parent5b10ca19ea4859d3884d10a3eb8495de92089792 (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.c11
-rw-r--r--fs/nfs/unlink.c2
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 }
595out:
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);