124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o/*
224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * resize2fs.c --- ext2 main routine
324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o *
40cee8a5c423c2a1054c7366e74870592ec8db95eTheodore Ts'o * Copyright (C) 1997, 1998 by Theodore Ts'o and
50cee8a5c423c2a1054c7366e74870592ec8db95eTheodore Ts'o * 	PowerQuest, Inc.
60cee8a5c423c2a1054c7366e74870592ec8db95eTheodore Ts'o *
70cee8a5c423c2a1054c7366e74870592ec8db95eTheodore Ts'o * Copyright (C) 1999, 2000 by Theosore Ts'o
8efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o *
924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * %Begin-Header%
100cee8a5c423c2a1054c7366e74870592ec8db95eTheodore Ts'o * This file may be redistributed under the terms of the GNU Public
110cee8a5c423c2a1054c7366e74870592ec8db95eTheodore Ts'o * License.
1224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * %End-Header%
1324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */
1424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
1505e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o/*
1605e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o * Resizing a filesystem consists of the following phases:
1705e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o *
18a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o *	1.  Adjust superblock and write out new parts of the inode
1905e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o * 		table
20a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 	2.  Determine blocks which need to be relocated, and copy the
21a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 		contents of blocks from their old locations to the new ones.
22a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 	3.  Scan the inode table, doing the following:
23a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 		a.  If blocks have been moved, update the block
24a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 			pointers in the inodes and indirect blocks to
25a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 			point at the new block locations.
26a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 		b.  If parts of the inode table need to be evacuated,
27a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 			copy inodes from their old locations to their
28a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 			new ones.
29a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 		c.  If (b) needs to be done, note which blocks contain
30a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 			directory information, since we will need to
31a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 			update the directory information.
32a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 	4.  Update the directory blocks with the new inode locations.
33a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 	5.  Move the inode tables, if necessary.
3405e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o */
35a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
3624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o#include "resize2fs.h"
37b969b1b8a5c13992cadb026114731958644540d8Matthias Andree#include <time.h>
3824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
39546a1ff18cc912003883ff67ba3e87c69f700fc4Theodore Ts'o#ifdef __linux__			/* Kludge for debugging */
40a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define RESIZE2FS_DEBUG
41a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif
42a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
4386acdebd539864908127561034752082c86105e2Theodore Ts'ostatic void fix_uninit_block_bitmaps(ext2_filsys fs);
44e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size);
45a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t blocks_to_move(ext2_resize_t rfs);
46a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t block_mover(ext2_resize_t rfs);
47a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t inode_scan_and_fix(ext2_resize_t rfs);
48a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t inode_ref_fix(ext2_resize_t rfs);
49a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t move_itables(ext2_resize_t rfs);
509213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'ostatic errcode_t fix_resize_inode(ext2_filsys fs);
51a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs);
528a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeenstatic errcode_t fix_sb_journal_backup(ext2_filsys fs);
53e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic errcode_t mark_table_blocks(ext2_filsys fs,
54e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				   ext2fs_block_bitmap bmap);
55a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
56a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/*
57a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Some helper CPP macros
58a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */
59e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define IS_BLOCK_BM(fs, i, blk) ((blk) == ext2fs_block_bitmap_loc((fs),(i)))
60e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define IS_INODE_BM(fs, i, blk) ((blk) == ext2fs_inode_bitmap_loc((fs),(i)))
61a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
62e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define IS_INODE_TB(fs, i, blk) (((blk) >= ext2fs_inode_table_loc((fs), (i))) && \
63e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				 ((blk) < (ext2fs_inode_table_loc((fs), (i)) + \
6465f0aab98b20b5994a726ab90d355248bcddfffdJP Abgrall					   (fs)->inode_blocks_per_group)))
651773c87c7e9ee5c4b8753919320d6d06910ea25bTheodore Ts'o
66e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* Some bigalloc helper macros which are more succint... */
67e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define B2C(x)	EXT2FS_B2C(fs, (x))
68e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define C2B(x)	EXT2FS_C2B(fs, (x))
69e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define EQ_CLSTR(x, y) (B2C(x) == B2C(y))
70e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define LE_CLSTR(x, y) (B2C(x) <= B2C(y))
71e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define LT_CLSTR(x, y) (B2C(x) <  B2C(y))
72e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define GE_CLSTR(x, y) (B2C(x) >= B2C(y))
73e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define GT_CLSTR(x, y) (B2C(x) >  B2C(y))
74e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
75e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int lazy_itable_init;
762d8c0c8a4fd99d79caa45afba1462dd5ae0f1e45Theodore Ts'o
77a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/*
78a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * This is the top-level routine which does the dirty deed....
79a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */
80e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, int flags,
81e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	    errcode_t (*progress)(ext2_resize_t rfs, int pass,
8286acdebd539864908127561034752082c86105e2Theodore Ts'o					  unsigned long cur,
8386acdebd539864908127561034752082c86105e2Theodore Ts'o					  unsigned long max_val))
84a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{
85a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	ext2_resize_t	rfs;
86a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	errcode_t	retval;
87e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	struct resource_track	rtrack, overall_track;
8896cdb37e27ff101fb23cefe422b4f77fb55209beTheodore Ts'o
89a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	/*
90a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 * Create the data structure
91a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 */
92c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o	retval = ext2fs_get_mem(sizeof(struct ext2_resize_struct), &rfs);
93a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval)
94a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		return retval;
9565f0aab98b20b5994a726ab90d355248bcddfffdJP Abgrall
96e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	memset(rfs, 0, sizeof(struct ext2_resize_struct));
977f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o	fs->priv_data = rfs;
98a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	rfs->old_fs = fs;
99a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	rfs->flags = flags;
100a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	rfs->itable_buf	 = 0;
101a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	rfs->progress = progress;
102e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
103e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	init_resource_track(&overall_track, "overall resize2fs", fs->io);
104e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	init_resource_track(&rtrack, "read_bitmaps", fs->io);
105e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	retval = ext2fs_read_bitmaps(fs);
106e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (retval)
107e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		goto errout;
108e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	print_resource_track(rfs, &rtrack, fs->io);
109e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
110e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	fs->super->s_state |= EXT2_ERROR_FS;
111e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	ext2fs_mark_super_dirty(fs);
112e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	ext2fs_flush(fs);
113e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
114e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	init_resource_track(&rtrack, "fix_uninit_block_bitmaps 1", fs->io);
115e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	fix_uninit_block_bitmaps(fs);
116e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	print_resource_track(rfs, &rtrack, fs->io);
117a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	retval = ext2fs_dup_handle(fs, &rfs->new_fs);
118a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval)
119a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		goto errout;
120a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
121e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	init_resource_track(&rtrack, "adjust_superblock", fs->io);
122116db1b513f6901415d1f5f8c01fc297d7cc64a4Theodore Ts'o	retval = adjust_superblock(rfs, *new_size);
123a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval)
124a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		goto errout;
125e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	print_resource_track(rfs, &rtrack, fs->io);
126e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
1271eb31c4885156b595e6ceb4516cb1e1fb2d251fdTheodore Ts'o
128e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	init_resource_track(&rtrack, "fix_uninit_block_bitmaps 2", fs->io);
12986acdebd539864908127561034752082c86105e2Theodore Ts'o	fix_uninit_block_bitmaps(rfs->new_fs);
130e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	print_resource_track(rfs, &rtrack, fs->io);
13186acdebd539864908127561034752082c86105e2Theodore Ts'o	/* Clear the block bitmap uninit flag for the last block group */
132e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	ext2fs_bg_flags_clear(rfs->new_fs, rfs->new_fs->group_desc_count - 1,
133e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			     EXT2_BG_BLOCK_UNINIT);
13486acdebd539864908127561034752082c86105e2Theodore Ts'o
135e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	*new_size = ext2fs_blocks_count(rfs->new_fs->super);
136116db1b513f6901415d1f5f8c01fc297d7cc64a4Theodore Ts'o
137e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	init_resource_track(&rtrack, "blocks_to_move", fs->io);
138a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	retval = blocks_to_move(rfs);
139a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval)
140a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		goto errout;
141e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	print_resource_track(rfs, &rtrack, fs->io);
142a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
143a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG
144a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (rfs->flags & RESIZE_DEBUG_BMOVE)
145e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		printf("Number of free blocks: %llu/%llu, Needed: %llu\n",
146e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		       ext2fs_free_blocks_count(rfs->old_fs->super),
147e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		       ext2fs_free_blocks_count(rfs->new_fs->super),
148a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		       rfs->needed_blocks);
149a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif
150efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
151e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	init_resource_track(&rtrack, "block_mover", fs->io);
152a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	retval = block_mover(rfs);
153a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval)
154a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		goto errout;
155e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	print_resource_track(rfs, &rtrack, fs->io);
156a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
157e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	init_resource_track(&rtrack, "inode_scan_and_fix", fs->io);
158a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	retval = inode_scan_and_fix(rfs);
159a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval)
160a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		goto errout;
161e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	print_resource_track(rfs, &rtrack, fs->io);
162a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
163e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	init_resource_track(&rtrack, "inode_ref_fix", fs->io);
164a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	retval = inode_ref_fix(rfs);
165a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval)
166a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		goto errout;
167e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	print_resource_track(rfs, &rtrack, fs->io);
168a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
169e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	init_resource_track(&rtrack, "move_itables", fs->io);
170a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	retval = move_itables(rfs);
171a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval)
172a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		goto errout;
173e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	print_resource_track(rfs, &rtrack, fs->io);
174a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
175e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	init_resource_track(&rtrack, "calculate_summary_stats", fs->io);
17664ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o	retval = ext2fs_calculate_summary_stats(rfs->new_fs);
17764ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o	if (retval)
17864ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o		goto errout;
179e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	print_resource_track(rfs, &rtrack, fs->io);
180efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
181e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	init_resource_track(&rtrack, "fix_resize_inode", fs->io);
1829213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	retval = fix_resize_inode(rfs->new_fs);
1839213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	if (retval)
1849213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		goto errout;
185e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	print_resource_track(rfs, &rtrack, fs->io);
1869213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
187e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	init_resource_track(&rtrack, "fix_sb_journal_backup", fs->io);
1888a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen	retval = fix_sb_journal_backup(rfs->new_fs);
1898a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen	if (retval)
1908a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen		goto errout;
191e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	print_resource_track(rfs, &rtrack, fs->io);
1928a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen
19396cdb37e27ff101fb23cefe422b4f77fb55209beTheodore Ts'o	rfs->new_fs->super->s_state &= ~EXT2_ERROR_FS;
194efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	rfs->new_fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
195e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
196e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	print_resource_track(rfs, &overall_track, fs->io);
197a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	retval = ext2fs_close(rfs->new_fs);
198a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval)
199a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		goto errout;
200a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
201a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	rfs->flags = flags;
202efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
203a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	ext2fs_free(rfs->old_fs);
204a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (rfs->itable_buf)
205c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o		ext2fs_free_mem(&rfs->itable_buf);
206e2ca097fc641e9be2bbafc3db7fd96e4ac87387aTheodore Ts'o	if (rfs->reserve_blocks)
207e2ca097fc641e9be2bbafc3db7fd96e4ac87387aTheodore Ts'o		ext2fs_free_block_bitmap(rfs->reserve_blocks);
208e2ca097fc641e9be2bbafc3db7fd96e4ac87387aTheodore Ts'o	if (rfs->move_blocks)
209e2ca097fc641e9be2bbafc3db7fd96e4ac87387aTheodore Ts'o		ext2fs_free_block_bitmap(rfs->move_blocks);
210c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o	ext2fs_free_mem(&rfs);
211efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
212a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	return 0;
213a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
214a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'oerrout:
215a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (rfs->new_fs)
216a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		ext2fs_free(rfs->new_fs);
217a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (rfs->itable_buf)
218c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o		ext2fs_free_mem(&rfs->itable_buf);
219c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o	ext2fs_free_mem(&rfs);
220a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	return retval;
221a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o}
222a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
22386acdebd539864908127561034752082c86105e2Theodore Ts'o/*
22486acdebd539864908127561034752082c86105e2Theodore Ts'o * Clean up the bitmaps for unitialized bitmaps
22586acdebd539864908127561034752082c86105e2Theodore Ts'o */
22686acdebd539864908127561034752082c86105e2Theodore Ts'ostatic void fix_uninit_block_bitmaps(ext2_filsys fs)
22786acdebd539864908127561034752082c86105e2Theodore Ts'o{
228e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t		blk, lblk;
22986acdebd539864908127561034752082c86105e2Theodore Ts'o	dgrp_t		g;
230e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	int		i;
23186acdebd539864908127561034752082c86105e2Theodore Ts'o
23286acdebd539864908127561034752082c86105e2Theodore Ts'o	if (!(EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
23386acdebd539864908127561034752082c86105e2Theodore Ts'o					 EXT4_FEATURE_RO_COMPAT_GDT_CSUM)))
23486acdebd539864908127561034752082c86105e2Theodore Ts'o		return;
23586acdebd539864908127561034752082c86105e2Theodore Ts'o
23686acdebd539864908127561034752082c86105e2Theodore Ts'o	for (g=0; g < fs->group_desc_count; g++) {
237e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (!(ext2fs_bg_flags_test(fs, g, EXT2_BG_BLOCK_UNINIT)))
23886acdebd539864908127561034752082c86105e2Theodore Ts'o			continue;
23986acdebd539864908127561034752082c86105e2Theodore Ts'o
240e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		blk = ext2fs_group_first_block2(fs, g);
241e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		lblk = ext2fs_group_last_block2(fs, g);
242e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_unmark_block_bitmap_range2(fs->block_map, blk,
243e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall						  lblk - blk + 1);
244e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
245e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_reserve_super_and_bgd(fs, g, fs->block_map);
246e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_mark_block_bitmap2(fs->block_map,
247e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					  ext2fs_block_bitmap_loc(fs, g));
248e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_mark_block_bitmap2(fs->block_map,
249e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					  ext2fs_inode_bitmap_loc(fs, g));
250e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		for (i = 0, blk = ext2fs_inode_table_loc(fs, g);
251e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		     i < (unsigned int) fs->inode_blocks_per_group;
252e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		     i++, blk++)
253e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_mark_block_bitmap2(fs->block_map, blk);
25486acdebd539864908127561034752082c86105e2Theodore Ts'o	}
25586acdebd539864908127561034752082c86105e2Theodore Ts'o}
25686acdebd539864908127561034752082c86105e2Theodore Ts'o
257a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* --------------------------------------------------------------------
258a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o *
259a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Resize processing, phase 1.
260a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o *
261a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * In this phase we adjust the in-memory superblock information, and
262a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * initialize any new parts of the inode table.  The new parts of the
263a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * inode table are created in virgin disk space, so we can abort here
264a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * without any side effects.
265a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * --------------------------------------------------------------------
266a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */
267a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
26824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o/*
2699227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o * If the group descriptor's bitmap and inode table blocks are valid,
270c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o * release them in the new filesystem data structure, and mark them as
271c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o * reserved so the old inode table blocks don't get overwritten.
2729227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o */
273c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'ostatic void free_gdp_blocks(ext2_filsys fs,
274c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o			    ext2fs_block_bitmap reserve_blocks,
275e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			    ext2_filsys old_fs,
276e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			    dgrp_t group)
2779227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o{
278e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t	blk;
2799227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o	int	j;
2809227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o
281e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk = ext2fs_block_bitmap_loc(old_fs, group);
282e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (blk &&
283e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	    (blk < ext2fs_blocks_count(fs->super))) {
284e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_block_alloc_stats2(fs, blk, -1);
285e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_mark_block_bitmap2(reserve_blocks, blk);
286c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o	}
2879227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o
288e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk = ext2fs_inode_bitmap_loc(old_fs, group);
289e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (blk &&
290e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	    (blk < ext2fs_blocks_count(fs->super))) {
291e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_block_alloc_stats2(fs, blk, -1);
292e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_mark_block_bitmap2(reserve_blocks, blk);
293c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o	}
2949227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o
295e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk = ext2fs_inode_table_loc(old_fs, group);
296e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (blk == 0 ||
297e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	    (blk >= ext2fs_blocks_count(fs->super)))
2989227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o		return;
2999227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o
300e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	for (j = 0;
3019227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o	     j < fs->inode_blocks_per_group; j++, blk++) {
302e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (blk >= ext2fs_blocks_count(fs->super))
3039227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o			break;
304e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_block_alloc_stats2(fs, blk, -1);
305e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_mark_block_bitmap2(reserve_blocks, blk);
3069227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o	}
3079227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o}
3089227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o
3099227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o/*
310bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o * This routine is shared by the online and offline resize routines.
311bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o * All of the information which is adjusted in memory is done here.
31224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */
313c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'oerrcode_t adjust_fs_info(ext2_filsys fs, ext2_filsys old_fs,
314e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			 ext2fs_block_bitmap reserve_blocks, blk64_t new_size)
31524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o{
31624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	errcode_t	retval;
317e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t		overhead = 0;
318e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t		rem;
319e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t		blk, group_block;
320e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t		real_end;
321e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t		old_numblocks, numblocks, adjblocks;
322e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	unsigned long	i, j, old_desc_blocks;
323544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	unsigned int	meta_bg, meta_bg_size;
32474128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o	int		has_super, csum_flag;
325de8f3a76218255e443ba57dec5d74850180fa75dAndreas Dilger	unsigned long long new_inodes;	/* u64 to check for overflow */
3269ff8ece57d46a9419fc60057547810824881bb45Theodore Ts'o	double		percent;
327bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o
328e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	ext2fs_blocks_count_set(fs->super, new_size);
32924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
33024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'oretry:
331e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	fs->group_desc_count = ext2fs_div64_ceil(ext2fs_blocks_count(fs->super) -
33269022e029f3273b3b860bf701219cd3fe615f76bTheodore Ts'o				       fs->super->s_first_data_block,
33369022e029f3273b3b860bf701219cd3fe615f76bTheodore Ts'o				       EXT2_BLOCKS_PER_GROUP(fs->super));
33424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	if (fs->group_desc_count == 0)
33524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o		return EXT2_ET_TOOSMALL;
336efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count,
33769022e029f3273b3b860bf701219cd3fe615f76bTheodore Ts'o					  EXT2_DESC_PER_BLOCK(fs->super));
33824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
33924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	/*
34024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * Overhead is the number of bookkeeping blocks per group.  It
34124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * includes the superblock backup, the group descriptor
34224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * backups, the inode bitmap, the block bitmap, and the inode
34324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * table.
34424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 */
3459213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	overhead = (int) (2 + fs->inode_blocks_per_group);
3469213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
3479213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	if (ext2fs_bg_has_super(fs, fs->group_desc_count - 1))
348efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		overhead += 1 + fs->desc_blocks +
3499213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o			fs->super->s_reserved_gdt_blocks;
3509213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
35124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	/*
35224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * See if the last group is big enough to support the
35324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * necessary data structures.  If not, we need to get rid of
35424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * it.
35524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 */
356e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	rem = (ext2fs_blocks_count(fs->super) - fs->super->s_first_data_block) %
35724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o		fs->super->s_blocks_per_group;
35824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	if ((fs->group_desc_count == 1) && rem && (rem < overhead))
35924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o		return EXT2_ET_TOOSMALL;
360e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if ((fs->group_desc_count > 1) && rem && (rem < overhead+50)) {
361e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_blocks_count_set(fs->super,
362e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					ext2fs_blocks_count(fs->super) - rem);
36324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o		goto retry;
36424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	}
36524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	/*
36624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * Adjust the number of inodes
36724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 */
368de8f3a76218255e443ba57dec5d74850180fa75dAndreas Dilger	new_inodes =(unsigned long long) fs->super->s_inodes_per_group * fs->group_desc_count;
369f335864338a6fbce8134a445ffdd0cdeb3f3f1bcEric Sandeen	if (new_inodes > ~0U) {
370f335864338a6fbce8134a445ffdd0cdeb3f3f1bcEric Sandeen		fprintf(stderr, _("inodes (%llu) must be less than %u"),
371f335864338a6fbce8134a445ffdd0cdeb3f3f1bcEric Sandeen				   new_inodes, ~0U);
372f335864338a6fbce8134a445ffdd0cdeb3f3f1bcEric Sandeen		return EXT2_ET_TOO_MANY_INODES;
373f335864338a6fbce8134a445ffdd0cdeb3f3f1bcEric Sandeen	}
37424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	fs->super->s_inodes_count = fs->super->s_inodes_per_group *
37524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o		fs->group_desc_count;
37624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
37724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	/*
37824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * Adjust the number of free blocks
37924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 */
380e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk = ext2fs_blocks_count(old_fs->super);
381e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (blk > ext2fs_blocks_count(fs->super))
382e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_free_blocks_count_set(fs->super,
383e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_free_blocks_count(fs->super) -
384e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			(blk - ext2fs_blocks_count(fs->super)));
38524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	else
386e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_free_blocks_count_set(fs->super,
387e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_free_blocks_count(fs->super) +
388e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			(ext2fs_blocks_count(fs->super) - blk));
38924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
39024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	/*
391c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	 * Adjust the number of reserved blocks
392c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	 */
393e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	percent = (ext2fs_r_blocks_count(old_fs->super) * 100.0) /
394e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_blocks_count(old_fs->super);
395e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	ext2fs_r_blocks_count_set(fs->super,
396e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				  (percent * ext2fs_blocks_count(fs->super) /
397e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				   100.0));
398c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o
399c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	/*
40024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * Adjust the bitmaps for size
40124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 */
402e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	retval = ext2fs_resize_inode_bitmap2(fs->super->s_inodes_count,
40324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o					    fs->super->s_inodes_count,
40424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o					    fs->inode_map);
405c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	if (retval) goto errout;
406efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
407e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	real_end = (((blk64_t) EXT2_BLOCKS_PER_GROUP(fs->super) *
408e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		     fs->group_desc_count)) - 1 +
409e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		fs->super->s_first_data_block;
410e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	retval = ext2fs_resize_block_bitmap2(new_size - 1,
411e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					     real_end, fs->block_map);
41265f0aab98b20b5994a726ab90d355248bcddfffdJP Abgrall	if (retval) goto errout;
413f026f1a37061a021f7188c9e45d0fbff1bde9e60Theodore Ts'o
414f026f1a37061a021f7188c9e45d0fbff1bde9e60Theodore Ts'o	/*
415e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 * If we are growing the file system, also grow the size of
416e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 * the reserve_blocks bitmap
417e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 */
418e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (reserve_blocks && new_size > ext2fs_blocks_count(old_fs->super)) {
419e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		retval = ext2fs_resize_block_bitmap2(new_size - 1,
420e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall						     real_end, reserve_blocks);
421e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (retval) goto errout;
422e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	}
423e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
424e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	/*
42524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * Reallocate the group descriptors as necessary.
42624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 */
427bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	if (old_fs->desc_blocks != fs->desc_blocks) {
428bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		retval = ext2fs_resize_mem(old_fs->desc_blocks *
42976f875daa1c9c2cdc72f0c6f0f7be4bbc7f0fc07Theodore Ts'o					   fs->blocksize,
43076f875daa1c9c2cdc72f0c6f0f7be4bbc7f0fc07Theodore Ts'o					   fs->desc_blocks * fs->blocksize,
431c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o					   &fs->group_desc);
432ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o		if (retval)
433a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			goto errout;
434efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		if (fs->desc_blocks > old_fs->desc_blocks)
435efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			memset((char *) fs->group_desc +
436bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o			       (old_fs->desc_blocks * fs->blocksize), 0,
437bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o			       (fs->desc_blocks - old_fs->desc_blocks) *
4382787276ec59e1d52087d307bc30446d088ec65bcTheodore Ts'o			       fs->blocksize);
43924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	}
4401e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o
4411e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	/*
4429213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	 * If the resize_inode feature is set, and we are changing the
4439213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	 * number of descriptor blocks, then adjust
4449213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	 * s_reserved_gdt_blocks if possible to avoid needing to move
4459213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	 * the inode table either now or in the future.
4469213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	 */
447efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	if ((fs->super->s_feature_compat &
4489213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	     EXT2_FEATURE_COMPAT_RESIZE_INODE) &&
449bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	    (old_fs->desc_blocks != fs->desc_blocks)) {
4509213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		int new;
4519213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
452efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		new = ((int) fs->super->s_reserved_gdt_blocks) +
453bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o			(old_fs->desc_blocks - fs->desc_blocks);
4549213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		if (new < 0)
4559213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o			new = 0;
456de8f3a76218255e443ba57dec5d74850180fa75dAndreas Dilger		if (new > (int) fs->blocksize/4)
4579213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o			new = fs->blocksize/4;
4589213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		fs->super->s_reserved_gdt_blocks = new;
4599213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	}
4609213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
4619213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	/*
462c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o	 * If we are shrinking the number of block groups, we're done
463c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o	 * and can exit now.
4641e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	 */
465bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	if (old_fs->group_desc_count > fs->group_desc_count) {
4669227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o		/*
4679227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o		 * Check the block groups that we are chopping off
4689227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o		 * and free any blocks associated with their metadata
4699227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o		 */
4709227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o		for (i = fs->group_desc_count;
471e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		     i < old_fs->group_desc_count; i++)
472e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			free_gdp_blocks(fs, reserve_blocks, old_fs, i);
473c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		retval = 0;
474c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		goto errout;
475c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	}
476bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o
477a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	/*
478a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 * Fix the count of the last (old) block group
479a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 */
480e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	old_numblocks = (ext2fs_blocks_count(old_fs->super) -
481bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o			 old_fs->super->s_first_data_block) %
482bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o				 old_fs->super->s_blocks_per_group;
4831e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	if (!old_numblocks)
484bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		old_numblocks = old_fs->super->s_blocks_per_group;
485bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	if (old_fs->group_desc_count == fs->group_desc_count) {
486e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		numblocks = (ext2fs_blocks_count(fs->super) -
487bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o			     fs->super->s_first_data_block) %
488bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o			fs->super->s_blocks_per_group;
4891e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		if (!numblocks)
490bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o			numblocks = fs->super->s_blocks_per_group;
4911e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	} else
492bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		numblocks = fs->super->s_blocks_per_group;
493bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	i = old_fs->group_desc_count - 1;
494e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	ext2fs_bg_free_blocks_count_set(fs, i, ext2fs_bg_free_blocks_count(fs, i) + (numblocks - old_numblocks));
495236efede1922fa173b3c2f20d9e0886856664ab4Jose R. Santos	ext2fs_group_desc_csum_set(fs, i);
496236efede1922fa173b3c2f20d9e0886856664ab4Jose R. Santos
4971e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	/*
498a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 * If the number of block groups is staying the same, we're
499a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 * done and can exit now.  (If the number block groups is
500a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 * shrinking, we had exited earlier.)
5011e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	 */
502bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	if (old_fs->group_desc_count >= fs->group_desc_count) {
503c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		retval = 0;
504c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		goto errout;
505c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	}
506bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o
507a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	/*
508a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 * Initialize the new block group descriptors
509a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 */
510e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	group_block = ext2fs_group_first_block2(fs,
511e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall						old_fs->group_desc_count);
51274128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o	csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
51374128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o					       EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
514e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (access("/sys/fs/ext4/features/lazy_itable_init", F_OK) == 0)
515e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		lazy_itable_init = 1;
51676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
51776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		old_desc_blocks = fs->super->s_first_meta_bg;
51876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	else
519efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		old_desc_blocks = fs->desc_blocks +
5209213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o			fs->super->s_reserved_gdt_blocks;
521e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
522e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	/*
523e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 * If we changed the number of block_group descriptor blocks,
524e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 * we need to make sure they are all marked as reserved in the
525e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 * file systems's block allocation map.
526e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 */
527e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	for (i = 0; i < old_fs->group_desc_count; i++)
528e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_reserve_super_and_bgd(fs, i, fs->block_map);
529e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
530bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	for (i = old_fs->group_desc_count;
5311e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	     i < fs->group_desc_count; i++) {
532e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		memset(ext2fs_group_desc(fs, fs->group_desc, i), 0,
5331e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		       sizeof(struct ext2_group_desc));
5341e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		adjblocks = 0;
5351e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o
536e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_bg_flags_zap(fs, i);
537e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (csum_flag) {
538e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT);
539e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			if (!lazy_itable_init)
540e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				ext2fs_bg_flags_set(fs, i,
541e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall						    EXT2_BG_INODE_ZEROED);
542e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_bg_itable_unused_set(fs, i,
543e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					fs->super->s_inodes_per_group);
5442d8c0c8a4fd99d79caa45afba1462dd5ae0f1e45Theodore Ts'o		}
54598f4547198b369bef7e41eb7ce4a16855726c393Eric Sandeen
546e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		numblocks = ext2fs_group_blocks_count(fs, i);
547e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if ((i < fs->group_desc_count - 1) && csum_flag)
548e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_bg_flags_set(fs, i, EXT2_BG_BLOCK_UNINIT);
549e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
55076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		has_super = ext2fs_bg_has_super(fs, i);
55176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		if (has_super) {
552e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_block_alloc_stats2(fs, group_block, +1);
55376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o			adjblocks++;
55476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		}
555f2de1d38d0819b17895977fabc52d81d0ea6ec00Valerie Clement		meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super);
55676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		meta_bg = i / meta_bg_size;
55776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		if (!(fs->super->s_feature_incompat &
55876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		      EXT2_FEATURE_INCOMPAT_META_BG) ||
55976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		    (meta_bg < fs->super->s_first_meta_bg)) {
56076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o			if (has_super) {
56176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o				for (j=0; j < old_desc_blocks; j++)
562e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					ext2fs_block_alloc_stats2(fs,
56374128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o						 group_block + 1 + j, +1);
56476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o				adjblocks += old_desc_blocks;
56576dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o			}
56676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		} else {
56776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o			if (has_super)
56876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o				has_super = 1;
56976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o			if (((i % meta_bg_size) == 0) ||
57076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o			    ((i % meta_bg_size) == 1) ||
57176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o			    ((i % meta_bg_size) == (meta_bg_size-1)))
572e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				ext2fs_block_alloc_stats2(fs,
57374128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o						 group_block + has_super, +1);
57424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o		}
575efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
5761e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		adjblocks += 2 + fs->inode_blocks_per_group;
577efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
5781e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		numblocks -= adjblocks;
579e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_free_blocks_count_set(fs->super,
580e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			     ext2fs_free_blocks_count(fs->super) - adjblocks);
5811e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		fs->super->s_free_inodes_count +=
5821e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o			fs->super->s_inodes_per_group;
583e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_bg_free_blocks_count_set(fs, i, numblocks);
584e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_bg_free_inodes_count_set(fs, i,
585e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall						fs->super->s_inodes_per_group);
586e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_bg_used_dirs_count_set(fs, i, 0);
587236efede1922fa173b3c2f20d9e0886856664ab4Jose R. Santos		ext2fs_group_desc_csum_set(fs, i);
58824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
5891e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		retval = ext2fs_allocate_group_table(fs, i, 0);
590c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		if (retval) goto errout;
59124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
592bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		group_block += fs->super->s_blocks_per_group;
593bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	}
594bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	retval = 0;
595bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o
596e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	/*
597e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 * Mark all of the metadata blocks as reserved so they won't
598e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 * get allocated by the call to ext2fs_allocate_group_table()
599e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 * in blocks_to_move(), where we allocate new blocks to
600e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 * replace those allocation bitmap and inode table blocks
601e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 * which have to get relocated to make space for an increased
602e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 * number of the block group descriptors.
603e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 */
604e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (reserve_blocks)
605e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		mark_table_blocks(fs, reserve_blocks);
606e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
607bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'oerrout:
608bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	return (retval);
609bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o}
610bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o
611bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o/*
612bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o * This routine adjusts the superblock and other data structures, both
613bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o * in disk as well as in memory...
614bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o */
615e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size)
616bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o{
617bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	ext2_filsys fs;
618bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	int		adj = 0;
619bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	errcode_t	retval;
620e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t		group_block;
621bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	unsigned long	i;
622bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	unsigned long	max_group;
623efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
624bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	fs = rfs->new_fs;
625bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	ext2fs_mark_super_dirty(fs);
626bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	ext2fs_mark_bb_dirty(fs);
627bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	ext2fs_mark_ib_dirty(fs);
628bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o
629c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o	retval = ext2fs_allocate_block_bitmap(fs, _("reserved blocks"),
630c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o					      &rfs->reserve_blocks);
631c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o	if (retval)
632c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o		return retval;
633c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o
634c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o	retval = adjust_fs_info(fs, rfs->old_fs, rfs->reserve_blocks, new_size);
635bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	if (retval)
636bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		goto errout;
637bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o
638bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	/*
639bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	 * Check to make sure there are enough inodes
640bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	 */
641bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	if ((rfs->old_fs->super->s_inodes_count -
642bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	     rfs->old_fs->super->s_free_inodes_count) >
643bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	    rfs->new_fs->super->s_inodes_count) {
644bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		retval = ENOSPC;
645bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		goto errout;
646bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	}
647bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o
648bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	/*
649bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	 * If we are shrinking the number block groups, we're done and
650bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	 * can exit now.
651bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	 */
652bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	if (rfs->old_fs->group_desc_count > fs->group_desc_count) {
653bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		retval = 0;
654bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		goto errout;
655bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	}
656bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o
657bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	/*
658bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	 * If the number of block groups is staying the same, we're
659bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	 * done and can exit now.  (If the number block groups is
660bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	 * shrinking, we had exited earlier.)
661bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	 */
662bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	if (rfs->old_fs->group_desc_count >= fs->group_desc_count) {
663bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		retval = 0;
664bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		goto errout;
665bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	}
666bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o
667bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	/*
668e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 * If we are using uninit_bg (aka GDT_CSUM) and the kernel
669e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 * supports lazy inode initialization, we can skip
670e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 * initializing the inode table.
671e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 */
672e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (lazy_itable_init &&
673e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	    EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
674e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				       EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
675e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		retval = 0;
676e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		goto errout;
677e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	}
678e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
679e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	/*
680e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 * Initialize the inode table
681bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	 */
682e5aace908e9d1161a594944d9360f9f0cdd18099Theodore Ts'o	retval = ext2fs_get_array(fs->blocksize, fs->inode_blocks_per_group,
683bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o				&rfs->itable_buf);
684bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	if (retval)
685bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		goto errout;
686bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o
687bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	memset(rfs->itable_buf, 0, fs->blocksize * fs->inode_blocks_per_group);
688e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	group_block = ext2fs_group_first_block2(fs,
689e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall						rfs->old_fs->group_desc_count);
690bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	adj = rfs->old_fs->group_desc_count;
691bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	max_group = fs->group_desc_count - adj;
692bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	if (rfs->progress) {
693bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
694bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o				       0, max_group);
695bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		if (retval)
696bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o			goto errout;
697bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	}
698bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	for (i = rfs->old_fs->group_desc_count;
699bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	     i < fs->group_desc_count; i++) {
70005e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o		/*
70105e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o		 * Write out the new inode table
70205e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o		 */
703e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		retval = io_channel_write_blk64(fs->io,
704e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall						ext2fs_inode_table_loc(fs, i),
705e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall						fs->inode_blocks_per_group,
706e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall						rfs->itable_buf);
707c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		if (retval) goto errout;
708c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o
709a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		io_channel_flush(fs->io);
7103b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		if (rfs->progress) {
7113b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o			retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
7123b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o					       i - adj + 1, max_group);
7133b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o			if (retval)
7143b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o				goto errout;
7153b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		}
7161e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		group_block += fs->super->s_blocks_per_group;
71724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	}
718c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	io_channel_flush(fs->io);
719c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	retval = 0;
720c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o
721c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'oerrout:
722c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	return retval;
723c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o}
724c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o
725a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* --------------------------------------------------------------------
726a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o *
727a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Resize processing, phase 2.
728a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o *
729a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * In this phase we adjust determine which blocks need to be moved, in
730a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * blocks_to_move().  We then copy the blocks to their ultimate new
731a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * destinations using block_mover().  Since we are copying blocks to
732a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * their new locations, again during this pass we can abort without
733a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * any problems.
734a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * --------------------------------------------------------------------
735a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */
736a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
737c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o/*
738c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * This helper function creates a block bitmap with all of the
739c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * filesystem meta-data blocks.
740c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o */
741c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'ostatic errcode_t mark_table_blocks(ext2_filsys fs,
74264ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o				   ext2fs_block_bitmap bmap)
743c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o{
744544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	dgrp_t			i;
745e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t			blk;
746c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o
747c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	for (i = 0; i < fs->group_desc_count; i++) {
74864ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o		ext2fs_reserve_super_and_bgd(fs, i, bmap);
749efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
750c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		/*
751c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		 * Mark the blocks used for the inode table
752c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		 */
753e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		blk = ext2fs_inode_table_loc(fs, i);
754e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (blk)
755e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_mark_block_bitmap_range2(bmap, blk,
756e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall						fs->inode_blocks_per_group);
757efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
758c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		/*
759efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		 * Mark block used for the block bitmap
760c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		 */
761e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		blk = ext2fs_block_bitmap_loc(fs, i);
762e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (blk)
763e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_mark_block_bitmap2(bmap, blk);
76464ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o
765c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		/*
766efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		 * Mark block used for the inode bitmap
767c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		 */
768e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		blk = ext2fs_inode_bitmap_loc(fs, i);
769e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (blk)
770e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_mark_block_bitmap2(bmap, blk);
771c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	}
7721e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	return 0;
77324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o}
77424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
77524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o/*
77676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o * This function checks to see if a particular block (either a
77776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o * superblock or a block group descriptor) overlaps with an inode or
77876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o * block bitmap block, or with the inode table.
77976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o */
78076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'ostatic void mark_fs_metablock(ext2_resize_t rfs,
78176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o			      ext2fs_block_bitmap meta_bmap,
782e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			      int group, blk64_t blk)
78376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o{
78476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	ext2_filsys 	fs = rfs->new_fs;
785efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
786e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	ext2fs_mark_block_bitmap2(rfs->reserve_blocks, blk);
787e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	ext2fs_block_alloc_stats2(fs, blk, +1);
78876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o
78976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	/*
79076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	 * Check to see if we overlap with the inode or block bitmap,
79176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	 * or the inode tables.  If not, and the block is in use, then
79276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	 * mark it as a block to be moved.
79376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	 */
79476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	if (IS_BLOCK_BM(fs, group, blk)) {
795e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_block_bitmap_loc_set(fs, group, 0);
79676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		rfs->needed_blocks++;
797e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		return;
798e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	}
799e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (IS_INODE_BM(fs, group, blk)) {
800e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_inode_bitmap_loc_set(fs, group, 0);
80176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		rfs->needed_blocks++;
802e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		return;
803e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	}
804e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (IS_INODE_TB(fs, group, blk)) {
805e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_inode_table_loc_set(fs, group, 0);
80676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		rfs->needed_blocks++;
807e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		return;
808e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	}
809e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) {
810e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		dgrp_t i;
811e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
812e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		for (i=0; i < rfs->old_fs->group_desc_count; i++) {
813e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			if (IS_BLOCK_BM(fs, i, blk)) {
814e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				ext2fs_block_bitmap_loc_set(fs, i, 0);
815e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				rfs->needed_blocks++;
816e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				return;
817e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			}
818e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			if (IS_INODE_BM(fs, i, blk)) {
819e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				ext2fs_inode_bitmap_loc_set(fs, i, 0);
820e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				rfs->needed_blocks++;
821e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				return;
822e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			}
823e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			if (IS_INODE_TB(fs, i, blk)) {
824e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				ext2fs_inode_table_loc_set(fs, i, 0);
825e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				rfs->needed_blocks++;
826e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				return;
827e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			}
828e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		}
829e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	}
830e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
831e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				       EXT4_FEATURE_RO_COMPAT_GDT_CSUM) &&
832e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		   (ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT))) {
83386acdebd539864908127561034752082c86105e2Theodore Ts'o		/*
83486acdebd539864908127561034752082c86105e2Theodore Ts'o		 * If the block bitmap is uninitialized, which means
83586acdebd539864908127561034752082c86105e2Theodore Ts'o		 * nothing other than standard metadata in use.
83686acdebd539864908127561034752082c86105e2Theodore Ts'o		 */
83786acdebd539864908127561034752082c86105e2Theodore Ts'o		return;
838e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	} else if (ext2fs_test_block_bitmap2(rfs->old_fs->block_map, blk) &&
839e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		   !ext2fs_test_block_bitmap2(meta_bmap, blk)) {
840e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_mark_block_bitmap2(rfs->move_blocks, blk);
84176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		rfs->needed_blocks++;
84276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	}
84376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o}
84476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o
84576dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o
84676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o/*
84724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * This routine marks and unmarks reserved blocks in the new block
84824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * bitmap.  It also determines which blocks need to be moved and
84924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * places this information into the move_blocks bitmap.
85024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */
851c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'ostatic errcode_t blocks_to_move(ext2_resize_t rfs)
85224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o{
853544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	int		j, has_super;
85486acdebd539864908127561034752082c86105e2Theodore Ts'o	dgrp_t		i, max_groups, g;
855e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t		blk, group_blk;
856e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t		old_blocks, new_blocks;
857e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t		new_size;
858544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	unsigned int	meta_bg, meta_bg_size;
85924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	errcode_t	retval;
860c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	ext2_filsys 	fs, old_fs;
861c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	ext2fs_block_bitmap	meta_bmap;
862e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	int		flex_bg;
86324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
864c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	fs = rfs->new_fs;
865c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	old_fs = rfs->old_fs;
866e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (ext2fs_blocks_count(old_fs->super) > ext2fs_blocks_count(fs->super))
867c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		fs = rfs->old_fs;
868efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
869a13575f4d29a908add19ea27baa102bc6944ee30Theodore Ts'o	retval = ext2fs_allocate_block_bitmap(fs, _("blocks to be moved"),
870c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o					      &rfs->move_blocks);
871c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	if (retval)
872c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		return retval;
873c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o
874efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	retval = ext2fs_allocate_block_bitmap(fs, _("meta-data blocks"),
87564ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o					      &meta_bmap);
87664ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o	if (retval)
87764ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o		return retval;
878efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
87964ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o	retval = mark_table_blocks(old_fs, meta_bmap);
880c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	if (retval)
881c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		return retval;
882c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o
883c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	fs = rfs->new_fs;
884efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
8851e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	/*
886e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 * If we're shrinking the filesystem, we need to move any
887e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 * group's metadata blocks (either allocation bitmaps or the
888e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 * inode table) which are beyond the end of the new
889e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 * filesystem.
890e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 */
891e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	new_size = ext2fs_blocks_count(fs->super);
892e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (new_size < ext2fs_blocks_count(old_fs->super)) {
893e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		for (g = 0; g < fs->group_desc_count; g++) {
894e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			int realloc = 0;
895e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			/*
896e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			 * ext2fs_allocate_group_table will re-allocate any
897e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			 * metadata blocks whose location is set to zero.
898e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			 */
899e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			if (ext2fs_block_bitmap_loc(fs, g) >= new_size) {
900e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				ext2fs_block_bitmap_loc_set(fs, g, 0);
901e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				realloc = 1;
902e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			}
903e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			if (ext2fs_inode_bitmap_loc(fs, g) >= new_size) {
904e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				ext2fs_inode_bitmap_loc_set(fs, g, 0);
905e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				realloc = 1;
906e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			}
907e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			if ((ext2fs_inode_table_loc(fs, g) +
908e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			     fs->inode_blocks_per_group) > new_size) {
909e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				ext2fs_inode_table_loc_set(fs, g, 0);
910e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				realloc = 1;
911e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			}
912e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
913e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			if (realloc) {
914e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				retval = ext2fs_allocate_group_table(fs, g, 0);
915e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				if (retval)
916e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					return retval;
917e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			}
918e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		}
919e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	}
920e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
921e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	/*
9221e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	 * If we're shrinking the filesystem, we need to move all of
9231e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	 * the blocks that don't fit any more
9241e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	 */
925e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	for (blk = ext2fs_blocks_count(fs->super);
926e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	     blk < ext2fs_blocks_count(old_fs->super); blk++) {
927e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		g = ext2fs_group_of_blk2(fs, blk);
92886acdebd539864908127561034752082c86105e2Theodore Ts'o		if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
92986acdebd539864908127561034752082c86105e2Theodore Ts'o					       EXT4_FEATURE_RO_COMPAT_GDT_CSUM) &&
930e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		    ext2fs_bg_flags_test(old_fs, g, EXT2_BG_BLOCK_UNINIT)) {
93186acdebd539864908127561034752082c86105e2Theodore Ts'o			/*
93286acdebd539864908127561034752082c86105e2Theodore Ts'o			 * The block bitmap is uninitialized, so skip
93386acdebd539864908127561034752082c86105e2Theodore Ts'o			 * to the next block group.
93486acdebd539864908127561034752082c86105e2Theodore Ts'o			 */
935e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			blk = ext2fs_group_first_block2(fs, g+1) - 1;
93686acdebd539864908127561034752082c86105e2Theodore Ts'o			continue;
93786acdebd539864908127561034752082c86105e2Theodore Ts'o		}
938e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) &&
939e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		    !ext2fs_test_block_bitmap2(meta_bmap, blk)) {
940e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_mark_block_bitmap2(rfs->move_blocks, blk);
9411e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o			rfs->needed_blocks++;
942c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		}
943e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_mark_block_bitmap2(rfs->reserve_blocks, blk);
9441e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	}
945efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
94676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) {
94776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		old_blocks = old_fs->super->s_first_meta_bg;
94876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		new_blocks = fs->super->s_first_meta_bg;
94976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	} else {
9509213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		old_blocks = old_fs->desc_blocks + old_fs->super->s_reserved_gdt_blocks;
9519213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		new_blocks = fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
95276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	}
953efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
954c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	if (old_blocks == new_blocks) {
955c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		retval = 0;
956c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		goto errout;
957c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	}
95824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
9591333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o	max_groups = fs->group_desc_count;
9601333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o	if (max_groups > old_fs->group_desc_count)
9611333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o		max_groups = old_fs->group_desc_count;
962c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	group_blk = old_fs->super->s_first_data_block;
96324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	/*
96424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * If we're reducing the number of descriptor blocks, this
96524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * makes life easy.  :-)   We just have to mark some extra
96624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * blocks as free.
96724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 */
96824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	if (old_blocks > new_blocks) {
9691333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o		for (i = 0; i < max_groups; i++) {
9701e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o			if (!ext2fs_bg_has_super(fs, i)) {
9711e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o				group_blk += fs->super->s_blocks_per_group;
97224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o				continue;
97324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o			}
974c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o			for (blk = group_blk+1+new_blocks;
975c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o			     blk < group_blk+1+old_blocks; blk++) {
976e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				ext2fs_block_alloc_stats2(fs, blk, -1);
977052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o				rfs->needed_blocks--;
978052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o			}
9791e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o			group_blk += fs->super->s_blocks_per_group;
98024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o		}
981c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		retval = 0;
982c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		goto errout;
98324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	}
98424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	/*
98524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * If we're increasing the number of descriptor blocks, life
986efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	 * gets interesting....
98724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 */
988f2de1d38d0819b17895977fabc52d81d0ea6ec00Valerie Clement	meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super);
989e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	flex_bg = fs->super->s_feature_incompat &
990e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		EXT4_FEATURE_INCOMPAT_FLEX_BG;
991e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	/* first reserve all of the existing fs meta blocks */
9921333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o	for (i = 0; i < max_groups; i++) {
99376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		has_super = ext2fs_bg_has_super(fs, i);
99476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		if (has_super)
99576dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o			mark_fs_metablock(rfs, meta_bmap, i, group_blk);
99676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o
99776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		meta_bg = i / meta_bg_size;
99876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		if (!(fs->super->s_feature_incompat &
99976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		      EXT2_FEATURE_INCOMPAT_META_BG) ||
100076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		    (meta_bg < fs->super->s_first_meta_bg)) {
1001424cb7b62aa417db2eaec79cfaec7433b31f8726Theodore Ts'o			if (has_super) {
1002424cb7b62aa417db2eaec79cfaec7433b31f8726Theodore Ts'o				for (blk = group_blk+1;
1003424cb7b62aa417db2eaec79cfaec7433b31f8726Theodore Ts'o				     blk < group_blk + 1 + new_blocks; blk++)
1004efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o					mark_fs_metablock(rfs, meta_bmap,
1005424cb7b62aa417db2eaec79cfaec7433b31f8726Theodore Ts'o							  i, blk);
1006424cb7b62aa417db2eaec79cfaec7433b31f8726Theodore Ts'o			}
100776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		} else {
100876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o			if (has_super)
100976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o				has_super = 1;
101076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o			if (((i % meta_bg_size) == 0) ||
101176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o			    ((i % meta_bg_size) == 1) ||
101276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o			    ((i % meta_bg_size) == (meta_bg_size-1)))
101376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o				mark_fs_metablock(rfs, meta_bmap, i,
101476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o						  group_blk + has_super);
101524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o		}
101676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o
10171e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		/*
1018c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		 * Reserve the existing meta blocks that we know
1019c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		 * aren't to be moved.
102065f0aab98b20b5994a726ab90d355248bcddfffdJP Abgrall		 *
1021e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		 * For flex_bg file systems, in order to avoid
1022e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		 * overwriting fs metadata (especially inode table
1023e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		 * blocks) belonging to a different block group when
1024e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		 * we are relocating the inode tables, we need to
1025e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		 * reserve all existing fs metadata blocks.
102665f0aab98b20b5994a726ab90d355248bcddfffdJP Abgrall		 */
1027e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (ext2fs_block_bitmap_loc(fs, i))
1028e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_mark_block_bitmap2(rfs->reserve_blocks,
1029e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				 ext2fs_block_bitmap_loc(fs, i));
1030e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		else if (flex_bg && i < old_fs->group_desc_count)
1031e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_mark_block_bitmap2(rfs->reserve_blocks,
1032e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				 ext2fs_block_bitmap_loc(old_fs, i));
1033e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
1034e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (ext2fs_inode_bitmap_loc(fs, i))
1035e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_mark_block_bitmap2(rfs->reserve_blocks,
1036e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				 ext2fs_inode_bitmap_loc(fs, i));
1037e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		else if (flex_bg && i < old_fs->group_desc_count)
1038e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_mark_block_bitmap2(rfs->reserve_blocks,
1039e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				 ext2fs_inode_bitmap_loc(old_fs, i));
1040e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
1041e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (ext2fs_inode_table_loc(fs, i))
1042e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_mark_block_bitmap_range2(rfs->reserve_blocks,
1043e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					ext2fs_inode_table_loc(fs, i),
1044e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					fs->inode_blocks_per_group);
1045e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		else if (flex_bg && i < old_fs->group_desc_count)
1046e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_mark_block_bitmap_range2(rfs->reserve_blocks,
1047e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					ext2fs_inode_table_loc(old_fs, i),
1048e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					old_fs->inode_blocks_per_group);
1049e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
1050e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		group_blk += rfs->new_fs->super->s_blocks_per_group;
1051e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	}
1052e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
1053e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	/* Allocate the missing data structures */
1054e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	for (i = 0; i < max_groups; i++) {
1055e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (ext2fs_inode_table_loc(fs, i) &&
1056e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		    ext2fs_inode_bitmap_loc(fs, i) &&
1057e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		    ext2fs_block_bitmap_loc(fs, i))
1058e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			continue;
1059e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
10601e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		retval = ext2fs_allocate_group_table(fs, i,
10611e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o						     rfs->reserve_blocks);
10621e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		if (retval)
1063c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o			goto errout;
106424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
10651e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		/*
1066c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		 * For those structures that have changed, we need to
1067c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		 * do bookkeepping.
10681e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		 */
1069e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (ext2fs_block_bitmap_loc(old_fs, i) !=
1070e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		    (blk = ext2fs_block_bitmap_loc(fs, i))) {
1071e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_block_alloc_stats2(fs, blk, +1);
1072e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) &&
1073e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			    !ext2fs_test_block_bitmap2(meta_bmap, blk))
1074e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				ext2fs_mark_block_bitmap2(rfs->move_blocks,
1075c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o							 blk);
1076c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		}
1077e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (ext2fs_inode_bitmap_loc(old_fs, i) !=
1078e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		    (blk = ext2fs_inode_bitmap_loc(fs, i))) {
1079e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_block_alloc_stats2(fs, blk, +1);
1080e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) &&
1081e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			    !ext2fs_test_block_bitmap2(meta_bmap, blk))
1082e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				ext2fs_mark_block_bitmap2(rfs->move_blocks,
1083c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o							 blk);
1084c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		}
108524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
1086052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		/*
1087052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		 * The inode table, if we need to relocate it, is
1088052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		 * handled specially.  We have to reserve the blocks
1089052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		 * for both the old and the new inode table, since we
1090052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		 * can't have the inode table be destroyed during the
1091052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		 * block relocation phase.
1092052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		 */
1093e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (ext2fs_inode_table_loc(fs, i) == ext2fs_inode_table_loc(old_fs, i))
1094e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			continue;	/* inode table not moved */
1095052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o
1096c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		rfs->needed_blocks += fs->inode_blocks_per_group;
1097052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o
1098052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		/*
1099052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		 * Mark the new inode table as in use in the new block
1100efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		 * allocation bitmap, and move any blocks that might
1101c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		 * be necessary.
1102052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		 */
1103e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		for (blk = ext2fs_inode_table_loc(fs, i), j=0;
1104c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		     j < fs->inode_blocks_per_group ; j++, blk++) {
1105e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_block_alloc_stats2(fs, blk, +1);
1106e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) &&
1107e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			    !ext2fs_test_block_bitmap2(meta_bmap, blk))
1108e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				ext2fs_mark_block_bitmap2(rfs->move_blocks,
1109c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o							 blk);
1110c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		}
1111efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
11121e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		/*
1113052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		 * Make sure the old inode table is reserved in the
1114052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		 * block reservation bitmap.
11151e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		 */
1116e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		for (blk = ext2fs_inode_table_loc(rfs->old_fs, i), j=0;
1117052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		     j < fs->inode_blocks_per_group ; j++, blk++)
1118e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_mark_block_bitmap2(rfs->reserve_blocks, blk);
11191e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	}
1120c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	retval = 0;
1121c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o
1122c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'oerrout:
1123c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	if (meta_bmap)
1124c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		ext2fs_free_block_bitmap(meta_bmap);
1125efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
1126c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	return retval;
11271e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o}
112824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
1129a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/*
1130a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * This helper function tries to allocate a new block.  We try to
1131a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * avoid hitting the original group descriptor blocks at least at
1132a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * first, since we want to make it possible to recover from a badly
1133a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * aborted resize operation as much as possible.
1134a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o *
1135a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * In the future, I may further modify this routine to balance out
1136a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * where we get the new blocks across the various block groups.
1137a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Ideally we would allocate blocks that corresponded with the block
1138a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * group of the containing inode, and keep contiguous blocks
1139a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * together.  However, this very difficult to do efficiently, since we
1140a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * don't have the necessary information up front.
1141a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */
1142a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1143a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define AVOID_OLD	1
1144a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define DESPERATION	2
1145a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1146a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic void init_block_alloc(ext2_resize_t rfs)
1147a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{
1148a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	rfs->alloc_state = AVOID_OLD;
1149a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	rfs->new_blk = rfs->new_fs->super->s_first_data_block;
11502bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o#if 0
11512bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o	/* HACK for testing */
1152e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (ext2fs_blocks_count(rfs->new_fs->super) >
1153e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	    ext2fs_blocks_count(rfs->old_fs->super))
1154e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		rfs->new_blk = ext2fs_blocks_count(rfs->old_fs->super);
11552bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o#endif
1156a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o}
1157a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1158e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic blk64_t get_new_block(ext2_resize_t rfs)
1159a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{
1160a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	ext2_filsys	fs = rfs->new_fs;
1161efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
1162a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	while (1) {
1163e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (rfs->new_blk >= ext2fs_blocks_count(fs->super)) {
1164a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			if (rfs->alloc_state == DESPERATION)
1165a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				return 0;
1166a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1167a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG
1168a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			if (rfs->flags & RESIZE_DEBUG_BMOVE)
1169f35fd3d5eeb3e35660ea87adbc170978c3cdf9e3Theodore Ts'o				printf("Going into desperation mode "
1170f35fd3d5eeb3e35660ea87adbc170978c3cdf9e3Theodore Ts'o				       "for block allocations\n");
1171efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o#endif
1172a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			rfs->alloc_state = DESPERATION;
1173a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			rfs->new_blk = fs->super->s_first_data_block;
1174a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			continue;
1175a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		}
1176e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (ext2fs_test_block_bitmap2(fs->block_map, rfs->new_blk) ||
1177e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		    ext2fs_test_block_bitmap2(rfs->reserve_blocks,
1178a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o					     rfs->new_blk) ||
1179a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		    ((rfs->alloc_state == AVOID_OLD) &&
1180e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		     (rfs->new_blk < ext2fs_blocks_count(rfs->old_fs->super)) &&
1181e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		     ext2fs_test_block_bitmap2(rfs->old_fs->block_map,
1182a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o					      rfs->new_blk))) {
1183a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			rfs->new_blk++;
1184a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			continue;
1185a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		}
1186a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		return rfs->new_blk;
1187a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	}
1188a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o}
1189a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
11907f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'ostatic errcode_t resize2fs_get_alloc_block(ext2_filsys fs, blk64_t goal,
11917f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o					   blk64_t *ret)
11927f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o{
11937f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o	ext2_resize_t rfs = (ext2_resize_t) fs->priv_data;
1194e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t blk;
11957f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o
11967f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o	blk = get_new_block(rfs);
11977f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o	if (!blk)
11987f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o		return ENOSPC;
11997f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o
12007f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o#ifdef RESIZE2FS_DEBUG
12017f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o	if (rfs->flags & 0xF)
1202e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		printf("get_alloc_block allocating %llu\n", blk);
12037f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o#endif
12047f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o
1205e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	ext2fs_mark_block_bitmap2(rfs->old_fs->block_map, blk);
1206e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	ext2fs_mark_block_bitmap2(rfs->new_fs->block_map, blk);
12077f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o	*ret = (blk64_t) blk;
12087f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o	return 0;
12097f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o}
12107f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o
1211a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t block_mover(ext2_resize_t rfs)
1212a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{
1213e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t			blk, old_blk, new_blk;
1214a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	ext2_filsys		fs = rfs->new_fs;
1215a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	ext2_filsys		old_fs = rfs->old_fs;
1216a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	errcode_t		retval;
1217e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	__u64			size;
1218e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	int			c;
1219a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	int			to_move, moved;
12207d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o	ext2_badblocks_list	badblock_list = 0;
12217d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o	int			bb_modified = 0;
1222efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
12237f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o	fs->get_alloc_block = resize2fs_get_alloc_block;
12247f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o	old_fs->get_alloc_block = resize2fs_get_alloc_block;
12257f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o
12267d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o	retval = ext2fs_read_bb_inode(old_fs, &badblock_list);
12277d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o	if (retval)
12287d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o		return retval;
1229a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1230a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	new_blk = fs->super->s_first_data_block;
1231a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (!rfs->itable_buf) {
1232e5aace908e9d1161a594944d9360f9f0cdd18099Theodore Ts'o		retval = ext2fs_get_array(fs->blocksize,
1233a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o					fs->inode_blocks_per_group,
1234c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o					&rfs->itable_buf);
1235a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (retval)
1236a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			return retval;
1237a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	}
1238a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	retval = ext2fs_create_extent_table(&rfs->bmap, 0);
1239a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval)
1240a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		return retval;
1241a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1242a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	/*
1243a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 * The first step is to figure out where all of the blocks
1244a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 * will go.
1245a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 */
1246a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	to_move = moved = 0;
1247a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	init_block_alloc(rfs);
1248e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	for (blk = B2C(old_fs->super->s_first_data_block);
1249e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	     blk < ext2fs_blocks_count(old_fs->super);
1250e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	     blk += EXT2FS_CLUSTER_RATIO(fs)) {
1251e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (!ext2fs_test_block_bitmap2(old_fs->block_map, blk))
1252a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			continue;
1253e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (!ext2fs_test_block_bitmap2(rfs->move_blocks, blk))
1254a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			continue;
12557d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o		if (ext2fs_badblocks_list_test(badblock_list, blk)) {
12567d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o			ext2fs_badblocks_list_del(badblock_list, blk);
12577d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o			bb_modified++;
12587d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o			continue;
12597d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o		}
1260a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1261a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		new_blk = get_new_block(rfs);
1262a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (!new_blk) {
1263a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			retval = ENOSPC;
1264a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			goto errout;
1265a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		}
1266e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_block_alloc_stats2(fs, new_blk, +1);
1267e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_add_extent_entry(rfs->bmap, B2C(blk), B2C(new_blk));
1268a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		to_move++;
1269a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	}
1270efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
1271a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (to_move == 0) {
1272cefbf4870c0593e3c7a01b8d5494463b247d90f0Theodore Ts'o		if (rfs->bmap) {
1273cefbf4870c0593e3c7a01b8d5494463b247d90f0Theodore Ts'o			ext2fs_free_extent_table(rfs->bmap);
1274cefbf4870c0593e3c7a01b8d5494463b247d90f0Theodore Ts'o			rfs->bmap = 0;
1275cefbf4870c0593e3c7a01b8d5494463b247d90f0Theodore Ts'o		}
1276a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		retval = 0;
1277a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		goto errout;
1278a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	}
1279a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1280a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	/*
1281a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 * Step two is to actually move the blocks
1282a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 */
1283a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	retval =  ext2fs_iterate_extent(rfs->bmap, 0, 0, 0);
1284a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval) goto errout;
1285a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
12863b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o	if (rfs->progress) {
12873b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		retval = (rfs->progress)(rfs, E2_RSZ_BLOCK_RELOC_PASS,
12883b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o					 0, to_move);
12893b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		if (retval)
12903b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o			goto errout;
12913b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o	}
1292a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	while (1) {
1293a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		retval = ext2fs_iterate_extent(rfs->bmap, &old_blk, &new_blk, &size);
1294a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (retval) goto errout;
1295a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (!size)
1296a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			break;
1297e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		old_blk = C2B(old_blk);
1298e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		new_blk = C2B(new_blk);
1299e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		size = C2B(size);
1300a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG
1301a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (rfs->flags & RESIZE_DEBUG_BMOVE)
1302e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			printf("Moving %llu blocks %llu->%llu\n",
1303f35fd3d5eeb3e35660ea87adbc170978c3cdf9e3Theodore Ts'o			       size, old_blk, new_blk);
1304a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif
1305a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		do {
1306a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			c = size;
1307a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			if (c > fs->inode_blocks_per_group)
1308a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				c = fs->inode_blocks_per_group;
1309e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			retval = io_channel_read_blk64(fs->io, old_blk, c,
1310e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall						       rfs->itable_buf);
1311a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			if (retval) goto errout;
1312e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			retval = io_channel_write_blk64(fs->io, new_blk, c,
1313e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall							rfs->itable_buf);
1314a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			if (retval) goto errout;
1315a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			size -= c;
1316a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			new_blk += c;
1317a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			old_blk += c;
1318a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			moved += c;
1319a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			if (rfs->progress) {
1320a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				io_channel_flush(fs->io);
13213b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o				retval = (rfs->progress)(rfs,
13223b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o						E2_RSZ_BLOCK_RELOC_PASS,
1323a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o						moved, to_move);
13243b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o				if (retval)
13253b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o					goto errout;
1326a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			}
1327a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		} while (size > 0);
1328a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		io_channel_flush(fs->io);
1329a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	}
1330a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1331a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'oerrout:
13327d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o	if (badblock_list) {
13337d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o		if (!retval && bb_modified)
13347d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o			retval = ext2fs_update_bb_inode(old_fs,
13357d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o							badblock_list);
13367d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o		ext2fs_badblocks_list_free(badblock_list);
13377d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o	}
1338a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	return retval;
1339a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o}
1340a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1341a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1342a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* --------------------------------------------------------------------
1343a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o *
1344a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Resize processing, phase 3
1345a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o *
1346a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * --------------------------------------------------------------------
1347a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */
1348a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1349a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1350e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/*
1351e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * The extent translation table is stored in clusters so we need to
1352e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * take special care when mapping a source block number to its
1353e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * destination block number.
1354e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */
1355e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic __u64 extent_translate(ext2_filsys fs, ext2_extent extent, __u64 old_loc)
1356e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{
1357e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	__u64 new_block = C2B(ext2fs_extent_translate(extent, B2C(old_loc)));
1358e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
1359e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (new_block != 0)
1360e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		new_block += old_loc & (EXT2FS_CLUSTER_RATIO(fs) - 1);
1361e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	return new_block;
1362e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}
1363e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
1364a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostruct process_block_struct {
1365a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	ext2_resize_t 		rfs;
1366dfcdc32f8d6623a35a9e66f503c535e4081b7266Theodore Ts'o	ext2_ino_t		ino;
1367a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	struct ext2_inode *	inode;
1368a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	errcode_t		error;
1369a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	int			is_dir;
1370a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	int			changed;
1371a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o};
1372a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1373e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int process_block(ext2_filsys fs, blk64_t	*block_nr,
1374efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			 e2_blkcnt_t blockcnt,
1375e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			 blk64_t ref_block EXT2FS_ATTR((unused)),
1376544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o			 int ref_offset EXT2FS_ATTR((unused)), void *priv_data)
1377a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{
1378a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	struct process_block_struct *pb;
1379a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	errcode_t	retval;
1380e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t		block, new_block;
1381a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	int		ret = 0;
1382a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1383a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	pb = (struct process_block_struct *) priv_data;
1384a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	block = *block_nr;
1385a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (pb->rfs->bmap) {
1386e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		new_block = extent_translate(fs, pb->rfs->bmap, block);
1387a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (new_block) {
1388a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			*block_nr = new_block;
1389a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			ret |= BLOCK_CHANGED;
1390a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			pb->changed = 1;
1391a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG
1392a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			if (pb->rfs->flags & RESIZE_DEBUG_BMOVE)
1393e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				printf("ino=%u, blockcnt=%lld, %llu->%llu\n",
1394a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				       pb->ino, blockcnt, block, new_block);
1395a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif
1396a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			block = new_block;
1397a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		}
1398a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	}
1399a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (pb->is_dir) {
1400e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		retval = ext2fs_add_dir_block2(fs->dblist, pb->ino,
1401e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					       block, (int) blockcnt);
1402a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (retval) {
1403a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			pb->error = retval;
1404a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			ret |= BLOCK_ABORT;
1405a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		}
1406a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	}
1407a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	return ret;
1408a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o}
1409a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1410a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/*
1411a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Progress callback
1412a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */
1413efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'ostatic errcode_t progress_callback(ext2_filsys fs,
1414544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o				   ext2_inode_scan scan EXT2FS_ATTR((unused)),
1415a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				   dgrp_t group, void * priv_data)
1416a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{
1417a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	ext2_resize_t rfs = (ext2_resize_t) priv_data;
14183b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o	errcode_t		retval;
1419a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1420a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	/*
1421f4b2a6db3f13f4210697bcd273086006c719929bTheodore Ts'o	 * This check is to protect against old ext2 libraries.  It
1422f4b2a6db3f13f4210697bcd273086006c719929bTheodore Ts'o	 * shouldn't be needed against new libraries.
1423a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 */
1424f4b2a6db3f13f4210697bcd273086006c719929bTheodore Ts'o	if ((group+1) == 0)
1425a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		return 0;
1426a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1427a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (rfs->progress) {
1428a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		io_channel_flush(fs->io);
14293b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		retval = (rfs->progress)(rfs, E2_RSZ_INODE_SCAN_PASS,
14303b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o					 group+1, fs->group_desc_count);
14313b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		if (retval)
14323b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o			return retval;
1433a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	}
1434efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
1435a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	return 0;
1436a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o}
1437a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1438a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t inode_scan_and_fix(ext2_resize_t rfs)
1439a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{
1440a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	struct process_block_struct	pb;
1441dfcdc32f8d6623a35a9e66f503c535e4081b7266Theodore Ts'o	ext2_ino_t		ino, new_inode;
1442edfd9b0a9fe7b90f56da981ca26d5233cc3749d6Theodore Ts'o	struct ext2_inode 	*inode = NULL;
1443a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	ext2_inode_scan 	scan = NULL;
1444a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	errcode_t		retval;
1445a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	char			*block_buf = 0;
1446dfcdc32f8d6623a35a9e66f503c535e4081b7266Theodore Ts'o	ext2_ino_t		start_to_move;
1447e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t			orig_size;
1448e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t			new_block;
14494ef28824ca29e86053398c3e4cecca6d88b2b397Eric Sandeen	int			inode_size;
1450efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
1451a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if ((rfs->old_fs->group_desc_count <=
1452a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	     rfs->new_fs->group_desc_count) &&
1453a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	    !rfs->bmap)
1454a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		return 0;
1455a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
14562bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o	/*
14572bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o	 * Save the original size of the old filesystem, and
14582bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o	 * temporarily set the size to be the new size if the new size
14592bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o	 * is larger.  We need to do this to avoid catching an error
14602bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o	 * by the block iterator routines
14612bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o	 */
1462e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	orig_size = ext2fs_blocks_count(rfs->old_fs->super);
1463e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (orig_size < ext2fs_blocks_count(rfs->new_fs->super))
1464e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_blocks_count_set(rfs->old_fs->super,
1465e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				ext2fs_blocks_count(rfs->new_fs->super));
14662bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o
1467a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	retval = ext2fs_open_inode_scan(rfs->old_fs, 0, &scan);
1468a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval) goto errout;
1469a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1470a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	retval = ext2fs_init_dblist(rfs->old_fs, 0);
1471a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval) goto errout;
1472e5aace908e9d1161a594944d9360f9f0cdd18099Theodore Ts'o	retval = ext2fs_get_array(rfs->old_fs->blocksize, 3, &block_buf);
1473a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval) goto errout;
1474a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1475a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	start_to_move = (rfs->new_fs->group_desc_count *
1476a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			 rfs->new_fs->super->s_inodes_per_group);
1477efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
14783b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o	if (rfs->progress) {
14793b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		retval = (rfs->progress)(rfs, E2_RSZ_INODE_SCAN_PASS,
14803b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o					 0, rfs->old_fs->group_desc_count);
14813b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		if (retval)
14823b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o			goto errout;
14833b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o	}
1484a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	ext2fs_set_inode_callback(scan, progress_callback, (void *) rfs);
1485a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	pb.rfs = rfs;
1486edfd9b0a9fe7b90f56da981ca26d5233cc3749d6Theodore Ts'o	pb.inode = inode;
1487a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	pb.error = 0;
1488a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	new_inode = EXT2_FIRST_INODE(rfs->new_fs->super);
14894ef28824ca29e86053398c3e4cecca6d88b2b397Eric Sandeen	inode_size = EXT2_INODE_SIZE(rfs->new_fs->super);
1490edfd9b0a9fe7b90f56da981ca26d5233cc3749d6Theodore Ts'o	inode = malloc(inode_size);
1491edfd9b0a9fe7b90f56da981ca26d5233cc3749d6Theodore Ts'o	if (!inode) {
14924ef28824ca29e86053398c3e4cecca6d88b2b397Eric Sandeen		retval = ENOMEM;
14934ef28824ca29e86053398c3e4cecca6d88b2b397Eric Sandeen		goto errout;
14944ef28824ca29e86053398c3e4cecca6d88b2b397Eric Sandeen	}
1495a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	/*
1496a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 * First, copy all of the inodes that need to be moved
1497a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 * elsewhere in the inode table
1498a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 */
1499a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	while (1) {
1500edfd9b0a9fe7b90f56da981ca26d5233cc3749d6Theodore Ts'o		retval = ext2fs_get_next_inode_full(scan, &ino, inode, inode_size);
1501a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (retval) goto errout;
1502a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (!ino)
1503a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			break;
1504a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1505edfd9b0a9fe7b90f56da981ca26d5233cc3749d6Theodore Ts'o		if (inode->i_links_count == 0 && ino != EXT2_RESIZE_INO)
1506a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			continue; /* inode not in use */
1507a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1508edfd9b0a9fe7b90f56da981ca26d5233cc3749d6Theodore Ts'o		pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
1509a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		pb.changed = 0;
1510a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1511e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (ext2fs_file_acl_block(rfs->old_fs, inode) && rfs->bmap) {
1512e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			new_block = extent_translate(rfs->old_fs, rfs->bmap,
1513e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				ext2fs_file_acl_block(rfs->old_fs, inode));
1514ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o			if (new_block) {
1515e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				ext2fs_file_acl_block_set(rfs->old_fs, inode,
1516e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall							  new_block);
1517efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o				retval = ext2fs_write_inode_full(rfs->old_fs,
1518edfd9b0a9fe7b90f56da981ca26d5233cc3749d6Theodore Ts'o							    ino, inode, inode_size);
1519ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o				if (retval) goto errout;
1520ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o			}
1521ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o		}
1522efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
1523e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (ext2fs_inode_has_valid_blocks2(rfs->old_fs, inode) &&
1524a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		    (rfs->bmap || pb.is_dir)) {
1525a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			pb.ino = ino;
1526e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			retval = ext2fs_block_iterate3(rfs->old_fs,
1527a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o						       ino, 0, block_buf,
1528a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o						       process_block, &pb);
1529a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			if (retval)
1530a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				goto errout;
1531a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			if (pb.error) {
1532a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				retval = pb.error;
1533a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				goto errout;
1534a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			}
1535a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		}
1536a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1537a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (ino <= start_to_move)
1538a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			continue; /* Don't need to move it. */
1539a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1540a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		/*
1541a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		 * Find a new inode
1542a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		 */
154386acdebd539864908127561034752082c86105e2Theodore Ts'o		retval = ext2fs_new_inode(rfs->new_fs, 0, 0, 0, &new_inode);
154486acdebd539864908127561034752082c86105e2Theodore Ts'o		if (retval)
154586acdebd539864908127561034752082c86105e2Theodore Ts'o			goto errout;
154686acdebd539864908127561034752082c86105e2Theodore Ts'o
154774128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o		ext2fs_inode_alloc_stats2(rfs->new_fs, new_inode, +1,
154874128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o					  pb.is_dir);
1549a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (pb.changed) {
1550a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			/* Get the new version of the inode */
15514ef28824ca29e86053398c3e4cecca6d88b2b397Eric Sandeen			retval = ext2fs_read_inode_full(rfs->old_fs, ino,
1552edfd9b0a9fe7b90f56da981ca26d5233cc3749d6Theodore Ts'o						inode, inode_size);
1553a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			if (retval) goto errout;
1554a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		}
1555edfd9b0a9fe7b90f56da981ca26d5233cc3749d6Theodore Ts'o		inode->i_ctime = time(0);
15564ef28824ca29e86053398c3e4cecca6d88b2b397Eric Sandeen		retval = ext2fs_write_inode_full(rfs->old_fs, new_inode,
1557edfd9b0a9fe7b90f56da981ca26d5233cc3749d6Theodore Ts'o						inode, inode_size);
1558a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (retval) goto errout;
1559a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1560a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG
1561a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (rfs->flags & RESIZE_DEBUG_INODEMAP)
1562f35fd3d5eeb3e35660ea87adbc170978c3cdf9e3Theodore Ts'o			printf("Inode moved %u->%u\n", ino, new_inode);
1563a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif
1564a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (!rfs->imap) {
1565a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			retval = ext2fs_create_extent_table(&rfs->imap, 0);
1566a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			if (retval)
1567a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				goto errout;
1568a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		}
1569a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		ext2fs_add_extent_entry(rfs->imap, ino, new_inode);
1570a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	}
1571a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	io_channel_flush(rfs->old_fs->io);
1572a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1573a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'oerrout:
1574e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	ext2fs_blocks_count_set(rfs->old_fs->super, orig_size);
1575a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (rfs->bmap) {
1576a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		ext2fs_free_extent_table(rfs->bmap);
1577a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		rfs->bmap = 0;
1578a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	}
1579a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (scan)
1580a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		ext2fs_close_inode_scan(scan);
1581a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (block_buf)
1582c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o		ext2fs_free_mem(&block_buf);
158345e338f5332a54295893dba2e32cc093d1316f60Jim Meyering	free(inode);
1584a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	return retval;
1585a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o}
1586a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1587a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* --------------------------------------------------------------------
1588a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o *
1589a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Resize processing, phase 4.
1590a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o *
1591a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * --------------------------------------------------------------------
1592a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */
1593a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1594a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostruct istruct {
1595a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	ext2_resize_t rfs;
15963b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o	errcode_t	err;
159703fa6f8ae28a87018325c892f731097cc97d9eacTheodore Ts'o	unsigned int	max_dirs;
159803fa6f8ae28a87018325c892f731097cc97d9eacTheodore Ts'o	unsigned int	num;
1599a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o};
1600a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1601efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'ostatic int check_and_change_inodes(ext2_ino_t dir,
1602544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o				   int entry EXT2FS_ATTR((unused)),
1603a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				   struct ext2_dir_entry *dirent, int offset,
1604544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o				   int	blocksize EXT2FS_ATTR((unused)),
1605efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o				   char *buf EXT2FS_ATTR((unused)),
1606544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o				   void *priv_data)
1607a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{
1608a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	struct istruct *is = (struct istruct *) priv_data;
1609085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o	struct ext2_inode 	inode;
1610085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o	ext2_ino_t		new_inode;
1611085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o	errcode_t		retval;
1612a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1613a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (is->rfs->progress && offset == 0) {
1614a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		io_channel_flush(is->rfs->old_fs->io);
16153b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		is->err = (is->rfs->progress)(is->rfs,
16163b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o					      E2_RSZ_INODE_REF_UPD_PASS,
16171333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o					      ++is->num, is->max_dirs);
16183b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		if (is->err)
16193b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o			return DIRENT_ABORT;
1620a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	}
1621a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1622a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (!dirent->inode)
1623a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		return 0;
1624a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1625a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	new_inode = ext2fs_extent_translate(is->rfs->imap, dirent->inode);
1626a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1627a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (!new_inode)
1628a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		return 0;
1629a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG
1630a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (is->rfs->flags & RESIZE_DEBUG_INODEMAP)
1631f35fd3d5eeb3e35660ea87adbc170978c3cdf9e3Theodore Ts'o		printf("Inode translate (dir=%u, name=%.*s, %u->%u)\n",
163206191693d4d253a8496677dd02e3b8529a7fce2cTheodore Ts'o		       dir, dirent->name_len&0xFF, dirent->name,
1633a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		       dirent->inode, new_inode);
1634a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif
1635a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1636a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	dirent->inode = new_inode;
1637a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1638085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o	/* Update the directory mtime and ctime */
1639085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o	retval = ext2fs_read_inode(is->rfs->old_fs, dir, &inode);
1640085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o	if (retval == 0) {
1641085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o		inode.i_mtime = inode.i_ctime = time(0);
1642d2b2a488f996871e6e40789a7890afc2f59730dbBrian Behlendorf		is->err = ext2fs_write_inode(is->rfs->old_fs, dir, &inode);
1643d2b2a488f996871e6e40789a7890afc2f59730dbBrian Behlendorf		if (is->err)
1644d2b2a488f996871e6e40789a7890afc2f59730dbBrian Behlendorf			return DIRENT_ABORT;
1645085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o	}
1646085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o
1647a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	return DIRENT_CHANGED;
1648a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o}
1649a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1650a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t inode_ref_fix(ext2_resize_t rfs)
1651a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{
1652a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	errcode_t		retval;
1653a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	struct istruct 		is;
1654efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
1655a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (!rfs->imap)
1656a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		return 0;
1657efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
1658a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	/*
1659a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 * Now, we iterate over all of the directories to update the
1660a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 * inode references
1661a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 */
1662a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	is.num = 0;
1663e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	is.max_dirs = ext2fs_dblist_count2(rfs->old_fs->dblist);
1664a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	is.rfs = rfs;
16653b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o	is.err = 0;
1666a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
16673b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o	if (rfs->progress) {
16683b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		retval = (rfs->progress)(rfs, E2_RSZ_INODE_REF_UPD_PASS,
16691333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o					 0, is.max_dirs);
16703b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		if (retval)
16713b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o			goto errout;
16723b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o	}
1673efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
1674a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	retval = ext2fs_dblist_dir_iterate(rfs->old_fs->dblist,
1675a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o					   DIRENT_FLAG_INCLUDE_EMPTY, 0,
1676a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o					   check_and_change_inodes, &is);
16773b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o	if (retval)
16783b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		goto errout;
16793b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o	if (is.err) {
16803b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		retval = is.err;
16813b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		goto errout;
16823b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o	}
1683a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
168488dbf8287f831d02e8d5023be4f9b42ca224fb75Theodore Ts'o	if (rfs->progress && (is.num < is.max_dirs))
168588dbf8287f831d02e8d5023be4f9b42ca224fb75Theodore Ts'o		(rfs->progress)(rfs, E2_RSZ_INODE_REF_UPD_PASS,
168688dbf8287f831d02e8d5023be4f9b42ca224fb75Theodore Ts'o				is.max_dirs, is.max_dirs);
168788dbf8287f831d02e8d5023be4f9b42ca224fb75Theodore Ts'o
16883b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'oerrout:
1689a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	ext2fs_free_extent_table(rfs->imap);
1690a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	rfs->imap = 0;
1691a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	return retval;
1692a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o}
1693a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1694a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1695a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* --------------------------------------------------------------------
1696a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o *
1697a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Resize processing, phase 5.
1698a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o *
1699a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * In this phase we actually move the inode table around, and then
1700a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * update the summary statistics.  This is scary, since aborting here
1701a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * will potentially scramble the filesystem.  (We are moving the
1702a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * inode tables around in place, and so the potential for lost data,
1703a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * or at the very least scrambling the mapping between filenames and
1704a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * inode numbers is very high in case of a power failure here.)
1705a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * --------------------------------------------------------------------
1706a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */
1707a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
170824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
170924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o/*
1710052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * A very scary routine --- this one moves the inode table around!!!
1711052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o *
1712052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * After this you have to use the rfs->new_fs file handle to read and
1713052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * write inodes.
1714052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o */
1715c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'ostatic errcode_t move_itables(ext2_resize_t rfs)
1716052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o{
1717e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	int		n, num, size;
1718e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	long long	diff;
1719544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	dgrp_t		i, max_groups;
1720052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	ext2_filsys	fs = rfs->new_fs;
172105e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o	char		*cp;
1722e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t		old_blk, new_blk, blk;
1723a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	errcode_t	retval;
172464ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o	int		j, to_move, moved;
1725052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o
17261333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o	max_groups = fs->group_desc_count;
17271333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o	if (max_groups > rfs->old_fs->group_desc_count)
17281333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o		max_groups = rfs->old_fs->group_desc_count;
1729052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o
173005e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o	size = fs->blocksize * fs->inode_blocks_per_group;
173105e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o	if (!rfs->itable_buf) {
1732c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o		retval = ext2fs_get_mem(size, &rfs->itable_buf);
1733ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o		if (retval)
1734ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o			return retval;
173505e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o	}
1736c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o
1737c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	/*
1738c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	 * Figure out how many inode tables we need to move
1739c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	 */
1740c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	to_move = moved = 0;
17411333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o	for (i=0; i < max_groups; i++)
1742e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (ext2fs_inode_table_loc(rfs->old_fs, i) !=
1743e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		    ext2fs_inode_table_loc(fs, i))
1744c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o			to_move++;
1745c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o
1746c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	if (to_move == 0)
1747c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		return 0;
1748c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o
17493b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o	if (rfs->progress) {
17503b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		retval = rfs->progress(rfs, E2_RSZ_MOVE_ITABLE_PASS,
17513b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o				       0, to_move);
17523b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		if (retval)
17533b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o			goto errout;
17543b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o	}
175563b44fbe303ea00118cbe24cbbcde351a9bc0aacTheodore Ts'o
1756a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	rfs->old_fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
1757a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
17581333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o	for (i=0; i < max_groups; i++) {
1759e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		old_blk = ext2fs_inode_table_loc(rfs->old_fs, i);
1760e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		new_blk = ext2fs_inode_table_loc(fs, i);
1761ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o		diff = new_blk - old_blk;
1762efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
176380c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#ifdef RESIZE2FS_DEBUG
1764efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE)
1765e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			printf("Itable move group %d block %llu->%llu (diff %lld)\n",
1766ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o			       i, old_blk, new_blk, diff);
176780c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#endif
1768efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
176905e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o		if (!diff)
1770052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o			continue;
1771052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o
1772e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		retval = io_channel_read_blk64(fs->io, old_blk,
1773e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					       fs->inode_blocks_per_group,
1774e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					       rfs->itable_buf);
1775efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		if (retval)
1776a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			goto errout;
177705e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o		/*
177805e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o		 * The end of the inode table segment often contains
1779a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		 * all zeros, and we're often only moving the inode
1780a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		 * table down a block or two.  If so, we can optimize
1781a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		 * things by not rewriting blocks that we know to be zero
1782a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		 * already.
178305e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o		 */
17842787276ec59e1d52087d307bc30446d088ec65bcTheodore Ts'o		for (cp = rfs->itable_buf+size-1, n=0; n < size; n++, cp--)
178505e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o			if (*cp)
178605e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o				break;
178705e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o		n = n >> EXT2_BLOCK_SIZE_BITS(fs->super);
178880c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#ifdef RESIZE2FS_DEBUG
1789efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE)
1790f35fd3d5eeb3e35660ea87adbc170978c3cdf9e3Theodore Ts'o			printf("%d blocks of zeros...\n", n);
179180c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#endif
179205e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o		num = fs->inode_blocks_per_group;
179305e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o		if (n > diff)
179405e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o			num -= n;
179505e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o
1796e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		retval = io_channel_write_blk64(fs->io, new_blk,
1797e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall						num, rfs->itable_buf);
1798052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		if (retval) {
1799e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			io_channel_write_blk64(fs->io, old_blk,
1800e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					       num, rfs->itable_buf);
1801a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			goto errout;
1802052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		}
180305e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o		if (n > diff) {
1804e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			retval = io_channel_write_blk64(fs->io,
1805ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o			      old_blk + fs->inode_blocks_per_group,
1806a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			      diff, (rfs->itable_buf +
1807a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				     (fs->inode_blocks_per_group - diff) *
1808a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				     fs->blocksize));
180905e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o			if (retval)
1810a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				goto errout;
1811c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		}
181264ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o
1813e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		for (blk = ext2fs_inode_table_loc(rfs->old_fs, i), j=0;
181464ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o		     j < fs->inode_blocks_per_group ; j++, blk++)
1815e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_block_alloc_stats2(fs, blk, -1);
181664ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o
1817e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_inode_table_loc_set(rfs->old_fs, i, new_blk);
1818236efede1922fa173b3c2f20d9e0886856664ab4Jose R. Santos		ext2fs_group_desc_csum_set(rfs->old_fs, i);
1819a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		ext2fs_mark_super_dirty(rfs->old_fs);
182064ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o		ext2fs_flush(rfs->old_fs);
182164ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o
1822a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (rfs->progress) {
18233b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o			retval = rfs->progress(rfs, E2_RSZ_MOVE_ITABLE_PASS,
18243b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o					       ++moved, to_move);
18253b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o			if (retval)
18263b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o				goto errout;
1827a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		}
1828052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	}
182964ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o	mark_table_blocks(fs, fs->block_map);
1830a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	ext2fs_flush(fs);
183180c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#ifdef RESIZE2FS_DEBUG
1832efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE)
1833f35fd3d5eeb3e35660ea87adbc170978c3cdf9e3Theodore Ts'o		printf("Inode table move finished.\n");
183480c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#endif
1835052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	return 0;
1836efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
1837a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'oerrout:
1838052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	return retval;
1839052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o}
1840052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o
1841052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o/*
1842efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * Fix the resize inode
18439213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o */
18449213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'ostatic errcode_t fix_resize_inode(ext2_filsys fs)
18459213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o{
18469213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	struct ext2_inode	inode;
18479213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	errcode_t		retval;
1848e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	char			*block_buf = NULL;
18499213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
1850efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	if (!(fs->super->s_feature_compat &
18519213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	      EXT2_FEATURE_COMPAT_RESIZE_INODE))
18529213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		return 0;
18539213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
18549213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	retval = ext2fs_get_mem(fs->blocksize, &block_buf);
18559213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	if (retval) goto errout;
18569213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
18579213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
18589213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	if (retval) goto errout;
18599213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
18601ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o	ext2fs_iblk_set(fs, &inode, 1);
18619213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
18629213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	retval = ext2fs_write_inode(fs, EXT2_RESIZE_INO, &inode);
18639213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	if (retval) goto errout;
18649213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
18659213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	if (!inode.i_block[EXT2_DIND_BLOCK]) {
1866efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		/*
18679213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		 * Avoid zeroing out block #0; that's rude.  This
18689213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		 * should never happen anyway since the filesystem
18699213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		 * should be fsck'ed and we assume it is consistent.
18709213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		 */
1871e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		fprintf(stderr, "%s",
1872f35fd3d5eeb3e35660ea87adbc170978c3cdf9e3Theodore Ts'o			_("Should never happen: resize inode corrupt!\n"));
18739213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		exit(1);
18749213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	}
18759213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
18769213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	memset(block_buf, 0, fs->blocksize);
18779213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
1878e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	retval = io_channel_write_blk64(fs->io, inode.i_block[EXT2_DIND_BLOCK],
1879e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					1, block_buf);
18809213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	if (retval) goto errout;
1881efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
18829213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	retval = ext2fs_create_resize_inode(fs);
18839213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	if (retval)
18849213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		goto errout;
18859213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
18869213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'oerrout:
18879213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	if (block_buf)
18889213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		ext2fs_free_mem(&block_buf);
18899213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	return retval;
18909213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o}
18919213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
18929213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o/*
1893052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * Finally, recalculate the summary information
1894052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o */
1895052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'ostatic errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs)
1896052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o{
1897e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t		blk;
1898dfcdc32f8d6623a35a9e66f503c535e4081b7266Theodore Ts'o	ext2_ino_t	ino;
1899544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	unsigned int	group = 0;
1900544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	unsigned int	count = 0;
1901e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t		total_blocks_free = 0;
1902e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	int		total_inodes_free = 0;
1903dfcdc32f8d6623a35a9e66f503c535e4081b7266Theodore Ts'o	int		group_free = 0;
190474128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o	int		uninit = 0;
1905e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t		super_blk, old_desc_blk, new_desc_blk;
190674128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o	int		old_desc_blocks;
1907052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o
1908052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	/*
1909052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	 * First calculate the block statistics
1910052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	 */
1911e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT);
1912e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	ext2fs_super_and_bgd_loc2(fs, group, &super_blk, &old_desc_blk,
1913e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				  &new_desc_blk, 0);
191474128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
191574128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o		old_desc_blocks = fs->super->s_first_meta_bg;
191674128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o	else
191774128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o		old_desc_blocks = fs->desc_blocks +
191874128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o			fs->super->s_reserved_gdt_blocks;
1919e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	for (blk = B2C(fs->super->s_first_data_block);
1920e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	     blk < ext2fs_blocks_count(fs->super);
1921e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	     blk += EXT2FS_CLUSTER_RATIO(fs)) {
192274128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o		if ((uninit &&
1923e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		     !(EQ_CLSTR(blk, super_blk) ||
192474128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o		       ((old_desc_blk && old_desc_blocks &&
1925e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			 GE_CLSTR(blk, old_desc_blk) &&
1926e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			 LT_CLSTR(blk, old_desc_blk + old_desc_blocks))) ||
1927e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		       ((new_desc_blk && EQ_CLSTR(blk, new_desc_blk))) ||
1928e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		       EQ_CLSTR(blk, ext2fs_block_bitmap_loc(fs, group)) ||
1929e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		       EQ_CLSTR(blk, ext2fs_inode_bitmap_loc(fs, group)) ||
1930e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		       ((GE_CLSTR(blk, ext2fs_inode_table_loc(fs, group)) &&
1931e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			 LT_CLSTR(blk, ext2fs_inode_table_loc(fs, group)
1932e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				  + fs->inode_blocks_per_group))))) ||
1933e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		    (!ext2fs_fast_test_block_bitmap2(fs->block_map, blk))) {
1934052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o			group_free++;
1935e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			total_blocks_free++;
1936052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		}
1937052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		count++;
1938e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if ((count == fs->super->s_clusters_per_group) ||
1939e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		    EQ_CLSTR(blk, ext2fs_blocks_count(fs->super)-1)) {
1940e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_bg_free_blocks_count_set(fs, group, group_free);
1941236efede1922fa173b3c2f20d9e0886856664ab4Jose R. Santos			ext2fs_group_desc_csum_set(fs, group);
1942236efede1922fa173b3c2f20d9e0886856664ab4Jose R. Santos			group++;
19434828bbe9e7380da0d9153109ab290e88b5d53bf5Theodore Ts'o			if (group >= fs->group_desc_count)
19444828bbe9e7380da0d9153109ab290e88b5d53bf5Theodore Ts'o				break;
1945052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o			count = 0;
1946052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o			group_free = 0;
1947e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT);
1948e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_super_and_bgd_loc2(fs, group, &super_blk,
1949e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall						  &old_desc_blk,
1950e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall						  &new_desc_blk, 0);
195174128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o			if (fs->super->s_feature_incompat &
195274128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o			    EXT2_FEATURE_INCOMPAT_META_BG)
195374128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o				old_desc_blocks = fs->super->s_first_meta_bg;
195474128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o			else
195574128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o				old_desc_blocks = fs->desc_blocks +
195674128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o					fs->super->s_reserved_gdt_blocks;
1957052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		}
1958052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	}
1959e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	total_blocks_free = C2B(total_blocks_free);
1960e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	ext2fs_free_blocks_count_set(fs->super, total_blocks_free);
1961efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
1962052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	/*
1963052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	 * Next, calculate the inode statistics
1964052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	 */
1965052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	group_free = 0;
1966052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	count = 0;
1967052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	group = 0;
19685830d6be9c33e23bb20c339036083e6e4fa6795eEric Sandeen
19695830d6be9c33e23bb20c339036083e6e4fa6795eEric Sandeen	/* Protect loop from wrap-around if s_inodes_count maxed */
1970e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT);
19715830d6be9c33e23bb20c339036083e6e4fa6795eEric Sandeen	for (ino = 1; ino <= fs->super->s_inodes_count && ino > 0; ino++) {
197274128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o		if (uninit ||
1973e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		    !ext2fs_fast_test_inode_bitmap2(fs->inode_map, ino)) {
1974052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o			group_free++;
1975e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			total_inodes_free++;
1976052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		}
1977052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		count++;
1978052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		if ((count == fs->super->s_inodes_per_group) ||
1979052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		    (ino == fs->super->s_inodes_count)) {
1980e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_bg_free_inodes_count_set(fs, group, group_free);
1981236efede1922fa173b3c2f20d9e0886856664ab4Jose R. Santos			ext2fs_group_desc_csum_set(fs, group);
1982236efede1922fa173b3c2f20d9e0886856664ab4Jose R. Santos			group++;
19834828bbe9e7380da0d9153109ab290e88b5d53bf5Theodore Ts'o			if (group >= fs->group_desc_count)
19844828bbe9e7380da0d9153109ab290e88b5d53bf5Theodore Ts'o				break;
1985052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o			count = 0;
1986052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o			group_free = 0;
1987e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT);
1988052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		}
1989052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	}
1990e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	fs->super->s_free_inodes_count = total_inodes_free;
1991052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	ext2fs_mark_super_dirty(fs);
1992052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	return 0;
1993052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o}
1994199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik
1995199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik/*
19968a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen *  Journal may have been relocated; update the backup journal blocks
19978a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen *  in the superblock.
19988a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen */
19998a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeenstatic errcode_t fix_sb_journal_backup(ext2_filsys fs)
20008a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen{
20018a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen	errcode_t	  retval;
20028a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen	struct ext2_inode inode;
20038a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen
20048a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen	if (!(fs->super->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
20058a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen		return 0;
20068a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen
2007d93d5bbf605f81eb13fa71a55dfbed06f88fe930Eric Sandeen	/* External journal? Nothing to do. */
2008d93d5bbf605f81eb13fa71a55dfbed06f88fe930Eric Sandeen	if (fs->super->s_journal_dev && !fs->super->s_journal_inum)
2009d93d5bbf605f81eb13fa71a55dfbed06f88fe930Eric Sandeen		return 0;
2010d93d5bbf605f81eb13fa71a55dfbed06f88fe930Eric Sandeen
20118a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen	retval = ext2fs_read_inode(fs, fs->super->s_journal_inum, &inode);
20128a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen	if (retval)
20138a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen		return retval;
20148a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen	memcpy(fs->super->s_jnl_blocks, inode.i_block, EXT2_N_BLOCKS*4);
2015e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	fs->super->s_jnl_blocks[15] = inode.i_size_high;
20168a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen	fs->super->s_jnl_blocks[16] = inode.i_size;
20178a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen	fs->super->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
20188a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen	ext2fs_mark_super_dirty(fs);
20198a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen	return 0;
20208a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen}
20218a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen
2022e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int calc_group_overhead(ext2_filsys fs, blk64_t grp,
2023e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			       int old_desc_blocks)
2024e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{
2025e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t	super_blk, old_desc_blk, new_desc_blk;
2026e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	int overhead;
2027e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
2028e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	/* inode table blocks plus allocation bitmaps */
2029e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	overhead = fs->inode_blocks_per_group + 2;
2030e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
2031e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	ext2fs_super_and_bgd_loc2(fs, grp, &super_blk,
2032e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				  &old_desc_blk, &new_desc_blk, 0);
2033e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if ((grp == 0) || super_blk)
2034e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		overhead++;
2035e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (old_desc_blk)
2036e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		overhead += old_desc_blocks;
2037e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	else if (new_desc_blk)
2038e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		overhead++;
2039e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	return overhead;
2040e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}
2041e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
2042e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
20438a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen/*
2044199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik * calcluate the minimum number of blocks the given fs can be resized to
2045199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik */
2046e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallblk64_t calculate_minimum_resize_size(ext2_filsys fs, int flags)
2047199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik{
2048e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	ext2_ino_t inode_count;
2049e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	dgrp_t groups;
2050e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t blks_needed, data_blocks;
2051e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t grp, data_needed, last_start;
2052e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t overhead = 0;
2053e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	int old_desc_blocks;
20542884d208a37fe8813267198a247694bc90b00f96Peng Tao	int extra_groups = 0;
20552884d208a37fe8813267198a247694bc90b00f96Peng Tao	int flexbg_size = 1 << fs->super->s_log_groups_per_flex;
2056199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik
2057199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	/*
2058199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	 * first figure out how many group descriptors we need to
2059199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	 * handle the number of inodes we have
2060199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	 */
2061199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	inode_count = fs->super->s_inodes_count -
2062199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik		fs->super->s_free_inodes_count;
2063199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	blks_needed = ext2fs_div_ceil(inode_count,
2064199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik				      fs->super->s_inodes_per_group) *
2065199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik		EXT2_BLOCKS_PER_GROUP(fs->super);
2066e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	groups = ext2fs_div64_ceil(blks_needed,
2067e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				   EXT2_BLOCKS_PER_GROUP(fs->super));
2068e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifdef RESIZE2FS_DEBUG
2069e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (flags & RESIZE_DEBUG_MIN_CALC)
2070e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		printf("fs has %d inodes, %d groups required.\n",
2071e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		       inode_count, groups);
2072e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif
2073199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik
2074199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	/*
2075e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 * number of old-style block group descriptor blocks
2076199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	 */
2077e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
2078e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		old_desc_blocks = fs->super->s_first_meta_bg;
2079e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	else
2080e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		old_desc_blocks = fs->desc_blocks +
2081e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			fs->super->s_reserved_gdt_blocks;
2082199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik
2083199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	/* calculate how many blocks are needed for data */
2084e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	data_needed = ext2fs_blocks_count(fs->super) -
2085e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_free_blocks_count(fs->super);
2086199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik
2087e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	for (grp = 0; grp < fs->group_desc_count; grp++)
2088e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		data_needed -= calc_group_overhead(fs, grp, old_desc_blocks);
2089e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifdef RESIZE2FS_DEBUG
2090e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (flags & RESIZE_DEBUG_MIN_CALC)
2091e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		printf("fs requires %llu data blocks.\n", data_needed);
2092e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif
2093e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
2094e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	/*
2095e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 * For ext4 we need to allow for up to a flex_bg worth of
2096e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 * inode tables of slack space so the resize operation can be
2097e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 * guaranteed to finish.
2098e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 */
2099c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o	if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) {
2100c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o		extra_groups = flexbg_size - (groups & (flexbg_size - 1));
2101e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		data_needed += fs->inode_blocks_per_group * extra_groups;
21022884d208a37fe8813267198a247694bc90b00f96Peng Tao		extra_groups = groups % flexbg_size;
2103c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o	}
2104c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o
2105199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	/*
2106199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	 * figure out how many data blocks we have given the number of groups
2107199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	 * we need for our inodes
2108199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	 */
2109199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	data_blocks = groups * EXT2_BLOCKS_PER_GROUP(fs->super);
2110199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	last_start = 0;
2111199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	for (grp = 0; grp < groups; grp++) {
2112e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		overhead = calc_group_overhead(fs, grp, old_desc_blocks);
2113199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik
2114199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik		/*
2115199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik		 * we want to keep track of how much data we can store in
2116199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik		 * the groups leading up to the last group so we can determine
2117199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik		 * how big the last group needs to be
2118199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik		 */
2119199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik		if (grp != (groups - 1))
2120199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik			last_start += EXT2_BLOCKS_PER_GROUP(fs->super) -
2121199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik				overhead;
2122199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik
2123199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik		data_blocks -= overhead;
2124199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	}
2125e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifdef RESIZE2FS_DEBUG
2126e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (flags & RESIZE_DEBUG_MIN_CALC)
2127e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		printf("With %d group(s), we have %llu blocks available.\n",
2128e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		       groups, data_blocks);
2129e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif
2130199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik
2131199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	/*
2132199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	 * if we need more group descriptors in order to accomodate our data
2133199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	 * then we need to add them here
2134199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	 */
2135199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	while (data_needed > data_blocks) {
2136e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		blk64_t remainder = data_needed - data_blocks;
2137e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		dgrp_t extra_grps;
2138199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik
2139199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik		/* figure out how many more groups we need for the data */
2140e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		extra_grps = ext2fs_div64_ceil(remainder,
2141e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					       EXT2_BLOCKS_PER_GROUP(fs->super));
2142199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik
2143199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik		data_blocks += extra_grps * EXT2_BLOCKS_PER_GROUP(fs->super);
2144199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik
2145199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik		/* ok we have to account for the last group */
2146e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		overhead = calc_group_overhead(fs, groups-1, old_desc_blocks);
2147199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik		last_start += EXT2_BLOCKS_PER_GROUP(fs->super) - overhead;
2148199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik
2149199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik		for (grp = groups; grp < groups+extra_grps; grp++) {
2150e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			overhead = calc_group_overhead(fs, grp,
2151e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall						       old_desc_blocks);
2152199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik
2153199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik			/*
2154199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik			 * again, we need to see how much data we cram into
2155199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik			 * all of the groups leading up to the last group
2156199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik			 */
2157199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik			if (grp != (groups + extra_grps - 1))
2158199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik				last_start += EXT2_BLOCKS_PER_GROUP(fs->super)
2159199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik					- overhead;
2160199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik
2161199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik			data_blocks -= overhead;
2162199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik		}
2163199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik
2164199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik		groups += extra_grps;
21652884d208a37fe8813267198a247694bc90b00f96Peng Tao		extra_groups += extra_grps;
21662884d208a37fe8813267198a247694bc90b00f96Peng Tao		if (fs->super->s_feature_incompat
21672884d208a37fe8813267198a247694bc90b00f96Peng Tao			& EXT4_FEATURE_INCOMPAT_FLEX_BG
21682884d208a37fe8813267198a247694bc90b00f96Peng Tao		    && extra_groups > flexbg_size) {
21692884d208a37fe8813267198a247694bc90b00f96Peng Tao			/*
21702884d208a37fe8813267198a247694bc90b00f96Peng Tao			 * For ext4 we need to allow for up to a flex_bg worth
21712884d208a37fe8813267198a247694bc90b00f96Peng Tao			 * of inode tables of slack space so the resize
21722884d208a37fe8813267198a247694bc90b00f96Peng Tao			 * operation can be guaranteed to finish.
21732884d208a37fe8813267198a247694bc90b00f96Peng Tao			 */
21742884d208a37fe8813267198a247694bc90b00f96Peng Tao			extra_groups = flexbg_size -
21752884d208a37fe8813267198a247694bc90b00f96Peng Tao						(groups & (flexbg_size - 1));
2176e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			data_needed += (fs->inode_blocks_per_group *
2177e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					extra_groups);
21782884d208a37fe8813267198a247694bc90b00f96Peng Tao			extra_groups = groups % flexbg_size;
21792884d208a37fe8813267198a247694bc90b00f96Peng Tao		}
2180e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifdef RESIZE2FS_DEBUG
2181e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (flags & RESIZE_DEBUG_MIN_CALC)
2182e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			printf("Added %d extra group(s), "
2183e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			       "data_needed %llu, data_blocks %llu, "
2184e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			       "last_start %llu\n",
2185e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			       extra_grps, data_needed, data_blocks,
2186e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			       last_start);
2187e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif
2188199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	}
2189199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik
2190199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	/* now for the fun voodoo */
2191e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	overhead = calc_group_overhead(fs, groups-1, old_desc_blocks);
2192e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifdef RESIZE2FS_DEBUG
2193e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (flags & RESIZE_DEBUG_MIN_CALC)
2194e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		printf("Last group's overhead is %llu\n", overhead);
2195e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif
2196199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik
2197199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	/*
2198199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	 * if this is the case then the last group is going to have data in it
2199199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	 * so we need to adjust the size of the last group accordingly
2200199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	 */
2201199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	if (last_start < data_needed) {
2202e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		blk64_t remainder = data_needed - last_start;
2203199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik
2204e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifdef RESIZE2FS_DEBUG
2205e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (flags & RESIZE_DEBUG_MIN_CALC)
2206e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			printf("Need %llu data blocks in last group\n",
2207e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			       remainder);
2208e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif
2209199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik		/*
2210199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik		 * 50 is a magic number that mkfs/resize uses to see if its
2211199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik		 * even worth making/resizing the fs.  basically you need to
2212199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik		 * have at least 50 blocks in addition to the blocks needed
2213199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik		 * for the metadata in the last group
2214199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik		 */
2215199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik		if (remainder > 50)
2216199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik			overhead += remainder;
2217199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik		else
2218199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik			overhead += 50;
2219199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	} else
2220199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik		overhead += 50;
2221199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik
2222e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	overhead += fs->super->s_first_data_block;
2223e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifdef RESIZE2FS_DEBUG
2224e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (flags & RESIZE_DEBUG_MIN_CALC)
2225e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		printf("Final size of last group is %lld\n", overhead);
2226e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif
2227199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik
2228199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	/*
2229199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	 * since our last group doesn't have to be BLOCKS_PER_GROUP large, we
2230199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	 * only do groups-1, and then add the number of blocks needed to
2231199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	 * handle the group descriptor metadata+data that we need
2232199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	 */
2233199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	blks_needed = (groups-1) * EXT2_BLOCKS_PER_GROUP(fs->super);
2234199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	blks_needed += overhead;
2235199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik
22362215293c7e85c88d2fbc06f9e9438fca9a25213cTheodore Ts'o	/*
2237e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 * Make sure blks_needed covers the end of the inode table in
2238e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 * the last block group.
2239e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 */
2240e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	overhead = ext2fs_inode_table_loc(fs, groups-1) +
2241e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		fs->inode_blocks_per_group;
2242e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (blks_needed < overhead)
2243e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		blks_needed = overhead;
2244e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
2245e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifdef RESIZE2FS_DEBUG
2246e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (flags & RESIZE_DEBUG_MIN_CALC)
2247e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		printf("Estimated blocks needed: %llu\n", blks_needed);
2248e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif
2249e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
2250e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	/*
225169f7c80eaf25a642b0eb85f4557605c89acd80b6Eric Sandeen	 * If at this point we've already added up more "needed" than
225269f7c80eaf25a642b0eb85f4557605c89acd80b6Eric Sandeen	 * the current size, just return current size as minimum.
225369f7c80eaf25a642b0eb85f4557605c89acd80b6Eric Sandeen	 */
2254e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (blks_needed >= ext2fs_blocks_count(fs->super))
2255e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		return ext2fs_blocks_count(fs->super);
225669f7c80eaf25a642b0eb85f4557605c89acd80b6Eric Sandeen	/*
2257793a04a0719d5688a0033e4bda3cf267f57ea760Theodore Ts'o	 * We need to reserve a few extra blocks if extents are
2258793a04a0719d5688a0033e4bda3cf267f57ea760Theodore Ts'o	 * enabled, in case we need to grow the extent tree.  The more
2259793a04a0719d5688a0033e4bda3cf267f57ea760Theodore Ts'o	 * we shrink the file system, the more space we need.
2260793a04a0719d5688a0033e4bda3cf267f57ea760Theodore Ts'o	 */
2261e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) {
2262e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		blk64_t safe_margin = (ext2fs_blocks_count(fs->super) -
2263e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				       blks_needed)/500;
2264e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifdef RESIZE2FS_DEBUG
2265e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (flags & RESIZE_DEBUG_MIN_CALC)
2266e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			printf("Extents safety margin: %llu\n", safe_margin);
2267e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif
2268e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		blks_needed += safe_margin;
2269e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	}
2270793a04a0719d5688a0033e4bda3cf267f57ea760Theodore Ts'o
2271199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik	return blks_needed;
2272199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik}
2273