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; }
static int handle_remove(const char *nodename, struct device *dev) { struct nameidata nd; struct dentry *dentry; struct kstat stat; int deleted = 1; int err; err = kern_path_parent(nodename, &nd); if (err) return err; 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); return err; }
/*! 2017. 8.12 study -ing */ static int handle_remove(const char *nodename, struct device *dev) { struct path parent; struct dentry *dentry; int deleted = 0; int err; dentry = kern_path_locked(nodename, &parent); if (IS_ERR(dentry)) return PTR_ERR(dentry); if (dentry->d_inode) { struct kstat stat; struct path p = {.mnt = parent.mnt, .dentry = dentry}; err = vfs_getattr(&p, &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 = GLOBAL_ROOT_UID; newattrs.ia_gid = GLOBAL_ROOT_GID; 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, NULL); mutex_unlock(&dentry->d_inode->i_mutex); err = vfs_unlink(parent.dentry->d_inode, dentry, NULL); if (!err || err == -ENOENT) deleted = 1; } } else { err = -ENOENT; } dput(dentry); mutex_unlock(&parent.dentry->d_inode->i_mutex); path_put(&parent); if (deleted && strchr(nodename, '/')) delete_path(nodename); return 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; }