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.
1002fbe5e61df654b2b39a1ddc1ae912c9e14c3dddPeter Korsgaard * By default, all devices are named after the name of the device,
1102fbe5e61df654b2b39a1ddc1ae912c9e14c3dddPeter Korsgaard * owned by root and have a default mode of 0600. Subsystems can
1202fbe5e61df654b2b39a1ddc1ae912c9e14c3dddPeter Korsgaard * 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>
27c3a30420902de10bcc4c8474766cb5f97f4c4dfcGreg Kroah-Hartman#include "base.h"
282b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
292780f1ff6aec0cf708a61c022d475bfcaa648965Al Virostatic struct task_struct *thread;
302b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
312b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers#if defined CONFIG_DEVTMPFS_MOUNT
32fc14f2fef682df677d64a145256dbd263df2aa7bAl Virostatic int mount_dev = 1;
332b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers#else
34fc14f2fef682df677d64a145256dbd263df2aa7bAl Virostatic int mount_dev;
352b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers#endif
362b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
372780f1ff6aec0cf708a61c022d475bfcaa648965Al Virostatic DEFINE_SPINLOCK(req_lock);
382780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
392780f1ff6aec0cf708a61c022d475bfcaa648965Al Virostatic struct req {
402780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	struct req *next;
412780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	struct completion done;
422780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	int err;
432780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	const char *name;
442c9ede55ecec58099b72e4bb8eab719f32f72c31Al Viro	umode_t mode;	/* 0 => delete */
454e4098a3e08783cfd75f9fcdab276dc1d46931daGreg Kroah-Hartman	kuid_t uid;
464e4098a3e08783cfd75f9fcdab276dc1d46931daGreg Kroah-Hartman	kgid_t gid;
472780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	struct device *dev;
482780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro} *requests;
49ed413ae6e7813d3227eef43bc6d84ca4f4fe6b21Kay Sievers
502b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversstatic int __init mount_param(char *str)
512b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
52fc14f2fef682df677d64a145256dbd263df2aa7bAl Viro	mount_dev = simple_strtoul(str, NULL, 0);
532b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return 1;
542b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
552b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers__setup("devtmpfs.mount=", mount_param);
562b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
57fc14f2fef682df677d64a145256dbd263df2aa7bAl Virostatic struct dentry *dev_mount(struct file_system_type *fs_type, int flags,
58fc14f2fef682df677d64a145256dbd263df2aa7bAl Viro		      const char *dev_name, void *data)
592b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
60da5e4ef7fdb8f2fb0878dee3bd9d4dd10cea8cf1Peter Korsgaard#ifdef CONFIG_TMPFS
61fc14f2fef682df677d64a145256dbd263df2aa7bAl Viro	return mount_single(fs_type, flags, data, shmem_fill_super);
62da5e4ef7fdb8f2fb0878dee3bd9d4dd10cea8cf1Peter Korsgaard#else
63fc14f2fef682df677d64a145256dbd263df2aa7bAl Viro	return mount_single(fs_type, flags, data, ramfs_fill_super);
64da5e4ef7fdb8f2fb0878dee3bd9d4dd10cea8cf1Peter Korsgaard#endif
652b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
662b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
672b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversstatic struct file_system_type dev_fs_type = {
682b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	.name = "devtmpfs",
69fc14f2fef682df677d64a145256dbd263df2aa7bAl Viro	.mount = dev_mount,
702b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	.kill_sb = kill_litter_super,
712b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers};
722b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
732b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers#ifdef CONFIG_BLOCK
742b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversstatic inline int is_blockdev(struct device *dev)
752b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
762b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return dev->class == &block_class;
772b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
782b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers#else
792b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversstatic inline int is_blockdev(struct device *dev) { return 0; }
802b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers#endif
812b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
822780f1ff6aec0cf708a61c022d475bfcaa648965Al Viroint devtmpfs_create_node(struct device *dev)
832780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro{
842780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	const char *tmp = NULL;
852780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	struct req req;
862780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
872780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	if (!thread)
882780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		return 0;
892780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
902780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	req.mode = 0;
914e4098a3e08783cfd75f9fcdab276dc1d46931daGreg Kroah-Hartman	req.uid = GLOBAL_ROOT_UID;
924e4098a3e08783cfd75f9fcdab276dc1d46931daGreg Kroah-Hartman	req.gid = GLOBAL_ROOT_GID;
933c2670e6515cf584810f417db9b00992c8b2d75aKay Sievers	req.name = device_get_devnode(dev, &req.mode, &req.uid, &req.gid, &tmp);
942780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	if (!req.name)
952780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		return -ENOMEM;
962780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
972780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	if (req.mode == 0)
982780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		req.mode = 0600;
992780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	if (is_blockdev(dev))
1002780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		req.mode |= S_IFBLK;
1012780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	else
1022780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		req.mode |= S_IFCHR;
1032780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
1042780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	req.dev = dev;
1052780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
1062780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	init_completion(&req.done);
1072780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
1082780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	spin_lock(&req_lock);
1092780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	req.next = requests;
1102780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	requests = &req;
1112780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	spin_unlock(&req_lock);
1122780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
1132780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	wake_up_process(thread);
1142780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	wait_for_completion(&req.done);
1152780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
1162780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	kfree(tmp);
1172780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
1182780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	return req.err;
1192780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro}
1202780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
1212780f1ff6aec0cf708a61c022d475bfcaa648965Al Viroint devtmpfs_delete_node(struct device *dev)
1222780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro{
1232780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	const char *tmp = NULL;
1242780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	struct req req;
1252780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
1262780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	if (!thread)
1272780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		return 0;
1282780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
1293c2670e6515cf584810f417db9b00992c8b2d75aKay Sievers	req.name = device_get_devnode(dev, NULL, NULL, NULL, &tmp);
1302780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	if (!req.name)
1312780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		return -ENOMEM;
1322780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
1332780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	req.mode = 0;
1342780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	req.dev = dev;
1352780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
1362780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	init_completion(&req.done);
1372780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
1382780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	spin_lock(&req_lock);
1392780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	req.next = requests;
1402780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	requests = &req;
1412780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	spin_unlock(&req_lock);
1422780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
1432780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	wake_up_process(thread);
1442780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	wait_for_completion(&req.done);
1452780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
1462780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	kfree(tmp);
1472780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	return req.err;
1482780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro}
1492780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
150fbd48a69a0b576dd8cba01b2b4fc24fad76f1b68Al Virostatic int dev_mkdir(const char *name, umode_t mode)
1512b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
1522b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	struct dentry *dentry;
15369753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro	struct path path;
1542b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	int err;
1552b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
1561ac12b4b6d707937f9de6d09622823b2fd0c93efJeff Layton	dentry = kern_path_create(AT_FDCWD, name, &path, LOOKUP_DIRECTORY);
15769753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro	if (IS_ERR(dentry))
15869753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro		return PTR_ERR(dentry);
15969753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro
16069753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro	err = vfs_mkdir(path.dentry->d_inode, dentry, mode);
16169753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro	if (!err)
16269753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro		/* mark as kernel-created inode */
16369753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro		dentry->d_inode->i_private = &thread;
164921a1650de9eed40dd64d681aba4a4d98856f289Al Viro	done_path_create(&path, dentry);
1652b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return err;
1662b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
1672b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
1682b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversstatic int create_path(const char *nodepath)
1692b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
1705da4e689449ad99ab31cf2208d99eddfce0498baAl Viro	char *path;
1715da4e689449ad99ab31cf2208d99eddfce0498baAl Viro	char *s;
1729d108d25487bf958f8093409a4c0bee6169edba6Al Viro	int err = 0;
1732b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
1745da4e689449ad99ab31cf2208d99eddfce0498baAl Viro	/* parent directories do not exist, create them */
1755da4e689449ad99ab31cf2208d99eddfce0498baAl Viro	path = kstrdup(nodepath, GFP_KERNEL);
1765da4e689449ad99ab31cf2208d99eddfce0498baAl Viro	if (!path)
1775da4e689449ad99ab31cf2208d99eddfce0498baAl Viro		return -ENOMEM;
1785da4e689449ad99ab31cf2208d99eddfce0498baAl Viro
1795da4e689449ad99ab31cf2208d99eddfce0498baAl Viro	s = path;
1805da4e689449ad99ab31cf2208d99eddfce0498baAl Viro	for (;;) {
1815da4e689449ad99ab31cf2208d99eddfce0498baAl Viro		s = strchr(s, '/');
1825da4e689449ad99ab31cf2208d99eddfce0498baAl Viro		if (!s)
1835da4e689449ad99ab31cf2208d99eddfce0498baAl Viro			break;
1845da4e689449ad99ab31cf2208d99eddfce0498baAl Viro		s[0] = '\0';
1855da4e689449ad99ab31cf2208d99eddfce0498baAl Viro		err = dev_mkdir(path, 0755);
1865da4e689449ad99ab31cf2208d99eddfce0498baAl Viro		if (err && err != -EEXIST)
1875da4e689449ad99ab31cf2208d99eddfce0498baAl Viro			break;
1885da4e689449ad99ab31cf2208d99eddfce0498baAl Viro		s[0] = '/';
1895da4e689449ad99ab31cf2208d99eddfce0498baAl Viro		s++;
1902b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	}
1915da4e689449ad99ab31cf2208d99eddfce0498baAl Viro	kfree(path);
1922b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return err;
1932b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
1942b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
1954e4098a3e08783cfd75f9fcdab276dc1d46931daGreg Kroah-Hartmanstatic int handle_create(const char *nodename, umode_t mode, kuid_t uid,
1964e4098a3e08783cfd75f9fcdab276dc1d46931daGreg Kroah-Hartman			 kgid_t gid, struct device *dev)
1972b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
1982b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	struct dentry *dentry;
19969753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro	struct path path;
2002b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	int err;
2012b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
20269753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro	dentry = kern_path_create(AT_FDCWD, nodename, &path, 0);
20369753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro	if (dentry == ERR_PTR(-ENOENT)) {
2042b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		create_path(nodename);
20569753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro		dentry = kern_path_create(AT_FDCWD, nodename, &path, 0);
2062b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	}
20769753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro	if (IS_ERR(dentry))
20869753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro		return PTR_ERR(dentry);
20969753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro
2103c2670e6515cf584810f417db9b00992c8b2d75aKay Sievers	err = vfs_mknod(path.dentry->d_inode, dentry, mode, dev->devt);
21169753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro	if (!err) {
21269753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro		struct iattr newattrs;
21369753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro
21469753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro		newattrs.ia_mode = mode;
2154e4098a3e08783cfd75f9fcdab276dc1d46931daGreg Kroah-Hartman		newattrs.ia_uid = uid;
2164e4098a3e08783cfd75f9fcdab276dc1d46931daGreg Kroah-Hartman		newattrs.ia_gid = gid;
2173c2670e6515cf584810f417db9b00992c8b2d75aKay Sievers		newattrs.ia_valid = ATTR_MODE|ATTR_UID|ATTR_GID;
21869753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro		mutex_lock(&dentry->d_inode->i_mutex);
21927ac0ffeac80ba6b9580529568d06144df044366J. Bruce Fields		notify_change(dentry, &newattrs, NULL);
22069753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro		mutex_unlock(&dentry->d_inode->i_mutex);
22169753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro
22269753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro		/* mark as kernel-created inode */
22369753a0f14d3cb2e8a70e559ef8d409e4deeac8aAl Viro		dentry->d_inode->i_private = &thread;
2242b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	}
225921a1650de9eed40dd64d681aba4a4d98856f289Al Viro	done_path_create(&path, dentry);
2262b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return err;
2272b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
2282b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2292b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversstatic int dev_rmdir(const char *name)
2302b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
23179714f72d3b964611997de512cb29198c9f2dbbbAl Viro	struct path parent;
2322b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	struct dentry *dentry;
2332b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	int err;
2342b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
23579714f72d3b964611997de512cb29198c9f2dbbbAl Viro	dentry = kern_path_locked(name, &parent);
23679714f72d3b964611997de512cb29198c9f2dbbbAl Viro	if (IS_ERR(dentry))
23779714f72d3b964611997de512cb29198c9f2dbbbAl Viro		return PTR_ERR(dentry);
23879714f72d3b964611997de512cb29198c9f2dbbbAl Viro	if (dentry->d_inode) {
23979714f72d3b964611997de512cb29198c9f2dbbbAl Viro		if (dentry->d_inode->i_private == &thread)
24079714f72d3b964611997de512cb29198c9f2dbbbAl Viro			err = vfs_rmdir(parent.dentry->d_inode, dentry);
24179714f72d3b964611997de512cb29198c9f2dbbbAl Viro		else
24279714f72d3b964611997de512cb29198c9f2dbbbAl Viro			err = -EPERM;
2432b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	} else {
24479714f72d3b964611997de512cb29198c9f2dbbbAl Viro		err = -ENOENT;
2452b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	}
24679714f72d3b964611997de512cb29198c9f2dbbbAl Viro	dput(dentry);
24779714f72d3b964611997de512cb29198c9f2dbbbAl Viro	mutex_unlock(&parent.dentry->d_inode->i_mutex);
24879714f72d3b964611997de512cb29198c9f2dbbbAl Viro	path_put(&parent);
2492b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return err;
2502b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
2512b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2522b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversstatic int delete_path(const char *nodepath)
2532b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
2542b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	const char *path;
2552b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	int err = 0;
2562b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2572b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	path = kstrdup(nodepath, GFP_KERNEL);
2582b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (!path)
2592b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		return -ENOMEM;
2602b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
261ed413ae6e7813d3227eef43bc6d84ca4f4fe6b21Kay Sievers	for (;;) {
2622b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		char *base;
2632b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2642b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		base = strrchr(path, '/');
2652b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		if (!base)
2662b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			break;
2672b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		base[0] = '\0';
2682b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		err = dev_rmdir(path);
2692b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		if (err)
2702b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			break;
2712b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	}
2722b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2732b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	kfree(path);
2742b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return err;
2752b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
2762b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2772b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversstatic int dev_mynode(struct device *dev, struct inode *inode, struct kstat *stat)
2782b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
2792b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	/* did we create it */
2802780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	if (inode->i_private != &thread)
2812b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		return 0;
2822b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2832b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	/* does the dev_t match */
2842b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (is_blockdev(dev)) {
2852b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		if (!S_ISBLK(stat->mode))
2862b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			return 0;
2872b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	} else {
2882b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		if (!S_ISCHR(stat->mode))
2892b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			return 0;
2902b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	}
2912b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (stat->rdev != dev->devt)
2922b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		return 0;
2932b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2942b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	/* ours */
2952b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return 1;
2962b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
2972b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2982780f1ff6aec0cf708a61c022d475bfcaa648965Al Virostatic int handle_remove(const char *nodename, struct device *dev)
2992b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
30079714f72d3b964611997de512cb29198c9f2dbbbAl Viro	struct path parent;
3012b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	struct dentry *dentry;
302fbde7c6119f99a0e316ad1a8fe0788bd76d277b1Axel Lin	int deleted = 0;
3032b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	int err;
3042b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
30579714f72d3b964611997de512cb29198c9f2dbbbAl Viro	dentry = kern_path_locked(nodename, &parent);
30679714f72d3b964611997de512cb29198c9f2dbbbAl Viro	if (IS_ERR(dentry))
30779714f72d3b964611997de512cb29198c9f2dbbbAl Viro		return PTR_ERR(dentry);
30879714f72d3b964611997de512cb29198c9f2dbbbAl Viro
30979714f72d3b964611997de512cb29198c9f2dbbbAl Viro	if (dentry->d_inode) {
31079714f72d3b964611997de512cb29198c9f2dbbbAl Viro		struct kstat stat;
3113dadecce20603aa380023c65e6f55f108fd5e952Al Viro		struct path p = {.mnt = parent.mnt, .dentry = dentry};
3123dadecce20603aa380023c65e6f55f108fd5e952Al Viro		err = vfs_getattr(&p, &stat);
31379714f72d3b964611997de512cb29198c9f2dbbbAl Viro		if (!err && dev_mynode(dev, dentry->d_inode, &stat)) {
31479714f72d3b964611997de512cb29198c9f2dbbbAl Viro			struct iattr newattrs;
31579714f72d3b964611997de512cb29198c9f2dbbbAl Viro			/*
31679714f72d3b964611997de512cb29198c9f2dbbbAl Viro			 * before unlinking this node, reset permissions
31779714f72d3b964611997de512cb29198c9f2dbbbAl Viro			 * of possible references like hardlinks
31879714f72d3b964611997de512cb29198c9f2dbbbAl Viro			 */
31991fa2ccaa87368314527ea7518c545063662d67fEric W. Biederman			newattrs.ia_uid = GLOBAL_ROOT_UID;
32091fa2ccaa87368314527ea7518c545063662d67fEric W. Biederman			newattrs.ia_gid = GLOBAL_ROOT_GID;
32179714f72d3b964611997de512cb29198c9f2dbbbAl Viro			newattrs.ia_mode = stat.mode & ~0777;
32279714f72d3b964611997de512cb29198c9f2dbbbAl Viro			newattrs.ia_valid =
32379714f72d3b964611997de512cb29198c9f2dbbbAl Viro				ATTR_UID|ATTR_GID|ATTR_MODE;
32479714f72d3b964611997de512cb29198c9f2dbbbAl Viro			mutex_lock(&dentry->d_inode->i_mutex);
32527ac0ffeac80ba6b9580529568d06144df044366J. Bruce Fields			notify_change(dentry, &newattrs, NULL);
32679714f72d3b964611997de512cb29198c9f2dbbbAl Viro			mutex_unlock(&dentry->d_inode->i_mutex);
327b21996e36c8e3b92a84e972378bde80b43acd890J. Bruce Fields			err = vfs_unlink(parent.dentry->d_inode, dentry, NULL);
32879714f72d3b964611997de512cb29198c9f2dbbbAl Viro			if (!err || err == -ENOENT)
32979714f72d3b964611997de512cb29198c9f2dbbbAl Viro				deleted = 1;
3302b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		}
3312b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	} else {
33279714f72d3b964611997de512cb29198c9f2dbbbAl Viro		err = -ENOENT;
3332b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	}
33479714f72d3b964611997de512cb29198c9f2dbbbAl Viro	dput(dentry);
33579714f72d3b964611997de512cb29198c9f2dbbbAl Viro	mutex_unlock(&parent.dentry->d_inode->i_mutex);
3362b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
33779714f72d3b964611997de512cb29198c9f2dbbbAl Viro	path_put(&parent);
3382b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (deleted && strchr(nodename, '/'))
3392b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		delete_path(nodename);
3402b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return err;
3412b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
3422b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
3432b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers/*
3442b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers * If configured, or requested by the commandline, devtmpfs will be
3452b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers * auto-mounted after the kernel mounted the root filesystem.
3462b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers */
347073120cc28ad9f6003452c8bb9d15a87b1820201Kay Sieversint devtmpfs_mount(const char *mntdir)
3482b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
3492b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	int err;
3502b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
351fc14f2fef682df677d64a145256dbd263df2aa7bAl Viro	if (!mount_dev)
3522b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		return 0;
3532b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
3542780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	if (!thread)
3552b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		return 0;
3562b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
357073120cc28ad9f6003452c8bb9d15a87b1820201Kay Sievers	err = sys_mount("devtmpfs", (char *)mntdir, "devtmpfs", MS_SILENT, NULL);
3582b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (err)
3592b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		printk(KERN_INFO "devtmpfs: error mounting %i\n", err);
3602b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	else
3612b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		printk(KERN_INFO "devtmpfs: mounted\n");
3622b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return err;
3632b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
3642b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
365f9e0b159dbff693bacb64a929e04f442df985b50Arnaud Lacombestatic DECLARE_COMPLETION(setup_done);
3662780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
3674e4098a3e08783cfd75f9fcdab276dc1d46931daGreg Kroah-Hartmanstatic int handle(const char *name, umode_t mode, kuid_t uid, kgid_t gid,
3683c2670e6515cf584810f417db9b00992c8b2d75aKay Sievers		  struct device *dev)
3692780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro{
3702780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	if (mode)
3713c2670e6515cf584810f417db9b00992c8b2d75aKay Sievers		return handle_create(name, mode, uid, gid, dev);
3722780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	else
3732780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		return handle_remove(name, dev);
3742780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro}
3752780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
3762780f1ff6aec0cf708a61c022d475bfcaa648965Al Virostatic int devtmpfsd(void *p)
3772780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro{
3782780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	char options[] = "mode=0755";
3792780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	int *err = p;
3802780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	*err = sys_unshare(CLONE_NEWNS);
3812780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	if (*err)
3822780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		goto out;
3832780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	*err = sys_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, options);
3842780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	if (*err)
3852780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		goto out;
3862780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	sys_chdir("/.."); /* will traverse into overmounted root */
3872780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	sys_chroot(".");
3882780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	complete(&setup_done);
3892780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	while (1) {
3902780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		spin_lock(&req_lock);
3912780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		while (requests) {
3922780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro			struct req *req = requests;
3932780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro			requests = NULL;
3942780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro			spin_unlock(&req_lock);
3952780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro			while (req) {
396e13889bab3c6b5c839075086d28fe05f71984ddaAl Viro				struct req *next = req->next;
3973c2670e6515cf584810f417db9b00992c8b2d75aKay Sievers				req->err = handle(req->name, req->mode,
3983c2670e6515cf584810f417db9b00992c8b2d75aKay Sievers						  req->uid, req->gid, req->dev);
3992780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro				complete(&req->done);
400e13889bab3c6b5c839075086d28fe05f71984ddaAl Viro				req = next;
4012780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro			}
4022780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro			spin_lock(&req_lock);
4032780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		}
40465e6757be42ddf0a9115ec0e6af268fec9727359Kautuk Consul		__set_current_state(TASK_INTERRUPTIBLE);
4052780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		spin_unlock(&req_lock);
4062780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		schedule();
4072780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	}
4082780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	return 0;
4092780f1ff6aec0cf708a61c022d475bfcaa648965Al Viroout:
4102780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	complete(&setup_done);
4112780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	return *err;
4122780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro}
4132780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
4142b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers/*
4152b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers * Create devtmpfs instance, driver-core devices will add their device
4162b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers * nodes here.
4172b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers */
4182b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversint __init devtmpfs_init(void)
4192b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
4202780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	int err = register_filesystem(&dev_fs_type);
4212b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (err) {
4222b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		printk(KERN_ERR "devtmpfs: unable to register devtmpfs "
4232b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		       "type %i\n", err);
4242b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		return err;
4252b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	}
4262b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
4272780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	thread = kthread_run(devtmpfsd, &err, "kdevtmpfs");
4282780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	if (!IS_ERR(thread)) {
4292780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		wait_for_completion(&setup_done);
4302780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	} else {
4312780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		err = PTR_ERR(thread);
4322780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro		thread = NULL;
4332780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	}
4342780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro
4352780f1ff6aec0cf708a61c022d475bfcaa648965Al Viro	if (err) {
4362b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		printk(KERN_ERR "devtmpfs: unable to create devtmpfs %i\n", err);
4372b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		unregister_filesystem(&dev_fs_type);
4382b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		return err;
4392b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	}
4402b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
4412b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	printk(KERN_INFO "devtmpfs: initialized\n");
4422b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return 0;
4432b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
444