xref: /aosp_15_r20/external/e2fsprogs/lib/ext2fs/blkmap64_rb.c (revision 6a54128f25917bfc36a8a6e9d722c04a0b4641b6)
1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker  * blkmap64_rb.c --- Simple rb-tree implementation for bitmaps
3*6a54128fSAndroid Build Coastguard Worker  *
4*6a54128fSAndroid Build Coastguard Worker  * (C)2010 Red Hat, Inc., Lukas Czerner <[email protected]>
5*6a54128fSAndroid Build Coastguard Worker  *
6*6a54128fSAndroid Build Coastguard Worker  * %Begin-Header%
7*6a54128fSAndroid Build Coastguard Worker  * This file may be redistributed under the terms of the GNU Public
8*6a54128fSAndroid Build Coastguard Worker  * License.
9*6a54128fSAndroid Build Coastguard Worker  * %End-Header%
10*6a54128fSAndroid Build Coastguard Worker  */
11*6a54128fSAndroid Build Coastguard Worker 
12*6a54128fSAndroid Build Coastguard Worker #include "config.h"
13*6a54128fSAndroid Build Coastguard Worker #include <stdio.h>
14*6a54128fSAndroid Build Coastguard Worker #include <string.h>
15*6a54128fSAndroid Build Coastguard Worker #if HAVE_UNISTD_H
16*6a54128fSAndroid Build Coastguard Worker #include <unistd.h>
17*6a54128fSAndroid Build Coastguard Worker #endif
18*6a54128fSAndroid Build Coastguard Worker #include <fcntl.h>
19*6a54128fSAndroid Build Coastguard Worker #include <time.h>
20*6a54128fSAndroid Build Coastguard Worker #if HAVE_SYS_STAT_H
21*6a54128fSAndroid Build Coastguard Worker #include <sys/stat.h>
22*6a54128fSAndroid Build Coastguard Worker #endif
23*6a54128fSAndroid Build Coastguard Worker #if HAVE_SYS_TYPES_H
24*6a54128fSAndroid Build Coastguard Worker #include <sys/types.h>
25*6a54128fSAndroid Build Coastguard Worker #endif
26*6a54128fSAndroid Build Coastguard Worker #if HAVE_LINUX_TYPES_H
27*6a54128fSAndroid Build Coastguard Worker #include <linux/types.h>
28*6a54128fSAndroid Build Coastguard Worker #endif
29*6a54128fSAndroid Build Coastguard Worker 
30*6a54128fSAndroid Build Coastguard Worker #include "ext2_fs.h"
31*6a54128fSAndroid Build Coastguard Worker #include "ext2fsP.h"
32*6a54128fSAndroid Build Coastguard Worker #include "bmap64.h"
33*6a54128fSAndroid Build Coastguard Worker #include "rbtree.h"
34*6a54128fSAndroid Build Coastguard Worker 
35*6a54128fSAndroid Build Coastguard Worker #include <limits.h>
36*6a54128fSAndroid Build Coastguard Worker 
37*6a54128fSAndroid Build Coastguard Worker struct bmap_rb_extent {
38*6a54128fSAndroid Build Coastguard Worker 	struct rb_node node;
39*6a54128fSAndroid Build Coastguard Worker 	__u64 start;
40*6a54128fSAndroid Build Coastguard Worker 	__u64 count;
41*6a54128fSAndroid Build Coastguard Worker };
42*6a54128fSAndroid Build Coastguard Worker 
43*6a54128fSAndroid Build Coastguard Worker struct ext2fs_rb_private {
44*6a54128fSAndroid Build Coastguard Worker 	struct rb_root root;
45*6a54128fSAndroid Build Coastguard Worker 	struct bmap_rb_extent *wcursor;
46*6a54128fSAndroid Build Coastguard Worker 	struct bmap_rb_extent *rcursor;
47*6a54128fSAndroid Build Coastguard Worker 	struct bmap_rb_extent *rcursor_next;
48*6a54128fSAndroid Build Coastguard Worker #ifdef ENABLE_BMAP_STATS_OPS
49*6a54128fSAndroid Build Coastguard Worker 	__u64 mark_hit;
50*6a54128fSAndroid Build Coastguard Worker 	__u64 test_hit;
51*6a54128fSAndroid Build Coastguard Worker #endif
52*6a54128fSAndroid Build Coastguard Worker };
53*6a54128fSAndroid Build Coastguard Worker 
node_to_extent(struct rb_node * node)54*6a54128fSAndroid Build Coastguard Worker inline static struct bmap_rb_extent *node_to_extent(struct rb_node *node)
55*6a54128fSAndroid Build Coastguard Worker {
56*6a54128fSAndroid Build Coastguard Worker 	/*
57*6a54128fSAndroid Build Coastguard Worker 	 * This depends on the fact the struct rb_node is at the
58*6a54128fSAndroid Build Coastguard Worker 	 * beginning of the bmap_rb_extent structure.  We use this
59*6a54128fSAndroid Build Coastguard Worker 	 * instead of the ext2fs_rb_entry macro because it causes gcc
60*6a54128fSAndroid Build Coastguard Worker 	 * -Wall to generate a huge amount of noise.
61*6a54128fSAndroid Build Coastguard Worker 	 */
62*6a54128fSAndroid Build Coastguard Worker 	return (struct bmap_rb_extent *) node;
63*6a54128fSAndroid Build Coastguard Worker }
64*6a54128fSAndroid Build Coastguard Worker 
65*6a54128fSAndroid Build Coastguard Worker static int rb_insert_extent(__u64 start, __u64 count,
66*6a54128fSAndroid Build Coastguard Worker 			    struct ext2fs_rb_private *);
67*6a54128fSAndroid Build Coastguard Worker static void rb_get_new_extent(struct bmap_rb_extent **, __u64, __u64);
68*6a54128fSAndroid Build Coastguard Worker 
69*6a54128fSAndroid Build Coastguard Worker /* #define DEBUG_RB */
70*6a54128fSAndroid Build Coastguard Worker 
71*6a54128fSAndroid Build Coastguard Worker #ifdef DEBUG_RB
print_tree(struct rb_root * root)72*6a54128fSAndroid Build Coastguard Worker static void print_tree(struct rb_root *root)
73*6a54128fSAndroid Build Coastguard Worker {
74*6a54128fSAndroid Build Coastguard Worker 	struct rb_node *node = NULL;
75*6a54128fSAndroid Build Coastguard Worker 	struct bmap_rb_extent *ext;
76*6a54128fSAndroid Build Coastguard Worker 
77*6a54128fSAndroid Build Coastguard Worker 	fprintf(stderr, "\t\t\t=================================\n");
78*6a54128fSAndroid Build Coastguard Worker 	node = ext2fs_rb_first(root);
79*6a54128fSAndroid Build Coastguard Worker 	for (node = ext2fs_rb_first(root); node != NULL;
80*6a54128fSAndroid Build Coastguard Worker 	     node = ext2fs_rb_next(node)) {
81*6a54128fSAndroid Build Coastguard Worker 		ext = node_to_extent(node);
82*6a54128fSAndroid Build Coastguard Worker 		fprintf(stderr, "\t\t\t--> (%llu -> %llu)\n",
83*6a54128fSAndroid Build Coastguard Worker 			(unsigned long long) ext->start,
84*6a54128fSAndroid Build Coastguard Worker 			(unsigned long long) ext->start + ext->count);
85*6a54128fSAndroid Build Coastguard Worker 	}
86*6a54128fSAndroid Build Coastguard Worker 	fprintf(stderr, "\t\t\t=================================\n");
87*6a54128fSAndroid Build Coastguard Worker }
88*6a54128fSAndroid Build Coastguard Worker 
check_tree(struct rb_root * root,const char * msg)89*6a54128fSAndroid Build Coastguard Worker static void check_tree(struct rb_root *root, const char *msg)
90*6a54128fSAndroid Build Coastguard Worker {
91*6a54128fSAndroid Build Coastguard Worker 	struct rb_node *node;
92*6a54128fSAndroid Build Coastguard Worker 	struct bmap_rb_extent *ext, *old = NULL;
93*6a54128fSAndroid Build Coastguard Worker 
94*6a54128fSAndroid Build Coastguard Worker 	for (node = ext2fs_rb_first(root); node;
95*6a54128fSAndroid Build Coastguard Worker 	     node = ext2fs_rb_next(node)) {
96*6a54128fSAndroid Build Coastguard Worker 		ext = node_to_extent(node);
97*6a54128fSAndroid Build Coastguard Worker 		if (ext->count == 0) {
98*6a54128fSAndroid Build Coastguard Worker 			fprintf(stderr, "Tree Error: count is zero\n");
99*6a54128fSAndroid Build Coastguard Worker 			fprintf(stderr, "extent: %llu -> %llu (%llu)\n",
100*6a54128fSAndroid Build Coastguard Worker 				(unsigned long long) ext->start,
101*6a54128fSAndroid Build Coastguard Worker 				(unsigned long long) ext->start + ext->count,
102*6a54128fSAndroid Build Coastguard Worker 				(unsigned long long) ext->count);
103*6a54128fSAndroid Build Coastguard Worker 			goto err_out;
104*6a54128fSAndroid Build Coastguard Worker 		}
105*6a54128fSAndroid Build Coastguard Worker 		if (ext->start + ext->count < ext->start) {
106*6a54128fSAndroid Build Coastguard Worker 			fprintf(stderr,
107*6a54128fSAndroid Build Coastguard Worker 				"Tree Error: start or count is crazy\n");
108*6a54128fSAndroid Build Coastguard Worker 			fprintf(stderr, "extent: %llu -> %llu (%llu)\n",
109*6a54128fSAndroid Build Coastguard Worker 				(unsigned long long) ext->start,
110*6a54128fSAndroid Build Coastguard Worker 				(unsigned long long) ext->start + ext->count,
111*6a54128fSAndroid Build Coastguard Worker 				(unsigned long long) ext->count);
112*6a54128fSAndroid Build Coastguard Worker 			goto err_out;
113*6a54128fSAndroid Build Coastguard Worker 		}
114*6a54128fSAndroid Build Coastguard Worker 
115*6a54128fSAndroid Build Coastguard Worker 		if (old) {
116*6a54128fSAndroid Build Coastguard Worker 			if (old->start > ext->start) {
117*6a54128fSAndroid Build Coastguard Worker 				fprintf(stderr, "Tree Error: start is crazy\n");
118*6a54128fSAndroid Build Coastguard Worker 				fprintf(stderr, "extent: %llu -> %llu (%llu)\n",
119*6a54128fSAndroid Build Coastguard Worker 					(unsigned long long) old->start,
120*6a54128fSAndroid Build Coastguard Worker 					(unsigned long long) old->start + old->count,
121*6a54128fSAndroid Build Coastguard Worker 					(unsigned long long) old->count);
122*6a54128fSAndroid Build Coastguard Worker 				fprintf(stderr,
123*6a54128fSAndroid Build Coastguard Worker 					"extent next: %llu -> %llu (%llu)\n",
124*6a54128fSAndroid Build Coastguard Worker 					(unsigned long long) ext->start,
125*6a54128fSAndroid Build Coastguard Worker 					(unsigned long long) ext->start + ext->count,
126*6a54128fSAndroid Build Coastguard Worker 					(unsigned long long) ext->count);
127*6a54128fSAndroid Build Coastguard Worker 				goto err_out;
128*6a54128fSAndroid Build Coastguard Worker 			}
129*6a54128fSAndroid Build Coastguard Worker 			if ((old->start + old->count) >= ext->start) {
130*6a54128fSAndroid Build Coastguard Worker 				fprintf(stderr,
131*6a54128fSAndroid Build Coastguard Worker 					"Tree Error: extent is crazy\n");
132*6a54128fSAndroid Build Coastguard Worker 				fprintf(stderr, "extent: %llu -> %llu (%llu)\n",
133*6a54128fSAndroid Build Coastguard Worker 					(unsigned long long) old->start,
134*6a54128fSAndroid Build Coastguard Worker 					(unsigned long long) old->start + old->count,
135*6a54128fSAndroid Build Coastguard Worker 					(unsigned long long) old->count);
136*6a54128fSAndroid Build Coastguard Worker 				fprintf(stderr,
137*6a54128fSAndroid Build Coastguard Worker 					"extent next: %llu -> %llu (%llu)\n",
138*6a54128fSAndroid Build Coastguard Worker 					(unsigned long long) ext->start,
139*6a54128fSAndroid Build Coastguard Worker 					(unsigned long long) ext->start + ext->count,
140*6a54128fSAndroid Build Coastguard Worker 					(unsigned long long) ext->count);
141*6a54128fSAndroid Build Coastguard Worker 				goto err_out;
142*6a54128fSAndroid Build Coastguard Worker 			}
143*6a54128fSAndroid Build Coastguard Worker 		}
144*6a54128fSAndroid Build Coastguard Worker 		old = ext;
145*6a54128fSAndroid Build Coastguard Worker 	}
146*6a54128fSAndroid Build Coastguard Worker 	return;
147*6a54128fSAndroid Build Coastguard Worker 
148*6a54128fSAndroid Build Coastguard Worker err_out:
149*6a54128fSAndroid Build Coastguard Worker 	fprintf(stderr, "%s\n", msg);
150*6a54128fSAndroid Build Coastguard Worker 	print_tree(root);
151*6a54128fSAndroid Build Coastguard Worker 	exit(1);
152*6a54128fSAndroid Build Coastguard Worker }
153*6a54128fSAndroid Build Coastguard Worker #else
154*6a54128fSAndroid Build Coastguard Worker #define check_tree(root, msg) do {} while (0)
155*6a54128fSAndroid Build Coastguard Worker #define print_tree(root) do {} while (0)
156*6a54128fSAndroid Build Coastguard Worker #endif
157*6a54128fSAndroid Build Coastguard Worker 
rb_get_new_extent(struct bmap_rb_extent ** ext,__u64 start,__u64 count)158*6a54128fSAndroid Build Coastguard Worker static void rb_get_new_extent(struct bmap_rb_extent **ext, __u64 start,
159*6a54128fSAndroid Build Coastguard Worker 			     __u64 count)
160*6a54128fSAndroid Build Coastguard Worker {
161*6a54128fSAndroid Build Coastguard Worker 	struct bmap_rb_extent *new_ext;
162*6a54128fSAndroid Build Coastguard Worker 	int retval;
163*6a54128fSAndroid Build Coastguard Worker 
164*6a54128fSAndroid Build Coastguard Worker 	retval = ext2fs_get_mem(sizeof (struct bmap_rb_extent),
165*6a54128fSAndroid Build Coastguard Worker 				&new_ext);
166*6a54128fSAndroid Build Coastguard Worker 	if (retval)
167*6a54128fSAndroid Build Coastguard Worker 		abort();
168*6a54128fSAndroid Build Coastguard Worker 
169*6a54128fSAndroid Build Coastguard Worker 	new_ext->start = start;
170*6a54128fSAndroid Build Coastguard Worker 	new_ext->count = count;
171*6a54128fSAndroid Build Coastguard Worker 	*ext = new_ext;
172*6a54128fSAndroid Build Coastguard Worker }
173*6a54128fSAndroid Build Coastguard Worker 
174*6a54128fSAndroid Build Coastguard Worker inline
rb_free_extent(struct ext2fs_rb_private * bp,struct bmap_rb_extent * ext)175*6a54128fSAndroid Build Coastguard Worker static void rb_free_extent(struct ext2fs_rb_private *bp,
176*6a54128fSAndroid Build Coastguard Worker 			   struct bmap_rb_extent *ext)
177*6a54128fSAndroid Build Coastguard Worker {
178*6a54128fSAndroid Build Coastguard Worker 	if (bp->wcursor == ext)
179*6a54128fSAndroid Build Coastguard Worker 		bp->wcursor = NULL;
180*6a54128fSAndroid Build Coastguard Worker 	if (bp->rcursor == ext)
181*6a54128fSAndroid Build Coastguard Worker 		bp->rcursor = NULL;
182*6a54128fSAndroid Build Coastguard Worker 	if (bp->rcursor_next == ext)
183*6a54128fSAndroid Build Coastguard Worker 		bp->rcursor_next = NULL;
184*6a54128fSAndroid Build Coastguard Worker 	ext2fs_free_mem(&ext);
185*6a54128fSAndroid Build Coastguard Worker }
186*6a54128fSAndroid Build Coastguard Worker 
rb_alloc_private_data(ext2fs_generic_bitmap_64 bitmap)187*6a54128fSAndroid Build Coastguard Worker static errcode_t rb_alloc_private_data (ext2fs_generic_bitmap_64 bitmap)
188*6a54128fSAndroid Build Coastguard Worker {
189*6a54128fSAndroid Build Coastguard Worker 	struct ext2fs_rb_private *bp;
190*6a54128fSAndroid Build Coastguard Worker 	errcode_t	retval;
191*6a54128fSAndroid Build Coastguard Worker 
192*6a54128fSAndroid Build Coastguard Worker 	retval = ext2fs_get_mem(sizeof (struct ext2fs_rb_private), &bp);
193*6a54128fSAndroid Build Coastguard Worker 	if (retval)
194*6a54128fSAndroid Build Coastguard Worker 		return retval;
195*6a54128fSAndroid Build Coastguard Worker 
196*6a54128fSAndroid Build Coastguard Worker 	bp->root = RB_ROOT;
197*6a54128fSAndroid Build Coastguard Worker 	bp->rcursor = NULL;
198*6a54128fSAndroid Build Coastguard Worker 	bp->rcursor_next = NULL;
199*6a54128fSAndroid Build Coastguard Worker 	bp->wcursor = NULL;
200*6a54128fSAndroid Build Coastguard Worker 
201*6a54128fSAndroid Build Coastguard Worker #ifdef ENABLE_BMAP_STATS_OPS
202*6a54128fSAndroid Build Coastguard Worker 	bp->test_hit = 0;
203*6a54128fSAndroid Build Coastguard Worker 	bp->mark_hit = 0;
204*6a54128fSAndroid Build Coastguard Worker #endif
205*6a54128fSAndroid Build Coastguard Worker 
206*6a54128fSAndroid Build Coastguard Worker 	bitmap->private = (void *) bp;
207*6a54128fSAndroid Build Coastguard Worker 	return 0;
208*6a54128fSAndroid Build Coastguard Worker }
209*6a54128fSAndroid Build Coastguard Worker 
rb_new_bmap(ext2_filsys fs EXT2FS_ATTR ((unused)),ext2fs_generic_bitmap_64 bitmap)210*6a54128fSAndroid Build Coastguard Worker static errcode_t rb_new_bmap(ext2_filsys fs EXT2FS_ATTR((unused)),
211*6a54128fSAndroid Build Coastguard Worker 			     ext2fs_generic_bitmap_64 bitmap)
212*6a54128fSAndroid Build Coastguard Worker {
213*6a54128fSAndroid Build Coastguard Worker 	errcode_t	retval;
214*6a54128fSAndroid Build Coastguard Worker 
215*6a54128fSAndroid Build Coastguard Worker 	retval = rb_alloc_private_data (bitmap);
216*6a54128fSAndroid Build Coastguard Worker 	if (retval)
217*6a54128fSAndroid Build Coastguard Worker 		return retval;
218*6a54128fSAndroid Build Coastguard Worker 
219*6a54128fSAndroid Build Coastguard Worker 	return 0;
220*6a54128fSAndroid Build Coastguard Worker }
221*6a54128fSAndroid Build Coastguard Worker 
rb_free_tree(struct rb_root * root)222*6a54128fSAndroid Build Coastguard Worker static void rb_free_tree(struct rb_root *root)
223*6a54128fSAndroid Build Coastguard Worker {
224*6a54128fSAndroid Build Coastguard Worker 	struct bmap_rb_extent *ext;
225*6a54128fSAndroid Build Coastguard Worker 	struct rb_node *node, *next;
226*6a54128fSAndroid Build Coastguard Worker 
227*6a54128fSAndroid Build Coastguard Worker 	for (node = ext2fs_rb_first(root); node; node = next) {
228*6a54128fSAndroid Build Coastguard Worker 		next = ext2fs_rb_next(node);
229*6a54128fSAndroid Build Coastguard Worker 		ext = node_to_extent(node);
230*6a54128fSAndroid Build Coastguard Worker 		ext2fs_rb_erase(node, root);
231*6a54128fSAndroid Build Coastguard Worker 		ext2fs_free_mem(&ext);
232*6a54128fSAndroid Build Coastguard Worker 	}
233*6a54128fSAndroid Build Coastguard Worker }
234*6a54128fSAndroid Build Coastguard Worker 
rb_free_bmap(ext2fs_generic_bitmap_64 bitmap)235*6a54128fSAndroid Build Coastguard Worker static void rb_free_bmap(ext2fs_generic_bitmap_64 bitmap)
236*6a54128fSAndroid Build Coastguard Worker {
237*6a54128fSAndroid Build Coastguard Worker 	struct ext2fs_rb_private *bp;
238*6a54128fSAndroid Build Coastguard Worker 
239*6a54128fSAndroid Build Coastguard Worker 	bp = (struct ext2fs_rb_private *) bitmap->private;
240*6a54128fSAndroid Build Coastguard Worker 
241*6a54128fSAndroid Build Coastguard Worker 	rb_free_tree(&bp->root);
242*6a54128fSAndroid Build Coastguard Worker 	ext2fs_free_mem(&bp);
243*6a54128fSAndroid Build Coastguard Worker 	bp = 0;
244*6a54128fSAndroid Build Coastguard Worker }
245*6a54128fSAndroid Build Coastguard Worker 
rb_copy_bmap(ext2fs_generic_bitmap_64 src,ext2fs_generic_bitmap_64 dest)246*6a54128fSAndroid Build Coastguard Worker static errcode_t rb_copy_bmap(ext2fs_generic_bitmap_64 src,
247*6a54128fSAndroid Build Coastguard Worker 			      ext2fs_generic_bitmap_64 dest)
248*6a54128fSAndroid Build Coastguard Worker {
249*6a54128fSAndroid Build Coastguard Worker 	struct ext2fs_rb_private *src_bp, *dest_bp;
250*6a54128fSAndroid Build Coastguard Worker 	struct bmap_rb_extent *src_ext, *dest_ext;
251*6a54128fSAndroid Build Coastguard Worker 	struct rb_node *dest_node, *src_node, *dest_last, **n;
252*6a54128fSAndroid Build Coastguard Worker 	errcode_t retval = 0;
253*6a54128fSAndroid Build Coastguard Worker 
254*6a54128fSAndroid Build Coastguard Worker 	retval = rb_alloc_private_data (dest);
255*6a54128fSAndroid Build Coastguard Worker 	if (retval)
256*6a54128fSAndroid Build Coastguard Worker 		return retval;
257*6a54128fSAndroid Build Coastguard Worker 
258*6a54128fSAndroid Build Coastguard Worker 	src_bp = (struct ext2fs_rb_private *) src->private;
259*6a54128fSAndroid Build Coastguard Worker 	dest_bp = (struct ext2fs_rb_private *) dest->private;
260*6a54128fSAndroid Build Coastguard Worker 	src_bp->rcursor = NULL;
261*6a54128fSAndroid Build Coastguard Worker 	dest_bp->rcursor = NULL;
262*6a54128fSAndroid Build Coastguard Worker 
263*6a54128fSAndroid Build Coastguard Worker 	src_node = ext2fs_rb_first(&src_bp->root);
264*6a54128fSAndroid Build Coastguard Worker 	while (src_node) {
265*6a54128fSAndroid Build Coastguard Worker 		src_ext = node_to_extent(src_node);
266*6a54128fSAndroid Build Coastguard Worker 		retval = ext2fs_get_mem(sizeof (struct bmap_rb_extent),
267*6a54128fSAndroid Build Coastguard Worker 					&dest_ext);
268*6a54128fSAndroid Build Coastguard Worker 		if (retval)
269*6a54128fSAndroid Build Coastguard Worker 			break;
270*6a54128fSAndroid Build Coastguard Worker 
271*6a54128fSAndroid Build Coastguard Worker 		memcpy(dest_ext, src_ext, sizeof(struct bmap_rb_extent));
272*6a54128fSAndroid Build Coastguard Worker 
273*6a54128fSAndroid Build Coastguard Worker 		dest_node = &dest_ext->node;
274*6a54128fSAndroid Build Coastguard Worker 		n = &dest_bp->root.rb_node;
275*6a54128fSAndroid Build Coastguard Worker 
276*6a54128fSAndroid Build Coastguard Worker 		dest_last = NULL;
277*6a54128fSAndroid Build Coastguard Worker 		if (*n) {
278*6a54128fSAndroid Build Coastguard Worker 			dest_last = ext2fs_rb_last(&dest_bp->root);
279*6a54128fSAndroid Build Coastguard Worker 			n = &(dest_last)->rb_right;
280*6a54128fSAndroid Build Coastguard Worker 		}
281*6a54128fSAndroid Build Coastguard Worker 
282*6a54128fSAndroid Build Coastguard Worker 		ext2fs_rb_link_node(dest_node, dest_last, n);
283*6a54128fSAndroid Build Coastguard Worker 		ext2fs_rb_insert_color(dest_node, &dest_bp->root);
284*6a54128fSAndroid Build Coastguard Worker 
285*6a54128fSAndroid Build Coastguard Worker 		src_node = ext2fs_rb_next(src_node);
286*6a54128fSAndroid Build Coastguard Worker 	}
287*6a54128fSAndroid Build Coastguard Worker 
288*6a54128fSAndroid Build Coastguard Worker 	return retval;
289*6a54128fSAndroid Build Coastguard Worker }
290*6a54128fSAndroid Build Coastguard Worker 
rb_truncate(__u64 new_max,struct rb_root * root)291*6a54128fSAndroid Build Coastguard Worker static void rb_truncate(__u64 new_max, struct rb_root *root)
292*6a54128fSAndroid Build Coastguard Worker {
293*6a54128fSAndroid Build Coastguard Worker 	struct bmap_rb_extent *ext;
294*6a54128fSAndroid Build Coastguard Worker 	struct rb_node *node;
295*6a54128fSAndroid Build Coastguard Worker 
296*6a54128fSAndroid Build Coastguard Worker 	node = ext2fs_rb_last(root);
297*6a54128fSAndroid Build Coastguard Worker 	while (node) {
298*6a54128fSAndroid Build Coastguard Worker 		ext = node_to_extent(node);
299*6a54128fSAndroid Build Coastguard Worker 
300*6a54128fSAndroid Build Coastguard Worker 		if ((ext->start + ext->count - 1) <= new_max)
301*6a54128fSAndroid Build Coastguard Worker 			break;
302*6a54128fSAndroid Build Coastguard Worker 		else if (ext->start > new_max) {
303*6a54128fSAndroid Build Coastguard Worker 			ext2fs_rb_erase(node, root);
304*6a54128fSAndroid Build Coastguard Worker 			ext2fs_free_mem(&ext);
305*6a54128fSAndroid Build Coastguard Worker 			node = ext2fs_rb_last(root);
306*6a54128fSAndroid Build Coastguard Worker 			continue;
307*6a54128fSAndroid Build Coastguard Worker 		} else
308*6a54128fSAndroid Build Coastguard Worker 			ext->count = new_max - ext->start + 1;
309*6a54128fSAndroid Build Coastguard Worker 	}
310*6a54128fSAndroid Build Coastguard Worker }
311*6a54128fSAndroid Build Coastguard Worker 
rb_resize_bmap(ext2fs_generic_bitmap_64 bmap,__u64 new_end,__u64 new_real_end)312*6a54128fSAndroid Build Coastguard Worker static errcode_t rb_resize_bmap(ext2fs_generic_bitmap_64 bmap,
313*6a54128fSAndroid Build Coastguard Worker 				__u64 new_end, __u64 new_real_end)
314*6a54128fSAndroid Build Coastguard Worker {
315*6a54128fSAndroid Build Coastguard Worker 	struct ext2fs_rb_private *bp;
316*6a54128fSAndroid Build Coastguard Worker 
317*6a54128fSAndroid Build Coastguard Worker 	bp = (struct ext2fs_rb_private *) bmap->private;
318*6a54128fSAndroid Build Coastguard Worker 	bp->rcursor = NULL;
319*6a54128fSAndroid Build Coastguard Worker 	bp->wcursor = NULL;
320*6a54128fSAndroid Build Coastguard Worker 
321*6a54128fSAndroid Build Coastguard Worker 	rb_truncate(((new_end < bmap->end) ? new_end : bmap->end) - bmap->start,
322*6a54128fSAndroid Build Coastguard Worker 		    &bp->root);
323*6a54128fSAndroid Build Coastguard Worker 
324*6a54128fSAndroid Build Coastguard Worker 	bmap->end = new_end;
325*6a54128fSAndroid Build Coastguard Worker 	bmap->real_end = new_real_end;
326*6a54128fSAndroid Build Coastguard Worker 
327*6a54128fSAndroid Build Coastguard Worker 	if (bmap->end < bmap->real_end)
328*6a54128fSAndroid Build Coastguard Worker 		rb_insert_extent(bmap->end + 1 - bmap->start,
329*6a54128fSAndroid Build Coastguard Worker 				 bmap->real_end - bmap->end, bp);
330*6a54128fSAndroid Build Coastguard Worker 	return 0;
331*6a54128fSAndroid Build Coastguard Worker 
332*6a54128fSAndroid Build Coastguard Worker }
333*6a54128fSAndroid Build Coastguard Worker 
334*6a54128fSAndroid Build Coastguard Worker inline static int
rb_test_bit(struct ext2fs_rb_private * bp,__u64 bit)335*6a54128fSAndroid Build Coastguard Worker rb_test_bit(struct ext2fs_rb_private *bp, __u64 bit)
336*6a54128fSAndroid Build Coastguard Worker {
337*6a54128fSAndroid Build Coastguard Worker 	struct bmap_rb_extent *rcursor, *next_ext = NULL;
338*6a54128fSAndroid Build Coastguard Worker 	struct rb_node *parent = NULL, *next;
339*6a54128fSAndroid Build Coastguard Worker 	struct rb_node **n = &bp->root.rb_node;
340*6a54128fSAndroid Build Coastguard Worker 	struct bmap_rb_extent *ext;
341*6a54128fSAndroid Build Coastguard Worker 
342*6a54128fSAndroid Build Coastguard Worker 	rcursor = bp->rcursor;
343*6a54128fSAndroid Build Coastguard Worker 	if (!rcursor)
344*6a54128fSAndroid Build Coastguard Worker 		goto search_tree;
345*6a54128fSAndroid Build Coastguard Worker 
346*6a54128fSAndroid Build Coastguard Worker 	if (bit >= rcursor->start && bit < rcursor->start + rcursor->count) {
347*6a54128fSAndroid Build Coastguard Worker #ifdef ENABLE_BMAP_STATS_OPS
348*6a54128fSAndroid Build Coastguard Worker 		bp->test_hit++;
349*6a54128fSAndroid Build Coastguard Worker #endif
350*6a54128fSAndroid Build Coastguard Worker 		return 1;
351*6a54128fSAndroid Build Coastguard Worker 	}
352*6a54128fSAndroid Build Coastguard Worker 
353*6a54128fSAndroid Build Coastguard Worker 	next_ext = bp->rcursor_next;
354*6a54128fSAndroid Build Coastguard Worker 	if (!next_ext) {
355*6a54128fSAndroid Build Coastguard Worker 		next = ext2fs_rb_next(&rcursor->node);
356*6a54128fSAndroid Build Coastguard Worker 		if (next)
357*6a54128fSAndroid Build Coastguard Worker 			next_ext = node_to_extent(next);
358*6a54128fSAndroid Build Coastguard Worker 		bp->rcursor_next = next_ext;
359*6a54128fSAndroid Build Coastguard Worker 	}
360*6a54128fSAndroid Build Coastguard Worker 	if (next_ext) {
361*6a54128fSAndroid Build Coastguard Worker 		if ((bit >= rcursor->start + rcursor->count) &&
362*6a54128fSAndroid Build Coastguard Worker 		    (bit < next_ext->start)) {
363*6a54128fSAndroid Build Coastguard Worker #ifdef BMAP_STATS_OPS
364*6a54128fSAndroid Build Coastguard Worker 			bp->test_hit++;
365*6a54128fSAndroid Build Coastguard Worker #endif
366*6a54128fSAndroid Build Coastguard Worker 			return 0;
367*6a54128fSAndroid Build Coastguard Worker 		}
368*6a54128fSAndroid Build Coastguard Worker 	}
369*6a54128fSAndroid Build Coastguard Worker 	bp->rcursor = NULL;
370*6a54128fSAndroid Build Coastguard Worker 	bp->rcursor_next = NULL;
371*6a54128fSAndroid Build Coastguard Worker 
372*6a54128fSAndroid Build Coastguard Worker 	rcursor = bp->wcursor;
373*6a54128fSAndroid Build Coastguard Worker 	if (!rcursor)
374*6a54128fSAndroid Build Coastguard Worker 		goto search_tree;
375*6a54128fSAndroid Build Coastguard Worker 
376*6a54128fSAndroid Build Coastguard Worker 	if (bit >= rcursor->start && bit < rcursor->start + rcursor->count)
377*6a54128fSAndroid Build Coastguard Worker 		return 1;
378*6a54128fSAndroid Build Coastguard Worker 
379*6a54128fSAndroid Build Coastguard Worker search_tree:
380*6a54128fSAndroid Build Coastguard Worker 
381*6a54128fSAndroid Build Coastguard Worker 	while (*n) {
382*6a54128fSAndroid Build Coastguard Worker 		parent = *n;
383*6a54128fSAndroid Build Coastguard Worker 		ext = node_to_extent(parent);
384*6a54128fSAndroid Build Coastguard Worker 		if (bit < ext->start)
385*6a54128fSAndroid Build Coastguard Worker 			n = &(*n)->rb_left;
386*6a54128fSAndroid Build Coastguard Worker 		else if (bit >= (ext->start + ext->count))
387*6a54128fSAndroid Build Coastguard Worker 			n = &(*n)->rb_right;
388*6a54128fSAndroid Build Coastguard Worker 		else {
389*6a54128fSAndroid Build Coastguard Worker 			bp->rcursor = ext;
390*6a54128fSAndroid Build Coastguard Worker 			bp->rcursor_next = NULL;
391*6a54128fSAndroid Build Coastguard Worker 			return 1;
392*6a54128fSAndroid Build Coastguard Worker 		}
393*6a54128fSAndroid Build Coastguard Worker 	}
394*6a54128fSAndroid Build Coastguard Worker 	return 0;
395*6a54128fSAndroid Build Coastguard Worker }
396*6a54128fSAndroid Build Coastguard Worker 
rb_insert_extent(__u64 start,__u64 count,struct ext2fs_rb_private * bp)397*6a54128fSAndroid Build Coastguard Worker static int rb_insert_extent(__u64 start, __u64 count,
398*6a54128fSAndroid Build Coastguard Worker 			    struct ext2fs_rb_private *bp)
399*6a54128fSAndroid Build Coastguard Worker {
400*6a54128fSAndroid Build Coastguard Worker 	struct rb_root *root = &bp->root;
401*6a54128fSAndroid Build Coastguard Worker 	struct rb_node *parent = NULL, **n = &root->rb_node;
402*6a54128fSAndroid Build Coastguard Worker 	struct rb_node *new_node, *node, *next;
403*6a54128fSAndroid Build Coastguard Worker 	struct bmap_rb_extent *new_ext;
404*6a54128fSAndroid Build Coastguard Worker 	struct bmap_rb_extent *ext;
405*6a54128fSAndroid Build Coastguard Worker 	int retval = 0;
406*6a54128fSAndroid Build Coastguard Worker 
407*6a54128fSAndroid Build Coastguard Worker 	if (count == 0)
408*6a54128fSAndroid Build Coastguard Worker 		return 0;
409*6a54128fSAndroid Build Coastguard Worker 
410*6a54128fSAndroid Build Coastguard Worker 	bp->rcursor_next = NULL;
411*6a54128fSAndroid Build Coastguard Worker 	ext = bp->wcursor;
412*6a54128fSAndroid Build Coastguard Worker 	if (ext) {
413*6a54128fSAndroid Build Coastguard Worker 		if (start >= ext->start &&
414*6a54128fSAndroid Build Coastguard Worker 		    start <= (ext->start + ext->count)) {
415*6a54128fSAndroid Build Coastguard Worker #ifdef ENABLE_BMAP_STATS_OPS
416*6a54128fSAndroid Build Coastguard Worker 			bp->mark_hit++;
417*6a54128fSAndroid Build Coastguard Worker #endif
418*6a54128fSAndroid Build Coastguard Worker 			goto got_extent;
419*6a54128fSAndroid Build Coastguard Worker 		}
420*6a54128fSAndroid Build Coastguard Worker 	}
421*6a54128fSAndroid Build Coastguard Worker 
422*6a54128fSAndroid Build Coastguard Worker 	while (*n) {
423*6a54128fSAndroid Build Coastguard Worker 		parent = *n;
424*6a54128fSAndroid Build Coastguard Worker 		ext = node_to_extent(parent);
425*6a54128fSAndroid Build Coastguard Worker 
426*6a54128fSAndroid Build Coastguard Worker 		if (start < ext->start) {
427*6a54128fSAndroid Build Coastguard Worker 			n = &(*n)->rb_left;
428*6a54128fSAndroid Build Coastguard Worker 		} else if (start > (ext->start + ext->count)) {
429*6a54128fSAndroid Build Coastguard Worker 			n = &(*n)->rb_right;
430*6a54128fSAndroid Build Coastguard Worker 		} else {
431*6a54128fSAndroid Build Coastguard Worker got_extent:
432*6a54128fSAndroid Build Coastguard Worker 			if ((start + count) <= (ext->start + ext->count))
433*6a54128fSAndroid Build Coastguard Worker 				return 1;
434*6a54128fSAndroid Build Coastguard Worker 
435*6a54128fSAndroid Build Coastguard Worker 			if ((ext->start + ext->count) == start)
436*6a54128fSAndroid Build Coastguard Worker 				retval = 0;
437*6a54128fSAndroid Build Coastguard Worker 			else
438*6a54128fSAndroid Build Coastguard Worker 				retval = 1;
439*6a54128fSAndroid Build Coastguard Worker 
440*6a54128fSAndroid Build Coastguard Worker 			count += (start - ext->start);
441*6a54128fSAndroid Build Coastguard Worker 			start = ext->start;
442*6a54128fSAndroid Build Coastguard Worker 			new_ext = ext;
443*6a54128fSAndroid Build Coastguard Worker 			new_node = &ext->node;
444*6a54128fSAndroid Build Coastguard Worker 
445*6a54128fSAndroid Build Coastguard Worker 			goto skip_insert;
446*6a54128fSAndroid Build Coastguard Worker 		}
447*6a54128fSAndroid Build Coastguard Worker 	}
448*6a54128fSAndroid Build Coastguard Worker 
449*6a54128fSAndroid Build Coastguard Worker 	rb_get_new_extent(&new_ext, start, count);
450*6a54128fSAndroid Build Coastguard Worker 
451*6a54128fSAndroid Build Coastguard Worker 	new_node = &new_ext->node;
452*6a54128fSAndroid Build Coastguard Worker 	ext2fs_rb_link_node(new_node, parent, n);
453*6a54128fSAndroid Build Coastguard Worker 	ext2fs_rb_insert_color(new_node, root);
454*6a54128fSAndroid Build Coastguard Worker 	bp->wcursor = new_ext;
455*6a54128fSAndroid Build Coastguard Worker 
456*6a54128fSAndroid Build Coastguard Worker 	node = ext2fs_rb_prev(new_node);
457*6a54128fSAndroid Build Coastguard Worker 	if (node) {
458*6a54128fSAndroid Build Coastguard Worker 		ext = node_to_extent(node);
459*6a54128fSAndroid Build Coastguard Worker 		if ((ext->start + ext->count) == start) {
460*6a54128fSAndroid Build Coastguard Worker 			start = ext->start;
461*6a54128fSAndroid Build Coastguard Worker 			count += ext->count;
462*6a54128fSAndroid Build Coastguard Worker 			ext2fs_rb_erase(node, root);
463*6a54128fSAndroid Build Coastguard Worker 			rb_free_extent(bp, ext);
464*6a54128fSAndroid Build Coastguard Worker 		}
465*6a54128fSAndroid Build Coastguard Worker 	}
466*6a54128fSAndroid Build Coastguard Worker 
467*6a54128fSAndroid Build Coastguard Worker skip_insert:
468*6a54128fSAndroid Build Coastguard Worker 	/* See if we can merge extent to the right */
469*6a54128fSAndroid Build Coastguard Worker 	for (node = ext2fs_rb_next(new_node); node != NULL; node = next) {
470*6a54128fSAndroid Build Coastguard Worker 		next = ext2fs_rb_next(node);
471*6a54128fSAndroid Build Coastguard Worker 		ext = node_to_extent(node);
472*6a54128fSAndroid Build Coastguard Worker 
473*6a54128fSAndroid Build Coastguard Worker 		if ((ext->start + ext->count) <= start)
474*6a54128fSAndroid Build Coastguard Worker 			continue;
475*6a54128fSAndroid Build Coastguard Worker 
476*6a54128fSAndroid Build Coastguard Worker 		/* No more merging */
477*6a54128fSAndroid Build Coastguard Worker 		if ((start + count) < ext->start)
478*6a54128fSAndroid Build Coastguard Worker 			break;
479*6a54128fSAndroid Build Coastguard Worker 
480*6a54128fSAndroid Build Coastguard Worker 		/* ext is embedded in new_ext interval */
481*6a54128fSAndroid Build Coastguard Worker 		if ((start + count) >= (ext->start + ext->count)) {
482*6a54128fSAndroid Build Coastguard Worker 			ext2fs_rb_erase(node, root);
483*6a54128fSAndroid Build Coastguard Worker 			rb_free_extent(bp, ext);
484*6a54128fSAndroid Build Coastguard Worker 			continue;
485*6a54128fSAndroid Build Coastguard Worker 		} else {
486*6a54128fSAndroid Build Coastguard Worker 		/* merge ext with new_ext */
487*6a54128fSAndroid Build Coastguard Worker 			count += ((ext->start + ext->count) -
488*6a54128fSAndroid Build Coastguard Worker 				  (start + count));
489*6a54128fSAndroid Build Coastguard Worker 			ext2fs_rb_erase(node, root);
490*6a54128fSAndroid Build Coastguard Worker 			rb_free_extent(bp, ext);
491*6a54128fSAndroid Build Coastguard Worker 			break;
492*6a54128fSAndroid Build Coastguard Worker 		}
493*6a54128fSAndroid Build Coastguard Worker 	}
494*6a54128fSAndroid Build Coastguard Worker 
495*6a54128fSAndroid Build Coastguard Worker 	new_ext->start = start;
496*6a54128fSAndroid Build Coastguard Worker 	new_ext->count = count;
497*6a54128fSAndroid Build Coastguard Worker 
498*6a54128fSAndroid Build Coastguard Worker 	return retval;
499*6a54128fSAndroid Build Coastguard Worker }
500*6a54128fSAndroid Build Coastguard Worker 
rb_remove_extent(__u64 start,__u64 count,struct ext2fs_rb_private * bp)501*6a54128fSAndroid Build Coastguard Worker static int rb_remove_extent(__u64 start, __u64 count,
502*6a54128fSAndroid Build Coastguard Worker 			    struct ext2fs_rb_private *bp)
503*6a54128fSAndroid Build Coastguard Worker {
504*6a54128fSAndroid Build Coastguard Worker 	struct rb_root *root = &bp->root;
505*6a54128fSAndroid Build Coastguard Worker 	struct rb_node *parent = NULL, **n = &root->rb_node;
506*6a54128fSAndroid Build Coastguard Worker 	struct rb_node *node;
507*6a54128fSAndroid Build Coastguard Worker 	struct bmap_rb_extent *ext;
508*6a54128fSAndroid Build Coastguard Worker 	__u64 new_start, new_count;
509*6a54128fSAndroid Build Coastguard Worker 	int retval = 0;
510*6a54128fSAndroid Build Coastguard Worker 
511*6a54128fSAndroid Build Coastguard Worker 	if (ext2fs_rb_empty_root(root))
512*6a54128fSAndroid Build Coastguard Worker 		return 0;
513*6a54128fSAndroid Build Coastguard Worker 
514*6a54128fSAndroid Build Coastguard Worker 	while (*n) {
515*6a54128fSAndroid Build Coastguard Worker 		parent = *n;
516*6a54128fSAndroid Build Coastguard Worker 		ext = node_to_extent(parent);
517*6a54128fSAndroid Build Coastguard Worker 		if (start < ext->start) {
518*6a54128fSAndroid Build Coastguard Worker 			n = &(*n)->rb_left;
519*6a54128fSAndroid Build Coastguard Worker 			continue;
520*6a54128fSAndroid Build Coastguard Worker 		} else if (start >= (ext->start + ext->count)) {
521*6a54128fSAndroid Build Coastguard Worker 			n = &(*n)->rb_right;
522*6a54128fSAndroid Build Coastguard Worker 			continue;
523*6a54128fSAndroid Build Coastguard Worker 		}
524*6a54128fSAndroid Build Coastguard Worker 
525*6a54128fSAndroid Build Coastguard Worker 		if ((start > ext->start) &&
526*6a54128fSAndroid Build Coastguard Worker 		    (start + count) < (ext->start + ext->count)) {
527*6a54128fSAndroid Build Coastguard Worker 			/* We have to split extent into two */
528*6a54128fSAndroid Build Coastguard Worker 			new_start = start + count;
529*6a54128fSAndroid Build Coastguard Worker 			new_count = (ext->start + ext->count) - new_start;
530*6a54128fSAndroid Build Coastguard Worker 
531*6a54128fSAndroid Build Coastguard Worker 			ext->count = start - ext->start;
532*6a54128fSAndroid Build Coastguard Worker 
533*6a54128fSAndroid Build Coastguard Worker 			rb_insert_extent(new_start, new_count, bp);
534*6a54128fSAndroid Build Coastguard Worker 			return 1;
535*6a54128fSAndroid Build Coastguard Worker 		}
536*6a54128fSAndroid Build Coastguard Worker 
537*6a54128fSAndroid Build Coastguard Worker 		if ((start + count) >= (ext->start + ext->count)) {
538*6a54128fSAndroid Build Coastguard Worker 			ext->count = start - ext->start;
539*6a54128fSAndroid Build Coastguard Worker 			retval = 1;
540*6a54128fSAndroid Build Coastguard Worker 		}
541*6a54128fSAndroid Build Coastguard Worker 
542*6a54128fSAndroid Build Coastguard Worker 		if (0 == ext->count) {
543*6a54128fSAndroid Build Coastguard Worker 			parent = ext2fs_rb_next(&ext->node);
544*6a54128fSAndroid Build Coastguard Worker 			ext2fs_rb_erase(&ext->node, root);
545*6a54128fSAndroid Build Coastguard Worker 			rb_free_extent(bp, ext);
546*6a54128fSAndroid Build Coastguard Worker 			break;
547*6a54128fSAndroid Build Coastguard Worker 		}
548*6a54128fSAndroid Build Coastguard Worker 
549*6a54128fSAndroid Build Coastguard Worker 		if (start == ext->start) {
550*6a54128fSAndroid Build Coastguard Worker 			ext->start += count;
551*6a54128fSAndroid Build Coastguard Worker 			ext->count -= count;
552*6a54128fSAndroid Build Coastguard Worker 			return 1;
553*6a54128fSAndroid Build Coastguard Worker 		}
554*6a54128fSAndroid Build Coastguard Worker 	}
555*6a54128fSAndroid Build Coastguard Worker 
556*6a54128fSAndroid Build Coastguard Worker 	/* See if we should delete or truncate extent on the right */
557*6a54128fSAndroid Build Coastguard Worker 	for (; parent != NULL; parent = node) {
558*6a54128fSAndroid Build Coastguard Worker 		node = ext2fs_rb_next(parent);
559*6a54128fSAndroid Build Coastguard Worker 		ext = node_to_extent(parent);
560*6a54128fSAndroid Build Coastguard Worker 		if ((ext->start + ext->count) <= start)
561*6a54128fSAndroid Build Coastguard Worker 			continue;
562*6a54128fSAndroid Build Coastguard Worker 
563*6a54128fSAndroid Build Coastguard Worker 		/* No more extents to be removed/truncated */
564*6a54128fSAndroid Build Coastguard Worker 		if ((start + count) < ext->start)
565*6a54128fSAndroid Build Coastguard Worker 			break;
566*6a54128fSAndroid Build Coastguard Worker 
567*6a54128fSAndroid Build Coastguard Worker 		/* The entire extent is within the region to be removed */
568*6a54128fSAndroid Build Coastguard Worker 		if ((start + count) >= (ext->start + ext->count)) {
569*6a54128fSAndroid Build Coastguard Worker 			ext2fs_rb_erase(parent, root);
570*6a54128fSAndroid Build Coastguard Worker 			rb_free_extent(bp, ext);
571*6a54128fSAndroid Build Coastguard Worker 			retval = 1;
572*6a54128fSAndroid Build Coastguard Worker 			continue;
573*6a54128fSAndroid Build Coastguard Worker 		} else {
574*6a54128fSAndroid Build Coastguard Worker 			/* modify the last extent in region to be removed */
575*6a54128fSAndroid Build Coastguard Worker 			ext->count -= ((start + count) - ext->start);
576*6a54128fSAndroid Build Coastguard Worker 			ext->start = start + count;
577*6a54128fSAndroid Build Coastguard Worker 			retval = 1;
578*6a54128fSAndroid Build Coastguard Worker 			break;
579*6a54128fSAndroid Build Coastguard Worker 		}
580*6a54128fSAndroid Build Coastguard Worker 	}
581*6a54128fSAndroid Build Coastguard Worker 
582*6a54128fSAndroid Build Coastguard Worker 	return retval;
583*6a54128fSAndroid Build Coastguard Worker }
584*6a54128fSAndroid Build Coastguard Worker 
rb_mark_bmap(ext2fs_generic_bitmap_64 bitmap,__u64 arg)585*6a54128fSAndroid Build Coastguard Worker static int rb_mark_bmap(ext2fs_generic_bitmap_64 bitmap, __u64 arg)
586*6a54128fSAndroid Build Coastguard Worker {
587*6a54128fSAndroid Build Coastguard Worker 	struct ext2fs_rb_private *bp;
588*6a54128fSAndroid Build Coastguard Worker 	int retval;
589*6a54128fSAndroid Build Coastguard Worker 
590*6a54128fSAndroid Build Coastguard Worker 	bp = (struct ext2fs_rb_private *) bitmap->private;
591*6a54128fSAndroid Build Coastguard Worker 	arg -= bitmap->start;
592*6a54128fSAndroid Build Coastguard Worker 
593*6a54128fSAndroid Build Coastguard Worker 	retval = rb_insert_extent(arg, 1, bp);
594*6a54128fSAndroid Build Coastguard Worker 	check_tree(&bp->root, __func__);
595*6a54128fSAndroid Build Coastguard Worker 	return retval;
596*6a54128fSAndroid Build Coastguard Worker }
597*6a54128fSAndroid Build Coastguard Worker 
rb_unmark_bmap(ext2fs_generic_bitmap_64 bitmap,__u64 arg)598*6a54128fSAndroid Build Coastguard Worker static int rb_unmark_bmap(ext2fs_generic_bitmap_64 bitmap, __u64 arg)
599*6a54128fSAndroid Build Coastguard Worker {
600*6a54128fSAndroid Build Coastguard Worker 	struct ext2fs_rb_private *bp;
601*6a54128fSAndroid Build Coastguard Worker 	int retval;
602*6a54128fSAndroid Build Coastguard Worker 
603*6a54128fSAndroid Build Coastguard Worker 	bp = (struct ext2fs_rb_private *) bitmap->private;
604*6a54128fSAndroid Build Coastguard Worker 	arg -= bitmap->start;
605*6a54128fSAndroid Build Coastguard Worker 
606*6a54128fSAndroid Build Coastguard Worker 	retval = rb_remove_extent(arg, 1, bp);
607*6a54128fSAndroid Build Coastguard Worker 	check_tree(&bp->root, __func__);
608*6a54128fSAndroid Build Coastguard Worker 
609*6a54128fSAndroid Build Coastguard Worker 	return retval;
610*6a54128fSAndroid Build Coastguard Worker }
611*6a54128fSAndroid Build Coastguard Worker 
612*6a54128fSAndroid Build Coastguard Worker inline
rb_test_bmap(ext2fs_generic_bitmap_64 bitmap,__u64 arg)613*6a54128fSAndroid Build Coastguard Worker static int rb_test_bmap(ext2fs_generic_bitmap_64 bitmap, __u64 arg)
614*6a54128fSAndroid Build Coastguard Worker {
615*6a54128fSAndroid Build Coastguard Worker 	struct ext2fs_rb_private *bp;
616*6a54128fSAndroid Build Coastguard Worker 
617*6a54128fSAndroid Build Coastguard Worker 	bp = (struct ext2fs_rb_private *) bitmap->private;
618*6a54128fSAndroid Build Coastguard Worker 	arg -= bitmap->start;
619*6a54128fSAndroid Build Coastguard Worker 
620*6a54128fSAndroid Build Coastguard Worker 	return rb_test_bit(bp, arg);
621*6a54128fSAndroid Build Coastguard Worker }
622*6a54128fSAndroid Build Coastguard Worker 
rb_mark_bmap_extent(ext2fs_generic_bitmap_64 bitmap,__u64 arg,unsigned int num)623*6a54128fSAndroid Build Coastguard Worker static void rb_mark_bmap_extent(ext2fs_generic_bitmap_64 bitmap, __u64 arg,
624*6a54128fSAndroid Build Coastguard Worker 				unsigned int num)
625*6a54128fSAndroid Build Coastguard Worker {
626*6a54128fSAndroid Build Coastguard Worker 	struct ext2fs_rb_private *bp;
627*6a54128fSAndroid Build Coastguard Worker 
628*6a54128fSAndroid Build Coastguard Worker 	bp = (struct ext2fs_rb_private *) bitmap->private;
629*6a54128fSAndroid Build Coastguard Worker 	arg -= bitmap->start;
630*6a54128fSAndroid Build Coastguard Worker 
631*6a54128fSAndroid Build Coastguard Worker 	rb_insert_extent(arg, num, bp);
632*6a54128fSAndroid Build Coastguard Worker 	check_tree(&bp->root, __func__);
633*6a54128fSAndroid Build Coastguard Worker }
634*6a54128fSAndroid Build Coastguard Worker 
rb_unmark_bmap_extent(ext2fs_generic_bitmap_64 bitmap,__u64 arg,unsigned int num)635*6a54128fSAndroid Build Coastguard Worker static void rb_unmark_bmap_extent(ext2fs_generic_bitmap_64 bitmap, __u64 arg,
636*6a54128fSAndroid Build Coastguard Worker 				  unsigned int num)
637*6a54128fSAndroid Build Coastguard Worker {
638*6a54128fSAndroid Build Coastguard Worker 	struct ext2fs_rb_private *bp;
639*6a54128fSAndroid Build Coastguard Worker 
640*6a54128fSAndroid Build Coastguard Worker 	bp = (struct ext2fs_rb_private *) bitmap->private;
641*6a54128fSAndroid Build Coastguard Worker 	arg -= bitmap->start;
642*6a54128fSAndroid Build Coastguard Worker 
643*6a54128fSAndroid Build Coastguard Worker 	rb_remove_extent(arg, num, bp);
644*6a54128fSAndroid Build Coastguard Worker 	check_tree(&bp->root, __func__);
645*6a54128fSAndroid Build Coastguard Worker }
646*6a54128fSAndroid Build Coastguard Worker 
rb_test_clear_bmap_extent(ext2fs_generic_bitmap_64 bitmap,__u64 start,unsigned int len)647*6a54128fSAndroid Build Coastguard Worker static int rb_test_clear_bmap_extent(ext2fs_generic_bitmap_64 bitmap,
648*6a54128fSAndroid Build Coastguard Worker 				     __u64 start, unsigned int len)
649*6a54128fSAndroid Build Coastguard Worker {
650*6a54128fSAndroid Build Coastguard Worker 	struct rb_node *parent = NULL, **n;
651*6a54128fSAndroid Build Coastguard Worker 	struct rb_node *node, *next;
652*6a54128fSAndroid Build Coastguard Worker 	struct ext2fs_rb_private *bp;
653*6a54128fSAndroid Build Coastguard Worker 	struct bmap_rb_extent *ext;
654*6a54128fSAndroid Build Coastguard Worker 	int retval = 1;
655*6a54128fSAndroid Build Coastguard Worker 
656*6a54128fSAndroid Build Coastguard Worker 	bp = (struct ext2fs_rb_private *) bitmap->private;
657*6a54128fSAndroid Build Coastguard Worker 	n = &bp->root.rb_node;
658*6a54128fSAndroid Build Coastguard Worker 	start -= bitmap->start;
659*6a54128fSAndroid Build Coastguard Worker 
660*6a54128fSAndroid Build Coastguard Worker 	if (len == 0 || ext2fs_rb_empty_root(&bp->root))
661*6a54128fSAndroid Build Coastguard Worker 		return 1;
662*6a54128fSAndroid Build Coastguard Worker 
663*6a54128fSAndroid Build Coastguard Worker 	/*
664*6a54128fSAndroid Build Coastguard Worker 	 * If we find nothing, we should examine whole extent, but
665*6a54128fSAndroid Build Coastguard Worker 	 * when we find match, the extent is not clean, thus be return
666*6a54128fSAndroid Build Coastguard Worker 	 * false.
667*6a54128fSAndroid Build Coastguard Worker 	 */
668*6a54128fSAndroid Build Coastguard Worker 	while (*n) {
669*6a54128fSAndroid Build Coastguard Worker 		parent = *n;
670*6a54128fSAndroid Build Coastguard Worker 		ext = node_to_extent(parent);
671*6a54128fSAndroid Build Coastguard Worker 		if (start < ext->start) {
672*6a54128fSAndroid Build Coastguard Worker 			n = &(*n)->rb_left;
673*6a54128fSAndroid Build Coastguard Worker 		} else if (start >= (ext->start + ext->count)) {
674*6a54128fSAndroid Build Coastguard Worker 			n = &(*n)->rb_right;
675*6a54128fSAndroid Build Coastguard Worker 		} else {
676*6a54128fSAndroid Build Coastguard Worker 			/*
677*6a54128fSAndroid Build Coastguard Worker 			 * We found extent int the tree -> extent is not
678*6a54128fSAndroid Build Coastguard Worker 			 * clean
679*6a54128fSAndroid Build Coastguard Worker 			 */
680*6a54128fSAndroid Build Coastguard Worker 			return 0;
681*6a54128fSAndroid Build Coastguard Worker 		}
682*6a54128fSAndroid Build Coastguard Worker 	}
683*6a54128fSAndroid Build Coastguard Worker 
684*6a54128fSAndroid Build Coastguard Worker 	node = parent;
685*6a54128fSAndroid Build Coastguard Worker 	while (node) {
686*6a54128fSAndroid Build Coastguard Worker 		next = ext2fs_rb_next(node);
687*6a54128fSAndroid Build Coastguard Worker 		ext = node_to_extent(node);
688*6a54128fSAndroid Build Coastguard Worker 		node = next;
689*6a54128fSAndroid Build Coastguard Worker 
690*6a54128fSAndroid Build Coastguard Worker 		if ((ext->start + ext->count) <= start)
691*6a54128fSAndroid Build Coastguard Worker 			continue;
692*6a54128fSAndroid Build Coastguard Worker 
693*6a54128fSAndroid Build Coastguard Worker 		/* No more merging */
694*6a54128fSAndroid Build Coastguard Worker 		if ((start + len) <= ext->start)
695*6a54128fSAndroid Build Coastguard Worker 			break;
696*6a54128fSAndroid Build Coastguard Worker 
697*6a54128fSAndroid Build Coastguard Worker 		retval = 0;
698*6a54128fSAndroid Build Coastguard Worker 		break;
699*6a54128fSAndroid Build Coastguard Worker 	}
700*6a54128fSAndroid Build Coastguard Worker 	return retval;
701*6a54128fSAndroid Build Coastguard Worker }
702*6a54128fSAndroid Build Coastguard Worker 
rb_set_bmap_range(ext2fs_generic_bitmap_64 bitmap,__u64 start,size_t num,void * in)703*6a54128fSAndroid Build Coastguard Worker static errcode_t rb_set_bmap_range(ext2fs_generic_bitmap_64 bitmap,
704*6a54128fSAndroid Build Coastguard Worker 				     __u64 start, size_t num, void *in)
705*6a54128fSAndroid Build Coastguard Worker {
706*6a54128fSAndroid Build Coastguard Worker 	struct ext2fs_rb_private *bp;
707*6a54128fSAndroid Build Coastguard Worker 	unsigned char *cp = in;
708*6a54128fSAndroid Build Coastguard Worker 	size_t i;
709*6a54128fSAndroid Build Coastguard Worker 	int first_set = -1;
710*6a54128fSAndroid Build Coastguard Worker 
711*6a54128fSAndroid Build Coastguard Worker 	bp = (struct ext2fs_rb_private *) bitmap->private;
712*6a54128fSAndroid Build Coastguard Worker 
713*6a54128fSAndroid Build Coastguard Worker 	for (i = 0; i < num; i++) {
714*6a54128fSAndroid Build Coastguard Worker 		if ((i & 7) == 0) {
715*6a54128fSAndroid Build Coastguard Worker 			unsigned char c = cp[i/8];
716*6a54128fSAndroid Build Coastguard Worker 			if (c == 0xFF) {
717*6a54128fSAndroid Build Coastguard Worker 				if (first_set == -1)
718*6a54128fSAndroid Build Coastguard Worker 					first_set = i;
719*6a54128fSAndroid Build Coastguard Worker 				i += 7;
720*6a54128fSAndroid Build Coastguard Worker 				continue;
721*6a54128fSAndroid Build Coastguard Worker 			}
722*6a54128fSAndroid Build Coastguard Worker 			if ((c == 0x00) && (first_set == -1)) {
723*6a54128fSAndroid Build Coastguard Worker 				i += 7;
724*6a54128fSAndroid Build Coastguard Worker 				continue;
725*6a54128fSAndroid Build Coastguard Worker 			}
726*6a54128fSAndroid Build Coastguard Worker 		}
727*6a54128fSAndroid Build Coastguard Worker 		if (ext2fs_test_bit(i, in)) {
728*6a54128fSAndroid Build Coastguard Worker 			if (first_set == -1)
729*6a54128fSAndroid Build Coastguard Worker 				first_set = i;
730*6a54128fSAndroid Build Coastguard Worker 			continue;
731*6a54128fSAndroid Build Coastguard Worker 		}
732*6a54128fSAndroid Build Coastguard Worker 		if (first_set == -1)
733*6a54128fSAndroid Build Coastguard Worker 			continue;
734*6a54128fSAndroid Build Coastguard Worker 
735*6a54128fSAndroid Build Coastguard Worker 		rb_insert_extent(start + first_set - bitmap->start,
736*6a54128fSAndroid Build Coastguard Worker 				 i - first_set, bp);
737*6a54128fSAndroid Build Coastguard Worker 		check_tree(&bp->root, __func__);
738*6a54128fSAndroid Build Coastguard Worker 		first_set = -1;
739*6a54128fSAndroid Build Coastguard Worker 	}
740*6a54128fSAndroid Build Coastguard Worker 	if (first_set != -1) {
741*6a54128fSAndroid Build Coastguard Worker 		rb_insert_extent(start + first_set - bitmap->start,
742*6a54128fSAndroid Build Coastguard Worker 				 num - first_set, bp);
743*6a54128fSAndroid Build Coastguard Worker 		check_tree(&bp->root, __func__);
744*6a54128fSAndroid Build Coastguard Worker 	}
745*6a54128fSAndroid Build Coastguard Worker 
746*6a54128fSAndroid Build Coastguard Worker 	return 0;
747*6a54128fSAndroid Build Coastguard Worker }
748*6a54128fSAndroid Build Coastguard Worker 
rb_get_bmap_range(ext2fs_generic_bitmap_64 bitmap,__u64 start,size_t num,void * out)749*6a54128fSAndroid Build Coastguard Worker static errcode_t rb_get_bmap_range(ext2fs_generic_bitmap_64 bitmap,
750*6a54128fSAndroid Build Coastguard Worker 				     __u64 start, size_t num, void *out)
751*6a54128fSAndroid Build Coastguard Worker {
752*6a54128fSAndroid Build Coastguard Worker 
753*6a54128fSAndroid Build Coastguard Worker 	struct rb_node *parent = NULL, *next, **n;
754*6a54128fSAndroid Build Coastguard Worker 	struct ext2fs_rb_private *bp;
755*6a54128fSAndroid Build Coastguard Worker 	struct bmap_rb_extent *ext;
756*6a54128fSAndroid Build Coastguard Worker 	__u64 count, pos;
757*6a54128fSAndroid Build Coastguard Worker 
758*6a54128fSAndroid Build Coastguard Worker 	bp = (struct ext2fs_rb_private *) bitmap->private;
759*6a54128fSAndroid Build Coastguard Worker 	n = &bp->root.rb_node;
760*6a54128fSAndroid Build Coastguard Worker 	start -= bitmap->start;
761*6a54128fSAndroid Build Coastguard Worker 
762*6a54128fSAndroid Build Coastguard Worker 	if (ext2fs_rb_empty_root(&bp->root))
763*6a54128fSAndroid Build Coastguard Worker 		return 0;
764*6a54128fSAndroid Build Coastguard Worker 
765*6a54128fSAndroid Build Coastguard Worker 	while (*n) {
766*6a54128fSAndroid Build Coastguard Worker 		parent = *n;
767*6a54128fSAndroid Build Coastguard Worker 		ext = node_to_extent(parent);
768*6a54128fSAndroid Build Coastguard Worker 		if (start < ext->start) {
769*6a54128fSAndroid Build Coastguard Worker 			n = &(*n)->rb_left;
770*6a54128fSAndroid Build Coastguard Worker 		} else if (start >= (ext->start + ext->count)) {
771*6a54128fSAndroid Build Coastguard Worker 			n = &(*n)->rb_right;
772*6a54128fSAndroid Build Coastguard Worker 		} else
773*6a54128fSAndroid Build Coastguard Worker 			break;
774*6a54128fSAndroid Build Coastguard Worker 	}
775*6a54128fSAndroid Build Coastguard Worker 
776*6a54128fSAndroid Build Coastguard Worker 	memset(out, 0, (num + 7) >> 3);
777*6a54128fSAndroid Build Coastguard Worker 
778*6a54128fSAndroid Build Coastguard Worker 	for (; parent != NULL; parent = next) {
779*6a54128fSAndroid Build Coastguard Worker 		next = ext2fs_rb_next(parent);
780*6a54128fSAndroid Build Coastguard Worker 		ext = node_to_extent(parent);
781*6a54128fSAndroid Build Coastguard Worker 
782*6a54128fSAndroid Build Coastguard Worker 		pos = ext->start;
783*6a54128fSAndroid Build Coastguard Worker 		count = ext->count;
784*6a54128fSAndroid Build Coastguard Worker 		if (pos >= start + num)
785*6a54128fSAndroid Build Coastguard Worker 			break;
786*6a54128fSAndroid Build Coastguard Worker 		if (pos < start) {
787*6a54128fSAndroid Build Coastguard Worker 			if (pos + count <  start)
788*6a54128fSAndroid Build Coastguard Worker 				continue;
789*6a54128fSAndroid Build Coastguard Worker 			count -= start - pos;
790*6a54128fSAndroid Build Coastguard Worker 			pos = start;
791*6a54128fSAndroid Build Coastguard Worker 		}
792*6a54128fSAndroid Build Coastguard Worker 		if (pos + count > start + num)
793*6a54128fSAndroid Build Coastguard Worker 			count = start + num - pos;
794*6a54128fSAndroid Build Coastguard Worker 
795*6a54128fSAndroid Build Coastguard Worker 		while (count > 0) {
796*6a54128fSAndroid Build Coastguard Worker 			if ((count >= 8) &&
797*6a54128fSAndroid Build Coastguard Worker 			    ((pos - start) % 8) == 0) {
798*6a54128fSAndroid Build Coastguard Worker 				int nbytes = count >> 3;
799*6a54128fSAndroid Build Coastguard Worker 				int offset = (pos - start) >> 3;
800*6a54128fSAndroid Build Coastguard Worker 
801*6a54128fSAndroid Build Coastguard Worker 				memset(((char *) out) + offset, 0xFF, nbytes);
802*6a54128fSAndroid Build Coastguard Worker 				pos += nbytes << 3;
803*6a54128fSAndroid Build Coastguard Worker 				count -= nbytes << 3;
804*6a54128fSAndroid Build Coastguard Worker 				continue;
805*6a54128fSAndroid Build Coastguard Worker 			}
806*6a54128fSAndroid Build Coastguard Worker 			ext2fs_fast_set_bit64((pos - start), out);
807*6a54128fSAndroid Build Coastguard Worker 			pos++;
808*6a54128fSAndroid Build Coastguard Worker 			count--;
809*6a54128fSAndroid Build Coastguard Worker 		}
810*6a54128fSAndroid Build Coastguard Worker 	}
811*6a54128fSAndroid Build Coastguard Worker 	return 0;
812*6a54128fSAndroid Build Coastguard Worker }
813*6a54128fSAndroid Build Coastguard Worker 
rb_clear_bmap(ext2fs_generic_bitmap_64 bitmap)814*6a54128fSAndroid Build Coastguard Worker static void rb_clear_bmap(ext2fs_generic_bitmap_64 bitmap)
815*6a54128fSAndroid Build Coastguard Worker {
816*6a54128fSAndroid Build Coastguard Worker 	struct ext2fs_rb_private *bp;
817*6a54128fSAndroid Build Coastguard Worker 
818*6a54128fSAndroid Build Coastguard Worker 	bp = (struct ext2fs_rb_private *) bitmap->private;
819*6a54128fSAndroid Build Coastguard Worker 
820*6a54128fSAndroid Build Coastguard Worker 	rb_free_tree(&bp->root);
821*6a54128fSAndroid Build Coastguard Worker 	bp->rcursor = NULL;
822*6a54128fSAndroid Build Coastguard Worker 	bp->rcursor_next = NULL;
823*6a54128fSAndroid Build Coastguard Worker 	bp->wcursor = NULL;
824*6a54128fSAndroid Build Coastguard Worker 	check_tree(&bp->root, __func__);
825*6a54128fSAndroid Build Coastguard Worker }
826*6a54128fSAndroid Build Coastguard Worker 
rb_find_first_zero(ext2fs_generic_bitmap_64 bitmap,__u64 start,__u64 end,__u64 * out)827*6a54128fSAndroid Build Coastguard Worker static errcode_t rb_find_first_zero(ext2fs_generic_bitmap_64 bitmap,
828*6a54128fSAndroid Build Coastguard Worker 				   __u64 start, __u64 end, __u64 *out)
829*6a54128fSAndroid Build Coastguard Worker {
830*6a54128fSAndroid Build Coastguard Worker 	struct rb_node *parent = NULL, **n;
831*6a54128fSAndroid Build Coastguard Worker 	struct ext2fs_rb_private *bp;
832*6a54128fSAndroid Build Coastguard Worker 	struct bmap_rb_extent *ext;
833*6a54128fSAndroid Build Coastguard Worker 
834*6a54128fSAndroid Build Coastguard Worker 	bp = (struct ext2fs_rb_private *) bitmap->private;
835*6a54128fSAndroid Build Coastguard Worker 	n = &bp->root.rb_node;
836*6a54128fSAndroid Build Coastguard Worker 	start -= bitmap->start;
837*6a54128fSAndroid Build Coastguard Worker 	end -= bitmap->start;
838*6a54128fSAndroid Build Coastguard Worker 
839*6a54128fSAndroid Build Coastguard Worker 	if (start > end)
840*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
841*6a54128fSAndroid Build Coastguard Worker 
842*6a54128fSAndroid Build Coastguard Worker 	if (ext2fs_rb_empty_root(&bp->root))
843*6a54128fSAndroid Build Coastguard Worker 		return ENOENT;
844*6a54128fSAndroid Build Coastguard Worker 
845*6a54128fSAndroid Build Coastguard Worker 	while (*n) {
846*6a54128fSAndroid Build Coastguard Worker 		parent = *n;
847*6a54128fSAndroid Build Coastguard Worker 		ext = node_to_extent(parent);
848*6a54128fSAndroid Build Coastguard Worker 		if (start < ext->start) {
849*6a54128fSAndroid Build Coastguard Worker 			n = &(*n)->rb_left;
850*6a54128fSAndroid Build Coastguard Worker 		} else if (start >= (ext->start + ext->count)) {
851*6a54128fSAndroid Build Coastguard Worker 			n = &(*n)->rb_right;
852*6a54128fSAndroid Build Coastguard Worker 		} else if (ext->start + ext->count <= end) {
853*6a54128fSAndroid Build Coastguard Worker 			*out = ext->start + ext->count + bitmap->start;
854*6a54128fSAndroid Build Coastguard Worker 			return 0;
855*6a54128fSAndroid Build Coastguard Worker 		} else
856*6a54128fSAndroid Build Coastguard Worker 			return ENOENT;
857*6a54128fSAndroid Build Coastguard Worker 	}
858*6a54128fSAndroid Build Coastguard Worker 
859*6a54128fSAndroid Build Coastguard Worker 	*out = start + bitmap->start;
860*6a54128fSAndroid Build Coastguard Worker 	return 0;
861*6a54128fSAndroid Build Coastguard Worker }
862*6a54128fSAndroid Build Coastguard Worker 
rb_find_first_set(ext2fs_generic_bitmap_64 bitmap,__u64 start,__u64 end,__u64 * out)863*6a54128fSAndroid Build Coastguard Worker static errcode_t rb_find_first_set(ext2fs_generic_bitmap_64 bitmap,
864*6a54128fSAndroid Build Coastguard Worker 				   __u64 start, __u64 end, __u64 *out)
865*6a54128fSAndroid Build Coastguard Worker {
866*6a54128fSAndroid Build Coastguard Worker 	struct rb_node *parent = NULL, **n;
867*6a54128fSAndroid Build Coastguard Worker 	struct rb_node *node;
868*6a54128fSAndroid Build Coastguard Worker 	struct ext2fs_rb_private *bp;
869*6a54128fSAndroid Build Coastguard Worker 	struct bmap_rb_extent *ext;
870*6a54128fSAndroid Build Coastguard Worker 
871*6a54128fSAndroid Build Coastguard Worker 	bp = (struct ext2fs_rb_private *) bitmap->private;
872*6a54128fSAndroid Build Coastguard Worker 	n = &bp->root.rb_node;
873*6a54128fSAndroid Build Coastguard Worker 	start -= bitmap->start;
874*6a54128fSAndroid Build Coastguard Worker 	end -= bitmap->start;
875*6a54128fSAndroid Build Coastguard Worker 
876*6a54128fSAndroid Build Coastguard Worker 	if (start > end)
877*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
878*6a54128fSAndroid Build Coastguard Worker 
879*6a54128fSAndroid Build Coastguard Worker 	if (ext2fs_rb_empty_root(&bp->root))
880*6a54128fSAndroid Build Coastguard Worker 		return ENOENT;
881*6a54128fSAndroid Build Coastguard Worker 
882*6a54128fSAndroid Build Coastguard Worker 	while (*n) {
883*6a54128fSAndroid Build Coastguard Worker 		parent = *n;
884*6a54128fSAndroid Build Coastguard Worker 		ext = node_to_extent(parent);
885*6a54128fSAndroid Build Coastguard Worker 		if (start < ext->start) {
886*6a54128fSAndroid Build Coastguard Worker 			n = &(*n)->rb_left;
887*6a54128fSAndroid Build Coastguard Worker 		} else if (start >= (ext->start + ext->count)) {
888*6a54128fSAndroid Build Coastguard Worker 			n = &(*n)->rb_right;
889*6a54128fSAndroid Build Coastguard Worker 		} else {
890*6a54128fSAndroid Build Coastguard Worker 			/* The start bit is set */
891*6a54128fSAndroid Build Coastguard Worker 			*out = start + bitmap->start;
892*6a54128fSAndroid Build Coastguard Worker 			return 0;
893*6a54128fSAndroid Build Coastguard Worker 		}
894*6a54128fSAndroid Build Coastguard Worker 	}
895*6a54128fSAndroid Build Coastguard Worker 
896*6a54128fSAndroid Build Coastguard Worker 	node = parent;
897*6a54128fSAndroid Build Coastguard Worker 	ext = node_to_extent(node);
898*6a54128fSAndroid Build Coastguard Worker 	if (ext->start < start) {
899*6a54128fSAndroid Build Coastguard Worker 		node = ext2fs_rb_next(node);
900*6a54128fSAndroid Build Coastguard Worker 		if (node == NULL)
901*6a54128fSAndroid Build Coastguard Worker 			return ENOENT;
902*6a54128fSAndroid Build Coastguard Worker 		ext = node_to_extent(node);
903*6a54128fSAndroid Build Coastguard Worker 	}
904*6a54128fSAndroid Build Coastguard Worker 	if (ext->start <= end) {
905*6a54128fSAndroid Build Coastguard Worker 		*out = ext->start + bitmap->start;
906*6a54128fSAndroid Build Coastguard Worker 		return 0;
907*6a54128fSAndroid Build Coastguard Worker 	}
908*6a54128fSAndroid Build Coastguard Worker 	return ENOENT;
909*6a54128fSAndroid Build Coastguard Worker }
910*6a54128fSAndroid Build Coastguard Worker 
911*6a54128fSAndroid Build Coastguard Worker #ifdef ENABLE_BMAP_STATS
rb_print_stats(ext2fs_generic_bitmap_64 bitmap)912*6a54128fSAndroid Build Coastguard Worker static void rb_print_stats(ext2fs_generic_bitmap_64 bitmap)
913*6a54128fSAndroid Build Coastguard Worker {
914*6a54128fSAndroid Build Coastguard Worker 	struct ext2fs_rb_private *bp;
915*6a54128fSAndroid Build Coastguard Worker 	struct rb_node *node = NULL;
916*6a54128fSAndroid Build Coastguard Worker 	struct bmap_rb_extent *ext;
917*6a54128fSAndroid Build Coastguard Worker 	__u64 count = 0;
918*6a54128fSAndroid Build Coastguard Worker 	__u64 max_size = 0;
919*6a54128fSAndroid Build Coastguard Worker 	__u64 min_size = ULONG_MAX;
920*6a54128fSAndroid Build Coastguard Worker 	__u64 size = 0, avg_size = 0;
921*6a54128fSAndroid Build Coastguard Worker 	double eff;
922*6a54128fSAndroid Build Coastguard Worker #ifdef ENABLE_BMAP_STATS_OPS
923*6a54128fSAndroid Build Coastguard Worker 	__u64 mark_all, test_all;
924*6a54128fSAndroid Build Coastguard Worker 	double m_hit = 0.0, t_hit = 0.0;
925*6a54128fSAndroid Build Coastguard Worker #endif
926*6a54128fSAndroid Build Coastguard Worker 
927*6a54128fSAndroid Build Coastguard Worker 	bp = (struct ext2fs_rb_private *) bitmap->private;
928*6a54128fSAndroid Build Coastguard Worker 
929*6a54128fSAndroid Build Coastguard Worker 	for (node = ext2fs_rb_first(&bp->root); node != NULL;
930*6a54128fSAndroid Build Coastguard Worker 	     node = ext2fs_rb_next(node)) {
931*6a54128fSAndroid Build Coastguard Worker 		ext = node_to_extent(node);
932*6a54128fSAndroid Build Coastguard Worker 		count++;
933*6a54128fSAndroid Build Coastguard Worker 		if (ext->count > max_size)
934*6a54128fSAndroid Build Coastguard Worker 			max_size = ext->count;
935*6a54128fSAndroid Build Coastguard Worker 		if (ext->count < min_size)
936*6a54128fSAndroid Build Coastguard Worker 			min_size = ext->count;
937*6a54128fSAndroid Build Coastguard Worker 		size += ext->count;
938*6a54128fSAndroid Build Coastguard Worker 	}
939*6a54128fSAndroid Build Coastguard Worker 
940*6a54128fSAndroid Build Coastguard Worker 	if (count)
941*6a54128fSAndroid Build Coastguard Worker 		avg_size = size / count;
942*6a54128fSAndroid Build Coastguard Worker 	if (min_size == ULONG_MAX)
943*6a54128fSAndroid Build Coastguard Worker 		min_size = 0;
944*6a54128fSAndroid Build Coastguard Worker 	eff = (double)((count * sizeof(struct bmap_rb_extent)) << 3) /
945*6a54128fSAndroid Build Coastguard Worker 	      (bitmap->real_end - bitmap->start);
946*6a54128fSAndroid Build Coastguard Worker #ifdef ENABLE_BMAP_STATS_OPS
947*6a54128fSAndroid Build Coastguard Worker 	mark_all = bitmap->stats.mark_count + bitmap->stats.mark_ext_count;
948*6a54128fSAndroid Build Coastguard Worker 	test_all = bitmap->stats.test_count + bitmap->stats.test_ext_count;
949*6a54128fSAndroid Build Coastguard Worker 	if (mark_all)
950*6a54128fSAndroid Build Coastguard Worker 		m_hit = ((double)bp->mark_hit / mark_all) * 100;
951*6a54128fSAndroid Build Coastguard Worker 	if (test_all)
952*6a54128fSAndroid Build Coastguard Worker 		t_hit = ((double)bp->test_hit / test_all) * 100;
953*6a54128fSAndroid Build Coastguard Worker 
954*6a54128fSAndroid Build Coastguard Worker 	fprintf(stderr, "%16llu cache hits on test (%.2f%%)\n"
955*6a54128fSAndroid Build Coastguard Worker 		"%16llu cache hits on mark (%.2f%%)\n",
956*6a54128fSAndroid Build Coastguard Worker 		bp->test_hit, t_hit, bp->mark_hit, m_hit);
957*6a54128fSAndroid Build Coastguard Worker #endif
958*6a54128fSAndroid Build Coastguard Worker 	fprintf(stderr, "%16llu extents (%llu bytes)\n",
959*6a54128fSAndroid Build Coastguard Worker 		(unsigned long long) count, (unsigned long long)
960*6a54128fSAndroid Build Coastguard Worker 		((count * sizeof(struct bmap_rb_extent)) +
961*6a54128fSAndroid Build Coastguard Worker 		 sizeof(struct ext2fs_rb_private)));
962*6a54128fSAndroid Build Coastguard Worker  	fprintf(stderr, "%16llu bits minimum size\n",
963*6a54128fSAndroid Build Coastguard Worker 		(unsigned long long) min_size);
964*6a54128fSAndroid Build Coastguard Worker 	fprintf(stderr, "%16llu bits maximum size\n"
965*6a54128fSAndroid Build Coastguard Worker 		"%16llu bits average size\n",
966*6a54128fSAndroid Build Coastguard Worker 		(unsigned long long) max_size, (unsigned long long) avg_size);
967*6a54128fSAndroid Build Coastguard Worker 	fprintf(stderr, "%16llu bits set in bitmap (out of %llu)\n",
968*6a54128fSAndroid Build Coastguard Worker 		(unsigned long long) size,
969*6a54128fSAndroid Build Coastguard Worker 		(unsigned long long) bitmap->real_end - bitmap->start);
970*6a54128fSAndroid Build Coastguard Worker 	fprintf(stderr,
971*6a54128fSAndroid Build Coastguard Worker 		"%16.4lf memory / bitmap bit memory ratio (bitarray = 1)\n",
972*6a54128fSAndroid Build Coastguard Worker 		eff);
973*6a54128fSAndroid Build Coastguard Worker }
974*6a54128fSAndroid Build Coastguard Worker #else
rb_print_stats(ext2fs_generic_bitmap_64 bitmap EXT2FS_ATTR ((unused)))975*6a54128fSAndroid Build Coastguard Worker static void rb_print_stats(ext2fs_generic_bitmap_64 bitmap EXT2FS_ATTR((unused)))
976*6a54128fSAndroid Build Coastguard Worker {
977*6a54128fSAndroid Build Coastguard Worker }
978*6a54128fSAndroid Build Coastguard Worker #endif
979*6a54128fSAndroid Build Coastguard Worker 
980*6a54128fSAndroid Build Coastguard Worker struct ext2_bitmap_ops ext2fs_blkmap64_rbtree = {
981*6a54128fSAndroid Build Coastguard Worker 	.type = EXT2FS_BMAP64_RBTREE,
982*6a54128fSAndroid Build Coastguard Worker 	.new_bmap = rb_new_bmap,
983*6a54128fSAndroid Build Coastguard Worker 	.free_bmap = rb_free_bmap,
984*6a54128fSAndroid Build Coastguard Worker 	.copy_bmap = rb_copy_bmap,
985*6a54128fSAndroid Build Coastguard Worker 	.resize_bmap = rb_resize_bmap,
986*6a54128fSAndroid Build Coastguard Worker 	.mark_bmap = rb_mark_bmap,
987*6a54128fSAndroid Build Coastguard Worker 	.unmark_bmap = rb_unmark_bmap,
988*6a54128fSAndroid Build Coastguard Worker 	.test_bmap = rb_test_bmap,
989*6a54128fSAndroid Build Coastguard Worker 	.test_clear_bmap_extent = rb_test_clear_bmap_extent,
990*6a54128fSAndroid Build Coastguard Worker 	.mark_bmap_extent = rb_mark_bmap_extent,
991*6a54128fSAndroid Build Coastguard Worker 	.unmark_bmap_extent = rb_unmark_bmap_extent,
992*6a54128fSAndroid Build Coastguard Worker 	.set_bmap_range = rb_set_bmap_range,
993*6a54128fSAndroid Build Coastguard Worker 	.get_bmap_range = rb_get_bmap_range,
994*6a54128fSAndroid Build Coastguard Worker 	.clear_bmap = rb_clear_bmap,
995*6a54128fSAndroid Build Coastguard Worker 	.print_stats = rb_print_stats,
996*6a54128fSAndroid Build Coastguard Worker 	.find_first_zero = rb_find_first_zero,
997*6a54128fSAndroid Build Coastguard Worker 	.find_first_set = rb_find_first_set,
998*6a54128fSAndroid Build Coastguard Worker };
999