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.
36 #include "resize2fs.h"
39 #ifdef __linux__ /* Kludge for debugging */
40 #define RESIZE2FS_DEBUG
43 static void fix_uninit_block_bitmaps(ext2_filsys fs
);
44 static errcode_t
adjust_superblock(ext2_resize_t rfs
, blk_t new_size
);
45 static errcode_t
blocks_to_move(ext2_resize_t rfs
);
46 static errcode_t
block_mover(ext2_resize_t rfs
);
47 static errcode_t
inode_scan_and_fix(ext2_resize_t rfs
);
48 static errcode_t
inode_ref_fix(ext2_resize_t rfs
);
49 static errcode_t
move_itables(ext2_resize_t rfs
);
50 static errcode_t
fix_resize_inode(ext2_filsys fs
);
51 static errcode_t
ext2fs_calculate_summary_stats(ext2_filsys fs
);
54 * Some helper CPP macros
56 #define FS_BLOCK_BM(fs, i) ((fs)->group_desc[(i)].bg_block_bitmap)
57 #define FS_INODE_BM(fs, i) ((fs)->group_desc[(i)].bg_inode_bitmap)
58 #define FS_INODE_TB(fs, i) ((fs)->group_desc[(i)].bg_inode_table)
60 #define IS_BLOCK_BM(fs, i, blk) ((blk) == FS_BLOCK_BM((fs),(i)))
61 #define IS_INODE_BM(fs, i, blk) ((blk) == FS_INODE_BM((fs),(i)))
63 #define IS_INODE_TB(fs, i, blk) (((blk) >= FS_INODE_TB((fs), (i))) && \
64 ((blk) < (FS_INODE_TB((fs), (i)) + \
65 (fs)->inode_blocks_per_group)))
67 #define META_OVERHEAD(fs) (2 + (fs)->inode_blocks_per_group)
68 #define SUPER_OVERHEAD(fs) (1 + (fs)->desc_blocks +\
69 (fs)->super->s_reserved_gdt_blocks)
72 * This is the top-level routine which does the dirty deed....
74 errcode_t
resize_fs(ext2_filsys fs
, blk_t
*new_size
, int flags
,
75 errcode_t (*progress
)(ext2_resize_t rfs
, int pass
,
77 unsigned long max_val
))
82 retval
= ext2fs_read_bitmaps(fs
);
87 * Create the data structure
89 retval
= ext2fs_get_mem(sizeof(struct ext2_resize_struct
), &rfs
);
92 memset(rfs
, 0, sizeof(struct ext2_resize_struct
));
94 fix_uninit_block_bitmaps(fs
);
99 rfs
->progress
= progress
;
100 retval
= ext2fs_dup_handle(fs
, &rfs
->new_fs
);
104 retval
= adjust_superblock(rfs
, *new_size
);
108 fix_uninit_block_bitmaps(rfs
->new_fs
);
109 /* Clear the block bitmap uninit flag for the last block group */
110 rfs
->new_fs
->group_desc
[rfs
->new_fs
->group_desc_count
-1].bg_flags
&=
111 ~EXT2_BG_BLOCK_UNINIT
;
113 *new_size
= rfs
->new_fs
->super
->s_blocks_count
;
115 retval
= blocks_to_move(rfs
);
119 #ifdef RESIZE2FS_DEBUG
120 if (rfs
->flags
& RESIZE_DEBUG_BMOVE
)
121 printf("Number of free blocks: %u/%u, Needed: %d\n",
122 rfs
->old_fs
->super
->s_free_blocks_count
,
123 rfs
->new_fs
->super
->s_free_blocks_count
,
127 retval
= block_mover(rfs
);
131 retval
= inode_scan_and_fix(rfs
);
135 retval
= inode_ref_fix(rfs
);
139 retval
= move_itables(rfs
);
143 retval
= ext2fs_calculate_summary_stats(rfs
->new_fs
);
147 retval
= fix_resize_inode(rfs
->new_fs
);
151 rfs
->new_fs
->flags
&= ~EXT2_FLAG_MASTER_SB_ONLY
;
152 retval
= ext2fs_close(rfs
->new_fs
);
158 ext2fs_free(rfs
->old_fs
);
160 ext2fs_free_mem(&rfs
->itable_buf
);
161 ext2fs_free_mem(&rfs
);
167 ext2fs_free(rfs
->new_fs
);
169 ext2fs_free_mem(&rfs
->itable_buf
);
170 ext2fs_free_mem(&rfs
);
175 * Clean up the bitmaps for unitialized bitmaps
177 static void fix_uninit_block_bitmaps(ext2_filsys fs
)
180 blk_t blk
, super_blk
, old_desc_blk
, new_desc_blk
;
184 if (!(EXT2_HAS_RO_COMPAT_FEATURE(fs
->super
,
185 EXT4_FEATURE_RO_COMPAT_GDT_CSUM
)))
188 for (g
=0; g
< fs
->group_desc_count
; g
++) {
189 if (!(fs
->group_desc
[g
].bg_flags
& EXT2_BG_BLOCK_UNINIT
))
192 blk
= (g
* fs
->super
->s_blocks_per_group
) +
193 fs
->super
->s_first_data_block
;
195 ext2fs_super_and_bgd_loc(fs
, g
, &super_blk
,
196 &old_desc_blk
, &new_desc_blk
, 0);
198 if (fs
->super
->s_feature_incompat
& EXT2_FEATURE_INCOMPAT_META_BG
)
199 old_desc_blocks
= fs
->super
->s_first_meta_bg
;
201 old_desc_blocks
= fs
->desc_blocks
+
202 fs
->super
->s_reserved_gdt_blocks
;
204 for (i
=0; i
< fs
->super
->s_blocks_per_group
; i
++, blk
++) {
205 if (blk
>= fs
->super
->s_blocks_count
)
207 if ((blk
== super_blk
) ||
208 (old_desc_blk
&& old_desc_blocks
&&
209 (blk
>= old_desc_blk
) &&
210 (blk
< old_desc_blk
+ old_desc_blocks
)) ||
211 (new_desc_blk
&& (blk
== new_desc_blk
)) ||
212 (blk
== fs
->group_desc
[g
].bg_block_bitmap
) ||
213 (blk
== fs
->group_desc
[g
].bg_inode_bitmap
) ||
214 (blk
>= fs
->group_desc
[g
].bg_inode_table
&&
215 (blk
< fs
->group_desc
[g
].bg_inode_table
216 + fs
->inode_blocks_per_group
)))
217 ext2fs_fast_mark_block_bitmap(fs
->block_map
, blk
);
219 ext2fs_fast_unmark_block_bitmap(fs
->block_map
, blk
);
224 /* --------------------------------------------------------------------
226 * Resize processing, phase 1.
228 * In this phase we adjust the in-memory superblock information, and
229 * initialize any new parts of the inode table. The new parts of the
230 * inode table are created in virgin disk space, so we can abort here
231 * without any side effects.
232 * --------------------------------------------------------------------
236 * This routine is shared by the online and offline resize routines.
237 * All of the information which is adjusted in memory is done here.
239 errcode_t
adjust_fs_info(ext2_filsys fs
, ext2_filsys old_fs
, blk_t new_size
)
244 blk_t blk
, group_block
;
246 int adj
, old_numblocks
, numblocks
, adjblocks
;
247 unsigned long i
, j
, old_desc_blocks
, max_group
;
248 unsigned int meta_bg
, meta_bg_size
;
249 int has_super
, csum_flag
;
250 unsigned long long new_inodes
; /* u64 to check for overflow */
253 fs
->super
->s_blocks_count
= new_size
;
256 fs
->group_desc_count
= ext2fs_div_ceil(fs
->super
->s_blocks_count
-
257 fs
->super
->s_first_data_block
,
258 EXT2_BLOCKS_PER_GROUP(fs
->super
));
259 if (fs
->group_desc_count
== 0)
260 return EXT2_ET_TOOSMALL
;
261 fs
->desc_blocks
= ext2fs_div_ceil(fs
->group_desc_count
,
262 EXT2_DESC_PER_BLOCK(fs
->super
));
265 * Overhead is the number of bookkeeping blocks per group. It
266 * includes the superblock backup, the group descriptor
267 * backups, the inode bitmap, the block bitmap, and the inode
270 overhead
= (int) (2 + fs
->inode_blocks_per_group
);
272 if (ext2fs_bg_has_super(fs
, fs
->group_desc_count
- 1))
273 overhead
+= 1 + fs
->desc_blocks
+
274 fs
->super
->s_reserved_gdt_blocks
;
277 * See if the last group is big enough to support the
278 * necessary data structures. If not, we need to get rid of
281 rem
= (fs
->super
->s_blocks_count
- fs
->super
->s_first_data_block
) %
282 fs
->super
->s_blocks_per_group
;
283 if ((fs
->group_desc_count
== 1) && rem
&& (rem
< overhead
))
284 return EXT2_ET_TOOSMALL
;
285 if (rem
&& (rem
< overhead
+50)) {
286 fs
->super
->s_blocks_count
-= rem
;
290 * Adjust the number of inodes
292 new_inodes
=(unsigned long long) fs
->super
->s_inodes_per_group
* fs
->group_desc_count
;
293 if (new_inodes
> ~0U) {
294 fprintf(stderr
, _("inodes (%llu) must be less than %u"),
296 return EXT2_ET_TOO_MANY_INODES
;
298 fs
->super
->s_inodes_count
= fs
->super
->s_inodes_per_group
*
299 fs
->group_desc_count
;
302 * Adjust the number of free blocks
304 blk
= old_fs
->super
->s_blocks_count
;
305 if (blk
> fs
->super
->s_blocks_count
)
306 fs
->super
->s_free_blocks_count
-=
307 (blk
- fs
->super
->s_blocks_count
);
309 fs
->super
->s_free_blocks_count
+=
310 (fs
->super
->s_blocks_count
- blk
);
313 * Adjust the number of reserved blocks
315 percent
= (old_fs
->super
->s_r_blocks_count
* 100.0) /
316 old_fs
->super
->s_blocks_count
;
317 fs
->super
->s_r_blocks_count
= (unsigned int) (percent
*
318 fs
->super
->s_blocks_count
/ 100.0);
321 * Adjust the bitmaps for size
323 retval
= ext2fs_resize_inode_bitmap(fs
->super
->s_inodes_count
,
324 fs
->super
->s_inodes_count
,
326 if (retval
) goto errout
;
328 real_end
= ((EXT2_BLOCKS_PER_GROUP(fs
->super
)
329 * fs
->group_desc_count
)) - 1 +
330 fs
->super
->s_first_data_block
;
331 retval
= ext2fs_resize_block_bitmap(fs
->super
->s_blocks_count
-1,
332 real_end
, fs
->block_map
);
334 if (retval
) goto errout
;
337 * Reallocate the group descriptors as necessary.
339 if (old_fs
->desc_blocks
!= fs
->desc_blocks
) {
340 retval
= ext2fs_resize_mem(old_fs
->desc_blocks
*
342 fs
->desc_blocks
* fs
->blocksize
,
346 if (fs
->desc_blocks
> old_fs
->desc_blocks
)
347 memset((char *) fs
->group_desc
+
348 (old_fs
->desc_blocks
* fs
->blocksize
), 0,
349 (fs
->desc_blocks
- old_fs
->desc_blocks
) *
354 * If the resize_inode feature is set, and we are changing the
355 * number of descriptor blocks, then adjust
356 * s_reserved_gdt_blocks if possible to avoid needing to move
357 * the inode table either now or in the future.
359 if ((fs
->super
->s_feature_compat
&
360 EXT2_FEATURE_COMPAT_RESIZE_INODE
) &&
361 (old_fs
->desc_blocks
!= fs
->desc_blocks
)) {
364 new = ((int) fs
->super
->s_reserved_gdt_blocks
) +
365 (old_fs
->desc_blocks
- fs
->desc_blocks
);
368 if (new > (int) fs
->blocksize
/4)
369 new = fs
->blocksize
/4;
370 fs
->super
->s_reserved_gdt_blocks
= new;
374 * If we are shrinking the number block groups, we're done and
377 if (old_fs
->group_desc_count
> fs
->group_desc_count
) {
383 * Fix the count of the last (old) block group
385 old_numblocks
= (old_fs
->super
->s_blocks_count
-
386 old_fs
->super
->s_first_data_block
) %
387 old_fs
->super
->s_blocks_per_group
;
389 old_numblocks
= old_fs
->super
->s_blocks_per_group
;
390 if (old_fs
->group_desc_count
== fs
->group_desc_count
) {
391 numblocks
= (fs
->super
->s_blocks_count
-
392 fs
->super
->s_first_data_block
) %
393 fs
->super
->s_blocks_per_group
;
395 numblocks
= fs
->super
->s_blocks_per_group
;
397 numblocks
= fs
->super
->s_blocks_per_group
;
398 i
= old_fs
->group_desc_count
- 1;
399 fs
->group_desc
[i
].bg_free_blocks_count
+= (numblocks
-old_numblocks
);
400 ext2fs_group_desc_csum_set(fs
, i
);
403 * If the number of block groups is staying the same, we're
404 * done and can exit now. (If the number block groups is
405 * shrinking, we had exited earlier.)
407 if (old_fs
->group_desc_count
>= fs
->group_desc_count
) {
413 * Initialize the new block group descriptors
415 group_block
= fs
->super
->s_first_data_block
+
416 old_fs
->group_desc_count
* fs
->super
->s_blocks_per_group
;
418 csum_flag
= EXT2_HAS_RO_COMPAT_FEATURE(fs
->super
,
419 EXT4_FEATURE_RO_COMPAT_GDT_CSUM
);
420 adj
= old_fs
->group_desc_count
;
421 max_group
= fs
->group_desc_count
- adj
;
422 if (fs
->super
->s_feature_incompat
& EXT2_FEATURE_INCOMPAT_META_BG
)
423 old_desc_blocks
= fs
->super
->s_first_meta_bg
;
425 old_desc_blocks
= fs
->desc_blocks
+
426 fs
->super
->s_reserved_gdt_blocks
;
427 for (i
= old_fs
->group_desc_count
;
428 i
< fs
->group_desc_count
; i
++) {
429 memset(&fs
->group_desc
[i
], 0,
430 sizeof(struct ext2_group_desc
));
433 fs
->group_desc
[i
].bg_flags
= 0;
435 fs
->group_desc
[i
].bg_flags
|= EXT2_BG_INODE_UNINIT
|
436 EXT2_BG_INODE_ZEROED
;
437 if (i
== fs
->group_desc_count
-1) {
438 numblocks
= (fs
->super
->s_blocks_count
-
439 fs
->super
->s_first_data_block
) %
440 fs
->super
->s_blocks_per_group
;
442 numblocks
= fs
->super
->s_blocks_per_group
;
444 numblocks
= fs
->super
->s_blocks_per_group
;
446 fs
->group_desc
[i
].bg_flags
|=
447 EXT2_BG_BLOCK_UNINIT
;
450 has_super
= ext2fs_bg_has_super(fs
, i
);
452 ext2fs_block_alloc_stats(fs
, group_block
, +1);
455 meta_bg_size
= EXT2_DESC_PER_BLOCK(fs
->super
);
456 meta_bg
= i
/ meta_bg_size
;
457 if (!(fs
->super
->s_feature_incompat
&
458 EXT2_FEATURE_INCOMPAT_META_BG
) ||
459 (meta_bg
< fs
->super
->s_first_meta_bg
)) {
461 for (j
=0; j
< old_desc_blocks
; j
++)
462 ext2fs_block_alloc_stats(fs
,
463 group_block
+ 1 + j
, +1);
464 adjblocks
+= old_desc_blocks
;
469 if (((i
% meta_bg_size
) == 0) ||
470 ((i
% meta_bg_size
) == 1) ||
471 ((i
% meta_bg_size
) == (meta_bg_size
-1)))
472 ext2fs_block_alloc_stats(fs
,
473 group_block
+ has_super
, +1);
476 adjblocks
+= 2 + fs
->inode_blocks_per_group
;
478 numblocks
-= adjblocks
;
479 fs
->super
->s_free_blocks_count
-= adjblocks
;
480 fs
->super
->s_free_inodes_count
+=
481 fs
->super
->s_inodes_per_group
;
482 fs
->group_desc
[i
].bg_free_blocks_count
= numblocks
;
483 fs
->group_desc
[i
].bg_free_inodes_count
=
484 fs
->super
->s_inodes_per_group
;
485 fs
->group_desc
[i
].bg_used_dirs_count
= 0;
486 ext2fs_group_desc_csum_set(fs
, i
);
488 retval
= ext2fs_allocate_group_table(fs
, i
, 0);
489 if (retval
) goto errout
;
491 group_block
+= fs
->super
->s_blocks_per_group
;
500 * This routine adjusts the superblock and other data structures, both
501 * in disk as well as in memory...
503 static errcode_t
adjust_superblock(ext2_resize_t rfs
, blk_t new_size
)
510 unsigned long max_group
;
513 ext2fs_mark_super_dirty(fs
);
514 ext2fs_mark_bb_dirty(fs
);
515 ext2fs_mark_ib_dirty(fs
);
517 retval
= adjust_fs_info(fs
, rfs
->old_fs
, new_size
);
522 * Check to make sure there are enough inodes
524 if ((rfs
->old_fs
->super
->s_inodes_count
-
525 rfs
->old_fs
->super
->s_free_inodes_count
) >
526 rfs
->new_fs
->super
->s_inodes_count
) {
532 * If we are shrinking the number block groups, we're done and
535 if (rfs
->old_fs
->group_desc_count
> fs
->group_desc_count
) {
541 * If the number of block groups is staying the same, we're
542 * done and can exit now. (If the number block groups is
543 * shrinking, we had exited earlier.)
545 if (rfs
->old_fs
->group_desc_count
>= fs
->group_desc_count
) {
551 * Initialize the new block group descriptors
553 retval
= ext2fs_get_array(fs
->blocksize
, fs
->inode_blocks_per_group
,
558 memset(rfs
->itable_buf
, 0, fs
->blocksize
* fs
->inode_blocks_per_group
);
559 group_block
= fs
->super
->s_first_data_block
+
560 rfs
->old_fs
->group_desc_count
* fs
->super
->s_blocks_per_group
;
562 adj
= rfs
->old_fs
->group_desc_count
;
563 max_group
= fs
->group_desc_count
- adj
;
565 retval
= rfs
->progress(rfs
, E2_RSZ_EXTEND_ITABLE_PASS
,
570 for (i
= rfs
->old_fs
->group_desc_count
;
571 i
< fs
->group_desc_count
; i
++) {
573 * Write out the new inode table
575 retval
= io_channel_write_blk(fs
->io
,
576 fs
->group_desc
[i
].bg_inode_table
,
577 fs
->inode_blocks_per_group
,
579 if (retval
) goto errout
;
581 io_channel_flush(fs
->io
);
583 retval
= rfs
->progress(rfs
, E2_RSZ_EXTEND_ITABLE_PASS
,
584 i
- adj
+ 1, max_group
);
588 group_block
+= fs
->super
->s_blocks_per_group
;
590 io_channel_flush(fs
->io
);
597 /* --------------------------------------------------------------------
599 * Resize processing, phase 2.
601 * In this phase we adjust determine which blocks need to be moved, in
602 * blocks_to_move(). We then copy the blocks to their ultimate new
603 * destinations using block_mover(). Since we are copying blocks to
604 * their new locations, again during this pass we can abort without
606 * --------------------------------------------------------------------
610 * This helper function creates a block bitmap with all of the
611 * filesystem meta-data blocks.
613 static errcode_t
mark_table_blocks(ext2_filsys fs
,
614 ext2fs_block_bitmap bmap
)
619 unsigned long meta_bg_size
;
620 unsigned int old_desc_blocks
;
622 meta_bg_size
= EXT2_DESC_PER_BLOCK(fs
->super
);
623 if (fs
->super
->s_feature_incompat
& EXT2_FEATURE_INCOMPAT_META_BG
)
624 old_desc_blocks
= fs
->super
->s_first_meta_bg
;
626 old_desc_blocks
= fs
->desc_blocks
+
627 fs
->super
->s_reserved_gdt_blocks
;
628 for (i
= 0; i
< fs
->group_desc_count
; i
++) {
629 ext2fs_reserve_super_and_bgd(fs
, i
, bmap
);
632 * Mark the blocks used for the inode table
634 for (j
= 0, b
= fs
->group_desc
[i
].bg_inode_table
;
635 j
< (unsigned int) fs
->inode_blocks_per_group
;
637 ext2fs_mark_block_bitmap(bmap
, b
);
640 * Mark block used for the block bitmap
642 ext2fs_mark_block_bitmap(bmap
,
643 fs
->group_desc
[i
].bg_block_bitmap
);
646 * Mark block used for the inode bitmap
648 ext2fs_mark_block_bitmap(bmap
,
649 fs
->group_desc
[i
].bg_inode_bitmap
);
655 * This function checks to see if a particular block (either a
656 * superblock or a block group descriptor) overlaps with an inode or
657 * block bitmap block, or with the inode table.
659 static void mark_fs_metablock(ext2_resize_t rfs
,
660 ext2fs_block_bitmap meta_bmap
,
661 int group
, blk_t blk
)
663 ext2_filsys fs
= rfs
->new_fs
;
665 ext2fs_mark_block_bitmap(rfs
->reserve_blocks
, blk
);
666 ext2fs_block_alloc_stats(fs
, blk
, +1);
669 * Check to see if we overlap with the inode or block bitmap,
670 * or the inode tables. If not, and the block is in use, then
671 * mark it as a block to be moved.
673 if (IS_BLOCK_BM(fs
, group
, blk
)) {
674 FS_BLOCK_BM(fs
, group
) = 0;
675 rfs
->needed_blocks
++;
676 } else if (IS_INODE_BM(fs
, group
, blk
)) {
677 FS_INODE_BM(fs
, group
) = 0;
678 rfs
->needed_blocks
++;
679 } else if (IS_INODE_TB(fs
, group
, blk
)) {
680 FS_INODE_TB(fs
, group
) = 0;
681 rfs
->needed_blocks
++;
682 } else if (EXT2_HAS_RO_COMPAT_FEATURE(fs
->super
,
683 EXT4_FEATURE_RO_COMPAT_GDT_CSUM
) &&
684 (fs
->group_desc
[group
].bg_flags
& EXT2_BG_BLOCK_UNINIT
)) {
686 * If the block bitmap is uninitialized, which means
687 * nothing other than standard metadata in use.
690 } else if (ext2fs_test_block_bitmap(rfs
->old_fs
->block_map
, blk
) &&
691 !ext2fs_test_block_bitmap(meta_bmap
, blk
)) {
692 ext2fs_mark_block_bitmap(rfs
->move_blocks
, blk
);
693 rfs
->needed_blocks
++;
699 * This routine marks and unmarks reserved blocks in the new block
700 * bitmap. It also determines which blocks need to be moved and
701 * places this information into the move_blocks bitmap.
703 static errcode_t
blocks_to_move(ext2_resize_t rfs
)
706 dgrp_t i
, max_groups
, g
;
707 blk_t blk
, group_blk
;
708 unsigned long old_blocks
, new_blocks
;
709 unsigned int meta_bg
, meta_bg_size
;
711 ext2_filsys fs
, old_fs
;
712 ext2fs_block_bitmap meta_bmap
;
715 old_fs
= rfs
->old_fs
;
716 if (old_fs
->super
->s_blocks_count
> fs
->super
->s_blocks_count
)
719 retval
= ext2fs_allocate_block_bitmap(fs
, _("reserved blocks"),
720 &rfs
->reserve_blocks
);
724 retval
= ext2fs_allocate_block_bitmap(fs
, _("blocks to be moved"),
729 retval
= ext2fs_allocate_block_bitmap(fs
, _("meta-data blocks"),
734 retval
= mark_table_blocks(old_fs
, meta_bmap
);
741 * If we're shrinking the filesystem, we need to move all of
742 * the blocks that don't fit any more
744 for (blk
= fs
->super
->s_blocks_count
;
745 blk
< old_fs
->super
->s_blocks_count
; blk
++) {
746 g
= ext2fs_group_of_blk(fs
, blk
);
747 if (EXT2_HAS_RO_COMPAT_FEATURE(fs
->super
,
748 EXT4_FEATURE_RO_COMPAT_GDT_CSUM
) &&
749 (fs
->group_desc
[g
].bg_flags
& EXT2_BG_BLOCK_UNINIT
)) {
751 * The block bitmap is uninitialized, so skip
752 * to the next block group.
754 blk
= ((g
+1) * fs
->super
->s_blocks_per_group
) +
755 fs
->super
->s_first_data_block
;
758 if (ext2fs_test_block_bitmap(old_fs
->block_map
, blk
) &&
759 !ext2fs_test_block_bitmap(meta_bmap
, blk
)) {
760 ext2fs_mark_block_bitmap(rfs
->move_blocks
, blk
);
761 rfs
->needed_blocks
++;
763 ext2fs_mark_block_bitmap(rfs
->reserve_blocks
, blk
);
766 if (fs
->super
->s_feature_incompat
& EXT2_FEATURE_INCOMPAT_META_BG
) {
767 old_blocks
= old_fs
->super
->s_first_meta_bg
;
768 new_blocks
= fs
->super
->s_first_meta_bg
;
770 old_blocks
= old_fs
->desc_blocks
+ old_fs
->super
->s_reserved_gdt_blocks
;
771 new_blocks
= fs
->desc_blocks
+ fs
->super
->s_reserved_gdt_blocks
;
774 if (old_blocks
== new_blocks
) {
779 max_groups
= fs
->group_desc_count
;
780 if (max_groups
> old_fs
->group_desc_count
)
781 max_groups
= old_fs
->group_desc_count
;
782 group_blk
= old_fs
->super
->s_first_data_block
;
784 * If we're reducing the number of descriptor blocks, this
785 * makes life easy. :-) We just have to mark some extra
788 if (old_blocks
> new_blocks
) {
789 for (i
= 0; i
< max_groups
; i
++) {
790 if (!ext2fs_bg_has_super(fs
, i
)) {
791 group_blk
+= fs
->super
->s_blocks_per_group
;
794 for (blk
= group_blk
+1+new_blocks
;
795 blk
< group_blk
+1+old_blocks
; blk
++) {
796 ext2fs_block_alloc_stats(fs
, blk
, -1);
797 rfs
->needed_blocks
--;
799 group_blk
+= fs
->super
->s_blocks_per_group
;
805 * If we're increasing the number of descriptor blocks, life
806 * gets interesting....
808 meta_bg_size
= EXT2_DESC_PER_BLOCK(fs
->super
);
809 for (i
= 0; i
< max_groups
; i
++) {
810 has_super
= ext2fs_bg_has_super(fs
, i
);
812 mark_fs_metablock(rfs
, meta_bmap
, i
, group_blk
);
814 meta_bg
= i
/ meta_bg_size
;
815 if (!(fs
->super
->s_feature_incompat
&
816 EXT2_FEATURE_INCOMPAT_META_BG
) ||
817 (meta_bg
< fs
->super
->s_first_meta_bg
)) {
819 for (blk
= group_blk
+1;
820 blk
< group_blk
+ 1 + new_blocks
; blk
++)
821 mark_fs_metablock(rfs
, meta_bmap
,
827 if (((i
% meta_bg_size
) == 0) ||
828 ((i
% meta_bg_size
) == 1) ||
829 ((i
% meta_bg_size
) == (meta_bg_size
-1)))
830 mark_fs_metablock(rfs
, meta_bmap
, i
,
831 group_blk
+ has_super
);
834 if (fs
->group_desc
[i
].bg_inode_table
&&
835 fs
->group_desc
[i
].bg_inode_bitmap
&&
836 fs
->group_desc
[i
].bg_block_bitmap
)
840 * Reserve the existing meta blocks that we know
841 * aren't to be moved.
843 if (fs
->group_desc
[i
].bg_block_bitmap
)
844 ext2fs_mark_block_bitmap(rfs
->reserve_blocks
,
845 fs
->group_desc
[i
].bg_block_bitmap
);
846 if (fs
->group_desc
[i
].bg_inode_bitmap
)
847 ext2fs_mark_block_bitmap(rfs
->reserve_blocks
,
848 fs
->group_desc
[i
].bg_inode_bitmap
);
849 if (fs
->group_desc
[i
].bg_inode_table
)
850 for (blk
= fs
->group_desc
[i
].bg_inode_table
, j
=0;
851 j
< fs
->inode_blocks_per_group
; j
++, blk
++)
852 ext2fs_mark_block_bitmap(rfs
->reserve_blocks
,
856 * Allocate the missing data structures
858 retval
= ext2fs_allocate_group_table(fs
, i
,
859 rfs
->reserve_blocks
);
864 * For those structures that have changed, we need to
867 if (FS_BLOCK_BM(old_fs
, i
) !=
868 (blk
= FS_BLOCK_BM(fs
, i
))) {
869 ext2fs_block_alloc_stats(fs
, blk
, +1);
870 if (ext2fs_test_block_bitmap(old_fs
->block_map
, blk
) &&
871 !ext2fs_test_block_bitmap(meta_bmap
, blk
))
872 ext2fs_mark_block_bitmap(rfs
->move_blocks
,
875 if (FS_INODE_BM(old_fs
, i
) !=
876 (blk
= FS_INODE_BM(fs
, i
))) {
877 ext2fs_block_alloc_stats(fs
, blk
, +1);
878 if (ext2fs_test_block_bitmap(old_fs
->block_map
, blk
) &&
879 !ext2fs_test_block_bitmap(meta_bmap
, blk
))
880 ext2fs_mark_block_bitmap(rfs
->move_blocks
,
885 * The inode table, if we need to relocate it, is
886 * handled specially. We have to reserve the blocks
887 * for both the old and the new inode table, since we
888 * can't have the inode table be destroyed during the
889 * block relocation phase.
891 if (FS_INODE_TB(fs
, i
) == FS_INODE_TB(old_fs
, i
))
892 goto next_group
; /* inode table not moved */
894 rfs
->needed_blocks
+= fs
->inode_blocks_per_group
;
897 * Mark the new inode table as in use in the new block
898 * allocation bitmap, and move any blocks that might
901 for (blk
= fs
->group_desc
[i
].bg_inode_table
, j
=0;
902 j
< fs
->inode_blocks_per_group
; j
++, blk
++) {
903 ext2fs_block_alloc_stats(fs
, blk
, +1);
904 if (ext2fs_test_block_bitmap(old_fs
->block_map
, blk
) &&
905 !ext2fs_test_block_bitmap(meta_bmap
, blk
))
906 ext2fs_mark_block_bitmap(rfs
->move_blocks
,
911 * Make sure the old inode table is reserved in the
912 * block reservation bitmap.
914 for (blk
= rfs
->old_fs
->group_desc
[i
].bg_inode_table
, j
=0;
915 j
< fs
->inode_blocks_per_group
; j
++, blk
++)
916 ext2fs_mark_block_bitmap(rfs
->reserve_blocks
, blk
);
919 group_blk
+= rfs
->new_fs
->super
->s_blocks_per_group
;
925 ext2fs_free_block_bitmap(meta_bmap
);
931 * This helper function tries to allocate a new block. We try to
932 * avoid hitting the original group descriptor blocks at least at
933 * first, since we want to make it possible to recover from a badly
934 * aborted resize operation as much as possible.
936 * In the future, I may further modify this routine to balance out
937 * where we get the new blocks across the various block groups.
938 * Ideally we would allocate blocks that corresponded with the block
939 * group of the containing inode, and keep contiguous blocks
940 * together. However, this very difficult to do efficiently, since we
941 * don't have the necessary information up front.
945 #define DESPERATION 2
947 static void init_block_alloc(ext2_resize_t rfs
)
949 rfs
->alloc_state
= AVOID_OLD
;
950 rfs
->new_blk
= rfs
->new_fs
->super
->s_first_data_block
;
952 /* HACK for testing */
953 if (rfs
->new_fs
->super
->s_blocks_count
>
954 rfs
->old_fs
->super
->s_blocks_count
)
955 rfs
->new_blk
= rfs
->old_fs
->super
->s_blocks_count
;
959 static blk_t
get_new_block(ext2_resize_t rfs
)
961 ext2_filsys fs
= rfs
->new_fs
;
964 if (rfs
->new_blk
>= fs
->super
->s_blocks_count
) {
965 if (rfs
->alloc_state
== DESPERATION
)
968 #ifdef RESIZE2FS_DEBUG
969 if (rfs
->flags
& RESIZE_DEBUG_BMOVE
)
970 printf("Going into desperation mode "
971 "for block allocations\n");
973 rfs
->alloc_state
= DESPERATION
;
974 rfs
->new_blk
= fs
->super
->s_first_data_block
;
977 if (ext2fs_test_block_bitmap(fs
->block_map
, rfs
->new_blk
) ||
978 ext2fs_test_block_bitmap(rfs
->reserve_blocks
,
980 ((rfs
->alloc_state
== AVOID_OLD
) &&
981 (rfs
->new_blk
< rfs
->old_fs
->super
->s_blocks_count
) &&
982 ext2fs_test_block_bitmap(rfs
->old_fs
->block_map
,
991 static errcode_t
resize2fs_get_alloc_block(ext2_filsys fs
, blk64_t goal
,
994 ext2_resize_t rfs
= (ext2_resize_t
) fs
->priv_data
;
997 blk
= get_new_block(rfs
);
1001 #ifdef RESIZE2FS_DEBUG
1002 if (rfs
->flags
& 0xF)
1003 printf("get_alloc_block allocating %u\n", blk
);
1006 ext2fs_mark_block_bitmap(rfs
->old_fs
->block_map
, blk
);
1007 ext2fs_mark_block_bitmap(rfs
->new_fs
->block_map
, blk
);
1008 *ret
= (blk64_t
) blk
;
1012 static errcode_t
block_mover(ext2_resize_t rfs
)
1014 blk_t blk
, old_blk
, new_blk
;
1015 ext2_filsys fs
= rfs
->new_fs
;
1016 ext2_filsys old_fs
= rfs
->old_fs
;
1020 ext2_badblocks_list badblock_list
= 0;
1021 int bb_modified
= 0;
1023 fs
->get_alloc_block
= resize2fs_get_alloc_block
;
1024 old_fs
->get_alloc_block
= resize2fs_get_alloc_block
;
1026 retval
= ext2fs_read_bb_inode(old_fs
, &badblock_list
);
1030 new_blk
= fs
->super
->s_first_data_block
;
1031 if (!rfs
->itable_buf
) {
1032 retval
= ext2fs_get_array(fs
->blocksize
,
1033 fs
->inode_blocks_per_group
,
1038 retval
= ext2fs_create_extent_table(&rfs
->bmap
, 0);
1043 * The first step is to figure out where all of the blocks
1046 to_move
= moved
= 0;
1047 init_block_alloc(rfs
);
1048 for (blk
= old_fs
->super
->s_first_data_block
;
1049 blk
< old_fs
->super
->s_blocks_count
; blk
++) {
1050 if (!ext2fs_test_block_bitmap(old_fs
->block_map
, blk
))
1052 if (!ext2fs_test_block_bitmap(rfs
->move_blocks
, blk
))
1054 if (ext2fs_badblocks_list_test(badblock_list
, blk
)) {
1055 ext2fs_badblocks_list_del(badblock_list
, blk
);
1060 new_blk
= get_new_block(rfs
);
1065 ext2fs_block_alloc_stats(fs
, new_blk
, +1);
1066 ext2fs_add_extent_entry(rfs
->bmap
, blk
, new_blk
);
1072 ext2fs_free_extent_table(rfs
->bmap
);
1080 * Step two is to actually move the blocks
1082 retval
= ext2fs_iterate_extent(rfs
->bmap
, 0, 0, 0);
1083 if (retval
) goto errout
;
1085 if (rfs
->progress
) {
1086 retval
= (rfs
->progress
)(rfs
, E2_RSZ_BLOCK_RELOC_PASS
,
1092 retval
= ext2fs_iterate_extent(rfs
->bmap
, &old_blk
, &new_blk
, &size
);
1093 if (retval
) goto errout
;
1096 #ifdef RESIZE2FS_DEBUG
1097 if (rfs
->flags
& RESIZE_DEBUG_BMOVE
)
1098 printf("Moving %d blocks %u->%u\n",
1099 size
, old_blk
, new_blk
);
1103 if (c
> fs
->inode_blocks_per_group
)
1104 c
= fs
->inode_blocks_per_group
;
1105 retval
= io_channel_read_blk(fs
->io
, old_blk
, c
,
1107 if (retval
) goto errout
;
1108 retval
= io_channel_write_blk(fs
->io
, new_blk
, c
,
1110 if (retval
) goto errout
;
1115 if (rfs
->progress
) {
1116 io_channel_flush(fs
->io
);
1117 retval
= (rfs
->progress
)(rfs
,
1118 E2_RSZ_BLOCK_RELOC_PASS
,
1124 io_channel_flush(fs
->io
);
1128 if (badblock_list
) {
1129 if (!retval
&& bb_modified
)
1130 retval
= ext2fs_update_bb_inode(old_fs
,
1132 ext2fs_badblocks_list_free(badblock_list
);
1138 /* --------------------------------------------------------------------
1140 * Resize processing, phase 3
1142 * --------------------------------------------------------------------
1146 struct process_block_struct
{
1149 struct ext2_inode
* inode
;
1155 static int process_block(ext2_filsys fs
, blk_t
*block_nr
,
1156 e2_blkcnt_t blockcnt
,
1157 blk_t ref_block
EXT2FS_ATTR((unused
)),
1158 int ref_offset
EXT2FS_ATTR((unused
)), void *priv_data
)
1160 struct process_block_struct
*pb
;
1162 blk_t block
, new_block
;
1165 pb
= (struct process_block_struct
*) priv_data
;
1167 if (pb
->rfs
->bmap
) {
1168 new_block
= ext2fs_extent_translate(pb
->rfs
->bmap
, block
);
1170 *block_nr
= new_block
;
1171 ret
|= BLOCK_CHANGED
;
1173 #ifdef RESIZE2FS_DEBUG
1174 if (pb
->rfs
->flags
& RESIZE_DEBUG_BMOVE
)
1175 printf("ino=%u, blockcnt=%lld, %u->%u\n",
1176 pb
->ino
, blockcnt
, block
, new_block
);
1182 retval
= ext2fs_add_dir_block(fs
->dblist
, pb
->ino
,
1183 block
, (int) blockcnt
);
1195 static errcode_t
progress_callback(ext2_filsys fs
,
1196 ext2_inode_scan scan
EXT2FS_ATTR((unused
)),
1197 dgrp_t group
, void * priv_data
)
1199 ext2_resize_t rfs
= (ext2_resize_t
) priv_data
;
1203 * This check is to protect against old ext2 libraries. It
1204 * shouldn't be needed against new libraries.
1209 if (rfs
->progress
) {
1210 io_channel_flush(fs
->io
);
1211 retval
= (rfs
->progress
)(rfs
, E2_RSZ_INODE_SCAN_PASS
,
1212 group
+1, fs
->group_desc_count
);
1220 static errcode_t
inode_scan_and_fix(ext2_resize_t rfs
)
1222 struct process_block_struct pb
;
1223 ext2_ino_t ino
, new_inode
;
1224 struct ext2_inode
*inode
= NULL
;
1225 ext2_inode_scan scan
= NULL
;
1227 char *block_buf
= 0;
1228 ext2_ino_t start_to_move
;
1229 blk_t orig_size
, new_block
;
1232 if ((rfs
->old_fs
->group_desc_count
<=
1233 rfs
->new_fs
->group_desc_count
) &&
1238 * Save the original size of the old filesystem, and
1239 * temporarily set the size to be the new size if the new size
1240 * is larger. We need to do this to avoid catching an error
1241 * by the block iterator routines
1243 orig_size
= rfs
->old_fs
->super
->s_blocks_count
;
1244 if (orig_size
< rfs
->new_fs
->super
->s_blocks_count
)
1245 rfs
->old_fs
->super
->s_blocks_count
=
1246 rfs
->new_fs
->super
->s_blocks_count
;
1248 retval
= ext2fs_open_inode_scan(rfs
->old_fs
, 0, &scan
);
1249 if (retval
) goto errout
;
1251 retval
= ext2fs_init_dblist(rfs
->old_fs
, 0);
1252 if (retval
) goto errout
;
1253 retval
= ext2fs_get_array(rfs
->old_fs
->blocksize
, 3, &block_buf
);
1254 if (retval
) goto errout
;
1256 start_to_move
= (rfs
->new_fs
->group_desc_count
*
1257 rfs
->new_fs
->super
->s_inodes_per_group
);
1259 if (rfs
->progress
) {
1260 retval
= (rfs
->progress
)(rfs
, E2_RSZ_INODE_SCAN_PASS
,
1261 0, rfs
->old_fs
->group_desc_count
);
1265 ext2fs_set_inode_callback(scan
, progress_callback
, (void *) rfs
);
1269 new_inode
= EXT2_FIRST_INODE(rfs
->new_fs
->super
);
1270 inode_size
= EXT2_INODE_SIZE(rfs
->new_fs
->super
);
1271 inode
= malloc(inode_size
);
1277 * First, copy all of the inodes that need to be moved
1278 * elsewhere in the inode table
1281 retval
= ext2fs_get_next_inode_full(scan
, &ino
, inode
, inode_size
);
1282 if (retval
) goto errout
;
1286 if (inode
->i_links_count
== 0 && ino
!= EXT2_RESIZE_INO
)
1287 continue; /* inode not in use */
1289 pb
.is_dir
= LINUX_S_ISDIR(inode
->i_mode
);
1292 if (inode
->i_file_acl
&& rfs
->bmap
) {
1293 new_block
= ext2fs_extent_translate(rfs
->bmap
,
1296 inode
->i_file_acl
= new_block
;
1297 retval
= ext2fs_write_inode_full(rfs
->old_fs
,
1298 ino
, inode
, inode_size
);
1299 if (retval
) goto errout
;
1303 if (ext2fs_inode_has_valid_blocks(inode
) &&
1304 (rfs
->bmap
|| pb
.is_dir
)) {
1306 retval
= ext2fs_block_iterate2(rfs
->old_fs
,
1308 process_block
, &pb
);
1317 if (ino
<= start_to_move
)
1318 continue; /* Don't need to move it. */
1323 retval
= ext2fs_new_inode(rfs
->new_fs
, 0, 0, 0, &new_inode
);
1327 ext2fs_inode_alloc_stats2(rfs
->new_fs
, new_inode
, +1,
1330 /* Get the new version of the inode */
1331 retval
= ext2fs_read_inode_full(rfs
->old_fs
, ino
,
1333 if (retval
) goto errout
;
1335 inode
->i_ctime
= time(0);
1336 retval
= ext2fs_write_inode_full(rfs
->old_fs
, new_inode
,
1338 if (retval
) goto errout
;
1340 #ifdef RESIZE2FS_DEBUG
1341 if (rfs
->flags
& RESIZE_DEBUG_INODEMAP
)
1342 printf("Inode moved %u->%u\n", ino
, new_inode
);
1345 retval
= ext2fs_create_extent_table(&rfs
->imap
, 0);
1349 ext2fs_add_extent_entry(rfs
->imap
, ino
, new_inode
);
1351 io_channel_flush(rfs
->old_fs
->io
);
1354 rfs
->old_fs
->super
->s_blocks_count
= orig_size
;
1356 ext2fs_free_extent_table(rfs
->bmap
);
1360 ext2fs_close_inode_scan(scan
);
1362 ext2fs_free_mem(&block_buf
);
1368 /* --------------------------------------------------------------------
1370 * Resize processing, phase 4.
1372 * --------------------------------------------------------------------
1378 unsigned long max_dirs
;
1382 static int check_and_change_inodes(ext2_ino_t dir
,
1383 int entry
EXT2FS_ATTR((unused
)),
1384 struct ext2_dir_entry
*dirent
, int offset
,
1385 int blocksize
EXT2FS_ATTR((unused
)),
1386 char *buf
EXT2FS_ATTR((unused
)),
1389 struct istruct
*is
= (struct istruct
*) priv_data
;
1390 struct ext2_inode inode
;
1391 ext2_ino_t new_inode
;
1394 if (is
->rfs
->progress
&& offset
== 0) {
1395 io_channel_flush(is
->rfs
->old_fs
->io
);
1396 is
->err
= (is
->rfs
->progress
)(is
->rfs
,
1397 E2_RSZ_INODE_REF_UPD_PASS
,
1398 ++is
->num
, is
->max_dirs
);
1400 return DIRENT_ABORT
;
1406 new_inode
= ext2fs_extent_translate(is
->rfs
->imap
, dirent
->inode
);
1410 #ifdef RESIZE2FS_DEBUG
1411 if (is
->rfs
->flags
& RESIZE_DEBUG_INODEMAP
)
1412 printf("Inode translate (dir=%u, name=%.*s, %u->%u)\n",
1413 dir
, dirent
->name_len
&0xFF, dirent
->name
,
1414 dirent
->inode
, new_inode
);
1417 dirent
->inode
= new_inode
;
1419 /* Update the directory mtime and ctime */
1420 retval
= ext2fs_read_inode(is
->rfs
->old_fs
, dir
, &inode
);
1422 inode
.i_mtime
= inode
.i_ctime
= time(0);
1423 is
->err
= ext2fs_write_inode(is
->rfs
->old_fs
, dir
, &inode
);
1425 return DIRENT_ABORT
;
1428 return DIRENT_CHANGED
;
1431 static errcode_t
inode_ref_fix(ext2_resize_t rfs
)
1440 * Now, we iterate over all of the directories to update the
1444 is
.max_dirs
= ext2fs_dblist_count(rfs
->old_fs
->dblist
);
1448 if (rfs
->progress
) {
1449 retval
= (rfs
->progress
)(rfs
, E2_RSZ_INODE_REF_UPD_PASS
,
1455 retval
= ext2fs_dblist_dir_iterate(rfs
->old_fs
->dblist
,
1456 DIRENT_FLAG_INCLUDE_EMPTY
, 0,
1457 check_and_change_inodes
, &is
);
1465 if (rfs
->progress
&& (is
.num
< is
.max_dirs
))
1466 (rfs
->progress
)(rfs
, E2_RSZ_INODE_REF_UPD_PASS
,
1467 is
.max_dirs
, is
.max_dirs
);
1470 ext2fs_free_extent_table(rfs
->imap
);
1476 /* --------------------------------------------------------------------
1478 * Resize processing, phase 5.
1480 * In this phase we actually move the inode table around, and then
1481 * update the summary statistics. This is scary, since aborting here
1482 * will potentially scramble the filesystem. (We are moving the
1483 * inode tables around in place, and so the potential for lost data,
1484 * or at the very least scrambling the mapping between filenames and
1485 * inode numbers is very high in case of a power failure here.)
1486 * --------------------------------------------------------------------
1491 * A very scary routine --- this one moves the inode table around!!!
1493 * After this you have to use the rfs->new_fs file handle to read and
1496 static errcode_t
move_itables(ext2_resize_t rfs
)
1498 int n
, num
, size
, diff
;
1499 dgrp_t i
, max_groups
;
1500 ext2_filsys fs
= rfs
->new_fs
;
1502 blk_t old_blk
, new_blk
, blk
;
1504 int j
, to_move
, moved
;
1506 max_groups
= fs
->group_desc_count
;
1507 if (max_groups
> rfs
->old_fs
->group_desc_count
)
1508 max_groups
= rfs
->old_fs
->group_desc_count
;
1510 size
= fs
->blocksize
* fs
->inode_blocks_per_group
;
1511 if (!rfs
->itable_buf
) {
1512 retval
= ext2fs_get_mem(size
, &rfs
->itable_buf
);
1518 * Figure out how many inode tables we need to move
1520 to_move
= moved
= 0;
1521 for (i
=0; i
< max_groups
; i
++)
1522 if (rfs
->old_fs
->group_desc
[i
].bg_inode_table
!=
1523 fs
->group_desc
[i
].bg_inode_table
)
1529 if (rfs
->progress
) {
1530 retval
= rfs
->progress(rfs
, E2_RSZ_MOVE_ITABLE_PASS
,
1536 rfs
->old_fs
->flags
|= EXT2_FLAG_MASTER_SB_ONLY
;
1538 for (i
=0; i
< max_groups
; i
++) {
1539 old_blk
= rfs
->old_fs
->group_desc
[i
].bg_inode_table
;
1540 new_blk
= fs
->group_desc
[i
].bg_inode_table
;
1541 diff
= new_blk
- old_blk
;
1543 #ifdef RESIZE2FS_DEBUG
1544 if (rfs
->flags
& RESIZE_DEBUG_ITABLEMOVE
)
1545 printf("Itable move group %d block %u->%u (diff %d)\n",
1546 i
, old_blk
, new_blk
, diff
);
1552 retval
= io_channel_read_blk(fs
->io
, old_blk
,
1553 fs
->inode_blocks_per_group
,
1558 * The end of the inode table segment often contains
1559 * all zeros, and we're often only moving the inode
1560 * table down a block or two. If so, we can optimize
1561 * things by not rewriting blocks that we know to be zero
1564 for (cp
= rfs
->itable_buf
+size
-1, n
=0; n
< size
; n
++, cp
--)
1567 n
= n
>> EXT2_BLOCK_SIZE_BITS(fs
->super
);
1568 #ifdef RESIZE2FS_DEBUG
1569 if (rfs
->flags
& RESIZE_DEBUG_ITABLEMOVE
)
1570 printf("%d blocks of zeros...\n", n
);
1572 num
= fs
->inode_blocks_per_group
;
1576 retval
= io_channel_write_blk(fs
->io
, new_blk
,
1577 num
, rfs
->itable_buf
);
1579 io_channel_write_blk(fs
->io
, old_blk
,
1580 num
, rfs
->itable_buf
);
1584 retval
= io_channel_write_blk(fs
->io
,
1585 old_blk
+ fs
->inode_blocks_per_group
,
1586 diff
, (rfs
->itable_buf
+
1587 (fs
->inode_blocks_per_group
- diff
) *
1593 for (blk
= rfs
->old_fs
->group_desc
[i
].bg_inode_table
, j
=0;
1594 j
< fs
->inode_blocks_per_group
; j
++, blk
++)
1595 ext2fs_block_alloc_stats(fs
, blk
, -1);
1597 rfs
->old_fs
->group_desc
[i
].bg_inode_table
= new_blk
;
1598 ext2fs_group_desc_csum_set(rfs
->old_fs
, i
);
1599 ext2fs_mark_super_dirty(rfs
->old_fs
);
1600 ext2fs_flush(rfs
->old_fs
);
1602 if (rfs
->progress
) {
1603 retval
= rfs
->progress(rfs
, E2_RSZ_MOVE_ITABLE_PASS
,
1609 mark_table_blocks(fs
, fs
->block_map
);
1611 #ifdef RESIZE2FS_DEBUG
1612 if (rfs
->flags
& RESIZE_DEBUG_ITABLEMOVE
)
1613 printf("Inode table move finished.\n");
1622 * Fix the resize inode
1624 static errcode_t
fix_resize_inode(ext2_filsys fs
)
1626 struct ext2_inode inode
;
1631 if (!(fs
->super
->s_feature_compat
&
1632 EXT2_FEATURE_COMPAT_RESIZE_INODE
))
1635 retval
= ext2fs_get_mem(fs
->blocksize
, &block_buf
);
1636 if (retval
) goto errout
;
1638 retval
= ext2fs_read_inode(fs
, EXT2_RESIZE_INO
, &inode
);
1639 if (retval
) goto errout
;
1641 if (fs
->super
->s_reserved_gdt_blocks
== 0) {
1642 fs
->super
->s_feature_compat
&=
1643 ~EXT2_FEATURE_COMPAT_RESIZE_INODE
;
1644 ext2fs_mark_super_dirty(fs
);
1646 if ((blk
= inode
.i_block
[EXT2_DIND_BLOCK
]) != 0)
1647 ext2fs_block_alloc_stats(fs
, blk
, -1);
1649 memset(&inode
, 0, sizeof(inode
));
1651 retval
= ext2fs_write_inode(fs
, EXT2_RESIZE_INO
, &inode
);
1655 ext2fs_iblk_set(fs
, &inode
, 1);
1657 retval
= ext2fs_write_inode(fs
, EXT2_RESIZE_INO
, &inode
);
1658 if (retval
) goto errout
;
1660 if (!inode
.i_block
[EXT2_DIND_BLOCK
]) {
1662 * Avoid zeroing out block #0; that's rude. This
1663 * should never happen anyway since the filesystem
1664 * should be fsck'ed and we assume it is consistent.
1667 _("Should never happen: resize inode corrupt!\n"));
1671 memset(block_buf
, 0, fs
->blocksize
);
1673 retval
= io_channel_write_blk(fs
->io
, inode
.i_block
[EXT2_DIND_BLOCK
],
1675 if (retval
) goto errout
;
1677 retval
= ext2fs_create_resize_inode(fs
);
1683 ext2fs_free_mem(&block_buf
);
1688 * Finally, recalculate the summary information
1690 static errcode_t
ext2fs_calculate_summary_stats(ext2_filsys fs
)
1694 unsigned int group
= 0;
1695 unsigned int count
= 0;
1699 blk_t super_blk
, old_desc_blk
, new_desc_blk
;
1700 int old_desc_blocks
;
1703 * First calculate the block statistics
1705 uninit
= fs
->group_desc
[group
].bg_flags
& EXT2_BG_BLOCK_UNINIT
;
1706 ext2fs_super_and_bgd_loc(fs
, group
, &super_blk
, &old_desc_blk
,
1708 if (fs
->super
->s_feature_incompat
& EXT2_FEATURE_INCOMPAT_META_BG
)
1709 old_desc_blocks
= fs
->super
->s_first_meta_bg
;
1711 old_desc_blocks
= fs
->desc_blocks
+
1712 fs
->super
->s_reserved_gdt_blocks
;
1713 for (blk
= fs
->super
->s_first_data_block
;
1714 blk
< fs
->super
->s_blocks_count
; blk
++) {
1716 !((blk
== super_blk
) ||
1717 ((old_desc_blk
&& old_desc_blocks
&&
1718 (blk
>= old_desc_blk
) &&
1719 (blk
< old_desc_blk
+ old_desc_blocks
))) ||
1720 ((new_desc_blk
&& (blk
== new_desc_blk
))) ||
1721 (blk
== fs
->group_desc
[group
].bg_block_bitmap
) ||
1722 (blk
== fs
->group_desc
[group
].bg_inode_bitmap
) ||
1723 ((blk
>= fs
->group_desc
[group
].bg_inode_table
&&
1724 (blk
< fs
->group_desc
[group
].bg_inode_table
1725 + fs
->inode_blocks_per_group
))))) ||
1726 (!ext2fs_fast_test_block_bitmap(fs
->block_map
, blk
))) {
1731 if ((count
== fs
->super
->s_blocks_per_group
) ||
1732 (blk
== fs
->super
->s_blocks_count
-1)) {
1733 fs
->group_desc
[group
].bg_free_blocks_count
=
1735 ext2fs_group_desc_csum_set(fs
, group
);
1739 uninit
= (fs
->group_desc
[group
].bg_flags
&
1740 EXT2_BG_BLOCK_UNINIT
);
1741 ext2fs_super_and_bgd_loc(fs
, group
, &super_blk
,
1744 if (fs
->super
->s_feature_incompat
&
1745 EXT2_FEATURE_INCOMPAT_META_BG
)
1746 old_desc_blocks
= fs
->super
->s_first_meta_bg
;
1748 old_desc_blocks
= fs
->desc_blocks
+
1749 fs
->super
->s_reserved_gdt_blocks
;
1752 fs
->super
->s_free_blocks_count
= total_free
;
1755 * Next, calculate the inode statistics
1762 /* Protect loop from wrap-around if s_inodes_count maxed */
1763 uninit
= fs
->group_desc
[group
].bg_flags
& EXT2_BG_INODE_UNINIT
;
1764 for (ino
= 1; ino
<= fs
->super
->s_inodes_count
&& ino
> 0; ino
++) {
1766 !ext2fs_fast_test_inode_bitmap(fs
->inode_map
, ino
)) {
1771 if ((count
== fs
->super
->s_inodes_per_group
) ||
1772 (ino
== fs
->super
->s_inodes_count
)) {
1773 fs
->group_desc
[group
].bg_free_inodes_count
=
1775 ext2fs_group_desc_csum_set(fs
, group
);
1779 uninit
= (fs
->group_desc
[group
].bg_flags
&
1780 EXT2_BG_INODE_UNINIT
);
1783 fs
->super
->s_free_inodes_count
= total_free
;
1784 ext2fs_mark_super_dirty(fs
);
1789 * calcluate the minimum number of blocks the given fs can be resized to
1791 blk_t
calculate_minimum_resize_size(ext2_filsys fs
)
1793 blk_t inode_count
, blks_needed
, groups
, data_blocks
;
1794 blk_t grp
, data_needed
, last_start
;
1795 int overhead
= 0, num_of_superblocks
= 0;
1798 * first figure out how many group descriptors we need to
1799 * handle the number of inodes we have
1801 inode_count
= fs
->super
->s_inodes_count
-
1802 fs
->super
->s_free_inodes_count
;
1803 blks_needed
= ext2fs_div_ceil(inode_count
,
1804 fs
->super
->s_inodes_per_group
) *
1805 EXT2_BLOCKS_PER_GROUP(fs
->super
);
1806 groups
= ext2fs_div_ceil(blks_needed
,
1807 EXT2_BLOCKS_PER_GROUP(fs
->super
));
1810 * we need to figure out how many backup superblocks we have so we can
1811 * account for that in the metadata
1813 for (grp
= 0; grp
< fs
->group_desc_count
; grp
++) {
1814 if (ext2fs_bg_has_super(fs
, grp
))
1815 num_of_superblocks
++;
1818 /* calculate how many blocks are needed for data */
1819 data_needed
= fs
->super
->s_blocks_count
-
1820 fs
->super
->s_free_blocks_count
;
1821 data_needed
-= SUPER_OVERHEAD(fs
) * num_of_superblocks
;
1822 data_needed
-= META_OVERHEAD(fs
) * fs
->group_desc_count
;
1825 * figure out how many data blocks we have given the number of groups
1826 * we need for our inodes
1828 data_blocks
= groups
* EXT2_BLOCKS_PER_GROUP(fs
->super
);
1830 for (grp
= 0; grp
< groups
; grp
++) {
1831 overhead
= META_OVERHEAD(fs
);
1833 if (ext2fs_bg_has_super(fs
, grp
))
1834 overhead
+= SUPER_OVERHEAD(fs
);
1837 * we want to keep track of how much data we can store in
1838 * the groups leading up to the last group so we can determine
1839 * how big the last group needs to be
1841 if (grp
!= (groups
- 1))
1842 last_start
+= EXT2_BLOCKS_PER_GROUP(fs
->super
) -
1845 data_blocks
-= overhead
;
1849 * if we need more group descriptors in order to accomodate our data
1850 * then we need to add them here
1852 while (data_needed
> data_blocks
) {
1853 blk_t remainder
= data_needed
- data_blocks
;
1856 /* figure out how many more groups we need for the data */
1857 extra_grps
= ext2fs_div_ceil(remainder
,
1858 EXT2_BLOCKS_PER_GROUP(fs
->super
));
1860 data_blocks
+= extra_grps
* EXT2_BLOCKS_PER_GROUP(fs
->super
);
1862 /* ok we have to account for the last group */
1863 overhead
= META_OVERHEAD(fs
);
1864 if (ext2fs_bg_has_super(fs
, groups
-1))
1865 overhead
+= SUPER_OVERHEAD(fs
);
1866 last_start
+= EXT2_BLOCKS_PER_GROUP(fs
->super
) - overhead
;
1868 for (grp
= groups
; grp
< groups
+extra_grps
; grp
++) {
1869 overhead
= META_OVERHEAD(fs
);
1870 if (ext2fs_bg_has_super(fs
, grp
))
1871 overhead
+= SUPER_OVERHEAD(fs
);
1874 * again, we need to see how much data we cram into
1875 * all of the groups leading up to the last group
1877 if (grp
!= (groups
+ extra_grps
- 1))
1878 last_start
+= EXT2_BLOCKS_PER_GROUP(fs
->super
)
1881 data_blocks
-= overhead
;
1884 groups
+= extra_grps
;
1887 /* now for the fun voodoo */
1888 overhead
= META_OVERHEAD(fs
);
1891 * if this is the case then the last group is going to have data in it
1892 * so we need to adjust the size of the last group accordingly
1894 if (last_start
< data_needed
) {
1895 blk_t remainder
= data_needed
- last_start
;
1898 * 50 is a magic number that mkfs/resize uses to see if its
1899 * even worth making/resizing the fs. basically you need to
1900 * have at least 50 blocks in addition to the blocks needed
1901 * for the metadata in the last group
1904 overhead
+= remainder
;
1910 if (ext2fs_bg_has_super(fs
, groups
-1))
1911 overhead
+= SUPER_OVERHEAD(fs
);
1914 * since our last group doesn't have to be BLOCKS_PER_GROUP large, we
1915 * only do groups-1, and then add the number of blocks needed to
1916 * handle the group descriptor metadata+data that we need
1918 blks_needed
= (groups
-1) * EXT2_BLOCKS_PER_GROUP(fs
->super
);
1919 blks_needed
+= overhead
;