]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/btrfs/extent-tree.c
Merge branch 'exynos-drm-fixes' of git://git.infradead.org/users/kmpark/linux-2.6...
[karo-tx-linux.git] / fs / btrfs / extent-tree.c
index 700879ed64cfcc73f43f6e03819e579578db1e57..37e0a800d34e3a867437a9c1b2072e51a7ccc743 100644 (file)
 #include "locking.h"
 #include "free-space-cache.h"
 
-/* control flags for do_chunk_alloc's force field
+/*
+ * control flags for do_chunk_alloc's force field
  * CHUNK_ALLOC_NO_FORCE means to only allocate a chunk
  * if we really need one.
  *
- * CHUNK_ALLOC_FORCE means it must try to allocate one
- *
  * CHUNK_ALLOC_LIMITED means to only try and allocate one
  * if we have very few chunks already allocated.  This is
  * used as part of the clustering code to help make sure
  * we have a good pool of storage to cluster in, without
  * filling the FS with empty chunks
  *
+ * CHUNK_ALLOC_FORCE means it must try to allocate one
+ *
  */
 enum {
        CHUNK_ALLOC_NO_FORCE = 0,
-       CHUNK_ALLOC_FORCE = 1,
-       CHUNK_ALLOC_LIMITED = 2,
+       CHUNK_ALLOC_LIMITED = 1,
+       CHUNK_ALLOC_FORCE = 2,
 };
 
 /*
@@ -3311,7 +3312,8 @@ commit_trans:
        }
        data_sinfo->bytes_may_use += bytes;
        trace_btrfs_space_reservation(root->fs_info, "space_info",
-                                     (u64)data_sinfo, bytes, 1);
+                                     (u64)(unsigned long)data_sinfo,
+                                     bytes, 1);
        spin_unlock(&data_sinfo->lock);
 
        return 0;
@@ -3332,7 +3334,8 @@ void btrfs_free_reserved_data_space(struct inode *inode, u64 bytes)
        spin_lock(&data_sinfo->lock);
        data_sinfo->bytes_may_use -= bytes;
        trace_btrfs_space_reservation(root->fs_info, "space_info",
-                                     (u64)data_sinfo, bytes, 0);
+                                     (u64)(unsigned long)data_sinfo,
+                                     bytes, 0);
        spin_unlock(&data_sinfo->lock);
 }
 
@@ -3414,7 +3417,7 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
 
 again:
        spin_lock(&space_info->lock);
-       if (space_info->force_alloc)
+       if (force < space_info->force_alloc)
                force = space_info->force_alloc;
        if (space_info->full) {
                spin_unlock(&space_info->lock);
@@ -3610,12 +3613,15 @@ static int may_commit_transaction(struct btrfs_root *root,
        if (space_info != delayed_rsv->space_info)
                return -ENOSPC;
 
+       spin_lock(&space_info->lock);
        spin_lock(&delayed_rsv->lock);
-       if (delayed_rsv->size < bytes) {
+       if (space_info->bytes_pinned + delayed_rsv->size < bytes) {
                spin_unlock(&delayed_rsv->lock);
+               spin_unlock(&space_info->lock);
                return -ENOSPC;
        }
        spin_unlock(&delayed_rsv->lock);
+       spin_unlock(&space_info->lock);
 
 commit:
        trans = btrfs_join_transaction(root);
@@ -3694,9 +3700,9 @@ again:
                if (used + orig_bytes <= space_info->total_bytes) {
                        space_info->bytes_may_use += orig_bytes;
                        trace_btrfs_space_reservation(root->fs_info,
-                                                     "space_info",
-                                                     (u64)space_info,
-                                                     orig_bytes, 1);
+                                             "space_info",
+                                             (u64)(unsigned long)space_info,
+                                             orig_bytes, 1);
                        ret = 0;
                } else {
                        /*
@@ -3765,9 +3771,9 @@ again:
                if (used + num_bytes < space_info->total_bytes + avail) {
                        space_info->bytes_may_use += orig_bytes;
                        trace_btrfs_space_reservation(root->fs_info,
-                                                     "space_info",
-                                                     (u64)space_info,
-                                                     orig_bytes, 1);
+                                             "space_info",
+                                             (u64)(unsigned long)space_info,
+                                             orig_bytes, 1);
                        ret = 0;
                } else {
                        wait_ordered = true;
@@ -3912,8 +3918,8 @@ static void block_rsv_release_bytes(struct btrfs_fs_info *fs_info,
                        spin_lock(&space_info->lock);
                        space_info->bytes_may_use -= num_bytes;
                        trace_btrfs_space_reservation(fs_info, "space_info",
-                                                     (u64)space_info,
-                                                     num_bytes, 0);
+                                             (u64)(unsigned long)space_info,
+                                             num_bytes, 0);
                        space_info->reservation_progress++;
                        spin_unlock(&space_info->lock);
                }
@@ -4104,7 +4110,7 @@ static u64 calc_global_metadata_size(struct btrfs_fs_info *fs_info)
        num_bytes += div64_u64(data_used + meta_used, 50);
 
        if (num_bytes * 3 > meta_used)
-               num_bytes = div64_u64(meta_used, 3);
+               num_bytes = div64_u64(meta_used, 3) * 2;
 
        return ALIGN(num_bytes, fs_info->extent_root->leafsize << 10);
 }
@@ -4131,14 +4137,14 @@ static void update_global_block_rsv(struct btrfs_fs_info *fs_info)
                block_rsv->reserved += num_bytes;
                sinfo->bytes_may_use += num_bytes;
                trace_btrfs_space_reservation(fs_info, "space_info",
-                                             (u64)sinfo, num_bytes, 1);
+                                     (u64)(unsigned long)sinfo, num_bytes, 1);
        }
 
        if (block_rsv->reserved >= block_rsv->size) {
                num_bytes = block_rsv->reserved - block_rsv->size;
                sinfo->bytes_may_use -= num_bytes;
                trace_btrfs_space_reservation(fs_info, "space_info",
-                                             (u64)sinfo, num_bytes, 0);
+                                     (u64)(unsigned long)sinfo, num_bytes, 0);
                sinfo->reservation_progress++;
                block_rsv->reserved = block_rsv->size;
                block_rsv->full = 1;
@@ -4191,7 +4197,8 @@ void btrfs_trans_release_metadata(struct btrfs_trans_handle *trans,
        if (!trans->bytes_reserved)
                return;
 
-       trace_btrfs_space_reservation(root->fs_info, "transaction", (u64)trans,
+       trace_btrfs_space_reservation(root->fs_info, "transaction",
+                                     (u64)(unsigned long)trans,
                                      trans->bytes_reserved, 0);
        btrfs_block_rsv_release(root, trans->block_rsv, trans->bytes_reserved);
        trans->bytes_reserved = 0;
@@ -4709,9 +4716,9 @@ static int btrfs_update_reserved_bytes(struct btrfs_block_group_cache *cache,
                        space_info->bytes_reserved += num_bytes;
                        if (reserve == RESERVE_ALLOC) {
                                trace_btrfs_space_reservation(cache->fs_info,
-                                                             "space_info",
-                                                             (u64)space_info,
-                                                             num_bytes, 0);
+                                             "space_info",
+                                             (u64)(unsigned long)space_info,
+                                             num_bytes, 0);
                                space_info->bytes_may_use -= num_bytes;
                        }
                }
@@ -5794,6 +5801,7 @@ int btrfs_reserve_extent(struct btrfs_trans_handle *trans,
                         u64 search_end, struct btrfs_key *ins,
                         u64 data)
 {
+       bool final_tried = false;
        int ret;
        u64 search_start = 0;
 
@@ -5813,22 +5821,25 @@ again:
                               search_start, search_end, hint_byte,
                               ins, data);
 
-       if (ret == -ENOSPC && num_bytes > min_alloc_size) {
-               num_bytes = num_bytes >> 1;
-               num_bytes = num_bytes & ~(root->sectorsize - 1);
-               num_bytes = max(num_bytes, min_alloc_size);
-               do_chunk_alloc(trans, root->fs_info->extent_root,
-                              num_bytes, data, CHUNK_ALLOC_FORCE);
-               goto again;
-       }
-       if (ret == -ENOSPC && btrfs_test_opt(root, ENOSPC_DEBUG)) {
-               struct btrfs_space_info *sinfo;
-
-               sinfo = __find_space_info(root->fs_info, data);
-               printk(KERN_ERR "btrfs allocation failed flags %llu, "
-                      "wanted %llu\n", (unsigned long long)data,
-                      (unsigned long long)num_bytes);
-               dump_space_info(sinfo, num_bytes, 1);
+       if (ret == -ENOSPC) {
+               if (!final_tried) {
+                       num_bytes = num_bytes >> 1;
+                       num_bytes = num_bytes & ~(root->sectorsize - 1);
+                       num_bytes = max(num_bytes, min_alloc_size);
+                       do_chunk_alloc(trans, root->fs_info->extent_root,
+                                      num_bytes, data, CHUNK_ALLOC_FORCE);
+                       if (num_bytes == min_alloc_size)
+                               final_tried = true;
+                       goto again;
+               } else if (btrfs_test_opt(root, ENOSPC_DEBUG)) {
+                       struct btrfs_space_info *sinfo;
+
+                       sinfo = __find_space_info(root->fs_info, data);
+                       printk(KERN_ERR "btrfs allocation failed flags %llu, "
+                              "wanted %llu\n", (unsigned long long)data,
+                              (unsigned long long)num_bytes);
+                       dump_space_info(sinfo, num_bytes, 1);
+               }
        }
 
        trace_btrfs_reserved_extent_alloc(root, ins->objectid, ins->offset);
@@ -7881,9 +7892,16 @@ int btrfs_trim_fs(struct btrfs_root *root, struct fstrim_range *range)
        u64 start;
        u64 end;
        u64 trimmed = 0;
+       u64 total_bytes = btrfs_super_total_bytes(fs_info->super_copy);
        int ret = 0;
 
-       cache = btrfs_lookup_block_group(fs_info, range->start);
+       /*
+        * try to trim all FS space, our block group may start from non-zero.
+        */
+       if (range->len == total_bytes)
+               cache = btrfs_lookup_first_block_group(fs_info, range->start);
+       else
+               cache = btrfs_lookup_block_group(fs_info, range->start);
 
        while (cache) {
                if (cache->key.objectid >= (range->start + range->len)) {