devtmpfs.c revision 2c9ede55ecec58099b72e4bb8eab719f32f72c31
12b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers/*
22b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers * devtmpfs - kernel-maintained tmpfs-based /dev
32b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers *
42b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers * Copyright (C) 2009, Kay Sievers <kay.sievers@vrfy.org>
52b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers *
62b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers * During bootup, before any driver core device is registered,
72b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers * devtmpfs, a tmpfs-based filesystem is created. Every driver-core
82b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers * device which requests a device node, will add a node in this
9e454cea20bdcff10ee698d11b8882662a0153a47Kay Sievers * filesystem.
10e454cea20bdcff10ee698d11b8882662a0153a47Kay Sievers * By default, all devices are named after the the name of the
11e454cea20bdcff10ee698d11b8882662a0153a47Kay Sievers * device, owned by root and have a default mode of 0600. Subsystems
12e454cea20bdcff10ee698d11b8882662a0153a47Kay Sievers * can overwrite the default setting if needed.
132b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers */
142b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
152b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers#include <linux/kernel.h>
162b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers#include <linux/syscalls.h>
172b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers#include <linux/mount.h>
182b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers#include <linux/device.h>
192b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers#include <linux/genhd.h>
202b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers#include <linux/namei.h>
212b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers#include <linux/fs.h>
222b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers#include <linux/shmem_fs.h>
23da5e4ef7fdb8f2fb0878dee3bd9d4dd10cea8cf1Peter Korsgaard#include <linux/ramfs.h>
24e454cea20bdcff10ee698d11b8882662a0153a47Kay Sievers#include <linux/sched.h>
255a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
262780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro#include <linux/kthread.h>
272b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
282780f1ff6aec0cf708a61c022d475bfcaa648965Al Virostatic struct task_struct *thread;
292b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
302b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers#if defined CONFIG_DEVTMPFS_MOUNT
31fc14f2fef682df677d64a145256dbd263df2aa7bAl Virostatic int mount_dev = 1;
322b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers#else
33fc14f2fef682df677d64a145256dbd263df2aa7bAl Virostatic int mount_dev;
342b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers#endif
352b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
362780f1ff6aec0cf708a61c022d475bfcaa648965Al Virostatic DEFINE_SPINLOCK(req_lock);
372780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
382780f1ff6aec0cf708a61c022d475bfcaa648965Al Virostatic struct req {
392780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	struct req *next;
402780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	struct completion done;
412780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	int err;
422780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	const char *name;
432c9ede55ecec58099b72e4bb8eab719f32f72c31Al Viro	umode_t mode;	/* 0 => delete */
442780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	struct device *dev;
452780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro} *requests;
46ed413ae6e7813d3227eef43bc6d84ca4f4fe6b21Kay Sievers
472b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversstatic int __init mount_param(char *str)
482b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
49fc14f2fef682df677d64a145256dbd263df2aa7bAl Viro	mount_dev = simple_strtoul(str, NULL, 0);
502b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return 1;
512b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
522b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers__setup("devtmpfs.mount=", mount_param);
532b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
54fc14f2fef682df677d64a145256dbd263df2aa7bAl Virostatic struct dentry *dev_mount(struct file_system_type *fs_type, int flags,
55fc14f2fef682df677d64a145256dbd263df2aa7bAl Viro		      const char *dev_name, void *data)
562b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
57da5e4ef7fdb8f2fb0878dee3bd9d4dd10cea8cf1Peter Korsgaard#ifdef CONFIG_TMPFS
58fc14f2fef682df677d64a145256dbd263df2aa7bAl Viro	return mount_single(fs_type, flags, data, shmem_fill_super);
59da5e4ef7fdb8f2fb0878dee3bd9d4dd10cea8cf1Peter Korsgaard#else
60fc14f2fef682df677d64a145256dbd263df2aa7bAl Viro	return mount_single(fs_type, flags, data, ramfs_fill_super);
61da5e4ef7fdb8f2fb0878dee3bd9d4dd10cea8cf1Peter Korsgaard#endif
622b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
632b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
642b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversstatic struct file_system_type dev_fs_type = {
652b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	.name = "devtmpfs",
66fc14f2fef682df677d64a145256dbd263df2aa7bAl Viro	.mount = dev_mount,
672b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	.kill_sb = kill_litter_super,
682b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers};
692b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
702b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers#ifdef CONFIG_BLOCK
712b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversstatic inline int is_blockdev(struct device *dev)
722b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
732b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return dev->class == &block_class;
742b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
752b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers#else
762b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversstatic inline int is_blockdev(struct device *dev) { return 0; }
772b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers#endif
782b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
792780f1ff6aec0cf708a61c022d475bfcaa648965Al Viroint devtmpfs_create_node(struct device *dev)
802780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro{
812780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	const char *tmp = NULL;
822780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	struct req req;
832780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
842780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	if (!thread)
852780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		return 0;
862780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
872780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	req.mode = 0;
882780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	req.name = device_get_devnode(dev, &req.mode, &tmp);
892780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	if (!req.name)
902780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		return -ENOMEM;
912780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
922780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	if (req.mode == 0)
932780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		req.mode = 0600;
942780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	if (is_blockdev(dev))
952780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		req.mode |= S_IFBLK;
962780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	else
972780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		req.mode |= S_IFCHR;
982780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
992780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	req.dev = dev;
1002780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
1012780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	init_completion(&req.done);
1022780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
1032780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	spin_lock(&req_lock);
1042780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	req.next = requests;
1052780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	requests = &req;
1062780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	spin_unlock(&req_lock);
1072780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
1082780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	wake_up_process(thread);
1092780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	wait_for_completion(&req.done);
1102780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
1112780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	kfree(tmp);
1122780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
1132780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	return req.err;
1142780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro}
1152780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
1162780f1ff6aec0cf708a61c022d475bfcaa648965Al Viroint devtmpfs_delete_node(struct device *dev)
1172780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro{
1182780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	const char *tmp = NULL;
1192780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	struct req req;
1202780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
1212780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	if (!thread)
1222780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		return 0;
1232780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
1242780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	req.name = device_get_devnode(dev, NULL, &tmp);
1252780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	if (!req.name)
1262780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		return -ENOMEM;
1272780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
1282780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	req.mode = 0;
1292780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	req.dev = dev;
1302780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
1312780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	init_completion(&req.done);
1322780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
1332780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	spin_lock(&req_lock);
1342780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	req.next = requests;
1352780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	requests = &req;
1362780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	spin_unlock(&req_lock);
1372780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
1382780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	wake_up_process(thread);
1392780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	wait_for_completion(&req.done);
1402780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
1412780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	kfree(tmp);
1422780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	return req.err;
1432780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro}
1442780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
1452b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversstatic int dev_mkdir(const char *name, mode_t mode)
1462b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
1472b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	struct dentry *dentry;
14869753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro	struct path path;
1492b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	int err;
1502b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
15169753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro	dentry = kern_path_create(AT_FDCWD, name, &path, 1);
15269753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro	if (IS_ERR(dentry))
15369753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro		return PTR_ERR(dentry);
15469753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro
15569753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro	err = vfs_mkdir(path.dentry->d_inode, dentry, mode);
15669753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro	if (!err)
15769753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro		/* mark as kernel-created inode */
15869753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro		dentry->d_inode->i_private = &thread;
15969753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro	dput(dentry);
16069753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro	mutex_unlock(&path.dentry->d_inode->i_mutex);
16169753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro	path_put(&path);
1622b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return err;
1632b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
1642b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
1652b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversstatic int create_path(const char *nodepath)
1662b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
1675da4e689449ad99ab31cf2208d99eddfce0498baAl Viro	char *path;
1685da4e689449ad99ab31cf2208d99eddfce0498baAl Viro	char *s;
1699d108d25487bf958f8093409a4c0bee6169edba6Al Viro	int err = 0;
1702b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
1715da4e689449ad99ab31cf2208d99eddfce0498baAl Viro	/* parent directories do not exist, create them */
1725da4e689449ad99ab31cf2208d99eddfce0498baAl Viro	path = kstrdup(nodepath, GFP_KERNEL);
1735da4e689449ad99ab31cf2208d99eddfce0498baAl Viro	if (!path)
1745da4e689449ad99ab31cf2208d99eddfce0498baAl Viro		return -ENOMEM;
1755da4e689449ad99ab31cf2208d99eddfce0498baAl Viro
1765da4e689449ad99ab31cf2208d99eddfce0498baAl Viro	s = path;
1775da4e689449ad99ab31cf2208d99eddfce0498baAl Viro	for (;;) {
1785da4e689449ad99ab31cf2208d99eddfce0498baAl Viro		s = strchr(s, '/');
1795da4e689449ad99ab31cf2208d99eddfce0498baAl Viro		if (!s)
1805da4e689449ad99ab31cf2208d99eddfce0498baAl Viro			break;
1815da4e689449ad99ab31cf2208d99eddfce0498baAl Viro		s[0] = '\0';
1825da4e689449ad99ab31cf2208d99eddfce0498baAl Viro		err = dev_mkdir(path, 0755);
1835da4e689449ad99ab31cf2208d99eddfce0498baAl Viro		if (err && err != -EEXIST)
1845da4e689449ad99ab31cf2208d99eddfce0498baAl Viro			break;
1855da4e689449ad99ab31cf2208d99eddfce0498baAl Viro		s[0] = '/';
1865da4e689449ad99ab31cf2208d99eddfce0498baAl Viro		s++;
1872b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	}
1885da4e689449ad99ab31cf2208d99eddfce0498baAl Viro	kfree(path);
1892b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return err;
1902b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
1912b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
1922780f1ff6aec0cf708a61c022d475bfcaa648965Al Virostatic int handle_create(const char *nodename, mode_t mode, struct device *dev)
1932b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
1942b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	struct dentry *dentry;
19569753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro	struct path path;
1962b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	int err;
1972b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
19869753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro	dentry = kern_path_create(AT_FDCWD, nodename, &path, 0);
19969753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro	if (dentry == ERR_PTR(-ENOENT)) {
2002b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		create_path(nodename);
20169753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro		dentry = kern_path_create(AT_FDCWD, nodename, &path, 0);
2022b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	}
20369753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro	if (IS_ERR(dentry))
20469753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro		return PTR_ERR(dentry);
20569753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro
20669753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro	err = vfs_mknod(path.dentry->d_inode,
20769753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro			dentry, mode, dev->devt);
20869753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro	if (!err) {
20969753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro		struct iattr newattrs;
21069753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro
21169753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro		/* fixup possibly umasked mode */
21269753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro		newattrs.ia_mode = mode;
21369753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro		newattrs.ia_valid = ATTR_MODE;
21469753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro		mutex_lock(&dentry->d_inode->i_mutex);
21569753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro		notify_change(dentry, &newattrs);
21669753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro		mutex_unlock(&dentry->d_inode->i_mutex);
21769753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro
21869753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro		/* mark as kernel-created inode */
21969753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro		dentry->d_inode->i_private = &thread;
2202b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	}
22169753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro	dput(dentry);
2222b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
22369753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro	mutex_unlock(&path.dentry->d_inode->i_mutex);
22469753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro	path_put(&path);
2252b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return err;
2262b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
2272b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2282b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversstatic int dev_rmdir(const char *name)
2292b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
2302b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	struct nameidata nd;
2312b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	struct dentry *dentry;
2322b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	int err;
2332b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2342780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	err = kern_path_parent(name, &nd);
2352b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (err)
2362b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		return err;
2372b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2382b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
2392b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
2402b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (!IS_ERR(dentry)) {
241015bf43b07158668c2f38af463939afcc6d19403Kay Sievers		if (dentry->d_inode) {
2422780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro			if (dentry->d_inode->i_private == &thread)
243015bf43b07158668c2f38af463939afcc6d19403Kay Sievers				err = vfs_rmdir(nd.path.dentry->d_inode,
244015bf43b07158668c2f38af463939afcc6d19403Kay Sievers						dentry);
245015bf43b07158668c2f38af463939afcc6d19403Kay Sievers			else
246015bf43b07158668c2f38af463939afcc6d19403Kay Sievers				err = -EPERM;
247015bf43b07158668c2f38af463939afcc6d19403Kay Sievers		} else {
2482b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			err = -ENOENT;
249015bf43b07158668c2f38af463939afcc6d19403Kay Sievers		}
2502b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		dput(dentry);
2512b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	} else {
2522b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		err = PTR_ERR(dentry);
2532b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	}
2542b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
255015bf43b07158668c2f38af463939afcc6d19403Kay Sievers	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
2562b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	path_put(&nd.path);
2572b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return err;
2582b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
2592b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2602b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversstatic int delete_path(const char *nodepath)
2612b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
2622b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	const char *path;
2632b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	int err = 0;
2642b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2652b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	path = kstrdup(nodepath, GFP_KERNEL);
2662b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (!path)
2672b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		return -ENOMEM;
2682b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
269ed413ae6e7813d3227eef43bc6d84ca4f4fe6b21Kay Sievers	for (;;) {
2702b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		char *base;
2712b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2722b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		base = strrchr(path, '/');
2732b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		if (!base)
2742b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			break;
2752b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		base[0] = '\0';
2762b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		err = dev_rmdir(path);
2772b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		if (err)
2782b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			break;
2792b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	}
2802b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2812b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	kfree(path);
2822b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return err;
2832b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
2842b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2852b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversstatic int dev_mynode(struct device *dev, struct inode *inode, struct kstat *stat)
2862b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
2872b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	/* did we create it */
2882780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	if (inode->i_private != &thread)
2892b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		return 0;
2902b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2912b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	/* does the dev_t match */
2922b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (is_blockdev(dev)) {
2932b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		if (!S_ISBLK(stat->mode))
2942b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			return 0;
2952b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	} else {
2962b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		if (!S_ISCHR(stat->mode))
2972b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			return 0;
2982b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	}
2992b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (stat->rdev != dev->devt)
3002b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		return 0;
3012b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
3022b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	/* ours */
3032b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return 1;
3042b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
3052b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
3062780f1ff6aec0cf708a61c022d475bfcaa648965Al Virostatic int handle_remove(const char *nodename, struct device *dev)
3072b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
3082b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	struct nameidata nd;
3092b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	struct dentry *dentry;
3102b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	struct kstat stat;
3112b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	int deleted = 1;
3122b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	int err;
3132b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
3142780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	err = kern_path_parent(nodename, &nd);
3152b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (err)
3162780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		return err;
3172b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
3182b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
3192b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
3202b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (!IS_ERR(dentry)) {
3212b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		if (dentry->d_inode) {
3222b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			err = vfs_getattr(nd.path.mnt, dentry, &stat);
3232b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			if (!err && dev_mynode(dev, dentry->d_inode, &stat)) {
3245e31d76f2817bd50258a092a7c5b15b3006fd61cKay Sievers				struct iattr newattrs;
3255e31d76f2817bd50258a092a7c5b15b3006fd61cKay Sievers				/*
3265e31d76f2817bd50258a092a7c5b15b3006fd61cKay Sievers				 * before unlinking this node, reset permissions
3275e31d76f2817bd50258a092a7c5b15b3006fd61cKay Sievers				 * of possible references like hardlinks
3285e31d76f2817bd50258a092a7c5b15b3006fd61cKay Sievers				 */
3295e31d76f2817bd50258a092a7c5b15b3006fd61cKay Sievers				newattrs.ia_uid = 0;
3305e31d76f2817bd50258a092a7c5b15b3006fd61cKay Sievers				newattrs.ia_gid = 0;
3315e31d76f2817bd50258a092a7c5b15b3006fd61cKay Sievers				newattrs.ia_mode = stat.mode & ~0777;
3325e31d76f2817bd50258a092a7c5b15b3006fd61cKay Sievers				newattrs.ia_valid =
3335e31d76f2817bd50258a092a7c5b15b3006fd61cKay Sievers					ATTR_UID|ATTR_GID|ATTR_MODE;
3345e31d76f2817bd50258a092a7c5b15b3006fd61cKay Sievers				mutex_lock(&dentry->d_inode->i_mutex);
3355e31d76f2817bd50258a092a7c5b15b3006fd61cKay Sievers				notify_change(dentry, &newattrs);
3365e31d76f2817bd50258a092a7c5b15b3006fd61cKay Sievers				mutex_unlock(&dentry->d_inode->i_mutex);
3372b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers				err = vfs_unlink(nd.path.dentry->d_inode,
3382b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers						 dentry);
3392b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers				if (!err || err == -ENOENT)
3402b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers					deleted = 1;
3412b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			}
3422b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		} else {
3432b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			err = -ENOENT;
3442b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		}
3452b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		dput(dentry);
3462b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	} else {
3472b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		err = PTR_ERR(dentry);
3482b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	}
3492b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
3502b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
3512b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	path_put(&nd.path);
3522b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (deleted && strchr(nodename, '/'))
3532b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		delete_path(nodename);
3542b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return err;
3552b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
3562b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
3572b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers/*
3582b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers * If configured, or requested by the commandline, devtmpfs will be
3592b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers * auto-mounted after the kernel mounted the root filesystem.
3602b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers */
361073120cc28ad9f6003452c8bb9d15a87b1820201Kay Sieversint devtmpfs_mount(const char *mntdir)
3622b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
3632b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	int err;
3642b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
365fc14f2fef682df677d64a145256dbd263df2aa7bAl Viro	if (!mount_dev)
3662b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		return 0;
3672b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
3682780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	if (!thread)
3692b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		return 0;
3702b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
371073120cc28ad9f6003452c8bb9d15a87b1820201Kay Sievers	err = sys_mount("devtmpfs", (char *)mntdir, "devtmpfs", MS_SILENT, NULL);
3722b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (err)
3732b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		printk(KERN_INFO "devtmpfs: error mounting %i\n", err);
3742b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	else
3752b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		printk(KERN_INFO "devtmpfs: mounted\n");
3762b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return err;
3772b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
3782b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
379f9e0b159dbff693bacb64a929e04f442df985b50Arnaud Lacombestatic DECLARE_COMPLETION(setup_done);
3802780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
3812780f1ff6aec0cf708a61c022d475bfcaa648965Al Virostatic int handle(const char *name, mode_t mode, struct device *dev)
3822780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro{
3832780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	if (mode)
3842780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		return handle_create(name, mode, dev);
3852780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	else
3862780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		return handle_remove(name, dev);
3872780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro}
3882780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
3892780f1ff6aec0cf708a61c022d475bfcaa648965Al Virostatic int devtmpfsd(void *p)
3902780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro{
3912780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	char options[] = "mode=0755";
3922780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	int *err = p;
3932780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	*err = sys_unshare(CLONE_NEWNS);
3942780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	if (*err)
3952780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		goto out;
3962780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	*err = sys_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, options);
3972780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	if (*err)
3982780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		goto out;
3992780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	sys_chdir("/.."); /* will traverse into overmounted root */
4002780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	sys_chroot(".");
4012780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	complete(&setup_done);
4022780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	while (1) {
4032780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		spin_lock(&req_lock);
4042780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		while (requests) {
4052780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro			struct req *req = requests;
4062780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro			requests = NULL;
4072780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro			spin_unlock(&req_lock);
4082780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro			while (req) {
409e13889bab3c6b5c839075086d28fe05f71984ddaAl Viro				struct req *next = req->next;
4102780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro				req->err = handle(req->name, req->mode, req->dev);
4112780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro				complete(&req->done);
412e13889bab3c6b5c839075086d28fe05f71984ddaAl Viro				req = next;
4132780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro			}
4142780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro			spin_lock(&req_lock);
4152780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		}
4162780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		set_current_state(TASK_INTERRUPTIBLE);
4172780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		spin_unlock(&req_lock);
4182780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		schedule();
4192780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		__set_current_state(TASK_RUNNING);
4202780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	}
4212780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	return 0;
4222780f1ff6aec0cf708a61c022d475bfcaa648965Al Viroout:
4232780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	complete(&setup_done);
4242780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	return *err;
4252780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro}
4262780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
4272b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers/*
4282b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers * Create devtmpfs instance, driver-core devices will add their device
4292b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers * nodes here.
4302b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers */
4312b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversint __init devtmpfs_init(void)
4322b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
4332780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	int err = register_filesystem(&dev_fs_type);
4342b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (err) {
4352b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		printk(KERN_ERR "devtmpfs: unable to register devtmpfs "
4362b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		       "type %i\n", err);
4372b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		return err;
4382b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	}
4392b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
4402780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	thread = kthread_run(devtmpfsd, &err, "kdevtmpfs");
4412780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	if (!IS_ERR(thread)) {
4422780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		wait_for_completion(&setup_done);
4432780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	} else {
4442780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		err = PTR_ERR(thread);
4452780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		thread = NULL;
4462780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	}
4472780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
4482780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	if (err) {
4492b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		printk(KERN_ERR "devtmpfs: unable to create devtmpfs %i\n", err);
4502b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		unregister_filesystem(&dev_fs_type);
4512b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		return err;
4522b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	}
4532b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
4542b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	printk(KERN_INFO "devtmpfs: initialized\n");
4552b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return 0;
4562b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
457