From 8fc6d57d41668adb3e02444885317ca429fd8ff9 Mon Sep 17 00:00:00 2001 From: Tomohiro Kusumi Date: Thu, 22 Jan 2015 00:14:10 +0900 Subject: [PATCH] sbin/newfs_hammer: optimize blockmap initialization loop This patch optimizes blockmap initialization loop of freemap zone by newfs_hammer command. newfs_hammer does not need to read (either actually read(2) or get cached malloc(3)ed buffer) layer 1 structure everytime within the loop while filling in layer 2 structure. The layer 1 that covers current phys_offset needs to be updated only when layer 1 bits of phys_offset has changed. In other words, phys_offset changes within lower 42 bits (lower 4TB address space) do not affect the layer 1, and newfs_hammer can reuse (keep the pointer of) the buffer until phys_offset reaches to the next layer 1 given that the buffer does not get released while running in this loop. This reduces reading layer 1 approximately from (size_of_volume / 8MB + 1) times to (size_of_volume / 4TB + 1) times. For exammple, if the volume size is < 4TB it reads layer 1 only once for that volume which is good enough as a single layer 1 structure covers 4TB of address space. --- sbin/hammer/ondisk.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/sbin/hammer/ondisk.c b/sbin/hammer/ondisk.c index 936db7e..c65b5eb 100644 --- a/sbin/hammer/ondisk.c +++ b/sbin/hammer/ondisk.c @@ -480,8 +480,8 @@ initialize_freemap(struct volume_info *vol) struct volume_info *root_vol; struct buffer_info *buffer1 = NULL; struct buffer_info *buffer2 = NULL; - struct hammer_blockmap_layer1 *layer1; - struct hammer_blockmap_layer2 *layer2; + struct hammer_blockmap_layer1 *layer1 = NULL; + struct hammer_blockmap_layer2 *layer2 = NULL; hammer_off_t layer1_base; hammer_off_t layer1_offset; hammer_off_t layer2_offset; @@ -526,11 +526,16 @@ initialize_freemap(struct volume_info *vol) phys_offset < aligned_vol_free_end; phys_offset += HAMMER_LARGEBLOCK_SIZE) { modified1 = 0; - layer1_offset = layer1_base + - HAMMER_BLOCKMAP_LAYER1_OFFSET(phys_offset); - layer1 = get_buffer_data(layer1_offset, &buffer1, 0); + /* + * Get layer 1 when moving on to the next layer 1 + */ + if ((phys_offset % HAMMER_BLOCKMAP_LAYER2) == 0) { + layer1_offset = layer1_base + + HAMMER_BLOCKMAP_LAYER1_OFFSET(phys_offset); + layer1 = get_buffer_data(layer1_offset, &buffer1, 0); + } - assert(layer1->phys_offset != HAMMER_BLOCKMAP_UNAVAIL); + assert(layer1 && layer1->phys_offset != HAMMER_BLOCKMAP_UNAVAIL); layer2_offset = layer1->phys_offset + HAMMER_BLOCKMAP_LAYER2_OFFSET(phys_offset); -- 2.1.2