diff options
Diffstat (limited to 'e2fsprogs/e2fsck/pass1.c')
-rw-r--r-- | e2fsprogs/e2fsck/pass1.c | 2122 |
1 files changed, 2122 insertions, 0 deletions
diff --git a/e2fsprogs/e2fsck/pass1.c b/e2fsprogs/e2fsck/pass1.c new file mode 100644 index 000000000..8d01cae2b --- /dev/null +++ b/e2fsprogs/e2fsck/pass1.c | |||
@@ -0,0 +1,2122 @@ | |||
1 | /* | ||
2 | * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table | ||
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 | * Pass 1 of e2fsck iterates over all the inodes in the filesystems, | ||
12 | * and applies the following tests to each inode: | ||
13 | * | ||
14 | * - The mode field of the inode must be legal. | ||
15 | * - The size and block count fields of the inode are correct. | ||
16 | * - A data block must not be used by another inode | ||
17 | * | ||
18 | * Pass 1 also gathers the collects the following information: | ||
19 | * | ||
20 | * - A bitmap of which inodes are in use. (inode_used_map) | ||
21 | * - A bitmap of which inodes are directories. (inode_dir_map) | ||
22 | * - A bitmap of which inodes are regular files. (inode_reg_map) | ||
23 | * - A bitmap of which inodes have bad fields. (inode_bad_map) | ||
24 | * - A bitmap of which inodes are in bad blocks. (inode_bb_map) | ||
25 | * - A bitmap of which inodes are imagic inodes. (inode_imagic_map) | ||
26 | * - A bitmap of which blocks are in use. (block_found_map) | ||
27 | * - A bitmap of which blocks are in use by two inodes (block_dup_map) | ||
28 | * - The data blocks of the directory inodes. (dir_map) | ||
29 | * | ||
30 | * Pass 1 is designed to stash away enough information so that the | ||
31 | * other passes should not need to read in the inode information | ||
32 | * during the normal course of a filesystem check. (Althogh if an | ||
33 | * inconsistency is detected, other passes may need to read in an | ||
34 | * inode to fix it.) | ||
35 | * | ||
36 | * Note that pass 1B will be invoked if there are any duplicate blocks | ||
37 | * found. | ||
38 | */ | ||
39 | |||
40 | #define _GNU_SOURCE 1 /* get strnlen() */ | ||
41 | #include <string.h> | ||
42 | #include <time.h> | ||
43 | #ifdef HAVE_ERRNO_H | ||
44 | #include <errno.h> | ||
45 | #endif | ||
46 | |||
47 | #include "e2fsck.h" | ||
48 | #include <ext2fs/ext2_ext_attr.h> | ||
49 | |||
50 | #include "problem.h" | ||
51 | |||
52 | #ifdef NO_INLINE_FUNCS | ||
53 | #define _INLINE_ | ||
54 | #else | ||
55 | #define _INLINE_ inline | ||
56 | #endif | ||
57 | |||
58 | static int process_block(ext2_filsys fs, blk_t *blocknr, | ||
59 | e2_blkcnt_t blockcnt, blk_t ref_blk, | ||
60 | int ref_offset, void *priv_data); | ||
61 | static int process_bad_block(ext2_filsys fs, blk_t *block_nr, | ||
62 | e2_blkcnt_t blockcnt, blk_t ref_blk, | ||
63 | int ref_offset, void *priv_data); | ||
64 | static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, | ||
65 | char *block_buf); | ||
66 | static void mark_table_blocks(e2fsck_t ctx); | ||
67 | static void alloc_bb_map(e2fsck_t ctx); | ||
68 | static void alloc_imagic_map(e2fsck_t ctx); | ||
69 | static void mark_inode_bad(e2fsck_t ctx, ino_t ino); | ||
70 | static void handle_fs_bad_blocks(e2fsck_t ctx); | ||
71 | static void process_inodes(e2fsck_t ctx, char *block_buf); | ||
72 | static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b); | ||
73 | static errcode_t scan_callback(ext2_filsys fs, ext2_inode_scan scan, | ||
74 | dgrp_t group, void * priv_data); | ||
75 | static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount, | ||
76 | char *block_buf, int adjust_sign); | ||
77 | /* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */ | ||
78 | |||
79 | extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino, | ||
80 | struct ext2_inode * inode, int bufsize, | ||
81 | const char *proc); | ||
82 | |||
83 | struct process_block_struct { | ||
84 | ext2_ino_t ino; | ||
85 | unsigned is_dir:1, is_reg:1, clear:1, suppress:1, | ||
86 | fragmented:1, compressed:1, bbcheck:1; | ||
87 | blk_t num_blocks; | ||
88 | blk_t max_blocks; | ||
89 | e2_blkcnt_t last_block; | ||
90 | int num_illegal_blocks; | ||
91 | blk_t previous_block; | ||
92 | struct ext2_inode *inode; | ||
93 | struct problem_context *pctx; | ||
94 | ext2fs_block_bitmap fs_meta_blocks; | ||
95 | e2fsck_t ctx; | ||
96 | }; | ||
97 | |||
98 | struct process_inode_block { | ||
99 | ext2_ino_t ino; | ||
100 | struct ext2_inode inode; | ||
101 | }; | ||
102 | |||
103 | struct scan_callback_struct { | ||
104 | e2fsck_t ctx; | ||
105 | char *block_buf; | ||
106 | }; | ||
107 | |||
108 | /* | ||
109 | * For the inodes to process list. | ||
110 | */ | ||
111 | static struct process_inode_block *inodes_to_process; | ||
112 | static int process_inode_count; | ||
113 | |||
114 | static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE - | ||
115 | EXT2_MIN_BLOCK_LOG_SIZE + 1]; | ||
116 | |||
117 | /* | ||
118 | * Free all memory allocated by pass1 in preparation for restarting | ||
119 | * things. | ||
120 | */ | ||
121 | static void unwind_pass1(ext2_filsys fs EXT2FS_ATTR((unused))) | ||
122 | { | ||
123 | ext2fs_free_mem(&inodes_to_process); | ||
124 | inodes_to_process = 0; | ||
125 | } | ||
126 | |||
127 | /* | ||
128 | * Check to make sure a device inode is real. Returns 1 if the device | ||
129 | * checks out, 0 if not. | ||
130 | * | ||
131 | * Note: this routine is now also used to check FIFO's and Sockets, | ||
132 | * since they have the same requirement; the i_block fields should be | ||
133 | * zero. | ||
134 | */ | ||
135 | int e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode) | ||
136 | { | ||
137 | int i; | ||
138 | |||
139 | /* | ||
140 | * If i_blocks is non-zero, or the index flag is set, then | ||
141 | * this is a bogus device/fifo/socket | ||
142 | */ | ||
143 | if ((ext2fs_inode_data_blocks(fs, inode) != 0) || | ||
144 | (inode->i_flags & EXT2_INDEX_FL)) | ||
145 | return 0; | ||
146 | |||
147 | /* | ||
148 | * We should be able to do the test below all the time, but | ||
149 | * because the kernel doesn't forcibly clear the device | ||
150 | * inode's additional i_block fields, there are some rare | ||
151 | * occasions when a legitimate device inode will have non-zero | ||
152 | * additional i_block fields. So for now, we only complain | ||
153 | * when the immutable flag is set, which should never happen | ||
154 | * for devices. (And that's when the problem is caused, since | ||
155 | * you can't set or clear immutable flags for devices.) Once | ||
156 | * the kernel has been fixed we can change this... | ||
157 | */ | ||
158 | if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) { | ||
159 | for (i=4; i < EXT2_N_BLOCKS; i++) | ||
160 | if (inode->i_block[i]) | ||
161 | return 0; | ||
162 | } | ||
163 | return 1; | ||
164 | } | ||
165 | |||
166 | /* | ||
167 | * Check to make sure a symlink inode is real. Returns 1 if the symlink | ||
168 | * checks out, 0 if not. | ||
169 | */ | ||
170 | int e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, | ||
171 | char *buf) | ||
172 | { | ||
173 | unsigned int len; | ||
174 | int i; | ||
175 | blk_t blocks; | ||
176 | |||
177 | if ((inode->i_size_high || inode->i_size == 0) || | ||
178 | (inode->i_flags & EXT2_INDEX_FL)) | ||
179 | return 0; | ||
180 | |||
181 | blocks = ext2fs_inode_data_blocks(fs, inode); | ||
182 | if (blocks) { | ||
183 | if ((inode->i_size >= fs->blocksize) || | ||
184 | (blocks != fs->blocksize >> 9) || | ||
185 | (inode->i_block[0] < fs->super->s_first_data_block) || | ||
186 | (inode->i_block[0] >= fs->super->s_blocks_count)) | ||
187 | return 0; | ||
188 | |||
189 | for (i = 1; i < EXT2_N_BLOCKS; i++) | ||
190 | if (inode->i_block[i]) | ||
191 | return 0; | ||
192 | |||
193 | if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf)) | ||
194 | return 0; | ||
195 | |||
196 | len = strnlen(buf, fs->blocksize); | ||
197 | if (len == fs->blocksize) | ||
198 | return 0; | ||
199 | } else { | ||
200 | if (inode->i_size >= sizeof(inode->i_block)) | ||
201 | return 0; | ||
202 | |||
203 | len = strnlen((char *)inode->i_block, sizeof(inode->i_block)); | ||
204 | if (len == sizeof(inode->i_block)) | ||
205 | return 0; | ||
206 | } | ||
207 | if (len != inode->i_size) | ||
208 | return 0; | ||
209 | return 1; | ||
210 | } | ||
211 | |||
212 | /* | ||
213 | * If the immutable (or append-only) flag is set on the inode, offer | ||
214 | * to clear it. | ||
215 | */ | ||
216 | #define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL) | ||
217 | static void check_immutable(e2fsck_t ctx, struct problem_context *pctx) | ||
218 | { | ||
219 | if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS)) | ||
220 | return; | ||
221 | |||
222 | if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx)) | ||
223 | return; | ||
224 | |||
225 | pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS; | ||
226 | e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1"); | ||
227 | } | ||
228 | |||
229 | /* | ||
230 | * If device, fifo or socket, check size is zero -- if not offer to | ||
231 | * clear it | ||
232 | */ | ||
233 | static void check_size(e2fsck_t ctx, struct problem_context *pctx) | ||
234 | { | ||
235 | struct ext2_inode *inode = pctx->inode; | ||
236 | |||
237 | if ((inode->i_size == 0) && (inode->i_size_high == 0)) | ||
238 | return; | ||
239 | |||
240 | if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx)) | ||
241 | return; | ||
242 | |||
243 | inode->i_size = 0; | ||
244 | inode->i_size_high = 0; | ||
245 | e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1"); | ||
246 | } | ||
247 | |||
248 | static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx) | ||
249 | { | ||
250 | struct ext2_super_block *sb = ctx->fs->super; | ||
251 | struct ext2_inode_large *inode; | ||
252 | struct ext2_ext_attr_entry *entry; | ||
253 | char *start, *end; | ||
254 | int storage_size, remain, offs; | ||
255 | int problem = 0; | ||
256 | |||
257 | inode = (struct ext2_inode_large *) pctx->inode; | ||
258 | storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE - | ||
259 | inode->i_extra_isize; | ||
260 | start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE + | ||
261 | inode->i_extra_isize + sizeof(__u32); | ||
262 | end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super); | ||
263 | entry = (struct ext2_ext_attr_entry *) start; | ||
264 | |||
265 | /* scan all entry's headers first */ | ||
266 | |||
267 | /* take finish entry 0UL into account */ | ||
268 | remain = storage_size - sizeof(__u32); | ||
269 | offs = end - start; | ||
270 | |||
271 | while (!EXT2_EXT_IS_LAST_ENTRY(entry)) { | ||
272 | |||
273 | /* header eats this space */ | ||
274 | remain -= sizeof(struct ext2_ext_attr_entry); | ||
275 | |||
276 | /* is attribute name valid? */ | ||
277 | if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) { | ||
278 | pctx->num = entry->e_name_len; | ||
279 | problem = PR_1_ATTR_NAME_LEN; | ||
280 | goto fix; | ||
281 | } | ||
282 | |||
283 | /* attribute len eats this space */ | ||
284 | remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len); | ||
285 | |||
286 | /* check value size */ | ||
287 | if (entry->e_value_size == 0 || entry->e_value_size > remain) { | ||
288 | pctx->num = entry->e_value_size; | ||
289 | problem = PR_1_ATTR_VALUE_SIZE; | ||
290 | goto fix; | ||
291 | } | ||
292 | |||
293 | /* check value placement */ | ||
294 | if (entry->e_value_offs + | ||
295 | EXT2_XATTR_SIZE(entry->e_value_size) != offs) { | ||
296 | printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs); | ||
297 | pctx->num = entry->e_value_offs; | ||
298 | problem = PR_1_ATTR_VALUE_OFFSET; | ||
299 | goto fix; | ||
300 | } | ||
301 | |||
302 | /* e_value_block must be 0 in inode's ea */ | ||
303 | if (entry->e_value_block != 0) { | ||
304 | pctx->num = entry->e_value_block; | ||
305 | problem = PR_1_ATTR_VALUE_BLOCK; | ||
306 | goto fix; | ||
307 | } | ||
308 | |||
309 | /* e_hash must be 0 in inode's ea */ | ||
310 | if (entry->e_hash != 0) { | ||
311 | pctx->num = entry->e_hash; | ||
312 | problem = PR_1_ATTR_HASH; | ||
313 | goto fix; | ||
314 | } | ||
315 | |||
316 | remain -= entry->e_value_size; | ||
317 | offs -= EXT2_XATTR_SIZE(entry->e_value_size); | ||
318 | |||
319 | entry = EXT2_EXT_ATTR_NEXT(entry); | ||
320 | } | ||
321 | fix: | ||
322 | /* | ||
323 | * it seems like a corruption. it's very unlikely we could repair | ||
324 | * EA(s) in automatic fashion -bzzz | ||
325 | */ | ||
326 | #if 0 | ||
327 | problem = PR_1_ATTR_HASH; | ||
328 | #endif | ||
329 | if (problem == 0 || !fix_problem(ctx, problem, pctx)) | ||
330 | return; | ||
331 | |||
332 | /* simple remove all possible EA(s) */ | ||
333 | *((__u32 *)start) = 0UL; | ||
334 | e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode, | ||
335 | EXT2_INODE_SIZE(sb), "pass1"); | ||
336 | } | ||
337 | |||
338 | static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx) | ||
339 | { | ||
340 | struct ext2_super_block *sb = ctx->fs->super; | ||
341 | struct ext2_inode_large *inode; | ||
342 | __u32 *eamagic; | ||
343 | int min, max; | ||
344 | |||
345 | inode = (struct ext2_inode_large *) pctx->inode; | ||
346 | if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) { | ||
347 | /* this isn't large inode. so, nothing to check */ | ||
348 | return; | ||
349 | } | ||
350 | |||
351 | #if 0 | ||
352 | printf("inode #%u, i_extra_size %d\n", pctx->ino, | ||
353 | inode->i_extra_isize); | ||
354 | #endif | ||
355 | /* i_extra_isize must cover i_extra_isize + i_pad1 at least */ | ||
356 | min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1); | ||
357 | max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE; | ||
358 | /* | ||
359 | * For now we will allow i_extra_isize to be 0, but really | ||
360 | * implementations should never allow i_extra_isize to be 0 | ||
361 | */ | ||
362 | if (inode->i_extra_isize && | ||
363 | (inode->i_extra_isize < min || inode->i_extra_isize > max)) { | ||
364 | if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx)) | ||
365 | return; | ||
366 | inode->i_extra_isize = min; | ||
367 | e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode, | ||
368 | EXT2_INODE_SIZE(sb), "pass1"); | ||
369 | return; | ||
370 | } | ||
371 | |||
372 | eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE + | ||
373 | inode->i_extra_isize); | ||
374 | if (*eamagic == EXT2_EXT_ATTR_MAGIC) { | ||
375 | /* it seems inode has an extended attribute(s) in body */ | ||
376 | check_ea_in_inode(ctx, pctx); | ||
377 | } | ||
378 | } | ||
379 | |||
380 | void e2fsck_pass1(e2fsck_t ctx) | ||
381 | { | ||
382 | int i; | ||
383 | __u64 max_sizes; | ||
384 | ext2_filsys fs = ctx->fs; | ||
385 | ext2_ino_t ino; | ||
386 | struct ext2_inode *inode; | ||
387 | ext2_inode_scan scan; | ||
388 | char *block_buf; | ||
389 | #ifdef RESOURCE_TRACK | ||
390 | struct resource_track rtrack; | ||
391 | #endif | ||
392 | unsigned char frag, fsize; | ||
393 | struct problem_context pctx; | ||
394 | struct scan_callback_struct scan_struct; | ||
395 | struct ext2_super_block *sb = ctx->fs->super; | ||
396 | int imagic_fs; | ||
397 | int busted_fs_time = 0; | ||
398 | int inode_size; | ||
399 | |||
400 | #ifdef RESOURCE_TRACK | ||
401 | init_resource_track(&rtrack); | ||
402 | #endif | ||
403 | clear_problem_context(&pctx); | ||
404 | |||
405 | if (!(ctx->options & E2F_OPT_PREEN)) | ||
406 | fix_problem(ctx, PR_1_PASS_HEADER, &pctx); | ||
407 | |||
408 | if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) && | ||
409 | !(ctx->options & E2F_OPT_NO)) { | ||
410 | if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50)) | ||
411 | ctx->dirs_to_hash = 0; | ||
412 | } | ||
413 | |||
414 | #ifdef MTRACE | ||
415 | mtrace_print("Pass 1"); | ||
416 | #endif | ||
417 | |||
418 | #define EXT2_BPP(bits) (1ULL << ((bits) - 2)) | ||
419 | |||
420 | for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) { | ||
421 | max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i); | ||
422 | max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i); | ||
423 | max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i); | ||
424 | max_sizes = (max_sizes * (1UL << i)) - 1; | ||
425 | ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes; | ||
426 | } | ||
427 | #undef EXT2_BPP | ||
428 | |||
429 | imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES); | ||
430 | |||
431 | /* | ||
432 | * Allocate bitmaps structures | ||
433 | */ | ||
434 | pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"), | ||
435 | &ctx->inode_used_map); | ||
436 | if (pctx.errcode) { | ||
437 | pctx.num = 1; | ||
438 | fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx); | ||
439 | ctx->flags |= E2F_FLAG_ABORT; | ||
440 | return; | ||
441 | } | ||
442 | pctx.errcode = ext2fs_allocate_inode_bitmap(fs, | ||
443 | _("directory inode map"), &ctx->inode_dir_map); | ||
444 | if (pctx.errcode) { | ||
445 | pctx.num = 2; | ||
446 | fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx); | ||
447 | ctx->flags |= E2F_FLAG_ABORT; | ||
448 | return; | ||
449 | } | ||
450 | pctx.errcode = ext2fs_allocate_inode_bitmap(fs, | ||
451 | _("regular file inode map"), &ctx->inode_reg_map); | ||
452 | if (pctx.errcode) { | ||
453 | pctx.num = 6; | ||
454 | fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx); | ||
455 | ctx->flags |= E2F_FLAG_ABORT; | ||
456 | return; | ||
457 | } | ||
458 | pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"), | ||
459 | &ctx->block_found_map); | ||
460 | if (pctx.errcode) { | ||
461 | pctx.num = 1; | ||
462 | fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx); | ||
463 | ctx->flags |= E2F_FLAG_ABORT; | ||
464 | return; | ||
465 | } | ||
466 | pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0, | ||
467 | &ctx->inode_link_info); | ||
468 | if (pctx.errcode) { | ||
469 | fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx); | ||
470 | ctx->flags |= E2F_FLAG_ABORT; | ||
471 | return; | ||
472 | } | ||
473 | inode_size = EXT2_INODE_SIZE(fs->super); | ||
474 | inode = (struct ext2_inode *) | ||
475 | e2fsck_allocate_memory(ctx, inode_size, "scratch inode"); | ||
476 | |||
477 | inodes_to_process = (struct process_inode_block *) | ||
478 | e2fsck_allocate_memory(ctx, | ||
479 | (ctx->process_inode_size * | ||
480 | sizeof(struct process_inode_block)), | ||
481 | "array of inodes to process"); | ||
482 | process_inode_count = 0; | ||
483 | |||
484 | pctx.errcode = ext2fs_init_dblist(fs, 0); | ||
485 | if (pctx.errcode) { | ||
486 | fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx); | ||
487 | ctx->flags |= E2F_FLAG_ABORT; | ||
488 | return; | ||
489 | } | ||
490 | |||
491 | /* | ||
492 | * If the last orphan field is set, clear it, since the pass1 | ||
493 | * processing will automatically find and clear the orphans. | ||
494 | * In the future, we may want to try using the last_orphan | ||
495 | * linked list ourselves, but for now, we clear it so that the | ||
496 | * ext3 mount code won't get confused. | ||
497 | */ | ||
498 | if (!(ctx->options & E2F_OPT_READONLY)) { | ||
499 | if (fs->super->s_last_orphan) { | ||
500 | fs->super->s_last_orphan = 0; | ||
501 | ext2fs_mark_super_dirty(fs); | ||
502 | } | ||
503 | } | ||
504 | |||
505 | mark_table_blocks(ctx); | ||
506 | block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3, | ||
507 | "block interate buffer"); | ||
508 | e2fsck_use_inode_shortcuts(ctx, 1); | ||
509 | ehandler_operation(_("doing inode scan")); | ||
510 | pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks, | ||
511 | &scan); | ||
512 | if (pctx.errcode) { | ||
513 | fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx); | ||
514 | ctx->flags |= E2F_FLAG_ABORT; | ||
515 | return; | ||
516 | } | ||
517 | ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0); | ||
518 | ctx->stashed_inode = inode; | ||
519 | scan_struct.ctx = ctx; | ||
520 | scan_struct.block_buf = block_buf; | ||
521 | ext2fs_set_inode_callback(scan, scan_callback, &scan_struct); | ||
522 | if (ctx->progress) | ||
523 | if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count)) | ||
524 | return; | ||
525 | if (fs->super->s_wtime < fs->super->s_inodes_count) | ||
526 | busted_fs_time = 1; | ||
527 | |||
528 | while (1) { | ||
529 | pctx.errcode = ext2fs_get_next_inode_full(scan, &ino, | ||
530 | inode, inode_size); | ||
531 | if (ctx->flags & E2F_FLAG_SIGNAL_MASK) | ||
532 | return; | ||
533 | if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) { | ||
534 | if (!ctx->inode_bb_map) | ||
535 | alloc_bb_map(ctx); | ||
536 | ext2fs_mark_inode_bitmap(ctx->inode_bb_map, ino); | ||
537 | ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino); | ||
538 | continue; | ||
539 | } | ||
540 | if (pctx.errcode) { | ||
541 | fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx); | ||
542 | ctx->flags |= E2F_FLAG_ABORT; | ||
543 | return; | ||
544 | } | ||
545 | if (!ino) | ||
546 | break; | ||
547 | pctx.ino = ino; | ||
548 | pctx.inode = inode; | ||
549 | ctx->stashed_ino = ino; | ||
550 | if (inode->i_links_count) { | ||
551 | pctx.errcode = ext2fs_icount_store(ctx->inode_link_info, | ||
552 | ino, inode->i_links_count); | ||
553 | if (pctx.errcode) { | ||
554 | pctx.num = inode->i_links_count; | ||
555 | fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx); | ||
556 | ctx->flags |= E2F_FLAG_ABORT; | ||
557 | return; | ||
558 | } | ||
559 | } | ||
560 | if (ino == EXT2_BAD_INO) { | ||
561 | struct process_block_struct pb; | ||
562 | |||
563 | pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map, | ||
564 | &pb.fs_meta_blocks); | ||
565 | if (pctx.errcode) { | ||
566 | pctx.num = 4; | ||
567 | fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx); | ||
568 | ctx->flags |= E2F_FLAG_ABORT; | ||
569 | return; | ||
570 | } | ||
571 | pb.ino = EXT2_BAD_INO; | ||
572 | pb.num_blocks = pb.last_block = 0; | ||
573 | pb.num_illegal_blocks = 0; | ||
574 | pb.suppress = 0; pb.clear = 0; pb.is_dir = 0; | ||
575 | pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0; | ||
576 | pb.inode = inode; | ||
577 | pb.pctx = &pctx; | ||
578 | pb.ctx = ctx; | ||
579 | pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, | ||
580 | block_buf, process_bad_block, &pb); | ||
581 | ext2fs_free_block_bitmap(pb.fs_meta_blocks); | ||
582 | if (pctx.errcode) { | ||
583 | fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx); | ||
584 | ctx->flags |= E2F_FLAG_ABORT; | ||
585 | return; | ||
586 | } | ||
587 | if (pb.bbcheck) | ||
588 | if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) { | ||
589 | ctx->flags |= E2F_FLAG_ABORT; | ||
590 | return; | ||
591 | } | ||
592 | ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino); | ||
593 | clear_problem_context(&pctx); | ||
594 | continue; | ||
595 | } else if (ino == EXT2_ROOT_INO) { | ||
596 | /* | ||
597 | * Make sure the root inode is a directory; if | ||
598 | * not, offer to clear it. It will be | ||
599 | * regnerated in pass #3. | ||
600 | */ | ||
601 | if (!LINUX_S_ISDIR(inode->i_mode)) { | ||
602 | if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) { | ||
603 | inode->i_dtime = time(0); | ||
604 | inode->i_links_count = 0; | ||
605 | ext2fs_icount_store(ctx->inode_link_info, | ||
606 | ino, 0); | ||
607 | e2fsck_write_inode(ctx, ino, inode, | ||
608 | "pass1"); | ||
609 | } | ||
610 | |||
611 | } | ||
612 | /* | ||
613 | * If dtime is set, offer to clear it. mke2fs | ||
614 | * version 0.2b created filesystems with the | ||
615 | * dtime field set for the root and lost+found | ||
616 | * directories. We won't worry about | ||
617 | * /lost+found, since that can be regenerated | ||
618 | * easily. But we will fix the root directory | ||
619 | * as a special case. | ||
620 | */ | ||
621 | if (inode->i_dtime && inode->i_links_count) { | ||
622 | if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) { | ||
623 | inode->i_dtime = 0; | ||
624 | e2fsck_write_inode(ctx, ino, inode, | ||
625 | "pass1"); | ||
626 | } | ||
627 | } | ||
628 | } else if (ino == EXT2_JOURNAL_INO) { | ||
629 | ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino); | ||
630 | if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) { | ||
631 | if (!LINUX_S_ISREG(inode->i_mode) && | ||
632 | fix_problem(ctx, PR_1_JOURNAL_BAD_MODE, | ||
633 | &pctx)) { | ||
634 | inode->i_mode = LINUX_S_IFREG; | ||
635 | e2fsck_write_inode(ctx, ino, inode, | ||
636 | "pass1"); | ||
637 | } | ||
638 | check_blocks(ctx, &pctx, block_buf); | ||
639 | continue; | ||
640 | } | ||
641 | if ((inode->i_links_count || inode->i_blocks || | ||
642 | inode->i_blocks || inode->i_block[0]) && | ||
643 | fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR, | ||
644 | &pctx)) { | ||
645 | memset(inode, 0, inode_size); | ||
646 | ext2fs_icount_store(ctx->inode_link_info, | ||
647 | ino, 0); | ||
648 | e2fsck_write_inode_full(ctx, ino, inode, | ||
649 | inode_size, "pass1"); | ||
650 | } | ||
651 | } else if (ino < EXT2_FIRST_INODE(fs->super)) { | ||
652 | int problem = 0; | ||
653 | |||
654 | ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino); | ||
655 | if (ino == EXT2_BOOT_LOADER_INO) { | ||
656 | if (LINUX_S_ISDIR(inode->i_mode)) | ||
657 | problem = PR_1_RESERVED_BAD_MODE; | ||
658 | } else if (ino == EXT2_RESIZE_INO) { | ||
659 | if (inode->i_mode && | ||
660 | !LINUX_S_ISREG(inode->i_mode)) | ||
661 | problem = PR_1_RESERVED_BAD_MODE; | ||
662 | } else { | ||
663 | if (inode->i_mode != 0) | ||
664 | problem = PR_1_RESERVED_BAD_MODE; | ||
665 | } | ||
666 | if (problem) { | ||
667 | if (fix_problem(ctx, problem, &pctx)) { | ||
668 | inode->i_mode = 0; | ||
669 | e2fsck_write_inode(ctx, ino, inode, | ||
670 | "pass1"); | ||
671 | } | ||
672 | } | ||
673 | check_blocks(ctx, &pctx, block_buf); | ||
674 | continue; | ||
675 | } | ||
676 | /* | ||
677 | * Check for inodes who might have been part of the | ||
678 | * orphaned list linked list. They should have gotten | ||
679 | * dealt with by now, unless the list had somehow been | ||
680 | * corrupted. | ||
681 | * | ||
682 | * FIXME: In the future, inodes which are still in use | ||
683 | * (and which are therefore) pending truncation should | ||
684 | * be handled specially. Right now we just clear the | ||
685 | * dtime field, and the normal e2fsck handling of | ||
686 | * inodes where i_size and the inode blocks are | ||
687 | * inconsistent is to fix i_size, instead of releasing | ||
688 | * the extra blocks. This won't catch the inodes that | ||
689 | * was at the end of the orphan list, but it's better | ||
690 | * than nothing. The right answer is that there | ||
691 | * shouldn't be any bugs in the orphan list handling. :-) | ||
692 | */ | ||
693 | if (inode->i_dtime && !busted_fs_time && | ||
694 | inode->i_dtime < ctx->fs->super->s_inodes_count) { | ||
695 | if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) { | ||
696 | inode->i_dtime = inode->i_links_count ? | ||
697 | 0 : time(0); | ||
698 | e2fsck_write_inode(ctx, ino, inode, | ||
699 | "pass1"); | ||
700 | } | ||
701 | } | ||
702 | |||
703 | /* | ||
704 | * This code assumes that deleted inodes have | ||
705 | * i_links_count set to 0. | ||
706 | */ | ||
707 | if (!inode->i_links_count) { | ||
708 | if (!inode->i_dtime && inode->i_mode) { | ||
709 | if (fix_problem(ctx, | ||
710 | PR_1_ZERO_DTIME, &pctx)) { | ||
711 | inode->i_dtime = time(0); | ||
712 | e2fsck_write_inode(ctx, ino, inode, | ||
713 | "pass1"); | ||
714 | } | ||
715 | } | ||
716 | continue; | ||
717 | } | ||
718 | /* | ||
719 | * n.b. 0.3c ext2fs code didn't clear i_links_count for | ||
720 | * deleted files. Oops. | ||
721 | * | ||
722 | * Since all new ext2 implementations get this right, | ||
723 | * we now assume that the case of non-zero | ||
724 | * i_links_count and non-zero dtime means that we | ||
725 | * should keep the file, not delete it. | ||
726 | * | ||
727 | */ | ||
728 | if (inode->i_dtime) { | ||
729 | if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) { | ||
730 | inode->i_dtime = 0; | ||
731 | e2fsck_write_inode(ctx, ino, inode, "pass1"); | ||
732 | } | ||
733 | } | ||
734 | |||
735 | ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino); | ||
736 | switch (fs->super->s_creator_os) { | ||
737 | case EXT2_OS_LINUX: | ||
738 | frag = inode->osd2.linux2.l_i_frag; | ||
739 | fsize = inode->osd2.linux2.l_i_fsize; | ||
740 | break; | ||
741 | case EXT2_OS_HURD: | ||
742 | frag = inode->osd2.hurd2.h_i_frag; | ||
743 | fsize = inode->osd2.hurd2.h_i_fsize; | ||
744 | break; | ||
745 | case EXT2_OS_MASIX: | ||
746 | frag = inode->osd2.masix2.m_i_frag; | ||
747 | fsize = inode->osd2.masix2.m_i_fsize; | ||
748 | break; | ||
749 | default: | ||
750 | frag = fsize = 0; | ||
751 | } | ||
752 | |||
753 | if (inode->i_faddr || frag || fsize || | ||
754 | (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl)) | ||
755 | mark_inode_bad(ctx, ino); | ||
756 | if (inode->i_flags & EXT2_IMAGIC_FL) { | ||
757 | if (imagic_fs) { | ||
758 | if (!ctx->inode_imagic_map) | ||
759 | alloc_imagic_map(ctx); | ||
760 | ext2fs_mark_inode_bitmap(ctx->inode_imagic_map, | ||
761 | ino); | ||
762 | } else { | ||
763 | if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) { | ||
764 | inode->i_flags &= ~EXT2_IMAGIC_FL; | ||
765 | e2fsck_write_inode(ctx, ino, | ||
766 | inode, "pass1"); | ||
767 | } | ||
768 | } | ||
769 | } | ||
770 | |||
771 | check_inode_extra_space(ctx, &pctx); | ||
772 | |||
773 | if (LINUX_S_ISDIR(inode->i_mode)) { | ||
774 | ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino); | ||
775 | e2fsck_add_dir_info(ctx, ino, 0); | ||
776 | ctx->fs_directory_count++; | ||
777 | } else if (LINUX_S_ISREG (inode->i_mode)) { | ||
778 | ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino); | ||
779 | ctx->fs_regular_count++; | ||
780 | } else if (LINUX_S_ISCHR (inode->i_mode) && | ||
781 | e2fsck_pass1_check_device_inode(fs, inode)) { | ||
782 | check_immutable(ctx, &pctx); | ||
783 | check_size(ctx, &pctx); | ||
784 | ctx->fs_chardev_count++; | ||
785 | } else if (LINUX_S_ISBLK (inode->i_mode) && | ||
786 | e2fsck_pass1_check_device_inode(fs, inode)) { | ||
787 | check_immutable(ctx, &pctx); | ||
788 | check_size(ctx, &pctx); | ||
789 | ctx->fs_blockdev_count++; | ||
790 | } else if (LINUX_S_ISLNK (inode->i_mode) && | ||
791 | e2fsck_pass1_check_symlink(fs, inode, block_buf)) { | ||
792 | check_immutable(ctx, &pctx); | ||
793 | ctx->fs_symlinks_count++; | ||
794 | if (ext2fs_inode_data_blocks(fs, inode) == 0) { | ||
795 | ctx->fs_fast_symlinks_count++; | ||
796 | check_blocks(ctx, &pctx, block_buf); | ||
797 | continue; | ||
798 | } | ||
799 | } | ||
800 | else if (LINUX_S_ISFIFO (inode->i_mode) && | ||
801 | e2fsck_pass1_check_device_inode(fs, inode)) { | ||
802 | check_immutable(ctx, &pctx); | ||
803 | check_size(ctx, &pctx); | ||
804 | ctx->fs_fifo_count++; | ||
805 | } else if ((LINUX_S_ISSOCK (inode->i_mode)) && | ||
806 | e2fsck_pass1_check_device_inode(fs, inode)) { | ||
807 | check_immutable(ctx, &pctx); | ||
808 | check_size(ctx, &pctx); | ||
809 | ctx->fs_sockets_count++; | ||
810 | } else | ||
811 | mark_inode_bad(ctx, ino); | ||
812 | if (inode->i_block[EXT2_IND_BLOCK]) | ||
813 | ctx->fs_ind_count++; | ||
814 | if (inode->i_block[EXT2_DIND_BLOCK]) | ||
815 | ctx->fs_dind_count++; | ||
816 | if (inode->i_block[EXT2_TIND_BLOCK]) | ||
817 | ctx->fs_tind_count++; | ||
818 | if (inode->i_block[EXT2_IND_BLOCK] || | ||
819 | inode->i_block[EXT2_DIND_BLOCK] || | ||
820 | inode->i_block[EXT2_TIND_BLOCK] || | ||
821 | inode->i_file_acl) { | ||
822 | inodes_to_process[process_inode_count].ino = ino; | ||
823 | inodes_to_process[process_inode_count].inode = *inode; | ||
824 | process_inode_count++; | ||
825 | } else | ||
826 | check_blocks(ctx, &pctx, block_buf); | ||
827 | |||
828 | if (ctx->flags & E2F_FLAG_SIGNAL_MASK) | ||
829 | return; | ||
830 | |||
831 | if (process_inode_count >= ctx->process_inode_size) { | ||
832 | process_inodes(ctx, block_buf); | ||
833 | |||
834 | if (ctx->flags & E2F_FLAG_SIGNAL_MASK) | ||
835 | return; | ||
836 | } | ||
837 | } | ||
838 | process_inodes(ctx, block_buf); | ||
839 | ext2fs_close_inode_scan(scan); | ||
840 | ehandler_operation(0); | ||
841 | |||
842 | /* | ||
843 | * If any extended attribute blocks' reference counts need to | ||
844 | * be adjusted, either up (ctx->refcount_extra), or down | ||
845 | * (ctx->refcount), then fix them. | ||
846 | */ | ||
847 | if (ctx->refcount) { | ||
848 | adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1); | ||
849 | ea_refcount_free(ctx->refcount); | ||
850 | ctx->refcount = 0; | ||
851 | } | ||
852 | if (ctx->refcount_extra) { | ||
853 | adjust_extattr_refcount(ctx, ctx->refcount_extra, | ||
854 | block_buf, +1); | ||
855 | ea_refcount_free(ctx->refcount_extra); | ||
856 | ctx->refcount_extra = 0; | ||
857 | } | ||
858 | |||
859 | if (ctx->invalid_bitmaps) | ||
860 | handle_fs_bad_blocks(ctx); | ||
861 | |||
862 | /* We don't need the block_ea_map any more */ | ||
863 | if (ctx->block_ea_map) { | ||
864 | ext2fs_free_block_bitmap(ctx->block_ea_map); | ||
865 | ctx->block_ea_map = 0; | ||
866 | } | ||
867 | |||
868 | if (ctx->flags & E2F_FLAG_RESIZE_INODE) { | ||
869 | ext2fs_block_bitmap save_bmap; | ||
870 | |||
871 | save_bmap = fs->block_map; | ||
872 | fs->block_map = ctx->block_found_map; | ||
873 | clear_problem_context(&pctx); | ||
874 | pctx.errcode = ext2fs_create_resize_inode(fs); | ||
875 | if (pctx.errcode) { | ||
876 | fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx); | ||
877 | /* Should never get here */ | ||
878 | ctx->flags |= E2F_FLAG_ABORT; | ||
879 | return; | ||
880 | } | ||
881 | fs->block_map = save_bmap; | ||
882 | ctx->flags &= ~E2F_FLAG_RESIZE_INODE; | ||
883 | } | ||
884 | |||
885 | if (ctx->flags & E2F_FLAG_RESTART) { | ||
886 | /* | ||
887 | * Only the master copy of the superblock and block | ||
888 | * group descriptors are going to be written during a | ||
889 | * restart, so set the superblock to be used to be the | ||
890 | * master superblock. | ||
891 | */ | ||
892 | ctx->use_superblock = 0; | ||
893 | unwind_pass1(fs); | ||
894 | goto endit; | ||
895 | } | ||
896 | |||
897 | if (ctx->block_dup_map) { | ||
898 | if (ctx->options & E2F_OPT_PREEN) { | ||
899 | clear_problem_context(&pctx); | ||
900 | fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx); | ||
901 | } | ||
902 | e2fsck_pass1_dupblocks(ctx, block_buf); | ||
903 | } | ||
904 | ext2fs_free_mem(&inodes_to_process); | ||
905 | endit: | ||
906 | e2fsck_use_inode_shortcuts(ctx, 0); | ||
907 | |||
908 | ext2fs_free_mem(&block_buf); | ||
909 | ext2fs_free_mem(&inode); | ||
910 | |||
911 | #ifdef RESOURCE_TRACK | ||
912 | if (ctx->options & E2F_OPT_TIME2) { | ||
913 | e2fsck_clear_progbar(ctx); | ||
914 | print_resource_track(_("Pass 1"), &rtrack); | ||
915 | } | ||
916 | #endif | ||
917 | } | ||
918 | |||
919 | /* | ||
920 | * When the inode_scan routines call this callback at the end of the | ||
921 | * glock group, call process_inodes. | ||
922 | */ | ||
923 | static errcode_t scan_callback(ext2_filsys fs, | ||
924 | ext2_inode_scan scan EXT2FS_ATTR((unused)), | ||
925 | dgrp_t group, void * priv_data) | ||
926 | { | ||
927 | struct scan_callback_struct *scan_struct; | ||
928 | e2fsck_t ctx; | ||
929 | |||
930 | scan_struct = (struct scan_callback_struct *) priv_data; | ||
931 | ctx = scan_struct->ctx; | ||
932 | |||
933 | process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf); | ||
934 | |||
935 | if (ctx->progress) | ||
936 | if ((ctx->progress)(ctx, 1, group+1, | ||
937 | ctx->fs->group_desc_count)) | ||
938 | return EXT2_ET_CANCEL_REQUESTED; | ||
939 | |||
940 | return 0; | ||
941 | } | ||
942 | |||
943 | /* | ||
944 | * Process the inodes in the "inodes to process" list. | ||
945 | */ | ||
946 | static void process_inodes(e2fsck_t ctx, char *block_buf) | ||
947 | { | ||
948 | int i; | ||
949 | struct ext2_inode *old_stashed_inode; | ||
950 | ext2_ino_t old_stashed_ino; | ||
951 | const char *old_operation; | ||
952 | char buf[80]; | ||
953 | struct problem_context pctx; | ||
954 | |||
955 | #if 0 | ||
956 | printf("begin process_inodes: "); | ||
957 | #endif | ||
958 | if (process_inode_count == 0) | ||
959 | return; | ||
960 | old_operation = ehandler_operation(0); | ||
961 | old_stashed_inode = ctx->stashed_inode; | ||
962 | old_stashed_ino = ctx->stashed_ino; | ||
963 | qsort(inodes_to_process, process_inode_count, | ||
964 | sizeof(struct process_inode_block), process_inode_cmp); | ||
965 | clear_problem_context(&pctx); | ||
966 | for (i=0; i < process_inode_count; i++) { | ||
967 | pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode; | ||
968 | pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino; | ||
969 | |||
970 | #if 0 | ||
971 | printf("%u ", pctx.ino); | ||
972 | #endif | ||
973 | sprintf(buf, _("reading indirect blocks of inode %u"), | ||
974 | pctx.ino); | ||
975 | ehandler_operation(buf); | ||
976 | check_blocks(ctx, &pctx, block_buf); | ||
977 | if (ctx->flags & E2F_FLAG_SIGNAL_MASK) | ||
978 | break; | ||
979 | } | ||
980 | ctx->stashed_inode = old_stashed_inode; | ||
981 | ctx->stashed_ino = old_stashed_ino; | ||
982 | process_inode_count = 0; | ||
983 | #if 0 | ||
984 | printf("end process inodes\n"); | ||
985 | #endif | ||
986 | ehandler_operation(old_operation); | ||
987 | } | ||
988 | |||
989 | static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b) | ||
990 | { | ||
991 | const struct process_inode_block *ib_a = | ||
992 | (const struct process_inode_block *) a; | ||
993 | const struct process_inode_block *ib_b = | ||
994 | (const struct process_inode_block *) b; | ||
995 | int ret; | ||
996 | |||
997 | ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] - | ||
998 | ib_b->inode.i_block[EXT2_IND_BLOCK]); | ||
999 | if (ret == 0) | ||
1000 | ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl; | ||
1001 | return ret; | ||
1002 | } | ||
1003 | |||
1004 | /* | ||
1005 | * Mark an inode as being bad in some what | ||
1006 | */ | ||
1007 | static void mark_inode_bad(e2fsck_t ctx, ino_t ino) | ||
1008 | { | ||
1009 | struct problem_context pctx; | ||
1010 | |||
1011 | if (!ctx->inode_bad_map) { | ||
1012 | clear_problem_context(&pctx); | ||
1013 | |||
1014 | pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs, | ||
1015 | _("bad inode map"), &ctx->inode_bad_map); | ||
1016 | if (pctx.errcode) { | ||
1017 | pctx.num = 3; | ||
1018 | fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx); | ||
1019 | /* Should never get here */ | ||
1020 | ctx->flags |= E2F_FLAG_ABORT; | ||
1021 | return; | ||
1022 | } | ||
1023 | } | ||
1024 | ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino); | ||
1025 | } | ||
1026 | |||
1027 | |||
1028 | /* | ||
1029 | * This procedure will allocate the inode "bb" (badblock) map table | ||
1030 | */ | ||
1031 | static void alloc_bb_map(e2fsck_t ctx) | ||
1032 | { | ||
1033 | struct problem_context pctx; | ||
1034 | |||
1035 | clear_problem_context(&pctx); | ||
1036 | pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs, | ||
1037 | _("inode in bad block map"), | ||
1038 | &ctx->inode_bb_map); | ||
1039 | if (pctx.errcode) { | ||
1040 | pctx.num = 4; | ||
1041 | fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx); | ||
1042 | /* Should never get here */ | ||
1043 | ctx->flags |= E2F_FLAG_ABORT; | ||
1044 | return; | ||
1045 | } | ||
1046 | } | ||
1047 | |||
1048 | /* | ||
1049 | * This procedure will allocate the inode imagic table | ||
1050 | */ | ||
1051 | static void alloc_imagic_map(e2fsck_t ctx) | ||
1052 | { | ||
1053 | struct problem_context pctx; | ||
1054 | |||
1055 | clear_problem_context(&pctx); | ||
1056 | pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs, | ||
1057 | _("imagic inode map"), | ||
1058 | &ctx->inode_imagic_map); | ||
1059 | if (pctx.errcode) { | ||
1060 | pctx.num = 5; | ||
1061 | fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx); | ||
1062 | /* Should never get here */ | ||
1063 | ctx->flags |= E2F_FLAG_ABORT; | ||
1064 | return; | ||
1065 | } | ||
1066 | } | ||
1067 | |||
1068 | /* | ||
1069 | * Marks a block as in use, setting the dup_map if it's been set | ||
1070 | * already. Called by process_block and process_bad_block. | ||
1071 | * | ||
1072 | * WARNING: Assumes checks have already been done to make sure block | ||
1073 | * is valid. This is true in both process_block and process_bad_block. | ||
1074 | */ | ||
1075 | static _INLINE_ void mark_block_used(e2fsck_t ctx, blk_t block) | ||
1076 | { | ||
1077 | struct problem_context pctx; | ||
1078 | |||
1079 | clear_problem_context(&pctx); | ||
1080 | |||
1081 | if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) { | ||
1082 | if (!ctx->block_dup_map) { | ||
1083 | pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs, | ||
1084 | _("multiply claimed block map"), | ||
1085 | &ctx->block_dup_map); | ||
1086 | if (pctx.errcode) { | ||
1087 | pctx.num = 3; | ||
1088 | fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, | ||
1089 | &pctx); | ||
1090 | /* Should never get here */ | ||
1091 | ctx->flags |= E2F_FLAG_ABORT; | ||
1092 | return; | ||
1093 | } | ||
1094 | } | ||
1095 | ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block); | ||
1096 | } else { | ||
1097 | ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block); | ||
1098 | } | ||
1099 | } | ||
1100 | |||
1101 | /* | ||
1102 | * Adjust the extended attribute block's reference counts at the end | ||
1103 | * of pass 1, either by subtracting out references for EA blocks that | ||
1104 | * are still referenced in ctx->refcount, or by adding references for | ||
1105 | * EA blocks that had extra references as accounted for in | ||
1106 | * ctx->refcount_extra. | ||
1107 | */ | ||
1108 | static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount, | ||
1109 | char *block_buf, int adjust_sign) | ||
1110 | { | ||
1111 | struct ext2_ext_attr_header *header; | ||
1112 | struct problem_context pctx; | ||
1113 | ext2_filsys fs = ctx->fs; | ||
1114 | blk_t blk; | ||
1115 | __u32 should_be; | ||
1116 | int count; | ||
1117 | |||
1118 | clear_problem_context(&pctx); | ||
1119 | |||
1120 | ea_refcount_intr_begin(refcount); | ||
1121 | while (1) { | ||
1122 | if ((blk = ea_refcount_intr_next(refcount, &count)) == 0) | ||
1123 | break; | ||
1124 | pctx.blk = blk; | ||
1125 | pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf); | ||
1126 | if (pctx.errcode) { | ||
1127 | fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx); | ||
1128 | return; | ||
1129 | } | ||
1130 | header = (struct ext2_ext_attr_header *) block_buf; | ||
1131 | pctx.blkcount = header->h_refcount; | ||
1132 | should_be = header->h_refcount + adjust_sign * count; | ||
1133 | pctx.num = should_be; | ||
1134 | if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) { | ||
1135 | header->h_refcount = should_be; | ||
1136 | pctx.errcode = ext2fs_write_ext_attr(fs, blk, | ||
1137 | block_buf); | ||
1138 | if (pctx.errcode) { | ||
1139 | fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx); | ||
1140 | continue; | ||
1141 | } | ||
1142 | } | ||
1143 | } | ||
1144 | } | ||
1145 | |||
1146 | /* | ||
1147 | * Handle processing the extended attribute blocks | ||
1148 | */ | ||
1149 | static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx, | ||
1150 | char *block_buf) | ||
1151 | { | ||
1152 | ext2_filsys fs = ctx->fs; | ||
1153 | ext2_ino_t ino = pctx->ino; | ||
1154 | struct ext2_inode *inode = pctx->inode; | ||
1155 | blk_t blk; | ||
1156 | char * end; | ||
1157 | struct ext2_ext_attr_header *header; | ||
1158 | struct ext2_ext_attr_entry *entry; | ||
1159 | int count; | ||
1160 | region_t region; | ||
1161 | |||
1162 | blk = inode->i_file_acl; | ||
1163 | if (blk == 0) | ||
1164 | return 0; | ||
1165 | |||
1166 | /* | ||
1167 | * If the Extended attribute flag isn't set, then a non-zero | ||
1168 | * file acl means that the inode is corrupted. | ||
1169 | * | ||
1170 | * Or if the extended attribute block is an invalid block, | ||
1171 | * then the inode is also corrupted. | ||
1172 | */ | ||
1173 | if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) || | ||
1174 | (blk < fs->super->s_first_data_block) || | ||
1175 | (blk >= fs->super->s_blocks_count)) { | ||
1176 | mark_inode_bad(ctx, ino); | ||
1177 | return 0; | ||
1178 | } | ||
1179 | |||
1180 | /* If ea bitmap hasn't been allocated, create it */ | ||
1181 | if (!ctx->block_ea_map) { | ||
1182 | pctx->errcode = ext2fs_allocate_block_bitmap(fs, | ||
1183 | _("ext attr block map"), | ||
1184 | &ctx->block_ea_map); | ||
1185 | if (pctx->errcode) { | ||
1186 | pctx->num = 2; | ||
1187 | fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx); | ||
1188 | ctx->flags |= E2F_FLAG_ABORT; | ||
1189 | return 0; | ||
1190 | } | ||
1191 | } | ||
1192 | |||
1193 | /* Create the EA refcount structure if necessary */ | ||
1194 | if (!ctx->refcount) { | ||
1195 | pctx->errcode = ea_refcount_create(0, &ctx->refcount); | ||
1196 | if (pctx->errcode) { | ||
1197 | pctx->num = 1; | ||
1198 | fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx); | ||
1199 | ctx->flags |= E2F_FLAG_ABORT; | ||
1200 | return 0; | ||
1201 | } | ||
1202 | } | ||
1203 | |||
1204 | #if 0 | ||
1205 | /* Debugging text */ | ||
1206 | printf("Inode %u has EA block %u\n", ino, blk); | ||
1207 | #endif | ||
1208 | |||
1209 | /* Have we seen this EA block before? */ | ||
1210 | if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) { | ||
1211 | if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0) | ||
1212 | return 1; | ||
1213 | /* Ooops, this EA was referenced more than it stated */ | ||
1214 | if (!ctx->refcount_extra) { | ||
1215 | pctx->errcode = ea_refcount_create(0, | ||
1216 | &ctx->refcount_extra); | ||
1217 | if (pctx->errcode) { | ||
1218 | pctx->num = 2; | ||
1219 | fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx); | ||
1220 | ctx->flags |= E2F_FLAG_ABORT; | ||
1221 | return 0; | ||
1222 | } | ||
1223 | } | ||
1224 | ea_refcount_increment(ctx->refcount_extra, blk, 0); | ||
1225 | return 1; | ||
1226 | } | ||
1227 | |||
1228 | /* | ||
1229 | * OK, we haven't seen this EA block yet. So we need to | ||
1230 | * validate it | ||
1231 | */ | ||
1232 | pctx->blk = blk; | ||
1233 | pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf); | ||
1234 | if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx)) | ||
1235 | goto clear_extattr; | ||
1236 | header = (struct ext2_ext_attr_header *) block_buf; | ||
1237 | pctx->blk = inode->i_file_acl; | ||
1238 | if (((ctx->ext_attr_ver == 1) && | ||
1239 | (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) || | ||
1240 | ((ctx->ext_attr_ver == 2) && | ||
1241 | (header->h_magic != EXT2_EXT_ATTR_MAGIC))) { | ||
1242 | if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx)) | ||
1243 | goto clear_extattr; | ||
1244 | } | ||
1245 | |||
1246 | if (header->h_blocks != 1) { | ||
1247 | if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx)) | ||
1248 | goto clear_extattr; | ||
1249 | } | ||
1250 | |||
1251 | region = region_create(0, fs->blocksize); | ||
1252 | if (!region) { | ||
1253 | fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx); | ||
1254 | ctx->flags |= E2F_FLAG_ABORT; | ||
1255 | return 0; | ||
1256 | } | ||
1257 | if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) { | ||
1258 | if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx)) | ||
1259 | goto clear_extattr; | ||
1260 | } | ||
1261 | |||
1262 | entry = (struct ext2_ext_attr_entry *)(header+1); | ||
1263 | end = block_buf + fs->blocksize; | ||
1264 | while ((char *)entry < end && *(__u32 *)entry) { | ||
1265 | if (region_allocate(region, (char *)entry - (char *)header, | ||
1266 | EXT2_EXT_ATTR_LEN(entry->e_name_len))) { | ||
1267 | if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx)) | ||
1268 | goto clear_extattr; | ||
1269 | } | ||
1270 | if ((ctx->ext_attr_ver == 1 && | ||
1271 | (entry->e_name_len == 0 || entry->e_name_index != 0)) || | ||
1272 | (ctx->ext_attr_ver == 2 && | ||
1273 | entry->e_name_index == 0)) { | ||
1274 | if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx)) | ||
1275 | goto clear_extattr; | ||
1276 | } | ||
1277 | if (entry->e_value_block != 0) { | ||
1278 | if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx)) | ||
1279 | goto clear_extattr; | ||
1280 | } | ||
1281 | if (entry->e_value_size && | ||
1282 | region_allocate(region, entry->e_value_offs, | ||
1283 | EXT2_EXT_ATTR_SIZE(entry->e_value_size))) { | ||
1284 | if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx)) | ||
1285 | goto clear_extattr; | ||
1286 | } | ||
1287 | entry = EXT2_EXT_ATTR_NEXT(entry); | ||
1288 | } | ||
1289 | if (region_allocate(region, (char *)entry - (char *)header, 4)) { | ||
1290 | if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx)) | ||
1291 | goto clear_extattr; | ||
1292 | } | ||
1293 | region_free(region); | ||
1294 | |||
1295 | count = header->h_refcount - 1; | ||
1296 | if (count) | ||
1297 | ea_refcount_store(ctx->refcount, blk, count); | ||
1298 | mark_block_used(ctx, blk); | ||
1299 | ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk); | ||
1300 | |||
1301 | return 1; | ||
1302 | |||
1303 | clear_extattr: | ||
1304 | inode->i_file_acl = 0; | ||
1305 | e2fsck_write_inode(ctx, ino, inode, "check_ext_attr"); | ||
1306 | return 0; | ||
1307 | } | ||
1308 | |||
1309 | /* Returns 1 if bad htree, 0 if OK */ | ||
1310 | static int handle_htree(e2fsck_t ctx, struct problem_context *pctx, | ||
1311 | ext2_ino_t ino EXT2FS_ATTR((unused)), | ||
1312 | struct ext2_inode *inode, | ||
1313 | char *block_buf) | ||
1314 | { | ||
1315 | struct ext2_dx_root_info *root; | ||
1316 | ext2_filsys fs = ctx->fs; | ||
1317 | errcode_t retval; | ||
1318 | blk_t blk; | ||
1319 | |||
1320 | if ((!LINUX_S_ISDIR(inode->i_mode) && | ||
1321 | fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) || | ||
1322 | (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) && | ||
1323 | fix_problem(ctx, PR_1_HTREE_SET, pctx))) | ||
1324 | return 1; | ||
1325 | |||
1326 | blk = inode->i_block[0]; | ||
1327 | if (((blk == 0) || | ||
1328 | (blk < fs->super->s_first_data_block) || | ||
1329 | (blk >= fs->super->s_blocks_count)) && | ||
1330 | fix_problem(ctx, PR_1_HTREE_BADROOT, pctx)) | ||
1331 | return 1; | ||
1332 | |||
1333 | retval = io_channel_read_blk(fs->io, blk, 1, block_buf); | ||
1334 | if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx)) | ||
1335 | return 1; | ||
1336 | |||
1337 | /* XXX should check that beginning matches a directory */ | ||
1338 | root = (struct ext2_dx_root_info *) (block_buf + 24); | ||
1339 | |||
1340 | if ((root->reserved_zero || root->info_length < 8) && | ||
1341 | fix_problem(ctx, PR_1_HTREE_BADROOT, pctx)) | ||
1342 | return 1; | ||
1343 | |||
1344 | pctx->num = root->hash_version; | ||
1345 | if ((root->hash_version != EXT2_HASH_LEGACY) && | ||
1346 | (root->hash_version != EXT2_HASH_HALF_MD4) && | ||
1347 | (root->hash_version != EXT2_HASH_TEA) && | ||
1348 | fix_problem(ctx, PR_1_HTREE_HASHV, pctx)) | ||
1349 | return 1; | ||
1350 | |||
1351 | if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) && | ||
1352 | fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx)) | ||
1353 | return 1; | ||
1354 | |||
1355 | pctx->num = root->indirect_levels; | ||
1356 | if ((root->indirect_levels > 1) && | ||
1357 | fix_problem(ctx, PR_1_HTREE_DEPTH, pctx)) | ||
1358 | return 1; | ||
1359 | |||
1360 | return 0; | ||
1361 | } | ||
1362 | |||
1363 | /* | ||
1364 | * This subroutine is called on each inode to account for all of the | ||
1365 | * blocks used by that inode. | ||
1366 | */ | ||
1367 | static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, | ||
1368 | char *block_buf) | ||
1369 | { | ||
1370 | ext2_filsys fs = ctx->fs; | ||
1371 | struct process_block_struct pb; | ||
1372 | ext2_ino_t ino = pctx->ino; | ||
1373 | struct ext2_inode *inode = pctx->inode; | ||
1374 | int bad_size = 0; | ||
1375 | int dirty_inode = 0; | ||
1376 | __u64 size; | ||
1377 | |||
1378 | pb.ino = ino; | ||
1379 | pb.num_blocks = 0; | ||
1380 | pb.last_block = -1; | ||
1381 | pb.num_illegal_blocks = 0; | ||
1382 | pb.suppress = 0; pb.clear = 0; | ||
1383 | pb.fragmented = 0; | ||
1384 | pb.compressed = 0; | ||
1385 | pb.previous_block = 0; | ||
1386 | pb.is_dir = LINUX_S_ISDIR(inode->i_mode); | ||
1387 | pb.is_reg = LINUX_S_ISREG(inode->i_mode); | ||
1388 | pb.max_blocks = 1 << (31 - fs->super->s_log_block_size); | ||
1389 | pb.inode = inode; | ||
1390 | pb.pctx = pctx; | ||
1391 | pb.ctx = ctx; | ||
1392 | pctx->ino = ino; | ||
1393 | pctx->errcode = 0; | ||
1394 | |||
1395 | if (inode->i_flags & EXT2_COMPRBLK_FL) { | ||
1396 | if (fs->super->s_feature_incompat & | ||
1397 | EXT2_FEATURE_INCOMPAT_COMPRESSION) | ||
1398 | pb.compressed = 1; | ||
1399 | else { | ||
1400 | if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) { | ||
1401 | inode->i_flags &= ~EXT2_COMPRBLK_FL; | ||
1402 | dirty_inode++; | ||
1403 | } | ||
1404 | } | ||
1405 | } | ||
1406 | |||
1407 | if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf)) | ||
1408 | pb.num_blocks++; | ||
1409 | |||
1410 | if (ext2fs_inode_has_valid_blocks(inode)) | ||
1411 | pctx->errcode = ext2fs_block_iterate2(fs, ino, | ||
1412 | pb.is_dir ? BLOCK_FLAG_HOLE : 0, | ||
1413 | block_buf, process_block, &pb); | ||
1414 | end_problem_latch(ctx, PR_LATCH_BLOCK); | ||
1415 | end_problem_latch(ctx, PR_LATCH_TOOBIG); | ||
1416 | if (ctx->flags & E2F_FLAG_SIGNAL_MASK) | ||
1417 | goto out; | ||
1418 | if (pctx->errcode) | ||
1419 | fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx); | ||
1420 | |||
1421 | if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group) | ||
1422 | ctx->fs_fragmented++; | ||
1423 | |||
1424 | if (pb.clear) { | ||
1425 | inode->i_links_count = 0; | ||
1426 | ext2fs_icount_store(ctx->inode_link_info, ino, 0); | ||
1427 | inode->i_dtime = time(0); | ||
1428 | dirty_inode++; | ||
1429 | ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino); | ||
1430 | ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino); | ||
1431 | ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino); | ||
1432 | /* | ||
1433 | * The inode was probably partially accounted for | ||
1434 | * before processing was aborted, so we need to | ||
1435 | * restart the pass 1 scan. | ||
1436 | */ | ||
1437 | ctx->flags |= E2F_FLAG_RESTART; | ||
1438 | goto out; | ||
1439 | } | ||
1440 | |||
1441 | if (inode->i_flags & EXT2_INDEX_FL) { | ||
1442 | if (handle_htree(ctx, pctx, ino, inode, block_buf)) { | ||
1443 | inode->i_flags &= ~EXT2_INDEX_FL; | ||
1444 | dirty_inode++; | ||
1445 | } else { | ||
1446 | #ifdef ENABLE_HTREE | ||
1447 | e2fsck_add_dx_dir(ctx, ino, pb.last_block+1); | ||
1448 | #endif | ||
1449 | } | ||
1450 | } | ||
1451 | if (ctx->dirs_to_hash && pb.is_dir && | ||
1452 | !(inode->i_flags & EXT2_INDEX_FL) && | ||
1453 | ((inode->i_size / fs->blocksize) >= 3)) | ||
1454 | ext2fs_u32_list_add(ctx->dirs_to_hash, ino); | ||
1455 | |||
1456 | if (!pb.num_blocks && pb.is_dir) { | ||
1457 | if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) { | ||
1458 | inode->i_links_count = 0; | ||
1459 | ext2fs_icount_store(ctx->inode_link_info, ino, 0); | ||
1460 | inode->i_dtime = time(0); | ||
1461 | dirty_inode++; | ||
1462 | ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino); | ||
1463 | ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino); | ||
1464 | ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino); | ||
1465 | ctx->fs_directory_count--; | ||
1466 | goto out; | ||
1467 | } | ||
1468 | } | ||
1469 | |||
1470 | pb.num_blocks *= (fs->blocksize / 512); | ||
1471 | #if 0 | ||
1472 | printf("inode %u, i_size = %lu, last_block = %lld, i_blocks=%lu, num_blocks = %lu\n", | ||
1473 | ino, inode->i_size, pb.last_block, inode->i_blocks, | ||
1474 | pb.num_blocks); | ||
1475 | #endif | ||
1476 | if (pb.is_dir) { | ||
1477 | int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super); | ||
1478 | if (nblock > (pb.last_block + 1)) | ||
1479 | bad_size = 1; | ||
1480 | else if (nblock < (pb.last_block + 1)) { | ||
1481 | if (((pb.last_block + 1) - nblock) > | ||
1482 | fs->super->s_prealloc_dir_blocks) | ||
1483 | bad_size = 2; | ||
1484 | } | ||
1485 | } else { | ||
1486 | size = EXT2_I_SIZE(inode); | ||
1487 | if ((pb.last_block >= 0) && | ||
1488 | (size < (__u64) pb.last_block * fs->blocksize)) | ||
1489 | bad_size = 3; | ||
1490 | else if (size > ext2_max_sizes[fs->super->s_log_block_size]) | ||
1491 | bad_size = 4; | ||
1492 | } | ||
1493 | /* i_size for symlinks is checked elsewhere */ | ||
1494 | if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) { | ||
1495 | pctx->num = (pb.last_block+1) * fs->blocksize; | ||
1496 | if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) { | ||
1497 | inode->i_size = pctx->num; | ||
1498 | if (!LINUX_S_ISDIR(inode->i_mode)) | ||
1499 | inode->i_size_high = pctx->num >> 32; | ||
1500 | dirty_inode++; | ||
1501 | } | ||
1502 | pctx->num = 0; | ||
1503 | } | ||
1504 | if (LINUX_S_ISREG(inode->i_mode) && | ||
1505 | (inode->i_size_high || inode->i_size & 0x80000000UL)) | ||
1506 | ctx->large_files++; | ||
1507 | if (pb.num_blocks != inode->i_blocks) { | ||
1508 | pctx->num = pb.num_blocks; | ||
1509 | if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) { | ||
1510 | inode->i_blocks = pb.num_blocks; | ||
1511 | dirty_inode++; | ||
1512 | } | ||
1513 | pctx->num = 0; | ||
1514 | } | ||
1515 | out: | ||
1516 | if (dirty_inode) | ||
1517 | e2fsck_write_inode(ctx, ino, inode, "check_blocks"); | ||
1518 | } | ||
1519 | |||
1520 | #if 0 | ||
1521 | /* | ||
1522 | * Helper function called by process block when an illegal block is | ||
1523 | * found. It returns a description about why the block is illegal | ||
1524 | */ | ||
1525 | static char *describe_illegal_block(ext2_filsys fs, blk_t block) | ||
1526 | { | ||
1527 | blk_t super; | ||
1528 | int i; | ||
1529 | static char problem[80]; | ||
1530 | |||
1531 | super = fs->super->s_first_data_block; | ||
1532 | strcpy(problem, "PROGRAMMING ERROR: Unknown reason for illegal block"); | ||
1533 | if (block < super) { | ||
1534 | sprintf(problem, "< FIRSTBLOCK (%u)", super); | ||
1535 | return(problem); | ||
1536 | } else if (block >= fs->super->s_blocks_count) { | ||
1537 | sprintf(problem, "> BLOCKS (%u)", fs->super->s_blocks_count); | ||
1538 | return(problem); | ||
1539 | } | ||
1540 | for (i = 0; i < fs->group_desc_count; i++) { | ||
1541 | if (block == super) { | ||
1542 | sprintf(problem, "is the superblock in group %d", i); | ||
1543 | break; | ||
1544 | } | ||
1545 | if (block > super && | ||
1546 | block <= (super + fs->desc_blocks)) { | ||
1547 | sprintf(problem, "is in the group descriptors " | ||
1548 | "of group %d", i); | ||
1549 | break; | ||
1550 | } | ||
1551 | if (block == fs->group_desc[i].bg_block_bitmap) { | ||
1552 | sprintf(problem, "is the block bitmap of group %d", i); | ||
1553 | break; | ||
1554 | } | ||
1555 | if (block == fs->group_desc[i].bg_inode_bitmap) { | ||
1556 | sprintf(problem, "is the inode bitmap of group %d", i); | ||
1557 | break; | ||
1558 | } | ||
1559 | if (block >= fs->group_desc[i].bg_inode_table && | ||
1560 | (block < fs->group_desc[i].bg_inode_table | ||
1561 | + fs->inode_blocks_per_group)) { | ||
1562 | sprintf(problem, "is in the inode table of group %d", | ||
1563 | i); | ||
1564 | break; | ||
1565 | } | ||
1566 | super += fs->super->s_blocks_per_group; | ||
1567 | } | ||
1568 | return(problem); | ||
1569 | } | ||
1570 | #endif | ||
1571 | |||
1572 | /* | ||
1573 | * This is a helper function for check_blocks(). | ||
1574 | */ | ||
1575 | static int process_block(ext2_filsys fs, | ||
1576 | blk_t *block_nr, | ||
1577 | e2_blkcnt_t blockcnt, | ||
1578 | blk_t ref_block EXT2FS_ATTR((unused)), | ||
1579 | int ref_offset EXT2FS_ATTR((unused)), | ||
1580 | void *priv_data) | ||
1581 | { | ||
1582 | struct process_block_struct *p; | ||
1583 | struct problem_context *pctx; | ||
1584 | blk_t blk = *block_nr; | ||
1585 | int ret_code = 0; | ||
1586 | int problem = 0; | ||
1587 | e2fsck_t ctx; | ||
1588 | |||
1589 | p = (struct process_block_struct *) priv_data; | ||
1590 | pctx = p->pctx; | ||
1591 | ctx = p->ctx; | ||
1592 | |||
1593 | if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) { | ||
1594 | /* todo: Check that the comprblk_fl is high, that the | ||
1595 | blkaddr pattern looks right (all non-holes up to | ||
1596 | first EXT2FS_COMPRESSED_BLKADDR, then all | ||
1597 | EXT2FS_COMPRESSED_BLKADDR up to end of cluster), | ||
1598 | that the feature_incompat bit is high, and that the | ||
1599 | inode is a regular file. If we're doing a "full | ||
1600 | check" (a concept introduced to e2fsck by e2compr, | ||
1601 | meaning that we look at data blocks as well as | ||
1602 | metadata) then call some library routine that | ||
1603 | checks the compressed data. I'll have to think | ||
1604 | about this, because one particularly important | ||
1605 | problem to be able to fix is to recalculate the | ||
1606 | cluster size if necessary. I think that perhaps | ||
1607 | we'd better do most/all e2compr-specific checks | ||
1608 | separately, after the non-e2compr checks. If not | ||
1609 | doing a full check, it may be useful to test that | ||
1610 | the personality is linux; e.g. if it isn't then | ||
1611 | perhaps this really is just an illegal block. */ | ||
1612 | return 0; | ||
1613 | } | ||
1614 | |||
1615 | if (blk == 0) { | ||
1616 | if (p->is_dir == 0) { | ||
1617 | /* | ||
1618 | * Should never happen, since only directories | ||
1619 | * get called with BLOCK_FLAG_HOLE | ||
1620 | */ | ||
1621 | #if DEBUG_E2FSCK | ||
1622 | printf("process_block() called with blk == 0, " | ||
1623 | "blockcnt=%d, inode %lu???\n", | ||
1624 | blockcnt, p->ino); | ||
1625 | #endif | ||
1626 | return 0; | ||
1627 | } | ||
1628 | if (blockcnt < 0) | ||
1629 | return 0; | ||
1630 | if (blockcnt * fs->blocksize < p->inode->i_size) { | ||
1631 | #if 0 | ||
1632 | printf("Missing block (#%d) in directory inode %lu!\n", | ||
1633 | blockcnt, p->ino); | ||
1634 | #endif | ||
1635 | goto mark_dir; | ||
1636 | } | ||
1637 | return 0; | ||
1638 | } | ||
1639 | |||
1640 | #if 0 | ||
1641 | printf("Process_block, inode %lu, block %u, #%d\n", p->ino, blk, | ||
1642 | blockcnt); | ||
1643 | #endif | ||
1644 | |||
1645 | /* | ||
1646 | * Simplistic fragmentation check. We merely require that the | ||
1647 | * file be contiguous. (Which can never be true for really | ||
1648 | * big files that are greater than a block group.) | ||
1649 | */ | ||
1650 | if (!HOLE_BLKADDR(p->previous_block)) { | ||
1651 | if (p->previous_block+1 != blk) | ||
1652 | p->fragmented = 1; | ||
1653 | } | ||
1654 | p->previous_block = blk; | ||
1655 | |||
1656 | if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size))) | ||
1657 | problem = PR_1_TOOBIG_DIR; | ||
1658 | if (p->is_reg && p->num_blocks+1 >= p->max_blocks) | ||
1659 | problem = PR_1_TOOBIG_REG; | ||
1660 | if (!p->is_dir && !p->is_reg && blockcnt > 0) | ||
1661 | problem = PR_1_TOOBIG_SYMLINK; | ||
1662 | |||
1663 | if (blk < fs->super->s_first_data_block || | ||
1664 | blk >= fs->super->s_blocks_count) | ||
1665 | problem = PR_1_ILLEGAL_BLOCK_NUM; | ||
1666 | |||
1667 | if (problem) { | ||
1668 | p->num_illegal_blocks++; | ||
1669 | if (!p->suppress && (p->num_illegal_blocks % 12) == 0) { | ||
1670 | if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) { | ||
1671 | p->clear = 1; | ||
1672 | return BLOCK_ABORT; | ||
1673 | } | ||
1674 | if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) { | ||
1675 | p->suppress = 1; | ||
1676 | set_latch_flags(PR_LATCH_BLOCK, | ||
1677 | PRL_SUPPRESS, 0); | ||
1678 | } | ||
1679 | } | ||
1680 | pctx->blk = blk; | ||
1681 | pctx->blkcount = blockcnt; | ||
1682 | if (fix_problem(ctx, problem, pctx)) { | ||
1683 | blk = *block_nr = 0; | ||
1684 | ret_code = BLOCK_CHANGED; | ||
1685 | goto mark_dir; | ||
1686 | } else | ||
1687 | return 0; | ||
1688 | } | ||
1689 | |||
1690 | if (p->ino == EXT2_RESIZE_INO) { | ||
1691 | /* | ||
1692 | * The resize inode has already be sanity checked | ||
1693 | * during pass #0 (the superblock checks). All we | ||
1694 | * have to do is mark the double indirect block as | ||
1695 | * being in use; all of the other blocks are handled | ||
1696 | * by mark_table_blocks()). | ||
1697 | */ | ||
1698 | if (blockcnt == BLOCK_COUNT_DIND) | ||
1699 | mark_block_used(ctx, blk); | ||
1700 | } else | ||
1701 | mark_block_used(ctx, blk); | ||
1702 | p->num_blocks++; | ||
1703 | if (blockcnt >= 0) | ||
1704 | p->last_block = blockcnt; | ||
1705 | mark_dir: | ||
1706 | if (p->is_dir && (blockcnt >= 0)) { | ||
1707 | pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino, | ||
1708 | blk, blockcnt); | ||
1709 | if (pctx->errcode) { | ||
1710 | pctx->blk = blk; | ||
1711 | pctx->num = blockcnt; | ||
1712 | fix_problem(ctx, PR_1_ADD_DBLOCK, pctx); | ||
1713 | /* Should never get here */ | ||
1714 | ctx->flags |= E2F_FLAG_ABORT; | ||
1715 | return BLOCK_ABORT; | ||
1716 | } | ||
1717 | } | ||
1718 | return ret_code; | ||
1719 | } | ||
1720 | |||
1721 | static int process_bad_block(ext2_filsys fs, | ||
1722 | blk_t *block_nr, | ||
1723 | e2_blkcnt_t blockcnt, | ||
1724 | blk_t ref_block EXT2FS_ATTR((unused)), | ||
1725 | int ref_offset EXT2FS_ATTR((unused)), | ||
1726 | void *priv_data) | ||
1727 | { | ||
1728 | struct process_block_struct *p; | ||
1729 | blk_t blk = *block_nr; | ||
1730 | blk_t first_block; | ||
1731 | dgrp_t i; | ||
1732 | struct problem_context *pctx; | ||
1733 | e2fsck_t ctx; | ||
1734 | |||
1735 | /* | ||
1736 | * Note: This function processes blocks for the bad blocks | ||
1737 | * inode, which is never compressed. So we don't use HOLE_BLKADDR(). | ||
1738 | */ | ||
1739 | |||
1740 | if (!blk) | ||
1741 | return 0; | ||
1742 | |||
1743 | p = (struct process_block_struct *) priv_data; | ||
1744 | ctx = p->ctx; | ||
1745 | pctx = p->pctx; | ||
1746 | |||
1747 | pctx->ino = EXT2_BAD_INO; | ||
1748 | pctx->blk = blk; | ||
1749 | pctx->blkcount = blockcnt; | ||
1750 | |||
1751 | if ((blk < fs->super->s_first_data_block) || | ||
1752 | (blk >= fs->super->s_blocks_count)) { | ||
1753 | if (fix_problem(ctx, PR_1_BB_ILLEGAL_BLOCK_NUM, pctx)) { | ||
1754 | *block_nr = 0; | ||
1755 | return BLOCK_CHANGED; | ||
1756 | } else | ||
1757 | return 0; | ||
1758 | } | ||
1759 | |||
1760 | if (blockcnt < 0) { | ||
1761 | if (ext2fs_test_block_bitmap(p->fs_meta_blocks, blk)) { | ||
1762 | p->bbcheck = 1; | ||
1763 | if (fix_problem(ctx, PR_1_BB_FS_BLOCK, pctx)) { | ||
1764 | *block_nr = 0; | ||
1765 | return BLOCK_CHANGED; | ||
1766 | } | ||
1767 | } else if (ext2fs_test_block_bitmap(ctx->block_found_map, | ||
1768 | blk)) { | ||
1769 | p->bbcheck = 1; | ||
1770 | if (fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK, | ||
1771 | pctx)) { | ||
1772 | *block_nr = 0; | ||
1773 | return BLOCK_CHANGED; | ||
1774 | } | ||
1775 | if (ctx->flags & E2F_FLAG_SIGNAL_MASK) | ||
1776 | return BLOCK_ABORT; | ||
1777 | } else | ||
1778 | mark_block_used(ctx, blk); | ||
1779 | return 0; | ||
1780 | } | ||
1781 | #if 0 | ||
1782 | printf ("DEBUG: Marking %u as bad.\n", blk); | ||
1783 | #endif | ||
1784 | ctx->fs_badblocks_count++; | ||
1785 | /* | ||
1786 | * If the block is not used, then mark it as used and return. | ||
1787 | * If it is already marked as found, this must mean that | ||
1788 | * there's an overlap between the filesystem table blocks | ||
1789 | * (bitmaps and inode table) and the bad block list. | ||
1790 | */ | ||
1791 | if (!ext2fs_test_block_bitmap(ctx->block_found_map, blk)) { | ||
1792 | ext2fs_mark_block_bitmap(ctx->block_found_map, blk); | ||
1793 | return 0; | ||
1794 | } | ||
1795 | /* | ||
1796 | * Try to find the where the filesystem block was used... | ||
1797 | */ | ||
1798 | first_block = fs->super->s_first_data_block; | ||
1799 | |||
1800 | for (i = 0; i < fs->group_desc_count; i++ ) { | ||
1801 | pctx->group = i; | ||
1802 | pctx->blk = blk; | ||
1803 | if (!ext2fs_bg_has_super(fs, i)) | ||
1804 | goto skip_super; | ||
1805 | if (blk == first_block) { | ||
1806 | if (i == 0) { | ||
1807 | if (fix_problem(ctx, | ||
1808 | PR_1_BAD_PRIMARY_SUPERBLOCK, | ||
1809 | pctx)) { | ||
1810 | *block_nr = 0; | ||
1811 | return BLOCK_CHANGED; | ||
1812 | } | ||
1813 | return 0; | ||
1814 | } | ||
1815 | fix_problem(ctx, PR_1_BAD_SUPERBLOCK, pctx); | ||
1816 | return 0; | ||
1817 | } | ||
1818 | if ((blk > first_block) && | ||
1819 | (blk <= first_block + fs->desc_blocks)) { | ||
1820 | if (i == 0) { | ||
1821 | pctx->blk = *block_nr; | ||
1822 | if (fix_problem(ctx, | ||
1823 | PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR, pctx)) { | ||
1824 | *block_nr = 0; | ||
1825 | return BLOCK_CHANGED; | ||
1826 | } | ||
1827 | return 0; | ||
1828 | } | ||
1829 | fix_problem(ctx, PR_1_BAD_GROUP_DESCRIPTORS, pctx); | ||
1830 | return 0; | ||
1831 | } | ||
1832 | skip_super: | ||
1833 | if (blk == fs->group_desc[i].bg_block_bitmap) { | ||
1834 | if (fix_problem(ctx, PR_1_BB_BAD_BLOCK, pctx)) { | ||
1835 | ctx->invalid_block_bitmap_flag[i]++; | ||
1836 | ctx->invalid_bitmaps++; | ||
1837 | } | ||
1838 | return 0; | ||
1839 | } | ||
1840 | if (blk == fs->group_desc[i].bg_inode_bitmap) { | ||
1841 | if (fix_problem(ctx, PR_1_IB_BAD_BLOCK, pctx)) { | ||
1842 | ctx->invalid_inode_bitmap_flag[i]++; | ||
1843 | ctx->invalid_bitmaps++; | ||
1844 | } | ||
1845 | return 0; | ||
1846 | } | ||
1847 | if ((blk >= fs->group_desc[i].bg_inode_table) && | ||
1848 | (blk < (fs->group_desc[i].bg_inode_table + | ||
1849 | fs->inode_blocks_per_group))) { | ||
1850 | /* | ||
1851 | * If there are bad blocks in the inode table, | ||
1852 | * the inode scan code will try to do | ||
1853 | * something reasonable automatically. | ||
1854 | */ | ||
1855 | return 0; | ||
1856 | } | ||
1857 | first_block += fs->super->s_blocks_per_group; | ||
1858 | } | ||
1859 | /* | ||
1860 | * If we've gotten to this point, then the only | ||
1861 | * possibility is that the bad block inode meta data | ||
1862 | * is using a bad block. | ||
1863 | */ | ||
1864 | if ((blk == p->inode->i_block[EXT2_IND_BLOCK]) || | ||
1865 | (blk == p->inode->i_block[EXT2_DIND_BLOCK]) || | ||
1866 | (blk == p->inode->i_block[EXT2_TIND_BLOCK])) { | ||
1867 | p->bbcheck = 1; | ||
1868 | if (fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK, pctx)) { | ||
1869 | *block_nr = 0; | ||
1870 | return BLOCK_CHANGED; | ||
1871 | } | ||
1872 | if (ctx->flags & E2F_FLAG_SIGNAL_MASK) | ||
1873 | return BLOCK_ABORT; | ||
1874 | return 0; | ||
1875 | } | ||
1876 | |||
1877 | pctx->group = -1; | ||
1878 | |||
1879 | /* Warn user that the block wasn't claimed */ | ||
1880 | fix_problem(ctx, PR_1_PROGERR_CLAIMED_BLOCK, pctx); | ||
1881 | |||
1882 | return 0; | ||
1883 | } | ||
1884 | |||
1885 | static void new_table_block(e2fsck_t ctx, blk_t first_block, int group, | ||
1886 | const char *name, int num, blk_t *new_block) | ||
1887 | { | ||
1888 | ext2_filsys fs = ctx->fs; | ||
1889 | blk_t old_block = *new_block; | ||
1890 | int i; | ||
1891 | char *buf; | ||
1892 | struct problem_context pctx; | ||
1893 | |||
1894 | clear_problem_context(&pctx); | ||
1895 | |||
1896 | pctx.group = group; | ||
1897 | pctx.blk = old_block; | ||
1898 | pctx.str = name; | ||
1899 | |||
1900 | pctx.errcode = ext2fs_get_free_blocks(fs, first_block, | ||
1901 | first_block + fs->super->s_blocks_per_group, | ||
1902 | num, ctx->block_found_map, new_block); | ||
1903 | if (pctx.errcode) { | ||
1904 | pctx.num = num; | ||
1905 | fix_problem(ctx, PR_1_RELOC_BLOCK_ALLOCATE, &pctx); | ||
1906 | ext2fs_unmark_valid(fs); | ||
1907 | return; | ||
1908 | } | ||
1909 | pctx.errcode = ext2fs_get_mem(fs->blocksize, &buf); | ||
1910 | if (pctx.errcode) { | ||
1911 | fix_problem(ctx, PR_1_RELOC_MEMORY_ALLOCATE, &pctx); | ||
1912 | ext2fs_unmark_valid(fs); | ||
1913 | return; | ||
1914 | } | ||
1915 | ext2fs_mark_super_dirty(fs); | ||
1916 | fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; | ||
1917 | pctx.blk2 = *new_block; | ||
1918 | fix_problem(ctx, (old_block ? PR_1_RELOC_FROM_TO : | ||
1919 | PR_1_RELOC_TO), &pctx); | ||
1920 | pctx.blk2 = 0; | ||
1921 | for (i = 0; i < num; i++) { | ||
1922 | pctx.blk = i; | ||
1923 | ext2fs_mark_block_bitmap(ctx->block_found_map, (*new_block)+i); | ||
1924 | if (old_block) { | ||
1925 | pctx.errcode = io_channel_read_blk(fs->io, | ||
1926 | old_block + i, 1, buf); | ||
1927 | if (pctx.errcode) | ||
1928 | fix_problem(ctx, PR_1_RELOC_READ_ERR, &pctx); | ||
1929 | } else | ||
1930 | memset(buf, 0, fs->blocksize); | ||
1931 | |||
1932 | pctx.blk = (*new_block) + i; | ||
1933 | pctx.errcode = io_channel_write_blk(fs->io, pctx.blk, | ||
1934 | 1, buf); | ||
1935 | if (pctx.errcode) | ||
1936 | fix_problem(ctx, PR_1_RELOC_WRITE_ERR, &pctx); | ||
1937 | } | ||
1938 | ext2fs_free_mem(&buf); | ||
1939 | } | ||
1940 | |||
1941 | /* | ||
1942 | * This routine gets called at the end of pass 1 if bad blocks are | ||
1943 | * detected in the superblock, group descriptors, inode_bitmaps, or | ||
1944 | * block bitmaps. At this point, all of the blocks have been mapped | ||
1945 | * out, so we can try to allocate new block(s) to replace the bad | ||
1946 | * blocks. | ||
1947 | */ | ||
1948 | static void handle_fs_bad_blocks(e2fsck_t ctx) | ||
1949 | { | ||
1950 | ext2_filsys fs = ctx->fs; | ||
1951 | dgrp_t i; | ||
1952 | int first_block = fs->super->s_first_data_block; | ||
1953 | |||
1954 | for (i = 0; i < fs->group_desc_count; i++) { | ||
1955 | if (ctx->invalid_block_bitmap_flag[i]) { | ||
1956 | new_table_block(ctx, first_block, i, _("block bitmap"), | ||
1957 | 1, &fs->group_desc[i].bg_block_bitmap); | ||
1958 | } | ||
1959 | if (ctx->invalid_inode_bitmap_flag[i]) { | ||
1960 | new_table_block(ctx, first_block, i, _("inode bitmap"), | ||
1961 | 1, &fs->group_desc[i].bg_inode_bitmap); | ||
1962 | } | ||
1963 | if (ctx->invalid_inode_table_flag[i]) { | ||
1964 | new_table_block(ctx, first_block, i, _("inode table"), | ||
1965 | fs->inode_blocks_per_group, | ||
1966 | &fs->group_desc[i].bg_inode_table); | ||
1967 | ctx->flags |= E2F_FLAG_RESTART; | ||
1968 | } | ||
1969 | first_block += fs->super->s_blocks_per_group; | ||
1970 | } | ||
1971 | ctx->invalid_bitmaps = 0; | ||
1972 | } | ||
1973 | |||
1974 | /* | ||
1975 | * This routine marks all blocks which are used by the superblock, | ||
1976 | * group descriptors, inode bitmaps, and block bitmaps. | ||
1977 | */ | ||
1978 | static void mark_table_blocks(e2fsck_t ctx) | ||
1979 | { | ||
1980 | ext2_filsys fs = ctx->fs; | ||
1981 | blk_t block, b; | ||
1982 | dgrp_t i; | ||
1983 | int j; | ||
1984 | struct problem_context pctx; | ||
1985 | |||
1986 | clear_problem_context(&pctx); | ||
1987 | |||
1988 | block = fs->super->s_first_data_block; | ||
1989 | for (i = 0; i < fs->group_desc_count; i++) { | ||
1990 | pctx.group = i; | ||
1991 | |||
1992 | ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map); | ||
1993 | |||
1994 | /* | ||
1995 | * Mark the blocks used for the inode table | ||
1996 | */ | ||
1997 | if (fs->group_desc[i].bg_inode_table) { | ||
1998 | for (j = 0, b = fs->group_desc[i].bg_inode_table; | ||
1999 | j < fs->inode_blocks_per_group; | ||
2000 | j++, b++) { | ||
2001 | if (ext2fs_test_block_bitmap(ctx->block_found_map, | ||
2002 | b)) { | ||
2003 | pctx.blk = b; | ||
2004 | if (fix_problem(ctx, | ||
2005 | PR_1_ITABLE_CONFLICT, &pctx)) { | ||
2006 | ctx->invalid_inode_table_flag[i]++; | ||
2007 | ctx->invalid_bitmaps++; | ||
2008 | } | ||
2009 | } else { | ||
2010 | ext2fs_mark_block_bitmap(ctx->block_found_map, | ||
2011 | b); | ||
2012 | } | ||
2013 | } | ||
2014 | } | ||
2015 | |||
2016 | /* | ||
2017 | * Mark block used for the block bitmap | ||
2018 | */ | ||
2019 | if (fs->group_desc[i].bg_block_bitmap) { | ||
2020 | if (ext2fs_test_block_bitmap(ctx->block_found_map, | ||
2021 | fs->group_desc[i].bg_block_bitmap)) { | ||
2022 | pctx.blk = fs->group_desc[i].bg_block_bitmap; | ||
2023 | if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) { | ||
2024 | ctx->invalid_block_bitmap_flag[i]++; | ||
2025 | ctx->invalid_bitmaps++; | ||
2026 | } | ||
2027 | } else { | ||
2028 | ext2fs_mark_block_bitmap(ctx->block_found_map, | ||
2029 | fs->group_desc[i].bg_block_bitmap); | ||
2030 | } | ||
2031 | |||
2032 | } | ||
2033 | /* | ||
2034 | * Mark block used for the inode bitmap | ||
2035 | */ | ||
2036 | if (fs->group_desc[i].bg_inode_bitmap) { | ||
2037 | if (ext2fs_test_block_bitmap(ctx->block_found_map, | ||
2038 | fs->group_desc[i].bg_inode_bitmap)) { | ||
2039 | pctx.blk = fs->group_desc[i].bg_inode_bitmap; | ||
2040 | if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) { | ||
2041 | ctx->invalid_inode_bitmap_flag[i]++; | ||
2042 | ctx->invalid_bitmaps++; | ||
2043 | } | ||
2044 | } else { | ||
2045 | ext2fs_mark_block_bitmap(ctx->block_found_map, | ||
2046 | fs->group_desc[i].bg_inode_bitmap); | ||
2047 | } | ||
2048 | } | ||
2049 | block += fs->super->s_blocks_per_group; | ||
2050 | } | ||
2051 | } | ||
2052 | |||
2053 | /* | ||
2054 | * Thes subroutines short circuits ext2fs_get_blocks and | ||
2055 | * ext2fs_check_directory; we use them since we already have the inode | ||
2056 | * structure, so there's no point in letting the ext2fs library read | ||
2057 | * the inode again. | ||
2058 | */ | ||
2059 | static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino, | ||
2060 | blk_t *blocks) | ||
2061 | { | ||
2062 | e2fsck_t ctx = (e2fsck_t) fs->priv_data; | ||
2063 | int i; | ||
2064 | |||
2065 | if ((ino != ctx->stashed_ino) || !ctx->stashed_inode) | ||
2066 | return EXT2_ET_CALLBACK_NOTHANDLED; | ||
2067 | |||
2068 | for (i=0; i < EXT2_N_BLOCKS; i++) | ||
2069 | blocks[i] = ctx->stashed_inode->i_block[i]; | ||
2070 | return 0; | ||
2071 | } | ||
2072 | |||
2073 | static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino, | ||
2074 | struct ext2_inode *inode) | ||
2075 | { | ||
2076 | e2fsck_t ctx = (e2fsck_t) fs->priv_data; | ||
2077 | |||
2078 | if ((ino != ctx->stashed_ino) || !ctx->stashed_inode) | ||
2079 | return EXT2_ET_CALLBACK_NOTHANDLED; | ||
2080 | *inode = *ctx->stashed_inode; | ||
2081 | return 0; | ||
2082 | } | ||
2083 | |||
2084 | static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino, | ||
2085 | struct ext2_inode *inode) | ||
2086 | { | ||
2087 | e2fsck_t ctx = (e2fsck_t) fs->priv_data; | ||
2088 | |||
2089 | if ((ino == ctx->stashed_ino) && ctx->stashed_inode) | ||
2090 | *ctx->stashed_inode = *inode; | ||
2091 | return EXT2_ET_CALLBACK_NOTHANDLED; | ||
2092 | } | ||
2093 | |||
2094 | static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino) | ||
2095 | { | ||
2096 | e2fsck_t ctx = (e2fsck_t) fs->priv_data; | ||
2097 | |||
2098 | if ((ino != ctx->stashed_ino) || !ctx->stashed_inode) | ||
2099 | return EXT2_ET_CALLBACK_NOTHANDLED; | ||
2100 | |||
2101 | if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode)) | ||
2102 | return EXT2_ET_NO_DIRECTORY; | ||
2103 | return 0; | ||
2104 | } | ||
2105 | |||
2106 | void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool) | ||
2107 | { | ||
2108 | ext2_filsys fs = ctx->fs; | ||
2109 | |||
2110 | if (bool) { | ||
2111 | fs->get_blocks = pass1_get_blocks; | ||
2112 | fs->check_directory = pass1_check_directory; | ||
2113 | fs->read_inode = pass1_read_inode; | ||
2114 | fs->write_inode = pass1_write_inode; | ||
2115 | ctx->stashed_ino = 0; | ||
2116 | } else { | ||
2117 | fs->get_blocks = 0; | ||
2118 | fs->check_directory = 0; | ||
2119 | fs->read_inode = 0; | ||
2120 | fs->write_inode = 0; | ||
2121 | } | ||
2122 | } | ||