blob: def492a9fd66a9b679d36bf3f08385772914ce0c [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
13#include "et/com_err.h"
14
15#include "e2fsck.h"
16
17static void check_block_bitmaps(ext2_filsys fs);
18static void check_inode_bitmaps(ext2_filsys fs);
19static void check_inode_end(ext2_filsys fs);
20static void check_block_end(ext2_filsys fs);
21
22static int do_fix = -1;
23static const char *fix_question = "Fix summary information";
24
25void pass5(ext2_filsys fs)
26{
27 struct resource_track rtrack;
28
29#ifdef MTRACE
30 mtrace_print("Pass 5");
31#endif
32
33 init_resource_track(&rtrack);
34
35 if (!preen)
Theodore Ts'of3db3561997-04-26 13:34:30 +000036 printf("Pass 5: Checking group summary information\n");
Theodore Ts'o3839e651997-04-26 13:21:57 +000037
38 read_bitmaps(fs);
39
40 check_block_bitmaps(fs);
41 check_inode_bitmaps(fs);
42 check_inode_end(fs);
43 check_block_end(fs);
44
Theodore Ts'of3db3561997-04-26 13:34:30 +000045 ext2fs_free_inode_bitmap(inode_used_map);
46 ext2fs_free_inode_bitmap(inode_dir_map);
47 ext2fs_free_block_bitmap(block_found_map);
Theodore Ts'o3839e651997-04-26 13:21:57 +000048
49 if (tflag > 1) {
50 printf("Pass 5: ");
51 print_resource_track(&rtrack);
52 }
53}
54
55static void check_block_bitmaps(ext2_filsys fs)
56{
Theodore Ts'of3db3561997-04-26 13:34:30 +000057 blk_t i;
Theodore Ts'o3839e651997-04-26 13:21:57 +000058 int *free_array;
59 int group = 0;
60 int blocks = 0;
61 int free_blocks = 0;
62 int group_free = 0;
63 int actual, bitmap;
64 const char *print_header = "Block bitmap differences:";
65
66 free_array = allocate_memory(fs->group_desc_count * sizeof(int),
67 "free block count array");
Theodore Ts'o50e1e101997-04-26 13:58:21 +000068
69 if ((fs->super->s_first_data_block <
70 ext2fs_get_block_bitmap_start(block_found_map)) ||
71 (fs->super->s_blocks_count-1 >
72 ext2fs_get_block_bitmap_end(block_found_map))) {
73 printf("PROGRAMMING ERROR: filesystem endpoints (%d, %d)\n\t"
74 "don't match block_found_map endpoints (%d, %d).\n",
75 fs->super->s_first_data_block,
76 fs->super->s_blocks_count -1,
77 ext2fs_get_block_bitmap_start(block_found_map),
78 ext2fs_get_block_bitmap_end(block_found_map));
79 fatal_error(0);
80 }
81
82 if ((fs->super->s_first_data_block <
83 ext2fs_get_block_bitmap_start(fs->block_map)) ||
84 (fs->super->s_blocks_count-1 >
85 ext2fs_get_block_bitmap_end(fs->block_map))) {
86 printf("PROGRAMMING ERROR: filesystem endpoints (%d, %d)\n\t"
87 "don't match fs->block_map endpoints (%d, %d).\n",
88 fs->super->s_first_data_block,
89 fs->super->s_blocks_count -1,
90 ext2fs_get_block_bitmap_start(fs->block_map),
91 ext2fs_get_block_bitmap_end(fs->block_map));
92 fatal_error(0);
93 }
94
95
Theodore Ts'o3839e651997-04-26 13:21:57 +000096 for (i = fs->super->s_first_data_block;
97 i < fs->super->s_blocks_count;
98 i++) {
Theodore Ts'o50e1e101997-04-26 13:58:21 +000099 actual = ext2fs_fast_test_block_bitmap(block_found_map, i);
100 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000101
102 if (actual == bitmap)
103 goto do_counts;
104
105 if (do_fix < 0)
106 do_fix = ask(fix_question, 1);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000107 if (!preen && print_header) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000108 printf(print_header);
109 print_header = 0;
110 }
111 if (!actual && bitmap) {
112 /*
113 * Block not used, but marked in use in the bitmap.
114 */
Theodore Ts'of3db3561997-04-26 13:34:30 +0000115 if (!preen)
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000116 printf(" -%u", i);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000117 if (do_fix)
Theodore Ts'of3db3561997-04-26 13:34:30 +0000118 ext2fs_unmark_block_bitmap(fs->block_map,
Theodore Ts'o3839e651997-04-26 13:21:57 +0000119 i);
120 } else {
121 /*
122 * Block used, but not marked in use in the bitmap.
123 */
Theodore Ts'of3db3561997-04-26 13:34:30 +0000124 if (!preen)
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000125 printf(" +%u", i);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000126 if (do_fix)
Theodore Ts'of3db3561997-04-26 13:34:30 +0000127 ext2fs_mark_block_bitmap(fs->block_map,
Theodore Ts'o3839e651997-04-26 13:21:57 +0000128 i);
129 }
130 if (do_fix) {
131 ext2fs_mark_bb_dirty(fs);
132 bitmap = actual;
133 } else
134 ext2fs_unmark_valid(fs);
135
136 do_counts:
137 if (!bitmap) {
138 group_free++;
139 free_blocks++;
140 }
141 blocks ++;
142 if ((blocks == fs->super->s_blocks_per_group) ||
143 (i == fs->super->s_blocks_count-1)) {
144 free_array[group] = group_free;
145 group ++;
146 blocks = 0;
147 group_free = 0;
148 }
149 }
150 if (!print_header)
151 printf(". %s\n", fix_msg[do_fix]);
152 for (i = 0; i < fs->group_desc_count; i++) {
153 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
154 if (do_fix < 0)
155 do_fix = ask(fix_question, 1);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000156 if (!preen)
157 printf("Free blocks count wrong for "
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000158 "group %u (%u, counted=%d). %s\n", i,
Theodore Ts'of3db3561997-04-26 13:34:30 +0000159 fs->group_desc[i].bg_free_blocks_count,
160 free_array[i], fix_msg[do_fix]);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000161 if (do_fix) {
162 fs->group_desc[i].bg_free_blocks_count =
163 free_array[i];
164 ext2fs_mark_super_dirty(fs);
165 } else
166 ext2fs_unmark_valid(fs);
167 }
168 }
169 if (free_blocks != fs->super->s_free_blocks_count) {
170 if (do_fix < 0)
171 do_fix = ask(fix_question, 1);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000172 if (!preen)
173 printf("Free blocks count wrong "
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000174 "(%u, counted=%d). %s\n",
Theodore Ts'of3db3561997-04-26 13:34:30 +0000175 fs->super->s_free_blocks_count, free_blocks,
176 fix_msg[do_fix]);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000177 if (do_fix) {
178 fs->super->s_free_blocks_count = free_blocks;
179 ext2fs_mark_super_dirty(fs);
180 } else
181 ext2fs_unmark_valid(fs);
182 }
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000183 free(free_array);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000184}
185
186static void check_inode_bitmaps(ext2_filsys fs)
187{
Theodore Ts'of3db3561997-04-26 13:34:30 +0000188 ino_t i;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000189 int free_inodes = 0;
190 int group_free = 0;
191 int dirs_count = 0;
192 int group = 0;
193 int inodes = 0;
194 int *free_array;
195 int *dir_array;
196 int actual, bitmap;
197 const char *print_header = "Inode bitmap differences:";
198
199 free_array = allocate_memory(fs->group_desc_count * sizeof(int),
200 "free inode count array");
201
202 dir_array = allocate_memory(fs->group_desc_count * sizeof(int),
203 "directory count array");
204
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000205 if ((1 < ext2fs_get_inode_bitmap_start(inode_used_map)) ||
206 (fs->super->s_inodes_count >
207 ext2fs_get_inode_bitmap_end(inode_used_map))) {
208 printf("PROGRAMMING ERROR: filesystem inode endpoints (%d, %d)\n\t"
209 "don't match inode_used_map endpoints (%d, %d).\n",
210 1, fs->super->s_inodes_count,
211 ext2fs_get_inode_bitmap_start(inode_used_map),
212 ext2fs_get_inode_bitmap_end(inode_used_map));
213 fatal_error(0);
214 }
215 if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
216 (fs->super->s_inodes_count >
217 ext2fs_get_inode_bitmap_end(fs->inode_map))) {
218 printf("PROGRAMMING ERROR: filesystem inode endpoints (%d, %d)\n\t"
219 "don't match fs->inode_map endpoints (%d, %d).\n",
220 1, fs->super->s_inodes_count,
221 ext2fs_get_inode_bitmap_start(fs->inode_map),
222 ext2fs_get_inode_bitmap_end(fs->inode_map));
223 fatal_error(0);
224 }
225
Theodore Ts'o3839e651997-04-26 13:21:57 +0000226 for (i = 1; i <= fs->super->s_inodes_count; i++) {
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000227 actual = ext2fs_fast_test_inode_bitmap(inode_used_map, i);
228 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000229
230 if (actual == bitmap)
231 goto do_counts;
232
233 if (do_fix < 0)
234 do_fix = ask(fix_question, 1);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000235 if (!preen && print_header) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000236 printf(print_header);
237 print_header = 0;
238 }
239 if (!actual && bitmap) {
240 /*
241 * Inode wasn't used, but marked in bitmap
242 */
Theodore Ts'of3db3561997-04-26 13:34:30 +0000243 if (!preen)
244 printf(" -%lu", i);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000245 if (do_fix)
Theodore Ts'of3db3561997-04-26 13:34:30 +0000246 ext2fs_unmark_inode_bitmap(fs->inode_map, i);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000247 } else if (actual && !bitmap) {
248 /*
249 * Inode used, but not in bitmap
250 */
Theodore Ts'of3db3561997-04-26 13:34:30 +0000251 if (!preen)
252 printf (" +%lu", i);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000253 if (do_fix)
Theodore Ts'of3db3561997-04-26 13:34:30 +0000254 ext2fs_mark_inode_bitmap(fs->inode_map, i);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000255 }
256 if (do_fix) {
257 ext2fs_mark_ib_dirty(fs);
258 bitmap = actual;
259 } else
260 ext2fs_unmark_valid(fs);
261
262do_counts:
263 if (!bitmap) {
264 group_free++;
265 free_inodes++;
266 } else {
Theodore Ts'of3db3561997-04-26 13:34:30 +0000267 if (ext2fs_test_inode_bitmap(inode_dir_map, i))
Theodore Ts'o3839e651997-04-26 13:21:57 +0000268 dirs_count++;
269 }
270 inodes++;
271 if ((inodes == fs->super->s_inodes_per_group) ||
272 (i == fs->super->s_inodes_count)) {
273 free_array[group] = group_free;
274 dir_array[group] = dirs_count;
275 group ++;
276 inodes = 0;
277 group_free = 0;
278 dirs_count = 0;
279 }
280 }
281 if (!print_header)
282 printf(". %s\n", fix_msg[do_fix]);
283
284 for (i = 0; i < fs->group_desc_count; i++) {
285 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
286 if (do_fix < 0)
287 do_fix = ask(fix_question, 1);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000288 if (!preen)
289 printf ("Free inodes count wrong for "
290 "group #%lu (%u, counted=%d). %s\n", i,
291 fs->group_desc[i].bg_free_inodes_count,
292 free_array[i], fix_msg[do_fix]);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000293 if (do_fix) {
294 fs->group_desc[i].bg_free_inodes_count =
295 free_array[i];
296 ext2fs_mark_super_dirty(fs);
297 } else
298 ext2fs_unmark_valid(fs);
299 }
300 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
301 if (do_fix < 0)
302 do_fix = ask(fix_question, 1);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000303 if (!preen)
304 printf ("Directories count wrong for "
305 "group #%lu (%u, counted=%d). %s\n", i,
306 fs->group_desc[i].bg_used_dirs_count,
307 dir_array[i], fix_msg[do_fix]);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000308 if (do_fix) {
309 fs->group_desc[i].bg_used_dirs_count =
310 dir_array[i];
311 ext2fs_mark_super_dirty(fs);
312 } else
313 ext2fs_unmark_valid(fs);
314 }
315 }
316 if (free_inodes != fs->super->s_free_inodes_count) {
317 if (do_fix < 0)
318 do_fix = ask(fix_question, 1);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000319 if (!preen)
320 printf("Free inodes count wrong "
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000321 "(%u, counted=%d). %s\n",
Theodore Ts'of3db3561997-04-26 13:34:30 +0000322 fs->super->s_free_inodes_count, free_inodes,
323 fix_msg[do_fix]);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000324 if (do_fix) {
325 fs->super->s_free_inodes_count = free_inodes;
326 ext2fs_mark_super_dirty(fs);
327 } else
328 ext2fs_unmark_valid(fs);
329 }
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000330 free(free_array);
331 free(dir_array);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000332}
333
334static void check_inode_end(ext2_filsys fs)
335{
Theodore Ts'of3db3561997-04-26 13:34:30 +0000336 ino_t end, save_inodes_count, i;
337 errcode_t retval;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000338
339 end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000340 retval = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
341 &save_inodes_count);
342 if (retval) {
343 com_err("check_inode_end", retval,
344 "while trying to fudge end of inode bitmap");
345 fatal_error(0);
346 }
Theodore Ts'o3839e651997-04-26 13:21:57 +0000347 if (save_inodes_count == end)
348 return;
349
Theodore Ts'o3839e651997-04-26 13:21:57 +0000350 for (i = save_inodes_count + 1; i <= end; i++) {
Theodore Ts'of3db3561997-04-26 13:34:30 +0000351 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000352 printf("Padding at end of inode bitmap is not set. ");
353 if (ask("Fix", 1)) {
354 for (i = save_inodes_count + 1; i <= end; i++)
Theodore Ts'of3db3561997-04-26 13:34:30 +0000355 ext2fs_mark_inode_bitmap(fs->inode_map,
Theodore Ts'o3839e651997-04-26 13:21:57 +0000356 i);
357 ext2fs_mark_ib_dirty(fs);
358 } else
359 ext2fs_unmark_valid(fs);
360 break;
361 }
362 }
363
Theodore Ts'of3db3561997-04-26 13:34:30 +0000364 retval = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
365 save_inodes_count, 0);
366 if (retval) {
367 com_err("check_inode_end", retval,
368 "while trying to fudge end of inode bitmap back");
369 fatal_error(0);
370 }
Theodore Ts'o3839e651997-04-26 13:21:57 +0000371}
372
373static void check_block_end(ext2_filsys fs)
374{
Theodore Ts'of3db3561997-04-26 13:34:30 +0000375 blk_t end, save_blocks_count, i;
376 errcode_t retval;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000377
Theodore Ts'of3db3561997-04-26 13:34:30 +0000378 end = fs->block_map->start +
379 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
380 retval = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
381 &save_blocks_count);
382 if (retval) {
383 com_err("check_block_end", retval,
384 "while trying to fudge end of block bitmap");
385 fatal_error(0);
386 }
Theodore Ts'o3839e651997-04-26 13:21:57 +0000387 if (save_blocks_count == end)
388 return;
389
Theodore Ts'of3db3561997-04-26 13:34:30 +0000390 for (i = save_blocks_count + 1; i <= end; i++) {
391 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000392 printf("Padding at end of block bitmap is not set. ");
393
394 if (ask("Fix", 1)) {
395 for (i = save_blocks_count + 1; i < end; i++)
Theodore Ts'of3db3561997-04-26 13:34:30 +0000396 ext2fs_mark_block_bitmap(fs->block_map,
Theodore Ts'o3839e651997-04-26 13:21:57 +0000397 i);
398 ext2fs_mark_bb_dirty(fs);
399 } else
400 ext2fs_unmark_valid(fs);
401 break;
402 }
403 }
404
Theodore Ts'of3db3561997-04-26 13:34:30 +0000405 retval = ext2fs_fudge_block_bitmap_end(fs->block_map,
406 save_blocks_count, 0);
407 if (retval) {
408 com_err("check_block_end", retval,
409 "while trying to fudge end of block bitmap back");
410 fatal_error(0);
411 }
Theodore Ts'o3839e651997-04-26 13:21:57 +0000412}
413