[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>
This commit is contained in:
parent
3a8cff4f02
commit
4ea3ada295
35
fs/dcache.c
35
fs/dcache.c
|
@ -1174,6 +1174,41 @@ struct dentry * d_alloc_anon(struct inode *inode)
|
||||||
return res;
|
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. If %NULL is returned (indicating kmalloc failure),
|
||||||
|
* the reference on the inode has been released. To make it easier
|
||||||
|
* to use in export operations a NULL or IS_ERR inode may be passed in
|
||||||
|
* and will be casted to the corresponding NULL or IS_ERR dentry.
|
||||||
|
*/
|
||||||
|
struct dentry *d_obtain_alias(struct inode *inode)
|
||||||
|
{
|
||||||
|
struct dentry *dentry;
|
||||||
|
|
||||||
|
if (!inode)
|
||||||
|
return NULL;
|
||||||
|
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_GPL(d_obtain_alias);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* d_splice_alias - splice a disconnected dentry into the tree if one exists
|
* d_splice_alias - splice a disconnected dentry into the tree if one exists
|
||||||
|
|
26
fs/libfs.c
26
fs/libfs.c
|
@ -732,28 +732,6 @@ ssize_t simple_attr_write(struct file *file, const char __user *buf,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* This is what d_alloc_anon should have been. Once the exportfs
|
|
||||||
* argument transition has been finished I will update d_alloc_anon
|
|
||||||
* to this prototype and this wrapper will go away. --hch
|
|
||||||
*/
|
|
||||||
static struct dentry *exportfs_d_alloc(struct inode *inode)
|
|
||||||
{
|
|
||||||
struct dentry *dentry;
|
|
||||||
|
|
||||||
if (!inode)
|
|
||||||
return NULL;
|
|
||||||
if (IS_ERR(inode))
|
|
||||||
return ERR_PTR(PTR_ERR(inode));
|
|
||||||
|
|
||||||
dentry = d_alloc_anon(inode);
|
|
||||||
if (!dentry) {
|
|
||||||
iput(inode);
|
|
||||||
dentry = ERR_PTR(-ENOMEM);
|
|
||||||
}
|
|
||||||
return dentry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* generic_fh_to_dentry - generic helper for the fh_to_dentry export operation
|
* generic_fh_to_dentry - generic helper for the fh_to_dentry export operation
|
||||||
* @sb: filesystem to do the file handle conversion on
|
* @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,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return exportfs_d_alloc(inode);
|
return d_obtain_alias(inode);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(generic_fh_to_dentry);
|
EXPORT_SYMBOL_GPL(generic_fh_to_dentry);
|
||||||
|
|
||||||
|
@ -815,7 +793,7 @@ struct dentry *generic_fh_to_parent(struct super_block *sb, struct fid *fid,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return exportfs_d_alloc(inode);
|
return d_obtain_alias(inode);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(generic_fh_to_parent);
|
EXPORT_SYMBOL_GPL(generic_fh_to_parent);
|
||||||
|
|
||||||
|
|
|
@ -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_alloc_anon(struct inode *);
|
||||||
extern struct dentry * d_splice_alias(struct inode *, struct dentry *);
|
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_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_sb(struct super_block *);
|
||||||
extern void shrink_dcache_parent(struct dentry *);
|
extern void shrink_dcache_parent(struct dentry *);
|
||||||
extern void shrink_dcache_for_umount(struct super_block *);
|
extern void shrink_dcache_for_umount(struct super_block *);
|
||||||
|
|
Loading…
Reference in New Issue