On Wed 24-09-25 14:05:52, 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. > > Add a delegated_inode parameter to lookup_open and have it break the > delegation. Then, open_last_lookups can wait for the delegation break > and retry the call to lookup_open once it's done. > > Signed-off-by: Jeff Layton <[email protected]>
Looks good. Feel free to add: Reviewed-by: Jan Kara <[email protected]> Honza > --- > fs/namei.c | 22 ++++++++++++++++++---- > 1 file changed, 18 insertions(+), 4 deletions(-) > > diff --git a/fs/namei.c b/fs/namei.c > index > 4e058b00208c1663ba828c6f8ed1f82c26a4f136..903b70a82530938a0fdf10508529a1b7cc38136d > 100644 > --- a/fs/namei.c > +++ b/fs/namei.c > @@ -3609,7 +3609,7 @@ static struct dentry *atomic_open(struct nameidata *nd, > struct dentry *dentry, > */ > static struct dentry *lookup_open(struct nameidata *nd, struct file *file, > const struct open_flags *op, > - bool got_write) > + bool got_write, struct inode > **delegated_inode) > { > struct mnt_idmap *idmap; > struct dentry *dir = nd->path.dentry; > @@ -3698,6 +3698,11 @@ static struct dentry *lookup_open(struct nameidata > *nd, struct file *file, > > /* Negative dentry, just create the file */ > if (!dentry->d_inode && (open_flag & O_CREAT)) { > + /* but break the directory lease first! */ > + error = try_break_deleg(dir_inode, delegated_inode); > + if (error) > + goto out_dput; > + > file->f_mode |= FMODE_CREATED; > audit_inode_child(dir_inode, dentry, AUDIT_TYPE_CHILD_CREATE); > if (!dir_inode->i_op->create) { > @@ -3761,6 +3766,7 @@ static const char *open_last_lookups(struct nameidata > *nd, > struct file *file, const struct open_flags *op) > { > struct dentry *dir = nd->path.dentry; > + struct inode *delegated_inode = NULL; > int open_flag = op->open_flag; > bool got_write = false; > struct dentry *dentry; > @@ -3791,7 +3797,7 @@ static const char *open_last_lookups(struct nameidata > *nd, > return ERR_PTR(-ECHILD); > } > } > - > +retry: > if (open_flag & (O_CREAT | O_TRUNC | O_WRONLY | O_RDWR)) { > got_write = !mnt_want_write(nd->path.mnt); > /* > @@ -3804,7 +3810,7 @@ static const char *open_last_lookups(struct nameidata > *nd, > inode_lock(dir->d_inode); > else > inode_lock_shared(dir->d_inode); > - dentry = lookup_open(nd, file, op, got_write); > + dentry = lookup_open(nd, file, op, got_write, &delegated_inode); > if (!IS_ERR(dentry)) { > if (file->f_mode & FMODE_CREATED) > fsnotify_create(dir->d_inode, dentry); > @@ -3819,8 +3825,16 @@ static const char *open_last_lookups(struct nameidata > *nd, > if (got_write) > mnt_drop_write(nd->path.mnt); > > - if (IS_ERR(dentry)) > + if (IS_ERR(dentry)) { > + if (delegated_inode) { > + int error = break_deleg_wait(&delegated_inode); > + > + if (!error) > + goto retry; > + return ERR_PTR(error); > + } > return ERR_CAST(dentry); > + } > > if (file->f_mode & (FMODE_OPENED | FMODE_CREATED)) { > dput(nd->path.dentry); > > -- > 2.51.0 > -- Jan Kara <[email protected]> SUSE Labs, CR
