diff options
Diffstat (limited to 'drivers/md/persistent-data/dm-btree-spine.c')
| -rw-r--r-- | drivers/md/persistent-data/dm-btree-spine.c | 102 |
1 files changed, 57 insertions, 45 deletions
diff --git a/drivers/md/persistent-data/dm-btree-spine.c b/drivers/md/persistent-data/dm-btree-spine.c index cf9fd676ae44..c46fc50c274e 100644 --- a/drivers/md/persistent-data/dm-btree-spine.c +++ b/drivers/md/persistent-data/dm-btree-spine.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) 2011 Red Hat, Inc. * @@ -15,11 +16,7 @@ #define BTREE_CSUM_XOR 121107 -static int node_check(struct dm_block_validator *v, - struct dm_block *b, - size_t block_size); - -static void node_prepare_for_write(struct dm_block_validator *v, +static void node_prepare_for_write(const struct dm_block_validator *v, struct dm_block *b, size_t block_size) { @@ -30,11 +27,9 @@ static void node_prepare_for_write(struct dm_block_validator *v, h->csum = cpu_to_le32(dm_bm_checksum(&h->flags, block_size - sizeof(__le32), BTREE_CSUM_XOR)); - - BUG_ON(node_check(v, b, 4096)); } -static int node_check(struct dm_block_validator *v, +static int node_check(const struct dm_block_validator *v, struct dm_block *b, size_t block_size) { @@ -42,10 +37,10 @@ static int node_check(struct dm_block_validator *v, struct node_header *h = &n->header; size_t value_size; __le32 csum_disk; - uint32_t flags; + uint32_t flags, nr_entries, max_entries; if (dm_block_location(b) != le64_to_cpu(h->blocknr)) { - DMERR_LIMIT("node_check failed: blocknr %llu != wanted %llu", + DMERR_LIMIT("%s failed: blocknr %llu != wanted %llu", __func__, le64_to_cpu(h->blocknr), dm_block_location(b)); return -ENOTBLK; } @@ -54,21 +49,23 @@ static int node_check(struct dm_block_validator *v, block_size - sizeof(__le32), BTREE_CSUM_XOR)); if (csum_disk != h->csum) { - DMERR_LIMIT("node_check failed: csum %u != wanted %u", + DMERR_LIMIT("%s failed: csum %u != wanted %u", __func__, le32_to_cpu(csum_disk), le32_to_cpu(h->csum)); return -EILSEQ; } + nr_entries = le32_to_cpu(h->nr_entries); + max_entries = le32_to_cpu(h->max_entries); value_size = le32_to_cpu(h->value_size); if (sizeof(struct node_header) + - (sizeof(__le64) + value_size) * le32_to_cpu(h->max_entries) > block_size) { - DMERR_LIMIT("node_check failed: max_entries too large"); + (sizeof(__le64) + value_size) * max_entries > block_size) { + DMERR_LIMIT("%s failed: max_entries too large", __func__); return -EILSEQ; } - if (le32_to_cpu(h->nr_entries) > le32_to_cpu(h->max_entries)) { - DMERR_LIMIT("node_check failed: too many entries"); + if (nr_entries > max_entries) { + DMERR_LIMIT("%s failed: too many entries", __func__); return -EILSEQ; } @@ -77,14 +74,14 @@ static int node_check(struct dm_block_validator *v, */ flags = le32_to_cpu(h->flags); if (!(flags & INTERNAL_NODE) && !(flags & LEAF_NODE)) { - DMERR_LIMIT("node_check failed: node is neither INTERNAL or LEAF"); + DMERR_LIMIT("%s failed: node is neither INTERNAL or LEAF", __func__); return -EILSEQ; } return 0; } -struct dm_block_validator btree_node_validator = { +const struct dm_block_validator btree_node_validator = { .name = "btree_node", .prepare_for_write = node_prepare_for_write, .check = node_check @@ -92,7 +89,7 @@ struct dm_block_validator btree_node_validator = { /*----------------------------------------------------------------*/ -static int bn_read_lock(struct dm_btree_info *info, dm_block_t b, +int bn_read_lock(struct dm_btree_info *info, dm_block_t b, struct dm_block **result) { return dm_tm_read_lock(info->tm, b, &btree_node_validator, result); @@ -117,9 +114,9 @@ int new_block(struct dm_btree_info *info, struct dm_block **result) return dm_tm_new_block(info->tm, &btree_node_validator, result); } -int unlock_block(struct dm_btree_info *info, struct dm_block *b) +void unlock_block(struct dm_btree_info *info, struct dm_block *b) { - return dm_tm_unlock(info->tm, b); + dm_tm_unlock(info->tm, b); } /*----------------------------------------------------------------*/ @@ -132,17 +129,12 @@ void init_ro_spine(struct ro_spine *s, struct dm_btree_info *info) s->nodes[1] = NULL; } -int exit_ro_spine(struct ro_spine *s) +void exit_ro_spine(struct ro_spine *s) { - int r = 0, i; + int i; - for (i = 0; i < s->count; i++) { - int r2 = unlock_block(s->info, s->nodes[i]); - if (r2 < 0) - r = r2; - } - - return r; + for (i = 0; i < s->count; i++) + unlock_block(s->info, s->nodes[i]); } int ro_step(struct ro_spine *s, dm_block_t new_child) @@ -150,9 +142,7 @@ int ro_step(struct ro_spine *s, dm_block_t new_child) int r; if (s->count == 2) { - r = unlock_block(s->info, s->nodes[0]); - if (r < 0) - return r; + unlock_block(s->info, s->nodes[0]); s->nodes[0] = s->nodes[1]; s->count--; } @@ -189,17 +179,12 @@ void init_shadow_spine(struct shadow_spine *s, struct dm_btree_info *info) s->count = 0; } -int exit_shadow_spine(struct shadow_spine *s) +void exit_shadow_spine(struct shadow_spine *s) { - int r = 0, i; + int i; - for (i = 0; i < s->count; i++) { - int r2 = unlock_block(s->info, s->nodes[i]); - if (r2 < 0) - r = r2; - } - - return r; + for (i = 0; i < s->count; i++) + unlock_block(s->info, s->nodes[i]); } int shadow_step(struct shadow_spine *s, dm_block_t b, @@ -208,9 +193,7 @@ int shadow_step(struct shadow_spine *s, dm_block_t b, int r; if (s->count == 2) { - r = unlock_block(s->info, s->nodes[0]); - if (r < 0) - return r; + unlock_block(s->info, s->nodes[0]); s->nodes[0] = s->nodes[1]; s->count--; } @@ -245,7 +228,36 @@ int shadow_has_parent(struct shadow_spine *s) return s->count >= 2; } -int shadow_root(struct shadow_spine *s) +dm_block_t shadow_root(struct shadow_spine *s) { return s->root; } + +static void le64_inc(void *context, const void *value_le, unsigned int count) +{ + dm_tm_with_runs(context, value_le, count, dm_tm_inc_range); +} + +static void le64_dec(void *context, const void *value_le, unsigned int count) +{ + dm_tm_with_runs(context, value_le, count, dm_tm_dec_range); +} + +static int le64_equal(void *context, const void *value1_le, const void *value2_le) +{ + __le64 v1_le, v2_le; + + memcpy(&v1_le, value1_le, sizeof(v1_le)); + memcpy(&v2_le, value2_le, sizeof(v2_le)); + return v1_le == v2_le; +} + +void init_le64_type(struct dm_transaction_manager *tm, + struct dm_btree_value_type *vt) +{ + vt->context = tm; + vt->size = sizeof(__le64); + vt->inc = le64_inc; + vt->dec = le64_dec; + vt->equal = le64_equal; +} |
