11b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o/*
21b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * e2fsck.c - superblock checks
3efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o *
41b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
51b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o *
61b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * %Begin-Header%
71b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * This file may be redistributed under the terms of the GNU Public
81b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * License.
91b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o * %End-Header%
101b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o */
111b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o
121b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o#ifdef HAVE_ERRNO_H
131b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o#include <errno.h>
141b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o#endif
151b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o
1654be2ccc2251784fd771590a5e72827afd82df40Theodore Ts'o#ifndef EXT2_SKIP_UUID
171b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o#include "uuid/uuid.h"
1854be2ccc2251784fd771590a5e72827afd82df40Theodore Ts'o#endif
191b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o#include "e2fsck.h"
201b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o#include "problem.h"
211b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o
221b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o#define MIN_CHECK 1
231b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o#define MAX_CHECK 2
24e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define LOG2_CHECK 4
251b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o
261b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic void check_super_value(e2fsck_t ctx, const char *descr,
271b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			      unsigned long value, int flags,
287f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o			      unsigned long min_val, unsigned long max_val)
291b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o{
301b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	struct		problem_context pctx;
311b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o
327f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o	if (((flags & MIN_CHECK) && (value < min_val)) ||
33e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	    ((flags & MAX_CHECK) && (value > max_val)) ||
34e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	    ((flags & LOG2_CHECK) && (value & (value - 1) != 0))) {
351b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		clear_problem_context(&pctx);
361b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		pctx.num = value;
371b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		pctx.str = descr;
381b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
3908b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
401b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	}
411b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o}
421b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o
434313932cd77c9323fbfe4cacf4d1dc84c95a39deTheodore Ts'o/*
4480bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o * helper function to release an inode
4580bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o */
4680bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'ostruct process_block_struct {
478394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	e2fsck_t 	ctx;
488394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	char 		*buf;
4980bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	struct problem_context *pctx;
508394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	int		truncating;
518394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	int		truncate_offset;
52544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	e2_blkcnt_t	truncate_block;
538394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	int		truncated_blocks;
548394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	int		abort;
558394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	errcode_t	errcode;
5680bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o};
5780bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o
5880bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'ostatic int release_inode_block(ext2_filsys fs,
59e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			       blk64_t	*block_nr,
60544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o			       e2_blkcnt_t blockcnt,
61e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			       blk64_t	ref_blk EXT2FS_ATTR((unused)),
62544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o			       int	ref_offset EXT2FS_ATTR((unused)),
6380bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o			       void *priv_data)
6480bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o{
6580bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	struct process_block_struct *pb;
668394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	e2fsck_t 		ctx;
678394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	struct problem_context	*pctx;
68e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t			blk = *block_nr;
698394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	int			retval = 0;
7080bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o
7180bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	pb = (struct process_block_struct *) priv_data;
7280bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	ctx = pb->ctx;
7380bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	pctx = pb->pctx;
7480bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o
7580bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	pctx->blk = blk;
7680bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	pctx->blkcount = blockcnt;
7780bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o
7880bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	if (HOLE_BLKADDR(blk))
7980bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o		return 0;
8080bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o
8180bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	if ((blk < fs->super->s_first_data_block) ||
82e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	    (blk >= ext2fs_blocks_count(fs->super))) {
8380bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o		fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
8453ef44c40a3e425d2c700d8fd77a6b655aa121feTheodore Ts'o	return_abort:
8580bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o		pb->abort = 1;
8680bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o		return BLOCK_ABORT;
8780bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	}
8880bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o
89e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (!ext2fs_test_block_bitmap2(fs->block_map, blk)) {
9080bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o		fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
9153ef44c40a3e425d2c700d8fd77a6b655aa121feTheodore Ts'o		goto return_abort;
928394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	}
938394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o
948394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	/*
958394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	 * If we are deleting an orphan, then we leave the fields alone.
968394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	 * If we are truncating an orphan, then update the inode fields
978394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	 * and clean up any partial block data.
988394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	 */
998394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	if (pb->truncating) {
1008394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		/*
1018394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		 * We only remove indirect blocks if they are
1028394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		 * completely empty.
1038394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		 */
1048394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		if (blockcnt < 0) {
1058394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o			int	i, limit;
10653ef44c40a3e425d2c700d8fd77a6b655aa121feTheodore Ts'o			blk_t	*bp;
107efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
108e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			pb->errcode = io_channel_read_blk64(fs->io, blk, 1,
1098394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o							pb->buf);
1108394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o			if (pb->errcode)
11153ef44c40a3e425d2c700d8fd77a6b655aa121feTheodore Ts'o				goto return_abort;
1128394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o
1138394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o			limit = fs->blocksize >> 2;
11453ef44c40a3e425d2c700d8fd77a6b655aa121feTheodore Ts'o			for (i = 0, bp = (blk_t *) pb->buf;
11553ef44c40a3e425d2c700d8fd77a6b655aa121feTheodore Ts'o			     i < limit;	 i++, bp++)
11653ef44c40a3e425d2c700d8fd77a6b655aa121feTheodore Ts'o				if (*bp)
1178394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o					return 0;
1188394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		}
1198394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		/*
1208394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		 * We don't remove direct blocks until we've reached
1218394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		 * the truncation block.
1228394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		 */
1238394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		if (blockcnt >= 0 && blockcnt < pb->truncate_block)
1248394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o			return 0;
1258394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		/*
1268394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		 * If part of the last block needs truncating, we do
1278394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		 * it here.
1288394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		 */
1298394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
130e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			pb->errcode = io_channel_read_blk64(fs->io, blk, 1,
1318394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o							pb->buf);
1328394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o			if (pb->errcode)
13353ef44c40a3e425d2c700d8fd77a6b655aa121feTheodore Ts'o				goto return_abort;
1348394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o			memset(pb->buf + pb->truncate_offset, 0,
1358394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o			       fs->blocksize - pb->truncate_offset);
136e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			pb->errcode = io_channel_write_blk64(fs->io, blk, 1,
1378394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o							 pb->buf);
1388394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o			if (pb->errcode)
13953ef44c40a3e425d2c700d8fd77a6b655aa121feTheodore Ts'o				goto return_abort;
1408394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		}
1418394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		pb->truncated_blocks++;
1428394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		*block_nr = 0;
1438394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		retval |= BLOCK_CHANGED;
14480bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	}
145efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
146e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	ext2fs_block_alloc_stats2(fs, blk, -1);
147e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	ctx->free_blocks++;
1488394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	return retval;
14980bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o}
150efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
15180bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o/*
15280bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o * This function releases an inode.  Returns 1 if an inconsistency was
1538394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o * found.  If the inode has a link count, then it is being truncated and
1548394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o * not deleted.
15580bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o */
15686c627ec1136446409a0170d439e60c148e6eb48Theodore Ts'ostatic int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
157721edd0eddcfb4ebdd4fba22338a674477795acdTheodore Ts'o				struct ext2_inode *inode, char *block_buf,
15880bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o				struct problem_context *pctx)
15980bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o{
1600684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o	struct process_block_struct 	pb;
1618394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	ext2_filsys			fs = ctx->fs;
16280bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	errcode_t			retval;
1630684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o	__u32				count;
16480bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o
165e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (!ext2fs_inode_has_valid_blocks2(fs, inode))
16642475e281d22dbefd7f0b399f6056f642fa0ab92Theodore Ts'o		return 0;
16742475e281d22dbefd7f0b399f6056f642fa0ab92Theodore Ts'o
1688394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	pb.buf = block_buf + 3 * ctx->fs->blocksize;
16980bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	pb.ctx = ctx;
17080bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	pb.abort = 0;
1718394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	pb.errcode = 0;
17280bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	pb.pctx = pctx;
1738394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	if (inode->i_links_count) {
1748394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		pb.truncating = 1;
175544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o		pb.truncate_block = (e2_blkcnt_t)
176e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			((EXT2_I_SIZE(inode) + fs->blocksize - 1) /
1778394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o			 fs->blocksize);
1788394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		pb.truncate_offset = inode->i_size % fs->blocksize;
1798394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	} else {
1808394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		pb.truncating = 0;
1818394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		pb.truncate_block = 0;
1828394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		pb.truncate_offset = 0;
1838394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	}
1848394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	pb.truncated_blocks = 0;
185e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	retval = ext2fs_block_iterate3(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
1868394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o				      block_buf, release_inode_block, &pb);
18780bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	if (retval) {
1888394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		com_err("release_inode_blocks", retval,
18980bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o			_("while calling ext2fs_block_iterate for inode %d"),
19080bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o			ino);
19180bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o		return 1;
19280bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	}
19380bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	if (pb.abort)
19480bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o		return 1;
19580bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o
1968394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	/* Refresh the inode since ext2fs_block_iterate may have changed it */
1978394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
1988394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o
1998394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	if (pb.truncated_blocks)
2001ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o		ext2fs_iblk_sub_blocks(fs, inode, pb.truncated_blocks);
2018394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o
202e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (ext2fs_file_acl_block(fs, inode)) {
203e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		retval = ext2fs_adjust_ea_refcount2(fs,
204e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					ext2fs_file_acl_block(fs, inode),
205e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					block_buf, -1, &count);
2060684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o		if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
2070684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o			retval = 0;
2080684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o			count = 1;
2090684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o		}
2100684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o		if (retval) {
2110684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o			com_err("release_inode_blocks", retval,
212e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		_("while calling ext2fs_adjust_ea_refcount2 for inode %d"),
2130684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o				ino);
2140684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o			return 1;
2150684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o		}
216e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (count == 0) {
217e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ext2fs_block_alloc_stats2(fs,
218e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					ext2fs_file_acl_block(fs, inode), -1);
219e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ctx->free_blocks++;
220e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		}
221e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_file_acl_block_set(fs, inode, 0);
2220684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o	}
22380bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	return 0;
22480bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o}
22580bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o
22680bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o/*
22780bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o * This function releases all of the orphan inodes.  It returns 1 if
22880bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o * it hit some error, and 0 on success.
22980bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o */
23080bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'ostatic int release_orphan_inodes(e2fsck_t ctx)
23180bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o{
23280bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	ext2_filsys fs = ctx->fs;
23386c627ec1136446409a0170d439e60c148e6eb48Theodore Ts'o	ext2_ino_t	ino, next_ino;
23480bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	struct ext2_inode inode;
23580bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	struct problem_context pctx;
23680bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	char *block_buf;
23780bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o
23880bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	if ((ino = fs->super->s_last_orphan) == 0)
23980bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o		return 0;
24080bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o
24125c63ba09fbdb5ab0f7385af156bd18165b3e76dTheodore Ts'o	/*
24225c63ba09fbdb5ab0f7385af156bd18165b3e76dTheodore Ts'o	 * Win or lose, we won't be using the head of the orphan inode
24325c63ba09fbdb5ab0f7385af156bd18165b3e76dTheodore Ts'o	 * list again.
24425c63ba09fbdb5ab0f7385af156bd18165b3e76dTheodore Ts'o	 */
24525c63ba09fbdb5ab0f7385af156bd18165b3e76dTheodore Ts'o	fs->super->s_last_orphan = 0;
24625c63ba09fbdb5ab0f7385af156bd18165b3e76dTheodore Ts'o	ext2fs_mark_super_dirty(fs);
247eb4ab51044706e52fc78907130f2cb9458a7023bTheodore Ts'o
248eb4ab51044706e52fc78907130f2cb9458a7023bTheodore Ts'o	/*
249eb4ab51044706e52fc78907130f2cb9458a7023bTheodore Ts'o	 * If the filesystem contains errors, don't run the orphan
250eb4ab51044706e52fc78907130f2cb9458a7023bTheodore Ts'o	 * list, since the orphan list can't be trusted; and we're
251eb4ab51044706e52fc78907130f2cb9458a7023bTheodore Ts'o	 * going to be running a full e2fsck run anyway...
252eb4ab51044706e52fc78907130f2cb9458a7023bTheodore Ts'o	 */
253eb4ab51044706e52fc78907130f2cb9458a7023bTheodore Ts'o	if (fs->super->s_state & EXT2_ERROR_FS)
254eb4ab51044706e52fc78907130f2cb9458a7023bTheodore Ts'o		return 0;
255efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
25680bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	if ((ino < EXT2_FIRST_INODE(fs->super)) ||
25780bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	    (ino > fs->super->s_inodes_count)) {
25880bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o		clear_problem_context(&pctx);
25953ef44c40a3e425d2c700d8fd77a6b655aa121feTheodore Ts'o		pctx.ino = ino;
26080bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o		fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
26180bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o		return 1;
26280bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	}
26380bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o
2648394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o	block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
2659b5657591b1db9b82fe433f3f90e496f3df6a851Theodore Ts'o						    "block iterate buffer");
26680bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	e2fsck_read_bitmaps(ctx);
267efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
26880bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	while (ino) {
2698394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
27080bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o		clear_problem_context(&pctx);
271ecf1b7767e1772f4c6dba8f02026057ed05397bdTheodore Ts'o		pctx.ino = ino;
27280bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o		pctx.inode = &inode;
273f0b8c87d2a196ecc9a19998d512f3d9a46b758eaTheodore Ts'o		pctx.str = inode.i_links_count ? _("Truncating") :
274f0b8c87d2a196ecc9a19998d512f3d9a46b758eaTheodore Ts'o			_("Clearing");
27580bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o
2768394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
277ecf1b7767e1772f4c6dba8f02026057ed05397bdTheodore Ts'o
27880bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o		next_ino = inode.i_dtime;
27980bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o		if (next_ino &&
28099a2cc969fb47e8c87965aa9fb93cabf6fe4ac1eTheodore Ts'o		    ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
28199a2cc969fb47e8c87965aa9fb93cabf6fe4ac1eTheodore Ts'o		     (next_ino > fs->super->s_inodes_count))) {
28299a2cc969fb47e8c87965aa9fb93cabf6fe4ac1eTheodore Ts'o			pctx.ino = next_ino;
28380bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o			fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
28453ef44c40a3e425d2c700d8fd77a6b655aa121feTheodore Ts'o			goto return_abort;
28580bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o		}
28680bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o
2878394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
28853ef44c40a3e425d2c700d8fd77a6b655aa121feTheodore Ts'o			goto return_abort;
289ecf1b7767e1772f4c6dba8f02026057ed05397bdTheodore Ts'o
2908394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		if (!inode.i_links_count) {
2910684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o			ext2fs_inode_alloc_stats2(fs, ino, -1,
2920684a4f33b5c268fe12f57fcbc77a880c79ab282Theodore Ts'o						  LINUX_S_ISDIR(inode.i_mode));
293e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ctx->free_inodes++;
2941f3ad14a5ad5df3ac4012d41ef5d76411cd8fff3Theodore Ts'o			inode.i_dtime = ctx->now;
295eb16f861e908101a7f395971ca832a98f4935406Stephen Tweedie		} else {
296eb16f861e908101a7f395971ca832a98f4935406Stephen Tweedie			inode.i_dtime = 0;
2978394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		}
2988394902e04e64ed10ca81e869892c00143ee4931Theodore Ts'o		e2fsck_write_inode(ctx, ino, &inode, "delete_file");
29980bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o		ino = next_ino;
30080bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	}
301c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o	ext2fs_free_mem(&block_buf);
30280bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	return 0;
30353ef44c40a3e425d2c700d8fd77a6b655aa121feTheodore Ts'oreturn_abort:
304c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o	ext2fs_free_mem(&block_buf);
30580bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	return 1;
30680bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o}
30780bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o
308c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o/*
309c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o * Check the resize inode to make sure it is sane.  We check both for
310c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o * the case where on-line resizing is not enabled (in which case the
311c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o * resize inode should be cleared) as well as the case where on-line
312c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o * resizing is enabled.
313c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o */
31469d0edfd01ef81efd9f880231999975582ea8b60Theodore Ts'ovoid check_resize_inode(e2fsck_t ctx)
315c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o{
316c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o	ext2_filsys fs = ctx->fs;
317c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o	struct ext2_inode inode;
318c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o	struct problem_context	pctx;
319642935c082ca22e1186fc9926fe06e4207d5ab56Theodore Ts'o	int		i, gdt_off, ind_off;
320642935c082ca22e1186fc9926fe06e4207d5ab56Theodore Ts'o	dgrp_t		j;
321e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk_t		blk, pblk;
322e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk_t		expect;	/* for resize inode, which is 32-bit only */
323c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o	__u32 		*dind_buf = 0, *ind_buf;
324c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o	errcode_t	retval;
325c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o
326c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o	clear_problem_context(&pctx);
327c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o
328efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	/*
329efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	 * If the resize inode feature isn't set, then
330ea774315631accb05e2407765c6b448d648d14d6Theodore Ts'o	 * s_reserved_gdt_blocks must be zero.
331c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o	 */
332efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	if (!(fs->super->s_feature_compat &
333c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o	      EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
334c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o		if (fs->super->s_reserved_gdt_blocks) {
335c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o			pctx.num = fs->super->s_reserved_gdt_blocks;
336c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o			if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
337c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o					&pctx)) {
338c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o				fs->super->s_reserved_gdt_blocks = 0;
339c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o				ext2fs_mark_super_dirty(fs);
340c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o			}
341c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o		}
342ea774315631accb05e2407765c6b448d648d14d6Theodore Ts'o	}
343ea774315631accb05e2407765c6b448d648d14d6Theodore Ts'o
3441f3ad14a5ad5df3ac4012d41ef5d76411cd8fff3Theodore Ts'o	/* Read the resize inode */
345ea774315631accb05e2407765c6b448d648d14d6Theodore Ts'o	pctx.ino = EXT2_RESIZE_INO;
346ea774315631accb05e2407765c6b448d648d14d6Theodore Ts'o	retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
347ea774315631accb05e2407765c6b448d648d14d6Theodore Ts'o	if (retval) {
348efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		if (fs->super->s_feature_compat &
349ea774315631accb05e2407765c6b448d648d14d6Theodore Ts'o		    EXT2_FEATURE_COMPAT_RESIZE_INODE)
350ea774315631accb05e2407765c6b448d648d14d6Theodore Ts'o			ctx->flags |= E2F_FLAG_RESIZE_INODE;
351ea774315631accb05e2407765c6b448d648d14d6Theodore Ts'o		return;
352ea774315631accb05e2407765c6b448d648d14d6Theodore Ts'o	}
353ea774315631accb05e2407765c6b448d648d14d6Theodore Ts'o
354efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	/*
355efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	 * If the resize inode feature isn't set, check to make sure
356ea774315631accb05e2407765c6b448d648d14d6Theodore Ts'o	 * the resize inode is cleared; then we're done.
357ea774315631accb05e2407765c6b448d648d14d6Theodore Ts'o	 */
358efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	if (!(fs->super->s_feature_compat &
359ea774315631accb05e2407765c6b448d648d14d6Theodore Ts'o	      EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
360c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o		for (i=0; i < EXT2_N_BLOCKS; i++) {
361c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o			if (inode.i_block[i])
362c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o				break;
363c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o		}
364c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o		if ((i < EXT2_N_BLOCKS) &&
365c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o		    fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
366c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o			memset(&inode, 0, sizeof(inode));
367c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o			e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
368c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o					   "clear_resize");
369c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o		}
370c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o		return;
371c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o	}
372ea774315631accb05e2407765c6b448d648d14d6Theodore Ts'o
373efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	/*
374c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o	 * The resize inode feature is enabled; check to make sure the
375c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o	 * only block in use is the double indirect block
376c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o	 */
377c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o	blk = inode.i_block[EXT2_DIND_BLOCK];
378c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o	for (i=0; i < EXT2_N_BLOCKS; i++) {
379c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o		if (i != EXT2_DIND_BLOCK && inode.i_block[i])
380c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o			break;
381c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o	}
382d4dc0a9e29f9e50a46840bc130c6a816c4c7faa5Theodore Ts'o	if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
383d4dc0a9e29f9e50a46840bc130c6a816c4c7faa5Theodore Ts'o	    !(inode.i_mode & LINUX_S_IFREG) ||
384c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o	    (blk < fs->super->s_first_data_block ||
385e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	     blk >= ext2fs_blocks_count(fs->super))) {
386c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o	resize_inode_invalid:
387c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o		if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
388c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o			memset(&inode, 0, sizeof(inode));
389c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o			e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
390c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o					   "clear_resize");
391c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o			ctx->flags |= E2F_FLAG_RESIZE_INODE;
392c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o		}
393c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o		if (!(ctx->options & E2F_OPT_READONLY)) {
394c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o			fs->super->s_state &= ~EXT2_VALID_FS;
395c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o			ext2fs_mark_super_dirty(fs);
396c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o		}
397c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o		goto cleanup;
398c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o	}
399c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o	dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
400c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o						    "resize dind buffer");
401c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o	ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
402c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o
403dc8ce3463791366ac844d3f0436709511fa09c49Theodore Ts'o	retval = ext2fs_read_ind_block(fs, blk, dind_buf);
404c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o	if (retval)
405c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o		goto resize_inode_invalid;
406c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o
407c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o	gdt_off = fs->desc_blocks;
408c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o	pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
409e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (fs->blocksize == 1024 && fs->super->s_first_data_block == 0)
410e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		pblk++;	/* Deal with 1024 blocksize bigalloc fs */
411efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
412c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o	     i++, gdt_off++, pblk++) {
413c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o		gdt_off %= fs->blocksize/4;
414c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o		if (dind_buf[gdt_off] != pblk)
415c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o			goto resize_inode_invalid;
416dc8ce3463791366ac844d3f0436709511fa09c49Theodore Ts'o		retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
417efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		if (retval)
418c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o			goto resize_inode_invalid;
419c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o		ind_off = 0;
420c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o		for (j = 1; j < fs->group_desc_count; j++) {
421c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o			if (!ext2fs_bg_has_super(fs, j))
422c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o				continue;
423c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o			expect = pblk + (j * fs->super->s_blocks_per_group);
424c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o			if (ind_buf[ind_off] != expect)
425c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o				goto resize_inode_invalid;
426c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o			ind_off++;
427c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o		}
428c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o	}
429c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o
430c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'ocleanup:
431c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o	if (dind_buf)
432c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o		ext2fs_free_mem(&dind_buf);
433c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o
434c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o }
43580bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o
436f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o/*
437f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o * This function checks the dirhash signed/unsigned hint if necessary.
438f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o */
439642935c082ca22e1186fc9926fe06e4207d5ab56Theodore Ts'ostatic void e2fsck_fix_dirhash_hint(e2fsck_t ctx)
440f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o{
441f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o	struct ext2_super_block *sb = ctx->fs->super;
442f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o	struct problem_context pctx;
443f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o	char	c;
444f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o
445f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o	if ((ctx->options & E2F_OPT_READONLY) ||
446f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o	    !(sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
447f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o	    (sb->s_flags & (EXT2_FLAGS_SIGNED_HASH|EXT2_FLAGS_UNSIGNED_HASH)))
448f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o		return;
449f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o
450f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o	c = (char) 255;
451f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o
452f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o	clear_problem_context(&pctx);
453f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o	if (fix_problem(ctx, PR_0_DIRHASH_HINT, &pctx)) {
454f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o		if (((int) c) == -1) {
455f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o			sb->s_flags |= EXT2_FLAGS_SIGNED_HASH;
456f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o		} else {
457f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o			sb->s_flags |= EXT2_FLAGS_UNSIGNED_HASH;
458f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o		}
459f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o		ext2fs_mark_super_dirty(ctx->fs);
460f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o	}
461f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o}
462f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o
463f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o
4641b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ovoid check_super_block(e2fsck_t ctx)
4651b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o{
4661b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	ext2_filsys fs = ctx->fs;
467e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t	first_block, last_block;
4685dd8f963d04fa4099a003cb3b13ffae05ab29210Theodore Ts'o	struct ext2_super_block *sb = fs->super;
469e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	unsigned int	ipg_max;
47026ea4899d1fea0fbc5d28120944d2c2758ac1b11Theodore Ts'o	problem_t	problem;
471e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t	blocks_per_group = fs->super->s_blocks_per_group;
472e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	__u32	bpg_max, cpg_max;
47378cf05478d9b97e458212bffad5c782a7e543326Theodore Ts'o	int	inodes_per_block;
47489db86d33c634374a3f6e15f943ab83cdc5bd93aTheodore Ts'o	int	inode_size;
475ba5131f6d48eded504e84c2a8ffc8131df8a512eTheodore Ts'o	int	accept_time_fudge;
476177839e2454dcc298244481da9c72a19b41836beTheodore Ts'o	int	broken_system_clock;
4777f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o	dgrp_t	i;
478e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t	should_be;
4791b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	struct problem_context	pctx;
480e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t	free_blocks = 0;
4815d38ef1d049bf56d1c1e88b8b4d287c0f9470e61Valerie Clement	ino_t	free_inodes = 0;
48280875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	int     csum_flag, clear_test_fs_flag;
483b21bf267783274683a432eea6e5c589eab94123eAndreas Dilger
484b21bf267783274683a432eea6e5c589eab94123eAndreas Dilger	inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
485b21bf267783274683a432eea6e5c589eab94123eAndreas Dilger	ipg_max = inodes_per_block * (blocks_per_group - 4);
486b21bf267783274683a432eea6e5c589eab94123eAndreas Dilger	if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
487b21bf267783274683a432eea6e5c589eab94123eAndreas Dilger		ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
488e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	cpg_max = 8 * EXT2_BLOCK_SIZE(sb);
489e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (cpg_max > EXT2_MAX_CLUSTERS_PER_GROUP(sb))
490e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		cpg_max = EXT2_MAX_CLUSTERS_PER_GROUP(sb);
491e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	bpg_max = 8 * EXT2_BLOCK_SIZE(sb) * EXT2FS_CLUSTER_RATIO(fs);
492b21bf267783274683a432eea6e5c589eab94123eAndreas Dilger	if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
493b21bf267783274683a432eea6e5c589eab94123eAndreas Dilger		bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
4941b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o
49554dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o	ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
496f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o		 sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
49754dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o	ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
498f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o		 sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
49954dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o	ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
500f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o		sizeof(int) * fs->group_desc_count, "invalid_inode_table");
501b21bf267783274683a432eea6e5c589eab94123eAndreas Dilger
5021b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	clear_problem_context(&pctx);
5031b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o
5041b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	/*
5051b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	 * Verify the super block constants...
5061b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	 */
5075dd8f963d04fa4099a003cb3b13ffae05ab29210Theodore Ts'o	check_super_value(ctx, "inodes_count", sb->s_inodes_count,
5081b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			  MIN_CHECK, 1, 0);
509e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	check_super_value(ctx, "blocks_count", ext2fs_blocks_count(sb),
5101b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			  MIN_CHECK, 1, 0);
5115dd8f963d04fa4099a003cb3b13ffae05ab29210Theodore Ts'o	check_super_value(ctx, "first_data_block", sb->s_first_data_block,
512e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			  MAX_CHECK, 0, ext2fs_blocks_count(sb));
5135dd8f963d04fa4099a003cb3b13ffae05ab29210Theodore Ts'o	check_super_value(ctx, "log_block_size", sb->s_log_block_size,
51431e29a12d1e22745c74afe47bf172a3c73280dd9Theodore Ts'o			  MIN_CHECK | MAX_CHECK, 0,
51531e29a12d1e22745c74afe47bf172a3c73280dd9Theodore Ts'o			  EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
516e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	check_super_value(ctx, "log_cluster_size",
517e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			  sb->s_log_cluster_size,
518e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			  MIN_CHECK | MAX_CHECK, sb->s_log_block_size,
519e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			  (EXT2_MAX_CLUSTER_LOG_SIZE -
520e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			   EXT2_MIN_CLUSTER_LOG_SIZE));
521e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	check_super_value(ctx, "clusters_per_group", sb->s_clusters_per_group,
522e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			  MIN_CHECK | MAX_CHECK, 8, cpg_max);
5235dd8f963d04fa4099a003cb3b13ffae05ab29210Theodore Ts'o	check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
524b21bf267783274683a432eea6e5c589eab94123eAndreas Dilger			  MIN_CHECK | MAX_CHECK, 8, bpg_max);
5255dd8f963d04fa4099a003cb3b13ffae05ab29210Theodore Ts'o	check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
526b21bf267783274683a432eea6e5c589eab94123eAndreas Dilger			  MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
527e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	check_super_value(ctx, "r_blocks_count", ext2fs_r_blocks_count(sb),
528e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			  MAX_CHECK, 0, ext2fs_blocks_count(sb) / 2);
529efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	check_super_value(ctx, "reserved_gdt_blocks",
530c3ffaf833b7ddb3c1d422c71f59e1623029ede0cTheodore Ts'o			  sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
531e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			  fs->blocksize / sizeof(__u32));
532e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	check_super_value(ctx, "desc_size",
533e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			  sb->s_desc_size, MAX_CHECK | LOG2_CHECK, 0,
534e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			  EXT2_MAX_DESC_SIZE);
5351f790a7cc1fbb0dc2d2f621d2508f52a62f80150Theodore Ts'o	if (sb->s_rev_level > EXT2_GOOD_OLD_REV)
5361f790a7cc1fbb0dc2d2f621d2508f52a62f80150Theodore Ts'o		check_super_value(ctx, "first_ino", sb->s_first_ino,
5371f790a7cc1fbb0dc2d2f621d2508f52a62f80150Theodore Ts'o				  MIN_CHECK | MAX_CHECK,
5381f790a7cc1fbb0dc2d2f621d2508f52a62f80150Theodore Ts'o				  EXT2_GOOD_OLD_FIRST_INO, sb->s_inodes_count);
53989db86d33c634374a3f6e15f943ab83cdc5bd93aTheodore Ts'o	inode_size = EXT2_INODE_SIZE(sb);
54089db86d33c634374a3f6e15f943ab83cdc5bd93aTheodore Ts'o	check_super_value(ctx, "inode_size",
541e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			  inode_size, MIN_CHECK | MAX_CHECK | LOG2_CHECK,
54289db86d33c634374a3f6e15f943ab83cdc5bd93aTheodore Ts'o			  EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
543e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (sb->s_blocks_per_group != (sb->s_clusters_per_group *
544e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				       EXT2FS_CLUSTER_RATIO(fs))) {
545e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		pctx.num = sb->s_clusters_per_group * EXT2FS_CLUSTER_RATIO(fs);
546e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		pctx.str = "block_size";
54744fe08f1fa1e9a994ff304aa02022c53c9341519Theodore Ts'o		fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
54844fe08f1fa1e9a994ff304aa02022c53c9341519Theodore Ts'o		ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
54944fe08f1fa1e9a994ff304aa02022c53c9341519Theodore Ts'o		return;
55044fe08f1fa1e9a994ff304aa02022c53c9341519Theodore Ts'o	}
551efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
552d2af1bdd0526603b762c875630e82e0dd9eff059Theodore Ts'o	if ((ctx->flags & E2F_FLAG_GOT_DEVSIZE) &&
553e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	    (ctx->num_blocks < ext2fs_blocks_count(sb))) {
554e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		pctx.blk = ext2fs_blocks_count(sb);
555d2af1bdd0526603b762c875630e82e0dd9eff059Theodore Ts'o		pctx.blk2 = ctx->num_blocks;
556d2af1bdd0526603b762c875630e82e0dd9eff059Theodore Ts'o		if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
55708b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o			ctx->flags |= E2F_FLAG_ABORT;
55808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o			return;
55908b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		}
5601b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	}
5611b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o
562e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	should_be = (sb->s_log_block_size == 0 &&
563e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		     EXT2FS_CLUSTER_RATIO(fs) == 1) ? 1 : 0;
5645dd8f963d04fa4099a003cb3b13ffae05ab29210Theodore Ts'o	if (sb->s_first_data_block != should_be) {
5655dd8f963d04fa4099a003cb3b13ffae05ab29210Theodore Ts'o		pctx.blk = sb->s_first_data_block;
5661b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		pctx.blk2 = should_be;
5671b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
56808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		ctx->flags |= E2F_FLAG_ABORT;
56908b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o		return;
5701b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	}
5711b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o
5725dd8f963d04fa4099a003cb3b13ffae05ab29210Theodore Ts'o	should_be = sb->s_inodes_per_group * fs->group_desc_count;
5735dd8f963d04fa4099a003cb3b13ffae05ab29210Theodore Ts'o	if (sb->s_inodes_count != should_be) {
5745dd8f963d04fa4099a003cb3b13ffae05ab29210Theodore Ts'o		pctx.ino = sb->s_inodes_count;
575d4b0ce03168d313e89110ab9fbaa6caf616d1786Theodore Ts'o		pctx.ino2 = should_be;
576d4b0ce03168d313e89110ab9fbaa6caf616d1786Theodore Ts'o		if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
5775dd8f963d04fa4099a003cb3b13ffae05ab29210Theodore Ts'o			sb->s_inodes_count = should_be;
578d4b0ce03168d313e89110ab9fbaa6caf616d1786Theodore Ts'o			ext2fs_mark_super_dirty(fs);
579d4b0ce03168d313e89110ab9fbaa6caf616d1786Theodore Ts'o		}
580d4b0ce03168d313e89110ab9fbaa6caf616d1786Theodore Ts'o	}
581d4b0ce03168d313e89110ab9fbaa6caf616d1786Theodore Ts'o
582e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	/* Is 64bit set and extents unset? */
583e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
584e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				      EXT4_FEATURE_INCOMPAT_64BIT) &&
585e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	    !EXT2_HAS_INCOMPAT_FEATURE(fs->super,
586e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				       EXT3_FEATURE_INCOMPAT_EXTENTS) &&
587e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	    fix_problem(ctx, PR_0_64BIT_WITHOUT_EXTENTS, &pctx)) {
588e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		fs->super->s_feature_incompat |=
589e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			EXT3_FEATURE_INCOMPAT_EXTENTS;
590e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_mark_super_dirty(fs);
591e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	}
592e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
5931b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	/*
5941b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	 * Verify the group descriptors....
5951b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	 */
59688b34b1f87c2d7c3dfc9be7ff6e5d916f06d960aJose R. Santos	first_block = sb->s_first_data_block;
597e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	last_block = ext2fs_blocks_count(sb)-1;
5981b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o
59949a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos	csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
60049a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos					       EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
601e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	for (i = 0; i < fs->group_desc_count; i++) {
6021b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		pctx.group = i;
603abf23439d51a3ddbca475b931abebd381ff7ceeaEric Sandeen
60488b34b1f87c2d7c3dfc9be7ff6e5d916f06d960aJose R. Santos		if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super,
60588b34b1f87c2d7c3dfc9be7ff6e5d916f06d960aJose R. Santos					       EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
606e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			first_block = ext2fs_group_first_block2(fs, i);
607e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			last_block = ext2fs_group_last_block2(fs, i);
60888b34b1f87c2d7c3dfc9be7ff6e5d916f06d960aJose R. Santos		}
609bb1a46a430a99f73ddaf7cf74e380dd5cf36382fEric Sandeen
610e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if ((ext2fs_block_bitmap_loc(fs, i) < first_block) ||
611e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		    (ext2fs_block_bitmap_loc(fs, i) > last_block)) {
612e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			pctx.blk = ext2fs_block_bitmap_loc(fs, i);
61324bfb443fccf2060c55d0f919ef650409f96674aTheodore Ts'o			if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
614e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				ext2fs_block_bitmap_loc_set(fs, i, 0);
61524bfb443fccf2060c55d0f919ef650409f96674aTheodore Ts'o		}
616e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (ext2fs_block_bitmap_loc(fs, i) == 0) {
61724bfb443fccf2060c55d0f919ef650409f96674aTheodore Ts'o			ctx->invalid_block_bitmap_flag[i]++;
61824bfb443fccf2060c55d0f919ef650409f96674aTheodore Ts'o			ctx->invalid_bitmaps++;
6191b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		}
620e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if ((ext2fs_inode_bitmap_loc(fs, i) < first_block) ||
621e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		    (ext2fs_inode_bitmap_loc(fs, i) > last_block)) {
622e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			pctx.blk = ext2fs_inode_bitmap_loc(fs, i);
62324bfb443fccf2060c55d0f919ef650409f96674aTheodore Ts'o			if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
624e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				ext2fs_inode_bitmap_loc_set(fs, i, 0);
62524bfb443fccf2060c55d0f919ef650409f96674aTheodore Ts'o		}
626e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (ext2fs_inode_bitmap_loc(fs, i) == 0) {
62724bfb443fccf2060c55d0f919ef650409f96674aTheodore Ts'o			ctx->invalid_inode_bitmap_flag[i]++;
62824bfb443fccf2060c55d0f919ef650409f96674aTheodore Ts'o			ctx->invalid_bitmaps++;
6291b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		}
630e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if ((ext2fs_inode_table_loc(fs, i) < first_block) ||
631e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		    ((ext2fs_inode_table_loc(fs, i) +
632bb1a46a430a99f73ddaf7cf74e380dd5cf36382fEric Sandeen		      fs->inode_blocks_per_group - 1) > last_block)) {
633e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			pctx.blk = ext2fs_inode_table_loc(fs, i);
63424bfb443fccf2060c55d0f919ef650409f96674aTheodore Ts'o			if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
635e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				ext2fs_inode_table_loc_set(fs, i, 0);
63624bfb443fccf2060c55d0f919ef650409f96674aTheodore Ts'o		}
637e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (ext2fs_inode_table_loc(fs, i) == 0) {
63824bfb443fccf2060c55d0f919ef650409f96674aTheodore Ts'o			ctx->invalid_inode_table_flag[i]++;
63924bfb443fccf2060c55d0f919ef650409f96674aTheodore Ts'o			ctx->invalid_bitmaps++;
6401b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		}
641e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		free_blocks += ext2fs_bg_free_blocks_count(fs, i);
642e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		free_inodes += ext2fs_bg_free_inodes_count(fs, i);
643550a4afa24be35976edffe578555de30e06c456aTheodore Ts'o
644e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if ((ext2fs_bg_free_blocks_count(fs, i) > sb->s_blocks_per_group) ||
645e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		    (ext2fs_bg_free_inodes_count(fs, i) > sb->s_inodes_per_group) ||
646e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		    (ext2fs_bg_used_dirs_count(fs, i) > sb->s_inodes_per_group))
647550a4afa24be35976edffe578555de30e06c456aTheodore Ts'o			ext2fs_unmark_valid(fs);
648550a4afa24be35976edffe578555de30e06c456aTheodore Ts'o
6490d5439c8e0bc63438f45315755e7f0d9dcb09ccfAndreas Dilger		should_be = 0;
65049a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos		if (!ext2fs_group_desc_csum_verify(fs, i)) {
651e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			pctx.csum1 = ext2fs_bg_checksum(fs, i);
652e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			pctx.csum2 = ext2fs_group_desc_csum(fs, i);
65349a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos			if (fix_problem(ctx, PR_0_GDT_CSUM, &pctx)) {
654e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				ext2fs_bg_flags_clear(fs, i, EXT2_BG_BLOCK_UNINIT);
655e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				ext2fs_bg_flags_clear(fs, i, EXT2_BG_INODE_UNINIT);
656e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				ext2fs_bg_itable_unused_set(fs, i, 0);
6570d5439c8e0bc63438f45315755e7f0d9dcb09ccfAndreas Dilger				should_be = 1;
65849a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos			}
65949a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos			ext2fs_unmark_valid(fs);
66049a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos		}
66149a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos
66216b851cdae98244e117fe91d93b267fcad1102b3Theodore Ts'o		if (!csum_flag &&
663e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		    (ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT) ||
664e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		     ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT) ||
665e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		     ext2fs_bg_itable_unused(fs, i) != 0)) {
66649a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos			if (fix_problem(ctx, PR_0_GDT_UNINIT, &pctx)) {
667e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				ext2fs_bg_flags_clear(fs, i, EXT2_BG_BLOCK_UNINIT);
668e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				ext2fs_bg_flags_clear(fs, i, EXT2_BG_INODE_UNINIT);
669e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				ext2fs_bg_itable_unused_set(fs, i, 0);
6700d5439c8e0bc63438f45315755e7f0d9dcb09ccfAndreas Dilger				should_be = 1;
67149a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos			}
67249a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos			ext2fs_unmark_valid(fs);
67349a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos		}
6740d5439c8e0bc63438f45315755e7f0d9dcb09ccfAndreas Dilger
6750d5439c8e0bc63438f45315755e7f0d9dcb09ccfAndreas Dilger		if (i == fs->group_desc_count - 1 &&
676e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		    ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT)) {
6770d5439c8e0bc63438f45315755e7f0d9dcb09ccfAndreas Dilger			if (fix_problem(ctx, PR_0_BB_UNINIT_LAST, &pctx)) {
678e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				ext2fs_bg_flags_clear(fs, i, EXT2_BG_BLOCK_UNINIT);
6790d5439c8e0bc63438f45315755e7f0d9dcb09ccfAndreas Dilger				should_be = 1;
6800d5439c8e0bc63438f45315755e7f0d9dcb09ccfAndreas Dilger			}
6810d5439c8e0bc63438f45315755e7f0d9dcb09ccfAndreas Dilger			ext2fs_unmark_valid(fs);
6820d5439c8e0bc63438f45315755e7f0d9dcb09ccfAndreas Dilger		}
6830d5439c8e0bc63438f45315755e7f0d9dcb09ccfAndreas Dilger
68449a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos		if (csum_flag &&
685e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		    (ext2fs_bg_itable_unused(fs, i) > ext2fs_bg_free_inodes_count(fs, i) ||
686e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		     ext2fs_bg_itable_unused(fs, i) > sb->s_inodes_per_group)) {
687e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			pctx.blk = ext2fs_bg_itable_unused(fs, i);
6880d5439c8e0bc63438f45315755e7f0d9dcb09ccfAndreas Dilger			if (fix_problem(ctx, PR_0_GDT_ITABLE_UNUSED, &pctx)) {
689e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				ext2fs_bg_itable_unused_set(fs, i, 0);
6900d5439c8e0bc63438f45315755e7f0d9dcb09ccfAndreas Dilger				should_be = 1;
6910d5439c8e0bc63438f45315755e7f0d9dcb09ccfAndreas Dilger			}
69249a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos			ext2fs_unmark_valid(fs);
69349a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos		}
6940d5439c8e0bc63438f45315755e7f0d9dcb09ccfAndreas Dilger
6950d5439c8e0bc63438f45315755e7f0d9dcb09ccfAndreas Dilger		if (should_be)
6960d5439c8e0bc63438f45315755e7f0d9dcb09ccfAndreas Dilger			ext2fs_group_desc_csum_set(fs, i);
697e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		/* If the user aborts e2fsck by typing ^C, stop right away */
698e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
699e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			return;
7001b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	}
701550a4afa24be35976edffe578555de30e06c456aTheodore Ts'o
702e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	ctx->free_blocks = EXT2FS_C2B(fs, free_blocks);
703e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	ctx->free_inodes = free_inodes;
704efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
705e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if ((ext2fs_free_blocks_count(sb) > ext2fs_blocks_count(sb)) ||
706550a4afa24be35976edffe578555de30e06c456aTheodore Ts'o	    (sb->s_free_inodes_count > sb->s_inodes_count))
707550a4afa24be35976edffe578555de30e06c456aTheodore Ts'o		ext2fs_unmark_valid(fs);
708550a4afa24be35976edffe578555de30e06c456aTheodore Ts'o
709550a4afa24be35976edffe578555de30e06c456aTheodore Ts'o
7101b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	/*
7111b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	 * If we have invalid bitmaps, set the error state of the
7121b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	 * filesystem.
7131b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	 */
7141b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
715550a4afa24be35976edffe578555de30e06c456aTheodore Ts'o		sb->s_state &= ~EXT2_VALID_FS;
7161b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		ext2fs_mark_super_dirty(fs);
7171b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	}
7181b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o
7194ea0a1109d761e9caaa53f6fa9e036321826c5faTheodore Ts'o	clear_problem_context(&pctx);
720efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
72154be2ccc2251784fd771590a5e72827afd82df40Theodore Ts'o#ifndef EXT2_SKIP_UUID
7221b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	/*
7231b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	 * If the UUID field isn't assigned, assign it.
7241b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	 */
7255dd8f963d04fa4099a003cb3b13ffae05ab29210Theodore Ts'o	if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
7261b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
7275dd8f963d04fa4099a003cb3b13ffae05ab29210Theodore Ts'o			uuid_generate(sb->s_uuid);
728e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			fs->flags |= EXT2_FLAG_DIRTY;
729299d742427776629ef07b4563f41a4e00fc23aa0Theodore Ts'o			fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
7301b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		}
7311b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	}
73254be2ccc2251784fd771590a5e72827afd82df40Theodore Ts'o#endif
7332a77a784a327835dbf0c8aa92978f201e44fbc26Theodore Ts'o
7342a77a784a327835dbf0c8aa92978f201e44fbc26Theodore Ts'o	/*
73580875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	 * Check to see if we should disable the test_fs flag
73680875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	 */
73780875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	profile_get_boolean(ctx->profile, "options",
73880875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o			    "clear_test_fs_flag", 0, 1,
73980875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o			    &clear_test_fs_flag);
74080875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	if (!(ctx->options & E2F_OPT_READONLY) &&
74180875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	    clear_test_fs_flag &&
74280875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	    (fs->super->s_flags & EXT2_FLAGS_TEST_FILESYS) &&
74380875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	    (fs_proc_check("ext4") || check_for_modules("ext4"))) {
74480875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o		if (fix_problem(ctx, PR_0_CLEAR_TESTFS_FLAG, &pctx)) {
74580875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o			fs->super->s_flags &= ~EXT2_FLAGS_TEST_FILESYS;
746e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			fs->flags |= EXT2_FLAG_DIRTY;
74780875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o			fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
74880875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o		}
74980875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	}
75080875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o
75180875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	/*
7524ea0a1109d761e9caaa53f6fa9e036321826c5faTheodore Ts'o	 * For the Hurd, check to see if the filetype option is set,
7534ea0a1109d761e9caaa53f6fa9e036321826c5faTheodore Ts'o	 * since it doesn't support it.
7544ea0a1109d761e9caaa53f6fa9e036321826c5faTheodore Ts'o	 */
75580bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	if (!(ctx->options & E2F_OPT_READONLY) &&
75680bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	    fs->super->s_creator_os == EXT2_OS_HURD &&
7574ea0a1109d761e9caaa53f6fa9e036321826c5faTheodore Ts'o	    (fs->super->s_feature_incompat &
7584ea0a1109d761e9caaa53f6fa9e036321826c5faTheodore Ts'o	     EXT2_FEATURE_INCOMPAT_FILETYPE)) {
7594ea0a1109d761e9caaa53f6fa9e036321826c5faTheodore Ts'o		if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
7604ea0a1109d761e9caaa53f6fa9e036321826c5faTheodore Ts'o			fs->super->s_feature_incompat &=
7614ea0a1109d761e9caaa53f6fa9e036321826c5faTheodore Ts'o				~EXT2_FEATURE_INCOMPAT_FILETYPE;
7624ea0a1109d761e9caaa53f6fa9e036321826c5faTheodore Ts'o			ext2fs_mark_super_dirty(fs);
7630cfce7f749ea519522929d91e705cf90518594c4Theodore Ts'o			fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
7644ea0a1109d761e9caaa53f6fa9e036321826c5faTheodore Ts'o		}
7654ea0a1109d761e9caaa53f6fa9e036321826c5faTheodore Ts'o	}
76680bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o
76780bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	/*
7687b59f1efb1c4ac53c64a2cc412acf5b056cc628bTheodore Ts'o	 * If we have any of the compatibility flags set, we need to have a
7697b59f1efb1c4ac53c64a2cc412acf5b056cc628bTheodore Ts'o	 * revision 1 filesystem.  Most kernels will not check the flags on
7707b59f1efb1c4ac53c64a2cc412acf5b056cc628bTheodore Ts'o	 * a rev 0 filesystem and we may have corruption issues because of
7717b59f1efb1c4ac53c64a2cc412acf5b056cc628bTheodore Ts'o	 * the incompatible changes to the filesystem.
7727b59f1efb1c4ac53c64a2cc412acf5b056cc628bTheodore Ts'o	 */
7737b59f1efb1c4ac53c64a2cc412acf5b056cc628bTheodore Ts'o	if (!(ctx->options & E2F_OPT_READONLY) &&
7747b59f1efb1c4ac53c64a2cc412acf5b056cc628bTheodore Ts'o	    fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
7757b59f1efb1c4ac53c64a2cc412acf5b056cc628bTheodore Ts'o	    (fs->super->s_feature_compat ||
7767b59f1efb1c4ac53c64a2cc412acf5b056cc628bTheodore Ts'o	     fs->super->s_feature_ro_compat ||
7777b59f1efb1c4ac53c64a2cc412acf5b056cc628bTheodore Ts'o	     fs->super->s_feature_incompat) &&
7787b59f1efb1c4ac53c64a2cc412acf5b056cc628bTheodore Ts'o	    fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
779a917d1ccf49605b3009f4e7225f00b81fc16100bTheodore Ts'o		ext2fs_update_dynamic_rev(fs);
7807b59f1efb1c4ac53c64a2cc412acf5b056cc628bTheodore Ts'o		ext2fs_mark_super_dirty(fs);
7810cfce7f749ea519522929d91e705cf90518594c4Theodore Ts'o		fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
7827b59f1efb1c4ac53c64a2cc412acf5b056cc628bTheodore Ts'o	}
7837b59f1efb1c4ac53c64a2cc412acf5b056cc628bTheodore Ts'o
7847b59f1efb1c4ac53c64a2cc412acf5b056cc628bTheodore Ts'o	/*
78580bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	 * Clean up any orphan inodes, if present.
78680bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	 */
78780bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
78880bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o		fs->super->s_state &= ~EXT2_VALID_FS;
7897b59f1efb1c4ac53c64a2cc412acf5b056cc628bTheodore Ts'o		ext2fs_mark_super_dirty(fs);
79080bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o	}
79180bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o
79260702c267d83bc75ca22e8efb5eff0e1a8821800Theodore Ts'o	/*
793ba5131f6d48eded504e84c2a8ffc8131df8a512eTheodore Ts'o	 * Unfortunately, due to Windows' unfortunate design decision
794ba5131f6d48eded504e84c2a8ffc8131df8a512eTheodore Ts'o	 * to configure the hardware clock to tick localtime, instead
795ba5131f6d48eded504e84c2a8ffc8131df8a512eTheodore Ts'o	 * of the more proper and less error-prone UTC time, many
796ba5131f6d48eded504e84c2a8ffc8131df8a512eTheodore Ts'o	 * users end up in the situation where the system clock is
797ba5131f6d48eded504e84c2a8ffc8131df8a512eTheodore Ts'o	 * incorrectly set at the time when e2fsck is run.
798ba5131f6d48eded504e84c2a8ffc8131df8a512eTheodore Ts'o	 *
799ba5131f6d48eded504e84c2a8ffc8131df8a512eTheodore Ts'o	 * Historically this was usually due to some distributions
800ba5131f6d48eded504e84c2a8ffc8131df8a512eTheodore Ts'o	 * having buggy init scripts and/or installers that didn't
801ba5131f6d48eded504e84c2a8ffc8131df8a512eTheodore Ts'o	 * correctly detect this case and take appropriate
802ba5131f6d48eded504e84c2a8ffc8131df8a512eTheodore Ts'o	 * countermeasures.  However, it's still possible, despite the
803ba5131f6d48eded504e84c2a8ffc8131df8a512eTheodore Ts'o	 * best efforts of init script and installer authors to not be
804ba5131f6d48eded504e84c2a8ffc8131df8a512eTheodore Ts'o	 * able to detect this misconfiguration, usually due to a
805ba5131f6d48eded504e84c2a8ffc8131df8a512eTheodore Ts'o	 * buggy or misconfigured virtualization manager or the
806ba5131f6d48eded504e84c2a8ffc8131df8a512eTheodore Ts'o	 * installer not having access to a network time server during
807ba5131f6d48eded504e84c2a8ffc8131df8a512eTheodore Ts'o	 * the installation process.  So by default, we allow the
808ba5131f6d48eded504e84c2a8ffc8131df8a512eTheodore Ts'o	 * superblock times to be fudged by up to 24 hours.  This can
809ba5131f6d48eded504e84c2a8ffc8131df8a512eTheodore Ts'o	 * be disabled by setting options.accept_time_fudge to the
810ba5131f6d48eded504e84c2a8ffc8131df8a512eTheodore Ts'o	 * boolean value of false in e2fsck.conf.  We also support
811ba5131f6d48eded504e84c2a8ffc8131df8a512eTheodore Ts'o	 * options.buggy_init_scripts for backwards compatibility.
81260702c267d83bc75ca22e8efb5eff0e1a8821800Theodore Ts'o	 */
813ba5131f6d48eded504e84c2a8ffc8131df8a512eTheodore Ts'o	profile_get_boolean(ctx->profile, "options", "accept_time_fudge",
814ba5131f6d48eded504e84c2a8ffc8131df8a512eTheodore Ts'o			    0, 1, &accept_time_fudge);
81560702c267d83bc75ca22e8efb5eff0e1a8821800Theodore Ts'o	profile_get_boolean(ctx->profile, "options", "buggy_init_scripts",
816ba5131f6d48eded504e84c2a8ffc8131df8a512eTheodore Ts'o			    0, accept_time_fudge, &accept_time_fudge);
817ba5131f6d48eded504e84c2a8ffc8131df8a512eTheodore Ts'o	ctx->time_fudge = accept_time_fudge ? 86400 : 0;
81860702c267d83bc75ca22e8efb5eff0e1a8821800Theodore Ts'o
819177839e2454dcc298244481da9c72a19b41836beTheodore Ts'o	profile_get_boolean(ctx->profile, "options", "broken_system_clock",
820177839e2454dcc298244481da9c72a19b41836beTheodore Ts'o			    0, 0, &broken_system_clock);
821177839e2454dcc298244481da9c72a19b41836beTheodore Ts'o
822efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	/*
8238dceb92407f751d1a8aecd4bfb36d1fe2dc3cf9aTheodore Ts'o	 * Check to see if the superblock last mount time or last
8248dceb92407f751d1a8aecd4bfb36d1fe2dc3cf9aTheodore Ts'o	 * write time is in the future.
8258dceb92407f751d1a8aecd4bfb36d1fe2dc3cf9aTheodore Ts'o	 */
826177839e2454dcc298244481da9c72a19b41836beTheodore Ts'o	if (!broken_system_clock &&
827177839e2454dcc298244481da9c72a19b41836beTheodore Ts'o	    !(ctx->flags & E2F_FLAG_TIME_INSANE) &&
828177839e2454dcc298244481da9c72a19b41836beTheodore Ts'o	    fs->super->s_mtime > (__u32) ctx->now) {
8298dceb92407f751d1a8aecd4bfb36d1fe2dc3cf9aTheodore Ts'o		pctx.num = fs->super->s_mtime;
83026ea4899d1fea0fbc5d28120944d2c2758ac1b11Theodore Ts'o		problem = PR_0_FUTURE_SB_LAST_MOUNT;
83126ea4899d1fea0fbc5d28120944d2c2758ac1b11Theodore Ts'o		if (fs->super->s_mtime <= (__u32) ctx->now + ctx->time_fudge)
83226ea4899d1fea0fbc5d28120944d2c2758ac1b11Theodore Ts'o			problem = PR_0_FUTURE_SB_LAST_MOUNT_FUDGED;
83326ea4899d1fea0fbc5d28120944d2c2758ac1b11Theodore Ts'o		if (fix_problem(ctx, problem, &pctx)) {
8348dceb92407f751d1a8aecd4bfb36d1fe2dc3cf9aTheodore Ts'o			fs->super->s_mtime = ctx->now;
835e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			fs->flags |= EXT2_FLAG_DIRTY;
8368dceb92407f751d1a8aecd4bfb36d1fe2dc3cf9aTheodore Ts'o		}
8378dceb92407f751d1a8aecd4bfb36d1fe2dc3cf9aTheodore Ts'o	}
838177839e2454dcc298244481da9c72a19b41836beTheodore Ts'o	if (!broken_system_clock &&
839177839e2454dcc298244481da9c72a19b41836beTheodore Ts'o	    !(ctx->flags & E2F_FLAG_TIME_INSANE) &&
840177839e2454dcc298244481da9c72a19b41836beTheodore Ts'o	    fs->super->s_wtime > (__u32) ctx->now) {
8418dceb92407f751d1a8aecd4bfb36d1fe2dc3cf9aTheodore Ts'o		pctx.num = fs->super->s_wtime;
842fe26a55ac923f4cce17c27ef51de84d2e3b6eebbTheodore Ts'o		problem = PR_0_FUTURE_SB_LAST_WRITE;
84326ea4899d1fea0fbc5d28120944d2c2758ac1b11Theodore Ts'o		if (fs->super->s_wtime <= (__u32) ctx->now + ctx->time_fudge)
84461a9d2b33e5c7afa4f03d6cc0ed4d81b2caf7023Theodore Ts'o			problem = PR_0_FUTURE_SB_LAST_WRITE_FUDGED;
84526ea4899d1fea0fbc5d28120944d2c2758ac1b11Theodore Ts'o		if (fix_problem(ctx, problem, &pctx)) {
8468dceb92407f751d1a8aecd4bfb36d1fe2dc3cf9aTheodore Ts'o			fs->super->s_wtime = ctx->now;
847e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			fs->flags |= EXT2_FLAG_DIRTY;
8488dceb92407f751d1a8aecd4bfb36d1fe2dc3cf9aTheodore Ts'o		}
8498dceb92407f751d1a8aecd4bfb36d1fe2dc3cf9aTheodore Ts'o	}
8508dceb92407f751d1a8aecd4bfb36d1fe2dc3cf9aTheodore Ts'o
851773fd8a1d4202af708a37bdc7754134e6fdcfe22Theodore Ts'o	/*
852773fd8a1d4202af708a37bdc7754134e6fdcfe22Theodore Ts'o	 * Move the ext3 journal file, if necessary.
853773fd8a1d4202af708a37bdc7754134e6fdcfe22Theodore Ts'o	 */
854773fd8a1d4202af708a37bdc7754134e6fdcfe22Theodore Ts'o	e2fsck_move_ext3_journal(ctx);
855b1c52b26a44efeb366402985763c242a4b21aeb1Theodore Ts'o
856b1c52b26a44efeb366402985763c242a4b21aeb1Theodore Ts'o	/*
857b1c52b26a44efeb366402985763c242a4b21aeb1Theodore Ts'o	 * Fix journal hint, if necessary
858b1c52b26a44efeb366402985763c242a4b21aeb1Theodore Ts'o	 */
859b1c52b26a44efeb366402985763c242a4b21aeb1Theodore Ts'o	e2fsck_fix_ext3_journal_hint(ctx);
860b1c52b26a44efeb366402985763c242a4b21aeb1Theodore Ts'o
861f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o	/*
862f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o	 * Add dirhash hint if necessary
863f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o	 */
864f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o	e2fsck_fix_dirhash_hint(ctx);
865f77704e416fca7dbe4cc91abba674d2ae3c14f6fTheodore Ts'o
866e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	/*
867e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 * Hide quota inodes if necessary.
868e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	 */
869e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	e2fsck_hide_quota(ctx);
870e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
8711b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	return;
8721b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o}
8730c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o
8740c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o/*
8750c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o * Check to see if we should backup the master sb to the backup super
876a8cde73acbf6e0f9c0a3601e4f5fac2b01a27bd2Theodore Ts'o * blocks.  Returns non-zero if the sb should be backed up.
8770c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o */
878a8cde73acbf6e0f9c0a3601e4f5fac2b01a27bd2Theodore Ts'o
879a8cde73acbf6e0f9c0a3601e4f5fac2b01a27bd2Theodore Ts'o/*
880a8cde73acbf6e0f9c0a3601e4f5fac2b01a27bd2Theodore Ts'o * A few flags are set on the fly by the kernel, but only in the
881a8cde73acbf6e0f9c0a3601e4f5fac2b01a27bd2Theodore Ts'o * primary superblock.  This is actually a bad thing, and we should
882a8cde73acbf6e0f9c0a3601e4f5fac2b01a27bd2Theodore Ts'o * try to discourage it in the future.  In particular, for the newer
883a8cde73acbf6e0f9c0a3601e4f5fac2b01a27bd2Theodore Ts'o * ext4 files, especially EXT4_FEATURE_RO_COMPAT_DIR_NLINK and
884a8cde73acbf6e0f9c0a3601e4f5fac2b01a27bd2Theodore Ts'o * EXT3_FEATURE_INCOMPAT_EXTENTS.  So some of these may go away in the
885d9ff474b742f700e049f336f055918060f21a543Eric Sandeen * future.  EXT3_FEATURE_INCOMPAT_RECOVER may also get set when
886d9ff474b742f700e049f336f055918060f21a543Eric Sandeen * copying the primary superblock during online resize.
887a8cde73acbf6e0f9c0a3601e4f5fac2b01a27bd2Theodore Ts'o *
888a8cde73acbf6e0f9c0a3601e4f5fac2b01a27bd2Theodore Ts'o * The kernel will set EXT2_FEATURE_COMPAT_EXT_ATTR, but
889a8cde73acbf6e0f9c0a3601e4f5fac2b01a27bd2Theodore Ts'o * unfortunately, we shouldn't ignore it since if it's not set in the
890a8cde73acbf6e0f9c0a3601e4f5fac2b01a27bd2Theodore Ts'o * backup, the extended attributes in the filesystem will be stripped
891a8cde73acbf6e0f9c0a3601e4f5fac2b01a27bd2Theodore Ts'o * away.
892a8cde73acbf6e0f9c0a3601e4f5fac2b01a27bd2Theodore Ts'o */
893a8cde73acbf6e0f9c0a3601e4f5fac2b01a27bd2Theodore Ts'o#define FEATURE_RO_COMPAT_IGNORE	(EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
894a8cde73acbf6e0f9c0a3601e4f5fac2b01a27bd2Theodore Ts'o					 EXT4_FEATURE_RO_COMPAT_DIR_NLINK)
895d9ff474b742f700e049f336f055918060f21a543Eric Sandeen#define FEATURE_INCOMPAT_IGNORE		(EXT3_FEATURE_INCOMPAT_EXTENTS| \
896d9ff474b742f700e049f336f055918060f21a543Eric Sandeen					 EXT3_FEATURE_INCOMPAT_RECOVER)
897a8cde73acbf6e0f9c0a3601e4f5fac2b01a27bd2Theodore Ts'o
8980c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'oint check_backup_super_block(e2fsck_t ctx)
8990c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o{
9000c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o	ext2_filsys	fs = ctx->fs;
9010c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o	errcode_t	retval;
9020c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o	dgrp_t		g;
903e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t		sb;
9040c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o	int		ret = 0;
905982dd30ce87d5fdfb9a6de5732633f31b3840090Theodore Ts'o	char		buf[SUPERBLOCK_SIZE];
906982dd30ce87d5fdfb9a6de5732633f31b3840090Theodore Ts'o	struct ext2_super_block	*backup_sb;
9070c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o
9080c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o	/*
9090c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o	 * If we are already writing out the backup blocks, then we
9100c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o	 * don't need to test.  Also, if the filesystem is invalid, or
9110c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o	 * the check was aborted or cancelled, we also don't want to
9120c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o	 * do the backup.  If the filesystem was opened read-only then
9130c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o	 * we can't do the backup.
9140c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o	 */
9150c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o	if (((fs->flags & EXT2_FLAG_MASTER_SB_ONLY) == 0) ||
9160c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o	    !ext2fs_test_valid(fs) ||
9170c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o	    (fs->super->s_state & EXT2_ERROR_FS) ||
9180c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o	    (ctx->flags & (E2F_FLAG_ABORT | E2F_FLAG_CANCEL)) ||
9190c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o	    (ctx->options & E2F_OPT_READONLY))
9200c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o		return 0;
9210c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o
9220c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o	for (g = 1; g < fs->group_desc_count; g++) {
9230c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o		if (!ext2fs_bg_has_super(fs, g))
9240c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o			continue;
9250c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o
926e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		sb = ext2fs_group_first_block2(fs, g);
9270c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o
928982dd30ce87d5fdfb9a6de5732633f31b3840090Theodore Ts'o		retval = io_channel_read_blk(fs->io, sb, -SUPERBLOCK_SIZE,
929982dd30ce87d5fdfb9a6de5732633f31b3840090Theodore Ts'o					     buf);
930982dd30ce87d5fdfb9a6de5732633f31b3840090Theodore Ts'o		if (retval)
931982dd30ce87d5fdfb9a6de5732633f31b3840090Theodore Ts'o			continue;
932982dd30ce87d5fdfb9a6de5732633f31b3840090Theodore Ts'o		backup_sb = (struct ext2_super_block *) buf;
933982dd30ce87d5fdfb9a6de5732633f31b3840090Theodore Ts'o#ifdef WORDS_BIGENDIAN
934982dd30ce87d5fdfb9a6de5732633f31b3840090Theodore Ts'o		ext2fs_swap_super(backup_sb);
935982dd30ce87d5fdfb9a6de5732633f31b3840090Theodore Ts'o#endif
936982dd30ce87d5fdfb9a6de5732633f31b3840090Theodore Ts'o		if ((backup_sb->s_magic != EXT2_SUPER_MAGIC) ||
937982dd30ce87d5fdfb9a6de5732633f31b3840090Theodore Ts'o		    (backup_sb->s_rev_level > EXT2_LIB_CURRENT_REV) ||
938982dd30ce87d5fdfb9a6de5732633f31b3840090Theodore Ts'o		    ((backup_sb->s_log_block_size + EXT2_MIN_BLOCK_LOG_SIZE) >
939982dd30ce87d5fdfb9a6de5732633f31b3840090Theodore Ts'o		     EXT2_MAX_BLOCK_LOG_SIZE) ||
940982dd30ce87d5fdfb9a6de5732633f31b3840090Theodore Ts'o		    (EXT2_INODE_SIZE(backup_sb) < EXT2_GOOD_OLD_INODE_SIZE))
9410c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o			continue;
9420c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o
943a8cde73acbf6e0f9c0a3601e4f5fac2b01a27bd2Theodore Ts'o#define SUPER_INCOMPAT_DIFFERENT(x)	\
944982dd30ce87d5fdfb9a6de5732633f31b3840090Theodore Ts'o	((fs->super->x & ~FEATURE_INCOMPAT_IGNORE) !=	\
945982dd30ce87d5fdfb9a6de5732633f31b3840090Theodore Ts'o	 (backup_sb->x & ~FEATURE_INCOMPAT_IGNORE))
946a8cde73acbf6e0f9c0a3601e4f5fac2b01a27bd2Theodore Ts'o#define SUPER_RO_COMPAT_DIFFERENT(x)	\
947982dd30ce87d5fdfb9a6de5732633f31b3840090Theodore Ts'o	((fs->super->x & ~FEATURE_RO_COMPAT_IGNORE) !=	\
948982dd30ce87d5fdfb9a6de5732633f31b3840090Theodore Ts'o	 (backup_sb->x & ~FEATURE_RO_COMPAT_IGNORE))
949a8cde73acbf6e0f9c0a3601e4f5fac2b01a27bd2Theodore Ts'o#define SUPER_DIFFERENT(x)		\
950982dd30ce87d5fdfb9a6de5732633f31b3840090Theodore Ts'o	(fs->super->x != backup_sb->x)
951a8cde73acbf6e0f9c0a3601e4f5fac2b01a27bd2Theodore Ts'o
9520c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o		if (SUPER_DIFFERENT(s_feature_compat) ||
953a8cde73acbf6e0f9c0a3601e4f5fac2b01a27bd2Theodore Ts'o		    SUPER_INCOMPAT_DIFFERENT(s_feature_incompat) ||
954a8cde73acbf6e0f9c0a3601e4f5fac2b01a27bd2Theodore Ts'o		    SUPER_RO_COMPAT_DIFFERENT(s_feature_ro_compat) ||
9550c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o		    SUPER_DIFFERENT(s_blocks_count) ||
956e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		    SUPER_DIFFERENT(s_blocks_count_hi) ||
9570c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o		    SUPER_DIFFERENT(s_inodes_count) ||
958982dd30ce87d5fdfb9a6de5732633f31b3840090Theodore Ts'o		    memcmp(fs->super->s_uuid, backup_sb->s_uuid,
9590c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o			   sizeof(fs->super->s_uuid)))
9600c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o			ret = 1;
9610c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o		break;
9620c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o	}
9630c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o	return ret;
9640c37f456d929dac47fcf87374f1c1b9a9a96c9faTheodore Ts'o}
965