super.c revision 4313932cd77c9323fbfe4cacf4d1dc84c95a39de
1/* 2 * e2fsck.c - superblock checks 3 * 4 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o. 5 * 6 * %Begin-Header% 7 * This file may be redistributed under the terms of the GNU Public 8 * License. 9 * %End-Header% 10 */ 11 12#include <stdio.h> 13#ifdef HAVE_STDLIB_H 14#include <stdlib.h> 15#endif 16#include <string.h> 17#include <time.h> 18#ifdef HAVE_GETOPT_H 19#include <getopt.h> 20#endif 21#include <unistd.h> 22#ifdef HAVE_ERRNO_H 23#include <errno.h> 24#endif 25#ifdef HAVE_MNTENT_H 26#include <mntent.h> 27#endif 28 29#ifndef EXT2_SKIP_UUID 30#include "uuid/uuid.h" 31#endif 32#include "e2fsck.h" 33#include "problem.h" 34 35#define MIN_CHECK 1 36#define MAX_CHECK 2 37 38static void check_super_value(e2fsck_t ctx, const char *descr, 39 unsigned long value, int flags, 40 unsigned long min, unsigned long max) 41{ 42 struct problem_context pctx; 43 44 if (((flags & MIN_CHECK) && (value < min)) || 45 ((flags & MAX_CHECK) && (value > max))) { 46 clear_problem_context(&pctx); 47 pctx.num = value; 48 pctx.str = descr; 49 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx); 50 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */ 51 } 52} 53 54/* 55 * This routine may get stubbed out in special compilations of the 56 * e2fsck code.. 57 */ 58#ifndef EXT2_SPECIAL_DEVICE_SIZE 59errcode_t e2fsck_get_device_size(e2fsck_t ctx) 60{ 61 return (ext2fs_get_device_size(ctx->filesystem_name, 62 EXT2_BLOCK_SIZE(ctx->fs->super), 63 &ctx->num_blocks)); 64} 65#else 66extern errcode_t e2fsck_get_device_size(e2fsck_t ctx); 67#endif 68 69void check_super_block(e2fsck_t ctx) 70{ 71 ext2_filsys fs = ctx->fs; 72 blk_t first_block, last_block; 73 struct ext2fs_sb *s = (struct ext2fs_sb *) fs->super; 74 blk_t blocks_per_group = fs->super->s_blocks_per_group; 75 int i; 76 blk_t should_be; 77 struct problem_context pctx; 78 79 ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx, 80 sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap"); 81 ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx, 82 sizeof(int) * fs->group_desc_count, "invalid_block_bitmap"); 83 ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx, 84 sizeof(int) * fs->group_desc_count, "invalid_inode_table"); 85 86 clear_problem_context(&pctx); 87 88 /* 89 * Verify the super block constants... 90 */ 91 check_super_value(ctx, "inodes_count", s->s_inodes_count, 92 MIN_CHECK, 1, 0); 93 check_super_value(ctx, "blocks_count", s->s_blocks_count, 94 MIN_CHECK, 1, 0); 95 check_super_value(ctx, "first_data_block", s->s_first_data_block, 96 MAX_CHECK, 0, s->s_blocks_count); 97 check_super_value(ctx, "log_frag_size", s->s_log_frag_size, 98 MAX_CHECK, 0, 2); 99 check_super_value(ctx, "log_block_size", s->s_log_block_size, 100 MIN_CHECK | MAX_CHECK, s->s_log_frag_size, 101 2); 102 check_super_value(ctx, "frags_per_group", s->s_frags_per_group, 103 MIN_CHECK | MAX_CHECK, 1, 8 * EXT2_BLOCK_SIZE(s)); 104 check_super_value(ctx, "blocks_per_group", s->s_blocks_per_group, 105 MIN_CHECK | MAX_CHECK, 1, 8 * EXT2_BLOCK_SIZE(s)); 106 check_super_value(ctx, "inodes_per_group", s->s_inodes_per_group, 107 MIN_CHECK, 1, 0); 108 check_super_value(ctx, "r_blocks_count", s->s_r_blocks_count, 109 MAX_CHECK, 0, s->s_blocks_count); 110 111 if (!ctx->num_blocks) { 112 pctx.errcode = e2fsck_get_device_size(ctx); 113 if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) { 114 fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx); 115 ctx->flags |= E2F_FLAG_ABORT; 116 return; 117 } 118 if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) && 119 (ctx->num_blocks < s->s_blocks_count)) { 120 pctx.blk = s->s_blocks_count; 121 pctx.blk2 = ctx->num_blocks; 122 if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) { 123 ctx->flags |= E2F_FLAG_ABORT; 124 return; 125 } 126 } 127 } 128 129 if (s->s_log_block_size != s->s_log_frag_size) { 130 pctx.blk = EXT2_BLOCK_SIZE(s); 131 pctx.blk2 = EXT2_FRAG_SIZE(s); 132 fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx); 133 ctx->flags |= E2F_FLAG_ABORT; 134 return; 135 } 136 137 should_be = s->s_frags_per_group / 138 (s->s_log_block_size - s->s_log_frag_size + 1); 139 if (s->s_blocks_per_group != should_be) { 140 pctx.blk = s->s_blocks_per_group; 141 pctx.blk2 = should_be; 142 fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx); 143 ctx->flags |= E2F_FLAG_ABORT; 144 return; 145 } 146 147 should_be = (s->s_log_block_size == 0) ? 1 : 0; 148 if (s->s_first_data_block != should_be) { 149 pctx.blk = s->s_first_data_block; 150 pctx.blk2 = should_be; 151 fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx); 152 ctx->flags |= E2F_FLAG_ABORT; 153 return; 154 } 155 156 /* 157 * Verify the group descriptors.... 158 */ 159 first_block = fs->super->s_first_data_block; 160 last_block = first_block + blocks_per_group; 161 162 for (i = 0; i < fs->group_desc_count; i++) { 163 pctx.group = i; 164 165 if (i == fs->group_desc_count - 1) 166 last_block = fs->super->s_blocks_count; 167 if ((fs->group_desc[i].bg_block_bitmap < first_block) || 168 (fs->group_desc[i].bg_block_bitmap >= last_block)) { 169 pctx.blk = fs->group_desc[i].bg_block_bitmap; 170 if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx)) { 171 fs->group_desc[i].bg_block_bitmap = 0; 172 ctx->invalid_block_bitmap_flag[i]++; 173 ctx->invalid_bitmaps++; 174 } 175 } 176 if ((fs->group_desc[i].bg_inode_bitmap < first_block) || 177 (fs->group_desc[i].bg_inode_bitmap >= last_block)) { 178 pctx.blk = fs->group_desc[i].bg_inode_bitmap; 179 if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx)) { 180 fs->group_desc[i].bg_inode_bitmap = 0; 181 ctx->invalid_inode_bitmap_flag[i]++; 182 ctx->invalid_bitmaps++; 183 } 184 } 185 if ((fs->group_desc[i].bg_inode_table < first_block) || 186 ((fs->group_desc[i].bg_inode_table + 187 fs->inode_blocks_per_group - 1) >= last_block)) { 188 pctx.blk = fs->group_desc[i].bg_inode_table; 189 if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx)) { 190 fs->group_desc[i].bg_inode_table = 0; 191 ctx->invalid_inode_table_flag[i]++; 192 ctx->invalid_bitmaps++; 193 } 194 } 195 first_block += fs->super->s_blocks_per_group; 196 last_block += fs->super->s_blocks_per_group; 197 } 198 /* 199 * If we have invalid bitmaps, set the error state of the 200 * filesystem. 201 */ 202 if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) { 203 fs->super->s_state &= ~EXT2_VALID_FS; 204 ext2fs_mark_super_dirty(fs); 205 } 206 207#ifndef EXT2_SKIP_UUID 208 /* 209 * If the UUID field isn't assigned, assign it. 210 */ 211 if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(s->s_uuid)) { 212 clear_problem_context(&pctx); 213 if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) { 214 uuid_generate(s->s_uuid); 215 ext2fs_mark_super_dirty(fs); 216 } 217 } 218#endif 219 return; 220} 221 222