mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
vfs: make vfs_mknod break delegations on parent directory
In order to add directory delegation support, we need to break delegations on the parent whenever there is going to be a change in the directory. Add a new delegated_inode pointer to vfs_mknod() and have the appropriate callers wait when there is an outstanding delegation. All other callers just set the pointer to NULL. Reviewed-by: Jan Kara <jack@suse.cz> Reviewed-by: NeilBrown <neil@brown.name> Signed-off-by: Jeff Layton <jlayton@kernel.org> Link: https://patch.msgid.link/20251111-dir-deleg-ro-v6-11-52f3feebb2f2@kernel.org Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
parent
c826229c6a
commit
e8960c1b2e
|
|
@ -231,7 +231,7 @@ static int handle_create(const char *nodename, umode_t mode, kuid_t uid,
|
||||||
return PTR_ERR(dentry);
|
return PTR_ERR(dentry);
|
||||||
|
|
||||||
err = vfs_mknod(&nop_mnt_idmap, d_inode(path.dentry), dentry, mode,
|
err = vfs_mknod(&nop_mnt_idmap, d_inode(path.dentry), dentry, mode,
|
||||||
dev->devt);
|
dev->devt, NULL);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
struct iattr newattrs;
|
struct iattr newattrs;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -564,7 +564,7 @@ ecryptfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
|
||||||
rc = lock_parent(dentry, &lower_dentry, &lower_dir);
|
rc = lock_parent(dentry, &lower_dentry, &lower_dir);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
rc = vfs_mknod(&nop_mnt_idmap, lower_dir,
|
rc = vfs_mknod(&nop_mnt_idmap, lower_dir,
|
||||||
lower_dentry, mode, dev);
|
lower_dentry, mode, dev, NULL);
|
||||||
if (rc || d_really_is_negative(lower_dentry))
|
if (rc || d_really_is_negative(lower_dentry))
|
||||||
goto out;
|
goto out;
|
||||||
rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb);
|
rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb);
|
||||||
|
|
|
||||||
|
|
@ -157,7 +157,7 @@ int __init init_mknod(const char *filename, umode_t mode, unsigned int dev)
|
||||||
error = security_path_mknod(&path, dentry, mode, dev);
|
error = security_path_mknod(&path, dentry, mode, dev);
|
||||||
if (!error)
|
if (!error)
|
||||||
error = vfs_mknod(mnt_idmap(path.mnt), path.dentry->d_inode,
|
error = vfs_mknod(mnt_idmap(path.mnt), path.dentry->d_inode,
|
||||||
dentry, mode, new_decode_dev(dev));
|
dentry, mode, new_decode_dev(dev), NULL);
|
||||||
end_creating_path(&path, dentry);
|
end_creating_path(&path, dentry);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
23
fs/namei.c
23
fs/namei.c
|
|
@ -4295,13 +4295,15 @@ inline struct dentry *start_creating_user_path(
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(start_creating_user_path);
|
EXPORT_SYMBOL(start_creating_user_path);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* vfs_mknod - create device node or file
|
* vfs_mknod - create device node or file
|
||||||
* @idmap: idmap of the mount the inode was found from
|
* @idmap: idmap of the mount the inode was found from
|
||||||
* @dir: inode of the parent directory
|
* @dir: inode of the parent directory
|
||||||
* @dentry: dentry of the child device node
|
* @dentry: dentry of the child device node
|
||||||
* @mode: mode of the child device node
|
* @mode: mode of the child device node
|
||||||
* @dev: device number of device to create
|
* @dev: device number of device to create
|
||||||
|
* @delegated_inode: returns parent inode, if the inode is delegated.
|
||||||
*
|
*
|
||||||
* Create a device node or file.
|
* Create a device node or file.
|
||||||
*
|
*
|
||||||
|
|
@ -4312,7 +4314,8 @@ EXPORT_SYMBOL(start_creating_user_path);
|
||||||
* raw inode simply pass @nop_mnt_idmap.
|
* raw inode simply pass @nop_mnt_idmap.
|
||||||
*/
|
*/
|
||||||
int vfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
|
int vfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
|
||||||
struct dentry *dentry, umode_t mode, dev_t dev)
|
struct dentry *dentry, umode_t mode, dev_t dev,
|
||||||
|
struct delegated_inode *delegated_inode)
|
||||||
{
|
{
|
||||||
bool is_whiteout = S_ISCHR(mode) && dev == WHITEOUT_DEV;
|
bool is_whiteout = S_ISCHR(mode) && dev == WHITEOUT_DEV;
|
||||||
int error = may_create(idmap, dir, dentry);
|
int error = may_create(idmap, dir, dentry);
|
||||||
|
|
@ -4336,6 +4339,10 @@ int vfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
|
error = try_break_deleg(dir, delegated_inode);
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
|
||||||
error = dir->i_op->mknod(idmap, dir, dentry, mode, dev);
|
error = dir->i_op->mknod(idmap, dir, dentry, mode, dev);
|
||||||
if (!error)
|
if (!error)
|
||||||
fsnotify_create(dir, dentry);
|
fsnotify_create(dir, dentry);
|
||||||
|
|
@ -4393,11 +4400,11 @@ static int do_mknodat(int dfd, struct filename *name, umode_t mode,
|
||||||
break;
|
break;
|
||||||
case S_IFCHR: case S_IFBLK:
|
case S_IFCHR: case S_IFBLK:
|
||||||
error = vfs_mknod(idmap, path.dentry->d_inode,
|
error = vfs_mknod(idmap, path.dentry->d_inode,
|
||||||
dentry, mode, new_decode_dev(dev));
|
dentry, mode, new_decode_dev(dev), &di);
|
||||||
break;
|
break;
|
||||||
case S_IFIFO: case S_IFSOCK:
|
case S_IFIFO: case S_IFSOCK:
|
||||||
error = vfs_mknod(idmap, path.dentry->d_inode,
|
error = vfs_mknod(idmap, path.dentry->d_inode,
|
||||||
dentry, mode, 0);
|
dentry, mode, 0, &di);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
out2:
|
out2:
|
||||||
|
|
|
||||||
|
|
@ -1573,7 +1573,7 @@ nfsd_create_locked(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
||||||
case S_IFIFO:
|
case S_IFIFO:
|
||||||
case S_IFSOCK:
|
case S_IFSOCK:
|
||||||
host_err = vfs_mknod(&nop_mnt_idmap, dirp, dchild,
|
host_err = vfs_mknod(&nop_mnt_idmap, dirp, dchild,
|
||||||
iap->ia_mode, rdev);
|
iap->ia_mode, rdev, NULL);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk(KERN_WARNING "nfsd: bad file type %o in nfsd_create\n",
|
printk(KERN_WARNING "nfsd: bad file type %o in nfsd_create\n",
|
||||||
|
|
|
||||||
|
|
@ -257,7 +257,7 @@ static inline int ovl_do_mknod(struct ovl_fs *ofs,
|
||||||
struct inode *dir, struct dentry *dentry,
|
struct inode *dir, struct dentry *dentry,
|
||||||
umode_t mode, dev_t dev)
|
umode_t mode, dev_t dev)
|
||||||
{
|
{
|
||||||
int err = vfs_mknod(ovl_upper_mnt_idmap(ofs), dir, dentry, mode, dev);
|
int err = vfs_mknod(ovl_upper_mnt_idmap(ofs), dir, dentry, mode, dev, NULL);
|
||||||
|
|
||||||
pr_debug("mknod(%pd2, 0%o, 0%o) = %i\n", dentry, mode, dev, err);
|
pr_debug("mknod(%pd2, 0%o, 0%o) = %i\n", dentry, mode, dev, err);
|
||||||
return err;
|
return err;
|
||||||
|
|
|
||||||
|
|
@ -2116,7 +2116,7 @@ int vfs_create(struct mnt_idmap *, struct dentry *, umode_t,
|
||||||
struct dentry *vfs_mkdir(struct mnt_idmap *, struct inode *,
|
struct dentry *vfs_mkdir(struct mnt_idmap *, struct inode *,
|
||||||
struct dentry *, umode_t, struct delegated_inode *);
|
struct dentry *, umode_t, struct delegated_inode *);
|
||||||
int vfs_mknod(struct mnt_idmap *, struct inode *, struct dentry *,
|
int vfs_mknod(struct mnt_idmap *, struct inode *, struct dentry *,
|
||||||
umode_t, dev_t);
|
umode_t, dev_t, struct delegated_inode *);
|
||||||
int vfs_symlink(struct mnt_idmap *, struct inode *,
|
int vfs_symlink(struct mnt_idmap *, struct inode *,
|
||||||
struct dentry *, const char *);
|
struct dentry *, const char *);
|
||||||
int vfs_link(struct dentry *, struct mnt_idmap *, struct inode *,
|
int vfs_link(struct dentry *, struct mnt_idmap *, struct inode *,
|
||||||
|
|
@ -2152,7 +2152,7 @@ static inline int vfs_whiteout(struct mnt_idmap *idmap,
|
||||||
struct inode *dir, struct dentry *dentry)
|
struct inode *dir, struct dentry *dentry)
|
||||||
{
|
{
|
||||||
return vfs_mknod(idmap, dir, dentry, S_IFCHR | WHITEOUT_MODE,
|
return vfs_mknod(idmap, dir, dentry, S_IFCHR | WHITEOUT_MODE,
|
||||||
WHITEOUT_DEV);
|
WHITEOUT_DEV, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct file *kernel_tmpfile_open(struct mnt_idmap *idmap,
|
struct file *kernel_tmpfile_open(struct mnt_idmap *idmap,
|
||||||
|
|
|
||||||
|
|
@ -1399,7 +1399,7 @@ static int unix_bind_bsd(struct sock *sk, struct sockaddr_un *sunaddr,
|
||||||
idmap = mnt_idmap(parent.mnt);
|
idmap = mnt_idmap(parent.mnt);
|
||||||
err = security_path_mknod(&parent, dentry, mode, 0);
|
err = security_path_mknod(&parent, dentry, mode, 0);
|
||||||
if (!err)
|
if (!err)
|
||||||
err = vfs_mknod(idmap, d_inode(parent.dentry), dentry, mode, 0);
|
err = vfs_mknod(idmap, d_inode(parent.dentry), dentry, mode, 0, NULL);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_path;
|
goto out_path;
|
||||||
err = mutex_lock_interruptible(&u->bindlock);
|
err = mutex_lock_interruptible(&u->bindlock);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user