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(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(src, dest);
176 if (!EXT2FS_IS_64_BITMAP(src))
179 /* Allocate a new bitmap struct */
180 retval = ext2fs_get_mem(sizeof(struct ext2fs_struct_generic_bitmap),
185 /* Copy all the high-level parts over */
186 new_bmap->magic = src->magic;
187 new_bmap->fs = src->fs;
188 new_bmap->start = src->start;
189 new_bmap->end = src->end;
190 new_bmap->real_end = src->real_end;
191 new_bmap->bitmap_ops = src->bitmap_ops;
192 new_bmap->base_error_code = src->base_error_code;
194 descr = src->description;
196 retval = ext2fs_get_mem(strlen(descr)+1, &new_descr);
198 ext2fs_free_mem(&new_bmap);
201 strcpy(new_descr, descr);
202 new_bmap->description = new_descr;
205 retval = src->bitmap_ops->copy_bmap(src, new_bmap);
207 ext2fs_free_mem(&new_bmap->description);
208 ext2fs_free_mem(&new_bmap);
217 errcode_t ext2fs_resize_generic_bmap(ext2fs_generic_bitmap bmap,
224 if (EXT2FS_IS_32_BITMAP(bmap))
225 return ext2fs_resize_generic_bitmap(bmap->magic, new_end,
228 if (!EXT2FS_IS_64_BITMAP(bmap))
231 return bmap->bitmap_ops->resize_bmap(bmap, new_end, new_real_end);
234 errcode_t ext2fs_fudge_generic_bmap_end(ext2fs_generic_bitmap bitmap,
236 __u64 end, __u64 *oend)
241 if (EXT2FS_IS_32_BITMAP(bitmap)) {
245 retval = ext2fs_fudge_generic_bitmap_end(bitmap, bitmap->magic,
246 neq, end, &tmp_oend);
252 if (!EXT2FS_IS_64_BITMAP(bitmap))
255 if (end > bitmap->real_end)
263 __u64 ext2fs_get_generic_bmap_start(ext2fs_generic_bitmap bitmap)
268 if (EXT2FS_IS_32_BITMAP(bitmap))
269 return ext2fs_get_generic_bitmap_start(bitmap);
271 if (!EXT2FS_IS_64_BITMAP(bitmap))
274 return bitmap->start;
277 __u64 ext2fs_get_generic_bmap_end(ext2fs_generic_bitmap bitmap)
282 if (EXT2FS_IS_32_BITMAP(bitmap))
283 return ext2fs_get_generic_bitmap_end(bitmap);
285 if (!EXT2FS_IS_64_BITMAP(bitmap))
291 void ext2fs_clear_generic_bmap(ext2fs_generic_bitmap bitmap)
293 if (EXT2FS_IS_32_BITMAP(bitmap))
294 ext2fs_clear_generic_bitmap(bitmap);
296 bitmap->bitmap_ops->clear_bmap (bitmap);
299 int ext2fs_mark_generic_bmap(ext2fs_generic_bitmap bitmap,
305 if (EXT2FS_IS_32_BITMAP(bitmap)) {
306 if (arg & ~0xffffffffULL) {
307 ext2fs_warn_bitmap2(bitmap,
308 EXT2FS_MARK_ERROR, 0xffffffff);
311 return ext2fs_mark_generic_bitmap(bitmap, arg);
314 if (!EXT2FS_IS_64_BITMAP(bitmap))
317 if ((arg < bitmap->start) || (arg > bitmap->end)) {
318 warn_bitmap(bitmap, EXT2FS_MARK_ERROR, arg);
322 return bitmap->bitmap_ops->mark_bmap(bitmap, arg);
325 int ext2fs_unmark_generic_bmap(ext2fs_generic_bitmap bitmap,
331 if (EXT2FS_IS_32_BITMAP(bitmap)) {
332 if (arg & ~0xffffffffULL) {
333 ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR,
337 return ext2fs_unmark_generic_bitmap(bitmap, arg);
340 if (!EXT2FS_IS_64_BITMAP(bitmap))
343 if ((arg < bitmap->start) || (arg > bitmap->end)) {
344 warn_bitmap(bitmap, EXT2FS_UNMARK_ERROR, arg);
348 return bitmap->bitmap_ops->unmark_bmap(bitmap, arg);
351 int ext2fs_test_generic_bmap(ext2fs_generic_bitmap bitmap,
357 if (EXT2FS_IS_32_BITMAP(bitmap)) {
358 if (arg & ~0xffffffffULL) {
359 ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR,
363 return ext2fs_test_generic_bitmap(bitmap, arg);
366 if (!EXT2FS_IS_64_BITMAP(bitmap))
369 if ((arg < bitmap->start) || (arg > bitmap->end)) {
370 warn_bitmap(bitmap, EXT2FS_TEST_ERROR, arg);
374 return bitmap->bitmap_ops->test_bmap(bitmap, arg);
377 errcode_t ext2fs_set_generic_bmap_range(ext2fs_generic_bitmap bmap,
378 __u64 start, unsigned int num,
384 if (EXT2FS_IS_32_BITMAP(bmap)) {
385 if ((start+num) & ~0xffffffffULL) {
386 ext2fs_warn_bitmap2(bmap, EXT2FS_UNMARK_ERROR,
390 return ext2fs_set_generic_bitmap_range(bmap, bmap->magic,
394 if (!EXT2FS_IS_64_BITMAP(bmap))
397 return bmap->bitmap_ops->set_bmap_range(bmap, start, num, in);
400 errcode_t ext2fs_get_generic_bmap_range(ext2fs_generic_bitmap bmap,
401 __u64 start, unsigned int num,
407 if (EXT2FS_IS_32_BITMAP(bmap)) {
408 if ((start+num) & ~0xffffffffULL) {
409 ext2fs_warn_bitmap2(bmap,
410 EXT2FS_UNMARK_ERROR, 0xffffffff);
413 return ext2fs_get_generic_bitmap_range(bmap, bmap->magic,
417 if (!EXT2FS_IS_64_BITMAP(bmap))
420 return bmap->bitmap_ops->get_bmap_range(bmap, start, num, out);
423 errcode_t ext2fs_compare_generic_bmap(errcode_t neq,
424 ext2fs_generic_bitmap bm1,
425 ext2fs_generic_bitmap bm2)
431 if (bm1->magic != bm2->magic)
434 /* Now we know both bitmaps have the same magic */
435 if (EXT2FS_IS_32_BITMAP(bm1))
436 return ext2fs_compare_generic_bitmap(bm1->magic, neq, bm1, bm2);
438 if (!EXT2FS_IS_64_BITMAP(bm1))
441 if ((bm1->start != bm2->start) ||
442 (bm1->end != bm2->end))
445 for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++)
446 if (ext2fs_test_generic_bmap(bm1, i) !=
447 ext2fs_test_generic_bmap(bm2, i))
453 void ext2fs_set_generic_bmap_padding(ext2fs_generic_bitmap bmap)
457 if (EXT2FS_IS_32_BITMAP(bmap)) {
458 ext2fs_set_generic_bitmap_padding(bmap);
462 start = bmap->end + 1;
463 num = bmap->real_end - bmap->end;
464 bmap->bitmap_ops->mark_bmap_extent(bmap, start, num);
465 /* XXX ought to warn on error */
468 int ext2fs_test_block_bitmap_range2(ext2fs_block_bitmap bmap,
469 blk64_t block, unsigned int num)
475 return !ext2fs_test_generic_bmap((ext2fs_generic_bitmap)
478 if (EXT2FS_IS_32_BITMAP(bmap)) {
479 if ((block+num) & ~0xffffffffULL) {
480 ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap,
481 EXT2FS_UNMARK_ERROR, 0xffffffff);
484 return ext2fs_test_block_bitmap_range(
485 (ext2fs_generic_bitmap) bmap, block, num);
488 if (!EXT2FS_IS_64_BITMAP(bmap))
491 return bmap->bitmap_ops->test_clear_bmap_extent(bmap, block, num);
494 void ext2fs_mark_block_bitmap_range2(ext2fs_block_bitmap bmap,
495 blk64_t block, unsigned int num)
500 if (EXT2FS_IS_32_BITMAP(bmap)) {
501 if ((block+num) & ~0xffffffffULL) {
502 ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap,
503 EXT2FS_UNMARK_ERROR, 0xffffffff);
506 ext2fs_mark_block_bitmap_range((ext2fs_generic_bitmap) bmap,
510 if (!EXT2FS_IS_64_BITMAP(bmap))
513 if ((block < bmap->start) || (block+num-1 > bmap->end)) {
514 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
519 bmap->bitmap_ops->mark_bmap_extent(bmap, block, num);
522 void ext2fs_unmark_block_bitmap_range2(ext2fs_block_bitmap bmap,
523 blk64_t block, unsigned int num)
528 if (EXT2FS_IS_32_BITMAP(bmap)) {
529 if ((block+num) & ~0xffffffffULL) {
530 ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap,
531 EXT2FS_UNMARK_ERROR, 0xffffffff);
534 ext2fs_unmark_block_bitmap_range((ext2fs_generic_bitmap) bmap,
538 if (!EXT2FS_IS_64_BITMAP(bmap))
541 if ((block < bmap->start) || (block+num-1 > bmap->end)) {
542 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
547 bmap->bitmap_ops->unmark_bmap_extent(bmap, block, num);
550 int ext2fs_warn_bitmap32(ext2fs_generic_bitmap bitmap, const char *func)
553 if (bitmap && bitmap->description)
554 com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
555 "called %s with 64-bit bitmap for %s", func,
556 bitmap->description);
558 com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
559 "called %s with 64-bit bitmap", func);