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
16 #ifndef EXT2_SKIP_UUID
17 #include "uuid/uuid.h"
25 static void check_super_value(e2fsck_t ctx
, const char *descr
,
26 unsigned long value
, int flags
,
27 unsigned long min_val
, unsigned long max_val
)
29 struct problem_context pctx
;
31 if (((flags
& MIN_CHECK
) && (value
< min_val
)) ||
32 ((flags
& MAX_CHECK
) && (value
> max_val
))) {
33 clear_problem_context(&pctx
);
36 fix_problem(ctx
, PR_0_MISC_CORRUPT_SUPER
, &pctx
);
37 ctx
->flags
|= E2F_FLAG_ABORT
; /* never get here! */
42 * This routine may get stubbed out in special compilations of the
45 #ifndef EXT2_SPECIAL_DEVICE_SIZE
46 errcode_t
e2fsck_get_device_size(e2fsck_t ctx
)
48 return (ext2fs_get_device_size(ctx
->filesystem_name
,
49 EXT2_BLOCK_SIZE(ctx
->fs
->super
),
55 * helper function to release an inode
57 struct process_block_struct
{
60 struct problem_context
*pctx
;
64 static int release_inode_block(ext2_filsys fs
,
69 struct process_block_struct
*pb
;
71 struct problem_context
*pctx
;
72 blk_t blk
= *block_nr
;
74 pb
= (struct process_block_struct
*) priv_data
;
79 pctx
->blkcount
= blockcnt
;
81 if (HOLE_BLKADDR(blk
))
84 if ((blk
< fs
->super
->s_first_data_block
) ||
85 (blk
>= fs
->super
->s_blocks_count
)) {
86 fix_problem(ctx
, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM
, pctx
);
91 if (!ext2fs_test_block_bitmap(fs
->block_map
, blk
)) {
92 fix_problem(ctx
, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK
, pctx
);
97 ext2fs_unmark_block_bitmap(fs
->block_map
, blk
);
103 * This function releases an inode. Returns 1 if an inconsistency was
106 static int release_inode_blocks(e2fsck_t ctx
, ino_t ino
, char* block_buf
,
107 struct problem_context
*pctx
)
109 ext2_filsys fs
= ctx
->fs
;
111 struct process_block_struct pb
;
117 retval
= ext2fs_block_iterate(fs
, ino
, 0, block_buf
,
118 release_inode_block
, &pb
);
120 com_err("delete_file", retval
,
121 _("while calling ext2fs_block_iterate for inode %d"),
128 ext2fs_unmark_inode_bitmap(fs
->inode_map
, ino
);
129 ext2fs_mark_ib_dirty(fs
);
130 ext2fs_mark_bb_dirty(fs
);
135 * This function releases all of the orphan inodes. It returns 1 if
136 * it hit some error, and 0 on success.
138 static int release_orphan_inodes(e2fsck_t ctx
)
140 ext2_filsys fs
= ctx
->fs
;
142 struct ext2_inode inode
;
143 struct problem_context pctx
;
146 if ((ino
= fs
->super
->s_last_orphan
) == 0)
149 if ((ino
< EXT2_FIRST_INODE(fs
->super
)) ||
150 (ino
> fs
->super
->s_inodes_count
)) {
151 clear_problem_context(&pctx
);
153 fix_problem(ctx
, PR_0_ORPHAN_ILLEGAL_HEAD_INODE
, &pctx
);
157 block_buf
= (char *) e2fsck_allocate_memory(ctx
, fs
->blocksize
* 3,
158 "block interate buffer");
159 e2fsck_read_bitmaps(ctx
);
163 printf("Clearing orphan inode %d\n", ino
);
166 e2fsck_read_inode(ctx
, ino
, &inode
, "delete_file");
167 clear_problem_context(&pctx
);
171 if (inode
.i_links_count
) {
172 fix_problem(ctx
, PR_0_ORPHAN_INODE_INUSE
, &pctx
);
175 next_ino
= inode
.i_dtime
;
177 ((ino
< EXT2_FIRST_INODE(fs
->super
)) ||
178 (ino
> fs
->super
->s_inodes_count
))) {
179 fix_problem(ctx
, PR_0_ORPHAN_ILLEGAL_INODE
, &pctx
);
183 if (release_inode_blocks(ctx
, ino
, block_buf
, &pctx
))
186 inode
.i_dtime
= time(0);
187 e2fsck_write_inode(ctx
, ino
, &inode
, "delete_file");
192 ext2fs_free_mem((void **) &block_buf
);
197 void check_super_block(e2fsck_t ctx
)
199 ext2_filsys fs
= ctx
->fs
;
200 blk_t first_block
, last_block
;
201 struct ext2fs_sb
*s
= (struct ext2fs_sb
*) fs
->super
;
202 blk_t blocks_per_group
= fs
->super
->s_blocks_per_group
;
203 int inodes_per_block
;
206 struct problem_context pctx
;
208 inodes_per_block
= (EXT2_INODE_SIZE(fs
->super
) +
209 EXT2_BLOCK_SIZE(fs
->super
) - 1) /
210 EXT2_BLOCK_SIZE(fs
->super
);
212 ctx
->invalid_inode_bitmap_flag
= (int *) e2fsck_allocate_memory(ctx
,
213 sizeof(int) * fs
->group_desc_count
, "invalid_inode_bitmap");
214 ctx
->invalid_block_bitmap_flag
= (int *) e2fsck_allocate_memory(ctx
,
215 sizeof(int) * fs
->group_desc_count
, "invalid_block_bitmap");
216 ctx
->invalid_inode_table_flag
= (int *) e2fsck_allocate_memory(ctx
,
217 sizeof(int) * fs
->group_desc_count
, "invalid_inode_table");
219 clear_problem_context(&pctx
);
222 * Verify the super block constants...
224 check_super_value(ctx
, "inodes_count", s
->s_inodes_count
,
226 check_super_value(ctx
, "blocks_count", s
->s_blocks_count
,
228 check_super_value(ctx
, "first_data_block", s
->s_first_data_block
,
229 MAX_CHECK
, 0, s
->s_blocks_count
);
230 check_super_value(ctx
, "log_frag_size", s
->s_log_frag_size
,
232 check_super_value(ctx
, "log_block_size", s
->s_log_block_size
,
233 MIN_CHECK
| MAX_CHECK
, s
->s_log_frag_size
,
235 check_super_value(ctx
, "frags_per_group", s
->s_frags_per_group
,
236 MIN_CHECK
| MAX_CHECK
, 1, 8 * EXT2_BLOCK_SIZE(s
));
237 check_super_value(ctx
, "blocks_per_group", s
->s_blocks_per_group
,
238 MIN_CHECK
| MAX_CHECK
, 1, 8 * EXT2_BLOCK_SIZE(s
));
239 check_super_value(ctx
, "inodes_per_group", s
->s_inodes_per_group
,
240 MIN_CHECK
| MAX_CHECK
, 1,
241 inodes_per_block
* blocks_per_group
);
242 check_super_value(ctx
, "r_blocks_count", s
->s_r_blocks_count
,
243 MAX_CHECK
, 0, s
->s_blocks_count
);
245 if (!ctx
->num_blocks
) {
246 pctx
.errcode
= e2fsck_get_device_size(ctx
);
247 if (pctx
.errcode
&& pctx
.errcode
!= EXT2_ET_UNIMPLEMENTED
) {
248 fix_problem(ctx
, PR_0_GETSIZE_ERROR
, &pctx
);
249 ctx
->flags
|= E2F_FLAG_ABORT
;
252 if ((pctx
.errcode
!= EXT2_ET_UNIMPLEMENTED
) &&
253 (ctx
->num_blocks
< s
->s_blocks_count
)) {
254 pctx
.blk
= s
->s_blocks_count
;
255 pctx
.blk2
= ctx
->num_blocks
;
256 if (fix_problem(ctx
, PR_0_FS_SIZE_WRONG
, &pctx
)) {
257 ctx
->flags
|= E2F_FLAG_ABORT
;
263 if (s
->s_log_block_size
!= s
->s_log_frag_size
) {
264 pctx
.blk
= EXT2_BLOCK_SIZE(s
);
265 pctx
.blk2
= EXT2_FRAG_SIZE(s
);
266 fix_problem(ctx
, PR_0_NO_FRAGMENTS
, &pctx
);
267 ctx
->flags
|= E2F_FLAG_ABORT
;
271 should_be
= s
->s_frags_per_group
>>
272 (s
->s_log_block_size
- s
->s_log_frag_size
);
273 if (s
->s_blocks_per_group
!= should_be
) {
274 pctx
.blk
= s
->s_blocks_per_group
;
275 pctx
.blk2
= should_be
;
276 fix_problem(ctx
, PR_0_BLOCKS_PER_GROUP
, &pctx
);
277 ctx
->flags
|= E2F_FLAG_ABORT
;
281 should_be
= (s
->s_log_block_size
== 0) ? 1 : 0;
282 if (s
->s_first_data_block
!= should_be
) {
283 pctx
.blk
= s
->s_first_data_block
;
284 pctx
.blk2
= should_be
;
285 fix_problem(ctx
, PR_0_FIRST_DATA_BLOCK
, &pctx
);
286 ctx
->flags
|= E2F_FLAG_ABORT
;
290 should_be
= s
->s_inodes_per_group
* fs
->group_desc_count
;
291 if (s
->s_inodes_count
!= should_be
) {
292 pctx
.ino
= s
->s_inodes_count
;
293 pctx
.ino2
= should_be
;
294 if (fix_problem(ctx
, PR_0_INODE_COUNT_WRONG
, &pctx
)) {
295 s
->s_inodes_count
= should_be
;
296 ext2fs_mark_super_dirty(fs
);
301 * Verify the group descriptors....
303 first_block
= fs
->super
->s_first_data_block
;
304 last_block
= first_block
+ blocks_per_group
;
306 for (i
= 0; i
< fs
->group_desc_count
; i
++) {
309 if (i
== fs
->group_desc_count
- 1)
310 last_block
= fs
->super
->s_blocks_count
;
311 if ((fs
->group_desc
[i
].bg_block_bitmap
< first_block
) ||
312 (fs
->group_desc
[i
].bg_block_bitmap
>= last_block
)) {
313 pctx
.blk
= fs
->group_desc
[i
].bg_block_bitmap
;
314 if (fix_problem(ctx
, PR_0_BB_NOT_GROUP
, &pctx
)) {
315 fs
->group_desc
[i
].bg_block_bitmap
= 0;
316 ctx
->invalid_block_bitmap_flag
[i
]++;
317 ctx
->invalid_bitmaps
++;
320 if ((fs
->group_desc
[i
].bg_inode_bitmap
< first_block
) ||
321 (fs
->group_desc
[i
].bg_inode_bitmap
>= last_block
)) {
322 pctx
.blk
= fs
->group_desc
[i
].bg_inode_bitmap
;
323 if (fix_problem(ctx
, PR_0_IB_NOT_GROUP
, &pctx
)) {
324 fs
->group_desc
[i
].bg_inode_bitmap
= 0;
325 ctx
->invalid_inode_bitmap_flag
[i
]++;
326 ctx
->invalid_bitmaps
++;
329 if ((fs
->group_desc
[i
].bg_inode_table
< first_block
) ||
330 ((fs
->group_desc
[i
].bg_inode_table
+
331 fs
->inode_blocks_per_group
- 1) >= last_block
)) {
332 pctx
.blk
= fs
->group_desc
[i
].bg_inode_table
;
333 if (fix_problem(ctx
, PR_0_ITABLE_NOT_GROUP
, &pctx
)) {
334 fs
->group_desc
[i
].bg_inode_table
= 0;
335 ctx
->invalid_inode_table_flag
[i
]++;
336 ctx
->invalid_bitmaps
++;
339 first_block
+= fs
->super
->s_blocks_per_group
;
340 last_block
+= fs
->super
->s_blocks_per_group
;
343 * If we have invalid bitmaps, set the error state of the
346 if (ctx
->invalid_bitmaps
&& !(ctx
->options
& E2F_OPT_READONLY
)) {
347 fs
->super
->s_state
&= ~EXT2_VALID_FS
;
348 ext2fs_mark_super_dirty(fs
);
351 clear_problem_context(&pctx
);
353 #ifndef EXT2_SKIP_UUID
355 * If the UUID field isn't assigned, assign it.
357 if (!(ctx
->options
& E2F_OPT_READONLY
) && uuid_is_null(s
->s_uuid
)) {
358 if (fix_problem(ctx
, PR_0_ADD_UUID
, &pctx
)) {
359 uuid_generate(s
->s_uuid
);
360 ext2fs_mark_super_dirty(fs
);
366 * For the Hurd, check to see if the filetype option is set,
367 * since it doesn't support it.
369 if (!(ctx
->options
& E2F_OPT_READONLY
) &&
370 fs
->super
->s_creator_os
== EXT2_OS_HURD
&&
371 (fs
->super
->s_feature_incompat
&
372 EXT2_FEATURE_INCOMPAT_FILETYPE
)) {
373 if (fix_problem(ctx
, PR_0_HURD_CLEAR_FILETYPE
, &pctx
)) {
374 fs
->super
->s_feature_incompat
&=
375 ~EXT2_FEATURE_INCOMPAT_FILETYPE
;
376 ext2fs_mark_super_dirty(fs
);
382 * Clean up any orphan inodes, if present.
384 if (!(ctx
->options
& E2F_OPT_READONLY
) && release_orphan_inodes(ctx
)) {
385 fs
->super
->s_state
&= ~EXT2_VALID_FS
;
386 ext2fs_mark_super_dirty(ctx
->fs
);