devtmpfs.c revision fc14f2fef682df677d64a145256dbd263df2aa7b
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>
242b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers#include <linux/cred.h>
25e454cea20bdcff10ee698d11b8882662a0153a47Kay Sievers#include <linux/sched.h>
262b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers#include <linux/init_task.h>
275a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
282b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
292b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversstatic struct vfsmount *dev_mnt;
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
37f1f76f865b5f66db5b5c7f2d19874f2bb9b43b8dThomas Gleixnerstatic DEFINE_MUTEX(dirlock);
38ed413ae6e7813d3227eef43bc6d84ca4f4fe6b21Kay Sievers
392b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversstatic int __init mount_param(char *str)
402b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
41fc14f2fef682df677d64a145256dbd263df2aa7bAl Viro	mount_dev = simple_strtoul(str, NULL, 0);
422b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return 1;
432b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
442b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers__setup("devtmpfs.mount=", mount_param);
452b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
46fc14f2fef682df677d64a145256dbd263df2aa7bAl Virostatic struct dentry *dev_mount(struct file_system_type *fs_type, int flags,
47fc14f2fef682df677d64a145256dbd263df2aa7bAl Viro		      const char *dev_name, void *data)
482b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
49da5e4ef7fdb8f2fb0878dee3bd9d4dd10cea8cf1Peter Korsgaard#ifdef CONFIG_TMPFS
50fc14f2fef682df677d64a145256dbd263df2aa7bAl Viro	return mount_single(fs_type, flags, data, shmem_fill_super);
51da5e4ef7fdb8f2fb0878dee3bd9d4dd10cea8cf1Peter Korsgaard#else
52fc14f2fef682df677d64a145256dbd263df2aa7bAl Viro	return mount_single(fs_type, flags, data, ramfs_fill_super);
53da5e4ef7fdb8f2fb0878dee3bd9d4dd10cea8cf1Peter Korsgaard#endif
542b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
552b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
562b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversstatic struct file_system_type dev_fs_type = {
572b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	.name = "devtmpfs",
58fc14f2fef682df677d64a145256dbd263df2aa7bAl Viro	.mount = dev_mount,
592b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	.kill_sb = kill_litter_super,
602b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers};
612b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
622b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers#ifdef CONFIG_BLOCK
632b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversstatic inline int is_blockdev(struct device *dev)
642b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
652b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return dev->class == &block_class;
662b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
672b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers#else
682b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversstatic inline int is_blockdev(struct device *dev) { return 0; }
692b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers#endif
702b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
712b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversstatic int dev_mkdir(const char *name, mode_t mode)
722b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
732b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	struct nameidata nd;
742b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	struct dentry *dentry;
752b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	int err;
762b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
772b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
782b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			      name, LOOKUP_PARENT, &nd);
792b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (err)
802b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		return err;
812b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
822b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	dentry = lookup_create(&nd, 1);
832b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (!IS_ERR(dentry)) {
842b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		err = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode);
85015bf43b07158668c2f38af463939afcc6d19403Kay Sievers		if (!err)
86015bf43b07158668c2f38af463939afcc6d19403Kay Sievers			/* mark as kernel-created inode */
87015bf43b07158668c2f38af463939afcc6d19403Kay Sievers			dentry->d_inode->i_private = &dev_mnt;
882b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		dput(dentry);
892b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	} else {
902b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		err = PTR_ERR(dentry);
912b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	}
922b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
93015bf43b07158668c2f38af463939afcc6d19403Kay Sievers	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
942b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	path_put(&nd.path);
952b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return err;
962b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
972b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
982b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversstatic int create_path(const char *nodepath)
992b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
100015bf43b07158668c2f38af463939afcc6d19403Kay Sievers	int err;
1012b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
102f1f76f865b5f66db5b5c7f2d19874f2bb9b43b8dThomas Gleixner	mutex_lock(&dirlock);
103015bf43b07158668c2f38af463939afcc6d19403Kay Sievers	err = dev_mkdir(nodepath, 0755);
104015bf43b07158668c2f38af463939afcc6d19403Kay Sievers	if (err == -ENOENT) {
105ed413ae6e7813d3227eef43bc6d84ca4f4fe6b21Kay Sievers		char *path;
1062b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		char *s;
1072b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
1082b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		/* parent directories do not exist, create them */
109ed413ae6e7813d3227eef43bc6d84ca4f4fe6b21Kay Sievers		path = kstrdup(nodepath, GFP_KERNEL);
1108042273801059884da2d53bbca34575d090b6f4eKay Sievers		if (!path) {
1118042273801059884da2d53bbca34575d090b6f4eKay Sievers			err = -ENOMEM;
1128042273801059884da2d53bbca34575d090b6f4eKay Sievers			goto out;
1138042273801059884da2d53bbca34575d090b6f4eKay Sievers		}
1142b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		s = path;
115ed413ae6e7813d3227eef43bc6d84ca4f4fe6b21Kay Sievers		for (;;) {
1162b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			s = strchr(s, '/');
1172b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			if (!s)
1182b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers				break;
1192b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			s[0] = '\0';
1202b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			err = dev_mkdir(path, 0755);
1212b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			if (err && err != -EEXIST)
1222b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers				break;
1232b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			s[0] = '/';
1242b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			s++;
1252b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		}
126ed413ae6e7813d3227eef43bc6d84ca4f4fe6b21Kay Sievers		kfree(path);
1272b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	}
1288042273801059884da2d53bbca34575d090b6f4eKay Sieversout:
129f1f76f865b5f66db5b5c7f2d19874f2bb9b43b8dThomas Gleixner	mutex_unlock(&dirlock);
1302b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return err;
1312b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
1322b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
1332b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversint devtmpfs_create_node(struct device *dev)
1342b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
1352b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	const char *tmp = NULL;
1362b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	const char *nodename;
1372b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	const struct cred *curr_cred;
138e454cea20bdcff10ee698d11b8882662a0153a47Kay Sievers	mode_t mode = 0;
1392b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	struct nameidata nd;
1402b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	struct dentry *dentry;
1412b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	int err;
1422b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
1432b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (!dev_mnt)
1442b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		return 0;
1452b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
146e454cea20bdcff10ee698d11b8882662a0153a47Kay Sievers	nodename = device_get_devnode(dev, &mode, &tmp);
1472b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (!nodename)
1482b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		return -ENOMEM;
1492b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
150e454cea20bdcff10ee698d11b8882662a0153a47Kay Sievers	if (mode == 0)
151e454cea20bdcff10ee698d11b8882662a0153a47Kay Sievers		mode = 0600;
1522b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (is_blockdev(dev))
153e454cea20bdcff10ee698d11b8882662a0153a47Kay Sievers		mode |= S_IFBLK;
1542b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	else
155e454cea20bdcff10ee698d11b8882662a0153a47Kay Sievers		mode |= S_IFCHR;
1562b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
1572b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	curr_cred = override_creds(&init_cred);
1580092699643703aefca6af0aa758a73f1624d53beKay Sievers
1592b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
1602b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			      nodename, LOOKUP_PARENT, &nd);
1612b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (err == -ENOENT) {
1622b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		create_path(nodename);
1632b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
1642b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers				      nodename, LOOKUP_PARENT, &nd);
1652b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	}
1660092699643703aefca6af0aa758a73f1624d53beKay Sievers	if (err)
1670092699643703aefca6af0aa758a73f1624d53beKay Sievers		goto out;
1682b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
1692b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	dentry = lookup_create(&nd, 0);
1702b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (!IS_ERR(dentry)) {
1712b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		err = vfs_mknod(nd.path.dentry->d_inode,
1722b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers				dentry, mode, dev->devt);
1730092699643703aefca6af0aa758a73f1624d53beKay Sievers		if (!err) {
1740092699643703aefca6af0aa758a73f1624d53beKay Sievers			struct iattr newattrs;
1750092699643703aefca6af0aa758a73f1624d53beKay Sievers
1760092699643703aefca6af0aa758a73f1624d53beKay Sievers			/* fixup possibly umasked mode */
1770092699643703aefca6af0aa758a73f1624d53beKay Sievers			newattrs.ia_mode = mode;
1780092699643703aefca6af0aa758a73f1624d53beKay Sievers			newattrs.ia_valid = ATTR_MODE;
1790092699643703aefca6af0aa758a73f1624d53beKay Sievers			mutex_lock(&dentry->d_inode->i_mutex);
1800092699643703aefca6af0aa758a73f1624d53beKay Sievers			notify_change(dentry, &newattrs);
1810092699643703aefca6af0aa758a73f1624d53beKay Sievers			mutex_unlock(&dentry->d_inode->i_mutex);
1820092699643703aefca6af0aa758a73f1624d53beKay Sievers
1830092699643703aefca6af0aa758a73f1624d53beKay Sievers			/* mark as kernel-created inode */
1842b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			dentry->d_inode->i_private = &dev_mnt;
1850092699643703aefca6af0aa758a73f1624d53beKay Sievers		}
1862b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		dput(dentry);
1872b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	} else {
1882b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		err = PTR_ERR(dentry);
1892b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	}
1902b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
1910092699643703aefca6af0aa758a73f1624d53beKay Sievers	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
1922b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	path_put(&nd.path);
1932b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversout:
1942b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	kfree(tmp);
1952b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	revert_creds(curr_cred);
1962b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return err;
1972b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
1982b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
1992b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversstatic int dev_rmdir(const char *name)
2002b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
2012b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	struct nameidata nd;
2022b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	struct dentry *dentry;
2032b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	int err;
2042b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2052b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
2062b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			      name, LOOKUP_PARENT, &nd);
2072b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (err)
2082b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		return err;
2092b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2102b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
2112b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
2122b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (!IS_ERR(dentry)) {
213015bf43b07158668c2f38af463939afcc6d19403Kay Sievers		if (dentry->d_inode) {
214015bf43b07158668c2f38af463939afcc6d19403Kay Sievers			if (dentry->d_inode->i_private == &dev_mnt)
215015bf43b07158668c2f38af463939afcc6d19403Kay Sievers				err = vfs_rmdir(nd.path.dentry->d_inode,
216015bf43b07158668c2f38af463939afcc6d19403Kay Sievers						dentry);
217015bf43b07158668c2f38af463939afcc6d19403Kay Sievers			else
218015bf43b07158668c2f38af463939afcc6d19403Kay Sievers				err = -EPERM;
219015bf43b07158668c2f38af463939afcc6d19403Kay Sievers		} else {
2202b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			err = -ENOENT;
221015bf43b07158668c2f38af463939afcc6d19403Kay Sievers		}
2222b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		dput(dentry);
2232b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	} else {
2242b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		err = PTR_ERR(dentry);
2252b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	}
2262b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
227015bf43b07158668c2f38af463939afcc6d19403Kay Sievers	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
2282b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	path_put(&nd.path);
2292b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return err;
2302b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
2312b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2322b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversstatic int delete_path(const char *nodepath)
2332b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
2342b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	const char *path;
2352b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	int err = 0;
2362b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2372b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	path = kstrdup(nodepath, GFP_KERNEL);
2382b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (!path)
2392b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		return -ENOMEM;
2402b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
241f1f76f865b5f66db5b5c7f2d19874f2bb9b43b8dThomas Gleixner	mutex_lock(&dirlock);
242ed413ae6e7813d3227eef43bc6d84ca4f4fe6b21Kay Sievers	for (;;) {
2432b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		char *base;
2442b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2452b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		base = strrchr(path, '/');
2462b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		if (!base)
2472b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			break;
2482b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		base[0] = '\0';
2492b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		err = dev_rmdir(path);
2502b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		if (err)
2512b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			break;
2522b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	}
253f1f76f865b5f66db5b5c7f2d19874f2bb9b43b8dThomas Gleixner	mutex_unlock(&dirlock);
2542b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2552b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	kfree(path);
2562b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return err;
2572b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
2582b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2592b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversstatic int dev_mynode(struct device *dev, struct inode *inode, struct kstat *stat)
2602b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
2612b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	/* did we create it */
2622b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (inode->i_private != &dev_mnt)
2632b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		return 0;
2642b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2652b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	/* does the dev_t match */
2662b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (is_blockdev(dev)) {
2672b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		if (!S_ISBLK(stat->mode))
2682b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			return 0;
2692b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	} else {
2702b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		if (!S_ISCHR(stat->mode))
2712b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			return 0;
2722b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	}
2732b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (stat->rdev != dev->devt)
2742b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		return 0;
2752b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2762b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	/* ours */
2772b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return 1;
2782b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
2792b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2802b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversint devtmpfs_delete_node(struct device *dev)
2812b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
2822b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	const char *tmp = NULL;
2832b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	const char *nodename;
2842b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	const struct cred *curr_cred;
2852b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	struct nameidata nd;
2862b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	struct dentry *dentry;
2872b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	struct kstat stat;
2882b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	int deleted = 1;
2892b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	int err;
2902b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2912b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (!dev_mnt)
2922b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		return 0;
2932b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
294e454cea20bdcff10ee698d11b8882662a0153a47Kay Sievers	nodename = device_get_devnode(dev, NULL, &tmp);
2952b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (!nodename)
2962b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		return -ENOMEM;
2972b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
2982b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	curr_cred = override_creds(&init_cred);
2992b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt,
3002b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			      nodename, LOOKUP_PARENT, &nd);
3012b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (err)
3022b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		goto out;
3032b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
3042b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
3052b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
3062b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (!IS_ERR(dentry)) {
3072b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		if (dentry->d_inode) {
3082b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			err = vfs_getattr(nd.path.mnt, dentry, &stat);
3092b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			if (!err && dev_mynode(dev, dentry->d_inode, &stat)) {
3105e31d76f2817bd50258a092a7c5b15b3006fd61cKay Sievers				struct iattr newattrs;
3115e31d76f2817bd50258a092a7c5b15b3006fd61cKay Sievers				/*
3125e31d76f2817bd50258a092a7c5b15b3006fd61cKay Sievers				 * before unlinking this node, reset permissions
3135e31d76f2817bd50258a092a7c5b15b3006fd61cKay Sievers				 * of possible references like hardlinks
3145e31d76f2817bd50258a092a7c5b15b3006fd61cKay Sievers				 */
3155e31d76f2817bd50258a092a7c5b15b3006fd61cKay Sievers				newattrs.ia_uid = 0;
3165e31d76f2817bd50258a092a7c5b15b3006fd61cKay Sievers				newattrs.ia_gid = 0;
3175e31d76f2817bd50258a092a7c5b15b3006fd61cKay Sievers				newattrs.ia_mode = stat.mode & ~0777;
3185e31d76f2817bd50258a092a7c5b15b3006fd61cKay Sievers				newattrs.ia_valid =
3195e31d76f2817bd50258a092a7c5b15b3006fd61cKay Sievers					ATTR_UID|ATTR_GID|ATTR_MODE;
3205e31d76f2817bd50258a092a7c5b15b3006fd61cKay Sievers				mutex_lock(&dentry->d_inode->i_mutex);
3215e31d76f2817bd50258a092a7c5b15b3006fd61cKay Sievers				notify_change(dentry, &newattrs);
3225e31d76f2817bd50258a092a7c5b15b3006fd61cKay Sievers				mutex_unlock(&dentry->d_inode->i_mutex);
3232b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers				err = vfs_unlink(nd.path.dentry->d_inode,
3242b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers						 dentry);
3252b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers				if (!err || err == -ENOENT)
3262b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers					deleted = 1;
3272b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			}
3282b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		} else {
3292b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers			err = -ENOENT;
3302b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		}
3312b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		dput(dentry);
3322b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	} else {
3332b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		err = PTR_ERR(dentry);
3342b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	}
3352b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
3362b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
3372b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	path_put(&nd.path);
3382b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (deleted && strchr(nodename, '/'))
3392b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		delete_path(nodename);
3402b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversout:
3412b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	kfree(tmp);
3422b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	revert_creds(curr_cred);
3432b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return err;
3442b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
3452b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
3462b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers/*
3472b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers * If configured, or requested by the commandline, devtmpfs will be
3482b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers * auto-mounted after the kernel mounted the root filesystem.
3492b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers */
350073120cc28ad9f6003452c8bb9d15a87b1820201Kay Sieversint devtmpfs_mount(const char *mntdir)
3512b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
3522b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	int err;
3532b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
354fc14f2fef682df677d64a145256dbd263df2aa7bAl Viro	if (!mount_dev)
3552b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		return 0;
3562b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
3572b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (!dev_mnt)
3582b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		return 0;
3592b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
360073120cc28ad9f6003452c8bb9d15a87b1820201Kay Sievers	err = sys_mount("devtmpfs", (char *)mntdir, "devtmpfs", MS_SILENT, NULL);
3612b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (err)
3622b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		printk(KERN_INFO "devtmpfs: error mounting %i\n", err);
3632b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	else
3642b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		printk(KERN_INFO "devtmpfs: mounted\n");
3652b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return err;
3662b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
3672b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
3682b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers/*
3692b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers * Create devtmpfs instance, driver-core devices will add their device
3702b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers * nodes here.
3712b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers */
3722b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sieversint __init devtmpfs_init(void)
3732b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers{
3742b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	int err;
3752b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	struct vfsmount *mnt;
376f776c5ec4690b21b3668ad5956774a22c86f541aHeiko Carstens	char options[] = "mode=0755";
3772b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
3782b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	err = register_filesystem(&dev_fs_type);
3792b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (err) {
3802b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		printk(KERN_ERR "devtmpfs: unable to register devtmpfs "
3812b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		       "type %i\n", err);
3822b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		return err;
3832b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	}
3842b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
385f776c5ec4690b21b3668ad5956774a22c86f541aHeiko Carstens	mnt = kern_mount_data(&dev_fs_type, options);
3862b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	if (IS_ERR(mnt)) {
3872b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		err = PTR_ERR(mnt);
3882b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		printk(KERN_ERR "devtmpfs: unable to create devtmpfs %i\n", err);
3892b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		unregister_filesystem(&dev_fs_type);
3902b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers		return err;
3912b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	}
3922b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	dev_mnt = mnt;
3932b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers
3942b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	printk(KERN_INFO "devtmpfs: initialized\n");
3952b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers	return 0;
3962b2af54a5bb6f7e80ccf78f20084b93c398c3a8bKay Sievers}
397