]> Pileus Git - ~andy/linux/blobdiff - fs/fuse/file.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[~andy/linux] / fs / fuse / file.c
index 89fdfd1919af90a87cd8e3e607e13cb507d1f4a3..77bcc303c3aeb9214ba4b13098da14fb8bcbe20b 100644 (file)
@@ -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;
@@ -687,7 +704,7 @@ static int fuse_readpage(struct file *file, struct page *page)
                SetPageUptodate(page);
        }
 
-       fuse_invalidate_attr(inode); /* atime changed */
+       fuse_invalidate_atime(inode);
  out:
        unlock_page(page);
        return err;
@@ -716,7 +733,7 @@ static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req)
                        fuse_read_update_size(inode, pos,
                                              req->misc.read.attr_ver);
                }
-               fuse_invalidate_attr(inode); /* atime changed */
+               fuse_invalidate_atime(inode);
        }
 
        for (i = 0; i < req->num_pages; i++) {