static int sm_metadata_new_block_(struct dm_space_map *sm, dm_block_t *b)
{
	int r, r2 = 0;
	enum allocation_event ev;
	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);

	r = sm_ll_find_free_block(&smm->old_ll, smm->begin, smm->old_ll.nr_blocks, b);
	if (r)
		return r;

	smm->begin = *b + 1;

	if (recursing(smm))
		r = add_bop(smm, BOP_INC, *b);
	else {
		in(smm);
		r = sm_ll_inc(&smm->ll, *b, &ev);
		r2 = out(smm);
	}

	if (!r)
		smm->allocated_this_transaction++;

	return combine_errors(r, r2);
}
static int sm_metadata_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
{
	int r, i;
	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
	dm_block_t old_len = smm->ll.nr_blocks;

	/*
	 * Flick into a mode where all blocks get allocated in the new area.
	 */
	smm->begin = old_len;
	memcpy(sm, &bootstrap_ops, sizeof(*sm));

	/*
	 * Extend.
	 */
	r = sm_ll_extend(&smm->ll, extra_blocks);
	if (r)
		goto out;

	/*
	 * We repeatedly increment then commit until the commit doesn't
	 * allocate any new blocks.
	 */
	do {
		for (i = old_len; !r && i < smm->begin; i++)
			r = add_bop(smm, BOP_INC, i);

		if (r)
			goto out;

		old_len = smm->begin;

		r = apply_bops(smm);
		if (r) {
			DMERR("%s: apply_bops failed", __func__);
			goto out;
		}

		r = sm_ll_commit(&smm->ll);
		if (r)
			goto out;

	} while (old_len != smm->begin);

out:
	/*
	 * Switch back to normal behaviour.
	 */
	memcpy(sm, &ops, sizeof(*sm));
	return r;
}
static int sm_metadata_dec_block(struct dm_space_map *sm, dm_block_t b)
{
	int r, r2 = 0;
	enum allocation_event ev;
	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);

	if (recursing(smm))
		r = add_bop(smm, BOP_DEC, b);
	else {
		in(smm);
		r = sm_ll_dec(&smm->ll, b, &ev);
		r2 = out(smm);
	}

	return combine_errors(r, r2);
}
int dm_sm_metadata_create(struct dm_space_map *sm,
			  struct dm_transaction_manager *tm,
			  dm_block_t nr_blocks,
			  dm_block_t superblock)
{
	int r;
	dm_block_t i;
	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);

	smm->begin = superblock + 1;
	smm->recursion_count = 0;
	smm->allocated_this_transaction = 0;
	brb_init(&smm->uncommitted);
	threshold_init(&smm->threshold);

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

	r = sm_ll_new_metadata(&smm->ll, tm);
	if (!r) {
		if (nr_blocks > DM_SM_METADATA_MAX_BLOCKS)
			nr_blocks = DM_SM_METADATA_MAX_BLOCKS;
		r = sm_ll_extend(&smm->ll, nr_blocks);
	}
	memcpy(&smm->sm, &ops, sizeof(smm->sm));
	if (r)
		return r;

	/*
	 * Now we need to update the newly created data structures with the
	 * allocated blocks that they were built from.
	 */
	for (i = superblock; !r && i < smm->begin; i++)
		r = add_bop(smm, BOP_INC, i);

	if (r)
		return r;

	r = apply_bops(smm);
	if (r) {
		DMERR("%s: apply_bops failed", __func__);
		return r;
	}

	return sm_metadata_commit(sm);
}
static int sm_bootstrap_dec_block(struct dm_space_map *sm, dm_block_t b)
{
	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);

	return add_bop(smm, BOP_DEC, b);
}