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