Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2fc48021 authored by Joe Thornber's avatar Joe Thornber Committed by Alasdair G Kergon
Browse files

dm persistent metadata: add space map threshold callback



Add a threshold callback to dm persistent data space maps.

Signed-off-by: default avatarJoe Thornber <ejt@redhat.com>
Signed-off-by: default avatarAlasdair G Kergon <agk@redhat.com>
parent 7c3d3f2a
Loading
Loading
Loading
Loading
+76 −1
Original line number Diff line number Diff line
@@ -16,6 +16,55 @@

/*----------------------------------------------------------------*/

/*
 * An edge triggered threshold.
 */
struct threshold {
	bool threshold_set;
	bool value_set;
	dm_block_t threshold;
	dm_block_t current_value;
	dm_sm_threshold_fn fn;
	void *context;
};

static void threshold_init(struct threshold *t)
{
	t->threshold_set = false;
	t->value_set = false;
}

static void set_threshold(struct threshold *t, dm_block_t value,
			  dm_sm_threshold_fn fn, void *context)
{
	t->threshold_set = true;
	t->threshold = value;
	t->fn = fn;
	t->context = context;
}

static bool below_threshold(struct threshold *t, dm_block_t value)
{
	return t->threshold_set && value <= t->threshold;
}

static bool threshold_already_triggered(struct threshold *t)
{
	return t->value_set && below_threshold(t, t->current_value);
}

static void check_threshold(struct threshold *t, dm_block_t value)
{
	if (below_threshold(t, value) &&
	    !threshold_already_triggered(t))
		t->fn(t->context);

	t->value_set = true;
	t->current_value = value;
}

/*----------------------------------------------------------------*/

/*
 * Space map interface.
 *
@@ -54,6 +103,8 @@ struct sm_metadata {
	unsigned allocated_this_transaction;
	unsigned nr_uncommitted;
	struct block_op uncommitted[MAX_RECURSIVE_ALLOCATIONS];

	struct threshold threshold;
};

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)

static int sm_metadata_new_block(struct dm_space_map *sm, dm_block_t *b)
{
	dm_block_t count;
	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);

	int r = sm_metadata_new_block_(sm, b);
	if (r)
		DMERR("unable to allocate new metadata block");

	r = sm_metadata_get_nr_free(sm, &count);
	if (r)
		DMERR("couldn't get free block count");

	check_threshold(&smm->threshold, count);

	return r;
}

@@ -351,6 +412,18 @@ static int sm_metadata_commit(struct dm_space_map *sm)
	return 0;
}

static int sm_metadata_register_threshold_callback(struct dm_space_map *sm,
						   dm_block_t threshold,
						   dm_sm_threshold_fn fn,
						   void *context)
{
	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);

	set_threshold(&smm->threshold, threshold, fn, context);

	return 0;
}

static int sm_metadata_root_size(struct dm_space_map *sm, size_t *result)
{
	*result = sizeof(struct disk_sm_root);
@@ -392,7 +465,7 @@ static struct dm_space_map ops = {
	.commit = sm_metadata_commit,
	.root_size = sm_metadata_root_size,
	.copy_root = sm_metadata_copy_root,
	.register_threshold_callback = NULL
	.register_threshold_callback = sm_metadata_register_threshold_callback
};

/*----------------------------------------------------------------*/
@@ -577,6 +650,7 @@ int dm_sm_metadata_create(struct dm_space_map *sm,
	smm->recursion_count = 0;
	smm->allocated_this_transaction = 0;
	smm->nr_uncommitted = 0;
	threshold_init(&smm->threshold);

	memcpy(&smm->sm, &bootstrap_ops, sizeof(smm->sm));

@@ -618,6 +692,7 @@ int dm_sm_metadata_open(struct dm_space_map *sm,
	smm->recursion_count = 0;
	smm->allocated_this_transaction = 0;
	smm->nr_uncommitted = 0;
	threshold_init(&smm->threshold);

	memcpy(&smm->old_ll, &smm->ll, sizeof(smm->old_ll));
	return 0;