2 * e2fsck.c - superblock checks
4 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
7 * This file may be redistributed under the terms of the GNU Public
31 #include <sys/ioctl.h>
34 #include "uuid/uuid.h"
37 #include "../version.h"
42 static void check_super_value(e2fsck_t ctx
, const char *descr
,
43 unsigned long value
, int flags
,
44 unsigned long min
, unsigned long max
)
46 struct problem_context pctx
;
48 if (((flags
& MIN_CHECK
) && (value
< min
)) ||
49 ((flags
& MAX_CHECK
) && (value
> max
))) {
50 clear_problem_context(&pctx
);
53 fix_problem(ctx
, PR_0_MISC_CORRUPT_SUPER
, &pctx
);
54 fatal_error(0); /* never get here! */
58 void check_super_block(e2fsck_t ctx
)
60 ext2_filsys fs
= ctx
->fs
;
61 blk_t first_block
, last_block
;
62 struct ext2fs_sb
*s
= (struct ext2fs_sb
*) fs
->super
;
63 blk_t blocks_per_group
= fs
->super
->s_blocks_per_group
;
66 struct problem_context pctx
;
68 ctx
->invalid_inode_bitmap_flag
= allocate_memory(sizeof(int) *
70 "invalid_inode_bitmap");
71 ctx
->invalid_block_bitmap_flag
= allocate_memory(sizeof(int) *
73 "invalid_block_bitmap");
74 ctx
->invalid_inode_table_flag
= allocate_memory(sizeof(int) *
76 "invalid_inode_table");
78 clear_problem_context(&pctx
);
81 * Verify the super block constants...
83 check_super_value(ctx
, "inodes_count", s
->s_inodes_count
,
85 check_super_value(ctx
, "blocks_count", s
->s_blocks_count
,
87 check_super_value(ctx
, "first_data_block", s
->s_first_data_block
,
88 MAX_CHECK
, 0, s
->s_blocks_count
);
89 check_super_value(ctx
, "log_frag_size", s
->s_log_frag_size
,
91 check_super_value(ctx
, "log_block_size", s
->s_log_block_size
,
92 MIN_CHECK
| MAX_CHECK
, s
->s_log_frag_size
,
94 check_super_value(ctx
, "frags_per_group", s
->s_frags_per_group
,
95 MIN_CHECK
| MAX_CHECK
, 1, 8 * EXT2_BLOCK_SIZE(s
));
96 check_super_value(ctx
, "blocks_per_group", s
->s_blocks_per_group
,
97 MIN_CHECK
| MAX_CHECK
, 1, 8 * EXT2_BLOCK_SIZE(s
));
98 check_super_value(ctx
, "inodes_per_group", s
->s_inodes_per_group
,
100 check_super_value(ctx
, "r_blocks_count", s
->s_r_blocks_count
,
101 MAX_CHECK
, 0, s
->s_blocks_count
);
103 pctx
.errcode
= ext2fs_get_device_size(ctx
->filesystem_name
,
107 fix_problem(ctx
, PR_0_GETSIZE_ERROR
, &pctx
);
110 if (should_be
< s
->s_blocks_count
) {
111 pctx
.blk
= s
->s_blocks_count
;
112 pctx
.blk2
= should_be
;
113 if (fix_problem(ctx
, PR_0_FS_SIZE_WRONG
, &pctx
))
117 if (s
->s_log_block_size
!= s
->s_log_frag_size
) {
118 pctx
.blk
= EXT2_BLOCK_SIZE(s
);
119 pctx
.blk2
= EXT2_FRAG_SIZE(s
);
120 fix_problem(ctx
, PR_0_NO_FRAGMENTS
, &pctx
);
124 should_be
= s
->s_frags_per_group
/
125 (s
->s_log_block_size
- s
->s_log_frag_size
+ 1);
126 if (s
->s_blocks_per_group
!= should_be
) {
127 pctx
.blk
= s
->s_blocks_per_group
;
128 pctx
.blk2
= should_be
;
129 fix_problem(ctx
, PR_0_BLOCKS_PER_GROUP
, &pctx
);
133 should_be
= (s
->s_log_block_size
== 0) ? 1 : 0;
134 if (s
->s_first_data_block
!= should_be
) {
135 pctx
.blk
= s
->s_first_data_block
;
136 pctx
.blk2
= should_be
;
137 fix_problem(ctx
, PR_0_FIRST_DATA_BLOCK
, &pctx
);
142 * Verify the group descriptors....
144 first_block
= fs
->super
->s_first_data_block
;
145 last_block
= first_block
+ blocks_per_group
;
147 for (i
= 0; i
< fs
->group_desc_count
; i
++) {
150 if (i
== fs
->group_desc_count
- 1)
151 last_block
= fs
->super
->s_blocks_count
;
152 if ((fs
->group_desc
[i
].bg_block_bitmap
< first_block
) ||
153 (fs
->group_desc
[i
].bg_block_bitmap
>= last_block
)) {
154 pctx
.blk
= fs
->group_desc
[i
].bg_block_bitmap
;
155 if (fix_problem(ctx
, PR_0_BB_NOT_GROUP
, &pctx
)) {
156 fs
->group_desc
[i
].bg_block_bitmap
= 0;
157 ctx
->invalid_block_bitmap_flag
[i
]++;
158 ctx
->invalid_bitmaps
++;
161 if ((fs
->group_desc
[i
].bg_inode_bitmap
< first_block
) ||
162 (fs
->group_desc
[i
].bg_inode_bitmap
>= last_block
)) {
163 pctx
.blk
= fs
->group_desc
[i
].bg_inode_bitmap
;
164 if (fix_problem(ctx
, PR_0_IB_NOT_GROUP
, &pctx
)) {
165 fs
->group_desc
[i
].bg_inode_bitmap
= 0;
166 ctx
->invalid_inode_bitmap_flag
[i
]++;
167 ctx
->invalid_bitmaps
++;
170 if ((fs
->group_desc
[i
].bg_inode_table
< first_block
) ||
171 ((fs
->group_desc
[i
].bg_inode_table
+
172 fs
->inode_blocks_per_group
- 1) >= last_block
)) {
173 pctx
.blk
= fs
->group_desc
[i
].bg_inode_table
;
174 if (fix_problem(ctx
, PR_0_ITABLE_NOT_GROUP
, &pctx
)) {
175 fs
->group_desc
[i
].bg_inode_table
= 0;
176 ctx
->invalid_inode_table_flag
[i
]++;
177 ctx
->invalid_bitmaps
++;
180 first_block
+= fs
->super
->s_blocks_per_group
;
181 last_block
+= fs
->super
->s_blocks_per_group
;
184 * If we have invalid bitmaps, set the error state of the
187 if (ctx
->invalid_bitmaps
&& !(ctx
->options
& E2F_OPT_READONLY
)) {
188 fs
->super
->s_state
&= ~EXT2_VALID_FS
;
189 ext2fs_mark_super_dirty(fs
);
193 * If the UUID field isn't assigned, assign it.
195 if (!(ctx
->options
& E2F_OPT_READONLY
) && uuid_is_null(s
->s_uuid
)) {
196 clear_problem_context(&pctx
);
197 if (fix_problem(ctx
, PR_0_ADD_UUID
, &pctx
)) {
198 uuid_generate(s
->s_uuid
);
199 ext2fs_mark_super_dirty(fs
);