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