Btrfs: fix null pointer dereference when replacing missing device
[sfrench/cifs-2.6.git] / fs / btrfs / extent-tree.c
index 2f4328511ac84e11b8148952b09b25f3b4bb4e9d..c1618ab9fecfb06a50861f26e4d445fe9d63190e 100644 (file)
@@ -2145,7 +2145,14 @@ int btrfs_discard_extent(struct btrfs_fs_info *fs_info, u64 bytenr,
 
                for (i = 0; i < bbio->num_stripes; i++, stripe++) {
                        u64 bytes;
-                       if (!stripe->dev->can_discard)
+                       struct request_queue *req_q;
+
+                       if (!stripe->dev->bdev) {
+                               ASSERT(btrfs_test_opt(fs_info, DEGRADED));
+                               continue;
+                       }
+                       req_q = bdev_get_queue(stripe->dev->bdev);
+                       if (!blk_queue_discard(req_q))
                                continue;
 
                        ret = btrfs_issue_discard(stripe->dev->bdev,
@@ -2894,7 +2901,7 @@ int btrfs_check_space_for_delayed_refs(struct btrfs_trans_handle *trans,
        struct btrfs_block_rsv *global_rsv;
        u64 num_heads = trans->transaction->delayed_refs.num_heads_ready;
        u64 csum_bytes = trans->transaction->delayed_refs.pending_csums;
-       u64 num_dirty_bgs = trans->transaction->num_dirty_bgs;
+       unsigned int num_dirty_bgs = trans->transaction->num_dirty_bgs;
        u64 num_bytes, num_dirty_bgs_bytes;
        int ret = 0;
 
@@ -4945,12 +4952,12 @@ static int may_commit_transaction(struct btrfs_fs_info *fs_info,
                bytes = 0;
        else
                bytes -= delayed_rsv->size;
+       spin_unlock(&delayed_rsv->lock);
+
        if (percpu_counter_compare(&space_info->total_bytes_pinned,
                                   bytes) < 0) {
-               spin_unlock(&delayed_rsv->lock);
                return -ENOSPC;
        }
-       spin_unlock(&delayed_rsv->lock);
 
 commit:
        trans = btrfs_join_transaction(fs_info->extent_root);
@@ -5738,8 +5745,8 @@ int btrfs_block_rsv_refill(struct btrfs_root *root,
  * or return if we already have enough space.  This will also handle the resreve
  * tracepoint for the reserved amount.
  */
-int btrfs_inode_rsv_refill(struct btrfs_inode *inode,
-                          enum btrfs_reserve_flush_enum flush)
+static int btrfs_inode_rsv_refill(struct btrfs_inode *inode,
+                                 enum btrfs_reserve_flush_enum flush)
 {
        struct btrfs_root *root = inode->root;
        struct btrfs_block_rsv *block_rsv = &inode->block_rsv;
@@ -5770,7 +5777,7 @@ int btrfs_inode_rsv_refill(struct btrfs_inode *inode,
  * This is the same as btrfs_block_rsv_release, except that it handles the
  * tracepoint for the reservation.
  */
-void btrfs_inode_rsv_release(struct btrfs_inode *inode)
+static void btrfs_inode_rsv_release(struct btrfs_inode *inode)
 {
        struct btrfs_fs_info *fs_info = inode->root->fs_info;
        struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv;
@@ -9690,7 +9697,7 @@ int btrfs_can_relocate(struct btrfs_fs_info *fs_info, u64 bytenr)
                 * space to fit our block group in.
                 */
                if (device->total_bytes > device->bytes_used + min_free &&
-                   !device->is_tgtdev_for_dev_replace) {
+                   !test_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state)) {
                        ret = find_free_dev_extent(trans, device, min_free,
                                                   &dev_offset, NULL);
                        if (!ret)
@@ -10875,7 +10882,7 @@ static int btrfs_trim_free_extents(struct btrfs_device *device,
        *trimmed = 0;
 
        /* Not writeable = nothing to do. */
-       if (!device->writeable)
+       if (!test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state))
                return 0;
 
        /* No free space = nothing to do. */