Merge branch 'for-linus-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/mason...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 4 Aug 2016 23:56:16 +0000 (19:56 -0400)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 4 Aug 2016 23:56:16 +0000 (19:56 -0400)
Pull more btrfs updates from Chris Mason:
 "This is part two of my btrfs pull, which is some cleanups and a batch
  of fixes.

  Most of the code here is from Jeff Mahoney, making the pointers we
  pass around internally more consistent and less confusing overall.  I
  noticed a small problem right before I sent this out yesterday, so I
  fixed it up and re-tested overnight"

* 'for-linus-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: (40 commits)
  Btrfs: fix __MAX_CSUM_ITEMS
  btrfs: btrfs_abort_transaction, drop root parameter
  btrfs: add btrfs_trans_handle->fs_info pointer
  btrfs: btrfs_relocate_chunk pass extent_root to btrfs_end_transaction
  btrfs: convert nodesize macros to static inlines
  btrfs: introduce BTRFS_MAX_ITEM_SIZE
  btrfs: cleanup, remove prototype for btrfs_find_root_ref
  btrfs: copy_to_sk drop unused root parameter
  btrfs: simpilify btrfs_subvol_inherit_props
  btrfs: tests, use BTRFS_FS_STATE_DUMMY_FS_INFO instead of dummy root
  btrfs: tests, require fs_info for root
  btrfs: tests, move initialization into tests/
  btrfs: btrfs_test_opt and friends should take a btrfs_fs_info
  btrfs: prefix fsid to all trace events
  btrfs: plumb fs_info into btrfs_work
  btrfs: remove obsolete part of comment in statfs
  btrfs: hide test-only member under ifdef
  btrfs: Ratelimit "no csum found" info message
  btrfs: Add ratelimit to btrfs printing
  Btrfs: fix unexpected balance crash due to BUG_ON
  ...

1  2 
fs/btrfs/compression.c
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/disk-io.h
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/inode.c
fs/btrfs/scrub.c
fs/btrfs/volumes.c

diff --combined fs/btrfs/compression.c
index cefedabf0a92fd6aaa4c4986d4899fc9cac3b859,7a4d9c81aa2a38364c43435bb505c190646a7a6a..029db6e1105c7eb2bd42a4abc06a9f910bf9e346
@@@ -363,7 -363,6 +363,7 @@@ int btrfs_submit_compressed_write(struc
                kfree(cb);
                return -ENOMEM;
        }
 +      bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
        bio->bi_private = cb;
        bio->bi_end_io = end_compressed_bio_write;
        atomic_inc(&cb->pending_bios);
                page = compressed_pages[pg_index];
                page->mapping = inode->i_mapping;
                if (bio->bi_iter.bi_size)
 -                      ret = io_tree->ops->merge_bio_hook(WRITE, page, 0,
 +                      ret = io_tree->ops->merge_bio_hook(page, 0,
                                                           PAGE_SIZE,
                                                           bio, 0);
                else
                                BUG_ON(ret); /* -ENOMEM */
                        }
  
 -                      ret = btrfs_map_bio(root, WRITE, bio, 0, 1);
 +                      ret = btrfs_map_bio(root, bio, 0, 1);
-                       BUG_ON(ret); /* -ENOMEM */
+                       if (ret) {
+                               bio->bi_error = ret;
+                               bio_endio(bio);
+                       }
  
                        bio_put(bio);
  
                        bio = compressed_bio_alloc(bdev, first_byte, GFP_NOFS);
                        BUG_ON(!bio);
 +                      bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
                        bio->bi_private = cb;
                        bio->bi_end_io = end_compressed_bio_write;
                        bio_add_page(bio, page, PAGE_SIZE, 0);
                BUG_ON(ret); /* -ENOMEM */
        }
  
 -      ret = btrfs_map_bio(root, WRITE, bio, 0, 1);
 +      ret = btrfs_map_bio(root, bio, 0, 1);
-       BUG_ON(ret); /* -ENOMEM */
+       if (ret) {
+               bio->bi_error = ret;
+               bio_endio(bio);
+       }
  
        bio_put(bio);
        return 0;
@@@ -648,7 -652,6 +654,7 @@@ int btrfs_submit_compressed_read(struc
        comp_bio = compressed_bio_alloc(bdev, cur_disk_byte, GFP_NOFS);
        if (!comp_bio)
                goto fail2;
 +      bio_set_op_attrs (comp_bio, REQ_OP_READ, 0);
        comp_bio->bi_private = cb;
        comp_bio->bi_end_io = end_compressed_bio_read;
        atomic_inc(&cb->pending_bios);
                page->index = em_start >> PAGE_SHIFT;
  
                if (comp_bio->bi_iter.bi_size)
 -                      ret = tree->ops->merge_bio_hook(READ, page, 0,
 +                      ret = tree->ops->merge_bio_hook(page, 0,
                                                        PAGE_SIZE,
                                                        comp_bio, 0);
                else
                        sums += DIV_ROUND_UP(comp_bio->bi_iter.bi_size,
                                             root->sectorsize);
  
 -                      ret = btrfs_map_bio(root, READ, comp_bio,
 -                                          mirror_num, 0);
 +                      ret = btrfs_map_bio(root, comp_bio, mirror_num, 0);
                        if (ret) {
                                bio->bi_error = ret;
                                bio_endio(comp_bio);
                        comp_bio = compressed_bio_alloc(bdev, cur_disk_byte,
                                                        GFP_NOFS);
                        BUG_ON(!comp_bio);
 +                      bio_set_op_attrs(comp_bio, REQ_OP_READ, 0);
                        comp_bio->bi_private = cb;
                        comp_bio->bi_end_io = end_compressed_bio_read;
  
                BUG_ON(ret); /* -ENOMEM */
        }
  
 -      ret = btrfs_map_bio(root, READ, comp_bio, mirror_num, 0);
 +      ret = btrfs_map_bio(root, comp_bio, mirror_num, 0);
        if (ret) {
                bio->bi_error = ret;
                bio_endio(comp_bio);
diff --combined fs/btrfs/ctree.h
index 443fcc4021141f0ea5f5f9bbe5a1cdca0fb6f4ee,f66a0ba9a2a9740c0a461cb18ffc0793c7d8588c..2fe8f89091a3097aa8e55bcee4a20c7b43ab1ca2
@@@ -117,6 -117,7 +117,7 @@@ static inline unsigned long btrfs_chunk
  #define BTRFS_FS_STATE_REMOUNTING     1
  #define BTRFS_FS_STATE_TRANS_ABORTED  2
  #define BTRFS_FS_STATE_DEV_REPLACING  3
+ #define BTRFS_FS_STATE_DUMMY_FS_INFO  4
  
  #define BTRFS_BACKREF_REV_MAX         256
  #define BTRFS_BACKREF_REV_SHIFT               56
@@@ -144,21 -145,6 +145,6 @@@ struct btrfs_header 
        u8 level;
  } __attribute__ ((__packed__));
  
- #define BTRFS_NODEPTRS_PER_BLOCK(r) (((r)->nodesize - \
-                                     sizeof(struct btrfs_header)) / \
-                                    sizeof(struct btrfs_key_ptr))
- #define __BTRFS_LEAF_DATA_SIZE(bs) ((bs) - sizeof(struct btrfs_header))
- #define BTRFS_LEAF_DATA_SIZE(r) (__BTRFS_LEAF_DATA_SIZE(r->nodesize))
- #define BTRFS_FILE_EXTENT_INLINE_DATA_START           \
-               (offsetof(struct btrfs_file_extent_item, disk_bytenr))
- #define BTRFS_MAX_INLINE_DATA_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \
-                                       sizeof(struct btrfs_item) - \
-                                       BTRFS_FILE_EXTENT_INLINE_DATA_START)
- #define BTRFS_MAX_XATTR_SIZE(r)       (BTRFS_LEAF_DATA_SIZE(r) - \
-                                sizeof(struct btrfs_item) -\
-                                sizeof(struct btrfs_dir_item))
  /*
   * this is a very generous portion of the super block, giving us
   * room to translate 14 chunks with 3 stripes each.
@@@ -1114,12 -1100,11 +1100,11 @@@ struct btrfs_subvolume_writers 
  #define BTRFS_ROOT_REF_COWS           1
  #define BTRFS_ROOT_TRACK_DIRTY                2
  #define BTRFS_ROOT_IN_RADIX           3
- #define BTRFS_ROOT_DUMMY_ROOT         4
- #define BTRFS_ROOT_ORPHAN_ITEM_INSERTED       5
- #define BTRFS_ROOT_DEFRAG_RUNNING     6
- #define BTRFS_ROOT_FORCE_COW          7
- #define BTRFS_ROOT_MULTI_LOG_TASKS    8
- #define BTRFS_ROOT_DIRTY              9
+ #define BTRFS_ROOT_ORPHAN_ITEM_INSERTED       4
+ #define BTRFS_ROOT_DEFRAG_RUNNING     5
+ #define BTRFS_ROOT_FORCE_COW          6
+ #define BTRFS_ROOT_MULTI_LOG_TASKS    7
+ #define BTRFS_ROOT_DIRTY              8
  
  /*
   * in ram representation of the tree.  extent_root is used for all allocations
@@@ -1181,8 -1166,10 +1166,10 @@@ struct btrfs_root 
  
        u64 highest_objectid;
  
+ #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
        /* only used with CONFIG_BTRFS_FS_RUN_SANITY_TESTS is enabled */
        u64 alloc_bytenr;
+ #endif
  
        u64 defrag_trans_start;
        struct btrfs_key defrag_progress;
        atomic_t qgroup_meta_rsv;
  };
  
+ static inline u32 __BTRFS_LEAF_DATA_SIZE(u32 blocksize)
+ {
+       return blocksize - sizeof(struct btrfs_header);
+ }
+ static inline u32 BTRFS_LEAF_DATA_SIZE(const struct btrfs_root *root)
+ {
+       return __BTRFS_LEAF_DATA_SIZE(root->nodesize);
+ }
+ static inline u32 BTRFS_MAX_ITEM_SIZE(const struct btrfs_root *root)
+ {
+       return BTRFS_LEAF_DATA_SIZE(root) - sizeof(struct btrfs_item);
+ }
+ static inline u32 BTRFS_NODEPTRS_PER_BLOCK(const struct btrfs_root *root)
+ {
+       return BTRFS_LEAF_DATA_SIZE(root) / sizeof(struct btrfs_key_ptr);
+ }
+ #define BTRFS_FILE_EXTENT_INLINE_DATA_START           \
+               (offsetof(struct btrfs_file_extent_item, disk_bytenr))
+ static inline u32 BTRFS_MAX_INLINE_DATA_SIZE(const struct btrfs_root *root)
+ {
+       return BTRFS_MAX_ITEM_SIZE(root) -
+              BTRFS_FILE_EXTENT_INLINE_DATA_START;
+ }
+ static inline u32 BTRFS_MAX_XATTR_SIZE(const struct btrfs_root *root)
+ {
+       return BTRFS_MAX_ITEM_SIZE(root) - sizeof(struct btrfs_dir_item);
+ }
  /*
   * Flags for mount options.
   *
  #define btrfs_clear_opt(o, opt)               ((o) &= ~BTRFS_MOUNT_##opt)
  #define btrfs_set_opt(o, opt)         ((o) |= BTRFS_MOUNT_##opt)
  #define btrfs_raw_test_opt(o, opt)    ((o) & BTRFS_MOUNT_##opt)
- #define btrfs_test_opt(root, opt)     ((root)->fs_info->mount_opt & \
+ #define btrfs_test_opt(fs_info, opt)  ((fs_info)->mount_opt & \
                                         BTRFS_MOUNT_##opt)
  
- #define btrfs_set_and_info(root, opt, fmt, args...)                   \
+ #define btrfs_set_and_info(fs_info, opt, fmt, args...)                        \
  {                                                                     \
-       if (!btrfs_test_opt(root, opt))                                 \
-               btrfs_info(root->fs_info, fmt, ##args);                 \
-       btrfs_set_opt(root->fs_info->mount_opt, opt);                   \
+       if (!btrfs_test_opt(fs_info, opt))                              \
+               btrfs_info(fs_info, fmt, ##args);                       \
+       btrfs_set_opt(fs_info->mount_opt, opt);                         \
  }
  
- #define btrfs_clear_and_info(root, opt, fmt, args...)                 \
+ #define btrfs_clear_and_info(fs_info, opt, fmt, args...)              \
  {                                                                     \
-       if (btrfs_test_opt(root, opt))                                  \
-               btrfs_info(root->fs_info, fmt, ##args);                 \
-       btrfs_clear_opt(root->fs_info->mount_opt, opt);                 \
+       if (btrfs_test_opt(fs_info, opt))                               \
+               btrfs_info(fs_info, fmt, ##args);                       \
+       btrfs_clear_opt(fs_info->mount_opt, opt);                       \
  }
  
  #ifdef CONFIG_BTRFS_DEBUG
@@@ -1321,9 -1341,9 +1341,9 @@@ static inline in
  btrfs_should_fragment_free_space(struct btrfs_root *root,
                                 struct btrfs_block_group_cache *block_group)
  {
-       return (btrfs_test_opt(root, FRAGMENT_METADATA) &&
+       return (btrfs_test_opt(root->fs_info, FRAGMENT_METADATA) &&
                block_group->flags & BTRFS_BLOCK_GROUP_METADATA) ||
-              (btrfs_test_opt(root, FRAGMENT_DATA) &&
+              (btrfs_test_opt(root->fs_info, FRAGMENT_DATA) &&
                block_group->flags &  BTRFS_BLOCK_GROUP_DATA);
  }
  #endif
@@@ -2886,9 -2906,6 +2906,6 @@@ void btrfs_put_tree_mod_seq(struct btrf
  int btrfs_old_root_level(struct btrfs_root *root, u64 time_seq);
  
  /* root-item.c */
