OSDN Git Service

Merge tag 'v4.4.207' into 10
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / fs / btrfs / file.c
index d4a6eef..73b547f 100644 (file)
@@ -1525,6 +1525,7 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,
                }
 
                reserve_bytes = num_pages << PAGE_CACHE_SHIFT;
+               only_release_metadata = false;
 
                if ((BTRFS_I(inode)->flags & (BTRFS_INODE_NODATACOW |
                                              BTRFS_INODE_PREALLOC)) &&
@@ -1659,7 +1660,6 @@ again:
                        set_extent_bit(&BTRFS_I(inode)->io_tree, lockstart,
                                       lockend, EXTENT_NORESERVE, NULL,
                                       NULL, GFP_NOFS);
-                       only_release_metadata = false;
                }
 
                btrfs_drop_pages(pages, num_pages);
@@ -1861,10 +1861,19 @@ int btrfs_release_file(struct inode *inode, struct file *filp)
 static int start_ordered_ops(struct inode *inode, loff_t start, loff_t end)
 {
        int ret;
+       struct blk_plug plug;
 
+       /*
+        * This is only called in fsync, which would do synchronous writes, so
+        * a plug can merge adjacent IOs as much as possible.  Esp. in case of
+        * multiple disks using raid profile, a large IO can be split to
+        * several segments of stripe length (currently 64K).
+        */
+       blk_start_plug(&plug);
        atomic_inc(&BTRFS_I(inode)->sync_writers);
        ret = btrfs_fdatawrite_range(inode, start, end);
        atomic_dec(&BTRFS_I(inode)->sync_writers);
+       blk_finish_plug(&plug);
 
        return ret;
 }
@@ -1892,6 +1901,18 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
        u64 len;
 
        /*
+        * If the inode needs a full sync, make sure we use a full range to
+        * avoid log tree corruption, due to hole detection racing with ordered
+        * extent completion for adjacent ranges, and assertion failures during
+        * hole detection.
+        */
+       if (test_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
+                    &BTRFS_I(inode)->runtime_flags)) {
+               start = 0;
+               end = LLONG_MAX;
+       }
+
+       /*
         * The range length can be represented by u64, we have to do the typecasts
         * to avoid signed overflow if it's [0, LLONG_MAX] eg. from fsync()
         */