blob: e5964e669cf2b735bdc2b2daabb99d9f49a62c03 [file] [log] [blame]
Theodore Ts'o3839e651997-04-26 13:21:57 +00001/*
2 * pass5.c --- check block and inode bitmaps against on-disk bitmaps
3 *
Theodore Ts'o21c84b71997-04-29 16:15:03 +00004 * 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%
Theodore Ts'o3839e651997-04-26 13:21:57 +000010 *
11 */
12
Theodore Ts'o3839e651997-04-26 13:21:57 +000013#include "e2fsck.h"
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000014#include "problem.h"
Theodore Ts'o3839e651997-04-26 13:21:57 +000015
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000016static void check_block_bitmaps(e2fsck_t ctx);
17static void check_inode_bitmaps(e2fsck_t ctx);
18static void check_inode_end(e2fsck_t ctx);
19static void check_block_end(e2fsck_t ctx);
Theodore Ts'o3839e651997-04-26 13:21:57 +000020
Theodore Ts'o08b21301997-11-03 19:42:40 +000021void e2fsck_pass5(e2fsck_t ctx)
Theodore Ts'o3839e651997-04-26 13:21:57 +000022{
Theodore Ts'o8bf191e1997-10-20 01:38:32 +000023#ifdef RESOURCE_TRACK
Theodore Ts'o3839e651997-04-26 13:21:57 +000024 struct resource_track rtrack;
Theodore Ts'o8bf191e1997-10-20 01:38:32 +000025#endif
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000026 struct problem_context pctx;
Theodore Ts'o3839e651997-04-26 13:21:57 +000027
28#ifdef MTRACE
29 mtrace_print("Pass 5");
30#endif
31
Theodore Ts'o8bf191e1997-10-20 01:38:32 +000032#ifdef RESOURCE_TRACK
Theodore Ts'o3839e651997-04-26 13:21:57 +000033 init_resource_track(&rtrack);
Theodore Ts'o8bf191e1997-10-20 01:38:32 +000034#endif
Theodore Ts'o3839e651997-04-26 13:21:57 +000035
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000036 clear_problem_context(&pctx);
Theodore Ts'o3839e651997-04-26 13:21:57 +000037
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000038 if (!(ctx->options & E2F_OPT_PREEN))
39 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
Theodore Ts'o3839e651997-04-26 13:21:57 +000040
Theodore Ts'of8188ff1997-11-14 05:23:04 +000041 if (ctx->progress)
Theodore Ts'oefac9a11998-05-07 05:02:00 +000042 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
Theodore Ts'oa02ce9d1998-02-24 20:22:23 +000043 return;
Theodore Ts'of8188ff1997-11-14 05:23:04 +000044
45 e2fsck_read_bitmaps(ctx);
46
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000047 check_block_bitmaps(ctx);
Theodore Ts'oa02ce9d1998-02-24 20:22:23 +000048 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
Theodore Ts'o08b21301997-11-03 19:42:40 +000049 return;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000050 check_inode_bitmaps(ctx);
Theodore Ts'oa02ce9d1998-02-24 20:22:23 +000051 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
Theodore Ts'o08b21301997-11-03 19:42:40 +000052 return;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000053 check_inode_end(ctx);
Theodore Ts'oa02ce9d1998-02-24 20:22:23 +000054 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
Theodore Ts'o08b21301997-11-03 19:42:40 +000055 return;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000056 check_block_end(ctx);
Theodore Ts'oa02ce9d1998-02-24 20:22:23 +000057 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
Theodore Ts'o08b21301997-11-03 19:42:40 +000058 return;
Theodore Ts'o3839e651997-04-26 13:21:57 +000059
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000060 ext2fs_free_inode_bitmap(ctx->inode_used_map);
61 ctx->inode_used_map = 0;
62 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
63 ctx->inode_dir_map = 0;
64 ext2fs_free_block_bitmap(ctx->block_found_map);
65 ctx->block_found_map = 0;
66
Theodore Ts'o8bf191e1997-10-20 01:38:32 +000067#ifdef RESOURCE_TRACK
Theodore Ts'o5596def1999-07-19 15:27:37 +000068 if (ctx->options & E2F_OPT_TIME2) {
69 e2fsck_clear_progbar(ctx);
Theodore Ts'o0c4a0722000-02-07 03:11:03 +000070 print_resource_track(_("Pass 5"), &rtrack);
Theodore Ts'o5596def1999-07-19 15:27:37 +000071 }
Theodore Ts'o8bf191e1997-10-20 01:38:32 +000072#endif
Theodore Ts'o3839e651997-04-26 13:21:57 +000073}
74
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000075static void check_block_bitmaps(e2fsck_t ctx)
Theodore Ts'o3839e651997-04-26 13:21:57 +000076{
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000077 ext2_filsys fs = ctx->fs;
Theodore Ts'of3db3561997-04-26 13:34:30 +000078 blk_t i;
Theodore Ts'o3839e651997-04-26 13:21:57 +000079 int *free_array;
80 int group = 0;
81 int blocks = 0;
82 int free_blocks = 0;
83 int group_free = 0;
84 int actual, bitmap;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000085 struct problem_context pctx;
Theodore Ts'o63c49691998-02-20 05:24:59 +000086 int problem, fixit, had_problem;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000087 errcode_t retval;
Theodore Ts'o3839e651997-04-26 13:21:57 +000088
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000089 clear_problem_context(&pctx);
Theodore Ts'o54dc7ca1998-01-19 14:50:49 +000090 free_array = (int *) e2fsck_allocate_memory(ctx,
Theodore Ts'of8188ff1997-11-14 05:23:04 +000091 fs->group_desc_count * sizeof(int), "free block count array");
Theodore Ts'o50e1e101997-04-26 13:58:21 +000092
93 if ((fs->super->s_first_data_block <
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000094 ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
Theodore Ts'o50e1e101997-04-26 13:58:21 +000095 (fs->super->s_blocks_count-1 >
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000096 ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
97 pctx.num = 1;
98 pctx.blk = fs->super->s_first_data_block;
99 pctx.blk2 = fs->super->s_blocks_count -1;
100 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
101 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
102 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
Theodore Ts'o08b21301997-11-03 19:42:40 +0000103
104 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
105 return;
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000106 }
107
108 if ((fs->super->s_first_data_block <
109 ext2fs_get_block_bitmap_start(fs->block_map)) ||
110 (fs->super->s_blocks_count-1 >
111 ext2fs_get_block_bitmap_end(fs->block_map))) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000112 pctx.num = 2;
113 pctx.blk = fs->super->s_first_data_block;
114 pctx.blk2 = fs->super->s_blocks_count -1;
115 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
116 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
117 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
Theodore Ts'o08b21301997-11-03 19:42:40 +0000118
119 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
120 return;
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000121 }
122
Theodore Ts'o63c49691998-02-20 05:24:59 +0000123redo_counts:
124 had_problem = 0;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000125 for (i = fs->super->s_first_data_block;
126 i < fs->super->s_blocks_count;
127 i++) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000128 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000129 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000130
131 if (actual == bitmap)
132 goto do_counts;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000133
Theodore Ts'o3839e651997-04-26 13:21:57 +0000134 if (!actual && bitmap) {
135 /*
136 * Block not used, but marked in use in the bitmap.
137 */
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000138 problem = PR_5_UNUSED_BLOCK;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000139 } else {
140 /*
141 * Block used, but not marked in use in the bitmap.
142 */
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000143 problem = PR_5_BLOCK_USED;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000144 }
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000145 pctx.blk = i;
146 fix_problem(ctx, problem, &pctx);
Theodore Ts'o5596def1999-07-19 15:27:37 +0000147 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
Theodore Ts'o63c49691998-02-20 05:24:59 +0000148 had_problem++;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000149
Theodore Ts'o3839e651997-04-26 13:21:57 +0000150 do_counts:
151 if (!bitmap) {
152 group_free++;
153 free_blocks++;
154 }
155 blocks ++;
156 if ((blocks == fs->super->s_blocks_per_group) ||
157 (i == fs->super->s_blocks_count-1)) {
158 free_array[group] = group_free;
159 group ++;
160 blocks = 0;
161 group_free = 0;
Theodore Ts'oefac9a11998-05-07 05:02:00 +0000162 if (ctx->progress)
163 if ((ctx->progress)(ctx, 5, group,
164 fs->group_desc_count*2))
165 return;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000166 }
167 }
Theodore Ts'o63c49691998-02-20 05:24:59 +0000168 if (had_problem)
169 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
170 else
171 fixit = -1;
Theodore Ts'o5596def1999-07-19 15:27:37 +0000172 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
173
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000174 if (fixit == 1) {
175 ext2fs_free_block_bitmap(fs->block_map);
176 retval = ext2fs_copy_bitmap(ctx->block_found_map,
177 &fs->block_map);
Theodore Ts'obbd47d72000-06-10 19:21:33 +0000178 if (retval) {
179 clear_problem_context(&pctx);
180 fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
181 ctx->flags |= E2F_FLAG_ABORT;
182 return;
183 }
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000184 ext2fs_set_bitmap_padding(fs->block_map);
185 ext2fs_mark_bb_dirty(fs);
186
187 /* Redo the counts */
188 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
189 memset(free_array, 0, fs->group_desc_count * sizeof(int));
190 goto redo_counts;
191 } else if (fixit == 0)
192 ext2fs_unmark_valid(fs);
193
Theodore Ts'o3839e651997-04-26 13:21:57 +0000194 for (i = 0; i < fs->group_desc_count; i++) {
195 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000196 pctx.group = i;
197 pctx.blk = fs->group_desc[i].bg_free_blocks_count;
198 pctx.blk2 = free_array[i];
199
200 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
201 &pctx)) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000202 fs->group_desc[i].bg_free_blocks_count =
203 free_array[i];
204 ext2fs_mark_super_dirty(fs);
205 } else
206 ext2fs_unmark_valid(fs);
207 }
208 }
209 if (free_blocks != fs->super->s_free_blocks_count) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000210 pctx.group = 0;
211 pctx.blk = fs->super->s_free_blocks_count;
212 pctx.blk2 = free_blocks;
213
214 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000215 fs->super->s_free_blocks_count = free_blocks;
216 ext2fs_mark_super_dirty(fs);
217 } else
218 ext2fs_unmark_valid(fs);
219 }
Theodore Ts'o08b21301997-11-03 19:42:40 +0000220 ext2fs_free_mem((void **) &free_array);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000221}
222
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000223static void check_inode_bitmaps(e2fsck_t ctx)
Theodore Ts'o3839e651997-04-26 13:21:57 +0000224{
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000225 ext2_filsys fs = ctx->fs;
Theodore Ts'o86c627e2001-01-11 15:12:14 +0000226 ext2_ino_t i;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000227 int free_inodes = 0;
228 int group_free = 0;
229 int dirs_count = 0;
230 int group = 0;
231 int inodes = 0;
232 int *free_array;
233 int *dir_array;
234 int actual, bitmap;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000235 errcode_t retval;
236 struct problem_context pctx;
Theodore Ts'o63c49691998-02-20 05:24:59 +0000237 int problem, fixit, had_problem;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000238
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000239 clear_problem_context(&pctx);
Theodore Ts'o54dc7ca1998-01-19 14:50:49 +0000240 free_array = (int *) e2fsck_allocate_memory(ctx,
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000241 fs->group_desc_count * sizeof(int), "free inode count array");
Theodore Ts'o3839e651997-04-26 13:21:57 +0000242
Theodore Ts'o54dc7ca1998-01-19 14:50:49 +0000243 dir_array = (int *) e2fsck_allocate_memory(ctx,
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000244 fs->group_desc_count * sizeof(int), "directory count array");
Theodore Ts'o3839e651997-04-26 13:21:57 +0000245
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000246 if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000247 (fs->super->s_inodes_count >
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000248 ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
249 pctx.num = 3;
250 pctx.blk = 1;
251 pctx.blk2 = fs->super->s_inodes_count;
252 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
253 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
254 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
Theodore Ts'o08b21301997-11-03 19:42:40 +0000255
256 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
257 return;
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000258 }
259 if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
260 (fs->super->s_inodes_count >
261 ext2fs_get_inode_bitmap_end(fs->inode_map))) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000262 pctx.num = 4;
263 pctx.blk = 1;
264 pctx.blk2 = fs->super->s_inodes_count;
265 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
266 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
267 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
Theodore Ts'o08b21301997-11-03 19:42:40 +0000268
269 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
270 return;
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000271 }
272
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000273redo_counts:
Theodore Ts'o63c49691998-02-20 05:24:59 +0000274 had_problem = 0;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000275 for (i = 1; i <= fs->super->s_inodes_count; i++) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000276 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000277 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000278
279 if (actual == bitmap)
280 goto do_counts;
281
Theodore Ts'o3839e651997-04-26 13:21:57 +0000282 if (!actual && bitmap) {
283 /*
284 * Inode wasn't used, but marked in bitmap
285 */
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000286 problem = PR_5_UNUSED_INODE;
287 } else /* if (actual && !bitmap) */ {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000288 /*
289 * Inode used, but not in bitmap
290 */
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000291 problem = PR_5_INODE_USED;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000292 }
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000293 pctx.ino = i;
294 fix_problem(ctx, problem, &pctx);
Theodore Ts'o5596def1999-07-19 15:27:37 +0000295 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
Theodore Ts'o63c49691998-02-20 05:24:59 +0000296 had_problem++;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000297
Theodore Ts'o3839e651997-04-26 13:21:57 +0000298do_counts:
299 if (!bitmap) {
300 group_free++;
301 free_inodes++;
302 } else {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000303 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
Theodore Ts'o3839e651997-04-26 13:21:57 +0000304 dirs_count++;
305 }
306 inodes++;
307 if ((inodes == fs->super->s_inodes_per_group) ||
308 (i == fs->super->s_inodes_count)) {
309 free_array[group] = group_free;
310 dir_array[group] = dirs_count;
311 group ++;
312 inodes = 0;
313 group_free = 0;
314 dirs_count = 0;
Theodore Ts'oefac9a11998-05-07 05:02:00 +0000315 if (ctx->progress)
316 if ((ctx->progress)(ctx, 5,
317 group + fs->group_desc_count,
318 fs->group_desc_count*2))
319 return;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000320 }
321 }
Theodore Ts'o63c49691998-02-20 05:24:59 +0000322 if (had_problem)
323 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
324 else
325 fixit = -1;
Theodore Ts'o5596def1999-07-19 15:27:37 +0000326 ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
327
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000328 if (fixit == 1) {
329 ext2fs_free_inode_bitmap(fs->inode_map);
330 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
331 &fs->inode_map);
Theodore Ts'obbd47d72000-06-10 19:21:33 +0000332 if (retval) {
333 clear_problem_context(&pctx);
334 fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
335 ctx->flags |= E2F_FLAG_ABORT;
336 return;
337 }
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000338 ext2fs_set_bitmap_padding(fs->inode_map);
339 ext2fs_mark_ib_dirty(fs);
340
341 /* redo counts */
342 inodes = 0; free_inodes = 0; group_free = 0;
343 dirs_count = 0; group = 0;
344 memset(free_array, 0, fs->group_desc_count * sizeof(int));
345 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
346 goto redo_counts;
347 } else if (fixit == 0)
348 ext2fs_unmark_valid(fs);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000349
350 for (i = 0; i < fs->group_desc_count; i++) {
351 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000352 pctx.group = i;
353 pctx.ino = fs->group_desc[i].bg_free_inodes_count;
354 pctx.ino2 = free_array[i];
355 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
356 &pctx)) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000357 fs->group_desc[i].bg_free_inodes_count =
358 free_array[i];
359 ext2fs_mark_super_dirty(fs);
360 } else
361 ext2fs_unmark_valid(fs);
362 }
363 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000364 pctx.group = i;
365 pctx.ino = fs->group_desc[i].bg_used_dirs_count;
366 pctx.ino2 = dir_array[i];
367
368 if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
369 &pctx)) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000370 fs->group_desc[i].bg_used_dirs_count =
371 dir_array[i];
372 ext2fs_mark_super_dirty(fs);
373 } else
374 ext2fs_unmark_valid(fs);
375 }
376 }
377 if (free_inodes != fs->super->s_free_inodes_count) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000378 pctx.group = -1;
379 pctx.ino = fs->super->s_free_inodes_count;
380 pctx.ino2 = free_inodes;
381
382 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000383 fs->super->s_free_inodes_count = free_inodes;
384 ext2fs_mark_super_dirty(fs);
385 } else
386 ext2fs_unmark_valid(fs);
387 }
Theodore Ts'o08b21301997-11-03 19:42:40 +0000388 ext2fs_free_mem((void **) &free_array);
389 ext2fs_free_mem((void **) &dir_array);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000390}
391
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000392static void check_inode_end(e2fsck_t ctx)
Theodore Ts'o3839e651997-04-26 13:21:57 +0000393{
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000394 ext2_filsys fs = ctx->fs;
Theodore Ts'o86c627e2001-01-11 15:12:14 +0000395 ext2_ino_t end, save_inodes_count, i;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000396 struct problem_context pctx;
397
398 clear_problem_context(&pctx);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000399
400 end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000401 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
402 &save_inodes_count);
403 if (pctx.errcode) {
404 pctx.num = 1;
405 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
Theodore Ts'o08b21301997-11-03 19:42:40 +0000406 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
407 return;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000408 }
Theodore Ts'o3839e651997-04-26 13:21:57 +0000409 if (save_inodes_count == end)
410 return;
411
Theodore Ts'o3839e651997-04-26 13:21:57 +0000412 for (i = save_inodes_count + 1; i <= end; i++) {
Theodore Ts'of3db3561997-04-26 13:34:30 +0000413 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000414 if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000415 for (i = save_inodes_count + 1; i <= end; i++)
Theodore Ts'of3db3561997-04-26 13:34:30 +0000416 ext2fs_mark_inode_bitmap(fs->inode_map,
Theodore Ts'o3839e651997-04-26 13:21:57 +0000417 i);
418 ext2fs_mark_ib_dirty(fs);
419 } else
420 ext2fs_unmark_valid(fs);
421 break;
422 }
423 }
424
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000425 pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
426 save_inodes_count, 0);
427 if (pctx.errcode) {
428 pctx.num = 2;
429 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
Theodore Ts'o08b21301997-11-03 19:42:40 +0000430 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
431 return;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000432 }
Theodore Ts'o3839e651997-04-26 13:21:57 +0000433}
434
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000435static void check_block_end(e2fsck_t ctx)
Theodore Ts'o3839e651997-04-26 13:21:57 +0000436{
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000437 ext2_filsys fs = ctx->fs;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000438 blk_t end, save_blocks_count, i;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000439 struct problem_context pctx;
440
441 clear_problem_context(&pctx);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000442
Theodore Ts'of3db3561997-04-26 13:34:30 +0000443 end = fs->block_map->start +
444 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000445 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
446 &save_blocks_count);
447 if (pctx.errcode) {
448 pctx.num = 3;
449 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
Theodore Ts'o08b21301997-11-03 19:42:40 +0000450 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
451 return;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000452 }
Theodore Ts'o3839e651997-04-26 13:21:57 +0000453 if (save_blocks_count == end)
454 return;
455
Theodore Ts'of3db3561997-04-26 13:34:30 +0000456 for (i = save_blocks_count + 1; i <= end; i++) {
457 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000458 if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
Theodore Ts'oe79d1b21999-06-18 01:06:59 +0000459 for (i = save_blocks_count + 1; i <= end; i++)
Theodore Ts'of3db3561997-04-26 13:34:30 +0000460 ext2fs_mark_block_bitmap(fs->block_map,
Theodore Ts'o3839e651997-04-26 13:21:57 +0000461 i);
462 ext2fs_mark_bb_dirty(fs);
463 } else
464 ext2fs_unmark_valid(fs);
465 break;
466 }
467 }
468
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000469 pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
470 save_blocks_count, 0);
471 if (pctx.errcode) {
472 pctx.num = 4;
473 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
Theodore Ts'o08b21301997-11-03 19:42:40 +0000474 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
475 return;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000476 }
Theodore Ts'o3839e651997-04-26 13:21:57 +0000477}
478
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000479
480