resize2fs.c revision d1b4b85c3a201705c5d3d2916c7a9ca00a04e44c
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
824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore 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
43a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t adjust_superblock(ext2_resize_t rfs, blk_t new_size);
44a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t blocks_to_move(ext2_resize_t rfs);
45a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t block_mover(ext2_resize_t rfs);
46a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t inode_scan_and_fix(ext2_resize_t rfs);
47a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t inode_ref_fix(ext2_resize_t rfs);
48a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t move_itables(ext2_resize_t rfs);
499213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'ostatic errcode_t fix_resize_inode(ext2_filsys fs);
50a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs);
51a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
52a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/*
53a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Some helper CPP macros
54a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */
55a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define FS_BLOCK_BM(fs, i) ((fs)->group_desc[(i)].bg_block_bitmap)
56a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define FS_INODE_BM(fs, i) ((fs)->group_desc[(i)].bg_inode_bitmap)
57a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define FS_INODE_TB(fs, i) ((fs)->group_desc[(i)].bg_inode_table)
58a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
59a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define IS_BLOCK_BM(fs, i, blk) ((blk) == FS_BLOCK_BM((fs),(i)))
60a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define IS_INODE_BM(fs, i, blk) ((blk) == FS_INODE_BM((fs),(i)))
61a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
62a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define IS_INODE_TB(fs, i, blk) (((blk) >= FS_INODE_TB((fs), (i))) && \
63a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				 ((blk) < (FS_INODE_TB((fs), (i)) + \
64a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o					   (fs)->inode_blocks_per_group)))
65a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
66a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
67a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
68a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/*
69a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * This is the top-level routine which does the dirty deed....
70a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */
71116db1b513f6901415d1f5f8c01fc297d7cc64a4Theodore Ts'oerrcode_t resize_fs(ext2_filsys fs, blk_t *new_size, int flags,
723b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		    errcode_t (*progress)(ext2_resize_t rfs, int pass,
73a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				     unsigned long cur,
741333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o				     unsigned long max_val))
75a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{
76a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	ext2_resize_t	rfs;
77a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	errcode_t	retval;
78a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
79a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	retval = ext2fs_read_bitmaps(fs);
80a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval)
81a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		return retval;
82a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
83a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	/*
84a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 * Create the data structure
85a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 */
86c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o	retval = ext2fs_get_mem(sizeof(struct ext2_resize_struct), &rfs);
87a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval)
88a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		return retval;
89a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	memset(rfs, 0, sizeof(struct ext2_resize_struct));
90a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
91a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	rfs->old_fs = fs;
92a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	rfs->flags = flags;
93a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	rfs->itable_buf	 = 0;
94a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	rfs->progress = progress;
95a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	retval = ext2fs_dup_handle(fs, &rfs->new_fs);
96a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval)
97a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		goto errout;
98a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
99116db1b513f6901415d1f5f8c01fc297d7cc64a4Theodore Ts'o	retval = adjust_superblock(rfs, *new_size);
100a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval)
101a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		goto errout;
102a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
103116db1b513f6901415d1f5f8c01fc297d7cc64a4Theodore Ts'o	*new_size = rfs->new_fs->super->s_blocks_count;
104116db1b513f6901415d1f5f8c01fc297d7cc64a4Theodore Ts'o
105a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	retval = blocks_to_move(rfs);
106a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval)
107a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		goto errout;
108a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
109a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG
110a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (rfs->flags & RESIZE_DEBUG_BMOVE)
1118deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato		printf("Number of free blocks: %u/%u, Needed: %d\n",
112a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		       rfs->old_fs->super->s_free_blocks_count,
113a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		       rfs->new_fs->super->s_free_blocks_count,
114a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		       rfs->needed_blocks);
115a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif
116a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
117a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	retval = block_mover(rfs);
118a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval)
119a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		goto errout;
120a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
121a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	retval = inode_scan_and_fix(rfs);
122a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval)
123a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		goto errout;
124a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
125a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	retval = inode_ref_fix(rfs);
126a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval)
127a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		goto errout;
128a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
129a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	retval = move_itables(rfs);
130a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval)
131a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		goto errout;
132a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
13364ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o	retval = ext2fs_calculate_summary_stats(rfs->new_fs);
13464ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o	if (retval)
13564ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o		goto errout;
13664ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o
1379213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	retval = fix_resize_inode(rfs->new_fs);
1389213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	if (retval)
1399213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		goto errout;
1409213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
141a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	retval = ext2fs_close(rfs->new_fs);
142a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval)
143a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		goto errout;
144a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
145a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	rfs->flags = flags;
146a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
147a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	ext2fs_free(rfs->old_fs);
148a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (rfs->itable_buf)
149c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o		ext2fs_free_mem(&rfs->itable_buf);
150c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o	ext2fs_free_mem(&rfs);
151a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
152a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	return 0;
153a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
154a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'oerrout:
155a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (rfs->new_fs)
156a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		ext2fs_free(rfs->new_fs);
157a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (rfs->itable_buf)
158c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o		ext2fs_free_mem(&rfs->itable_buf);
159c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o	ext2fs_free_mem(&rfs);
160a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	return retval;
161a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o}
162a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
163a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* --------------------------------------------------------------------
164a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o *
165a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Resize processing, phase 1.
166a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o *
167a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * In this phase we adjust the in-memory superblock information, and
168a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * initialize any new parts of the inode table.  The new parts of the
169a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * inode table are created in virgin disk space, so we can abort here
170a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * without any side effects.
171a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * --------------------------------------------------------------------
172a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */
173a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
17424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o/*
175bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o * This routine is shared by the online and offline resize routines.
176bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o * All of the information which is adjusted in memory is done here.
17724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */
178bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'oerrcode_t adjust_fs_info(ext2_filsys fs, ext2_filsys old_fs, blk_t new_size)
17924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o{
18024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	errcode_t	retval;
181bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	int		overhead = 0;
182bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	int		rem;
18324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	blk_t		blk, group_block;
184bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	ext2_ino_t	real_end;
185bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	int		adj, old_numblocks, numblocks, adjblocks;
186bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	unsigned long	i, j, old_desc_blocks, max_group;
187544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	unsigned int	meta_bg, meta_bg_size;
188544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	int		has_super;
189f335864338a6fbce8134a445ffdd0cdeb3f3f1bcEric Sandeen	__u64		new_inodes;	/* u64 to check for overflow */
190bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o
19124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	fs->super->s_blocks_count = new_size;
19224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
19324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'oretry:
19469022e029f3273b3b860bf701219cd3fe615f76bTheodore Ts'o	fs->group_desc_count = ext2fs_div_ceil(fs->super->s_blocks_count -
19569022e029f3273b3b860bf701219cd3fe615f76bTheodore Ts'o				       fs->super->s_first_data_block,
19669022e029f3273b3b860bf701219cd3fe615f76bTheodore Ts'o				       EXT2_BLOCKS_PER_GROUP(fs->super));
19724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	if (fs->group_desc_count == 0)
19824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o		return EXT2_ET_TOOSMALL;
19969022e029f3273b3b860bf701219cd3fe615f76bTheodore Ts'o	fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count,
20069022e029f3273b3b860bf701219cd3fe615f76bTheodore Ts'o					  EXT2_DESC_PER_BLOCK(fs->super));
20124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
20224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	/*
20324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * Overhead is the number of bookkeeping blocks per group.  It
20424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * includes the superblock backup, the group descriptor
20524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * backups, the inode bitmap, the block bitmap, and the inode
20624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * table.
20724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 */
2089213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	overhead = (int) (2 + fs->inode_blocks_per_group);
2099213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
2109213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	if (ext2fs_bg_has_super(fs, fs->group_desc_count - 1))
2119213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		overhead += 1 + fs->desc_blocks +
2129213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o			fs->super->s_reserved_gdt_blocks;
2139213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
21424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	/*
21524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * See if the last group is big enough to support the
21624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * necessary data structures.  If not, we need to get rid of
21724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * it.
21824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 */
21924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	rem = (fs->super->s_blocks_count - fs->super->s_first_data_block) %
22024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o		fs->super->s_blocks_per_group;
22124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	if ((fs->group_desc_count == 1) && rem && (rem < overhead))
22224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o		return EXT2_ET_TOOSMALL;
22324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	if (rem && (rem < overhead+50)) {
22424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o		fs->super->s_blocks_count -= rem;
22524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o		goto retry;
22624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	}
22724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	/*
22824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * Adjust the number of inodes
22924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 */
230f335864338a6fbce8134a445ffdd0cdeb3f3f1bcEric Sandeen	new_inodes =(__u64)fs->super->s_inodes_per_group * fs->group_desc_count;
231f335864338a6fbce8134a445ffdd0cdeb3f3f1bcEric Sandeen	if (new_inodes > ~0U) {
232f335864338a6fbce8134a445ffdd0cdeb3f3f1bcEric Sandeen		fprintf(stderr, _("inodes (%llu) must be less than %u"),
233f335864338a6fbce8134a445ffdd0cdeb3f3f1bcEric Sandeen				   new_inodes, ~0U);
234f335864338a6fbce8134a445ffdd0cdeb3f3f1bcEric Sandeen		return EXT2_ET_TOO_MANY_INODES;
235f335864338a6fbce8134a445ffdd0cdeb3f3f1bcEric Sandeen	}
23624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	fs->super->s_inodes_count = fs->super->s_inodes_per_group *
23724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o		fs->group_desc_count;
23824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
23924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	/*
24024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * Adjust the number of free blocks
24124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 */
242bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	blk = old_fs->super->s_blocks_count;
24324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	if (blk > fs->super->s_blocks_count)
24424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o		fs->super->s_free_blocks_count -=
24524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o			(blk - fs->super->s_blocks_count);
24624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	else
24724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o		fs->super->s_free_blocks_count +=
24824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o			(fs->super->s_blocks_count - blk);
24924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
25024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	/*
251c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	 * Adjust the number of reserved blocks
252c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	 */
253d1b4b85c3a201705c5d3d2916c7a9ca00a04e44cEric Sandeen	blk = (__u64)old_fs->super->s_r_blocks_count * 100 /
254bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		old_fs->super->s_blocks_count;
255a8862d9e90d0d94761ba28dbbf9674308fd7d7c0Theodore Ts'o	fs->super->s_r_blocks_count = e2p_percent(blk,
256a8862d9e90d0d94761ba28dbbf9674308fd7d7c0Theodore Ts'o						  fs->super->s_blocks_count);
257c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o
258c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	/*
25924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * Adjust the bitmaps for size
26024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 */
26124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	retval = ext2fs_resize_inode_bitmap(fs->super->s_inodes_count,
26224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o					    fs->super->s_inodes_count,
26324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o					    fs->inode_map);
264c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	if (retval) goto errout;
26524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
26624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	real_end = ((EXT2_BLOCKS_PER_GROUP(fs->super)
26724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o		     * fs->group_desc_count)) - 1 +
26824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o			     fs->super->s_first_data_block;
26924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	retval = ext2fs_resize_block_bitmap(fs->super->s_blocks_count-1,
27024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o					    real_end, fs->block_map);
27124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
272c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	if (retval) goto errout;
27324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
27424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	/*
27524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * Reallocate the group descriptors as necessary.
27624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 */
277bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	if (old_fs->desc_blocks != fs->desc_blocks) {
278bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		retval = ext2fs_resize_mem(old_fs->desc_blocks *
27976f875daa1c9c2cdc72f0c6f0f7be4bbc7f0fc07Theodore Ts'o					   fs->blocksize,
28076f875daa1c9c2cdc72f0c6f0f7be4bbc7f0fc07Theodore Ts'o					   fs->desc_blocks * fs->blocksize,
281c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o					   &fs->group_desc);
282ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o		if (retval)
283a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			goto errout;
284bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		if (fs->desc_blocks > old_fs->desc_blocks)
2852787276ec59e1d52087d307bc30446d088ec65bcTheodore Ts'o			memset((char *) fs->group_desc +
286bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o			       (old_fs->desc_blocks * fs->blocksize), 0,
287bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o			       (fs->desc_blocks - old_fs->desc_blocks) *
2882787276ec59e1d52087d307bc30446d088ec65bcTheodore Ts'o			       fs->blocksize);
28924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	}
2901e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o
2911e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	/*
2929213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	 * If the resize_inode feature is set, and we are changing the
2939213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	 * number of descriptor blocks, then adjust
2949213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	 * s_reserved_gdt_blocks if possible to avoid needing to move
2959213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	 * the inode table either now or in the future.
2969213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	 */
2979213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	if ((fs->super->s_feature_compat &
2989213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	     EXT2_FEATURE_COMPAT_RESIZE_INODE) &&
299bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	    (old_fs->desc_blocks != fs->desc_blocks)) {
3009213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		int new;
3019213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
3029213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		new = ((int) fs->super->s_reserved_gdt_blocks) +
303bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o			(old_fs->desc_blocks - fs->desc_blocks);
3049213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		if (new < 0)
3059213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o			new = 0;
3069213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		if (new > fs->blocksize/4)
3079213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o			new = fs->blocksize/4;
3089213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		fs->super->s_reserved_gdt_blocks = new;
3099213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		if (new == 0)
3109213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o			fs->super->s_feature_compat &=
3119213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o				~EXT2_FEATURE_COMPAT_RESIZE_INODE;
3129213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	}
3139213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
3149213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	/*
315a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 * If we are shrinking the number block groups, we're done and
316a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 * can exit now.
3171e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	 */
318bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	if (old_fs->group_desc_count > fs->group_desc_count) {
319c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		retval = 0;
320c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		goto errout;
321c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	}
322bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o
323a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	/*
324a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 * Fix the count of the last (old) block group
325a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 */
326bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	old_numblocks = (old_fs->super->s_blocks_count -
327bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o			 old_fs->super->s_first_data_block) %
328bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o				 old_fs->super->s_blocks_per_group;
3291e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	if (!old_numblocks)
330bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		old_numblocks = old_fs->super->s_blocks_per_group;
331bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	if (old_fs->group_desc_count == fs->group_desc_count) {
332bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		numblocks = (fs->super->s_blocks_count -
333bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o			     fs->super->s_first_data_block) %
334bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o			fs->super->s_blocks_per_group;
3351e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		if (!numblocks)
336bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o			numblocks = fs->super->s_blocks_per_group;
3371e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	} else
338bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		numblocks = fs->super->s_blocks_per_group;
339bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	i = old_fs->group_desc_count - 1;
3401e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	fs->group_desc[i].bg_free_blocks_count += (numblocks-old_numblocks);
3411e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o
3421e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	/*
343a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 * If the number of block groups is staying the same, we're
344a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 * done and can exit now.  (If the number block groups is
345a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 * shrinking, we had exited earlier.)
3461e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	 */
347bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	if (old_fs->group_desc_count >= fs->group_desc_count) {
348c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		retval = 0;
349c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		goto errout;
350c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	}
351bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o
352a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	/*
353a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 * Initialize the new block group descriptors
354a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 */
3551e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	group_block = fs->super->s_first_data_block +
356bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		old_fs->group_desc_count * fs->super->s_blocks_per_group;
357c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o
358bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	adj = old_fs->group_desc_count;
35963b44fbe303ea00118cbe24cbbcde351a9bc0aacTheodore Ts'o	max_group = fs->group_desc_count - adj;
36076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
36176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		old_desc_blocks = fs->super->s_first_meta_bg;
36276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	else
3639213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		old_desc_blocks = fs->desc_blocks +
3649213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o			fs->super->s_reserved_gdt_blocks;
365bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	for (i = old_fs->group_desc_count;
3661e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	     i < fs->group_desc_count; i++) {
3671e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		memset(&fs->group_desc[i], 0,
3681e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		       sizeof(struct ext2_group_desc));
3691e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		adjblocks = 0;
3701e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o
3711e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		if (i == fs->group_desc_count-1) {
3721e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o			numblocks = (fs->super->s_blocks_count -
3731e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o				     fs->super->s_first_data_block) %
3741e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o					     fs->super->s_blocks_per_group;
3751e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o			if (!numblocks)
3761e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o				numblocks = fs->super->s_blocks_per_group;
3771e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		} else
3781e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o			numblocks = fs->super->s_blocks_per_group;
3791e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o
38076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		has_super = ext2fs_bg_has_super(fs, i);
38176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		if (has_super) {
38276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o			ext2fs_mark_block_bitmap(fs->block_map, group_block);
38376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o			adjblocks++;
38476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		}
38576dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		meta_bg_size = (fs->blocksize /
38676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o				sizeof (struct ext2_group_desc));
38776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		meta_bg = i / meta_bg_size;
38876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		if (!(fs->super->s_feature_incompat &
38976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		      EXT2_FEATURE_INCOMPAT_META_BG) ||
39076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		    (meta_bg < fs->super->s_first_meta_bg)) {
39176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o			if (has_super) {
39276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o				for (j=0; j < old_desc_blocks; j++)
39376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o					ext2fs_mark_block_bitmap(fs->block_map,
39476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o							 group_block + 1 + j);
39576dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o				adjblocks += old_desc_blocks;
39676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o			}
39776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		} else {
39876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o			if (has_super)
39976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o				has_super = 1;
40076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o			if (((i % meta_bg_size) == 0) ||
40176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o			    ((i % meta_bg_size) == 1) ||
40276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o			    ((i % meta_bg_size) == (meta_bg_size-1)))
4031e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o				ext2fs_mark_block_bitmap(fs->block_map,
40476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o						 group_block + has_super);
40524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o		}
40676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o
4071e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		adjblocks += 2 + fs->inode_blocks_per_group;
4081e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o
4091e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		numblocks -= adjblocks;
4101e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		fs->super->s_free_blocks_count -= adjblocks;
4111e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		fs->super->s_free_inodes_count +=
4121e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o			fs->super->s_inodes_per_group;
4131e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		fs->group_desc[i].bg_free_blocks_count = numblocks;
4141e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		fs->group_desc[i].bg_free_inodes_count =
4151e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o			fs->super->s_inodes_per_group;
4161e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		fs->group_desc[i].bg_used_dirs_count = 0;
41724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
4181e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		retval = ext2fs_allocate_group_table(fs, i, 0);
419c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		if (retval) goto errout;
42024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
421bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		group_block += fs->super->s_blocks_per_group;
422bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	}
423bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	retval = 0;
424bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o
425bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'oerrout:
426bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	return (retval);
427bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o}
428bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o
429bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o/*
430bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o * This routine adjusts the superblock and other data structures, both
431bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o * in disk as well as in memory...
432bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o */
433bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'ostatic errcode_t adjust_superblock(ext2_resize_t rfs, blk_t new_size)
434bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o{
435bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	ext2_filsys fs;
436bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	int		adj = 0;
437bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	errcode_t	retval;
438bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	blk_t		group_block;
439bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	unsigned long	i;
440bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	unsigned long	max_group;
441bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o
442bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	fs = rfs->new_fs;
443bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	ext2fs_mark_super_dirty(fs);
444bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	ext2fs_mark_bb_dirty(fs);
445bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	ext2fs_mark_ib_dirty(fs);
446bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o
447bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	retval = adjust_fs_info(fs, rfs->old_fs, new_size);
448bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	if (retval)
449bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		goto errout;
450bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o
451bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	/*
452bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	 * Check to make sure there are enough inodes
453bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	 */
454bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	if ((rfs->old_fs->super->s_inodes_count -
455bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	     rfs->old_fs->super->s_free_inodes_count) >
456bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	    rfs->new_fs->super->s_inodes_count) {
457bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		retval = ENOSPC;
458bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		goto errout;
459bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	}
460bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o
461bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	/*
462bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	 * If we are shrinking the number block groups, we're done and
463bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	 * can exit now.
464bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	 */
465bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	if (rfs->old_fs->group_desc_count > fs->group_desc_count) {
466bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		retval = 0;
467bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		goto errout;
468bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	}
469bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o
470bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	/*
471bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	 * If the number of block groups is staying the same, we're
472bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	 * done and can exit now.  (If the number block groups is
473bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	 * shrinking, we had exited earlier.)
474bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	 */
475bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	if (rfs->old_fs->group_desc_count >= fs->group_desc_count) {
476bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		retval = 0;
477bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		goto errout;
478bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	}
479bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o
480bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	/*
481bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	 * Initialize the new block group descriptors
482bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	 */
483bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
484bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o				&rfs->itable_buf);
485bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	if (retval)
486bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		goto errout;
487bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o
488bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	memset(rfs->itable_buf, 0, fs->blocksize * fs->inode_blocks_per_group);
489bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	group_block = fs->super->s_first_data_block +
490bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		rfs->old_fs->group_desc_count * fs->super->s_blocks_per_group;
491bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o
492bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	adj = rfs->old_fs->group_desc_count;
493bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	max_group = fs->group_desc_count - adj;
494bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	if (rfs->progress) {
495bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
496bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o				       0, max_group);
497bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o		if (retval)
498bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o			goto errout;
499bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	}
500bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	for (i = rfs->old_fs->group_desc_count;
501bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o	     i < fs->group_desc_count; i++) {
50205e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o		/*
50305e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o		 * Write out the new inode table
50405e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o		 */
50505e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o		retval = io_channel_write_blk(fs->io,
50605e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o					      fs->group_desc[i].bg_inode_table,
50705e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o					      fs->inode_blocks_per_group,
50805e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o					      rfs->itable_buf);
509c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		if (retval) goto errout;
510c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o
511a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		io_channel_flush(fs->io);
5123b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		if (rfs->progress) {
5133b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o			retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
5143b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o					       i - adj + 1, max_group);
5153b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o			if (retval)
5163b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o				goto errout;
5173b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		}
5181e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		group_block += fs->super->s_blocks_per_group;
51924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	}
520c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	io_channel_flush(fs->io);
521c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	retval = 0;
522c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o
523c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'oerrout:
524c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	return retval;
525c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o}
526c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o
527a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* --------------------------------------------------------------------
528a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o *
529a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Resize processing, phase 2.
530a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o *
531a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * In this phase we adjust determine which blocks need to be moved, in
532a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * blocks_to_move().  We then copy the blocks to their ultimate new
533a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * destinations using block_mover().  Since we are copying blocks to
534a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * their new locations, again during this pass we can abort without
535a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * any problems.
536a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * --------------------------------------------------------------------
537a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */
538a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
539c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o/*
540c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * This helper function creates a block bitmap with all of the
541c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * filesystem meta-data blocks.
542c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o */
543c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'ostatic errcode_t mark_table_blocks(ext2_filsys fs,
54464ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o				   ext2fs_block_bitmap bmap)
545c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o{
54662c6d1403ea00dd72890862c761a41baa10a7ad4Eric Sandeen	blk_t			b;
547544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	unsigned int		j;
548544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	dgrp_t			i;
54968963d5a262ad49cbdad8f946e59ebc34677fe33Theodore Ts'o	unsigned long		meta_bg_size;
550544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	unsigned int		old_desc_blocks;
551c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o
55276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	meta_bg_size = (fs->blocksize / sizeof (struct ext2_group_desc));
55376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
55476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		old_desc_blocks = fs->super->s_first_meta_bg;
55576dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	else
5569213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		old_desc_blocks = fs->desc_blocks +
5579213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o			fs->super->s_reserved_gdt_blocks;
558c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	for (i = 0; i < fs->group_desc_count; i++) {
55964ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o		ext2fs_reserve_super_and_bgd(fs, i, bmap);
56076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o
561c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		/*
562c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		 * Mark the blocks used for the inode table
563c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		 */
564c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		for (j = 0, b = fs->group_desc[i].bg_inode_table;
565544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o		     j < (unsigned int) fs->inode_blocks_per_group;
566c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		     j++, b++)
567c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o			ext2fs_mark_block_bitmap(bmap, b);
568c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o
569c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		/*
570c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		 * Mark block used for the block bitmap
571c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		 */
572c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		ext2fs_mark_block_bitmap(bmap,
573c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o					 fs->group_desc[i].bg_block_bitmap);
57464ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o
575c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		/*
576c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		 * Mark block used for the inode bitmap
577c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		 */
578c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		ext2fs_mark_block_bitmap(bmap,
579c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o					 fs->group_desc[i].bg_inode_bitmap);
580c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	}
5811e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	return 0;
58224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o}
58324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
58424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o/*
58576dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o * This function checks to see if a particular block (either a
58676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o * superblock or a block group descriptor) overlaps with an inode or
58776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o * block bitmap block, or with the inode table.
58876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o */
58976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'ostatic void mark_fs_metablock(ext2_resize_t rfs,
59076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o			      ext2fs_block_bitmap meta_bmap,
59176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o			      int group, blk_t blk)
59276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o{
59376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	ext2_filsys 	fs = rfs->new_fs;
59476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o
59576dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	ext2fs_mark_block_bitmap(rfs->reserve_blocks, blk);
59676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	ext2fs_mark_block_bitmap(fs->block_map, blk);
59776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o
59876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	/*
59976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	 * Check to see if we overlap with the inode or block bitmap,
60076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	 * or the inode tables.  If not, and the block is in use, then
60176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	 * mark it as a block to be moved.
60276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	 */
60376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	if (IS_BLOCK_BM(fs, group, blk)) {
60476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		FS_BLOCK_BM(fs, group) = 0;
60576dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		rfs->needed_blocks++;
60676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	} else if (IS_INODE_BM(fs, group, blk)) {
60776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		FS_INODE_BM(fs, group) = 0;
60876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		rfs->needed_blocks++;
60976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	} else if (IS_INODE_TB(fs, group, blk)) {
61076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		FS_INODE_TB(fs, group) = 0;
61176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		rfs->needed_blocks++;
61276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	} else if (ext2fs_test_block_bitmap(rfs->old_fs->block_map, blk) &&
61376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		   !ext2fs_test_block_bitmap(meta_bmap, blk)) {
61476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		ext2fs_mark_block_bitmap(rfs->move_blocks, blk);
61576dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		rfs->needed_blocks++;
61676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	}
61776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o}
61876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o
61976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o
62076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o/*
62124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * This routine marks and unmarks reserved blocks in the new block
62224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * bitmap.  It also determines which blocks need to be moved and
62324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * places this information into the move_blocks bitmap.
62424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */
625c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'ostatic errcode_t blocks_to_move(ext2_resize_t rfs)
62624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o{
627544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	int		j, has_super;
628544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	dgrp_t		i, max_groups;
629544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	blk_t		blk, group_blk;
630544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	unsigned long	old_blocks, new_blocks;
631544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	unsigned int	meta_bg, meta_bg_size;
63224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	errcode_t	retval;
633c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	ext2_filsys 	fs, old_fs;
634c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	ext2fs_block_bitmap	meta_bmap;
63524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
636c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	fs = rfs->new_fs;
637c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	old_fs = rfs->old_fs;
638c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	if (old_fs->super->s_blocks_count > fs->super->s_blocks_count)
639c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		fs = rfs->old_fs;
640c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o
641a13575f4d29a908add19ea27baa102bc6944ee30Theodore Ts'o	retval = ext2fs_allocate_block_bitmap(fs, _("reserved blocks"),
6421e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o					      &rfs->reserve_blocks);
64324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	if (retval)
64424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o		return retval;
6451e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o
646a13575f4d29a908add19ea27baa102bc6944ee30Theodore Ts'o	retval = ext2fs_allocate_block_bitmap(fs, _("blocks to be moved"),
647c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o					      &rfs->move_blocks);
648c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	if (retval)
649c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		return retval;
650c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o
65164ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o	retval = ext2fs_allocate_block_bitmap(fs, _("meta-data blocks"),
65264ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o					      &meta_bmap);
65364ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o	if (retval)
65464ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o		return retval;
65564ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o
65664ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o	retval = mark_table_blocks(old_fs, meta_bmap);
657c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	if (retval)
658c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		return retval;
659c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o
660c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	fs = rfs->new_fs;
661c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o
6621e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	/*
6631e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	 * If we're shrinking the filesystem, we need to move all of
6641e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	 * the blocks that don't fit any more
6651e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	 */
6661e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	for (blk = fs->super->s_blocks_count;
667c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	     blk < old_fs->super->s_blocks_count; blk++) {
668c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		if (ext2fs_test_block_bitmap(old_fs->block_map, blk) &&
669c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		    !ext2fs_test_block_bitmap(meta_bmap, blk)) {
670c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o			ext2fs_mark_block_bitmap(rfs->move_blocks, blk);
6711e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o			rfs->needed_blocks++;
672c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		}
6731e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		ext2fs_mark_block_bitmap(rfs->reserve_blocks, blk);
6741e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	}
67524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
67676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) {
67776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		old_blocks = old_fs->super->s_first_meta_bg;
67876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		new_blocks = fs->super->s_first_meta_bg;
67976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	} else {
6809213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		old_blocks = old_fs->desc_blocks + old_fs->super->s_reserved_gdt_blocks;
6819213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		new_blocks = fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
68276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	}
68376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o
684c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	if (old_blocks == new_blocks) {
685c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		retval = 0;
686c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		goto errout;
687c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	}
68824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
6891333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o	max_groups = fs->group_desc_count;
6901333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o	if (max_groups > old_fs->group_desc_count)
6911333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o		max_groups = old_fs->group_desc_count;
692c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	group_blk = old_fs->super->s_first_data_block;
69324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	/*
69424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * If we're reducing the number of descriptor blocks, this
69524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * makes life easy.  :-)   We just have to mark some extra
69624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * blocks as free.
69724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 */
69824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	if (old_blocks > new_blocks) {
6991333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o		for (i = 0; i < max_groups; i++) {
7001e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o			if (!ext2fs_bg_has_super(fs, i)) {
7011e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o				group_blk += fs->super->s_blocks_per_group;
70224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o				continue;
70324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o			}
704c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o			for (blk = group_blk+1+new_blocks;
705c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o			     blk < group_blk+1+old_blocks; blk++) {
7061e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o				ext2fs_unmark_block_bitmap(fs->block_map,
70724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o							   blk);
708052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o				rfs->needed_blocks--;
709052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o			}
7101e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o			group_blk += fs->super->s_blocks_per_group;
71124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o		}
712c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		retval = 0;
713c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		goto errout;
71424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	}
71524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	/*
71624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 * If we're increasing the number of descriptor blocks, life
7171e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	 * gets interesting....
71824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o	 */
71976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o	meta_bg_size = (fs->blocksize / sizeof (struct ext2_group_desc));
7201333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o	for (i = 0; i < max_groups; i++) {
72176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		has_super = ext2fs_bg_has_super(fs, i);
72276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		if (has_super)
72376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o			mark_fs_metablock(rfs, meta_bmap, i, group_blk);
72476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o
72576dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		meta_bg = i / meta_bg_size;
72676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		if (!(fs->super->s_feature_incompat &
72776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		      EXT2_FEATURE_INCOMPAT_META_BG) ||
72876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		    (meta_bg < fs->super->s_first_meta_bg)) {
729424cb7b62aa417db2eaec79cfaec7433b31f8726Theodore Ts'o			if (has_super) {
730424cb7b62aa417db2eaec79cfaec7433b31f8726Theodore Ts'o				for (blk = group_blk+1;
731424cb7b62aa417db2eaec79cfaec7433b31f8726Theodore Ts'o				     blk < group_blk + 1 + new_blocks; blk++)
732424cb7b62aa417db2eaec79cfaec7433b31f8726Theodore Ts'o					mark_fs_metablock(rfs, meta_bmap,
733424cb7b62aa417db2eaec79cfaec7433b31f8726Theodore Ts'o							  i, blk);
734424cb7b62aa417db2eaec79cfaec7433b31f8726Theodore Ts'o			}
73576dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o		} else {
73676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o			if (has_super)
73776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o				has_super = 1;
73876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o			if (((i % meta_bg_size) == 0) ||
73976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o			    ((i % meta_bg_size) == 1) ||
74076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o			    ((i % meta_bg_size) == (meta_bg_size-1)))
74176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o				mark_fs_metablock(rfs, meta_bmap, i,
74276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o						  group_blk + has_super);
74324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o		}
74476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o
7451e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		if (fs->group_desc[i].bg_inode_table &&
7461e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		    fs->group_desc[i].bg_inode_bitmap &&
7471e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		    fs->group_desc[i].bg_block_bitmap)
7481e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o			goto next_group;
74924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
7501e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		/*
751c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		 * Reserve the existing meta blocks that we know
752c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		 * aren't to be moved.
7531e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		 */
7541e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		if (fs->group_desc[i].bg_block_bitmap)
7551e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o			ext2fs_mark_block_bitmap(rfs->reserve_blocks,
7561e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o				 fs->group_desc[i].bg_block_bitmap);
7571e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		if (fs->group_desc[i].bg_inode_bitmap)
7581e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o			ext2fs_mark_block_bitmap(rfs->reserve_blocks,
7591e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o				 fs->group_desc[i].bg_inode_bitmap);
7601e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		if (fs->group_desc[i].bg_inode_table)
7611e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o			for (blk = fs->group_desc[i].bg_inode_table, j=0;
7621e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o			     j < fs->inode_blocks_per_group ; j++, blk++)
7631e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o				ext2fs_mark_block_bitmap(rfs->reserve_blocks,
7641e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o							 blk);
76524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
766c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		/*
767c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		 * Allocate the missing data structures
768c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		 */
7691e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		retval = ext2fs_allocate_group_table(fs, i,
7701e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o						     rfs->reserve_blocks);
7711e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		if (retval)
772c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o			goto errout;
77324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
7741e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		/*
775c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		 * For those structures that have changed, we need to
776c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		 * do bookkeepping.
7771e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		 */
778c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		if (FS_BLOCK_BM(old_fs, i) !=
779c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		    (blk = FS_BLOCK_BM(fs, i))) {
780c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o			ext2fs_mark_block_bitmap(fs->block_map, blk);
781c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o			if (ext2fs_test_block_bitmap(old_fs->block_map, blk) &&
782c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o			    !ext2fs_test_block_bitmap(meta_bmap, blk))
783c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o				ext2fs_mark_block_bitmap(rfs->move_blocks,
784c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o							 blk);
785c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		}
786c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		if (FS_INODE_BM(old_fs, i) !=
787c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		    (blk = FS_INODE_BM(fs, i))) {
788c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o			ext2fs_mark_block_bitmap(fs->block_map, blk);
789c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o			if (ext2fs_test_block_bitmap(old_fs->block_map, blk) &&
790c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o			    !ext2fs_test_block_bitmap(meta_bmap, blk))
791c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o				ext2fs_mark_block_bitmap(rfs->move_blocks,
792c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o							 blk);
793c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		}
79424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
795052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		/*
796052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		 * The inode table, if we need to relocate it, is
797052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		 * handled specially.  We have to reserve the blocks
798052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		 * for both the old and the new inode table, since we
799052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		 * can't have the inode table be destroyed during the
800052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		 * block relocation phase.
801052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		 */
802c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		if (FS_INODE_TB(fs, i) == FS_INODE_TB(old_fs, i))
803052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o			goto next_group; /* inode table not moved */
804052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o
805c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		rfs->needed_blocks += fs->inode_blocks_per_group;
806052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o
807052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		/*
808052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		 * Mark the new inode table as in use in the new block
809c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		 * allocation bitmap, and move any blocks that might
810c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		 * be necessary.
811052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		 */
8121e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		for (blk = fs->group_desc[i].bg_inode_table, j=0;
813c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		     j < fs->inode_blocks_per_group ; j++, blk++) {
8141e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o			ext2fs_mark_block_bitmap(fs->block_map, blk);
815c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o			if (ext2fs_test_block_bitmap(old_fs->block_map, blk) &&
816c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o			    !ext2fs_test_block_bitmap(meta_bmap, blk))
817c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o				ext2fs_mark_block_bitmap(rfs->move_blocks,
818c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o							 blk);
819c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		}
820c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o
8211e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		/*
822052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		 * Make sure the old inode table is reserved in the
823052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		 * block reservation bitmap.
8241e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		 */
825052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		for (blk = rfs->old_fs->group_desc[i].bg_inode_table, j=0;
826052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		     j < fs->inode_blocks_per_group ; j++, blk++)
827052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o			ext2fs_mark_block_bitmap(rfs->reserve_blocks, blk);
8281e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o
8291e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	next_group:
8301e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o		group_blk += rfs->new_fs->super->s_blocks_per_group;
8311e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o	}
832c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	retval = 0;
833c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o
834c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'oerrout:
835c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	if (meta_bmap)
836c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		ext2fs_free_block_bitmap(meta_bmap);
837c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o
838c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	return retval;
8391e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o}
84024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
841a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/*
842a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * This helper function tries to allocate a new block.  We try to
843a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * avoid hitting the original group descriptor blocks at least at
844a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * first, since we want to make it possible to recover from a badly
845a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * aborted resize operation as much as possible.
846a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o *
847a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * In the future, I may further modify this routine to balance out
848a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * where we get the new blocks across the various block groups.
849a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Ideally we would allocate blocks that corresponded with the block
850a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * group of the containing inode, and keep contiguous blocks
851a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * together.  However, this very difficult to do efficiently, since we
852a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * don't have the necessary information up front.
853a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */
854a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
855a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define AVOID_OLD	1
856a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define DESPERATION	2
857a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
858a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic void init_block_alloc(ext2_resize_t rfs)
859a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{
860a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	rfs->alloc_state = AVOID_OLD;
861a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	rfs->new_blk = rfs->new_fs->super->s_first_data_block;
8622bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o#if 0
8632bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o	/* HACK for testing */
8642bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o	if (rfs->new_fs->super->s_blocks_count >
8652bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o	    rfs->old_fs->super->s_blocks_count)
8662bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o		rfs->new_blk = rfs->old_fs->super->s_blocks_count;
8672bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o#endif
868a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o}
869a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
870a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic blk_t get_new_block(ext2_resize_t rfs)
871a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{
872a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	ext2_filsys	fs = rfs->new_fs;
873a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
874a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	while (1) {
875a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (rfs->new_blk >= fs->super->s_blocks_count) {
876a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			if (rfs->alloc_state == DESPERATION)
877a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				return 0;
878a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
879a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG
880a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			if (rfs->flags & RESIZE_DEBUG_BMOVE)
881f35fd3d5eeb3e35660ea87adbc170978c3cdf9e3Theodore Ts'o				printf("Going into desperation mode "
882f35fd3d5eeb3e35660ea87adbc170978c3cdf9e3Theodore Ts'o				       "for block allocations\n");
883a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif
884a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			rfs->alloc_state = DESPERATION;
885a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			rfs->new_blk = fs->super->s_first_data_block;
886a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			continue;
887a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		}
888a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (ext2fs_test_block_bitmap(fs->block_map, rfs->new_blk) ||
889a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		    ext2fs_test_block_bitmap(rfs->reserve_blocks,
890a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o					     rfs->new_blk) ||
891a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		    ((rfs->alloc_state == AVOID_OLD) &&
892bce49798f7f4380dff5693bc8308019b3cf8de25Theodore Ts'o		     (rfs->new_blk < rfs->old_fs->super->s_blocks_count) &&
893a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		     ext2fs_test_block_bitmap(rfs->old_fs->block_map,
894a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o					      rfs->new_blk))) {
895a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			rfs->new_blk++;
896a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			continue;
897a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		}
898a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		return rfs->new_blk;
899a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	}
900a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o}
901a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
902a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t block_mover(ext2_resize_t rfs)
903a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{
904a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	blk_t			blk, old_blk, new_blk;
905a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	ext2_filsys		fs = rfs->new_fs;
906a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	ext2_filsys		old_fs = rfs->old_fs;
907a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	errcode_t		retval;
908a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	int			size, c;
909a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	int			to_move, moved;
9107d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o	ext2_badblocks_list	badblock_list = 0;
9117d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o	int			bb_modified = 0;
9127d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o
9137d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o	retval = ext2fs_read_bb_inode(old_fs, &badblock_list);
9147d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o	if (retval)
9157d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o		return retval;
916a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
917a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	new_blk = fs->super->s_first_data_block;
918a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (!rfs->itable_buf) {
919a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		retval = ext2fs_get_mem(fs->blocksize *
920a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o					fs->inode_blocks_per_group,
921c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o					&rfs->itable_buf);
922a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (retval)
923a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			return retval;
924a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	}
925a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	retval = ext2fs_create_extent_table(&rfs->bmap, 0);
926a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval)
927a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		return retval;
928a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
929a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	/*
930a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 * The first step is to figure out where all of the blocks
931a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 * will go.
932a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 */
933a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	to_move = moved = 0;
934a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	init_block_alloc(rfs);
935a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	for (blk = old_fs->super->s_first_data_block;
936a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	     blk < old_fs->super->s_blocks_count; blk++) {
937a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (!ext2fs_test_block_bitmap(old_fs->block_map, blk))
938a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			continue;
939a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (!ext2fs_test_block_bitmap(rfs->move_blocks, blk))
940a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			continue;
9417d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o		if (ext2fs_badblocks_list_test(badblock_list, blk)) {
9427d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o			ext2fs_badblocks_list_del(badblock_list, blk);
9437d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o			bb_modified++;
9447d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o			continue;
9457d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o		}
946a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
947a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		new_blk = get_new_block(rfs);
948a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (!new_blk) {
949a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			retval = ENOSPC;
950a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			goto errout;
951a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		}
952a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		ext2fs_mark_block_bitmap(fs->block_map, new_blk);
953a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		ext2fs_add_extent_entry(rfs->bmap, blk, new_blk);
954a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		to_move++;
955a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	}
956a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
957a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (to_move == 0) {
958cefbf4870c0593e3c7a01b8d5494463b247d90f0Theodore Ts'o		if (rfs->bmap) {
959cefbf4870c0593e3c7a01b8d5494463b247d90f0Theodore Ts'o			ext2fs_free_extent_table(rfs->bmap);
960cefbf4870c0593e3c7a01b8d5494463b247d90f0Theodore Ts'o			rfs->bmap = 0;
961cefbf4870c0593e3c7a01b8d5494463b247d90f0Theodore Ts'o		}
962a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		retval = 0;
963a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		goto errout;
964a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	}
965a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
966a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	/*
967a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 * Step two is to actually move the blocks
968a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 */
969a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	retval =  ext2fs_iterate_extent(rfs->bmap, 0, 0, 0);
970a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval) goto errout;
971a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
9723b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o	if (rfs->progress) {
9733b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		retval = (rfs->progress)(rfs, E2_RSZ_BLOCK_RELOC_PASS,
9743b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o					 0, to_move);
9753b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		if (retval)
9763b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o			goto errout;
9773b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o	}
978a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	while (1) {
979a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		retval = ext2fs_iterate_extent(rfs->bmap, &old_blk, &new_blk, &size);
980a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (retval) goto errout;
981a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (!size)
982a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			break;
983a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG
984a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (rfs->flags & RESIZE_DEBUG_BMOVE)
985f35fd3d5eeb3e35660ea87adbc170978c3cdf9e3Theodore Ts'o			printf("Moving %d blocks %u->%u\n",
986f35fd3d5eeb3e35660ea87adbc170978c3cdf9e3Theodore Ts'o			       size, old_blk, new_blk);
987a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif
988a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		do {
989a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			c = size;
990a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			if (c > fs->inode_blocks_per_group)
991a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				c = fs->inode_blocks_per_group;
992a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			retval = io_channel_read_blk(fs->io, old_blk, c,
993a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o						     rfs->itable_buf);
994a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			if (retval) goto errout;
995a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			retval = io_channel_write_blk(fs->io, new_blk, c,
996a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o						      rfs->itable_buf);
997a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			if (retval) goto errout;
998a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			size -= c;
999a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			new_blk += c;
1000a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			old_blk += c;
1001a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			moved += c;
1002a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			if (rfs->progress) {
1003a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				io_channel_flush(fs->io);
10043b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o				retval = (rfs->progress)(rfs,
10053b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o						E2_RSZ_BLOCK_RELOC_PASS,
1006a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o						moved, to_move);
10073b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o				if (retval)
10083b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o					goto errout;
1009a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			}
1010a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		} while (size > 0);
1011a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		io_channel_flush(fs->io);
1012a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	}
1013a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1014a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'oerrout:
10157d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o	if (badblock_list) {
10167d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o		if (!retval && bb_modified)
10177d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o			retval = ext2fs_update_bb_inode(old_fs,
10187d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o							badblock_list);
10197d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o		ext2fs_badblocks_list_free(badblock_list);
10207d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o	}
1021a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	return retval;
1022a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o}
1023a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1024a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1025a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* --------------------------------------------------------------------
1026a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o *
1027a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Resize processing, phase 3
1028a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o *
1029a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * --------------------------------------------------------------------
1030a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */
1031a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1032a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1033a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostruct process_block_struct {
1034a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	ext2_resize_t 		rfs;
1035dfcdc32f8d6623a35a9e66f503c535e4081b7266Theodore Ts'o	ext2_ino_t		ino;
1036a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	struct ext2_inode *	inode;
1037a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	errcode_t		error;
1038a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	int			is_dir;
1039a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	int			changed;
1040a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o};
1041a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1042a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic int process_block(ext2_filsys fs, blk_t	*block_nr,
1043544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o			 e2_blkcnt_t blockcnt,
1044544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o			 blk_t ref_block EXT2FS_ATTR((unused)),
1045544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o			 int ref_offset EXT2FS_ATTR((unused)), void *priv_data)
1046a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{
1047a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	struct process_block_struct *pb;
1048a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	errcode_t	retval;
1049a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	blk_t		block, new_block;
1050a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	int		ret = 0;
1051a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1052a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	pb = (struct process_block_struct *) priv_data;
1053a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	block = *block_nr;
1054a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (pb->rfs->bmap) {
1055a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		new_block = ext2fs_extent_translate(pb->rfs->bmap, block);
1056a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (new_block) {
1057a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			*block_nr = new_block;
1058a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			ret |= BLOCK_CHANGED;
1059a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			pb->changed = 1;
1060a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG
1061a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			if (pb->rfs->flags & RESIZE_DEBUG_BMOVE)
1062f35fd3d5eeb3e35660ea87adbc170978c3cdf9e3Theodore Ts'o				printf("ino=%u, blockcnt=%lld, %u->%u\n",
1063a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				       pb->ino, blockcnt, block, new_block);
1064a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif
1065a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			block = new_block;
1066a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		}
1067a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	}
1068a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (pb->is_dir) {
1069a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		retval = ext2fs_add_dir_block(fs->dblist, pb->ino,
1070101c84f2e049bffcdb6c5ba1784842cdd50dbf05Theodore Ts'o					      block, (int) blockcnt);
1071a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (retval) {
1072a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			pb->error = retval;
1073a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			ret |= BLOCK_ABORT;
1074a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		}
1075a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	}
1076a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	return ret;
1077a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o}
1078a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1079a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/*
1080a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Progress callback
1081a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */
1082544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'ostatic errcode_t progress_callback(ext2_filsys fs,
1083544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o				   ext2_inode_scan scan EXT2FS_ATTR((unused)),
1084a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				   dgrp_t group, void * priv_data)
1085a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{
1086a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	ext2_resize_t rfs = (ext2_resize_t) priv_data;
10873b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o	errcode_t		retval;
1088a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1089a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	/*
1090f4b2a6db3f13f4210697bcd273086006c719929bTheodore Ts'o	 * This check is to protect against old ext2 libraries.  It
1091f4b2a6db3f13f4210697bcd273086006c719929bTheodore Ts'o	 * shouldn't be needed against new libraries.
1092a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 */
1093f4b2a6db3f13f4210697bcd273086006c719929bTheodore Ts'o	if ((group+1) == 0)
1094a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		return 0;
1095a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1096a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (rfs->progress) {
1097a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		io_channel_flush(fs->io);
10983b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		retval = (rfs->progress)(rfs, E2_RSZ_INODE_SCAN_PASS,
10993b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o					 group+1, fs->group_desc_count);
11003b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		if (retval)
11013b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o			return retval;
1102a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	}
1103a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1104a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	return 0;
1105a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o}
1106a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1107a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t inode_scan_and_fix(ext2_resize_t rfs)
1108a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{
1109a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	struct process_block_struct	pb;
1110dfcdc32f8d6623a35a9e66f503c535e4081b7266Theodore Ts'o	ext2_ino_t		ino, new_inode;
1111a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	struct ext2_inode 	inode;
1112a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	ext2_inode_scan 	scan = NULL;
1113a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	errcode_t		retval;
1114a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	int			group;
1115a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	char			*block_buf = 0;
1116dfcdc32f8d6623a35a9e66f503c535e4081b7266Theodore Ts'o	ext2_ino_t		start_to_move;
11170ccd488a764c14b27983b92435deca5e1adf9061Theodore Ts'o	blk_t			orig_size, new_block;
1118a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1119a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if ((rfs->old_fs->group_desc_count <=
1120a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	     rfs->new_fs->group_desc_count) &&
1121a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	    !rfs->bmap)
1122a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		return 0;
1123a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
11242bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o	/*
11252bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o	 * Save the original size of the old filesystem, and
11262bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o	 * temporarily set the size to be the new size if the new size
11272bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o	 * is larger.  We need to do this to avoid catching an error
11282bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o	 * by the block iterator routines
11292bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o	 */
11302bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o	orig_size = rfs->old_fs->super->s_blocks_count;
11312bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o	if (orig_size < rfs->new_fs->super->s_blocks_count)
11322bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o		rfs->old_fs->super->s_blocks_count =
11332bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o			rfs->new_fs->super->s_blocks_count;
11342bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o
1135a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	retval = ext2fs_open_inode_scan(rfs->old_fs, 0, &scan);
1136a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval) goto errout;
1137a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1138a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	retval = ext2fs_init_dblist(rfs->old_fs, 0);
1139a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval) goto errout;
1140c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o	retval = ext2fs_get_mem(rfs->old_fs->blocksize * 3, &block_buf);
1141a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (retval) goto errout;
1142a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1143a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	start_to_move = (rfs->new_fs->group_desc_count *
1144a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			 rfs->new_fs->super->s_inodes_per_group);
1145a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
11463b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o	if (rfs->progress) {
11473b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		retval = (rfs->progress)(rfs, E2_RSZ_INODE_SCAN_PASS,
11483b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o					 0, rfs->old_fs->group_desc_count);
11493b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		if (retval)
11503b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o			goto errout;
11513b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o	}
1152a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	ext2fs_set_inode_callback(scan, progress_callback, (void *) rfs);
1153a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	pb.rfs = rfs;
1154a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	pb.inode = &inode;
1155a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	pb.error = 0;
1156a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	new_inode = EXT2_FIRST_INODE(rfs->new_fs->super);
1157a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	/*
1158a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 * First, copy all of the inodes that need to be moved
1159a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 * elsewhere in the inode table
1160a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 */
1161a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	while (1) {
1162a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		retval = ext2fs_get_next_inode(scan, &ino, &inode);
1163a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (retval) goto errout;
1164a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (!ino)
1165a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			break;
1166a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
11679213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		if (inode.i_links_count == 0 && ino != EXT2_RESIZE_INO)
1168a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			continue; /* inode not in use */
1169a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1170a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		pb.is_dir = LINUX_S_ISDIR(inode.i_mode);
1171a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		pb.changed = 0;
1172a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
11730ccd488a764c14b27983b92435deca5e1adf9061Theodore Ts'o		if (inode.i_file_acl && rfs->bmap) {
11740ccd488a764c14b27983b92435deca5e1adf9061Theodore Ts'o			new_block = ext2fs_extent_translate(rfs->bmap,
1175ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o							    inode.i_file_acl);
1176ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o			if (new_block) {
1177ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o				inode.i_file_acl = new_block;
1178ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o				retval = ext2fs_write_inode(rfs->old_fs,
1179ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o							    ino, &inode);
1180ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o				if (retval) goto errout;
1181ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o			}
1182ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o		}
1183ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o
1184a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (ext2fs_inode_has_valid_blocks(&inode) &&
1185a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		    (rfs->bmap || pb.is_dir)) {
1186a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			pb.ino = ino;
1187a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			retval = ext2fs_block_iterate2(rfs->old_fs,
1188a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o						       ino, 0, block_buf,
1189a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o						       process_block, &pb);
1190a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			if (retval)
1191a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				goto errout;
1192a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			if (pb.error) {
1193a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				retval = pb.error;
1194a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				goto errout;
1195a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			}
1196a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		}
1197a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1198a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (ino <= start_to_move)
1199a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			continue; /* Don't need to move it. */
1200a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1201a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		/*
1202a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		 * Find a new inode
1203a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		 */
1204a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		while (1) {
1205a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			if (!ext2fs_test_inode_bitmap(rfs->new_fs->inode_map,
1206a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o						      new_inode))
1207a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				break;
1208a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			new_inode++;
1209a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			if (new_inode > rfs->new_fs->super->s_inodes_count) {
1210a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				retval = ENOSPC;
1211a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				goto errout;
1212a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			}
1213a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		}
1214a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		ext2fs_mark_inode_bitmap(rfs->new_fs->inode_map, new_inode);
1215a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (pb.changed) {
1216a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			/* Get the new version of the inode */
1217a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			retval = ext2fs_read_inode(rfs->old_fs, ino, &inode);
1218a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			if (retval) goto errout;
1219a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		}
1220085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o		inode.i_ctime = time(0);
1221a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		retval = ext2fs_write_inode(rfs->old_fs, new_inode, &inode);
1222a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (retval) goto errout;
1223a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1224a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		group = (new_inode-1) / EXT2_INODES_PER_GROUP(rfs->new_fs->super);
1225a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (LINUX_S_ISDIR(inode.i_mode))
1226a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			rfs->new_fs->group_desc[group].bg_used_dirs_count++;
1227a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1228a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG
1229a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (rfs->flags & RESIZE_DEBUG_INODEMAP)
1230f35fd3d5eeb3e35660ea87adbc170978c3cdf9e3Theodore Ts'o			printf("Inode moved %u->%u\n", ino, new_inode);
1231a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif
1232a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (!rfs->imap) {
1233a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			retval = ext2fs_create_extent_table(&rfs->imap, 0);
1234a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			if (retval)
1235a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				goto errout;
1236a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		}
1237a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		ext2fs_add_extent_entry(rfs->imap, ino, new_inode);
1238a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	}
1239a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	io_channel_flush(rfs->old_fs->io);
1240a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1241a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'oerrout:
12422bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o	rfs->old_fs->super->s_blocks_count = orig_size;
1243a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (rfs->bmap) {
1244a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		ext2fs_free_extent_table(rfs->bmap);
1245a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		rfs->bmap = 0;
1246a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	}
1247a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (scan)
1248a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		ext2fs_close_inode_scan(scan);
1249a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (block_buf)
1250c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o		ext2fs_free_mem(&block_buf);
1251a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	return retval;
1252a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o}
1253a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1254a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* --------------------------------------------------------------------
1255a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o *
1256a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Resize processing, phase 4.
1257a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o *
1258a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * --------------------------------------------------------------------
1259a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */
1260a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1261a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostruct istruct {
1262a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	ext2_resize_t rfs;
12633b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o	errcode_t	err;
12641333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o	unsigned long	max_dirs;
1265a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	int		num;
1266a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o};
1267a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1268544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'ostatic int check_and_change_inodes(ext2_ino_t dir,
1269544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o				   int entry EXT2FS_ATTR((unused)),
1270a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				   struct ext2_dir_entry *dirent, int offset,
1271544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o				   int	blocksize EXT2FS_ATTR((unused)),
1272544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o				   char *buf EXT2FS_ATTR((unused)),
1273544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o				   void *priv_data)
1274a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{
1275a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	struct istruct *is = (struct istruct *) priv_data;
1276085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o	struct ext2_inode 	inode;
1277085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o	ext2_ino_t		new_inode;
1278085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o	errcode_t		retval;
1279a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1280a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (is->rfs->progress && offset == 0) {
1281a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		io_channel_flush(is->rfs->old_fs->io);
12823b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		is->err = (is->rfs->progress)(is->rfs,
12833b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o					      E2_RSZ_INODE_REF_UPD_PASS,
12841333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o					      ++is->num, is->max_dirs);
12853b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		if (is->err)
12863b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o			return DIRENT_ABORT;
1287a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	}
1288a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1289a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (!dirent->inode)
1290a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		return 0;
1291a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1292a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	new_inode = ext2fs_extent_translate(is->rfs->imap, dirent->inode);
1293a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1294a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (!new_inode)
1295a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		return 0;
1296a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG
1297a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (is->rfs->flags & RESIZE_DEBUG_INODEMAP)
1298f35fd3d5eeb3e35660ea87adbc170978c3cdf9e3Theodore Ts'o		printf("Inode translate (dir=%u, name=%.*s, %u->%u)\n",
129906191693d4d253a8496677dd02e3b8529a7fce2cTheodore Ts'o		       dir, dirent->name_len&0xFF, dirent->name,
1300a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		       dirent->inode, new_inode);
1301a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif
1302a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1303a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	dirent->inode = new_inode;
1304a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1305085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o	/* Update the directory mtime and ctime */
1306085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o	retval = ext2fs_read_inode(is->rfs->old_fs, dir, &inode);
1307085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o	if (retval == 0) {
1308085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o		inode.i_mtime = inode.i_ctime = time(0);
1309085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o		ext2fs_write_inode(is->rfs->old_fs, dir, &inode);
1310085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o	}
1311085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o
1312a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	return DIRENT_CHANGED;
1313a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o}
1314a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1315a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t inode_ref_fix(ext2_resize_t rfs)
1316a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{
1317a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	errcode_t		retval;
1318a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	struct istruct 		is;
1319a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1320a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	if (!rfs->imap)
1321a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		return 0;
1322a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1323a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	/*
1324a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 * Now, we iterate over all of the directories to update the
1325a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 * inode references
1326a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	 */
1327a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	is.num = 0;
13281333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o	is.max_dirs = ext2fs_dblist_count(rfs->old_fs->dblist);
1329a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	is.rfs = rfs;
13303b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o	is.err = 0;
1331a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
13323b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o	if (rfs->progress) {
13333b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		retval = (rfs->progress)(rfs, E2_RSZ_INODE_REF_UPD_PASS,
13341333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o					 0, is.max_dirs);
13353b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		if (retval)
13363b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o			goto errout;
13373b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o	}
1338a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1339a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	retval = ext2fs_dblist_dir_iterate(rfs->old_fs->dblist,
1340a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o					   DIRENT_FLAG_INCLUDE_EMPTY, 0,
1341a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o					   check_and_change_inodes, &is);
13423b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o	if (retval)
13433b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		goto errout;
13443b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o	if (is.err) {
13453b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		retval = is.err;
13463b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		goto errout;
13473b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o	}
1348a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
13493b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'oerrout:
1350a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	ext2fs_free_extent_table(rfs->imap);
1351a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	rfs->imap = 0;
1352a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	return retval;
1353a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o}
1354a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1355a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
1356a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* --------------------------------------------------------------------
1357a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o *
1358a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Resize processing, phase 5.
1359a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o *
1360a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * In this phase we actually move the inode table around, and then
1361a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * update the summary statistics.  This is scary, since aborting here
1362a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * will potentially scramble the filesystem.  (We are moving the
1363a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * inode tables around in place, and so the potential for lost data,
1364a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * or at the very least scrambling the mapping between filenames and
1365a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * inode numbers is very high in case of a power failure here.)
1366a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * --------------------------------------------------------------------
1367a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */
1368a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
136924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o
137024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o/*
1371052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * A very scary routine --- this one moves the inode table around!!!
1372052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o *
1373052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * After this you have to use the rfs->new_fs file handle to read and
1374052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * write inodes.
1375052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o */
1376c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'ostatic errcode_t move_itables(ext2_resize_t rfs)
1377052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o{
1378544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	int		n, num, size, diff;
1379544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	dgrp_t		i, max_groups;
1380052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	ext2_filsys	fs = rfs->new_fs;
138105e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o	char		*cp;
138264ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o	blk_t		old_blk, new_blk, blk;
1383a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	errcode_t	retval;
138464ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o	int		j, to_move, moved;
1385052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o
13861333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o	max_groups = fs->group_desc_count;
13871333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o	if (max_groups > rfs->old_fs->group_desc_count)
13881333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o		max_groups = rfs->old_fs->group_desc_count;
1389052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o
139005e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o	size = fs->blocksize * fs->inode_blocks_per_group;
139105e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o	if (!rfs->itable_buf) {
1392c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o		retval = ext2fs_get_mem(size, &rfs->itable_buf);
1393ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o		if (retval)
1394ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o			return retval;
139505e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o	}
1396c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o
1397c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	/*
1398c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	 * Figure out how many inode tables we need to move
1399c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	 */
1400c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	to_move = moved = 0;
14011333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o	for (i=0; i < max_groups; i++)
1402c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		if (rfs->old_fs->group_desc[i].bg_inode_table !=
1403c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		    fs->group_desc[i].bg_inode_table)
1404c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o			to_move++;
1405c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o
1406c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o	if (to_move == 0)
1407c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		return 0;
1408c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o
14093b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o	if (rfs->progress) {
14103b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		retval = rfs->progress(rfs, E2_RSZ_MOVE_ITABLE_PASS,
14113b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o				       0, to_move);
14123b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o		if (retval)
14133b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o			goto errout;
14143b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o	}
141563b44fbe303ea00118cbe24cbbcde351a9bc0aacTheodore Ts'o
1416a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	rfs->old_fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
1417a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o
14181333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o	for (i=0; i < max_groups; i++) {
1419ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o		old_blk = rfs->old_fs->group_desc[i].bg_inode_table;
1420ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o		new_blk = fs->group_desc[i].bg_inode_table;
1421ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o		diff = new_blk - old_blk;
1422052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o
142380c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#ifdef RESIZE2FS_DEBUG
142405e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o		if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE)
1425f35fd3d5eeb3e35660ea87adbc170978c3cdf9e3Theodore Ts'o			printf("Itable move group %d block %u->%u (diff %d)\n",
1426ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o			       i, old_blk, new_blk, diff);
142780c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#endif
1428052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o
142905e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o		if (!diff)
1430052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o			continue;
1431052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o
1432ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o		retval = io_channel_read_blk(fs->io, old_blk,
143305e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o					     fs->inode_blocks_per_group,
143405e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o					     rfs->itable_buf);
1435052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		if (retval)
1436a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			goto errout;
143705e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o		/*
143805e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o		 * The end of the inode table segment often contains
1439a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		 * all zeros, and we're often only moving the inode
1440a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		 * table down a block or two.  If so, we can optimize
1441a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		 * things by not rewriting blocks that we know to be zero
1442a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		 * already.
144305e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o		 */
14442787276ec59e1d52087d307bc30446d088ec65bcTheodore Ts'o		for (cp = rfs->itable_buf+size-1, n=0; n < size; n++, cp--)
144505e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o			if (*cp)
144605e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o				break;
144705e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o		n = n >> EXT2_BLOCK_SIZE_BITS(fs->super);
144880c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#ifdef RESIZE2FS_DEBUG
144905e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o		if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE)
1450f35fd3d5eeb3e35660ea87adbc170978c3cdf9e3Theodore Ts'o			printf("%d blocks of zeros...\n", n);
145180c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#endif
145205e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o		num = fs->inode_blocks_per_group;
145305e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o		if (n > diff)
145405e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o			num -= n;
145505e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o
1456ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o		retval = io_channel_write_blk(fs->io, new_blk,
145705e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o					      num, rfs->itable_buf);
1458052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		if (retval) {
1459ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o			io_channel_write_blk(fs->io, old_blk,
146005e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o					     num, rfs->itable_buf);
1461a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			goto errout;
1462052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		}
146305e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o		if (n > diff) {
146405e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o			retval = io_channel_write_blk(fs->io,
1465ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o			      old_blk + fs->inode_blocks_per_group,
1466a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o			      diff, (rfs->itable_buf +
1467a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				     (fs->inode_blocks_per_group - diff) *
1468a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				     fs->blocksize));
146905e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o			if (retval)
1470a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o				goto errout;
1471c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o		}
147264ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o
147364ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o		for (blk = rfs->old_fs->group_desc[i].bg_inode_table, j=0;
147464ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o		     j < fs->inode_blocks_per_group ; j++, blk++)
147564ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o			ext2fs_unmark_block_bitmap(fs->block_map, blk);
147664ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o
1477a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		rfs->old_fs->group_desc[i].bg_inode_table = new_blk;
1478a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		ext2fs_mark_super_dirty(rfs->old_fs);
147964ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o		ext2fs_flush(rfs->old_fs);
148064ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o
1481a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		if (rfs->progress) {
14823b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o			retval = rfs->progress(rfs, E2_RSZ_MOVE_ITABLE_PASS,
14833b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o					       ++moved, to_move);
14843b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o			if (retval)
14853b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o				goto errout;
1486a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o		}
1487052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	}
148864ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o	mark_table_blocks(fs, fs->block_map);
1489a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o	ext2fs_flush(fs);
149080c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#ifdef RESIZE2FS_DEBUG
149105e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o	if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE)
1492f35fd3d5eeb3e35660ea87adbc170978c3cdf9e3Theodore Ts'o		printf("Inode table move finished.\n");
149380c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#endif
1494052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	return 0;
1495052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o
1496a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'oerrout:
1497052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	return retval;
1498052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o}
1499052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o
1500052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o/*
15019213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o * Fix the resize inode
15029213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o */
15039213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'ostatic errcode_t fix_resize_inode(ext2_filsys fs)
15049213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o{
15059213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	struct ext2_inode	inode;
15069213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	errcode_t		retval;
15079213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	char *			block_buf;
15089213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
15099213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	if (!(fs->super->s_feature_compat &
15109213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	      EXT2_FEATURE_COMPAT_RESIZE_INODE))
15119213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		return 0;
15129213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
15139213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	retval = ext2fs_get_mem(fs->blocksize, &block_buf);
15149213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	if (retval) goto errout;
15159213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
15169213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
15179213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	if (retval) goto errout;
15189213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
15199213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	inode.i_blocks = fs->blocksize/512;
15209213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
15219213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	retval = ext2fs_write_inode(fs, EXT2_RESIZE_INO, &inode);
15229213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	if (retval) goto errout;
15239213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
15249213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	if (!inode.i_block[EXT2_DIND_BLOCK]) {
15259213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		/*
15269213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		 * Avoid zeroing out block #0; that's rude.  This
15279213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		 * should never happen anyway since the filesystem
15289213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		 * should be fsck'ed and we assume it is consistent.
15299213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		 */
15309213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		fprintf(stderr,
1531f35fd3d5eeb3e35660ea87adbc170978c3cdf9e3Theodore Ts'o			_("Should never happen: resize inode corrupt!\n"));
15329213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		exit(1);
15339213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	}
15349213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
15359213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	memset(block_buf, 0, fs->blocksize);
15369213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
15379213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	retval = io_channel_write_blk(fs->io, inode.i_block[EXT2_DIND_BLOCK],
15389213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o				      1, block_buf);
15399213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	if (retval) goto errout;
15409213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
15419213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	retval = ext2fs_create_resize_inode(fs);
15429213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	if (retval)
15439213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		goto errout;
15449213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
15459213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'oerrout:
15469213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	if (block_buf)
15479213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o		ext2fs_free_mem(&block_buf);
15489213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o	return retval;
15499213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o}
15509213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o
15519213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o/*
1552052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * Finally, recalculate the summary information
1553052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o */
1554052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'ostatic errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs)
1555052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o{
1556dfcdc32f8d6623a35a9e66f503c535e4081b7266Theodore Ts'o	blk_t		blk;
1557dfcdc32f8d6623a35a9e66f503c535e4081b7266Theodore Ts'o	ext2_ino_t	ino;
1558544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	unsigned int	group = 0;
1559544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	unsigned int	count = 0;
1560dfcdc32f8d6623a35a9e66f503c535e4081b7266Theodore Ts'o	int		total_free = 0;
1561dfcdc32f8d6623a35a9e66f503c535e4081b7266Theodore Ts'o	int		group_free = 0;
1562052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o
1563052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	/*
1564052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	 * First calculate the block statistics
1565052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	 */
1566052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	for (blk = fs->super->s_first_data_block;
1567052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	     blk < fs->super->s_blocks_count; blk++) {
1568052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		if (!ext2fs_fast_test_block_bitmap(fs->block_map, blk)) {
1569052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o			group_free++;
1570052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o			total_free++;
1571052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		}
1572052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		count++;
1573052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		if ((count == fs->super->s_blocks_per_group) ||
1574052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		    (blk == fs->super->s_blocks_count-1)) {
1575052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o			fs->group_desc[group++].bg_free_blocks_count =
1576052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o				group_free;
1577052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o			count = 0;
1578052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o			group_free = 0;
1579052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		}
1580052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	}
1581052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	fs->super->s_free_blocks_count = total_free;
1582052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o
1583052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	/*
1584052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	 * Next, calculate the inode statistics
1585052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	 */
1586052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	group_free = 0;
1587052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	total_free = 0;
1588052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	count = 0;
1589052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	group = 0;
15905830d6be9c33e23bb20c339036083e6e4fa6795eEric Sandeen
15915830d6be9c33e23bb20c339036083e6e4fa6795eEric Sandeen	/* Protect loop from wrap-around if s_inodes_count maxed */
15925830d6be9c33e23bb20c339036083e6e4fa6795eEric Sandeen	for (ino = 1; ino <= fs->super->s_inodes_count && ino > 0; ino++) {
1593052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		if (!ext2fs_fast_test_inode_bitmap(fs->inode_map, ino)) {
1594052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o			group_free++;
1595052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o			total_free++;
1596052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		}
1597052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		count++;
1598052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		if ((count == fs->super->s_inodes_per_group) ||
1599052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		    (ino == fs->super->s_inodes_count)) {
1600052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o			fs->group_desc[group++].bg_free_inodes_count =
1601052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o				group_free;
1602052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o			count = 0;
1603052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o			group_free = 0;
1604052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o		}
1605052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	}
1606052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	fs->super->s_free_inodes_count = total_free;
1607052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	ext2fs_mark_super_dirty(fs);
1608052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o	return 0;
1609052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o}
1610