Commit 14a98a02 authored by Trond Myklebust's avatar Trond Myklebust

NFS: The fact that readdirplus calls now create dentries from within readdir

     calls renders nfs_cached_lookup() obsolete.
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@fys.uio.no>
parent 49deafa1
......@@ -40,8 +40,6 @@
static int nfs_opendir(struct inode *, struct file *);
static int nfs_readdir(struct file *, void *, filldir_t);
static struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameidata *);
static int nfs_cached_lookup(struct inode *, struct dentry *,
struct nfs_fh *, struct nfs_fattr *);
static int nfs_create(struct inode *, struct dentry *, int, struct nameidata *);
static int nfs_mkdir(struct inode *, struct dentry *, int);
static int nfs_rmdir(struct inode *, struct dentry *);
......@@ -613,24 +611,10 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
goto out_valid;
}
/*
* Note: we're not holding inode->i_sem and so may be racing with
* operations that change the directory. We therefore save the
* change attribute *before* we do the RPC call.
*/
verifier = nfs_save_change_attribute(dir);
error = nfs_cached_lookup(dir, dentry, &fhandle, &fattr);
if (!error) {
if (nfs_compare_fh(NFS_FH(inode), &fhandle))
goto out_bad;
if (nfs_lookup_verify_inode(inode, isopen))
goto out_zap_parent;
goto out_valid_renew;
}
if (NFS_STALE(inode))
goto out_bad;
verifier = nfs_save_change_attribute(dir);
error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
if (error)
goto out_bad;
......@@ -639,7 +623,6 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
if ((error = nfs_refresh_inode(inode, &fattr)) != 0)
goto out_bad;
out_valid_renew:
nfs_renew_times(dentry);
nfs_set_verifier(dentry, verifier);
out_valid:
......@@ -744,15 +727,11 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
if (nfs_is_exclusive_create(dir, nd))
goto no_entry;
error = nfs_cached_lookup(dir, dentry, &fhandle, &fattr);
if (error != 0) {
error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name,
&fhandle, &fattr);
if (error == -ENOENT)
goto no_entry;
if (error != 0)
goto out_unlock;
}
error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
if (error == -ENOENT)
goto no_entry;
if (error != 0)
goto out_unlock;
error = -EACCES;
inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr);
if (!inode)
......@@ -947,85 +926,6 @@ static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc)
return dentry;
}
static inline
int find_dirent_name(nfs_readdir_descriptor_t *desc, struct page *page, struct dentry *dentry)
{
struct nfs_entry *entry = desc->entry;
int status;
while((status = dir_decode(desc)) == 0) {
if (entry->len != dentry->d_name.len)
continue;
if (memcmp(entry->name, dentry->d_name.name, entry->len))
continue;
if (!(entry->fattr->valid & NFS_ATTR_FATTR))
continue;
break;
}
return status;
}
/*
* Use the cached Readdirplus results in order to avoid a LOOKUP call
* whenever we believe that the parent directory has not changed.
*
* We assume that any file creation/rename changes the directory mtime.
* As this results in a page cache invalidation whenever it occurs,
* we don't require any other tests for cache coherency.
*/
static
int nfs_cached_lookup(struct inode *dir, struct dentry *dentry,
struct nfs_fh *fh, struct nfs_fattr *fattr)
{
nfs_readdir_descriptor_t desc;
struct nfs_server *server;
struct nfs_entry entry;
struct page *page;
unsigned long timestamp;
int res;
if (!NFS_USE_READDIRPLUS(dir))
return -ENOENT;
server = NFS_SERVER(dir);
/* Don't use readdirplus unless the cache is stable */
if ((server->flags & NFS_MOUNT_NOAC) != 0
|| nfs_caches_unstable(dir)
|| nfs_attribute_timeout(dir))
return -ENOENT;
if ((NFS_FLAGS(dir) & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA)) != 0)
return -ENOENT;
timestamp = NFS_I(dir)->readdir_timestamp;
entry.fh = fh;
entry.fattr = fattr;
desc.decode = NFS_PROTO(dir)->decode_dirent;
desc.entry = &entry;
desc.page_index = 0;
desc.plus = 1;
for(;(page = find_get_page(dir->i_mapping, desc.page_index)); desc.page_index++) {
res = -EIO;
if (PageUptodate(page)) {
void * kaddr = kmap_atomic(page, KM_USER0);
desc.ptr = kaddr;
res = find_dirent_name(&desc, page, dentry);
kunmap_atomic(kaddr, KM_USER0);
}
page_cache_release(page);
if (res == 0)
goto out_found;
if (res != -EAGAIN)
break;
}
return -ENOENT;
out_found:
fattr->timestamp = timestamp;
return 0;
}
/*
* Code common to create, mkdir, and mknod.
*/
......
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