callers of iov_copy_from_user_atomic() don't need pagecache_disable()
[platform/adaptation/renesas_rcar/renesas_kernel.git] / fs / fuse / file.c
index 7e70506..a91d3b4 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++) {
@@ -986,9 +1003,7 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req,
                if (mapping_writably_mapped(mapping))
                        flush_dcache_page(page);
 
-               pagefault_disable();
                tmp = iov_iter_copy_from_user_atomic(page, ii, offset, bytes);
-               pagefault_enable();
                flush_dcache_page(page);
 
                mark_page_accessed(page);
@@ -2710,6 +2725,9 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
        inode = file->f_mapping->host;
        i_size = i_size_read(inode);
 
+       if ((rw == READ) && (offset > i_size))
+               return 0;
+
        /* optimization for short read */
        if (async_dio && rw != WRITE && offset + count > i_size) {
                if (offset >= i_size)