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: allow mkdir to wait for delegation break on parent

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 parameter to vfs_mkdir. All of the existing
callers set that to NULL for now, except for do_mkdirat which will
properly block until the lease is gone.

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

authored by

Jeff Layton and committed by
Christian Brauner
e12d203b b46ebf9a

+28 -16
+1 -1
drivers/base/devtmpfs.c
··· 180 180 if (IS_ERR(dentry)) 181 181 return PTR_ERR(dentry); 182 182 183 - dentry = vfs_mkdir(&nop_mnt_idmap, d_inode(path.dentry), dentry, mode); 183 + dentry = vfs_mkdir(&nop_mnt_idmap, d_inode(path.dentry), dentry, mode, NULL); 184 184 if (!IS_ERR(dentry)) 185 185 /* mark as kernel-created inode */ 186 186 d_inode(dentry)->i_private = &thread;
+1 -1
fs/cachefiles/namei.c
··· 130 130 goto mkdir_error; 131 131 ret = cachefiles_inject_write_error(); 132 132 if (ret == 0) 133 - subdir = vfs_mkdir(&nop_mnt_idmap, d_inode(dir), subdir, 0700); 133 + subdir = vfs_mkdir(&nop_mnt_idmap, d_inode(dir), subdir, 0700, NULL); 134 134 else 135 135 subdir = ERR_PTR(ret); 136 136 if (IS_ERR(subdir)) {
+1 -1
fs/ecryptfs/inode.c
··· 508 508 goto out; 509 509 510 510 lower_dentry = vfs_mkdir(&nop_mnt_idmap, lower_dir, 511 - lower_dentry, mode); 511 + lower_dentry, mode, NULL); 512 512 rc = PTR_ERR(lower_dentry); 513 513 if (IS_ERR(lower_dentry)) 514 514 goto out;
+1 -1
fs/init.c
··· 233 233 error = security_path_mkdir(&path, dentry, mode); 234 234 if (!error) { 235 235 dentry = vfs_mkdir(mnt_idmap(path.mnt), path.dentry->d_inode, 236 - dentry, mode); 236 + dentry, mode, NULL); 237 237 if (IS_ERR(dentry)) 238 238 error = PTR_ERR(dentry); 239 239 }
+18 -6
fs/namei.c
··· 4407 4407 4408 4408 /** 4409 4409 * vfs_mkdir - create directory returning correct dentry if possible 4410 - * @idmap: idmap of the mount the inode was found from 4411 - * @dir: inode of the parent directory 4412 - * @dentry: dentry of the child directory 4413 - * @mode: mode of the child directory 4410 + * @idmap: idmap of the mount the inode was found from 4411 + * @dir: inode of the parent directory 4412 + * @dentry: dentry of the child directory 4413 + * @mode: mode of the child directory 4414 + * @delegated_inode: returns parent inode, if the inode is delegated. 4414 4415 * 4415 4416 * Create a directory. 4416 4417 * ··· 4428 4427 * In case of an error the dentry is dput() and an ERR_PTR() is returned. 4429 4428 */ 4430 4429 struct dentry *vfs_mkdir(struct mnt_idmap *idmap, struct inode *dir, 4431 - struct dentry *dentry, umode_t mode) 4430 + struct dentry *dentry, umode_t mode, 4431 + struct delegated_inode *delegated_inode) 4432 4432 { 4433 4433 int error; 4434 4434 unsigned max_links = dir->i_sb->s_max_links; ··· 4450 4448 4451 4449 error = -EMLINK; 4452 4450 if (max_links && dir->i_nlink >= max_links) 4451 + goto err; 4452 + 4453 + error = try_break_deleg(dir, delegated_inode); 4454 + if (error) 4453 4455 goto err; 4454 4456 4455 4457 de = dir->i_op->mkdir(idmap, dir, dentry, mode); ··· 4479 4473 struct path path; 4480 4474 int error; 4481 4475 unsigned int lookup_flags = LOOKUP_DIRECTORY; 4476 + struct delegated_inode delegated_inode = { }; 4482 4477 4483 4478 retry: 4484 4479 dentry = filename_create(dfd, name, &path, lookup_flags); ··· 4491 4484 mode_strip_umask(path.dentry->d_inode, mode)); 4492 4485 if (!error) { 4493 4486 dentry = vfs_mkdir(mnt_idmap(path.mnt), path.dentry->d_inode, 4494 - dentry, mode); 4487 + dentry, mode, &delegated_inode); 4495 4488 if (IS_ERR(dentry)) 4496 4489 error = PTR_ERR(dentry); 4497 4490 } 4498 4491 end_creating_path(&path, dentry); 4492 + if (is_delegated(&delegated_inode)) { 4493 + error = break_deleg_wait(&delegated_inode); 4494 + if (!error) 4495 + goto retry; 4496 + } 4499 4497 if (retry_estale(error, lookup_flags)) { 4500 4498 lookup_flags |= LOOKUP_REVAL; 4501 4499 goto retry;
+1 -1
fs/nfsd/nfs4recover.c
··· 213 213 * as well be forgiving and just succeed silently. 214 214 */ 215 215 goto out_put; 216 - dentry = vfs_mkdir(&nop_mnt_idmap, d_inode(dir), dentry, S_IRWXU); 216 + dentry = vfs_mkdir(&nop_mnt_idmap, d_inode(dir), dentry, 0700, NULL); 217 217 if (IS_ERR(dentry)) 218 218 status = PTR_ERR(dentry); 219 219 out_put:
+1 -1
fs/nfsd/vfs.c
··· 1558 1558 nfsd_check_ignore_resizing(iap); 1559 1559 break; 1560 1560 case S_IFDIR: 1561 - dchild = vfs_mkdir(&nop_mnt_idmap, dirp, dchild, iap->ia_mode); 1561 + dchild = vfs_mkdir(&nop_mnt_idmap, dirp, dchild, iap->ia_mode, NULL); 1562 1562 if (IS_ERR(dchild)) { 1563 1563 host_err = PTR_ERR(dchild); 1564 1564 } else if (d_is_negative(dchild)) {
+1 -1
fs/overlayfs/overlayfs.h
··· 248 248 { 249 249 struct dentry *ret; 250 250 251 - ret = vfs_mkdir(ovl_upper_mnt_idmap(ofs), dir, dentry, mode); 251 + ret = vfs_mkdir(ovl_upper_mnt_idmap(ofs), dir, dentry, mode, NULL); 252 252 pr_debug("mkdir(%pd2, 0%o) = %i\n", dentry, mode, PTR_ERR_OR_ZERO(ret)); 253 253 return ret; 254 254 }
+1 -1
fs/smb/server/vfs.c
··· 230 230 idmap = mnt_idmap(path.mnt); 231 231 mode |= S_IFDIR; 232 232 d = dentry; 233 - dentry = vfs_mkdir(idmap, d_inode(path.dentry), dentry, mode); 233 + dentry = vfs_mkdir(idmap, d_inode(path.dentry), dentry, mode, NULL); 234 234 if (IS_ERR(dentry)) 235 235 err = PTR_ERR(dentry); 236 236 else if (d_is_negative(dentry))
+1 -1
fs/xfs/scrub/orphanage.c
··· 167 167 */ 168 168 if (d_really_is_negative(orphanage_dentry)) { 169 169 orphanage_dentry = vfs_mkdir(&nop_mnt_idmap, root_inode, 170 - orphanage_dentry, 0750); 170 + orphanage_dentry, 0750, NULL); 171 171 error = PTR_ERR(orphanage_dentry); 172 172 if (IS_ERR(orphanage_dentry)) 173 173 goto out_unlock_root;
+1 -1
include/linux/fs.h
··· 2114 2114 int vfs_create(struct mnt_idmap *, struct inode *, 2115 2115 struct dentry *, umode_t, bool); 2116 2116 struct dentry *vfs_mkdir(struct mnt_idmap *, struct inode *, 2117 - struct dentry *, umode_t); 2117 + struct dentry *, umode_t, struct delegated_inode *); 2118 2118 int vfs_mknod(struct mnt_idmap *, struct inode *, struct dentry *, 2119 2119 umode_t, dev_t); 2120 2120 int vfs_symlink(struct mnt_idmap *, struct inode *,