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;
111 case EXT2_ET_MAGIC_INODE_BITMAP64:
112 bitmap->base_error_code = EXT2_ET_BAD_INODE_MARK;
114 case EXT2_ET_MAGIC_BLOCK_BITMAP64:
115 bitmap->base_error_code = EXT2_ET_BAD_BLOCK_MARK;
118 bitmap->base_error_code = EXT2_ET_BAD_GENERIC_MARK;
121 retval = ext2fs_get_mem(strlen(descr)+1, &bitmap->description);
123 ext2fs_free_mem(&bitmap);
126 strcpy(bitmap->description, descr);
128 bitmap->description = 0;
130 retval = bitmap->bitmap_ops->new_bmap(fs, bitmap);
132 ext2fs_free_mem(&bitmap);
133 ext2fs_free_mem(&bitmap->description);
141 void ext2fs_free_generic_bmap(ext2fs_generic_bitmap bmap)
146 if (EXT2FS_IS_32_BITMAP(bmap)) {
147 ext2fs_free_generic_bitmap((ext2fs_generic_bitmap) bmap);
151 if (!EXT2FS_IS_64_BITMAP(bmap))
154 bmap->bitmap_ops->free_bmap(bmap);
156 if (bmap->description) {
157 ext2fs_free_mem(&bmap->description);
158 bmap->description = 0;
163 errcode_t ext2fs_copy_generic_bmap(ext2fs_generic_bitmap src,
164 ext2fs_generic_bitmap *dest)
166 char *descr, *new_descr;
167 ext2fs_generic_bitmap new_bmap;
173 if (EXT2FS_IS_32_BITMAP(src))
174 return ext2fs_copy_generic_bitmap((ext2fs_generic_bitmap) src,
175 (ext2fs_generic_bitmap *) dest);
177 if (!EXT2FS_IS_64_BITMAP(src))
180 /* Allocate a new bitmap struct */
181 retval = ext2fs_get_mem(sizeof(struct ext2fs_struct_generic_bitmap),
186 /* Copy all the high-level parts over */
187 new_bmap->magic = src->magic;
188 new_bmap->fs = src->fs;
189 new_bmap->start = src->start;
190 new_bmap->end = src->end;
191 new_bmap->real_end = src->real_end;
192 new_bmap->bitmap_ops = src->bitmap_ops;
193 new_bmap->base_error_code = src->base_error_code;
195 descr = src->description;
197 retval = ext2fs_get_mem(strlen(descr)+1, &new_descr);
199 ext2fs_free_mem(&new_bmap);
202 strcpy(new_descr, descr);
203 new_bmap->description = new_descr;
206 retval = src->bitmap_ops->copy_bmap(src, new_bmap);
208 ext2fs_free_mem(&new_bmap->description);
209 ext2fs_free_mem(&new_bmap);
218 errcode_t ext2fs_resize_generic_bmap(ext2fs_generic_bitmap bmap,
225 if (EXT2FS_IS_32_BITMAP(bmap)) {
226 return ext2fs_resize_generic_bitmap(bmap->magic,
227 new_end, new_real_end,
228 (ext2fs_generic_bitmap) bmap);
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((ext2fs_generic_bitmap) bitmap,
256 if (!EXT2FS_IS_64_BITMAP(bitmap))
259 if (end > bitmap->real_end)
267 __u64 ext2fs_get_generic_bmap_start(ext2fs_generic_bitmap bitmap)
272 if (EXT2FS_IS_32_BITMAP(bitmap)) {
273 return ext2fs_get_generic_bitmap_start((ext2fs_generic_bitmap)
278 if (!EXT2FS_IS_64_BITMAP(bitmap))
281 return bitmap->start;
284 __u64 ext2fs_get_generic_bmap_end(ext2fs_generic_bitmap bitmap)
289 if (EXT2FS_IS_32_BITMAP(bitmap)) {
290 return ext2fs_get_generic_bitmap_end((ext2fs_generic_bitmap)
295 if (!EXT2FS_IS_64_BITMAP(bitmap))
301 void ext2fs_clear_generic_bmap(ext2fs_generic_bitmap bitmap)
303 if (EXT2FS_IS_32_BITMAP(bitmap)) {
304 ext2fs_clear_generic_bitmap((ext2fs_generic_bitmap) bitmap);
308 bitmap->bitmap_ops->clear_bmap (bitmap);
311 int ext2fs_mark_generic_bmap(ext2fs_generic_bitmap bitmap,
317 if (EXT2FS_IS_32_BITMAP(bitmap)) {
318 if (arg & ~0xffffffffULL) {
319 ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bitmap,
320 EXT2FS_MARK_ERROR, 0xffffffff);
323 return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap)
327 if (!EXT2FS_IS_64_BITMAP(bitmap))
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((ext2fs_generic_bitmap) bitmap,
347 EXT2FS_UNMARK_ERROR, 0xffffffff);
350 return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap)
354 if (!EXT2FS_IS_64_BITMAP(bitmap))
357 if ((arg < bitmap->start) || (arg > bitmap->end)) {
358 warn_bitmap(bitmap, EXT2FS_UNMARK_ERROR, arg);
362 return bitmap->bitmap_ops->unmark_bmap(bitmap, arg);
365 int ext2fs_test_generic_bmap(ext2fs_generic_bitmap bitmap,
371 if (EXT2FS_IS_32_BITMAP(bitmap)) {
372 if (arg & ~0xffffffffULL) {
373 ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bitmap,
374 EXT2FS_TEST_ERROR, 0xffffffff);
377 return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap)
381 if (!EXT2FS_IS_64_BITMAP(bitmap))
384 if ((arg < bitmap->start) || (arg > bitmap->end)) {
385 warn_bitmap(bitmap, EXT2FS_TEST_ERROR, arg);
389 return bitmap->bitmap_ops->test_bmap(bitmap, arg);
392 errcode_t ext2fs_set_generic_bmap_range(ext2fs_generic_bitmap bmap,
393 __u64 start, unsigned int num,
399 if (EXT2FS_IS_32_BITMAP(bmap)) {
400 if ((start+num) & ~0xffffffffULL) {
401 ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap,
402 EXT2FS_UNMARK_ERROR, 0xffffffff);
405 return ext2fs_set_generic_bitmap_range((ext2fs_generic_bitmap) bmap,
406 bmap->magic, start, num,
410 if (!EXT2FS_IS_64_BITMAP(bmap))
413 return bmap->bitmap_ops->set_bmap_range(bmap, start, num, in);
416 errcode_t ext2fs_get_generic_bmap_range(ext2fs_generic_bitmap bmap,
417 __u64 start, unsigned int num,
423 if (EXT2FS_IS_32_BITMAP(bmap)) {
424 if ((start+num) & ~0xffffffffULL) {
425 ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap,
426 EXT2FS_UNMARK_ERROR, 0xffffffff);
429 return ext2fs_get_generic_bitmap_range((ext2fs_generic_bitmap) bmap,
430 bmap->magic, start, num,
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,
454 (ext2fs_generic_bitmap) bm1,
455 (ext2fs_generic_bitmap) bm2);
457 if (!EXT2FS_IS_64_BITMAP(bm1))
460 if ((bm1->start != bm2->start) ||
461 (bm1->end != bm2->end))
464 for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++)
465 if (ext2fs_test_generic_bmap(bm1, i) !=
466 ext2fs_test_generic_bmap(bm2, i))
472 void ext2fs_set_generic_bmap_padding(ext2fs_generic_bitmap bmap)
476 if (EXT2FS_IS_32_BITMAP(bmap)) {
477 ext2fs_set_generic_bitmap_padding((ext2fs_generic_bitmap) bmap);
481 start = bmap->end + 1;
482 num = bmap->real_end - bmap->end;
483 bmap->bitmap_ops->mark_bmap_extent(bmap, start, num);
484 /* XXX ought to warn on error */
487 int ext2fs_test_block_bitmap_range2(ext2fs_block_bitmap bmap,
488 blk64_t block, unsigned int num)
494 return !ext2fs_test_generic_bmap((ext2fs_generic_bitmap)
497 if (EXT2FS_IS_32_BITMAP(bmap)) {
498 if ((block+num) & ~0xffffffffULL) {
499 ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap,
500 EXT2FS_UNMARK_ERROR, 0xffffffff);
503 return ext2fs_test_block_bitmap_range(
504 (ext2fs_generic_bitmap) bmap, block, num);
507 if (!EXT2FS_IS_64_BITMAP(bmap))
510 return bmap->bitmap_ops->test_clear_bmap_extent(bmap, block, num);
513 void ext2fs_mark_block_bitmap_range2(ext2fs_block_bitmap bmap,
514 blk64_t block, unsigned int num)
519 if (EXT2FS_IS_32_BITMAP(bmap)) {
520 if ((block+num) & ~0xffffffffULL) {
521 ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap,
522 EXT2FS_UNMARK_ERROR, 0xffffffff);
525 ext2fs_mark_block_bitmap_range((ext2fs_generic_bitmap) bmap,
529 if (!EXT2FS_IS_64_BITMAP(bmap))
532 if ((block < bmap->start) || (block+num-1 > bmap->end)) {
533 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
538 bmap->bitmap_ops->mark_bmap_extent(bmap, block, num);
541 void ext2fs_unmark_block_bitmap_range2(ext2fs_block_bitmap bmap,
542 blk64_t block, unsigned int num)
547 if (EXT2FS_IS_32_BITMAP(bmap)) {
548 if ((block+num) & ~0xffffffffULL) {
549 ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap,
550 EXT2FS_UNMARK_ERROR, 0xffffffff);
553 ext2fs_unmark_block_bitmap_range((ext2fs_generic_bitmap) bmap,
557 if (!EXT2FS_IS_64_BITMAP(bmap))
560 if ((block < bmap->start) || (block+num-1 > bmap->end)) {
561 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
566 bmap->bitmap_ops->unmark_bmap_extent(bmap, block, num);
569 int ext2fs_warn_bitmap32(ext2fs_generic_bitmap bitmap, const char *func)
572 if (bitmap && bitmap->description)
573 com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
574 "called %s with 64-bit bitmap for %s", func,
575 bitmap->description);
577 com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
578 "called %s with 64-bit bitmap", func);