Commit fccca7fc authored by Trond Myklebust's avatar Trond Myklebust

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: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 5b10ca19
...@@ -537,12 +537,6 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) ...@@ -537,12 +537,6 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
lock_kernel(); 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. * filp->f_pos points to the dirent entry number.
* *desc->dir_cookie has the cookie for the next entry. We have * *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,6 +558,10 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
desc->entry = &my_entry; desc->entry = &my_entry;
nfs_block_sillyrename(dentry); nfs_block_sillyrename(dentry);
res = nfs_revalidate_mapping_nolock(inode, filp->f_mapping);
if (res < 0)
goto out;
while(!desc->entry->eof) { while(!desc->entry->eof) {
res = readdir_search_pagecache(desc); res = readdir_search_pagecache(desc);
...@@ -594,6 +592,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) ...@@ -594,6 +592,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
break; break;
} }
} }
out:
nfs_unblock_sillyrename(dentry); nfs_unblock_sillyrename(dentry);
unlock_kernel(); unlock_kernel();
if (res > 0) if (res > 0)
......
...@@ -138,7 +138,7 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n ...@@ -138,7 +138,7 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n
spin_lock(&alias->d_lock); spin_lock(&alias->d_lock);
if (!(alias->d_flags & DCACHE_NFSFS_RENAMED)) { if (!(alias->d_flags & DCACHE_NFSFS_RENAMED)) {
alias->d_fsdata = data; alias->d_fsdata = data;
alias->d_flags ^= DCACHE_NFSFS_RENAMED; alias->d_flags |= DCACHE_NFSFS_RENAMED;
ret = 1; ret = 1;
} }
spin_unlock(&alias->d_lock); spin_unlock(&alias->d_lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment