2014-09-08 23:11:42

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 00/25] e2fsprogs Summer 2014 patchbomb, part 5.2

Hi all,

This is the third release of part 5^H4 of the Summer 2014 e2fsprogs
patchset. Whereas all the patches I've sent previously were to fix
problems in the library and e2fsck uncovered by the e2fuzz metadata
fuzzer, we're now to the part of the patch set that includes new
features. I'm only posting things that have been discussed recently;
the other "new" features (most of which have been out for review for
quite some time) haven't changed since May. They'll be in part 6,
which I'm holding until we get through this pile of patches.

Patch 1 introduces journal_csum v3 to fix numerous journal block tag
size handling bugs when metadata_csum+journal_checksum are turned on.
The test of 64bitness should not rely on guessing the tag size when it
could simply query the feature flags, since it was guessing
incorrectly. Furthermore, the journal_csum v2 structure had memory
access alignment issues. Just replace this all with a 16-byte tag
with everything in it; the overhead for checksums is no more than
0.1%.

Patches 2-4 fix some problems with incorrect error codes being
returned and a place where error codes could be dropped.

Patches 5-6 enable us to format the ext4 superblock of an external
journal device with metadata_csum enabled, so that the ext4 superblock
can be protected with a checksum. Note that this is entirely separate
from journal_checksum, which only applies to the journal blocks on the
external device. See section 11.2 of the ext4 disk layout page for
details about external journal devices.

Patches 7-8 fix a few small problems when dealing with external
journal devices, namely that dumpe2fs failed to print external journal
features, and that tune2fs shouldn't print 'cannot find superblock'
when passed an external journal device.

Patch 9 zeroes the superblock's j_blocks field when discarding an
internal journal.

Patches 10-12 enhance debugfs with the ability to replay journals with
dirty data and more importantly to create journal transactions; this
feature gives us the ability to (easily) create journal replay
scenarios for testing. #11 fixes a minor bug in the e2fsck journal
management code that could in theory lead to journal corruption.

Patches 13-22 add 'make check' tests that exercise (1) the new
transaction writing ability and e2fsck' ability to replay; (2)
recovering with journal_csum v1-3; and (3) the ability to replay
journals where different kinds of journal blocks fail checksum
verification. The test journals created in these tests have been run
through kernel jbd2 to verify that they recover properly. There
are now tests to verify the writability and replayability when
an external journal is used.

NOTE: The test "j_corrupt_journal_block" in patch 21 ensures that
e2fsck will replay everything but the corrupt block, and then proceeds
with the fsck to fix up whatever might be broken. You can decompress
the image.gz and try to mount it to verify that it's unmountable (and
hence requires e2fsck to be run).

Patches 23-25 implement v2 of the e2fsck readahead functionality,
which promises to reduce fsck runtime by 10-30%. You might want to
read the report: http://marc.info/?l=linux-ext4&m=140755433701165&w=2
("e2fsck readahead speedup performance report") for all the juicy
details!

I've tested these e2fsprogs changes against the -next branch as of
8/29. The patches have been tested against the 'make check' suite and
some amount of e2fuzz testing.

Comments and questions are, as always, welcome.

--D


2014-09-08 23:11:49

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 01/25] e2fsck/debugfs: fix descriptor block size handling errors with journal_csum

It turns out that there are some serious problems with the on-disk
format of journal checksum v2. The foremost is that the function to
calculate descriptor tag size returns sizes that are too big. This
causes alignment issues on some architectures and is compounded by the
fact that some parts of jbd2 use the structure size (incorrectly) to
determine the presence of a 64bit journal instead of checking the
feature flags. These errors regrettably lead to the journal
corruption reported by Mr. Reardon.

Therefore, introduce journal checksum v3, which enlarges the
descriptor block tag format to allow for full 32-bit checksums of
journal blocks, fix the journal tag function to return the correct
sizes, and fix the jbd2 recovery code to use feature flags to
determine 64bitness.

Add a few function helpers so we don't have to open-code quite so
many pieces.

Switching to a 16-byte block size was found to increase journal size
overhead by a maximum of 0.1%, to convert a 32-bit journal with no
checksumming to a 32-bit journal with checksum v3 enabled.

Signed-off-by: Darrick J. Wong <[email protected]>
Reported-by: TR Reardon <[email protected]>
---
debugfs/jfs_user.h | 21 +++++++++++++++++++++
debugfs/logdump.c | 12 +++++++-----
e2fsck/journal.c | 14 +++++++++-----
e2fsck/recovery.c | 24 ++++++++++++++----------
e2fsck/revoke.c | 4 ++--
lib/e2p/feature.c | 2 ++
lib/ext2fs/kernel-jbd.h | 46 +++++++++++++++++++++++++++++++++++-----------
misc/dumpe2fs.c | 12 ++++++++----
8 files changed, 98 insertions(+), 37 deletions(-)


diff --git a/debugfs/jfs_user.h b/debugfs/jfs_user.h
index 3070cd5..66756fc 100644
--- a/debugfs/jfs_user.h
+++ b/debugfs/jfs_user.h
@@ -5,4 +5,25 @@ typedef unsigned short kdev_t;

#include <ext2fs/kernel-jbd.h>

+#define JSB_HAS_INCOMPAT_FEATURE(jsb, mask) \
+ ((jsb)->s_header.h_blocktype == ext2fs_cpu_to_be32(JFS_SUPERBLOCK_V2) && \
+ ((jsb)->s_feature_incompat & ext2fs_cpu_to_be32((mask))))
+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))
+ return sizeof(journal_block_tag3_t);
+
+ sz = sizeof(journal_block_tag_t);
+
+ if (JSB_HAS_INCOMPAT_FEATURE(jsb, JFS_FEATURE_INCOMPAT_CSUM_V2))
+ sz += sizeof(__u16);
+
+ if (JSB_HAS_INCOMPAT_FEATURE(jsb, JFS_FEATURE_INCOMPAT_64BIT))
+ return sz;
+
+ return sz - sizeof(__u32);
+}
+
#endif /* _JFS_USER_H */
diff --git a/debugfs/logdump.c b/debugfs/logdump.c
index 9f9594f..70a7c36 100644
--- a/debugfs/logdump.c
+++ b/debugfs/logdump.c
@@ -476,19 +476,21 @@ static void dump_descriptor_block(FILE *out_file,
unsigned int *blockp, int blocksize,
tid_t transaction)
{
- int offset, tag_size = JBD_TAG_SIZE32;
+ int offset, tag_size, csum_size = 0;
char *tagp;
journal_block_tag_t *tag;
unsigned int blocknr;
__u32 tag_block;
__u32 tag_flags;

- if (be32_to_cpu(jsb->s_feature_incompat) & JFS_FEATURE_INCOMPAT_64BIT)
- tag_size = JBD_TAG_SIZE64;
-
+ tag_size = journal_super_tag_bytes(jsb);
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 (dump_all)
fprintf(out_file, "Dumping descriptor block, sequence %u, at "
"block %u:\n", transaction, blocknr);
@@ -505,7 +507,7 @@ static void dump_descriptor_block(FILE *out_file,

/* ... and if we have gone too far, then we've reached the
end of this block. */
- if (offset > blocksize)
+ if (offset > blocksize - csum_size)
break;

tag_block = be32_to_cpu(tag->t_blocknr);
diff --git a/e2fsck/journal.c b/e2fsck/journal.c
index 533b1d6..a19d40b 100644
--- a/e2fsck/journal.c
+++ b/e2fsck/journal.c
@@ -44,7 +44,7 @@ static int bh_count = 0;
static int e2fsck_journal_verify_csum_type(journal_t *j,
journal_superblock_t *jsb)
{
- if (!JFS_HAS_INCOMPAT_FEATURE(j, JFS_FEATURE_INCOMPAT_CSUM_V2))
+ if (!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 (!JFS_HAS_INCOMPAT_FEATURE(j, JFS_FEATURE_INCOMPAT_CSUM_V2))
+ if (!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 (!JFS_HAS_INCOMPAT_FEATURE(j, JFS_FEATURE_INCOMPAT_CSUM_V2))
+ if (!journal_has_csum_v2or3(j))
return 0;

crc = e2fsck_journal_sb_csum(jsb);
@@ -623,8 +623,12 @@ static errcode_t e2fsck_journal_load(journal_t *journal)
if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
return EXT2_ET_RO_UNSUPP_FEATURE;

- /* Checksum v1 and v2 are mutually exclusive features. */
+ /* Checksum v1-3 are mutually exclusive features. */
if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V2) &&
+ JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V3))
+ return EXT2_ET_CORRUPT_SUPERBLOCK;
+
+ if (journal_has_csum_v2or3(journal) &&
JFS_HAS_COMPAT_FEATURE(journal, JFS_FEATURE_COMPAT_CHECKSUM))
return EXT2_ET_CORRUPT_SUPERBLOCK;

@@ -632,7 +636,7 @@ static errcode_t e2fsck_journal_load(journal_t *journal)
!e2fsck_journal_sb_csum_verify(journal, jsb))
return EXT2_ET_CORRUPT_SUPERBLOCK;

- if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V2))
+ if (journal_has_csum_v2or3(journal))
journal->j_csum_seed = jbd2_chksum(journal, ~0, jsb->s_uuid,
sizeof(jsb->s_uuid));

diff --git a/e2fsck/recovery.c b/e2fsck/recovery.c
index dae7239..3dc7c06 100644
--- a/e2fsck/recovery.c
+++ b/e2fsck/recovery.c
@@ -181,7 +181,7 @@ static int jbd2_descr_block_csum_verify(journal_t *j,
__u32 provided;
__u32 calculated;

- if (!JFS_HAS_INCOMPAT_FEATURE(j, JFS_FEATURE_INCOMPAT_CSUM_V2))
+ if (!journal_has_csum_v2or3(j))
return 1;

tail = (struct journal_block_tail *)(buf + j->j_blocksize -
@@ -205,7 +205,7 @@ 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 (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V2))
+ if (journal_has_csum_v2or3(journal))
size -= sizeof(struct journal_block_tail);

tagp = &bh->b_data[sizeof(journal_header_t)];
@@ -338,10 +338,11 @@ int journal_skip_recovery(journal_t *journal)
return err;
}

-static inline unsigned long long read_tag_block(int tag_bytes, journal_block_tag_t *tag)
+static inline unsigned long long read_tag_block(journal_t *journal,
+ journal_block_tag_t *tag)
{
unsigned long long block = ext2fs_be32_to_cpu(tag->t_blocknr);
- if (tag_bytes > JFS_TAG_SIZE32)
+ if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_64BIT))
block |= (u64)ext2fs_be32_to_cpu(tag->t_blocknr_high) << 32;
return block;
}
@@ -384,7 +385,7 @@ static int jbd2_commit_block_csum_verify(journal_t *j, void *buf)
__u32 provided;
__u32 calculated;

- if (!JFS_HAS_INCOMPAT_FEATURE(j, JFS_FEATURE_INCOMPAT_CSUM_V2))
+ if (!journal_has_csum_v2or3(j))
return 1;

h = buf;
@@ -399,16 +400,20 @@ static int jbd2_commit_block_csum_verify(journal_t *j, void *buf)
static int jbd2_block_tag_csum_verify(journal_t *j, journal_block_tag_t *tag,
void *buf, __u32 sequence)
{
+ journal_block_tag3_t *tag3 = (journal_block_tag3_t *)tag;
__u32 csum32;
__u32 seq;

- if (!JFS_HAS_INCOMPAT_FEATURE(j, JFS_FEATURE_INCOMPAT_CSUM_V2))
+ if (!journal_has_csum_v2or3(j))
return 1;

seq = ext2fs_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_INCOMPAT_FEATURE(j, JFS_FEATURE_INCOMPAT_CSUM_V3))
+ return tag3->t_checksum == ext2fs_cpu_to_be32(csum32);
+
return tag->t_checksum == ext2fs_cpu_to_be16(csum32);
}

@@ -513,8 +518,7 @@ static int do_one_pass(journal_t *journal,
switch(blocktype) {
case JFS_DESCRIPTOR_BLOCK:
/* Verify checksum first */
- if (JFS_HAS_INCOMPAT_FEATURE(journal,
- JFS_FEATURE_INCOMPAT_CSUM_V2))
+ if (journal_has_csum_v2or3(journal))
descr_csum_size =
sizeof(struct journal_block_tail);
if (descr_csum_size > 0 &&
@@ -575,7 +579,7 @@ static int do_one_pass(journal_t *journal,
unsigned long long blocknr;

J_ASSERT(obh != NULL);
- blocknr = read_tag_block(tag_bytes,
+ blocknr = read_tag_block(journal,
tag);

/* If the block has been
@@ -814,7 +818,7 @@ static int jbd2_revoke_block_csum_verify(journal_t *j,
__u32 provided;
__u32 calculated;

- if (!JFS_HAS_INCOMPAT_FEATURE(j, JFS_FEATURE_INCOMPAT_CSUM_V2))
+ if (!journal_has_csum_v2or3(j))
return 1;

tail = (struct journal_revoke_tail *)(buf + j->j_blocksize -
diff --git a/e2fsck/revoke.c b/e2fsck/revoke.c
index 383164e..b4c3f5f 100644
--- a/e2fsck/revoke.c
+++ b/e2fsck/revoke.c
@@ -597,7 +597,7 @@ static void write_one_revoke_record(journal_t *journal,
offset = *offsetp;

/* Do we need to leave space at the end for a checksum? */
- if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V2))
+ if (journal_has_csum_v2or3(journal))
csum_size = sizeof(struct journal_revoke_tail);

/* Make sure we have a descriptor with space left for the record */
@@ -644,7 +644,7 @@ static void jbd2_revoke_csum_set(journal_t *j, struct buffer_head *bh)
struct journal_revoke_tail *tail;
__u32 csum;

- if (!JFS_HAS_INCOMPAT_FEATURE(j, JFS_FEATURE_INCOMPAT_CSUM_V2))
+ if (!journal_has_csum_v2or3(j))
return;

tail = (struct journal_revoke_tail *)(bh->b_data + j->j_blocksize -
diff --git a/lib/e2p/feature.c b/lib/e2p/feature.c
index d0e29b8..6e53cfe 100644
--- a/lib/e2p/feature.c
+++ b/lib/e2p/feature.c
@@ -112,6 +112,8 @@ static struct feature jrnl_feature_list[] = {
"journal_async_commit" },
{ E2P_FEATURE_INCOMPAT, JFS_FEATURE_INCOMPAT_CSUM_V2,
"journal_checksum_v2" },
+ { E2P_FEATURE_INCOMPAT, JFS_FEATURE_INCOMPAT_CSUM_V3,
+ "journal_checksum_v3" },
{ 0, 0, 0 },
};

diff --git a/lib/ext2fs/kernel-jbd.h b/lib/ext2fs/kernel-jbd.h
index 407f4a5..4020429 100644
--- a/lib/ext2fs/kernel-jbd.h
+++ b/lib/ext2fs/kernel-jbd.h
@@ -131,7 +131,11 @@ typedef struct journal_header_s
* journal_block_tag (in the descriptor). The other h_chksum* fields are
* not used.
*
- * Checksum v1 and v2 are mutually exclusive features.
+ * If FEATURE_INCOMPAT_CSUM_V3 is set, the descriptor block uses
+ * journal_block_tag3_t to store a full 32-bit checksum. Everything else
+ * is the same as v2.
+ *
+ * Checksum v1, v2, and v3 are mutually exclusive features.
*/
struct commit_header {
__u32 h_magic;
@@ -148,6 +152,14 @@ struct commit_header {
/*
* The block tag: used to describe a single buffer in the journal
*/
+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) */
+} journal_block_tag3_t;
+
typedef struct journal_block_tag_s
{
__u32 t_blocknr; /* The on-disk block number */
@@ -156,9 +168,6 @@ typedef struct journal_block_tag_s
__u32 t_blocknr_high; /* most-significant high 32bits. */
} journal_block_tag_t;

-#define JBD_TAG_SIZE64 (sizeof(journal_block_tag_t))
-#define JBD_TAG_SIZE32 (8)
-
/* Tail of descriptor block, for checksumming */
struct journal_block_tail {
__u32 t_checksum;
@@ -257,6 +266,7 @@ typedef struct journal_superblock_s
#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

/* Features known to this kernel version: */
#define JFS_KNOWN_COMPAT_FEATURES 0
@@ -264,7 +274,8 @@ typedef struct journal_superblock_s
#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_V2|\
+ JFS_FEATURE_INCOMPAT_CSUM_V3)

#if (defined(E2FSCK_INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS))
#ifdef E2FSCK_INCLUDE_INLINE_FUNCS
@@ -290,16 +301,29 @@ typedef struct journal_superblock_s
*/
_INLINE_ size_t journal_tag_bytes(journal_t *journal)
{
- journal_block_tag_t tag;
- size_t x = 0;
+ size_t sz;
+
+ if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V3))
+ return sizeof(journal_block_tag3_t);
+
+ sz = sizeof(journal_block_tag_t);

if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V2))
- x += sizeof(tag.t_checksum);
+ sz += sizeof(__u16);

if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_64BIT))
- return x + JBD_TAG_SIZE64;
- else
- return x + JBD_TAG_SIZE32;
+ return sz;
+
+ return sz - sizeof(__u32);
+}
+
+_INLINE_ int journal_has_csum_v2or3(journal_t *journal)
+{
+ if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V2) ||
+ JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V3))
+ return 1;
+
+ return 0;
}
#undef _INLINE_
#endif
diff --git a/misc/dumpe2fs.c b/misc/dumpe2fs.c
index a1c5ba2..25dce9c 100644
--- a/misc/dumpe2fs.c
+++ b/misc/dumpe2fs.c
@@ -415,8 +415,10 @@ static void print_inline_journal_information(ext2_filsys fs)
if (jsb->s_feature_compat &
ext2fs_cpu_to_be32(JFS_FEATURE_COMPAT_CHECKSUM))
printf("%s", _("Journal checksum type: crc32\n"));
- if (jsb->s_feature_incompat &
- ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_CSUM_V2))
+ if ((jsb->s_feature_incompat &
+ ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_CSUM_V3)) ||
+ (jsb->s_feature_incompat &
+ ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_CSUM_V2)))
printf(_("Journal checksum type: %s\n"
"Journal checksum: 0x%08x\n"),
journal_checksum_type_str(jsb->s_checksum_type),
@@ -454,8 +456,10 @@ static void print_journal_information(ext2_filsys fs)
if (jsb->s_feature_compat &
ext2fs_cpu_to_be32(JFS_FEATURE_COMPAT_CHECKSUM))
printf("%s", _("Journal checksum type: crc32\n"));
- if (jsb->s_feature_incompat &
- ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_CSUM_V2))
+ if ((jsb->s_feature_incompat &
+ ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_CSUM_V3)) ||
+ (jsb->s_feature_incompat &
+ ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_CSUM_V2)))
printf(_("Journal checksum type: %s\n"
"Journal checksum: 0x%08x\n"),
journal_checksum_type_str(jsb->s_checksum_type),


2014-09-08 23:12:02

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 03/25] misc: don't return ENOMEM if we run out of disk space

If there aren't enough blocks in the FS to allocate all of the
hugefiles, return ENOSPC, not ENOMEM.

Signed-off-by: Darrick J. Wong <[email protected]>
---
misc/mk_hugefiles.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)


diff --git a/misc/mk_hugefiles.c b/misc/mk_hugefiles.c
index 8291f01..3e4274c 100644
--- a/misc/mk_hugefiles.c
+++ b/misc/mk_hugefiles.c
@@ -530,10 +530,10 @@ errcode_t mk_hugefiles(ext2_filsys fs, const char *device_name)

fs_blocks = ext2fs_free_blocks_count(fs->super);
if (fs_blocks < num_slack + align)
- return ENOMEM;
+ return ENOSPC;
fs_blocks -= num_slack + align;
if (num_blocks && num_blocks > fs_blocks)
- return ENOMEM;
+ return ENOSPC;
if (num_blocks == 0 && num_files == 0)
num_files = 1;



2014-09-08 23:12:13

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 05/25] mke2fs: allow creation of journal device with superblock checksum

Enable mke2fs to create an external journal device with a superblock
checksum.

Signed-off-by: Darrick J. Wong <[email protected]>
Cc: TR Reardon <[email protected]>
---
misc/mke2fs.c | 6 +++++-
tests/m_mcsum_extjournal/expect | 5 +++++
tests/m_mcsum_extjournal/name | 1 +
tests/m_mcsum_extjournal/script | 29 +++++++++++++++++++++++++++++
4 files changed, 40 insertions(+), 1 deletion(-)
create mode 100644 tests/m_mcsum_extjournal/expect
create mode 100644 tests/m_mcsum_extjournal/name
create mode 100644 tests/m_mcsum_extjournal/script


diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index fc03766..2bc435b 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -2124,7 +2124,8 @@ profile_error:
reserved_ratio = 0;
fs_param.s_feature_incompat = EXT3_FEATURE_INCOMPAT_JOURNAL_DEV;
fs_param.s_feature_compat = 0;
- fs_param.s_feature_ro_compat = 0;
+ fs_param.s_feature_ro_compat &=
+ EXT4_FEATURE_RO_COMPAT_METADATA_CSUM;
}

/* Check the user's mkfs options for 64bit */
@@ -2743,6 +2744,8 @@ int main (int argc, char *argv[])

/* Check the user's mkfs options for metadata checksumming */
if (!quiet &&
+ !EXT2_HAS_INCOMPAT_FEATURE(fs->super,
+ EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) &&
EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super,
@@ -2909,6 +2912,7 @@ int main (int argc, char *argv[])
if (fs->super->s_feature_incompat &
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
create_journal_dev(fs);
+ printf("\n");
exit(ext2fs_close_free(&fs) ? 1 : 0);
}

diff --git a/tests/m_mcsum_extjournal/expect b/tests/m_mcsum_extjournal/expect
new file mode 100644
index 0000000..ef895f8
--- /dev/null
+++ b/tests/m_mcsum_extjournal/expect
@@ -0,0 +1,5 @@
+Creating filesystem with 4096 1k blocks and 0 inodes
+Superblock backups stored on blocks:
+
+Zeroing journal device: 
+Filesystem features: journal_dev metadata_csum
diff --git a/tests/m_mcsum_extjournal/name b/tests/m_mcsum_extjournal/name
new file mode 100644
index 0000000..7df8389
--- /dev/null
+++ b/tests/m_mcsum_extjournal/name
@@ -0,0 +1 @@
+create external journal with sb checksum (metadata_csum)
diff --git a/tests/m_mcsum_extjournal/script b/tests/m_mcsum_extjournal/script
new file mode 100644
index 0000000..624bf02
--- /dev/null
+++ b/tests/m_mcsum_extjournal/script
@@ -0,0 +1,29 @@
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+$MKE2FS -F -o Linux -b 1024 -O journal_dev,metadata_csum -T ext4 $TMPFILE 4096 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT 2>&1
+$DUMPE2FS -h $TMPFILE 2>&1 | grep 'Filesystem features:' >> $OUT
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP


2014-09-08 23:12:21

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 06/25] e2fsck: detect and repair external journal superblock checksum errors

Verify the (ext4) superblock checksum of an external journal device
and prompt to correct the checksum if nothing else is wrong with the
superblock.

Signed-off-by: Darrick J. Wong <[email protected]>
Cc: TR Reardon <[email protected]>
---
e2fsck/journal.c | 25 ++++++++++++++
e2fsck/problem.c | 5 +++
e2fsck/problem.h | 3 ++
tests/j_corrupt_ext_jnl_sb_block/expect | 5 +++
tests/j_corrupt_ext_jnl_sb_block/image.tar.bz2 | Bin
tests/j_corrupt_ext_jnl_sb_block/name | 1 +
tests/j_corrupt_ext_jnl_sb_block/script | 36 +++++++++++++++++++++
tests/j_corrupt_ext_jnl_sb_csum/expect | 25 ++++++++++++++
tests/j_corrupt_ext_jnl_sb_csum/image.tar.bz2 | Bin
tests/j_corrupt_ext_jnl_sb_csum/name | 1 +
tests/j_corrupt_ext_jnl_sb_csum/script | 42 ++++++++++++++++++++++++
11 files changed, 142 insertions(+), 1 deletion(-)
create mode 100644 tests/j_corrupt_ext_jnl_sb_block/expect
create mode 100644 tests/j_corrupt_ext_jnl_sb_block/image.tar.bz2
create mode 100644 tests/j_corrupt_ext_jnl_sb_block/name
create mode 100644 tests/j_corrupt_ext_jnl_sb_block/script
create mode 100644 tests/j_corrupt_ext_jnl_sb_csum/expect
create mode 100644 tests/j_corrupt_ext_jnl_sb_csum/image.tar.bz2
create mode 100644 tests/j_corrupt_ext_jnl_sb_csum/name
create mode 100644 tests/j_corrupt_ext_jnl_sb_csum/script


diff --git a/e2fsck/journal.c b/e2fsck/journal.c
index a19d40b..16bd757 100644
--- a/e2fsck/journal.c
+++ b/e2fsck/journal.c
@@ -456,7 +456,6 @@ static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
}
memcpy(&jsuper, start ? bh->b_data : bh->b_data + SUPERBLOCK_OFFSET,
sizeof(jsuper));
- brelse(bh);
#ifdef WORDS_BIGENDIAN
if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
ext2fs_swap_super(&jsuper);
@@ -465,6 +464,7 @@ static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
!(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
retval = EXT2_ET_LOAD_EXT_JOURNAL;
+ brelse(bh);
goto errout;
}
/* Make sure the journal UUID is correct */
@@ -472,9 +472,32 @@ static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
sizeof(jsuper.s_uuid))) {
fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
retval = EXT2_ET_LOAD_EXT_JOURNAL;
+ brelse(bh);
goto errout;
}

+ /* Check the superblock checksum */
+ if (jsuper.s_feature_ro_compat &
+ EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) {
+ struct struct_ext2_filsys fsx;
+ struct ext2_super_block superx;
+ void *p;
+
+ p = start ? bh->b_data : bh->b_data + SUPERBLOCK_OFFSET;
+ memcpy(&fsx, ctx->fs, sizeof(fsx));
+ memcpy(&superx, ctx->fs->super, sizeof(superx));
+ fsx.super = &superx;
+ fsx.super->s_feature_ro_compat |=
+ EXT4_FEATURE_RO_COMPAT_METADATA_CSUM;
+ if (!ext2fs_superblock_csum_verify(&fsx, p) &&
+ fix_problem(ctx, PR_0_EXT_JOURNAL_SUPER_CSUM_INVALID,
+ &pctx)) {
+ ext2fs_superblock_csum_set(&fsx, p);
+ mark_buffer_dirty(bh);
+ }
+ }
+ brelse(bh);
+
maxlen = ext2fs_blocks_count(&jsuper);
journal->j_maxlen = (maxlen < 1ULL << 32) ? maxlen : (1ULL << 32) - 1;
start++;
diff --git a/e2fsck/problem.c b/e2fsck/problem.c
index 99ca7cb..4b41a21 100644
--- a/e2fsck/problem.c
+++ b/e2fsck/problem.c
@@ -459,6 +459,11 @@ static struct e2fsck_problem problem_table[] = {
N_("First_meta_bg is too big. (%N, max value %g). "),
PROMPT_CLEAR, 0 },

+ /* External journal has corrupt superblock */
+ { PR_0_EXT_JOURNAL_SUPER_CSUM_INVALID,
+ N_("External @j @S checksum does not match @S. "),
+ PROMPT_FIX, PR_PREEN_OK },
+
/* Pass 1 errors */

/* Pass 1: Checking inodes, blocks, and sizes */
diff --git a/e2fsck/problem.h b/e2fsck/problem.h
index 5c92d0a..f86c531 100644
--- a/e2fsck/problem.h
+++ b/e2fsck/problem.h
@@ -264,6 +264,9 @@ struct problem_context {
/* The first_meta_bg is too big */
#define PR_0_FIRST_META_BG_TOO_BIG 0x000049

+/* External journal has corrupt superblock */
+#define PR_0_EXT_JOURNAL_SUPER_CSUM_INVALID 0x00004A
+
/*
* Pass 1 errors
*/
diff --git a/tests/j_corrupt_ext_jnl_sb_block/expect b/tests/j_corrupt_ext_jnl_sb_block/expect
new file mode 100644
index 0000000..e638e11
--- /dev/null
+++ b/tests/j_corrupt_ext_jnl_sb_block/expect
@@ -0,0 +1,5 @@
+External journal does not support this filesystem
+
+test_filesys: ********** WARNING: Filesystem still has errors **********
+
+Exit status is 12
diff --git a/tests/j_corrupt_ext_jnl_sb_block/image.tar.bz2 b/tests/j_corrupt_ext_jnl_sb_block/image.tar.bz2
new file mode 100644
index 0000000000000000000000000000000000000000..efb382fafeb26de434c8d182fa155abe803e3d02
GIT binary patch
literal 939
zcmV;c162G%T4*^jL0KkKSz<fD_W**WfB*mg{mfbo|Lyj@{%QaJ-@)M(+E(B<X47Hk
zDTgOh>|ekG2LLG)kd#R@WKUFi2x+0}Jtw5~2GlV$&>Cm~>H+EofEqMt4X6Ma8Uxe~
z9!(~XYMOeVst7d5$TDIy(*kLN448}rWYMD#Vi^pYGGK;ACWZ)P$j~&zGz^BBFd)+-
zAjyc+ObMn4GGZ_hlSYg|h-5No$$}XeniwIIBS6y-&@viiz$8$FDL)YOQ`FKnqiTAX
z5$Ge(jW(u+nW_4w6F>$Lk?K7(XhQ_`Gyq{RO{Dc2F+DVqhfapJ9@oAhS;CWf=SQ~a
zuQoD6kcXKJiz*~_ZXx8j*}Yucz26L#7jq9SE?xC|wg$ngaj8~*y3`^O*Dj(sEt;Yb
zkq*`!ju+iJ64CqcO8J06hRZ;a1X^vRj3$s$!3i(%q_P?SMe6_rfhDhKNg(klGBovh
zRqjrdY>+_~5puf)sKbV_sOjJ<o^HA(4!ZHX8vifMqZ45~T<{ga`1JAY$S7@yJ}*k_
zLh*&;1cZP9oussF2(Q=2h>4hMFW}gs^iHe4YL<mr34#Ft0fIG%(NJ<2uo}{`EEQHv
zGy%J5D7pp`dwWm|A&g^Pu1zq-QHZM5k%GW#EjA<}00Cya0+UMtXFE*sT-vj|RQl!u
zhj4xdblm)?7MM~<fn};Qk|BpSg#UA9K_|v$ihLs6gU+#DJw^@Ik*2pKi|@{2F&+!@
zI7mb&?%T}HNSP2SPEvB6@7pi|Q4A4N@4aDbax+eOMkgg^V5KZSwXC6R5Hiiy&cWeh
zhNvLG$;rheDGFvlVTxgpQ6&L!<HYP#CL;=lsM?}H+-M;pX3-<Fl(Q8Awd)^*eami&
z+bt4%0>!e*r8|eYggc?+WlaspJ{tNCYn(D|l0r*WQ81JVr28xRF?NG!CYeCG?8Bdr
zJ=4@)7h%>R7R?k)Qi!8;RPYMWzC2dWYKsWHGM}c?r2zO2rGcxizBrfn!EszVfuJFe
zO$J9ys&5bIq>Sf>wK~KK-w*ReW2$iJ3}M8Y`wCNixB&*I8YNpr9GMFpWWV^NAFM0N
z&PS%6Aghy*UE)^yo5Vx;kd;;WJwo;^d~8991x?h+&FTl^HT^^&fNMsih01_0QX`4a
z2q8`lVY|9a@Qy9-vu;}+`3+l0(gs-skFzQXAV2^V3%?Be2@sLUV4yHFd=ZLKMq)So
NUC9*TLP3b{1KjPKr%M0;

literal 0
HcmV?d00001

diff --git a/tests/j_corrupt_ext_jnl_sb_block/name b/tests/j_corrupt_ext_jnl_sb_block/name
new file mode 100644
index 0000000..a5188be
--- /dev/null
+++ b/tests/j_corrupt_ext_jnl_sb_block/name
@@ -0,0 +1 @@
+corrupt external journal fs superblock block (metadata_csum)
diff --git a/tests/j_corrupt_ext_jnl_sb_block/script b/tests/j_corrupt_ext_jnl_sb_block/script
new file mode 100644
index 0000000..02b8e65
--- /dev/null
+++ b/tests/j_corrupt_ext_jnl_sb_block/script
@@ -0,0 +1,36 @@
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+bzip2 -dc < $test_dir/image.tar.bz2 | tar x
+test -d "$JOURNAL_DUMP_DIR" -a -w "$JOURNAL_DUMP_DIR" && cp $test_name.img "$JOURNAL_DUMP_DIR/$test_name.img"
+test -d "$JOURNAL_DUMP_DIR" -a -w "$JOURNAL_DUMP_DIR" && cp $test_name.img.jnl "$JOURNAL_DUMP_DIR/$test_name.img.jnl"
+
+$FSCK $FSCK_OPT -N test_filesys -j $test_name.img.jnl $test_name.img > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+rm -f $TMPFILE $test_name.img $test_name.img.jnl
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
diff --git a/tests/j_corrupt_ext_jnl_sb_csum/expect b/tests/j_corrupt_ext_jnl_sb_csum/expect
new file mode 100644
index 0000000..70a4fe7
--- /dev/null
+++ b/tests/j_corrupt_ext_jnl_sb_csum/expect
@@ -0,0 +1,25 @@
+External journal superblock checksum does not match superblock. Fix? yes
+
+test_filesys: recovering journal
+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
+Block bitmap differences: +(1--31) +34 +(50--82)
+Fix? yes
+
+Inode bitmap differences: +(1--11)
+Fix? yes
+
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 11/128 files (0.0% non-contiguous), 66/2048 blocks
+Exit status is 1
+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/128 files (0.0% non-contiguous), 66/2048 blocks
+Exit status is 0
diff --git a/tests/j_corrupt_ext_jnl_sb_csum/image.tar.bz2 b/tests/j_corrupt_ext_jnl_sb_csum/image.tar.bz2
new file mode 100644
index 0000000000000000000000000000000000000000..d04d584c0389112d09a7427fd967a9d9605e68ac
GIT binary patch
literal 929
zcmV;S177?>T4*^jL0KkKS#@A;5dea(|NsC0{mj`}|L^_xUmpMW-qr2{7r{S85b04)
ztBp5X?Rmfh9ZCfiQ9@A?dPIk&iRm=aiRx`bO*DF$sp<_400*c5Xda*d4^T7!Xc~Hr
z1Jnj;V2=|}KpJVLnrVbGWHJmUhKvCX3<;wn2r_A-Kn4iV#4$9<rXvWznlxcF2m?(t
z(@ijjOol;((9wV)p@B4HVFpb!XaK<)7=|X9G{j*T6Gn_CfJmeeMyHh8jWqQ%4FDQ6
z05ll}hJXM713(6VGynhq8UPv<MB{@dgRy8L@@dqU12~~<oe2xv*oqL8pJ6tWl41I|
zt16?CKWB<YmgibSkI1ZrT1#w^v8*bjUOtf2N5#vkAy$ZRIM@6rjzU{%kV>(DM8h#u
zkpxQHNfr$ttYCzf*`&N}03wqB1c4=F(2_yotT>pN-8vPrq-|Kh8lcyix>U8%GD4$m
zSS5Yc!%W@8MOb$-bdSo?vC6W+7~$B*3VgaT#w22GH1P!{6q-U300LH$sM0G~j%J(R
z5Q`}wrZf%T+~-lMZA#Ez5SSnk02pzsvqa&>F<{!TWK0Pfp5+*T)-hlhh}?q-9k!kV
zq#9w{&?5+jiH#H*DGd|Yn*@-60IFd~uz;)GHelSC^YTr!kO_{of982yy!aH_D+tI@
zWY5|}F66$SSnk*nvyi2eqO>x3CQndRg7FUvD*y?Kk5F*di-ft&S_m=?G)42@8Yqn2
zJ9dkfUBA2E(+CK*8J%U2@uyUR+B;hKSNGC9q1oYB_H5=2mqx065%9v-7!fcywbuk<
zj0P~X83N7%gxLs)XK`vv)G8}@21Y|cXF#M+C^D`XGhD8L2z+UX3i2I{!aDI3?XSz3
z%ELdf5|kfve+B6}Y*6-n`P!0k`ADd)TVlFkZFE<b*a_C8s96RD&|P$ctocsI0PPn+
zdN^T!@jV3KnD2t6@xFjidNYlM1`K%F8&7m66`?U&+#9j_0=Zj<oWJs@%sk}NU|xtu
zO)6y%NdgxxwWJ!Nd8(`kKSKnzv#x-e8Z4dnsetthVUf;ATgsnJ5OIu6`zAIBQM5hz
zOi;7WELoxIJ+Ua{dE2(H`GZVMI+i%`@xlF1uKJVK0@7W%QJJ8~#Rh;`QDHBLh%!aJ
zK$%?$(y5FEtUWMD>)wAV;}3&K1ONg3o+vY?{U8b<fhYXdqBRScfAM!DQ-ui!RtDh^
DW^tU{

literal 0
HcmV?d00001

diff --git a/tests/j_corrupt_ext_jnl_sb_csum/name b/tests/j_corrupt_ext_jnl_sb_csum/name
new file mode 100644
index 0000000..c182f81
--- /dev/null
+++ b/tests/j_corrupt_ext_jnl_sb_csum/name
@@ -0,0 +1 @@
+corrupt external journal fs superblock csum (metadata_csum)
diff --git a/tests/j_corrupt_ext_jnl_sb_csum/script b/tests/j_corrupt_ext_jnl_sb_csum/script
new file mode 100644
index 0000000..7a110bf
--- /dev/null
+++ b/tests/j_corrupt_ext_jnl_sb_csum/script
@@ -0,0 +1,42 @@
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+bzip2 -dc < $test_dir/image.tar.bz2 | tar x
+test -d "$JOURNAL_DUMP_DIR" -a -w "$JOURNAL_DUMP_DIR" && cp $test_name.img "$JOURNAL_DUMP_DIR/$test_name.img"
+test -d "$JOURNAL_DUMP_DIR" -a -w "$JOURNAL_DUMP_DIR" && cp $test_name.img.jnl "$JOURNAL_DUMP_DIR/$test_name.img.jnl"
+
+$FSCK $FSCK_OPT -N test_filesys -j $test_name.img.jnl $test_name.img > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+$FSCK $FSCK_OPT -N test_filesys -j $test_name.img.jnl $test_name.img > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+rm -f $TMPFILE $test_name.img $test_name.img.jnl
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP


2014-09-08 23:12:08

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 04/25] libext2fs: write_journal_inode should check iterate return value

When creating a journal inode, check the return value from
block_iterate3() because otherwise we fail to capture errors such as
being unable to allocate an extent tree block, which leads to e2fsck
creating broken journals.

Signed-off-by: Darrick J. Wong <[email protected]>
---
lib/ext2fs/mkjournal.c | 2 ++
tests/f_jnl_etb_alloc_fail/expect.1 | 31 +++++++++++++++++++++++++++++++
tests/f_jnl_etb_alloc_fail/expect.2 | 20 ++++++++++++++++++++
tests/f_jnl_etb_alloc_fail/image.gz | Bin
tests/f_jnl_etb_alloc_fail/name | 1 +
5 files changed, 54 insertions(+)
create mode 100644 tests/f_jnl_etb_alloc_fail/expect.1
create mode 100644 tests/f_jnl_etb_alloc_fail/expect.2
create mode 100644 tests/f_jnl_etb_alloc_fail/image.gz
create mode 100644 tests/f_jnl_etb_alloc_fail/name


diff --git a/lib/ext2fs/mkjournal.c b/lib/ext2fs/mkjournal.c
index 96b6d36..85f86bf 100644
--- a/lib/ext2fs/mkjournal.c
+++ b/lib/ext2fs/mkjournal.c
@@ -365,6 +365,8 @@ static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,

retval = ext2fs_block_iterate3(fs, journal_ino, BLOCK_FLAG_APPEND,
0, mkjournal_proc, &es);
+ if (retval)
+ goto errout;
if (es.err) {
retval = es.err;
goto errout;
diff --git a/tests/f_jnl_etb_alloc_fail/expect.1 b/tests/f_jnl_etb_alloc_fail/expect.1
new file mode 100644
index 0000000..8f4ebbb
--- /dev/null
+++ b/tests/f_jnl_etb_alloc_fail/expect.1
@@ -0,0 +1,31 @@
+Superblock has an invalid journal (inode 8).
+Clear? yes
+
+*** ext3 journal has been deleted - filesystem is now ext2 only ***
+
+Superblock has_journal flag is clear, but a journal is present.
+Clear? yes
+
+Pass 1: Checking inodes, blocks, and sizes
+Journal inode is not in use, but contains data. Clear? yes
+
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+Block bitmap differences: -(32--33) -(35--49) -(83--511) -(513--1087) -1089
+Fix? yes
+
+Free blocks count wrong for group #0 (0, counted=1022).
+Fix? yes
+
+Free blocks count wrong (0, counted=1022).
+Fix? yes
+
+Recreate journal? yes
+
+Creating journal (1024 blocks): Could not allocate block in ext2 filesystem: while trying to create journal
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 12/128 files (8.3% non-contiguous), 2048/2048 blocks
+Exit status is 1
diff --git a/tests/f_jnl_etb_alloc_fail/expect.2 b/tests/f_jnl_etb_alloc_fail/expect.2
new file mode 100644
index 0000000..69859dd
--- /dev/null
+++ b/tests/f_jnl_etb_alloc_fail/expect.2
@@ -0,0 +1,20 @@
+Pass 1: Checking inodes, blocks, and sizes
+Journal inode is not in use, but contains data. Clear? yes
+
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+Block bitmap differences: -(32--33) -(35--49) -(83--511) -(513--1087) -1089
+Fix? yes
+
+Free blocks count wrong for group #0 (0, counted=1022).
+Fix? yes
+
+Free blocks count wrong (0, counted=1022).
+Fix? yes
+
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 12/128 files (8.3% non-contiguous), 1026/2048 blocks
+Exit status is 1
diff --git a/tests/f_jnl_etb_alloc_fail/image.gz b/tests/f_jnl_etb_alloc_fail/image.gz
new file mode 100644
index 0000000000000000000000000000000000000000..4cf2dbf400ce2d113b886919a4448176b3999956
GIT binary patch
literal 3450
zcmeIwX;6}R90zd9HfzhQX*(uO(q@(#O~N!yBf4v}!VS&R6pbx!v9vT5pPEW7uNv=M
zCG*IGXQ^Dp3&{>lNlDEk4XKb*Nx=hAc>X)RbY@@gD}Uda-^};zXTIp<6(}3g1Zk;(
zQgAxJw0|pV!oIOm>0Ak)bd+sNx@z6Be5kxRch)!AG!B>6<hpx#!Go5vbH92YTDEV8
zYaGt{_OgsS>GhJY#!L4(T#uQ+J)860Zo2YX@V$*+NP&L{hw|X#-4;hn6~XZYl`!vf
zL9eXiM=W(1I^krFa<|J5OS>CheLjr)zTMK4za7>DHTTYH4p*&vt-eOt8O+SVN*(#5
zmK&|#wvmI(KfIN{Pt8kA#<Y5A68<JUZdQN&ILHxwD5#M1xkQ8r@F$!nSzZ(xcHF0V
zZcMJPueZ-guO7Q3V~W$+NtZ`yUdH&+>EL6k;CIw`EY}H_tuVK32!niky90D>4UDW>
z)x6m_{)W&uWj&7jV32Itd+W;V2z_QPYT@a?E`zMB=AkmepEW(^pfDeCttvQB044In
zWw8E-h+s<;=%Qm3EcuJIh$sIg(KbJP+Z0>@K)G}pUA{ti%uqpif*AbQL&XkG8h1h)
zFmjt|xe)5U{3?CG($$F9+Gk~u)m5RvO1x6fxK-%AnlhyXAEqV5rXBpW&s0Inhn+J@
z49bc^2ate3gv{y$?4Wr%{;G~_d5N?I)@sQ>nSMfvci1fgF)8a!7@lF<JF_IM&XY$<
zwG3NAZi8#ANeZ~l_IoayB4OffY$=IsoA%Iz3hX}*QHGJa95vm)Q49t9mEe_y;FRze
zrzWEzw0Ct=kCx9QB-^968m(UiAICVp>DL%b#r%d$z;p046OP=BAm}GXJ{=bW?GTz-
zx`NIr44@LuM9tB*0nW@cxeY|c>REPx?lZnw4aRJRz^K>G%k;Y-C1YHK>xk@P>HAgt
zyJMJ_gqaqrc)Zk72HU5equ9@6p09gomY&*v>aVmfxi{;guQgq#%I1pYmd0yfy;J9x
zyr3|)ZEK%^bRbW4BbYHR7Vtdics9Xab47hM+k3UXCQC#gW=*@(;@}<e@NCEUyJ!se
z>=&ZINq*aoHZN1qE}R^y6GPSm29^2RIF>-yh9X@qorDzmp?kK#_wIkg2;-hj-_^sB
z2+`33&uXc><0p<QRM#I=PUYfPKIacYbl^TWNf1Hd2z?SfX{d}xh!j5!A84oENHaRY
zk{j(ITR@>wenE)%D<jag-v<wD1}q+W`C*n?T9JMRp;So|#yZs7frnN{X0!;@P<53W
zsu~5FV+i(i_0vPM5jg0DKNtZEXS%T6O6{eTxMU+1+@j6$m(S#tOioIdNilY$KUVLa
zQf$r{RvmoLj9NWLt~O_m*&m7DC6c>d<kyL!%>vmTlko8eR#sU1?3Xh!;!(S(!hR2{
zizn0j59i+Rd1SK3coQ*=^~1;;vZaYzifW+NJSS2IoFf@%h)v6sP+8nLpJ8^~^yi-W
zhzRQMX#daeK9YH87xBQH-LT=gU8!6;gXbA&!is6q4AA%l2jH&SD4cS7+2xtLIbPin
zHDhL)G)Lc%2&8+@Uw<BearCCZpOl)x4AeYB&-snoDG|}nL_VH<)V-oo6I!c4;ly_m
zSbp=x!Pz`fTfxM%ze-YE?02cCS9bK7S1btkK^QJtP739f>a-aSOufk<nPdSe6>7@1
zh(ltYvh@yv3N_ZFuTeSGYU6g^v7E4uV#RIym;xit#eJ(uWSRN5ua9@FQH=mGs0cxr
z=SINZV+eYUo1Q3eQ)Gz2lFDv`2Y%*`j-w;EwTE0y!T>BFUY>+%EC6e#8iYSlK#H=n
zwIZkkL`iyfzxH2(nlIAlfS)ncLRzRi^Yiz$M1+jc6`lm7D&d{W&3hpX6VRJnaz&#e
zH&6o_xtzeJO`;xSI`Ld6sOD+uS$wdDI<qge?=_X1?W1cOHdr`>#kMH0D6lB7D6lB7
UDDZy@+!CnJ_LxKFDAYF8zeHzNwEzGB

literal 0
HcmV?d00001

diff --git a/tests/f_jnl_etb_alloc_fail/name b/tests/f_jnl_etb_alloc_fail/name
new file mode 100644
index 0000000..7651fdc
--- /dev/null
+++ b/tests/f_jnl_etb_alloc_fail/name
@@ -0,0 +1 @@
+can't allocate extent tree block while recreating journal


2014-09-08 23:12:27

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 07/25] tune2fs: explicitly disallow tuning of journal devices

Spit out a more specific error if someone tries to modify an
external journal device.

Signed-off-by: Darrick J. Wong <[email protected]>
Reported-by: TR Reardon <[email protected]>
---
misc/tune2fs.c | 8 +++++++-
tests/t_ext_jnl_fail/expect | 6 ++++++
tests/t_ext_jnl_fail/name | 1 +
tests/t_ext_jnl_fail/script | 30 ++++++++++++++++++++++++++++++
4 files changed, 44 insertions(+), 1 deletion(-)
create mode 100644 tests/t_ext_jnl_fail/expect
create mode 100644 tests/t_ext_jnl_fail/name
create mode 100644 tests/t_ext_jnl_fail/script


diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index ee47c04..c22c8fd 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -2539,7 +2539,7 @@ retry_open:
if ((open_flag & EXT2_FLAG_RW) == 0 || f_flag)
open_flag |= EXT2_FLAG_SKIP_MMP;

- open_flag |= EXT2_FLAG_64BITS;
+ open_flag |= EXT2_FLAG_64BITS | EXT2_FLAG_JOURNAL_DEV_OK;

/* keep the filesystem struct around to dump MMP data */
open_flag |= EXT2_FLAG_NOFREE_ON_ERROR;
@@ -2569,6 +2569,12 @@ retry_open:
ext2fs_free(fs);
exit(1);
}
+ if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
+ EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
+ fprintf(stderr, "%s", _("Cannot modify a journal device.\n"));
+ ext2fs_free(fs);
+ exit(1);
+ }
fs->default_bitmap_type = EXT2FS_BMAP64_RBTREE;

if (I_flag && !io_ptr_orig) {
diff --git a/tests/t_ext_jnl_fail/expect b/tests/t_ext_jnl_fail/expect
new file mode 100644
index 0000000..db0aecb
--- /dev/null
+++ b/tests/t_ext_jnl_fail/expect
@@ -0,0 +1,6 @@
+Creating filesystem with 4096 1k blocks and 0 inodes
+Superblock backups stored on blocks:
+
+Zeroing journal device: 
+tune2fs external journal
+Cannot modify a journal device.
diff --git a/tests/t_ext_jnl_fail/name b/tests/t_ext_jnl_fail/name
new file mode 100644
index 0000000..2fe7d04
--- /dev/null
+++ b/tests/t_ext_jnl_fail/name
@@ -0,0 +1 @@
+tune2fs fail external journal
diff --git a/tests/t_ext_jnl_fail/script b/tests/t_ext_jnl_fail/script
new file mode 100644
index 0000000..bb31cc7
--- /dev/null
+++ b/tests/t_ext_jnl_fail/script
@@ -0,0 +1,30 @@
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+$MKE2FS -F -o Linux -b 1024 -O journal_dev,metadata_csum -T ext4 $TMPFILE 4096 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT 2>&1
+echo "tune2fs external journal" >> $OUT
+$TUNE2FS -i 0 $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP


2014-09-08 23:12:34

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 08/25] dumpe2fs: display external journal feature flags

Display the feature flags of an external journal.

Signed-off-by: Darrick J. Wong <[email protected]>
Reported-by: TR Reardon <[email protected]>
---
misc/dumpe2fs.c | 14 ++++++++++
tests/j_ext_dumpe2fs/expect | 55 +++++++++++++++++++++++++++++++++++++++++
tests/j_ext_dumpe2fs/image.gz | Bin
tests/j_ext_dumpe2fs/name | 1 +
tests/j_ext_dumpe2fs/script | 40 ++++++++++++++++++++++++++++++
5 files changed, 109 insertions(+), 1 deletion(-)
create mode 100644 tests/j_ext_dumpe2fs/expect
create mode 100644 tests/j_ext_dumpe2fs/image.gz
create mode 100644 tests/j_ext_dumpe2fs/name
create mode 100644 tests/j_ext_dumpe2fs/script


diff --git a/misc/dumpe2fs.c b/misc/dumpe2fs.c
index 25dce9c..4c7bf46 100644
--- a/misc/dumpe2fs.c
+++ b/misc/dumpe2fs.c
@@ -433,8 +433,9 @@ static void print_journal_information(ext2_filsys fs)
errcode_t retval;
char buf[1024];
char str[80];
- unsigned int i;
+ unsigned int i, j, printed = 0;
journal_superblock_t *jsb;
+ __u32 *mask_ptr, mask, m;

/* Get the journal superblock */
if ((retval = io_channel_read_blk64(fs->io,
@@ -465,6 +466,17 @@ static void print_journal_information(ext2_filsys fs)
journal_checksum_type_str(jsb->s_checksum_type),
ext2fs_be32_to_cpu(jsb->s_checksum));

+ printf("%s", _("Journal features: "));
+ for (i = 0, mask_ptr = &jsb->s_feature_compat; i < 3; i++, mask_ptr++) {
+ mask = be32_to_cpu(*mask_ptr);
+ for (j = 0, m = 1; j < 32; j++, m <<= 1) {
+ if (mask & m) {
+ printf(" %s", e2p_jrnl_feature2string(i, m));
+ printed++;
+ }
+ }
+ }
+
printf(_("\nJournal block size: %u\n"
"Journal length: %u\n"
"Journal first block: %u\n"
diff --git a/tests/j_ext_dumpe2fs/expect b/tests/j_ext_dumpe2fs/expect
new file mode 100644
index 0000000..c75f74c
--- /dev/null
+++ b/tests/j_ext_dumpe2fs/expect
@@ -0,0 +1,55 @@
+e2fsck external journal
+../e2fsck/e2fsck: Filesystem has unsupported feature(s) while trying to open test.img
+
+The superblock could not be read or does not describe a valid ext2/ext3/ext4
+filesystem. If the device is valid and it really contains an ext2/ext3/ext4
+filesystem (and not swap or ufs or something else), then the superblock
+is corrupt, and you might try running e2fsck with an alternate superblock:
+ e2fsck -b 8193 <device>
+ or
+ e2fsck -b 32768 <device>
+
+Exit status is 8
+dumpe2fs external journal
+Filesystem volume name: <none>
+Last mounted on: <not available>
+Filesystem magic number: 0xEF53
+Filesystem revision #: 1 (dynamic)
+Filesystem features: journal_dev metadata_csum
+Default mount options: user_xattr acl block_validity
+Filesystem state: clean
+Errors behavior: Continue
+Filesystem OS type: Linux
+Inode count: 0
+Block count: 2048
+Reserved block count: 0
+Free blocks: 0
+Free inodes: 0
+First block: 1
+Block size: 1024
+Fragment size: 1024
+Blocks per group: 8192
+Fragments per group: 8192
+Inodes per group: 0
+Inode blocks per group: 0
+Mount count: 0
+Check interval: 0 (<none>)
+Reserved blocks uid: 0
+Reserved blocks gid: 0
+First inode: 11
+Inode size: 256
+Required extra isize: 28
+Desired extra isize: 28
+Default directory hash: half_md4
+Checksum type: crc32c
+Checksum: 0x3a9935ab
+Journal checksum type: crc32c
+Journal checksum: 0x661e816f
+Journal features: journal_64bit journal_checksum_v3
+Journal block size: 1024
+Journal length: 2048
+Journal first block: 3
+Journal sequence: 0x00000003
+Journal start: 0
+Journal number of users: 1
+Journal users: 117f752e-f27d-4f6f-a652-072586a29b82
diff --git a/tests/j_ext_dumpe2fs/image.gz b/tests/j_ext_dumpe2fs/image.gz
new file mode 100644
index 0000000000000000000000000000000000000000..781b591c0f81778a4209096878b15bc0be99e04e
GIT binary patch
literal 2963
zcmeIu{ZpC+00(euw^_RI&`eE((a35qap@MVrQV{cx#nCr=F8OE(saJ$Is<VK&u&i1
zbLpJ3@`ah+rb}g=3JAX8sZ)b+Y6BD;hz=1D*;s)3@H|hu{)~?APv7tN#}Bsh6^{+E
zSK`Y%EGov2iDyDQpE9zQG)`CIIHqBNbdsCQJ&*>HjK|}0Lvw+$Oz)v{aRGR2%Pkxl
zLdW`|lNPYM(6I!CGO7l>3p$e!{W*TWYV5U&tCl8CeZfbC>9Ga3Am-2Ey@m~@lUQuc
z+c?sQAGxAf6gMhp6O@$W%G=AWc%xBdZRa_u%}xhsnEu1~4{VyiZ(WuS@=LR2X*QSX
zF4$Iw(k55S*XJX_%{1@T0+tiX^6U=~i-^MyaAmfKxyqIAgWehrD;qs2qa8KnP4c*0
zM)ova#Jom9J+h(I2^ab0lkDp&Lanj&Sx5>Z_%K+-j(B`}oBG)0uy{946sR1MXvWSR
zU+6chCoc(o+iE+c8T6brD2PBvOtH!5_y=|NJ_^_j&q80Wy(k<r>W3P9DY#v{{w;j}
ztM))p9r^3!kqoSf4h3uHXNzWkhpI43P1I!J+o!y^hj~6RwDvl+?#}aN4mj}lsyAX0
zYU!E!o135RdlJfaoX&}=s!(n>sLMxNVv4Laq>cV0@yyZbr`4`1gU$8}d)?m6!ga#L
z>L>ciYx(ah3a2`dk)}bHKThpyCT7Z;H!10?{Hgc~dvLGGDk2hqtf}~){u|c6q#6D_
z#PRLY9+Q~2p8!y&G=XLxNe41^b<lMf#~^nB=@iH!vI6I(;w$ap&uhyK`bqY>teZuq
zuylSUTd(36C%T&Jqc#iDVbu)|#!SrCSEkx*ek5A-i(h*P%7<Ou)U#o~$s%ZPEFv<L
z4_UI(FQ*L22kv}xNk~6nAqv9ry!z5pTn9OCIna3RJYU*BJ@WDTpM%{kF6N;}T*2@$
zm1Ntg;bB1Q*QrhyoV8lAwz2XZ6d;BTI=l94Y8SQ{u|iAZ7GO0(*b9S5&4T`z^uC_}
zAeAh&7J^PKveKg<FCsDGfIj5jiB9z}1_UCg*Wa8sAj(h72*zv3VB;m2z~O}V>Lf+<
zy*DrDx*c_$p?&<~uB7xx12A`^O}d*ia^zr$)KjT}^NY7w=i}xSlvvFNe7xBHdXE9|
z27u_eyj5f%J`BOW>luj>vB%273vYAv&-^>%$8zu1BiS>Fu&y?MDPR`s1Tq53v`D-F
zN#qy9ItyX3dAAH{50VCtjjGAu9=qMtu=POV%FqsK9u{e~-XZke6B=^NGo-!H&X+vg
gaSONw+yZU^w}4yVe<^UKcQ&KvGxI(Vk3Am$0x-=eNB{r;

literal 0
HcmV?d00001

diff --git a/tests/j_ext_dumpe2fs/name b/tests/j_ext_dumpe2fs/name
new file mode 100644
index 0000000..60d276c
--- /dev/null
+++ b/tests/j_ext_dumpe2fs/name
@@ -0,0 +1 @@
+dumpe2fs of external journal device
diff --git a/tests/j_ext_dumpe2fs/script b/tests/j_ext_dumpe2fs/script
new file mode 100644
index 0000000..1611c45
--- /dev/null
+++ b/tests/j_ext_dumpe2fs/script
@@ -0,0 +1,40 @@
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+gunzip < $test_dir/image.gz > $TMPFILE
+
+echo "e2fsck external journal" >> $OUT
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+echo "dumpe2fs external journal" >> $OUT
+$DUMPE2FS $TMPFILE > $OUT.new 2>&1
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP


2014-09-08 23:12:40

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 09/25] misc: zero s_jnl_blocks when removing internal journal

When we're removing the internal journal (broken journal, turning it
off, or adding an external journal), zero s_jnl_blocks so that they
can't be picked up by accident later.

Signed-off-by: Darrick J. Wong <[email protected]>
Cc: TR Reardon <[email protected]>
---
e2fsck/journal.c | 1 +
lib/ext2fs/mkjournal.c | 1 +
misc/tune2fs.c | 1 +
3 files changed, 3 insertions(+)


diff --git a/e2fsck/journal.c b/e2fsck/journal.c
index 16bd757..d12e317 100644
--- a/e2fsck/journal.c
+++ b/e2fsck/journal.c
@@ -549,6 +549,7 @@ static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
"filesystem is now ext2 only ***\n\n");
sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
sb->s_journal_inum = 0;
+ memset(sb->s_jnl_blocks, 0, sizeof(sb->s_jnl_blocks));
ctx->flags |= E2F_FLAG_JOURNAL_INODE;
ctx->fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
e2fsck_clear_recover(ctx, 1);
diff --git a/lib/ext2fs/mkjournal.c b/lib/ext2fs/mkjournal.c
index 85f86bf..0a7cd18 100644
--- a/lib/ext2fs/mkjournal.c
+++ b/lib/ext2fs/mkjournal.c
@@ -490,6 +490,7 @@ errcode_t ext2fs_add_journal_device(ext2_filsys fs, ext2_filsys journal_dev)
fs->super->s_journal_dev = st.st_rdev;
memcpy(fs->super->s_journal_uuid, jsb->s_uuid,
sizeof(fs->super->s_journal_uuid));
+ memset(fs->super->s_jnl_blocks, 0, sizeof(fs->super->s_jnl_blocks));
fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
ext2fs_mark_super_dirty(fs);
return 0;
diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index c22c8fd..7292ab1 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -377,6 +377,7 @@ static errcode_t remove_journal_inode(ext2_filsys fs)
return retval;
}
fs->super->s_journal_inum = 0;
+ memset(fs->super->s_jnl_blocks, 0, sizeof(fs->super->s_jnl_blocks));
ext2fs_mark_super_dirty(fs);

return 0;


2014-09-08 23:11:54

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 02/25] libext2fs: report bad magic over bad sb checksum

We don't want ext2fs_open2() to report bad sb checksum on something
that's not even an ext* superblock. This apparently happens pretty
easily if we try to open an XFS filesystem. Thus, make it so that a
bad magic number code always trumps the sb checksum error code.

Signed-off-by: Darrick J. Wong <[email protected]>
---
lib/ext2fs/openfs.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)


diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c
index 00320f3..1d6f147 100644
--- a/lib/ext2fs/openfs.c
+++ b/lib/ext2fs/openfs.c
@@ -221,8 +221,6 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
retval = EXT2_ET_UNKNOWN_CSUM;
if (!ext2fs_superblock_csum_verify(fs, fs->super))
retval = EXT2_ET_SB_CSUM_INVALID;
- if (retval)
- goto cleanup;
}

#ifdef WORDS_BIGENDIAN
@@ -235,10 +233,11 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
}
#endif

- if (fs->super->s_magic != EXT2_SUPER_MAGIC) {
+ if (fs->super->s_magic != EXT2_SUPER_MAGIC)
retval = EXT2_ET_BAD_MAGIC;
+ if (retval)
goto cleanup;
- }
+
if (fs->super->s_rev_level > EXT2_LIB_CURRENT_REV) {
retval = EXT2_ET_REV_TOO_HIGH;
goto cleanup;


2014-09-08 23:12:47

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 10/25] debugfs: create journal handling routines

Create a journal.c with routines adapted from e2fsck/journal.c to
handle opening and closing the journal, and setting up the
descriptors, and all that. Unlike e2fsck's versions which try to
identify and fix problems, the routines here have no way to repair
anything.

v2: Don't feed ext2_filsys state flags to the IO manager file open
routine. Fix a few bugs when handling external journal devices.

Signed-off-by: Darrick J. Wong <[email protected]>
---
debugfs/Makefile.in | 54 ++-
debugfs/jfs_user.h | 144 +++++++
debugfs/journal.c | 935 +++++++++++++++++++++++++++++++++++++++++++++
lib/ext2fs/Makefile.in | 20 +
lib/ext2fs/ext2_err.et.in | 3
lib/ext2fs/ext2fs.h | 3
6 files changed, 1153 insertions(+), 6 deletions(-)
create mode 100644 debugfs/journal.c


diff --git a/debugfs/Makefile.in b/debugfs/Makefile.in
index 0f23595..9523b9b 100644
--- a/debugfs/Makefile.in
+++ b/debugfs/Makefile.in
@@ -19,7 +19,7 @@ MK_CMDS= _SS_DIR_OVERRIDE=../lib/ss ../lib/ss/mk_cmds
DEBUG_OBJS= debug_cmds.o debugfs.o util.o ncheck.o icheck.o ls.o \
lsdel.o dump.o set_fields.o logdump.o htree.o unused.o e2freefrag.o \
filefrag.o extent_cmds.o extent_inode.o zap.o create_inode.o \
- quota.o xattrs.o
+ quota.o xattrs.o journal.o revoke.o recovery.o

RO_DEBUG_OBJS= ro_debug_cmds.o ro_debugfs.o util.o ncheck.o icheck.o ls.o \
lsdel.o logdump.o htree.o e2freefrag.o filefrag.o extent_cmds.o \
@@ -30,7 +30,9 @@ SRCS= debug_cmds.c $(srcdir)/debugfs.c $(srcdir)/util.c $(srcdir)/ls.c \
$(srcdir)/dump.c $(srcdir)/set_fields.c ${srcdir}/logdump.c \
$(srcdir)/htree.c $(srcdir)/unused.c ${srcdir}/../misc/e2freefrag.c \
$(srcdir)/filefrag.c $(srcdir)/extent_inode.c $(srcdir)/zap.c \
- $(srcdir)/../misc/create_inode.c $(srcdir)/xattrs.c $(srcdir)/quota.c
+ $(srcdir)/../misc/create_inode.c $(srcdir)/xattrs.c $(srcdir)/quota.c \
+ $(srcdir)/journal.c $(srcdir)/../e2fsck/revoke.c \
+ $(srcdir)/../e2fsck/recovery.c

LIBS= $(LIBQUOTA) $(LIBEXT2FS) $(LIBE2P) $(LIBSS) $(LIBCOM_ERR) $(LIBBLKID) \
$(LIBUUID) $(SYSLIBS)
@@ -85,6 +87,18 @@ e2freefrag.o: $(srcdir)/../misc/e2freefrag.c
$(E) " CC $@"
$(Q) $(CC) -c $(ALL_CFLAGS) -I$(srcdir) $< -DDEBUGFS -o $@

+recovery.o: $(srcdir)/../e2fsck/recovery.c
+ cp $(srcdir)/../e2fsck/recovery.c $(srcdir)/recovery.c
+ $(E) " CC $@"
+ $(Q) $(CC) -c $(ALL_CFLAGS) -I$(srcdir) \
+ $(srcdir)/recovery.c -DDEBUGFS -o $@
+
+revoke.o: $(srcdir)/../e2fsck/revoke.c
+ cp $(srcdir)/../e2fsck/revoke.c $(srcdir)/revoke.c
+ $(E) " CC $@"
+ $(Q) $(CC) -c $(ALL_CFLAGS) -I$(srcdir) \
+ $(srcdir)/revoke.c -DDEBUGFS -o $@
+
create_inode.o: $(srcdir)/../misc/create_inode.c
$(E) " CC $@"
$(Q) $(CC) -c $(ALL_CFLAGS) -I$(srcdir) \
@@ -133,7 +147,8 @@ clean::
mostlyclean: clean
distclean: clean
$(RM) -f debug_cmds.c .depend Makefile $(srcdir)/TAGS \
- $(srcdir)/Makefile.in.old
+ $(srcdir)/Makefile.in.old $(srcdir)/recovery.c \
+ $(srcdir)/revoke.c

# +++ Dependency line eater +++
#
@@ -310,6 +325,39 @@ create_inode.o: $(srcdir)/../misc/create_inode.c \
$(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \
$(srcdir)/../misc/nls-enable.h
+journal.o: $(srcdir)/journal.c $(top_builddir)/lib/config.h \
+ $(top_builddir)/lib/dirpaths.h $(srcdir)/jfs_user.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/bitops.h \
+ $(top_srcdir)/lib/quota/quotaio.h \
+ $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \
+ $(top_srcdir)/lib/../e2fsck/dict.h $(top_srcdir)/lib/ext2fs/kernel-jbd.h \
+ $(top_srcdir)/lib/ext2fs/jfs_compat.h $(top_srcdir)/lib/ext2fs/kernel-list.h
+recovery.o: $(srcdir)/../e2fsck/recovery.c $(top_builddir)/lib/config.h \
+ $(top_builddir)/lib/dirpaths.h $(srcdir)/jfs_user.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/bitops.h \
+ $(top_srcdir)/lib/quota/quotaio.h \
+ $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \
+ $(top_srcdir)/lib/../e2fsck/dict.h $(top_srcdir)/lib/ext2fs/kernel-jbd.h \
+ $(top_srcdir)/lib/ext2fs/jfs_compat.h $(top_srcdir)/lib/ext2fs/kernel-list.h
+revoke.o: $(srcdir)/../e2fsck/revoke.c $(top_builddir)/lib/config.h \
+ $(top_builddir)/lib/dirpaths.h $(srcdir)/jfs_user.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/bitops.h \
+ $(top_srcdir)/lib/quota/quotaio.h \
+ $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \
+ $(top_srcdir)/lib/../e2fsck/dict.h $(top_srcdir)/lib/ext2fs/kernel-jbd.h \
+ $(top_srcdir)/lib/ext2fs/jfs_compat.h $(top_srcdir)/lib/ext2fs/kernel-list.h
xattrs.o: $(srcdir)/xattrs.c $(srcdir)/debugfs.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 \
diff --git a/debugfs/jfs_user.h b/debugfs/jfs_user.h
index 66756fc..1a80ecb 100644
--- a/debugfs/jfs_user.h
+++ b/debugfs/jfs_user.h
@@ -1,10 +1,152 @@
+/*
+ * Compatibility header file for e2fsck which should be included
+ * instead of linux/jfs.h
+ *
+ * Copyright (C) 2000 Stephen C. Tweedie
+ *
+ * This file may be redistributed under the terms of the
+ * GNU General Public License version 2 or at your discretion
+ * any later version.
+ */
#ifndef _JFS_USER_H
#define _JFS_USER_H

-typedef unsigned short kdev_t;
+#if EXT2_FLAT_INCLUDES
+#include "ext2_fs.h"
+#include "ext2fs.h"
+#include "blkid.h"
+#else
+#include "ext2fs/ext2_fs.h"
+#include "ext2fs/ext2fs.h"
+#include "blkid/blkid.h"
+#endif

+struct buffer_head {
+ ext2_filsys b_fs;
+ io_channel b_io;
+ int b_size;
+ unsigned long long b_blocknr;
+ int b_dirty;
+ int b_uptodate;
+ int b_err;
+ char b_data[1024];
+};
+
+struct inode {
+ ext2_filsys i_fs;
+ ext2_ino_t i_ino;
+ struct ext2_inode i_ext2;
+};
+
+struct kdev_s {
+ ext2_filsys k_fs;
+ int k_dev;
+};
+
+#define K_DEV_FS 1
+#define K_DEV_JOURNAL 2
+
+typedef struct kdev_s *kdev_t;
+
+#define lock_buffer(bh) do {} while (0)
+#define unlock_buffer(bh) do {} while (0)
+#define buffer_req(bh) 1
+#define do_readahead(journal, start) do {} while (0)
+
+typedef struct {
+ int object_length;
+} lkmem_cache_t;
+
+#define kmem_cache_alloc(cache, flags) malloc((cache)->object_length)
+#define kmem_cache_free(cache, obj) free(obj)
+#define kmem_cache_create(name, len, a, b, c) do_cache_create(len)
+#define kmem_cache_destroy(cache) do_cache_destroy(cache)
+#define kmalloc(len, flags) malloc(len)
+#define kfree(p) free(p)
+
+#define cond_resched() do { } while (0)
+
+typedef unsigned int __be32;
+typedef __u64 __be64;
+
+#define __init
+
+/*
+ * Now pull in the real linux/jfs.h definitions.
+ */
#include <ext2fs/kernel-jbd.h>

+/*
+ * We use the standard libext2fs portability tricks for inline
+ * functions.
+ */
+#ifdef NO_INLINE_FUNCS
+extern lkmem_cache_t *do_cache_create(int len);
+extern void do_cache_destroy(lkmem_cache_t *cache);
+extern size_t journal_tag_bytes(journal_t *journal);
+#endif
+
+#if (defined(E2FSCK_INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS))
+#ifdef E2FSCK_INCLUDE_INLINE_FUNCS
+#if (__STDC_VERSION__ >= 199901L)
+#define _INLINE_ extern inline
+#else
+#define _INLINE_ inline
+#endif
+#else /* !E2FSCK_INCLUDE_INLINE FUNCS */
+#if (__STDC_VERSION__ >= 199901L)
+#define _INLINE_ inline
+#else /* not C99 */
+#ifdef __GNUC__
+#define _INLINE_ extern __inline__
+#else /* For Watcom C */
+#define _INLINE_ extern inline
+#endif /* __GNUC__ */
+#endif /* __STDC_VERSION__ >= 199901L */
+#endif /* E2FSCK_INCLUDE_INLINE_FUNCS */
+
+
+_INLINE_ lkmem_cache_t *do_cache_create(int len)
+{
+ lkmem_cache_t *new_cache;
+
+ new_cache = malloc(sizeof(*new_cache));
+ if (new_cache)
+ new_cache->object_length = len;
+ return new_cache;
+}
+
+_INLINE_ void do_cache_destroy(lkmem_cache_t *cache)
+{
+ free(cache);
+}
+
+#undef _INLINE_
+#endif
+
+/*
+ * 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 sync_blockdev(kdev_t kdev);
+void ll_rw_block(int rw, int dummy, 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);
+int buffer_uptodate(struct buffer_head *bh);
+void wait_on_buffer(struct buffer_head *bh);
+
+/*
+ * Define newer 2.5 interfaces
+ */
+#define __getblk(dev, blocknr, blocksize) getblk(dev, blocknr, blocksize)
+#define set_buffer_uptodate(bh) mark_buffer_uptodate(bh, 1)
+
+#include <assert.h>
+#undef J_ASSERT
+#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_feature_incompat & ext2fs_cpu_to_be32((mask))))
diff --git a/debugfs/journal.c b/debugfs/journal.c
new file mode 100644
index 0000000..99547c9
--- /dev/null
+++ b/debugfs/journal.c
@@ -0,0 +1,935 @@
+/*
+ * journal.c --- code for handling the "ext3" journal
+ *
+ * Copyright (C) 2000 Andreas Dilger
+ * Copyright (C) 2000 Theodore Ts'o
+ *
+ * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * This file may be redistributed under the terms of the
+ * GNU General Public License version 2 or at your discretion
+ * any later version.
+ */
+
+#include "config.h"
+#ifdef HAVE_SYS_MOUNT_H
+#include <sys/param.h>
+#include <sys/mount.h>
+#define MNT_FL (MS_MGC_VAL | MS_RDONLY)
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#define E2FSCK_INCLUDE_INLINE_FUNCS
+#include "jfs_user.h"
+#include "uuid/uuid.h"
+
+#ifdef CONFIG_JBD_DEBUG /* Enabled by configure --enable-jfs-debug */
+static int bh_count = 0;
+#endif
+
+#if EXT2_FLAT_INCLUDES
+#include "blkid.h"
+#else
+#include "blkid/blkid.h"
+#endif
+
+/*
+ * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
+ * This creates a larger static binary, and a smaller binary using
+ * shared libraries. It's also probably slightly less CPU-efficient,
+ * which is why it's not on by default. But, it's a good way of
+ * testing the functions in inode_io.c and fileio.c.
+ */
+#undef USE_INODE_IO
+
+/* Checksumming functions */
+static int ext2fs_journal_verify_csum_type(journal_t *j,
+ journal_superblock_t *jsb)
+{
+ if (!journal_has_csum_v2or3(j))
+ return 1;
+
+ return jsb->s_checksum_type == JBD2_CRC32C_CHKSUM;
+}
+
+static __u32 ext2fs_journal_sb_csum(journal_superblock_t *jsb)
+{
+ __u32 crc, old_crc;
+
+ old_crc = jsb->s_checksum;
+ jsb->s_checksum = 0;
+ crc = ext2fs_crc32c_le(~0, (unsigned char *)jsb,
+ sizeof(journal_superblock_t));
+ jsb->s_checksum = old_crc;
+
+ return crc;
+}
+
+static int ext2fs_journal_sb_csum_verify(journal_t *j,
+ journal_superblock_t *jsb)
+{
+ __u32 provided, calculated;
+
+ if (!journal_has_csum_v2or3(j))
+ return 1;
+
+ provided = ext2fs_be32_to_cpu(jsb->s_checksum);
+ calculated = ext2fs_journal_sb_csum(jsb);
+
+ return provided == calculated;
+}
+
+static errcode_t ext2fs_journal_sb_csum_set(journal_t *j,
+ journal_superblock_t *jsb)
+{
+ __u32 crc;
+
+ if (!journal_has_csum_v2or3(j))
+ return 0;
+
+ crc = ext2fs_journal_sb_csum(jsb);
+ jsb->s_checksum = ext2fs_cpu_to_be32(crc);
+ return 0;
+}
+
+/* Kernel compatibility functions for handling the journal. These allow us
+ * 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)
+{
+#ifdef USE_INODE_IO
+ *phys = block;
+ return 0;
+#else
+ struct inode *inode = journal->j_inode;
+ errcode_t retval;
+ blk64_t pblk;
+
+ if (!inode) {
+ *phys = block;
+ return 0;
+ }
+
+ retval = ext2fs_bmap2(inode->i_fs, inode->i_ino,
+ &inode->i_ext2, NULL, 0, block, 0, &pblk);
+ *phys = pblk;
+ return (int) retval;
+#endif
+}
+
+struct buffer_head *getblk(kdev_t kdev, blk64_t blocknr, int blocksize)
+{
+ struct buffer_head *bh;
+ int bufsize = sizeof(*bh) + kdev->k_fs->blocksize -
+ sizeof(bh->b_data);
+ errcode_t retval;
+
+ retval = ext2fs_get_memzero(bufsize, &bh);
+ if (retval)
+ return NULL;
+
+#ifdef CONFIG_JBD_DEBUG
+ if (journal_enable_debug >= 3)
+ bh_count++;
+#endif
+ jfs_debug(4, "getblk for block %llu (%d bytes)(total %d)\n",
+ (unsigned long long) blocknr, blocksize, bh_count);
+
+ bh->b_fs = kdev->k_fs;
+ if (kdev->k_dev == K_DEV_FS)
+ bh->b_io = kdev->k_fs->io;
+ else
+ bh->b_io = kdev->k_fs->journal_io;
+ bh->b_size = blocksize;
+ bh->b_blocknr = blocknr;
+
+ return bh;
+}
+
+int sync_blockdev(kdev_t kdev)
+{
+ io_channel io;
+
+ if (kdev->k_dev == K_DEV_FS)
+ io = kdev->k_fs->io;
+ else
+ io = kdev->k_fs->journal_io;
+
+ return io_channel_flush(io) ? EIO : 0;
+}
+
+void ll_rw_block(int rw, 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) {
+ jfs_debug(3, "reading block %llu/%p\n",
+ bh->b_blocknr, (void *) bh);
+ retval = io_channel_read_blk64(bh->b_io,
+ bh->b_blocknr,
+ 1, bh->b_data);
+ if (retval) {
+ com_err(bh->b_fs->device_name, retval,
+ "while reading block %llu\n",
+ bh->b_blocknr);
+ bh->b_err = (int) retval;
+ continue;
+ }
+ bh->b_uptodate = 1;
+ } else if (rw == WRITE && bh->b_dirty) {
+ jfs_debug(3, "writing block %llu/%p\n",
+ bh->b_blocknr,
+ (void *) bh);
+ retval = io_channel_write_blk64(bh->b_io,
+ bh->b_blocknr,
+ 1, bh->b_data);
+ if (retval) {
+ com_err(bh->b_fs->device_name, retval,
+ "while writing block %llu\n",
+ bh->b_blocknr);
+ bh->b_err = (int) retval;
+ continue;
+ }
+ bh->b_dirty = 0;
+ bh->b_uptodate = 1;
+ } else {
+ jfs_debug(3, "no-op %s for block %llu\n",
+ rw == READ ? "read" : "write",
+ bh->b_blocknr);
+ }
+ }
+}
+
+void mark_buffer_dirty(struct buffer_head *bh)
+{
+ bh->b_dirty = 1;
+}
+
+static void mark_buffer_clean(struct buffer_head *bh)
+{
+ bh->b_dirty = 0;
+}
+
+void brelse(struct buffer_head *bh)
+{
+ if (bh->b_dirty)
+ ll_rw_block(WRITE, 1, &bh);
+ jfs_debug(3, "freeing block %llu/%p (total %d)\n",
+ bh->b_blocknr, (void *) bh, --bh_count);
+ ext2fs_free_mem(&bh);
+}
+
+int buffer_uptodate(struct buffer_head *bh)
+{
+ return bh->b_uptodate;
+}
+
+void mark_buffer_uptodate(struct buffer_head *bh, int val)
+{
+ bh->b_uptodate = val;
+}
+
+void wait_on_buffer(struct buffer_head *bh)
+{
+ if (!bh->b_uptodate)
+ ll_rw_block(READ, 1, &bh);
+}
+
+
+static void ext2fs_clear_recover(ext2_filsys fs, int error)
+{
+ fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
+
+ /* if we had an error doing journal recovery, we need a full fsck */
+ if (error)
+ fs->super->s_state &= ~EXT2_VALID_FS;
+ ext2fs_mark_super_dirty(fs);
+}
+
+/*
+ * This is a helper function to check the validity of the journal.
+ */
+struct process_block_struct {
+ e2_blkcnt_t last_block;
+};
+
+static int process_journal_block(ext2_filsys fs,
+ blk64_t *block_nr,
+ e2_blkcnt_t blockcnt,
+ blk64_t ref_block EXT2FS_ATTR((unused)),
+ int ref_offset EXT2FS_ATTR((unused)),
+ void *priv_data)
+{
+ struct process_block_struct *p;
+ blk64_t blk = *block_nr;
+
+ p = (struct process_block_struct *) priv_data;
+
+ if (!blk || blk < fs->super->s_first_data_block ||
+ blk >= ext2fs_blocks_count(fs->super))
+ return BLOCK_ABORT;
+
+ if (blockcnt >= 0)
+ p->last_block = blockcnt;
+ return 0;
+}
+
+static errcode_t ext2fs_get_journal(ext2_filsys fs, journal_t **ret_journal)
+{
+ struct process_block_struct pb;
+ struct ext2_super_block *sb = fs->super;
+ struct ext2_super_block jsuper;
+ struct buffer_head *bh;
+ struct inode *j_inode = NULL;
+ struct kdev_s *dev_fs = NULL, *dev_journal;
+ const char *journal_name = 0;
+ journal_t *journal = NULL;
+ errcode_t retval = 0;
+ io_manager io_ptr = 0;
+ unsigned long long start = 0;
+ int ext_journal = 0;
+ int tried_backup_jnl = 0;
+
+ retval = ext2fs_get_memzero(sizeof(journal_t), &journal);
+ if (retval)
+ return retval;
+
+ retval = ext2fs_get_memzero(2 * sizeof(struct kdev_s), &dev_fs);
+ if (retval)
+ goto errout;
+ dev_journal = dev_fs+1;
+
+ dev_fs->k_fs = dev_journal->k_fs = fs;
+ dev_fs->k_dev = K_DEV_FS;
+ dev_journal->k_dev = K_DEV_JOURNAL;
+
+ journal->j_dev = dev_journal;
+ journal->j_fs_dev = dev_fs;
+ journal->j_inode = NULL;
+ journal->j_blocksize = fs->blocksize;
+
+ if (uuid_is_null(sb->s_journal_uuid)) {
+ if (!sb->s_journal_inum) {
+ retval = EXT2_ET_BAD_INODE_NUM;
+ goto errout;
+ }
+ retval = ext2fs_get_memzero(sizeof(*j_inode), &j_inode);
+ if (retval)
+ goto errout;
+
+ j_inode->i_fs = fs;
+ j_inode->i_ino = sb->s_journal_inum;
+
+ retval = ext2fs_read_inode(fs, sb->s_journal_inum,
+ &j_inode->i_ext2);
+ if (retval) {
+try_backup_journal:
+ if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
+ tried_backup_jnl)
+ goto errout;
+ memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
+ memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
+ EXT2_N_BLOCKS*4);
+ j_inode->i_ext2.i_size_high = sb->s_jnl_blocks[15];
+ j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
+ j_inode->i_ext2.i_links_count = 1;
+ j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
+ tried_backup_jnl++;
+ }
+ if (!j_inode->i_ext2.i_links_count ||
+ !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
+ retval = EXT2_ET_NO_JOURNAL;
+ goto try_backup_journal;
+ }
+ if (EXT2_I_SIZE(&j_inode->i_ext2) / journal->j_blocksize <
+ JFS_MIN_JOURNAL_BLOCKS) {
+ retval = EXT2_ET_JOURNAL_TOO_SMALL;
+ goto try_backup_journal;
+ }
+ pb.last_block = -1;
+ retval = ext2fs_block_iterate3(fs, j_inode->i_ino,
+ BLOCK_FLAG_HOLE, 0,
+ process_journal_block, &pb);
+ if ((pb.last_block + 1) * fs->blocksize <
+ (int) EXT2_I_SIZE(&j_inode->i_ext2)) {
+ retval = EXT2_ET_JOURNAL_TOO_SMALL;
+ goto try_backup_journal;
+ }
+ if (tried_backup_jnl && (fs->flags & EXT2_FLAG_RW)) {
+ retval = ext2fs_write_inode(fs, sb->s_journal_inum,
+ &j_inode->i_ext2);
+ if (retval)
+ goto errout;
+ }
+
+ journal->j_maxlen = EXT2_I_SIZE(&j_inode->i_ext2) /
+ journal->j_blocksize;
+
+#ifdef USE_INODE_IO
+ retval = ext2fs_inode_io_intern2(fs, sb->s_journal_inum,
+ &j_inode->i_ext2,
+ &journal_name);
+ if (retval)
+ goto errout;
+
+ io_ptr = inode_io_manager;
+#else
+ journal->j_inode = j_inode;
+ fs->journal_io = fs->io;
+ retval = (errcode_t)journal_bmap(journal, 0, &start);
+ if (retval)
+ goto errout;
+#endif
+ } else {
+ ext_journal = 1;
+ if (!fs->journal_name) {
+ char uuid[37];
+ blkid_cache blkid;
+
+ blkid_get_cache(&blkid, NULL);
+ uuid_unparse(sb->s_journal_uuid, uuid);
+ fs->journal_name = blkid_get_devname(blkid,
+ "UUID", uuid);
+ if (!fs->journal_name)
+ fs->journal_name = blkid_devno_to_devname(sb->s_journal_dev);
+ blkid_put_cache(blkid);
+ }
+ journal_name = fs->journal_name;
+
+ if (!journal_name) {
+ retval = EXT2_ET_LOAD_EXT_JOURNAL;
+ goto errout;
+ }
+
+ jfs_debug(1, "Using journal file %s\n", journal_name);
+ io_ptr = unix_io_manager;
+ }
+
+#if 0
+ test_io_backing_manager = io_ptr;
+ io_ptr = test_io_manager;
+#endif
+#ifndef USE_INODE_IO
+ if (ext_journal)
+#endif
+ {
+ retval = io_ptr->open(journal_name, fs->flags & EXT2_FLAG_RW,
+ &fs->journal_io);
+ }
+ if (retval)
+ goto errout;
+
+ io_channel_set_blksize(fs->journal_io, fs->blocksize);
+
+ if (ext_journal) {
+ blk64_t maxlen;
+
+ start = ext2fs_journal_sb_start(fs->blocksize) - 1;
+ bh = getblk(dev_journal, start, fs->blocksize);
+ if (!bh) {
+ retval = EXT2_ET_NO_MEMORY;
+ goto errout;
+ }
+ ll_rw_block(READ, 1, &bh);
+ retval = bh->b_err;
+ if (retval) {
+ brelse(bh);
+ goto errout;
+ }
+ memcpy(&jsuper, start ? bh->b_data :
+ bh->b_data + SUPERBLOCK_OFFSET,
+ sizeof(jsuper));
+#ifdef WORDS_BIGENDIAN
+ if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
+ ext2fs_swap_super(&jsuper);
+#endif
+ if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
+ !(jsuper.s_feature_incompat &
+ EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
+ retval = EXT2_ET_LOAD_EXT_JOURNAL;
+ brelse(bh);
+ goto errout;
+ }
+ /* Make sure the journal UUID is correct */
+ if (memcmp(jsuper.s_uuid, fs->super->s_journal_uuid,
+ sizeof(jsuper.s_uuid))) {
+ retval = EXT2_ET_LOAD_EXT_JOURNAL;
+ brelse(bh);
+ goto errout;
+ }
+
+ /* Check the superblock checksum */
+ if (jsuper.s_feature_ro_compat &
+ EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) {
+ struct struct_ext2_filsys fsx;
+ struct ext2_super_block superx;
+ void *p;
+
+ p = start ? bh->b_data : bh->b_data + SUPERBLOCK_OFFSET;
+ memcpy(&fsx, fs, sizeof(fsx));
+ memcpy(&superx, fs->super, sizeof(superx));
+ fsx.super = &superx;
+ fsx.super->s_feature_ro_compat |=
+ EXT4_FEATURE_RO_COMPAT_METADATA_CSUM;
+ if (!ext2fs_superblock_csum_verify(&fsx, p)) {
+ retval = EXT2_ET_LOAD_EXT_JOURNAL;
+ brelse(bh);
+ goto errout;
+ }
+ }
+ brelse(bh);
+
+ maxlen = ext2fs_blocks_count(&jsuper);
+ journal->j_maxlen = (maxlen < 1ULL << 32) ? maxlen :
+ (1ULL << 32) - 1;
+ start++;
+ }
+
+ bh = getblk(dev_journal, start, journal->j_blocksize);
+ if (!bh) {
+ retval = EXT2_ET_NO_MEMORY;
+ goto errout;
+ }
+
+ journal->j_sb_buffer = bh;
+ journal->j_superblock = (journal_superblock_t *)bh->b_data;
+
+#ifdef USE_INODE_IO
+ if (j_inode)
+ ext2fs_free_mem(&j_inode);
+#endif
+
+ *ret_journal = journal;
+ return 0;
+
+errout:
+ if (dev_fs)
+ ext2fs_free_mem(&dev_fs);
+ if (j_inode)
+ ext2fs_free_mem(&j_inode);
+ if (journal)
+ ext2fs_free_mem(&journal);
+ return retval;
+}
+
+static errcode_t ext2fs_journal_fix_bad_inode(ext2_filsys fs)
+{
+ struct ext2_super_block *sb = fs->super;
+ int recover = fs->super->s_feature_incompat &
+ EXT3_FEATURE_INCOMPAT_RECOVER;
+ int has_journal = fs->super->s_feature_compat &
+ EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+
+ if (has_journal || sb->s_journal_inum) {
+ /* The journal inode is bogus, remove and force full fsck */
+ return EXT2_ET_BAD_INODE_NUM;
+ } else if (recover) {
+ return EXT2_ET_UNSUPP_FEATURE;
+ }
+ return 0;
+}
+
+#define V1_SB_SIZE 0x0024
+static void clear_v2_journal_fields(journal_t *journal)
+{
+ ext2_filsys fs = journal->j_dev->k_fs;
+
+ memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
+ fs->blocksize-V1_SB_SIZE);
+ mark_buffer_dirty(journal->j_sb_buffer);
+}
+
+
+static errcode_t ext2fs_journal_load(journal_t *journal)
+{
+ ext2_filsys fs = journal->j_dev->k_fs;
+ journal_superblock_t *jsb;
+ struct buffer_head *jbh = journal->j_sb_buffer;
+
+ ll_rw_block(READ, 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))
+ return ext2fs_journal_fix_bad_inode(fs);
+
+ switch (ntohl(jsb->s_header.h_blocktype)) {
+ case JFS_SUPERBLOCK_V1:
+ journal->j_format_version = 1;
+ if (jsb->s_feature_compat ||
+ jsb->s_feature_incompat ||
+ jsb->s_feature_ro_compat ||
+ jsb->s_nr_users)
+ clear_v2_journal_fields(journal);
+ break;
+
+ case JFS_SUPERBLOCK_V2:
+ journal->j_format_version = 2;
+ if (ntohl(jsb->s_nr_users) > 1 &&
+ uuid_is_null(fs->super->s_journal_uuid))
+ clear_v2_journal_fields(journal);
+ if (ntohl(jsb->s_nr_users) > 1)
+ return EXT2_ET_JOURNAL_UNSUPP_VERSION;
+ break;
+
+ /*
+ * These should never appear in a journal super block, so if
+ * they do, the journal is badly corrupted.
+ */
+ case JFS_DESCRIPTOR_BLOCK:
+ case JFS_COMMIT_BLOCK:
+ case JFS_REVOKE_BLOCK:
+ return EXT2_ET_CORRUPT_SUPERBLOCK;
+
+ /* If we don't understand the superblock major type, but there
+ * is a magic number, then it is likely to be a new format we
+ * just don't understand, so leave it alone. */
+ default:
+ return EXT2_ET_JOURNAL_UNSUPP_VERSION;
+ }
+
+ if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
+ return EXT2_ET_UNSUPP_FEATURE;
+
+ if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
+ return EXT2_ET_RO_UNSUPP_FEATURE;
+
+ /* Checksum v1-3 are mutually exclusive features. */
+ if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V2) &&
+ JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V3))
+ return EXT2_ET_CORRUPT_SUPERBLOCK;
+
+ if (journal_has_csum_v2or3(journal) &&
+ JFS_HAS_COMPAT_FEATURE(journal, JFS_FEATURE_COMPAT_CHECKSUM))
+ return EXT2_ET_CORRUPT_SUPERBLOCK;
+
+ if (!ext2fs_journal_verify_csum_type(journal, jsb) ||
+ !ext2fs_journal_sb_csum_verify(journal, jsb))
+ return EXT2_ET_CORRUPT_SUPERBLOCK;
+
+ if (journal_has_csum_v2or3(journal))
+ journal->j_csum_seed = jbd2_chksum(journal, ~0, jsb->s_uuid,
+ sizeof(jsb->s_uuid));
+
+ /* We have now checked whether we know enough about the journal
+ * format to be able to proceed safely, so any other checks that
+ * fail we should attempt to recover from. */
+ if (jsb->s_blocksize != htonl(journal->j_blocksize))
+ return EXT2_ET_CORRUPT_SUPERBLOCK;
+
+ if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
+ journal->j_maxlen = ntohl(jsb->s_maxlen);
+ else if (ntohl(jsb->s_maxlen) > journal->j_maxlen)
+ return EXT2_ET_CORRUPT_SUPERBLOCK;
+
+ journal->j_tail_sequence = ntohl(jsb->s_sequence);
+ journal->j_transaction_sequence = journal->j_tail_sequence;
+ journal->j_tail = ntohl(jsb->s_start);
+ journal->j_first = ntohl(jsb->s_first);
+ journal->j_last = ntohl(jsb->s_maxlen);
+
+ return 0;
+}
+
+void ext2fs_journal_release(ext2_filsys fs, journal_t *journal,
+ int reset, int drop)
+{
+ journal_superblock_t *jsb;
+
+ if (drop)
+ mark_buffer_clean(journal->j_sb_buffer);
+ else if (fs->flags & EXT2_FLAG_RW) {
+ jsb = journal->j_superblock;
+ jsb->s_sequence = htonl(journal->j_tail_sequence);
+ if (reset)
+ jsb->s_start = 0; /* this marks the journal as empty */
+ ext2fs_journal_sb_csum_set(journal, jsb);
+ mark_buffer_dirty(journal->j_sb_buffer);
+ }
+ brelse(journal->j_sb_buffer);
+
+ if (fs->journal_io) {
+ if (fs && fs->io != fs->journal_io)
+ io_channel_close(fs->journal_io);
+ fs->journal_io = 0;
+ }
+
+#ifndef USE_INODE_IO
+ if (journal->j_inode)
+ ext2fs_free_mem(&journal->j_inode);
+#endif
+ if (journal->j_fs_dev)
+ ext2fs_free_mem(&journal->j_fs_dev);
+ ext2fs_free_mem(&journal);
+}
+
+/*
+ * This function makes sure that the superblock fields regarding the
+ * journal are consistent.
+ */
+errcode_t ext2fs_check_ext3_journal(ext2_filsys fs)
+{
+ struct ext2_super_block *sb = fs->super;
+ journal_t *journal;
+ int recover = fs->super->s_feature_incompat &
+ EXT3_FEATURE_INCOMPAT_RECOVER;
+ int reset = 0;
+ errcode_t retval;
+
+ /* If we don't have any journal features, don't do anything more */
+ if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
+ !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
+ uuid_is_null(sb->s_journal_uuid))
+ return 0;
+
+ retval = ext2fs_get_journal(fs, &journal);
+ if (retval)
+ return retval;
+
+ retval = ext2fs_journal_load(journal);
+ if (retval) {
+ ext2fs_journal_release(fs, journal, 0, 1);
+ return retval;
+ }
+
+ /*
+ * We want to make the flags consistent here. We will not leave with
+ * needs_recovery set but has_journal clear. We can't get in a loop
+ * with -y, -n, or -p, only if a user isn't making up their mind.
+ */
+ if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
+ return EXT2_ET_JOURNAL_FLAGS_WRONG;
+
+ if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
+ !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
+ journal->j_superblock->s_start != 0)
+ return EXT2_ET_JOURNAL_FLAGS_WRONG;
+
+ /*
+ * If we don't need to do replay the journal, check to see if
+ * the journal's errno is set; if so, we need to mark the file
+ * system as being corrupt and clear the journal's s_errno.
+ */
+ if (!(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
+ journal->j_superblock->s_errno) {
+ fs->super->s_state |= EXT2_ERROR_FS;
+ ext2fs_mark_super_dirty(fs);
+ journal->j_superblock->s_errno = 0;
+ ext2fs_journal_sb_csum_set(journal, journal->j_superblock);
+ mark_buffer_dirty(journal->j_sb_buffer);
+ }
+
+ ext2fs_journal_release(fs, journal, reset, 0);
+ return retval;
+}
+
+static errcode_t recover_ext3_journal(ext2_filsys fs)
+{
+ journal_t *journal;
+ errcode_t retval;
+
+ journal_init_revoke_caches();
+ retval = ext2fs_get_journal(fs, &journal);
+ if (retval)
+ return retval;
+
+ retval = ext2fs_journal_load(journal);
+ if (retval)
+ goto errout;
+
+ retval = journal_init_revoke(journal, 1024);
+ if (retval)
+ goto errout;
+
+ retval = -journal_recover(journal);
+ if (retval)
+ goto errout;
+
+ if (journal->j_failed_commit) {
+ journal->j_superblock->s_errno = -EINVAL;
+ mark_buffer_dirty(journal->j_sb_buffer);
+ }
+
+errout:
+ journal_destroy_revoke(journal);
+ journal_destroy_revoke_caches();
+ ext2fs_journal_release(fs, journal, 1, 0);
+ return retval;
+}
+
+errcode_t ext2fs_run_ext3_journal(ext2_filsys *fsp)
+{
+ ext2_filsys fs = *fsp;
+ io_manager io_ptr = fs->io->manager;
+ errcode_t retval, recover_retval;
+ io_stats stats = 0;
+ unsigned long long kbytes_written = 0;
+ char *fsname;
+ int fsflags;
+ int fsblocksize;
+
+ if (!(fs->flags & EXT2_FLAG_RW))
+ return EXT2_ET_FILE_RO;
+
+ if (fs->flags & EXT2_FLAG_DIRTY)
+ ext2fs_flush(fs); /* Force out any modifications */
+
+ recover_retval = recover_ext3_journal(fs);
+
+ /*
+ * Reload the filesystem context to get up-to-date data from disk
+ * because journal recovery will change the filesystem under us.
+ */
+ if (fs->super->s_kbytes_written &&
+ fs->io->manager->get_stats)
+ fs->io->manager->get_stats(fs->io, &stats);
+ if (stats && stats->bytes_written)
+ kbytes_written = stats->bytes_written >> 10;
+
+ ext2fs_mmp_stop(fs);
+ fsname = strdup(fs->device_name);
+ fsflags = fs->flags;
+ fsblocksize = fs->blocksize;
+ ext2fs_free(fs);
+ retval = ext2fs_open(fsname, fsflags,
+ 0, fsblocksize, io_ptr,
+ fsp);
+ free(fsname);
+ if (retval)
+ return retval;
+
+ fs = *fsp;
+ fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
+ fs->super->s_kbytes_written += kbytes_written;
+
+ /* Set the superblock flags */
+ ext2fs_clear_recover(fs, recover_retval != 0);
+
+ /*
+ * Do one last sanity check, and propagate journal->s_errno to
+ * the EXT2_ERROR_FS flag in the fs superblock if needed.
+ */
+ retval = ext2fs_check_ext3_journal(fs);
+ return retval ? retval : recover_retval;
+}
+
+errcode_t ext2fs_open_journal(ext2_filsys fs, journal_t **j)
+{
+ journal_t *journal;
+ errcode_t retval;
+
+ journal_init_revoke_caches();
+ retval = ext2fs_get_journal(fs, &journal);
+ if (retval)
+ return retval;
+
+ retval = ext2fs_journal_load(journal);
+ if (retval)
+ goto errout;
+
+ retval = journal_init_revoke(journal, 1024);
+ if (retval)
+ goto errout;
+
+ if (journal->j_failed_commit) {
+ journal->j_superblock->s_errno = -EINVAL;
+ mark_buffer_dirty(journal->j_sb_buffer);
+ }
+
+ *j = journal;
+ return 0;
+
+errout:
+ journal_destroy_revoke(journal);
+ journal_destroy_revoke_caches();
+ ext2fs_journal_release(fs, journal, 1, 0);
+ return retval;
+}
+
+errcode_t ext2fs_close_journal(ext2_filsys fs, journal_t **j)
+{
+ journal_t *journal = *j;
+
+ journal_destroy_revoke(journal);
+ journal_destroy_revoke_caches();
+ ext2fs_journal_release(fs, journal, 0, 0);
+ *j = NULL;
+
+ return 0;
+}
+
+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))
+ return;
+
+ h = (struct commit_header *)(bh->b_data);
+ h->h_chksum_type = 0;
+ h->h_chksum_size = 0;
+ h->h_chksum[0] = 0;
+ csum = jbd2_chksum(j, j->j_csum_seed, bh->b_data, j->j_blocksize);
+ h->h_chksum[0] = ext2fs_cpu_to_be32(csum);
+}
+
+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);
+}
+
+void jbd2_descr_block_csum_set(journal_t *j, struct buffer_head *bh)
+{
+ struct journal_block_tail *tail;
+ __u32 csum;
+
+ if (!journal_has_csum_v2or3(j))
+ return;
+
+ tail = (struct journal_block_tail *)(bh->b_data + j->j_blocksize -
+ sizeof(struct 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);
+}
+
+void jbd2_block_tag_csum_set(journal_t *j, journal_block_tag_t *tag,
+ struct buffer_head *bh, __u32 sequence)
+{
+ journal_block_tag3_t *tag3 = (journal_block_tag3_t *)tag;
+ __u32 csum32;
+ __be32 seq;
+
+ if (!journal_has_csum_v2or3(j))
+ return;
+
+ seq = ext2fs_cpu_to_be32(sequence);
+ csum32 = jbd2_chksum(j, j->j_csum_seed, (__u8 *)&seq, sizeof(seq));
+ csum32 = jbd2_chksum(j, csum32, bh->b_data, bh->b_size);
+
+ if (JFS_HAS_INCOMPAT_FEATURE(j, JFS_FEATURE_INCOMPAT_CSUM_V3))
+ tag3->t_checksum = ext2fs_cpu_to_be32(csum32);
+ else
+ tag->t_checksum = ext2fs_cpu_to_be16(csum32);
+}
+
diff --git a/lib/ext2fs/Makefile.in b/lib/ext2fs/Makefile.in
index f88545d..058eb64 100644
--- a/lib/ext2fs/Makefile.in
+++ b/lib/ext2fs/Makefile.in
@@ -19,7 +19,8 @@ MK_CMDS= _SS_DIR_OVERRIDE=../ss ../ss/mk_cmds
DEBUG_OBJS= debug_cmds.o extent_cmds.o tst_cmds.o debugfs.o util.o \
ncheck.o icheck.o ls.o lsdel.o dump.o set_fields.o logdump.o \
htree.o unused.o e2freefrag.o filefrag.o extent_inode.o zap.o \
- xattrs.o quota.o tst_libext2fs.o create_inode.o
+ xattrs.o quota.o tst_libext2fs.o create_inode.o journal.o \
+ revoke.o recovery.o

DEBUG_SRCS= debug_cmds.c extent_cmds.c tst_cmds.c \
$(top_srcdir)/debugfs/debugfs.c \
@@ -39,7 +40,10 @@ DEBUG_SRCS= debug_cmds.c extent_cmds.c tst_cmds.c \
$(top_srcdir)/debugfs/quota.c \
$(top_srcdir)/debugfs/xattrs.c \
$(top_srcdir)/misc/e2freefrag.c \
- $(top_srcdir)/misc/create_inode.c
+ $(top_srcdir)/misc/create_inode.c \
+ $(top_srcdir)/debugfs/journal.c \
+ $(top_srcdir)/debugfs/revoke.c \
+ $(top_srcdir)/debugfs/recovery.c

OBJS= $(DEBUGFS_LIB_OBJS) $(RESIZE_LIB_OBJS) $(E2IMAGE_LIB_OBJS) \
$(TEST_IO_LIB_OBJS) \
@@ -391,6 +395,18 @@ quota.o: $(top_srcdir)/debugfs/quota.c
$(E) " CC $<"
$(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@

+journal.o: $(top_srcdir)/debugfs/journal.c
+ $(E) " CC $<"
+ $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
+
+revoke.o: $(top_srcdir)/debugfs/revoke.c
+ $(E) " CC $<"
+ $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
+
+recovery.o: $(top_srcdir)/debugfs/recovery.c
+ $(E) " CC $<"
+ $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
+
xattrs.o: $(top_srcdir)/debugfs/xattrs.c
$(E) " CC $<"
$(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
diff --git a/lib/ext2fs/ext2_err.et.in b/lib/ext2fs/ext2_err.et.in
index 6b6d8b8..790d135 100644
--- a/lib/ext2fs/ext2_err.et.in
+++ b/lib/ext2fs/ext2_err.et.in
@@ -521,4 +521,7 @@ ec EXT2_ET_INODE_IS_GARBAGE,
ec EXT2_ET_EA_BAD_VALUE_OFFSET,
"Extended attribute has an invalid value offset"

+ec EXT2_ET_JOURNAL_FLAGS_WRONG,
+ "Journal flags inconsistent"
+
end
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index b4a9f84..d931fff 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -282,6 +282,9 @@ struct struct_ext2_filsys {

/* Precomputed FS UUID checksum for seeding other checksums */
__u32 csum_seed;
+
+ io_channel journal_io;
+ char *journal_name;
};

#if EXT2_FLAT_INCLUDES


2014-09-08 23:12:52

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 11/25] e2fsck: fix minor errors in journal handling

The journal superblock's s_sequence field seems to track the tid of
the tail (oldest) transaction in the log. Therefore, when we release
the journal, set the s_sequence to the tail_sequence, because setting
it to the transaction_sequence means that we're setting the tid to
that of the head of the log. Granted, for replay these two are
usually the same (and s_start == 0 anyway) so thus far we've gotten
lucky and nobody noticed.

Signed-off-by: Darrick J. Wong <[email protected]>
---
e2fsck/journal.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)


diff --git a/e2fsck/journal.c b/e2fsck/journal.c
index d12e317..6119cda 100644
--- a/e2fsck/journal.c
+++ b/e2fsck/journal.c
@@ -769,7 +769,7 @@ static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
mark_buffer_clean(journal->j_sb_buffer);
else if (!(ctx->options & E2F_OPT_READONLY)) {
jsb = journal->j_superblock;
- jsb->s_sequence = htonl(journal->j_transaction_sequence);
+ jsb->s_sequence = htonl(journal->j_tail_sequence);
if (reset)
jsb->s_start = 0; /* this marks the journal as empty */
e2fsck_journal_sb_csum_set(journal, jsb);


2014-09-08 23:13:00

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 12/25] debugfs: add the ability to write transactions to the journal

Extend debugfs with the ability to create transactions and replay the
journal. This will eventually be used to test kernel recovery and
metadata_csum recovery.

v2: Find the FS context without using j_inode, since it won't always
be valid; allow user to specify external journal file; start writing
transactions at j_first.

Signed-off-by: Darrick J. Wong <[email protected]>
---
debugfs/Makefile.in | 16 +
debugfs/debug_cmds.ct | 11 +
debugfs/debugfs.h | 1
debugfs/do_journal.c | 982 ++++++++++++++++++++++++++++++++++++++++++++++++
debugfs/util.c | 37 ++
lib/ext2fs/Makefile.in | 9
6 files changed, 1052 insertions(+), 4 deletions(-)
create mode 100644 debugfs/do_journal.c


diff --git a/debugfs/Makefile.in b/debugfs/Makefile.in
index 9523b9b..4a7ddac 100644
--- a/debugfs/Makefile.in
+++ b/debugfs/Makefile.in
@@ -19,7 +19,7 @@ MK_CMDS= _SS_DIR_OVERRIDE=../lib/ss ../lib/ss/mk_cmds
DEBUG_OBJS= debug_cmds.o debugfs.o util.o ncheck.o icheck.o ls.o \
lsdel.o dump.o set_fields.o logdump.o htree.o unused.o e2freefrag.o \
filefrag.o extent_cmds.o extent_inode.o zap.o create_inode.o \
- quota.o xattrs.o journal.o revoke.o recovery.o
+ quota.o xattrs.o journal.o revoke.o recovery.o do_journal.o

RO_DEBUG_OBJS= ro_debug_cmds.o ro_debugfs.o util.o ncheck.o icheck.o ls.o \
lsdel.o logdump.o htree.o e2freefrag.o filefrag.o extent_cmds.o \
@@ -32,7 +32,7 @@ SRCS= debug_cmds.c $(srcdir)/debugfs.c $(srcdir)/util.c $(srcdir)/ls.c \
$(srcdir)/filefrag.c $(srcdir)/extent_inode.c $(srcdir)/zap.c \
$(srcdir)/../misc/create_inode.c $(srcdir)/xattrs.c $(srcdir)/quota.c \
$(srcdir)/journal.c $(srcdir)/../e2fsck/revoke.c \
- $(srcdir)/../e2fsck/recovery.c
+ $(srcdir)/../e2fsck/recovery.c $(srcdir)/do_journal.c

LIBS= $(LIBQUOTA) $(LIBEXT2FS) $(LIBE2P) $(LIBSS) $(LIBCOM_ERR) $(LIBBLKID) \
$(LIBUUID) $(SYSLIBS)
@@ -358,6 +358,18 @@ revoke.o: $(srcdir)/../e2fsck/revoke.c $(top_builddir)/lib/config.h \
$(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \
$(top_srcdir)/lib/../e2fsck/dict.h $(top_srcdir)/lib/ext2fs/kernel-jbd.h \
$(top_srcdir)/lib/ext2fs/jfs_compat.h $(top_srcdir)/lib/ext2fs/kernel-list.h
+do_journal.o: $(srcdir)/do_journal.c $(srcdir)/debugfs.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/bitops.h \
+ $(srcdir)/jfs_user.h $(top_srcdir)/lib/ext2fs/kernel-jbd.h \
+ $(top_srcdir)/lib/ext2fs/jfs_compat.h $(top_srcdir)/lib/ext2fs/kernel-list.h \
+ $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \
+ $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \
+ $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h \
+ $(top_srcdir)/lib/e2p/e2p.h
xattrs.o: $(srcdir)/xattrs.c $(srcdir)/debugfs.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 \
diff --git a/debugfs/debug_cmds.ct b/debugfs/debug_cmds.ct
index 5bd3fe1..c6f6d6c 100644
--- a/debugfs/debug_cmds.ct
+++ b/debugfs/debug_cmds.ct
@@ -211,6 +211,17 @@ request do_get_quota, "Get quota",
request do_idump, "Dump the inode structure in hex",
inode_dump, idump, id;

+request do_journal_open, "Open the journal",
+ journal_open, jo;
+
+request do_journal_close, "Close the journal",
+ journal_close, jc;
+
+request do_journal_write, "Write a transaction to the journal",
+ journal_write, jw;
+
+request do_journal_run, "Recover the journal",
+ journal_run, jr;

end;

diff --git a/debugfs/debugfs.h b/debugfs/debugfs.h
index 6eb5732..e163d0a 100644
--- a/debugfs/debugfs.h
+++ b/debugfs/debugfs.h
@@ -180,6 +180,7 @@ extern void do_get_quota(int argc, char *argv[]);

/* util.c */
extern time_t string_to_time(const char *arg);
+errcode_t read_list(const char *str, blk64_t **list, size_t *len);

/* xattrs.c */
void dump_inode_attributes(FILE *out, ext2_ino_t ino);
diff --git a/debugfs/do_journal.c b/debugfs/do_journal.c
new file mode 100644
index 0000000..711ed27
--- /dev/null
+++ b/debugfs/do_journal.c
@@ -0,0 +1,982 @@
+/*
+ * do_journal.c --- Scribble onto the journal!
+ *
+ * Copyright (C) 2014 Oracle. This file may be redistributed
+ * under the terms of the GNU Public License.
+ */
+
+#include "config.h"
+#include <stdio.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+extern int optind;
+extern char *optarg;
+#endif
+#include <ctype.h>
+#include <unistd.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#include "debugfs.h"
+#include "jfs_user.h"
+#include "ext2fs/kernel-jbd.h"
+
+/* journal.c */
+errcode_t ext2fs_open_journal(ext2_filsys fs, journal_t **j);
+errcode_t ext2fs_close_journal(ext2_filsys fs, journal_t **j);
+errcode_t ext2fs_run_ext3_journal(ext2_filsys *fs);
+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);
+void jbd2_descr_block_csum_set(journal_t *j, struct buffer_head *bh);
+void jbd2_block_tag_csum_set(journal_t *j, journal_block_tag_t *tag,
+ struct buffer_head *bh, __u32 sequence);
+
+#undef DEBUG
+
+#ifdef DEBUG
+# define dbg_printf(f, a...) do {printf("JFS DEBUG: " f, ## a); \
+ fflush(stdout); \
+} while (0)
+#else
+# define dbg_printf(f, a...)
+#endif
+
+#define JOURNAL_CHECK_TRANS_MAGIC(x) \
+ do { \
+ if ((x)->magic != J_TRANS_MAGIC) \
+ return EXT2_ET_INVALID_ARGUMENT; \
+ } while (0)
+
+#define J_TRANS_MAGIC 0xD15EA5ED
+#define J_TRANS_OPEN 1
+#define J_TRANS_COMMITTED 2
+struct journal_transaction_s {
+ unsigned int magic;
+ ext2_filsys fs;
+ journal_t *journal;
+ blk64_t block;
+ blk64_t start, end;
+ tid_t tid;
+ int flags;
+};
+
+typedef struct journal_transaction_s journal_transaction_t;
+
+static journal_t *current_journal = NULL;
+
+static void journal_dump_trans(journal_transaction_t *trans, const char *tag)
+{
+ dbg_printf("TRANS %p(%s): tid=%d start=%llu block=%llu end=%llu "
+ "flags=0x%x\n", trans, tag, trans->tid, trans->start,
+ trans->block, trans->end, trans->flags);
+}
+
+static errcode_t journal_commit_trans(journal_transaction_t *trans)
+{
+ struct buffer_head *bh, *cbh = NULL;
+ struct commit_header *commit;
+#ifdef HAVE_SYS_TIME_H
+ struct timeval tv;
+#endif
+ errcode_t err;
+
+ JOURNAL_CHECK_TRANS_MAGIC(trans);
+
+ if ((trans->flags & J_TRANS_COMMITTED) ||
+ !(trans->flags & J_TRANS_OPEN))
+ return EXT2_ET_INVALID_ARGUMENT;
+
+ bh = getblk(trans->journal->j_dev, 0, trans->journal->j_blocksize);
+ if (bh == NULL)
+ return ENOMEM;
+
+ /* 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_sequence = ext2fs_cpu_to_be32(trans->tid);
+ if (JFS_HAS_COMPAT_FEATURE(trans->journal,
+ JFS_FEATURE_COMPAT_CHECKSUM)) {
+ __u32 csum_v1 = ~0;
+ blk64_t cblk;
+
+ cbh = getblk(trans->journal->j_dev, 0,
+ trans->journal->j_blocksize);
+ if (cbh == NULL) {
+ err = ENOMEM;
+ goto error;
+ }
+
+ for (cblk = trans->start; cblk < trans->block; cblk++) {
+ err = journal_bmap(trans->journal, cblk,
+ &cbh->b_blocknr);
+ if (err)
+ goto error;
+ mark_buffer_uptodate(cbh, 0);
+ ll_rw_block(READ, 1, &cbh);
+ err = cbh->b_err;
+ if (err)
+ goto error;
+ csum_v1 = ext2fs_crc32_be(csum_v1,
+ (unsigned char const *)cbh->b_data,
+ cbh->b_size);
+ }
+
+ commit->h_chksum_type = JFS_CRC32_CHKSUM;
+ commit->h_chksum_size = JFS_CRC32_CHKSUM_SIZE;
+ commit->h_chksum[0] = ext2fs_cpu_to_be32(csum_v1);
+ } else {
+ commit->h_chksum_type = 0;
+ commit->h_chksum_size = 0;
+ commit->h_chksum[0] = 0;
+ }
+#ifdef HAVE_SYS_TIME_H
+ gettimeofday(&tv, NULL);
+ commit->h_commit_sec = ext2fs_cpu_to_be32(tv.tv_sec);
+ commit->h_commit_nsec = ext2fs_cpu_to_be32(tv.tv_usec * 1000);
+#else
+ commit->h_commit_sec = 0;
+ commit->h_commit_nsec = 0;
+#endif
+
+ /* Write block */
+ jbd2_commit_block_csum_set(trans->journal, bh);
+ err = 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);
+ err = bh->b_err;
+ if (err)
+ goto error;
+ trans->flags |= J_TRANS_COMMITTED;
+ trans->flags &= ~J_TRANS_OPEN;
+ trans->block++;
+
+error:
+ if (cbh)
+ brelse(cbh);
+ brelse(bh);
+ return err;
+}
+
+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;
+ void *buf;
+ size_t i, offset;
+ blk64_t curr_blk;
+ int csum_size = 0;
+ struct buffer_head *bh;
+ errcode_t err;
+
+ JOURNAL_CHECK_TRANS_MAGIC(trans);
+
+ if ((trans->flags & J_TRANS_COMMITTED) ||
+ !(trans->flags & J_TRANS_OPEN))
+ return EXT2_ET_INVALID_ARGUMENT;
+
+ if (revoke_len == 0)
+ 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);
+
+ curr_blk = trans->block;
+
+ bh = getblk(trans->journal->j_dev, curr_blk,
+ trans->journal->j_blocksize);
+ 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_sequence = ext2fs_cpu_to_be32(trans->tid);
+ offset = sizeof(*jrb);
+
+ for (i = 0; i < revoke_len; i++) {
+ /* Block full, write to journal */
+ if (offset > trans->journal->j_blocksize - csum_size) {
+ 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);
+ 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);
+ err = bh->b_err;
+ if (err)
+ goto error;
+
+ offset = sizeof(*jrb);
+ curr_blk++;
+ }
+
+ if (revoke_list[i] >=
+ ext2fs_blocks_count(trans->journal->j_fs_dev->k_fs->super)) {
+ err = EXT2_ET_BAD_BLOCK_NUM;
+ goto error;
+ }
+
+ if (JFS_HAS_INCOMPAT_FEATURE(trans->journal,
+ JFS_FEATURE_INCOMPAT_64BIT)) {
+ *((__u64 *)(&((char *)buf)[offset])) =
+ ext2fs_cpu_to_be64(revoke_list[i]);
+ offset += 8;
+
+ } else {
+ *((__u32 *)(&((char *)buf)[offset])) =
+ ext2fs_cpu_to_be32(revoke_list[i]);
+ offset += 4;
+ }
+ }
+
+ if (offset > 0) {
+ 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);
+ 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);
+ err = bh->b_err;
+ if (err)
+ goto error;
+ curr_blk++;
+ }
+
+error:
+ trans->block = curr_blk;
+ brelse(bh);
+ return err;
+}
+
+static errcode_t journal_add_blocks_to_trans(journal_transaction_t *trans,
+ blk64_t *block_list, size_t block_len,
+ FILE *fp)
+{
+ blk64_t curr_blk, jdb_blk;
+ size_t i, j;
+ int csum_size = 0;
+ journal_header_t *jdb;
+ journal_block_tag_t *jdbt;
+ int tag_bytes;
+ void *buf = NULL, *jdb_buf = NULL;
+ struct buffer_head *bh = NULL, *data_bh;
+ errcode_t err;
+
+ JOURNAL_CHECK_TRANS_MAGIC(trans);
+
+ if ((trans->flags & J_TRANS_COMMITTED) ||
+ !(trans->flags & J_TRANS_OPEN))
+ return EXT2_ET_INVALID_ARGUMENT;
+
+ if (block_len == 0)
+ 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);
+
+ curr_blk = jdb_blk = trans->block;
+
+ data_bh = getblk(trans->journal->j_dev, curr_blk,
+ trans->journal->j_blocksize);
+ if (data_bh == NULL)
+ return ENOMEM;
+ buf = data_bh->b_data;
+
+ /* write the descriptor block header */
+ bh = getblk(trans->journal->j_dev, curr_blk,
+ trans->journal->j_blocksize);
+ if (bh == NULL) {
+ err = ENOMEM;
+ 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_sequence = ext2fs_cpu_to_be32(trans->tid);
+ jdbt = (journal_block_tag_t *)(jdb + 1);
+
+ curr_blk++;
+ for (i = 0; i < block_len; i++) {
+ j = fread(data_bh->b_data, trans->journal->j_blocksize, 1, fp);
+ if (j != 1) {
+ err = errno;
+ goto error;
+ }
+
+ tag_bytes = journal_tag_bytes(trans->journal);
+
+ /* No space left in descriptor block, write it out */
+ 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,
+ &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);
+ err = bh->b_err;
+ if (err)
+ goto error;
+
+ jdbt = (journal_block_tag_t *)(jdb + 1);
+ jdb_blk = curr_blk;
+ curr_blk++;
+ }
+
+ if (block_list[i] >=
+ ext2fs_blocks_count(trans->journal->j_fs_dev->k_fs->super)) {
+ err = EXT2_ET_BAD_BLOCK_NUM;
+ goto error;
+ }
+
+ /* Fill out the block tag */
+ 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);
+ else {
+ memcpy(jdbt + tag_bytes,
+ trans->journal->j_superblock->s_uuid,
+ sizeof(trans->journal->j_superblock->s_uuid));
+ 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)) {
+ *((__u32 *)buf) = 0;
+ jdbt->t_flags |= ext2fs_cpu_to_be16(JFS_FLAG_ESCAPE);
+ }
+ if (JFS_HAS_INCOMPAT_FEATURE(trans->journal,
+ JFS_FEATURE_INCOMPAT_64BIT))
+ 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);
+ 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);
+ err = data_bh->b_err;
+ if (err)
+ goto error;
+
+ curr_blk++;
+ jdbt = (journal_block_tag_t *)(((char *)jdbt) + tag_bytes);
+ }
+
+ /* 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);
+ 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);
+ err = bh->b_err;
+ if (err)
+ goto error;
+ }
+
+error:
+ trans->block = curr_blk;
+ if (bh)
+ brelse(bh);
+ brelse(data_bh);
+ return err;
+}
+
+static blk64_t journal_guess_blocks(journal_t *journal, blk64_t data_blocks,
+ blk64_t revoke_blocks)
+{
+ blk64_t ret = 1;
+ unsigned int bs, sz;
+
+ /* Estimate # of revoke blocks */
+ bs = journal->j_blocksize;
+ if (journal_has_csum_v2or3(journal))
+ bs -= sizeof(struct journal_revoke_tail);
+ sz = JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_64BIT) ?
+ 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);
+ sz = journal_tag_bytes(journal);
+ ret += data_blocks * sz / bs;
+
+ ret += data_blocks;
+
+ return ret;
+}
+
+static errcode_t journal_open_trans(journal_t *journal,
+ journal_transaction_t *trans,
+ blk64_t blocks)
+{
+ trans->fs = journal->j_fs_dev->k_fs;
+ trans->journal = journal;
+ trans->flags = J_TRANS_OPEN;
+
+ if (journal->j_tail == 0) {
+ /* Clean journal, start at the tail */
+ trans->tid = journal->j_tail_sequence;
+ trans->start = journal->j_first;
+ } else {
+ /* Put new transaction at the head of the list */
+ trans->tid = journal->j_transaction_sequence;
+ trans->start = journal->j_head;
+ }
+
+ trans->block = trans->start;
+ if (trans->start + blocks > journal->j_last)
+ return ENOSPC;
+ trans->end = trans->block + blocks;
+ journal_dump_trans(trans, "new transaction");
+
+ trans->magic = J_TRANS_MAGIC;
+ return 0;
+}
+
+static errcode_t journal_close_trans(journal_transaction_t *trans)
+{
+ journal_t *journal;
+
+ JOURNAL_CHECK_TRANS_MAGIC(trans);
+
+ if (!(trans->flags & J_TRANS_COMMITTED))
+ return 0;
+
+ journal = trans->journal;
+ if (journal->j_tail == 0) {
+ /* Update the tail */
+ journal->j_tail_sequence = trans->tid;
+ journal->j_tail = trans->start;
+ journal->j_superblock->s_start = ext2fs_cpu_to_be32(trans->start);
+ }
+
+ /* Update the head */
+ journal->j_head = trans->end + 1;
+ journal->j_transaction_sequence = trans->tid + 1;
+
+ trans->magic = 0;
+
+ /* Mark ourselves as needing recovery */
+ if (!(EXT2_HAS_INCOMPAT_FEATURE(trans->fs->super,
+ EXT3_FEATURE_INCOMPAT_RECOVER))) {
+ trans->fs->super->s_feature_incompat |=
+ EXT3_FEATURE_INCOMPAT_RECOVER;
+ ext2fs_mark_super_dirty(trans->fs);
+ }
+
+ return 0;
+}
+
+#define JOURNAL_WRITE_NO_COMMIT 1
+static errcode_t journal_write(journal_t *journal,
+ int flags, blk64_t *block_list,
+ size_t block_len, blk64_t *revoke_list,
+ size_t revoke_len, FILE *fp)
+{
+ blk64_t blocks;
+ journal_transaction_t trans;
+ errcode_t err;
+
+ if (revoke_len > 0) {
+ journal->j_superblock->s_feature_incompat |=
+ ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_REVOKE);
+ mark_buffer_dirty(journal->j_sb_buffer);
+ }
+
+ blocks = journal_guess_blocks(journal, block_len, revoke_len);
+ err = journal_open_trans(journal, &trans, blocks);
+ if (err)
+ goto error;
+
+ err = journal_add_blocks_to_trans(&trans, block_list, block_len, fp);
+ if (err)
+ goto error;
+
+ err = journal_add_revoke_to_trans(&trans, revoke_list, revoke_len);
+ if (err)
+ goto error;
+
+ if (!(flags & JOURNAL_WRITE_NO_COMMIT)) {
+ err = journal_commit_trans(&trans);
+ if (err)
+ goto error;
+ }
+
+ err = journal_close_trans(&trans);
+ if (err)
+ goto error;
+error:
+ return err;
+}
+
+void do_journal_write(int argc, char *argv[])
+{
+ blk64_t *blist = NULL, *rlist = NULL;
+ size_t bn = 0, rn = 0;
+ FILE *fp = NULL;
+ int opt;
+ int flags = 0;
+ errcode_t err;
+
+ if (current_journal == NULL) {
+ printf("Journal not open.\n");
+ return;
+ }
+
+ reset_getopt();
+ while ((opt = getopt(argc, argv, "b:r:c")) != -1) {
+ switch (opt) {
+ case 'b':
+ err = read_list(optarg, &blist, &bn);
+ if (err)
+ com_err(argv[0], err,
+ "while reading block list");
+ break;
+ case 'r':
+ err = read_list(optarg, &rlist, &rn);
+ if (err)
+ com_err(argv[0], err,
+ "while reading revoke list");
+ break;
+ case 'c':
+ flags |= JOURNAL_WRITE_NO_COMMIT;
+ break;
+ default:
+ printf("%s [-b blocks] [-r revoke] [-c] file\n",
+ argv[0]);
+ printf("-b: Write these blocks into transaction.\n");
+ printf("-c: Do not commit transaction.\n");
+ printf("-r: Revoke these blocks from transaction.\n");
+
+ goto out;
+ }
+ }
+
+ if (bn > 0 && optind != argc - 1) {
+ printf("Need a file to read blocks from.\n");
+ return;
+ }
+
+ if (bn > 0) {
+ fp = fopen(argv[optind], "r");
+ if (fp == NULL) {
+ com_err(argv[0], errno,
+ "while opening journal data file");
+ goto out;
+ }
+ }
+
+ err = journal_write(current_journal, flags, blist, bn,
+ rlist, rn, fp);
+ if (err)
+ com_err("journal_write", err, "while writing journal");
+
+ if (fp)
+ fclose(fp);
+out:
+ if (blist)
+ free(blist);
+ if (rlist)
+ free(rlist);
+}
+
+/* Make sure we wrap around the log correctly! */
+#define wrap(journal, var) \
+do { \
+ if (var >= (journal)->j_last) \
+ var -= ((journal)->j_last - (journal)->j_first); \
+} while (0)
+
+/*
+ * Count the number of in-use tags in a journal descriptor block.
+ */
+
+static int count_tags(journal_t *journal, char *buf)
+{
+ char *tagp;
+ journal_block_tag_t *tag;
+ 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);
+
+ tagp = buf + sizeof(journal_header_t);
+
+ while ((tagp - buf + tag_bytes) <= size) {
+ tag = (journal_block_tag_t *) tagp;
+
+ nr++;
+ tagp += tag_bytes;
+ if (!(tag->t_flags & ext2fs_cpu_to_be16(JFS_FLAG_SAME_UUID)))
+ tagp += 16;
+
+ if (tag->t_flags & ext2fs_cpu_to_be16(JFS_FLAG_LAST_TAG))
+ break;
+ }
+
+ return nr;
+}
+
+errcode_t journal_find_head(journal_t *journal)
+{
+ unsigned int next_commit_ID;
+ blk64_t next_log_block, head_block;
+ int err;
+ journal_superblock_t *sb;
+ journal_header_t *tmp;
+ struct buffer_head *bh;
+ unsigned int sequence;
+ int blocktype;
+
+ /*
+ * First thing is to establish what we expect to find in the log
+ * (in terms of transaction IDs), and where (in terms of log
+ * block offsets): query the superblock.
+ */
+
+ sb = journal->j_superblock;
+ next_commit_ID = ext2fs_be32_to_cpu(sb->s_sequence);
+ next_log_block = ext2fs_be32_to_cpu(sb->s_start);
+ head_block = next_log_block;
+
+ if (next_log_block == 0)
+ return 0;
+
+ bh = getblk(journal->j_dev, 0, journal->j_blocksize);
+ if (bh == NULL)
+ return ENOMEM;
+
+ /*
+ * Now we walk through the log, transaction by transaction,
+ * making sure that each transaction has a commit block in the
+ * expected place. Each complete transaction gets replayed back
+ * into the main filesystem.
+ */
+ while (1) {
+ dbg_printf("Scanning for sequence ID %u at %lu/%lu\n",
+ next_commit_ID, (unsigned long)next_log_block,
+ journal->j_last);
+
+ /* 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);
+ if (err)
+ goto err;
+ mark_buffer_uptodate(bh, 0);
+ ll_rw_block(READ, 1, &bh);
+ err = bh->b_err;
+ if (err)
+ goto err;
+
+ next_log_block++;
+ wrap(journal, next_log_block);
+
+ /* What kind of buffer is it?
+ *
+ * If it is a descriptor block, check that it has the
+ * expected sequence number. Otherwise, we're all done
+ * here. */
+
+ tmp = (journal_header_t *)bh->b_data;
+
+ if (tmp->h_magic != ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER)) {
+ dbg_printf("JBD2: wrong magic 0x%x\n", tmp->h_magic);
+ goto err;
+ }
+
+ blocktype = ext2fs_be32_to_cpu(tmp->h_blocktype);
+ sequence = ext2fs_be32_to_cpu(tmp->h_sequence);
+ dbg_printf("Found magic %d, sequence %d\n",
+ blocktype, sequence);
+
+ if (sequence != next_commit_ID) {
+ dbg_printf("JBD2: Wrong sequence %d (wanted %d)\n",
+ sequence, next_commit_ID);
+ goto err;
+ }
+
+ /* OK, we have a valid descriptor block which matches
+ * all of the sequence number checks. What are we going
+ * to do with it? That depends on the pass... */
+
+ switch (blocktype) {
+ case JFS_DESCRIPTOR_BLOCK:
+ next_log_block += count_tags(journal, bh->b_data);
+ wrap(journal, next_log_block);
+ continue;
+
+ case JFS_COMMIT_BLOCK:
+ head_block = next_log_block;
+ next_commit_ID++;
+ continue;
+
+ case JFS_REVOKE_BLOCK:
+ continue;
+
+ default:
+ dbg_printf("Unrecognised magic %d, end of scan.\n",
+ blocktype);
+ err = -EINVAL;
+ goto err;
+ }
+ }
+
+err:
+ if (err == 0) {
+ dbg_printf("head seq=%d blk=%llu\n", next_commit_ID,
+ head_block);
+ journal->j_transaction_sequence = next_commit_ID;
+ journal->j_head = head_block;
+ }
+ brelse(bh);
+ return err;
+}
+
+static void update_journal_csum(journal_t *journal, int ver)
+{
+ journal_superblock_t *jsb;
+
+ if (journal->j_format_version < 2)
+ return;
+
+ if (journal->j_tail != 0 ||
+ EXT2_HAS_INCOMPAT_FEATURE(journal->j_fs_dev->k_fs->super,
+ EXT3_FEATURE_INCOMPAT_RECOVER)) {
+ printf("Journal needs recovery, will not add csums.\n");
+ return;
+ }
+
+ /* metadata_csum implies journal csum v3 */
+ jsb = journal->j_superblock;
+ if (EXT2_HAS_RO_COMPAT_FEATURE(journal->j_fs_dev->k_fs->super,
+ EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
+ printf("Setting csum v%d\n", ver);
+ switch (ver) {
+ case 2:
+ journal->j_superblock->s_feature_incompat &=
+ ext2fs_cpu_to_be32(~JFS_FEATURE_INCOMPAT_CSUM_V3);
+ journal->j_superblock->s_feature_incompat |=
+ ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_CSUM_V2);
+ journal->j_superblock->s_feature_compat &=
+ ext2fs_cpu_to_be32(~JFS_FEATURE_COMPAT_CHECKSUM);
+ break;
+ case 3:
+ journal->j_superblock->s_feature_incompat &=
+ ext2fs_cpu_to_be32(~JFS_FEATURE_INCOMPAT_CSUM_V2);
+ journal->j_superblock->s_feature_incompat |=
+ ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_CSUM_V3);
+ journal->j_superblock->s_feature_compat &=
+ ext2fs_cpu_to_be32(~JFS_FEATURE_COMPAT_CHECKSUM);
+ break;
+ default:
+ printf("Unknown checksum v%d\n", ver);
+ break;
+ }
+ journal->j_superblock->s_checksum_type = JBD2_CRC32C_CHKSUM;
+ journal->j_csum_seed = jbd2_chksum(journal, ~0, jsb->s_uuid,
+ sizeof(jsb->s_uuid));
+ } else {
+ journal->j_superblock->s_feature_compat |=
+ ext2fs_cpu_to_be32(JFS_FEATURE_COMPAT_CHECKSUM);
+ journal->j_superblock->s_feature_incompat &=
+ ext2fs_cpu_to_be32(~(JFS_FEATURE_INCOMPAT_CSUM_V2 |
+ JFS_FEATURE_INCOMPAT_CSUM_V3));
+ }
+}
+
+static void update_uuid(journal_t *journal)
+{
+ size_t z;
+ ext2_filsys fs;
+
+ if (journal->j_format_version < 2)
+ return;
+
+ for (z = 0; z < sizeof(journal->j_superblock->s_uuid); z++)
+ if (journal->j_superblock->s_uuid[z])
+ break;
+ if (z == 0)
+ return;
+
+ fs = journal->j_fs_dev->k_fs;
+ if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super,
+ EXT4_FEATURE_INCOMPAT_64BIT))
+ return;
+
+ if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_64BIT) &&
+ EXT2_HAS_INCOMPAT_FEATURE(fs->super,
+ EXT4_FEATURE_INCOMPAT_64BIT))
+ return;
+
+ if (journal->j_tail != 0 ||
+ EXT2_HAS_INCOMPAT_FEATURE(fs->super,
+ EXT3_FEATURE_INCOMPAT_RECOVER)) {
+ printf("Journal needs recovery, will not set 64bit.\n");
+ return;
+ }
+
+ memcpy(journal->j_superblock->s_uuid, fs->super->s_uuid,
+ sizeof(fs->super->s_uuid));
+}
+
+static void update_64bit_flag(journal_t *journal)
+{
+ if (journal->j_format_version < 2)
+ return;
+
+ if (!EXT2_HAS_INCOMPAT_FEATURE(journal->j_fs_dev->k_fs->super,
+ EXT4_FEATURE_INCOMPAT_64BIT))
+ return;
+
+ if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_64BIT) &&
+ EXT2_HAS_INCOMPAT_FEATURE(journal->j_fs_dev->k_fs->super,
+ EXT4_FEATURE_INCOMPAT_64BIT))
+ return;
+
+ if (journal->j_tail != 0 ||
+ EXT2_HAS_INCOMPAT_FEATURE(journal->j_fs_dev->k_fs->super,
+ EXT3_FEATURE_INCOMPAT_RECOVER)) {
+ printf("Journal needs recovery, will not set 64bit.\n");
+ return;
+ }
+
+ journal->j_superblock->s_feature_incompat |=
+ ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_64BIT);
+}
+
+void do_journal_open(int argc, char *argv[])
+{
+ int opt, enable_csum = 0, csum_ver = 3;
+ journal_t *journal;
+ errcode_t err;
+
+ if (check_fs_open(argv[0]))
+ return;
+ if (check_fs_read_write(argv[0]))
+ return;
+ if (check_fs_bitmaps(argv[0]))
+ return;
+ if (current_journal) {
+ printf("Journal is already open.\n");
+ return;
+ }
+ if (!EXT2_HAS_COMPAT_FEATURE(current_fs->super,
+ EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
+ printf("Journalling is not enabled on this filesystem.\n");
+ return;
+ }
+
+ reset_getopt();
+ while ((opt = getopt(argc, argv, "cv:f:")) != -1) {
+ switch (opt) {
+ case 'c':
+ enable_csum = 1;
+ break;
+ case 'f':
+ if (current_fs->journal_name)
+ free(current_fs->journal_name);
+ current_fs->journal_name = strdup(optarg);
+ break;
+ case 'v':
+ csum_ver = atoi(optarg);
+ if (csum_ver != 2 && csum_ver != 3) {
+ printf("Unknown journal csum v%d\n", csum_ver);
+ csum_ver = 3;
+ }
+ break;
+ default:
+ printf("%s: [-c] [-v ver]\n", argv[0]);
+ printf("-c: Enable journal checksumming.\n");
+ printf("-v: Use this version checksum format.\n");
+ }
+ }
+
+ err = ext2fs_open_journal(current_fs, &current_journal);
+ if (err) {
+ com_err(argv[0], err, "while opening journal");
+ return;
+ }
+ journal = current_journal;
+
+ dbg_printf("JOURNAL: seq=%d tailseq=%d start=%lu first=%lu "
+ "maxlen=%lu\n", journal->j_tail_sequence,
+ journal->j_transaction_sequence, journal->j_tail,
+ journal->j_first, journal->j_last);
+
+ update_uuid(journal);
+ update_64bit_flag(journal);
+ if (enable_csum)
+ update_journal_csum(journal, csum_ver);
+
+ err = journal_find_head(journal);
+ if (err)
+ com_err(argv[0], err, "while examining journal");
+}
+
+void do_journal_close(int argc, char *argv[])
+{
+ if (current_journal == NULL) {
+ printf("Journal not open.\n");
+ return;
+ }
+
+ ext2fs_close_journal(current_fs, &current_journal);
+}
+
+void do_journal_run(int argc, char *argv[])
+{
+ errcode_t err;
+
+ if (check_fs_open(argv[0]))
+ return;
+ if (check_fs_read_write(argv[0]))
+ return;
+ if (check_fs_bitmaps(argv[0]))
+ return;
+ if (current_journal) {
+ printf("Please close the journal before recovering it.\n");
+ return;
+ }
+
+ err = ext2fs_run_ext3_journal(&current_fs);
+ if (err)
+ com_err("journal_run", err, "while recovering journal");
+}
diff --git a/debugfs/util.c b/debugfs/util.c
index 6c48fba..54fcdc4 100644
--- a/debugfs/util.c
+++ b/debugfs/util.c
@@ -497,3 +497,40 @@ int ext2_file_type(unsigned int mode)

return 0;
}
+
+errcode_t read_list(const char *str, blk64_t **list, size_t *len)
+{
+ blk64_t *lst = *list;
+ size_t ln = *len;
+ char *tok, *p = optarg;
+
+ while ((tok = strtok(p, ","))) {
+ blk64_t *l;
+ blk64_t x, y;
+ char *e;
+
+ errno = 0;
+ y = x = strtoull(tok, &e, 0);
+ if (errno)
+ return errno;
+ if (*e == '-') {
+ y = strtoull(e + 1, NULL, 0);
+ if (errno)
+ return errno;
+ } else if (*e != 0)
+ return EINVAL;
+ if (y < x)
+ return EINVAL;
+ l = realloc(lst, sizeof(blk64_t) * (ln + y - x + 1));
+ if (l == NULL)
+ return ENOMEM;
+ lst = l;
+ for (; x <= y; x++)
+ lst[ln++] = x;
+ p = NULL;
+ }
+
+ *list = lst;
+ *len = ln;
+ return 0;
+}
diff --git a/lib/ext2fs/Makefile.in b/lib/ext2fs/Makefile.in
index 058eb64..6597e2d 100644
--- a/lib/ext2fs/Makefile.in
+++ b/lib/ext2fs/Makefile.in
@@ -20,7 +20,7 @@ DEBUG_OBJS= debug_cmds.o extent_cmds.o tst_cmds.o debugfs.o util.o \
ncheck.o icheck.o ls.o lsdel.o dump.o set_fields.o logdump.o \
htree.o unused.o e2freefrag.o filefrag.o extent_inode.o zap.o \
xattrs.o quota.o tst_libext2fs.o create_inode.o journal.o \
- revoke.o recovery.o
+ revoke.o recovery.o do_journal.o

DEBUG_SRCS= debug_cmds.c extent_cmds.c tst_cmds.c \
$(top_srcdir)/debugfs/debugfs.c \
@@ -43,7 +43,8 @@ DEBUG_SRCS= debug_cmds.c extent_cmds.c tst_cmds.c \
$(top_srcdir)/misc/create_inode.c \
$(top_srcdir)/debugfs/journal.c \
$(top_srcdir)/debugfs/revoke.c \
- $(top_srcdir)/debugfs/recovery.c
+ $(top_srcdir)/debugfs/recovery.c \
+ $(top_srcdir)/debugfs/do_journal.c

OBJS= $(DEBUGFS_LIB_OBJS) $(RESIZE_LIB_OBJS) $(E2IMAGE_LIB_OBJS) \
$(TEST_IO_LIB_OBJS) \
@@ -407,6 +408,10 @@ recovery.o: $(top_srcdir)/debugfs/recovery.c
$(E) " CC $<"
$(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@

+do_journal.o: $(top_srcdir)/debugfs/do_journal.c
+ $(E) " CC $<"
+ $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
+
xattrs.o: $(top_srcdir)/debugfs/xattrs.c
$(E) " CC $<"
$(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@


2014-09-08 23:13:07

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 13/25] tests: test writing and recovering checksum-free 32/64bit journals

Simple tests for the journal transaction creation code. We test
writing (bad) block bitmaps out through the journal and replaying them
via fsck, with a few twists:

(a) All bitmaps are committed (fs errors reported)
(b) All the bitmap blocks are revoked (no errors)
(c) The transaction is never committed (no errors)
(d) Same as (a), but debugfs gets to do the replay.

We also test:

(a) writing and replaying transactions with multiple
descriptor blocks
(b) same, but with multiple revoke blocks.
(c) adding the 64bit flag to a journal

Signed-off-by: Darrick J. Wong <[email protected]>
---
tests/defaults/j_script | 1
tests/j_long_revoke_trans/expect | 81 +++++++++++++++++++++++
tests/j_long_revoke_trans/name | 1
tests/j_long_revoke_trans/script | 62 ++++++++++++++++++
tests/j_long_trans/expect | 107 +++++++++++++++++++++++++++++++
tests/j_long_trans/name | 1
tests/j_long_trans/script | 59 +++++++++++++++++
tests/j_short_revoke_trans/expect | 32 +++++++++
tests/j_short_revoke_trans/name | 1
tests/j_short_revoke_trans/script | 64 +++++++++++++++++++
tests/j_short_trans/expect | 38 +++++++++++
tests/j_short_trans/name | 1
tests/j_short_trans/script | 61 ++++++++++++++++++
tests/j_short_trans_64bit/expect | 40 ++++++++++++
tests/j_short_trans_64bit/name | 1
tests/j_short_trans_64bit/script | 65 +++++++++++++++++++
tests/j_short_trans_open_recover/expect | 43 ++++++++++++
tests/j_short_trans_open_recover/name | 1
tests/j_short_trans_open_recover/script | 69 ++++++++++++++++++++
tests/j_short_trans_recover/expect | 40 ++++++++++++
tests/j_short_trans_recover/name | 1
tests/j_short_trans_recover/script | 70 ++++++++++++++++++++
tests/j_short_uncommitted_trans/expect | 26 ++++++++
tests/j_short_uncommitted_trans/name | 1
tests/j_short_uncommitted_trans/script | 61 ++++++++++++++++++
25 files changed, 927 insertions(+)
create mode 100644 tests/defaults/j_script
create mode 100644 tests/j_long_revoke_trans/expect
create mode 100644 tests/j_long_revoke_trans/name
create mode 100644 tests/j_long_revoke_trans/script
create mode 100644 tests/j_long_trans/expect
create mode 100644 tests/j_long_trans/name
create mode 100644 tests/j_long_trans/script
create mode 100644 tests/j_short_revoke_trans/expect
create mode 100644 tests/j_short_revoke_trans/name
create mode 100644 tests/j_short_revoke_trans/script
create mode 100644 tests/j_short_trans/expect
create mode 100644 tests/j_short_trans/name
create mode 100644 tests/j_short_trans/script
create mode 100644 tests/j_short_trans_64bit/expect
create mode 100644 tests/j_short_trans_64bit/name
create mode 100644 tests/j_short_trans_64bit/script
create mode 100644 tests/j_short_trans_open_recover/expect
create mode 100644 tests/j_short_trans_open_recover/name
create mode 100644 tests/j_short_trans_open_recover/script
create mode 100644 tests/j_short_trans_recover/expect
create mode 100644 tests/j_short_trans_recover/name
create mode 100644 tests/j_short_trans_recover/script
create mode 100644 tests/j_short_uncommitted_trans/expect
create mode 100644 tests/j_short_uncommitted_trans/name
create mode 100644 tests/j_short_uncommitted_trans/script


diff --git a/tests/defaults/j_script b/tests/defaults/j_script
new file mode 100644
index 0000000..7a3b34f
--- /dev/null
+++ b/tests/defaults/j_script
@@ -0,0 +1 @@
+. $cmd_dir/run_e2fsck
diff --git a/tests/j_long_revoke_trans/expect b/tests/j_long_revoke_trans/expect
new file mode 100644
index 0000000..c0730e6
--- /dev/null
+++ b/tests/j_long_revoke_trans/expect
@@ -0,0 +1,81 @@
+Creating filesystem with 262144 1k blocks and 16384 inodes
+Superblock backups stored on blocks:
+ 8193, 24577, 40961, 57345, 73729, 204801, 221185
+
+Allocating group tables: done
+Writing inode tables: done
+Creating journal (8192 blocks): done
+Writing superblocks and filesystem accounting information: done
+
+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/16384 files (0.0% non-contiguous), 14431/262144 blocks
+Exit status is 0
+debugfs write journal
+debugfs: logdump -c
+Journal starts at block 1, transaction 1
+Found expected sequence 1, type 1 (descriptor block) at block 1
+Found expected sequence 1, type 1 (descriptor block) at block 126
+Found expected sequence 1, type 1 (descriptor block) at block 251
+Found expected sequence 1, type 1 (descriptor block) at block 376
+Found expected sequence 1, type 1 (descriptor block) at block 501
+Found expected sequence 1, type 1 (descriptor block) at block 626
+Found expected sequence 1, type 1 (descriptor block) at block 751
+Found expected sequence 1, type 1 (descriptor block) at block 876
+Found expected sequence 1, type 1 (descriptor block) at block 1001
+Found expected sequence 1, type 1 (descriptor block) at block 1126
+Found expected sequence 1, type 1 (descriptor block) at block 1251
+Found expected sequence 1, type 1 (descriptor block) at block 1376
+Found expected sequence 1, type 1 (descriptor block) at block 1501
+Found expected sequence 1, type 1 (descriptor block) at block 1626
+Found expected sequence 1, type 1 (descriptor block) at block 1751
+Found expected sequence 1, type 1 (descriptor block) at block 1876
+Found expected sequence 1, type 1 (descriptor block) at block 2001
+Found expected sequence 1, type 1 (descriptor block) at block 2126
+Found expected sequence 1, type 1 (descriptor block) at block 2251
+Found expected sequence 1, type 1 (descriptor block) at block 2376
+Found expected sequence 1, type 1 (descriptor block) at block 2501
+Found expected sequence 1, type 1 (descriptor block) at block 2626
+Found expected sequence 1, type 1 (descriptor block) at block 2751
+Found expected sequence 1, type 1 (descriptor block) at block 2876
+Found expected sequence 1, type 1 (descriptor block) at block 3001
+Found expected sequence 1, type 1 (descriptor block) at block 3126
+Found expected sequence 1, type 1 (descriptor block) at block 3251
+Found expected sequence 1, type 1 (descriptor block) at block 3376
+Found expected sequence 1, type 1 (descriptor block) at block 3501
+Found expected sequence 1, type 1 (descriptor block) at block 3626
+Found expected sequence 1, type 1 (descriptor block) at block 3751
+Found expected sequence 1, type 1 (descriptor block) at block 3876
+Found expected sequence 1, type 1 (descriptor block) at block 4001
+Found expected sequence 1, type 1 (descriptor block) at block 4126
+Found expected sequence 1, type 2 (commit block) at block 4133
+Found expected sequence 2, type 5 (revoke table) at block 4134
+Found expected sequence 2, type 5 (revoke table) at block 4135
+Found expected sequence 2, type 5 (revoke table) at block 4136
+Found expected sequence 2, type 5 (revoke table) at block 4137
+Found expected sequence 2, type 5 (revoke table) at block 4138
+Found expected sequence 2, type 5 (revoke table) at block 4139
+Found expected sequence 2, type 5 (revoke table) at block 4140
+Found expected sequence 2, type 5 (revoke table) at block 4141
+Found expected sequence 2, type 5 (revoke table) at block 4142
+Found expected sequence 2, type 5 (revoke table) at block 4143
+Found expected sequence 2, type 5 (revoke table) at block 4144
+Found expected sequence 2, type 5 (revoke table) at block 4145
+Found expected sequence 2, type 5 (revoke table) at block 4146
+Found expected sequence 2, type 5 (revoke table) at block 4147
+Found expected sequence 2, type 5 (revoke table) at block 4148
+Found expected sequence 2, type 5 (revoke table) at block 4149
+Found expected sequence 2, type 5 (revoke table) at block 4150
+Found expected sequence 2, type 2 (commit block) at block 4151
+No magic number at block 4152: end of journal.
+test_filesys: recovering journal
+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/16384 files (0.0% non-contiguous), 14431/262144 blocks
+Exit status is 0
diff --git a/tests/j_long_revoke_trans/name b/tests/j_long_revoke_trans/name
new file mode 100644
index 0000000..3cbb2cd
--- /dev/null
+++ b/tests/j_long_revoke_trans/name
@@ -0,0 +1 @@
+revoked transaction nuking free space
diff --git a/tests/j_long_revoke_trans/script b/tests/j_long_revoke_trans/script
new file mode 100644
index 0000000..4289c2e
--- /dev/null
+++ b/tests/j_long_revoke_trans/script
@@ -0,0 +1,62 @@
+if test -x $DEBUGFS_EXE; then
+
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+$MKE2FS -F -o Linux -b 1024 -O has_journal -T ext4 $TMPFILE 262144 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT 2>&1
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+echo "debugfs write journal" >> $OUT
+echo "jo" > $TMPFILE.cmd
+echo "jw -b 259-4356 /dev/zero" >> $TMPFILE.cmd
+echo "jc" >> $TMPFILE.cmd
+echo "jo" >> $TMPFILE.cmd
+echo "jw -r 259-4356" >> $TMPFILE.cmd
+echo "jc" >> $TMPFILE.cmd
+$DEBUGFS_EXE -w $TMPFILE -f $TMPFILE.cmd 2>> $OUT.new > /dev/null
+sed -f $cmd_dir/filter.sed < $OUT.new >> $OUT
+rm -rf $OUT.new
+
+test -d "$JOURNAL_DUMP_DIR" -a -w "$JOURNAL_DUMP_DIR" && cp "$TMPFILE" "$JOURNAL_DUMP_DIR/$test_name.img"
+echo "logdump -c" > $TMPFILE.cmd
+$DEBUGFS_EXE $TMPFILE -f $TMPFILE.cmd 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+rm -rf $TMPFILE.cmd
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi
diff --git a/tests/j_long_trans/expect b/tests/j_long_trans/expect
new file mode 100644
index 0000000..7638ef1
--- /dev/null
+++ b/tests/j_long_trans/expect
@@ -0,0 +1,107 @@
+Creating filesystem with 262144 1k blocks and 16384 inodes
+Superblock backups stored on blocks:
+ 8193, 24577, 40961, 57345, 73729, 204801, 221185
+
+Allocating group tables: done
+Writing inode tables: done
+Creating journal (8192 blocks): done
+Writing superblocks and filesystem accounting information: done
+
+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/16384 files (0.0% non-contiguous), 14431/262144 blocks
+Exit status is 0
+debugfs write journal
+debugfs: logdump -c
+Journal starts at block 1, transaction 1
+Found expected sequence 1, type 1 (descriptor block) at block 1
+Found expected sequence 1, type 1 (descriptor block) at block 126
+Found expected sequence 1, type 1 (descriptor block) at block 251
+Found expected sequence 1, type 1 (descriptor block) at block 376
+Found expected sequence 1, type 1 (descriptor block) at block 501
+Found expected sequence 1, type 1 (descriptor block) at block 626
+Found expected sequence 1, type 1 (descriptor block) at block 751
+Found expected sequence 1, type 1 (descriptor block) at block 876
+Found expected sequence 1, type 1 (descriptor block) at block 1001
+Found expected sequence 1, type 1 (descriptor block) at block 1126
+Found expected sequence 1, type 1 (descriptor block) at block 1251
+Found expected sequence 1, type 1 (descriptor block) at block 1376
+Found expected sequence 1, type 1 (descriptor block) at block 1501
+Found expected sequence 1, type 1 (descriptor block) at block 1626
+Found expected sequence 1, type 1 (descriptor block) at block 1751
+Found expected sequence 1, type 1 (descriptor block) at block 1876
+Found expected sequence 1, type 1 (descriptor block) at block 2001
+Found expected sequence 1, type 1 (descriptor block) at block 2126
+Found expected sequence 1, type 1 (descriptor block) at block 2251
+Found expected sequence 1, type 1 (descriptor block) at block 2376
+Found expected sequence 1, type 1 (descriptor block) at block 2501
+Found expected sequence 1, type 1 (descriptor block) at block 2626
+Found expected sequence 1, type 1 (descriptor block) at block 2751
+Found expected sequence 1, type 1 (descriptor block) at block 2876
+Found expected sequence 1, type 1 (descriptor block) at block 3001
+Found expected sequence 1, type 1 (descriptor block) at block 3126
+Found expected sequence 1, type 1 (descriptor block) at block 3251
+Found expected sequence 1, type 1 (descriptor block) at block 3376
+Found expected sequence 1, type 1 (descriptor block) at block 3501
+Found expected sequence 1, type 1 (descriptor block) at block 3626
+Found expected sequence 1, type 1 (descriptor block) at block 3751
+Found expected sequence 1, type 1 (descriptor block) at block 3876
+Found expected sequence 1, type 1 (descriptor block) at block 4001
+Found expected sequence 1, type 1 (descriptor block) at block 4126
+Found expected sequence 1, type 2 (commit block) at block 4133
+No magic number at block 4134: end of journal.
+test_filesys: recovering journal
+Superblock has an invalid journal (inode 8).
+Clear? yes
+
+*** ext3 journal has been deleted - filesystem is now ext2 only ***
+
+Resize inode not valid. Recreate? yes
+
+Pass 1: Checking inodes, blocks, and sizes
+Root inode is not a directory. Clear? yes
+
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Root inode not allocated. Allocate? yes
+
+/lost+found not found. Create? yes
+
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+Block bitmap differences: +(1--259) +273 +275 +289 +(291--418) +(2083--2210) +2341
+Fix? yes
+
+Free blocks count wrong for group #0 (5838, counted=5851).
+Fix? yes
+
+Free blocks count wrong for group #14 (0, counted=8192).
+Fix? yes
+
+Free blocks count wrong (247711, counted=255916).
+Fix? yes
+
+Inode bitmap differences: +1 +(3--10)
+Fix? yes
+
+Free inodes count wrong for group #0 (500, counted=501).
+Fix? yes
+
+Directories count wrong for group #0 (3, counted=2).
+Fix? yes
+
+Free inodes count wrong (16372, counted=16373).
+Fix? yes
+
+Recreate journal? yes
+
+Creating journal (8192 blocks): Done.
+
+*** journal has been re-created - filesystem is now ext3 again ***
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 11/16384 files (0.0% non-contiguous), 14420/262144 blocks
+Exit status is 1
diff --git a/tests/j_long_trans/name b/tests/j_long_trans/name
new file mode 100644
index 0000000..7a70f8f
--- /dev/null
+++ b/tests/j_long_trans/name
@@ -0,0 +1 @@
+transaction nuking free space
diff --git a/tests/j_long_trans/script b/tests/j_long_trans/script
new file mode 100644
index 0000000..9a4f131
--- /dev/null
+++ b/tests/j_long_trans/script
@@ -0,0 +1,59 @@
+if test -x $DEBUGFS_EXE; then
+
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+$MKE2FS -F -o Linux -b 1024 -O has_journal -T ext4 $TMPFILE 262144 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT 2>&1
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+echo "debugfs write journal" >> $OUT
+echo "jo" > $TMPFILE.cmd
+echo "jw -b 259-4356 /dev/zero" >> $TMPFILE.cmd
+echo "jc" >> $TMPFILE.cmd
+$DEBUGFS_EXE -w $TMPFILE -f $TMPFILE.cmd 2>> $OUT.new > /dev/null
+sed -f $cmd_dir/filter.sed < $OUT.new >> $OUT
+rm -rf $OUT.new
+
+test -d "$JOURNAL_DUMP_DIR" -a -w "$JOURNAL_DUMP_DIR" && cp "$TMPFILE" "$JOURNAL_DUMP_DIR/$test_name.img"
+echo "logdump -c" > $TMPFILE.cmd
+$DEBUGFS_EXE $TMPFILE -f $TMPFILE.cmd 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+rm -rf $TMPFILE.cmd
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi
diff --git a/tests/j_short_revoke_trans/expect b/tests/j_short_revoke_trans/expect
new file mode 100644
index 0000000..e83c5ea
--- /dev/null
+++ b/tests/j_short_revoke_trans/expect
@@ -0,0 +1,32 @@
+Creating filesystem with 65536 4k blocks and 16384 inodes
+Superblock backups stored on blocks:
+ 32768
+
+Allocating group tables: done
+Writing inode tables: done
+Creating journal (4096 blocks): done
+Writing superblocks and filesystem accounting information: done
+
+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/16384 files (0.0% non-contiguous), 5164/65536 blocks
+Exit status is 0
+debugfs write journal
+debugfs: logdump -c
+Journal starts at block 1, transaction 1
+Found expected sequence 1, type 1 (descriptor block) at block 1
+Found expected sequence 1, type 2 (commit block) at block 6
+Found expected sequence 2, type 5 (revoke table) at block 7
+Found expected sequence 2, type 2 (commit block) at block 8
+No magic number at block 9: end of journal.
+test_filesys: recovering journal
+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/16384 files (0.0% non-contiguous), 5164/65536 blocks
+Exit status is 0
diff --git a/tests/j_short_revoke_trans/name b/tests/j_short_revoke_trans/name
new file mode 100644
index 0000000..5470018
--- /dev/null
+++ b/tests/j_short_revoke_trans/name
@@ -0,0 +1 @@
+revoke blocks of transaction nuking bitmaps
diff --git a/tests/j_short_revoke_trans/script b/tests/j_short_revoke_trans/script
new file mode 100644
index 0000000..edf28f9
--- /dev/null
+++ b/tests/j_short_revoke_trans/script
@@ -0,0 +1,64 @@
+if test -x $DEBUGFS_EXE; then
+
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+$MKE2FS -F -o Linux -b 4096 -O has_journal -T ext4 $TMPFILE 65536 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT 2>&1
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+bitmaps="$($DUMPE2FS $TMPFILE 2>&1 | grep 'bitmap at' | sed -e 's/^.*Block bitmap at \([0-9]*\) .*Inode bitmap at \([0-9]*\).*$/\1,\2/g' | tr '\n' ',')"
+
+echo "debugfs write journal" >> $OUT
+echo "jo" > $TMPFILE.cmd
+echo "jw -b $bitmaps /dev/zero" >> $TMPFILE.cmd
+echo "jc" >> $TMPFILE.cmd
+echo "jo" >> $TMPFILE.cmd
+echo "jw -r $bitmaps" >> $TMPFILE.cmd
+echo "jc" >> $TMPFILE.cmd
+$DEBUGFS_EXE -w $TMPFILE -f $TMPFILE.cmd 2>> $OUT.new > /dev/null
+sed -f $cmd_dir/filter.sed < $OUT.new >> $OUT
+rm -rf $OUT.new
+
+test -d "$JOURNAL_DUMP_DIR" -a -w "$JOURNAL_DUMP_DIR" && cp "$TMPFILE" "$JOURNAL_DUMP_DIR/$test_name.img"
+echo "logdump -c" > $TMPFILE.cmd
+$DEBUGFS_EXE $TMPFILE -f $TMPFILE.cmd 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+rm -rf $TMPFILE.cmd
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi
diff --git a/tests/j_short_trans/expect b/tests/j_short_trans/expect
new file mode 100644
index 0000000..bcc8fe8
--- /dev/null
+++ b/tests/j_short_trans/expect
@@ -0,0 +1,38 @@
+Creating filesystem with 65536 4k blocks and 16384 inodes
+Superblock backups stored on blocks:
+ 32768
+
+Allocating group tables: done
+Writing inode tables: done
+Creating journal (4096 blocks): done
+Writing superblocks and filesystem accounting information: done
+
+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/16384 files (0.0% non-contiguous), 5164/65536 blocks
+Exit status is 0
+debugfs write journal
+debugfs: logdump -c
+Journal starts at block 1, transaction 1
+Found expected sequence 1, type 1 (descriptor block) at block 1
+Found expected sequence 1, type 2 (commit block) at block 6
+No magic number at block 7: end of journal.
+test_filesys: recovering journal
+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
+Block bitmap differences: +(0--1050) +(32768--36880)
+Fix? yes
+
+Inode bitmap differences: +(1--11)
+Fix? yes
+
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 11/16384 files (0.0% non-contiguous), 5164/65536 blocks
+Exit status is 1
diff --git a/tests/j_short_trans/name b/tests/j_short_trans/name
new file mode 100644
index 0000000..730fbad
--- /dev/null
+++ b/tests/j_short_trans/name
@@ -0,0 +1 @@
+transaction nuking the bitmaps
diff --git a/tests/j_short_trans/script b/tests/j_short_trans/script
new file mode 100644
index 0000000..00f4d6e
--- /dev/null
+++ b/tests/j_short_trans/script
@@ -0,0 +1,61 @@
+if test -x $DEBUGFS_EXE; then
+
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+$MKE2FS -F -o Linux -b 4096 -O has_journal -T ext4 $TMPFILE 65536 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT 2>&1
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+bitmaps="$($DUMPE2FS $TMPFILE 2>&1 | grep 'bitmap at' | sed -e 's/^.*Block bitmap at \([0-9]*\) .*Inode bitmap at \([0-9]*\).*$/\1,\2/g' | tr '\n' ',')"
+
+echo "debugfs write journal" >> $OUT
+echo "jo" > $TMPFILE.cmd
+echo "jw -b $bitmaps /dev/zero" >> $TMPFILE.cmd
+echo "jc" >> $TMPFILE.cmd
+$DEBUGFS_EXE -w $TMPFILE -f $TMPFILE.cmd 2>> $OUT.new > /dev/null
+sed -f $cmd_dir/filter.sed < $OUT.new >> $OUT
+rm -rf $OUT.new
+
+test -d "$JOURNAL_DUMP_DIR" -a -w "$JOURNAL_DUMP_DIR" && cp "$TMPFILE" "$JOURNAL_DUMP_DIR/$test_name.img"
+echo "logdump -c" > $TMPFILE.cmd
+$DEBUGFS_EXE $TMPFILE -f $TMPFILE.cmd 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+rm -rf $TMPFILE.cmd
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi
diff --git a/tests/j_short_trans_64bit/expect b/tests/j_short_trans_64bit/expect
new file mode 100644
index 0000000..f9971eb
--- /dev/null
+++ b/tests/j_short_trans_64bit/expect
@@ -0,0 +1,40 @@
+Creating filesystem with 65536 4k blocks and 16384 inodes
+Superblock backups stored on blocks:
+ 32768
+
+Allocating group tables: done
+Writing inode tables: done
+Creating journal (4096 blocks): done
+Writing superblocks and filesystem accounting information: done
+
+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/16384 files (0.0% non-contiguous), 5196/65536 blocks
+Exit status is 0
+Journal features: (none)
+debugfs write journal
+Journal features: journal_64bit
+debugfs: logdump -c
+Journal starts at block 1, transaction 1
+Found expected sequence 1, type 1 (descriptor block) at block 1
+Found expected sequence 1, type 2 (commit block) at block 6
+No magic number at block 7: end of journal.
+test_filesys: recovering journal
+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
+Block bitmap differences: +(0--1066) +(32768--36896)
+Fix? yes
+
+Inode bitmap differences: +(1--11)
+Fix? yes
+
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 11/16384 files (0.0% non-contiguous), 5196/65536 blocks
+Exit status is 1
diff --git a/tests/j_short_trans_64bit/name b/tests/j_short_trans_64bit/name
new file mode 100644
index 0000000..17b70d0
--- /dev/null
+++ b/tests/j_short_trans_64bit/name
@@ -0,0 +1 @@
+transaction nuking the bitmaps on 64bit
diff --git a/tests/j_short_trans_64bit/script b/tests/j_short_trans_64bit/script
new file mode 100644
index 0000000..daf0866
--- /dev/null
+++ b/tests/j_short_trans_64bit/script
@@ -0,0 +1,65 @@
+if test -x $DEBUGFS_EXE; then
+
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+$MKE2FS -F -o Linux -b 4096 -O 64bit,has_journal -T ext4 $TMPFILE 65536 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT 2>&1
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+bitmaps="$($DUMPE2FS $TMPFILE 2>&1 | grep 'bitmap at' | sed -e 's/^.*Block bitmap at \([0-9]*\) .*Inode bitmap at \([0-9]*\).*$/\1,\2/g' | tr '\n' ',')"
+
+$DUMPE2FS $TMPFILE 2>&1 | grep '^Journal features:' >> $OUT
+
+echo "debugfs write journal" >> $OUT
+echo "jo" > $TMPFILE.cmd
+echo "jw -b $bitmaps /dev/zero" >> $TMPFILE.cmd
+echo "jc" >> $TMPFILE.cmd
+$DEBUGFS_EXE -w $TMPFILE -f $TMPFILE.cmd 2>> $OUT.new > /dev/null
+sed -f $cmd_dir/filter.sed < $OUT.new >> $OUT
+rm -rf $OUT.new
+
+$DUMPE2FS $TMPFILE 2>&1 | grep '^Journal features:' >> $OUT
+
+test -d "$JOURNAL_DUMP_DIR" -a -w "$JOURNAL_DUMP_DIR" && cp "$TMPFILE" "$JOURNAL_DUMP_DIR/$test_name.img"
+echo "logdump -c" > $TMPFILE.cmd
+$DEBUGFS_EXE $TMPFILE -f $TMPFILE.cmd 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+rm -rf $TMPFILE.cmd
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi
diff --git a/tests/j_short_trans_open_recover/expect b/tests/j_short_trans_open_recover/expect
new file mode 100644
index 0000000..be6e363
--- /dev/null
+++ b/tests/j_short_trans_open_recover/expect
@@ -0,0 +1,43 @@
+Creating filesystem with 65536 4k blocks and 16384 inodes
+Superblock backups stored on blocks:
+ 32768
+
+Allocating group tables: done
+Writing inode tables: done
+Creating journal (4096 blocks): done
+Writing superblocks and filesystem accounting information: done
+
+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/16384 files (0.0% non-contiguous), 5164/65536 blocks
+Exit status is 0
+debugfs write journal
+debugfs: logdump -c
+Journal starts at block 1, transaction 1
+Found expected sequence 1, type 1 (descriptor block) at block 1
+Found expected sequence 1, type 2 (commit block) at block 6
+No magic number at block 7: end of journal.
+debugfs can't recover open journal
+debugfs: jo
+debugfs: jr
+Please close the journal before recovering it.
+debugfs: jc
+test_filesys: recovering journal
+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
+Block bitmap differences: +(0--1050) +(32768--36880)
+Fix? yes
+
+Inode bitmap differences: +(1--11)
+Fix? yes
+
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 11/16384 files (0.0% non-contiguous), 5164/65536 blocks
+Exit status is 1
diff --git a/tests/j_short_trans_open_recover/name b/tests/j_short_trans_open_recover/name
new file mode 100644
index 0000000..892e95c
--- /dev/null
+++ b/tests/j_short_trans_open_recover/name
@@ -0,0 +1 @@
+ensure we can't recover the journal with journal open
diff --git a/tests/j_short_trans_open_recover/script b/tests/j_short_trans_open_recover/script
new file mode 100644
index 0000000..fbbb714
--- /dev/null
+++ b/tests/j_short_trans_open_recover/script
@@ -0,0 +1,69 @@
+if test -x $DEBUGFS_EXE; then
+
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+$MKE2FS -F -o Linux -b 4096 -O has_journal -T ext4 $TMPFILE 65536 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT 2>&1
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+bitmaps="$($DUMPE2FS $TMPFILE 2>&1 | grep 'bitmap at' | sed -e 's/^.*Block bitmap at \([0-9]*\) .*Inode bitmap at \([0-9]*\).*$/\1,\2/g' | tr '\n' ',')"
+
+echo "debugfs write journal" >> $OUT
+echo "jo" > $TMPFILE.cmd
+echo "jw -b $bitmaps /dev/zero" >> $TMPFILE.cmd
+echo "jc" >> $TMPFILE.cmd
+$DEBUGFS_EXE -w $TMPFILE -f $TMPFILE.cmd 2>> $OUT.new > /dev/null
+sed -f $cmd_dir/filter.sed < $OUT.new >> $OUT
+rm -rf $OUT.new
+
+test -d "$JOURNAL_DUMP_DIR" -a -w "$JOURNAL_DUMP_DIR" && cp "$TMPFILE" "$JOURNAL_DUMP_DIR/$test_name.img"
+echo "logdump -c" > $TMPFILE.cmd
+$DEBUGFS_EXE $TMPFILE -f $TMPFILE.cmd 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+rm -rf $TMPFILE.cmd
+
+echo "debugfs can't recover open journal" >> $OUT
+echo "jo" > $TMPFILE.cmd
+echo "jr" >> $TMPFILE.cmd
+echo "jc" >> $TMPFILE.cmd
+$DEBUGFS_EXE -w $TMPFILE -f $TMPFILE.cmd > $OUT.new 2>&1
+sed -f $cmd_dir/filter.sed < $OUT.new >> $OUT
+rm -rf $OUT.new
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi
diff --git a/tests/j_short_trans_recover/expect b/tests/j_short_trans_recover/expect
new file mode 100644
index 0000000..7586733
--- /dev/null
+++ b/tests/j_short_trans_recover/expect
@@ -0,0 +1,40 @@
+Creating filesystem with 65536 4k blocks and 16384 inodes
+Superblock backups stored on blocks:
+ 32768
+
+Allocating group tables: done
+Writing inode tables: done
+Creating journal (4096 blocks): done
+Writing superblocks and filesystem accounting information: done
+
+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/16384 files (0.0% non-contiguous), 5164/65536 blocks
+Exit status is 0
+debugfs write journal
+debugfs: logdump -c
+Journal starts at block 1, transaction 1
+Found expected sequence 1, type 1 (descriptor block) at block 1
+Found expected sequence 1, type 2 (commit block) at block 7
+Found expected sequence 2, type 5 (revoke table) at block 8
+Found expected sequence 2, type 2 (commit block) at block 9
+No magic number at block 10: end of journal.
+debugfs recover journal
+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
+Block bitmap differences: +(0--1050) +(32768--36880)
+Fix? yes
+
+Inode bitmap differences: +(1--11)
+Fix? yes
+
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 11/16384 files (0.0% non-contiguous), 5164/65536 blocks
+Exit status is 1
diff --git a/tests/j_short_trans_recover/name b/tests/j_short_trans_recover/name
new file mode 100644
index 0000000..54e3553
--- /dev/null
+++ b/tests/j_short_trans_recover/name
@@ -0,0 +1 @@
+transaction nuking the bitmaps (debugfs recovery)
diff --git a/tests/j_short_trans_recover/script b/tests/j_short_trans_recover/script
new file mode 100644
index 0000000..7fa6158
--- /dev/null
+++ b/tests/j_short_trans_recover/script
@@ -0,0 +1,70 @@
+if test -x $DEBUGFS_EXE; then
+
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+$MKE2FS -F -o Linux -b 4096 -O has_journal -T ext4 $TMPFILE 65536 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT 2>&1
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+bitmaps="$($DUMPE2FS $TMPFILE 2>&1 | grep 'bitmap at' | sed -e 's/^.*Block bitmap at \([0-9]*\) .*Inode bitmap at \([0-9]*\).*$/\1,\2/g' | tr '\n' ',')"
+
+echo "debugfs write journal" >> $OUT
+echo "jo" > $TMPFILE.cmd
+echo "jw -b 333,$bitmaps /dev/zero" >> $TMPFILE.cmd
+echo "jc" >> $TMPFILE.cmd
+echo "jo" >> $TMPFILE.cmd
+echo "jw -r 333" >> $TMPFILE.cmd
+echo "jc" >> $TMPFILE.cmd
+$DEBUGFS_EXE -w $TMPFILE -f $TMPFILE.cmd 2>> $OUT.new > /dev/null
+sed -f $cmd_dir/filter.sed < $OUT.new >> $OUT
+rm -rf $OUT.new
+
+test -d "$JOURNAL_DUMP_DIR" -a -w "$JOURNAL_DUMP_DIR" && cp "$TMPFILE" "$JOURNAL_DUMP_DIR/$test_name.img"
+echo "logdump -c" > $TMPFILE.cmd
+$DEBUGFS_EXE $TMPFILE -f $TMPFILE.cmd 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+rm -rf $TMPFILE.cmd
+
+echo "debugfs recover journal" >> $OUT
+echo "jr" > $TMPFILE.cmd
+$DEBUGFS_EXE -w $TMPFILE -f $TMPFILE.cmd 2>> $OUT.new > /dev/null
+sed -f $cmd_dir/filter.sed < $OUT.new >> $OUT
+rm -rf $OUT.new
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi
diff --git a/tests/j_short_uncommitted_trans/expect b/tests/j_short_uncommitted_trans/expect
new file mode 100644
index 0000000..dedddb5
--- /dev/null
+++ b/tests/j_short_uncommitted_trans/expect
@@ -0,0 +1,26 @@
+Creating filesystem with 65536 4k blocks and 16384 inodes
+Superblock backups stored on blocks:
+ 32768
+
+Allocating group tables: done
+Writing inode tables: done
+Creating journal (4096 blocks): done
+Writing superblocks and filesystem accounting information: done
+
+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/16384 files (0.0% non-contiguous), 5164/65536 blocks
+Exit status is 0
+debugfs write journal
+debugfs: logdump -c
+Journal starts at block 0, transaction 1
+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/16384 files (0.0% non-contiguous), 5164/65536 blocks
+Exit status is 0
diff --git a/tests/j_short_uncommitted_trans/name b/tests/j_short_uncommitted_trans/name
new file mode 100644
index 0000000..b617231
--- /dev/null
+++ b/tests/j_short_uncommitted_trans/name
@@ -0,0 +1 @@
+uncommitted transaction nuking bitmaps
diff --git a/tests/j_short_uncommitted_trans/script b/tests/j_short_uncommitted_trans/script
new file mode 100644
index 0000000..207d746
--- /dev/null
+++ b/tests/j_short_uncommitted_trans/script
@@ -0,0 +1,61 @@
+if test -x $DEBUGFS_EXE; then
+
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+$MKE2FS -F -o Linux -b 4096 -O has_journal -T ext4 $TMPFILE 65536 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT 2>&1
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+bitmaps="$($DUMPE2FS $TMPFILE 2>&1 | grep 'bitmap at' | sed -e 's/^.*Block bitmap at \([0-9]*\) .*Inode bitmap at \([0-9]*\).*$/\1,\2/g' | tr '\n' ',')"
+
+echo "debugfs write journal" >> $OUT
+echo "jo" > $TMPFILE.cmd
+echo "jw -b $bitmaps -c /dev/zero" >> $TMPFILE.cmd
+echo "jc" >> $TMPFILE.cmd
+$DEBUGFS_EXE -w $TMPFILE -f $TMPFILE.cmd 2>> $OUT.new > /dev/null
+sed -f $cmd_dir/filter.sed < $OUT.new >> $OUT
+rm -rf $OUT.new
+
+test -d "$JOURNAL_DUMP_DIR" -a -w "$JOURNAL_DUMP_DIR" && cp "$TMPFILE" "$JOURNAL_DUMP_DIR/$test_name.img"
+echo "logdump -c" > $TMPFILE.cmd
+$DEBUGFS_EXE $TMPFILE -f $TMPFILE.cmd 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+rm -rf $TMPFILE.cmd
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi


2014-09-08 23:13:13

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 14/25] tests: test writing and recovering 64bit csum_v3 journals

Simple tests for the 64bit journal transaction creation code when
journal and metadata_csum are enabled. We test writing (bad) block
bitmaps out through the journal and replaying them via fsck, with a
few twists:

(a) All bitmaps are committed (fs errors reported)
(b) All the bitmap blocks are revoked (no errors)
(c) The transaction is never committed (no errors)
(d) Same as (a), but debugfs gets to do the replay.

We also test:

(a) writing and replaying transactions with multiple
descriptor blocks
(b) same, but with multiple revoke blocks.

Signed-off-by: Darrick J. Wong <[email protected]>
---
tests/j_long_revoke_trans_mcsum_64bit/expect | 132 ++++++++++++++++++
tests/j_long_revoke_trans_mcsum_64bit/name | 1
tests/j_long_revoke_trans_mcsum_64bit/script | 67 +++++++++
tests/j_long_trans_mcsum_64bit/expect | 145 ++++++++++++++++++++
tests/j_long_trans_mcsum_64bit/name | 1
tests/j_long_trans_mcsum_64bit/script | 63 +++++++++
tests/j_short_revoke_trans_mcsum_64bit/expect | 34 +++++
tests/j_short_revoke_trans_mcsum_64bit/name | 1
tests/j_short_revoke_trans_mcsum_64bit/script | 68 +++++++++
tests/j_short_trans_mcsum_64bit/expect | 40 ++++++
tests/j_short_trans_mcsum_64bit/name | 1
tests/j_short_trans_mcsum_64bit/script | 65 +++++++++
tests/j_short_trans_recover_mcsum_64bit/expect | 42 ++++++
tests/j_short_trans_recover_mcsum_64bit/name | 1
tests/j_short_trans_recover_mcsum_64bit/script | 74 ++++++++++
tests/j_short_uncommitted_trans_mcsum_64bit/expect | 28 ++++
tests/j_short_uncommitted_trans_mcsum_64bit/name | 1
tests/j_short_uncommitted_trans_mcsum_64bit/script | 65 +++++++++
18 files changed, 829 insertions(+)
create mode 100644 tests/j_long_revoke_trans_mcsum_64bit/expect
create mode 100644 tests/j_long_revoke_trans_mcsum_64bit/name
create mode 100644 tests/j_long_revoke_trans_mcsum_64bit/script
create mode 100644 tests/j_long_trans_mcsum_64bit/expect
create mode 100644 tests/j_long_trans_mcsum_64bit/name
create mode 100644 tests/j_long_trans_mcsum_64bit/script
create mode 100644 tests/j_short_revoke_trans_mcsum_64bit/expect
create mode 100644 tests/j_short_revoke_trans_mcsum_64bit/name
create mode 100644 tests/j_short_revoke_trans_mcsum_64bit/script
create mode 100644 tests/j_short_trans_mcsum_64bit/expect
create mode 100644 tests/j_short_trans_mcsum_64bit/name
create mode 100644 tests/j_short_trans_mcsum_64bit/script
create mode 100644 tests/j_short_trans_recover_mcsum_64bit/expect
create mode 100644 tests/j_short_trans_recover_mcsum_64bit/name
create mode 100644 tests/j_short_trans_recover_mcsum_64bit/script
create mode 100644 tests/j_short_uncommitted_trans_mcsum_64bit/expect
create mode 100644 tests/j_short_uncommitted_trans_mcsum_64bit/name
create mode 100644 tests/j_short_uncommitted_trans_mcsum_64bit/script


diff --git a/tests/j_long_revoke_trans_mcsum_64bit/expect b/tests/j_long_revoke_trans_mcsum_64bit/expect
new file mode 100644
index 0000000..29dc407
--- /dev/null
+++ b/tests/j_long_revoke_trans_mcsum_64bit/expect
@@ -0,0 +1,132 @@
+Creating filesystem with 524288 1k blocks and 32768 inodes
+Superblock backups stored on blocks:
+ 8193, 24577, 40961, 57345, 73729, 204801, 221185, 401409
+
+Allocating group tables: done
+Writing inode tables: done
+Creating journal (16384 blocks): done
+Writing superblocks and filesystem accounting information: done
+
+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/32768 files (0.0% non-contiguous), 27068/524288 blocks
+Exit status is 0
+Journal features: (none)
+debugfs write journal
+Journal features: journal_incompat_revoke journal_64bit journal_checksum_v3
+debugfs: logdump -c
+Journal starts at block 1, transaction 1
+Found expected sequence 1, type 1 (descriptor block) at block 1
+Found expected sequence 1, type 1 (descriptor block) at block 64
+Found expected sequence 1, type 1 (descriptor block) at block 127
+Found expected sequence 1, type 1 (descriptor block) at block 190
+Found expected sequence 1, type 1 (descriptor block) at block 253
+Found expected sequence 1, type 1 (descriptor block) at block 316
+Found expected sequence 1, type 1 (descriptor block) at block 379
+Found expected sequence 1, type 1 (descriptor block) at block 442
+Found expected sequence 1, type 1 (descriptor block) at block 505
+Found expected sequence 1, type 1 (descriptor block) at block 568
+Found expected sequence 1, type 1 (descriptor block) at block 631
+Found expected sequence 1, type 1 (descriptor block) at block 694
+Found expected sequence 1, type 1 (descriptor block) at block 757
+Found expected sequence 1, type 1 (descriptor block) at block 820
+Found expected sequence 1, type 1 (descriptor block) at block 883
+Found expected sequence 1, type 1 (descriptor block) at block 946
+Found expected sequence 1, type 1 (descriptor block) at block 1009
+Found expected sequence 1, type 1 (descriptor block) at block 1072
+Found expected sequence 1, type 1 (descriptor block) at block 1135
+Found expected sequence 1, type 1 (descriptor block) at block 1198
+Found expected sequence 1, type 1 (descriptor block) at block 1261
+Found expected sequence 1, type 1 (descriptor block) at block 1324
+Found expected sequence 1, type 1 (descriptor block) at block 1387
+Found expected sequence 1, type 1 (descriptor block) at block 1450
+Found expected sequence 1, type 1 (descriptor block) at block 1513
+Found expected sequence 1, type 1 (descriptor block) at block 1576
+Found expected sequence 1, type 1 (descriptor block) at block 1639
+Found expected sequence 1, type 1 (descriptor block) at block 1702
+Found expected sequence 1, type 1 (descriptor block) at block 1765
+Found expected sequence 1, type 1 (descriptor block) at block 1828
+Found expected sequence 1, type 1 (descriptor block) at block 1891
+Found expected sequence 1, type 1 (descriptor block) at block 1954
+Found expected sequence 1, type 1 (descriptor block) at block 2017
+Found expected sequence 1, type 1 (descriptor block) at block 2080
+Found expected sequence 1, type 1 (descriptor block) at block 2143
+Found expected sequence 1, type 1 (descriptor block) at block 2206
+Found expected sequence 1, type 1 (descriptor block) at block 2269
+Found expected sequence 1, type 1 (descriptor block) at block 2332
+Found expected sequence 1, type 1 (descriptor block) at block 2395
+Found expected sequence 1, type 1 (descriptor block) at block 2458
+Found expected sequence 1, type 1 (descriptor block) at block 2521
+Found expected sequence 1, type 1 (descriptor block) at block 2584
+Found expected sequence 1, type 1 (descriptor block) at block 2647
+Found expected sequence 1, type 1 (descriptor block) at block 2710
+Found expected sequence 1, type 1 (descriptor block) at block 2773
+Found expected sequence 1, type 1 (descriptor block) at block 2836
+Found expected sequence 1, type 1 (descriptor block) at block 2899
+Found expected sequence 1, type 1 (descriptor block) at block 2962
+Found expected sequence 1, type 1 (descriptor block) at block 3025
+Found expected sequence 1, type 1 (descriptor block) at block 3088
+Found expected sequence 1, type 1 (descriptor block) at block 3151
+Found expected sequence 1, type 1 (descriptor block) at block 3214
+Found expected sequence 1, type 1 (descriptor block) at block 3277
+Found expected sequence 1, type 1 (descriptor block) at block 3340
+Found expected sequence 1, type 1 (descriptor block) at block 3403
+Found expected sequence 1, type 1 (descriptor block) at block 3466
+Found expected sequence 1, type 1 (descriptor block) at block 3529
+Found expected sequence 1, type 1 (descriptor block) at block 3592
+Found expected sequence 1, type 1 (descriptor block) at block 3655
+Found expected sequence 1, type 1 (descriptor block) at block 3718
+Found expected sequence 1, type 1 (descriptor block) at block 3781
+Found expected sequence 1, type 1 (descriptor block) at block 3844
+Found expected sequence 1, type 1 (descriptor block) at block 3907
+Found expected sequence 1, type 1 (descriptor block) at block 3970
+Found expected sequence 1, type 1 (descriptor block) at block 4033
+Found expected sequence 1, type 1 (descriptor block) at block 4096
+Found expected sequence 1, type 1 (descriptor block) at block 4159
+Found expected sequence 1, type 2 (commit block) at block 4165
+Found expected sequence 2, type 5 (revoke table) at block 4166
+Found expected sequence 2, type 5 (revoke table) at block 4167
+Found expected sequence 2, type 5 (revoke table) at block 4168
+Found expected sequence 2, type 5 (revoke table) at block 4169
+Found expected sequence 2, type 5 (revoke table) at block 4170
+Found expected sequence 2, type 5 (revoke table) at block 4171
+Found expected sequence 2, type 5 (revoke table) at block 4172
+Found expected sequence 2, type 5 (revoke table) at block 4173
+Found expected sequence 2, type 5 (revoke table) at block 4174
+Found expected sequence 2, type 5 (revoke table) at block 4175
+Found expected sequence 2, type 5 (revoke table) at block 4176
+Found expected sequence 2, type 5 (revoke table) at block 4177
+Found expected sequence 2, type 5 (revoke table) at block 4178
+Found expected sequence 2, type 5 (revoke table) at block 4179
+Found expected sequence 2, type 5 (revoke table) at block 4180
+Found expected sequence 2, type 5 (revoke table) at block 4181
+Found expected sequence 2, type 5 (revoke table) at block 4182
+Found expected sequence 2, type 5 (revoke table) at block 4183
+Found expected sequence 2, type 5 (revoke table) at block 4184
+Found expected sequence 2, type 5 (revoke table) at block 4185
+Found expected sequence 2, type 5 (revoke table) at block 4186
+Found expected sequence 2, type 5 (revoke table) at block 4187
+Found expected sequence 2, type 5 (revoke table) at block 4188
+Found expected sequence 2, type 5 (revoke table) at block 4189
+Found expected sequence 2, type 5 (revoke table) at block 4190
+Found expected sequence 2, type 5 (revoke table) at block 4191
+Found expected sequence 2, type 5 (revoke table) at block 4192
+Found expected sequence 2, type 5 (revoke table) at block 4193
+Found expected sequence 2, type 5 (revoke table) at block 4194
+Found expected sequence 2, type 5 (revoke table) at block 4195
+Found expected sequence 2, type 5 (revoke table) at block 4196
+Found expected sequence 2, type 5 (revoke table) at block 4197
+Found expected sequence 2, type 5 (revoke table) at block 4198
+Found expected sequence 2, type 2 (commit block) at block 4199
+No magic number at block 4200: end of journal.
+test_filesys: recovering journal
+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/32768 files (0.0% non-contiguous), 27068/524288 blocks
+Exit status is 0
diff --git a/tests/j_long_revoke_trans_mcsum_64bit/name b/tests/j_long_revoke_trans_mcsum_64bit/name
new file mode 100644
index 0000000..809900b
--- /dev/null
+++ b/tests/j_long_revoke_trans_mcsum_64bit/name
@@ -0,0 +1 @@
+revoked transaction nuking free space on 64bit,metadata_csum
diff --git a/tests/j_long_revoke_trans_mcsum_64bit/script b/tests/j_long_revoke_trans_mcsum_64bit/script
new file mode 100644
index 0000000..8133a66
--- /dev/null
+++ b/tests/j_long_revoke_trans_mcsum_64bit/script
@@ -0,0 +1,67 @@
+if test -x $DEBUGFS_EXE; then
+
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+$MKE2FS -F -o Linux -b 1024 -O 64bit,has_journal,metadata_csum -T ext4 $TMPFILE 524288 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT 2>&1
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+$DUMPE2FS $TMPFILE 2>&1 | grep '^Journal features:' >> $OUT
+
+echo "debugfs write journal" >> $OUT
+echo "jo -c" > $TMPFILE.cmd
+echo "jw -b 262-4358 /dev/zero" >> $TMPFILE.cmd
+echo "jc" >> $TMPFILE.cmd
+echo "jo" >> $TMPFILE.cmd
+echo "jw -r 262-4358" >> $TMPFILE.cmd
+echo "jc" >> $TMPFILE.cmd
+#$DEBUGFS_EXE -w $TMPFILE -f $TMPFILE.cmd >> $OUT 2>&1
+$DEBUGFS_EXE -w $TMPFILE -f $TMPFILE.cmd 2>> $OUT.new > /dev/null
+sed -f $cmd_dir/filter.sed < $OUT.new >> $OUT
+rm -rf $OUT.new
+
+$DUMPE2FS $TMPFILE 2>&1 | grep '^Journal features:' >> $OUT
+
+test -d "$JOURNAL_DUMP_DIR" -a -w "$JOURNAL_DUMP_DIR" && cp "$TMPFILE" "$JOURNAL_DUMP_DIR/$test_name.img"
+echo "logdump -c" > $TMPFILE.cmd
+$DEBUGFS_EXE $TMPFILE -f $TMPFILE.cmd 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+rm -rf $TMPFILE.cmd
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi
diff --git a/tests/j_long_trans_mcsum_64bit/expect b/tests/j_long_trans_mcsum_64bit/expect
new file mode 100644
index 0000000..94e9925
--- /dev/null
+++ b/tests/j_long_trans_mcsum_64bit/expect
@@ -0,0 +1,145 @@
+Creating filesystem with 524288 1k blocks and 32768 inodes
+Superblock backups stored on blocks:
+ 8193, 24577, 40961, 57345, 73729, 204801, 221185, 401409
+
+Allocating group tables: done
+Writing inode tables: done
+Creating journal (16384 blocks): done
+Writing superblocks and filesystem accounting information: done
+
+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/32768 files (0.0% non-contiguous), 27068/524288 blocks
+Exit status is 0
+Journal features: (none)
+debugfs write journal
+Journal features: journal_64bit journal_checksum_v3
+debugfs: logdump -c
+Journal starts at block 1, transaction 1
+Found expected sequence 1, type 1 (descriptor block) at block 1
+Found expected sequence 1, type 1 (descriptor block) at block 64
+Found expected sequence 1, type 1 (descriptor block) at block 127
+Found expected sequence 1, type 1 (descriptor block) at block 190
+Found expected sequence 1, type 1 (descriptor block) at block 253
+Found expected sequence 1, type 1 (descriptor block) at block 316
+Found expected sequence 1, type 1 (descriptor block) at block 379
+Found expected sequence 1, type 1 (descriptor block) at block 442
+Found expected sequence 1, type 1 (descriptor block) at block 505
+Found expected sequence 1, type 1 (descriptor block) at block 568
+Found expected sequence 1, type 1 (descriptor block) at block 631
+Found expected sequence 1, type 1 (descriptor block) at block 694
+Found expected sequence 1, type 1 (descriptor block) at block 757
+Found expected sequence 1, type 1 (descriptor block) at block 820
+Found expected sequence 1, type 1 (descriptor block) at block 883
+Found expected sequence 1, type 1 (descriptor block) at block 946
+Found expected sequence 1, type 1 (descriptor block) at block 1009
+Found expected sequence 1, type 1 (descriptor block) at block 1072
+Found expected sequence 1, type 1 (descriptor block) at block 1135
+Found expected sequence 1, type 1 (descriptor block) at block 1198
+Found expected sequence 1, type 1 (descriptor block) at block 1261
+Found expected sequence 1, type 1 (descriptor block) at block 1324
+Found expected sequence 1, type 1 (descriptor block) at block 1387
+Found expected sequence 1, type 1 (descriptor block) at block 1450
+Found expected sequence 1, type 1 (descriptor block) at block 1513
+Found expected sequence 1, type 1 (descriptor block) at block 1576
+Found expected sequence 1, type 1 (descriptor block) at block 1639
+Found expected sequence 1, type 1 (descriptor block) at block 1702
+Found expected sequence 1, type 1 (descriptor block) at block 1765
+Found expected sequence 1, type 1 (descriptor block) at block 1828
+Found expected sequence 1, type 1 (descriptor block) at block 1891
+Found expected sequence 1, type 1 (descriptor block) at block 1954
+Found expected sequence 1, type 1 (descriptor block) at block 2017
+Found expected sequence 1, type 1 (descriptor block) at block 2080
+Found expected sequence 1, type 1 (descriptor block) at block 2143
+Found expected sequence 1, type 1 (descriptor block) at block 2206
+Found expected sequence 1, type 1 (descriptor block) at block 2269
+Found expected sequence 1, type 1 (descriptor block) at block 2332
+Found expected sequence 1, type 1 (descriptor block) at block 2395
+Found expected sequence 1, type 1 (descriptor block) at block 2458
+Found expected sequence 1, type 1 (descriptor block) at block 2521
+Found expected sequence 1, type 1 (descriptor block) at block 2584
+Found expected sequence 1, type 1 (descriptor block) at block 2647
+Found expected sequence 1, type 1 (descriptor block) at block 2710
+Found expected sequence 1, type 1 (descriptor block) at block 2773
+Found expected sequence 1, type 1 (descriptor block) at block 2836
+Found expected sequence 1, type 1 (descriptor block) at block 2899
+Found expected sequence 1, type 1 (descriptor block) at block 2962
+Found expected sequence 1, type 1 (descriptor block) at block 3025
+Found expected sequence 1, type 1 (descriptor block) at block 3088
+Found expected sequence 1, type 1 (descriptor block) at block 3151
+Found expected sequence 1, type 1 (descriptor block) at block 3214
+Found expected sequence 1, type 1 (descriptor block) at block 3277
+Found expected sequence 1, type 1 (descriptor block) at block 3340
+Found expected sequence 1, type 1 (descriptor block) at block 3403
+Found expected sequence 1, type 1 (descriptor block) at block 3466
+Found expected sequence 1, type 1 (descriptor block) at block 3529
+Found expected sequence 1, type 1 (descriptor block) at block 3592
+Found expected sequence 1, type 1 (descriptor block) at block 3655
+Found expected sequence 1, type 1 (descriptor block) at block 3718
+Found expected sequence 1, type 1 (descriptor block) at block 3781
+Found expected sequence 1, type 1 (descriptor block) at block 3844
+Found expected sequence 1, type 1 (descriptor block) at block 3907
+Found expected sequence 1, type 1 (descriptor block) at block 3970
+Found expected sequence 1, type 1 (descriptor block) at block 4033
+Found expected sequence 1, type 1 (descriptor block) at block 4096
+Found expected sequence 1, type 1 (descriptor block) at block 4159
+Found expected sequence 1, type 2 (commit block) at block 4165
+No magic number at block 4166: end of journal.
+test_filesys: recovering journal
+Superblock has an invalid journal (inode 8).
+Clear? yes
+
+*** ext3 journal has been deleted - filesystem is now ext2 only ***
+
+Resize inode not valid. Recreate? yes
+
+Pass 1: Checking inodes, blocks, and sizes
+Root inode is not a directory. Clear? yes
+
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Root inode not allocated. Allocate? yes
+
+/lost+found not found. Create? yes
+
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+Block bitmap differences: +(1--262) +278 +(294--421) +2344 -(139265--155648)
+Fix? yes
+
+Free blocks count wrong for group #0 (5835, counted=5848).
+Fix? yes
+
+Free blocks count wrong for group #17 (0, counted=8192).
+Fix? yes
+
+Free blocks count wrong for group #18 (0, counted=8192).
+Fix? yes
+
+Free blocks count wrong (497218, counted=513615).
+Fix? yes
+
+Inode bitmap differences: +1 +(3--10)
+Fix? yes
+
+Free inodes count wrong for group #0 (500, counted=501).
+Fix? yes
+
+Directories count wrong for group #0 (3, counted=2).
+Fix? yes
+
+Free inodes count wrong (32756, counted=32757).
+Fix? yes
+
+Recreate journal? yes
+
+Creating journal (16384 blocks): Done.
+
+*** journal has been re-created - filesystem is now ext3 again ***
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 11/32768 files (0.0% non-contiguous), 27057/524288 blocks
+Exit status is 1
diff --git a/tests/j_long_trans_mcsum_64bit/name b/tests/j_long_trans_mcsum_64bit/name
new file mode 100644
index 0000000..9dab338
--- /dev/null
+++ b/tests/j_long_trans_mcsum_64bit/name
@@ -0,0 +1 @@
+transaction nuking free space on 64bit,metadata_csum
diff --git a/tests/j_long_trans_mcsum_64bit/script b/tests/j_long_trans_mcsum_64bit/script
new file mode 100644
index 0000000..8ded550
--- /dev/null
+++ b/tests/j_long_trans_mcsum_64bit/script
@@ -0,0 +1,63 @@
+if test -x $DEBUGFS_EXE; then
+
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+$MKE2FS -F -o Linux -b 1024 -O 64bit,has_journal,metadata_csum -T ext4 $TMPFILE 524288 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT 2>&1
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+$DUMPE2FS $TMPFILE 2>&1 | grep '^Journal features:' >> $OUT
+
+echo "debugfs write journal" >> $OUT
+echo "jo -c" > $TMPFILE.cmd
+echo "jw -b 262-4358 /dev/zero" >> $TMPFILE.cmd
+echo "jc" >> $TMPFILE.cmd
+$DEBUGFS_EXE -w $TMPFILE -f $TMPFILE.cmd 2>> $OUT.new > /dev/null
+sed -f $cmd_dir/filter.sed < $OUT.new >> $OUT
+rm -rf $OUT.new
+
+$DUMPE2FS $TMPFILE 2>&1 | grep '^Journal features:' >> $OUT
+
+test -d "$JOURNAL_DUMP_DIR" -a -w "$JOURNAL_DUMP_DIR" && cp "$TMPFILE" "$JOURNAL_DUMP_DIR/$test_name.img"
+echo "logdump -c" > $TMPFILE.cmd
+$DEBUGFS_EXE $TMPFILE -f $TMPFILE.cmd 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+rm -rf $TMPFILE.cmd
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi
diff --git a/tests/j_short_revoke_trans_mcsum_64bit/expect b/tests/j_short_revoke_trans_mcsum_64bit/expect
new file mode 100644
index 0000000..2b0eeb3
--- /dev/null
+++ b/tests/j_short_revoke_trans_mcsum_64bit/expect
@@ -0,0 +1,34 @@
+Creating filesystem with 131072 4k blocks and 32768 inodes
+Superblock backups stored on blocks:
+ 32768, 98304
+
+Allocating group tables: done
+Writing inode tables: done
+Creating journal (4096 blocks): done
+Writing superblocks and filesystem accounting information: done
+
+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/32768 files (0.0% non-contiguous), 6353/131072 blocks
+Exit status is 0
+Journal features: (none)
+debugfs write journal
+Journal features: journal_incompat_revoke journal_64bit journal_checksum_v3
+debugfs: logdump -c
+Journal starts at block 1, transaction 1
+Found expected sequence 1, type 1 (descriptor block) at block 1
+Found expected sequence 1, type 2 (commit block) at block 10
+Found expected sequence 2, type 5 (revoke table) at block 11
+Found expected sequence 2, type 2 (commit block) at block 12
+No magic number at block 13: end of journal.
+test_filesys: recovering journal
+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/32768 files (0.0% non-contiguous), 6353/131072 blocks
+Exit status is 0
diff --git a/tests/j_short_revoke_trans_mcsum_64bit/name b/tests/j_short_revoke_trans_mcsum_64bit/name
new file mode 100644
index 0000000..fb286fd
--- /dev/null
+++ b/tests/j_short_revoke_trans_mcsum_64bit/name
@@ -0,0 +1 @@
+revoke blocks of transaction nuking the bitmaps on 64bit,metadata_csum
diff --git a/tests/j_short_revoke_trans_mcsum_64bit/script b/tests/j_short_revoke_trans_mcsum_64bit/script
new file mode 100644
index 0000000..8bd6e08
--- /dev/null
+++ b/tests/j_short_revoke_trans_mcsum_64bit/script
@@ -0,0 +1,68 @@
+if test -x $DEBUGFS_EXE; then
+
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+$MKE2FS -F -o Linux -b 4096 -O 64bit,has_journal,metadata_csum -T ext4 $TMPFILE 131072 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT 2>&1
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+bitmaps="$($DUMPE2FS $TMPFILE 2>&1 | grep 'bitmap at' | sed -e 's/^.*Block bitmap at \([0-9]*\) .*Inode bitmap at \([0-9]*\).*$/\1,\2/g' | tr '\n' ',')"
+
+$DUMPE2FS $TMPFILE 2>&1 | grep '^Journal features:' >> $OUT
+
+echo "debugfs write journal" >> $OUT
+echo "jo -c" > $TMPFILE.cmd
+echo "jw -b $bitmaps /dev/zero" >> $TMPFILE.cmd
+echo "jc" >> $TMPFILE.cmd
+echo "jo" >> $TMPFILE.cmd
+echo "jw -r $bitmaps" >> $TMPFILE.cmd
+echo "jc" >> $TMPFILE.cmd
+$DEBUGFS_EXE -w $TMPFILE -f $TMPFILE.cmd 2>> $OUT.new > /dev/null
+sed -f $cmd_dir/filter.sed < $OUT.new >> $OUT
+rm -rf $OUT.new
+
+$DUMPE2FS $TMPFILE 2>&1 | grep '^Journal features:' >> $OUT
+
+test -d "$JOURNAL_DUMP_DIR" -a -w "$JOURNAL_DUMP_DIR" && cp "$TMPFILE" "$JOURNAL_DUMP_DIR/$test_name.img"
+echo "logdump -c" > $TMPFILE.cmd
+$DEBUGFS_EXE $TMPFILE -f $TMPFILE.cmd 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+rm -rf $TMPFILE.cmd
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi
diff --git a/tests/j_short_trans_mcsum_64bit/expect b/tests/j_short_trans_mcsum_64bit/expect
new file mode 100644
index 0000000..d876ff0
--- /dev/null
+++ b/tests/j_short_trans_mcsum_64bit/expect
@@ -0,0 +1,40 @@
+Creating filesystem with 131072 4k blocks and 32768 inodes
+Superblock backups stored on blocks:
+ 32768, 98304
+
+Allocating group tables: done
+Writing inode tables: done
+Creating journal (4096 blocks): done
+Writing superblocks and filesystem accounting information: done
+
+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/32768 files (0.0% non-contiguous), 6353/131072 blocks
+Exit status is 0
+Journal features: (none)
+debugfs write journal
+Journal features: journal_64bit journal_checksum_v3
+debugfs: logdump -c
+Journal starts at block 1, transaction 1
+Found expected sequence 1, type 1 (descriptor block) at block 1
+Found expected sequence 1, type 2 (commit block) at block 10
+No magic number at block 11: end of journal.
+test_filesys: recovering journal
+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
+Block bitmap differences: +(0--65) +(67--69) +(71--584) +(1097--2126) +(65536--69631) +(98304--98368)
+Fix? yes
+
+Inode bitmap differences: +(1--11)
+Fix? yes
+
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 11/32768 files (0.0% non-contiguous), 6353/131072 blocks
+Exit status is 1
diff --git a/tests/j_short_trans_mcsum_64bit/name b/tests/j_short_trans_mcsum_64bit/name
new file mode 100644
index 0000000..4751cc2
--- /dev/null
+++ b/tests/j_short_trans_mcsum_64bit/name
@@ -0,0 +1 @@
+transaction nuking the bitmaps on 64bit,metadata_csum
diff --git a/tests/j_short_trans_mcsum_64bit/script b/tests/j_short_trans_mcsum_64bit/script
new file mode 100644
index 0000000..0534941
--- /dev/null
+++ b/tests/j_short_trans_mcsum_64bit/script
@@ -0,0 +1,65 @@
+if test -x $DEBUGFS_EXE; then
+
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+$MKE2FS -F -o Linux -b 4096 -O 64bit,has_journal,metadata_csum -T ext4 $TMPFILE 131072 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT 2>&1
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+bitmaps="$($DUMPE2FS $TMPFILE 2>&1 | grep 'bitmap at' | sed -e 's/^.*Block bitmap at \([0-9]*\) .*Inode bitmap at \([0-9]*\).*$/\1,\2/g' | tr '\n' ',')"
+
+$DUMPE2FS $TMPFILE 2>&1 | grep '^Journal features:' >> $OUT
+
+echo "debugfs write journal" >> $OUT
+echo "jo -c" > $TMPFILE.cmd
+echo "jw -b $bitmaps /dev/zero" >> $TMPFILE.cmd
+echo "jc" >> $TMPFILE.cmd
+$DEBUGFS_EXE -w $TMPFILE -f $TMPFILE.cmd 2>> $OUT.new > /dev/null
+sed -f $cmd_dir/filter.sed < $OUT.new >> $OUT
+rm -rf $OUT.new
+
+$DUMPE2FS $TMPFILE 2>&1 | grep '^Journal features:' >> $OUT
+
+test -d "$JOURNAL_DUMP_DIR" -a -w "$JOURNAL_DUMP_DIR" && cp "$TMPFILE" "$JOURNAL_DUMP_DIR/$test_name.img"
+echo "logdump -c" > $TMPFILE.cmd
+$DEBUGFS_EXE $TMPFILE -f $TMPFILE.cmd 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+rm -rf $TMPFILE.cmd
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi
diff --git a/tests/j_short_trans_recover_mcsum_64bit/expect b/tests/j_short_trans_recover_mcsum_64bit/expect
new file mode 100644
index 0000000..9cc3309
--- /dev/null
+++ b/tests/j_short_trans_recover_mcsum_64bit/expect
@@ -0,0 +1,42 @@
+Creating filesystem with 131072 4k blocks and 32768 inodes
+Superblock backups stored on blocks:
+ 32768, 98304
+
+Allocating group tables: done
+Writing inode tables: done
+Creating journal (4096 blocks): done
+Writing superblocks and filesystem accounting information: done
+
+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/32768 files (0.0% non-contiguous), 6353/131072 blocks
+Exit status is 0
+Journal features: (none)
+debugfs write journal
+Journal features: journal_incompat_revoke journal_64bit journal_checksum_v3
+debugfs: logdump -c
+Journal starts at block 1, transaction 1
+Found expected sequence 1, type 1 (descriptor block) at block 1
+Found expected sequence 1, type 2 (commit block) at block 11
+Found expected sequence 2, type 5 (revoke table) at block 12
+Found expected sequence 2, type 2 (commit block) at block 13
+No magic number at block 14: end of journal.
+debugfs recover journal
+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
+Block bitmap differences: +(0--65) +(67--69) +(71--584) +(1097--2126) +(65536--69631) +(98304--98368)
+Fix? yes
+
+Inode bitmap differences: +(1--11)
+Fix? yes
+
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 11/32768 files (0.0% non-contiguous), 6353/131072 blocks
+Exit status is 1
diff --git a/tests/j_short_trans_recover_mcsum_64bit/name b/tests/j_short_trans_recover_mcsum_64bit/name
new file mode 100644
index 0000000..7ccdcb0
--- /dev/null
+++ b/tests/j_short_trans_recover_mcsum_64bit/name
@@ -0,0 +1 @@
+uncommitted transaction nuking the bitmaps on 64bit,metadata_csum (debugfs recover)
diff --git a/tests/j_short_trans_recover_mcsum_64bit/script b/tests/j_short_trans_recover_mcsum_64bit/script
new file mode 100644
index 0000000..c283fe2
--- /dev/null
+++ b/tests/j_short_trans_recover_mcsum_64bit/script
@@ -0,0 +1,74 @@
+if test -x $DEBUGFS_EXE; then
+
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+$MKE2FS -F -o Linux -b 4096 -O 64bit,has_journal,metadata_csum -T ext4 $TMPFILE 131072 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT 2>&1
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+bitmaps="$($DUMPE2FS $TMPFILE 2>&1 | grep 'bitmap at' | sed -e 's/^.*Block bitmap at \([0-9]*\) .*Inode bitmap at \([0-9]*\).*$/\1,\2/g' | tr '\n' ',')"
+
+$DUMPE2FS $TMPFILE 2>&1 | grep '^Journal features:' >> $OUT
+
+echo "debugfs write journal" >> $OUT
+echo "jo -c" > $TMPFILE.cmd
+echo "jw -b 333,$bitmaps /dev/zero" >> $TMPFILE.cmd
+echo "jc" >> $TMPFILE.cmd
+echo "jo" >> $TMPFILE.cmd
+echo "jw -r 333" >> $TMPFILE.cmd
+echo "jc" >> $TMPFILE.cmd
+$DEBUGFS_EXE -w $TMPFILE -f $TMPFILE.cmd 2>> $OUT.new > /dev/null
+sed -f $cmd_dir/filter.sed < $OUT.new >> $OUT
+rm -rf $OUT.new
+
+$DUMPE2FS $TMPFILE 2>&1 | grep '^Journal features:' >> $OUT
+
+test -d "$JOURNAL_DUMP_DIR" -a -w "$JOURNAL_DUMP_DIR" && cp "$TMPFILE" "$JOURNAL_DUMP_DIR/$test_name.img"
+echo "logdump -c" > $TMPFILE.cmd
+$DEBUGFS_EXE $TMPFILE -f $TMPFILE.cmd 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+rm -rf $TMPFILE.cmd
+
+echo "debugfs recover journal" >> $OUT
+echo "jr" > $TMPFILE.cmd
+$DEBUGFS_EXE -w $TMPFILE -f $TMPFILE.cmd 2>> $OUT.new > /dev/null
+sed -f $cmd_dir/filter.sed < $OUT.new >> $OUT
+rm -rf $OUT.new
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi
diff --git a/tests/j_short_uncommitted_trans_mcsum_64bit/expect b/tests/j_short_uncommitted_trans_mcsum_64bit/expect
new file mode 100644
index 0000000..3effc94
--- /dev/null
+++ b/tests/j_short_uncommitted_trans_mcsum_64bit/expect
@@ -0,0 +1,28 @@
+Creating filesystem with 131072 4k blocks and 32768 inodes
+Superblock backups stored on blocks:
+ 32768, 98304
+
+Allocating group tables: done
+Writing inode tables: done
+Creating journal (4096 blocks): done
+Writing superblocks and filesystem accounting information: done
+
+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/32768 files (0.0% non-contiguous), 6353/131072 blocks
+Exit status is 0
+Journal features: (none)
+debugfs write journal
+Journal features: journal_64bit journal_checksum_v3
+debugfs: logdump -c
+Journal starts at block 0, transaction 1
+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/32768 files (0.0% non-contiguous), 6353/131072 blocks
+Exit status is 0
diff --git a/tests/j_short_uncommitted_trans_mcsum_64bit/name b/tests/j_short_uncommitted_trans_mcsum_64bit/name
new file mode 100644
index 0000000..9771f4b
--- /dev/null
+++ b/tests/j_short_uncommitted_trans_mcsum_64bit/name
@@ -0,0 +1 @@
+uncommitted transaction nuking the bitmaps on 64bit,metadata_csum
diff --git a/tests/j_short_uncommitted_trans_mcsum_64bit/script b/tests/j_short_uncommitted_trans_mcsum_64bit/script
new file mode 100644
index 0000000..de506be
--- /dev/null
+++ b/tests/j_short_uncommitted_trans_mcsum_64bit/script
@@ -0,0 +1,65 @@
+if test -x $DEBUGFS_EXE; then
+
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+$MKE2FS -F -o Linux -b 4096 -O 64bit,has_journal,metadata_csum -T ext4 $TMPFILE 131072 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT 2>&1
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+bitmaps="$($DUMPE2FS $TMPFILE 2>&1 | grep 'bitmap at' | sed -e 's/^.*Block bitmap at \([0-9]*\) .*Inode bitmap at \([0-9]*\).*$/\1,\2/g' | tr '\n' ',')"
+
+$DUMPE2FS $TMPFILE 2>&1 | grep '^Journal features:' >> $OUT
+
+echo "debugfs write journal" >> $OUT
+echo "jo -c" > $TMPFILE.cmd
+echo "jw -b $bitmaps /dev/zero -c" >> $TMPFILE.cmd
+echo "jc" >> $TMPFILE.cmd
+$DEBUGFS_EXE -w $TMPFILE -f $TMPFILE.cmd 2>> $OUT.new > /dev/null
+sed -f $cmd_dir/filter.sed < $OUT.new >> $OUT
+rm -rf $OUT.new
+
+$DUMPE2FS $TMPFILE 2>&1 | grep '^Journal features:' >> $OUT
+
+test -d "$JOURNAL_DUMP_DIR" -a -w "$JOURNAL_DUMP_DIR" && cp "$TMPFILE" "$JOURNAL_DUMP_DIR/$test_name.img"
+echo "logdump -c" > $TMPFILE.cmd
+$DEBUGFS_EXE $TMPFILE -f $TMPFILE.cmd 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+rm -rf $TMPFILE.cmd
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi


2014-09-08 23:13:21

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 15/25] tests: test writing and recovering 32bit csum_v3 journals

Simple tests for the 32bit journal transaction creation code when
journal and metadata_csum are enabled. We test the following:

(a) writing and replaying transactions with multiple
descriptor blocks
(b) same, but with multiple revoke blocks.

Signed-off-by: Darrick J. Wong <[email protected]>
---
tests/j_long_revoke_trans_mcsum_32bit/expect | 117 +++++++++++++++++++++
tests/j_long_revoke_trans_mcsum_32bit/name | 1
tests/j_long_revoke_trans_mcsum_32bit/script | 67 ++++++++++++
tests/j_long_trans_mcsum_32bit/expect | 146 ++++++++++++++++++++++++++
tests/j_long_trans_mcsum_32bit/name | 1
tests/j_long_trans_mcsum_32bit/script | 63 +++++++++++
6 files changed, 395 insertions(+)
create mode 100644 tests/j_long_revoke_trans_mcsum_32bit/expect
create mode 100644 tests/j_long_revoke_trans_mcsum_32bit/name
create mode 100644 tests/j_long_revoke_trans_mcsum_32bit/script
create mode 100644 tests/j_long_trans_mcsum_32bit/expect
create mode 100644 tests/j_long_trans_mcsum_32bit/name
create mode 100644 tests/j_long_trans_mcsum_32bit/script


diff --git a/tests/j_long_revoke_trans_mcsum_32bit/expect b/tests/j_long_revoke_trans_mcsum_32bit/expect
new file mode 100644
index 0000000..664a301
--- /dev/null
+++ b/tests/j_long_revoke_trans_mcsum_32bit/expect
@@ -0,0 +1,117 @@
+64-bit filesystem support is not enabled. The larger fields afforded by this feature enable full-strength checksumming. Pass -O 64bit to rectify.
+Creating filesystem with 524288 1k blocks and 32768 inodes
+Superblock backups stored on blocks:
+ 8193, 24577, 40961, 57345, 73729, 204801, 221185, 401409
+
+Allocating group tables: done
+Writing inode tables: done
+Creating journal (16384 blocks): done
+Writing superblocks and filesystem accounting information: done
+
+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/32768 files (0.0% non-contiguous), 27050/524288 blocks
+Exit status is 0
+Journal features: (none)
+debugfs write journal
+Journal features: journal_incompat_revoke journal_checksum_v3
+debugfs: logdump -c
+Journal starts at block 1, transaction 1
+Found expected sequence 1, type 1 (descriptor block) at block 1
+Found expected sequence 1, type 1 (descriptor block) at block 64
+Found expected sequence 1, type 1 (descriptor block) at block 127
+Found expected sequence 1, type 1 (descriptor block) at block 190
+Found expected sequence 1, type 1 (descriptor block) at block 253
+Found expected sequence 1, type 1 (descriptor block) at block 316
+Found expected sequence 1, type 1 (descriptor block) at block 379
+Found expected sequence 1, type 1 (descriptor block) at block 442
+Found expected sequence 1, type 1 (descriptor block) at block 505
+Found expected sequence 1, type 1 (descriptor block) at block 568
+Found expected sequence 1, type 1 (descriptor block) at block 631
+Found expected sequence 1, type 1 (descriptor block) at block 694
+Found expected sequence 1, type 1 (descriptor block) at block 757
+Found expected sequence 1, type 1 (descriptor block) at block 820
+Found expected sequence 1, type 1 (descriptor block) at block 883
+Found expected sequence 1, type 1 (descriptor block) at block 946
+Found expected sequence 1, type 1 (descriptor block) at block 1009
+Found expected sequence 1, type 1 (descriptor block) at block 1072
+Found expected sequence 1, type 1 (descriptor block) at block 1135
+Found expected sequence 1, type 1 (descriptor block) at block 1198
+Found expected sequence 1, type 1 (descriptor block) at block 1261
+Found expected sequence 1, type 1 (descriptor block) at block 1324
+Found expected sequence 1, type 1 (descriptor block) at block 1387
+Found expected sequence 1, type 1 (descriptor block) at block 1450
+Found expected sequence 1, type 1 (descriptor block) at block 1513
+Found expected sequence 1, type 1 (descriptor block) at block 1576
+Found expected sequence 1, type 1 (descriptor block) at block 1639
+Found expected sequence 1, type 1 (descriptor block) at block 1702
+Found expected sequence 1, type 1 (descriptor block) at block 1765
+Found expected sequence 1, type 1 (descriptor block) at block 1828
+Found expected sequence 1, type 1 (descriptor block) at block 1891
+Found expected sequence 1, type 1 (descriptor block) at block 1954
+Found expected sequence 1, type 1 (descriptor block) at block 2017
+Found expected sequence 1, type 1 (descriptor block) at block 2080
+Found expected sequence 1, type 1 (descriptor block) at block 2143
+Found expected sequence 1, type 1 (descriptor block) at block 2206
+Found expected sequence 1, type 1 (descriptor block) at block 2269
+Found expected sequence 1, type 1 (descriptor block) at block 2332
+Found expected sequence 1, type 1 (descriptor block) at block 2395
+Found expected sequence 1, type 1 (descriptor block) at block 2458
+Found expected sequence 1, type 1 (descriptor block) at block 2521
+Found expected sequence 1, type 1 (descriptor block) at block 2584
+Found expected sequence 1, type 1 (descriptor block) at block 2647
+Found expected sequence 1, type 1 (descriptor block) at block 2710
+Found expected sequence 1, type 1 (descriptor block) at block 2773
+Found expected sequence 1, type 1 (descriptor block) at block 2836
+Found expected sequence 1, type 1 (descriptor block) at block 2899
+Found expected sequence 1, type 1 (descriptor block) at block 2962
+Found expected sequence 1, type 1 (descriptor block) at block 3025
+Found expected sequence 1, type 1 (descriptor block) at block 3088
+Found expected sequence 1, type 1 (descriptor block) at block 3151
+Found expected sequence 1, type 1 (descriptor block) at block 3214
+Found expected sequence 1, type 1 (descriptor block) at block 3277
+Found expected sequence 1, type 1 (descriptor block) at block 3340
+Found expected sequence 1, type 1 (descriptor block) at block 3403
+Found expected sequence 1, type 1 (descriptor block) at block 3466
+Found expected sequence 1, type 1 (descriptor block) at block 3529
+Found expected sequence 1, type 1 (descriptor block) at block 3592
+Found expected sequence 1, type 1 (descriptor block) at block 3655
+Found expected sequence 1, type 1 (descriptor block) at block 3718
+Found expected sequence 1, type 1 (descriptor block) at block 3781
+Found expected sequence 1, type 1 (descriptor block) at block 3844
+Found expected sequence 1, type 1 (descriptor block) at block 3907
+Found expected sequence 1, type 1 (descriptor block) at block 3970
+Found expected sequence 1, type 1 (descriptor block) at block 4033
+Found expected sequence 1, type 1 (descriptor block) at block 4096
+Found expected sequence 1, type 1 (descriptor block) at block 4159
+Found expected sequence 1, type 2 (commit block) at block 4165
+Found expected sequence 2, type 5 (revoke table) at block 4166
+Found expected sequence 2, type 5 (revoke table) at block 4167
+Found expected sequence 2, type 5 (revoke table) at block 4168
+Found expected sequence 2, type 5 (revoke table) at block 4169
+Found expected sequence 2, type 5 (revoke table) at block 4170
+Found expected sequence 2, type 5 (revoke table) at block 4171
+Found expected sequence 2, type 5 (revoke table) at block 4172
+Found expected sequence 2, type 5 (revoke table) at block 4173
+Found expected sequence 2, type 5 (revoke table) at block 4174
+Found expected sequence 2, type 5 (revoke table) at block 4175
+Found expected sequence 2, type 5 (revoke table) at block 4176
+Found expected sequence 2, type 5 (revoke table) at block 4177
+Found expected sequence 2, type 5 (revoke table) at block 4178
+Found expected sequence 2, type 5 (revoke table) at block 4179
+Found expected sequence 2, type 5 (revoke table) at block 4180
+Found expected sequence 2, type 5 (revoke table) at block 4181
+Found expected sequence 2, type 5 (revoke table) at block 4182
+Found expected sequence 2, type 2 (commit block) at block 4183
+No magic number at block 4184: end of journal.
+test_filesys: recovering journal
+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/32768 files (0.0% non-contiguous), 27050/524288 blocks
+Exit status is 0
diff --git a/tests/j_long_revoke_trans_mcsum_32bit/name b/tests/j_long_revoke_trans_mcsum_32bit/name
new file mode 100644
index 0000000..3d78c07
--- /dev/null
+++ b/tests/j_long_revoke_trans_mcsum_32bit/name
@@ -0,0 +1 @@
+revoked transaction nuking free space on 32bit,metadata_csum
diff --git a/tests/j_long_revoke_trans_mcsum_32bit/script b/tests/j_long_revoke_trans_mcsum_32bit/script
new file mode 100644
index 0000000..4354fe5
--- /dev/null
+++ b/tests/j_long_revoke_trans_mcsum_32bit/script
@@ -0,0 +1,67 @@
+if test -x $DEBUGFS_EXE; then
+
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+$MKE2FS -F -o Linux -b 1024 -O ^64bit,has_journal,metadata_csum -T ext4 $TMPFILE 524288 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT 2>&1
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+$DUMPE2FS $TMPFILE 2>&1 | grep '^Journal features:' >> $OUT
+
+echo "debugfs write journal" >> $OUT
+echo "jo -c" > $TMPFILE.cmd
+echo "jw -b 260-4356 /dev/zero" >> $TMPFILE.cmd
+echo "jc" >> $TMPFILE.cmd
+echo "jo" >> $TMPFILE.cmd
+echo "jw -r 260-4356" >> $TMPFILE.cmd
+echo "jc" >> $TMPFILE.cmd
+#$DEBUGFS_EXE -w $TMPFILE -f $TMPFILE.cmd >> $OUT 2>&1
+$DEBUGFS_EXE -w $TMPFILE -f $TMPFILE.cmd 2>> $OUT.new > /dev/null
+sed -f $cmd_dir/filter.sed < $OUT.new >> $OUT
+rm -rf $OUT.new
+
+$DUMPE2FS $TMPFILE 2>&1 | grep '^Journal features:' >> $OUT
+
+test -d "$JOURNAL_DUMP_DIR" -a -w "$JOURNAL_DUMP_DIR" && cp "$TMPFILE" "$JOURNAL_DUMP_DIR/$test_name.img"
+echo "logdump -c" > $TMPFILE.cmd
+$DEBUGFS_EXE $TMPFILE -f $TMPFILE.cmd 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+rm -rf $TMPFILE.cmd
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi
diff --git a/tests/j_long_trans_mcsum_32bit/expect b/tests/j_long_trans_mcsum_32bit/expect
new file mode 100644
index 0000000..0d141c1
--- /dev/null
+++ b/tests/j_long_trans_mcsum_32bit/expect
@@ -0,0 +1,146 @@
+64-bit filesystem support is not enabled. The larger fields afforded by this feature enable full-strength checksumming. Pass -O 64bit to rectify.
+Creating filesystem with 524288 1k blocks and 32768 inodes
+Superblock backups stored on blocks:
+ 8193, 24577, 40961, 57345, 73729, 204801, 221185, 401409
+
+Allocating group tables: done
+Writing inode tables: done
+Creating journal (16384 blocks): done
+Writing superblocks and filesystem accounting information: done
+
+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/32768 files (0.0% non-contiguous), 27050/524288 blocks
+Exit status is 0
+Journal features: (none)
+debugfs write journal
+Journal features: journal_checksum_v3
+debugfs: logdump -c
+Journal starts at block 1, transaction 1
+Found expected sequence 1, type 1 (descriptor block) at block 1
+Found expected sequence 1, type 1 (descriptor block) at block 64
+Found expected sequence 1, type 1 (descriptor block) at block 127
+Found expected sequence 1, type 1 (descriptor block) at block 190
+Found expected sequence 1, type 1 (descriptor block) at block 253
+Found expected sequence 1, type 1 (descriptor block) at block 316
+Found expected sequence 1, type 1 (descriptor block) at block 379
+Found expected sequence 1, type 1 (descriptor block) at block 442
+Found expected sequence 1, type 1 (descriptor block) at block 505
+Found expected sequence 1, type 1 (descriptor block) at block 568
+Found expected sequence 1, type 1 (descriptor block) at block 631
+Found expected sequence 1, type 1 (descriptor block) at block 694
+Found expected sequence 1, type 1 (descriptor block) at block 757
+Found expected sequence 1, type 1 (descriptor block) at block 820
+Found expected sequence 1, type 1 (descriptor block) at block 883
+Found expected sequence 1, type 1 (descriptor block) at block 946
+Found expected sequence 1, type 1 (descriptor block) at block 1009
+Found expected sequence 1, type 1 (descriptor block) at block 1072
+Found expected sequence 1, type 1 (descriptor block) at block 1135
+Found expected sequence 1, type 1 (descriptor block) at block 1198
+Found expected sequence 1, type 1 (descriptor block) at block 1261
+Found expected sequence 1, type 1 (descriptor block) at block 1324
+Found expected sequence 1, type 1 (descriptor block) at block 1387
+Found expected sequence 1, type 1 (descriptor block) at block 1450
+Found expected sequence 1, type 1 (descriptor block) at block 1513
+Found expected sequence 1, type 1 (descriptor block) at block 1576
+Found expected sequence 1, type 1 (descriptor block) at block 1639
+Found expected sequence 1, type 1 (descriptor block) at block 1702
+Found expected sequence 1, type 1 (descriptor block) at block 1765
+Found expected sequence 1, type 1 (descriptor block) at block 1828
+Found expected sequence 1, type 1 (descriptor block) at block 1891
+Found expected sequence 1, type 1 (descriptor block) at block 1954
+Found expected sequence 1, type 1 (descriptor block) at block 2017
+Found expected sequence 1, type 1 (descriptor block) at block 2080
+Found expected sequence 1, type 1 (descriptor block) at block 2143
+Found expected sequence 1, type 1 (descriptor block) at block 2206
+Found expected sequence 1, type 1 (descriptor block) at block 2269
+Found expected sequence 1, type 1 (descriptor block) at block 2332
+Found expected sequence 1, type 1 (descriptor block) at block 2395
+Found expected sequence 1, type 1 (descriptor block) at block 2458
+Found expected sequence 1, type 1 (descriptor block) at block 2521
+Found expected sequence 1, type 1 (descriptor block) at block 2584
+Found expected sequence 1, type 1 (descriptor block) at block 2647
+Found expected sequence 1, type 1 (descriptor block) at block 2710
+Found expected sequence 1, type 1 (descriptor block) at block 2773
+Found expected sequence 1, type 1 (descriptor block) at block 2836
+Found expected sequence 1, type 1 (descriptor block) at block 2899
+Found expected sequence 1, type 1 (descriptor block) at block 2962
+Found expected sequence 1, type 1 (descriptor block) at block 3025
+Found expected sequence 1, type 1 (descriptor block) at block 3088
+Found expected sequence 1, type 1 (descriptor block) at block 3151
+Found expected sequence 1, type 1 (descriptor block) at block 3214
+Found expected sequence 1, type 1 (descriptor block) at block 3277
+Found expected sequence 1, type 1 (descriptor block) at block 3340
+Found expected sequence 1, type 1 (descriptor block) at block 3403
+Found expected sequence 1, type 1 (descriptor block) at block 3466
+Found expected sequence 1, type 1 (descriptor block) at block 3529
+Found expected sequence 1, type 1 (descriptor block) at block 3592
+Found expected sequence 1, type 1 (descriptor block) at block 3655
+Found expected sequence 1, type 1 (descriptor block) at block 3718
+Found expected sequence 1, type 1 (descriptor block) at block 3781
+Found expected sequence 1, type 1 (descriptor block) at block 3844
+Found expected sequence 1, type 1 (descriptor block) at block 3907
+Found expected sequence 1, type 1 (descriptor block) at block 3970
+Found expected sequence 1, type 1 (descriptor block) at block 4033
+Found expected sequence 1, type 1 (descriptor block) at block 4096
+Found expected sequence 1, type 1 (descriptor block) at block 4159
+Found expected sequence 1, type 2 (commit block) at block 4165
+No magic number at block 4166: end of journal.
+test_filesys: recovering journal
+Superblock has an invalid journal (inode 8).
+Clear? yes
+
+*** ext3 journal has been deleted - filesystem is now ext2 only ***
+
+Resize inode not valid. Recreate? yes
+
+Pass 1: Checking inodes, blocks, and sizes
+Root inode is not a directory. Clear? yes
+
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Root inode not allocated. Allocate? yes
+
+/lost+found not found. Create? yes
+
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+Block bitmap differences: +(1--260) +276 +(292--419) +2342 -(139265--155648)
+Fix? yes
+
+Free blocks count wrong for group #0 (5837, counted=5850).
+Fix? yes
+
+Free blocks count wrong for group #17 (0, counted=8192).
+Fix? yes
+
+Free blocks count wrong for group #18 (0, counted=8192).
+Fix? yes
+
+Free blocks count wrong (497236, counted=513633).
+Fix? yes
+
+Inode bitmap differences: +1 +(3--10)
+Fix? yes
+
+Free inodes count wrong for group #0 (500, counted=501).
+Fix? yes
+
+Directories count wrong for group #0 (3, counted=2).
+Fix? yes
+
+Free inodes count wrong (32756, counted=32757).
+Fix? yes
+
+Recreate journal? yes
+
+Creating journal (16384 blocks): Done.
+
+*** journal has been re-created - filesystem is now ext3 again ***
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 11/32768 files (0.0% non-contiguous), 27039/524288 blocks
+Exit status is 1
diff --git a/tests/j_long_trans_mcsum_32bit/name b/tests/j_long_trans_mcsum_32bit/name
new file mode 100644
index 0000000..ac43f51
--- /dev/null
+++ b/tests/j_long_trans_mcsum_32bit/name
@@ -0,0 +1 @@
+transaction nuking free space on 32bit,metadata_csum
diff --git a/tests/j_long_trans_mcsum_32bit/script b/tests/j_long_trans_mcsum_32bit/script
new file mode 100644
index 0000000..3255001
--- /dev/null
+++ b/tests/j_long_trans_mcsum_32bit/script
@@ -0,0 +1,63 @@
+if test -x $DEBUGFS_EXE; then
+
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+$MKE2FS -F -o Linux -b 1024 -O ^64bit,has_journal,metadata_csum -T ext4 $TMPFILE 524288 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT 2>&1
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+$DUMPE2FS $TMPFILE 2>&1 | grep '^Journal features:' >> $OUT
+
+echo "debugfs write journal" >> $OUT
+echo "jo -c" > $TMPFILE.cmd
+echo "jw -b 260-4356 /dev/zero" >> $TMPFILE.cmd
+echo "jc" >> $TMPFILE.cmd
+$DEBUGFS_EXE -w $TMPFILE -f $TMPFILE.cmd 2>> $OUT.new > /dev/null
+sed -f $cmd_dir/filter.sed < $OUT.new >> $OUT
+rm -rf $OUT.new
+
+$DUMPE2FS $TMPFILE 2>&1 | grep '^Journal features:' >> $OUT
+
+test -d "$JOURNAL_DUMP_DIR" -a -w "$JOURNAL_DUMP_DIR" && cp "$TMPFILE" "$JOURNAL_DUMP_DIR/$test_name.img"
+echo "logdump -c" > $TMPFILE.cmd
+$DEBUGFS_EXE $TMPFILE -f $TMPFILE.cmd 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+rm -rf $TMPFILE.cmd
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi


2014-09-08 23:13:27

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 16/25] tests: write and replay blocks with the old journal checksum

Test that we can write and replay transactions with the old journal
checksum algorithm.

Signed-off-by: Darrick J. Wong <[email protected]>
---
tests/j_short_trans_old_csum/expect | 40 ++++++++++++++++++++++
tests/j_short_trans_old_csum/name | 1 +
tests/j_short_trans_old_csum/script | 65 +++++++++++++++++++++++++++++++++++
3 files changed, 106 insertions(+)
create mode 100644 tests/j_short_trans_old_csum/expect
create mode 100644 tests/j_short_trans_old_csum/name
create mode 100644 tests/j_short_trans_old_csum/script


diff --git a/tests/j_short_trans_old_csum/expect b/tests/j_short_trans_old_csum/expect
new file mode 100644
index 0000000..29ac27f
--- /dev/null
+++ b/tests/j_short_trans_old_csum/expect
@@ -0,0 +1,40 @@
+Creating filesystem with 65536 4k blocks and 16384 inodes
+Superblock backups stored on blocks:
+ 32768
+
+Allocating group tables: done
+Writing inode tables: done
+Creating journal (4096 blocks): done
+Writing superblocks and filesystem accounting information: done
+
+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/16384 files (0.0% non-contiguous), 5164/65536 blocks
+Exit status is 0
+Journal features: (none)
+debugfs write journal
+Journal features: journal_checksum
+debugfs: logdump -c
+Journal starts at block 1, transaction 1
+Found expected sequence 1, type 1 (descriptor block) at block 1
+Found expected sequence 1, type 2 (commit block) at block 6
+No magic number at block 7: end of journal.
+test_filesys: recovering journal
+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
+Block bitmap differences: +(0--1050) +(32768--36880)
+Fix? yes
+
+Inode bitmap differences: +(1--11)
+Fix? yes
+
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 11/16384 files (0.0% non-contiguous), 5164/65536 blocks
+Exit status is 1
diff --git a/tests/j_short_trans_old_csum/name b/tests/j_short_trans_old_csum/name
new file mode 100644
index 0000000..2e81f94
--- /dev/null
+++ b/tests/j_short_trans_old_csum/name
@@ -0,0 +1 @@
+transaction nuking the bitmaps with old journal checksum (v1)
diff --git a/tests/j_short_trans_old_csum/script b/tests/j_short_trans_old_csum/script
new file mode 100644
index 0000000..b968bc1
--- /dev/null
+++ b/tests/j_short_trans_old_csum/script
@@ -0,0 +1,65 @@
+if test -x $DEBUGFS_EXE; then
+
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+$MKE2FS -F -o Linux -b 4096 -O has_journal -T ext4 $TMPFILE 65536 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT 2>&1
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+bitmaps="$($DUMPE2FS $TMPFILE 2>&1 | grep 'bitmap at' | sed -e 's/^.*Block bitmap at \([0-9]*\) .*Inode bitmap at \([0-9]*\).*$/\1,\2/g' | tr '\n' ',')"
+
+$DUMPE2FS $TMPFILE 2>&1 | grep '^Journal features:' >> $OUT
+
+echo "debugfs write journal" >> $OUT
+echo "jo -c" > $TMPFILE.cmd
+echo "jw -b $bitmaps /dev/zero" >> $TMPFILE.cmd
+echo "jc" >> $TMPFILE.cmd
+$DEBUGFS_EXE -w $TMPFILE -f $TMPFILE.cmd 2>> $OUT.new > /dev/null
+sed -f $cmd_dir/filter.sed < $OUT.new >> $OUT
+rm -rf $OUT.new
+
+$DUMPE2FS $TMPFILE 2>&1 | grep '^Journal features:' >> $OUT
+
+test -d "$JOURNAL_DUMP_DIR" -a -w "$JOURNAL_DUMP_DIR" && cp "$TMPFILE" "$JOURNAL_DUMP_DIR/$test_name.img"
+echo "logdump -c" > $TMPFILE.cmd
+$DEBUGFS_EXE $TMPFILE -f $TMPFILE.cmd 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+rm -rf $TMPFILE.cmd
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi


2014-09-08 23:13:33

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 17/25] tests: test recovery of 32 and 64-bit journals with checksum v2

Add tests to ensure that we know how to recover journals with the
csum_v2 feature set.

Signed-off-by: Darrick J. Wong <[email protected]>
---
tests/j_recover_csum2_32bit/expect.1 | 16 ++++++++++++++++
tests/j_recover_csum2_32bit/expect.2 | 7 +++++++
tests/j_recover_csum2_32bit/image.bz2 | Bin
tests/j_recover_csum2_32bit/name | 1 +
tests/j_recover_csum2_32bit/script | 31 +++++++++++++++++++++++++++++++
tests/j_recover_csum2_64bit/expect.1 | 16 ++++++++++++++++
tests/j_recover_csum2_64bit/expect.2 | 7 +++++++
tests/j_recover_csum2_64bit/image.bz2 | Bin
tests/j_recover_csum2_64bit/name | 1 +
tests/j_recover_csum2_64bit/script | 31 +++++++++++++++++++++++++++++++
10 files changed, 110 insertions(+)
create mode 100644 tests/j_recover_csum2_32bit/expect.1
create mode 100644 tests/j_recover_csum2_32bit/expect.2
create mode 100644 tests/j_recover_csum2_32bit/image.bz2
create mode 100644 tests/j_recover_csum2_32bit/name
create mode 100755 tests/j_recover_csum2_32bit/script
create mode 100644 tests/j_recover_csum2_64bit/expect.1
create mode 100644 tests/j_recover_csum2_64bit/expect.2
create mode 100644 tests/j_recover_csum2_64bit/image.bz2
create mode 100644 tests/j_recover_csum2_64bit/name
create mode 100755 tests/j_recover_csum2_64bit/script


diff --git a/tests/j_recover_csum2_32bit/expect.1 b/tests/j_recover_csum2_32bit/expect.1
new file mode 100644
index 0000000..491784a
--- /dev/null
+++ b/tests/j_recover_csum2_32bit/expect.1
@@ -0,0 +1,16 @@
+test_filesys: recovering journal
+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
+Block bitmap differences: +(1--259) +265 +(274--275) +281 +(290--418) +(1059--1186) +(2211--2352)
+Fix? yes
+
+Inode bitmap differences: +(1--11)
+Fix? yes
+
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 11/8192 files (0.0% non-contiguous), 7739/131072 blocks
+Exit status is 0
diff --git a/tests/j_recover_csum2_32bit/expect.2 b/tests/j_recover_csum2_32bit/expect.2
new file mode 100644
index 0000000..d223026
--- /dev/null
+++ b/tests/j_recover_csum2_32bit/expect.2
@@ -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), 7739/131072 blocks
+Exit status is 0
diff --git a/tests/j_recover_csum2_32bit/image.bz2 b/tests/j_recover_csum2_32bit/image.bz2
new file mode 100644
index 0000000000000000000000000000000000000000..2212edd9ab3c825914a98a21deb10007d5c035d9
GIT binary patch
literal 3371
zcmbtXdpwj|_upeQBPB)1xa8ENsG&4OE-B4q7`e=hdm8t9xh6UoVTv)BAu^l@gXA_5
zZ*E6N?vvY4q9TryB1a*i@;*-Q`<~D5_s{#syFQ<1ueH8w@BOUx?6vn^&l!6!onxo%
zlu34x;fZrVD0$<*(!`Ejcy3_Blo9~j0jwENMU<2bV_<`BEdYSiF?#@lwqJ59Z5NBS
zYX-mxG+=}!0w7S@8jCN^6MjlGD{;;PU@NVpBoDz+EQ&STo+XQ*Avjt^TjL^<1VbEI
zu&e?0(7cvVNpudfWP1_^!4y+0*!iUY7{GSQVmrGEhDK>F&KuuL??F##-YuN@sbTUd
zG5}gdN{R*eZupSDp&00oDuFx#aKp{^--PXlBp>6AWfLy;-`Ee1`oAgw2$Q1_1lw$Y
zBoL+|XaJ_+)}s7(KgcF2ED*}K+R4O{hV@Ze`4PGAMecB7hmPXU6%bOruqZb%_)sUT
z$ZKc+DD${+M2ctxO$;c;pip8ODDTuIT2zUPtUli833I#PxN44W(bw?rf+zdk{8#4n
zrsQ3-=&haEMps)KcWGsN@R^>s$G@rPuS(j!4f~bWd+j*0p>nQQS9h=3i+9Rgv>5wv
z$3|V<%E^3VJ(!i!x?({Znr)_Tv>$!*s*mw6QcBTM31~E1?ioSC_~v_6f{=tinSJ)`
z{sU883bIeAGv+l%vzv{?zB5FAIgobCC4{V`(7@5?NsZ0!l@~_;eDJ7biA{=Ua7X2S
z!HcEuw6*Prj>1%thBNYTr5U9&no>&iXsx*GcLxsDcwA30E*!iw_`0?6MiI$-Xe}Pk
z-9?Jh5ZQvGxQE84R!QN79%CY{p9|U8G>?aVMo24b;jKLaQ-QrUls^6#GwPU}L-u36
zro;Np1{w9go@%*DrRKf)$vMWT^(;JL6$fV|F_TkL)maNW2!v!B>`=#HjQX+Ti))b{
zMZcXt|LwZDdB4Sg<)D=SMH(UxQ=VDJR8(%G?$M^!YMq|@fblP%H&{7g6PB5;Uiswv
z7OIF;Z2XM`1~Y}V+SM(cs=l0=mA&38`}O-q^%6FOE+&vGL6Td}*Z$+9jLh4mkS2r5
zi@ZD_?rZR8bnE0aT|BdI<_%rEa%_I$YgF|4J%EiiPIjMPZInMXAC|y-Hz&7|IW!Y?
zZ2Y6x6@m>(=<96{vri!nI8($qbZIG<%e`J$^U%J6U0OLh5OV!n9&C1)LcXn{#x5-Z
z_Coz&3xPtR9H3Ch5(FgzItI-aW*cvcI>bD}0V$WMRTP5bU6i&R%{F8cgdli3{D>5V
zqH1z~*{0N_wDcZ2lR{AfKrQv+X7)<|Na1}mP8VR%q(Deb=CKk0h7kN6@+S}C+YE)w
zJ%v6a5C}-wBw+xY)B#YJsd}LbdG$95!@`4Rw)8jF{|)^m32n9_fLh3=P%QqR?JpI+
zz%DJNL82kpBk`X;B4973T(uH%TBrrc$YcTlZ98B4o<cTmkg)F^niX1(c2uVUb_+mP
zfo%XdJ_>q=&UnZz$9Q`I_*VUa+AAHqUvAPytW#6OH|MGqPf7ID5kdp0Ij7(s+T24{
zRz7L&%+iELx2&xQGX0H}(!-A7CxZm!GC7VJZ_G?*`Nc5^I~wy6s_schoW1#b`fHW(
z>_WC_=;yV9V53C;?BW1_h2JN%#ifJJ!-E3k5i2KsCbW0JIl*F!^|}QU$(DTq@<>=q
z2=eUZT#*0;=ZS`K^Mla~o_pVI6WkJ)v$Z>D=+rx(fzF-PZ~xe)J=#0kN58kgopO|u
zL!m@fCcM*YFnVrDue9k;E9$Dgq>QYl<W4HTaLY0JLYz$h+FE3ABJF-r;h0wPxqN-6
zXMOS{=bCWWGs+EPcKZTe(OdO&uGr~&huQqxAXd<UGV)2r|0-9EU618rwJNWvyxDQX
zn!ebUX<6(VJ@X<PmmSs~uA*RLR{FCn{#9}n-`kVy&Fb6Tv-iO6Zvvv8dP3F<&I26}
zH%xqG;*l(Kgl%`AsjTJYlXh>_3sp*g8;ZVLCNK`{)?kmUPO9AUa_fp!e>{SRX`oDh
zk`H)%2tmEmOpi(G%&ik0yPWM`J1O@Xd*T<dQ*^->F@qb|`^Q4+NtfXkuUZ5r^glco
zHxWb>3?g!nK=CS4@-b}^3?m<{B+DD@k-v$m+Xu8a5|&!$f*qTyBB|>gS~?_-`~*-C
z`F3IN>3*8{ADXX>_r9wLJ!k*^RhYxGlO0rMRCD{WBxw8mFJx^yuQQz-9D9Sv*ChWz
zG9td8UGAx~@Zqi79C48Dcz9eZ(LJ8$XFq#CuHLq0de+06qmp4h&A-ObXe-tUYO6G{
zA%yV!!aUsULl1r6_cjjaJ8ZM`Taq{o4R6{Kon>$PXYL7(<ty169T)c(;dp-EtoYS!
z*0!~nw<;OBUAJd@lx^#1)eAjbPIr%V8_#<p-`*<gHbZC8l5=l8UL8BEjL*@Wo8Poe
z@mqTwt6QvX>*9(ormAFM7_J2`f4{0w{^4^wP!xvM(%;m=JAqiI+)ZQ-iWY8xN;wZ*
zlVjo@fku>jz-O5X?a4?R=$>1z2ms=I_)5s>ftaD#b<O$-Fxz^uke4Ygjvg+>c-f`T
zsgY|jL32IQ`6IO$hJ9IgxX^THgNNDS2Vea{Ps~0Imu{;LD68n^H^oQc-kFZhws$YP
zzZ_=yg(5ry?Aq#~02jC#y_77Mfy+x$8^c`vgBNc2K0khe;WDz&?&hG)b%&%{%$Kg+
zUl)mA*4&eS<}+Lb@717ze;F7q&(8#XGE;R>?9osQch&pU9zLD4*aHylh<>n891SkT
zOthziF&Yv&N#On3GUXAhxjO|T;$ClBwCT_}hExPWROG;P3v|`58P324cd!H}0}wT*
zCXi0L((HD8%DD_3rZnS-dy?lJjXpiz9q286&QS-625Zv{mvQHPPuICA2X1GyRp3@^
z#xn0~PF=0uOp1!*`$lRF+#q*HYJ)_J+#H~#x%{9yEu?73@z*dS&kq8speS5F^E)AC
z-dI-tpm$Cn@k%smml-rc-;FY!Z~5j_YaI7sBF}e)p}~FRs`oMJ+T4=e)DbAw7C*@U
zDA*fly)H$Oh_J?0>L+Cy><>uSRxU*H0vgo{weuhih*4pDh(%Qa<fmv0UqjdkoZxDg
z<e4OQ<ygVoBj}U0uOxY9B<A)7<$SxQ%Vl^fuF=*<(=<ukGM-=LGtYDA^d6;JV}kDh
z=}1JH24<UM5TEz5>o$tngiU@qza7i-%V^`x6FZ?k5@=j;glPsQ?%@k*@Ag*8pz3JO
z{dl(9;Mi#NYNBYD28aLRs>D@z-1?7Vv-d97gJtjH9^YM$KWYI7Py7hicPR>|CB%pJ
z0;vfon9UHN<@+h`FAl(tfALPQe+h8f4?*KURh+8Hu6t?5LyyIwsuPuRcGQchc=v7|
z+|c`O-oSh86SvVjoIAxu!^b~#R_IQ3MSf&5O{JY2m$N!EoXSK)hP+qxRYw9IoUfmf
zl00oSdgiDFOKEGirNmA|xiD*=$@`JM-e%rsKc0-XX?dvBClyQ~evRDH?=-3HOCGP0
zX|GS3#(yt7%SN*lwwQ5^2gvv{EENeB-6Fq)vgIe7)$Z(Rf)Dqu8IB=L*hknEjC!^j
z&uYJ@n0Rwam88Qeow#>~ohD2)c}hMViOx!7AB3~0&Q|BBO>QhS3w^WCGUu+Zez1P4
zYdG<_Y*$cD?ZIPD1LZTa`+RghNZ-#N^gStNgDd-8=aNI=y9Tqmgz-z*HZ4EBQL_U?
z6M}yGiM(3uV7etC%c$IR#QwGJXqjy})3kaoNfN#oY`sTDmpROELI@qWZ>MQv-c;V|
z_nLpjrd>U9!dopzDqQF3l?I$|Xx!jJZ4OR=Gox46*VPn@=E6vtL?1PqaKZ}4wzKdx
zPVf9R)#vv!I$&1#*iW`{Dus{yCadcmke9dgUHJOTqtE;uVJlzC!=l0hJ+8G-qi&6O
z-&Po_OC)s<P#p^b-=8p7v_=dsejc0El-oAOZ-PrNK5*B=^*&0N3L9N4`E9J^)c9fy
z!@;FldKT{A*!VCdw%Ro?=23Uxhf7sulNo#7lDoU#UOu=tHJA9*|47(t>5xBlGEQ%P
zzwV+3xj#~|cdh@Sh3L6?VW`mA3H`tT7@cZHA{vsp5S-q4p=<Y>Gls!8|JeCY<|obb

literal 0
HcmV?d00001

diff --git a/tests/j_recover_csum2_32bit/name b/tests/j_recover_csum2_32bit/name
new file mode 100644
index 0000000..6fd378c
--- /dev/null
+++ b/tests/j_recover_csum2_32bit/name
@@ -0,0 +1 @@
+recover 32-bit journal checksum v2
diff --git a/tests/j_recover_csum2_32bit/script b/tests/j_recover_csum2_32bit/script
new file mode 100755
index 0000000..4b0ec48
--- /dev/null
+++ b/tests/j_recover_csum2_32bit/script
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+FSCK_OPT=-fy
+IMAGE=$test_dir/image.bz2
+
+bzip2 -d < $IMAGE > $TMPFILE
+
+# Run fsck to fix things?
+EXP1=$test_dir/expect.1
+OUT1=$test_name.1.log
+rm -rf $test_name.failed $test_name.ok
+
+$FSCK $FSCK_OPT -N test_filesys $TMPFILE 2>&1 | head -n 1000 | tail -n +2 > $OUT1
+echo "Exit status is $?" >> $OUT1
+
+# Run a second time
+EXP2=$test_dir/expect.2
+OUT2=$test_name.2.log
+
+$FSCK $FSCK_OPT -N test_filesys $TMPFILE 2>&1 | head -n 1000 | tail -n +2 > $OUT2
+echo "Exit status is $?" >> $OUT2
+
+# Figure out what happened
+if cmp -s $EXP1 $OUT1 && cmp -s $EXP2 $OUT2; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff -u $EXP1 $OUT1 >> $test_name.failed
+ diff -u $EXP2 $OUT2 >> $test_name.failed
+fi
diff --git a/tests/j_recover_csum2_64bit/expect.1 b/tests/j_recover_csum2_64bit/expect.1
new file mode 100644
index 0000000..491784a
--- /dev/null
+++ b/tests/j_recover_csum2_64bit/expect.1
@@ -0,0 +1,16 @@
+test_filesys: recovering journal
+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
+Block bitmap differences: +(1--259) +265 +(274--275) +281 +(290--418) +(1059--1186) +(2211--2352)
+Fix? yes
+
+Inode bitmap differences: +(1--11)
+Fix? yes
+
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 11/8192 files (0.0% non-contiguous), 7739/131072 blocks
+Exit status is 0
diff --git a/tests/j_recover_csum2_64bit/expect.2 b/tests/j_recover_csum2_64bit/expect.2
new file mode 100644
index 0000000..d223026
--- /dev/null
+++ b/tests/j_recover_csum2_64bit/expect.2
@@ -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), 7739/131072 blocks
+Exit status is 0
diff --git a/tests/j_recover_csum2_64bit/image.bz2 b/tests/j_recover_csum2_64bit/image.bz2
new file mode 100644
index 0000000000000000000000000000000000000000..acf1daed92e6805adee12a099ebff4dd22507a83
GIT binary patch
literal 3486
zcmbtWdpwi<`~S?CoE4!Vr&;OQ97aTsj3~>gtQB)8+F}klRYTDvIyl58Hm3-~Qcpvn
z1CuO=NT%h`VUkB8Dx^HcZ=Rmt_x1Zd|NQ>=U4MM8>w4eUec#vny06cDeH@6v)@JtJ
zNWAx2`GgiA!9BC`e~CzO#YSbuYDXXdfCn^1Fo=YNq~sdKWXC`fg~n6?lDu?)bOmB9
z0Y8ETGWAGOx`hne0`x(#K*bfvXIL;*ATS{1w$B+xTY!`R7&dr=1rQ9_?FY747zF^*
zMuvShJ2eBq>`R~?&XAJM5=sf|d==b6hob<8+wNRhA>daQ2n0zEvT~V|{Q&@5WIu$R
zJP;fh42Qa2<%pB}w^+dJ*)*spZe^)rPuar1ul~!&u$imK--`@QB3_(2kYOMprhmsF
z|6Z9u<}4*?pOJ;L3cl~cf-UU1?WReY?D|dR3gwg!@ow_=lNbw<#k?C_0c?OUJRB_9
zD#3kv?9^Quu;MZ|$OVjiI<}9r04ct<0iK9ku5hQSzAKJwIU_h_aV%3k;v>F(tT4L3
zLq5SIYTM4Nu&p-hHbGM<+0`xgW0v3W;FoC$YX^%O+O&8LlGxaXZ<V0_ib;dihpOf!
zv-#`11;#qsn|TRA$Ci(+lozOGS$0g@g+Bc#bW9$*<fs!~i9^ucOsLsexaXcbE3fV5
z*6Px6TA|8W7iNSGdV2RX*5QElq`|dqVHXy5uV_S_c31o;7*(mNJ$^tVw!`M^*(7pa
z2~~Pc-#$cu?02U!+ho;vCnP-n^UM|JNO^hB$($i3o~`>{`y5Zlz9d1ycD?@jD!ZpT
zrJ}d`z9~+P`B&Vlv7D#R30H(_2XbGiAI#%7W4HWFGBxGGz#4K!c8;d`_MI+xFLPZG
z7Je)wA`%XyUZ`(s;CcMf^T#J;Q*4f?)gjJbFQAn7$g$mtzw1X?(&G;2AMeT^O64pi
zkoQ!a-);D(G!4kNn{TzU-u_i~-Kp6f@U!P^*J~SU#1li}FK>0*d+Bc1@VM-!w<uIt
z&7)!Bh|f#kSAMVkFE+RES|7Ik2uzHM`XiFtnn@y!lan4j>FIsi_iT5+D$2jOr1k8=
zuBpV-sY~<m3I2`2)j<YBAA=W9E$eJ7^bP7lcL3?0tCd2l>G?Lv<J4Dd4ZF21#X(l}
zBYJDH^>?g~q0Ua6;dT`GT{({|&Mk^)O}9R<leqPTLe7Z$!JzN{R)LmbLv<DKshf9i
zpi%1$D>%;yNrrx*PW|$7Sg4T0sn!K@SRw!`{Rld?10hn;Wnt+!2^>NOktIgNW+a^=
zf!p%xq)N#<WmD7f?mQD*>N=b*4v~Z?W<Wu=1Wr%F4KXS~Ab8@8IUI3|`|0vlTU%{)
z0YKfUI}b}B5CBL^{e=J^;c;;BLE_K9L;%$P2LpfxfWJvVG=Z=e9HMhLV)q}RnHc*)
z<eo)~{u}s5W5pT*lvWV`EBZe{SpXz_+0R+s#}M#8ABlyI-L4=^5(rpvl8yHpfg}KO
zM4=yoZcN9i;}B^#DEgx`AmIW4ohQCqOu;yp-cKa<3v+3}q;tMA8M$_o0I4VzrGe0!
zcb5c|S$AU`-;0rfFWaFzo~e5+r#y@i?j}Txv5*M5Z7JzofB7~t!r*r3qdt{z=ZiNk
zpq&{MQnrc_BBhGq*(sy%c;TJunCknN4miWRU%u{^mKSY1j~YIXoQr#tX@7sz?a#T4
z5ru-DKj%iZOZ&Cjm{e$)4f@Zyxcl#lj5@6fdK+i$l-`iWsb!gqj}y$a{RUo=7y$vF
z4Hv8~dC?P&FEz)GYN0(UZ+<wGUMHs-RkyfkwF6J7$>C6m7<#+W^N#zU+pQu``lsC-
z|FO~^*(<AsSsJ@=c(S*$L{M4&GJM-lqXvH_n=QaQAnS3x_Y_<Q?!F<AME<Y+_+wG!
zR^E1!V=VqeB&Cr(rRhGxKEHM#FQBsVUPj}w2Oi!A?4_TKs9jSUM{RHC!$|?IbrYd2
zPL`TxZNF7fPvz&o3t%ofF;FgkVQGkNxub6v9r(FtF8Wc9?1_E5gvs~v*+}E&ZUp5F
zBlKS%Vm&uga%DB#?0FU)!6F=EFX(Ww&wKGzbg1~<fSO1%d@TIV>$w{*Puz)r)$K!l
zy}h`>UnqRta7#KRqAZwN+Va^T1lpoK|7rBL=3XVc_r3C#JZWXf)YAh1ngPaavuBhT
za|My7Z$(3=ny}J{gwb!<@ym~_lOuJq|I&H7xZD?G@LgxJr(t_>n8~-WFfYE@CC>j(
z1lsCmeX|o3R%+K7DOdJzveA$be^(vlqt<?_eoh@loLWjo=AyUx3x>yBhw_bb-H{}p
zt`*<qG)w>R8FIeY=Twr9+G9BkI?ZE`FFVEEm}OJT_PQf>BmISbsFP2n@>jjU*Ntqi
z`j0QT7M<@ye|w@vzFcRnxFNc|?nPd$QCy|IYlhW}+7^6kHsy_6UX&}BGT>NWVQ!{&
zdf#y_rFOh1BTifViogktLB4r)ky+tn`h;tc%@J$<jzqIOy9vdzKJh&790m&0n&u7D
zJZe@%X$_#_g8}#=+DL9yR8Q4X)-ru7-jUN<hn3C(OA*+?)FDB0L9}R`-`sdctpx*g
z<}ED`nDWijZ=Z;|%<<)h4IZ*4dNp{m{9ixehM?1e+`I#Y-AJ#7nTSJ2uMEbc@(+38
zQD4dALa8aainzaaz*vKL)X>pY!m$J0YVFlwM6^qM|B`!)!OMl|5zoOp==ZYZv>@G@
z%2Q1qSxte$5lnmK&pecm?fj+gjUyPejl_7G$C|jB{-S{B-ZAgMq37#!)q3eq?i0yr
zXWrKwYvkW#GkcHoW7t5EeXRGw5P*FG(}$-Y)WhZhtWW&Y_`R)52{jT|dMA>m^;_~h
z(Ap~ob>x8-4brK_1kxgfwz*{*2&F-PCX*=*eDl(~A!C}&W<{=J8!I(>nS8Tc^t&8!
z^4ze*<|9)s7_lM#!l)-{XLhgx1=A*R0)0W(Asx08H}q95IW163DlJg(SZg_6n;G*t
z`g;iZ_es~A0jpIA*}u3@k(OZQS~p8Nuv!(5z*Y6TESi023trr0MKfRH17=-v(J?MR
zZue_qV%o`R?$*)MMpwGnsVud-iBar)mcVtw6*l!0I~gDxX*dW@hzTjo-KI$=DJesE
zKsp`TmBjl*gFf3987bOUVtYL;>Tpzvm^84)f<!+a<cXb^LL@k5Uwg+aeKM8(Jw0TG
zC4e{b*=&o|N~T8{vZ$)vYFDc^vdj57!@k^zNV<#7wMmj%2V!;{bH5^;y96T<)ryRw
zAGb10(Y9s@qhHvXC}KiWbUQc12jPHlzAWeMF3dCPT4<^`S6?wSeye|SeYkt(D2Zip
zXGML5SyIC=swvK-W&*?3U+2`H2>5Hg1{4Cl&PHB8$vnn*AJ)0aL9e&vn46;rk|-ts
zuX<*|+r`W<RoTVTNKck9MIu?ING3!>`JrjDiiCoh=_<)zA{n3|HtgBIPItesbOW)5
zc<#->cgSGiho4!pi}4|W@yrafa;R&vZm_(4)}!DK!K30zcA1qS@A%6n)_G4-9dc1`
zYE@*vO4Zc6)UA)t4}oruL?~!CEAFCwvs6$1+_gESRkzXRan^9{+N{F#5|)F{{AGI=
z4x(^r4OTJ35kW^}(yt-1pq^#PEzR7YC%r7E!p;YbdHLWBjQ1x)&pnOWpdfWa|2u|&
zJY-KwLg4hRy9%~2(yJI7oO3QZH<w>4uka+uI+i-`+n=J(CqC>evkv4TE+U*Td8Qav
zxZ&p>Pq-l&LrfKkr=1^cD|w4@%Ox(%&|b4>`#S$pll}B{j&uXFU7o2S!qCpZ@WG)T
zEA~4xYh!#@(1YEag+k%??hy0BMe8a-%uCoQ+o=cVjmARmDw@Z&9Y}Tx@nuihUk~ls
zPc}l#Vg`lvggu`7a7HfE0f%E_W=z^h!Q&r`4j`ea<xQc-U)K<CN3CnGp&GN&<>m5r
zpU6n)W?%7r+aNF1t{viSuF6e$=ym!!a}p{2h5I}db#-LU>*PT6euZ*8Z6(*DX?V&f
z1*iB2ul8uskE`>`+UT^Uxu)T`%)%D|Cq^bd_>3Ibl#o<dR0h=@s~#F08aAz-{^YM%
zR^Oe_MdE6A&D=}r3Ho?F^}07v`t%aK;AO;#TSKu(tAR!BWag(^(isOod@Cq)uT%dP
z;dLwgcDFBIDub$b<k5*Ya>pM`yd@4+?v~`<!$0_ZGSV+XCH8$`!cssyZeYmLMbmxC
zd;Ctpo&IbYecaj=)$!_odN`%INjwf&CD_9NC<94lpm9_pN3i*te%StfYk&9aR2_A|
JK7Sr6`Y+b~7ncA4

literal 0
HcmV?d00001

diff --git a/tests/j_recover_csum2_64bit/name b/tests/j_recover_csum2_64bit/name
new file mode 100644
index 0000000..1770502
--- /dev/null
+++ b/tests/j_recover_csum2_64bit/name
@@ -0,0 +1 @@
+recover 64-bit journal checksum v2
diff --git a/tests/j_recover_csum2_64bit/script b/tests/j_recover_csum2_64bit/script
new file mode 100755
index 0000000..4b0ec48
--- /dev/null
+++ b/tests/j_recover_csum2_64bit/script
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+FSCK_OPT=-fy
+IMAGE=$test_dir/image.bz2
+
+bzip2 -d < $IMAGE > $TMPFILE
+
+# Run fsck to fix things?
+EXP1=$test_dir/expect.1
+OUT1=$test_name.1.log
+rm -rf $test_name.failed $test_name.ok
+
+$FSCK $FSCK_OPT -N test_filesys $TMPFILE 2>&1 | head -n 1000 | tail -n +2 > $OUT1
+echo "Exit status is $?" >> $OUT1
+
+# Run a second time
+EXP2=$test_dir/expect.2
+OUT2=$test_name.2.log
+
+$FSCK $FSCK_OPT -N test_filesys $TMPFILE 2>&1 | head -n 1000 | tail -n +2 > $OUT2
+echo "Exit status is $?" >> $OUT2
+
+# Figure out what happened
+if cmp -s $EXP1 $OUT1 && cmp -s $EXP2 $OUT2; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff -u $EXP1 $OUT1 >> $test_name.failed
+ diff -u $EXP2 $OUT2 >> $test_name.failed
+fi


2014-09-08 23:13:40

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 18/25] tests: test how e2fsck recovers from corrupt journal superblocks

Test e2fsck' ability to deal with corrupt journal superblock checksum
and a bad magic.

Signed-off-by: Darrick J. Wong <[email protected]>
---
tests/j_corrupt_sb_csum/expect | 21 +++++++++++++++
tests/j_corrupt_sb_csum/image.gz | Bin
tests/j_corrupt_sb_csum/name | 1 +
tests/j_corrupt_sb_csum/script | 51 +++++++++++++++++++++++++++++++++++++
tests/j_corrupt_sb_magic/expect | 42 ++++++++++++++++++++++++++++++
tests/j_corrupt_sb_magic/image.gz | Bin
tests/j_corrupt_sb_magic/name | 1 +
tests/j_corrupt_sb_magic/script | 51 +++++++++++++++++++++++++++++++++++++
8 files changed, 167 insertions(+)
create mode 100644 tests/j_corrupt_sb_csum/expect
create mode 100644 tests/j_corrupt_sb_csum/image.gz
create mode 100644 tests/j_corrupt_sb_csum/name
create mode 100644 tests/j_corrupt_sb_csum/script
create mode 100644 tests/j_corrupt_sb_magic/expect
create mode 100644 tests/j_corrupt_sb_magic/image.gz
create mode 100644 tests/j_corrupt_sb_magic/name
create mode 100644 tests/j_corrupt_sb_magic/script


diff --git a/tests/j_corrupt_sb_csum/expect b/tests/j_corrupt_sb_csum/expect
new file mode 100644
index 0000000..0493500
--- /dev/null
+++ b/tests/j_corrupt_sb_csum/expect
@@ -0,0 +1,21 @@
+Journal superblock is corrupt.
+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: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 12/128 files (8.3% non-contiguous), 1092/2048 blocks
+Exit status is 1
+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/128 files (8.3% non-contiguous), 1092/2048 blocks
+Exit status is 0
+debugfs: cat /a
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
aaaaaaaaaa
\ No newline at end of file
diff --git a/tests/j_corrupt_sb_csum/image.gz b/tests/j_corrupt_sb_csum/image.gz
new file mode 100644
index 0000000000000000000000000000000000000000..ee92f6b10a68ac7bb761e645969f612af7598b8b
GIT binary patch
literal 3030
zcmeH_|5MU;9LFiT(94}(Ds;<L+PCZGj+~^a6{Y92)ODE?Ly>Dt^N=s87y>FZ?8`OH
zYJQs{)e_14ww7UNLSGiv@>_1|P!W}(ATtmT5RuP&KWzQbzu@`$<#o@y*DsI9^R@j4
z7ns00cX~a1UPZW?@Qn}5lygoYNDn6D-rd#|)VzNK_Ez}27iE4f`R85PF}smPDR5kP
zbke5pO`=P8T<UK8(rt=7wyQYW&$sB>{apv56Rr{%w>MY!DLDu$X@%FT$Sss>xyEr$
z|35v_9AG2O^awn77Y<Zy9P(J6*5!p1T|C&QK<VD>EFU|>mIg;6=PVObl%|wwniqAv
z^<GsHDr#?xFQv7}WKnkQ#7VlA7H3C>RdQYFobXLQ$$lNWs2@pxUluZy)m|yU<}5v%
zi>tIUONE_5ZRY5TX7^fA{+S0+^W=~OMLF7g2<;76S;ee?%Nq6^b$N;4S&vl6n~pb}
zsA%=f5G{(W`2pDLs8@N}{s1v85z?#rFBDo#M|EI|Z7Wz28;9|H*vDg1-&gylx7RQ8
zb2CW#c4}xuA|7d0OZ9G|!C%wt^d-g>yxvmVxv|1JKdu6JJn}`m)_;uL?iz^i(W>1E
zKb?MGRR&ORSrDAbgy@Gl3^fc+8>QfArxpYnx8e7JV-VcD{RZHzApXYg0PF1TuenDd
zcpw^_Y$7b468N+4wP0xVw8pn*zr{^%8oYBHJK@>!M0i|<7aOt4%^Bw+A(TB;IZy>=
z^;Gw-zaS{LARZgg^yWQ|J(Hn{PW;vf{k81a4WloEV0Y%dMu2GADcf(JQFhZ9y#pK;
zBj;0e!SY>P%CYB!1xVdA-RwYIv)O}^0?#uYj>#)1#b==VNCyWRvM1B#mw*D9>5(pZ
zj=6t%02M`4e9lvy9Yic2X4PfaM4@f<ufw}0!UQGdF@Kc&T;j;}@-$5Az8il;X&qmA
zB-Ms3BkGAY($g~u-Kx}VsAme^7)%&dA7;NF9r%6c8Oaewg*mNZ+v7&9>pbd2q$TDR
zH`RxfT0Hec$gVk3I8xMbX#t%X|KOI^umP{{(nN@zP;gso)+`Vu$5k^vG5t1)F#g3~
z|6hyGYDMoP^n8wNjG9+xu|Njt{$VqV?0g%^zdDz+RW>?A2_Jigp+CoLcia^I`ISlJ
zL}3en#;auHE<qv{7iJm-VU9%32v>K>+5!}0!|j)ovV%#d8e&x-jYPdI&W)A6F>{CO
zoa%@CA4?+u#~FdkNCZz8@*uxBIdv)FusGgHENm;c&_zV6gb6X5$j+RDH~YAWm@u%<
zo4Aom0iONbP!i+h;=@W=tppgk6s;8~Wlyj5n&sL2MR}QRD{UdnC#tlUI7or^&c-{@
z#h5-2U)N0+Z2F({<FEaYnsL`}c6?dutr2c{6ft2ibOn$DLc=H2hJt{ZqNj3A%MBaT
u?ZfffUNf*}VAUEJASbWmNi=RQtCnyLY|X&xG{76v69;z-J7KULuzvwe)<rY`

literal 0
HcmV?d00001

diff --git a/tests/j_corrupt_sb_csum/name b/tests/j_corrupt_sb_csum/name
new file mode 100644
index 0000000..921a0fd
--- /dev/null
+++ b/tests/j_corrupt_sb_csum/name
@@ -0,0 +1 @@
+corrupt sb csum (csum v3)
diff --git a/tests/j_corrupt_sb_csum/script b/tests/j_corrupt_sb_csum/script
new file mode 100644
index 0000000..102feba
--- /dev/null
+++ b/tests/j_corrupt_sb_csum/script
@@ -0,0 +1,51 @@
+if test -x $DEBUGFS_EXE; then
+
+IMAGE=$test_dir/image.gz
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+gzip -d < $IMAGE > $TMPFILE
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+echo "cat /a" > $TMPFILE.cmd
+$DEBUGFS_EXE -f $TMPFILE.cmd $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+rm -f $TMPFILE.cmd
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi
diff --git a/tests/j_corrupt_sb_magic/expect b/tests/j_corrupt_sb_magic/expect
new file mode 100644
index 0000000..a233033
--- /dev/null
+++ b/tests/j_corrupt_sb_magic/expect
@@ -0,0 +1,42 @@
+Superblock has an invalid journal (inode 8).
+Clear? yes
+
+*** ext3 journal has been deleted - filesystem is now ext2 only ***
+
+Superblock has_journal flag is clear, but a journal is present.
+Clear? yes
+
+Pass 1: Checking inodes, blocks, and sizes
+Journal inode is not in use, but contains data. Clear? yes
+
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+Block bitmap differences: -(32--33) -(35--49) -(83--1089)
+Fix? yes
+
+Free blocks count wrong for group #0 (956, counted=1980).
+Fix? yes
+
+Free blocks count wrong (956, counted=1980).
+Fix? yes
+
+Recreate journal? yes
+
+Creating journal (1024 blocks): Done.
+
+*** journal has been re-created - filesystem is now ext3 again ***
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 12/128 files (0.0% non-contiguous), 1092/2048 blocks
+Exit status is 1
+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/128 files (8.3% non-contiguous), 1092/2048 blocks
+Exit status is 0
+debugfs: cat /a
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
aaaaaaaaaa
\ No newline at end of file
diff --git a/tests/j_corrupt_sb_magic/image.gz b/tests/j_corrupt_sb_magic/image.gz
new file mode 100644
index 0000000000000000000000000000000000000000..5d895e78beaf49dd8e53370b85d7a7e5ce1afe82
GIT binary patch
literal 3036
zcmeIw>o?m67zgka-5hl6Y=_n@%E75p%_zDwby+ROn7S7^T8_DtR!TxDL|j|6?lme%
z)hV4aT1-Zw3@vpZQ9(9o5Rrr*@w1TMZ*TU-zu<V@eP28;zMtno<|!lcch<cX6h(`;
z2R^>Kh|Tzj!3Cl%jzHIMvUzn;$-dZWvai%onLKB_W>Kb*8La5<<PxBozDd_iH!O7O
z)9=?hS#;6xVWx)JvtqxDYgu#7;5oXWs>{myH9EETXWq9gF2G6@_eAWDb;ZMpV%lXZ
zQ>9wmsTYn|WzO<i5-O8!H@2?2!!H_^{uHe3Qj~R%bkqFTQn%^$XYKn0U(?xv$@fmm
z9JjONON_(=V0M)v+gN8LYsr^dBLH3iGb}Dr)?R@Q_rNZSj915Wul{y_dO+UuRYc3<
zrYpta!tWB#hCErHB-NjGCGb^e*0o;3Bz!&zHMmUFj$}a9*^OCSmbblLmhw4Dfr5ob
zOwD)!&l#oP@(K1_U~lVf3&fU4U6l-Oh>%$T?TG?|G!Tae(&2Od+?e&D{H_*jF7I$p
ze5W$v1fgvg>7D@{=J2VSrHLC!gw<wxJ%=dPCmUO+{_`~SNi2RY^Nhs`a5v||_&K8c
zFswRo1*W3Wu&w^0l)%7Te}k!A1mMO_^;e~^0es?L^>-8pND)95!f6Mef3i1#sTJk0
z0PTQpo7W*U60Hb9IJHMOs-;VYi9E?R0gowRw5NihU;~CqB!-GA)!|WaDtrFG-s5f$
zC0Z~wXt&nA3(Q8}i&1F4HDgIL;&(mTCL3wb5BVW#MLsRC>I}Hww<oMC2$odd`g`gc
zMcXn3pq2+azSY};xJ~OpAn40o<=h<UrHNWHkX0?o@)mLexG}PA%Uuw{x1Yv3{_-(<
zy4EN&7Qf@%tuUu&l2Xep$C|P2@lgiOn!|i*Ym?UncXsZqnC(jo(88MXio%lxgEgZT
zT$G))eEtLNn-_KB-QxI&FOUH}f@Nsw;cI`apZ@zcDgBQ^OE>9Sw^vLg%d^3c<tZP}
z3;U3V((Igen3jUpKU(BdZj^Y{n{!PjTqU~5%Oa3PPnn^?T6b)srY`k{^-EZMWtIOg
z*;yXQVaj&No%3@^LZN)siarI9qUCurpM9xUW<#d=w`F%wqn6U6n)m6<zrNqhl51Th
zN$S3CU!~)AyG&DKB~>~pbv;6RAUK&#3BwAJ{hLg?fa_-N7%04~V|@C)d)Hfl#eUA?
zwq}%s<UpV-r+T6ZBJs8keyB|4Y&Oa~>Se6Gxbs4;tGy&vav%wukqyNe(%_~@BIMnW
zdge_BY+DT{46V^t80E~0U09MD$%kM8vpaVbU?tGDS*4)P9RRJ1Ef@`%ih+hAyyfEs
z>@nEuxs*M2^2FhvJ(SXB&kwrbD#mj0{`nuzN~BWpX&Q>*w8Rx+P%D|;EM9dXn5cGW
r<v1J*919#pfr;oKL|O+=P5CI6JMMHWaD)ZYf&@ryg3DtB!T|9f_U=kB

literal 0
HcmV?d00001

diff --git a/tests/j_corrupt_sb_magic/name b/tests/j_corrupt_sb_magic/name
new file mode 100644
index 0000000..dc781aa
--- /dev/null
+++ b/tests/j_corrupt_sb_magic/name
@@ -0,0 +1 @@
+corrupt sb magic (csum v3)
diff --git a/tests/j_corrupt_sb_magic/script b/tests/j_corrupt_sb_magic/script
new file mode 100644
index 0000000..102feba
--- /dev/null
+++ b/tests/j_corrupt_sb_magic/script
@@ -0,0 +1,51 @@
+if test -x $DEBUGFS_EXE; then
+
+IMAGE=$test_dir/image.gz
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+gzip -d < $IMAGE > $TMPFILE
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+echo "cat /a" > $TMPFILE.cmd
+$DEBUGFS_EXE -f $TMPFILE.cmd $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+rm -f $TMPFILE.cmd
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi


2014-09-08 23:13:48

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 19/25] tests: test e2fsck recovery of corrupt revoke blocks

Test e2fsck' ability to deal with (a) revoke blocks with a bad
checksum and (b) revoke blocks with an obviously bad block number.

Signed-off-by: Darrick J. Wong <[email protected]>
---
tests/j_corrupt_revoke_block/expect | 17 +++++++++++
tests/j_corrupt_revoke_block/image.gz | Bin
tests/j_corrupt_revoke_block/name | 1 +
tests/j_corrupt_revoke_block/script | 51 +++++++++++++++++++++++++++++++++
tests/j_corrupt_revoke_csum/expect | 17 +++++++++++
tests/j_corrupt_revoke_csum/image.gz | Bin
tests/j_corrupt_revoke_csum/name | 1 +
tests/j_corrupt_revoke_csum/script | 51 +++++++++++++++++++++++++++++++++
8 files changed, 138 insertions(+)
create mode 100644 tests/j_corrupt_revoke_block/expect
create mode 100644 tests/j_corrupt_revoke_block/image.gz
create mode 100644 tests/j_corrupt_revoke_block/name
create mode 100644 tests/j_corrupt_revoke_block/script
create mode 100644 tests/j_corrupt_revoke_csum/expect
create mode 100644 tests/j_corrupt_revoke_csum/image.gz
create mode 100644 tests/j_corrupt_revoke_csum/name
create mode 100644 tests/j_corrupt_revoke_csum/script


diff --git a/tests/j_corrupt_revoke_block/expect b/tests/j_corrupt_revoke_block/expect
new file mode 100644
index 0000000..52cda2c
--- /dev/null
+++ b/tests/j_corrupt_revoke_block/expect
@@ -0,0 +1,17 @@
+test_filesys: recovering journal
+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/128 files (8.3% non-contiguous), 1092/2048 blocks
+Exit status is 0
+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/128 files (8.3% non-contiguous), 1092/2048 blocks
+Exit status is 0
+debugfs: cat /a
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb!
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb!
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb!
bbbbbbbbbb
\ No newline at end of file
diff --git a/tests/j_corrupt_revoke_block/image.gz b/tests/j_corrupt_revoke_block/image.gz
new file mode 100644
index 0000000000000000000000000000000000000000..b165d00b46676b6c35d974053ee557c1a757bc09
GIT binary patch
literal 3038
zcmeIw*;7*o6bA4JGbS}!El`RI5(f)q!c<Ze5NeTH#Ssw{WfO=f9Rz{Ypp6*GWeJN=
z#1>OFB_It#(O^(w7Lu??U_iE_!2l*hiGT<piQX*SaBm;_#J|9B-oA(P@cqtlEW)5D
z#`#bS%f+`qfz4Tal*UVVIh9&feIo>jh>42Bz{fTn!G;#%G+Rq*kkg;}_j+jd(CJTc
z7^ESmrr@tTPyD(7o1Z!h_E`PcP;kO$i`AF^elC(&2^2y(YeER3qq)_P$zEA;zv8(U
zG&AGt>j9+_F^7cn!8v5ix#_tG0$uDqDE(?~(1|hOO>T5KVtX`zn%BZ1CkkSp!ELw4
zUsQVgoWjJNbEP+<4V#Gyoq32!j7eL{R`v^B#J5=!RH#0-N?tm1x94E&RrSl-6}(sU
z<k)_)e!gAT70LBHgEh6BDd}Te_@)?7Y&a_kfd;S_U*00vJP!>X1u32<21@)QOHZ@h
zl+MG)XHTl(3#s;d3$(@v*wCGEP)T62Y2bO{+{#qcP{yZ+OJNh)sMVuU+KGZ*CI^8~
zKy5K=iQAa>=*b?HGA(pVZs#9gn<&PsxyPqoJNQDjq_><V1LK(+om3RbmB(4vx0d%y
z9NNBbdPCTa?6vu5MynUhL?C|F>%I2ah(7bze&nIz2VOLsV@9j|aL5MJ)?VNcY^ig+
zgJhb~^+ec_D4Or`j{Hz8I0KXm9)FuBWw+0={7Y$VI|aPzlW(IWRF2Q3;F|ldb&@}q
zSl2)kaBrN9sQzJrS3>xDoh*r*Y{8D}e&5$Vw;)Z2opy}(*rI9{U$GHvE0hsu1UmxQ
zl!4*2#Q2Ll_R@4&Wzqf}4p$J;Q31b<jZQL{Wb*HRNq|1Iqi6kK!wRraCrlt#3*XNu
z5aL8Uw)2yWx$)gLu5_eKyXky*xh9K7+0{5H{XOuYYm2+jxX0aMM&Ky;0Gz${%31be
z<kt0gd6+<(kQVsdpbrvxK6M#zEupr}O;#L+!c%#?=F6&u*IDoKpC+d?*y?_6+{M6m
z=jpMzQ6RQe+2$_2XLtCDFSsuTNa%WHHkR&pJ=>>Cv3UGxkdqZEMs|*m@gN|#DyZ`6
z7EJ^Kkq%^A{C~^#MV5j~x=9tEOS!}YLHJ{ZyG)l(UMXtb_{BSp=S>Da^6*6aK9a&_
zY$b$}<Yep=W0_*ZslsJtZH%7pLQ7e?xASJ5=!2gonmPt#@WJL<fMoB6XE-||EgbGp
z=#5~0hfWgCnpTcjS}XHm!*c%M@FO^VT5B%Z2Xd!MuQ5-6fOaZOCSlOzqY9If^8jp~
zy6%HS$`;HIx2dty21NRine-dml}*)FB_asi6Q)L(ivvw>+>pSr14v-HMD2{^Pxp@S
ziz){YRr246X=>R-EPMtp^Kq-6c6A!Q(QVg=AKgw+7ZN;FBC*1u&Z^EywIWhjUkvMo
yeAS!Nfu7YX>uFtJU0^K=JmzjkUGg2wT#Mb-JFN?>WdR-o-hkUp??Rz)sQ&=iqgHMJ

literal 0
HcmV?d00001

diff --git a/tests/j_corrupt_revoke_block/name b/tests/j_corrupt_revoke_block/name
new file mode 100644
index 0000000..c7a0088
--- /dev/null
+++ b/tests/j_corrupt_revoke_block/name
@@ -0,0 +1 @@
+corrupt revoke block (csum v3)
diff --git a/tests/j_corrupt_revoke_block/script b/tests/j_corrupt_revoke_block/script
new file mode 100644
index 0000000..102feba
--- /dev/null
+++ b/tests/j_corrupt_revoke_block/script
@@ -0,0 +1,51 @@
+if test -x $DEBUGFS_EXE; then
+
+IMAGE=$test_dir/image.gz
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+gzip -d < $IMAGE > $TMPFILE
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+echo "cat /a" > $TMPFILE.cmd
+$DEBUGFS_EXE -f $TMPFILE.cmd $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+rm -f $TMPFILE.cmd
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi
diff --git a/tests/j_corrupt_revoke_csum/expect b/tests/j_corrupt_revoke_csum/expect
new file mode 100644
index 0000000..52cda2c
--- /dev/null
+++ b/tests/j_corrupt_revoke_csum/expect
@@ -0,0 +1,17 @@
+test_filesys: recovering journal
+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/128 files (8.3% non-contiguous), 1092/2048 blocks
+Exit status is 0
+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/128 files (8.3% non-contiguous), 1092/2048 blocks
+Exit status is 0
+debugfs: cat /a
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb!
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb!
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb!
bbbbbbbbbb
\ No newline at end of file
diff --git a/tests/j_corrupt_revoke_csum/image.gz b/tests/j_corrupt_revoke_csum/image.gz
new file mode 100644
index 0000000000000000000000000000000000000000..f505592079452ad78b22f5c096f951158d47981d
GIT binary patch
literal 3034
zcmeH_>o?m67{_DICZ~k0T2s|VXS2Fg=CoT}aw*!PV|K!EkGLIkO<YDSwMIwP$z0m4
znPM0gw^o=-G?GZ`oJu<fahqChCUXx#BqF!pUaW6=&i;bV^X~bc^St<cz7O<!Fi3Q;
z5%QMtmIzmNBF`4IBazXWqD<0;H!=bn6%RH99J^{7Lb2O<YQJ`Y`fdrrIM~PE-SoSi
zCUa7mKLvcl40qznNZE(SecH<~o{(cFm&`fvrp*IZ4NbsOTEs9Kw1>8mn)(`vc$<(v
z+;_2$E5d;<vuyl})4&4hT7gH2!F|HPYVCzRRe&IMz^_`3j*{;5?dGHo#rEIiP9!8?
zZR=fb_p}@znfKLRb0yp`tWI{*S;Q&%9OuVI-d_E;`kC%=p<`~RB_8HMR_#2Ut8+cO
zb{0v@%UZtY5)DnG6-IXY@u)fNf#-2foj50hV#!*OV8&C<3ifwdHmz2p+(!W&*MI7^
zOra^-R5#twmG3_*C`15SDWie#Ab5V5)PvsFXLV^&ni*nxmpAD3Q4`8V4#|V98skL%
z=rlnv>k}4bwI^YA+{UCX^y=V+L%x3Nb6A$P8ZQ}WlT-U$N(f_-j5)kza{q%d?wKJ(
zo6y4%fZbQ<Otxh@Nx|0#@O4$nf~F{c3}_Rh`Z0!Loyp&5JHY7B;yL-U!FUgP7bw!1
zB*z*WBUmfN?veY~upN>>QCPKaV)&xz^e+KuF$5bk`76Fl!ihND`w@SFqJ!;mdYe!{
z)r?@fF>0vS&D@jDVGq>G>Wb1Ml<B<1m%`C+hTns1C7uTH^C=1dlg)vZvr+rcl@q5(
zunPPaQd%%-=ZA~uAKTM`aVJ-iBs^wS5I6p${z5%K-j{0uwI6YE7(pHz=Kx&BGn<l{
zOgl*Dxs0k7nDo?>hELXw^$iFNbG)UR6q1xZIpy_pMfK-1%4VfD&&qOhX)Q_ECu<j~
z`<TmKT1^|Sjv2BN`mr!J#~}Nw_#qsN;3G-f8;if&M>0^e*AII`t16wBOI4<{W({o#
z4Xbp6jb_CJbAq7Uhw*9gy0O~(ok@qDx57xP>cvzp0NF|(QF5op9fCYf3NjY;gEDWU
ze|ub1VF&{FZ%9ekXNYMH2~Y-F6AlprhUI4OD|u`Pjz@jelo?k$7*|`R|1vnuUOjTl
zw2^%fPtk1hT?InRum1E}EfuH8H5RCOu~HI|sn4~32{mzcqIPJx8SE`Zzc>WnqmzG{
z3J_&8FXX<!4ZUx8N*KW2Eiil##LZNPBHJ)}T;XG?l0d_$28aeCJx!nMey@@ocFD`&
zcoO$c7Xhf?p$Du*Gleo5p>+$;LZg{_G6UV6(5LH;SyjW9^`&(>bKX><qWV%Du*(bu
z(0&^{vg5RLzUu8)q_6+&tF7n{XP!T{W`dF(UcPWnu2gPYpK<f_6-zdeZYw2hu9SZF
wfN1ugr$^zDfg=NNk^z2Nv{4a53I@MPP)96B2L1;IilWz{_JJk~AdnsCAAu!D7XSbN

literal 0
HcmV?d00001

diff --git a/tests/j_corrupt_revoke_csum/name b/tests/j_corrupt_revoke_csum/name
new file mode 100644
index 0000000..b63ea23
--- /dev/null
+++ b/tests/j_corrupt_revoke_csum/name
@@ -0,0 +1 @@
+corrupt revoke csum (csum v3)
diff --git a/tests/j_corrupt_revoke_csum/script b/tests/j_corrupt_revoke_csum/script
new file mode 100644
index 0000000..102feba
--- /dev/null
+++ b/tests/j_corrupt_revoke_csum/script
@@ -0,0 +1,51 @@
+if test -x $DEBUGFS_EXE; then
+
+IMAGE=$test_dir/image.gz
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+gzip -d < $IMAGE > $TMPFILE
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+echo "cat /a" > $TMPFILE.cmd
+$DEBUGFS_EXE -f $TMPFILE.cmd $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+rm -f $TMPFILE.cmd
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi


2014-09-08 23:13:54

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 20/25] tests: test e2fsck recovery with broken commit blocks

Test e2fsck' recovery of commit blocks with (a) only a corrupt
checksum and (b) an obviously incorrect tid.

Signed-off-by: Darrick J. Wong <[email protected]>
---
tests/j_corrupt_commit_csum/expect | 18 ++++++++++++
tests/j_corrupt_commit_csum/image.gz | Bin
tests/j_corrupt_commit_csum/name | 1 +
tests/j_corrupt_commit_csum/script | 51 ++++++++++++++++++++++++++++++++++
tests/j_corrupt_commit_tid/expect | 17 +++++++++++
tests/j_corrupt_commit_tid/image.gz | Bin
tests/j_corrupt_commit_tid/name | 1 +
tests/j_corrupt_commit_tid/script | 51 ++++++++++++++++++++++++++++++++++
8 files changed, 139 insertions(+)
create mode 100644 tests/j_corrupt_commit_csum/expect
create mode 100644 tests/j_corrupt_commit_csum/image.gz
create mode 100644 tests/j_corrupt_commit_csum/name
create mode 100644 tests/j_corrupt_commit_csum/script
create mode 100644 tests/j_corrupt_commit_tid/expect
create mode 100644 tests/j_corrupt_commit_tid/image.gz
create mode 100644 tests/j_corrupt_commit_tid/name
create mode 100644 tests/j_corrupt_commit_tid/script


diff --git a/tests/j_corrupt_commit_csum/expect b/tests/j_corrupt_commit_csum/expect
new file mode 100644
index 0000000..5fc82b8
--- /dev/null
+++ b/tests/j_corrupt_commit_csum/expect
@@ -0,0 +1,18 @@
+test_filesys: recovering journal
+Journal transaction 3 was corrupt, replay was aborted.
+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/128 files (8.3% non-contiguous), 1092/2048 blocks
+Exit status is 0
+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/128 files (8.3% non-contiguous), 1092/2048 blocks
+Exit status is 0
+debugfs: cat /a
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
aaaaaaaaaa
\ No newline at end of file
diff --git a/tests/j_corrupt_commit_csum/image.gz b/tests/j_corrupt_commit_csum/image.gz
new file mode 100644
index 0000000000000000000000000000000000000000..334fcd000d57f589e45987e6dc447c5f3e39c4bb
GIT binary patch
literal 2949
zcmb2|=3tok=T$Hh^V_?=88V?V3?H`38x{)BzVhwC!i){<fr@Qa7m~QPIkC1jEemkb
zy3!wYbXiwm=7dYX0@q{+ez_3*F=1neM#e%d(Q1K@A!`%##WqgY(iF<A+91^V{;i+N
z?3^rxTe(L2<A0ogQ}gEBzLS5_@0~k$j+^ns>bWZ~iyeA)!#ap7(cl~R<n$NoTxaEH
z<m|9_RqW~i-Y>H1^U{Z%k?QlV&*S}a^j`Q;0XgmV4Ry!A{a$amvF!WnYQMZ+wF!s6
zt$hD@*;?l2VtwD|TMTn2%l$7%I@$hSc31Y3%eJ-b^8XW#zI1x{?Ly!hU+<?YdZsy5
zUix!%&5xsRrcOT|A(O1KZu!5q)9+VFM~VIC;(exdd?It|ZMn0h`#%5Jrk(u%mW1}I
zpY{^lzus!w`R)1D^*n7~<IjD$^M3#C_1C3X7*IgN|6@N?7j3mXdf$@Ia@xDx%Ys}-
z=LPIO@9VB1R$Z0#{X?Xb)=~9swzd_IpXHwCv6-{1^+V~(fEy{>IX_38c`EP!cgwqi
z-&6klUm9|{J|XdW{m%nu{g)np?sbj*iSGaQdscrp{bB#ff1=*uAM+>q3I7}Zus^X^
z_|N#0|IGeB_Eon})fO6L_wKU!XkZ#0%k|Z_QQvbe+uMrkriHfiXKk%}*DcL=Q|QEI
zo&TF_^w-an*#Ggf@$cp5WA`bSX&L+HuVeeImcX|EZct_6p3QZ0;$58UY&aO6_<j4i
zf5zPRtFQgn|1xu7eMOGO*Xmz<_g@K%=yZIp*S)#&_v%fbYqHl!M%?(f>-o>Wll%T(
zUH|T0OzEp9Z~Fc}zrT$w@nFsW>yu=^-@f!?o4x#w;(b$(ey=yEzQ1SN_g(D`cV>nB
z_kYfC=v29P{+U((_P=`9{A~d=SPL>GrKI1@@95roCcNBy|DFBo_^xWtUp{?*$X*Sl
zSiYHheQSEeUcJkma!hyT<4xu{oQaVYUrrX3UHpCZ#6SMZo6pwOnccT6e^;^Z^#7YP
zYo^zqZhW@CeeUk0<=bQC?fb9Y^3HPKx4r+3YF|&>^8faa<5wPEaMiDW!PR?eek^Ca
z?5dt=ufF|%dE>&|ua|X8rh!t+5|KkW+#f#f3i;PxX0rLu*^+O!Yo6DCS1n-Qx_ITk
z%ePnj3qDiFW3}<`_3QOkNjh^MZ?ezyz5V}d_3WL0_itVucEs&x{62@j`cMDPioExx
zDCO$D=~BJ*4<oexE6@FZ<$qGh^!Zm=8BtOdDyQL@_E8VtncI%+&~eLNvGrF~Wsg_S
zw}9;TU%Mo_o!0Jsybj2gK-DwK8x4Wc5EzCbu;8W{Bg4+cY-sh+F!brDmqtTic!j`$
Q|1a~U-z3gpU{GKH0EFfkcmMzZ

literal 0
HcmV?d00001

diff --git a/tests/j_corrupt_commit_csum/name b/tests/j_corrupt_commit_csum/name
new file mode 100644
index 0000000..05a99ea
--- /dev/null
+++ b/tests/j_corrupt_commit_csum/name
@@ -0,0 +1 @@
+corrupt commit csum (csum v3)
diff --git a/tests/j_corrupt_commit_csum/script b/tests/j_corrupt_commit_csum/script
new file mode 100644
index 0000000..102feba
--- /dev/null
+++ b/tests/j_corrupt_commit_csum/script
@@ -0,0 +1,51 @@
+if test -x $DEBUGFS_EXE; then
+
+IMAGE=$test_dir/image.gz
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+gzip -d < $IMAGE > $TMPFILE
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+echo "cat /a" > $TMPFILE.cmd
+$DEBUGFS_EXE -f $TMPFILE.cmd $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+rm -f $TMPFILE.cmd
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi
diff --git a/tests/j_corrupt_commit_tid/expect b/tests/j_corrupt_commit_tid/expect
new file mode 100644
index 0000000..dfbb3f5
--- /dev/null
+++ b/tests/j_corrupt_commit_tid/expect
@@ -0,0 +1,17 @@
+test_filesys: recovering journal
+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/128 files (8.3% non-contiguous), 1092/2048 blocks
+Exit status is 0
+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/128 files (8.3% non-contiguous), 1092/2048 blocks
+Exit status is 0
+debugfs: cat /a
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
aaaaaaaaaa
\ No newline at end of file
diff --git a/tests/j_corrupt_commit_tid/image.gz b/tests/j_corrupt_commit_tid/image.gz
new file mode 100644
index 0000000000000000000000000000000000000000..988e5c6763b541de0d5c70f336619ae94cb891f4
GIT binary patch
literal 2953
zcmb2|=3sd7=T$Hh^V_?z9U-AI3?Gc;XW!njbC%tg4Ob@d2OivZ!`Vyk2^$-$(^>^V
zwr>l?c8cY;dUt$NlvH)J{h?y3;_2eZ87A>l;Ns-e3HqK-x?6>!*YQhA-?lU^PdYw#
zYpd?@yT5<y{;z&scjk^|`TPI(jLYBM5oVeYZXLATwxxGt`3{jo0dK_B&RvM@Ho5=d
z#>+;LRs%abgP;}XrnkM`d~LqDy>x_Rb-bu^#TuDIx8B~C+wtzltJwAL?KVFAez5em
zUXA?r97&m3m6=xRy_xer{AhpNZC~^L!CmF~@8T*SeB_@tS4-p_hwRZ?TSEFyWoS-O
zKNEkZEB;JeWoD17q1&S>sf=BJT6vvgKd!%!vaU$RGGg1?i&4+5`*ZhNeOuqZam}p%
z&V|wIb7!oskNbKmAmaDakn?~4?fzZ8){y}f{K)T#S9`W~*$?YuipMYQ&9!n`ctber
z`_7jfN0a>h-^$r}J1zZj<l6G~yn8#o&OGRTX^X%<Jy9;{H)e@p-8=t0J~{uI%&dCH
zfB%D4J+(L3{(1kN|JRmZdR(mfn)%bT|A+JERz?16{=@#nUg1CEPyQ424*!@x$xry-
z@P|Du{-6BL+N1X@W^8qfU1#reHf*|6a`1!h;N_my_jr9{&M!+_JOB5iWzE}IKIxqP
zuXF$O->)BE+uLu>|8(c6b@FnfuV1cZZOUg__ThH!RPp21(#L<gnmjq~%;4}YW&Z!}
zm3k9i{g0i^bz1-1%)|#@ZWO%wzQ$(D9d(Tv!q5NT+7$f#ddl;kzt&35xczU}_n)<2
zAJ_j~z1#e^-@F<3KK}o6`<lX;neTz>9@kY%-T(Kzx%}+5O+WteFMB`x`nNkD3?@Vi
zzxw}D#v$Tk-pk(1tN(w$vrORUf(GsM=?^zvX8yV(<aAAG`0LYuU#|+-`>C?%r}x!v
zrAtpIynJ-xRK~)G_uMk?Jd)I_zWYpI*P&(Vhi|gJ4_E$e|0H$x?r%41p5NJ-{8R6L
zditl>e`kM3|CcL!(=+#8QRSz9>jieD|G4%2@98hP?U(=M|CJY)YuBs%dHB$UHGghS
z{cv^Rsf?A0|L6Dd-i@@s>y!>oFkXs2+Zp87dp`Z2QLTOYzE}GGv*rKF<JrmstS7y)
z-+T6z{n0na7kquYf8)Q)g2^X&rvE*;XUpIFJC;wq{omR;+cjs}|EJwo{s-Or?*BP$
zx^iuGe3se2*2OFT^q2h${@)!KTNftIf|{^Uc~R>{luc7_i9PO;`0TXy>UHhpkfbyG
zTffDv@7kzv<(74vMAlnbW>h_+ywMOC4S``80$XmeF({N@X&8oH8}-s?2n_2G_+kH-
NSAdZ%h=D<Y0RS767W@DJ

literal 0
HcmV?d00001

diff --git a/tests/j_corrupt_commit_tid/name b/tests/j_corrupt_commit_tid/name
new file mode 100644
index 0000000..9b4054c
--- /dev/null
+++ b/tests/j_corrupt_commit_tid/name
@@ -0,0 +1 @@
+corrupt commit tid (csum v3)
diff --git a/tests/j_corrupt_commit_tid/script b/tests/j_corrupt_commit_tid/script
new file mode 100644
index 0000000..102feba
--- /dev/null
+++ b/tests/j_corrupt_commit_tid/script
@@ -0,0 +1,51 @@
+if test -x $DEBUGFS_EXE; then
+
+IMAGE=$test_dir/image.gz
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+gzip -d < $IMAGE > $TMPFILE
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+echo "cat /a" > $TMPFILE.cmd
+$DEBUGFS_EXE -f $TMPFILE.cmd $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+rm -f $TMPFILE.cmd
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi


2014-09-08 23:13:59

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 21/25] tests: test e2fsck recovery of corrupt descriptor blocks

Test e2fsck' ability to deal with (a) corrupt descriptor block
checksum; (b) obviously bad journal block tid; and (c) corrupt journal
blocks. These should exercise the journal recovery infinite loop
bugfix earlier in this patchset.

Signed-off-by: Darrick J. Wong <[email protected]>
---
tests/j_corrupt_descr_csum/expect | 18 +++++++++++
tests/j_corrupt_descr_csum/image.gz | Bin
tests/j_corrupt_descr_csum/name | 1 +
tests/j_corrupt_descr_csum/script | 51 ++++++++++++++++++++++++++++++++
tests/j_corrupt_descr_tid/expect | 17 +++++++++++
tests/j_corrupt_descr_tid/image.gz | Bin
tests/j_corrupt_descr_tid/name | 1 +
tests/j_corrupt_descr_tid/script | 51 ++++++++++++++++++++++++++++++++
tests/j_corrupt_journal_block/expect | 19 ++++++++++++
tests/j_corrupt_journal_block/image.gz | Bin
tests/j_corrupt_journal_block/name | 1 +
tests/j_corrupt_journal_block/script | 51 ++++++++++++++++++++++++++++++++
12 files changed, 210 insertions(+)
create mode 100644 tests/j_corrupt_descr_csum/expect
create mode 100644 tests/j_corrupt_descr_csum/image.gz
create mode 100644 tests/j_corrupt_descr_csum/name
create mode 100644 tests/j_corrupt_descr_csum/script
create mode 100644 tests/j_corrupt_descr_tid/expect
create mode 100644 tests/j_corrupt_descr_tid/image.gz
create mode 100644 tests/j_corrupt_descr_tid/name
create mode 100644 tests/j_corrupt_descr_tid/script
create mode 100644 tests/j_corrupt_journal_block/expect
create mode 100644 tests/j_corrupt_journal_block/image.gz
create mode 100644 tests/j_corrupt_journal_block/name
create mode 100644 tests/j_corrupt_journal_block/script


diff --git a/tests/j_corrupt_descr_csum/expect b/tests/j_corrupt_descr_csum/expect
new file mode 100644
index 0000000..419e775
--- /dev/null
+++ b/tests/j_corrupt_descr_csum/expect
@@ -0,0 +1,18 @@
+test_filesys: recovering journal
+../e2fsck/e2fsck: Input/output error while recovering ext3 journal of test_filesys
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+
+test_filesys: ********** WARNING: Filesystem still has errors **********
+
+Exit status is 12
+test_filesys: recovering journal
+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/128 files (8.3% non-contiguous), 1093/2048 blocks
+Exit status is 0
+debugfs: cat /a
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
\ No newline at end of file
diff --git a/tests/j_corrupt_descr_csum/image.gz b/tests/j_corrupt_descr_csum/image.gz
new file mode 100644
index 0000000000000000000000000000000000000000..2a81e5daeb13fcec40d8fa9ef95151427a35b584
GIT binary patch
literal 2989
zcmeIz{WIGK90%~AZF)0h>dI+O^eVOMRO%2mCN1k(kuutNzHG8aiAYOP59jORX~~qf
zPSS`*v#nb591mqkHuKO<mLQ6GTxcjMsfR4`^!;x8vHk?-^V{b>_xa)dy3gGQ`TbGY
z$Pq=DvB~-z?gru-0`|_Mn^TF_v5)XB=Bq*(2|FR5d@zVN{rt|z(X6DlB1Q`jQ$eHA
z8LUN|i=DSs)<-m}v+EZbs;{5n3j@%DKTO7rT%FE`yNHKHzCIY+@4m$?t4*n-3{rYL
zRIZWqu>X2wZ5(p-_ZF#*FEFjENA!hE2a|$F*cG0!*_nI~rbAG$`U=WbO2Ji!J2nU!
zQNY&C>67TfcX6l!M~;}#og>@C4jmJw$m?GB2X14B8d+r@p2Jp}nHIT;v-GR6j=?>^
zTYBmCab2-_&*(Ps!A`+MD8_kkG^Z7DwzUQ=m$9}o=DAE<0y}^eM*UMmt=g_XZ3s*Z
zx^@|E*ASt8)|Bnztr}i#12UpEs$W99+p!Y7C_h}N$^01M(>X;}BRo@wEf2xot2}6M
z2kI}<7GS;24xdm`q_z)2!(VKqN^Jw4G&a7q^P%v%+|J)gx)Bfky?MHLvD3o2qWmWb
z={UaKjRk1yWNW3&ObyUmCC4^*Yy;7fp|H)(2EN?r(lBIQDiGknd_DX%)*dp_n7;rn
zfF@hWdr+PpjwgVGoHxIX?j+3HrajS~$3({-OXV0ZSbDinZ*ryms>H+z?R~!=QDoyw
z%oTvEtmu6uTPRhhIaU3_N3Xk~eFTEUBu?I?ajmSE@P*$kZ#c~AO0J&pheTc2y5Q~r
z-4=~_MJAUS20h>sPa4hr7T9zOn+Evja;Z%y6Y@-NKC%ZxhOnut$!hDBbY}_#$Rh(S
zCPXS>QI2rIrnsy$#*orJu&6~k&H0DL8YCu#?sXtiVpLH6Xin)|3qlhcijK$4q%}w}
zriF;Fw7|lYN%lDO&H87C%PDIXArY<rjTSL7v6QGj*8l=|1M+`-JiS5way~J#Hgn_Q
z&%mtE$Cf0}AeNFPftVTupJU=KjzLfaY*E+quMi#AyEXx&ufNSy&MN!qOk6F9Wbnml
z=2l)SXPm9QKy@xUU9ZD7LGd<rbb3Us(=6!7OJyq!<H8cG-hUQEc`Pf7@!nvw%Qyq8
zJ0l8moC8@aNzjsj=c*ivev=eDT+<d*;TMqzTd5@Kg}qUdUB&A3<bW7bQ70kSm=aa>
zMwChz3KB=wwAkmMw369zU99U9bb?6WDOUll-gkQV&ta9&q1#^Yr2!2_<SH$x>7TZc
zXUyA+JnjzdQcLg(prv0EuAseldwZG-hJlVCVpxq?0-eI0Kf%WnIAdc~Oy<3IbyjxN
zL~(uZ(%n;JrOlqTgZ4n+Kw$p~Jf7FWV0nEv5AFF_`!DH1q62~bCGcy&?#Ysla&s8W
G9`-Nik0OEq

literal 0
HcmV?d00001

diff --git a/tests/j_corrupt_descr_csum/name b/tests/j_corrupt_descr_csum/name
new file mode 100644
index 0000000..e15ccfb
--- /dev/null
+++ b/tests/j_corrupt_descr_csum/name
@@ -0,0 +1 @@
+corrupt descr csum (csum v3)
diff --git a/tests/j_corrupt_descr_csum/script b/tests/j_corrupt_descr_csum/script
new file mode 100644
index 0000000..102feba
--- /dev/null
+++ b/tests/j_corrupt_descr_csum/script
@@ -0,0 +1,51 @@
+if test -x $DEBUGFS_EXE; then
+
+IMAGE=$test_dir/image.gz
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+gzip -d < $IMAGE > $TMPFILE
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+echo "cat /a" > $TMPFILE.cmd
+$DEBUGFS_EXE -f $TMPFILE.cmd $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+rm -f $TMPFILE.cmd
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi
diff --git a/tests/j_corrupt_descr_tid/expect b/tests/j_corrupt_descr_tid/expect
new file mode 100644
index 0000000..0444203
--- /dev/null
+++ b/tests/j_corrupt_descr_tid/expect
@@ -0,0 +1,17 @@
+test_filesys: recovering journal
+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/128 files (8.3% non-contiguous), 1093/2048 blocks
+Exit status is 0
+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/128 files (8.3% non-contiguous), 1093/2048 blocks
+Exit status is 0
+debugfs: cat /a
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
\ No newline at end of file
diff --git a/tests/j_corrupt_descr_tid/image.gz b/tests/j_corrupt_descr_tid/image.gz
new file mode 100644
index 0000000000000000000000000000000000000000..3ad88f9d15549c24758ae53015a08b62f938f5f8
GIT binary patch
literal 2999
zcmeIw|1;Zn90%}dw7R;Loo_88Y`3Xv6<1ptN~l)q)S|TYU0ROBx6oy%FKP6&i!p6?
zH;sx>U2!3%i3k;up<zb|O3ark3*yU3NMy*D&wIBY+dsj1{r3Ff^~3Y=dLc@V!s3k9
zLl40>-eFVCZ=8T_B6(3~YIW4U2mUr&7mE&~?ETG7pZdheB+|?)L|Etl(zn>*T6|-l
z@m3wn?!uD{H-{e$;YJtV6dGO*a*bwQYQFSB_-A(^tE;VrzAe5<AAiMFX@6;J@jSO7
zM~aZDjjQ<BqdwO@t*1&%HPZQ1)PtJyqOZjxWo_;_%wBGKazuIgimkXo)%3V|y+uMH
zMr;Us?_|`N_mq^GRz>G7uho(sgPgeevO!z|Cbj}XaXa&G5uj0KrCVL*m`W`7&Rs0@
z!~Rfpa>lDuHdKXZVLEbX$|R>pT>4V*Gj|HZ@*d+~I<k-J!QE=F%(dwP4NlD-QUS9&
zy6n92maqdudZ!&_;UsSsyjW?C%OE&<Qe{C>l%?OZI|k3gYo~1UzMEqk8o)l7d4by&
zn#D#fm|%VG*XGS|sLXL&rFND>4Po#+1ypgz$jxc=T>^mw<`>}FF^=ikr!7ozqM0S9
zd=Ral_&(t+J86&7R4GHhYFAPG#E#O{y(adO!R0|<b-b&~7b?^lEu!s#!Jf%q6dwq#
zL_7fnIwQ+isG73UJ-W-5*ksm1?wL_B$3uCCaCAHCZK+pn$@;_bCiRzE|3HahG4m;i
z=&*E6R19l&(_OYRhbwvP)83pRZ~klRRC+-~Co64lYSn6v_l0$_6a{;pk^CM6wo1th
z<JrzrXfl3<A1lAoD``7|)f_oo^3N_VaAQROTdOqR)A?lhtlUPo*&3h)YYg57u5#`|
zn;tCToqfYUmjR{q^N#oFK~fCnkNnpoad#k-Ww~@q4$1EKR9px3@vsHLq-1CLIuP*n
z70##5RA?vxOn_*d1Y}3MziS|>aDBIaibeLh9n=75FVlKr`mwX<HVybygZTdnmPP8N
zb-p@_H%EGVS0#niqrv(?nRzy*X(@ETL4XQQQ7;l^hEfOkrDN@_s#2ge_2`AZv8v9=
zjY(Dm>I)_*YRAe`)_2yz6WXD;Wa)V5bO?XKF5stdhG-VT*Q8Vlv<%8K?@i1!lz^;L
zP>FfE+cya26o}?JL2cK&V5gvZvR_zQIkBe2jXS|ArTLYo!0Km0bOQdgXqUdaHYpqi
z77BN8t`e&jOZ?S1MwT0atgns)oPI8`N<k)uMFJDSj7SZ3uh?Df|5@WQh%FL_fZCF!
z?BT6MT71;Ex)FkI%-9LC`CYAXY2Aj@k)|Jf;YWecHBL)f8{mA!9ha@zIw;hcNvUZp
zXX6}7^I&|`XG-W%*uzdi{6|{{@j&1}VE+jeB(B3@uw%VQ`~BDLpwWTAz7`--1qKMw
Kr~n4Dhy4e5RXFwl

literal 0
HcmV?d00001

diff --git a/tests/j_corrupt_descr_tid/name b/tests/j_corrupt_descr_tid/name
new file mode 100644
index 0000000..2325d6d
--- /dev/null
+++ b/tests/j_corrupt_descr_tid/name
@@ -0,0 +1 @@
+corrupt descr tid (csum v3)
diff --git a/tests/j_corrupt_descr_tid/script b/tests/j_corrupt_descr_tid/script
new file mode 100644
index 0000000..102feba
--- /dev/null
+++ b/tests/j_corrupt_descr_tid/script
@@ -0,0 +1,51 @@
+if test -x $DEBUGFS_EXE; then
+
+IMAGE=$test_dir/image.gz
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+gzip -d < $IMAGE > $TMPFILE
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+echo "cat /a" > $TMPFILE.cmd
+$DEBUGFS_EXE -f $TMPFILE.cmd $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+rm -f $TMPFILE.cmd
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi
diff --git a/tests/j_corrupt_journal_block/expect b/tests/j_corrupt_journal_block/expect
new file mode 100644
index 0000000..50d0b78
--- /dev/null
+++ b/tests/j_corrupt_journal_block/expect
@@ -0,0 +1,19 @@
+test_filesys: recovering journal
+JBD2: Invalid checksum recovering block 1090 in log
+../e2fsck/e2fsck: Input/output error while recovering ext3 journal of test_filesys
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+
+test_filesys: ********** WARNING: Filesystem still has errors **********
+
+Exit status is 12
+test_filesys: recovering journal
+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/128 files (8.3% non-contiguous), 1093/2048 blocks
+Exit status is 0
+debugfs: cat /a
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb!
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb!
bbbbbbbbbbddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd!
dddddddddddddddddddddddddddddddddddddddddddddd
\ No newline at end of file
diff --git a/tests/j_corrupt_journal_block/image.gz b/tests/j_corrupt_journal_block/image.gz
new file mode 100644
index 0000000000000000000000000000000000000000..f60439f02ea11289639dc2c3e5108bf5b3a662bb
GIT binary patch
literal 2998
zcmeH{`#0Nn9L9rfY+4+;QXJ8)&h)G}+k!eQ>1>_4giaLA7>#RO>N2;ueW^>kso1n`
zO;J5_=`;xHn$l$@npC2RTd<}|o6vm|;>Zp8tiQH@LXY=v&kye(p4ao72U(_v@YH#Y
z)7F9i#l~8mw?u3>4^wV-_N@gO8KZ(7no-nmrhmIkn{hX^LS449pf(c{+px{I33pyJ
zXW_2t8kU3<TbFp{*p6j)1+=@{)Xd(QBTNM>6zP7+VLx$4JDFci!@g4JCq-vQXT*T(
zDlWZFP;aVzE})3UH)9m`W_DOIPA~Yi_)S$+oeIq%(VeT0`}oRzkK_1>XB&e)r;c>k
zK(ez7!@-{{H+$*%Io3bOSM8cWWUJh5*4*RGniz;o?X<KC&PBD04iIn2m0LM}mS97C
zy*{QBKC-kE$gS|?nc%$z17;pu)YLW~%E*l?VJsmj0zdm_)Ui<C2aY14)5?Vyb<K3`
zUzG-K{xr#tVG1Z$R&$>SMtTz(S)ed2lpFXYFG8qsGcu4+r1xDF4MT|^Ya`yehfstJ
zBBbXrkhhAp%M^XYgPwO?BNc<hgU$Y#nHh$S+f9RMZ9x3+mChd1Kw7clJ`mtriKbwK
zdAtzKT4yN@Yu6(KKe(`=aFPh};I^7<Zo=I!wa&1CX$Af1QShxsM~3_z6zuA*VyuCd
z%5VZYt<mvz01j@uQ^{&nQu&a7o*9K|f29sv*jZL@4rg&=Uu2(fjNcP$mMa|#kFmEf
zTm`FReM4$5Pv_JRb-ThSE@osTE`d@&q7UZ1928*ain3T+vPi3d@wftbt5hS&>YdWn
zM)HwtCL5*+l^NiK$GNVP9N@UxDv@%yTX1(|IBAgwp1$VG0j@@pkxPo+V#q;IL(c~n
z1tB1QLa|exqTHC85AwD<JO{#;(RE^US5&oW0i!k$REQ9aUpo?|4s9C1AzSp_?n+n(
zU+~mmWkwAN#YL_&;G)W0b<$-JX?u^j4L(hwBy%UkI{NLPF%am!$)Lc7@EwWXkC#ll
zIb)|Wk}#w`PMAwh=@;2p;0y$lh32jHWGA6l^wOfO!B743N=UEiYfF62njmJD>A#0L
z6ji^N(Khdr38&Ilz;gwGIVvhsL#2N=)n2V)Ey0lS&|%dxKfqQNL66|D)L-QJVlorC
z;7(QcBr$x_c`!s8mt!OrL$Z8&31__bo+tZzm*SF-l3QHH!D9UOwb6zS2>0J^*!HD8
z%s(Z;KoHoj31UG9@Sz}P7Q*wp^Z(dFkGggM=CgK@8uQhS5Bca;O--cfBhg(jhGa|e
z&nN9W6X5}Td=`Jq3`{P^?KxDR0&$^6Z*}k;(Kb3?O-x|*9<`%Q@`v4L*W+>cn|z*e
zxBTazmZ<X+3$B;+FXS-a`P!HJ1ojEMhXl4~->l`K($B2lLvQ<*_6fYt1SG|yTAt-}
J0s>);_#dgmGFbos

literal 0
HcmV?d00001

diff --git a/tests/j_corrupt_journal_block/name b/tests/j_corrupt_journal_block/name
new file mode 100644
index 0000000..5d862cd
--- /dev/null
+++ b/tests/j_corrupt_journal_block/name
@@ -0,0 +1 @@
+corrupt journal block (csum v3)
diff --git a/tests/j_corrupt_journal_block/script b/tests/j_corrupt_journal_block/script
new file mode 100644
index 0000000..102feba
--- /dev/null
+++ b/tests/j_corrupt_journal_block/script
@@ -0,0 +1,51 @@
+if test -x $DEBUGFS_EXE; then
+
+IMAGE=$test_dir/image.gz
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+gzip -d < $IMAGE > $TMPFILE
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+echo "cat /a" > $TMPFILE.cmd
+$DEBUGFS_EXE -f $TMPFILE.cmd $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+rm -f $TMPFILE.cmd
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi


2014-09-08 23:14:06

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 22/25] tests: test recovery from an external journal

Add a couple of tests to verify that writing to and recovering from
an external journal work properly.

Signed-off-by: Darrick J. Wong <[email protected]>
---
tests/j_ext_long_revoke_trans/expect | 91 ++++++++++++++++++++++++++++++
tests/j_ext_long_revoke_trans/name | 1
tests/j_ext_long_revoke_trans/script | 77 +++++++++++++++++++++++++
tests/j_ext_long_trans/expect | 104 ++++++++++++++++++++++++++++++++++
tests/j_ext_long_trans/name | 1
tests/j_ext_long_trans/script | 74 ++++++++++++++++++++++++
6 files changed, 348 insertions(+)
create mode 100644 tests/j_ext_long_revoke_trans/expect
create mode 100644 tests/j_ext_long_revoke_trans/name
create mode 100644 tests/j_ext_long_revoke_trans/script
create mode 100644 tests/j_ext_long_trans/expect
create mode 100644 tests/j_ext_long_trans/name
create mode 100644 tests/j_ext_long_trans/script


diff --git a/tests/j_ext_long_revoke_trans/expect b/tests/j_ext_long_revoke_trans/expect
new file mode 100644
index 0000000..ed19872
--- /dev/null
+++ b/tests/j_ext_long_revoke_trans/expect
@@ -0,0 +1,91 @@
+Creating filesystem with 262144 1k blocks and 0 inodes
+Superblock backups stored on blocks:
+
+Zeroing journal device: 
+Creating filesystem with 262144 1k blocks and 16384 inodes
+Superblock backups stored on blocks:
+ 8193, 24577, 40961, 57345, 73729, 204801, 221185
+
+Allocating group tables: done
+Writing inode tables: done
+Writing superblocks and filesystem accounting information: done
+
+debugfs add journal device/UUID
+debugfs: feature has_journal
+Filesystem features: has_journal ext_attr resize_inode dir_index filetype extent flex_bg sparse_super huge_file uninit_bg dir_nlink extra_isize
+debugfs: ssv journal_dev 0x9999
+debugfs: ssv journal_uuid 1db3f677-6832-4adb-bafc-8e4059c30a34
+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/16384 files (0.0% non-contiguous), 6239/262144 blocks
+Exit status is 0
+debugfs write journal
+debugfs: logdump -c
+Ext2 superblock header found.
+Journal starts at block 3, transaction 1
+Found expected sequence 1, type 1 (descriptor block) at block 3
+Found expected sequence 1, type 1 (descriptor block) at block 128
+Found expected sequence 1, type 1 (descriptor block) at block 253
+Found expected sequence 1, type 1 (descriptor block) at block 378
+Found expected sequence 1, type 1 (descriptor block) at block 503
+Found expected sequence 1, type 1 (descriptor block) at block 628
+Found expected sequence 1, type 1 (descriptor block) at block 753
+Found expected sequence 1, type 1 (descriptor block) at block 878
+Found expected sequence 1, type 1 (descriptor block) at block 1003
+Found expected sequence 1, type 1 (descriptor block) at block 1128
+Found expected sequence 1, type 1 (descriptor block) at block 1253
+Found expected sequence 1, type 1 (descriptor block) at block 1378
+Found expected sequence 1, type 1 (descriptor block) at block 1503
+Found expected sequence 1, type 1 (descriptor block) at block 1628
+Found expected sequence 1, type 1 (descriptor block) at block 1753
+Found expected sequence 1, type 1 (descriptor block) at block 1878
+Found expected sequence 1, type 1 (descriptor block) at block 2003
+Found expected sequence 1, type 1 (descriptor block) at block 2128
+Found expected sequence 1, type 1 (descriptor block) at block 2253
+Found expected sequence 1, type 1 (descriptor block) at block 2378
+Found expected sequence 1, type 1 (descriptor block) at block 2503
+Found expected sequence 1, type 1 (descriptor block) at block 2628
+Found expected sequence 1, type 1 (descriptor block) at block 2753
+Found expected sequence 1, type 1 (descriptor block) at block 2878
+Found expected sequence 1, type 1 (descriptor block) at block 3003
+Found expected sequence 1, type 1 (descriptor block) at block 3128
+Found expected sequence 1, type 1 (descriptor block) at block 3253
+Found expected sequence 1, type 1 (descriptor block) at block 3378
+Found expected sequence 1, type 1 (descriptor block) at block 3503
+Found expected sequence 1, type 1 (descriptor block) at block 3628
+Found expected sequence 1, type 1 (descriptor block) at block 3753
+Found expected sequence 1, type 1 (descriptor block) at block 3878
+Found expected sequence 1, type 1 (descriptor block) at block 4003
+Found expected sequence 1, type 1 (descriptor block) at block 4128
+Found expected sequence 1, type 2 (commit block) at block 4135
+Found expected sequence 2, type 5 (revoke table) at block 4136
+Found expected sequence 2, type 5 (revoke table) at block 4137
+Found expected sequence 2, type 5 (revoke table) at block 4138
+Found expected sequence 2, type 5 (revoke table) at block 4139
+Found expected sequence 2, type 5 (revoke table) at block 4140
+Found expected sequence 2, type 5 (revoke table) at block 4141
+Found expected sequence 2, type 5 (revoke table) at block 4142
+Found expected sequence 2, type 5 (revoke table) at block 4143
+Found expected sequence 2, type 5 (revoke table) at block 4144
+Found expected sequence 2, type 5 (revoke table) at block 4145
+Found expected sequence 2, type 5 (revoke table) at block 4146
+Found expected sequence 2, type 5 (revoke table) at block 4147
+Found expected sequence 2, type 5 (revoke table) at block 4148
+Found expected sequence 2, type 5 (revoke table) at block 4149
+Found expected sequence 2, type 5 (revoke table) at block 4150
+Found expected sequence 2, type 5 (revoke table) at block 4151
+Found expected sequence 2, type 5 (revoke table) at block 4152
+Found expected sequence 2, type 2 (commit block) at block 4153
+No magic number at block 4154: end of journal.
+debugfs fsck
+test_filesys: recovering journal
+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/16384 files (0.0% non-contiguous), 6239/262144 blocks
+Exit status is 0
diff --git a/tests/j_ext_long_revoke_trans/name b/tests/j_ext_long_revoke_trans/name
new file mode 100644
index 0000000..777010d
--- /dev/null
+++ b/tests/j_ext_long_revoke_trans/name
@@ -0,0 +1 @@
+revoked transaction nuking free space w/ ext. journal
diff --git a/tests/j_ext_long_revoke_trans/script b/tests/j_ext_long_revoke_trans/script
new file mode 100644
index 0000000..4a60850
--- /dev/null
+++ b/tests/j_ext_long_revoke_trans/script
@@ -0,0 +1,77 @@
+if test -x $DEBUGFS_EXE; then
+
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+JNLFILE=$TMPFILE.jnl
+
+touch $JNLFILE
+$MKE2FS -F -o Linux -b 1024 -O journal_dev -T ext4 -U 1db3f677-6832-4adb-bafc-8e4059c30a34 $JNLFILE 262144 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT 2>&1
+$MKE2FS -F -o Linux -b 1024 -O ^has_journal -T ext4 $TMPFILE 262144 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT 2>&1
+
+echo "debugfs add journal device/UUID" >> $OUT
+$DEBUGFS -w -f - $TMPFILE <<- EOF >> $OUT.new 2>&1
+ feature has_journal
+ ssv journal_dev 0x9999
+ ssv journal_uuid 1db3f677-6832-4adb-bafc-8e4059c30a34
+EOF
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+$FSCK -fy -N test_filesys -j $JNLFILE $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+echo "debugfs write journal" >> $OUT
+echo "jo -f $JNLFILE" > $TMPFILE.cmd
+echo "jw -b 259-4356 /dev/zero" >> $TMPFILE.cmd
+echo "jc" >> $TMPFILE.cmd
+echo "jo -f $JNLFILE" >> $TMPFILE.cmd
+echo "jw -r 259-4356 /dev/zero" >> $TMPFILE.cmd
+echo "jc" >> $TMPFILE.cmd
+$DEBUGFS_EXE -w $TMPFILE -f $TMPFILE.cmd 2>> $OUT.new > /dev/null
+sed -f $cmd_dir/filter.sed < $OUT.new >> $OUT
+rm -rf $OUT.new
+
+test -d "$JOURNAL_DUMP_DIR" -a -w "$JOURNAL_DUMP_DIR" && cp "$TMPFILE" "$JOURNAL_DUMP_DIR/$test_name.img"
+test -d "$JOURNAL_DUMP_DIR" -a -w "$JOURNAL_DUMP_DIR" && cp "$JNLFILE" "$JOURNAL_DUMP_DIR/$test_name.img.jnl"
+echo "logdump -c -f $JNLFILE" > $TMPFILE.cmd
+$DEBUGFS_EXE $TMPFILE -f $TMPFILE.cmd 2>&1 | sed -f $cmd_dir/filter.sed -e 's/logdump -c -f.*/logdump -c/g' >> $OUT
+rm -rf $TMPFILE.cmd
+
+echo "debugfs fsck" >> $OUT
+$FSCK -fy -N test_filesys -j $JNLFILE $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+rm -f $TMPFILE $JNLFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP JNLFILE
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi
diff --git a/tests/j_ext_long_trans/expect b/tests/j_ext_long_trans/expect
new file mode 100644
index 0000000..d379610
--- /dev/null
+++ b/tests/j_ext_long_trans/expect
@@ -0,0 +1,104 @@
+Creating filesystem with 262144 1k blocks and 0 inodes
+Superblock backups stored on blocks:
+
+Zeroing journal device: 
+Creating filesystem with 262144 1k blocks and 16384 inodes
+Superblock backups stored on blocks:
+ 8193, 24577, 40961, 57345, 73729, 204801, 221185
+
+Allocating group tables: done
+Writing inode tables: done
+Writing superblocks and filesystem accounting information: done
+
+debugfs add journal device/UUID
+debugfs: feature has_journal
+Filesystem features: has_journal ext_attr resize_inode dir_index filetype extent flex_bg sparse_super huge_file uninit_bg dir_nlink extra_isize
+debugfs: ssv journal_dev 0x9999
+debugfs: ssv journal_uuid 1db3f677-6832-4adb-bafc-8e4059c30a34
+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/16384 files (0.0% non-contiguous), 6239/262144 blocks
+Exit status is 0
+debugfs write journal
+debugfs: logdump -c
+Ext2 superblock header found.
+Journal starts at block 3, transaction 1
+Found expected sequence 1, type 1 (descriptor block) at block 3
+Found expected sequence 1, type 1 (descriptor block) at block 128
+Found expected sequence 1, type 1 (descriptor block) at block 253
+Found expected sequence 1, type 1 (descriptor block) at block 378
+Found expected sequence 1, type 1 (descriptor block) at block 503
+Found expected sequence 1, type 1 (descriptor block) at block 628
+Found expected sequence 1, type 1 (descriptor block) at block 753
+Found expected sequence 1, type 1 (descriptor block) at block 878
+Found expected sequence 1, type 1 (descriptor block) at block 1003
+Found expected sequence 1, type 1 (descriptor block) at block 1128
+Found expected sequence 1, type 1 (descriptor block) at block 1253
+Found expected sequence 1, type 1 (descriptor block) at block 1378
+Found expected sequence 1, type 1 (descriptor block) at block 1503
+Found expected sequence 1, type 1 (descriptor block) at block 1628
+Found expected sequence 1, type 1 (descriptor block) at block 1753
+Found expected sequence 1, type 1 (descriptor block) at block 1878
+Found expected sequence 1, type 1 (descriptor block) at block 2003
+Found expected sequence 1, type 1 (descriptor block) at block 2128
+Found expected sequence 1, type 1 (descriptor block) at block 2253
+Found expected sequence 1, type 1 (descriptor block) at block 2378
+Found expected sequence 1, type 1 (descriptor block) at block 2503
+Found expected sequence 1, type 1 (descriptor block) at block 2628
+Found expected sequence 1, type 1 (descriptor block) at block 2753
+Found expected sequence 1, type 1 (descriptor block) at block 2878
+Found expected sequence 1, type 1 (descriptor block) at block 3003
+Found expected sequence 1, type 1 (descriptor block) at block 3128
+Found expected sequence 1, type 1 (descriptor block) at block 3253
+Found expected sequence 1, type 1 (descriptor block) at block 3378
+Found expected sequence 1, type 1 (descriptor block) at block 3503
+Found expected sequence 1, type 1 (descriptor block) at block 3628
+Found expected sequence 1, type 1 (descriptor block) at block 3753
+Found expected sequence 1, type 1 (descriptor block) at block 3878
+Found expected sequence 1, type 1 (descriptor block) at block 4003
+Found expected sequence 1, type 1 (descriptor block) at block 4128
+Found expected sequence 1, type 2 (commit block) at block 4135
+No magic number at block 4136: end of journal.
+debugfs fsck
+test_filesys: recovering journal
+Resize inode not valid. Recreate? yes
+
+Pass 1: Checking inodes, blocks, and sizes
+Root inode is not a directory. Clear? yes
+
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Root inode not allocated. Allocate? yes
+
+/lost+found not found. Create? yes
+
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+Block bitmap differences: +(1--259) +275 +(291--418) +2341
+Fix? yes
+
+Free blocks count wrong for group #0 (5838, counted=5851).
+Fix? yes
+
+Free blocks count wrong (255903, counted=255916).
+Fix? yes
+
+Inode bitmap differences: +1 +(3--10)
+Fix? yes
+
+Free inodes count wrong for group #0 (500, counted=501).
+Fix? yes
+
+Directories count wrong for group #0 (3, counted=2).
+Fix? yes
+
+Free inodes count wrong (16372, counted=16373).
+Fix? yes
+
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 11/16384 files (0.0% non-contiguous), 6228/262144 blocks
+Exit status is 1
diff --git a/tests/j_ext_long_trans/name b/tests/j_ext_long_trans/name
new file mode 100644
index 0000000..8ae5722
--- /dev/null
+++ b/tests/j_ext_long_trans/name
@@ -0,0 +1 @@
+transaction nuking free space w/ ext. journal
diff --git a/tests/j_ext_long_trans/script b/tests/j_ext_long_trans/script
new file mode 100644
index 0000000..c02f791
--- /dev/null
+++ b/tests/j_ext_long_trans/script
@@ -0,0 +1,74 @@
+if test -x $DEBUGFS_EXE; then
+
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+JNLFILE=$TMPFILE.jnl
+
+touch $JNLFILE
+$MKE2FS -F -o Linux -b 1024 -O journal_dev -T ext4 -U 1db3f677-6832-4adb-bafc-8e4059c30a34 $JNLFILE 262144 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT 2>&1
+$MKE2FS -F -o Linux -b 1024 -O ^has_journal -T ext4 $TMPFILE 262144 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT 2>&1
+
+echo "debugfs add journal device/UUID" >> $OUT
+$DEBUGFS -w -f - $TMPFILE <<- EOF >> $OUT.new 2>&1
+ feature has_journal
+ ssv journal_dev 0x9999
+ ssv journal_uuid 1db3f677-6832-4adb-bafc-8e4059c30a34
+EOF
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+$FSCK -fy -N test_filesys -j $JNLFILE $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+echo "debugfs write journal" >> $OUT
+echo "jo -f $JNLFILE" > $TMPFILE.cmd
+echo "jw -b 259-4356 /dev/zero" >> $TMPFILE.cmd
+echo "jc" >> $TMPFILE.cmd
+$DEBUGFS_EXE -w $TMPFILE -f $TMPFILE.cmd 2>> $OUT.new > /dev/null
+sed -f $cmd_dir/filter.sed < $OUT.new >> $OUT
+rm -rf $OUT.new
+
+test -d "$JOURNAL_DUMP_DIR" -a -w "$JOURNAL_DUMP_DIR" && cp "$TMPFILE" "$JOURNAL_DUMP_DIR/$test_name.img"
+test -d "$JOURNAL_DUMP_DIR" -a -w "$JOURNAL_DUMP_DIR" && cp "$JNLFILE" "$JOURNAL_DUMP_DIR/$test_name.img.jnl"
+echo "logdump -c -f $JNLFILE" > $TMPFILE.cmd
+$DEBUGFS_EXE $TMPFILE -f $TMPFILE.cmd 2>&1 | sed -f $cmd_dir/filter.sed -e 's/logdump -c -f.*/logdump -c/g' >> $OUT
+rm -rf $TMPFILE.cmd
+
+echo "debugfs fsck" >> $OUT
+$FSCK -fy -N test_filesys -j $JNLFILE $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+rm -f $TMPFILE $JNLFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP JNLFILE
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi


2014-09-08 23:14:14

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 23/25] ext2fs: add readahead method to improve scanning

Frøm: Andreas Dilger <[email protected]>

Add a readahead method for prefetching ranges of disk blocks. This is
useful for inode table scanning, and other large contiguous ranges of
blocks, and may also prove useful for random block prefetch, since it
will allow reordering of the IO without waiting synchronously for the
reads to complete.

It is currently using the posix_fadvise(POSIX_FADV_WILLNEED)
interface, as this proved most efficient during our testing.

[[email protected]]
Make the arguments to the readahead function take the same ULL values
as the other IO functions, and return an appropriate error code when
fadvise isn't available.

Signed-off-by: Andreas Dilger <[email protected]>
Signed-off-by: Darrick J. Wong <[email protected]>
---
lib/ext2fs/ext2_io.h | 8 +++++++-
lib/ext2fs/io_manager.c | 9 +++++++++
lib/ext2fs/unix_io.c | 27 ++++++++++++++++++++++++---
3 files changed, 40 insertions(+), 4 deletions(-)


diff --git a/lib/ext2fs/ext2_io.h b/lib/ext2fs/ext2_io.h
index 1894fb8..4c5a5c5 100644
--- a/lib/ext2fs/ext2_io.h
+++ b/lib/ext2fs/ext2_io.h
@@ -90,7 +90,10 @@ struct struct_io_manager {
int count, const void *data);
errcode_t (*discard)(io_channel channel, unsigned long long block,
unsigned long long count);
- long reserved[16];
+ errcode_t (*cache_readahead)(io_channel channel,
+ unsigned long long block,
+ unsigned long long count);
+ long reserved[15];
};

#define IO_FLAG_RW 0x0001
@@ -124,6 +127,9 @@ extern errcode_t io_channel_discard(io_channel channel,
unsigned long long count);
extern errcode_t io_channel_alloc_buf(io_channel channel,
int count, void *ptr);
+extern errcode_t io_channel_cache_readahead(io_channel io,
+ unsigned long long block,
+ unsigned long long count);

/* unix_io.c */
extern io_manager unix_io_manager;
diff --git a/lib/ext2fs/io_manager.c b/lib/ext2fs/io_manager.c
index 34e4859..dc5888d 100644
--- a/lib/ext2fs/io_manager.c
+++ b/lib/ext2fs/io_manager.c
@@ -128,3 +128,12 @@ errcode_t io_channel_alloc_buf(io_channel io, int count, void *ptr)
else
return ext2fs_get_mem(size, ptr);
}
+
+errcode_t io_channel_cache_readahead(io_channel io, unsigned long long block,
+ unsigned long long count)
+{
+ if (!io->manager->cache_readahead)
+ return EXT2_ET_OP_NOT_SUPPORTED;
+
+ return io->manager->cache_readahead(io, block, count);
+}
diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c
index eb39b28..189adce 100644
--- a/lib/ext2fs/unix_io.c
+++ b/lib/ext2fs/unix_io.c
@@ -15,6 +15,9 @@
* %End-Header%
*/

+#define _XOPEN_SOURCE 600
+#define _DARWIN_C_SOURCE
+#define _FILE_OFFSET_BITS 64
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#ifndef _GNU_SOURCE
@@ -35,6 +38,9 @@
#ifdef __linux__
#include <sys/utsname.h>
#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
@@ -44,9 +50,6 @@
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
#if HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
@@ -830,6 +833,23 @@ static errcode_t unix_write_blk64(io_channel channel, unsigned long long block,
#endif /* NO_IO_CACHE */
}

+static errcode_t unix_cache_readahead(io_channel channel,
+ unsigned long long block,
+ unsigned long long count)
+{
+#ifdef POSIX_FADV_WILLNEED
+ struct unix_private_data *data;
+
+ data = (struct unix_private_data *)channel->private_data;
+ return posix_fadvise(data->dev,
+ (ext2_loff_t)block * channel->block_size,
+ (ext2_loff_t)count * channel->block_size,
+ POSIX_FADV_WILLNEED);
+#else
+ return EXT2_ET_OP_NOT_SUPPORTED;
+#endif
+}
+
static errcode_t unix_write_blk(io_channel channel, unsigned long block,
int count, const void *buf)
{
@@ -981,6 +1001,7 @@ static struct struct_io_manager struct_unix_manager = {
.read_blk64 = unix_read_blk64,
.write_blk64 = unix_write_blk64,
.discard = unix_discard,
+ .cache_readahead = unix_cache_readahead,
};

io_manager unix_io_manager = &struct_unix_manager;

2014-09-08 23:14:20

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 24/25] libext2fs/e2fsck: provide routines to read-ahead metadata

This patch adds to e2fsck the ability to pre-fetch metadata into the
page cache in the hopes of speeding up fsck runs. There are two new
functions -- the first allows a caller to readahead a list of blocks,
and the second is a helper function that uses that first mechanism to
load group data (bitmaps, inode tables).

These new e2fsck routines require the addition of a dblist API to
allow us to iterate a subset of a dblist. This will enable
incremental directory block readahead in e2fsck pass 2.

There's also a function to estimate the readahead given a FS.

v2: Add an API to create a dblist with a given number of list elements
pre-allocated. This enables us to save ~2ms per call to
e2fsck_readahead() (assuming a 2MB RA buffer) by not having to
repeatedly call ext2_resize_mem as we add blocks to the list.

Signed-off-by: Darrick J. Wong <[email protected]>
---
configure | 2
configure.in | 1
e2fsck/Makefile.in | 8 +-
e2fsck/e2fsck.h | 18 ++++
e2fsck/readahead.c | 252 +++++++++++++++++++++++++++++++++++++++++++++++++++
e2fsck/util.c | 51 ++++++++++
lib/config.h.in | 3 +
lib/ext2fs/dblist.c | 21 ++++
lib/ext2fs/ext2fs.h | 10 ++
9 files changed, 358 insertions(+), 8 deletions(-)
create mode 100644 e2fsck/readahead.c


diff --git a/configure b/configure
index 65449c9..0ea5fc5 100755
--- a/configure
+++ b/configure
@@ -12404,7 +12404,7 @@ fi
done

fi
-for ac_header in dirent.h errno.h execinfo.h getopt.h malloc.h mntent.h paths.h semaphore.h setjmp.h signal.h stdarg.h stdint.h stdlib.h termios.h termio.h unistd.h utime.h attr/xattr.h linux/falloc.h linux/fd.h linux/major.h linux/loop.h net/if_dl.h netinet/in.h sys/disklabel.h sys/disk.h sys/file.h sys/ioctl.h sys/mkdev.h sys/mman.h sys/mount.h sys/prctl.h sys/resource.h sys/select.h sys/socket.h sys/sockio.h sys/stat.h sys/syscall.h sys/sysmacros.h sys/time.h sys/types.h sys/un.h sys/wait.h
+for ac_header in dirent.h errno.h execinfo.h getopt.h malloc.h mntent.h paths.h semaphore.h setjmp.h signal.h stdarg.h stdint.h stdlib.h termios.h termio.h unistd.h utime.h attr/xattr.h linux/falloc.h linux/fd.h linux/major.h linux/loop.h net/if_dl.h netinet/in.h sys/disklabel.h sys/disk.h sys/file.h sys/ioctl.h sys/mkdev.h sys/mman.h sys/mount.h sys/prctl.h sys/resource.h sys/select.h sys/socket.h sys/sockio.h sys/stat.h sys/syscall.h sys/sysctl.h sys/sysmacros.h sys/time.h sys/types.h sys/un.h sys/wait.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
diff --git a/configure.in b/configure.in
index 97a58c5..5106f96 100644
--- a/configure.in
+++ b/configure.in
@@ -941,6 +941,7 @@ AC_CHECK_HEADERS(m4_flatten([
sys/sockio.h
sys/stat.h
sys/syscall.h
+ sys/sysctl.h
sys/sysmacros.h
sys/time.h
sys/types.h
diff --git a/e2fsck/Makefile.in b/e2fsck/Makefile.in
index c40b188..5b1a37e 100644
--- a/e2fsck/Makefile.in
+++ b/e2fsck/Makefile.in
@@ -62,7 +62,7 @@ OBJS= dict.o unix.o e2fsck.o super.o pass1.o pass1b.o pass2.o \
pass3.o pass4.o pass5.o journal.o badblocks.o util.o dirinfo.o \
dx_dirinfo.o ehandler.o problem.o message.o quota.o recovery.o \
region.o revoke.o ea_refcount.o rehash.o profile.o prof_err.o \
- logfile.o sigcatcher.o $(MTRACE_OBJ)
+ logfile.o sigcatcher.o readahead.o $(MTRACE_OBJ)

PROFILED_OBJS= profiled/dict.o profiled/unix.o profiled/e2fsck.o \
profiled/super.o profiled/pass1.o profiled/pass1b.o \
@@ -73,7 +73,7 @@ PROFILED_OBJS= profiled/dict.o profiled/unix.o profiled/e2fsck.o \
profiled/recovery.o profiled/region.o profiled/revoke.o \
profiled/ea_refcount.o profiled/rehash.o profiled/profile.o \
profiled/prof_err.o profiled/logfile.o \
- profiled/sigcatcher.o
+ profiled/sigcatcher.o profiled/readahead.o

SRCS= $(srcdir)/e2fsck.c \
$(srcdir)/dict.c \
@@ -97,6 +97,7 @@ SRCS= $(srcdir)/e2fsck.c \
$(srcdir)/message.c \
$(srcdir)/ea_refcount.c \
$(srcdir)/rehash.c \
+ $(srcdir)/readahead.c \
$(srcdir)/region.c \
$(srcdir)/profile.c \
$(srcdir)/sigcatcher.c \
@@ -527,3 +528,6 @@ quota.o: $(srcdir)/quota.c $(top_builddir)/lib/config.h \
$(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/quotaio.h \
$(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \
$(top_srcdir)/lib/../e2fsck/dict.h $(srcdir)/problem.h
+readahead.o: $(srcdir)/readahead.c $(top_builddir)/lib/config.h \
+ $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/e2fsck.h prof_err.h
diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h
index 8f16218..ead546e 100644
--- a/e2fsck/e2fsck.h
+++ b/e2fsck/e2fsck.h
@@ -490,6 +490,23 @@ extern ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix);
extern errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino,
int adj);

+/* readahead.c */
+#define E2FSCK_READA_SUPER (0x01)
+#define E2FSCK_READA_GDT (0x02)
+#define E2FSCK_READA_BBITMAP (0x04)
+#define E2FSCK_READA_IBITMAP (0x08)
+#define E2FSCK_READA_ITABLE (0x10)
+#define E2FSCK_READA_ALL_FLAGS (0x1F)
+errcode_t e2fsck_readahead(ext2_filsys fs, int flags, dgrp_t start,
+ dgrp_t ngroups);
+#define E2FSCK_RA_DBLIST_IGNORE_BLOCKCNT (0x01)
+#define E2FSCK_RA_DBLIST_ALL_FLAGS (0x01)
+errcode_t e2fsck_readahead_dblist(ext2_filsys fs, int flags,
+ ext2_dblist dblist,
+ unsigned long long start,
+ unsigned long long count);
+int e2fsck_can_readahead(ext2_filsys fs);
+unsigned long long e2fsck_guess_readahead(ext2_filsys fs);

/* region.c */
extern region_t region_create(region_addr_t min, region_addr_t max);
@@ -579,6 +596,7 @@ extern errcode_t e2fsck_allocate_subcluster_bitmap(ext2_filsys fs,
int default_type,
const char *profile_name,
ext2fs_block_bitmap *ret);
+unsigned long long get_memory_size(void);

/* unix.c */
extern void e2fsck_clear_progbar(e2fsck_t ctx);
diff --git a/e2fsck/readahead.c b/e2fsck/readahead.c
new file mode 100644
index 0000000..a35f9f8
--- /dev/null
+++ b/e2fsck/readahead.c
@@ -0,0 +1,252 @@
+/*
+ * readahead.c -- Prefetch filesystem metadata to speed up fsck.
+ *
+ * Copyright (C) 2014 Oracle.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Library
+ * General Public License, version 2.
+ * %End-Header%
+ */
+
+#include "config.h"
+#include <string.h>
+
+#include "e2fsck.h"
+
+#undef DEBUG
+
+#ifdef DEBUG
+# define dbg_printf(f, a...) do {printf(f, ## a); fflush(stdout); } while (0)
+#else
+# define dbg_printf(f, a...)
+#endif
+
+struct read_dblist {
+ errcode_t err;
+ blk64_t run_start;
+ blk64_t run_len;
+ int flags;
+};
+
+static int readahead_dir_block(ext2_filsys fs, struct ext2_db_entry2 *db,
+ void *priv_data)
+{
+ struct read_dblist *pr = priv_data;
+ e2_blkcnt_t count = (pr->flags & E2FSCK_RA_DBLIST_IGNORE_BLOCKCNT ?
+ 1 : db->blockcnt);
+
+ if (!pr->run_len || db->blk != pr->run_start + pr->run_len) {
+ if (pr->run_len) {
+ pr->err = io_channel_cache_readahead(fs->io,
+ pr->run_start,
+ pr->run_len);
+ dbg_printf("readahead start=%llu len=%llu err=%d\n",
+ pr->run_start, pr->run_len,
+ (int)pr->err);
+ }
+ pr->run_start = db->blk;
+ pr->run_len = 0;
+ }
+ pr->run_len += count;
+
+ return pr->err ? DBLIST_ABORT : 0;
+}
+
+errcode_t e2fsck_readahead_dblist(ext2_filsys fs, int flags,
+ ext2_dblist dblist,
+ unsigned long long start,
+ unsigned long long count)
+{
+ errcode_t err;
+ struct read_dblist pr;
+
+ dbg_printf("%s: flags=0x%x\n", __func__, flags);
+ if (flags & ~E2FSCK_RA_DBLIST_ALL_FLAGS)
+ return EXT2_ET_INVALID_ARGUMENT;
+
+ memset(&pr, 0, sizeof(pr));
+ pr.flags = flags;
+ err = ext2fs_dblist_iterate3(dblist, readahead_dir_block, start,
+ count, &pr);
+ if (pr.err)
+ return pr.err;
+ if (err)
+ return err;
+
+ if (pr.run_len)
+ err = io_channel_cache_readahead(fs->io, pr.run_start,
+ pr.run_len);
+
+ return err;
+}
+
+static errcode_t e2fsck_readahead_bitmap(ext2_filsys fs,
+ ext2fs_block_bitmap ra_map)
+{
+ blk64_t start, end, out;
+ errcode_t err;
+
+ start = 1;
+ end = ext2fs_blocks_count(fs->super) - 1;
+
+ err = ext2fs_find_first_set_block_bitmap2(ra_map, start, end, &out);
+ while (err == 0) {
+ start = out;
+ err = ext2fs_find_first_zero_block_bitmap2(ra_map, start, end,
+ &out);
+ if (err == ENOENT) {
+ out = end;
+ err = 0;
+ } else if (err)
+ break;
+
+ err = io_channel_cache_readahead(fs->io, start, out - start);
+ if (err)
+ break;
+ start = out;
+ err = ext2fs_find_first_set_block_bitmap2(ra_map, start, end,
+ &out);
+ }
+
+ if (err == ENOENT)
+ err = 0;
+
+ return err;
+}
+
+/* Try not to spew bitmap range errors for readahead */
+static errcode_t mark_bmap_range(ext2_filsys fs, ext2fs_block_bitmap map,
+ blk64_t blk, unsigned int num)
+{
+ if (blk >= ext2fs_get_generic_bmap_start(map) &&
+ blk + num <= ext2fs_get_generic_bmap_end(map))
+ ext2fs_mark_block_bitmap_range2(map, blk, num);
+ else
+ return EXT2_ET_INVALID_ARGUMENT;
+ return 0;
+}
+
+static errcode_t mark_bmap(ext2_filsys fs, ext2fs_block_bitmap map, blk64_t blk)
+{
+ if (blk >= ext2fs_get_generic_bmap_start(map) &&
+ blk <= ext2fs_get_generic_bmap_end(map))
+ ext2fs_mark_block_bitmap2(map, blk);
+ else
+ return EXT2_ET_INVALID_ARGUMENT;
+ return 0;
+}
+
+errcode_t e2fsck_readahead(ext2_filsys fs, int flags, dgrp_t start,
+ dgrp_t ngroups)
+{
+ blk64_t super, old_gdt, new_gdt;
+ blk_t blocks;
+ dgrp_t i;
+ ext2fs_block_bitmap ra_map = NULL;
+ dgrp_t end = start + ngroups;
+ errcode_t err = 0;
+
+ dbg_printf("%s: flags=0x%x start=%d groups=%d\n", __func__, flags,
+ start, ngroups);
+ if (flags & ~E2FSCK_READA_ALL_FLAGS)
+ return EXT2_ET_INVALID_ARGUMENT;
+
+ if (end > fs->group_desc_count)
+ end = fs->group_desc_count;
+
+ if (flags == 0)
+ return 0;
+
+ err = ext2fs_allocate_block_bitmap(fs, "readahead bitmap",
+ &ra_map);
+ if (err)
+ return err;
+
+ for (i = start; i < end; i++) {
+ err = ext2fs_super_and_bgd_loc2(fs, i, &super, &old_gdt,
+ &new_gdt, &blocks);
+ if (err)
+ break;
+
+ if (flags & E2FSCK_READA_SUPER) {
+ err = mark_bmap(fs, ra_map, super);
+ if (err)
+ break;
+ }
+
+ if (flags & E2FSCK_READA_GDT) {
+ err = mark_bmap_range(fs, ra_map,
+ old_gdt ? old_gdt : new_gdt,
+ blocks);
+ if (err)
+ break;
+ }
+
+ if ((flags & E2FSCK_READA_BBITMAP) &&
+ !ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT) &&
+ ext2fs_bg_free_blocks_count(fs, i) <
+ fs->super->s_blocks_per_group) {
+ super = ext2fs_block_bitmap_loc(fs, i);
+ err = mark_bmap(fs, ra_map, super);
+ if (err)
+ break;
+ }
+
+ if ((flags & E2FSCK_READA_IBITMAP) &&
+ !ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT) &&
+ ext2fs_bg_free_inodes_count(fs, i) <
+ fs->super->s_inodes_per_group) {
+ super = ext2fs_inode_bitmap_loc(fs, i);
+ err = mark_bmap(fs, ra_map, super);
+ if (err)
+ break;
+ }
+
+ if ((flags & E2FSCK_READA_ITABLE) &&
+ ext2fs_bg_free_inodes_count(fs, i) <
+ fs->super->s_inodes_per_group) {
+ super = ext2fs_inode_table_loc(fs, i);
+ blocks = fs->inode_blocks_per_group -
+ (ext2fs_bg_itable_unused(fs, i) *
+ EXT2_INODE_SIZE(fs->super) / fs->blocksize);
+ err = mark_bmap_range(fs, ra_map, super, blocks);
+ if (err)
+ break;
+ }
+ }
+
+ if (!err)
+ err = e2fsck_readahead_bitmap(fs, ra_map);
+
+ ext2fs_free_block_bitmap(ra_map);
+ return err;
+}
+
+int e2fsck_can_readahead(ext2_filsys fs)
+{
+ errcode_t err;
+
+ err = io_channel_cache_readahead(fs->io, 0, 1);
+ dbg_printf("%s: supp=%d\n", __func__, err != EXT2_ET_OP_NOT_SUPPORTED);
+ return err != EXT2_ET_OP_NOT_SUPPORTED;
+}
+
+unsigned long long e2fsck_guess_readahead(ext2_filsys fs)
+{
+ unsigned long long guess;
+
+ /*
+ * The optimal readahead sizes were experimentally determined by
+ * djwong in August 2014. Setting the RA size to one block group's
+ * worth of inode table blocks seems to yield the largest reductions
+ * in e2fsck runtime.
+ */
+ guess = fs->blocksize * fs->inode_blocks_per_group;
+
+ /* Disable RA if it'd use more 1/100th of RAM. */
+ if (get_memory_size() > (guess * 100))
+ return guess / 1024;
+
+ return 0;
+}
diff --git a/e2fsck/util.c b/e2fsck/util.c
index 8237328..74f20062 100644
--- a/e2fsck/util.c
+++ b/e2fsck/util.c
@@ -37,6 +37,10 @@
#include <errno.h>
#endif

+#ifdef HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
+
#include "e2fsck.h"

extern e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */
@@ -848,3 +852,50 @@ errcode_t e2fsck_allocate_subcluster_bitmap(ext2_filsys fs, const char *descr,
fs->default_bitmap_type = save_type;
return retval;
}
+
+/* Return memory size in bytes */
+unsigned long long get_memory_size(void)
+{
+#if defined(_SC_PHYS_PAGES)
+# if defined(_SC_PAGESIZE)
+ return (unsigned long long)sysconf(_SC_PHYS_PAGES) *
+ (unsigned long long)sysconf(_SC_PAGESIZE);
+# elif defined(_SC_PAGE_SIZE)
+ return (unsigned long long)sysconf(_SC_PHYS_PAGES) *
+ (unsigned long long)sysconf(_SC_PAGE_SIZE);
+# endif
+#elif defined(CTL_HW)
+# if (defined(HW_MEMSIZE) || defined(HW_PHYSMEM64))
+# define CTL_HW_INT64
+# elif (defined(HW_PHYSMEM) || defined(HW_REALMEM))
+# define CTL_HW_UINT
+# endif
+ int mib[2];
+
+ mib[0] = CTL_HW;
+# if defined(HW_MEMSIZE)
+ mib[1] = HW_MEMSIZE;
+# elif defined(HW_PHYSMEM64)
+ mib[1] = HW_PHYSMEM64;
+# elif defined(HW_REALMEM)
+ mib[1] = HW_REALMEM;
+# elif defined(HW_PYSMEM)
+ mib[1] = HW_PHYSMEM;
+# endif
+# if defined(CTL_HW_INT64)
+ unsigned long long size = 0;
+# elif defined(CTL_HW_UINT)
+ unsigned int size = 0;
+# endif
+# if defined(CTL_HW_INT64) || defined(CTL_HW_UINT)
+ size_t len = sizeof(size);
+
+ if (sysctl(mib, 2, &size, &len, NULL, 0) == 0)
+ return (unsigned long long)size;
+# endif
+ return 0;
+#else
+# warning "Don't know how to detect memory on your platform?"
+ return 0;
+#endif
+}
diff --git a/lib/config.h.in b/lib/config.h.in
index 4dcc966..be8f976 100644
--- a/lib/config.h.in
+++ b/lib/config.h.in
@@ -506,6 +506,9 @@
/* Define to 1 if you have the <sys/syscall.h> header file. */
#undef HAVE_SYS_SYSCALL_H

+/* Define to 1 if you have the <sys/sysctl.h> header file. */
+#undef HAVE_SYS_SYSCTL_H
+
/* Define to 1 if you have the <sys/sysmacros.h> header file. */
#undef HAVE_SYS_SYSMACROS_H

diff --git a/lib/ext2fs/dblist.c b/lib/ext2fs/dblist.c
index 942c4f0..bbdb221 100644
--- a/lib/ext2fs/dblist.c
+++ b/lib/ext2fs/dblist.c
@@ -194,20 +194,25 @@ void ext2fs_dblist_sort2(ext2_dblist dblist,
/*
* This function iterates over the directory block list
*/
-errcode_t ext2fs_dblist_iterate2(ext2_dblist dblist,
+errcode_t ext2fs_dblist_iterate3(ext2_dblist dblist,
int (*func)(ext2_filsys fs,
struct ext2_db_entry2 *db_info,
void *priv_data),
+ unsigned long long start,
+ unsigned long long count,
void *priv_data)
{
- unsigned long long i;
+ unsigned long long i, end;
int ret;

EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);

+ end = start + count;
if (!dblist->sorted)
ext2fs_dblist_sort2(dblist, 0);
- for (i=0; i < dblist->count; i++) {
+ if (end > dblist->count)
+ end = dblist->count;
+ for (i = start; i < end; i++) {
ret = (*func)(dblist->fs, &dblist->list[i], priv_data);
if (ret & DBLIST_ABORT)
return 0;
@@ -215,6 +220,16 @@ errcode_t ext2fs_dblist_iterate2(ext2_dblist dblist,
return 0;
}

+errcode_t ext2fs_dblist_iterate2(ext2_dblist dblist,
+ int (*func)(ext2_filsys fs,
+ struct ext2_db_entry2 *db_info,
+ void *priv_data),
+ void *priv_data)
+{
+ return ext2fs_dblist_iterate3(dblist, func, 0, dblist->count,
+ priv_data);
+}
+
static EXT2_QSORT_TYPE dir_block_cmp2(const void *a, const void *b)
{
const struct ext2_db_entry2 *db_a =
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index d931fff..bba40ac 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -1055,11 +1055,17 @@ extern void ext2fs_dblist_sort2(ext2_dblist dblist,
extern errcode_t ext2fs_dblist_iterate(ext2_dblist dblist,
int (*func)(ext2_filsys fs, struct ext2_db_entry *db_info,
void *priv_data),
- void *priv_data);
+ void *priv_data);
extern errcode_t ext2fs_dblist_iterate2(ext2_dblist dblist,
int (*func)(ext2_filsys fs, struct ext2_db_entry2 *db_info,
void *priv_data),
- void *priv_data);
+ void *priv_data);
+extern errcode_t ext2fs_dblist_iterate3(ext2_dblist dblist,
+ int (*func)(ext2_filsys fs, struct ext2_db_entry2 *db_info,
+ void *priv_data),
+ unsigned long long start,
+ unsigned long long count,
+ void *priv_data);
extern errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ext2_ino_t ino,
blk_t blk, int blockcnt);
extern errcode_t ext2fs_set_dir_block2(ext2_dblist dblist, ext2_ino_t ino,


2014-09-08 23:14:26

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 25/25] e2fsck: read-ahead metadata during passes 1, 2, and 4

e2fsck pass1 is modified to use the block group data prefetch function
to try to fetch the inode tables into the pagecache before it is
needed. We iterate through the blockgroups until we have enough inode
tables that need reading such that we can issue readahead; then we sit
and wait until the last inode table block read of the last group to
start fetching the next bunch.

pass2 is modified to use the dirblock prefetching function to prefetch
the list of directory blocks that are assembled in pass1. We use the
"iterate a subset of a dblist" and avoid copying the dblist. Directory
blocks are fetched incrementally as we walk through the directory
block list. In previous iterations of this patch we would free the
directory blocks after processing, but the performance hit to e2fsck
itself wasn't worth it. Furthermore, it is anticipated that most
users will then mount the FS and start using the directories, so they
may as well remain in the page cache.

pass4 is modified to prefetch the block and inode bitmaps in
anticipation of pass 5, because pass4 is entirely CPU bound.

In general, these mechanisms can decrease fsck time by 10-40%, if the
host system has sufficient memory and the storage system can provide a
lot of IOPs. Pretty much any storage system capable of handling
multiple IOs in-flight at any time will see a fairly large performance
boost. (Single-issue USB mass storage disks seem to suffer badly.)

By default, the readahead buffer size will be set to the size of a block
group's inode table (which is 2MiB for a regular ext4 FS). The -E
readahead_kb= option can be given to specify the amount of memory to
use for readahead or zero to disable it entirely; or an option can be
given in e2fsck.conf.

v2: Fix an off-by-one error in the pass1 readahead which made the
readahead trigger one inode too late if the block groups are full.

Signed-off-by: Darrick J. Wong <[email protected]>
---
e2fsck/e2fsck.8.in | 7 +++++
e2fsck/e2fsck.conf.5.in | 15 +++++++++++
e2fsck/e2fsck.h | 3 ++
e2fsck/pass1.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++
e2fsck/pass2.c | 38 +++++++++++++++++++++++++++
e2fsck/pass4.c | 9 +++++++
e2fsck/unix.c | 28 ++++++++++++++++++++
lib/ext2fs/ext2fs.h | 1 +
lib/ext2fs/inode.c | 3 +-
9 files changed, 167 insertions(+), 2 deletions(-)


diff --git a/e2fsck/e2fsck.8.in b/e2fsck/e2fsck.8.in
index f5ed758..84ae50f 100644
--- a/e2fsck/e2fsck.8.in
+++ b/e2fsck/e2fsck.8.in
@@ -207,6 +207,13 @@ option may prevent you from further manual data recovery.
.BI nodiscard
Do not attempt to discard free blocks and unused inode blocks. This option is
exactly the opposite of discard option. This is set as default.
+.TP
+.BI readahead_kb
+Use this many KiB of memory to pre-fetch metadata in the hopes of reducing
+e2fsck runtime. By default, this is set to the size of a block group's inode
+table (typically 2MiB on a regular ext4 filesystem); if this amount is more
+than 1/100 of total physical memory, readahead is disabled. Set this to zero
+to disable readahead entirely.
.RE
.TP
.B \-f
diff --git a/e2fsck/e2fsck.conf.5.in b/e2fsck/e2fsck.conf.5.in
index 9ebfbbf..e1d0518 100644
--- a/e2fsck/e2fsck.conf.5.in
+++ b/e2fsck/e2fsck.conf.5.in
@@ -205,6 +205,21 @@ of that type are squelched. This can be useful if the console is slow
(i.e., connected to a serial port) and so a large amount of output could
end up delaying the boot process for a long time (potentially hours).
.TP
+.I readahead_mem_pct
+Use this percentage of memory to try to read in metadata blocks ahead of the
+main e2fsck thread. This should reduce run times, depending on the speed of
+the underlying storage and the amount of free memory. There is no default, but
+see
+.B readahead_mem_pct
+for more details.
+.TP
+.I readahead_kb
+Use this amount of memory to read in metadata blocks ahead of the main checking
+thread. Setting this value to zero disables readahead entirely. By default,
+this is set the size of one block group's inode table (typically 2MiB on a
+regular ext4 filesystem); if this amount is more than 1/100th of total physical
+memory, readahead is disabled.
+.TP
.I report_features
If this boolean relation is true, e2fsck will print the file system
features as part of its verbose reporting (i.e., if the
diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h
index ead546e..39aa353 100644
--- a/e2fsck/e2fsck.h
+++ b/e2fsck/e2fsck.h
@@ -378,6 +378,9 @@ struct e2fsck_struct {
*/
void *priv_data;
ext2fs_block_bitmap block_metadata_map; /* Metadata blocks */
+
+ /* How much are we allowed to readahead? */
+ unsigned long long readahead_kb;
};

/* Used by the region allocation code */
diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index 4fc5311..f09cddb 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -867,6 +867,60 @@ out:
return 0;
}

+static void pass1_readahead(e2fsck_t ctx, dgrp_t *group, ext2_ino_t *next_ino)
+{
+ ext2_ino_t inodes_in_group = 0, inodes_per_block, inodes_per_buffer;
+ dgrp_t start = *group, grp;
+ blk64_t blocks_to_read = 0;
+ errcode_t err = EXT2_ET_INVALID_ARGUMENT;
+
+ if (ctx->readahead_kb == 0)
+ goto out;
+
+ /* Keep iterating groups until we have enough to readahead */
+ inodes_per_block = EXT2_INODES_PER_BLOCK(ctx->fs->super);
+ for (grp = start; grp < ctx->fs->group_desc_count; grp++) {
+ if (ext2fs_bg_flags_test(ctx->fs, grp, EXT2_BG_INODE_UNINIT))
+ continue;
+ inodes_in_group = ctx->fs->super->s_inodes_per_group -
+ ext2fs_bg_itable_unused(ctx->fs, grp);
+ blocks_to_read += (inodes_in_group + inodes_per_block - 1) /
+ inodes_per_block;
+ if (blocks_to_read * ctx->fs->blocksize >
+ ctx->readahead_kb * 1024)
+ break;
+ }
+
+ err = e2fsck_readahead(ctx->fs, E2FSCK_READA_ITABLE, start,
+ grp - start + 1);
+ if (err == EAGAIN) {
+ ctx->readahead_kb /= 2;
+ err = 0;
+ }
+
+out:
+ if (err) {
+ /* Error; disable itable readahead */
+ *group = ctx->fs->group_desc_count;
+ *next_ino = ctx->fs->super->s_inodes_count;
+ } else {
+ /*
+ * Don't do more readahead until we've reached the first inode
+ * of the last inode scan buffer block for the last group.
+ */
+ *group = grp + 1;
+ inodes_per_buffer = (ctx->inode_buffer_blocks ?
+ ctx->inode_buffer_blocks :
+ EXT2_INODE_SCAN_DEFAULT_BUFFER_BLOCKS) *
+ ctx->fs->blocksize /
+ EXT2_INODE_SIZE(ctx->fs->super);
+ inodes_in_group--;
+ *next_ino = inodes_in_group -
+ (inodes_in_group % inodes_per_buffer) + 1 +
+ (grp * ctx->fs->super->s_inodes_per_group);
+ }
+}
+
void e2fsck_pass1(e2fsck_t ctx)
{
int i;
@@ -889,10 +943,19 @@ void e2fsck_pass1(e2fsck_t ctx)
int low_dtime_check = 1;
int inode_size;
int failed_csum = 0;
+ ext2_ino_t ino_threshold = 0;
+ dgrp_t ra_group = 0;

init_resource_track(&rtrack, ctx->fs->io);
clear_problem_context(&pctx);

+ /* If we can do readahead, figure out how many groups to pull in. */
+ if (!e2fsck_can_readahead(ctx->fs))
+ ctx->readahead_kb = 0;
+ else if (ctx->readahead_kb == ~0ULL)
+ ctx->readahead_kb = e2fsck_guess_readahead(ctx->fs);
+ pass1_readahead(ctx, &ra_group, &ino_threshold);
+
if (!(ctx->options & E2F_OPT_PREEN))
fix_problem(ctx, PR_1_PASS_HEADER, &pctx);

@@ -1072,6 +1135,8 @@ void e2fsck_pass1(e2fsck_t ctx)
old_op = ehandler_operation(_("getting next inode from scan"));
pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
inode, inode_size);
+ if (ino > ino_threshold)
+ pass1_readahead(ctx, &ra_group, &ino_threshold);
ehandler_operation(old_op);
if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
return;
diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c
index 0b9c5c5..2060ed2 100644
--- a/e2fsck/pass2.c
+++ b/e2fsck/pass2.c
@@ -61,6 +61,9 @@
* Keeps track of how many times an inode is referenced.
*/
static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
+static int check_dir_block2(ext2_filsys fs,
+ struct ext2_db_entry2 *dir_blocks_info,
+ void *priv_data);
static int check_dir_block(ext2_filsys fs,
struct ext2_db_entry2 *dir_blocks_info,
void *priv_data);
@@ -77,6 +80,9 @@ struct check_dir_struct {
struct problem_context pctx;
int count, max;
e2fsck_t ctx;
+ unsigned long long list_offset;
+ unsigned long long ra_entries;
+ unsigned long long next_ra_off;
};

void e2fsck_pass2(e2fsck_t ctx)
@@ -96,6 +102,9 @@ void e2fsck_pass2(e2fsck_t ctx)
int i, depth;
problem_t code;
int bad_dir;
+ int (*check_dir_func)(ext2_filsys fs,
+ struct ext2_db_entry2 *dir_blocks_info,
+ void *priv_data);

init_resource_track(&rtrack, ctx->fs->io);
clear_problem_context(&cd.pctx);
@@ -139,6 +148,9 @@ void e2fsck_pass2(e2fsck_t ctx)
cd.ctx = ctx;
cd.count = 1;
cd.max = ext2fs_dblist_count2(fs->dblist);
+ cd.list_offset = 0;
+ cd.ra_entries = ctx->readahead_kb * 1024 / ctx->fs->blocksize;
+ cd.next_ra_off = 0;

if (ctx->progress)
(void) (ctx->progress)(ctx, 2, 0, cd.max);
@@ -146,7 +158,8 @@ void e2fsck_pass2(e2fsck_t ctx)
if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
ext2fs_dblist_sort2(fs->dblist, special_dir_block_cmp);

- cd.pctx.errcode = ext2fs_dblist_iterate2(fs->dblist, check_dir_block,
+ check_dir_func = cd.ra_entries ? check_dir_block2 : check_dir_block;
+ cd.pctx.errcode = ext2fs_dblist_iterate2(fs->dblist, check_dir_func,
&cd);
if (ctx->flags & E2F_FLAG_SIGNAL_MASK || ctx->flags & E2F_FLAG_RESTART)
return;
@@ -824,6 +837,29 @@ err:
return retval;
}

+static int check_dir_block2(ext2_filsys fs,
+ struct ext2_db_entry2 *db,
+ void *priv_data)
+{
+ int err;
+ struct check_dir_struct *cd = priv_data;
+
+ if (cd->ra_entries && cd->list_offset >= cd->next_ra_off) {
+ err = e2fsck_readahead_dblist(fs,
+ E2FSCK_RA_DBLIST_IGNORE_BLOCKCNT,
+ fs->dblist,
+ cd->list_offset + cd->ra_entries / 8,
+ cd->ra_entries);
+ if (err)
+ cd->ra_entries = 0;
+ cd->next_ra_off = cd->list_offset + (cd->ra_entries * 7 / 8);
+ }
+
+ err = check_dir_block(fs, db, priv_data);
+ cd->list_offset++;
+ return err;
+}
+
static int check_dir_block(ext2_filsys fs,
struct ext2_db_entry2 *db,
void *priv_data)
diff --git a/e2fsck/pass4.c b/e2fsck/pass4.c
index 21d93f0..bc9a2c4 100644
--- a/e2fsck/pass4.c
+++ b/e2fsck/pass4.c
@@ -106,6 +106,15 @@ void e2fsck_pass4(e2fsck_t ctx)
#ifdef MTRACE
mtrace_print("Pass 4");
#endif
+ /*
+ * Since pass4 is mostly CPU bound, start readahead of bitmaps
+ * ahead of pass 5 if we haven't already loaded them.
+ */
+ if (ctx->readahead_kb &&
+ (fs->block_map == NULL || fs->inode_map == NULL))
+ e2fsck_readahead(fs, E2FSCK_READA_BBITMAP |
+ E2FSCK_READA_IBITMAP,
+ 0, fs->group_desc_count);

clear_problem_context(&pctx);

diff --git a/e2fsck/unix.c b/e2fsck/unix.c
index 1a089a9..6b0ca96 100644
--- a/e2fsck/unix.c
+++ b/e2fsck/unix.c
@@ -649,6 +649,7 @@ static void parse_extended_opts(e2fsck_t ctx, const char *opts)
char *buf, *token, *next, *p, *arg;
int ea_ver;
int extended_usage = 0;
+ unsigned long long reada_kb;

buf = string_copy(ctx, opts, 0);
for (token = buf; token && *token; token = next) {
@@ -677,6 +678,15 @@ static void parse_extended_opts(e2fsck_t ctx, const char *opts)
continue;
}
ctx->ext_attr_ver = ea_ver;
+ } else if (strcmp(token, "readahead_kb") == 0) {
+ reada_kb = strtoull(arg, &p, 0);
+ if (*p) {
+ fprintf(stderr, "%s",
+ _("Invalid readahead buffer size.\n"));
+ extended_usage++;
+ continue;
+ }
+ ctx->readahead_kb = reada_kb;
} else if (strcmp(token, "fragcheck") == 0) {
ctx->options |= E2F_OPT_FRAGCHECK;
continue;
@@ -716,6 +726,7 @@ static void parse_extended_opts(e2fsck_t ctx, const char *opts)
fputs(("\tjournal_only\n"), stderr);
fputs(("\tdiscard\n"), stderr);
fputs(("\tnodiscard\n"), stderr);
+ fputs(("\treadahead_kb=<buffer size>\n"), stderr);
fputc('\n', stderr);
exit(1);
}
@@ -749,6 +760,7 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
#ifdef CONFIG_JBD_DEBUG
char *jbd_debug;
#endif
+ unsigned long long phys_mem_kb;

retval = e2fsck_allocate_context(&ctx);
if (retval)
@@ -776,6 +788,8 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
else
ctx->program_name = "e2fsck";

+ phys_mem_kb = get_memory_size() / 1024;
+ ctx->readahead_kb = ~0ULL;
while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
switch (c) {
case 'C':
@@ -960,6 +974,20 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
if (c)
verbose = 1;

+ if (ctx->readahead_kb == ~0ULL) {
+ profile_get_integer(ctx->profile, "options",
+ "readahead_mem_pct", 0, -1, &c);
+ if (c >= 0 && c <= 100)
+ ctx->readahead_kb = phys_mem_kb * c / 100;
+ profile_get_integer(ctx->profile, "options",
+ "readahead_kb", 0, -1, &c);
+ if (c >= 0)
+ ctx->readahead_kb = c;
+ if (ctx->readahead_kb != ~0ULL &&
+ ctx->readahead_kb > phys_mem_kb)
+ ctx->readahead_kb = phys_mem_kb;
+ }
+
/* Turn off discard in read-only mode */
if ((ctx->options & E2F_OPT_NO) &&
(ctx->options & E2F_OPT_DISCARD))
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index bba40ac..fe82a32 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -1421,6 +1421,7 @@ extern errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan,
ext2_ino_t *ino,
struct ext2_inode *inode,
int bufsize);
+#define EXT2_INODE_SCAN_DEFAULT_BUFFER_BLOCKS 8
extern errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
ext2_inode_scan *ret_scan);
extern void ext2fs_close_inode_scan(ext2_inode_scan scan);
diff --git a/lib/ext2fs/inode.c b/lib/ext2fs/inode.c
index 4310b82..4b3e14e 100644
--- a/lib/ext2fs/inode.c
+++ b/lib/ext2fs/inode.c
@@ -175,7 +175,8 @@ errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
scan->bytes_left = 0;
scan->current_group = 0;
scan->groups_left = fs->group_desc_count - 1;
- scan->inode_buffer_blocks = buffer_blocks ? buffer_blocks : 8;
+ scan->inode_buffer_blocks = buffer_blocks ? buffer_blocks :
+ EXT2_INODE_SCAN_DEFAULT_BUFFER_BLOCKS;
scan->current_block = ext2fs_inode_table_loc(scan->fs,
scan->current_group);
scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);


2014-09-09 22:52:43

by Andreas Dilger

[permalink] [raw]
Subject: Re: [PATCH 00/25] e2fsprogs Summer 2014 patchbomb, part 5.2

On Sep 8, 2014, at 5:11 PM, Darrick J. Wong <[email protected]> wrote:
> Patch 1 introduces journal_csum v3 to fix numerous journal block tag
> size handling bugs when metadata_csum+journal_checksum are turned on.
> The test of 64bitness should not rely on guessing the tag size when it
> could simply query the feature flags, since it was guessing
> incorrectly. Furthermore, the journal_csum v2 structure had memory
> access alignment issues. Just replace this all with a 16-byte tag
> with everything in it; the overhead for checksums is no more than
> 0.1%.

It's really too bad that we are introducing a new journal checksum
feature, when the current journal checksum implementation is
essentially unusable. Any minor corruption in one transaction block
that has following un-checkpointed transactions will almost certainly
result in _more_ corruption of the filesystem rather than less, due
to all of the *committed* but uncheckpointed blocks being discarded
from the journal. This would also result in a silent rollback of
filesystem state and loss of user data if running with data=journal.

As a result, there is no practical value (IMHO) to enabling this
feature at all currently.

We've discussed in the past that having per-block checksums is
necessary in order to fix this, so that only corrupt blocks in the
journal are skipped during replay, and may not result in any visible
filesystem corruption if the blocks are overwritten later during
replay. Otherwise, this will itself result in yet a new block tag
format and journal checksum feature.

Is there any chance you could take a look at implementing this as
part of journal_checksum_v3 instead of fixing the current bugs only
to have a "correctly working" but not usable feature?

Cheers, Andreas

> NOTE: The test "j_corrupt_journal_block" in patch 21 ensures that
> e2fsck will replay everything but the corrupt block, and then proceeds
> with the fsck to fix up whatever might be broken. You can decompress
> the image.gz and try to mount it to verify that it's unmountable (and
> hence requires e2fsck to be run).
>
> Patches 23-25 implement v2 of the e2fsck readahead functionality,
> which promises to reduce fsck runtime by 10-30%. You might want to
> read the report: http://marc.info/?l=linux-ext4&m=140755433701165&w=2
> ("e2fsck readahead speedup performance report") for all the juicy
> details!
>
> I've tested these e2fsprogs changes against the -next branch as of
> 8/29. The patches have been tested against the 'make check' suite and
> some amount of e2fuzz testing.
>
> Comments and questions are, as always, welcome.
>
> --D
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html


Cheers, Andreas






Attachments:
signature.asc (833.00 B)
Message signed with OpenPGP using GPGMail

2014-09-10 01:13:35

by Darrick J. Wong

[permalink] [raw]
Subject: Re: [PATCH 00/25] e2fsprogs Summer 2014 patchbomb, part 5.2

On Tue, Sep 09, 2014 at 04:53:16PM -0600, Andreas Dilger wrote:
> On Sep 8, 2014, at 5:11 PM, Darrick J. Wong <[email protected]> wrote:
> > Patch 1 introduces journal_csum v3 to fix numerous journal block tag
> > size handling bugs when metadata_csum+journal_checksum are turned on.
> > The test of 64bitness should not rely on guessing the tag size when it
> > could simply query the feature flags, since it was guessing
> > incorrectly. Furthermore, the journal_csum v2 structure had memory
> > access alignment issues. Just replace this all with a 16-byte tag
> > with everything in it; the overhead for checksums is no more than
> > 0.1%.
>
> It's really too bad that we are introducing a new journal checksum
> feature, when the current journal checksum implementation is
> essentially unusable. Any minor corruption in one transaction block
> that has following un-checkpointed transactions will almost certainly
> result in _more_ corruption of the filesystem rather than less, due
> to all of the *committed* but uncheckpointed blocks being discarded
> from the journal. This would also result in a silent rollback of
> filesystem state and loss of user data if running with data=journal.
>
> As a result, there is no practical value (IMHO) to enabling this
> feature at all currently.
>
> We've discussed in the past that having per-block checksums is
> necessary in order to fix this, so that only corrupt blocks in the
> journal are skipped during replay, and may not result in any visible
> filesystem corruption if the blocks are overwritten later during
> replay. Otherwise, this will itself result in yet a new block tag
> format and journal checksum feature.
>
> Is there any chance you could take a look at implementing this as
> part of journal_checksum_v3 instead of fixing the current bugs only
> to have a "correctly working" but not usable feature?

Journal checksum v2 implements this. The kernel skips the corrupt block,
continues the journal replay and refuses to mount, thereby forcing a fsck run.
fsck does the same, but it (obviously) runs a full check after the replay to
find anything other damage.

>From tests/j_corrupt_journal_block/image.gz, we see these journal contents:

debugfs: logdump -c
Journal starts at block 1, transaction 3
Found expected sequence 3, type 1 (descriptor block) at block 1
Found expected sequence 3, type 2 (commit block) at block 4
Found expected sequence 4, type 5 (revoke table) at block 5
Found expected sequence 4, type 2 (commit block) at block 6
Found expected sequence 5, type 1 (descriptor block) at block 7
Found expected sequence 5, type 2 (commit block) at block 9
Found expected sequence 6, type 1 (descriptor block) at block 10
Found expected sequence 6, type 2 (commit block) at block 12
No magic number at block 13: end of journal.

This test checks the "continues replaying even after a corrupt journal block"
feature by using the journal to overwrite the blocks of a file. Originally, /a
contains 3 blocks worth of 'a':

debugfs: cat /a
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<snip>
debugfs: stat /a
Inode: 12 Type: regular Mode: 0644 Flags: 0x80000
Generation: 3642437594 Version: 0x00000000:00000001
User: 0 Group: 0 Size: 3072
File ACL: 0 Directory ACL: 0
Links: 1 Blockcount: 6
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x53eb0316:145457c8 -- Tue Aug 12 23:17:58 2014
atime: 0x53eb0316:145457c8 -- Tue Aug 12 23:17:58 2014
mtime: 0x53eb0316:145457c8 -- Tue Aug 12 23:17:58 2014
crtime: 0x53eb0316:145457c8 -- Tue Aug 12 23:17:58 2014
Size of extra inode fields: 28
Inode checksum: 0x98f0c609
EXTENTS:
(0-2):1090-1092

(For the ease of the reader, 1090 == 0x442.)

In the first transaction, we overwrite the first two blocks of /a with 'b'.

debugfs: bmap <8> 1
33
debugfs: bd 33
0000 c03b 3998 0000 0001 0000 0003 0000 0442 .;9............B
0020 0000 0000 0000 0000 cdc6 611c 0000 0000 ..........a.....
0040 0000 0000 0000 0000 0000 0000 0000 0443 ...............C
0060 0000 000a 0000 0000 cdc6 611c 0000 0000 ..........a.....

Note the two descriptor tags referring to blocks 1090-1091.

debugfs: bmap <8> 2
35
debugfs: bd 35
0000 6262 6262 6262 6262 6262 6262 6262 6262 bbbbbbbbbbbbbbbb
*
debugfs: bmap <8> 3
36
debugfs: bd 36
0000 6262 6262 6262 6262 6262 6262 6262 6262 bbbbbbbbbbbbbbbb
*

We commit the first transaction in block 4.

In the second transaction, we revoke the first block of the first transaction.
At this point, /a will be left with a block of 'a', a block of 'b', and another
block of 'a':

debugfs: bmap <8> 5
38
debugfs: bd 38
0000 c03b 3998 0000 0005 0000 0004 0000 0018 .;9.............
0020 0000 0000 0000 0442 0000 0000 0000 0000 .......B........

This was done mostly to test ... NUTS, a bug. When we see an error, we ought
to kill all the revoke records and restart the replay, because the revoke table
could've nixed a previous journal block.

Ok, I'll go fix that.

In the third transaction, we overwrite the first block of /a (1090) with 'c'.
However, I have corrupted the journal block (by overwriting some of it with
'-') so that this block should not replay:

debugfs: bmap <8> 7
40
debugfs: bd 40
0000 c03b 3998 0000 0001 0000 0005 0000 0442 .;9............B
0020 0000 0008 0000 0000 9881 d4c5 0000 0000 ................
debugfs: bmap <8> 8
41
debugfs: bd 41
0000 2d2d 2d2d 2d2d 2d2d 2d2d 2d2d 2d2d 2d2d ----------------
0020 6363 6363 6363 6363 6363 6363 6363 6363 cccccccccccccccc
*

In the fourth transaction, we overwrite the last block of /a (1092) with 'd':

debugfs: bmap <8> 10
43
debugfs: bd 43
0000 c03b 3998 0000 0001 0000 0006 0000 0444 .;9............D
0020 0000 0008 0000 0000 61ac 3738 0000 0000 ........a.78....
debugfs: bmap <8> 11
44
debugfs: bd 44
0000 6464 6464 6464 6464 6464 6464 6464 6464 dddddddddddddddd
*

As you can see from the expect output, after replaying the journal, the file
contents are a block of 'a', then a block of 'b', and then a block of 'd',
which is consistent with skipping the corrupted block but replaying the rest.

This is actually broken; the file contents SHOULD be two blocks of 'b' and a
block of 'd'.

--D

>
> Cheers, Andreas
>
> > NOTE: The test "j_corrupt_journal_block" in patch 21 ensures that
> > e2fsck will replay everything but the corrupt block, and then proceeds
> > with the fsck to fix up whatever might be broken. You can decompress
> > the image.gz and try to mount it to verify that it's unmountable (and
> > hence requires e2fsck to be run).
> >
> > Patches 23-25 implement v2 of the e2fsck readahead functionality,
> > which promises to reduce fsck runtime by 10-30%. You might want to
> > read the report: http://marc.info/?l=linux-ext4&m=140755433701165&w=2
> > ("e2fsck readahead speedup performance report") for all the juicy
> > details!
> >
> > I've tested these e2fsprogs changes against the -next branch as of
> > 8/29. The patches have been tested against the 'make check' suite and
> > some amount of e2fuzz testing.
> >
> > Comments and questions are, as always, welcome.
> >
> > --D
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> > the body of a message to [email protected]
> > More majordomo info at http://vger.kernel.org/majordomo-info.html
>
>
> Cheers, Andreas
>
>
>
>
>



2014-09-10 01:15:35

by Darrick J. Wong

[permalink] [raw]
Subject: Re: [PATCH 21/25] tests: test e2fsck recovery of corrupt descriptor blocks

On Mon, Sep 08, 2014 at 04:13:55PM -0700, Darrick J. Wong wrote:
> Test e2fsck' ability to deal with (a) corrupt descriptor block
> checksum; (b) obviously bad journal block tid; and (c) corrupt journal
> blocks. These should exercise the journal recovery infinite loop
> bugfix earlier in this patchset.
>
> Signed-off-by: Darrick J. Wong <[email protected]>
> ---
> tests/j_corrupt_descr_csum/expect | 18 +++++++++++
> tests/j_corrupt_descr_csum/image.gz | Bin
> tests/j_corrupt_descr_csum/name | 1 +
> tests/j_corrupt_descr_csum/script | 51 ++++++++++++++++++++++++++++++++
> tests/j_corrupt_descr_tid/expect | 17 +++++++++++
> tests/j_corrupt_descr_tid/image.gz | Bin
> tests/j_corrupt_descr_tid/name | 1 +
> tests/j_corrupt_descr_tid/script | 51 ++++++++++++++++++++++++++++++++
> tests/j_corrupt_journal_block/expect | 19 ++++++++++++

NAK, this file is incorrect. As noted in a previous email, the revoke block
should itself be revoked (and the replay restarted) if we encounter corrupt
blocks.

Silly /me didn't consider that revoke records aren't intended to unilaterally
kill journal blocks; they only make sense if there's a subsequent transaction
also writing the block.

--D

> tests/j_corrupt_journal_block/image.gz | Bin
> tests/j_corrupt_journal_block/name | 1 +
> tests/j_corrupt_journal_block/script | 51 ++++++++++++++++++++++++++++++++
> 12 files changed, 210 insertions(+)
> create mode 100644 tests/j_corrupt_descr_csum/expect
> create mode 100644 tests/j_corrupt_descr_csum/image.gz
> create mode 100644 tests/j_corrupt_descr_csum/name
> create mode 100644 tests/j_corrupt_descr_csum/script
> create mode 100644 tests/j_corrupt_descr_tid/expect
> create mode 100644 tests/j_corrupt_descr_tid/image.gz
> create mode 100644 tests/j_corrupt_descr_tid/name
> create mode 100644 tests/j_corrupt_descr_tid/script
> create mode 100644 tests/j_corrupt_journal_block/expect
> create mode 100644 tests/j_corrupt_journal_block/image.gz
> create mode 100644 tests/j_corrupt_journal_block/name
> create mode 100644 tests/j_corrupt_journal_block/script
>
>
> diff --git a/tests/j_corrupt_descr_csum/expect b/tests/j_corrupt_descr_csum/expect
> new file mode 100644
> index 0000000..419e775
> --- /dev/null
> +++ b/tests/j_corrupt_descr_csum/expect
> @@ -0,0 +1,18 @@
> +test_filesys: recovering journal
> +../e2fsck/e2fsck: Input/output error while recovering ext3 journal of test_filesys
> +
> +test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
> +
> +test_filesys: ********** WARNING: Filesystem still has errors **********
> +
> +Exit status is 12
> +test_filesys: recovering journal
> +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/128 files (8.3% non-contiguous), 1093/2048 blocks
> +Exit status is 0
> +debugfs: cat /a
> +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
> \ No newline at end of file
> diff --git a/tests/j_corrupt_descr_csum/image.gz b/tests/j_corrupt_descr_csum/image.gz
> new file mode 100644
> index 0000000000000000000000000000000000000000..2a81e5daeb13fcec40d8fa9ef95151427a35b584
> GIT binary patch
> literal 2989
> zcmeIz{WIGK90%~AZF)0h>dI+O^eVOMRO%2mCN1k(kuutNzHG8aiAYOP59jORX~~qf
> zPSS`*v#nb591mqkHuKO<mLQ6GTxcjMsfR4`^!;x8vHk?-^V{b>_xa)dy3gGQ`TbGY
> z$Pq=DvB~-z?gru-0`|_Mn^TF_v5)XB=Bq*(2|FR5d@zVN{rt|z(X6DlB1Q`jQ$eHA
> z8LUN|i=DSs)<-m}v+EZbs;{5n3j@%DKTO7rT%FE`yNHKHzCIY+@4m$?t4*n-3{rYL
> zRIZWqu>X2wZ5(p-_ZF#*FEFjENA!hE2a|$F*cG0!*_nI~rbAG$`U=WbO2Ji!J2nU!
> zQNY&C>67TfcX6l!M~;}#og>@C4jmJw$m?GB2X14B8d+r@p2Jp}nHIT;v-GR6j=?>^
> zTYBmCab2-_&*(Ps!A`+MD8_kkG^Z7DwzUQ=m$9}o=DAE<0y}^eM*UMmt=g_XZ3s*Z
> zx^@|E*ASt8)|Bnztr}i#12UpEs$W99+p!Y7C_h}N$^01M(>X;}BRo@wEf2xot2}6M
> z2kI}<7GS;24xdm`q_z)2!(VKqN^Jw4G&a7q^P%v%+|J)gx)Bfky?MHLvD3o2qWmWb
> z={UaKjRk1yWNW3&ObyUmCC4^*Yy;7fp|H)(2EN?r(lBIQDiGknd_DX%)*dp_n7;rn
> zfF@hWdr+PpjwgVGoHxIX?j+3HrajS~$3({-OXV0ZSbDinZ*ryms>H+z?R~!=QDoyw
> z%oTvEtmu6uTPRhhIaU3_N3Xk~eFTEUBu?I?ajmSE@P*$kZ#c~AO0J&pheTc2y5Q~r
> z-4=~_MJAUS20h>sPa4hr7T9zOn+Evja;Z%y6Y@-NKC%ZxhOnut$!hDBbY}_#$Rh(S
> zCPXS>QI2rIrnsy$#*orJu&6~k&H0DL8YCu#?sXtiVpLH6Xin)|3qlhcijK$4q%}w}
> zriF;Fw7|lYN%lDO&H87C%PDIXArY<rjTSL7v6QGj*8l=|1M+`-JiS5way~J#Hgn_Q
> z&%mtE$Cf0}AeNFPftVTupJU=KjzLfaY*E+quMi#AyEXx&ufNSy&MN!qOk6F9Wbnml
> z=2l)SXPm9QKy@xUU9ZD7LGd<rbb3Us(=6!7OJyq!<H8cG-hUQEc`Pf7@!nvw%Qyq8
> zJ0l8moC8@aNzjsj=c*ivev=eDT+<d*;TMqzTd5@Kg}qUdUB&A3<bW7bQ70kSm=aa>
> zMwChz3KB=wwAkmMw369zU99U9bb?6WDOUll-gkQV&ta9&q1#^Yr2!2_<SH$x>7TZc
> zXUyA+JnjzdQcLg(prv0EuAseldwZG-hJlVCVpxq?0-eI0Kf%WnIAdc~Oy<3IbyjxN
> zL~(uZ(%n;JrOlqTgZ4n+Kw$p~Jf7FWV0nEv5AFF_`!DH1q62~bCGcy&?#Ysla&s8W
> G9`-Nik0OEq
>
> literal 0
> HcmV?d00001
>
> diff --git a/tests/j_corrupt_descr_csum/name b/tests/j_corrupt_descr_csum/name
> new file mode 100644
> index 0000000..e15ccfb
> --- /dev/null
> +++ b/tests/j_corrupt_descr_csum/name
> @@ -0,0 +1 @@
> +corrupt descr csum (csum v3)
> diff --git a/tests/j_corrupt_descr_csum/script b/tests/j_corrupt_descr_csum/script
> new file mode 100644
> index 0000000..102feba
> --- /dev/null
> +++ b/tests/j_corrupt_descr_csum/script
> @@ -0,0 +1,51 @@
> +if test -x $DEBUGFS_EXE; then
> +
> +IMAGE=$test_dir/image.gz
> +FSCK_OPT=-fy
> +OUT=$test_name.log
> +if [ -f $test_dir/expect.gz ]; then
> + EXP=$test_name.tmp
> + gunzip < $test_dir/expect.gz > $EXP1
> +else
> + EXP=$test_dir/expect
> +fi
> +
> +cp /dev/null $OUT
> +
> +gzip -d < $IMAGE > $TMPFILE
> +
> +$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
> +status=$?
> +echo Exit status is $status >> $OUT.new
> +sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
> +rm -f $OUT.new
> +
> +$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
> +status=$?
> +echo Exit status is $status >> $OUT.new
> +sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
> +rm -f $OUT.new
> +
> +echo "cat /a" > $TMPFILE.cmd
> +$DEBUGFS_EXE -f $TMPFILE.cmd $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
> +rm -f $TMPFILE.cmd
> +
> +rm -f $TMPFILE
> +
> +cmp -s $OUT $EXP
> +status=$?
> +
> +if [ "$status" = 0 ] ; then
> + echo "$test_name: $test_description: ok"
> + touch $test_name.ok
> +else
> + echo "$test_name: $test_description: failed"
> + diff $DIFF_OPTS $EXP $OUT > $test_name.failed
> + rm -f $test_name.tmp
> +fi
> +
> +unset IMAGE FSCK_OPT OUT EXP
> +
> +else #if test -x $DEBUGFS_EXE; then
> + echo "$test_name: $test_description: skipped"
> +fi
> diff --git a/tests/j_corrupt_descr_tid/expect b/tests/j_corrupt_descr_tid/expect
> new file mode 100644
> index 0000000..0444203
> --- /dev/null
> +++ b/tests/j_corrupt_descr_tid/expect
> @@ -0,0 +1,17 @@
> +test_filesys: recovering journal
> +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/128 files (8.3% non-contiguous), 1093/2048 blocks
> +Exit status is 0
> +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/128 files (8.3% non-contiguous), 1093/2048 blocks
> +Exit status is 0
> +debugfs: cat /a
> +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
> \ No newline at end of file
> diff --git a/tests/j_corrupt_descr_tid/image.gz b/tests/j_corrupt_descr_tid/image.gz
> new file mode 100644
> index 0000000000000000000000000000000000000000..3ad88f9d15549c24758ae53015a08b62f938f5f8
> GIT binary patch
> literal 2999
> zcmeIw|1;Zn90%}dw7R;Loo_88Y`3Xv6<1ptN~l)q)S|TYU0ROBx6oy%FKP6&i!p6?
> zH;sx>U2!3%i3k;up<zb|O3ark3*yU3NMy*D&wIBY+dsj1{r3Ff^~3Y=dLc@V!s3k9
> zLl40>-eFVCZ=8T_B6(3~YIW4U2mUr&7mE&~?ETG7pZdheB+|?)L|Etl(zn>*T6|-l
> z@m3wn?!uD{H-{e$;YJtV6dGO*a*bwQYQFSB_-A(^tE;VrzAe5<AAiMFX@6;J@jSO7
> zM~aZDjjQ<BqdwO@t*1&%HPZQ1)PtJyqOZjxWo_;_%wBGKazuIgimkXo)%3V|y+uMH
> zMr;Us?_|`N_mq^GRz>G7uho(sgPgeevO!z|Cbj}XaXa&G5uj0KrCVL*m`W`7&Rs0@
> z!~Rfpa>lDuHdKXZVLEbX$|R>pT>4V*Gj|HZ@*d+~I<k-J!QE=F%(dwP4NlD-QUS9&
> zy6n92maqdudZ!&_;UsSsyjW?C%OE&<Qe{C>l%?OZI|k3gYo~1UzMEqk8o)l7d4by&
> zn#D#fm|%VG*XGS|sLXL&rFND>4Po#+1ypgz$jxc=T>^mw<`>}FF^=ikr!7ozqM0S9
> zd=Ral_&(t+J86&7R4GHhYFAPG#E#O{y(adO!R0|<b-b&~7b?^lEu!s#!Jf%q6dwq#
> zL_7fnIwQ+isG73UJ-W-5*ksm1?wL_B$3uCCaCAHCZK+pn$@;_bCiRzE|3HahG4m;i
> z=&*E6R19l&(_OYRhbwvP)83pRZ~klRRC+-~Co64lYSn6v_l0$_6a{;pk^CM6wo1th
> z<JrzrXfl3<A1lAoD``7|)f_oo^3N_VaAQROTdOqR)A?lhtlUPo*&3h)YYg57u5#`|
> zn;tCToqfYUmjR{q^N#oFK~fCnkNnpoad#k-Ww~@q4$1EKR9px3@vsHLq-1CLIuP*n
> z70##5RA?vxOn_*d1Y}3MziS|>aDBIaibeLh9n=75FVlKr`mwX<HVybygZTdnmPP8N
> zb-p@_H%EGVS0#niqrv(?nRzy*X(@ETL4XQQQ7;l^hEfOkrDN@_s#2ge_2`AZv8v9=
> zjY(Dm>I)_*YRAe`)_2yz6WXD;Wa)V5bO?XKF5stdhG-VT*Q8Vlv<%8K?@i1!lz^;L
> zP>FfE+cya26o}?JL2cK&V5gvZvR_zQIkBe2jXS|ArTLYo!0Km0bOQdgXqUdaHYpqi
> z77BN8t`e&jOZ?S1MwT0atgns)oPI8`N<k)uMFJDSj7SZ3uh?Df|5@WQh%FL_fZCF!
> z?BT6MT71;Ex)FkI%-9LC`CYAXY2Aj@k)|Jf;YWecHBL)f8{mA!9ha@zIw;hcNvUZp
> zXX6}7^I&|`XG-W%*uzdi{6|{{@j&1}VE+jeB(B3@uw%VQ`~BDLpwWTAz7`--1qKMw
> Kr~n4Dhy4e5RXFwl
>
> literal 0
> HcmV?d00001
>
> diff --git a/tests/j_corrupt_descr_tid/name b/tests/j_corrupt_descr_tid/name
> new file mode 100644
> index 0000000..2325d6d
> --- /dev/null
> +++ b/tests/j_corrupt_descr_tid/name
> @@ -0,0 +1 @@
> +corrupt descr tid (csum v3)
> diff --git a/tests/j_corrupt_descr_tid/script b/tests/j_corrupt_descr_tid/script
> new file mode 100644
> index 0000000..102feba
> --- /dev/null
> +++ b/tests/j_corrupt_descr_tid/script
> @@ -0,0 +1,51 @@
> +if test -x $DEBUGFS_EXE; then
> +
> +IMAGE=$test_dir/image.gz
> +FSCK_OPT=-fy
> +OUT=$test_name.log
> +if [ -f $test_dir/expect.gz ]; then
> + EXP=$test_name.tmp
> + gunzip < $test_dir/expect.gz > $EXP1
> +else
> + EXP=$test_dir/expect
> +fi
> +
> +cp /dev/null $OUT
> +
> +gzip -d < $IMAGE > $TMPFILE
> +
> +$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
> +status=$?
> +echo Exit status is $status >> $OUT.new
> +sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
> +rm -f $OUT.new
> +
> +$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
> +status=$?
> +echo Exit status is $status >> $OUT.new
> +sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
> +rm -f $OUT.new
> +
> +echo "cat /a" > $TMPFILE.cmd
> +$DEBUGFS_EXE -f $TMPFILE.cmd $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
> +rm -f $TMPFILE.cmd
> +
> +rm -f $TMPFILE
> +
> +cmp -s $OUT $EXP
> +status=$?
> +
> +if [ "$status" = 0 ] ; then
> + echo "$test_name: $test_description: ok"
> + touch $test_name.ok
> +else
> + echo "$test_name: $test_description: failed"
> + diff $DIFF_OPTS $EXP $OUT > $test_name.failed
> + rm -f $test_name.tmp
> +fi
> +
> +unset IMAGE FSCK_OPT OUT EXP
> +
> +else #if test -x $DEBUGFS_EXE; then
> + echo "$test_name: $test_description: skipped"
> +fi
> diff --git a/tests/j_corrupt_journal_block/expect b/tests/j_corrupt_journal_block/expect
> new file mode 100644
> index 0000000..50d0b78
> --- /dev/null
> +++ b/tests/j_corrupt_journal_block/expect
> @@ -0,0 +1,19 @@
> +test_filesys: recovering journal
> +JBD2: Invalid checksum recovering block 1090 in log
> +../e2fsck/e2fsck: Input/output error while recovering ext3 journal of test_filesys
> +
> +test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
> +
> +test_filesys: ********** WARNING: Filesystem still has errors **********
> +
> +Exit status is 12
> +test_filesys: recovering journal
> +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/128 files (8.3% non-contiguous), 1093/2048 blocks
> +Exit status is 0
> +debugfs: cat /a
> +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb!
> bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb!
> bbbbbbbbbbddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd!
> dddddddddddddddddddddddddddddddddddddddddddddd
> \ No newline at end of file
> diff --git a/tests/j_corrupt_journal_block/image.gz b/tests/j_corrupt_journal_block/image.gz
> new file mode 100644
> index 0000000000000000000000000000000000000000..f60439f02ea11289639dc2c3e5108bf5b3a662bb
> GIT binary patch
> literal 2998
> zcmeH{`#0Nn9L9rfY+4+;QXJ8)&h)G}+k!eQ>1>_4giaLA7>#RO>N2;ueW^>kso1n`
> zO;J5_=`;xHn$l$@npC2RTd<}|o6vm|;>Zp8tiQH@LXY=v&kye(p4ao72U(_v@YH#Y
> z)7F9i#l~8mw?u3>4^wV-_N@gO8KZ(7no-nmrhmIkn{hX^LS449pf(c{+px{I33pyJ
> zXW_2t8kU3<TbFp{*p6j)1+=@{)Xd(QBTNM>6zP7+VLx$4JDFci!@g4JCq-vQXT*T(
> zDlWZFP;aVzE})3UH)9m`W_DOIPA~Yi_)S$+oeIq%(VeT0`}oRzkK_1>XB&e)r;c>k
> zK(ez7!@-{{H+$*%Io3bOSM8cWWUJh5*4*RGniz;o?X<KC&PBD04iIn2m0LM}mS97C
> zy*{QBKC-kE$gS|?nc%$z17;pu)YLW~%E*l?VJsmj0zdm_)Ui<C2aY14)5?Vyb<K3`
> zUzG-K{xr#tVG1Z$R&$>SMtTz(S)ed2lpFXYFG8qsGcu4+r1xDF4MT|^Ya`yehfstJ
> zBBbXrkhhAp%M^XYgPwO?BNc<hgU$Y#nHh$S+f9RMZ9x3+mChd1Kw7clJ`mtriKbwK
> zdAtzKT4yN@Yu6(KKe(`=aFPh};I^7<Zo=I!wa&1CX$Af1QShxsM~3_z6zuA*VyuCd
> z%5VZYt<mvz01j@uQ^{&nQu&a7o*9K|f29sv*jZL@4rg&=Uu2(fjNcP$mMa|#kFmEf
> zTm`FReM4$5Pv_JRb-ThSE@osTE`d@&q7UZ1928*ain3T+vPi3d@wftbt5hS&>YdWn
> zM)HwtCL5*+l^NiK$GNVP9N@UxDv@%yTX1(|IBAgwp1$VG0j@@pkxPo+V#q;IL(c~n
> z1tB1QLa|exqTHC85AwD<JO{#;(RE^US5&oW0i!k$REQ9aUpo?|4s9C1AzSp_?n+n(
> zU+~mmWkwAN#YL_&;G)W0b<$-JX?u^j4L(hwBy%UkI{NLPF%am!$)Lc7@EwWXkC#ll
> zIb)|Wk}#w`PMAwh=@;2p;0y$lh32jHWGA6l^wOfO!B743N=UEiYfF62njmJD>A#0L
> z6ji^N(Khdr38&Ilz;gwGIVvhsL#2N=)n2V)Ey0lS&|%dxKfqQNL66|D)L-QJVlorC
> z;7(QcBr$x_c`!s8mt!OrL$Z8&31__bo+tZzm*SF-l3QHH!D9UOwb6zS2>0J^*!HD8
> z%s(Z;KoHoj31UG9@Sz}P7Q*wp^Z(dFkGggM=CgK@8uQhS5Bca;O--cfBhg(jhGa|e
> z&nN9W6X5}Td=`Jq3`{P^?KxDR0&$^6Z*}k;(Kb3?O-x|*9<`%Q@`v4L*W+>cn|z*e
> zxBTazmZ<X+3$B;+FXS-a`P!HJ1ojEMhXl4~->l`K($B2lLvQ<*_6fYt1SG|yTAt-}
> J0s>);_#dgmGFbos
>
> literal 0
> HcmV?d00001
>
> diff --git a/tests/j_corrupt_journal_block/name b/tests/j_corrupt_journal_block/name
> new file mode 100644
> index 0000000..5d862cd
> --- /dev/null
> +++ b/tests/j_corrupt_journal_block/name
> @@ -0,0 +1 @@
> +corrupt journal block (csum v3)
> diff --git a/tests/j_corrupt_journal_block/script b/tests/j_corrupt_journal_block/script
> new file mode 100644
> index 0000000..102feba
> --- /dev/null
> +++ b/tests/j_corrupt_journal_block/script
> @@ -0,0 +1,51 @@
> +if test -x $DEBUGFS_EXE; then
> +
> +IMAGE=$test_dir/image.gz
> +FSCK_OPT=-fy
> +OUT=$test_name.log
> +if [ -f $test_dir/expect.gz ]; then
> + EXP=$test_name.tmp
> + gunzip < $test_dir/expect.gz > $EXP1
> +else
> + EXP=$test_dir/expect
> +fi
> +
> +cp /dev/null $OUT
> +
> +gzip -d < $IMAGE > $TMPFILE
> +
> +$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
> +status=$?
> +echo Exit status is $status >> $OUT.new
> +sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
> +rm -f $OUT.new
> +
> +$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
> +status=$?
> +echo Exit status is $status >> $OUT.new
> +sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
> +rm -f $OUT.new
> +
> +echo "cat /a" > $TMPFILE.cmd
> +$DEBUGFS_EXE -f $TMPFILE.cmd $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
> +rm -f $TMPFILE.cmd
> +
> +rm -f $TMPFILE
> +
> +cmp -s $OUT $EXP
> +status=$?
> +
> +if [ "$status" = 0 ] ; then
> + echo "$test_name: $test_description: ok"
> + touch $test_name.ok
> +else
> + echo "$test_name: $test_description: failed"
> + diff $DIFF_OPTS $EXP $OUT > $test_name.failed
> + rm -f $test_name.tmp
> +fi
> +
> +unset IMAGE FSCK_OPT OUT EXP
> +
> +else #if test -x $DEBUGFS_EXE; then
> + echo "$test_name: $test_description: skipped"
> +fi
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

2014-09-11 16:43:14

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 02/25] libext2fs: report bad magic over bad sb checksum

On Mon, Sep 08, 2014 at 04:11:49PM -0700, Darrick J. Wong wrote:
> We don't want ext2fs_open2() to report bad sb checksum on something
> that's not even an ext* superblock. This apparently happens pretty
> easily if we try to open an XFS filesystem. Thus, make it so that a
> bad magic number code always trumps the sb checksum error code.
>
> Signed-off-by: Darrick J. Wong <[email protected]>

Applied, thanks.

- Ted

2014-09-11 16:43:05

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 01/25] e2fsck/debugfs: fix descriptor block size handling errors with journal_csum

On Mon, Sep 08, 2014 at 04:11:43PM -0700, Darrick J. Wong wrote:
> It turns out that there are some serious problems with the on-disk
> format of journal checksum v2. The foremost is that the function to
> calculate descriptor tag size returns sizes that are too big. This
> causes alignment issues on some architectures and is compounded by the
> fact that some parts of jbd2 use the structure size (incorrectly) to
> determine the presence of a 64bit journal instead of checking the
> feature flags. These errors regrettably lead to the journal
> corruption reported by Mr. Reardon.
>
> Therefore, introduce journal checksum v3, which enlarges the
> descriptor block tag format to allow for full 32-bit checksums of
> journal blocks, fix the journal tag function to return the correct
> sizes, and fix the jbd2 recovery code to use feature flags to
> determine 64bitness.
>
> Add a few function helpers so we don't have to open-code quite so
> many pieces.
>
> Switching to a 16-byte block size was found to increase journal size
> overhead by a maximum of 0.1%, to convert a 32-bit journal with no
> checksumming to a 32-bit journal with checksum v3 enabled.
>
> Signed-off-by: Darrick J. Wong <[email protected]>
> Reported-by: TR Reardon <[email protected]>

Applied, thanks.

- Ted

2014-09-11 16:43:25

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 03/25] misc: don't return ENOMEM if we run out of disk space

On Mon, Sep 08, 2014 at 04:11:55PM -0700, Darrick J. Wong wrote:
> If there aren't enough blocks in the FS to allocate all of the
> hugefiles, return ENOSPC, not ENOMEM.
>
> Signed-off-by: Darrick J. Wong <[email protected]>

Applied, thanks.

- Ted

2014-09-11 16:43:47

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 05/25] mke2fs: allow creation of journal device with superblock checksum

On Mon, Sep 08, 2014 at 04:12:08PM -0700, Darrick J. Wong wrote:
> Enable mke2fs to create an external journal device with a superblock
> checksum.
>
> Signed-off-by: Darrick J. Wong <[email protected]>
> Cc: TR Reardon <[email protected]>

Applied, thanks.

- Ted

2014-09-11 16:43:36

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 04/25] libext2fs: write_journal_inode should check iterate return value

On Mon, Sep 08, 2014 at 04:12:02PM -0700, Darrick J. Wong wrote:
> When creating a journal inode, check the return value from
> block_iterate3() because otherwise we fail to capture errors such as
> being unable to allocate an extent tree block, which leads to e2fsck
> creating broken journals.
>
> Signed-off-by: Darrick J. Wong <[email protected]>

Applied, thanks.

- Ted

2014-09-11 16:44:01

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 06/25] e2fsck: detect and repair external journal superblock checksum errors

On Mon, Sep 08, 2014 at 04:12:15PM -0700, Darrick J. Wong wrote:
> Verify the (ext4) superblock checksum of an external journal device
> and prompt to correct the checksum if nothing else is wrong with the
> superblock.
>
> Signed-off-by: Darrick J. Wong <[email protected]>
> Cc: TR Reardon <[email protected]>

Applied, thanks.

- Ted

2014-09-11 16:44:10

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 07/25] tune2fs: explicitly disallow tuning of journal devices

On Mon, Sep 08, 2014 at 04:12:21PM -0700, Darrick J. Wong wrote:
> Spit out a more specific error if someone tries to modify an
> external journal device.
>
> Signed-off-by: Darrick J. Wong <[email protected]>
> Reported-by: TR Reardon <[email protected]>

Applied, thanks.

- Ted

2014-09-11 16:44:23

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 08/25] dumpe2fs: display external journal feature flags

On Mon, Sep 08, 2014 at 04:12:28PM -0700, Darrick J. Wong wrote:
> Display the feature flags of an external journal.
>
> Signed-off-by: Darrick J. Wong <[email protected]>
> Reported-by: TR Reardon <[email protected]>

Applied, thanks.

- Ted

2014-09-11 16:44:33

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 09/25] misc: zero s_jnl_blocks when removing internal journal

On Mon, Sep 08, 2014 at 04:12:35PM -0700, Darrick J. Wong wrote:
> When we're removing the internal journal (broken journal, turning it
> off, or adding an external journal), zero s_jnl_blocks so that they
> can't be picked up by accident later.
>
> Signed-off-by: Darrick J. Wong <[email protected]>
> Cc: TR Reardon <[email protected]>

Applied, thanks.

- Ted

2014-09-11 17:33:45

by Darrick J. Wong

[permalink] [raw]
Subject: Re: [PATCH 21/25] tests: test e2fsck recovery of corrupt descriptor blocks

On Tue, Sep 09, 2014 at 06:15:29PM -0700, Darrick J. Wong wrote:
> On Mon, Sep 08, 2014 at 04:13:55PM -0700, Darrick J. Wong wrote:
> > Test e2fsck' ability to deal with (a) corrupt descriptor block
> > checksum; (b) obviously bad journal block tid; and (c) corrupt journal
> > blocks. These should exercise the journal recovery infinite loop
> > bugfix earlier in this patchset.
> >
> > Signed-off-by: Darrick J. Wong <[email protected]>
> > ---
> > tests/j_corrupt_descr_csum/expect | 18 +++++++++++
> > tests/j_corrupt_descr_csum/image.gz | Bin
> > tests/j_corrupt_descr_csum/name | 1 +
> > tests/j_corrupt_descr_csum/script | 51 ++++++++++++++++++++++++++++++++
> > tests/j_corrupt_descr_tid/expect | 17 +++++++++++
> > tests/j_corrupt_descr_tid/image.gz | Bin
> > tests/j_corrupt_descr_tid/name | 1 +
> > tests/j_corrupt_descr_tid/script | 51 ++++++++++++++++++++++++++++++++
> > tests/j_corrupt_journal_block/expect | 19 ++++++++++++
>
> NAK, this file is incorrect. As noted in a previous email, the revoke block
> should itself be revoked (and the replay restarted) if we encounter corrupt
> blocks.
>
> Silly /me didn't consider that revoke records aren't intended to unilaterally
> kill journal blocks; they only make sense if there's a subsequent transaction
> also writing the block.

I guess that my interpretation was incorrect; see Jan Kara's reply to "jbd2:
restart replay without revokes if journal block csum fails". This test is
of course still broken, but the patchbomb is fine up through patch #20.

--D

>
> --D
>
> > tests/j_corrupt_journal_block/image.gz | Bin
> > tests/j_corrupt_journal_block/name | 1 +
> > tests/j_corrupt_journal_block/script | 51 ++++++++++++++++++++++++++++++++
> > 12 files changed, 210 insertions(+)
> > create mode 100644 tests/j_corrupt_descr_csum/expect
> > create mode 100644 tests/j_corrupt_descr_csum/image.gz
> > create mode 100644 tests/j_corrupt_descr_csum/name
> > create mode 100644 tests/j_corrupt_descr_csum/script
> > create mode 100644 tests/j_corrupt_descr_tid/expect
> > create mode 100644 tests/j_corrupt_descr_tid/image.gz
> > create mode 100644 tests/j_corrupt_descr_tid/name
> > create mode 100644 tests/j_corrupt_descr_tid/script
> > create mode 100644 tests/j_corrupt_journal_block/expect
> > create mode 100644 tests/j_corrupt_journal_block/image.gz
> > create mode 100644 tests/j_corrupt_journal_block/name
> > create mode 100644 tests/j_corrupt_journal_block/script
> >
> >
> > diff --git a/tests/j_corrupt_descr_csum/expect b/tests/j_corrupt_descr_csum/expect
> > new file mode 100644
> > index 0000000..419e775
> > --- /dev/null
> > +++ b/tests/j_corrupt_descr_csum/expect
> > @@ -0,0 +1,18 @@
> > +test_filesys: recovering journal
> > +../e2fsck/e2fsck: Input/output error while recovering ext3 journal of test_filesys
> > +
> > +test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
> > +
> > +test_filesys: ********** WARNING: Filesystem still has errors **********
> > +
> > +Exit status is 12
> > +test_filesys: recovering journal
> > +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/128 files (8.3% non-contiguous), 1093/2048 blocks
> > +Exit status is 0
> > +debugfs: cat /a
> > +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
> aa!
> > aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
> aa!
> > aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
> > aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
> aa!
> > aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
> > \ No newline at end of file
> > diff --git a/tests/j_corrupt_descr_csum/image.gz b/tests/j_corrupt_descr_csum/image.gz
> > new file mode 100644
> > index 0000000000000000000000000000000000000000..2a81e5daeb13fcec40d8fa9ef95151427a35b584
> > GIT binary patch
> > literal 2989
> > zcmeIz{WIGK90%~AZF)0h>dI+O^eVOMRO%2mCN1k(kuutNzHG8aiAYOP59jORX~~qf
> > zPSS`*v#nb591mqkHuKO<mLQ6GTxcjMsfR4`^!;x8vHk?-^V{b>_xa)dy3gGQ`TbGY
> > z$Pq=DvB~-z?gru-0`|_Mn^TF_v5)XB=Bq*(2|FR5d@zVN{rt|z(X6DlB1Q`jQ$eHA
> > z8LUN|i=DSs)<-m}v+EZbs;{5n3j@%DKTO7rT%FE`yNHKHzCIY+@4m$?t4*n-3{rYL
> > zRIZWqu>X2wZ5(p-_ZF#*FEFjENA!hE2a|$F*cG0!*_nI~rbAG$`U=WbO2Ji!J2nU!
> > zQNY&C>67TfcX6l!M~;}#og>@C4jmJw$m?GB2X14B8d+r@p2Jp}nHIT;v-GR6j=?>^
> > zTYBmCab2-_&*(Ps!A`+MD8_kkG^Z7DwzUQ=m$9}o=DAE<0y}^eM*UMmt=g_XZ3s*Z
> > zx^@|E*ASt8)|Bnztr}i#12UpEs$W99+p!Y7C_h}N$^01M(>X;}BRo@wEf2xot2}6M
> > z2kI}<7GS;24xdm`q_z)2!(VKqN^Jw4G&a7q^P%v%+|J)gx)Bfky?MHLvD3o2qWmWb
> > z={UaKjRk1yWNW3&ObyUmCC4^*Yy;7fp|H)(2EN?r(lBIQDiGknd_DX%)*dp_n7;rn
> > zfF@hWdr+PpjwgVGoHxIX?j+3HrajS~$3({-OXV0ZSbDinZ*ryms>H+z?R~!=QDoyw
> > z%oTvEtmu6uTPRhhIaU3_N3Xk~eFTEUBu?I?ajmSE@P*$kZ#c~AO0J&pheTc2y5Q~r
> > z-4=~_MJAUS20h>sPa4hr7T9zOn+Evja;Z%y6Y@-NKC%ZxhOnut$!hDBbY}_#$Rh(S
> > zCPXS>QI2rIrnsy$#*orJu&6~k&H0DL8YCu#?sXtiVpLH6Xin)|3qlhcijK$4q%}w}
> > zriF;Fw7|lYN%lDO&H87C%PDIXArY<rjTSL7v6QGj*8l=|1M+`-JiS5way~J#Hgn_Q
> > z&%mtE$Cf0}AeNFPftVTupJU=KjzLfaY*E+quMi#AyEXx&ufNSy&MN!qOk6F9Wbnml
> > z=2l)SXPm9QKy@xUU9ZD7LGd<rbb3Us(=6!7OJyq!<H8cG-hUQEc`Pf7@!nvw%Qyq8
> > zJ0l8moC8@aNzjsj=c*ivev=eDT+<d*;TMqzTd5@Kg}qUdUB&A3<bW7bQ70kSm=aa>
> > zMwChz3KB=wwAkmMw369zU99U9bb?6WDOUll-gkQV&ta9&q1#^Yr2!2_<SH$x>7TZc
> > zXUyA+JnjzdQcLg(prv0EuAseldwZG-hJlVCVpxq?0-eI0Kf%WnIAdc~Oy<3IbyjxN
> > zL~(uZ(%n;JrOlqTgZ4n+Kw$p~Jf7FWV0nEv5AFF_`!DH1q62~bCGcy&?#Ysla&s8W
> > G9`-Nik0OEq
> >
> > literal 0
> > HcmV?d00001
> >
> > diff --git a/tests/j_corrupt_descr_csum/name b/tests/j_corrupt_descr_csum/name
> > new file mode 100644
> > index 0000000..e15ccfb
> > --- /dev/null
> > +++ b/tests/j_corrupt_descr_csum/name
> > @@ -0,0 +1 @@
> > +corrupt descr csum (csum v3)
> > diff --git a/tests/j_corrupt_descr_csum/script b/tests/j_corrupt_descr_csum/script
> > new file mode 100644
> > index 0000000..102feba
> > --- /dev/null
> > +++ b/tests/j_corrupt_descr_csum/script
> > @@ -0,0 +1,51 @@
> > +if test -x $DEBUGFS_EXE; then
> > +
> > +IMAGE=$test_dir/image.gz
> > +FSCK_OPT=-fy
> > +OUT=$test_name.log
> > +if [ -f $test_dir/expect.gz ]; then
> > + EXP=$test_name.tmp
> > + gunzip < $test_dir/expect.gz > $EXP1
> > +else
> > + EXP=$test_dir/expect
> > +fi
> > +
> > +cp /dev/null $OUT
> > +
> > +gzip -d < $IMAGE > $TMPFILE
> > +
> > +$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
> > +status=$?
> > +echo Exit status is $status >> $OUT.new
> > +sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
> > +rm -f $OUT.new
> > +
> > +$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
> > +status=$?
> > +echo Exit status is $status >> $OUT.new
> > +sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
> > +rm -f $OUT.new
> > +
> > +echo "cat /a" > $TMPFILE.cmd
> > +$DEBUGFS_EXE -f $TMPFILE.cmd $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
> > +rm -f $TMPFILE.cmd
> > +
> > +rm -f $TMPFILE
> > +
> > +cmp -s $OUT $EXP
> > +status=$?
> > +
> > +if [ "$status" = 0 ] ; then
> > + echo "$test_name: $test_description: ok"
> > + touch $test_name.ok
> > +else
> > + echo "$test_name: $test_description: failed"
> > + diff $DIFF_OPTS $EXP $OUT > $test_name.failed
> > + rm -f $test_name.tmp
> > +fi
> > +
> > +unset IMAGE FSCK_OPT OUT EXP
> > +
> > +else #if test -x $DEBUGFS_EXE; then
> > + echo "$test_name: $test_description: skipped"
> > +fi
> > diff --git a/tests/j_corrupt_descr_tid/expect b/tests/j_corrupt_descr_tid/expect
> > new file mode 100644
> > index 0000000..0444203
> > --- /dev/null
> > +++ b/tests/j_corrupt_descr_tid/expect
> > @@ -0,0 +1,17 @@
> > +test_filesys: recovering journal
> > +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/128 files (8.3% non-contiguous), 1093/2048 blocks
> > +Exit status is 0
> > +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/128 files (8.3% non-contiguous), 1093/2048 blocks
> > +Exit status is 0
> > +debugfs: cat /a
> > +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
> aa!
> > aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
> aa!
> > aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
> > aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
> aa!
> > aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
> > \ No newline at end of file
> > diff --git a/tests/j_corrupt_descr_tid/image.gz b/tests/j_corrupt_descr_tid/image.gz
> > new file mode 100644
> > index 0000000000000000000000000000000000000000..3ad88f9d15549c24758ae53015a08b62f938f5f8
> > GIT binary patch
> > literal 2999
> > zcmeIw|1;Zn90%}dw7R;Loo_88Y`3Xv6<1ptN~l)q)S|TYU0ROBx6oy%FKP6&i!p6?
> > zH;sx>U2!3%i3k;up<zb|O3ark3*yU3NMy*D&wIBY+dsj1{r3Ff^~3Y=dLc@V!s3k9
> > zLl40>-eFVCZ=8T_B6(3~YIW4U2mUr&7mE&~?ETG7pZdheB+|?)L|Etl(zn>*T6|-l
> > z@m3wn?!uD{H-{e$;YJtV6dGO*a*bwQYQFSB_-A(^tE;VrzAe5<AAiMFX@6;J@jSO7
> > zM~aZDjjQ<BqdwO@t*1&%HPZQ1)PtJyqOZjxWo_;_%wBGKazuIgimkXo)%3V|y+uMH
> > zMr;Us?_|`N_mq^GRz>G7uho(sgPgeevO!z|Cbj}XaXa&G5uj0KrCVL*m`W`7&Rs0@
> > z!~Rfpa>lDuHdKXZVLEbX$|R>pT>4V*Gj|HZ@*d+~I<k-J!QE=F%(dwP4NlD-QUS9&
> > zy6n92maqdudZ!&_;UsSsyjW?C%OE&<Qe{C>l%?OZI|k3gYo~1UzMEqk8o)l7d4by&
> > zn#D#fm|%VG*XGS|sLXL&rFND>4Po#+1ypgz$jxc=T>^mw<`>}FF^=ikr!7ozqM0S9
> > zd=Ral_&(t+J86&7R4GHhYFAPG#E#O{y(adO!R0|<b-b&~7b?^lEu!s#!Jf%q6dwq#
> > zL_7fnIwQ+isG73UJ-W-5*ksm1?wL_B$3uCCaCAHCZK+pn$@;_bCiRzE|3HahG4m;i
> > z=&*E6R19l&(_OYRhbwvP)83pRZ~klRRC+-~Co64lYSn6v_l0$_6a{;pk^CM6wo1th
> > z<JrzrXfl3<A1lAoD``7|)f_oo^3N_VaAQROTdOqR)A?lhtlUPo*&3h)YYg57u5#`|
> > zn;tCToqfYUmjR{q^N#oFK~fCnkNnpoad#k-Ww~@q4$1EKR9px3@vsHLq-1CLIuP*n
> > z70##5RA?vxOn_*d1Y}3MziS|>aDBIaibeLh9n=75FVlKr`mwX<HVybygZTdnmPP8N
> > zb-p@_H%EGVS0#niqrv(?nRzy*X(@ETL4XQQQ7;l^hEfOkrDN@_s#2ge_2`AZv8v9=
> > zjY(Dm>I)_*YRAe`)_2yz6WXD;Wa)V5bO?XKF5stdhG-VT*Q8Vlv<%8K?@i1!lz^;L
> > zP>FfE+cya26o}?JL2cK&V5gvZvR_zQIkBe2jXS|ArTLYo!0Km0bOQdgXqUdaHYpqi
> > z77BN8t`e&jOZ?S1MwT0atgns)oPI8`N<k)uMFJDSj7SZ3uh?Df|5@WQh%FL_fZCF!
> > z?BT6MT71;Ex)FkI%-9LC`CYAXY2Aj@k)|Jf;YWecHBL)f8{mA!9ha@zIw;hcNvUZp
> > zXX6}7^I&|`XG-W%*uzdi{6|{{@j&1}VE+jeB(B3@uw%VQ`~BDLpwWTAz7`--1qKMw
> > Kr~n4Dhy4e5RXFwl
> >
> > literal 0
> > HcmV?d00001
> >
> > diff --git a/tests/j_corrupt_descr_tid/name b/tests/j_corrupt_descr_tid/name
> > new file mode 100644
> > index 0000000..2325d6d
> > --- /dev/null
> > +++ b/tests/j_corrupt_descr_tid/name
> > @@ -0,0 +1 @@
> > +corrupt descr tid (csum v3)
> > diff --git a/tests/j_corrupt_descr_tid/script b/tests/j_corrupt_descr_tid/script
> > new file mode 100644
> > index 0000000..102feba
> > --- /dev/null
> > +++ b/tests/j_corrupt_descr_tid/script
> > @@ -0,0 +1,51 @@
> > +if test -x $DEBUGFS_EXE; then
> > +
> > +IMAGE=$test_dir/image.gz
> > +FSCK_OPT=-fy
> > +OUT=$test_name.log
> > +if [ -f $test_dir/expect.gz ]; then
> > + EXP=$test_name.tmp
> > + gunzip < $test_dir/expect.gz > $EXP1
> > +else
> > + EXP=$test_dir/expect
> > +fi
> > +
> > +cp /dev/null $OUT
> > +
> > +gzip -d < $IMAGE > $TMPFILE
> > +
> > +$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
> > +status=$?
> > +echo Exit status is $status >> $OUT.new
> > +sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
> > +rm -f $OUT.new
> > +
> > +$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
> > +status=$?
> > +echo Exit status is $status >> $OUT.new
> > +sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
> > +rm -f $OUT.new
> > +
> > +echo "cat /a" > $TMPFILE.cmd
> > +$DEBUGFS_EXE -f $TMPFILE.cmd $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
> > +rm -f $TMPFILE.cmd
> > +
> > +rm -f $TMPFILE
> > +
> > +cmp -s $OUT $EXP
> > +status=$?
> > +
> > +if [ "$status" = 0 ] ; then
> > + echo "$test_name: $test_description: ok"
> > + touch $test_name.ok
> > +else
> > + echo "$test_name: $test_description: failed"
> > + diff $DIFF_OPTS $EXP $OUT > $test_name.failed
> > + rm -f $test_name.tmp
> > +fi
> > +
> > +unset IMAGE FSCK_OPT OUT EXP
> > +
> > +else #if test -x $DEBUGFS_EXE; then
> > + echo "$test_name: $test_description: skipped"
> > +fi
> > diff --git a/tests/j_corrupt_journal_block/expect b/tests/j_corrupt_journal_block/expect
> > new file mode 100644
> > index 0000000..50d0b78
> > --- /dev/null
> > +++ b/tests/j_corrupt_journal_block/expect
> > @@ -0,0 +1,19 @@
> > +test_filesys: recovering journal
> > +JBD2: Invalid checksum recovering block 1090 in log
> > +../e2fsck/e2fsck: Input/output error while recovering ext3 journal of test_filesys
> > +
> > +test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
> > +
> > +test_filesys: ********** WARNING: Filesystem still has errors **********
> > +
> > +Exit status is 12
> > +test_filesys: recovering journal
> > +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/128 files (8.3% non-contiguous), 1093/2048 blocks
> > +Exit status is 0
> > +debugfs: cat /a
> > +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
> aa!
> > aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb!
> bb!
> > bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb!
> > bbbbbbbbbbddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd!
> dd!
> > dddddddddddddddddddddddddddddddddddddddddddddd
> > \ No newline at end of file
> > diff --git a/tests/j_corrupt_journal_block/image.gz b/tests/j_corrupt_journal_block/image.gz
> > new file mode 100644
> > index 0000000000000000000000000000000000000000..f60439f02ea11289639dc2c3e5108bf5b3a662bb
> > GIT binary patch
> > literal 2998
> > zcmeH{`#0Nn9L9rfY+4+;QXJ8)&h)G}+k!eQ>1>_4giaLA7>#RO>N2;ueW^>kso1n`
> > zO;J5_=`;xHn$l$@npC2RTd<}|o6vm|;>Zp8tiQH@LXY=v&kye(p4ao72U(_v@YH#Y
> > z)7F9i#l~8mw?u3>4^wV-_N@gO8KZ(7no-nmrhmIkn{hX^LS449pf(c{+px{I33pyJ
> > zXW_2t8kU3<TbFp{*p6j)1+=@{)Xd(QBTNM>6zP7+VLx$4JDFci!@g4JCq-vQXT*T(
> > zDlWZFP;aVzE})3UH)9m`W_DOIPA~Yi_)S$+oeIq%(VeT0`}oRzkK_1>XB&e)r;c>k
> > zK(ez7!@-{{H+$*%Io3bOSM8cWWUJh5*4*RGniz;o?X<KC&PBD04iIn2m0LM}mS97C
> > zy*{QBKC-kE$gS|?nc%$z17;pu)YLW~%E*l?VJsmj0zdm_)Ui<C2aY14)5?Vyb<K3`
> > zUzG-K{xr#tVG1Z$R&$>SMtTz(S)ed2lpFXYFG8qsGcu4+r1xDF4MT|^Ya`yehfstJ
> > zBBbXrkhhAp%M^XYgPwO?BNc<hgU$Y#nHh$S+f9RMZ9x3+mChd1Kw7clJ`mtriKbwK
> > zdAtzKT4yN@Yu6(KKe(`=aFPh};I^7<Zo=I!wa&1CX$Af1QShxsM~3_z6zuA*VyuCd
> > z%5VZYt<mvz01j@uQ^{&nQu&a7o*9K|f29sv*jZL@4rg&=Uu2(fjNcP$mMa|#kFmEf
> > zTm`FReM4$5Pv_JRb-ThSE@osTE`d@&q7UZ1928*ain3T+vPi3d@wftbt5hS&>YdWn
> > zM)HwtCL5*+l^NiK$GNVP9N@UxDv@%yTX1(|IBAgwp1$VG0j@@pkxPo+V#q;IL(c~n
> > z1tB1QLa|exqTHC85AwD<JO{#;(RE^US5&oW0i!k$REQ9aUpo?|4s9C1AzSp_?n+n(
> > zU+~mmWkwAN#YL_&;G)W0b<$-JX?u^j4L(hwBy%UkI{NLPF%am!$)Lc7@EwWXkC#ll
> > zIb)|Wk}#w`PMAwh=@;2p;0y$lh32jHWGA6l^wOfO!B743N=UEiYfF62njmJD>A#0L
> > z6ji^N(Khdr38&Ilz;gwGIVvhsL#2N=)n2V)Ey0lS&|%dxKfqQNL66|D)L-QJVlorC
> > z;7(QcBr$x_c`!s8mt!OrL$Z8&31__bo+tZzm*SF-l3QHH!D9UOwb6zS2>0J^*!HD8
> > z%s(Z;KoHoj31UG9@Sz}P7Q*wp^Z(dFkGggM=CgK@8uQhS5Bca;O--cfBhg(jhGa|e
> > z&nN9W6X5}Td=`Jq3`{P^?KxDR0&$^6Z*}k;(Kb3?O-x|*9<`%Q@`v4L*W+>cn|z*e
> > zxBTazmZ<X+3$B;+FXS-a`P!HJ1ojEMhXl4~->l`K($B2lLvQ<*_6fYt1SG|yTAt-}
> > J0s>);_#dgmGFbos
> >
> > literal 0
> > HcmV?d00001
> >
> > diff --git a/tests/j_corrupt_journal_block/name b/tests/j_corrupt_journal_block/name
> > new file mode 100644
> > index 0000000..5d862cd
> > --- /dev/null
> > +++ b/tests/j_corrupt_journal_block/name
> > @@ -0,0 +1 @@
> > +corrupt journal block (csum v3)
> > diff --git a/tests/j_corrupt_journal_block/script b/tests/j_corrupt_journal_block/script
> > new file mode 100644
> > index 0000000..102feba
> > --- /dev/null
> > +++ b/tests/j_corrupt_journal_block/script
> > @@ -0,0 +1,51 @@
> > +if test -x $DEBUGFS_EXE; then
> > +
> > +IMAGE=$test_dir/image.gz
> > +FSCK_OPT=-fy
> > +OUT=$test_name.log
> > +if [ -f $test_dir/expect.gz ]; then
> > + EXP=$test_name.tmp
> > + gunzip < $test_dir/expect.gz > $EXP1
> > +else
> > + EXP=$test_dir/expect
> > +fi
> > +
> > +cp /dev/null $OUT
> > +
> > +gzip -d < $IMAGE > $TMPFILE
> > +
> > +$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
> > +status=$?
> > +echo Exit status is $status >> $OUT.new
> > +sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
> > +rm -f $OUT.new
> > +
> > +$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
> > +status=$?
> > +echo Exit status is $status >> $OUT.new
> > +sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
> > +rm -f $OUT.new
> > +
> > +echo "cat /a" > $TMPFILE.cmd
> > +$DEBUGFS_EXE -f $TMPFILE.cmd $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
> > +rm -f $TMPFILE.cmd
> > +
> > +rm -f $TMPFILE
> > +
> > +cmp -s $OUT $EXP
> > +status=$?
> > +
> > +if [ "$status" = 0 ] ; then
> > + echo "$test_name: $test_description: ok"
> > + touch $test_name.ok
> > +else
> > + echo "$test_name: $test_description: failed"
> > + diff $DIFF_OPTS $EXP $OUT > $test_name.failed
> > + rm -f $test_name.tmp
> > +fi
> > +
> > +unset IMAGE FSCK_OPT OUT EXP
> > +
> > +else #if test -x $DEBUGFS_EXE; then
> > + echo "$test_name: $test_description: skipped"
> > +fi
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> > the body of a message to [email protected]
> > More majordomo info at http://vger.kernel.org/majordomo-info.html
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

2014-09-11 18:18:52

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 21/25] tests: test e2fsck recovery of corrupt descriptor blocks

On Thu, Sep 11, 2014 at 10:33:37AM -0700, Darrick J. Wong wrote:
> I guess that my interpretation was incorrect; see Jan Kara's reply to "jbd2:
> restart replay without revokes if journal block csum fails". This test is
> of course still broken, but the patchbomb is fine up through patch #20.

Is patch #22 ok?

- Ted

2014-09-11 18:40:23

by Darrick J. Wong

[permalink] [raw]
Subject: Re: [PATCH 21/25] tests: test e2fsck recovery of corrupt descriptor blocks

On Thu, Sep 11, 2014 at 02:18:48PM -0400, Theodore Ts'o wrote:
> On Thu, Sep 11, 2014 at 10:33:37AM -0700, Darrick J. Wong wrote:
> > I guess that my interpretation was incorrect; see Jan Kara's reply to "jbd2:
> > restart replay without revokes if journal block csum fails". This test is
> > of course still broken, but the patchbomb is fine up through patch #20.
>
> Is patch #22 ok?

Yeah, everything but #21 is ok. I'll issue a new #21 shortly.

(and four other patches to fix other problems e2fuzz found along the way...)

--D

>
> - Ted
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

2014-09-11 18:53:46

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 10/25] debugfs: create journal handling routines

On Mon, Sep 08, 2014 at 04:12:42PM -0700, Darrick J. Wong wrote:
> +recovery.o: $(srcdir)/../e2fsck/recovery.c
> + cp $(srcdir)/../e2fsck/recovery.c $(srcdir)/recovery.c
> + $(E) " CC $@"
> + $(Q) $(CC) -c $(ALL_CFLAGS) -I$(srcdir) \
> + $(srcdir)/recovery.c -DDEBUGFS -o $@
> +
> +revoke.o: $(srcdir)/../e2fsck/revoke.c
> + cp $(srcdir)/../e2fsck/revoke.c $(srcdir)/revoke.c
> + $(E) " CC $@"
> + $(Q) $(CC) -c $(ALL_CFLAGS) -I$(srcdir) \
> + $(srcdir)/revoke.c -DDEBUGFS -o $@
> +

Please don't copy the .c files around. That just invites confusion
because git will show that there are new files, debugfs/recovery.c and
debugfs/revoke.c, and some future unwary developer might try to edit
recovery.c and revoke.c in the debugfs directory.

Much better to do it this way:

recovery.o: $(srcdir)/../e2fsck/recovery.c
$(E) " CC $@"
$(Q) $(CC) -c $(ALL_CFLAGS) -I$(srcdir) \
$(srcdir)/../e2fsck/recovery.c -DDEBUGFS -o $@

revoke.o: $(srcdir)/../e2fsck/revoke.c
$(E) " CC $@"
$(Q) $(CC) -c $(ALL_CFLAGS) -I$(srcdir) \
$(srcdir)/../e2fsck/revoke.c -DDEBUGFS -o $@

I'll fix this up when I apply this patch.

Cheers,

- Ted

2014-09-11 19:03:54

by Darrick J. Wong

[permalink] [raw]
Subject: Re: [PATCH 10/25] debugfs: create journal handling routines

On Thu, Sep 11, 2014 at 02:53:43PM -0400, Theodore Ts'o wrote:
> On Mon, Sep 08, 2014 at 04:12:42PM -0700, Darrick J. Wong wrote:
> > +recovery.o: $(srcdir)/../e2fsck/recovery.c
> > + cp $(srcdir)/../e2fsck/recovery.c $(srcdir)/recovery.c
> > + $(E) " CC $@"
> > + $(Q) $(CC) -c $(ALL_CFLAGS) -I$(srcdir) \
> > + $(srcdir)/recovery.c -DDEBUGFS -o $@
> > +
> > +revoke.o: $(srcdir)/../e2fsck/revoke.c
> > + cp $(srcdir)/../e2fsck/revoke.c $(srcdir)/revoke.c
> > + $(E) " CC $@"
> > + $(Q) $(CC) -c $(ALL_CFLAGS) -I$(srcdir) \
> > + $(srcdir)/revoke.c -DDEBUGFS -o $@
> > +
>
> Please don't copy the .c files around. That just invites confusion
> because git will show that there are new files, debugfs/recovery.c and
> debugfs/revoke.c, and some future unwary developer might try to edit
> recovery.c and revoke.c in the debugfs directory.
>
> Much better to do it this way:
>
> recovery.o: $(srcdir)/../e2fsck/recovery.c
> $(E) " CC $@"
> $(Q) $(CC) -c $(ALL_CFLAGS) -I$(srcdir) \
> $(srcdir)/../e2fsck/recovery.c -DDEBUGFS -o $@
>
> revoke.o: $(srcdir)/../e2fsck/revoke.c
> $(E) " CC $@"
> $(Q) $(CC) -c $(ALL_CFLAGS) -I$(srcdir) \
> $(srcdir)/../e2fsck/revoke.c -DDEBUGFS -o $@
>
> I'll fix this up when I apply this patch.

Will that pick up debugfs/jfs_user.h, though? I originally tried it this way
but gcc seemed to want to pull in the jfs_user.h from e2fsck/.

--D

>
> Cheers,
>
> - Ted
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

2014-09-11 19:31:47

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 21/25 v2] tests: test e2fsck recovery of corrupt descriptor blocks

Test e2fsck' ability to deal with (a) corrupt descriptor block
checksum; (b) obviously bad journal block tid; and (c) corrupt journal
blocks. These should exercise the journal recovery infinite loop
bugfix earlier in this patchset.

This test also ensures that (with metadata_csum and journal_csum_v3)
journal replay continues past a corrupt journal block.

v2: Update j_corrupt_journal_block after a clarification of what
revoke records actually do.

Signed-off-by: Darrick J. Wong <[email protected]>
---
tests/j_corrupt_descr_csum/expect | 18 +++++++++++
tests/j_corrupt_descr_csum/image.gz | Bin
tests/j_corrupt_descr_csum/name | 1 +
tests/j_corrupt_descr_csum/script | 51 +++++++++++++++++++++++++++++++
tests/j_corrupt_descr_tid/expect | 17 ++++++++++
tests/j_corrupt_descr_tid/image.gz | Bin
tests/j_corrupt_descr_tid/name | 1 +
tests/j_corrupt_descr_tid/script | 51 +++++++++++++++++++++++++++++++
tests/j_corrupt_journal_block/expect | 19 ++++++++++++
tests/j_corrupt_journal_block/image.gz | Bin
tests/j_corrupt_journal_block/name | 1 +
tests/j_corrupt_journal_block/script | 52 ++++++++++++++++++++++++++++++++
12 files changed, 211 insertions(+)
create mode 100644 tests/j_corrupt_descr_csum/expect
create mode 100644 tests/j_corrupt_descr_csum/image.gz
create mode 100644 tests/j_corrupt_descr_csum/name
create mode 100644 tests/j_corrupt_descr_csum/script
create mode 100644 tests/j_corrupt_descr_tid/expect
create mode 100644 tests/j_corrupt_descr_tid/image.gz
create mode 100644 tests/j_corrupt_descr_tid/name
create mode 100644 tests/j_corrupt_descr_tid/script
create mode 100644 tests/j_corrupt_journal_block/expect
create mode 100644 tests/j_corrupt_journal_block/image.gz
create mode 100644 tests/j_corrupt_journal_block/name
create mode 100644 tests/j_corrupt_journal_block/script

diff --git a/tests/j_corrupt_descr_csum/expect b/tests/j_corrupt_descr_csum/expect
new file mode 100644
index 0000000..419e775
--- /dev/null
+++ b/tests/j_corrupt_descr_csum/expect
@@ -0,0 +1,18 @@
+test_filesys: recovering journal
+../e2fsck/e2fsck: Input/output error while recovering ext3 journal of test_filesys
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+
+test_filesys: ********** WARNING: Filesystem still has errors **********
+
+Exit status is 12
+test_filesys: recovering journal
+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/128 files (8.3% non-contiguous), 1093/2048 blocks
+Exit status is 0
+debugfs: cat /a
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
\ No newline at end of file
diff --git a/tests/j_corrupt_descr_csum/image.gz b/tests/j_corrupt_descr_csum/image.gz
new file mode 100644
index 0000000000000000000000000000000000000000..2a81e5daeb13fcec40d8fa9ef95151427a35b584
GIT binary patch
literal 2989
zcmeIz{WIGK90%~AZF)0h>dI+O^eVOMRO%2mCN1k(kuutNzHG8aiAYOP59jORX~~qf
zPSS`*v#nb591mqkHuKO<mLQ6GTxcjMsfR4`^!;x8vHk?-^V{b>_xa)dy3gGQ`TbGY
z$Pq=DvB~-z?gru-0`|_Mn^TF_v5)XB=Bq*(2|FR5d@zVN{rt|z(X6DlB1Q`jQ$eHA
z8LUN|i=DSs)<-m}v+EZbs;{5n3j@%DKTO7rT%FE`yNHKHzCIY+@4m$?t4*n-3{rYL
zRIZWqu>X2wZ5(p-_ZF#*FEFjENA!hE2a|$F*cG0!*_nI~rbAG$`U=WbO2Ji!J2nU!
zQNY&C>67TfcX6l!M~;}#og>@C4jmJw$m?GB2X14B8d+r@p2Jp}nHIT;v-GR6j=?>^
zTYBmCab2-_&*(Ps!A`+MD8_kkG^Z7DwzUQ=m$9}o=DAE<0y}^eM*UMmt=g_XZ3s*Z
zx^@|E*ASt8)|Bnztr}i#12UpEs$W99+p!Y7C_h}N$^01M(>X;}BRo@wEf2xot2}6M
z2kI}<7GS;24xdm`q_z)2!(VKqN^Jw4G&a7q^P%v%+|J)gx)Bfky?MHLvD3o2qWmWb
z={UaKjRk1yWNW3&ObyUmCC4^*Yy;7fp|H)(2EN?r(lBIQDiGknd_DX%)*dp_n7;rn
zfF@hWdr+PpjwgVGoHxIX?j+3HrajS~$3({-OXV0ZSbDinZ*ryms>H+z?R~!=QDoyw
z%oTvEtmu6uTPRhhIaU3_N3Xk~eFTEUBu?I?ajmSE@P*$kZ#c~AO0J&pheTc2y5Q~r
z-4=~_MJAUS20h>sPa4hr7T9zOn+Evja;Z%y6Y@-NKC%ZxhOnut$!hDBbY}_#$Rh(S
zCPXS>QI2rIrnsy$#*orJu&6~k&H0DL8YCu#?sXtiVpLH6Xin)|3qlhcijK$4q%}w}
zriF;Fw7|lYN%lDO&H87C%PDIXArY<rjTSL7v6QGj*8l=|1M+`-JiS5way~J#Hgn_Q
z&%mtE$Cf0}AeNFPftVTupJU=KjzLfaY*E+quMi#AyEXx&ufNSy&MN!qOk6F9Wbnml
z=2l)SXPm9QKy@xUU9ZD7LGd<rbb3Us(=6!7OJyq!<H8cG-hUQEc`Pf7@!nvw%Qyq8
zJ0l8moC8@aNzjsj=c*ivev=eDT+<d*;TMqzTd5@Kg}qUdUB&A3<bW7bQ70kSm=aa>
zMwChz3KB=wwAkmMw369zU99U9bb?6WDOUll-gkQV&ta9&q1#^Yr2!2_<SH$x>7TZc
zXUyA+JnjzdQcLg(prv0EuAseldwZG-hJlVCVpxq?0-eI0Kf%WnIAdc~Oy<3IbyjxN
zL~(uZ(%n;JrOlqTgZ4n+Kw$p~Jf7FWV0nEv5AFF_`!DH1q62~bCGcy&?#Ysla&s8W
G9`-Nik0OEq

literal 0
HcmV?d00001

diff --git a/tests/j_corrupt_descr_csum/name b/tests/j_corrupt_descr_csum/name
new file mode 100644
index 0000000..e15ccfb
--- /dev/null
+++ b/tests/j_corrupt_descr_csum/name
@@ -0,0 +1 @@
+corrupt descr csum (csum v3)
diff --git a/tests/j_corrupt_descr_csum/script b/tests/j_corrupt_descr_csum/script
new file mode 100644
index 0000000..102feba
--- /dev/null
+++ b/tests/j_corrupt_descr_csum/script
@@ -0,0 +1,51 @@
+if test -x $DEBUGFS_EXE; then
+
+IMAGE=$test_dir/image.gz
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+gzip -d < $IMAGE > $TMPFILE
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+echo "cat /a" > $TMPFILE.cmd
+$DEBUGFS_EXE -f $TMPFILE.cmd $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+rm -f $TMPFILE.cmd
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi
diff --git a/tests/j_corrupt_descr_tid/expect b/tests/j_corrupt_descr_tid/expect
new file mode 100644
index 0000000..0444203
--- /dev/null
+++ b/tests/j_corrupt_descr_tid/expect
@@ -0,0 +1,17 @@
+test_filesys: recovering journal
+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/128 files (8.3% non-contiguous), 1093/2048 blocks
+Exit status is 0
+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/128 files (8.3% non-contiguous), 1093/2048 blocks
+Exit status is 0
+debugfs: cat /a
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
\ No newline at end of file
diff --git a/tests/j_corrupt_descr_tid/image.gz b/tests/j_corrupt_descr_tid/image.gz
new file mode 100644
index 0000000000000000000000000000000000000000..3ad88f9d15549c24758ae53015a08b62f938f5f8
GIT binary patch
literal 2999
zcmeIw|1;Zn90%}dw7R;Loo_88Y`3Xv6<1ptN~l)q)S|TYU0ROBx6oy%FKP6&i!p6?
zH;sx>U2!3%i3k;up<zb|O3ark3*yU3NMy*D&wIBY+dsj1{r3Ff^~3Y=dLc@V!s3k9
zLl40>-eFVCZ=8T_B6(3~YIW4U2mUr&7mE&~?ETG7pZdheB+|?)L|Etl(zn>*T6|-l
z@m3wn?!uD{H-{e$;YJtV6dGO*a*bwQYQFSB_-A(^tE;VrzAe5<AAiMFX@6;J@jSO7
zM~aZDjjQ<BqdwO@t*1&%HPZQ1)PtJyqOZjxWo_;_%wBGKazuIgimkXo)%3V|y+uMH
zMr;Us?_|`N_mq^GRz>G7uho(sgPgeevO!z|Cbj}XaXa&G5uj0KrCVL*m`W`7&Rs0@
z!~Rfpa>lDuHdKXZVLEbX$|R>pT>4V*Gj|HZ@*d+~I<k-J!QE=F%(dwP4NlD-QUS9&
zy6n92maqdudZ!&_;UsSsyjW?C%OE&<Qe{C>l%?OZI|k3gYo~1UzMEqk8o)l7d4by&
zn#D#fm|%VG*XGS|sLXL&rFND>4Po#+1ypgz$jxc=T>^mw<`>}FF^=ikr!7ozqM0S9
zd=Ral_&(t+J86&7R4GHhYFAPG#E#O{y(adO!R0|<b-b&~7b?^lEu!s#!Jf%q6dwq#
zL_7fnIwQ+isG73UJ-W-5*ksm1?wL_B$3uCCaCAHCZK+pn$@;_bCiRzE|3HahG4m;i
z=&*E6R19l&(_OYRhbwvP)83pRZ~klRRC+-~Co64lYSn6v_l0$_6a{;pk^CM6wo1th
z<JrzrXfl3<A1lAoD``7|)f_oo^3N_VaAQROTdOqR)A?lhtlUPo*&3h)YYg57u5#`|
zn;tCToqfYUmjR{q^N#oFK~fCnkNnpoad#k-Ww~@q4$1EKR9px3@vsHLq-1CLIuP*n
z70##5RA?vxOn_*d1Y}3MziS|>aDBIaibeLh9n=75FVlKr`mwX<HVybygZTdnmPP8N
zb-p@_H%EGVS0#niqrv(?nRzy*X(@ETL4XQQQ7;l^hEfOkrDN@_s#2ge_2`AZv8v9=
zjY(Dm>I)_*YRAe`)_2yz6WXD;Wa)V5bO?XKF5stdhG-VT*Q8Vlv<%8K?@i1!lz^;L
zP>FfE+cya26o}?JL2cK&V5gvZvR_zQIkBe2jXS|ArTLYo!0Km0bOQdgXqUdaHYpqi
z77BN8t`e&jOZ?S1MwT0atgns)oPI8`N<k)uMFJDSj7SZ3uh?Df|5@WQh%FL_fZCF!
z?BT6MT71;Ex)FkI%-9LC`CYAXY2Aj@k)|Jf;YWecHBL)f8{mA!9ha@zIw;hcNvUZp
zXX6}7^I&|`XG-W%*uzdi{6|{{@j&1}VE+jeB(B3@uw%VQ`~BDLpwWTAz7`--1qKMw
Kr~n4Dhy4e5RXFwl

literal 0
HcmV?d00001

diff --git a/tests/j_corrupt_descr_tid/name b/tests/j_corrupt_descr_tid/name
new file mode 100644
index 0000000..2325d6d
--- /dev/null
+++ b/tests/j_corrupt_descr_tid/name
@@ -0,0 +1 @@
+corrupt descr tid (csum v3)
diff --git a/tests/j_corrupt_descr_tid/script b/tests/j_corrupt_descr_tid/script
new file mode 100644
index 0000000..102feba
--- /dev/null
+++ b/tests/j_corrupt_descr_tid/script
@@ -0,0 +1,51 @@
+if test -x $DEBUGFS_EXE; then
+
+IMAGE=$test_dir/image.gz
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+gzip -d < $IMAGE > $TMPFILE
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+echo "cat /a" > $TMPFILE.cmd
+$DEBUGFS_EXE -f $TMPFILE.cmd $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+rm -f $TMPFILE.cmd
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi
diff --git a/tests/j_corrupt_journal_block/expect b/tests/j_corrupt_journal_block/expect
new file mode 100644
index 0000000..443a2b3
--- /dev/null
+++ b/tests/j_corrupt_journal_block/expect
@@ -0,0 +1,19 @@
+test_filesys: recovering journal
+JBD2: Invalid checksum recovering block 1090 in log
+../e2fsck/e2fsck: Input/output error while recovering ext3 journal of test_filesys
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+
+test_filesys: ********** WARNING: Filesystem still has errors **********
+
+Exit status is 12
+test_filesys: recovering journal
+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/128 files (8.3% non-contiguous), 1093/2048 blocks
+Exit status is 0
+debugfs: cat /a
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
diff --git a/tests/j_corrupt_journal_block/image.gz b/tests/j_corrupt_journal_block/image.gz
new file mode 100644
index 0000000000000000000000000000000000000000..6ab196ebb651e27d5db50f5dccbc495bd63e4fc7
GIT binary patch
literal 2984
zcmeIw|1;Zn90%}}>xJ4D?$)w45$m<SO?_GKvNl6HjJETg`WB=@eM`})j7Tat6j{;D
z*B&yrhB*>nTa_Tx=#G|Js;T(yRO)L)B>51@d$%9`3(o7e=MT>xo{xK>89Ff1Cj);i
z?akS+eE(ZW*!E@g8kV<`XaSi#dkT5C74DWi&wAqMf^gl}e_(`f_gUtAh<CVPDK{!`
zh(ernF#6Hzo!?hZkiL)3*B2ND*L4RhhfVP|ckYT`*JMr2{(KsP6slC0Vzy?AtG*X+
zshL;BW4+28*z)AS?%Oj?bY!)8uI-l(bB9lIJ4(y(SkW`}<H}PJMB;Q%9d{=CN;siY
z!&Qi`Cn0J0&lZQ0b($1K)sSk6jW(u`cV)t{d2;-kIH;F&J66#hY@cuwKPVH(x_ano
zG-qi|<gDI!f+Mfl`-48VaH^-YcqGlD^jx{k`*uQeudJ|=OFYY%j>8M&sh(%?#^97k
zx#g<@>WIQ2q)C}3L3h1coV8=Khk^Huumg4f<LU!m-b+IjM<J4SDG{P<*x}m-l`n2s
zC3+|jp4W<4)ajHQr#7=FW%sJi5Yfx)7X<TSoiB~DT~<d`!IfWZxXYX%j=%Y?1t!9i
z(MH?a&U%FF^eO-ozGpx`8wG6G684<2Wc;_y6BGuxxM|4Ar|W}E2>v(DL~}xl$fsXB
z&|X68gZ>!?_#MHa+7!J{|I=E?tWRwEDIz&=p|NQpTAk*#wv=v7CiOO??0HbNC;<!*
z(o^x>WJ3#YN8Tc+u*M<LmVwOq5RVbl1xqZBJ#$(9k{amZoM8`#Eqk)ngl3dP4^)eK
zsr8sa1!v;Xq;?Kz8aI)hjbDKX-BM`2f`F1RS0RFIuLul;O5Z(}%(tF4;n%{Go9fgA
z2Xe!%kY&~~q47${Y>i!>H7l*XH`)orL+5YbM+QiA_az!Px0R6aPO!LNL*XW+nU&x_
zmjg<pI}{Bq=?VV=NjC=JTtbpxw$}gP{cjQmVugxyuFpEMPnTn|?-2IJe{6@}S>Aq?
zwN`w7H6=eK+2u};?dqIsoCwtss>CaETkQ{^=_=GZ-Lp|c|7X-O5L+Ut<lV!}?*WL`
zC*!BSkTVw->Y&#8(Asc~p_9^TUL_^H=F?&<0mdF9r+&&4<5KdX_r}L^Ml)78zgC!*
zfmL1|598kTHrT)~&^?l+|2$004J6#$19zX6?Ip3=m^&zdKqaVSu2ikzNKYm~VMK83
z3@{VYvBZ#XN69S*=9@s-68}*{-|#N4VhPshxwiDYeF8TqLqML}*r{N<G2<}mCAbC9
zez-2@m;SrIPX6KW*BwrO$bAX*jo%0;b}UCP!<=TJFxT!DF&+_2Z($I*m!j0D)VyYX
v<l)kBIu<w<ID!J10qfc@ShBO8&Ji4UJn2~A2n%GMTg3Hgxu(NlCb0hiq@E#f

literal 0
HcmV?d00001

diff --git a/tests/j_corrupt_journal_block/name b/tests/j_corrupt_journal_block/name
new file mode 100644
index 0000000..5d862cd
--- /dev/null
+++ b/tests/j_corrupt_journal_block/name
@@ -0,0 +1 @@
+corrupt journal block (csum v3)
diff --git a/tests/j_corrupt_journal_block/script b/tests/j_corrupt_journal_block/script
new file mode 100644
index 0000000..c17c70e
--- /dev/null
+++ b/tests/j_corrupt_journal_block/script
@@ -0,0 +1,52 @@
+if test -x $DEBUGFS_EXE; then
+
+IMAGE=$test_dir/image.gz
+FSCK_OPT=-fy
+OUT=$test_name.log
+if [ -f $test_dir/expect.gz ]; then
+ EXP=$test_name.tmp
+ gunzip < $test_dir/expect.gz > $EXP1
+else
+ EXP=$test_dir/expect
+fi
+
+cp /dev/null $OUT
+
+gzip -d < $IMAGE > $TMPFILE
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+$FSCK -fy -N test_filesys $TMPFILE > $OUT.new 2>&1
+status=$?
+echo Exit status is $status >> $OUT.new
+sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" $OUT.new >> $OUT
+rm -f $OUT.new
+
+echo "cat /a" > $TMPFILE.cmd
+$DEBUGFS_EXE -f $TMPFILE.cmd $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+echo >> $OUT
+rm -f $TMPFILE.cmd
+
+rm -f $TMPFILE
+
+cmp -s $OUT $EXP
+status=$?
+
+if [ "$status" = 0 ] ; then
+ echo "$test_name: $test_description: ok"
+ touch $test_name.ok
+else
+ echo "$test_name: $test_description: failed"
+ diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+ rm -f $test_name.tmp
+fi
+
+unset IMAGE FSCK_OPT OUT EXP
+
+else #if test -x $DEBUGFS_EXE; then
+ echo "$test_name: $test_description: skipped"
+fi

2014-09-11 19:41:59

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 26/25] libext2fs: call get_alloc_block hook when allocating blocks

If a libext2fs client has provided a get_alloc_block hook, we need to
ensure that all code paths in the library use it to allocate blocks.

Signed-off-by: Darrick J. Wong <[email protected]>
---
lib/ext2fs/bb_inode.c | 11 ++++++++++-
lib/ext2fs/expanddir.c | 3 +--
lib/ext2fs/inline_data.c | 7 ++++---
lib/ext2fs/mkdir.c | 5 ++++-
lib/ext2fs/mkjournal.c | 5 ++++-
lib/ext2fs/symlink.c | 5 ++++-
6 files changed, 27 insertions(+), 9 deletions(-)

diff --git a/lib/ext2fs/bb_inode.c b/lib/ext2fs/bb_inode.c
index b0e114b..d659bb9 100644
--- a/lib/ext2fs/bb_inode.c
+++ b/lib/ext2fs/bb_inode.c
@@ -219,6 +219,7 @@ static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
priv_data;
errcode_t retval;
blk_t blk;
+ blk64_t blk2;

if (blockcnt >= 0) {
/*
@@ -241,7 +242,15 @@ static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
if (ext2fs_test_block_bitmap2(fs->block_map, blk))
goto retry;
} else {
- retval = ext2fs_new_block(fs, 0, 0, &blk);
+ if (fs->get_alloc_block) {
+ retval = fs->get_alloc_block(fs, 0, &blk2);
+ if (!retval && (blk2 >> 32)) {
+ rec->err = EOVERFLOW;
+ return BLOCK_ABORT;
+ }
+ blk = blk2;
+ } else
+ retval = ext2fs_new_block(fs, 0, 0, &blk);
if (retval) {
rec->err = retval;
return BLOCK_ABORT;
diff --git a/lib/ext2fs/expanddir.c b/lib/ext2fs/expanddir.c
index d0f7287..f412923 100644
--- a/lib/ext2fs/expanddir.c
+++ b/lib/ext2fs/expanddir.c
@@ -50,13 +50,12 @@ static int expand_dir_proc(ext2_filsys fs,
new_blk = es->goal+1;
else {
es->goal &= ~EXT2FS_CLUSTER_MASK(fs);
- retval = ext2fs_new_block2(fs, es->goal, 0, &new_blk);
+ retval = ext2fs_alloc_block2(fs, es->goal, NULL, &new_blk);
if (retval) {
es->err = retval;
return BLOCK_ABORT;
}
es->newblocks++;
- ext2fs_block_alloc_stats2(fs, new_blk, +1);
}
if (blockcnt > 0) {
retval = ext2fs_new_dir_block(fs, 0, 0, &block);
diff --git a/lib/ext2fs/inline_data.c b/lib/ext2fs/inline_data.c
index 7eb8b94..7a6c721 100644
--- a/lib/ext2fs/inline_data.c
+++ b/lib/ext2fs/inline_data.c
@@ -357,7 +357,7 @@ ext2fs_inline_data_dir_expand(ext2_filsys fs, ext2_ino_t ino,
struct ext2_inode *inode, char *buf, size_t size)
{
errcode_t retval;
- blk64_t blk;
+ blk64_t blk = 0;
char *blk_buf;

retval = ext2fs_get_memzero(fs->blocksize, &blk_buf);
@@ -376,7 +376,7 @@ ext2fs_inline_data_dir_expand(ext2_filsys fs, ext2_ino_t ino,
if (retval)
goto errout;
/* Allocate a new block */
- retval = ext2fs_new_block2(fs, 0, 0, &blk);
+ retval = ext2fs_alloc_block2(fs, 0, NULL, &blk);
if (retval)
goto errout;
retval = ext2fs_write_dir_block4(fs, blk, blk_buf, 0, ino);
@@ -397,9 +397,10 @@ ext2fs_inline_data_dir_expand(ext2_filsys fs, ext2_ino_t ino,
retval = ext2fs_write_inode(fs, ino, inode);
if (retval)
goto errout;
- ext2fs_block_alloc_stats(fs, blk, +1);

errout:
+ if (retval && blk)
+ ext2fs_block_alloc_stats(fs, blk, -1);
ext2fs_free_mem(&blk_buf);
return retval;
}
diff --git a/lib/ext2fs/mkdir.c b/lib/ext2fs/mkdir.c
index c4c7967..a184129 100644
--- a/lib/ext2fs/mkdir.c
+++ b/lib/ext2fs/mkdir.c
@@ -69,7 +69,10 @@ errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
* Allocate a data block for the directory
*/
if (!inline_data) {
- retval = ext2fs_new_block2(fs, 0, 0, &blk);
+ if (fs->get_alloc_block)
+ retval = fs->get_alloc_block(fs, 0, &blk);
+ else
+ retval = ext2fs_new_block2(fs, 0, 0, &blk);
if (retval)
goto cleanup;
}
diff --git a/lib/ext2fs/mkjournal.c b/lib/ext2fs/mkjournal.c
index 0a7cd18..f9cec4e 100644
--- a/lib/ext2fs/mkjournal.c
+++ b/lib/ext2fs/mkjournal.c
@@ -242,7 +242,10 @@ static int mkjournal_proc(ext2_filsys fs,
new_blk = es->goal+1;
else {
es->goal &= ~EXT2FS_CLUSTER_MASK(fs);
- retval = ext2fs_new_block2(fs, es->goal, 0, &new_blk);
+ if (fs->get_alloc_block)
+ retval = fs->get_alloc_block(fs, es->goal, &new_blk);
+ else
+ retval = ext2fs_new_block2(fs, es->goal, 0, &new_blk);
if (retval) {
es->err = retval;
return BLOCK_ABORT;
diff --git a/lib/ext2fs/symlink.c b/lib/ext2fs/symlink.c
index f6eb6b6..b361e02 100644
--- a/lib/ext2fs/symlink.c
+++ b/lib/ext2fs/symlink.c
@@ -53,7 +53,10 @@ errcode_t ext2fs_symlink(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t ino,
*/
fastlink = (target_len < sizeof(inode.i_block));
if (!fastlink) {
- retval = ext2fs_new_block2(fs, 0, 0, &blk);
+ if (fs->get_alloc_block)
+ retval = fs->get_alloc_block(fs, 0, &blk);
+ else
+ retval = ext2fs_new_block2(fs, 0, 0, &blk);
if (retval)
goto cleanup;
retval = ext2fs_get_mem(fs->blocksize, &block_buf);

2014-09-11 19:43:42

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 27/25] tune2fs: always check disable_uninit_bg() return code

Enhance disable_uninit_bg() to return error codes -- if something goes
wrong, we want to flag the FS as needing a fsck and exit. Mr. Reardon
discovered that tune2fs -O ^metadata_csum on a FS with a corrupt
bitmap would leave the FS in a weird state.

Signed-off-by: Darrick J. Wong <[email protected]>
Reported-by: TR Reardon <[email protected]>
---
misc/tune2fs.c | 28 +++++++++++++++++++---------
1 file changed, 19 insertions(+), 9 deletions(-)

diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index 7292ab1..80debe7 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -839,7 +839,7 @@ out:
return retval;
}

-static void disable_uninit_bg(ext2_filsys fs, __u32 csum_feature_flag)
+static errcode_t disable_uninit_bg(ext2_filsys fs, __u32 csum_feature_flag)
{
struct ext2_group_desc *gd;
dgrp_t i;
@@ -849,14 +849,15 @@ static void disable_uninit_bg(ext2_filsys fs, __u32 csum_feature_flag)
/* Load bitmaps to ensure that the uninit ones get written out */
fs->super->s_feature_ro_compat |= csum_feature_flag;
retval = ext2fs_read_bitmaps(fs);
+ fs->super->s_feature_ro_compat &= ~csum_feature_flag;
if (retval) {
com_err("disable_uninit_bg", retval,
"while reading bitmaps");
- return;
+ request_fsck_afterwards(fs);
+ return retval;
}
ext2fs_mark_ib_dirty(fs);
ext2fs_mark_bb_dirty(fs);
- fs->super->s_feature_ro_compat &= ~csum_feature_flag;

/* If we're only turning off uninit_bg, zero the inodes */
if (csum_feature_flag == EXT4_FEATURE_RO_COMPAT_GDT_CSUM) {
@@ -865,6 +866,7 @@ static void disable_uninit_bg(ext2_filsys fs, __u32 csum_feature_flag)
com_err("disable_uninit_bg", retval,
"while zeroing unused inodes");
request_fsck_afterwards(fs);
+ return retval;
}
}

@@ -895,6 +897,8 @@ static void disable_uninit_bg(ext2_filsys fs, __u32 csum_feature_flag)
}
fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
ext2fs_mark_super_dirty(fs);
+
+ return 0;
}

/*
@@ -906,6 +910,7 @@ static int update_feature_set(ext2_filsys fs, char *features)
__u32 old_features[3];
int type_err;
unsigned int mask_err;
+ errcode_t err;

#define FEATURE_ON(type, mask) (!(old_features[(type)] & (mask)) && \
((&sb->s_feature_compat)[(type)] & (mask)))
@@ -1114,10 +1119,12 @@ mmp_error:
* uninit_bg, rewrite group desc.
*/
if (!(fs->super->s_feature_ro_compat &
- EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
- disable_uninit_bg(fs,
- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM);
- else
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
+ err = disable_uninit_bg(fs,
+ EXT4_FEATURE_RO_COMPAT_METADATA_CSUM);
+ if (err)
+ return 1;
+ } else
/*
* metadata_csum previously provided uninit_bg, so if
* we're also setting the uninit_bg feature bit,
@@ -1140,9 +1147,12 @@ mmp_error:
}

if (FEATURE_OFF(E2P_FEATURE_RO_INCOMPAT,
- EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
- disable_uninit_bg(fs,
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
+ err = disable_uninit_bg(fs,
EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
+ if (err)
+ return 1;
+ }

if (FEATURE_ON(E2P_FEATURE_RO_INCOMPAT,
EXT4_FEATURE_RO_COMPAT_QUOTA)) {

2014-09-11 19:44:55

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 28/25] e2fsck: ignore badblocks if it says badblocks inode is bad

If the badblocks list says that the badblocks inode is bad, it's quite
likely that badblocks is broken. Worse yet, if the root inode is in
the same block as the badblocks inode (likely since they're adjacent),
the filesystem becomes unfixable because pass3 notices the bad root
inode and exits.

So... if we encounter this case, just kill the badblocks inode.

Signed-off-by: Darrick J. Wong <[email protected]>
---
e2fsck/pass1.c | 31 +++++++++++++++++++++++++++++++
e2fsck/problem.c | 5 +++++
e2fsck/problem.h | 3 +++
tests/f_bb_in_bb/expect.1 | 17 +++++++++++++++++
tests/f_bb_in_bb/expect.2 | 7 +++++++
tests/f_bb_in_bb/image.gz | Bin
tests/f_bb_in_bb/name | 1 +
7 files changed, 64 insertions(+)
create mode 100644 tests/f_bb_in_bb/expect.1
create mode 100644 tests/f_bb_in_bb/expect.2
create mode 100644 tests/f_bb_in_bb/image.gz
create mode 100644 tests/f_bb_in_bb/name

diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index f09cddb..7dfb1bd 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -1141,6 +1141,37 @@ void e2fsck_pass1(e2fsck_t ctx)
if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
return;
if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
+ /*
+ * If badblocks says badblocks is bad, offer to clear
+ * the list, update the in-core bb list, and restart
+ * the inode scan.
+ */
+ if (ino == EXT2_BAD_INO &&
+ fix_problem(ctx, PR_1_BADBLOCKS_IN_BADBLOCKS,
+ &pctx)) {
+ errcode_t err;
+
+ e2fsck_clear_inode(ctx, ino, inode, 0, "pass1");
+ ext2fs_badblocks_list_free(ctx->fs->badblocks);
+ ctx->fs->badblocks = NULL;
+ err = ext2fs_read_bb_inode(ctx->fs,
+ &ctx->fs->badblocks);
+ if (err) {
+ fix_problem(ctx, PR_1_ISCAN_ERROR,
+ &pctx);
+ ctx->flags |= E2F_FLAG_ABORT;
+ goto endit;
+ }
+ err = ext2fs_inode_scan_goto_blockgroup(scan,
+ 0);
+ if (err) {
+ fix_problem(ctx, PR_1_ISCAN_ERROR,
+ &pctx);
+ ctx->flags |= E2F_FLAG_ABORT;
+ goto endit;
+ }
+ continue;
+ }
if (!ctx->inode_bb_map)
alloc_bb_map(ctx);
ext2fs_mark_inode_bitmap2(ctx->inode_bb_map, ino);
diff --git a/e2fsck/problem.c b/e2fsck/problem.c
index 4b41a21..79bba1a 100644
--- a/e2fsck/problem.c
+++ b/e2fsck/problem.c
@@ -1086,6 +1086,11 @@ static struct e2fsck_problem problem_table[] = {
N_("@i %i has inline data and @x flags set but i_block contains junk.\n"),
PROMPT_CLEAR_INODE, 0 },

+ /* Bad block list says the bad block list inode is bad */
+ { PR_1_BADBLOCKS_IN_BADBLOCKS,
+ N_("Bad block list says the bad block list @i is bad. "),
+ PROMPT_CLEAR_INODE, 0 },
+
/* Pass 1b errors */

/* Pass 1B: Rescan for duplicate/bad blocks */
diff --git a/e2fsck/problem.h b/e2fsck/problem.h
index f86c531..5b32aeb 100644
--- a/e2fsck/problem.h
+++ b/e2fsck/problem.h
@@ -632,6 +632,9 @@ struct problem_context {
/* inlinedata/extent set, clear inode */
#define PR_1_CLEAR_EXTENT_INLINE_DATA_INODE 0x01007A

+/* badblocks is in badblocks */
+#define PR_1_BADBLOCKS_IN_BADBLOCKS 0x01007B
+
/*
* Pass 1b errors
*/
diff --git a/tests/f_bb_in_bb/expect.1 b/tests/f_bb_in_bb/expect.1
new file mode 100644
index 0000000..1d719e5
--- /dev/null
+++ b/tests/f_bb_in_bb/expect.1
@@ -0,0 +1,17 @@
+Pass 1: Checking inodes, blocks, and sizes
+Bad block list says the bad block list inode is bad. Clear inode? yes
+
+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 #0 (493, counted=494).
+Fix? yes
+
+Free blocks count wrong (493, counted=494).
+Fix? yes
+
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 11/128 files (0.0% non-contiguous), 18/512 blocks
+Exit status is 1
diff --git a/tests/f_bb_in_bb/expect.2 b/tests/f_bb_in_bb/expect.2
new file mode 100644
index 0000000..411e656
--- /dev/null
+++ b/tests/f_bb_in_bb/expect.2
@@ -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/128 files (0.0% non-contiguous), 18/512 blocks
+Exit status is 0
diff --git a/tests/f_bb_in_bb/image.gz b/tests/f_bb_in_bb/image.gz
new file mode 100644
index 0000000000000000000000000000000000000000..e2c46c09ed2f92070579537d0b03faf9796970dd
GIT binary patch
literal 2414
zcmb2|=3ubDE)c@R{Pxzy>|jR;h7a%K<RfM|G(S)Xo8s3r;pWOCM?DKNVp+@!g}O7A
z=@ni)dGY_DgN_F`mJ}Afd+<mjqwqpghk$<Ndet_KBwgRf@5SHsy}!5jfb7E`@1D9c
z{9k=<ftHfr^E7qWlGpzh=^bX=TNSfy)7_}<7vIC}mwNmzRK1$Jm{0F%ns)t3w>)|K
zoxd_3-<`^T-v4gR*3z=_?;6jl9v_<Be}7(__2);gPe0pv_4@aql0}g{=U(5BIyK*9
z;r=sEcg>e$U~o^E@NeFk)XEwE%Zp>)#lJpwJ3Wkpfq|iK|Gyf^`_K6b?13DEuWbMS
zn=6aHU2%^!!!2;j?W@*%-iwQOS-<`+AG2rgy}i|^HwyvPS*(*ve*Ry-`|3}5Aa91D
zt~ZckIQJh&G<*gbL@bb5_pfuK1W@%1%XtmNYQm!K!|^CV?b~a&?%j0V*4`+k(rx*^
z;-BH4=dXSqf0cWF@D%0mOCNSLM@x0PUzdMi@Kx?v)@I|x|K9d*|JN@z6jT2#?=$tR
z<G;%@r~DTw{Ad2tKT`ZBKNf37g+@bQGz3ONU^E0qLtr!ns1gE~pRg}xmOQ|~puhkC
D<cZO-

literal 0
HcmV?d00001

diff --git a/tests/f_bb_in_bb/name b/tests/f_bb_in_bb/name
new file mode 100644
index 0000000..88727e1
--- /dev/null
+++ b/tests/f_bb_in_bb/name
@@ -0,0 +1 @@
+bad block inode table block in bad block list

2014-09-11 19:48:10

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 29/25] e2fsck: expand root dir if linking l+f fails

If there isn't space in the root directory to add the lost+found
entry, try expanding the root directory before failing the fsck.

Signed-off-by: Darrick J. Wong <[email protected]>
---
e2fsck/pass3.c | 8 ++++++++
tests/f_expandroot_create_lnf/expect.1 | 12 ++++++++++++
tests/f_expandroot_create_lnf/expect.2 | 7 +++++++
tests/f_expandroot_create_lnf/image.gz | Bin
tests/f_expandroot_create_lnf/name | 1 +
5 files changed, 28 insertions(+)
create mode 100644 tests/f_expandroot_create_lnf/expect.1
create mode 100644 tests/f_expandroot_create_lnf/expect.2
create mode 100644 tests/f_expandroot_create_lnf/image.gz
create mode 100644 tests/f_expandroot_create_lnf/name

diff --git a/e2fsck/pass3.c b/e2fsck/pass3.c
index 9860cdf..f03c7ae 100644
--- a/e2fsck/pass3.c
+++ b/e2fsck/pass3.c
@@ -530,7 +530,15 @@ skip_new_block:
* Finally, create the directory link
*/
pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
+ if (pctx.errcode == EXT2_ET_DIR_NO_SPACE) {
+ pctx.errcode = ext2fs_expand_dir(fs, EXT2_ROOT_INO);
+ if (pctx.errcode)
+ goto link_error;
+ pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino,
+ EXT2_FT_DIR);
+ }
if (pctx.errcode) {
+link_error:
pctx.str = "ext2fs_link";
fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
return 0;
diff --git a/tests/f_expandroot_create_lnf/expect.1 b/tests/f_expandroot_create_lnf/expect.1
new file mode 100644
index 0000000..9593dbf
--- /dev/null
+++ b/tests/f_expandroot_create_lnf/expect.1
@@ -0,0 +1,12 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+/lost+found not found. Create? yes
+
+Pass 3A: Optimizing directories
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 16/64 files (0.0% non-contiguous), 33/1024 blocks
+Exit status is 1
diff --git a/tests/f_expandroot_create_lnf/expect.2 b/tests/f_expandroot_create_lnf/expect.2
new file mode 100644
index 0000000..5eec1f0
--- /dev/null
+++ b/tests/f_expandroot_create_lnf/expect.2
@@ -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: 16/64 files (6.3% non-contiguous), 33/1024 blocks
+Exit status is 0
diff --git a/tests/f_expandroot_create_lnf/image.gz b/tests/f_expandroot_create_lnf/image.gz
new file mode 100644
index 0000000000000000000000000000000000000000..ccdbfa7a03aafbc206638d704d8bb22b21a293ed
GIT binary patch
literal 1622
zcmb2|=3r2MEf~VY{Pynoe4juOh6lfwHLnVq9ARRT*uBKWY?_CPl9<ruWak#%tpT3e
zg0JK^2-piLiG_tJDaA%8OzfE28qwLSWOB*%=%pRy_x3Ev4Jo;_^2~SBbido*Z{04o
ze*V?ZI6scVVfU?xd8ZU}x?h&Mb1)mG?|-*Jv46|`o#&@!RW1rT>$J8k!D#h+^N%Zo
zbjx)2<+(m?ersr}+iD>6`55nY_iuOa{(X4w*Szjv{rJ4u|B7=gEiFv`XHENC`1-}|
z^^dpnzr9uc_DA=|f9BzRDH~V43)=Vgy49?u`ukEh*Vy@$TfA6zT<L;na&C|B*MIUH
zOMmS(HW$dVHF0KufDJ#cW<8(Y_I~Rc*TeBE7<DJl`*%%tQ&9bxpTCy|)z|-%*=M?N
zb;+X-FBhIY?l)J`X4baW3p1~7diYH&%<Ng>lD(~=y_FWX?>YI;X?K6<SoXtyOH$PT
z`nM;3%V!9u1~dGUzwp1|ANv>k1^*fU^1rBe_|FUyVqiFs6k>h<gu`vmz4tHv5I-<U
z!rQq{bnZEc)3S1mP^Uqt1*&Rxp{rcC1mBG>Yx{Nbe7;@ys`XM6^Ixur=eL~8Irm)e
zyIH5|s%LJ|d2-!j{`!3qhue3}TQ0$EUUfV7U*ol%22%OkrkytK{~sA)d;b02cl!PH
zm;dwqTzlY9#hh#Q(dp6ur#j^){}oP){9j_eNb>dkuy6n8UbKntdc9AnZrz7ZzcyF>
z{r}Hs=i};k@_&N=UOkx}-tF;t`JM}3<NF?qU3~NF{`tWFXY=15>w=1Qf<^7m1pfag
zdw-tD#AE)I3t!ipKK|(c`PF|5_rFIU&lk!3GeveLsy|UYJ<1skfzc2cG9i$#O#ZIS
K!%zkW0R{l3<x~Iw

literal 0
HcmV?d00001

diff --git a/tests/f_expandroot_create_lnf/name b/tests/f_expandroot_create_lnf/name
new file mode 100644
index 0000000..f22542b
--- /dev/null
+++ b/tests/f_expandroot_create_lnf/name
@@ -0,0 +1 @@
+no space in root to create lost+found entry

2014-09-11 20:15:04

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 10/25] debugfs: create journal handling routines

On Thu, Sep 11, 2014 at 12:03:49PM -0700, Darrick J. Wong wrote:
> Will that pick up debugfs/jfs_user.h, though? I originally tried it this way
> but gcc seemed to want to pull in the jfs_user.h from e2fsck/.

Yeah, I figured that out shortly after I sent the message. The way I
fixed it was a bit more involved, but I think it's cleaner.

Long run, what I want to do is to rename libquota to libsupport, and
then move things like profile.c, recovery.c, revoke.c, etc. into that
single directory, and then harmonize all of the ugly hacks that we
have in various different versions of jfs_user.h. Given that, what I
did for now was to harmonize (as much as possible) debugfs/jfs_user.h
and e2fsck/jfs_user.h, and there is now a single version of jfs_user.h
in e2fsck. We still have some customizations based on -DDEBUGFS, but
we can clean that up later.

- Ted

commit cdca03d363aabe8026a1b343d3035ea333117ffa
Author: Darrick J. Wong <[email protected]>
Date: Mon Sep 8 16:12:42 2014 -0700

debugfs: create journal handling routines

Create a journal.c with routines adapted from e2fsck/journal.c to
handle opening and closing the journal, and setting up the
descriptors, and all that. Unlike e2fsck's versions which try to
identify and fix problems, the routines here have no way to repair
anything.

Signed-off-by: Darrick J. Wong <[email protected]>
Signed-off-by: Theodore Ts'o <[email protected]>

diff --git a/MCONFIG.in b/MCONFIG.in
index edaa6f6..2a5055f 100644
--- a/MCONFIG.in
+++ b/MCONFIG.in
@@ -73,7 +73,7 @@ pkgconfigdir = $(libdir)/pkgconfig

CC = @CC@
BUILD_CC = @BUILD_CC@
-CFLAGS = @CFLAGS@ @DEFS@
+CFLAGS = @CFLAGS@ @DEFS@ $(LOCAL_CFLAGS)
CPPFLAGS = @INCLUDES@
ALL_CFLAGS = $(CPPFLAGS) $(CFLAGS)
LDFLAGS = @LDFLAGS@
diff --git a/debugfs/Makefile.in b/debugfs/Makefile.in
index 0f23595..6d88267 100644
--- a/debugfs/Makefile.in
+++ b/debugfs/Makefile.in
@@ -19,7 +19,7 @@ MK_CMDS= _SS_DIR_OVERRIDE=../lib/ss ../lib/ss/mk_cmds
DEBUG_OBJS= debug_cmds.o debugfs.o util.o ncheck.o icheck.o ls.o \
lsdel.o dump.o set_fields.o logdump.o htree.o unused.o e2freefrag.o \
filefrag.o extent_cmds.o extent_inode.o zap.o create_inode.o \
- quota.o xattrs.o
+ quota.o xattrs.o journal.o revoke.o recovery.o

RO_DEBUG_OBJS= ro_debug_cmds.o ro_debugfs.o util.o ncheck.o icheck.o ls.o \
lsdel.o logdump.o htree.o e2freefrag.o filefrag.o extent_cmds.o \
@@ -30,7 +30,9 @@ SRCS= debug_cmds.c $(srcdir)/debugfs.c $(srcdir)/util.c $(srcdir)/ls.c \
$(srcdir)/dump.c $(srcdir)/set_fields.c ${srcdir}/logdump.c \
$(srcdir)/htree.c $(srcdir)/unused.c ${srcdir}/../misc/e2freefrag.c \
$(srcdir)/filefrag.c $(srcdir)/extent_inode.c $(srcdir)/zap.c \
- $(srcdir)/../misc/create_inode.c $(srcdir)/xattrs.c $(srcdir)/quota.c
+ $(srcdir)/../misc/create_inode.c $(srcdir)/xattrs.c $(srcdir)/quota.c \
+ $(srcdir)/journal.c $(srcdir)/../e2fsck/revoke.c \
+ $(srcdir)/../e2fsck/recovery.c

LIBS= $(LIBQUOTA) $(LIBEXT2FS) $(LIBE2P) $(LIBSS) $(LIBCOM_ERR) $(LIBBLKID) \
$(LIBUUID) $(SYSLIBS)
@@ -44,6 +46,11 @@ STATIC_DEPLIBS= $(STATIC_LIBEXT2FS) $(DEPSTATIC_LIBSS) \
$(DEPSTATIC_LIBCOM_ERR) $(DEPSTATIC_LIBUUID) \
$(DEPSTATIC_LIBE2P)

+# This nastyness is needed because of jfs_user.h hackery; when we finally
+# clean up this mess, we should be able to drop it
+LOCAL_CFLAGS = -I$(srcdir)/../e2fsck -DDEBUGFS
+DEPEND_CFLAGS = -I$(srcdir)
+
.c.o:
$(E) " CC $<"
$(Q) $(CC) -c $(ALL_CFLAGS) $< -o $@
@@ -83,12 +90,22 @@ ro_debugfs.o: debugfs.c

e2freefrag.o: $(srcdir)/../misc/e2freefrag.c
$(E) " CC $@"
- $(Q) $(CC) -c $(ALL_CFLAGS) -I$(srcdir) $< -DDEBUGFS -o $@
+ $(Q) $(CC) -c $(ALL_CFLAGS) -I$(srcdir) $< -o $@
+
+recovery.o: $(srcdir)/../e2fsck/recovery.c
+ cp $(srcdir)/../e2fsck/recovery.c $(srcdir)/recovery.c
+ $(E) " CC $@"
+ $(Q) $(CC) -c $(ALL_CFLAGS) -I$(srcdir) $(srcdir)/recovery.c -o $@
+
+revoke.o: $(srcdir)/../e2fsck/revoke.c
+ cp $(srcdir)/../e2fsck/revoke.c $(srcdir)/revoke.c
+ $(E) " CC $@"
+ $(Q) $(CC) -c $(ALL_CFLAGS) -I$(srcdir) $(srcdir)/revoke.c -o $@

create_inode.o: $(srcdir)/../misc/create_inode.c
$(E) " CC $@"
$(Q) $(CC) -c $(ALL_CFLAGS) -I$(srcdir) \
- $(srcdir)/../misc/create_inode.c -DDEBUGFS -o $@
+ $(srcdir)/../misc/create_inode.c -o $@

debugfs.8: $(DEP_SUBSTITUTE) $(srcdir)/debugfs.8.in
$(E) " SUBST $@"
@@ -133,7 +150,8 @@ clean::
mostlyclean: clean
distclean: clean
$(RM) -f debug_cmds.c .depend Makefile $(srcdir)/TAGS \
- $(srcdir)/Makefile.in.old
+ $(srcdir)/Makefile.in.old $(srcdir)/recovery.c \
+ $(srcdir)/revoke.c

# +++ Dependency line eater +++
#
@@ -149,13 +167,12 @@ debugfs.o: $(srcdir)/debugfs.c $(top_builddir)/lib/config.h \
$(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.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/bitops.h \
- $(srcdir)/../misc/create_inode.h \
- $(srcdir)/../misc/nls-enable.h \
- $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \
- $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h \
- $(top_srcdir)/lib/e2p/e2p.h $(top_srcdir)/version.h $(srcdir)/jfs_user.h \
- $(top_srcdir)/lib/ext2fs/kernel-jbd.h $(top_srcdir)/lib/ext2fs/jfs_compat.h \
- $(top_srcdir)/lib/ext2fs/kernel-list.h
+ $(srcdir)/../misc/create_inode.h $(top_srcdir)/lib/e2p/e2p.h \
+ $(srcdir)/../misc/nls-enable.h $(top_srcdir)/lib/quota/quotaio.h \
+ $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \
+ $(top_srcdir)/lib/../e2fsck/dict.h $(top_srcdir)/version.h \
+ $(srcdir)/../e2fsck/jfs_user.h $(top_srcdir)/lib/ext2fs/kernel-jbd.h \
+ $(top_srcdir)/lib/ext2fs/jfs_compat.h $(top_srcdir)/lib/ext2fs/kernel-list.h
util.o: $(srcdir)/util.c $(top_builddir)/lib/config.h \
$(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/ss/ss.h \
$(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \
@@ -165,9 +182,9 @@ util.o: $(srcdir)/util.c $(top_builddir)/lib/config.h \
$(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \
$(srcdir)/../misc/create_inode.h $(top_srcdir)/lib/e2p/e2p.h \
- $(srcdir)/../misc/nls-enable.h \
- $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \
- $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h
+ $(srcdir)/../misc/nls-enable.h $(top_srcdir)/lib/quota/quotaio.h \
+ $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \
+ $(top_srcdir)/lib/../e2fsck/dict.h
ls.o: $(srcdir)/ls.c $(top_builddir)/lib/config.h \
$(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \
$(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \
@@ -176,9 +193,9 @@ ls.o: $(srcdir)/ls.c $(top_builddir)/lib/config.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/bitops.h \
$(srcdir)/../misc/create_inode.h $(top_srcdir)/lib/e2p/e2p.h \
- $(srcdir)/../misc/nls-enable.h \
- $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \
- $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h
+ $(srcdir)/../misc/nls-enable.h $(top_srcdir)/lib/quota/quotaio.h \
+ $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \
+ $(top_srcdir)/lib/../e2fsck/dict.h
ncheck.o: $(srcdir)/ncheck.c $(top_builddir)/lib/config.h \
$(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \
$(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \
@@ -187,9 +204,9 @@ ncheck.o: $(srcdir)/ncheck.c $(top_builddir)/lib/config.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/bitops.h \
$(srcdir)/../misc/create_inode.h $(top_srcdir)/lib/e2p/e2p.h \
- $(srcdir)/../misc/nls-enable.h \
- $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \
- $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h
+ $(srcdir)/../misc/nls-enable.h $(top_srcdir)/lib/quota/quotaio.h \
+ $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \
+ $(top_srcdir)/lib/../e2fsck/dict.h
icheck.o: $(srcdir)/icheck.c $(top_builddir)/lib/config.h \
$(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \
$(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \
@@ -198,9 +215,9 @@ icheck.o: $(srcdir)/icheck.c $(top_builddir)/lib/config.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/bitops.h \
$(srcdir)/../misc/create_inode.h $(top_srcdir)/lib/e2p/e2p.h \
- $(srcdir)/../misc/nls-enable.h \
- $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \
- $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h
+ $(srcdir)/../misc/nls-enable.h $(top_srcdir)/lib/quota/quotaio.h \
+ $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \
+ $(top_srcdir)/lib/../e2fsck/dict.h
lsdel.o: $(srcdir)/lsdel.c $(top_builddir)/lib/config.h \
$(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \
$(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \
@@ -209,9 +226,9 @@ lsdel.o: $(srcdir)/lsdel.c $(top_builddir)/lib/config.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/bitops.h \
$(srcdir)/../misc/create_inode.h $(top_srcdir)/lib/e2p/e2p.h \
- $(srcdir)/../misc/nls-enable.h \
- $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \
- $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h
+ $(srcdir)/../misc/nls-enable.h $(top_srcdir)/lib/quota/quotaio.h \
+ $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \
+ $(top_srcdir)/lib/../e2fsck/dict.h
dump.o: $(srcdir)/dump.c $(top_builddir)/lib/config.h \
$(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \
$(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \
@@ -220,9 +237,9 @@ dump.o: $(srcdir)/dump.c $(top_builddir)/lib/config.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/bitops.h \
$(srcdir)/../misc/create_inode.h $(top_srcdir)/lib/e2p/e2p.h \
- $(srcdir)/../misc/nls-enable.h \
- $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \
- $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h
+ $(srcdir)/../misc/nls-enable.h $(top_srcdir)/lib/quota/quotaio.h \
+ $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \
+ $(top_srcdir)/lib/../e2fsck/dict.h
set_fields.o: $(srcdir)/set_fields.c $(top_builddir)/lib/config.h \
$(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \
$(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \
@@ -231,10 +248,9 @@ set_fields.o: $(srcdir)/set_fields.c $(top_builddir)/lib/config.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/bitops.h \
$(srcdir)/../misc/create_inode.h $(top_srcdir)/lib/e2p/e2p.h \
- $(srcdir)/../misc/nls-enable.h \
- $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \
- $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h \
- $(top_srcdir)/lib/e2p/e2p.h
+ $(srcdir)/../misc/nls-enable.h $(top_srcdir)/lib/quota/quotaio.h \
+ $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \
+ $(top_srcdir)/lib/../e2fsck/dict.h
logdump.o: $(srcdir)/logdump.c $(top_builddir)/lib/config.h \
$(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \
$(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \
@@ -243,13 +259,11 @@ logdump.o: $(srcdir)/logdump.c $(top_builddir)/lib/config.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/bitops.h \
$(srcdir)/../misc/create_inode.h $(top_srcdir)/lib/e2p/e2p.h \
- $(srcdir)/../misc/nls-enable.h $(srcdir)/jfs_user.h \
+ $(srcdir)/../misc/nls-enable.h $(top_srcdir)/lib/quota/quotaio.h \
+ $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \
+ $(top_srcdir)/lib/../e2fsck/dict.h $(srcdir)/../e2fsck/jfs_user.h \
$(top_srcdir)/lib/ext2fs/kernel-jbd.h $(top_srcdir)/lib/ext2fs/jfs_compat.h \
- $(top_srcdir)/lib/ext2fs/kernel-list.h \
- $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \
- $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h \
- $(srcdir)/jfs_user.h $(top_srcdir)/lib/ext2fs/kernel-jbd.h \
- $(top_srcdir)/lib/ext2fs/jfs_compat.h $(top_srcdir)/lib/ext2fs/kernel-list.h
+ $(top_srcdir)/lib/ext2fs/kernel-list.h
htree.o: $(srcdir)/htree.c $(top_builddir)/lib/config.h \
$(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \
$(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \
@@ -258,7 +272,9 @@ htree.o: $(srcdir)/htree.c $(top_builddir)/lib/config.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/bitops.h \
$(srcdir)/../misc/create_inode.h $(top_srcdir)/lib/e2p/e2p.h \
- $(srcdir)/../misc/nls-enable.h
+ $(srcdir)/../misc/nls-enable.h $(top_srcdir)/lib/quota/quotaio.h \
+ $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \
+ $(top_srcdir)/lib/../e2fsck/dict.h
unused.o: $(srcdir)/unused.c $(top_builddir)/lib/config.h \
$(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \
$(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \
@@ -267,14 +283,20 @@ unused.o: $(srcdir)/unused.c $(top_builddir)/lib/config.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/bitops.h \
$(srcdir)/../misc/create_inode.h $(top_srcdir)/lib/e2p/e2p.h \
- $(srcdir)/../misc/nls-enable.h
+ $(srcdir)/../misc/nls-enable.h $(top_srcdir)/lib/quota/quotaio.h \
+ $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \
+ $(top_srcdir)/lib/../e2fsck/dict.h
e2freefrag.o: $(srcdir)/../misc/e2freefrag.c $(top_builddir)/lib/config.h \
$(top_builddir)/lib/dirpaths.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/bitops.h \
- $(srcdir)/../misc/e2freefrag.h
+ $(srcdir)/../misc/e2freefrag.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \
+ $(top_builddir)/lib/ss/ss_err.h $(srcdir)/../misc/create_inode.h \
+ $(top_srcdir)/lib/e2p/e2p.h $(srcdir)/../misc/nls-enable.h \
+ $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \
+ $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h
filefrag.o: $(srcdir)/filefrag.c $(top_builddir)/lib/config.h \
$(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \
$(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \
@@ -283,7 +305,9 @@ filefrag.o: $(srcdir)/filefrag.c $(top_builddir)/lib/config.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/bitops.h \
$(srcdir)/../misc/create_inode.h $(top_srcdir)/lib/e2p/e2p.h \
- $(srcdir)/../misc/nls-enable.h
+ $(srcdir)/../misc/nls-enable.h $(top_srcdir)/lib/quota/quotaio.h \
+ $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \
+ $(top_srcdir)/lib/../e2fsck/dict.h
extent_inode.o: $(srcdir)/extent_inode.c $(top_builddir)/lib/config.h \
$(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \
$(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \
@@ -292,7 +316,9 @@ extent_inode.o: $(srcdir)/extent_inode.c $(top_builddir)/lib/config.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/bitops.h \
$(srcdir)/../misc/create_inode.h $(top_srcdir)/lib/e2p/e2p.h \
- $(srcdir)/../misc/nls-enable.h
+ $(srcdir)/../misc/nls-enable.h $(top_srcdir)/lib/quota/quotaio.h \
+ $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \
+ $(top_srcdir)/lib/../e2fsck/dict.h
zap.o: $(srcdir)/zap.c $(top_builddir)/lib/config.h \
$(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \
$(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \
@@ -301,7 +327,9 @@ zap.o: $(srcdir)/zap.c $(top_builddir)/lib/config.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/bitops.h \
$(srcdir)/../misc/create_inode.h $(top_srcdir)/lib/e2p/e2p.h \
- $(srcdir)/../misc/nls-enable.h
+ $(srcdir)/../misc/nls-enable.h $(top_srcdir)/lib/quota/quotaio.h \
+ $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \
+ $(top_srcdir)/lib/../e2fsck/dict.h
create_inode.o: $(srcdir)/../misc/create_inode.c \
$(srcdir)/../misc/create_inode.h $(top_srcdir)/lib/et/com_err.h \
$(top_srcdir)/lib/e2p/e2p.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \
@@ -310,67 +338,50 @@ create_inode.o: $(srcdir)/../misc/create_inode.c \
$(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \
$(srcdir)/../misc/nls-enable.h
-xattrs.o: $(srcdir)/xattrs.c $(srcdir)/debugfs.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/bitops.h \
- $(srcdir)/jfs_user.h $(top_srcdir)/lib/ext2fs/kernel-jbd.h \
- $(top_srcdir)/lib/ext2fs/jfs_compat.h $(top_srcdir)/lib/ext2fs/kernel-list.h \
- $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \
- $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \
- $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h \
- $(top_srcdir)/lib/e2p/e2p.h
-unused.o: $(srcdir)/unused.c $(top_builddir)/lib/config.h \
+xattrs.o: $(srcdir)/xattrs.c $(top_builddir)/lib/config.h \
$(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \
$(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.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/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \
- $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \
- $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h
-e2freefrag.o: $(srcdir)/../misc/e2freefrag.c $(top_builddir)/lib/config.h \
- $(top_builddir)/lib/dirpaths.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/bitops.h \
- $(srcdir)/../misc/e2freefrag.h
-filefrag.o: $(srcdir)/filefrag.c $(top_builddir)/lib/config.h \
+ $(srcdir)/../misc/create_inode.h $(top_srcdir)/lib/e2p/e2p.h \
+ $(srcdir)/../misc/nls-enable.h $(top_srcdir)/lib/quota/quotaio.h \
+ $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \
+ $(top_srcdir)/lib/../e2fsck/dict.h
+quota.o: $(srcdir)/quota.c $(top_builddir)/lib/config.h \
$(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \
$(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.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/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \
- $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \
- $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h
-extent_inode.o: $(srcdir)/extent_inode.c $(top_builddir)/lib/config.h \
- $(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \
- $(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/../misc/create_inode.h $(top_srcdir)/lib/e2p/e2p.h \
+ $(srcdir)/../misc/nls-enable.h $(top_srcdir)/lib/quota/quotaio.h \
+ $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \
+ $(top_srcdir)/lib/../e2fsck/dict.h
+journal.o: $(srcdir)/journal.c $(top_builddir)/lib/config.h \
+ $(top_builddir)/lib/dirpaths.h $(srcdir)/../e2fsck/jfs_user.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/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.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/bitops.h \
- $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \
- $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h
-zap.o: $(srcdir)/zap.c $(top_builddir)/lib/config.h \
- $(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \
- $(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \
+ $(top_srcdir)/lib/ext2fs/kernel-jbd.h $(top_srcdir)/lib/ext2fs/jfs_compat.h \
+ $(top_srcdir)/lib/ext2fs/kernel-list.h
+revoke.o: $(srcdir)/../e2fsck/revoke.c $(srcdir)/../e2fsck/jfs_user.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/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.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/bitops.h \
- $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \
- $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h
-quota.o: $(srcdir)/quota.c $(top_builddir)/lib/config.h \
- $(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \
- $(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \
+ $(top_srcdir)/lib/ext2fs/kernel-jbd.h $(top_srcdir)/lib/ext2fs/jfs_compat.h \
+ $(top_srcdir)/lib/ext2fs/kernel-list.h
+recovery.o: $(srcdir)/../e2fsck/recovery.c $(srcdir)/../e2fsck/jfs_user.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/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.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/bitops.h \
- $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \
- $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h
+ $(top_srcdir)/lib/ext2fs/kernel-jbd.h $(top_srcdir)/lib/ext2fs/jfs_compat.h \
+ $(top_srcdir)/lib/ext2fs/kernel-list.h
diff --git a/debugfs/jfs_user.h b/debugfs/jfs_user.h
deleted file mode 100644
index 66756fc..0000000
--- a/debugfs/jfs_user.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef _JFS_USER_H
-#define _JFS_USER_H
-
-typedef unsigned short kdev_t;
-
-#include <ext2fs/kernel-jbd.h>
-
-#define JSB_HAS_INCOMPAT_FEATURE(jsb, mask) \
- ((jsb)->s_header.h_blocktype == ext2fs_cpu_to_be32(JFS_SUPERBLOCK_V2) && \
- ((jsb)->s_feature_incompat & ext2fs_cpu_to_be32((mask))))
-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))
- return sizeof(journal_block_tag3_t);
-
- sz = sizeof(journal_block_tag_t);
-
- if (JSB_HAS_INCOMPAT_FEATURE(jsb, JFS_FEATURE_INCOMPAT_CSUM_V2))
- sz += sizeof(__u16);
-
- if (JSB_HAS_INCOMPAT_FEATURE(jsb, JFS_FEATURE_INCOMPAT_64BIT))
- return sz;
-
- return sz - sizeof(__u32);
-}
-
-#endif /* _JFS_USER_H */
diff --git a/debugfs/journal.c b/debugfs/journal.c
new file mode 100644
index 0000000..99547c9
--- /dev/null
+++ b/debugfs/journal.c
@@ -0,0 +1,935 @@
+/*
+ * journal.c --- code for handling the "ext3" journal
+ *
+ * Copyright (C) 2000 Andreas Dilger
+ * Copyright (C) 2000 Theodore Ts'o
+ *
+ * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * This file may be redistributed under the terms of the
+ * GNU General Public License version 2 or at your discretion
+ * any later version.
+ */
+
+#include "config.h"
+#ifdef HAVE_SYS_MOUNT_H
+#include <sys/param.h>
+#include <sys/mount.h>
+#define MNT_FL (MS_MGC_VAL | MS_RDONLY)
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#define E2FSCK_INCLUDE_INLINE_FUNCS
+#include "jfs_user.h"
+#include "uuid/uuid.h"
+
+#ifdef CONFIG_JBD_DEBUG /* Enabled by configure --enable-jfs-debug */
+static int bh_count = 0;
+#endif
+
+#if EXT2_FLAT_INCLUDES
+#include "blkid.h"
+#else
+#include "blkid/blkid.h"
+#endif
+
+/*
+ * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
+ * This creates a larger static binary, and a smaller binary using
+ * shared libraries. It's also probably slightly less CPU-efficient,
+ * which is why it's not on by default. But, it's a good way of
+ * testing the functions in inode_io.c and fileio.c.
+ */
+#undef USE_INODE_IO
+
+/* Checksumming functions */
+static int ext2fs_journal_verify_csum_type(journal_t *j,
+ journal_superblock_t *jsb)
+{
+ if (!journal_has_csum_v2or3(j))
+ return 1;
+
+ return jsb->s_checksum_type == JBD2_CRC32C_CHKSUM;
+}
+
+static __u32 ext2fs_journal_sb_csum(journal_superblock_t *jsb)
+{
+ __u32 crc, old_crc;
+
+ old_crc = jsb->s_checksum;
+ jsb->s_checksum = 0;
+ crc = ext2fs_crc32c_le(~0, (unsigned char *)jsb,
+ sizeof(journal_superblock_t));
+ jsb->s_checksum = old_crc;
+
+ return crc;
+}
+
+static int ext2fs_journal_sb_csum_verify(journal_t *j,
+ journal_superblock_t *jsb)
+{
+ __u32 provided, calculated;
+
+ if (!journal_has_csum_v2or3(j))
+ return 1;
+
+ provided = ext2fs_be32_to_cpu(jsb->s_checksum);
+ calculated = ext2fs_journal_sb_csum(jsb);
+
+ return provided == calculated;
+}
+
+static errcode_t ext2fs_journal_sb_csum_set(journal_t *j,
+ journal_superblock_t *jsb)
+{
+ __u32 crc;
+
+ if (!journal_has_csum_v2or3(j))
+ return 0;
+
+ crc = ext2fs_journal_sb_csum(jsb);
+ jsb->s_checksum = ext2fs_cpu_to_be32(crc);
+ return 0;
+}
+
+/* Kernel compatibility functions for handling the journal. These allow us
+ * 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)
+{
+#ifdef USE_INODE_IO
+ *phys = block;
+ return 0;
+#else
+ struct inode *inode = journal->j_inode;
+ errcode_t retval;
+ blk64_t pblk;
+
+ if (!inode) {
+ *phys = block;
+ return 0;
+ }
+
+ retval = ext2fs_bmap2(inode->i_fs, inode->i_ino,
+ &inode->i_ext2, NULL, 0, block, 0, &pblk);
+ *phys = pblk;
+ return (int) retval;
+#endif
+}
+
+struct buffer_head *getblk(kdev_t kdev, blk64_t blocknr, int blocksize)
+{
+ struct buffer_head *bh;
+ int bufsize = sizeof(*bh) + kdev->k_fs->blocksize -
+ sizeof(bh->b_data);
+ errcode_t retval;
+
+ retval = ext2fs_get_memzero(bufsize, &bh);
+ if (retval)
+ return NULL;
+
+#ifdef CONFIG_JBD_DEBUG
+ if (journal_enable_debug >= 3)
+ bh_count++;
+#endif
+ jfs_debug(4, "getblk for block %llu (%d bytes)(total %d)\n",
+ (unsigned long long) blocknr, blocksize, bh_count);
+
+ bh->b_fs = kdev->k_fs;
+ if (kdev->k_dev == K_DEV_FS)
+ bh->b_io = kdev->k_fs->io;
+ else
+ bh->b_io = kdev->k_fs->journal_io;
+ bh->b_size = blocksize;
+ bh->b_blocknr = blocknr;
+
+ return bh;
+}
+
+int sync_blockdev(kdev_t kdev)
+{
+ io_channel io;
+
+ if (kdev->k_dev == K_DEV_FS)
+ io = kdev->k_fs->io;
+ else
+ io = kdev->k_fs->journal_io;
+
+ return io_channel_flush(io) ? EIO : 0;
+}
+
+void ll_rw_block(int rw, 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) {
+ jfs_debug(3, "reading block %llu/%p\n",
+ bh->b_blocknr, (void *) bh);
+ retval = io_channel_read_blk64(bh->b_io,
+ bh->b_blocknr,
+ 1, bh->b_data);
+ if (retval) {
+ com_err(bh->b_fs->device_name, retval,
+ "while reading block %llu\n",
+ bh->b_blocknr);
+ bh->b_err = (int) retval;
+ continue;
+ }
+ bh->b_uptodate = 1;
+ } else if (rw == WRITE && bh->b_dirty) {
+ jfs_debug(3, "writing block %llu/%p\n",
+ bh->b_blocknr,
+ (void *) bh);
+ retval = io_channel_write_blk64(bh->b_io,
+ bh->b_blocknr,
+ 1, bh->b_data);
+ if (retval) {
+ com_err(bh->b_fs->device_name, retval,
+ "while writing block %llu\n",
+ bh->b_blocknr);
+ bh->b_err = (int) retval;
+ continue;
+ }
+ bh->b_dirty = 0;
+ bh->b_uptodate = 1;
+ } else {
+ jfs_debug(3, "no-op %s for block %llu\n",
+ rw == READ ? "read" : "write",
+ bh->b_blocknr);
+ }
+ }
+}
+
+void mark_buffer_dirty(struct buffer_head *bh)
+{
+ bh->b_dirty = 1;
+}
+
+static void mark_buffer_clean(struct buffer_head *bh)
+{
+ bh->b_dirty = 0;
+}
+
+void brelse(struct buffer_head *bh)
+{
+ if (bh->b_dirty)
+ ll_rw_block(WRITE, 1, &bh);
+ jfs_debug(3, "freeing block %llu/%p (total %d)\n",
+ bh->b_blocknr, (void *) bh, --bh_count);
+ ext2fs_free_mem(&bh);
+}
+
+int buffer_uptodate(struct buffer_head *bh)
+{
+ return bh->b_uptodate;
+}
+
+void mark_buffer_uptodate(struct buffer_head *bh, int val)
+{
+ bh->b_uptodate = val;
+}
+
+void wait_on_buffer(struct buffer_head *bh)
+{
+ if (!bh->b_uptodate)
+ ll_rw_block(READ, 1, &bh);
+}
+
+
+static void ext2fs_clear_recover(ext2_filsys fs, int error)
+{
+ fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
+
+ /* if we had an error doing journal recovery, we need a full fsck */
+ if (error)
+ fs->super->s_state &= ~EXT2_VALID_FS;
+ ext2fs_mark_super_dirty(fs);
+}
+
+/*
+ * This is a helper function to check the validity of the journal.
+ */
+struct process_block_struct {
+ e2_blkcnt_t last_block;
+};
+
+static int process_journal_block(ext2_filsys fs,
+ blk64_t *block_nr,
+ e2_blkcnt_t blockcnt,
+ blk64_t ref_block EXT2FS_ATTR((unused)),
+ int ref_offset EXT2FS_ATTR((unused)),
+ void *priv_data)
+{
+ struct process_block_struct *p;
+ blk64_t blk = *block_nr;
+
+ p = (struct process_block_struct *) priv_data;
+
+ if (!blk || blk < fs->super->s_first_data_block ||
+ blk >= ext2fs_blocks_count(fs->super))
+ return BLOCK_ABORT;
+
+ if (blockcnt >= 0)
+ p->last_block = blockcnt;
+ return 0;
+}
+
+static errcode_t ext2fs_get_journal(ext2_filsys fs, journal_t **ret_journal)
+{
+ struct process_block_struct pb;
+ struct ext2_super_block *sb = fs->super;
+ struct ext2_super_block jsuper;
+ struct buffer_head *bh;
+ struct inode *j_inode = NULL;
+ struct kdev_s *dev_fs = NULL, *dev_journal;
+ const char *journal_name = 0;
+ journal_t *journal = NULL;
+ errcode_t retval = 0;
+ io_manager io_ptr = 0;
+ unsigned long long start = 0;
+ int ext_journal = 0;
+ int tried_backup_jnl = 0;
+
+ retval = ext2fs_get_memzero(sizeof(journal_t), &journal);
+ if (retval)
+ return retval;
+
+ retval = ext2fs_get_memzero(2 * sizeof(struct kdev_s), &dev_fs);
+ if (retval)
+ goto errout;
+ dev_journal = dev_fs+1;
+
+ dev_fs->k_fs = dev_journal->k_fs = fs;
+ dev_fs->k_dev = K_DEV_FS;
+ dev_journal->k_dev = K_DEV_JOURNAL;
+
+ journal->j_dev = dev_journal;
+ journal->j_fs_dev = dev_fs;
+ journal->j_inode = NULL;
+ journal->j_blocksize = fs->blocksize;
+
+ if (uuid_is_null(sb->s_journal_uuid)) {
+ if (!sb->s_journal_inum) {
+ retval = EXT2_ET_BAD_INODE_NUM;
+ goto errout;
+ }
+ retval = ext2fs_get_memzero(sizeof(*j_inode), &j_inode);
+ if (retval)
+ goto errout;
+
+ j_inode->i_fs = fs;
+ j_inode->i_ino = sb->s_journal_inum;
+
+ retval = ext2fs_read_inode(fs, sb->s_journal_inum,
+ &j_inode->i_ext2);
+ if (retval) {
+try_backup_journal:
+ if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
+ tried_backup_jnl)
+ goto errout;
+ memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
+ memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
+ EXT2_N_BLOCKS*4);
+ j_inode->i_ext2.i_size_high = sb->s_jnl_blocks[15];
+ j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
+ j_inode->i_ext2.i_links_count = 1;
+ j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
+ tried_backup_jnl++;
+ }
+ if (!j_inode->i_ext2.i_links_count ||
+ !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
+ retval = EXT2_ET_NO_JOURNAL;
+ goto try_backup_journal;
+ }
+ if (EXT2_I_SIZE(&j_inode->i_ext2) / journal->j_blocksize <
+ JFS_MIN_JOURNAL_BLOCKS) {
+ retval = EXT2_ET_JOURNAL_TOO_SMALL;
+ goto try_backup_journal;
+ }
+ pb.last_block = -1;
+ retval = ext2fs_block_iterate3(fs, j_inode->i_ino,
+ BLOCK_FLAG_HOLE, 0,
+ process_journal_block, &pb);
+ if ((pb.last_block + 1) * fs->blocksize <
+ (int) EXT2_I_SIZE(&j_inode->i_ext2)) {
+ retval = EXT2_ET_JOURNAL_TOO_SMALL;
+ goto try_backup_journal;
+ }
+ if (tried_backup_jnl && (fs->flags & EXT2_FLAG_RW)) {
+ retval = ext2fs_write_inode(fs, sb->s_journal_inum,
+ &j_inode->i_ext2);
+ if (retval)
+ goto errout;
+ }
+
+ journal->j_maxlen = EXT2_I_SIZE(&j_inode->i_ext2) /
+ journal->j_blocksize;
+
+#ifdef USE_INODE_IO
+ retval = ext2fs_inode_io_intern2(fs, sb->s_journal_inum,
+ &j_inode->i_ext2,
+ &journal_name);
+ if (retval)
+ goto errout;
+
+ io_ptr = inode_io_manager;
+#else
+ journal->j_inode = j_inode;
+ fs->journal_io = fs->io;
+ retval = (errcode_t)journal_bmap(journal, 0, &start);
+ if (retval)
+ goto errout;
+#endif
+ } else {
+ ext_journal = 1;
+ if (!fs->journal_name) {
+ char uuid[37];
+ blkid_cache blkid;
+
+ blkid_get_cache(&blkid, NULL);
+ uuid_unparse(sb->s_journal_uuid, uuid);
+ fs->journal_name = blkid_get_devname(blkid,
+ "UUID", uuid);
+ if (!fs->journal_name)
+ fs->journal_name = blkid_devno_to_devname(sb->s_journal_dev);
+ blkid_put_cache(blkid);
+ }
+ journal_name = fs->journal_name;
+
+ if (!journal_name) {
+ retval = EXT2_ET_LOAD_EXT_JOURNAL;
+ goto errout;
+ }
+
+ jfs_debug(1, "Using journal file %s\n", journal_name);
+ io_ptr = unix_io_manager;
+ }
+
+#if 0
+ test_io_backing_manager = io_ptr;
+ io_ptr = test_io_manager;
+#endif
+#ifndef USE_INODE_IO
+ if (ext_journal)
+#endif
+ {
+ retval = io_ptr->open(journal_name, fs->flags & EXT2_FLAG_RW,
+ &fs->journal_io);
+ }
+ if (retval)
+ goto errout;
+
+ io_channel_set_blksize(fs->journal_io, fs->blocksize);
+
+ if (ext_journal) {
+ blk64_t maxlen;
+
+ start = ext2fs_journal_sb_start(fs->blocksize) - 1;
+ bh = getblk(dev_journal, start, fs->blocksize);
+ if (!bh) {
+ retval = EXT2_ET_NO_MEMORY;
+ goto errout;
+ }
+ ll_rw_block(READ, 1, &bh);
+ retval = bh->b_err;
+ if (retval) {
+ brelse(bh);
+ goto errout;
+ }
+ memcpy(&jsuper, start ? bh->b_data :
+ bh->b_data + SUPERBLOCK_OFFSET,
+ sizeof(jsuper));
+#ifdef WORDS_BIGENDIAN
+ if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
+ ext2fs_swap_super(&jsuper);
+#endif
+ if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
+ !(jsuper.s_feature_incompat &
+ EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
+ retval = EXT2_ET_LOAD_EXT_JOURNAL;
+ brelse(bh);
+ goto errout;
+ }
+ /* Make sure the journal UUID is correct */
+ if (memcmp(jsuper.s_uuid, fs->super->s_journal_uuid,
+ sizeof(jsuper.s_uuid))) {
+ retval = EXT2_ET_LOAD_EXT_JOURNAL;
+ brelse(bh);
+ goto errout;
+ }
+
+ /* Check the superblock checksum */
+ if (jsuper.s_feature_ro_compat &
+ EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) {
+ struct struct_ext2_filsys fsx;
+ struct ext2_super_block superx;
+ void *p;
+
+ p = start ? bh->b_data : bh->b_data + SUPERBLOCK_OFFSET;
+ memcpy(&fsx, fs, sizeof(fsx));
+ memcpy(&superx, fs->super, sizeof(superx));
+ fsx.super = &superx;
+ fsx.super->s_feature_ro_compat |=
+ EXT4_FEATURE_RO_COMPAT_METADATA_CSUM;
+ if (!ext2fs_superblock_csum_verify(&fsx, p)) {
+ retval = EXT2_ET_LOAD_EXT_JOURNAL;
+ brelse(bh);
+ goto errout;
+ }
+ }
+ brelse(bh);
+
+ maxlen = ext2fs_blocks_count(&jsuper);
+ journal->j_maxlen = (maxlen < 1ULL << 32) ? maxlen :
+ (1ULL << 32) - 1;
+ start++;
+ }
+
+ bh = getblk(dev_journal, start, journal->j_blocksize);
+ if (!bh) {
+ retval = EXT2_ET_NO_MEMORY;
+ goto errout;
+ }
+
+ journal->j_sb_buffer = bh;
+ journal->j_superblock = (journal_superblock_t *)bh->b_data;
+
+#ifdef USE_INODE_IO
+ if (j_inode)
+ ext2fs_free_mem(&j_inode);
+#endif
+
+ *ret_journal = journal;
+ return 0;
+
+errout:
+ if (dev_fs)
+ ext2fs_free_mem(&dev_fs);
+ if (j_inode)
+ ext2fs_free_mem(&j_inode);
+ if (journal)
+ ext2fs_free_mem(&journal);
+ return retval;
+}
+
+static errcode_t ext2fs_journal_fix_bad_inode(ext2_filsys fs)
+{
+ struct ext2_super_block *sb = fs->super;
+ int recover = fs->super->s_feature_incompat &
+ EXT3_FEATURE_INCOMPAT_RECOVER;
+ int has_journal = fs->super->s_feature_compat &
+ EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+
+ if (has_journal || sb->s_journal_inum) {
+ /* The journal inode is bogus, remove and force full fsck */
+ return EXT2_ET_BAD_INODE_NUM;
+ } else if (recover) {
+ return EXT2_ET_UNSUPP_FEATURE;
+ }
+ return 0;
+}
+
+#define V1_SB_SIZE 0x0024
+static void clear_v2_journal_fields(journal_t *journal)
+{
+ ext2_filsys fs = journal->j_dev->k_fs;
+
+ memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
+ fs->blocksize-V1_SB_SIZE);
+ mark_buffer_dirty(journal->j_sb_buffer);
+}
+
+
+static errcode_t ext2fs_journal_load(journal_t *journal)
+{
+ ext2_filsys fs = journal->j_dev->k_fs;
+ journal_superblock_t *jsb;
+ struct buffer_head *jbh = journal->j_sb_buffer;
+
+ ll_rw_block(READ, 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))
+ return ext2fs_journal_fix_bad_inode(fs);
+
+ switch (ntohl(jsb->s_header.h_blocktype)) {
+ case JFS_SUPERBLOCK_V1:
+ journal->j_format_version = 1;
+ if (jsb->s_feature_compat ||
+ jsb->s_feature_incompat ||
+ jsb->s_feature_ro_compat ||
+ jsb->s_nr_users)
+ clear_v2_journal_fields(journal);
+ break;
+
+ case JFS_SUPERBLOCK_V2:
+ journal->j_format_version = 2;
+ if (ntohl(jsb->s_nr_users) > 1 &&
+ uuid_is_null(fs->super->s_journal_uuid))
+ clear_v2_journal_fields(journal);
+ if (ntohl(jsb->s_nr_users) > 1)
+ return EXT2_ET_JOURNAL_UNSUPP_VERSION;
+ break;
+
+ /*
+ * These should never appear in a journal super block, so if
+ * they do, the journal is badly corrupted.
+ */
+ case JFS_DESCRIPTOR_BLOCK:
+ case JFS_COMMIT_BLOCK:
+ case JFS_REVOKE_BLOCK:
+ return EXT2_ET_CORRUPT_SUPERBLOCK;
+
+ /* If we don't understand the superblock major type, but there
+ * is a magic number, then it is likely to be a new format we
+ * just don't understand, so leave it alone. */
+ default:
+ return EXT2_ET_JOURNAL_UNSUPP_VERSION;
+ }
+
+ if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
+ return EXT2_ET_UNSUPP_FEATURE;
+
+ if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
+ return EXT2_ET_RO_UNSUPP_FEATURE;
+
+ /* Checksum v1-3 are mutually exclusive features. */
+ if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V2) &&
+ JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V3))
+ return EXT2_ET_CORRUPT_SUPERBLOCK;
+
+ if (journal_has_csum_v2or3(journal) &&
+ JFS_HAS_COMPAT_FEATURE(journal, JFS_FEATURE_COMPAT_CHECKSUM))
+ return EXT2_ET_CORRUPT_SUPERBLOCK;
+
+ if (!ext2fs_journal_verify_csum_type(journal, jsb) ||
+ !ext2fs_journal_sb_csum_verify(journal, jsb))
+ return EXT2_ET_CORRUPT_SUPERBLOCK;
+
+ if (journal_has_csum_v2or3(journal))
+ journal->j_csum_seed = jbd2_chksum(journal, ~0, jsb->s_uuid,
+ sizeof(jsb->s_uuid));
+
+ /* We have now checked whether we know enough about the journal
+ * format to be able to proceed safely, so any other checks that
+ * fail we should attempt to recover from. */
+ if (jsb->s_blocksize != htonl(journal->j_blocksize))
+ return EXT2_ET_CORRUPT_SUPERBLOCK;
+
+ if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
+ journal->j_maxlen = ntohl(jsb->s_maxlen);
+ else if (ntohl(jsb->s_maxlen) > journal->j_maxlen)
+ return EXT2_ET_CORRUPT_SUPERBLOCK;
+
+ journal->j_tail_sequence = ntohl(jsb->s_sequence);
+ journal->j_transaction_sequence = journal->j_tail_sequence;
+ journal->j_tail = ntohl(jsb->s_start);
+ journal->j_first = ntohl(jsb->s_first);
+ journal->j_last = ntohl(jsb->s_maxlen);
+
+ return 0;
+}
+
+void ext2fs_journal_release(ext2_filsys fs, journal_t *journal,
+ int reset, int drop)
+{
+ journal_superblock_t *jsb;
+
+ if (drop)
+ mark_buffer_clean(journal->j_sb_buffer);
+ else if (fs->flags & EXT2_FLAG_RW) {
+ jsb = journal->j_superblock;
+ jsb->s_sequence = htonl(journal->j_tail_sequence);
+ if (reset)
+ jsb->s_start = 0; /* this marks the journal as empty */
+ ext2fs_journal_sb_csum_set(journal, jsb);
+ mark_buffer_dirty(journal->j_sb_buffer);
+ }
+ brelse(journal->j_sb_buffer);
+
+ if (fs->journal_io) {
+ if (fs && fs->io != fs->journal_io)
+ io_channel_close(fs->journal_io);
+ fs->journal_io = 0;
+ }
+
+#ifndef USE_INODE_IO
+ if (journal->j_inode)
+ ext2fs_free_mem(&journal->j_inode);
+#endif
+ if (journal->j_fs_dev)
+ ext2fs_free_mem(&journal->j_fs_dev);
+ ext2fs_free_mem(&journal);
+}
+
+/*
+ * This function makes sure that the superblock fields regarding the
+ * journal are consistent.
+ */
+errcode_t ext2fs_check_ext3_journal(ext2_filsys fs)
+{
+ struct ext2_super_block *sb = fs->super;
+ journal_t *journal;
+ int recover = fs->super->s_feature_incompat &
+ EXT3_FEATURE_INCOMPAT_RECOVER;
+ int reset = 0;
+ errcode_t retval;
+
+ /* If we don't have any journal features, don't do anything more */
+ if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
+ !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
+ uuid_is_null(sb->s_journal_uuid))
+ return 0;
+
+ retval = ext2fs_get_journal(fs, &journal);
+ if (retval)
+ return retval;
+
+ retval = ext2fs_journal_load(journal);
+ if (retval) {
+ ext2fs_journal_release(fs, journal, 0, 1);
+ return retval;
+ }
+
+ /*
+ * We want to make the flags consistent here. We will not leave with
+ * needs_recovery set but has_journal clear. We can't get in a loop
+ * with -y, -n, or -p, only if a user isn't making up their mind.
+ */
+ if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
+ return EXT2_ET_JOURNAL_FLAGS_WRONG;
+
+ if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
+ !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
+ journal->j_superblock->s_start != 0)
+ return EXT2_ET_JOURNAL_FLAGS_WRONG;
+
+ /*
+ * If we don't need to do replay the journal, check to see if
+ * the journal's errno is set; if so, we need to mark the file
+ * system as being corrupt and clear the journal's s_errno.
+ */
+ if (!(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
+ journal->j_superblock->s_errno) {
+ fs->super->s_state |= EXT2_ERROR_FS;
+ ext2fs_mark_super_dirty(fs);
+ journal->j_superblock->s_errno = 0;
+ ext2fs_journal_sb_csum_set(journal, journal->j_superblock);
+ mark_buffer_dirty(journal->j_sb_buffer);
+ }
+
+ ext2fs_journal_release(fs, journal, reset, 0);
+ return retval;
+}
+
+static errcode_t recover_ext3_journal(ext2_filsys fs)
+{
+ journal_t *journal;
+ errcode_t retval;
+
+ journal_init_revoke_caches();
+ retval = ext2fs_get_journal(fs, &journal);
+ if (retval)
+ return retval;
+
+ retval = ext2fs_journal_load(journal);
+ if (retval)
+ goto errout;
+
+ retval = journal_init_revoke(journal, 1024);
+ if (retval)
+ goto errout;
+
+ retval = -journal_recover(journal);
+ if (retval)
+ goto errout;
+
+ if (journal->j_failed_commit) {
+ journal->j_superblock->s_errno = -EINVAL;
+ mark_buffer_dirty(journal->j_sb_buffer);
+ }
+
+errout:
+ journal_destroy_revoke(journal);
+ journal_destroy_revoke_caches();
+ ext2fs_journal_release(fs, journal, 1, 0);
+ return retval;
+}
+
+errcode_t ext2fs_run_ext3_journal(ext2_filsys *fsp)
+{
+ ext2_filsys fs = *fsp;
+ io_manager io_ptr = fs->io->manager;
+ errcode_t retval, recover_retval;
+ io_stats stats = 0;
+ unsigned long long kbytes_written = 0;
+ char *fsname;
+ int fsflags;
+ int fsblocksize;
+
+ if (!(fs->flags & EXT2_FLAG_RW))
+ return EXT2_ET_FILE_RO;
+
+ if (fs->flags & EXT2_FLAG_DIRTY)
+ ext2fs_flush(fs); /* Force out any modifications */
+
+ recover_retval = recover_ext3_journal(fs);
+
+ /*
+ * Reload the filesystem context to get up-to-date data from disk
+ * because journal recovery will change the filesystem under us.
+ */
+ if (fs->super->s_kbytes_written &&
+ fs->io->manager->get_stats)
+ fs->io->manager->get_stats(fs->io, &stats);
+ if (stats && stats->bytes_written)
+ kbytes_written = stats->bytes_written >> 10;
+
+ ext2fs_mmp_stop(fs);
+ fsname = strdup(fs->device_name);
+ fsflags = fs->flags;
+ fsblocksize = fs->blocksize;
+ ext2fs_free(fs);
+ retval = ext2fs_open(fsname, fsflags,
+ 0, fsblocksize, io_ptr,
+ fsp);
+ free(fsname);
+ if (retval)
+ return retval;
+
+ fs = *fsp;
+ fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
+ fs->super->s_kbytes_written += kbytes_written;
+
+ /* Set the superblock flags */
+ ext2fs_clear_recover(fs, recover_retval != 0);
+
+ /*
+ * Do one last sanity check, and propagate journal->s_errno to
+ * the EXT2_ERROR_FS flag in the fs superblock if needed.
+ */
+ retval = ext2fs_check_ext3_journal(fs);
+ return retval ? retval : recover_retval;
+}
+
+errcode_t ext2fs_open_journal(ext2_filsys fs, journal_t **j)
+{
+ journal_t *journal;
+ errcode_t retval;
+
+ journal_init_revoke_caches();
+ retval = ext2fs_get_journal(fs, &journal);
+ if (retval)
+ return retval;
+
+ retval = ext2fs_journal_load(journal);
+ if (retval)
+ goto errout;
+
+ retval = journal_init_revoke(journal, 1024);
+ if (retval)
+ goto errout;
+
+ if (journal->j_failed_commit) {
+ journal->j_superblock->s_errno = -EINVAL;
+ mark_buffer_dirty(journal->j_sb_buffer);
+ }
+
+ *j = journal;
+ return 0;
+
+errout:
+ journal_destroy_revoke(journal);
+ journal_destroy_revoke_caches();
+ ext2fs_journal_release(fs, journal, 1, 0);
+ return retval;
+}
+
+errcode_t ext2fs_close_journal(ext2_filsys fs, journal_t **j)
+{
+ journal_t *journal = *j;
+
+ journal_destroy_revoke(journal);
+ journal_destroy_revoke_caches();
+ ext2fs_journal_release(fs, journal, 0, 0);
+ *j = NULL;
+
+ return 0;
+}
+
+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))
+ return;
+
+ h = (struct commit_header *)(bh->b_data);
+ h->h_chksum_type = 0;
+ h->h_chksum_size = 0;
+ h->h_chksum[0] = 0;
+ csum = jbd2_chksum(j, j->j_csum_seed, bh->b_data, j->j_blocksize);
+ h->h_chksum[0] = ext2fs_cpu_to_be32(csum);
+}
+
+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);
+}
+
+void jbd2_descr_block_csum_set(journal_t *j, struct buffer_head *bh)
+{
+ struct journal_block_tail *tail;
+ __u32 csum;
+
+ if (!journal_has_csum_v2or3(j))
+ return;
+
+ tail = (struct journal_block_tail *)(bh->b_data + j->j_blocksize -
+ sizeof(struct 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);
+}
+
+void jbd2_block_tag_csum_set(journal_t *j, journal_block_tag_t *tag,
+ struct buffer_head *bh, __u32 sequence)
+{
+ journal_block_tag3_t *tag3 = (journal_block_tag3_t *)tag;
+ __u32 csum32;
+ __be32 seq;
+
+ if (!journal_has_csum_v2or3(j))
+ return;
+
+ seq = ext2fs_cpu_to_be32(sequence);
+ csum32 = jbd2_chksum(j, j->j_csum_seed, (__u8 *)&seq, sizeof(seq));
+ csum32 = jbd2_chksum(j, csum32, bh->b_data, bh->b_size);
+
+ if (JFS_HAS_INCOMPAT_FEATURE(j, JFS_FEATURE_INCOMPAT_CSUM_V3))
+ tag3->t_checksum = ext2fs_cpu_to_be32(csum32);
+ else
+ tag->t_checksum = ext2fs_cpu_to_be16(csum32);
+}
+
diff --git a/e2fsck/Makefile.in b/e2fsck/Makefile.in
index cf044b1..a9c377d 100644
--- a/e2fsck/Makefile.in
+++ b/e2fsck/Makefile.in
@@ -273,10 +273,9 @@ e2fsck.o: $(srcdir)/e2fsck.c $(top_builddir)/lib/config.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/bitops.h \
- $(srcdir)/profile.h prof_err.h \
- $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \
- $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h \
- $(srcdir)/problem.h
+ $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/quotaio.h \
+ $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \
+ $(top_srcdir)/lib/../e2fsck/dict.h $(srcdir)/problem.h
dict.o: $(srcdir)/dict.c $(top_builddir)/lib/config.h \
$(top_builddir)/lib/dirpaths.h $(srcdir)/dict.h
super.o: $(srcdir)/super.c $(top_builddir)/lib/config.h \
@@ -361,8 +360,7 @@ journal.o: $(srcdir)/journal.c $(top_builddir)/lib/config.h \
$(top_srcdir)/lib/../e2fsck/dict.h $(top_srcdir)/lib/ext2fs/kernel-jbd.h \
$(top_srcdir)/lib/ext2fs/jfs_compat.h $(top_srcdir)/lib/ext2fs/kernel-list.h \
$(srcdir)/problem.h
-recovery.o: $(srcdir)/recovery.c $(top_builddir)/lib/config.h \
- $(top_builddir)/lib/dirpaths.h $(srcdir)/jfs_user.h $(srcdir)/e2fsck.h \
+recovery.o: $(srcdir)/recovery.c $(srcdir)/jfs_user.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 \
@@ -372,8 +370,7 @@ recovery.o: $(srcdir)/recovery.c $(top_builddir)/lib/config.h \
$(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \
$(top_srcdir)/lib/../e2fsck/dict.h $(top_srcdir)/lib/ext2fs/kernel-jbd.h \
$(top_srcdir)/lib/ext2fs/jfs_compat.h $(top_srcdir)/lib/ext2fs/kernel-list.h
-revoke.o: $(srcdir)/revoke.c $(top_builddir)/lib/config.h \
- $(top_builddir)/lib/dirpaths.h $(srcdir)/jfs_user.h $(srcdir)/e2fsck.h \
+revoke.o: $(srcdir)/revoke.c $(srcdir)/jfs_user.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 \
diff --git a/e2fsck/jfs_user.h b/e2fsck/jfs_user.h
index 9405e47..adb8ae9 100644
--- a/e2fsck/jfs_user.h
+++ b/e2fsck/jfs_user.h
@@ -8,31 +8,57 @@
* GNU General Public License version 2 or at your discretion
* any later version.
*/
-
+#ifndef _JFS_USER_H
+#define _JFS_USER_H
+
+#ifdef DEBUGFS
+#if EXT2_FLAT_INCLUDES
+#include "ext2_fs.h"
+#include "ext2fs.h"
+#include "blkid.h"
+#else
+#include "ext2fs/ext2_fs.h"
+#include "ext2fs/ext2fs.h"
+#include "blkid/blkid.h"
+#endif
+#else
/*
* Pull in the definition of the e2fsck context structure
*/
#include "e2fsck.h"
+#endif

struct buffer_head {
+#ifdef DEBUGFS
+ ext2_filsys b_fs;
+#else
e2fsck_t b_ctx;
- io_channel b_io;
- int b_size;
+#endif
+ io_channel b_io;
+ int b_size;
unsigned long long b_blocknr;
- int b_dirty;
- int b_uptodate;
- int b_err;
+ int b_dirty;
+ int b_uptodate;
+ int b_err;
char b_data[1024];
};

struct inode {
+#ifdef DEBUGFS
+ ext2_filsys i_fs;
+#else
e2fsck_t i_ctx;
+#endif
ext2_ino_t i_ino;
struct ext2_inode i_ext2;
};

struct kdev_s {
+#ifdef DEBUGFS
+ ext2_filsys k_fs;
+#else
e2fsck_t k_ctx;
+#endif
int k_dev;
};

@@ -41,22 +67,20 @@ struct kdev_s {

typedef struct kdev_s *kdev_t;

-#define lock_buffer(bh) do {} while(0)
-#define unlock_buffer(bh) do {} while(0)
+#define lock_buffer(bh) do {} while (0)
+#define unlock_buffer(bh) do {} while (0)
#define buffer_req(bh) 1
-#define do_readahead(journal, start) do {} while(0)
-
-extern e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */
+#define do_readahead(journal, start) do {} while (0)

typedef struct {
int object_length;
} lkmem_cache_t;

-#define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
-#define kmem_cache_free(cache,obj) free(obj)
-#define kmem_cache_create(name,len,a,b,c) do_cache_create(len)
+#define kmem_cache_alloc(cache, flags) malloc((cache)->object_length)
+#define kmem_cache_free(cache, obj) free(obj)
+#define kmem_cache_create(name, len, a, b, c) do_cache_create(len)
#define kmem_cache_destroy(cache) do_cache_destroy(cache)
-#define kmalloc(len,flags) malloc(len)
+#define kmalloc(len, flags) malloc(len)
#define kfree(p) free(p)

#define cond_resched() do { } while (0)
@@ -76,7 +100,7 @@ typedef __u64 __be64;
* functions.
*/
#ifdef NO_INLINE_FUNCS
-extern lkmem_cache_t * do_cache_create(int len);
+extern lkmem_cache_t *do_cache_create(int len);
extern void do_cache_destroy(lkmem_cache_t *cache);
extern size_t journal_tag_bytes(journal_t *journal);
#endif
@@ -101,9 +125,10 @@ extern size_t journal_tag_bytes(journal_t *journal);
#endif /* E2FSCK_INCLUDE_INLINE_FUNCS */


-_INLINE_ lkmem_cache_t * do_cache_create(int len)
+_INLINE_ lkmem_cache_t *do_cache_create(int len)
{
lkmem_cache_t *new_cache;
+
new_cache = malloc(sizeof(*new_cache));
if (new_cache)
new_cache->object_length = len;
@@ -136,3 +161,44 @@ void wait_on_buffer(struct buffer_head *bh);
*/
#define __getblk(dev, blocknr, blocksize) getblk(dev, blocknr, blocksize)
#define set_buffer_uptodate(bh) mark_buffer_uptodate(bh, 1)
+
+#ifdef DEBUGFS
+#include <assert.h>
+#undef J_ASSERT
+#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_feature_incompat & ext2fs_cpu_to_be32((mask))))
+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))
+ return sizeof(journal_block_tag3_t);
+
+ sz = sizeof(journal_block_tag_t);
+
+ if (JSB_HAS_INCOMPAT_FEATURE(jsb, JFS_FEATURE_INCOMPAT_CSUM_V2))
+ sz += sizeof(__u16);
+
+ if (JSB_HAS_INCOMPAT_FEATURE(jsb, JFS_FEATURE_INCOMPAT_64BIT))
+ return sz;
+
+ return sz - sizeof(__u32);
+}
+#else /* !DEBUGFS */
+
+extern e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */
+
+#define J_ASSERT(assert) \
+ do { if (!(assert)) { \
+ printf ("Assertion failure in %s() at %s line %d: " \
+ "\"%s\"\n", \
+ __FUNCTION__, __FILE__, __LINE__, # assert); \
+ fatal_error(e2fsck_global_ctx, 0); \
+ } } while (0)
+
+#endif /* DEBUGFS */
+
+#endif /* _JFS_USER_H */
diff --git a/lib/ext2fs/Makefile.in b/lib/ext2fs/Makefile.in
index 0f8b598..985c60f 100644
--- a/lib/ext2fs/Makefile.in
+++ b/lib/ext2fs/Makefile.in
@@ -4,7 +4,10 @@ VPATH = @srcdir@
top_builddir = ../..
my_dir = lib/ext2fs
INSTALL = @INSTALL@
-DEPEND_CFLAGS = -I$(top_srcdir)/debugfs
+DEPEND_CFLAGS = -I$(top_srcdir)/debugfs -I$(srcdir)/../../e2fsck -DDEBUGFS
+# This nastyness is needed because of jfs_user.h hackery; when we finally
+# clean up this mess, we should be able to drop it
+DEBUGFS_CFLAGS = $(ALL_CFLAGS) -I$(srcdir)/../../e2fsck -DDEBUGFS -DDEBUGFS

@MCONFIG@

@@ -19,7 +22,8 @@ MK_CMDS= _SS_DIR_OVERRIDE=../ss ../ss/mk_cmds
DEBUG_OBJS= debug_cmds.o extent_cmds.o tst_cmds.o debugfs.o util.o \
ncheck.o icheck.o ls.o lsdel.o dump.o set_fields.o logdump.o \
htree.o unused.o e2freefrag.o filefrag.o extent_inode.o zap.o \
- xattrs.o quota.o tst_libext2fs.o create_inode.o
+ xattrs.o quota.o tst_libext2fs.o create_inode.o journal.o \
+ revoke.o recovery.o

DEBUG_SRCS= debug_cmds.c extent_cmds.c tst_cmds.c \
$(top_srcdir)/debugfs/debugfs.c \
@@ -39,7 +43,10 @@ DEBUG_SRCS= debug_cmds.c extent_cmds.c tst_cmds.c \
$(top_srcdir)/debugfs/quota.c \
$(top_srcdir)/debugfs/xattrs.c \
$(top_srcdir)/misc/e2freefrag.c \
- $(top_srcdir)/misc/create_inode.c
+ $(top_srcdir)/misc/create_inode.c \
+ $(top_srcdir)/debugfs/journal.c \
+ $(top_srcdir)/e2fsck/revoke.c \
+ $(top_srcdir)/e2fsck/recovery.c

OBJS= $(DEBUGFS_LIB_OBJS) $(RESIZE_LIB_OBJS) $(E2IMAGE_LIB_OBJS) \
$(TEST_IO_LIB_OBJS) \
@@ -338,63 +345,75 @@ extent_cmds.c extent_cmds.h: $(top_srcdir)/debugfs/extent_cmds.ct

debugfs.o: $(top_srcdir)/debugfs/debugfs.c
$(E) " CC $<"
- $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
+ $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@

extent_inode.o: $(top_srcdir)/debugfs/extent_inode.c
$(E) " CC $<"
- $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
+ $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@

util.o: $(top_srcdir)/debugfs/util.c
$(E) " CC $<"
- $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
+ $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@

ncheck.o: $(top_srcdir)/debugfs/ncheck.c
$(E) " CC $<"
- $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
+ $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@

icheck.o: $(top_srcdir)/debugfs/icheck.c
$(E) " CC $<"
- $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
+ $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@

ls.o: $(top_srcdir)/debugfs/ls.c
$(E) " CC $<"
- $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
+ $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@

lsdel.o: $(top_srcdir)/debugfs/lsdel.c
$(E) " CC $<"
- $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
+ $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@

dump.o: $(top_srcdir)/debugfs/dump.c
$(E) " CC $<"
- $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
+ $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@

set_fields.o: $(top_srcdir)/debugfs/set_fields.c
$(E) " CC $<"
- $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
+ $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@

logdump.o: $(top_srcdir)/debugfs/logdump.c
$(E) " CC $<"
- $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
+ $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@

htree.o: $(top_srcdir)/debugfs/htree.c
$(E) " CC $<"
- $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
+ $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@

unused.o: $(top_srcdir)/debugfs/unused.c
$(E) " CC $<"
- $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
+ $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@

zap.o: $(top_srcdir)/debugfs/zap.c
$(E) " CC $<"
- $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
+ $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@

quota.o: $(top_srcdir)/debugfs/quota.c
$(E) " CC $<"
- $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
+ $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@
+
+journal.o: $(top_srcdir)/debugfs/journal.c
+ $(E) " CC $<"
+ $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@
+
+revoke.o: $(top_srcdir)/e2fsck/revoke.c
+ $(E) " CC $<"
+ $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@
+
+recovery.o: $(top_srcdir)/e2fsck/recovery.c
+ $(E) " CC $<"
+ $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@

xattrs.o: $(top_srcdir)/debugfs/xattrs.c
$(E) " CC $<"
- $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
+ $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@

e2freefrag.o: $(top_srcdir)/misc/e2freefrag.c
$(E) " CC $<"
@@ -1083,7 +1102,7 @@ debugfs.o: $(top_srcdir)/debugfs/debugfs.c $(top_builddir)/lib/config.h \
$(top_srcdir)/lib/e2p/e2p.h $(top_srcdir)/debugfs/../misc/nls-enable.h \
$(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \
$(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h \
- $(top_srcdir)/debugfs/../version.h $(top_srcdir)/debugfs/jfs_user.h \
+ $(top_srcdir)/debugfs/../version.h $(srcdir)/../../e2fsck/jfs_user.h \
$(srcdir)/kernel-jbd.h $(srcdir)/jfs_compat.h $(srcdir)/kernel-list.h
util.o: $(top_srcdir)/debugfs/util.c $(top_builddir)/lib/config.h \
$(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/ss/ss.h \
@@ -1173,7 +1192,7 @@ logdump.o: $(top_srcdir)/debugfs/logdump.c $(top_builddir)/lib/config.h \
$(top_srcdir)/lib/e2p/e2p.h $(top_srcdir)/debugfs/../misc/nls-enable.h \
$(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \
$(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h \
- $(top_srcdir)/debugfs/jfs_user.h $(srcdir)/kernel-jbd.h \
+ $(srcdir)/../../e2fsck/jfs_user.h $(srcdir)/kernel-jbd.h \
$(srcdir)/jfs_compat.h $(srcdir)/kernel-list.h
htree.o: $(top_srcdir)/debugfs/htree.c $(top_builddir)/lib/config.h \
$(top_builddir)/lib/dirpaths.h $(top_srcdir)/debugfs/debugfs.h \
@@ -1257,7 +1276,12 @@ e2freefrag.o: $(top_srcdir)/misc/e2freefrag.c $(top_builddir)/lib/config.h \
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
$(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
$(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/ext2_ext_attr.h \
- $(srcdir)/bitops.h $(top_srcdir)/misc/e2freefrag.h
+ $(srcdir)/bitops.h $(top_srcdir)/misc/e2freefrag.h \
+ $(top_srcdir)/debugfs/debugfs.h $(top_srcdir)/lib/ss/ss.h \
+ $(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/debugfs/../misc/create_inode.h \
+ $(top_srcdir)/lib/e2p/e2p.h $(top_srcdir)/debugfs/../misc/nls-enable.h \
+ $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \
+ $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h
create_inode.o: $(top_srcdir)/misc/create_inode.c \
$(top_srcdir)/misc/create_inode.h $(top_srcdir)/lib/et/com_err.h \
$(top_srcdir)/lib/e2p/e2p.h $(srcdir)/ext2_fs.h \
@@ -1265,3 +1289,22 @@ create_inode.o: $(top_srcdir)/misc/create_inode.c \
$(srcdir)/ext3_extents.h $(srcdir)/ext2_io.h \
$(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/ext2_ext_attr.h \
$(srcdir)/bitops.h $(top_srcdir)/misc/nls-enable.h
+journal.o: $(top_srcdir)/debugfs/journal.c $(top_builddir)/lib/config.h \
+ $(top_builddir)/lib/dirpaths.h $(srcdir)/../../e2fsck/jfs_user.h \
+ $(srcdir)/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \
+ $(srcdir)/ext2fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h $(srcdir)/kernel-jbd.h \
+ $(srcdir)/jfs_compat.h $(srcdir)/kernel-list.h
+revoke.o: $(top_srcdir)/e2fsck/revoke.c $(top_srcdir)/e2fsck/jfs_user.h \
+ $(srcdir)/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \
+ $(srcdir)/ext2fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h $(srcdir)/kernel-jbd.h \
+ $(srcdir)/jfs_compat.h $(srcdir)/kernel-list.h
+recovery.o: $(top_srcdir)/e2fsck/recovery.c $(top_srcdir)/e2fsck/jfs_user.h \
+ $(srcdir)/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \
+ $(srcdir)/ext2fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h $(srcdir)/kernel-jbd.h \
+ $(srcdir)/jfs_compat.h $(srcdir)/kernel-list.h
diff --git a/lib/ext2fs/ext2_err.et.in b/lib/ext2fs/ext2_err.et.in
index 6b6d8b8..790d135 100644
--- a/lib/ext2fs/ext2_err.et.in
+++ b/lib/ext2fs/ext2_err.et.in
@@ -521,4 +521,7 @@ ec EXT2_ET_INODE_IS_GARBAGE,
ec EXT2_ET_EA_BAD_VALUE_OFFSET,
"Extended attribute has an invalid value offset"

+ec EXT2_ET_JOURNAL_FLAGS_WRONG,
+ "Journal flags inconsistent"
+
end
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index b4a9f84..d931fff 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -282,6 +282,9 @@ struct struct_ext2_filsys {

/* Precomputed FS UUID checksum for seeding other checksums */
__u32 csum_seed;
+
+ io_channel journal_io;
+ char *journal_name;
};

#if EXT2_FLAT_INCLUDES

2014-09-11 20:17:50

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 30/25] libext2fs: check ea value offset when loading

When reading extended attributes, check e_value_offs to make sure that
it starts in the value area and not the name area. The attached test
case image will crash the kernel if it is mounted and you append more
than 4096 bytes of data to /a, due to insufficient validation.

Signed-off-by: Darrick J. Wong <[email protected]>
---
lib/ext2fs/ext_attr.c | 29 ++++++++++++++++++++++++-----
tests/f_ea_value_crash/expect.1 | 15 +++++++++++++++
tests/f_ea_value_crash/expect.2 | 7 +++++++
tests/f_ea_value_crash/image.gz | Bin
tests/f_ea_value_crash/name | 1 +
5 files changed, 47 insertions(+), 5 deletions(-)
create mode 100644 tests/f_ea_value_crash/expect.1
create mode 100644 tests/f_ea_value_crash/expect.2
create mode 100644 tests/f_ea_value_crash/image.gz
create mode 100644 tests/f_ea_value_crash/name

diff --git a/lib/ext2fs/ext_attr.c b/lib/ext2fs/ext_attr.c
index f9b9208..b52abb5 100644
--- a/lib/ext2fs/ext_attr.c
+++ b/lib/ext2fs/ext_attr.c
@@ -618,7 +618,7 @@ static errcode_t read_xattrs_from_buffer(struct ext2_xattr_handle *handle,
size_t *nr_read)
{
struct ext2_xattr *x;
- struct ext2_ext_attr_entry *entry;
+ struct ext2_ext_attr_entry *entry, *end;
const char *prefix;
unsigned int remain, prefix_len;
errcode_t err;
@@ -629,20 +629,34 @@ static errcode_t read_xattrs_from_buffer(struct ext2_xattr_handle *handle,
while (x->name)
x++;

- entry = entries;
+ /* find the end */
+ end = entries;
remain = storage_size;
while (remain >= sizeof(struct ext2_ext_attr_entry) &&
- !EXT2_EXT_IS_LAST_ENTRY(entry)) {
- __u32 hash;
+ !EXT2_EXT_IS_LAST_ENTRY(end)) {

/* header eats this space */
remain -= sizeof(struct ext2_ext_attr_entry);

/* is attribute name valid? */
- if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain)
+ if (EXT2_EXT_ATTR_SIZE(end->e_name_len) > remain)
return EXT2_ET_EA_BAD_NAME_LEN;

/* attribute len eats this space */
+ remain -= EXT2_EXT_ATTR_SIZE(end->e_name_len);
+ end = EXT2_EXT_ATTR_NEXT(end);
+ }
+
+ entry = entries;
+ remain = storage_size;
+ while (remain >= sizeof(struct ext2_ext_attr_entry) &&
+ !EXT2_EXT_IS_LAST_ENTRY(entry)) {
+ __u32 hash;
+
+ /* header eats this space */
+ remain -= sizeof(struct ext2_ext_attr_entry);
+
+ /* attribute len eats this space */
remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);

/* check value size */
@@ -652,6 +666,11 @@ static errcode_t read_xattrs_from_buffer(struct ext2_xattr_handle *handle,
if (entry->e_value_offs + entry->e_value_size > values_size)
return EXT2_ET_EA_BAD_VALUE_OFFSET;

+ if (entry->e_value_size > 0 &&
+ value_start + entry->e_value_offs <
+ (void *)end + sizeof(__u32))
+ return EXT2_ET_EA_BAD_VALUE_OFFSET;
+
/* e_value_block must be 0 in inode's ea */
if (entry->e_value_block != 0)
return EXT2_ET_BAD_EA_BLOCK_NUM;
diff --git a/tests/f_ea_value_crash/expect.1 b/tests/f_ea_value_crash/expect.1
new file mode 100644
index 0000000..8315358
--- /dev/null
+++ b/tests/f_ea_value_crash/expect.1
@@ -0,0 +1,15 @@
+Pass 1: Checking inodes, blocks, and sizes
+Inode 12 has INLINE_DATA_FL flag but extended attribute not found. Truncate? yes
+
+Inode 12 extended attribute is corrupt (allocation collision). Clear? yes
+
+Inode 13 extended attribute is corrupt (allocation collision). Clear? yes
+
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 13/128 files (0.0% non-contiguous), 17/512 blocks
+Exit status is 1
diff --git a/tests/f_ea_value_crash/expect.2 b/tests/f_ea_value_crash/expect.2
new file mode 100644
index 0000000..06886a4
--- /dev/null
+++ b/tests/f_ea_value_crash/expect.2
@@ -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/128 files (0.0% non-contiguous), 17/512 blocks
+Exit status is 0
diff --git a/tests/f_ea_value_crash/image.gz b/tests/f_ea_value_crash/image.gz
new file mode 100644
index 0000000000000000000000000000000000000000..c45fb0e1dd7d349f32bca100653a3aa428255f00
GIT binary patch
literal 2627
zcmb2|=3rp@FBrna{Pvb@j&Gs_!-My8?j7;Xch#2ln8nfEC=%_eVs#;OQS;G&&}pxH
z?|7-QrEZ(SbL7g5-JTOB@RbNADjCk4@Wazb=*suI)q0_8170n!o%hW4{m-B8&R3s%
zd;R;pdjbtpvut!f30yn=#fp1j*qig+EBGb!FCFjux7zTNfpM_{U*F-wPcHZUdsdt3
zx=uve*3fq@_rsDiw&qpkZ}Z<*SNwJIe?PPQyZSS`{@mm4Zqs*NySiQP{k<Iv^IzSH
zs4IWow^BOthVZRV$2Q(9{i7HAQGIrLz2>nveOm^Ge@$2Zt?S*m^4|aJkIG(t-WYYG
z=CULc14G0A`!kC)_vA<Zd7I7v<krXi`d=S?;?uheKlB`;Pkes&?pS$+wR5&z%-Y^O
z%P3pRA{E)y{b$*d;$)Mne5c8N6XXJF`}0|gd(VIWd20*nfV_m88Ra0+1HbEmBq<;w
z%2@hY4l_{8={|o4QgouJ{UJHo-}=|=jgwy0-INx8s~Gd^#>M)j9mgh43t0EO=)~hq
zUvtI0Hs?*h>i%cfI*I&SY`=qe%KhY{GM~%;s6KZ7*wMGPpU?b{H2kj{mwK*j+krpk
z-``JI%~XHv?UnyI^Vk1BeR$WR|D2z{*suJq`FGjB^oRHV|2Z0T-Cpqd{#rx(j{e^U
z$C@KQ$1k*9JNFl>yqbLIzVQD)tDA2YJpK4t<mJcUyle4MS0l1@kI73)$ZDj=uX8Ng
zWLC21cg5CU%3t}yj;CF{w8GxA_WhCYzxkX071gf&`u5TK?{mA4$JMU?_fp+?`E1*Q
zsy|a^f1SR0?fq*}vXWZq?ECN9TZR3-_<Ty+vE7D@XaO?H9Swoe5Eu=C(GVC7fzc44
TRtOw0`oj6orzoF+L4g4P<Nr%E

literal 0
HcmV?d00001

diff --git a/tests/f_ea_value_crash/name b/tests/f_ea_value_crash/name
new file mode 100644
index 0000000..194bbed
--- /dev/null
+++ b/tests/f_ea_value_crash/name
@@ -0,0 +1 @@
+extended attribute value conflicts with key

2014-09-11 20:25:36

by Darrick J. Wong

[permalink] [raw]
Subject: Re: [PATCH 10/25] debugfs: create journal handling routines

On Thu, Sep 11, 2014 at 04:14:58PM -0400, Theodore Ts'o wrote:
> On Thu, Sep 11, 2014 at 12:03:49PM -0700, Darrick J. Wong wrote:
> > Will that pick up debugfs/jfs_user.h, though? I originally tried it this way
> > but gcc seemed to want to pull in the jfs_user.h from e2fsck/.
>
> Yeah, I figured that out shortly after I sent the message. The way I
> fixed it was a bit more involved, but I think it's cleaner.
>
> Long run, what I want to do is to rename libquota to libsupport, and
> then move things like profile.c, recovery.c, revoke.c, etc. into that
> single directory, and then harmonize all of the ugly hacks that we
> have in various different versions of jfs_user.h. Given that, what I
> did for now was to harmonize (as much as possible) debugfs/jfs_user.h
> and e2fsck/jfs_user.h, and there is now a single version of jfs_user.h
> in e2fsck. We still have some customizations based on -DDEBUGFS, but
> we can clean that up later.

Ok, thanks for your help! :)

<snip>

> diff --git a/lib/ext2fs/Makefile.in b/lib/ext2fs/Makefile.in
> index 0f8b598..985c60f 100644
> --- a/lib/ext2fs/Makefile.in
> +++ b/lib/ext2fs/Makefile.in
> @@ -4,7 +4,10 @@ VPATH = @srcdir@
> top_builddir = ../..
> my_dir = lib/ext2fs
> INSTALL = @INSTALL@
> -DEPEND_CFLAGS = -I$(top_srcdir)/debugfs
> +DEPEND_CFLAGS = -I$(top_srcdir)/debugfs -I$(srcdir)/../../e2fsck -DDEBUGFS
> +# This nastyness is needed because of jfs_user.h hackery; when we finally
> +# clean up this mess, we should be able to drop it
> +DEBUGFS_CFLAGS = $(ALL_CFLAGS) -I$(srcdir)/../../e2fsck -DDEBUGFS -DDEBUGFS

Probably not necessary to -DDEBUGFS twice here.

--D

>
> @MCONFIG@
>
> @@ -19,7 +22,8 @@ MK_CMDS= _SS_DIR_OVERRIDE=../ss ../ss/mk_cmds
> DEBUG_OBJS= debug_cmds.o extent_cmds.o tst_cmds.o debugfs.o util.o \
> ncheck.o icheck.o ls.o lsdel.o dump.o set_fields.o logdump.o \
> htree.o unused.o e2freefrag.o filefrag.o extent_inode.o zap.o \
> - xattrs.o quota.o tst_libext2fs.o create_inode.o
> + xattrs.o quota.o tst_libext2fs.o create_inode.o journal.o \
> + revoke.o recovery.o
>
> DEBUG_SRCS= debug_cmds.c extent_cmds.c tst_cmds.c \
> $(top_srcdir)/debugfs/debugfs.c \
> @@ -39,7 +43,10 @@ DEBUG_SRCS= debug_cmds.c extent_cmds.c tst_cmds.c \
> $(top_srcdir)/debugfs/quota.c \
> $(top_srcdir)/debugfs/xattrs.c \
> $(top_srcdir)/misc/e2freefrag.c \
> - $(top_srcdir)/misc/create_inode.c
> + $(top_srcdir)/misc/create_inode.c \
> + $(top_srcdir)/debugfs/journal.c \
> + $(top_srcdir)/e2fsck/revoke.c \
> + $(top_srcdir)/e2fsck/recovery.c
>
> OBJS= $(DEBUGFS_LIB_OBJS) $(RESIZE_LIB_OBJS) $(E2IMAGE_LIB_OBJS) \
> $(TEST_IO_LIB_OBJS) \
> @@ -338,63 +345,75 @@ extent_cmds.c extent_cmds.h: $(top_srcdir)/debugfs/extent_cmds.ct
>
> debugfs.o: $(top_srcdir)/debugfs/debugfs.c
> $(E) " CC $<"
> - $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
> + $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@
>
> extent_inode.o: $(top_srcdir)/debugfs/extent_inode.c
> $(E) " CC $<"
> - $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
> + $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@
>
> util.o: $(top_srcdir)/debugfs/util.c
> $(E) " CC $<"
> - $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
> + $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@
>
> ncheck.o: $(top_srcdir)/debugfs/ncheck.c
> $(E) " CC $<"
> - $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
> + $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@
>
> icheck.o: $(top_srcdir)/debugfs/icheck.c
> $(E) " CC $<"
> - $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
> + $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@
>
> ls.o: $(top_srcdir)/debugfs/ls.c
> $(E) " CC $<"
> - $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
> + $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@
>
> lsdel.o: $(top_srcdir)/debugfs/lsdel.c
> $(E) " CC $<"
> - $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
> + $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@
>
> dump.o: $(top_srcdir)/debugfs/dump.c
> $(E) " CC $<"
> - $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
> + $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@
>
> set_fields.o: $(top_srcdir)/debugfs/set_fields.c
> $(E) " CC $<"
> - $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
> + $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@
>
> logdump.o: $(top_srcdir)/debugfs/logdump.c
> $(E) " CC $<"
> - $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
> + $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@
>
> htree.o: $(top_srcdir)/debugfs/htree.c
> $(E) " CC $<"
> - $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
> + $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@
>
> unused.o: $(top_srcdir)/debugfs/unused.c
> $(E) " CC $<"
> - $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
> + $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@
>
> zap.o: $(top_srcdir)/debugfs/zap.c
> $(E) " CC $<"
> - $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
> + $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@
>
> quota.o: $(top_srcdir)/debugfs/quota.c
> $(E) " CC $<"
> - $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
> + $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@
> +
> +journal.o: $(top_srcdir)/debugfs/journal.c
> + $(E) " CC $<"
> + $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@
> +
> +revoke.o: $(top_srcdir)/e2fsck/revoke.c
> + $(E) " CC $<"
> + $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@
> +
> +recovery.o: $(top_srcdir)/e2fsck/recovery.c
> + $(E) " CC $<"
> + $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@
>
> xattrs.o: $(top_srcdir)/debugfs/xattrs.c
> $(E) " CC $<"
> - $(Q) $(CC) $(ALL_CFLAGS) -c $< -o $@
> + $(Q) $(CC) $(DEBUGFS_CFLAGS) -c $< -o $@
>
> e2freefrag.o: $(top_srcdir)/misc/e2freefrag.c
> $(E) " CC $<"
> @@ -1083,7 +1102,7 @@ debugfs.o: $(top_srcdir)/debugfs/debugfs.c $(top_builddir)/lib/config.h \
> $(top_srcdir)/lib/e2p/e2p.h $(top_srcdir)/debugfs/../misc/nls-enable.h \
> $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \
> $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h \
> - $(top_srcdir)/debugfs/../version.h $(top_srcdir)/debugfs/jfs_user.h \
> + $(top_srcdir)/debugfs/../version.h $(srcdir)/../../e2fsck/jfs_user.h \
> $(srcdir)/kernel-jbd.h $(srcdir)/jfs_compat.h $(srcdir)/kernel-list.h
> util.o: $(top_srcdir)/debugfs/util.c $(top_builddir)/lib/config.h \
> $(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/ss/ss.h \
> @@ -1173,7 +1192,7 @@ logdump.o: $(top_srcdir)/debugfs/logdump.c $(top_builddir)/lib/config.h \
> $(top_srcdir)/lib/e2p/e2p.h $(top_srcdir)/debugfs/../misc/nls-enable.h \
> $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \
> $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h \
> - $(top_srcdir)/debugfs/jfs_user.h $(srcdir)/kernel-jbd.h \
> + $(srcdir)/../../e2fsck/jfs_user.h $(srcdir)/kernel-jbd.h \
> $(srcdir)/jfs_compat.h $(srcdir)/kernel-list.h
> htree.o: $(top_srcdir)/debugfs/htree.c $(top_builddir)/lib/config.h \
> $(top_builddir)/lib/dirpaths.h $(top_srcdir)/debugfs/debugfs.h \
> @@ -1257,7 +1276,12 @@ e2freefrag.o: $(top_srcdir)/misc/e2freefrag.c $(top_builddir)/lib/config.h \
> $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
> $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h $(srcdir)/ext2_io.h \
> $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/ext2_ext_attr.h \
> - $(srcdir)/bitops.h $(top_srcdir)/misc/e2freefrag.h
> + $(srcdir)/bitops.h $(top_srcdir)/misc/e2freefrag.h \
> + $(top_srcdir)/debugfs/debugfs.h $(top_srcdir)/lib/ss/ss.h \
> + $(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/debugfs/../misc/create_inode.h \
> + $(top_srcdir)/lib/e2p/e2p.h $(top_srcdir)/debugfs/../misc/nls-enable.h \
> + $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \
> + $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h
> create_inode.o: $(top_srcdir)/misc/create_inode.c \
> $(top_srcdir)/misc/create_inode.h $(top_srcdir)/lib/et/com_err.h \
> $(top_srcdir)/lib/e2p/e2p.h $(srcdir)/ext2_fs.h \
> @@ -1265,3 +1289,22 @@ create_inode.o: $(top_srcdir)/misc/create_inode.c \
> $(srcdir)/ext3_extents.h $(srcdir)/ext2_io.h \
> $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/ext2_ext_attr.h \
> $(srcdir)/bitops.h $(top_srcdir)/misc/nls-enable.h
> +journal.o: $(top_srcdir)/debugfs/journal.c $(top_builddir)/lib/config.h \
> + $(top_builddir)/lib/dirpaths.h $(srcdir)/../../e2fsck/jfs_user.h \
> + $(srcdir)/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \
> + $(srcdir)/ext2fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
> + $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
> + $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h $(srcdir)/kernel-jbd.h \
> + $(srcdir)/jfs_compat.h $(srcdir)/kernel-list.h
> +revoke.o: $(top_srcdir)/e2fsck/revoke.c $(top_srcdir)/e2fsck/jfs_user.h \
> + $(srcdir)/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \
> + $(srcdir)/ext2fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
> + $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
> + $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h $(srcdir)/kernel-jbd.h \
> + $(srcdir)/jfs_compat.h $(srcdir)/kernel-list.h
> +recovery.o: $(top_srcdir)/e2fsck/recovery.c $(top_srcdir)/e2fsck/jfs_user.h \
> + $(srcdir)/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \
> + $(srcdir)/ext2fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
> + $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
> + $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h $(srcdir)/kernel-jbd.h \
> + $(srcdir)/jfs_compat.h $(srcdir)/kernel-list.h
> diff --git a/lib/ext2fs/ext2_err.et.in b/lib/ext2fs/ext2_err.et.in
> index 6b6d8b8..790d135 100644
> --- a/lib/ext2fs/ext2_err.et.in
> +++ b/lib/ext2fs/ext2_err.et.in
> @@ -521,4 +521,7 @@ ec EXT2_ET_INODE_IS_GARBAGE,
> ec EXT2_ET_EA_BAD_VALUE_OFFSET,
> "Extended attribute has an invalid value offset"
>
> +ec EXT2_ET_JOURNAL_FLAGS_WRONG,
> + "Journal flags inconsistent"
> +
> end
> diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
> index b4a9f84..d931fff 100644
> --- a/lib/ext2fs/ext2fs.h
> +++ b/lib/ext2fs/ext2fs.h
> @@ -282,6 +282,9 @@ struct struct_ext2_filsys {
>
> /* Precomputed FS UUID checksum for seeding other checksums */
> __u32 csum_seed;
> +
> + io_channel journal_io;
> + char *journal_name;
> };
>
> #if EXT2_FLAT_INCLUDES
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

2014-09-11 20:58:43

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 11/25] e2fsck: fix minor errors in journal handling

On Mon, Sep 08, 2014 at 04:12:48PM -0700, Darrick J. Wong wrote:
> The journal superblock's s_sequence field seems to track the tid of
> the tail (oldest) transaction in the log. Therefore, when we release
> the journal, set the s_sequence to the tail_sequence, because setting
> it to the transaction_sequence means that we're setting the tid to
> that of the head of the log. Granted, for replay these two are
> usually the same (and s_start == 0 anyway) so thus far we've gotten
> lucky and nobody noticed.
>
> Signed-off-by: Darrick J. Wong <[email protected]>

Thanks, applied.

(Actually, for e2fsck for replay it will always be the same because
the journal *must* be completely replaied cleared before the rest of
e2fsck can be allowed to proceed.)

- Ted


2014-09-11 20:58:52

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 12/25] debugfs: add the ability to write transactions to the journal

On Mon, Sep 08, 2014 at 04:12:54PM -0700, Darrick J. Wong wrote:
> Extend debugfs with the ability to create transactions and replay the
> journal. This will eventually be used to test kernel recovery and
> metadata_csum recovery.
>
> v2: Find the FS context without using j_inode, since it won't always
> be valid; allow user to specify external journal file; start writing
> transactions at j_first.
>
> Signed-off-by: Darrick J. Wong <[email protected]>

Thanks, applied.

- Ted

2014-09-11 20:59:05

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 13/25] tests: test writing and recovering checksum-free 32/64bit journals

On Mon, Sep 08, 2014 at 04:13:01PM -0700, Darrick J. Wong wrote:
> Simple tests for the journal transaction creation code. We test
> writing (bad) block bitmaps out through the journal and replaying them
> via fsck, with a few twists:
>
> (a) All bitmaps are committed (fs errors reported)
> (b) All the bitmap blocks are revoked (no errors)
> (c) The transaction is never committed (no errors)
> (d) Same as (a), but debugfs gets to do the replay.
>
> We also test:
>
> (a) writing and replaying transactions with multiple
> descriptor blocks
> (b) same, but with multiple revoke blocks.
> (c) adding the 64bit flag to a journal
>
> Signed-off-by: Darrick J. Wong <[email protected]>

Thanks, applied.

- Ted

2014-09-11 20:59:17

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 14/25] tests: test writing and recovering 64bit csum_v3 journals

On Mon, Sep 08, 2014 at 04:13:08PM -0700, Darrick J. Wong wrote:
> Simple tests for the 64bit journal transaction creation code when
> journal and metadata_csum are enabled. We test writing (bad) block
> bitmaps out through the journal and replaying them via fsck, with a
> few twists:
>
> (a) All bitmaps are committed (fs errors reported)
> (b) All the bitmap blocks are revoked (no errors)
> (c) The transaction is never committed (no errors)
> (d) Same as (a), but debugfs gets to do the replay.
>
> We also test:
>
> (a) writing and replaying transactions with multiple
> descriptor blocks
> (b) same, but with multiple revoke blocks.
>
> Signed-off-by: Darrick J. Wong <[email protected]>

Thanks, applied.

- Ted

2014-09-11 20:59:27

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 15/25] tests: test writing and recovering 32bit csum_v3 journals

On Mon, Sep 08, 2014 at 04:13:14PM -0700, Darrick J. Wong wrote:
> Simple tests for the 32bit journal transaction creation code when
> journal and metadata_csum are enabled. We test the following:
>
> (a) writing and replaying transactions with multiple
> descriptor blocks
> (b) same, but with multiple revoke blocks.
>
> Signed-off-by: Darrick J. Wong <[email protected]>

Thanks, applied.

- Ted

2014-09-11 20:59:39

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 16/25] tests: write and replay blocks with the old journal checksum

On Mon, Sep 08, 2014 at 04:13:22PM -0700, Darrick J. Wong wrote:
> Test that we can write and replay transactions with the old journal
> checksum algorithm.
>
> Signed-off-by: Darrick J. Wong <[email protected]>

Thanks, applied.

- Ted

2014-09-11 20:59:50

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 17/25] tests: test recovery of 32 and 64-bit journals with checksum v2

On Mon, Sep 08, 2014 at 04:13:28PM -0700, Darrick J. Wong wrote:
> Add tests to ensure that we know how to recover journals with the
> csum_v2 feature set.
>
> Signed-off-by: Darrick J. Wong <[email protected]>

Thanks, applied.

- Ted

2014-09-11 21:04:21

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 18/25] tests: test how e2fsck recovers from corrupt journal superblocks

On Mon, Sep 08, 2014 at 04:13:35PM -0700, Darrick J. Wong wrote:
> Test e2fsck' ability to deal with corrupt journal superblock checksum
> and a bad magic.
>
> Signed-off-by: Darrick J. Wong <[email protected]>

Thanks, applied.

- Ted

2014-09-11 21:04:30

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 19/25] tests: test e2fsck recovery of corrupt revoke blocks

On Mon, Sep 08, 2014 at 04:13:41PM -0700, Darrick J. Wong wrote:
> Test e2fsck' ability to deal with (a) revoke blocks with a bad
> checksum and (b) revoke blocks with an obviously bad block number.
>
> Signed-off-by: Darrick J. Wong <[email protected]>

Thanks, applied.

- Ted

2014-09-11 21:04:41

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 20/25] tests: test e2fsck recovery with broken commit blocks

On Mon, Sep 08, 2014 at 04:13:48PM -0700, Darrick J. Wong wrote:
> Test e2fsck' recovery of commit blocks with (a) only a corrupt
> checksum and (b) an obviously incorrect tid.
>
> Signed-off-by: Darrick J. Wong <[email protected]>

Thanks, applied.

- Ted

2014-09-11 21:04:52

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 22/25] tests: test recovery from an external journal

On Mon, Sep 08, 2014 at 04:14:01PM -0700, Darrick J. Wong wrote:
> Add a couple of tests to verify that writing to and recovering from
> an external journal work properly.
>
> Signed-off-by: Darrick J. Wong <[email protected]>

Thanks, applied.

- Ted

2014-09-11 21:10:36

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 23/25] ext2fs: add readahead method to improve scanning

On Mon, Sep 08, 2014 at 04:14:08PM -0700, Darrick J. Wong wrote:
> Fr?m: Andreas Dilger <[email protected]>
>
> Add a readahead method for prefetching ranges of disk blocks. This is
> useful for inode table scanning, and other large contiguous ranges of
> blocks, and may also prove useful for random block prefetch, since it
> will allow reordering of the IO without waiting synchronously for the
> reads to complete.
>
> It is currently using the posix_fadvise(POSIX_FADV_WILLNEED)
> interface, as this proved most efficient during our testing.
>
> [[email protected]]
> Make the arguments to the readahead function take the same ULL values
> as the other IO functions, and return an appropriate error code when
> fadvise isn't available.
>
> Signed-off-by: Andreas Dilger <[email protected]>
> Signed-off-by: Darrick J. Wong <[email protected]>
> ---
> lib/ext2fs/ext2_io.h | 8 +++++++-
> lib/ext2fs/io_manager.c | 9 +++++++++
> lib/ext2fs/unix_io.c | 27 ++++++++++++++++++++++++---
> 3 files changed, 40 insertions(+), 4 deletions(-)

Could you also plumb through the new method in test_io.c? Because we
often use this to interposed between mke2fs or e2fsprogs and unix_io.c
for debugging purposes.

Thanks!

- Ted

2014-09-11 21:29:56

by Darrick J. Wong

[permalink] [raw]
Subject: [PATCH 23/25 v2] ext2fs: add readahead method to improve scanning

Sure thing. Here's the patch again, but with the test_io.c bits added.
---
From: Andreas Dilger <[email protected]>

Add a readahead method for prefetching ranges of disk blocks. This is
useful for inode table scanning, and other large contiguous ranges of
blocks, and may also prove useful for random block prefetch, since it
will allow reordering of the IO without waiting synchronously for the
reads to complete.

It is currently using the posix_fadvise(POSIX_FADV_WILLNEED)
interface, as this proved most efficient during our testing.

[[email protected]]
Make the arguments to the readahead function take the same ULL values
as the other IO functions, and return an appropriate error code when
fadvise isn't available.

v2: Plumb in test_io.c for cache readahead.

Signed-off-by: Andreas Dilger <[email protected]>
Signed-off-by: Darrick J. Wong <[email protected]>
---
lib/ext2fs/ext2_io.h | 8 +++++++-
lib/ext2fs/io_manager.c | 9 +++++++++
lib/ext2fs/test_io.c | 22 ++++++++++++++++++++++
lib/ext2fs/unix_io.c | 27 ++++++++++++++++++++++++---
4 files changed, 62 insertions(+), 4 deletions(-)

diff --git a/lib/ext2fs/ext2_io.h b/lib/ext2fs/ext2_io.h
index 1894fb8..4c5a5c5 100644
--- a/lib/ext2fs/ext2_io.h
+++ b/lib/ext2fs/ext2_io.h
@@ -90,7 +90,10 @@ struct struct_io_manager {
int count, const void *data);
errcode_t (*discard)(io_channel channel, unsigned long long block,
unsigned long long count);
- long reserved[16];
+ errcode_t (*cache_readahead)(io_channel channel,
+ unsigned long long block,
+ unsigned long long count);
+ long reserved[15];
};

#define IO_FLAG_RW 0x0001
@@ -124,6 +127,9 @@ extern errcode_t io_channel_discard(io_channel channel,
unsigned long long count);
extern errcode_t io_channel_alloc_buf(io_channel channel,
int count, void *ptr);
+extern errcode_t io_channel_cache_readahead(io_channel io,
+ unsigned long long block,
+ unsigned long long count);

/* unix_io.c */
extern io_manager unix_io_manager;
diff --git a/lib/ext2fs/io_manager.c b/lib/ext2fs/io_manager.c
index 34e4859..dc5888d 100644
--- a/lib/ext2fs/io_manager.c
+++ b/lib/ext2fs/io_manager.c
@@ -128,3 +128,12 @@ errcode_t io_channel_alloc_buf(io_channel io, int count, void *ptr)
else
return ext2fs_get_mem(size, ptr);
}
+
+errcode_t io_channel_cache_readahead(io_channel io, unsigned long long block,
+ unsigned long long count)
+{
+ if (!io->manager->cache_readahead)
+ return EXT2_ET_OP_NOT_SUPPORTED;
+
+ return io->manager->cache_readahead(io, block, count);
+}
diff --git a/lib/ext2fs/test_io.c b/lib/ext2fs/test_io.c
index 6f0d035..b03a939 100644
--- a/lib/ext2fs/test_io.c
+++ b/lib/ext2fs/test_io.c
@@ -85,6 +85,7 @@ void (*test_io_cb_write_byte)
#define TEST_FLAG_DUMP 0x10
#define TEST_FLAG_SET_OPTION 0x20
#define TEST_FLAG_DISCARD 0x40
+#define TEST_FLAG_READAHEAD 0x80

static void test_dump_block(io_channel channel,
struct test_private_data *data,
@@ -486,6 +487,26 @@ static errcode_t test_discard(io_channel channel, unsigned long long block,
return retval;
}

+static errcode_t test_cache_readahead(io_channel channel,
+ unsigned long long block,
+ unsigned long long count)
+{
+ struct test_private_data *data;
+ errcode_t retval = 0;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct test_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
+
+ if (data->real)
+ retval = io_channel_cache_readahead(data->real, block, count);
+ if (data->flags & TEST_FLAG_READAHEAD)
+ fprintf(data->outfile,
+ "Test_io: readahead(%llu, %llu) returned %s\n",
+ block, count, retval ? error_message(retval) : "OK");
+ return retval;
+}
+
static struct struct_io_manager struct_test_manager = {
.magic = EXT2_ET_MAGIC_IO_MANAGER,
.name = "Test I/O Manager",
@@ -501,6 +522,7 @@ static struct struct_io_manager struct_test_manager = {
.read_blk64 = test_read_blk64,
.write_blk64 = test_write_blk64,
.discard = test_discard,
+ .cache_readahead = test_cache_readahead,
};

io_manager test_io_manager = &struct_test_manager;
diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c
index eb39b28..189adce 100644
--- a/lib/ext2fs/unix_io.c
+++ b/lib/ext2fs/unix_io.c
@@ -15,6 +15,9 @@
* %End-Header%
*/

+#define _XOPEN_SOURCE 600
+#define _DARWIN_C_SOURCE
+#define _FILE_OFFSET_BITS 64
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#ifndef _GNU_SOURCE
@@ -35,6 +38,9 @@
#ifdef __linux__
#include <sys/utsname.h>
#endif
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
@@ -44,9 +50,6 @@
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
#if HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
@@ -830,6 +833,23 @@ static errcode_t unix_write_blk64(io_channel channel, unsigned long long block,
#endif /* NO_IO_CACHE */
}

+static errcode_t unix_cache_readahead(io_channel channel,
+ unsigned long long block,
+ unsigned long long count)
+{
+#ifdef POSIX_FADV_WILLNEED
+ struct unix_private_data *data;
+
+ data = (struct unix_private_data *)channel->private_data;
+ return posix_fadvise(data->dev,
+ (ext2_loff_t)block * channel->block_size,
+ (ext2_loff_t)count * channel->block_size,
+ POSIX_FADV_WILLNEED);
+#else
+ return EXT2_ET_OP_NOT_SUPPORTED;
+#endif
+}
+
static errcode_t unix_write_blk(io_channel channel, unsigned long block,
int count, const void *buf)
{
@@ -981,6 +1001,7 @@ static struct struct_io_manager struct_unix_manager = {
.read_blk64 = unix_read_blk64,
.write_blk64 = unix_write_blk64,
.discard = unix_discard,
+ .cache_readahead = unix_cache_readahead,
};

io_manager unix_io_manager = &struct_unix_manager;

2014-09-11 22:05:54

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 26/25] libext2fs: call get_alloc_block hook when allocating blocks

On Thu, Sep 11, 2014 at 12:41:53PM -0700, Darrick J. Wong wrote:
> If a libext2fs client has provided a get_alloc_block hook, we need to
> ensure that all code paths in the library use it to allocate blocks.

I noticed you didn't replace ext2fs_new_block[2] with
ext2fs_alloc_block[2] everywhere, because ext2fs_alloc_block[2]() does
extra work; specifically, it zeroes the newly allocated data block.
In the case of mkjournal.c, that would be disastrous from a
performance perspective, since we go to significant work to avoid
zeroing blocks one at a time.

But in other cases, when we create a symlink, expand a directory,
etc., we're still doing a double write (once in ext2fs_alloc_block,
and then a second time after ext2fs_alloc_block returns).

Hmm... I wonder if we can get away with changing ext2fs_new_block2(fs,
goal, bmap, ret_blk) so that if bmap is NULL, we change its behavior
so that (a) it tries to use the get_alloc_block() hook if it is present, and
(b) it will try to load the block bitmap if it is not already loaded,
instead of returning an error.

There are very few clients that are registering a get_alloc_block hook
today, and so it seems highly unlikely that this will cause problems.
What do you think?

- Ted

2014-09-11 22:07:04

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 27/25] tune2fs: always check disable_uninit_bg() return code

On Thu, Sep 11, 2014 at 12:43:33PM -0700, Darrick J. Wong wrote:
> Enhance disable_uninit_bg() to return error codes -- if something goes
> wrong, we want to flag the FS as needing a fsck and exit. Mr. Reardon
> discovered that tune2fs -O ^metadata_csum on a FS with a corrupt
> bitmap would leave the FS in a weird state.
>
> Signed-off-by: Darrick J. Wong <[email protected]>
> Reported-by: TR Reardon <[email protected]>

Thanks, applied.

- Ted

2014-09-11 22:09:53

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 28/25] e2fsck: ignore badblocks if it says badblocks inode is bad

On Thu, Sep 11, 2014 at 12:44:49PM -0700, Darrick J. Wong wrote:
> If the badblocks list says that the badblocks inode is bad, it's quite
> likely that badblocks is broken. Worse yet, if the root inode is in
> the same block as the badblocks inode (likely since they're adjacent),
> the filesystem becomes unfixable because pass3 notices the bad root
> inode and exits.
>
> So... if we encounter this case, just kill the badblocks inode.
>
> Signed-off-by: Darrick J. Wong <[email protected]>

Applied, thanks.

- Ted

2014-09-11 22:10:05

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 29/25] e2fsck: expand root dir if linking l+f fails

On Thu, Sep 11, 2014 at 12:48:04PM -0700, Darrick J. Wong wrote:
> If there isn't space in the root directory to add the lost+found
> entry, try expanding the root directory before failing the fsck.
>
> Signed-off-by: Darrick J. Wong <[email protected]>

Applied, thanks.

- Ted

2014-09-11 22:11:30

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 30/25] libext2fs: check ea value offset when loading

On Thu, Sep 11, 2014 at 01:17:44PM -0700, Darrick J. Wong wrote:
> When reading extended attributes, check e_value_offs to make sure that
> it starts in the value area and not the name area. The attached test
> case image will crash the kernel if it is mounted and you append more
> than 4096 bytes of data to /a, due to insufficient validation.
>
> Signed-off-by: Darrick J. Wong <[email protected]>

Applied, thanks.

- Ted

2014-09-11 22:33:52

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 00/25] e2fsprogs Summer 2014 patchbomb, part 5.2

... and I've pushed out the next branch with all but 23-26 applied.

Darrick, can you take a look and see if everything landed as you
expect?

23-25 is a new feature (pending comments on 23, and I remember wanting
to take a much closer look at 24 and 25 from a month or two ago), and
26 is pending some comments I had vis-a-vis ext2fs_new_block() vs
ext2fs_get_block(), so if you want to send out patchbomb part 6 with
what's left of part 5, that might be appropriate.

Thanks for all of your work on e2fsprogs!

- Ted

2014-09-11 22:34:51

by Darrick J. Wong

[permalink] [raw]
Subject: Re: [PATCH 26/25] libext2fs: call get_alloc_block hook when allocating blocks

On Thu, Sep 11, 2014 at 06:05:52PM -0400, Theodore Ts'o wrote:
> On Thu, Sep 11, 2014 at 12:41:53PM -0700, Darrick J. Wong wrote:
> > If a libext2fs client has provided a get_alloc_block hook, we need to
> > ensure that all code paths in the library use it to allocate blocks.
>
> I noticed you didn't replace ext2fs_new_block[2] with
> ext2fs_alloc_block[2] everywhere, because ext2fs_alloc_block[2]() does
> extra work; specifically, it zeroes the newly allocated data block.
> In the case of mkjournal.c, that would be disastrous from a
> performance perspective, since we go to significant work to avoid
> zeroing blocks one at a time.
>
> But in other cases, when we create a symlink, expand a directory,
> etc., we're still doing a double write (once in ext2fs_alloc_block,
> and then a second time after ext2fs_alloc_block returns).
>
> Hmm... I wonder if we can get away with changing ext2fs_new_block2(fs,
> goal, bmap, ret_blk) so that if bmap is NULL, we change its behavior
> so that (a) it tries to use the get_alloc_block() hook if it is present, and
> (b) it will try to load the block bitmap if it is not already loaded,
> instead of returning an error.

Quite probably. I tried to avoid API behavioral change, at least for the
inital patch, though I was thinking that a general cleanup was probably in
order.

> There are very few clients that are registering a get_alloc_block hook
> today, and so it seems highly unlikely that this will cause problems.
> What do you think?

e2fuzz found the usual "using the wrong bitmap" bug in mkjournal.c, and patch
#29 (which you just applied) makes e2fsck a client of expand_dir. So long as
e2fsck is never changed to use _mkdir() and _symlink() we can probably get away
with not bothering, but then we'll quietly introduce this corruption bug again
if e2fsck ever does start using them.

Also any other client who uses the alloc_block hook will be silently broken.
Less broken than now, but I don't like discarding a small fix because we don't
guess anyone will care if it stays broken.

--D

>
> - Ted
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

2014-09-11 22:34:57

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 21/25 v2] tests: test e2fsck recovery of corrupt descriptor blocks

On Thu, Sep 11, 2014 at 12:31:41PM -0700, Darrick J. Wong wrote:
> Test e2fsck' ability to deal with (a) corrupt descriptor block
> checksum; (b) obviously bad journal block tid; and (c) corrupt journal
> blocks. These should exercise the journal recovery infinite loop
> bugfix earlier in this patchset.
>
> This test also ensures that (with metadata_csum and journal_csum_v3)
> journal replay continues past a corrupt journal block.
>
> v2: Update j_corrupt_journal_block after a clarification of what
> revoke records actually do.
>
> Signed-off-by: Darrick J. Wong <[email protected]>

Oops, forgot to ack this earlier.

Thanks, applied.

- Ted

2014-09-11 22:50:27

by Darrick J. Wong

[permalink] [raw]
Subject: Re: [PATCH 00/25] e2fsprogs Summer 2014 patchbomb, part 5.2

On Thu, Sep 11, 2014 at 06:33:47PM -0400, Theodore Ts'o wrote:
> ... and I've pushed out the next branch with all but 23-26 applied.
>
> Darrick, can you take a look and see if everything landed as you
> expect?
>
> 23-25 is a new feature (pending comments on 23, and I remember wanting
> to take a much closer look at 24 and 25 from a month or two ago), and
> 26 is pending some comments I had vis-a-vis ext2fs_new_block() vs
> ext2fs_get_block(), so if you want to send out patchbomb part 6 with
> what's left of part 5, that might be appropriate.
>
> Thanks for all of your work on e2fsprogs!

Looks like most everything landed ok except for:

Yikes, make check explodes:

make[1]: Entering directory `/storage/home/djwong/cdev/work/e2fsprogs-csum/lib/ext2fs'
SUBST ../../lib/dirpaths.h
SUBST ext2_err.et
CC ../../debugfs/journal.c
In file included from ./kernel-jbd.h:23:0,
from ./jfs_user.h:6,
from ../../debugfs/journal.c:26:
./jfs_compat.h:33:1: error: unknown type name ‘__u64’
typedef __u64 u64;
^
./jfs_compat.h:39:1: error: unknown type name ‘__u32’
static inline __u32 jbd2_chksum(journal_t *j, __u32 crc, const void *address,
^
./jfs_compat.h:39:47: error: unknown type name ‘__u32’
static inline __u32 jbd2_chksum(journal_t *j, __u32 crc, const void *address,
^
./jfs_compat.h:77:2: error: unknown type name ‘__u8’
__u8 j_uuid[16];
^
./jfs_compat.h:81:2: error: unknown type name ‘__u32’
<continues on for 1000 more lines>

--D

>
> - Ted
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

2014-09-11 22:52:25

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 00/25] e2fsprogs Summer 2014 patchbomb, part 5.2

On Thu, Sep 11, 2014 at 03:50:22PM -0700, Darrick J. Wong wrote:
>
> Looks like most everything landed ok except for:
>
> Yikes, make check explodes:

Hmm, works for me. Could you make sure you've done a "make clean" and
also a "git clean"? In particular, make sure you don't have a
leftover file in debugfs/jfs_user.h....

- Ted

2014-09-11 23:08:04

by Darrick J. Wong

[permalink] [raw]
Subject: Re: [PATCH 00/25] e2fsprogs Summer 2014 patchbomb, part 5.2

On Thu, Sep 11, 2014 at 06:52:23PM -0400, Theodore Ts'o wrote:
> On Thu, Sep 11, 2014 at 03:50:22PM -0700, Darrick J. Wong wrote:
> >
> > Looks like most everything landed ok except for:
> >
> > Yikes, make check explodes:
>
> Hmm, works for me. Could you make sure you've done a "make clean" and
> also a "git clean"? In particular, make sure you don't have a
> leftover file in debugfs/jfs_user.h....

There aren't any stray jfs_user.h files, but rearranging DEBUGFS_CFLAGS seems
to fix it. On Ubuntu 14.04 it seems that the compile command for
lib/ext2fs/journal.o is:

gcc -I. -I../../lib -I../../lib -Wall -g -O2 -fstack-protector --param=ssp-buffer-size=4 -DHAVE_CONFIG_H -I./../../e2fsck -DDEBUGFS -c ../../debugfs/journal.c -o journal.o

...which means that it picks up lib/ext2fs/jfs_user.h instead of the one in
e2fsck/. The attached patch changes it to:

gcc -I./../../e2fsck -I. -I../../lib -I../../lib -Wall -g -O2 -fstack-protector --param=ssp-buffer-size=4 -DHAVE_CONFIG_H -DDEBUGFS -c ../../debugfs/journal.c -o journal.o

...which runs the compile ok.

--D

diff --git a/lib/ext2fs/Makefile.in b/lib/ext2fs/Makefile.in
index 597bed6..bc0dc8a 100644
--- a/lib/ext2fs/Makefile.in
+++ b/lib/ext2fs/Makefile.in
@@ -7,7 +7,7 @@ INSTALL = @INSTALL@
DEPEND_CFLAGS = -I$(top_srcdir)/debugfs -I$(srcdir)/../../e2fsck -DDEBUGFS
# This nastyness is needed because of jfs_user.h hackery; when we finally
# clean up this mess, we should be able to drop it
-DEBUGFS_CFLAGS = $(ALL_CFLAGS) -I$(srcdir)/../../e2fsck -DDEBUGFS
+DEBUGFS_CFLAGS = -I$(srcdir)/../../e2fsck $(ALL_CFLAGS) -DDEBUGFS

@MCONFIG@



2014-09-11 23:14:49

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 00/25] e2fsprogs Summer 2014 patchbomb, part 5.2

On Thu, Sep 11, 2014 at 04:07:58PM -0700, Darrick J. Wong wrote:
> On Thu, Sep 11, 2014 at 06:52:23PM -0400, Theodore Ts'o wrote:
> > On Thu, Sep 11, 2014 at 03:50:22PM -0700, Darrick J. Wong wrote:
> > >
> > > Looks like most everything landed ok except for:
> > >
> > > Yikes, make check explodes:
> >
> > Hmm, works for me. Could you make sure you've done a "make clean" and
> > also a "git clean"? In particular, make sure you don't have a
> > leftover file in debugfs/jfs_user.h....
>
> There aren't any stray jfs_user.h files, but rearranging DEBUGFS_CFLAGS seems
> to fix it. On Ubuntu 14.04 it seems that the compile command for
> lib/ext2fs/journal.o is:
>
> gcc -I. -I../../lib -I../../lib -Wall -g -O2 -fstack-protector --param=ssp-buffer-size=4 -DHAVE_CONFIG_H -I./../../e2fsck -DDEBUGFS -c ../../debugfs/journal.c -o journal.o

Ah, now I see why it works for me. I was using a VPATH build
directory, so it wasn't finding the one in lib/ext2fs/jfs_user.h. But
you're probably building in the source directory, so it was finding it
via "-I.".

Your patch looks good, thanks. I'll apply it and push out an update.

- Ted

2014-09-11 23:30:22

by Darrick J. Wong

[permalink] [raw]
Subject: Re: [PATCH 00/25] e2fsprogs Summer 2014 patchbomb, part 5.2

On Thu, Sep 11, 2014 at 07:14:46PM -0400, Theodore Ts'o wrote:
> On Thu, Sep 11, 2014 at 04:07:58PM -0700, Darrick J. Wong wrote:
> > On Thu, Sep 11, 2014 at 06:52:23PM -0400, Theodore Ts'o wrote:
> > > On Thu, Sep 11, 2014 at 03:50:22PM -0700, Darrick J. Wong wrote:
> > > >
> > > > Looks like most everything landed ok except for:
> > > >
> > > > Yikes, make check explodes:
> > >
> > > Hmm, works for me. Could you make sure you've done a "make clean" and
> > > also a "git clean"? In particular, make sure you don't have a
> > > leftover file in debugfs/jfs_user.h....
> >
> > There aren't any stray jfs_user.h files, but rearranging DEBUGFS_CFLAGS seems
> > to fix it. On Ubuntu 14.04 it seems that the compile command for
> > lib/ext2fs/journal.o is:
> >
> > gcc -I. -I../../lib -I../../lib -Wall -g -O2 -fstack-protector --param=ssp-buffer-size=4 -DHAVE_CONFIG_H -I./../../e2fsck -DDEBUGFS -c ../../debugfs/journal.c -o journal.o
>
> Ah, now I see why it works for me. I was using a VPATH build
> directory, so it wasn't finding the one in lib/ext2fs/jfs_user.h. But
> you're probably building in the source directory, so it was finding it
> via "-I.".
>
> Your patch looks good, thanks. I'll apply it and push out an update.

Cool, thanks! Yes, I do build out of the source dir.

Part 6 will have: e2fsck readahead; alloc_block cleanup; dumpe2fs output
cleanup; reporting of foreign FSes being fed to tune2fs/debugfs/e2fsck; uninit
block handling for fileio; 32->64bit resize2fs; fallocate; fuse2fs.

I'll give it all a spin on the usual x64/ppc64/arm64/i386 testbeds. Hopefully
it'll be out tomorrow.

--D

>
> - Ted
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

2014-09-12 16:43:47

by Darrick J. Wong

[permalink] [raw]
Subject: Re: [PATCH 09/25] misc: zero s_jnl_blocks when removing internal journal

[cc linux-ext4]

On Fri, Sep 12, 2014 at 10:09:55AM -0400, TR Reardon wrote:
> Note that this only works (zeroes out) when removing inode journal. Removing
> an existing journal_dev leaves s_jnl_blocks untouched. To be absolutely
> clean, perhaps it should be wiped in all removal cases?

s_jnl_blocks shouldn't be set if an external journal is in use.

(Unless it is somehow?)

--D

>
> --- Original Message ---
>
> From: "Theodore Ts'o" <[email protected]>
> Sent: September 11, 2014 12:44 PM
> To: "Darrick J. Wong" <[email protected]>
> Cc: [email protected], "TR Reardon" <[email protected]>
> Subject: Re: [PATCH 09/25] misc: zero s_jnl_blocks when removing internal journal
>
> On Mon, Sep 08, 2014 at 04:12:35PM -0700, Darrick J. Wong wrote:
> > When we're removing the internal journal (broken journal, turning it
> > off, or adding an external journal), zero s_jnl_blocks so that they
> > can't be picked up by accident later.
> >
> > Signed-off-by: Darrick J. Wong <[email protected]>
> > Cc: TR Reardon <[email protected]>
>
> Applied, thanks.
>
> - Ted
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

2014-09-12 17:35:54

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 26/25] libext2fs: call get_alloc_block hook when allocating blocks

On Thu, Sep 11, 2014 at 03:34:47PM -0700, Darrick J. Wong wrote:
> > Hmm... I wonder if we can get away with changing ext2fs_new_block2(fs,
> > goal, bmap, ret_blk) so that if bmap is NULL, we change its behavior
> > so that (a) it tries to use the get_alloc_block() hook if it is present, and
> > (b) it will try to load the block bitmap if it is not already loaded,
> > instead of returning an error.
>
> Quite probably. I tried to avoid API behavioral change, at least for the
> inital patch, though I was thinking that a general cleanup was probably in
> order.

It turns out that making a behavioral change could very well break
some callers --- including e2fsck (see e2fsck_get_alloc_block for an
example of wahy). What I'm currently thinking about is an API sort of
like this:

errcode_t ext2fs_alloc_blocks(ext2_filsys fs, blk64_t goal,
unsigned int *num_blocks,
char *block_buf, int flags, blk64_t *ret)

... which can be used to efficiently allocate up to *num_blocks blocks
at a time, much like the mballoc interface. I suspect that would be
useful for a number of different cases, including ext2fs_fallocate and
mk_hugefiles.c.

What I'm currently wondering about is whether it's worth the interface
complexity to have something like a "struct ext2fs_allocation_request"
structure, so we can potentially add more hints that a future
implementation might use, or whether that's not worth it.

What do folks think?

- Ted

2014-09-12 17:57:55

by Darrick J. Wong

[permalink] [raw]
Subject: Re: [PATCH 26/25] libext2fs: call get_alloc_block hook when allocating blocks

On Fri, Sep 12, 2014 at 01:35:51PM -0400, Theodore Ts'o wrote:
> On Thu, Sep 11, 2014 at 03:34:47PM -0700, Darrick J. Wong wrote:
> > > Hmm... I wonder if we can get away with changing ext2fs_new_block2(fs,
> > > goal, bmap, ret_blk) so that if bmap is NULL, we change its behavior
> > > so that (a) it tries to use the get_alloc_block() hook if it is present, and
> > > (b) it will try to load the block bitmap if it is not already loaded,
> > > instead of returning an error.
> >
> > Quite probably. I tried to avoid API behavioral change, at least for the
> > inital patch, though I was thinking that a general cleanup was probably in
> > order.
>
> It turns out that making a behavioral change could very well break
> some callers --- including e2fsck (see e2fsck_get_alloc_block for an
> example of wahy). What I'm currently thinking about is an API sort of
> like this:

I currently patched that the stupid way -- by temporarily swapping
fs->get_alloc_block with NULL in new_block2() while we call the function
pointer.

(Also by fixing e2fsck.)

> errcode_t ext2fs_alloc_blocks(ext2_filsys fs, blk64_t goal,
> unsigned int *num_blocks,
> char *block_buf, int flags, blk64_t *ret)
>
> ... which can be used to efficiently allocate up to *num_blocks blocks
> at a time, much like the mballoc interface. I suspect that would be
> useful for a number of different cases, including ext2fs_fallocate and
> mk_hugefiles.c.

Sounds familiar: http://marc.info/?l=linux-ext4&m=139898612510491&w=2

> What I'm currently wondering about is whether it's worth the interface
> complexity to have something like a "struct ext2fs_allocation_request"
> structure, so we can potentially add more hints that a future
> implementation might use, or whether that's not worth it.
>
> What do folks think?

I'm not sure changing a struct vs. changing whatever parameters we feed into
that function is all that much different. I guess you could get around
structure size changes by forcing callers to use a library allocator function.
But OTOH large allocations are probably rare.

--D

>
> - Ted
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

2014-09-12 19:06:25

by TR Reardon

[permalink] [raw]
Subject: RE: [PATCH 09/25] misc: zero s_jnl_blocks when removing internal journal

If the change from journal_inode to journal_dev is/was made prior to the recent change, the s_jnl_blocks will have whatever it last had. ?So if it started with journal_inode and then switched to journal_dev (again, prior to your fix) or no journal, the s_jnl_blocks will have the old journal_inode info, and adding/removing journal_dev does no clear it out. ?For a new fs with created only with journal_dev, there is no issue. ?I'm just arguing that *adding* journal_dev should also zero this out.

+Reardon


----------------------------------------
> Date: Fri, 12 Sep 2014 09:43:42 -0700
> From: [email protected]
> To: [email protected]
> CC: [email protected]
> Subject: Re: [PATCH 09/25] misc: zero s_jnl_blocks when removing internal journal
>
> [cc linux-ext4]
>
> On Fri, Sep 12, 2014 at 10:09:55AM -0400, TR Reardon wrote:
>> Note that this only works (zeroes out) when removing inode journal. Removing
>> an existing journal_dev leaves s_jnl_blocks untouched. To be absolutely
>> clean, perhaps it should be wiped in all removal cases?
>
> s_jnl_blocks shouldn't be set if an external journal is in use.
>
> (Unless it is somehow?)
>
> --D

-

2014-09-12 19:43:45

by Darrick J. Wong

[permalink] [raw]
Subject: Re: [PATCH 09/25] misc: zero s_jnl_blocks when removing internal journal

On Fri, Sep 12, 2014 at 03:06:23PM -0400, TR Reardon wrote:
> If the change from journal_inode to journal_dev is/was made prior to the
> recent change, the s_jnl_blocks will have whatever it last had. ?So if it
> started with journal_inode and then switched to journal_dev (again, prior to
> your fix) or no journal, the s_jnl_blocks will have the old journal_inode
> info, and adding/removing journal_dev does no clear it out. ?For a new fs
> with created only with journal_dev, there is no issue. ?I'm just arguing that
> *adding* journal_dev should also zero this out.

You would also want to zero out s_jnl_blocks if creating a journal on a mounted
FS, since there's no way to find the block map/ETB blocks; the best we can do
is hope the user runs e2fsck, which will fix it.

--D
>
> +Reardon
>
>
> ----------------------------------------
> > Date: Fri, 12 Sep 2014 09:43:42 -0700
> > From: [email protected]
> > To: [email protected]
> > CC: [email protected]
> > Subject: Re: [PATCH 09/25] misc: zero s_jnl_blocks when removing internal journal
> >
> > [cc linux-ext4]
> >
> > On Fri, Sep 12, 2014 at 10:09:55AM -0400, TR Reardon wrote:
> >> Note that this only works (zeroes out) when removing inode journal. Removing
> >> an existing journal_dev leaves s_jnl_blocks untouched. To be absolutely
> >> clean, perhaps it should be wiped in all removal cases?
> >
> > s_jnl_blocks shouldn't be set if an external journal is in use.
> >
> > (Unless it is somehow?)
> >
> > --D
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

2014-09-12 22:17:57

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH 26/25] libext2fs: call get_alloc_block hook when allocating blocks

On Fri, Sep 12, 2014 at 10:57:50AM -0700, Darrick J. Wong wrote:
>
> > errcode_t ext2fs_alloc_blocks(ext2_filsys fs, blk64_t goal,
> > unsigned int *num_blocks,
> > char *block_buf, int flags, blk64_t *ret)
> >
> > ... which can be used to efficiently allocate up to *num_blocks blocks
> > at a time, much like the mballoc interface. I suspect that would be
> > useful for a number of different cases, including ext2fs_fallocate and
> > mk_hugefiles.c.
>
> Sounds familiar: http://marc.info/?l=linux-ext4&m=139898612510491&w=2

Yes, but I'm thinking of something which is a superset of
ext2fs_alloc_block2(). That is, that it should call the
get_alloc_block hook (and also adding a possible get_alloc_blocks
hook), and that a flag would control whether the data blocks would be
zero'ed or not. (Indeed, I was thinking originally of calling it
ext2fs_alloc_block3.)

> > What I'm currently wondering about is whether it's worth the interface
> > complexity to have something like a "struct ext2fs_allocation_request"
> > structure, so we can potentially add more hints that a future
> > implementation might use, or whether that's not worth it.
> >
> > What do folks think?
>
> I'm not sure changing a struct vs. changing whatever parameters we feed into
> that function is all that much different. I guess you could get around
> structure size changes by forcing callers to use a library allocator function.
> But OTOH large allocations are probably rare.

We can also insulate against structure sizes by using padding fields,
but the ultimate question is how complicated we want to make this
interface. We know it will be used by mk_hugeblock and the fallocate
interface. In theory it could be use by your fuse driver to do
allocations more efficiently. There is the question of whether it's
worth it, although it has crossed my mind that this might be an
interesting place to start experimenting with an eventual replacement
of the buddy-bitmap implementation in mballoc with something that use
in-memory rbtrees, for example....

- Ted

2014-09-13 00:13:53

by Darrick J. Wong

[permalink] [raw]
Subject: Re: [PATCH 26/25] libext2fs: call get_alloc_block hook when allocating blocks

On Fri, Sep 12, 2014 at 06:17:53PM -0400, Theodore Ts'o wrote:
> On Fri, Sep 12, 2014 at 10:57:50AM -0700, Darrick J. Wong wrote:
> >
> > > errcode_t ext2fs_alloc_blocks(ext2_filsys fs, blk64_t goal,
> > > unsigned int *num_blocks,
> > > char *block_buf, int flags, blk64_t *ret)
> > >
> > > ... which can be used to efficiently allocate up to *num_blocks blocks
> > > at a time, much like the mballoc interface. I suspect that would be
> > > useful for a number of different cases, including ext2fs_fallocate and
> > > mk_hugefiles.c.
> >
> > Sounds familiar: http://marc.info/?l=linux-ext4&m=139898612510491&w=2
>
> Yes, but I'm thinking of something which is a superset of
> ext2fs_alloc_block2(). That is, that it should call the
> get_alloc_block hook (and also adding a possible get_alloc_blocks
> hook), and that a flag would control whether the data blocks would be
> zero'ed or not. (Indeed, I was thinking originally of calling it
> ext2fs_alloc_block3.)

Ah, I see. I _think_ the big difference between what you're talking about and
my new_range implementation is that new_range finds you a chunk of free blocks
that could be longer than what you asked for and lets you decide what to do
with them (like new_block does) whereas alloc_blocks3 (or alloc_range) would
find that chunk and call alloc_stats on just the piece you want.

I'd prefer the new_range feature since you can do some trivial preallocation
with it, but I'm open to an alloc_block3 too.

(I dislike the name alloc_block3, since we're really allocating a range.)

Anyway, we'll see what everyone thinks when the patch comes out in part 6.

--D

> > > What I'm currently wondering about is whether it's worth the interface
> > > complexity to have something like a "struct ext2fs_allocation_request"
> > > structure, so we can potentially add more hints that a future
> > > implementation might use, or whether that's not worth it.
> > >
> > > What do folks think?
> >
> > I'm not sure changing a struct vs. changing whatever parameters we feed into
> > that function is all that much different. I guess you could get around
> > structure size changes by forcing callers to use a library allocator function.
> > But OTOH large allocations are probably rare.
>
> We can also insulate against structure sizes by using padding fields,
> but the ultimate question is how complicated we want to make this
> interface. We know it will be used by mk_hugeblock and the fallocate
> interface. In theory it could be use by your fuse driver to do
> allocations more efficiently. There is the question of whether it's
> worth it, although it has crossed my mind that this might be an
> interesting place to start experimenting with an eventual replacement
> of the buddy-bitmap implementation in mballoc with something that use
> in-memory rbtrees, for example....
>
> - Ted
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html