|
@@ -127,7 +127,15 @@ static void fuse_file_put(struct fuse_file *ff, bool sync)
|
|
|
if (atomic_dec_and_test(&ff->count)) {
|
|
|
struct fuse_req *req = ff->reserved_req;
|
|
|
|
|
|
- if (sync) {
|
|
|
+ if (ff->fc->no_open) {
|
|
|
+ /*
|
|
|
+ * Drop the release request when client does not
|
|
|
+ * implement 'open'
|
|
|
+ */
|
|
|
+ req->background = 0;
|
|
|
+ path_put(&req->misc.release.path);
|
|
|
+ fuse_put_request(ff->fc, req);
|
|
|
+ } else if (sync) {
|
|
|
req->background = 0;
|
|
|
fuse_request_send(ff->fc, req);
|
|
|
path_put(&req->misc.release.path);
|
|
@@ -144,27 +152,36 @@ static void fuse_file_put(struct fuse_file *ff, bool sync)
|
|
|
int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
|
|
|
bool isdir)
|
|
|
{
|
|
|
- struct fuse_open_out outarg;
|
|
|
struct fuse_file *ff;
|
|
|
- int err;
|
|
|
int opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN;
|
|
|
|
|
|
ff = fuse_file_alloc(fc);
|
|
|
if (!ff)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- err = fuse_send_open(fc, nodeid, file, opcode, &outarg);
|
|
|
- if (err) {
|
|
|
- fuse_file_free(ff);
|
|
|
- return err;
|
|
|
+ ff->fh = 0;
|
|
|
+ ff->open_flags = FOPEN_KEEP_CACHE; /* Default for no-open */
|
|
|
+ if (!fc->no_open || isdir) {
|
|
|
+ struct fuse_open_out outarg;
|
|
|
+ int err;
|
|
|
+
|
|
|
+ err = fuse_send_open(fc, nodeid, file, opcode, &outarg);
|
|
|
+ if (!err) {
|
|
|
+ ff->fh = outarg.fh;
|
|
|
+ ff->open_flags = outarg.open_flags;
|
|
|
+
|
|
|
+ } else if (err != -ENOSYS || isdir) {
|
|
|
+ fuse_file_free(ff);
|
|
|
+ return err;
|
|
|
+ } else {
|
|
|
+ fc->no_open = 1;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if (isdir)
|
|
|
- outarg.open_flags &= ~FOPEN_DIRECT_IO;
|
|
|
+ ff->open_flags &= ~FOPEN_DIRECT_IO;
|
|
|
|
|
|
- ff->fh = outarg.fh;
|
|
|
ff->nodeid = nodeid;
|
|
|
- ff->open_flags = outarg.open_flags;
|
|
|
file->private_data = fuse_file_get(ff);
|
|
|
|
|
|
return 0;
|