diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-01-26 22:37:47 (GMT) |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-01-30 07:05:21 (GMT) |
commit | fccca7fc6aab4e6b519e2d606ef34632e4f50e33 (patch) | |
tree | 4d12d88039d229263a610647df6c751585f714dc /fs | |
parent | 5b10ca19ea4859d3884d10a3eb8495de92089792 (diff) | |
download | linux-fsl-qoriq-fccca7fc6aab4e6b519e2d606ef34632e4f50e33.tar.xz |
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>
Diffstat (limited to 'fs')
-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 f697b5c..d9abdb1 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) lock_kernel(); - res = nfs_revalidate_mapping_nolock(inode, filp->f_mapping); - if (res < 0) { - unlock_kernel(); - return res; - } - /* * filp->f_pos points to the dirent entry number. * *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) desc->entry = &my_entry; nfs_block_sillyrename(dentry); + res = nfs_revalidate_mapping_nolock(inode, filp->f_mapping); + if (res < 0) + goto out; + while(!desc->entry->eof) { res = readdir_search_pagecache(desc); @@ -594,6 +592,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) break; } } +out: nfs_unblock_sillyrename(dentry); unlock_kernel(); if (res > 0) diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index 233ad38..c5fa6d8 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 spin_lock(&alias->d_lock); if (!(alias->d_flags & DCACHE_NFSFS_RENAMED)) { alias->d_fsdata = data; - alias->d_flags ^= DCACHE_NFSFS_RENAMED; + alias->d_flags |= DCACHE_NFSFS_RENAMED; ret = 1; } spin_unlock(&alias->d_lock); |