Home | History | Annotate | Download | only in resize
      1 /*
      2  * resize2fs.c --- ext2 main routine
      3  *
      4  * Copyright (C) 1997, 1998 by Theodore Ts'o and
      5  * 	PowerQuest, Inc.
      6  *
      7  * Copyright (C) 1999, 2000 by Theosore Ts'o
      8  *
      9  * %Begin-Header%
     10  * This file may be redistributed under the terms of the GNU Public
     11  * License.
     12  * %End-Header%
     13  */
     14 
     15 /*
     16  * Resizing a filesystem consists of the following phases:
     17  *
     18  *	1.  Adjust superblock and write out new parts of the inode
     19  * 		table
     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
     28  * 			new ones.
     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.
     34  */
     35 
     36 #include "resize2fs.h"
     37 #include <time.h>
     38 
     39 #ifdef __linux__			/* Kludge for debugging */
     40 #define RESIZE2FS_DEBUG
     41 #endif
     42 
     43 static void fix_uninit_block_bitmaps(ext2_filsys fs);
     44 static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_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);
     52 static errcode_t fix_sb_journal_backup(ext2_filsys fs);
     53 static errcode_t mark_table_blocks(ext2_filsys fs,
     54 				   ext2fs_block_bitmap bmap);
     55 
     56 /*
     57  * Some helper CPP macros
     58  */
     59 #define IS_BLOCK_BM(fs, i, blk) ((blk) == ext2fs_block_bitmap_loc((fs),(i)))
     60 #define IS_INODE_BM(fs, i, blk) ((blk) == ext2fs_inode_bitmap_loc((fs),(i)))
     61 
     62 #define IS_INODE_TB(fs, i, blk) (((blk) >= ext2fs_inode_table_loc((fs), (i))) && \
     63 				 ((blk) < (ext2fs_inode_table_loc((fs), (i)) + \
     64 					   (fs)->inode_blocks_per_group)))
     65 
     66 /* Some bigalloc helper macros which are more succint... */
     67 #define B2C(x)	EXT2FS_B2C(fs, (x))
     68 #define C2B(x)	EXT2FS_C2B(fs, (x))
     69 #define EQ_CLSTR(x, y) (B2C(x) == B2C(y))
     70 #define LE_CLSTR(x, y) (B2C(x) <= B2C(y))
     71 #define LT_CLSTR(x, y) (B2C(x) <  B2C(y))
     72 #define GE_CLSTR(x, y) (B2C(x) >= B2C(y))
     73 #define GT_CLSTR(x, y) (B2C(x) >  B2C(y))
     74 
     75 static int lazy_itable_init;
     76 
     77 /*
     78  * This is the top-level routine which does the dirty deed....
     79  */
     80 errcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, int flags,
     81 	    errcode_t (*progress)(ext2_resize_t rfs, int pass,
     82 					  unsigned long cur,
     83 					  unsigned long max_val))
     84 {
     85 	ext2_resize_t	rfs;
     86 	errcode_t	retval;
     87 	struct resource_track	rtrack, overall_track;
     88 
     89 	/*
     90 	 * Create the data structure
     91 	 */
     92 	retval = ext2fs_get_mem(sizeof(struct ext2_resize_struct), &rfs);
     93 	if (retval)
     94 		return retval;
     95 
     96 	memset(rfs, 0, sizeof(struct ext2_resize_struct));
     97 	fs->priv_data = rfs;
     98 	rfs->old_fs = fs;
     99 	rfs->flags = flags;
    100 	rfs->itable_buf	 = 0;
    101 	rfs->progress = progress;
    102 
    103 	init_resource_track(&overall_track, "overall resize2fs", fs->io);
    104 	init_resource_track(&rtrack, "read_bitmaps", fs->io);
    105 	retval = ext2fs_read_bitmaps(fs);
    106 	if (retval)
    107 		goto errout;
    108 	print_resource_track(rfs, &rtrack, fs->io);
    109 
    110 	fs->super->s_state |= EXT2_ERROR_FS;
    111 	ext2fs_mark_super_dirty(fs);
    112 	ext2fs_flush(fs);
    113 
    114 	init_resource_track(&rtrack, "fix_uninit_block_bitmaps 1", fs->io);
    115 	fix_uninit_block_bitmaps(fs);
    116 	print_resource_track(rfs, &rtrack, fs->io);
    117 	retval = ext2fs_dup_handle(fs, &rfs->new_fs);
    118 	if (retval)
    119 		goto errout;
    120 
    121 	init_resource_track(&rtrack, "adjust_superblock", fs->io);
    122 	retval = adjust_superblock(rfs, *new_size);
    123 	if (retval)
    124 		goto errout;
    125 	print_resource_track(rfs, &rtrack, fs->io);
    126 
    127 
    128 	init_resource_track(&rtrack, "fix_uninit_block_bitmaps 2", fs->io);
    129 	fix_uninit_block_bitmaps(rfs->new_fs);
    130 	print_resource_track(rfs, &rtrack, fs->io);
    131 	/* Clear the block bitmap uninit flag for the last block group */
    132 	ext2fs_bg_flags_clear(rfs->new_fs, rfs->new_fs->group_desc_count - 1,
    133 			     EXT2_BG_BLOCK_UNINIT);
    134 
    135 	*new_size = ext2fs_blocks_count(rfs->new_fs->super);
    136 
    137 	init_resource_track(&rtrack, "blocks_to_move", fs->io);
    138 	retval = blocks_to_move(rfs);
    139 	if (retval)
    140 		goto errout;
    141 	print_resource_track(rfs, &rtrack, fs->io);
    142 
    143 #ifdef RESIZE2FS_DEBUG
    144 	if (rfs->flags & RESIZE_DEBUG_BMOVE)
    145 		printf("Number of free blocks: %llu/%llu, Needed: %llu\n",
    146 		       ext2fs_free_blocks_count(rfs->old_fs->super),
    147 		       ext2fs_free_blocks_count(rfs->new_fs->super),
    148 		       rfs->needed_blocks);
    149 #endif
    150 
    151 	init_resource_track(&rtrack, "block_mover", fs->io);
    152 	retval = block_mover(rfs);
    153 	if (retval)
    154 		goto errout;
    155 	print_resource_track(rfs, &rtrack, fs->io);
    156 
    157 	init_resource_track(&rtrack, "inode_scan_and_fix", fs->io);
    158 	retval = inode_scan_and_fix(rfs);
    159 	if (retval)
    160 		goto errout;
    161 	print_resource_track(rfs, &rtrack, fs->io);
    162 
    163 	init_resource_track(&rtrack, "inode_ref_fix", fs->io);
    164 	retval = inode_ref_fix(rfs);
    165 	if (retval)
    166 		goto errout;
    167 	print_resource_track(rfs, &rtrack, fs->io);
    168 
    169 	init_resource_track(&rtrack, "move_itables", fs->io);
    170 	retval = move_itables(rfs);
    171 	if (retval)
    172 		goto errout;
    173 	print_resource_track(rfs, &rtrack, fs->io);
    174 
    175 	init_resource_track(&rtrack, "calculate_summary_stats", fs->io);
    176 	retval = ext2fs_calculate_summary_stats(rfs->new_fs);
    177 	if (retval)
    178 		goto errout;
    179 	print_resource_track(rfs, &rtrack, fs->io);
    180 
    181 	init_resource_track(&rtrack, "fix_resize_inode", fs->io);
    182 	retval = fix_resize_inode(rfs->new_fs);
    183 	if (retval)
    184 		goto errout;
    185 	print_resource_track(rfs, &rtrack, fs->io);
    186 
    187 	init_resource_track(&rtrack, "fix_sb_journal_backup", fs->io);
    188 	retval = fix_sb_journal_backup(rfs->new_fs);
    189 	if (retval)
    190 		goto errout;
    191 	print_resource_track(rfs, &rtrack, fs->io);
    192 
    193 	rfs->new_fs->super->s_state &= ~EXT2_ERROR_FS;
    194 	rfs->new_fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
    195 
    196 	print_resource_track(rfs, &overall_track, fs->io);
    197 	retval = ext2fs_close(rfs->new_fs);
    198 	if (retval)
    199 		goto errout;
    200 
    201 	rfs->flags = flags;
    202 
    203 	ext2fs_free(rfs->old_fs);
    204 	if (rfs->itable_buf)
    205 		ext2fs_free_mem(&rfs->itable_buf);
    206 	if (rfs->reserve_blocks)
    207 		ext2fs_free_block_bitmap(rfs->reserve_blocks);
    208 	if (rfs->move_blocks)
    209 		ext2fs_free_block_bitmap(rfs->move_blocks);
    210 	ext2fs_free_mem(&rfs);
    211 
    212 	return 0;
    213 
    214 errout:
    215 	if (rfs->new_fs)
    216 		ext2fs_free(rfs->new_fs);
    217 	if (rfs->itable_buf)
    218 		ext2fs_free_mem(&rfs->itable_buf);
    219 	ext2fs_free_mem(&rfs);
    220 	return retval;
    221 }
    222 
    223 /*
    224  * Clean up the bitmaps for unitialized bitmaps
    225  */
    226 static void fix_uninit_block_bitmaps(ext2_filsys fs)
    227 {
    228 	blk64_t		blk, lblk;
    229 	dgrp_t		g;
    230 	int		i;
    231 
    232 	if (!(EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
    233 					 EXT4_FEATURE_RO_COMPAT_GDT_CSUM)))
    234 		return;
    235 
    236 	for (g=0; g < fs->group_desc_count; g++) {
    237 		if (!(ext2fs_bg_flags_test(fs, g, EXT2_BG_BLOCK_UNINIT)))
    238 			continue;
    239 
    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,
    243 						  lblk - blk + 1);
    244 
    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;
    252 		     i++, blk++)
    253 			ext2fs_mark_block_bitmap2(fs->block_map, blk);
    254 	}
    255 }
    256 
    257 /* --------------------------------------------------------------------
    258  *
    259  * Resize processing, phase 1.
    260  *
    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  * --------------------------------------------------------------------
    266  */
    267 
    268 /*
    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.
    272  */
    273 static void free_gdp_blocks(ext2_filsys fs,
    274 			    ext2fs_block_bitmap reserve_blocks,
    275 			    ext2_filsys old_fs,
    276 			    dgrp_t group)
    277 {
    278 	blk64_t	blk;
    279 	int	j;
    280 
    281 	blk = ext2fs_block_bitmap_loc(old_fs, group);
    282 	if (blk &&
    283 	    (blk < ext2fs_blocks_count(fs->super))) {
    284 		ext2fs_block_alloc_stats2(fs, blk, -1);
    285 		ext2fs_mark_block_bitmap2(reserve_blocks, blk);
    286 	}
    287 
    288 	blk = ext2fs_inode_bitmap_loc(old_fs, group);
    289 	if (blk &&
    290 	    (blk < ext2fs_blocks_count(fs->super))) {
    291 		ext2fs_block_alloc_stats2(fs, blk, -1);
    292 		ext2fs_mark_block_bitmap2(reserve_blocks, blk);
    293 	}
    294 
    295 	blk = ext2fs_inode_table_loc(old_fs, group);
    296 	if (blk == 0 ||
    297 	    (blk >= ext2fs_blocks_count(fs->super)))
    298 		return;
    299 
    300 	for (j = 0;
    301 	     j < fs->inode_blocks_per_group; j++, blk++) {
    302 		if (blk >= ext2fs_blocks_count(fs->super))
    303 			break;
    304 		ext2fs_block_alloc_stats2(fs, blk, -1);
    305 		ext2fs_mark_block_bitmap2(reserve_blocks, blk);
    306 	}
    307 }
    308 
    309 /*
    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.
    312  */
    313 errcode_t adjust_fs_info(ext2_filsys fs, ext2_filsys old_fs,
    314 			 ext2fs_block_bitmap reserve_blocks, blk64_t new_size)
    315 {
    316 	errcode_t	retval;
    317 	blk64_t		overhead = 0;
    318 	blk64_t		rem;
    319 	blk64_t		blk, group_block;
    320 	blk64_t		real_end;
    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 */
    326 	double		percent;
    327 
    328 	ext2fs_blocks_count_set(fs->super, new_size);
    329 
    330 retry:
    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));
    338 
    339 	/*
    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
    343 	 * table.
    344 	 */
    345 	overhead = (int) (2 + fs->inode_blocks_per_group);
    346 
    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;
    350 
    351 	/*
    352 	 * See if the last group is big enough to support the
    353 	 * necessary data structures.  If not, we need to get rid of
    354 	 * it.
    355 	 */
    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);
    363 		goto retry;
    364 	}
    365 	/*
    366 	 * Adjust the number of inodes
    367 	 */
    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"),
    371 				   new_inodes, ~0U);
    372 		return EXT2_ET_TOO_MANY_INODES;
    373 	}
    374 	fs->super->s_inodes_count = fs->super->s_inodes_per_group *
    375 		fs->group_desc_count;
    376 
    377 	/*
    378 	 * Adjust the number of free blocks
    379 	 */
    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)));
    385 	else
    386 		ext2fs_free_blocks_count_set(fs->super,
    387 			ext2fs_free_blocks_count(fs->super) +
    388 			(ext2fs_blocks_count(fs->super) - blk));
    389 
    390 	/*
    391 	 * Adjust the number of reserved blocks
    392 	 */
    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) /
    397 				   100.0));
    398 
    399 	/*
    400 	 * Adjust the bitmaps for size
    401 	 */
    402 	retval = ext2fs_resize_inode_bitmap2(fs->super->s_inodes_count,
    403 					    fs->super->s_inodes_count,
    404 					    fs->inode_map);
    405 	if (retval) goto errout;
    406 
    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;
    413 
    414 	/*
    415 	 * If we are growing the file system, also grow the size of
    416 	 * the reserve_blocks bitmap
    417 	 */
    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;
    422 	}
    423 
    424 	/*
    425 	 * Reallocate the group descriptors as necessary.
    426 	 */
    427 	if (old_fs->desc_blocks != fs->desc_blocks) {
    428 		retval = ext2fs_resize_mem(old_fs->desc_blocks *
    429 					   fs->blocksize,
    430 					   fs->desc_blocks * fs->blocksize,
    431 					   &fs->group_desc);
    432 		if (retval)
    433 			goto errout;
    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) *
    438 			       fs->blocksize);
    439 	}
    440 
    441 	/*
    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.
    446 	 */
    447 	if ((fs->super->s_feature_compat &
    448 	     EXT2_FEATURE_COMPAT_RESIZE_INODE) &&
    449 	    (old_fs->desc_blocks != fs->desc_blocks)) {
    450 		int new;
    451 
    452 		new = ((int) fs->super->s_reserved_gdt_blocks) +
    453 			(old_fs->desc_blocks - fs->desc_blocks);
    454 		if (new < 0)
    455 			new = 0;
    456 		if (new > (int) fs->blocksize/4)
    457 			new = fs->blocksize/4;
    458 		fs->super->s_reserved_gdt_blocks = new;
    459 	}
    460 
    461 	/*
    462 	 * If we are shrinking the number of block groups, we're done
    463 	 * and can exit now.
    464 	 */
    465 	if (old_fs->group_desc_count > fs->group_desc_count) {
    466 		/*
    467 		 * Check the block groups that we are chopping off
    468 		 * and free any blocks associated with their metadata
    469 		 */
    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);
    473 		retval = 0;
    474 		goto errout;
    475 	}
    476 
    477 	/*
    478 	 * Fix the count of the last (old) block group
    479 	 */
    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;
    483 	if (!old_numblocks)
    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;
    489 		if (!numblocks)
    490 			numblocks = fs->super->s_blocks_per_group;
    491 	} else
    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);
    496 
    497 	/*
    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.)
    501 	 */
    502 	if (old_fs->group_desc_count >= fs->group_desc_count) {
    503 		retval = 0;
    504 		goto errout;
    505 	}
    506 
    507 	/*
    508 	 * Initialize the new block group descriptors
    509 	 */
    510 	group_block = ext2fs_group_first_block2(fs,
    511 						old_fs->group_desc_count);
    512 	csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
    513 					       EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
    514 	if (access("/sys/fs/ext4/features/lazy_itable_init", F_OK) == 0)
    515 		lazy_itable_init = 1;
    516 	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
    517 		old_desc_blocks = fs->super->s_first_meta_bg;
    518 	else
    519 		old_desc_blocks = fs->desc_blocks +
    520 			fs->super->s_reserved_gdt_blocks;
    521 
    522 	/*
    523 	 * If we changed the number of block_group descriptor blocks,
    524 	 * we need to make sure they are all marked as reserved in the
    525 	 * file systems's block allocation map.
    526 	 */
    527 	for (i = 0; i < old_fs->group_desc_count; i++)
    528 		ext2fs_reserve_super_and_bgd(fs, i, fs->block_map);
    529 
    530 	for (i = old_fs->group_desc_count;
    531 	     i < fs->group_desc_count; i++) {
    532 		memset(ext2fs_group_desc(fs, fs->group_desc, i), 0,
    533 		       sizeof(struct ext2_group_desc));
    534 		adjblocks = 0;
    535 
    536 		ext2fs_bg_flags_zap(fs, i);
    537 		if (csum_flag) {
    538 			ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT);
    539 			if (!lazy_itable_init)
    540 				ext2fs_bg_flags_set(fs, i,
    541 						    EXT2_BG_INODE_ZEROED);
    542 			ext2fs_bg_itable_unused_set(fs, i,
    543 					fs->super->s_inodes_per_group);
    544 		}
    545 
    546 		numblocks = ext2fs_group_blocks_count(fs, i);
    547 		if ((i < fs->group_desc_count - 1) && csum_flag)
    548 			ext2fs_bg_flags_set(fs, i, EXT2_BG_BLOCK_UNINIT);
    549 
    550 		has_super = ext2fs_bg_has_super(fs, i);
    551 		if (has_super) {
    552 			ext2fs_block_alloc_stats2(fs, group_block, +1);
    553 			adjblocks++;
    554 		}
    555 		meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super);
    556 		meta_bg = i / meta_bg_size;
    557 		if (!(fs->super->s_feature_incompat &
    558 		      EXT2_FEATURE_INCOMPAT_META_BG) ||
    559 		    (meta_bg < fs->super->s_first_meta_bg)) {
    560 			if (has_super) {
    561 				for (j=0; j < old_desc_blocks; j++)
    562 					ext2fs_block_alloc_stats2(fs,
    563 						 group_block + 1 + j, +1);
    564 				adjblocks += old_desc_blocks;
    565 			}
    566 		} else {
    567 			if (has_super)
    568 				has_super = 1;
    569 			if (((i % meta_bg_size) == 0) ||
    570 			    ((i % meta_bg_size) == 1) ||
    571 			    ((i % meta_bg_size) == (meta_bg_size-1)))
    572 				ext2fs_block_alloc_stats2(fs,
    573 						 group_block + has_super, +1);
    574 		}
    575 
    576 		adjblocks += 2 + fs->inode_blocks_per_group;
    577 
    578 		numblocks -= adjblocks;
    579 		ext2fs_free_blocks_count_set(fs->super,
    580 			     ext2fs_free_blocks_count(fs->super) - adjblocks);
    581 		fs->super->s_free_inodes_count +=
    582 			fs->super->s_inodes_per_group;
    583 		ext2fs_bg_free_blocks_count_set(fs, i, numblocks);
    584 		ext2fs_bg_free_inodes_count_set(fs, i,
    585 						fs->super->s_inodes_per_group);
    586 		ext2fs_bg_used_dirs_count_set(fs, i, 0);
    587 		ext2fs_group_desc_csum_set(fs, i);
    588 
    589 		retval = ext2fs_allocate_group_table(fs, i, 0);
    590 		if (retval) goto errout;
    591 
    592 		group_block += fs->super->s_blocks_per_group;
    593 	}
    594 	retval = 0;
    595 
    596 	/*
    597 	 * Mark all of the metadata blocks as reserved so they won't
    598 	 * get allocated by the call to ext2fs_allocate_group_table()
    599 	 * in blocks_to_move(), where we allocate new blocks to
    600 	 * replace those allocation bitmap and inode table blocks
    601 	 * which have to get relocated to make space for an increased
    602 	 * number of the block group descriptors.
    603 	 */
    604 	if (reserve_blocks)
    605 		mark_table_blocks(fs, reserve_blocks);
    606 
    607 errout:
    608 	return (retval);
    609 }
    610 
    611 /*
    612  * This routine adjusts the superblock and other data structures, both
    613  * in disk as well as in memory...
    614  */
    615 static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size)
    616 {
    617 	ext2_filsys fs;
    618 	int		adj = 0;
    619 	errcode_t	retval;
    620 	blk64_t		group_block;
    621 	unsigned long	i;
    622 	unsigned long	max_group;
    623 
    624 	fs = rfs->new_fs;
    625 	ext2fs_mark_super_dirty(fs);
    626 	ext2fs_mark_bb_dirty(fs);
    627 	ext2fs_mark_ib_dirty(fs);
    628 
    629 	retval = ext2fs_allocate_block_bitmap(fs, _("reserved blocks"),
    630 					      &rfs->reserve_blocks);
    631 	if (retval)
    632 		return retval;
    633 
    634 	retval = adjust_fs_info(fs, rfs->old_fs, rfs->reserve_blocks, new_size);
    635 	if (retval)
    636 		goto errout;
    637 
    638 	/*
    639 	 * Check to make sure there are enough inodes
    640 	 */
    641 	if ((rfs->old_fs->super->s_inodes_count -
    642 	     rfs->old_fs->super->s_free_inodes_count) >
    643 	    rfs->new_fs->super->s_inodes_count) {
    644 		retval = ENOSPC;
    645 		goto errout;
    646 	}
    647 
    648 	/*
    649 	 * If we are shrinking the number block groups, we're done and
    650 	 * can exit now.
    651 	 */
    652 	if (rfs->old_fs->group_desc_count > fs->group_desc_count) {
    653 		retval = 0;
    654 		goto errout;
    655 	}
    656 
    657 	/*
    658 	 * If the number of block groups is staying the same, we're
    659 	 * done and can exit now.  (If the number block groups is
    660 	 * shrinking, we had exited earlier.)
    661 	 */
    662 	if (rfs->old_fs->group_desc_count >= fs->group_desc_count) {
    663 		retval = 0;
    664 		goto errout;
    665 	}
    666 
    667 	/*
    668 	 * If we are using uninit_bg (aka GDT_CSUM) and the kernel
    669 	 * supports lazy inode initialization, we can skip
    670 	 * initializing the inode table.
    671 	 */
    672 	if (lazy_itable_init &&
    673 	    EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
    674 				       EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
    675 		retval = 0;
    676 		goto errout;
    677 	}
    678 
    679 	/*
    680 	 * Initialize the inode table
    681 	 */
    682 	retval = ext2fs_get_array(fs->blocksize, fs->inode_blocks_per_group,
    683 				&rfs->itable_buf);
    684 	if (retval)
    685 		goto errout;
    686 
    687 	memset(rfs->itable_buf, 0, fs->blocksize * fs->inode_blocks_per_group);
    688 	group_block = ext2fs_group_first_block2(fs,
    689 						rfs->old_fs->group_desc_count);
    690 	adj = rfs->old_fs->group_desc_count;
    691 	max_group = fs->group_desc_count - adj;
    692 	if (rfs->progress) {
    693 		retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
    694 				       0, max_group);
    695 		if (retval)
    696 			goto errout;
    697 	}
    698 	for (i = rfs->old_fs->group_desc_count;
    699 	     i < fs->group_desc_count; i++) {
    700 		/*
    701 		 * Write out the new inode table
    702 		 */
    703 		retval = io_channel_write_blk64(fs->io,
    704 						ext2fs_inode_table_loc(fs, i),
    705 						fs->inode_blocks_per_group,
    706 						rfs->itable_buf);
    707 		if (retval) goto errout;
    708 
    709 		io_channel_flush(fs->io);
    710 		if (rfs->progress) {
    711 			retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
    712 					       i - adj + 1, max_group);
    713 			if (retval)
    714 				goto errout;
    715 		}
    716 		group_block += fs->super->s_blocks_per_group;
    717 	}
    718 	io_channel_flush(fs->io);
    719 	retval = 0;
    720 
    721 errout:
    722 	return retval;
    723 }
    724 
    725 /* --------------------------------------------------------------------
    726  *
    727  * Resize processing, phase 2.
    728  *
    729  * In this phase we adjust determine which blocks need to be moved, in
    730  * blocks_to_move().  We then copy the blocks to their ultimate new
    731  * destinations using block_mover().  Since we are copying blocks to
    732  * their new locations, again during this pass we can abort without
    733  * any problems.
    734  * --------------------------------------------------------------------
    735  */
    736 
    737 /*
    738  * This helper function creates a block bitmap with all of the
    739  * filesystem meta-data blocks.
    740  */
    741 static errcode_t mark_table_blocks(ext2_filsys fs,
    742 				   ext2fs_block_bitmap bmap)
    743 {
    744 	dgrp_t			i;
    745 	blk64_t			blk;
    746 
    747 	for (i = 0; i < fs->group_desc_count; i++) {
    748 		ext2fs_reserve_super_and_bgd(fs, i, bmap);
    749 
    750 		/*
    751 		 * Mark the blocks used for the inode table
    752 		 */
    753 		blk = ext2fs_inode_table_loc(fs, i);
    754 		if (blk)
    755 			ext2fs_mark_block_bitmap_range2(bmap, blk,
    756 						fs->inode_blocks_per_group);
    757 
    758 		/*
    759 		 * Mark block used for the block bitmap
    760 		 */
    761 		blk = ext2fs_block_bitmap_loc(fs, i);
    762 		if (blk)
    763 			ext2fs_mark_block_bitmap2(bmap, blk);
    764 
    765 		/*
    766 		 * Mark block used for the inode bitmap
    767 		 */
    768 		blk = ext2fs_inode_bitmap_loc(fs, i);
    769 		if (blk)
    770 			ext2fs_mark_block_bitmap2(bmap, blk);
    771 	}
    772 	return 0;
    773 }
    774 
    775 /*
    776  * This function checks to see if a particular block (either a
    777  * superblock or a block group descriptor) overlaps with an inode or
    778  * block bitmap block, or with the inode table.
    779  */
    780 static void mark_fs_metablock(ext2_resize_t rfs,
    781 			      ext2fs_block_bitmap meta_bmap,
    782 			      int group, blk64_t blk)
    783 {
    784 	ext2_filsys 	fs = rfs->new_fs;
    785 
    786 	ext2fs_mark_block_bitmap2(rfs->reserve_blocks, blk);
    787 	ext2fs_block_alloc_stats2(fs, blk, +1);
    788 
    789 	/*
    790 	 * Check to see if we overlap with the inode or block bitmap,
    791 	 * or the inode tables.  If not, and the block is in use, then
    792 	 * mark it as a block to be moved.
    793 	 */
    794 	if (IS_BLOCK_BM(fs, group, blk)) {
    795 		ext2fs_block_bitmap_loc_set(fs, group, 0);
    796 		rfs->needed_blocks++;
    797 		return;
    798 	}
    799 	if (IS_INODE_BM(fs, group, blk)) {
    800 		ext2fs_inode_bitmap_loc_set(fs, group, 0);
    801 		rfs->needed_blocks++;
    802 		return;
    803 	}
    804 	if (IS_INODE_TB(fs, group, blk)) {
    805 		ext2fs_inode_table_loc_set(fs, group, 0);
    806 		rfs->needed_blocks++;
    807 		return;
    808 	}
    809 	if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) {
    810 		dgrp_t i;
    811 
    812 		for (i=0; i < rfs->old_fs->group_desc_count; i++) {
    813 			if (IS_BLOCK_BM(fs, i, blk)) {
    814 				ext2fs_block_bitmap_loc_set(fs, i, 0);
    815 				rfs->needed_blocks++;
    816 				return;
    817 			}
    818 			if (IS_INODE_BM(fs, i, blk)) {
    819 				ext2fs_inode_bitmap_loc_set(fs, i, 0);
    820 				rfs->needed_blocks++;
    821 				return;
    822 			}
    823 			if (IS_INODE_TB(fs, i, blk)) {
    824 				ext2fs_inode_table_loc_set(fs, i, 0);
    825 				rfs->needed_blocks++;
    826 				return;
    827 			}
    828 		}
    829 	}
    830 	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
    831 				       EXT4_FEATURE_RO_COMPAT_GDT_CSUM) &&
    832 		   (ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT))) {
    833 		/*
    834 		 * If the block bitmap is uninitialized, which means
    835 		 * nothing other than standard metadata in use.
    836 		 */
    837 		return;
    838 	} else if (ext2fs_test_block_bitmap2(rfs->old_fs->block_map, blk) &&
    839 		   !ext2fs_test_block_bitmap2(meta_bmap, blk)) {
    840 		ext2fs_mark_block_bitmap2(rfs->move_blocks, blk);
    841 		rfs->needed_blocks++;
    842 	}
    843 }
    844 
    845 
    846 /*
    847  * This routine marks and unmarks reserved blocks in the new block
    848  * bitmap.  It also determines which blocks need to be moved and
    849  * places this information into the move_blocks bitmap.
    850  */
    851 static errcode_t blocks_to_move(ext2_resize_t rfs)
    852 {
    853 	int		j, has_super;
    854 	dgrp_t		i, max_groups, g;
    855 	blk64_t		blk, group_blk;
    856 	blk64_t		old_blocks, new_blocks;
    857 	blk64_t		new_size;
    858 	unsigned int	meta_bg, meta_bg_size;
    859 	errcode_t	retval;
    860 	ext2_filsys 	fs, old_fs;
    861 	ext2fs_block_bitmap	meta_bmap;
    862 	int		flex_bg;
    863 
    864 	fs = rfs->new_fs;
    865 	old_fs = rfs->old_fs;
    866 	if (ext2fs_blocks_count(old_fs->super) > ext2fs_blocks_count(fs->super))
    867 		fs = rfs->old_fs;
    868 
    869 	retval = ext2fs_allocate_block_bitmap(fs, _("blocks to be moved"),
    870 					      &rfs->move_blocks);
    871 	if (retval)
    872 		return retval;
    873 
    874 	retval = ext2fs_allocate_block_bitmap(fs, _("meta-data blocks"),
    875 					      &meta_bmap);
    876 	if (retval)
    877 		return retval;
    878 
    879 	retval = mark_table_blocks(old_fs, meta_bmap);
    880 	if (retval)
    881 		return retval;
    882 
    883 	fs = rfs->new_fs;
    884 
    885 	/*
    886 	 * If we're shrinking the filesystem, we need to move any
    887 	 * group's metadata blocks (either allocation bitmaps or the
    888 	 * inode table) which are beyond the end of the new
    889 	 * filesystem.
    890 	 */
    891 	new_size = ext2fs_blocks_count(fs->super);
    892 	if (new_size < ext2fs_blocks_count(old_fs->super)) {
    893 		for (g = 0; g < fs->group_desc_count; g++) {
    894 			int realloc = 0;
    895 			/*
    896 			 * ext2fs_allocate_group_table will re-allocate any
    897 			 * metadata blocks whose location is set to zero.
    898 			 */
    899 			if (ext2fs_block_bitmap_loc(fs, g) >= new_size) {
    900 				ext2fs_block_bitmap_loc_set(fs, g, 0);
    901 				realloc = 1;
    902 			}
    903 			if (ext2fs_inode_bitmap_loc(fs, g) >= new_size) {
    904 				ext2fs_inode_bitmap_loc_set(fs, g, 0);
    905 				realloc = 1;
    906 			}
    907 			if ((ext2fs_inode_table_loc(fs, g) +
    908 			     fs->inode_blocks_per_group) > new_size) {
    909 				ext2fs_inode_table_loc_set(fs, g, 0);
    910 				realloc = 1;
    911 			}
    912 
    913 			if (realloc) {
    914 				retval = ext2fs_allocate_group_table(fs, g, 0);
    915 				if (retval)
    916 					return retval;
    917 			}
    918 		}
    919 	}
    920 
    921 	/*
    922 	 * If we're shrinking the filesystem, we need to move all of
    923 	 * the blocks that don't fit any more
    924 	 */
    925 	for (blk = ext2fs_blocks_count(fs->super);
    926 	     blk < ext2fs_blocks_count(old_fs->super); blk++) {
    927 		g = ext2fs_group_of_blk2(fs, blk);
    928 		if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
    929 					       EXT4_FEATURE_RO_COMPAT_GDT_CSUM) &&
    930 		    ext2fs_bg_flags_test(old_fs, g, EXT2_BG_BLOCK_UNINIT)) {
    931 			/*
    932 			 * The block bitmap is uninitialized, so skip
    933 			 * to the next block group.
    934 			 */
    935 			blk = ext2fs_group_first_block2(fs, g+1) - 1;
    936 			continue;
    937 		}
    938 		if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) &&
    939 		    !ext2fs_test_block_bitmap2(meta_bmap, blk)) {
    940 			ext2fs_mark_block_bitmap2(rfs->move_blocks, blk);
    941 			rfs->needed_blocks++;
    942 		}
    943 		ext2fs_mark_block_bitmap2(rfs->reserve_blocks, blk);
    944 	}
    945 
    946 	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) {
    947 		old_blocks = old_fs->super->s_first_meta_bg;
    948 		new_blocks = fs->super->s_first_meta_bg;
    949 	} else {
    950 		old_blocks = old_fs->desc_blocks + old_fs->super->s_reserved_gdt_blocks;
    951 		new_blocks = fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
    952 	}
    953 
    954 	if (old_blocks == new_blocks) {
    955 		retval = 0;
    956 		goto errout;
    957 	}
    958 
    959 	max_groups = fs->group_desc_count;
    960 	if (max_groups > old_fs->group_desc_count)
    961 		max_groups = old_fs->group_desc_count;
    962 	group_blk = old_fs->super->s_first_data_block;
    963 	/*
    964 	 * If we're reducing the number of descriptor blocks, this
    965 	 * makes life easy.  :-)   We just have to mark some extra
    966 	 * blocks as free.
    967 	 */
    968 	if (old_blocks > new_blocks) {
    969 		for (i = 0; i < max_groups; i++) {
    970 			if (!ext2fs_bg_has_super(fs, i)) {
    971 				group_blk += fs->super->s_blocks_per_group;
    972 				continue;
    973 			}
    974 			for (blk = group_blk+1+new_blocks;
    975 			     blk < group_blk+1+old_blocks; blk++) {
    976 				ext2fs_block_alloc_stats2(fs, blk, -1);
    977 				rfs->needed_blocks--;
    978 			}
    979 			group_blk += fs->super->s_blocks_per_group;
    980 		}
    981 		retval = 0;
    982 		goto errout;
    983 	}
    984 	/*
    985 	 * If we're increasing the number of descriptor blocks, life
    986 	 * gets interesting....
    987 	 */
    988 	meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super);
    989 	flex_bg = fs->super->s_feature_incompat &
    990 		EXT4_FEATURE_INCOMPAT_FLEX_BG;
    991 	/* first reserve all of the existing fs meta blocks */
    992 	for (i = 0; i < max_groups; i++) {
    993 		has_super = ext2fs_bg_has_super(fs, i);
    994 		if (has_super)
    995 			mark_fs_metablock(rfs, meta_bmap, i, group_blk);
    996 
    997 		meta_bg = i / meta_bg_size;
    998 		if (!(fs->super->s_feature_incompat &
    999 		      EXT2_FEATURE_INCOMPAT_META_BG) ||
   1000 		    (meta_bg < fs->super->s_first_meta_bg)) {
   1001 			if (has_super) {
   1002 				for (blk = group_blk+1;
   1003 				     blk < group_blk + 1 + new_blocks; blk++)
   1004 					mark_fs_metablock(rfs, meta_bmap,
   1005 							  i, blk);
   1006 			}
   1007 		} else {
   1008 			if (has_super)
   1009 				has_super = 1;
   1010 			if (((i % meta_bg_size) == 0) ||
   1011 			    ((i % meta_bg_size) == 1) ||
   1012 			    ((i % meta_bg_size) == (meta_bg_size-1)))
   1013 				mark_fs_metablock(rfs, meta_bmap, i,
   1014 						  group_blk + has_super);
   1015 		}
   1016 
   1017 		/*
   1018 		 * Reserve the existing meta blocks that we know
   1019 		 * aren't to be moved.
   1020 		 *
   1021 		 * For flex_bg file systems, in order to avoid
   1022 		 * overwriting fs metadata (especially inode table
   1023 		 * blocks) belonging to a different block group when
   1024 		 * we are relocating the inode tables, we need to
   1025 		 * reserve all existing fs metadata blocks.
   1026 		 */
   1027 		if (ext2fs_block_bitmap_loc(fs, i))
   1028 			ext2fs_mark_block_bitmap2(rfs->reserve_blocks,
   1029 				 ext2fs_block_bitmap_loc(fs, i));
   1030 		else if (flex_bg && i < old_fs->group_desc_count)
   1031 			ext2fs_mark_block_bitmap2(rfs->reserve_blocks,
   1032 				 ext2fs_block_bitmap_loc(old_fs, i));
   1033 
   1034 		if (ext2fs_inode_bitmap_loc(fs, i))
   1035 			ext2fs_mark_block_bitmap2(rfs->reserve_blocks,
   1036 				 ext2fs_inode_bitmap_loc(fs, i));
   1037 		else if (flex_bg && i < old_fs->group_desc_count)
   1038 			ext2fs_mark_block_bitmap2(rfs->reserve_blocks,
   1039 				 ext2fs_inode_bitmap_loc(old_fs, i));
   1040 
   1041 		if (ext2fs_inode_table_loc(fs, i))
   1042 			ext2fs_mark_block_bitmap_range2(rfs->reserve_blocks,
   1043 					ext2fs_inode_table_loc(fs, i),
   1044 					fs->inode_blocks_per_group);
   1045 		else if (flex_bg && i < old_fs->group_desc_count)
   1046 			ext2fs_mark_block_bitmap_range2(rfs->reserve_blocks,
   1047 					ext2fs_inode_table_loc(old_fs, i),
   1048 					old_fs->inode_blocks_per_group);
   1049 
   1050 		group_blk += rfs->new_fs->super->s_blocks_per_group;
   1051 	}
   1052 
   1053 	/* Allocate the missing data structures */
   1054 	for (i = 0; i < max_groups; i++) {
   1055 		if (ext2fs_inode_table_loc(fs, i) &&
   1056 		    ext2fs_inode_bitmap_loc(fs, i) &&
   1057 		    ext2fs_block_bitmap_loc(fs, i))
   1058 			continue;
   1059 
   1060 		retval = ext2fs_allocate_group_table(fs, i,
   1061 						     rfs->reserve_blocks);
   1062 		if (retval)
   1063 			goto errout;
   1064 
   1065 		/*
   1066 		 * For those structures that have changed, we need to
   1067 		 * do bookkeepping.
   1068 		 */
   1069 		if (ext2fs_block_bitmap_loc(old_fs, i) !=
   1070 		    (blk = ext2fs_block_bitmap_loc(fs, i))) {
   1071 			ext2fs_block_alloc_stats2(fs, blk, +1);
   1072 			if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) &&
   1073 			    !ext2fs_test_block_bitmap2(meta_bmap, blk))
   1074 				ext2fs_mark_block_bitmap2(rfs->move_blocks,
   1075 							 blk);
   1076 		}
   1077 		if (ext2fs_inode_bitmap_loc(old_fs, i) !=
   1078 		    (blk = ext2fs_inode_bitmap_loc(fs, i))) {
   1079 			ext2fs_block_alloc_stats2(fs, blk, +1);
   1080 			if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) &&
   1081 			    !ext2fs_test_block_bitmap2(meta_bmap, blk))
   1082 				ext2fs_mark_block_bitmap2(rfs->move_blocks,
   1083 							 blk);
   1084 		}
   1085 
   1086 		/*
   1087 		 * The inode table, if we need to relocate it, is
   1088 		 * handled specially.  We have to reserve the blocks
   1089 		 * for both the old and the new inode table, since we
   1090 		 * can't have the inode table be destroyed during the
   1091 		 * block relocation phase.
   1092 		 */
   1093 		if (ext2fs_inode_table_loc(fs, i) == ext2fs_inode_table_loc(old_fs, i))
   1094 			continue;	/* inode table not moved */
   1095 
   1096 		rfs->needed_blocks += fs->inode_blocks_per_group;
   1097 
   1098 		/*
   1099 		 * Mark the new inode table as in use in the new block
   1100 		 * allocation bitmap, and move any blocks that might
   1101 		 * be necessary.
   1102 		 */
   1103 		for (blk = ext2fs_inode_table_loc(fs, i), j=0;
   1104 		     j < fs->inode_blocks_per_group ; j++, blk++) {
   1105 			ext2fs_block_alloc_stats2(fs, blk, +1);
   1106 			if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) &&
   1107 			    !ext2fs_test_block_bitmap2(meta_bmap, blk))
   1108 				ext2fs_mark_block_bitmap2(rfs->move_blocks,
   1109 							 blk);
   1110 		}
   1111 
   1112 		/*
   1113 		 * Make sure the old inode table is reserved in the
   1114 		 * block reservation bitmap.
   1115 		 */
   1116 		for (blk = ext2fs_inode_table_loc(rfs->old_fs, i), j=0;
   1117 		     j < fs->inode_blocks_per_group ; j++, blk++)
   1118 			ext2fs_mark_block_bitmap2(rfs->reserve_blocks, blk);
   1119 	}
   1120 	retval = 0;
   1121 
   1122 errout:
   1123 	if (meta_bmap)
   1124 		ext2fs_free_block_bitmap(meta_bmap);
   1125 
   1126 	return retval;
   1127 }
   1128 
   1129 /*
   1130  * This helper function tries to allocate a new block.  We try to
   1131  * avoid hitting the original group descriptor blocks at least at
   1132  * first, since we want to make it possible to recover from a badly
   1133  * aborted resize operation as much as possible.
   1134  *
   1135  * In the future, I may further modify this routine to balance out
   1136  * where we get the new blocks across the various block groups.
   1137  * Ideally we would allocate blocks that corresponded with the block
   1138  * group of the containing inode, and keep contiguous blocks
   1139  * together.  However, this very difficult to do efficiently, since we
   1140  * don't have the necessary information up front.
   1141  */
   1142 
   1143 #define AVOID_OLD	1
   1144 #define DESPERATION	2
   1145 
   1146 static void init_block_alloc(ext2_resize_t rfs)
   1147 {
   1148 	rfs->alloc_state = AVOID_OLD;
   1149 	rfs->new_blk = rfs->new_fs->super->s_first_data_block;
   1150 #if 0
   1151 	/* HACK for testing */
   1152 	if (ext2fs_blocks_count(rfs->new_fs->super) >
   1153 	    ext2fs_blocks_count(rfs->old_fs->super))
   1154 		rfs->new_blk = ext2fs_blocks_count(rfs->old_fs->super);
   1155 #endif
   1156 }
   1157 
   1158 static blk64_t get_new_block(ext2_resize_t rfs)
   1159 {
   1160 	ext2_filsys	fs = rfs->new_fs;
   1161 
   1162 	while (1) {
   1163 		if (rfs->new_blk >= ext2fs_blocks_count(fs->super)) {
   1164 			if (rfs->alloc_state == DESPERATION)
   1165 				return 0;
   1166 
   1167 #ifdef RESIZE2FS_DEBUG
   1168 			if (rfs->flags & RESIZE_DEBUG_BMOVE)
   1169 				printf("Going into desperation mode "
   1170 				       "for block allocations\n");
   1171 #endif
   1172 			rfs->alloc_state = DESPERATION;
   1173 			rfs->new_blk = fs->super->s_first_data_block;
   1174 			continue;
   1175 		}
   1176 		if (ext2fs_test_block_bitmap2(fs->block_map, rfs->new_blk) ||
   1177 		    ext2fs_test_block_bitmap2(rfs->reserve_blocks,
   1178 					     rfs->new_blk) ||
   1179 		    ((rfs->alloc_state == AVOID_OLD) &&
   1180 		     (rfs->new_blk < ext2fs_blocks_count(rfs->old_fs->super)) &&
   1181 		     ext2fs_test_block_bitmap2(rfs->old_fs->block_map,
   1182 					      rfs->new_blk))) {
   1183 			rfs->new_blk++;
   1184 			continue;
   1185 		}
   1186 		return rfs->new_blk;
   1187 	}
   1188 }
   1189 
   1190 static errcode_t resize2fs_get_alloc_block(ext2_filsys fs, blk64_t goal,
   1191 					   blk64_t *ret)
   1192 {
   1193 	ext2_resize_t rfs = (ext2_resize_t) fs->priv_data;
   1194 	blk64_t blk;
   1195 
   1196 	blk = get_new_block(rfs);
   1197 	if (!blk)
   1198 		return ENOSPC;
   1199 
   1200 #ifdef RESIZE2FS_DEBUG
   1201 	if (rfs->flags & 0xF)
   1202 		printf("get_alloc_block allocating %llu\n", blk);
   1203 #endif
   1204 
   1205 	ext2fs_mark_block_bitmap2(rfs->old_fs->block_map, blk);
   1206 	ext2fs_mark_block_bitmap2(rfs->new_fs->block_map, blk);
   1207 	*ret = (blk64_t) blk;
   1208 	return 0;
   1209 }
   1210 
   1211 static errcode_t block_mover(ext2_resize_t rfs)
   1212 {
   1213 	blk64_t			blk, old_blk, new_blk;
   1214 	ext2_filsys		fs = rfs->new_fs;
   1215 	ext2_filsys		old_fs = rfs->old_fs;
   1216 	errcode_t		retval;
   1217 	__u64			size;
   1218 	int			c;
   1219 	int			to_move, moved;
   1220 	ext2_badblocks_list	badblock_list = 0;
   1221 	int			bb_modified = 0;
   1222 
   1223 	fs->get_alloc_block = resize2fs_get_alloc_block;
   1224 	old_fs->get_alloc_block = resize2fs_get_alloc_block;
   1225 
   1226 	retval = ext2fs_read_bb_inode(old_fs, &badblock_list);
   1227 	if (retval)
   1228 		return retval;
   1229 
   1230 	new_blk = fs->super->s_first_data_block;
   1231 	if (!rfs->itable_buf) {
   1232 		retval = ext2fs_get_array(fs->blocksize,
   1233 					fs->inode_blocks_per_group,
   1234 					&rfs->itable_buf);
   1235 		if (retval)
   1236 			return retval;
   1237 	}
   1238 	retval = ext2fs_create_extent_table(&rfs->bmap, 0);
   1239 	if (retval)
   1240 		return retval;
   1241 
   1242 	/*
   1243 	 * The first step is to figure out where all of the blocks
   1244 	 * will go.
   1245 	 */
   1246 	to_move = moved = 0;
   1247 	init_block_alloc(rfs);
   1248 	for (blk = B2C(old_fs->super->s_first_data_block);
   1249 	     blk < ext2fs_blocks_count(old_fs->super);
   1250 	     blk += EXT2FS_CLUSTER_RATIO(fs)) {
   1251 		if (!ext2fs_test_block_bitmap2(old_fs->block_map, blk))
   1252 			continue;
   1253 		if (!ext2fs_test_block_bitmap2(rfs->move_blocks, blk))
   1254 			continue;
   1255 		if (ext2fs_badblocks_list_test(badblock_list, blk)) {
   1256 			ext2fs_badblocks_list_del(badblock_list, blk);
   1257 			bb_modified++;
   1258 			continue;
   1259 		}
   1260 
   1261 		new_blk = get_new_block(rfs);
   1262 		if (!new_blk) {
   1263 			retval = ENOSPC;
   1264 			goto errout;
   1265 		}
   1266 		ext2fs_block_alloc_stats2(fs, new_blk, +1);
   1267 		ext2fs_add_extent_entry(rfs->bmap, B2C(blk), B2C(new_blk));
   1268 		to_move++;
   1269 	}
   1270 
   1271 	if (to_move == 0) {
   1272 		if (rfs->bmap) {
   1273 			ext2fs_free_extent_table(rfs->bmap);
   1274 			rfs->bmap = 0;
   1275 		}
   1276 		retval = 0;
   1277 		goto errout;
   1278 	}
   1279 
   1280 	/*
   1281 	 * Step two is to actually move the blocks
   1282 	 */
   1283 	retval =  ext2fs_iterate_extent(rfs->bmap, 0, 0, 0);
   1284 	if (retval) goto errout;
   1285 
   1286 	if (rfs->progress) {
   1287 		retval = (rfs->progress)(rfs, E2_RSZ_BLOCK_RELOC_PASS,
   1288 					 0, to_move);
   1289 		if (retval)
   1290 			goto errout;
   1291 	}
   1292 	while (1) {
   1293 		retval = ext2fs_iterate_extent(rfs->bmap, &old_blk, &new_blk, &size);
   1294 		if (retval) goto errout;
   1295 		if (!size)
   1296 			break;
   1297 		old_blk = C2B(old_blk);
   1298 		new_blk = C2B(new_blk);
   1299 		size = C2B(size);
   1300 #ifdef RESIZE2FS_DEBUG
   1301 		if (rfs->flags & RESIZE_DEBUG_BMOVE)
   1302 			printf("Moving %llu blocks %llu->%llu\n",
   1303 			       size, old_blk, new_blk);
   1304 #endif
   1305 		do {
   1306 			c = size;
   1307 			if (c > fs->inode_blocks_per_group)
   1308 				c = fs->inode_blocks_per_group;
   1309 			retval = io_channel_read_blk64(fs->io, old_blk, c,
   1310 						       rfs->itable_buf);
   1311 			if (retval) goto errout;
   1312 			retval = io_channel_write_blk64(fs->io, new_blk, c,
   1313 							rfs->itable_buf);
   1314 			if (retval) goto errout;
   1315 			size -= c;
   1316 			new_blk += c;
   1317 			old_blk += c;
   1318 			moved += c;
   1319 			if (rfs->progress) {
   1320 				io_channel_flush(fs->io);
   1321 				retval = (rfs->progress)(rfs,
   1322 						E2_RSZ_BLOCK_RELOC_PASS,
   1323 						moved, to_move);
   1324 				if (retval)
   1325 					goto errout;
   1326 			}
   1327 		} while (size > 0);
   1328 		io_channel_flush(fs->io);
   1329 	}
   1330 
   1331 errout:
   1332 	if (badblock_list) {
   1333 		if (!retval && bb_modified)
   1334 			retval = ext2fs_update_bb_inode(old_fs,
   1335 							badblock_list);
   1336 		ext2fs_badblocks_list_free(badblock_list);
   1337 	}
   1338 	return retval;
   1339 }
   1340 
   1341 
   1342 /* --------------------------------------------------------------------
   1343  *
   1344  * Resize processing, phase 3
   1345  *
   1346  * --------------------------------------------------------------------
   1347  */
   1348 
   1349 
   1350 /*
   1351  * The extent translation table is stored in clusters so we need to
   1352  * take special care when mapping a source block number to its
   1353  * destination block number.
   1354  */
   1355 static __u64 extent_translate(ext2_filsys fs, ext2_extent extent, __u64 old_loc)
   1356 {
   1357 	__u64 new_block = C2B(ext2fs_extent_translate(extent, B2C(old_loc)));
   1358 
   1359 	if (new_block != 0)
   1360 		new_block += old_loc & (EXT2FS_CLUSTER_RATIO(fs) - 1);
   1361 	return new_block;
   1362 }
   1363 
   1364 struct process_block_struct {
   1365 	ext2_resize_t 		rfs;
   1366 	ext2_ino_t		ino;
   1367 	struct ext2_inode *	inode;
   1368 	errcode_t		error;
   1369 	int			is_dir;
   1370 	int			changed;
   1371 };
   1372 
   1373 static int process_block(ext2_filsys fs, blk64_t	*block_nr,
   1374 			 e2_blkcnt_t blockcnt,
   1375 			 blk64_t ref_block EXT2FS_ATTR((unused)),
   1376 			 int ref_offset EXT2FS_ATTR((unused)), void *priv_data)
   1377 {
   1378 	struct process_block_struct *pb;
   1379 	errcode_t	retval;
   1380 	blk64_t		block, new_block;
   1381 	int		ret = 0;
   1382 
   1383 	pb = (struct process_block_struct *) priv_data;
   1384 	block = *block_nr;
   1385 	if (pb->rfs->bmap) {
   1386 		new_block = extent_translate(fs, pb->rfs->bmap, block);
   1387 		if (new_block) {
   1388 			*block_nr = new_block;
   1389 			ret |= BLOCK_CHANGED;
   1390 			pb->changed = 1;
   1391 #ifdef RESIZE2FS_DEBUG
   1392 			if (pb->rfs->flags & RESIZE_DEBUG_BMOVE)
   1393 				printf("ino=%u, blockcnt=%lld, %llu->%llu\n",
   1394 				       pb->ino, blockcnt, block, new_block);
   1395 #endif
   1396 			block = new_block;
   1397 		}
   1398 	}
   1399 	if (pb->is_dir) {
   1400 		retval = ext2fs_add_dir_block2(fs->dblist, pb->ino,
   1401 					       block, (int) blockcnt);
   1402 		if (retval) {
   1403 			pb->error = retval;
   1404 			ret |= BLOCK_ABORT;
   1405 		}
   1406 	}
   1407 	return ret;
   1408 }
   1409 
   1410 /*
   1411  * Progress callback
   1412  */
   1413 static errcode_t progress_callback(ext2_filsys fs,
   1414 				   ext2_inode_scan scan EXT2FS_ATTR((unused)),
   1415 				   dgrp_t group, void * priv_data)
   1416 {
   1417 	ext2_resize_t rfs = (ext2_resize_t) priv_data;
   1418 	errcode_t		retval;
   1419 
   1420 	/*
   1421 	 * This check is to protect against old ext2 libraries.  It
   1422 	 * shouldn't be needed against new libraries.
   1423 	 */
   1424 	if ((group+1) == 0)
   1425 		return 0;
   1426 
   1427 	if (rfs->progress) {
   1428 		io_channel_flush(fs->io);
   1429 		retval = (rfs->progress)(rfs, E2_RSZ_INODE_SCAN_PASS,
   1430 					 group+1, fs->group_desc_count);
   1431 		if (retval)
   1432 			return retval;
   1433 	}
   1434 
   1435 	return 0;
   1436 }
   1437 
   1438 static errcode_t inode_scan_and_fix(ext2_resize_t rfs)
   1439 {
   1440 	struct process_block_struct	pb;
   1441 	ext2_ino_t		ino, new_inode;
   1442 	struct ext2_inode 	*inode = NULL;
   1443 	ext2_inode_scan 	scan = NULL;
   1444 	errcode_t		retval;
   1445 	char			*block_buf = 0;
   1446 	ext2_ino_t		start_to_move;
   1447 	blk64_t			orig_size;
   1448 	blk64_t			new_block;
   1449 	int			inode_size;
   1450 
   1451 	if ((rfs->old_fs->group_desc_count <=
   1452 	     rfs->new_fs->group_desc_count) &&
   1453 	    !rfs->bmap)
   1454 		return 0;
   1455 
   1456 	/*
   1457 	 * Save the original size of the old filesystem, and
   1458 	 * temporarily set the size to be the new size if the new size
   1459 	 * is larger.  We need to do this to avoid catching an error
   1460 	 * by the block iterator routines
   1461 	 */
   1462 	orig_size = ext2fs_blocks_count(rfs->old_fs->super);
   1463 	if (orig_size < ext2fs_blocks_count(rfs->new_fs->super))
   1464 		ext2fs_blocks_count_set(rfs->old_fs->super,
   1465 				ext2fs_blocks_count(rfs->new_fs->super));
   1466 
   1467 	retval = ext2fs_open_inode_scan(rfs->old_fs, 0, &scan);
   1468 	if (retval) goto errout;
   1469 
   1470 	retval = ext2fs_init_dblist(rfs->old_fs, 0);
   1471 	if (retval) goto errout;
   1472 	retval = ext2fs_get_array(rfs->old_fs->blocksize, 3, &block_buf);
   1473 	if (retval) goto errout;
   1474 
   1475 	start_to_move = (rfs->new_fs->group_desc_count *
   1476 			 rfs->new_fs->super->s_inodes_per_group);
   1477 
   1478 	if (rfs->progress) {
   1479 		retval = (rfs->progress)(rfs, E2_RSZ_INODE_SCAN_PASS,
   1480 					 0, rfs->old_fs->group_desc_count);
   1481 		if (retval)
   1482 			goto errout;
   1483 	}
   1484 	ext2fs_set_inode_callback(scan, progress_callback, (void *) rfs);
   1485 	pb.rfs = rfs;
   1486 	pb.inode = inode;
   1487 	pb.error = 0;
   1488 	new_inode = EXT2_FIRST_INODE(rfs->new_fs->super);
   1489 	inode_size = EXT2_INODE_SIZE(rfs->new_fs->super);
   1490 	inode = malloc(inode_size);
   1491 	if (!inode) {
   1492 		retval = ENOMEM;
   1493 		goto errout;
   1494 	}
   1495 	/*
   1496 	 * First, copy all of the inodes that need to be moved
   1497 	 * elsewhere in the inode table
   1498 	 */
   1499 	while (1) {
   1500 		retval = ext2fs_get_next_inode_full(scan, &ino, inode, inode_size);
   1501 		if (retval) goto errout;
   1502 		if (!ino)
   1503 			break;
   1504 
   1505 		if (inode->i_links_count == 0 && ino != EXT2_RESIZE_INO)
   1506 			continue; /* inode not in use */
   1507 
   1508 		pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
   1509 		pb.changed = 0;
   1510 
   1511 		if (ext2fs_file_acl_block(rfs->old_fs, inode) && rfs->bmap) {
   1512 			new_block = extent_translate(rfs->old_fs, rfs->bmap,
   1513 				ext2fs_file_acl_block(rfs->old_fs, inode));
   1514 			if (new_block) {
   1515 				ext2fs_file_acl_block_set(rfs->old_fs, inode,
   1516 							  new_block);
   1517 				retval = ext2fs_write_inode_full(rfs->old_fs,
   1518 							    ino, inode, inode_size);
   1519 				if (retval) goto errout;
   1520 			}
   1521 		}
   1522 
   1523 		if (ext2fs_inode_has_valid_blocks2(rfs->old_fs, inode) &&
   1524 		    (rfs->bmap || pb.is_dir)) {
   1525 			pb.ino = ino;
   1526 			retval = ext2fs_block_iterate3(rfs->old_fs,
   1527 						       ino, 0, block_buf,
   1528 						       process_block, &pb);
   1529 			if (retval)
   1530 				goto errout;
   1531 			if (pb.error) {
   1532 				retval = pb.error;
   1533 				goto errout;
   1534 			}
   1535 		}
   1536 
   1537 		if (ino <= start_to_move)
   1538 			continue; /* Don't need to move it. */
   1539 
   1540 		/*
   1541 		 * Find a new inode
   1542 		 */
   1543 		retval = ext2fs_new_inode(rfs->new_fs, 0, 0, 0, &new_inode);
   1544 		if (retval)
   1545 			goto errout;
   1546 
   1547 		ext2fs_inode_alloc_stats2(rfs->new_fs, new_inode, +1,
   1548 					  pb.is_dir);
   1549 		if (pb.changed) {
   1550 			/* Get the new version of the inode */
   1551 			retval = ext2fs_read_inode_full(rfs->old_fs, ino,
   1552 						inode, inode_size);
   1553 			if (retval) goto errout;
   1554 		}
   1555 		inode->i_ctime = time(0);
   1556 		retval = ext2fs_write_inode_full(rfs->old_fs, new_inode,
   1557 						inode, inode_size);
   1558 		if (retval) goto errout;
   1559 
   1560 #ifdef RESIZE2FS_DEBUG
   1561 		if (rfs->flags & RESIZE_DEBUG_INODEMAP)
   1562 			printf("Inode moved %u->%u\n", ino, new_inode);
   1563 #endif
   1564 		if (!rfs->imap) {
   1565 			retval = ext2fs_create_extent_table(&rfs->imap, 0);
   1566 			if (retval)
   1567 				goto errout;
   1568 		}
   1569 		ext2fs_add_extent_entry(rfs->imap, ino, new_inode);
   1570 	}
   1571 	io_channel_flush(rfs->old_fs->io);
   1572 
   1573 errout:
   1574 	ext2fs_blocks_count_set(rfs->old_fs->super, orig_size);
   1575 	if (rfs->bmap) {
   1576 		ext2fs_free_extent_table(rfs->bmap);
   1577 		rfs->bmap = 0;
   1578 	}
   1579 	if (scan)
   1580 		ext2fs_close_inode_scan(scan);
   1581 	if (block_buf)
   1582 		ext2fs_free_mem(&block_buf);
   1583 	free(inode);
   1584 	return retval;
   1585 }
   1586 
   1587 /* --------------------------------------------------------------------
   1588  *
   1589  * Resize processing, phase 4.
   1590  *
   1591  * --------------------------------------------------------------------
   1592  */
   1593 
   1594 struct istruct {
   1595 	ext2_resize_t rfs;
   1596 	errcode_t	err;
   1597 	unsigned int	max_dirs;
   1598 	unsigned int	num;
   1599 };
   1600 
   1601 static int check_and_change_inodes(ext2_ino_t dir,
   1602 				   int entry EXT2FS_ATTR((unused)),
   1603 				   struct ext2_dir_entry *dirent, int offset,
   1604 				   int	blocksize EXT2FS_ATTR((unused)),
   1605 				   char *buf EXT2FS_ATTR((unused)),
   1606 				   void *priv_data)
   1607 {
   1608 	struct istruct *is = (struct istruct *) priv_data;
   1609 	struct ext2_inode 	inode;
   1610 	ext2_ino_t		new_inode;
   1611 	errcode_t		retval;
   1612 
   1613 	if (is->rfs->progress && offset == 0) {
   1614 		io_channel_flush(is->rfs->old_fs->io);
   1615 		is->err = (is->rfs->progress)(is->rfs,
   1616 					      E2_RSZ_INODE_REF_UPD_PASS,
   1617 					      ++is->num, is->max_dirs);
   1618 		if (is->err)
   1619 			return DIRENT_ABORT;
   1620 	}
   1621 
   1622 	if (!dirent->inode)
   1623 		return 0;
   1624 
   1625 	new_inode = ext2fs_extent_translate(is->rfs->imap, dirent->inode);
   1626 
   1627 	if (!new_inode)
   1628 		return 0;
   1629 #ifdef RESIZE2FS_DEBUG
   1630 	if (is->rfs->flags & RESIZE_DEBUG_INODEMAP)
   1631 		printf("Inode translate (dir=%u, name=%.*s, %u->%u)\n",
   1632 		       dir, dirent->name_len&0xFF, dirent->name,
   1633 		       dirent->inode, new_inode);
   1634 #endif
   1635 
   1636 	dirent->inode = new_inode;
   1637 
   1638 	/* Update the directory mtime and ctime */
   1639 	retval = ext2fs_read_inode(is->rfs->old_fs, dir, &inode);
   1640 	if (retval == 0) {
   1641 		inode.i_mtime = inode.i_ctime = time(0);
   1642 		is->err = ext2fs_write_inode(is->rfs->old_fs, dir, &inode);
   1643 		if (is->err)
   1644 			return DIRENT_ABORT;
   1645 	}
   1646 
   1647 	return DIRENT_CHANGED;
   1648 }
   1649 
   1650 static errcode_t inode_ref_fix(ext2_resize_t rfs)
   1651 {
   1652 	errcode_t		retval;
   1653 	struct istruct 		is;
   1654 
   1655 	if (!rfs->imap)
   1656 		return 0;
   1657 
   1658 	/*
   1659 	 * Now, we iterate over all of the directories to update the
   1660 	 * inode references
   1661 	 */
   1662 	is.num = 0;
   1663 	is.max_dirs = ext2fs_dblist_count2(rfs->old_fs->dblist);
   1664 	is.rfs = rfs;
   1665 	is.err = 0;
   1666 
   1667 	if (rfs->progress) {
   1668 		retval = (rfs->progress)(rfs, E2_RSZ_INODE_REF_UPD_PASS,
   1669 					 0, is.max_dirs);
   1670 		if (retval)
   1671 			goto errout;
   1672 	}
   1673 
   1674 	retval = ext2fs_dblist_dir_iterate(rfs->old_fs->dblist,
   1675 					   DIRENT_FLAG_INCLUDE_EMPTY, 0,
   1676 					   check_and_change_inodes, &is);
   1677 	if (retval)
   1678 		goto errout;
   1679 	if (is.err) {
   1680 		retval = is.err;
   1681 		goto errout;
   1682 	}
   1683 
   1684 	if (rfs->progress && (is.num < is.max_dirs))
   1685 		(rfs->progress)(rfs, E2_RSZ_INODE_REF_UPD_PASS,
   1686 				is.max_dirs, is.max_dirs);
   1687 
   1688 errout:
   1689 	ext2fs_free_extent_table(rfs->imap);
   1690 	rfs->imap = 0;
   1691 	return retval;
   1692 }
   1693 
   1694 
   1695 /* --------------------------------------------------------------------
   1696  *
   1697  * Resize processing, phase 5.
   1698  *
   1699  * In this phase we actually move the inode table around, and then
   1700  * update the summary statistics.  This is scary, since aborting here
   1701  * will potentially scramble the filesystem.  (We are moving the
   1702  * inode tables around in place, and so the potential for lost data,
   1703  * or at the very least scrambling the mapping between filenames and
   1704  * inode numbers is very high in case of a power failure here.)
   1705  * --------------------------------------------------------------------
   1706  */
   1707 
   1708 
   1709 /*
   1710  * A very scary routine --- this one moves the inode table around!!!
   1711  *
   1712  * After this you have to use the rfs->new_fs file handle to read and
   1713  * write inodes.
   1714  */
   1715 static errcode_t move_itables(ext2_resize_t rfs)
   1716 {
   1717 	int		n, num, size;
   1718 	long long	diff;
   1719 	dgrp_t		i, max_groups;
   1720 	ext2_filsys	fs = rfs->new_fs;
   1721 	char		*cp;
   1722 	blk64_t		old_blk, new_blk, blk;
   1723 	errcode_t	retval;
   1724 	int		j, to_move, moved;
   1725 
   1726 	max_groups = fs->group_desc_count;
   1727 	if (max_groups > rfs->old_fs->group_desc_count)
   1728 		max_groups = rfs->old_fs->group_desc_count;
   1729 
   1730 	size = fs->blocksize * fs->inode_blocks_per_group;
   1731 	if (!rfs->itable_buf) {
   1732 		retval = ext2fs_get_mem(size, &rfs->itable_buf);
   1733 		if (retval)
   1734 			return retval;
   1735 	}
   1736 
   1737 	/*
   1738 	 * Figure out how many inode tables we need to move
   1739 	 */
   1740 	to_move = moved = 0;
   1741 	for (i=0; i < max_groups; i++)
   1742 		if (ext2fs_inode_table_loc(rfs->old_fs, i) !=
   1743 		    ext2fs_inode_table_loc(fs, i))
   1744 			to_move++;
   1745 
   1746 	if (to_move == 0)
   1747 		return 0;
   1748 
   1749 	if (rfs->progress) {
   1750 		retval = rfs->progress(rfs, E2_RSZ_MOVE_ITABLE_PASS,
   1751 				       0, to_move);
   1752 		if (retval)
   1753 			goto errout;
   1754 	}
   1755 
   1756 	rfs->old_fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
   1757 
   1758 	for (i=0; i < max_groups; i++) {
   1759 		old_blk = ext2fs_inode_table_loc(rfs->old_fs, i);
   1760 		new_blk = ext2fs_inode_table_loc(fs, i);
   1761 		diff = new_blk - old_blk;
   1762 
   1763 #ifdef RESIZE2FS_DEBUG
   1764 		if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE)
   1765 			printf("Itable move group %d block %llu->%llu (diff %lld)\n",
   1766 			       i, old_blk, new_blk, diff);
   1767 #endif
   1768 
   1769 		if (!diff)
   1770 			continue;
   1771 
   1772 		retval = io_channel_read_blk64(fs->io, old_blk,
   1773 					       fs->inode_blocks_per_group,
   1774 					       rfs->itable_buf);
   1775 		if (retval)
   1776 			goto errout;
   1777 		/*
   1778 		 * The end of the inode table segment often contains
   1779 		 * all zeros, and we're often only moving the inode
   1780 		 * table down a block or two.  If so, we can optimize
   1781 		 * things by not rewriting blocks that we know to be zero
   1782 		 * already.
   1783 		 */
   1784 		for (cp = rfs->itable_buf+size-1, n=0; n < size; n++, cp--)
   1785 			if (*cp)
   1786 				break;
   1787 		n = n >> EXT2_BLOCK_SIZE_BITS(fs->super);
   1788 #ifdef RESIZE2FS_DEBUG
   1789 		if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE)
   1790 			printf("%d blocks of zeros...\n", n);
   1791 #endif
   1792 		num = fs->inode_blocks_per_group;
   1793 		if (n > diff)
   1794 			num -= n;
   1795 
   1796 		retval = io_channel_write_blk64(fs->io, new_blk,
   1797 						num, rfs->itable_buf);
   1798 		if (retval) {
   1799 			io_channel_write_blk64(fs->io, old_blk,
   1800 					       num, rfs->itable_buf);
   1801 			goto errout;
   1802 		}
   1803 		if (n > diff) {
   1804 			retval = io_channel_write_blk64(fs->io,
   1805 			      old_blk + fs->inode_blocks_per_group,
   1806 			      diff, (rfs->itable_buf +
   1807 				     (fs->inode_blocks_per_group - diff) *
   1808 				     fs->blocksize));
   1809 			if (retval)
   1810 				goto errout;
   1811 		}
   1812 
   1813 		for (blk = ext2fs_inode_table_loc(rfs->old_fs, i), j=0;
   1814 		     j < fs->inode_blocks_per_group ; j++, blk++)
   1815 			ext2fs_block_alloc_stats2(fs, blk, -1);
   1816 
   1817 		ext2fs_inode_table_loc_set(rfs->old_fs, i, new_blk);
   1818 		ext2fs_group_desc_csum_set(rfs->old_fs, i);
   1819 		ext2fs_mark_super_dirty(rfs->old_fs);
   1820 		ext2fs_flush(rfs->old_fs);
   1821 
   1822 		if (rfs->progress) {
   1823 			retval = rfs->progress(rfs, E2_RSZ_MOVE_ITABLE_PASS,
   1824 					       ++moved, to_move);
   1825 			if (retval)
   1826 				goto errout;
   1827 		}
   1828 	}
   1829 	mark_table_blocks(fs, fs->block_map);
   1830 	ext2fs_flush(fs);
   1831 #ifdef RESIZE2FS_DEBUG
   1832 	if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE)
   1833 		printf("Inode table move finished.\n");
   1834 #endif
   1835 	return 0;
   1836 
   1837 errout:
   1838 	return retval;
   1839 }
   1840 
   1841 /*
   1842  * Fix the resize inode
   1843  */
   1844 static errcode_t fix_resize_inode(ext2_filsys fs)
   1845 {
   1846 	struct ext2_inode	inode;
   1847 	errcode_t		retval;
   1848 	char			*block_buf = NULL;
   1849 
   1850 	if (!(fs->super->s_feature_compat &
   1851 	      EXT2_FEATURE_COMPAT_RESIZE_INODE))
   1852 		return 0;
   1853 
   1854 	retval = ext2fs_get_mem(fs->blocksize, &block_buf);
   1855 	if (retval) goto errout;
   1856 
   1857 	retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
   1858 	if (retval) goto errout;
   1859 
   1860 	ext2fs_iblk_set(fs, &inode, 1);
   1861 
   1862 	retval = ext2fs_write_inode(fs, EXT2_RESIZE_INO, &inode);
   1863 	if (retval) goto errout;
   1864 
   1865 	if (!inode.i_block[EXT2_DIND_BLOCK]) {
   1866 		/*
   1867 		 * Avoid zeroing out block #0; that's rude.  This
   1868 		 * should never happen anyway since the filesystem
   1869 		 * should be fsck'ed and we assume it is consistent.
   1870 		 */
   1871 		fprintf(stderr, "%s",
   1872 			_("Should never happen: resize inode corrupt!\n"));
   1873 		exit(1);
   1874 	}
   1875 
   1876 	memset(block_buf, 0, fs->blocksize);
   1877 
   1878 	retval = io_channel_write_blk64(fs->io, inode.i_block[EXT2_DIND_BLOCK],
   1879 					1, block_buf);
   1880 	if (retval) goto errout;
   1881 
   1882 	retval = ext2fs_create_resize_inode(fs);
   1883 	if (retval)
   1884 		goto errout;
   1885 
   1886 errout:
   1887 	if (block_buf)
   1888 		ext2fs_free_mem(&block_buf);
   1889 	return retval;
   1890 }
   1891 
   1892 /*
   1893  * Finally, recalculate the summary information
   1894  */
   1895 static errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs)
   1896 {
   1897 	blk64_t		blk;
   1898 	ext2_ino_t	ino;
   1899 	unsigned int	group = 0;
   1900 	unsigned int	count = 0;
   1901 	blk64_t		total_blocks_free = 0;
   1902 	int		total_inodes_free = 0;
   1903 	int		group_free = 0;
   1904 	int		uninit = 0;
   1905 	blk64_t		super_blk, old_desc_blk, new_desc_blk;
   1906 	int		old_desc_blocks;
   1907 
   1908 	/*
   1909 	 * First calculate the block statistics
   1910 	 */
   1911 	uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT);
   1912 	ext2fs_super_and_bgd_loc2(fs, group, &super_blk, &old_desc_blk,
   1913 				  &new_desc_blk, 0);
   1914 	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
   1915 		old_desc_blocks = fs->super->s_first_meta_bg;
   1916 	else
   1917 		old_desc_blocks = fs->desc_blocks +
   1918 			fs->super->s_reserved_gdt_blocks;
   1919 	for (blk = B2C(fs->super->s_first_data_block);
   1920 	     blk < ext2fs_blocks_count(fs->super);
   1921 	     blk += EXT2FS_CLUSTER_RATIO(fs)) {
   1922 		if ((uninit &&
   1923 		     !(EQ_CLSTR(blk, super_blk) ||
   1924 		       ((old_desc_blk && old_desc_blocks &&
   1925 			 GE_CLSTR(blk, old_desc_blk) &&
   1926 			 LT_CLSTR(blk, old_desc_blk + old_desc_blocks))) ||
   1927 		       ((new_desc_blk && EQ_CLSTR(blk, new_desc_blk))) ||
   1928 		       EQ_CLSTR(blk, ext2fs_block_bitmap_loc(fs, group)) ||
   1929 		       EQ_CLSTR(blk, ext2fs_inode_bitmap_loc(fs, group)) ||
   1930 		       ((GE_CLSTR(blk, ext2fs_inode_table_loc(fs, group)) &&
   1931 			 LT_CLSTR(blk, ext2fs_inode_table_loc(fs, group)
   1932 				  + fs->inode_blocks_per_group))))) ||
   1933 		    (!ext2fs_fast_test_block_bitmap2(fs->block_map, blk))) {
   1934 			group_free++;
   1935 			total_blocks_free++;
   1936 		}
   1937 		count++;
   1938 		if ((count == fs->super->s_clusters_per_group) ||
   1939 		    EQ_CLSTR(blk, ext2fs_blocks_count(fs->super)-1)) {
   1940 			ext2fs_bg_free_blocks_count_set(fs, group, group_free);
   1941 			ext2fs_group_desc_csum_set(fs, group);
   1942 			group++;
   1943 			if (group >= fs->group_desc_count)
   1944 				break;
   1945 			count = 0;
   1946 			group_free = 0;
   1947 			uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT);
   1948 			ext2fs_super_and_bgd_loc2(fs, group, &super_blk,
   1949 						  &old_desc_blk,
   1950 						  &new_desc_blk, 0);
   1951 			if (fs->super->s_feature_incompat &
   1952 			    EXT2_FEATURE_INCOMPAT_META_BG)
   1953 				old_desc_blocks = fs->super->s_first_meta_bg;
   1954 			else
   1955 				old_desc_blocks = fs->desc_blocks +
   1956 					fs->super->s_reserved_gdt_blocks;
   1957 		}
   1958 	}
   1959 	total_blocks_free = C2B(total_blocks_free);
   1960 	ext2fs_free_blocks_count_set(fs->super, total_blocks_free);
   1961 
   1962 	/*
   1963 	 * Next, calculate the inode statistics
   1964 	 */
   1965 	group_free = 0;
   1966 	count = 0;
   1967 	group = 0;
   1968 
   1969 	/* Protect loop from wrap-around if s_inodes_count maxed */
   1970 	uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT);
   1971 	for (ino = 1; ino <= fs->super->s_inodes_count && ino > 0; ino++) {
   1972 		if (uninit ||
   1973 		    !ext2fs_fast_test_inode_bitmap2(fs->inode_map, ino)) {
   1974 			group_free++;
   1975 			total_inodes_free++;
   1976 		}
   1977 		count++;
   1978 		if ((count == fs->super->s_inodes_per_group) ||
   1979 		    (ino == fs->super->s_inodes_count)) {
   1980 			ext2fs_bg_free_inodes_count_set(fs, group, group_free);
   1981 			ext2fs_group_desc_csum_set(fs, group);
   1982 			group++;
   1983 			if (group >= fs->group_desc_count)
   1984 				break;
   1985 			count = 0;
   1986 			group_free = 0;
   1987 			uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT);
   1988 		}
   1989 	}
   1990 	fs->super->s_free_inodes_count = total_inodes_free;
   1991 	ext2fs_mark_super_dirty(fs);
   1992 	return 0;
   1993 }
   1994 
   1995 /*
   1996  *  Journal may have been relocated; update the backup journal blocks
   1997  *  in the superblock.
   1998  */
   1999 static errcode_t fix_sb_journal_backup(ext2_filsys fs)
   2000 {
   2001 	errcode_t	  retval;
   2002 	struct ext2_inode inode;
   2003 
   2004 	if (!(fs->super->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
   2005 		return 0;
   2006 
   2007 	/* External journal? Nothing to do. */
   2008 	if (fs->super->s_journal_dev && !fs->super->s_journal_inum)
   2009 		return 0;
   2010 
   2011 	retval = ext2fs_read_inode(fs, fs->super->s_journal_inum, &inode);
   2012 	if (retval)
   2013 		return retval;
   2014 	memcpy(fs->super->s_jnl_blocks, inode.i_block, EXT2_N_BLOCKS*4);
   2015 	fs->super->s_jnl_blocks[15] = inode.i_size_high;
   2016 	fs->super->s_jnl_blocks[16] = inode.i_size;
   2017 	fs->super->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
   2018 	ext2fs_mark_super_dirty(fs);
   2019 	return 0;
   2020 }
   2021 
   2022 static int calc_group_overhead(ext2_filsys fs, blk64_t grp,
   2023 			       int old_desc_blocks)
   2024 {
   2025 	blk64_t	super_blk, old_desc_blk, new_desc_blk;
   2026 	int overhead;
   2027 
   2028 	/* inode table blocks plus allocation bitmaps */
   2029 	overhead = fs->inode_blocks_per_group + 2;
   2030 
   2031 	ext2fs_super_and_bgd_loc2(fs, grp, &super_blk,
   2032 				  &old_desc_blk, &new_desc_blk, 0);
   2033 	if ((grp == 0) || super_blk)
   2034 		overhead++;
   2035 	if (old_desc_blk)
   2036 		overhead += old_desc_blocks;
   2037 	else if (new_desc_blk)
   2038 		overhead++;
   2039 	return overhead;
   2040 }
   2041 
   2042 
   2043 /*
   2044  * calcluate the minimum number of blocks the given fs can be resized to
   2045  */
   2046 blk64_t calculate_minimum_resize_size(ext2_filsys fs, int flags)
   2047 {
   2048 	ext2_ino_t inode_count;
   2049 	dgrp_t groups;
   2050 	blk64_t blks_needed, data_blocks;
   2051 	blk64_t grp, data_needed, last_start;
   2052 	blk64_t overhead = 0;
   2053 	int old_desc_blocks;
   2054 	int extra_groups = 0;
   2055 	int flexbg_size = 1 << fs->super->s_log_groups_per_flex;
   2056 
   2057 	/*
   2058 	 * first figure out how many group descriptors we need to
   2059 	 * handle the number of inodes we have
   2060 	 */
   2061 	inode_count = fs->super->s_inodes_count -
   2062 		fs->super->s_free_inodes_count;
   2063 	blks_needed = ext2fs_div_ceil(inode_count,
   2064 				      fs->super->s_inodes_per_group) *
   2065 		EXT2_BLOCKS_PER_GROUP(fs->super);
   2066 	groups = ext2fs_div64_ceil(blks_needed,
   2067 				   EXT2_BLOCKS_PER_GROUP(fs->super));
   2068 #ifdef RESIZE2FS_DEBUG
   2069 	if (flags & RESIZE_DEBUG_MIN_CALC)
   2070 		printf("fs has %d inodes, %d groups required.\n",
   2071 		       inode_count, groups);
   2072 #endif
   2073 
   2074 	/*
   2075 	 * number of old-style block group descriptor blocks
   2076 	 */
   2077 	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
   2078 		old_desc_blocks = fs->super->s_first_meta_bg;
   2079 	else
   2080 		old_desc_blocks = fs->desc_blocks +
   2081 			fs->super->s_reserved_gdt_blocks;
   2082 
   2083 	/* calculate how many blocks are needed for data */
   2084 	data_needed = ext2fs_blocks_count(fs->super) -
   2085 		ext2fs_free_blocks_count(fs->super);
   2086 
   2087 	for (grp = 0; grp < fs->group_desc_count; grp++)
   2088 		data_needed -= calc_group_overhead(fs, grp, old_desc_blocks);
   2089 #ifdef RESIZE2FS_DEBUG
   2090 	if (flags & RESIZE_DEBUG_MIN_CALC)
   2091 		printf("fs requires %llu data blocks.\n", data_needed);
   2092 #endif
   2093 
   2094 	/*
   2095 	 * For ext4 we need to allow for up to a flex_bg worth of
   2096 	 * inode tables of slack space so the resize operation can be
   2097 	 * guaranteed to finish.
   2098 	 */
   2099 	if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) {
   2100 		extra_groups = flexbg_size - (groups & (flexbg_size - 1));
   2101 		data_needed += fs->inode_blocks_per_group * extra_groups;
   2102 		extra_groups = groups % flexbg_size;
   2103 	}
   2104 
   2105 	/*
   2106 	 * figure out how many data blocks we have given the number of groups
   2107 	 * we need for our inodes
   2108 	 */
   2109 	data_blocks = groups * EXT2_BLOCKS_PER_GROUP(fs->super);
   2110 	last_start = 0;
   2111 	for (grp = 0; grp < groups; grp++) {
   2112 		overhead = calc_group_overhead(fs, grp, old_desc_blocks);
   2113 
   2114 		/*
   2115 		 * we want to keep track of how much data we can store in
   2116 		 * the groups leading up to the last group so we can determine
   2117 		 * how big the last group needs to be
   2118 		 */
   2119 		if (grp != (groups - 1))
   2120 			last_start += EXT2_BLOCKS_PER_GROUP(fs->super) -
   2121 				overhead;
   2122 
   2123 		data_blocks -= overhead;
   2124 	}
   2125 #ifdef RESIZE2FS_DEBUG
   2126 	if (flags & RESIZE_DEBUG_MIN_CALC)
   2127 		printf("With %d group(s), we have %llu blocks available.\n",
   2128 		       groups, data_blocks);
   2129 #endif
   2130 
   2131 	/*
   2132 	 * if we need more group descriptors in order to accomodate our data
   2133 	 * then we need to add them here
   2134 	 */
   2135 	while (data_needed > data_blocks) {
   2136 		blk64_t remainder = data_needed - data_blocks;
   2137 		dgrp_t extra_grps;
   2138 
   2139 		/* figure out how many more groups we need for the data */
   2140 		extra_grps = ext2fs_div64_ceil(remainder,
   2141 					       EXT2_BLOCKS_PER_GROUP(fs->super));
   2142 
   2143 		data_blocks += extra_grps * EXT2_BLOCKS_PER_GROUP(fs->super);
   2144 
   2145 		/* ok we have to account for the last group */
   2146 		overhead = calc_group_overhead(fs, groups-1, old_desc_blocks);
   2147 		last_start += EXT2_BLOCKS_PER_GROUP(fs->super) - overhead;
   2148 
   2149 		for (grp = groups; grp < groups+extra_grps; grp++) {
   2150 			overhead = calc_group_overhead(fs, grp,
   2151 						       old_desc_blocks);
   2152 
   2153 			/*
   2154 			 * again, we need to see how much data we cram into
   2155 			 * all of the groups leading up to the last group
   2156 			 */
   2157 			if (grp != (groups + extra_grps - 1))
   2158 				last_start += EXT2_BLOCKS_PER_GROUP(fs->super)
   2159 					- overhead;
   2160 
   2161 			data_blocks -= overhead;
   2162 		}
   2163 
   2164 		groups += extra_grps;
   2165 		extra_groups += extra_grps;
   2166 		if (fs->super->s_feature_incompat
   2167 			& EXT4_FEATURE_INCOMPAT_FLEX_BG
   2168 		    && extra_groups > flexbg_size) {
   2169 			/*
   2170 			 * For ext4 we need to allow for up to a flex_bg worth
   2171 			 * of inode tables of slack space so the resize
   2172 			 * operation can be guaranteed to finish.
   2173 			 */
   2174 			extra_groups = flexbg_size -
   2175 						(groups & (flexbg_size - 1));
   2176 			data_needed += (fs->inode_blocks_per_group *
   2177 					extra_groups);
   2178 			extra_groups = groups % flexbg_size;
   2179 		}
   2180 #ifdef RESIZE2FS_DEBUG
   2181 		if (flags & RESIZE_DEBUG_MIN_CALC)
   2182 			printf("Added %d extra group(s), "
   2183 			       "data_needed %llu, data_blocks %llu, "
   2184 			       "last_start %llu\n",
   2185 			       extra_grps, data_needed, data_blocks,
   2186 			       last_start);
   2187 #endif
   2188 	}
   2189 
   2190 	/* now for the fun voodoo */
   2191 	overhead = calc_group_overhead(fs, groups-1, old_desc_blocks);
   2192 #ifdef RESIZE2FS_DEBUG
   2193 	if (flags & RESIZE_DEBUG_MIN_CALC)
   2194 		printf("Last group's overhead is %llu\n", overhead);
   2195 #endif
   2196 
   2197 	/*
   2198 	 * if this is the case then the last group is going to have data in it
   2199 	 * so we need to adjust the size of the last group accordingly
   2200 	 */
   2201 	if (last_start < data_needed) {
   2202 		blk64_t remainder = data_needed - last_start;
   2203 
   2204 #ifdef RESIZE2FS_DEBUG
   2205 		if (flags & RESIZE_DEBUG_MIN_CALC)
   2206 			printf("Need %llu data blocks in last group\n",
   2207 			       remainder);
   2208 #endif
   2209 		/*
   2210 		 * 50 is a magic number that mkfs/resize uses to see if its
   2211 		 * even worth making/resizing the fs.  basically you need to
   2212 		 * have at least 50 blocks in addition to the blocks needed
   2213 		 * for the metadata in the last group
   2214 		 */
   2215 		if (remainder > 50)
   2216 			overhead += remainder;
   2217 		else
   2218 			overhead += 50;
   2219 	} else
   2220 		overhead += 50;
   2221 
   2222 	overhead += fs->super->s_first_data_block;
   2223 #ifdef RESIZE2FS_DEBUG
   2224 	if (flags & RESIZE_DEBUG_MIN_CALC)
   2225 		printf("Final size of last group is %lld\n", overhead);
   2226 #endif
   2227 
   2228 	/*
   2229 	 * since our last group doesn't have to be BLOCKS_PER_GROUP large, we
   2230 	 * only do groups-1, and then add the number of blocks needed to
   2231 	 * handle the group descriptor metadata+data that we need
   2232 	 */
   2233 	blks_needed = (groups-1) * EXT2_BLOCKS_PER_GROUP(fs->super);
   2234 	blks_needed += overhead;
   2235 
   2236 	/*
   2237 	 * Make sure blks_needed covers the end of the inode table in
   2238 	 * the last block group.
   2239 	 */
   2240 	overhead = ext2fs_inode_table_loc(fs, groups-1) +
   2241 		fs->inode_blocks_per_group;
   2242 	if (blks_needed < overhead)
   2243 		blks_needed = overhead;
   2244 
   2245 #ifdef RESIZE2FS_DEBUG
   2246 	if (flags & RESIZE_DEBUG_MIN_CALC)
   2247 		printf("Estimated blocks needed: %llu\n", blks_needed);
   2248 #endif
   2249 
   2250 	/*
   2251 	 * If at this point we've already added up more "needed" than
   2252 	 * the current size, just return current size as minimum.
   2253 	 */
   2254 	if (blks_needed >= ext2fs_blocks_count(fs->super))
   2255 		return ext2fs_blocks_count(fs->super);
   2256 	/*
   2257 	 * We need to reserve a few extra blocks if extents are
   2258 	 * enabled, in case we need to grow the extent tree.  The more
   2259 	 * we shrink the file system, the more space we need.
   2260 	 */
   2261 	if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) {
   2262 		blk64_t safe_margin = (ext2fs_blocks_count(fs->super) -
   2263 				       blks_needed)/500;
   2264 #ifdef RESIZE2FS_DEBUG
   2265 		if (flags & RESIZE_DEBUG_MIN_CALC)
   2266 			printf("Extents safety margin: %llu\n", safe_margin);
   2267 #endif
   2268 		blks_needed += safe_margin;
   2269 	}
   2270 
   2271 	return blks_needed;
   2272 }
   2273