blob: 744aee20cd72f54433494cbddb2defa20566674b [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 *
4 * Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
5 * redistributed under the terms of the GNU Public License.
6 *
7 */
8
9#include "et/com_err.h"
10
11#include "e2fsck.h"
12
13static void check_block_bitmaps(ext2_filsys fs);
14static void check_inode_bitmaps(ext2_filsys fs);
15static void check_inode_end(ext2_filsys fs);
16static void check_block_end(ext2_filsys fs);
17
18static int do_fix = -1;
19static const char *fix_question = "Fix summary information";
20
21void pass5(ext2_filsys fs)
22{
23 struct resource_track rtrack;
24
25#ifdef MTRACE
26 mtrace_print("Pass 5");
27#endif
28
29 init_resource_track(&rtrack);
30
31 if (!preen)
Theodore Ts'of3db3561997-04-26 13:34:30 +000032 printf("Pass 5: Checking group summary information\n");
Theodore Ts'o3839e651997-04-26 13:21:57 +000033
34 read_bitmaps(fs);
35
36 check_block_bitmaps(fs);
37 check_inode_bitmaps(fs);
38 check_inode_end(fs);
39 check_block_end(fs);
40
Theodore Ts'of3db3561997-04-26 13:34:30 +000041 ext2fs_free_inode_bitmap(inode_used_map);
42 ext2fs_free_inode_bitmap(inode_dir_map);
43 ext2fs_free_block_bitmap(block_found_map);
Theodore Ts'o3839e651997-04-26 13:21:57 +000044
45 if (tflag > 1) {
46 printf("Pass 5: ");
47 print_resource_track(&rtrack);
48 }
49}
50
51static void check_block_bitmaps(ext2_filsys fs)
52{
Theodore Ts'of3db3561997-04-26 13:34:30 +000053 blk_t i;
Theodore Ts'o3839e651997-04-26 13:21:57 +000054 int *free_array;
55 int group = 0;
56 int blocks = 0;
57 int free_blocks = 0;
58 int group_free = 0;
59 int actual, bitmap;
60 const char *print_header = "Block bitmap differences:";
61
62 free_array = allocate_memory(fs->group_desc_count * sizeof(int),
63 "free block count array");
Theodore Ts'o50e1e101997-04-26 13:58:21 +000064
65 if ((fs->super->s_first_data_block <
66 ext2fs_get_block_bitmap_start(block_found_map)) ||
67 (fs->super->s_blocks_count-1 >
68 ext2fs_get_block_bitmap_end(block_found_map))) {
69 printf("PROGRAMMING ERROR: filesystem endpoints (%d, %d)\n\t"
70 "don't match block_found_map endpoints (%d, %d).\n",
71 fs->super->s_first_data_block,
72 fs->super->s_blocks_count -1,
73 ext2fs_get_block_bitmap_start(block_found_map),
74 ext2fs_get_block_bitmap_end(block_found_map));
75 fatal_error(0);
76 }
77
78 if ((fs->super->s_first_data_block <
79 ext2fs_get_block_bitmap_start(fs->block_map)) ||
80 (fs->super->s_blocks_count-1 >
81 ext2fs_get_block_bitmap_end(fs->block_map))) {
82 printf("PROGRAMMING ERROR: filesystem endpoints (%d, %d)\n\t"
83 "don't match fs->block_map endpoints (%d, %d).\n",
84 fs->super->s_first_data_block,
85 fs->super->s_blocks_count -1,
86 ext2fs_get_block_bitmap_start(fs->block_map),
87 ext2fs_get_block_bitmap_end(fs->block_map));
88 fatal_error(0);
89 }
90
91
Theodore Ts'o3839e651997-04-26 13:21:57 +000092 for (i = fs->super->s_first_data_block;
93 i < fs->super->s_blocks_count;
94 i++) {
Theodore Ts'o50e1e101997-04-26 13:58:21 +000095 actual = ext2fs_fast_test_block_bitmap(block_found_map, i);
96 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
Theodore Ts'o3839e651997-04-26 13:21:57 +000097
98 if (actual == bitmap)
99 goto do_counts;
100
101 if (do_fix < 0)
102 do_fix = ask(fix_question, 1);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000103 if (!preen && print_header) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000104 printf(print_header);
105 print_header = 0;
106 }
107 if (!actual && bitmap) {
108 /*
109 * Block not used, but marked in use in the bitmap.
110 */
Theodore Ts'of3db3561997-04-26 13:34:30 +0000111 if (!preen)
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000112 printf(" -%u", i);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000113 if (do_fix)
Theodore Ts'of3db3561997-04-26 13:34:30 +0000114 ext2fs_unmark_block_bitmap(fs->block_map,
Theodore Ts'o3839e651997-04-26 13:21:57 +0000115 i);
116 } else {
117 /*
118 * Block used, but not marked in use in the bitmap.
119 */
Theodore Ts'of3db3561997-04-26 13:34:30 +0000120 if (!preen)
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000121 printf(" +%u", i);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000122 if (do_fix)
Theodore Ts'of3db3561997-04-26 13:34:30 +0000123 ext2fs_mark_block_bitmap(fs->block_map,
Theodore Ts'o3839e651997-04-26 13:21:57 +0000124 i);
125 }
126 if (do_fix) {
127 ext2fs_mark_bb_dirty(fs);
128 bitmap = actual;
129 } else
130 ext2fs_unmark_valid(fs);
131
132 do_counts:
133 if (!bitmap) {
134 group_free++;
135 free_blocks++;
136 }
137 blocks ++;
138 if ((blocks == fs->super->s_blocks_per_group) ||
139 (i == fs->super->s_blocks_count-1)) {
140 free_array[group] = group_free;
141 group ++;
142 blocks = 0;
143 group_free = 0;
144 }
145 }
146 if (!print_header)
147 printf(". %s\n", fix_msg[do_fix]);
148 for (i = 0; i < fs->group_desc_count; i++) {
149 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
150 if (do_fix < 0)
151 do_fix = ask(fix_question, 1);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000152 if (!preen)
153 printf("Free blocks count wrong for "
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000154 "group %u (%u, counted=%d). %s\n", i,
Theodore Ts'of3db3561997-04-26 13:34:30 +0000155 fs->group_desc[i].bg_free_blocks_count,
156 free_array[i], fix_msg[do_fix]);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000157 if (do_fix) {
158 fs->group_desc[i].bg_free_blocks_count =
159 free_array[i];
160 ext2fs_mark_super_dirty(fs);
161 } else
162 ext2fs_unmark_valid(fs);
163 }
164 }
165 if (free_blocks != fs->super->s_free_blocks_count) {
166 if (do_fix < 0)
167 do_fix = ask(fix_question, 1);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000168 if (!preen)
169 printf("Free blocks count wrong "
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000170 "(%u, counted=%d). %s\n",
Theodore Ts'of3db3561997-04-26 13:34:30 +0000171 fs->super->s_free_blocks_count, free_blocks,
172 fix_msg[do_fix]);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000173 if (do_fix) {
174 fs->super->s_free_blocks_count = free_blocks;
175 ext2fs_mark_super_dirty(fs);
176 } else
177 ext2fs_unmark_valid(fs);
178 }
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000179 free(free_array);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000180}
181
182static void check_inode_bitmaps(ext2_filsys fs)
183{
Theodore Ts'of3db3561997-04-26 13:34:30 +0000184 ino_t i;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000185 int free_inodes = 0;
186 int group_free = 0;
187 int dirs_count = 0;
188 int group = 0;
189 int inodes = 0;
190 int *free_array;
191 int *dir_array;
192 int actual, bitmap;
193 const char *print_header = "Inode bitmap differences:";
194
195 free_array = allocate_memory(fs->group_desc_count * sizeof(int),
196 "free inode count array");
197
198 dir_array = allocate_memory(fs->group_desc_count * sizeof(int),
199 "directory count array");
200
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000201 if ((1 < ext2fs_get_inode_bitmap_start(inode_used_map)) ||
202 (fs->super->s_inodes_count >
203 ext2fs_get_inode_bitmap_end(inode_used_map))) {
204 printf("PROGRAMMING ERROR: filesystem inode endpoints (%d, %d)\n\t"
205 "don't match inode_used_map endpoints (%d, %d).\n",
206 1, fs->super->s_inodes_count,
207 ext2fs_get_inode_bitmap_start(inode_used_map),
208 ext2fs_get_inode_bitmap_end(inode_used_map));
209 fatal_error(0);
210 }
211 if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
212 (fs->super->s_inodes_count >
213 ext2fs_get_inode_bitmap_end(fs->inode_map))) {
214 printf("PROGRAMMING ERROR: filesystem inode endpoints (%d, %d)\n\t"
215 "don't match fs->inode_map endpoints (%d, %d).\n",
216 1, fs->super->s_inodes_count,
217 ext2fs_get_inode_bitmap_start(fs->inode_map),
218 ext2fs_get_inode_bitmap_end(fs->inode_map));
219 fatal_error(0);
220 }
221
Theodore Ts'o3839e651997-04-26 13:21:57 +0000222 for (i = 1; i <= fs->super->s_inodes_count; i++) {
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000223 actual = ext2fs_fast_test_inode_bitmap(inode_used_map, i);
224 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000225
226 if (actual == bitmap)
227 goto do_counts;
228
229 if (do_fix < 0)
230 do_fix = ask(fix_question, 1);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000231 if (!preen && print_header) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000232 printf(print_header);
233 print_header = 0;
234 }
235 if (!actual && bitmap) {
236 /*
237 * Inode wasn't used, but marked in bitmap
238 */
Theodore Ts'of3db3561997-04-26 13:34:30 +0000239 if (!preen)
240 printf(" -%lu", i);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000241 if (do_fix)
Theodore Ts'of3db3561997-04-26 13:34:30 +0000242 ext2fs_unmark_inode_bitmap(fs->inode_map, i);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000243 } else if (actual && !bitmap) {
244 /*
245 * Inode used, but not in bitmap
246 */
Theodore Ts'of3db3561997-04-26 13:34:30 +0000247 if (!preen)
248 printf (" +%lu", i);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000249 if (do_fix)
Theodore Ts'of3db3561997-04-26 13:34:30 +0000250 ext2fs_mark_inode_bitmap(fs->inode_map, i);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000251 }
252 if (do_fix) {
253 ext2fs_mark_ib_dirty(fs);
254 bitmap = actual;
255 } else
256 ext2fs_unmark_valid(fs);
257
258do_counts:
259 if (!bitmap) {
260 group_free++;
261 free_inodes++;
262 } else {
Theodore Ts'of3db3561997-04-26 13:34:30 +0000263 if (ext2fs_test_inode_bitmap(inode_dir_map, i))
Theodore Ts'o3839e651997-04-26 13:21:57 +0000264 dirs_count++;
265 }
266 inodes++;
267 if ((inodes == fs->super->s_inodes_per_group) ||
268 (i == fs->super->s_inodes_count)) {
269 free_array[group] = group_free;
270 dir_array[group] = dirs_count;
271 group ++;
272 inodes = 0;
273 group_free = 0;
274 dirs_count = 0;
275 }
276 }
277 if (!print_header)
278 printf(". %s\n", fix_msg[do_fix]);
279
280 for (i = 0; i < fs->group_desc_count; i++) {
281 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
282 if (do_fix < 0)
283 do_fix = ask(fix_question, 1);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000284 if (!preen)
285 printf ("Free inodes count wrong for "
286 "group #%lu (%u, counted=%d). %s\n", i,
287 fs->group_desc[i].bg_free_inodes_count,
288 free_array[i], fix_msg[do_fix]);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000289 if (do_fix) {
290 fs->group_desc[i].bg_free_inodes_count =
291 free_array[i];
292 ext2fs_mark_super_dirty(fs);
293 } else
294 ext2fs_unmark_valid(fs);
295 }
296 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
297 if (do_fix < 0)
298 do_fix = ask(fix_question, 1);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000299 if (!preen)
300 printf ("Directories count wrong for "
301 "group #%lu (%u, counted=%d). %s\n", i,
302 fs->group_desc[i].bg_used_dirs_count,
303 dir_array[i], fix_msg[do_fix]);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000304 if (do_fix) {
305 fs->group_desc[i].bg_used_dirs_count =
306 dir_array[i];
307 ext2fs_mark_super_dirty(fs);
308 } else
309 ext2fs_unmark_valid(fs);
310 }
311 }
312 if (free_inodes != fs->super->s_free_inodes_count) {
313 if (do_fix < 0)
314 do_fix = ask(fix_question, 1);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000315 if (!preen)
316 printf("Free inodes count wrong "
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000317 "(%u, counted=%d). %s\n",
Theodore Ts'of3db3561997-04-26 13:34:30 +0000318 fs->super->s_free_inodes_count, free_inodes,
319 fix_msg[do_fix]);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000320 if (do_fix) {
321 fs->super->s_free_inodes_count = free_inodes;
322 ext2fs_mark_super_dirty(fs);
323 } else
324 ext2fs_unmark_valid(fs);
325 }
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000326 free(free_array);
327 free(dir_array);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000328}
329
330static void check_inode_end(ext2_filsys fs)
331{
Theodore Ts'of3db3561997-04-26 13:34:30 +0000332 ino_t end, save_inodes_count, i;
333 errcode_t retval;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000334
335 end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000336 retval = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
337 &save_inodes_count);
338 if (retval) {
339 com_err("check_inode_end", retval,
340 "while trying to fudge end of inode bitmap");
341 fatal_error(0);
342 }
Theodore Ts'o3839e651997-04-26 13:21:57 +0000343 if (save_inodes_count == end)
344 return;
345
Theodore Ts'o3839e651997-04-26 13:21:57 +0000346 for (i = save_inodes_count + 1; i <= end; i++) {
Theodore Ts'of3db3561997-04-26 13:34:30 +0000347 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000348 printf("Padding at end of inode bitmap is not set. ");
349 if (ask("Fix", 1)) {
350 for (i = save_inodes_count + 1; i <= end; i++)
Theodore Ts'of3db3561997-04-26 13:34:30 +0000351 ext2fs_mark_inode_bitmap(fs->inode_map,
Theodore Ts'o3839e651997-04-26 13:21:57 +0000352 i);
353 ext2fs_mark_ib_dirty(fs);
354 } else
355 ext2fs_unmark_valid(fs);
356 break;
357 }
358 }
359
Theodore Ts'of3db3561997-04-26 13:34:30 +0000360 retval = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
361 save_inodes_count, 0);
362 if (retval) {
363 com_err("check_inode_end", retval,
364 "while trying to fudge end of inode bitmap back");
365 fatal_error(0);
366 }
Theodore Ts'o3839e651997-04-26 13:21:57 +0000367}
368
369static void check_block_end(ext2_filsys fs)
370{
Theodore Ts'of3db3561997-04-26 13:34:30 +0000371 blk_t end, save_blocks_count, i;
372 errcode_t retval;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000373
Theodore Ts'of3db3561997-04-26 13:34:30 +0000374 end = fs->block_map->start +
375 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
376 retval = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
377 &save_blocks_count);
378 if (retval) {
379 com_err("check_block_end", retval,
380 "while trying to fudge end of block bitmap");
381 fatal_error(0);
382 }
Theodore Ts'o3839e651997-04-26 13:21:57 +0000383 if (save_blocks_count == end)
384 return;
385
Theodore Ts'of3db3561997-04-26 13:34:30 +0000386 for (i = save_blocks_count + 1; i <= end; i++) {
387 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000388 printf("Padding at end of block bitmap is not set. ");
389
390 if (ask("Fix", 1)) {
391 for (i = save_blocks_count + 1; i < end; i++)
Theodore Ts'of3db3561997-04-26 13:34:30 +0000392 ext2fs_mark_block_bitmap(fs->block_map,
Theodore Ts'o3839e651997-04-26 13:21:57 +0000393 i);
394 ext2fs_mark_bb_dirty(fs);
395 } else
396 ext2fs_unmark_valid(fs);
397 break;
398 }
399 }
400
Theodore Ts'of3db3561997-04-26 13:34:30 +0000401 retval = ext2fs_fudge_block_bitmap_end(fs->block_map,
402 save_blocks_count, 0);
403 if (retval) {
404 com_err("check_block_end", retval,
405 "while trying to fudge end of block bitmap back");
406 fatal_error(0);
407 }
Theodore Ts'o3839e651997-04-26 13:21:57 +0000408}
409