1616
1717/*----------------------------------------------------------------*/
1818
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+
1968/*
2069 * Space map interface.
2170 *
@@ -54,6 +103,8 @@ struct sm_metadata {
54103 unsigned allocated_this_transaction ;
55104 unsigned nr_uncommitted ;
56105 struct block_op uncommitted [MAX_RECURSIVE_ALLOCATIONS ];
106+
107+ struct threshold threshold ;
57108};
58109
59110static 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)
329380
330381static int sm_metadata_new_block (struct dm_space_map * sm , dm_block_t * b )
331382{
383+ dm_block_t count ;
384+ struct sm_metadata * smm = container_of (sm , struct sm_metadata , sm );
385+
332386 int r = sm_metadata_new_block_ (sm , b );
333387 if (r )
334388 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+
335396 return r ;
336397}
337398
@@ -351,6 +412,18 @@ static int sm_metadata_commit(struct dm_space_map *sm)
351412 return 0 ;
352413}
353414
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+
354427static int sm_metadata_root_size (struct dm_space_map * sm , size_t * result )
355428{
356429 * result = sizeof (struct disk_sm_root );
@@ -392,7 +465,7 @@ static struct dm_space_map ops = {
392465 .commit = sm_metadata_commit ,
393466 .root_size = sm_metadata_root_size ,
394467 .copy_root = sm_metadata_copy_root ,
395- .register_threshold_callback = NULL
468+ .register_threshold_callback = sm_metadata_register_threshold_callback
396469};
397470
398471/*----------------------------------------------------------------*/
@@ -577,6 +650,7 @@ int dm_sm_metadata_create(struct dm_space_map *sm,
577650 smm -> recursion_count = 0 ;
578651 smm -> allocated_this_transaction = 0 ;
579652 smm -> nr_uncommitted = 0 ;
653+ threshold_init (& smm -> threshold );
580654
581655 memcpy (& smm -> sm , & bootstrap_ops , sizeof (smm -> sm ));
582656
@@ -618,6 +692,7 @@ int dm_sm_metadata_open(struct dm_space_map *sm,
618692 smm -> recursion_count = 0 ;
619693 smm -> allocated_this_transaction = 0 ;
620694 smm -> nr_uncommitted = 0 ;
695+ threshold_init (& smm -> threshold );
621696
622697 memcpy (& smm -> old_ll , & smm -> ll , sizeof (smm -> old_ll ));
623698 return 0 ;
0 commit comments