NFS: The fact that readdirplus calls now create dentries from within readdir calls renders nfs_cached_lookup() obsolete. Signed-off-by: Trond Myklebust --- dir.c | 112 +++--------------------------------------------------------------- 1 files changed, 6 insertions(+), 106 deletions(-) Index: linux-2.6.9-rc1/fs/nfs/dir.c =================================================================== --- linux-2.6.9-rc1.orig/fs/nfs/dir.c 2004-09-09 19:57:04.988450869 -0400 +++ linux-2.6.9-rc1/fs/nfs/dir.c 2004-09-09 20:00:24.734763069 -0400 @@ -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 @@ 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 @@ 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 @@ 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 @@ 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. */