2 * resize2fs.c --- ext2 main routine
4 * Copyright (C) 1997, 1998 by Theodore Ts'o and
7 * Copyright (C) 1999, 2000 by Theosore Ts'o
10 * This file may be redistributed under the terms of the GNU Public
16 * Resizing a filesystem consists of the following phases:
18 * 1. Adjust superblock and write out new parts of the inode
20 * 2. Determine blocks which need to be relocated, and copy the
21 * contents of blocks from their old locations to the new ones.
22 * 3. Scan the inode table, doing the following:
23 * a. If blocks have been moved, update the block
24 * pointers in the inodes and indirect blocks to
25 * point at the new block locations.
26 * b. If parts of the inode table need to be evacuated,
27 * copy inodes from their old locations to their
29 * c. If (b) needs to be done, note which blocks contain
30 * directory information, since we will need to
31 * update the directory information.
32 * 4. Update the directory blocks with the new inode locations.
33 * 5. Move the inode tables, if necessary.
37 #include "resize2fs.h"
40 #ifdef __linux__ /* Kludge for debugging */
41 #define RESIZE2FS_DEBUG
44 static void fix_uninit_block_bitmaps(ext2_filsys fs
);
45 static errcode_t
adjust_superblock(ext2_resize_t rfs
, blk64_t new_size
);
46 static errcode_t
blocks_to_move(ext2_resize_t rfs
);
47 static errcode_t
block_mover(ext2_resize_t rfs
);
48 static errcode_t
inode_scan_and_fix(ext2_resize_t rfs
);
49 static errcode_t
inode_ref_fix(ext2_resize_t rfs
);
50 static errcode_t
move_itables(ext2_resize_t rfs
);
51 static errcode_t
fix_resize_inode(ext2_filsys fs
);
52 static errcode_t
ext2fs_calculate_summary_stats(ext2_filsys fs
);
53 static errcode_t
fix_sb_journal_backup(ext2_filsys fs
);
54 static errcode_t
mark_table_blocks(ext2_filsys fs
,
55 ext2fs_block_bitmap bmap
);
58 * Some helper CPP macros
60 #define IS_BLOCK_BM(fs, i, blk) ((blk) == ext2fs_block_bitmap_loc((fs),(i)))
61 #define IS_INODE_BM(fs, i, blk) ((blk) == ext2fs_inode_bitmap_loc((fs),(i)))
63 #define IS_INODE_TB(fs, i, blk) (((blk) >= ext2fs_inode_table_loc((fs), (i))) && \
64 ((blk) < (ext2fs_inode_table_loc((fs), (i)) + \
65 (fs)->inode_blocks_per_group)))
67 /* Some bigalloc helper macros which are more succint... */
68 #define B2C(x) EXT2FS_B2C(fs, (x))
69 #define C2B(x) EXT2FS_C2B(fs, (x))
70 #define EQ_CLSTR(x, y) (B2C(x) == B2C(y))
71 #define LE_CLSTR(x, y) (B2C(x) <= B2C(y))
72 #define LT_CLSTR(x, y) (B2C(x) < B2C(y))
73 #define GE_CLSTR(x, y) (B2C(x) >= B2C(y))
74 #define GT_CLSTR(x, y) (B2C(x) > B2C(y))
79 * This is the top-level routine which does the dirty deed....
81 errcode_t
resize_fs(ext2_filsys fs
, blk64_t
*new_size
, int flags
,
82 errcode_t (*progress
)(ext2_resize_t rfs
, int pass
,
84 unsigned long max_val
))
88 struct resource_track rtrack
, overall_track
;
91 * Create the data structure
93 retval
= ext2fs_get_mem(sizeof(struct ext2_resize_struct
), &rfs
);
97 memset(rfs
, 0, sizeof(struct ext2_resize_struct
));
102 rfs
->progress
= progress
;
104 init_resource_track(&overall_track
, "overall resize2fs", fs
->io
);
105 init_resource_track(&rtrack
, "read_bitmaps", fs
->io
);
106 retval
= ext2fs_read_bitmaps(fs
);
109 print_resource_track(rfs
, &rtrack
, fs
->io
);
111 fs
->super
->s_state
|= EXT2_ERROR_FS
;
112 ext2fs_mark_super_dirty(fs
);
115 init_resource_track(&rtrack
, "fix_uninit_block_bitmaps 1", fs
->io
);
116 fix_uninit_block_bitmaps(fs
);
117 print_resource_track(rfs
, &rtrack
, fs
->io
);
118 retval
= ext2fs_dup_handle(fs
, &rfs
->new_fs
);
122 init_resource_track(&rtrack
, "adjust_superblock", fs
->io
);
123 retval
= adjust_superblock(rfs
, *new_size
);
126 print_resource_track(rfs
, &rtrack
, fs
->io
);
129 init_resource_track(&rtrack
, "fix_uninit_block_bitmaps 2", fs
->io
);
130 fix_uninit_block_bitmaps(rfs
->new_fs
);
131 print_resource_track(rfs
, &rtrack
, fs
->io
);
132 /* Clear the block bitmap uninit flag for the last block group */
133 ext2fs_bg_flags_clear(rfs
->new_fs
, rfs
->new_fs
->group_desc_count
- 1,
134 EXT2_BG_BLOCK_UNINIT
);
136 *new_size
= ext2fs_blocks_count(rfs
->new_fs
->super
);
138 init_resource_track(&rtrack
, "blocks_to_move", fs
->io
);
139 retval
= blocks_to_move(rfs
);
142 print_resource_track(rfs
, &rtrack
, fs
->io
);
144 #ifdef RESIZE2FS_DEBUG
145 if (rfs
->flags
& RESIZE_DEBUG_BMOVE
)
146 printf("Number of free blocks: %llu/%llu, Needed: %llu\n",
147 ext2fs_free_blocks_count(rfs
->old_fs
->super
),
148 ext2fs_free_blocks_count(rfs
->new_fs
->super
),
152 init_resource_track(&rtrack
, "block_mover", fs
->io
);
153 retval
= block_mover(rfs
);
156 print_resource_track(rfs
, &rtrack
, fs
->io
);
158 init_resource_track(&rtrack
, "inode_scan_and_fix", fs
->io
);
159 retval
= inode_scan_and_fix(rfs
);
162 print_resource_track(rfs
, &rtrack
, fs
->io
);
164 init_resource_track(&rtrack
, "inode_ref_fix", fs
->io
);
165 retval
= inode_ref_fix(rfs
);
168 print_resource_track(rfs
, &rtrack
, fs
->io
);
170 init_resource_track(&rtrack
, "move_itables", fs
->io
);
171 retval
= move_itables(rfs
);
174 print_resource_track(rfs
, &rtrack
, fs
->io
);
176 init_resource_track(&rtrack
, "calculate_summary_stats", fs
->io
);
177 retval
= ext2fs_calculate_summary_stats(rfs
->new_fs
);
180 print_resource_track(rfs
, &rtrack
, fs
->io
);
182 init_resource_track(&rtrack
, "fix_resize_inode", fs
->io
);
183 retval
= fix_resize_inode(rfs
->new_fs
);
186 print_resource_track(rfs
, &rtrack
, fs
->io
);
188 init_resource_track(&rtrack
, "fix_sb_journal_backup", fs
->io
);
189 retval
= fix_sb_journal_backup(rfs
->new_fs
);
192 print_resource_track(rfs
, &rtrack
, fs
->io
);
194 rfs
->new_fs
->super
->s_state
&= ~EXT2_ERROR_FS
;
195 rfs
->new_fs
->flags
&= ~EXT2_FLAG_MASTER_SB_ONLY
;
197 print_resource_track(rfs
, &overall_track
, fs
->io
);
198 retval
= ext2fs_close(rfs
->new_fs
);
204 ext2fs_free(rfs
->old_fs
);
206 ext2fs_free_mem(&rfs
->itable_buf
);
207 if (rfs
->reserve_blocks
)
208 ext2fs_free_block_bitmap(rfs
->reserve_blocks
);
209 if (rfs
->move_blocks
)
210 ext2fs_free_block_bitmap(rfs
->move_blocks
);
211 ext2fs_free_mem(&rfs
);
217 ext2fs_free(rfs
->new_fs
);
219 ext2fs_free_mem(&rfs
->itable_buf
);
220 ext2fs_free_mem(&rfs
);
225 * Clean up the bitmaps for unitialized bitmaps
227 static void fix_uninit_block_bitmaps(ext2_filsys fs
)
233 if (!ext2fs_has_group_desc_csum(fs
))
236 for (g
=0; g
< fs
->group_desc_count
; g
++) {
237 if (!(ext2fs_bg_flags_test(fs
, g
, EXT2_BG_BLOCK_UNINIT
)))
240 blk
= ext2fs_group_first_block2(fs
, g
);
241 lblk
= ext2fs_group_last_block2(fs
, g
);
242 ext2fs_unmark_block_bitmap_range2(fs
->block_map
, blk
,
245 ext2fs_reserve_super_and_bgd(fs
, g
, fs
->block_map
);
246 ext2fs_mark_block_bitmap2(fs
->block_map
,
247 ext2fs_block_bitmap_loc(fs
, g
));
248 ext2fs_mark_block_bitmap2(fs
->block_map
,
249 ext2fs_inode_bitmap_loc(fs
, g
));
250 for (i
= 0, blk
= ext2fs_inode_table_loc(fs
, g
);
251 i
< (unsigned int) fs
->inode_blocks_per_group
;
253 ext2fs_mark_block_bitmap2(fs
->block_map
, blk
);
257 /* --------------------------------------------------------------------
259 * Resize processing, phase 1.
261 * In this phase we adjust the in-memory superblock information, and
262 * initialize any new parts of the inode table. The new parts of the
263 * inode table are created in virgin disk space, so we can abort here
264 * without any side effects.
265 * --------------------------------------------------------------------
269 * If the group descriptor's bitmap and inode table blocks are valid,
270 * release them in the new filesystem data structure, and mark them as
271 * reserved so the old inode table blocks don't get overwritten.
273 static void free_gdp_blocks(ext2_filsys fs
,
274 ext2fs_block_bitmap reserve_blocks
,
281 blk
= ext2fs_block_bitmap_loc(old_fs
, group
);
283 (blk
< ext2fs_blocks_count(fs
->super
))) {
284 ext2fs_block_alloc_stats2(fs
, blk
, -1);
285 ext2fs_mark_block_bitmap2(reserve_blocks
, blk
);
288 blk
= ext2fs_inode_bitmap_loc(old_fs
, group
);
290 (blk
< ext2fs_blocks_count(fs
->super
))) {
291 ext2fs_block_alloc_stats2(fs
, blk
, -1);
292 ext2fs_mark_block_bitmap2(reserve_blocks
, blk
);
295 blk
= ext2fs_inode_table_loc(old_fs
, group
);
297 (blk
>= ext2fs_blocks_count(fs
->super
)))
301 j
< fs
->inode_blocks_per_group
; j
++, blk
++) {
302 if (blk
>= ext2fs_blocks_count(fs
->super
))
304 ext2fs_block_alloc_stats2(fs
, blk
, -1);
305 ext2fs_mark_block_bitmap2(reserve_blocks
, blk
);
310 * This routine is shared by the online and offline resize routines.
311 * All of the information which is adjusted in memory is done here.
313 errcode_t
adjust_fs_info(ext2_filsys fs
, ext2_filsys old_fs
,
314 ext2fs_block_bitmap reserve_blocks
, blk64_t new_size
)
317 blk64_t overhead
= 0;
319 blk64_t blk
, group_block
;
321 blk64_t old_numblocks
, numblocks
, adjblocks
;
322 unsigned long i
, j
, old_desc_blocks
;
323 unsigned int meta_bg
, meta_bg_size
;
324 int has_super
, csum_flag
;
325 unsigned long long new_inodes
; /* u64 to check for overflow */
328 ext2fs_blocks_count_set(fs
->super
, new_size
);
331 fs
->group_desc_count
= ext2fs_div64_ceil(ext2fs_blocks_count(fs
->super
) -
332 fs
->super
->s_first_data_block
,
333 EXT2_BLOCKS_PER_GROUP(fs
->super
));
334 if (fs
->group_desc_count
== 0)
335 return EXT2_ET_TOOSMALL
;
336 fs
->desc_blocks
= ext2fs_div_ceil(fs
->group_desc_count
,
337 EXT2_DESC_PER_BLOCK(fs
->super
));
340 * Overhead is the number of bookkeeping blocks per group. It
341 * includes the superblock backup, the group descriptor
342 * backups, the inode bitmap, the block bitmap, and the inode
345 overhead
= (int) (2 + fs
->inode_blocks_per_group
);
347 if (ext2fs_bg_has_super(fs
, fs
->group_desc_count
- 1))
348 overhead
+= 1 + fs
->desc_blocks
+
349 fs
->super
->s_reserved_gdt_blocks
;
352 * See if the last group is big enough to support the
353 * necessary data structures. If not, we need to get rid of
356 rem
= (ext2fs_blocks_count(fs
->super
) - fs
->super
->s_first_data_block
) %
357 fs
->super
->s_blocks_per_group
;
358 if ((fs
->group_desc_count
== 1) && rem
&& (rem
< overhead
))
359 return EXT2_ET_TOOSMALL
;
360 if ((fs
->group_desc_count
> 1) && rem
&& (rem
< overhead
+50)) {
361 ext2fs_blocks_count_set(fs
->super
,
362 ext2fs_blocks_count(fs
->super
) - rem
);
366 * Adjust the number of inodes
368 new_inodes
=(unsigned long long) fs
->super
->s_inodes_per_group
* fs
->group_desc_count
;
369 if (new_inodes
> ~0U) {
370 fprintf(stderr
, _("inodes (%llu) must be less than %u"),
372 return EXT2_ET_TOO_MANY_INODES
;
374 fs
->super
->s_inodes_count
= fs
->super
->s_inodes_per_group
*
375 fs
->group_desc_count
;
378 * Adjust the number of free blocks
380 blk
= ext2fs_blocks_count(old_fs
->super
);
381 if (blk
> ext2fs_blocks_count(fs
->super
))
382 ext2fs_free_blocks_count_set(fs
->super
,
383 ext2fs_free_blocks_count(fs
->super
) -
384 (blk
- ext2fs_blocks_count(fs
->super
)));
386 ext2fs_free_blocks_count_set(fs
->super
,
387 ext2fs_free_blocks_count(fs
->super
) +
388 (ext2fs_blocks_count(fs
->super
) - blk
));
391 * Adjust the number of reserved blocks
393 percent
= (ext2fs_r_blocks_count(old_fs
->super
) * 100.0) /
394 ext2fs_blocks_count(old_fs
->super
);
395 ext2fs_r_blocks_count_set(fs
->super
,
396 (percent
* ext2fs_blocks_count(fs
->super
) /
400 * Adjust the bitmaps for size
402 retval
= ext2fs_resize_inode_bitmap2(fs
->super
->s_inodes_count
,
403 fs
->super
->s_inodes_count
,
405 if (retval
) goto errout
;
407 real_end
= (((blk64_t
) EXT2_BLOCKS_PER_GROUP(fs
->super
) *
408 fs
->group_desc_count
)) - 1 +
409 fs
->super
->s_first_data_block
;
410 retval
= ext2fs_resize_block_bitmap2(new_size
- 1,
411 real_end
, fs
->block_map
);
412 if (retval
) goto errout
;
415 * If we are growing the file system, also grow the size of
416 * the reserve_blocks bitmap
418 if (reserve_blocks
&& new_size
> ext2fs_blocks_count(old_fs
->super
)) {
419 retval
= ext2fs_resize_block_bitmap2(new_size
- 1,
420 real_end
, reserve_blocks
);
421 if (retval
) goto errout
;
425 * Reallocate the group descriptors as necessary.
427 if (old_fs
->desc_blocks
!= fs
->desc_blocks
) {
428 retval
= ext2fs_resize_mem(old_fs
->desc_blocks
*
430 fs
->desc_blocks
* fs
->blocksize
,
434 if (fs
->desc_blocks
> old_fs
->desc_blocks
)
435 memset((char *) fs
->group_desc
+
436 (old_fs
->desc_blocks
* fs
->blocksize
), 0,
437 (fs
->desc_blocks
- old_fs
->desc_blocks
) *
442 * If the resize_inode feature is set, and we are changing the
443 * number of descriptor blocks, then adjust
444 * s_reserved_gdt_blocks if possible to avoid needing to move
445 * the inode table either now or in the future.
447 if ((fs
->super
->s_feature_compat
&
448 EXT2_FEATURE_COMPAT_RESIZE_INODE
) &&
449 (old_fs
->desc_blocks
!= fs
->desc_blocks
)) {
452 new = ((int) fs
->super
->s_reserved_gdt_blocks
) +
453 (old_fs
->desc_blocks
- fs
->desc_blocks
);
456 if (new > (int) fs
->blocksize
/4)
457 new = fs
->blocksize
/4;
458 fs
->super
->s_reserved_gdt_blocks
= new;
462 * If we are shrinking the number of block groups, we're done
465 if (old_fs
->group_desc_count
> fs
->group_desc_count
) {
467 * Check the block groups that we are chopping off
468 * and free any blocks associated with their metadata
470 for (i
= fs
->group_desc_count
;
471 i
< old_fs
->group_desc_count
; i
++)
472 free_gdp_blocks(fs
, reserve_blocks
, old_fs
, i
);
478 * Fix the count of the last (old) block group
480 old_numblocks
= (ext2fs_blocks_count(old_fs
->super
) -
481 old_fs
->super
->s_first_data_block
) %
482 old_fs
->super
->s_blocks_per_group
;
484 old_numblocks
= old_fs
->super
->s_blocks_per_group
;
485 if (old_fs
->group_desc_count
== fs
->group_desc_count
) {
486 numblocks
= (ext2fs_blocks_count(fs
->super
) -
487 fs
->super
->s_first_data_block
) %
488 fs
->super
->s_blocks_per_group
;
490 numblocks
= fs
->super
->s_blocks_per_group
;
492 numblocks
= fs
->super
->s_blocks_per_group
;
493 i
= old_fs
->group_desc_count
- 1;
494 ext2fs_bg_free_blocks_count_set(fs
, i
, ext2fs_bg_free_blocks_count(fs
, i
) + (numblocks
- old_numblocks
));
495 ext2fs_group_desc_csum_set(fs
, i
);
498 * If the number of block groups is staying the same, we're
499 * done and can exit now. (If the number block groups is
500 * shrinking, we had exited earlier.)
502 if (old_fs
->group_desc_count
>= fs
->group_desc_count
) {
508 * Initialize the new block group descriptors
510 group_block
= ext2fs_group_first_block2(fs
,
511 old_fs
->group_desc_count
);
512 csum_flag
= ext2fs_has_group_desc_csum(fs
);
513 if (access("/sys/fs/ext4/features/lazy_itable_init", F_OK
) == 0)
514 lazy_itable_init
= 1;
515 if (fs
->super
->s_feature_incompat
& EXT2_FEATURE_INCOMPAT_META_BG
)
516 old_desc_blocks
= fs
->super
->s_first_meta_bg
;
518 old_desc_blocks
= fs
->desc_blocks
+
519 fs
->super
->s_reserved_gdt_blocks
;
522 * If we changed the number of block_group descriptor blocks,
523 * we need to make sure they are all marked as reserved in the
524 * file systems's block allocation map.
526 for (i
= 0; i
< old_fs
->group_desc_count
; i
++)
527 ext2fs_reserve_super_and_bgd(fs
, i
, fs
->block_map
);
529 for (i
= old_fs
->group_desc_count
;
530 i
< fs
->group_desc_count
; i
++) {
531 memset(ext2fs_group_desc(fs
, fs
->group_desc
, i
), 0,
532 sizeof(struct ext2_group_desc
));
535 ext2fs_bg_flags_zap(fs
, i
);
537 ext2fs_bg_flags_set(fs
, i
, EXT2_BG_INODE_UNINIT
);
538 if (!lazy_itable_init
)
539 ext2fs_bg_flags_set(fs
, i
,
540 EXT2_BG_INODE_ZEROED
);
541 ext2fs_bg_itable_unused_set(fs
, i
,
542 fs
->super
->s_inodes_per_group
);
545 numblocks
= ext2fs_group_blocks_count(fs
, i
);
546 if ((i
< fs
->group_desc_count
- 1) && csum_flag
)
547 ext2fs_bg_flags_set(fs
, i
, EXT2_BG_BLOCK_UNINIT
);
549 has_super
= ext2fs_bg_has_super(fs
, i
);
551 ext2fs_block_alloc_stats2(fs
, group_block
, +1);
554 meta_bg_size
= EXT2_DESC_PER_BLOCK(fs
->super
);
555 meta_bg
= i
/ meta_bg_size
;
556 if (!(fs
->super
->s_feature_incompat
&
557 EXT2_FEATURE_INCOMPAT_META_BG
) ||
558 (meta_bg
< fs
->super
->s_first_meta_bg
)) {
560 for (j
=0; j
< old_desc_blocks
; j
++)
561 ext2fs_block_alloc_stats2(fs
,
562 group_block
+ 1 + j
, +1);
563 adjblocks
+= old_desc_blocks
;
568 if (((i
% meta_bg_size
) == 0) ||
569 ((i
% meta_bg_size
) == 1) ||
570 ((i
% meta_bg_size
) == (meta_bg_size
-1)))
571 ext2fs_block_alloc_stats2(fs
,
572 group_block
+ has_super
, +1);
575 adjblocks
+= 2 + fs
->inode_blocks_per_group
;
577 numblocks
-= adjblocks
;
578 ext2fs_free_blocks_count_set(fs
->super
,
579 ext2fs_free_blocks_count(fs
->super
) - adjblocks
);
580 fs
->super
->s_free_inodes_count
+=
581 fs
->super
->s_inodes_per_group
;
582 ext2fs_bg_free_blocks_count_set(fs
, i
, numblocks
);
583 ext2fs_bg_free_inodes_count_set(fs
, i
,
584 fs
->super
->s_inodes_per_group
);
585 ext2fs_bg_used_dirs_count_set(fs
, i
, 0);
586 ext2fs_group_desc_csum_set(fs
, i
);
588 retval
= ext2fs_allocate_group_table(fs
, i
, 0);
589 if (retval
) goto errout
;
591 group_block
+= fs
->super
->s_blocks_per_group
;
596 * Mark all of the metadata blocks as reserved so they won't
597 * get allocated by the call to ext2fs_allocate_group_table()
598 * in blocks_to_move(), where we allocate new blocks to
599 * replace those allocation bitmap and inode table blocks
600 * which have to get relocated to make space for an increased
601 * number of the block group descriptors.
604 mark_table_blocks(fs
, reserve_blocks
);
611 * This routine adjusts the superblock and other data structures, both
612 * in disk as well as in memory...
614 static errcode_t
adjust_superblock(ext2_resize_t rfs
, blk64_t new_size
)
621 unsigned long max_group
;
624 ext2fs_mark_super_dirty(fs
);
625 ext2fs_mark_bb_dirty(fs
);
626 ext2fs_mark_ib_dirty(fs
);
628 retval
= ext2fs_allocate_block_bitmap(fs
, _("reserved blocks"),
629 &rfs
->reserve_blocks
);
633 retval
= adjust_fs_info(fs
, rfs
->old_fs
, rfs
->reserve_blocks
, new_size
);
638 * Check to make sure there are enough inodes
640 if ((rfs
->old_fs
->super
->s_inodes_count
-
641 rfs
->old_fs
->super
->s_free_inodes_count
) >
642 rfs
->new_fs
->super
->s_inodes_count
) {
648 * If we are shrinking the number block groups, we're done and
651 if (rfs
->old_fs
->group_desc_count
> fs
->group_desc_count
) {
657 * If the number of block groups is staying the same, we're
658 * done and can exit now. (If the number block groups is
659 * shrinking, we had exited earlier.)
661 if (rfs
->old_fs
->group_desc_count
>= fs
->group_desc_count
) {
667 * If we are using uninit_bg (aka GDT_CSUM) and the kernel
668 * supports lazy inode initialization, we can skip
669 * initializing the inode table.
671 if (lazy_itable_init
&&
672 EXT2_HAS_RO_COMPAT_FEATURE(fs
->super
,
673 EXT4_FEATURE_RO_COMPAT_GDT_CSUM
)) {
679 * Initialize the inode table
681 retval
= ext2fs_get_array(fs
->blocksize
, fs
->inode_blocks_per_group
,
686 memset(rfs
->itable_buf
, 0, fs
->blocksize
* fs
->inode_blocks_per_group
);
687 group_block
= ext2fs_group_first_block2(fs
,
688 rfs
->old_fs
->group_desc_count
);
689 adj
= rfs
->old_fs
->group_desc_count
;
690 max_group
= fs
->group_desc_count
- adj
;
692 retval
= rfs
->progress(rfs
, E2_RSZ_EXTEND_ITABLE_PASS
,
697 for (i
= rfs
->old_fs
->group_desc_count
;
698 i
< fs
->group_desc_count
; i
++) {
700 * Write out the new inode table
702 retval
= io_channel_write_blk64(fs
->io
,
703 ext2fs_inode_table_loc(fs
, i
),
704 fs
->inode_blocks_per_group
,
706 if (retval
) goto errout
;
708 io_channel_flush(fs
->io
);
710 retval
= rfs
->progress(rfs
, E2_RSZ_EXTEND_ITABLE_PASS
,
711 i
- adj
+ 1, max_group
);
715 group_block
+= fs
->super
->s_blocks_per_group
;
717 io_channel_flush(fs
->io
);
724 /* --------------------------------------------------------------------
726 * Resize processing, phase 2.
728 * In this phase we adjust determine which blocks need to be moved, in
729 * blocks_to_move(). We then copy the blocks to their ultimate new
730 * destinations using block_mover(). Since we are copying blocks to
731 * their new locations, again during this pass we can abort without
733 * --------------------------------------------------------------------
737 * This helper function creates a block bitmap with all of the
738 * filesystem meta-data blocks.
740 static errcode_t
mark_table_blocks(ext2_filsys fs
,
741 ext2fs_block_bitmap bmap
)
746 for (i
= 0; i
< fs
->group_desc_count
; i
++) {
747 ext2fs_reserve_super_and_bgd(fs
, i
, bmap
);
750 * Mark the blocks used for the inode table
752 blk
= ext2fs_inode_table_loc(fs
, i
);
754 ext2fs_mark_block_bitmap_range2(bmap
, blk
,
755 fs
->inode_blocks_per_group
);
758 * Mark block used for the block bitmap
760 blk
= ext2fs_block_bitmap_loc(fs
, i
);
762 ext2fs_mark_block_bitmap2(bmap
, blk
);
765 * Mark block used for the inode bitmap
767 blk
= ext2fs_inode_bitmap_loc(fs
, i
);
769 ext2fs_mark_block_bitmap2(bmap
, blk
);
775 * This function checks to see if a particular block (either a
776 * superblock or a block group descriptor) overlaps with an inode or
777 * block bitmap block, or with the inode table.
779 static void mark_fs_metablock(ext2_resize_t rfs
,
780 ext2fs_block_bitmap meta_bmap
,
781 int group
, blk64_t blk
)
783 ext2_filsys fs
= rfs
->new_fs
;
785 ext2fs_mark_block_bitmap2(rfs
->reserve_blocks
, blk
);
786 ext2fs_block_alloc_stats2(fs
, blk
, +1);
789 * Check to see if we overlap with the inode or block bitmap,
790 * or the inode tables. If not, and the block is in use, then
791 * mark it as a block to be moved.
793 if (IS_BLOCK_BM(fs
, group
, blk
)) {
794 ext2fs_block_bitmap_loc_set(fs
, group
, 0);
795 rfs
->needed_blocks
++;
798 if (IS_INODE_BM(fs
, group
, blk
)) {
799 ext2fs_inode_bitmap_loc_set(fs
, group
, 0);
800 rfs
->needed_blocks
++;
803 if (IS_INODE_TB(fs
, group
, blk
)) {
804 ext2fs_inode_table_loc_set(fs
, group
, 0);
805 rfs
->needed_blocks
++;
808 if (fs
->super
->s_feature_incompat
& EXT4_FEATURE_INCOMPAT_FLEX_BG
) {
811 for (i
=0; i
< rfs
->old_fs
->group_desc_count
; i
++) {
812 if (IS_BLOCK_BM(fs
, i
, blk
)) {
813 ext2fs_block_bitmap_loc_set(fs
, i
, 0);
814 rfs
->needed_blocks
++;
817 if (IS_INODE_BM(fs
, i
, blk
)) {
818 ext2fs_inode_bitmap_loc_set(fs
, i
, 0);
819 rfs
->needed_blocks
++;
822 if (IS_INODE_TB(fs
, i
, blk
)) {
823 ext2fs_inode_table_loc_set(fs
, i
, 0);
824 rfs
->needed_blocks
++;
830 if (ext2fs_has_group_desc_csum(fs
) &&
831 (ext2fs_bg_flags_test(fs
, group
, EXT2_BG_BLOCK_UNINIT
))) {
833 * If the block bitmap is uninitialized, which means
834 * nothing other than standard metadata in use.
837 } else if (ext2fs_test_block_bitmap2(rfs
->old_fs
->block_map
, blk
) &&
838 !ext2fs_test_block_bitmap2(meta_bmap
, blk
)) {
839 ext2fs_mark_block_bitmap2(rfs
->move_blocks
, blk
);
840 rfs
->needed_blocks
++;
846 * This routine marks and unmarks reserved blocks in the new block
847 * bitmap. It also determines which blocks need to be moved and
848 * places this information into the move_blocks bitmap.
850 static errcode_t
blocks_to_move(ext2_resize_t rfs
)
853 dgrp_t i
, max_groups
, g
;
854 blk64_t blk
, group_blk
;
855 blk64_t old_blocks
, new_blocks
;
857 unsigned int meta_bg
, meta_bg_size
;
859 ext2_filsys fs
, old_fs
;
860 ext2fs_block_bitmap meta_bmap
;
864 old_fs
= rfs
->old_fs
;
865 if (ext2fs_blocks_count(old_fs
->super
) > ext2fs_blocks_count(fs
->super
))
868 retval
= ext2fs_allocate_block_bitmap(fs
, _("blocks to be moved"),
873 retval
= ext2fs_allocate_block_bitmap(fs
, _("meta-data blocks"),
878 retval
= mark_table_blocks(old_fs
, meta_bmap
);
885 * If we're shrinking the filesystem, we need to move any
886 * group's metadata blocks (either allocation bitmaps or the
887 * inode table) which are beyond the end of the new
890 new_size
= ext2fs_blocks_count(fs
->super
);
891 if (new_size
< ext2fs_blocks_count(old_fs
->super
)) {
892 for (g
= 0; g
< fs
->group_desc_count
; g
++) {
895 * ext2fs_allocate_group_table will re-allocate any
896 * metadata blocks whose location is set to zero.
898 if (ext2fs_block_bitmap_loc(fs
, g
) >= new_size
) {
899 ext2fs_block_bitmap_loc_set(fs
, g
, 0);
902 if (ext2fs_inode_bitmap_loc(fs
, g
) >= new_size
) {
903 ext2fs_inode_bitmap_loc_set(fs
, g
, 0);
906 if ((ext2fs_inode_table_loc(fs
, g
) +
907 fs
->inode_blocks_per_group
) > new_size
) {
908 ext2fs_inode_table_loc_set(fs
, g
, 0);
913 retval
= ext2fs_allocate_group_table(fs
, g
, 0);
921 * If we're shrinking the filesystem, we need to move all of
922 * the blocks that don't fit any more
924 for (blk
= ext2fs_blocks_count(fs
->super
);
925 blk
< ext2fs_blocks_count(old_fs
->super
); blk
++) {
926 g
= ext2fs_group_of_blk2(fs
, blk
);
927 if (ext2fs_has_group_desc_csum(fs
) &&
928 ext2fs_bg_flags_test(old_fs
, g
, EXT2_BG_BLOCK_UNINIT
)) {
930 * The block bitmap is uninitialized, so skip
931 * to the next block group.
933 blk
= ext2fs_group_first_block2(fs
, g
+1) - 1;
936 if (ext2fs_test_block_bitmap2(old_fs
->block_map
, blk
) &&
937 !ext2fs_test_block_bitmap2(meta_bmap
, blk
)) {
938 ext2fs_mark_block_bitmap2(rfs
->move_blocks
, blk
);
939 rfs
->needed_blocks
++;
941 ext2fs_mark_block_bitmap2(rfs
->reserve_blocks
, blk
);
944 if (fs
->super
->s_feature_incompat
& EXT2_FEATURE_INCOMPAT_META_BG
) {
945 old_blocks
= old_fs
->super
->s_first_meta_bg
;
946 new_blocks
= fs
->super
->s_first_meta_bg
;
948 old_blocks
= old_fs
->desc_blocks
+ old_fs
->super
->s_reserved_gdt_blocks
;
949 new_blocks
= fs
->desc_blocks
+ fs
->super
->s_reserved_gdt_blocks
;
952 if (old_blocks
== new_blocks
) {
957 max_groups
= fs
->group_desc_count
;
958 if (max_groups
> old_fs
->group_desc_count
)
959 max_groups
= old_fs
->group_desc_count
;
960 group_blk
= old_fs
->super
->s_first_data_block
;
962 * If we're reducing the number of descriptor blocks, this
963 * makes life easy. :-) We just have to mark some extra
966 if (old_blocks
> new_blocks
) {
967 for (i
= 0; i
< max_groups
; i
++) {
968 if (!ext2fs_bg_has_super(fs
, i
)) {
969 group_blk
+= fs
->super
->s_blocks_per_group
;
972 for (blk
= group_blk
+1+new_blocks
;
973 blk
< group_blk
+1+old_blocks
; blk
++) {
974 ext2fs_block_alloc_stats2(fs
, blk
, -1);
975 rfs
->needed_blocks
--;
977 group_blk
+= fs
->super
->s_blocks_per_group
;
983 * If we're increasing the number of descriptor blocks, life
984 * gets interesting....
986 meta_bg_size
= EXT2_DESC_PER_BLOCK(fs
->super
);
987 flex_bg
= fs
->super
->s_feature_incompat
&
988 EXT4_FEATURE_INCOMPAT_FLEX_BG
;
989 /* first reserve all of the existing fs meta blocks */
990 for (i
= 0; i
< max_groups
; i
++) {
991 has_super
= ext2fs_bg_has_super(fs
, i
);
993 mark_fs_metablock(rfs
, meta_bmap
, i
, group_blk
);
995 meta_bg
= i
/ meta_bg_size
;
996 if (!(fs
->super
->s_feature_incompat
&
997 EXT2_FEATURE_INCOMPAT_META_BG
) ||
998 (meta_bg
< fs
->super
->s_first_meta_bg
)) {
1000 for (blk
= group_blk
+1;
1001 blk
< group_blk
+ 1 + new_blocks
; blk
++)
1002 mark_fs_metablock(rfs
, meta_bmap
,
1008 if (((i
% meta_bg_size
) == 0) ||
1009 ((i
% meta_bg_size
) == 1) ||
1010 ((i
% meta_bg_size
) == (meta_bg_size
-1)))
1011 mark_fs_metablock(rfs
, meta_bmap
, i
,
1012 group_blk
+ has_super
);
1016 * Reserve the existing meta blocks that we know
1017 * aren't to be moved.
1019 * For flex_bg file systems, in order to avoid
1020 * overwriting fs metadata (especially inode table
1021 * blocks) belonging to a different block group when
1022 * we are relocating the inode tables, we need to
1023 * reserve all existing fs metadata blocks.
1025 if (ext2fs_block_bitmap_loc(fs
, i
))
1026 ext2fs_mark_block_bitmap2(rfs
->reserve_blocks
,
1027 ext2fs_block_bitmap_loc(fs
, i
));
1028 else if (flex_bg
&& i
< old_fs
->group_desc_count
)
1029 ext2fs_mark_block_bitmap2(rfs
->reserve_blocks
,
1030 ext2fs_block_bitmap_loc(old_fs
, i
));
1032 if (ext2fs_inode_bitmap_loc(fs
, i
))
1033 ext2fs_mark_block_bitmap2(rfs
->reserve_blocks
,
1034 ext2fs_inode_bitmap_loc(fs
, i
));
1035 else if (flex_bg
&& i
< old_fs
->group_desc_count
)
1036 ext2fs_mark_block_bitmap2(rfs
->reserve_blocks
,
1037 ext2fs_inode_bitmap_loc(old_fs
, i
));
1039 if (ext2fs_inode_table_loc(fs
, i
))
1040 ext2fs_mark_block_bitmap_range2(rfs
->reserve_blocks
,
1041 ext2fs_inode_table_loc(fs
, i
),
1042 fs
->inode_blocks_per_group
);
1043 else if (flex_bg
&& i
< old_fs
->group_desc_count
)
1044 ext2fs_mark_block_bitmap_range2(rfs
->reserve_blocks
,
1045 ext2fs_inode_table_loc(old_fs
, i
),
1046 old_fs
->inode_blocks_per_group
);
1048 group_blk
+= rfs
->new_fs
->super
->s_blocks_per_group
;
1051 /* Allocate the missing data structures */
1052 for (i
= 0; i
< max_groups
; i
++) {
1053 if (ext2fs_inode_table_loc(fs
, i
) &&
1054 ext2fs_inode_bitmap_loc(fs
, i
) &&
1055 ext2fs_block_bitmap_loc(fs
, i
))
1058 retval
= ext2fs_allocate_group_table(fs
, i
,
1059 rfs
->reserve_blocks
);
1064 * For those structures that have changed, we need to
1067 if (ext2fs_block_bitmap_loc(old_fs
, i
) !=
1068 (blk
= ext2fs_block_bitmap_loc(fs
, i
))) {
1069 ext2fs_block_alloc_stats2(fs
, blk
, +1);
1070 if (ext2fs_test_block_bitmap2(old_fs
->block_map
, blk
) &&
1071 !ext2fs_test_block_bitmap2(meta_bmap
, blk
))
1072 ext2fs_mark_block_bitmap2(rfs
->move_blocks
,
1075 if (ext2fs_inode_bitmap_loc(old_fs
, i
) !=
1076 (blk
= ext2fs_inode_bitmap_loc(fs
, i
))) {
1077 ext2fs_block_alloc_stats2(fs
, blk
, +1);
1078 if (ext2fs_test_block_bitmap2(old_fs
->block_map
, blk
) &&
1079 !ext2fs_test_block_bitmap2(meta_bmap
, blk
))
1080 ext2fs_mark_block_bitmap2(rfs
->move_blocks
,
1085 * The inode table, if we need to relocate it, is
1086 * handled specially. We have to reserve the blocks
1087 * for both the old and the new inode table, since we
1088 * can't have the inode table be destroyed during the
1089 * block relocation phase.
1091 if (ext2fs_inode_table_loc(fs
, i
) == ext2fs_inode_table_loc(old_fs
, i
))
1092 continue; /* inode table not moved */
1094 rfs
->needed_blocks
+= fs
->inode_blocks_per_group
;
1097 * Mark the new inode table as in use in the new block
1098 * allocation bitmap, and move any blocks that might
1101 for (blk
= ext2fs_inode_table_loc(fs
, i
), j
=0;
1102 j
< fs
->inode_blocks_per_group
; j
++, blk
++) {
1103 ext2fs_block_alloc_stats2(fs
, blk
, +1);
1104 if (ext2fs_test_block_bitmap2(old_fs
->block_map
, blk
) &&
1105 !ext2fs_test_block_bitmap2(meta_bmap
, blk
))
1106 ext2fs_mark_block_bitmap2(rfs
->move_blocks
,
1111 * Make sure the old inode table is reserved in the
1112 * block reservation bitmap.
1114 for (blk
= ext2fs_inode_table_loc(rfs
->old_fs
, i
), j
=0;
1115 j
< fs
->inode_blocks_per_group
; j
++, blk
++)
1116 ext2fs_mark_block_bitmap2(rfs
->reserve_blocks
, blk
);
1122 ext2fs_free_block_bitmap(meta_bmap
);
1128 * This helper function tries to allocate a new block. We try to
1129 * avoid hitting the original group descriptor blocks at least at
1130 * first, since we want to make it possible to recover from a badly
1131 * aborted resize operation as much as possible.
1133 * In the future, I may further modify this routine to balance out
1134 * where we get the new blocks across the various block groups.
1135 * Ideally we would allocate blocks that corresponded with the block
1136 * group of the containing inode, and keep contiguous blocks
1137 * together. However, this very difficult to do efficiently, since we
1138 * don't have the necessary information up front.
1142 #define DESPERATION 2
1144 static void init_block_alloc(ext2_resize_t rfs
)
1146 rfs
->alloc_state
= AVOID_OLD
;
1147 rfs
->new_blk
= rfs
->new_fs
->super
->s_first_data_block
;
1149 /* HACK for testing */
1150 if (ext2fs_blocks_count(rfs
->new_fs
->super
) >
1151 ext2fs_blocks_count(rfs
->old_fs
->super
))
1152 rfs
->new_blk
= ext2fs_blocks_count(rfs
->old_fs
->super
);
1156 static blk64_t
get_new_block(ext2_resize_t rfs
)
1158 ext2_filsys fs
= rfs
->new_fs
;
1161 if (rfs
->new_blk
>= ext2fs_blocks_count(fs
->super
)) {
1162 if (rfs
->alloc_state
== DESPERATION
)
1165 #ifdef RESIZE2FS_DEBUG
1166 if (rfs
->flags
& RESIZE_DEBUG_BMOVE
)
1167 printf("Going into desperation mode "
1168 "for block allocations\n");
1170 rfs
->alloc_state
= DESPERATION
;
1171 rfs
->new_blk
= fs
->super
->s_first_data_block
;
1174 if (ext2fs_test_block_bitmap2(fs
->block_map
, rfs
->new_blk
) ||
1175 ext2fs_test_block_bitmap2(rfs
->reserve_blocks
,
1177 ((rfs
->alloc_state
== AVOID_OLD
) &&
1178 (rfs
->new_blk
< ext2fs_blocks_count(rfs
->old_fs
->super
)) &&
1179 ext2fs_test_block_bitmap2(rfs
->old_fs
->block_map
,
1184 return rfs
->new_blk
;
1188 static errcode_t
resize2fs_get_alloc_block(ext2_filsys fs
, blk64_t goal
,
1191 ext2_resize_t rfs
= (ext2_resize_t
) fs
->priv_data
;
1194 blk
= get_new_block(rfs
);
1198 #ifdef RESIZE2FS_DEBUG
1199 if (rfs
->flags
& 0xF)
1200 printf("get_alloc_block allocating %llu\n", blk
);
1203 ext2fs_mark_block_bitmap2(rfs
->old_fs
->block_map
, blk
);
1204 ext2fs_mark_block_bitmap2(rfs
->new_fs
->block_map
, blk
);
1205 *ret
= (blk64_t
) blk
;
1209 static errcode_t
block_mover(ext2_resize_t rfs
)
1211 blk64_t blk
, old_blk
, new_blk
;
1212 ext2_filsys fs
= rfs
->new_fs
;
1213 ext2_filsys old_fs
= rfs
->old_fs
;
1218 ext2_badblocks_list badblock_list
= 0;
1219 int bb_modified
= 0;
1221 fs
->get_alloc_block
= resize2fs_get_alloc_block
;
1222 old_fs
->get_alloc_block
= resize2fs_get_alloc_block
;
1224 retval
= ext2fs_read_bb_inode(old_fs
, &badblock_list
);
1228 new_blk
= fs
->super
->s_first_data_block
;
1229 if (!rfs
->itable_buf
) {
1230 retval
= ext2fs_get_array(fs
->blocksize
,
1231 fs
->inode_blocks_per_group
,
1236 retval
= ext2fs_create_extent_table(&rfs
->bmap
, 0);
1241 * The first step is to figure out where all of the blocks
1244 to_move
= moved
= 0;
1245 init_block_alloc(rfs
);
1246 for (blk
= B2C(old_fs
->super
->s_first_data_block
);
1247 blk
< ext2fs_blocks_count(old_fs
->super
);
1248 blk
+= EXT2FS_CLUSTER_RATIO(fs
)) {
1249 if (!ext2fs_test_block_bitmap2(old_fs
->block_map
, blk
))
1251 if (!ext2fs_test_block_bitmap2(rfs
->move_blocks
, blk
))
1253 if (ext2fs_badblocks_list_test(badblock_list
, blk
)) {
1254 ext2fs_badblocks_list_del(badblock_list
, blk
);
1259 new_blk
= get_new_block(rfs
);
1264 ext2fs_block_alloc_stats2(fs
, new_blk
, +1);
1265 ext2fs_add_extent_entry(rfs
->bmap
, B2C(blk
), B2C(new_blk
));
1271 ext2fs_free_extent_table(rfs
->bmap
);
1279 * Step two is to actually move the blocks
1281 retval
= ext2fs_iterate_extent(rfs
->bmap
, 0, 0, 0);
1282 if (retval
) goto errout
;
1284 if (rfs
->progress
) {
1285 retval
= (rfs
->progress
)(rfs
, E2_RSZ_BLOCK_RELOC_PASS
,
1291 retval
= ext2fs_iterate_extent(rfs
->bmap
, &old_blk
, &new_blk
, &size
);
1292 if (retval
) goto errout
;
1295 old_blk
= C2B(old_blk
);
1296 new_blk
= C2B(new_blk
);
1298 #ifdef RESIZE2FS_DEBUG
1299 if (rfs
->flags
& RESIZE_DEBUG_BMOVE
)
1300 printf("Moving %llu blocks %llu->%llu\n",
1301 size
, old_blk
, new_blk
);
1305 if (c
> fs
->inode_blocks_per_group
)
1306 c
= fs
->inode_blocks_per_group
;
1307 retval
= io_channel_read_blk64(fs
->io
, old_blk
, c
,
1309 if (retval
) goto errout
;
1310 retval
= io_channel_write_blk64(fs
->io
, new_blk
, c
,
1312 if (retval
) goto errout
;
1317 if (rfs
->progress
) {
1318 io_channel_flush(fs
->io
);
1319 retval
= (rfs
->progress
)(rfs
,
1320 E2_RSZ_BLOCK_RELOC_PASS
,
1326 io_channel_flush(fs
->io
);
1330 if (badblock_list
) {
1331 if (!retval
&& bb_modified
)
1332 retval
= ext2fs_update_bb_inode(old_fs
,
1334 ext2fs_badblocks_list_free(badblock_list
);
1340 /* --------------------------------------------------------------------
1342 * Resize processing, phase 3
1344 * --------------------------------------------------------------------
1349 * The extent translation table is stored in clusters so we need to
1350 * take special care when mapping a source block number to its
1351 * destination block number.
1353 __u64
extent_translate(ext2_filsys fs
, ext2_extent extent
, __u64 old_loc
)
1355 __u64 new_block
= C2B(ext2fs_extent_translate(extent
, B2C(old_loc
)));
1358 new_block
+= old_loc
& (EXT2FS_CLUSTER_RATIO(fs
) - 1);
1362 struct process_block_struct
{
1365 struct ext2_inode
* inode
;
1371 static int process_block(ext2_filsys fs
, blk64_t
*block_nr
,
1372 e2_blkcnt_t blockcnt
,
1373 blk64_t ref_block
EXT2FS_ATTR((unused
)),
1374 int ref_offset
EXT2FS_ATTR((unused
)), void *priv_data
)
1376 struct process_block_struct
*pb
;
1378 blk64_t block
, new_block
;
1381 pb
= (struct process_block_struct
*) priv_data
;
1383 if (pb
->rfs
->bmap
) {
1384 new_block
= extent_translate(fs
, pb
->rfs
->bmap
, block
);
1386 *block_nr
= new_block
;
1387 ret
|= BLOCK_CHANGED
;
1389 #ifdef RESIZE2FS_DEBUG
1390 if (pb
->rfs
->flags
& RESIZE_DEBUG_BMOVE
)
1391 printf("ino=%u, blockcnt=%lld, %llu->%llu\n",
1392 pb
->ino
, blockcnt
, block
, new_block
);
1398 retval
= ext2fs_add_dir_block2(fs
->dblist
, pb
->ino
,
1399 block
, (int) blockcnt
);
1411 static errcode_t
progress_callback(ext2_filsys fs
,
1412 ext2_inode_scan scan
EXT2FS_ATTR((unused
)),
1413 dgrp_t group
, void * priv_data
)
1415 ext2_resize_t rfs
= (ext2_resize_t
) priv_data
;
1419 * This check is to protect against old ext2 libraries. It
1420 * shouldn't be needed against new libraries.
1425 if (rfs
->progress
) {
1426 io_channel_flush(fs
->io
);
1427 retval
= (rfs
->progress
)(rfs
, E2_RSZ_INODE_SCAN_PASS
,
1428 group
+1, fs
->group_desc_count
);
1436 static errcode_t
inode_scan_and_fix(ext2_resize_t rfs
)
1438 struct process_block_struct pb
;
1439 ext2_ino_t ino
, new_inode
;
1440 struct ext2_inode
*inode
= NULL
;
1441 ext2_inode_scan scan
= NULL
;
1443 char *block_buf
= 0;
1444 ext2_ino_t start_to_move
;
1449 if ((rfs
->old_fs
->group_desc_count
<=
1450 rfs
->new_fs
->group_desc_count
) &&
1455 * Save the original size of the old filesystem, and
1456 * temporarily set the size to be the new size if the new size
1457 * is larger. We need to do this to avoid catching an error
1458 * by the block iterator routines
1460 orig_size
= ext2fs_blocks_count(rfs
->old_fs
->super
);
1461 if (orig_size
< ext2fs_blocks_count(rfs
->new_fs
->super
))
1462 ext2fs_blocks_count_set(rfs
->old_fs
->super
,
1463 ext2fs_blocks_count(rfs
->new_fs
->super
));
1465 retval
= ext2fs_open_inode_scan(rfs
->old_fs
, 0, &scan
);
1466 if (retval
) goto errout
;
1468 retval
= ext2fs_init_dblist(rfs
->old_fs
, 0);
1469 if (retval
) goto errout
;
1470 retval
= ext2fs_get_array(rfs
->old_fs
->blocksize
, 3, &block_buf
);
1471 if (retval
) goto errout
;
1473 start_to_move
= (rfs
->new_fs
->group_desc_count
*
1474 rfs
->new_fs
->super
->s_inodes_per_group
);
1476 if (rfs
->progress
) {
1477 retval
= (rfs
->progress
)(rfs
, E2_RSZ_INODE_SCAN_PASS
,
1478 0, rfs
->old_fs
->group_desc_count
);
1482 ext2fs_set_inode_callback(scan
, progress_callback
, (void *) rfs
);
1486 new_inode
= EXT2_FIRST_INODE(rfs
->new_fs
->super
);
1487 inode_size
= EXT2_INODE_SIZE(rfs
->new_fs
->super
);
1488 inode
= malloc(inode_size
);
1494 * First, copy all of the inodes that need to be moved
1495 * elsewhere in the inode table
1498 retval
= ext2fs_get_next_inode_full(scan
, &ino
, inode
, inode_size
);
1499 if (retval
) goto errout
;
1503 if (inode
->i_links_count
== 0 && ino
!= EXT2_RESIZE_INO
)
1504 continue; /* inode not in use */
1506 pb
.is_dir
= LINUX_S_ISDIR(inode
->i_mode
);
1509 if (ext2fs_file_acl_block(rfs
->old_fs
, inode
) && rfs
->bmap
) {
1510 new_block
= extent_translate(rfs
->old_fs
, rfs
->bmap
,
1511 ext2fs_file_acl_block(rfs
->old_fs
, inode
));
1513 ext2fs_file_acl_block_set(rfs
->old_fs
, inode
,
1515 retval
= ext2fs_write_inode_full(rfs
->old_fs
,
1516 ino
, inode
, inode_size
);
1517 if (retval
) goto errout
;
1521 if (ext2fs_inode_has_valid_blocks2(rfs
->old_fs
, inode
) &&
1522 (rfs
->bmap
|| pb
.is_dir
)) {
1524 retval
= ext2fs_block_iterate3(rfs
->old_fs
,
1526 process_block
, &pb
);
1535 if (ino
<= start_to_move
)
1536 continue; /* Don't need to move it. */
1541 retval
= ext2fs_new_inode(rfs
->new_fs
, 0, 0, 0, &new_inode
);
1545 ext2fs_inode_alloc_stats2(rfs
->new_fs
, new_inode
, +1,
1548 /* Get the new version of the inode */
1549 retval
= ext2fs_read_inode_full(rfs
->old_fs
, ino
,
1551 if (retval
) goto errout
;
1553 inode
->i_ctime
= time(0);
1554 retval
= ext2fs_write_inode_full(rfs
->old_fs
, new_inode
,
1556 if (retval
) goto errout
;
1558 #ifdef RESIZE2FS_DEBUG
1559 if (rfs
->flags
& RESIZE_DEBUG_INODEMAP
)
1560 printf("Inode moved %u->%u\n", ino
, new_inode
);
1563 retval
= ext2fs_create_extent_table(&rfs
->imap
, 0);
1567 ext2fs_add_extent_entry(rfs
->imap
, ino
, new_inode
);
1569 io_channel_flush(rfs
->old_fs
->io
);
1572 ext2fs_blocks_count_set(rfs
->old_fs
->super
, orig_size
);
1574 ext2fs_free_extent_table(rfs
->bmap
);
1578 ext2fs_close_inode_scan(scan
);
1580 ext2fs_free_mem(&block_buf
);
1585 /* --------------------------------------------------------------------
1587 * Resize processing, phase 4.
1589 * --------------------------------------------------------------------
1595 unsigned int max_dirs
;
1599 static int check_and_change_inodes(ext2_ino_t dir
,
1600 int entry
EXT2FS_ATTR((unused
)),
1601 struct ext2_dir_entry
*dirent
, int offset
,
1602 int blocksize
EXT2FS_ATTR((unused
)),
1603 char *buf
EXT2FS_ATTR((unused
)),
1606 struct istruct
*is
= (struct istruct
*) priv_data
;
1607 struct ext2_inode inode
;
1608 ext2_ino_t new_inode
;
1611 if (is
->rfs
->progress
&& offset
== 0) {
1612 io_channel_flush(is
->rfs
->old_fs
->io
);
1613 is
->err
= (is
->rfs
->progress
)(is
->rfs
,
1614 E2_RSZ_INODE_REF_UPD_PASS
,
1615 ++is
->num
, is
->max_dirs
);
1617 return DIRENT_ABORT
;
1623 new_inode
= ext2fs_extent_translate(is
->rfs
->imap
, dirent
->inode
);
1627 #ifdef RESIZE2FS_DEBUG
1628 if (is
->rfs
->flags
& RESIZE_DEBUG_INODEMAP
)
1629 printf("Inode translate (dir=%u, name=%.*s, %u->%u)\n",
1630 dir
, ext2fs_dirent_name_len(dirent
), dirent
->name
,
1631 dirent
->inode
, new_inode
);
1634 dirent
->inode
= new_inode
;
1636 /* Update the directory mtime and ctime */
1637 retval
= ext2fs_read_inode(is
->rfs
->old_fs
, dir
, &inode
);
1639 inode
.i_mtime
= inode
.i_ctime
= time(0);
1640 is
->err
= ext2fs_write_inode(is
->rfs
->old_fs
, dir
, &inode
);
1642 return DIRENT_ABORT
;
1645 return DIRENT_CHANGED
;
1648 static errcode_t
inode_ref_fix(ext2_resize_t rfs
)
1657 * Now, we iterate over all of the directories to update the
1661 is
.max_dirs
= ext2fs_dblist_count2(rfs
->old_fs
->dblist
);
1665 if (rfs
->progress
) {
1666 retval
= (rfs
->progress
)(rfs
, E2_RSZ_INODE_REF_UPD_PASS
,
1672 retval
= ext2fs_dblist_dir_iterate(rfs
->old_fs
->dblist
,
1673 DIRENT_FLAG_INCLUDE_EMPTY
, 0,
1674 check_and_change_inodes
, &is
);
1682 if (rfs
->progress
&& (is
.num
< is
.max_dirs
))
1683 (rfs
->progress
)(rfs
, E2_RSZ_INODE_REF_UPD_PASS
,
1684 is
.max_dirs
, is
.max_dirs
);
1687 ext2fs_free_extent_table(rfs
->imap
);
1693 /* --------------------------------------------------------------------
1695 * Resize processing, phase 5.
1697 * In this phase we actually move the inode table around, and then
1698 * update the summary statistics. This is scary, since aborting here
1699 * will potentially scramble the filesystem. (We are moving the
1700 * inode tables around in place, and so the potential for lost data,
1701 * or at the very least scrambling the mapping between filenames and
1702 * inode numbers is very high in case of a power failure here.)
1703 * --------------------------------------------------------------------
1708 * A very scary routine --- this one moves the inode table around!!!
1710 * After this you have to use the rfs->new_fs file handle to read and
1713 static errcode_t
move_itables(ext2_resize_t rfs
)
1717 dgrp_t i
, max_groups
;
1718 ext2_filsys fs
= rfs
->new_fs
;
1720 blk64_t old_blk
, new_blk
, blk
;
1722 int j
, to_move
, moved
;
1724 max_groups
= fs
->group_desc_count
;
1725 if (max_groups
> rfs
->old_fs
->group_desc_count
)
1726 max_groups
= rfs
->old_fs
->group_desc_count
;
1728 size
= fs
->blocksize
* fs
->inode_blocks_per_group
;
1729 if (!rfs
->itable_buf
) {
1730 retval
= ext2fs_get_mem(size
, &rfs
->itable_buf
);
1736 * Figure out how many inode tables we need to move
1738 to_move
= moved
= 0;
1739 for (i
=0; i
< max_groups
; i
++)
1740 if (ext2fs_inode_table_loc(rfs
->old_fs
, i
) !=
1741 ext2fs_inode_table_loc(fs
, i
))
1747 if (rfs
->progress
) {
1748 retval
= rfs
->progress(rfs
, E2_RSZ_MOVE_ITABLE_PASS
,
1754 rfs
->old_fs
->flags
|= EXT2_FLAG_MASTER_SB_ONLY
;
1756 for (i
=0; i
< max_groups
; i
++) {
1757 old_blk
= ext2fs_inode_table_loc(rfs
->old_fs
, i
);
1758 new_blk
= ext2fs_inode_table_loc(fs
, i
);
1759 diff
= new_blk
- old_blk
;
1761 #ifdef RESIZE2FS_DEBUG
1762 if (rfs
->flags
& RESIZE_DEBUG_ITABLEMOVE
)
1763 printf("Itable move group %d block %llu->%llu (diff %lld)\n",
1764 i
, old_blk
, new_blk
, diff
);
1770 retval
= io_channel_read_blk64(fs
->io
, old_blk
,
1771 fs
->inode_blocks_per_group
,
1776 * The end of the inode table segment often contains
1777 * all zeros, and we're often only moving the inode
1778 * table down a block or two. If so, we can optimize
1779 * things by not rewriting blocks that we know to be zero
1782 for (cp
= rfs
->itable_buf
+size
-1, n
=0; n
< size
; n
++, cp
--)
1785 n
= n
>> EXT2_BLOCK_SIZE_BITS(fs
->super
);
1786 #ifdef RESIZE2FS_DEBUG
1787 if (rfs
->flags
& RESIZE_DEBUG_ITABLEMOVE
)
1788 printf("%d blocks of zeros...\n", n
);
1790 num
= fs
->inode_blocks_per_group
;
1794 retval
= io_channel_write_blk64(fs
->io
, new_blk
,
1795 num
, rfs
->itable_buf
);
1797 io_channel_write_blk64(fs
->io
, old_blk
,
1798 num
, rfs
->itable_buf
);
1802 retval
= io_channel_write_blk64(fs
->io
,
1803 old_blk
+ fs
->inode_blocks_per_group
,
1804 diff
, (rfs
->itable_buf
+
1805 (fs
->inode_blocks_per_group
- diff
) *
1811 for (blk
= ext2fs_inode_table_loc(rfs
->old_fs
, i
), j
=0;
1812 j
< fs
->inode_blocks_per_group
; j
++, blk
++)
1813 ext2fs_block_alloc_stats2(fs
, blk
, -1);
1815 ext2fs_inode_table_loc_set(rfs
->old_fs
, i
, new_blk
);
1816 ext2fs_group_desc_csum_set(rfs
->old_fs
, i
);
1817 ext2fs_mark_super_dirty(rfs
->old_fs
);
1818 ext2fs_flush(rfs
->old_fs
);
1820 if (rfs
->progress
) {
1821 retval
= rfs
->progress(rfs
, E2_RSZ_MOVE_ITABLE_PASS
,
1827 mark_table_blocks(fs
, fs
->block_map
);
1829 #ifdef RESIZE2FS_DEBUG
1830 if (rfs
->flags
& RESIZE_DEBUG_ITABLEMOVE
)
1831 printf("Inode table move finished.\n");
1840 * Fix the resize inode
1842 static errcode_t
fix_resize_inode(ext2_filsys fs
)
1844 struct ext2_inode inode
;
1846 char *block_buf
= NULL
;
1848 if (!(fs
->super
->s_feature_compat
&
1849 EXT2_FEATURE_COMPAT_RESIZE_INODE
))
1852 retval
= ext2fs_get_mem(fs
->blocksize
, &block_buf
);
1853 if (retval
) goto errout
;
1855 retval
= ext2fs_read_inode(fs
, EXT2_RESIZE_INO
, &inode
);
1856 if (retval
) goto errout
;
1858 ext2fs_iblk_set(fs
, &inode
, 1);
1860 retval
= ext2fs_write_inode(fs
, EXT2_RESIZE_INO
, &inode
);
1861 if (retval
) goto errout
;
1863 if (!inode
.i_block
[EXT2_DIND_BLOCK
]) {
1865 * Avoid zeroing out block #0; that's rude. This
1866 * should never happen anyway since the filesystem
1867 * should be fsck'ed and we assume it is consistent.
1870 _("Should never happen: resize inode corrupt!\n"));
1874 memset(block_buf
, 0, fs
->blocksize
);
1876 retval
= io_channel_write_blk64(fs
->io
, inode
.i_block
[EXT2_DIND_BLOCK
],
1878 if (retval
) goto errout
;
1880 retval
= ext2fs_create_resize_inode(fs
);
1886 ext2fs_free_mem(&block_buf
);
1891 * Finally, recalculate the summary information
1893 static errcode_t
ext2fs_calculate_summary_stats(ext2_filsys fs
)
1897 unsigned int group
= 0;
1898 unsigned int count
= 0;
1899 blk64_t total_blocks_free
= 0;
1900 int total_inodes_free
= 0;
1903 blk64_t super_blk
, old_desc_blk
, new_desc_blk
;
1904 int old_desc_blocks
;
1907 * First calculate the block statistics
1909 uninit
= ext2fs_bg_flags_test(fs
, group
, EXT2_BG_BLOCK_UNINIT
);
1910 ext2fs_super_and_bgd_loc2(fs
, group
, &super_blk
, &old_desc_blk
,
1912 if (fs
->super
->s_feature_incompat
& EXT2_FEATURE_INCOMPAT_META_BG
)
1913 old_desc_blocks
= fs
->super
->s_first_meta_bg
;
1915 old_desc_blocks
= fs
->desc_blocks
+
1916 fs
->super
->s_reserved_gdt_blocks
;
1917 for (blk
= B2C(fs
->super
->s_first_data_block
);
1918 blk
< ext2fs_blocks_count(fs
->super
);
1919 blk
+= EXT2FS_CLUSTER_RATIO(fs
)) {
1921 !(EQ_CLSTR(blk
, super_blk
) ||
1922 ((old_desc_blk
&& old_desc_blocks
&&
1923 GE_CLSTR(blk
, old_desc_blk
) &&
1924 LT_CLSTR(blk
, old_desc_blk
+ old_desc_blocks
))) ||
1925 ((new_desc_blk
&& EQ_CLSTR(blk
, new_desc_blk
))) ||
1926 EQ_CLSTR(blk
, ext2fs_block_bitmap_loc(fs
, group
)) ||
1927 EQ_CLSTR(blk
, ext2fs_inode_bitmap_loc(fs
, group
)) ||
1928 ((GE_CLSTR(blk
, ext2fs_inode_table_loc(fs
, group
)) &&
1929 LT_CLSTR(blk
, ext2fs_inode_table_loc(fs
, group
)
1930 + fs
->inode_blocks_per_group
))))) ||
1931 (!ext2fs_fast_test_block_bitmap2(fs
->block_map
, blk
))) {
1933 total_blocks_free
++;
1936 if ((count
== fs
->super
->s_clusters_per_group
) ||
1937 EQ_CLSTR(blk
, ext2fs_blocks_count(fs
->super
)-1)) {
1938 ext2fs_bg_free_blocks_count_set(fs
, group
, group_free
);
1939 ext2fs_group_desc_csum_set(fs
, group
);
1941 if (group
>= fs
->group_desc_count
)
1945 uninit
= ext2fs_bg_flags_test(fs
, group
, EXT2_BG_BLOCK_UNINIT
);
1946 ext2fs_super_and_bgd_loc2(fs
, group
, &super_blk
,
1949 if (fs
->super
->s_feature_incompat
&
1950 EXT2_FEATURE_INCOMPAT_META_BG
)
1951 old_desc_blocks
= fs
->super
->s_first_meta_bg
;
1953 old_desc_blocks
= fs
->desc_blocks
+
1954 fs
->super
->s_reserved_gdt_blocks
;
1957 total_blocks_free
= C2B(total_blocks_free
);
1958 ext2fs_free_blocks_count_set(fs
->super
, total_blocks_free
);
1961 * Next, calculate the inode statistics
1967 /* Protect loop from wrap-around if s_inodes_count maxed */
1968 uninit
= ext2fs_bg_flags_test(fs
, group
, EXT2_BG_INODE_UNINIT
);
1969 for (ino
= 1; ino
<= fs
->super
->s_inodes_count
&& ino
> 0; ino
++) {
1971 !ext2fs_fast_test_inode_bitmap2(fs
->inode_map
, ino
)) {
1973 total_inodes_free
++;
1976 if ((count
== fs
->super
->s_inodes_per_group
) ||
1977 (ino
== fs
->super
->s_inodes_count
)) {
1978 ext2fs_bg_free_inodes_count_set(fs
, group
, group_free
);
1979 ext2fs_group_desc_csum_set(fs
, group
);
1981 if (group
>= fs
->group_desc_count
)
1985 uninit
= ext2fs_bg_flags_test(fs
, group
, EXT2_BG_INODE_UNINIT
);
1988 fs
->super
->s_free_inodes_count
= total_inodes_free
;
1989 ext2fs_mark_super_dirty(fs
);
1994 * Journal may have been relocated; update the backup journal blocks
1995 * in the superblock.
1997 static errcode_t
fix_sb_journal_backup(ext2_filsys fs
)
2000 struct ext2_inode inode
;
2002 if (!(fs
->super
->s_feature_compat
& EXT3_FEATURE_COMPAT_HAS_JOURNAL
))
2005 /* External journal? Nothing to do. */
2006 if (fs
->super
->s_journal_dev
&& !fs
->super
->s_journal_inum
)
2009 retval
= ext2fs_read_inode(fs
, fs
->super
->s_journal_inum
, &inode
);
2012 memcpy(fs
->super
->s_jnl_blocks
, inode
.i_block
, EXT2_N_BLOCKS
*4);
2013 fs
->super
->s_jnl_blocks
[15] = inode
.i_size_high
;
2014 fs
->super
->s_jnl_blocks
[16] = inode
.i_size
;
2015 fs
->super
->s_jnl_backup_type
= EXT3_JNL_BACKUP_BLOCKS
;
2016 ext2fs_mark_super_dirty(fs
);
2020 static int calc_group_overhead(ext2_filsys fs
, blk64_t grp
,
2021 int old_desc_blocks
)
2023 blk64_t super_blk
, old_desc_blk
, new_desc_blk
;
2026 /* inode table blocks plus allocation bitmaps */
2027 overhead
= fs
->inode_blocks_per_group
+ 2;
2029 ext2fs_super_and_bgd_loc2(fs
, grp
, &super_blk
,
2030 &old_desc_blk
, &new_desc_blk
, 0);
2031 if ((grp
== 0) || super_blk
)
2034 overhead
+= old_desc_blocks
;
2035 else if (new_desc_blk
)
2042 * calcluate the minimum number of blocks the given fs can be resized to
2044 blk64_t
calculate_minimum_resize_size(ext2_filsys fs
, int flags
)
2046 ext2_ino_t inode_count
;
2048 blk64_t blks_needed
, data_blocks
;
2049 blk64_t grp
, data_needed
, last_start
;
2050 blk64_t overhead
= 0;
2051 int old_desc_blocks
;
2052 int extra_groups
= 0;
2053 int flexbg_size
= 1 << fs
->super
->s_log_groups_per_flex
;
2056 * first figure out how many group descriptors we need to
2057 * handle the number of inodes we have
2059 inode_count
= fs
->super
->s_inodes_count
-
2060 fs
->super
->s_free_inodes_count
;
2061 blks_needed
= ext2fs_div_ceil(inode_count
,
2062 fs
->super
->s_inodes_per_group
) *
2063 EXT2_BLOCKS_PER_GROUP(fs
->super
);
2064 groups
= ext2fs_div64_ceil(blks_needed
,
2065 EXT2_BLOCKS_PER_GROUP(fs
->super
));
2066 #ifdef RESIZE2FS_DEBUG
2067 if (flags
& RESIZE_DEBUG_MIN_CALC
)
2068 printf("fs has %d inodes, %d groups required.\n",
2069 inode_count
, groups
);
2073 * number of old-style block group descriptor blocks
2075 if (fs
->super
->s_feature_incompat
& EXT2_FEATURE_INCOMPAT_META_BG
)
2076 old_desc_blocks
= fs
->super
->s_first_meta_bg
;
2078 old_desc_blocks
= fs
->desc_blocks
+
2079 fs
->super
->s_reserved_gdt_blocks
;
2081 /* calculate how many blocks are needed for data */
2082 data_needed
= ext2fs_blocks_count(fs
->super
) -
2083 ext2fs_free_blocks_count(fs
->super
);
2085 for (grp
= 0; grp
< fs
->group_desc_count
; grp
++)
2086 data_needed
-= calc_group_overhead(fs
, grp
, old_desc_blocks
);
2087 #ifdef RESIZE2FS_DEBUG
2088 if (flags
& RESIZE_DEBUG_MIN_CALC
)
2089 printf("fs requires %llu data blocks.\n", data_needed
);
2093 * For ext4 we need to allow for up to a flex_bg worth of
2094 * inode tables of slack space so the resize operation can be
2095 * guaranteed to finish.
2097 if (fs
->super
->s_feature_incompat
& EXT4_FEATURE_INCOMPAT_FLEX_BG
) {
2098 extra_groups
= flexbg_size
- (groups
& (flexbg_size
- 1));
2099 data_needed
+= fs
->inode_blocks_per_group
* extra_groups
;
2100 extra_groups
= groups
% flexbg_size
;
2104 * figure out how many data blocks we have given the number of groups
2105 * we need for our inodes
2107 data_blocks
= groups
* EXT2_BLOCKS_PER_GROUP(fs
->super
);
2109 for (grp
= 0; grp
< groups
; grp
++) {
2110 overhead
= calc_group_overhead(fs
, grp
, old_desc_blocks
);
2113 * we want to keep track of how much data we can store in
2114 * the groups leading up to the last group so we can determine
2115 * how big the last group needs to be
2117 if (grp
!= (groups
- 1))
2118 last_start
+= EXT2_BLOCKS_PER_GROUP(fs
->super
) -
2121 data_blocks
-= overhead
;
2123 #ifdef RESIZE2FS_DEBUG
2124 if (flags
& RESIZE_DEBUG_MIN_CALC
)
2125 printf("With %d group(s), we have %llu blocks available.\n",
2126 groups
, data_blocks
);
2130 * if we need more group descriptors in order to accomodate our data
2131 * then we need to add them here
2133 while (data_needed
> data_blocks
) {
2134 blk64_t remainder
= data_needed
- data_blocks
;
2137 /* figure out how many more groups we need for the data */
2138 extra_grps
= ext2fs_div64_ceil(remainder
,
2139 EXT2_BLOCKS_PER_GROUP(fs
->super
));
2141 data_blocks
+= extra_grps
* EXT2_BLOCKS_PER_GROUP(fs
->super
);
2143 /* ok we have to account for the last group */
2144 overhead
= calc_group_overhead(fs
, groups
-1, old_desc_blocks
);
2145 last_start
+= EXT2_BLOCKS_PER_GROUP(fs
->super
) - overhead
;
2147 for (grp
= groups
; grp
< groups
+extra_grps
; grp
++) {
2148 overhead
= calc_group_overhead(fs
, grp
,
2152 * again, we need to see how much data we cram into
2153 * all of the groups leading up to the last group
2155 if (grp
!= (groups
+ extra_grps
- 1))
2156 last_start
+= EXT2_BLOCKS_PER_GROUP(fs
->super
)
2159 data_blocks
-= overhead
;
2162 groups
+= extra_grps
;
2163 extra_groups
+= extra_grps
;
2164 if (fs
->super
->s_feature_incompat
2165 & EXT4_FEATURE_INCOMPAT_FLEX_BG
2166 && extra_groups
> flexbg_size
) {
2168 * For ext4 we need to allow for up to a flex_bg worth
2169 * of inode tables of slack space so the resize
2170 * operation can be guaranteed to finish.
2172 extra_groups
= flexbg_size
-
2173 (groups
& (flexbg_size
- 1));
2174 data_needed
+= (fs
->inode_blocks_per_group
*
2176 extra_groups
= groups
% flexbg_size
;
2178 #ifdef RESIZE2FS_DEBUG
2179 if (flags
& RESIZE_DEBUG_MIN_CALC
)
2180 printf("Added %d extra group(s), "
2181 "data_needed %llu, data_blocks %llu, "
2182 "last_start %llu\n",
2183 extra_grps
, data_needed
, data_blocks
,
2188 /* now for the fun voodoo */
2189 overhead
= calc_group_overhead(fs
, groups
-1, old_desc_blocks
);
2190 #ifdef RESIZE2FS_DEBUG
2191 if (flags
& RESIZE_DEBUG_MIN_CALC
)
2192 printf("Last group's overhead is %llu\n", overhead
);
2196 * if this is the case then the last group is going to have data in it
2197 * so we need to adjust the size of the last group accordingly
2199 if (last_start
< data_needed
) {
2200 blk64_t remainder
= data_needed
- last_start
;
2202 #ifdef RESIZE2FS_DEBUG
2203 if (flags
& RESIZE_DEBUG_MIN_CALC
)
2204 printf("Need %llu data blocks in last group\n",
2208 * 50 is a magic number that mkfs/resize uses to see if its
2209 * even worth making/resizing the fs. basically you need to
2210 * have at least 50 blocks in addition to the blocks needed
2211 * for the metadata in the last group
2214 overhead
+= remainder
;
2220 overhead
+= fs
->super
->s_first_data_block
;
2221 #ifdef RESIZE2FS_DEBUG
2222 if (flags
& RESIZE_DEBUG_MIN_CALC
)
2223 printf("Final size of last group is %lld\n", overhead
);
2227 * since our last group doesn't have to be BLOCKS_PER_GROUP large, we
2228 * only do groups-1, and then add the number of blocks needed to
2229 * handle the group descriptor metadata+data that we need
2231 blks_needed
= (groups
-1) * EXT2_BLOCKS_PER_GROUP(fs
->super
);
2232 blks_needed
+= overhead
;
2235 * Make sure blks_needed covers the end of the inode table in
2236 * the last block group.
2238 overhead
= ext2fs_inode_table_loc(fs
, groups
-1) +
2239 fs
->inode_blocks_per_group
;
2240 if (blks_needed
< overhead
)
2241 blks_needed
= overhead
;
2243 #ifdef RESIZE2FS_DEBUG
2244 if (flags
& RESIZE_DEBUG_MIN_CALC
)
2245 printf("Estimated blocks needed: %llu\n", blks_needed
);
2249 * If at this point we've already added up more "needed" than
2250 * the current size, just return current size as minimum.
2252 if (blks_needed
>= ext2fs_blocks_count(fs
->super
))
2253 return ext2fs_blocks_count(fs
->super
);
2255 * We need to reserve a few extra blocks if extents are
2256 * enabled, in case we need to grow the extent tree. The more
2257 * we shrink the file system, the more space we need.
2259 if (fs
->super
->s_feature_incompat
& EXT3_FEATURE_INCOMPAT_EXTENTS
) {
2260 blk64_t safe_margin
= (ext2fs_blocks_count(fs
->super
) -
2262 #ifdef RESIZE2FS_DEBUG
2263 if (flags
& RESIZE_DEBUG_MIN_CALC
)
2264 printf("Extents safety margin: %llu\n", safe_margin
);
2266 blks_needed
+= safe_margin
;