// SPDX-License-Identifier: GPL-2.0 /* * devtmpfs - kernel-maintained tmpfs-based /dev * * Copyright (C) 2009, Kay Sievers <kay.sievers@vrfy.org> * * During bootup, before any driver core device is registered, * devtmpfs, a tmpfs-based filesystem is created. Every driver-core * device which requests a device node, will add a node in this * filesystem. * By default, all devices are named after the name of the device, * owned by root and have a default mode of 0600. Subsystems can * overwrite the default setting if needed.
*/
/* Ops are filled in during init depending on underlying shmem or ramfs type */ struct fs_context_operations devtmpfs_context_ops = {};
/* Call the underlying initialization and set to our ops */ staticint devtmpfs_init_fs_context(struct fs_context *fc)
{ int ret; #ifdef CONFIG_TMPFS
ret = shmem_init_fs_context(fc); #else
ret = ramfs_init_fs_context(fc); #endif if (ret < 0) return ret;
staticint delete_path(constchar *nodepath)
{ char *path; int err = 0;
path = kstrdup(nodepath, GFP_KERNEL); if (!path) return -ENOMEM;
for (;;) { char *base;
base = strrchr(path, '/'); if (!base) break;
base[0] = '\0';
err = dev_rmdir(path); if (err) break;
}
kfree(path); return err;
}
staticint dev_mynode(struct device *dev, struct inode *inode)
{ /* did we create it */ if (inode->i_private != &thread) return 0;
/* does the dev_t match */ if (is_blockdev(dev)) { if (!S_ISBLK(inode->i_mode)) return 0;
} else { if (!S_ISCHR(inode->i_mode)) return 0;
} if (inode->i_rdev != dev->devt) return 0;
dentry = kern_path_locked(nodename, &parent); if (IS_ERR(dentry)) return PTR_ERR(dentry);
inode = d_inode(dentry); if (dev_mynode(dev, inode)) { struct iattr newattrs; /* * before unlinking this node, reset permissions * of possible references like hardlinks
*/
newattrs.ia_uid = GLOBAL_ROOT_UID;
newattrs.ia_gid = GLOBAL_ROOT_GID;
newattrs.ia_mode = inode->i_mode & ~0777;
newattrs.ia_valid =
ATTR_UID|ATTR_GID|ATTR_MODE;
inode_lock(d_inode(dentry));
notify_change(&nop_mnt_idmap, dentry, &newattrs, NULL);
inode_unlock(d_inode(dentry));
err = vfs_unlink(&nop_mnt_idmap, d_inode(parent.dentry),
dentry, NULL); if (!err || err == -ENOENT)
deleted = 1;
}
dput(dentry);
inode_unlock(d_inode(parent.dentry));
path_put(&parent); if (deleted && strchr(nodename, '/'))
delete_path(nodename); return err;
}
/* * If configured, or requested by the commandline, devtmpfs will be * auto-mounted after the kernel mounted the root filesystem.
*/ int __init devtmpfs_mount(void)
{ int err;
static noinline int __init devtmpfs_setup(void *p)
{ int err;
err = ksys_unshare(CLONE_NEWNS); if (err) goto out;
err = init_mount("devtmpfs", "/", "devtmpfs", DEVTMPFS_MFLAGS, NULL); if (err) goto out;
init_chdir("/.."); /* will traverse into overmounted root */
init_chroot(".");
out:
*(int *)p = err; return err;
}
/* * The __ref is because devtmpfs_setup needs to be __init for the routines it * calls. That call is done while devtmpfs_init, which is marked __init, * synchronously waits for it to complete.
*/ staticint __ref devtmpfsd(void *p)
{ int err = devtmpfs_setup(p);
complete(&setup_done); if (err) return err;
devtmpfs_work_loop(); return 0;
}
/* * Get the underlying (shmem/ramfs) context ops to build ours
*/ staticint devtmpfs_configure_context(void)
{ struct fs_context *fc;
fc = fs_context_for_reconfigure(mnt->mnt_root, mnt->mnt_sb->s_flags,
MS_RMT_MASK); if (IS_ERR(fc)) return PTR_ERR(fc);
/* Set up devtmpfs_context_ops based on underlying type */
devtmpfs_context_ops.free = fc->ops->free;
devtmpfs_context_ops.dup = fc->ops->dup;
devtmpfs_context_ops.parse_param = fc->ops->parse_param;
devtmpfs_context_ops.parse_monolithic = fc->ops->parse_monolithic;
devtmpfs_context_ops.get_tree = &devtmpfs_get_tree;
devtmpfs_context_ops.reconfigure = fc->ops->reconfigure;
put_fs_context(fc);
return 0;
}
/* * Create devtmpfs instance, driver-core devices will add their device * nodes here.
*/ int __init devtmpfs_init(void)
{ char opts[] = "mode=0755"; int err;
mnt = vfs_kern_mount(&internal_fs_type, 0, "devtmpfs", opts); if (IS_ERR(mnt)) {
pr_err("unable to create devtmpfs %ld\n", PTR_ERR(mnt)); return PTR_ERR(mnt);
}
err = devtmpfs_configure_context(); if (err) {
pr_err("unable to configure devtmpfs type %d\n", err); return err;
}
err = register_filesystem(&dev_fs_type); if (err) {
pr_err("unable to register devtmpfs type %d\n", err); return err;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.