@@ -1170,7 +1170,7 @@ static void handle_io_error(struct vdo_completion *completion)
11701170
11711171 vio_record_metadata_io_error (vio );
11721172 return_vio_to_pool (vio_as_pooled_vio (vio ));
1173- slab -> active_count -- ;
1173+ slab -> active_count -= vio -> io_size / VDO_BLOCK_SIZE ;
11741174 vdo_enter_read_only_mode (slab -> allocator -> depot -> vdo , result );
11751175 check_if_slab_drained (slab );
11761176}
@@ -2239,13 +2239,20 @@ static void finish_reference_block_load(struct vdo_completion *completion)
22392239 struct pooled_vio * pooled = vio_as_pooled_vio (vio );
22402240 struct reference_block * block = completion -> parent ;
22412241 struct vdo_slab * slab = block -> slab ;
2242+ unsigned int block_count = vio -> io_size / VDO_BLOCK_SIZE ;
2243+ unsigned int i ;
2244+ char * data = vio -> data ;
2245+
2246+ for (i = 0 ; i < block_count ; i ++ , block ++ , data += VDO_BLOCK_SIZE ) {
2247+ struct packed_reference_block * packed = (struct packed_reference_block * ) data ;
22422248
2243- unpack_reference_block ((struct packed_reference_block * ) vio -> data , block );
2249+ unpack_reference_block (packed , block );
2250+ clear_provisional_references (block );
2251+ slab -> free_blocks -= block -> allocated_count ;
2252+ }
22442253 return_vio_to_pool (pooled );
2245- slab -> active_count -- ;
2246- clear_provisional_references (block );
2254+ slab -> active_count -= block_count ;
22472255
2248- slab -> free_blocks -= block -> allocated_count ;
22492256 check_if_slab_drained (slab );
22502257}
22512258
@@ -2259,23 +2266,25 @@ static void load_reference_block_endio(struct bio *bio)
22592266}
22602267
22612268/**
2262- * load_reference_block () - After a block waiter has gotten a VIO from the VIO pool, load the
2263- * block .
2264- * @waiter: The waiter of the block to load.
2269+ * load_reference_block_group () - After a block waiter has gotten a VIO from the VIO pool, load
2270+ * a set of blocks .
2271+ * @waiter: The waiter of the first block to load.
22652272 * @context: The VIO returned by the pool.
22662273 */
2267- static void load_reference_block (struct vdo_waiter * waiter , void * context )
2274+ static void load_reference_block_group (struct vdo_waiter * waiter , void * context )
22682275{
22692276 struct pooled_vio * pooled = context ;
22702277 struct vio * vio = & pooled -> vio ;
22712278 struct reference_block * block =
22722279 container_of (waiter , struct reference_block , waiter );
2273- size_t block_offset = (block - block -> slab -> reference_blocks );
2280+ u32 block_offset = block - block -> slab -> reference_blocks ;
2281+ u32 max_block_count = block -> slab -> reference_block_count - block_offset ;
2282+ u32 block_count = min_t (int , vio -> block_count , max_block_count );
22742283
22752284 vio -> completion .parent = block ;
2276- vdo_submit_metadata_vio (vio , block -> slab -> ref_counts_origin + block_offset ,
2277- load_reference_block_endio , handle_io_error ,
2278- REQ_OP_READ );
2285+ vdo_submit_metadata_vio_with_size (vio , block -> slab -> ref_counts_origin + block_offset ,
2286+ load_reference_block_endio , handle_io_error ,
2287+ REQ_OP_READ , block_count * VDO_BLOCK_SIZE );
22792288}
22802289
22812290/**
@@ -2285,14 +2294,21 @@ static void load_reference_block(struct vdo_waiter *waiter, void *context)
22852294static void load_reference_blocks (struct vdo_slab * slab )
22862295{
22872296 block_count_t i ;
2297+ u64 blocks_per_vio = slab -> allocator -> refcount_blocks_per_big_vio ;
2298+ struct vio_pool * pool = slab -> allocator -> refcount_big_vio_pool ;
2299+
2300+ if (!pool ) {
2301+ pool = slab -> allocator -> vio_pool ;
2302+ blocks_per_vio = 1 ;
2303+ }
22882304
22892305 slab -> free_blocks = slab -> block_count ;
22902306 slab -> active_count = slab -> reference_block_count ;
2291- for (i = 0 ; i < slab -> reference_block_count ; i ++ ) {
2307+ for (i = 0 ; i < slab -> reference_block_count ; i += blocks_per_vio ) {
22922308 struct vdo_waiter * waiter = & slab -> reference_blocks [i ].waiter ;
22932309
2294- waiter -> callback = load_reference_block ;
2295- acquire_vio_from_pool (slab -> allocator -> vio_pool , waiter );
2310+ waiter -> callback = load_reference_block_group ;
2311+ acquire_vio_from_pool (pool , waiter );
22962312 }
22972313}
22982314
@@ -2699,6 +2715,7 @@ static void finish_scrubbing(struct slab_scrubber *scrubber, int result)
26992715 vdo_log_info ("VDO commencing normal operation" );
27002716 else if (prior_state == VDO_RECOVERING )
27012717 vdo_log_info ("Exiting recovery mode" );
2718+ free_vio_pool (vdo_forget (allocator -> refcount_big_vio_pool ));
27022719 }
27032720
27042721 /*
@@ -3982,6 +3999,7 @@ static int __must_check initialize_block_allocator(struct slab_depot *depot,
39823999 struct vdo * vdo = depot -> vdo ;
39834000 block_count_t max_free_blocks = depot -> slab_config .data_blocks ;
39844001 unsigned int max_priority = (2 + ilog2 (max_free_blocks ));
4002+ u32 reference_block_count , refcount_reads_needed , refcount_blocks_per_vio ;
39854003
39864004 * allocator = (struct block_allocator ) {
39874005 .depot = depot ,
@@ -4005,6 +4023,18 @@ static int __must_check initialize_block_allocator(struct slab_depot *depot,
40054023 if (result != VDO_SUCCESS )
40064024 return result ;
40074025
4026+ /* Initialize the refcount-reading vio pool. */
4027+ reference_block_count = vdo_get_saved_reference_count_size (depot -> slab_config .slab_blocks );
4028+ refcount_reads_needed = DIV_ROUND_UP (reference_block_count , MAX_BLOCKS_PER_VIO );
4029+ refcount_blocks_per_vio = DIV_ROUND_UP (reference_block_count , refcount_reads_needed );
4030+ allocator -> refcount_blocks_per_big_vio = refcount_blocks_per_vio ;
4031+ result = make_vio_pool (vdo , BLOCK_ALLOCATOR_REFCOUNT_VIO_POOL_SIZE ,
4032+ allocator -> refcount_blocks_per_big_vio , allocator -> thread_id ,
4033+ VIO_TYPE_SLAB_JOURNAL , VIO_PRIORITY_METADATA ,
4034+ NULL , & allocator -> refcount_big_vio_pool );
4035+ if (result != VDO_SUCCESS )
4036+ return result ;
4037+
40084038 result = initialize_slab_scrubber (allocator );
40094039 if (result != VDO_SUCCESS )
40104040 return result ;
@@ -4222,6 +4252,7 @@ void vdo_free_slab_depot(struct slab_depot *depot)
42224252 uninitialize_allocator_summary (allocator );
42234253 uninitialize_scrubber_vio (& allocator -> scrubber );
42244254 free_vio_pool (vdo_forget (allocator -> vio_pool ));
4255+ free_vio_pool (vdo_forget (allocator -> refcount_big_vio_pool ));
42254256 vdo_free_priority_table (vdo_forget (allocator -> prioritized_slabs ));
42264257 }
42274258
0 commit comments