Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

vfs: make vfs_create 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 delegated_inode parameter to vfs_create. Most callers are
converted to pass in NULL, but do_mknodat() is changed to wait for a
delegation break if there is one.

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-10-52f3feebb2f2@kernel.org
Signed-off-by: Christian Brauner <brauner@kernel.org>

authored by

Jeff Layton and committed by
Christian Brauner
c826229c 85bbffca

+21 -9
+1 -1
fs/ecryptfs/inode.c
··· 188 188 189 189 rc = lock_parent(ecryptfs_dentry, &lower_dentry, &lower_dir); 190 190 if (!rc) 191 - rc = vfs_create(&nop_mnt_idmap, lower_dentry, mode); 191 + rc = vfs_create(&nop_mnt_idmap, lower_dentry, mode, NULL); 192 192 if (rc) { 193 193 printk(KERN_ERR "%s: Failure to create dentry in lower fs; " 194 194 "rc = [%d]\n", __func__, rc);
+13 -2
fs/namei.c
··· 3463 3463 * @idmap: idmap of the mount the inode was found from 3464 3464 * @dentry: dentry of the child file 3465 3465 * @mode: mode of the child file 3466 + * @di: returns parent inode, if the inode is delegated. 3466 3467 * 3467 3468 * Create a new file. 3468 3469 * ··· 3473 3472 * On non-idmapped mounts or if permission checking is to be performed on the 3474 3473 * raw inode simply pass @nop_mnt_idmap. 3475 3474 */ 3476 - int vfs_create(struct mnt_idmap *idmap, struct dentry *dentry, umode_t mode) 3475 + int vfs_create(struct mnt_idmap *idmap, struct dentry *dentry, umode_t mode, 3476 + struct delegated_inode *di) 3477 3477 { 3478 3478 struct inode *dir = d_inode(dentry->d_parent); 3479 3479 int error; ··· 3488 3486 3489 3487 mode = vfs_prepare_mode(idmap, dir, mode, S_IALLUGO, S_IFREG); 3490 3488 error = security_inode_create(dir, dentry, mode); 3489 + if (error) 3490 + return error; 3491 + error = try_break_deleg(dir, di); 3491 3492 if (error) 3492 3493 return error; 3493 3494 error = dir->i_op->create(idmap, dir, dentry, mode, true); ··· 4363 4358 static int do_mknodat(int dfd, struct filename *name, umode_t mode, 4364 4359 unsigned int dev) 4365 4360 { 4361 + struct delegated_inode di = { }; 4366 4362 struct mnt_idmap *idmap; 4367 4363 struct dentry *dentry; 4368 4364 struct path path; ··· 4387 4381 idmap = mnt_idmap(path.mnt); 4388 4382 switch (mode & S_IFMT) { 4389 4383 case 0: case S_IFREG: 4390 - error = vfs_create(idmap, dentry, mode); 4384 + error = vfs_create(idmap, dentry, mode, &di); 4391 4385 if (!error) 4392 4386 security_path_post_mknod(idmap, dentry); 4393 4387 break; ··· 4402 4396 } 4403 4397 out2: 4404 4398 end_creating_path(&path, dentry); 4399 + if (is_delegated(&di)) { 4400 + error = break_deleg_wait(&di); 4401 + if (!error) 4402 + goto retry; 4403 + } 4405 4404 if (retry_estale(error, lookup_flags)) { 4406 4405 lookup_flags |= LOOKUP_REVAL; 4407 4406 goto retry;
+1 -1
fs/nfsd/nfs3proc.c
··· 344 344 status = fh_fill_pre_attrs(fhp); 345 345 if (status != nfs_ok) 346 346 goto out; 347 - host_err = vfs_create(&nop_mnt_idmap, child, iap->ia_mode); 347 + host_err = vfs_create(&nop_mnt_idmap, child, iap->ia_mode, NULL); 348 348 if (host_err < 0) { 349 349 status = nfserrno(host_err); 350 350 goto out;
+1 -1
fs/nfsd/vfs.c
··· 1552 1552 err = 0; 1553 1553 switch (type) { 1554 1554 case S_IFREG: 1555 - host_err = vfs_create(&nop_mnt_idmap, dchild, iap->ia_mode); 1555 + host_err = vfs_create(&nop_mnt_idmap, dchild, iap->ia_mode, NULL); 1556 1556 if (!host_err) 1557 1557 nfsd_check_ignore_resizing(iap); 1558 1558 break;
+1 -1
fs/open.c
··· 1171 1171 if (IS_ERR(f)) 1172 1172 return f; 1173 1173 1174 - error = vfs_create(mnt_idmap(path->mnt), path->dentry, mode); 1174 + error = vfs_create(mnt_idmap(path->mnt), path->dentry, mode, NULL); 1175 1175 if (!error) 1176 1176 error = vfs_open(path, f); 1177 1177
+1 -1
fs/overlayfs/overlayfs.h
··· 235 235 struct inode *dir, struct dentry *dentry, 236 236 umode_t mode) 237 237 { 238 - int err = vfs_create(ovl_upper_mnt_idmap(ofs), dentry, mode); 238 + int err = vfs_create(ovl_upper_mnt_idmap(ofs), dentry, mode, NULL); 239 239 240 240 pr_debug("create(%pd2, 0%o) = %i\n", dentry, mode, err); 241 241 return err;
+1 -1
fs/smb/server/vfs.c
··· 188 188 } 189 189 190 190 mode |= S_IFREG; 191 - err = vfs_create(mnt_idmap(path.mnt), dentry, mode); 191 + err = vfs_create(mnt_idmap(path.mnt), dentry, mode, NULL); 192 192 if (!err) { 193 193 ksmbd_vfs_inherit_owner(work, d_inode(path.dentry), 194 194 d_inode(dentry));
+2 -1
include/linux/fs.h
··· 2111 2111 /* 2112 2112 * VFS helper functions.. 2113 2113 */ 2114 - int vfs_create(struct mnt_idmap *, struct dentry *, umode_t); 2114 + int vfs_create(struct mnt_idmap *, struct dentry *, umode_t, 2115 + struct delegated_inode *); 2115 2116 struct dentry *vfs_mkdir(struct mnt_idmap *, struct inode *, 2116 2117 struct dentry *, umode_t, struct delegated_inode *); 2117 2118 int vfs_mknod(struct mnt_idmap *, struct inode *, struct dentry *,