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
25 #include <sys/types.h>
33 * Design of 64-bit bitmaps
35 * In order maintain ABI compatibility with programs that don't
36 * understand about 64-bit blocks/inodes,
37 * ext2fs_allocate_inode_bitmap() and ext2fs_allocate_block_bitmap()
38 * will create old-style bitmaps unless the application passes the
39 * flag EXT2_FLAG_64BITS to ext2fs_open(). If this flag is
40 * passed, then we know the application has been recompiled, so we can
41 * use the new-style bitmaps. If it is not passed, we have to return
42 * an error if trying to open a filesystem which needs 64-bit bitmaps.
44 * The new bitmaps use a new set of structure magic numbers, so that
45 * both the old-style and new-style interfaces can identify which
46 * version of the data structure was used. Both the old-style and
47 * new-style interfaces will support either type of bitmap, although
48 * of course 64-bit operation will only be possible when both the
49 * new-style interface and the new-style bitmap are used.
51 * For example, the new bitmap interfaces will check the structure
52 * magic numbers and so will be able to detect old-stype bitmap. If
53 * they see an old-style bitmap, they will pass it to the gen_bitmap.c
54 * functions for handling. The same will be true for the old
57 * The new-style interfaces will have several different back-end
58 * implementations, so we can support different encodings that are
59 * appropriate for different applications. In general the default
60 * should be whatever makes sense, and what the application/library
61 * will use. However, e2fsck may need specialized implementations for
62 * its own uses. For example, when doing parent directory pointer
63 * loop detections in pass 3, the bitmap will *always* be sparse, so
64 * e2fsck can request an encoding which is optimized for that.
67 static void warn_bitmap(ext2fs_generic_bitmap bitmap,
71 if (bitmap->description)
72 com_err(0, bitmap->base_error_code+code,
73 "#%llu for %s", arg, bitmap->description);
75 com_err(0, bitmap->base_error_code + code, "#%llu", arg);
80 errcode_t ext2fs_alloc_generic_bmap(ext2_filsys fs, errcode_t magic,
81 int type, __u64 start, __u64 end,
84 ext2fs_generic_bitmap *ret)
86 ext2fs_generic_bitmap bitmap;
87 struct ext2_bitmap_ops *ops;
91 case EXT2FS_BMAP64_BITARRAY:
92 ops = &ext2fs_blkmap64_bitarray;
98 retval = ext2fs_get_mem(sizeof(struct ext2fs_struct_generic_bitmap),
103 /* XXX factor out, repeated in copy_bmap */
104 bitmap->magic = magic;
106 bitmap->start = start;
108 bitmap->real_end = real_end;
109 bitmap->bitmap_ops = ops;
110 bitmap->cluster_bits = 0;
112 case EXT2_ET_MAGIC_INODE_BITMAP64:
113 bitmap->base_error_code = EXT2_ET_BAD_INODE_MARK;
115 case EXT2_ET_MAGIC_BLOCK_BITMAP64:
116 bitmap->base_error_code = EXT2_ET_BAD_BLOCK_MARK;
117 bitmap->cluster_bits = fs->cluster_ratio_bits;
120 bitmap->base_error_code = EXT2_ET_BAD_GENERIC_MARK;
123 retval = ext2fs_get_mem(strlen(descr)+1, &bitmap->description);
125 ext2fs_free_mem(&bitmap);
128 strcpy(bitmap->description, descr);
130 bitmap->description = 0;
132 retval = bitmap->bitmap_ops->new_bmap(fs, bitmap);
134 ext2fs_free_mem(&bitmap->description);
135 ext2fs_free_mem(&bitmap);
143 void ext2fs_free_generic_bmap(ext2fs_generic_bitmap bmap)
148 if (EXT2FS_IS_32_BITMAP(bmap)) {
149 ext2fs_free_generic_bitmap(bmap);
153 if (!EXT2FS_IS_64_BITMAP(bmap))
156 bmap->bitmap_ops->free_bmap(bmap);
158 if (bmap->description) {
159 ext2fs_free_mem(&bmap->description);
160 bmap->description = 0;
163 ext2fs_free_mem(&bmap);
166 errcode_t ext2fs_copy_generic_bmap(ext2fs_generic_bitmap src,
167 ext2fs_generic_bitmap *dest)
169 char *descr, *new_descr;
170 ext2fs_generic_bitmap new_bmap;
176 if (EXT2FS_IS_32_BITMAP(src))
177 return ext2fs_copy_generic_bitmap(src, dest);
179 if (!EXT2FS_IS_64_BITMAP(src))
182 /* Allocate a new bitmap struct */
183 retval = ext2fs_get_mem(sizeof(struct ext2fs_struct_generic_bitmap),
188 /* Copy all the high-level parts over */
189 new_bmap->magic = src->magic;
190 new_bmap->fs = src->fs;
191 new_bmap->start = src->start;
192 new_bmap->end = src->end;
193 new_bmap->real_end = src->real_end;
194 new_bmap->bitmap_ops = src->bitmap_ops;
195 new_bmap->base_error_code = src->base_error_code;
197 descr = src->description;
199 retval = ext2fs_get_mem(strlen(descr)+1, &new_descr);
201 ext2fs_free_mem(&new_bmap);
204 strcpy(new_descr, descr);
205 new_bmap->description = new_descr;
208 retval = src->bitmap_ops->copy_bmap(src, new_bmap);
210 ext2fs_free_mem(&new_bmap->description);
211 ext2fs_free_mem(&new_bmap);
220 errcode_t ext2fs_resize_generic_bmap(ext2fs_generic_bitmap bmap,
227 if (EXT2FS_IS_32_BITMAP(bmap))
228 return ext2fs_resize_generic_bitmap(bmap->magic, new_end,
231 if (!EXT2FS_IS_64_BITMAP(bmap))
234 return bmap->bitmap_ops->resize_bmap(bmap, new_end, new_real_end);
237 errcode_t ext2fs_fudge_generic_bmap_end(ext2fs_generic_bitmap bitmap,
239 __u64 end, __u64 *oend)
244 if (EXT2FS_IS_32_BITMAP(bitmap)) {
248 retval = ext2fs_fudge_generic_bitmap_end(bitmap, bitmap->magic,
249 neq, end, &tmp_oend);
255 if (!EXT2FS_IS_64_BITMAP(bitmap))
258 if (end > bitmap->real_end)
266 __u64 ext2fs_get_generic_bmap_start(ext2fs_generic_bitmap bitmap)
271 if (EXT2FS_IS_32_BITMAP(bitmap))
272 return ext2fs_get_generic_bitmap_start(bitmap);
274 if (!EXT2FS_IS_64_BITMAP(bitmap))
277 return bitmap->start;
280 __u64 ext2fs_get_generic_bmap_end(ext2fs_generic_bitmap bitmap)
285 if (EXT2FS_IS_32_BITMAP(bitmap))
286 return ext2fs_get_generic_bitmap_end(bitmap);
288 if (!EXT2FS_IS_64_BITMAP(bitmap))
294 void ext2fs_clear_generic_bmap(ext2fs_generic_bitmap bitmap)
296 if (EXT2FS_IS_32_BITMAP(bitmap))
297 ext2fs_clear_generic_bitmap(bitmap);
299 bitmap->bitmap_ops->clear_bmap (bitmap);
302 int ext2fs_mark_generic_bmap(ext2fs_generic_bitmap bitmap,
308 if (EXT2FS_IS_32_BITMAP(bitmap)) {
309 if (arg & ~0xffffffffULL) {
310 ext2fs_warn_bitmap2(bitmap,
311 EXT2FS_MARK_ERROR, 0xffffffff);
314 return ext2fs_mark_generic_bitmap(bitmap, arg);
317 if (!EXT2FS_IS_64_BITMAP(bitmap))
320 arg >>= bitmap->cluster_bits;
322 if ((arg < bitmap->start) || (arg > bitmap->end)) {
323 warn_bitmap(bitmap, EXT2FS_MARK_ERROR, arg);
327 return bitmap->bitmap_ops->mark_bmap(bitmap, arg);
330 int ext2fs_unmark_generic_bmap(ext2fs_generic_bitmap bitmap,
336 if (EXT2FS_IS_32_BITMAP(bitmap)) {
337 if (arg & ~0xffffffffULL) {
338 ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR,
342 return ext2fs_unmark_generic_bitmap(bitmap, arg);
345 if (!EXT2FS_IS_64_BITMAP(bitmap))
348 arg >>= bitmap->cluster_bits;
350 if ((arg < bitmap->start) || (arg > bitmap->end)) {
351 warn_bitmap(bitmap, EXT2FS_UNMARK_ERROR, arg);
355 return bitmap->bitmap_ops->unmark_bmap(bitmap, arg);
358 int ext2fs_test_generic_bmap(ext2fs_generic_bitmap bitmap,
364 if (EXT2FS_IS_32_BITMAP(bitmap)) {
365 if (arg & ~0xffffffffULL) {
366 ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR,
370 return ext2fs_test_generic_bitmap(bitmap, arg);
373 if (!EXT2FS_IS_64_BITMAP(bitmap))
376 arg >>= bitmap->cluster_bits;
378 if ((arg < bitmap->start) || (arg > bitmap->end)) {
379 warn_bitmap(bitmap, EXT2FS_TEST_ERROR, arg);
383 return bitmap->bitmap_ops->test_bmap(bitmap, arg);
386 errcode_t ext2fs_set_generic_bmap_range(ext2fs_generic_bitmap bmap,
387 __u64 start, unsigned int num,
393 if (EXT2FS_IS_32_BITMAP(bmap)) {
394 if ((start+num) & ~0xffffffffULL) {
395 ext2fs_warn_bitmap2(bmap, EXT2FS_UNMARK_ERROR,
399 return ext2fs_set_generic_bitmap_range(bmap, bmap->magic,
403 if (!EXT2FS_IS_64_BITMAP(bmap))
406 return bmap->bitmap_ops->set_bmap_range(bmap, start, num, in);
409 errcode_t ext2fs_get_generic_bmap_range(ext2fs_generic_bitmap bmap,
410 __u64 start, unsigned int num,
416 if (EXT2FS_IS_32_BITMAP(bmap)) {
417 if ((start+num) & ~0xffffffffULL) {
418 ext2fs_warn_bitmap2(bmap,
419 EXT2FS_UNMARK_ERROR, 0xffffffff);
422 return ext2fs_get_generic_bitmap_range(bmap, bmap->magic,
426 if (!EXT2FS_IS_64_BITMAP(bmap))
429 return bmap->bitmap_ops->get_bmap_range(bmap, start, num, out);
432 errcode_t ext2fs_compare_generic_bmap(errcode_t neq,
433 ext2fs_generic_bitmap bm1,
434 ext2fs_generic_bitmap bm2)
440 if (bm1->magic != bm2->magic)
443 /* Now we know both bitmaps have the same magic */
444 if (EXT2FS_IS_32_BITMAP(bm1))
445 return ext2fs_compare_generic_bitmap(bm1->magic, neq, bm1, bm2);
447 if (!EXT2FS_IS_64_BITMAP(bm1))
450 if ((bm1->start != bm2->start) ||
451 (bm1->end != bm2->end))
454 for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++)
455 if (ext2fs_test_generic_bmap(bm1, i) !=
456 ext2fs_test_generic_bmap(bm2, i))
462 void ext2fs_set_generic_bmap_padding(ext2fs_generic_bitmap bmap)
466 if (EXT2FS_IS_32_BITMAP(bmap)) {
467 ext2fs_set_generic_bitmap_padding(bmap);
471 start = bmap->end + 1;
472 num = bmap->real_end - bmap->end;
473 bmap->bitmap_ops->mark_bmap_extent(bmap, start, num);
474 /* XXX ought to warn on error */
477 int ext2fs_test_block_bitmap_range2(ext2fs_block_bitmap bmap,
478 blk64_t block, unsigned int num)
484 return !ext2fs_test_generic_bmap((ext2fs_generic_bitmap)
487 if (EXT2FS_IS_32_BITMAP(bmap)) {
488 if ((block+num) & ~0xffffffffULL) {
489 ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap,
490 EXT2FS_UNMARK_ERROR, 0xffffffff);
493 return ext2fs_test_block_bitmap_range(
494 (ext2fs_generic_bitmap) bmap, block, num);
497 if (!EXT2FS_IS_64_BITMAP(bmap))
500 return bmap->bitmap_ops->test_clear_bmap_extent(bmap, block, num);
503 void ext2fs_mark_block_bitmap_range2(ext2fs_block_bitmap bmap,
504 blk64_t block, unsigned int num)
509 if (EXT2FS_IS_32_BITMAP(bmap)) {
510 if ((block+num) & ~0xffffffffULL) {
511 ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap,
512 EXT2FS_UNMARK_ERROR, 0xffffffff);
515 ext2fs_mark_block_bitmap_range((ext2fs_generic_bitmap) bmap,
519 if (!EXT2FS_IS_64_BITMAP(bmap))
522 if ((block < bmap->start) || (block+num-1 > bmap->end)) {
523 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
528 bmap->bitmap_ops->mark_bmap_extent(bmap, block, num);
531 void ext2fs_unmark_block_bitmap_range2(ext2fs_block_bitmap bmap,
532 blk64_t block, unsigned int num)
537 if (EXT2FS_IS_32_BITMAP(bmap)) {
538 if ((block+num) & ~0xffffffffULL) {
539 ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap,
540 EXT2FS_UNMARK_ERROR, 0xffffffff);
543 ext2fs_unmark_block_bitmap_range((ext2fs_generic_bitmap) bmap,
547 if (!EXT2FS_IS_64_BITMAP(bmap))
550 if ((block < bmap->start) || (block+num-1 > bmap->end)) {
551 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
556 bmap->bitmap_ops->unmark_bmap_extent(bmap, block, num);
559 int ext2fs_warn_bitmap32(ext2fs_generic_bitmap bitmap, const char *func)
562 if (bitmap && bitmap->description)
563 com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
564 "called %s with 64-bit bitmap for %s", func,
565 bitmap->description);
567 com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
568 "called %s with 64-bit bitmap", func);
572 errcode_t ext2fs_convert_subcluster_bitmap(ext2_filsys fs,
573 ext2fs_block_bitmap *bitmap)
575 ext2fs_block_bitmap cmap, bmap;
577 blk64_t i, b_end, c_end;
582 if (fs->cluster_ratio_bits == ext2fs_get_bitmap_granularity(bmap))
583 return 0; /* Nothing to do */
585 retval = ext2fs_allocate_block_bitmap(fs, "converted cluster bitmap",
592 bmap->end = bmap->real_end;
594 cmap->end = cmap->real_end;
596 ratio = 1 << fs->cluster_ratio_bits;
597 while (i < bmap->real_end) {
598 if (ext2fs_test_block_bitmap2(bmap, i)) {
599 ext2fs_mark_block_bitmap2(cmap, i);
610 ext2fs_free_block_bitmap(bmap);