]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
Merge branch 'maint' into next
authorTheodore Ts'o <tytso@mit.edu>
Thu, 16 Jan 2020 23:33:24 +0000 (18:33 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Thu, 16 Jan 2020 23:33:24 +0000 (18:33 -0500)
90 files changed:
configure
configure.ac
contrib/ext4-ioc.c [new file with mode: 0644]
contrib/jbd2-resync.sh [deleted file]
debian/changelog
debian/libext2fs2.symbols
debugfs/debugfs.c
debugfs/do_journal.c
debugfs/htree.c
debugfs/journal.c
debugfs/logdump.c
e2fsck/Android.bp
e2fsck/Makefile.in
e2fsck/e2fsck.c
e2fsck/e2fsck.h
e2fsck/encrypted_files.c [new file with mode: 0644]
e2fsck/jfs_user.h
e2fsck/journal.c
e2fsck/pass1.c
e2fsck/pass2.c
e2fsck/problem.c
e2fsck/problem.h
e2fsck/recovery.c
e2fsck/revoke.c
e2fsck/unix.c
lib/config.h.in
lib/e2p/feature.c
lib/e2p/ljs.c
lib/ext2fs/blknum.c
lib/ext2fs/csum.c
lib/ext2fs/ext2_fs.h
lib/ext2fs/ext2fs.h
lib/ext2fs/imager.c
lib/ext2fs/jfs_compat.h
lib/ext2fs/kernel-jbd.h
lib/ext2fs/mkjournal.c
lib/ext2fs/openfs.c
misc/dumpe2fs.c
misc/fuse2fs.1.in
misc/fuse2fs.c
misc/mke2fs.c
misc/tune2fs.c
po/POTFILES.in
resize/main.c
tests/f_bad_encryption/expect.1 [new file with mode: 0644]
tests/f_bad_encryption/expect.2 [new file with mode: 0644]
tests/f_bad_encryption/image.gz [new file with mode: 0644]
tests/f_bad_encryption/mkimage.sh [new file with mode: 0755]
tests/f_bad_encryption/name [new file with mode: 0644]
tests/f_many_subdirs/expect.1 [new file with mode: 0644]
tests/f_many_subdirs/expect.2 [new file with mode: 0644]
tests/f_many_subdirs/image.gz [new file with mode: 0644]
tests/f_many_subdirs/name [new file with mode: 0644]
tests/f_short_encrypted_dirent/expect.1
tests/f_short_encrypted_dirent/expect.2
tests/f_short_encrypted_dirent/image.gz
tests/f_uninit_bad_free_inodes/expect.1 [new file with mode: 0644]
tests/f_uninit_bad_free_inodes/expect.2 [new file with mode: 0644]
tests/f_uninit_bad_free_inodes/image.gz [new file with mode: 0644]
tests/f_uninit_bad_free_inodes/name [new file with mode: 0644]
tests/f_uninit_blk_used_not_set/expect.1 [new file with mode: 0644]
tests/f_uninit_blk_used_not_set/expect.2 [new file with mode: 0644]
tests/f_uninit_blk_used_not_set/image.gz [new file with mode: 0644]
tests/f_uninit_blk_used_not_set/name [new file with mode: 0644]
tests/f_uninit_checksum_bad/expect.1 [new file with mode: 0644]
tests/f_uninit_checksum_bad/expect.2 [new file with mode: 0644]
tests/f_uninit_checksum_bad/image.gz [new file with mode: 0644]
tests/f_uninit_checksum_bad/name [new file with mode: 0644]
tests/f_uninit_disable/expect.1 [new file with mode: 0644]
tests/f_uninit_disable/expect.2 [new file with mode: 0644]
tests/f_uninit_disable/image.gz [new file with mode: 0644]
tests/f_uninit_disable/name [new file with mode: 0644]
tests/f_uninit_enable/expect.1 [new file with mode: 0644]
tests/f_uninit_enable/expect.2 [new file with mode: 0644]
tests/f_uninit_enable/image.gz [new file with mode: 0644]
tests/f_uninit_enable/name [new file with mode: 0644]
tests/f_uninit_inode_past_unused/expect.1 [new file with mode: 0644]
tests/f_uninit_inode_past_unused/expect.2 [new file with mode: 0644]
tests/f_uninit_inode_past_unused/image.gz [new file with mode: 0644]
tests/f_uninit_inode_past_unused/name [new file with mode: 0644]
tests/f_uninit_restart_fsck/expect.1 [new file with mode: 0644]
tests/f_uninit_restart_fsck/expect.2 [new file with mode: 0644]
tests/f_uninit_restart_fsck/image.gz [new file with mode: 0644]
tests/f_uninit_restart_fsck/name [new file with mode: 0644]
tests/f_uninit_set_inode_not_set/expect.1 [new file with mode: 0644]
tests/f_uninit_set_inode_not_set/expect.2 [new file with mode: 0644]
tests/f_uninit_set_inode_not_set/image.gz [new file with mode: 0644]
tests/f_uninit_set_inode_not_set/name [new file with mode: 0644]
tests/j_corrupt_journal_block/expect
version.h

index a38735b0133ea16771fa78fc3ef144607a6049ae..d90188afe0420ee7363f67845e2d7a7e4853acb3 100755 (executable)
--- a/configure
+++ b/configure
@@ -785,6 +785,7 @@ LIBUUID
 PKG_CONFIG_LIBDIR
 PKG_CONFIG_PATH
 PKG_CONFIG
+DEV_FEATURES_CMT
 TEST_IO_CMT
 PRIVATE_LIBS_CMT
 LDFLAG_DYNAMIC
@@ -894,6 +895,7 @@ enable_hardening
 enable_jbd_debug
 enable_blkid_debug
 enable_testio_debug
+enable_developer_features
 enable_libuuid
 enable_libblkid
 enable_subset
@@ -1580,6 +1582,7 @@ Optional Features:
   --enable-jbd-debug     enable journal debugging
   --enable-blkid-debug    enable blkid debugging
   --disable-testio-debug  disable the use of the test I/O manager for debugging
+  --enable-developer-features  enable features for use by ext4 developers
   --enable-libuuid       build and use private uuid library
   --enable-libblkid      build and use private blkid library
   --enable-subset        enable subset-only build
@@ -5168,6 +5171,30 @@ TEST_IO_CMT=
 fi
 
 
+# Check whether --enable-developer-features was given.
+if test "${enable_developer_features+set}" = set; then :
+  enableval=$enable_developer_features;
+if test "$enableval" = "yes"
+then
+       DEV_FEATURES_CMT=
+       $as_echo "#define CONFIG_DEVELOPER_FEATURES 1" >>confdefs.h
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling ext4 developer features" >&5
+$as_echo "Enabling ext4 developer features" >&6; }
+else
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling ext4 developer features" >&5
+$as_echo "Disabling ext4 developer features" >&6; }
+       DEV_FEATURES_CMT="#"
+fi
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling ext4 developer features by default" >&5
+$as_echo "Disabling ext4 developer features by default" >&6; }
+DEV_FEATURES_CMT=
+
+fi
+
+
 
 
 
index cf03444d8f178fd28b08ed4aef69ce4e0cf5bbdb..18e434bc6ebc945775d53e4ed1f08ef4033dacc5 100644 (file)
@@ -439,6 +439,27 @@ TEST_IO_CMT=
 )
 AC_SUBST(TEST_IO_CMT)
 dnl
+dnl handle --enable-developer-features
+dnl
+AC_ARG_ENABLE([developer-features],
+[  --enable-developer-features  enable features for use by ext4 developers],
+AH_TEMPLATE([CONFIG_DEVELOPER_FEATURES],
+       [Define to 1 for features for use by ext4 developers])
+if test "$enableval" = "yes"
+then
+       DEV_FEATURES_CMT=
+       AC_DEFINE(CONFIG_DEVELOPER_FEATURES, 1)
+       AC_MSG_RESULT([Enabling ext4 developer features])
+else
+       AC_MSG_RESULT([Disabling ext4 developer features])
+       DEV_FEATURES_CMT="#"
+fi
+,
+AC_MSG_RESULT([Disabling ext4 developer features by default])
+DEV_FEATURES_CMT=
+)
+AC_SUBST(DEV_FEATURES_CMT)
+dnl
 dnl handle --disable-libuuid
 dnl
 PKG_PROG_PKG_CONFIG
diff --git a/contrib/ext4-ioc.c b/contrib/ext4-ioc.c
new file mode 100644 (file)
index 0000000..42f022d
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Test program to trigger various ext4 ioctl's
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#if (!defined(EXT4_IOC_ALLOC_DA_BLKS) && defined(__linux__))
+#define EXT4_IOC_ALLOC_DA_BLKS         _IO('f', 12)
+#endif
+
+#if (!defined(EXT4_IOC_SWAP_BOOT) && defined(__linux__))
+#define EXT4_IOC_SWAP_BOOT             _IO('f', 17)
+#endif
+
+#if (!defined(EXT4_IOC_PRECACHE_EXTENTS) && defined(__linux__))
+#define EXT4_IOC_PRECACHE_EXTENTS      _IO('f', 18)
+#endif
+
+#if (!defined(EXT4_IOC_CLEAR_ES_CACHE) && defined(__linux__))
+#define EXT4_IOC_CLEAR_ES_CACHE                _IO('f', 40)
+#endif
+
+
+#define EXT4_F_RW      0x0001
+
+struct cmd {
+       const char      *cmd;
+       unsigned long   ioc;
+       int             flags;
+};
+
+struct cmd cmds[] = {
+       { "alloc_da_blks", EXT4_IOC_ALLOC_DA_BLKS, EXT4_F_RW },
+       { "precache", EXT4_IOC_PRECACHE_EXTENTS, 0 },
+       { "swap_boot", EXT4_IOC_SWAP_BOOT, EXT4_F_RW },
+       { "clear_es_cache", EXT4_IOC_CLEAR_ES_CACHE, EXT4_F_RW },
+       { NULL, 0 }
+};
+
+const char *progname;
+
+void usage()
+{
+       struct cmd *p;
+
+       fprintf(stderr, "Usage: %s <cmd> <file>\n\n", progname);
+       fprintf(stderr, "Available commands:\n");
+       for (p = cmds; p->cmd; p++) {
+               fprintf(stderr, "\t%s\n", p->cmd);
+       }
+       exit(1);
+}
+
+int do_single_cmd(const char *fn, struct cmd *p)
+{
+       int     fd;
+       int     oflags = O_RDONLY;
+
+       if (p->flags & EXT4_F_RW)
+               oflags = O_RDWR;
+       fd = open(fn, oflags, 0);
+       if (fd < 0) {
+               perror("open");
+               return 1;
+       }
+       if (ioctl(fd, p->ioc) < 0) {
+               perror("ioctl");
+               return 1;
+       }
+       close(fd);
+       return 0;
+}
+
+int main(int argc, char **argv)
+{
+       int     i, fails = 0;
+       struct cmd *p;
+
+       progname = argv[0];
+       if (argc < 3 || strcmp(argv[1], "help") == 0)
+               usage();
+       for (p = cmds; p->cmd; p++) {
+               if (strcmp(argv[1], p->cmd) == 0)
+                       break;
+       }
+       if (p->cmd == NULL) {
+               fprintf(stderr, "Invalid command: %s\n", argv[1]);
+               usage();
+       }
+       for (i = 2; i < argc; i++)
+               fails += do_single_cmd(argv[i], p);
+       return fails;
+}
diff --git a/contrib/jbd2-resync.sh b/contrib/jbd2-resync.sh
deleted file mode 100755 (executable)
index 4133b63..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/bash
-
-if [ -z "$1" -o -z "$2" ]; then
-       echo "Usage: $0 kernel-file e2fsprogs-file"
-       exit 0
-fi
-
-# Transform a few things to fit the compatibility things defined in jfs_user.h.
-# Use the ext2fs_ endian conversion functions because they truncate oversized
-# inputs (e.g. passing a u32 to cpu_to_be16()) like the kernel versions and
-# unlike the libc6 versions.
-exec sed -e 's/JBD_/JFS_/g' \
-        -e 's/JBD2_/JFS_/g' \
-        -e 's/jbd2_journal_/journal_/g' \
-        -e 's/__be/__u/g' \
-        -e 's/struct kmem_cache/lkmem_cache_t/g' \
-        -e 's/cpu_to_be/ext2fs_cpu_to_be/g' \
-        -e 's/be\([0-9][0-9]\)_to_cpu/ext2fs_be\1_to_cpu/g' \
-        < "$1" > "$2"
index bf82d154bad854428684fae015bdde883f37527e..b388f1231eb516b26664c40b4b2a4747e1e93898 100644 (file)
@@ -39,6 +39,15 @@ e2fsprogs (1.45.5-1) unstable; urgency=medium
 
  -- Theodore Y. Ts'o <tytso@mit.edu>  Tue, 07 Jan 2020 09:18:39 -0500
 
+e2fsprogs (1.46~WIP.2019.10.09-1) experimental; urgency=medium
+
+  * Add (minimal) support to enable the fast commit feaure.  This is just
+    enough to enable kernel development work; e2fsck replay of journals
+    with the fast commit feature is *not* available.
+  * E2fsck will now check encryption policies for consistency
+
+ -- Theodore Y. Ts'o <tytso@mit.edu>  Wed, 09 Oct 2019 20:22:50 -0400
+
 e2fsprogs (1.45.4-1) unstable; urgency=medium
 
   * New upstream feature
index 3645c67b49ff0339750999c57dfd30f616360099..024630fadcf2e526882f6282441bb87679a78b6f 100644 (file)
@@ -185,6 +185,7 @@ libext2fs.so.2 libext2fs2 #MINVER#
  ext2fs_div_ceil@Base 1.40
  ext2fs_djb2_hash@Base 1.44.3~rc1
  ext2fs_dup_handle@Base 1.37
+ ext2fs_dx_csum@Base 1.46~WIP.2019.10.09
  ext2fs_expand_dir@Base 1.37
  ext2fs_ext_attr_block_csum_set@Base 1.43
  ext2fs_ext_attr_block_csum_verify@Base 1.43
index 15b01214a8df28a26955d50f7771ec4a9cae20d0..9b701455982b2a5f545f76546e6b81deb6b84987 100644 (file)
@@ -2279,9 +2279,9 @@ void do_supported_features(int argc, char *argv[],
        __u32   supp[3] = { EXT2_LIB_FEATURE_COMPAT_SUPP,
                            EXT2_LIB_FEATURE_INCOMPAT_SUPP,
                            EXT2_LIB_FEATURE_RO_COMPAT_SUPP };
-       __u32   jrnl_supp[3] = { JFS_KNOWN_COMPAT_FEATURES,
-                                JFS_KNOWN_INCOMPAT_FEATURES,
-                                JFS_KNOWN_ROCOMPAT_FEATURES };
+       __u32   jrnl_supp[3] = { JBD2_KNOWN_COMPAT_FEATURES,
+                                JBD2_KNOWN_INCOMPAT_FEATURES,
+                                JBD2_KNOWN_ROCOMPAT_FEATURES };
 
        if (argc > 1) {
                ret = find_supp_feature(supp, E2P_FS_FEATURE, argv[1]);
index eeb363eb401e85bf5810282c8b088962a7ea1b64..48b2149c36fa9f1518504ab3c66c5e19fa842e35 100644 (file)
@@ -85,10 +85,10 @@ static errcode_t journal_commit_trans(journal_transaction_t *trans)
 
        /* write the descriptor block header */
        commit = (struct commit_header *)bh->b_data;
-       commit->h_magic = ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER);
-       commit->h_blocktype = ext2fs_cpu_to_be32(JFS_COMMIT_BLOCK);
+       commit->h_magic = ext2fs_cpu_to_be32(JBD2_MAGIC_NUMBER);
+       commit->h_blocktype = ext2fs_cpu_to_be32(JBD2_COMMIT_BLOCK);
        commit->h_sequence = ext2fs_cpu_to_be32(trans->tid);
-       if (jfs_has_feature_checksum(trans->journal)) {
+       if (jbd2_has_feature_checksum(trans->journal)) {
                __u32 csum_v1 = ~0;
                blk64_t cblk;
 
@@ -100,12 +100,12 @@ static errcode_t journal_commit_trans(journal_transaction_t *trans)
                }
 
                for (cblk = trans->start; cblk < trans->block; cblk++) {
-                       err = journal_bmap(trans->journal, cblk,
-                                          &cbh->b_blocknr);
+                       err = jbd2_journal_bmap(trans->journal, cblk,
+                                               &cbh->b_blocknr);
                        if (err)
                                goto error;
                        mark_buffer_uptodate(cbh, 0);
-                       ll_rw_block(READ, 1, &cbh);
+                       ll_rw_block(REQ_OP_READ, 0, 1, &cbh);
                        err = cbh->b_err;
                        if (err)
                                goto error;
@@ -114,8 +114,8 @@ static errcode_t journal_commit_trans(journal_transaction_t *trans)
                                        cbh->b_size);
                }
 
-               commit->h_chksum_type = JFS_CRC32_CHKSUM;
-               commit->h_chksum_size = JFS_CRC32_CHKSUM_SIZE;
+               commit->h_chksum_type = JBD2_CRC32_CHKSUM;
+               commit->h_chksum_size = JBD2_CRC32_CHKSUM_SIZE;
                commit->h_chksum[0] = ext2fs_cpu_to_be32(csum_v1);
        } else {
                commit->h_chksum_type = 0;
@@ -133,14 +133,14 @@ static errcode_t journal_commit_trans(journal_transaction_t *trans)
 
        /* Write block */
        jbd2_commit_block_csum_set(trans->journal, bh);
-       err = journal_bmap(trans->journal, trans->block, &bh->b_blocknr);
+       err = jbd2_journal_bmap(trans->journal, trans->block, &bh->b_blocknr);
        if (err)
                goto error;
 
        dbg_printf("Writing commit block at %llu:%llu\n", trans->block,
                   bh->b_blocknr);
        mark_buffer_dirty(bh);
-       ll_rw_block(WRITE, 1, &bh);
+       ll_rw_block(REQ_OP_WRITE, 0, 1, &bh);
        err = bh->b_err;
        if (err)
                goto error;
@@ -161,7 +161,7 @@ static errcode_t journal_add_revoke_to_trans(journal_transaction_t *trans,
                                             blk64_t *revoke_list,
                                             size_t revoke_len)
 {
-       journal_revoke_header_t *jrb;
+       jbd2_journal_revoke_header_t *jrb;
        void *buf;
        size_t i, offset;
        blk64_t curr_blk;
@@ -180,8 +180,8 @@ static errcode_t journal_add_revoke_to_trans(journal_transaction_t *trans,
                return 0;
 
        /* Do we need to leave space at the end for a checksum? */
-       if (journal_has_csum_v2or3(trans->journal))
-               csum_size = sizeof(struct journal_revoke_tail);
+       if (jbd2_journal_has_csum_v2or3(trans->journal))
+               csum_size = sizeof(struct jbd2_journal_block_tail);
 
        curr_blk = trans->block;
 
@@ -190,12 +190,12 @@ static errcode_t journal_add_revoke_to_trans(journal_transaction_t *trans,
        if (bh == NULL)
                return ENOMEM;
        jrb = buf = bh->b_data;
-       jrb->r_header.h_magic = ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER);
-       jrb->r_header.h_blocktype = ext2fs_cpu_to_be32(JFS_REVOKE_BLOCK);
+       jrb->r_header.h_magic = ext2fs_cpu_to_be32(JBD2_MAGIC_NUMBER);
+       jrb->r_header.h_blocktype = ext2fs_cpu_to_be32(JBD2_REVOKE_BLOCK);
        jrb->r_header.h_sequence = ext2fs_cpu_to_be32(trans->tid);
        offset = sizeof(*jrb);
 
-       if (jfs_has_feature_64bit(trans->journal))
+       if (jbd2_has_feature_64bit(trans->journal))
                sz = 8;
        else
                sz = 4;
@@ -206,14 +206,14 @@ static errcode_t journal_add_revoke_to_trans(journal_transaction_t *trans,
                        jrb->r_count = ext2fs_cpu_to_be32(offset);
                        jbd2_revoke_csum_set(trans->journal, bh);
 
-                       err = journal_bmap(trans->journal, curr_blk,
-                                          &bh->b_blocknr);
+                       err = jbd2_journal_bmap(trans->journal, curr_blk,
+                                               &bh->b_blocknr);
                        if (err)
                                goto error;
                        dbg_printf("Writing revoke block at %llu:%llu\n",
                                   curr_blk, bh->b_blocknr);
                        mark_buffer_dirty(bh);
-                       ll_rw_block(WRITE, 1, &bh);
+                       ll_rw_block(REQ_OP_WRITE, 0, 1, &bh);
                        err = bh->b_err;
                        if (err)
                                goto error;
@@ -228,7 +228,7 @@ static errcode_t journal_add_revoke_to_trans(journal_transaction_t *trans,
                        goto error;
                }
 
-               if (jfs_has_feature_64bit(trans->journal))
+               if (jbd2_has_feature_64bit(trans->journal))
                        *((__u64 *)(&((char *)buf)[offset])) =
                                ext2fs_cpu_to_be64(revoke_list[i]);
                else
@@ -241,13 +241,14 @@ static errcode_t journal_add_revoke_to_trans(journal_transaction_t *trans,
                jrb->r_count = ext2fs_cpu_to_be32(offset);
                jbd2_revoke_csum_set(trans->journal, bh);
 
-               err = journal_bmap(trans->journal, curr_blk, &bh->b_blocknr);
+               err = jbd2_journal_bmap(trans->journal, curr_blk,
+                                       &bh->b_blocknr);
                if (err)
                        goto error;
                dbg_printf("Writing revoke block at %llu:%llu\n",
                           curr_blk, bh->b_blocknr);
                mark_buffer_dirty(bh);
-               ll_rw_block(WRITE, 1, &bh);
+               ll_rw_block(REQ_OP_WRITE, 0, 1, &bh);
                err = bh->b_err;
                if (err)
                        goto error;
@@ -284,8 +285,8 @@ static errcode_t journal_add_blocks_to_trans(journal_transaction_t *trans,
                return 0;
 
        /* Do we need to leave space at the end for a checksum? */
-       if (journal_has_csum_v2or3(trans->journal))
-               csum_size = sizeof(struct journal_block_tail);
+       if (jbd2_journal_has_csum_v2or3(trans->journal))
+               csum_size = sizeof(struct jbd2_journal_block_tail);
 
        curr_blk = jdb_blk = trans->block;
 
@@ -303,8 +304,8 @@ static errcode_t journal_add_blocks_to_trans(journal_transaction_t *trans,
                goto error;
        }
        jdb = jdb_buf = bh->b_data;
-       jdb->h_magic = ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER);
-       jdb->h_blocktype = ext2fs_cpu_to_be32(JFS_DESCRIPTOR_BLOCK);
+       jdb->h_magic = ext2fs_cpu_to_be32(JBD2_MAGIC_NUMBER);
+       jdb->h_blocktype = ext2fs_cpu_to_be32(JBD2_DESCRIPTOR_BLOCK);
        jdb->h_sequence = ext2fs_cpu_to_be32(trans->tid);
        jdbt = (journal_block_tag_t *)(jdb + 1);
 
@@ -322,14 +323,14 @@ static errcode_t journal_add_blocks_to_trans(journal_transaction_t *trans,
                if ((char *)jdbt + tag_bytes >
                    (char *)jdb_buf + trans->journal->j_blocksize - csum_size) {
                        jbd2_descr_block_csum_set(trans->journal, bh);
-                       err = journal_bmap(trans->journal, jdb_blk,
+                       err = jbd2_journal_bmap(trans->journal, jdb_blk,
                                           &bh->b_blocknr);
                        if (err)
                                goto error;
                        dbg_printf("Writing descriptor block at %llu:%llu\n",
                                   jdb_blk, bh->b_blocknr);
                        mark_buffer_dirty(bh);
-                       ll_rw_block(WRITE, 1, &bh);
+                       ll_rw_block(REQ_OP_WRITE, 0, 1, &bh);
                        err = bh->b_err;
                        if (err)
                                goto error;
@@ -349,7 +350,7 @@ static errcode_t journal_add_blocks_to_trans(journal_transaction_t *trans,
                jdbt->t_blocknr = ext2fs_cpu_to_be32(block_list[i] & 0xFFFFFFFF);
                jdbt->t_flags = 0;
                if (jdbt != (journal_block_tag_t *)(jdb + 1))
-                       jdbt->t_flags |= ext2fs_cpu_to_be16(JFS_FLAG_SAME_UUID);
+                       jdbt->t_flags |= ext2fs_cpu_to_be16(JBD2_FLAG_SAME_UUID);
                else {
                        memcpy(jdbt + tag_bytes,
                               trans->journal->j_superblock->s_uuid,
@@ -357,26 +358,26 @@ static errcode_t journal_add_blocks_to_trans(journal_transaction_t *trans,
                        tag_bytes += 16;
                }
                if (i == block_len - 1)
-                       jdbt->t_flags |= ext2fs_cpu_to_be16(JFS_FLAG_LAST_TAG);
-               if (*((__u32 *)buf) == ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER)) {
+                       jdbt->t_flags |= ext2fs_cpu_to_be16(JBD2_FLAG_LAST_TAG);
+               if (*((__u32 *)buf) == ext2fs_cpu_to_be32(JBD2_MAGIC_NUMBER)) {
                        *((__u32 *)buf) = 0;
-                       jdbt->t_flags |= ext2fs_cpu_to_be16(JFS_FLAG_ESCAPE);
+                       jdbt->t_flags |= ext2fs_cpu_to_be16(JBD2_FLAG_ESCAPE);
                }
-               if (jfs_has_feature_64bit(trans->journal))
+               if (jbd2_has_feature_64bit(trans->journal))
                        jdbt->t_blocknr_high = ext2fs_cpu_to_be32(block_list[i] >> 32);
                jbd2_block_tag_csum_set(trans->journal, jdbt, data_bh,
                                        trans->tid);
 
                /* Write the data block */
-               err = journal_bmap(trans->journal, curr_blk,
-                                  &data_bh->b_blocknr);
+               err = jbd2_journal_bmap(trans->journal, curr_blk,
+                                       &data_bh->b_blocknr);
                if (err)
                        goto error;
                dbg_printf("Writing data block %llu at %llu:%llu tag %d\n",
                           block_list[i], curr_blk, data_bh->b_blocknr,
                           tag_bytes);
                mark_buffer_dirty(data_bh);
-               ll_rw_block(WRITE, 1, &data_bh);
+               ll_rw_block(REQ_OP_WRITE, 0, 1, &data_bh);
                err = data_bh->b_err;
                if (err)
                        goto error;
@@ -388,13 +389,14 @@ static errcode_t journal_add_blocks_to_trans(journal_transaction_t *trans,
        /* Write out the last descriptor block */
        if (jdbt != (journal_block_tag_t *)(jdb + 1)) {
                jbd2_descr_block_csum_set(trans->journal, bh);
-               err = journal_bmap(trans->journal, jdb_blk, &bh->b_blocknr);
+               err = jbd2_journal_bmap(trans->journal, jdb_blk,
+                                       &bh->b_blocknr);
                if (err)
                        goto error;
                dbg_printf("Writing descriptor block at %llu:%llu\n",
                           jdb_blk, bh->b_blocknr);
                mark_buffer_dirty(bh);
-               ll_rw_block(WRITE, 1, &bh);
+               ll_rw_block(REQ_OP_WRITE, 0, 1, &bh);
                err = bh->b_err;
                if (err)
                        goto error;
@@ -416,15 +418,15 @@ static blk64_t journal_guess_blocks(journal_t *journal, blk64_t data_blocks,
 
        /* Estimate # of revoke blocks */
        bs = journal->j_blocksize;
-       if (journal_has_csum_v2or3(journal))
-               bs -= sizeof(struct journal_revoke_tail);
-       sz = jfs_has_feature_64bit(journal) ? sizeof(__u64) : sizeof(__u32);
+       if (jbd2_journal_has_csum_v2or3(journal))
+               bs -= sizeof(struct jbd2_journal_block_tail);
+       sz = jbd2_has_feature_64bit(journal) ? sizeof(__u64) : sizeof(__u32);
        ret += revoke_blocks * sz / bs;
 
        /* Estimate # of data blocks */
        bs = journal->j_blocksize - 16;
-       if (journal_has_csum_v2or3(journal))
-               bs -= sizeof(struct journal_block_tail);
+       if (jbd2_journal_has_csum_v2or3(journal))
+               bs -= sizeof(struct jbd2_journal_block_tail);
        sz = journal_tag_bytes(journal);
        ret += data_blocks * sz / bs;
 
@@ -504,7 +506,7 @@ static errcode_t journal_write(journal_t *journal,
        errcode_t err;
 
        if (revoke_len > 0) {
-               jfs_set_feature_revoke(journal);
+               jbd2_set_feature_revoke(journal);
                mark_buffer_dirty(journal->j_sb_buffer);
        }
 
@@ -624,8 +626,8 @@ static int count_tags(journal_t *journal, char *buf)
        int                     nr = 0, size = journal->j_blocksize;
        int                     tag_bytes = journal_tag_bytes(journal);
 
-       if (journal_has_csum_v2or3(journal))
-               size -= sizeof(struct journal_block_tail);
+       if (jbd2_journal_has_csum_v2or3(journal))
+               size -= sizeof(struct jbd2_journal_block_tail);
 
        tagp = buf + sizeof(journal_header_t);
 
@@ -634,10 +636,10 @@ static int count_tags(journal_t *journal, char *buf)
 
                nr++;
                tagp += tag_bytes;
-               if (!(tag->t_flags & ext2fs_cpu_to_be16(JFS_FLAG_SAME_UUID)))
+               if (!(tag->t_flags & ext2fs_cpu_to_be16(JBD2_FLAG_SAME_UUID)))
                        tagp += 16;
 
-               if (tag->t_flags & ext2fs_cpu_to_be16(JFS_FLAG_LAST_TAG))
+               if (tag->t_flags & ext2fs_cpu_to_be16(JBD2_FLAG_LAST_TAG))
                        break;
        }
 
@@ -687,11 +689,12 @@ static errcode_t journal_find_head(journal_t *journal)
                /* Skip over each chunk of the transaction looking
                 * either the next descriptor block or the final commit
                 * record. */
-               err = journal_bmap(journal, next_log_block, &bh->b_blocknr);
+               err = jbd2_journal_bmap(journal, next_log_block,
+                                       &bh->b_blocknr);
                if (err)
                        goto err;
                mark_buffer_uptodate(bh, 0);
-               ll_rw_block(READ, 1, &bh);
+               ll_rw_block(REQ_OP_READ, 0, 1, &bh);
                err = bh->b_err;
                if (err)
                        goto err;
@@ -707,7 +710,7 @@ static errcode_t journal_find_head(journal_t *journal)
 
                tmp = (journal_header_t *)bh->b_data;
 
-               if (tmp->h_magic != ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER)) {
+               if (tmp->h_magic != ext2fs_cpu_to_be32(JBD2_MAGIC_NUMBER)) {
                        dbg_printf("JBD2: wrong magic 0x%x\n", tmp->h_magic);
                        goto err;
                }
@@ -728,17 +731,17 @@ static errcode_t journal_find_head(journal_t *journal)
                 * to do with it?  That depends on the pass... */
 
                switch (blocktype) {
-               case JFS_DESCRIPTOR_BLOCK:
+               case JBD2_DESCRIPTOR_BLOCK:
                        next_log_block += count_tags(journal, bh->b_data);
                        wrap(journal, next_log_block);
                        continue;
 
-               case JFS_COMMIT_BLOCK:
+               case JBD2_COMMIT_BLOCK:
                        head_block = next_log_block;
                        next_commit_ID++;
                        continue;
 
-               case JFS_REVOKE_BLOCK:
+               case JBD2_REVOKE_BLOCK:
                        continue;
 
                default:
@@ -780,14 +783,14 @@ static void update_journal_csum(journal_t *journal, int ver)
                printf("Setting csum v%d\n", ver);
                switch (ver) {
                case 2:
-                       jfs_clear_feature_csum3(journal);
-                       jfs_set_feature_csum2(journal);
-                       jfs_clear_feature_checksum(journal);
+                       jbd2_clear_feature_csum3(journal);
+                       jbd2_set_feature_csum2(journal);
+                       jbd2_clear_feature_checksum(journal);
                        break;
                case 3:
-                       jfs_set_feature_csum3(journal);
-                       jfs_clear_feature_csum2(journal);
-                       jfs_clear_feature_checksum(journal);
+                       jbd2_set_feature_csum3(journal);
+                       jbd2_clear_feature_csum2(journal);
+                       jbd2_clear_feature_checksum(journal);
                        break;
                default:
                        printf("Unknown checksum v%d\n", ver);
@@ -797,9 +800,9 @@ static void update_journal_csum(journal_t *journal, int ver)
                journal->j_csum_seed = jbd2_chksum(journal, ~0, jsb->s_uuid,
                                                   sizeof(jsb->s_uuid));
        } else {
-               jfs_clear_feature_csum3(journal);
-               jfs_clear_feature_csum2(journal);
-               jfs_set_feature_checksum(journal);
+               jbd2_clear_feature_csum3(journal);
+               jbd2_clear_feature_csum2(journal);
+               jbd2_set_feature_checksum(journal);
        }
 }
 
@@ -821,7 +824,7 @@ static void update_uuid(journal_t *journal)
        if (!ext2fs_has_feature_64bit(fs->super))
                return;
 
-       if (jfs_has_feature_64bit(journal) &&
+       if (jbd2_has_feature_64bit(journal) &&
            ext2fs_has_feature_64bit(fs->super))
                return;
 
@@ -843,7 +846,7 @@ static void update_64bit_flag(journal_t *journal)
        if (!ext2fs_has_feature_64bit(journal->j_fs_dev->k_fs->super))
                return;
 
-       if (jfs_has_feature_64bit(journal) &&
+       if (jbd2_has_feature_64bit(journal) &&
            ext2fs_has_feature_64bit(journal->j_fs_dev->k_fs->super))
                return;
 
@@ -854,7 +857,7 @@ static void update_64bit_flag(journal_t *journal)
                return;
        }
 
-       jfs_set_feature_64bit(journal);
+       jbd2_set_feature_64bit(journal);
 }
 
 void do_journal_open(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)),
index 3aae3c27a3daccab594501e29a966550ec2e6772..b567a76b504666bb3a0576faa90574aab2222144 100644 (file)
@@ -136,7 +136,7 @@ static void htree_dump_int_block(ext2_filsys fs, ext2_ino_t ino,
 static void htree_dump_int_node(ext2_filsys fs, ext2_ino_t ino,
                                struct ext2_inode *inode,
                                struct ext2_dx_root_info * rootnode,
-                               struct ext2_dx_entry *ent,
+                               struct ext2_dx_entry *ent, __u32 crc,
                                char *buf, int level)
 {
        struct ext2_dx_countlimit       dx_countlimit;
@@ -160,8 +160,11 @@ static void htree_dump_int_node(ext2_filsys fs, ext2_ino_t ino,
        if (ext2fs_has_feature_metadata_csum(fs->super) &&
            remainder == sizeof(struct ext2_dx_tail)) {
                tail = (struct ext2_dx_tail *)(ent + limit);
-               fprintf(pager, "Checksum: 0x%08x\n",
+               fprintf(pager, "Checksum: 0x%08x",
                        ext2fs_le32_to_cpu(tail->dt_checksum));
+               if (tail->dt_checksum != crc)
+                       fprintf(pager, " --- EXPECTED: 0x%08x", crc);
+               fputc('\n', pager);
        }
 
        for (i=0; i < count; i++) {
@@ -199,6 +202,7 @@ static void htree_dump_int_block(ext2_filsys fs, ext2_ino_t ino,
        char            *cbuf;
        errcode_t       errcode;
        blk64_t         pblk;
+       __u32           crc;
 
        cbuf = malloc(fs->blocksize);
        if (!cbuf) {
@@ -216,13 +220,21 @@ static void htree_dump_int_block(ext2_filsys fs, ext2_ino_t ino,
        errcode = io_channel_read_blk64(current_fs->io, pblk, 1, buf);
        if (errcode) {
                com_err("htree_dump_int_block", errcode,
-                       "while  reading block %llu\n", blk);
+                       "while reading block %llu\n", blk);
                goto errout;
        }
 
+       errcode = ext2fs_dx_csum(current_fs, ino,
+                                (struct ext2_dir_entry *) buf, &crc, NULL);
+       if (errcode) {
+               com_err("htree_dump_int_block", errcode,
+                       "while calculating checksum for logical block %llu\n",
+                       (unsigned long long) blk);
+               crc = (unsigned int) -1;
+       }
        htree_dump_int_node(fs, ino, inode, rootnode,
                            (struct ext2_dx_entry *) (buf+8),
-                           cbuf, level);
+                           crc, cbuf, level);
 errout:
        free(cbuf);
 }
@@ -239,6 +251,7 @@ void do_htree_dump(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)),
        struct          ext2_dx_root_info  *rootnode;
        struct          ext2_dx_entry *ent;
        errcode_t       errcode;
+       __u32           crc;
 
        if (check_fs_open(argv[0]))
                return;
@@ -293,7 +306,14 @@ void do_htree_dump(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)),
        ent = (struct ext2_dx_entry *)
                ((char *)rootnode + rootnode->info_length);
 
-       htree_dump_int_node(current_fs, ino, &inode, rootnode, ent,
+       errcode = ext2fs_dx_csum(current_fs, ino,
+                                (struct ext2_dir_entry *) buf, &crc, NULL);
+       if (errcode) {
+               com_err("htree_dump_int_block", errcode,
+                       "while calculating checksum for htree root\n");
+               crc = (unsigned int) -1;
+       }
+       htree_dump_int_node(current_fs, ino, &inode, rootnode, ent, crc,
                            buf + current_fs->blocksize,
                            rootnode->indirect_levels);
 
index c16daa5b7a6850c353a571a278b4c704116294f5..fa72ec5720d19d19570d680339e2045ae7a009e2 100644 (file)
@@ -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, unsigned long block,
+                     unsigned long long *phys)
 {
 #ifdef USE_INODE_IO
        *phys = block;
@@ -115,13 +116,15 @@ int journal_bmap(journal_t *journal, blk64_t block, unsigned long long *phys)
        }
 
        retval = ext2fs_bmap2(inode->i_fs, inode->i_ino,
-                             &inode->i_ext2, NULL, 0, block, 0, &pblk);
+                             &inode->i_ext2, NULL, 0, (blk64_t) block,
+                             0, &pblk);
        *phys = pblk;
        return (int) retval;
 #endif
 }
 
-struct buffer_head *getblk(kdev_t kdev, blk64_t blocknr, int blocksize)
+struct buffer_head *getblk(kdev_t kdev, unsigned long long blocknr,
+                          int blocksize)
 {
        struct buffer_head *bh;
        int bufsize = sizeof(*bh) + kdev->k_fs->blocksize -
@@ -137,7 +140,7 @@ struct buffer_head *getblk(kdev_t kdev, blk64_t blocknr, int blocksize)
                bh_count++;
 #endif
        jfs_debug(4, "getblk for block %llu (%d bytes)(total %d)\n",
-                 (unsigned long long) blocknr, blocksize, bh_count);
+                 blocknr, blocksize, bh_count);
 
        bh->b_fs = kdev->k_fs;
        if (kdev->k_dev == K_DEV_FS)
@@ -162,14 +165,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 +186,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 +204,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 +223,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,7 +242,7 @@ 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);
 }
 
 
@@ -355,7 +358,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;
                }
@@ -389,7 +392,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
@@ -443,7 +446,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);
@@ -554,17 +557,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 ||
@@ -573,7 +576,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))
@@ -586,9 +589,9 @@ 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:
+       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
@@ -598,25 +601,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_feature_csum2(journal) && jfs_has_feature_csum3(journal))
+       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_feature_checksum(journal))
+       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_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));
 
@@ -740,7 +743,14 @@ static errcode_t recover_ext3_journal(ext2_filsys fs)
        journal_t *journal;
        errcode_t retval;
 
-       journal_init_revoke_caches();
+       retval = jbd2_journal_init_revoke_record_cache();
+       if (retval)
+               return retval;
+
+       retval = jbd2_journal_init_revoke_table_cache();
+       if (retval)
+               return retval;
+
        retval = ext2fs_get_journal(fs, &journal);
        if (retval)
                return retval;
@@ -749,11 +759,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;
 
@@ -763,8 +773,9 @@ 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_record_cache();
+       jbd2_journal_destroy_revoke_table_cache();
        ext2fs_journal_release(fs, journal, 1, 0);
        return retval;
 }
@@ -830,7 +841,14 @@ errcode_t ext2fs_open_journal(ext2_filsys fs, journal_t **j)
        journal_t *journal;
        errcode_t retval;
 
-       journal_init_revoke_caches();
+       retval = jbd2_journal_init_revoke_record_cache();
+       if (retval)
+               return retval;
+
+       retval = jbd2_journal_init_revoke_table_cache();
+       if (retval)
+               return retval;
+
        retval = ext2fs_get_journal(fs, &journal);
        if (retval)
                return retval;
@@ -839,7 +857,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;
 
@@ -852,8 +870,9 @@ 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_record_cache();
+       jbd2_journal_destroy_revoke_table_cache();
        ext2fs_journal_release(fs, journal, 1, 0);
        return retval;
 }
@@ -862,8 +881,9 @@ 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_record_cache();
+       jbd2_journal_destroy_revoke_table_cache();
        ext2fs_journal_release(fs, journal, 0, 0);
        *j = NULL;
 
@@ -875,7 +895,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);
@@ -888,29 +908,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);
@@ -923,14 +933,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_feature_csum3(j))
+       if (jbd2_has_feature_csum3(j))
                tag3->t_checksum = ext2fs_cpu_to_be32(csum32);
        else
                tag->t_checksum = ext2fs_cpu_to_be16(csum32);
