1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2011 Red Hat, Inc.
5 * This file is released under the GPL.
8 #include "dm-btree-internal.h"
9 #include "dm-transaction-manager.h"
11 #include <linux/device-mapper.h>
13 #define DM_MSG_PREFIX "btree spine"
15 /*----------------------------------------------------------------*/
17 #define BTREE_CSUM_XOR 121107
19 static void node_prepare_for_write(const struct dm_block_validator
*v
,
23 struct btree_node
*n
= dm_block_data(b
);
24 struct node_header
*h
= &n
->header
;
26 h
->blocknr
= cpu_to_le64(dm_block_location(b
));
27 h
->csum
= cpu_to_le32(dm_bm_checksum(&h
->flags
,
28 block_size
- sizeof(__le32
),
32 static int node_check(const struct dm_block_validator
*v
,
36 struct btree_node
*n
= dm_block_data(b
);
37 struct node_header
*h
= &n
->header
;
40 uint32_t flags
, nr_entries
, max_entries
;
42 if (dm_block_location(b
) != le64_to_cpu(h
->blocknr
)) {
43 DMERR_LIMIT("%s failed: blocknr %llu != wanted %llu", __func__
,
44 le64_to_cpu(h
->blocknr
), dm_block_location(b
));
48 csum_disk
= cpu_to_le32(dm_bm_checksum(&h
->flags
,
49 block_size
- sizeof(__le32
),
51 if (csum_disk
!= h
->csum
) {
52 DMERR_LIMIT("%s failed: csum %u != wanted %u", __func__
,
53 le32_to_cpu(csum_disk
), le32_to_cpu(h
->csum
));
57 nr_entries
= le32_to_cpu(h
->nr_entries
);
58 max_entries
= le32_to_cpu(h
->max_entries
);
59 value_size
= le32_to_cpu(h
->value_size
);
61 if (sizeof(struct node_header
) +
62 (sizeof(__le64
) + value_size
) * max_entries
> block_size
) {
63 DMERR_LIMIT("%s failed: max_entries too large", __func__
);
67 if (nr_entries
> max_entries
) {
68 DMERR_LIMIT("%s failed: too many entries", __func__
);
73 * The node must be either INTERNAL or LEAF.
75 flags
= le32_to_cpu(h
->flags
);
76 if (!(flags
& INTERNAL_NODE
) && !(flags
& LEAF_NODE
)) {
77 DMERR_LIMIT("%s failed: node is neither INTERNAL or LEAF", __func__
);
84 const struct dm_block_validator btree_node_validator
= {
86 .prepare_for_write
= node_prepare_for_write
,
90 /*----------------------------------------------------------------*/
92 int bn_read_lock(struct dm_btree_info
*info
, dm_block_t b
,
93 struct dm_block
**result
)
95 return dm_tm_read_lock(info
->tm
, b
, &btree_node_validator
, result
);
98 static int bn_shadow(struct dm_btree_info
*info
, dm_block_t orig
,
99 struct dm_btree_value_type
*vt
,
100 struct dm_block
**result
)
104 r
= dm_tm_shadow_block(info
->tm
, orig
, &btree_node_validator
,
107 inc_children(info
->tm
, dm_block_data(*result
), vt
);
112 int new_block(struct dm_btree_info
*info
, struct dm_block
**result
)
114 return dm_tm_new_block(info
->tm
, &btree_node_validator
, result
);
117 void unlock_block(struct dm_btree_info
*info
, struct dm_block
*b
)
119 dm_tm_unlock(info
->tm
, b
);
122 /*----------------------------------------------------------------*/
124 void init_ro_spine(struct ro_spine
*s
, struct dm_btree_info
*info
)
132 void exit_ro_spine(struct ro_spine
*s
)
136 for (i
= 0; i
< s
->count
; i
++)
137 unlock_block(s
->info
, s
->nodes
[i
]);
140 int ro_step(struct ro_spine
*s
, dm_block_t new_child
)
145 unlock_block(s
->info
, s
->nodes
[0]);
146 s
->nodes
[0] = s
->nodes
[1];
150 r
= bn_read_lock(s
->info
, new_child
, s
->nodes
+ s
->count
);
157 void ro_pop(struct ro_spine
*s
)
161 unlock_block(s
->info
, s
->nodes
[s
->count
]);
164 struct btree_node
*ro_node(struct ro_spine
*s
)
166 struct dm_block
*block
;
169 block
= s
->nodes
[s
->count
- 1];
171 return dm_block_data(block
);
174 /*----------------------------------------------------------------*/
176 void init_shadow_spine(struct shadow_spine
*s
, struct dm_btree_info
*info
)
182 void exit_shadow_spine(struct shadow_spine
*s
)
186 for (i
= 0; i
< s
->count
; i
++)
187 unlock_block(s
->info
, s
->nodes
[i
]);
190 int shadow_step(struct shadow_spine
*s
, dm_block_t b
,
191 struct dm_btree_value_type
*vt
)
196 unlock_block(s
->info
, s
->nodes
[0]);
197 s
->nodes
[0] = s
->nodes
[1];
201 r
= bn_shadow(s
->info
, b
, vt
, s
->nodes
+ s
->count
);
204 s
->root
= dm_block_location(s
->nodes
[0]);
212 struct dm_block
*shadow_current(struct shadow_spine
*s
)
216 return s
->nodes
[s
->count
- 1];
219 struct dm_block
*shadow_parent(struct shadow_spine
*s
)
221 BUG_ON(s
->count
!= 2);
223 return s
->count
== 2 ? s
->nodes
[0] : NULL
;
226 int shadow_has_parent(struct shadow_spine
*s
)
228 return s
->count
>= 2;
231 dm_block_t
shadow_root(struct shadow_spine
*s
)
236 static void le64_inc(void *context
, const void *value_le
, unsigned int count
)
238 dm_tm_with_runs(context
, value_le
, count
, dm_tm_inc_range
);
241 static void le64_dec(void *context
, const void *value_le
, unsigned int count
)
243 dm_tm_with_runs(context
, value_le
, count
, dm_tm_dec_range
);
246 static int le64_equal(void *context
, const void *value1_le
, const void *value2_le
)
250 memcpy(&v1_le
, value1_le
, sizeof(v1_le
));
251 memcpy(&v2_le
, value2_le
, sizeof(v2_le
));
252 return v1_le
== v2_le
;
255 void init_le64_type(struct dm_transaction_manager
*tm
,
256 struct dm_btree_value_type
*vt
)
259 vt
->size
= sizeof(__le64
);
262 vt
->equal
= le64_equal
;