Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4ea3ada2 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Al Viro
Browse files

[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: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 3a8cff4f
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -1174,6 +1174,41 @@ 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.  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
+2 −24
Original line number Diff line number Diff line
@@ -732,28 +732,6 @@ out:
	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
 * @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;
	}

	return exportfs_d_alloc(inode);
	return d_obtain_alias(inode);
}
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;
	}

	return exportfs_d_alloc(inode);
	return d_obtain_alias(inode);
}
EXPORT_SYMBOL_GPL(generic_fh_to_parent);

+1 −0
Original line number Diff line number Diff line
@@ -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 *);