fuse: remove unused arg in fuse_write_file_get()
[linux-2.6-microblaze.git] / fs / fuse / file.c
index 4722fa3..f196680 100644 (file)
@@ -198,12 +198,11 @@ void fuse_finish_open(struct inode *inode, struct file *file)
        struct fuse_file *ff = file->private_data;
        struct fuse_conn *fc = get_fuse_conn(inode);
 
-       if (!(ff->open_flags & FOPEN_KEEP_CACHE))
-               invalidate_inode_pages2(inode->i_mapping);
        if (ff->open_flags & FOPEN_STREAM)
                stream_open(inode, file);
        else if (ff->open_flags & FOPEN_NONSEEKABLE)
                nonseekable_open(inode, file);
+
        if (fc->atomic_o_trunc && (file->f_flags & O_TRUNC)) {
                struct fuse_inode *fi = get_fuse_inode(inode);
 
@@ -211,10 +210,14 @@ void fuse_finish_open(struct inode *inode, struct file *file)
                fi->attr_version = atomic64_inc_return(&fc->attr_version);
                i_size_write(inode, 0);
                spin_unlock(&fi->lock);
+               truncate_pagecache(inode, 0);
                fuse_invalidate_attr(inode);
                if (fc->writeback_cache)
                        file_update_time(file);
+       } else if (!(ff->open_flags & FOPEN_KEEP_CACHE)) {
+               invalidate_inode_pages2(inode->i_mapping);
        }
+
        if ((file->f_mode & FMODE_WRITE) && fc->writeback_cache)
                fuse_link_write_file(file);
 }
