]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'for-linus-4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/mason...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 11 Sep 2015 19:38:25 +0000 (12:38 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 11 Sep 2015 19:38:25 +0000 (12:38 -0700)
Pull btrfs cleanups and fixes from Chris Mason:
 "These are small cleanups, and also some fixes for our async worker
  thread initialization.

  I was having some trouble testing these, but it ended up being a
  combination of changing around my test servers and a shiny new
  schedule while atomic from the new start/finish_plug in
  writeback_sb_inodes().

  That one only hits on btrfs raid5/6 or MD raid10, and if I wasn't
  changing a bunch of things in my test setup at once it would have been
  really clear.  Fix for writeback_sb_inodes() on the way as well"

* 'for-linus-4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs:
  Btrfs: cleanup: remove unnecessary check before btrfs_free_path is called
  btrfs: async_thread: Fix workqueue 'max_active' value when initializing
  btrfs: Add raid56 support for updating  num_tolerated_disk_barrier_failures in btrfs_balance
  btrfs: Cleanup for btrfs_calc_num_tolerated_disk_barrier_failures
  btrfs: Remove noused chunk_tree and chunk_objectid from scrub_enumerate_chunks and scrub_chunk
  btrfs: Update out-of-date "skip parity stripe" comment

1  2 
fs/btrfs/disk-io.c
fs/btrfs/inode.c
fs/btrfs/scrub.c
fs/btrfs/volumes.c

diff --combined fs/btrfs/disk-io.c
index 9ebd34f1c67752590beaae1288ed506f8b9fc561,0b658d0230f02911142a6557c1daca92c6fe6775..0d98aee34fee8f716771e46a70cbee478ac27e2d
@@@ -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)
@@@ -3330,8 -3325,10 +3330,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 -3356,8 +3359,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);
                }
@@@ -3443,6 -3440,26 +3443,26 @@@ static int barrier_all_devices(struct b
        return 0;
  }
  
+ int btrfs_get_num_tolerated_disk_barrier_failures(u64 flags)
+ {
+       if ((flags & (BTRFS_BLOCK_GROUP_DUP |
+                     BTRFS_BLOCK_GROUP_RAID0 |
+                     BTRFS_AVAIL_ALLOC_BIT_SINGLE)) ||
+           ((flags & BTRFS_BLOCK_GROUP_PROFILE_MASK) == 0))
+               return 0;
+       if (flags & (BTRFS_BLOCK_GROUP_RAID1 |
+                    BTRFS_BLOCK_GROUP_RAID5 |
+                    BTRFS_BLOCK_GROUP_RAID10))
+               return 1;
+       if (flags & BTRFS_BLOCK_GROUP_RAID6)
+               return 2;
+       pr_warn("BTRFS: unknown raid type: %llu\n", flags);
+       return 0;
+ }
  int btrfs_calc_num_tolerated_disk_barrier_failures(
        struct btrfs_fs_info *fs_info)
  {
                       BTRFS_BLOCK_GROUP_SYSTEM,
                       BTRFS_BLOCK_GROUP_METADATA,
                       BTRFS_BLOCK_GROUP_DATA | BTRFS_BLOCK_GROUP_METADATA};
-       int num_types = 4;
        int i;
        int c;
        int num_tolerated_disk_barrier_failures =
                (int)fs_info->fs_devices->num_devices;
  
