Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Christoph Hellwig and committed by
Al Viro
4ea3ada2 3a8cff4f

+38 -24
+35
fs/dcache.c
··· 1174 1174 return res; 1175 1175 } 1176 1176 1177 + /** 1178 + * d_obtain_alias - find or allocate a dentry for a given inode 1179 + * @inode: inode to allocate the dentry for 1180 + * 1181 + * Obtain a dentry for an inode resulting from NFS filehandle conversion or 1182 + * similar open by handle operations. The returned dentry may be anonymous, 1183 + * or may have a full name (if the inode was already in the cache). 1184 + * 1185 + * When called on a directory inode, we must ensure that the inode only ever 1186 + * has one dentry. If a dentry is found, that is returned instead of 1187 + * allocating a new one. 1188 + * 1189 + * On successful return, the reference to the inode has been transferred 1190 + * to the dentry. If %NULL is returned (indicating kmalloc failure), 1191 + * the reference on the inode has been released. To make it easier 1192 + * to use in export operations a NULL or IS_ERR inode may be passed in 1193 + * and will be casted to the corresponding NULL or IS_ERR dentry. 1194 + */ 1195 + struct dentry *d_obtain_alias(struct inode *inode) 1196 + { 1197 + struct dentry *dentry; 1198 + 1199 + if (!inode) 1200 + return NULL; 1201 + if (IS_ERR(inode)) 1202 + return ERR_CAST(inode); 1203 + 1204 + dentry = d_alloc_anon(inode); 1205 + if (!dentry) { 1206 + iput(inode); 1207 + dentry = ERR_PTR(-ENOMEM); 1208 + } 1209 + return dentry; 1210 + } 1211 + EXPORT_SYMBOL_GPL(d_obtain_alias); 1177 1212 1178 1213 /** 1179 1214 * d_splice_alias - splice a disconnected dentry into the tree if one exists
+2 -24
fs/libfs.c
··· 732 732 return ret; 733 733 } 734 734 735 - /* 736 - * This is what d_alloc_anon should have been. Once the exportfs 737 - * argument transition has been finished I will update d_alloc_anon 738 - * to this prototype and this wrapper will go away. --hch 739 - */ 740 - static struct dentry *exportfs_d_alloc(struct inode *inode) 741 - { 742 - struct dentry *dentry; 743 - 744 - if (!inode) 745 - return NULL; 746 - if (IS_ERR(inode)) 747 - return ERR_PTR(PTR_ERR(inode)); 748 - 749 - dentry = d_alloc_anon(inode); 750 - if (!dentry) { 751 - iput(inode); 752 - dentry = ERR_PTR(-ENOMEM); 753 - } 754 - return dentry; 755 - } 756 - 757 735 /** 758 736 * generic_fh_to_dentry - generic helper for the fh_to_dentry export operation 759 737 * @sb: filesystem to do the file handle conversion on ··· 760 782 break; 761 783 } 762 784 763 - return exportfs_d_alloc(inode); 785 + return d_obtain_alias(inode); 764 786 } 765 787 EXPORT_SYMBOL_GPL(generic_fh_to_dentry); 766 788 ··· 793 815 break; 794 816 } 795 817 796 - return exportfs_d_alloc(inode); 818 + return d_obtain_alias(inode); 797 819 } 798 820 EXPORT_SYMBOL_GPL(generic_fh_to_parent); 799 821
+1
include/linux/dcache.h
··· 231 231 extern struct dentry * d_alloc_anon(struct inode *); 232 232 extern struct dentry * d_splice_alias(struct inode *, struct dentry *); 233 233 extern struct dentry * d_add_ci(struct dentry *, struct inode *, struct qstr *); 234 + extern struct dentry * d_obtain_alias(struct inode *); 234 235 extern void shrink_dcache_sb(struct super_block *); 235 236 extern void shrink_dcache_parent(struct dentry *); 236 237 extern void shrink_dcache_for_umount(struct super_block *);