@@ -389,6 +392,7 @@ struct fuse_writepage_args {
        struct list_head queue_entry;
        struct fuse_writepage_args *next;
        struct inode *inode;
+       struct fuse_sync_bucket *bucket;
 };
 
 static struct fuse_writepage_args *fuse_find_writeback(struct fuse_inode *fi,
@@ -645,7 +649,7 @@ static ssize_t fuse_get_res_by_io(struct fuse_io_priv *io)
  * == bytes_transferred or rw == WRITE, the caller sets 'pos' to -1.
  *
  * An example:
- * User requested DIO read of 64K. It was splitted into two 32K fuse requests,
+ * User requested DIO read of 64K. It was split into two 32K fuse requests,
  * both submitted asynchronously. The first of them was ACKed by userspace as
  * fully completed (req->out.args[0].size == 32K) resulting in pos == -1. The
  * second request was ACKed as short, e.g. only 1K was read, resulting in
@@ -1403,7 +1407,7 @@ static int fuse_get_user_pages(struct fuse_args_pages *ap, struct iov_iter *ii,
                nbytes += ret;
 
                ret += start;
-               npages = (ret + PAGE_SIZE - 1) / PAGE_SIZE;
+               npages = DIV_ROUND_UP(ret, PAGE_SIZE);
 
                ap->descs[ap->num_pages].offset = start;
                fuse_page_descs_length_init(ap->descs, ap->num_pages, npages);
@@ -1608,6 +1612,9 @@ static void fuse_writepage_free(struct fuse_writepage_args *wpa)
        struct fuse_args_pages *ap = &wpa->ia.ap;
        int i;
 
+       if (wpa->bucket)
+               fuse_sync_bucket_dec(wpa->bucket);
+
        for (i = 0; i < ap->num_pages; i++)
                __free_page(ap->pages[i]);
 
@@ -1813,8 +1820,7 @@ static void fuse_writepage_end(struct fuse_mount *fm, struct fuse_args *args,
        fuse_writepage_free(wpa);
 }
 
-static struct fuse_file *__fuse_write_file_get(struct fuse_conn *fc,
-                                              struct fuse_inode *fi)
+static struct fuse_file *__fuse_write_file_get(struct fuse_inode *fi)
 {
        struct fuse_file *ff = NULL;
 
@@ -1829,22 +1835,20 @@ static struct fuse_file *__fuse_write_file_get(struct fuse_conn *fc,
        return ff;
 }
 
-static struct fuse_file *fuse_write_file_get(struct fuse_conn *fc,
-                                            struct fuse_inode *fi)
+static struct fuse_file *fuse_write_file_get(struct fuse_inode *fi)
 {
-       struct fuse_file *ff = __fuse_write_file_get(fc, fi);
+       struct fuse_file *ff = __fuse_write_file_get(fi);
        WARN_ON(!ff);
        return ff;
 }
 
 int fuse_write_inode(struct inode *inode, struct writeback_control *wbc)
 {
-       struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_inode *fi = get_fuse_inode(inode);
        struct fuse_file *ff;
        int err;
 
-       ff = __fuse_write_file_get(fc, fi);
+       ff = __fuse_write_file_get(fi);
        err = fuse_flush_times(inode, ff);
        if (ff)
                fuse_file_put(ff, false, false);
@@ -1871,6 +1875,20 @@ static struct fuse_writepage_args *fuse_writepage_args_alloc(void)
 
 }
 
+static void fuse_writepage_add_to_bucket(struct fuse_conn *fc,
+                                        struct fuse_writepage_args *wpa)
+{
+       if (!fc->sync_fs)
+               return;
+
+       rcu_read_lock();
+       /* Prevent resurrection of dead bucket in unlikely race with syncfs */
+       do {
+               wpa->bucket = rcu_dereference(fc->curr_bucket);
+       } while (unlikely(!atomic_inc_not_zero(&wpa->bucket->count)));
+       rcu_read_unlock();
+}
+
 static int fuse_writepage_locked(struct page *page)
 {
        struct address_space *mapping = page->mapping;
@@ -1894,10 +1912,11 @@ static int fuse_writepage_locked(struct page *page)
                goto err_free;
 
        error = -EIO;
-       wpa->ia.ff = fuse_write_file_get(fc, fi);
+       wpa->ia.ff = fuse_write_file_get(fi);
        if (!wpa->ia.ff)
                goto err_nofile;
 
+       fuse_writepage_add_to_bucket(fc, wpa);
        fuse_write_args_fill(&wpa->ia, wpa->ia.ff, page_offset(page), 0);
 
        copy_highpage(tmp_page, page);
@@ -2113,7 +2132,7 @@ static int fuse_writepages_fill(struct page *page,
 
        if (!data->ff) {
                err = -EIO;
-               data->ff = fuse_write_file_get(fc, fi);
+               data->ff = fuse_write_file_get(fi);
                if (!data->ff)
                        goto out_unlock;
        }
@@ -2148,6 +2167,8 @@ static int fuse_writepages_fill(struct page *page,
                        __free_page(tmp_page);
                        goto out_unlock;
                }
+               fuse_writepage_add_to_bucket(fc, wpa);
+
                data->max_pages = 1;
 
                ap = &wpa->ia.ap;
@@ -2881,7 +2902,7 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
 
 static int fuse_writeback_range(struct inode *inode, loff_t start, loff_t end)
 {
-       int err = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       int err = filemap_write_and_wait_range(inode->i_mapping, start, -1);
 
        if (!err)
                fuse_sync_writes(inode);
@@ -2905,11 +2926,13 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
        };
        int err;
        bool lock_inode = !(mode & FALLOC_FL_KEEP_SIZE) ||
-                          (mode & FALLOC_FL_PUNCH_HOLE);
+                          (mode & (FALLOC_FL_PUNCH_HOLE |
+                                   FALLOC_FL_ZERO_RANGE));
 
        bool block_faults = FUSE_IS_DAX(inode) && lock_inode;
 
-       if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
+       if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE |
+                    FALLOC_FL_ZERO_RANGE))
                return -EOPNOTSUPP;
 
        if (fm->fc->no_fallocate)
@@ -2924,7 +2947,7 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
                                goto out;
                }
 
-               if (mode & FALLOC_FL_PUNCH_HOLE) {
+               if (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE)) {
                        loff_t endbyte = offset + length - 1;
 
                        err = fuse_writeback_range(inode, offset, endbyte);
@@ -2964,7 +2987,7 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
                        file_update_time(file);
        }
 
-       if (mode & FALLOC_FL_PUNCH_HOLE)
+       if (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE))
                truncate_pagecache_range(inode, offset, offset + length - 1);
 
        fuse_invalidate_attr(inode);