On Wed 24-09-25 14:05:53, Jeff Layton wrote: > 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. > > Rename vfs_create as __vfs_create, make it static, and add a new > delegated_inode parameter. Fix do_mknodat to call __vfs_create and wait > for a delegation break if there is one. Add a new exported vfs_create > wrapper that passes in NULL for delegated_inode. > > Signed-off-by: Jeff Layton <[email protected]>
Looks good. Feel free to add: Reviewed-by: Jan Kara <[email protected]> Honza > --- > fs/namei.c | 55 ++++++++++++++++++++++++++++++++++++------------------- > 1 file changed, 36 insertions(+), 19 deletions(-) > > diff --git a/fs/namei.c b/fs/namei.c > index > 903b70a82530938a0fdf10508529a1b7cc38136d..d4b8330a3eb97e205dc2e71766fed1e45503323b > 100644 > --- a/fs/namei.c > +++ b/fs/namei.c > @@ -3370,6 +3370,32 @@ static inline umode_t vfs_prepare_mode(struct > mnt_idmap *idmap, > return mode; > } > > +static int __vfs_create(struct mnt_idmap *idmap, struct inode *dir, > + struct dentry *dentry, umode_t mode, bool want_excl, > + struct inode **delegated_inode) > +{ > + int error; > + > + error = may_create(idmap, dir, dentry); > + if (error) > + return error; > + > + if (!dir->i_op->create) > + return -EACCES; /* shouldn't it be ENOSYS? */ > + > + mode = vfs_prepare_mode(idmap, dir, mode, S_IALLUGO, S_IFREG); > + error = security_inode_create(dir, dentry, mode); > + if (error) > + return error; > + error = try_break_deleg(dir, delegated_inode); > + if (error) > + return error; > + error = dir->i_op->create(idmap, dir, dentry, mode, want_excl); > + if (!error) > + fsnotify_create(dir, dentry); > + return error; > +} > + > /** > * vfs_create - create new file > * @idmap: idmap of the mount the inode was found from > @@ -3389,23 +3415,7 @@ static inline umode_t vfs_prepare_mode(struct > mnt_idmap *idmap, > int vfs_create(struct mnt_idmap *idmap, struct inode *dir, > struct dentry *dentry, umode_t mode, bool want_excl) > { > - int error; > - > - error = may_create(idmap, dir, dentry); > - if (error) > - return error; > - > - if (!dir->i_op->create) > - return -EACCES; /* shouldn't it be ENOSYS? */ > - > - mode = vfs_prepare_mode(idmap, dir, mode, S_IALLUGO, S_IFREG); > - error = security_inode_create(dir, dentry, mode); > - if (error) > - return error; > - error = dir->i_op->create(idmap, dir, dentry, mode, want_excl); > - if (!error) > - fsnotify_create(dir, dentry); > - return error; > + return __vfs_create(idmap, dir, dentry, mode, want_excl, NULL); > } > EXPORT_SYMBOL(vfs_create); > > @@ -4278,6 +4288,7 @@ static int do_mknodat(int dfd, struct filename *name, > umode_t mode, > struct path path; > int error; > unsigned int lookup_flags = 0; > + struct inode *delegated_inode = NULL; > > error = may_mknod(mode); > if (error) > @@ -4296,8 +4307,9 @@ static int do_mknodat(int dfd, struct filename *name, > umode_t mode, > idmap = mnt_idmap(path.mnt); > switch (mode & S_IFMT) { > case 0: case S_IFREG: > - error = vfs_create(idmap, path.dentry->d_inode, > - dentry, mode, true); > + error = __vfs_create(idmap, path.dentry->d_inode, > + dentry, mode, true, > + &delegated_inode); > if (!error) > security_path_post_mknod(idmap, dentry); > break; > @@ -4312,6 +4324,11 @@ static int do_mknodat(int dfd, struct filename *name, > umode_t mode, > } > out2: > done_path_create(&path, dentry); > + if (delegated_inode) { > + error = break_deleg_wait(&delegated_inode); > + if (!error) > + goto retry; > + } > if (retry_estale(error, lookup_flags)) { > lookup_flags |= LOOKUP_REVAL; > goto retry; > > -- > 2.51.0 > -- Jan Kara <[email protected]> SUSE Labs, CR
