]>
Commit | Line | Data |
---|---|---|
3839e657 TT |
1 | /* |
2 | * pass5.c --- check block and inode bitmaps against on-disk bitmaps | |
efc6f628 | 3 | * |
21c84b71 TT |
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% | |
efc6f628 | 10 | * |
3839e657 TT |
11 | */ |
12 | ||
3839e657 | 13 | #include "e2fsck.h" |
1b6bf175 | 14 | #include "problem.h" |
3839e657 | 15 | |
1b6bf175 TT |
16 | static void check_block_bitmaps(e2fsck_t ctx); |
17 | static void check_inode_bitmaps(e2fsck_t ctx); | |
18 | static void check_inode_end(e2fsck_t ctx); | |
19 | static void check_block_end(e2fsck_t ctx); | |
3839e657 | 20 | |
08b21301 | 21 | void e2fsck_pass5(e2fsck_t ctx) |
3839e657 | 22 | { |
8bf191e8 | 23 | #ifdef RESOURCE_TRACK |
3839e657 | 24 | struct resource_track rtrack; |
8bf191e8 | 25 | #endif |
1b6bf175 | 26 | struct problem_context pctx; |
efc6f628 | 27 | |
3839e657 TT |
28 | #ifdef MTRACE |
29 | mtrace_print("Pass 5"); | |
30 | #endif | |
31 | ||
6d96b00d | 32 | init_resource_track(&rtrack, ctx->fs->io); |
1b6bf175 | 33 | clear_problem_context(&pctx); |
3839e657 | 34 | |
1b6bf175 TT |
35 | if (!(ctx->options & E2F_OPT_PREEN)) |
36 | fix_problem(ctx, PR_5_PASS_HEADER, &pctx); | |
3839e657 | 37 | |
f8188fff | 38 | if (ctx->progress) |
efac9a1b | 39 | if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2)) |
a02ce9df | 40 | return; |
f8188fff TT |
41 | |
42 | e2fsck_read_bitmaps(ctx); | |
43 | ||
1b6bf175 | 44 | check_block_bitmaps(ctx); |
a02ce9df | 45 | if (ctx->flags & E2F_FLAG_SIGNAL_MASK) |
08b21301 | 46 | return; |
1b6bf175 | 47 | check_inode_bitmaps(ctx); |
a02ce9df | 48 | if (ctx->flags & E2F_FLAG_SIGNAL_MASK) |
08b21301 | 49 | return; |
1b6bf175 | 50 | check_inode_end(ctx); |
a02ce9df | 51 | if (ctx->flags & E2F_FLAG_SIGNAL_MASK) |
08b21301 | 52 | return; |
1b6bf175 | 53 | check_block_end(ctx); |
a02ce9df | 54 | if (ctx->flags & E2F_FLAG_SIGNAL_MASK) |
08b21301 | 55 | return; |
3839e657 | 56 | |
1b6bf175 TT |
57 | ext2fs_free_inode_bitmap(ctx->inode_used_map); |
58 | ctx->inode_used_map = 0; | |
59 | ext2fs_free_inode_bitmap(ctx->inode_dir_map); | |
60 | ctx->inode_dir_map = 0; | |
61 | ext2fs_free_block_bitmap(ctx->block_found_map); | |
62 | ctx->block_found_map = 0; | |
63 | ||
9facd076 | 64 | print_resource_track(ctx, _("Pass 5"), &rtrack, ctx->fs->io); |
3839e657 TT |
65 | } |
66 | ||
f122632e TT |
67 | #define NO_BLK ((blk_t) -1) |
68 | ||
546a1ff1 | 69 | static void print_bitmap_problem(e2fsck_t ctx, int problem, |
f122632e TT |
70 | struct problem_context *pctx) |
71 | { | |
72 | switch (problem) { | |
73 | case PR_5_BLOCK_UNUSED: | |
74 | if (pctx->blk == pctx->blk2) | |
75 | pctx->blk2 = 0; | |
76 | else | |
77 | problem = PR_5_BLOCK_RANGE_UNUSED; | |
78 | break; | |
79 | case PR_5_BLOCK_USED: | |
80 | if (pctx->blk == pctx->blk2) | |
81 | pctx->blk2 = 0; | |
82 | else | |
83 | problem = PR_5_BLOCK_RANGE_USED; | |
84 | break; | |
85 | case PR_5_INODE_UNUSED: | |
86 | if (pctx->ino == pctx->ino2) | |
87 | pctx->ino2 = 0; | |
88 | else | |
89 | problem = PR_5_INODE_RANGE_UNUSED; | |
90 | break; | |
91 | case PR_5_INODE_USED: | |
92 | if (pctx->ino == pctx->ino2) | |
93 | pctx->ino2 = 0; | |
94 | else | |
95 | problem = PR_5_INODE_RANGE_USED; | |
96 | break; | |
97 | } | |
98 | fix_problem(ctx, problem, pctx); | |
99 | pctx->blk = pctx->blk2 = NO_BLK; | |
100 | pctx->ino = pctx->ino2 = 0; | |
101 | } | |
49e2df29 | 102 | |
1b6bf175 | 103 | static void check_block_bitmaps(e2fsck_t ctx) |
3839e657 | 104 | { |
1b6bf175 | 105 | ext2_filsys fs = ctx->fs; |
20f2ccb3 | 106 | blk64_t i; |
3839e657 TT |
107 | int *free_array; |
108 | int group = 0; | |
5d38ef1d VC |
109 | blk_t blocks = 0; |
110 | blk_t free_blocks = 0; | |
3839e657 TT |
111 | int group_free = 0; |
112 | int actual, bitmap; | |
1b6bf175 | 113 | struct problem_context pctx; |
f122632e | 114 | int problem, save_problem, fixit, had_problem; |
1b6bf175 | 115 | errcode_t retval; |
16b851cd | 116 | int csum_flag; |
f5fa2007 | 117 | int skip_group = 0; |
479463aa KM |
118 | int old_desc_blocks = 0; |
119 | int count = 0; | |
120 | int cmp_block = 0; | |
121 | int redo_flag = 0; | |
20f2ccb3 | 122 | blk64_t super_blk, old_desc_blk, new_desc_blk; |
49e2df29 | 123 | |
1b6bf175 | 124 | clear_problem_context(&pctx); |
54dc7ca2 | 125 | free_array = (int *) e2fsck_allocate_memory(ctx, |
f8188fff | 126 | fs->group_desc_count * sizeof(int), "free block count array"); |
50e1e10f TT |
127 | |
128 | if ((fs->super->s_first_data_block < | |
c5d2f50d | 129 | ext2fs_get_block_bitmap_start2(ctx->block_found_map)) || |
4efbac6f | 130 | (ext2fs_blocks_count(fs->super)-1 > |
c5d2f50d | 131 | ext2fs_get_block_bitmap_end2(ctx->block_found_map))) { |
1b6bf175 TT |
132 | pctx.num = 1; |
133 | pctx.blk = fs->super->s_first_data_block; | |
4efbac6f | 134 | pctx.blk2 = ext2fs_blocks_count(fs->super) -1; |
c5d2f50d VAH |
135 | pctx.ino = ext2fs_get_block_bitmap_start2(ctx->block_found_map); |
136 | pctx.ino2 = ext2fs_get_block_bitmap_end2(ctx->block_found_map); | |
1b6bf175 | 137 | fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx); |
08b21301 TT |
138 | |
139 | ctx->flags |= E2F_FLAG_ABORT; /* fatal */ | |
49e2df29 | 140 | goto errout; |
50e1e10f | 141 | } |
49e2df29 | 142 | |
50e1e10f | 143 | if ((fs->super->s_first_data_block < |
c5d2f50d | 144 | ext2fs_get_block_bitmap_start2(fs->block_map)) || |
4efbac6f | 145 | (ext2fs_blocks_count(fs->super)-1 > |
c5d2f50d | 146 | ext2fs_get_block_bitmap_end2(fs->block_map))) { |
1b6bf175 TT |
147 | pctx.num = 2; |
148 | pctx.blk = fs->super->s_first_data_block; | |
4efbac6f | 149 | pctx.blk2 = ext2fs_blocks_count(fs->super) -1; |
c5d2f50d VAH |
150 | pctx.ino = ext2fs_get_block_bitmap_start2(fs->block_map); |
151 | pctx.ino2 = ext2fs_get_block_bitmap_end2(fs->block_map); | |
1b6bf175 | 152 | fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx); |
08b21301 TT |
153 | |
154 | ctx->flags |= E2F_FLAG_ABORT; /* fatal */ | |
49e2df29 | 155 | goto errout; |
50e1e10f | 156 | } |
49e2df29 | 157 | |
49a7360b JS |
158 | csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super, |
159 | EXT4_FEATURE_RO_COMPAT_GDT_CSUM); | |
63c4969c TT |
160 | redo_counts: |
161 | had_problem = 0; | |
f122632e TT |
162 | save_problem = 0; |
163 | pctx.blk = pctx.blk2 = NO_BLK; | |
16b851cd | 164 | if (csum_flag && |
cd65a24e | 165 | (ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT))) |
f5fa2007 | 166 | skip_group++; |
3839e657 | 167 | for (i = fs->super->s_first_data_block; |
4efbac6f | 168 | i < ext2fs_blocks_count(fs->super); |
3839e657 | 169 | i++) { |
c5d2f50d | 170 | actual = ext2fs_fast_test_block_bitmap2(ctx->block_found_map, i); |
f5fa2007 TT |
171 | |
172 | if (skip_group) { | |
479463aa KM |
173 | if ((i - fs->super->s_first_data_block) % |
174 | fs->super->s_blocks_per_group == 0) { | |
175 | super_blk = 0; | |
176 | old_desc_blk = 0; | |
177 | new_desc_blk = 0; | |
20f2ccb3 | 178 | ext2fs_super_and_bgd_loc2(fs, group, &super_blk, |
4a2924ea TT |
179 | &old_desc_blk, &new_desc_blk, 0); |
180 | ||
479463aa KM |
181 | if (fs->super->s_feature_incompat & |
182 | EXT2_FEATURE_INCOMPAT_META_BG) | |
183 | old_desc_blocks = | |
184 | fs->super->s_first_meta_bg; | |
185 | else | |
186 | old_desc_blocks = fs->desc_blocks + | |
4a2924ea TT |
187 | fs->super->s_reserved_gdt_blocks; |
188 | ||
479463aa KM |
189 | count = 0; |
190 | cmp_block = fs->super->s_blocks_per_group; | |
191 | if (group == (int)fs->group_desc_count - 1) | |
192 | cmp_block = | |
4efbac6f | 193 | ext2fs_blocks_count(fs->super) % |
479463aa KM |
194 | fs->super->s_blocks_per_group; |
195 | } | |
196 | ||
4a2924ea | 197 | bitmap = 0; |
479463aa KM |
198 | if ((i == super_blk) || |
199 | (old_desc_blk && old_desc_blocks && | |
200 | (i >= old_desc_blk) && | |
201 | (i < old_desc_blk + old_desc_blocks)) || | |
202 | (new_desc_blk && (i == new_desc_blk)) || | |
203 | (i == fs->group_desc[group].bg_block_bitmap) || | |
204 | (i == fs->group_desc[group].bg_inode_bitmap) || | |
205 | (i >= fs->group_desc[group].bg_inode_table && | |
206 | (i < fs->group_desc[group].bg_inode_table + | |
207 | fs->inode_blocks_per_group))) { | |
4a2924ea | 208 | bitmap = 1; |
479463aa KM |
209 | actual = (actual != 0); |
210 | count++; | |
211 | cmp_block--; | |
212 | } else if ((i - count - fs->super->s_first_data_block) % | |
213 | fs->super->s_blocks_per_group == 0) { | |
214 | /* | |
215 | * When the compare data blocks in block bitmap | |
216 | * are 0, count the free block, | |
217 | * skip the current block group. | |
218 | */ | |
c5d2f50d | 219 | if (ext2fs_test_block_bitmap_range2( |
479463aa KM |
220 | ctx->block_found_map, i, |
221 | cmp_block)) { | |
222 | /* | |
223 | * -1 means to skip the current block | |
224 | * group. | |
225 | */ | |
226 | blocks = fs->super->s_blocks_per_group | |
227 | - 1; | |
228 | group_free = cmp_block; | |
229 | free_blocks += cmp_block; | |
230 | /* | |
231 | * The current block group's last block | |
232 | * is set to i. | |
233 | */ | |
234 | i += cmp_block - 1; | |
235 | bitmap = 1; | |
236 | goto do_counts; | |
237 | } | |
238 | } | |
239 | } else if (redo_flag) | |
240 | bitmap = actual; | |
241 | else | |
c5d2f50d | 242 | bitmap = ext2fs_fast_test_block_bitmap2(fs->block_map, i); |
49e2df29 | 243 | |
3839e657 TT |
244 | if (actual == bitmap) |
245 | goto do_counts; | |
f5fa2007 | 246 | |
3839e657 TT |
247 | if (!actual && bitmap) { |
248 | /* | |
249 | * Block not used, but marked in use in the bitmap. | |
250 | */ | |
f122632e | 251 | problem = PR_5_BLOCK_UNUSED; |
3839e657 TT |
252 | } else { |
253 | /* | |
254 | * Block used, but not marked in use in the bitmap. | |
255 | */ | |
1b6bf175 | 256 | problem = PR_5_BLOCK_USED; |
49a7360b JS |
257 | |
258 | if (skip_group) { | |
259 | struct problem_context pctx2; | |
260 | pctx2.blk = i; | |
261 | pctx2.group = group; | |
262 | if (fix_problem(ctx, PR_5_BLOCK_UNINIT,&pctx2)){ | |
e633b58a | 263 | ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT); |
49a7360b JS |
264 | skip_group = 0; |
265 | } | |
266 | } | |
3839e657 | 267 | } |
f122632e TT |
268 | if (pctx.blk == NO_BLK) { |
269 | pctx.blk = pctx.blk2 = i; | |
270 | save_problem = problem; | |
271 | } else { | |
272 | if ((problem == save_problem) && | |
273 | (pctx.blk2 == i-1)) | |
274 | pctx.blk2++; | |
275 | else { | |
276 | print_bitmap_problem(ctx, save_problem, &pctx); | |
277 | pctx.blk = pctx.blk2 = i; | |
278 | save_problem = problem; | |
279 | } | |
280 | } | |
5596defa | 281 | ctx->flags |= E2F_FLAG_PROG_SUPPRESS; |
63c4969c | 282 | had_problem++; |
49e2df29 | 283 | |
3839e657 | 284 | do_counts: |
49a7360b | 285 | if (!bitmap && (!skip_group || csum_flag)) { |
3839e657 TT |
286 | group_free++; |
287 | free_blocks++; | |
288 | } | |
289 | blocks ++; | |
290 | if ((blocks == fs->super->s_blocks_per_group) || | |
4efbac6f | 291 | (i == ext2fs_blocks_count(fs->super)-1)) { |
3839e657 TT |
292 | free_array[group] = group_free; |
293 | group ++; | |
294 | blocks = 0; | |
295 | group_free = 0; | |
f5fa2007 | 296 | skip_group = 0; |
efac9a1b TT |
297 | if (ctx->progress) |
298 | if ((ctx->progress)(ctx, 5, group, | |
299 | fs->group_desc_count*2)) | |
49e2df29 | 300 | goto errout; |
16b851cd | 301 | if (csum_flag && |
4efbac6f | 302 | (i != ext2fs_blocks_count(fs->super)-1) && |
cd65a24e | 303 | ext2fs_bg_flags_test(fs, group, |
732c8cd5 | 304 | EXT2_BG_BLOCK_UNINIT)) |
f5fa2007 | 305 | skip_group++; |
3839e657 TT |
306 | } |
307 | } | |
f122632e TT |
308 | if (pctx.blk != NO_BLK) |
309 | print_bitmap_problem(ctx, save_problem, &pctx); | |
63c4969c | 310 | if (had_problem) |
f122632e | 311 | fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP); |
63c4969c TT |
312 | else |
313 | fixit = -1; | |
5596defa | 314 | ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS; |
49e2df29 | 315 | |
1b6bf175 TT |
316 | if (fixit == 1) { |
317 | ext2fs_free_block_bitmap(fs->block_map); | |
318 | retval = ext2fs_copy_bitmap(ctx->block_found_map, | |
319 | &fs->block_map); | |
bbd47d76 TT |
320 | if (retval) { |
321 | clear_problem_context(&pctx); | |
322 | fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx); | |
323 | ctx->flags |= E2F_FLAG_ABORT; | |
49e2df29 | 324 | goto errout; |
bbd47d76 | 325 | } |
1b6bf175 TT |
326 | ext2fs_set_bitmap_padding(fs->block_map); |
327 | ext2fs_mark_bb_dirty(fs); | |
49e2df29 | 328 | |
1b6bf175 TT |
329 | /* Redo the counts */ |
330 | blocks = 0; free_blocks = 0; group_free = 0; group = 0; | |
331 | memset(free_array, 0, fs->group_desc_count * sizeof(int)); | |
479463aa | 332 | redo_flag++; |
1b6bf175 TT |
333 | goto redo_counts; |
334 | } else if (fixit == 0) | |
335 | ext2fs_unmark_valid(fs); | |
336 | ||
3839e657 TT |
337 | for (i = 0; i < fs->group_desc_count; i++) { |
338 | if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) { | |
1b6bf175 TT |
339 | pctx.group = i; |
340 | pctx.blk = fs->group_desc[i].bg_free_blocks_count; | |
341 | pctx.blk2 = free_array[i]; | |
342 | ||
343 | if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP, | |
344 | &pctx)) { | |
e633b58a | 345 | ext2fs_bg_free_blocks_count_set(fs, i, free_array[i]); |
3839e657 TT |
346 | ext2fs_mark_super_dirty(fs); |
347 | } else | |
348 | ext2fs_unmark_valid(fs); | |
349 | } | |
350 | } | |
4efbac6f | 351 | if (free_blocks != ext2fs_free_blocks_count(fs->super)) { |
1b6bf175 | 352 | pctx.group = 0; |
4efbac6f | 353 | pctx.blk = ext2fs_free_blocks_count(fs->super); |
1b6bf175 TT |
354 | pctx.blk2 = free_blocks; |
355 | ||
356 | if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) { | |
4efbac6f | 357 | ext2fs_free_blocks_count_set(fs->super, free_blocks); |
3839e657 TT |
358 | ext2fs_mark_super_dirty(fs); |
359 | } else | |
360 | ext2fs_unmark_valid(fs); | |
361 | } | |
49e2df29 | 362 | errout: |
c4e3d3f3 | 363 | ext2fs_free_mem(&free_array); |
3839e657 | 364 | } |
49e2df29 | 365 | |
1b6bf175 | 366 | static void check_inode_bitmaps(e2fsck_t ctx) |
3839e657 | 367 | { |
1b6bf175 | 368 | ext2_filsys fs = ctx->fs; |
86c627ec | 369 | ext2_ino_t i; |
54434927 TT |
370 | unsigned int free_inodes = 0; |
371 | int group_free = 0; | |
372 | int dirs_count = 0; | |
373 | int group = 0; | |
374 | unsigned int inodes = 0; | |
375 | int *free_array; | |
376 | int *dir_array; | |
377 | int actual, bitmap; | |
1b6bf175 TT |
378 | errcode_t retval; |
379 | struct problem_context pctx; | |
54434927 | 380 | int problem, save_problem, fixit, had_problem; |
16b851cd | 381 | int csum_flag; |
f5fa2007 | 382 | int skip_group = 0; |
479463aa | 383 | int redo_flag = 0; |
49e2df29 | 384 | |
1b6bf175 | 385 | clear_problem_context(&pctx); |
54dc7ca2 | 386 | free_array = (int *) e2fsck_allocate_memory(ctx, |
f8188fff | 387 | fs->group_desc_count * sizeof(int), "free inode count array"); |
49e2df29 | 388 | |
54dc7ca2 | 389 | dir_array = (int *) e2fsck_allocate_memory(ctx, |
f8188fff | 390 | fs->group_desc_count * sizeof(int), "directory count array"); |
49e2df29 | 391 | |
c5d2f50d | 392 | if ((1 < ext2fs_get_inode_bitmap_start2(ctx->inode_used_map)) || |
49e2df29 | 393 | (fs->super->s_inodes_count > |
c5d2f50d | 394 | ext2fs_get_inode_bitmap_end2(ctx->inode_used_map))) { |
1b6bf175 TT |
395 | pctx.num = 3; |
396 | pctx.blk = 1; | |
397 | pctx.blk2 = fs->super->s_inodes_count; | |
c5d2f50d VAH |
398 | pctx.ino = ext2fs_get_inode_bitmap_start2(ctx->inode_used_map); |
399 | pctx.ino2 = ext2fs_get_inode_bitmap_end2(ctx->inode_used_map); | |
1b6bf175 | 400 | fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx); |
08b21301 TT |
401 | |
402 | ctx->flags |= E2F_FLAG_ABORT; /* fatal */ | |
49e2df29 | 403 | goto errout; |
50e1e10f | 404 | } |
c5d2f50d | 405 | if ((1 < ext2fs_get_inode_bitmap_start2(fs->inode_map)) || |
49e2df29 | 406 | (fs->super->s_inodes_count > |
c5d2f50d | 407 | ext2fs_get_inode_bitmap_end2(fs->inode_map))) { |
1b6bf175 TT |
408 | pctx.num = 4; |
409 | pctx.blk = 1; | |
410 | pctx.blk2 = fs->super->s_inodes_count; | |
c5d2f50d VAH |
411 | pctx.ino = ext2fs_get_inode_bitmap_start2(fs->inode_map); |
412 | pctx.ino2 = ext2fs_get_inode_bitmap_end2(fs->inode_map); | |
1b6bf175 | 413 | fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx); |
08b21301 TT |
414 | |
415 | ctx->flags |= E2F_FLAG_ABORT; /* fatal */ | |
49e2df29 | 416 | goto errout; |
50e1e10f TT |
417 | } |
418 | ||
49a7360b JS |
419 | csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super, |
420 | EXT4_FEATURE_RO_COMPAT_GDT_CSUM); | |
1b6bf175 | 421 | redo_counts: |
63c4969c | 422 | had_problem = 0; |
f122632e TT |
423 | save_problem = 0; |
424 | pctx.ino = pctx.ino2 = 0; | |
16b851cd | 425 | if (csum_flag && |
cd65a24e | 426 | (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT))) |
f5fa2007 TT |
427 | skip_group++; |
428 | ||
5830d6be ES |
429 | /* Protect loop from wrap-around if inodes_count is maxed */ |
430 | for (i = 1; i <= fs->super->s_inodes_count && i > 0; i++) { | |
479463aa KM |
431 | bitmap = 0; |
432 | if (skip_group && | |
433 | i % fs->super->s_inodes_per_group == 1) { | |
434 | /* | |
435 | * Current inode is the first inode | |
436 | * in the current block group. | |
437 | */ | |
438 | if (ext2fs_test_inode_bitmap_range( | |
439 | ctx->inode_used_map, i, | |
440 | fs->super->s_inodes_per_group)) { | |
441 | /* | |
442 | * When the compared inodes in inodes bitmap | |
443 | * are 0, count the free inode, | |
444 | * skip the current block group. | |
445 | */ | |
446 | inodes = fs->super->s_inodes_per_group - 1; | |
447 | group_free = inodes; | |
448 | free_inodes += inodes; | |
449 | i += inodes; | |
450 | skip_group = 0; | |
451 | goto do_counts; | |
452 | } | |
453 | } | |
454 | ||
c5d2f50d | 455 | actual = ext2fs_fast_test_inode_bitmap2(ctx->inode_used_map, i); |
479463aa KM |
456 | if (redo_flag) |
457 | bitmap = actual; | |
458 | else if (!skip_group) | |
c5d2f50d | 459 | bitmap = ext2fs_fast_test_inode_bitmap2(fs->inode_map, i); |
3839e657 TT |
460 | if (actual == bitmap) |
461 | goto do_counts; | |
49e2df29 | 462 | |
3839e657 TT |
463 | if (!actual && bitmap) { |
464 | /* | |
465 | * Inode wasn't used, but marked in bitmap | |
466 | */ | |
f122632e | 467 | problem = PR_5_INODE_UNUSED; |
1b6bf175 | 468 | } else /* if (actual && !bitmap) */ { |
3839e657 TT |
469 | /* |
470 | * Inode used, but not in bitmap | |
471 | */ | |
1b6bf175 | 472 | problem = PR_5_INODE_USED; |
49a7360b JS |
473 | |
474 | /* We should never hit this, because it means that | |
475 | * inodes were marked in use that weren't noticed | |
476 | * in pass1 or pass 2. It is easier to fix the problem | |
477 | * than to kill e2fsck and leave the user stuck. */ | |
478 | if (skip_group) { | |
479 | struct problem_context pctx2; | |
480 | pctx2.blk = i; | |
481 | pctx2.group = group; | |
482 | if (fix_problem(ctx, PR_5_INODE_UNINIT,&pctx2)){ | |
e633b58a | 483 | ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT); |
49a7360b JS |
484 | skip_group = 0; |
485 | } | |
486 | } | |
3839e657 | 487 | } |
f122632e TT |
488 | if (pctx.ino == 0) { |
489 | pctx.ino = pctx.ino2 = i; | |
490 | save_problem = problem; | |
491 | } else { | |
492 | if ((problem == save_problem) && | |
493 | (pctx.ino2 == i-1)) | |
494 | pctx.ino2++; | |
495 | else { | |
496 | print_bitmap_problem(ctx, save_problem, &pctx); | |
497 | pctx.ino = pctx.ino2 = i; | |
498 | save_problem = problem; | |
499 | } | |
500 | } | |
5596defa | 501 | ctx->flags |= E2F_FLAG_PROG_SUPPRESS; |
63c4969c | 502 | had_problem++; |
49e2df29 | 503 | |
3839e657 | 504 | do_counts: |
f5fa2007 | 505 | if (bitmap) { |
c5d2f50d | 506 | if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, i)) |
3839e657 | 507 | dirs_count++; |
49a7360b | 508 | } else if (!skip_group || csum_flag) { |
f5fa2007 TT |
509 | group_free++; |
510 | free_inodes++; | |
3839e657 TT |
511 | } |
512 | inodes++; | |
513 | if ((inodes == fs->super->s_inodes_per_group) || | |
514 | (i == fs->super->s_inodes_count)) { | |
515 | free_array[group] = group_free; | |
516 | dir_array[group] = dirs_count; | |
517 | group ++; | |
518 | inodes = 0; | |
f5fa2007 | 519 | skip_group = 0; |
3839e657 TT |
520 | group_free = 0; |
521 | dirs_count = 0; | |
efac9a1b TT |
522 | if (ctx->progress) |
523 | if ((ctx->progress)(ctx, 5, | |
524 | group + fs->group_desc_count, | |
525 | fs->group_desc_count*2)) | |
49e2df29 | 526 | goto errout; |
16b851cd | 527 | if (csum_flag && |
f5fa2007 | 528 | (i != fs->super->s_inodes_count) && |
cd65a24e | 529 | (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT) |
732c8cd5 | 530 | )) |
f5fa2007 | 531 | skip_group++; |
3839e657 TT |
532 | } |
533 | } | |
f122632e TT |
534 | if (pctx.ino) |
535 | print_bitmap_problem(ctx, save_problem, &pctx); | |
49e2df29 | 536 | |
63c4969c TT |
537 | if (had_problem) |
538 | fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP); | |
539 | else | |
540 | fixit = -1; | |
5596defa | 541 | ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS; |
49e2df29 | 542 | |
1b6bf175 TT |
543 | if (fixit == 1) { |
544 | ext2fs_free_inode_bitmap(fs->inode_map); | |
545 | retval = ext2fs_copy_bitmap(ctx->inode_used_map, | |
546 | &fs->inode_map); | |
bbd47d76 TT |
547 | if (retval) { |
548 | clear_problem_context(&pctx); | |
549 | fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx); | |
550 | ctx->flags |= E2F_FLAG_ABORT; | |
49e2df29 | 551 | goto errout; |
bbd47d76 | 552 | } |
1b6bf175 TT |
553 | ext2fs_set_bitmap_padding(fs->inode_map); |
554 | ext2fs_mark_ib_dirty(fs); | |
555 | ||
556 | /* redo counts */ | |
557 | inodes = 0; free_inodes = 0; group_free = 0; | |
558 | dirs_count = 0; group = 0; | |
559 | memset(free_array, 0, fs->group_desc_count * sizeof(int)); | |
560 | memset(dir_array, 0, fs->group_desc_count * sizeof(int)); | |
479463aa | 561 | redo_flag++; |
1b6bf175 TT |
562 | goto redo_counts; |
563 | } else if (fixit == 0) | |
564 | ext2fs_unmark_valid(fs); | |
49e2df29 | 565 | |
3839e657 TT |
566 | for (i = 0; i < fs->group_desc_count; i++) { |
567 | if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) { | |
1b6bf175 TT |
568 | pctx.group = i; |
569 | pctx.ino = fs->group_desc[i].bg_free_inodes_count; | |
570 | pctx.ino2 = free_array[i]; | |
571 | if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP, | |
572 | &pctx)) { | |
3839e657 TT |
573 | fs->group_desc[i].bg_free_inodes_count = |
574 | free_array[i]; | |
575 | ext2fs_mark_super_dirty(fs); | |
576 | } else | |
577 | ext2fs_unmark_valid(fs); | |
578 | } | |
579 | if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) { | |
1b6bf175 TT |
580 | pctx.group = i; |
581 | pctx.ino = fs->group_desc[i].bg_used_dirs_count; | |
582 | pctx.ino2 = dir_array[i]; | |
583 | ||
584 | if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP, | |
585 | &pctx)) { | |
3839e657 TT |
586 | fs->group_desc[i].bg_used_dirs_count = |
587 | dir_array[i]; | |
588 | ext2fs_mark_super_dirty(fs); | |
589 | } else | |
590 | ext2fs_unmark_valid(fs); | |
591 | } | |
592 | } | |
593 | if (free_inodes != fs->super->s_free_inodes_count) { | |
1b6bf175 TT |
594 | pctx.group = -1; |
595 | pctx.ino = fs->super->s_free_inodes_count; | |
596 | pctx.ino2 = free_inodes; | |
597 | ||
598 | if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) { | |
3839e657 TT |
599 | fs->super->s_free_inodes_count = free_inodes; |
600 | ext2fs_mark_super_dirty(fs); | |
601 | } else | |
602 | ext2fs_unmark_valid(fs); | |
603 | } | |
49e2df29 | 604 | errout: |
c4e3d3f3 TT |
605 | ext2fs_free_mem(&free_array); |
606 | ext2fs_free_mem(&dir_array); | |
3839e657 TT |
607 | } |
608 | ||
1b6bf175 | 609 | static void check_inode_end(e2fsck_t ctx) |
3839e657 | 610 | { |
1b6bf175 | 611 | ext2_filsys fs = ctx->fs; |
86c627ec | 612 | ext2_ino_t end, save_inodes_count, i; |
1b6bf175 TT |
613 | struct problem_context pctx; |
614 | ||
615 | clear_problem_context(&pctx); | |
3839e657 TT |
616 | |
617 | end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count; | |
1b6bf175 TT |
618 | pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end, |
619 | &save_inodes_count); | |
620 | if (pctx.errcode) { | |
621 | pctx.num = 1; | |
622 | fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx); | |
08b21301 TT |
623 | ctx->flags |= E2F_FLAG_ABORT; /* fatal */ |
624 | return; | |
f3db3566 | 625 | } |
3839e657 TT |
626 | if (save_inodes_count == end) |
627 | return; | |
5830d6be | 628 | |
efc6f628 | 629 | /* protect loop from wrap-around if end is maxed */ |
5830d6be | 630 | for (i = save_inodes_count + 1; i <= end && i > save_inodes_count; i++) { |
f3db3566 | 631 | if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) { |
1b6bf175 | 632 | if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) { |
01ec1268 | 633 | for (; i <= end; i++) |
f3db3566 | 634 | ext2fs_mark_inode_bitmap(fs->inode_map, |
3839e657 TT |
635 | i); |
636 | ext2fs_mark_ib_dirty(fs); | |
637 | } else | |
638 | ext2fs_unmark_valid(fs); | |
639 | break; | |
640 | } | |
641 | } | |
642 | ||
1b6bf175 TT |
643 | pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, |
644 | save_inodes_count, 0); | |
645 | if (pctx.errcode) { | |
646 | pctx.num = 2; | |
647 | fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx); | |
08b21301 TT |
648 | ctx->flags |= E2F_FLAG_ABORT; /* fatal */ |
649 | return; | |
f3db3566 | 650 | } |
3839e657 TT |
651 | } |
652 | ||
1b6bf175 | 653 | static void check_block_end(e2fsck_t ctx) |
3839e657 | 654 | { |
1b6bf175 | 655 | ext2_filsys fs = ctx->fs; |
c5d2f50d | 656 | blk64_t end, save_blocks_count, i; |
1b6bf175 TT |
657 | struct problem_context pctx; |
658 | ||
659 | clear_problem_context(&pctx); | |
3839e657 | 660 | |
c5d2f50d | 661 | end = ext2fs_get_block_bitmap_start2(fs->block_map) + |
c5b7b6ba | 662 | ((blk64_t)EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1; |
c5d2f50d | 663 | pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map, end, |
1b6bf175 TT |
664 | &save_blocks_count); |
665 | if (pctx.errcode) { | |
666 | pctx.num = 3; | |
667 | fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx); | |
08b21301 TT |
668 | ctx->flags |= E2F_FLAG_ABORT; /* fatal */ |
669 | return; | |
f3db3566 | 670 | } |
3839e657 TT |
671 | if (save_blocks_count == end) |
672 | return; | |
5830d6be | 673 | |
efc6f628 | 674 | /* Protect loop from wrap-around if end is maxed */ |
5830d6be | 675 | for (i = save_blocks_count + 1; i <= end && i > save_blocks_count; i++) { |
c5d2f50d | 676 | if (!ext2fs_test_block_bitmap2(fs->block_map, i)) { |
1b6bf175 | 677 | if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) { |
01ec1268 | 678 | for (; i <= end; i++) |
c5d2f50d VAH |
679 | ext2fs_mark_block_bitmap2(fs->block_map, |
680 | i); | |
3839e657 TT |
681 | ext2fs_mark_bb_dirty(fs); |
682 | } else | |
683 | ext2fs_unmark_valid(fs); | |
684 | break; | |
685 | } | |
686 | } | |
687 | ||
c5d2f50d | 688 | pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map, |
1b6bf175 TT |
689 | save_blocks_count, 0); |
690 | if (pctx.errcode) { | |
691 | pctx.num = 4; | |
692 | fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx); | |
08b21301 TT |
693 | ctx->flags |= E2F_FLAG_ABORT; /* fatal */ |
694 | return; | |
f3db3566 | 695 | } |
3839e657 TT |
696 | } |
697 | ||
1b6bf175 TT |
698 | |
699 |