-       for (i = 0; i < num_types; i++) {
+       for (i = 0; i < ARRAY_SIZE(types); i++) {
                struct btrfs_space_info *tmp;
  
                sinfo = NULL;
  
                down_read(&sinfo->groups_sem);
                for (c = 0; c < BTRFS_NR_RAID_TYPES; c++) {
-                       if (!list_empty(&sinfo->block_groups[c])) {
-                               u64 flags;
-                               btrfs_get_block_group_info(
-                                       &sinfo->block_groups[c], &space);
-                               if (space.total_bytes == 0 ||
-                                   space.used_bytes == 0)
-                                       continue;
-                               flags = space.flags;
-                               /*
-                                * return
-                                * 0: if dup, single or RAID0 is configured for
-                                *    any of metadata, system or data, else
-                                * 1: if RAID5 is configured, or if RAID1 or
-                                *    RAID10 is configured and only two mirrors
-                                *    are used, else
-                                * 2: if RAID6 is configured, else
-                                * num_mirrors - 1: if RAID1 or RAID10 is
-                                *                  configured and more than
-                                *                  2 mirrors are used.
-                                */
-                               if (num_tolerated_disk_barrier_failures > 0 &&
-                                   ((flags & (BTRFS_BLOCK_GROUP_DUP |
-                                              BTRFS_BLOCK_GROUP_RAID0)) ||
-                                    ((flags & BTRFS_BLOCK_GROUP_PROFILE_MASK)
-                                     == 0)))
-                                       num_tolerated_disk_barrier_failures = 0;
-                               else if (num_tolerated_disk_barrier_failures > 1) {
-                                       if (flags & (BTRFS_BLOCK_GROUP_RAID1 |
-                                           BTRFS_BLOCK_GROUP_RAID5 |
-                                           BTRFS_BLOCK_GROUP_RAID10)) {
-                                               num_tolerated_disk_barrier_failures = 1;
-                                       } else if (flags &
-                                                  BTRFS_BLOCK_GROUP_RAID6) {
-                                               num_tolerated_disk_barrier_failures = 2;
-                                       }
-                               }
-                       }
+                       u64 flags;
+                       if (list_empty(&sinfo->block_groups[c]))
+                               continue;
+                       btrfs_get_block_group_info(&sinfo->block_groups[c],
+                                                  &space);
+                       if (space.total_bytes == 0 || space.used_bytes == 0)
+                               continue;
+                       flags = space.flags;
+                       num_tolerated_disk_barrier_failures = min(
+                               num_tolerated_disk_barrier_failures,
+                               btrfs_get_num_tolerated_disk_barrier_failures(
+                                       flags));
                }
                up_read(&sinfo->groups_sem);
        }
diff --combined fs/btrfs/inode.c
index 237da012f7d09e3ac0e4c4aabef8224a5d5a06f1,37dd8d0f1fb330c04bea3d734637be9033758ab2..a0fa7253a2d77b6faa2e71366c762b331cd784b2
@@@ -1845,10 -1845,8 +1845,10 @@@ static int __btrfs_submit_bio_done(stru
        int ret;
  
        ret = btrfs_map_bio(root, rw, bio, mirror_num, 1);
 -      if (ret)
 -              bio_endio(bio, ret);
 +      if (ret) {
 +              bio->bi_error = ret;
 +              bio_endio(bio);
 +      }
        return ret;
  }
  
@@@ -1908,10 -1906,8 +1908,10 @@@ mapit
        ret = btrfs_map_bio(root, rw, bio, mirror_num, 0);
  
  out:
 -      if (ret < 0)
 -              bio_endio(bio, ret);
 +      if (ret < 0) {
 +              bio->bi_error = ret;
 +              bio_endio(bio);
 +      }
        return ret;
  }
  
@@@ -6909,8 -6905,7 +6909,7 @@@ out
  
        trace_btrfs_get_extent(root, em);
  
