18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright (C) 2011 Red Hat, Inc.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * This file is released under the GPL.
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include "dm-space-map-common.h"
88c2ecf20Sopenharmony_ci#include "dm-transaction-manager.h"
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/bitops.h>
118c2ecf20Sopenharmony_ci#include <linux/device-mapper.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#define DM_MSG_PREFIX "space map common"
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci/*----------------------------------------------------------------*/
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci/*
188c2ecf20Sopenharmony_ci * Index validator.
198c2ecf20Sopenharmony_ci */
208c2ecf20Sopenharmony_ci#define INDEX_CSUM_XOR 160478
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_cistatic void index_prepare_for_write(struct dm_block_validator *v,
238c2ecf20Sopenharmony_ci				    struct dm_block *b,
248c2ecf20Sopenharmony_ci				    size_t block_size)
258c2ecf20Sopenharmony_ci{
268c2ecf20Sopenharmony_ci	struct disk_metadata_index *mi_le = dm_block_data(b);
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci	mi_le->blocknr = cpu_to_le64(dm_block_location(b));
298c2ecf20Sopenharmony_ci	mi_le->csum = cpu_to_le32(dm_bm_checksum(&mi_le->padding,
308c2ecf20Sopenharmony_ci						 block_size - sizeof(__le32),
318c2ecf20Sopenharmony_ci						 INDEX_CSUM_XOR));
328c2ecf20Sopenharmony_ci}
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_cistatic int index_check(struct dm_block_validator *v,
358c2ecf20Sopenharmony_ci		       struct dm_block *b,
368c2ecf20Sopenharmony_ci		       size_t block_size)
378c2ecf20Sopenharmony_ci{
388c2ecf20Sopenharmony_ci	struct disk_metadata_index *mi_le = dm_block_data(b);
398c2ecf20Sopenharmony_ci	__le32 csum_disk;
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	if (dm_block_location(b) != le64_to_cpu(mi_le->blocknr)) {
428c2ecf20Sopenharmony_ci		DMERR_LIMIT("index_check failed: blocknr %llu != wanted %llu",
438c2ecf20Sopenharmony_ci			    le64_to_cpu(mi_le->blocknr), dm_block_location(b));
448c2ecf20Sopenharmony_ci		return -ENOTBLK;
458c2ecf20Sopenharmony_ci	}
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci	csum_disk = cpu_to_le32(dm_bm_checksum(&mi_le->padding,
488c2ecf20Sopenharmony_ci					       block_size - sizeof(__le32),
498c2ecf20Sopenharmony_ci					       INDEX_CSUM_XOR));
508c2ecf20Sopenharmony_ci	if (csum_disk != mi_le->csum) {
518c2ecf20Sopenharmony_ci		DMERR_LIMIT("index_check failed: csum %u != wanted %u",
528c2ecf20Sopenharmony_ci			    le32_to_cpu(csum_disk), le32_to_cpu(mi_le->csum));
538c2ecf20Sopenharmony_ci		return -EILSEQ;
548c2ecf20Sopenharmony_ci	}
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	return 0;
578c2ecf20Sopenharmony_ci}
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_cistatic struct dm_block_validator index_validator = {
608c2ecf20Sopenharmony_ci	.name = "index",
618c2ecf20Sopenharmony_ci	.prepare_for_write = index_prepare_for_write,
628c2ecf20Sopenharmony_ci	.check = index_check
638c2ecf20Sopenharmony_ci};
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci/*----------------------------------------------------------------*/
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci/*
688c2ecf20Sopenharmony_ci * Bitmap validator
698c2ecf20Sopenharmony_ci */
708c2ecf20Sopenharmony_ci#define BITMAP_CSUM_XOR 240779
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_cistatic void dm_bitmap_prepare_for_write(struct dm_block_validator *v,
738c2ecf20Sopenharmony_ci					struct dm_block *b,
748c2ecf20Sopenharmony_ci					size_t block_size)
758c2ecf20Sopenharmony_ci{
768c2ecf20Sopenharmony_ci	struct disk_bitmap_header *disk_header = dm_block_data(b);
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	disk_header->blocknr = cpu_to_le64(dm_block_location(b));
798c2ecf20Sopenharmony_ci	disk_header->csum = cpu_to_le32(dm_bm_checksum(&disk_header->not_used,
808c2ecf20Sopenharmony_ci						       block_size - sizeof(__le32),
818c2ecf20Sopenharmony_ci						       BITMAP_CSUM_XOR));
828c2ecf20Sopenharmony_ci}
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_cistatic int dm_bitmap_check(struct dm_block_validator *v,
858c2ecf20Sopenharmony_ci			   struct dm_block *b,
868c2ecf20Sopenharmony_ci			   size_t block_size)
878c2ecf20Sopenharmony_ci{
888c2ecf20Sopenharmony_ci	struct disk_bitmap_header *disk_header = dm_block_data(b);
898c2ecf20Sopenharmony_ci	__le32 csum_disk;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	if (dm_block_location(b) != le64_to_cpu(disk_header->blocknr)) {
928c2ecf20Sopenharmony_ci		DMERR_LIMIT("bitmap check failed: blocknr %llu != wanted %llu",
938c2ecf20Sopenharmony_ci			    le64_to_cpu(disk_header->blocknr), dm_block_location(b));
948c2ecf20Sopenharmony_ci		return -ENOTBLK;
958c2ecf20Sopenharmony_ci	}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	csum_disk = cpu_to_le32(dm_bm_checksum(&disk_header->not_used,
988c2ecf20Sopenharmony_ci					       block_size - sizeof(__le32),
998c2ecf20Sopenharmony_ci					       BITMAP_CSUM_XOR));
1008c2ecf20Sopenharmony_ci	if (csum_disk != disk_header->csum) {
1018c2ecf20Sopenharmony_ci		DMERR_LIMIT("bitmap check failed: csum %u != wanted %u",
1028c2ecf20Sopenharmony_ci			    le32_to_cpu(csum_disk), le32_to_cpu(disk_header->csum));
1038c2ecf20Sopenharmony_ci		return -EILSEQ;
1048c2ecf20Sopenharmony_ci	}
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci	return 0;
1078c2ecf20Sopenharmony_ci}
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_cistatic struct dm_block_validator dm_sm_bitmap_validator = {
1108c2ecf20Sopenharmony_ci	.name = "sm_bitmap",
1118c2ecf20Sopenharmony_ci	.prepare_for_write = dm_bitmap_prepare_for_write,
1128c2ecf20Sopenharmony_ci	.check = dm_bitmap_check,
1138c2ecf20Sopenharmony_ci};
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci/*----------------------------------------------------------------*/
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci#define ENTRIES_PER_WORD 32
1188c2ecf20Sopenharmony_ci#define ENTRIES_SHIFT	5
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_cistatic void *dm_bitmap_data(struct dm_block *b)
1218c2ecf20Sopenharmony_ci{
1228c2ecf20Sopenharmony_ci	return dm_block_data(b) + sizeof(struct disk_bitmap_header);
1238c2ecf20Sopenharmony_ci}
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci#define WORD_MASK_HIGH 0xAAAAAAAAAAAAAAAAULL
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_cistatic unsigned dm_bitmap_word_used(void *addr, unsigned b)
1288c2ecf20Sopenharmony_ci{
1298c2ecf20Sopenharmony_ci	__le64 *words_le = addr;
1308c2ecf20Sopenharmony_ci	__le64 *w_le = words_le + (b >> ENTRIES_SHIFT);
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	uint64_t bits = le64_to_cpu(*w_le);
1338c2ecf20Sopenharmony_ci	uint64_t mask = (bits + WORD_MASK_HIGH + 1) & WORD_MASK_HIGH;
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci	return !(~bits & mask);
1368c2ecf20Sopenharmony_ci}
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_cistatic unsigned sm_lookup_bitmap(void *addr, unsigned b)
1398c2ecf20Sopenharmony_ci{
1408c2ecf20Sopenharmony_ci	__le64 *words_le = addr;
1418c2ecf20Sopenharmony_ci	__le64 *w_le = words_le + (b >> ENTRIES_SHIFT);
1428c2ecf20Sopenharmony_ci	unsigned hi, lo;
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	b = (b & (ENTRIES_PER_WORD - 1)) << 1;
1458c2ecf20Sopenharmony_ci	hi = !!test_bit_le(b, (void *) w_le);
1468c2ecf20Sopenharmony_ci	lo = !!test_bit_le(b + 1, (void *) w_le);
1478c2ecf20Sopenharmony_ci	return (hi << 1) | lo;
1488c2ecf20Sopenharmony_ci}
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_cistatic void sm_set_bitmap(void *addr, unsigned b, unsigned val)
1518c2ecf20Sopenharmony_ci{
1528c2ecf20Sopenharmony_ci	__le64 *words_le = addr;
1538c2ecf20Sopenharmony_ci	__le64 *w_le = words_le + (b >> ENTRIES_SHIFT);
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	b = (b & (ENTRIES_PER_WORD - 1)) << 1;
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	if (val & 2)
1588c2ecf20Sopenharmony_ci		__set_bit_le(b, (void *) w_le);
1598c2ecf20Sopenharmony_ci	else
1608c2ecf20Sopenharmony_ci		__clear_bit_le(b, (void *) w_le);
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	if (val & 1)
1638c2ecf20Sopenharmony_ci		__set_bit_le(b + 1, (void *) w_le);
1648c2ecf20Sopenharmony_ci	else
1658c2ecf20Sopenharmony_ci		__clear_bit_le(b + 1, (void *) w_le);
1668c2ecf20Sopenharmony_ci}
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_cistatic int sm_find_free(void *addr, unsigned begin, unsigned end,
1698c2ecf20Sopenharmony_ci			unsigned *result)
1708c2ecf20Sopenharmony_ci{
1718c2ecf20Sopenharmony_ci	while (begin < end) {
1728c2ecf20Sopenharmony_ci		if (!(begin & (ENTRIES_PER_WORD - 1)) &&
1738c2ecf20Sopenharmony_ci		    dm_bitmap_word_used(addr, begin)) {
1748c2ecf20Sopenharmony_ci			begin += ENTRIES_PER_WORD;
1758c2ecf20Sopenharmony_ci			continue;
1768c2ecf20Sopenharmony_ci		}
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci		if (!sm_lookup_bitmap(addr, begin)) {
1798c2ecf20Sopenharmony_ci			*result = begin;
1808c2ecf20Sopenharmony_ci			return 0;
1818c2ecf20Sopenharmony_ci		}
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci		begin++;
1848c2ecf20Sopenharmony_ci	}
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	return -ENOSPC;
1878c2ecf20Sopenharmony_ci}
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci/*----------------------------------------------------------------*/
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_cistatic int sm_ll_init(struct ll_disk *ll, struct dm_transaction_manager *tm)
1928c2ecf20Sopenharmony_ci{
1938c2ecf20Sopenharmony_ci	memset(ll, 0, sizeof(struct ll_disk));
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	ll->tm = tm;
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	ll->bitmap_info.tm = tm;
1988c2ecf20Sopenharmony_ci	ll->bitmap_info.levels = 1;
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci	/*
2018c2ecf20Sopenharmony_ci	 * Because the new bitmap blocks are created via a shadow
2028c2ecf20Sopenharmony_ci	 * operation, the old entry has already had its reference count
2038c2ecf20Sopenharmony_ci	 * decremented and we don't need the btree to do any bookkeeping.
2048c2ecf20Sopenharmony_ci	 */
2058c2ecf20Sopenharmony_ci	ll->bitmap_info.value_type.size = sizeof(struct disk_index_entry);
2068c2ecf20Sopenharmony_ci	ll->bitmap_info.value_type.inc = NULL;
2078c2ecf20Sopenharmony_ci	ll->bitmap_info.value_type.dec = NULL;
2088c2ecf20Sopenharmony_ci	ll->bitmap_info.value_type.equal = NULL;
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	ll->ref_count_info.tm = tm;
2118c2ecf20Sopenharmony_ci	ll->ref_count_info.levels = 1;
2128c2ecf20Sopenharmony_ci	ll->ref_count_info.value_type.size = sizeof(uint32_t);
2138c2ecf20Sopenharmony_ci	ll->ref_count_info.value_type.inc = NULL;
2148c2ecf20Sopenharmony_ci	ll->ref_count_info.value_type.dec = NULL;
2158c2ecf20Sopenharmony_ci	ll->ref_count_info.value_type.equal = NULL;
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	ll->block_size = dm_bm_block_size(dm_tm_get_bm(tm));
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	if (ll->block_size > (1 << 30)) {
2208c2ecf20Sopenharmony_ci		DMERR("block size too big to hold bitmaps");
2218c2ecf20Sopenharmony_ci		return -EINVAL;
2228c2ecf20Sopenharmony_ci	}
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	ll->entries_per_block = (ll->block_size - sizeof(struct disk_bitmap_header)) *
2258c2ecf20Sopenharmony_ci		ENTRIES_PER_BYTE;
2268c2ecf20Sopenharmony_ci	ll->nr_blocks = 0;
2278c2ecf20Sopenharmony_ci	ll->bitmap_root = 0;
2288c2ecf20Sopenharmony_ci	ll->ref_count_root = 0;
2298c2ecf20Sopenharmony_ci	ll->bitmap_index_changed = false;
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	return 0;
2328c2ecf20Sopenharmony_ci}
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ciint sm_ll_extend(struct ll_disk *ll, dm_block_t extra_blocks)
2358c2ecf20Sopenharmony_ci{
2368c2ecf20Sopenharmony_ci	int r;
2378c2ecf20Sopenharmony_ci	dm_block_t i, nr_blocks, nr_indexes;
2388c2ecf20Sopenharmony_ci	unsigned old_blocks, blocks;
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	nr_blocks = ll->nr_blocks + extra_blocks;
2418c2ecf20Sopenharmony_ci	old_blocks = dm_sector_div_up(ll->nr_blocks, ll->entries_per_block);
2428c2ecf20Sopenharmony_ci	blocks = dm_sector_div_up(nr_blocks, ll->entries_per_block);
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	nr_indexes = dm_sector_div_up(nr_blocks, ll->entries_per_block);
2458c2ecf20Sopenharmony_ci	if (nr_indexes > ll->max_entries(ll)) {
2468c2ecf20Sopenharmony_ci		DMERR("space map too large");
2478c2ecf20Sopenharmony_ci		return -EINVAL;
2488c2ecf20Sopenharmony_ci	}
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	/*
2518c2ecf20Sopenharmony_ci	 * We need to set this before the dm_tm_new_block() call below.
2528c2ecf20Sopenharmony_ci	 */
2538c2ecf20Sopenharmony_ci	ll->nr_blocks = nr_blocks;
2548c2ecf20Sopenharmony_ci	for (i = old_blocks; i < blocks; i++) {
2558c2ecf20Sopenharmony_ci		struct dm_block *b;
2568c2ecf20Sopenharmony_ci		struct disk_index_entry idx;
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci		r = dm_tm_new_block(ll->tm, &dm_sm_bitmap_validator, &b);
2598c2ecf20Sopenharmony_ci		if (r < 0)
2608c2ecf20Sopenharmony_ci			return r;
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci		idx.blocknr = cpu_to_le64(dm_block_location(b));
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci		dm_tm_unlock(ll->tm, b);
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci		idx.nr_free = cpu_to_le32(ll->entries_per_block);
2678c2ecf20Sopenharmony_ci		idx.none_free_before = 0;
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci		r = ll->save_ie(ll, i, &idx);
2708c2ecf20Sopenharmony_ci		if (r < 0)
2718c2ecf20Sopenharmony_ci			return r;
2728c2ecf20Sopenharmony_ci	}
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci	return 0;
2758c2ecf20Sopenharmony_ci}
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ciint sm_ll_lookup_bitmap(struct ll_disk *ll, dm_block_t b, uint32_t *result)
2788c2ecf20Sopenharmony_ci{
2798c2ecf20Sopenharmony_ci	int r;
2808c2ecf20Sopenharmony_ci	dm_block_t index = b;
2818c2ecf20Sopenharmony_ci	struct disk_index_entry ie_disk;
2828c2ecf20Sopenharmony_ci	struct dm_block *blk;
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	if (b >= ll->nr_blocks) {
2858c2ecf20Sopenharmony_ci		DMERR_LIMIT("metadata block out of bounds");
2868c2ecf20Sopenharmony_ci		return -EINVAL;
2878c2ecf20Sopenharmony_ci	}
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci	b = do_div(index, ll->entries_per_block);
2908c2ecf20Sopenharmony_ci	r = ll->load_ie(ll, index, &ie_disk);
2918c2ecf20Sopenharmony_ci	if (r < 0)
2928c2ecf20Sopenharmony_ci		return r;
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	r = dm_tm_read_lock(ll->tm, le64_to_cpu(ie_disk.blocknr),
2958c2ecf20Sopenharmony_ci			    &dm_sm_bitmap_validator, &blk);
2968c2ecf20Sopenharmony_ci	if (r < 0)
2978c2ecf20Sopenharmony_ci		return r;
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	*result = sm_lookup_bitmap(dm_bitmap_data(blk), b);
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci	dm_tm_unlock(ll->tm, blk);
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	return 0;
3048c2ecf20Sopenharmony_ci}
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_cistatic int sm_ll_lookup_big_ref_count(struct ll_disk *ll, dm_block_t b,
3078c2ecf20Sopenharmony_ci				      uint32_t *result)
3088c2ecf20Sopenharmony_ci{
3098c2ecf20Sopenharmony_ci	__le32 le_rc;
3108c2ecf20Sopenharmony_ci	int r;
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	r = dm_btree_lookup(&ll->ref_count_info, ll->ref_count_root, &b, &le_rc);
3138c2ecf20Sopenharmony_ci	if (r < 0)
3148c2ecf20Sopenharmony_ci		return r;
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	*result = le32_to_cpu(le_rc);
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci	return r;
3198c2ecf20Sopenharmony_ci}
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ciint sm_ll_lookup(struct ll_disk *ll, dm_block_t b, uint32_t *result)
3228c2ecf20Sopenharmony_ci{
3238c2ecf20Sopenharmony_ci	int r = sm_ll_lookup_bitmap(ll, b, result);
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	if (r)
3268c2ecf20Sopenharmony_ci		return r;
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci	if (*result != 3)
3298c2ecf20Sopenharmony_ci		return r;
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci	return sm_ll_lookup_big_ref_count(ll, b, result);
3328c2ecf20Sopenharmony_ci}
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ciint sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
3358c2ecf20Sopenharmony_ci			  dm_block_t end, dm_block_t *result)
3368c2ecf20Sopenharmony_ci{
3378c2ecf20Sopenharmony_ci	int r;
3388c2ecf20Sopenharmony_ci	struct disk_index_entry ie_disk;
3398c2ecf20Sopenharmony_ci	dm_block_t i, index_begin = begin;
3408c2ecf20Sopenharmony_ci	dm_block_t index_end = dm_sector_div_up(end, ll->entries_per_block);
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	/*
3438c2ecf20Sopenharmony_ci	 * FIXME: Use shifts
3448c2ecf20Sopenharmony_ci	 */
3458c2ecf20Sopenharmony_ci	begin = do_div(index_begin, ll->entries_per_block);
3468c2ecf20Sopenharmony_ci	end = do_div(end, ll->entries_per_block);
3478c2ecf20Sopenharmony_ci	if (end == 0)
3488c2ecf20Sopenharmony_ci		end = ll->entries_per_block;
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci	for (i = index_begin; i < index_end; i++, begin = 0) {
3518c2ecf20Sopenharmony_ci		struct dm_block *blk;
3528c2ecf20Sopenharmony_ci		unsigned position;
3538c2ecf20Sopenharmony_ci		uint32_t bit_end;
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci		r = ll->load_ie(ll, i, &ie_disk);
3568c2ecf20Sopenharmony_ci		if (r < 0)
3578c2ecf20Sopenharmony_ci			return r;
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci		if (le32_to_cpu(ie_disk.nr_free) == 0)
3608c2ecf20Sopenharmony_ci			continue;
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci		r = dm_tm_read_lock(ll->tm, le64_to_cpu(ie_disk.blocknr),
3638c2ecf20Sopenharmony_ci				    &dm_sm_bitmap_validator, &blk);
3648c2ecf20Sopenharmony_ci		if (r < 0)
3658c2ecf20Sopenharmony_ci			return r;
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci		bit_end = (i == index_end - 1) ?  end : ll->entries_per_block;
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci		r = sm_find_free(dm_bitmap_data(blk),
3708c2ecf20Sopenharmony_ci				 max_t(unsigned, begin, le32_to_cpu(ie_disk.none_free_before)),
3718c2ecf20Sopenharmony_ci				 bit_end, &position);
3728c2ecf20Sopenharmony_ci		if (r == -ENOSPC) {
3738c2ecf20Sopenharmony_ci			/*
3748c2ecf20Sopenharmony_ci			 * This might happen because we started searching
3758c2ecf20Sopenharmony_ci			 * part way through the bitmap.
3768c2ecf20Sopenharmony_ci			 */
3778c2ecf20Sopenharmony_ci			dm_tm_unlock(ll->tm, blk);
3788c2ecf20Sopenharmony_ci			continue;
3798c2ecf20Sopenharmony_ci		}
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci		dm_tm_unlock(ll->tm, blk);
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci		*result = i * ll->entries_per_block + (dm_block_t) position;
3848c2ecf20Sopenharmony_ci		return 0;
3858c2ecf20Sopenharmony_ci	}
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci	return -ENOSPC;
3888c2ecf20Sopenharmony_ci}
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ciint sm_ll_find_common_free_block(struct ll_disk *old_ll, struct ll_disk *new_ll,
3918c2ecf20Sopenharmony_ci	                         dm_block_t begin, dm_block_t end, dm_block_t *b)
3928c2ecf20Sopenharmony_ci{
3938c2ecf20Sopenharmony_ci	int r;
3948c2ecf20Sopenharmony_ci	uint32_t count;
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci	do {
3978c2ecf20Sopenharmony_ci		r = sm_ll_find_free_block(new_ll, begin, new_ll->nr_blocks, b);
3988c2ecf20Sopenharmony_ci		if (r)
3998c2ecf20Sopenharmony_ci			break;
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci		/* double check this block wasn't used in the old transaction */
4028c2ecf20Sopenharmony_ci		if (*b >= old_ll->nr_blocks)
4038c2ecf20Sopenharmony_ci			count = 0;
4048c2ecf20Sopenharmony_ci		else {
4058c2ecf20Sopenharmony_ci			r = sm_ll_lookup(old_ll, *b, &count);
4068c2ecf20Sopenharmony_ci			if (r)
4078c2ecf20Sopenharmony_ci				break;
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci			if (count)
4108c2ecf20Sopenharmony_ci				begin = *b + 1;
4118c2ecf20Sopenharmony_ci		}
4128c2ecf20Sopenharmony_ci	} while (count);
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci	return r;
4158c2ecf20Sopenharmony_ci}
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_cistatic int sm_ll_mutate(struct ll_disk *ll, dm_block_t b,
4188c2ecf20Sopenharmony_ci			int (*mutator)(void *context, uint32_t old, uint32_t *new),
4198c2ecf20Sopenharmony_ci			void *context, enum allocation_event *ev)
4208c2ecf20Sopenharmony_ci{
4218c2ecf20Sopenharmony_ci	int r;
4228c2ecf20Sopenharmony_ci	uint32_t bit, old, ref_count;
4238c2ecf20Sopenharmony_ci	struct dm_block *nb;
4248c2ecf20Sopenharmony_ci	dm_block_t index = b;
4258c2ecf20Sopenharmony_ci	struct disk_index_entry ie_disk;
4268c2ecf20Sopenharmony_ci	void *bm_le;
4278c2ecf20Sopenharmony_ci	int inc;
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci	bit = do_div(index, ll->entries_per_block);
4308c2ecf20Sopenharmony_ci	r = ll->load_ie(ll, index, &ie_disk);
4318c2ecf20Sopenharmony_ci	if (r < 0)
4328c2ecf20Sopenharmony_ci		return r;
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci	r = dm_tm_shadow_block(ll->tm, le64_to_cpu(ie_disk.blocknr),
4358c2ecf20Sopenharmony_ci			       &dm_sm_bitmap_validator, &nb, &inc);
4368c2ecf20Sopenharmony_ci	if (r < 0) {
4378c2ecf20Sopenharmony_ci		DMERR("dm_tm_shadow_block() failed");
4388c2ecf20Sopenharmony_ci		return r;
4398c2ecf20Sopenharmony_ci	}
4408c2ecf20Sopenharmony_ci	ie_disk.blocknr = cpu_to_le64(dm_block_location(nb));
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ci	bm_le = dm_bitmap_data(nb);
4438c2ecf20Sopenharmony_ci	old = sm_lookup_bitmap(bm_le, bit);
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ci	if (old > 2) {
4468c2ecf20Sopenharmony_ci		r = sm_ll_lookup_big_ref_count(ll, b, &old);
4478c2ecf20Sopenharmony_ci		if (r < 0) {
4488c2ecf20Sopenharmony_ci			dm_tm_unlock(ll->tm, nb);
4498c2ecf20Sopenharmony_ci			return r;
4508c2ecf20Sopenharmony_ci		}
4518c2ecf20Sopenharmony_ci	}
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	r = mutator(context, old, &ref_count);
4548c2ecf20Sopenharmony_ci	if (r) {
4558c2ecf20Sopenharmony_ci		dm_tm_unlock(ll->tm, nb);
4568c2ecf20Sopenharmony_ci		return r;
4578c2ecf20Sopenharmony_ci	}
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci	if (ref_count <= 2) {
4608c2ecf20Sopenharmony_ci		sm_set_bitmap(bm_le, bit, ref_count);
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci		dm_tm_unlock(ll->tm, nb);
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci		if (old > 2) {
4658c2ecf20Sopenharmony_ci			r = dm_btree_remove(&ll->ref_count_info,
4668c2ecf20Sopenharmony_ci					    ll->ref_count_root,
4678c2ecf20Sopenharmony_ci					    &b, &ll->ref_count_root);
4688c2ecf20Sopenharmony_ci			if (r)
4698c2ecf20Sopenharmony_ci				return r;
4708c2ecf20Sopenharmony_ci		}
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci	} else {
4738c2ecf20Sopenharmony_ci		__le32 le_rc = cpu_to_le32(ref_count);
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci		sm_set_bitmap(bm_le, bit, 3);
4768c2ecf20Sopenharmony_ci		dm_tm_unlock(ll->tm, nb);
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci		__dm_bless_for_disk(&le_rc);
4798c2ecf20Sopenharmony_ci		r = dm_btree_insert(&ll->ref_count_info, ll->ref_count_root,
4808c2ecf20Sopenharmony_ci				    &b, &le_rc, &ll->ref_count_root);
4818c2ecf20Sopenharmony_ci		if (r < 0) {
4828c2ecf20Sopenharmony_ci			DMERR("ref count insert failed");
4838c2ecf20Sopenharmony_ci			return r;
4848c2ecf20Sopenharmony_ci		}
4858c2ecf20Sopenharmony_ci	}
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci	if (ref_count && !old) {
4888c2ecf20Sopenharmony_ci		*ev = SM_ALLOC;
4898c2ecf20Sopenharmony_ci		ll->nr_allocated++;
4908c2ecf20Sopenharmony_ci		le32_add_cpu(&ie_disk.nr_free, -1);
4918c2ecf20Sopenharmony_ci		if (le32_to_cpu(ie_disk.none_free_before) == bit)
4928c2ecf20Sopenharmony_ci			ie_disk.none_free_before = cpu_to_le32(bit + 1);
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci	} else if (old && !ref_count) {
4958c2ecf20Sopenharmony_ci		*ev = SM_FREE;
4968c2ecf20Sopenharmony_ci		ll->nr_allocated--;
4978c2ecf20Sopenharmony_ci		le32_add_cpu(&ie_disk.nr_free, 1);
4988c2ecf20Sopenharmony_ci		ie_disk.none_free_before = cpu_to_le32(min(le32_to_cpu(ie_disk.none_free_before), bit));
4998c2ecf20Sopenharmony_ci	} else
5008c2ecf20Sopenharmony_ci		*ev = SM_NONE;
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci	return ll->save_ie(ll, index, &ie_disk);
5038c2ecf20Sopenharmony_ci}
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_cistatic int set_ref_count(void *context, uint32_t old, uint32_t *new)
5068c2ecf20Sopenharmony_ci{
5078c2ecf20Sopenharmony_ci	*new = *((uint32_t *) context);
5088c2ecf20Sopenharmony_ci	return 0;
5098c2ecf20Sopenharmony_ci}
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ciint sm_ll_insert(struct ll_disk *ll, dm_block_t b,
5128c2ecf20Sopenharmony_ci		 uint32_t ref_count, enum allocation_event *ev)
5138c2ecf20Sopenharmony_ci{
5148c2ecf20Sopenharmony_ci	return sm_ll_mutate(ll, b, set_ref_count, &ref_count, ev);
5158c2ecf20Sopenharmony_ci}
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_cistatic int inc_ref_count(void *context, uint32_t old, uint32_t *new)
5188c2ecf20Sopenharmony_ci{
5198c2ecf20Sopenharmony_ci	*new = old + 1;
5208c2ecf20Sopenharmony_ci	return 0;
5218c2ecf20Sopenharmony_ci}
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_ciint sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev)
5248c2ecf20Sopenharmony_ci{
5258c2ecf20Sopenharmony_ci	return sm_ll_mutate(ll, b, inc_ref_count, NULL, ev);
5268c2ecf20Sopenharmony_ci}
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_cistatic int dec_ref_count(void *context, uint32_t old, uint32_t *new)
5298c2ecf20Sopenharmony_ci{
5308c2ecf20Sopenharmony_ci	if (!old) {
5318c2ecf20Sopenharmony_ci		DMERR_LIMIT("unable to decrement a reference count below 0");
5328c2ecf20Sopenharmony_ci		return -EINVAL;
5338c2ecf20Sopenharmony_ci	}
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci	*new = old - 1;
5368c2ecf20Sopenharmony_ci	return 0;
5378c2ecf20Sopenharmony_ci}
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ciint sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev)
5408c2ecf20Sopenharmony_ci{
5418c2ecf20Sopenharmony_ci	return sm_ll_mutate(ll, b, dec_ref_count, NULL, ev);
5428c2ecf20Sopenharmony_ci}
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ciint sm_ll_commit(struct ll_disk *ll)
5458c2ecf20Sopenharmony_ci{
5468c2ecf20Sopenharmony_ci	int r = 0;
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	if (ll->bitmap_index_changed) {
5498c2ecf20Sopenharmony_ci		r = ll->commit(ll);
5508c2ecf20Sopenharmony_ci		if (!r)
5518c2ecf20Sopenharmony_ci			ll->bitmap_index_changed = false;
5528c2ecf20Sopenharmony_ci	}
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_ci	return r;
5558c2ecf20Sopenharmony_ci}
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci/*----------------------------------------------------------------*/
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_cistatic int metadata_ll_load_ie(struct ll_disk *ll, dm_block_t index,
5608c2ecf20Sopenharmony_ci			       struct disk_index_entry *ie)
5618c2ecf20Sopenharmony_ci{
5628c2ecf20Sopenharmony_ci	memcpy(ie, ll->mi_le.index + index, sizeof(*ie));
5638c2ecf20Sopenharmony_ci	return 0;
5648c2ecf20Sopenharmony_ci}
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_cistatic int metadata_ll_save_ie(struct ll_disk *ll, dm_block_t index,
5678c2ecf20Sopenharmony_ci			       struct disk_index_entry *ie)
5688c2ecf20Sopenharmony_ci{
5698c2ecf20Sopenharmony_ci	ll->bitmap_index_changed = true;
5708c2ecf20Sopenharmony_ci	memcpy(ll->mi_le.index + index, ie, sizeof(*ie));
5718c2ecf20Sopenharmony_ci	return 0;
5728c2ecf20Sopenharmony_ci}
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_cistatic int metadata_ll_init_index(struct ll_disk *ll)
5758c2ecf20Sopenharmony_ci{
5768c2ecf20Sopenharmony_ci	int r;
5778c2ecf20Sopenharmony_ci	struct dm_block *b;
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	r = dm_tm_new_block(ll->tm, &index_validator, &b);
5808c2ecf20Sopenharmony_ci	if (r < 0)
5818c2ecf20Sopenharmony_ci		return r;
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	ll->bitmap_root = dm_block_location(b);
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci	dm_tm_unlock(ll->tm, b);
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_ci	return 0;
5888c2ecf20Sopenharmony_ci}
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_cistatic int metadata_ll_open(struct ll_disk *ll)
5918c2ecf20Sopenharmony_ci{
5928c2ecf20Sopenharmony_ci	int r;
5938c2ecf20Sopenharmony_ci	struct dm_block *block;
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	r = dm_tm_read_lock(ll->tm, ll->bitmap_root,
5968c2ecf20Sopenharmony_ci			    &index_validator, &block);
5978c2ecf20Sopenharmony_ci	if (r)
5988c2ecf20Sopenharmony_ci		return r;
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_ci	memcpy(&ll->mi_le, dm_block_data(block), sizeof(ll->mi_le));
6018c2ecf20Sopenharmony_ci	dm_tm_unlock(ll->tm, block);
6028c2ecf20Sopenharmony_ci
6038c2ecf20Sopenharmony_ci	return 0;
6048c2ecf20Sopenharmony_ci}
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_cistatic dm_block_t metadata_ll_max_entries(struct ll_disk *ll)
6078c2ecf20Sopenharmony_ci{
6088c2ecf20Sopenharmony_ci	return MAX_METADATA_BITMAPS;
6098c2ecf20Sopenharmony_ci}
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_cistatic int metadata_ll_commit(struct ll_disk *ll)
6128c2ecf20Sopenharmony_ci{
6138c2ecf20Sopenharmony_ci	int r, inc;
6148c2ecf20Sopenharmony_ci	struct dm_block *b;
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci	r = dm_tm_shadow_block(ll->tm, ll->bitmap_root, &index_validator, &b, &inc);
6178c2ecf20Sopenharmony_ci	if (r)
6188c2ecf20Sopenharmony_ci		return r;
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci	memcpy(dm_block_data(b), &ll->mi_le, sizeof(ll->mi_le));
6218c2ecf20Sopenharmony_ci	ll->bitmap_root = dm_block_location(b);
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_ci	dm_tm_unlock(ll->tm, b);
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_ci	return 0;
6268c2ecf20Sopenharmony_ci}
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ciint sm_ll_new_metadata(struct ll_disk *ll, struct dm_transaction_manager *tm)
6298c2ecf20Sopenharmony_ci{
6308c2ecf20Sopenharmony_ci	int r;
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_ci	r = sm_ll_init(ll, tm);
6338c2ecf20Sopenharmony_ci	if (r < 0)
6348c2ecf20Sopenharmony_ci		return r;
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_ci	ll->load_ie = metadata_ll_load_ie;
6378c2ecf20Sopenharmony_ci	ll->save_ie = metadata_ll_save_ie;
6388c2ecf20Sopenharmony_ci	ll->init_index = metadata_ll_init_index;
6398c2ecf20Sopenharmony_ci	ll->open_index = metadata_ll_open;
6408c2ecf20Sopenharmony_ci	ll->max_entries = metadata_ll_max_entries;
6418c2ecf20Sopenharmony_ci	ll->commit = metadata_ll_commit;
6428c2ecf20Sopenharmony_ci
6438c2ecf20Sopenharmony_ci	ll->nr_blocks = 0;
6448c2ecf20Sopenharmony_ci	ll->nr_allocated = 0;
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_ci	r = ll->init_index(ll);
6478c2ecf20Sopenharmony_ci	if (r < 0)
6488c2ecf20Sopenharmony_ci		return r;
6498c2ecf20Sopenharmony_ci
6508c2ecf20Sopenharmony_ci	r = dm_btree_empty(&ll->ref_count_info, &ll->ref_count_root);
6518c2ecf20Sopenharmony_ci	if (r < 0)
6528c2ecf20Sopenharmony_ci		return r;
6538c2ecf20Sopenharmony_ci
6548c2ecf20Sopenharmony_ci	return 0;
6558c2ecf20Sopenharmony_ci}
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ciint sm_ll_open_metadata(struct ll_disk *ll, struct dm_transaction_manager *tm,
6588c2ecf20Sopenharmony_ci			void *root_le, size_t len)
6598c2ecf20Sopenharmony_ci{
6608c2ecf20Sopenharmony_ci	int r;
6618c2ecf20Sopenharmony_ci	struct disk_sm_root smr;
6628c2ecf20Sopenharmony_ci
6638c2ecf20Sopenharmony_ci	if (len < sizeof(struct disk_sm_root)) {
6648c2ecf20Sopenharmony_ci		DMERR("sm_metadata root too small");
6658c2ecf20Sopenharmony_ci		return -ENOMEM;
6668c2ecf20Sopenharmony_ci	}
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ci	/*
6698c2ecf20Sopenharmony_ci	 * We don't know the alignment of the root_le buffer, so need to
6708c2ecf20Sopenharmony_ci	 * copy into a new structure.
6718c2ecf20Sopenharmony_ci	 */
6728c2ecf20Sopenharmony_ci	memcpy(&smr, root_le, sizeof(smr));
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci	r = sm_ll_init(ll, tm);
6758c2ecf20Sopenharmony_ci	if (r < 0)
6768c2ecf20Sopenharmony_ci		return r;
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_ci	ll->load_ie = metadata_ll_load_ie;
6798c2ecf20Sopenharmony_ci	ll->save_ie = metadata_ll_save_ie;
6808c2ecf20Sopenharmony_ci	ll->init_index = metadata_ll_init_index;
6818c2ecf20Sopenharmony_ci	ll->open_index = metadata_ll_open;
6828c2ecf20Sopenharmony_ci	ll->max_entries = metadata_ll_max_entries;
6838c2ecf20Sopenharmony_ci	ll->commit = metadata_ll_commit;
6848c2ecf20Sopenharmony_ci
6858c2ecf20Sopenharmony_ci	ll->nr_blocks = le64_to_cpu(smr.nr_blocks);
6868c2ecf20Sopenharmony_ci	ll->nr_allocated = le64_to_cpu(smr.nr_allocated);
6878c2ecf20Sopenharmony_ci	ll->bitmap_root = le64_to_cpu(smr.bitmap_root);
6888c2ecf20Sopenharmony_ci	ll->ref_count_root = le64_to_cpu(smr.ref_count_root);
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_ci	return ll->open_index(ll);
6918c2ecf20Sopenharmony_ci}
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_ci/*----------------------------------------------------------------*/
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_cistatic int disk_ll_load_ie(struct ll_disk *ll, dm_block_t index,
6968c2ecf20Sopenharmony_ci			   struct disk_index_entry *ie)
6978c2ecf20Sopenharmony_ci{
6988c2ecf20Sopenharmony_ci	return dm_btree_lookup(&ll->bitmap_info, ll->bitmap_root, &index, ie);
6998c2ecf20Sopenharmony_ci}
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_cistatic int disk_ll_save_ie(struct ll_disk *ll, dm_block_t index,
7028c2ecf20Sopenharmony_ci			   struct disk_index_entry *ie)
7038c2ecf20Sopenharmony_ci{
7048c2ecf20Sopenharmony_ci	__dm_bless_for_disk(ie);
7058c2ecf20Sopenharmony_ci	return dm_btree_insert(&ll->bitmap_info, ll->bitmap_root,
7068c2ecf20Sopenharmony_ci			       &index, ie, &ll->bitmap_root);
7078c2ecf20Sopenharmony_ci}
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_cistatic int disk_ll_init_index(struct ll_disk *ll)
7108c2ecf20Sopenharmony_ci{
7118c2ecf20Sopenharmony_ci	return dm_btree_empty(&ll->bitmap_info, &ll->bitmap_root);
7128c2ecf20Sopenharmony_ci}
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_cistatic int disk_ll_open(struct ll_disk *ll)
7158c2ecf20Sopenharmony_ci{
7168c2ecf20Sopenharmony_ci	/* nothing to do */
7178c2ecf20Sopenharmony_ci	return 0;
7188c2ecf20Sopenharmony_ci}
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_cistatic dm_block_t disk_ll_max_entries(struct ll_disk *ll)
7218c2ecf20Sopenharmony_ci{
7228c2ecf20Sopenharmony_ci	return -1ULL;
7238c2ecf20Sopenharmony_ci}
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_cistatic int disk_ll_commit(struct ll_disk *ll)
7268c2ecf20Sopenharmony_ci{
7278c2ecf20Sopenharmony_ci	return 0;
7288c2ecf20Sopenharmony_ci}
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ciint sm_ll_new_disk(struct ll_disk *ll, struct dm_transaction_manager *tm)
7318c2ecf20Sopenharmony_ci{
7328c2ecf20Sopenharmony_ci	int r;
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ci	r = sm_ll_init(ll, tm);
7358c2ecf20Sopenharmony_ci	if (r < 0)
7368c2ecf20Sopenharmony_ci		return r;
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci	ll->load_ie = disk_ll_load_ie;
7398c2ecf20Sopenharmony_ci	ll->save_ie = disk_ll_save_ie;
7408c2ecf20Sopenharmony_ci	ll->init_index = disk_ll_init_index;
7418c2ecf20Sopenharmony_ci	ll->open_index = disk_ll_open;
7428c2ecf20Sopenharmony_ci	ll->max_entries = disk_ll_max_entries;
7438c2ecf20Sopenharmony_ci	ll->commit = disk_ll_commit;
7448c2ecf20Sopenharmony_ci
7458c2ecf20Sopenharmony_ci	ll->nr_blocks = 0;
7468c2ecf20Sopenharmony_ci	ll->nr_allocated = 0;
7478c2ecf20Sopenharmony_ci
7488c2ecf20Sopenharmony_ci	r = ll->init_index(ll);
7498c2ecf20Sopenharmony_ci	if (r < 0)
7508c2ecf20Sopenharmony_ci		return r;
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_ci	r = dm_btree_empty(&ll->ref_count_info, &ll->ref_count_root);
7538c2ecf20Sopenharmony_ci	if (r < 0)
7548c2ecf20Sopenharmony_ci		return r;
7558c2ecf20Sopenharmony_ci
7568c2ecf20Sopenharmony_ci	return 0;
7578c2ecf20Sopenharmony_ci}
7588c2ecf20Sopenharmony_ci
7598c2ecf20Sopenharmony_ciint sm_ll_open_disk(struct ll_disk *ll, struct dm_transaction_manager *tm,
7608c2ecf20Sopenharmony_ci		    void *root_le, size_t len)
7618c2ecf20Sopenharmony_ci{
7628c2ecf20Sopenharmony_ci	int r;
7638c2ecf20Sopenharmony_ci	struct disk_sm_root *smr = root_le;
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_ci	if (len < sizeof(struct disk_sm_root)) {
7668c2ecf20Sopenharmony_ci		DMERR("sm_metadata root too small");
7678c2ecf20Sopenharmony_ci		return -ENOMEM;
7688c2ecf20Sopenharmony_ci	}
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_ci	r = sm_ll_init(ll, tm);
7718c2ecf20Sopenharmony_ci	if (r < 0)
7728c2ecf20Sopenharmony_ci		return r;
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_ci	ll->load_ie = disk_ll_load_ie;
7758c2ecf20Sopenharmony_ci	ll->save_ie = disk_ll_save_ie;
7768c2ecf20Sopenharmony_ci	ll->init_index = disk_ll_init_index;
7778c2ecf20Sopenharmony_ci	ll->open_index = disk_ll_open;
7788c2ecf20Sopenharmony_ci	ll->max_entries = disk_ll_max_entries;
7798c2ecf20Sopenharmony_ci	ll->commit = disk_ll_commit;
7808c2ecf20Sopenharmony_ci
7818c2ecf20Sopenharmony_ci	ll->nr_blocks = le64_to_cpu(smr->nr_blocks);
7828c2ecf20Sopenharmony_ci	ll->nr_allocated = le64_to_cpu(smr->nr_allocated);
7838c2ecf20Sopenharmony_ci	ll->bitmap_root = le64_to_cpu(smr->bitmap_root);
7848c2ecf20Sopenharmony_ci	ll->ref_count_root = le64_to_cpu(smr->ref_count_root);
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_ci	return ll->open_index(ll);
7878c2ecf20Sopenharmony_ci}
7888c2ecf20Sopenharmony_ci
7898c2ecf20Sopenharmony_ci/*----------------------------------------------------------------*/
790