13bd94003SHeinz Mauelshagen /* SPDX-License-Identifier: GPL-2.0-only */
23241b1d3SJoe Thornber /*
33241b1d3SJoe Thornber  * Copyright (C) 2011 Red Hat, Inc.
43241b1d3SJoe Thornber  *
53241b1d3SJoe Thornber  * This file is released under the GPL.
63241b1d3SJoe Thornber  */
73241b1d3SJoe Thornber 
83241b1d3SJoe Thornber #ifndef DM_BTREE_INTERNAL_H
93241b1d3SJoe Thornber #define DM_BTREE_INTERNAL_H
103241b1d3SJoe Thornber 
113241b1d3SJoe Thornber #include "dm-btree.h"
123241b1d3SJoe Thornber 
133241b1d3SJoe Thornber /*----------------------------------------------------------------*/
143241b1d3SJoe Thornber 
153241b1d3SJoe Thornber /*
163241b1d3SJoe Thornber  * We'll need 2 accessor functions for n->csum and n->blocknr
173241b1d3SJoe Thornber  * to support dm-btree-spine.c in that case.
183241b1d3SJoe Thornber  */
193241b1d3SJoe Thornber 
203241b1d3SJoe Thornber enum node_flags {
213241b1d3SJoe Thornber 	INTERNAL_NODE = 1,
223241b1d3SJoe Thornber 	LEAF_NODE = 1 << 1
233241b1d3SJoe Thornber };
243241b1d3SJoe Thornber 
253241b1d3SJoe Thornber /*
263241b1d3SJoe Thornber  * Every btree node begins with this structure.  Make sure it's a multiple
273241b1d3SJoe Thornber  * of 8-bytes in size, otherwise the 64bit keys will be mis-aligned.
283241b1d3SJoe Thornber  */
293241b1d3SJoe Thornber struct node_header {
303241b1d3SJoe Thornber 	__le32 csum;
313241b1d3SJoe Thornber 	__le32 flags;
323241b1d3SJoe Thornber 	__le64 blocknr; /* Block this node is supposed to live in. */
333241b1d3SJoe Thornber 
343241b1d3SJoe Thornber 	__le32 nr_entries;
353241b1d3SJoe Thornber 	__le32 max_entries;
363241b1d3SJoe Thornber 	__le32 value_size;
373241b1d3SJoe Thornber 	__le32 padding;
38*ae99111eSHeinz Mauelshagen } __packed __aligned(8);
393241b1d3SJoe Thornber 
40550929faSMikulas Patocka struct btree_node {
413241b1d3SJoe Thornber 	struct node_header header;
42b18ae8ddSGustavo A. R. Silva 	__le64 keys[];
43*ae99111eSHeinz Mauelshagen } __packed __aligned(8);
443241b1d3SJoe Thornber 
453241b1d3SJoe Thornber 
469b460d36SJoe Thornber /*
479b460d36SJoe Thornber  * Locks a block using the btree node validator.
489b460d36SJoe Thornber  */
499b460d36SJoe Thornber int bn_read_lock(struct dm_btree_info *info, dm_block_t b,
509b460d36SJoe Thornber 		 struct dm_block **result);
519b460d36SJoe Thornber 
52550929faSMikulas Patocka void inc_children(struct dm_transaction_manager *tm, struct btree_node *n,
533241b1d3SJoe Thornber 		  struct dm_btree_value_type *vt);
543241b1d3SJoe Thornber 
553241b1d3SJoe Thornber int new_block(struct dm_btree_info *info, struct dm_block **result);
564c7da06fSMikulas Patocka void unlock_block(struct dm_btree_info *info, struct dm_block *b);
573241b1d3SJoe Thornber 
583241b1d3SJoe Thornber /*
593241b1d3SJoe Thornber  * Spines keep track of the rolling locks.  There are 2 variants, read-only
603241b1d3SJoe Thornber  * and one that uses shadowing.  These are separate structs to allow the
613241b1d3SJoe Thornber  * type checker to spot misuse, for example accidentally calling read_lock
623241b1d3SJoe Thornber  * on a shadow spine.
633241b1d3SJoe Thornber  */
643241b1d3SJoe Thornber struct ro_spine {
653241b1d3SJoe Thornber 	struct dm_btree_info *info;
663241b1d3SJoe Thornber 
673241b1d3SJoe Thornber 	int count;
683241b1d3SJoe Thornber 	struct dm_block *nodes[2];
693241b1d3SJoe Thornber };
703241b1d3SJoe Thornber 
713241b1d3SJoe Thornber void init_ro_spine(struct ro_spine *s, struct dm_btree_info *info);
729431cf6eSZhiqiang Liu void exit_ro_spine(struct ro_spine *s);
733241b1d3SJoe Thornber int ro_step(struct ro_spine *s, dm_block_t new_child);
744e7f1f90SJoe Thornber void ro_pop(struct ro_spine *s);
75550929faSMikulas Patocka struct btree_node *ro_node(struct ro_spine *s);
763241b1d3SJoe Thornber 
773241b1d3SJoe Thornber struct shadow_spine {
783241b1d3SJoe Thornber 	struct dm_btree_info *info;
793241b1d3SJoe Thornber 
803241b1d3SJoe Thornber 	int count;
813241b1d3SJoe Thornber 	struct dm_block *nodes[2];
823241b1d3SJoe Thornber 
833241b1d3SJoe Thornber 	dm_block_t root;
843241b1d3SJoe Thornber };
853241b1d3SJoe Thornber 
863241b1d3SJoe Thornber void init_shadow_spine(struct shadow_spine *s, struct dm_btree_info *info);
87ece25773SJiapeng Chong void exit_shadow_spine(struct shadow_spine *s);
883241b1d3SJoe Thornber 
893241b1d3SJoe Thornber int shadow_step(struct shadow_spine *s, dm_block_t b,
903241b1d3SJoe Thornber 		struct dm_btree_value_type *vt);
913241b1d3SJoe Thornber 
923241b1d3SJoe Thornber /*
933241b1d3SJoe Thornber  * The spine must have at least one entry before calling this.
943241b1d3SJoe Thornber  */
953241b1d3SJoe Thornber struct dm_block *shadow_current(struct shadow_spine *s);
963241b1d3SJoe Thornber 
973241b1d3SJoe Thornber /*
983241b1d3SJoe Thornber  * The spine must have at least two entries before calling this.
993241b1d3SJoe Thornber  */
1003241b1d3SJoe Thornber struct dm_block *shadow_parent(struct shadow_spine *s);
1013241b1d3SJoe Thornber 
1023241b1d3SJoe Thornber int shadow_has_parent(struct shadow_spine *s);
1033241b1d3SJoe Thornber 
1044c9e9883SJinoh Kang dm_block_t shadow_root(struct shadow_spine *s);
1053241b1d3SJoe Thornber 
1063241b1d3SJoe Thornber /*
1073241b1d3SJoe Thornber  * Some inlines.
1083241b1d3SJoe Thornber  */
key_ptr(struct btree_node * n,uint32_t index)109550929faSMikulas Patocka static inline __le64 *key_ptr(struct btree_node *n, uint32_t index)
1103241b1d3SJoe Thornber {
1113241b1d3SJoe Thornber 	return n->keys + index;
1123241b1d3SJoe Thornber }
1133241b1d3SJoe Thornber 
value_base(struct btree_node * n)114550929faSMikulas Patocka static inline void *value_base(struct btree_node *n)
1153241b1d3SJoe Thornber {
1163241b1d3SJoe Thornber 	return &n->keys[le32_to_cpu(n->header.max_entries)];
1173241b1d3SJoe Thornber }
1183241b1d3SJoe Thornber 
value_ptr(struct btree_node * n,uint32_t index)119550929faSMikulas Patocka static inline void *value_ptr(struct btree_node *n, uint32_t index)
1203241b1d3SJoe Thornber {
121a3aefb39SJoe Thornber 	uint32_t value_size = le32_to_cpu(n->header.value_size);
1220ef0b471SHeinz Mauelshagen 
1233241b1d3SJoe Thornber 	return value_base(n) + (value_size * index);
1243241b1d3SJoe Thornber }
1253241b1d3SJoe Thornber 
1263241b1d3SJoe Thornber /*
1273241b1d3SJoe Thornber  * Assumes the values are suitably-aligned and converts to core format.
1283241b1d3SJoe Thornber  */
value64(struct btree_node * n,uint32_t index)129550929faSMikulas Patocka static inline uint64_t value64(struct btree_node *n, uint32_t index)
1303241b1d3SJoe Thornber {
1313241b1d3SJoe Thornber 	__le64 *values_le = value_base(n);
1323241b1d3SJoe Thornber 
1333241b1d3SJoe Thornber 	return le64_to_cpu(values_le[index]);
1343241b1d3SJoe Thornber }
1353241b1d3SJoe Thornber 
1363241b1d3SJoe Thornber /*
1373241b1d3SJoe Thornber  * Searching for a key within a single node.
1383241b1d3SJoe Thornber  */
139550929faSMikulas Patocka int lower_bound(struct btree_node *n, uint64_t key);
1403241b1d3SJoe Thornber 
1413241b1d3SJoe Thornber extern struct dm_block_validator btree_node_validator;
1423241b1d3SJoe Thornber 
143b0dc3c8bSJoe Thornber /*
144b0dc3c8bSJoe Thornber  * Value type for upper levels of multi-level btrees.
145b0dc3c8bSJoe Thornber  */
146b0dc3c8bSJoe Thornber extern void init_le64_type(struct dm_transaction_manager *tm,
147b0dc3c8bSJoe Thornber 			   struct dm_btree_value_type *vt);
148b0dc3c8bSJoe Thornber 
149be500ed7SJoe Thornber /*
150be500ed7SJoe Thornber  * This returns a shadowed btree leaf that you may modify.  In practise
151be500ed7SJoe Thornber  * this means overwrites only, since an insert could cause a node to
152be500ed7SJoe Thornber  * be split.  Useful if you need access to the old value to calculate the
153be500ed7SJoe Thornber  * new one.
154be500ed7SJoe Thornber  *
155be500ed7SJoe Thornber  * This only works with single level btrees.  The given key must be present in
156be500ed7SJoe Thornber  * the tree, otherwise -EINVAL will be returned.
157be500ed7SJoe Thornber  */
158be500ed7SJoe Thornber int btree_get_overwrite_leaf(struct dm_btree_info *info, dm_block_t root,
159be500ed7SJoe Thornber 			     uint64_t key, int *index,
160be500ed7SJoe Thornber 			     dm_block_t *new_root, struct dm_block **leaf);
161be500ed7SJoe Thornber 
1623241b1d3SJoe Thornber #endif	/* DM_BTREE_INTERNAL_H */
163