Loading fs/btrfs/backref.c +6 −0 Original line number Diff line number Diff line Loading @@ -362,6 +362,12 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, goto out; } if (btrfs_test_is_dummy_root(root)) { srcu_read_unlock(&fs_info->subvol_srcu, index); ret = -ENOENT; goto out; } if (path->search_commit_root) root_level = btrfs_header_level(root->commit_root); else if (time_seq == (u64)-1) Loading fs/btrfs/ctree.h +21 −0 Original line number Diff line number Diff line Loading @@ -1154,6 +1154,10 @@ struct btrfs_space_info { delalloc/allocations */ u64 bytes_readonly; /* total bytes that are read only */ u64 max_extent_size; /* This will hold the maximum extent size of the space info if we had an ENOSPC in the allocator. */ unsigned int full:1; /* indicates that we cannot allocate any more chunks for this space */ unsigned int chunk_alloc:1; /* set if we are allocating a chunk */ Loading Loading @@ -1228,6 +1232,9 @@ struct btrfs_free_cluster { /* first extent starting offset */ u64 window_start; /* We did a full search and couldn't create a cluster */ bool fragmented; struct btrfs_block_group_cache *block_group; /* * when a cluster is allocated from a block group, we put the Loading Loading @@ -2148,6 +2155,8 @@ struct btrfs_ioctl_defrag_range_args { #define BTRFS_MOUNT_CHECK_INTEGRITY_INCLUDING_EXTENT_DATA (1 << 21) #define BTRFS_MOUNT_PANIC_ON_FATAL_ERROR (1 << 22) #define BTRFS_MOUNT_RESCAN_UUID_TREE (1 << 23) #define BTRFS_MOUNT_FRAGMENT_DATA (1 << 24) #define BTRFS_MOUNT_FRAGMENT_METADATA (1 << 25) #define BTRFS_DEFAULT_COMMIT_INTERVAL (30) #define BTRFS_DEFAULT_MAX_INLINE (8192) Loading @@ -2172,6 +2181,18 @@ struct btrfs_ioctl_defrag_range_args { btrfs_clear_opt(root->fs_info->mount_opt, opt); \ } #ifdef CONFIG_BTRFS_DEBUG static inline int btrfs_should_fragment_free_space(struct btrfs_root *root, struct btrfs_block_group_cache *block_group) { return (btrfs_test_opt(root, FRAGMENT_METADATA) && block_group->flags & BTRFS_BLOCK_GROUP_METADATA) || (btrfs_test_opt(root, FRAGMENT_DATA) && block_group->flags & BTRFS_BLOCK_GROUP_DATA); } #endif /* * Requests for changes that need to be done during transaction commit. * Loading fs/btrfs/disk-io.c +0 −20 Original line number Diff line number Diff line Loading @@ -4327,25 +4327,6 @@ static int btrfs_destroy_pinned_extent(struct btrfs_root *root, return 0; } static void btrfs_free_pending_ordered(struct btrfs_transaction *cur_trans, struct btrfs_fs_info *fs_info) { struct btrfs_ordered_extent *ordered; spin_lock(&fs_info->trans_lock); while (!list_empty(&cur_trans->pending_ordered)) { ordered = list_first_entry(&cur_trans->pending_ordered, struct btrfs_ordered_extent, trans_list); list_del_init(&ordered->trans_list); spin_unlock(&fs_info->trans_lock); btrfs_put_ordered_extent(ordered); spin_lock(&fs_info->trans_lock); } spin_unlock(&fs_info->trans_lock); } void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans, struct btrfs_root *root) { Loading @@ -4357,7 +4338,6 @@ void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans, cur_trans->state = TRANS_STATE_UNBLOCKED; wake_up(&root->fs_info->transaction_wait); btrfs_free_pending_ordered(cur_trans, root->fs_info); btrfs_destroy_delayed_inodes(root); btrfs_assert_delayed_root_empty(root); Loading fs/btrfs/extent-tree.c +240 −32 Original line number Diff line number Diff line Loading @@ -332,6 +332,27 @@ static void put_caching_control(struct btrfs_caching_control *ctl) kfree(ctl); } #ifdef CONFIG_BTRFS_DEBUG static void fragment_free_space(struct btrfs_root *root, struct btrfs_block_group_cache *block_group) { u64 start = block_group->key.objectid; u64 len = block_group->key.offset; u64 chunk = block_group->flags & BTRFS_BLOCK_GROUP_METADATA ? root->nodesize : root->sectorsize; u64 step = chunk << 1; while (len > chunk) { btrfs_remove_free_space(block_group, start, chunk); start += step; if (len < step) len = 0; else len -= step; } } #endif /* * this is only called by cache_block_group, since we could have freed extents * we need to check the pinned_extents for any extents that can't be used yet Loading Loading @@ -388,6 +409,7 @@ static noinline void caching_thread(struct btrfs_work *work) u64 last = 0; u32 nritems; int ret = -ENOMEM; bool wakeup = true; caching_ctl = container_of(work, struct btrfs_caching_control, work); block_group = caching_ctl->block_group; Loading @@ -400,6 +422,15 @@ static noinline void caching_thread(struct btrfs_work *work) last = max_t(u64, block_group->key.objectid, BTRFS_SUPER_INFO_OFFSET); #ifdef CONFIG_BTRFS_DEBUG /* * If we're fragmenting we don't want to make anybody think we can * allocate from this block group until we've had a chance to fragment * the free space. */ if (btrfs_should_fragment_free_space(extent_root, block_group)) wakeup = false; #endif /* * We don't want to deadlock with somebody trying to allocate a new * extent for the extent root while also trying to search the extent Loading Loading @@ -441,6 +472,7 @@ static noinline void caching_thread(struct btrfs_work *work) if (need_resched() || rwsem_is_contended(&fs_info->commit_root_sem)) { if (wakeup) caching_ctl->progress = last; btrfs_release_path(path); up_read(&fs_info->commit_root_sem); Loading @@ -464,6 +496,7 @@ static noinline void caching_thread(struct btrfs_work *work) key.offset = 0; key.type = BTRFS_EXTENT_ITEM_KEY; if (wakeup) caching_ctl->progress = last; btrfs_release_path(path); goto next; Loading Loading @@ -491,6 +524,7 @@ static noinline void caching_thread(struct btrfs_work *work) if (total_found > (1024 * 1024 * 2)) { total_found = 0; if (wakeup) wake_up(&caching_ctl->wait); } } Loading @@ -501,13 +535,27 @@ static noinline void caching_thread(struct btrfs_work *work) total_found += add_new_free_space(block_group, fs_info, last, block_group->key.objectid + block_group->key.offset); caching_ctl->progress = (u64)-1; spin_lock(&block_group->lock); block_group->caching_ctl = NULL; block_group->cached = BTRFS_CACHE_FINISHED; spin_unlock(&block_group->lock); #ifdef CONFIG_BTRFS_DEBUG if (btrfs_should_fragment_free_space(extent_root, block_group)) { u64 bytes_used; spin_lock(&block_group->space_info->lock); spin_lock(&block_group->lock); bytes_used = block_group->key.offset - btrfs_block_group_used(&block_group->item); block_group->space_info->bytes_used += bytes_used >> 1; spin_unlock(&block_group->lock); spin_unlock(&block_group->space_info->lock); fragment_free_space(extent_root, block_group); } #endif caching_ctl->progress = (u64)-1; err: btrfs_free_path(path); up_read(&fs_info->commit_root_sem); Loading Loading @@ -607,6 +655,22 @@ static int cache_block_group(struct btrfs_block_group_cache *cache, } } spin_unlock(&cache->lock); #ifdef CONFIG_BTRFS_DEBUG if (ret == 1 && btrfs_should_fragment_free_space(fs_info->extent_root, cache)) { u64 bytes_used; spin_lock(&cache->space_info->lock); spin_lock(&cache->lock); bytes_used = cache->key.offset - btrfs_block_group_used(&cache->item); cache->space_info->bytes_used += bytes_used >> 1; spin_unlock(&cache->lock); spin_unlock(&cache->space_info->lock); fragment_free_space(fs_info->extent_root, cache); } #endif mutex_unlock(&caching_ctl->mutex); wake_up(&caching_ctl->wait); Loading Loading @@ -3343,6 +3407,15 @@ static int cache_save_setup(struct btrfs_block_group_cache *block_group, } spin_unlock(&block_group->lock); /* * We hit an ENOSPC when setting up the cache in this transaction, just * skip doing the setup, we've already cleared the cache so we're safe. */ if (test_bit(BTRFS_TRANS_CACHE_ENOSPC, &trans->transaction->flags)) { ret = -ENOSPC; goto out_put; } /* * Try to preallocate enough space based on how big the block group is. * Keep in mind this has to include any pinned space which could end up Loading @@ -3363,8 +3436,18 @@ static int cache_save_setup(struct btrfs_block_group_cache *block_group, ret = btrfs_prealloc_file_range_trans(inode, trans, 0, 0, num_pages, num_pages, num_pages, &alloc_hint); /* * Our cache requires contiguous chunks so that we don't modify a bunch * of metadata or split extents when writing the cache out, which means * we can enospc if we are heavily fragmented in addition to just normal * out of space conditions. So if we hit this just skip setting up any * other block groups for this transaction, maybe we'll unpin enough * space the next time around. */ if (!ret) dcs = BTRFS_DC_SETUP; else if (ret == -ENOSPC) set_bit(BTRFS_TRANS_CACHE_ENOSPC, &trans->transaction->flags); btrfs_free_reserved_data_space(inode, 0, num_pages); out_put: Loading Loading @@ -3751,6 +3834,7 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags, found->bytes_readonly = 0; found->bytes_may_use = 0; found->full = 0; found->max_extent_size = 0; found->force_alloc = CHUNK_ALLOC_NO_FORCE; found->chunk_alloc = 0; found->flush = 0; Loading Loading @@ -4003,7 +4087,8 @@ int btrfs_alloc_data_chunk_ondemand(struct inode *inode, u64 bytes) if (IS_ERR(trans)) return PTR_ERR(trans); if (have_pinned_space >= 0 || trans->transaction->have_free_bgs || test_bit(BTRFS_TRANS_HAVE_FREE_BGS, &trans->transaction->flags) || need_commit > 0) { ret = btrfs_commit_transaction(trans, root); if (ret) Loading Loading @@ -6112,6 +6197,34 @@ void btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans, update_global_block_rsv(fs_info); } /* * Returns the free cluster for the given space info and sets empty_cluster to * what it should be based on the mount options. */ static struct btrfs_free_cluster * fetch_cluster_info(struct btrfs_root *root, struct btrfs_space_info *space_info, u64 *empty_cluster) { struct btrfs_free_cluster *ret = NULL; bool ssd = btrfs_test_opt(root, SSD); *empty_cluster = 0; if (btrfs_mixed_space_info(space_info)) return ret; if (ssd) *empty_cluster = 2 * 1024 * 1024; if (space_info->flags & BTRFS_BLOCK_GROUP_METADATA) { ret = &root->fs_info->meta_alloc_cluster; if (!ssd) *empty_cluster = 64 * 1024; } else if ((space_info->flags & BTRFS_BLOCK_GROUP_DATA) && ssd) { ret = &root->fs_info->data_alloc_cluster; } return ret; } static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end, const bool return_free_space) { Loading @@ -6119,7 +6232,10 @@ static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end, struct btrfs_block_group_cache *cache = NULL; struct btrfs_space_info *space_info; struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; struct btrfs_free_cluster *cluster = NULL; u64 len; u64 total_unpinned = 0; u64 empty_cluster = 0; bool readonly; while (start <= end) { Loading @@ -6128,8 +6244,14 @@ static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end, start >= cache->key.objectid + cache->key.offset) { if (cache) btrfs_put_block_group(cache); total_unpinned = 0; cache = btrfs_lookup_block_group(fs_info, start); BUG_ON(!cache); /* Logic error */ cluster = fetch_cluster_info(root, cache->space_info, &empty_cluster); empty_cluster <<= 1; } len = cache->key.objectid + cache->key.offset - start; Loading @@ -6142,12 +6264,27 @@ static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end, } start += len; total_unpinned += len; space_info = cache->space_info; /* * If this space cluster has been marked as fragmented and we've * unpinned enough in this block group to potentially allow a * cluster to be created inside of it go ahead and clear the * fragmented check. */ if (cluster && cluster->fragmented && total_unpinned > empty_cluster) { spin_lock(&cluster->lock); cluster->fragmented = 0; spin_unlock(&cluster->lock); } spin_lock(&space_info->lock); spin_lock(&cache->lock); cache->pinned -= len; space_info->bytes_pinned -= len; space_info->max_extent_size = 0; percpu_counter_add(&space_info->total_bytes_pinned, -len); if (cache->ro) { space_info->bytes_readonly += len; Loading Loading @@ -6880,7 +7017,7 @@ static noinline int find_free_extent(struct btrfs_root *orig_root, struct btrfs_block_group_cache *block_group = NULL; u64 search_start = 0; u64 max_extent_size = 0; int empty_cluster = 2 * 1024 * 1024; u64 empty_cluster = 0; struct btrfs_space_info *space_info; int loop = 0; int index = __get_raid_index(flags); Loading @@ -6890,6 +7027,7 @@ static noinline int find_free_extent(struct btrfs_root *orig_root, bool failed_alloc = false; bool use_cluster = true; bool have_caching_bg = false; bool full_search = false; WARN_ON(num_bytes < root->sectorsize); ins->type = BTRFS_EXTENT_ITEM_KEY; Loading @@ -6905,36 +7043,47 @@ static noinline int find_free_extent(struct btrfs_root *orig_root, } /* * If the space info is for both data and metadata it means we have a * small filesystem and we can't use the clustering stuff. * If our free space is heavily fragmented we may not be able to make * big contiguous allocations, so instead of doing the expensive search * for free space, simply return ENOSPC with our max_extent_size so we * can go ahead and search for a more manageable chunk. * * If our max_extent_size is large enough for our allocation simply * disable clustering since we will likely not be able to find enough * space to create a cluster and induce latency trying. */ if (btrfs_mixed_space_info(space_info)) if (unlikely(space_info->max_extent_size)) { spin_lock(&space_info->lock); if (space_info->max_extent_size && num_bytes > space_info->max_extent_size) { ins->offset = space_info->max_extent_size; spin_unlock(&space_info->lock); return -ENOSPC; } else if (space_info->max_extent_size) { use_cluster = false; if (flags & BTRFS_BLOCK_GROUP_METADATA && use_cluster) { last_ptr = &root->fs_info->meta_alloc_cluster; if (!btrfs_test_opt(root, SSD)) empty_cluster = 64 * 1024; } if ((flags & BTRFS_BLOCK_GROUP_DATA) && use_cluster && btrfs_test_opt(root, SSD)) { last_ptr = &root->fs_info->data_alloc_cluster; spin_unlock(&space_info->lock); } last_ptr = fetch_cluster_info(orig_root, space_info, &empty_cluster); if (last_ptr) { spin_lock(&last_ptr->lock); if (last_ptr->block_group) hint_byte = last_ptr->window_start; if (last_ptr->fragmented) { /* * We still set window_start so we can keep track of the * last place we found an allocation to try and save * some time. */ hint_byte = last_ptr->window_start; use_cluster = false; } spin_unlock(&last_ptr->lock); } search_start = max(search_start, first_logical_byte(root, 0)); search_start = max(search_start, hint_byte); if (!last_ptr) empty_cluster = 0; if (search_start == hint_byte) { block_group = btrfs_lookup_block_group(root->fs_info, search_start); Loading Loading @@ -6969,6 +7118,8 @@ static noinline int find_free_extent(struct btrfs_root *orig_root, } search: have_caching_bg = false; if (index == 0 || index == __get_raid_index(flags)) full_search = true; down_read(&space_info->groups_sem); list_for_each_entry(block_group, &space_info->block_groups[index], list) { Loading Loading @@ -7002,6 +7153,7 @@ static noinline int find_free_extent(struct btrfs_root *orig_root, have_block_group: cached = block_group_cache_done(block_group); if (unlikely(!cached)) { have_caching_bg = true; ret = cache_block_group(block_group, 0); BUG_ON(ret < 0); ret = 0; Loading @@ -7016,7 +7168,7 @@ static noinline int find_free_extent(struct btrfs_root *orig_root, * Ok we want to try and use the cluster allocator, so * lets look there */ if (last_ptr) { if (last_ptr && use_cluster) { struct btrfs_block_group_cache *used_block_group; unsigned long aligned_cluster; /* Loading Loading @@ -7142,6 +7294,16 @@ static noinline int find_free_extent(struct btrfs_root *orig_root, } unclustered_alloc: /* * We are doing an unclustered alloc, set the fragmented flag so * we don't bother trying to setup a cluster again until we get * more space. */ if (unlikely(last_ptr)) { spin_lock(&last_ptr->lock); last_ptr->fragmented = 1; spin_unlock(&last_ptr->lock); } spin_lock(&block_group->free_space_ctl->tree_lock); if (cached && block_group->free_space_ctl->free_space < Loading Loading @@ -7174,8 +7336,6 @@ static noinline int find_free_extent(struct btrfs_root *orig_root, failed_alloc = true; goto have_block_group; } else if (!offset) { if (!cached) have_caching_bg = true; goto loop; } checks: Loading Loading @@ -7232,7 +7392,20 @@ static noinline int find_free_extent(struct btrfs_root *orig_root, */ if (!ins->objectid && loop < LOOP_NO_EMPTY_SIZE) { index = 0; if (loop == LOOP_CACHING_NOWAIT) { /* * We want to skip the LOOP_CACHING_WAIT step if we * don't have any unached bgs and we've alrelady done a * full search through. */ if (have_caching_bg || !full_search) loop = LOOP_CACHING_WAIT; else loop = LOOP_ALLOC_CHUNK; } else { loop++; } if (loop == LOOP_ALLOC_CHUNK) { struct btrfs_trans_handle *trans; int exist = 0; Loading @@ -7250,6 +7423,15 @@ static noinline int find_free_extent(struct btrfs_root *orig_root, ret = do_chunk_alloc(trans, root, flags, CHUNK_ALLOC_FORCE); /* * If we can't allocate a new chunk we've already looped * through at least once, move on to the NO_EMPTY_SIZE * case. */ if (ret == -ENOSPC) loop = LOOP_NO_EMPTY_SIZE; /* * Do not bail out on ENOSPC since we * can do more things. Loading @@ -7266,6 +7448,15 @@ static noinline int find_free_extent(struct btrfs_root *orig_root, } if (loop == LOOP_NO_EMPTY_SIZE) { /* * Don't loop again if we already have no empty_size and * no empty_cluster. */ if (empty_size == 0 && empty_cluster == 0) { ret = -ENOSPC; goto out; } empty_size = 0; empty_cluster = 0; } Loading @@ -7274,11 +7465,20 @@ static noinline int find_free_extent(struct btrfs_root *orig_root, } else if (!ins->objectid) { ret = -ENOSPC; } else if (ins->objectid) { if (!use_cluster && last_ptr) { spin_lock(&last_ptr->lock); last_ptr->window_start = ins->objectid; spin_unlock(&last_ptr->lock); } ret = 0; } out: if (ret == -ENOSPC) if (ret == -ENOSPC) { spin_lock(&space_info->lock); space_info->max_extent_size = max_extent_size; spin_unlock(&space_info->lock); ins->offset = max_extent_size; } return ret; } Loading Loading @@ -7327,7 +7527,7 @@ int btrfs_reserve_extent(struct btrfs_root *root, u64 empty_size, u64 hint_byte, struct btrfs_key *ins, int is_data, int delalloc) { bool final_tried = false; bool final_tried = num_bytes == min_alloc_size; u64 flags; int ret; Loading Loading @@ -8929,7 +9129,7 @@ int btrfs_inc_block_group_ro(struct btrfs_root *root, * back off and let this transaction commit */ mutex_lock(&root->fs_info->ro_block_group_mutex); if (trans->transaction->dirty_bg_run) { if (test_bit(BTRFS_TRANS_DIRTY_BG_RUN, &trans->transaction->flags)) { u64 transid = trans->transid; mutex_unlock(&root->fs_info->ro_block_group_mutex); Loading Loading @@ -9679,6 +9879,14 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans, free_excluded_extents(root, cache); #ifdef CONFIG_BTRFS_DEBUG if (btrfs_should_fragment_free_space(root, cache)) { u64 new_bytes_used = size - bytes_used; bytes_used += new_bytes_used >> 1; fragment_free_space(root, cache); } #endif /* * Call to ensure the corresponding space_info object is created and * assigned to our block group, but don't update its counters just yet. Loading fs/btrfs/free-space-cache.c +57 −10 Original line number Diff line number Diff line Loading @@ -1730,7 +1730,7 @@ static void bitmap_set_bits(struct btrfs_free_space_ctl *ctl, */ static int search_bitmap(struct btrfs_free_space_ctl *ctl, struct btrfs_free_space *bitmap_info, u64 *offset, u64 *bytes) u64 *bytes, bool for_alloc) { unsigned long found_bits = 0; unsigned long max_bits = 0; Loading @@ -1738,11 +1738,26 @@ static int search_bitmap(struct btrfs_free_space_ctl *ctl, unsigned long next_zero; unsigned long extent_bits; /* * Skip searching the bitmap if we don't have a contiguous section that * is large enough for this allocation. */ if (for_alloc && bitmap_info->max_extent_size && bitmap_info->max_extent_size < *bytes) { *bytes = bitmap_info->max_extent_size; return -1; } i = offset_to_bit(bitmap_info->offset, ctl->unit, max_t(u64, *offset, bitmap_info->offset)); bits = bytes_to_bits(*bytes, ctl->unit); for_each_set_bit_from(i, bitmap_info->bitmap, BITS_PER_BITMAP) { if (for_alloc && bits == 1) { found_bits = 1; break; } next_zero = find_next_zero_bit(bitmap_info->bitmap, BITS_PER_BITMAP, i); extent_bits = next_zero - i; Loading @@ -1762,6 +1777,7 @@ static int search_bitmap(struct btrfs_free_space_ctl *ctl, } *bytes = (u64)(max_bits) * ctl->unit; bitmap_info->max_extent_size = *bytes; return -1; } Loading Loading @@ -1813,7 +1829,7 @@ find_free_space(struct btrfs_free_space_ctl *ctl, u64 *offset, u64 *bytes, if (entry->bitmap) { u64 size = *bytes; ret = search_bitmap(ctl, entry, &tmp, &size); ret = search_bitmap(ctl, entry, &tmp, &size, true); if (!ret) { *offset = tmp; *bytes = size; Loading Loading @@ -1874,7 +1890,8 @@ static noinline int remove_from_bitmap(struct btrfs_free_space_ctl *ctl, search_start = *offset; search_bytes = ctl->unit; search_bytes = min(search_bytes, end - search_start + 1); ret = search_bitmap(ctl, bitmap_info, &search_start, &search_bytes); ret = search_bitmap(ctl, bitmap_info, &search_start, &search_bytes, false); if (ret < 0 || search_start != *offset) return -EINVAL; Loading Loading @@ -1919,7 +1936,7 @@ static noinline int remove_from_bitmap(struct btrfs_free_space_ctl *ctl, search_start = *offset; search_bytes = ctl->unit; ret = search_bitmap(ctl, bitmap_info, &search_start, &search_bytes); &search_bytes, false); if (ret < 0 || search_start != *offset) return -EAGAIN; Loading @@ -1943,6 +1960,12 @@ static u64 add_bytes_to_bitmap(struct btrfs_free_space_ctl *ctl, bitmap_set_bits(ctl, info, offset, bytes_to_set); /* * We set some bytes, we have no idea what the max extent size is * anymore. */ info->max_extent_size = 0; return bytes_to_set; } Loading @@ -1951,12 +1974,19 @@ static bool use_bitmap(struct btrfs_free_space_ctl *ctl, struct btrfs_free_space *info) { struct btrfs_block_group_cache *block_group = ctl->private; bool forced = false; #ifdef CONFIG_BTRFS_DEBUG if (btrfs_should_fragment_free_space(block_group->fs_info->extent_root, block_group)) forced = true; #endif /* * If we are below the extents threshold then we can add this as an * extent, and don't have to deal with the bitmap */ if (ctl->free_extents < ctl->extents_thresh) { if (!forced && ctl->free_extents < ctl->extents_thresh) { /* * If this block group has some small extents we don't want to * use up all of our free slots in the cache with them, we want Loading Loading @@ -2661,7 +2691,7 @@ static u64 btrfs_alloc_from_bitmap(struct btrfs_block_group_cache *block_group, search_start = min_start; search_bytes = bytes; err = search_bitmap(ctl, entry, &search_start, &search_bytes); err = search_bitmap(ctl, entry, &search_start, &search_bytes, true); if (err) { if (search_bytes > *max_extent_size) *max_extent_size = search_bytes; Loading Loading @@ -2775,6 +2805,7 @@ static int btrfs_bitmap_cluster(struct btrfs_block_group_cache *block_group, unsigned long want_bits; unsigned long min_bits; unsigned long found_bits; unsigned long max_bits = 0; unsigned long start = 0; unsigned long total_found = 0; int ret; Loading @@ -2784,6 +2815,13 @@ static int btrfs_bitmap_cluster(struct btrfs_block_group_cache *block_group, want_bits = bytes_to_bits(bytes, ctl->unit); min_bits = bytes_to_bits(min_bytes, ctl->unit); /* * Don't bother looking for a cluster in this bitmap if it's heavily * fragmented. */ if (entry->max_extent_size && entry->max_extent_size < cont1_bytes) return -ENOSPC; again: found_bits = 0; for_each_set_bit_from(i, entry->bitmap, BITS_PER_BITMAP) { Loading @@ -2791,13 +2829,19 @@ static int btrfs_bitmap_cluster(struct btrfs_block_group_cache *block_group, BITS_PER_BITMAP, i); if (next_zero - i >= min_bits) { found_bits = next_zero - i; if (found_bits > max_bits) max_bits = found_bits; break; } if (next_zero - i > max_bits) max_bits = next_zero - i; i = next_zero; } if (!found_bits) if (!found_bits) { entry->max_extent_size = (u64)max_bits * ctl->unit; return -ENOSPC; } if (!total_found) { start = i; Loading Loading @@ -3056,6 +3100,7 @@ void btrfs_init_free_cluster(struct btrfs_free_cluster *cluster) spin_lock_init(&cluster->refill_lock); cluster->root = RB_ROOT; cluster->max_size = 0; cluster->fragmented = false; INIT_LIST_HEAD(&cluster->block_group_list); cluster->block_group = NULL; } Loading Loading @@ -3223,7 +3268,7 @@ static int trim_bitmaps(struct btrfs_block_group_cache *block_group, } bytes = minlen; ret2 = search_bitmap(ctl, entry, &start, &bytes); ret2 = search_bitmap(ctl, entry, &start, &bytes, false); if (ret2 || start >= end) { spin_unlock(&ctl->tree_lock); mutex_unlock(&ctl->cache_writeout_mutex); Loading Loading @@ -3376,7 +3421,7 @@ u64 btrfs_find_ino_for_alloc(struct btrfs_root *fs_root) u64 count = 1; int ret; ret = search_bitmap(ctl, entry, &offset, &count); ret = search_bitmap(ctl, entry, &offset, &count, true); /* Logic error; Should be empty if it can't find anything */ ASSERT(!ret); Loading Loading @@ -3532,6 +3577,7 @@ int test_add_free_space_entry(struct btrfs_block_group_cache *cache, spin_lock(&ctl->tree_lock); info->offset = offset; info->bytes = bytes; info->max_extent_size = 0; ret = link_free_space(ctl, info); spin_unlock(&ctl->tree_lock); if (ret) Loading Loading @@ -3559,6 +3605,7 @@ int test_add_free_space_entry(struct btrfs_block_group_cache *cache, } bytes_added = add_bytes_to_bitmap(ctl, bitmap_info, offset, bytes); bytes -= bytes_added; offset += bytes_added; spin_unlock(&ctl->tree_lock); Loading Loading @@ -3602,7 +3649,7 @@ int test_check_exists(struct btrfs_block_group_cache *cache, bit_off = offset; bit_bytes = ctl->unit; ret = search_bitmap(ctl, info, &bit_off, &bit_bytes); ret = search_bitmap(ctl, info, &bit_off, &bit_bytes, false); if (!ret) { if (bit_off == offset) { ret = 1; Loading Loading
fs/btrfs/backref.c +6 −0 Original line number Diff line number Diff line Loading @@ -362,6 +362,12 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, goto out; } if (btrfs_test_is_dummy_root(root)) { srcu_read_unlock(&fs_info->subvol_srcu, index); ret = -ENOENT; goto out; } if (path->search_commit_root) root_level = btrfs_header_level(root->commit_root); else if (time_seq == (u64)-1) Loading
fs/btrfs/ctree.h +21 −0 Original line number Diff line number Diff line Loading @@ -1154,6 +1154,10 @@ struct btrfs_space_info { delalloc/allocations */ u64 bytes_readonly; /* total bytes that are read only */ u64 max_extent_size; /* This will hold the maximum extent size of the space info if we had an ENOSPC in the allocator. */ unsigned int full:1; /* indicates that we cannot allocate any more chunks for this space */ unsigned int chunk_alloc:1; /* set if we are allocating a chunk */ Loading Loading @@ -1228,6 +1232,9 @@ struct btrfs_free_cluster { /* first extent starting offset */ u64 window_start; /* We did a full search and couldn't create a cluster */ bool fragmented; struct btrfs_block_group_cache *block_group; /* * when a cluster is allocated from a block group, we put the Loading Loading @@ -2148,6 +2155,8 @@ struct btrfs_ioctl_defrag_range_args { #define BTRFS_MOUNT_CHECK_INTEGRITY_INCLUDING_EXTENT_DATA (1 << 21) #define BTRFS_MOUNT_PANIC_ON_FATAL_ERROR (1 << 22) #define BTRFS_MOUNT_RESCAN_UUID_TREE (1 << 23) #define BTRFS_MOUNT_FRAGMENT_DATA (1 << 24) #define BTRFS_MOUNT_FRAGMENT_METADATA (1 << 25) #define BTRFS_DEFAULT_COMMIT_INTERVAL (30) #define BTRFS_DEFAULT_MAX_INLINE (8192) Loading @@ -2172,6 +2181,18 @@ struct btrfs_ioctl_defrag_range_args { btrfs_clear_opt(root->fs_info->mount_opt, opt); \ } #ifdef CONFIG_BTRFS_DEBUG static inline int btrfs_should_fragment_free_space(struct btrfs_root *root, struct btrfs_block_group_cache *block_group) { return (btrfs_test_opt(root, FRAGMENT_METADATA) && block_group->flags & BTRFS_BLOCK_GROUP_METADATA) || (btrfs_test_opt(root, FRAGMENT_DATA) && block_group->flags & BTRFS_BLOCK_GROUP_DATA); } #endif /* * Requests for changes that need to be done during transaction commit. * Loading
fs/btrfs/disk-io.c +0 −20 Original line number Diff line number Diff line Loading @@ -4327,25 +4327,6 @@ static int btrfs_destroy_pinned_extent(struct btrfs_root *root, return 0; } static void btrfs_free_pending_ordered(struct btrfs_transaction *cur_trans, struct btrfs_fs_info *fs_info) { struct btrfs_ordered_extent *ordered; spin_lock(&fs_info->trans_lock); while (!list_empty(&cur_trans->pending_ordered)) { ordered = list_first_entry(&cur_trans->pending_ordered, struct btrfs_ordered_extent, trans_list); list_del_init(&ordered->trans_list); spin_unlock(&fs_info->trans_lock); btrfs_put_ordered_extent(ordered); spin_lock(&fs_info->trans_lock); } spin_unlock(&fs_info->trans_lock); } void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans, struct btrfs_root *root) { Loading @@ -4357,7 +4338,6 @@ void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans, cur_trans->state = TRANS_STATE_UNBLOCKED; wake_up(&root->fs_info->transaction_wait); btrfs_free_pending_ordered(cur_trans, root->fs_info); btrfs_destroy_delayed_inodes(root); btrfs_assert_delayed_root_empty(root); Loading
fs/btrfs/extent-tree.c +240 −32 Original line number Diff line number Diff line Loading @@ -332,6 +332,27 @@ static void put_caching_control(struct btrfs_caching_control *ctl) kfree(ctl); } #ifdef CONFIG_BTRFS_DEBUG static void fragment_free_space(struct btrfs_root *root, struct btrfs_block_group_cache *block_group) { u64 start = block_group->key.objectid; u64 len = block_group->key.offset; u64 chunk = block_group->flags & BTRFS_BLOCK_GROUP_METADATA ? root->nodesize : root->sectorsize; u64 step = chunk << 1; while (len > chunk) { btrfs_remove_free_space(block_group, start, chunk); start += step; if (len < step) len = 0; else len -= step; } } #endif /* * this is only called by cache_block_group, since we could have freed extents * we need to check the pinned_extents for any extents that can't be used yet Loading Loading @@ -388,6 +409,7 @@ static noinline void caching_thread(struct btrfs_work *work) u64 last = 0; u32 nritems; int ret = -ENOMEM; bool wakeup = true; caching_ctl = container_of(work, struct btrfs_caching_control, work); block_group = caching_ctl->block_group; Loading @@ -400,6 +422,15 @@ static noinline void caching_thread(struct btrfs_work *work) last = max_t(u64, block_group->key.objectid, BTRFS_SUPER_INFO_OFFSET); #ifdef CONFIG_BTRFS_DEBUG /* * If we're fragmenting we don't want to make anybody think we can * allocate from this block group until we've had a chance to fragment * the free space. */ if (btrfs_should_fragment_free_space(extent_root, block_group)) wakeup = false; #endif /* * We don't want to deadlock with somebody trying to allocate a new * extent for the extent root while also trying to search the extent Loading Loading @@ -441,6 +472,7 @@ static noinline void caching_thread(struct btrfs_work *work) if (need_resched() || rwsem_is_contended(&fs_info->commit_root_sem)) { if (wakeup) caching_ctl->progress = last; btrfs_release_path(path); up_read(&fs_info->commit_root_sem); Loading @@ -464,6 +496,7 @@ static noinline void caching_thread(struct btrfs_work *work) key.offset = 0; key.type = BTRFS_EXTENT_ITEM_KEY; if (wakeup) caching_ctl->progress = last; btrfs_release_path(path); goto next; Loading Loading @@ -491,6 +524,7 @@ static noinline void caching_thread(struct btrfs_work *work) if (total_found > (1024 * 1024 * 2)) { total_found = 0; if (wakeup) wake_up(&caching_ctl->wait); } } Loading @@ -501,13 +535,27 @@ static noinline void caching_thread(struct btrfs_work *work) total_found += add_new_free_space(block_group, fs_info, last, block_group->key.objectid + block_group->key.offset); caching_ctl->progress = (u64)-1; spin_lock(&block_group->lock); block_group->caching_ctl = NULL; block_group->cached = BTRFS_CACHE_FINISHED; spin_unlock(&block_group->lock); #ifdef CONFIG_BTRFS_DEBUG if (btrfs_should_fragment_free_space(extent_root, block_group)) { u64 bytes_used; spin_lock(&block_group->space_info->lock); spin_lock(&block_group->lock); bytes_used = block_group->key.offset - btrfs_block_group_used(&block_group->item); block_group->space_info->bytes_used += bytes_used >> 1; spin_unlock(&block_group->lock); spin_unlock(&block_group->space_info->lock); fragment_free_space(extent_root, block_group); } #endif caching_ctl->progress = (u64)-1; err: btrfs_free_path(path); up_read(&fs_info->commit_root_sem); Loading Loading @@ -607,6 +655,22 @@ static int cache_block_group(struct btrfs_block_group_cache *cache, } } spin_unlock(&cache->lock); #ifdef CONFIG_BTRFS_DEBUG if (ret == 1 && btrfs_should_fragment_free_space(fs_info->extent_root, cache)) { u64 bytes_used; spin_lock(&cache->space_info->lock); spin_lock(&cache->lock); bytes_used = cache->key.offset - btrfs_block_group_used(&cache->item); cache->space_info->bytes_used += bytes_used >> 1; spin_unlock(&cache->lock); spin_unlock(&cache->space_info->lock); fragment_free_space(fs_info->extent_root, cache); } #endif mutex_unlock(&caching_ctl->mutex); wake_up(&caching_ctl->wait); Loading Loading @@ -3343,6 +3407,15 @@ static int cache_save_setup(struct btrfs_block_group_cache *block_group, } spin_unlock(&block_group->lock); /* * We hit an ENOSPC when setting up the cache in this transaction, just * skip doing the setup, we've already cleared the cache so we're safe. */ if (test_bit(BTRFS_TRANS_CACHE_ENOSPC, &trans->transaction->flags)) { ret = -ENOSPC; goto out_put; } /* * Try to preallocate enough space based on how big the block group is. * Keep in mind this has to include any pinned space which could end up Loading @@ -3363,8 +3436,18 @@ static int cache_save_setup(struct btrfs_block_group_cache *block_group, ret = btrfs_prealloc_file_range_trans(inode, trans, 0, 0, num_pages, num_pages, num_pages, &alloc_hint); /* * Our cache requires contiguous chunks so that we don't modify a bunch * of metadata or split extents when writing the cache out, which means * we can enospc if we are heavily fragmented in addition to just normal * out of space conditions. So if we hit this just skip setting up any * other block groups for this transaction, maybe we'll unpin enough * space the next time around. */ if (!ret) dcs = BTRFS_DC_SETUP; else if (ret == -ENOSPC) set_bit(BTRFS_TRANS_CACHE_ENOSPC, &trans->transaction->flags); btrfs_free_reserved_data_space(inode, 0, num_pages); out_put: Loading Loading @@ -3751,6 +3834,7 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags, found->bytes_readonly = 0; found->bytes_may_use = 0; found->full = 0; found->max_extent_size = 0; found->force_alloc = CHUNK_ALLOC_NO_FORCE; found->chunk_alloc = 0; found->flush = 0; Loading Loading @@ -4003,7 +4087,8 @@ int btrfs_alloc_data_chunk_ondemand(struct inode *inode, u64 bytes) if (IS_ERR(trans)) return PTR_ERR(trans); if (have_pinned_space >= 0 || trans->transaction->have_free_bgs || test_bit(BTRFS_TRANS_HAVE_FREE_BGS, &trans->transaction->flags) || need_commit > 0) { ret = btrfs_commit_transaction(trans, root); if (ret) Loading Loading @@ -6112,6 +6197,34 @@ void btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans, update_global_block_rsv(fs_info); } /* * Returns the free cluster for the given space info and sets empty_cluster to * what it should be based on the mount options. */ static struct btrfs_free_cluster * fetch_cluster_info(struct btrfs_root *root, struct btrfs_space_info *space_info, u64 *empty_cluster) { struct btrfs_free_cluster *ret = NULL; bool ssd = btrfs_test_opt(root, SSD); *empty_cluster = 0; if (btrfs_mixed_space_info(space_info)) return ret; if (ssd) *empty_cluster = 2 * 1024 * 1024; if (space_info->flags & BTRFS_BLOCK_GROUP_METADATA) { ret = &root->fs_info->meta_alloc_cluster; if (!ssd) *empty_cluster = 64 * 1024; } else if ((space_info->flags & BTRFS_BLOCK_GROUP_DATA) && ssd) { ret = &root->fs_info->data_alloc_cluster; } return ret; } static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end, const bool return_free_space) { Loading @@ -6119,7 +6232,10 @@ static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end, struct btrfs_block_group_cache *cache = NULL; struct btrfs_space_info *space_info; struct btrfs_block_rsv *global_rsv = &fs_info->global_block_rsv; struct btrfs_free_cluster *cluster = NULL; u64 len; u64 total_unpinned = 0; u64 empty_cluster = 0; bool readonly; while (start <= end) { Loading @@ -6128,8 +6244,14 @@ static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end, start >= cache->key.objectid + cache->key.offset) { if (cache) btrfs_put_block_group(cache); total_unpinned = 0; cache = btrfs_lookup_block_group(fs_info, start); BUG_ON(!cache); /* Logic error */ cluster = fetch_cluster_info(root, cache->space_info, &empty_cluster); empty_cluster <<= 1; } len = cache->key.objectid + cache->key.offset - start; Loading @@ -6142,12 +6264,27 @@ static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end, } start += len; total_unpinned += len; space_info = cache->space_info; /* * If this space cluster has been marked as fragmented and we've * unpinned enough in this block group to potentially allow a * cluster to be created inside of it go ahead and clear the * fragmented check. */ if (cluster && cluster->fragmented && total_unpinned > empty_cluster) { spin_lock(&cluster->lock); cluster->fragmented = 0; spin_unlock(&cluster->lock); } spin_lock(&space_info->lock); spin_lock(&cache->lock); cache->pinned -= len; space_info->bytes_pinned -= len; space_info->max_extent_size = 0; percpu_counter_add(&space_info->total_bytes_pinned, -len); if (cache->ro) { space_info->bytes_readonly += len; Loading Loading @@ -6880,7 +7017,7 @@ static noinline int find_free_extent(struct btrfs_root *orig_root, struct btrfs_block_group_cache *block_group = NULL; u64 search_start = 0; u64 max_extent_size = 0; int empty_cluster = 2 * 1024 * 1024; u64 empty_cluster = 0; struct btrfs_space_info *space_info; int loop = 0; int index = __get_raid_index(flags); Loading @@ -6890,6 +7027,7 @@ static noinline int find_free_extent(struct btrfs_root *orig_root, bool failed_alloc = false; bool use_cluster = true; bool have_caching_bg = false; bool full_search = false; WARN_ON(num_bytes < root->sectorsize); ins->type = BTRFS_EXTENT_ITEM_KEY; Loading @@ -6905,36 +7043,47 @@ static noinline int find_free_extent(struct btrfs_root *orig_root, } /* * If the space info is for both data and metadata it means we have a * small filesystem and we can't use the clustering stuff. * If our free space is heavily fragmented we may not be able to make * big contiguous allocations, so instead of doing the expensive search * for free space, simply return ENOSPC with our max_extent_size so we * can go ahead and search for a more manageable chunk. * * If our max_extent_size is large enough for our allocation simply * disable clustering since we will likely not be able to find enough * space to create a cluster and induce latency trying. */ if (btrfs_mixed_space_info(space_info)) if (unlikely(space_info->max_extent_size)) { spin_lock(&space_info->lock); if (space_info->max_extent_size && num_bytes > space_info->max_extent_size) { ins->offset = space_info->max_extent_size; spin_unlock(&space_info->lock); return -ENOSPC; } else if (space_info->max_extent_size) { use_cluster = false; if (flags & BTRFS_BLOCK_GROUP_METADATA && use_cluster) { last_ptr = &root->fs_info->meta_alloc_cluster; if (!btrfs_test_opt(root, SSD)) empty_cluster = 64 * 1024; } if ((flags & BTRFS_BLOCK_GROUP_DATA) && use_cluster && btrfs_test_opt(root, SSD)) { last_ptr = &root->fs_info->data_alloc_cluster; spin_unlock(&space_info->lock); } last_ptr = fetch_cluster_info(orig_root, space_info, &empty_cluster); if (last_ptr) { spin_lock(&last_ptr->lock); if (last_ptr->block_group) hint_byte = last_ptr->window_start; if (last_ptr->fragmented) { /* * We still set window_start so we can keep track of the * last place we found an allocation to try and save * some time. */ hint_byte = last_ptr->window_start; use_cluster = false; } spin_unlock(&last_ptr->lock); } search_start = max(search_start, first_logical_byte(root, 0)); search_start = max(search_start, hint_byte); if (!last_ptr) empty_cluster = 0; if (search_start == hint_byte) { block_group = btrfs_lookup_block_group(root->fs_info, search_start); Loading Loading @@ -6969,6 +7118,8 @@ static noinline int find_free_extent(struct btrfs_root *orig_root, } search: have_caching_bg = false; if (index == 0 || index == __get_raid_index(flags)) full_search = true; down_read(&space_info->groups_sem); list_for_each_entry(block_group, &space_info->block_groups[index], list) { Loading Loading @@ -7002,6 +7153,7 @@ static noinline int find_free_extent(struct btrfs_root *orig_root, have_block_group: cached = block_group_cache_done(block_group); if (unlikely(!cached)) { have_caching_bg = true; ret = cache_block_group(block_group, 0); BUG_ON(ret < 0); ret = 0; Loading @@ -7016,7 +7168,7 @@ static noinline int find_free_extent(struct btrfs_root *orig_root, * Ok we want to try and use the cluster allocator, so * lets look there */ if (last_ptr) { if (last_ptr && use_cluster) { struct btrfs_block_group_cache *used_block_group; unsigned long aligned_cluster; /* Loading Loading @@ -7142,6 +7294,16 @@ static noinline int find_free_extent(struct btrfs_root *orig_root, } unclustered_alloc: /* * We are doing an unclustered alloc, set the fragmented flag so * we don't bother trying to setup a cluster again until we get * more space. */ if (unlikely(last_ptr)) { spin_lock(&last_ptr->lock); last_ptr->fragmented = 1; spin_unlock(&last_ptr->lock); } spin_lock(&block_group->free_space_ctl->tree_lock); if (cached && block_group->free_space_ctl->free_space < Loading Loading @@ -7174,8 +7336,6 @@ static noinline int find_free_extent(struct btrfs_root *orig_root, failed_alloc = true; goto have_block_group; } else if (!offset) { if (!cached) have_caching_bg = true; goto loop; } checks: Loading Loading @@ -7232,7 +7392,20 @@ static noinline int find_free_extent(struct btrfs_root *orig_root, */ if (!ins->objectid && loop < LOOP_NO_EMPTY_SIZE) { index = 0; if (loop == LOOP_CACHING_NOWAIT) { /* * We want to skip the LOOP_CACHING_WAIT step if we * don't have any unached bgs and we've alrelady done a * full search through. */ if (have_caching_bg || !full_search) loop = LOOP_CACHING_WAIT; else loop = LOOP_ALLOC_CHUNK; } else { loop++; } if (loop == LOOP_ALLOC_CHUNK) { struct btrfs_trans_handle *trans; int exist = 0; Loading @@ -7250,6 +7423,15 @@ static noinline int find_free_extent(struct btrfs_root *orig_root, ret = do_chunk_alloc(trans, root, flags, CHUNK_ALLOC_FORCE); /* * If we can't allocate a new chunk we've already looped * through at least once, move on to the NO_EMPTY_SIZE * case. */ if (ret == -ENOSPC) loop = LOOP_NO_EMPTY_SIZE; /* * Do not bail out on ENOSPC since we * can do more things. Loading @@ -7266,6 +7448,15 @@ static noinline int find_free_extent(struct btrfs_root *orig_root, } if (loop == LOOP_NO_EMPTY_SIZE) { /* * Don't loop again if we already have no empty_size and * no empty_cluster. */ if (empty_size == 0 && empty_cluster == 0) { ret = -ENOSPC; goto out; } empty_size = 0; empty_cluster = 0; } Loading @@ -7274,11 +7465,20 @@ static noinline int find_free_extent(struct btrfs_root *orig_root, } else if (!ins->objectid) { ret = -ENOSPC; } else if (ins->objectid) { if (!use_cluster && last_ptr) { spin_lock(&last_ptr->lock); last_ptr->window_start = ins->objectid; spin_unlock(&last_ptr->lock); } ret = 0; } out: if (ret == -ENOSPC) if (ret == -ENOSPC) { spin_lock(&space_info->lock); space_info->max_extent_size = max_extent_size; spin_unlock(&space_info->lock); ins->offset = max_extent_size; } return ret; } Loading Loading @@ -7327,7 +7527,7 @@ int btrfs_reserve_extent(struct btrfs_root *root, u64 empty_size, u64 hint_byte, struct btrfs_key *ins, int is_data, int delalloc) { bool final_tried = false; bool final_tried = num_bytes == min_alloc_size; u64 flags; int ret; Loading Loading @@ -8929,7 +9129,7 @@ int btrfs_inc_block_group_ro(struct btrfs_root *root, * back off and let this transaction commit */ mutex_lock(&root->fs_info->ro_block_group_mutex); if (trans->transaction->dirty_bg_run) { if (test_bit(BTRFS_TRANS_DIRTY_BG_RUN, &trans->transaction->flags)) { u64 transid = trans->transid; mutex_unlock(&root->fs_info->ro_block_group_mutex); Loading Loading @@ -9679,6 +9879,14 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans, free_excluded_extents(root, cache); #ifdef CONFIG_BTRFS_DEBUG if (btrfs_should_fragment_free_space(root, cache)) { u64 new_bytes_used = size - bytes_used; bytes_used += new_bytes_used >> 1; fragment_free_space(root, cache); } #endif /* * Call to ensure the corresponding space_info object is created and * assigned to our block group, but don't update its counters just yet. Loading
fs/btrfs/free-space-cache.c +57 −10 Original line number Diff line number Diff line Loading @@ -1730,7 +1730,7 @@ static void bitmap_set_bits(struct btrfs_free_space_ctl *ctl, */ static int search_bitmap(struct btrfs_free_space_ctl *ctl, struct btrfs_free_space *bitmap_info, u64 *offset, u64 *bytes) u64 *bytes, bool for_alloc) { unsigned long found_bits = 0; unsigned long max_bits = 0; Loading @@ -1738,11 +1738,26 @@ static int search_bitmap(struct btrfs_free_space_ctl *ctl, unsigned long next_zero; unsigned long extent_bits; /* * Skip searching the bitmap if we don't have a contiguous section that * is large enough for this allocation. */ if (for_alloc && bitmap_info->max_extent_size && bitmap_info->max_extent_size < *bytes) { *bytes = bitmap_info->max_extent_size; return -1; } i = offset_to_bit(bitmap_info->offset, ctl->unit, max_t(u64, *offset, bitmap_info->offset)); bits = bytes_to_bits(*bytes, ctl->unit); for_each_set_bit_from(i, bitmap_info->bitmap, BITS_PER_BITMAP) { if (for_alloc && bits == 1) { found_bits = 1; break; } next_zero = find_next_zero_bit(bitmap_info->bitmap, BITS_PER_BITMAP, i); extent_bits = next_zero - i; Loading @@ -1762,6 +1777,7 @@ static int search_bitmap(struct btrfs_free_space_ctl *ctl, } *bytes = (u64)(max_bits) * ctl->unit; bitmap_info->max_extent_size = *bytes; return -1; } Loading Loading @@ -1813,7 +1829,7 @@ find_free_space(struct btrfs_free_space_ctl *ctl, u64 *offset, u64 *bytes, if (entry->bitmap) { u64 size = *bytes; ret = search_bitmap(ctl, entry, &tmp, &size); ret = search_bitmap(ctl, entry, &tmp, &size, true); if (!ret) { *offset = tmp; *bytes = size; Loading Loading @@ -1874,7 +1890,8 @@ static noinline int remove_from_bitmap(struct btrfs_free_space_ctl *ctl, search_start = *offset; search_bytes = ctl->unit; search_bytes = min(search_bytes, end - search_start + 1); ret = search_bitmap(ctl, bitmap_info, &search_start, &search_bytes); ret = search_bitmap(ctl, bitmap_info, &search_start, &search_bytes, false); if (ret < 0 || search_start != *offset) return -EINVAL; Loading Loading @@ -1919,7 +1936,7 @@ static noinline int remove_from_bitmap(struct btrfs_free_space_ctl *ctl, search_start = *offset; search_bytes = ctl->unit; ret = search_bitmap(ctl, bitmap_info, &search_start, &search_bytes); &search_bytes, false); if (ret < 0 || search_start != *offset) return -EAGAIN; Loading @@ -1943,6 +1960,12 @@ static u64 add_bytes_to_bitmap(struct btrfs_free_space_ctl *ctl, bitmap_set_bits(ctl, info, offset, bytes_to_set); /* * We set some bytes, we have no idea what the max extent size is * anymore. */ info->max_extent_size = 0; return bytes_to_set; } Loading @@ -1951,12 +1974,19 @@ static bool use_bitmap(struct btrfs_free_space_ctl *ctl, struct btrfs_free_space *info) { struct btrfs_block_group_cache *block_group = ctl->private; bool forced = false; #ifdef CONFIG_BTRFS_DEBUG if (btrfs_should_fragment_free_space(block_group->fs_info->extent_root, block_group)) forced = true; #endif /* * If we are below the extents threshold then we can add this as an * extent, and don't have to deal with the bitmap */ if (ctl->free_extents < ctl->extents_thresh) { if (!forced && ctl->free_extents < ctl->extents_thresh) { /* * If this block group has some small extents we don't want to * use up all of our free slots in the cache with them, we want Loading Loading @@ -2661,7 +2691,7 @@ static u64 btrfs_alloc_from_bitmap(struct btrfs_block_group_cache *block_group, search_start = min_start; search_bytes = bytes; err = search_bitmap(ctl, entry, &search_start, &search_bytes); err = search_bitmap(ctl, entry, &search_start, &search_bytes, true); if (err) { if (search_bytes > *max_extent_size) *max_extent_size = search_bytes; Loading Loading @@ -2775,6 +2805,7 @@ static int btrfs_bitmap_cluster(struct btrfs_block_group_cache *block_group, unsigned long want_bits; unsigned long min_bits; unsigned long found_bits; unsigned long max_bits = 0; unsigned long start = 0; unsigned long total_found = 0; int ret; Loading @@ -2784,6 +2815,13 @@ static int btrfs_bitmap_cluster(struct btrfs_block_group_cache *block_group, want_bits = bytes_to_bits(bytes, ctl->unit); min_bits = bytes_to_bits(min_bytes, ctl->unit); /* * Don't bother looking for a cluster in this bitmap if it's heavily * fragmented. */ if (entry->max_extent_size && entry->max_extent_size < cont1_bytes) return -ENOSPC; again: found_bits = 0; for_each_set_bit_from(i, entry->bitmap, BITS_PER_BITMAP) { Loading @@ -2791,13 +2829,19 @@ static int btrfs_bitmap_cluster(struct btrfs_block_group_cache *block_group, BITS_PER_BITMAP, i); if (next_zero - i >= min_bits) { found_bits = next_zero - i; if (found_bits > max_bits) max_bits = found_bits; break; } if (next_zero - i > max_bits) max_bits = next_zero - i; i = next_zero; } if (!found_bits) if (!found_bits) { entry->max_extent_size = (u64)max_bits * ctl->unit; return -ENOSPC; } if (!total_found) { start = i; Loading Loading @@ -3056,6 +3100,7 @@ void btrfs_init_free_cluster(struct btrfs_free_cluster *cluster) spin_lock_init(&cluster->refill_lock); cluster->root = RB_ROOT; cluster->max_size = 0; cluster->fragmented = false; INIT_LIST_HEAD(&cluster->block_group_list); cluster->block_group = NULL; } Loading Loading @@ -3223,7 +3268,7 @@ static int trim_bitmaps(struct btrfs_block_group_cache *block_group, } bytes = minlen; ret2 = search_bitmap(ctl, entry, &start, &bytes); ret2 = search_bitmap(ctl, entry, &start, &bytes, false); if (ret2 || start >= end) { spin_unlock(&ctl->tree_lock); mutex_unlock(&ctl->cache_writeout_mutex); Loading Loading @@ -3376,7 +3421,7 @@ u64 btrfs_find_ino_for_alloc(struct btrfs_root *fs_root) u64 count = 1; int ret; ret = search_bitmap(ctl, entry, &offset, &count); ret = search_bitmap(ctl, entry, &offset, &count, true); /* Logic error; Should be empty if it can't find anything */ ASSERT(!ret); Loading Loading @@ -3532,6 +3577,7 @@ int test_add_free_space_entry(struct btrfs_block_group_cache *cache, spin_lock(&ctl->tree_lock); info->offset = offset; info->bytes = bytes; info->max_extent_size = 0; ret = link_free_space(ctl, info); spin_unlock(&ctl->tree_lock); if (ret) Loading Loading @@ -3559,6 +3605,7 @@ int test_add_free_space_entry(struct btrfs_block_group_cache *cache, } bytes_added = add_bytes_to_bitmap(ctl, bitmap_info, offset, bytes); bytes -= bytes_added; offset += bytes_added; spin_unlock(&ctl->tree_lock); Loading Loading @@ -3602,7 +3649,7 @@ int test_check_exists(struct btrfs_block_group_cache *cache, bit_off = offset; bit_bytes = ctl->unit; ret = search_bitmap(ctl, info, &bit_off, &bit_bytes); ret = search_bitmap(ctl, info, &bit_off, &bit_bytes, false); if (!ret) { if (bit_off == offset) { ret = 1; Loading