anon_inodes.c 4.91 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
/*
 *  fs/anon_inodes.c
 *
 *  Copyright (C) 2007  Davide Libenzi <davidel@xmailserver.org>
 *
 *  Thanks to Arnd Bergmann for code review and suggestions.
 *  More changes for Thomas Gleixner suggestions.
 *
 */

11
#include <linux/cred.h>
12 13
#include <linux/file.h>
#include <linux/poll.h>
14
#include <linux/sched.h>
15 16 17 18 19 20 21 22 23 24 25 26 27
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/mount.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/magic.h>
#include <linux/anon_inodes.h>

#include <asm/uaccess.h>

static struct vfsmount *anon_inode_mnt __read_mostly;
static struct inode *anon_inode_inode;

28 29 30 31 32 33 34 35 36
/*
 * anon_inodefs_dname() is called from d_path().
 */
static char *anon_inodefs_dname(struct dentry *dentry, char *buffer, int buflen)
{
	return dynamic_dname(dentry, buffer, buflen, "anon_inode:%s",
				dentry->d_name.name);
}

37 38 39 40
static const struct dentry_operations anon_inodefs_dentry_operations = {
	.d_dname	= anon_inodefs_dname,
};

41 42 43
static struct dentry *anon_inodefs_mount(struct file_system_type *fs_type,
				int flags, const char *dev_name, void *data)
{
44
	return mount_pseudo(fs_type, "anon_inode:", NULL,
45 46 47 48 49 50 51 52 53
			&anon_inodefs_dentry_operations, ANON_INODE_FS_MAGIC);
}

static struct file_system_type anon_inode_fs_type = {
	.name		= "anon_inodefs",
	.mount		= anon_inodefs_mount,
	.kill_sb	= kill_anon_super,
};

54
/**
55 56 57
 * anon_inode_getfile - creates a new file instance by hooking it up to an
 *                      anonymous inode, and a dentry that describe the "class"
 *                      of the file
58 59
 *
 * @name:    [in]    name of the "class" of the new file
60 61 62
 * @fops:    [in]    file operations for the new file
 * @priv:    [in]    private data for the new file (will be file's private_data)
 * @flags:   [in]    flags
63 64 65
 *
 * Creates a new file by hooking it on a single inode. This is useful for files
 * that do not need to have a full-fledged inode in order to operate correctly.
66
 * All the files created with anon_inode_getfile() will share a single inode,
67
 * hence saving memory and avoiding code duplication for the file/inode/dentry
68
 * setup.  Returns the newly created file* or an error pointer.
69
 */
70 71 72
struct file *anon_inode_getfile(const char *name,
				const struct file_operations *fops,
				void *priv, int flags)
73 74
{
	struct qstr this;
75
	struct path path;
76 77 78
	struct file *file;

	if (IS_ERR(anon_inode_inode))
79
		return ERR_PTR(-ENODEV);
80

81
	if (fops->owner && !try_module_get(fops->owner))
82
		return ERR_PTR(-ENOENT);
83 84 85 86 87

	/*
	 * Link the inode to a directory entry by creating a unique name
	 * using the inode sequence number.
	 */
88
	file = ERR_PTR(-ENOMEM);
89 90 91
	this.name = name;
	this.len = strlen(name);
	this.hash = 0;
92
	path.dentry = d_alloc_pseudo(anon_inode_mnt->mnt_sb, &this);
93
	if (!path.dentry)
94
		goto err_module;
95

96
	path.mnt = mntget(anon_inode_mnt);
97 98
	/*
	 * We know the anon_inode inode count is always greater than zero,
Al Viro's avatar
Al Viro committed
99
	 * so ihold() is safe.
100
	 */
Al Viro's avatar
Al Viro committed
101
	ihold(anon_inode_inode);
102

103
	d_instantiate(path.dentry, anon_inode_inode);
104

Al Viro's avatar
Al Viro committed
105
	file = alloc_file(&path, OPEN_FMODE(flags), fops);
106
	if (IS_ERR(file))
107
		goto err_dput;
108
	file->f_mapping = anon_inode_inode->i_mapping;
109

110
	file->f_flags = flags & (O_ACCMODE | O_NONBLOCK);
111 112
	file->private_data = priv;

113 114 115
	return file;

err_dput:
116
	path_put(&path);
117 118
err_module:
	module_put(fops->owner);
119
	return file;
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
}
EXPORT_SYMBOL_GPL(anon_inode_getfile);

/**
 * anon_inode_getfd - creates a new file instance by hooking it up to an
 *                    anonymous inode, and a dentry that describe the "class"
 *                    of the file
 *
 * @name:    [in]    name of the "class" of the new file
 * @fops:    [in]    file operations for the new file
 * @priv:    [in]    private data for the new file (will be file's private_data)
 * @flags:   [in]    flags
 *
 * Creates a new file by hooking it on a single inode. This is useful for files
 * that do not need to have a full-fledged inode in order to operate correctly.
 * All the files created with anon_inode_getfd() will share a single inode,
 * hence saving memory and avoiding code duplication for the file/inode/dentry
 * setup.  Returns new descriptor or an error code.
 */
int anon_inode_getfd(const char *name, const struct file_operations *fops,
		     void *priv, int flags)
{
	int error, fd;
	struct file *file;

	error = get_unused_fd_flags(flags);
	if (error < 0)
		return error;
	fd = error;

	file = anon_inode_getfile(name, fops, priv, flags);
	if (IS_ERR(file)) {
		error = PTR_ERR(file);
		goto err_put_unused_fd;
	}
155 156
	fd_install(fd, file);

157
	return fd;
158 159 160 161 162

err_put_unused_fd:
	put_unused_fd(fd);
	return error;
}
163
EXPORT_SYMBOL_GPL(anon_inode_getfd);
164 165 166 167

static int __init anon_inode_init(void)
{
	anon_inode_mnt = kern_mount(&anon_inode_fs_type);
168 169
	if (IS_ERR(anon_inode_mnt))
		panic("anon_inode_init() kernel mount failed (%ld)\n", PTR_ERR(anon_inode_mnt));
170

171 172 173 174 175
	anon_inode_inode = alloc_anon_inode(anon_inode_mnt->mnt_sb);
	if (IS_ERR(anon_inode_inode))
		panic("anon_inode_init() inode allocation failed (%ld)\n", PTR_ERR(anon_inode_inode));

	return 0;
176 177 178 179
}

fs_initcall(anon_inode_init);