@@ -1170,7 +1170,7 @@ static void handle_io_error(struct vdo_completion *completion)
1170
1170
1171
1171
vio_record_metadata_io_error (vio );
1172
1172
return_vio_to_pool (vio_as_pooled_vio (vio ));
1173
- slab -> active_count -- ;
1173
+ slab -> active_count -= vio -> io_size / VDO_BLOCK_SIZE ;
1174
1174
vdo_enter_read_only_mode (slab -> allocator -> depot -> vdo , result );
1175
1175
check_if_slab_drained (slab );
1176
1176
}
@@ -2239,13 +2239,20 @@ static void finish_reference_block_load(struct vdo_completion *completion)
2239
2239
struct pooled_vio * pooled = vio_as_pooled_vio (vio );
2240
2240
struct reference_block * block = completion -> parent ;
2241
2241
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 ;
2242
2248
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
+ }
2244
2253
return_vio_to_pool (pooled );
2245
- slab -> active_count -- ;
2246
- clear_provisional_references (block );
2254
+ slab -> active_count -= block_count ;
2247
2255
2248
- slab -> free_blocks -= block -> allocated_count ;
2249
2256
check_if_slab_drained (slab );
2250
2257
}
2251
2258
@@ -2259,23 +2266,25 @@ static void load_reference_block_endio(struct bio *bio)
2259
2266
}
2260
2267
2261
2268
/**
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.
2265
2272
* @context: The VIO returned by the pool.
2266
2273
*/
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 )
2268
2275
{
2269
2276
struct pooled_vio * pooled = context ;
2270
2277
struct vio * vio = & pooled -> vio ;
2271
2278
struct reference_block * block =
2272
2279
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 );
2274
2283
2275
2284
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 );
2279
2288
}
2280
2289
2281
2290
/**
@@ -2285,14 +2294,21 @@ static void load_reference_block(struct vdo_waiter *waiter, void *context)
2285
2294
static void load_reference_blocks (struct vdo_slab * slab )
2286
2295
{
2287
2296
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
+ }
2288
2304
2289
2305
slab -> free_blocks = slab -> block_count ;
2290
2306
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 ) {
2292
2308
struct vdo_waiter * waiter = & slab -> reference_blocks [i ].waiter ;
2293
2309
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 );
2296
2312
}
2297
2313
}
2298
2314
@@ -2699,6 +2715,7 @@ static void finish_scrubbing(struct slab_scrubber *scrubber, int result)
2699
2715
vdo_log_info ("VDO commencing normal operation" );
2700
2716
else if (prior_state == VDO_RECOVERING )
2701
2717
vdo_log_info ("Exiting recovery mode" );
2718
+ free_vio_pool (vdo_forget (allocator -> refcount_big_vio_pool ));
2702
2719
}
2703
2720
2704
2721
/*
@@ -3982,6 +3999,7 @@ static int __must_check initialize_block_allocator(struct slab_depot *depot,
3982
3999
struct vdo * vdo = depot -> vdo ;
3983
4000
block_count_t max_free_blocks = depot -> slab_config .data_blocks ;
3984
4001
unsigned int max_priority = (2 + ilog2 (max_free_blocks ));
4002
+ u32 reference_block_count , refcount_reads_needed , refcount_blocks_per_vio ;
3985
4003
3986
4004
* allocator = (struct block_allocator ) {
3987
4005
.depot = depot ,
@@ -4005,6 +4023,18 @@ static int __must_check initialize_block_allocator(struct slab_depot *depot,
4005
4023
if (result != VDO_SUCCESS )
4006
4024
return result ;
4007
4025
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
+
4008
4038
result = initialize_slab_scrubber (allocator );
4009
4039
if (result != VDO_SUCCESS )
4010
4040
return result ;
@@ -4222,6 +4252,7 @@ void vdo_free_slab_depot(struct slab_depot *depot)
4222
4252
uninitialize_allocator_summary (allocator );
4223
4253
uninitialize_scrubber_vio (& allocator -> scrubber );
4224
4254
free_vio_pool (vdo_forget (allocator -> vio_pool ));
4255
+ free_vio_pool (vdo_forget (allocator -> refcount_big_vio_pool ));
4225
4256
vdo_free_priority_table (vdo_forget (allocator -> prioritized_slabs ));
4226
4257
}
4227
4258
0 commit comments