Merge branch 'for-linus-4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/mason...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 9 Oct 2015 23:39:35 +0000 (16:39 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 9 Oct 2015 23:39:35 +0000 (16:39 -0700)
Pull btrfs fixes from Chris Mason:
 "These are small and assorted.  Neil's is the oldest, I dropped the
  ball thinking he was going to send it in"

* 'for-linus-4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs:
  Btrfs: support NFSv2 export
  Btrfs: open_ctree: Fix possible memory leak
  Btrfs: fix deadlock when finalizing block group creation
  Btrfs: update fix for read corruption of compressed and shared extents
  Btrfs: send, fix corner case for reference overwrite detection

1  2 
fs/btrfs/disk-io.c
fs/btrfs/extent_io.c
fs/btrfs/transaction.c

diff --combined fs/btrfs/disk-io.c
index 295795aebe0b42330cc1147e02340eb2c59f1d7b,807f6854acaa4f9d51e51db98abee1342505360d..1e60d00d4ea7c42104614ede9e203a1f56e6408a
@@@ -703,7 -703,7 +703,7 @@@ static int btree_io_failed_hook(struct 
        return -EIO;    /* we fixed nothing */
  }
  
 -static void end_workqueue_bio(struct bio *bio, int err)
 +static void end_workqueue_bio(struct bio *bio)
  {
        struct btrfs_end_io_wq *end_io_wq = bio->bi_private;
        struct btrfs_fs_info *fs_info;
        btrfs_work_func_t func;
  
        fs_info = end_io_wq->info;
 -      end_io_wq->error = err;
 +      end_io_wq->error = bio->bi_error;
  
        if (bio->bi_rw & REQ_WRITE) {
                if (end_io_wq->metadata == BTRFS_WQ_ENDIO_METADATA) {
@@@ -808,8 -808,7 +808,8 @@@ static void run_one_async_done(struct b
  
        /* If an error occured we just want to clean up the bio and move on */
        if (async->error) {
 -              bio_endio(async->bio, async->error);
 +              async->bio->bi_error = async->error;
 +              bio_endio(async->bio);
                return;
        }
  
@@@ -909,10 -908,8 +909,10 @@@ static int __btree_submit_bio_done(stru
         * submission context.  Just jump into btrfs_map_bio
         */
        ret = btrfs_map_bio(BTRFS_I(inode)->root, rw, bio, mirror_num, 1);
 -      if (ret)
 -              bio_endio(bio, ret);
 +      if (ret) {
 +              bio->bi_error = ret;
 +              bio_endio(bio);
 +      }
        return ret;
  }
  
@@@ -963,13 -960,10 +963,13 @@@ static int btree_submit_bio_hook(struc
                                          __btree_submit_bio_done);
        }
  
 -      if (ret) {
 +      if (ret)
 +              goto out_w_error;
 +      return 0;
 +
  out_w_error:
 -              bio_endio(bio, ret);
 -      }
 +      bio->bi_error = ret;
 +      bio_endio(bio);
        return ret;
  }
  
@@@ -1742,15 -1736,16 +1742,15 @@@ static void end_workqueue_fn(struct btr
  {
        struct bio *bio;
        struct btrfs_end_io_wq *end_io_wq;
 -      int error;
  
        end_io_wq = container_of(work, struct btrfs_end_io_wq, work);
        bio = end_io_wq->bio;
  
 -      error = end_io_wq->error;
 +      bio->bi_error = end_io_wq->error;
        bio->bi_private = end_io_wq->private;
        bio->bi_end_io = end_io_wq->end_io;
        kmem_cache_free(btrfs_end_io_wq_cache, end_io_wq);
 -      bio_endio(bio, error);
 +      bio_endio(bio);
  }
  
  static int cleaner_kthread(void *arg)
@@@ -2847,6 -2842,8 +2847,8 @@@ int open_ctree(struct super_block *sb
            !extent_buffer_uptodate(chunk_root->node)) {
                printk(KERN_ERR "BTRFS: failed to read chunk root on %s\n",
                       sb->s_id);
+               if (!IS_ERR(chunk_root->node))
+                       free_extent_buffer(chunk_root->node);
                chunk_root->node = NULL;
                goto fail_tree_roots;
        }
@@@ -2885,6 -2882,8 +2887,8 @@@ retry_root_backup
            !extent_buffer_uptodate(tree_root->node)) {
                printk(KERN_WARNING "BTRFS: failed to read tree root on %s\n",
                       sb->s_id);
+               if (!IS_ERR(tree_root->node))
+                       free_extent_buffer(tree_root->node);
                tree_root->node = NULL;
                goto recovery_tree_root;
        }
@@@ -3330,8 -3329,10 +3334,8 @@@ static int write_dev_supers(struct btrf
   * endio for the write_dev_flush, this will wake anyone waiting
   * for the barrier when it is done
   */
 -static void btrfs_end_empty_barrier(struct bio *bio, int err)
 +static void btrfs_end_empty_barrier(struct bio *bio)
  {
 -      if (err)
 -              clear_bit(BIO_UPTODATE, &bio->bi_flags);
        if (bio->bi_private)
                complete(bio->bi_private);
        bio_put(bio);
@@@ -3359,8 -3360,8 +3363,8 @@@ static int write_dev_flush(struct btrfs
  
                wait_for_completion(&device->flush_wait);
  
 -              if (!bio_flagged(bio, BIO_UPTODATE)) {
 -                      ret = -EIO;
 +              if (bio->bi_error) {
 +                      ret = bio->bi_error;
                        btrfs_dev_stat_inc_and_print(device,
                                BTRFS_DEV_STAT_FLUSH_ERRS);
                }
diff --combined fs/btrfs/extent_io.c
index e2357e31609a2e8469b38c7e95b66f6dd68fcd93,363726b08a51e6f23ba984985fd7aaef2cfac1c2..3915c9473e9445d4aeada81c8fb96af7fb521f2c
@@@ -2486,7 -2486,7 +2486,7 @@@ int end_extent_writepage(struct page *p
   * Scheduling is not allowed, so the extent state tree is expected
   * to have one and only one object corresponding to this IO.
   */
 -static void end_bio_extent_writepage(struct bio *bio, int err)
 +static void end_bio_extent_writepage(struct bio *bio)
  {
        struct bio_vec *bvec;
        u64 start;
                start = page_offset(page);
                end = start + bvec->bv_offset + bvec->bv_len - 1;
  
 -              if (end_extent_writepage(page, err, start, end))
 +              if (end_extent_writepage(page, bio->bi_error, start, end))
                        continue;
  
                end_page_writeback(page);
@@@ -2548,10 -2548,10 +2548,10 @@@ endio_readpage_release_extent(struct ex
   * Scheduling is not allowed, so the extent state tree is expected
   * to have one and only one object corresponding to this IO.
   */
 -static void end_bio_extent_readpage(struct bio *bio, int err)
 +static void end_bio_extent_readpage(struct bio *bio)
  {
        struct bio_vec *bvec;
 -      int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 +      int uptodate = !bio->bi_error;
        struct btrfs_io_bio *io_bio = btrfs_io_bio(bio);
        struct extent_io_tree *tree;
        u64 offset = 0;
        int ret;
        int i;
  
 -      if (err)
 -              uptodate = 0;
 -
        bio_for_each_segment_all(bvec, bio, i) {
                struct page *page = bvec->bv_page;
                struct inode *inode = page->mapping->host;
  
                pr_debug("end_bio_extent_readpage: bi_sector=%llu, err=%d, "
 -                       "mirror=%u\n", (u64)bio->bi_iter.bi_sector, err,
 -                       io_bio->mirror_num);
 +                       "mirror=%u\n", (u64)bio->bi_iter.bi_sector,
 +                       bio->bi_error, io_bio->mirror_num);
                tree = &BTRFS_I(inode)->io_tree;
  
                /* We always issue full-page reads, but if some block
  
                if (tree->ops && tree->ops->readpage_io_failed_hook) {
                        ret = tree->ops->readpage_io_failed_hook(page, mirror);
 -                      if (!ret && !err &&
 -                          test_bit(BIO_UPTODATE, &bio->bi_flags))
 +                      if (!ret && !bio->bi_error)
                                uptodate = 1;
                } else {
                        /*
                        ret = bio_readpage_error(bio, offset, page, start, end,
                                                 mirror);
                        if (ret == 0) {
 -                              uptodate =
 -                                      test_bit(BIO_UPTODATE, &bio->bi_flags);
 -                              if (err)
 -                                      uptodate = 0;
 +                              uptodate = !bio->bi_error;
                                offset += len;
                                continue;
                        }
@@@ -2677,7 -2684,7 +2677,7 @@@ readpage_ok
                endio_readpage_release_extent(tree, extent_start, extent_len,
                                              uptodate);
        if (io_bio->end_io)
 -              io_bio->end_io(io_bio, err);
 +              io_bio->end_io(io_bio, bio->bi_error);
        bio_put(bio);
  }
  
@@@ -2803,7 -2810,9 +2803,7 @@@ static int submit_extent_page(int rw, s
  {
        int ret = 0;
        struct bio *bio;
 -      int nr;
        int contig = 0;
 -      int this_compressed = bio_flags & EXTENT_BIO_COMPRESSED;
        int old_compressed = prev_bio_flags & EXTENT_BIO_COMPRESSED;
        size_t page_size = min_t(size_t, size, PAGE_CACHE_SIZE);
  
                        return 0;
                }
        }
 -      if (this_compressed)
 -              nr = BIO_MAX_PAGES;
 -      else
 -              nr = bio_get_nr_vecs(bdev);
  
 -      bio = btrfs_bio_alloc(bdev, sector, nr, GFP_NOFS | __GFP_HIGH);
 +      bio = btrfs_bio_alloc(bdev, sector, BIO_MAX_PAGES,
 +                      GFP_NOFS | __GFP_HIGH);
        if (!bio)
                return -ENOMEM;
  
@@@ -3132,12 -3144,12 +3132,12 @@@ static inline void __do_contiguous_read
                                             get_extent_t *get_extent,
                                             struct extent_map **em_cached,
                                             struct bio **bio, int mirror_num,
-                                            unsigned long *bio_flags, int rw)
+                                            unsigned long *bio_flags, int rw,
+                                            u64 *prev_em_start)
  {
        struct inode *inode;
        struct btrfs_ordered_extent *ordered;
        int index;
-       u64 prev_em_start = (u64)-1;
  
        inode = pages[0]->mapping->host;
        while (1) {
  
        for (index = 0; index < nr_pages; index++) {
                __do_readpage(tree, pages[index], get_extent, em_cached, bio,
-                             mirror_num, bio_flags, rw, &prev_em_start);
+                             mirror_num, bio_flags, rw, prev_em_start);
                page_cache_release(pages[index]);
        }
  }
@@@ -3163,7 -3175,8 +3163,8 @@@ static void __extent_readpages(struct e
                               int nr_pages, get_extent_t *get_extent,
                               struct extent_map **em_cached,
                               struct bio **bio, int mirror_num,
-                              unsigned long *bio_flags, int rw)
+                              unsigned long *bio_flags, int rw,
+                              u64 *prev_em_start)
  {
        u64 start = 0;
        u64 end = 0;
                                                  index - first_index, start,
                                                  end, get_extent, em_cached,
                                                  bio, mirror_num, bio_flags,
-                                                 rw);
+                                                 rw, prev_em_start);
                        start = page_start;
                        end = start + PAGE_CACHE_SIZE - 1;
                        first_index = index;
                __do_contiguous_readpages(tree, &pages[first_index],
                                          index - first_index, start,
                                          end, get_extent, em_cached, bio,
-                                         mirror_num, bio_flags, rw);
+                                         mirror_num, bio_flags, rw,
+                                         prev_em_start);
  }
  
  static int __extent_read_full_page(struct extent_io_tree *tree,
@@@ -3746,7 -3760,7 +3748,7 @@@ static void set_btree_ioerr(struct pag
        }
  }
  
 -static void end_bio_extent_buffer_writepage(struct bio *bio, int err)
 +static void end_bio_extent_buffer_writepage(struct bio *bio)
  {
        struct bio_vec *bvec;
        struct extent_buffer *eb;
                BUG_ON(!eb);
                done = atomic_dec_and_test(&eb->io_pages);
  
 -              if (err || test_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags)) {
 +              if (bio->bi_error ||
 +                  test_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags)) {
                        ClearPageUptodate(page);
                        set_btree_ioerr(page);
                }
@@@ -4207,6 -4220,7 +4209,7 @@@ int extent_readpages(struct extent_io_t
        struct page *page;
        struct extent_map *em_cached = NULL;
        int nr = 0;
+       u64 prev_em_start = (u64)-1;
  
        for (page_idx = 0; page_idx < nr_pages; page_idx++) {
                page = list_entry(pages->prev, struct page, lru);
                if (nr < ARRAY_SIZE(pagepool))
                        continue;
                __extent_readpages(tree, pagepool, nr, get_extent, &em_cached,
-                                  &bio, 0, &bio_flags, READ);
+                                  &bio, 0, &bio_flags, READ, &prev_em_start);
                nr = 0;
        }
        if (nr)
                __extent_readpages(tree, pagepool, nr, get_extent, &em_cached,
-                                  &bio, 0, &bio_flags, READ);
+                                  &bio, 0, &bio_flags, READ, &prev_em_start);
  
        if (em_cached)
                free_extent_map(em_cached);
diff --combined fs/btrfs/transaction.c
index 74bc3338418be39badb2eb73160c20b3e2240c74,376191c7da1370f3b102c2c90bcba2db9103fcf1..a5b06442f0bf9d1630f201da3e0eb5c0422e8cc9
@@@ -557,6 -557,7 +557,7 @@@ again
        h->delayed_ref_elem.seq = 0;
        h->type = type;
        h->allocating_chunk = false;
+       h->can_flush_pending_bgs = true;
        h->reloc_reserved = false;
        h->sync = false;
        INIT_LIST_HEAD(&h->qgroup_ref_list);
@@@ -1672,7 -1673,9 +1673,7 @@@ static void do_async_commit(struct work
         * Tell lockdep about it.
         */
        if (ac->newtrans->type & __TRANS_FREEZABLE)
 -              rwsem_acquire_read(
 -                   &ac->root->fs_info->sb->s_writers.lock_map[SB_FREEZE_FS-1],
 -                   0, 1, _THIS_IP_);
 +              __sb_writers_acquired(ac->root->fs_info->sb, SB_FREEZE_FS);
  
        current->journal_info = ac->newtrans;
  
@@@ -1711,7 -1714,9 +1712,7 @@@ int btrfs_commit_transaction_async(stru
         * async commit thread will be the one to unlock it.
         */
        if (ac->newtrans->type & __TRANS_FREEZABLE)
 -              rwsem_release(
 -                      &root->fs_info->sb->s_writers.lock_map[SB_FREEZE_FS-1],
 -                      1, _THIS_IP_);
 +              __sb_writers_release(root->fs_info->sb, SB_FREEZE_FS);
  
        schedule_work(&ac->work);