aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2008-08-11 09:48:57 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2008-10-23 05:13:00 -0400
commit4ea3ada2955e4519befa98ff55dd62d6dfbd1705 (patch)
treeb473278d0df8d869d183fbc0e4a1a07585de240a
parent3a8cff4f026c0b98bee6291eb28d4df42feb76dc (diff)
[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>
-rw-r--r--fs/dcache.c35
-rw-r--r--fs/libfs.c26
-rw-r--r--include/linux/dcache.h1
3 files changed, 38 insertions, 24 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index e7a1a99b7464..46fc78206782 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1174,6 +1174,41 @@ struct dentry * d_alloc_anon(struct inode *inode)
1174 return res; 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 */
1195struct 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}
1211EXPORT_SYMBOL_GPL(d_obtain_alias);
1177 1212
1178/** 1213/**
1179 * d_splice_alias - splice a disconnected dentry into the tree if one exists 1214 * d_splice_alias - splice a disconnected dentry into the tree if one exists
diff --git a/fs/libfs.c b/fs/libfs.c
index 1add676a19df..74688598bcf7 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -732,28 +732,6 @@ out:
732 return ret; 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 */
740static 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 * generic_fh_to_dentry - generic helper for the fh_to_dentry export operation 736 * generic_fh_to_dentry - generic helper for the fh_to_dentry export operation
759 * @sb: filesystem to do the file handle conversion on 737 * @sb: filesystem to do the file handle conversion on
@@ -782,7 +760,7 @@ struct dentry *generic_fh_to_dentry(struct super_block *sb, struct fid *fid,
782 break; 760 break;
783 } 761 }
784 762
785 return exportfs_d_alloc(inode); 763 return d_obtain_alias(inode);
786} 764}
787EXPORT_SYMBOL_GPL(generic_fh_to_dentry); 765EXPORT_SYMBOL_GPL(generic_fh_to_dentry);
788 766
@@ -815,7 +793,7 @@ struct dentry *generic_fh_to_parent(struct super_block *sb, struct fid *fid,
815 break; 793 break;
816 } 794 }
817 795
818 return exportfs_d_alloc(inode); 796 return d_obtain_alias(inode);
819} 797}
820EXPORT_SYMBOL_GPL(generic_fh_to_parent); 798EXPORT_SYMBOL_GPL(generic_fh_to_parent);
821 799
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index efba1de629ac..2404257d6c67 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 *);
231extern struct dentry * d_alloc_anon(struct inode *); 231extern struct dentry * d_alloc_anon(struct inode *);
232extern struct dentry * d_splice_alias(struct inode *, struct dentry *); 232extern struct dentry * d_splice_alias(struct inode *, struct dentry *);
233extern struct dentry * d_add_ci(struct dentry *, struct inode *, struct qstr *); 233extern struct dentry * d_add_ci(struct dentry *, struct inode *, struct qstr *);
234extern struct dentry * d_obtain_alias(struct inode *);
234extern void shrink_dcache_sb(struct super_block *); 235extern void shrink_dcache_sb(struct super_block *);
235extern void shrink_dcache_parent(struct dentry *); 236extern void shrink_dcache_parent(struct dentry *);
236extern void shrink_dcache_for_umount(struct super_block *); 237extern void shrink_dcache_for_umount(struct super_block *);