blob: 99a88b0912c0773e43a217336eee38cc27cea602 [file] [log] [blame]
Theodore Ts'o3839e651997-04-26 13:21:57 +00001/*
2 * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
3 *
Theodore Ts'o21c84b71997-04-29 16:15:03 +00004 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
5 *
6 * %Begin-Header%
7 * This file may be redistributed under the terms of the GNU Public
8 * License.
9 * %End-Header%
Theodore Ts'o3839e651997-04-26 13:21:57 +000010 *
11 * 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)
Theodore Ts'oaa4115a1999-10-21 19:33:18 +000022 * - A bitmap of which inodes are regular files. (inode_reg_map)
Theodore Ts'o3839e651997-04-26 13:21:57 +000023 * - A bitmap of which inodes have bad fields. (inode_bad_map)
Theodore Ts'o21c84b71997-04-29 16:15:03 +000024 * - A bitmap of which inodes are in bad blocks. (inode_bb_map)
Theodore Ts'oaa4115a1999-10-21 19:33:18 +000025 * - A bitmap of which inodes are imagic inodes. (inode_imagic_map)
Theodore Ts'o3839e651997-04-26 13:21:57 +000026 * - 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#include <time.h>
Theodore Ts'o50e1e101997-04-26 13:58:21 +000041#ifdef HAVE_ERRNO_H
42#include <errno.h>
43#endif
Theodore Ts'o3839e651997-04-26 13:21:57 +000044
Theodore Ts'o3839e651997-04-26 13:21:57 +000045#include "e2fsck.h"
Theodore Ts'o21c84b71997-04-29 16:15:03 +000046#include "problem.h"
Theodore Ts'o3839e651997-04-26 13:21:57 +000047
Theodore Ts'o50e1e101997-04-26 13:58:21 +000048#ifdef NO_INLINE_FUNCS
49#define _INLINE_
50#else
51#define _INLINE_ inline
52#endif
53
Theodore Ts'o3839e651997-04-26 13:21:57 +000054static int process_block(ext2_filsys fs, blk_t *blocknr,
Theodore Ts'o9d1bd3d1998-06-10 20:45:22 +000055 e2_blkcnt_t blockcnt, blk_t ref_blk,
Theodore Ts'o54dc7ca1998-01-19 14:50:49 +000056 int ref_offset, void *priv_data);
Theodore Ts'o3839e651997-04-26 13:21:57 +000057static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
Theodore Ts'o9d1bd3d1998-06-10 20:45:22 +000058 e2_blkcnt_t blockcnt, blk_t ref_blk,
Theodore Ts'o54dc7ca1998-01-19 14:50:49 +000059 int ref_offset, void *priv_data);
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000060static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
Theodore Ts'o3839e651997-04-26 13:21:57 +000061 char *block_buf);
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000062static void mark_table_blocks(e2fsck_t ctx);
63static void alloc_bad_map(e2fsck_t ctx);
64static void alloc_bb_map(e2fsck_t ctx);
Theodore Ts'oaa4115a1999-10-21 19:33:18 +000065static void alloc_imagic_map(e2fsck_t ctx);
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000066static void handle_fs_bad_blocks(e2fsck_t ctx);
67static void process_inodes(e2fsck_t ctx, char *block_buf);
Theodore Ts'o4c77fe51998-04-30 17:35:59 +000068static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b);
Theodore Ts'of3db3561997-04-26 13:34:30 +000069static errcode_t scan_callback(ext2_filsys fs, ext2_inode_scan scan,
Theodore Ts'o54dc7ca1998-01-19 14:50:49 +000070 dgrp_t group, void * priv_data);
Theodore Ts'o21c84b71997-04-29 16:15:03 +000071/* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
Theodore Ts'o3839e651997-04-26 13:21:57 +000072
73struct process_block_struct {
Theodore Ts'o86c627e2001-01-11 15:12:14 +000074 ext2_ino_t ino;
Theodore Ts'o19178752000-02-11 15:55:07 +000075 int is_dir:1, clear:1, suppress:1,
76 fragmented:1, compressed:1;
Theodore Ts'o246501c1998-03-24 16:22:38 +000077 blk_t num_blocks;
Theodore Ts'o9d1bd3d1998-06-10 20:45:22 +000078 e2_blkcnt_t last_block;
Theodore Ts'o246501c1998-03-24 16:22:38 +000079 int num_illegal_blocks;
80 blk_t previous_block;
Theodore Ts'of3db3561997-04-26 13:34:30 +000081 struct ext2_inode *inode;
Theodore Ts'o21c84b71997-04-29 16:15:03 +000082 struct problem_context *pctx;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000083 e2fsck_t ctx;
Theodore Ts'o3839e651997-04-26 13:21:57 +000084};
85
86struct process_inode_block {
Theodore Ts'o86c627e2001-01-11 15:12:14 +000087 ext2_ino_t ino;
Theodore Ts'o3839e651997-04-26 13:21:57 +000088 struct ext2_inode inode;
89};
90
Theodore Ts'of8188ff1997-11-14 05:23:04 +000091struct scan_callback_struct {
92 e2fsck_t ctx;
93 char *block_buf;
94};
95
Theodore Ts'o3839e651997-04-26 13:21:57 +000096/*
Theodore Ts'o3839e651997-04-26 13:21:57 +000097 * For the inodes to process list.
98 */
99static struct process_inode_block *inodes_to_process;
100static int process_inode_count;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000101
Theodore Ts'o9d1bd3d1998-06-10 20:45:22 +0000102static __u64 ext2_max_sizes[4];
Theodore Ts'o246501c1998-03-24 16:22:38 +0000103
Theodore Ts'o3839e651997-04-26 13:21:57 +0000104/*
Theodore Ts'of3db3561997-04-26 13:34:30 +0000105 * Free all memory allocated by pass1 in preparation for restarting
106 * things.
107 */
108static void unwind_pass1(ext2_filsys fs)
109{
Theodore Ts'o08b21301997-11-03 19:42:40 +0000110 ext2fs_free_mem((void **) &inodes_to_process);
111 inodes_to_process = 0;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000112}
113
Theodore Ts'o7cf73dc1997-08-14 17:17:16 +0000114/*
115 * Check to make sure a device inode is real. Returns 1 if the device
116 * checks out, 0 if not.
Theodore Ts'o1dde43f1998-11-14 04:18:28 +0000117 *
118 * Note: this routine is now also used to check FIFO's and Sockets,
119 * since they have the same requirement; the i_block fields should be
120 * zero.
Theodore Ts'o7cf73dc1997-08-14 17:17:16 +0000121 */
122int e2fsck_pass1_check_device_inode(struct ext2_inode *inode)
123{
124 int i;
125
Theodore Ts'o7fdfabd1997-11-24 11:51:17 +0000126 /*
127 * We should be able to do the test below all the time, but
128 * because the kernel doesn't forcibly clear the device
129 * inode's additional i_block fields, there are some rare
130 * occasions when a legitimate device inode will have non-zero
131 * additional i_block fields. So for now, we only complain
132 * when the immutable flag is set, which should never happen
133 * for devices. (And that's when the problem is caused, since
134 * you can't set or clear immutable flags for devices.) Once
135 * the kernel has been fixed we can change this...
136 */
Theodore Ts'o01fbc702000-04-03 13:57:21 +0000137 if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
Theodore Ts'o7fdfabd1997-11-24 11:51:17 +0000138 for (i=4; i < EXT2_N_BLOCKS; i++)
139 if (inode->i_block[i])
140 return 0;
141 }
Theodore Ts'o7cf73dc1997-08-14 17:17:16 +0000142 return 1;
143}
144
Theodore Ts'o6fdc7a31999-11-10 13:34:40 +0000145/*
Theodore Ts'o01fbc702000-04-03 13:57:21 +0000146 * If the immutable (or append-only) flag is set on the inode, offer
147 * to clear it.
Theodore Ts'o6fdc7a31999-11-10 13:34:40 +0000148 */
149static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
150{
Theodore Ts'o01fbc702000-04-03 13:57:21 +0000151 if (!(pctx->inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)))
Theodore Ts'o6fdc7a31999-11-10 13:34:40 +0000152 return;
153
154 if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
155 return;
156
Theodore Ts'o01fbc702000-04-03 13:57:21 +0000157 pctx->inode->i_flags &= ~((EXT2_IMMUTABLE_FL | EXT2_APPEND_FL));
Theodore Ts'o6fdc7a31999-11-10 13:34:40 +0000158 e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
159}
160
Theodore Ts'od647a1e2000-05-27 14:40:09 +0000161/*
162 * If device, fifo or socket, check size is zero -- if not offer to
163 * clear it
164 */
165static void check_size(e2fsck_t ctx, struct problem_context *pctx)
166{
167 struct ext2_inode *inode = pctx->inode;
168
169 if ((LINUX_S_ISBLK(inode->i_mode) ||
170 LINUX_S_ISCHR(inode->i_mode) ||
171 LINUX_S_ISFIFO(inode->i_mode) ||
172 LINUX_S_ISSOCK(inode->i_mode)) &&
173 !inode->i_size)
174 return;
175
176 if(!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
177 return;
178
179 inode->i_size = 0;
180 e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
181}
182
Theodore Ts'o6fdc7a31999-11-10 13:34:40 +0000183
Theodore Ts'o08b21301997-11-03 19:42:40 +0000184void e2fsck_pass1(e2fsck_t ctx)
Theodore Ts'o3839e651997-04-26 13:21:57 +0000185{
Theodore Ts'o9d1bd3d1998-06-10 20:45:22 +0000186 int i;
Theodore Ts'oa9ca2012001-01-12 21:53:25 +0000187 __u64 max_sizes, max_sect_limit;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000188 ext2_filsys fs = ctx->fs;
Theodore Ts'o86c627e2001-01-11 15:12:14 +0000189 ext2_ino_t ino;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000190 struct ext2_inode inode;
191 ext2_inode_scan scan;
192 char *block_buf;
Theodore Ts'o8bf191e1997-10-20 01:38:32 +0000193#ifdef RESOURCE_TRACK
Theodore Ts'o3839e651997-04-26 13:21:57 +0000194 struct resource_track rtrack;
Theodore Ts'o8bf191e1997-10-20 01:38:32 +0000195#endif
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000196 unsigned char frag, fsize;
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000197 struct problem_context pctx;
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000198 struct scan_callback_struct scan_struct;
Theodore Ts'o5dd8f962001-01-01 15:51:50 +0000199 struct ext2_super_block *sb = ctx->fs->super;
Theodore Ts'o6fdc7a31999-11-10 13:34:40 +0000200 int imagic_fs;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000201
Theodore Ts'o8bf191e1997-10-20 01:38:32 +0000202#ifdef RESOURCE_TRACK
Theodore Ts'o3839e651997-04-26 13:21:57 +0000203 init_resource_track(&rtrack);
Theodore Ts'o8bf191e1997-10-20 01:38:32 +0000204#endif
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000205 clear_problem_context(&pctx);
206
207 if (!(ctx->options & E2F_OPT_PREEN))
208 fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000209
210#ifdef MTRACE
211 mtrace_print("Pass 1");
212#endif
213
Theodore Ts'o9d1bd3d1998-06-10 20:45:22 +0000214#define EXT2_BPP(bits) (1UL << ((bits) - 2))
215
216 for (i=0; i < 4; i++) {
217 max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(10+i);
218 max_sizes = max_sizes + EXT2_BPP(10+i) * EXT2_BPP(10+i);
219 max_sizes = (max_sizes +
220 (__u64) EXT2_BPP(10+i) * EXT2_BPP(10+i) *
221 EXT2_BPP(10+i));
222 max_sizes = (max_sizes * (1UL << (10+i))) - 1;
Theodore Ts'oa9ca2012001-01-12 21:53:25 +0000223 max_sect_limit = 512ULL * ((1LL << 32) - (1 << (i+1)));
224 if (max_sizes > max_sect_limit)
225 max_sizes = max_sect_limit;
Theodore Ts'o9d1bd3d1998-06-10 20:45:22 +0000226 ext2_max_sizes[i] = max_sizes;
227 }
228#undef EXT2_BPP
Theodore Ts'o6fdc7a31999-11-10 13:34:40 +0000229
Theodore Ts'o6fdc7a31999-11-10 13:34:40 +0000230 imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
231
Theodore Ts'o3839e651997-04-26 13:21:57 +0000232 /*
233 * Allocate bitmaps structures
234 */
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000235 pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000236 &ctx->inode_used_map);
237 if (pctx.errcode) {
238 pctx.num = 1;
239 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
Theodore Ts'o08b21301997-11-03 19:42:40 +0000240 ctx->flags |= E2F_FLAG_ABORT;
241 return;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000242 }
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000243 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
244 _("directory inode map"), &ctx->inode_dir_map);
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000245 if (pctx.errcode) {
246 pctx.num = 2;
247 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
Theodore Ts'o08b21301997-11-03 19:42:40 +0000248 ctx->flags |= E2F_FLAG_ABORT;
249 return;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000250 }
Theodore Ts'oaa4115a1999-10-21 19:33:18 +0000251 pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000252 _("regular file inode map"), &ctx->inode_reg_map);
Theodore Ts'oaa4115a1999-10-21 19:33:18 +0000253 if (pctx.errcode) {
254 pctx.num = 6;
255 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
256 ctx->flags |= E2F_FLAG_ABORT;
257 return;
258 }
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000259 pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000260 &ctx->block_found_map);
261 if (pctx.errcode) {
262 pctx.num = 1;
263 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
Theodore Ts'o08b21301997-11-03 19:42:40 +0000264 ctx->flags |= E2F_FLAG_ABORT;
265 return;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000266 }
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000267 pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
268 &ctx->inode_link_info);
269 if (pctx.errcode) {
270 fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
Theodore Ts'o08b21301997-11-03 19:42:40 +0000271 ctx->flags |= E2F_FLAG_ABORT;
272 return;
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000273 }
Theodore Ts'o54dc7ca1998-01-19 14:50:49 +0000274 inodes_to_process = (struct process_inode_block *)
275 e2fsck_allocate_memory(ctx,
276 (ctx->process_inode_size *
277 sizeof(struct process_inode_block)),
278 "array of inodes to process");
Theodore Ts'o3839e651997-04-26 13:21:57 +0000279 process_inode_count = 0;
280
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000281 pctx.errcode = ext2fs_init_dblist(fs, 0);
282 if (pctx.errcode) {
283 fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
Theodore Ts'o08b21301997-11-03 19:42:40 +0000284 ctx->flags |= E2F_FLAG_ABORT;
285 return;
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000286 }
Theodore Ts'o3839e651997-04-26 13:21:57 +0000287
Theodore Ts'o9cbfb8d2000-07-04 19:51:22 +0000288 /*
289 * If the last orphan field is set, clear it, since the pass1
290 * processing will automatically find and clear the orphans.
291 * In the future, we may want to try using the last_orphan
292 * linked list ourselves, but for now, we clear it so that the
293 * ext3 mount code won't get confused.
294 */
295 if (!(ctx->options & E2F_OPT_READONLY)) {
296 if (fs->super->s_last_orphan) {
297 fs->super->s_last_orphan = 0;
298 ext2fs_mark_super_dirty(fs);
299 }
300 }
301
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000302 mark_table_blocks(ctx);
Theodore Ts'o54dc7ca1998-01-19 14:50:49 +0000303 block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
304 "block interate buffer");
Theodore Ts'oe72a9ba1999-06-25 15:40:18 +0000305 e2fsck_use_inode_shortcuts(ctx, 1);
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000306 ehandler_operation(_("doing inode scan"));
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000307 pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
308 &scan);
309 if (pctx.errcode) {
310 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
Theodore Ts'o08b21301997-11-03 19:42:40 +0000311 ctx->flags |= E2F_FLAG_ABORT;
312 return;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000313 }
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000314 ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000315 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
316 if (pctx.errcode) {
317 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
Theodore Ts'o08b21301997-11-03 19:42:40 +0000318 ctx->flags |= E2F_FLAG_ABORT;
319 return;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000320 }
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000321 ctx->stashed_inode = &inode;
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000322 scan_struct.ctx = ctx;
323 scan_struct.block_buf = block_buf;
324 ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
325 if (ctx->progress)
Theodore Ts'oa02ce9d1998-02-24 20:22:23 +0000326 if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
327 return;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000328 while (ino) {
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000329 pctx.ino = ino;
330 pctx.inode = &inode;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000331 ctx->stashed_ino = ino;
332 if (inode.i_links_count) {
333 pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
334 ino, inode.i_links_count);
335 if (pctx.errcode) {
336 pctx.num = inode.i_links_count;
337 fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
Theodore Ts'o08b21301997-11-03 19:42:40 +0000338 ctx->flags |= E2F_FLAG_ABORT;
339 return;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000340 }
341 }
Theodore Ts'o3839e651997-04-26 13:21:57 +0000342 if (ino == EXT2_BAD_INO) {
343 struct process_block_struct pb;
344
345 pb.ino = EXT2_BAD_INO;
346 pb.num_blocks = pb.last_block = 0;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000347 pb.num_illegal_blocks = 0;
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000348 pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
Theodore Ts'o74becf31997-04-26 14:37:06 +0000349 pb.fragmented = 0;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000350 pb.inode = &inode;
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000351 pb.pctx = &pctx;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000352 pb.ctx = ctx;
353 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
354 block_buf, process_bad_block, &pb);
355 if (pctx.errcode) {
356 fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
Theodore Ts'o08b21301997-11-03 19:42:40 +0000357 ctx->flags |= E2F_FLAG_ABORT;
358 return;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000359 }
360 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000361 clear_problem_context(&pctx);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000362 goto next;
Theodore Ts'oa9ca2012001-01-12 21:53:25 +0000363 } else if (ino == EXT2_ROOT_INO) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000364 /*
365 * Make sure the root inode is a directory; if
366 * not, offer to clear it. It will be
367 * regnerated in pass #3.
368 */
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000369 if (!LINUX_S_ISDIR(inode.i_mode)) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000370 if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000371 inode.i_dtime = time(0);
372 inode.i_links_count = 0;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000373 ext2fs_icount_store(ctx->inode_link_info,
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000374 ino, 0);
Theodore Ts'o08b21301997-11-03 19:42:40 +0000375 e2fsck_write_inode(ctx, ino, &inode,
Theodore Ts'of3db3561997-04-26 13:34:30 +0000376 "pass1");
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000377 }
Theodore Ts'ob09a4b02000-10-24 21:16:09 +0000378
Theodore Ts'o3839e651997-04-26 13:21:57 +0000379 }
380 /*
381 * If dtime is set, offer to clear it. mke2fs
382 * version 0.2b created filesystems with the
383 * dtime field set for the root and lost+found
384 * directories. We won't worry about
385 * /lost+found, since that can be regenerated
386 * easily. But we will fix the root directory
387 * as a special case.
388 */
389 if (inode.i_dtime && inode.i_links_count) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000390 if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000391 inode.i_dtime = 0;
Theodore Ts'o08b21301997-11-03 19:42:40 +0000392 e2fsck_write_inode(ctx, ino, &inode,
Theodore Ts'of3db3561997-04-26 13:34:30 +0000393 "pass1");
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000394 }
Theodore Ts'o3839e651997-04-26 13:21:57 +0000395 }
Theodore Ts'oa9ca2012001-01-12 21:53:25 +0000396 } else if (ino == EXT2_JOURNAL_INO) {
Theodore Ts'of18996c2001-01-03 16:57:24 +0000397 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
398 if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
Theodore Ts'oa9ca2012001-01-12 21:53:25 +0000399 /*
400 * XXX arguably this check should be
401 * in journal.c, before we decide it's
402 * safe to run the journal...
403 */
404 if (!LINUX_S_ISREG(inode.i_mode) &&
405 fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
406 &pctx)) {
407 inode.i_mode = LINUX_S_IFREG;
408 e2fsck_write_inode(ctx, ino, &inode,
409 "pass1");
410 }
Theodore Ts'of18996c2001-01-03 16:57:24 +0000411 check_blocks(ctx, &pctx, block_buf);
412 goto next;
413 }
Theodore Ts'oa9ca2012001-01-12 21:53:25 +0000414 if ((inode.i_links_count || inode.i_blocks ||
415 inode.i_blocks || inode.i_block[0]) &&
416 fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
Theodore Ts'of18996c2001-01-03 16:57:24 +0000417 &pctx)) {
418 memset(&inode, 0, sizeof(inode));
Theodore Ts'oa9ca2012001-01-12 21:53:25 +0000419 ext2fs_icount_store(ctx->inode_link_info,
420 ino, 0);
Theodore Ts'of18996c2001-01-03 16:57:24 +0000421 e2fsck_write_inode(ctx, ino, &inode, "pass1");
422 }
Theodore Ts'oa9ca2012001-01-12 21:53:25 +0000423 } else if (ino < EXT2_FIRST_INODE(fs->super)) {
Theodore Ts'ob09a4b02000-10-24 21:16:09 +0000424 int problem = 0;
425
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000426 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
Theodore Ts'o53ef44c2001-01-06 05:55:58 +0000427 if (ino == EXT2_BOOT_LOADER_INO) {
Theodore Ts'ob09a4b02000-10-24 21:16:09 +0000428 if (LINUX_S_ISDIR(inode.i_mode))
429 problem = PR_1_RESERVED_BAD_MODE;
Theodore Ts'o53ef44c2001-01-06 05:55:58 +0000430 } else {
Theodore Ts'ob09a4b02000-10-24 21:16:09 +0000431 if (inode.i_mode != 0)
432 problem = PR_1_RESERVED_BAD_MODE;
Theodore Ts'ob09a4b02000-10-24 21:16:09 +0000433 }
434 if (problem) {
435 if (fix_problem(ctx, problem, &pctx)) {
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000436 inode.i_mode = 0;
Theodore Ts'o08b21301997-11-03 19:42:40 +0000437 e2fsck_write_inode(ctx, ino, &inode,
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000438 "pass1");
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000439 }
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000440 }
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000441 check_blocks(ctx, &pctx, block_buf);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000442 goto next;
443 }
444 /*
445 * This code assumes that deleted inodes have
446 * i_links_count set to 0.
447 */
448 if (!inode.i_links_count) {
449 if (!inode.i_dtime && inode.i_mode) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000450 if (fix_problem(ctx,
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000451 PR_1_ZERO_DTIME, &pctx)) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000452 inode.i_dtime = time(0);
Theodore Ts'o08b21301997-11-03 19:42:40 +0000453 e2fsck_write_inode(ctx, ino, &inode,
Theodore Ts'of3db3561997-04-26 13:34:30 +0000454 "pass1");
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000455 }
Theodore Ts'o3839e651997-04-26 13:21:57 +0000456 }
457 goto next;
458 }
459 /*
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000460 * n.b. 0.3c ext2fs code didn't clear i_links_count for
Theodore Ts'o3839e651997-04-26 13:21:57 +0000461 * deleted files. Oops.
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000462 *
463 * Since all new ext2 implementations get this right,
464 * we now assume that the case of non-zero
465 * i_links_count and non-zero dtime means that we
466 * should keep the file, not delete it.
Theodore Ts'o3839e651997-04-26 13:21:57 +0000467 *
Theodore Ts'o3839e651997-04-26 13:21:57 +0000468 */
469 if (inode.i_dtime) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000470 if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000471 inode.i_dtime = 0;
Theodore Ts'o08b21301997-11-03 19:42:40 +0000472 e2fsck_write_inode(ctx, ino, &inode, "pass1");
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000473 }
Theodore Ts'o3839e651997-04-26 13:21:57 +0000474 }
475
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000476 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000477 switch (fs->super->s_creator_os) {
478 case EXT2_OS_LINUX:
479 frag = inode.osd2.linux2.l_i_frag;
480 fsize = inode.osd2.linux2.l_i_fsize;
481 break;
482 case EXT2_OS_HURD:
483 frag = inode.osd2.hurd2.h_i_frag;
484 fsize = inode.osd2.hurd2.h_i_fsize;
485 break;
486 case EXT2_OS_MASIX:
487 frag = inode.osd2.masix2.m_i_frag;
488 fsize = inode.osd2.masix2.m_i_fsize;
489 break;
490 default:
491 frag = fsize = 0;
492 }
493
494 if (inode.i_faddr || frag || fsize
Theodore Ts'o246501c1998-03-24 16:22:38 +0000495 || inode.i_file_acl ||
496 (LINUX_S_ISDIR(inode.i_mode) && inode.i_dir_acl)) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000497 if (!ctx->inode_bad_map)
498 alloc_bad_map(ctx);
499 ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000500 }
Theodore Ts'oaa4115a1999-10-21 19:33:18 +0000501 if (inode.i_flags & EXT2_IMAGIC_FL) {
Theodore Ts'o6fdc7a31999-11-10 13:34:40 +0000502 if (imagic_fs) {
503 if (!ctx->inode_imagic_map)
504 alloc_imagic_map(ctx);
505 ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
506 ino);
507 } else {
508 if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
509 inode.i_flags &= ~EXT2_IMAGIC_FL;
510 e2fsck_write_inode(ctx, ino,
511 &inode, "pass1");
512 }
513 }
Theodore Ts'oaa4115a1999-10-21 19:33:18 +0000514 }
Theodore Ts'o3839e651997-04-26 13:21:57 +0000515
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000516 if (LINUX_S_ISDIR(inode.i_mode)) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000517 ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
Theodore Ts'o08b21301997-11-03 19:42:40 +0000518 e2fsck_add_dir_info(ctx, ino, 0);
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000519 ctx->fs_directory_count++;
Theodore Ts'oaa4115a1999-10-21 19:33:18 +0000520 } else if (LINUX_S_ISREG (inode.i_mode)) {
521 ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000522 ctx->fs_regular_count++;
Theodore Ts'oaa4115a1999-10-21 19:33:18 +0000523 } else if (LINUX_S_ISCHR (inode.i_mode) &&
Theodore Ts'o6fdc7a31999-11-10 13:34:40 +0000524 e2fsck_pass1_check_device_inode(&inode)) {
525 check_immutable(ctx, &pctx);
Theodore Ts'od647a1e2000-05-27 14:40:09 +0000526 check_size(ctx, &pctx);
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000527 ctx->fs_chardev_count++;
Theodore Ts'o6fdc7a31999-11-10 13:34:40 +0000528 } else if (LINUX_S_ISBLK (inode.i_mode) &&
529 e2fsck_pass1_check_device_inode(&inode)) {
530 check_immutable(ctx, &pctx);
Theodore Ts'od647a1e2000-05-27 14:40:09 +0000531 check_size(ctx, &pctx);
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000532 ctx->fs_blockdev_count++;
Theodore Ts'o6fdc7a31999-11-10 13:34:40 +0000533 } else if (LINUX_S_ISLNK (inode.i_mode)) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000534 ctx->fs_symlinks_count++;
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000535 if (!inode.i_blocks) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000536 ctx->fs_fast_symlinks_count++;
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000537 goto next;
538 }
Theodore Ts'o3839e651997-04-26 13:21:57 +0000539 }
Theodore Ts'o1dde43f1998-11-14 04:18:28 +0000540 else if (LINUX_S_ISFIFO (inode.i_mode) &&
Theodore Ts'o6fdc7a31999-11-10 13:34:40 +0000541 e2fsck_pass1_check_device_inode(&inode)) {
542 check_immutable(ctx, &pctx);
Theodore Ts'od647a1e2000-05-27 14:40:09 +0000543 check_size(ctx, &pctx);
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000544 ctx->fs_fifo_count++;
Theodore Ts'o6fdc7a31999-11-10 13:34:40 +0000545 } else if ((LINUX_S_ISSOCK (inode.i_mode)) &&
546 e2fsck_pass1_check_device_inode(&inode)) {
547 check_immutable(ctx, &pctx);
Theodore Ts'od647a1e2000-05-27 14:40:09 +0000548 check_size(ctx, &pctx);
549 ctx->fs_sockets_count++;
Theodore Ts'o6fdc7a31999-11-10 13:34:40 +0000550 } else {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000551 if (!ctx->inode_bad_map)
552 alloc_bad_map(ctx);
553 ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000554 }
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000555 if (inode.i_block[EXT2_IND_BLOCK])
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000556 ctx->fs_ind_count++;
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000557 if (inode.i_block[EXT2_DIND_BLOCK])
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000558 ctx->fs_dind_count++;
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000559 if (inode.i_block[EXT2_TIND_BLOCK])
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000560 ctx->fs_tind_count++;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000561 if (inode.i_block[EXT2_IND_BLOCK] ||
562 inode.i_block[EXT2_DIND_BLOCK] ||
563 inode.i_block[EXT2_TIND_BLOCK]) {
564 inodes_to_process[process_inode_count].ino = ino;
565 inodes_to_process[process_inode_count].inode = inode;
566 process_inode_count++;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000567 } else
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000568 check_blocks(ctx, &pctx, block_buf);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000569
Theodore Ts'oa02ce9d1998-02-24 20:22:23 +0000570 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
Theodore Ts'o08b21301997-11-03 19:42:40 +0000571 return;
572
573 if (process_inode_count >= ctx->process_inode_size) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000574 process_inodes(ctx, block_buf);
Theodore Ts'o08b21301997-11-03 19:42:40 +0000575
Theodore Ts'oa02ce9d1998-02-24 20:22:23 +0000576 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
Theodore Ts'o08b21301997-11-03 19:42:40 +0000577 return;
578 }
Theodore Ts'o3839e651997-04-26 13:21:57 +0000579 next:
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000580 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
Theodore Ts'o2df1f6a1998-02-27 05:03:48 +0000581 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
582 return;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000583 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
584 if (!ctx->inode_bb_map)
585 alloc_bb_map(ctx);
586 ext2fs_mark_inode_bitmap(ctx->inode_bb_map, ino);
587 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000588 goto next;
589 }
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000590 if (pctx.errcode) {
591 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
Theodore Ts'o08b21301997-11-03 19:42:40 +0000592 ctx->flags |= E2F_FLAG_ABORT;
593 return;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000594 }
595 }
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000596 process_inodes(ctx, block_buf);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000597 ext2fs_close_inode_scan(scan);
598 ehandler_operation(0);
599
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000600 if (ctx->invalid_bitmaps)
601 handle_fs_bad_blocks(ctx);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000602
Theodore Ts'o08b21301997-11-03 19:42:40 +0000603 if (ctx->flags & E2F_FLAG_RESTART) {
Theodore Ts'oaa4115a1999-10-21 19:33:18 +0000604 /*
605 * Only the master copy of the superblock and block
606 * group descriptors are going to be written during a
607 * restart, so set the superblock to be used to be the
608 * master superblock.
609 */
610 ctx->use_superblock = 0;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000611 unwind_pass1(fs);
612 goto endit;
613 }
614
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000615 if (ctx->block_dup_map) {
616 if (ctx->options & E2F_OPT_PREEN) {
617 clear_problem_context(&pctx);
618 fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000619 }
Theodore Ts'o08b21301997-11-03 19:42:40 +0000620 e2fsck_pass1_dupblocks(ctx, block_buf);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000621 }
Theodore Ts'o08b21301997-11-03 19:42:40 +0000622 ext2fs_free_mem((void **) &inodes_to_process);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000623endit:
Theodore Ts'oe72a9ba1999-06-25 15:40:18 +0000624 e2fsck_use_inode_shortcuts(ctx, 0);
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000625
Theodore Ts'o08b21301997-11-03 19:42:40 +0000626 ext2fs_free_mem((void **) &block_buf);
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000627
Theodore Ts'o8188c9e2000-12-13 18:39:14 +0000628 if (ctx->large_files) {
Theodore Ts'of5ae75e2001-01-01 14:52:52 +0000629 if (!(sb->s_feature_ro_compat &
630 EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
Theodore Ts'o8188c9e2000-12-13 18:39:14 +0000631 fix_problem(ctx, PR_1_FEATURE_LARGE_FILES, &pctx)) {
632 sb->s_feature_ro_compat |=
Theodore Ts'o246501c1998-03-24 16:22:38 +0000633 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
634 ext2fs_mark_super_dirty(fs);
635 }
Theodore Ts'o8188c9e2000-12-13 18:39:14 +0000636 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
637 fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
638 ext2fs_update_dynamic_rev(fs);
639 ext2fs_mark_super_dirty(fs);
640 }
Theodore Ts'o246501c1998-03-24 16:22:38 +0000641 } else if (!ctx->large_files &&
Theodore Ts'o874b4d21998-07-06 14:33:12 +0000642 (sb->s_feature_ro_compat &
Theodore Ts'o246501c1998-03-24 16:22:38 +0000643 EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
644 if (fs->flags & EXT2_FLAG_RW) {
Theodore Ts'o874b4d21998-07-06 14:33:12 +0000645 sb->s_feature_ro_compat &=
Theodore Ts'o246501c1998-03-24 16:22:38 +0000646 ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
647 ext2fs_mark_super_dirty(fs);
648 }
649 }
650
Theodore Ts'o8bf191e1997-10-20 01:38:32 +0000651#ifdef RESOURCE_TRACK
Theodore Ts'o5596def1999-07-19 15:27:37 +0000652 if (ctx->options & E2F_OPT_TIME2) {
653 e2fsck_clear_progbar(ctx);
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000654 print_resource_track(_("Pass 1"), &rtrack);
Theodore Ts'o5596def1999-07-19 15:27:37 +0000655 }
Theodore Ts'o8bf191e1997-10-20 01:38:32 +0000656#endif
Theodore Ts'o3839e651997-04-26 13:21:57 +0000657}
658
659/*
Theodore Ts'of3db3561997-04-26 13:34:30 +0000660 * When the inode_scan routines call this callback at the end of the
661 * glock group, call process_inodes.
662 */
663static errcode_t scan_callback(ext2_filsys fs, ext2_inode_scan scan,
Theodore Ts'o54dc7ca1998-01-19 14:50:49 +0000664 dgrp_t group, void * priv_data)
Theodore Ts'of3db3561997-04-26 13:34:30 +0000665{
Theodore Ts'o54dc7ca1998-01-19 14:50:49 +0000666 struct scan_callback_struct *scan_struct;
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000667 e2fsck_t ctx;
668
Theodore Ts'o54dc7ca1998-01-19 14:50:49 +0000669 scan_struct = (struct scan_callback_struct *) priv_data;
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000670 ctx = scan_struct->ctx;
671
Theodore Ts'o54dc7ca1998-01-19 14:50:49 +0000672 process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000673
674 if (ctx->progress)
Theodore Ts'oa02ce9d1998-02-24 20:22:23 +0000675 if ((ctx->progress)(ctx, 1, group+1,
676 ctx->fs->group_desc_count))
677 return EXT2_ET_CANCEL_REQUESTED;
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000678
Theodore Ts'of3db3561997-04-26 13:34:30 +0000679 return 0;
680}
681
682/*
Theodore Ts'o3839e651997-04-26 13:21:57 +0000683 * Process the inodes in the "inodes to process" list.
684 */
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000685static void process_inodes(e2fsck_t ctx, char *block_buf)
Theodore Ts'o3839e651997-04-26 13:21:57 +0000686{
687 int i;
688 struct ext2_inode *old_stashed_inode;
Theodore Ts'o86c627e2001-01-11 15:12:14 +0000689 ext2_ino_t old_stashed_ino;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000690 const char *old_operation;
691 char buf[80];
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000692 struct problem_context pctx;
693
Theodore Ts'o3839e651997-04-26 13:21:57 +0000694#if 0
Theodore Ts'of3db3561997-04-26 13:34:30 +0000695 printf("begin process_inodes: ");
Theodore Ts'o3839e651997-04-26 13:21:57 +0000696#endif
Theodore Ts'o86a63e91999-11-23 13:52:48 +0000697 if (process_inode_count == 0)
698 return;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000699 old_operation = ehandler_operation(0);
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000700 old_stashed_inode = ctx->stashed_inode;
701 old_stashed_ino = ctx->stashed_ino;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000702 qsort(inodes_to_process, process_inode_count,
703 sizeof(struct process_inode_block), process_inode_cmp);
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000704 clear_problem_context(&pctx);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000705 for (i=0; i < process_inode_count; i++) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000706 pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
707 pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000708
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000709#if 0
710 printf("%u ", pctx.ino);
711#endif
Theodore Ts'o86c627e2001-01-11 15:12:14 +0000712 sprintf(buf, _("reading indirect blocks of inode %u"),
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000713 pctx.ino);
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000714 ehandler_operation(buf);
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000715 check_blocks(ctx, &pctx, block_buf);
Theodore Ts'oa02ce9d1998-02-24 20:22:23 +0000716 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
Theodore Ts'o2df1f6a1998-02-27 05:03:48 +0000717 break;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000718 }
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000719 ctx->stashed_inode = old_stashed_inode;
720 ctx->stashed_ino = old_stashed_ino;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000721 process_inode_count = 0;
722#if 0
Theodore Ts'of3db3561997-04-26 13:34:30 +0000723 printf("end process inodes\n");
Theodore Ts'o3839e651997-04-26 13:21:57 +0000724#endif
725 ehandler_operation(old_operation);
726}
727
Theodore Ts'o4c77fe51998-04-30 17:35:59 +0000728static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b)
Theodore Ts'o3839e651997-04-26 13:21:57 +0000729{
730 const struct process_inode_block *ib_a =
731 (const struct process_inode_block *) a;
732 const struct process_inode_block *ib_b =
733 (const struct process_inode_block *) b;
734
735 return (ib_a->inode.i_block[EXT2_IND_BLOCK] -
736 ib_b->inode.i_block[EXT2_IND_BLOCK]);
737}
738
Theodore Ts'o3839e651997-04-26 13:21:57 +0000739/*
740 * This procedure will allocate the inode bad map table
741 */
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000742static void alloc_bad_map(e2fsck_t ctx)
Theodore Ts'o3839e651997-04-26 13:21:57 +0000743{
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000744 struct problem_context pctx;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000745
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000746 clear_problem_context(&pctx);
747
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000748 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs, _("bad inode map"),
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000749 &ctx->inode_bad_map);
750 if (pctx.errcode) {
751 pctx.num = 3;
752 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
Theodore Ts'o08b21301997-11-03 19:42:40 +0000753 /* Should never get here */
754 ctx->flags |= E2F_FLAG_ABORT;
755 return;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000756 }
757}
758
759/*
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000760 * This procedure will allocate the inode "bb" (badblock) map table
761 */
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000762static void alloc_bb_map(e2fsck_t ctx)
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000763{
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000764 struct problem_context pctx;
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000765
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000766 clear_problem_context(&pctx);
767 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000768 _("inode in bad block map"),
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000769 &ctx->inode_bb_map);
770 if (pctx.errcode) {
771 pctx.num = 4;
772 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
Theodore Ts'o08b21301997-11-03 19:42:40 +0000773 /* Should never get here */
774 ctx->flags |= E2F_FLAG_ABORT;
775 return;
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000776 }
777}
778
779/*
Theodore Ts'oaa4115a1999-10-21 19:33:18 +0000780 * This procedure will allocate the inode imagic table
781 */
782static void alloc_imagic_map(e2fsck_t ctx)
783{
784 struct problem_context pctx;
785
786 clear_problem_context(&pctx);
787 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000788 _("imagic inode map"),
Theodore Ts'oaa4115a1999-10-21 19:33:18 +0000789 &ctx->inode_imagic_map);
790 if (pctx.errcode) {
791 pctx.num = 5;
792 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
793 /* Should never get here */
794 ctx->flags |= E2F_FLAG_ABORT;
795 return;
796 }
797}
798
799/*
Theodore Ts'o3839e651997-04-26 13:21:57 +0000800 * Marks a block as in use, setting the dup_map if it's been set
801 * already. Called by process_block and process_bad_block.
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000802 *
803 * WARNING: Assumes checks have already been done to make sure block
804 * is valid. This is true in both process_block and process_bad_block.
Theodore Ts'o3839e651997-04-26 13:21:57 +0000805 */
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000806static _INLINE_ void mark_block_used(e2fsck_t ctx, blk_t block)
Theodore Ts'o3839e651997-04-26 13:21:57 +0000807{
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000808 struct problem_context pctx;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000809
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000810 clear_problem_context(&pctx);
811
812 if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
813 if (!ctx->block_dup_map) {
814 pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
Theodore Ts'o0c4a0722000-02-07 03:11:03 +0000815 _("multiply claimed block map"),
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000816 &ctx->block_dup_map);
817 if (pctx.errcode) {
818 pctx.num = 3;
819 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
820 &pctx);
Theodore Ts'o08b21301997-11-03 19:42:40 +0000821 /* Should never get here */
822 ctx->flags |= E2F_FLAG_ABORT;
823 return;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000824 }
825 }
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000826 ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000827 } else {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000828 ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000829 }
830}
831
832/*
833 * This subroutine is called on each inode to account for all of the
834 * blocks used by that inode.
835 */
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000836static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
Theodore Ts'o3839e651997-04-26 13:21:57 +0000837 char *block_buf)
838{
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000839 ext2_filsys fs = ctx->fs;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000840 struct process_block_struct pb;
Theodore Ts'o86c627e2001-01-11 15:12:14 +0000841 ext2_ino_t ino = pctx->ino;
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000842 struct ext2_inode *inode = pctx->inode;
Theodore Ts'o246501c1998-03-24 16:22:38 +0000843 int bad_size = 0;
844 __u64 size;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000845
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000846 if (!ext2fs_inode_has_valid_blocks(pctx->inode))
Theodore Ts'o3839e651997-04-26 13:21:57 +0000847 return;
848
849 pb.ino = ino;
850 pb.num_blocks = pb.last_block = 0;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000851 pb.num_illegal_blocks = 0;
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000852 pb.suppress = 0; pb.clear = 0;
Theodore Ts'o74becf31997-04-26 14:37:06 +0000853 pb.fragmented = 0;
Theodore Ts'o19178752000-02-11 15:55:07 +0000854 pb.compressed = 0;
Theodore Ts'o74becf31997-04-26 14:37:06 +0000855 pb.previous_block = 0;
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000856 pb.is_dir = LINUX_S_ISDIR(pctx->inode->i_mode);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000857 pb.inode = inode;
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000858 pb.pctx = pctx;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000859 pb.ctx = ctx;
860 pctx->ino = ino;
Theodore Ts'o19178752000-02-11 15:55:07 +0000861
862 if (inode->i_flags & EXT2_COMPRBLK_FL) {
Theodore Ts'of5ae75e2001-01-01 14:52:52 +0000863 if (fs->super->s_feature_incompat &
864 EXT2_FEATURE_INCOMPAT_COMPRESSION)
Theodore Ts'o19178752000-02-11 15:55:07 +0000865 pb.compressed = 1;
866 else {
867 if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
868 inode->i_flags &= ~EXT2_COMPRBLK_FL;
869 e2fsck_write_inode(ctx, ino, inode,
870 "check_blocks");
871 }
872 }
873 }
874
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000875 pctx->errcode = ext2fs_block_iterate2(fs, ino,
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000876 pb.is_dir ? BLOCK_FLAG_HOLE : 0,
877 block_buf, process_block, &pb);
Theodore Ts'oa02ce9d1998-02-24 20:22:23 +0000878 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
Theodore Ts'o08b21301997-11-03 19:42:40 +0000879 return;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000880 end_problem_latch(ctx, PR_LATCH_BLOCK);
881 if (pctx->errcode)
882 fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000883
Theodore Ts'o74becf31997-04-26 14:37:06 +0000884 if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000885 ctx->fs_fragmented++;
Theodore Ts'o74becf31997-04-26 14:37:06 +0000886
Theodore Ts'of3db3561997-04-26 13:34:30 +0000887 if (pb.clear) {
Theodore Ts'o08b21301997-11-03 19:42:40 +0000888 e2fsck_read_inode(ctx, ino, inode, "check_blocks");
Theodore Ts'of3db3561997-04-26 13:34:30 +0000889 inode->i_links_count = 0;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000890 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000891 inode->i_dtime = time(0);
Theodore Ts'o08b21301997-11-03 19:42:40 +0000892 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000893 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
Theodore Ts'oaa4115a1999-10-21 19:33:18 +0000894 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000895 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000896 /*
897 * The inode was probably partially accounted for
898 * before processing was aborted, so we need to
899 * restart the pass 1 scan.
900 */
Theodore Ts'o08b21301997-11-03 19:42:40 +0000901 ctx->flags |= E2F_FLAG_RESTART;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000902 return;
903 }
904
Theodore Ts'o3839e651997-04-26 13:21:57 +0000905 pb.num_blocks *= (fs->blocksize / 512);
906#if 0
Theodore Ts'o246501c1998-03-24 16:22:38 +0000907 printf("inode %u, i_size = %lu, last_block = %lld, i_blocks=%lu, num_blocks = %lu\n",
Theodore Ts'o3839e651997-04-26 13:21:57 +0000908 ino, inode->i_size, pb.last_block, inode->i_blocks,
909 pb.num_blocks);
910#endif
911 if (!pb.num_blocks && pb.is_dir) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000912 if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000913 inode->i_links_count = 0;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000914 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000915 inode->i_dtime = time(0);
Theodore Ts'o08b21301997-11-03 19:42:40 +0000916 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000917 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
Theodore Ts'oaa4115a1999-10-21 19:33:18 +0000918 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000919 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
920 ctx->fs_directory_count--;
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000921 pb.is_dir = 0;
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000922 }
Theodore Ts'o3839e651997-04-26 13:21:57 +0000923 }
Theodore Ts'o246501c1998-03-24 16:22:38 +0000924 if (pb.is_dir) {
925 int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
Theodore Ts'oa5c33f22001-01-18 02:34:03 +0000926 /* We don't let a directory become larger than 2GB */
927 if (nblock > (pb.last_block + 1) ||
928 (inode->i_size & ((fs->blocksize-1) | 0x80000000UL)) != 0)
Theodore Ts'o246501c1998-03-24 16:22:38 +0000929 bad_size = 1;
930 else if (nblock < (pb.last_block + 1)) {
Theodore Ts'o246501c1998-03-24 16:22:38 +0000931 if (((pb.last_block + 1) - nblock) >
Theodore Ts'o5dd8f962001-01-01 15:51:50 +0000932 fs->super->s_prealloc_dir_blocks)
Theodore Ts'o9d1bd3d1998-06-10 20:45:22 +0000933 bad_size = 2;
Theodore Ts'o246501c1998-03-24 16:22:38 +0000934 }
935 } else {
Theodore Ts'oa5c33f22001-01-18 02:34:03 +0000936 size = inode->i_size | ((__u64) inode->i_size_high << 32);
Theodore Ts'o246501c1998-03-24 16:22:38 +0000937 if ((size < pb.last_block * fs->blocksize))
Theodore Ts'o9d1bd3d1998-06-10 20:45:22 +0000938 bad_size = 3;
Theodore Ts'o246501c1998-03-24 16:22:38 +0000939 else if (size > ext2_max_sizes[fs->super->s_log_block_size])
Theodore Ts'o9d1bd3d1998-06-10 20:45:22 +0000940 bad_size = 4;
Theodore Ts'oa5c33f22001-01-18 02:34:03 +0000941 /* FIXME: need to ensure pb.num_blocks < 2^32 */
Theodore Ts'o246501c1998-03-24 16:22:38 +0000942 }
943 if (bad_size) {
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000944 pctx->num = (pb.last_block+1) * fs->blocksize;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000945 if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000946 inode->i_size = pctx->num;
Theodore Ts'o246501c1998-03-24 16:22:38 +0000947 if (!pb.is_dir)
948 inode->i_size_high = pctx->num >> 32;
Theodore Ts'o08b21301997-11-03 19:42:40 +0000949 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000950 }
951 pctx->num = 0;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000952 }
Theodore Ts'oa5c33f22001-01-18 02:34:03 +0000953 if (!pb.is_dir && (inode->i_size_high || inode->i_size & 0x80000000UL))
Theodore Ts'o246501c1998-03-24 16:22:38 +0000954 ctx->large_files++;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000955 if (pb.num_blocks != inode->i_blocks) {
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000956 pctx->num = pb.num_blocks;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000957 if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000958 inode->i_blocks = pb.num_blocks;
Theodore Ts'o08b21301997-11-03 19:42:40 +0000959 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000960 }
961 pctx->num = 0;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000962 }
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000963}
964
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000965#if 0
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000966/*
967 * Helper function called by process block when an illegal block is
968 * found. It returns a description about why the block is illegal
969 */
970static char *describe_illegal_block(ext2_filsys fs, blk_t block)
971{
972 blk_t super;
973 int i;
974 static char problem[80];
975
976 super = fs->super->s_first_data_block;
977 strcpy(problem, "PROGRAMMING ERROR: Unknown reason for illegal block");
978 if (block < super) {
979 sprintf(problem, "< FIRSTBLOCK (%u)", super);
980 return(problem);
981 } else if (block >= fs->super->s_blocks_count) {
982 sprintf(problem, "> BLOCKS (%u)", fs->super->s_blocks_count);
983 return(problem);
984 }
985 for (i = 0; i < fs->group_desc_count; i++) {
986 if (block == super) {
987 sprintf(problem, "is the superblock in group %d", i);
988 break;
989 }
990 if (block > super &&
991 block <= (super + fs->desc_blocks)) {
992 sprintf(problem, "is in the group descriptors "
993 "of group %d", i);
994 break;
995 }
996 if (block == fs->group_desc[i].bg_block_bitmap) {
997 sprintf(problem, "is the block bitmap of group %d", i);
998 break;
999 }
1000 if (block == fs->group_desc[i].bg_inode_bitmap) {
1001 sprintf(problem, "is the inode bitmap of group %d", i);
1002 break;
1003 }
1004 if (block >= fs->group_desc[i].bg_inode_table &&
1005 (block < fs->group_desc[i].bg_inode_table
1006 + fs->inode_blocks_per_group)) {
1007 sprintf(problem, "is in the inode table of group %d",
1008 i);
1009 break;
1010 }
1011 super += fs->super->s_blocks_per_group;
1012 }
1013 return(problem);
1014}
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001015#endif
Theodore Ts'o3839e651997-04-26 13:21:57 +00001016
1017/*
1018 * This is a helper function for check_blocks().
1019 */
Theodore Ts'o53ef44c2001-01-06 05:55:58 +00001020static int process_block(ext2_filsys fs,
Theodore Ts'o3839e651997-04-26 13:21:57 +00001021 blk_t *block_nr,
Theodore Ts'o9d1bd3d1998-06-10 20:45:22 +00001022 e2_blkcnt_t blockcnt,
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001023 blk_t ref_block,
1024 int ref_offset,
Theodore Ts'o54dc7ca1998-01-19 14:50:49 +00001025 void *priv_data)
Theodore Ts'o3839e651997-04-26 13:21:57 +00001026{
1027 struct process_block_struct *p;
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001028 struct problem_context *pctx;
Theodore Ts'o3839e651997-04-26 13:21:57 +00001029 blk_t blk = *block_nr;
Theodore Ts'o50e1e101997-04-26 13:58:21 +00001030 int ret_code = 0;
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001031 int problem = 0;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001032 e2fsck_t ctx;
Theodore Ts'o3839e651997-04-26 13:21:57 +00001033
Theodore Ts'o54dc7ca1998-01-19 14:50:49 +00001034 p = (struct process_block_struct *) priv_data;
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001035 pctx = p->pctx;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001036 ctx = p->ctx;
Theodore Ts'o3839e651997-04-26 13:21:57 +00001037
Theodore Ts'o19178752000-02-11 15:55:07 +00001038 if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
1039 /* todo: Check that the comprblk_fl is high, that the
1040 blkaddr pattern looks right (all non-holes up to
1041 first EXT2FS_COMPRESSED_BLKADDR, then all
1042 EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
1043 that the feature_incompat bit is high, and that the
1044 inode is a regular file. If we're doing a "full
1045 check" (a concept introduced to e2fsck by e2compr,
1046 meaning that we look at data blocks as well as
1047 metadata) then call some library routine that
1048 checks the compressed data. I'll have to think
1049 about this, because one particularly important
1050 problem to be able to fix is to recalculate the
1051 cluster size if necessary. I think that perhaps
1052 we'd better do most/all e2compr-specific checks
1053 separately, after the non-e2compr checks. If not
1054 doing a full check, it may be useful to test that
1055 the personality is linux; e.g. if it isn't then
1056 perhaps this really is just an illegal block. */
1057 return 0;
1058 }
1059
Theodore Ts'o50e1e101997-04-26 13:58:21 +00001060 if (blk == 0) {
1061 if (p->is_dir == 0) {
Theodore Ts'o1e3472c1997-04-29 14:53:37 +00001062 /*
1063 * Should never happen, since only directories
1064 * get called with BLOCK_FLAG_HOLE
1065 */
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001066#if DEBUG_E2FSCK
Theodore Ts'o50e1e101997-04-26 13:58:21 +00001067 printf("process_block() called with blk == 0, "
Theodore Ts'o5c576471997-04-29 15:29:49 +00001068 "blockcnt=%d, inode %lu???\n",
1069 blockcnt, p->ino);
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001070#endif
Theodore Ts'o50e1e101997-04-26 13:58:21 +00001071 return 0;
1072 }
1073 if (blockcnt < 0)
1074 return 0;
1075 if (blockcnt * fs->blocksize < p->inode->i_size) {
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001076#if 0
1077 printf("Missing block (#%d) in directory inode %lu!\n",
1078 blockcnt, p->ino);
1079#endif
Theodore Ts'o50e1e101997-04-26 13:58:21 +00001080 goto mark_dir;
1081 }
1082 return 0;
Theodore Ts'o3839e651997-04-26 13:21:57 +00001083 }
Theodore Ts'o50e1e101997-04-26 13:58:21 +00001084
1085#if 0
1086 printf("Process_block, inode %lu, block %u, #%d\n", p->ino, blk,
1087 blockcnt);
1088#endif
1089
Theodore Ts'o74becf31997-04-26 14:37:06 +00001090 /*
1091 * Simplistic fragmentation check. We merely require that the
1092 * file be contiguous. (Which can never be true for really
1093 * big files that are greater than a block group.)
1094 */
Theodore Ts'o19178752000-02-11 15:55:07 +00001095 if (!HOLE_BLKADDR(p->previous_block)) {
Theodore Ts'o74becf31997-04-26 14:37:06 +00001096 if (p->previous_block+1 != blk)
1097 p->fragmented = 1;
1098 }
1099 p->previous_block = blk;
1100
Theodore Ts'o50e1e101997-04-26 13:58:21 +00001101 if (blk < fs->super->s_first_data_block ||
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001102 blk >= fs->super->s_blocks_count)
1103 problem = PR_1_ILLEGAL_BLOCK_NUM;
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001104
1105 if (problem) {
Theodore Ts'of3db3561997-04-26 13:34:30 +00001106 p->num_illegal_blocks++;
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001107 if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001108 if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
Theodore Ts'of3db3561997-04-26 13:34:30 +00001109 p->clear = 1;
1110 return BLOCK_ABORT;
1111 }
Theodore Ts'of8188ff1997-11-14 05:23:04 +00001112 if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
Theodore Ts'of3db3561997-04-26 13:34:30 +00001113 p->suppress = 1;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001114 set_latch_flags(PR_LATCH_BLOCK,
1115 PRL_SUPPRESS, 0);
Theodore Ts'of3db3561997-04-26 13:34:30 +00001116 }
1117 }
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001118 pctx->blk = blk;
1119 pctx->blkcount = blockcnt;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001120 if (fix_problem(ctx, problem, pctx)) {
Theodore Ts'o50e1e101997-04-26 13:58:21 +00001121 blk = *block_nr = 0;
1122 ret_code = BLOCK_CHANGED;
1123 goto mark_dir;
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001124 } else
Theodore Ts'o3839e651997-04-26 13:21:57 +00001125 return 0;
Theodore Ts'o3839e651997-04-26 13:21:57 +00001126 }
1127
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001128 mark_block_used(ctx, blk);
Theodore Ts'o50e1e101997-04-26 13:58:21 +00001129 p->num_blocks++;
Theodore Ts'o1e3472c1997-04-29 14:53:37 +00001130 if (blockcnt >= 0)
1131 p->last_block = blockcnt;
Theodore Ts'o50e1e101997-04-26 13:58:21 +00001132mark_dir:
Theodore Ts'o1e3472c1997-04-29 14:53:37 +00001133 if (p->is_dir && (blockcnt >= 0)) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001134 pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
1135 blk, blockcnt);
1136 if (pctx->errcode) {
1137 pctx->blk = blk;
1138 pctx->num = blockcnt;
1139 fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
Theodore Ts'o08b21301997-11-03 19:42:40 +00001140 /* Should never get here */
1141 ctx->flags |= E2F_FLAG_ABORT;
1142 return BLOCK_ABORT;
Theodore Ts'o3839e651997-04-26 13:21:57 +00001143 }
Theodore Ts'o3839e651997-04-26 13:21:57 +00001144 }
Theodore Ts'o50e1e101997-04-26 13:58:21 +00001145 return ret_code;
Theodore Ts'o3839e651997-04-26 13:21:57 +00001146}
1147
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001148static void bad_block_indirect(e2fsck_t ctx, blk_t blk)
Theodore Ts'of3db3561997-04-26 13:34:30 +00001149{
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001150 struct problem_context pctx;
Theodore Ts'of3db3561997-04-26 13:34:30 +00001151
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001152 clear_problem_context(&pctx);
1153 /*
1154 * Prompt to see if we should continue or not.
1155 */
1156 if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK, &pctx))
Theodore Ts'o08b21301997-11-03 19:42:40 +00001157 ctx->flags |= E2F_FLAG_ABORT;
Theodore Ts'o50e1e101997-04-26 13:58:21 +00001158}
1159
Theodore Ts'o53ef44c2001-01-06 05:55:58 +00001160static int process_bad_block(ext2_filsys fs,
Theodore Ts'o3839e651997-04-26 13:21:57 +00001161 blk_t *block_nr,
Theodore Ts'o9d1bd3d1998-06-10 20:45:22 +00001162 e2_blkcnt_t blockcnt,
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001163 blk_t ref_block,
1164 int ref_offset,
Theodore Ts'o54dc7ca1998-01-19 14:50:49 +00001165 void *priv_data)
Theodore Ts'o3839e651997-04-26 13:21:57 +00001166{
1167 struct process_block_struct *p;
Theodore Ts'o3839e651997-04-26 13:21:57 +00001168 blk_t blk = *block_nr;
Theodore Ts'of3db3561997-04-26 13:34:30 +00001169 int first_block;
1170 int i;
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001171 struct problem_context *pctx;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001172 e2fsck_t ctx;
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001173
Theodore Ts'o19178752000-02-11 15:55:07 +00001174 /*
1175 * Note: This function processes blocks for the bad blocks
1176 * inode, which is never compressed. So we don't use HOLE_BLKADDR().
1177 */
1178
Theodore Ts'o3839e651997-04-26 13:21:57 +00001179 if (!blk)
1180 return 0;
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001181
Theodore Ts'o54dc7ca1998-01-19 14:50:49 +00001182 p = (struct process_block_struct *) priv_data;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001183 ctx = p->ctx;
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001184 pctx = p->pctx;
1185
Theodore Ts'of8188ff1997-11-14 05:23:04 +00001186 pctx->ino = EXT2_BAD_INO;
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001187 pctx->blk = blk;
1188 pctx->blkcount = blockcnt;
Theodore Ts'o3839e651997-04-26 13:21:57 +00001189
1190 if ((blk < fs->super->s_first_data_block) ||
1191 (blk >= fs->super->s_blocks_count)) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001192 if (fix_problem(ctx, PR_1_BB_ILLEGAL_BLOCK_NUM, pctx)) {
Theodore Ts'o3839e651997-04-26 13:21:57 +00001193 *block_nr = 0;
1194 return BLOCK_CHANGED;
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001195 } else
Theodore Ts'o3839e651997-04-26 13:21:57 +00001196 return 0;
Theodore Ts'o3839e651997-04-26 13:21:57 +00001197 }
1198
1199 if (blockcnt < 0) {
Theodore Ts'o08b21301997-11-03 19:42:40 +00001200 if (ext2fs_test_block_bitmap(ctx->block_found_map, blk)) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001201 bad_block_indirect(ctx, blk);
Theodore Ts'oa02ce9d1998-02-24 20:22:23 +00001202 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
Theodore Ts'o08b21301997-11-03 19:42:40 +00001203 return BLOCK_ABORT;
1204 } else
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001205 mark_block_used(ctx, blk);
Theodore Ts'o3839e651997-04-26 13:21:57 +00001206 return 0;
1207 }
1208#if 0
Theodore Ts'o50e1e101997-04-26 13:58:21 +00001209 printf ("DEBUG: Marking %u as bad.\n", blk);
Theodore Ts'o3839e651997-04-26 13:21:57 +00001210#endif
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001211 ctx->fs_badblocks_count++;
Theodore Ts'o3839e651997-04-26 13:21:57 +00001212 /*
1213 * If the block is not used, then mark it as used and return.
1214 * If it is already marked as found, this must mean that
1215 * there's an overlap between the filesystem table blocks
1216 * (bitmaps and inode table) and the bad block list.
1217 */
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001218 if (!ext2fs_test_block_bitmap(ctx->block_found_map, blk)) {
1219 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
Theodore Ts'o3839e651997-04-26 13:21:57 +00001220 return 0;
1221 }
Theodore Ts'of3db3561997-04-26 13:34:30 +00001222 /*
1223 * Try to find the where the filesystem block was used...
1224 */
1225 first_block = fs->super->s_first_data_block;
1226
1227 for (i = 0; i < fs->group_desc_count; i++ ) {
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001228 pctx->group = i;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001229 pctx->blk = blk;
Theodore Ts'o8039c481997-11-19 21:39:13 +00001230 if (!ext2fs_bg_has_super(fs, i))
1231 goto skip_super;
Theodore Ts'of3db3561997-04-26 13:34:30 +00001232 if (blk == first_block) {
1233 if (i == 0) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001234 if (fix_problem(ctx,
1235 PR_1_BAD_PRIMARY_SUPERBLOCK,
1236 pctx)) {
1237 *block_nr = 0;
Theodore Ts'o50e1e101997-04-26 13:58:21 +00001238 return BLOCK_CHANGED;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001239 }
Theodore Ts'o50e1e101997-04-26 13:58:21 +00001240 return 0;
Theodore Ts'of3db3561997-04-26 13:34:30 +00001241 }
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001242 fix_problem(ctx, PR_1_BAD_SUPERBLOCK, pctx);
Theodore Ts'of3db3561997-04-26 13:34:30 +00001243 return 0;
Theodore Ts'o3839e651997-04-26 13:21:57 +00001244 }
Theodore Ts'of3db3561997-04-26 13:34:30 +00001245 if ((blk > first_block) &&
1246 (blk <= first_block + fs->desc_blocks)) {
1247 if (i == 0) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001248 pctx->blk = *block_nr;
1249 if (fix_problem(ctx,
1250 PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR, pctx)) {
1251 *block_nr = 0;
Theodore Ts'o50e1e101997-04-26 13:58:21 +00001252 return BLOCK_CHANGED;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001253 }
Theodore Ts'o50e1e101997-04-26 13:58:21 +00001254 return 0;
Theodore Ts'of3db3561997-04-26 13:34:30 +00001255 }
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001256 fix_problem(ctx, PR_1_BAD_GROUP_DESCRIPTORS, pctx);
Theodore Ts'of3db3561997-04-26 13:34:30 +00001257 return 0;
1258 }
Theodore Ts'o8039c481997-11-19 21:39:13 +00001259 skip_super:
Theodore Ts'of3db3561997-04-26 13:34:30 +00001260 if (blk == fs->group_desc[i].bg_block_bitmap) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001261 if (fix_problem(ctx, PR_1_BB_BAD_BLOCK, pctx)) {
1262 ctx->invalid_block_bitmap_flag[i]++;
1263 ctx->invalid_bitmaps++;
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001264 }
Theodore Ts'of3db3561997-04-26 13:34:30 +00001265 return 0;
1266 }
1267 if (blk == fs->group_desc[i].bg_inode_bitmap) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001268 if (fix_problem(ctx, PR_1_IB_BAD_BLOCK, pctx)) {
1269 ctx->invalid_inode_bitmap_flag[i]++;
1270 ctx->invalid_bitmaps++;
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001271 }
Theodore Ts'of3db3561997-04-26 13:34:30 +00001272 return 0;
1273 }
1274 if ((blk >= fs->group_desc[i].bg_inode_table) &&
1275 (blk < (fs->group_desc[i].bg_inode_table +
1276 fs->inode_blocks_per_group))) {
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001277 /*
1278 * If there are bad blocks in the inode table,
1279 * the inode scan code will try to do
1280 * something reasonable automatically.
1281 */
Theodore Ts'of3db3561997-04-26 13:34:30 +00001282 return 0;
1283 }
Theodore Ts'o8039c481997-11-19 21:39:13 +00001284 first_block += fs->super->s_blocks_per_group;
Theodore Ts'o3839e651997-04-26 13:21:57 +00001285 }
Theodore Ts'of3db3561997-04-26 13:34:30 +00001286 /*
1287 * If we've gotten to this point, then the only
1288 * possibility is that the bad block inode meta data
1289 * is using a bad block.
1290 */
1291 if ((blk == p->inode->i_block[EXT2_IND_BLOCK]) ||
1292 p->inode->i_block[EXT2_DIND_BLOCK]) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001293 bad_block_indirect(ctx, blk);
Theodore Ts'oa02ce9d1998-02-24 20:22:23 +00001294 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
Theodore Ts'o08b21301997-11-03 19:42:40 +00001295 return BLOCK_ABORT;
Theodore Ts'of3db3561997-04-26 13:34:30 +00001296 return 0;
1297 }
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001298
1299 pctx->group = -1;
1300
1301 /* Warn user that the block wasn't claimed */
1302 fix_problem(ctx, PR_1_PROGERR_CLAIMED_BLOCK, pctx);
1303
Theodore Ts'o3839e651997-04-26 13:21:57 +00001304 return 0;
1305}
1306
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001307static void new_table_block(e2fsck_t ctx, blk_t first_block, int group,
Theodore Ts'o3839e651997-04-26 13:21:57 +00001308 const char *name, int num, blk_t *new_block)
1309{
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001310 ext2_filsys fs = ctx->fs;
Theodore Ts'o3839e651997-04-26 13:21:57 +00001311 blk_t old_block = *new_block;
1312 int i;
1313 char *buf;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001314 struct problem_context pctx;
1315
1316 clear_problem_context(&pctx);
1317
1318 pctx.group = group;
1319 pctx.blk = old_block;
1320 pctx.str = name;
1321
1322 pctx.errcode = ext2fs_get_free_blocks(fs, first_block,
Theodore Ts'o3839e651997-04-26 13:21:57 +00001323 first_block + fs->super->s_blocks_per_group,
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001324 num, ctx->block_found_map, new_block);
1325 if (pctx.errcode) {
1326 pctx.num = num;
1327 fix_problem(ctx, PR_1_RELOC_BLOCK_ALLOCATE, &pctx);
Theodore Ts'o3839e651997-04-26 13:21:57 +00001328 ext2fs_unmark_valid(fs);
1329 return;
1330 }
Theodore Ts'o08b21301997-11-03 19:42:40 +00001331 pctx.errcode = ext2fs_get_mem(fs->blocksize, (void **) &buf);
1332 if (pctx.errcode) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001333 fix_problem(ctx, PR_1_RELOC_MEMORY_ALLOCATE, &pctx);
Theodore Ts'o3839e651997-04-26 13:21:57 +00001334 ext2fs_unmark_valid(fs);
1335 return;
1336 }
1337 ext2fs_mark_super_dirty(fs);
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001338 pctx.blk2 = *new_block;
1339 fix_problem(ctx, (old_block ? PR_1_RELOC_FROM_TO :
1340 PR_1_RELOC_TO), &pctx);
1341 pctx.blk2 = 0;
Theodore Ts'o3839e651997-04-26 13:21:57 +00001342 for (i = 0; i < num; i++) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001343 pctx.blk = i;
1344 ext2fs_mark_block_bitmap(ctx->block_found_map, (*new_block)+i);
Theodore Ts'of3db3561997-04-26 13:34:30 +00001345 if (old_block) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001346 pctx.errcode = io_channel_read_blk(fs->io,
1347 old_block + i, 1, buf);
1348 if (pctx.errcode)
1349 fix_problem(ctx, PR_1_RELOC_READ_ERR, &pctx);
Theodore Ts'of3db3561997-04-26 13:34:30 +00001350 } else
1351 memset(buf, 0, fs->blocksize);
1352
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001353 pctx.blk = (*new_block) + i;
1354 pctx.errcode = io_channel_write_blk(fs->io, pctx.blk,
Theodore Ts'o3839e651997-04-26 13:21:57 +00001355 1, buf);
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001356 if (pctx.errcode)
1357 fix_problem(ctx, PR_1_RELOC_WRITE_ERR, &pctx);
Theodore Ts'o3839e651997-04-26 13:21:57 +00001358 }
Theodore Ts'o08b21301997-11-03 19:42:40 +00001359 ext2fs_free_mem((void **) &buf);
Theodore Ts'o3839e651997-04-26 13:21:57 +00001360}
1361
1362/*
Theodore Ts'of3db3561997-04-26 13:34:30 +00001363 * This routine gets called at the end of pass 1 if bad blocks are
1364 * detected in the superblock, group descriptors, inode_bitmaps, or
1365 * block bitmaps. At this point, all of the blocks have been mapped
1366 * out, so we can try to allocate new block(s) to replace the bad
1367 * blocks.
Theodore Ts'o3839e651997-04-26 13:21:57 +00001368 */
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001369static void handle_fs_bad_blocks(e2fsck_t ctx)
Theodore Ts'o3839e651997-04-26 13:21:57 +00001370{
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001371 ext2_filsys fs = ctx->fs;
Theodore Ts'of3db3561997-04-26 13:34:30 +00001372 int i;
1373 int first_block = fs->super->s_first_data_block;
Theodore Ts'o3839e651997-04-26 13:21:57 +00001374
1375 for (i = 0; i < fs->group_desc_count; i++) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001376 if (ctx->invalid_block_bitmap_flag[i]) {
Theodore Ts'o0c4a0722000-02-07 03:11:03 +00001377 new_table_block(ctx, first_block, i, _("block bitmap"),
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001378 1, &fs->group_desc[i].bg_block_bitmap);
Theodore Ts'o3839e651997-04-26 13:21:57 +00001379 }
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001380 if (ctx->invalid_inode_bitmap_flag[i]) {
Theodore Ts'o0c4a0722000-02-07 03:11:03 +00001381 new_table_block(ctx, first_block, i, _("inode bitmap"),
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001382 1, &fs->group_desc[i].bg_inode_bitmap);
Theodore Ts'o3839e651997-04-26 13:21:57 +00001383 }
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001384 if (ctx->invalid_inode_table_flag[i]) {
Theodore Ts'o0c4a0722000-02-07 03:11:03 +00001385 new_table_block(ctx, first_block, i, _("inode table"),
Theodore Ts'of3db3561997-04-26 13:34:30 +00001386 fs->inode_blocks_per_group,
Theodore Ts'o3839e651997-04-26 13:21:57 +00001387 &fs->group_desc[i].bg_inode_table);
Theodore Ts'o08b21301997-11-03 19:42:40 +00001388 ctx->flags |= E2F_FLAG_RESTART;
Theodore Ts'o3839e651997-04-26 13:21:57 +00001389 }
Theodore Ts'o3839e651997-04-26 13:21:57 +00001390 first_block += fs->super->s_blocks_per_group;
1391 }
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001392 ctx->invalid_bitmaps = 0;
Theodore Ts'o3839e651997-04-26 13:21:57 +00001393}
1394
1395/*
1396 * This routine marks all blocks which are used by the superblock,
1397 * group descriptors, inode bitmaps, and block bitmaps.
1398 */
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001399static void mark_table_blocks(e2fsck_t ctx)
Theodore Ts'o3839e651997-04-26 13:21:57 +00001400{
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001401 ext2_filsys fs = ctx->fs;
Theodore Ts'of3db3561997-04-26 13:34:30 +00001402 blk_t block, b;
Theodore Ts'o3839e651997-04-26 13:21:57 +00001403 int i,j;
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001404 struct problem_context pctx;
1405
1406 clear_problem_context(&pctx);
Theodore Ts'o3839e651997-04-26 13:21:57 +00001407
1408 block = fs->super->s_first_data_block;
1409 for (i = 0; i < fs->group_desc_count; i++) {
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001410 pctx.group = i;
Theodore Ts'oda2e97f1997-06-12 04:28:07 +00001411
1412 if (ext2fs_bg_has_super(fs, i)) {
1413 /*
1414 * Mark this group's copy of the superblock
1415 */
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001416 ext2fs_mark_block_bitmap(ctx->block_found_map, block);
Theodore Ts'oda2e97f1997-06-12 04:28:07 +00001417
1418 /*
1419 * Mark this group's copy of the descriptors
1420 */
1421 for (j = 0; j < fs->desc_blocks; j++) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001422 ext2fs_mark_block_bitmap(ctx->block_found_map,
Theodore Ts'oda2e97f1997-06-12 04:28:07 +00001423 block + j + 1);
Theodore Ts'oda2e97f1997-06-12 04:28:07 +00001424 }
1425 }
1426
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001427 /*
1428 * Mark the blocks used for the inode table
1429 */
1430 if (fs->group_desc[i].bg_inode_table) {
1431 for (j = 0, b = fs->group_desc[i].bg_inode_table;
1432 j < fs->inode_blocks_per_group;
1433 j++, b++) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001434 if (ext2fs_test_block_bitmap(ctx->block_found_map,
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001435 b)) {
1436 pctx.blk = b;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001437 if (fix_problem(ctx,
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001438 PR_1_ITABLE_CONFLICT, &pctx)) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001439 ctx->invalid_inode_table_flag[i]++;
1440 ctx->invalid_bitmaps++;
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001441 }
1442 } else {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001443 ext2fs_mark_block_bitmap(ctx->block_found_map,
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001444 b);
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001445 }
1446 }
1447 }
1448
Theodore Ts'o3839e651997-04-26 13:21:57 +00001449 /*
1450 * Mark block used for the block bitmap
1451 */
Theodore Ts'of3db3561997-04-26 13:34:30 +00001452 if (fs->group_desc[i].bg_block_bitmap) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001453 if (ext2fs_test_block_bitmap(ctx->block_found_map,
Theodore Ts'of3db3561997-04-26 13:34:30 +00001454 fs->group_desc[i].bg_block_bitmap)) {
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001455 pctx.blk = fs->group_desc[i].bg_block_bitmap;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001456 if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
1457 ctx->invalid_block_bitmap_flag[i]++;
1458 ctx->invalid_bitmaps++;
Theodore Ts'of3db3561997-04-26 13:34:30 +00001459 }
Theodore Ts'o50e1e101997-04-26 13:58:21 +00001460 } else {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001461 ext2fs_mark_block_bitmap(ctx->block_found_map,
Theodore Ts'of3db3561997-04-26 13:34:30 +00001462 fs->group_desc[i].bg_block_bitmap);
Theodore Ts'o50e1e101997-04-26 13:58:21 +00001463 }
1464
Theodore Ts'of3db3561997-04-26 13:34:30 +00001465 }
Theodore Ts'o3839e651997-04-26 13:21:57 +00001466 /*
1467 * Mark block used for the inode bitmap
1468 */
Theodore Ts'of3db3561997-04-26 13:34:30 +00001469 if (fs->group_desc[i].bg_inode_bitmap) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001470 if (ext2fs_test_block_bitmap(ctx->block_found_map,
Theodore Ts'of3db3561997-04-26 13:34:30 +00001471 fs->group_desc[i].bg_inode_bitmap)) {
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001472 pctx.blk = fs->group_desc[i].bg_inode_bitmap;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001473 if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
1474 ctx->invalid_inode_bitmap_flag[i]++;
1475 ctx->invalid_bitmaps++;
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001476 }
Theodore Ts'o50e1e101997-04-26 13:58:21 +00001477 } else {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001478 ext2fs_mark_block_bitmap(ctx->block_found_map,
Theodore Ts'of3db3561997-04-26 13:34:30 +00001479 fs->group_desc[i].bg_inode_bitmap);
Theodore Ts'o50e1e101997-04-26 13:58:21 +00001480 }
Theodore Ts'of3db3561997-04-26 13:34:30 +00001481 }
Theodore Ts'o3839e651997-04-26 13:21:57 +00001482 block += fs->super->s_blocks_per_group;
1483 }
1484}
1485
1486/*
Theodore Ts'oe72a9ba1999-06-25 15:40:18 +00001487 * Thes subroutines short circuits ext2fs_get_blocks and
Theodore Ts'o3839e651997-04-26 13:21:57 +00001488 * ext2fs_check_directory; we use them since we already have the inode
1489 * structure, so there's no point in letting the ext2fs library read
1490 * the inode again.
1491 */
Theodore Ts'o86c627e2001-01-11 15:12:14 +00001492static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
1493 blk_t *blocks)
Theodore Ts'o3839e651997-04-26 13:21:57 +00001494{
Theodore Ts'o54dc7ca1998-01-19 14:50:49 +00001495 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
Theodore Ts'o3839e651997-04-26 13:21:57 +00001496 int i;
1497
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001498 if (ino != ctx->stashed_ino)
Theodore Ts'o521e3681997-04-29 17:48:10 +00001499 return EXT2_ET_CALLBACK_NOTHANDLED;
1500
1501 for (i=0; i < EXT2_N_BLOCKS; i++)
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001502 blocks[i] = ctx->stashed_inode->i_block[i];
Theodore Ts'o521e3681997-04-29 17:48:10 +00001503 return 0;
Theodore Ts'o3839e651997-04-26 13:21:57 +00001504}
1505
Theodore Ts'o86c627e2001-01-11 15:12:14 +00001506static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
Theodore Ts'oe72a9ba1999-06-25 15:40:18 +00001507 struct ext2_inode *inode)
Theodore Ts'o1e3472c1997-04-29 14:53:37 +00001508{
Theodore Ts'o54dc7ca1998-01-19 14:50:49 +00001509 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001510
1511 if (ino != ctx->stashed_ino)
Theodore Ts'o1e3472c1997-04-29 14:53:37 +00001512 return EXT2_ET_CALLBACK_NOTHANDLED;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001513 *inode = *ctx->stashed_inode;
Theodore Ts'o1e3472c1997-04-29 14:53:37 +00001514 return 0;
1515}
1516
Theodore Ts'o86c627e2001-01-11 15:12:14 +00001517static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
Theodore Ts'o1e3472c1997-04-29 14:53:37 +00001518 struct ext2_inode *inode)
1519{
Theodore Ts'o54dc7ca1998-01-19 14:50:49 +00001520 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001521
1522 if (ino == ctx->stashed_ino)
1523 *ctx->stashed_inode = *inode;
Theodore Ts'o1e3472c1997-04-29 14:53:37 +00001524 return EXT2_ET_CALLBACK_NOTHANDLED;
1525}
1526
Theodore Ts'o86c627e2001-01-11 15:12:14 +00001527static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
Theodore Ts'o3839e651997-04-26 13:21:57 +00001528{
Theodore Ts'o54dc7ca1998-01-19 14:50:49 +00001529 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001530
1531 if (ino != ctx->stashed_ino)
1532 return EXT2_ET_CALLBACK_NOTHANDLED;
1533
1534 if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
Theodore Ts'o291c9041997-10-31 06:17:08 +00001535 return EXT2_ET_NO_DIRECTORY;
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001536 return 0;
Theodore Ts'o3839e651997-04-26 13:21:57 +00001537}
Theodore Ts'oe72a9ba1999-06-25 15:40:18 +00001538
1539void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
1540{
1541 ext2_filsys fs = ctx->fs;
1542
1543 if (bool) {
1544 fs->get_blocks = pass1_get_blocks;
1545 fs->check_directory = pass1_check_directory;
1546 fs->read_inode = pass1_read_inode;
1547 fs->write_inode = pass1_write_inode;
1548 ctx->stashed_ino = 0;
1549 } else {
1550 fs->get_blocks = 0;
1551 fs->check_directory = 0;
1552 fs->read_inode = 0;
1553 fs->write_inode = 0;
1554 }
1555}
1556
1557