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>
This commit is contained in:
11
fs/nfs/dir.c
11
fs/nfs/dir.c
@@ -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)
|
|||||||
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)
|
|||||||
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
|
|||||||
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);
|
||||||
|
Reference in New Issue
Block a user