fuse: continue to send FUSE_RELEASEDIR when FUSE_OPEN returns ENOSYS
Subsystems (2)
PATCH 1/1 fuse: continue to send FUSE_RELEASEDIR when FUSE_OPEN returns ENOSYS
When FUSE_OPEN returns ENOSYS, the no_open bit is set on the connection. Because the FUSE_RELEASE and FUSE_RELEASEDIR paths share code, this incorrectly caused the FUSE_RELEASEDIR request to be dropped and never sent to userspace. Pass an isdir bool to distinguish between FUSE_RELEASE and FUSE_RELEASEDIR inside of fuse_file_put.
--- fs/fuse/dir.c | 2 +- fs/fuse/file.c | 20 ++++++++++---------- fs/fuse/fuse_i.h | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-)
fs/fuse/dir.c +1 -1
@@ -1462,7 +1462,7 @@ static int fuse_dir_open(struct inode *inode, struct file *file)static int fuse_dir_release (struct inode *inode,struct file *file) { -fuse_release_common (file,FUSE_RELEASEDIR ); +fuse_release_common (file,FUSE_RELEASEDIR , true);return 0 ; }
fs/fuse/file.c +10 -10
@@ -86,12 +86,12 @@ static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req)iput (req->misc.release.inode); } -static void fuse_file_put (struct fuse_file *ff,bool sync) +static void fuse_file_put (struct fuse_file *ff,bool sync,bool isdir) {if (refcount_dec_and_test (&ff->count)) {struct fuse_req *req = ff->reserved_req; -if (ff->fc->no_open) { +if (ff->fc->no_open && !isdir) {/* * Drop the release request when client does not * implement 'open'
@@ -244,7 +244,7 @@ static void fuse_prepare_release(struct fuse_file *ff, int flags, int opcode) req->in.args[0 ].value = inarg; } -void fuse_release_common (struct file *file,int opcode) +void fuse_release_common (struct file *file,int opcode,bool isdir) {struct fuse_file *ff = file->private_data;struct fuse_req *req = ff->reserved_req;
@@ -269,7 +269,7 @@ void fuse_release_common(struct file *file, int opcode)* synchronous RELEASE is allowed (and desirable) in this case * because the server can be trusted not to screw up. */ -fuse_file_put (ff, ff->fc->destroy_req !=NULL ); +fuse_file_put (ff, ff->fc->destroy_req !=NULL , isdir); }static int fuse_open (struct inode *inode,struct file *file)
@@ -285,7 +285,7 @@ static int fuse_release(struct inode *inode, struct file *file)if (fc->writeback_cache)write_inode_now (inode,1 ); -fuse_release_common (file,FUSE_RELEASE ); +fuse_release_common (file,FUSE_RELEASE , false);/* return value is ignored by VFS */ return 0 ;
@@ -299,7 +299,7 @@ void fuse_sync_release(struct fuse_file *ff, int flags)* iput(NULL) is a no-op and since the refcount is 1 and everything's * synchronous, we are fine with not doing igrab() here" */ -fuse_file_put (ff, true); +fuse_file_put (ff, true, false); }EXPORT_SYMBOL_GPL (fuse_sync_release);
@@ -804,7 +804,7 @@ static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req)put_page (page); }if (req->ff) -fuse_file_put (req->ff, false); +fuse_file_put (req->ff, false, false); }static void fuse_send_readpages (struct fuse_req *req,struct file *file)
@@ -1457,7 +1457,7 @@ static void fuse_writepage_free(struct fuse_conn *fc, struct fuse_req *req)__free_page (req->pages[i]);if (req->ff) -fuse_file_put (req->ff, false); +fuse_file_put (req->ff, false, false); }static void fuse_writepage_finish (struct fuse_conn *fc,struct fuse_req *req)
@@ -1614,7 +1614,7 @@ int fuse_write_inode(struct inode *inode, struct writeback_control *wbc) ff =__fuse_write_file_get (fc, fi); err =fuse_flush_times (inode, ff);if (ff) -fuse_file_put (ff,0 ); +fuse_file_put (ff,0 , false);return err; }
@@ -1928,7 +1928,7 @@ static int fuse_writepages(struct address_space *mapping, err =0 ; }if (data.ff) -fuse_file_put (data.ff, false); +fuse_file_put (data.ff, false, false);kfree (data.orig_pages); out:
fs/fuse/fuse_i.h +1 -1
@@ -742,7 +742,7 @@ void fuse_sync_release(struct fuse_file *ff, int flags);/** * Send RELEASE or RELEASEDIR request */ -void fuse_release_common (struct file *file,int opcode); +void fuse_release_common (struct file *file,int opcode,bool isdir);/** * Send FSYNC or FSYNCDIR request
Signature · 1 line
2.17.1
Miklos Szeredi
maintainerQuoted 8 lines · Chad Austin
When
FUSE_OPENreturns ENOSYS, theno_openbit is set on the connection. Because theFUSE_RELEASEandFUSE_RELEASEDIRpaths share code, this incorrectly caused theFUSE_RELEASEDIRrequest to be dropped and never sent to userspace. Pass an isdir bool to distinguish betweenFUSE_RELEASEandFUSE_RELEASEDIRinside offuse_file_put.Fixes 7678ac50615d ("fuse: support clients that don't implement 'open'")
Thanks.
You did not add a Signed-off-by. Can I add it for you?
Quoted 39 lines
--- fs/fuse/dir.c | 2 +- fs/fuse/file.c | 20 ++++++++++---------- fs/fuse/fuse_i.h | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-)fs/fuse/dir.c +1
-1@@ -1462,7 +1462,7 @@ static int fuse_dir_open(struct inode *inode, struct file *file)static int fuse_dir_release (struct inode *inode,struct file *file) { -fuse_release_common (file,FUSE_RELEASEDIR ); +fuse_release_common (file,FUSE_RELEASEDIR , true);return 0 ; }fs/fuse/file.c +2
-2@@ -86,12 +86,12 @@ static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req)iput (req->misc.release.inode); } -static void fuse_file_put (struct fuse_file *ff,bool sync) +static void fuse_file_put (struct fuse_file *ff,bool sync,bool isdir) {if (refcount_dec_and_test (&ff->count)) {struct fuse_req *req = ff->reserved_req; -if (ff->fc->no_open) { +if (ff->fc->no_open && !isdir) {/* * Drop the release request when client does not * implement 'open'
fs/fuse/file.c static void fuse_prepare_release(struct fuse_file *ff, int flags, int opcode) · line 247
Quoted 5 lines
fs/fuse/file.c +1
-1@@ -244,7 +244,7 @@ static void fuse_prepare_release(struct fuse_file *ff, int flags, int opcode) req->in.args[0 ].value = inarg; } -void fuse_release_common (struct file *file,int opcode) +void fuse_release_common (struct file *file,int opcode,bool isdir)
opcode and isdir are redundant. I've fixed it up (kept isdir) to match fuse_open_common() signature.
Otherwise looks good.
Quoted 82 lines
fs/fuse/file.c +7
-7{struct fuse_file *ff = file->private_data;struct fuse_req *req = ff->reserved_req;@@ -269,7 +269,7 @@ void fuse_release_common(struct file *file, int opcode)* synchronous RELEASE is allowed (and desirable) in this case * because the server can be trusted not to screw up. */ -fuse_file_put (ff, ff->fc->destroy_req !=NULL ); +fuse_file_put (ff, ff->fc->destroy_req !=NULL , isdir); }static int fuse_open (struct inode *inode,struct file *file)@@ -285,7 +285,7 @@ static int fuse_release(struct inode *inode, struct file *file)if (fc->writeback_cache)write_inode_now (inode,1 ); -fuse_release_common (file,FUSE_RELEASE ); +fuse_release_common (file,FUSE_RELEASE , false);/* return value is ignored by VFS */ return 0 ;@@ -299,7 +299,7 @@ void fuse_sync_release(struct fuse_file *ff, int flags)* iput(NULL) is a no-op and since the refcount is 1 and everything's * synchronous, we are fine with not doing igrab() here" */ -fuse_file_put (ff, true); +fuse_file_put (ff, true, false); }EXPORT_SYMBOL_GPL (fuse_sync_release);@@ -804,7 +804,7 @@ static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req)put_page (page); }if (req->ff) -fuse_file_put (req->ff, false); +fuse_file_put (req->ff, false, false); }static void fuse_send_readpages (struct fuse_req *req,struct file *file)@@ -1457,7 +1457,7 @@ static void fuse_writepage_free(struct fuse_conn *fc, struct fuse_req *req)__free_page (req->pages[i]);if (req->ff) -fuse_file_put (req->ff, false); +fuse_file_put (req->ff, false, false); }static void fuse_writepage_finish (struct fuse_conn *fc,struct fuse_req *req)@@ -1614,7 +1614,7 @@ int fuse_write_inode(struct inode *inode, struct writeback_control *wbc) ff =__fuse_write_file_get (fc, fi); err =fuse_flush_times (inode, ff);if (ff) -fuse_file_put (ff,0 ); +fuse_file_put (ff,0 , false);return err; }@@ -1928,7 +1928,7 @@ static int fuse_writepages(struct address_space *mapping, err =0 ; }if (data.ff) -fuse_file_put (data.ff, false); +fuse_file_put (data.ff, false, false);kfree (data.orig_pages); out:fs/fuse/fuse_i.h +1
-2@@ -742,7 +742,7 @@ void fuse_sync_release(struct fuse_file *ff, int flags);/** * Send RELEASE or RELEASEDIR request */ -void fuse_release_common (struct file *file,int opcode); +void fuse_release_common (struct file *file,int opcode,bool isdir);/** * Send FSYNC or FSYNCDIR request -- 2.17.1
Quoted 8 lines · Miklos Szeredi
Quoted 7 lines · Chad Austin
When
FUSE_OPENreturns ENOSYS, theno_openbit is set on the connection. Because theFUSE_RELEASEandFUSE_RELEASEDIRpaths share code, this incorrectly caused theFUSE_RELEASEDIRrequest to be dropped and never sent to userspace. Pass an isdir bool to distinguish betweenFUSE_RELEASEandFUSE_RELEASEDIRinside offuse_file_put.
Quoted 5 lines
Quoted 1 line
Fixes 7678ac50615d ("fuse: support clients that don't implement 'open'")Thanks.
You did not add a Signed-off-by. Can I add it for you?
By all means, thank you.
Quoted 2 lines
opcode and isdir are redundant. I've fixed it up (kept isdir) to match
fuse_open_common()signature.
Perfect!
Chad