journal.c revision ecf1b7767e1772f4c6dba8f02026057ed05397bd
117390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o/* 217390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o * journal.c --- code for handling the "ext3" journal 33b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * 43b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * Copyright (C) 2000 Andreas Dilger 53b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * Copyright (C) 2000 Theodore Ts'o 63b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * 73b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie 83b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * Copyright (C) 1999 Red Hat Software 93b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * 103b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * This file may be redistributed under the terms of the 113b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * GNU General Public License version 2 or at your discretion 123b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * any later version. 1317390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o */ 1417390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o 153b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o#ifdef HAVE_SYS_MOUNT_H 163b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o#include <sys/mount.h> 173b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o#define MNT_FL (MS_MGC_VAL | MS_RDONLY) 183b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o#endif 193b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o#ifdef HAVE_SYS_STAT_H 203b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o#include <sys/stat.h> 213b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o#endif 2217390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o 233b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o#include "jfs.h" 243b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o#include "problem.h" 253b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o#include "uuid/uuid.h" 2617390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o 273b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o#ifdef JFS_DEBUG 283b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'ostatic int bh_count = 0; 293b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'oint jfs_enable_debug = 2; 303b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o#endif 313b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 323b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'oint bmap(struct inode *inode, int block) 333b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o{ 343b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o int retval; 353b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o blk_t phys; 363b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 373b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o retval = ext2fs_bmap(inode->i_ctx->fs, inode->i_ino, &inode->i_ext2, 383b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o NULL, 0, block, &phys); 393b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 403b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (retval) 413b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o com_err(inode->i_ctx->device_name, retval, 423b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o _("bmap journal inode %ld, block %d\n"), 433b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o inode->i_ino, block); 443b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 453b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return phys; 463b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o} 473b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 483b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'ostruct buffer_head *getblk(e2fsck_t ctx, blk_t blocknr, int blocksize) 493b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o{ 503b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o struct buffer_head *bh; 513b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 523b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o bh = e2fsck_allocate_memory(ctx, sizeof(*bh), "block buffer"); 533b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (!bh) 543b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return NULL; 553b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 563b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o jfs_debug(4, "getblk for block %lu (%d bytes)(total %d)\n", 573b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o blocknr, blocksize, ++bh_count); 583b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 593b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o bh->b_ctx = ctx; 603b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o bh->b_size = blocksize; 613b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o bh->b_blocknr = blocknr; 623b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 633b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return bh; 643b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o} 653b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 663b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'ovoid ll_rw_block(int rw, int dummy, struct buffer_head *bh) 673b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o{ 683b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o int retval; 693b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 703b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (rw == READ && !bh->b_uptodate) { 713b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o jfs_debug(3, "reading block %lu/%p\n", bh->b_blocknr, bh); 723b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o retval = io_channel_read_blk(bh->b_ctx->fs->io, bh->b_blocknr, 733b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 1, bh->b_data); 743b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (retval) { 753b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o com_err(bh->b_ctx->device_name, retval, 763b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o "while reading block %ld\n", bh->b_blocknr); 773b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o bh->b_err = retval; 783b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return; 793b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 803b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o bh->b_uptodate = 1; 813b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } else if (rw == WRITE && bh->b_dirty) { 823b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o jfs_debug(3, "writing block %lu/%p\n", bh->b_blocknr, bh); 833b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o retval = io_channel_write_blk(bh->b_ctx->fs->io, bh->b_blocknr, 843b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 1, bh->b_data); 853b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (retval) { 863b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o com_err(bh->b_ctx->device_name, retval, 873b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o "while writing block %ld\n", bh->b_blocknr); 883b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o bh->b_err = retval; 893b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return; 903b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 913b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o bh->b_dirty = 0; 923b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o bh->b_uptodate = 1; 933b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } else 943b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o jfs_debug(3, "no-op %s for block %lu\n", 953b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o rw == READ ? "read" : "write", bh->b_blocknr); 963b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o} 973b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 983b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'ovoid mark_buffer_dirty(struct buffer_head *bh, int dummy) 993b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o{ 1003b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o bh->b_dirty = dummy | 1; /* use dummy to avoid unused variable */ 1013b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o} 1023b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 1033b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'ovoid brelse(struct buffer_head *bh) 1043b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o{ 1053b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (bh->b_dirty) 1063b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o ll_rw_block(WRITE, 1, bh); 1073b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o jfs_debug(3, "freeing block %lu/%p (total %d)\n", 1083b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o bh->b_blocknr, bh, --bh_count); 1093b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o ext2fs_free_mem((void **) &bh); 1103b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o} 1113b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 1123b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'oint buffer_uptodate(struct buffer_head *bh) 1133b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o{ 1143b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return bh->b_uptodate; 1153b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o} 1163b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 1173b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'ovoid wait_on_buffer(struct buffer_head *bh) 1183b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o{ 1193b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (!bh->b_uptodate) 1203b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o ll_rw_block(READ, 1, bh); 1213b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o} 1223b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 12380bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o 1243b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'ostatic void e2fsck_clear_recover(e2fsck_t ctx, int error) 1253b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o{ 1263b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o struct ext2fs_sb *s = (struct ext2fs_sb *)ctx->fs->super; 1273b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 1283b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o s->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER; 1293b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 1303b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o /* if we had an error doing journal recovery, we need a full fsck */ 1313b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (error) 1323b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o s->s_state &= ~EXT2_VALID_FS; 1333b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o ext2fs_mark_super_dirty(ctx->fs); 1343b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o} 1353b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 1363b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'ostatic int e2fsck_journal_init_inode(e2fsck_t ctx, struct ext2fs_sb *s, 1373b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o ino_t journal_inum, journal_t **journal) 1383b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o{ 1393b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o struct inode *inode; 1403b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o const char *cmdname = ctx->program_name; 1413b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o struct buffer_head *bh; 1423b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o blk_t start; 1433b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o int retval; 1443b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 1453b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o jfs_debug(1, "Using journal inode %lu\n", journal_inum); 1463b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o *journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal"); 1473b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (!*journal) { 1483b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return EXT2_ET_NO_MEMORY; 1493b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 1503b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 1513b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o inode = e2fsck_allocate_memory(ctx, sizeof(*inode), "journal inode"); 1523b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (!inode) { 1533b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o retval = EXT2_ET_NO_MEMORY; 1543b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o goto exit_journal; 1553b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 1563b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 1573b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o inode->i_ctx = ctx; 1583b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o inode->i_ino = journal_inum; 1593b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o retval = ext2fs_read_inode(ctx->fs, journal_inum, &inode->i_ext2); 1603b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (retval) 1613b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o goto exit_inode; 1623b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 1633b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o (*journal)->j_dev = ctx; 1643b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o (*journal)->j_inode = inode; 1653b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o (*journal)->j_blocksize = ctx->fs->blocksize; 1663b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o (*journal)->j_maxlen = inode->i_ext2.i_size / (*journal)->j_blocksize; 1673b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 1683b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (!inode->i_ext2.i_links_count || 1693b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o !LINUX_S_ISREG(inode->i_ext2.i_mode) || 1703b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o (*journal)->j_maxlen < JFS_MIN_JOURNAL_BLOCKS || 1713b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o (start = bmap(inode, 0)) == 0) { 1723b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o retval = EXT2_ET_BAD_INODE_NUM; 1733b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o goto exit_inode; 1743b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 1753b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 1763b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o bh = getblk(ctx, start, (*journal)->j_blocksize); 1773b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (!bh) { 1783b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o retval = EXT2_ET_NO_MEMORY; 1793b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o goto exit_inode; 1803b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 1813b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o (*journal)->j_sb_buffer = bh; 1823b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o (*journal)->j_superblock = (journal_superblock_t *)bh->b_data; 1833b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 1843b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return 0; 1853b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 1863b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'oexit_inode: 1873b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o ext2fs_free_mem((void **)&inode); 1883b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'oexit_journal: 1893b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o ext2fs_free_mem((void **)journal); 1903b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 1913b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return retval; 1923b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o} 1933b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 1943b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'ostatic int e2fsck_get_journal(e2fsck_t ctx, journal_t **journal) 1953b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o{ 1963b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o char uuid_str[40]; 1973b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o struct problem_context pctx; 1983b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o struct ext2fs_sb *s = (struct ext2fs_sb *)ctx->fs->super; 1993b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o int recover = s->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER; 2003b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 2013b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o clear_problem_context(&pctx); 2023b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 2033b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (s->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) { 2043b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (s->s_journal_dev) { 2053b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o pctx.num = s->s_journal_dev; 2063b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o /* this problem aborts on -y, -p, unsupported on -n */ 2073b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_DEV, &pctx)) 2083b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return EXT2_ET_UNSUPP_FEATURE; 2093b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o s->s_journal_dev = 0; 2103b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o s->s_state &= ~EXT2_VALID_FS; 2113b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o ext2fs_mark_super_dirty(ctx->fs); 2123b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 2133b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (!uuid_is_null(s->s_journal_uuid)) { 2143b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o uuid_unparse(s->s_journal_uuid, uuid_str); 2153b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o pctx.str = uuid_str; 2163b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o /* this problem aborts on -y, -p, unsupported on -n */ 2173b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_UUID, &pctx)) 2183b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return EXT2_ET_UNSUPP_FEATURE; 2193b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o uuid_clear(s->s_journal_uuid); 2203b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o s->s_state &= ~EXT2_VALID_FS; 2213b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o ext2fs_mark_super_dirty(ctx->fs); 2223b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 2233b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (!s->s_journal_inum) 2243b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return EXT2_ET_BAD_INODE_NUM; 2253b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 2263b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 2273b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (s->s_journal_dev) { 2283b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o pctx.num = s->s_journal_dev; 2293b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (!fix_problem(ctx, PR_0_JOURNAL_BAD_DEV, &pctx)) 2303b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return EXT2_ET_UNSUPP_FEATURE; 2313b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o s->s_journal_dev = 0; 2323b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o s->s_state &= ~EXT2_VALID_FS; 2333b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o ext2fs_mark_super_dirty(ctx->fs); 2343b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 2353b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (!uuid_is_null(s->s_journal_uuid)) { 2363b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o uuid_unparse(s->s_journal_uuid, uuid_str); 2373b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o pctx.str = uuid_str; 2383b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (!fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx)) 2393b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return EXT2_ET_UNSUPP_FEATURE; 2403b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o uuid_clear(s->s_journal_uuid); 2413b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o s->s_state &= ~EXT2_VALID_FS; 2423b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o ext2fs_mark_super_dirty(ctx->fs); 2433b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 2443b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 2453b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return e2fsck_journal_init_inode(ctx, s, s->s_journal_inum, journal); 2463b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o} 2473b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 2483b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'ostatic int e2fsck_journal_fix_bad_inode(e2fsck_t ctx, 2493b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o struct problem_context *pctx) 2503b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o{ 2513b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o struct ext2fs_sb *s = (struct ext2fs_sb *)ctx->fs->super; 2523b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o int recover = s->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER; 2533b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o int has_journal = s->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL; 2543b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 2553b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (has_journal || s->s_journal_inum) { 2563b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o /* The journal inode is bogus, remove and force full fsck */ 2573b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) { 2583b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o struct ext2fs_sb *s =(struct ext2fs_sb *)ctx->fs->super; 2593b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 2603b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (has_journal && s->s_journal_inum) 2613b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o printf("*** ext3 journal has been deleted - " 2623b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o "filesystem is now ext2 only ***\n\n"); 2633b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o s->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL; 2643b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o s->s_journal_inum = 0; 2653b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o e2fsck_clear_recover(ctx, 1); 2663b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return 0; 2673b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 2683b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return EXT2_ET_BAD_INODE_NUM; 2693b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } else if (recover) { 2703b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) { 2713b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o e2fsck_clear_recover(ctx, 1); 2723b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return 0; 2733b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 2743b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return EXT2_ET_UNSUPP_FEATURE; 2753b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 2763b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return 0; 2773b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o} 2783b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 2793b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'ostatic int e2fsck_journal_fix_unsupported_super(e2fsck_t ctx, 2803b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o struct problem_context *pctx) 2813b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o{ 2823b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o struct ext2fs_sb *s = (struct ext2fs_sb *)ctx->fs->super; 2833b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 2843b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o /* Unsupported journal superblock - first choice is abort. 2853b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * Declining that gives the option to reset the superblock. 2863b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * 2873b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * Otherwise we get the chance to delete the journal, and 2883b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * failing that we abort because we can't handle this. 2893b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o */ 2903b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (s->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL && 2913b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o fix_problem(ctx, PR_0_JOURNAL_UNSUPP_SUPER, pctx)) 2923b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return EXT2_ET_CORRUPT_SUPERBLOCK; 2933b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 2943b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (e2fsck_journal_fix_bad_inode(ctx, pctx)) 2953b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return EXT2_ET_UNSUPP_FEATURE; 2963b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 2973b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return 0; 2983b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o} 2993b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 3003b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'ostatic int e2fsck_journal_load(journal_t *journal) 3013b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o{ 3023b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o e2fsck_t ctx = journal->j_dev; 3033b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o journal_superblock_t *jsb; 3043b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o struct buffer_head *jbh = journal->j_sb_buffer; 3053b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o struct problem_context pctx; 3063b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 3073b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o clear_problem_context(&pctx); 3083b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 3093b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o ll_rw_block(READ, 1, jbh); 3103b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (jbh->b_err) { 3113b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o com_err(ctx->device_name, jbh->b_err, 3123b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o _("reading journal superblock\n")); 3133b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return jbh->b_err; 3143b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 3153b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 3163b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o jsb = journal->j_superblock; 3173b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o /* If we don't even have JFS_MAGIC, we probably have a wrong inode */ 3183b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER)) 3193b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return e2fsck_journal_fix_bad_inode(ctx, &pctx); 3203b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 3213b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK) || 3223b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o jsb->s_blocksize != htonl(journal->j_blocksize)) { 3233b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o com_err(ctx->device_name, EXT2_ET_CORRUPT_SUPERBLOCK, 3243b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o _("%s: no valid journal superblock found\n")); 3253b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return EXT2_ET_CORRUPT_SUPERBLOCK; 3263b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 3273b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 3283b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK)) { 3293b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o pctx.num = ntohl(jsb->s_header.h_blocktype); 3303b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return e2fsck_journal_fix_unsupported_super(ctx, &pctx); 3313b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 3323b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 3333b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (ntohl(jsb->s_maxlen) < journal->j_maxlen) 3343b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o journal->j_maxlen = ntohl(jsb->s_maxlen); 3353b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) { 3363b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o com_err(ctx->device_name, EXT2_ET_CORRUPT_SUPERBLOCK, 3373b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o _("%s: journal too short\n")); 3383b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return EXT2_ET_CORRUPT_SUPERBLOCK; 3393b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 3403b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 3413b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o journal->j_tail_sequence = ntohl(jsb->s_sequence); 342ecf1b7767e1772f4c6dba8f02026057ed05397bdTheodore Ts'o journal->j_transaction_sequence = journal->j_tail_sequence; 3433b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o journal->j_tail = ntohl(jsb->s_start); 3443b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o journal->j_first = ntohl(jsb->s_first); 3453b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o journal->j_last = ntohl(jsb->s_maxlen); 3463b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 3473b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return 0; 3483b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o} 3493b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 3503b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'ovoid e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb, 3513b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o blk_t size) 3523b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o{ 3533b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER); 3543b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK); 3553b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o jsb->s_blocksize = htonl(ctx->fs->blocksize); 3563b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o jsb->s_maxlen = htonl(size); 3573b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o jsb->s_first = 1; 3583b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o jsb->s_sequence = htonl(1); 3593b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o} 3603b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 3613b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'ostatic int e2fsck_journal_fix_corrupt_super(e2fsck_t ctx, journal_t *journal, 3623b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o struct problem_context *pctx) 3633b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o{ 3643b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o struct ext2fs_sb *s = (struct ext2fs_sb *)ctx->fs->super; 3653b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o int recover = s->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER; 3663b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 3673b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o pctx->num = journal->j_inode->i_ino; 3683b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 3693b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (s->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) { 3703b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) { 3713b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o journal_superblock_t *jsb = journal->j_superblock; 3723b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 3733b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o e2fsck_journal_reset_super(ctx, jsb, journal->j_maxlen); 3743b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 3753b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o journal->j_transaction_sequence = 1; 3763b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o e2fsck_clear_recover(ctx, recover); 3773b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return 0; 3783b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 3793b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return EXT2_ET_CORRUPT_SUPERBLOCK; 3803b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } else if (e2fsck_journal_fix_bad_inode(ctx, pctx)) 3813b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return EXT2_ET_CORRUPT_SUPERBLOCK; 3823b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 3833b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return 0; 3843b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o} 3853b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 3863b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'ostatic void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal, int reset) 3873b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o{ 3883b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o journal_superblock_t *jsb; 3893b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 3903b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (!(ctx->options & E2F_OPT_READONLY)) { 3913b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o jsb = journal->j_superblock; 3923b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o jsb->s_sequence = htonl(journal->j_transaction_sequence); 3933b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (reset) 3943b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o jsb->s_start = 0; /* this marks the journal as empty */ 3953b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o mark_buffer_dirty(journal->j_sb_buffer, 1); 3963b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 3973b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o brelse(journal->j_sb_buffer); 3983b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 3993b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (journal->j_inode) 4003b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o free(journal->j_inode); 4013b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o ext2fs_free_mem((void **)&journal); 4023b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o} 4033b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 4043b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'oint e2fsck_check_ext3_journal(e2fsck_t ctx) 4053b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o{ 4063b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o struct ext2fs_sb *s = (struct ext2fs_sb *)ctx->fs->super; 4073b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o journal_t *journal; 4083b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o int recover = s->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER; 4093b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o struct problem_context pctx; 4103b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o int reset = 0; 4113b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o int retval; 4123b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 4133b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o /* If we don't have any journal features, don't do anything more */ 4143b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (!(s->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) && 4153b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o !recover && s->s_journal_inum == 0 && s->s_journal_dev == 0 && 4163b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o uuid_is_null(s->s_journal_uuid)) 4173b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return 0; 4183b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 4193b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o clear_problem_context(&pctx); 4203b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o pctx.num = s->s_journal_inum; 4213b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 4223b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o retval = e2fsck_get_journal(ctx, &journal); 4233b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (retval) { 4243b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (retval == EXT2_ET_BAD_INODE_NUM) 4253b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return e2fsck_journal_fix_bad_inode(ctx, &pctx); 4263b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return retval; 4273b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 4283b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 4293b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o retval = e2fsck_journal_load(journal); 4303b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (retval) { 4313b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (retval == EXT2_ET_CORRUPT_SUPERBLOCK) 4323b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return e2fsck_journal_fix_corrupt_super(ctx, journal, 4333b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o &pctx); 4343b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return retval; 4353b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 4363b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 4373b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o /* 4383b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * We want to make the flags consistent here. We will not leave with 4393b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * needs_recovery set but has_journal clear. We can't get in a loop 4403b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * with -y, -n, or -p, only if a user isn't making up their mind. 4413b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o */ 4423b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'ono_has_journal: 4433b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (!(s->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) { 4443b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o recover = s->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER; 4453b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o pctx.str = "inode"; 4463b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) { 4473b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (recover && 4483b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx)) 4493b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o goto no_has_journal; 4503b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o s->s_journal_inum = 0; 4513b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o e2fsck_clear_recover(ctx, recover); 4523b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } else if (!(ctx->options & E2F_OPT_READONLY)) { 4533b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o s->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL; 4543b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o ext2fs_mark_super_dirty(ctx->fs); 4553b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 4563b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 4573b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 4583b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (s->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL && 4593b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o !(s->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) && 4603b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o journal->j_superblock->s_start != 0) { 4613b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (fix_problem(ctx, PR_0_JOURNAL_RESET_JOURNAL, &pctx)) 4623b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o reset = 1; 4633b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o /* I refuse to enable recovery for journal */ 4643b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 4653b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 4663b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o e2fsck_journal_release(ctx, journal, reset); 4673b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return retval; 4683b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o} 4693b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 47080bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'ostatic int recover_ext3_journal(e2fsck_t ctx) 4713b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o{ 4723b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o ext2_filsys fs = ctx->fs; 4733b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o journal_t *journal; 4743b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o int retval; 4753b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 4763b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o retval = e2fsck_get_journal(ctx, &journal); 4773b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (retval) 478ecf1b7767e1772f4c6dba8f02026057ed05397bdTheodore Ts'o return retval; 479ecf1b7767e1772f4c6dba8f02026057ed05397bdTheodore Ts'o 4803b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o retval = e2fsck_journal_load(journal); 4813b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (retval) 482ecf1b7767e1772f4c6dba8f02026057ed05397bdTheodore Ts'o return retval; 4833b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 4843b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o retval = -journal_recover(journal); 4853b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o e2fsck_journal_release(ctx, journal, 1); 4863b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return retval; 4873b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o} 4883b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 4893b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 49080bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o#if 0 4913b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o#define TEMPLATE "/tmp/ext3.XXXXXX" 49217390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o 49317390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o/* 49417390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o * This function attempts to mount and unmount an ext3 filesystem, 49517390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o * which is a cheap way to force the kernel to run the journal and 49680bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o * handle the recovery for us. 49717390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o */ 49880bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'ostatic int recover_ext3_journal_via_mount(e2fsck_t ctx) 49917390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o{ 5003b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o ext2_filsys fs = ctx->fs; 5013b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o char *dirlist[] = {"/mnt","/lost+found","/tmp","/root","/boot",0}; 50280bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o errcode_t retval, retval2; 5033b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o int count = 0; 5043b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o char template[] = TEMPLATE; 5053b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o struct stat buf; 50617390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o char *tmpdir; 50717390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o 5083b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (ctx->options & E2F_OPT_READONLY) { 5093b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o printf("%s: won't do journal recovery while read-only\n", 5103b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o ctx->device_name); 5113b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return EXT2_ET_FILE_RO; 5123b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 5133b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 5143b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o printf(_("%s: trying for ext3 kernel journal recovery\n"), 5153b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o ctx->device_name); 51617390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o /* 51717390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o * First try to make a temporary directory. This may fail if 51817390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o * the root partition is still mounted read-only. 51917390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o */ 5203b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'onewtemp: 52117390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o tmpdir = mktemp(template); 52217390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o if (tmpdir) { 5233b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o jfs_debug(2, "trying %s as ext3 temp mount point\n", tmpdir); 52480bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o if (mkdir(template, 0700)) { 5253b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (errno == EROFS) { 5263b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o tmpdir = NULL; 5273b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o template[0] = '\0'; 5283b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } else if (errno == EEXIST && count++ < 10) { 5293b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o strcpy(template, TEMPLATE); 5303b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o goto newtemp; 53180bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o } 53280bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o return errno; 53317390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o } 5343b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 5353b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 5363b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o /* 5373b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * OK, creating a temporary directory didn't work. 5383b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * Let's try a list of possible temporary mountpoints. 5393b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o */ 5403b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (!tmpdir) { 5413b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o dev_t rootdev; 5423b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o char **cpp, *dir; 5433b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 5443b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (stat("/", &buf)) 54580bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o return errno; 5463b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 5473b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o rootdev = buf.st_dev; 5483b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 54917390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o /* 5503b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * Check that dir is on the same device as root (no other 5513b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * filesystem is mounted there), and it's a directory. 55217390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o */ 5533b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o for (cpp = dirlist; (dir = *cpp); cpp++) 5543b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (stat(dir, &buf) == 0 && buf.st_dev == rootdev && 5553b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o S_ISDIR(buf.st_mode)) { 5563b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o tmpdir = dir; 55717390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o break; 5583b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 5593b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 5603b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 5613b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (tmpdir) { 5623b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o io_manager io_ptr = fs->io->manager; 5633b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o int blocksize = fs->blocksize; 5643b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 5653b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o jfs_debug(2, "using %s for ext3 mount\n", tmpdir); 5663b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o /* FIXME - need to handle loop devices here */ 56780bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o if (mount(ctx->device_name, tmpdir, "ext3", MNT_FL, NULL)) { 56880bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o retval = errno; 5693b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o com_err(ctx->program_name, errno, 5703b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o "when mounting %s", ctx->device_name); 5713b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (template[0]) 5723b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o rmdir(tmpdir); 57380bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o return retval; 57417390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o } 5753b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o /* 5763b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * Now that it mounted cleanly, the filesystem will have been 5773b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * recovered, so we can now unmount it. 5783b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o */ 57980bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o if (umount(tmpdir)) 58017390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o return errno; 5813b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 5823b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o /* 5833b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * Remove the temporary directory, if it was created. 5843b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o */ 5853b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (template[0]) 5863b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o rmdir(tmpdir); 5873b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return 0; 58817390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o } 58980bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o} 59080bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o#endif 59180bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o 59280bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'oint e2fsck_run_ext3_journal(e2fsck_t ctx) 59380bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o{ 59480bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o io_manager io_ptr = ctx->fs->io->manager; 59580bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o int blocksize = ctx->fs->blocksize; 596ecf1b7767e1772f4c6dba8f02026057ed05397bdTheodore Ts'o errcode_t retval, recover_retval; 59780bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o 598ecf1b7767e1772f4c6dba8f02026057ed05397bdTheodore Ts'o if (ctx->options & E2F_OPT_READONLY) { 599ecf1b7767e1772f4c6dba8f02026057ed05397bdTheodore Ts'o printf("%s: won't do journal recovery while read-only\n", 600ecf1b7767e1772f4c6dba8f02026057ed05397bdTheodore Ts'o ctx->device_name); 601ecf1b7767e1772f4c6dba8f02026057ed05397bdTheodore Ts'o return EXT2_ET_FILE_RO; 602ecf1b7767e1772f4c6dba8f02026057ed05397bdTheodore Ts'o } 603ecf1b7767e1772f4c6dba8f02026057ed05397bdTheodore Ts'o 604ecf1b7767e1772f4c6dba8f02026057ed05397bdTheodore Ts'o recover_retval = recover_ext3_journal(ctx); 60580bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o 60680bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o /* 60780bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o * Reload the filesystem context to get up-to-date data from disk 60880bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o * because journal recovery will change the filesystem under us. 60980bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o */ 61080bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o ext2fs_close(ctx->fs); 611ecf1b7767e1772f4c6dba8f02026057ed05397bdTheodore Ts'o retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW, 61280bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o ctx->superblock, blocksize, io_ptr, 61380bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o &ctx->fs); 61480bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o 61580bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o if (retval) { 61680bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o com_err(ctx->program_name, retval, 61780bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o _("while trying to re-open %s"), 61880bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o ctx->device_name); 61980bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o exit(FSCK_ERROR); 62080bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o } 62180bfaa3e40ae6ab00cc3d4d1f4c0eeefce0b1a96Theodore Ts'o ctx->fs->priv_data = ctx; 62217390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o 623ecf1b7767e1772f4c6dba8f02026057ed05397bdTheodore Ts'o /* Set the superblock flags */ 624ecf1b7767e1772f4c6dba8f02026057ed05397bdTheodore Ts'o e2fsck_clear_recover(ctx, recover_retval); 625ecf1b7767e1772f4c6dba8f02026057ed05397bdTheodore Ts'o return recover_retval; 62617390c047f5470eec005c5461a7926d03d6bbbe7Theodore Ts'o} 627