diff options
| author | Joe Thornber <ejt@redhat.com> | 2013-05-10 09:37:20 -0400 |
|---|---|---|
| committer | Alasdair G Kergon <agk@redhat.com> | 2013-05-10 09:37:20 -0400 |
| commit | 2fc48021f4afdd109b9e52b6eef5db89ca80bac7 (patch) | |
| tree | 38ee98f1a8fb8ca377822c01e34554fe0befd30a /drivers/md/persistent-data | |
| parent | 7c3d3f2a87b01ff167a5f048285d5e3dee920235 (diff) | |
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>
Diffstat (limited to 'drivers/md/persistent-data')
| -rw-r--r-- | drivers/md/persistent-data/dm-space-map-metadata.c | 77 |
1 files changed, 76 insertions, 1 deletions
diff --git a/drivers/md/persistent-data/dm-space-map-metadata.c b/drivers/md/persistent-data/dm-space-map-metadata.c index 883b465794d4..1c959684caef 100644 --- a/drivers/md/persistent-data/dm-space-map-metadata.c +++ b/drivers/md/persistent-data/dm-space-map-metadata.c | |||
| @@ -17,6 +17,55 @@ | |||
| 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 | * Space map interface. | 69 | * Space map interface. |
| 21 | * | 70 | * |
| 22 | * The low level disk format is written using the standard btree and | 71 | * The low level disk format is written using the standard btree and |
| @@ -54,6 +103,8 @@ struct sm_metadata { | |||
| 54 | unsigned allocated_this_transaction; | 103 | unsigned allocated_this_transaction; |
| 55 | unsigned nr_uncommitted; | 104 | unsigned nr_uncommitted; |
| 56 | struct block_op uncommitted[MAX_RECURSIVE_ALLOCATIONS]; | 105 | struct block_op uncommitted[MAX_RECURSIVE_ALLOCATIONS]; |
| 106 | |||
| 107 | struct threshold threshold; | ||
| 57 | }; | 108 | }; |
| 58 | 109 | ||
| 59 | static int add_bop(struct sm_metadata *smm, enum block_op_type type, dm_block_t b) | 110 | static int add_bop(struct sm_metadata *smm, enum block_op_type type, dm_block_t b) |
| @@ -329,9 +380,19 @@ static int sm_metadata_new_block_(struct dm_space_map *sm, dm_block_t *b) | |||
| 329 | 380 | ||
| 330 | static int sm_metadata_new_block(struct dm_space_map *sm, dm_block_t *b) | 381 | static int sm_metadata_new_block(struct dm_space_map *sm, dm_block_t *b) |
| 331 | { | 382 | { |
| 383 | dm_block_t count; | ||
| 384 | struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); | ||
| 385 | |||
| 332 | int r = sm_metadata_new_block_(sm, b); | 386 | int r = sm_metadata_new_block_(sm, b); |
| 333 | if (r) | 387 | if (r) |
| 334 | DMERR("unable to allocate new metadata block"); | 388 | DMERR("unable to allocate new metadata block"); |
| 389 | |||
| 390 | r = sm_metadata_get_nr_free(sm, &count); | ||
| 391 | if (r) | ||
| 392 | DMERR("couldn't get free block count"); | ||
| 393 | |||
| 394 | check_threshold(&smm->threshold, count); | ||
| 395 | |||
| 335 | return r; | 396 | return r; |
| 336 | } | 397 | } |
| 337 | 398 | ||
| @@ -351,6 +412,18 @@ static int sm_metadata_commit(struct dm_space_map *sm) | |||
| 351 | return 0; | 412 | return 0; |
| 352 | } | 413 | } |
| 353 | 414 | ||
| 415 | static int sm_metadata_register_threshold_callback(struct dm_space_map *sm, | ||
| 416 | dm_block_t threshold, | ||
| 417 | dm_sm_threshold_fn fn, | ||
| 418 | void *context) | ||
| 419 | { | ||
| 420 | struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); | ||
| 421 | |||
| 422 | set_threshold(&smm->threshold, threshold, fn, context); | ||
| 423 | |||
| 424 | return 0; | ||
| 425 | } | ||
| 426 | |||
| 354 | static int sm_metadata_root_size(struct dm_space_map *sm, size_t *result) | 427 | static int sm_metadata_root_size(struct dm_space_map *sm, size_t *result) |
| 355 | { | 428 | { |
| 356 | *result = sizeof(struct disk_sm_root); | 429 | *result = sizeof(struct disk_sm_root); |
| @@ -392,7 +465,7 @@ static struct dm_space_map ops = { | |||
| 392 | .commit = sm_metadata_commit, | 465 | .commit = sm_metadata_commit, |
| 393 | .root_size = sm_metadata_root_size, | 466 | .root_size = sm_metadata_root_size, |
| 394 | .copy_root = sm_metadata_copy_root, | 467 | .copy_root = sm_metadata_copy_root, |
| 395 | .register_threshold_callback = NULL | 468 | .register_threshold_callback = sm_metadata_register_threshold_callback |
| 396 | }; | 469 | }; |
| 397 | 470 | ||
| 398 | /*----------------------------------------------------------------*/ | 471 | /*----------------------------------------------------------------*/ |
| @@ -577,6 +650,7 @@ int dm_sm_metadata_create(struct dm_space_map *sm, | |||
| 577 | smm->recursion_count = 0; | 650 | smm->recursion_count = 0; |
| 578 | smm->allocated_this_transaction = 0; | 651 | smm->allocated_this_transaction = 0; |
| 579 | smm->nr_uncommitted = 0; | 652 | smm->nr_uncommitted = 0; |
| 653 | threshold_init(&smm->threshold); | ||
| 580 | 654 | ||
| 581 | memcpy(&smm->sm, &bootstrap_ops, sizeof(smm->sm)); | 655 | memcpy(&smm->sm, &bootstrap_ops, sizeof(smm->sm)); |
| 582 | 656 | ||
| @@ -618,6 +692,7 @@ int dm_sm_metadata_open(struct dm_space_map *sm, | |||
| 618 | smm->recursion_count = 0; | 692 | smm->recursion_count = 0; |
| 619 | smm->allocated_this_transaction = 0; | 693 | smm->allocated_this_transaction = 0; |
| 620 | smm->nr_uncommitted = 0; | 694 | smm->nr_uncommitted = 0; |
| 695 | threshold_init(&smm->threshold); | ||
| 621 | 696 | ||
| 622 | memcpy(&smm->old_ll, &smm->ll, sizeof(smm->old_ll)); | 697 | memcpy(&smm->old_ll, &smm->ll, sizeof(smm->old_ll)); |
| 623 | return 0; | 698 | return 0; |
