Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dm persistent metadata: add space map threshold callback

Add a threshold callback to dm persistent data space maps.

Signed-off-by: Joe Thornber <ejt@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>

authored by

Joe Thornber and committed by
Alasdair G Kergon
2fc48021 7c3d3f2a

+76 -1
+76 -1
drivers/md/persistent-data/dm-space-map-metadata.c
··· 17 17 /*----------------------------------------------------------------*/ 18 18 19 19 /* 20 + * An edge triggered threshold. 21 + */ 22 + struct threshold { 23 + bool threshold_set; 24 + bool value_set; 25 + dm_block_t threshold; 26 + dm_block_t current_value; 27 + dm_sm_threshold_fn fn; 28 + void *context; 29 + }; 30 + 31 + static void threshold_init(struct threshold *t) 32 + { 33 + t->threshold_set = false; 34 + t->value_set = false; 35 + } 36 + 37 + static void set_threshold(struct threshold *t, dm_block_t value, 38 + dm_sm_threshold_fn fn, void *context) 39 + { 40 + t->threshold_set = true; 41 + t->threshold = value; 42 + t->fn = fn; 43 + t->context = context; 44 + } 45 + 46 + static bool below_threshold(struct threshold *t, dm_block_t value) 47 + { 48 + return t->threshold_set && value <= t->threshold; 49 + } 50 + 51 + static bool threshold_already_triggered(struct threshold *t) 52 + { 53 + return t->value_set && below_threshold(t, t->current_value); 54 + } 55 + 56 + static void check_threshold(struct threshold *t, dm_block_t value) 57 + { 58 + if (below_threshold(t, value) && 59 + !threshold_already_triggered(t)) 60 + t->fn(t->context); 61 + 62 + t->value_set = true; 63 + t->current_value = value; 64 + } 65 + 66 + /*----------------------------------------------------------------*/ 67 + 68 + /* 20 69 * Space map interface. 21 70 * 22 71 * The low level disk format is written using the standard btree and ··· 103 54 unsigned allocated_this_transaction; 104 55 unsigned nr_uncommitted; 105 56 struct block_op uncommitted[MAX_RECURSIVE_ALLOCATIONS]; 57 + 58 + struct threshold threshold; 106 59 }; 107 60 108 61 static int add_bop(struct sm_metadata *smm, enum block_op_type type, dm_block_t b) ··· 380 329 381 330 static int sm_metadata_new_block(struct dm_space_map *sm, dm_block_t *b) 382 331 { 332 + dm_block_t count; 333 + struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); 334 + 383 335 int r = sm_metadata_new_block_(sm, b); 384 336 if (r) 385 337 DMERR("unable to allocate new metadata block"); 338 + 339 + r = sm_metadata_get_nr_free(sm, &count); 340 + if (r) 341 + DMERR("couldn't get free block count"); 342 + 343 + check_threshold(&smm->threshold, count); 344 + 386 345 return r; 387 346 } 388 347 ··· 408 347 memcpy(&smm->old_ll, &smm->ll, sizeof(smm->old_ll)); 409 348 smm->begin = 0; 410 349 smm->allocated_this_transaction = 0; 350 + 351 + return 0; 352 + } 353 + 354 + static int sm_metadata_register_threshold_callback(struct dm_space_map *sm, 355 + dm_block_t threshold, 356 + dm_sm_threshold_fn fn, 357 + void *context) 358 + { 359 + struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); 360 + 361 + set_threshold(&smm->threshold, threshold, fn, context); 411 362 412 363 return 0; 413 364 } ··· 465 392 .commit = sm_metadata_commit, 466 393 .root_size = sm_metadata_root_size, 467 394 .copy_root = sm_metadata_copy_root, 468 - .register_threshold_callback = NULL 395 + .register_threshold_callback = sm_metadata_register_threshold_callback 469 396 }; 470 397 471 398 /*----------------------------------------------------------------*/ ··· 650 577 smm->recursion_count = 0; 651 578 smm->allocated_this_transaction = 0; 652 579 smm->nr_uncommitted = 0; 580 + threshold_init(&smm->threshold); 653 581 654 582 memcpy(&smm->sm, &bootstrap_ops, sizeof(smm->sm)); 655 583 ··· 692 618 smm->recursion_count = 0; 693 619 smm->allocated_this_transaction = 0; 694 620 smm->nr_uncommitted = 0; 621 + threshold_init(&smm->threshold); 695 622 696 623 memcpy(&smm->old_ll, &smm->ll, sizeof(smm->old_ll)); 697 624 return 0;