File: btree.h

package info (click to toggle)
apfsprogs 0.2.1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,112 kB
  • sloc: ansic: 16,034; makefile: 175; sh: 57
file content (238 lines) | stat: -rw-r--r-- 7,298 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
/*
 * Copyright (C) 2019 Ernesto A. Fernández <ernesto.mnd.fernandez@gmail.com>
 */

#ifndef _BTREE_H
#define _BTREE_H

#include <apfs/raw.h>
#include <apfs/types.h>
#include "htable.h"
#include "object.h"

struct super_block;
struct extref_record;
struct free_queue;

/*
 * Omap record data in memory
 */
struct omap_record {
	struct omap_record *next; /* Next entry in linked list */

	u64	xid;	/* Transaction id */
	u64	oid;	/* Virtual object id */
	u64	bno;	/* Block number */
	u32	flags;	/* Omap record flags */

	/* Was this oid-xid pair ever seen in use? */
	bool	seen;
	/* Was it ever seen in use for the latest checkpoint? */
	bool	seen_for_latest;
	/* If we are currently checking a snapshot, was it seen in use for it? */
	bool	seen_for_snap;
};

/*
 * List of all omap records for a given oid
 */
struct omap_record_list {
	struct htable_entry	o_htable;	/* Hash table entry header */
	struct omap_record 	*o_records;	/* Linked list of records */
};

/*
 * In-memory representation of an APFS node
 */
struct node {
	u16 flags;		/* Node flags */
	u32 records;		/* Number of records in the node */
	int level;		/* Number of child levels below this node */

	int toc;		/* Offset of the TOC in the block */
	int key;		/* Offset of the key area in the block */
	int free;		/* Offset of the free area in the block */
	int data;		/* Offset of the data area in the block */

	u8 *free_key_bmap;	/* Free space bitmap for the key area */
	u8 *free_val_bmap;	/* Free space bitmap for the value area */
	u8 *used_key_bmap;	/* Used space bitmap for the key area */
	u8 *used_val_bmap;	/* Used space bitmap for the value area */

	struct btree *btree;			/* Btree the node belongs to */
	struct apfs_btree_node_phys *raw;	/* Raw node in memory */
	struct object object;			/* Object holding the node */
};

/**
 * apfs_node_is_leaf - Check if a b-tree node is a leaf
 * @node: the node to check
 */
static inline bool node_is_leaf(struct node *node)
{
	return (node->flags & APFS_BTNODE_LEAF) != 0;
}

/**
 * apfs_node_is_root - Check if a b-tree node is the root
 * @node: the node to check
 */
static inline bool node_is_root(struct node *node)
{
	return (node->flags & APFS_BTNODE_ROOT) != 0;
}

/**
 * apfs_node_has_fixed_kv_size - Check if a b-tree node has fixed key/value
 * sizes
 * @node: the node to check
 */
static inline bool node_has_fixed_kv_size(struct node *node)
{
	return (node->flags & APFS_BTNODE_FIXED_KV_SIZE) != 0;
}

/* Flags for the query structure */
#define QUERY_TREE_MASK		0017	/* Which b-tree we query */
#define QUERY_OMAP		0001	/* This is a b-tree object map query */
#define QUERY_CAT		0002	/* This is a catalog tree query */
#define QUERY_EXTENTREF		0004	/* This is an extentref tree query */
#define QUERY_FEXT		0010	/* This is an extentref tree query */
#define QUERY_MULTIPLE		0020	/* Search for multiple matches */
#define QUERY_NEXT		0040	/* Find next of multiple matches */
#define QUERY_EXACT		0100	/* Search for an exact match */
#define QUERY_DONE		0200	/* The search at this level is over */

/*
 * Structure used to retrieve data from an APFS B-Tree. For now only used
 * on the calalog and the object map.
 */
struct query {
	struct node *node;		/* Node being searched */
	struct key *key;		/* What the query is looking for */

	struct query *parent;		/* Query for parent node */
	unsigned int flags;

	/* Set by the query on success */
	int index;			/* Index of the entry in the node */
	int key_off;			/* Offset of the key in the node */
	int key_len;			/* Length of the key */
	int off;			/* Offset of the data in the node */
	int len;			/* Length of the data */

	int depth;			/* Put a limit on recursion */
};

