• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 Theodore 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 
44 static void fix_uninit_block_bitmaps(ext2_filsys fs);
45 static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size);
46 static errcode_t blocks_to_move(ext2_resize_t rfs);
47 static errcode_t block_mover(ext2_resize_t rfs);
48 static errcode_t inode_scan_and_fix(ext2_resize_t rfs);
49 static errcode_t inode_ref_fix(ext2_resize_t rfs);
50 static errcode_t move_itables(ext2_resize_t rfs);
51 static errcode_t fix_resize_inode(ext2_filsys fs);
52 static errcode_t resize2fs_calculate_summary_stats(ext2_filsys fs);
53 static errcode_t fix_sb_journal_backup(ext2_filsys fs);
54 static errcode_t mark_table_blocks(ext2_filsys fs,
55 				   ext2fs_block_bitmap bmap);
56 static errcode_t clear_sparse_super2_last_group(ext2_resize_t rfs);
57 static errcode_t reserve_sparse_super2_last_group(ext2_resize_t rfs,
58 						 ext2fs_block_bitmap meta_bmap);
59 static errcode_t resize_group_descriptors(ext2_resize_t rfs, blk64_t new_size);
60 static errcode_t move_bg_metadata(ext2_resize_t rfs);
61 static errcode_t zero_high_bits_in_inodes(ext2_resize_t rfs);
62 
63 /*
64  * Some helper functions to check if a block is in a metadata area
65  */
is_block_bm(ext2_filsys fs,unsigned int grp,blk64_t blk)66 static inline int is_block_bm(ext2_filsys fs, unsigned int grp, blk64_t blk)
67 {
68 	return blk == ext2fs_block_bitmap_loc(fs, grp);
69 }
70 
is_inode_bm(ext2_filsys fs,unsigned int grp,blk64_t blk)71 static inline int is_inode_bm(ext2_filsys fs, unsigned int grp, blk64_t blk)
72 {
73 	return blk == ext2fs_inode_bitmap_loc(fs, grp);
74 }
75 
is_inode_tb(ext2_filsys fs,unsigned int grp,blk64_t blk)76 static int is_inode_tb(ext2_filsys fs, unsigned int grp, blk64_t blk)
77 {
78 	return blk >= ext2fs_inode_table_loc(fs, grp) &&
79 	       blk < (ext2fs_inode_table_loc(fs, grp) +
80 		      fs->inode_blocks_per_group);
81 }
82 
83 /* Some bigalloc helper macros which are more succinct... */
84 #define B2C(x)	EXT2FS_B2C(fs, (x))
85 #define C2B(x)	EXT2FS_C2B(fs, (x))
86 #define EQ_CLSTR(x, y) (B2C(x) == B2C(y))
87 #define LE_CLSTR(x, y) (B2C(x) <= B2C(y))
88 #define LT_CLSTR(x, y) (B2C(x) <  B2C(y))
89 #define GE_CLSTR(x, y) (B2C(x) >= B2C(y))
90 #define GT_CLSTR(x, y) (B2C(x) >  B2C(y))
91 
92 static int lazy_itable_init;
93 
94 /*
95  * This is the top-level routine which does the dirty deed....
96  */
resize_fs(ext2_filsys fs,blk64_t * new_size,int flags,errcode_t (* progress)(ext2_resize_t rfs,int pass,unsigned long cur,unsigned long max_val))97 errcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, int flags,
98 	    errcode_t (*progress)(ext2_resize_t rfs, int pass,
99 					  unsigned long cur,
100 					  unsigned long max_val))
101 {
102 	ext2_resize_t	rfs;
103 	errcode_t	retval;
104 	struct resource_track	rtrack, overall_track;
105 
106 	/*
107 	 * Create the data structure
108 	 */
109 	retval = ext2fs_get_mem(sizeof(struct ext2_resize_struct), &rfs);
110 	if (retval)
111 		return retval;
112 
113 	memset(rfs, 0, sizeof(struct ext2_resize_struct));
114 	fs->priv_data = rfs;
115 	rfs->old_fs = fs;
116 	rfs->flags = flags;
117 	rfs->itable_buf	 = 0;
118 	rfs->progress = progress;
119 
120 	init_resource_track(&overall_track, "overall resize2fs", fs->io);
121 	init_resource_track(&rtrack, "read_bitmaps", fs->io);
122 	retval = ext2fs_read_bitmaps(fs);
123 	if (retval)
124 		goto errout;
125 	print_resource_track(rfs, &rtrack, fs->io);
126 
127 	fs->super->s_state |= EXT2_ERROR_FS;
128 	ext2fs_mark_super_dirty(fs);
129 	ext2fs_flush(fs);
130 
131 	init_resource_track(&rtrack, "fix_uninit_block_bitmaps 1", fs->io);
132 	fix_uninit_block_bitmaps(fs);
133 	print_resource_track(rfs, &rtrack, fs->io);
134 	retval = ext2fs_dup_handle(fs, &rfs->new_fs);
135 	if (retval)
136 		goto errout;
137 
138 	init_resource_track(&rtrack, "resize_group_descriptors", fs->io);
139 	retval = resize_group_descriptors(rfs, *new_size);
140 	if (retval)
141 		goto errout;
142 	print_resource_track(rfs, &rtrack, fs->io);
143 
144 	init_resource_track(&rtrack, "move_bg_metadata", fs->io);
145 	retval = move_bg_metadata(rfs);
146 	if (retval)
147 		goto errout;
148 	print_resource_track(rfs, &rtrack, fs->io);
149 
150 	init_resource_track(&rtrack, "zero_high_bits_in_metadata", fs->io);
151 	retval = zero_high_bits_in_inodes(rfs);
152 	if (retval)
153 		goto errout;
154 	print_resource_track(rfs, &rtrack, fs->io);
155 
156 	init_resource_track(&rtrack, "adjust_superblock", fs->io);
157 	retval = adjust_superblock(rfs, *new_size);
158 	if (retval)
159 		goto errout;
160 	print_resource_track(rfs, &rtrack, fs->io);
161 
162 	init_resource_track(&rtrack, "fix_uninit_block_bitmaps 2", fs->io);
163 	fix_uninit_block_bitmaps(rfs->new_fs);
164 	print_resource_track(rfs, &rtrack, fs->io);
165 	/* Clear the block bitmap uninit flag for the last block group */
166 	ext2fs_bg_flags_clear(rfs->new_fs, rfs->new_fs->group_desc_count - 1,
167 			     EXT2_BG_BLOCK_UNINIT);
168 
169 	*new_size = ext2fs_blocks_count(rfs->new_fs->super);
170 
171 	init_resource_track(&rtrack, "blocks_to_move", fs->io);
172 	retval = blocks_to_move(rfs);
173 	if (retval)
174 		goto errout;
175 	print_resource_track(rfs, &rtrack, fs->io);
176 
177 #ifdef RESIZE2FS_DEBUG
178 	if (rfs->flags & RESIZE_DEBUG_BMOVE)
179 		printf("Number of free blocks: %llu/%llu, Needed: %llu\n",
180 		       (unsigned long long) ext2fs_free_blocks_count(rfs->old_fs->super),
181 		       (unsigned long long) ext2fs_free_blocks_count(rfs->new_fs->super),
182 		       (unsigned long long) rfs->needed_blocks);
183 #endif
184 
185 	init_resource_track(&rtrack, "block_mover", fs->io);
186 	retval = block_mover(rfs);
187 	if (retval)
188 		goto errout;
189 	print_resource_track(rfs, &rtrack, fs->io);
190 
191 	init_resource_track(&rtrack, "inode_scan_and_fix", fs->io);
192 	retval = inode_scan_and_fix(rfs);
193 	if (retval)
194 		goto errout;
195 	print_resource_track(rfs, &rtrack, fs->io);
196 
197 	init_resource_track(&rtrack, "inode_ref_fix", fs->io);
198 	retval = inode_ref_fix(rfs);
199 	if (retval)
200 		goto errout;
201 	print_resource_track(rfs, &rtrack, fs->io);
202 
203 	init_resource_track(&rtrack, "move_itables", fs->io);
204 	retval = move_itables(rfs);
205 	if (retval)
206 		goto errout;
207 	print_resource_track(rfs, &rtrack, fs->io);
208 
209 	retval = clear_sparse_super2_last_group(rfs);
210 	if (retval)
211 		goto errout;
212 
213 	init_resource_track(&rtrack, "calculate_summary_stats", fs->io);
214 	retval = resize2fs_calculate_summary_stats(rfs->new_fs);
215 	if (retval)
216 		goto errout;
217 	print_resource_track(rfs, &rtrack, fs->io);
218 
219 	init_resource_track(&rtrack, "fix_resize_inode", fs->io);
220 	retval = fix_resize_inode(rfs->new_fs);
221 	if (retval)
222 		goto errout;
223 	print_resource_track(rfs, &rtrack, fs->io);
224 
225 	init_resource_track(&rtrack, "fix_sb_journal_backup", fs->io);
226 	retval = fix_sb_journal_backup(rfs->new_fs);
227 	if (retval)
228 		goto errout;
229 	print_resource_track(rfs, &rtrack, fs->io);
230 
231 	retval = ext2fs_set_gdt_csum(rfs->new_fs);
232 	if (retval)
233 		goto errout;
234 
235 	rfs->new_fs->super->s_state &= ~EXT2_ERROR_FS;
236 	rfs->new_fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
237 
238 	print_resource_track(rfs, &overall_track, fs->io);
239 	retval = ext2fs_close_free(&rfs->new_fs);
240 	if (retval)
241 		goto errout;
242 
243 	rfs->flags = flags;
244 
245 	ext2fs_free(rfs->old_fs);
246 	rfs->old_fs = NULL;
247 	if (rfs->itable_buf)
248 		ext2fs_free_mem(&rfs->itable_buf);
249 	if (rfs->reserve_blocks)
250 		ext2fs_free_block_bitmap(rfs->reserve_blocks);
251 	if (rfs->move_blocks)
252 		ext2fs_free_block_bitmap(rfs->move_blocks);
253 	ext2fs_free_mem(&rfs);
254 
255 	return 0;
256 
257 errout:
258 	if (rfs->new_fs) {
259 		ext2fs_free(rfs->new_fs);
260 		rfs->new_fs = NULL;
261 	}
262 	if (rfs->itable_buf)
263 		ext2fs_free_mem(&rfs->itable_buf);
264 	ext2fs_free_mem(&rfs);
265 	return retval;
266 }
267 
268 /* Keep the size of the group descriptor region constant */
adjust_reserved_gdt_blocks(ext2_filsys old_fs,ext2_filsys fs)269 static void adjust_reserved_gdt_blocks(ext2_filsys old_fs, ext2_filsys fs)
270 {
271 	if (ext2fs_has_feature_resize_inode(fs->super) &&
272 	    (old_fs->desc_blocks != fs->desc_blocks)) {
273 		int new;
274 
275 		new = ((int) fs->super->s_reserved_gdt_blocks) +
276 			(old_fs->desc_blocks - fs->desc_blocks);
277 		if (new < 0)
278 			new = 0;
279 		if (new > (int) fs->blocksize/4)
280 			new = fs->blocksize/4;
281 		fs->super->s_reserved_gdt_blocks = new;
282 	}
283 }
284 
285 /* Toggle 64bit mode */
resize_group_descriptors(ext2_resize_t rfs,blk64_t new_size)286 static errcode_t resize_group_descriptors(ext2_resize_t rfs, blk64_t new_size)
287 {
288 	void *o, *n, *new_group_desc;
289 	dgrp_t i;
290 	int copy_size;
291 	errcode_t retval;
292 
293 	if (!(rfs->flags & (RESIZE_DISABLE_64BIT | RESIZE_ENABLE_64BIT)))
294 		return 0;
295 
296 	if (new_size != ext2fs_blocks_count(rfs->new_fs->super) ||
297 	    ext2fs_blocks_count(rfs->new_fs->super) >= (1ULL << 32) ||
298 	    (rfs->flags & RESIZE_DISABLE_64BIT &&
299 	     rfs->flags & RESIZE_ENABLE_64BIT))
300 		return EXT2_ET_INVALID_ARGUMENT;
301 
302 	if (rfs->flags & RESIZE_DISABLE_64BIT) {
303 		ext2fs_clear_feature_64bit(rfs->new_fs->super);
304 		rfs->new_fs->super->s_desc_size = EXT2_MIN_DESC_SIZE;
305 	} else if (rfs->flags & RESIZE_ENABLE_64BIT) {
306 		ext2fs_set_feature_64bit(rfs->new_fs->super);
307 		rfs->new_fs->super->s_desc_size = EXT2_MIN_DESC_SIZE_64BIT;
308 	}
309 
310 	if (EXT2_DESC_SIZE(rfs->old_fs->super) ==
311 	    EXT2_DESC_SIZE(rfs->new_fs->super))
312 		return 0;
313 
314 	o = rfs->new_fs->group_desc;
315 	rfs->new_fs->desc_blocks = ext2fs_div_ceil(
316 			rfs->old_fs->group_desc_count,
317 			EXT2_DESC_PER_BLOCK(rfs->new_fs->super));
318 	retval = ext2fs_get_arrayzero(rfs->new_fs->desc_blocks,
319 				      rfs->old_fs->blocksize, &new_group_desc);
320 	if (retval)
321 		return retval;
322 
323 	n = new_group_desc;
324 
325 	if (EXT2_DESC_SIZE(rfs->old_fs->super) <=
326 	    EXT2_DESC_SIZE(rfs->new_fs->super))
327 		copy_size = EXT2_DESC_SIZE(rfs->old_fs->super);
328 	else
329 		copy_size = EXT2_DESC_SIZE(rfs->new_fs->super);
330 	for (i = 0; i < rfs->old_fs->group_desc_count; i++) {
331 		memcpy(n, o, copy_size);
332 		n = (char *)n + EXT2_DESC_SIZE(rfs->new_fs->super);
333 		o = (char *)o + EXT2_DESC_SIZE(rfs->old_fs->super);
334 	}
335 
336 	ext2fs_free_mem(&rfs->new_fs->group_desc);
337 	rfs->new_fs->group_desc = new_group_desc;
338 
339 	for (i = 0; i < rfs->old_fs->group_desc_count; i++)
340 		ext2fs_group_desc_csum_set(rfs->new_fs, i);
341 
342 	adjust_reserved_gdt_blocks(rfs->old_fs, rfs->new_fs);
343 
344 	return 0;
345 }
346 
347 /* Move bitmaps/inode tables out of the way. */
move_bg_metadata(ext2_resize_t rfs)348 static errcode_t move_bg_metadata(ext2_resize_t rfs)
349 {
350 	dgrp_t i;
351 	blk64_t b, c, d, old_desc_blocks, new_desc_blocks, j;
352 	ext2fs_block_bitmap old_map, new_map;
353 	int old, new;
354 	errcode_t retval;
355 	int cluster_ratio;
356 
357 	if (!(rfs->flags & (RESIZE_DISABLE_64BIT | RESIZE_ENABLE_64BIT)))
358 		return 0;
359 
360 	retval = ext2fs_allocate_block_bitmap(rfs->old_fs, "oldfs", &old_map);
361 	if (retval)
362 		return retval;
363 
364 	retval = ext2fs_allocate_block_bitmap(rfs->new_fs, "newfs", &new_map);
365 	if (retval)
366 		goto out;
367 
368 	if (ext2fs_has_feature_meta_bg(rfs->old_fs->super)) {
369 		old_desc_blocks = rfs->old_fs->super->s_first_meta_bg;
370 		new_desc_blocks = rfs->new_fs->super->s_first_meta_bg;
371 	} else {
372 		old_desc_blocks = rfs->old_fs->desc_blocks +
373 				rfs->old_fs->super->s_reserved_gdt_blocks;
374 		new_desc_blocks = rfs->new_fs->desc_blocks +
375 				rfs->new_fs->super->s_reserved_gdt_blocks;
376 	}
377 
378 	/* Construct bitmaps of super/descriptor blocks in old and new fs */
379 	for (i = 0; i < rfs->old_fs->group_desc_count; i++) {
380 		retval = ext2fs_super_and_bgd_loc2(rfs->old_fs, i, &b, &c, &d,
381 						   NULL);
382 		if (retval)
383 			goto out;
384 		if (b)
385 			ext2fs_mark_block_bitmap2(old_map, b);
386 		for (j = 0; c != 0 && j < old_desc_blocks; j++)
387 			ext2fs_mark_block_bitmap2(old_map, c + j);
388 		if (d)
389 			ext2fs_mark_block_bitmap2(old_map, d);
390 
391 		retval = ext2fs_super_and_bgd_loc2(rfs->new_fs, i, &b, &c, &d,
392 						   NULL);
393 		if (retval)
394 			goto out;
395 		if (b)
396 			ext2fs_mark_block_bitmap2(new_map, b);
397 		for (j = 0; c != 0 && j < new_desc_blocks; j++)
398 			ext2fs_mark_block_bitmap2(new_map, c + j);
399 		if (d)
400 			ext2fs_mark_block_bitmap2(new_map, d);
401 	}
402 
403 	cluster_ratio = EXT2FS_CLUSTER_RATIO(rfs->new_fs);
404 
405 	/* Find changes in block allocations for bg metadata */
406 	for (b = EXT2FS_B2C(rfs->old_fs,
407 			    rfs->old_fs->super->s_first_data_block);
408 	     b < ext2fs_blocks_count(rfs->new_fs->super);
409 	     b += cluster_ratio) {
410 		old = ext2fs_test_block_bitmap2(old_map, b);
411 		new = ext2fs_test_block_bitmap2(new_map, b);
412 
413 		if (old && !new) {
414 			/* mark old_map, unmark new_map */
415 			if (cluster_ratio == 1)
416 				ext2fs_unmark_block_bitmap2(
417 						rfs->new_fs->block_map, b);
418 		} else if (!old && new)
419 			; /* unmark old_map, mark new_map */
420 		else {
421 			ext2fs_unmark_block_bitmap2(old_map, b);
422 			ext2fs_unmark_block_bitmap2(new_map, b);
423 		}
424 	}
425 
426 	/*
427 	 * new_map now shows blocks that have been newly allocated.
428 	 * old_map now shows blocks that have been newly freed.
429 	 */
430 
431 	/*
432 	 * Move any conflicting bitmaps and inode tables.  Ensure that we
433 	 * don't try to free clusters associated with bitmaps or tables.
434 	 */
435 	for (i = 0; i < rfs->old_fs->group_desc_count; i++) {
436 		b = ext2fs_block_bitmap_loc(rfs->new_fs, i);
437 		if (ext2fs_test_block_bitmap2(new_map, b))
438 			ext2fs_block_bitmap_loc_set(rfs->new_fs, i, 0);
439 		else if (ext2fs_test_block_bitmap2(old_map, b))
440 			ext2fs_unmark_block_bitmap2(old_map, b);
441 
442 		b = ext2fs_inode_bitmap_loc(rfs->new_fs, i);
443 		if (ext2fs_test_block_bitmap2(new_map, b))
444 			ext2fs_inode_bitmap_loc_set(rfs->new_fs, i, 0);
445 		else if (ext2fs_test_block_bitmap2(old_map, b))
446 			ext2fs_unmark_block_bitmap2(old_map, b);
447 
448 		c = ext2fs_inode_table_loc(rfs->new_fs, i);
449 		for (b = 0;
450 		     b < rfs->new_fs->inode_blocks_per_group;
451 		     b++) {
452 			if (ext2fs_test_block_bitmap2(new_map, b + c))
453 				ext2fs_inode_table_loc_set(rfs->new_fs, i, 0);
454 			else if (ext2fs_test_block_bitmap2(old_map, b + c))
455 				ext2fs_unmark_block_bitmap2(old_map, b + c);
456 		}
457 	}
458 
459 	/* Free unused clusters */
460 	for (b = 0;
461 	     cluster_ratio > 1 && b < ext2fs_blocks_count(rfs->new_fs->super);
462 	     b += cluster_ratio)
463 		if (ext2fs_test_block_bitmap2(old_map, b))
464 			ext2fs_unmark_block_bitmap2(rfs->new_fs->block_map, b);
465 out:
466 	if (old_map)
467 		ext2fs_free_block_bitmap(old_map);
468 	if (new_map)
469 		ext2fs_free_block_bitmap(new_map);
470 	return retval;
471 }
472 
473 /* Zero out the high bits of extent fields */
zero_high_bits_in_extents(ext2_filsys fs,ext2_ino_t ino,struct ext2_inode * inode)474 static errcode_t zero_high_bits_in_extents(ext2_filsys fs, ext2_ino_t ino,
475 				 struct ext2_inode *inode)
476 {
477 	ext2_extent_handle_t	handle;
478 	struct ext2fs_extent	extent;
479 	int			op = EXT2_EXTENT_ROOT;
480 	errcode_t		errcode;
481 
482 	if (!(inode->i_flags & EXT4_EXTENTS_FL))
483 		return 0;
484 
485 	errcode = ext2fs_extent_open(fs, ino, &handle);
486 	if (errcode)
487 		return errcode;
488 
489 	while (1) {
490 		errcode = ext2fs_extent_get(handle, op, &extent);
491 		if (errcode)
492 			break;
493 
494 		op = EXT2_EXTENT_NEXT_SIB;
495 
496 		if (extent.e_pblk > (1ULL << 32)) {
497 			extent.e_pblk &= (1ULL << 32) - 1;
498 			errcode = ext2fs_extent_replace(handle, 0, &extent);
499 			if (errcode)
500 				break;
501 		}
502 	}
503 
504 	/* Ok if we run off the end */
505 	if (errcode == EXT2_ET_EXTENT_NO_NEXT)
506 		errcode = 0;
507 	ext2fs_extent_free(handle);
508 	return errcode;
509 }
510 
511 /* Zero out the high bits of inodes. */
zero_high_bits_in_inodes(ext2_resize_t rfs)512 static errcode_t zero_high_bits_in_inodes(ext2_resize_t rfs)
513 {
514 	ext2_filsys	fs = rfs->old_fs;
515 	int length = EXT2_INODE_SIZE(fs->super);
516 	struct ext2_inode *inode = NULL;
517 	ext2_inode_scan	scan = NULL;
518 	errcode_t	retval;
519 	ext2_ino_t	ino;
520 
521 	if (!(rfs->flags & (RESIZE_DISABLE_64BIT | RESIZE_ENABLE_64BIT)))
522 		return 0;
523 
524 	if (fs->super->s_creator_os == EXT2_OS_HURD)
525 		return 0;
526 
527 	retval = ext2fs_open_inode_scan(fs, 0, &scan);
528 	if (retval)
529 		return retval;
530 
531 	retval = ext2fs_get_mem(length, &inode);
532 	if (retval)
533 		goto out;
534 
535 	do {
536 		retval = ext2fs_get_next_inode_full(scan, &ino, inode, length);
537 		if (retval)
538 			goto out;
539 		if (!ino)
540 			break;
541 		if (!ext2fs_test_inode_bitmap2(fs->inode_map, ino))
542 			continue;
543 
544 		/*
545 		 * Here's how we deal with high block number fields:
546 		 *
547 		 *  - i_size_high has been been written out with i_size_lo
548 		 *    since the ext2 days, so no conversion is needed.
549 		 *
550 		 *  - i_blocks_hi is guarded by both the huge_file feature and
551 		 *    inode flags and has always been written out with
552 		 *    i_blocks_lo if the feature is set.  The field is only
553 		 *    ever read if both feature and inode flag are set, so
554 		 *    we don't need to zero it now.
555 		 *
556 		 *  - i_file_acl_high can be uninitialized, so zero it if
557 		 *    it isn't already.
558 		 */
559 		if (inode->osd2.linux2.l_i_file_acl_high) {
560 			inode->osd2.linux2.l_i_file_acl_high = 0;
561 			retval = ext2fs_write_inode_full(fs, ino, inode,
562 							 length);
563 			if (retval)
564 				goto out;
565 		}
566 
567 		retval = zero_high_bits_in_extents(fs, ino, inode);
568 		if (retval)
569 			goto out;
570 	} while (ino);
571 
572 out:
573 	if (inode)
574 		ext2fs_free_mem(&inode);
575 	if (scan)
576 		ext2fs_close_inode_scan(scan);
577 	return retval;
578 }
579 
580 /*
581  * Clean up the bitmaps for uninitialized bitmaps
582  */
fix_uninit_block_bitmaps(ext2_filsys fs)583 static void fix_uninit_block_bitmaps(ext2_filsys fs)
584 {
585 	blk64_t		blk, lblk;
586 	dgrp_t		g;
587 	unsigned int	i;
588 
589 	if (!ext2fs_has_group_desc_csum(fs))
590 		return;
591 
592 	for (g=0; g < fs->group_desc_count; g++) {
593 		if (!(ext2fs_bg_flags_test(fs, g, EXT2_BG_BLOCK_UNINIT)))
594 			continue;
595 
596 		blk = ext2fs_group_first_block2(fs, g);
597 		lblk = ext2fs_group_last_block2(fs, g);
598 		ext2fs_unmark_block_bitmap_range2(fs->block_map, blk,
599 						  lblk - blk + 1);
600 
601 		ext2fs_reserve_super_and_bgd(fs, g, fs->block_map);
602 		ext2fs_mark_block_bitmap2(fs->block_map,
603 					  ext2fs_block_bitmap_loc(fs, g));
604 		ext2fs_mark_block_bitmap2(fs->block_map,
605 					  ext2fs_inode_bitmap_loc(fs, g));
606 		for (i = 0, blk = ext2fs_inode_table_loc(fs, g);
607 		     i < fs->inode_blocks_per_group;
608 		     i++, blk++)
609 			ext2fs_mark_block_bitmap2(fs->block_map, blk);
610 	}
611 }
612 
613 /* --------------------------------------------------------------------
614  *
615  * Resize processing, phase 1.
616  *
617  * In this phase we adjust the in-memory superblock information, and
618  * initialize any new parts of the inode table.  The new parts of the
619  * inode table are created in virgin disk space, so we can abort here
620  * without any side effects.
621  * --------------------------------------------------------------------
622  */
623 
624 /*
625  * If the group descriptor's bitmap and inode table blocks are valid,
626  * release them in the new filesystem data structure, and mark them as
627  * reserved so the old inode table blocks don't get overwritten.
628  */
free_gdp_blocks(ext2_filsys fs,ext2fs_block_bitmap reserve_blocks,ext2_filsys old_fs,dgrp_t group)629 static errcode_t free_gdp_blocks(ext2_filsys fs,
630 				 ext2fs_block_bitmap reserve_blocks,
631 				 ext2_filsys old_fs,
632 				 dgrp_t group)
633 {
634 	blk64_t		blk;
635 	unsigned int	j;
636 	dgrp_t		i;
637 	ext2fs_block_bitmap bg_map = NULL;
638 	errcode_t	retval = 0;
639 	dgrp_t		count = old_fs->group_desc_count - fs->group_desc_count;
640 
641 	/* If bigalloc, don't free metadata living in the same cluster */
642 	if (EXT2FS_CLUSTER_RATIO(fs) > 1) {
643 		retval = ext2fs_allocate_block_bitmap(fs, "bgdata", &bg_map);
644 		if (retval)
645 			goto out;
646 
647 		retval = mark_table_blocks(fs, bg_map);
648 		if (retval)
649 			goto out;
650 	}
651 
652 	for (i = group; i < group + count; i++) {
653 		blk = ext2fs_block_bitmap_loc(old_fs, i);
654 		if (blk &&
655 		    (blk < ext2fs_blocks_count(fs->super)) &&
656 		    !(bg_map && ext2fs_test_block_bitmap2(bg_map, blk))) {
657 			ext2fs_block_alloc_stats2(fs, blk, -1);
658 			ext2fs_mark_block_bitmap2(reserve_blocks, blk);
659 		}
660 
661 		blk = ext2fs_inode_bitmap_loc(old_fs, i);
662 		if (blk &&
663 		    (blk < ext2fs_blocks_count(fs->super)) &&
664 		    !(bg_map && ext2fs_test_block_bitmap2(bg_map, blk))) {
665 			ext2fs_block_alloc_stats2(fs, blk, -1);
666 			ext2fs_mark_block_bitmap2(reserve_blocks, blk);
667 		}
668 
669 		blk = ext2fs_inode_table_loc(old_fs, i);
670 		for (j = 0;
671 		     j < fs->inode_blocks_per_group; j++, blk++) {
672 			if (blk >= ext2fs_blocks_count(fs->super) ||
673 			    (bg_map && ext2fs_test_block_bitmap2(bg_map, blk)))
674 				continue;
675 			ext2fs_block_alloc_stats2(fs, blk, -1);
676 			ext2fs_mark_block_bitmap2(reserve_blocks, blk);
677 		}
678 	}
679 
680 out:
681 	if (bg_map)
682 		ext2fs_free_block_bitmap(bg_map);
683 	return retval;
684 }
685 
686 /*
687  * This routine is shared by the online and offline resize routines.
688  * All of the information which is adjusted in memory is done here.
689  */
adjust_fs_info(ext2_filsys fs,ext2_filsys old_fs,ext2fs_block_bitmap reserve_blocks,blk64_t new_size)690 errcode_t adjust_fs_info(ext2_filsys fs, ext2_filsys old_fs,
691 			 ext2fs_block_bitmap reserve_blocks, blk64_t new_size)
692 {
693 	errcode_t	retval;
694 	blk64_t		overhead = 0;
695 	blk64_t		rem;
696 	blk64_t		blk, group_block;
697 	blk64_t		real_end;
698 	blk64_t		old_numblocks, numblocks, adjblocks;
699 	unsigned long	i, j, old_desc_blocks;
700 	unsigned int	meta_bg, meta_bg_size;
701 	int		has_super, csum_flag, has_bg;
702 	unsigned long long new_inodes;	/* u64 to check for overflow */
703 	double		percent;
704 
705 	ext2fs_blocks_count_set(fs->super, new_size);
706 	fs->super->s_overhead_clusters = 0;
707 
708 retry:
709 	fs->group_desc_count = ext2fs_div64_ceil(ext2fs_blocks_count(fs->super) -
710 				       fs->super->s_first_data_block,
711 				       EXT2_BLOCKS_PER_GROUP(fs->super));
712 	if (fs->group_desc_count == 0)
713 		return EXT2_ET_TOOSMALL;
714 	fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count,
715 					  EXT2_DESC_PER_BLOCK(fs->super));
716 
717 	/*
718 	 * Overhead is the number of bookkeeping blocks per group.  It
719 	 * includes the superblock backup, the group descriptor
720 	 * backups, the inode bitmap, the block bitmap, and the inode
721 	 * table.
722 	 */
723 	overhead = (int) (2 + fs->inode_blocks_per_group);
724 
725 	has_bg = 0;
726 	if (ext2fs_has_feature_sparse_super2(fs->super)) {
727 		/*
728 		 * We have to do this manually since
729 		 * super->s_backup_bgs hasn't been set up yet.
730 		 */
731 		if (fs->group_desc_count == 2)
732 			has_bg = fs->super->s_backup_bgs[0] != 0;
733 		else
734 			has_bg = fs->super->s_backup_bgs[1] != 0;
735 	} else
736 		has_bg = ext2fs_bg_has_super(fs, fs->group_desc_count - 1);
737 	if (has_bg)
738 		overhead += 1 + fs->desc_blocks +
739 			fs->super->s_reserved_gdt_blocks;
740 
741 	/*
742 	 * See if the last group is big enough to support the
743 	 * necessary data structures.  If not, we need to get rid of
744 	 * it.
745 	 */
746 	rem = (ext2fs_blocks_count(fs->super) - fs->super->s_first_data_block) %
747 		fs->super->s_blocks_per_group;
748 	if ((fs->group_desc_count == 1) && rem && (rem < overhead))
749 		return EXT2_ET_TOOSMALL;
750 	if ((fs->group_desc_count > 1) && rem && (rem < overhead+50)) {
751 		ext2fs_blocks_count_set(fs->super,
752 					ext2fs_blocks_count(fs->super) - rem);
753 		goto retry;
754 	}
755 	/*
756 	 * Adjust the number of inodes
757 	 */
758 	new_inodes =(unsigned long long) fs->super->s_inodes_per_group * fs->group_desc_count;
759 	if (new_inodes > ~0U) {
760 		fprintf(stderr, _("inodes (%llu) must be less than %u\n"),
761 			(unsigned long long) new_inodes, ~0U);
762 		return EXT2_ET_TOO_MANY_INODES;
763 	}
764 	fs->super->s_inodes_count = fs->super->s_inodes_per_group *
765 		fs->group_desc_count;
766 
767 	/*
768 	 * Adjust the number of free blocks
769 	 */
770 	blk = ext2fs_blocks_count(old_fs->super);
771 	if (blk > ext2fs_blocks_count(fs->super))
772 		ext2fs_free_blocks_count_set(fs->super,
773 			ext2fs_free_blocks_count(fs->super) -
774 			(blk - ext2fs_blocks_count(fs->super)));
775 	else
776 		ext2fs_free_blocks_count_set(fs->super,
777 			ext2fs_free_blocks_count(fs->super) +
778 			(ext2fs_blocks_count(fs->super) - blk));
779 
780 	/*
781 	 * Adjust the number of reserved blocks
782 	 */
783 	percent = (ext2fs_r_blocks_count(old_fs->super) * 100.0) /
784 		ext2fs_blocks_count(old_fs->super);
785 	ext2fs_r_blocks_count_set(fs->super,
786 				  (percent * ext2fs_blocks_count(fs->super) /
787 				   100.0));
788 
789 	/*
790 	 * Adjust the bitmaps for size
791 	 */
792 	retval = ext2fs_resize_inode_bitmap2(fs->super->s_inodes_count,
793 					    fs->super->s_inodes_count,
794 					    fs->inode_map);
795 	if (retval) goto errout;
796 
797 	real_end = EXT2_GROUPS_TO_BLOCKS(fs->super, fs->group_desc_count) - 1 +
798 		fs->super->s_first_data_block;
799 	retval = ext2fs_resize_block_bitmap2(new_size - 1,
800 					     real_end, fs->block_map);
801 	if (retval) goto errout;
802 
803 	/*
804 	 * If we are growing the file system, also grow the size of
805 	 * the reserve_blocks bitmap
806 	 */
807 	if (reserve_blocks && new_size > ext2fs_blocks_count(old_fs->super)) {
808 		retval = ext2fs_resize_block_bitmap2(new_size - 1,
809 						     real_end, reserve_blocks);
810 		if (retval) goto errout;
811 	}
812 
813 	/*
814 	 * Reallocate the group descriptors as necessary.
815 	 */
816 	if (EXT2_DESC_SIZE(old_fs->super) == EXT2_DESC_SIZE(fs->super) &&
817 	    old_fs->desc_blocks != fs->desc_blocks) {
818 		retval = ext2fs_resize_mem(old_fs->desc_blocks *
819 					   fs->blocksize,
820 					   fs->desc_blocks * fs->blocksize,
821 					   &fs->group_desc);
822 		if (retval)
823 			goto errout;
824 		if (fs->desc_blocks > old_fs->desc_blocks)
825 			memset((char *) fs->group_desc +
826 			       (old_fs->desc_blocks * fs->blocksize), 0,
827 			       (fs->desc_blocks - old_fs->desc_blocks) *
828 			       fs->blocksize);
829 	}
830 
831 	/*
832 	 * If the resize_inode feature is set, and we are changing the
833 	 * number of descriptor blocks, then adjust
834 	 * s_reserved_gdt_blocks if possible to avoid needing to move
835 	 * the inode table either now or in the future.
836 	 *
837 	 * Note: If we're converting to 64bit mode, we did this earlier.
838 	 */
839 	if (EXT2_DESC_SIZE(old_fs->super) == EXT2_DESC_SIZE(fs->super))
840 		adjust_reserved_gdt_blocks(old_fs, fs);
841 
842 	if (ext2fs_has_feature_meta_bg(fs->super) &&
843 	    (fs->super->s_first_meta_bg > fs->desc_blocks)) {
844 		ext2fs_clear_feature_meta_bg(fs->super);
845 		fs->super->s_first_meta_bg = 0;
846 	}
847 
848 	/*
849 	 * Update the location of the backup superblocks if the
850 	 * sparse_super2 feature is enabled.
851 	 */
852 	if (ext2fs_has_feature_sparse_super2(fs->super)) {
853 		dgrp_t last_bg = fs->group_desc_count - 1;
854 		dgrp_t old_last_bg = old_fs->group_desc_count - 1;
855 
856 		if (last_bg > old_last_bg) {
857 			if (old_fs->group_desc_count == 1)
858 				fs->super->s_backup_bgs[0] = 1;
859 			if ((old_fs->group_desc_count < 3 &&
860 			     fs->group_desc_count > 2) ||
861 			    fs->super->s_backup_bgs[1])
862 				fs->super->s_backup_bgs[1] = last_bg;
863 		} else if (last_bg < old_last_bg) {
864 			if (fs->super->s_backup_bgs[0] > last_bg)
865 				fs->super->s_backup_bgs[0] = 0;
866 			if (fs->super->s_backup_bgs[1] > last_bg)
867 				fs->super->s_backup_bgs[1] = 0;
868 			if (last_bg > 1 &&
869 			    old_fs->super->s_backup_bgs[1] == old_last_bg)
870 				fs->super->s_backup_bgs[1] = last_bg;
871 		}
872 	}
873 
874 	/*
875 	 * If we are shrinking the number of block groups, we're done
876 	 * and can exit now.
877 	 */
878 	if (old_fs->group_desc_count > fs->group_desc_count) {
879 		/*
880 		 * Check the block groups that we are chopping off
881 		 * and free any blocks associated with their metadata
882 		 */
883 		retval = free_gdp_blocks(fs, reserve_blocks, old_fs,
884 					 fs->group_desc_count);
885 		goto errout;
886 	}
887 
888 	/*
889 	 * Fix the count of the last (old) block group
890 	 */
891 	old_numblocks = (ext2fs_blocks_count(old_fs->super) -
892 			 old_fs->super->s_first_data_block) %
893 				 old_fs->super->s_blocks_per_group;
894 	if (!old_numblocks)
895 		old_numblocks = old_fs->super->s_blocks_per_group;
896 	if (old_fs->group_desc_count == fs->group_desc_count) {
897 		numblocks = (ext2fs_blocks_count(fs->super) -
898 			     fs->super->s_first_data_block) %
899 			fs->super->s_blocks_per_group;
900 		if (!numblocks)
901 			numblocks = fs->super->s_blocks_per_group;
902 	} else
903 		numblocks = fs->super->s_blocks_per_group;
904 	i = old_fs->group_desc_count - 1;
905 	ext2fs_bg_free_blocks_count_set(fs, i, ext2fs_bg_free_blocks_count(fs, i) + (numblocks - old_numblocks));
906 	ext2fs_group_desc_csum_set(fs, i);
907 
908 	/*
909 	 * If the number of block groups is staying the same, we're
910 	 * done and can exit now.  (If the number block groups is
911 	 * shrinking, we had exited earlier.)
912 	 */
913 	if (old_fs->group_desc_count >= fs->group_desc_count) {
914 		retval = 0;
915 		goto errout;
916 	}
917 
918 	/*
919 	 * Initialize the new block group descriptors
920 	 */
921 	group_block = ext2fs_group_first_block2(fs,
922 						old_fs->group_desc_count);
923 	csum_flag = ext2fs_has_group_desc_csum(fs);
924 	if (getenv("RESIZE2FS_FORCE_LAZY_ITABLE_INIT") ||
925 	    (!getenv("RESIZE2FS_FORCE_ITABLE_INIT") &&
926 	     access("/sys/fs/ext4/features/lazy_itable_init", F_OK) == 0))
927 		lazy_itable_init = 1;
928 	if (ext2fs_has_feature_meta_bg(fs->super))
929 		old_desc_blocks = fs->super->s_first_meta_bg;
930 	else
931 		old_desc_blocks = fs->desc_blocks +
932 			fs->super->s_reserved_gdt_blocks;
933 
934 	/*
935 	 * If we changed the number of block_group descriptor blocks,
936 	 * we need to make sure they are all marked as reserved in the
937 	 * filesystem's block allocation map.
938 	 */
939 	for (i = 0; i < old_fs->group_desc_count; i++)
940 		ext2fs_reserve_super_and_bgd(fs, i, fs->block_map);
941 
942 	for (i = old_fs->group_desc_count;
943 	     i < fs->group_desc_count; i++) {
944 		memset(ext2fs_group_desc(fs, fs->group_desc, i), 0,
945 		       sizeof(struct ext2_group_desc));
946 		adjblocks = 0;
947 
948 		ext2fs_bg_flags_zap(fs, i);
949 		if (csum_flag) {
950 			ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT);
951 			if (!lazy_itable_init)
952 				ext2fs_bg_flags_set(fs, i,
953 						    EXT2_BG_INODE_ZEROED);
954 			ext2fs_bg_itable_unused_set(fs, i,
955 					fs->super->s_inodes_per_group);
956 		}
957 
958 		numblocks = ext2fs_group_blocks_count(fs, i);
959 		if ((i < fs->group_desc_count - 1) && csum_flag)
960 			ext2fs_bg_flags_set(fs, i, EXT2_BG_BLOCK_UNINIT);
961 
962 		has_super = ext2fs_bg_has_super(fs, i);
963 		if (has_super) {
964 			ext2fs_block_alloc_stats2(fs, group_block, +1);
965 			adjblocks++;
966 		}
967 		meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super);
968 		meta_bg = i / meta_bg_size;
969 		if (!ext2fs_has_feature_meta_bg(fs->super) ||
970 		    (meta_bg < fs->super->s_first_meta_bg)) {
971 			if (has_super) {
972 				for (j=0; j < old_desc_blocks; j++)
973 					ext2fs_block_alloc_stats2(fs,
974 						 group_block + 1 + j, +1);
975 				adjblocks += old_desc_blocks;
976 			}
977 		} else {
978 			if (has_super)
979 				has_super = 1;
980 			if (((i % meta_bg_size) == 0) ||
981 			    ((i % meta_bg_size) == 1) ||
982 			    ((i % meta_bg_size) == (meta_bg_size-1)))
983 				ext2fs_block_alloc_stats2(fs,
984 						 group_block + has_super, +1);
985 		}
986 
987 		adjblocks += 2 + fs->inode_blocks_per_group;
988 
989 		numblocks -= adjblocks;
990 		ext2fs_free_blocks_count_set(fs->super,
991 			     ext2fs_free_blocks_count(fs->super) - adjblocks);
992 		fs->super->s_free_inodes_count +=
993 			fs->super->s_inodes_per_group;
994 		ext2fs_bg_free_blocks_count_set(fs, i, numblocks);
995 		ext2fs_bg_free_inodes_count_set(fs, i,
996 						fs->super->s_inodes_per_group);
997 		ext2fs_bg_used_dirs_count_set(fs, i, 0);
998 		ext2fs_group_desc_csum_set(fs, i);
999 
1000 		retval = ext2fs_allocate_group_table(fs, i, 0);
1001 		if (retval) goto errout;
1002 
1003 		group_block += fs->super->s_blocks_per_group;
1004 	}
1005 	retval = 0;
1006 
1007 	/*
1008 	 * Mark all of the metadata blocks as reserved so they won't
1009 	 * get allocated by the call to ext2fs_allocate_group_table()
1010 	 * in blocks_to_move(), where we allocate new blocks to
1011 	 * replace those allocation bitmap and inode table blocks
1012 	 * which have to get relocated to make space for an increased
1013 	 * number of the block group descriptors.
1014 	 */
1015 	if (reserve_blocks)
1016 		mark_table_blocks(fs, reserve_blocks);
1017 
1018 errout:
1019 	return (retval);
1020 }
1021 
1022 /*
1023  * This routine adjusts the superblock and other data structures, both
1024  * in disk as well as in memory...
1025  */
adjust_superblock(ext2_resize_t rfs,blk64_t new_size)1026 static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size)
1027 {
1028 	ext2_filsys	fs = rfs->new_fs;
1029 	int		adj = 0;
1030 	errcode_t	retval;
1031 	blk64_t		group_block;
1032 	unsigned long	i;
1033 	unsigned long	max_group;
1034 
1035 	ext2fs_mark_super_dirty(fs);
1036 	ext2fs_mark_bb_dirty(fs);
1037 	ext2fs_mark_ib_dirty(fs);
1038 
1039 	retval = ext2fs_allocate_block_bitmap(fs, _("reserved blocks"),
1040 					      &rfs->reserve_blocks);
1041 	if (retval)
1042 		return retval;
1043 
1044 	retval = adjust_fs_info(fs, rfs->old_fs, rfs->reserve_blocks, new_size);
1045 	if (retval)
1046 		goto errout;
1047 
1048 	/*
1049 	 * Check to make sure there are enough inodes
1050 	 */
1051 	if ((rfs->old_fs->super->s_inodes_count -
1052 	     rfs->old_fs->super->s_free_inodes_count) >
1053 	    rfs->new_fs->super->s_inodes_count) {
1054 		retval = ENOSPC;
1055 		goto errout;
1056 	}
1057 
1058 	/*
1059 	 * If we are shrinking the number block groups, we're done and
1060 	 * can exit now.
1061 	 */
1062 	if (rfs->old_fs->group_desc_count > fs->group_desc_count) {
1063 		retval = 0;
1064 		goto errout;
1065 	}
1066 
1067 	/*
1068 	 * If the number of block groups is staying the same, we're
1069 	 * done and can exit now.  (If the number block groups is
1070 	 * shrinking, we had exited earlier.)
1071 	 */
1072 	if (rfs->old_fs->group_desc_count >= fs->group_desc_count) {
1073 		retval = 0;
1074 		goto errout;
1075 	}
1076 
1077 	/*
1078 	 * If we are using uninit_bg (aka GDT_CSUM) and the kernel
1079 	 * supports lazy inode initialization, we can skip
1080 	 * initializing the inode table.
1081 	 */
1082 	if (lazy_itable_init && ext2fs_has_group_desc_csum(fs)) {
1083 		retval = 0;
1084 		goto errout;
1085 	}
1086 
1087 	/*
1088 	 * Initialize the inode table
1089 	 */
1090 	retval = ext2fs_get_array(fs->blocksize, fs->inode_blocks_per_group,
1091 				&rfs->itable_buf);
1092 	if (retval)
1093 		goto errout;
1094 
1095 	memset(rfs->itable_buf, 0, fs->blocksize * fs->inode_blocks_per_group);
1096 	group_block = ext2fs_group_first_block2(fs,
1097 						rfs->old_fs->group_desc_count);
1098 	adj = rfs->old_fs->group_desc_count;
1099 	max_group = fs->group_desc_count - adj;
1100 	if (rfs->progress) {
1101 		retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
1102 				       0, max_group);
1103 		if (retval)
1104 			goto errout;
1105 	}
1106 	for (i = rfs->old_fs->group_desc_count;
1107 	     i < fs->group_desc_count; i++) {
1108 		/*
1109 		 * Write out the new inode table
1110 		 */
1111 		retval = ext2fs_zero_blocks2(fs, ext2fs_inode_table_loc(fs, i),
1112 					     fs->inode_blocks_per_group, NULL,
1113 					     NULL);
1114 		if (retval)
1115 			goto errout;
1116 
1117 		io_channel_flush(fs->io);
1118 		if (rfs->progress) {
1119 			retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS,
1120 					       i - adj + 1, max_group);
1121 			if (retval)
1122 				goto errout;
1123 		}
1124 		group_block += fs->super->s_blocks_per_group;
1125 	}
1126 	io_channel_flush(fs->io);
1127 	retval = 0;
1128 
1129 errout:
1130 	return retval;
1131 }
1132 
1133 /* --------------------------------------------------------------------
1134  *
1135  * Resize processing, phase 2.
1136  *
1137  * In this phase we adjust determine which blocks need to be moved, in
1138  * blocks_to_move().  We then copy the blocks to their ultimate new
1139  * destinations using block_mover().  Since we are copying blocks to
1140  * their new locations, again during this pass we can abort without
1141  * any problems.
1142  * --------------------------------------------------------------------
1143  */
1144 
1145 /*
1146  * This helper function creates a block bitmap with all of the
1147  * filesystem meta-data blocks.
1148  */
mark_table_blocks(ext2_filsys fs,ext2fs_block_bitmap bmap)1149 static errcode_t mark_table_blocks(ext2_filsys fs,
1150 				   ext2fs_block_bitmap bmap)
1151 {
1152 	dgrp_t			i;
1153 	blk64_t			blk;
1154 
1155 	for (i = 0; i < fs->group_desc_count; i++) {
1156 		ext2fs_reserve_super_and_bgd(fs, i, bmap);
1157 
1158 		/*
1159 		 * Mark the blocks used for the inode table
1160 		 */
1161 		blk = ext2fs_inode_table_loc(fs, i);
1162 		if (blk)
1163 			ext2fs_mark_block_bitmap_range2(bmap, blk,
1164 						fs->inode_blocks_per_group);
1165 
1166 		/*
1167 		 * Mark block used for the block bitmap
1168 		 */
1169 		blk = ext2fs_block_bitmap_loc(fs, i);
1170 		if (blk)
1171 			ext2fs_mark_block_bitmap2(bmap, blk);
1172 
1173 		/*
1174 		 * Mark block used for the inode bitmap
1175 		 */
1176 		blk = ext2fs_inode_bitmap_loc(fs, i);
1177 		if (blk)
1178 			ext2fs_mark_block_bitmap2(bmap, blk);
1179 	}
1180 	/* Reserve the MMP block */
1181 	if (ext2fs_has_feature_mmp(fs->super) &&
1182 	    fs->super->s_mmp_block > fs->super->s_first_data_block &&
1183 	    fs->super->s_mmp_block < ext2fs_blocks_count(fs->super))
1184 		ext2fs_mark_block_bitmap2(bmap, fs->super->s_mmp_block);
1185 	return 0;
1186 }
1187 
1188 /*
1189  * This function checks to see if a particular block (either a
1190  * superblock or a block group descriptor) overlaps with an inode or
1191  * block bitmap block, or with the inode table.
1192  */
mark_fs_metablock(ext2_resize_t rfs,ext2fs_block_bitmap meta_bmap,int group,blk64_t blk)1193 static void mark_fs_metablock(ext2_resize_t rfs,
1194 			      ext2fs_block_bitmap meta_bmap,
1195 			      int group, blk64_t blk)
1196 {
1197 	ext2_filsys fs = rfs->new_fs;
1198 
1199 	ext2fs_mark_block_bitmap2(rfs->reserve_blocks, blk);
1200 	ext2fs_block_alloc_stats2(fs, blk, +1);
1201 
1202 	/*
1203 	 * Check to see if we overlap with the inode or block bitmap,
1204 	 * or the inode tables.  If not, and the block is in use, then
1205 	 * mark it as a block to be moved.
1206 	 */
1207 	if (is_block_bm(fs, group, blk)) {
1208 		ext2fs_block_bitmap_loc_set(fs, group, 0);
1209 		rfs->needed_blocks++;
1210 		return;
1211 	}
1212 	if (is_inode_bm(fs, group, blk)) {
1213 		ext2fs_inode_bitmap_loc_set(fs, group, 0);
1214 		rfs->needed_blocks++;
1215 		return;
1216 	}
1217 	if (is_inode_tb(fs, group, blk)) {
1218 		ext2fs_inode_table_loc_set(fs, group, 0);
1219 		rfs->needed_blocks++;
1220 		return;
1221 	}
1222 	if (ext2fs_has_feature_flex_bg(fs->super)) {
1223 		dgrp_t i;
1224 
1225 		for (i = 0; i < rfs->old_fs->group_desc_count; i++) {
1226 			if (is_block_bm(fs, i, blk)) {
1227 				ext2fs_block_bitmap_loc_set(fs, i, 0);
1228 				rfs->needed_blocks++;
1229 				return;
1230 			}
1231 			if (is_inode_bm(fs, i, blk)) {
1232 				ext2fs_inode_bitmap_loc_set(fs, i, 0);
1233 				rfs->needed_blocks++;
1234 				return;
1235 			}
1236 			if (is_inode_tb(fs, i, blk)) {
1237 				ext2fs_inode_table_loc_set(fs, i, 0);
1238 				rfs->needed_blocks++;
1239 				return;
1240 			}
1241 		}
1242 	}
1243 
1244 	if (ext2fs_has_group_desc_csum(fs) &&
1245 	    (ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT))) {
1246 		/*
1247 		 * If the block bitmap is uninitialized, which means
1248 		 * nothing other than standard metadata in use.
1249 		 */
1250 		return;
1251 	} else if (blk < ext2fs_blocks_count(rfs->old_fs->super) &&
1252 		   ext2fs_test_block_bitmap2(rfs->old_fs->block_map, blk) &&
1253 		   !ext2fs_test_block_bitmap2(meta_bmap, blk)) {
1254 		ext2fs_mark_block_bitmap2(rfs->move_blocks, blk);
1255 		rfs->needed_blocks++;
1256 	}
1257 }
1258 
1259 
1260 /*
1261  * This routine marks and unmarks reserved blocks in the new block
1262  * bitmap.  It also determines which blocks need to be moved and
1263  * places this information into the move_blocks bitmap.
1264  */
blocks_to_move(ext2_resize_t rfs)1265 static errcode_t blocks_to_move(ext2_resize_t rfs)
1266 {
1267 	unsigned int	j;
1268 	int		has_super;
1269 	dgrp_t		i, max_groups, g;
1270 	blk64_t		blk, group_blk;
1271 	blk64_t		old_blocks, new_blocks, group_end, cluster_freed;
1272 	blk64_t		new_size;
1273 	unsigned int	meta_bg, meta_bg_size;
1274 	errcode_t	retval;
1275 	ext2_filsys 	fs, old_fs;
1276 	ext2fs_block_bitmap	meta_bmap, new_meta_bmap = NULL;
1277 	int		flex_bg;
1278 
1279 	fs = rfs->new_fs;
1280 	old_fs = rfs->old_fs;
1281 	if (ext2fs_blocks_count(old_fs->super) > ext2fs_blocks_count(fs->super))
1282 		fs = rfs->old_fs;
1283 
1284 	retval = ext2fs_allocate_block_bitmap(fs, _("blocks to be moved"),
1285 					      &rfs->move_blocks);
1286 	if (retval)
1287 		return retval;
1288 
1289 	retval = ext2fs_allocate_block_bitmap(fs, _("meta-data blocks"),
1290 					      &meta_bmap);
1291 	if (retval)
1292 		return retval;
1293 
1294 	retval = mark_table_blocks(old_fs, meta_bmap);
1295 	if (retval)
1296 		return retval;
1297 
1298 	fs = rfs->new_fs;
1299 
1300 	/*
1301 	 * If we're shrinking the filesystem, we need to move any
1302 	 * group's metadata blocks (either allocation bitmaps or the
1303 	 * inode table) which are beyond the end of the new
1304 	 * filesystem.
1305 	 */
1306 	new_size = ext2fs_blocks_count(fs->super);
1307 	if (new_size < ext2fs_blocks_count(old_fs->super)) {
1308 		for (g = 0; g < fs->group_desc_count; g++) {
1309 			int realloc = 0;
1310 			/*
1311 			 * ext2fs_allocate_group_table will re-allocate any
1312 			 * metadata blocks whose location is set to zero.
1313 			 */
1314 			if (ext2fs_block_bitmap_loc(fs, g) >= new_size) {
1315 				ext2fs_block_bitmap_loc_set(fs, g, 0);
1316 				realloc = 1;
1317 			}
1318 			if (ext2fs_inode_bitmap_loc(fs, g) >= new_size) {
1319 				ext2fs_inode_bitmap_loc_set(fs, g, 0);
1320 				realloc = 1;
1321 			}
1322 			if ((ext2fs_inode_table_loc(fs, g) +
1323 			     fs->inode_blocks_per_group) > new_size) {
1324 				ext2fs_inode_table_loc_set(fs, g, 0);
1325 				realloc = 1;
1326 			}
1327 
1328 			if (realloc) {
1329 				retval = ext2fs_allocate_group_table(fs, g, 0);
1330 				if (retval)
1331 					return retval;
1332 			}
1333 		}
1334 	}
1335 
1336 	/*
1337 	 * If we're shrinking the filesystem, we need to move all of
1338 	 * the blocks that don't fit any more
1339 	 */
1340 	for (blk = ext2fs_blocks_count(fs->super);
1341 	     blk < ext2fs_blocks_count(old_fs->super); blk++) {
1342 		g = ext2fs_group_of_blk2(fs, blk);
1343 		if (ext2fs_has_group_desc_csum(fs) &&
1344 		    ext2fs_bg_flags_test(old_fs, g, EXT2_BG_BLOCK_UNINIT)) {
1345 			/*
1346 			 * The block bitmap is uninitialized, so skip
1347 			 * to the next block group.
1348 			 */
1349 			blk = ext2fs_group_first_block2(fs, g+1) - 1;
1350 			continue;
1351 		}
1352 		if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) &&
1353 		    !ext2fs_test_block_bitmap2(meta_bmap, blk)) {
1354 			ext2fs_mark_block_bitmap2(rfs->move_blocks, blk);
1355 			rfs->needed_blocks++;
1356 		}
1357 		ext2fs_mark_block_bitmap2(rfs->reserve_blocks, blk);
1358 	}
1359 
1360 	if (ext2fs_has_feature_meta_bg(old_fs->super))
1361 		old_blocks = old_fs->super->s_first_meta_bg;
1362 	else
1363 		old_blocks = old_fs->desc_blocks +
1364 			old_fs->super->s_reserved_gdt_blocks;
1365 	if (ext2fs_has_feature_meta_bg(fs->super))
1366 		new_blocks = fs->super->s_first_meta_bg;
1367 	else
1368 		new_blocks = fs->desc_blocks + fs->super->s_reserved_gdt_blocks;
1369 
1370 	retval = reserve_sparse_super2_last_group(rfs, meta_bmap);
1371 	if (retval)
1372 		goto errout;
1373 
1374 	if (EXT2_DESC_SIZE(rfs->old_fs->super) ==
1375 	    EXT2_DESC_SIZE(rfs->new_fs->super) &&
1376 	    old_blocks == new_blocks) {
1377 		retval = 0;
1378 		goto errout;
1379 	}
1380 
1381 	max_groups = fs->group_desc_count;
1382 	if (max_groups > old_fs->group_desc_count)
1383 		max_groups = old_fs->group_desc_count;
1384 	group_blk = old_fs->super->s_first_data_block;
1385 	/*
1386 	 * If we're reducing the number of descriptor blocks, this
1387 	 * makes life easy.  :-)   We just have to mark some extra
1388 	 * blocks as free.
1389 	 */
1390 	if (old_blocks > new_blocks) {
1391 		if (EXT2FS_CLUSTER_RATIO(fs) > 1) {
1392 			retval = ext2fs_allocate_block_bitmap(fs,
1393 							_("new meta blocks"),
1394 							&new_meta_bmap);
1395 			if (retval)
1396 				goto errout;
1397 
1398 			retval = mark_table_blocks(fs, new_meta_bmap);
1399 			if (retval)
1400 				goto errout;
1401 		}
1402 
1403 		for (i = 0; i < max_groups; i++) {
1404 			if (!ext2fs_bg_has_super(old_fs, i)) {
1405 				group_blk += fs->super->s_blocks_per_group;
1406 				continue;
1407 			}
1408 			group_end = group_blk + 1 + old_blocks;
1409 			for (blk = group_blk + 1 + new_blocks;
1410 			     blk < group_end;) {
1411 				if (new_meta_bmap == NULL ||
1412 				    !ext2fs_test_block_bitmap2(new_meta_bmap,
1413 							       blk)) {
1414 					cluster_freed =
1415 						EXT2FS_CLUSTER_RATIO(fs) -
1416 						(blk &
1417 						 EXT2FS_CLUSTER_MASK(fs));
1418 					if (cluster_freed > group_end - blk)
1419 						cluster_freed = group_end - blk;
1420 					ext2fs_block_alloc_stats2(fs, blk, -1);
1421 					blk += EXT2FS_CLUSTER_RATIO(fs);
1422 					rfs->needed_blocks -= cluster_freed;
1423 					continue;
1424 				}
1425 				rfs->needed_blocks--;
1426 				blk++;
1427 			}
1428 			group_blk += fs->super->s_blocks_per_group;
1429 		}
1430 		retval = 0;
1431 		goto errout;
1432 	}
1433 	/*
1434 	 * If we're increasing the number of descriptor blocks, life
1435 	 * gets interesting....
1436 	 */
1437 	meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super);
1438 	flex_bg = ext2fs_has_feature_flex_bg(fs->super);
1439 	/* first reserve all of the existing fs meta blocks */
1440 	for (i = 0; i < max_groups; i++) {
1441 		has_super = ext2fs_bg_has_super(fs, i);
1442 		if (has_super)
1443 			mark_fs_metablock(rfs, meta_bmap, i, group_blk);
1444 
1445 		meta_bg = i / meta_bg_size;
1446 		if (!ext2fs_has_feature_meta_bg(fs->super) ||
1447 		    (meta_bg < fs->super->s_first_meta_bg)) {
1448 			if (has_super) {
1449 				for (blk = group_blk+1;
1450 				     blk < group_blk + 1 + new_blocks; blk++)
1451 					mark_fs_metablock(rfs, meta_bmap,
1452 							  i, blk);
1453 			}
1454 		} else {
1455 			if (has_super)
1456 				has_super = 1;
1457 			if (((i % meta_bg_size) == 0) ||
1458 			    ((i % meta_bg_size) == 1) ||
1459 			    ((i % meta_bg_size) == (meta_bg_size-1)))
1460 				mark_fs_metablock(rfs, meta_bmap, i,
1461 						  group_blk + has_super);
1462 		}
1463 
1464 		/*
1465 		 * Reserve the existing meta blocks that we know
1466 		 * aren't to be moved.
1467 		 *
1468 		 * For flex_bg file systems, in order to avoid
1469 		 * overwriting fs metadata (especially inode table
1470 		 * blocks) belonging to a different block group when
1471 		 * we are relocating the inode tables, we need to
1472 		 * reserve all existing fs metadata blocks.
1473 		 */
1474 		if (ext2fs_block_bitmap_loc(fs, i))
1475 			ext2fs_mark_block_bitmap2(rfs->reserve_blocks,
1476 				 ext2fs_block_bitmap_loc(fs, i));
1477 		else if (flex_bg && i < old_fs->group_desc_count)
1478 			ext2fs_mark_block_bitmap2(rfs->reserve_blocks,
1479 				 ext2fs_block_bitmap_loc(old_fs, i));
1480 
1481 		if (ext2fs_inode_bitmap_loc(fs, i))
1482 			ext2fs_mark_block_bitmap2(rfs->reserve_blocks,
1483 				 ext2fs_inode_bitmap_loc(fs, i));
1484 		else if (flex_bg && i < old_fs->group_desc_count)
1485 			ext2fs_mark_block_bitmap2(rfs->reserve_blocks,
1486 				 ext2fs_inode_bitmap_loc(old_fs, i));
1487 
1488 		if (ext2fs_inode_table_loc(fs, i))
1489 			ext2fs_mark_block_bitmap_range2(rfs->reserve_blocks,
1490 					ext2fs_inode_table_loc(fs, i),
1491 					fs->inode_blocks_per_group);
1492 		else if (flex_bg && i < old_fs->group_desc_count)
1493 			ext2fs_mark_block_bitmap_range2(rfs->reserve_blocks,
1494 					ext2fs_inode_table_loc(old_fs, i),
1495 					old_fs->inode_blocks_per_group);
1496 
1497 		group_blk += rfs->new_fs->super->s_blocks_per_group;
1498 	}
1499 
1500 	/* Allocate the missing data structures */
1501 	for (i = 0; i < max_groups; i++) {
1502 		if (ext2fs_inode_table_loc(fs, i) &&
1503 		    ext2fs_inode_bitmap_loc(fs, i) &&
1504 		    ext2fs_block_bitmap_loc(fs, i))
1505 			continue;
1506 
1507 		retval = ext2fs_allocate_group_table(fs, i,
1508 						     rfs->reserve_blocks);
1509 		if (retval)
1510 			goto errout;
1511 
1512 		/*
1513 		 * For those structures that have changed, we need to
1514 		 * do bookkeeping.
1515 		 */
1516 		if (ext2fs_block_bitmap_loc(old_fs, i) !=
1517 		    (blk = ext2fs_block_bitmap_loc(fs, i))) {
1518 			ext2fs_block_alloc_stats2(fs, blk, +1);
1519 			if (blk < ext2fs_blocks_count(old_fs->super) &&
1520 			    ext2fs_test_block_bitmap2(old_fs->block_map, blk) &&
1521 			    !ext2fs_test_block_bitmap2(meta_bmap, blk))
1522 				ext2fs_mark_block_bitmap2(rfs->move_blocks,
1523 							 blk);
1524 		}
1525 		if (ext2fs_inode_bitmap_loc(old_fs, i) !=
1526 		    (blk = ext2fs_inode_bitmap_loc(fs, i))) {
1527 			ext2fs_block_alloc_stats2(fs, blk, +1);
1528 			if (blk < ext2fs_blocks_count(old_fs->super) &&
1529 			    ext2fs_test_block_bitmap2(old_fs->block_map, blk) &&
1530 			    !ext2fs_test_block_bitmap2(meta_bmap, blk))
1531 				ext2fs_mark_block_bitmap2(rfs->move_blocks,
1532 							 blk);
1533 		}
1534 
1535 		/*
1536 		 * The inode table, if we need to relocate it, is
1537 		 * handled specially.  We have to reserve the blocks
1538 		 * for both the old and the new inode table, since we
1539 		 * can't have the inode table be destroyed during the
1540 		 * block relocation phase.
1541 		 */
1542 		if (ext2fs_inode_table_loc(fs, i) == ext2fs_inode_table_loc(old_fs, i))
1543 			continue;	/* inode table not moved */
1544 
1545 		rfs->needed_blocks += fs->inode_blocks_per_group;
1546 
1547 		/*
1548 		 * Mark the new inode table as in use in the new block
1549 		 * allocation bitmap, and move any blocks that might
1550 		 * be necessary.
1551 		 */
1552 		for (blk = ext2fs_inode_table_loc(fs, i), j=0;
1553 		     j < fs->inode_blocks_per_group ; j++, blk++) {
1554 			ext2fs_block_alloc_stats2(fs, blk, +1);
1555 			if (blk < ext2fs_blocks_count(old_fs->super) &&
1556 			    ext2fs_test_block_bitmap2(old_fs->block_map, blk) &&
1557 			    !ext2fs_test_block_bitmap2(meta_bmap, blk))
1558 				ext2fs_mark_block_bitmap2(rfs->move_blocks,
1559 							 blk);
1560 		}
1561 
1562 		/*
1563 		 * Make sure the old inode table is reserved in the
1564 		 * block reservation bitmap.
1565 		 */
1566 		for (blk = ext2fs_inode_table_loc(rfs->old_fs, i), j=0;
1567 		     j < fs->inode_blocks_per_group ; j++, blk++)
1568 			ext2fs_mark_block_bitmap2(rfs->reserve_blocks, blk);
1569 	}
1570 	retval = 0;
1571 
1572 errout:
1573 	if (new_meta_bmap)
1574 		ext2fs_free_block_bitmap(new_meta_bmap);
1575 	if (meta_bmap)
1576 		ext2fs_free_block_bitmap(meta_bmap);
1577 
1578 	return retval;
1579 }
1580 
1581 /*
1582  * This helper function tries to allocate a new block.  We try to
1583  * avoid hitting the original group descriptor blocks at least at
1584  * first, since we want to make it possible to recover from a badly
1585  * aborted resize operation as much as possible.
1586  *
1587  * In the future, I may further modify this routine to balance out
1588  * where we get the new blocks across the various block groups.
1589  * Ideally we would allocate blocks that corresponded with the block
1590  * group of the containing inode, and keep contiguous blocks
1591  * together.  However, this very difficult to do efficiently, since we
1592  * don't have the necessary information up front.
1593  */
1594 
1595 #define AVOID_OLD	1
1596 #define DESPERATION	2
1597 
init_block_alloc(ext2_resize_t rfs)1598 static void init_block_alloc(ext2_resize_t rfs)
1599 {
1600 	rfs->alloc_state = AVOID_OLD;
1601 	rfs->new_blk = rfs->new_fs->super->s_first_data_block;
1602 #if 0
1603 	/* HACK for testing */
1604 	if (ext2fs_blocks_count(rfs->new_fs->super) >
1605 	    ext2fs_blocks_count(rfs->old_fs->super))
1606 		rfs->new_blk = ext2fs_blocks_count(rfs->old_fs->super);
1607 #endif
1608 }
1609 
get_new_block(ext2_resize_t rfs)1610 static blk64_t get_new_block(ext2_resize_t rfs)
1611 {
1612 	ext2_filsys	fs = rfs->new_fs;
1613 
1614 	while (1) {
1615 		if (rfs->new_blk >= ext2fs_blocks_count(fs->super)) {
1616 			if (rfs->alloc_state == DESPERATION)
1617 				return 0;
1618 
1619 #ifdef RESIZE2FS_DEBUG
1620 			if (rfs->flags & RESIZE_DEBUG_BMOVE)
1621 				printf("Going into desperation mode "
1622 				       "for block allocations\n");
1623 #endif
1624 			rfs->alloc_state = DESPERATION;
1625 			rfs->new_blk = fs->super->s_first_data_block;
1626 			continue;
1627 		}
1628 		if (ext2fs_test_block_bitmap2(fs->block_map, rfs->new_blk) ||
1629 		    ext2fs_test_block_bitmap2(rfs->reserve_blocks,
1630 					     rfs->new_blk) ||
1631 		    ((rfs->alloc_state == AVOID_OLD) &&
1632 		     (rfs->new_blk < ext2fs_blocks_count(rfs->old_fs->super)) &&
1633 		     ext2fs_test_block_bitmap2(rfs->old_fs->block_map,
1634 					      rfs->new_blk))) {
1635 			rfs->new_blk++;
1636 			continue;
1637 		}
1638 		return rfs->new_blk;
1639 	}
1640 }
1641 
resize2fs_get_alloc_block(ext2_filsys fs,blk64_t goal EXT2FS_ATTR ((unused)),blk64_t * ret)1642 static errcode_t resize2fs_get_alloc_block(ext2_filsys fs,
1643 					   blk64_t goal EXT2FS_ATTR((unused)),
1644 					   blk64_t *ret)
1645 {
1646 	ext2_resize_t rfs = (ext2_resize_t) fs->priv_data;
1647 	blk64_t blk;
1648 	int group;
1649 
1650 	blk = get_new_block(rfs);
1651 	if (!blk)
1652 		return ENOSPC;
1653 
1654 #ifdef RESIZE2FS_DEBUG
1655 	if (rfs->flags & 0xF)
1656 		printf("get_alloc_block allocating %llu\n",
1657 		       (unsigned long long) blk);
1658 #endif
1659 
1660 	ext2fs_mark_block_bitmap2(rfs->old_fs->block_map, blk);
1661 	ext2fs_mark_block_bitmap2(rfs->new_fs->block_map, blk);
1662 
1663 	group = ext2fs_group_of_blk2(rfs->old_fs, blk);
1664 	ext2fs_clear_block_uninit(rfs->old_fs, group);
1665 	group = ext2fs_group_of_blk2(rfs->new_fs, blk);
1666 	ext2fs_clear_block_uninit(rfs->new_fs, group);
1667 
1668 	*ret = (blk64_t) blk;
1669 	return 0;
1670 }
1671 
block_mover(ext2_resize_t rfs)1672 static errcode_t block_mover(ext2_resize_t rfs)
1673 {
1674 	blk64_t			blk, old_blk, new_blk;
1675 	ext2_filsys		fs = rfs->new_fs;
1676 	ext2_filsys		old_fs = rfs->old_fs;
1677 	errcode_t		retval;
1678 	__u64			c, size;
1679 	int			to_move, moved;
1680 	ext2_badblocks_list	badblock_list = 0;
1681 	int			bb_modified = 0;
1682 
1683 	fs->get_alloc_block = resize2fs_get_alloc_block;
1684 	old_fs->get_alloc_block = resize2fs_get_alloc_block;
1685 
1686 	retval = ext2fs_read_bb_inode(old_fs, &badblock_list);
1687 	if (retval)
1688 		return retval;
1689 
1690 	new_blk = fs->super->s_first_data_block;
1691 	if (!rfs->itable_buf) {
1692 		retval = ext2fs_get_array(fs->blocksize,
1693 					fs->inode_blocks_per_group,
1694 					&rfs->itable_buf);
1695 		if (retval)
1696 			return retval;
1697 	}
1698 	retval = ext2fs_create_extent_table(&rfs->bmap, 0);
1699 	if (retval)
1700 		return retval;
1701 
1702 	/*
1703 	 * The first step is to figure out where all of the blocks
1704 	 * will go.
1705 	 */
1706 	to_move = moved = 0;
1707 	init_block_alloc(rfs);
1708 	for (blk = B2C(old_fs->super->s_first_data_block);
1709 	     blk < ext2fs_blocks_count(old_fs->super);
1710 	     blk += EXT2FS_CLUSTER_RATIO(fs)) {
1711 		if (!ext2fs_test_block_bitmap2(old_fs->block_map, blk))
1712 			continue;
1713 		if (!ext2fs_test_block_bitmap2(rfs->move_blocks, blk))
1714 			continue;
1715 		if (ext2fs_badblocks_list_test(badblock_list, blk)) {
1716 			ext2fs_badblocks_list_del(badblock_list, blk);
1717 			bb_modified++;
1718 			continue;
1719 		}
1720 
1721 		new_blk = get_new_block(rfs);
1722 		if (!new_blk) {
1723 			retval = ENOSPC;
1724 			goto errout;
1725 		}
1726 		ext2fs_block_alloc_stats2(fs, new_blk, +1);
1727 		ext2fs_add_extent_entry(rfs->bmap, B2C(blk), B2C(new_blk));
1728 		to_move++;
1729 	}
1730 
1731 	if (to_move == 0) {
1732 		if (rfs->bmap) {
1733 			ext2fs_free_extent_table(rfs->bmap);
1734 			rfs->bmap = 0;
1735 		}
1736 		retval = 0;
1737 		goto errout;
1738 	}
1739 
1740 	/*
1741 	 * Step two is to actually move the blocks
1742 	 */
1743 	retval =  ext2fs_iterate_extent(rfs->bmap, 0, 0, 0);
1744 	if (retval) goto errout;
1745 
1746 	if (rfs->progress) {
1747 		retval = (rfs->progress)(rfs, E2_RSZ_BLOCK_RELOC_PASS,
1748 					 0, to_move);
1749 		if (retval)
1750 			goto errout;
1751 	}
1752 	while (1) {
1753 		retval = ext2fs_iterate_extent(rfs->bmap, &old_blk, &new_blk, &size);
1754 		if (retval) goto errout;
1755 		if (!size)
1756 			break;
1757 		old_blk = C2B(old_blk);
1758 		new_blk = C2B(new_blk);
1759 		size = C2B(size);
1760 #ifdef RESIZE2FS_DEBUG
1761 		if (rfs->flags & RESIZE_DEBUG_BMOVE)
1762 			printf("Moving %llu blocks %llu->%llu\n",
1763 			       (unsigned long long) size,
1764 			       (unsigned long long) old_blk,
1765 			       (unsigned long long) new_blk);
1766 #endif
1767 		do {
1768 			c = size;
1769 			if (c > fs->inode_blocks_per_group)
1770 				c = fs->inode_blocks_per_group;
1771 			retval = io_channel_read_blk64(fs->io, old_blk, c,
1772 						       rfs->itable_buf);
1773 			if (retval) goto errout;
1774 			retval = io_channel_write_blk64(fs->io, new_blk, c,
1775 							rfs->itable_buf);
1776 			if (retval) goto errout;
1777 			size -= c;
1778 			new_blk += c;
1779 			old_blk += c;
1780 			moved += c;
1781 			if (rfs->progress) {
1782 				io_channel_flush(fs->io);
1783 				retval = (rfs->progress)(rfs,
1784 						E2_RSZ_BLOCK_RELOC_PASS,
1785 						moved, to_move);
1786 				if (retval)
1787 					goto errout;
1788 			}
1789 		} while (size > 0);
1790 		io_channel_flush(fs->io);
1791 	}
1792 
1793 errout:
1794 	if (badblock_list) {
1795 		if (!retval && bb_modified)
1796 			retval = ext2fs_update_bb_inode(old_fs,
1797 							badblock_list);
1798 		ext2fs_badblocks_list_free(badblock_list);
1799 	}
1800 	return retval;
1801 }
1802 
1803 
1804 /* --------------------------------------------------------------------
1805  *
1806  * Resize processing, phase 3
1807  *
1808  * --------------------------------------------------------------------
1809  */
1810 
1811 
1812 /*
1813  * The extent translation table is stored in clusters so we need to
1814  * take special care when mapping a source block number to its
1815  * destination block number.
1816  */
extent_translate(ext2_filsys fs,ext2_extent extent,__u64 old_loc)1817 static __u64 extent_translate(ext2_filsys fs, ext2_extent extent, __u64 old_loc)
1818 {
1819 	__u64 new_block = C2B(ext2fs_extent_translate(extent, B2C(old_loc)));
1820 
1821 	if (new_block != 0)
1822 		new_block += old_loc & (EXT2FS_CLUSTER_RATIO(fs) - 1);
1823 	return new_block;
1824 }
1825 
1826 struct process_block_struct {
1827 	ext2_resize_t 		rfs;
1828 	ext2_ino_t		ino;
1829 	ext2_ino_t		old_ino;
1830 	struct ext2_inode *	inode;
1831 	errcode_t		error;
1832 	int			is_dir;
1833 	int			changed;
1834 	int			has_extents;
1835 };
1836 
process_block(ext2_filsys fs,blk64_t * block_nr,e2_blkcnt_t blockcnt,blk64_t ref_block EXT2FS_ATTR ((unused)),int ref_offset EXT2FS_ATTR ((unused)),void * priv_data)1837 static int process_block(ext2_filsys fs, blk64_t	*block_nr,
1838 			 e2_blkcnt_t blockcnt,
1839 			 blk64_t ref_block EXT2FS_ATTR((unused)),
1840 			 int ref_offset EXT2FS_ATTR((unused)), void *priv_data)
1841 {
1842 	struct process_block_struct *pb;
1843 	errcode_t	retval;
1844 	blk64_t		block, new_block;
1845 	int		ret = 0;
1846 
1847 	pb = (struct process_block_struct *) priv_data;
1848 	block = *block_nr;
1849 	if (pb->rfs->bmap) {
1850 		new_block = extent_translate(fs, pb->rfs->bmap, block);
1851 		if (new_block) {
1852 			*block_nr = new_block;
1853 			ret |= BLOCK_CHANGED;
1854 			pb->changed = 1;
1855 #ifdef RESIZE2FS_DEBUG
1856 			if (pb->rfs->flags & RESIZE_DEBUG_BMOVE)
1857 				printf("ino=%u, blockcnt=%lld, %llu->%llu\n",
1858 				       pb->old_ino, (long long) blockcnt,
1859 				       (unsigned long long) block,
1860 				       (unsigned long long) new_block);
1861 #endif
1862 			block = new_block;
1863 		}
1864 	}
1865 
1866 	if (pb->is_dir) {
1867 		retval = ext2fs_add_dir_block2(fs->dblist, pb->ino,
1868 					       block, (int) blockcnt);
1869 		if (retval) {
1870 			pb->error = retval;
1871 			ret |= BLOCK_ABORT;
1872 		}
1873 	}
1874 	return ret;
1875 }
1876 
1877 /*
1878  * Progress callback
1879  */
progress_callback(ext2_filsys fs,ext2_inode_scan scan EXT2FS_ATTR ((unused)),dgrp_t group,void * priv_data)1880 static errcode_t progress_callback(ext2_filsys fs,
1881 				   ext2_inode_scan scan EXT2FS_ATTR((unused)),
1882 				   dgrp_t group, void * priv_data)
1883 {
1884 	ext2_resize_t rfs = (ext2_resize_t) priv_data;
1885 	errcode_t		retval;
1886 
1887 	/*
1888 	 * This check is to protect against old ext2 libraries.  It
1889 	 * shouldn't be needed against new libraries.
1890 	 */
1891 	if ((group+1) == 0)
1892 		return 0;
1893 
1894 	if (rfs->progress) {
1895 		io_channel_flush(fs->io);
1896 		retval = (rfs->progress)(rfs, E2_RSZ_INODE_SCAN_PASS,
1897 					 group+1, fs->group_desc_count);
1898 		if (retval)
1899 			return retval;
1900 	}
1901 
1902 	return 0;
1903 }
1904 
migrate_ea_block(ext2_resize_t rfs,ext2_ino_t ino,struct ext2_inode * inode,int * changed)1905 static errcode_t migrate_ea_block(ext2_resize_t rfs, ext2_ino_t ino,
1906 				  struct ext2_inode *inode, int *changed)
1907 {
1908 	char *buf = NULL;
1909 	blk64_t new_block;
1910 	errcode_t err = 0;
1911 
1912 	/* No EA block or no remapping?  Quit early. */
1913 	if (ext2fs_file_acl_block(rfs->old_fs, inode) == 0 || !rfs->bmap)
1914 		return 0;
1915 	new_block = extent_translate(rfs->old_fs, rfs->bmap,
1916 		ext2fs_file_acl_block(rfs->old_fs, inode));
1917 	if (new_block == 0)
1918 		return 0;
1919 
1920 	/* Set the new ACL block */
1921 	ext2fs_file_acl_block_set(rfs->old_fs, inode, new_block);
1922 
1923 	/* Update checksum */
1924 	if (ext2fs_has_feature_metadata_csum(rfs->new_fs->super)) {
1925 		err = ext2fs_get_mem(rfs->old_fs->blocksize, &buf);
1926 		if (err)
1927 			return err;
1928 		rfs->old_fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
1929 		err = ext2fs_read_ext_attr3(rfs->old_fs, new_block, buf, ino);
1930 		rfs->old_fs->flags &= ~EXT2_FLAG_IGNORE_CSUM_ERRORS;
1931 		if (err)
1932 			goto out;
1933 		err = ext2fs_write_ext_attr3(rfs->old_fs, new_block, buf, ino);
1934 		if (err)
1935 			goto out;
1936 	}
1937 	*changed = 1;
1938 
1939 out:
1940 	ext2fs_free_mem(&buf);
1941 	return err;
1942 }
1943 
quiet_com_err_proc(const char * whoami EXT2FS_ATTR ((unused)),errcode_t code EXT2FS_ATTR ((unused)),const char * fmt EXT2FS_ATTR ((unused)),va_list args EXT2FS_ATTR ((unused)))1944 static void quiet_com_err_proc(const char *whoami EXT2FS_ATTR((unused)),
1945 			       errcode_t code EXT2FS_ATTR((unused)),
1946 			       const char *fmt EXT2FS_ATTR((unused)),
1947 			       va_list args EXT2FS_ATTR((unused)))
1948 {
1949 }
1950 
fix_ea_entries(ext2_extent imap,struct ext2_ext_attr_entry * entry,struct ext2_ext_attr_entry * end,ext2_ino_t last_ino)1951 static int fix_ea_entries(ext2_extent imap, struct ext2_ext_attr_entry *entry,
1952 			  struct ext2_ext_attr_entry *end, ext2_ino_t last_ino)
1953 {
1954 	int modified = 0;
1955 	ext2_ino_t new_ino;
1956 
1957 	while (entry < end && !EXT2_EXT_IS_LAST_ENTRY(entry)) {
1958 		if (entry->e_value_inum > last_ino) {
1959 			new_ino = ext2fs_extent_translate(imap,
1960 							  entry->e_value_inum);
1961 			entry->e_value_inum = new_ino;
1962 			modified = 1;
1963 		}
1964 		entry = EXT2_EXT_ATTR_NEXT(entry);
1965 	}
1966 	return modified;
1967 }
1968 
fix_ea_ibody_entries(ext2_extent imap,struct ext2_inode_large * inode,int inode_size,ext2_ino_t last_ino)1969 static int fix_ea_ibody_entries(ext2_extent imap,
1970 				struct ext2_inode_large *inode, int inode_size,
1971 				ext2_ino_t last_ino)
1972 {
1973 	struct ext2_ext_attr_entry *start, *end;
1974 	__u32 *ea_magic;
1975 
1976 	if (inode->i_extra_isize == 0)
1977 		return 0;
1978 
1979 	ea_magic = (__u32 *)((char *)inode + EXT2_GOOD_OLD_INODE_SIZE +
1980 				inode->i_extra_isize);
1981 	if (*ea_magic != EXT2_EXT_ATTR_MAGIC)
1982 		return 0;
1983 
1984 	start = (struct ext2_ext_attr_entry *)(ea_magic + 1);
1985 	end = (struct ext2_ext_attr_entry *)((char *)inode + inode_size);
1986 
1987 	return fix_ea_entries(imap, start, end, last_ino);
1988 }
1989 
fix_ea_block_entries(ext2_extent imap,char * block_buf,unsigned int blocksize,ext2_ino_t last_ino)1990 static int fix_ea_block_entries(ext2_extent imap, char *block_buf,
1991 				unsigned int blocksize, ext2_ino_t last_ino)
1992 {
1993 	struct ext2_ext_attr_header *header;
1994 	struct ext2_ext_attr_entry *start, *end;
1995 
1996 	header = (struct ext2_ext_attr_header *)block_buf;
1997 	start = (struct ext2_ext_attr_entry *)(header+1);
1998 	end = (struct ext2_ext_attr_entry *)(block_buf + blocksize);
1999 
2000 	return fix_ea_entries(imap, start, end, last_ino);
2001 }
2002 
2003 /* A simple LRU cache to check recently processed blocks. */
2004 struct blk_cache {
2005 	int cursor;
2006 	blk64_t blks[4];
2007 };
2008 
2009 #define BLK_IN_CACHE(b,c) ((b) == (c).blks[0] || (b) == (c).blks[1] || \
2010 			   (b) == (c).blks[2] || (b) == (c).blks[3])
2011 #define BLK_ADD_CACHE(b,c) { 			\
2012 	(c).blks[(c).cursor] = (b);		\
2013 	(c).cursor = ((c).cursor + 1) % 4;	\
2014 }
2015 
fix_ea_inode_refs(ext2_resize_t rfs,struct ext2_inode * inode,char * block_buf,ext2_ino_t last_ino)2016 static errcode_t fix_ea_inode_refs(ext2_resize_t rfs, struct ext2_inode *inode,
2017 				   char *block_buf, ext2_ino_t last_ino)
2018 {
2019 	ext2_filsys	fs = rfs->new_fs;
2020 	ext2_inode_scan	scan = NULL;
2021 	ext2_ino_t	ino;
2022 	int		inode_size = EXT2_INODE_SIZE(fs->super);
2023 	blk64_t		blk;
2024 	int		modified;
2025 	struct blk_cache blk_cache;
2026 	struct ext2_ext_attr_header *header;
2027 	errcode_t		retval;
2028 
2029 	memset(&blk_cache, 0, sizeof(blk_cache));
2030 
2031 	header = (struct ext2_ext_attr_header *)block_buf;
2032 
2033 	retval = ext2fs_open_inode_scan(fs, 0, &scan);
2034 	if (retval)
2035 		goto out;
2036 
2037 	while (1) {
2038 		retval = ext2fs_get_next_inode_full(scan, &ino, inode,
2039 						    inode_size);
2040 		if (retval)
2041 			goto out;
2042 		if (!ino)
2043 			break;
2044 
2045 		if (inode->i_links_count == 0 && ino != EXT2_RESIZE_INO)
2046 			continue; /* inode not in use */
2047 
2048 		if (inode_size != EXT2_GOOD_OLD_INODE_SIZE) {
2049 			modified = fix_ea_ibody_entries(rfs->imap,
2050 					(struct ext2_inode_large *)inode,
2051 					inode_size, last_ino);
2052 			if (modified) {
2053 				retval = ext2fs_write_inode_full(fs, ino, inode,
2054 								 inode_size);
2055 				if (retval)
2056 					goto out;
2057 			}
2058 		}
2059 
2060 		blk = ext2fs_file_acl_block(fs, inode);
2061 		if (blk && !BLK_IN_CACHE(blk, blk_cache)) {
2062 			retval = ext2fs_read_ext_attr3(fs, blk, block_buf, ino);
2063 			if (retval)
2064 				goto out;
2065 
2066 			modified = fix_ea_block_entries(rfs->imap, block_buf,
2067 							fs->blocksize,
2068 							last_ino);
2069 			if (modified) {
2070 				retval = ext2fs_write_ext_attr3(fs, blk,
2071 								block_buf, ino);
2072 				if (retval)
2073 					goto out;
2074 				/*
2075 				 * If refcount is greater than 1, we might see
2076 				 * the same block referenced by other inodes
2077 				 * later.
2078 				 */
2079 				if (header->h_refcount > 1)
2080 					BLK_ADD_CACHE(blk, blk_cache);
2081 			}
2082 		}
2083 	}
2084 	retval = 0;
2085 out:
2086 	if (scan)
2087 		ext2fs_close_inode_scan(scan);
2088 	return retval;
2089 
2090 }
inode_scan_and_fix(ext2_resize_t rfs)2091 static errcode_t inode_scan_and_fix(ext2_resize_t rfs)
2092 {
2093 	struct process_block_struct	pb;
2094 	ext2_ino_t		ino, new_inode;
2095 	struct ext2_inode 	*inode = NULL;
2096 	ext2_inode_scan 	scan = NULL;
2097 	errcode_t		retval;
2098 	char			*block_buf = 0;
2099 	ext2_ino_t		start_to_move;
2100 	int			inode_size;
2101 	int			update_ea_inode_refs = 0;
2102 
2103 	if ((rfs->old_fs->group_desc_count <=
2104 	     rfs->new_fs->group_desc_count) &&
2105 	    !rfs->bmap)
2106 		return 0;
2107 
2108 	set_com_err_hook(quiet_com_err_proc);
2109 
2110 	retval = ext2fs_open_inode_scan(rfs->old_fs, 0, &scan);
2111 	if (retval) goto errout;
2112 
2113 	retval = ext2fs_init_dblist(rfs->old_fs, 0);
2114 	if (retval) goto errout;
2115 	retval = ext2fs_get_array(rfs->old_fs->blocksize, 3, &block_buf);
2116 	if (retval) goto errout;
2117 
2118 	start_to_move = (rfs->new_fs->group_desc_count *
2119 			 rfs->new_fs->super->s_inodes_per_group);
2120 
2121 	if (rfs->progress) {
2122 		retval = (rfs->progress)(rfs, E2_RSZ_INODE_SCAN_PASS,
2123 					 0, rfs->old_fs->group_desc_count);
2124 		if (retval)
2125 			goto errout;
2126 	}
2127 	ext2fs_set_inode_callback(scan, progress_callback, (void *) rfs);
2128 	pb.rfs = rfs;
2129 	pb.inode = inode;
2130 	pb.error = 0;
2131 	new_inode = EXT2_FIRST_INODE(rfs->new_fs->super);
2132 	inode_size = EXT2_INODE_SIZE(rfs->new_fs->super);
2133 	inode = malloc(inode_size);
2134 	if (!inode) {
2135 		retval = ENOMEM;
2136 		goto errout;
2137 	}
2138 	/*
2139 	 * First, copy all of the inodes that need to be moved
2140 	 * elsewhere in the inode table
2141 	 */
2142 	while (1) {
2143 		retval = ext2fs_get_next_inode_full(scan, &ino, inode, inode_size);
2144 		if (retval) goto errout;
2145 		if (!ino)
2146 			break;
2147 
2148 		if (inode->i_links_count == 0 && ino != EXT2_RESIZE_INO)
2149 			continue; /* inode not in use */
2150 
2151 		pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
2152 		pb.changed = 0;
2153 
2154 		/* Remap EA block */
2155 		retval = migrate_ea_block(rfs, ino, inode, &pb.changed);
2156 		if (retval)
2157 			goto errout;
2158 
2159 		new_inode = ino;
2160 		if (ino <= start_to_move)
2161 			goto remap_blocks; /* Don't need to move inode. */
2162 
2163 		/*
2164 		 * Find a new inode.  Now that extents and directory blocks
2165 		 * are tied to the inode number through the checksum, we must
2166 		 * set up the new inode before we start rewriting blocks.
2167 		 */
2168 		retval = ext2fs_new_inode(rfs->new_fs, 0, 0, 0, &new_inode);
2169 		if (retval)
2170 			goto errout;
2171 
2172 		ext2fs_inode_alloc_stats2(rfs->new_fs, new_inode, +1,
2173 					  pb.is_dir);
2174 		/*
2175 		 * i_ctime field in xattr inodes contain a portion of the ref
2176 		 * count, do not overwrite.
2177 		 */
2178 		if (inode->i_flags & EXT4_EA_INODE_FL)
2179 			update_ea_inode_refs = 1;
2180 		else
2181 			inode->i_ctime = time(0);
2182 
2183 		retval = ext2fs_write_inode_full(rfs->old_fs, new_inode,
2184 						inode, inode_size);
2185 		if (retval)
2186 			goto errout;
2187 		pb.changed = 0;
2188 
2189 #ifdef RESIZE2FS_DEBUG
2190 		if (rfs->flags & RESIZE_DEBUG_INODEMAP)
2191 			printf("Inode moved %u->%u\n", ino, new_inode);
2192 #endif
2193 		if (!rfs->imap) {
2194 			retval = ext2fs_create_extent_table(&rfs->imap, 0);
2195 			if (retval)
2196 				goto errout;
2197 		}
2198 		ext2fs_add_extent_entry(rfs->imap, ino, new_inode);
2199 
2200 remap_blocks:
2201 		if (pb.changed)
2202 			retval = ext2fs_write_inode_full(rfs->old_fs,
2203 							 new_inode,
2204 							 inode, inode_size);
2205 		if (retval)
2206 			goto errout;
2207 
2208 		/*
2209 		 * Update inodes to point to new blocks; schedule directory
2210 		 * blocks for inode remapping.  Need to write out dir blocks
2211 		 * with new inode numbers if we have metadata_csum enabled.
2212 		 */
2213 		rfs->old_fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
2214 		if (ext2fs_inode_has_valid_blocks2(rfs->old_fs, inode) &&
2215 		    (rfs->bmap || pb.is_dir)) {
2216 			pb.ino = new_inode;
2217 			pb.old_ino = ino;
2218 			pb.has_extents = inode->i_flags & EXT4_EXTENTS_FL;
2219 			retval = ext2fs_block_iterate3(rfs->old_fs,
2220 						       new_inode, 0, block_buf,
2221 						       process_block, &pb);
2222 			if (retval)
2223 				goto errout;
2224 			if (pb.error) {
2225 				retval = pb.error;
2226 				goto errout;
2227 			}
2228 		} else if ((inode->i_flags & EXT4_INLINE_DATA_FL) &&
2229 			   (rfs->bmap || pb.is_dir)) {
2230 			/* inline data dir; update it too */
2231 			retval = ext2fs_add_dir_block2(rfs->old_fs->dblist,
2232 						       new_inode, 0, 0);
2233 			if (retval)
2234 				goto errout;
2235 		}
2236 
2237 		/* Fix up extent block checksums with the new inode number */
2238 		if (ext2fs_has_feature_metadata_csum(rfs->old_fs->super) &&
2239 		    (inode->i_flags & EXT4_EXTENTS_FL)) {
2240 			retval = ext2fs_fix_extents_checksums(rfs->old_fs,
2241 							      new_inode, NULL);
2242 			if (retval)
2243 				goto errout;
2244 		}
2245 	}
2246 
2247 	if (update_ea_inode_refs &&
2248 	    ext2fs_has_feature_ea_inode(rfs->new_fs->super)) {
2249 		retval = fix_ea_inode_refs(rfs, inode, block_buf,
2250 					   start_to_move);
2251 		if (retval)
2252 			goto errout;
2253 	}
2254 	io_channel_flush(rfs->old_fs->io);
2255 
2256 errout:
2257 	reset_com_err_hook();
2258 	rfs->old_fs->flags &= ~EXT2_FLAG_IGNORE_CSUM_ERRORS;
2259 	if (rfs->bmap) {
2260 		ext2fs_free_extent_table(rfs->bmap);
2261 		rfs->bmap = 0;
2262 	}
2263 	if (scan)
2264 		ext2fs_close_inode_scan(scan);
2265 	if (block_buf)
2266 		ext2fs_free_mem(&block_buf);
2267 	free(inode);
2268 	return retval;
2269 }
2270 
2271 /* --------------------------------------------------------------------
2272  *
2273  * Resize processing, phase 4.
2274  *
2275  * --------------------------------------------------------------------
2276  */
2277 
2278 struct istruct {
2279 	ext2_resize_t rfs;
2280 	errcode_t	err;
2281 	unsigned int	max_dirs;
2282 	unsigned int	num;
2283 };
2284 
check_and_change_inodes(ext2_ino_t dir,int entry EXT2FS_ATTR ((unused)),struct ext2_dir_entry * dirent,int offset,int blocksize EXT2FS_ATTR ((unused)),char * buf EXT2FS_ATTR ((unused)),void * priv_data)2285 static int check_and_change_inodes(ext2_ino_t dir,
2286 				   int entry EXT2FS_ATTR((unused)),
2287 				   struct ext2_dir_entry *dirent, int offset,
2288 				   int	blocksize EXT2FS_ATTR((unused)),
2289 				   char *buf EXT2FS_ATTR((unused)),
2290 				   void *priv_data)
2291 {
2292 	struct istruct *is = (struct istruct *) priv_data;
2293 	struct ext2_inode 	inode;
2294 	ext2_ino_t		new_inode;
2295 	errcode_t		retval;
2296 	int			ret = 0;
2297 
2298 	if (is->rfs->progress && offset == 0) {
2299 		io_channel_flush(is->rfs->old_fs->io);
2300 		is->err = (is->rfs->progress)(is->rfs,
2301 					      E2_RSZ_INODE_REF_UPD_PASS,
2302 					      ++is->num, is->max_dirs);
2303 		if (is->err)
2304 			return DIRENT_ABORT;
2305 	}
2306 
2307 	/*
2308 	 * If we have checksums enabled and the inode wasn't present in the
2309 	 * old fs, then we must rewrite all dir blocks with new checksums.
2310 	 */
2311 	if (ext2fs_has_feature_metadata_csum(is->rfs->old_fs->super) &&
2312 	    !ext2fs_test_inode_bitmap2(is->rfs->old_fs->inode_map, dir))
2313 		ret |= DIRENT_CHANGED;
2314 
2315 	if (!dirent->inode)
2316 		return ret;
2317 
2318 	new_inode = ext2fs_extent_translate(is->rfs->imap, dirent->inode);
2319 
2320 	if (!new_inode)
2321 		return ret;
2322 #ifdef RESIZE2FS_DEBUG
2323 	if (is->rfs->flags & RESIZE_DEBUG_INODEMAP)
2324 		printf("Inode translate (dir=%u, name=%.*s, %u->%u)\n",
2325 		       dir, ext2fs_dirent_name_len(dirent), dirent->name,
2326 		       dirent->inode, new_inode);
2327 #endif
2328 
2329 	dirent->inode = new_inode;
2330 
2331 	/* Update the directory mtime and ctime */
2332 	retval = ext2fs_read_inode(is->rfs->old_fs, dir, &inode);
2333 	if (retval == 0) {
2334 		inode.i_mtime = inode.i_ctime = time(0);
2335 		is->err = ext2fs_write_inode(is->rfs->old_fs, dir, &inode);
2336 		if (is->err)
2337 			return ret | DIRENT_ABORT;
2338 	}
2339 
2340 	return ret | DIRENT_CHANGED;
2341 }
2342 
inode_ref_fix(ext2_resize_t rfs)2343 static errcode_t inode_ref_fix(ext2_resize_t rfs)
2344 {
2345 	errcode_t		retval;
2346 	struct istruct 		is;
2347 
2348 	if (!rfs->imap)
2349 		return 0;
2350 
2351 	/*
2352 	 * Now, we iterate over all of the directories to update the
2353 	 * inode references
2354 	 */
2355 	is.num = 0;
2356 	is.max_dirs = ext2fs_dblist_count2(rfs->old_fs->dblist);
2357 	is.rfs = rfs;
2358 	is.err = 0;
2359 
2360 	if (rfs->progress) {
2361 		retval = (rfs->progress)(rfs, E2_RSZ_INODE_REF_UPD_PASS,
2362 					 0, is.max_dirs);
2363 		if (retval)
2364 			goto errout;
2365 	}
2366 
2367 	rfs->old_fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
2368 	retval = ext2fs_dblist_dir_iterate(rfs->old_fs->dblist,
2369 					   DIRENT_FLAG_INCLUDE_EMPTY, 0,
2370 					   check_and_change_inodes, &is);
2371 	rfs->old_fs->flags &= ~EXT2_FLAG_IGNORE_CSUM_ERRORS;
2372 	if (retval)
2373 		goto errout;
2374 	if (is.err) {
2375 		retval = is.err;
2376 		goto errout;
2377 	}
2378 
2379 	if (rfs->progress && (is.num < is.max_dirs))
2380 		(rfs->progress)(rfs, E2_RSZ_INODE_REF_UPD_PASS,
2381 				is.max_dirs, is.max_dirs);
2382 
2383 errout:
2384 	ext2fs_free_extent_table(rfs->imap);
2385 	rfs->imap = 0;
2386 	return retval;
2387 }
2388 
2389 
2390 /* --------------------------------------------------------------------
2391  *
2392  * Resize processing, phase 5.
2393  *
2394  * In this phase we actually move the inode table around, and then
2395  * update the summary statistics.  This is scary, since aborting here
2396  * will potentially scramble the filesystem.  (We are moving the
2397  * inode tables around in place, and so the potential for lost data,
2398  * or at the very least scrambling the mapping between filenames and
2399  * inode numbers is very high in case of a power failure here.)
2400  * --------------------------------------------------------------------
2401  */
2402 
2403 
2404 /*
2405  * A very scary routine --- this one moves the inode table around!!!
2406  *
2407  * After this you have to use the rfs->new_fs file handle to read and
2408  * write inodes.
2409  */
move_itables(ext2_resize_t rfs)2410 static errcode_t move_itables(ext2_resize_t rfs)
2411 {
2412 	int		n, num, size;
2413 	long long	diff;
2414 	dgrp_t		i, max_groups;
2415 	ext2_filsys	fs = rfs->new_fs;
2416 	char		*cp;
2417 	blk64_t		old_blk, new_blk, blk, cluster_freed;
2418 	errcode_t	retval;
2419 	int		to_move, moved;
2420 	unsigned int	j;
2421 	ext2fs_block_bitmap	new_bmap = NULL;
2422 
2423 	max_groups = fs->group_desc_count;
2424 	if (max_groups > rfs->old_fs->group_desc_count)
2425 		max_groups = rfs->old_fs->group_desc_count;
2426 
2427 	size = fs->blocksize * fs->inode_blocks_per_group;
2428 	if (!rfs->itable_buf) {
2429 		retval = ext2fs_get_mem(size, &rfs->itable_buf);
2430 		if (retval)
2431 			return retval;
2432 	}
2433 
2434 	if (EXT2FS_CLUSTER_RATIO(fs) > 1) {
2435 		retval = ext2fs_allocate_block_bitmap(fs, _("new meta blocks"),
2436 						      &new_bmap);
2437 		if (retval)
2438 			return retval;
2439 
2440 		retval = mark_table_blocks(fs, new_bmap);
2441 		if (retval)
2442 			goto errout;
2443 	}
2444 
2445 	/*
2446 	 * Figure out how many inode tables we need to move
2447 	 */
2448 	to_move = moved = 0;
2449 	for (i=0; i < max_groups; i++)
2450 		if (ext2fs_inode_table_loc(rfs->old_fs, i) !=
2451 		    ext2fs_inode_table_loc(fs, i))
2452 			to_move++;
2453 
2454 	if (to_move == 0) {
2455 		retval = 0;
2456 		goto errout;
2457 	}
2458 
2459 	if (rfs->progress) {
2460 		retval = rfs->progress(rfs, E2_RSZ_MOVE_ITABLE_PASS,
2461 				       0, to_move);
2462 		if (retval)
2463 			goto errout;
2464 	}
2465 
2466 	rfs->old_fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
2467 
2468 	for (i=0; i < max_groups; i++) {
2469 		old_blk = ext2fs_inode_table_loc(rfs->old_fs, i);
2470 		new_blk = ext2fs_inode_table_loc(fs, i);
2471 		diff = new_blk - old_blk;
2472 
2473 #ifdef RESIZE2FS_DEBUG
2474 		if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE)
2475 			printf("Itable move group %d block %llu->%llu (diff %lld)\n",
2476 			       i, (unsigned long long) old_blk,
2477 			       (unsigned long long) new_blk, diff);
2478 #endif
2479 
2480 		if (!diff)
2481 			continue;
2482 		if (diff < 0)
2483 			diff = 0;
2484 
2485 		retval = io_channel_read_blk64(fs->io, old_blk,
2486 					       fs->inode_blocks_per_group,
2487 					       rfs->itable_buf);
2488 		if (retval)
2489 			goto errout;
2490 		/*
2491 		 * The end of the inode table segment often contains
2492 		 * all zeros, and we're often only moving the inode
2493 		 * table down a block or two.  If so, we can optimize
2494 		 * things by not rewriting blocks that we know to be zero
2495 		 * already.
2496 		 */
2497 		for (cp = rfs->itable_buf+size-1, n=0; n < size; n++, cp--)
2498 			if (*cp)
2499 				break;
2500 		n = n >> EXT2_BLOCK_SIZE_BITS(fs->super);
2501 #ifdef RESIZE2FS_DEBUG
2502 		if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE)
2503 			printf("%d blocks of zeros...\n", n);
2504 #endif
2505 		num = fs->inode_blocks_per_group;
2506 		if (n > diff)
2507 			num -= n;
2508 
2509 		retval = io_channel_write_blk64(fs->io, new_blk,
2510 						num, rfs->itable_buf);
2511 		if (retval) {
2512 			io_channel_write_blk64(fs->io, old_blk,
2513 					       num, rfs->itable_buf);
2514 			goto errout;
2515 		}
2516 		if (n > diff) {
2517 			retval = io_channel_write_blk64(fs->io,
2518 			      old_blk + fs->inode_blocks_per_group,
2519 			      diff, (rfs->itable_buf +
2520 				     (fs->inode_blocks_per_group - diff) *
2521 				     fs->blocksize));
2522 			if (retval)
2523 				goto errout;
2524 		}
2525 
2526 		for (blk = ext2fs_inode_table_loc(rfs->old_fs, i), j=0;
2527 		     j < fs->inode_blocks_per_group;) {
2528 			if (new_bmap == NULL ||
2529 			    !ext2fs_test_block_bitmap2(new_bmap, blk)) {
2530 				ext2fs_block_alloc_stats2(fs, blk, -1);
2531 				cluster_freed = EXT2FS_CLUSTER_RATIO(fs) -
2532 						(blk & EXT2FS_CLUSTER_MASK(fs));
2533 				blk += cluster_freed;
2534 				j += cluster_freed;
2535 				continue;
2536 			}
2537 			blk++;
2538 			j++;
2539 		}
2540 
2541 		ext2fs_inode_table_loc_set(rfs->old_fs, i, new_blk);
2542 		ext2fs_group_desc_csum_set(rfs->old_fs, i);
2543 		ext2fs_mark_super_dirty(rfs->old_fs);
2544 		ext2fs_flush(rfs->old_fs);
2545 
2546 		if (rfs->progress) {
2547 			retval = rfs->progress(rfs, E2_RSZ_MOVE_ITABLE_PASS,
2548 					       ++moved, to_move);
2549 			if (retval)
2550 				goto errout;
2551 		}
2552 	}
2553 	mark_table_blocks(fs, fs->block_map);
2554 	ext2fs_flush(fs);
2555 #ifdef RESIZE2FS_DEBUG
2556 	if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE)
2557 		printf("Inode table move finished.\n");
2558 #endif
2559 	retval = 0;
2560 
2561 errout:
2562 	if (new_bmap)
2563 		ext2fs_free_block_bitmap(new_bmap);
2564 	return retval;
2565 }
2566 
2567 /*
2568  * This function is used when expanding a file system.  It frees the
2569  * superblock and block group descriptor blocks from the block group
2570  * which is no longer the last block group.
2571  */
clear_sparse_super2_last_group(ext2_resize_t rfs)2572 static errcode_t clear_sparse_super2_last_group(ext2_resize_t rfs)
2573 {
2574 	ext2_filsys	fs = rfs->new_fs;
2575 	ext2_filsys	old_fs = rfs->old_fs;
2576 	errcode_t	retval;
2577 	dgrp_t		old_last_bg = rfs->old_fs->group_desc_count - 1;
2578 	dgrp_t		last_bg = fs->group_desc_count - 1;
2579 	blk64_t		sb, old_desc;
2580 	blk_t		num;
2581 
2582 	if (!ext2fs_has_feature_sparse_super2(fs->super))
2583 		return 0;
2584 
2585 	if (last_bg <= old_last_bg)
2586 		return 0;
2587 
2588 	if (fs->super->s_backup_bgs[0] == old_fs->super->s_backup_bgs[0] &&
2589 	    fs->super->s_backup_bgs[1] == old_fs->super->s_backup_bgs[1])
2590 		return 0;
2591 
2592 	if (old_fs->super->s_backup_bgs[0] != old_last_bg &&
2593 	    old_fs->super->s_backup_bgs[1] != old_last_bg)
2594 		return 0;
2595 
2596 	if (fs->super->s_backup_bgs[0] == old_last_bg ||
2597 	    fs->super->s_backup_bgs[1] == old_last_bg)
2598 		return 0;
2599 
2600 	if (old_last_bg == 0)
2601 		return 0;
2602 
2603 	retval = ext2fs_super_and_bgd_loc2(rfs->old_fs, old_last_bg,
2604 					   &sb, &old_desc, NULL, &num);
2605 	if (retval)
2606 		return retval;
2607 
2608 	if (sb)
2609 		ext2fs_unmark_block_bitmap2(fs->block_map, sb);
2610 	if (old_desc)
2611 		ext2fs_unmark_block_bitmap_range2(fs->block_map, old_desc, num);
2612 	return 0;
2613 }
2614 
2615 /*
2616  * This function is used when shrinking a file system.  We need to
2617  * utilize blocks from what will be the new last block group for the
2618  * backup superblock and block group descriptor blocks.
2619  * Unfortunately, those blocks may be used by other files or fs
2620  * metadata blocks.  We need to mark them as being in use.
2621  */
reserve_sparse_super2_last_group(ext2_resize_t rfs,ext2fs_block_bitmap meta_bmap)2622 static errcode_t reserve_sparse_super2_last_group(ext2_resize_t rfs,
2623 						 ext2fs_block_bitmap meta_bmap)
2624 {
2625 	ext2_filsys	fs = rfs->new_fs;
2626 	ext2_filsys	old_fs = rfs->old_fs;
2627 	errcode_t	retval;
2628 	dgrp_t		old_last_bg = rfs->old_fs->group_desc_count - 1;
2629 	dgrp_t		last_bg = fs->group_desc_count - 1;
2630 	dgrp_t		g;
2631 	blk64_t		blk, sb, old_desc;
2632 	blk_t		i, num;
2633 	int		realloc = 0;
2634 
2635 	if (!ext2fs_has_feature_sparse_super2(fs->super))
2636 		return 0;
2637 
2638 	if (last_bg >= old_last_bg)
2639 		return 0;
2640 
2641 	if (fs->super->s_backup_bgs[0] == old_fs->super->s_backup_bgs[0] &&
2642 	    fs->super->s_backup_bgs[1] == old_fs->super->s_backup_bgs[1])
2643 		return 0;
2644 
2645 	if (fs->super->s_backup_bgs[0] != last_bg &&
2646 	    fs->super->s_backup_bgs[1] != last_bg)
2647 		return 0;
2648 
2649 	if (old_fs->super->s_backup_bgs[0] == last_bg ||
2650 	    old_fs->super->s_backup_bgs[1] == last_bg)
2651 		return 0;
2652 
2653 	retval = ext2fs_super_and_bgd_loc2(rfs->new_fs, last_bg,
2654 					   &sb, &old_desc, NULL, &num);
2655 	if (retval)
2656 		return retval;
2657 
2658 	if (last_bg && !sb) {
2659 		fputs(_("Should never happen!  No sb in last super_sparse bg?\n"),
2660 		      stderr);
2661 		exit(1);
2662 	}
2663 	if (old_desc && old_desc != sb+1) {
2664 		fputs(_("Should never happen!  Unexpected old_desc in "
2665 			"super_sparse bg?\n"),
2666 		      stderr);
2667 		exit(1);
2668 	}
2669 	num = (old_desc) ? num : 1;
2670 
2671 	/* Reserve the backup blocks */
2672 	ext2fs_mark_block_bitmap_range2(fs->block_map, sb, num);
2673 
2674 	for (g = 0; g < fs->group_desc_count; g++) {
2675 		blk64_t mb;
2676 
2677 		mb = ext2fs_block_bitmap_loc(fs, g);
2678 		if ((mb >= sb) && (mb < sb + num)) {
2679 			ext2fs_block_bitmap_loc_set(fs, g, 0);
2680 			realloc = 1;
2681 		}
2682 		mb = ext2fs_inode_bitmap_loc(fs, g);
2683 		if ((mb >= sb) && (mb < sb + num)) {
2684 			ext2fs_inode_bitmap_loc_set(fs, g, 0);
2685 			realloc = 1;
2686 		}
2687 		mb = ext2fs_inode_table_loc(fs, g);
2688 		if ((mb < sb + num) &&
2689 		    (sb < mb + fs->inode_blocks_per_group)) {
2690 			ext2fs_inode_table_loc_set(fs, g, 0);
2691 			realloc = 1;
2692 		}
2693 		if (realloc) {
2694 			retval = ext2fs_allocate_group_table(fs, g, 0);
2695 			if (retval)
2696 				return retval;
2697 		}
2698 	}
2699 
2700 	for (blk = sb, i = 0; i < num; blk++, i++) {
2701 		if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) &&
2702 		    !ext2fs_test_block_bitmap2(meta_bmap, blk)) {
2703 			ext2fs_mark_block_bitmap2(rfs->move_blocks, blk);
2704 			rfs->needed_blocks++;
2705 		}
2706 		ext2fs_mark_block_bitmap2(rfs->reserve_blocks, blk);
2707 	}
2708 	return 0;
2709 }
2710 
2711 /*
2712  * Fix the resize inode
2713  */
fix_resize_inode(ext2_filsys fs)2714 static errcode_t fix_resize_inode(ext2_filsys fs)
2715 {
2716 	struct ext2_inode	inode;
2717 	errcode_t		retval;
2718 
2719 	if (!ext2fs_has_feature_resize_inode(fs->super))
2720 		return 0;
2721 
2722 	retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
2723 	if (retval) goto errout;
2724 
2725 	ext2fs_iblk_set(fs, &inode, 1);
2726 
2727 	retval = ext2fs_write_inode(fs, EXT2_RESIZE_INO, &inode);
2728 	if (retval) goto errout;
2729 
2730 	if (!inode.i_block[EXT2_DIND_BLOCK]) {
2731 		/*
2732 		 * Avoid zeroing out block #0; that's rude.  This
2733 		 * should never happen anyway since the filesystem
2734 		 * should be fsck'ed and we assume it is consistent.
2735 		 */
2736 		fprintf(stderr, "%s",
2737 			_("Should never happen: resize inode corrupt!\n"));
2738 		exit(1);
2739 	}
2740 
2741 	retval = ext2fs_zero_blocks2(fs, inode.i_block[EXT2_DIND_BLOCK], 1,
2742 				     NULL, NULL);
2743 	if (retval)
2744 		goto errout;
2745 
2746 	retval = ext2fs_create_resize_inode(fs);
2747 	if (retval)
2748 		goto errout;
2749 
2750 errout:
2751 	return retval;
2752 }
2753 
2754 /*
2755  * Finally, recalculate the summary information
2756  */
resize2fs_calculate_summary_stats(ext2_filsys fs)2757 static errcode_t resize2fs_calculate_summary_stats(ext2_filsys fs)
2758 {
2759 	blk64_t		blk;
2760 	ext2_ino_t	ino;
2761 	unsigned int	group = 0;
2762 	unsigned int	count = 0;
2763 	blk64_t		total_blocks_free = 0;
2764 	int		total_inodes_free = 0;
2765 	int		group_free = 0;
2766 	int		uninit = 0;
2767 	blk64_t		super_blk, old_desc_blk, new_desc_blk;
2768 	int		old_desc_blocks;
2769 
2770 	/*
2771 	 * First calculate the block statistics
2772 	 */
2773 	uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT);
2774 	ext2fs_super_and_bgd_loc2(fs, group, &super_blk, &old_desc_blk,
2775 				  &new_desc_blk, 0);
2776 	if (ext2fs_has_feature_meta_bg(fs->super))
2777 		old_desc_blocks = fs->super->s_first_meta_bg;
2778 	else
2779 		old_desc_blocks = fs->desc_blocks +
2780 			fs->super->s_reserved_gdt_blocks;
2781 	for (blk = B2C(fs->super->s_first_data_block);
2782 	     blk < ext2fs_blocks_count(fs->super);
2783 	     blk += EXT2FS_CLUSTER_RATIO(fs)) {
2784 		if ((uninit &&
2785 		     !(EQ_CLSTR(blk, super_blk) ||
2786 		       ((old_desc_blk && old_desc_blocks &&
2787 			 GE_CLSTR(blk, old_desc_blk) &&
2788 			 LT_CLSTR(blk, old_desc_blk + old_desc_blocks))) ||
2789 		       ((new_desc_blk && EQ_CLSTR(blk, new_desc_blk))) ||
2790 		       EQ_CLSTR(blk, ext2fs_block_bitmap_loc(fs, group)) ||
2791 		       EQ_CLSTR(blk, ext2fs_inode_bitmap_loc(fs, group)) ||
2792 		       ((GE_CLSTR(blk, ext2fs_inode_table_loc(fs, group)) &&
2793 			 LT_CLSTR(blk, ext2fs_inode_table_loc(fs, group)
2794 				  + fs->inode_blocks_per_group))))) ||
2795 		    (!ext2fs_fast_test_block_bitmap2(fs->block_map, blk))) {
2796 			group_free++;
2797 			total_blocks_free++;
2798 		}
2799 		count++;
2800 		if ((count == fs->super->s_clusters_per_group) ||
2801 		    EQ_CLSTR(blk, ext2fs_blocks_count(fs->super)-1)) {
2802 			ext2fs_bg_free_blocks_count_set(fs, group, group_free);
2803 			ext2fs_group_desc_csum_set(fs, group);
2804 			group++;
2805 			if (group >= fs->group_desc_count)
2806 				break;
2807 			count = 0;
2808 			group_free = 0;
2809 			uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT);
2810 			ext2fs_super_and_bgd_loc2(fs, group, &super_blk,
2811 						  &old_desc_blk,
2812 						  &new_desc_blk, 0);
2813 			if (ext2fs_has_feature_meta_bg(fs->super))
2814 				old_desc_blocks = fs->super->s_first_meta_bg;
2815 			else
2816 				old_desc_blocks = fs->desc_blocks +
2817 					fs->super->s_reserved_gdt_blocks;
2818 		}
2819 	}
2820 	total_blocks_free = C2B(total_blocks_free);
2821 	ext2fs_free_blocks_count_set(fs->super, total_blocks_free);
2822 
2823 	/*
2824 	 * Next, calculate the inode statistics
2825 	 */
2826 	group_free = 0;
2827 	count = 0;
2828 	group = 0;
2829 
2830 	/* Protect loop from wrap-around if s_inodes_count maxed */
2831 	uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT);
2832 	for (ino = 1; ino <= fs->super->s_inodes_count && ino > 0; ino++) {
2833 		if (uninit ||
2834 		    !ext2fs_fast_test_inode_bitmap2(fs->inode_map, ino)) {
2835 			group_free++;
2836 			total_inodes_free++;
2837 		}
2838 		count++;
2839 		if ((count == fs->super->s_inodes_per_group) ||
2840 		    (ino == fs->super->s_inodes_count)) {
2841 			ext2fs_bg_free_inodes_count_set(fs, group, group_free);
2842 			ext2fs_group_desc_csum_set(fs, group);
2843 			group++;
2844 			if (group >= fs->group_desc_count)
2845 				break;
2846 			count = 0;
2847 			group_free = 0;
2848 			uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT);
2849 		}
2850 	}
2851 	fs->super->s_free_inodes_count = total_inodes_free;
2852 	ext2fs_mark_super_dirty(fs);
2853 	return 0;
2854 }
2855 
2856 /*
2857  *  Journal may have been relocated; update the backup journal blocks
2858  *  in the superblock.
2859  */
fix_sb_journal_backup(ext2_filsys fs)2860 static errcode_t fix_sb_journal_backup(ext2_filsys fs)
2861 {
2862 	errcode_t	  retval;
2863 	struct ext2_inode inode;
2864 
2865 	if (!ext2fs_has_feature_journal(fs->super))
2866 		return 0;
2867 
2868 	/* External journal? Nothing to do. */
2869 	if (fs->super->s_journal_dev && !fs->super->s_journal_inum)
2870 		return 0;
2871 
2872 	retval = ext2fs_read_inode(fs, fs->super->s_journal_inum, &inode);
2873 	if (retval)
2874 		return retval;
2875 	memcpy(fs->super->s_jnl_blocks, inode.i_block, EXT2_N_BLOCKS*4);
2876 	fs->super->s_jnl_blocks[15] = inode.i_size_high;
2877 	fs->super->s_jnl_blocks[16] = inode.i_size;
2878 	fs->super->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
2879 	ext2fs_mark_super_dirty(fs);
2880 	return 0;
2881 }
2882 
calc_group_overhead(ext2_filsys fs,blk64_t grp,int old_desc_blocks)2883 static int calc_group_overhead(ext2_filsys fs, blk64_t grp,
2884 			       int old_desc_blocks)
2885 {
2886 	blk64_t	super_blk, old_desc_blk, new_desc_blk;
2887 	int overhead;
2888 
2889 	/* inode table blocks plus allocation bitmaps */
2890 	overhead = fs->inode_blocks_per_group + 2;
2891 
2892 	ext2fs_super_and_bgd_loc2(fs, grp, &super_blk,
2893 				  &old_desc_blk, &new_desc_blk, 0);
2894 	if ((grp == 0) || super_blk)
2895 		overhead++;
2896 	if (old_desc_blk)
2897 		overhead += old_desc_blocks;
2898 	else if (new_desc_blk)
2899 		overhead++;
2900 	return overhead;
2901 }
2902 
2903 
2904 /*
2905  * calculate the minimum number of blocks the given fs can be resized to
2906  */
calculate_minimum_resize_size(ext2_filsys fs,int flags)2907 blk64_t calculate_minimum_resize_size(ext2_filsys fs, int flags)
2908 {
2909 	ext2_ino_t inode_count;
2910 	dgrp_t groups, flex_groups;
2911 	blk64_t blks_needed, data_blocks;
2912 	blk64_t grp, data_needed, last_start;
2913 	blk64_t overhead = 0;
2914 	int old_desc_blocks;
2915 	int flexbg_size = 1 << fs->super->s_log_groups_per_flex;
2916 
2917 	/*
2918 	 * first figure out how many group descriptors we need to
2919 	 * handle the number of inodes we have
2920 	 */
2921 	inode_count = fs->super->s_inodes_count -
2922 		fs->super->s_free_inodes_count;
2923 	blks_needed = ext2fs_div_ceil(inode_count,
2924 				      fs->super->s_inodes_per_group) *
2925 		(blk64_t) EXT2_BLOCKS_PER_GROUP(fs->super);
2926 	groups = ext2fs_div64_ceil(blks_needed,
2927 				   EXT2_BLOCKS_PER_GROUP(fs->super));
2928 #ifdef RESIZE2FS_DEBUG
2929 	if (flags & RESIZE_DEBUG_MIN_CALC)
2930 		printf("fs has %d inodes, %d groups required.\n",
2931 		       inode_count, groups);
2932 #endif
2933 
2934 	/*
2935 	 * number of old-style block group descriptor blocks
2936 	 */
2937 	if (ext2fs_has_feature_meta_bg(fs->super))
2938 		old_desc_blocks = fs->super->s_first_meta_bg;
2939 	else
2940 		old_desc_blocks = fs->desc_blocks +
2941 			fs->super->s_reserved_gdt_blocks;
2942 
2943 	/* calculate how many blocks are needed for data */
2944 	data_needed = ext2fs_blocks_count(fs->super);
2945 	for (grp = 0; grp < fs->group_desc_count; grp++) {
2946 		data_needed -= calc_group_overhead(fs, grp, old_desc_blocks);
2947 		data_needed -= ext2fs_bg_free_blocks_count(fs, grp);
2948 	}
2949 #ifdef RESIZE2FS_DEBUG
2950 	if (flags & RESIZE_DEBUG_MIN_CALC)
2951 		printf("fs requires %llu data blocks.\n",
2952 		       (unsigned long long) data_needed);
2953 #endif
2954 
2955 	/*
2956 	 * For ext4 we need to allow for up to a flex_bg worth of
2957 	 * inode tables of slack space so the resize operation can be
2958 	 * guaranteed to finish.
2959 	 */
2960 	flex_groups = groups;
2961 	if (ext2fs_has_feature_flex_bg(fs->super)) {
2962 		dgrp_t remainder = groups & (flexbg_size - 1);
2963 
2964 		flex_groups += flexbg_size - remainder;
2965 		if (flex_groups > fs->group_desc_count)
2966 			flex_groups = fs->group_desc_count;
2967 	}
2968 
2969 	/*
2970 	 * figure out how many data blocks we have given the number of groups
2971 	 * we need for our inodes
2972 	 */
2973 	data_blocks = EXT2_GROUPS_TO_BLOCKS(fs->super, groups);
2974 	last_start = 0;
2975 	for (grp = 0; grp < flex_groups; grp++) {
2976 		overhead = calc_group_overhead(fs, grp, old_desc_blocks);
2977 
2978 		/*
2979 		 * we want to keep track of how much data we can store in
2980 		 * the groups leading up to the last group so we can determine
2981 		 * how big the last group needs to be
2982 		 */
2983 		if (grp < (groups - 1))
2984 			last_start += EXT2_BLOCKS_PER_GROUP(fs->super) -
2985 				overhead;
2986 
2987 		if (data_blocks > overhead)
2988 			data_blocks -= overhead;
2989 		else
2990 			data_blocks = 0;
2991 	}
2992 #ifdef RESIZE2FS_DEBUG
2993 	if (flags & RESIZE_DEBUG_MIN_CALC)
2994 		printf("With %d group(s), we have %llu blocks available.\n",
2995 		       groups, (unsigned long long) data_blocks);
2996 #endif
2997 
2998 	/*
2999 	 * if we need more group descriptors in order to accommodate our data
3000 	 * then we need to add them here
3001 	 */
3002 	blks_needed = data_needed;
3003 	while (blks_needed > data_blocks) {
3004 		blk64_t remainder = blks_needed - data_blocks;
3005 		dgrp_t extra_grps;
3006 
3007 		/* figure out how many more groups we need for the data */
3008 		extra_grps = ext2fs_div64_ceil(remainder,
3009 					       EXT2_BLOCKS_PER_GROUP(fs->super));
3010 
3011 		data_blocks += EXT2_GROUPS_TO_BLOCKS(fs->super, extra_grps);
3012 
3013 		/* ok we have to account for the last group */
3014 		overhead = calc_group_overhead(fs, groups-1, old_desc_blocks);
3015 		last_start += EXT2_BLOCKS_PER_GROUP(fs->super) - overhead;
3016 
3017 		grp = flex_groups;
3018 		groups += extra_grps;
3019 		if (!ext2fs_has_feature_flex_bg(fs->super))
3020 			flex_groups = groups;
3021 		else if (groups > flex_groups) {
3022 			dgrp_t r = groups & (flexbg_size - 1);
3023 
3024 			flex_groups = groups + flexbg_size - r;
3025 			if (flex_groups > fs->group_desc_count)
3026 				flex_groups = fs->group_desc_count;
3027 		}
3028 
3029 		for (; grp < flex_groups; grp++) {
3030 			overhead = calc_group_overhead(fs, grp,
3031 						       old_desc_blocks);
3032 
3033 			/*
3034 			 * again, we need to see how much data we cram into
3035 			 * all of the groups leading up to the last group
3036 			 */
3037 			if (grp < groups - 1)
3038 				last_start += EXT2_BLOCKS_PER_GROUP(fs->super)
3039 					- overhead;
3040 
3041 			data_blocks -= overhead;
3042 		}
3043 
3044 #ifdef RESIZE2FS_DEBUG
3045 		if (flags & RESIZE_DEBUG_MIN_CALC)
3046 			printf("Added %d extra group(s), "
3047 			       "blks_needed %llu, data_blocks %llu, "
3048 			       "last_start %llu\n", extra_grps,
3049 			       (unsigned long long) blks_needed,
3050 			       (unsigned long long) data_blocks,
3051 			       (unsigned long long) last_start);
3052 #endif
3053 	}
3054 
3055 	/* now for the fun voodoo */
3056 	grp = groups - 1;
3057 	if (ext2fs_has_feature_flex_bg(fs->super) &&
3058 	    (grp & ~(flexbg_size - 1)) == 0)
3059 		grp = grp & ~(flexbg_size - 1);
3060 	overhead = 0;
3061 	for (; grp < flex_groups; grp++)
3062 		overhead += calc_group_overhead(fs, grp, old_desc_blocks);
3063 
3064 #ifdef RESIZE2FS_DEBUG
3065 	if (flags & RESIZE_DEBUG_MIN_CALC)
3066 		printf("Last group's overhead is %llu\n",
3067 		       (unsigned long long) overhead);
3068 #endif
3069 
3070 	/*
3071 	 * if this is the case then the last group is going to have data in it
3072 	 * so we need to adjust the size of the last group accordingly
3073 	 */
3074 	if (last_start < blks_needed) {
3075 		blk64_t remainder = blks_needed - last_start;
3076 
3077 #ifdef RESIZE2FS_DEBUG
3078 		if (flags & RESIZE_DEBUG_MIN_CALC)
3079 			printf("Need %llu data blocks in last group\n",
3080 			       (unsigned long long) remainder);
3081 #endif
3082 		/*
3083 		 * 50 is a magic number that mkfs/resize uses to see if its
3084 		 * even worth making/resizing the fs.  basically you need to
3085 		 * have at least 50 blocks in addition to the blocks needed
3086 		 * for the metadata in the last group
3087 		 */
3088 		if (remainder > 50)
3089 			overhead += remainder;
3090 		else
3091 			overhead += 50;
3092 	} else
3093 		overhead += 50;
3094 
3095 	overhead += fs->super->s_first_data_block;
3096 #ifdef RESIZE2FS_DEBUG
3097 	if (flags & RESIZE_DEBUG_MIN_CALC)
3098 		printf("Final size of last group is %llu\n",
3099 		       (unsigned long long) overhead);
3100 #endif
3101 
3102 	/* Add extra slack for bigalloc file systems */
3103 	if (EXT2FS_CLUSTER_RATIO(fs) > 1)
3104 		overhead += EXT2FS_CLUSTER_RATIO(fs) * 2;
3105 
3106 	/*
3107 	 * since our last group doesn't have to be BLOCKS_PER_GROUP
3108 	 * large, we only do groups-1, and then add the number of
3109 	 * blocks needed to handle the group descriptor metadata+data
3110 	 * that we need
3111 	 */
3112 	blks_needed = EXT2_GROUPS_TO_BLOCKS(fs->super, groups - 1);
3113 	blks_needed += overhead;
3114 
3115 	/*
3116 	 * Make sure blks_needed covers the end of the inode table in
3117 	 * the last block group.
3118 	 */
3119 	overhead = ext2fs_inode_table_loc(fs, groups-1) +
3120 		fs->inode_blocks_per_group;
3121 	if (blks_needed < overhead)
3122 		blks_needed = overhead;
3123 
3124 #ifdef RESIZE2FS_DEBUG
3125 	if (flags & RESIZE_DEBUG_MIN_CALC)
3126 		printf("Estimated blocks needed: %llu\n",
3127 		       (unsigned long long) blks_needed);
3128 #endif
3129 
3130 	/*
3131 	 * If at this point we've already added up more "needed" than
3132 	 * the current size, just return current size as minimum.
3133 	 */
3134 	if (blks_needed >= ext2fs_blocks_count(fs->super))
3135 		return ext2fs_blocks_count(fs->super);
3136 	/*
3137 	 * We need to reserve a few extra blocks if extents are
3138 	 * enabled, in case we need to grow the extent tree.  The more
3139 	 * we shrink the file system, the more space we need.
3140 	 *
3141 	 * The absolute worst case is every single data block is in
3142 	 * the part of the file system that needs to be evacuated,
3143 	 * with each data block needs to be in its own extent, and
3144 	 * with each inode needing at least one extent block.
3145 	 */
3146 	if (ext2fs_has_feature_extents(fs->super)) {
3147 		blk64_t safe_margin = (ext2fs_blocks_count(fs->super) -
3148 				       blks_needed)/500;
3149 		unsigned int exts_per_blk = (fs->blocksize /
3150 					     sizeof(struct ext3_extent)) - 1;
3151 		blk64_t worst_case = ((data_needed + exts_per_blk - 1) /
3152 				      exts_per_blk);
3153 
3154 		if (worst_case < inode_count)
3155 			worst_case = inode_count;
3156 
3157 		if (safe_margin > worst_case)
3158 			safe_margin = worst_case;
3159 
3160 #ifdef RESIZE2FS_DEBUG
3161 		if (flags & RESIZE_DEBUG_MIN_CALC)
3162 			printf("Extents safety margin: %llu\n",
3163 			       (unsigned long long) safe_margin);
3164 #endif
3165 		blks_needed += safe_margin;
3166 	}
3167 
3168 	return blks_needed;
3169 }
3170