119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * e2fsck.c - superblock checks
33984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *
419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *
619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * %Begin-Header%
719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This file may be redistributed under the terms of the GNU Public
819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * License.
919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * %End-Header%
1019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
1119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
1219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef HAVE_ERRNO_H
1319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <errno.h>
1419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
1519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
1619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifndef EXT2_SKIP_UUID
1719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "uuid/uuid.h"
1819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
1919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "e2fsck.h"
2019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "problem.h"
2119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
2219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#define MIN_CHECK 1
2319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#define MAX_CHECK 2
2419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
2519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void check_super_value(e2fsck_t ctx, const char *descr,
2619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      unsigned long value, int flags,
2719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			      unsigned long min_val, unsigned long max_val)
2819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
2919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct		problem_context pctx;
3019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
3119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (((flags & MIN_CHECK) && (value < min_val)) ||
3219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    ((flags & MAX_CHECK) && (value > max_val))) {
3319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		clear_problem_context(&pctx);
3419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx.num = value;
3519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx.str = descr;
3619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
3719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
3819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
3919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
4019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
4119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
4219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * helper function to release an inode
4319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
4419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstruct process_block_struct {
4519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	e2fsck_t 	ctx;
4619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	char 		*buf;
4719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct problem_context *pctx;
4819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int		truncating;
4919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int		truncate_offset;
5019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	e2_blkcnt_t	truncate_block;
5119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int		truncated_blocks;
5219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int		abort;
5319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t	errcode;
5419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project};
5519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
5619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int release_inode_block(ext2_filsys fs,
5719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			       blk_t	*block_nr,
5819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			       e2_blkcnt_t blockcnt,
5919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			       blk_t	ref_blk EXT2FS_ATTR((unused)),
6019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			       int	ref_offset EXT2FS_ATTR((unused)),
6119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			       void *priv_data)
6219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
6319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct process_block_struct *pb;
6419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	e2fsck_t 		ctx;
6519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct problem_context	*pctx;
6619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	blk_t			blk = *block_nr;
6719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int			retval = 0;
6819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
6919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	pb = (struct process_block_struct *) priv_data;
7019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ctx = pb->ctx;
7119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	pctx = pb->pctx;
7219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
7319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	pctx->blk = blk;
7419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	pctx->blkcount = blockcnt;
7519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
7619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (HOLE_BLKADDR(blk))
7719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 0;
7819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
7919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if ((blk < fs->super->s_first_data_block) ||
8019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    (blk >= fs->super->s_blocks_count)) {
8119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
8219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return_abort:
8319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pb->abort = 1;
8419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return BLOCK_ABORT;
8519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
8619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
8719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
8819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
8919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		goto return_abort;
9019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
9119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
9219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
9319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * If we are deleting an orphan, then we leave the fields alone.
9419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * If we are truncating an orphan, then update the inode fields
9519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * and clean up any partial block data.
9619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
9719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (pb->truncating) {
9819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		/*
9919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * We only remove indirect blocks if they are
10019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * completely empty.
10119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 */
10219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (blockcnt < 0) {
10319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			int	i, limit;
10419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			blk_t	*bp;
1053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
10619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			pb->errcode = io_channel_read_blk(fs->io, blk, 1,
10719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project							pb->buf);
10819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (pb->errcode)
10919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				goto return_abort;
11019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
11119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			limit = fs->blocksize >> 2;
11219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			for (i = 0, bp = (blk_t *) pb->buf;
11319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			     i < limit;	 i++, bp++)
11419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				if (*bp)
11519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					return 0;
11619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
11719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		/*
11819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * We don't remove direct blocks until we've reached
11919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * the truncation block.
12019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 */
12119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (blockcnt >= 0 && blockcnt < pb->truncate_block)
12219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return 0;
12319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		/*
12419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * If part of the last block needs truncating, we do
12519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * it here.
12619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 */
12719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
12819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			pb->errcode = io_channel_read_blk(fs->io, blk, 1,
12919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project							pb->buf);
13019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (pb->errcode)
13119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				goto return_abort;
13219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			memset(pb->buf + pb->truncate_offset, 0,
13319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			       fs->blocksize - pb->truncate_offset);
13419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			pb->errcode = io_channel_write_blk(fs->io, blk, 1,
13519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project							 pb->buf);
13619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (pb->errcode)
13719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				goto return_abort;
13819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
13919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pb->truncated_blocks++;
14019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		*block_nr = 0;
14119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		retval |= BLOCK_CHANGED;
14219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
1433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
14419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_block_alloc_stats(fs, blk, -1);
14519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return retval;
14619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
1473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
14819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
14919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This function releases an inode.  Returns 1 if an inconsistency was
15019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * found.  If the inode has a link count, then it is being truncated and
15119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * not deleted.
15219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
15319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
15419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				struct ext2_inode *inode, char *block_buf,
15519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				struct problem_context *pctx)
15619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
15719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct process_block_struct 	pb;
15819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_filsys			fs = ctx->fs;
15919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t			retval;
16019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	__u32				count;
16119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
16219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!ext2fs_inode_has_valid_blocks(inode))
16319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 0;
16419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
16519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	pb.buf = block_buf + 3 * ctx->fs->blocksize;
16619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	pb.ctx = ctx;
16719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	pb.abort = 0;
16819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	pb.errcode = 0;
16919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	pb.pctx = pctx;
17019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (inode->i_links_count) {
17119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pb.truncating = 1;
17219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pb.truncate_block = (e2_blkcnt_t)
17319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			((((long long)inode->i_size_high << 32) +
17419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			  inode->i_size + fs->blocksize - 1) /
17519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 fs->blocksize);
17619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pb.truncate_offset = inode->i_size % fs->blocksize;
17719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	} else {
17819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pb.truncating = 0;
17919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pb.truncate_block = 0;
18019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pb.truncate_offset = 0;
18119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
18219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	pb.truncated_blocks = 0;
1833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
18419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				      block_buf, release_inode_block, &pb);
18519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (retval) {
18619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		com_err("release_inode_blocks", retval,
18719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			_("while calling ext2fs_block_iterate for inode %d"),
18819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ino);
18919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 1;
19019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
19119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (pb.abort)
19219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 1;
19319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
19419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/* Refresh the inode since ext2fs_block_iterate may have changed it */
19519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
19619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
19719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (pb.truncated_blocks)
1983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ext2fs_iblk_sub_blocks(fs, inode, pb.truncated_blocks);
19919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
20019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (inode->i_file_acl) {
20119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
20219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project						   block_buf, -1, &count);
20319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
20419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			retval = 0;
20519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			count = 1;
20619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
20719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (retval) {
20819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			com_err("release_inode_blocks", retval,
20919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		_("while calling ext2fs_adjust_ea_refcount for inode %d"),
21019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				ino);
21119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return 1;
21219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
21319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (count == 0)
21419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
21519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		inode->i_file_acl = 0;
21619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
21719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return 0;
21819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
21919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
22019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
22119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This function releases all of the orphan inodes.  It returns 1 if
22219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * it hit some error, and 0 on success.
22319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
22419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int release_orphan_inodes(e2fsck_t ctx)
22519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
22619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_filsys fs = ctx->fs;
22719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_ino_t	ino, next_ino;
22819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct ext2_inode inode;
22919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct problem_context pctx;
23019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	char *block_buf;
23119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
23219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if ((ino = fs->super->s_last_orphan) == 0)
23319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 0;
23419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
23519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
23619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * Win or lose, we won't be using the head of the orphan inode
23719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * list again.
23819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
23919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	fs->super->s_last_orphan = 0;
24019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_mark_super_dirty(fs);
24119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
24219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
24319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * If the filesystem contains errors, don't run the orphan
24419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * list, since the orphan list can't be trusted; and we're
24519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * going to be running a full e2fsck run anyway...
24619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
24719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (fs->super->s_state & EXT2_ERROR_FS)
24819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 0;
2493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
25019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if ((ino < EXT2_FIRST_INODE(fs->super)) ||
25119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    (ino > fs->super->s_inodes_count)) {
25219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		clear_problem_context(&pctx);
25319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx.ino = ino;
25419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
25519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 1;
25619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
25719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
25819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
25919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project						    "block iterate buffer");
26019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	e2fsck_read_bitmaps(ctx);
2613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
26219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	while (ino) {
26319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
26419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		clear_problem_context(&pctx);
26519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx.ino = ino;
26619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx.inode = &inode;
26719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx.str = inode.i_links_count ? _("Truncating") :
26819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			_("Clearing");
26919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
27019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
27119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
27219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		next_ino = inode.i_dtime;
27319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (next_ino &&
27419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
27519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		     (next_ino > fs->super->s_inodes_count))) {
27619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			pctx.ino = next_ino;
27719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
27819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			goto return_abort;
27919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
28019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
28119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
28219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			goto return_abort;
28319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
28419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (!inode.i_links_count) {
28519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ext2fs_inode_alloc_stats2(fs, ino, -1,
28619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project						  LINUX_S_ISDIR(inode.i_mode));
28719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			inode.i_dtime = ctx->now;
28819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		} else {
28919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			inode.i_dtime = 0;
29019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
29119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		e2fsck_write_inode(ctx, ino, &inode, "delete_file");
29219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ino = next_ino;
29319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
29419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_free_mem(&block_buf);
29519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return 0;
29619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectreturn_abort:
29719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_free_mem(&block_buf);
29819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return 1;
29919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
30019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
30119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
30219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Check the resize inode to make sure it is sane.  We check both for
30319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * the case where on-line resizing is not enabled (in which case the
30419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * resize inode should be cleared) as well as the case where on-line
30519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * resizing is enabled.
30619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
3073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtvoid check_resize_inode(e2fsck_t ctx)
30819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
30919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_filsys fs = ctx->fs;
31019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct ext2_inode inode;
31119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct problem_context	pctx;
31219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int		i, gdt_off, ind_off;
31319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	dgrp_t		j;
31419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	blk_t		blk, pblk, expect;
31519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	__u32 		*dind_buf = 0, *ind_buf;
31619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t	retval;
31719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
31819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	clear_problem_context(&pctx);
31919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
3203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/*
3213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * If the resize inode feature isn't set, then
32219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * s_reserved_gdt_blocks must be zero.
32319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
3243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!(fs->super->s_feature_compat &
32519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	      EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
32619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (fs->super->s_reserved_gdt_blocks) {
32719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			pctx.num = fs->super->s_reserved_gdt_blocks;
32819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
32919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					&pctx)) {
33019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				fs->super->s_reserved_gdt_blocks = 0;
33119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				ext2fs_mark_super_dirty(fs);
33219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
33319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
33419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
33519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
33619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/* Read the resize inode */
33719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	pctx.ino = EXT2_RESIZE_INO;
33819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
33919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (retval) {
3403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (fs->super->s_feature_compat &
34119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    EXT2_FEATURE_COMPAT_RESIZE_INODE)
34219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ctx->flags |= E2F_FLAG_RESIZE_INODE;
34319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return;
34419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
34519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
3463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/*
3473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * If the resize inode feature isn't set, check to make sure
34819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * the resize inode is cleared; then we're done.
34919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
3503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!(fs->super->s_feature_compat &
35119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	      EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
35219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		for (i=0; i < EXT2_N_BLOCKS; i++) {
35319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (inode.i_block[i])
35419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				break;
35519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
35619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if ((i < EXT2_N_BLOCKS) &&
35719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
35819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			memset(&inode, 0, sizeof(inode));
35919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
36019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					   "clear_resize");
36119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
36219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return;
36319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
36419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
3653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/*
36619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * The resize inode feature is enabled; check to make sure the
36719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * only block in use is the double indirect block
36819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
36919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	blk = inode.i_block[EXT2_DIND_BLOCK];
37019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	for (i=0; i < EXT2_N_BLOCKS; i++) {
37119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (i != EXT2_DIND_BLOCK && inode.i_block[i])
37219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			break;
37319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
37419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
37519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    !(inode.i_mode & LINUX_S_IFREG) ||
37619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    (blk < fs->super->s_first_data_block ||
37719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	     blk >= fs->super->s_blocks_count)) {
37819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	resize_inode_invalid:
37919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
38019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			memset(&inode, 0, sizeof(inode));
38119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
38219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					   "clear_resize");
38319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ctx->flags |= E2F_FLAG_RESIZE_INODE;
38419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
38519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (!(ctx->options & E2F_OPT_READONLY)) {
38619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			fs->super->s_state &= ~EXT2_VALID_FS;
38719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ext2fs_mark_super_dirty(fs);
38819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
38919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		goto cleanup;
39019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
39119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
39219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project						    "resize dind buffer");
39319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
39419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
39519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	retval = ext2fs_read_ind_block(fs, blk, dind_buf);
39619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (retval)
39719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		goto resize_inode_invalid;
39819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
39919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	gdt_off = fs->desc_blocks;
40019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
4013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
40219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	     i++, gdt_off++, pblk++) {
40319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		gdt_off %= fs->blocksize/4;
40419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (dind_buf[gdt_off] != pblk)
40519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			goto resize_inode_invalid;
40619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
4073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval)
40819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			goto resize_inode_invalid;
40919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ind_off = 0;
41019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		for (j = 1; j < fs->group_desc_count; j++) {
41119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (!ext2fs_bg_has_super(fs, j))
41219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				continue;
41319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			expect = pblk + (j * fs->super->s_blocks_per_group);
41419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (ind_buf[ind_off] != expect)
41519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				goto resize_inode_invalid;
41619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ind_off++;
41719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
41819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
41919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
42019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectcleanup:
42119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (dind_buf)
42219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_free_mem(&dind_buf);
42319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
42419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project }
42519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
42619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
42719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This function checks the dirhash signed/unsigned hint if necessary.
42819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
42919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void e2fsck_fix_dirhash_hint(e2fsck_t ctx)
43019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
43119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct ext2_super_block *sb = ctx->fs->super;
43219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct problem_context pctx;
43319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	char	c;
43419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
43519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if ((ctx->options & E2F_OPT_READONLY) ||
43619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    !(sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
43719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    (sb->s_flags & (EXT2_FLAGS_SIGNED_HASH|EXT2_FLAGS_UNSIGNED_HASH)))
43819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return;
43919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
44019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	c = (char) 255;
44119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
44219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	clear_problem_context(&pctx);
44319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (fix_problem(ctx, PR_0_DIRHASH_HINT, &pctx)) {
44419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (((int) c) == -1) {
44519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			sb->s_flags |= EXT2_FLAGS_SIGNED_HASH;
44619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		} else {
44719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			sb->s_flags |= EXT2_FLAGS_UNSIGNED_HASH;
44819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
44919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_mark_super_dirty(ctx->fs);
45019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
45119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
45219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
45319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
45419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectvoid check_super_block(e2fsck_t ctx)
45519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
45619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_filsys fs = ctx->fs;
45719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	blk_t	first_block, last_block;
45819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct ext2_super_block *sb = fs->super;
45919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct ext2_group_desc *gd;
4603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	problem_t	problem;
46119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	blk_t	blocks_per_group = fs->super->s_blocks_per_group;
46219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	blk_t	bpg_max;
46319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int	inodes_per_block;
46419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int	ipg_max;
46519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int	inode_size;
4663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int	accept_time_fudge;
4678558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall	int	broken_system_clock;
46819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	dgrp_t	i;
46919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	blk_t	should_be;
47019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct problem_context	pctx;
4713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	blk_t	free_blocks = 0;
4723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	ino_t	free_inodes = 0;
4733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int     csum_flag, clear_test_fs_flag;
47419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
47519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
47619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ipg_max = inodes_per_block * (blocks_per_group - 4);
47719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
47819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
47919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
48019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
48119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
48219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
48319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
48419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
48519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
48619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
48719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
48819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		sizeof(int) * fs->group_desc_count, "invalid_inode_table");
48919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
49019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	clear_problem_context(&pctx);
49119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
49219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
49319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * Verify the super block constants...
49419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
49519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	check_super_value(ctx, "inodes_count", sb->s_inodes_count,
49619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			  MIN_CHECK, 1, 0);
49719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	check_super_value(ctx, "blocks_count", sb->s_blocks_count,
49819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			  MIN_CHECK, 1, 0);
49919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	check_super_value(ctx, "first_data_block", sb->s_first_data_block,
50019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			  MAX_CHECK, 0, sb->s_blocks_count);
50119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	check_super_value(ctx, "log_block_size", sb->s_log_block_size,
50219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			  MIN_CHECK | MAX_CHECK, 0,
50319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			  EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
50419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
50519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			  MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
50619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
50719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			  MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
50819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			  bpg_max);
50919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
51019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			  MIN_CHECK | MAX_CHECK, 8, bpg_max);
51119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
51219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			  MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
51319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
51419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			  MAX_CHECK, 0, sb->s_blocks_count / 2);
5153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	check_super_value(ctx, "reserved_gdt_blocks",
51619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			  sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
51719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			  fs->blocksize/4);
5183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (sb->s_rev_level > EXT2_GOOD_OLD_REV)
5193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		check_super_value(ctx, "first_ino", sb->s_first_ino,
5203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				  MIN_CHECK | MAX_CHECK,
5213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				  EXT2_GOOD_OLD_FIRST_INO, sb->s_inodes_count);
52219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	inode_size = EXT2_INODE_SIZE(sb);
52319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	check_super_value(ctx, "inode_size",
52419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			  inode_size, MIN_CHECK | MAX_CHECK,
52519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			  EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
52619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (inode_size & (inode_size - 1)) {
52719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx.num = inode_size;
52819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx.str = "inode_size";
52919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
53019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
53119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return;
53219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
5333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
53419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if ((ctx->flags & E2F_FLAG_GOT_DEVSIZE) &&
53519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    (ctx->num_blocks < sb->s_blocks_count)) {
53619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx.blk = sb->s_blocks_count;
53719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx.blk2 = ctx->num_blocks;
53819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
53919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ctx->flags |= E2F_FLAG_ABORT;
54019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return;
54119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
54219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
54319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
54419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
54519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx.blk = EXT2_BLOCK_SIZE(sb);
54619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx.blk2 = EXT2_FRAG_SIZE(sb);
54719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
54819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ctx->flags |= E2F_FLAG_ABORT;
54919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return;
55019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
55119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
55219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	should_be = sb->s_frags_per_group >>
5533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		(sb->s_log_block_size - sb->s_log_frag_size);
55419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (sb->s_blocks_per_group != should_be) {
55519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx.blk = sb->s_blocks_per_group;
55619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx.blk2 = should_be;
55719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
55819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ctx->flags |= E2F_FLAG_ABORT;
55919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return;
56019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
56119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
56219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	should_be = (sb->s_log_block_size == 0) ? 1 : 0;
56319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (sb->s_first_data_block != should_be) {
56419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx.blk = sb->s_first_data_block;
56519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx.blk2 = should_be;
56619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
56719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ctx->flags |= E2F_FLAG_ABORT;
56819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return;
56919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
57019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
57119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	should_be = sb->s_inodes_per_group * fs->group_desc_count;
57219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (sb->s_inodes_count != should_be) {
57319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx.ino = sb->s_inodes_count;
57419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx.ino2 = should_be;
57519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
57619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			sb->s_inodes_count = should_be;
57719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ext2fs_mark_super_dirty(fs);
57819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
57919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
58019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
58119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
58219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * Verify the group descriptors....
58319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
5843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	first_block = sb->s_first_data_block;
5853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	last_block = sb->s_blocks_count-1;
58619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
5873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
5883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					       EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
58919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
59019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx.group = i;
59119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
5923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super,
5933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					       EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
5943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			first_block = ext2fs_group_first_block(fs, i);
5953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			last_block = ext2fs_group_last_block(fs, i);
5963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
59719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
59819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if ((gd->bg_block_bitmap < first_block) ||
59919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    (gd->bg_block_bitmap > last_block)) {
60019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			pctx.blk = gd->bg_block_bitmap;
60119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
60219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				gd->bg_block_bitmap = 0;
60319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
60419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (gd->bg_block_bitmap == 0) {
60519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ctx->invalid_block_bitmap_flag[i]++;
60619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ctx->invalid_bitmaps++;
60719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
60819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if ((gd->bg_inode_bitmap < first_block) ||
60919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    (gd->bg_inode_bitmap > last_block)) {
61019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			pctx.blk = gd->bg_inode_bitmap;
61119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
61219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				gd->bg_inode_bitmap = 0;
61319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
61419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (gd->bg_inode_bitmap == 0) {
61519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ctx->invalid_inode_bitmap_flag[i]++;
61619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ctx->invalid_bitmaps++;
61719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
61819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if ((gd->bg_inode_table < first_block) ||
61919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    ((gd->bg_inode_table +
62019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		      fs->inode_blocks_per_group - 1) > last_block)) {
62119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			pctx.blk = gd->bg_inode_table;
62219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
62319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				gd->bg_inode_table = 0;
62419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
62519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (gd->bg_inode_table == 0) {
62619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ctx->invalid_inode_table_flag[i]++;
62719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ctx->invalid_bitmaps++;
62819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
62919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		free_blocks += gd->bg_free_blocks_count;
63019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		free_inodes += gd->bg_free_inodes_count;
63119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
63219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
63319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
63419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    (gd->bg_used_dirs_count > sb->s_inodes_per_group))
63519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ext2fs_unmark_valid(fs);
63619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
6373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		should_be = 0;
6383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (!ext2fs_group_desc_csum_verify(fs, i)) {
6393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (fix_problem(ctx, PR_0_GDT_CSUM, &pctx)) {
6403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				gd->bg_flags &=	~(EXT2_BG_BLOCK_UNINIT |
6413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				                  EXT2_BG_INODE_UNINIT);
6423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				gd->bg_itable_unused = 0;
6433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				should_be = 1;
6443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			}
6453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ext2fs_unmark_valid(fs);
6463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
6473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
6483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (!csum_flag &&
6493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    (gd->bg_flags &(EXT2_BG_BLOCK_UNINIT|EXT2_BG_INODE_UNINIT)||
6503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		     gd->bg_itable_unused != 0)){
6513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (fix_problem(ctx, PR_0_GDT_UNINIT, &pctx)) {
6523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				gd->bg_flags &= ~(EXT2_BG_BLOCK_UNINIT |
6533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt						  EXT2_BG_INODE_UNINIT);
6543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				gd->bg_itable_unused = 0;
6553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				should_be = 1;
6563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			}
6573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ext2fs_unmark_valid(fs);
6583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
6593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
6603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (i == fs->group_desc_count - 1 &&
6613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    gd->bg_flags & EXT2_BG_BLOCK_UNINIT) {
6623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (fix_problem(ctx, PR_0_BB_UNINIT_LAST, &pctx)) {
6633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				gd->bg_flags &= ~EXT2_BG_BLOCK_UNINIT;
6643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				should_be = 1;
6653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			}
6663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ext2fs_unmark_valid(fs);
6673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
6683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
6693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (gd->bg_flags & EXT2_BG_BLOCK_UNINIT &&
6703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    !(gd->bg_flags & EXT2_BG_INODE_UNINIT)) {
6713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (fix_problem(ctx, PR_0_BB_UNINIT_IB_INIT, &pctx)) {
6723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				gd->bg_flags &= ~EXT2_BG_BLOCK_UNINIT;
6733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				should_be = 1;
6743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			}
6753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ext2fs_unmark_valid(fs);
6763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
6773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
6783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (csum_flag &&
6793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    (gd->bg_itable_unused > gd->bg_free_inodes_count ||
6803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		     gd->bg_itable_unused > sb->s_inodes_per_group)) {
6813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			pctx.blk = gd->bg_itable_unused;
6823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (fix_problem(ctx, PR_0_GDT_ITABLE_UNUSED, &pctx)) {
6833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				gd->bg_itable_unused = 0;
6843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				should_be = 1;
6853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			}
6863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ext2fs_unmark_valid(fs);
6873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
6883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
6893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (should_be)
6903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ext2fs_group_desc_csum_set(fs, i);
69119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
69219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
69319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
69419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * Update the global counts from the block group counts.  This
69519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * is needed for an experimental patch which eliminates
69619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * locking the entire filesystem when allocating blocks or
69719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * inodes; if the filesystem is not unmounted cleanly, the
69819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * global counts may not be accurate.
69919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
70019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if ((free_blocks != sb->s_free_blocks_count) ||
70119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    (free_inodes != sb->s_free_inodes_count)) {
70219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (ctx->options & E2F_OPT_READONLY)
70319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ext2fs_unmark_valid(fs);
70419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		else {
70519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			sb->s_free_blocks_count = free_blocks;
70619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			sb->s_free_inodes_count = free_inodes;
70719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ext2fs_mark_super_dirty(fs);
70819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
70919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
7103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
71119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
71219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    (sb->s_free_inodes_count > sb->s_inodes_count))
71319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_unmark_valid(fs);
71419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
71519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
71619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
71719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * If we have invalid bitmaps, set the error state of the
71819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * filesystem.
71919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
72019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
72119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		sb->s_state &= ~EXT2_VALID_FS;
72219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_mark_super_dirty(fs);
72319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
72419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
72519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	clear_problem_context(&pctx);
7263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
72719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifndef EXT2_SKIP_UUID
72819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
72919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * If the UUID field isn't assigned, assign it.
73019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
73119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
73219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
73319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			uuid_generate(sb->s_uuid);
73419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ext2fs_mark_super_dirty(fs);
73519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
73619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
73719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
73819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
73919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
74019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
7413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * Check to see if we should disable the test_fs flag
7423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 */
7433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	profile_get_boolean(ctx->profile, "options",
7443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			    "clear_test_fs_flag", 0, 1,
7453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			    &clear_test_fs_flag);
7463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!(ctx->options & E2F_OPT_READONLY) &&
7473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	    clear_test_fs_flag &&
7483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	    (fs->super->s_flags & EXT2_FLAGS_TEST_FILESYS) &&
7493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	    (fs_proc_check("ext4") || check_for_modules("ext4"))) {
7503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (fix_problem(ctx, PR_0_CLEAR_TESTFS_FLAG, &pctx)) {
7513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			fs->super->s_flags &= ~EXT2_FLAGS_TEST_FILESYS;
7523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ext2fs_mark_super_dirty(fs);
7533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
7543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
7553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
7563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
7573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/*
75819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * For the Hurd, check to see if the filetype option is set,
75919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * since it doesn't support it.
76019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
76119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!(ctx->options & E2F_OPT_READONLY) &&
76219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    fs->super->s_creator_os == EXT2_OS_HURD &&
76319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    (fs->super->s_feature_incompat &
76419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	     EXT2_FEATURE_INCOMPAT_FILETYPE)) {
76519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
76619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			fs->super->s_feature_incompat &=
76719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				~EXT2_FEATURE_INCOMPAT_FILETYPE;
76819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ext2fs_mark_super_dirty(fs);
76919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
77019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
77119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
77219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
77319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
77419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * If we have any of the compatibility flags set, we need to have a
77519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * revision 1 filesystem.  Most kernels will not check the flags on
77619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * a rev 0 filesystem and we may have corruption issues because of
77719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * the incompatible changes to the filesystem.
77819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
77919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!(ctx->options & E2F_OPT_READONLY) &&
78019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
78119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    (fs->super->s_feature_compat ||
78219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	     fs->super->s_feature_ro_compat ||
78319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	     fs->super->s_feature_incompat) &&
78419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
78519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_update_dynamic_rev(fs);
78619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_mark_super_dirty(fs);
78719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
78819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
78919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
79019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
79119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * Clean up any orphan inodes, if present.
79219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
79319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
79419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fs->super->s_state &= ~EXT2_VALID_FS;
79519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_mark_super_dirty(fs);
79619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
79719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
79819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
7993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * Unfortunately, due to Windows' unfortunate design decision
8003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * to configure the hardware clock to tick localtime, instead
8013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * of the more proper and less error-prone UTC time, many
8023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * users end up in the situation where the system clock is
8033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * incorrectly set at the time when e2fsck is run.
8043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 *
8053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * Historically this was usually due to some distributions
8063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * having buggy init scripts and/or installers that didn't
8073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * correctly detect this case and take appropriate
8083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * countermeasures.  However, it's still possible, despite the
8093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * best efforts of init script and installer authors to not be
8103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * able to detect this misconfiguration, usually due to a
8113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * buggy or misconfigured virtualization manager or the
8123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * installer not having access to a network time server during
8133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * the installation process.  So by default, we allow the
8143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * superblock times to be fudged by up to 24 hours.  This can
8153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * be disabled by setting options.accept_time_fudge to the
8163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * boolean value of false in e2fsck.conf.  We also support
8173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * options.buggy_init_scripts for backwards compatibility.
81819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
8193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	profile_get_boolean(ctx->profile, "options", "accept_time_fudge",
8203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			    0, 1, &accept_time_fudge);
82119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	profile_get_boolean(ctx->profile, "options", "buggy_init_scripts",
8223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			    0, accept_time_fudge, &accept_time_fudge);
8233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	ctx->time_fudge = accept_time_fudge ? 86400 : 0;
82419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
8258558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall	profile_get_boolean(ctx->profile, "options", "broken_system_clock",
8268558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall			    0, 0, &broken_system_clock);
8278558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall
8283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/*
82919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * Check to see if the superblock last mount time or last
83019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * write time is in the future.
83119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
8328558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall	if (!broken_system_clock &&
8338558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall	    !(ctx->flags & E2F_FLAG_TIME_INSANE) &&
8348558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall	    fs->super->s_mtime > (__u32) ctx->now) {
83519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx.num = fs->super->s_mtime;
8363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		problem = PR_0_FUTURE_SB_LAST_MOUNT;
8373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (fs->super->s_mtime <= (__u32) ctx->now + ctx->time_fudge)
8383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			problem = PR_0_FUTURE_SB_LAST_MOUNT_FUDGED;
8393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (fix_problem(ctx, problem, &pctx)) {
84019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			fs->super->s_mtime = ctx->now;
84119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ext2fs_mark_super_dirty(fs);
84219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
84319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
8448558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall	if (!broken_system_clock &&
8458558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall	    !(ctx->flags & E2F_FLAG_TIME_INSANE) &&
8468558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall	    fs->super->s_wtime > (__u32) ctx->now) {
84719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pctx.num = fs->super->s_wtime;
8483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		problem = PR_0_FUTURE_SB_LAST_WRITE;
8493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (fs->super->s_wtime <= (__u32) ctx->now + ctx->time_fudge)
8503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			problem = PR_0_FUTURE_SB_LAST_WRITE_FUDGED;
8513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (fix_problem(ctx, problem, &pctx)) {
85219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			fs->super->s_wtime = ctx->now;
85319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ext2fs_mark_super_dirty(fs);
85419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
85519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
85619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
85719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
85819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * Move the ext3 journal file, if necessary.
85919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
86019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	e2fsck_move_ext3_journal(ctx);
86119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
86219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
86319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * Fix journal hint, if necessary
86419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
86519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	e2fsck_fix_ext3_journal_hint(ctx);
86619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
86719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
86819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * Add dirhash hint if necessary
86919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
87019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	e2fsck_fix_dirhash_hint(ctx);
87119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
87219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return;
87319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
87419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
87519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
87619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Check to see if we should backup the master sb to the backup super
87719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * blocks.  Returns non-zero if the sb should be backed up.
87819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
87919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
88019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
88119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * A few flags are set on the fly by the kernel, but only in the
88219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * primary superblock.  This is actually a bad thing, and we should
88319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * try to discourage it in the future.  In particular, for the newer
88419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * ext4 files, especially EXT4_FEATURE_RO_COMPAT_DIR_NLINK and
88519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * EXT3_FEATURE_INCOMPAT_EXTENTS.  So some of these may go away in the
8863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * future.  EXT3_FEATURE_INCOMPAT_RECOVER may also get set when
8873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * copying the primary superblock during online resize.
88819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *
88919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * The kernel will set EXT2_FEATURE_COMPAT_EXT_ATTR, but
89019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * unfortunately, we shouldn't ignore it since if it's not set in the
89119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * backup, the extended attributes in the filesystem will be stripped
89219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * away.
89319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
89419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#define FEATURE_RO_COMPAT_IGNORE	(EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
89519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					 EXT4_FEATURE_RO_COMPAT_DIR_NLINK)
8963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#define FEATURE_INCOMPAT_IGNORE		(EXT3_FEATURE_INCOMPAT_EXTENTS| \
8973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					 EXT3_FEATURE_INCOMPAT_RECOVER)
89819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
89919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectint check_backup_super_block(e2fsck_t ctx)
90019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
90119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2_filsys	fs = ctx->fs;
90219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t	retval;
90319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	dgrp_t		g;
90419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	blk_t		sb;
90519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int		ret = 0;
9063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	char		buf[SUPERBLOCK_SIZE];
9073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct ext2_super_block	*backup_sb;
90819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
90919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/*
91019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * If we are already writing out the backup blocks, then we
91119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * don't need to test.  Also, if the filesystem is invalid, or
91219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * the check was aborted or cancelled, we also don't want to
91319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * do the backup.  If the filesystem was opened read-only then
91419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 * we can't do the backup.
91519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	 */
91619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (((fs->flags & EXT2_FLAG_MASTER_SB_ONLY) == 0) ||
91719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    !ext2fs_test_valid(fs) ||
91819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    (fs->super->s_state & EXT2_ERROR_FS) ||
91919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    (ctx->flags & (E2F_FLAG_ABORT | E2F_FLAG_CANCEL)) ||
92019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    (ctx->options & E2F_OPT_READONLY))
92119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 0;
92219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
92319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	for (g = 1; g < fs->group_desc_count; g++) {
92419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (!ext2fs_bg_has_super(fs, g))
92519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			continue;
92619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
92719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		sb = fs->super->s_first_data_block +
92819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			(g * fs->super->s_blocks_per_group);
92919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
9303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		retval = io_channel_read_blk(fs->io, sb, -SUPERBLOCK_SIZE,
9313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					     buf);
9323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (retval)
9333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			continue;
9343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		backup_sb = (struct ext2_super_block *) buf;
9353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef WORDS_BIGENDIAN
9363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ext2fs_swap_super(backup_sb);
9373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
9383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if ((backup_sb->s_magic != EXT2_SUPER_MAGIC) ||
9393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    (backup_sb->s_rev_level > EXT2_LIB_CURRENT_REV) ||
9403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    ((backup_sb->s_log_block_size + EXT2_MIN_BLOCK_LOG_SIZE) >
9413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		     EXT2_MAX_BLOCK_LOG_SIZE) ||
9423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    (EXT2_INODE_SIZE(backup_sb) < EXT2_GOOD_OLD_INODE_SIZE))
94319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			continue;
94419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
94519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#define SUPER_INCOMPAT_DIFFERENT(x)	\
9463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	((fs->super->x & ~FEATURE_INCOMPAT_IGNORE) !=	\
9473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 (backup_sb->x & ~FEATURE_INCOMPAT_IGNORE))
94819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#define SUPER_RO_COMPAT_DIFFERENT(x)	\
9493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	((fs->super->x & ~FEATURE_RO_COMPAT_IGNORE) !=	\
9503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 (backup_sb->x & ~FEATURE_RO_COMPAT_IGNORE))
95119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#define SUPER_DIFFERENT(x)		\
9523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	(fs->super->x != backup_sb->x)
95319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
95419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (SUPER_DIFFERENT(s_feature_compat) ||
95519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    SUPER_INCOMPAT_DIFFERENT(s_feature_incompat) ||
95619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    SUPER_RO_COMPAT_DIFFERENT(s_feature_ro_compat) ||
95719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    SUPER_DIFFERENT(s_blocks_count) ||
95819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		    SUPER_DIFFERENT(s_inodes_count) ||
9593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    memcmp(fs->super->s_uuid, backup_sb->s_uuid,
96019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			   sizeof(fs->super->s_uuid)))
96119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			ret = 1;
96219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		break;
96319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
96419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return ret;
96519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
966