index e286ae83bbfed625eb32a35cc454f391a6873fdd..168899542928cf5f33c5e057b9a91a72a05e6d02 100644 (file)
@@ -325,15 +325,15 @@ static int read_journal_block(const char *cmd, struct journal_source *source,
 static const char *type_to_name(int btype)
 {
        switch (btype) {
-       case JFS_DESCRIPTOR_BLOCK:
+       case JBD2_DESCRIPTOR_BLOCK:
                return "descriptor block";
-       case JFS_COMMIT_BLOCK:
+       case JBD2_COMMIT_BLOCK:
                return "commit block";
-       case JFS_SUPERBLOCK_V1:
+       case JBD2_SUPERBLOCK_V1:
                return "V1 superblock";
-       case JFS_SUPERBLOCK_V2:
+       case JBD2_SUPERBLOCK_V2:
                return "V2 superblock";
-       case JFS_REVOKE_BLOCK:
+       case JBD2_REVOKE_BLOCK:
                return "revoke table";
        }
        return "unrecognised type";
@@ -366,7 +366,7 @@ static void dump_journal(char *cmdname, FILE *out_file,
                ext2fs_swap_super(sb);
 #endif
 
-       if ((be32_to_cpu(jsb->s_header.h_magic) != JFS_MAGIC_NUMBER) &&
+       if ((be32_to_cpu(jsb->s_header.h_magic) != JBD2_MAGIC_NUMBER) &&
            (sb->s_magic == EXT2_SUPER_MAGIC) &&
            ext2fs_has_feature_journal_dev(sb)) {
                blocksize = EXT2_BLOCK_SIZE(sb);
@@ -395,7 +395,7 @@ static void dump_journal(char *cmdname, FILE *out_file,
        }
 
        jsb = (journal_superblock_t *) jsb_buffer;
-       if (be32_to_cpu(jsb->s_header.h_magic) != JFS_MAGIC_NUMBER) {
+       if (be32_to_cpu(jsb->s_header.h_magic) != JBD2_MAGIC_NUMBER) {
                fprintf(out_file,
                        "Journal superblock magic number invalid!\n");
                return;
@@ -428,7 +428,7 @@ static void dump_journal(char *cmdname, FILE *out_file,
                sequence = be32_to_cpu(header->h_sequence);
                blocktype = be32_to_cpu(header->h_blocktype);
 
-               if (magic != JFS_MAGIC_NUMBER) {
+               if (magic != JBD2_MAGIC_NUMBER) {
                        fprintf (out_file, "No magic number at block %u: "
                                 "end of journal.\n", blocknr);
                        return;
@@ -450,19 +450,19 @@ static void dump_journal(char *cmdname, FILE *out_file,
                }
 
                switch (blocktype) {
-               case JFS_DESCRIPTOR_BLOCK:
+               case JBD2_DESCRIPTOR_BLOCK:
                        dump_descriptor_block(out_file, source, buf, jsb,
                                              &blocknr, blocksize,
                                              transaction);
                        continue;
 
-               case JFS_COMMIT_BLOCK:
+               case JBD2_COMMIT_BLOCK:
                        transaction++;
                        blocknr++;
                        WRAP(jsb, blocknr);
                        continue;
 
-               case JFS_REVOKE_BLOCK:
+               case JBD2_REVOKE_BLOCK:
                        dump_revoke_block(out_file, buf, jsb,
                                          blocknr, blocksize,
                                          transaction);
@@ -482,15 +482,15 @@ static inline size_t journal_super_tag_bytes(journal_superblock_t *jsb)
 {
        size_t sz;
 
-       if (JSB_HAS_INCOMPAT_FEATURE(jsb, JFS_FEATURE_INCOMPAT_CSUM_V3))
+       if (JSB_HAS_INCOMPAT_FEATURE(jsb, JBD2_FEATURE_INCOMPAT_CSUM_V3))
                return sizeof(journal_block_tag3_t);
 
        sz = sizeof(journal_block_tag_t);
 
-       if (JSB_HAS_INCOMPAT_FEATURE(jsb, JFS_FEATURE_INCOMPAT_CSUM_V2))
+       if (JSB_HAS_INCOMPAT_FEATURE(jsb, JBD2_FEATURE_INCOMPAT_CSUM_V2))
                sz += sizeof(__u16);
 
-       if (JSB_HAS_INCOMPAT_FEATURE(jsb, JFS_FEATURE_INCOMPAT_64BIT))
+       if (JSB_HAS_INCOMPAT_FEATURE(jsb, JBD2_FEATURE_INCOMPAT_64BIT))
                return sz;
 
        return sz - sizeof(__u32);
@@ -514,9 +514,9 @@ static void dump_descriptor_block(FILE *out_file,
        offset = sizeof(journal_header_t);
        blocknr = *blockp;
 
-       if (JSB_HAS_INCOMPAT_FEATURE(jsb, JFS_FEATURE_INCOMPAT_CSUM_V3) ||
-           JSB_HAS_INCOMPAT_FEATURE(jsb, JFS_FEATURE_INCOMPAT_CSUM_V2))
-               csum_size = sizeof(struct journal_block_tail);
+       if (JSB_HAS_INCOMPAT_FEATURE(jsb, JBD2_FEATURE_INCOMPAT_CSUM_V3) ||
+           JSB_HAS_INCOMPAT_FEATURE(jsb, JBD2_FEATURE_INCOMPAT_CSUM_V2))
+               csum_size = sizeof(struct jbd2_journal_block_tail);
 
        if (dump_all)
                fprintf(out_file, "Dumping descriptor block, sequence %u, at "
@@ -540,7 +540,7 @@ static void dump_descriptor_block(FILE *out_file,
                tag_block = be32_to_cpu(tag->t_blocknr);
                tag_flags = be16_to_cpu(tag->t_flags);
 
-               if (!(tag_flags & JFS_FLAG_SAME_UUID))
+               if (!(tag_flags & JBD2_FLAG_SAME_UUID))
                        offset += 16;
 
                dump_metadata_block(out_file, source, jsb,
@@ -550,7 +550,7 @@ static void dump_descriptor_block(FILE *out_file,
                ++blocknr;
                WRAP(jsb, blocknr);
 
-       } while (!(tag_flags & JFS_FLAG_LAST_TAG));
+       } while (!(tag_flags & JBD2_FLAG_LAST_TAG));
 
        *blockp = blocknr;
 }
@@ -563,7 +563,7 @@ static void dump_revoke_block(FILE *out_file, char *buf,
                              tid_t transaction)
 {
        int                     offset, max;
-       journal_revoke_header_t *header;
+       jbd2_journal_revoke_header_t *header;
        unsigned long long      rblock;
        int                     tag_size = sizeof(__u32);
 
@@ -571,11 +571,11 @@ static void dump_revoke_block(FILE *out_file, char *buf,
                fprintf(out_file, "Dumping revoke block, sequence %u, at "
                        "block %u:\n", transaction, blocknr);
 
-       if (be32_to_cpu(jsb->s_feature_incompat) & JFS_FEATURE_INCOMPAT_64BIT)
+       if (be32_to_cpu(jsb->s_feature_incompat) & JBD2_FEATURE_INCOMPAT_64BIT)
                tag_size = sizeof(__u64);
 
-       header = (journal_revoke_header_t *) buf;
-       offset = sizeof(journal_revoke_header_t);
+       header = (jbd2_journal_revoke_header_t *) buf;
+       offset = sizeof(jbd2_journal_revoke_header_t);
        max = be32_to_cpu(header->r_count);
 
        while (offset < max) {
index f3443127a6e04a60ffe45b5213423f8669212cd2..5c802ac6dd867e97bd12a8c5144c2e3d1fe4fd56 100644 (file)
@@ -34,6 +34,7 @@ cc_defaults {
         "sigcatcher.c",
         "readahead.c",
         "extents.c",
+        "encrypted_files.c",
     ],
     cflags: [
         "-Wno-sign-compare",
index bc7195f3df4c146ee1c292230a34166d63ec0ce7..a56550ef39a318651deb943858835ad49bdde869 100644 (file)
@@ -63,7 +63,7 @@ OBJS= unix.o e2fsck.o super.o pass1.o pass1b.o pass2.o \
        dx_dirinfo.o ehandler.o problem.o message.o quota.o recovery.o \
        region.o revoke.o ea_refcount.o rehash.o \
        logfile.o sigcatcher.o $(MTRACE_OBJ) readahead.o \
-       extents.o
+       extents.o encrypted_files.o
 
 PROFILED_OBJS= profiled/unix.o profiled/e2fsck.o \
        profiled/super.o profiled/pass1.o profiled/pass1b.o \
@@ -74,7 +74,8 @@ PROFILED_OBJS= profiled/unix.o profiled/e2fsck.o \
        profiled/recovery.o profiled/region.o profiled/revoke.o \
        profiled/ea_refcount.o profiled/rehash.o \
        profiled/logfile.o profiled/sigcatcher.o \
-       profiled/readahead.o profiled/extents.o
+       profiled/readahead.o profiled/extents.o \
+       profiled/encrypted_files.o
 
 SRCS= $(srcdir)/e2fsck.c \
        $(srcdir)/super.c \
@@ -103,6 +104,7 @@ SRCS= $(srcdir)/e2fsck.c \
        $(srcdir)/logfile.c \
        $(srcdir)/quota.c \
        $(srcdir)/extents.c \
+       $(srcdir)/encrypted_files.c \
        $(MTRACE_SRC)
 
 all:: profiled $(PROGS) e2fsck $(MANPAGES) $(FMANPAGES)
@@ -572,3 +574,15 @@ extents.o: $(srcdir)/extents.c $(top_builddir)/lib/config.h \
  $(top_builddir)/lib/support/prof_err.h $(top_srcdir)/lib/support/quotaio.h \
  $(top_srcdir)/lib/support/dqblk_v2.h \
  $(top_srcdir)/lib/support/quotaio_tree.h $(srcdir)/problem.h
+encrypted_files.o: $(srcdir)/encrypted_files.c $(top_builddir)/lib/config.h \
+ $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.h \
+ $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \
+ $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \
+ $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/hashmap.h \
+ $(top_srcdir)/lib/ext2fs/bitops.h $(top_srcdir)/lib/support/profile.h \
+ $(top_builddir)/lib/support/prof_err.h $(top_srcdir)/lib/support/quotaio.h \
+ $(top_srcdir)/lib/support/dqblk_v2.h \
+ $(top_srcdir)/lib/support/quotaio_tree.h $(srcdir)/problem.h \
+ $(top_srcdir)/lib/ext2fs/rbtree.h
index 929bd78d81cb149df5a1d0c843ba1fa5c7649a8a..d8be566fbe97307bab36116bc95f3f8a6f5256be 100644 (file)
@@ -138,6 +138,7 @@ errcode_t e2fsck_reset_context(e2fsck_t ctx)
                ext2fs_u32_list_free(ctx->dirs_to_hash);
                ctx->dirs_to_hash = 0;
        }
+       destroy_encrypted_file_info(ctx);
 
        /*
         * Clear the array of invalid meta-data flags
@@ -154,10 +155,6 @@ errcode_t e2fsck_reset_context(e2fsck_t ctx)
                ext2fs_free_mem(&ctx->invalid_inode_table_flag);
                ctx->invalid_inode_table_flag = 0;
        }
-       if (ctx->encrypted_dirs) {
-               ext2fs_u32_list_free(ctx->encrypted_dirs);
-               ctx->encrypted_dirs = 0;
-       }
        if (ctx->inode_count) {
                ext2fs_free_icount(ctx->inode_count);
                ctx->inode_count = 0;
index 2d359b384c1887acc7ff8e909e5ba11f44809ba3..954bc9822ed26e699908da1dcbdef29bce8bb8d3 100644 (file)
@@ -135,6 +135,8 @@ struct dx_dirblock_info {
 #define DX_FLAG_FIRST          4
 #define DX_FLAG_LAST           8
 
+struct encrypted_file_info;
+
 #define RESOURCE_TRACK
 
 #ifdef RESOURCE_TRACK
@@ -174,6 +176,7 @@ struct resource_track {
 #define E2F_OPT_NOOPT_EXTENTS  0x10000 /* don't optimize extents */
 #define E2F_OPT_ICOUNT_FULLMAP 0x20000 /* use an array for inode counts */
 #define E2F_OPT_UNSHARE_BLOCKS  0x40000
+#define E2F_OPT_CLEAR_UNINIT   0x80000 /* Hack to clear the uninit bit */
 
 /*
  * E2fsck flags
@@ -327,6 +330,11 @@ struct e2fsck_struct {
         */
        ext2_u32_list   dirs_to_hash;
 
+       /*
+        * Encrypted file information
+        */
+       struct encrypted_file_info *encrypted_files;
+
        /*
         * Tuning parameters
         */
@@ -389,7 +397,6 @@ struct e2fsck_struct {
        int ext_attr_ver;
        profile_t       profile;
        int blocks_per_page;
-       ext2_u32_list encrypted_dirs;
 
        /* Reserve blocks for root and l+f re-creation */
        blk64_t root_repair_block, lnf_repair_block;
@@ -504,8 +511,20 @@ extern ea_key_t ea_refcount_intr_next(ext2_refcount_t refcount,
 extern const char *ehandler_operation(const char *op);
 extern void ehandler_init(io_channel channel);
 
-/* extents.c */
+/* encrypted_files.c */
+
 struct problem_context;
+int add_encrypted_file(e2fsck_t ctx, struct problem_context *pctx);
+
+#define NO_ENCRYPTION_POLICY           ((__u32)-1)
+#define CORRUPT_ENCRYPTION_POLICY      ((__u32)-2)
+#define UNRECOGNIZED_ENCRYPTION_POLICY ((__u32)-3)
+__u32 find_encryption_policy(e2fsck_t ctx, ext2_ino_t ino);
+
+void destroy_encryption_policy_map(e2fsck_t ctx);
+void destroy_encrypted_file_info(e2fsck_t ctx);
+
+/* extents.c */
 errcode_t e2fsck_rebuild_extents_later(e2fsck_t ctx, ext2_ino_t ino);
 int e2fsck_ino_will_be_rebuilt(e2fsck_t ctx, ext2_ino_t ino);
 void e2fsck_pass1e(e2fsck_t ctx);
diff --git a/e2fsck/encrypted_files.c b/e2fsck/encrypted_files.c
new file mode 100644 (file)
index 0000000..16be2d6
--- /dev/null
@@ -0,0 +1,458 @@
+/*
+ * encrypted_files.c --- save information about encrypted files
+ *
+ * Copyright 2019 Google LLC
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+/*
+ * e2fsck pass 1 (inode table scan) creates a map from inode number to
+ * encryption policy for all encrypted inodes.  But it's optimized so that the
+ * full xattrs aren't saved but rather only 32-bit "policy IDs", since usually
+ * many inodes share the same encryption policy.  This requires also maintaining
+ * a second map, from policy to policy ID.  See add_encrypted_file().
+ *
+ * We also use run-length encoding to save memory when many adjacent inodes
+ * share the same encryption policy, which is often the case too.
+ *
+ * e2fsck pass 2 (directory structure check) uses the inode => policy ID map to
+ * verify that all regular files, directories, and symlinks in encrypted
+ * directories use the directory's encryption policy.
+ */
+
+#include "config.h"
+
+#include "e2fsck.h"
+#include "problem.h"
+#include "ext2fs/rbtree.h"
+
+#define FSCRYPT_KEY_DESCRIPTOR_SIZE    8
+#define FSCRYPT_KEY_IDENTIFIER_SIZE    16
+#define FS_KEY_DERIVATION_NONCE_SIZE   16
+
+struct fscrypt_context_v1 {
+       __u8 version;
+       __u8 contents_encryption_mode;
+       __u8 filenames_encryption_mode;
+       __u8 flags;
+       __u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE];
+       __u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE];
+};
+
+struct fscrypt_context_v2 {
+       __u8 version;
+       __u8 contents_encryption_mode;
+       __u8 filenames_encryption_mode;
+       __u8 flags;
+       __u8 __reserved[4];
+       __u8 master_key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE];
+       __u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE];
+};
+
+/* On-disk format of encryption xattr */
+union fscrypt_context {
+       __u8 version;
+       struct fscrypt_context_v1 v1;
+       struct fscrypt_context_v2 v2;
+};
+
+struct fscrypt_policy_v1 {
+       __u8 version;
+       __u8 contents_encryption_mode;
+       __u8 filenames_encryption_mode;
+       __u8 flags;
+       __u8 master_key_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE];
+};
+
+struct fscrypt_policy_v2 {
+       __u8 version;
+       __u8 contents_encryption_mode;
+       __u8 filenames_encryption_mode;
+       __u8 flags;
+       __u8 __reserved[4];
+       __u8 master_key_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE];
+};
+
+/* The encryption "policy" is the fscrypt_context excluding the nonce. */
+union fscrypt_policy {
+       __u8 version;
+       struct fscrypt_policy_v1 v1;
+       struct fscrypt_policy_v2 v2;
+};
+
+/* A range of inodes which share the same encryption policy */
+struct encrypted_file_range {
+       ext2_ino_t              first_ino;
+       ext2_ino_t              last_ino;
+       __u32                   policy_id;
+};
+
+/* Information about the encrypted files which have been seen so far */
+struct encrypted_file_info {
+       /*
+        * Map from inode number to encryption policy ID, implemented as a
+        * sorted array of inode ranges, each of which shares the same policy.
+        * Inodes are added in order of increasing inode number.
+        *
+        * Freed after pass 2.
+        */
+       struct encrypted_file_range     *file_ranges;
+       size_t                          file_ranges_count;
+       size_t                          file_ranges_capacity;
+
+       /*
+        * Map from encryption policy to encryption policy ID, for the unique
+        * encryption policies that have been seen so far.  next_policy_id is
+        * the next available ID, starting at 0.
+        *
+        * Freed after pass 1.
+        */
+       struct rb_root          policies;
+       __u32                   next_policy_id;
+};
+
+/* Entry in encrypted_file_info::policies */
+struct policy_map_entry {
+       union fscrypt_policy    policy;
+       __u32                   policy_id;
+       struct rb_node          node;
+};
+
+static int cmp_fscrypt_policies(e2fsck_t ctx, const union fscrypt_policy *a,
+                               const union fscrypt_policy *b)
+{
+       if (a->version != b->version)
+               return (int)a->version - (int)b->version;
+
+       switch (a->version) {
+       case 1:
+               return memcmp(a, b, sizeof(a->v1));
+       case 2:
+               return memcmp(a, b, sizeof(a->v2));
+       }
+       fatal_error(ctx, "Unhandled encryption policy version");
+       return 0;
+}
+
+/* Read an inode's encryption xattr. */
+static errcode_t read_encryption_xattr(e2fsck_t ctx, ext2_ino_t ino,
+                                      void **value, size_t *value_len)
+{
+       struct ext2_xattr_handle *h;
+       errcode_t retval;
+
+       retval = ext2fs_xattrs_open(ctx->fs, ino, &h);
+       if (retval)
+               return retval;
+
+       retval = ext2fs_xattrs_read(h);
+       if (retval == 0)
+               retval = ext2fs_xattr_get(h, "c", value, value_len);
+
+       ext2fs_xattrs_close(&h);
+       return retval;
+}
+
+/*
+ * Convert an fscrypt_context to an fscrypt_policy.  Returns 0,
+ * CORRUPT_ENCRYPTION_POLICY, or UNRECOGNIZED_ENCRYPTION_POLICY.
+ */
+static __u32 fscrypt_context_to_policy(const void *xattr, size_t xattr_size,
+                                      union fscrypt_policy *policy_u)
+{
+       const union fscrypt_context *ctx_u = xattr;
+
+       if (xattr_size < 1)
+               return CORRUPT_ENCRYPTION_POLICY;
+       switch (ctx_u->version) {
+       case 0:
+               return CORRUPT_ENCRYPTION_POLICY;
+       case 1: {
+               struct fscrypt_policy_v1 *policy = &policy_u->v1;
+               const struct fscrypt_context_v1 *ctx = &ctx_u->v1;
+
+               if (xattr_size != sizeof(*ctx))
+                       return CORRUPT_ENCRYPTION_POLICY;
+               policy->version = ctx->version;
+               policy->contents_encryption_mode =
+                       ctx->contents_encryption_mode;
+               policy->filenames_encryption_mode =
+                       ctx->filenames_encryption_mode;
+               policy->flags = ctx->flags;
+               memcpy(policy->master_key_descriptor,
+                      ctx->master_key_descriptor,
+                      sizeof(policy->master_key_descriptor));
+               return 0;
+       }
+       case 2: {
+               struct fscrypt_policy_v2 *policy = &policy_u->v2;
+               const struct fscrypt_context_v2 *ctx = &ctx_u->v2;
+
+               if (xattr_size != sizeof(*ctx))
+                       return CORRUPT_ENCRYPTION_POLICY;
+               policy->version = ctx->version;
+               policy->contents_encryption_mode =
+                       ctx->contents_encryption_mode;
+               policy->filenames_encryption_mode =
+                       ctx->filenames_encryption_mode;
+               policy->flags = ctx->flags;
+               memcpy(policy->__reserved, ctx->__reserved,
+                      sizeof(policy->__reserved));
+               memcpy(policy->master_key_identifier,
+                      ctx->master_key_identifier,
+                      sizeof(policy->master_key_identifier));
+               return 0;
+       }
+       }
+       return UNRECOGNIZED_ENCRYPTION_POLICY;
+}
+
+/*
+ * Read an inode's encryption xattr and get/allocate its encryption policy ID,
+ * or alternatively use one of the special IDs NO_ENCRYPTION_POLICY,
+ * CORRUPT_ENCRYPTION_POLICY, or UNRECOGNIZED_ENCRYPTION_POLICY.
+ *
+ * Returns nonzero only if out of memory.
+ */
+static errcode_t get_encryption_policy_id(e2fsck_t ctx, ext2_ino_t ino,
+                                         __u32 *policy_id_ret)
+{
+       struct encrypted_file_info *info = ctx->encrypted_files;
+       struct rb_node **new = &info->policies.rb_node;
+       struct rb_node *parent = NULL;
+       void *xattr;
+       size_t xattr_size;
+       union fscrypt_policy policy;
+       __u32 policy_id;
+       struct policy_map_entry *entry;
+       errcode_t retval;
+
+       retval = read_encryption_xattr(ctx, ino, &xattr, &xattr_size);
+       if (retval == EXT2_ET_NO_MEMORY)
+               return retval;
+       if (retval) {
+               *policy_id_ret = NO_ENCRYPTION_POLICY;
+               return 0;
+       }
+
+       /* Translate the xattr to an fscrypt_policy, if possible. */
+       policy_id = fscrypt_context_to_policy(xattr, xattr_size, &policy);
+       ext2fs_free_mem(&xattr);
+       if (policy_id != 0)
+               goto out;
+
+       /* Check if the policy was already seen. */
+       while (*new) {
+               int res;
+
+               parent = *new;
+               entry = ext2fs_rb_entry(parent, struct policy_map_entry, node);
+               res = cmp_fscrypt_policies(ctx, &policy, &entry->policy);
+               if (res < 0) {
+                       new = &parent->rb_left;
+               } else if (res > 0) {
+                       new = &parent->rb_right;
+               } else {
+                       /* Policy already seen.  Use existing ID. */
+                       policy_id = entry->policy_id;
+                       goto out;
+               }
+       }
+
+       /* First time seeing this policy.  Allocate a new policy ID. */
+       retval = ext2fs_get_mem(sizeof(*entry), &entry);
+       if (retval)
+               goto out;
+       policy_id = info->next_policy_id++;
+       entry->policy_id = policy_id;
+       entry->policy = policy;
+       ext2fs_rb_link_node(&entry->node, parent, new);
+       ext2fs_rb_insert_color(&entry->node, &info->policies);
+out:
+       *policy_id_ret = policy_id;
+       return retval;
+}
+
+static int handle_nomem(e2fsck_t ctx, struct problem_context *pctx,
+                       size_t size_needed)
+{
+       pctx->num = size_needed;
+       fix_problem(ctx, PR_1_ALLOCATE_ENCRYPTED_INODE_LIST, pctx);
+       /* Should never get here */
+       ctx->flags |= E2F_FLAG_ABORT;
+       return 0;
+}
+
+static int append_ino_and_policy_id(e2fsck_t ctx, struct problem_context *pctx,
+                                   ext2_ino_t ino, __u32 policy_id)
+{
+       struct encrypted_file_info *info = ctx->encrypted_files;
+       struct encrypted_file_range *range;
+
+       /* See if we can just extend the last range. */
+       if (info->file_ranges_count > 0) {
+               range = &info->file_ranges[info->file_ranges_count - 1];
+
+               if (ino <= range->last_ino) {
+                       /* Should never get here */
+                       fatal_error(ctx,
+                                   "Encrypted inodes processed out of order");
+               }
+
+               if (ino == range->last_ino + 1 &&
+                   policy_id == range->policy_id) {
+                       range->last_ino++;
+                       return 0;
+               }
+       }
+       /* Nope, a new range is needed. */
+
+       if (info->file_ranges_count == info->file_ranges_capacity) {
+               /* Double the capacity by default. */
+               size_t new_capacity = info->file_ranges_capacity * 2;
+
+               /* ... but go from 0 to 128 right away. */
+               if (new_capacity < 128)
+                       new_capacity = 128;
+
+               /* We won't need more than the filesystem's inode count. */
+               if (new_capacity > ctx->fs->super->s_inodes_count)
+                       new_capacity = ctx->fs->super->s_inodes_count;
+
+               /* To be safe, ensure the capacity really increases. */
+               if (new_capacity < info->file_ranges_capacity + 1)
+                       new_capacity = info->file_ranges_capacity + 1;
+
+               if (ext2fs_resize_mem(info->file_ranges_capacity *
+                                       sizeof(*range),
+                                     new_capacity * sizeof(*range),
+                                     &info->file_ranges) != 0)
+                       return handle_nomem(ctx, pctx,
+                                           new_capacity * sizeof(*range));
+
+               info->file_ranges_capacity = new_capacity;
+       }
+       range = &info->file_ranges[info->file_ranges_count++];
+       range->first_ino = ino;
+       range->last_ino = ino;
+       range->policy_id = policy_id;
+       return 0;
+}
+
+/*
+ * Handle an inode that has EXT4_ENCRYPT_FL set during pass 1.  Normally this
+ * just finds the unique ID that identifies the inode's encryption policy
+ * (allocating a new ID if needed), and adds the inode number and its policy ID
+ * to the encrypted_file_info so that it's available in pass 2.
+ *
+ * But this also handles:
+ * - If the inode doesn't have an encryption xattr at all, offer to clear the
+ *   encrypt flag.
+ * - If the encryption xattr is clearly corrupt, tell the caller that the whole
+ *   inode should be cleared.
+ * - To be future-proof: if the encryption xattr has an unrecognized version
+ *   number, it *might* be valid, so we don't consider it invalid.  But we can't
+ *   do much with it, so give all such policies the same ID,
+ *   UNRECOGNIZED_ENCRYPTION_POLICY.
+ *
+ * Returns -1 if the inode should be cleared, otherwise 0.
+ */
+int add_encrypted_file(e2fsck_t ctx, struct problem_context *pctx)
+{
+       struct encrypted_file_info *info = ctx->encrypted_files;
+       ext2_ino_t ino = pctx->ino;
+       __u32 policy_id;
+
+       /* Allocate the encrypted_file_info if needed. */
+       if (info == NULL) {
+               if (ext2fs_get_memzero(sizeof(*info), &info) != 0)
+                       return handle_nomem(ctx, pctx, sizeof(*info));
+               ctx->encrypted_files = info;
+       }
+
+       /* Get a unique ID for this inode's encryption policy. */
+       if (get_encryption_policy_id(ctx, ino, &policy_id) != 0)
+               return handle_nomem(ctx, pctx, 0 /* unknown size */);
+       if (policy_id == NO_ENCRYPTION_POLICY) {
+               if (fix_problem(ctx, PR_1_MISSING_ENCRYPTION_XATTR, pctx)) {
+                       pctx->inode->i_flags &= ~EXT4_ENCRYPT_FL;
+                       e2fsck_write_inode(ctx, ino, pctx->inode, "pass1");
+               }
+               return 0;
+       } else if (policy_id == CORRUPT_ENCRYPTION_POLICY) {
+               if (fix_problem(ctx, PR_1_CORRUPT_ENCRYPTION_XATTR, pctx))
+                       return -1;
+               return 0;
+       }
+
+       /* Store this ino => policy_id mapping in the encrypted_file_info. */
+       return append_ino_and_policy_id(ctx, pctx, ino, policy_id);
+}
+
+/*
+ * Find the ID of an inode's encryption policy, using the information saved
+ * earlier.
+ *
+ * If the inode is encrypted, returns the policy ID or
+ * UNRECOGNIZED_ENCRYPTION_POLICY.  Else, returns NO_ENCRYPTION_POLICY.
+ */
+__u32 find_encryption_policy(e2fsck_t ctx, ext2_ino_t ino)
+{
+       const struct encrypted_file_info *info = ctx->encrypted_files;
+       size_t l, r;
+
+       if (info == NULL)
+               return NO_ENCRYPTION_POLICY;
+       l = 0;
+       r = info->file_ranges_count;
+       while (l < r) {
+               size_t m = l + (r - l) / 2;
+               const struct encrypted_file_range *range =
+                       &info->file_ranges[m];
+
+               if (ino < range->first_ino)
+                       r = m;
+               else if (ino > range->last_ino)
+                       l = m + 1;
+               else
+                       return range->policy_id;
+       }
+       return NO_ENCRYPTION_POLICY;
+}
+
+/* Destroy ctx->encrypted_files->policies */
+void destroy_encryption_policy_map(e2fsck_t ctx)
+{
+       struct encrypted_file_info *info = ctx->encrypted_files;
+
+       if (info) {
+               struct rb_root *policies = &info->policies;
+
+               while (!ext2fs_rb_empty_root(policies)) {
+                       struct policy_map_entry *entry;
+
+                       entry = ext2fs_rb_entry(policies->rb_node,
+                                               struct policy_map_entry, node);
+                       ext2fs_rb_erase(&entry->node, policies);
+                       ext2fs_free_mem(&entry);
+               }
+               info->next_policy_id = 0;
+       }
+}
+
+/* Destroy ctx->encrypted_files */
+void destroy_encrypted_file_info(e2fsck_t ctx)
+{
+       struct encrypted_file_info *info = ctx->encrypted_files;
+
+       if (info) {
+               destroy_encryption_policy_map(ctx);
+               ext2fs_free_mem(&info->file_ranges);
+               ext2fs_free_mem(&info);
+               ctx->encrypted_files = NULL;
+       }
+}
index a1c6951cb2c5b1a8872caa8a389d0af6530d9512..a97fcc18a704b5ec302e0f62153fe1ee4d19511a 100644 (file)
@@ -81,9 +81,9 @@ struct kdev_s {
 #define buffer_req(bh) 1
 #define do_readahead(journal, start) do {} while (0)
 
-typedef struct {
+typedef struct kmem_cache {
        int     object_length;
-} lkmem_cache_t;
+} kmem_cache_t;
 
 #define kmem_cache_alloc(cache, flags) malloc((cache)->object_length)
 #define kmem_cache_free(cache, obj) free(obj)
@@ -92,6 +92,13 @@ typedef struct {
 #define kmalloc(len, flags) malloc(len)
 #define kfree(p) free(p)
 
+static inline void *kmalloc_array(unsigned n, unsigned size, int flags)
+{
+       if (n && (~0U)/n < size)
+               return NULL;
+       return malloc(n * size);
+}
+
 #define cond_resched() do { } while (0)
 
 #define __init
@@ -106,8 +113,8 @@ typedef struct {
  * functions.
  */
 #ifdef NO_INLINE_FUNCS
-extern lkmem_cache_t *do_cache_create(int len);
-extern void do_cache_destroy(lkmem_cache_t *cache);
+extern kmem_cache_t *do_cache_create(int len);
+extern void do_cache_destroy(kmem_cache_t *cache);
 extern size_t journal_tag_bytes(journal_t *journal);
 extern __u32 __hash_32(__u32 val);
 extern __u32 hash_32(__u32 val, unsigned int bits);
@@ -133,9 +140,9 @@ extern __u32 hash_64(__u64 val, unsigned int bits);
 #endif /* __STDC_VERSION__ >= 199901L */
 #endif /* E2FSCK_INCLUDE_INLINE_FUNCS */
 
-_INLINE_ lkmem_cache_t *do_cache_create(int len)
+_INLINE_ kmem_cache_t *do_cache_create(int len)
 {
-       lkmem_cache_t *new_cache;
+       kmem_cache_t *new_cache;
 
        new_cache = malloc(sizeof(*new_cache));
        if (new_cache)
@@ -143,7 +150,7 @@ _INLINE_ lkmem_cache_t *do_cache_create(int len)
        return new_cache;
 }
 
-_INLINE_ void do_cache_destroy(lkmem_cache_t *cache)
+_INLINE_ void do_cache_destroy(kmem_cache_t *cache)
 {
        free(cache);
 }
@@ -180,10 +187,12 @@ _INLINE_ __u32 hash_64(__u64 val, unsigned int bits)
 /*
  * Kernel compatibility functions are defined in journal.c
  */
-int journal_bmap(journal_t *journal, blk64_t block, unsigned long long *phys);
-struct buffer_head *getblk(kdev_t ctx, blk64_t blocknr, int blocksize);
+int jbd2_journal_bmap(journal_t *journal, unsigned long block,
+                     unsigned long long *phys);
+struct buffer_head *getblk(kdev_t ctx, unsigned long long blocknr,
+                          int blocksize);
 int sync_blockdev(kdev_t kdev);
-void ll_rw_block(int rw, int dummy, struct buffer_head *bh[]);
+void ll_rw_block(int rw, int op_flags, int nr, struct buffer_head *bh[]);
 void mark_buffer_dirty(struct buffer_head *bh);
 void mark_buffer_uptodate(struct buffer_head *bh, int val);
 void brelse(struct buffer_head *bh);
@@ -202,7 +211,7 @@ void wait_on_buffer(struct buffer_head *bh);
 #define J_ASSERT(x)    assert(x)
 
 #define JSB_HAS_INCOMPAT_FEATURE(jsb, mask)                            \
-       ((jsb)->s_header.h_blocktype == ext2fs_cpu_to_be32(JFS_SUPERBLOCK_V2) &&        \
+       ((jsb)->s_header.h_blocktype == ext2fs_cpu_to_be32(JBD2_SUPERBLOCK_V2) &&       \
         ((jsb)->s_feature_incompat & ext2fs_cpu_to_be32((mask))))
 #else  /* !DEBUGFS */
 
@@ -225,18 +234,37 @@ extern e2fsck_t e2fsck_global_ctx;  /* Try your very best not to use this! */
 #define EFSCORRUPTED   EXT2_ET_FILESYSTEM_CORRUPTED
 #endif
 
+static inline void jbd2_descriptor_block_csum_set(journal_t *j,
+                                                 struct buffer_head *bh)
+{
+       struct jbd2_journal_block_tail *tail;
+       __u32 csum;
+
+       if (!jbd2_journal_has_csum_v2or3(j))
+               return;
+
+       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 = cpu_to_be32(csum);
+}
+
 /* recovery.c */
-extern int     journal_recover    (journal_t *journal);
-extern int     journal_skip_recovery (journal_t *);
+extern int     jbd2_journal_recover    (journal_t *journal);
+extern int     jbd2_journal_skip_recovery (journal_t *);
 
 /* revoke.c */
-extern int     journal_init_revoke(journal_t *, int);
-extern void    journal_destroy_revoke(journal_t *);
-extern void    journal_destroy_revoke_caches(void);
-extern int     journal_init_revoke_caches(void);
-
-extern int     journal_set_revoke(journal_t *, unsigned long long, tid_t);
-extern int     journal_test_revoke(journal_t *, unsigned long long, tid_t);
-extern void    journal_clear_revoke(journal_t *);
+extern int     jbd2_journal_init_revoke(journal_t *, int);
+extern void    jbd2_journal_destroy_revoke(journal_t *);
+extern void    jbd2_journal_destroy_revoke_record_cache(void);
+extern void    jbd2_journal_destroy_revoke_table_cache(void);
+extern int     jbd2_journal_init_revoke_record_cache(void);
+extern int     jbd2_journal_init_revoke_table_cache(void);
+
+
+extern int     jbd2_journal_set_revoke(journal_t *, unsigned long long, tid_t);
+extern int     jbd2_journal_test_revoke(journal_t *, unsigned long long, tid_t);
+extern void    jbd2_journal_clear_revoke(journal_t *);
 
 #endif /* _JFS_USER_H */
index e83f3a91c0228914515540df641be3aaba934279..7d9f1b40dcee1f93cfa624b918352a34c8882730 100644 (file)
@@ -44,7 +44,7 @@ static int bh_count = 0;
 static int e2fsck_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;
@@ -68,7 +68,7 @@ static int e2fsck_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);
@@ -82,7 +82,7 @@ static errcode_t e2fsck_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 = e2fsck_journal_sb_csum(jsb);
@@ -94,7 +94,8 @@ static errcode_t e2fsck_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, unsigned long block,
+                     unsigned long long *phys)
 {
 #ifdef USE_INODE_IO
        *phys = block;
@@ -110,13 +111,15 @@ int journal_bmap(journal_t *journal, blk64_t block, unsigned long long *phys)
        }
 
        retval= ext2fs_bmap2(inode->i_ctx->fs, inode->i_ino,
-                            &inode->i_ext2, NULL, 0, block, 0, &pblk);
+                            &inode->i_ext2, NULL, 0, (blk64_t) block,
+                            0, &pblk);
        *phys = pblk;
        return -1 * ((int) retval);
 #endif
 }
 
-struct buffer_head *getblk(kdev_t kdev, blk64_t blocknr, int blocksize)
+struct buffer_head *getblk(kdev_t kdev, unsigned long long blocknr,
+                          int blocksize)
 {
        struct buffer_head *bh;
        int bufsize = sizeof(*bh) + kdev->k_ctx->fs->blocksize -
@@ -131,7 +134,7 @@ struct buffer_head *getblk(kdev_t kdev, blk64_t blocknr, int blocksize)
                bh_count++;
 #endif
        jfs_debug(4, "getblk for block %llu (%d bytes)(total %d)\n",
-                 (unsigned long long) blocknr, blocksize, bh_count);
+                 blocknr, blocksize, bh_count);
 
        bh->b_ctx = kdev->k_ctx;
        if (kdev->k_dev == K_DEV_FS)
@@ -156,14 +159,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,
@@ -177,7 +180,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);
@@ -195,7 +198,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);
                }
        }
@@ -214,7 +217,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);
@@ -233,7 +236,7 @@ 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);
 }
 
 
@@ -356,7 +359,7 @@ static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_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;
                }
@@ -390,7 +393,7 @@ static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
 #else
                journal->j_inode = j_inode;
                ctx->journal_io = ctx->fs->io;
-               if ((ret = journal_bmap(journal, 0, &start)) != 0) {
+               if ((ret = jbd2_journal_bmap(journal, 0, &start)) != 0) {
                        retval = (errcode_t) (-1 * ret);
                        goto errout;
                }
@@ -452,7 +455,7 @@ static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
                        retval = EXT2_ET_NO_MEMORY;
                        goto errout;
                }
-               ll_rw_block(READ, 1, &bh);
+               ll_rw_block(REQ_OP_READ, 0, 1, &bh);
                if ((retval = bh->b_err) != 0) {
                        brelse(bh);
                        goto errout;
@@ -591,7 +594,7 @@ static errcode_t e2fsck_journal_load(journal_t *journal)
 
        clear_problem_context(&pctx);
 
-       ll_rw_block(READ, 1, &jbh);
+       ll_rw_block(REQ_OP_READ, 0, 1, &jbh);
        if (jbh->b_err) {
                com_err(ctx->device_name, jbh->b_err, "%s",
                        _("reading journal superblock\n"));
@@ -599,12 +602,12 @@ static errcode_t e2fsck_journal_load(journal_t *journal)
        }
 
        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 e2fsck_journal_fix_bad_inode(ctx, &pctx);
 
        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 ||
@@ -613,7 +616,7 @@ static errcode_t e2fsck_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(ctx->fs->super->s_journal_uuid))
@@ -628,9 +631,9 @@ static errcode_t e2fsck_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:
+       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
@@ -640,25 +643,25 @@ static errcode_t e2fsck_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_feature_csum2(journal) && jfs_has_feature_csum3(journal))
+       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_feature_checksum(journal))
+       if (jbd2_journal_has_csum_v2or3(journal) &&
+           jbd2_has_feature_checksum(journal))
                return EXT2_ET_CORRUPT_JOURNAL_SB;
 
        if (!e2fsck_journal_verify_csum_type(journal, jsb) ||
            !e2fsck_journal_sb_csum_verify(journal, jsb))
                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));
 
@@ -705,10 +708,10 @@ static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
         * Anything unrecognisable we overwrite with a new V2
         * signature. */
 
-       if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
-           jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
-               jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
-               jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
+       if (jsb->s_header.h_magic != htonl(JBD2_MAGIC_NUMBER) ||
+           jsb->s_header.h_blocktype != htonl(JBD2_SUPERBLOCK_V1)) {
+               jsb->s_header.h_magic = htonl(JBD2_MAGIC_NUMBER);
+               jsb->s_header.h_blocktype = htonl(JBD2_SUPERBLOCK_V2);
        }
 
        /* Zero out everything else beyond the superblock header */
@@ -732,7 +735,7 @@ static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
        e2fsck_journal_sb_csum_set(journal, jsb);
 
        mark_buffer_dirty(journal->j_sb_buffer);
-       ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
+       ll_rw_block(REQ_OP_WRITE, 0, 1, &journal->j_sb_buffer);
 }
 
 static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
