]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-client.git/commitdiff
btrfs: update per-profile available estimation
authorQu Wenruo <wqu@suse.com>
Wed, 4 Feb 2026 02:54:07 +0000 (13:24 +1030)
committerDavid Sterba <dsterba@suse.com>
Tue, 7 Apr 2026 16:55:53 +0000 (18:55 +0200)
This involves the following timing:

- Chunk allocation
- Chunk removal
- After Mount
- New device
- Device removal
- Device shrink
- Device enlarge

And since the function btrfs_update_per_profile_avail() will not return
an error, this won't cause new error handling path.

Although when btrfs_update_per_profile_avail() failed (only ENOSPC
possible) it will mark the per-profile available estimation as
unreliable, so later btrfs_get_per_profile_avail() will return false and
require the caller to have a fallback solution.

The function btrfs_update_per_profile_avail() will be executed with
chunk_mutex hold, thus it will slightly slow down those involved
functions, but not a lot.

As all the core workload is just various u64 calculations inside a loop,
without any tree search, the overhead should be acceptable even for all
supported 9 profiles.

For 4 disks (which exercises all 9 profiles), the execution time of that
function will still be less than 10 us.

Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/volumes.c

index 9eb07f48cf827e235041165ae8c0c3263ca4b8fa..62e02cc1efc93261f83a0cb171821408e9f00f53 100644 (file)
@@ -2340,6 +2340,7 @@ int btrfs_rm_device(struct btrfs_fs_info *fs_info,
                mutex_lock(&fs_info->chunk_mutex);
                list_del_init(&device->dev_alloc_list);
                device->fs_devices->rw_devices--;
+               btrfs_update_per_profile_avail(fs_info);
                mutex_unlock(&fs_info->chunk_mutex);
        }
 
@@ -2451,6 +2452,7 @@ error_undo:
                list_add(&device->dev_alloc_list,
                         &fs_devices->alloc_list);
                device->fs_devices->rw_devices++;
+               btrfs_update_per_profile_avail(fs_info);
                mutex_unlock(&fs_info->chunk_mutex);
        }
        return ret;
@@ -2938,6 +2940,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
         */
        btrfs_clear_space_info_full(fs_info);
 
+       btrfs_update_per_profile_avail(fs_info);
        mutex_unlock(&fs_info->chunk_mutex);
 
        /* Add sysfs device entry */
@@ -2948,6 +2951,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
        if (seeding_dev) {
                mutex_lock(&fs_info->chunk_mutex);
                ret = init_first_rw_device(trans);
+               btrfs_update_per_profile_avail(fs_info);
                mutex_unlock(&fs_info->chunk_mutex);
                if (unlikely(ret)) {
                        btrfs_abort_transaction(trans, ret);
@@ -3030,6 +3034,7 @@ error_sysfs:
                                    orig_super_total_bytes);
        btrfs_set_super_num_devices(fs_info->super_copy,
                                    orig_super_num_devices);
+       btrfs_update_per_profile_avail(fs_info);
        mutex_unlock(&fs_info->chunk_mutex);
        mutex_unlock(&fs_info->fs_devices->device_list_mutex);
 error_trans:
@@ -3122,6 +3127,7 @@ int btrfs_grow_device(struct btrfs_trans_handle *trans,
        if (list_empty(&device->post_commit_list))
                list_add_tail(&device->post_commit_list,
                              &trans->transaction->dev_update_list);
+       btrfs_update_per_profile_avail(fs_info);
        mutex_unlock(&fs_info->chunk_mutex);
 
        btrfs_reserve_chunk_metadata(trans, false);
@@ -3498,6 +3504,7 @@ int btrfs_remove_chunk(struct btrfs_trans_handle *trans, u64 chunk_offset)
                }
        }
 
+       btrfs_update_per_profile_avail(fs_info);
        mutex_unlock(&fs_info->chunk_mutex);
        trans->removing_chunk = false;
 
@@ -5201,6 +5208,7 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size)
                atomic64_sub(free_diff, &fs_info->free_chunk_space);
        }
 
+       btrfs_update_per_profile_avail(fs_info);
        /*
         * Once the device's size has been set to the new size, ensure all
         * in-memory chunks are synced to disk so that the loop below sees them
@@ -5316,6 +5324,7 @@ again:
        WARN_ON(diff > old_total);
        btrfs_set_super_total_bytes(super_copy,
                        round_down(old_total - diff, fs_info->sectorsize));
+       btrfs_update_per_profile_avail(fs_info);
        mutex_unlock(&fs_info->chunk_mutex);
 
        btrfs_reserve_chunk_metadata(trans, false);
@@ -6028,6 +6037,8 @@ static struct btrfs_block_group *create_chunk(struct btrfs_trans_handle *trans,
        check_raid56_incompat_flag(info, type);
        check_raid1c34_incompat_flag(info, type);
 
+       btrfs_update_per_profile_avail(info);
+
        return block_group;
 }
 
@@ -8603,7 +8614,14 @@ int btrfs_verify_dev_extents(struct btrfs_fs_info *fs_info)
        }
 
        /* Ensure all chunks have corresponding dev extents */
-       return verify_chunk_dev_extent_mapping(fs_info);
+       ret = verify_chunk_dev_extent_mapping(fs_info);
+       if (ret < 0)
+               return ret;
+
+       mutex_lock(&fs_info->chunk_mutex);
+       btrfs_update_per_profile_avail(fs_info);
+       mutex_unlock(&fs_info->chunk_mutex);
+       return 0;
 }
 
 /*