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