Added nfs4_vfh_getdentry() that traverses all the dcache entries for the nfs mount and looks for a matching file handle. The dentry with a matching file handle can then be used for recovering from a FHEXPIRED error. Signed-off-by: Matthew Treinish <treinish@xxxxxxxxxxxxxxxxxx> --- fs/nfs/nfs4proc.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 47 insertions(+), 0 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 3706c44..ee62c1e 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -2547,6 +2547,53 @@ static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qst return err; } +/* In the case of gettattr only a fh is given, and we need a VFS object to do + * vfh recovery. This function traverses the dcache to find the dentry with + * a matching fh + */ +struct dentry *nfs4_vfh_getdentry(struct nfs_server *server, struct nfs_fh *fhandle) +{ + struct dentry *this_parent; + struct list_head *next; + struct dentry *d_root = server->rootdentry; + + this_parent = d_root; +repeat: + next = this_parent->d_subdirs.next; +resume: + while (next != &this_parent->d_subdirs) { + struct list_head *tmp = next; + struct dentry *dentry = list_entry(tmp, struct dentry, + d_u.d_child); + next = tmp->next; + /* Compare dentry's fh with one provided */ + if (dentry && dentry->d_inode && &dentry->d_name) + if (!nfs_compare_fh(NFS_FH(dentry->d_inode), fhandle)) + return dget(dentry); + + if (!list_empty(&dentry->d_subdirs)) { + this_parent = dentry; + goto repeat; + } + } + if (this_parent != d_root) { + struct dentry *child = this_parent; + struct dentry *new = this_parent->d_parent; + /* + * might go back up the wrong parent if we have had a rename + * or deletion return ESTALE if it is renamed or deleted + */ + if (new != this_parent->d_parent || + (this_parent->d_flags & DCACHE_DISCONNECTED)) { + return ERR_PTR(-ESTALE); + } + this_parent = new; + next = child->d_u.d_child.next; + goto resume; + } + return ERR_PTR(-ENOENT); +} + static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) { struct nfs_server *server = NFS_SERVER(inode); -- 1.7.4.4 -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html