^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * devtmpfs - kernel-maintained tmpfs-based /dev
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2009, Kay Sievers <kay.sievers@vrfy.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * During bootup, before any driver core device is registered,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * devtmpfs, a tmpfs-based filesystem is created. Every driver-core
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * device which requests a device node, will add a node in this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * filesystem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * By default, all devices are named after the name of the device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * owned by root and have a default mode of 0600. Subsystems can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * overwrite the default setting if needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/syscalls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/mount.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/genhd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/namei.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/shmem_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/ramfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/kthread.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/init_syscalls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <uapi/linux/mount.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include "base.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static struct task_struct *thread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static int __initdata mount_dev = IS_ENABLED(CONFIG_DEVTMPFS_MOUNT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static DEFINE_SPINLOCK(req_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static struct req {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct req *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct completion done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) umode_t mode; /* 0 => delete */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) kuid_t uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) kgid_t gid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) } *requests;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) static int __init mount_param(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) mount_dev = simple_strtoul(str, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) __setup("devtmpfs.mount=", mount_param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static struct vfsmount *mnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static struct dentry *public_dev_mount(struct file_system_type *fs_type, int flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) const char *dev_name, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct super_block *s = mnt->mnt_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) atomic_inc(&s->s_active);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) down_write(&s->s_umount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) err = reconfigure_single(s, flags, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) deactivate_locked_super(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return dget(s->s_root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static struct file_system_type internal_fs_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) .name = "devtmpfs",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #ifdef CONFIG_TMPFS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) .init_fs_context = shmem_init_fs_context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) .parameters = shmem_fs_parameters,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) .init_fs_context = ramfs_init_fs_context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) .parameters = ramfs_fs_parameters,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) .kill_sb = kill_litter_super,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static struct file_system_type dev_fs_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) .name = "devtmpfs",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) .mount = public_dev_mount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #ifdef CONFIG_BLOCK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static inline int is_blockdev(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return dev->class == &block_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static inline int is_blockdev(struct device *dev) { return 0; }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static int devtmpfs_submit_req(struct req *req, const char *tmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) init_completion(&req->done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) spin_lock(&req_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) req->next = requests;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) requests = req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) spin_unlock(&req_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) wake_up_process(thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) wait_for_completion(&req->done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) kfree(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return req->err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) int devtmpfs_create_node(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) const char *tmp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct req req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (!thread)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) req.mode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) req.uid = GLOBAL_ROOT_UID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) req.gid = GLOBAL_ROOT_GID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) req.name = device_get_devnode(dev, &req.mode, &req.uid, &req.gid, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (!req.name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (req.mode == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) req.mode = 0600;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (is_blockdev(dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) req.mode |= S_IFBLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) req.mode |= S_IFCHR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) req.dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return devtmpfs_submit_req(&req, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) int devtmpfs_delete_node(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) const char *tmp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct req req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (!thread)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) req.name = device_get_devnode(dev, NULL, NULL, NULL, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (!req.name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) req.mode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) req.dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return devtmpfs_submit_req(&req, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) static int dev_mkdir(const char *name, umode_t mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) struct dentry *dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct path path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) dentry = kern_path_create(AT_FDCWD, name, &path, LOOKUP_DIRECTORY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (IS_ERR(dentry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return PTR_ERR(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) err = vfs_mkdir(d_inode(path.dentry), dentry, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) /* mark as kernel-created inode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) d_inode(dentry)->i_private = &thread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) done_path_create(&path, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) static int create_path(const char *nodepath)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) char *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) char *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) /* parent directories do not exist, create them */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) path = kstrdup(nodepath, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (!path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) s = path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) s = strchr(s, '/');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (!s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) s[0] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) err = dev_mkdir(path, 0755);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (err && err != -EEXIST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) s[0] = '/';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) s++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) kfree(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) static int handle_create(const char *nodename, umode_t mode, kuid_t uid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) kgid_t gid, struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) struct dentry *dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) struct path path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) dentry = kern_path_create(AT_FDCWD, nodename, &path, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (dentry == ERR_PTR(-ENOENT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) create_path(nodename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) dentry = kern_path_create(AT_FDCWD, nodename, &path, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (IS_ERR(dentry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) return PTR_ERR(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) err = vfs_mknod(d_inode(path.dentry), dentry, mode, dev->devt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (!err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) struct iattr newattrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) newattrs.ia_mode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) newattrs.ia_uid = uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) newattrs.ia_gid = gid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) newattrs.ia_valid = ATTR_MODE|ATTR_UID|ATTR_GID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) inode_lock(d_inode(dentry));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) notify_change(dentry, &newattrs, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) inode_unlock(d_inode(dentry));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) /* mark as kernel-created inode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) d_inode(dentry)->i_private = &thread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) done_path_create(&path, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) static int dev_rmdir(const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) struct path parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) struct dentry *dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) dentry = kern_path_locked(name, &parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (IS_ERR(dentry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return PTR_ERR(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (d_really_is_positive(dentry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (d_inode(dentry)->i_private == &thread)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) err = vfs_rmdir(d_inode(parent.dentry), dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) err = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) err = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) dput(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) inode_unlock(d_inode(parent.dentry));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) path_put(&parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) static int delete_path(const char *nodepath)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) char *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) path = kstrdup(nodepath, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (!path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) char *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) base = strrchr(path, '/');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (!base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) base[0] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) err = dev_rmdir(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) kfree(path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) static int dev_mynode(struct device *dev, struct inode *inode, struct kstat *stat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /* did we create it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (inode->i_private != &thread)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) /* does the dev_t match */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (is_blockdev(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (!S_ISBLK(stat->mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (!S_ISCHR(stat->mode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (stat->rdev != dev->devt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) /* ours */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) static int handle_remove(const char *nodename, struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) struct path parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) struct dentry *dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) int deleted = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) dentry = kern_path_locked(nodename, &parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (IS_ERR(dentry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) return PTR_ERR(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (d_really_is_positive(dentry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) struct kstat stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) struct path p = {.mnt = parent.mnt, .dentry = dentry};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) err = vfs_getattr(&p, &stat, STATX_TYPE | STATX_MODE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) AT_STATX_SYNC_AS_STAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (!err && dev_mynode(dev, d_inode(dentry), &stat)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) struct iattr newattrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) * before unlinking this node, reset permissions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) * of possible references like hardlinks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) newattrs.ia_uid = GLOBAL_ROOT_UID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) newattrs.ia_gid = GLOBAL_ROOT_GID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) newattrs.ia_mode = stat.mode & ~0777;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) newattrs.ia_valid =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) ATTR_UID|ATTR_GID|ATTR_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) inode_lock(d_inode(dentry));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) notify_change(dentry, &newattrs, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) inode_unlock(d_inode(dentry));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) err = vfs_unlink(d_inode(parent.dentry), dentry, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (!err || err == -ENOENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) deleted = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) err = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) dput(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) inode_unlock(d_inode(parent.dentry));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) path_put(&parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (deleted && strchr(nodename, '/'))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) delete_path(nodename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * If configured, or requested by the commandline, devtmpfs will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * auto-mounted after the kernel mounted the root filesystem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) int __init devtmpfs_mount(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (!mount_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (!thread)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) err = init_mount("devtmpfs", "dev", "devtmpfs", MS_SILENT, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) printk(KERN_INFO "devtmpfs: error mounting %i\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) printk(KERN_INFO "devtmpfs: mounted\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) static DECLARE_COMPLETION(setup_done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) static int handle(const char *name, umode_t mode, kuid_t uid, kgid_t gid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) return handle_create(name, mode, uid, gid, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return handle_remove(name, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static void __noreturn devtmpfs_work_loop(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) spin_lock(&req_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) while (requests) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) struct req *req = requests;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) requests = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) spin_unlock(&req_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) while (req) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) struct req *next = req->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) req->err = handle(req->name, req->mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) req->uid, req->gid, req->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) complete(&req->done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) req = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) spin_lock(&req_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) __set_current_state(TASK_INTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) spin_unlock(&req_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) static int __init devtmpfs_setup(void *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) err = ksys_unshare(CLONE_NEWNS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) err = init_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) init_chdir("/.."); /* will traverse into overmounted root */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) init_chroot(".");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) *(int *)p = err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) * The __ref is because devtmpfs_setup needs to be __init for the routines it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) * calls. That call is done while devtmpfs_init, which is marked __init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) * synchronously waits for it to complete.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) static int __ref devtmpfsd(void *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) int err = devtmpfs_setup(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) complete(&setup_done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) devtmpfs_work_loop();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) * Create devtmpfs instance, driver-core devices will add their device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) * nodes here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) int __init devtmpfs_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) char opts[] = "mode=0755";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) mnt = vfs_kern_mount(&internal_fs_type, 0, "devtmpfs", opts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) if (IS_ERR(mnt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) printk(KERN_ERR "devtmpfs: unable to create devtmpfs %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) PTR_ERR(mnt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return PTR_ERR(mnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) err = register_filesystem(&dev_fs_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) printk(KERN_ERR "devtmpfs: unable to register devtmpfs "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) "type %i\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) thread = kthread_run(devtmpfsd, &err, "kdevtmpfs");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (!IS_ERR(thread)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) wait_for_completion(&setup_done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) err = PTR_ERR(thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) thread = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) printk(KERN_ERR "devtmpfs: unable to create devtmpfs %i\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) unregister_filesystem(&dev_fs_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) printk(KERN_INFO "devtmpfs: initialized\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) }