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 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 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("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("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("node_check failed: max_entries too large");
70 if (le32_to_cpu(h
->nr_entries
) > le32_to_cpu(h
->max_entries
)) {
71 DMERR("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("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 struct node
*ro_node(struct ro_spine
*s
)
169 struct dm_block
*block
;
172 block
= s
->nodes
[s
->count
- 1];
174 return dm_block_data(block
);
177 /*----------------------------------------------------------------*/
179 void init_shadow_spine(struct shadow_spine
*s
, struct dm_btree_info
*info
)
185 int exit_shadow_spine(struct shadow_spine
*s
)
189 for (i
= 0; i
< s
->count
; i
++) {
190 int r2
= unlock_block(s
->info
, s
->nodes
[i
]);
198 int shadow_step(struct shadow_spine
*s
, dm_block_t b
,
199 struct dm_btree_value_type
*vt
)
204 r
= unlock_block(s
->info
, s
->nodes
[0]);
207 s
->nodes
[0] = s
->nodes
[1];
211 r
= bn_shadow(s
->info
, b
, vt
, s
->nodes
+ s
->count
);
214 s
->root
= dm_block_location(s
->nodes
[0]);
222 struct dm_block
*shadow_current(struct shadow_spine
*s
)
226 return s
->nodes
[s
->count
- 1];
229 struct dm_block
*shadow_parent(struct shadow_spine
*s
)
231 BUG_ON(s
->count
!= 2);
233 return s
->count
== 2 ? s
->nodes
[0] : NULL
;
236 int shadow_has_parent(struct shadow_spine
*s
)
238 return s
->count
>= 2;
241 int shadow_root(struct shadow_spine
*s
)