@@ -928,7 +931,14 @@ static errcode_t recover_ext3_journal(e2fsck_t ctx)
 
        clear_problem_context(&pctx);
 
-       journal_init_revoke_caches();
+       retval = jbd2_journal_init_revoke_record_cache();
+       if (retval)
+               return retval;
+
+       retval = jbd2_journal_init_revoke_table_cache();
+       if (retval)
+               return retval;
+
        retval = e2fsck_get_journal(ctx, &journal);
        if (retval)
                return retval;
@@ -937,11 +947,11 @@ static errcode_t recover_ext3_journal(e2fsck_t ctx)
        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;
 
@@ -955,8 +965,9 @@ static errcode_t recover_ext3_journal(e2fsck_t ctx)
        journal->j_tail_sequence = journal->j_transaction_sequence;
 
 errout:
-       journal_destroy_revoke(journal);
-       journal_destroy_revoke_caches();
+       jbd2_journal_destroy_revoke(journal);
+       jbd2_journal_destroy_revoke_record_cache();
+       jbd2_journal_destroy_revoke_table_cache();
        e2fsck_journal_release(ctx, journal, 1, 0);
        return retval;
 }
index c9e8bf828f288c0a824170d45c85c7bf919784b1..a57c1c0670e61a94a0414367674092d56b9017e1 100644 (file)
@@ -27,6 +27,7 @@
  *     - A bitmap of which blocks are in use by two inodes     (block_dup_map)
  *     - The data blocks of the directory inodes.      (dir_map)
  *     - Ref counts for ea_inodes.                     (ea_inode_refs)
+ *     - The encryption policy ID of each encrypted inode. (encrypted_files)
  *
  * Pass 1 is designed to stash away enough information so that the
  * other passes should not need to read in the inode information
@@ -78,7 +79,6 @@ static void mark_table_blocks(e2fsck_t ctx);
 static void alloc_bb_map(e2fsck_t ctx);
 static void alloc_imagic_map(e2fsck_t ctx);
 static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
-static void add_encrypted_dir(e2fsck_t ctx, ino_t ino);
 static void handle_fs_bad_blocks(e2fsck_t ctx);
 static void process_inodes(e2fsck_t ctx, char *block_buf);
 static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b);
@@ -1884,12 +1884,14 @@ void e2fsck_pass1(e2fsck_t ctx)
                        failed_csum = 0;
                }
 
