Whamcloud - gitweb
Sync kernel's unification of jbd2 revoke and tag block checksum handling
[tools/e2fsprogs.git] / debugfs / journal.c
index 82d5bca..7908e98 100644 (file)
@@ -23,8 +23,8 @@
 #endif
 
 #define E2FSCK_INCLUDE_INLINE_FUNCS
-#include "jfs_user.h"
 #include "uuid/uuid.h"
+#include "journal.h"
 
 #ifdef CONFIG_JBD_DEBUG                /* Enabled by configure --enable-jfs-debug */
 static int bh_count = 0;
@@ -49,7 +49,7 @@ static int bh_count = 0;
 static int ext2fs_journal_verify_csum_type(journal_t *j,
                                           journal_superblock_t *jsb)
 {
-       if (!journal_has_csum_v2or3(j))
+       if (!jbd2_journal_has_csum_v2or3(j))
                return 1;
 
        return jsb->s_checksum_type == JBD2_CRC32C_CHKSUM;
@@ -73,7 +73,7 @@ static int ext2fs_journal_sb_csum_verify(journal_t *j,
 {
        __u32 provided, calculated;
 
-       if (!journal_has_csum_v2or3(j))
+       if (!jbd2_journal_has_csum_v2or3(j))
                return 1;
 
        provided = ext2fs_be32_to_cpu(jsb->s_checksum);
@@ -87,7 +87,7 @@ static errcode_t ext2fs_journal_sb_csum_set(journal_t *j,
 {
        __u32 crc;
 
-       if (!journal_has_csum_v2or3(j))
+       if (!jbd2_journal_has_csum_v2or3(j))
                return 0;
 
        crc = ext2fs_journal_sb_csum(jsb);
@@ -99,7 +99,8 @@ static errcode_t ext2fs_journal_sb_csum_set(journal_t *j,
  * to use the recovery.c file virtually unchanged from the kernel, so we
  * don't have to do much to keep kernel and user recovery in sync.
  */
-int journal_bmap(journal_t *journal, blk64_t block, unsigned long long *phys)
+int jbd2_journal_bmap(journal_t *journal, blk64_t block,
+                     unsigned long long *phys)
 {
 #ifdef USE_INODE_IO
        *phys = block;
@@ -162,14 +163,14 @@ int sync_blockdev(kdev_t kdev)
        return io_channel_flush(io) ? EIO : 0;
 }
 
-void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
+void ll_rw_block(int rw, int op_flags, int nr, struct buffer_head *bhp[])
 {
        errcode_t retval;
        struct buffer_head *bh;
 
        for (; nr > 0; --nr) {
                bh = *bhp++;
-               if (rw == READ && !bh->b_uptodate) {
+               if (rw == REQ_OP_READ && !bh->b_uptodate) {
                        jfs_debug(3, "reading block %llu/%p\n",
                                  bh->b_blocknr, (void *) bh);
                        retval = io_channel_read_blk64(bh->b_io,
@@ -183,7 +184,7 @@ void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
                                continue;
                        }
                        bh->b_uptodate = 1;
-               } else if (rw == WRITE && bh->b_dirty) {
+               } else if (rw == REQ_OP_WRITE && bh->b_dirty) {
                        jfs_debug(3, "writing block %llu/%p\n",
                                  bh->b_blocknr,
                                  (void *) bh);
@@ -201,7 +202,7 @@ void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
                        bh->b_uptodate = 1;
                } else {
                        jfs_debug(3, "no-op %s for block %llu\n",
-                                 rw == READ ? "read" : "write",
+                                 rw == REQ_OP_READ ? "read" : "write",
                                  bh->b_blocknr);
                }
        }
@@ -220,7 +221,7 @@ static void mark_buffer_clean(struct buffer_head *bh)
 void brelse(struct buffer_head *bh)
 {
        if (bh->b_dirty)
-               ll_rw_block(WRITE, 1, &bh);
+               ll_rw_block(REQ_OP_WRITE, 0, 1, &bh);
        jfs_debug(3, "freeing block %llu/%p (total %d)\n",
                  bh->b_blocknr, (void *) bh, --bh_count);
        ext2fs_free_mem(&bh);
@@ -239,17 +240,23 @@ void mark_buffer_uptodate(struct buffer_head *bh, int val)
 void wait_on_buffer(struct buffer_head *bh)
 {
        if (!bh->b_uptodate)
-               ll_rw_block(READ, 1, &bh);
+               ll_rw_block(REQ_OP_READ, 0, 1, &bh);
 }
 
 
 static void ext2fs_clear_recover(ext2_filsys fs, int error)
 {
-       fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
+       ext2fs_clear_feature_journal_needs_recovery(fs->super);
 
        /* if we had an error doing journal recovery, we need a full fsck */
        if (error)
                fs->super->s_state &= ~EXT2_VALID_FS;
+       /*
+        * If we replayed the journal by definition the file system
+        * was mounted since the last time it was checked
+        */
+       if (fs->super->s_lastcheck >= fs->super->s_mtime)
+               fs->super->s_lastcheck = fs->super->s_mtime - 1;
        ext2fs_mark_super_dirty(fs);
 }
 
@@ -349,7 +356,7 @@ try_backup_journal:
                        goto try_backup_journal;
                }
                if (EXT2_I_SIZE(&j_inode->i_ext2) / journal->j_blocksize <
-                   JFS_MIN_JOURNAL_BLOCKS) {
+                   JBD2_MIN_JOURNAL_BLOCKS) {
                        retval = EXT2_ET_JOURNAL_TOO_SMALL;
                        goto try_backup_journal;
                }
@@ -383,7 +390,7 @@ try_backup_journal:
 #else
                journal->j_inode = j_inode;
                fs->journal_io = fs->io;
-               retval = (errcode_t)journal_bmap(journal, 0, &start);
+               retval = (errcode_t) jbd2_journal_bmap(journal, 0, &start);
                if (retval)
                        goto errout;
 #endif
@@ -437,7 +444,7 @@ try_backup_journal:
                        retval = EXT2_ET_NO_MEMORY;
                        goto errout;
                }
-               ll_rw_block(READ, 1, &bh);
+               ll_rw_block(REQ_OP_READ, 0, 1, &bh);
                retval = bh->b_err;
                if (retval) {
                        brelse(bh);
@@ -451,8 +458,7 @@ try_backup_journal:
                        ext2fs_swap_super(&jsuper);
 #endif
                if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
-                   !(jsuper.s_feature_incompat &
-                     EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
+                   !ext2fs_has_feature_journal_dev(&jsuper)) {
                        retval = EXT2_ET_LOAD_EXT_JOURNAL;
                        brelse(bh);
                        goto errout;
@@ -466,8 +472,7 @@ try_backup_journal:
                }
 
                /* Check the superblock checksum */
-               if (jsuper.s_feature_ro_compat &
-                   EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) {
+               if (ext2fs_has_feature_metadata_csum(&jsuper)) {
                        struct struct_ext2_filsys fsx;
                        struct ext2_super_block superx;
                        void *p;
@@ -476,8 +481,7 @@ try_backup_journal:
                        memcpy(&fsx, fs, sizeof(fsx));
                        memcpy(&superx, fs->super, sizeof(superx));
                        fsx.super = &superx;
-                       fsx.super->s_feature_ro_compat |=
-                                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM;
+                       ext2fs_set_feature_metadata_csum(fsx.super);
                        if (!ext2fs_superblock_csum_verify(&fsx, p)) {
                                retval = EXT2_ET_LOAD_EXT_JOURNAL;
                                brelse(bh);
@@ -522,10 +526,8 @@ errout:
 static errcode_t ext2fs_journal_fix_bad_inode(ext2_filsys fs)
 {
        struct ext2_super_block *sb = fs->super;
-       int recover = fs->super->s_feature_incompat &
-               EXT3_FEATURE_INCOMPAT_RECOVER;
-       int has_journal = fs->super->s_feature_compat &
-               EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+       int recover = ext2fs_has_feature_journal_needs_recovery(fs->super);
+       int has_journal = ext2fs_has_feature_journal(fs->super);
 
        if (has_journal || sb->s_journal_inum) {
                /* The journal inode is bogus, remove and force full fsck */
@@ -553,17 +555,17 @@ static errcode_t ext2fs_journal_load(journal_t *journal)
        journal_superblock_t *jsb;
        struct buffer_head *jbh = journal->j_sb_buffer;
 
-       ll_rw_block(READ, 1, &jbh);
+       ll_rw_block(REQ_OP_READ, 0, 1, &jbh);
        if (jbh->b_err)
                return jbh->b_err;
 
        jsb = journal->j_superblock;
-       /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
-       if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
+       /* If we don't even have JBD2_MAGIC, we probably have a wrong inode */
+       if (jsb->s_header.h_magic != htonl(JBD2_MAGIC_NUMBER))
                return ext2fs_journal_fix_bad_inode(fs);
 
        switch (ntohl(jsb->s_header.h_blocktype)) {
-       case JFS_SUPERBLOCK_V1:
+       case JBD2_SUPERBLOCK_V1:
                journal->j_format_version = 1;
                if (jsb->s_feature_compat ||
                    jsb->s_feature_incompat ||
@@ -572,7 +574,7 @@ static errcode_t ext2fs_journal_load(journal_t *journal)
                        clear_v2_journal_fields(journal);
                break;
 
-       case JFS_SUPERBLOCK_V2:
+       case JBD2_SUPERBLOCK_V2:
                journal->j_format_version = 2;
                if (ntohl(jsb->s_nr_users) > 1 &&
                    uuid_is_null(fs->super->s_journal_uuid))
@@ -585,10 +587,10 @@ static errcode_t ext2fs_journal_load(journal_t *journal)
         * These should never appear in a journal super block, so if
         * they do, the journal is badly corrupted.
         */
-       case JFS_DESCRIPTOR_BLOCK:
-       case JFS_COMMIT_BLOCK:
-       case JFS_REVOKE_BLOCK:
-               return EXT2_ET_CORRUPT_SUPERBLOCK;
+       case JBD2_DESCRIPTOR_BLOCK:
+       case JBD2_COMMIT_BLOCK:
+       case JBD2_REVOKE_BLOCK:
+               return EXT2_ET_CORRUPT_JOURNAL_SB;
 
        /* If we don't understand the superblock major type, but there
         * is a magic number, then it is likely to be a new format we
@@ -597,26 +599,25 @@ static errcode_t ext2fs_journal_load(journal_t *journal)
                return EXT2_ET_JOURNAL_UNSUPP_VERSION;
        }
 
-       if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
+       if (JBD2_HAS_INCOMPAT_FEATURE(journal, ~JBD2_KNOWN_INCOMPAT_FEATURES))
                return EXT2_ET_UNSUPP_FEATURE;
 
-       if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
+       if (JBD2_HAS_RO_COMPAT_FEATURE(journal, ~JBD2_KNOWN_ROCOMPAT_FEATURES))
                return EXT2_ET_RO_UNSUPP_FEATURE;
 
        /* Checksum v1-3 are mutually exclusive features. */
-       if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V2) &&
-           JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V3))
-               return EXT2_ET_CORRUPT_SUPERBLOCK;
+       if (jbd2_has_feature_csum2(journal) && jbd2_has_feature_csum3(journal))
+               return EXT2_ET_CORRUPT_JOURNAL_SB;
 
-       if (journal_has_csum_v2or3(journal) &&
-           JFS_HAS_COMPAT_FEATURE(journal, JFS_FEATURE_COMPAT_CHECKSUM))
-               return EXT2_ET_CORRUPT_SUPERBLOCK;
+       if (jbd2_journal_has_csum_v2or3(journal) &&
+           jbd2_has_feature_checksum(journal))
+               return EXT2_ET_CORRUPT_JOURNAL_SB;
 
        if (!ext2fs_journal_verify_csum_type(journal, jsb) ||
            !ext2fs_journal_sb_csum_verify(journal, jsb))
-               return EXT2_ET_CORRUPT_SUPERBLOCK;
+               return EXT2_ET_CORRUPT_JOURNAL_SB;
 
-       if (journal_has_csum_v2or3(journal))
+       if (jbd2_journal_has_csum_v2or3(journal))
                journal->j_csum_seed = jbd2_chksum(journal, ~0, jsb->s_uuid,
                                                   sizeof(jsb->s_uuid));
 
@@ -624,12 +625,12 @@ static errcode_t ext2fs_journal_load(journal_t *journal)
         * format to be able to proceed safely, so any other checks that
         * fail we should attempt to recover from. */
        if (jsb->s_blocksize != htonl(journal->j_blocksize))
-               return EXT2_ET_CORRUPT_SUPERBLOCK;
+               return EXT2_ET_CORRUPT_JOURNAL_SB;
 
        if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
                journal->j_maxlen = ntohl(jsb->s_maxlen);
        else if (ntohl(jsb->s_maxlen) > journal->j_maxlen)
-               return EXT2_ET_CORRUPT_SUPERBLOCK;
+               return EXT2_ET_CORRUPT_JOURNAL_SB;
 
        journal->j_tail_sequence = ntohl(jsb->s_sequence);
        journal->j_transaction_sequence = journal->j_tail_sequence;
@@ -640,7 +641,7 @@ static errcode_t ext2fs_journal_load(journal_t *journal)
        return 0;
 }
 
-void ext2fs_journal_release(ext2_filsys fs, journal_t *journal,
+static void ext2fs_journal_release(ext2_filsys fs, journal_t *journal,
                                   int reset, int drop)
 {
        journal_superblock_t *jsb;
@@ -661,6 +662,8 @@ void ext2fs_journal_release(ext2_filsys fs, journal_t *journal,
                if (fs->io != fs->journal_io)
                        io_channel_close(fs->journal_io);
                fs->journal_io = NULL;
+               free(fs->journal_name);
+               fs->journal_name = NULL;
        }
 
 #ifndef USE_INODE_IO
@@ -676,16 +679,15 @@ void ext2fs_journal_release(ext2_filsys fs, journal_t *journal,
  * This function makes sure that the superblock fields regarding the
  * journal are consistent.
  */
-errcode_t ext2fs_check_ext3_journal(ext2_filsys fs)
+static errcode_t ext2fs_check_ext3_journal(ext2_filsys fs)
 {
        struct ext2_super_block *sb = fs->super;
        journal_t *journal;
-       int recover = fs->super->s_feature_incompat &
-               EXT3_FEATURE_INCOMPAT_RECOVER;
+       int recover = ext2fs_has_feature_journal_needs_recovery(fs->super);
        errcode_t retval;
 
        /* If we don't have any journal features, don't do anything more */
-       if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
+       if (!ext2fs_has_feature_journal(sb) &&
            !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
            uuid_is_null(sb->s_journal_uuid))
                return 0;
@@ -703,13 +705,13 @@ errcode_t ext2fs_check_ext3_journal(ext2_filsys fs)
         * needs_recovery set but has_journal clear.  We can't get in a loop
         * with -y, -n, or -p, only if a user isn't making up their mind.
         */
-       if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
+       if (!ext2fs_has_feature_journal(sb)) {
                retval = EXT2_ET_JOURNAL_FLAGS_WRONG;
                goto err;
        }
 
-       if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
-           !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
+       if (ext2fs_has_feature_journal(sb) &&
+           !ext2fs_has_feature_journal_needs_recovery(sb) &&
            journal->j_superblock->s_start != 0) {
                retval = EXT2_ET_JOURNAL_FLAGS_WRONG;
                goto err;
@@ -720,7 +722,7 @@ errcode_t ext2fs_check_ext3_journal(ext2_filsys fs)
         * the journal's errno is set; if so, we need to mark the file
         * system as being corrupt and clear the journal's s_errno.
         */
-       if (!(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
+       if (!ext2fs_has_feature_journal_needs_recovery(sb) &&
            journal->j_superblock->s_errno) {
                fs->super->s_state |= EXT2_ERROR_FS;
                ext2fs_mark_super_dirty(fs);
@@ -739,7 +741,7 @@ static errcode_t recover_ext3_journal(ext2_filsys fs)
        journal_t *journal;
        errcode_t retval;
 
-       journal_init_revoke_caches();
+       jbd2_journal_init_revoke_caches();
        retval = ext2fs_get_journal(fs, &journal);
        if (retval)
                return retval;
@@ -748,11 +750,11 @@ static errcode_t recover_ext3_journal(ext2_filsys fs)
        if (retval)
                goto errout;
 
-       retval = journal_init_revoke(journal, 1024);
+       retval = jbd2_journal_init_revoke(journal, 1024);
        if (retval)
                goto errout;
 
-       retval = -journal_recover(journal);
+       retval = -jbd2_journal_recover(journal);
        if (retval)
                goto errout;
 
@@ -762,8 +764,8 @@ static errcode_t recover_ext3_journal(ext2_filsys fs)
        }
 
 errout:
-       journal_destroy_revoke(journal);
-       journal_destroy_revoke_caches();
+       jbd2_journal_destroy_revoke(journal);
+       jbd2_journal_destroy_revoke_caches();
        ext2fs_journal_release(fs, journal, 1, 0);
        return retval;
 }
@@ -798,14 +800,14 @@ errcode_t ext2fs_run_ext3_journal(ext2_filsys *fsp)
                kbytes_written = stats->bytes_written >> 10;
 
        ext2fs_mmp_stop(fs);
-       fsname = strdup(fs->device_name);
+       fsname = fs->device_name;
+       fs->device_name = NULL;
        fsflags = fs->flags;
        fsblocksize = fs->blocksize;
        ext2fs_free(fs);
-       retval = ext2fs_open(fsname, fsflags,
-                            0, fsblocksize, io_ptr,
-                            fsp);
-       free(fsname);
+       *fsp = NULL;
+       retval = ext2fs_open(fsname, fsflags, 0, fsblocksize, io_ptr, fsp);
+       ext2fs_free_mem(&fsname);
        if (retval)
                return retval;
 
@@ -829,7 +831,7 @@ errcode_t ext2fs_open_journal(ext2_filsys fs, journal_t **j)
        journal_t *journal;
        errcode_t retval;
 
-       journal_init_revoke_caches();
+       jbd2_journal_init_revoke_caches();
        retval = ext2fs_get_journal(fs, &journal);
        if (retval)
                return retval;
@@ -838,7 +840,7 @@ errcode_t ext2fs_open_journal(ext2_filsys fs, journal_t **j)
        if (retval)
                goto errout;
 
-       retval = journal_init_revoke(journal, 1024);
+       retval = jbd2_journal_init_revoke(journal, 1024);
        if (retval)
                goto errout;
 
@@ -851,8 +853,8 @@ errcode_t ext2fs_open_journal(ext2_filsys fs, journal_t **j)
        return 0;
 
 errout:
-       journal_destroy_revoke(journal);
-       journal_destroy_revoke_caches();
+       jbd2_journal_destroy_revoke(journal);
+       jbd2_journal_destroy_revoke_caches();
        ext2fs_journal_release(fs, journal, 1, 0);
        return retval;
 }
@@ -861,8 +863,8 @@ errcode_t ext2fs_close_journal(ext2_filsys fs, journal_t **j)
 {
        journal_t *journal = *j;
 
-       journal_destroy_revoke(journal);
-       journal_destroy_revoke_caches();
+       jbd2_journal_destroy_revoke(journal);
+       jbd2_journal_destroy_revoke_caches();
        ext2fs_journal_release(fs, journal, 0, 0);
        *j = NULL;
 
@@ -874,7 +876,7 @@ void jbd2_commit_block_csum_set(journal_t *j, struct buffer_head *bh)
        struct commit_header *h;
        __u32 csum;
 
-       if (!journal_has_csum_v2or3(j))
+       if (!jbd2_journal_has_csum_v2or3(j))
                return;
 
        h = (struct commit_header *)(bh->b_data);
@@ -887,29 +889,19 @@ void jbd2_commit_block_csum_set(journal_t *j, struct buffer_head *bh)
 
 void jbd2_revoke_csum_set(journal_t *j, struct buffer_head *bh)
 {
-       struct journal_revoke_tail *tail;
-       __u32 csum;
-
-       if (!journal_has_csum_v2or3(j))
-               return;
-
-       tail = (struct journal_revoke_tail *)(bh->b_data + j->j_blocksize -
-                       sizeof(struct journal_revoke_tail));
-       tail->r_checksum = 0;
-       csum = jbd2_chksum(j, j->j_csum_seed, bh->b_data, j->j_blocksize);
-       tail->r_checksum = ext2fs_cpu_to_be32(csum);
+       jbd2_descr_block_csum_set(j, bh);
 }
 
 void jbd2_descr_block_csum_set(journal_t *j, struct buffer_head *bh)
 {
-       struct journal_block_tail *tail;
+       struct jbd2_journal_block_tail *tail;
        __u32 csum;
 
-       if (!journal_has_csum_v2or3(j))
+       if (!jbd2_journal_has_csum_v2or3(j))
                return;
 
-       tail = (struct journal_block_tail *)(bh->b_data + j->j_blocksize -
-                       sizeof(struct journal_block_tail));
+       tail = (struct jbd2_journal_block_tail *)(bh->b_data + j->j_blocksize -
+                       sizeof(struct jbd2_journal_block_tail));
        tail->t_checksum = 0;
        csum = jbd2_chksum(j, j->j_csum_seed, bh->b_data, j->j_blocksize);
        tail->t_checksum = ext2fs_cpu_to_be32(csum);
@@ -922,14 +914,14 @@ void jbd2_block_tag_csum_set(journal_t *j, journal_block_tag_t *tag,
        __u32 csum32;
        __be32 seq;
 
-       if (!journal_has_csum_v2or3(j))
+       if (!jbd2_journal_has_csum_v2or3(j))
                return;
 
        seq = ext2fs_cpu_to_be32(sequence);
        csum32 = jbd2_chksum(j, j->j_csum_seed, (__u8 *)&seq, sizeof(seq));
        csum32 = jbd2_chksum(j, csum32, bh->b_data, bh->b_size);
 
-       if (JFS_HAS_INCOMPAT_FEATURE(j, JFS_FEATURE_INCOMPAT_CSUM_V3))
+       if (jbd2_has_feature_csum3(j))
                tag3->t_checksum = ext2fs_cpu_to_be32(csum32);
        else
                tag->t_checksum = ext2fs_cpu_to_be16(csum32);