int devtmpfs_delete_node(struct device *dev) { const char *tmp = NULL; struct req req; if (!thread) return 0; req.name = device_get_devnode(dev, NULL, &tmp); if (!req.name) return -ENOMEM; req.mode = 0; req.dev = dev; init_completion(&req.done); spin_lock(&req_lock); req.next = requests; requests = &req; spin_unlock(&req_lock); wake_up_process(thread); wait_for_completion(&req.done); kfree(tmp); return req.err; }
int devtmpfs_delete_node(struct device *dev) { const char *tmp = NULL; const char *nodename; const struct cred *curr_cred; struct nameidata nd; struct dentry *dentry; struct kstat stat; int deleted = 1; int err; if (!dev_mnt) return 0; nodename = device_get_devnode(dev, NULL, &tmp); if (!nodename) return -ENOMEM; curr_cred = override_creds(&init_cred); err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt, nodename, LOOKUP_PARENT, &nd); if (err) goto out; mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len); if (!IS_ERR(dentry)) { if (dentry->d_inode) { err = vfs_getattr(nd.path.mnt, dentry, &stat); if (!err && dev_mynode(dev, dentry->d_inode, &stat)) { err = vfs_unlink(nd.path.dentry->d_inode, dentry); if (!err || err == -ENOENT) deleted = 1; } } else { err = -ENOENT; } dput(dentry); } else { err = PTR_ERR(dentry); } mutex_unlock(&nd.path.dentry->d_inode->i_mutex); path_put(&nd.path); if (deleted && strchr(nodename, '/')) delete_path(nodename); out: kfree(tmp); revert_creds(curr_cred); return err; }
int devtmpfs_create_node(struct device *dev) { const char *tmp = NULL; struct req req; if (!thread) return 0; req.mode = 0; req.uid = GLOBAL_ROOT_UID; req.gid = GLOBAL_ROOT_GID; req.name = device_get_devnode(dev, &req.mode, &req.uid, &req.gid, &tmp); if (!req.name) return -ENOMEM; if (req.mode == 0) req.mode = 0600; if (is_blockdev(dev)) req.mode |= S_IFBLK; else req.mode |= S_IFCHR; req.dev = dev; init_completion(&req.done); spin_lock(&req_lock); req.next = requests; requests = &req; spin_unlock(&req_lock); wake_up_process(thread); wait_for_completion(&req.done); kfree(tmp); return req.err; }
int devtmpfs_delete_node(struct device *dev) { const char *tmp = NULL; const char *nodename; const struct cred *curr_cred; struct nameidata nd; struct dentry *dentry; struct kstat stat; int deleted = 1; int err; if (!dev_mnt) return 0; nodename = device_get_devnode(dev, NULL, &tmp); if (!nodename) return -ENOMEM; curr_cred = override_creds(&init_cred); err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt, nodename, LOOKUP_PARENT, &nd); if (err) goto out; mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len); if (!IS_ERR(dentry)) { if (dentry->d_inode) { err = vfs_getattr(nd.path.mnt, dentry, &stat); if (!err && dev_mynode(dev, dentry->d_inode, &stat)) { struct iattr newattrs; /* * before unlinking this node, reset permissions * of possible references like hardlinks */ newattrs.ia_uid = 0; newattrs.ia_gid = 0; newattrs.ia_mode = stat.mode & ~0777; newattrs.ia_valid = ATTR_UID|ATTR_GID|ATTR_MODE; mutex_lock(&dentry->d_inode->i_mutex); notify_change(dentry, &newattrs); mutex_unlock(&dentry->d_inode->i_mutex); err = vfs_unlink(nd.path.dentry->d_inode, dentry); if (!err || err == -ENOENT) deleted = 1; } } else { err = -ENOENT; } dput(dentry); } else { err = PTR_ERR(dentry); } mutex_unlock(&nd.path.dentry->d_inode->i_mutex); path_put(&nd.path); if (deleted && strchr(nodename, '/')) delete_path(nodename); out: kfree(tmp); revert_creds(curr_cred); return err; }
int devtmpfs_create_node(struct device *dev) { const char *tmp = NULL; const char *nodename; const struct cred *curr_cred; mode_t mode = 0; struct nameidata nd; struct dentry *dentry; int err; if (!dev_mnt) return 0; nodename = device_get_devnode(dev, &mode, &tmp); if (!nodename) return -ENOMEM; if (mode == 0) mode = 0600; if (is_blockdev(dev)) mode |= S_IFBLK; else mode |= S_IFCHR; curr_cred = override_creds(&init_cred); err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt, nodename, LOOKUP_PARENT, &nd); if (err == -ENOENT) { create_path(nodename); err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt, nodename, LOOKUP_PARENT, &nd); } if (err) goto out; dentry = lookup_create(&nd, 0); if (!IS_ERR(dentry)) { err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, dev->devt); if (!err) { struct iattr newattrs; /* fixup possibly umasked mode */ newattrs.ia_mode = mode; newattrs.ia_valid = ATTR_MODE; mutex_lock(&dentry->d_inode->i_mutex); notify_change(dentry, &newattrs); mutex_unlock(&dentry->d_inode->i_mutex); /* mark as kernel-created inode */ dentry->d_inode->i_private = &dev_mnt; } dput(dentry); } else { err = PTR_ERR(dentry); } mutex_unlock(&nd.path.dentry->d_inode->i_mutex); path_put(&nd.path); out: kfree(tmp); revert_creds(curr_cred); return err; }
int devtmpfs_create_node(struct device *dev) { const char *tmp = NULL; const char *nodename; const struct cred *curr_cred; struct user_beancounter *curr_ub; mode_t mode = 0; struct nameidata nd; struct dentry *dentry; int err; struct vfsmount *dev_mnt = ve_devmnt(); if (!dev_mnt) return 0; nodename = device_get_devnode(dev, &mode, &tmp); if (!nodename) return -ENOMEM; if (mode == 0) mode = 0600; if (is_blockdev(dev)) mode |= S_IFBLK; else mode |= S_IFCHR; curr_ub = set_exec_ub(&ub0); curr_cred = override_creds(&init_cred); err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt, nodename, LOOKUP_PARENT, &nd); if (err == -ENOENT) { /* create missing parent directories */ create_path(nodename); err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt, nodename, LOOKUP_PARENT, &nd); if (err) goto out; } dentry = lookup_create(&nd, 0); if (!IS_ERR(dentry)) { int umask; umask = sys_umask(0000); err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, dev->devt); sys_umask(umask); /* mark as kernel created inode */ if (!err) dentry->d_inode->i_private = &dev_mnt; dput(dentry); } else { err = PTR_ERR(dentry); } mutex_unlock(&nd.path.dentry->d_inode->i_mutex); path_put(&nd.path); out: kfree(tmp); revert_creds(curr_cred); (void)set_exec_ub(curr_ub); return err; }