-       if (path)
-               btrfs_free_path(path);
+       btrfs_free_path(path);
        if (trans) {
                ret = btrfs_end_transaction(trans, root);
                if (!err)
@@@ -7721,13 -7716,13 +7720,13 @@@ struct btrfs_retry_complete 
        int uptodate;
  };
  
 -static void btrfs_retry_endio_nocsum(struct bio *bio, int err)
 +static void btrfs_retry_endio_nocsum(struct bio *bio)
  {
        struct btrfs_retry_complete *done = bio->bi_private;
        struct bio_vec *bvec;
        int i;
  
 -      if (err)
 +      if (bio->bi_error)
                goto end;
  
        done->uptodate = 1;
@@@ -7776,7 -7771,7 +7775,7 @@@ try_again
        return 0;
  }
  
 -static void btrfs_retry_endio(struct bio *bio, int err)
 +static void btrfs_retry_endio(struct bio *bio)
  {
        struct btrfs_retry_complete *done = bio->bi_private;
        struct btrfs_io_bio *io_bio = btrfs_io_bio(bio);
        int ret;
        int i;
  
 -      if (err)
 +      if (bio->bi_error)
                goto end;
  
        uptodate = 1;
@@@ -7868,13 -7863,12 +7867,13 @@@ static int btrfs_subio_endio_read(struc
        }
  }
  
 -static void btrfs_endio_direct_read(struct bio *bio, int err)
 +static void btrfs_endio_direct_read(struct bio *bio)
  {
        struct btrfs_dio_private *dip = bio->bi_private;
        struct inode *inode = dip->inode;
        struct bio *dio_bio;
        struct btrfs_io_bio *io_bio = btrfs_io_bio(bio);
 +      int err = bio->bi_error;
  
        if (dip->flags & BTRFS_DIO_ORIG_BIO_SUBMITTED)
                err = btrfs_subio_endio_read(inode, io_bio, err);
  
        kfree(dip);
  
 -      /* If we had a csum failure make sure to clear the uptodate flag */
 -      if (err)
 -              clear_bit(BIO_UPTODATE, &dio_bio->bi_flags);
 -      dio_end_io(dio_bio, err);
 +      dio_end_io(dio_bio, bio->bi_error);
  
        if (io_bio->end_io)
                io_bio->end_io(io_bio, err);
        bio_put(bio);
  }
  
 -static void btrfs_endio_direct_write(struct bio *bio, int err)
 +static void btrfs_endio_direct_write(struct bio *bio)
  {
        struct btrfs_dio_private *dip = bio->bi_private;
        struct inode *inode = dip->inode;
  again:
        ret = btrfs_dec_test_first_ordered_pending(inode, &ordered,
                                                   &ordered_offset,
 -                                                 ordered_bytes, !err);
 +                                                 ordered_bytes,
 +                                                 !bio->bi_error);
        if (!ret)
                goto out_test;
  
@@@ -7930,7 -7926,10 +7929,7 @@@ out_test
  
        kfree(dip);
  
 -      /* If we had an error make sure to clear the uptodate flag */
 -      if (err)
 -              clear_bit(BIO_UPTODATE, &dio_bio->bi_flags);
 -      dio_end_io(dio_bio, err);
 +      dio_end_io(dio_bio, bio->bi_error);
        bio_put(bio);
  }
  
