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

Commit d93aa9d8 authored by Al Viro's avatar Al Viro
Browse files

new wrapper: alloc_file_pseudo()



takes inode, vfsmount, name, O_... flags and file_operations and
either returns a new struct file (in which case inode reference we
held is consumed) or returns ERR_PTR(), in which case no refcounts
are altered.

converted aio_private_file() and sock_alloc_file() to it

Acked-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent dbae8f2c
Loading
Loading
Loading
Loading
+4 −16
Original line number Diff line number Diff line
@@ -215,9 +215,7 @@ static const struct address_space_operations aio_ctx_aops;

static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages)
{
	struct qstr this = QSTR_INIT("[aio]", 5);
	struct file *file;
	struct path path;
	struct inode *inode = alloc_anon_inode(aio_mnt->mnt_sb);
	if (IS_ERR(inode))
		return ERR_CAST(inode);
@@ -226,27 +224,17 @@ static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages)
	inode->i_mapping->private_data = ctx;
	inode->i_size = PAGE_SIZE * nr_pages;

	path.dentry = d_alloc_pseudo(aio_mnt->mnt_sb, &this);
	if (!path.dentry) {
		iput(inode);
		return ERR_PTR(-ENOMEM);
	}
	path.mnt = mntget(aio_mnt);

	d_instantiate(path.dentry, inode);
	file = alloc_file(&path, O_RDWR, &aio_ring_fops);
	file = alloc_file_pseudo(inode, aio_mnt, "[aio]",
				O_RDWR, &aio_ring_fops);
	if (IS_ERR(file))
		path_put(&path);
		iput(inode);
	return file;
}

static struct dentry *aio_mount(struct file_system_type *fs_type,
				int flags, const char *dev_name, void *data)
{
	static const struct dentry_operations ops = {
		.d_dname	= simple_dname,
	};
	struct dentry *root = mount_pseudo(fs_type, "aio:", NULL, &ops,
	struct dentry *root = mount_pseudo(fs_type, "aio:", NULL, NULL,
					   AIO_RING_MAGIC);

	if (!IS_ERR(root))
+27 −0
Original line number Diff line number Diff line
@@ -184,6 +184,33 @@ struct file *alloc_file(const struct path *path, int flags,
}
EXPORT_SYMBOL(alloc_file);

struct file *alloc_file_pseudo(struct inode *inode, struct vfsmount *mnt,
				const char *name, int flags,
				const struct file_operations *fops)
{
	static const struct dentry_operations anon_ops = {
		.d_dname = simple_dname
	};
	struct qstr this = QSTR_INIT(name, strlen(name));
	struct path path;
	struct file *file;

	path.dentry = d_alloc_pseudo(mnt->mnt_sb, &this);
	if (!path.dentry)
		return ERR_PTR(-ENOMEM);
	if (!mnt->mnt_sb->s_d_op)
		d_set_d_op(path.dentry, &anon_ops);
	path.mnt = mntget(mnt);
	d_instantiate(path.dentry, inode);
	file = alloc_file(&path, flags, fops);
	if (IS_ERR(file)) {
		ihold(inode);
		path_put(&path);
	}
	return file;
}
EXPORT_SYMBOL(alloc_file_pseudo);

/* the real guts of fput() - releasing the last reference to file
 */
static void __fput(struct file *file)
+3 −0
Original line number Diff line number Diff line
@@ -17,9 +17,12 @@ extern void fput(struct file *);
struct file_operations;
struct vfsmount;
struct dentry;
struct inode;
struct path;
extern struct file *alloc_file(const struct path *, int flags,
	const struct file_operations *fop);
extern struct file *alloc_file_pseudo(struct inode *, struct vfsmount *,
	const char *, int flags, const struct file_operations *);

static inline void fput_light(struct file *file, int fput_needed)
{
+5 −23
Original line number Diff line number Diff line
@@ -391,33 +391,15 @@ static struct file_system_type sock_fs_type = {

struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname)
{
	struct qstr name = { .name = "" };
	struct path path;
	struct file *file;

	if (dname) {
		name.name = dname;
		name.len = strlen(name.name);
	} else if (sock->sk) {
		name.name = sock->sk->sk_prot_creator->name;
		name.len = strlen(name.name);
	}
	path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
	if (unlikely(!path.dentry)) {
		sock_release(sock);
		return ERR_PTR(-ENOMEM);
	}
	path.mnt = mntget(sock_mnt);

	d_instantiate(path.dentry, SOCK_INODE(sock));
	if (!dname)
		dname = sock->sk ? sock->sk->sk_prot_creator->name : "";

	file = alloc_file(&path, O_RDWR | (flags & O_NONBLOCK),
	file = alloc_file_pseudo(SOCK_INODE(sock), sock_mnt, dname,
				O_RDWR | (flags & O_NONBLOCK),
				&socket_file_ops);
	if (IS_ERR(file)) {
		/* drop dentry, keep inode for a bit */
		ihold(d_inode(path.dentry));
		path_put(&path);
		/* ... and now kill it properly */
		sock_release(sock);
		return file;
	}