2 * Copyright (C) 2011 Red Hat, Inc.
4 * This file is released under the GPL.
7 #include "dm-btree-internal.h"
8 #include "dm-transaction-manager.h"
10 #include <linux/device-mapper.h>
12 #define DM_MSG_PREFIX "btree spine"
14 /*----------------------------------------------------------------*/
16 #define BTREE_CSUM_XOR 121107
18 static int node_check(struct dm_block_validator
*v
,
22 static void node_prepare_for_write(struct dm_block_validator
*v
,
26 struct btree_node
*n
= dm_block_data(b
);
27 struct node_header
*h
= &n
->header
;
29 h
->blocknr
= cpu_to_le64(dm_block_location(b
));
30 h
->csum
= cpu_to_le32(dm_bm_checksum(&h
->flags
,
31 block_size
- sizeof(__le32
),
34 BUG_ON(node_check(v
, b
, 4096));
37 static int node_check(struct dm_block_validator
*v
,
41 struct btree_node
*n
= dm_block_data(b
);
42 struct node_header
*h
= &n
->header
;
47 if (dm_block_location(b
) != le64_to_cpu(h
->blocknr
)) {
48 DMERR_LIMIT("node_check failed: blocknr %llu != wanted %llu",
49 le64_to_cpu(h
->blocknr
), dm_block_location(b
));
53 csum_disk
= cpu_to_le32(dm_bm_checksum(&h
->flags
,
54 block_size
- sizeof(__le32
),
56 if (csum_disk
!= h
->csum
) {
57 DMERR_LIMIT("node_check failed: csum %u != wanted %u",
58 le32_to_cpu(csum_disk
), le32_to_cpu(h
->csum
));
62 value_size
= le32_to_cpu(h
->value_size
);
64 if (sizeof(struct node_header
) +
65 (sizeof(__le64
) + value_size
) * le32_to_cpu(h
->max_entries
) > block_size
) {
66 DMERR_LIMIT("node_check failed: max_entries too large");
70 if (le32_to_cpu(h
->nr_entries
) > le32_to_cpu(h
->max_entries
)) {
71 DMERR_LIMIT("node_check failed: too many entries");
76 * The node must be either INTERNAL or LEAF.
78 flags
= le32_to_cpu(h
->flags
);
79 if (!(flags
& INTERNAL_NODE
) && !(flags
& LEAF_NODE
)) {
80 DMERR_LIMIT("node_check failed: node is neither INTERNAL or LEAF");
87 struct dm_block_validator btree_node_validator
= {
89 .prepare_for_write
= node_prepare_for_write
,
93 /*----------------------------------------------------------------*/
95 int bn_read_lock(struct dm_btree_info
*info
, dm_block_t b
,
96 struct dm_block
**result
)
98 return dm_tm_read_lock(info
->tm
, b
, &btree_node_validator
, result
);
101 static int bn_shadow(struct dm_btree_info
*info
, dm_block_t orig
,
102 struct dm_btree_value_type
*vt
,
103 struct dm_block
**result
)
107 r
= dm_tm_shadow_block(info
->tm
, orig
, &btree_node_validator
,
110 inc_children(info
->tm
, dm_block_data(*result
), vt
);
115 int new_block(struct dm_btree_info
*info
, struct dm_block
**result
)
117 return dm_tm_new_block(info
->tm
, &btree_node_validator
, result
);
120 void unlock_block(struct dm_btree_info
*info
, struct dm_block
*b
)
122 dm_tm_unlock(info
->tm
, b
);
125 /*----------------------------------------------------------------*/
127 void init_ro_spine(struct ro_spine
*s
, struct dm_btree_info
*info
)
135 int exit_ro_spine(struct ro_spine
*s
)
139 for (i
= 0; i
< s
->count
; i
++) {
140 unlock_block(s
->info
, s
->nodes
[i
]);
146 int ro_step(struct ro_spine
*s
, dm_block_t new_child
)
151 unlock_block(s
->info
, s
->nodes
[0]);
152 s
->nodes
[0] = s
->nodes
[1];
156 r
= bn_read_lock(s
->info
, new_child
, s
->nodes
+ s
->count
);
163 void ro_pop(struct ro_spine
*s
)
167 unlock_block(s
->info
, s
->nodes
[s
->count
]);
170 struct btree_node
*ro_node(struct ro_spine
*s
)
172 struct dm_block
*block
;
175 block
= s
->nodes
[s
->count
- 1];
177 return dm_block_data(block
);
180 /*----------------------------------------------------------------*/
182 void init_shadow_spine(struct shadow_spine
*s
, struct dm_btree_info
*info
)
188 int exit_shadow_spine(struct shadow_spine
*s
)
192 for (i
= 0; i
< s
->count
; i
++) {
193 unlock_block(s
->info
, s
->nodes
[i
]);
199 int shadow_step(struct shadow_spine
*s
, dm_block_t b
,
200 struct dm_btree_value_type
*vt
)
205 unlock_block(s
->info
, s
->nodes
[0]);
206 s
->nodes
[0] = s
->nodes
[1];
210 r
= bn_shadow(s
->info
, b
, vt
, s
->nodes
+ s
->count
);
213 s
->root
= dm_block_location(s
->nodes
[0]);
221 struct dm_block
*shadow_current(struct shadow_spine
*s
)
225 return s
->nodes
[s
->count
- 1];
228 struct dm_block
*shadow_parent(struct shadow_spine
*s
)
230 BUG_ON(s
->count
!= 2);
232 return s
->count
== 2 ? s
->nodes
[0] : NULL
;
235 int shadow_has_parent(struct shadow_spine
*s
)
237 return s
->count
>= 2;
240 int shadow_root(struct shadow_spine
*s
)
245 static void le64_inc(void *context
, const void *value_le
)
247 struct dm_transaction_manager
*tm
= context
;
250 memcpy(&v_le
, value_le
, sizeof(v_le
));
251 dm_tm_inc(tm
, le64_to_cpu(v_le
));
254 static void le64_dec(void *context
, const void *value_le
)
256 struct dm_transaction_manager
*tm
= context
;
259 memcpy(&v_le
, value_le
, sizeof(v_le
));
260 dm_tm_dec(tm
, le64_to_cpu(v_le
));
263 static int le64_equal(void *context
, const void *value1_le
, const void *value2_le
)
267 memcpy(&v1_le
, value1_le
, sizeof(v1_le
));
268 memcpy(&v2_le
, value2_le
, sizeof(v2_le
));
269 return v1_le
== v2_le
;
272 void init_le64_type(struct dm_transaction_manager
*tm
,
273 struct dm_btree_value_type
*vt
)
276 vt
->size
= sizeof(__le64
);
279 vt
->equal
= le64_equal
;