Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs...
[cascardo/linux.git] / fs / btrfs / extent-tree.c
index 227e581..b552693 100644 (file)
@@ -3089,7 +3089,7 @@ static u64 get_alloc_profile(struct btrfs_root *root, u64 flags)
        return btrfs_reduce_alloc_profile(root, flags);
 }
 
-static u64 btrfs_get_alloc_profile(struct btrfs_root *root, int data)
+u64 btrfs_get_alloc_profile(struct btrfs_root *root, int data)
 {
        u64 flags;
 
@@ -3161,8 +3161,12 @@ alloc:
                                             bytes + 2 * 1024 * 1024,
                                             alloc_target, 0);
                        btrfs_end_transaction(trans, root);
-                       if (ret < 0)
-                               return ret;
+                       if (ret < 0) {
+                               if (ret != -ENOSPC)
+                                       return ret;
+                               else
+                                       goto commit_trans;
+                       }
 
                        if (!data_sinfo) {
                                btrfs_set_inode_space_info(root, inode);
@@ -3173,6 +3177,7 @@ alloc:
                spin_unlock(&data_sinfo->lock);
 
                /* commit the current transaction and try again */
+commit_trans:
                if (!committed && !root->fs_info->open_ioctl_trans) {
                        committed = 1;
                        trans = btrfs_join_transaction(root, 1);
@@ -3721,11 +3726,6 @@ int btrfs_block_rsv_check(struct btrfs_trans_handle *trans,
                return 0;
        }
 
-       WARN_ON(1);
-       printk(KERN_INFO"block_rsv size %llu reserved %llu freed %llu %llu\n",
-               block_rsv->size, block_rsv->reserved,
-               block_rsv->freed[0], block_rsv->freed[1]);
-
        return -ENOSPC;
 }
 
@@ -7970,13 +7970,14 @@ static int set_block_group_ro(struct btrfs_block_group_cache *cache)
 
        if (sinfo->bytes_used + sinfo->bytes_reserved + sinfo->bytes_pinned +
            sinfo->bytes_may_use + sinfo->bytes_readonly +
-           cache->reserved_pinned + num_bytes < sinfo->total_bytes) {
+           cache->reserved_pinned + num_bytes <= sinfo->total_bytes) {
                sinfo->bytes_readonly += num_bytes;
                sinfo->bytes_reserved += cache->reserved_pinned;
                cache->reserved_pinned = 0;
                cache->ro = 1;
                ret = 0;
        }
+
        spin_unlock(&cache->lock);
        spin_unlock(&sinfo->lock);
        return ret;
@@ -8012,6 +8013,62 @@ out:
        return ret;
 }
 
+/*
+ * helper to account the unused space of all the readonly block group in the
+ * list. takes mirrors into account.
+ */
+static u64 __btrfs_get_ro_block_group_free_space(struct list_head *groups_list)
+{
+       struct btrfs_block_group_cache *block_group;
+       u64 free_bytes = 0;
+       int factor;
+
+       list_for_each_entry(block_group, groups_list, list) {
+               spin_lock(&block_group->lock);
+
+               if (!block_group->ro) {
+                       spin_unlock(&block_group->lock);
+                       continue;
+               }
+
+               if (block_group->flags & (BTRFS_BLOCK_GROUP_RAID1 |
+                                         BTRFS_BLOCK_GROUP_RAID10 |
+                                         BTRFS_BLOCK_GROUP_DUP))
+                       factor = 2;
+               else
+                       factor = 1;
+
+               free_bytes += (block_group->key.offset -
+                              btrfs_block_group_used(&block_group->item)) *
+                              factor;
+
+               spin_unlock(&block_group->lock);
+       }
+
+       return free_bytes;
+}
+
+/*
+ * helper to account the unused space of all the readonly block group in the
+ * space_info. takes mirrors into account.
+ */
+u64 btrfs_account_ro_block_groups_free_space(struct btrfs_space_info *sinfo)
+{
+       int i;
+       u64 free_bytes = 0;
+
+       spin_lock(&sinfo->lock);
+
+       for(i = 0; i < BTRFS_NR_RAID_TYPES; i++)
+               if (!list_empty(&sinfo->block_groups[i]))
+                       free_bytes += __btrfs_get_ro_block_group_free_space(
+                                               &sinfo->block_groups[i]);
+
+       spin_unlock(&sinfo->lock);
+
+       return free_bytes;
+}
+
 int btrfs_set_block_group_rw(struct btrfs_root *root,
                              struct btrfs_block_group_cache *cache)
 {
@@ -8092,7 +8149,7 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
        mutex_lock(&root->fs_info->chunk_mutex);
        list_for_each_entry(device, &fs_devices->alloc_list, dev_alloc_list) {
                u64 min_free = btrfs_block_group_used(&block_group->item);
-               u64 dev_offset, max_avail;
+               u64 dev_offset;
 
                /*
                 * check to make sure we can actually find a chunk with enough
@@ -8100,7 +8157,7 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
                 */
                if (device->total_bytes > device->bytes_used + min_free) {
                        ret = find_free_dev_extent(NULL, device, min_free,
-                                                  &dev_offset, &max_avail);
+                                                  &dev_offset, NULL);
                        if (!ret)
                                break;
                        ret = -1;
@@ -8584,3 +8641,14 @@ out:
        btrfs_free_path(path);
        return ret;
 }
+
+int btrfs_error_unpin_extent_range(struct btrfs_root *root, u64 start, u64 end)
+{
+       return unpin_extent_range(root, start, end);
+}
+
+int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr,
+                              u64 num_bytes)
+{
+       return btrfs_discard_extent(root, bytenr, num_bytes);
+}