2 * gen_bitmap64.c --- routines to read, write, and manipulate the new qinode and
5 * Copyright (C) 2007, 2008 Theodore Ts'o.
8 * This file may be redistributed under the terms of the GNU Public
26 #include <sys/types.h>
34 * Design of 64-bit bitmaps
36 * In order maintain ABI compatibility with programs that don't
37 * understand about 64-bit blocks/inodes,
38 * ext2fs_allocate_inode_bitmap() and ext2fs_allocate_block_bitmap()
39 * will create old-style bitmaps unless the application passes the
40 * flag EXT2_FLAG_64BITS to ext2fs_open(). If this flag is
41 * passed, then we know the application has been recompiled, so we can
42 * use the new-style bitmaps. If it is not passed, we have to return
43 * an error if trying to open a filesystem which needs 64-bit bitmaps.
45 * The new bitmaps use a new set of structure magic numbers, so that
46 * both the old-style and new-style interfaces can identify which
47 * version of the data structure was used. Both the old-style and
48 * new-style interfaces will support either type of bitmap, although
49 * of course 64-bit operation will only be possible when both the
50 * new-style interface and the new-style bitmap are used.
52 * For example, the new bitmap interfaces will check the structure
53 * magic numbers and so will be able to detect old-stype bitmap. If
54 * they see an old-style bitmap, they will pass it to the gen_bitmap.c
55 * functions for handling. The same will be true for the old
58 * The new-style interfaces will have several different back-end
59 * implementations, so we can support different encodings that are
60 * appropriate for different applications. In general the default
61 * should be whatever makes sense, and what the application/library
62 * will use. However, e2fsck may need specialized implementations for
63 * its own uses. For example, when doing parent directory pointer
64 * loop detections in pass 3, the bitmap will *always* be sparse, so
65 * e2fsck can request an encoding which is optimized for that.
68 static void warn_bitmap(ext2fs_generic_bitmap bitmap
,
72 if (bitmap
->description
)
73 com_err(0, bitmap
->base_error_code
+code
,
74 "#%llu for %s", arg
, bitmap
->description
);
76 com_err(0, bitmap
->base_error_code
+ code
, "#%llu", arg
);
81 errcode_t
ext2fs_alloc_generic_bmap(ext2_filsys fs
, errcode_t magic
,
82 int type
, __u64 start
, __u64 end
,
85 ext2fs_generic_bitmap
*ret
)
87 ext2fs_generic_bitmap bitmap
;
88 struct ext2_bitmap_ops
*ops
;
92 type
= EXT2FS_BMAP64_BITARRAY
;
95 case EXT2FS_BMAP64_BITARRAY
:
96 ops
= &ext2fs_blkmap64_bitarray
;
98 case EXT2FS_BMAP64_RBTREE
:
99 ops
= &ext2fs_blkmap64_rbtree
;
105 retval
= ext2fs_get_mem(sizeof(struct ext2fs_struct_generic_bitmap
),
110 /* XXX factor out, repeated in copy_bmap */
111 bitmap
->magic
= magic
;
113 bitmap
->start
= start
;
115 bitmap
->real_end
= real_end
;
116 bitmap
->bitmap_ops
= ops
;
117 bitmap
->cluster_bits
= 0;
119 case EXT2_ET_MAGIC_INODE_BITMAP64
:
120 bitmap
->base_error_code
= EXT2_ET_BAD_INODE_MARK
;
122 case EXT2_ET_MAGIC_BLOCK_BITMAP64
:
123 bitmap
->base_error_code
= EXT2_ET_BAD_BLOCK_MARK
;
124 bitmap
->cluster_bits
= fs
->cluster_ratio_bits
;
127 bitmap
->base_error_code
= EXT2_ET_BAD_GENERIC_MARK
;
130 retval
= ext2fs_get_mem(strlen(descr
)+1, &bitmap
->description
);
132 ext2fs_free_mem(&bitmap
);
135 strcpy(bitmap
->description
, descr
);
137 bitmap
->description
= 0;
139 retval
= bitmap
->bitmap_ops
->new_bmap(fs
, bitmap
);
141 ext2fs_free_mem(&bitmap
->description
);
142 ext2fs_free_mem(&bitmap
);
150 void ext2fs_free_generic_bmap(ext2fs_generic_bitmap bmap
)
155 if (EXT2FS_IS_32_BITMAP(bmap
)) {
156 ext2fs_free_generic_bitmap(bmap
);
160 if (!EXT2FS_IS_64_BITMAP(bmap
))
163 bmap
->bitmap_ops
->free_bmap(bmap
);
165 if (bmap
->description
) {
166 ext2fs_free_mem(&bmap
->description
);
167 bmap
->description
= 0;
170 ext2fs_free_mem(&bmap
);
173 errcode_t
ext2fs_copy_generic_bmap(ext2fs_generic_bitmap src
,
174 ext2fs_generic_bitmap
*dest
)
176 char *descr
, *new_descr
;
177 ext2fs_generic_bitmap new_bmap
;
183 if (EXT2FS_IS_32_BITMAP(src
))
184 return ext2fs_copy_generic_bitmap(src
, dest
);
186 if (!EXT2FS_IS_64_BITMAP(src
))
189 /* Allocate a new bitmap struct */
190 retval
= ext2fs_get_mem(sizeof(struct ext2fs_struct_generic_bitmap
),
195 /* Copy all the high-level parts over */
196 new_bmap
->magic
= src
->magic
;
197 new_bmap
->fs
= src
->fs
;
198 new_bmap
->start
= src
->start
;
199 new_bmap
->end
= src
->end
;
200 new_bmap
->real_end
= src
->real_end
;
201 new_bmap
->bitmap_ops
= src
->bitmap_ops
;
202 new_bmap
->base_error_code
= src
->base_error_code
;
203 new_bmap
->cluster_bits
= src
->cluster_bits
;
205 descr
= src
->description
;
207 retval
= ext2fs_get_mem(strlen(descr
)+1, &new_descr
);
209 ext2fs_free_mem(&new_bmap
);
212 strcpy(new_descr
, descr
);
213 new_bmap
->description
= new_descr
;
216 retval
= src
->bitmap_ops
->copy_bmap(src
, new_bmap
);
218 ext2fs_free_mem(&new_bmap
->description
);
219 ext2fs_free_mem(&new_bmap
);
228 errcode_t
ext2fs_resize_generic_bmap(ext2fs_generic_bitmap bmap
,
235 if (EXT2FS_IS_32_BITMAP(bmap
))
236 return ext2fs_resize_generic_bitmap(bmap
->magic
, new_end
,
239 if (!EXT2FS_IS_64_BITMAP(bmap
))
242 return bmap
->bitmap_ops
->resize_bmap(bmap
, new_end
, new_real_end
);
245 errcode_t
ext2fs_fudge_generic_bmap_end(ext2fs_generic_bitmap bitmap
,
247 __u64 end
, __u64
*oend
)
252 if (EXT2FS_IS_32_BITMAP(bitmap
)) {
256 retval
= ext2fs_fudge_generic_bitmap_end(bitmap
, bitmap
->magic
,
257 neq
, end
, &tmp_oend
);
263 if (!EXT2FS_IS_64_BITMAP(bitmap
))
266 if (end
> bitmap
->real_end
)
274 __u64
ext2fs_get_generic_bmap_start(ext2fs_generic_bitmap bitmap
)
279 if (EXT2FS_IS_32_BITMAP(bitmap
))
280 return ext2fs_get_generic_bitmap_start(bitmap
);
282 if (!EXT2FS_IS_64_BITMAP(bitmap
))
285 return bitmap
->start
;
288 __u64
ext2fs_get_generic_bmap_end(ext2fs_generic_bitmap bitmap
)
293 if (EXT2FS_IS_32_BITMAP(bitmap
))
294 return ext2fs_get_generic_bitmap_end(bitmap
);
296 if (!EXT2FS_IS_64_BITMAP(bitmap
))
302 void ext2fs_clear_generic_bmap(ext2fs_generic_bitmap bitmap
)
304 if (EXT2FS_IS_32_BITMAP(bitmap
))
305 ext2fs_clear_generic_bitmap(bitmap
);
307 bitmap
->bitmap_ops
->clear_bmap (bitmap
);
310 int ext2fs_mark_generic_bmap(ext2fs_generic_bitmap bitmap
,
316 if (EXT2FS_IS_32_BITMAP(bitmap
)) {
317 if (arg
& ~0xffffffffULL
) {
318 ext2fs_warn_bitmap2(bitmap
,
319 EXT2FS_MARK_ERROR
, 0xffffffff);
322 return ext2fs_mark_generic_bitmap(bitmap
, arg
);
325 if (!EXT2FS_IS_64_BITMAP(bitmap
))
328 arg
>>= bitmap
->cluster_bits
;
330 if ((arg
< bitmap
->start
) || (arg
> bitmap
->end
)) {
331 warn_bitmap(bitmap
, EXT2FS_MARK_ERROR
, arg
);
335 return bitmap
->bitmap_ops
->mark_bmap(bitmap
, arg
);
338 int ext2fs_unmark_generic_bmap(ext2fs_generic_bitmap bitmap
,
344 if (EXT2FS_IS_32_BITMAP(bitmap
)) {
345 if (arg
& ~0xffffffffULL
) {
346 ext2fs_warn_bitmap2(bitmap
, EXT2FS_UNMARK_ERROR
,
350 return ext2fs_unmark_generic_bitmap(bitmap
, arg
);
353 if (!EXT2FS_IS_64_BITMAP(bitmap
))
356 arg
>>= bitmap
->cluster_bits
;
358 if ((arg
< bitmap
->start
) || (arg
> bitmap
->end
)) {
359 warn_bitmap(bitmap
, EXT2FS_UNMARK_ERROR
, arg
);
363 return bitmap
->bitmap_ops
->unmark_bmap(bitmap
, arg
);
366 int ext2fs_test_generic_bmap(ext2fs_generic_bitmap bitmap
,
372 if (EXT2FS_IS_32_BITMAP(bitmap
)) {
373 if (arg
& ~0xffffffffULL
) {
374 ext2fs_warn_bitmap2(bitmap
, EXT2FS_TEST_ERROR
,
378 return ext2fs_test_generic_bitmap(bitmap
, arg
);
381 if (!EXT2FS_IS_64_BITMAP(bitmap
))
384 arg
>>= bitmap
->cluster_bits
;
386 if ((arg
< bitmap
->start
) || (arg
> bitmap
->end
)) {
387 warn_bitmap(bitmap
, EXT2FS_TEST_ERROR
, arg
);
391 return bitmap
->bitmap_ops
->test_bmap(bitmap
, arg
);
394 errcode_t
ext2fs_set_generic_bmap_range(ext2fs_generic_bitmap bmap
,
395 __u64 start
, unsigned int num
,
401 if (EXT2FS_IS_32_BITMAP(bmap
)) {
402 if ((start
+num
-1) & ~0xffffffffULL
) {
403 ext2fs_warn_bitmap2(bmap
, EXT2FS_UNMARK_ERROR
,
407 return ext2fs_set_generic_bitmap_range(bmap
, bmap
->magic
,
411 if (!EXT2FS_IS_64_BITMAP(bmap
))
414 return bmap
->bitmap_ops
->set_bmap_range(bmap
, start
, num
, in
);
417 errcode_t
ext2fs_get_generic_bmap_range(ext2fs_generic_bitmap bmap
,
418 __u64 start
, unsigned int num
,
424 if (EXT2FS_IS_32_BITMAP(bmap
)) {
425 if ((start
+num
-1) & ~0xffffffffULL
) {
426 ext2fs_warn_bitmap2(bmap
,
427 EXT2FS_UNMARK_ERROR
, 0xffffffff);
430 return ext2fs_get_generic_bitmap_range(bmap
, bmap
->magic
,
434 if (!EXT2FS_IS_64_BITMAP(bmap
))
437 return bmap
->bitmap_ops
->get_bmap_range(bmap
, start
, num
, out
);
440 errcode_t
ext2fs_compare_generic_bmap(errcode_t neq
,
441 ext2fs_generic_bitmap bm1
,
442 ext2fs_generic_bitmap bm2
)
448 if (bm1
->magic
!= bm2
->magic
)
451 /* Now we know both bitmaps have the same magic */
452 if (EXT2FS_IS_32_BITMAP(bm1
))
453 return ext2fs_compare_generic_bitmap(bm1
->magic
, neq
, bm1
, bm2
);
455 if (!EXT2FS_IS_64_BITMAP(bm1
))
458 if ((bm1
->start
!= bm2
->start
) ||
459 (bm1
->end
!= bm2
->end
))
462 for (i
= bm1
->end
- ((bm1
->end
- bm1
->start
) % 8); i
<= bm1
->end
; i
++)
463 if (ext2fs_test_generic_bmap(bm1
, i
) !=
464 ext2fs_test_generic_bmap(bm2
, i
))
470 void ext2fs_set_generic_bmap_padding(ext2fs_generic_bitmap bmap
)
474 if (EXT2FS_IS_32_BITMAP(bmap
)) {
475 ext2fs_set_generic_bitmap_padding(bmap
);
479 start
= bmap
->end
+ 1;
480 num
= bmap
->real_end
- bmap
->end
;
481 bmap
->bitmap_ops
->mark_bmap_extent(bmap
, start
, num
);
482 /* XXX ought to warn on error */
485 int ext2fs_test_block_bitmap_range2(ext2fs_block_bitmap bmap
,
486 blk64_t block
, unsigned int num
)
492 return !ext2fs_test_generic_bmap((ext2fs_generic_bitmap
)
495 if (EXT2FS_IS_32_BITMAP(bmap
)) {
496 if ((block
+num
-1) & ~0xffffffffULL
) {
497 ext2fs_warn_bitmap2((ext2fs_generic_bitmap
) bmap
,
498 EXT2FS_UNMARK_ERROR
, 0xffffffff);
501 return ext2fs_test_block_bitmap_range(
502 (ext2fs_generic_bitmap
) bmap
, block
, num
);
505 if (!EXT2FS_IS_64_BITMAP(bmap
))
508 return bmap
->bitmap_ops
->test_clear_bmap_extent(bmap
, block
, num
);
511 void ext2fs_mark_block_bitmap_range2(ext2fs_block_bitmap bmap
,
512 blk64_t block
, unsigned int num
)
517 if (EXT2FS_IS_32_BITMAP(bmap
)) {
518 if ((block
+num
-1) & ~0xffffffffULL
) {
519 ext2fs_warn_bitmap2((ext2fs_generic_bitmap
) bmap
,
520 EXT2FS_UNMARK_ERROR
, 0xffffffff);
523 ext2fs_mark_block_bitmap_range((ext2fs_generic_bitmap
) bmap
,
527 if (!EXT2FS_IS_64_BITMAP(bmap
))
530 if ((block
< bmap
->start
) || (block
+num
-1 > bmap
->end
)) {
531 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK
, block
,
536 bmap
->bitmap_ops
->mark_bmap_extent(bmap
, block
, num
);
539 void ext2fs_unmark_block_bitmap_range2(ext2fs_block_bitmap bmap
,
540 blk64_t block
, unsigned int num
)
545 if (EXT2FS_IS_32_BITMAP(bmap
)) {
546 if ((block
+num
-1) & ~0xffffffffULL
) {
547 ext2fs_warn_bitmap2((ext2fs_generic_bitmap
) bmap
,
548 EXT2FS_UNMARK_ERROR
, 0xffffffff);
551 ext2fs_unmark_block_bitmap_range((ext2fs_generic_bitmap
) bmap
,
555 if (!EXT2FS_IS_64_BITMAP(bmap
))
558 if ((block
< bmap
->start
) || (block
+num
-1 > bmap
->end
)) {
559 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK
, block
,
564 bmap
->bitmap_ops
->unmark_bmap_extent(bmap
, block
, num
);
567 void ext2fs_warn_bitmap32(ext2fs_generic_bitmap bitmap
, const char *func
)
570 if (bitmap
&& bitmap
->description
)
571 com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP
,
572 "called %s with 64-bit bitmap for %s", func
,
573 bitmap
->description
);
575 com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP
,
576 "called %s with 64-bit bitmap", func
);
580 errcode_t
ext2fs_convert_subcluster_bitmap(ext2_filsys fs
,
581 ext2fs_block_bitmap
*bitmap
)
583 ext2fs_block_bitmap cmap
, bmap
;
585 blk64_t i
, b_end
, c_end
;
590 if (fs
->cluster_ratio_bits
== ext2fs_get_bitmap_granularity(bmap
))
591 return 0; /* Nothing to do */
593 retval
= ext2fs_allocate_block_bitmap(fs
, "converted cluster bitmap",
600 bmap
->end
= bmap
->real_end
;
602 cmap
->end
= cmap
->real_end
;
604 ratio
= 1 << fs
->cluster_ratio_bits
;
605 while (i
< bmap
->real_end
) {
606 if (ext2fs_test_block_bitmap2(bmap
, i
)) {
607 ext2fs_mark_block_bitmap2(cmap
, i
);
618 ext2fs_free_block_bitmap(bmap
);