aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/persistent-data
diff options
context:
space:
mode:
authorJoe Thornber <ejt@redhat.com>2013-05-10 09:37:20 -0400
committerAlasdair G Kergon <agk@redhat.com>2013-05-10 09:37:20 -0400
commit2fc48021f4afdd109b9e52b6eef5db89ca80bac7 (patch)
tree38ee98f1a8fb8ca377822c01e34554fe0befd30a /drivers/md/persistent-data
parent7c3d3f2a87b01ff167a5f048285d5e3dee920235 (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.c77
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 */
22struct 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
31static void threshold_init(struct threshold *t)
32{
33 t->threshold_set = false;
34 t->value_set = false;
35}
36
37static 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
46static bool below_threshold(struct threshold *t, dm_block_t value)
47{
48 return t->threshold_set && value <= t->threshold;
49}
50
51static bool threshold_already_triggered(struct threshold *t)
52{
53 return t->value_set && below_threshold(t, t->current_value);
54}
55
56static 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
59static int add_bop(struct sm_metadata *smm, enum block_op_type type, dm_block_t b) 110static 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
330static int sm_metadata_new_block(struct dm_space_map *sm, dm_block_t *b) 381static 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
415static 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
354static int sm_metadata_root_size(struct dm_space_map *sm, size_t *result) 427static 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;