Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1 | /* |
| 2 | * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table |
| 3 | * |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 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% |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 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 have bad fields. (inode_bad_map) |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 23 | * - A bitmap of which inodes are in bad blocks. (inode_bb_map) |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 24 | * - A bitmap of which blocks are in use. (block_found_map) |
| 25 | * - A bitmap of which blocks are in use by two inodes (block_dup_map) |
| 26 | * - The data blocks of the directory inodes. (dir_map) |
| 27 | * |
| 28 | * Pass 1 is designed to stash away enough information so that the |
| 29 | * other passes should not need to read in the inode information |
| 30 | * during the normal course of a filesystem check. (Althogh if an |
| 31 | * inconsistency is detected, other passes may need to read in an |
| 32 | * inode to fix it.) |
| 33 | * |
| 34 | * Note that pass 1B will be invoked if there are any duplicate blocks |
| 35 | * found. |
| 36 | */ |
| 37 | |
| 38 | #include <time.h> |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 39 | #ifdef HAVE_ERRNO_H |
| 40 | #include <errno.h> |
| 41 | #endif |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 42 | |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 43 | #include "e2fsck.h" |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 44 | #include "problem.h" |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 45 | |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 46 | #ifdef NO_INLINE_FUNCS |
| 47 | #define _INLINE_ |
| 48 | #else |
| 49 | #define _INLINE_ inline |
| 50 | #endif |
| 51 | |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 52 | static int process_block(ext2_filsys fs, blk_t *blocknr, |
Theodore Ts'o | 246501c | 1998-03-24 16:22:38 +0000 | [diff] [blame^] | 53 | blkcnt_t blockcnt, blk_t ref_blk, |
Theodore Ts'o | 54dc7ca | 1998-01-19 14:50:49 +0000 | [diff] [blame] | 54 | int ref_offset, void *priv_data); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 55 | static int process_bad_block(ext2_filsys fs, blk_t *block_nr, |
Theodore Ts'o | 246501c | 1998-03-24 16:22:38 +0000 | [diff] [blame^] | 56 | blkcnt_t blockcnt, blk_t ref_blk, |
Theodore Ts'o | 54dc7ca | 1998-01-19 14:50:49 +0000 | [diff] [blame] | 57 | int ref_offset, void *priv_data); |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 58 | static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 59 | char *block_buf); |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 60 | static void mark_table_blocks(e2fsck_t ctx); |
| 61 | static void alloc_bad_map(e2fsck_t ctx); |
| 62 | static void alloc_bb_map(e2fsck_t ctx); |
| 63 | static void handle_fs_bad_blocks(e2fsck_t ctx); |
| 64 | static void process_inodes(e2fsck_t ctx, char *block_buf); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 65 | static int process_inode_cmp(const void *a, const void *b); |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 66 | static errcode_t scan_callback(ext2_filsys fs, ext2_inode_scan scan, |
Theodore Ts'o | 54dc7ca | 1998-01-19 14:50:49 +0000 | [diff] [blame] | 67 | dgrp_t group, void * priv_data); |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 68 | /* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */ |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 69 | |
| 70 | struct process_block_struct { |
Theodore Ts'o | 246501c | 1998-03-24 16:22:38 +0000 | [diff] [blame^] | 71 | ino_t ino; |
| 72 | int is_dir:1, clear:1, suppress:1, fragmented:1; |
| 73 | blk_t num_blocks; |
| 74 | blkcnt_t last_block; |
| 75 | int num_illegal_blocks; |
| 76 | blk_t previous_block; |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 77 | struct ext2_inode *inode; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 78 | struct problem_context *pctx; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 79 | e2fsck_t ctx; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 80 | }; |
| 81 | |
| 82 | struct process_inode_block { |
| 83 | ino_t ino; |
| 84 | struct ext2_inode inode; |
| 85 | }; |
| 86 | |
Theodore Ts'o | f8188ff | 1997-11-14 05:23:04 +0000 | [diff] [blame] | 87 | struct scan_callback_struct { |
| 88 | e2fsck_t ctx; |
| 89 | char *block_buf; |
| 90 | }; |
| 91 | |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 92 | /* |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 93 | * For the inodes to process list. |
| 94 | */ |
| 95 | static struct process_inode_block *inodes_to_process; |
| 96 | static int process_inode_count; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 97 | |
Theodore Ts'o | 246501c | 1998-03-24 16:22:38 +0000 | [diff] [blame^] | 98 | #define EXT2_BPP(bits) (1UL << ((bits) - 2)) |
| 99 | |
| 100 | #define EXT2_MAX_SIZE(bits) \ |
| 101 | (((EXT2_NDIR_BLOCKS + EXT2_BPP(bits) + \ |
| 102 | EXT2_BPP(bits) * EXT2_BPP(bits) + \ |
| 103 | EXT2_BPP(bits) * EXT2_BPP(bits) * EXT2_BPP(bits)) * \ |
| 104 | (1UL << bits)) - 1) |
| 105 | |
| 106 | static long long ext2_max_sizes[] = { |
| 107 | EXT2_MAX_SIZE(10), EXT2_MAX_SIZE(11), EXT2_MAX_SIZE(12), EXT2_MAX_SIZE(13) |
| 108 | }; |
| 109 | |
| 110 | #undef EXT2_BPP |
| 111 | |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 112 | /* |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 113 | * Free all memory allocated by pass1 in preparation for restarting |
| 114 | * things. |
| 115 | */ |
| 116 | static void unwind_pass1(ext2_filsys fs) |
| 117 | { |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 118 | ext2fs_free_mem((void **) &inodes_to_process); |
| 119 | inodes_to_process = 0; |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 120 | } |
| 121 | |
Theodore Ts'o | 7cf73dc | 1997-08-14 17:17:16 +0000 | [diff] [blame] | 122 | /* |
| 123 | * Check to make sure a device inode is real. Returns 1 if the device |
| 124 | * checks out, 0 if not. |
| 125 | */ |
| 126 | int e2fsck_pass1_check_device_inode(struct ext2_inode *inode) |
| 127 | { |
| 128 | int i; |
| 129 | |
Theodore Ts'o | 7fdfabd | 1997-11-24 11:51:17 +0000 | [diff] [blame] | 130 | /* |
| 131 | * We should be able to do the test below all the time, but |
| 132 | * because the kernel doesn't forcibly clear the device |
| 133 | * inode's additional i_block fields, there are some rare |
| 134 | * occasions when a legitimate device inode will have non-zero |
| 135 | * additional i_block fields. So for now, we only complain |
| 136 | * when the immutable flag is set, which should never happen |
| 137 | * for devices. (And that's when the problem is caused, since |
| 138 | * you can't set or clear immutable flags for devices.) Once |
| 139 | * the kernel has been fixed we can change this... |
| 140 | */ |
| 141 | if (inode->i_flags & EXT2_IMMUTABLE_FL) { |
| 142 | for (i=4; i < EXT2_N_BLOCKS; i++) |
| 143 | if (inode->i_block[i]) |
| 144 | return 0; |
| 145 | } |
Theodore Ts'o | 7cf73dc | 1997-08-14 17:17:16 +0000 | [diff] [blame] | 146 | return 1; |
| 147 | } |
| 148 | |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 149 | void e2fsck_pass1(e2fsck_t ctx) |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 150 | { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 151 | ext2_filsys fs = ctx->fs; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 152 | ino_t ino; |
| 153 | struct ext2_inode inode; |
| 154 | ext2_inode_scan scan; |
| 155 | char *block_buf; |
Theodore Ts'o | 8bf191e | 1997-10-20 01:38:32 +0000 | [diff] [blame] | 156 | #ifdef RESOURCE_TRACK |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 157 | struct resource_track rtrack; |
Theodore Ts'o | 8bf191e | 1997-10-20 01:38:32 +0000 | [diff] [blame] | 158 | #endif |
Theodore Ts'o | 1e3472c | 1997-04-29 14:53:37 +0000 | [diff] [blame] | 159 | unsigned char frag, fsize; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 160 | struct problem_context pctx; |
Theodore Ts'o | f8188ff | 1997-11-14 05:23:04 +0000 | [diff] [blame] | 161 | struct scan_callback_struct scan_struct; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 162 | |
Theodore Ts'o | 8bf191e | 1997-10-20 01:38:32 +0000 | [diff] [blame] | 163 | #ifdef RESOURCE_TRACK |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 164 | init_resource_track(&rtrack); |
Theodore Ts'o | 8bf191e | 1997-10-20 01:38:32 +0000 | [diff] [blame] | 165 | #endif |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 166 | clear_problem_context(&pctx); |
| 167 | |
| 168 | if (!(ctx->options & E2F_OPT_PREEN)) |
| 169 | fix_problem(ctx, PR_1_PASS_HEADER, &pctx); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 170 | |
| 171 | #ifdef MTRACE |
| 172 | mtrace_print("Pass 1"); |
| 173 | #endif |
| 174 | |
| 175 | /* |
| 176 | * Allocate bitmaps structures |
| 177 | */ |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 178 | pctx.errcode = ext2fs_allocate_inode_bitmap(fs, "in-use inode map", |
| 179 | &ctx->inode_used_map); |
| 180 | if (pctx.errcode) { |
| 181 | pctx.num = 1; |
| 182 | fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx); |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 183 | ctx->flags |= E2F_FLAG_ABORT; |
| 184 | return; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 185 | } |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 186 | pctx.errcode = ext2fs_allocate_inode_bitmap(fs, "directory inode map", |
| 187 | &ctx->inode_dir_map); |
| 188 | if (pctx.errcode) { |
| 189 | pctx.num = 2; |
| 190 | fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx); |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 191 | ctx->flags |= E2F_FLAG_ABORT; |
| 192 | return; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 193 | } |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 194 | pctx.errcode = ext2fs_allocate_block_bitmap(fs, "in-use block map", |
| 195 | &ctx->block_found_map); |
| 196 | if (pctx.errcode) { |
| 197 | pctx.num = 1; |
| 198 | fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx); |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 199 | ctx->flags |= E2F_FLAG_ABORT; |
| 200 | return; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 201 | } |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 202 | pctx.errcode = ext2fs_allocate_block_bitmap(fs, "illegal block map", |
| 203 | &ctx->block_illegal_map); |
| 204 | if (pctx.errcode) { |
| 205 | pctx.num = 2; |
| 206 | fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx); |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 207 | ctx->flags |= E2F_FLAG_ABORT; |
| 208 | return; |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 209 | } |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 210 | pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0, |
| 211 | &ctx->inode_link_info); |
| 212 | if (pctx.errcode) { |
| 213 | fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx); |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 214 | ctx->flags |= E2F_FLAG_ABORT; |
| 215 | return; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 216 | } |
Theodore Ts'o | 54dc7ca | 1998-01-19 14:50:49 +0000 | [diff] [blame] | 217 | inodes_to_process = (struct process_inode_block *) |
| 218 | e2fsck_allocate_memory(ctx, |
| 219 | (ctx->process_inode_size * |
| 220 | sizeof(struct process_inode_block)), |
| 221 | "array of inodes to process"); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 222 | process_inode_count = 0; |
| 223 | |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 224 | pctx.errcode = ext2fs_init_dblist(fs, 0); |
| 225 | if (pctx.errcode) { |
| 226 | fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx); |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 227 | ctx->flags |= E2F_FLAG_ABORT; |
| 228 | return; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 229 | } |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 230 | |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 231 | mark_table_blocks(ctx); |
Theodore Ts'o | 54dc7ca | 1998-01-19 14:50:49 +0000 | [diff] [blame] | 232 | block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3, |
| 233 | "block interate buffer"); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 234 | fs->get_blocks = pass1_get_blocks; |
| 235 | fs->check_directory = pass1_check_directory; |
Theodore Ts'o | 1e3472c | 1997-04-29 14:53:37 +0000 | [diff] [blame] | 236 | fs->read_inode = pass1_read_inode; |
| 237 | fs->write_inode = pass1_write_inode; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 238 | ehandler_operation("doing inode scan"); |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 239 | pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks, |
| 240 | &scan); |
| 241 | if (pctx.errcode) { |
| 242 | fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx); |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 243 | ctx->flags |= E2F_FLAG_ABORT; |
| 244 | return; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 245 | } |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 246 | ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0); |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 247 | pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode); |
| 248 | if (pctx.errcode) { |
| 249 | fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx); |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 250 | ctx->flags |= E2F_FLAG_ABORT; |
| 251 | return; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 252 | } |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 253 | ctx->stashed_inode = &inode; |
Theodore Ts'o | f8188ff | 1997-11-14 05:23:04 +0000 | [diff] [blame] | 254 | scan_struct.ctx = ctx; |
| 255 | scan_struct.block_buf = block_buf; |
| 256 | ext2fs_set_inode_callback(scan, scan_callback, &scan_struct); |
| 257 | if (ctx->progress) |
Theodore Ts'o | a02ce9d | 1998-02-24 20:22:23 +0000 | [diff] [blame] | 258 | if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count)) |
| 259 | return; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 260 | while (ino) { |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 261 | pctx.ino = ino; |
| 262 | pctx.inode = &inode; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 263 | ctx->stashed_ino = ino; |
| 264 | if (inode.i_links_count) { |
| 265 | pctx.errcode = ext2fs_icount_store(ctx->inode_link_info, |
| 266 | ino, inode.i_links_count); |
| 267 | if (pctx.errcode) { |
| 268 | pctx.num = inode.i_links_count; |
| 269 | fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx); |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 270 | ctx->flags |= E2F_FLAG_ABORT; |
| 271 | return; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 272 | } |
| 273 | } |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 274 | if (ino == EXT2_BAD_INO) { |
| 275 | struct process_block_struct pb; |
| 276 | |
| 277 | pb.ino = EXT2_BAD_INO; |
| 278 | pb.num_blocks = pb.last_block = 0; |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 279 | pb.num_illegal_blocks = 0; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 280 | pb.suppress = 0; pb.clear = 0; pb.is_dir = 0; |
Theodore Ts'o | 74becf3 | 1997-04-26 14:37:06 +0000 | [diff] [blame] | 281 | pb.fragmented = 0; |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 282 | pb.inode = &inode; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 283 | pb.pctx = &pctx; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 284 | pb.ctx = ctx; |
| 285 | pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, |
| 286 | block_buf, process_bad_block, &pb); |
| 287 | if (pctx.errcode) { |
| 288 | fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx); |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 289 | ctx->flags |= E2F_FLAG_ABORT; |
| 290 | return; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 291 | } |
| 292 | ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino); |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 293 | clear_problem_context(&pctx); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 294 | goto next; |
| 295 | } |
| 296 | if (ino == EXT2_ROOT_INO) { |
| 297 | /* |
| 298 | * Make sure the root inode is a directory; if |
| 299 | * not, offer to clear it. It will be |
| 300 | * regnerated in pass #3. |
| 301 | */ |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 302 | if (!LINUX_S_ISDIR(inode.i_mode)) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 303 | if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) { |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 304 | inode.i_dtime = time(0); |
| 305 | inode.i_links_count = 0; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 306 | ext2fs_icount_store(ctx->inode_link_info, |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 307 | ino, 0); |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 308 | e2fsck_write_inode(ctx, ino, &inode, |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 309 | "pass1"); |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 310 | } |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 311 | } |
| 312 | /* |
| 313 | * If dtime is set, offer to clear it. mke2fs |
| 314 | * version 0.2b created filesystems with the |
| 315 | * dtime field set for the root and lost+found |
| 316 | * directories. We won't worry about |
| 317 | * /lost+found, since that can be regenerated |
| 318 | * easily. But we will fix the root directory |
| 319 | * as a special case. |
| 320 | */ |
| 321 | if (inode.i_dtime && inode.i_links_count) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 322 | if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) { |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 323 | inode.i_dtime = 0; |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 324 | e2fsck_write_inode(ctx, ino, &inode, |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 325 | "pass1"); |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 326 | } |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 327 | } |
| 328 | } |
Theodore Ts'o | 5c57647 | 1997-04-29 15:29:49 +0000 | [diff] [blame] | 329 | if (ino == EXT2_BOOT_LOADER_INO) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 330 | ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino); |
| 331 | check_blocks(ctx, &pctx, block_buf); |
Theodore Ts'o | 5c57647 | 1997-04-29 15:29:49 +0000 | [diff] [blame] | 332 | goto next; |
| 333 | } |
Theodore Ts'o | 7f88b04 | 1997-04-26 14:48:50 +0000 | [diff] [blame] | 334 | if ((ino != EXT2_ROOT_INO) && |
| 335 | (ino < EXT2_FIRST_INODE(fs->super))) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 336 | ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino); |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 337 | if (inode.i_mode != 0) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 338 | if (fix_problem(ctx, |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 339 | PR_1_RESERVED_BAD_MODE, &pctx)) { |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 340 | inode.i_mode = 0; |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 341 | e2fsck_write_inode(ctx, ino, &inode, |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 342 | "pass1"); |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 343 | } |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 344 | } |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 345 | check_blocks(ctx, &pctx, block_buf); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 346 | goto next; |
| 347 | } |
| 348 | /* |
| 349 | * This code assumes that deleted inodes have |
| 350 | * i_links_count set to 0. |
| 351 | */ |
| 352 | if (!inode.i_links_count) { |
| 353 | if (!inode.i_dtime && inode.i_mode) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 354 | if (fix_problem(ctx, |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 355 | PR_1_ZERO_DTIME, &pctx)) { |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 356 | inode.i_dtime = time(0); |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 357 | e2fsck_write_inode(ctx, ino, &inode, |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 358 | "pass1"); |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 359 | } |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 360 | } |
| 361 | goto next; |
| 362 | } |
| 363 | /* |
Theodore Ts'o | 1e3472c | 1997-04-29 14:53:37 +0000 | [diff] [blame] | 364 | * n.b. 0.3c ext2fs code didn't clear i_links_count for |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 365 | * deleted files. Oops. |
Theodore Ts'o | 1e3472c | 1997-04-29 14:53:37 +0000 | [diff] [blame] | 366 | * |
| 367 | * Since all new ext2 implementations get this right, |
| 368 | * we now assume that the case of non-zero |
| 369 | * i_links_count and non-zero dtime means that we |
| 370 | * should keep the file, not delete it. |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 371 | * |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 372 | */ |
| 373 | if (inode.i_dtime) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 374 | if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) { |
Theodore Ts'o | 1e3472c | 1997-04-29 14:53:37 +0000 | [diff] [blame] | 375 | inode.i_dtime = 0; |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 376 | e2fsck_write_inode(ctx, ino, &inode, "pass1"); |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 377 | } |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 378 | } |
| 379 | |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 380 | ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino); |
Theodore Ts'o | 1e3472c | 1997-04-29 14:53:37 +0000 | [diff] [blame] | 381 | switch (fs->super->s_creator_os) { |
| 382 | case EXT2_OS_LINUX: |
| 383 | frag = inode.osd2.linux2.l_i_frag; |
| 384 | fsize = inode.osd2.linux2.l_i_fsize; |
| 385 | break; |
| 386 | case EXT2_OS_HURD: |
| 387 | frag = inode.osd2.hurd2.h_i_frag; |
| 388 | fsize = inode.osd2.hurd2.h_i_fsize; |
| 389 | break; |
| 390 | case EXT2_OS_MASIX: |
| 391 | frag = inode.osd2.masix2.m_i_frag; |
| 392 | fsize = inode.osd2.masix2.m_i_fsize; |
| 393 | break; |
| 394 | default: |
| 395 | frag = fsize = 0; |
| 396 | } |
| 397 | |
| 398 | if (inode.i_faddr || frag || fsize |
Theodore Ts'o | 246501c | 1998-03-24 16:22:38 +0000 | [diff] [blame^] | 399 | || inode.i_file_acl || |
| 400 | (LINUX_S_ISDIR(inode.i_mode) && inode.i_dir_acl)) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 401 | if (!ctx->inode_bad_map) |
| 402 | alloc_bad_map(ctx); |
| 403 | ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 404 | } |
| 405 | |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 406 | if (LINUX_S_ISDIR(inode.i_mode)) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 407 | ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino); |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 408 | e2fsck_add_dir_info(ctx, ino, 0); |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 409 | ctx->fs_directory_count++; |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 410 | } else if (LINUX_S_ISREG (inode.i_mode)) |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 411 | ctx->fs_regular_count++; |
Theodore Ts'o | 7cf73dc | 1997-08-14 17:17:16 +0000 | [diff] [blame] | 412 | else if (LINUX_S_ISCHR (inode.i_mode) && |
| 413 | e2fsck_pass1_check_device_inode(&inode)) |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 414 | ctx->fs_chardev_count++; |
Theodore Ts'o | 7cf73dc | 1997-08-14 17:17:16 +0000 | [diff] [blame] | 415 | else if (LINUX_S_ISBLK (inode.i_mode) && |
| 416 | e2fsck_pass1_check_device_inode(&inode)) |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 417 | ctx->fs_blockdev_count++; |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 418 | else if (LINUX_S_ISLNK (inode.i_mode)) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 419 | ctx->fs_symlinks_count++; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 420 | if (!inode.i_blocks) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 421 | ctx->fs_fast_symlinks_count++; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 422 | goto next; |
| 423 | } |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 424 | } |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 425 | else if (LINUX_S_ISFIFO (inode.i_mode)) |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 426 | ctx->fs_fifo_count++; |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 427 | else if (LINUX_S_ISSOCK (inode.i_mode)) |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 428 | ctx->fs_sockets_count++; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 429 | else { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 430 | if (!ctx->inode_bad_map) |
| 431 | alloc_bad_map(ctx); |
| 432 | ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 433 | } |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 434 | if (inode.i_block[EXT2_IND_BLOCK]) |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 435 | ctx->fs_ind_count++; |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 436 | if (inode.i_block[EXT2_DIND_BLOCK]) |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 437 | ctx->fs_dind_count++; |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 438 | if (inode.i_block[EXT2_TIND_BLOCK]) |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 439 | ctx->fs_tind_count++; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 440 | if (inode.i_block[EXT2_IND_BLOCK] || |
| 441 | inode.i_block[EXT2_DIND_BLOCK] || |
| 442 | inode.i_block[EXT2_TIND_BLOCK]) { |
| 443 | inodes_to_process[process_inode_count].ino = ino; |
| 444 | inodes_to_process[process_inode_count].inode = inode; |
| 445 | process_inode_count++; |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 446 | } else |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 447 | check_blocks(ctx, &pctx, block_buf); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 448 | |
Theodore Ts'o | a02ce9d | 1998-02-24 20:22:23 +0000 | [diff] [blame] | 449 | if (ctx->flags & E2F_FLAG_SIGNAL_MASK) |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 450 | return; |
| 451 | |
| 452 | if (process_inode_count >= ctx->process_inode_size) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 453 | process_inodes(ctx, block_buf); |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 454 | |
Theodore Ts'o | a02ce9d | 1998-02-24 20:22:23 +0000 | [diff] [blame] | 455 | if (ctx->flags & E2F_FLAG_SIGNAL_MASK) |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 456 | return; |
| 457 | } |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 458 | next: |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 459 | pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode); |
Theodore Ts'o | 2df1f6a | 1998-02-27 05:03:48 +0000 | [diff] [blame] | 460 | if (ctx->flags & E2F_FLAG_SIGNAL_MASK) |
| 461 | return; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 462 | if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) { |
| 463 | if (!ctx->inode_bb_map) |
| 464 | alloc_bb_map(ctx); |
| 465 | ext2fs_mark_inode_bitmap(ctx->inode_bb_map, ino); |
| 466 | ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino); |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 467 | goto next; |
| 468 | } |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 469 | if (pctx.errcode) { |
| 470 | fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx); |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 471 | ctx->flags |= E2F_FLAG_ABORT; |
| 472 | return; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 473 | } |
| 474 | } |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 475 | process_inodes(ctx, block_buf); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 476 | ext2fs_close_inode_scan(scan); |
| 477 | ehandler_operation(0); |
| 478 | |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 479 | if (ctx->invalid_bitmaps) |
| 480 | handle_fs_bad_blocks(ctx); |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 481 | |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 482 | if (ctx->flags & E2F_FLAG_RESTART) { |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 483 | unwind_pass1(fs); |
| 484 | goto endit; |
| 485 | } |
| 486 | |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 487 | if (ctx->block_dup_map) { |
| 488 | if (ctx->options & E2F_OPT_PREEN) { |
| 489 | clear_problem_context(&pctx); |
| 490 | fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 491 | } |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 492 | e2fsck_pass1_dupblocks(ctx, block_buf); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 493 | } |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 494 | ext2fs_free_mem((void **) &inodes_to_process); |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 495 | endit: |
Theodore Ts'o | 1e3472c | 1997-04-29 14:53:37 +0000 | [diff] [blame] | 496 | fs->get_blocks = 0; |
| 497 | fs->check_directory = 0; |
| 498 | fs->read_inode = 0; |
| 499 | fs->write_inode = 0; |
| 500 | |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 501 | ext2fs_free_mem((void **) &block_buf); |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 502 | ext2fs_free_block_bitmap(ctx->block_illegal_map); |
| 503 | ctx->block_illegal_map = 0; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 504 | |
Theodore Ts'o | 246501c | 1998-03-24 16:22:38 +0000 | [diff] [blame^] | 505 | if (ctx->large_files && |
| 506 | !(fs->super->s_feature_ro_compat & |
| 507 | EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) { |
| 508 | if (fix_problem(ctx, PR_1_FEATURE_LARGE_FILES, &pctx)) { |
| 509 | fs->super->s_feature_ro_compat |= |
| 510 | EXT2_FEATURE_RO_COMPAT_LARGE_FILE; |
| 511 | ext2fs_mark_super_dirty(fs); |
| 512 | } |
| 513 | } else if (!ctx->large_files && |
| 514 | (fs->super->s_feature_ro_compat & |
| 515 | EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) { |
| 516 | if (fs->flags & EXT2_FLAG_RW) { |
| 517 | fs->super->s_feature_ro_compat &= |
| 518 | ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE; |
| 519 | ext2fs_mark_super_dirty(fs); |
| 520 | } |
| 521 | } |
| 522 | |
Theodore Ts'o | 8bf191e | 1997-10-20 01:38:32 +0000 | [diff] [blame] | 523 | #ifdef RESOURCE_TRACK |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 524 | if (ctx->options & E2F_OPT_TIME2) |
| 525 | print_resource_track("Pass 1", &rtrack); |
Theodore Ts'o | 8bf191e | 1997-10-20 01:38:32 +0000 | [diff] [blame] | 526 | #endif |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 527 | } |
| 528 | |
| 529 | /* |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 530 | * When the inode_scan routines call this callback at the end of the |
| 531 | * glock group, call process_inodes. |
| 532 | */ |
| 533 | static errcode_t scan_callback(ext2_filsys fs, ext2_inode_scan scan, |
Theodore Ts'o | 54dc7ca | 1998-01-19 14:50:49 +0000 | [diff] [blame] | 534 | dgrp_t group, void * priv_data) |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 535 | { |
Theodore Ts'o | 54dc7ca | 1998-01-19 14:50:49 +0000 | [diff] [blame] | 536 | struct scan_callback_struct *scan_struct; |
Theodore Ts'o | f8188ff | 1997-11-14 05:23:04 +0000 | [diff] [blame] | 537 | e2fsck_t ctx; |
| 538 | |
Theodore Ts'o | 54dc7ca | 1998-01-19 14:50:49 +0000 | [diff] [blame] | 539 | scan_struct = (struct scan_callback_struct *) priv_data; |
Theodore Ts'o | f8188ff | 1997-11-14 05:23:04 +0000 | [diff] [blame] | 540 | ctx = scan_struct->ctx; |
| 541 | |
Theodore Ts'o | 54dc7ca | 1998-01-19 14:50:49 +0000 | [diff] [blame] | 542 | process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf); |
Theodore Ts'o | f8188ff | 1997-11-14 05:23:04 +0000 | [diff] [blame] | 543 | |
| 544 | if (ctx->progress) |
Theodore Ts'o | a02ce9d | 1998-02-24 20:22:23 +0000 | [diff] [blame] | 545 | if ((ctx->progress)(ctx, 1, group+1, |
| 546 | ctx->fs->group_desc_count)) |
| 547 | return EXT2_ET_CANCEL_REQUESTED; |
Theodore Ts'o | f8188ff | 1997-11-14 05:23:04 +0000 | [diff] [blame] | 548 | |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 549 | return 0; |
| 550 | } |
| 551 | |
| 552 | /* |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 553 | * Process the inodes in the "inodes to process" list. |
| 554 | */ |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 555 | static void process_inodes(e2fsck_t ctx, char *block_buf) |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 556 | { |
| 557 | int i; |
| 558 | struct ext2_inode *old_stashed_inode; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 559 | ino_t old_stashed_ino; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 560 | const char *old_operation; |
| 561 | char buf[80]; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 562 | struct problem_context pctx; |
| 563 | |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 564 | #if 0 |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 565 | printf("begin process_inodes: "); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 566 | #endif |
| 567 | old_operation = ehandler_operation(0); |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 568 | old_stashed_inode = ctx->stashed_inode; |
| 569 | old_stashed_ino = ctx->stashed_ino; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 570 | qsort(inodes_to_process, process_inode_count, |
| 571 | sizeof(struct process_inode_block), process_inode_cmp); |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 572 | clear_problem_context(&pctx); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 573 | for (i=0; i < process_inode_count; i++) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 574 | pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode; |
| 575 | pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 576 | |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 577 | #if 0 |
| 578 | printf("%u ", pctx.ino); |
| 579 | #endif |
| 580 | sprintf(buf, "reading indirect blocks of inode %lu", pctx.ino); |
| 581 | ehandler_operation(buf); |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 582 | check_blocks(ctx, &pctx, block_buf); |
Theodore Ts'o | a02ce9d | 1998-02-24 20:22:23 +0000 | [diff] [blame] | 583 | if (ctx->flags & E2F_FLAG_SIGNAL_MASK) |
Theodore Ts'o | 2df1f6a | 1998-02-27 05:03:48 +0000 | [diff] [blame] | 584 | break; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 585 | } |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 586 | ctx->stashed_inode = old_stashed_inode; |
| 587 | ctx->stashed_ino = old_stashed_ino; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 588 | process_inode_count = 0; |
| 589 | #if 0 |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 590 | printf("end process inodes\n"); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 591 | #endif |
| 592 | ehandler_operation(old_operation); |
| 593 | } |
| 594 | |
| 595 | static int process_inode_cmp(const void *a, const void *b) |
| 596 | { |
| 597 | const struct process_inode_block *ib_a = |
| 598 | (const struct process_inode_block *) a; |
| 599 | const struct process_inode_block *ib_b = |
| 600 | (const struct process_inode_block *) b; |
| 601 | |
| 602 | return (ib_a->inode.i_block[EXT2_IND_BLOCK] - |
| 603 | ib_b->inode.i_block[EXT2_IND_BLOCK]); |
| 604 | } |
| 605 | |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 606 | /* |
| 607 | * This procedure will allocate the inode bad map table |
| 608 | */ |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 609 | static void alloc_bad_map(e2fsck_t ctx) |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 610 | { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 611 | struct problem_context pctx; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 612 | |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 613 | clear_problem_context(&pctx); |
| 614 | |
| 615 | pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs, "bad inode map", |
| 616 | &ctx->inode_bad_map); |
| 617 | if (pctx.errcode) { |
| 618 | pctx.num = 3; |
| 619 | fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx); |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 620 | /* Should never get here */ |
| 621 | ctx->flags |= E2F_FLAG_ABORT; |
| 622 | return; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 623 | } |
| 624 | } |
| 625 | |
| 626 | /* |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 627 | * This procedure will allocate the inode "bb" (badblock) map table |
| 628 | */ |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 629 | static void alloc_bb_map(e2fsck_t ctx) |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 630 | { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 631 | struct problem_context pctx; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 632 | |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 633 | clear_problem_context(&pctx); |
| 634 | pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs, |
| 635 | "inode in bad block map", |
| 636 | &ctx->inode_bb_map); |
| 637 | if (pctx.errcode) { |
| 638 | pctx.num = 4; |
| 639 | fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx); |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 640 | /* Should never get here */ |
| 641 | ctx->flags |= E2F_FLAG_ABORT; |
| 642 | return; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 643 | } |
| 644 | } |
| 645 | |
| 646 | /* |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 647 | * Marks a block as in use, setting the dup_map if it's been set |
| 648 | * already. Called by process_block and process_bad_block. |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 649 | * |
| 650 | * WARNING: Assumes checks have already been done to make sure block |
| 651 | * is valid. This is true in both process_block and process_bad_block. |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 652 | */ |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 653 | static _INLINE_ void mark_block_used(e2fsck_t ctx, blk_t block) |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 654 | { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 655 | struct problem_context pctx; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 656 | |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 657 | clear_problem_context(&pctx); |
| 658 | |
| 659 | if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) { |
| 660 | if (!ctx->block_dup_map) { |
| 661 | pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs, |
| 662 | "multiply claimed block map", |
| 663 | &ctx->block_dup_map); |
| 664 | if (pctx.errcode) { |
| 665 | pctx.num = 3; |
| 666 | fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, |
| 667 | &pctx); |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 668 | /* Should never get here */ |
| 669 | ctx->flags |= E2F_FLAG_ABORT; |
| 670 | return; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 671 | } |
| 672 | } |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 673 | ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 674 | } else { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 675 | ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 676 | } |
| 677 | } |
| 678 | |
| 679 | /* |
| 680 | * This subroutine is called on each inode to account for all of the |
| 681 | * blocks used by that inode. |
| 682 | */ |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 683 | static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 684 | char *block_buf) |
| 685 | { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 686 | ext2_filsys fs = ctx->fs; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 687 | struct process_block_struct pb; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 688 | ino_t ino = pctx->ino; |
| 689 | struct ext2_inode *inode = pctx->inode; |
Theodore Ts'o | 246501c | 1998-03-24 16:22:38 +0000 | [diff] [blame^] | 690 | int bad_size = 0; |
| 691 | __u64 size; |
| 692 | struct ext2fs_sb *sb; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 693 | |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 694 | if (!ext2fs_inode_has_valid_blocks(pctx->inode)) |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 695 | return; |
| 696 | |
| 697 | pb.ino = ino; |
| 698 | pb.num_blocks = pb.last_block = 0; |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 699 | pb.num_illegal_blocks = 0; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 700 | pb.suppress = 0; pb.clear = 0; |
Theodore Ts'o | 74becf3 | 1997-04-26 14:37:06 +0000 | [diff] [blame] | 701 | pb.fragmented = 0; |
| 702 | pb.previous_block = 0; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 703 | pb.is_dir = LINUX_S_ISDIR(pctx->inode->i_mode); |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 704 | pb.inode = inode; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 705 | pb.pctx = pctx; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 706 | pb.ctx = ctx; |
| 707 | pctx->ino = ino; |
| 708 | pctx->errcode = ext2fs_block_iterate2(fs, ino, |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 709 | pb.is_dir ? BLOCK_FLAG_HOLE : 0, |
| 710 | block_buf, process_block, &pb); |
Theodore Ts'o | a02ce9d | 1998-02-24 20:22:23 +0000 | [diff] [blame] | 711 | if (ctx->flags & E2F_FLAG_SIGNAL_MASK) |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 712 | return; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 713 | end_problem_latch(ctx, PR_LATCH_BLOCK); |
| 714 | if (pctx->errcode) |
| 715 | fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 716 | |
Theodore Ts'o | 74becf3 | 1997-04-26 14:37:06 +0000 | [diff] [blame] | 717 | if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group) |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 718 | ctx->fs_fragmented++; |
Theodore Ts'o | 74becf3 | 1997-04-26 14:37:06 +0000 | [diff] [blame] | 719 | |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 720 | if (pb.clear) { |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 721 | e2fsck_read_inode(ctx, ino, inode, "check_blocks"); |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 722 | inode->i_links_count = 0; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 723 | ext2fs_icount_store(ctx->inode_link_info, ino, 0); |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 724 | inode->i_dtime = time(0); |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 725 | e2fsck_write_inode(ctx, ino, inode, "check_blocks"); |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 726 | ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino); |
| 727 | ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino); |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 728 | /* |
| 729 | * The inode was probably partially accounted for |
| 730 | * before processing was aborted, so we need to |
| 731 | * restart the pass 1 scan. |
| 732 | */ |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 733 | ctx->flags |= E2F_FLAG_RESTART; |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 734 | return; |
| 735 | } |
| 736 | |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 737 | pb.num_blocks *= (fs->blocksize / 512); |
| 738 | #if 0 |
Theodore Ts'o | 246501c | 1998-03-24 16:22:38 +0000 | [diff] [blame^] | 739 | printf("inode %u, i_size = %lu, last_block = %lld, i_blocks=%lu, num_blocks = %lu\n", |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 740 | ino, inode->i_size, pb.last_block, inode->i_blocks, |
| 741 | pb.num_blocks); |
| 742 | #endif |
| 743 | if (!pb.num_blocks && pb.is_dir) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 744 | if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) { |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 745 | inode->i_links_count = 0; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 746 | ext2fs_icount_store(ctx->inode_link_info, ino, 0); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 747 | inode->i_dtime = time(0); |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 748 | e2fsck_write_inode(ctx, ino, inode, "check_blocks"); |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 749 | ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino); |
| 750 | ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino); |
| 751 | ctx->fs_directory_count--; |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 752 | pb.is_dir = 0; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 753 | } |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 754 | } |
Theodore Ts'o | 246501c | 1998-03-24 16:22:38 +0000 | [diff] [blame^] | 755 | if (pb.is_dir) { |
| 756 | int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super); |
| 757 | if ((nblock > (pb.last_block + 1)) || |
| 758 | ((inode->i_size & (fs->blocksize-1)) != 0)) |
| 759 | bad_size = 1; |
| 760 | else if (nblock < (pb.last_block + 1)) { |
| 761 | sb = (struct ext2fs_sb *) fs->super; |
| 762 | if (((pb.last_block + 1) - nblock) > |
| 763 | sb->s_prealloc_dir_blocks) |
| 764 | bad_size = 1; |
| 765 | } |
| 766 | } else { |
| 767 | size = inode->i_size + ((__u64) inode->i_size_high << 32); |
| 768 | if ((size < pb.last_block * fs->blocksize)) |
| 769 | bad_size = 1; |
| 770 | else if (size > ext2_max_sizes[fs->super->s_log_block_size]) |
| 771 | bad_size = 1; |
| 772 | } |
| 773 | if (bad_size) { |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 774 | pctx->num = (pb.last_block+1) * fs->blocksize; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 775 | if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) { |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 776 | inode->i_size = pctx->num; |
Theodore Ts'o | 246501c | 1998-03-24 16:22:38 +0000 | [diff] [blame^] | 777 | if (!pb.is_dir) |
| 778 | inode->i_size_high = pctx->num >> 32; |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 779 | e2fsck_write_inode(ctx, ino, inode, "check_blocks"); |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 780 | } |
| 781 | pctx->num = 0; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 782 | } |
Theodore Ts'o | 246501c | 1998-03-24 16:22:38 +0000 | [diff] [blame^] | 783 | if (!pb.is_dir && inode->i_size_high) |
| 784 | ctx->large_files++; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 785 | if (pb.num_blocks != inode->i_blocks) { |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 786 | pctx->num = pb.num_blocks; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 787 | if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) { |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 788 | inode->i_blocks = pb.num_blocks; |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 789 | e2fsck_write_inode(ctx, ino, inode, "check_blocks"); |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 790 | } |
| 791 | pctx->num = 0; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 792 | } |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 793 | } |
| 794 | |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 795 | #if 0 |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 796 | /* |
| 797 | * Helper function called by process block when an illegal block is |
| 798 | * found. It returns a description about why the block is illegal |
| 799 | */ |
| 800 | static char *describe_illegal_block(ext2_filsys fs, blk_t block) |
| 801 | { |
| 802 | blk_t super; |
| 803 | int i; |
| 804 | static char problem[80]; |
| 805 | |
| 806 | super = fs->super->s_first_data_block; |
| 807 | strcpy(problem, "PROGRAMMING ERROR: Unknown reason for illegal block"); |
| 808 | if (block < super) { |
| 809 | sprintf(problem, "< FIRSTBLOCK (%u)", super); |
| 810 | return(problem); |
| 811 | } else if (block >= fs->super->s_blocks_count) { |
| 812 | sprintf(problem, "> BLOCKS (%u)", fs->super->s_blocks_count); |
| 813 | return(problem); |
| 814 | } |
| 815 | for (i = 0; i < fs->group_desc_count; i++) { |
| 816 | if (block == super) { |
| 817 | sprintf(problem, "is the superblock in group %d", i); |
| 818 | break; |
| 819 | } |
| 820 | if (block > super && |
| 821 | block <= (super + fs->desc_blocks)) { |
| 822 | sprintf(problem, "is in the group descriptors " |
| 823 | "of group %d", i); |
| 824 | break; |
| 825 | } |
| 826 | if (block == fs->group_desc[i].bg_block_bitmap) { |
| 827 | sprintf(problem, "is the block bitmap of group %d", i); |
| 828 | break; |
| 829 | } |
| 830 | if (block == fs->group_desc[i].bg_inode_bitmap) { |
| 831 | sprintf(problem, "is the inode bitmap of group %d", i); |
| 832 | break; |
| 833 | } |
| 834 | if (block >= fs->group_desc[i].bg_inode_table && |
| 835 | (block < fs->group_desc[i].bg_inode_table |
| 836 | + fs->inode_blocks_per_group)) { |
| 837 | sprintf(problem, "is in the inode table of group %d", |
| 838 | i); |
| 839 | break; |
| 840 | } |
| 841 | super += fs->super->s_blocks_per_group; |
| 842 | } |
| 843 | return(problem); |
| 844 | } |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 845 | #endif |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 846 | |
| 847 | /* |
| 848 | * This is a helper function for check_blocks(). |
| 849 | */ |
| 850 | int process_block(ext2_filsys fs, |
| 851 | blk_t *block_nr, |
Theodore Ts'o | 246501c | 1998-03-24 16:22:38 +0000 | [diff] [blame^] | 852 | blkcnt_t blockcnt, |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 853 | blk_t ref_block, |
| 854 | int ref_offset, |
Theodore Ts'o | 54dc7ca | 1998-01-19 14:50:49 +0000 | [diff] [blame] | 855 | void *priv_data) |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 856 | { |
| 857 | struct process_block_struct *p; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 858 | struct problem_context *pctx; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 859 | blk_t blk = *block_nr; |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 860 | int ret_code = 0; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 861 | int problem = 0; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 862 | e2fsck_t ctx; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 863 | |
Theodore Ts'o | 54dc7ca | 1998-01-19 14:50:49 +0000 | [diff] [blame] | 864 | p = (struct process_block_struct *) priv_data; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 865 | pctx = p->pctx; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 866 | ctx = p->ctx; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 867 | |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 868 | if (blk == 0) { |
| 869 | if (p->is_dir == 0) { |
Theodore Ts'o | 1e3472c | 1997-04-29 14:53:37 +0000 | [diff] [blame] | 870 | /* |
| 871 | * Should never happen, since only directories |
| 872 | * get called with BLOCK_FLAG_HOLE |
| 873 | */ |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 874 | #if DEBUG_E2FSCK |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 875 | printf("process_block() called with blk == 0, " |
Theodore Ts'o | 5c57647 | 1997-04-29 15:29:49 +0000 | [diff] [blame] | 876 | "blockcnt=%d, inode %lu???\n", |
| 877 | blockcnt, p->ino); |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 878 | #endif |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 879 | return 0; |
| 880 | } |
| 881 | if (blockcnt < 0) |
| 882 | return 0; |
| 883 | if (blockcnt * fs->blocksize < p->inode->i_size) { |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 884 | #if 0 |
| 885 | printf("Missing block (#%d) in directory inode %lu!\n", |
| 886 | blockcnt, p->ino); |
| 887 | #endif |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 888 | goto mark_dir; |
| 889 | } |
| 890 | return 0; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 891 | } |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 892 | |
| 893 | #if 0 |
| 894 | printf("Process_block, inode %lu, block %u, #%d\n", p->ino, blk, |
| 895 | blockcnt); |
| 896 | #endif |
| 897 | |
Theodore Ts'o | 74becf3 | 1997-04-26 14:37:06 +0000 | [diff] [blame] | 898 | /* |
| 899 | * Simplistic fragmentation check. We merely require that the |
| 900 | * file be contiguous. (Which can never be true for really |
| 901 | * big files that are greater than a block group.) |
| 902 | */ |
| 903 | if (p->previous_block) { |
| 904 | if (p->previous_block+1 != blk) |
| 905 | p->fragmented = 1; |
| 906 | } |
| 907 | p->previous_block = blk; |
| 908 | |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 909 | if (blk < fs->super->s_first_data_block || |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 910 | blk >= fs->super->s_blocks_count) |
| 911 | problem = PR_1_ILLEGAL_BLOCK_NUM; |
Theodore Ts'o | 521e368 | 1997-04-29 17:48:10 +0000 | [diff] [blame] | 912 | #if 0 |
| 913 | else |
| 914 | if (ext2fs_test_block_bitmap(block_illegal_map, blk)) |
| 915 | problem = PR_1_BLOCK_OVERLAPS_METADATA; |
| 916 | #endif |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 917 | |
| 918 | if (problem) { |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 919 | p->num_illegal_blocks++; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 920 | if (!p->suppress && (p->num_illegal_blocks % 12) == 0) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 921 | if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) { |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 922 | p->clear = 1; |
| 923 | return BLOCK_ABORT; |
| 924 | } |
Theodore Ts'o | f8188ff | 1997-11-14 05:23:04 +0000 | [diff] [blame] | 925 | if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) { |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 926 | p->suppress = 1; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 927 | set_latch_flags(PR_LATCH_BLOCK, |
| 928 | PRL_SUPPRESS, 0); |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 929 | } |
| 930 | } |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 931 | pctx->blk = blk; |
| 932 | pctx->blkcount = blockcnt; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 933 | if (fix_problem(ctx, problem, pctx)) { |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 934 | blk = *block_nr = 0; |
| 935 | ret_code = BLOCK_CHANGED; |
| 936 | goto mark_dir; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 937 | } else |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 938 | return 0; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 939 | pctx->blk = 0; |
| 940 | pctx->blkcount = -1; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 941 | } |
| 942 | |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 943 | mark_block_used(ctx, blk); |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 944 | p->num_blocks++; |
Theodore Ts'o | 1e3472c | 1997-04-29 14:53:37 +0000 | [diff] [blame] | 945 | if (blockcnt >= 0) |
| 946 | p->last_block = blockcnt; |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 947 | mark_dir: |
Theodore Ts'o | 1e3472c | 1997-04-29 14:53:37 +0000 | [diff] [blame] | 948 | if (p->is_dir && (blockcnt >= 0)) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 949 | pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino, |
| 950 | blk, blockcnt); |
| 951 | if (pctx->errcode) { |
| 952 | pctx->blk = blk; |
| 953 | pctx->num = blockcnt; |
| 954 | fix_problem(ctx, PR_1_ADD_DBLOCK, pctx); |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 955 | /* Should never get here */ |
| 956 | ctx->flags |= E2F_FLAG_ABORT; |
| 957 | return BLOCK_ABORT; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 958 | } |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 959 | } |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 960 | return ret_code; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 961 | } |
| 962 | |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 963 | static void bad_block_indirect(e2fsck_t ctx, blk_t blk) |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 964 | { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 965 | struct problem_context pctx; |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 966 | |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 967 | clear_problem_context(&pctx); |
| 968 | /* |
| 969 | * Prompt to see if we should continue or not. |
| 970 | */ |
| 971 | if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK, &pctx)) |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 972 | ctx->flags |= E2F_FLAG_ABORT; |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 973 | } |
| 974 | |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 975 | int process_bad_block(ext2_filsys fs, |
| 976 | blk_t *block_nr, |
Theodore Ts'o | 246501c | 1998-03-24 16:22:38 +0000 | [diff] [blame^] | 977 | blkcnt_t blockcnt, |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 978 | blk_t ref_block, |
| 979 | int ref_offset, |
Theodore Ts'o | 54dc7ca | 1998-01-19 14:50:49 +0000 | [diff] [blame] | 980 | void *priv_data) |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 981 | { |
| 982 | struct process_block_struct *p; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 983 | blk_t blk = *block_nr; |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 984 | int first_block; |
| 985 | int i; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 986 | struct problem_context *pctx; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 987 | e2fsck_t ctx; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 988 | |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 989 | if (!blk) |
| 990 | return 0; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 991 | |
Theodore Ts'o | 54dc7ca | 1998-01-19 14:50:49 +0000 | [diff] [blame] | 992 | p = (struct process_block_struct *) priv_data; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 993 | ctx = p->ctx; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 994 | pctx = p->pctx; |
| 995 | |
Theodore Ts'o | f8188ff | 1997-11-14 05:23:04 +0000 | [diff] [blame] | 996 | pctx->ino = EXT2_BAD_INO; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 997 | pctx->blk = blk; |
| 998 | pctx->blkcount = blockcnt; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 999 | |
| 1000 | if ((blk < fs->super->s_first_data_block) || |
| 1001 | (blk >= fs->super->s_blocks_count)) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1002 | if (fix_problem(ctx, PR_1_BB_ILLEGAL_BLOCK_NUM, pctx)) { |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1003 | *block_nr = 0; |
| 1004 | return BLOCK_CHANGED; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 1005 | } else |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1006 | return 0; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1007 | } |
| 1008 | |
| 1009 | if (blockcnt < 0) { |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 1010 | if (ext2fs_test_block_bitmap(ctx->block_found_map, blk)) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1011 | bad_block_indirect(ctx, blk); |
Theodore Ts'o | a02ce9d | 1998-02-24 20:22:23 +0000 | [diff] [blame] | 1012 | if (ctx->flags & E2F_FLAG_SIGNAL_MASK) |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 1013 | return BLOCK_ABORT; |
| 1014 | } else |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1015 | mark_block_used(ctx, blk); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1016 | return 0; |
| 1017 | } |
| 1018 | #if 0 |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 1019 | printf ("DEBUG: Marking %u as bad.\n", blk); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1020 | #endif |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1021 | ctx->fs_badblocks_count++; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1022 | /* |
| 1023 | * If the block is not used, then mark it as used and return. |
| 1024 | * If it is already marked as found, this must mean that |
| 1025 | * there's an overlap between the filesystem table blocks |
| 1026 | * (bitmaps and inode table) and the bad block list. |
| 1027 | */ |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1028 | if (!ext2fs_test_block_bitmap(ctx->block_found_map, blk)) { |
| 1029 | ext2fs_mark_block_bitmap(ctx->block_found_map, blk); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1030 | return 0; |
| 1031 | } |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 1032 | /* |
| 1033 | * Try to find the where the filesystem block was used... |
| 1034 | */ |
| 1035 | first_block = fs->super->s_first_data_block; |
| 1036 | |
| 1037 | for (i = 0; i < fs->group_desc_count; i++ ) { |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 1038 | pctx->group = i; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1039 | pctx->blk = blk; |
Theodore Ts'o | 8039c48 | 1997-11-19 21:39:13 +0000 | [diff] [blame] | 1040 | if (!ext2fs_bg_has_super(fs, i)) |
| 1041 | goto skip_super; |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 1042 | if (blk == first_block) { |
| 1043 | if (i == 0) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1044 | if (fix_problem(ctx, |
| 1045 | PR_1_BAD_PRIMARY_SUPERBLOCK, |
| 1046 | pctx)) { |
| 1047 | *block_nr = 0; |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 1048 | return BLOCK_CHANGED; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1049 | } |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 1050 | return 0; |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 1051 | } |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1052 | fix_problem(ctx, PR_1_BAD_SUPERBLOCK, pctx); |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 1053 | return 0; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1054 | } |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 1055 | if ((blk > first_block) && |
| 1056 | (blk <= first_block + fs->desc_blocks)) { |
| 1057 | if (i == 0) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1058 | pctx->blk = *block_nr; |
| 1059 | if (fix_problem(ctx, |
| 1060 | PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR, pctx)) { |
| 1061 | *block_nr = 0; |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 1062 | return BLOCK_CHANGED; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1063 | } |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 1064 | return 0; |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 1065 | } |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1066 | fix_problem(ctx, PR_1_BAD_GROUP_DESCRIPTORS, pctx); |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 1067 | return 0; |
| 1068 | } |
Theodore Ts'o | 8039c48 | 1997-11-19 21:39:13 +0000 | [diff] [blame] | 1069 | skip_super: |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 1070 | if (blk == fs->group_desc[i].bg_block_bitmap) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1071 | if (fix_problem(ctx, PR_1_BB_BAD_BLOCK, pctx)) { |
| 1072 | ctx->invalid_block_bitmap_flag[i]++; |
| 1073 | ctx->invalid_bitmaps++; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 1074 | } |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 1075 | return 0; |
| 1076 | } |
| 1077 | if (blk == fs->group_desc[i].bg_inode_bitmap) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1078 | if (fix_problem(ctx, PR_1_IB_BAD_BLOCK, pctx)) { |
| 1079 | ctx->invalid_inode_bitmap_flag[i]++; |
| 1080 | ctx->invalid_bitmaps++; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 1081 | } |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 1082 | return 0; |
| 1083 | } |
| 1084 | if ((blk >= fs->group_desc[i].bg_inode_table) && |
| 1085 | (blk < (fs->group_desc[i].bg_inode_table + |
| 1086 | fs->inode_blocks_per_group))) { |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 1087 | /* |
| 1088 | * If there are bad blocks in the inode table, |
| 1089 | * the inode scan code will try to do |
| 1090 | * something reasonable automatically. |
| 1091 | */ |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 1092 | return 0; |
| 1093 | } |
Theodore Ts'o | 8039c48 | 1997-11-19 21:39:13 +0000 | [diff] [blame] | 1094 | first_block += fs->super->s_blocks_per_group; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1095 | } |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 1096 | /* |
| 1097 | * If we've gotten to this point, then the only |
| 1098 | * possibility is that the bad block inode meta data |
| 1099 | * is using a bad block. |
| 1100 | */ |
| 1101 | if ((blk == p->inode->i_block[EXT2_IND_BLOCK]) || |
| 1102 | p->inode->i_block[EXT2_DIND_BLOCK]) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1103 | bad_block_indirect(ctx, blk); |
Theodore Ts'o | a02ce9d | 1998-02-24 20:22:23 +0000 | [diff] [blame] | 1104 | if (ctx->flags & E2F_FLAG_SIGNAL_MASK) |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 1105 | return BLOCK_ABORT; |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 1106 | return 0; |
| 1107 | } |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1108 | |
| 1109 | pctx->group = -1; |
| 1110 | |
| 1111 | /* Warn user that the block wasn't claimed */ |
| 1112 | fix_problem(ctx, PR_1_PROGERR_CLAIMED_BLOCK, pctx); |
| 1113 | |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1114 | return 0; |
| 1115 | } |
| 1116 | |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1117 | static void new_table_block(e2fsck_t ctx, blk_t first_block, int group, |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1118 | const char *name, int num, blk_t *new_block) |
| 1119 | { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1120 | ext2_filsys fs = ctx->fs; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1121 | blk_t old_block = *new_block; |
| 1122 | int i; |
| 1123 | char *buf; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1124 | struct problem_context pctx; |
| 1125 | |
| 1126 | clear_problem_context(&pctx); |
| 1127 | |
| 1128 | pctx.group = group; |
| 1129 | pctx.blk = old_block; |
| 1130 | pctx.str = name; |
| 1131 | |
| 1132 | pctx.errcode = ext2fs_get_free_blocks(fs, first_block, |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1133 | first_block + fs->super->s_blocks_per_group, |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1134 | num, ctx->block_found_map, new_block); |
| 1135 | if (pctx.errcode) { |
| 1136 | pctx.num = num; |
| 1137 | fix_problem(ctx, PR_1_RELOC_BLOCK_ALLOCATE, &pctx); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1138 | ext2fs_unmark_valid(fs); |
| 1139 | return; |
| 1140 | } |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 1141 | pctx.errcode = ext2fs_get_mem(fs->blocksize, (void **) &buf); |
| 1142 | if (pctx.errcode) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1143 | fix_problem(ctx, PR_1_RELOC_MEMORY_ALLOCATE, &pctx); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1144 | ext2fs_unmark_valid(fs); |
| 1145 | return; |
| 1146 | } |
| 1147 | ext2fs_mark_super_dirty(fs); |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1148 | pctx.blk2 = *new_block; |
| 1149 | fix_problem(ctx, (old_block ? PR_1_RELOC_FROM_TO : |
| 1150 | PR_1_RELOC_TO), &pctx); |
| 1151 | pctx.blk2 = 0; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1152 | for (i = 0; i < num; i++) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1153 | pctx.blk = i; |
| 1154 | ext2fs_mark_block_bitmap(ctx->block_found_map, (*new_block)+i); |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 1155 | if (old_block) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1156 | pctx.errcode = io_channel_read_blk(fs->io, |
| 1157 | old_block + i, 1, buf); |
| 1158 | if (pctx.errcode) |
| 1159 | fix_problem(ctx, PR_1_RELOC_READ_ERR, &pctx); |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 1160 | } else |
| 1161 | memset(buf, 0, fs->blocksize); |
| 1162 | |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1163 | pctx.blk = (*new_block) + i; |
| 1164 | pctx.errcode = io_channel_write_blk(fs->io, pctx.blk, |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1165 | 1, buf); |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1166 | if (pctx.errcode) |
| 1167 | fix_problem(ctx, PR_1_RELOC_WRITE_ERR, &pctx); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1168 | } |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 1169 | ext2fs_free_mem((void **) &buf); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1170 | } |
| 1171 | |
| 1172 | /* |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 1173 | * This routine gets called at the end of pass 1 if bad blocks are |
| 1174 | * detected in the superblock, group descriptors, inode_bitmaps, or |
| 1175 | * block bitmaps. At this point, all of the blocks have been mapped |
| 1176 | * out, so we can try to allocate new block(s) to replace the bad |
| 1177 | * blocks. |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1178 | */ |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1179 | static void handle_fs_bad_blocks(e2fsck_t ctx) |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1180 | { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1181 | ext2_filsys fs = ctx->fs; |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 1182 | int i; |
| 1183 | int first_block = fs->super->s_first_data_block; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1184 | |
| 1185 | for (i = 0; i < fs->group_desc_count; i++) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1186 | if (ctx->invalid_block_bitmap_flag[i]) { |
| 1187 | new_table_block(ctx, first_block, i, "block bitmap", |
| 1188 | 1, &fs->group_desc[i].bg_block_bitmap); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1189 | } |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1190 | if (ctx->invalid_inode_bitmap_flag[i]) { |
| 1191 | new_table_block(ctx, first_block, i, "inode bitmap", |
| 1192 | 1, &fs->group_desc[i].bg_inode_bitmap); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1193 | } |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1194 | if (ctx->invalid_inode_table_flag[i]) { |
| 1195 | new_table_block(ctx, first_block, i, "inode table", |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 1196 | fs->inode_blocks_per_group, |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1197 | &fs->group_desc[i].bg_inode_table); |
Theodore Ts'o | 08b2130 | 1997-11-03 19:42:40 +0000 | [diff] [blame] | 1198 | ctx->flags |= E2F_FLAG_RESTART; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1199 | } |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1200 | first_block += fs->super->s_blocks_per_group; |
| 1201 | } |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1202 | ctx->invalid_bitmaps = 0; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1203 | } |
| 1204 | |
| 1205 | /* |
| 1206 | * This routine marks all blocks which are used by the superblock, |
| 1207 | * group descriptors, inode bitmaps, and block bitmaps. |
| 1208 | */ |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1209 | static void mark_table_blocks(e2fsck_t ctx) |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1210 | { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1211 | ext2_filsys fs = ctx->fs; |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 1212 | blk_t block, b; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1213 | int i,j; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 1214 | struct problem_context pctx; |
| 1215 | |
| 1216 | clear_problem_context(&pctx); |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1217 | |
| 1218 | block = fs->super->s_first_data_block; |
| 1219 | for (i = 0; i < fs->group_desc_count; i++) { |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 1220 | pctx.group = i; |
Theodore Ts'o | da2e97f | 1997-06-12 04:28:07 +0000 | [diff] [blame] | 1221 | |
| 1222 | if (ext2fs_bg_has_super(fs, i)) { |
| 1223 | /* |
| 1224 | * Mark this group's copy of the superblock |
| 1225 | */ |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1226 | ext2fs_mark_block_bitmap(ctx->block_found_map, block); |
| 1227 | ext2fs_mark_block_bitmap(ctx->block_illegal_map, |
| 1228 | block); |
Theodore Ts'o | da2e97f | 1997-06-12 04:28:07 +0000 | [diff] [blame] | 1229 | |
| 1230 | /* |
| 1231 | * Mark this group's copy of the descriptors |
| 1232 | */ |
| 1233 | for (j = 0; j < fs->desc_blocks; j++) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1234 | ext2fs_mark_block_bitmap(ctx->block_found_map, |
Theodore Ts'o | da2e97f | 1997-06-12 04:28:07 +0000 | [diff] [blame] | 1235 | block + j + 1); |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1236 | ext2fs_mark_block_bitmap(ctx->block_illegal_map, |
Theodore Ts'o | da2e97f | 1997-06-12 04:28:07 +0000 | [diff] [blame] | 1237 | block + j + 1); |
| 1238 | } |
| 1239 | } |
| 1240 | |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 1241 | /* |
| 1242 | * Mark the blocks used for the inode table |
| 1243 | */ |
| 1244 | if (fs->group_desc[i].bg_inode_table) { |
| 1245 | for (j = 0, b = fs->group_desc[i].bg_inode_table; |
| 1246 | j < fs->inode_blocks_per_group; |
| 1247 | j++, b++) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1248 | if (ext2fs_test_block_bitmap(ctx->block_found_map, |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 1249 | b)) { |
| 1250 | pctx.blk = b; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1251 | if (fix_problem(ctx, |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 1252 | PR_1_ITABLE_CONFLICT, &pctx)) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1253 | ctx->invalid_inode_table_flag[i]++; |
| 1254 | ctx->invalid_bitmaps++; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 1255 | } |
| 1256 | } else { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1257 | ext2fs_mark_block_bitmap(ctx->block_found_map, |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 1258 | b); |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1259 | ext2fs_mark_block_bitmap(ctx->block_illegal_map, |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 1260 | b); |
| 1261 | } |
| 1262 | } |
| 1263 | } |
| 1264 | |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1265 | /* |
| 1266 | * Mark block used for the block bitmap |
| 1267 | */ |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 1268 | if (fs->group_desc[i].bg_block_bitmap) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1269 | if (ext2fs_test_block_bitmap(ctx->block_found_map, |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 1270 | fs->group_desc[i].bg_block_bitmap)) { |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 1271 | pctx.blk = fs->group_desc[i].bg_block_bitmap; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1272 | if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) { |
| 1273 | ctx->invalid_block_bitmap_flag[i]++; |
| 1274 | ctx->invalid_bitmaps++; |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 1275 | } |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 1276 | } else { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1277 | ext2fs_mark_block_bitmap(ctx->block_found_map, |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 1278 | fs->group_desc[i].bg_block_bitmap); |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1279 | ext2fs_mark_block_bitmap(ctx->block_illegal_map, |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 1280 | fs->group_desc[i].bg_block_bitmap); |
| 1281 | } |
| 1282 | |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 1283 | } |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1284 | /* |
| 1285 | * Mark block used for the inode bitmap |
| 1286 | */ |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 1287 | if (fs->group_desc[i].bg_inode_bitmap) { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1288 | if (ext2fs_test_block_bitmap(ctx->block_found_map, |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 1289 | fs->group_desc[i].bg_inode_bitmap)) { |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 1290 | pctx.blk = fs->group_desc[i].bg_inode_bitmap; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1291 | if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) { |
| 1292 | ctx->invalid_inode_bitmap_flag[i]++; |
| 1293 | ctx->invalid_bitmaps++; |
Theodore Ts'o | 21c84b7 | 1997-04-29 16:15:03 +0000 | [diff] [blame] | 1294 | } |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 1295 | } else { |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1296 | ext2fs_mark_block_bitmap(ctx->block_found_map, |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 1297 | fs->group_desc[i].bg_inode_bitmap); |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1298 | ext2fs_mark_block_bitmap(ctx->block_illegal_map, |
Theodore Ts'o | 50e1e10 | 1997-04-26 13:58:21 +0000 | [diff] [blame] | 1299 | fs->group_desc[i].bg_inode_bitmap); |
| 1300 | } |
Theodore Ts'o | f3db356 | 1997-04-26 13:34:30 +0000 | [diff] [blame] | 1301 | } |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1302 | block += fs->super->s_blocks_per_group; |
| 1303 | } |
| 1304 | } |
| 1305 | |
| 1306 | /* |
| 1307 | * This subroutines short circuits ext2fs_get_blocks and |
| 1308 | * ext2fs_check_directory; we use them since we already have the inode |
| 1309 | * structure, so there's no point in letting the ext2fs library read |
| 1310 | * the inode again. |
| 1311 | */ |
Theodore Ts'o | 1e3472c | 1997-04-29 14:53:37 +0000 | [diff] [blame] | 1312 | errcode_t pass1_get_blocks(ext2_filsys fs, ino_t ino, blk_t *blocks) |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1313 | { |
Theodore Ts'o | 54dc7ca | 1998-01-19 14:50:49 +0000 | [diff] [blame] | 1314 | e2fsck_t ctx = (e2fsck_t) fs->priv_data; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1315 | int i; |
| 1316 | |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1317 | if (ino != ctx->stashed_ino) |
Theodore Ts'o | 521e368 | 1997-04-29 17:48:10 +0000 | [diff] [blame] | 1318 | return EXT2_ET_CALLBACK_NOTHANDLED; |
| 1319 | |
| 1320 | for (i=0; i < EXT2_N_BLOCKS; i++) |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1321 | blocks[i] = ctx->stashed_inode->i_block[i]; |
Theodore Ts'o | 521e368 | 1997-04-29 17:48:10 +0000 | [diff] [blame] | 1322 | return 0; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1323 | } |
| 1324 | |
Theodore Ts'o | 1e3472c | 1997-04-29 14:53:37 +0000 | [diff] [blame] | 1325 | errcode_t pass1_read_inode(ext2_filsys fs, ino_t ino, struct ext2_inode *inode) |
| 1326 | { |
Theodore Ts'o | 54dc7ca | 1998-01-19 14:50:49 +0000 | [diff] [blame] | 1327 | e2fsck_t ctx = (e2fsck_t) fs->priv_data; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1328 | |
| 1329 | if (ino != ctx->stashed_ino) |
Theodore Ts'o | 1e3472c | 1997-04-29 14:53:37 +0000 | [diff] [blame] | 1330 | return EXT2_ET_CALLBACK_NOTHANDLED; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1331 | *inode = *ctx->stashed_inode; |
Theodore Ts'o | 1e3472c | 1997-04-29 14:53:37 +0000 | [diff] [blame] | 1332 | return 0; |
| 1333 | } |
| 1334 | |
| 1335 | errcode_t pass1_write_inode(ext2_filsys fs, ino_t ino, |
| 1336 | struct ext2_inode *inode) |
| 1337 | { |
Theodore Ts'o | 54dc7ca | 1998-01-19 14:50:49 +0000 | [diff] [blame] | 1338 | e2fsck_t ctx = (e2fsck_t) fs->priv_data; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1339 | |
| 1340 | if (ino == ctx->stashed_ino) |
| 1341 | *ctx->stashed_inode = *inode; |
Theodore Ts'o | 1e3472c | 1997-04-29 14:53:37 +0000 | [diff] [blame] | 1342 | return EXT2_ET_CALLBACK_NOTHANDLED; |
| 1343 | } |
| 1344 | |
| 1345 | errcode_t pass1_check_directory(ext2_filsys fs, ino_t ino) |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1346 | { |
Theodore Ts'o | 54dc7ca | 1998-01-19 14:50:49 +0000 | [diff] [blame] | 1347 | e2fsck_t ctx = (e2fsck_t) fs->priv_data; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1348 | |
| 1349 | if (ino != ctx->stashed_ino) |
| 1350 | return EXT2_ET_CALLBACK_NOTHANDLED; |
| 1351 | |
| 1352 | if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode)) |
Theodore Ts'o | 291c904 | 1997-10-31 06:17:08 +0000 | [diff] [blame] | 1353 | return EXT2_ET_NO_DIRECTORY; |
Theodore Ts'o | 1b6bf17 | 1997-10-03 17:48:10 +0000 | [diff] [blame] | 1354 | return 0; |
Theodore Ts'o | 3839e65 | 1997-04-26 13:21:57 +0000 | [diff] [blame] | 1355 | } |