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