]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blobdiff - fs/btrfs/extent-tree.c
Btrfs: Bring back mount -o ssd optimizations
[mirror_ubuntu-jammy-kernel.git] / fs / btrfs / extent-tree.c
index 14eb8fc87015d7d25099ec1622fa648cf6d74162..e9ef644ff56f841d3502d55405004b4d5c4614a8 100644 (file)
@@ -1473,13 +1473,31 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
        struct btrfs_root * root = orig_root->fs_info->extent_root;
        struct btrfs_fs_info *info = root->fs_info;
        u64 total_needed = num_bytes;
+       u64 *last_ptr = NULL;
        struct btrfs_block_group_cache *block_group;
        int full_scan = 0;
        int wrapped = 0;
+       int empty_cluster = 2 * 1024 * 1024;
 
        WARN_ON(num_bytes < root->sectorsize);
        btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY);
 
+       if (data & BTRFS_BLOCK_GROUP_METADATA) {
+               last_ptr = &root->fs_info->last_alloc;
+       }
+
+       if ((data & BTRFS_BLOCK_GROUP_DATA) && btrfs_test_opt(root, SSD)) {
+               last_ptr = &root->fs_info->last_data_alloc;
+       }
+
+       if (last_ptr) {
+               if (*last_ptr)
+                       hint_byte = *last_ptr;
+               else {
+                       empty_size += empty_cluster;
+               }
+       }
+
        if (search_end == (u64)-1)
                search_end = btrfs_super_total_bytes(&info->super_copy);
 
@@ -1489,11 +1507,14 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
                        hint_byte = search_start;
                block_group = btrfs_find_block_group(root, block_group,
                                                     hint_byte, data, 1);
+               if (last_ptr && *last_ptr == 0 && block_group)
+                       hint_byte = block_group->key.objectid;
        } else {
                block_group = btrfs_find_block_group(root,
                                                     trans->block_group,
                                                     search_start, data, 1);
        }
+       search_start = max(search_start, hint_byte);
 
        total_needed += empty_size;
 
@@ -1506,9 +1527,36 @@ check_failed:
        }
        ret = find_search_start(root, &block_group, &search_start,
                                total_needed, data);
+       if (ret == -ENOSPC && last_ptr && *last_ptr) {
+               *last_ptr = 0;
+               block_group = btrfs_lookup_block_group(info,
+                                                      orig_search_start);
+               search_start = orig_search_start;
+               ret = find_search_start(root, &block_group, &search_start,
+                                       total_needed, data);
+       }
+       if (ret == -ENOSPC)
+               goto enospc;
        if (ret)
                goto error;
 
+       if (last_ptr && *last_ptr && search_start != *last_ptr) {
+               *last_ptr = 0;
+               if (!empty_size) {
+                       empty_size += empty_cluster;
+                       total_needed += empty_size;
+               }
+               block_group = btrfs_lookup_block_group(info,
+                                                      orig_search_start);
+               search_start = orig_search_start;
+               ret = find_search_start(root, &block_group,
+                                       &search_start, total_needed, data);
+               if (ret == -ENOSPC)
+                       goto enospc;
+               if (ret)
+                       goto error;
+       }
+
        search_start = stripe_align(root, search_start);
        ins->objectid = search_start;
        ins->offset = num_bytes;
@@ -1547,6 +1595,13 @@ check_failed:
                        trans->block_group = block_group;
        }
        ins->offset = num_bytes;
+       if (last_ptr) {
+               *last_ptr = ins->objectid + ins->offset;
+               if (*last_ptr ==
+                   btrfs_super_total_bytes(&root->fs_info->super_copy)) {
+                       *last_ptr = 0;
+               }
+       }
        return 0;
 
 new_group:
@@ -1612,12 +1667,12 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
        if (root->ref_cows) {
                if (data != BTRFS_BLOCK_GROUP_METADATA) {
                        ret = do_chunk_alloc(trans, root->fs_info->extent_root,
-                                            num_bytes,
+                                            2 * 1024 * 1024,
                                             BTRFS_BLOCK_GROUP_METADATA);
                        BUG_ON(ret);
                }
                ret = do_chunk_alloc(trans, root->fs_info->extent_root,
-                                    num_bytes, data);
+                                    num_bytes + 2 * 1024 * 1024, data);
                BUG_ON(ret);
        }