2 * Copyright (C) 2011 Red Hat, Inc. All rights reserved.
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 static void node_prepare_for_write(struct dm_block_validator
*v
,
20 struct node
*n
= dm_block_data(b
);
21 struct node_header
*h
= &n
->header
;
23 h
->blocknr
= cpu_to_le64(dm_block_location(b
));
24 h
->csum
= cpu_to_le32(dm_block_csum_data(&h
->flags
, block_size
- sizeof(__le32
)));
27 static int node_check(struct dm_block_validator
*v
,
31 struct node
*n
= dm_block_data(b
);
32 struct node_header
*h
= &n
->header
;
36 if (dm_block_location(b
) != le64_to_cpu(h
->blocknr
)) {
37 DMERR("node_check failed blocknr %llu wanted %llu",
38 le64_to_cpu(h
->blocknr
), dm_block_location(b
));
42 csum_disk
= cpu_to_le32(dm_block_csum_data(&h
->flags
, block_size
- sizeof(__le32
)));
43 if (csum_disk
!= h
->csum
) {
44 DMERR("node_check failed csum %u wanted %u",
45 le32_to_cpu(csum_disk
), le32_to_cpu(h
->csum
));
49 value_size
= le32_to_cpu(h
->value_size
);
51 if (sizeof(struct node_header
) +
52 (sizeof(__le64
) + value_size
) * le32_to_cpu(h
->max_entries
) > block_size
) {
53 DMERR("node_check failed: max_entries too large");
57 if (le32_to_cpu(h
->nr_entries
) > le32_to_cpu(h
->max_entries
)) {
58 DMERR("node_check failed, too many entries");
65 struct dm_block_validator btree_node_validator
= {
67 .prepare_for_write
= node_prepare_for_write
,
71 /*----------------------------------------------------------------*/
73 static int bn_read_lock(struct dm_btree_info
*info
, dm_block_t b
,
74 struct dm_block
**result
)
76 return dm_tm_read_lock(info
->tm
, b
, &btree_node_validator
, result
);
79 static int bn_shadow(struct dm_btree_info
*info
, dm_block_t orig
,
80 struct dm_btree_value_type
*vt
,
81 struct dm_block
**result
, int *inc
)
85 r
= dm_tm_shadow_block(info
->tm
, orig
, &btree_node_validator
,
88 inc_children(info
->tm
, dm_block_data(*result
), vt
);
93 int new_block(struct dm_btree_info
*info
, struct dm_block
**result
)
95 return dm_tm_new_block(info
->tm
, &btree_node_validator
, result
);
98 int unlock_block(struct dm_btree_info
*info
, struct dm_block
*b
)
100 return dm_tm_unlock(info
->tm
, b
);
103 /*----------------------------------------------------------------*/
105 void init_ro_spine(struct ro_spine
*s
, struct dm_btree_info
*info
)
113 int exit_ro_spine(struct ro_spine
*s
)
117 for (i
= 0; i
< s
->count
; i
++) {
118 int r2
= unlock_block(s
->info
, s
->nodes
[i
]);
126 int ro_step(struct ro_spine
*s
, dm_block_t new_child
)
131 r
= unlock_block(s
->info
, s
->nodes
[0]);
134 s
->nodes
[0] = s
->nodes
[1];
138 r
= bn_read_lock(s
->info
, new_child
, s
->nodes
+ s
->count
);
145 struct node
*ro_node(struct ro_spine
*s
)
147 struct dm_block
*block
;
150 block
= s
->nodes
[s
->count
- 1];
152 return dm_block_data(block
);
155 /*----------------------------------------------------------------*/
157 void init_shadow_spine(struct shadow_spine
*s
, struct dm_btree_info
*info
)
163 int exit_shadow_spine(struct shadow_spine
*s
)
167 for (i
= 0; i
< s
->count
; i
++) {
168 int r2
= unlock_block(s
->info
, s
->nodes
[i
]);
176 int shadow_step(struct shadow_spine
*s
, dm_block_t b
,
177 struct dm_btree_value_type
*vt
, int *inc
)
182 r
= unlock_block(s
->info
, s
->nodes
[0]);
185 s
->nodes
[0] = s
->nodes
[1];
189 r
= bn_shadow(s
->info
, b
, vt
, s
->nodes
+ s
->count
, inc
);
192 s
->root
= dm_block_location(s
->nodes
[0]);
200 struct dm_block
*shadow_current(struct shadow_spine
*s
)
204 return s
->nodes
[s
->count
- 1];
207 struct dm_block
*shadow_parent(struct shadow_spine
*s
)
209 BUG_ON(s
->count
!= 2);
211 return s
->count
== 2 ? s
->nodes
[0] : NULL
;
214 int shadow_has_parent(struct shadow_spine
*s
)
216 return s
->count
>= 2;
219 int shadow_root(struct shadow_spine
*s
)