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 errcode_t
adjust_superblock(ext2_resize_t rfs
, blk_t new_size
);
44 static errcode_t
blocks_to_move(ext2_resize_t rfs
);
45 static errcode_t
block_mover(ext2_resize_t rfs
);
46 static errcode_t
inode_scan_and_fix(ext2_resize_t rfs
);
47 static errcode_t
inode_ref_fix(ext2_resize_t rfs
);
48 static errcode_t
move_itables(ext2_resize_t rfs
);
49 static errcode_t
fix_resize_inode(ext2_filsys fs
);
50 static errcode_t
ext2fs_calculate_summary_stats(ext2_filsys fs
);
53 * Some helper CPP macros
55 #define FS_BLOCK_BM(fs, i) ((fs)->group_desc[(i)].bg_block_bitmap)
56 #define FS_INODE_BM(fs, i) ((fs)->group_desc[(i)].bg_inode_bitmap)
57 #define FS_INODE_TB(fs, i) ((fs)->group_desc[(i)].bg_inode_table)
59 #define IS_BLOCK_BM(fs, i, blk) ((blk) == FS_BLOCK_BM((fs),(i)))
60 #define IS_INODE_BM(fs, i, blk) ((blk) == FS_INODE_BM((fs),(i)))
62 #define IS_INODE_TB(fs, i, blk) (((blk) >= FS_INODE_TB((fs), (i))) && \
63 ((blk) < (FS_INODE_TB((fs), (i)) + \
64 (fs)->inode_blocks_per_group)))
69 * This is the top-level routine which does the dirty deed....
71 errcode_t
resize_fs(ext2_filsys fs
, blk_t
*new_size
, int flags
,
72 errcode_t (*progress
)(ext2_resize_t rfs
, int pass
,
74 unsigned long max_val
))
79 retval
= ext2fs_read_bitmaps(fs
);
84 * Create the data structure
86 retval
= ext2fs_get_mem(sizeof(struct ext2_resize_struct
), &rfs
);
89 memset(rfs
, 0, sizeof(struct ext2_resize_struct
));
94 rfs
->progress
= progress
;
95 retval
= ext2fs_dup_handle(fs
, &rfs
->new_fs
);
99 retval
= adjust_superblock(rfs
, *new_size
);
103 *new_size
= rfs
->new_fs
->super
->s_blocks_count
;
105 retval
= blocks_to_move(rfs
);
109 #ifdef RESIZE2FS_DEBUG
110 if (rfs
->flags
& RESIZE_DEBUG_BMOVE
)
111 printf("Number of free blocks: %u/%u, Needed: %d\n",
112 rfs
->old_fs
->super
->s_free_blocks_count
,
113 rfs
->new_fs
->super
->s_free_blocks_count
,
117 retval
= block_mover(rfs
);
121 retval
= inode_scan_and_fix(rfs
);
125 retval
= inode_ref_fix(rfs
);
129 retval
= move_itables(rfs
);
133 retval
= ext2fs_calculate_summary_stats(rfs
->new_fs
);
137 retval
= fix_resize_inode(rfs
->new_fs
);
141 rfs
->new_fs
->flags
&= ~EXT2_FLAG_MASTER_SB_ONLY
;
142 retval
= ext2fs_close(rfs
->new_fs
);
148 ext2fs_free(rfs
->old_fs
);
150 ext2fs_free_mem(&rfs
->itable_buf
);
151 ext2fs_free_mem(&rfs
);
157 ext2fs_free(rfs
->new_fs
);
159 ext2fs_free_mem(&rfs
->itable_buf
);
160 ext2fs_free_mem(&rfs
);
164 /* --------------------------------------------------------------------
166 * Resize processing, phase 1.
168 * In this phase we adjust the in-memory superblock information, and
169 * initialize any new parts of the inode table. The new parts of the
170 * inode table are created in virgin disk space, so we can abort here
171 * without any side effects.
172 * --------------------------------------------------------------------
176 * This routine is shared by the online and offline resize routines.
177 * All of the information which is adjusted in memory is done here.
179 errcode_t
adjust_fs_info(ext2_filsys fs
, ext2_filsys old_fs
, blk_t new_size
)
184 blk_t blk
, group_block
;
186 int adj
, old_numblocks
, numblocks
, adjblocks
;
187 unsigned long i
, j
, old_desc_blocks
, max_group
;
188 unsigned int meta_bg
, meta_bg_size
;
190 unsigned long long new_inodes
; /* u64 to check for overflow */
192 fs
->super
->s_blocks_count
= new_size
;
195 fs
->group_desc_count
= ext2fs_div_ceil(fs
->super
->s_blocks_count
-
196 fs
->super
->s_first_data_block
,
197 EXT2_BLOCKS_PER_GROUP(fs
->super
));
198 if (fs
->group_desc_count
== 0)
199 return EXT2_ET_TOOSMALL
;
200 fs
->desc_blocks
= ext2fs_div_ceil(fs
->group_desc_count
,
201 EXT2_DESC_PER_BLOCK(fs
->super
));
204 * Overhead is the number of bookkeeping blocks per group. It
205 * includes the superblock backup, the group descriptor
206 * backups, the inode bitmap, the block bitmap, and the inode
209 overhead
= (int) (2 + fs
->inode_blocks_per_group
);
211 if (ext2fs_bg_has_super(fs
, fs
->group_desc_count
- 1))
212 overhead
+= 1 + fs
->desc_blocks
+
213 fs
->super
->s_reserved_gdt_blocks
;
216 * See if the last group is big enough to support the
217 * necessary data structures. If not, we need to get rid of
220 rem
= (fs
->super
->s_blocks_count
- fs
->super
->s_first_data_block
) %
221 fs
->super
->s_blocks_per_group
;
222 if ((fs
->group_desc_count
== 1) && rem
&& (rem
< overhead
))
223 return EXT2_ET_TOOSMALL
;
224 if (rem
&& (rem
< overhead
+50)) {
225 fs
->super
->s_blocks_count
-= rem
;
229 * Adjust the number of inodes
231 new_inodes
=(unsigned long long) fs
->super
->s_inodes_per_group
* fs
->group_desc_count
;
232 if (new_inodes
> ~0U) {
233 fprintf(stderr
, _("inodes (%llu) must be less than %u"),
235 return EXT2_ET_TOO_MANY_INODES
;
237 fs
->super
->s_inodes_count
= fs
->super
->s_inodes_per_group
*
238 fs
->group_desc_count
;
241 * Adjust the number of free blocks
243 blk
= old_fs
->super
->s_blocks_count
;
244 if (blk
> fs
->super
->s_blocks_count
)
245 fs
->super
->s_free_blocks_count
-=
246 (blk
- fs
->super
->s_blocks_count
);
248 fs
->super
->s_free_blocks_count
+=
249 (fs
->super
->s_blocks_count
- blk
);
252 * Adjust the number of reserved blocks
254 blk
= (__u64
)old_fs
->super
->s_r_blocks_count
* 100 /
255 old_fs
->super
->s_blocks_count
;
256 fs
->super
->s_r_blocks_count
= e2p_percent(blk
,
257 fs
->super
->s_blocks_count
);
260 * Adjust the bitmaps for size
262 retval
= ext2fs_resize_inode_bitmap(fs
->super
->s_inodes_count
,
263 fs
->super
->s_inodes_count
,
265 if (retval
) goto errout
;
267 real_end
= ((EXT2_BLOCKS_PER_GROUP(fs
->super
)
268 * fs
->group_desc_count
)) - 1 +
269 fs
->super
->s_first_data_block
;
270 retval
= ext2fs_resize_block_bitmap(fs
->super
->s_blocks_count
-1,
271 real_end
, fs
->block_map
);
273 if (retval
) goto errout
;
276 * Reallocate the group descriptors as necessary.
278 if (old_fs
->desc_blocks
!= fs
->desc_blocks
) {
279 retval
= ext2fs_resize_mem(old_fs
->desc_blocks
*
281 fs
->desc_blocks
* fs
->blocksize
,
285 if (fs
->desc_blocks
> old_fs
->desc_blocks
)
286 memset((char *) fs
->group_desc
+
287 (old_fs
->desc_blocks
* fs
->blocksize
), 0,
288 (fs
->desc_blocks
- old_fs
->desc_blocks
) *
293 * If the resize_inode feature is set, and we are changing the
294 * number of descriptor blocks, then adjust
295 * s_reserved_gdt_blocks if possible to avoid needing to move
296 * the inode table either now or in the future.
298 if ((fs
->super
->s_feature_compat
&
299 EXT2_FEATURE_COMPAT_RESIZE_INODE
) &&
300 (old_fs
->desc_blocks
!= fs
->desc_blocks
)) {
303 new = ((int) fs
->super
->s_reserved_gdt_blocks
) +
304 (old_fs
->desc_blocks
- fs
->desc_blocks
);
307 if (new > (int) fs
->blocksize
/4)
308 new = fs
->blocksize
/4;
309 fs
->super
->s_reserved_gdt_blocks
= new;
311 fs
->super
->s_feature_compat
&=
312 ~EXT2_FEATURE_COMPAT_RESIZE_INODE
;
316 * If we are shrinking the number block groups, we're done and
319 if (old_fs
->group_desc_count
> fs
->group_desc_count
) {
325 * Fix the count of the last (old) block group
327 old_numblocks
= (old_fs
->super
->s_blocks_count
-
328 old_fs
->super
->s_first_data_block
) %
329 old_fs
->super
->s_blocks_per_group
;
331 old_numblocks
= old_fs
->super
->s_blocks_per_group
;
332 if (old_fs
->group_desc_count
== fs
->group_desc_count
) {
333 numblocks
= (fs
->super
->s_blocks_count
-
334 fs
->super
->s_first_data_block
) %
335 fs
->super
->s_blocks_per_group
;
337 numblocks
= fs
->super
->s_blocks_per_group
;
339 numblocks
= fs
->super
->s_blocks_per_group
;
340 i
= old_fs
->group_desc_count
- 1;
341 fs
->group_desc
[i
].bg_free_blocks_count
+= (numblocks
-old_numblocks
);
344 * If the number of block groups is staying the same, we're
345 * done and can exit now. (If the number block groups is
346 * shrinking, we had exited earlier.)
348 if (old_fs
->group_desc_count
>= fs
->group_desc_count
) {
354 * Initialize the new block group descriptors
356 group_block
= fs
->super
->s_first_data_block
+
357 old_fs
->group_desc_count
* fs
->super
->s_blocks_per_group
;
359 adj
= old_fs
->group_desc_count
;
360 max_group
= fs
->group_desc_count
- adj
;
361 if (fs
->super
->s_feature_incompat
& EXT2_FEATURE_INCOMPAT_META_BG
)
362 old_desc_blocks
= fs
->super
->s_first_meta_bg
;
364 old_desc_blocks
= fs
->desc_blocks
+
365 fs
->super
->s_reserved_gdt_blocks
;
366 for (i
= old_fs
->group_desc_count
;
367 i
< fs
->group_desc_count
; i
++) {
368 memset(&fs
->group_desc
[i
], 0,
369 sizeof(struct ext2_group_desc
));
372 if (i
== fs
->group_desc_count
-1) {
373 numblocks
= (fs
->super
->s_blocks_count
-
374 fs
->super
->s_first_data_block
) %
375 fs
->super
->s_blocks_per_group
;
377 numblocks
= fs
->super
->s_blocks_per_group
;
379 numblocks
= fs
->super
->s_blocks_per_group
;
381 has_super
= ext2fs_bg_has_super(fs
, i
);
383 ext2fs_mark_block_bitmap(fs
->block_map
, group_block
);
386 meta_bg_size
= EXT2_DESC_PER_BLOCK(fs
->super
);
387 meta_bg
= i
/ meta_bg_size
;
388 if (!(fs
->super
->s_feature_incompat
&
389 EXT2_FEATURE_INCOMPAT_META_BG
) ||
390 (meta_bg
< fs
->super
->s_first_meta_bg
)) {
392 for (j
=0; j
< old_desc_blocks
; j
++)
393 ext2fs_mark_block_bitmap(fs
->block_map
,
394 group_block
+ 1 + j
);
395 adjblocks
+= old_desc_blocks
;
400 if (((i
% meta_bg_size
) == 0) ||
401 ((i
% meta_bg_size
) == 1) ||
402 ((i
% meta_bg_size
) == (meta_bg_size
-1)))
403 ext2fs_mark_block_bitmap(fs
->block_map
,
404 group_block
+ has_super
);
407 adjblocks
+= 2 + fs
->inode_blocks_per_group
;
409 numblocks
-= adjblocks
;
410 fs
->super
->s_free_blocks_count
-= adjblocks
;
411 fs
->super
->s_free_inodes_count
+=
412 fs
->super
->s_inodes_per_group
;
413 fs
->group_desc
[i
].bg_free_blocks_count
= numblocks
;
414 fs
->group_desc
[i
].bg_free_inodes_count
=
415 fs
->super
->s_inodes_per_group
;
416 fs
->group_desc
[i
].bg_used_dirs_count
= 0;
418 retval
= ext2fs_allocate_group_table(fs
, i
, 0);
419 if (retval
) goto errout
;
421 group_block
+= fs
->super
->s_blocks_per_group
;
430 * This routine adjusts the superblock and other data structures, both
431 * in disk as well as in memory...
433 static errcode_t
adjust_superblock(ext2_resize_t rfs
, blk_t new_size
)
440 unsigned long max_group
;
443 ext2fs_mark_super_dirty(fs
);
444 ext2fs_mark_bb_dirty(fs
);
445 ext2fs_mark_ib_dirty(fs
);
447 retval
= adjust_fs_info(fs
, rfs
->old_fs
, new_size
);
452 * Check to make sure there are enough inodes
454 if ((rfs
->old_fs
->super
->s_inodes_count
-
455 rfs
->old_fs
->super
->s_free_inodes_count
) >
456 rfs
->new_fs
->super
->s_inodes_count
) {
462 * If we are shrinking the number block groups, we're done and
465 if (rfs
->old_fs
->group_desc_count
> fs
->group_desc_count
) {
471 * If the number of block groups is staying the same, we're
472 * done and can exit now. (If the number block groups is
473 * shrinking, we had exited earlier.)
475 if (rfs
->old_fs
->group_desc_count
>= fs
->group_desc_count
) {
481 * Initialize the new block group descriptors
483 retval
= ext2fs_get_array(fs
->blocksize
, fs
->inode_blocks_per_group
,
488 memset(rfs
->itable_buf
, 0, fs
->blocksize
* fs
->inode_blocks_per_group
);
489 group_block
= fs
->super
->s_first_data_block
+
490 rfs
->old_fs
->group_desc_count
* fs
->super
->s_blocks_per_group
;
492 adj
= rfs
->old_fs
->group_desc_count
;
493 max_group
= fs
->group_desc_count
- adj
;
495 retval
= rfs
->progress(rfs
, E2_RSZ_EXTEND_ITABLE_PASS
,
500 for (i
= rfs
->old_fs
->group_desc_count
;
501 i
< fs
->group_desc_count
; i
++) {
503 * Write out the new inode table
505 retval
= io_channel_write_blk(fs
->io
,
506 fs
->group_desc
[i
].bg_inode_table
,
507 fs
->inode_blocks_per_group
,
509 if (retval
) goto errout
;
511 io_channel_flush(fs
->io
);
513 retval
= rfs
->progress(rfs
, E2_RSZ_EXTEND_ITABLE_PASS
,
514 i
- adj
+ 1, max_group
);
518 group_block
+= fs
->super
->s_blocks_per_group
;
520 io_channel_flush(fs
->io
);
527 /* --------------------------------------------------------------------
529 * Resize processing, phase 2.
531 * In this phase we adjust determine which blocks need to be moved, in
532 * blocks_to_move(). We then copy the blocks to their ultimate new
533 * destinations using block_mover(). Since we are copying blocks to
534 * their new locations, again during this pass we can abort without
536 * --------------------------------------------------------------------
540 * This helper function creates a block bitmap with all of the
541 * filesystem meta-data blocks.
543 static errcode_t
mark_table_blocks(ext2_filsys fs
,
544 ext2fs_block_bitmap bmap
)
549 unsigned long meta_bg_size
;
550 unsigned int old_desc_blocks
;
552 meta_bg_size
= EXT2_DESC_PER_BLOCK(fs
->super
);
553 if (fs
->super
->s_feature_incompat
& EXT2_FEATURE_INCOMPAT_META_BG
)
554 old_desc_blocks
= fs
->super
->s_first_meta_bg
;
556 old_desc_blocks
= fs
->desc_blocks
+
557 fs
->super
->s_reserved_gdt_blocks
;
558 for (i
= 0; i
< fs
->group_desc_count
; i
++) {
559 ext2fs_reserve_super_and_bgd(fs
, i
, bmap
);
562 * Mark the blocks used for the inode table
564 for (j
= 0, b
= fs
->group_desc
[i
].bg_inode_table
;
565 j
< (unsigned int) fs
->inode_blocks_per_group
;
567 ext2fs_mark_block_bitmap(bmap
, b
);
570 * Mark block used for the block bitmap
572 ext2fs_mark_block_bitmap(bmap
,
573 fs
->group_desc
[i
].bg_block_bitmap
);
576 * Mark block used for the inode bitmap
578 ext2fs_mark_block_bitmap(bmap
,
579 fs
->group_desc
[i
].bg_inode_bitmap
);
585 * This function checks to see if a particular block (either a
586 * superblock or a block group descriptor) overlaps with an inode or
587 * block bitmap block, or with the inode table.
589 static void mark_fs_metablock(ext2_resize_t rfs
,
590 ext2fs_block_bitmap meta_bmap
,
591 int group
, blk_t blk
)
593 ext2_filsys fs
= rfs
->new_fs
;
595 ext2fs_mark_block_bitmap(rfs
->reserve_blocks
, blk
);
596 ext2fs_mark_block_bitmap(fs
->block_map
, blk
);
599 * Check to see if we overlap with the inode or block bitmap,
600 * or the inode tables. If not, and the block is in use, then
601 * mark it as a block to be moved.
603 if (IS_BLOCK_BM(fs
, group
, blk
)) {
604 FS_BLOCK_BM(fs
, group
) = 0;
605 rfs
->needed_blocks
++;
606 } else if (IS_INODE_BM(fs
, group
, blk
)) {
607 FS_INODE_BM(fs
, group
) = 0;
608 rfs
->needed_blocks
++;
609 } else if (IS_INODE_TB(fs
, group
, blk
)) {
610 FS_INODE_TB(fs
, group
) = 0;
611 rfs
->needed_blocks
++;
612 } else if (ext2fs_test_block_bitmap(rfs
->old_fs
->block_map
, blk
) &&
613 !ext2fs_test_block_bitmap(meta_bmap
, blk
)) {
614 ext2fs_mark_block_bitmap(rfs
->move_blocks
, blk
);
615 rfs
->needed_blocks
++;
621 * This routine marks and unmarks reserved blocks in the new block
622 * bitmap. It also determines which blocks need to be moved and
623 * places this information into the move_blocks bitmap.
625 static errcode_t
blocks_to_move(ext2_resize_t rfs
)
628 dgrp_t i
, max_groups
;
629 blk_t blk
, group_blk
;
630 unsigned long old_blocks
, new_blocks
;
631 unsigned int meta_bg
, meta_bg_size
;
633 ext2_filsys fs
, old_fs
;
634 ext2fs_block_bitmap meta_bmap
;
637 old_fs
= rfs
->old_fs
;
638 if (old_fs
->super
->s_blocks_count
> fs
->super
->s_blocks_count
)
641 retval
= ext2fs_allocate_block_bitmap(fs
, _("reserved blocks"),
642 &rfs
->reserve_blocks
);
646 retval
= ext2fs_allocate_block_bitmap(fs
, _("blocks to be moved"),
651 retval
= ext2fs_allocate_block_bitmap(fs
, _("meta-data blocks"),
656 retval
= mark_table_blocks(old_fs
, meta_bmap
);
663 * If we're shrinking the filesystem, we need to move all of
664 * the blocks that don't fit any more
666 for (blk
= fs
->super
->s_blocks_count
;
667 blk
< old_fs
->super
->s_blocks_count
; blk
++) {
668 if (ext2fs_test_block_bitmap(old_fs
->block_map
, blk
) &&
669 !ext2fs_test_block_bitmap(meta_bmap
, blk
)) {
670 ext2fs_mark_block_bitmap(rfs
->move_blocks
, blk
);
671 rfs
->needed_blocks
++;
673 ext2fs_mark_block_bitmap(rfs
->reserve_blocks
, blk
);
676 if (fs
->super
->s_feature_incompat
& EXT2_FEATURE_INCOMPAT_META_BG
) {
677 old_blocks
= old_fs
->super
->s_first_meta_bg
;
678 new_blocks
= fs
->super
->s_first_meta_bg
;
680 old_blocks
= old_fs
->desc_blocks
+ old_fs
->super
->s_reserved_gdt_blocks
;
681 new_blocks
= fs
->desc_blocks
+ fs
->super
->s_reserved_gdt_blocks
;
684 if (old_blocks
== new_blocks
) {
689 max_groups
= fs
->group_desc_count
;
690 if (max_groups
> old_fs
->group_desc_count
)
691 max_groups
= old_fs
->group_desc_count
;
692 group_blk
= old_fs
->super
->s_first_data_block
;
694 * If we're reducing the number of descriptor blocks, this
695 * makes life easy. :-) We just have to mark some extra
698 if (old_blocks
> new_blocks
) {
699 for (i
= 0; i
< max_groups
; i
++) {
700 if (!ext2fs_bg_has_super(fs
, i
)) {
701 group_blk
+= fs
->super
->s_blocks_per_group
;
704 for (blk
= group_blk
+1+new_blocks
;
705 blk
< group_blk
+1+old_blocks
; blk
++) {
706 ext2fs_unmark_block_bitmap(fs
->block_map
,
708 rfs
->needed_blocks
--;
710 group_blk
+= fs
->super
->s_blocks_per_group
;
716 * If we're increasing the number of descriptor blocks, life
717 * gets interesting....
719 meta_bg_size
= EXT2_DESC_PER_BLOCK(fs
->super
);
720 for (i
= 0; i
< max_groups
; i
++) {
721 has_super
= ext2fs_bg_has_super(fs
, i
);
723 mark_fs_metablock(rfs
, meta_bmap
, i
, group_blk
);
725 meta_bg
= i
/ meta_bg_size
;
726 if (!(fs
->super
->s_feature_incompat
&
727 EXT2_FEATURE_INCOMPAT_META_BG
) ||
728 (meta_bg
< fs
->super
->s_first_meta_bg
)) {
730 for (blk
= group_blk
+1;
731 blk
< group_blk
+ 1 + new_blocks
; blk
++)
732 mark_fs_metablock(rfs
, meta_bmap
,
738 if (((i
% meta_bg_size
) == 0) ||
739 ((i
% meta_bg_size
) == 1) ||
740 ((i
% meta_bg_size
) == (meta_bg_size
-1)))
741 mark_fs_metablock(rfs
, meta_bmap
, i
,
742 group_blk
+ has_super
);
745 if (fs
->group_desc
[i
].bg_inode_table
&&
746 fs
->group_desc
[i
].bg_inode_bitmap
&&
747 fs
->group_desc
[i
].bg_block_bitmap
)
751 * Reserve the existing meta blocks that we know
752 * aren't to be moved.
754 if (fs
->group_desc
[i
].bg_block_bitmap
)
755 ext2fs_mark_block_bitmap(rfs
->reserve_blocks
,
756 fs
->group_desc
[i
].bg_block_bitmap
);
757 if (fs
->group_desc
[i
].bg_inode_bitmap
)
758 ext2fs_mark_block_bitmap(rfs
->reserve_blocks
,
759 fs
->group_desc
[i
].bg_inode_bitmap
);
760 if (fs
->group_desc
[i
].bg_inode_table
)
761 for (blk
= fs
->group_desc
[i
].bg_inode_table
, j
=0;
762 j
< fs
->inode_blocks_per_group
; j
++, blk
++)
763 ext2fs_mark_block_bitmap(rfs
->reserve_blocks
,
767 * Allocate the missing data structures
769 retval
= ext2fs_allocate_group_table(fs
, i
,
770 rfs
->reserve_blocks
);
775 * For those structures that have changed, we need to
778 if (FS_BLOCK_BM(old_fs
, i
) !=
779 (blk
= FS_BLOCK_BM(fs
, i
))) {
780 ext2fs_mark_block_bitmap(fs
->block_map
, blk
);
781 if (ext2fs_test_block_bitmap(old_fs
->block_map
, blk
) &&
782 !ext2fs_test_block_bitmap(meta_bmap
, blk
))
783 ext2fs_mark_block_bitmap(rfs
->move_blocks
,
786 if (FS_INODE_BM(old_fs
, i
) !=
787 (blk
= FS_INODE_BM(fs
, i
))) {
788 ext2fs_mark_block_bitmap(fs
->block_map
, blk
);
789 if (ext2fs_test_block_bitmap(old_fs
->block_map
, blk
) &&
790 !ext2fs_test_block_bitmap(meta_bmap
, blk
))
791 ext2fs_mark_block_bitmap(rfs
->move_blocks
,
796 * The inode table, if we need to relocate it, is
797 * handled specially. We have to reserve the blocks
798 * for both the old and the new inode table, since we
799 * can't have the inode table be destroyed during the
800 * block relocation phase.
802 if (FS_INODE_TB(fs
, i
) == FS_INODE_TB(old_fs
, i
))
803 goto next_group
; /* inode table not moved */
805 rfs
->needed_blocks
+= fs
->inode_blocks_per_group
;
808 * Mark the new inode table as in use in the new block
809 * allocation bitmap, and move any blocks that might
812 for (blk
= fs
->group_desc
[i
].bg_inode_table
, j
=0;
813 j
< fs
->inode_blocks_per_group
; j
++, blk
++) {
814 ext2fs_mark_block_bitmap(fs
->block_map
, blk
);
815 if (ext2fs_test_block_bitmap(old_fs
->block_map
, blk
) &&
816 !ext2fs_test_block_bitmap(meta_bmap
, blk
))
817 ext2fs_mark_block_bitmap(rfs
->move_blocks
,
822 * Make sure the old inode table is reserved in the
823 * block reservation bitmap.
825 for (blk
= rfs
->old_fs
->group_desc
[i
].bg_inode_table
, j
=0;
826 j
< fs
->inode_blocks_per_group
; j
++, blk
++)
827 ext2fs_mark_block_bitmap(rfs
->reserve_blocks
, blk
);
830 group_blk
+= rfs
->new_fs
->super
->s_blocks_per_group
;
836 ext2fs_free_block_bitmap(meta_bmap
);
842 * This helper function tries to allocate a new block. We try to
843 * avoid hitting the original group descriptor blocks at least at
844 * first, since we want to make it possible to recover from a badly
845 * aborted resize operation as much as possible.
847 * In the future, I may further modify this routine to balance out
848 * where we get the new blocks across the various block groups.
849 * Ideally we would allocate blocks that corresponded with the block
850 * group of the containing inode, and keep contiguous blocks
851 * together. However, this very difficult to do efficiently, since we
852 * don't have the necessary information up front.
856 #define DESPERATION 2
858 static void init_block_alloc(ext2_resize_t rfs
)
860 rfs
->alloc_state
= AVOID_OLD
;
861 rfs
->new_blk
= rfs
->new_fs
->super
->s_first_data_block
;
863 /* HACK for testing */
864 if (rfs
->new_fs
->super
->s_blocks_count
>
865 rfs
->old_fs
->super
->s_blocks_count
)
866 rfs
->new_blk
= rfs
->old_fs
->super
->s_blocks_count
;
870 static blk_t
get_new_block(ext2_resize_t rfs
)
872 ext2_filsys fs
= rfs
->new_fs
;
875 if (rfs
->new_blk
>= fs
->super
->s_blocks_count
) {
876 if (rfs
->alloc_state
== DESPERATION
)
879 #ifdef RESIZE2FS_DEBUG
880 if (rfs
->flags
& RESIZE_DEBUG_BMOVE
)
881 printf("Going into desperation mode "
882 "for block allocations\n");
884 rfs
->alloc_state
= DESPERATION
;
885 rfs
->new_blk
= fs
->super
->s_first_data_block
;
888 if (ext2fs_test_block_bitmap(fs
->block_map
, rfs
->new_blk
) ||
889 ext2fs_test_block_bitmap(rfs
->reserve_blocks
,
891 ((rfs
->alloc_state
== AVOID_OLD
) &&
892 (rfs
->new_blk
< rfs
->old_fs
->super
->s_blocks_count
) &&
893 ext2fs_test_block_bitmap(rfs
->old_fs
->block_map
,
902 static errcode_t
block_mover(ext2_resize_t rfs
)
904 blk_t blk
, old_blk
, new_blk
;
905 ext2_filsys fs
= rfs
->new_fs
;
906 ext2_filsys old_fs
= rfs
->old_fs
;
910 ext2_badblocks_list badblock_list
= 0;
913 retval
= ext2fs_read_bb_inode(old_fs
, &badblock_list
);
917 new_blk
= fs
->super
->s_first_data_block
;
918 if (!rfs
->itable_buf
) {
919 retval
= ext2fs_get_array(fs
->blocksize
,
920 fs
->inode_blocks_per_group
,
925 retval
= ext2fs_create_extent_table(&rfs
->bmap
, 0);
930 * The first step is to figure out where all of the blocks
934 init_block_alloc(rfs
);
935 for (blk
= old_fs
->super
->s_first_data_block
;
936 blk
< old_fs
->super
->s_blocks_count
; blk
++) {
937 if (!ext2fs_test_block_bitmap(old_fs
->block_map
, blk
))
939 if (!ext2fs_test_block_bitmap(rfs
->move_blocks
, blk
))
941 if (ext2fs_badblocks_list_test(badblock_list
, blk
)) {
942 ext2fs_badblocks_list_del(badblock_list
, blk
);
947 new_blk
= get_new_block(rfs
);
952 ext2fs_mark_block_bitmap(fs
->block_map
, new_blk
);
953 ext2fs_add_extent_entry(rfs
->bmap
, blk
, new_blk
);
959 ext2fs_free_extent_table(rfs
->bmap
);
967 * Step two is to actually move the blocks
969 retval
= ext2fs_iterate_extent(rfs
->bmap
, 0, 0, 0);
970 if (retval
) goto errout
;
973 retval
= (rfs
->progress
)(rfs
, E2_RSZ_BLOCK_RELOC_PASS
,
979 retval
= ext2fs_iterate_extent(rfs
->bmap
, &old_blk
, &new_blk
, &size
);
980 if (retval
) goto errout
;
983 #ifdef RESIZE2FS_DEBUG
984 if (rfs
->flags
& RESIZE_DEBUG_BMOVE
)
985 printf("Moving %d blocks %u->%u\n",
986 size
, old_blk
, new_blk
);
990 if (c
> fs
->inode_blocks_per_group
)
991 c
= fs
->inode_blocks_per_group
;
992 retval
= io_channel_read_blk(fs
->io
, old_blk
, c
,
994 if (retval
) goto errout
;
995 retval
= io_channel_write_blk(fs
->io
, new_blk
, c
,
997 if (retval
) goto errout
;
1002 if (rfs
->progress
) {
1003 io_channel_flush(fs
->io
);
1004 retval
= (rfs
->progress
)(rfs
,
1005 E2_RSZ_BLOCK_RELOC_PASS
,
1011 io_channel_flush(fs
->io
);
1015 if (badblock_list
) {
1016 if (!retval
&& bb_modified
)
1017 retval
= ext2fs_update_bb_inode(old_fs
,
1019 ext2fs_badblocks_list_free(badblock_list
);
1025 /* --------------------------------------------------------------------
1027 * Resize processing, phase 3
1029 * --------------------------------------------------------------------
1033 struct process_block_struct
{
1036 struct ext2_inode
* inode
;
1042 static int process_block(ext2_filsys fs
, blk_t
*block_nr
,
1043 e2_blkcnt_t blockcnt
,
1044 blk_t ref_block
EXT2FS_ATTR((unused
)),
1045 int ref_offset
EXT2FS_ATTR((unused
)), void *priv_data
)
1047 struct process_block_struct
*pb
;
1049 blk_t block
, new_block
;
1052 pb
= (struct process_block_struct
*) priv_data
;
1054 if (pb
->rfs
->bmap
) {
1055 new_block
= ext2fs_extent_translate(pb
->rfs
->bmap
, block
);
1057 *block_nr
= new_block
;
1058 ret
|= BLOCK_CHANGED
;
1060 #ifdef RESIZE2FS_DEBUG
1061 if (pb
->rfs
->flags
& RESIZE_DEBUG_BMOVE
)
1062 printf("ino=%u, blockcnt=%lld, %u->%u\n",
1063 pb
->ino
, blockcnt
, block
, new_block
);
1069 retval
= ext2fs_add_dir_block(fs
->dblist
, pb
->ino
,
1070 block
, (int) blockcnt
);
1082 static errcode_t
progress_callback(ext2_filsys fs
,
1083 ext2_inode_scan scan
EXT2FS_ATTR((unused
)),
1084 dgrp_t group
, void * priv_data
)
1086 ext2_resize_t rfs
= (ext2_resize_t
) priv_data
;
1090 * This check is to protect against old ext2 libraries. It
1091 * shouldn't be needed against new libraries.
1096 if (rfs
->progress
) {
1097 io_channel_flush(fs
->io
);
1098 retval
= (rfs
->progress
)(rfs
, E2_RSZ_INODE_SCAN_PASS
,
1099 group
+1, fs
->group_desc_count
);
1107 static errcode_t
inode_scan_and_fix(ext2_resize_t rfs
)
1109 struct process_block_struct pb
;
1110 ext2_ino_t ino
, new_inode
;
1111 struct ext2_inode inode
;
1112 ext2_inode_scan scan
= NULL
;
1115 char *block_buf
= 0;
1116 ext2_ino_t start_to_move
;
1117 blk_t orig_size
, new_block
;
1119 if ((rfs
->old_fs
->group_desc_count
<=
1120 rfs
->new_fs
->group_desc_count
) &&
1125 * Save the original size of the old filesystem, and
1126 * temporarily set the size to be the new size if the new size
1127 * is larger. We need to do this to avoid catching an error
1128 * by the block iterator routines
1130 orig_size
= rfs
->old_fs
->super
->s_blocks_count
;
1131 if (orig_size
< rfs
->new_fs
->super
->s_blocks_count
)
1132 rfs
->old_fs
->super
->s_blocks_count
=
1133 rfs
->new_fs
->super
->s_blocks_count
;
1135 retval
= ext2fs_open_inode_scan(rfs
->old_fs
, 0, &scan
);
1136 if (retval
) goto errout
;
1138 retval
= ext2fs_init_dblist(rfs
->old_fs
, 0);
1139 if (retval
) goto errout
;
1140 retval
= ext2fs_get_array(rfs
->old_fs
->blocksize
, 3, &block_buf
);
1141 if (retval
) goto errout
;
1143 start_to_move
= (rfs
->new_fs
->group_desc_count
*
1144 rfs
->new_fs
->super
->s_inodes_per_group
);
1146 if (rfs
->progress
) {
1147 retval
= (rfs
->progress
)(rfs
, E2_RSZ_INODE_SCAN_PASS
,
1148 0, rfs
->old_fs
->group_desc_count
);
1152 ext2fs_set_inode_callback(scan
, progress_callback
, (void *) rfs
);
1156 new_inode
= EXT2_FIRST_INODE(rfs
->new_fs
->super
);
1158 * First, copy all of the inodes that need to be moved
1159 * elsewhere in the inode table
1162 retval
= ext2fs_get_next_inode(scan
, &ino
, &inode
);
1163 if (retval
) goto errout
;
1167 if (inode
.i_links_count
== 0 && ino
!= EXT2_RESIZE_INO
)
1168 continue; /* inode not in use */
1170 pb
.is_dir
= LINUX_S_ISDIR(inode
.i_mode
);
1173 if (inode
.i_file_acl
&& rfs
->bmap
) {
1174 new_block
= ext2fs_extent_translate(rfs
->bmap
,
1177 inode
.i_file_acl
= new_block
;
1178 retval
= ext2fs_write_inode(rfs
->old_fs
,
1180 if (retval
) goto errout
;
1184 if (ext2fs_inode_has_valid_blocks(&inode
) &&
1185 (rfs
->bmap
|| pb
.is_dir
)) {
1187 retval
= ext2fs_block_iterate2(rfs
->old_fs
,
1189 process_block
, &pb
);
1198 if (ino
<= start_to_move
)
1199 continue; /* Don't need to move it. */
1205 if (!ext2fs_test_inode_bitmap(rfs
->new_fs
->inode_map
,
1209 if (new_inode
> rfs
->new_fs
->super
->s_inodes_count
) {
1214 ext2fs_mark_inode_bitmap(rfs
->new_fs
->inode_map
, new_inode
);
1216 /* Get the new version of the inode */
1217 retval
= ext2fs_read_inode(rfs
->old_fs
, ino
, &inode
);
1218 if (retval
) goto errout
;
1220 inode
.i_ctime
= time(0);
1221 retval
= ext2fs_write_inode(rfs
->old_fs
, new_inode
, &inode
);
1222 if (retval
) goto errout
;
1224 group
= (new_inode
-1) / EXT2_INODES_PER_GROUP(rfs
->new_fs
->super
);
1225 if (LINUX_S_ISDIR(inode
.i_mode
))
1226 rfs
->new_fs
->group_desc
[group
].bg_used_dirs_count
++;
1228 #ifdef RESIZE2FS_DEBUG
1229 if (rfs
->flags
& RESIZE_DEBUG_INODEMAP
)
1230 printf("Inode moved %u->%u\n", ino
, new_inode
);
1233 retval
= ext2fs_create_extent_table(&rfs
->imap
, 0);
1237 ext2fs_add_extent_entry(rfs
->imap
, ino
, new_inode
);
1239 io_channel_flush(rfs
->old_fs
->io
);
1242 rfs
->old_fs
->super
->s_blocks_count
= orig_size
;
1244 ext2fs_free_extent_table(rfs
->bmap
);
1248 ext2fs_close_inode_scan(scan
);
1250 ext2fs_free_mem(&block_buf
);
1254 /* --------------------------------------------------------------------
1256 * Resize processing, phase 4.
1258 * --------------------------------------------------------------------
1264 unsigned long max_dirs
;
1268 static int check_and_change_inodes(ext2_ino_t dir
,
1269 int entry
EXT2FS_ATTR((unused
)),
1270 struct ext2_dir_entry
*dirent
, int offset
,
1271 int blocksize
EXT2FS_ATTR((unused
)),
1272 char *buf
EXT2FS_ATTR((unused
)),
1275 struct istruct
*is
= (struct istruct
*) priv_data
;
1276 struct ext2_inode inode
;
1277 ext2_ino_t new_inode
;
1280 if (is
->rfs
->progress
&& offset
== 0) {
1281 io_channel_flush(is
->rfs
->old_fs
->io
);
1282 is
->err
= (is
->rfs
->progress
)(is
->rfs
,
1283 E2_RSZ_INODE_REF_UPD_PASS
,
1284 ++is
->num
, is
->max_dirs
);
1286 return DIRENT_ABORT
;
1292 new_inode
= ext2fs_extent_translate(is
->rfs
->imap
, dirent
->inode
);
1296 #ifdef RESIZE2FS_DEBUG
1297 if (is
->rfs
->flags
& RESIZE_DEBUG_INODEMAP
)
1298 printf("Inode translate (dir=%u, name=%.*s, %u->%u)\n",
1299 dir
, dirent
->name_len
&0xFF, dirent
->name
,
1300 dirent
->inode
, new_inode
);
1303 dirent
->inode
= new_inode
;
1305 /* Update the directory mtime and ctime */
1306 retval
= ext2fs_read_inode(is
->rfs
->old_fs
, dir
, &inode
);
1308 inode
.i_mtime
= inode
.i_ctime
= time(0);
1309 is
->err
= ext2fs_write_inode(is
->rfs
->old_fs
, dir
, &inode
);
1311 return DIRENT_ABORT
;
1314 return DIRENT_CHANGED
;
1317 static errcode_t
inode_ref_fix(ext2_resize_t rfs
)
1326 * Now, we iterate over all of the directories to update the
1330 is
.max_dirs
= ext2fs_dblist_count(rfs
->old_fs
->dblist
);
1334 if (rfs
->progress
) {
1335 retval
= (rfs
->progress
)(rfs
, E2_RSZ_INODE_REF_UPD_PASS
,
1341 retval
= ext2fs_dblist_dir_iterate(rfs
->old_fs
->dblist
,
1342 DIRENT_FLAG_INCLUDE_EMPTY
, 0,
1343 check_and_change_inodes
, &is
);
1352 ext2fs_free_extent_table(rfs
->imap
);
1358 /* --------------------------------------------------------------------
1360 * Resize processing, phase 5.
1362 * In this phase we actually move the inode table around, and then
1363 * update the summary statistics. This is scary, since aborting here
1364 * will potentially scramble the filesystem. (We are moving the
1365 * inode tables around in place, and so the potential for lost data,
1366 * or at the very least scrambling the mapping between filenames and
1367 * inode numbers is very high in case of a power failure here.)
1368 * --------------------------------------------------------------------
1373 * A very scary routine --- this one moves the inode table around!!!
1375 * After this you have to use the rfs->new_fs file handle to read and
1378 static errcode_t
move_itables(ext2_resize_t rfs
)
1380 int n
, num
, size
, diff
;
1381 dgrp_t i
, max_groups
;
1382 ext2_filsys fs
= rfs
->new_fs
;
1384 blk_t old_blk
, new_blk
, blk
;
1386 int j
, to_move
, moved
;
1388 max_groups
= fs
->group_desc_count
;
1389 if (max_groups
> rfs
->old_fs
->group_desc_count
)
1390 max_groups
= rfs
->old_fs
->group_desc_count
;
1392 size
= fs
->blocksize
* fs
->inode_blocks_per_group
;
1393 if (!rfs
->itable_buf
) {
1394 retval
= ext2fs_get_mem(size
, &rfs
->itable_buf
);
1400 * Figure out how many inode tables we need to move
1402 to_move
= moved
= 0;
1403 for (i
=0; i
< max_groups
; i
++)
1404 if (rfs
->old_fs
->group_desc
[i
].bg_inode_table
!=
1405 fs
->group_desc
[i
].bg_inode_table
)
1411 if (rfs
->progress
) {
1412 retval
= rfs
->progress(rfs
, E2_RSZ_MOVE_ITABLE_PASS
,
1418 rfs
->old_fs
->flags
|= EXT2_FLAG_MASTER_SB_ONLY
;
1420 for (i
=0; i
< max_groups
; i
++) {
1421 old_blk
= rfs
->old_fs
->group_desc
[i
].bg_inode_table
;
1422 new_blk
= fs
->group_desc
[i
].bg_inode_table
;
1423 diff
= new_blk
- old_blk
;
1425 #ifdef RESIZE2FS_DEBUG
1426 if (rfs
->flags
& RESIZE_DEBUG_ITABLEMOVE
)
1427 printf("Itable move group %d block %u->%u (diff %d)\n",
1428 i
, old_blk
, new_blk
, diff
);
1434 retval
= io_channel_read_blk(fs
->io
, old_blk
,
1435 fs
->inode_blocks_per_group
,
1440 * The end of the inode table segment often contains
1441 * all zeros, and we're often only moving the inode
1442 * table down a block or two. If so, we can optimize
1443 * things by not rewriting blocks that we know to be zero
1446 for (cp
= rfs
->itable_buf
+size
-1, n
=0; n
< size
; n
++, cp
--)
1449 n
= n
>> EXT2_BLOCK_SIZE_BITS(fs
->super
);
1450 #ifdef RESIZE2FS_DEBUG
1451 if (rfs
->flags
& RESIZE_DEBUG_ITABLEMOVE
)
1452 printf("%d blocks of zeros...\n", n
);
1454 num
= fs
->inode_blocks_per_group
;
1458 retval
= io_channel_write_blk(fs
->io
, new_blk
,
1459 num
, rfs
->itable_buf
);
1461 io_channel_write_blk(fs
->io
, old_blk
,
1462 num
, rfs
->itable_buf
);
1466 retval
= io_channel_write_blk(fs
->io
,
1467 old_blk
+ fs
->inode_blocks_per_group
,
1468 diff
, (rfs
->itable_buf
+
1469 (fs
->inode_blocks_per_group
- diff
) *
1475 for (blk
= rfs
->old_fs
->group_desc
[i
].bg_inode_table
, j
=0;
1476 j
< fs
->inode_blocks_per_group
; j
++, blk
++)
1477 ext2fs_unmark_block_bitmap(fs
->block_map
, blk
);
1479 rfs
->old_fs
->group_desc
[i
].bg_inode_table
= new_blk
;
1480 ext2fs_mark_super_dirty(rfs
->old_fs
);
1481 ext2fs_flush(rfs
->old_fs
);
1483 if (rfs
->progress
) {
1484 retval
= rfs
->progress(rfs
, E2_RSZ_MOVE_ITABLE_PASS
,
1490 mark_table_blocks(fs
, fs
->block_map
);
1492 #ifdef RESIZE2FS_DEBUG
1493 if (rfs
->flags
& RESIZE_DEBUG_ITABLEMOVE
)
1494 printf("Inode table move finished.\n");
1503 * Fix the resize inode
1505 static errcode_t
fix_resize_inode(ext2_filsys fs
)
1507 struct ext2_inode inode
;
1511 if (!(fs
->super
->s_feature_compat
&
1512 EXT2_FEATURE_COMPAT_RESIZE_INODE
))
1515 retval
= ext2fs_get_mem(fs
->blocksize
, &block_buf
);
1516 if (retval
) goto errout
;
1518 retval
= ext2fs_read_inode(fs
, EXT2_RESIZE_INO
, &inode
);
1519 if (retval
) goto errout
;
1521 inode
.i_blocks
= fs
->blocksize
/512;
1523 retval
= ext2fs_write_inode(fs
, EXT2_RESIZE_INO
, &inode
);
1524 if (retval
) goto errout
;
1526 if (!inode
.i_block
[EXT2_DIND_BLOCK
]) {
1528 * Avoid zeroing out block #0; that's rude. This
1529 * should never happen anyway since the filesystem
1530 * should be fsck'ed and we assume it is consistent.
1533 _("Should never happen: resize inode corrupt!\n"));
1537 memset(block_buf
, 0, fs
->blocksize
);
1539 retval
= io_channel_write_blk(fs
->io
, inode
.i_block
[EXT2_DIND_BLOCK
],
1541 if (retval
) goto errout
;
1543 retval
= ext2fs_create_resize_inode(fs
);
1549 ext2fs_free_mem(&block_buf
);
1554 * Finally, recalculate the summary information
1556 static errcode_t
ext2fs_calculate_summary_stats(ext2_filsys fs
)
1560 unsigned int group
= 0;
1561 unsigned int count
= 0;
1566 * First calculate the block statistics
1568 for (blk
= fs
->super
->s_first_data_block
;
1569 blk
< fs
->super
->s_blocks_count
; blk
++) {
1570 if (!ext2fs_fast_test_block_bitmap(fs
->block_map
, blk
)) {
1575 if ((count
== fs
->super
->s_blocks_per_group
) ||
1576 (blk
== fs
->super
->s_blocks_count
-1)) {
1577 fs
->group_desc
[group
++].bg_free_blocks_count
=
1583 fs
->super
->s_free_blocks_count
= total_free
;
1586 * Next, calculate the inode statistics
1593 /* Protect loop from wrap-around if s_inodes_count maxed */
1594 for (ino
= 1; ino
<= fs
->super
->s_inodes_count
&& ino
> 0; ino
++) {
1595 if (!ext2fs_fast_test_inode_bitmap(fs
->inode_map
, ino
)) {
1600 if ((count
== fs
->super
->s_inodes_per_group
) ||
1601 (ino
== fs
->super
->s_inodes_count
)) {
1602 fs
->group_desc
[group
++].bg_free_inodes_count
=
1608 fs
->super
->s_free_inodes_count
= total_free
;
1609 ext2fs_mark_super_dirty(fs
);