@@@ -7945,10 -7944,9 +7944,10 @@@ static int __btrfs_submit_bio_start_dir
        return 0;
  }
  
 -static void btrfs_end_dio_bio(struct bio *bio, int err)
 +static void btrfs_end_dio_bio(struct bio *bio)
  {
        struct btrfs_dio_private *dip = bio->bi_private;
 +      int err = bio->bi_error;
  
        if (err)
                btrfs_warn(BTRFS_I(dip->inode)->root->fs_info,
        if (dip->errors) {
                bio_io_error(dip->orig_bio);
        } else {
 -              set_bit(BIO_UPTODATE, &dip->dio_bio->bi_flags);
 -              bio_endio(dip->orig_bio, 0);
 +              dip->dio_bio->bi_error = 0;
 +              bio_endio(dip->orig_bio);
        }
  out:
        bio_put(bio);
  static struct bio *btrfs_dio_bio_alloc(struct block_device *bdev,
                                       u64 first_sector, gfp_t gfp_flags)
  {
 -      int nr_vecs = bio_get_nr_vecs(bdev);
        struct bio *bio;
 -      bio = btrfs_bio_alloc(bdev, first_sector, nr_vecs, gfp_flags);
 +      bio = btrfs_bio_alloc(bdev, first_sector, BIO_MAX_PAGES, gfp_flags);
        if (bio)
                bio_associate_current(bio);
        return bio;
@@@ -8252,8 -8251,7 +8251,8 @@@ free_ordered
         * callbacks - they require an allocated dip and a clone of dio_bio.
         */
        if (io_bio && dip) {
 -              bio_endio(io_bio, ret);
 +              io_bio->bi_error = -EIO;
 +              bio_endio(io_bio);
                /*
                 * The end io callbacks free our dip, do the final put on io_bio
                 * and all the cleanup and final put for dio_bio (through
                        unlock_extent(&BTRFS_I(inode)->io_tree, file_offset,
                              file_offset + dio_bio->bi_iter.bi_size - 1);
                }
 -              clear_bit(BIO_UPTODATE, &dio_bio->bi_flags);
 +              dio_bio->bi_error = -EIO;
                /*
                 * Releases and cleans up our dio_bio, no need to bio_put()
                 * nor bio_endio()/bio_io_error() against dio_bio.
diff --combined fs/btrfs/scrub.c
index 9a11db0c47ee7bc1b51d8f79226a9a25f7a3b8eb,d64f557ea91e4535f9a726be97e7411d2a45118a..a39f5d1144e8e0fe90b459f3c5528d5672be0d4a
@@@ -279,7 -279,7 +279,7 @@@ static int scrub_pages(struct scrub_ct
                       u64 physical, struct btrfs_device *dev, u64 flags,
                       u64 gen, int mirror_num, u8 *csum, int force,
                       u64 physical_for_dev_replace);
 -static void scrub_bio_end_io(struct bio *bio, int err);
 +static void scrub_bio_end_io(struct bio *bio);
  static void scrub_bio_end_io_worker(struct btrfs_work *work);
  static void scrub_block_complete(struct scrub_block *sblock);
  static void scrub_remap_extent(struct btrfs_fs_info *fs_info,
@@@ -296,7 -296,7 +296,7 @@@ static void scrub_free_wr_ctx(struct sc
  static int scrub_add_page_to_wr_bio(struct scrub_ctx *sctx,
                                    struct scrub_page *spage);
  static void scrub_wr_submit(struct scrub_ctx *sctx);
 -static void scrub_wr_bio_end_io(struct bio *bio, int err);
 +static void scrub_wr_bio_end_io(struct bio *bio);
  static void scrub_wr_bio_end_io_worker(struct btrfs_work *work);
  static int write_page_nocow(struct scrub_ctx *sctx,
                            u64 physical_for_dev_replace, struct page *page);
@@@ -464,14 -464,27 +464,14 @@@ struct scrub_ctx *scrub_setup_ctx(struc
        struct scrub_ctx *sctx;
        int             i;
        struct btrfs_fs_info *fs_info = dev->dev_root->fs_info;
 -      int pages_per_rd_bio;
        int ret;
  
 -      /*
 -       * the setting of pages_per_rd_bio is correct for scrub but might
 -       * be wrong for the dev_replace code where we might read from
 -       * different devices in the initial huge bios. However, that
 -       * code is able to correctly handle the case when adding a page
 -       * to a bio fails.
 -       */
 -      if (dev->bdev)
 -              pages_per_rd_bio = min_t(int, SCRUB_PAGES_PER_RD_BIO,
 -                                       bio_get_nr_vecs(dev->bdev));
 -      else
 -              pages_per_rd_bio = SCRUB_PAGES_PER_RD_BIO;
        sctx = kzalloc(sizeof(*sctx), GFP_NOFS);
        if (!sctx)
                goto nomem;
        atomic_set(&sctx->refs, 1);
        sctx->is_dev_replace = is_dev_replace;
 -      sctx->pages_per_rd_bio = pages_per_rd_bio;
 +      sctx->pages_per_rd_bio = SCRUB_PAGES_PER_RD_BIO;
        sctx->curr = -1;
        sctx->dev_root = dev->dev_root;
        for (i = 0; i < SCRUB_BIOS_PER_SCTX; ++i) {
@@@ -1426,11 -1439,11 +1426,11 @@@ struct scrub_bio_ret 
        int error;
  };
  
 -static void scrub_bio_wait_endio(struct bio *bio, int error)
 +static void scrub_bio_wait_endio(struct bio *bio)
  {
        struct scrub_bio_ret *ret = bio->bi_private;
  
 -      ret->error = error;
 +      ret->error = bio->bi_error;
        complete(&ret->event);
  }
  
@@@ -1787,12 -1800,12 +1787,12 @@@ static void scrub_wr_submit(struct scru
        btrfsic_submit_bio(WRITE, sbio->bio);
  }
  
 -static void scrub_wr_bio_end_io(struct bio *bio, int err)
 +static void scrub_wr_bio_end_io(struct bio *bio)
  {
        struct scrub_bio *sbio = bio->bi_private;
        struct btrfs_fs_info *fs_info = sbio->dev->dev_root->fs_info;
  
 -      sbio->err = err;
 +      sbio->err = bio->bi_error;
        sbio->bio = bio;
  
        btrfs_init_work(&sbio->work, btrfs_scrubwrc_helper,
@@@ -2161,12 -2174,12 +2161,12 @@@ again
        return 0;
  }
  
 -static void scrub_missing_raid56_end_io(struct bio *bio, int error)
 +static void scrub_missing_raid56_end_io(struct bio *bio)
  {
        struct scrub_block *sblock = bio->bi_private;
        struct btrfs_fs_info *fs_info = sblock->sctx->dev_root->fs_info;
  
 -      if (error)
 +      if (bio->bi_error)
                sblock->no_io_error_seen = 0;
  
        btrfs_queue_work(fs_info->scrub_workers, &sblock->work);
@@@ -2379,12 -2392,12 +2379,12 @@@ leave_nomem
        return 0;
  }
  
 -static void scrub_bio_end_io(struct bio *bio, int err)
 +static void scrub_bio_end_io(struct bio *bio)
  {
        struct scrub_bio *sbio = bio->bi_private;
        struct btrfs_fs_info *fs_info = sbio->dev->dev_root->fs_info;
  
 -      sbio->err = err;
 +      sbio->err = bio->bi_error;
        sbio->bio = bio;
  
        btrfs_queue_work(fs_info->scrub_workers, &sbio->work);
@@@ -2796,11 -2809,11 +2796,11 @@@ static void scrub_parity_bio_endio_work
        scrub_pending_bio_dec(sctx);
  }
  
 -static void scrub_parity_bio_endio(struct bio *bio, int error)
 +static void scrub_parity_bio_endio(struct bio *bio)
  {
        struct scrub_parity *sparity = (struct scrub_parity *)bio->bi_private;
  
 -      if (error)
 +      if (bio->bi_error)
                bitmap_or(sparity->ebitmap, sparity->ebitmap, sparity->dbitmap,
                          sparity->nsectors);
  
@@@ -3267,13 -3280,13 +3267,13 @@@ static noinline_for_stack int scrub_str
                        scrub_blocked_if_needed(fs_info);
                }
  
-               /* for raid56, we skip parity stripe */
                if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK) {
                        ret = get_raid56_logic_offset(physical, num, map,
                                                      &logical,
                                                      &stripe_logical);
                        logical += base;
                        if (ret) {
+                               /* it is parity strip */
                                stripe_logical += base;
                                stripe_end = stripe_logical + increment;
                                ret = scrub_raid56_parity(sctx, map, scrub_dev,
@@@ -3480,7 -3493,6 +3480,6 @@@ out
  
  static noinline_for_stack int scrub_chunk(struct scrub_ctx *sctx,
                                          struct btrfs_device *scrub_dev,
-                                         u64 chunk_tree, u64 chunk_objectid,
                                          u64 chunk_offset, u64 length,
                                          u64 dev_offset, int is_dev_replace)
  {
@@@ -3531,8 -3543,6 +3530,6 @@@ int scrub_enumerate_chunks(struct scrub
        struct btrfs_root *root = sctx->dev_root;
        struct btrfs_fs_info *fs_info = root->fs_info;
        u64 length;
-       u64 chunk_tree;
-       u64 chunk_objectid;
        u64 chunk_offset;
        int ret = 0;
        int slot;
                if (found_key.offset + length <= start)
                        goto skip;
  
-               chunk_tree = btrfs_dev_extent_chunk_tree(l, dev_extent);
-               chunk_objectid = btrfs_dev_extent_chunk_objectid(l, dev_extent);
                chunk_offset = btrfs_dev_extent_chunk_offset(l, dev_extent);
  
                /*
                dev_replace->cursor_right = found_key.offset + length;
                dev_replace->cursor_left = found_key.offset;
                dev_replace->item_needs_writeback = 1;
-               ret = scrub_chunk(sctx, scrub_dev, chunk_tree, chunk_objectid,
-                                 chunk_offset, length, found_key.offset,
-                                 is_dev_replace);
+               ret = scrub_chunk(sctx, scrub_dev, chunk_offset, length,
+                                 found_key.offset, is_dev_replace);
  
                /*
                 * flush, submit all pending read and write bios, afterwards
@@@ -4059,7 -4066,8 +4053,7 @@@ static int scrub_setup_wr_ctx(struct sc
                return 0;
  
        WARN_ON(!dev->bdev);
 -      wr_ctx->pages_per_wr_bio = min_t(int, SCRUB_PAGES_PER_WR_BIO,
 -                                       bio_get_nr_vecs(dev->bdev));
 +      wr_ctx->pages_per_wr_bio = SCRUB_PAGES_PER_WR_BIO;
        wr_ctx->tgtdev = dev;
        atomic_set(&wr_ctx->flush_all_writes, 0);
        return 0;
diff --combined fs/btrfs/volumes.c
index 76201d6f6ce46371784e8fa6462bc2f5fde3879b,644e070b3bd24657e676556a68f042becead03bb..6fc735869c186c35fb79fa66decc7d3519ed2e93
@@@ -3585,23 -3585,10 +3585,10 @@@ int btrfs_balance(struct btrfs_balance_
        } while (read_seqretry(&fs_info->profiles_lock, seq));
  
        if (bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) {
-               int num_tolerated_disk_barrier_failures;
-               u64 target = bctl->sys.target;
-               num_tolerated_disk_barrier_failures =
-                       btrfs_calc_num_tolerated_disk_barrier_failures(fs_info);
-               if (num_tolerated_disk_barrier_failures > 0 &&
-                   (target &
-                    (BTRFS_BLOCK_GROUP_DUP | BTRFS_BLOCK_GROUP_RAID0 |
-                     BTRFS_AVAIL_ALLOC_BIT_SINGLE)))
-                       num_tolerated_disk_barrier_failures = 0;
-               else if (num_tolerated_disk_barrier_failures > 1 &&
-                        (target &
-                         (BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10)))
-                       num_tolerated_disk_barrier_failures = 1;
-               fs_info->num_tolerated_disk_barrier_failures =
-                       num_tolerated_disk_barrier_failures;
+               fs_info->num_tolerated_disk_barrier_failures = min(
+                       btrfs_calc_num_tolerated_disk_barrier_failures(fs_info),
+                       btrfs_get_num_tolerated_disk_barrier_failures(
+                               bctl->sys.target));
        }
  
        ret = insert_balance_item(fs_info->tree_root, bctl);
@@@ -5750,23 -5737,23 +5737,23 @@@ int btrfs_rmap_block(struct btrfs_mappi
        return 0;
  }
  
 -static inline void btrfs_end_bbio(struct btrfs_bio *bbio, struct bio *bio, int err)
 +static inline void btrfs_end_bbio(struct btrfs_bio *bbio, struct bio *bio)
  {
        bio->bi_private = bbio->private;
        bio->bi_end_io = bbio->end_io;
 -      bio_endio(bio, err);
 +      bio_endio(bio);
  
        btrfs_put_bbio(bbio);
  }
  
 -static void btrfs_end_bio(struct bio *bio, int err)
 +static void btrfs_end_bio(struct bio *bio)
  {
        struct btrfs_bio *bbio = bio->bi_private;
        int is_orig_bio = 0;
  
 -      if (err) {
 +      if (bio->bi_error) {
                atomic_inc(&bbio->error);
 -              if (err == -EIO || err == -EREMOTEIO) {
 +              if (bio->bi_error == -EIO || bio->bi_error == -EREMOTEIO) {
                        unsigned int stripe_index =
                                btrfs_io_bio(bio)->stripe_index;
                        struct btrfs_device *dev;
                 * beyond the tolerance of the btrfs bio
                 */
                if (atomic_read(&bbio->error) > bbio->max_errors) {
 -                      err = -EIO;
 +                      bio->bi_error = -EIO;
                } else {
                        /*
                         * this bio is actually up to date, we didn't
                         * go over the max number of errors
                         */
 -                      set_bit(BIO_UPTODATE, &bio->bi_flags);
 -                      err = 0;
 +                      bio->bi_error = 0;
                }
  
 -              btrfs_end_bbio(bbio, bio, err);
 +              btrfs_end_bbio(bbio, bio);
        } else if (!is_orig_bio) {
                bio_put(bio);
        }
@@@ -5834,7 -5822,7 +5821,7 @@@ static noinline void btrfs_schedule_bio
        struct btrfs_pending_bios *pending_bios;
  
        if (device->missing || !device->bdev) {
 -              bio_endio(bio, -EIO);
 +              bio_io_error(bio);
                return;
        }
  
                                 &device->work);
  }
  
 -static int bio_size_ok(struct block_device *bdev, struct bio *bio,
 -                     sector_t sector)
 -{
 -      struct bio_vec *prev;
 -      struct request_queue *q = bdev_get_queue(bdev);
 -      unsigned int max_sectors = queue_max_sectors(q);
 -      struct bvec_merge_data bvm = {
 -              .bi_bdev = bdev,
 -              .bi_sector = sector,
 -              .bi_rw = bio->bi_rw,
 -      };
 -
 -      if (WARN_ON(bio->bi_vcnt == 0))
 -              return 1;
 -
 -      prev = &bio->bi_io_vec[bio->bi_vcnt - 1];
 -      if (bio_sectors(bio) > max_sectors)
 -              return 0;
 -
 -      if (!q->merge_bvec_fn)
 -              return 1;
 -
 -      bvm.bi_size = bio->bi_iter.bi_size - prev->bv_len;
 -      if (q->merge_bvec_fn(q, &bvm, prev) < prev->bv_len)
 -              return 0;
 -      return 1;
 -}
 -
  static void submit_stripe_bio(struct btrfs_root *root, struct btrfs_bio *bbio,
                              struct bio *bio, u64 physical, int dev_nr,
                              int rw, int async)
                btrfsic_submit_bio(rw, bio);
  }
  
 -static int breakup_stripe_bio(struct btrfs_root *root, struct btrfs_bio *bbio,
 -                            struct bio *first_bio, struct btrfs_device *dev,
 -                            int dev_nr, int rw, int async)
 -{
 -      struct bio_vec *bvec = first_bio->bi_io_vec;
 -      struct bio *bio;
 -      int nr_vecs = bio_get_nr_vecs(dev->bdev);
 -      u64 physical = bbio->stripes[dev_nr].physical;
 -
 -again:
 -      bio = btrfs_bio_alloc(dev->bdev, physical >> 9, nr_vecs, GFP_NOFS);
 -      if (!bio)
 -              return -ENOMEM;
 -
 -#ifdef CONFIG_BLK_CGROUP
 -      if (first_bio->bi_ioc) {
 -              get_io_context_active(first_bio->bi_ioc);
 -              bio->bi_ioc = first_bio->bi_ioc;
 -      }
 -      if (first_bio->bi_css) {
 -              css_get(first_bio->bi_css);
 -              bio->bi_css = first_bio->bi_css;
 -      }
 -#endif
 -      while (bvec <= (first_bio->bi_io_vec + first_bio->bi_vcnt - 1)) {
 -              if (bio_add_page(bio, bvec->bv_page, bvec->bv_len,
 -                               bvec->bv_offset) < bvec->bv_len) {
 -                      u64 len = bio->bi_iter.bi_size;
 -
 -                      atomic_inc(&bbio->stripes_pending);
 -                      submit_stripe_bio(root, bbio, bio, physical, dev_nr,
 -                                        rw, async);
 -                      physical += len;
 -                      goto again;
 -              }
 -              bvec++;
 -      }
 -
 -      submit_stripe_bio(root, bbio, bio, physical, dev_nr, rw, async);
 -      return 0;
 -}
 -
  static void bbio_error(struct btrfs_bio *bbio, struct bio *bio, u64 logical)
  {
        atomic_inc(&bbio->error);
  
                btrfs_io_bio(bio)->mirror_num = bbio->mirror_num;
                bio->bi_iter.bi_sector = logical >> 9;
 -
 -              btrfs_end_bbio(bbio, bio, -EIO);
 +              bio->bi_error = -EIO;
 +              btrfs_end_bbio(bbio, bio);
        }
  }
  
@@@ -5984,6 -6042,18 +5971,6 @@@ int btrfs_map_bio(struct btrfs_root *ro
                        continue;
                }
  
 -              /*
 -               * Check and see if we're ok with this bio based on it's size
 -               * and offset with the given device.
 -               */
 -              if (!bio_size_ok(dev->bdev, first_bio,
 -                               bbio->stripes[dev_nr].physical >> 9)) {
 -                      ret = breakup_stripe_bio(root, bbio, first_bio, dev,
 -                                               dev_nr, rw, async_submit);
 -                      BUG_ON(ret);
 -                      continue;
 -              }
 -
                if (dev_nr < total_devs - 1) {
                        bio = btrfs_bio_clone(first_bio, GFP_NOFS);
                        BUG_ON(!bio); /* -ENOMEM */