pass5.c revision 2db19bce8146a63b1cef19fe4628014c7f7de816
1/*
2 * pass5.c --- check block and inode bitmaps against on-disk bitmaps
3 *
4 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
5 *
6 * %Begin-Header%
7 * This file may be redistributed under the terms of the GNU Public
8 * License.
9 * %End-Header%
10 *
11 */
12
13#include "config.h"
14#include <stdint.h>
15#include <sys/types.h>
16#include <sys/stat.h>
17#include <sys/ioctl.h>
18#include <fcntl.h>
19#include <errno.h>
20
21#include "e2fsck.h"
22#include "problem.h"
23
24#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
25
26static void check_block_bitmaps(e2fsck_t ctx);
27static void check_inode_bitmaps(e2fsck_t ctx);
28static void check_inode_end(e2fsck_t ctx);
29static void check_block_end(e2fsck_t ctx);
30static void check_inode_bitmap_checksum(e2fsck_t ctx);
31static void check_block_bitmap_checksum(e2fsck_t ctx);
32
33void e2fsck_pass5(e2fsck_t ctx)
34{
35#ifdef RESOURCE_TRACK
36	struct resource_track	rtrack;
37#endif
38	struct problem_context	pctx;
39
40#ifdef MTRACE
41	mtrace_print("Pass 5");
42#endif
43
44	init_resource_track(&rtrack, ctx->fs->io);
45	clear_problem_context(&pctx);
46
47	if (!(ctx->options & E2F_OPT_PREEN))
48		fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
49
50	if (ctx->progress)
51		if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
52			return;
53
54	e2fsck_read_bitmaps(ctx);
55
56	check_block_bitmaps(ctx);
57	if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
58		return;
59	check_inode_bitmaps(ctx);
60	if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
61		return;
62	check_inode_end(ctx);
63	if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
64		return;
65	check_block_end(ctx);
66	if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
67		return;
68
69	check_inode_bitmap_checksum(ctx);
70	check_block_bitmap_checksum(ctx);
71
72	ext2fs_free_inode_bitmap(ctx->inode_used_map);
73	ctx->inode_used_map = 0;
74	ext2fs_free_inode_bitmap(ctx->inode_dir_map);
75	ctx->inode_dir_map = 0;
76	ext2fs_free_block_bitmap(ctx->block_found_map);
77	ctx->block_found_map = 0;
78
79	print_resource_track(ctx, _("Pass 5"), &rtrack, ctx->fs->io);
80}
81
82static void check_inode_bitmap_checksum(e2fsck_t ctx)
83{
84	struct problem_context	pctx;
85	char		*buf;
86	dgrp_t		i;
87	int		nbytes;
88	ext2_ino_t	ino_itr;
89	errcode_t	retval;
90
91	if (!EXT2_HAS_RO_COMPAT_FEATURE(ctx->fs->super,
92					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
93		return;
94
95	/* If bitmap is dirty from being fixed, checksum will be corrected */
96	if (ext2fs_test_ib_dirty(ctx->fs))
97		return;
98
99	nbytes = (size_t)(EXT2_INODES_PER_GROUP(ctx->fs->super) / 8);
100	retval = ext2fs_get_memalign(ctx->fs->blocksize, ctx->fs->blocksize,
101				     &buf);
102	if (retval) {
103		com_err(ctx->program_name, 0,
104		    _("check_inode_bitmap_checksum: Memory allocation error"));
105		fatal_error(ctx, 0);
106	}
107
108	clear_problem_context(&pctx);
109	for (i = 0; i < ctx->fs->group_desc_count; i++) {
110		if (ext2fs_bg_flags_test(ctx->fs, i, EXT2_BG_INODE_UNINIT))
111			continue;
112
113		ino_itr = 1 + (i * (nbytes << 3));
114		retval = ext2fs_get_inode_bitmap_range2(ctx->fs->inode_map,
115							ino_itr, nbytes << 3,
116							buf);
117		if (retval)
118			break;
119
120		if (ext2fs_inode_bitmap_csum_verify(ctx->fs, i, buf, nbytes))
121			continue;
122		pctx.group = i;
123		if (!fix_problem(ctx, PR_5_INODE_BITMAP_CSUM_INVALID, &pctx))
124			continue;
125
126		/*
127		 * Fixing one checksum will rewrite all of them.  The bitmap
128		 * will be checked against the one we made during pass1 for
129		 * discrepancies, and fixed if need be.
130		 */
131		ext2fs_mark_ib_dirty(ctx->fs);
132		break;
133	}
134
135	ext2fs_free_mem(&buf);
136}
137
138static void check_block_bitmap_checksum(e2fsck_t ctx)
139{
140	struct problem_context	pctx;
141	char		*buf;
142	dgrp_t		i;
143	int		nbytes;
144	blk64_t		blk_itr;
145	errcode_t	retval;
146
147	if (!EXT2_HAS_RO_COMPAT_FEATURE(ctx->fs->super,
148					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
149		return;
150
151	/* If bitmap is dirty from being fixed, checksum will be corrected */
152	if (ext2fs_test_bb_dirty(ctx->fs))
153		return;
154
155	nbytes = (size_t)(EXT2_CLUSTERS_PER_GROUP(ctx->fs->super) / 8);
156	retval = ext2fs_get_memalign(ctx->fs->blocksize, ctx->fs->blocksize,
157				     &buf);
158	if (retval) {
159		com_err(ctx->program_name, 0,
160		    _("check_block_bitmap_checksum: Memory allocation error"));
161		fatal_error(ctx, 0);
162	}
163
164	clear_problem_context(&pctx);
165	for (i = 0; i < ctx->fs->group_desc_count; i++) {
166		if (ext2fs_bg_flags_test(ctx->fs, i, EXT2_BG_BLOCK_UNINIT))
167			continue;
168
169		blk_itr = EXT2FS_B2C(ctx->fs,
170				     ctx->fs->super->s_first_data_block) +
171			  ((blk64_t) i * (nbytes << 3));
172		retval = ext2fs_get_block_bitmap_range2(ctx->fs->block_map,
173							blk_itr, nbytes << 3,
174							buf);
175		if (retval)
176			break;
177
178		if (ext2fs_block_bitmap_csum_verify(ctx->fs, i, buf, nbytes))
179			continue;
180		pctx.group = i;
181		if (!fix_problem(ctx, PR_5_BLOCK_BITMAP_CSUM_INVALID, &pctx))
182			continue;
183
184		/*
185		 * Fixing one checksum will rewrite all of them.  The bitmap
186		 * will be checked against the one we made during pass1 for
187		 * discrepancies, and fixed if need be.
188		 */
189		ext2fs_mark_bb_dirty(ctx->fs);
190		break;
191	}
192
193	ext2fs_free_mem(&buf);
194}
195
196static void e2fsck_discard_blocks(e2fsck_t ctx, blk64_t start,
197				  blk64_t count)
198{
199	ext2_filsys fs = ctx->fs;
200
201	/*
202	 * If the filesystem has changed it means that there was an corruption
203	 * which should be repaired, but in some cases just one e2fsck run is
204	 * not enough to fix the problem, hence it is not safe to run discard
205	 * in this case.
206	 */
207	if (ext2fs_test_changed(fs))
208		ctx->options &= ~E2F_OPT_DISCARD;
209
210	if ((ctx->options & E2F_OPT_DISCARD) &&
211	    (io_channel_discard(fs->io, start, count)))
212		ctx->options &= ~E2F_OPT_DISCARD;
213}
214
215/*
216 * This will try to discard number 'count' inodes starting at
217 * inode number 'start' within the 'group'. Note that 'start'
218 * is 1-based, it means that we need to adjust it by -1 in this
219 * function to compute right offset in the particular inode table.
220 */
221static void e2fsck_discard_inodes(e2fsck_t ctx, dgrp_t group,
222				  ext2_ino_t start, int count)
223{
224	ext2_filsys fs = ctx->fs;
225	blk64_t blk, num;
226
227	/*
228	 * Sanity check for 'start'
229	 */
230	if ((start < 1) || (start > EXT2_INODES_PER_GROUP(fs->super))) {
231		printf("PROGRAMMING ERROR: Got start %d outside of group %d!"
232		       " Disabling discard\n",
233			start, group);
234		ctx->options &= ~E2F_OPT_DISCARD;
235	}
236
237	/*
238	 * Do not attempt to discard if E2F_OPT_DISCARD is not set. And also
239	 * skip the discard on this group if discard does not zero data.
240	 * The reason is that if the inode table is not zeroed discard would
241	 * no help us since we need to zero it anyway, or if the inode table
242	 * is zeroed then the read after discard would not be deterministic
243	 * anyway and we would not be able to assume that this inode table
244	 * was zeroed anymore so we would have to zero it again, which does
245	 * not really make sense.
246	 */
247	if (!(ctx->options & E2F_OPT_DISCARD) ||
248	    !io_channel_discard_zeroes_data(fs->io))
249		return;
250
251	/*
252	 * Start is inode number within the group which starts
253	 * counting from 1, so we need to adjust it.
254	 */
255	start -= 1;
256
257	/*
258	 * We can discard only blocks containing only unused
259	 * inodes in the table.
260	 */
261	blk = DIV_ROUND_UP(start,
262		EXT2_INODES_PER_BLOCK(fs->super));
263	count -= (blk * EXT2_INODES_PER_BLOCK(fs->super) - start);
264	blk += ext2fs_inode_table_loc(fs, group);
265	num = count / EXT2_INODES_PER_BLOCK(fs->super);
266
267	if (num > 0)
268		e2fsck_discard_blocks(ctx, blk, num);
269}
270
271#define NO_BLK ((blk64_t) -1)
272
273static void print_bitmap_problem(e2fsck_t ctx, int problem,
274			    struct problem_context *pctx)
275{
276	switch (problem) {
277	case PR_5_BLOCK_UNUSED:
278		if (pctx->blk == pctx->blk2)
279			pctx->blk2 = 0;
280		else
281			problem = PR_5_BLOCK_RANGE_UNUSED;
282		break;
283	case PR_5_BLOCK_USED:
284		if (pctx->blk == pctx->blk2)
285			pctx->blk2 = 0;
286		else
287			problem = PR_5_BLOCK_RANGE_USED;
288		break;
289	case PR_5_INODE_UNUSED:
290		if (pctx->ino == pctx->ino2)
291			pctx->ino2 = 0;
292		else
293			problem = PR_5_INODE_RANGE_UNUSED;
294		break;
295	case PR_5_INODE_USED:
296		if (pctx->ino == pctx->ino2)
297			pctx->ino2 = 0;
298		else
299			problem = PR_5_INODE_RANGE_USED;
300		break;
301	}
302	fix_problem(ctx, problem, pctx);
303	pctx->blk = pctx->blk2 = NO_BLK;
304	pctx->ino = pctx->ino2 = 0;
305}
306
307/* Just to be more succint */
308#define B2C(x)	EXT2FS_B2C(fs, (x))
309#define EQ_CLSTR(x, y) (B2C(x) == B2C(y))
310#define LE_CLSTR(x, y) (B2C(x) <= B2C(y))
311#define GE_CLSTR(x, y) (B2C(x) >= B2C(y))
312
313static void check_block_bitmaps(e2fsck_t ctx)
314{
315	ext2_filsys fs = ctx->fs;
316	blk64_t	i;
317	unsigned int	*free_array;
318	int	group = 0;
319	unsigned int	blocks = 0;
320	blk64_t	free_blocks = 0;
321	blk64_t first_free = ext2fs_blocks_count(fs->super);
322	unsigned int	group_free = 0;
323	int	actual, bitmap;
324	struct problem_context	pctx;
325	int	problem, save_problem, fixit, had_problem;
326	errcode_t	retval;
327	int		csum_flag;
328	int		skip_group = 0;
329	int	old_desc_blocks = 0;
330	int	count = 0;
331	int	cmp_block = 0;
332	int	redo_flag = 0;
333	blk64_t	super_blk, old_desc_blk, new_desc_blk;
334	char *actual_buf, *bitmap_buf;
335
336	actual_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize,
337						     "actual bitmap buffer");
338	bitmap_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize,
339						     "bitmap block buffer");
340
341	clear_problem_context(&pctx);
342	free_array = (unsigned int *) e2fsck_allocate_memory(ctx,
343	    fs->group_desc_count * sizeof(unsigned int), "free block count array");
344
345	if ((B2C(fs->super->s_first_data_block) <
346	     ext2fs_get_block_bitmap_start2(ctx->block_found_map)) ||
347	    (B2C(ext2fs_blocks_count(fs->super)-1) >
348	     ext2fs_get_block_bitmap_end2(ctx->block_found_map))) {
349		pctx.num = 1;
350		pctx.blk = B2C(fs->super->s_first_data_block);
351		pctx.blk2 = B2C(ext2fs_blocks_count(fs->super) - 1);
352		pctx.ino = ext2fs_get_block_bitmap_start2(ctx->block_found_map);
353		pctx.ino2 = ext2fs_get_block_bitmap_end2(ctx->block_found_map);
354		fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
355
356		ctx->flags |= E2F_FLAG_ABORT; /* fatal */
357		goto errout;
358	}
359
360	if ((B2C(fs->super->s_first_data_block) <
361	     ext2fs_get_block_bitmap_start2(fs->block_map)) ||
362	    (B2C(ext2fs_blocks_count(fs->super)-1) >
363	     ext2fs_get_block_bitmap_end2(fs->block_map))) {
364		pctx.num = 2;
365		pctx.blk = B2C(fs->super->s_first_data_block);
366		pctx.blk2 = B2C(ext2fs_blocks_count(fs->super) - 1);
367		pctx.ino = ext2fs_get_block_bitmap_start2(fs->block_map);
368		pctx.ino2 = ext2fs_get_block_bitmap_end2(fs->block_map);
369		fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
370
371		ctx->flags |= E2F_FLAG_ABORT; /* fatal */
372		goto errout;
373	}
374
375	csum_flag = ext2fs_has_group_desc_csum(fs);
376redo_counts:
377	had_problem = 0;
378	save_problem = 0;
379	pctx.blk = pctx.blk2 = NO_BLK;
380	if (csum_flag &&
381	    (ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT)))
382		skip_group++;
383	for (i = B2C(fs->super->s_first_data_block);
384	     i < ext2fs_blocks_count(fs->super);
385	     i += EXT2FS_CLUSTER_RATIO(fs)) {
386		int first_block_in_bg = (B2C(i) -
387					 B2C(fs->super->s_first_data_block)) %
388			fs->super->s_clusters_per_group == 0;
389		int n, nbytes = fs->super->s_clusters_per_group / 8;
390
391		actual = ext2fs_fast_test_block_bitmap2(ctx->block_found_map, i);
392
393		/*
394		 * Try to optimize pass5 by extracting a bitmap block
395		 * as expected from what we have on disk, and then
396		 * comparing the two.  If they are identical, then
397		 * update the free block counts and go on to the next
398		 * block group.  This is much faster than doing the
399		 * individual bit-by-bit comparison.  The one downside
400		 * is that this doesn't work if we are asking e2fsck
401		 * to do a discard operation.
402		 */
403		if (!first_block_in_bg ||
404		    (group == (int)fs->group_desc_count - 1) ||
405		    (ctx->options & E2F_OPT_DISCARD))
406			goto no_optimize;
407
408		retval = ext2fs_get_block_bitmap_range2(ctx->block_found_map,
409				B2C(i), fs->super->s_clusters_per_group,
410				actual_buf);
411		if (retval)
412			goto no_optimize;
413		if (ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT))
414			memset(bitmap_buf, 0, nbytes);
415		else {
416			retval = ext2fs_get_block_bitmap_range2(fs->block_map,
417					B2C(i), fs->super->s_clusters_per_group,
418					bitmap_buf);
419			if (retval)
420				goto no_optimize;
421		}
422		if (memcmp(actual_buf, bitmap_buf, nbytes) != 0)
423			goto no_optimize;
424		n = ext2fs_bitcount(actual_buf, nbytes);
425		group_free = fs->super->s_clusters_per_group - n;
426		free_blocks += group_free;
427		i += EXT2FS_C2B(fs, fs->super->s_clusters_per_group - 1);
428		goto next_group;
429	no_optimize:
430
431		if (skip_group) {
432			if (first_block_in_bg) {
433				super_blk = 0;
434				old_desc_blk = 0;
435				new_desc_blk = 0;
436				ext2fs_super_and_bgd_loc2(fs, group, &super_blk,
437					 &old_desc_blk, &new_desc_blk, 0);
438
439				if (fs->super->s_feature_incompat &
440						EXT2_FEATURE_INCOMPAT_META_BG)
441					old_desc_blocks =
442						fs->super->s_first_meta_bg;
443				else
444					old_desc_blocks = fs->desc_blocks +
445					fs->super->s_reserved_gdt_blocks;
446
447				count = 0;
448				cmp_block = fs->super->s_clusters_per_group;
449				if (group == (int)fs->group_desc_count - 1)
450					cmp_block = EXT2FS_NUM_B2C(fs,
451						    ext2fs_group_blocks_count(fs, group));
452			}
453
454			bitmap = 0;
455			if (EQ_CLSTR(i, super_blk) ||
456			    (old_desc_blk && old_desc_blocks &&
457			     GE_CLSTR(i, old_desc_blk) &&
458			     LE_CLSTR(i, old_desc_blk + old_desc_blocks-1)) ||
459			    (new_desc_blk && EQ_CLSTR(i, new_desc_blk)) ||
460			    EQ_CLSTR(i, ext2fs_block_bitmap_loc(fs, group)) ||
461			    EQ_CLSTR(i, ext2fs_inode_bitmap_loc(fs, group)) ||
462			    (GE_CLSTR(i, ext2fs_inode_table_loc(fs, group)) &&
463			     LE_CLSTR(i, (ext2fs_inode_table_loc(fs, group) +
464					  fs->inode_blocks_per_group - 1)))) {
465				bitmap = 1;
466				actual = (actual != 0);
467				count++;
468				cmp_block--;
469			} else if ((EXT2FS_B2C(fs, i) - count -
470				    EXT2FS_B2C(fs, fs->super->s_first_data_block)) %
471				   fs->super->s_clusters_per_group == 0) {
472				/*
473				 * When the compare data blocks in block bitmap
474				 * are 0, count the free block,
475				 * skip the current block group.
476				 */
477				if (ext2fs_test_block_bitmap_range2(
478					    ctx->block_found_map,
479					    EXT2FS_B2C(fs, i),
480					    cmp_block)) {
481					/*
482					 * -1 means to skip the current block
483					 * group.
484					 */
485					blocks = fs->super->s_clusters_per_group - 1;
486					group_free = cmp_block;
487					free_blocks += cmp_block;
488					/*
489					 * The current block group's last block
490					 * is set to i.
491					 */
492					i += EXT2FS_C2B(fs, cmp_block - 1);
493					bitmap = 1;
494					goto do_counts;
495				}
496			}
497		} else if (redo_flag)
498			bitmap = actual;
499		else
500			bitmap = ext2fs_fast_test_block_bitmap2(fs->block_map, i);
501
502		if (!actual == !bitmap)
503			goto do_counts;
504
505		if (!actual && bitmap) {
506			/*
507			 * Block not used, but marked in use in the bitmap.
508			 */
509			problem = PR_5_BLOCK_UNUSED;
510		} else {
511			/*
512			 * Block used, but not marked in use in the bitmap.
513			 */
514			problem = PR_5_BLOCK_USED;
515
516			if (skip_group) {
517				struct problem_context pctx2;
518				pctx2.blk = i;
519				pctx2.group = group;
520				if (fix_problem(ctx, PR_5_BLOCK_UNINIT,&pctx2)){
521					ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
522					skip_group = 0;
523				}
524			}
525		}
526		if (pctx.blk == NO_BLK) {
527			pctx.blk = pctx.blk2 = i;
528			save_problem = problem;
529		} else {
530			if ((problem == save_problem) &&
531			    (pctx.blk2 == i-1))
532				pctx.blk2++;
533			else {
534				print_bitmap_problem(ctx, save_problem, &pctx);
535				pctx.blk = pctx.blk2 = i;
536				save_problem = problem;
537			}
538		}
539		ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
540		had_problem++;
541
542		/*
543		 * If there a problem we should turn off the discard so we
544		 * do not compromise the filesystem.
545		 */
546		ctx->options &= ~E2F_OPT_DISCARD;
547
548	do_counts:
549		if (!bitmap) {
550			group_free++;
551			free_blocks++;
552			if (first_free > i)
553				first_free = i;
554		} else if (i > first_free) {
555			e2fsck_discard_blocks(ctx, first_free,
556					      (i - first_free));
557			first_free = ext2fs_blocks_count(fs->super);
558		}
559		blocks ++;
560		if ((blocks == fs->super->s_clusters_per_group) ||
561		    (EXT2FS_B2C(fs, i) ==
562		     EXT2FS_B2C(fs, ext2fs_blocks_count(fs->super)-1))) {
563			/*
564			 * If the last block of this group is free, then we can
565			 * discard it as well.
566			 */
567			if (!bitmap && i >= first_free)
568				e2fsck_discard_blocks(ctx, first_free,
569						      (i - first_free) + 1);
570		next_group:
571			first_free = ext2fs_blocks_count(fs->super);
572
573			free_array[group] = group_free;
574			group ++;
575			blocks = 0;
576			group_free = 0;
577			skip_group = 0;
578			if (ctx->progress)
579				if ((ctx->progress)(ctx, 5, group,
580						    fs->group_desc_count*2))
581					goto errout;
582			if (csum_flag &&
583			    (i != ext2fs_blocks_count(fs->super)-1) &&
584			    ext2fs_bg_flags_test(fs, group,
585						EXT2_BG_BLOCK_UNINIT))
586				skip_group++;
587		}
588	}
589	if (pctx.blk != NO_BLK)
590		print_bitmap_problem(ctx, save_problem, &pctx);
591	if (had_problem)
592		fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
593	else
594		fixit = -1;
595	ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
596
597	if (fixit == 1) {
598		ext2fs_free_block_bitmap(fs->block_map);
599		retval = ext2fs_copy_bitmap(ctx->block_found_map,
600						  &fs->block_map);
601		if (retval) {
602			clear_problem_context(&pctx);
603			fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
604			ctx->flags |= E2F_FLAG_ABORT;
605			goto errout;
606		}
607		ext2fs_set_bitmap_padding(fs->block_map);
608		ext2fs_mark_bb_dirty(fs);
609
610		/* Redo the counts */
611		blocks = 0; free_blocks = 0; group_free = 0; group = 0;
612		memset(free_array, 0, fs->group_desc_count * sizeof(int));
613		redo_flag++;
614		goto redo_counts;
615	} else if (fixit == 0)
616		ext2fs_unmark_valid(fs);
617
618	for (i = 0; i < fs->group_desc_count; i++) {
619		if (free_array[i] != ext2fs_bg_free_blocks_count(fs, i)) {
620			pctx.group = i;
621			pctx.blk = ext2fs_bg_free_blocks_count(fs, i);
622			pctx.blk2 = free_array[i];
623
624			if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
625					&pctx)) {
626				ext2fs_bg_free_blocks_count_set(fs, i, free_array[i]);
627				ext2fs_mark_super_dirty(fs);
628			} else
629				ext2fs_unmark_valid(fs);
630		}
631	}
632	free_blocks = EXT2FS_C2B(fs, free_blocks);
633	if (free_blocks != ext2fs_free_blocks_count(fs->super)) {
634		pctx.group = 0;
635		pctx.blk = ext2fs_free_blocks_count(fs->super);
636		pctx.blk2 = free_blocks;
637
638		if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
639			ext2fs_free_blocks_count_set(fs->super, free_blocks);
640			ext2fs_mark_super_dirty(fs);
641		}
642	}
643errout:
644	ext2fs_free_mem(&free_array);
645	ext2fs_free_mem(&actual_buf);
646	ext2fs_free_mem(&bitmap_buf);
647}
648
649static void check_inode_bitmaps(e2fsck_t ctx)
650{
651	ext2_filsys fs = ctx->fs;
652	ext2_ino_t	i;
653	unsigned int	free_inodes = 0;
654	int		group_free = 0;
655	int		dirs_count = 0;
656	int		group = 0;
657	unsigned int	inodes = 0;
658	ext2_ino_t	*free_array;
659	ext2_ino_t	*dir_array;
660	int		actual, bitmap;
661	errcode_t	retval;
662	struct problem_context	pctx;
663	int		problem, save_problem, fixit, had_problem;
664	int		csum_flag;
665	int		skip_group = 0;
666	int		redo_flag = 0;
667	ext2_ino_t		first_free = fs->super->s_inodes_per_group + 1;
668
669	clear_problem_context(&pctx);
670	free_array = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
671	    fs->group_desc_count * sizeof(ext2_ino_t), "free inode count array");
672
673	dir_array = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
674	   fs->group_desc_count * sizeof(ext2_ino_t), "directory count array");
675
676	if ((1 < ext2fs_get_inode_bitmap_start2(ctx->inode_used_map)) ||
677	    (fs->super->s_inodes_count >
678	     ext2fs_get_inode_bitmap_end2(ctx->inode_used_map))) {
679		pctx.num = 3;
680		pctx.blk = 1;
681		pctx.blk2 = fs->super->s_inodes_count;
682		pctx.ino = ext2fs_get_inode_bitmap_start2(ctx->inode_used_map);
683		pctx.ino2 = ext2fs_get_inode_bitmap_end2(ctx->inode_used_map);
684		fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
685
686		ctx->flags |= E2F_FLAG_ABORT; /* fatal */
687		goto errout;
688	}
689	if ((1 < ext2fs_get_inode_bitmap_start2(fs->inode_map)) ||
690	    (fs->super->s_inodes_count >
691	     ext2fs_get_inode_bitmap_end2(fs->inode_map))) {
692		pctx.num = 4;
693		pctx.blk = 1;
694		pctx.blk2 = fs->super->s_inodes_count;
695		pctx.ino = ext2fs_get_inode_bitmap_start2(fs->inode_map);
696		pctx.ino2 = ext2fs_get_inode_bitmap_end2(fs->inode_map);
697		fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
698
699		ctx->flags |= E2F_FLAG_ABORT; /* fatal */
700		goto errout;
701	}
702
703	csum_flag = ext2fs_has_group_desc_csum(fs);
704redo_counts:
705	had_problem = 0;
706	save_problem = 0;
707	pctx.ino = pctx.ino2 = 0;
708	if (csum_flag &&
709	    (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT)))
710		skip_group++;
711
712	/* Protect loop from wrap-around if inodes_count is maxed */
713	for (i = 1; i <= fs->super->s_inodes_count && i > 0; i++) {
714		bitmap = 0;
715		if (skip_group &&
716		    i % fs->super->s_inodes_per_group == 1) {
717			/*
718			 * Current inode is the first inode
719			 * in the current block group.
720			 */
721			if (ext2fs_test_inode_bitmap_range(
722				    ctx->inode_used_map, i,
723				    fs->super->s_inodes_per_group)) {
724				/*
725				 * When the compared inodes in inodes bitmap
726				 * are 0, count the free inode,
727				 * skip the current block group.
728				 */
729				first_free = 1;
730				inodes = fs->super->s_inodes_per_group - 1;
731				group_free = inodes;
732				free_inodes += inodes;
733				i += inodes;
734				skip_group = 0;
735				goto do_counts;
736			}
737		}
738
739		actual = ext2fs_fast_test_inode_bitmap2(ctx->inode_used_map, i);
740		if (redo_flag)
741			bitmap = actual;
742		else if (!skip_group)
743			bitmap = ext2fs_fast_test_inode_bitmap2(fs->inode_map, i);
744		if (!actual == !bitmap)
745			goto do_counts;
746
747		if (!actual && bitmap) {
748			/*
749			 * Inode wasn't used, but marked in bitmap
750			 */
751			problem = PR_5_INODE_UNUSED;
752		} else /* if (actual && !bitmap) */ {
753			/*
754			 * Inode used, but not in bitmap
755			 */
756			problem = PR_5_INODE_USED;
757
758			/* We should never hit this, because it means that
759			 * inodes were marked in use that weren't noticed
760			 * in pass1 or pass 2. It is easier to fix the problem
761			 * than to kill e2fsck and leave the user stuck. */
762			if (skip_group) {
763				struct problem_context pctx2;
764				pctx2.blk = i;
765				pctx2.group = group;
766				if (fix_problem(ctx, PR_5_INODE_UNINIT,&pctx2)){
767					ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT);
768					skip_group = 0;
769				}
770			}
771		}
772		if (pctx.ino == 0) {
773			pctx.ino = pctx.ino2 = i;
774			save_problem = problem;
775		} else {
776			if ((problem == save_problem) &&
777			    (pctx.ino2 == i-1))
778				pctx.ino2++;
779			else {
780				print_bitmap_problem(ctx, save_problem, &pctx);
781				pctx.ino = pctx.ino2 = i;
782				save_problem = problem;
783			}
784		}
785		ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
786		had_problem++;
787		/*
788		 * If there a problem we should turn off the discard so we
789		 * do not compromise the filesystem.
790		 */
791		ctx->options &= ~E2F_OPT_DISCARD;
792
793do_counts:
794		inodes++;
795		if (bitmap) {
796			if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, i))
797				dirs_count++;
798			if (inodes > first_free) {
799				e2fsck_discard_inodes(ctx, group, first_free,
800						      inodes - first_free);
801				first_free = fs->super->s_inodes_per_group + 1;
802			}
803		} else {
804			group_free++;
805			free_inodes++;
806			if (first_free > inodes)
807				first_free = inodes;
808		}
809
810		if ((inodes == fs->super->s_inodes_per_group) ||
811		    (i == fs->super->s_inodes_count)) {
812			/*
813			 * If the last inode is free, we can discard it as well.
814			 */
815			if (!bitmap && inodes >= first_free)
816				e2fsck_discard_inodes(ctx, group, first_free,
817						      inodes - first_free + 1);
818			/*
819			 * If discard zeroes data and the group inode table
820			 * was not zeroed yet, set itable as zeroed
821			 */
822			if ((ctx->options & E2F_OPT_DISCARD) &&
823			    io_channel_discard_zeroes_data(fs->io) &&
824			    !(ext2fs_bg_flags_test(fs, group,
825						   EXT2_BG_INODE_ZEROED))) {
826				ext2fs_bg_flags_set(fs, group,
827						    EXT2_BG_INODE_ZEROED);
828				ext2fs_group_desc_csum_set(fs, group);
829			}
830
831			first_free = fs->super->s_inodes_per_group + 1;
832			free_array[group] = group_free;
833			dir_array[group] = dirs_count;
834			group ++;
835			inodes = 0;
836			skip_group = 0;
837			group_free = 0;
838			dirs_count = 0;
839			if (ctx->progress)
840				if ((ctx->progress)(ctx, 5,
841					    group + fs->group_desc_count,
842					    fs->group_desc_count*2))
843					goto errout;
844			if (csum_flag &&
845			    (i != fs->super->s_inodes_count) &&
846			    (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT)
847			     ))
848				skip_group++;
849		}
850	}
851	if (pctx.ino)
852		print_bitmap_problem(ctx, save_problem, &pctx);
853
854	if (had_problem)
855		fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
856	else
857		fixit = -1;
858	ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
859
860	if (fixit == 1) {
861		ext2fs_free_inode_bitmap(fs->inode_map);
862		retval = ext2fs_copy_bitmap(ctx->inode_used_map,
863						  &fs->inode_map);
864		if (retval) {
865			clear_problem_context(&pctx);
866			fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
867			ctx->flags |= E2F_FLAG_ABORT;
868			goto errout;
869		}
870		ext2fs_set_bitmap_padding(fs->inode_map);
871		ext2fs_mark_ib_dirty(fs);
872
873		/* redo counts */
874		inodes = 0; free_inodes = 0; group_free = 0;
875		dirs_count = 0; group = 0;
876		memset(free_array, 0, fs->group_desc_count * sizeof(int));
877		memset(dir_array, 0, fs->group_desc_count * sizeof(int));
878		redo_flag++;
879		goto redo_counts;
880	} else if (fixit == 0)
881		ext2fs_unmark_valid(fs);
882
883	for (i = 0; i < fs->group_desc_count; i++) {
884		if (free_array[i] != ext2fs_bg_free_inodes_count(fs, i)) {
885			pctx.group = i;
886			pctx.ino = ext2fs_bg_free_inodes_count(fs, i);
887			pctx.ino2 = free_array[i];
888			if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
889					&pctx)) {
890				ext2fs_bg_free_inodes_count_set(fs, i, free_array[i]);
891				ext2fs_mark_super_dirty(fs);
892			} else
893				ext2fs_unmark_valid(fs);
894		}
895		if (dir_array[i] != ext2fs_bg_used_dirs_count(fs, i)) {
896			pctx.group = i;
897			pctx.ino = ext2fs_bg_used_dirs_count(fs, i);
898			pctx.ino2 = dir_array[i];
899
900			if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
901					&pctx)) {
902				ext2fs_bg_used_dirs_count_set(fs, i, dir_array[i]);
903				ext2fs_mark_super_dirty(fs);
904			} else
905				ext2fs_unmark_valid(fs);
906		}
907	}
908	if (free_inodes != fs->super->s_free_inodes_count) {
909		pctx.group = -1;
910		pctx.ino = fs->super->s_free_inodes_count;
911		pctx.ino2 = free_inodes;
912
913		if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
914			fs->super->s_free_inodes_count = free_inodes;
915			ext2fs_mark_super_dirty(fs);
916		}
917	}
918errout:
919	ext2fs_free_mem(&free_array);
920	ext2fs_free_mem(&dir_array);
921}
922
923static void check_inode_end(e2fsck_t ctx)
924{
925	ext2_filsys fs = ctx->fs;
926	ext2_ino_t	end, save_inodes_count, i;
927	struct problem_context	pctx;
928
929	clear_problem_context(&pctx);
930
931	end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
932	pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
933						     &save_inodes_count);
934	if (pctx.errcode) {
935		pctx.num = 1;
936		fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
937		ctx->flags |= E2F_FLAG_ABORT; /* fatal */
938		return;
939	}
940	if (save_inodes_count == end)
941		return;
942
943	/* protect loop from wrap-around if end is maxed */
944	for (i = save_inodes_count + 1; i <= end && i > save_inodes_count; i++) {
945		if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
946			if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
947				for (; i <= end; i++)
948					ext2fs_mark_inode_bitmap(fs->inode_map,
949								 i);
950				ext2fs_mark_ib_dirty(fs);
951			} else
952				ext2fs_unmark_valid(fs);
953			break;
954		}
955	}
956
957	pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
958						     save_inodes_count, 0);
959	if (pctx.errcode) {
960		pctx.num = 2;
961		fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
962		ctx->flags |= E2F_FLAG_ABORT; /* fatal */
963		return;
964	}
965}
966
967static void check_block_end(e2fsck_t ctx)
968{
969	ext2_filsys fs = ctx->fs;
970	blk64_t	end, save_blocks_count, i;
971	struct problem_context	pctx;
972
973	clear_problem_context(&pctx);
974
975	end = ext2fs_get_block_bitmap_start2(fs->block_map) +
976		((blk64_t)EXT2_CLUSTERS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
977	pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map, end,
978						     &save_blocks_count);
979	if (pctx.errcode) {
980		pctx.num = 3;
981		fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
982		ctx->flags |= E2F_FLAG_ABORT; /* fatal */
983		return;
984	}
985	if (save_blocks_count == end)
986		return;
987
988	/* Protect loop from wrap-around if end is maxed */
989	for (i = save_blocks_count + 1; i <= end && i > save_blocks_count; i++) {
990		if (!ext2fs_test_block_bitmap2(fs->block_map,
991					       EXT2FS_C2B(fs, i))) {
992			if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
993				for (; i <= end; i++)
994					ext2fs_mark_block_bitmap2(fs->block_map,
995							EXT2FS_C2B(fs, i));
996				ext2fs_mark_bb_dirty(fs);
997			} else
998				ext2fs_unmark_valid(fs);
999			break;
1000		}
1001	}
1002
1003	pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map,
1004						     save_blocks_count, 0);
1005	if (pctx.errcode) {
1006		pctx.num = 4;
1007		fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
1008		ctx->flags |= E2F_FLAG_ABORT; /* fatal */
1009		return;
1010	}
1011}
1012
1013
1014
1015