Merge tag 'for-4.18-rc5-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 21 Jul 2018 23:42:03 +0000 (16:42 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 21 Jul 2018 23:42:03 +0000 (16:42 -0700)
Pull btrfs fix from David Sterba:
 "A fix of a corruption regarding fsync and clone, under some very
  specific conditions explained in the patch.

  The fix is marked for stable 3.16+ so I'd like to get it merged now
  given the impact"

* tag 'for-4.18-rc5-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  Btrfs: fix file data corruption after cloning a range and fsync

1  2 
fs/btrfs/extent_io.c

diff --combined fs/btrfs/extent_io.c
index e55843f536bcaa03b6b2aa8e1c3ffb67b946df88,8fd86e29085f20ddcb368b7d62129a45b01b987c..b3e45714d28f0507f40e590ff14076fcdb7728a5
@@@ -26,7 -26,7 +26,7 @@@
  
  static struct kmem_cache *extent_state_cache;
  static struct kmem_cache *extent_buffer_cache;
 -static struct bio_set *btrfs_bioset;
 +static struct bio_set btrfs_bioset;
  
  static inline bool extent_state_in_tree(const struct extent_state *state)
  {
@@@ -162,18 -162,20 +162,18 @@@ int __init extent_io_init(void
        if (!extent_buffer_cache)
                goto free_state_cache;
  
 -      btrfs_bioset = bioset_create(BIO_POOL_SIZE,
 -                                   offsetof(struct btrfs_io_bio, bio),
 -                                   BIOSET_NEED_BVECS);
 -      if (!btrfs_bioset)
 +      if (bioset_init(&btrfs_bioset, BIO_POOL_SIZE,
 +                      offsetof(struct btrfs_io_bio, bio),
 +                      BIOSET_NEED_BVECS))
                goto free_buffer_cache;
  
 -      if (bioset_integrity_create(btrfs_bioset, BIO_POOL_SIZE))
 +      if (bioset_integrity_create(&btrfs_bioset, BIO_POOL_SIZE))
                goto free_bioset;
  
        return 0;
  
  free_bioset:
 -      bioset_free(btrfs_bioset);
 -      btrfs_bioset = NULL;
 +      bioset_exit(&btrfs_bioset);
  
  free_buffer_cache:
        kmem_cache_destroy(extent_buffer_cache);
@@@ -196,7 -198,8 +196,7 @@@ void __cold extent_io_exit(void
        rcu_barrier();
        kmem_cache_destroy(extent_state_cache);
        kmem_cache_destroy(extent_buffer_cache);
 -      if (btrfs_bioset)
 -              bioset_free(btrfs_bioset);
 +      bioset_exit(&btrfs_bioset);
  }
  
  void extent_io_tree_init(struct extent_io_tree *tree,
@@@ -2676,7 -2679,7 +2676,7 @@@ struct bio *btrfs_bio_alloc(struct bloc
  {
        struct bio *bio;
  
 -      bio = bio_alloc_bioset(GFP_NOFS, BIO_MAX_PAGES, btrfs_bioset);
 +      bio = bio_alloc_bioset(GFP_NOFS, BIO_MAX_PAGES, &btrfs_bioset);
        bio_set_dev(bio, bdev);
        bio->bi_iter.bi_sector = first_byte >> 9;
        btrfs_io_bio_init(btrfs_io_bio(bio));
@@@ -2689,7 -2692,7 +2689,7 @@@ struct bio *btrfs_bio_clone(struct bio 
        struct bio *new;
  
        /* Bio allocation backed by a bioset does not fail */
 -      new = bio_clone_fast(bio, GFP_NOFS, btrfs_bioset);
 +      new = bio_clone_fast(bio, GFP_NOFS, &btrfs_bioset);
        btrfs_bio = btrfs_io_bio(new);
        btrfs_io_bio_init(btrfs_bio);
        btrfs_bio->iter = bio->bi_iter;
@@@ -2701,7 -2704,7 +2701,7 @@@ struct bio *btrfs_io_bio_alloc(unsigne
        struct bio *bio;
  
        /* Bio allocation backed by a bioset does not fail */
 -      bio = bio_alloc_bioset(GFP_NOFS, nr_iovecs, btrfs_bioset);
 +      bio = bio_alloc_bioset(GFP_NOFS, nr_iovecs, &btrfs_bioset);
        btrfs_io_bio_init(btrfs_io_bio(bio));
        return bio;
  }
@@@ -2712,7 -2715,7 +2712,7 @@@ struct bio *btrfs_bio_clone_partial(str
        struct btrfs_io_bio *btrfs_bio;
  
        /* this will never fail when it's backed by a bioset */
 -      bio = bio_clone_fast(orig, GFP_NOFS, btrfs_bioset);
 +      bio = bio_clone_fast(orig, GFP_NOFS, &btrfs_bioset);
        ASSERT(bio);
  
        btrfs_bio = btrfs_io_bio(bio);
@@@ -4238,8 -4241,9 +4238,9 @@@ int try_release_extent_mapping(struct p
        struct extent_map *em;
        u64 start = page_offset(page);
        u64 end = start + PAGE_SIZE - 1;
-       struct extent_io_tree *tree = &BTRFS_I(page->mapping->host)->io_tree;
-       struct extent_map_tree *map = &BTRFS_I(page->mapping->host)->extent_tree;
+       struct btrfs_inode *btrfs_inode = BTRFS_I(page->mapping->host);
+       struct extent_io_tree *tree = &btrfs_inode->io_tree;
+       struct extent_map_tree *map = &btrfs_inode->extent_tree;
  
        if (gfpflags_allow_blocking(mask) &&
            page->mapping->host->i_size > SZ_16M) {
                                            extent_map_end(em) - 1,
                                            EXTENT_LOCKED | EXTENT_WRITEBACK,
                                            0, NULL)) {
+                               set_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
+                                       &btrfs_inode->runtime_flags);
                                remove_extent_mapping(map, em);
                                /* once for the rb tree */
                                free_extent_map(em);