+               if ((inode->i_flags & EXT4_ENCRYPT_FL) &&
+                   add_encrypted_file(ctx, &pctx) < 0)
+                       goto clear_inode;
+
                if (LINUX_S_ISDIR(inode->i_mode)) {
                        ext2fs_mark_inode_bitmap2(ctx->inode_dir_map, ino);
                        e2fsck_add_dir_info(ctx, ino, 0);
                        ctx->fs_directory_count++;
-                       if (inode->i_flags & EXT4_ENCRYPT_FL)
-                               add_encrypted_dir(ctx, ino);
                } else if (LINUX_S_ISREG (inode->i_mode)) {
                        ext2fs_mark_inode_bitmap2(ctx->inode_reg_map, ino);
                        ctx->fs_regular_count++;
@@ -2018,6 +2020,9 @@ void e2fsck_pass1(e2fsck_t ctx)
                ctx->block_ea_map = 0;
        }
 
+       /* We don't need the encryption policy => ID map any more */
+       destroy_encryption_policy_map(ctx);
+
        if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
                clear_problem_context(&pctx);
                pctx.errcode = ext2fs_create_resize_inode(fs);
@@ -2202,24 +2207,6 @@ static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
        ext2fs_mark_inode_bitmap2(ctx->inode_bad_map, ino);
 }
 
-static void add_encrypted_dir(e2fsck_t ctx, ino_t ino)
-{
-       struct          problem_context pctx;
-
-       if (!ctx->encrypted_dirs) {
-               pctx.errcode = ext2fs_u32_list_create(&ctx->encrypted_dirs, 0);
-               if (pctx.errcode)
-                       goto error;
-       }
-       pctx.errcode = ext2fs_u32_list_add(ctx->encrypted_dirs, ino);
-       if (pctx.errcode == 0)
-               return;
-error:
-       fix_problem(ctx, PR_1_ALLOCATE_ENCRYPTED_DIRLIST, &pctx);
-       /* Should never get here */
-       ctx->flags |= E2F_FLAG_ABORT;
-}
-
 /*
  * This procedure will allocate the inode "bb" (badblock) map table
  */
@@ -2868,7 +2855,20 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx,
                                return;
                        failed_csum = 0;
                }
-
+#ifdef CONFIG_DEVELOPER_FEATURES
+               if (try_repairs && !is_dir && problem == 0 &&
+                   (ctx->options & E2F_OPT_CLEAR_UNINIT) &&
+                   (extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT) &&
+                   fix_problem(ctx, PR_1_CLEAR_UNINIT_EXTENT, pctx)) {
+                       extent.e_flags &= ~EXT2_EXTENT_FLAGS_UNINIT;
+                       pb->inode_modified = 1;
+                       pctx->errcode = ext2fs_extent_replace(ehandle, 0,
+                                                             &extent);
+                       if (pctx->errcode)
+                               return;
+                       failed_csum = 0;
+               }
+#endif
                if (try_repairs && problem) {
 report_problem:
                        if (fix_problem(ctx, problem, pctx)) {
index 06f0954939472d7d2617ac82703bfc9557885e19..d3f21017234c66b6a724a035d0566bdf2479d3c4 100644 (file)
  *     - The inode_used_map bitmap
  *     - The inode_bad_map bitmap
  *     - The inode_dir_map bitmap
+ *     - The encrypted_file_info
  *
  * Pass 2 frees the following data structures
  *     - The inode_bad_map bitmap
  *     - The inode_reg_map bitmap
+ *     - The encrypted_file_info
  */
 
 #define _GNU_SOURCE 1 /* get strnlen() */
@@ -284,10 +286,7 @@ void e2fsck_pass2(e2fsck_t ctx)
                ext2fs_free_inode_bitmap(ctx->inode_reg_map);
                ctx->inode_reg_map = 0;
        }
-       if (ctx->encrypted_dirs) {
-               ext2fs_u32_list_free(ctx->encrypted_dirs);
-               ctx->encrypted_dirs = 0;
-       }
+       destroy_encrypted_file_info(ctx);
 
        clear_problem_context(&pctx);
        if (ctx->large_files) {
@@ -504,14 +503,12 @@ static int check_name(e2fsck_t ctx,
 }
 
 static int encrypted_check_name(e2fsck_t ctx,
-                               struct ext2_dir_entry *dirent,
+                               const struct ext2_dir_entry *dirent,
                                struct problem_context *pctx)
 {
        if (ext2fs_dirent_name_len(dirent) < EXT4_CRYPTO_BLOCK_SIZE) {
-               if (fix_problem(ctx, PR_2_BAD_ENCRYPTED_NAME, pctx)) {
-                       dirent->inode = 0;
+               if (fix_problem(ctx, PR_2_BAD_ENCRYPTED_NAME, pctx))
                        return 1;
-               }
                ext2fs_unmark_valid(ctx->fs);
        }
        return 0;
@@ -877,6 +874,71 @@ err:
        return retval;
 }
 
+/* Return true if this type of file needs encryption */
+static int needs_encryption(e2fsck_t ctx, const struct ext2_dir_entry *dirent)
+{
+       int filetype = ext2fs_dirent_file_type(dirent);
+       ext2_ino_t ino = dirent->inode;
+       struct ext2_inode inode;
+
+       if (filetype != EXT2_FT_UNKNOWN)
+               return filetype == EXT2_FT_REG_FILE ||
+                      filetype == EXT2_FT_DIR ||
+                      filetype == EXT2_FT_SYMLINK;
+
+       if (ext2fs_test_inode_bitmap2(ctx->inode_reg_map, ino) ||
+           ext2fs_test_inode_bitmap2(ctx->inode_dir_map, ino))
+               return 1;
+
+       e2fsck_read_inode(ctx, ino, &inode, "check_encryption_policy");
+       return LINUX_S_ISREG(inode.i_mode) ||
+              LINUX_S_ISDIR(inode.i_mode) ||
+              LINUX_S_ISLNK(inode.i_mode);
+}
+
+/*
+ * All regular files, directories, and symlinks in encrypted directories must be
+ * encrypted using the same encryption policy as their directory.
+ *
+ * Returns 1 if the dirent should be cleared, otherwise 0.
+ */
+static int check_encryption_policy(e2fsck_t ctx,
+                                  const struct ext2_dir_entry *dirent,
+                                  __u32 dir_encpolicy_id,
+                                  struct problem_context *pctx)
+{
+       __u32 file_encpolicy_id = find_encryption_policy(ctx, dirent->inode);
+
+       /* Same policy or both UNRECOGNIZED_ENCRYPTION_POLICY? */
+       if (file_encpolicy_id == dir_encpolicy_id)
+               return 0;
+
+       if (file_encpolicy_id == NO_ENCRYPTION_POLICY) {
+               if (!needs_encryption(ctx, dirent))
+                       return 0;
+               return fix_problem(ctx, PR_2_UNENCRYPTED_FILE, pctx);
+       }
+
+       return fix_problem(ctx, PR_2_INCONSISTENT_ENCRYPTION_POLICY, pctx);
+}
+
+/*
+ * Check an encrypted directory entry.
+ *
+ * Returns 1 if the dirent should be cleared, otherwise 0.
+ */
+static int check_encrypted_dirent(e2fsck_t ctx,
+                                 const struct ext2_dir_entry *dirent,
+                                 __u32 dir_encpolicy_id,
+                                 struct problem_context *pctx)
+{
+       if (encrypted_check_name(ctx, dirent, pctx))
+               return 1;
+       if (check_encryption_policy(ctx, dirent, dir_encpolicy_id, pctx))
+               return 1;
+       return 0;
+}
+
 static int check_dir_block2(ext2_filsys fs,
                           struct ext2_db_entry2 *db,
                           void *priv_data)
@@ -931,7 +993,7 @@ static int check_dir_block(ext2_filsys fs,
        int     is_leaf = 1;
        size_t  inline_data_size = 0;
        int     filetype = 0;
-       int     encrypted = 0;
+       __u32   dir_encpolicy_id = NO_ENCRYPTION_POLICY;
        size_t  max_block_size;
        int     hash_flags = 0;
        static char *eop_read_dirblock = NULL;
@@ -1153,8 +1215,7 @@ skip_checksum:
        } else
                max_block_size = fs->blocksize - de_csum_size;
 
-       if (ctx->encrypted_dirs)
-               encrypted = ext2fs_u32_list_test(ctx->encrypted_dirs, ino);
+       dir_encpolicy_id = find_encryption_policy(ctx, ino);
 
        dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
        prev = 0;
@@ -1418,18 +1479,25 @@ skip_checksum:
                        }
                }
 
-               if (!encrypted && check_name(ctx, dirent, &cd->pctx))
+               if (check_filetype(ctx, dirent, ino, &cd->pctx))
                        dir_modified++;
 
