fuse_create_open()'s close_wait branch was not correct -- in particular the fput() in its error path was wrong; fuse_open()'s close_wait branch should apply instead. Refactor the close_wait branch into a new function used in both places. fuse_sync_release() applies to the close_wait error path in both places.
Signed-off-by: Liu Kui <[email protected]> --- Changes in v2: - Factor the close_wait open branch into fuse_open_close_wait(); call it from both fuse_open() and fuse_create_open() instead of duplicating the block in each. - Use fuse_sync_release() on the close_wait error path for both callers. It is functionally equivalent to fuse_release_common() used in fuse_open(). fs/fuse/dir.c | 18 ++----------- fs/fuse/file.c | 67 +++++++++++++++++++++++++++--------------------- fs/fuse/fuse_i.h | 1 + 3 files changed, 41 insertions(+), 45 deletions(-) diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 45ee4f1e4b68..2faf052632d6 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -722,22 +722,8 @@ static int fuse_create_open(struct mnt_idmap *idmap, struct inode *dir, invalidate_inode_pages2(inode->i_mapping); } - if (fm->fc->close_wait) { - struct fuse_inode *fi = get_fuse_inode(inode); - bool need_open; - - inode_lock(inode); - spin_lock(&fi->lock); - need_open = (++fi->num_openers == 1); - spin_unlock(&fi->lock); - - if (need_open && fm->fc->kio.op && fm->fc->kio.op->file_open) { - err = fm->fc->kio.op->file_open(file, inode); - if (err) - fput(file); - } - inode_unlock(inode); - } + if (!err && fm->fc->close_wait) + err = fuse_open_close_wait(inode, file); return err; diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 58202a96517e..faf39887125a 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -337,6 +337,42 @@ static void fuse_truncate_update_attr(struct inode *inode, struct file *file) fuse_invalidate_attr_mask(inode, FUSE_STATX_MODSIZE); } +int fuse_open_close_wait(struct inode *inode, struct file *file) +{ + struct fuse_conn *fc = get_fuse_conn(inode); + struct fuse_inode *fi = get_fuse_inode(inode); + struct fuse_file *ff = file->private_data; + int err = 0; + + inode_lock(inode); + spin_lock(&fi->lock); + + if (++fi->num_openers == 1 || fi->i_size_unstable) { + fi->i_size_unstable = 1; + fi->inval_mask = ~0; + spin_unlock(&fi->lock); + err = fuse_update_attributes(inode, file, ~0); + + if (!err && fc->kio.op && fc->kio.op->file_open) + err = fc->kio.op->file_open(file, inode); + + spin_lock(&fi->lock); + fi->i_size_unstable = 0; + if (err) + fi->num_openers--; + } + + file->f_mode |= FMODE_NOWAIT; + + spin_unlock(&fi->lock); + inode_unlock(inode); + + if (err) + fuse_sync_release(fi, ff, file->f_flags); + + return err; +} + static int fuse_open(struct inode *inode, struct file *file) { struct fuse_mount *fm = get_fuse_mount(inode); @@ -399,35 +435,8 @@ static int fuse_open(struct inode *inode, struct file *file) if (is_wb_truncate || dax_truncate) inode_unlock(inode); - if (!err && fc->close_wait) { - inode_lock(inode); - spin_lock(&fi->lock); - - if (++fi->num_openers == 1 || fi->i_size_unstable) { - fi->i_size_unstable = 1; - fi->inval_mask = ~0; - spin_unlock(&fi->lock); - err = fuse_update_attributes(inode, file, ~0); - - if (!err && fc->kio.op && fc->kio.op->file_open) - err = fc->kio.op->file_open(file, inode); - - spin_lock(&fi->lock); - fi->i_size_unstable = 0; - if (err) - fi->num_openers--; - } - - file->f_mode |= FMODE_NOWAIT; - - spin_unlock(&fi->lock); - inode_unlock(inode); - - if (err) { - fuse_release_common(file, false); - return err; - } - } + if (!err && fc->close_wait) + err = fuse_open_close_wait(inode, file); return err; } diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index a834a5b4dfe2..6f462f0c4c3c 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -1317,6 +1317,7 @@ void fuse_read_args_fill(struct fuse_io_args *ia, struct file *file, loff_t pos, struct fuse_file *fuse_file_alloc(struct fuse_mount *fm, bool release); void fuse_file_free(struct fuse_file *ff); int fuse_finish_open(struct inode *inode, struct file *file); +int fuse_open_close_wait(struct inode *inode, struct file *file); void fuse_sync_release(struct fuse_inode *fi, struct fuse_file *ff, unsigned int flags); -- 2.50.1 (Apple Git-155) _______________________________________________ Devel mailing list [email protected] https://lists.openvz.org/mailman/listinfo/devel