/* In-memory tree types */
#define BTREE_TYPE_OMAP		1 /* The tree is an object map */
#define BTREE_TYPE_CATALOG	2 /* The tree is a catalog */
#define BTREE_TYPE_EXTENTREF	3 /* The tree is for extent references */
#define BTREE_TYPE_SNAP_META	4 /* The tree is for snapshot metadata */
#define BTREE_TYPE_FREE_QUEUE	5 /* The tree is for a free-space queue */
#define BTREE_TYPE_SNAPSHOTS	6 /* The tree is for omap snapshots */
#define BTREE_TYPE_FEXT		7 /* The tree is for file extents */
#define BTREE_TYPE_FUSION_MT	8 /* The is the fusion middle-tree */

/* In-memory structure representing a b-tree */
struct btree {
	u8 type;		/* Type of the tree */
	struct node *root;	/* Root of this b-tree */

	/* Hash table for the tree's object map (can be NULL) */
	struct htable_entry **omap_table;

	/* B-tree stats as measured by the fsck */
	u64 key_count;		/* Number of keys */
	u64 node_count;		/* Number of nodes */
	int longest_key;	/* Length of longest key */
	int longest_val;	/* Length of longest value */
};

/**
 * btree_is_free_queue - Check if a b-tree is a free-space queue
 * @btree: the b-tree to check
 */
static inline bool btree_is_free_queue(struct btree *btree)
{
	return btree->type == BTREE_TYPE_FREE_QUEUE;
}

static inline bool btree_is_snapshots(struct btree *btree)
{
	return btree->type == BTREE_TYPE_SNAPSHOTS;
}

/**
 * btree_is_omap - Check if a b-tree is an object map
 * @btree: the b-tree to check
 */
static inline bool btree_is_omap(struct btree *btree)
{
	return btree->type == BTREE_TYPE_OMAP;
}

/**
 * btree_is_snap_meta - Check if a b-tree is for snapshot metadata
 * @btree: the b-tree to check
 */
static inline bool btree_is_snap_meta(struct btree *btree)
{
	return btree->type == BTREE_TYPE_SNAP_META;
}

/**
 * btree_is_catalog - Check if a b-tree is a catalog
 * @btree: the b-tree to check
 */
static inline bool btree_is_catalog(struct btree *btree)
{
	return btree->type == BTREE_TYPE_CATALOG;
}

/**
 * btree_is_extentref - Check if a b-tree is for extent references
 * @btree: the b-tree to check
 */
static inline bool btree_is_extentref(struct btree *btree)
{
	return btree->type == BTREE_TYPE_EXTENTREF;
}

/**
 * btree_is_fext - Check if a b-tree is for file extents
 * @btree: the b-tree to check
 */
static inline bool btree_is_fext(struct btree *btree)
{
	return btree->type == BTREE_TYPE_FEXT;
}

/**
 * btree_is_fusion_mt - Check if a b-tree is a fusion middle-tree
 * @btree: the b-tree to check
 */
static inline bool btree_is_fusion_mt(struct btree *btree)
{
	return btree->type == BTREE_TYPE_FUSION_MT;
}

extern struct free_queue *parse_free_queue_btree(u64 oid, int index);
extern struct btree *parse_snap_meta_btree(u64 oid);
extern struct btree *parse_extentref_btree(u64 oid);
extern struct btree *parse_omap_btree(u64 oid);
extern struct btree *parse_cat_btree(u64 oid, struct htable_entry **omap_table);
extern struct btree *parse_fext_btree(u64 oid);
extern struct btree *parse_fusion_middle_tree(u64 oid);
extern struct query *alloc_query(struct node *node, struct query *parent);
extern void free_query(struct query *query);
extern int btree_query(struct query **query);
extern struct node *omap_read_node(u64 id);
extern void free_omap_table(struct htable_entry **table);
extern struct omap_record *get_latest_omap_record(u64 oid, u64 xid, struct htable_entry **table);
extern void extentref_update_lookup(u64 bno, struct extref_record *extref);
extern int fext_tree_lookup(u64 oid, u64 logaddr, u64 *bno);
extern int file_extent_lookup(u64 oid, u64 logaddr, u64 *bno);
extern void omap_htable_clear_seen_for_snap(struct htable_entry **table);

#endif	/* _BTREE_H */