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 static 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 int unlock_block(struct dm_btree_info
*info
, struct dm_block
*b
)
122 return 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 int r2
= unlock_block(s
->info
, s
->nodes
[i
]);
148 int ro_step(struct ro_spine
*s
, dm_block_t new_child
)
153 r
= unlock_block(s
->info
, s
->nodes
[0]);
156 s
->nodes
[0] = s
->nodes
[1];
160 r
= bn_read_lock(s
->info
, new_child
, s
->nodes
+ s
->count
);
167 void ro_pop(struct ro_spine
*s
)
171 unlock_block(s
->info
, s
->nodes
[s
->count
]);
174 struct btree_node
*ro_node(struct ro_spine
*s
)
176 struct dm_block
*block
;
179 block
= s
->nodes
[s
->count
- 1];
181 return dm_block_data(block
);
184 /*----------------------------------------------------------------*/
186 void init_shadow_spine(struct shadow_spine
*s
, struct dm_btree_info
*info
)
192 int exit_shadow_spine(struct shadow_spine
*s
)
196 for (i
= 0; i
< s
->count
; i
++) {
197 int r2
= unlock_block(s
->info
, s
->nodes
[i
]);
205 int shadow_step(struct shadow_spine
*s
, dm_block_t b
,
206 struct dm_btree_value_type
*vt
)
211 r
= unlock_block(s
->info
, s
->nodes
[0]);
214 s
->nodes
[0] = s
->nodes
[1];
218 r
= bn_shadow(s
->info
, b
, vt
, s
->nodes
+ s
->count
);
221 s
->root
= dm_block_location(s
->nodes
[0]);
229 struct dm_block
*shadow_current(struct shadow_spine
*s
)
233 return s
->nodes
[s
->count
- 1];
236 struct dm_block
*shadow_parent(struct shadow_spine
*s
)
238 BUG_ON(s
->count
!= 2);
240 return s
->count
== 2 ? s
->nodes
[0] : NULL
;
243 int shadow_has_parent(struct shadow_spine
*s
)
245 return s
->count
>= 2;
248 int shadow_root(struct shadow_spine
*s
)