From: Eric Sandeen <sandeen@redhat.com> Date: Wed, 25 Mar 2009 15:44:49 -0500 Subject: [fs] d_obtain_alias helper Message-id: 49CA97C1.9030408@redhat.com O-Subject: [PATCH 5/10] d_obtain_alias helper Bugzilla: 470845 RH-Acked-by: Steven Whitehouse <swhiteho@redhat.com> RH-Acked-by: Josef Bacik <josef@redhat.com> Backport of: commit 4ea3ada2955e4519befa98ff55dd62d6dfbd1705 Author: Christoph Hellwig <hch@lst.de> Date: Mon Aug 11 15:48:57 2008 +0200 [PATCH] new helper: d_obtain_alias The calling conventions of d_alloc_anon are rather unfortunate for all users, and it's name is not very descriptive either. Add d_obtain_alias as a new exported helper that drops the inode reference in the failure case, too and allows to pass-through NULL pointers and inodes to allow for tail-calls in the export operations. Incidentally this helper already existed as a private function in libfs.c as exportfs_d_alloc so kill that one and switch the callers to d_obtain_alias. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> and one small bit of this (just the ESTALE change): commit 440037287c5ebb07033ab927ca16bb68c291d309 Author: Christoph Hellwig <hch@lst.de> Date: Mon Aug 11 15:49:04 2008 +0200 [PATCH] switch all filesystems over to d_obtain_alias Switch all users of d_alloc_anon to d_obtain_alias. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> diff --git a/fs/dcache.c b/fs/dcache.c index 3aec28c..6071ec0 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1117,6 +1117,42 @@ struct dentry * d_alloc_anon(struct inode *inode) return res; } +/** + * d_obtain_alias - find or allocate a dentry for a given inode + * @inode: inode to allocate the dentry for + * + * Obtain a dentry for an inode resulting from NFS filehandle conversion or + * similar open by handle operations. The returned dentry may be anonymous, + * or may have a full name (if the inode was already in the cache). + * + * When called on a directory inode, we must ensure that the inode only ever + * has one dentry. If a dentry is found, that is returned instead of + * allocating a new one. + * + * On successful return, the reference to the inode has been transferred + * to the dentry. In case of an error the reference on the inode is released. + * To make it easier to use in export operations a %NULL or IS_ERR inode may + * be passed in and will be the error will be propagate to the return value, + * with a %NULL @inode replaced by ERR_PTR(-ESTALE). + */ +struct dentry *d_obtain_alias(struct inode *inode) +{ + struct dentry *dentry; + + if (!inode) + return ERR_PTR(-ESTALE); + if (IS_ERR(inode)) + return ERR_CAST(inode); + + dentry = d_alloc_anon(inode); + if (!dentry) { + iput(inode); + dentry = ERR_PTR(-ENOMEM); + } + return dentry; +} +EXPORT_SYMBOL(d_obtain_alias); + /** * d_splice_alias - splice a disconnected dentry into the tree if one exists diff --git a/include/linux/dcache.h b/include/linux/dcache.h index f8e03cc..ba24c70 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -231,6 +231,7 @@ extern struct dentry * d_alloc(struct dentry *, const struct qstr *); extern struct dentry * d_alloc_anon(struct inode *); extern struct dentry * d_splice_alias(struct inode *, struct dentry *); extern struct dentry * d_add_ci(struct dentry *, struct inode *, struct qstr *); +extern struct dentry * d_obtain_alias(struct inode *); extern void shrink_dcache_sb(struct super_block *); extern void shrink_dcache_parent(struct dentry *); extern void shrink_dcache_for_umount(struct super_block *);