-               if (encrypted && (dot_state) > 1 &&
-                   encrypted_check_name(ctx, dirent, &cd->pctx)) {
-                       dir_modified++;
-                       goto next;
+               if (dir_encpolicy_id == NO_ENCRYPTION_POLICY) {
+                       /* Unencrypted directory */
+                       if (check_name(ctx, dirent, &cd->pctx))
+                               dir_modified++;
+               } else {
+                       /* Encrypted directory */
+                       if (dot_state > 1 &&
+                           check_encrypted_dirent(ctx, dirent,
+                                                  dir_encpolicy_id,
+                                                  &cd->pctx)) {
+                               dirent->inode = 0;
+                               dir_modified++;
+                               goto next;
+                       }
                }
 
-               if (check_filetype(ctx, dirent, ino, &cd->pctx))
-                       dir_modified++;
-
                if (dx_db) {
                        if (dx_dir->casefolded_hash)
                                hash_flags = EXT4_CASEFOLD_FL;
index 5eb5973d75e9b42d4e1f0524e60583d27a1bc856..c7c0ba9860061707b7e92fb72d1290b9b25e8614 100644 (file)
@@ -1199,9 +1199,9 @@ static struct e2fsck_problem problem_table[] = {
          N_("@i %i has a duplicate @x mapping\n\t(logical @b %c, @n physical @b %b, len %N)\n"),
          PROMPT_CLEAR, 0, 0, 0, 0 },
 
-       /* Error allocating memory for encrypted directory list */
-       { PR_1_ALLOCATE_ENCRYPTED_DIRLIST,
-         N_("@A memory for encrypted @d list\n"),
+       /* Error allocating memory for encrypted inode list */
+       { PR_1_ALLOCATE_ENCRYPTED_INODE_LIST,
+         N_("@A %N bytes of memory for encrypted @i list\n"),
          PROMPT_NONE, PR_FATAL, 0, 0, 0 },
 
        /* Inode extent tree could be more shallow */
@@ -1243,6 +1243,12 @@ static struct e2fsck_problem problem_table[] = {
          N_("EA @i %N for parent @i %i missing EA_INODE flag.\n "),
          PROMPT_FIX, PR_PREEN_OK, 0, 0, 0 },
 
+       /* Offer to clear uninitialized flag on an extent */
+       { PR_1_CLEAR_UNINIT_EXTENT,
+         /* xgettext:no-c-format */
+         N_("@i %i has @x marked uninitialized at @b %c (len %N).  "),
+         PROMPT_CLEAR, PR_PREEN_OK, 0, 0, 0 },
+
        /* Casefold flag set on a non-directory */
        { PR_1_CASEFOLD_NONDIR,
          N_("@i %i has the casefold flag set but is not a directory.  "),
@@ -1253,6 +1259,16 @@ static struct e2fsck_problem problem_table[] = {
          N_("@d %p has the casefold flag, but the\ncasefold feature is not enabled.  "),
          PROMPT_CLEAR_FLAG, 0, 0, 0, 0 },
 
+       /* Inode has encrypt flag but no encryption extended attribute */
+       { PR_1_MISSING_ENCRYPTION_XATTR,
+         N_("@i %i has encrypt flag but no encryption @a.\n"),
+         PROMPT_CLEAR_FLAG, 0, 0, 0, 0 },
+
+       /* Encrypted inode has corrupt encryption extended attribute */
+       { PR_1_CORRUPT_ENCRYPTION_XATTR,
+         N_("Encrypted @i %i has corrupt encryption @a.\n"),
+         PROMPT_CLEAR_INODE, 0, 0, 0, 0 },
+
        /* Pass 1b errors */
 
        /* Pass 1B: Rescan for duplicate/bad blocks */
@@ -1779,6 +1795,16 @@ static struct e2fsck_problem problem_table[] = {
          N_("Encrypted @E is too short.\n"),
          PROMPT_CLEAR, 0, 0, 0, 0 },
 
+       /* Encrypted directory contains unencrypted file */
+       { PR_2_UNENCRYPTED_FILE,
+         N_("Encrypted @E references unencrypted @i %Di.\n"),
+         PROMPT_CLEAR, 0, 0, 0, 0 },
+
+       /* Encrypted directory contains file with different encryption policy */
+       { PR_2_INCONSISTENT_ENCRYPTION_POLICY,
+         N_("Encrypted @E references @i %Di, which has a different encryption policy.\n"),
+         PROMPT_CLEAR, 0, 0, 0, 0 },
+
        /* Pass 3 errors */
 
        /* Pass 3: Checking directory connectivity */
index 5cc89249992ee206bd3fcbc779fec0d004f29d0e..c7f65f6dee0fbfa590a0a905a8eb065efe4b2194 100644 (file)
@@ -667,8 +667,8 @@ struct problem_context {
 /* Inode leaf has a duplicate extent mapping */
 #define PR_1_EXTENT_COLLISION                  0x01007D
 
-/* Error allocating memory for encrypted directory list */
-#define PR_1_ALLOCATE_ENCRYPTED_DIRLIST                0x01007E
+/* Error allocating memory for encrypted inode list */
+#define PR_1_ALLOCATE_ENCRYPTED_INODE_LIST     0x01007E
 
 /* Inode extent tree could be more shallow */
 #define PR_1_EXTENT_BAD_MAX_DEPTH              0x01007F
@@ -701,6 +701,11 @@ struct problem_context {
 /* Casefold flag set, but file system is missing the casefold feature */
 #define PR_1_CASEFOLD_FEATURE                  0x010089
 
+/* Inode has encrypt flag but no encryption extended attribute */
+#define PR_1_MISSING_ENCRYPTION_XATTR          0x01008A
+
+/* Encrypted inode has corrupt encryption extended attribute */
+#define PR_1_CORRUPT_ENCRYPTION_XATTR          0x01008B
 
 /*
  * Pass 1b errors
@@ -1017,6 +1022,12 @@ struct problem_context {
 /* Encrypted directory entry is too short */
 #define PR_2_BAD_ENCRYPTED_NAME                0x020050
 
+/* Encrypted directory contains unencrypted file */
+#define PR_2_UNENCRYPTED_FILE          0x020051
+
+/* Encrypted directory contains file with different encryption policy */
+#define PR_2_INCONSISTENT_ENCRYPTION_POLICY    0x020052
+
 /*
  * Pass 3 errors
  */
index 81110e4d445065edbfc2b0b576d0d1fec453cadb..5df690ad51d2abc76008b986645507bf1b6c8d19 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * linux/fs/jbd2/recovery.c
  *
@@ -5,10 +6,6 @@
  *
  * Copyright 1999-2000 Red Hat Software --- All Rights Reserved
  *
- * This file is part of the Linux kernel and is made available under
- * the terms of the GNU General Public License, version 2, or at your
- * option, any later version, incorporated herein by reference.
- *
  * Journal recovery routines for the generic filesystem journaling code;
  * part of the ext2fs journaling system.
  */
@@ -87,7 +84,7 @@ static int do_readahead(journal_t *journal, unsigned int start)
        nbufs = 0;
 
        for (next = start; next < max; next++) {
-               err = journal_bmap(journal, next, &blocknr);
+               err = jbd2_journal_bmap(journal, next, &blocknr);
 
                if (err) {
                        printk(KERN_ERR "JBD2: bad block at offset %u\n",
@@ -104,7 +101,7 @@ static int do_readahead(journal_t *journal, unsigned int start)
                if (!buffer_uptodate(bh) && !buffer_locked(bh)) {
                        bufs[nbufs++] = bh;
                        if (nbufs == MAXBUF) {
-                               ll_rw_block(READ, nbufs, bufs);
+                               ll_rw_block(REQ_OP_READ, 0, nbufs, bufs);
                                journal_brelse_array(bufs, nbufs);
                                nbufs = 0;
                        }
@@ -113,7 +110,7 @@ static int do_readahead(journal_t *journal, unsigned int start)
        }
 
        if (nbufs)
-               ll_rw_block(READ, nbufs, bufs);
+               ll_rw_block(REQ_OP_READ, 0, nbufs, bufs);
        err = 0;
 
 failed:
@@ -164,7 +161,7 @@ static int jread(struct buffer_head **bhp, journal_t *journal,
                return -EFSCORRUPTED;
        }
 
-       err = journal_bmap(journal, offset, &blocknr);
+       err = jbd2_journal_bmap(journal, offset, &blocknr);
 
        if (err) {
                printk(KERN_ERR "JBD2: bad block at offset %u\n",
@@ -195,24 +192,23 @@ static int jread(struct buffer_head **bhp, journal_t *journal,
        return 0;
 }
 
-static int jbd2_descr_block_csum_verify(journal_t *j,
-                                       void *buf)
+static int jbd2_descriptor_block_csum_verify(journal_t *j, void *buf)
 {
-       struct journal_block_tail *tail;
-       __u32 provided;
+       struct jbd2_journal_block_tail *tail;
+       __be32 provided;
        __u32 calculated;
 
-       if (!journal_has_csum_v2or3(j))
+       if (!jbd2_journal_has_csum_v2or3(j))
                return 1;
 
-       tail = (struct journal_block_tail *)((char *)buf + j->j_blocksize -
-                       sizeof(struct journal_block_tail));
+       tail = (struct jbd2_journal_block_tail *)((char *)buf + j->j_blocksize -
+                       sizeof(struct jbd2_journal_block_tail));
        provided = tail->t_checksum;
        tail->t_checksum = 0;
        calculated = jbd2_chksum(j, j->j_csum_seed, buf, j->j_blocksize);
        tail->t_checksum = provided;
 
-       return provided == ext2fs_cpu_to_be32(calculated);
+       return provided == cpu_to_be32(calculated);
 }
 
 /*
@@ -226,8 +222,8 @@ static int count_tags(journal_t *journal, struct buffer_head *bh)
        int                     nr = 0, size = journal->j_blocksize;
        int                     tag_bytes = journal_tag_bytes(journal);
 
-       if (journal_has_csum_v2or3(journal))
-               size -= sizeof(struct journal_block_tail);
+       if (jbd2_journal_has_csum_v2or3(journal))
+               size -= sizeof(struct jbd2_journal_block_tail);
 
        tagp = &bh->b_data[sizeof(journal_header_t)];
 
@@ -236,10 +232,10 @@ static int count_tags(journal_t *journal, struct buffer_head *bh)
 
                nr++;
                tagp += tag_bytes;
-               if (!(get_be16(&tag->t_flags) & JFS_FLAG_SAME_UUID))
+               if (!(get_be16(&tag->t_flags) & JBD2_FLAG_SAME_UUID))
                        tagp += 16;
 
-               if (get_be16(&tag->t_flags) & JFS_FLAG_LAST_TAG)
+               if (get_be16(&tag->t_flags) & JBD2_FLAG_LAST_TAG)
                        break;
        }
 
@@ -255,7 +251,7 @@ do {                                                                        \
 } while (0)
 
 /**
- * journal_recover - recovers a on-disk journal
+ * jbd2_journal_recover - recovers a on-disk journal
  * @journal: the journal to recover
  *
  * The primary function for recovering the log contents when mounting a
@@ -266,7 +262,7 @@ do {                                                                        \
  * blocks.  In the third and final pass, we replay any un-revoked blocks
  * in the log.
  */
-int journal_recover(journal_t *journal)
+int jbd2_journal_recover(journal_t *journal)
 {
        int                     err, err2;
        journal_superblock_t *  sb;
@@ -284,8 +280,8 @@ int journal_recover(journal_t *journal)
 
        if (!sb->s_start) {
                jbd_debug(1, "No recovery required, last transaction %d\n",
-                         ext2fs_be32_to_cpu(sb->s_sequence));
-               journal->j_transaction_sequence = ext2fs_be32_to_cpu(sb->s_sequence) + 1;
+                         be32_to_cpu(sb->s_sequence));
+               journal->j_transaction_sequence = be32_to_cpu(sb->s_sequence) + 1;
                return 0;
        }
 
@@ -305,12 +301,12 @@ int journal_recover(journal_t *journal)
         * any existing commit records in the log. */
        journal->j_transaction_sequence = ++info.end_transaction;
 
-       journal_clear_revoke(journal);
+       jbd2_journal_clear_revoke(journal);
        err2 = sync_blockdev(journal->j_fs_dev);
        if (!err)
                err = err2;
        /* Make sure all replayed data is on permanent storage */
-       if (journal->j_flags & JFS_BARRIER) {
+       if (journal->j_flags & JBD2_BARRIER) {
                err2 = blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL);
                if (!err)
                        err = err2;
@@ -319,7 +315,7 @@ int journal_recover(journal_t *journal)
 }
 
 /**
- * journal_skip_recovery - Start journal and wipe exiting records
+ * jbd2_journal_skip_recovery - Start journal and wipe exiting records
  * @journal: journal to startup
  *
  * Locate any valid recovery information from the journal and set up the
@@ -331,7 +327,7 @@ int journal_recover(journal_t *journal)
  * much recovery information is being erased, and to let us initialise
  * the journal transaction sequence numbers to the next unused ID.
  */
-int journal_skip_recovery(journal_t *journal)
+int jbd2_journal_skip_recovery(journal_t *journal)
 {
        int                     err;
 
@@ -345,9 +341,9 @@ int journal_skip_recovery(journal_t *journal)
                printk(KERN_ERR "JBD2: error %d scanning journal\n", err);
                ++journal->j_transaction_sequence;
        } else {
-#ifdef CONFIG_JFS_DEBUG
-               int dropped = info.end_transaction -
-                       ext2fs_be32_to_cpu(journal->j_superblock->s_sequence);
+#ifdef CONFIG_JBD2_DEBUG
+               int dropped = info.end_transaction - 
+                       be32_to_cpu(journal->j_superblock->s_sequence);
                jbd_debug(1,
                          "JBD2: ignoring %d transaction%s from the journal.\n",
                          dropped, (dropped == 1) ? "" : "s");
@@ -363,7 +359,7 @@ static inline unsigned long long read_tag_block(journal_t *journal,
                                                journal_block_tag_t *tag)
 {
        unsigned long long block = get_be32(&tag->t_blocknr);
-       if (jfs_has_feature_64bit(journal))
+       if (jbd2_has_feature_64bit(journal))
                block |= (u64)get_be32(&tag->t_blocknr_high) << 32;
        return block;
 }
@@ -403,10 +399,10 @@ static int calc_chksums(journal_t *journal, struct buffer_head *bh,
 static int jbd2_commit_block_csum_verify(journal_t *j, void *buf)
 {
        struct commit_header *h;
-       __u32 provided;
+       __be32 provided;
        __u32 calculated;
 
-       if (!journal_has_csum_v2or3(j))
+       if (!jbd2_journal_has_csum_v2or3(j))
                return 1;
 
        h = buf;
@@ -415,7 +411,7 @@ static int jbd2_commit_block_csum_verify(journal_t *j, void *buf)
        calculated = jbd2_chksum(j, j->j_csum_seed, buf, j->j_blocksize);
        h->h_chksum[0] = provided;
 
-       return provided == ext2fs_cpu_to_be32(calculated);
+       return provided == cpu_to_be32(calculated);
 }
 
 static int jbd2_block_tag_csum_verify(journal_t *j, journal_block_tag_t *tag,
@@ -423,16 +419,16 @@ static int jbd2_block_tag_csum_verify(journal_t *j, journal_block_tag_t *tag,
 {
        journal_block_tag3_t *tag3 = (journal_block_tag3_t *)tag;
        __u32 csum32;
-       __u32 seq;
+       __be32 seq;
 
-       if (!journal_has_csum_v2or3(j))
+       if (!jbd2_journal_has_csum_v2or3(j))
                return 1;
 
-       seq = ext2fs_cpu_to_be32(sequence);
+       seq = cpu_to_be32(sequence);
        csum32 = jbd2_chksum(j, j->j_csum_seed, (__u8 *)&seq, sizeof(seq));
        csum32 = jbd2_chksum(j, csum32, buf, j->j_blocksize);
 
-       if (jfs_has_feature_csum3(j))
+       if (jbd2_has_feature_csum3(j))
                return get_be32(&tag3->t_checksum) == csum32;
 
        return get_be16(&tag->t_checksum) == (csum32 & 0xFFFF);
@@ -461,8 +457,8 @@ static int do_one_pass(journal_t *journal,
         */
 
        sb = journal->j_superblock;
-       next_commit_ID = ext2fs_be32_to_cpu(sb->s_sequence);
-       next_log_block = ext2fs_be32_to_cpu(sb->s_start);
+       next_commit_ID = be32_to_cpu(sb->s_sequence);
+       next_log_block = be32_to_cpu(sb->s_start);
 
        first_commit_ID = next_commit_ID;
        if (pass == PASS_SCAN)
@@ -517,13 +513,13 @@ static int do_one_pass(journal_t *journal,
 
                tmp = (journal_header_t *)bh->b_data;
 
-               if (tmp->h_magic != ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER)) {
+               if (tmp->h_magic != cpu_to_be32(JBD2_MAGIC_NUMBER)) {
                        brelse(bh);
                        break;
                }
 
-               blocktype = ext2fs_be32_to_cpu(tmp->h_blocktype);
-               sequence = ext2fs_be32_to_cpu(tmp->h_sequence);
+               blocktype = be32_to_cpu(tmp->h_blocktype);
+               sequence = be32_to_cpu(tmp->h_sequence);
                jbd_debug(3, "Found magic %d, sequence %d\n",
                          blocktype, sequence);
 
@@ -537,14 +533,14 @@ static int do_one_pass(journal_t *journal,
                 * to do with it?  That depends on the pass... */
 
                switch(blocktype) {
-               case JFS_DESCRIPTOR_BLOCK:
+               case JBD2_DESCRIPTOR_BLOCK:
                        /* Verify checksum first */
-                       if (journal_has_csum_v2or3(journal))
+                       if (jbd2_journal_has_csum_v2or3(journal))
                                descr_csum_size =
-                                       sizeof(struct journal_block_tail);
+                                       sizeof(struct jbd2_journal_block_tail);
                        if (descr_csum_size > 0 &&
-                           !jbd2_descr_block_csum_verify(journal,
-                                                         bh->b_data)) {
+                           !jbd2_descriptor_block_csum_verify(journal,
+                                                              bh->b_data)) {
                                err = -EFSBADCRC;
                                brelse(bh);
                                goto failed;
@@ -556,7 +552,7 @@ static int do_one_pass(journal_t *journal,
                         * just skip over the blocks it describes. */
                        if (pass != PASS_REPLAY) {
                                if (pass == PASS_SCAN &&
-                                   jfs_has_feature_checksum(journal) &&
+                                   jbd2_has_feature_checksum(journal) &&
                                    !info->end_transaction) {
                                        if (calc_chksums(journal, bh,
                                                        &next_log_block,
@@ -606,7 +602,7 @@ static int do_one_pass(journal_t *journal,
                                        /* If the block has been
                                         * revoked, then we're all done
                                         * here. */
-                                       if (journal_test_revoke
+                                       if (jbd2_journal_test_revoke
                                            (journal, blocknr,
                                             next_commit_ID)) {
                                                brelse(obh);
@@ -617,13 +613,13 @@ static int do_one_pass(journal_t *journal,
                                        /* Look for block corruption */
                                        if (!jbd2_block_tag_csum_verify(
                                                journal, tag, obh->b_data,
-                                               ext2fs_be32_to_cpu(tmp->h_sequence))) {
+                                               be32_to_cpu(tmp->h_sequence))) {
                                                brelse(obh);
                                                success = -EFSBADCRC;
                                                printk(KERN_ERR "JBD2: Invalid "
                                                       "checksum recovering "
-                                                      "block %llu in log\n",
-                                                      blocknr);
+                                                      "data block %llu in "
+                                                      "log\n", blocknr);
                                                block_error = 1;
                                                goto skip_write;
                                        }
@@ -646,8 +642,8 @@ static int do_one_pass(journal_t *journal,
                                        lock_buffer(nbh);
                                        memcpy(nbh->b_data, obh->b_data,
                                                        journal->j_blocksize);
-                                       if (flags & JFS_FLAG_ESCAPE) {
-                                               __u32 magic = ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER);
+                                       if (flags & JBD2_FLAG_ESCAPE) {
+                                               __be32 magic = cpu_to_be32(JBD2_MAGIC_NUMBER);
                                                memcpy(nbh->b_data, &magic,
                                                       sizeof(magic));
                                        }
@@ -665,17 +661,17 @@ static int do_one_pass(journal_t *journal,
 
                        skip_write:
                                tagp += tag_bytes;
-                               if (!(flags & JFS_FLAG_SAME_UUID))
+                               if (!(flags & JBD2_FLAG_SAME_UUID))
                                        tagp += 16;
 
-                               if (flags & JFS_FLAG_LAST_TAG)
+                               if (flags & JBD2_FLAG_LAST_TAG)
                                        break;
                        }
 
                        brelse(bh);
                        continue;
 
-               case JFS_COMMIT_BLOCK:
+               case JBD2_COMMIT_BLOCK:
                        /*     How to differentiate between interrupted commit
                         *               and journal corruption ?
                         *
@@ -712,12 +708,12 @@ static int do_one_pass(journal_t *journal,
                         * much to do other than move on to the next sequence
                         * number. */
                        if (pass == PASS_SCAN &&
-                           jfs_has_feature_checksum(journal)) {
+                           jbd2_has_feature_checksum(journal)) {
                                int chksum_err, chksum_seen;
                                struct commit_header *cbh =
                                        (struct commit_header *)bh->b_data;
                                unsigned found_chksum =
-                                       ext2fs_be32_to_cpu(cbh->h_chksum[0]);
+                                       be32_to_cpu(cbh->h_chksum[0]);
 
                                chksum_err = chksum_seen = 0;
 
@@ -729,9 +725,9 @@ static int do_one_pass(journal_t *journal,
                                }
 
                                if (crc32_sum == found_chksum &&
-                                   cbh->h_chksum_type == JFS_CRC32_CHKSUM &&
+                                   cbh->h_chksum_type == JBD2_CRC32_CHKSUM &&
                                    cbh->h_chksum_size ==
-                                               JFS_CRC32_CHKSUM_SIZE)
+                                               JBD2_CRC32_CHKSUM_SIZE)
                                       chksum_seen = 1;
                                else if (!(cbh->h_chksum_type == 0 &&
                                             cbh->h_chksum_size == 0 &&
@@ -752,7 +748,7 @@ static int do_one_pass(journal_t *journal,
                                if (chksum_err) {
                                        info->end_transaction = next_commit_ID;
 
-                                       if (!jfs_has_feature_async_commit(journal)){
+                                       if (!jbd2_has_feature_async_commit(journal)) {
                                                journal->j_failed_commit =
                                                        next_commit_ID;
                                                brelse(bh);
@@ -766,7 +762,7 @@ static int do_one_pass(journal_t *journal,
                                                           bh->b_data)) {
                                info->end_transaction = next_commit_ID;
 
-                               if (!jfs_has_feature_async_commit(journal)) {
+                               if (!jbd2_has_feature_async_commit(journal)) {
                                        journal->j_failed_commit =
                                                next_commit_ID;
                                        brelse(bh);
@@ -777,7 +773,7 @@ static int do_one_pass(journal_t *journal,
                        next_commit_ID++;
                        continue;
 
-               case JFS_REVOKE_BLOCK:
+               case JBD2_REVOKE_BLOCK:
                        /* If we aren't in the REVOKE pass, then we can
                         * just skip over this block. */
                        if (pass != PASS_REVOKE) {
@@ -830,51 +826,31 @@ static int do_one_pass(journal_t *journal,
        return err;
 }
 
-static int jbd2_revoke_block_csum_verify(journal_t *j,
-                                        void *buf)
-{
-       struct journal_revoke_tail *tail;
-       __u32 provided;
-       __u32 calculated;
-
-       if (!journal_has_csum_v2or3(j))
-               return 1;
-
-       tail = (struct journal_revoke_tail *)((char *)buf + j->j_blocksize -
-                       sizeof(struct journal_revoke_tail));
-       provided = tail->r_checksum;
-       tail->r_checksum = 0;
-       calculated = jbd2_chksum(j, j->j_csum_seed, buf, j->j_blocksize);
-       tail->r_checksum = provided;
-
-       return provided == ext2fs_cpu_to_be32(calculated);
-}
-
 /* Scan a revoke record, marking all blocks mentioned as revoked. */
 
 static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
                               tid_t sequence, struct recovery_info *info)
 {
-       journal_revoke_header_t *header;
+       jbd2_journal_revoke_header_t *header;
        int offset, max;
        unsigned csum_size = 0;
        __u32 rcount;
        int record_len = 4;
 
-       header = (journal_revoke_header_t *) bh->b_data;
-       offset = sizeof(journal_revoke_header_t);
-       rcount = ext2fs_be32_to_cpu(header->r_count);
+       header = (jbd2_journal_revoke_header_t *) bh->b_data;
+       offset = sizeof(jbd2_journal_revoke_header_t);
+       rcount = be32_to_cpu(header->r_count);
 
-       if (!jbd2_revoke_block_csum_verify(journal, header))
+       if (!jbd2_descriptor_block_csum_verify(journal, header))
                return -EFSBADCRC;
 
-       if (journal_has_csum_v2or3(journal))
-               csum_size = sizeof(struct journal_revoke_tail);
+       if (jbd2_journal_has_csum_v2or3(journal))
+               csum_size = sizeof(struct jbd2_journal_block_tail);
        if (rcount > journal->j_blocksize - csum_size)
                return -EINVAL;
        max = rcount;
 
-       if (jfs_has_feature_64bit(journal))
+       if (jbd2_has_feature_64bit(journal))
                record_len = 8;
 
        while (offset + record_len <= max) {
@@ -882,11 +858,11 @@ static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
                int err;
 
                if (record_len == 4)
-                       blocknr = ext2fs_be32_to_cpu(* ((__u32 *) (bh->b_data+offset)));
+                       blocknr = be32_to_cpu(* ((__be32 *) (bh->b_data+offset)));
                else
-                       blocknr = ext2fs_be64_to_cpu(* ((__u64 *) (bh->b_data+offset)));
+                       blocknr = be64_to_cpu(* ((__be64 *) (bh->b_data+offset)));
                offset += record_len;
-               err = journal_set_revoke(journal, blocknr, sequence);
+               err = jbd2_journal_set_revoke(journal, blocknr, sequence);
                if (err)
                        return err;
                ++info->nr_revokes;
index f72547135093525f89ee6287cad86059b220d675..fa608788b93d7c55977b8c64201374ffb6a1a42c 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * linux/fs/jbd2/revoke.c
  *
@@ -5,10 +6,6 @@
  *
  * Copyright 2000 Red Hat corp --- All Rights Reserved
  *
- * This file is part of the Linux kernel and is made available under
- * the terms of the GNU General Public License, version 2, or at your
- * option, any later version, incorporated herein by reference.
- *
  * Journal revoke routines for the generic filesystem journaling code;
  * part of the ext2fs journaling system.
  *
 #include <linux/init.h>
 #include <linux/bio.h>
 #include <linux/log2.h>
+#include <linux/hash.h>
 #endif
 
-static lkmem_cache_t *jbd2_revoke_record_cache;
-static lkmem_cache_t *jbd2_revoke_table_cache;
+static struct kmem_cache *jbd2_revoke_record_cache;
+static struct kmem_cache *jbd2_revoke_table_cache;
 
 /* Each revoke record represents one single revoked block.  During
    journal replay, this involves recording the transaction ID of the
@@ -121,21 +119,18 @@ struct jbd2_revoke_table_s
 
 
 #ifdef __KERNEL__
-static void write_one_revoke_record(journal_t *, transaction_t *,
+static void write_one_revoke_record(transaction_t *,
                                    struct list_head *,
                                    struct buffer_head **, int *,
-                                   struct jbd2_revoke_record_s *, int);
-static void flush_descriptor(journal_t *, struct buffer_head *, int, int);
+                                   struct jbd2_revoke_record_s *);
+static void flush_descriptor(journal_t *, struct buffer_head *, int);
 #endif
 
 /* Utility functions to maintain the revoke table */
 
-/* Borrowed from buffer.c: this is a tried and tested block hash function */
 static inline int hash(journal_t *journal, unsigned long long block)
 {
-       struct jbd2_revoke_table_s *table = journal->j_revoke;
-
-       return (hash_64(block, table->hash_shift));
+       return hash_64(block, journal->j_revoke->hash_shift);
 }
 
 static int insert_revoke_hash(journal_t *journal, unsigned long long blocknr,
@@ -143,11 +138,13 @@ static int insert_revoke_hash(journal_t *journal, unsigned long long blocknr,
 {
        struct list_head *hash_list;
        struct jbd2_revoke_record_s *record;
+       gfp_t gfp_mask = GFP_NOFS;
 
-repeat:
-       record = kmem_cache_alloc(jbd2_revoke_record_cache, GFP_NOFS);
+       if (journal_oom_retry)
+               gfp_mask |= __GFP_NOFAIL;
+       record = kmem_cache_alloc(jbd2_revoke_record_cache, gfp_mask);
        if (!record)
-               goto oom;
+               return -ENOMEM;
 
        record->sequence = seq;
        record->blocknr = blocknr;
@@ -156,13 +153,6 @@ repeat:
        list_add(&record->hash, hash_list);
        spin_unlock(&journal->j_revoke_lock);
        return 0;
-
-oom:
-       if (!journal_oom_retry)
-               return -ENOMEM;
-       jbd_debug(1, "ENOMEM in %s, retrying\n", __func__);
-       yield();
-       goto repeat;
 }
 
 /* Find a revoke record in the journal's hash table. */
@@ -188,40 +178,44 @@ static struct jbd2_revoke_record_s *find_revoke_record(journal_t *journal,
        return NULL;
 }
 
-void journal_destroy_revoke_caches(void)
+void jbd2_journal_destroy_revoke_record_cache(void)
 {
-       if (jbd2_revoke_record_cache) {
-               kmem_cache_destroy(jbd2_revoke_record_cache);
-               jbd2_revoke_record_cache = NULL;
-       }
-       if (jbd2_revoke_table_cache) {
-               kmem_cache_destroy(jbd2_revoke_table_cache);
-               jbd2_revoke_table_cache = NULL;
-       }
+       kmem_cache_destroy(jbd2_revoke_record_cache);
+       jbd2_revoke_record_cache = NULL;
 }
 
-int __init journal_init_revoke_caches(void)
+void jbd2_journal_destroy_revoke_table_cache(void)
 {
-       J_ASSERT(!jbd2_revoke_record_cache);
-       J_ASSERT(!jbd2_revoke_table_cache);
+       kmem_cache_destroy(jbd2_revoke_table_cache);
+       jbd2_revoke_table_cache = NULL;
+}
 
+int __init jbd2_journal_init_revoke_record_cache(void)
+{
+       J_ASSERT(!jbd2_revoke_record_cache);
        jbd2_revoke_record_cache = KMEM_CACHE(jbd2_revoke_record_s,
                                        SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY);
-       if (!jbd2_revoke_record_cache)
-               goto record_cache_failure;
 
+       if (!jbd2_revoke_record_cache) {
+               pr_emerg("JBD2: failed to create revoke_record cache\n");
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+int __init jbd2_journal_init_revoke_table_cache(void)
+{
+       J_ASSERT(!jbd2_revoke_table_cache);
        jbd2_revoke_table_cache = KMEM_CACHE(jbd2_revoke_table_s,
                                             SLAB_TEMPORARY);
-       if (!jbd2_revoke_table_cache)
-               goto table_cache_failure;
-       return 0;
-table_cache_failure:
-       journal_destroy_revoke_caches();
-record_cache_failure:
+       if (!jbd2_revoke_table_cache) {
+               pr_emerg("JBD2: failed to create revoke_table cache\n");
                return -ENOMEM;
+       }
+       return 0;
 }
 
-static struct jbd2_revoke_table_s *journal_init_revoke_table(int hash_size)
+static struct jbd2_revoke_table_s *jbd2_journal_init_revoke_table(int hash_size)
 {
        int shift = 0;
        int tmp = hash_size;
@@ -237,7 +231,7 @@ static struct jbd2_revoke_table_s *journal_init_revoke_table(int hash_size)
        table->hash_size = hash_size;
        table->hash_shift = shift;
        table->hash_table =
-               kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL);
+               kmalloc_array(hash_size, sizeof(struct list_head), GFP_KERNEL);
        if (!table->hash_table) {
                kmem_cache_free(jbd2_revoke_table_cache, table);
                table = NULL;
@@ -251,7 +245,7 @@ out:
        return table;
 }
 
-static void journal_destroy_revoke_table(struct jbd2_revoke_table_s *table)
+static void jbd2_journal_destroy_revoke_table(struct jbd2_revoke_table_s *table)
 {
        int i;
        struct list_head *hash_list;
@@ -266,16 +260,16 @@ static void journal_destroy_revoke_table(struct jbd2_revoke_table_s *table)
 }
 
 /* Initialise the revoke table for a given journal to a given size. */
-int journal_init_revoke(journal_t *journal, int hash_size)
+int jbd2_journal_init_revoke(journal_t *journal, int hash_size)
 {
        J_ASSERT(journal->j_revoke_table[0] == NULL);
        J_ASSERT(is_power_of_2(hash_size));
 
-       journal->j_revoke_table[0] = journal_init_revoke_table(hash_size);
+       journal->j_revoke_table[0] = jbd2_journal_init_revoke_table(hash_size);
        if (!journal->j_revoke_table[0])
                goto fail0;
 
-       journal->j_revoke_table[1] = journal_init_revoke_table(hash_size);
+       journal->j_revoke_table[1] = jbd2_journal_init_revoke_table(hash_size);
        if (!journal->j_revoke_table[1])
                goto fail1;
 
@@ -286,26 +280,27 @@ int journal_init_revoke(journal_t *journal, int hash_size)
        return 0;
 
 fail1:
-       journal_destroy_revoke_table(journal->j_revoke_table[0]);
+       jbd2_journal_destroy_revoke_table(journal->j_revoke_table[0]);
+       journal->j_revoke_table[0] = NULL;
 fail0:
        return -ENOMEM;
 }
 
 /* Destroy a journal's revoke table.  The table must already be empty! */
-void journal_destroy_revoke(journal_t *journal)
+void jbd2_journal_destroy_revoke(journal_t *journal)
 {
        journal->j_revoke = NULL;
        if (journal->j_revoke_table[0])
-               journal_destroy_revoke_table(journal->j_revoke_table[0]);
+               jbd2_journal_destroy_revoke_table(journal->j_revoke_table[0]);
        if (journal->j_revoke_table[1])
-               journal_destroy_revoke_table(journal->j_revoke_table[1]);
+               jbd2_journal_destroy_revoke_table(journal->j_revoke_table[1]);
 }
 
 
 #ifdef __KERNEL__
 
 /*
- * journal_revoke: revoke a given buffer_head from the journal.  This
+ * jbd2_journal_revoke: revoke a given buffer_head from the journal.  This
  * prevents the block from being replayed during recovery if we take a
  * crash after this current transaction commits.  Any subsequent
  * metadata writes of the buffer in this transaction cancel the
@@ -317,18 +312,18 @@ void journal_destroy_revoke(journal_t *journal)
  * revoke before clearing the block bitmap when we are deleting
  * metadata.
  *
- * Revoke performs a journal_forget on any buffer_head passed in as a
+ * Revoke performs a jbd2_journal_forget on any buffer_head passed in as a
  * parameter, but does _not_ forget the buffer_head if the bh was only
  * found implicitly.
  *
  * bh_in may not be a journalled buffer - it may have come off
  * the hash tables without an attached journal_head.
  *
- * If bh_in is non-zero, journal_revoke() will decrement its b_count
+ * If bh_in is non-zero, jbd2_journal_revoke() will decrement its b_count
  * by one.
  */
 
-int journal_revoke(handle_t *handle, unsigned long long blocknr,
+int jbd2_journal_revoke(handle_t *handle, unsigned long long blocknr,
                   struct buffer_head *bh_in)
 {
        struct buffer_head *bh = NULL;
@@ -341,7 +336,7 @@ int journal_revoke(handle_t *handle, unsigned long long blocknr,
                BUFFER_TRACE(bh_in, "enter");
 
        journal = handle->h_transaction->t_journal;
-       if (!journal_set_features(journal, 0, 0, JFS_FEATURE_INCOMPAT_REVOKE)){
+       if (!jbd2_journal_set_features(journal, 0, 0, JBD2_FEATURE_INCOMPAT_REVOKE)){
                J_ASSERT (!"Cannot set revoke feature!");
                return -EINVAL;
        }
@@ -354,7 +349,7 @@ int journal_revoke(handle_t *handle, unsigned long long blocknr,
                if (bh)
                        BUFFER_TRACE(bh, "found on hash");
        }
-#ifdef JFS_EXPENSIVE_CHECKING
+#ifdef JBD2_EXPENSIVE_CHECKING
        else {
                struct buffer_head *bh2;
 
@@ -376,6 +371,11 @@ int journal_revoke(handle_t *handle, unsigned long long blocknr,
        }
 #endif
 
+       if (WARN_ON_ONCE(handle->h_revoke_credits <= 0)) {
+               if (!bh_in)
+                       brelse(bh);
+               return -EIO;
+       }
        /* We really ought not ever to revoke twice in a row without
            first having the revoke cancelled: it's illegal to free a
            block twice without allocating it in between! */
@@ -389,13 +389,14 @@ int journal_revoke(handle_t *handle, unsigned long long blocknr,
                set_buffer_revoked(bh);
                set_buffer_revokevalid(bh);
                if (bh_in) {
-                       BUFFER_TRACE(bh_in, "call journal_forget");
-                       journal_forget(handle, bh_in);
+                       BUFFER_TRACE(bh_in, "call jbd2_journal_forget");
+                       jbd2_journal_forget(handle, bh_in);
                } else {
                        BUFFER_TRACE(bh, "call brelse");
                        __brelse(bh);
                }
        }
+       handle->h_revoke_credits--;
 
        jbd_debug(2, "insert revoke for block %llu, bh_in=%p\n",blocknr, bh_in);
        err = insert_revoke_hash(journal, blocknr,
@@ -406,7 +407,7 @@ int journal_revoke(handle_t *handle, unsigned long long blocknr,
 
 /*
  * Cancel an outstanding revoke.  For use only internally by the
- * journaling code (called from journal_get_write_access).
+ * journaling code (called from jbd2_journal_get_write_access).
  *
  * We trust buffer_revoked() on the buffer if the buffer is already
  * being journaled: if there is no revoke pending on the buffer, then we
@@ -419,7 +420,7 @@ int journal_revoke(handle_t *handle, unsigned long long blocknr,
  * do not trust the Revoked bit on buffers unless RevokeValid is also
  * set.
  */
-int journal_cancel_revoke(handle_t *handle, struct journal_head *jh)
+int jbd2_journal_cancel_revoke(handle_t *handle, struct journal_head *jh)
 {
        struct jbd2_revoke_record_s *record;
        journal_t *journal = handle->h_transaction->t_journal;
@@ -427,7 +428,7 @@ int journal_cancel_revoke(handle_t *handle, struct journal_head *jh)
        int did_revoke = 0;     /* akpm: debug */
        struct buffer_head *bh = jh2bh(jh);
 
-       jbd_debug(4, "journal_head %p, canceling revoke\n", jh);
+       jbd_debug(4, "journal_head %p, cancelling revoke\n", jh);
 
        /* Is the existing Revoke bit valid?  If so, we trust it, and
         * only perform the full cancel if the revoke bit is set.  If
@@ -453,7 +454,7 @@ int journal_cancel_revoke(handle_t *handle, struct journal_head *jh)
                }
        }
 
-#ifdef JFS_EXPENSIVE_CHECKING
+#ifdef JBD2_EXPENSIVE_CHECKING
        /* There better not be one left behind by now! */
        record = find_revoke_record(journal, bh->b_blocknr);
        J_ASSERT_JH(jh, record == NULL);
@@ -509,7 +510,7 @@ void jbd2_clear_buffer_revoked_flags(journal_t *journal)
  * we do not want to suspend any processing until all revokes are
  * written -bzzz
  */
-void journal_switch_revoke_table(journal_t *journal)
+void jbd2_journal_switch_revoke_table(journal_t *journal)
 {
        int i;
 
@@ -526,11 +527,10 @@ void journal_switch_revoke_table(journal_t *journal)
  * Write revoke records to the journal for all entries in the current
  * revoke hash, deleting the entries as we go.
  */
-void journal_write_revoke_records(journal_t *journal,
-                                      transaction_t *transaction,
-                                      struct list_head *log_bufs,
-                                      int write_op)
+void jbd2_journal_write_revoke_records(transaction_t *transaction,
+                                      struct list_head *log_bufs)
 {
+       journal_t *journal = transaction->t_journal;
        struct buffer_head *descriptor;
        struct jbd2_revoke_record_s *record;
        struct jbd2_revoke_table_s *revoke;
@@ -551,16 +551,15 @@ void journal_write_revoke_records(journal_t *journal,
                while (!list_empty(hash_list)) {
                        record = (struct jbd2_revoke_record_s *)
                                hash_list->next;
-                       write_one_revoke_record(journal, transaction, log_bufs,
-                                               &descriptor, &offset,
-                                               record, write_op);
+                       write_one_revoke_record(transaction, log_bufs,
+                                               &descriptor, &offset, record);
                        count++;
                        list_del(&record->hash);
                        kmem_cache_free(jbd2_revoke_record_cache, record);
                }
        }
        if (descriptor)
-               flush_descriptor(journal, descriptor, offset, write_op);
+               flush_descriptor(journal, descriptor, offset);
        jbd_debug(1, "Wrote %d revoke records\n", count);
 }
 
@@ -569,22 +568,20 @@ void journal_write_revoke_records(journal_t *journal,
  * block if the old one is full or if we have not already created one.
  */
 
-static void write_one_revoke_record(journal_t *journal,
-                                   transaction_t *transaction,
+static void write_one_revoke_record(transaction_t *transaction,
                                    struct list_head *log_bufs,
                                    struct buffer_head **descriptorp,
                                    int *offsetp,
-                                   struct jbd2_revoke_record_s *record,
-                                   int write_op)
+                                   struct jbd2_revoke_record_s *record)
 {
+       journal_t *journal = transaction->t_journal;
        int csum_size = 0;
        struct buffer_head *descriptor;
        int sz, offset;
-       journal_header_t *header;
 
        /* If we are already aborting, this all becomes a noop.  We
            still need to go round the loop in
-           journal_write_revoke_records in order to free all of the
+           jbd2_journal_write_revoke_records in order to free all of the
            revoke records: only the IO to the journal is omitted. */
        if (is_journal_aborted(journal))
                return;
@@ -593,10 +590,10 @@ static void write_one_revoke_record(journal_t *journal,
        offset = *offsetp;
 
        /* Do we need to leave space at the end for a checksum? */
-       if (journal_has_csum_v2or3(journal))
-               csum_size = sizeof(struct journal_revoke_tail);
+       if (jbd2_journal_has_csum_v2or3(journal))
+               csum_size = sizeof(struct jbd2_journal_block_tail);
 
-       if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT))
+       if (jbd2_has_feature_64bit(journal))
                sz = 8;
        else
                sz = 4;
@@ -604,29 +601,26 @@ static void write_one_revoke_record(journal_t *journal,
        /* Make sure we have a descriptor with space left for the record */
        if (descriptor) {
                if (offset + sz > journal->j_blocksize - csum_size) {
-                       flush_descriptor(journal, descriptor, offset, write_op);
+                       flush_descriptor(journal, descriptor, offset);
                        descriptor = NULL;
                }
        }
 
        if (!descriptor) {
-               descriptor = journal_get_descriptor_buffer(journal);
+               descriptor = jbd2_journal_get_descriptor_buffer(transaction,
+                                                       JBD2_REVOKE_BLOCK);
                if (!descriptor)
                        return;
-               header = (journal_header_t *)descriptor->b_data;
-               header->h_magic     = ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER);
-               header->h_blocktype = ext2fs_cpu_to_be32(JFS_REVOKE_BLOCK);
-               header->h_sequence  = ext2fs_cpu_to_be32(transaction->t_tid);
 
                /* Record it so that we can wait for IO completion later */
                BUFFER_TRACE(descriptor, "file in log_bufs");
                jbd2_file_log_bh(log_bufs, descriptor);
 
-               offset = sizeof(journal_revoke_header_t);
+               offset = sizeof(jbd2_journal_revoke_header_t);
                *descriptorp = descriptor;
        }
 
-       if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) {
+       if (jbd2_has_feature_64bit(journal))
                * ((__be64 *)(&descriptor->b_data[offset])) =
                        cpu_to_be64(record->blocknr);
        else
@@ -637,21 +631,6 @@ static void write_one_revoke_record(journal_t *journal,
        *offsetp = offset;
 }
 
-static 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);
-}
-
 /*
  * Flush a revoke descriptor out to the journal.  If we are aborting,
  * this is a noop; otherwise we are generating a buffer which needs to
@@ -661,23 +640,21 @@ static void jbd2_revoke_csum_set(journal_t *j, struct buffer_head *bh)
 
 static void flush_descriptor(journal_t *journal,
                             struct buffer_head *descriptor,
-                            int offset, int write_op)
+                            int offset)
 {
-       journal_revoke_header_t *header;
+       jbd2_journal_revoke_header_t *header;
 
-       if (is_journal_aborted(journal)) {
-               put_bh(descriptor);
+       if (is_journal_aborted(journal))
                return;
-       }
 
-       header = (journal_revoke_header_t *)descriptor->b_data;
-       header->r_count = ext2fs_cpu_to_be32(offset);
-       jbd2_revoke_csum_set(journal, descriptor);
+       header = (jbd2_journal_revoke_header_t *)descriptor->b_data;
+       header->r_count = cpu_to_be32(offset);
+       jbd2_descriptor_block_csum_set(journal, descriptor);
 
        set_buffer_jwrite(descriptor);
        BUFFER_TRACE(descriptor, "write");
        set_buffer_dirty(descriptor);
-       write_dirty_buffer(descriptor, write_op);
+       write_dirty_buffer(descriptor, REQ_SYNC);
 }
 #endif
 
@@ -703,7 +680,7 @@ static void flush_descriptor(journal_t *journal,
  * single block.
  */
 
-int journal_set_revoke(journal_t *journal,
+int jbd2_journal_set_revoke(journal_t *journal,
                       unsigned long long blocknr,
                       tid_t sequence)
 {
@@ -727,7 +704,7 @@ int journal_set_revoke(journal_t *journal,
  * ones, but later transactions still need replayed.
  */
 
-int journal_test_revoke(journal_t *journal,
+int jbd2_journal_test_revoke(journal_t *journal,
                        unsigned long long blocknr,
                        tid_t sequence)
 {
@@ -746,7 +723,7 @@ int journal_test_revoke(journal_t *journal,
  * that it can be reused by the running filesystem.
  */
 
-void journal_clear_revoke(journal_t *journal)
+void jbd2_journal_clear_revoke(journal_t *journal)
 {
        int i;
        struct list_head *hash_list;
index 68f4987398624d171e93a82de0797dc9457f96fc..b3ef0f22b866f5a895a6d687a9ca12faa6f7b973 100644 (file)
@@ -753,6 +753,11 @@ static void parse_extended_opts(e2fsck_t ctx, const char *opts)
                        ctx->options |= E2F_OPT_UNSHARE_BLOCKS;
                        ctx->options |= E2F_OPT_FORCE;
                        continue;
+#ifdef CONFIG_DEVELOPER_FEATURES
+               } else if (strcmp(token, "clear_all_uninit_bits") == 0) {
+                       ctx->options |= E2F_OPT_CLEAR_UNINIT;
+                       continue;
+#endif
                } else {
                        fprintf(stderr, _("Unknown extended option: %s\n"),
                                token);
index 407911ca0aa918cb8139f2329c1c9d3ab285e6eb..b448482c06f858bd5e48eb4ca723282bb6f63dd8 100644 (file)
@@ -9,6 +9,9 @@
 /* Define to 1 to compile findfs */
 #undef CONFIG_BUILD_FINDFS
 
+/* Define to 1 for features for use by ext4 developers */
+#undef CONFIG_DEVELOPER_FEATURES
+
 /* Define to 1 if debugging ext3/4 journal code */
 #undef CONFIG_JBD_DEBUG
 
index ae7f7f0aac20e610d22b1877217e2c5ce9b698d0..965ba33be5452cdbaedfa0edaefbcb27de58b116 100644 (file)
@@ -47,6 +47,8 @@ static struct feature feature_list[] = {
                        "sparse_super2" },
        {       E2P_FEATURE_COMPAT, EXT4_FEATURE_COMPAT_FAST_COMMIT,
                        "fast_commit" },
+       {       E2P_FEATURE_COMPAT, EXT4_FEATURE_COMPAT_STABLE_INODES,
+                       "stable_inodes" },
 
        {       E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER,
                        "sparse_super" },
@@ -119,18 +121,18 @@ static struct feature feature_list[] = {
 };
 
 static struct feature jrnl_feature_list[] = {
-       {       E2P_FEATURE_COMPAT, JFS_FEATURE_COMPAT_CHECKSUM,
+       {       E2P_FEATURE_COMPAT, JBD2_FEATURE_COMPAT_CHECKSUM,
                        "journal_checksum" },
 
-       {       E2P_FEATURE_INCOMPAT, JFS_FEATURE_INCOMPAT_REVOKE,
+       {       E2P_FEATURE_INCOMPAT, JBD2_FEATURE_INCOMPAT_REVOKE,
                        "journal_incompat_revoke" },
-       {       E2P_FEATURE_INCOMPAT, JFS_FEATURE_INCOMPAT_64BIT,
+       {       E2P_FEATURE_INCOMPAT, JBD2_FEATURE_INCOMPAT_64BIT,
                        "journal_64bit" },
-       {       E2P_FEATURE_INCOMPAT, JFS_FEATURE_INCOMPAT_ASYNC_COMMIT,
+       {       E2P_FEATURE_INCOMPAT, JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT,
                        "journal_async_commit" },
-       {       E2P_FEATURE_INCOMPAT, JFS_FEATURE_INCOMPAT_CSUM_V2,
+       {       E2P_FEATURE_INCOMPAT, JBD2_FEATURE_INCOMPAT_CSUM_V2,
                        "journal_checksum_v2" },
-       {       E2P_FEATURE_INCOMPAT, JFS_FEATURE_INCOMPAT_CSUM_V3,
+       {       E2P_FEATURE_INCOMPAT, JBD2_FEATURE_INCOMPAT_CSUM_V3,
                        "journal_checksum_v3" },
        {       0, 0, 0 },
 };
index c99126b61b2b456c9e78cee9a0be6883699a00b2..4ffe9b6150ecca42b8838b3e490b6938115f19d3 100644 (file)
@@ -89,19 +89,19 @@ void e2p_list_journal_super(FILE *f, char *journal_sb_buf,
                (unsigned int)ntohl(jsb->s_start));
        if (nr_users != 1)
                fprintf(f, "Journal number of users:  %u\n", nr_users);
-       if (jsb->s_feature_compat & e2p_be32(JFS_FEATURE_COMPAT_CHECKSUM))
+       if (jsb->s_feature_compat & e2p_be32(JBD2_FEATURE_COMPAT_CHECKSUM))
                fprintf(f, "%s", "Journal checksum type:    crc32\n");
        if ((jsb->s_feature_incompat &
-            e2p_be32(JFS_FEATURE_INCOMPAT_CSUM_V3)) ||
+            e2p_be32(JBD2_FEATURE_INCOMPAT_CSUM_V3)) ||
            (jsb->s_feature_incompat &
-            e2p_be32(JFS_FEATURE_INCOMPAT_CSUM_V2)))
+            e2p_be32(JBD2_FEATURE_INCOMPAT_CSUM_V2)))
                fprintf(f, "Journal checksum type:    %s\n"
                        "Journal checksum:         0x%08x\n",
                        journal_checksum_type_str(jsb->s_checksum_type),
                        e2p_be32(jsb->s_checksum));
        if ((nr_users > 1) ||
            !e2p_is_null_uuid(&jsb->s_users[0])) {
-               for (i=0; i < nr_users && i < JFS_USERS_MAX; i++) {
+               for (i=0; i < nr_users && i < JBD2_USERS_MAX; i++) {
                        printf(i ? "                          %s\n"
                               : "Journal users:            %s\n",
                               e2p_uuid2str(&jsb->s_users[i * UUID_SIZE]));
index ec77a067b37188be04932317e69dd600f60a5d92..7c3c6b5a1f81758ed8e92f719a4742a28fadfcce 100644 (file)
@@ -201,9 +201,42 @@ struct ext2_group_desc *ext2fs_group_desc(ext2_filsys fs,
                                          struct opaque_ext2_group_desc *gdp,
                                          dgrp_t group)
 {
-       int desc_size = EXT2_DESC_SIZE(fs->super) & ~7;
-
-       return (struct ext2_group_desc *)((char *)gdp + group * desc_size);
+       struct ext2_group_desc *ret_gdp;
+       errcode_t       retval;
+       static char     *buf = 0;
+       static int      bufsize = 0;
+       blk64_t         blk;
+       int             desc_size = EXT2_DESC_SIZE(fs->super) & ~7;
+       int             desc_per_blk = EXT2_DESC_PER_BLOCK(fs->super);
+
+       if (group > fs->group_desc_count)
+               return NULL;
+       if (gdp)
+               return (struct ext2_group_desc *)((char *)gdp +
+                                                 group * desc_size);
+       /*
+        * If fs->group_desc wasn't read in when the file system was
+        * opened, then read it on demand here.
+        */
+       if (bufsize < fs->blocksize)
+               ext2fs_free_mem(&buf);
+       if (!buf) {
+               retval = ext2fs_get_mem(fs->blocksize, &buf);
+               if (retval)
+                       return NULL;
+               bufsize = fs->blocksize;
+       }
+       blk = ext2fs_descriptor_block_loc2(fs, fs->super->s_first_data_block,
+                                          group / desc_per_blk);
+       retval = io_channel_read_blk(fs->io, blk, 1, buf);
+       if (retval)
+               return NULL;
+       ret_gdp = (struct ext2_group_desc *)
+               (buf + ((group % desc_per_blk) * desc_size));
+#ifdef WORDS_BIGENDIAN
+       ext2fs_swap_group_desc2(fs, ret_gdp);
+#endif
+       return ret_gdp;
 }
 
 /* Do the same but as an ext4 group desc for internal use here */
index 9823613760a94389028c70e2618fd6f1f1e68bde..2c5b0f26f61dcde4552ab341c875daf135a39d7c 100644 (file)
@@ -358,20 +358,31 @@ static errcode_t ext2fs_dirent_csum_set(ext2_filsys fs, ext2_ino_t inum,
        return 0;
 }
 
-static errcode_t ext2fs_dx_csum(ext2_filsys fs, ext2_ino_t inum,
-                               struct ext2_dir_entry *dirent,
-                               __u32 *crc, int count_offset, int count,
-                               struct ext2_dx_tail *t)
+errcode_t ext2fs_dx_csum(ext2_filsys fs, ext2_ino_t inum,
+                        struct ext2_dir_entry *dirent,
+                        __u32 *crc, struct ext2_dx_tail **ret_t)
 {
        errcode_t retval;
        char *buf = (char *)dirent;
        int size;
-       __u32 old_csum, gen;
+       __u32 gen, dummy_csum = 0;
        struct ext2_inode inode;
+       struct ext2_dx_tail *t;
+       struct ext2_dx_countlimit *c;
+       int count_offset, limit, count;
+
+       retval = __get_dx_countlimit(fs, dirent, &c, &count_offset, 1);
+       if (retval)
+               return retval;
+       limit = ext2fs_le16_to_cpu(c->limit);
+       count = ext2fs_le16_to_cpu(c->count);
+       if (count_offset + (limit * sizeof(struct ext2_dx_entry)) >
+           fs->blocksize - sizeof(struct ext2_dx_tail))
+               return EXT2_ET_DIR_NO_SPACE_FOR_CSUM;
+       /* htree structs are accessed in LE order */
+       t = (struct ext2_dx_tail *)(((struct ext2_dx_entry *)c) + limit);
 
        size = count_offset + (count * sizeof(struct ext2_dx_entry));
-       old_csum = t->dt_checksum;
-       t->dt_checksum = 0;
 
        retval = ext2fs_read_inode(fs, inum, &inode);
        if (retval)
@@ -383,10 +394,11 @@ static errcode_t ext2fs_dx_csum(ext2_filsys fs, ext2_ino_t inum,
                                sizeof(inum));
        *crc = ext2fs_crc32c_le(*crc, (unsigned char *)&gen, sizeof(gen));
        *crc = ext2fs_crc32c_le(*crc, (unsigned char *)buf, size);
-       *crc = ext2fs_crc32c_le(*crc, (unsigned char *)t,
-                               sizeof(struct ext2_dx_tail));
-       t->dt_checksum = old_csum;
+       *crc = ext2fs_crc32c_le(*crc, (unsigned char *)t, 4);
+       *crc = ext2fs_crc32c_le(*crc, (unsigned char *)&dummy_csum, 4);
 
+       if (ret_t)
+               *ret_t = t;
        return 0;
 }
 
@@ -395,22 +407,9 @@ static int ext2fs_dx_csum_verify(ext2_filsys fs, ext2_ino_t inum,
 {
        __u32 calculated;
        errcode_t retval;
-       struct ext2_dx_countlimit *c;
        struct ext2_dx_tail *t;
-       int count_offset, limit, count;
 
-       retval = __get_dx_countlimit(fs, dirent, &c, &count_offset, 1);
-       if (retval)
-               return 1;
-       limit = ext2fs_le16_to_cpu(c->limit);
-       count = ext2fs_le16_to_cpu(c->count);
-       if (count_offset + (limit * sizeof(struct ext2_dx_entry)) >
-           fs->blocksize - sizeof(struct ext2_dx_tail))
-               return 0;
-       /* htree structs are accessed in LE order */
-       t = (struct ext2_dx_tail *)(((struct ext2_dx_entry *)c) + limit);
-       retval = ext2fs_dx_csum(fs, inum, dirent, &calculated, count_offset,
-                               count, t);
+       retval = ext2fs_dx_csum(fs, inum, dirent, &calculated, &t);
        if (retval)
                return 0;
 
@@ -422,22 +421,9 @@ static errcode_t ext2fs_dx_csum_set(ext2_filsys fs, ext2_ino_t inum,
 {
        __u32 crc;
        errcode_t retval = 0;
-       struct ext2_dx_countlimit *c;
        struct ext2_dx_tail *t;
-       int count_offset, limit, count;
 
-       retval = __get_dx_countlimit(fs, dirent, &c, &count_offset, 1);
-       if (retval)
-               return retval;
-       limit = ext2fs_le16_to_cpu(c->limit);
-       count = ext2fs_le16_to_cpu(c->count);
-       if (count_offset + (limit * sizeof(struct ext2_dx_entry)) >
-           fs->blocksize - sizeof(struct ext2_dx_tail))
-               return EXT2_ET_DIR_NO_SPACE_FOR_CSUM;
-       t = (struct ext2_dx_tail *)(((struct ext2_dx_entry *)c) + limit);
-
-       /* htree structs are accessed in LE order */
-       retval = ext2fs_dx_csum(fs, inum, dirent, &crc, count_offset, count, t);
+       retval = ext2fs_dx_csum(fs, inum, dirent, &crc, &t);
        if (retval)
                return retval;
        t->dt_checksum = ext2fs_cpu_to_le32(crc);
index febcb476a996b497dea0122aa26a055d6e3cce31..3165b3895222228b72f14c77baf905456877d175 100644 (file)
@@ -811,6 +811,7 @@ struct ext2_super_block {
 #define EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP     0x0100
 #define EXT4_FEATURE_COMPAT_SPARSE_SUPER2      0x0200
 #define EXT4_FEATURE_COMPAT_FAST_COMMIT                0x0400
+#define EXT4_FEATURE_COMPAT_STABLE_INODES      0x0800
 
 
 #define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER    0x0001
@@ -913,6 +914,7 @@ EXT4_FEATURE_COMPAT_FUNCS(lazy_bg,          2, LAZY_BG)
 EXT4_FEATURE_COMPAT_FUNCS(exclude_bitmap,      2, EXCLUDE_BITMAP)
 EXT4_FEATURE_COMPAT_FUNCS(sparse_super2,       4, SPARSE_SUPER2)
 EXT4_FEATURE_COMPAT_FUNCS(fast_commit,         4, FAST_COMMIT)
+EXT4_FEATURE_COMPAT_FUNCS(stable_inodes,       4, STABLE_INODES)
 
 EXT4_FEATURE_RO_COMPAT_FUNCS(sparse_super,     2, SPARSE_SUPER)
 EXT4_FEATURE_RO_COMPAT_FUNCS(large_file,       2, LARGE_FILE)
index cbf0c6f4db68c9bd10f3ea648f324012fd43a044..93ecf29c568da2607030632560f2186a9c38f3a6 100644 (file)
@@ -611,7 +611,9 @@ typedef struct ext2_icount *ext2_icount_t;
                                         EXT2_FEATURE_COMPAT_RESIZE_INODE|\
                                         EXT2_FEATURE_COMPAT_DIR_INDEX|\
                                         EXT2_FEATURE_COMPAT_EXT_ATTR|\
-                                        EXT4_FEATURE_COMPAT_SPARSE_SUPER2)
+                                        EXT4_FEATURE_COMPAT_SPARSE_SUPER2|\
+                                        EXT4_FEATURE_COMPAT_FAST_COMMIT|\
+                                        EXT4_FEATURE_COMPAT_STABLE_INODES)
 
 #ifdef CONFIG_MMP
 #define EXT4_LIB_INCOMPAT_MMP          EXT4_FEATURE_INCOMPAT_MMP
@@ -1082,6 +1084,9 @@ extern errcode_t ext2fs_get_dx_countlimit(ext2_filsys fs,
                                          struct ext2_dir_entry *dirent,
                                          struct ext2_dx_countlimit **cc,
                                          int *offset);
+extern errcode_t ext2fs_dx_csum(ext2_filsys fs, ext2_ino_t inum,
+                               struct ext2_dir_entry *dirent,
+                               __u32 *crc, struct ext2_dx_tail **ret_t);
 extern errcode_t ext2fs_extent_block_csum_set(ext2_filsys fs,
                                              ext2_ino_t inum,
                                              struct ext3_extent_header *eh);
index 20bb99aea999b35dde0d4a7ff6796f74153c450b..f7f8df423aa7ae37b5ac907760cc78034bf49184 100644 (file)
@@ -245,10 +245,10 @@ errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd,
         * if needed
         */
        groups_per_block = EXT2_DESC_PER_BLOCK(fs->super);
-       gdp = (struct ext2_group_desc *) cp;
        for (j=0; j < groups_per_block*fs->desc_blocks; j++) {
                gdp = ext2fs_group_desc(fs, fs->group_desc, j);
-               ext2fs_swap_group_desc2(fs, gdp);
+               if (gdp)
+                       ext2fs_swap_group_desc2(fs, gdp);
        }
 #endif
 
@@ -257,10 +257,10 @@ errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd,
 
 #ifdef WORDS_BIGENDIAN
        groups_per_block = EXT2_DESC_PER_BLOCK(fs->super);
-       gdp = (struct ext2_group_desc *) cp;
        for (j=0; j < groups_per_block*fs->desc_blocks; j++) {
                gdp = ext2fs_group_desc(fs, fs->group_desc, j);
-               ext2fs_swap_group_desc2(fs, gdp);
+               if (gdp)
+                       ext2fs_swap_group_desc2(fs, gdp);
        }
 #endif
 
index f1a3f968e86fddb0ccb3749593ff289199ae8008..2bda521d2103448628e270223f1d55a615b5613d 100644 (file)
 #define KERN_ERR ""
 #define KERN_DEBUG ""
 
-#define READ 0
-#define WRITE 1
+#define REQ_OP_READ 0
+#define REQ_OP_WRITE 1
 
-#define cpu_to_be32(n) htonl(n)
-#define be32_to_cpu(n) ntohl(n)
-#define cpu_to_be16(n) htons(n)
-#define be16_to_cpu(n) ntohs(n)
+#define cpu_to_be16(x) ext2fs_cpu_to_be16(x)
+#define cpu_to_be32(x) ext2fs_cpu_to_be32(x)
+#define cpu_to_be64(x) ext2fs_cpu_to_be64(x)
+
+#define be16_to_cpu(x) ext2fs_be16_to_cpu(x)
+#define be32_to_cpu(x) ext2fs_be32_to_cpu(x)
+#define be64_to_cpu(x) ext2fs_be64_to_cpu(x)
 
 typedef unsigned int tid_t;
 typedef struct journal_s journal_t;
@@ -32,14 +35,14 @@ typedef struct kdev_s *kdev_t;
 struct buffer_head;
 struct inode;
 
+typedef unsigned int gfp_t;
 #define GFP_KERNEL     0
-#define JFS_TAG_SIZE32 JBD_TAG_SIZE32
-#define JFS_BARRIER    0
+#define GFP_NOFS       0
+#define __GFP_NOFAIL   0
+#define JBD2_TAG_SIZE32        JBD_TAG_SIZE32
+#define JBD2_BARRIER   0
 typedef __u64 u64;
-#define JFS_CRC32_CHKSUM       JBD2_CRC32_CHKSUM
-#define JFS_CRC32_CHKSUM_SIZE  JBD2_CRC32_CHKSUM_SIZE
 #define put_bh(x)      brelse(x)
-#define be64_to_cpu(x) ext2fs_be64_to_cpu(x)
 
 static inline __u32 jbd2_chksum(journal_t *j EXT2FS_ATTR((unused)),
                                __u32 crc, const void *address,
@@ -51,7 +54,6 @@ static inline __u32 jbd2_chksum(journal_t *j EXT2FS_ATTR((unused)),
 #define spin_lock_init(x)
 #define spin_lock(x)
 #define spin_unlock(x)
-#define yield()
 #define SLAB_HWCACHE_ALIGN     0
 #define SLAB_TEMPORARY         0
 #define KMEM_CACHE(__struct, __flags) kmem_cache_create(#__struct,\
@@ -60,6 +62,7 @@ static inline __u32 jbd2_chksum(journal_t *j EXT2FS_ATTR((unused)),
 
 #define blkdev_issue_flush(kdev, a, b) sync_blockdev(kdev)
 #define is_power_of_2(x)       ((x) != 0 && (((x) & ((x) - 1)) == 0))
+#define pr_emerg(fmt)
 
 struct journal_s
 {
index a7507b57b94511ba81f98fcd879752df41423731..cb1bc30843160ff3f003a38502cd060b488d826a 100644 (file)
@@ -24,7 +24,7 @@
 #define __FUNCTION__ ""
 #endif
 
-#define journal_oom_retry 1
+#define journal_oom_retry 0
 
 #ifdef __STDC__
 #ifdef CONFIG_JBD_DEBUG
@@ -73,13 +73,13 @@ extern void * __jbd_kmalloc (char *where, size_t size, int flags, int retry);
 #define jbd_rep_kmalloc(size, flags) \
        __jbd_kmalloc(__FUNCTION__, (size), (flags), 1)
 
-#define JFS_MIN_JOURNAL_BLOCKS 1024
+#define JBD2_MIN_JOURNAL_BLOCKS 1024
 
 /*
  * Internal structures used by the logging mechanism:
  */
 
-#define JFS_MAGIC_NUMBER 0xc03b3998U /* The first 4 bytes of /dev/random! */
+#define JBD2_MAGIC_NUMBER 0xc03b3998U /* The first 4 bytes of /dev/random! */
 
 /*
  * On-disk structures
@@ -89,20 +89,20 @@ extern void * __jbd_kmalloc (char *where, size_t size, int flags, int retry);
  * Descriptor block types:
  */
 
-#define JFS_DESCRIPTOR_BLOCK   1
-#define JFS_COMMIT_BLOCK       2
-#define JFS_SUPERBLOCK_V1      3
-#define JFS_SUPERBLOCK_V2      4
-#define JFS_REVOKE_BLOCK       5
+#define JBD2_DESCRIPTOR_BLOCK  1
+#define JBD2_COMMIT_BLOCK      2
+#define JBD2_SUPERBLOCK_V1     3
+#define JBD2_SUPERBLOCK_V2     4
+#define JBD2_REVOKE_BLOCK      5
 
 /*
  * Standard header for all descriptor blocks:
  */
 typedef struct journal_header_s
 {
-       __u32           h_magic;
-       __u32           h_blocktype;
-       __u32           h_sequence;
+       __be32          h_magic;
+       __be32          h_blocktype;
+       __be32          h_sequence;
 } journal_header_t;
 
 /*
@@ -135,15 +135,15 @@ typedef struct journal_header_s
  * Checksum v1, v2, and v3 are mutually exclusive features.
  */
 struct commit_header {
-       __u32           h_magic;
-       __u32           h_blocktype;
-       __u32           h_sequence;
+       __be32          h_magic;
+       __be32          h_blocktype;
+       __be32          h_sequence;
        unsigned char   h_chksum_type;
        unsigned char   h_chksum_size;
        unsigned char   h_padding[2];
-       __u32           h_chksum[JBD2_CHECKSUM_BYTES];
-       __u64           h_commit_sec;
-       __u32           h_commit_nsec;
+       __be32          h_chksum[JBD2_CHECKSUM_BYTES];
+       __be64          h_commit_sec;
+       __be32          h_commit_nsec;
 };
 
 /*
@@ -151,22 +151,22 @@ struct commit_header {
  */
 typedef struct journal_block_tag3_s
 {
-       __u32           t_blocknr;      /* The on-disk block number */
-       __u32           t_flags;        /* See below */
-       __u32           t_blocknr_high; /* most-significant high 32bits. */
-       __u32           t_checksum;     /* crc32c(uuid+seq+block) */
+       __be32          t_blocknr;      /* The on-disk block number */
+       __be32          t_flags;        /* See below */
+       __be32          t_blocknr_high; /* most-significant high 32bits. */
+       __be32          t_checksum;     /* crc32c(uuid+seq+block) */
 } journal_block_tag3_t;
 
 typedef struct journal_block_tag_s
 {
-       __u32           t_blocknr;      /* The on-disk block number */
-       __u16           t_checksum;     /* truncated crc32c(uuid+seq+block) */
-       __u16           t_flags;        /* See below */
-       __u32           t_blocknr_high; /* most-significant high 32bits. */
+       __be32          t_blocknr;      /* The on-disk block number */
+       __be16          t_checksum;     /* truncated crc32c(uuid+seq+block) */
+       __be16          t_flags;        /* See below */
+       __be32          t_blocknr_high; /* most-significant high 32bits. */
 } journal_block_tag_t;
 
-/* Tail of descriptor block, for checksumming */
-struct journal_block_tail {
+/* Tail of descriptor or revoke block, for checksumming */
+struct jbd2_journal_block_tail {
        __be32          t_checksum;
 };
 
@@ -177,24 +177,19 @@ struct journal_block_tail {
 typedef struct journal_revoke_header_s
 {
        journal_header_t r_header;
-       int              r_count;       /* Count of bytes used in the block */
-} journal_revoke_header_t;
-
-/* Tail of revoke block, for checksumming */
-struct journal_revoke_tail {
-       __be32          r_checksum;
-};
+       __be32           r_count;       /* Count of bytes used in the block */
+} jbd2_journal_revoke_header_t;
 
 /* Definitions for the journal tag flags word: */
-#define JFS_FLAG_ESCAPE                1       /* on-disk block is escaped */
-#define JFS_FLAG_SAME_UUID     2       /* block has same uuid as previous */
-#define JFS_FLAG_DELETED       4       /* block deleted by this transaction */
-#define JFS_FLAG_LAST_TAG      8       /* last tag in this descriptor block */
+#define JBD2_FLAG_ESCAPE               1       /* on-disk block is escaped */
+#define JBD2_FLAG_SAME_UUID    2       /* block has same uuid as previous */
+#define JBD2_FLAG_DELETED      4       /* block deleted by this transaction */
+#define JBD2_FLAG_LAST_TAG     8       /* last tag in this descriptor block */
 
 
 #define UUID_SIZE 16
-#define JFS_USERS_MAX 48
-#define JFS_USERS_SIZE (UUID_SIZE * JFS_USERS_MAX)
+#define JBD2_USERS_MAX 48
+#define JBD2_USERS_SIZE (UUID_SIZE * JBD2_USERS_MAX)
 /*
  * The journal superblock.  All fields are in big-endian byte order.
  */
@@ -205,14 +200,14 @@ typedef struct journal_superblock_s
 
 /* 0x000C */
        /* Static information describing the journal */
-       __u32   s_blocksize;            /* journal device blocksize */
-       __u32   s_maxlen;               /* total blocks in journal file */
-       __u32   s_first;                /* first block of log information */
+       __be32  s_blocksize;            /* journal device blocksize */
+       __be32  s_maxlen;               /* total blocks in journal file */
+       __be32  s_first;                /* first block of log information */
 
 /* 0x0018 */
        /* Dynamic information describing the current state of the log */
-       __u32   s_sequence;             /* first commit ID expected in log */
-       __u32   s_start;                /* blocknr of start of log */
+       __be32  s_sequence;             /* first commit ID expected in log */
+       __be32  s_start;                /* blocknr of start of log */
 
 /* 0x0020 */
        /* Error value, as set by journal_abort(). */
@@ -220,63 +215,63 @@ typedef struct journal_superblock_s
 
 /* 0x0024 */
        /* Remaining fields are only valid in a version-2 superblock */
-       __u32   s_feature_compat;       /* compatible feature set */
-       __u32   s_feature_incompat;     /* incompatible feature set */
-       __u32   s_feature_ro_compat;    /* readonly-compatible feature set */
+       __be32  s_feature_compat;       /* compatible feature set */
+       __be32  s_feature_incompat;     /* incompatible feature set */
+       __be32  s_feature_ro_compat;    /* readonly-compatible feature set */
 /* 0x0030 */
        __u8    s_uuid[16];             /* 128-bit uuid for journal */
 
 /* 0x0040 */
-       __u32   s_nr_users;             /* Nr of filesystems sharing log */
+       __be32  s_nr_users;             /* Nr of filesystems sharing log */
 
-       __u32   s_dynsuper;             /* Blocknr of dynamic superblock copy*/
+       __be32  s_dynsuper;             /* Blocknr of dynamic superblock copy*/
 
 /* 0x0048 */
-       __u32   s_max_transaction;      /* Limit of journal blocks per trans.*/
-       __u32   s_max_trans_data;       /* Limit of data blocks per trans. */
+       __be32  s_max_transaction;      /* Limit of journal blocks per trans.*/
+       __be32  s_max_trans_data;       /* Limit of data blocks per trans. */
 
 /* 0x0050 */
        __u8    s_checksum_type;        /* checksum type */
        __u8    s_padding2[3];
-       __u32   s_padding[42];
-       __u32   s_checksum;             /* crc32c(superblock) */
+       __be32  s_padding[42];
+       __be32  s_checksum;             /* crc32c(superblock) */
 
 /* 0x0100 */
-       __u8    s_users[JFS_USERS_SIZE];                /* ids of all fs'es sharing the log */
+       __u8    s_users[JBD2_USERS_SIZE];               /* ids of all fs'es sharing the log */
 
 /* 0x0400 */
 } journal_superblock_t;
 
-#define JFS_HAS_COMPAT_FEATURE(j,mask)                                 \
+#define JBD2_HAS_COMPAT_FEATURE(j,mask)                                        \
        ((j)->j_format_version >= 2 &&                                  \
         ((j)->j_superblock->s_feature_compat & ext2fs_cpu_to_be32((mask))))
-#define JFS_HAS_RO_COMPAT_FEATURE(j,mask)                              \
+#define JBD2_HAS_RO_COMPAT_FEATURE(j,mask)                             \
        ((j)->j_format_version >= 2 &&                                  \
         ((j)->j_superblock->s_feature_ro_compat & ext2fs_cpu_to_be32((mask))))
-#define JFS_HAS_INCOMPAT_FEATURE(j,mask)                               \
+#define JBD2_HAS_INCOMPAT_FEATURE(j,mask)                              \
        ((j)->j_format_version >= 2 &&                                  \
         ((j)->j_superblock->s_feature_incompat & ext2fs_cpu_to_be32((mask))))
 
-#define JFS_FEATURE_COMPAT_CHECKSUM            0x00000001
+#define JBD2_FEATURE_COMPAT_CHECKSUM           0x00000001
 
-#define JFS_FEATURE_INCOMPAT_REVOKE            0x00000001
-#define JFS_FEATURE_INCOMPAT_64BIT             0x00000002
-#define JFS_FEATURE_INCOMPAT_ASYNC_COMMIT      0x00000004
-#define JFS_FEATURE_INCOMPAT_CSUM_V2           0x00000008
-#define JFS_FEATURE_INCOMPAT_CSUM_V3           0x00000010
+#define JBD2_FEATURE_INCOMPAT_REVOKE           0x00000001
+#define JBD2_FEATURE_INCOMPAT_64BIT            0x00000002
+#define JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT     0x00000004
+#define JBD2_FEATURE_INCOMPAT_CSUM_V2          0x00000008
+#define JBD2_FEATURE_INCOMPAT_CSUM_V3          0x00000010
 
 /* Features known to this kernel version: */
-#define JFS_KNOWN_COMPAT_FEATURES      0
-#define JFS_KNOWN_ROCOMPAT_FEATURES    0
-#define JFS_KNOWN_INCOMPAT_FEATURES    (JFS_FEATURE_INCOMPAT_REVOKE|\
-                                        JFS_FEATURE_INCOMPAT_ASYNC_COMMIT|\
-                                        JFS_FEATURE_INCOMPAT_64BIT|\
-                                        JFS_FEATURE_INCOMPAT_CSUM_V2|\
-                                        JFS_FEATURE_INCOMPAT_CSUM_V3)
+#define JBD2_KNOWN_COMPAT_FEATURES     0
+#define JBD2_KNOWN_ROCOMPAT_FEATURES   0
+#define JBD2_KNOWN_INCOMPAT_FEATURES   (JBD2_FEATURE_INCOMPAT_REVOKE|\
+                                        JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT| \
+                                        JBD2_FEATURE_INCOMPAT_64BIT|\
+                                        JBD2_FEATURE_INCOMPAT_CSUM_V2| \
+                                        JBD2_FEATURE_INCOMPAT_CSUM_V3)
 
 #ifdef NO_INLINE_FUNCS
 extern size_t journal_tag_bytes(journal_t *journal);
-extern int journal_has_csum_v2or3(journal_t *journal);
+extern int jbd2_journal_has_csum_v2or3(journal_t *journal);
 extern int tid_gt(tid_t x, tid_t y) EXT2FS_ATTR((unused));
 extern int tid_geq(tid_t x, tid_t y) EXT2FS_ATTR((unused));
 #endif
@@ -301,94 +296,94 @@ extern int tid_geq(tid_t x, tid_t y) EXT2FS_ATTR((unused));
 #endif /* INCLUDE_INLINE_FUNCS */
 
 /* journal feature predicate functions */
-#define JFS_FEATURE_COMPAT_FUNCS(name, flagname) \
-_INLINE_ int jfs_has_feature_##name(journal_t *j); \
-_INLINE_ int jfs_has_feature_##name(journal_t *j) \
+#define JBD2_FEATURE_COMPAT_FUNCS(name, flagname) \
+_INLINE_ int jbd2_has_feature_##name(journal_t *j); \
+_INLINE_ int jbd2_has_feature_##name(journal_t *j) \
 { \
        return ((j)->j_format_version >= 2 && \
                ((j)->j_superblock->s_feature_compat & \
-                ext2fs_cpu_to_be32(JFS_FEATURE_COMPAT_##flagname)) != 0); \
+                ext2fs_cpu_to_be32(JBD2_FEATURE_COMPAT_##flagname)) != 0); \
 } \
-_INLINE_ void jfs_set_feature_##name(journal_t *j); \
-_INLINE_ void jfs_set_feature_##name(journal_t *j) \
+_INLINE_ void jbd2_set_feature_##name(journal_t *j); \
+_INLINE_ void jbd2_set_feature_##name(journal_t *j) \
 { \
        (j)->j_superblock->s_feature_compat |= \
-               ext2fs_cpu_to_be32(JFS_FEATURE_COMPAT_##flagname); \
+               ext2fs_cpu_to_be32(JBD2_FEATURE_COMPAT_##flagname); \
 } \
-_INLINE_ void jfs_clear_feature_##name(journal_t *j); \
-_INLINE_ void jfs_clear_feature_##name(journal_t *j) \
+_INLINE_ void jbd2_clear_feature_##name(journal_t *j); \
+_INLINE_ void jbd2_clear_feature_##name(journal_t *j) \
 { \
        (j)->j_superblock->s_feature_compat &= \
-               ~ext2fs_cpu_to_be32(JFS_FEATURE_COMPAT_##flagname); \
+               ~ext2fs_cpu_to_be32(JBD2_FEATURE_COMPAT_##flagname); \
 }
 
-#define JFS_FEATURE_RO_COMPAT_FUNCS(name, flagname) \
-_INLINE_ int jfs_has_feature_##name(journal_t *j);     \
-_INLINE_ int jfs_has_feature_##name(journal_t *j) \
+#define JBD2_FEATURE_RO_COMPAT_FUNCS(name, flagname) \
+_INLINE_ int jbd2_has_feature_##name(journal_t *j);    \
+_INLINE_ int jbd2_has_feature_##name(journal_t *j) \
 { \
        return ((j)->j_format_version >= 2 && \
                ((j)->j_superblock->s_feature_ro_compat & \
-                ext2fs_cpu_to_be32(JFS_FEATURE_RO_COMPAT_##flagname)) != 0); \
+                ext2fs_cpu_to_be32(JBD2_FEATURE_RO_COMPAT_##flagname)) != 0); \
 } \
-_INLINE_ void jfs_set_feature_##name(journal_t *j); \
-_INLINE_ void jfs_set_feature_##name(journal_t *j) \
+_INLINE_ void jbd2_set_feature_##name(journal_t *j); \
+_INLINE_ void jbd2_set_feature_##name(journal_t *j) \
 { \
        (j)->j_superblock->s_feature_ro_compat |= \
-               ext2fs_cpu_to_be32(JFS_FEATURE_RO_COMPAT_##flagname); \
+               ext2fs_cpu_to_be32(JBD2_FEATURE_RO_COMPAT_##flagname); \
 } \
-_INLINE_ void jfs_clear_feature_##name(journal_t *j); \
-_INLINE_ void jfs_clear_feature_##name(journal_t *j) \
+_INLINE_ void jbd2_clear_feature_##name(journal_t *j); \
+_INLINE_ void jbd2_clear_feature_##name(journal_t *j) \
 { \
        (j)->j_superblock->s_feature_ro_compat &= \
-               ~ext2fs_cpu_to_be32(JFS_FEATURE_RO_COMPAT_##flagname); \
+               ~ext2fs_cpu_to_be32(JBD2_FEATURE_RO_COMPAT_##flagname); \
 }
 
-#define JFS_FEATURE_INCOMPAT_FUNCS(name, flagname) \
-_INLINE_ int jfs_has_feature_##name(journal_t *j); \
-_INLINE_ int jfs_has_feature_##name(journal_t *j) \
+#define JBD2_FEATURE_INCOMPAT_FUNCS(name, flagname) \
+_INLINE_ int jbd2_has_feature_##name(journal_t *j); \
+_INLINE_ int jbd2_has_feature_##name(journal_t *j) \
 { \
        return ((j)->j_format_version >= 2 && \
                ((j)->j_superblock->s_feature_incompat & \
-                ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_##flagname)) != 0); \
+                ext2fs_cpu_to_be32(JBD2_FEATURE_INCOMPAT_##flagname)) != 0); \
 } \
-_INLINE_ void jfs_set_feature_##name(journal_t *j); \
-_INLINE_ void jfs_set_feature_##name(journal_t *j) \
+_INLINE_ void jbd2_set_feature_##name(journal_t *j); \
+_INLINE_ void jbd2_set_feature_##name(journal_t *j) \
 { \
        (j)->j_superblock->s_feature_incompat |= \
-               ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_##flagname); \
+               ext2fs_cpu_to_be32(JBD2_FEATURE_INCOMPAT_##flagname); \
 } \
-_INLINE_ void jfs_clear_feature_##name(journal_t *j); \
-_INLINE_ void jfs_clear_feature_##name(journal_t *j) \
+_INLINE_ void jbd2_clear_feature_##name(journal_t *j); \
+_INLINE_ void jbd2_clear_feature_##name(journal_t *j) \
 { \
        (j)->j_superblock->s_feature_incompat &= \
-               ~ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_##flagname); \
+               ~ext2fs_cpu_to_be32(JBD2_FEATURE_INCOMPAT_##flagname); \
 }
 
 #else
-#define JFS_FEATURE_COMPAT_FUNCS(name, flagname) \
-extern int jfs_has_feature_##name(journal_t *j); \
-extern void jfs_set_feature_##name(journal_t *j); \
-extern void jfs_clear_feature_##name(journal_t *j);
+#define JBD2_FEATURE_COMPAT_FUNCS(name, flagname) \
+extern int jbd2_has_feature_##name(journal_t *j); \
+extern void jbd2_set_feature_##name(journal_t *j); \
+extern void jbd2_clear_feature_##name(journal_t *j);
 
-#define JFS_FEATURE_RO_COMPAT_FUNCS(name, flagname) \
-extern int jfs_has_feature_##name(journal_t *j); \
-extern void jfs_set_feature_##name(journal_t *j); \
-extern void jfs_clear_feature_##name(journal_t *j);
+#define JBD2_FEATURE_RO_COMPAT_FUNCS(name, flagname) \
+extern int jbd2_has_feature_##name(journal_t *j); \
+extern void jbd2_set_feature_##name(journal_t *j); \
+extern void jbd2_clear_feature_##name(journal_t *j);
 
-#define JFS_FEATURE_INCOMPAT_FUNCS(name, flagname) \
-extern int jfs_has_feature_##name(journal_t *j); \
-extern void jfs_set_feature_##name(journal_t *j); \
-extern void jfs_clear_feature_##name(journal_t *j);
+#define JBD2_FEATURE_INCOMPAT_FUNCS(name, flagname) \
+extern int jbd2_has_feature_##name(journal_t *j); \
+extern void jbd2_set_feature_##name(journal_t *j); \
+extern void jbd2_clear_feature_##name(journal_t *j);
 
 #endif /* (defined(E2FSCK_INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS)) */
 
-JFS_FEATURE_COMPAT_FUNCS(checksum,             CHECKSUM)
+JBD2_FEATURE_COMPAT_FUNCS(checksum,            CHECKSUM)
 
-JFS_FEATURE_INCOMPAT_FUNCS(revoke,             REVOKE)
-JFS_FEATURE_INCOMPAT_FUNCS(64bit,              64BIT)
-JFS_FEATURE_INCOMPAT_FUNCS(async_commit,       ASYNC_COMMIT)
-JFS_FEATURE_INCOMPAT_FUNCS(csum2,              CSUM_V2)
-JFS_FEATURE_INCOMPAT_FUNCS(csum3,              CSUM_V3)
+JBD2_FEATURE_INCOMPAT_FUNCS(revoke,            REVOKE)
+JBD2_FEATURE_INCOMPAT_FUNCS(64bit,             64BIT)
+JBD2_FEATURE_INCOMPAT_FUNCS(async_commit,      ASYNC_COMMIT)
+JBD2_FEATURE_INCOMPAT_FUNCS(csum2,             CSUM_V2)
+JBD2_FEATURE_INCOMPAT_FUNCS(csum3,             CSUM_V3)
 
 #if (defined(E2FSCK_INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS))
 /*
@@ -398,23 +393,23 @@ _INLINE_ size_t journal_tag_bytes(journal_t *journal)
 {
        size_t sz;
 
-       if (jfs_has_feature_csum3(journal))
+       if (jbd2_has_feature_csum3(journal))
                return sizeof(journal_block_tag3_t);
 
        sz = sizeof(journal_block_tag_t);
 
-       if (jfs_has_feature_csum2(journal))
+       if (jbd2_has_feature_csum2(journal))
                sz += sizeof(__u16);
 
-       if (jfs_has_feature_64bit(journal))
+       if (jbd2_has_feature_64bit(journal))
                return sz;
 
        return sz - sizeof(__u32);
 }
 
-_INLINE_ int journal_has_csum_v2or3(journal_t *journal)
+_INLINE_ int jbd2_journal_has_csum_v2or3(journal_t *journal)
 {
-       if (jfs_has_feature_csum2(journal) || jfs_has_feature_csum3(journal))
+       if (jbd2_has_feature_csum2(journal) || jbd2_has_feature_csum3(journal))
                return 1;
 
        return 0;
index a90e80e0bc21818d5c9baa00c0a94b11aa97f32d..f47f71e62534e6f8c1e73d041f953dc8f1d449d1 100644 (file)
@@ -50,7 +50,7 @@ errcode_t ext2fs_create_journal_superblock(ext2_filsys fs,
        errcode_t               retval;
        journal_superblock_t    *jsb;
 
-       if (num_blocks < JFS_MIN_JOURNAL_BLOCKS)
+       if (num_blocks < JBD2_MIN_JOURNAL_BLOCKS)
                return EXT2_ET_JOURNAL_TOO_SMALL;
 
        if ((retval = ext2fs_get_mem(fs->blocksize, &jsb)))
@@ -58,11 +58,11 @@ errcode_t ext2fs_create_journal_superblock(ext2_filsys fs,
 
        memset (jsb, 0, fs->blocksize);
 
-       jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
+       jsb->s_header.h_magic = htonl(JBD2_MAGIC_NUMBER);
        if (flags & EXT2_MKJOURNAL_V1_SUPER)
-               jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V1);
+               jsb->s_header.h_blocktype = htonl(JBD2_SUPERBLOCK_V1);
        else
-               jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
+               jsb->s_header.h_blocktype = htonl(JBD2_SUPERBLOCK_V2);
        jsb->s_blocksize = htonl(fs->blocksize);
        jsb->s_maxlen = htonl(num_blocks);
        jsb->s_nr_users = htonl(1);
@@ -392,8 +392,8 @@ errcode_t ext2fs_add_journal_device(ext2_filsys fs, ext2_filsys journal_dev)
                return retval;
 
        jsb = (journal_superblock_t *) buf;
-       if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) ||
-           (jsb->s_header.h_blocktype != (unsigned) ntohl(JFS_SUPERBLOCK_V2)))
+       if ((jsb->s_header.h_magic != (unsigned) ntohl(JBD2_MAGIC_NUMBER)) ||
+           (jsb->s_header.h_blocktype != (unsigned) ntohl(JBD2_SUPERBLOCK_V2)))
                return EXT2_ET_NO_JOURNAL_SB;
 
        if (ntohl(jsb->s_blocksize) != (unsigned long) fs->blocksize)
@@ -401,7 +401,7 @@ errcode_t ext2fs_add_journal_device(ext2_filsys fs, ext2_filsys journal_dev)
 
        /* Check and see if this filesystem has already been added */
        nr_users = ntohl(jsb->s_nr_users);
-       if (nr_users > JFS_USERS_MAX)
+       if (nr_users > JBD2_USERS_MAX)
                return EXT2_ET_CORRUPT_JOURNAL_SB;
        for (i=0; i < nr_users; i++) {
                if (memcmp(fs->super->s_uuid,
@@ -572,7 +572,7 @@ main(int argc, char **argv)
                exit(1);
        }
 
-       retval = ext2fs_add_journal_inode(fs, JFS_MIN_JOURNAL_BLOCKS, 0);
+       retval = ext2fs_add_journal_inode(fs, JBD2_MIN_JOURNAL_BLOCKS, 0);
        if (retval) {
                com_err(argv[0], retval, "while adding journal to %s",
                        device_name);
index 51b54a4492eaf67c2d82613ce46fcb7d1b0c0901..3331452df910c86183a1301c95569f47632da27c 100644 (file)
@@ -393,6 +393,8 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
        }
        fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count,
                                          EXT2_DESC_PER_BLOCK(fs->super));
+       if (flags & EXT2_FLAG_SUPER_ONLY)
+               goto skip_read_bg;
        retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize,
                                &fs->group_desc);
        if (retval)
@@ -433,7 +435,8 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
                gdp = (struct ext2_group_desc *) dest;
                for (j=0; j < groups_per_block*first_meta_bg; j++) {
                        gdp = ext2fs_group_desc(fs, fs->group_desc, j);
-                       ext2fs_swap_group_desc2(fs, gdp);
+                       if (gdp)
+                               ext2fs_swap_group_desc2(fs, gdp);
                }
 #endif
                dest += fs->blocksize*first_meta_bg;
@@ -453,7 +456,8 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
                for (j=0; j < groups_per_block; j++) {
                        gdp = ext2fs_group_desc(fs, fs->group_desc,
                                                i * groups_per_block + j);
-                       ext2fs_swap_group_desc2(fs, gdp);
+                       if (gdp)
+                               ext2fs_swap_group_desc2(fs, gdp);
                }
 #endif
                dest += fs->blocksize;
@@ -479,7 +483,7 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
                if (fs->flags & EXT2_FLAG_RW)
                        ext2fs_mark_super_dirty(fs);
        }
-
+skip_read_bg:
        if (ext2fs_has_feature_mmp(fs->super) &&
            !(flags & EXT2_FLAG_SKIP_MMP) &&
            (flags & (EXT2_FLAG_RW | EXT2_FLAG_EXCLUSIVE))) {
index 384ce925378e6a47c306bbb4461f6405da5b4e58..9a6f586ec068c76ff3936112f820dbc51e0e21b7 100644 (file)
@@ -387,7 +387,7 @@ static void print_inline_journal_information(ext2_filsys fs)
        }
        ext2fs_file_close(journal_file);
        jsb = (journal_superblock_t *) buf;
-       if (be32_to_cpu(jsb->s_header.h_magic) != JFS_MAGIC_NUMBER) {
+       if (be32_to_cpu(jsb->s_header.h_magic) != JBD2_MAGIC_NUMBER) {
                fprintf(stderr, "%s",
                        _("Journal superblock magic number invalid!\n"));
                exit(1);
@@ -410,9 +410,9 @@ static void print_journal_information(ext2_filsys fs)
                exit(1);
        }
        jsb = (journal_superblock_t *) buf;
-       if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) ||
+       if ((jsb->s_header.h_magic != (unsigned) ntohl(JBD2_MAGIC_NUMBER)) ||
            (jsb->s_header.h_blocktype !=
-            (unsigned) ntohl(JFS_SUPERBLOCK_V2))) {
+            (unsigned) ntohl(JBD2_SUPERBLOCK_V2))) {
                com_err(program_name, 0, "%s",
                        _("Couldn't find journal superblock magic numbers"));
                exit(1);
@@ -666,6 +666,8 @@ int main (int argc, char ** argv)
                flags |= EXT2_FLAG_FORCE;
        if (image_dump)
                flags |= EXT2_FLAG_IMAGE_FILE;
+       if (header_only)
+               flags |= EXT2_FLAG_SUPER_ONLY;
 try_open_again:
        if (use_superblock && !use_blocksize) {
                for (use_blocksize = EXT2_MIN_BLOCK_SIZE;
index 3bc7ada3b30781daf39e0deb129ea7ea82a3eff0..1a0c9d54f5893a9a71b3a269fba926002e07ce64 100644 (file)
@@ -48,6 +48,9 @@ pretend to be root for permission checks
 \fB-o\fR no_default_opts
 do not include default fuse options
 .TP
+\fB-o\fR norecovery
+do not replay the journal and mount the file system read-only
+.TP
 \fB-o\fR fuse2fs_debug
 enable fuse2fs debugging
 .SS "FUSE options:"
index 68ddddd3bed863fdbeedc93bba874f999afb65b2..b385d3393651f9d299edd58447c519723ced4341 100644 (file)
@@ -324,6 +324,7 @@ struct fuse2fs {
        int minixdf;
        int fakeroot;
        int alloc_all_blocks;
+       int norecovery;
        FILE *err_fp;
        unsigned int next_generation;
 };
@@ -3657,6 +3658,7 @@ static struct fuse_opt fuse2fs_opts[] = {
        FUSE2FS_OPT("fakeroot",         fakeroot,               1),
        FUSE2FS_OPT("fuse2fs_debug",    debug,                  1),
        FUSE2FS_OPT("no_default_opts",  no_default_opts,        1),
+       FUSE2FS_OPT("norecovery",       norecovery,             1),
 
        FUSE_OPT_KEY("-V",             FUSE2FS_VERSION),
        FUSE_OPT_KEY("--version",      FUSE2FS_VERSION),
@@ -3695,6 +3697,7 @@ static int fuse2fs_opt_proc(void *data, const char *arg,
        "    -o minixdf             minix-style df\n"
        "    -o fakeroot            pretend to be root for permission checks\n"
        "    -o no_default_opts     do not include default fuse options\n"
+       "    -o norecovery          don't replay the journal (implies ro)\n"
        "    -o fuse2fs_debug       enable fuse2fs debugging\n"
        "\n",
                        outargs->argv[0]);
@@ -3736,6 +3739,8 @@ int main(int argc, char *argv[])
                exit(1);
        }
 
+       if (fctx.norecovery)
+               fctx.ro = 1;
        if (fctx.ro)
                printf("%s", _("Mounting read-only.\n"));
 
@@ -3783,7 +3788,11 @@ int main(int argc, char *argv[])
        ret = 3;
 
        if (ext2fs_has_feature_journal_needs_recovery(global_fs->super)) {
-               if (!fctx.ro) {
+               if (fctx.norecovery) {
+                       printf(_("%s: mounting read-only without "
+                                "recovering journal\n"),
+                              fctx.device);
+               } else if (!fctx.ro) {
                        printf(_("%s: recovering journal\n"), fctx.device);
                        err = ext2fs_run_ext3_journal(&global_fs);
                        if (err) {
index 30e353d335c3e018c8dec94c0f36ca14f7fbc7f9..be38d2c4f14b317828a6c3c71749bd829c990012 100644 (file)
@@ -1143,7 +1143,9 @@ static __u32 ok_features[3] = {
                EXT2_FEATURE_COMPAT_RESIZE_INODE |
                EXT2_FEATURE_COMPAT_DIR_INDEX |
                EXT2_FEATURE_COMPAT_EXT_ATTR |
-               EXT4_FEATURE_COMPAT_SPARSE_SUPER2,
+               EXT4_FEATURE_COMPAT_SPARSE_SUPER2 |
+               EXT4_FEATURE_COMPAT_FAST_COMMIT |
+               EXT4_FEATURE_COMPAT_STABLE_INODES,
        /* Incompat */
        EXT2_FEATURE_INCOMPAT_FILETYPE|
                EXT3_FEATURE_INCOMPAT_EXTENTS|
index 301cf3880724458b382a391921a91c6fd25d82ec..a0448f63d1d5f31289254bb115dd5de483de875f 100644 (file)
@@ -149,7 +149,9 @@ static void usage(void)
 static __u32 ok_features[3] = {
        /* Compat */
        EXT3_FEATURE_COMPAT_HAS_JOURNAL |
-               EXT2_FEATURE_COMPAT_DIR_INDEX,
+               EXT2_FEATURE_COMPAT_DIR_INDEX |
+               EXT4_FEATURE_COMPAT_FAST_COMMIT |
+               EXT4_FEATURE_COMPAT_STABLE_INODES,
        /* Incompat */
        EXT2_FEATURE_INCOMPAT_FILETYPE |
                EXT3_FEATURE_INCOMPAT_EXTENTS |
@@ -178,7 +180,9 @@ static __u32 clear_ok_features[3] = {
        /* Compat */
        EXT3_FEATURE_COMPAT_HAS_JOURNAL |
                EXT2_FEATURE_COMPAT_RESIZE_INODE |
-               EXT2_FEATURE_COMPAT_DIR_INDEX,
+               EXT2_FEATURE_COMPAT_DIR_INDEX |
+               EXT4_FEATURE_COMPAT_FAST_COMMIT |
+               EXT4_FEATURE_COMPAT_STABLE_INODES,
        /* Incompat */
        EXT2_FEATURE_INCOMPAT_FILETYPE |
                EXT4_FEATURE_INCOMPAT_FLEX_BG |
@@ -218,8 +222,8 @@ static int get_journal_sb(ext2_filsys jfs, char buf[SUPERBLOCK_SIZE])
        }
 
        jsb = (journal_superblock_t *) buf;
-       if ((jsb->s_header.h_magic != (unsigned)ntohl(JFS_MAGIC_NUMBER)) ||
-           (jsb->s_header.h_blocktype != (unsigned)ntohl(JFS_SUPERBLOCK_V2))) {
+       if ((jsb->s_header.h_magic != (unsigned)ntohl(JBD2_MAGIC_NUMBER)) ||
+           (jsb->s_header.h_blocktype != (unsigned)ntohl(JBD2_SUPERBLOCK_V2))) {
                fputs(_("Journal superblock not found!\n"), stderr);
                return EXT2_ET_BAD_MAGIC;
        }
@@ -227,7 +231,7 @@ static int get_journal_sb(ext2_filsys jfs, char buf[SUPERBLOCK_SIZE])
        return 0;
 }
 
-static __u8 *journal_user(__u8 uuid[UUID_SIZE], __u8 s_users[JFS_USERS_SIZE],
+static __u8 *journal_user(__u8 uuid[UUID_SIZE], __u8 s_users[JBD2_USERS_SIZE],
                          int nr_users)
 {
        int i;
@@ -292,7 +296,7 @@ static int remove_journal_device(ext2_filsys fs)
        jsb = (journal_superblock_t *) buf;
        /* Find the filesystem UUID */
        nr_users = ntohl(jsb->s_nr_users);
-       if (nr_users > JFS_USERS_MAX) {
+       if (nr_users > JBD2_USERS_MAX) {
                fprintf(stderr, _("Journal superblock is corrupted, nr_users\n"
                                 "is too high (%d).\n"), nr_users);
                commit_remove_journal = 1;
@@ -1708,7 +1712,7 @@ static void parse_e2label_options(int argc, char ** argv)
                        argv[1]);
                exit(1);
        }
-       open_flag = EXT2_FLAG_JOURNAL_DEV_OK;
+       open_flag = EXT2_FLAG_JOURNAL_DEV_OK | EXT2_FLAG_SUPER_ONLY;
        if (argc == 3) {
                open_flag |= EXT2_FLAG_RW;
                L_flag = 1;
@@ -2821,7 +2825,7 @@ fs_update_journal_user(struct ext2_super_block *sb, __u8 old_uuid[UUID_SIZE])
        jsb = (journal_superblock_t *) buf;
        /* Find the filesystem UUID */
        nr_users = ntohl(jsb->s_nr_users);
-       if (nr_users > JFS_USERS_MAX) {
+       if (nr_users > JBD2_USERS_MAX) {
                fprintf(stderr, _("Journal superblock is corrupted, nr_users\n"
                                 "is too high (%d).\n"), nr_users);
                return EXT2_ET_CORRUPT_JOURNAL_SB;
index d6b4f433505bf100ebdc7907719e7a9a6c19244a..f5b5936ebcc697d8729522ea217f1090b0888d4b 100644 (file)
@@ -5,6 +5,7 @@ e2fsck/e2fsck.c
 e2fsck/ea_refcount.c
 e2fsck/ehandler.c
 e2fsck/emptydir.c
+e2fsck/encrypted_files.c
 e2fsck/extend.c
 e2fsck/extents.c
 e2fsck/flushb.c
index a0c31c069f3c71ca9764cf7a9949fb0979bf1dae..cb0bf6a0d271822109637e6294e290f958079e52 100644 (file)
@@ -605,6 +605,12 @@ int main (int argc, char ** argv)
                fprintf(stderr, _("The filesystem is already 32-bit.\n"));
                exit(0);
        }
+       if (new_size < ext2fs_blocks_count(fs->super) &&
+           ext2fs_has_feature_stable_inodes(fs->super)) {
+               fprintf(stderr, _("Cannot shrink this filesystem "
+                       "because it has the stable_inodes feature flag.\n"));
+               exit(1);
+       }
        if (mount_flags & EXT2_MF_MOUNTED) {
                retval = online_resize_fs(fs, mtpt, &new_size, flags);
        } else {
diff --git a/tests/f_bad_encryption/expect.1 b/tests/f_bad_encryption/expect.1
new file mode 100644 (file)
index 0000000..d743e66
--- /dev/null
@@ -0,0 +1,125 @@
+Pass 1: Checking inodes, blocks, and sizes
+Inode 17 has encrypt flag but no encryption extended attribute.
+Clear flag? yes
+
+Inode 18 has encrypt flag but no encryption extended attribute.
+Clear flag? yes
+
+Encrypted inode 19 has corrupt encryption extended attribute.
+Clear inode? yes
+
+Encrypted inode 20 has corrupt encryption extended attribute.
+Clear inode? yes
+
+Encrypted inode 21 has corrupt encryption extended attribute.
+Clear inode? yes
+
+Encrypted inode 22 has corrupt encryption extended attribute.
+Clear inode? yes
+
+Pass 2: Checking directory structure
+Encrypted entry 'd6M->'M-#I^VM-^KM-F~^WSJ+M-uM-zM-zXM-^' in /edir (12) references unencrypted inode 17.
+Clear? yes
+
+Encrypted entry '\M-!M-Y%DhM-OM-VM-zM-CM-gVM-R3M-^RM-IkE^JM-^S' in /edir (12) references unencrypted inode 18.
+Clear? yes
+
+Entry 'M-{^Qp-M-sM-U7eM-^C^L^PG^ZM-FM-,M-B' in /edir (12) has deleted/unused inode 19.  Clear? yes
+
+Entry 'M-f0M-f3/M-NM-GM-:M-^YM-jM-XM-91DM-^_M-V' in /edir (12) has deleted/unused inode 20.  Clear? yes
+
+Entry '^M-R"M-^K^P7M-'M-EM-C}^MM-yM-^LwM-^N^Z' in /edir (12) has deleted/unused inode 21.  Clear? yes
+
+Entry 'M-s^J_;uIvM-^Z[M-nIM-5vM-^AcM-o' in /edir (12) has deleted/unused inode 22.  Clear? yes
+
+Encrypted entry 'kK=,M-bM-^AM-{M-YM-^J6M-hM-y^XM-^W}M-M' in /edir (12) references unencrypted inode 23.
+Clear? yes
+
+Encrypted entry 'M-VM-cxM-jM-zM-b^WM-o*M-jM-uM-,R^PM-hM-2' in /edir (12) references unencrypted inode 24.
+Clear? yes
+
+Encrypted entry 'UqM-AM-#KM-^PM-_^kM-9P0M-^FM-_^@;A^J"R' in /edir (12) references unencrypted inode 25.
+Clear? yes
+
+Encrypted entry 'M-TM-N8^[M-3M-( M-[A^FR}^ZhkM-^?=M-c^Mo' in /edir (12) references inode 26, which has a different encryption policy.
+Clear? yes
+
+Encrypted entry 'M--aM-^?~M-^\M-u^FM-/!^YM-OZM-^LM-)M-p1' in /edir (12) references inode 27, which has a different encryption policy.
+Clear? yes
+
+Encrypted entry '(M-8RKM-LM-eM-^W^[M-'M-SM-@uM-^VM-|M-GiM-^JbM-nM-z' in /edir (12) references inode 28, which has a different encryption policy.
+Clear? yes
+
+Encrypted entry '\M-ggCeM-/?M-^BM-{(M-^OM-9M-^QQAM-^N=M-c^Mo' in /edir (12) references inode 29, which has a different encryption policy.
+Clear? yes
+
+Pass 3: Checking directory connectivity
+Unconnected directory inode 18 (/edir/???)
+Connect to /lost+found? yes
+
+Unconnected directory inode 24 (/edir/???)
+Connect to /lost+found? yes
+
+Unconnected directory inode 27 (/edir/???)
+Connect to /lost+found? yes
+
+Pass 4: Checking reference counts
+Unattached inode 17
+Connect to /lost+found? yes
+
+Inode 17 ref count is 2, should be 1.  Fix? yes
+
+Inode 18 ref count is 3, should be 2.  Fix? yes
+
+Unattached inode 23
+Connect to /lost+found? yes
+
+Inode 23 ref count is 2, should be 1.  Fix? yes
+
+Inode 24 ref count is 3, should be 2.  Fix? yes
+
+Unattached inode 25
+Connect to /lost+found? yes
+
+Inode 25 ref count is 2, should be 1.  Fix? yes
+
+Unattached inode 26
+Connect to /lost+found? yes
+
+Inode 26 ref count is 2, should be 1.  Fix? yes
+
+Inode 27 ref count is 3, should be 2.  Fix? yes
+
+Unattached inode 28
+Connect to /lost+found? yes
+
+Inode 28 ref count is 2, should be 1.  Fix? yes
+
+Unattached inode 29
+Connect to /lost+found? yes
+
+Inode 29 ref count is 2, should be 1.  Fix? yes
+
+Pass 5: Checking group summary information
+Block bitmap differences:  -(25--32)
+Fix? yes
+
+Free blocks count wrong for group #0 (75, counted=83).
+Fix? yes
+
+Free blocks count wrong (75, counted=83).
+Fix? yes
+
+Inode bitmap differences:  -(19--22)
+Fix? yes
+
+Free inodes count wrong for group #0 (95, counted=99).
+Fix? yes
+
+Free inodes count wrong (95, counted=99).
+Fix? yes
+
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 29/128 files (0.0% non-contiguous), 45/128 blocks
+Exit status is 1
diff --git a/tests/f_bad_encryption/expect.2 b/tests/f_bad_encryption/expect.2
new file mode 100644 (file)
index 0000000..fcfabdb
--- /dev/null
@@ -0,0 +1,7 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 29/128 files (0.0% non-contiguous), 45/128 blocks
+Exit status is 0
diff --git a/tests/f_bad_encryption/image.gz b/tests/f_bad_encryption/image.gz
new file mode 100644 (file)
index 0000000..64b59b7
Binary files /dev/null and b/tests/f_bad_encryption/image.gz differ
diff --git a/tests/f_bad_encryption/mkimage.sh b/tests/f_bad_encryption/mkimage.sh
new file mode 100755 (executable)
index 0000000..e58395d
--- /dev/null
@@ -0,0 +1,169 @@
+#!/bin/bash
+#
+# This is the script that was used to create the image.gz in this directory.
+#
+# This requires a patched version of debugfs that understands the "fscrypt."
+# xattr name prefix, so that the encryption xattrs can be manipulated.
+
+set -e -u
+umask 0022
+
+do_debugfs() {
+       umount mnt
+       debugfs -w "$@" image
+       mount image mnt
+}
+
+create_encrypted_file() {
+       local file=$1
+       local ino
+
+       echo foo > "$file"
+
+       # not needed, but makes image more compressible
+       ino=$(stat -c %i "$file")
+       do_debugfs -R "zap_block -f <$ino> 0"
+}
+
+set_encryption_xattr() {
+       local file=$1
+       local value=$2
+       local ino
+
+       ino=$(stat -c %i "$file")
+       do_debugfs -R "ea_set <$ino> fscrypt.c $value"
+}
+
+rm_encryption_xattr() {
+       local file=$1
+       local ino
+
+       ino=$(stat -c %i "$file")
+       do_debugfs -R "ea_rm <$ino> fscrypt.c"
+}
+
+clear_encrypt_flag() {
+       local file=$1
+       local ino
+
+       ino=$(stat -c %i "$file")
+       do_debugfs -R "set_inode_field <$ino> flags 0"
+}
+
+clear_encryption() {
+       local file=$1
+       local ino
+       local is_symlink=false
+
+       if [ -L "$file" ]; then
+               is_symlink=true
+       fi
+       ino=$(stat -c %i "$file")
+
+       do_debugfs -R "ea_rm <$ino> fscrypt.c"
+       do_debugfs -R "set_inode_field <$ino> flags 0"
+       if $is_symlink; then
+               do_debugfs -R "set_inode_field <$ino> block[0] 0xAAAAAAAA"
+               do_debugfs -R "set_inode_field <$ino> block[1] 0"
+               do_debugfs -R "set_inode_field <$ino> size 4"
+       fi
+}
+
+mkdir -p mnt
+umount mnt &> /dev/null || true
+
+dd if=/dev/zero of=image bs=4096 count=128
+mke2fs -O encrypt -b 4096 -N 128 image
+mount image mnt
+
+# Create an encrypted directory (ino 12)
+dir=mnt/edir
+mkdir $dir
+echo password | e4crypt add_key $dir
+
+# Control cases: valid encrypted regular file, dir, and symlink (ino 13-15)
+create_encrypted_file $dir/encrypted_file
+mkdir $dir/encrypted_dir
+ln -s target $dir/encrypted_symlink
+
+# Control case: file type that is never encrypted (ino 16)
+mkfifo $dir/fifo
+
+# Inodes with missing encryption xattr (ino 17-18).
+# e2fsck should offer to clear the encrypt flag on these inodes.
+
+create_encrypted_file $dir/missing_xattr_file
+rm_encryption_xattr $dir/missing_xattr_file
+
+mkdir $dir/missing_xattr_dir
+rm_encryption_xattr $dir/missing_xattr_dir
+
+# Inodes with corrupt encryption xattr (ino 19-22).
+# e2fsck should offer to clear these inodes.
+
+create_encrypted_file $dir/corrupt_xattr_1
+set_encryption_xattr $dir/corrupt_xattr_1 '\0'
+
+create_encrypted_file $dir/corrupt_xattr_2
+set_encryption_xattr $dir/corrupt_xattr_2 \
+       '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0'
+
+create_encrypted_file $dir/corrupt_xattr_3
+set_encryption_xattr $dir/corrupt_xattr_3 '\1'
+
+create_encrypted_file $dir/corrupt_xattr_4
+set_encryption_xattr $dir/corrupt_xattr_4 '\2'
+
+# Unencrypted inodes in encrypted directory (ino 23-25).
+# e2fsck should offer to clear these directory entries.
+
+create_encrypted_file $dir/unencrypted_file
+clear_encryption $dir/unencrypted_file
+
+mkdir $dir/unencrypted_dir
+clear_encryption $dir/unencrypted_dir
+
+ln -s target $dir/unencrypted_symlink
+clear_encryption $dir/unencrypted_symlink
+
+# Inodes with different encryption policy in encrypted directory (ino 26-29).
+# e2fsck should offer to clear these directory entries.
+
+xattr='\1\1\4\0AAAAAAAABBBBBBBBBBBBBBBB'
+
+create_encrypted_file $dir/inconsistent_file_1
+set_encryption_xattr $dir/inconsistent_file_1 $xattr
+
+mkdir $dir/inconsistent_dir
+set_encryption_xattr $dir/inconsistent_dir $xattr
+
+ln -s target $dir/inconsistent_symlink
+set_encryption_xattr $dir/inconsistent_symlink $xattr
+
+xattr='\2\1\4\0\0\0\0\0AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB'
+create_encrypted_file $dir/inconsistent_file_2
+set_encryption_xattr $dir/inconsistent_file_2 $xattr
+
+# Encrypted file and directory with valid v2 encryption policy (ino 30-31).
+# e2fsck shouldn't change these.
+dir2=mnt/edir2
+mkdir $dir2
+echo password | e4crypt add_key $dir2
+xattr='\2\1\4\0\0\0\0\0AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB'
+create_encrypted_file $dir2/file
+set_encryption_xattr $dir2/file $xattr
+set_encryption_xattr $dir2 $xattr
+
+# Encrypted file and directory with unrecognized encryption policy version
+# (ino 32-33).  e2fsck shouldn't change these.
+dir3=mnt/edir3
+mkdir $dir3
+echo password | e4crypt add_key $dir3
+xattr='\3'
+create_encrypted_file $dir3/file
+set_encryption_xattr $dir3/file $xattr
+set_encryption_xattr $dir3 $xattr
+
+umount mnt
+rmdir mnt
+gzip -9 -f image
diff --git a/tests/f_bad_encryption/name b/tests/f_bad_encryption/name
new file mode 100644 (file)
index 0000000..85b19ed
--- /dev/null
@@ -0,0 +1 @@
+missing, corrupt, and inconsistent encryption policies
diff --git a/tests/f_many_subdirs/expect.1 b/tests/f_many_subdirs/expect.1
new file mode 100644 (file)
index 0000000..f2fd78f
--- /dev/null
@@ -0,0 +1,45 @@
+Pass 1: Checking inodes, blocks, and sizes
+Deleted inode 26363 has zero dtime.  Fix? yes
+
+Pass 2: Checking directory structure
+Entry 'nlink_eq_0' in / (2) has deleted/unused inode 26363.  Clear? yes
+
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Inode 2 ref count is 9, should be 8.  Fix? yes
+
+Inode 13201 ref count is 1, should be 2.  Fix? yes
+
+Inode 19763 ref count is 65535, should be 2.  Fix? yes
+
+Directory exceeds max links, but no DIR_NLINK feature in superblock.
+Fix? yes
+
+Inode 32963 ref count is 65000, should be 2.  Fix? yes
+
+Pass 5: Checking group summary information
+Block bitmap differences:  -73383
+Fix? yes
+
+Free blocks count wrong for group #8 (0, counted=1).
+Fix? yes
+
+Free blocks count wrong (5388, counted=5389).
+Fix? yes
+
+Inode bitmap differences:  -26363
+Fix? yes
+
+Free inodes count wrong for group #3 (37, counted=38).
+Fix? yes
+
+Directories count wrong for group #3 (6563, counted=6562).
+Fix? yes
+
+Free inodes count wrong (382, counted=383).
+Fix? yes
+
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 65617/66000 files (0.0% non-contiguous), 76531/81920 blocks
+Exit status is 1
diff --git a/tests/f_many_subdirs/expect.2 b/tests/f_many_subdirs/expect.2
new file mode 100644 (file)
index 0000000..bb0d829
--- /dev/null
@@ -0,0 +1,7 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 65617/66000 files (0.0% non-contiguous), 76531/81920 blocks
+Exit status is 0
diff --git a/tests/f_many_subdirs/image.gz b/tests/f_many_subdirs/image.gz
new file mode 100644 (file)
index 0000000..7f60fff
Binary files /dev/null and b/tests/f_many_subdirs/image.gz differ
diff --git a/tests/f_many_subdirs/name b/tests/f_many_subdirs/name
new file mode 100644 (file)
index 0000000..6264a60
--- /dev/null
@@ -0,0 +1 @@
+directory with more than 65000 sub-directories
index bc649222ea76e8b73eef365c7808959498017296..29e1625c457fea82b93a7349113670d757d292e2 100644 (file)
@@ -13,5 +13,5 @@ Inode 13 ref count is 2, should be 1.  Fix? yes
 Pass 5: Checking group summary information
 
 test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
-test_filesys: 13/16 files (0.0% non-contiguous), 23/100 blocks
+test_filesys: 13/16 files (0.0% non-contiguous), 24/100 blocks
 Exit status is 1
index 636c6e9ec2978f8385ac30419d51120d6764fc75..1ebd598eefa000c128ee2117d8383791cf4fedae 100644 (file)
@@ -3,5 +3,5 @@ Pass 2: Checking directory structure
 Pass 3: Checking directory connectivity
 Pass 4: Checking reference counts
 Pass 5: Checking group summary information
-test_filesys: 13/16 files (0.0% non-contiguous), 23/100 blocks
+test_filesys: 13/16 files (0.0% non-contiguous), 24/100 blocks
 Exit status is 0
index a35bfb23b51aee75da142886a39380915d629f8e..7eb1c951f4e747c72a8245e5ca040ab07828a632 100644 (file)
Binary files a/tests/f_short_encrypted_dirent/image.gz and b/tests/f_short_encrypted_dirent/image.gz differ
diff --git a/tests/f_uninit_bad_free_inodes/expect.1 b/tests/f_uninit_bad_free_inodes/expect.1
new file mode 100644 (file)
index 0000000..23d7b1f
--- /dev/null
@@ -0,0 +1,25 @@
+Group descriptor 1 has invalid unused inodes count 2048.  Fix? yes
+
+Group descriptor 2 has invalid unused inodes count 1344.  Fix? yes
+
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+Free inodes count wrong for group #1 (490, counted=2048).
+Fix? yes
+
+Free inodes count wrong for group #2 (250, counted=1344).
+Fix? yes
+
+Free inodes count wrong for group #3 (1967, counted=1969).
+Fix? yes
+
+Free inodes count wrong (4744, counted=7398).
+Fix? yes
+
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 794/8192 files (0.4% non-contiguous), 8473/32768 blocks
+Exit status is 1
diff --git a/tests/f_uninit_bad_free_inodes/expect.2 b/tests/f_uninit_bad_free_inodes/expect.2
new file mode 100644 (file)
index 0000000..431227b
--- /dev/null
@@ -0,0 +1,7 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 794/8192 files (0.4% non-contiguous), 8473/32768 blocks
+Exit status is 0
diff --git a/tests/f_uninit_bad_free_inodes/image.gz b/tests/f_uninit_bad_free_inodes/image.gz
new file mode 100644 (file)
index 0000000..3e6218b
Binary files /dev/null and b/tests/f_uninit_bad_free_inodes/image.gz differ
diff --git a/tests/f_uninit_bad_free_inodes/name b/tests/f_uninit_bad_free_inodes/name
new file mode 100644 (file)
index 0000000..8bd3180
--- /dev/null
@@ -0,0 +1 @@
+bad free inode count, but good checksum
diff --git a/tests/f_uninit_blk_used_not_set/expect.1 b/tests/f_uninit_blk_used_not_set/expect.1
new file mode 100644 (file)
index 0000000..9e473f8
--- /dev/null
@@ -0,0 +1,34 @@
+Group descriptor 1 has invalid unused inodes count 2048.  Fix? yes
+
+Group descriptor 2 has invalid unused inodes count 2048.  Fix? yes
+
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+Group 1 block(s) in use but group is marked BLOCK_UNINIT
+Fix? yes
+
+Block bitmap differences:  +(8585--8777)
+Fix? yes
+
+Free blocks count wrong for group #2 (0, counted=7934).
+Fix? yes
+
+Free blocks count wrong (19530, counted=27464).
+Fix? yes
+
+Free inodes count wrong for group #1 (0, counted=2048).
+Fix? yes
+
+Free inodes count wrong for group #2 (0, counted=2048).
+Fix? yes
+
+Free inodes count wrong (4084, counted=8180).
+Fix? yes
+
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 12/8192 files (8.3% non-contiguous), 5304/32768 blocks
+Exit status is 1
diff --git a/tests/f_uninit_blk_used_not_set/expect.2 b/tests/f_uninit_blk_used_not_set/expect.2
new file mode 100644 (file)
index 0000000..17d0cfa
--- /dev/null
@@ -0,0 +1,7 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 12/8192 files (8.3% non-contiguous), 5304/32768 blocks
+Exit status is 0
diff --git a/tests/f_uninit_blk_used_not_set/image.gz b/tests/f_uninit_blk_used_not_set/image.gz
new file mode 100644 (file)
index 0000000..6316285
Binary files /dev/null and b/tests/f_uninit_blk_used_not_set/image.gz differ
diff --git a/tests/f_uninit_blk_used_not_set/name b/tests/f_uninit_blk_used_not_set/name
new file mode 100644 (file)
index 0000000..e6ee718
--- /dev/null
@@ -0,0 +1 @@
+blocks used but block uninit set
diff --git a/tests/f_uninit_checksum_bad/expect.1 b/tests/f_uninit_checksum_bad/expect.1
new file mode 100644 (file)
index 0000000..4ff8a8b
--- /dev/null
@@ -0,0 +1,29 @@
+One or more block group descriptor checksums are invalid.  Fix? yes
+
+Group descriptor 1 checksum is 0xbbaa, should be 0xff0b.  FIXED.
+Group descriptor 2 has invalid unused inodes count 2048.  Fix? yes
+
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+Free blocks count wrong for group #2 (0, counted=7934).
+Fix? yes
+
+Free blocks count wrong (19286, counted=27220).
+Fix? yes
+
+Free inodes count wrong for group #1 (0, counted=2048).
+Fix? yes
+
+Free inodes count wrong for group #2 (0, counted=2048).
+Fix? yes
+
+Free inodes count wrong (4085, counted=8181).
+Fix? yes
+
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 11/8192 files (0.0% non-contiguous), 5548/32768 blocks
+Exit status is 1
diff --git a/tests/f_uninit_checksum_bad/expect.2 b/tests/f_uninit_checksum_bad/expect.2
new file mode 100644 (file)
index 0000000..38f2334
--- /dev/null
@@ -0,0 +1,7 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 11/8192 files (0.0% non-contiguous), 5548/32768 blocks
+Exit status is 0
diff --git a/tests/f_uninit_checksum_bad/image.gz b/tests/f_uninit_checksum_bad/image.gz
new file mode 100644 (file)
index 0000000..8e91e01
Binary files /dev/null and b/tests/f_uninit_checksum_bad/image.gz differ
diff --git a/tests/f_uninit_checksum_bad/name b/tests/f_uninit_checksum_bad/name
new file mode 100644 (file)
index 0000000..b9e4a31
--- /dev/null
@@ -0,0 +1 @@
+invalid group descriptor checksum
diff --git a/tests/f_uninit_disable/expect.1 b/tests/f_uninit_disable/expect.1
new file mode 100644 (file)
index 0000000..f568bec
--- /dev/null
@@ -0,0 +1,10 @@
+Group descriptor 0 marked uninitialized without feature set.
+Fix? yes
+
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 11/2048 files (0.0% non-contiguous), 306/8192 blocks
+Exit status is 1
diff --git a/tests/f_uninit_disable/expect.2 b/tests/f_uninit_disable/expect.2
new file mode 100644 (file)
index 0000000..4cd9aa9
--- /dev/null
@@ -0,0 +1,7 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 11/2048 files (0.0% non-contiguous), 306/8192 blocks
+Exit status is 0
diff --git a/tests/f_uninit_disable/image.gz b/tests/f_uninit_disable/image.gz
new file mode 100644 (file)
index 0000000..38c7455
Binary files /dev/null and b/tests/f_uninit_disable/image.gz differ
diff --git a/tests/f_uninit_disable/name b/tests/f_uninit_disable/name
new file mode 100644 (file)
index 0000000..494b472
--- /dev/null
@@ -0,0 +1 @@
+disable uninit_bg feature
diff --git a/tests/f_uninit_enable/expect.1 b/tests/f_uninit_enable/expect.1
new file mode 100644 (file)
index 0000000..02801bf
--- /dev/null
@@ -0,0 +1,10 @@
+One or more block group descriptor checksums are invalid.  Fix? yes
+
+Group descriptor 0 checksum is 0x0000, should be 0x13f6.  FIXED.
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 11/2048 files (0.0% non-contiguous), 306/8192 blocks
+Exit status is 1
diff --git a/tests/f_uninit_enable/expect.2 b/tests/f_uninit_enable/expect.2
new file mode 100644 (file)
index 0000000..4cd9aa9
--- /dev/null
@@ -0,0 +1,7 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 11/2048 files (0.0% non-contiguous), 306/8192 blocks
+Exit status is 0
diff --git a/tests/f_uninit_enable/image.gz b/tests/f_uninit_enable/image.gz
new file mode 100644 (file)
index 0000000..4da79c9
Binary files /dev/null and b/tests/f_uninit_enable/image.gz differ
diff --git a/tests/f_uninit_enable/name b/tests/f_uninit_enable/name
new file mode 100644 (file)
index 0000000..a818f5c
--- /dev/null
@@ -0,0 +1 @@
+enable uninit_bg feature
diff --git a/tests/f_uninit_inode_past_unused/expect.1 b/tests/f_uninit_inode_past_unused/expect.1
new file mode 100644 (file)
index 0000000..1cf5c85
--- /dev/null
@@ -0,0 +1,27 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Entry 'foo' in / (2) references inode 14 found in group 0's unused inodes area.
+Fix? yes
+
+Restarting e2fsck from the beginning...
+One or more block group descriptor checksums are invalid.  Fix? yes
+
+Group descriptor 0 checksum is 0x4c72, should be 0xde74.  FIXED.
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+Inode bitmap differences:  -12
+Fix? yes
+
+Free inodes count wrong for group #0 (2037, counted=2035).
+Fix? yes
+
+Free inodes count wrong (4073, counted=2035).
+Fix? yes
+
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 13/2048 files (0.0% non-contiguous), 1336/8192 blocks
+Exit status is 1
diff --git a/tests/f_uninit_inode_past_unused/expect.2 b/tests/f_uninit_inode_past_unused/expect.2
new file mode 100644 (file)
index 0000000..bdb029e
--- /dev/null
@@ -0,0 +1,7 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 13/2048 files (0.0% non-contiguous), 1336/8192 blocks
+Exit status is 0
diff --git a/tests/f_uninit_inode_past_unused/image.gz b/tests/f_uninit_inode_past_unused/image.gz
new file mode 100644 (file)
index 0000000..9104a70
Binary files /dev/null and b/tests/f_uninit_inode_past_unused/image.gz differ
diff --git a/tests/f_uninit_inode_past_unused/name b/tests/f_uninit_inode_past_unused/name
new file mode 100644 (file)
index 0000000..95d07f1
--- /dev/null
@@ -0,0 +1 @@
+inode in use beyond bg_itable_unused
diff --git a/tests/f_uninit_restart_fsck/expect.1 b/tests/f_uninit_restart_fsck/expect.1
new file mode 100644 (file)
index 0000000..d396beb
--- /dev/null
@@ -0,0 +1,36 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Entry 'foo2' in /d1 (1881) references inode 500 found in group 0's unused inodes area.
+Fix? yes
+
+Entry 'foo2' in /d1 (1881) has an incorrect filetype (was 1, should be 0).
+Fix? yes
+
+Entry 'bar2' in /d2 (3761) references inode 2100 found in group 1's unused inodes area.
+Fix? yes
+
+Entry 'bar2' in /d2 (3761) has an incorrect filetype (was 1, should be 0).
+Fix? yes
+
+Restarting e2fsck from the beginning...
+One or more block group descriptor checksums are invalid.  Fix? yes
+
+Group descriptor 0 checksum is 0xb92b, should be 0x2b5f.  FIXED.
+Group descriptor 1 checksum is 0x2f53, should be 0x8d2f.  FIXED.
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Entry 'foo2' in /d1 (1881) has deleted/unused inode 500.  Clear? yes
+
+Entry 'bar2' in /d2 (3761) has deleted/unused inode 2100.  Clear? yes
+
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Unattached zero-length inode 1883.  Clear? yes
+
+Unattached zero-length inode 3763.  Clear? yes
+
+Pass 5: Checking group summary information
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 21/7520 files (0.0% non-contiguous), 2352/30000 blocks
+Exit status is 1
diff --git a/tests/f_uninit_restart_fsck/expect.2 b/tests/f_uninit_restart_fsck/expect.2
new file mode 100644 (file)
index 0000000..156eb07
--- /dev/null
@@ -0,0 +1,7 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 21/7520 files (0.0% non-contiguous), 2352/30000 blocks
+Exit status is 0
diff --git a/tests/f_uninit_restart_fsck/image.gz b/tests/f_uninit_restart_fsck/image.gz
new file mode 100644 (file)
index 0000000..f073186
Binary files /dev/null and b/tests/f_uninit_restart_fsck/image.gz differ
diff --git a/tests/f_uninit_restart_fsck/name b/tests/f_uninit_restart_fsck/name
new file mode 100644 (file)
index 0000000..def2234
--- /dev/null
@@ -0,0 +1 @@
+re-start e2fsck only once for inodes in uninit space
diff --git a/tests/f_uninit_set_inode_not_set/expect.1 b/tests/f_uninit_set_inode_not_set/expect.1
new file mode 100644 (file)
index 0000000..4ea3f10
--- /dev/null
@@ -0,0 +1,25 @@
+Group descriptor 1 has invalid unused inodes count 1464.  Fix? yes
+
+Group descriptor 2 has invalid unused inodes count 1849.  Fix? yes
+
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+Group 1 block(s) in use but group is marked BLOCK_UNINIT
+Fix? yes
+
+Block bitmap differences:  +(9729--14621)
+Fix? yes
+
+Free inodes count wrong for group #1 (0, counted=1464).
+Fix? yes
+
+Free inodes count wrong for group #2 (0, counted=1849).
+Fix? yes
+
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 794/8192 files (0.3% non-contiguous), 8473/32768 blocks
+Exit status is 1
diff --git a/tests/f_uninit_set_inode_not_set/expect.2 b/tests/f_uninit_set_inode_not_set/expect.2
new file mode 100644 (file)
index 0000000..846c558
--- /dev/null
@@ -0,0 +1,7 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 794/8192 files (0.3% non-contiguous), 8473/32768 blocks
+Exit status is 0
diff --git a/tests/f_uninit_set_inode_not_set/image.gz b/tests/f_uninit_set_inode_not_set/image.gz
new file mode 100644 (file)
index 0000000..cd38e27
Binary files /dev/null and b/tests/f_uninit_set_inode_not_set/image.gz differ
diff --git a/tests/f_uninit_set_inode_not_set/name b/tests/f_uninit_set_inode_not_set/name
new file mode 100644 (file)
index 0000000..42b9c53
--- /dev/null
@@ -0,0 +1 @@
+block uninit set but inode uninit not set
index 36a76990ae6e3b54e5b4947f0c2705194a747fe0..8b6545aec4bbb7a5dabe100ae7703585d7365d23 100644 (file)
@@ -1,5 +1,5 @@
 test_filesys: recovering journal
-JBD2: Invalid checksum recovering block 1090 in log
+JBD2: Invalid checksum recovering data block 1090 in log
 Journal checksum error found in test_filesys
 Pass 1: Checking inodes, blocks, and sizes
 Pass 2: Checking directory structure
index 3efe120957ed93ae9f4592dcbb26a8a12c3e6c08..da06950e0e8055479b595c41b15456aeca8c4f37 100644 (file)
--- a/version.h
+++ b/version.h
@@ -7,5 +7,5 @@
  * file may be redistributed under the GNU Public License v2.
  */
 
-#define E2FSPROGS_VERSION "1.45.5"
-#define E2FSPROGS_DATE "07-Jan-2020"
+#define E2FSPROGS_VERSION "1.46-WIP"
+#define E2FSPROGS_DATE "09-Oct-2019"