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