xref: /aosp_15_r20/external/e2fsprogs/lib/ext2fs/gen_bitmap64.c (revision 6a54128f25917bfc36a8a6e9d722c04a0b4641b6)
1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker  * gen_bitmap64.c --- routines to read, write, and manipulate the new qinode and
3*6a54128fSAndroid Build Coastguard Worker  * block bitmaps.
4*6a54128fSAndroid Build Coastguard Worker  *
5*6a54128fSAndroid Build Coastguard Worker  * Copyright (C) 2007, 2008 Theodore Ts'o.
6*6a54128fSAndroid Build Coastguard Worker  *
7*6a54128fSAndroid Build Coastguard Worker  * %Begin-Header%
8*6a54128fSAndroid Build Coastguard Worker  * This file may be redistributed under the terms of the GNU Public
9*6a54128fSAndroid Build Coastguard Worker  * License.
10*6a54128fSAndroid Build Coastguard Worker  * %End-Header%
11*6a54128fSAndroid Build Coastguard Worker  */
12*6a54128fSAndroid Build Coastguard Worker 
13*6a54128fSAndroid Build Coastguard Worker #include "config.h"
14*6a54128fSAndroid Build Coastguard Worker #include <stdio.h>
15*6a54128fSAndroid Build Coastguard Worker #include <string.h>
16*6a54128fSAndroid Build Coastguard Worker #if HAVE_UNISTD_H
17*6a54128fSAndroid Build Coastguard Worker #include <unistd.h>
18*6a54128fSAndroid Build Coastguard Worker #endif
19*6a54128fSAndroid Build Coastguard Worker #include <fcntl.h>
20*6a54128fSAndroid Build Coastguard Worker #include <time.h>
21*6a54128fSAndroid Build Coastguard Worker #include <errno.h>
22*6a54128fSAndroid Build Coastguard Worker #if HAVE_SYS_STAT_H
23*6a54128fSAndroid Build Coastguard Worker #include <sys/stat.h>
24*6a54128fSAndroid Build Coastguard Worker #endif
25*6a54128fSAndroid Build Coastguard Worker #if HAVE_SYS_TYPES_H
26*6a54128fSAndroid Build Coastguard Worker #include <sys/types.h>
27*6a54128fSAndroid Build Coastguard Worker #endif
28*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_SYS_TIME_H
29*6a54128fSAndroid Build Coastguard Worker #include <sys/time.h>
30*6a54128fSAndroid Build Coastguard Worker #endif
31*6a54128fSAndroid Build Coastguard Worker 
32*6a54128fSAndroid Build Coastguard Worker #include "ext2_fs.h"
33*6a54128fSAndroid Build Coastguard Worker #include "ext2fsP.h"
34*6a54128fSAndroid Build Coastguard Worker #include "bmap64.h"
35*6a54128fSAndroid Build Coastguard Worker 
36*6a54128fSAndroid Build Coastguard Worker /*
37*6a54128fSAndroid Build Coastguard Worker  * Design of 64-bit bitmaps
38*6a54128fSAndroid Build Coastguard Worker  *
39*6a54128fSAndroid Build Coastguard Worker  * In order maintain ABI compatibility with programs that don't
40*6a54128fSAndroid Build Coastguard Worker  * understand about 64-bit blocks/inodes,
41*6a54128fSAndroid Build Coastguard Worker  * ext2fs_allocate_inode_bitmap() and ext2fs_allocate_block_bitmap()
42*6a54128fSAndroid Build Coastguard Worker  * will create old-style bitmaps unless the application passes the
43*6a54128fSAndroid Build Coastguard Worker  * flag EXT2_FLAG_64BITS to ext2fs_open().  If this flag is
44*6a54128fSAndroid Build Coastguard Worker  * passed, then we know the application has been recompiled, so we can
45*6a54128fSAndroid Build Coastguard Worker  * use the new-style bitmaps.  If it is not passed, we have to return
46*6a54128fSAndroid Build Coastguard Worker  * an error if trying to open a filesystem which needs 64-bit bitmaps.
47*6a54128fSAndroid Build Coastguard Worker  *
48*6a54128fSAndroid Build Coastguard Worker  * The new bitmaps use a new set of structure magic numbers, so that
49*6a54128fSAndroid Build Coastguard Worker  * both the old-style and new-style interfaces can identify which
50*6a54128fSAndroid Build Coastguard Worker  * version of the data structure was used.  Both the old-style and
51*6a54128fSAndroid Build Coastguard Worker  * new-style interfaces will support either type of bitmap, although
52*6a54128fSAndroid Build Coastguard Worker  * of course 64-bit operation will only be possible when both the
53*6a54128fSAndroid Build Coastguard Worker  * new-style interface and the new-style bitmap are used.
54*6a54128fSAndroid Build Coastguard Worker  *
55*6a54128fSAndroid Build Coastguard Worker  * For example, the new bitmap interfaces will check the structure
56*6a54128fSAndroid Build Coastguard Worker  * magic numbers and so will be able to detect old-stype bitmap.  If
57*6a54128fSAndroid Build Coastguard Worker  * they see an old-style bitmap, they will pass it to the gen_bitmap.c
58*6a54128fSAndroid Build Coastguard Worker  * functions for handling.  The same will be true for the old
59*6a54128fSAndroid Build Coastguard Worker  * interfaces as well.
60*6a54128fSAndroid Build Coastguard Worker  *
61*6a54128fSAndroid Build Coastguard Worker  * The new-style interfaces will have several different back-end
62*6a54128fSAndroid Build Coastguard Worker  * implementations, so we can support different encodings that are
63*6a54128fSAndroid Build Coastguard Worker  * appropriate for different applications.  In general the default
64*6a54128fSAndroid Build Coastguard Worker  * should be whatever makes sense, and what the application/library
65*6a54128fSAndroid Build Coastguard Worker  * will use.  However, e2fsck may need specialized implementations for
66*6a54128fSAndroid Build Coastguard Worker  * its own uses.  For example, when doing parent directory pointer
67*6a54128fSAndroid Build Coastguard Worker  * loop detections in pass 3, the bitmap will *always* be sparse, so
68*6a54128fSAndroid Build Coastguard Worker  * e2fsck can request an encoding which is optimized for that.
69*6a54128fSAndroid Build Coastguard Worker  */
70*6a54128fSAndroid Build Coastguard Worker 
warn_bitmap(ext2fs_generic_bitmap_64 bitmap,int code,__u64 arg)71*6a54128fSAndroid Build Coastguard Worker static void warn_bitmap(ext2fs_generic_bitmap_64 bitmap,
72*6a54128fSAndroid Build Coastguard Worker 			int code, __u64 arg)
73*6a54128fSAndroid Build Coastguard Worker {
74*6a54128fSAndroid Build Coastguard Worker #ifndef OMIT_COM_ERR
75*6a54128fSAndroid Build Coastguard Worker 	if (bitmap->description)
76*6a54128fSAndroid Build Coastguard Worker 		com_err(0, bitmap->base_error_code+code,
77*6a54128fSAndroid Build Coastguard Worker 			"#%llu for %s", (unsigned long long) arg,
78*6a54128fSAndroid Build Coastguard Worker 			bitmap->description);
79*6a54128fSAndroid Build Coastguard Worker 	else
80*6a54128fSAndroid Build Coastguard Worker 		com_err(0, bitmap->base_error_code + code, "#%llu",
81*6a54128fSAndroid Build Coastguard Worker 			(unsigned long long) arg);
82*6a54128fSAndroid Build Coastguard Worker #endif
83*6a54128fSAndroid Build Coastguard Worker }
84*6a54128fSAndroid Build Coastguard Worker 
85*6a54128fSAndroid Build Coastguard Worker #ifdef ENABLE_BMAP_STATS_OPS
86*6a54128fSAndroid Build Coastguard Worker #define INC_STAT(map, name) map->stats.name
87*6a54128fSAndroid Build Coastguard Worker #else
88*6a54128fSAndroid Build Coastguard Worker #define INC_STAT(map, name) ;;
89*6a54128fSAndroid Build Coastguard Worker #endif
90*6a54128fSAndroid Build Coastguard Worker 
91*6a54128fSAndroid Build Coastguard Worker 
ext2fs_alloc_generic_bmap(ext2_filsys fs,errcode_t magic,int type,__u64 start,__u64 end,__u64 real_end,const char * descr,ext2fs_generic_bitmap * ret)92*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_alloc_generic_bmap(ext2_filsys fs, errcode_t magic,
93*6a54128fSAndroid Build Coastguard Worker 				    int type, __u64 start, __u64 end,
94*6a54128fSAndroid Build Coastguard Worker 				    __u64 real_end,
95*6a54128fSAndroid Build Coastguard Worker 				    const char *descr,
96*6a54128fSAndroid Build Coastguard Worker 				    ext2fs_generic_bitmap *ret)
97*6a54128fSAndroid Build Coastguard Worker {
98*6a54128fSAndroid Build Coastguard Worker 	ext2fs_generic_bitmap_64 bitmap;
99*6a54128fSAndroid Build Coastguard Worker 	struct ext2_bitmap_ops	*ops;
100*6a54128fSAndroid Build Coastguard Worker 	ext2_ino_t num_dirs;
101*6a54128fSAndroid Build Coastguard Worker 	errcode_t retval;
102*6a54128fSAndroid Build Coastguard Worker 
103*6a54128fSAndroid Build Coastguard Worker 	if (!type)
104*6a54128fSAndroid Build Coastguard Worker 		type = EXT2FS_BMAP64_BITARRAY;
105*6a54128fSAndroid Build Coastguard Worker 
106*6a54128fSAndroid Build Coastguard Worker 	switch (type) {
107*6a54128fSAndroid Build Coastguard Worker 	case EXT2FS_BMAP64_BITARRAY:
108*6a54128fSAndroid Build Coastguard Worker 		ops = &ext2fs_blkmap64_bitarray;
109*6a54128fSAndroid Build Coastguard Worker 		break;
110*6a54128fSAndroid Build Coastguard Worker 	case EXT2FS_BMAP64_RBTREE:
111*6a54128fSAndroid Build Coastguard Worker 		ops = &ext2fs_blkmap64_rbtree;
112*6a54128fSAndroid Build Coastguard Worker 		break;
113*6a54128fSAndroid Build Coastguard Worker 	case EXT2FS_BMAP64_AUTODIR:
114*6a54128fSAndroid Build Coastguard Worker 		retval = ext2fs_get_num_dirs(fs, &num_dirs);
115*6a54128fSAndroid Build Coastguard Worker 		if (retval || num_dirs > (fs->super->s_inodes_count / 320))
116*6a54128fSAndroid Build Coastguard Worker 			ops = &ext2fs_blkmap64_bitarray;
117*6a54128fSAndroid Build Coastguard Worker 		else
118*6a54128fSAndroid Build Coastguard Worker 			ops = &ext2fs_blkmap64_rbtree;
119*6a54128fSAndroid Build Coastguard Worker 		break;
120*6a54128fSAndroid Build Coastguard Worker 	default:
121*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
122*6a54128fSAndroid Build Coastguard Worker 	}
123*6a54128fSAndroid Build Coastguard Worker 
124*6a54128fSAndroid Build Coastguard Worker 	retval = ext2fs_get_memzero(sizeof(struct ext2fs_struct_generic_bitmap_64),
125*6a54128fSAndroid Build Coastguard Worker 				    &bitmap);
126*6a54128fSAndroid Build Coastguard Worker 	if (retval)
127*6a54128fSAndroid Build Coastguard Worker 		return retval;
128*6a54128fSAndroid Build Coastguard Worker 
129*6a54128fSAndroid Build Coastguard Worker #ifdef ENABLE_BMAP_STATS
130*6a54128fSAndroid Build Coastguard Worker 	if (gettimeofday(&bitmap->stats.created,
131*6a54128fSAndroid Build Coastguard Worker 			 (struct timezone *) NULL) == -1) {
132*6a54128fSAndroid Build Coastguard Worker 		perror("gettimeofday");
133*6a54128fSAndroid Build Coastguard Worker 		ext2fs_free_mem(&bitmap);
134*6a54128fSAndroid Build Coastguard Worker 		return 1;
135*6a54128fSAndroid Build Coastguard Worker 	}
136*6a54128fSAndroid Build Coastguard Worker 	bitmap->stats.type = type;
137*6a54128fSAndroid Build Coastguard Worker #endif
138*6a54128fSAndroid Build Coastguard Worker 
139*6a54128fSAndroid Build Coastguard Worker 	/* XXX factor out, repeated in copy_bmap */
140*6a54128fSAndroid Build Coastguard Worker 	bitmap->magic = magic;
141*6a54128fSAndroid Build Coastguard Worker 	bitmap->fs = fs;
142*6a54128fSAndroid Build Coastguard Worker 	bitmap->start = start;
143*6a54128fSAndroid Build Coastguard Worker 	bitmap->end = end;
144*6a54128fSAndroid Build Coastguard Worker 	bitmap->real_end = real_end;
145*6a54128fSAndroid Build Coastguard Worker 	bitmap->bitmap_ops = ops;
146*6a54128fSAndroid Build Coastguard Worker 	bitmap->cluster_bits = 0;
147*6a54128fSAndroid Build Coastguard Worker 	switch (magic) {
148*6a54128fSAndroid Build Coastguard Worker 	case EXT2_ET_MAGIC_INODE_BITMAP64:
149*6a54128fSAndroid Build Coastguard Worker 		bitmap->base_error_code = EXT2_ET_BAD_INODE_MARK;
150*6a54128fSAndroid Build Coastguard Worker 		break;
151*6a54128fSAndroid Build Coastguard Worker 	case EXT2_ET_MAGIC_BLOCK_BITMAP64:
152*6a54128fSAndroid Build Coastguard Worker 		bitmap->base_error_code = EXT2_ET_BAD_BLOCK_MARK;
153*6a54128fSAndroid Build Coastguard Worker 		bitmap->cluster_bits = fs->cluster_ratio_bits;
154*6a54128fSAndroid Build Coastguard Worker 		break;
155*6a54128fSAndroid Build Coastguard Worker 	default:
156*6a54128fSAndroid Build Coastguard Worker 		bitmap->base_error_code = EXT2_ET_BAD_GENERIC_MARK;
157*6a54128fSAndroid Build Coastguard Worker 	}
158*6a54128fSAndroid Build Coastguard Worker 	if (descr) {
159*6a54128fSAndroid Build Coastguard Worker 		retval = ext2fs_get_mem(strlen(descr)+1, &bitmap->description);
160*6a54128fSAndroid Build Coastguard Worker 		if (retval) {
161*6a54128fSAndroid Build Coastguard Worker 			ext2fs_free_mem(&bitmap);
162*6a54128fSAndroid Build Coastguard Worker 			return retval;
163*6a54128fSAndroid Build Coastguard Worker 		}
164*6a54128fSAndroid Build Coastguard Worker 		strcpy(bitmap->description, descr);
165*6a54128fSAndroid Build Coastguard Worker 	} else
166*6a54128fSAndroid Build Coastguard Worker 		bitmap->description = 0;
167*6a54128fSAndroid Build Coastguard Worker 
168*6a54128fSAndroid Build Coastguard Worker 	retval = bitmap->bitmap_ops->new_bmap(fs, bitmap);
169*6a54128fSAndroid Build Coastguard Worker 	if (retval) {
170*6a54128fSAndroid Build Coastguard Worker 		ext2fs_free_mem(&bitmap->description);
171*6a54128fSAndroid Build Coastguard Worker 		ext2fs_free_mem(&bitmap);
172*6a54128fSAndroid Build Coastguard Worker 		return retval;
173*6a54128fSAndroid Build Coastguard Worker 	}
174*6a54128fSAndroid Build Coastguard Worker 
175*6a54128fSAndroid Build Coastguard Worker 	*ret = (ext2fs_generic_bitmap) bitmap;
176*6a54128fSAndroid Build Coastguard Worker 	return 0;
177*6a54128fSAndroid Build Coastguard Worker }
178*6a54128fSAndroid Build Coastguard Worker 
179*6a54128fSAndroid Build Coastguard Worker #ifdef ENABLE_BMAP_STATS
ext2fs_print_bmap_statistics(ext2fs_generic_bitmap_64 bitmap)180*6a54128fSAndroid Build Coastguard Worker static void ext2fs_print_bmap_statistics(ext2fs_generic_bitmap_64 bitmap)
181*6a54128fSAndroid Build Coastguard Worker {
182*6a54128fSAndroid Build Coastguard Worker 	struct ext2_bmap_statistics *stats = &bitmap->stats;
183*6a54128fSAndroid Build Coastguard Worker #ifdef ENABLE_BMAP_STATS_OPS
184*6a54128fSAndroid Build Coastguard Worker 	float mark_seq_perc = 0.0, test_seq_perc = 0.0;
185*6a54128fSAndroid Build Coastguard Worker 	float mark_back_perc = 0.0, test_back_perc = 0.0;
186*6a54128fSAndroid Build Coastguard Worker 	struct timeval now;
187*6a54128fSAndroid Build Coastguard Worker 	double inuse;
188*6a54128fSAndroid Build Coastguard Worker 
189*6a54128fSAndroid Build Coastguard Worker 	if (stats->test_count) {
190*6a54128fSAndroid Build Coastguard Worker 		test_seq_perc = ((float)stats->test_seq /
191*6a54128fSAndroid Build Coastguard Worker 				 stats->test_count) * 100;
192*6a54128fSAndroid Build Coastguard Worker 		test_back_perc = ((float)stats->test_back /
193*6a54128fSAndroid Build Coastguard Worker 				  stats->test_count) * 100;
194*6a54128fSAndroid Build Coastguard Worker 	}
195*6a54128fSAndroid Build Coastguard Worker 
196*6a54128fSAndroid Build Coastguard Worker 	if (stats->mark_count) {
197*6a54128fSAndroid Build Coastguard Worker 		mark_seq_perc = ((float)stats->mark_seq /
198*6a54128fSAndroid Build Coastguard Worker 				 stats->mark_count) * 100;
199*6a54128fSAndroid Build Coastguard Worker 		mark_back_perc = ((float)stats->mark_back /
200*6a54128fSAndroid Build Coastguard Worker 				  stats->mark_count) * 100;
201*6a54128fSAndroid Build Coastguard Worker 	}
202*6a54128fSAndroid Build Coastguard Worker 
203*6a54128fSAndroid Build Coastguard Worker 	if (gettimeofday(&now, (struct timezone *) NULL) == -1) {
204*6a54128fSAndroid Build Coastguard Worker 		perror("gettimeofday");
205*6a54128fSAndroid Build Coastguard Worker 		return;
206*6a54128fSAndroid Build Coastguard Worker 	}
207*6a54128fSAndroid Build Coastguard Worker 
208*6a54128fSAndroid Build Coastguard Worker 	inuse = (double) now.tv_sec + \
209*6a54128fSAndroid Build Coastguard Worker 		(((double) now.tv_usec) * 0.000001);
210*6a54128fSAndroid Build Coastguard Worker 	inuse -= (double) stats->created.tv_sec + \
211*6a54128fSAndroid Build Coastguard Worker 		(((double) stats->created.tv_usec) * 0.000001);
212*6a54128fSAndroid Build Coastguard Worker #endif /* ENABLE_BMAP_STATS_OPS */
213*6a54128fSAndroid Build Coastguard Worker 
214*6a54128fSAndroid Build Coastguard Worker 	fprintf(stderr, "\n[+] %s bitmap (type %d)\n", bitmap->description,
215*6a54128fSAndroid Build Coastguard Worker 		stats->type);
216*6a54128fSAndroid Build Coastguard Worker 	fprintf(stderr, "=================================================\n");
217*6a54128fSAndroid Build Coastguard Worker #ifdef ENABLE_BMAP_STATS_OPS
218*6a54128fSAndroid Build Coastguard Worker 	fprintf(stderr, "%16llu bits long\n",
219*6a54128fSAndroid Build Coastguard Worker 		bitmap->real_end - bitmap->start);
220*6a54128fSAndroid Build Coastguard Worker 	fprintf(stderr, "%16lu copy_bmap\n%16lu resize_bmap\n",
221*6a54128fSAndroid Build Coastguard Worker 		stats->copy_count, stats->resize_count);
222*6a54128fSAndroid Build Coastguard Worker 	fprintf(stderr, "%16lu mark bmap\n%16lu unmark_bmap\n",
223*6a54128fSAndroid Build Coastguard Worker 		stats->mark_count, stats->unmark_count);
224*6a54128fSAndroid Build Coastguard Worker 	fprintf(stderr, "%16lu test_bmap\n%16lu mark_bmap_extent\n",
225*6a54128fSAndroid Build Coastguard Worker 		stats->test_count, stats->mark_ext_count);
226*6a54128fSAndroid Build Coastguard Worker 	fprintf(stderr, "%16lu unmark_bmap_extent\n"
227*6a54128fSAndroid Build Coastguard Worker 		"%16lu test_clear_bmap_extent\n",
228*6a54128fSAndroid Build Coastguard Worker 		stats->unmark_ext_count, stats->test_ext_count);
229*6a54128fSAndroid Build Coastguard Worker 	fprintf(stderr, "%16lu set_bmap_range\n%16lu set_bmap_range\n",
230*6a54128fSAndroid Build Coastguard Worker 		stats->set_range_count, stats->get_range_count);
231*6a54128fSAndroid Build Coastguard Worker 	fprintf(stderr, "%16lu clear_bmap\n%16lu contiguous bit test (%.2f%%)\n",
232*6a54128fSAndroid Build Coastguard Worker 		stats->clear_count, stats->test_seq, test_seq_perc);
233*6a54128fSAndroid Build Coastguard Worker 	fprintf(stderr, "%16lu contiguous bit mark (%.2f%%)\n"
234*6a54128fSAndroid Build Coastguard Worker 		"%16llu bits tested backwards (%.2f%%)\n",
235*6a54128fSAndroid Build Coastguard Worker 		stats->mark_seq, mark_seq_perc,
236*6a54128fSAndroid Build Coastguard Worker 		stats->test_back, test_back_perc);
237*6a54128fSAndroid Build Coastguard Worker 	fprintf(stderr, "%16llu bits marked backwards (%.2f%%)\n"
238*6a54128fSAndroid Build Coastguard Worker 		"%16.2f seconds in use\n",
239*6a54128fSAndroid Build Coastguard Worker 		stats->mark_back, mark_back_perc, inuse);
240*6a54128fSAndroid Build Coastguard Worker #endif /* ENABLE_BMAP_STATS_OPS */
241*6a54128fSAndroid Build Coastguard Worker }
242*6a54128fSAndroid Build Coastguard Worker #endif
243*6a54128fSAndroid Build Coastguard Worker 
ext2fs_free_generic_bmap(ext2fs_generic_bitmap gen_bmap)244*6a54128fSAndroid Build Coastguard Worker void ext2fs_free_generic_bmap(ext2fs_generic_bitmap gen_bmap)
245*6a54128fSAndroid Build Coastguard Worker {
246*6a54128fSAndroid Build Coastguard Worker 	ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap;
247*6a54128fSAndroid Build Coastguard Worker 
248*6a54128fSAndroid Build Coastguard Worker 	if (!bmap)
249*6a54128fSAndroid Build Coastguard Worker 		return;
250*6a54128fSAndroid Build Coastguard Worker 
251*6a54128fSAndroid Build Coastguard Worker 	if (EXT2FS_IS_32_BITMAP(bmap)) {
252*6a54128fSAndroid Build Coastguard Worker 		ext2fs_free_generic_bitmap(gen_bmap);
253*6a54128fSAndroid Build Coastguard Worker 		return;
254*6a54128fSAndroid Build Coastguard Worker 	}
255*6a54128fSAndroid Build Coastguard Worker 
256*6a54128fSAndroid Build Coastguard Worker 	if (!EXT2FS_IS_64_BITMAP(bmap))
257*6a54128fSAndroid Build Coastguard Worker 		return;
258*6a54128fSAndroid Build Coastguard Worker 
259*6a54128fSAndroid Build Coastguard Worker #ifdef ENABLE_BMAP_STATS
260*6a54128fSAndroid Build Coastguard Worker 	if (getenv("E2FSPROGS_BITMAP_STATS")) {
261*6a54128fSAndroid Build Coastguard Worker 		ext2fs_print_bmap_statistics(bmap);
262*6a54128fSAndroid Build Coastguard Worker 		bmap->bitmap_ops->print_stats(bmap);
263*6a54128fSAndroid Build Coastguard Worker 	}
264*6a54128fSAndroid Build Coastguard Worker #endif
265*6a54128fSAndroid Build Coastguard Worker 
266*6a54128fSAndroid Build Coastguard Worker 	bmap->bitmap_ops->free_bmap(bmap);
267*6a54128fSAndroid Build Coastguard Worker 
268*6a54128fSAndroid Build Coastguard Worker 	if (bmap->description) {
269*6a54128fSAndroid Build Coastguard Worker 		ext2fs_free_mem(&bmap->description);
270*6a54128fSAndroid Build Coastguard Worker 		bmap->description = 0;
271*6a54128fSAndroid Build Coastguard Worker 	}
272*6a54128fSAndroid Build Coastguard Worker 	bmap->magic = 0;
273*6a54128fSAndroid Build Coastguard Worker 	ext2fs_free_mem(&bmap);
274*6a54128fSAndroid Build Coastguard Worker }
275*6a54128fSAndroid Build Coastguard Worker 
ext2fs_copy_generic_bmap(ext2fs_generic_bitmap gen_src,ext2fs_generic_bitmap * dest)276*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_copy_generic_bmap(ext2fs_generic_bitmap gen_src,
277*6a54128fSAndroid Build Coastguard Worker 				   ext2fs_generic_bitmap *dest)
278*6a54128fSAndroid Build Coastguard Worker {
279*6a54128fSAndroid Build Coastguard Worker 	ext2fs_generic_bitmap_64 src = (ext2fs_generic_bitmap_64) gen_src;
280*6a54128fSAndroid Build Coastguard Worker 	char *descr, *new_descr;
281*6a54128fSAndroid Build Coastguard Worker 	ext2fs_generic_bitmap_64 new_bmap;
282*6a54128fSAndroid Build Coastguard Worker 	errcode_t retval;
283*6a54128fSAndroid Build Coastguard Worker 
284*6a54128fSAndroid Build Coastguard Worker 	if (!src)
285*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
286*6a54128fSAndroid Build Coastguard Worker 
287*6a54128fSAndroid Build Coastguard Worker 	if (EXT2FS_IS_32_BITMAP(src))
288*6a54128fSAndroid Build Coastguard Worker 		return ext2fs_copy_generic_bitmap(gen_src, dest);
289*6a54128fSAndroid Build Coastguard Worker 
290*6a54128fSAndroid Build Coastguard Worker 	if (!EXT2FS_IS_64_BITMAP(src))
291*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
292*6a54128fSAndroid Build Coastguard Worker 
293*6a54128fSAndroid Build Coastguard Worker 	/* Allocate a new bitmap struct */
294*6a54128fSAndroid Build Coastguard Worker 	retval = ext2fs_get_memzero(sizeof(struct ext2fs_struct_generic_bitmap_64),
295*6a54128fSAndroid Build Coastguard Worker 				    &new_bmap);
296*6a54128fSAndroid Build Coastguard Worker 	if (retval)
297*6a54128fSAndroid Build Coastguard Worker 		return retval;
298*6a54128fSAndroid Build Coastguard Worker 
299*6a54128fSAndroid Build Coastguard Worker 
300*6a54128fSAndroid Build Coastguard Worker #ifdef ENABLE_BMAP_STATS_OPS
301*6a54128fSAndroid Build Coastguard Worker 	src->stats.copy_count++;
302*6a54128fSAndroid Build Coastguard Worker #endif
303*6a54128fSAndroid Build Coastguard Worker #ifdef ENABLE_BMAP_STATS
304*6a54128fSAndroid Build Coastguard Worker 	if (gettimeofday(&new_bmap->stats.created,
305*6a54128fSAndroid Build Coastguard Worker 			 (struct timezone *) NULL) == -1) {
306*6a54128fSAndroid Build Coastguard Worker 		perror("gettimeofday");
307*6a54128fSAndroid Build Coastguard Worker 		ext2fs_free_mem(&new_bmap);
308*6a54128fSAndroid Build Coastguard Worker 		return 1;
309*6a54128fSAndroid Build Coastguard Worker 	}
310*6a54128fSAndroid Build Coastguard Worker 	new_bmap->stats.type = src->stats.type;
311*6a54128fSAndroid Build Coastguard Worker #endif
312*6a54128fSAndroid Build Coastguard Worker 
313*6a54128fSAndroid Build Coastguard Worker 	/* Copy all the high-level parts over */
314*6a54128fSAndroid Build Coastguard Worker 	new_bmap->magic = src->magic;
315*6a54128fSAndroid Build Coastguard Worker 	new_bmap->fs = src->fs;
316*6a54128fSAndroid Build Coastguard Worker 	new_bmap->start = src->start;
317*6a54128fSAndroid Build Coastguard Worker 	new_bmap->end = src->end;
318*6a54128fSAndroid Build Coastguard Worker 	new_bmap->real_end = src->real_end;
319*6a54128fSAndroid Build Coastguard Worker 	new_bmap->bitmap_ops = src->bitmap_ops;
320*6a54128fSAndroid Build Coastguard Worker 	new_bmap->base_error_code = src->base_error_code;
321*6a54128fSAndroid Build Coastguard Worker 	new_bmap->cluster_bits = src->cluster_bits;
322*6a54128fSAndroid Build Coastguard Worker 
323*6a54128fSAndroid Build Coastguard Worker 	descr = src->description;
324*6a54128fSAndroid Build Coastguard Worker 	if (descr) {
325*6a54128fSAndroid Build Coastguard Worker 		retval = ext2fs_get_mem(strlen(descr)+10, &new_descr);
326*6a54128fSAndroid Build Coastguard Worker 		if (retval) {
327*6a54128fSAndroid Build Coastguard Worker 			ext2fs_free_mem(&new_bmap);
328*6a54128fSAndroid Build Coastguard Worker 			return retval;
329*6a54128fSAndroid Build Coastguard Worker 		}
330*6a54128fSAndroid Build Coastguard Worker 		strcpy(new_descr, "copy of ");
331*6a54128fSAndroid Build Coastguard Worker 		strcat(new_descr, descr);
332*6a54128fSAndroid Build Coastguard Worker 		new_bmap->description = new_descr;
333*6a54128fSAndroid Build Coastguard Worker 	}
334*6a54128fSAndroid Build Coastguard Worker 
335*6a54128fSAndroid Build Coastguard Worker 	retval = src->bitmap_ops->copy_bmap(src, new_bmap);
336*6a54128fSAndroid Build Coastguard Worker 	if (retval) {
337*6a54128fSAndroid Build Coastguard Worker 		ext2fs_free_mem(&new_bmap->description);
338*6a54128fSAndroid Build Coastguard Worker 		ext2fs_free_mem(&new_bmap);
339*6a54128fSAndroid Build Coastguard Worker 		return retval;
340*6a54128fSAndroid Build Coastguard Worker 	}
341*6a54128fSAndroid Build Coastguard Worker 
342*6a54128fSAndroid Build Coastguard Worker 	*dest = (ext2fs_generic_bitmap) new_bmap;
343*6a54128fSAndroid Build Coastguard Worker 
344*6a54128fSAndroid Build Coastguard Worker 	return 0;
345*6a54128fSAndroid Build Coastguard Worker }
346*6a54128fSAndroid Build Coastguard Worker 
ext2fs_resize_generic_bmap(ext2fs_generic_bitmap gen_bmap,__u64 new_end,__u64 new_real_end)347*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_resize_generic_bmap(ext2fs_generic_bitmap gen_bmap,
348*6a54128fSAndroid Build Coastguard Worker 				     __u64 new_end,
349*6a54128fSAndroid Build Coastguard Worker 				     __u64 new_real_end)
350*6a54128fSAndroid Build Coastguard Worker {
351*6a54128fSAndroid Build Coastguard Worker 	ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap;
352*6a54128fSAndroid Build Coastguard Worker 
353*6a54128fSAndroid Build Coastguard Worker 	if (!bmap)
354*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
355*6a54128fSAndroid Build Coastguard Worker 
356*6a54128fSAndroid Build Coastguard Worker 	if (EXT2FS_IS_32_BITMAP(bmap))
357*6a54128fSAndroid Build Coastguard Worker 		return ext2fs_resize_generic_bitmap(gen_bmap->magic, new_end,
358*6a54128fSAndroid Build Coastguard Worker 						    new_real_end, gen_bmap);
359*6a54128fSAndroid Build Coastguard Worker 
360*6a54128fSAndroid Build Coastguard Worker 	if (!EXT2FS_IS_64_BITMAP(bmap))
361*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
362*6a54128fSAndroid Build Coastguard Worker 
363*6a54128fSAndroid Build Coastguard Worker 	INC_STAT(bmap, resize_count);
364*6a54128fSAndroid Build Coastguard Worker 
365*6a54128fSAndroid Build Coastguard Worker 	return bmap->bitmap_ops->resize_bmap(bmap, new_end, new_real_end);
366*6a54128fSAndroid Build Coastguard Worker }
367*6a54128fSAndroid Build Coastguard Worker 
ext2fs_fudge_generic_bmap_end(ext2fs_generic_bitmap gen_bitmap,errcode_t neq,__u64 end,__u64 * oend)368*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_fudge_generic_bmap_end(ext2fs_generic_bitmap gen_bitmap,
369*6a54128fSAndroid Build Coastguard Worker 					errcode_t neq,
370*6a54128fSAndroid Build Coastguard Worker 					__u64 end, __u64 *oend)
371*6a54128fSAndroid Build Coastguard Worker {
372*6a54128fSAndroid Build Coastguard Worker 	ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap;
373*6a54128fSAndroid Build Coastguard Worker 
374*6a54128fSAndroid Build Coastguard Worker 	if (!bitmap)
375*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
376*6a54128fSAndroid Build Coastguard Worker 
377*6a54128fSAndroid Build Coastguard Worker 	if (EXT2FS_IS_32_BITMAP(bitmap)) {
378*6a54128fSAndroid Build Coastguard Worker 		ext2_ino_t tmp_oend;
379*6a54128fSAndroid Build Coastguard Worker 		int retval;
380*6a54128fSAndroid Build Coastguard Worker 
381*6a54128fSAndroid Build Coastguard Worker 		retval = ext2fs_fudge_generic_bitmap_end(gen_bitmap,
382*6a54128fSAndroid Build Coastguard Worker 							 bitmap->magic,
383*6a54128fSAndroid Build Coastguard Worker 							 neq, end, &tmp_oend);
384*6a54128fSAndroid Build Coastguard Worker 		if (oend)
385*6a54128fSAndroid Build Coastguard Worker 			*oend = tmp_oend;
386*6a54128fSAndroid Build Coastguard Worker 		return retval;
387*6a54128fSAndroid Build Coastguard Worker 	}
388*6a54128fSAndroid Build Coastguard Worker 
389*6a54128fSAndroid Build Coastguard Worker 	if (!EXT2FS_IS_64_BITMAP(bitmap))
390*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
391*6a54128fSAndroid Build Coastguard Worker 
392*6a54128fSAndroid Build Coastguard Worker 	if (end > bitmap->real_end)
393*6a54128fSAndroid Build Coastguard Worker 		return neq;
394*6a54128fSAndroid Build Coastguard Worker 	if (oend)
395*6a54128fSAndroid Build Coastguard Worker 		*oend = bitmap->end;
396*6a54128fSAndroid Build Coastguard Worker 	bitmap->end = end;
397*6a54128fSAndroid Build Coastguard Worker 	return 0;
398*6a54128fSAndroid Build Coastguard Worker }
399*6a54128fSAndroid Build Coastguard Worker 
ext2fs_get_generic_bmap_start(ext2fs_generic_bitmap gen_bitmap)400*6a54128fSAndroid Build Coastguard Worker __u64 ext2fs_get_generic_bmap_start(ext2fs_generic_bitmap gen_bitmap)
401*6a54128fSAndroid Build Coastguard Worker {
402*6a54128fSAndroid Build Coastguard Worker 	ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap;
403*6a54128fSAndroid Build Coastguard Worker 
404*6a54128fSAndroid Build Coastguard Worker 	if (!bitmap)
405*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
406*6a54128fSAndroid Build Coastguard Worker 
407*6a54128fSAndroid Build Coastguard Worker 	if (EXT2FS_IS_32_BITMAP(bitmap))
408*6a54128fSAndroid Build Coastguard Worker 		return ext2fs_get_generic_bitmap_start(gen_bitmap);
409*6a54128fSAndroid Build Coastguard Worker 
410*6a54128fSAndroid Build Coastguard Worker 	if (!EXT2FS_IS_64_BITMAP(bitmap))
411*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
412*6a54128fSAndroid Build Coastguard Worker 
413*6a54128fSAndroid Build Coastguard Worker 	return bitmap->start;
414*6a54128fSAndroid Build Coastguard Worker }
415*6a54128fSAndroid Build Coastguard Worker 
ext2fs_get_generic_bmap_end(ext2fs_generic_bitmap gen_bitmap)416*6a54128fSAndroid Build Coastguard Worker __u64 ext2fs_get_generic_bmap_end(ext2fs_generic_bitmap gen_bitmap)
417*6a54128fSAndroid Build Coastguard Worker {
418*6a54128fSAndroid Build Coastguard Worker 	ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap;
419*6a54128fSAndroid Build Coastguard Worker 
420*6a54128fSAndroid Build Coastguard Worker 	if (!bitmap)
421*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
422*6a54128fSAndroid Build Coastguard Worker 
423*6a54128fSAndroid Build Coastguard Worker 	if (EXT2FS_IS_32_BITMAP(bitmap))
424*6a54128fSAndroid Build Coastguard Worker 		return ext2fs_get_generic_bitmap_end(gen_bitmap);
425*6a54128fSAndroid Build Coastguard Worker 
426*6a54128fSAndroid Build Coastguard Worker 	if (!EXT2FS_IS_64_BITMAP(bitmap))
427*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
428*6a54128fSAndroid Build Coastguard Worker 
429*6a54128fSAndroid Build Coastguard Worker 	return bitmap->end;
430*6a54128fSAndroid Build Coastguard Worker }
431*6a54128fSAndroid Build Coastguard Worker 
ext2fs_clear_generic_bmap(ext2fs_generic_bitmap gen_bitmap)432*6a54128fSAndroid Build Coastguard Worker void ext2fs_clear_generic_bmap(ext2fs_generic_bitmap gen_bitmap)
433*6a54128fSAndroid Build Coastguard Worker {
434*6a54128fSAndroid Build Coastguard Worker 	ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap;
435*6a54128fSAndroid Build Coastguard Worker 
436*6a54128fSAndroid Build Coastguard Worker 	if (EXT2FS_IS_32_BITMAP(bitmap))
437*6a54128fSAndroid Build Coastguard Worker 		ext2fs_clear_generic_bitmap(gen_bitmap);
438*6a54128fSAndroid Build Coastguard Worker 	else
439*6a54128fSAndroid Build Coastguard Worker 		bitmap->bitmap_ops->clear_bmap(bitmap);
440*6a54128fSAndroid Build Coastguard Worker }
441*6a54128fSAndroid Build Coastguard Worker 
ext2fs_mark_generic_bmap(ext2fs_generic_bitmap gen_bitmap,__u64 arg)442*6a54128fSAndroid Build Coastguard Worker int ext2fs_mark_generic_bmap(ext2fs_generic_bitmap gen_bitmap,
443*6a54128fSAndroid Build Coastguard Worker 			     __u64 arg)
444*6a54128fSAndroid Build Coastguard Worker {
445*6a54128fSAndroid Build Coastguard Worker 	ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap;
446*6a54128fSAndroid Build Coastguard Worker 
447*6a54128fSAndroid Build Coastguard Worker 	if (!bitmap)
448*6a54128fSAndroid Build Coastguard Worker 		return 0;
449*6a54128fSAndroid Build Coastguard Worker 
450*6a54128fSAndroid Build Coastguard Worker 	if (EXT2FS_IS_32_BITMAP(bitmap)) {
451*6a54128fSAndroid Build Coastguard Worker 		if (arg & ~0xffffffffULL) {
452*6a54128fSAndroid Build Coastguard Worker 			ext2fs_warn_bitmap2(gen_bitmap,
453*6a54128fSAndroid Build Coastguard Worker 					    EXT2FS_MARK_ERROR, 0xffffffff);
454*6a54128fSAndroid Build Coastguard Worker 			return 0;
455*6a54128fSAndroid Build Coastguard Worker 		}
456*6a54128fSAndroid Build Coastguard Worker 		return ext2fs_mark_generic_bitmap(gen_bitmap, arg);
457*6a54128fSAndroid Build Coastguard Worker 	}
458*6a54128fSAndroid Build Coastguard Worker 
459*6a54128fSAndroid Build Coastguard Worker 	if (!EXT2FS_IS_64_BITMAP(bitmap))
460*6a54128fSAndroid Build Coastguard Worker 		return 0;
461*6a54128fSAndroid Build Coastguard Worker 
462*6a54128fSAndroid Build Coastguard Worker 	arg >>= bitmap->cluster_bits;
463*6a54128fSAndroid Build Coastguard Worker 
464*6a54128fSAndroid Build Coastguard Worker #ifdef ENABLE_BMAP_STATS_OPS
465*6a54128fSAndroid Build Coastguard Worker 	if (arg == bitmap->stats.last_marked + 1)
466*6a54128fSAndroid Build Coastguard Worker 		bitmap->stats.mark_seq++;
467*6a54128fSAndroid Build Coastguard Worker 	if (arg < bitmap->stats.last_marked)
468*6a54128fSAndroid Build Coastguard Worker 		bitmap->stats.mark_back++;
469*6a54128fSAndroid Build Coastguard Worker 	bitmap->stats.last_marked = arg;
470*6a54128fSAndroid Build Coastguard Worker 	bitmap->stats.mark_count++;
471*6a54128fSAndroid Build Coastguard Worker #endif
472*6a54128fSAndroid Build Coastguard Worker 
473*6a54128fSAndroid Build Coastguard Worker 	if ((arg < bitmap->start) || (arg > bitmap->end)) {
474*6a54128fSAndroid Build Coastguard Worker 		warn_bitmap(bitmap, EXT2FS_MARK_ERROR, arg);
475*6a54128fSAndroid Build Coastguard Worker 		return 0;
476*6a54128fSAndroid Build Coastguard Worker 	}
477*6a54128fSAndroid Build Coastguard Worker 
478*6a54128fSAndroid Build Coastguard Worker 	return bitmap->bitmap_ops->mark_bmap(bitmap, arg);
479*6a54128fSAndroid Build Coastguard Worker }
480*6a54128fSAndroid Build Coastguard Worker 
ext2fs_unmark_generic_bmap(ext2fs_generic_bitmap gen_bitmap,__u64 arg)481*6a54128fSAndroid Build Coastguard Worker int ext2fs_unmark_generic_bmap(ext2fs_generic_bitmap gen_bitmap,
482*6a54128fSAndroid Build Coastguard Worker 			       __u64 arg)
483*6a54128fSAndroid Build Coastguard Worker {
484*6a54128fSAndroid Build Coastguard Worker 	ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap;
485*6a54128fSAndroid Build Coastguard Worker 
486*6a54128fSAndroid Build Coastguard Worker 	if (!bitmap)
487*6a54128fSAndroid Build Coastguard Worker 		return 0;
488*6a54128fSAndroid Build Coastguard Worker 
489*6a54128fSAndroid Build Coastguard Worker 	if (EXT2FS_IS_32_BITMAP(bitmap)) {
490*6a54128fSAndroid Build Coastguard Worker 		if (arg & ~0xffffffffULL) {
491*6a54128fSAndroid Build Coastguard Worker 			ext2fs_warn_bitmap2(gen_bitmap, EXT2FS_UNMARK_ERROR,
492*6a54128fSAndroid Build Coastguard Worker 					    0xffffffff);
493*6a54128fSAndroid Build Coastguard Worker 			return 0;
494*6a54128fSAndroid Build Coastguard Worker 		}
495*6a54128fSAndroid Build Coastguard Worker 		return ext2fs_unmark_generic_bitmap(gen_bitmap, arg);
496*6a54128fSAndroid Build Coastguard Worker 	}
497*6a54128fSAndroid Build Coastguard Worker 
498*6a54128fSAndroid Build Coastguard Worker 	if (!EXT2FS_IS_64_BITMAP(bitmap))
499*6a54128fSAndroid Build Coastguard Worker 		return 0;
500*6a54128fSAndroid Build Coastguard Worker 
501*6a54128fSAndroid Build Coastguard Worker 	arg >>= bitmap->cluster_bits;
502*6a54128fSAndroid Build Coastguard Worker 
503*6a54128fSAndroid Build Coastguard Worker 	INC_STAT(bitmap, unmark_count);
504*6a54128fSAndroid Build Coastguard Worker 
505*6a54128fSAndroid Build Coastguard Worker 	if ((arg < bitmap->start) || (arg > bitmap->end)) {
506*6a54128fSAndroid Build Coastguard Worker 		warn_bitmap(bitmap, EXT2FS_UNMARK_ERROR, arg);
507*6a54128fSAndroid Build Coastguard Worker 		return 0;
508*6a54128fSAndroid Build Coastguard Worker 	}
509*6a54128fSAndroid Build Coastguard Worker 
510*6a54128fSAndroid Build Coastguard Worker 	return bitmap->bitmap_ops->unmark_bmap(bitmap, arg);
511*6a54128fSAndroid Build Coastguard Worker }
512*6a54128fSAndroid Build Coastguard Worker 
ext2fs_test_generic_bmap(ext2fs_generic_bitmap gen_bitmap,__u64 arg)513*6a54128fSAndroid Build Coastguard Worker int ext2fs_test_generic_bmap(ext2fs_generic_bitmap gen_bitmap,
514*6a54128fSAndroid Build Coastguard Worker 			     __u64 arg)
515*6a54128fSAndroid Build Coastguard Worker {
516*6a54128fSAndroid Build Coastguard Worker 	ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap;
517*6a54128fSAndroid Build Coastguard Worker 	if (!bitmap)
518*6a54128fSAndroid Build Coastguard Worker 		return 0;
519*6a54128fSAndroid Build Coastguard Worker 
520*6a54128fSAndroid Build Coastguard Worker 	if (EXT2FS_IS_32_BITMAP(bitmap)) {
521*6a54128fSAndroid Build Coastguard Worker 		if (arg & ~0xffffffffULL) {
522*6a54128fSAndroid Build Coastguard Worker 			ext2fs_warn_bitmap2(gen_bitmap, EXT2FS_TEST_ERROR,
523*6a54128fSAndroid Build Coastguard Worker 					    0xffffffff);
524*6a54128fSAndroid Build Coastguard Worker 			return 0;
525*6a54128fSAndroid Build Coastguard Worker 		}
526*6a54128fSAndroid Build Coastguard Worker 		return ext2fs_test_generic_bitmap(gen_bitmap, arg);
527*6a54128fSAndroid Build Coastguard Worker 	}
528*6a54128fSAndroid Build Coastguard Worker 
529*6a54128fSAndroid Build Coastguard Worker 	if (!EXT2FS_IS_64_BITMAP(bitmap))
530*6a54128fSAndroid Build Coastguard Worker 		return 0;
531*6a54128fSAndroid Build Coastguard Worker 
532*6a54128fSAndroid Build Coastguard Worker 	arg >>= bitmap->cluster_bits;
533*6a54128fSAndroid Build Coastguard Worker 
534*6a54128fSAndroid Build Coastguard Worker #ifdef ENABLE_BMAP_STATS_OPS
535*6a54128fSAndroid Build Coastguard Worker 	bitmap->stats.test_count++;
536*6a54128fSAndroid Build Coastguard Worker 	if (arg == bitmap->stats.last_tested + 1)
537*6a54128fSAndroid Build Coastguard Worker 		bitmap->stats.test_seq++;
538*6a54128fSAndroid Build Coastguard Worker 	if (arg < bitmap->stats.last_tested)
539*6a54128fSAndroid Build Coastguard Worker 		bitmap->stats.test_back++;
540*6a54128fSAndroid Build Coastguard Worker 	bitmap->stats.last_tested = arg;
541*6a54128fSAndroid Build Coastguard Worker #endif
542*6a54128fSAndroid Build Coastguard Worker 
543*6a54128fSAndroid Build Coastguard Worker 	if ((arg < bitmap->start) || (arg > bitmap->end)) {
544*6a54128fSAndroid Build Coastguard Worker 		warn_bitmap(bitmap, EXT2FS_TEST_ERROR, arg);
545*6a54128fSAndroid Build Coastguard Worker 		return 0;
546*6a54128fSAndroid Build Coastguard Worker 	}
547*6a54128fSAndroid Build Coastguard Worker 
548*6a54128fSAndroid Build Coastguard Worker 	return bitmap->bitmap_ops->test_bmap(bitmap, arg);
549*6a54128fSAndroid Build Coastguard Worker }
550*6a54128fSAndroid Build Coastguard Worker 
ext2fs_set_generic_bmap_range(ext2fs_generic_bitmap gen_bmap,__u64 start,unsigned int num,void * in)551*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_set_generic_bmap_range(ext2fs_generic_bitmap gen_bmap,
552*6a54128fSAndroid Build Coastguard Worker 					__u64 start, unsigned int num,
553*6a54128fSAndroid Build Coastguard Worker 					void *in)
554*6a54128fSAndroid Build Coastguard Worker {
555*6a54128fSAndroid Build Coastguard Worker 	ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap;
556*6a54128fSAndroid Build Coastguard Worker 
557*6a54128fSAndroid Build Coastguard Worker 	if (!bmap)
558*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
559*6a54128fSAndroid Build Coastguard Worker 
560*6a54128fSAndroid Build Coastguard Worker 	if (EXT2FS_IS_32_BITMAP(bmap)) {
561*6a54128fSAndroid Build Coastguard Worker 		if ((start+num-1) & ~0xffffffffULL) {
562*6a54128fSAndroid Build Coastguard Worker 			ext2fs_warn_bitmap2(gen_bmap, EXT2FS_UNMARK_ERROR,
563*6a54128fSAndroid Build Coastguard Worker 					    0xffffffff);
564*6a54128fSAndroid Build Coastguard Worker 			return EINVAL;
565*6a54128fSAndroid Build Coastguard Worker 		}
566*6a54128fSAndroid Build Coastguard Worker 		return ext2fs_set_generic_bitmap_range(gen_bmap, bmap->magic,
567*6a54128fSAndroid Build Coastguard Worker 						       start, num, in);
568*6a54128fSAndroid Build Coastguard Worker 	}
569*6a54128fSAndroid Build Coastguard Worker 
570*6a54128fSAndroid Build Coastguard Worker 	if (!EXT2FS_IS_64_BITMAP(bmap))
571*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
572*6a54128fSAndroid Build Coastguard Worker 
573*6a54128fSAndroid Build Coastguard Worker 	INC_STAT(bmap, set_range_count);
574*6a54128fSAndroid Build Coastguard Worker 
575*6a54128fSAndroid Build Coastguard Worker 	return bmap->bitmap_ops->set_bmap_range(bmap, start, num, in);
576*6a54128fSAndroid Build Coastguard Worker }
577*6a54128fSAndroid Build Coastguard Worker 
ext2fs_get_generic_bmap_range(ext2fs_generic_bitmap gen_bmap,__u64 start,unsigned int num,void * out)578*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_get_generic_bmap_range(ext2fs_generic_bitmap gen_bmap,
579*6a54128fSAndroid Build Coastguard Worker 					__u64 start, unsigned int num,
580*6a54128fSAndroid Build Coastguard Worker 					void *out)
581*6a54128fSAndroid Build Coastguard Worker {
582*6a54128fSAndroid Build Coastguard Worker 	ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap;
583*6a54128fSAndroid Build Coastguard Worker 
584*6a54128fSAndroid Build Coastguard Worker 	if (!bmap)
585*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
586*6a54128fSAndroid Build Coastguard Worker 
587*6a54128fSAndroid Build Coastguard Worker 	if (EXT2FS_IS_32_BITMAP(bmap)) {
588*6a54128fSAndroid Build Coastguard Worker 		if ((start+num-1) & ~0xffffffffULL) {
589*6a54128fSAndroid Build Coastguard Worker 			ext2fs_warn_bitmap2(gen_bmap,
590*6a54128fSAndroid Build Coastguard Worker 					    EXT2FS_UNMARK_ERROR, 0xffffffff);
591*6a54128fSAndroid Build Coastguard Worker 			return EINVAL;
592*6a54128fSAndroid Build Coastguard Worker 		}
593*6a54128fSAndroid Build Coastguard Worker 		return ext2fs_get_generic_bitmap_range(gen_bmap, bmap->magic,
594*6a54128fSAndroid Build Coastguard Worker 						       start, num, out);
595*6a54128fSAndroid Build Coastguard Worker 	}
596*6a54128fSAndroid Build Coastguard Worker 
597*6a54128fSAndroid Build Coastguard Worker 	if (!EXT2FS_IS_64_BITMAP(bmap))
598*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
599*6a54128fSAndroid Build Coastguard Worker 
600*6a54128fSAndroid Build Coastguard Worker 	INC_STAT(bmap, get_range_count);
601*6a54128fSAndroid Build Coastguard Worker 
602*6a54128fSAndroid Build Coastguard Worker 	return bmap->bitmap_ops->get_bmap_range(bmap, start, num, out);
603*6a54128fSAndroid Build Coastguard Worker }
604*6a54128fSAndroid Build Coastguard Worker 
ext2fs_compare_generic_bmap(errcode_t neq,ext2fs_generic_bitmap gen_bm1,ext2fs_generic_bitmap gen_bm2)605*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_compare_generic_bmap(errcode_t neq,
606*6a54128fSAndroid Build Coastguard Worker 				      ext2fs_generic_bitmap gen_bm1,
607*6a54128fSAndroid Build Coastguard Worker 				      ext2fs_generic_bitmap gen_bm2)
608*6a54128fSAndroid Build Coastguard Worker {
609*6a54128fSAndroid Build Coastguard Worker 	ext2fs_generic_bitmap_64 bm1 = (ext2fs_generic_bitmap_64) gen_bm1;
610*6a54128fSAndroid Build Coastguard Worker 	ext2fs_generic_bitmap_64 bm2 = (ext2fs_generic_bitmap_64) gen_bm2;
611*6a54128fSAndroid Build Coastguard Worker 	blk64_t	i;
612*6a54128fSAndroid Build Coastguard Worker 
613*6a54128fSAndroid Build Coastguard Worker 	if (!bm1 || !bm2)
614*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
615*6a54128fSAndroid Build Coastguard Worker 	if (bm1->magic != bm2->magic)
616*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
617*6a54128fSAndroid Build Coastguard Worker 
618*6a54128fSAndroid Build Coastguard Worker 	/* Now we know both bitmaps have the same magic */
619*6a54128fSAndroid Build Coastguard Worker 	if (EXT2FS_IS_32_BITMAP(bm1))
620*6a54128fSAndroid Build Coastguard Worker 		return ext2fs_compare_generic_bitmap(bm1->magic, neq,
621*6a54128fSAndroid Build Coastguard Worker 						     gen_bm1, gen_bm2);
622*6a54128fSAndroid Build Coastguard Worker 
623*6a54128fSAndroid Build Coastguard Worker 	if (!EXT2FS_IS_64_BITMAP(bm1))
624*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
625*6a54128fSAndroid Build Coastguard Worker 
626*6a54128fSAndroid Build Coastguard Worker 	if ((bm1->start != bm2->start) ||
627*6a54128fSAndroid Build Coastguard Worker 	    (bm1->end != bm2->end))
628*6a54128fSAndroid Build Coastguard Worker 		return neq;
629*6a54128fSAndroid Build Coastguard Worker 
630*6a54128fSAndroid Build Coastguard Worker 	for (i = bm1->start; i < bm1->end; i++) {
631*6a54128fSAndroid Build Coastguard Worker 		int ret1, ret2;
632*6a54128fSAndroid Build Coastguard Worker 		ret1 = !!ext2fs_test_generic_bmap(gen_bm1, i);
633*6a54128fSAndroid Build Coastguard Worker 		ret2 = !!ext2fs_test_generic_bmap(gen_bm2, i);
634*6a54128fSAndroid Build Coastguard Worker 		if (ret1 != ret2) {
635*6a54128fSAndroid Build Coastguard Worker 			return neq;
636*6a54128fSAndroid Build Coastguard Worker 		}
637*6a54128fSAndroid Build Coastguard Worker 	}
638*6a54128fSAndroid Build Coastguard Worker 
639*6a54128fSAndroid Build Coastguard Worker 	return 0;
640*6a54128fSAndroid Build Coastguard Worker }
641*6a54128fSAndroid Build Coastguard Worker 
ext2fs_set_generic_bmap_padding(ext2fs_generic_bitmap gen_bmap)642*6a54128fSAndroid Build Coastguard Worker void ext2fs_set_generic_bmap_padding(ext2fs_generic_bitmap gen_bmap)
643*6a54128fSAndroid Build Coastguard Worker {
644*6a54128fSAndroid Build Coastguard Worker 	ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap;
645*6a54128fSAndroid Build Coastguard Worker 	__u64	start, num;
646*6a54128fSAndroid Build Coastguard Worker 
647*6a54128fSAndroid Build Coastguard Worker 	if (EXT2FS_IS_32_BITMAP(bmap)) {
648*6a54128fSAndroid Build Coastguard Worker 		ext2fs_set_generic_bitmap_padding(gen_bmap);
649*6a54128fSAndroid Build Coastguard Worker 		return;
650*6a54128fSAndroid Build Coastguard Worker 	}
651*6a54128fSAndroid Build Coastguard Worker 
652*6a54128fSAndroid Build Coastguard Worker 	start = bmap->end + 1;
653*6a54128fSAndroid Build Coastguard Worker 	num = bmap->real_end - bmap->end;
654*6a54128fSAndroid Build Coastguard Worker 	bmap->bitmap_ops->mark_bmap_extent(bmap, start, num);
655*6a54128fSAndroid Build Coastguard Worker 	/* XXX ought to warn on error */
656*6a54128fSAndroid Build Coastguard Worker }
657*6a54128fSAndroid Build Coastguard Worker 
ext2fs_test_block_bitmap_range2(ext2fs_block_bitmap gen_bmap,blk64_t block,unsigned int num)658*6a54128fSAndroid Build Coastguard Worker int ext2fs_test_block_bitmap_range2(ext2fs_block_bitmap gen_bmap,
659*6a54128fSAndroid Build Coastguard Worker 				    blk64_t block, unsigned int num)
660*6a54128fSAndroid Build Coastguard Worker {
661*6a54128fSAndroid Build Coastguard Worker 	ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap;
662*6a54128fSAndroid Build Coastguard Worker 	__u64	end = block + num;
663*6a54128fSAndroid Build Coastguard Worker 
664*6a54128fSAndroid Build Coastguard Worker 	if (!bmap)
665*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
666*6a54128fSAndroid Build Coastguard Worker 
667*6a54128fSAndroid Build Coastguard Worker 	if (num == 1)
668*6a54128fSAndroid Build Coastguard Worker 		return !ext2fs_test_generic_bmap((ext2fs_generic_bitmap)
669*6a54128fSAndroid Build Coastguard Worker 						 bmap, block);
670*6a54128fSAndroid Build Coastguard Worker 
671*6a54128fSAndroid Build Coastguard Worker 	if (EXT2FS_IS_32_BITMAP(bmap)) {
672*6a54128fSAndroid Build Coastguard Worker 		if ((block & ~0xffffffffULL) ||
673*6a54128fSAndroid Build Coastguard Worker 		    ((block+num-1) & ~0xffffffffULL)) {
674*6a54128fSAndroid Build Coastguard Worker 			ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap,
675*6a54128fSAndroid Build Coastguard Worker 					    EXT2FS_UNMARK_ERROR, 0xffffffff);
676*6a54128fSAndroid Build Coastguard Worker 			return EINVAL;
677*6a54128fSAndroid Build Coastguard Worker 		}
678*6a54128fSAndroid Build Coastguard Worker 		return ext2fs_test_block_bitmap_range(
679*6a54128fSAndroid Build Coastguard Worker 			(ext2fs_generic_bitmap) bmap, block, num);
680*6a54128fSAndroid Build Coastguard Worker 	}
681*6a54128fSAndroid Build Coastguard Worker 
682*6a54128fSAndroid Build Coastguard Worker 	if (!EXT2FS_IS_64_BITMAP(bmap))
683*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
684*6a54128fSAndroid Build Coastguard Worker 
685*6a54128fSAndroid Build Coastguard Worker 	INC_STAT(bmap, test_ext_count);
686*6a54128fSAndroid Build Coastguard Worker 
687*6a54128fSAndroid Build Coastguard Worker 	/* convert to clusters if necessary */
688*6a54128fSAndroid Build Coastguard Worker 	block >>= bmap->cluster_bits;
689*6a54128fSAndroid Build Coastguard Worker 	end += (1ULL << bmap->cluster_bits) - 1;
690*6a54128fSAndroid Build Coastguard Worker 	end >>= bmap->cluster_bits;
691*6a54128fSAndroid Build Coastguard Worker 	num = end - block;
692*6a54128fSAndroid Build Coastguard Worker 
693*6a54128fSAndroid Build Coastguard Worker 	if ((block < bmap->start) || (block > bmap->end) ||
694*6a54128fSAndroid Build Coastguard Worker 	    (block+num-1 > bmap->end)) {
695*6a54128fSAndroid Build Coastguard Worker 		ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST, block,
696*6a54128fSAndroid Build Coastguard Worker 				   bmap->description);
697*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
698*6a54128fSAndroid Build Coastguard Worker 	}
699*6a54128fSAndroid Build Coastguard Worker 
700*6a54128fSAndroid Build Coastguard Worker 	return bmap->bitmap_ops->test_clear_bmap_extent(bmap, block, num);
701*6a54128fSAndroid Build Coastguard Worker }
702*6a54128fSAndroid Build Coastguard Worker 
ext2fs_mark_block_bitmap_range2(ext2fs_block_bitmap gen_bmap,blk64_t block,unsigned int num)703*6a54128fSAndroid Build Coastguard Worker void ext2fs_mark_block_bitmap_range2(ext2fs_block_bitmap gen_bmap,
704*6a54128fSAndroid Build Coastguard Worker 				     blk64_t block, unsigned int num)
705*6a54128fSAndroid Build Coastguard Worker {
706*6a54128fSAndroid Build Coastguard Worker 	ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap;
707*6a54128fSAndroid Build Coastguard Worker 	__u64	end = block + num;
708*6a54128fSAndroid Build Coastguard Worker 
709*6a54128fSAndroid Build Coastguard Worker 	if (!bmap)
710*6a54128fSAndroid Build Coastguard Worker 		return;
711*6a54128fSAndroid Build Coastguard Worker 
712*6a54128fSAndroid Build Coastguard Worker 	if (EXT2FS_IS_32_BITMAP(bmap)) {
713*6a54128fSAndroid Build Coastguard Worker 		if ((block & ~0xffffffffULL) ||
714*6a54128fSAndroid Build Coastguard Worker 		    ((block+num-1) & ~0xffffffffULL)) {
715*6a54128fSAndroid Build Coastguard Worker 			ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap,
716*6a54128fSAndroid Build Coastguard Worker 					    EXT2FS_UNMARK_ERROR, 0xffffffff);
717*6a54128fSAndroid Build Coastguard Worker 			return;
718*6a54128fSAndroid Build Coastguard Worker 		}
719*6a54128fSAndroid Build Coastguard Worker 		ext2fs_mark_block_bitmap_range((ext2fs_generic_bitmap) bmap,
720*6a54128fSAndroid Build Coastguard Worker 					       block, num);
721*6a54128fSAndroid Build Coastguard Worker 	}
722*6a54128fSAndroid Build Coastguard Worker 
723*6a54128fSAndroid Build Coastguard Worker 	if (!EXT2FS_IS_64_BITMAP(bmap))
724*6a54128fSAndroid Build Coastguard Worker 		return;
725*6a54128fSAndroid Build Coastguard Worker 
726*6a54128fSAndroid Build Coastguard Worker 	INC_STAT(bmap, mark_ext_count);
727*6a54128fSAndroid Build Coastguard Worker 
728*6a54128fSAndroid Build Coastguard Worker 	/* convert to clusters if necessary */
729*6a54128fSAndroid Build Coastguard Worker 	block >>= bmap->cluster_bits;
730*6a54128fSAndroid Build Coastguard Worker 	end += (1ULL << bmap->cluster_bits) - 1;
731*6a54128fSAndroid Build Coastguard Worker 	end >>= bmap->cluster_bits;
732*6a54128fSAndroid Build Coastguard Worker 	num = end - block;
733*6a54128fSAndroid Build Coastguard Worker 
734*6a54128fSAndroid Build Coastguard Worker 	if ((block < bmap->start) || (block > bmap->end) ||
735*6a54128fSAndroid Build Coastguard Worker 	    (block+num-1 > bmap->end)) {
736*6a54128fSAndroid Build Coastguard Worker 		ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
737*6a54128fSAndroid Build Coastguard Worker 				   bmap->description);
738*6a54128fSAndroid Build Coastguard Worker 		return;
739*6a54128fSAndroid Build Coastguard Worker 	}
740*6a54128fSAndroid Build Coastguard Worker 
741*6a54128fSAndroid Build Coastguard Worker 	bmap->bitmap_ops->mark_bmap_extent(bmap, block, num);
742*6a54128fSAndroid Build Coastguard Worker }
743*6a54128fSAndroid Build Coastguard Worker 
ext2fs_unmark_block_bitmap_range2(ext2fs_block_bitmap gen_bmap,blk64_t block,unsigned int num)744*6a54128fSAndroid Build Coastguard Worker void ext2fs_unmark_block_bitmap_range2(ext2fs_block_bitmap gen_bmap,
745*6a54128fSAndroid Build Coastguard Worker 				       blk64_t block, unsigned int num)
746*6a54128fSAndroid Build Coastguard Worker {
747*6a54128fSAndroid Build Coastguard Worker 	ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap;
748*6a54128fSAndroid Build Coastguard Worker 	__u64	end = block + num;
749*6a54128fSAndroid Build Coastguard Worker 
750*6a54128fSAndroid Build Coastguard Worker 	if (!bmap)
751*6a54128fSAndroid Build Coastguard Worker 		return;
752*6a54128fSAndroid Build Coastguard Worker 
753*6a54128fSAndroid Build Coastguard Worker 	if (EXT2FS_IS_32_BITMAP(bmap)) {
754*6a54128fSAndroid Build Coastguard Worker 		if ((block & ~0xffffffffULL) ||
755*6a54128fSAndroid Build Coastguard Worker 		    ((block+num-1) & ~0xffffffffULL)) {
756*6a54128fSAndroid Build Coastguard Worker 			ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap,
757*6a54128fSAndroid Build Coastguard Worker 					    EXT2FS_UNMARK_ERROR, 0xffffffff);
758*6a54128fSAndroid Build Coastguard Worker 			return;
759*6a54128fSAndroid Build Coastguard Worker 		}
760*6a54128fSAndroid Build Coastguard Worker 		ext2fs_unmark_block_bitmap_range((ext2fs_generic_bitmap) bmap,
761*6a54128fSAndroid Build Coastguard Worker 						 block, num);
762*6a54128fSAndroid Build Coastguard Worker 	}
763*6a54128fSAndroid Build Coastguard Worker 
764*6a54128fSAndroid Build Coastguard Worker 	if (!EXT2FS_IS_64_BITMAP(bmap))
765*6a54128fSAndroid Build Coastguard Worker 		return;
766*6a54128fSAndroid Build Coastguard Worker 
767*6a54128fSAndroid Build Coastguard Worker 	INC_STAT(bmap, unmark_ext_count);
768*6a54128fSAndroid Build Coastguard Worker 
769*6a54128fSAndroid Build Coastguard Worker 	/* convert to clusters if necessary */
770*6a54128fSAndroid Build Coastguard Worker 	block >>= bmap->cluster_bits;
771*6a54128fSAndroid Build Coastguard Worker 	end += (1ULL << bmap->cluster_bits) - 1;
772*6a54128fSAndroid Build Coastguard Worker 	end >>= bmap->cluster_bits;
773*6a54128fSAndroid Build Coastguard Worker 	num = end - block;
774*6a54128fSAndroid Build Coastguard Worker 
775*6a54128fSAndroid Build Coastguard Worker 	if ((block < bmap->start) || (block > bmap->end) ||
776*6a54128fSAndroid Build Coastguard Worker 	    (block+num-1 > bmap->end)) {
777*6a54128fSAndroid Build Coastguard Worker 		ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
778*6a54128fSAndroid Build Coastguard Worker 				   bmap->description);
779*6a54128fSAndroid Build Coastguard Worker 		return;
780*6a54128fSAndroid Build Coastguard Worker 	}
781*6a54128fSAndroid Build Coastguard Worker 
782*6a54128fSAndroid Build Coastguard Worker 	bmap->bitmap_ops->unmark_bmap_extent(bmap, block, num);
783*6a54128fSAndroid Build Coastguard Worker }
784*6a54128fSAndroid Build Coastguard Worker 
ext2fs_warn_bitmap32(ext2fs_generic_bitmap gen_bitmap,const char * func)785*6a54128fSAndroid Build Coastguard Worker void ext2fs_warn_bitmap32(ext2fs_generic_bitmap gen_bitmap, const char *func)
786*6a54128fSAndroid Build Coastguard Worker {
787*6a54128fSAndroid Build Coastguard Worker 	ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap;
788*6a54128fSAndroid Build Coastguard Worker 
789*6a54128fSAndroid Build Coastguard Worker #ifndef OMIT_COM_ERR
790*6a54128fSAndroid Build Coastguard Worker 	if (bitmap && bitmap->description)
791*6a54128fSAndroid Build Coastguard Worker 		com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
792*6a54128fSAndroid Build Coastguard Worker 			"called %s with 64-bit bitmap for %s", func,
793*6a54128fSAndroid Build Coastguard Worker 			bitmap->description);
794*6a54128fSAndroid Build Coastguard Worker 	else
795*6a54128fSAndroid Build Coastguard Worker 		com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
796*6a54128fSAndroid Build Coastguard Worker 			"called %s with 64-bit bitmap", func);
797*6a54128fSAndroid Build Coastguard Worker #endif
798*6a54128fSAndroid Build Coastguard Worker }
799*6a54128fSAndroid Build Coastguard Worker 
ext2fs_convert_subcluster_bitmap(ext2_filsys fs,ext2fs_block_bitmap * bitmap)800*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_convert_subcluster_bitmap(ext2_filsys fs,
801*6a54128fSAndroid Build Coastguard Worker 					   ext2fs_block_bitmap *bitmap)
802*6a54128fSAndroid Build Coastguard Worker {
803*6a54128fSAndroid Build Coastguard Worker 	ext2fs_generic_bitmap_64 bmap, cmap;
804*6a54128fSAndroid Build Coastguard Worker 	ext2fs_block_bitmap	gen_bmap = *bitmap, gen_cmap;
805*6a54128fSAndroid Build Coastguard Worker 	errcode_t		retval;
806*6a54128fSAndroid Build Coastguard Worker 	blk64_t			i, next, b_end, c_end;
807*6a54128fSAndroid Build Coastguard Worker 
808*6a54128fSAndroid Build Coastguard Worker 	bmap = (ext2fs_generic_bitmap_64) gen_bmap;
809*6a54128fSAndroid Build Coastguard Worker 	if (fs->cluster_ratio_bits == ext2fs_get_bitmap_granularity(gen_bmap))
810*6a54128fSAndroid Build Coastguard Worker 		return 0;	/* Nothing to do */
811*6a54128fSAndroid Build Coastguard Worker 
812*6a54128fSAndroid Build Coastguard Worker 	retval = ext2fs_allocate_block_bitmap(fs, "converted cluster bitmap",
813*6a54128fSAndroid Build Coastguard Worker 					      &gen_cmap);
814*6a54128fSAndroid Build Coastguard Worker 	if (retval)
815*6a54128fSAndroid Build Coastguard Worker 		return retval;
816*6a54128fSAndroid Build Coastguard Worker 
817*6a54128fSAndroid Build Coastguard Worker 	cmap = (ext2fs_generic_bitmap_64) gen_cmap;
818*6a54128fSAndroid Build Coastguard Worker 	i = bmap->start;
819*6a54128fSAndroid Build Coastguard Worker 	b_end = bmap->end;
820*6a54128fSAndroid Build Coastguard Worker 	bmap->end = bmap->real_end;
821*6a54128fSAndroid Build Coastguard Worker 	c_end = cmap->end;
822*6a54128fSAndroid Build Coastguard Worker 	cmap->end = cmap->real_end;
823*6a54128fSAndroid Build Coastguard Worker 	while (i < bmap->real_end) {
824*6a54128fSAndroid Build Coastguard Worker 		retval = ext2fs_find_first_set_block_bitmap2(gen_bmap,
825*6a54128fSAndroid Build Coastguard Worker 						i, bmap->real_end, &next);
826*6a54128fSAndroid Build Coastguard Worker 		if (retval)
827*6a54128fSAndroid Build Coastguard Worker 			break;
828*6a54128fSAndroid Build Coastguard Worker 		ext2fs_mark_block_bitmap2(gen_cmap, next);
829*6a54128fSAndroid Build Coastguard Worker 		i = EXT2FS_C2B(fs, EXT2FS_B2C(fs, next) + 1);
830*6a54128fSAndroid Build Coastguard Worker 	}
831*6a54128fSAndroid Build Coastguard Worker 	bmap->end = b_end;
832*6a54128fSAndroid Build Coastguard Worker 	cmap->end = c_end;
833*6a54128fSAndroid Build Coastguard Worker 	ext2fs_free_block_bitmap(gen_bmap);
834*6a54128fSAndroid Build Coastguard Worker 	*bitmap = (ext2fs_block_bitmap) cmap;
835*6a54128fSAndroid Build Coastguard Worker 	return 0;
836*6a54128fSAndroid Build Coastguard Worker }
837*6a54128fSAndroid Build Coastguard Worker 
ext2fs_find_first_zero_generic_bmap(ext2fs_generic_bitmap bitmap,__u64 start,__u64 end,__u64 * out)838*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_find_first_zero_generic_bmap(ext2fs_generic_bitmap bitmap,
839*6a54128fSAndroid Build Coastguard Worker 					      __u64 start, __u64 end, __u64 *out)
840*6a54128fSAndroid Build Coastguard Worker {
841*6a54128fSAndroid Build Coastguard Worker 	ext2fs_generic_bitmap_64 bmap64 = (ext2fs_generic_bitmap_64) bitmap;
842*6a54128fSAndroid Build Coastguard Worker 	__u64 cstart, cend, cout;
843*6a54128fSAndroid Build Coastguard Worker 	errcode_t retval;
844*6a54128fSAndroid Build Coastguard Worker 
845*6a54128fSAndroid Build Coastguard Worker 	if (!bitmap)
846*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
847*6a54128fSAndroid Build Coastguard Worker 
848*6a54128fSAndroid Build Coastguard Worker 	if (EXT2FS_IS_32_BITMAP(bitmap)) {
849*6a54128fSAndroid Build Coastguard Worker 		blk_t blk = 0;
850*6a54128fSAndroid Build Coastguard Worker 
851*6a54128fSAndroid Build Coastguard Worker 		if (((start) & ~0xffffffffULL) ||
852*6a54128fSAndroid Build Coastguard Worker 		    ((end) & ~0xffffffffULL)) {
853*6a54128fSAndroid Build Coastguard Worker 			ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, start);
854*6a54128fSAndroid Build Coastguard Worker 			return EINVAL;
855*6a54128fSAndroid Build Coastguard Worker 		}
856*6a54128fSAndroid Build Coastguard Worker 
857*6a54128fSAndroid Build Coastguard Worker 		retval = ext2fs_find_first_zero_generic_bitmap(bitmap, start,
858*6a54128fSAndroid Build Coastguard Worker 							       end, &blk);
859*6a54128fSAndroid Build Coastguard Worker 		if (retval == 0)
860*6a54128fSAndroid Build Coastguard Worker 			*out = blk;
861*6a54128fSAndroid Build Coastguard Worker 		return retval;
862*6a54128fSAndroid Build Coastguard Worker 	}
863*6a54128fSAndroid Build Coastguard Worker 
864*6a54128fSAndroid Build Coastguard Worker 	if (!EXT2FS_IS_64_BITMAP(bitmap))
865*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
866*6a54128fSAndroid Build Coastguard Worker 
867*6a54128fSAndroid Build Coastguard Worker 	cstart = start >> bmap64->cluster_bits;
868*6a54128fSAndroid Build Coastguard Worker 	cend = end >> bmap64->cluster_bits;
869*6a54128fSAndroid Build Coastguard Worker 
870*6a54128fSAndroid Build Coastguard Worker 	if (cstart < bmap64->start || cend > bmap64->end || start > end) {
871*6a54128fSAndroid Build Coastguard Worker 		warn_bitmap(bmap64, EXT2FS_TEST_ERROR, start);
872*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
873*6a54128fSAndroid Build Coastguard Worker 	}
874*6a54128fSAndroid Build Coastguard Worker 
875*6a54128fSAndroid Build Coastguard Worker 	if (bmap64->bitmap_ops->find_first_zero) {
876*6a54128fSAndroid Build Coastguard Worker 		retval = bmap64->bitmap_ops->find_first_zero(bmap64, cstart,
877*6a54128fSAndroid Build Coastguard Worker 							     cend, &cout);
878*6a54128fSAndroid Build Coastguard Worker 		if (retval)
879*6a54128fSAndroid Build Coastguard Worker 			return retval;
880*6a54128fSAndroid Build Coastguard Worker 	found:
881*6a54128fSAndroid Build Coastguard Worker 		cout <<= bmap64->cluster_bits;
882*6a54128fSAndroid Build Coastguard Worker 		*out = (cout >= start) ? cout : start;
883*6a54128fSAndroid Build Coastguard Worker 		return 0;
884*6a54128fSAndroid Build Coastguard Worker 	}
885*6a54128fSAndroid Build Coastguard Worker 
886*6a54128fSAndroid Build Coastguard Worker 	for (cout = cstart; cout <= cend; cout++)
887*6a54128fSAndroid Build Coastguard Worker 		if (!bmap64->bitmap_ops->test_bmap(bmap64, cout))
888*6a54128fSAndroid Build Coastguard Worker 			goto found;
889*6a54128fSAndroid Build Coastguard Worker 
890*6a54128fSAndroid Build Coastguard Worker 	return ENOENT;
891*6a54128fSAndroid Build Coastguard Worker }
892*6a54128fSAndroid Build Coastguard Worker 
ext2fs_find_first_set_generic_bmap(ext2fs_generic_bitmap bitmap,__u64 start,__u64 end,__u64 * out)893*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_find_first_set_generic_bmap(ext2fs_generic_bitmap bitmap,
894*6a54128fSAndroid Build Coastguard Worker 					     __u64 start, __u64 end, __u64 *out)
895*6a54128fSAndroid Build Coastguard Worker {
896*6a54128fSAndroid Build Coastguard Worker 	ext2fs_generic_bitmap_64 bmap64 = (ext2fs_generic_bitmap_64) bitmap;
897*6a54128fSAndroid Build Coastguard Worker 	__u64 cstart, cend, cout;
898*6a54128fSAndroid Build Coastguard Worker 	errcode_t retval;
899*6a54128fSAndroid Build Coastguard Worker 
900*6a54128fSAndroid Build Coastguard Worker 	if (!bitmap)
901*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
902*6a54128fSAndroid Build Coastguard Worker 
903*6a54128fSAndroid Build Coastguard Worker 	if (EXT2FS_IS_32_BITMAP(bitmap)) {
904*6a54128fSAndroid Build Coastguard Worker 		blk_t blk = 0;
905*6a54128fSAndroid Build Coastguard Worker 
906*6a54128fSAndroid Build Coastguard Worker 		if (((start) & ~0xffffffffULL) ||
907*6a54128fSAndroid Build Coastguard Worker 		    ((end) & ~0xffffffffULL)) {
908*6a54128fSAndroid Build Coastguard Worker 			ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, start);
909*6a54128fSAndroid Build Coastguard Worker 			return EINVAL;
910*6a54128fSAndroid Build Coastguard Worker 		}
911*6a54128fSAndroid Build Coastguard Worker 
912*6a54128fSAndroid Build Coastguard Worker 		retval = ext2fs_find_first_set_generic_bitmap(bitmap, start,
913*6a54128fSAndroid Build Coastguard Worker 							      end, &blk);
914*6a54128fSAndroid Build Coastguard Worker 		if (retval == 0)
915*6a54128fSAndroid Build Coastguard Worker 			*out = blk;
916*6a54128fSAndroid Build Coastguard Worker 		return retval;
917*6a54128fSAndroid Build Coastguard Worker 	}
918*6a54128fSAndroid Build Coastguard Worker 
919*6a54128fSAndroid Build Coastguard Worker 	if (!EXT2FS_IS_64_BITMAP(bitmap))
920*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
921*6a54128fSAndroid Build Coastguard Worker 
922*6a54128fSAndroid Build Coastguard Worker 	cstart = start >> bmap64->cluster_bits;
923*6a54128fSAndroid Build Coastguard Worker 	cend = end >> bmap64->cluster_bits;
924*6a54128fSAndroid Build Coastguard Worker 
925*6a54128fSAndroid Build Coastguard Worker 	if (cstart < bmap64->start || cend > bmap64->end || start > end) {
926*6a54128fSAndroid Build Coastguard Worker 		warn_bitmap(bmap64, EXT2FS_TEST_ERROR, start);
927*6a54128fSAndroid Build Coastguard Worker 		return EINVAL;
928*6a54128fSAndroid Build Coastguard Worker 	}
929*6a54128fSAndroid Build Coastguard Worker 
930*6a54128fSAndroid Build Coastguard Worker 	if (bmap64->bitmap_ops->find_first_set) {
931*6a54128fSAndroid Build Coastguard Worker 		retval = bmap64->bitmap_ops->find_first_set(bmap64, cstart,
932*6a54128fSAndroid Build Coastguard Worker 							    cend, &cout);
933*6a54128fSAndroid Build Coastguard Worker 		if (retval)
934*6a54128fSAndroid Build Coastguard Worker 			return retval;
935*6a54128fSAndroid Build Coastguard Worker 	found:
936*6a54128fSAndroid Build Coastguard Worker 		cout <<= bmap64->cluster_bits;
937*6a54128fSAndroid Build Coastguard Worker 		*out = (cout >= start) ? cout : start;
938*6a54128fSAndroid Build Coastguard Worker 		return 0;
939*6a54128fSAndroid Build Coastguard Worker 	}
940*6a54128fSAndroid Build Coastguard Worker 
941*6a54128fSAndroid Build Coastguard Worker 	for (cout = cstart; cout <= cend; cout++)
942*6a54128fSAndroid Build Coastguard Worker 		if (bmap64->bitmap_ops->test_bmap(bmap64, cout))
943*6a54128fSAndroid Build Coastguard Worker 			goto found;
944*6a54128fSAndroid Build Coastguard Worker 
945*6a54128fSAndroid Build Coastguard Worker 	return ENOENT;
946*6a54128fSAndroid Build Coastguard Worker }
947*6a54128fSAndroid Build Coastguard Worker 
ext2fs_count_used_clusters(ext2_filsys fs,blk64_t start,blk64_t end,blk64_t * out)948*6a54128fSAndroid Build Coastguard Worker errcode_t ext2fs_count_used_clusters(ext2_filsys fs, blk64_t start,
949*6a54128fSAndroid Build Coastguard Worker 				     blk64_t end, blk64_t *out)
950*6a54128fSAndroid Build Coastguard Worker {
951*6a54128fSAndroid Build Coastguard Worker 	blk64_t		next;
952*6a54128fSAndroid Build Coastguard Worker 	blk64_t		tot_set = 0;
953*6a54128fSAndroid Build Coastguard Worker 	errcode_t	retval = 0;
954*6a54128fSAndroid Build Coastguard Worker 
955*6a54128fSAndroid Build Coastguard Worker 	while (start < end) {
956*6a54128fSAndroid Build Coastguard Worker 		retval = ext2fs_find_first_set_block_bitmap2(fs->block_map,
957*6a54128fSAndroid Build Coastguard Worker 							start, end, &next);
958*6a54128fSAndroid Build Coastguard Worker 		if (retval) {
959*6a54128fSAndroid Build Coastguard Worker 			if (retval == ENOENT)
960*6a54128fSAndroid Build Coastguard Worker 				retval = 0;
961*6a54128fSAndroid Build Coastguard Worker 			break;
962*6a54128fSAndroid Build Coastguard Worker 		}
963*6a54128fSAndroid Build Coastguard Worker 		start = next;
964*6a54128fSAndroid Build Coastguard Worker 
965*6a54128fSAndroid Build Coastguard Worker 		retval = ext2fs_find_first_zero_block_bitmap2(fs->block_map,
966*6a54128fSAndroid Build Coastguard Worker 							start, end, &next);
967*6a54128fSAndroid Build Coastguard Worker 		if (retval == 0) {
968*6a54128fSAndroid Build Coastguard Worker 			tot_set += next - start;
969*6a54128fSAndroid Build Coastguard Worker 			start  = next + 1;
970*6a54128fSAndroid Build Coastguard Worker 		} else if (retval == ENOENT) {
971*6a54128fSAndroid Build Coastguard Worker 			retval = 0;
972*6a54128fSAndroid Build Coastguard Worker 			tot_set += end - start + 1;
973*6a54128fSAndroid Build Coastguard Worker 			break;
974*6a54128fSAndroid Build Coastguard Worker 		} else
975*6a54128fSAndroid Build Coastguard Worker 			break;
976*6a54128fSAndroid Build Coastguard Worker 	}
977*6a54128fSAndroid Build Coastguard Worker 
978*6a54128fSAndroid Build Coastguard Worker 	if (!retval)
979*6a54128fSAndroid Build Coastguard Worker 		*out = EXT2FS_NUM_B2C(fs, tot_set);
980*6a54128fSAndroid Build Coastguard Worker 	return retval;
981*6a54128fSAndroid Build Coastguard Worker }
982