mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-11 06:00:55 -04:00
btrfs: scrub: reduce memory usage of struct scrub_sector_verification
That structure records needed info for block verification (either data checksum pointer, or expected tree block generation). But there is also a boolean to tell if this block belongs to a metadata or not, as the data checksum pointer and expected tree block generation is already a union, we need a dedicated bit to tell if this block is a metadata or not. However such layout means we're wasting 63 bits for x86_64, which is a huge memory waste. Thanks to the recent bitmap aggregation, we can easily move this single-bit-per-block member to a new sub-bitmap. And since we already have six 16 bits long bitmaps, adding another bitmap won't even increase any memory usage for x86_64, as we need two 64 bits long anyway. This will reduce the following memory usages: - sizeof(struct scrub_sector_verification) From 16 bytes to 8 bytes on x86_64. - scrub_stripe::sectors From 16 * 16 to 16 * 8 bytes. - Per-device scrub_ctx memory usage From 128 * (16 * 16) to 128 * (16 * 8), which saves 16KiB memory. Reviewed-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
@@ -66,8 +66,6 @@ struct scrub_ctx;
|
||||
|
||||
/* Represent one sector and its needed info to verify the content. */
|
||||
struct scrub_sector_verification {
|
||||
bool is_metadata;
|
||||
|
||||
union {
|
||||
/*
|
||||
* Csum pointer for data csum verification. Should point to a
|
||||
@@ -115,6 +113,9 @@ enum {
|
||||
/* Which blocks are covered by extent items. */
|
||||
scrub_bitmap_nr_has_extent = 0,
|
||||
|
||||
/* Which blocks are meteadata. */
|
||||
scrub_bitmap_nr_is_metadata,
|
||||
|
||||
/*
|
||||
* Which blocks have errors, including IO, csum, and metadata
|
||||
* errors.
|
||||
@@ -304,6 +305,7 @@ static inline unsigned int scrub_bitmap_weight_##name(struct scrub_stripe *strip
|
||||
return bitmap_weight(&bitmap, stripe->nr_sectors); \
|
||||
}
|
||||
IMPLEMENT_SCRUB_BITMAP_OPS(has_extent);
|
||||
IMPLEMENT_SCRUB_BITMAP_OPS(is_metadata);
|
||||
IMPLEMENT_SCRUB_BITMAP_OPS(error);
|
||||
IMPLEMENT_SCRUB_BITMAP_OPS(io_error);
|
||||
IMPLEMENT_SCRUB_BITMAP_OPS(csum_error);
|
||||
@@ -801,7 +803,7 @@ static void scrub_verify_one_sector(struct scrub_stripe *stripe, int sector_nr)
|
||||
return;
|
||||
|
||||
/* Metadata, verify the full tree block. */
|
||||
if (sector->is_metadata) {
|
||||
if (scrub_bitmap_test_bit_is_metadata(stripe, sector_nr)) {
|
||||
/*
|
||||
* Check if the tree block crosses the stripe boundary. If
|
||||
* crossed the boundary, we cannot verify it but only give a
|
||||
@@ -850,7 +852,7 @@ static void scrub_verify_one_stripe(struct scrub_stripe *stripe, unsigned long b
|
||||
|
||||
for_each_set_bit(sector_nr, &bitmap, stripe->nr_sectors) {
|
||||
scrub_verify_one_sector(stripe, sector_nr);
|
||||
if (stripe->sectors[sector_nr].is_metadata)
|
||||
if (scrub_bitmap_test_bit_is_metadata(stripe, sector_nr))
|
||||
sector_nr += sectors_per_tree - 1;
|
||||
}
|
||||
}
|
||||
@@ -1019,7 +1021,7 @@ static void scrub_stripe_report_errors(struct scrub_ctx *sctx,
|
||||
for_each_set_bit(sector_nr, &extent_bitmap, stripe->nr_sectors) {
|
||||
bool repaired = false;
|
||||
|
||||
if (stripe->sectors[sector_nr].is_metadata) {
|
||||
if (scrub_bitmap_test_bit_is_metadata(stripe, sector_nr)) {
|
||||
nr_meta_sectors++;
|
||||
} else {
|
||||
nr_data_sectors++;
|
||||
@@ -1616,7 +1618,7 @@ static void fill_one_extent_info(struct btrfs_fs_info *fs_info,
|
||||
|
||||
scrub_bitmap_set_bit_has_extent(stripe, nr_sector);
|
||||
if (extent_flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) {
|
||||
sector->is_metadata = true;
|
||||
scrub_bitmap_set_bit_is_metadata(stripe, nr_sector);
|
||||
sector->generation = extent_gen;
|
||||
}
|
||||
}
|
||||
@@ -1760,7 +1762,6 @@ static void scrub_reset_stripe(struct scrub_stripe *stripe)
|
||||
stripe->state = 0;
|
||||
|
||||
for (int i = 0; i < stripe->nr_sectors; i++) {
|
||||
stripe->sectors[i].is_metadata = false;
|
||||
stripe->sectors[i].csum = NULL;
|
||||
stripe->sectors[i].generation = 0;
|
||||
}
|
||||
@@ -1902,7 +1903,7 @@ static bool stripe_has_metadata_error(struct scrub_stripe *stripe)
|
||||
int i;
|
||||
|
||||
for_each_set_bit(i, &error, stripe->nr_sectors) {
|
||||
if (stripe->sectors[i].is_metadata) {
|
||||
if (scrub_bitmap_test_bit_is_metadata(stripe, i)) {
|
||||
struct btrfs_fs_info *fs_info = stripe->bg->fs_info;
|
||||
|
||||
btrfs_err(fs_info,
|
||||
|
||||
Reference in New Issue
Block a user