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

Reply via email to