Skip to content

Commit e8960c1

Browse files
jtlaytonbrauner
authored andcommitted
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>
1 parent c826229 commit e8960c1

8 files changed

Lines changed: 23 additions & 16 deletions

File tree

drivers/base/devtmpfs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ static int handle_create(const char *nodename, umode_t mode, kuid_t uid,
231231
return PTR_ERR(dentry);
232232

233233
err = vfs_mknod(&nop_mnt_idmap, d_inode(path.dentry), dentry, mode,
234-
dev->devt);
234+
dev->devt, NULL);
235235
if (!err) {
236236
struct iattr newattrs;
237237

fs/ecryptfs/inode.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,7 @@ ecryptfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
564564
rc = lock_parent(dentry, &lower_dentry, &lower_dir);
565565
if (!rc)
566566
rc = vfs_mknod(&nop_mnt_idmap, lower_dir,
567-
lower_dentry, mode, dev);
567+
lower_dentry, mode, dev, NULL);
568568
if (rc || d_really_is_negative(lower_dentry))
569569
goto out;
570570
rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb);

fs/init.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ int __init init_mknod(const char *filename, umode_t mode, unsigned int dev)
157157
error = security_path_mknod(&path, dentry, mode, dev);
158158
if (!error)
159159
error = vfs_mknod(mnt_idmap(path.mnt), path.dentry->d_inode,
160-
dentry, mode, new_decode_dev(dev));
160+
dentry, mode, new_decode_dev(dev), NULL);
161161
end_creating_path(&path, dentry);
162162
return error;
163163
}

fs/namei.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4295,13 +4295,15 @@ inline struct dentry *start_creating_user_path(
42954295
}
42964296
EXPORT_SYMBOL(start_creating_user_path);
42974297

4298+
42984299
/**
42994300
* vfs_mknod - create device node or file
4300-
* @idmap: idmap of the mount the inode was found from
4301-
* @dir: inode of the parent directory
4302-
* @dentry: dentry of the child device node
4303-
* @mode: mode of the child device node
4304-
* @dev: device number of device to create
4301+
* @idmap: idmap of the mount the inode was found from
4302+
* @dir: inode of the parent directory
4303+
* @dentry: dentry of the child device node
4304+
* @mode: mode of the child device node
4305+
* @dev: device number of device to create
4306+
* @delegated_inode: returns parent inode, if the inode is delegated.
43054307
*
43064308
* Create a device node or file.
43074309
*
@@ -4312,7 +4314,8 @@ EXPORT_SYMBOL(start_creating_user_path);
43124314
* raw inode simply pass @nop_mnt_idmap.
43134315
*/
43144316
int vfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
4315-
struct dentry *dentry, umode_t mode, dev_t dev)
4317+
struct dentry *dentry, umode_t mode, dev_t dev,
4318+
struct delegated_inode *delegated_inode)
43164319
{
43174320
bool is_whiteout = S_ISCHR(mode) && dev == WHITEOUT_DEV;
43184321
int error = may_create(idmap, dir, dentry);
@@ -4336,6 +4339,10 @@ int vfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
43364339
if (error)
43374340
return error;
43384341

4342+
error = try_break_deleg(dir, delegated_inode);
4343+
if (error)
4344+
return error;
4345+
43394346
error = dir->i_op->mknod(idmap, dir, dentry, mode, dev);
43404347
if (!error)
43414348
fsnotify_create(dir, dentry);
@@ -4393,11 +4400,11 @@ static int do_mknodat(int dfd, struct filename *name, umode_t mode,
43934400
break;
43944401
case S_IFCHR: case S_IFBLK:
43954402
error = vfs_mknod(idmap, path.dentry->d_inode,
4396-
dentry, mode, new_decode_dev(dev));
4403+
dentry, mode, new_decode_dev(dev), &di);
43974404
break;
43984405
case S_IFIFO: case S_IFSOCK:
43994406
error = vfs_mknod(idmap, path.dentry->d_inode,
4400-
dentry, mode, 0);
4407+
dentry, mode, 0, &di);
44014408
break;
44024409
}
44034410
out2:

fs/nfsd/vfs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1573,7 +1573,7 @@ nfsd_create_locked(struct svc_rqst *rqstp, struct svc_fh *fhp,
15731573
case S_IFIFO:
15741574
case S_IFSOCK:
15751575
host_err = vfs_mknod(&nop_mnt_idmap, dirp, dchild,
1576-
iap->ia_mode, rdev);
1576+
iap->ia_mode, rdev, NULL);
15771577
break;
15781578
default:
15791579
printk(KERN_WARNING "nfsd: bad file type %o in nfsd_create\n",

fs/overlayfs/overlayfs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ static inline int ovl_do_mknod(struct ovl_fs *ofs,
257257
struct inode *dir, struct dentry *dentry,
258258
umode_t mode, dev_t dev)
259259
{
260-
int err = vfs_mknod(ovl_upper_mnt_idmap(ofs), dir, dentry, mode, dev);
260+
int err = vfs_mknod(ovl_upper_mnt_idmap(ofs), dir, dentry, mode, dev, NULL);
261261

262262
pr_debug("mknod(%pd2, 0%o, 0%o) = %i\n", dentry, mode, dev, err);
263263
return err;

include/linux/fs.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2116,7 +2116,7 @@ int vfs_create(struct mnt_idmap *, struct dentry *, umode_t,
21162116
struct dentry *vfs_mkdir(struct mnt_idmap *, struct inode *,
21172117
struct dentry *, umode_t, struct delegated_inode *);
21182118
int vfs_mknod(struct mnt_idmap *, struct inode *, struct dentry *,
2119-
umode_t, dev_t);
2119+
umode_t, dev_t, struct delegated_inode *);
21202120
int vfs_symlink(struct mnt_idmap *, struct inode *,
21212121
struct dentry *, const char *);
21222122
int vfs_link(struct dentry *, struct mnt_idmap *, struct inode *,
@@ -2152,7 +2152,7 @@ static inline int vfs_whiteout(struct mnt_idmap *idmap,
21522152
struct inode *dir, struct dentry *dentry)
21532153
{
21542154
return vfs_mknod(idmap, dir, dentry, S_IFCHR | WHITEOUT_MODE,
2155-
WHITEOUT_DEV);
2155+
WHITEOUT_DEV, NULL);
21562156
}
21572157

21582158
struct file *kernel_tmpfile_open(struct mnt_idmap *idmap,

net/unix/af_unix.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1399,7 +1399,7 @@ static int unix_bind_bsd(struct sock *sk, struct sockaddr_un *sunaddr,
13991399
idmap = mnt_idmap(parent.mnt);
14001400
err = security_path_mknod(&parent, dentry, mode, 0);
14011401
if (!err)
1402-
err = vfs_mknod(idmap, d_inode(parent.dentry), dentry, mode, 0);
1402+
err = vfs_mknod(idmap, d_inode(parent.dentry), dentry, mode, 0, NULL);
14031403
if (err)
14041404
goto out_path;
14051405
err = mutex_lock_interruptible(&u->bindlock);

0 commit comments

Comments
 (0)