- int btrfs_find_root_ref(struct btrfs_root *tree_root,
-                       struct btrfs_path *path,
-                       u64 root_id, u64 ref_id);
  int btrfs_add_root_ref(struct btrfs_trans_handle *trans,
                       struct btrfs_root *tree_root,
                       u64 root_id, u64 ref_id, u64 dirid, u64 sequence,
@@@ -3102,7 -3119,7 +3119,7 @@@ int btrfs_create_subvol_root(struct btr
                             struct btrfs_root *new_root,
                             struct btrfs_root *parent_root,
                             u64 new_dirid);
 -int btrfs_merge_bio_hook(int rw, struct page *page, unsigned long offset,
 +int btrfs_merge_bio_hook(struct page *page, unsigned long offset,
                         size_t size, struct bio *bio,
                         unsigned long bio_flags);
  int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf);
@@@ -3362,23 -3379,23 +3379,23 @@@ const char *btrfs_decode_error(int errn
  
  __cold
  void __btrfs_abort_transaction(struct btrfs_trans_handle *trans,
-                              struct btrfs_root *root, const char *function,
+                              const char *function,
                               unsigned int line, int errno);
  
  /*
   * Call btrfs_abort_transaction as early as possible when an error condition is
   * detected, that way the exact line number is reported.
   */
- #define btrfs_abort_transaction(trans, root, errno)           \
+ #define btrfs_abort_transaction(trans, errno)         \
  do {                                                          \
        /* Report first abort since mount */                    \
        if (!test_and_set_bit(BTRFS_FS_STATE_TRANS_ABORTED,     \
-                       &((root)->fs_info->fs_state))) {        \
+                       &((trans)->fs_info->fs_state))) {       \
                WARN(1, KERN_DEBUG                              \
                "BTRFS: Transaction aborted (error %d)\n",      \
                (errno));                                       \
        }                                                       \
-       __btrfs_abort_transaction((trans), (root), __func__,    \
+       __btrfs_abort_transaction((trans), __func__,            \
                                  __LINE__, (errno));           \
  } while (0)
  
@@@ -3610,13 -3627,13 +3627,13 @@@ static inline int btrfs_defrag_cancelle
  void btrfs_test_destroy_inode(struct inode *inode);
  #endif
  
- static inline int btrfs_test_is_dummy_root(struct btrfs_root *root)
+ static inline int btrfs_is_testing(struct btrfs_fs_info *fs_info)
  {
  #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
-       if (unlikely(test_bit(BTRFS_ROOT_DUMMY_ROOT, &root->state)))
+       if (unlikely(test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO,
+                             &fs_info->fs_state)))
                return 1;
  #endif
        return 0;
  }
  #endif
diff --combined fs/btrfs/disk-io.c
index 9a726ded2c6d150e73bd2719a09cb95a8634ab57,ff2362dca91aa92ef77c719f911283456a04d1ad..87dad552e39ae13ea2533c4a5718a5af635bcbee
@@@ -101,7 -101,7 +101,7 @@@ int __init btrfs_end_io_wq_init(void
        btrfs_end_io_wq_cache = kmem_cache_create("btrfs_end_io_wq",
                                        sizeof(struct btrfs_end_io_wq),
                                        0,
-                                       SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD,
+                                       SLAB_MEM_SPREAD,
                                        NULL);
        if (!btrfs_end_io_wq_cache)
                return -ENOMEM;
@@@ -124,6 -124,7 +124,6 @@@ struct async_submit_bio 
        struct list_head list;
        extent_submit_bio_hook_t *submit_bio_start;
        extent_submit_bio_hook_t *submit_bio_done;
 -      int rw;
        int mirror_num;
        unsigned long bio_flags;
        /*
@@@ -726,7 -727,7 +726,7 @@@ static void end_workqueue_bio(struct bi
        fs_info = end_io_wq->info;
        end_io_wq->error = bio->bi_error;
  
 -      if (bio->bi_rw & REQ_WRITE) {
 +      if (bio_op(bio) == REQ_OP_WRITE) {
                if (end_io_wq->metadata == BTRFS_WQ_ENDIO_METADATA) {
                        wq = fs_info->endio_meta_write_workers;
                        func = btrfs_endio_meta_write_helper;
@@@ -796,7 -797,7 +796,7 @@@ static void run_one_async_start(struct 
        int ret;
  
        async = container_of(work, struct  async_submit_bio, work);
 -      ret = async->submit_bio_start(async->inode, async->rw, async->bio,
 +      ret = async->submit_bio_start(async->inode, async->bio,
                                      async->mirror_num, async->bio_flags,
                                      async->bio_offset);
        if (ret)
@@@ -829,8 -830,9 +829,8 @@@ static void run_one_async_done(struct b
                return;
        }
  
 -      async->submit_bio_done(async->inode, async->rw, async->bio,
 -                             async->mirror_num, async->bio_flags,
 -                             async->bio_offset);
 +      async->submit_bio_done(async->inode, async->bio, async->mirror_num,
 +                             async->bio_flags, async->bio_offset);
  }
  
  static void run_one_async_free(struct btrfs_work *work)
  }
  
  int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode,
 -                      int rw, struct bio *bio, int mirror_num,
 +                      struct bio *bio, int mirror_num,
                        unsigned long bio_flags,
                        u64 bio_offset,
                        extent_submit_bio_hook_t *submit_bio_start,
                return -ENOMEM;
  
        async->inode = inode;
 -      async->rw = rw;
        async->bio = bio;
        async->mirror_num = mirror_num;
        async->submit_bio_start = submit_bio_start;
  
        atomic_inc(&fs_info->nr_async_submits);
  
 -      if (rw & REQ_SYNC)
 +      if (bio->bi_rw & REQ_SYNC)
                btrfs_set_work_high_priority(&async->work);
  
        btrfs_queue_work(fs_info->workers, &async->work);
@@@ -900,8 -903,9 +900,8 @@@ static int btree_csum_one_bio(struct bi
        return ret;
  }
  
 -static int __btree_submit_bio_start(struct inode *inode, int rw,
 -                                  struct bio *bio, int mirror_num,
 -                                  unsigned long bio_flags,
 +static int __btree_submit_bio_start(struct inode *inode, struct bio *bio,
 +                                  int mirror_num, unsigned long bio_flags,
                                    u64 bio_offset)
  {
        /*
        return btree_csum_one_bio(bio);
  }
  
 -static int __btree_submit_bio_done(struct inode *inode, int rw, struct bio *bio,
 +static int __btree_submit_bio_done(struct inode *inode, struct bio *bio,
                                 int mirror_num, unsigned long bio_flags,
                                 u64 bio_offset)
  {
         * when we're called for a write, we're already in the async
         * submission context.  Just jump into btrfs_map_bio
         */
 -      ret = btrfs_map_bio(BTRFS_I(inode)->root, rw, bio, mirror_num, 1);
 +      ret = btrfs_map_bio(BTRFS_I(inode)->root, bio, mirror_num, 1);
        if (ret) {
                bio->bi_error = ret;
                bio_endio(bio);
@@@ -940,14 -944,14 +940,14 @@@ static int check_async_write(struct ino
        return 1;
  }
  
 -static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio,
 +static int btree_submit_bio_hook(struct inode *inode, struct bio *bio,
                                 int mirror_num, unsigned long bio_flags,
                                 u64 bio_offset)
  {
        int async = check_async_write(inode, bio_flags);
        int ret;
  
 -      if (!(rw & REQ_WRITE)) {
 +      if (bio_op(bio) != REQ_OP_WRITE) {
                /*
                 * called for a read, do the setup so that checksum validation
                 * can happen in the async kernel threads
                                          bio, BTRFS_WQ_ENDIO_METADATA);
                if (ret)
                        goto out_w_error;
 -              ret = btrfs_map_bio(BTRFS_I(inode)->root, rw, bio,
 -                                  mirror_num, 0);
 +              ret = btrfs_map_bio(BTRFS_I(inode)->root, bio, mirror_num, 0);
        } else if (!async) {
                ret = btree_csum_one_bio(bio);
                if (ret)
                        goto out_w_error;
 -              ret = btrfs_map_bio(BTRFS_I(inode)->root, rw, bio,
 -                                  mirror_num, 0);
 +              ret = btrfs_map_bio(BTRFS_I(inode)->root, bio, mirror_num, 0);
        } else {
                /*
                 * kthread helpers are used to submit writes so that
                 * checksumming can happen in parallel across all CPUs
                 */
                ret = btrfs_wq_submit_bio(BTRFS_I(inode)->root->fs_info,
 -                                        inode, rw, bio, mirror_num, 0,
 +                                        inode, bio, mirror_num, 0,
                                          bio_offset,
                                          __btree_submit_bio_start,
                                          __btree_submit_bio_done);
@@@ -1140,7 -1146,7 +1140,7 @@@ struct extent_buffer *btrfs_find_tree_b
  struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root,
                                                 u64 bytenr)
  {
-       if (btrfs_test_is_dummy_root(root))
+       if (btrfs_is_testing(root->fs_info))
                return alloc_test_extent_buffer(root->fs_info, bytenr,
                                root->nodesize);
        return alloc_extent_buffer(root->fs_info, bytenr);
@@@ -1227,6 -1233,7 +1227,7 @@@ static void __setup_root(u32 nodesize, 
                         struct btrfs_root *root, struct btrfs_fs_info *fs_info,
                         u64 objectid)
  {
+       bool dummy = test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state);
        root->node = NULL;
        root->commit_root = NULL;
        root->sectorsize = sectorsize;
        root->log_transid = 0;
        root->log_transid_committed = -1;
        root->last_log_commit = 0;
-       if (fs_info)
+       if (!dummy)
                extent_io_tree_init(&root->dirty_log_pages,
                                     fs_info->btree_inode->i_mapping);
  
        memset(&root->root_key, 0, sizeof(root->root_key));
        memset(&root->root_item, 0, sizeof(root->root_item));
        memset(&root->defrag_progress, 0, sizeof(root->defrag_progress));
-       if (fs_info)
+       if (!dummy)
                root->defrag_trans_start = fs_info->generation;
        else
                root->defrag_trans_start = 0;
@@@ -1309,17 -1316,20 +1310,20 @@@ static struct btrfs_root *btrfs_alloc_r
  
  #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
  /* Should only be used by the testing infrastructure */
- struct btrfs_root *btrfs_alloc_dummy_root(u32 sectorsize, u32 nodesize)
+ struct btrfs_root *btrfs_alloc_dummy_root(struct btrfs_fs_info *fs_info,
+                                         u32 sectorsize, u32 nodesize)
  {
        struct btrfs_root *root;
  
-       root = btrfs_alloc_root(NULL, GFP_KERNEL);
+       if (!fs_info)
+               return ERR_PTR(-EINVAL);
+       root = btrfs_alloc_root(fs_info, GFP_KERNEL);
        if (!root)
                return ERR_PTR(-ENOMEM);
        /* We don't use the stripesize in selftest, set it as sectorsize */
-       __setup_root(nodesize, sectorsize, sectorsize, root, NULL,
+       __setup_root(nodesize, sectorsize, sectorsize, root, fs_info,
                        BTRFS_ROOT_TREE_OBJECTID);
-       set_bit(BTRFS_ROOT_DUMMY_ROOT, &root->state);
        root->alloc_bytenr = 0;
  
        return root;
@@@ -1594,14 -1604,14 +1598,14 @@@ int btrfs_init_fs_root(struct btrfs_roo
  
        ret = get_anon_bdev(&root->anon_dev);
        if (ret)
-               goto free_writers;
+               goto fail;
  
        mutex_lock(&root->objectid_mutex);
        ret = btrfs_find_highest_objectid(root,
                                        &root->highest_objectid);
        if (ret) {
                mutex_unlock(&root->objectid_mutex);
-               goto free_root_dev;
+               goto fail;
        }
  
        ASSERT(root->highest_objectid <= BTRFS_LAST_FREE_OBJECTID);
        mutex_unlock(&root->objectid_mutex);
  
        return 0;
- free_root_dev:
-       free_anon_bdev(root->anon_dev);
- free_writers:
-       btrfs_free_subvolume_writers(root->subv_writers);
  fail:
-       kfree(root->free_ino_ctl);
-       kfree(root->free_ino_pinned);
+       /* the caller is responsible to call free_fs_root */
        return ret;
  }
  
@@@ -2310,17 -2314,19 +2308,19 @@@ static int btrfs_init_workqueues(struc
        unsigned int flags = WQ_MEM_RECLAIM | WQ_FREEZABLE | WQ_UNBOUND;
  
        fs_info->workers =
-               btrfs_alloc_workqueue("worker", flags | WQ_HIGHPRI,
-                                     max_active, 16);
+               btrfs_alloc_workqueue(fs_info, "worker",
+                                     flags | WQ_HIGHPRI, max_active, 16);
  
        fs_info->delalloc_workers =
-               btrfs_alloc_workqueue("delalloc", flags, max_active, 2);
+               btrfs_alloc_workqueue(fs_info, "delalloc",
+                                     flags, max_active, 2);
  
        fs_info->flush_workers =
-               btrfs_alloc_workqueue("flush_delalloc", flags, max_active, 0);
+               btrfs_alloc_workqueue(fs_info, "flush_delalloc",
+                                     flags, max_active, 0);
  
        fs_info->caching_workers =
-               btrfs_alloc_workqueue("cache", flags, max_active, 0);
+               btrfs_alloc_workqueue(fs_info, "cache", flags, max_active, 0);
  
        /*
         * a higher idle thresh on the submit workers makes it much more
         * devices
         */
        fs_info->submit_workers =
-               btrfs_alloc_workqueue("submit", flags,
+               btrfs_alloc_workqueue(fs_info, "submit", flags,
                                      min_t(u64, fs_devices->num_devices,
                                            max_active), 64);
  
        fs_info->fixup_workers =
-               btrfs_alloc_workqueue("fixup", flags, 1, 0);
+               btrfs_alloc_workqueue(fs_info, "fixup", flags, 1, 0);
  
        /*
         * endios are largely parallel and should have a very
         * low idle thresh
         */
        fs_info->endio_workers =
-               btrfs_alloc_workqueue("endio", flags, max_active, 4);
+               btrfs_alloc_workqueue(fs_info, "endio", flags, max_active, 4);
        fs_info->endio_meta_workers =
-               btrfs_alloc_workqueue("endio-meta", flags, max_active, 4);
+               btrfs_alloc_workqueue(fs_info, "endio-meta", flags,
+                                     max_active, 4);
        fs_info->endio_meta_write_workers =
-               btrfs_alloc_workqueue("endio-meta-write", flags, max_active, 2);
+               btrfs_alloc_workqueue(fs_info, "endio-meta-write", flags,
+                                     max_active, 2);
        fs_info->endio_raid56_workers =
-               btrfs_alloc_workqueue("endio-raid56", flags, max_active, 4);
+               btrfs_alloc_workqueue(fs_info, "endio-raid56", flags,
+                                     max_active, 4);
        fs_info->endio_repair_workers =
-               btrfs_alloc_workqueue("endio-repair", flags, 1, 0);
+               btrfs_alloc_workqueue(fs_info, "endio-repair", flags, 1, 0);
        fs_info->rmw_workers =
-               btrfs_alloc_workqueue("rmw", flags, max_active, 2);
+               btrfs_alloc_workqueue(fs_info, "rmw", flags, max_active, 2);
        fs_info->endio_write_workers =
-               btrfs_alloc_workqueue("endio-write", flags, max_active, 2);
+               btrfs_alloc_workqueue(fs_info, "endio-write", flags,
+                                     max_active, 2);
        fs_info->endio_freespace_worker =
-               btrfs_alloc_workqueue("freespace-write", flags, max_active, 0);
+               btrfs_alloc_workqueue(fs_info, "freespace-write", flags,
+                                     max_active, 0);
        fs_info->delayed_workers =
-               btrfs_alloc_workqueue("delayed-meta", flags, max_active, 0);
+               btrfs_alloc_workqueue(fs_info, "delayed-meta", flags,
+                                     max_active, 0);
        fs_info->readahead_workers =
-               btrfs_alloc_workqueue("readahead", flags, max_active, 2);
+               btrfs_alloc_workqueue(fs_info, "readahead", flags,
+                                     max_active, 2);
        fs_info->qgroup_rescan_workers =
-               btrfs_alloc_workqueue("qgroup-rescan", flags, 1, 0);
+               btrfs_alloc_workqueue(fs_info, "qgroup-rescan", flags, 1, 0);
        fs_info->extent_workers =
-               btrfs_alloc_workqueue("extent-refs", flags,
+               btrfs_alloc_workqueue(fs_info, "extent-refs", flags,
                                      min_t(u64, fs_devices->num_devices,
                                            max_active), 8);
  
@@@ -3010,8 -3023,8 +3017,8 @@@ retry_root_backup
        if (IS_ERR(fs_info->transaction_kthread))
                goto fail_cleaner;
  
-       if (!btrfs_test_opt(tree_root, SSD) &&
-           !btrfs_test_opt(tree_root, NOSSD) &&
+       if (!btrfs_test_opt(tree_root->fs_info, SSD) &&
+           !btrfs_test_opt(tree_root->fs_info, NOSSD) &&
            !fs_info->fs_devices->rotating) {
                btrfs_info(fs_info, "detected SSD devices, enabling SSD mode");
                btrfs_set_opt(fs_info->mount_opt, SSD);
        btrfs_apply_pending_changes(fs_info);
  
  #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
-       if (btrfs_test_opt(tree_root, CHECK_INTEGRITY)) {
+       if (btrfs_test_opt(tree_root->fs_info, CHECK_INTEGRITY)) {
                ret = btrfsic_mount(tree_root, fs_devices,
-                                   btrfs_test_opt(tree_root,
+                                   btrfs_test_opt(tree_root->fs_info,
                                        CHECK_INTEGRITY_INCLUDING_EXTENT_DATA) ?
                                    1 : 0,
                                    fs_info->check_integrity_print_mask);
  
        /* do not make disk changes in broken FS or nologreplay is given */
        if (btrfs_super_log_root(disk_super) != 0 &&
-           !btrfs_test_opt(tree_root, NOLOGREPLAY)) {
+           !btrfs_test_opt(tree_root->fs_info, NOLOGREPLAY)) {
                ret = btrfs_replay_log(fs_info, fs_devices);
                if (ret) {
                        err = ret;
        if (sb->s_flags & MS_RDONLY)
                return 0;
  
-       if (btrfs_test_opt(tree_root, FREE_SPACE_TREE) &&
+       if (btrfs_test_opt(tree_root->fs_info, FREE_SPACE_TREE) &&
            !btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
                btrfs_info(fs_info, "creating free space tree");
                ret = btrfs_create_free_space_tree(fs_info);
  
        btrfs_qgroup_rescan_resume(fs_info);
  
-       if (btrfs_test_opt(tree_root, CLEAR_CACHE) &&
+       if (btrfs_test_opt(tree_root->fs_info, CLEAR_CACHE) &&
            btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
                btrfs_info(fs_info, "clearing free space tree");
                ret = btrfs_clear_free_space_tree(fs_info);
                        close_ctree(tree_root);
                        return ret;
                }
-       } else if (btrfs_test_opt(tree_root, RESCAN_UUID_TREE) ||
+       } else if (btrfs_test_opt(tree_root->fs_info, RESCAN_UUID_TREE) ||
                   fs_info->generation !=
                                btrfs_super_uuid_tree_generation(disk_super)) {
                btrfs_info(fs_info, "checking UUID tree");
@@@ -3218,7 -3231,7 +3225,7 @@@ fail
        return err;
  
  recovery_tree_root:
-       if (!btrfs_test_opt(tree_root, USEBACKUPROOT))
+       if (!btrfs_test_opt(tree_root->fs_info, USEBACKUPROOT))
                goto fail_tree_roots;
  
        free_root_pointers(fs_info, 0);
@@@ -3412,9 -3425,9 +3419,9 @@@ static int write_dev_supers(struct btrf
                 * to go down lazy.
                 */
                if (i == 0)
 -                      ret = btrfsic_submit_bh(WRITE_FUA, bh);
 +                      ret = btrfsic_submit_bh(REQ_OP_WRITE, WRITE_FUA, bh);
                else
 -                      ret = btrfsic_submit_bh(WRITE_SYNC, bh);
 +                      ret = btrfsic_submit_bh(REQ_OP_WRITE, WRITE_SYNC, bh);
                if (ret)
                        errors++;
        }
@@@ -3478,13 -3491,12 +3485,13 @@@ static int write_dev_flush(struct btrfs
  
        bio->bi_end_io = btrfs_end_empty_barrier;
        bio->bi_bdev = device->bdev;
 +      bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_FLUSH);
        init_completion(&device->flush_wait);
        bio->bi_private = &device->flush_wait;
        device->flush_bio = bio;
  
        bio_get(bio);
 -      btrfsic_submit_bio(WRITE_FLUSH, bio);
 +      btrfsic_submit_bio(bio);
  
        return 0;
  }
@@@ -3634,7 -3646,7 +3641,7 @@@ static int write_all_supers(struct btrf
        int total_errors = 0;
        u64 flags;
  
-       do_barriers = !btrfs_test_opt(root, NOBARRIER);
+       do_barriers = !btrfs_test_opt(root->fs_info, NOBARRIER);
        backup_super_roots(root->fs_info);
  
        sb = root->fs_info->super_for_commit;
@@@ -3918,7 -3930,7 +3925,7 @@@ void close_ctree(struct btrfs_root *roo
        iput(fs_info->btree_inode);
  
  #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
-       if (btrfs_test_opt(root, CHECK_INTEGRITY))
+       if (btrfs_test_opt(root->fs_info, CHECK_INTEGRITY))
                btrfsic_unmount(root, fs_info->fs_devices);
  #endif
  
diff --combined fs/btrfs/disk-io.h
index dbf3e1aab69e904a75a6828bbcb6f955166c8b25,c9d42c92da2b2602113328cc299912982ca3a253..b3207a0e09f7966703e1d130e250f05f610b2a3f
@@@ -90,7 -90,8 +90,8 @@@ void btrfs_drop_and_free_fs_root(struc
  void btrfs_free_fs_root(struct btrfs_root *root);
  
  #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
- struct btrfs_root *btrfs_alloc_dummy_root(u32 sectorsize, u32 nodesize);
+ struct btrfs_root *btrfs_alloc_dummy_root(struct btrfs_fs_info *fs_info,
+                                         u32 sectorsize, u32 nodesize);
  #endif
  
  /*
@@@ -122,7 -123,7 +123,7 @@@ void btrfs_csum_final(u32 crc, char *re
  int btrfs_bio_wq_end_io(struct btrfs_fs_info *info, struct bio *bio,
                        enum btrfs_wq_endio_type metadata);
  int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode,
 -                      int rw, struct bio *bio, int mirror_num,
 +                      struct bio *bio, int mirror_num,
                        unsigned long bio_flags, u64 bio_offset,
                        extent_submit_bio_hook_t *submit_bio_start,
                        extent_submit_bio_hook_t *submit_bio_done);
diff --combined fs/btrfs/extent-tree.c
index e9376b1657e25ff18f72d8f41bc37e1d520d3f01,c2b81b0d3fe08c3d7d391769ea87cb0e9a5b815d..61b494e8e604e9e80f1c46c581ede724f56ea050
@@@ -2058,7 -2058,7 +2058,7 @@@ int btrfs_discard_extent(struct btrfs_r
         */
        btrfs_bio_counter_inc_blocked(root->fs_info);
        /* Tell the block device(s) that the sectors can be discarded */
 -      ret = btrfs_map_block(root->fs_info, REQ_DISCARD,
 +      ret = btrfs_map_block(root->fs_info, REQ_OP_DISCARD,
                              bytenr, &num_bytes, &bbio, 0);
        /* Error condition is -ENOMEM */
        if (!ret) {
@@@ -2180,7 -2180,7 +2180,7 @@@ static int __btrfs_inc_extent_ref(struc
                                    path, bytenr, parent, root_objectid,
                                    owner, offset, refs_to_add);
        if (ret)
-               btrfs_abort_transaction(trans, root, ret);
+               btrfs_abort_transaction(trans, ret);
  out:
        btrfs_free_path(path);
        return ret;
@@@ -2204,7 -2204,7 +2204,7 @@@ static int run_delayed_data_ref(struct 
        ins.type = BTRFS_EXTENT_ITEM_KEY;
  
        ref = btrfs_delayed_node_to_data_ref(node);
-       trace_run_delayed_data_ref(node, ref, node->action);
+       trace_run_delayed_data_ref(root->fs_info, node, ref, node->action);
  
        if (node->type == BTRFS_SHARED_DATA_REF_KEY)
                parent = ref->parent;
@@@ -2359,7 -2359,7 +2359,7 @@@ static int run_delayed_tree_ref(struct 
                                                 SKINNY_METADATA);
  
        ref = btrfs_delayed_node_to_tree_ref(node);
-       trace_run_delayed_tree_ref(node, ref, node->action);
+       trace_run_delayed_tree_ref(root->fs_info, node, ref, node->action);
  
        if (node->type == BTRFS_SHARED_BLOCK_REF_KEY)
                parent = ref->parent;
@@@ -2423,7 -2423,8 +2423,8 @@@ static int run_one_delayed_ref(struct b
                 */
                BUG_ON(extent_op);
                head = btrfs_delayed_node_to_head(node);
-               trace_run_delayed_ref_head(node, head, node->action);
+               trace_run_delayed_ref_head(root->fs_info, node, head,
+                                          node->action);
  
                if (insert_reserved) {
                        btrfs_pin_extent(root, node->bytenr,
@@@ -2778,7 -2779,7 +2779,7 @@@ u64 btrfs_csum_bytes_to_leaves(struct b
        u64 num_csums_per_leaf;
        u64 num_csums;
  
-       csum_size = BTRFS_LEAF_DATA_SIZE(root) - sizeof(struct btrfs_item);
+       csum_size = BTRFS_MAX_ITEM_SIZE(root);
        num_csums_per_leaf = div64_u64(csum_size,
                        (u64)btrfs_super_csum_size(root->fs_info->super_copy));
        num_csums = div64_u64(csum_bytes, root->sectorsize);
@@@ -2970,7 -2971,7 +2971,7 @@@ again
        trans->can_flush_pending_bgs = false;
        ret = __btrfs_run_delayed_refs(trans, root, count);
        if (ret < 0) {
-               btrfs_abort_transaction(trans, root, ret);
+               btrfs_abort_transaction(trans, ret);
                return ret;
        }
  
@@@ -3234,7 -3235,7 +3235,7 @@@ static int __btrfs_mod_ref(struct btrfs
                            u64, u64, u64, u64, u64, u64);
  
  
-       if (btrfs_test_is_dummy_root(root))
+       if (btrfs_is_testing(root->fs_info))
                return 0;
  
        ref_root = btrfs_header_owner(buf);
@@@ -3429,7 -3430,7 +3430,7 @@@ again
                 * transaction, this only happens in really bad situations
                 * anyway.
                 */
-               btrfs_abort_transaction(trans, root, ret);
+               btrfs_abort_transaction(trans, ret);
                goto out_put;
        }
        WARN_ON(ret);
  
        spin_lock(&block_group->lock);
        if (block_group->cached != BTRFS_CACHE_FINISHED ||
-           !btrfs_test_opt(root, SPACE_CACHE)) {
+           !btrfs_test_opt(root->fs_info, SPACE_CACHE)) {
                /*
                 * don't bother trying to write stuff out _if_
                 * a) we're not cached,
@@@ -3524,7 -3525,7 +3525,7 @@@ int btrfs_setup_space_cache(struct btrf
        struct btrfs_path *path;
  
        if (list_empty(&cur_trans->dirty_bgs) ||
-           !btrfs_test_opt(root, SPACE_CACHE))
+           !btrfs_test_opt(root->fs_info, SPACE_CACHE))
                return 0;
  
        path = btrfs_alloc_path();
@@@ -3669,7 -3670,7 +3670,7 @@@ again
                                }
                                spin_unlock(&cur_trans->dirty_bgs_lock);
                        } else if (ret) {
-                               btrfs_abort_transaction(trans, root, ret);
+                               btrfs_abort_transaction(trans, ret);
                        }
                }
  
@@@ -3815,7 -3816,7 +3816,7 @@@ int btrfs_write_dirty_block_groups(stru
                                                            cache);
                        }
                        if (ret)
-                               btrfs_abort_transaction(trans, root, ret);
+                               btrfs_abort_transaction(trans, ret);
                }
  
                /* if its not on the io list, we need to put the block group */
@@@ -4443,7 -4444,7 +4444,7 @@@ void check_system_chunk(struct btrfs_tr
        thresh = btrfs_calc_trunc_metadata_size(root, num_devs) +
                btrfs_calc_trans_metadata_size(root, 1);
  
-       if (left < thresh && btrfs_test_opt(root, ENOSPC_DEBUG)) {
+       if (left < thresh && btrfs_test_opt(root->fs_info, ENOSPC_DEBUG)) {
                btrfs_info(root->fs_info, "left=%llu, need=%llu, flags=%llu",
                        left, thresh, type);
                dump_space_info(info, 0, 0);
@@@ -4588,7 -4589,7 +4589,7 @@@ out
         */
        if (trans->can_flush_pending_bgs &&
            trans->chunk_bytes_reserved >= (u64)SZ_2M) {
-               btrfs_create_pending_block_groups(trans, trans->root);
+               btrfs_create_pending_block_groups(trans, extent_root);
                btrfs_trans_release_chunk_metadata(trans);
        }
        return ret;
@@@ -5729,7 -5730,7 +5730,7 @@@ void btrfs_trans_release_metadata(struc
   */
  void btrfs_trans_release_chunk_metadata(struct btrfs_trans_handle *trans)
  {
-       struct btrfs_fs_info *fs_info = trans->root->fs_info;
+       struct btrfs_fs_info *fs_info = trans->fs_info;
  
        if (!trans->chunk_bytes_reserved)
                return;
@@@ -6100,7 -6101,7 +6101,7 @@@ void btrfs_delalloc_release_metadata(st
        if (dropped > 0)
                to_free += btrfs_calc_trans_metadata_size(root, dropped);
  
-       if (btrfs_test_is_dummy_root(root))
+       if (btrfs_is_testing(root->fs_info))
                return;
  
        trace_btrfs_space_reservation(root->fs_info, "delalloc",
@@@ -6215,7 -6216,7 +6216,7 @@@ static int update_block_group(struct bt
                spin_lock(&cache->space_info->lock);
                spin_lock(&cache->lock);
  
-               if (btrfs_test_opt(root, SPACE_CACHE) &&
+               if (btrfs_test_opt(root->fs_info, SPACE_CACHE) &&
                    cache->disk_cache_state < BTRFS_DC_CLEAR)
                        cache->disk_cache_state = BTRFS_DC_CLEAR;
  
@@@ -6597,7 -6598,7 +6598,7 @@@ fetch_cluster_info(struct btrfs_root *r
                   u64 *empty_cluster)
  {
        struct btrfs_free_cluster *ret = NULL;
-       bool ssd = btrfs_test_opt(root, SSD);
+       bool ssd = btrfs_test_opt(root->fs_info, SSD);
  
        *empty_cluster = 0;
        if (btrfs_mixed_space_info(space_info))
@@@ -6742,7 -6743,7 +6743,7 @@@ int btrfs_finish_extent_commit(struct b
                        break;
                }
  
-               if (btrfs_test_opt(root, DISCARD))
+               if (btrfs_test_opt(root->fs_info, DISCARD))
                        ret = btrfs_discard_extent(root, start,
                                                   end + 1 - start, NULL);
  
@@@ -6880,7 -6881,7 +6881,7 @@@ static int __btrfs_free_extent(struct b
                                                    NULL, refs_to_drop,
                                                    is_data, &last_ref);
                        if (ret) {
-                               btrfs_abort_transaction(trans, extent_root, ret);
+                               btrfs_abort_transaction(trans, ret);
                                goto out;
                        }
                        btrfs_release_path(path);
                                                         path->nodes[0]);
                        }
                        if (ret < 0) {
-                               btrfs_abort_transaction(trans, extent_root, ret);
+                               btrfs_abort_transaction(trans, ret);
                                goto out;
                        }
                        extent_slot = path->slots[0];
                        "unable to find ref byte nr %llu parent %llu root %llu  owner %llu offset %llu",
                        bytenr, parent, root_objectid, owner_objectid,
                        owner_offset);
-               btrfs_abort_transaction(trans, extent_root, ret);
+               btrfs_abort_transaction(trans, ret);
                goto out;
        } else {
-               btrfs_abort_transaction(trans, extent_root, ret);
+               btrfs_abort_transaction(trans, ret);
                goto out;
        }
  
                ret = convert_extent_item_v0(trans, extent_root, path,
                                             owner_objectid, 0);
                if (ret < 0) {
-                       btrfs_abort_transaction(trans, extent_root, ret);
+                       btrfs_abort_transaction(trans, ret);
                        goto out;
                }
  
                        btrfs_print_leaf(extent_root, path->nodes[0]);
                }
                if (ret < 0) {
-                       btrfs_abort_transaction(trans, extent_root, ret);
+                       btrfs_abort_transaction(trans, ret);
                        goto out;
                }
  
                btrfs_err(info, "trying to drop %d refs but we only have %Lu "
                          "for bytenr %Lu", refs_to_drop, refs, bytenr);
                ret = -EINVAL;
-               btrfs_abort_transaction(trans, extent_root, ret);
+               btrfs_abort_transaction(trans, ret);
                goto out;
        }
        refs -= refs_to_drop;
                                                    iref, refs_to_drop,
                                                    is_data, &last_ref);
                        if (ret) {
-                               btrfs_abort_transaction(trans, extent_root, ret);
+                               btrfs_abort_transaction(trans, ret);
                                goto out;
                        }
                }
                ret = btrfs_del_items(trans, extent_root, path, path->slots[0],
                                      num_to_del);
                if (ret) {
-                       btrfs_abort_transaction(trans, extent_root, ret);
+                       btrfs_abort_transaction(trans, ret);
                        goto out;
                }
                btrfs_release_path(path);
                if (is_data) {
                        ret = btrfs_del_csums(trans, root, bytenr, num_bytes);
                        if (ret) {
-                               btrfs_abort_transaction(trans, extent_root, ret);
+                               btrfs_abort_transaction(trans, ret);
                                goto out;
                        }
                }
                ret = add_to_free_space_tree(trans, root->fs_info, bytenr,
                                             num_bytes);
                if (ret) {
-                       btrfs_abort_transaction(trans, extent_root, ret);
+                       btrfs_abort_transaction(trans, ret);
                        goto out;
                }
  
                ret = update_block_group(trans, root, bytenr, num_bytes, 0);
                if (ret) {
-                       btrfs_abort_transaction(trans, extent_root, ret);
+                       btrfs_abort_transaction(trans, ret);
                        goto out;
                }
        }
@@@ -7216,7 -7217,7 +7217,7 @@@ int btrfs_free_extent(struct btrfs_tran
        int ret;
        struct btrfs_fs_info *fs_info = root->fs_info;
  
-       if (btrfs_test_is_dummy_root(root))
+       if (btrfs_is_testing(fs_info))
                return 0;
  
        add_pinned_bytes(root->fs_info, num_bytes, owner, root_objectid);
@@@ -7851,8 -7852,7 +7852,7 @@@ loop
                         * can do more things.
                         */
                        if (ret < 0 && ret != -ENOSPC)
-                               btrfs_abort_transaction(trans,
-                                                       root, ret);
+                               btrfs_abort_transaction(trans, ret);
                        else
                                ret = 0;
                        if (!exist)
@@@ -7906,8 -7906,8 +7906,8 @@@ static void dump_space_info(struct btrf
        printk(KERN_INFO "BTRFS: space_info %llu has %llu free, is %sfull\n",
               info->flags,
               info->total_bytes - info->bytes_used - info->bytes_pinned -
-              info->bytes_reserved - info->bytes_readonly,
-              (info->full) ? "" : "not ");
+              info->bytes_reserved - info->bytes_readonly -
+              info->bytes_may_use, (info->full) ? "" : "not ");
        printk(KERN_INFO "BTRFS: space_info total=%llu, used=%llu, pinned=%llu, "
               "reserved=%llu, may_use=%llu, readonly=%llu\n",
               info->total_bytes, info->bytes_used, info->bytes_pinned,
@@@ -7961,7 -7961,7 +7961,7 @@@ again
                        if (num_bytes == min_alloc_size)
                                final_tried = true;
                        goto again;
-               } else if (btrfs_test_opt(root, ENOSPC_DEBUG)) {
+               } else if (btrfs_test_opt(root->fs_info, ENOSPC_DEBUG)) {
                        struct btrfs_space_info *sinfo;
  
                        sinfo = __find_space_info(root->fs_info, flags);
@@@ -7992,7 -7992,7 +7992,7 @@@ static int __btrfs_free_reserved_extent
        if (pin)
                pin_down_extent(root, cache, start, len, 1);
        else {
-               if (btrfs_test_opt(root, DISCARD))
+               if (btrfs_test_opt(root->fs_info, DISCARD))
                        ret = btrfs_discard_extent(root, start, len, NULL);
                btrfs_add_free_space(cache, start, len);
                btrfs_update_reserved_bytes(cache, len, RESERVE_FREE, delalloc);
@@@ -8300,7 -8300,7 +8300,7 @@@ again
                goto again;
        }
  
-       if (btrfs_test_opt(root, ENOSPC_DEBUG)) {
+       if (btrfs_test_opt(root->fs_info, ENOSPC_DEBUG)) {
                static DEFINE_RATELIMIT_STATE(_rs,
                                DEFAULT_RATELIMIT_INTERVAL * 10,
                                /*DEFAULT_RATELIMIT_BURST*/ 1);
@@@ -8354,13 -8354,15 +8354,15 @@@ struct extent_buffer *btrfs_alloc_tree_
        bool skinny_metadata = btrfs_fs_incompat(root->fs_info,
                                                 SKINNY_METADATA);
  
-       if (btrfs_test_is_dummy_root(root)) {
+ #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
+       if (btrfs_is_testing(root->fs_info)) {
                buf = btrfs_init_new_buffer(trans, root, root->alloc_bytenr,
                                            level);
                if (!IS_ERR(buf))
                        root->alloc_bytenr += blocksize;
                return buf;
        }
+ #endif
  
        block_rsv = use_block_rsv(trans, root, blocksize);
        if (IS_ERR(block_rsv))
@@@ -8540,7 -8542,8 +8542,8 @@@ static int record_one_subtree_extent(st
  
        delayed_refs = &trans->transaction->delayed_refs;
        spin_lock(&delayed_refs->lock);
-       if (btrfs_qgroup_insert_dirty_extent(delayed_refs, qrecord))
+       if (btrfs_qgroup_insert_dirty_extent(trans->fs_info,
+                                            delayed_refs, qrecord))
                kfree(qrecord);
        spin_unlock(&delayed_refs->lock);
  
@@@ -9325,7 -9328,7 +9328,7 @@@ int btrfs_drop_snapshot(struct btrfs_ro
                                                &root->root_key,
                                                root_item);
                        if (ret) {
-                               btrfs_abort_transaction(trans, tree_root, ret);
+                               btrfs_abort_transaction(trans, ret);
                                err = ret;
                                goto out_end_trans;
                        }
  
        ret = btrfs_del_root(trans, tree_root, &root->root_key);
        if (ret) {
-               btrfs_abort_transaction(trans, tree_root, ret);
+               btrfs_abort_transaction(trans, ret);
                goto out_end_trans;
        }
  
                ret = btrfs_find_root(tree_root, &root->root_key, path,
                                      NULL, NULL);
                if (ret < 0) {
-                       btrfs_abort_transaction(trans, tree_root, ret);
+                       btrfs_abort_transaction(trans, ret);
                        err = ret;
                        goto out_end_trans;
                } else if (ret > 0) {
@@@ -9731,7 -9734,7 +9734,7 @@@ int btrfs_can_relocate(struct btrfs_roo
        int full = 0;
        int ret = 0;
  
-       debug = btrfs_test_opt(root, ENOSPC_DEBUG);
+       debug = btrfs_test_opt(root->fs_info, ENOSPC_DEBUG);
  
        block_group = btrfs_lookup_block_group(root->fs_info, bytenr);
  
@@@ -9887,7 -9890,22 +9890,22 @@@ static int find_first_block_group(struc
  
                if (found_key.objectid >= key->objectid &&
                    found_key.type == BTRFS_BLOCK_GROUP_ITEM_KEY) {
-                       ret = 0;
+                       struct extent_map_tree *em_tree;
+                       struct extent_map *em;
+                       em_tree = &root->fs_info->mapping_tree.map_tree;
+                       read_lock(&em_tree->lock);
+                       em = lookup_extent_mapping(em_tree, found_key.objectid,
+                                                  found_key.offset);
+                       read_unlock(&em_tree->lock);
+                       if (!em) {
+                               btrfs_err(root->fs_info,
+                       "logical %llu len %llu found bg but no related chunk",
+                                         found_key.objectid, found_key.offset);
+                               ret = -ENOENT;
+                       } else {
+                               ret = 0;
+                       }
                        goto out;
                }
                path->slots[0]++;
@@@ -10129,10 -10147,10 +10147,10 @@@ int btrfs_read_block_groups(struct btrf
        path->reada = READA_FORWARD;
  
        cache_gen = btrfs_super_cache_generation(root->fs_info->super_copy);
-       if (btrfs_test_opt(root, SPACE_CACHE) &&
+       if (btrfs_test_opt(root->fs_info, SPACE_CACHE) &&
            btrfs_super_generation(root->fs_info->super_copy) != cache_gen)
                need_clear = 1;
-       if (btrfs_test_opt(root, CLEAR_CACHE))
+       if (btrfs_test_opt(root->fs_info, CLEAR_CACHE))
                need_clear = 1;
  
        while (1) {
                         * b) Setting 'dirty flag' makes sure that we flush
                         *    the new space cache info onto disk.
                         */
-                       if (btrfs_test_opt(root, SPACE_CACHE))
+                       if (btrfs_test_opt(root->fs_info, SPACE_CACHE))
                                cache->disk_cache_state = BTRFS_DC_CLEAR;
                }
  
@@@ -10305,11 -10323,11 +10323,11 @@@ void btrfs_create_pending_block_groups(
                ret = btrfs_insert_item(trans, extent_root, &key, &item,
                                        sizeof(item));
                if (ret)
-                       btrfs_abort_transaction(trans, extent_root, ret);
+                       btrfs_abort_transaction(trans, ret);
                ret = btrfs_finish_chunk_alloc(trans, extent_root,
                                               key.objectid, key.offset);
                if (ret)
-                       btrfs_abort_transaction(trans, extent_root, ret);
+                       btrfs_abort_transaction(trans, ret);
                add_block_group_free_space(trans, root->fs_info, block_group);
                /* already aborted the transaction if it failed. */
  next:
@@@ -10622,7 -10640,7 +10640,7 @@@ int btrfs_remove_block_group(struct btr
        spin_lock(&block_group->space_info->lock);
        list_del_init(&block_group->ro_list);
  
-       if (btrfs_test_opt(root, ENOSPC_DEBUG)) {
+       if (btrfs_test_opt(root->fs_info, ENOSPC_DEBUG)) {
                WARN_ON(block_group->space_info->total_bytes
                        < block_group->key.offset);
                WARN_ON(block_group->space_info->bytes_readonly
@@@ -10890,7 -10908,7 +10908,7 @@@ void btrfs_delete_unused_bgs(struct btr
                spin_unlock(&space_info->lock);
  
                /* DISCARD can flip during remount */
-               trimming = btrfs_test_opt(root, DISCARD);
+               trimming = btrfs_test_opt(root->fs_info, DISCARD);
  
                /* Implicit trim during transaction commit. */
                if (trimming)
diff --combined fs/btrfs/extent_io.c
index cee4cb99b8ce7b436c60f394b518e22256ecbf97,dae2f8470e042ee4c8cde3abbecb5af86aa272ed..80d92839d119548f1c02bcb22e6b45263c85ce80
@@@ -163,13 -163,13 +163,13 @@@ int __init extent_io_init(void
  {
        extent_state_cache = kmem_cache_create("btrfs_extent_state",
                        sizeof(struct extent_state), 0,
-                       SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
+                       SLAB_MEM_SPREAD, NULL);
        if (!extent_state_cache)
                return -ENOMEM;
  
        extent_buffer_cache = kmem_cache_create("btrfs_extent_buffer",
                        sizeof(struct extent_buffer), 0,
-                       SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
+                       SLAB_MEM_SPREAD, NULL);
        if (!extent_buffer_cache)
                goto free_state_cache;
  
@@@ -2049,10 -2049,9 +2049,10 @@@ int repair_io_failure(struct inode *ino
                return -EIO;
        }
        bio->bi_bdev = dev->bdev;
 +      bio->bi_rw = WRITE_SYNC;
        bio_add_page(bio, page, length, pg_offset);
  
 -      if (btrfsic_submit_bio_wait(WRITE_SYNC, bio)) {
 +      if (btrfsic_submit_bio_wait(bio)) {
                /* try to remap that extent elsewhere? */
                btrfs_bio_counter_dec(fs_info);
                bio_put(bio);
@@@ -2387,7 -2386,7 +2387,7 @@@ static int bio_readpage_error(struct bi
        int read_mode;
        int ret;
  
 -      BUG_ON(failed_bio->bi_rw & REQ_WRITE);
 +      BUG_ON(bio_op(failed_bio) == REQ_OP_WRITE);
  
        ret = btrfs_get_io_failure_record(inode, start, end, &failrec);
        if (ret)
                free_io_failure(inode, failrec);
                return -EIO;
        }
 +      bio_set_op_attrs(bio, REQ_OP_READ, read_mode);
  
        pr_debug("Repair Read Error: submitting new read[%#x] to this_mirror=%d, in_validation=%d\n",
                 read_mode, failrec->this_mirror, failrec->in_validation);
  
 -      ret = tree->ops->submit_bio_hook(inode, read_mode, bio,
 -                                       failrec->this_mirror,
 +      ret = tree->ops->submit_bio_hook(inode, bio, failrec->this_mirror,
                                         failrec->bio_flags, 0);
        if (ret) {
                free_io_failure(inode, failrec);
@@@ -2724,8 -2723,8 +2724,8 @@@ struct bio *btrfs_io_bio_alloc(gfp_t gf
  }
  
  
 -static int __must_check submit_one_bio(int rw, struct bio *bio,
 -                                     int mirror_num, unsigned long bio_flags)
 +static int __must_check submit_one_bio(struct bio *bio, int mirror_num,
 +                                     unsigned long bio_flags)
  {
        int ret = 0;
        struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
        start = page_offset(page) + bvec->bv_offset;
  
        bio->bi_private = NULL;
 -
        bio_get(bio);
  
        if (tree->ops && tree->ops->submit_bio_hook)
 -              ret = tree->ops->submit_bio_hook(page->mapping->host, rw, bio,
 +              ret = tree->ops->submit_bio_hook(page->mapping->host, bio,
                                           mirror_num, bio_flags, start);
        else
 -              btrfsic_submit_bio(rw, bio);
 +              btrfsic_submit_bio(bio);
  
        bio_put(bio);
        return ret;
  }
  
 -static int merge_bio(int rw, struct extent_io_tree *tree, struct page *page,
 +static int merge_bio(struct extent_io_tree *tree, struct page *page,
                     unsigned long offset, size_t size, struct bio *bio,
                     unsigned long bio_flags)
  {
        int ret = 0;
        if (tree->ops && tree->ops->merge_bio_hook)
 -              ret = tree->ops->merge_bio_hook(rw, page, offset, size, bio,
 +              ret = tree->ops->merge_bio_hook(page, offset, size, bio,
                                                bio_flags);
-       BUG_ON(ret < 0);
        return ret;
  
  }
  
 -static int submit_extent_page(int rw, struct extent_io_tree *tree,
 +static int submit_extent_page(int op, int op_flags, struct extent_io_tree *tree,
                              struct writeback_control *wbc,
                              struct page *page, sector_t sector,
                              size_t size, unsigned long offset,
  
                if (prev_bio_flags != bio_flags || !contig ||
                    force_bio_submit ||
 -                  merge_bio(rw, tree, page, offset, page_size, bio, bio_flags) ||
 +                  merge_bio(tree, page, offset, page_size, bio, bio_flags) ||
                    bio_add_page(bio, page, page_size, offset) < page_size) {
 -                      ret = submit_one_bio(rw, bio, mirror_num,
 -                                           prev_bio_flags);
 +                      ret = submit_one_bio(bio, mirror_num, prev_bio_flags);
                        if (ret < 0) {
                                *bio_ret = NULL;
                                return ret;
        bio_add_page(bio, page, page_size, offset);
        bio->bi_end_io = end_io_func;
        bio->bi_private = tree;
 +      bio_set_op_attrs(bio, op, op_flags);
        if (wbc) {
                wbc_init_bio(wbc, bio);
                wbc_account_io(wbc, page, page_size);
        if (bio_ret)
                *bio_ret = bio;
        else
 -              ret = submit_one_bio(rw, bio, mirror_num, bio_flags);
 +              ret = submit_one_bio(bio, mirror_num, bio_flags);
  
        return ret;
  }
@@@ -2879,13 -2878,14 +2878,14 @@@ __get_extent_map(struct inode *inode, s
   * into the tree that are removed when the IO is done (by the end_io
   * handlers)
   * XXX JDM: This needs looking at to ensure proper page locking
+  * return 0 on success, otherwise return error
   */
  static int __do_readpage(struct extent_io_tree *tree,
                         struct page *page,
                         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 read_flags,
                         u64 *prev_em_start)
  {
        struct inode *inode = page->mapping->host;
        sector_t sector;
        struct extent_map *em;
        struct block_device *bdev;
-       int ret;
+       int ret = 0;
        int nr = 0;
        size_t pg_offset = 0;
        size_t iosize;
                }
  
                pnr -= page->index;
 -              ret = submit_extent_page(rw, tree, NULL, page,
 -                                       sector, disk_io_size, pg_offset,
 +              ret = submit_extent_page(REQ_OP_READ, read_flags, tree, NULL,
 +                                       page, sector, disk_io_size, pg_offset,
                                         bdev, bio, pnr,
                                         end_bio_extent_readpage, mirror_num,
                                         *bio_flags,
                } else {
                        SetPageError(page);
                        unlock_extent(tree, cur, cur + iosize - 1);
+                       goto out;
                }
                cur = cur + iosize;
                pg_offset += iosize;
@@@ -3091,7 -3092,7 +3092,7 @@@ out
                        SetPageUptodate(page);
                unlock_page(page);
        }
-       return 0;
+       return ret;
  }
  
  static inline void __do_contiguous_readpages(struct extent_io_tree *tree,
                                             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,
                                             u64 *prev_em_start)
  {
        struct inode *inode;
  
        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, 0, prev_em_start);
                put_page(pages[index]);
        }
  }
@@@ -3131,7 -3132,7 +3132,7 @@@ 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,
                               u64 *prev_em_start)
  {
        u64 start = 0;
                                                  index - first_index, start,
                                                  end, get_extent, em_cached,
                                                  bio, mirror_num, bio_flags,
 -                                                rw, prev_em_start);
 +                                                prev_em_start);
                        start = page_start;
                        end = start + PAGE_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,
                                          prev_em_start);
  }
  
@@@ -3172,7 -3173,7 +3173,7 @@@ static int __extent_read_full_page(stru
                                   struct page *page,
                                   get_extent_t *get_extent,
                                   struct bio **bio, int mirror_num,
 -                                 unsigned long *bio_flags, int rw)
 +                                 unsigned long *bio_flags, int read_flags)
  {
        struct inode *inode = page->mapping->host;
        struct btrfs_ordered_extent *ordered;
        }
  
        ret = __do_readpage(tree, page, get_extent, NULL, bio, mirror_num,
 -                          bio_flags, rw, NULL);
 +                          bio_flags, read_flags, NULL);
        return ret;
  }
  
@@@ -3204,9 -3205,9 +3205,9 @@@ int extent_read_full_page(struct extent
        int ret;
  
        ret = __extent_read_full_page(tree, page, get_extent, &bio, mirror_num,
 -                                    &bio_flags, READ);
 +                                    &bio_flags, 0);
        if (bio)
 -              ret = submit_one_bio(READ, bio, mirror_num, bio_flags);
 +              ret = submit_one_bio(bio, mirror_num, bio_flags);
        return ret;
  }
  
@@@ -3440,8 -3441,8 +3441,8 @@@ static noinline_for_stack int __extent_
                               page->index, cur, end);
                }
  
 -              ret = submit_extent_page(write_flags, tree, wbc, page,
 -                                       sector, iosize, pg_offset,
 +              ret = submit_extent_page(REQ_OP_WRITE, write_flags, tree, wbc,
 +                                       page, sector, iosize, pg_offset,
                                         bdev, &epd->bio, max_nr,
                                         end_bio_extent_writepage,
                                         0, 0, 0, false);
@@@ -3480,11 -3481,13 +3481,11 @@@ static int __extent_writepage(struct pa
        size_t pg_offset = 0;
        loff_t i_size = i_size_read(inode);
        unsigned long end_index = i_size >> PAGE_SHIFT;
 -      int write_flags;
 +      int write_flags = 0;
        unsigned long nr_written = 0;
  
        if (wbc->sync_mode == WB_SYNC_ALL)
                write_flags = WRITE_SYNC;
 -      else
 -              write_flags = WRITE;
  
        trace___extent_writepage(page, inode, wbc);
  
@@@ -3728,7 -3731,7 +3729,7 @@@ static noinline_for_stack int write_one
        u64 offset = eb->start;
        unsigned long i, num_pages;
        unsigned long bio_flags = 0;
 -      int rw = (epd->sync_io ? WRITE_SYNC : WRITE) | REQ_META;
 +      int write_flags = (epd->sync_io ? WRITE_SYNC : 0) | REQ_META;
        int ret = 0;
  
        clear_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags);
  
                clear_page_dirty_for_io(p);
                set_page_writeback(p);
 -              ret = submit_extent_page(rw, tree, wbc, p, offset >> 9,
 -                                       PAGE_SIZE, 0, bdev, &epd->bio,
 -                                       -1, end_bio_extent_buffer_writepage,
 +              ret = submit_extent_page(REQ_OP_WRITE, write_flags, tree, wbc,
 +                                       p, offset >> 9, PAGE_SIZE, 0, bdev,
 +                                       &epd->bio, -1,
 +                                       end_bio_extent_buffer_writepage,
                                         0, epd->bio_flags, bio_flags, false);
                epd->bio_flags = bio_flags;
                if (ret) {
@@@ -4055,12 -4057,13 +4056,12 @@@ retry
  static void flush_epd_write_bio(struct extent_page_data *epd)
  {
        if (epd->bio) {
 -              int rw = WRITE;
                int ret;
  
 -              if (epd->sync_io)
 -                      rw = WRITE_SYNC;
 +              bio_set_op_attrs(epd->bio, REQ_OP_WRITE,
 +                               epd->sync_io ? WRITE_SYNC : 0);
  
 -              ret = submit_one_bio(rw, epd->bio, 0, epd->bio_flags);
 +              ret = submit_one_bio(epd->bio, 0, epd->bio_flags);
                BUG_ON(ret < 0); /* -ENOMEM */
                epd->bio = NULL;
        }
@@@ -4178,8 -4181,7 +4179,8 @@@ int extent_readpages(struct extent_io_t
                prefetchw(&page->flags);
                list_del(&page->lru);
                if (add_to_page_cache_lru(page, mapping,
 -                                      page->index, GFP_NOFS)) {
 +                                      page->index,
 +                                      readahead_gfp_mask(mapping))) {
                        put_page(page);
                        continue;
                }
                if (nr < ARRAY_SIZE(pagepool))
                        continue;
                __extent_readpages(tree, pagepool, nr, get_extent, &em_cached,
 -                                 &bio, 0, &bio_flags, READ, &prev_em_start);
 +                                 &bio, 0, &bio_flags, &prev_em_start);
                nr = 0;
        }
        if (nr)
                __extent_readpages(tree, pagepool, nr, get_extent, &em_cached,
 -                                 &bio, 0, &bio_flags, READ, &prev_em_start);
 +                                 &bio, 0, &bio_flags, &prev_em_start);
  
        if (em_cached)
                free_extent_map(em_cached);
  
        BUG_ON(!list_empty(pages));
        if (bio)
 -              return submit_one_bio(READ, bio, 0, bio_flags);
 +              return submit_one_bio(bio, 0, bio_flags);
        return 0;
  }
  
@@@ -5230,21 -5232,39 +5231,38 @@@ int read_extent_buffer_pages(struct ext
        atomic_set(&eb->io_pages, num_reads);
        for (i = start_i; i < num_pages; i++) {
                page = eb->pages[i];
                if (!PageUptodate(page)) {
+                       if (ret) {
+                               atomic_dec(&eb->io_pages);
+                               unlock_page(page);
+                               continue;
+                       }
                        ClearPageError(page);
                        err = __extent_read_full_page(tree, page,
                                                      get_extent, &bio,
                                                      mirror_num, &bio_flags,
 -                                                    READ | REQ_META);
 +                                                    REQ_META);
-                       if (err)
+                       if (err) {
                                ret = err;
+                               /*
+                                * We use &bio in above __extent_read_full_page,
+                                * so we ensure that if it returns error, the
+                                * current page fails to add itself to bio and
+                                * it's been unlocked.
+                                *
+                                * We must dec io_pages by ourselves.
+                                */
+                               atomic_dec(&eb->io_pages);
+                       }
                } else {
                        unlock_page(page);
                }
        }
  
        if (bio) {
 -              err = submit_one_bio(READ | REQ_META, bio, mirror_num,
 -                                   bio_flags);
 +              err = submit_one_bio(bio, mirror_num, bio_flags);
                if (err)
                        return err;
        }
diff --combined fs/btrfs/inode.c
index 8078077d109084aaa24a32f1a8914e36850f180d,72cfd15b1fa87730fccf3f26abaf0de22e034c46..b0f421f332ae911b731f4c4eb8705053705504ce
@@@ -60,6 -60,7 +60,7 @@@
  #include "hash.h"
  #include "props.h"
  #include "qgroup.h"
+ #include "dedupe.h"
  
  struct btrfs_iget_args {
        struct btrfs_key *location;
@@@ -105,8 -106,9 +106,9 @@@ static int btrfs_truncate(struct inode 
  static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent);
  static noinline int cow_file_range(struct inode *inode,
                                   struct page *locked_page,
-                                  u64 start, u64 end, int *page_started,
-                                  unsigned long *nr_written, int unlock);
+                                  u64 start, u64 end, u64 delalloc_end,
+                                  int *page_started, unsigned long *nr_written,
+                                  int unlock, struct btrfs_dedupe_hash *hash);
  static struct extent_map *create_pinned_em(struct inode *inode, u64 start,
                                           u64 len, u64 orig_start,
                                           u64 block_start, u64 block_len,
@@@ -294,7 -296,7 +296,7 @@@ static noinline int cow_file_range_inli
                                   start, aligned_end, NULL,
                                   1, 1, extent_item_size, &extent_inserted);
        if (ret) {
-               btrfs_abort_transaction(trans, root, ret);
+               btrfs_abort_transaction(trans, ret);
                goto out;
        }
  
                                   inline_len, compressed_size,
                                   compress_type, compressed_pages);
        if (ret && ret != -ENOSPC) {
-               btrfs_abort_transaction(trans, root, ret);
+               btrfs_abort_transaction(trans, ret);
                goto out;
        } else if (ret == -ENOSPC) {
                ret = 1;
@@@ -374,12 -376,12 +376,12 @@@ static inline int inode_need_compress(s
        struct btrfs_root *root = BTRFS_I(inode)->root;
  
        /* force compress */
-       if (btrfs_test_opt(root, FORCE_COMPRESS))
+       if (btrfs_test_opt(root->fs_info, FORCE_COMPRESS))
                return 1;
        /* bad compression ratios */
        if (BTRFS_I(inode)->flags & BTRFS_INODE_NOCOMPRESS)
                return 0;
-       if (btrfs_test_opt(root, COMPRESS) ||
+       if (btrfs_test_opt(root->fs_info, COMPRESS) ||
            BTRFS_I(inode)->flags & BTRFS_INODE_COMPRESS ||
            BTRFS_I(inode)->force_compress)
                return 1;
@@@ -585,9 -587,27 +587,27 @@@ cont
                        will_compress = 0;
                } else {
                        num_bytes = total_in;
+                       *num_added += 1;
+                       /*
+                        * The async work queues will take care of doing actual
+                        * allocation on disk for these compressed pages, and
+                        * will submit them to the elevator.
+                        */
+                       add_async_extent(async_cow, start, num_bytes,
+                                       total_compressed, pages, nr_pages_ret,
+                                       compress_type);
+                       if (start + num_bytes < end) {
+                               start += num_bytes;
+                               pages = NULL;
+                               cond_resched();
+                               goto again;
+                       }
+                       return;
                }
        }
-       if (!will_compress && pages) {
+       if (pages) {
                /*
                 * the compression code ran but failed to make things smaller,
                 * free any pages it allocated and our page pointer array
                nr_pages_ret = 0;
  
                /* flag the file so we don't compress in the future */
-               if (!btrfs_test_opt(root, FORCE_COMPRESS) &&
+               if (!btrfs_test_opt(root->fs_info, FORCE_COMPRESS) &&
                    !(BTRFS_I(inode)->force_compress)) {
                        BTRFS_I(inode)->flags |= BTRFS_INODE_NOCOMPRESS;
                }
        }
-       if (will_compress) {
-               *num_added += 1;
-               /* the async work queues will take care of doing actual
-                * allocation on disk for these compressed pages,
-                * and will submit them to the elevator.
-                */
-               add_async_extent(async_cow, start, num_bytes,
-                                total_compressed, pages, nr_pages_ret,
-                                compress_type);
-               if (start + num_bytes < end) {
-                       start += num_bytes;
-                       pages = NULL;
-                       cond_resched();
-                       goto again;
-               }
-       } else {
  cleanup_and_bail_uncompressed:
-               /*
-                * No compression, but we still need to write the pages in
-                * the file we've been given so far.  redirty the locked
-                * page if it corresponds to our extent and set things up
-                * for the async work queue to run cow_file_range to do
-                * the normal delalloc dance
-                */
-               if (page_offset(locked_page) >= start &&
-                   page_offset(locked_page) <= end) {
-                       __set_page_dirty_nobuffers(locked_page);
-                       /* unlocked later on in the async handlers */
-               }
-               if (redirty)
-                       extent_range_redirty_for_io(inode, start, end);
-               add_async_extent(async_cow, start, end - start + 1,
-                                0, NULL, 0, BTRFS_COMPRESS_NONE);
-               *num_added += 1;
-       }
+       /*
+        * No compression, but we still need to write the pages in the file
+        * we've been given so far.  redirty the locked page if it corresponds
+        * to our extent and set things up for the async work queue to run
+        * cow_file_range to do the normal delalloc dance.
+        */
+       if (page_offset(locked_page) >= start &&
+           page_offset(locked_page) <= end)
+               __set_page_dirty_nobuffers(locked_page);
+               /* unlocked later on in the async handlers */
+       if (redirty)
+               extent_range_redirty_for_io(inode, start, end);
+       add_async_extent(async_cow, start, end - start + 1, 0, NULL, 0,
+                        BTRFS_COMPRESS_NONE);
+       *num_added += 1;
  
        return;
  
@@@ -712,7 -712,10 +712,10 @@@ retry
                                             async_extent->start,
                                             async_extent->start +
                                             async_extent->ram_size - 1,
-                                            &page_started, &nr_written, 0);
+                                            async_extent->start +
+                                            async_extent->ram_size - 1,
+                                            &page_started, &nr_written, 0,
+                                            NULL);
  
                        /* JDM XXX */
  
@@@ -925,9 -928,9 +928,9 @@@ static u64 get_extent_allocation_hint(s
   */
  static noinline int cow_file_range(struct inode *inode,
                                   struct page *locked_page,
-                                  u64 start, u64 end, int *page_started,
-                                  unsigned long *nr_written,
-                                  int unlock)
+                                  u64 start, u64 end, u64 delalloc_end,
+                                  int *page_started, unsigned long *nr_written,
+                                  int unlock, struct btrfs_dedupe_hash *hash)
  {
        struct btrfs_root *root = BTRFS_I(inode)->root;
        u64 alloc_hint = 0;
@@@ -1156,7 -1159,7 +1159,7 @@@ static int cow_file_range_async(struct 
                async_cow->start = start;
  
                if (BTRFS_I(inode)->flags & BTRFS_INODE_NOCOMPRESS &&
-                   !btrfs_test_opt(root, FORCE_COMPRESS))
+                   !btrfs_test_opt(root->fs_info, FORCE_COMPRESS))
                        cur_end = end;
                else
                        cur_end = min(end, start + SZ_512K - 1);
@@@ -1418,7 -1421,8 +1421,8 @@@ out_check
                if (cow_start != (u64)-1) {
                        ret = cow_file_range(inode, locked_page,
                                             cow_start, found_key.offset - 1,
-                                            page_started, nr_written, 1);
+                                            end, page_started, nr_written, 1,
+                                            NULL);
                        if (ret) {
                                if (!nolock && nocow)
                                        btrfs_end_write_no_snapshoting(root);
        }
  
        if (cow_start != (u64)-1) {
-               ret = cow_file_range(inode, locked_page, cow_start, end,
-                                    page_started, nr_written, 1);
+               ret = cow_file_range(inode, locked_page, cow_start, end, end,
+                                    page_started, nr_written, 1, NULL);
                if (ret)
                        goto error;
        }
@@@ -1561,8 -1565,8 +1565,8 @@@ static int run_delalloc_range(struct in
                ret = run_delalloc_nocow(inode, locked_page, start, end,
                                         page_started, 0, nr_written);
        } else if (!inode_need_compress(inode)) {
-               ret = cow_file_range(inode, locked_page, start, end,
-                                     page_started, nr_written, 1);
+               ret = cow_file_range(inode, locked_page, start, end, end,
+                                     page_started, nr_written, 1, NULL);
        } else {
                set_bit(BTRFS_INODE_HAS_ASYNC_EXTENT,
                        &BTRFS_I(inode)->runtime_flags);
@@@ -1740,7 -1744,7 +1744,7 @@@ static void btrfs_set_bit_hook(struct i
                }
  
                /* For sanity tests */
-               if (btrfs_test_is_dummy_root(root))
+               if (btrfs_is_testing(root->fs_info))
                        return;
  
                __percpu_counter_add(&root->fs_info->delalloc_bytes, len,
@@@ -1799,7 -1803,7 +1803,7 @@@ static void btrfs_clear_bit_hook(struc
                        btrfs_delalloc_release_metadata(inode, len);
  
                /* For sanity tests. */
-               if (btrfs_test_is_dummy_root(root))
+               if (btrfs_is_testing(root->fs_info))
                        return;
  
                if (root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID
  /*
   * extent_io.c merge_bio_hook, this must check the chunk tree to make sure
   * we don't create bios that span stripes or chunks
+  *
+  * return 1 if page cannot be merged to bio
+  * return 0 if page can be merged to bio
+  * return error otherwise
   */
 -int btrfs_merge_bio_hook(int rw, struct page *page, unsigned long offset,
 +int btrfs_merge_bio_hook(struct page *page, unsigned long offset,
                         size_t size, struct bio *bio,
                         unsigned long bio_flags)
  {
  
        length = bio->bi_iter.bi_size;
        map_length = length;
 -      ret = btrfs_map_block(root->fs_info, rw, logical,
 +      ret = btrfs_map_block(root->fs_info, bio_op(bio), logical,
                              &map_length, NULL, 0);
-       /* Will always return 0 with map_multi == NULL */
-       BUG_ON(ret < 0);
+       if (ret < 0)
+               return ret;
        if (map_length < length + size)
                return 1;
        return 0;
   * At IO completion time the cums attached on the ordered extent record
   * are inserted into the btree
   */
 -static int __btrfs_submit_bio_start(struct inode *inode, int rw,
 -                                  struct bio *bio, int mirror_num,
 -                                  unsigned long bio_flags,
 +static int __btrfs_submit_bio_start(struct inode *inode, struct bio *bio,
 +                                  int mirror_num, unsigned long bio_flags,
                                    u64 bio_offset)
  {
        struct btrfs_root *root = BTRFS_I(inode)->root;
   * At IO completion time the cums attached on the ordered extent record
   * are inserted into the btree
   */
 -static int __btrfs_submit_bio_done(struct inode *inode, int rw, struct bio *bio,
 +static int __btrfs_submit_bio_done(struct inode *inode, struct bio *bio,
                          int mirror_num, unsigned long bio_flags,
                          u64 bio_offset)
  {
        struct btrfs_root *root = BTRFS_I(inode)->root;
        int ret;
  
 -      ret = btrfs_map_bio(root, rw, bio, mirror_num, 1);
 +      ret = btrfs_map_bio(root, bio, mirror_num, 1);
        if (ret) {
                bio->bi_error = ret;
                bio_endio(bio);
   * extent_io.c submission hook. This does the right thing for csum calculation
   * on write, or reading the csums from the tree before a read
   */
 -static int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio,
 +static int btrfs_submit_bio_hook(struct inode *inode, struct bio *bio,
                          int mirror_num, unsigned long bio_flags,
                          u64 bio_offset)
  {
        if (btrfs_is_free_space_inode(inode))
                metadata = BTRFS_WQ_ENDIO_FREE_SPACE;
  
 -      if (!(rw & REQ_WRITE)) {
 +      if (bio_op(bio) != REQ_OP_WRITE) {
                ret = btrfs_bio_wq_end_io(root->fs_info, bio, metadata);
                if (ret)
                        goto out;
                        goto mapit;
                /* we're doing a write, do the async checksumming */
                ret = btrfs_wq_submit_bio(BTRFS_I(inode)->root->fs_info,
 -                                 inode, rw, bio, mirror_num,
 +                                 inode, bio, mirror_num,
                                   bio_flags, bio_offset,
                                   __btrfs_submit_bio_start,
                                   __btrfs_submit_bio_done);
        }
  
  mapit:
 -      ret = btrfs_map_bio(root, rw, bio, mirror_num, 0);
 +      ret = btrfs_map_bio(root, bio, mirror_num, 0);
  
  out:
        if (ret < 0) {
@@@ -2594,7 -2603,7 +2602,7 @@@ again
        ret = btrfs_insert_empty_item(trans, root, path, &key,
                                        sizeof(*extent));
        if (ret) {
-               btrfs_abort_transaction(trans, root, ret);
+               btrfs_abort_transaction(trans, ret);
                goto out_free_path;
        }
  
                        backref->root_id, backref->inum,
                        new->file_pos); /* start - extent_offset */
        if (ret) {
-               btrfs_abort_transaction(trans, root, ret);
+               btrfs_abort_transaction(trans, ret);
                goto out_free_path;
        }
  
@@@ -2890,7 -2899,7 +2898,7 @@@ static int btrfs_finish_ordered_io(stru
                trans->block_rsv = &root->fs_info->delalloc_block_rsv;
                ret = btrfs_update_inode_fallback(trans, root, inode);
                if (ret) /* -ENOMEM or corruption */
-                       btrfs_abort_transaction(trans, root, ret);
+                       btrfs_abort_transaction(trans, ret);
                goto out;
        }
  
                           ordered_extent->file_offset, ordered_extent->len,
                           trans->transid);
        if (ret < 0) {
-               btrfs_abort_transaction(trans, root, ret);
+               btrfs_abort_transaction(trans, ret);
                goto out_unlock;
        }
  
        btrfs_ordered_update_i_size(inode, 0, ordered_extent);
        ret = btrfs_update_inode_fallback(trans, root, inode);
        if (ret) { /* -ENOMEM or corruption */
-               btrfs_abort_transaction(trans, root, ret);
+               btrfs_abort_transaction(trans, ret);
                goto out_unlock;
        }
        ret = 0;
@@@ -3204,7 -3213,7 +3212,7 @@@ void btrfs_orphan_commit_root(struct bt
                ret = btrfs_del_orphan_item(trans, root->fs_info->tree_root,
                                            root->root_key.objectid);
                if (ret)
-                       btrfs_abort_transaction(trans, root, ret);
+                       btrfs_abort_transaction(trans, ret);
                else
                        clear_bit(BTRFS_ROOT_ORPHAN_ITEM_INSERTED,
                                  &root->state);
@@@ -3295,7 -3304,7 +3303,7 @@@ int btrfs_orphan_add(struct btrfs_trans
                        if (ret != -EEXIST) {
                                clear_bit(BTRFS_INODE_HAS_ORPHAN_ITEM,
                                          &BTRFS_I(inode)->runtime_flags);
-                               btrfs_abort_transaction(trans, root, ret);
+                               btrfs_abort_transaction(trans, ret);
                                return ret;
                        }
                }
                ret = btrfs_insert_orphan_item(trans, root->fs_info->tree_root,
                                               root->root_key.objectid);
                if (ret && ret != -EEXIST) {
-                       btrfs_abort_transaction(trans, root, ret);
+                       btrfs_abort_transaction(trans, ret);
                        return ret;
                }
        }
@@@ -4006,20 -4015,20 +4014,20 @@@ static int __btrfs_unlink_inode(struct 
                btrfs_info(root->fs_info,
                        "failed to delete reference to %.*s, inode %llu parent %llu",
                        name_len, name, ino, dir_ino);
-               btrfs_abort_transaction(trans, root, ret);
+               btrfs_abort_transaction(trans, ret);
                goto err;
        }
  skip_backref:
        ret = btrfs_delete_delayed_dir_index(trans, root, dir, index);
        if (ret) {
-               btrfs_abort_transaction(trans, root, ret);
+               btrfs_abort_transaction(trans, ret);
                goto err;
        }
  
        ret = btrfs_del_inode_ref_in_log(trans, root, name, name_len,
                                         inode, dir_ino);
        if (ret != 0 && ret != -ENOENT) {
-               btrfs_abort_transaction(trans, root, ret);
+               btrfs_abort_transaction(trans, ret);
                goto err;
        }
  
        if (ret == -ENOENT)
                ret = 0;
        else if (ret)
-               btrfs_abort_transaction(trans, root, ret);
+               btrfs_abort_transaction(trans, ret);
  err:
        btrfs_free_path(path);
        if (ret)
@@@ -4142,7 -4151,7 +4150,7 @@@ int btrfs_unlink_subvol(struct btrfs_tr
        WARN_ON(key.type != BTRFS_ROOT_ITEM_KEY || key.objectid != objectid);
        ret = btrfs_delete_one_dir_name(trans, root, path, di);
        if (ret) {
-               btrfs_abort_transaction(trans, root, ret);
+               btrfs_abort_transaction(trans, ret);
                goto out;
        }
        btrfs_release_path(path);
                                 dir_ino, &index, name, name_len);
        if (ret < 0) {
                if (ret != -ENOENT) {
-                       btrfs_abort_transaction(trans, root, ret);
+                       btrfs_abort_transaction(trans, ret);
                        goto out;
                }
                di = btrfs_search_dir_index_item(root, path, dir_ino,
                                ret = -ENOENT;
                        else
                                ret = PTR_ERR(di);
-                       btrfs_abort_transaction(trans, root, ret);
+                       btrfs_abort_transaction(trans, ret);
                        goto out;
                }
  
  
        ret = btrfs_delete_delayed_dir_index(trans, root, dir, index);
        if (ret) {
-               btrfs_abort_transaction(trans, root, ret);
+               btrfs_abort_transaction(trans, ret);
                goto out;
        }
  
        dir->i_mtime = dir->i_ctime = current_fs_time(dir->i_sb);
        ret = btrfs_update_inode_fallback(trans, root, dir);
        if (ret)
-               btrfs_abort_transaction(trans, root, ret);
+               btrfs_abort_transaction(trans, ret);
  out:
        btrfs_free_path(path);
        return ret;
@@@ -4505,7 -4514,6 +4513,6 @@@ search_again
                                                              pending_del_nr);
                                        if (err) {
                                                btrfs_abort_transaction(trans,
-                                                                       root,
                                                                        err);
                                                goto error;
                                        }
                                                             item_end,
                                                             new_size);
                                if (err) {
-                                       btrfs_abort_transaction(trans,
-                                                               root, err);
+                                       btrfs_abort_transaction(trans, err);
                                        goto error;
                                }
                        } else if (test_bit(BTRFS_ROOT_REF_COWS,
@@@ -4582,8 -4589,7 +4588,7 @@@ delete
                                                pending_del_slot,
                                                pending_del_nr);
                                if (ret) {
-                                       btrfs_abort_transaction(trans,
-                                                               root, ret);
+                                       btrfs_abort_transaction(trans, ret);
                                        goto error;
                                }
                                pending_del_nr = 0;
@@@ -4616,7 -4622,7 +4621,7 @@@ out
                ret = btrfs_del_items(trans, root, path, pending_del_slot,
                                      pending_del_nr);
                if (ret)
-                       btrfs_abort_transaction(trans, root, ret);
+                       btrfs_abort_transaction(trans, ret);
        }
  error:
        if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID)
@@@ -4785,7 -4791,7 +4790,7 @@@ static int maybe_insert_hole(struct btr
  
        ret = btrfs_drop_extents(trans, root, inode, offset, offset + len, 1);
        if (ret) {
-               btrfs_abort_transaction(trans, root, ret);
+               btrfs_abort_transaction(trans, ret);
                btrfs_end_transaction(trans, root);
                return ret;
        }
        ret = btrfs_insert_file_extent(trans, root, btrfs_ino(inode), offset,
                                       0, 0, len, 0, len, 0, 0, 0);
        if (ret)
-               btrfs_abort_transaction(trans, root, ret);
+               btrfs_abort_transaction(trans, ret);
        else
                btrfs_update_inode(trans, root, inode);
        btrfs_end_transaction(trans, root);
@@@ -5020,7 -5026,7 +5025,7 @@@ static int btrfs_setsize(struct inode *
                        i_size_write(inode, BTRFS_I(inode)->disk_i_size);
                        err = btrfs_orphan_del(trans, inode);
                        if (err)
-                               btrfs_abort_transaction(trans, root, err);
+                               btrfs_abort_transaction(trans, err);
                        btrfs_end_transaction(trans, root);
                }
        }
@@@ -5158,11 -5164,18 +5163,18 @@@ void btrfs_evict_inode(struct inode *in
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_block_rsv *rsv, *global_rsv;
        int steal_from_global = 0;
-       u64 min_size = btrfs_calc_trunc_metadata_size(root, 1);
+       u64 min_size;
        int ret;
  
        trace_btrfs_inode_evict(inode);
  
+       if (!root) {
+               kmem_cache_free(btrfs_inode_cachep, BTRFS_I(inode));
+               return;
+       }
+       min_size = btrfs_calc_trunc_metadata_size(root, 1);
        evict_inode_truncate_pages(inode);
  
        if (inode->i_nlink &&
@@@ -6239,9 -6252,9 +6251,9 @@@ static struct inode *btrfs_new_inode(st
        btrfs_inherit_iflags(inode, dir);
  
        if (S_ISREG(mode)) {
-               if (btrfs_test_opt(root, NODATASUM))
+               if (btrfs_test_opt(root->fs_info, NODATASUM))
                        BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM;
-               if (btrfs_test_opt(root, NODATACOW))
+               if (btrfs_test_opt(root->fs_info, NODATACOW))
                        BTRFS_I(inode)->flags |= BTRFS_INODE_NODATACOW |
                                BTRFS_INODE_NODATASUM;
        }
@@@ -6319,7 -6332,7 +6331,7 @@@ int btrfs_add_link(struct btrfs_trans_h
        if (ret == -EEXIST || ret == -EOVERFLOW)
                goto fail_dir_item;
        else if (ret) {
-               btrfs_abort_transaction(trans, root, ret);
+               btrfs_abort_transaction(trans, ret);
                return ret;
        }
  
                current_fs_time(parent_inode->i_sb);
        ret = btrfs_update_inode(trans, root, parent_inode);
        if (ret)
-               btrfs_abort_transaction(trans, root, ret);
+               btrfs_abort_transaction(trans, ret);
        return ret;
  
  fail_dir_item:
  }
  
  static inline int submit_dio_repair_bio(struct inode *inode, struct bio *bio,
 -                                      int rw, int mirror_num)
 +                                      int mirror_num)
  {
        struct btrfs_root *root = BTRFS_I(inode)->root;
        int ret;
  
 -      BUG_ON(rw & REQ_WRITE);
 +      BUG_ON(bio_op(bio) == REQ_OP_WRITE);
  
        bio_get(bio);
  
        if (ret)
                goto err;
  
 -      ret = btrfs_map_bio(root, rw, bio, mirror_num, 0);
 +      ret = btrfs_map_bio(root, bio, mirror_num, 0);
  err:
        bio_put(bio);
        return ret;
@@@ -7854,7 -7867,7 +7866,7 @@@ static int dio_read_error(struct inode 
        int read_mode;
        int ret;
  
 -      BUG_ON(failed_bio->bi_rw & REQ_WRITE);
 +      BUG_ON(bio_op(failed_bio) == REQ_OP_WRITE);
  
        ret = btrfs_get_io_failure_record(inode, start, end, &failrec);
        if (ret)
                free_io_failure(inode, failrec);
                return -EIO;
        }
 +      bio_set_op_attrs(bio, REQ_OP_READ, read_mode);
  
        btrfs_debug(BTRFS_I(inode)->root->fs_info,
                    "Repair DIO Read Error: submitting new dio read[%#x] to this_mirror=%d, in_validation=%d\n",
                    read_mode, failrec->this_mirror, failrec->in_validation);
  
 -      ret = submit_dio_repair_bio(inode, bio, read_mode,
 -                                  failrec->this_mirror);
 +      ret = submit_dio_repair_bio(inode, bio, failrec->this_mirror);
        if (ret) {
                free_io_failure(inode, failrec);
                bio_put(bio);
@@@ -8178,7 -8191,7 +8190,7 @@@ static void btrfs_endio_direct_write(st
        bio_put(bio);
  }
  
 -static int __btrfs_submit_bio_start_direct_io(struct inode *inode, int rw,
 +static int __btrfs_submit_bio_start_direct_io(struct inode *inode,
                                    struct bio *bio, int mirror_num,
                                    unsigned long bio_flags, u64 offset)
  {
@@@ -8196,8 -8209,8 +8208,8 @@@ static void btrfs_end_dio_bio(struct bi
  
        if (err)
                btrfs_warn(BTRFS_I(dip->inode)->root->fs_info,
 -                         "direct IO failed ino %llu rw %lu sector %#Lx len %u err no %d",
 -                         btrfs_ino(dip->inode), bio->bi_rw,
 +                         "direct IO failed ino %llu rw %d,%u sector %#Lx len %u err no %d",
 +                         btrfs_ino(dip->inode), bio_op(bio), bio->bi_rw,
                           (unsigned long long)bio->bi_iter.bi_sector,
                           bio->bi_iter.bi_size, err);
  
@@@ -8271,11 -8284,11 +8283,11 @@@ static inline int btrfs_lookup_and_bind
  }
  
  static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode,
 -                                       int rw, u64 file_offset, int skip_sum,
 +                                       u64 file_offset, int skip_sum,
                                         int async_submit)
  {
        struct btrfs_dio_private *dip = bio->bi_private;
 -      int write = rw & REQ_WRITE;
 +      bool write = bio_op(bio) == REQ_OP_WRITE;
        struct btrfs_root *root = BTRFS_I(inode)->root;
        int ret;
  
  
        if (write && async_submit) {
                ret = btrfs_wq_submit_bio(root->fs_info,
 -                                 inode, rw, bio, 0, 0,
 -                                 file_offset,
 +                                 inode, bio, 0, 0, file_offset,
                                   __btrfs_submit_bio_start_direct_io,
                                   __btrfs_submit_bio_done);
                goto err;
                        goto err;
        }
  map:
 -      ret = btrfs_map_bio(root, rw, bio, 0, async_submit);
 +      ret = btrfs_map_bio(root, bio, 0, async_submit);
  err:
        bio_put(bio);
        return ret;
  }
  
 -static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
 +static int btrfs_submit_direct_hook(struct btrfs_dio_private *dip,
                                    int skip_sum)
  {
        struct inode *inode = dip->inode;
        int i;
  
        map_length = orig_bio->bi_iter.bi_size;
 -      ret = btrfs_map_block(root->fs_info, rw, start_sector << 9,
 -                            &map_length, NULL, 0);
 +      ret = btrfs_map_block(root->fs_info, bio_op(orig_bio),
 +                            start_sector << 9, &map_length, NULL, 0);
        if (ret)
                return -EIO;
  
        if (!bio)
                return -ENOMEM;
  
 +      bio_set_op_attrs(bio, bio_op(orig_bio), orig_bio->bi_rw);
        bio->bi_private = dip;
        bio->bi_end_io = btrfs_end_dio_bio;
        btrfs_io_bio(bio)->logical = file_offset;
@@@ -8381,7 -8394,7 +8393,7 @@@ next_block
                         * before we're done setting it up
                         */
                        atomic_inc(&dip->pending_bios);
 -                      ret = __btrfs_submit_dio_bio(bio, inode, rw,
 +                      ret = __btrfs_submit_dio_bio(bio, inode,
                                                     file_offset, skip_sum,
                                                     async_submit);
                        if (ret) {
                                                  start_sector, GFP_NOFS);
                        if (!bio)
                                goto out_err;
 +                      bio_set_op_attrs(bio, bio_op(orig_bio), orig_bio->bi_rw);
                        bio->bi_private = dip;
                        bio->bi_end_io = btrfs_end_dio_bio;
                        btrfs_io_bio(bio)->logical = file_offset;
  
                        map_length = orig_bio->bi_iter.bi_size;
 -                      ret = btrfs_map_block(root->fs_info, rw,
 +                      ret = btrfs_map_block(root->fs_info, bio_op(orig_bio),
                                              start_sector << 9,
                                              &map_length, NULL, 0);
                        if (ret) {
        }
  
  submit:
 -      ret = __btrfs_submit_dio_bio(bio, inode, rw, file_offset, skip_sum,
 +      ret = __btrfs_submit_dio_bio(bio, inode, file_offset, skip_sum,
                                     async_submit);
        if (!ret)
                return 0;
@@@ -8445,14 -8457,14 +8457,14 @@@ out_err
        return 0;
  }
  
 -static void btrfs_submit_direct(int rw, struct bio *dio_bio,
 -                              struct inode *inode, loff_t file_offset)
 +static void btrfs_submit_direct(struct bio *dio_bio, struct inode *inode,
 +                              loff_t file_offset)
  {
        struct btrfs_dio_private *dip = NULL;
        struct bio *io_bio = NULL;
        struct btrfs_io_bio *btrfs_bio;
        int skip_sum;
 -      int write = rw & REQ_WRITE;
 +      bool write = (bio_op(dio_bio) == REQ_OP_WRITE);
        int ret = 0;
  
        skip_sum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM;
                        dio_data->unsubmitted_oe_range_end;
        }
  
 -      ret = btrfs_submit_direct_hook(rw, dip, skip_sum);
 +      ret = btrfs_submit_direct_hook(dip, skip_sum);
        if (!ret)
                return;
  
@@@ -9385,25 -9397,25 +9397,25 @@@ int btrfs_init_cachep(void
  
        btrfs_trans_handle_cachep = kmem_cache_create("btrfs_trans_handle",
                        sizeof(struct btrfs_trans_handle), 0,
-                       SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
+                       SLAB_TEMPORARY | SLAB_MEM_SPREAD, NULL);
        if (!btrfs_trans_handle_cachep)
                goto fail;
  
        btrfs_transaction_cachep = kmem_cache_create("btrfs_transaction",
                        sizeof(struct btrfs_transaction), 0,
-                       SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
+                       SLAB_TEMPORARY | SLAB_MEM_SPREAD, NULL);
        if (!btrfs_transaction_cachep)
                goto fail;
  
        btrfs_path_cachep = kmem_cache_create("btrfs_path",
                        sizeof(struct btrfs_path), 0,
-                       SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
+                       SLAB_MEM_SPREAD, NULL);
        if (!btrfs_path_cachep)
                goto fail;
  
        btrfs_free_space_cachep = kmem_cache_create("btrfs_free_space",
                        sizeof(struct btrfs_free_space), 0,
-                       SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
+                       SLAB_MEM_SPREAD, NULL);
        if (!btrfs_free_space_cachep)
                goto fail;
  
@@@ -9553,7 -9565,7 +9565,7 @@@ static int btrfs_rename_exchange(struc
                        ret = btrfs_update_inode(trans, root, old_inode);
        }
        if (ret) {
-               btrfs_abort_transaction(trans, root, ret);
+               btrfs_abort_transaction(trans, ret);
                goto out_fail;
        }
  
                        ret = btrfs_update_inode(trans, dest, new_inode);
        }
        if (ret) {
-               btrfs_abort_transaction(trans, root, ret);
+               btrfs_abort_transaction(trans, ret);
                goto out_fail;
        }
  
                             new_dentry->d_name.name,
                             new_dentry->d_name.len, 0, old_idx);
        if (ret) {
-               btrfs_abort_transaction(trans, root, ret);
+               btrfs_abort_transaction(trans, ret);
                goto out_fail;
        }
  
                             old_dentry->d_name.name,
                             old_dentry->d_name.len, 0, new_idx);
        if (ret) {
-               btrfs_abort_transaction(trans, root, ret);
+               btrfs_abort_transaction(trans, ret);
                goto out_fail;
        }
  
@@@ -9828,7 -9840,7 +9840,7 @@@ static int btrfs_rename(struct inode *o
                        ret = btrfs_update_inode(trans, root, old_inode);
        }
        if (ret) {
-               btrfs_abort_transaction(trans, root, ret);
+               btrfs_abort_transaction(trans, ret);
                goto out_fail;
        }
  
                if (!ret && new_inode->i_nlink == 0)
                        ret = btrfs_orphan_add(trans, d_inode(new_dentry));
                if (ret) {
-                       btrfs_abort_transaction(trans, root, ret);
+                       btrfs_abort_transaction(trans, ret);
                        goto out_fail;
                }
        }
                             new_dentry->d_name.name,
                             new_dentry->d_name.len, 0, index);
        if (ret) {
-               btrfs_abort_transaction(trans, root, ret);
+               btrfs_abort_transaction(trans, ret);
                goto out_fail;
        }
  
                                                old_dentry);
  
                if (ret) {
-                       btrfs_abort_transaction(trans, root, ret);
+                       btrfs_abort_transaction(trans, ret);
                        goto out_fail;
                }
        }
@@@ -10307,7 -10319,7 +10319,7 @@@ static int __btrfs_prealloc_file_range(
                if (ret) {
                        btrfs_free_reserved_extent(root, ins.objectid,
                                                   ins.offset, 0);
-                       btrfs_abort_transaction(trans, root, ret);
+                       btrfs_abort_transaction(trans, ret);
                        if (own_trans)
                                btrfs_end_transaction(trans, root);
                        break;
@@@ -10367,7 -10379,7 +10379,7 @@@ next
                ret = btrfs_update_inode(trans, root, inode);
  
                if (ret) {
-                       btrfs_abort_transaction(trans, root, ret);
+                       btrfs_abort_transaction(trans, ret);
                        if (own_trans)
                                btrfs_end_transaction(trans, root);
                        break;
diff --combined fs/btrfs/scrub.c
index e08b6bc676e3faa4d93c211b11a59a90c1a62891,68c8a09ae7e556b92451e5f0bed6582a049585bf..1d195d2b32c6ee62d497539172c15e011c26e467
@@@ -1504,9 -1504,8 +1504,9 @@@ static void scrub_recheck_block(struct 
                                sblock->no_io_error_seen = 0;
                } else {
                        bio->bi_iter.bi_sector = page->physical >> 9;
 +                      bio_set_op_attrs(bio, REQ_OP_READ, 0);
  
 -                      if (btrfsic_submit_bio_wait(READ, bio))
 +                      if (btrfsic_submit_bio_wait(bio))
                                sblock->no_io_error_seen = 0;
                }
  
@@@ -1584,7 -1583,6 +1584,7 @@@ static int scrub_repair_page_from_good_
                        return -EIO;
                bio->bi_bdev = page_bad->dev->bdev;
                bio->bi_iter.bi_sector = page_bad->physical >> 9;
 +              bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
  
                ret = bio_add_page(bio, page_good->page, PAGE_SIZE, 0);
                if (PAGE_SIZE != ret) {
                        return -EIO;
                }
  
 -              if (btrfsic_submit_bio_wait(WRITE, bio)) {
 +              if (btrfsic_submit_bio_wait(bio)) {
                        btrfs_dev_stat_inc_and_print(page_bad->dev,
                                BTRFS_DEV_STAT_WRITE_ERRS);
                        btrfs_dev_replace_stats_inc(
@@@ -1686,7 -1684,6 +1686,7 @@@ again
                bio->bi_end_io = scrub_wr_bio_end_io;
                bio->bi_bdev = sbio->dev->bdev;
                bio->bi_iter.bi_sector = sbio->physical >> 9;
 +              bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
                sbio->err = 0;
        } else if (sbio->physical + sbio->page_count * PAGE_SIZE !=
                   spage->physical_for_dev_replace ||
@@@ -1734,7 -1731,7 +1734,7 @@@ static void scrub_wr_submit(struct scru
         * orders the requests before sending them to the driver which
         * doubled the write performance on spinning disks when measured
         * with Linux 3.5 */
 -      btrfsic_submit_bio(WRITE, sbio->bio);
 +      btrfsic_submit_bio(sbio->bio);
  }
  
  static void scrub_wr_bio_end_io(struct bio *bio)
@@@ -2044,7 -2041,7 +2044,7 @@@ static void scrub_submit(struct scrub_c
        sbio = sctx->bios[sctx->curr];
        sctx->curr = -1;
        scrub_pending_bio_inc(sctx);
 -      btrfsic_submit_bio(READ, sbio->bio);
 +      btrfsic_submit_bio(sbio->bio);
  }
  
  static int scrub_add_page_to_rd_bio(struct scrub_ctx *sctx,
@@@ -2091,7 -2088,6 +2091,7 @@@ again
                bio->bi_end_io = scrub_bio_end_io;
                bio->bi_bdev = sbio->dev->bdev;
                bio->bi_iter.bi_sector = sbio->physical >> 9;
 +              bio_set_op_attrs(bio, REQ_OP_READ, 0);
                sbio->err = 0;
        } else if (sbio->physical + sbio->page_count * PAGE_SIZE !=
                   spage->physical ||
@@@ -3785,27 -3781,27 +3785,27 @@@ static noinline_for_stack int scrub_wor
        if (fs_info->scrub_workers_refcnt == 0) {
                if (is_dev_replace)
                        fs_info->scrub_workers =
-                               btrfs_alloc_workqueue("scrub", flags,
+                               btrfs_alloc_workqueue(fs_info, "scrub", flags,
                                                      1, 4);
                else
                        fs_info->scrub_workers =
-                               btrfs_alloc_workqueue("scrub", flags,
+                               btrfs_alloc_workqueue(fs_info, "scrub", flags,
                                                      max_active, 4);
                if (!fs_info->scrub_workers)
                        goto fail_scrub_workers;
  
                fs_info->scrub_wr_completion_workers =
-                       btrfs_alloc_workqueue("scrubwrc", flags,
+                       btrfs_alloc_workqueue(fs_info, "scrubwrc", flags,
                                              max_active, 2);
                if (!fs_info->scrub_wr_completion_workers)
                        goto fail_scrub_wr_completion_workers;
  
                fs_info->scrub_nocow_workers =
-                       btrfs_alloc_workqueue("scrubnc", flags, 1, 0);
+                       btrfs_alloc_workqueue(fs_info, "scrubnc", flags, 1, 0);
                if (!fs_info->scrub_nocow_workers)
                        goto fail_scrub_nocow_workers;
                fs_info->scrub_parity_workers =
-                       btrfs_alloc_workqueue("scrubparity", flags,
+                       btrfs_alloc_workqueue(fs_info, "scrubparity", flags,
                                              max_active, 2);
                if (!fs_info->scrub_parity_workers)
                        goto fail_scrub_parity_workers;
@@@ -3860,7 -3856,7 +3860,7 @@@ int btrfs_scrub_dev(struct btrfs_fs_inf
  
        if (fs_info->chunk_root->sectorsize != PAGE_SIZE) {
                /* not supported for data w/o checksums */
-               btrfs_err(fs_info,
+               btrfs_err_rl(fs_info,
                           "scrub: size assumption sectorsize != PAGE_SIZE "
                           "(%d != %lu) fails",
                       fs_info->chunk_root->sectorsize, PAGE_SIZE);
@@@ -4440,7 -4436,6 +4440,7 @@@ static int write_page_nocow(struct scru
        bio->bi_iter.bi_size = 0;
        bio->bi_iter.bi_sector = physical_for_dev_replace >> 9;
        bio->bi_bdev = dev->bdev;
 +      bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_SYNC);
        ret = bio_add_page(bio, page, PAGE_SIZE, 0);
        if (ret != PAGE_SIZE) {
  leave_with_eio:
                return -EIO;
        }
  
 -      if (btrfsic_submit_bio_wait(WRITE_SYNC, bio))
 +      if (btrfsic_submit_bio_wait(bio))
                goto leave_with_eio;
  
        bio_put(bio);
diff --combined fs/btrfs/volumes.c
index 0fb4a959012e0db9cff59828d6734d0cdfc761f5,e217035d63df419d29ebeaf4113ee210d67e9c4e..bb0addce755865dbb3fb3726998e2792c90205ed
@@@ -140,7 -140,6 +140,6 @@@ static int btrfs_relocate_sys_chunks(st
  static void __btrfs_reset_dev_stats(struct btrfs_device *dev);
  static void btrfs_dev_stat_print_on_error(struct btrfs_device *dev);
  static void btrfs_dev_stat_print_on_load(struct btrfs_device *device);
- static void btrfs_close_one_device(struct btrfs_device *device);
  
  DEFINE_MUTEX(uuid_mutex);
  static LIST_HEAD(fs_uuids);
@@@ -462,7 -461,7 +461,7 @@@ loop_lock
                        sync_pending = 0;
                }
  
 -              btrfsic_submit_bio(cur->bi_rw, cur);
 +              btrfsic_submit_bio(cur);
                num_run++;
                batch_run++;
  
@@@ -853,6 -852,46 +852,46 @@@ static void free_device(struct rcu_hea
        schedule_work(&device->rcu_work);
  }
  
+ static void btrfs_close_one_device(struct btrfs_device *device)
+ {
+       struct btrfs_fs_devices *fs_devices = device->fs_devices;
+       struct btrfs_device *new_device;
+       struct rcu_string *name;
+       if (device->bdev)
+               fs_devices->open_devices--;
+       if (device->writeable &&
+           device->devid != BTRFS_DEV_REPLACE_DEVID) {
+               list_del_init(&device->dev_alloc_list);
+               fs_devices->rw_devices--;
+       }
+       if (device->missing)
+               fs_devices->missing_devices--;
+       if (device->bdev && device->writeable) {
+               sync_blockdev(device->bdev);
+               invalidate_bdev(device->bdev);
+       }
+       new_device = btrfs_alloc_device(NULL, &device->devid,
+                                       device->uuid);
+       BUG_ON(IS_ERR(new_device)); /* -ENOMEM */
+       /* Safe because we are under uuid_mutex */
+       if (device->name) {
+               name = rcu_string_strdup(device->name->str, GFP_NOFS);
+               BUG_ON(!name); /* -ENOMEM */
+               rcu_assign_pointer(new_device->name, name);
+       }
+       list_replace_rcu(&device->dev_list, &new_device->dev_list);
+       new_device->fs_devices = device->fs_devices;
+       call_rcu(&device->rcu, free_device);
+ }
  static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
  {
        struct btrfs_device *device, *tmp;
@@@ -2399,14 -2438,14 +2438,14 @@@ int btrfs_init_new_device(struct btrfs_
                ret = init_first_rw_device(trans, root, device);
                unlock_chunks(root);
                if (ret) {
-                       btrfs_abort_transaction(trans, root, ret);
+                       btrfs_abort_transaction(trans, ret);
                        goto error_trans;
                }
        }
  
        ret = btrfs_add_device(trans, root, device);
        if (ret) {
-               btrfs_abort_transaction(trans, root, ret);
+               btrfs_abort_transaction(trans, ret);
                goto error_trans;
        }
  
  
                ret = btrfs_finish_sprout(trans, root);
                if (ret) {
-                       btrfs_abort_transaction(trans, root, ret);
+                       btrfs_abort_transaction(trans, ret);
                        goto error_trans;
                }
  
@@@ -2801,7 -2840,7 +2840,7 @@@ int btrfs_remove_chunk(struct btrfs_tra
                                            &dev_extent_len);
                if (ret) {
                        mutex_unlock(&fs_devices->device_list_mutex);
-                       btrfs_abort_transaction(trans, root, ret);
+                       btrfs_abort_transaction(trans, ret);
                        goto out;
                }
  
                        ret = btrfs_update_device(trans, map->stripes[i].dev);
                        if (ret) {
                                mutex_unlock(&fs_devices->device_list_mutex);
-                               btrfs_abort_transaction(trans, root, ret);
+                               btrfs_abort_transaction(trans, ret);
                                goto out;
                        }
                }
  
        ret = btrfs_free_chunk(trans, root, chunk_objectid, chunk_offset);
        if (ret) {
-               btrfs_abort_transaction(trans, root, ret);
+               btrfs_abort_transaction(trans, ret);
                goto out;
        }
  
        if (map->type & BTRFS_BLOCK_GROUP_SYSTEM) {
                ret = btrfs_del_sys_chunk(root, chunk_objectid, chunk_offset);
                if (ret) {
-                       btrfs_abort_transaction(trans, root, ret);
+                       btrfs_abort_transaction(trans, ret);
                        goto out;
                }
        }
  
        ret = btrfs_remove_block_group(trans, extent_root, chunk_offset, em);
        if (ret) {
-               btrfs_abort_transaction(trans, extent_root, ret);
+               btrfs_abort_transaction(trans, ret);
                goto out;
        }
  
@@@ -2902,7 -2941,7 +2941,7 @@@ static int btrfs_relocate_chunk(struct 
         * chunk tree entries
         */
        ret = btrfs_remove_chunk(trans, root, chunk_offset);
-       btrfs_end_transaction(trans, root);
+       btrfs_end_transaction(trans, extent_root);
        return ret;
  }
  
@@@ -3421,7 -3460,7 +3460,7 @@@ static int __btrfs_balance(struct btrfs
        u64 size_to_free;
        u64 chunk_type;
        struct btrfs_chunk *chunk;
-       struct btrfs_path *path;
+       struct btrfs_path *path = NULL;
        struct btrfs_key key;
        struct btrfs_key found_key;
        struct btrfs_trans_handle *trans;
                ret = btrfs_shrink_device(device, old_size - size_to_free);
                if (ret == -ENOSPC)
                        break;
-               BUG_ON(ret);
+               if (ret) {
+                       /* btrfs_shrink_device never returns ret > 0 */
+                       WARN_ON(ret > 0);
+                       goto error;
+               }
  
                trans = btrfs_start_transaction(dev_root, 0);
-               BUG_ON(IS_ERR(trans));
+               if (IS_ERR(trans)) {
+                       ret = PTR_ERR(trans);
+                       btrfs_info_in_rcu(fs_info,
+                "resize: unable to start transaction after shrinking device %s (error %d), old size %llu, new size %llu",
+                                         rcu_str_deref(device->name), ret,
+                                         old_size, old_size - size_to_free);
+                       goto error;
+               }
  
                ret = btrfs_grow_device(trans, device, old_size);
-               BUG_ON(ret);
+               if (ret) {
+                       btrfs_end_transaction(trans, dev_root);
+                       /* btrfs_grow_device never returns ret > 0 */
+                       WARN_ON(ret > 0);
+                       btrfs_info_in_rcu(fs_info,
+                "resize: unable to grow device after shrinking device %s (error %d), old size %llu, new size %llu",
+                                         rcu_str_deref(device->name), ret,
+                                         old_size, old_size - size_to_free);
+                       goto error;
+               }
  
                btrfs_end_transaction(trans, dev_root);
        }
@@@ -3885,7 -3944,7 +3944,7 @@@ int btrfs_resume_balance_async(struct b
        }
        spin_unlock(&fs_info->balance_lock);
  
-       if (btrfs_test_opt(fs_info->tree_root, SKIP_BALANCE)) {
+       if (btrfs_test_opt(fs_info, SKIP_BALANCE)) {
                btrfs_info(fs_info, "force skipping balance");
                return 0;
        }
@@@ -4240,7 -4299,7 +4299,7 @@@ int btrfs_create_uuid_tree(struct btrfs
                                      BTRFS_UUID_TREE_OBJECTID);
        if (IS_ERR(uuid_root)) {
                ret = PTR_ERR(uuid_root);
-               btrfs_abort_transaction(trans, tree_root, ret);
+               btrfs_abort_transaction(trans, ret);
                btrfs_end_transaction(trans, tree_root);
                return ret;
        }
@@@ -4514,8 -4573,7 +4573,7 @@@ static void check_raid56_incompat_flag(
        btrfs_set_fs_incompat(info, RAID56);
  }
  
- #define BTRFS_MAX_DEVS(r) ((BTRFS_LEAF_DATA_SIZE(r)           \
-                       - sizeof(struct btrfs_item)             \
+ #define BTRFS_MAX_DEVS(r) ((BTRFS_MAX_ITEM_SIZE(r)            \
                        - sizeof(struct btrfs_chunk))           \
                        / sizeof(struct btrfs_stripe) + 1)
  
@@@ -5260,7 -5318,7 +5318,7 @@@ void btrfs_put_bbio(struct btrfs_bio *b
                kfree(bbio);
  }
  
 -static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
 +static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int op,
                             u64 logical, u64 *length,
                             struct btrfs_bio **bbio_ret,
                             int mirror_num, int need_raid_map)
                raid56_full_stripe_start *= full_stripe_len;
        }
  
 -      if (rw & REQ_DISCARD) {
 +      if (op == REQ_OP_DISCARD) {
                /* we don't discard raid56 yet */
                if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK) {
                        ret = -EOPNOTSUPP;
                   For other RAID types and for RAID[56] reads, just allow a single
                   stripe (on a single disk). */
                if ((map->type & BTRFS_BLOCK_GROUP_RAID56_MASK) &&
 -                  (rw & REQ_WRITE)) {
 +                  (op == REQ_OP_WRITE)) {
                        max_len = stripe_len * nr_data_stripes(map) -
                                (offset - raid56_full_stripe_start);
                } else {
                btrfs_dev_replace_set_lock_blocking(dev_replace);
  
        if (dev_replace_is_ongoing && mirror_num == map->num_stripes + 1 &&
 -          !(rw & (REQ_WRITE | REQ_DISCARD | REQ_GET_READ_MIRRORS)) &&
 -          dev_replace->tgtdev != NULL) {
 +          op != REQ_OP_WRITE && op != REQ_OP_DISCARD &&
 +          op != REQ_GET_READ_MIRRORS && dev_replace->tgtdev != NULL) {
                /*
                 * in dev-replace case, for repair case (that's the only
                 * case where the mirror is selected explicitly when
                            (offset + *length);
  
        if (map->type & BTRFS_BLOCK_GROUP_RAID0) {
 -              if (rw & REQ_DISCARD)
 +              if (op == REQ_OP_DISCARD)
                        num_stripes = min_t(u64, map->num_stripes,
                                            stripe_nr_end - stripe_nr_orig);
                stripe_nr = div_u64_rem(stripe_nr, map->num_stripes,
                                &stripe_index);
 -              if (!(rw & (REQ_WRITE | REQ_DISCARD | REQ_GET_READ_MIRRORS)))
 +              if (op != REQ_OP_WRITE && op != REQ_OP_DISCARD &&
 +                  op != REQ_GET_READ_MIRRORS)
                        mirror_num = 1;
        } else if (map->type & BTRFS_BLOCK_GROUP_RAID1) {
 -              if (rw & (REQ_WRITE | REQ_DISCARD | REQ_GET_READ_MIRRORS))
 +              if (op == REQ_OP_WRITE || op == REQ_OP_DISCARD ||
 +                  op == REQ_GET_READ_MIRRORS)
                        num_stripes = map->num_stripes;
                else if (mirror_num)
                        stripe_index = mirror_num - 1;
                }
  
        } else if (map->type & BTRFS_BLOCK_GROUP_DUP) {
 -              if (rw & (REQ_WRITE | REQ_DISCARD | REQ_GET_READ_MIRRORS)) {
 +              if (op == REQ_OP_WRITE || op == REQ_OP_DISCARD ||
 +                  op == REQ_GET_READ_MIRRORS) {
                        num_stripes = map->num_stripes;
                } else if (mirror_num) {
                        stripe_index = mirror_num - 1;
                stripe_nr = div_u64_rem(stripe_nr, factor, &stripe_index);
                stripe_index *= map->sub_stripes;
  
 -              if (rw & (REQ_WRITE | REQ_GET_READ_MIRRORS))
 +              if (op == REQ_OP_WRITE || op == REQ_GET_READ_MIRRORS)
                        num_stripes = map->sub_stripes;
 -              else if (rw & REQ_DISCARD)
 +              else if (op == REQ_OP_DISCARD)
                        num_stripes = min_t(u64, map->sub_stripes *
                                            (stripe_nr_end - stripe_nr_orig),
                                            map->num_stripes);
  
        } else if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK) {
                if (need_raid_map &&
 -                  ((rw & (REQ_WRITE | REQ_GET_READ_MIRRORS)) ||
 +                  (op == REQ_OP_WRITE || op == REQ_GET_READ_MIRRORS ||
                     mirror_num > 1)) {
                        /* push stripe_nr back to the start of the full stripe */
                        stripe_nr = div_u64(raid56_full_stripe_start,
                        /* We distribute the parity blocks across stripes */
                        div_u64_rem(stripe_nr + stripe_index, map->num_stripes,
                                        &stripe_index);
 -                      if (!(rw & (REQ_WRITE | REQ_DISCARD |
 -                                  REQ_GET_READ_MIRRORS)) && mirror_num <= 1)
 +                      if ((op != REQ_OP_WRITE && op != REQ_OP_DISCARD &&
 +                          op != REQ_GET_READ_MIRRORS) && mirror_num <= 1)
                                mirror_num = 1;
                }
        } else {
  
        num_alloc_stripes = num_stripes;
        if (dev_replace_is_ongoing) {
 -              if (rw & (REQ_WRITE | REQ_DISCARD))
 +              if (op == REQ_OP_WRITE || op == REQ_OP_DISCARD)
                        num_alloc_stripes <<= 1;
 -              if (rw & REQ_GET_READ_MIRRORS)
 +              if (op == REQ_GET_READ_MIRRORS)
                        num_alloc_stripes++;
                tgtdev_indexes = num_stripes;
        }
  
        /* build raid_map */
        if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK &&
 -          need_raid_map && ((rw & (REQ_WRITE | REQ_GET_READ_MIRRORS)) ||
 +          need_raid_map &&
 +          ((op == REQ_OP_WRITE || op == REQ_GET_READ_MIRRORS) ||
            mirror_num > 1)) {
                u64 tmp;
                unsigned rot;
                                RAID6_Q_STRIPE;
        }
  
 -      if (rw & REQ_DISCARD) {
 +      if (op == REQ_OP_DISCARD) {
                u32 factor = 0;
                u32 sub_stripes = 0;
                u64 stripes_per_dev = 0;
                }
        }
  
 -      if (rw & (REQ_WRITE | REQ_GET_READ_MIRRORS))
 +      if (op == REQ_OP_WRITE || op == REQ_GET_READ_MIRRORS)
                max_errors = btrfs_chunk_max_errors(map);
  
        if (bbio->raid_map)
                sort_parity_stripes(bbio, num_stripes);
  
        tgtdev_indexes = 0;
 -      if (dev_replace_is_ongoing && (rw & (REQ_WRITE | REQ_DISCARD)) &&
 +      if (dev_replace_is_ongoing &&
 +         (op == REQ_OP_WRITE || op == REQ_OP_DISCARD) &&
            dev_replace->tgtdev != NULL) {
                int index_where_to_add;
                u64 srcdev_devid = dev_replace->srcdev->devid;
                        }
                }
                num_stripes = index_where_to_add;
 -      } else if (dev_replace_is_ongoing && (rw & REQ_GET_READ_MIRRORS) &&
 +      } else if (dev_replace_is_ongoing && (op == REQ_GET_READ_MIRRORS) &&
                   dev_replace->tgtdev != NULL) {
                u64 srcdev_devid = dev_replace->srcdev->devid;
                int index_srcdev = 0;
        return ret;
  }
  
 -int btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
 +int btrfs_map_block(struct btrfs_fs_info *fs_info, int op,
                      u64 logical, u64 *length,
                      struct btrfs_bio **bbio_ret, int mirror_num)
  {
 -      return __btrfs_map_block(fs_info, rw, logical, length, bbio_ret,
 +      return __btrfs_map_block(fs_info, op, logical, length, bbio_ret,
                                 mirror_num, 0);
  }
  
  /* For Scrub/replace */
 -int btrfs_map_sblock(struct btrfs_fs_info *fs_info, int rw,
 +int btrfs_map_sblock(struct btrfs_fs_info *fs_info, int op,
                     u64 logical, u64 *length,
                     struct btrfs_bio **bbio_ret, int mirror_num,
                     int need_raid_map)
  {
 -      return __btrfs_map_block(fs_info, rw, logical, length, bbio_ret,
 +      return __btrfs_map_block(fs_info, op, logical, length, bbio_ret,
                                 mirror_num, need_raid_map);
  }
  
@@@ -5948,7 -6001,7 +6006,7 @@@ static void btrfs_end_bio(struct bio *b
                        BUG_ON(stripe_index >= bbio->num_stripes);
                        dev = bbio->stripes[stripe_index].dev;
                        if (dev->bdev) {
 -                              if (bio->bi_rw & WRITE)
 +                              if (bio_op(bio) == REQ_OP_WRITE)
                                        btrfs_dev_stat_inc(dev,
                                                BTRFS_DEV_STAT_WRITE_ERRS);
                                else
   */
  static noinline void btrfs_schedule_bio(struct btrfs_root *root,
                                        struct btrfs_device *device,
 -                                      int rw, struct bio *bio)
 +                                      struct bio *bio)
  {
        int should_queue = 1;
        struct btrfs_pending_bios *pending_bios;
        }
  
        /* don't bother with additional async steps for reads, right now */
 -      if (!(rw & REQ_WRITE)) {
 +      if (bio_op(bio) == REQ_OP_READ) {
                bio_get(bio);
 -              btrfsic_submit_bio(rw, bio);
 +              btrfsic_submit_bio(bio);
                bio_put(bio);
                return;
        }
        atomic_inc(&root->fs_info->nr_async_bios);
        WARN_ON(bio->bi_next);
        bio->bi_next = NULL;
 -      bio->bi_rw |= rw;
  
        spin_lock(&device->io_lock);
        if (bio->bi_rw & REQ_SYNC)
  
  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)
 +                            int async)
  {
        struct btrfs_device *dev = bbio->stripes[dev_nr].dev;
  
  
                rcu_read_lock();
                name = rcu_dereference(dev->name);
 -              pr_debug("btrfs_map_bio: rw %d, sector=%llu, dev=%lu "
 -                       "(%s id %llu), size=%u\n", rw,
 +              pr_debug("btrfs_map_bio: rw %d 0x%x, sector=%llu, dev=%lu "
 +                       "(%s id %llu), size=%u\n", bio_op(bio), bio->bi_rw,
                         (u64)bio->bi_iter.bi_sector, (u_long)dev->bdev->bd_dev,
                         name->str, dev->devid, bio->bi_iter.bi_size);
                rcu_read_unlock();
        btrfs_bio_counter_inc_noblocked(root->fs_info);
  
        if (async)
 -              btrfs_schedule_bio(root, dev, rw, bio);
 +              btrfs_schedule_bio(root, dev, bio);
        else
 -              btrfsic_submit_bio(rw, bio);
 +              btrfsic_submit_bio(bio);
  }
  
  static void bbio_error(struct btrfs_bio *bbio, struct bio *bio, u64 logical)
        }
  }
  
 -int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
 +int btrfs_map_bio(struct btrfs_root *root, struct bio *bio,
                  int mirror_num, int async_submit)
  {
        struct btrfs_device *dev;
        map_length = length;
  
        btrfs_bio_counter_inc_blocked(root->fs_info);
 -      ret = __btrfs_map_block(root->fs_info, rw, logical, &map_length, &bbio,
 -                            mirror_num, 1);
 +      ret = __btrfs_map_block(root->fs_info, bio_op(bio), logical,
 +                              &map_length, &bbio, mirror_num, 1);
        if (ret) {
                btrfs_bio_counter_dec(root->fs_info);
                return ret;
        atomic_set(&bbio->stripes_pending, bbio->num_stripes);
  
        if ((bbio->map_type & BTRFS_BLOCK_GROUP_RAID56_MASK) &&
 -          ((rw & WRITE) || (mirror_num > 1))) {
 +          ((bio_op(bio) == REQ_OP_WRITE) || (mirror_num > 1))) {
                /* In this case, map_length has been set to the length of
                   a single stripe; not the whole write */
 -              if (rw & WRITE) {
 +              if (bio_op(bio) == REQ_OP_WRITE) {
                        ret = raid56_parity_write(root, bio, bbio, map_length);
                } else {
                        ret = raid56_parity_recover(root, bio, bbio, map_length,
  
        for (dev_nr = 0; dev_nr < total_devs; dev_nr++) {
                dev = bbio->stripes[dev_nr].dev;
 -              if (!dev || !dev->bdev || (rw & WRITE && !dev->writeable)) {
 +              if (!dev || !dev->bdev ||
 +                  (bio_op(bio) == REQ_OP_WRITE && !dev->writeable)) {
                        bbio_error(bbio, first_bio, logical);
                        continue;
                }
                        bio = first_bio;
  
                submit_stripe_bio(root, bbio, bio,
 -                                bbio->stripes[dev_nr].physical, dev_nr, rw,
 +                                bbio->stripes[dev_nr].physical, dev_nr,
                                  async_submit);
        }
        btrfs_bio_counter_dec(root->fs_info);
@@@ -6401,7 -6454,8 +6459,8 @@@ static int read_one_chunk(struct btrfs_
                                   BTRFS_UUID_SIZE);
                map->stripes[i].dev = btrfs_find_device(root->fs_info, devid,
                                                        uuid, NULL);
-               if (!map->stripes[i].dev && !btrfs_test_opt(root, DEGRADED)) {
+               if (!map->stripes[i].dev &&
+                   !btrfs_test_opt(root->fs_info, DEGRADED)) {
                        free_extent_map(em);
                        return -EIO;
                }
@@@ -6469,7 -6523,7 +6528,7 @@@ static struct btrfs_fs_devices *open_se
  
        fs_devices = find_fsid(fsid);
        if (!fs_devices) {
-               if (!btrfs_test_opt(root, DEGRADED))
+               if (!btrfs_test_opt(root->fs_info, DEGRADED))
                        return ERR_PTR(-ENOENT);
  
                fs_devices = alloc_fs_devices(fsid);
@@@ -6531,7 -6585,7 +6590,7 @@@ static int read_one_dev(struct btrfs_ro
  
        device = btrfs_find_device(root->fs_info, devid, dev_uuid, fs_uuid);
        if (!device) {
-               if (!btrfs_test_opt(root, DEGRADED))
+               if (!btrfs_test_opt(root->fs_info, DEGRADED))
                        return -EIO;
  
                device = add_missing_dev(root, fs_devices, devid, dev_uuid);
                btrfs_warn(root->fs_info, "devid %llu uuid %pU missing",
                                devid, dev_uuid);
        } else {
-               if (!device->bdev && !btrfs_test_opt(root, DEGRADED))
+               if (!device->bdev && !btrfs_test_opt(root->fs_info, DEGRADED))
                        return -EIO;
  
                if(!device->bdev && !device->missing) {
@@@ -7143,38 -7197,3 +7202,3 @@@ void btrfs_reset_fs_info_ptr(struct btr
                fs_devices = fs_devices->seed;
        }
  }
- static void btrfs_close_one_device(struct btrfs_device *device)
- {
-       struct btrfs_fs_devices *fs_devices = device->fs_devices;
-       struct btrfs_device *new_device;
-       struct rcu_string *name;
-       if (device->bdev)
-               fs_devices->open_devices--;
-       if (device->writeable &&
-           device->devid != BTRFS_DEV_REPLACE_DEVID) {
-               list_del_init(&device->dev_alloc_list);
-               fs_devices->rw_devices--;
-       }
-       if (device->missing)
-               fs_devices->missing_devices--;
-       new_device = btrfs_alloc_device(NULL, &device->devid,
-                                       device->uuid);
-       BUG_ON(IS_ERR(new_device)); /* -ENOMEM */
-       /* Safe because we are under uuid_mutex */
-       if (device->name) {
-               name = rcu_string_strdup(device->name->str, GFP_NOFS);
-               BUG_ON(!name); /* -ENOMEM */
-               rcu_assign_pointer(new_device->name, name);
-       }
-       list_replace_rcu(&device->dev_list, &new_device->dev_list);
-       new_device->fs_devices = device->fs_devices;
-       call_rcu(&device->rcu, free_device);
- }
This page took 0.087887 seconds and 5 git commands to generate.