xref: /aosp_15_r20/external/e2fsprogs/lib/ext2fs/blkmap64_ba.c (revision 6a54128f25917bfc36a8a6e9d722c04a0b4641b6)
1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker  * blkmap64_ba.c --- Simple bitarray implementation for bitmaps
3*6a54128fSAndroid Build Coastguard Worker  *
4*6a54128fSAndroid Build Coastguard Worker  * Copyright (C) 2008 Theodore Ts'o.
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 
27*6a54128fSAndroid Build Coastguard Worker #include "ext2_fs.h"
28*6a54128fSAndroid Build Coastguard Worker #include "ext2fsP.h"
29*6a54128fSAndroid Build Coastguard Worker #include "bmap64.h"
30*6a54128fSAndroid Build Coastguard Worker 
31*6a54128fSAndroid Build Coastguard Worker /*
32*6a54128fSAndroid Build Coastguard Worker  * Private data for bit array implementation of bitmap ops.
33*6a54128fSAndroid Build Coastguard Worker  * Currently, this is just a pointer to our big flat hunk of memory,
34*6a54128fSAndroid Build Coastguard Worker  * exactly equivalent to the old-skool char * bitmap member.
35*6a54128fSAndroid Build Coastguard Worker  */
36*6a54128fSAndroid Build Coastguard Worker 
37*6a54128fSAndroid Build Coastguard Worker struct ext2fs_ba_private_struct {
38*6a54128fSAndroid Build Coastguard Worker 	char *bitarray;
39*6a54128fSAndroid Build Coastguard Worker };
40*6a54128fSAndroid Build Coastguard Worker 
41*6a54128fSAndroid Build Coastguard Worker typedef struct ext2fs_ba_private_struct *ext2fs_ba_private;
42*6a54128fSAndroid Build Coastguard Worker 
ba_alloc_private_data(ext2fs_generic_bitmap_64 bitmap)43*6a54128fSAndroid Build Coastguard Worker static errcode_t ba_alloc_private_data (ext2fs_generic_bitmap_64 bitmap)
44*6a54128fSAndroid Build Coastguard Worker {
45*6a54128fSAndroid Build Coastguard Worker 	ext2fs_ba_private bp;
46*6a54128fSAndroid Build Coastguard Worker 	errcode_t	retval;
47*6a54128fSAndroid Build Coastguard Worker 	size_t		size;
48*6a54128fSAndroid Build Coastguard Worker 
49*6a54128fSAndroid Build Coastguard Worker 	/*
50*6a54128fSAndroid Build Coastguard Worker 	 * Since we only have the one pointer, we could just shove our
51*6a54128fSAndroid Build Coastguard Worker 	 * private data in the void *private field itself, but then
52*6a54128fSAndroid Build Coastguard Worker 	 * we'd have to do a fair bit of rewriting if we ever added a
53*6a54128fSAndroid Build Coastguard Worker 	 * field.  I'm agnostic.
54*6a54128fSAndroid Build Coastguard Worker 	 */
55*6a54128fSAndroid Build Coastguard Worker 	retval = ext2fs_get_mem(sizeof (ext2fs_ba_private), &bp);
56*6a54128fSAndroid Build Coastguard Worker 	if (retval)
57*6a54128fSAndroid Build Coastguard Worker 		return retval;
58*6a54128fSAndroid Build Coastguard Worker 
59*6a54128fSAndroid Build Coastguard Worker 	size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1);
60*6a54128fSAndroid Build Coastguard Worker 
61*6a54128fSAndroid Build Coastguard Worker 	retval = ext2fs_get_mem(size, &bp->bitarray);
62*6a54128fSAndroid Build Coastguard Worker 	if (retval) {
63*6a54128fSAndroid Build Coastguard Worker 		ext2fs_free_mem(&bp);
64*6a54128fSAndroid Build Coastguard Worker 		bp = 0;
65*6a54128fSAndroid Build Coastguard Worker 		return retval;
66*6a54128fSAndroid Build Coastguard Worker 	}
67*6a54128fSAndroid Build Coastguard Worker 	bitmap->private = (void *) bp;
68*6a54128fSAndroid Build Coastguard Worker 	return 0;
69*6a54128fSAndroid Build Coastguard Worker }
70*6a54128fSAndroid Build Coastguard Worker 
ba_new_bmap(ext2_filsys fs EXT2FS_ATTR ((unused)),ext2fs_generic_bitmap_64 bitmap)71*6a54128fSAndroid Build Coastguard Worker static errcode_t ba_new_bmap(ext2_filsys fs EXT2FS_ATTR((unused)),
72*6a54128fSAndroid Build Coastguard Worker 			     ext2fs_generic_bitmap_64 bitmap)
73*6a54128fSAndroid Build Coastguard Worker {
74*6a54128fSAndroid Build Coastguard Worker 	ext2fs_ba_private bp;
75*6a54128fSAndroid Build Coastguard Worker 	errcode_t	retval;
76*6a54128fSAndroid Build Coastguard Worker 	size_t		size;
77*6a54128fSAndroid Build Coastguard Worker 
78*6a54128fSAndroid Build Coastguard Worker 	retval = ba_alloc_private_data (bitmap);
79*6a54128fSAndroid Build Coastguard Worker 	if (retval)
80*6a54128fSAndroid Build Coastguard Worker 		return retval;
81*6a54128fSAndroid Build Coastguard Worker 
82*6a54128fSAndroid Build Coastguard Worker 	bp = (ext2fs_ba_private) bitmap->private;
83*6a54128fSAndroid Build Coastguard Worker 	size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1);
84*6a54128fSAndroid Build Coastguard Worker 	memset(bp->bitarray, 0, size);
85*6a54128fSAndroid Build Coastguard Worker 
86*6a54128fSAndroid Build Coastguard Worker 	return 0;
87*6a54128fSAndroid Build Coastguard Worker }
88*6a54128fSAndroid Build Coastguard Worker 
ba_free_bmap(ext2fs_generic_bitmap_64 bitmap)89*6a54128fSAndroid Build Coastguard Worker static void ba_free_bmap(ext2fs_generic_bitmap_64 bitmap)
90*6a54128fSAndroid Build Coastguard Worker {
91*6a54128fSAndroid Build Coastguard Worker 	ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
92*6a54128fSAndroid Build Coastguard Worker 
93*6a54128fSAndroid Build Coastguard Worker 	if (!bp)
94*6a54128fSAndroid Build Coastguard Worker 		return;
95*6a54128fSAndroid Build Coastguard Worker 
96*6a54128fSAndroid Build Coastguard Worker 	if (bp->bitarray) {
97*6a54128fSAndroid Build Coastguard Worker 		ext2fs_free_mem (&bp->bitarray);
98*6a54128fSAndroid Build Coastguard Worker 		bp->bitarray = 0;
99*6a54128fSAndroid Build Coastguard Worker 	}
100*6a54128fSAndroid Build Coastguard Worker 	ext2fs_free_mem (&bp);
101*6a54128fSAndroid Build Coastguard Worker 	bp = 0;
102*6a54128fSAndroid Build Coastguard Worker }
103*6a54128fSAndroid Build Coastguard Worker 
ba_copy_bmap(ext2fs_generic_bitmap_64 src,ext2fs_generic_bitmap_64 dest)104*6a54128fSAndroid Build Coastguard Worker static errcode_t ba_copy_bmap(ext2fs_generic_bitmap_64 src,
105*6a54128fSAndroid Build Coastguard Worker 			      ext2fs_generic_bitmap_64 dest)
106*6a54128fSAndroid Build Coastguard Worker {
107*6a54128fSAndroid Build Coastguard Worker 	ext2fs_ba_private src_bp = (ext2fs_ba_private) src->private;
108*6a54128fSAndroid Build Coastguard Worker 	ext2fs_ba_private dest_bp;
109*6a54128fSAndroid Build Coastguard Worker 	errcode_t retval;
110*6a54128fSAndroid Build Coastguard Worker 	size_t size;
111*6a54128fSAndroid Build Coastguard Worker 
112*6a54128fSAndroid Build Coastguard Worker 	retval = ba_alloc_private_data (dest);
113*6a54128fSAndroid Build Coastguard Worker 	if (retval)
114*6a54128fSAndroid Build Coastguard Worker 		return retval;
115*6a54128fSAndroid Build Coastguard Worker 
116*6a54128fSAndroid Build Coastguard Worker 	dest_bp = (ext2fs_ba_private) dest->private;
117*6a54128fSAndroid Build Coastguard Worker 
118*6a54128fSAndroid Build Coastguard Worker 	size = (size_t) (((src->real_end - src->start) / 8) + 1);
119*6a54128fSAndroid Build Coastguard Worker 	memcpy (dest_bp->bitarray, src_bp->bitarray, size);
120*6a54128fSAndroid Build Coastguard Worker 
121*6a54128fSAndroid Build Coastguard Worker 	return 0;
122*6a54128fSAndroid Build Coastguard Worker }
123*6a54128fSAndroid Build Coastguard Worker 
ba_resize_bmap(ext2fs_generic_bitmap_64 bmap,__u64 new_end,__u64 new_real_end)124*6a54128fSAndroid Build Coastguard Worker static errcode_t ba_resize_bmap(ext2fs_generic_bitmap_64 bmap,
125*6a54128fSAndroid Build Coastguard Worker 				__u64 new_end, __u64 new_real_end)
126*6a54128fSAndroid Build Coastguard Worker {
127*6a54128fSAndroid Build Coastguard Worker 	ext2fs_ba_private bp = (ext2fs_ba_private) bmap->private;
128*6a54128fSAndroid Build Coastguard Worker 	errcode_t	retval;
129*6a54128fSAndroid Build Coastguard Worker 	size_t		size, new_size;
130*6a54128fSAndroid Build Coastguard Worker 	__u64		bitno;
131*6a54128fSAndroid Build Coastguard Worker 
132*6a54128fSAndroid Build Coastguard Worker 	/*
133*6a54128fSAndroid Build Coastguard Worker 	 * If we're expanding the bitmap, make sure all of the new
134*6a54128fSAndroid Build Coastguard Worker 	 * parts of the bitmap are zero.
135*6a54128fSAndroid Build Coastguard Worker 	 */
136*6a54128fSAndroid Build Coastguard Worker 	if (new_end > bmap->end) {
137*6a54128fSAndroid Build Coastguard Worker 		bitno = bmap->real_end;
138*6a54128fSAndroid Build Coastguard Worker 		if (bitno > new_end)
139*6a54128fSAndroid Build Coastguard Worker 			bitno = new_end;
140*6a54128fSAndroid Build Coastguard Worker 		for (; bitno > bmap->end; bitno--)
141*6a54128fSAndroid Build Coastguard Worker 			ext2fs_clear_bit64(bitno - bmap->start, bp->bitarray);
142*6a54128fSAndroid Build Coastguard Worker 	}
143*6a54128fSAndroid Build Coastguard Worker 	if (new_real_end == bmap->real_end) {
144*6a54128fSAndroid Build Coastguard Worker 		bmap->end = new_end;
145*6a54128fSAndroid Build Coastguard Worker 		return 0;
146*6a54128fSAndroid Build Coastguard Worker 	}
147*6a54128fSAndroid Build Coastguard Worker 
148*6a54128fSAndroid Build Coastguard Worker 	size = ((bmap->real_end - bmap->start) / 8) + 1;
149*6a54128fSAndroid Build Coastguard Worker 	new_size = ((new_real_end - bmap->start) / 8) + 1;
150*6a54128fSAndroid Build Coastguard Worker 
151*6a54128fSAndroid Build Coastguard Worker 	if (size != new_size) {
152*6a54128fSAndroid Build Coastguard Worker 		retval = ext2fs_resize_mem(size, new_size, &bp->bitarray);
153*6a54128fSAndroid Build Coastguard Worker 		if (retval)
154*6a54128fSAndroid Build Coastguard Worker 			return retval;
155*6a54128fSAndroid Build Coastguard Worker 	}
156*6a54128fSAndroid Build Coastguard Worker 	if (new_size > size)
157*6a54128fSAndroid Build Coastguard Worker 		memset(bp->bitarray + size, 0, new_size - size);
158*6a54128fSAndroid Build Coastguard Worker 
159*6a54128fSAndroid Build Coastguard Worker 	bmap->end = new_end;
160*6a54128fSAndroid Build Coastguard Worker 	bmap->real_end = new_real_end;
161*6a54128fSAndroid Build Coastguard Worker 	return 0;
162*6a54128fSAndroid Build Coastguard Worker 
163*6a54128fSAndroid Build Coastguard Worker }
164*6a54128fSAndroid Build Coastguard Worker 
ba_mark_bmap(ext2fs_generic_bitmap_64 bitmap,__u64 arg)165*6a54128fSAndroid Build Coastguard Worker static int ba_mark_bmap(ext2fs_generic_bitmap_64 bitmap, __u64 arg)
166*6a54128fSAndroid Build Coastguard Worker {
167*6a54128fSAndroid Build Coastguard Worker 	ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
168*6a54128fSAndroid Build Coastguard Worker 	blk64_t bitno = (blk64_t) arg;
169*6a54128fSAndroid Build Coastguard Worker 
170*6a54128fSAndroid Build Coastguard Worker 	return ext2fs_set_bit64(bitno - bitmap->start, bp->bitarray);
171*6a54128fSAndroid Build Coastguard Worker }
172*6a54128fSAndroid Build Coastguard Worker 
ba_unmark_bmap(ext2fs_generic_bitmap_64 bitmap,__u64 arg)173*6a54128fSAndroid Build Coastguard Worker static int ba_unmark_bmap(ext2fs_generic_bitmap_64 bitmap, __u64 arg)
174*6a54128fSAndroid Build Coastguard Worker {
175*6a54128fSAndroid Build Coastguard Worker 	ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
176*6a54128fSAndroid Build Coastguard Worker 	blk64_t bitno = (blk64_t) arg;
177*6a54128fSAndroid Build Coastguard Worker 
178*6a54128fSAndroid Build Coastguard Worker 	return ext2fs_clear_bit64(bitno - bitmap->start, bp->bitarray);
179*6a54128fSAndroid Build Coastguard Worker }
180*6a54128fSAndroid Build Coastguard Worker 
ba_test_bmap(ext2fs_generic_bitmap_64 bitmap,__u64 arg)181*6a54128fSAndroid Build Coastguard Worker static int ba_test_bmap(ext2fs_generic_bitmap_64 bitmap, __u64 arg)
182*6a54128fSAndroid Build Coastguard Worker {
183*6a54128fSAndroid Build Coastguard Worker 	ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
184*6a54128fSAndroid Build Coastguard Worker 	blk64_t bitno = (blk64_t) arg;
185*6a54128fSAndroid Build Coastguard Worker 
186*6a54128fSAndroid Build Coastguard Worker 	return ext2fs_test_bit64(bitno - bitmap->start, bp->bitarray);
187*6a54128fSAndroid Build Coastguard Worker }
188*6a54128fSAndroid Build Coastguard Worker 
ba_mark_bmap_extent(ext2fs_generic_bitmap_64 bitmap,__u64 arg,unsigned int num)189*6a54128fSAndroid Build Coastguard Worker static void ba_mark_bmap_extent(ext2fs_generic_bitmap_64 bitmap, __u64 arg,
190*6a54128fSAndroid Build Coastguard Worker 				unsigned int num)
191*6a54128fSAndroid Build Coastguard Worker {
192*6a54128fSAndroid Build Coastguard Worker 	ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
193*6a54128fSAndroid Build Coastguard Worker 	blk64_t bitno = (blk64_t) arg;
194*6a54128fSAndroid Build Coastguard Worker 	unsigned int i;
195*6a54128fSAndroid Build Coastguard Worker 
196*6a54128fSAndroid Build Coastguard Worker 	for (i = 0; i < num; i++)
197*6a54128fSAndroid Build Coastguard Worker 		ext2fs_fast_set_bit64(bitno + i - bitmap->start, bp->bitarray);
198*6a54128fSAndroid Build Coastguard Worker }
199*6a54128fSAndroid Build Coastguard Worker 
ba_unmark_bmap_extent(ext2fs_generic_bitmap_64 bitmap,__u64 arg,unsigned int num)200*6a54128fSAndroid Build Coastguard Worker static void ba_unmark_bmap_extent(ext2fs_generic_bitmap_64 bitmap, __u64 arg,
201*6a54128fSAndroid Build Coastguard Worker 				  unsigned int num)
202*6a54128fSAndroid Build Coastguard Worker {
203*6a54128fSAndroid Build Coastguard Worker 	ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
204*6a54128fSAndroid Build Coastguard Worker 	blk64_t bitno = (blk64_t) arg;
205*6a54128fSAndroid Build Coastguard Worker 	unsigned int i;
206*6a54128fSAndroid Build Coastguard Worker 
207*6a54128fSAndroid Build Coastguard Worker 	for (i = 0; i < num; i++)
208*6a54128fSAndroid Build Coastguard Worker 		ext2fs_fast_clear_bit64(bitno + i - bitmap->start, bp->bitarray);
209*6a54128fSAndroid Build Coastguard Worker }
210*6a54128fSAndroid Build Coastguard Worker 
ba_test_clear_bmap_extent(ext2fs_generic_bitmap_64 bitmap,__u64 start,unsigned int len)211*6a54128fSAndroid Build Coastguard Worker static int ba_test_clear_bmap_extent(ext2fs_generic_bitmap_64 bitmap,
212*6a54128fSAndroid Build Coastguard Worker 				     __u64 start, unsigned int len)
213*6a54128fSAndroid Build Coastguard Worker {
214*6a54128fSAndroid Build Coastguard Worker 	ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
215*6a54128fSAndroid Build Coastguard Worker 	__u64 start_byte, len_byte = len >> 3;
216*6a54128fSAndroid Build Coastguard Worker 	unsigned int start_bit, len_bit = len % 8;
217*6a54128fSAndroid Build Coastguard Worker 	unsigned int first_bit = 0;
218*6a54128fSAndroid Build Coastguard Worker 	unsigned int last_bit  = 0;
219*6a54128fSAndroid Build Coastguard Worker 	int mark_count = 0;
220*6a54128fSAndroid Build Coastguard Worker 	int mark_bit = 0;
221*6a54128fSAndroid Build Coastguard Worker 	int i;
222*6a54128fSAndroid Build Coastguard Worker 	const char *ADDR;
223*6a54128fSAndroid Build Coastguard Worker 
224*6a54128fSAndroid Build Coastguard Worker 	ADDR = bp->bitarray;
225*6a54128fSAndroid Build Coastguard Worker 	start -= bitmap->start;
226*6a54128fSAndroid Build Coastguard Worker 	start_byte = start >> 3;
227*6a54128fSAndroid Build Coastguard Worker 	start_bit = start % 8;
228*6a54128fSAndroid Build Coastguard Worker 
229*6a54128fSAndroid Build Coastguard Worker 	if (start_bit != 0) {
230*6a54128fSAndroid Build Coastguard Worker 		/*
231*6a54128fSAndroid Build Coastguard Worker 		 * The compared start block number or start inode number
232*6a54128fSAndroid Build Coastguard Worker 		 * is not the first bit in a byte.
233*6a54128fSAndroid Build Coastguard Worker 		 */
234*6a54128fSAndroid Build Coastguard Worker 		mark_count = 8 - start_bit;
235*6a54128fSAndroid Build Coastguard Worker 		if (len < 8 - start_bit) {
236*6a54128fSAndroid Build Coastguard Worker 			mark_count = (int)len;
237*6a54128fSAndroid Build Coastguard Worker 			mark_bit = len + start_bit - 1;
238*6a54128fSAndroid Build Coastguard Worker 		} else
239*6a54128fSAndroid Build Coastguard Worker 			mark_bit = 7;
240*6a54128fSAndroid Build Coastguard Worker 
241*6a54128fSAndroid Build Coastguard Worker 		for (i = mark_count; i > 0; i--, mark_bit--)
242*6a54128fSAndroid Build Coastguard Worker 			first_bit |= 1 << mark_bit;
243*6a54128fSAndroid Build Coastguard Worker 
244*6a54128fSAndroid Build Coastguard Worker 		/*
245*6a54128fSAndroid Build Coastguard Worker 		 * Compare blocks or inodes in the first byte.
246*6a54128fSAndroid Build Coastguard Worker 		 * If there is any marked bit, this function returns 0.
247*6a54128fSAndroid Build Coastguard Worker 		 */
248*6a54128fSAndroid Build Coastguard Worker 		if (first_bit & ADDR[start_byte])
249*6a54128fSAndroid Build Coastguard Worker 			return 0;
250*6a54128fSAndroid Build Coastguard Worker 		else if (len <= 8 - start_bit)
251*6a54128fSAndroid Build Coastguard Worker 			return 1;
252*6a54128fSAndroid Build Coastguard Worker 
253*6a54128fSAndroid Build Coastguard Worker 		start_byte++;
254*6a54128fSAndroid Build Coastguard Worker 		len_bit = (len - mark_count) % 8;
255*6a54128fSAndroid Build Coastguard Worker 		len_byte = (len - mark_count) >> 3;
256*6a54128fSAndroid Build Coastguard Worker 	}
257*6a54128fSAndroid Build Coastguard Worker 
258*6a54128fSAndroid Build Coastguard Worker 	/*
259*6a54128fSAndroid Build Coastguard Worker 	 * The compared start block number or start inode number is
260*6a54128fSAndroid Build Coastguard Worker 	 * the first bit in a byte.
261*6a54128fSAndroid Build Coastguard Worker 	 */
262*6a54128fSAndroid Build Coastguard Worker 	if (len_bit != 0) {
263*6a54128fSAndroid Build Coastguard Worker 		/*
264*6a54128fSAndroid Build Coastguard Worker 		 * The compared end block number or end inode number is
265*6a54128fSAndroid Build Coastguard Worker 		 * not the last bit in a byte.
266*6a54128fSAndroid Build Coastguard Worker 		 */
267*6a54128fSAndroid Build Coastguard Worker 		for (mark_bit = len_bit - 1; mark_bit >= 0; mark_bit--)
268*6a54128fSAndroid Build Coastguard Worker 			last_bit |= 1 << mark_bit;
269*6a54128fSAndroid Build Coastguard Worker 
270*6a54128fSAndroid Build Coastguard Worker 		/*
271*6a54128fSAndroid Build Coastguard Worker 		 * Compare blocks or inodes in the last byte.
272*6a54128fSAndroid Build Coastguard Worker 		 * If there is any marked bit, this function returns 0.
273*6a54128fSAndroid Build Coastguard Worker 		 */
274*6a54128fSAndroid Build Coastguard Worker 		if (last_bit & ADDR[start_byte + len_byte])
275*6a54128fSAndroid Build Coastguard Worker 			return 0;
276*6a54128fSAndroid Build Coastguard Worker 		else if (len_byte == 0)
277*6a54128fSAndroid Build Coastguard Worker 			return 1;
278*6a54128fSAndroid Build Coastguard Worker 	}
279*6a54128fSAndroid Build Coastguard Worker 
280*6a54128fSAndroid Build Coastguard Worker 	/* Check whether all bytes are 0 */
281*6a54128fSAndroid Build Coastguard Worker 	return ext2fs_mem_is_zero(ADDR + start_byte, len_byte);
282*6a54128fSAndroid Build Coastguard Worker }
283*6a54128fSAndroid Build Coastguard Worker 
284*6a54128fSAndroid Build Coastguard Worker 
ba_set_bmap_range(ext2fs_generic_bitmap_64 bitmap,__u64 start,size_t num,void * in)285*6a54128fSAndroid Build Coastguard Worker static errcode_t ba_set_bmap_range(ext2fs_generic_bitmap_64 bitmap,
286*6a54128fSAndroid Build Coastguard Worker 				     __u64 start, size_t num, void *in)
287*6a54128fSAndroid Build Coastguard Worker {
288*6a54128fSAndroid Build Coastguard Worker 	ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
289*6a54128fSAndroid Build Coastguard Worker 
290*6a54128fSAndroid Build Coastguard Worker 	memcpy (bp->bitarray + (start >> 3), in, (num + 7) >> 3);
291*6a54128fSAndroid Build Coastguard Worker 
292*6a54128fSAndroid Build Coastguard Worker 	return 0;
293*6a54128fSAndroid Build Coastguard Worker }
294*6a54128fSAndroid Build Coastguard Worker 
ba_get_bmap_range(ext2fs_generic_bitmap_64 bitmap,__u64 start,size_t num,void * out)295*6a54128fSAndroid Build Coastguard Worker static errcode_t ba_get_bmap_range(ext2fs_generic_bitmap_64 bitmap,
296*6a54128fSAndroid Build Coastguard Worker 				     __u64 start, size_t num, void *out)
297*6a54128fSAndroid Build Coastguard Worker {
298*6a54128fSAndroid Build Coastguard Worker 	ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
299*6a54128fSAndroid Build Coastguard Worker 
300*6a54128fSAndroid Build Coastguard Worker 	memcpy (out, bp->bitarray + (start >> 3), (num + 7) >> 3);
301*6a54128fSAndroid Build Coastguard Worker 
302*6a54128fSAndroid Build Coastguard Worker 	return 0;
303*6a54128fSAndroid Build Coastguard Worker }
304*6a54128fSAndroid Build Coastguard Worker 
ba_clear_bmap(ext2fs_generic_bitmap_64 bitmap)305*6a54128fSAndroid Build Coastguard Worker static void ba_clear_bmap(ext2fs_generic_bitmap_64 bitmap)
306*6a54128fSAndroid Build Coastguard Worker {
307*6a54128fSAndroid Build Coastguard Worker 	ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
308*6a54128fSAndroid Build Coastguard Worker 
309*6a54128fSAndroid Build Coastguard Worker 	memset(bp->bitarray, 0,
310*6a54128fSAndroid Build Coastguard Worker 	       (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1));
311*6a54128fSAndroid Build Coastguard Worker }
312*6a54128fSAndroid Build Coastguard Worker 
313*6a54128fSAndroid Build Coastguard Worker #ifdef ENABLE_BMAP_STATS
ba_print_stats(ext2fs_generic_bitmap_64 bitmap)314*6a54128fSAndroid Build Coastguard Worker static void ba_print_stats(ext2fs_generic_bitmap_64 bitmap)
315*6a54128fSAndroid Build Coastguard Worker {
316*6a54128fSAndroid Build Coastguard Worker 	fprintf(stderr, "%16llu Bytes used by bitarray\n", (unsigned long long)
317*6a54128fSAndroid Build Coastguard Worker 		((bitmap->real_end - bitmap->start) >> 3) + 1 +
318*6a54128fSAndroid Build Coastguard Worker 		sizeof(struct ext2fs_ba_private_struct));
319*6a54128fSAndroid Build Coastguard Worker }
320*6a54128fSAndroid Build Coastguard Worker #else
ba_print_stats(ext2fs_generic_bitmap_64 bitmap EXT2FS_ATTR ((unused)))321*6a54128fSAndroid Build Coastguard Worker static void ba_print_stats(ext2fs_generic_bitmap_64 bitmap EXT2FS_ATTR((unused)))
322*6a54128fSAndroid Build Coastguard Worker {
323*6a54128fSAndroid Build Coastguard Worker }
324*6a54128fSAndroid Build Coastguard Worker #endif
325*6a54128fSAndroid Build Coastguard Worker 
326*6a54128fSAndroid Build Coastguard Worker /* Find the first zero bit between start and end, inclusive. */
ba_find_first_zero(ext2fs_generic_bitmap_64 bitmap,__u64 start,__u64 end,__u64 * out)327*6a54128fSAndroid Build Coastguard Worker static errcode_t ba_find_first_zero(ext2fs_generic_bitmap_64 bitmap,
328*6a54128fSAndroid Build Coastguard Worker 				    __u64 start, __u64 end, __u64 *out)
329*6a54128fSAndroid Build Coastguard Worker {
330*6a54128fSAndroid Build Coastguard Worker 	ext2fs_ba_private bp = (ext2fs_ba_private)bitmap->private;
331*6a54128fSAndroid Build Coastguard Worker 	unsigned long bitpos = start - bitmap->start;
332*6a54128fSAndroid Build Coastguard Worker 	unsigned long count = end - start + 1;
333*6a54128fSAndroid Build Coastguard Worker 	int byte_found = 0; /* whether a != 0xff byte has been found */
334*6a54128fSAndroid Build Coastguard Worker 	const unsigned char *pos;
335*6a54128fSAndroid Build Coastguard Worker 	unsigned long max_loop_count, i;
336*6a54128fSAndroid Build Coastguard Worker 
337*6a54128fSAndroid Build Coastguard Worker 	/* scan bits until we hit a byte boundary */
338*6a54128fSAndroid Build Coastguard Worker 	while ((bitpos & 0x7) != 0 && count > 0) {
339*6a54128fSAndroid Build Coastguard Worker 		if (!ext2fs_test_bit64(bitpos, bp->bitarray)) {
340*6a54128fSAndroid Build Coastguard Worker 			*out = bitpos + bitmap->start;
341*6a54128fSAndroid Build Coastguard Worker 			return 0;
342*6a54128fSAndroid Build Coastguard Worker 		}
343*6a54128fSAndroid Build Coastguard Worker 		bitpos++;
344*6a54128fSAndroid Build Coastguard Worker 		count--;
345*6a54128fSAndroid Build Coastguard Worker 	}
346*6a54128fSAndroid Build Coastguard Worker 
347*6a54128fSAndroid Build Coastguard Worker 	if (!count)
348*6a54128fSAndroid Build Coastguard Worker 		return ENOENT;
349*6a54128fSAndroid Build Coastguard Worker 
350*6a54128fSAndroid Build Coastguard Worker 	pos = ((unsigned char *)bp->bitarray) + (bitpos >> 3);
351*6a54128fSAndroid Build Coastguard Worker 	/* scan bytes until 8-byte (64-bit) aligned */
352*6a54128fSAndroid Build Coastguard Worker 	while (count >= 8 && (((uintptr_t)pos) & 0x07)) {
353*6a54128fSAndroid Build Coastguard Worker 		if (*pos != 0xff) {
354*6a54128fSAndroid Build Coastguard Worker 			byte_found = 1;
355*6a54128fSAndroid Build Coastguard Worker 			break;
356*6a54128fSAndroid Build Coastguard Worker 		}
357*6a54128fSAndroid Build Coastguard Worker 		pos++;
358*6a54128fSAndroid Build Coastguard Worker 		count -= 8;
359*6a54128fSAndroid Build Coastguard Worker 		bitpos += 8;
360*6a54128fSAndroid Build Coastguard Worker 	}
361*6a54128fSAndroid Build Coastguard Worker 
362*6a54128fSAndroid Build Coastguard Worker 	if (!byte_found) {
363*6a54128fSAndroid Build Coastguard Worker 		max_loop_count = count >> 6; /* 8-byte blocks */
364*6a54128fSAndroid Build Coastguard Worker 		i = max_loop_count;
365*6a54128fSAndroid Build Coastguard Worker 		while (i) {
366*6a54128fSAndroid Build Coastguard Worker 			if (*((const __u64 *)pos) != ((__u64)-1))
367*6a54128fSAndroid Build Coastguard Worker 				break;
368*6a54128fSAndroid Build Coastguard Worker 			pos += 8;
369*6a54128fSAndroid Build Coastguard Worker 			i--;
370*6a54128fSAndroid Build Coastguard Worker 		}
371*6a54128fSAndroid Build Coastguard Worker 		count -= 64 * (max_loop_count - i);
372*6a54128fSAndroid Build Coastguard Worker 		bitpos += 64 * (max_loop_count - i);
373*6a54128fSAndroid Build Coastguard Worker 
374*6a54128fSAndroid Build Coastguard Worker 		max_loop_count = count >> 3;
375*6a54128fSAndroid Build Coastguard Worker 		i = max_loop_count;
376*6a54128fSAndroid Build Coastguard Worker 		while (i) {
377*6a54128fSAndroid Build Coastguard Worker 			if (*pos != 0xff) {
378*6a54128fSAndroid Build Coastguard Worker 				byte_found = 1;
379*6a54128fSAndroid Build Coastguard Worker 				break;
380*6a54128fSAndroid Build Coastguard Worker 			}
381*6a54128fSAndroid Build Coastguard Worker 			pos++;
382*6a54128fSAndroid Build Coastguard Worker 			i--;
383*6a54128fSAndroid Build Coastguard Worker 		}
384*6a54128fSAndroid Build Coastguard Worker 		count -= 8 * (max_loop_count - i);
385*6a54128fSAndroid Build Coastguard Worker 		bitpos += 8 * (max_loop_count - i);
386*6a54128fSAndroid Build Coastguard Worker 	}
387*6a54128fSAndroid Build Coastguard Worker 
388*6a54128fSAndroid Build Coastguard Worker 	/* Here either count < 8 or byte_found == 1. */
389*6a54128fSAndroid Build Coastguard Worker 	while (count-- > 0) {
390*6a54128fSAndroid Build Coastguard Worker 		if (!ext2fs_test_bit64(bitpos, bp->bitarray)) {
391*6a54128fSAndroid Build Coastguard Worker 			*out = bitpos + bitmap->start;
392*6a54128fSAndroid Build Coastguard Worker 			return 0;
393*6a54128fSAndroid Build Coastguard Worker 		}
394*6a54128fSAndroid Build Coastguard Worker 		bitpos++;
395*6a54128fSAndroid Build Coastguard Worker 	}
396*6a54128fSAndroid Build Coastguard Worker 
397*6a54128fSAndroid Build Coastguard Worker 	return ENOENT;
398*6a54128fSAndroid Build Coastguard Worker }
399*6a54128fSAndroid Build Coastguard Worker 
400*6a54128fSAndroid Build Coastguard Worker /* Find the first one bit between start and end, inclusive. */
ba_find_first_set(ext2fs_generic_bitmap_64 bitmap,__u64 start,__u64 end,__u64 * out)401*6a54128fSAndroid Build Coastguard Worker static errcode_t ba_find_first_set(ext2fs_generic_bitmap_64 bitmap,
402*6a54128fSAndroid Build Coastguard Worker 				    __u64 start, __u64 end, __u64 *out)
403*6a54128fSAndroid Build Coastguard Worker {
404*6a54128fSAndroid Build Coastguard Worker 	ext2fs_ba_private bp = (ext2fs_ba_private)bitmap->private;
405*6a54128fSAndroid Build Coastguard Worker 	unsigned long bitpos = start - bitmap->start;
406*6a54128fSAndroid Build Coastguard Worker 	unsigned long count = end - start + 1;
407*6a54128fSAndroid Build Coastguard Worker 	int byte_found = 0; /* whether a != 0xff byte has been found */
408*6a54128fSAndroid Build Coastguard Worker 	const unsigned char *pos;
409*6a54128fSAndroid Build Coastguard Worker 	unsigned long max_loop_count, i;
410*6a54128fSAndroid Build Coastguard Worker 
411*6a54128fSAndroid Build Coastguard Worker 	/* scan bits until we hit a byte boundary */
412*6a54128fSAndroid Build Coastguard Worker 	while ((bitpos & 0x7) != 0 && count > 0) {
413*6a54128fSAndroid Build Coastguard Worker 		if (ext2fs_test_bit64(bitpos, bp->bitarray)) {
414*6a54128fSAndroid Build Coastguard Worker 			*out = bitpos + bitmap->start;
415*6a54128fSAndroid Build Coastguard Worker 			return 0;
416*6a54128fSAndroid Build Coastguard Worker 		}
417*6a54128fSAndroid Build Coastguard Worker 		bitpos++;
418*6a54128fSAndroid Build Coastguard Worker 		count--;
419*6a54128fSAndroid Build Coastguard Worker 	}
420*6a54128fSAndroid Build Coastguard Worker 
421*6a54128fSAndroid Build Coastguard Worker 	if (!count)
422*6a54128fSAndroid Build Coastguard Worker 		return ENOENT;
423*6a54128fSAndroid Build Coastguard Worker 
424*6a54128fSAndroid Build Coastguard Worker 	pos = ((unsigned char *)bp->bitarray) + (bitpos >> 3);
425*6a54128fSAndroid Build Coastguard Worker 	/* scan bytes until 8-byte (64-bit) aligned */
426*6a54128fSAndroid Build Coastguard Worker 	while (count >= 8 && (((uintptr_t)pos) & 0x07)) {
427*6a54128fSAndroid Build Coastguard Worker 		if (*pos != 0) {
428*6a54128fSAndroid Build Coastguard Worker 			byte_found = 1;
429*6a54128fSAndroid Build Coastguard Worker 			break;
430*6a54128fSAndroid Build Coastguard Worker 		}
431*6a54128fSAndroid Build Coastguard Worker 		pos++;
432*6a54128fSAndroid Build Coastguard Worker 		count -= 8;
433*6a54128fSAndroid Build Coastguard Worker 		bitpos += 8;
434*6a54128fSAndroid Build Coastguard Worker 	}
435*6a54128fSAndroid Build Coastguard Worker 
436*6a54128fSAndroid Build Coastguard Worker 	if (!byte_found) {
437*6a54128fSAndroid Build Coastguard Worker 		max_loop_count = count >> 6; /* 8-byte blocks */
438*6a54128fSAndroid Build Coastguard Worker 		i = max_loop_count;
439*6a54128fSAndroid Build Coastguard Worker 		while (i) {
440*6a54128fSAndroid Build Coastguard Worker 			if (*((const __u64 *)pos) != 0)
441*6a54128fSAndroid Build Coastguard Worker 				break;
442*6a54128fSAndroid Build Coastguard Worker 			pos += 8;
443*6a54128fSAndroid Build Coastguard Worker 			i--;
444*6a54128fSAndroid Build Coastguard Worker 		}
445*6a54128fSAndroid Build Coastguard Worker 		count -= 64 * (max_loop_count - i);
446*6a54128fSAndroid Build Coastguard Worker 		bitpos += 64 * (max_loop_count - i);
447*6a54128fSAndroid Build Coastguard Worker 
448*6a54128fSAndroid Build Coastguard Worker 		max_loop_count = count >> 3;
449*6a54128fSAndroid Build Coastguard Worker 		i = max_loop_count;
450*6a54128fSAndroid Build Coastguard Worker 		while (i) {
451*6a54128fSAndroid Build Coastguard Worker 			if (*pos != 0) {
452*6a54128fSAndroid Build Coastguard Worker 				byte_found = 1;
453*6a54128fSAndroid Build Coastguard Worker 				break;
454*6a54128fSAndroid Build Coastguard Worker 			}
455*6a54128fSAndroid Build Coastguard Worker 			pos++;
456*6a54128fSAndroid Build Coastguard Worker 			i--;
457*6a54128fSAndroid Build Coastguard Worker 		}
458*6a54128fSAndroid Build Coastguard Worker 		count -= 8 * (max_loop_count - i);
459*6a54128fSAndroid Build Coastguard Worker 		bitpos += 8 * (max_loop_count - i);
460*6a54128fSAndroid Build Coastguard Worker 	}
461*6a54128fSAndroid Build Coastguard Worker 
462*6a54128fSAndroid Build Coastguard Worker 	/* Here either count < 8 or byte_found == 1. */
463*6a54128fSAndroid Build Coastguard Worker 	while (count-- > 0) {
464*6a54128fSAndroid Build Coastguard Worker 		if (ext2fs_test_bit64(bitpos, bp->bitarray)) {
465*6a54128fSAndroid Build Coastguard Worker 			*out = bitpos + bitmap->start;
466*6a54128fSAndroid Build Coastguard Worker 			return 0;
467*6a54128fSAndroid Build Coastguard Worker 		}
468*6a54128fSAndroid Build Coastguard Worker 		bitpos++;
469*6a54128fSAndroid Build Coastguard Worker 	}
470*6a54128fSAndroid Build Coastguard Worker 
471*6a54128fSAndroid Build Coastguard Worker 	return ENOENT;
472*6a54128fSAndroid Build Coastguard Worker }
473*6a54128fSAndroid Build Coastguard Worker 
474*6a54128fSAndroid Build Coastguard Worker struct ext2_bitmap_ops ext2fs_blkmap64_bitarray = {
475*6a54128fSAndroid Build Coastguard Worker 	.type = EXT2FS_BMAP64_BITARRAY,
476*6a54128fSAndroid Build Coastguard Worker 	.new_bmap = ba_new_bmap,
477*6a54128fSAndroid Build Coastguard Worker 	.free_bmap = ba_free_bmap,
478*6a54128fSAndroid Build Coastguard Worker 	.copy_bmap = ba_copy_bmap,
479*6a54128fSAndroid Build Coastguard Worker 	.resize_bmap = ba_resize_bmap,
480*6a54128fSAndroid Build Coastguard Worker 	.mark_bmap = ba_mark_bmap,
481*6a54128fSAndroid Build Coastguard Worker 	.unmark_bmap = ba_unmark_bmap,
482*6a54128fSAndroid Build Coastguard Worker 	.test_bmap = ba_test_bmap,
483*6a54128fSAndroid Build Coastguard Worker 	.test_clear_bmap_extent = ba_test_clear_bmap_extent,
484*6a54128fSAndroid Build Coastguard Worker 	.mark_bmap_extent = ba_mark_bmap_extent,
485*6a54128fSAndroid Build Coastguard Worker 	.unmark_bmap_extent = ba_unmark_bmap_extent,
486*6a54128fSAndroid Build Coastguard Worker 	.set_bmap_range = ba_set_bmap_range,
487*6a54128fSAndroid Build Coastguard Worker 	.get_bmap_range = ba_get_bmap_range,
488*6a54128fSAndroid Build Coastguard Worker 	.clear_bmap = ba_clear_bmap,
489*6a54128fSAndroid Build Coastguard Worker 	.print_stats = ba_print_stats,
490*6a54128fSAndroid Build Coastguard Worker 	.find_first_zero = ba_find_first_zero,
491*6a54128fSAndroid Build Coastguard Worker 	.find_first_set = ba_find_first_set
492*6a54128fSAndroid Build Coastguard Worker };
493