All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1
@ 2014-08-16 23:45 Darrick J. Wong
  2014-08-16 23:45 ` [PATCH 01/27] e2fuzz: fix pwrite64/pwrite usage Darrick J. Wong
                   ` (27 more replies)
  0 siblings, 28 replies; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-16 23:45 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

Hi all,

This is the second 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 (that 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.

Patches 1-5 fix various problems: #1 brings e2fuzz' pwrite detection
in line with unix_io.c.  #2 fixes some gcc warnings about unused
variables and ignored return values.  #3 fixes endian handling
problems with the inode sanity scan.  #4 fixes other endian handling
errors in the library.  #5 teaches e2fsck pass2 to undo dirent
byteswap on the remainder of the dirent block before trying to salvage
a directory with a bad rec_len.

Patch 6 adds the ability to create inline data symlinks, as suggested
by Pu Hou.

Patches 7-9 bring e2fsck's journal recovery and revoke code up to date
with Linux 3.16.

Patch 10 fixes a longstanding bug -- e2fsck recovery goes into an
infinite loop when a non-revoked journal block fails its metadata
checksum test.  Instead of doing that, keep replaying the journal and
proceed to the e2fsck.

Patch 11 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 12-14 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.  #13 fixes a minor bug in the e2fsck journal
management code that could in theory lead to journal corruption.

Patches 15-23 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.

Patch 24 turns on block_validity for new filesystems, to guard against
accidental re-allocations of critical FS metadata.

Patch 25-27 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/15.  The patches have been tested against the 'make check' suite and
some amount of e2fuzz testing.

Comments and questions are, as always, welcome.

--D

^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH 01/27] e2fuzz: fix pwrite64/pwrite usage
  2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
@ 2014-08-16 23:45 ` Darrick J. Wong
  2014-08-24 23:56   ` Theodore Ts'o
  2014-08-16 23:46 ` [PATCH 02/27] misc: fix gcc warnings Darrick J. Wong
                   ` (26 subsequent siblings)
  27 siblings, 1 reply; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-16 23:45 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

Select pwrite64 or pwrite depending on what autoconf finds.  This
makes e2fuzz find a suitable pwrite variant regardless of platform.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 misc/e2fuzz.c |   18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)


diff --git a/misc/e2fuzz.c b/misc/e2fuzz.c
index 91aafe5..5794f97 100644
--- a/misc/e2fuzz.c
+++ b/misc/e2fuzz.c
@@ -32,15 +32,15 @@ static int metadata_only = 1;
 static unsigned long long user_corrupt_bytes = 0;
 static double user_corrupt_pct = 0.0;
 
-#ifndef HAVE_PWRITE
-ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
+#if !defined HAVE_PWRITE64 && !defined HAVE_PWRITE
+static ssize_t my_pwrite(int fd, const void *buf, size_t count, off_t offset)
 {
 	if (lseek(fd, offset, SEEK_SET) < 0)
 		return 0;
 
 	return write(fd, buf, count);
 }
-#endif /* HAVE_PWRITE */
+#endif /* !defined HAVE_PWRITE64 && !defined HAVE_PWRITE */
 
 int getseed(void)
 {
@@ -276,10 +276,22 @@ int process_fs(const char *fsname)
 			       off % fs->blocksize, off / fs->blocksize, c);
 		if (dryrun)
 			continue;
+#ifdef HAVE_PWRITE64
+		if (pwrite64(fd, &c, sizeof(c), off) != sizeof(c)) {
+			perror(fsname);
+			goto fail3;
+		}
+#elif HAVE_PWRITE
 		if (pwrite(fd, &c, sizeof(c), off) != sizeof(c)) {
 			perror(fsname);
 			goto fail3;
 		}
+#else
+		if (my_pwrite(fd, &c, sizeof(c), off) != sizeof(c)) {
+			perror(fsname);
+			goto fail3;
+		}
+#endif
 	}
 	close(fd);
 


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 02/27] misc: fix gcc warnings
  2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
  2014-08-16 23:45 ` [PATCH 01/27] e2fuzz: fix pwrite64/pwrite usage Darrick J. Wong
@ 2014-08-16 23:46 ` Darrick J. Wong
  2014-08-24 23:56   ` Theodore Ts'o
  2014-08-16 23:46 ` [PATCH 03/27] libext2fs: byteswap inode when performing the sanity scan Darrick J. Wong
                   ` (25 subsequent siblings)
  27 siblings, 1 reply; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-16 23:46 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

Fix a number of warnings about unneeded variables, uninitialized
variables, and ignored return values.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 debugfs/debugfs.c     |   11 +++--------
 debugfs/xattrs.c      |    3 ---
 debugfs/zap.c         |    1 -
 e2fsck/pass1.c        |    1 -
 e2fsck/pass2.c        |    1 -
 e2fsck/pass3.c        |    2 +-
 e2fsck/pass5.c        |    4 ----
 lib/ext2fs/ext_attr.c |   13 ++-----------
 lib/ext2fs/newdir.c   |    2 --
 misc/create_inode.c   |    5 +----
 misc/e2fuzz.c         |    3 ++-
 misc/tune2fs.c        |    4 +---
 12 files changed, 10 insertions(+), 40 deletions(-)


diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c
index 6366465..0d8e9e8 100644
--- a/debugfs/debugfs.c
+++ b/debugfs/debugfs.c
@@ -498,11 +498,6 @@ static void internal_dump_inode_extra(FILE *out,
 				      ext2_ino_t inode_num EXT2FS_ATTR((unused)),
 				      struct ext2_inode_large *inode)
 {
-	struct ext2_ext_attr_entry *entry;
-	__u32 *magic;
-	char *start, *end;
-	unsigned int storage_size;
-
 	fprintf(out, "Size of extra inode fields: %u\n", inode->i_extra_isize);
 	if (inode->i_extra_isize > EXT2_INODE_SIZE(current_fs->super) -
 			EXT2_GOOD_OLD_INODE_SIZE) {
@@ -1595,9 +1590,9 @@ void do_write(int argc, char *argv[])
 
 void do_mknod(int argc, char *argv[])
 {
-	unsigned long	mode, major, minor;
+	unsigned long	major, minor;
 	errcode_t 	retval;
-	int		filetype, nr;
+	int		nr;
 	struct stat	st;
 
 	if (check_fs_open(argv[0]))
@@ -1608,7 +1603,7 @@ void do_mknod(int argc, char *argv[])
 		return;
 	}
 
-	mode = minor = major = 0;
+	minor = major = 0;
 	switch (argv[2][0]) {
 		case 'p':
 			st.st_mode = S_IFIFO;
diff --git a/debugfs/xattrs.c b/debugfs/xattrs.c
index 1c19b2f..a80fd0b 100644
--- a/debugfs/xattrs.c
+++ b/debugfs/xattrs.c
@@ -288,9 +288,6 @@ void do_rm_xattr(int argc, char **argv)
 		goto out;
 
 	for (i = 2; i < argc; i++) {
-		size_t buflen;
-		char *buf;
-
 		err = ext2fs_xattr_remove(h, argv[i]);
 		if (err)
 			goto out;
diff --git a/debugfs/zap.c b/debugfs/zap.c
index 917bddf..0a1ae9b 100644
--- a/debugfs/zap.c
+++ b/debugfs/zap.c
@@ -174,7 +174,6 @@ void do_block_dump(int argc, char *argv[])
 	errcode_t	errcode;
 	blk64_t		block;
 	char		*file = NULL;
-	unsigned int	i, j;
 	int		c, err;
 
 	if (check_fs_open(argv[0]))
diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index a473bd7..4fc5311 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -2383,7 +2383,6 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx,
 		if (try_repairs && problem) {
 report_problem:
 			if (fix_problem(ctx, problem, pctx)) {
-fix_problem_now:
 				if (ctx->invalid_bitmaps) {
 					/*
 					 * If fsck knows the bitmaps are bad,
diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c
index fb98af5..23310f1 100644
--- a/e2fsck/pass2.c
+++ b/e2fsck/pass2.c
@@ -746,7 +746,6 @@ static errcode_t insert_dirent_tail(ext2_filsys fs, void *dirbuf)
 	struct ext2_dir_entry *d;
 	void *top;
 	struct ext2_dir_entry_tail *t;
-	unsigned int rec_len;
 
 	d = dirbuf;
 	top = EXT2_DIRENT_TAIL(dirbuf, fs->blocksize);
diff --git a/e2fsck/pass3.c b/e2fsck/pass3.c
index 63b1d70..9860cdf 100644
--- a/e2fsck/pass3.c
+++ b/e2fsck/pass3.c
@@ -831,7 +831,7 @@ errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
 	errcode_t	retval;
 	struct expand_dir_struct es;
 	struct ext2_inode	inode;
-	blk64_t		sz, before, after;
+	blk64_t		sz;
 
 	if (!(fs->flags & EXT2_FLAG_RW))
 		return EXT2_ET_RO_FILSYS;
diff --git a/e2fsck/pass5.c b/e2fsck/pass5.c
index bf3f733..86ac9fd 100644
--- a/e2fsck/pass5.c
+++ b/e2fsck/pass5.c
@@ -327,11 +327,7 @@ static void check_block_bitmaps(e2fsck_t ctx)
 	problem_t	problem, save_problem;
 	int		fixit, had_problem;
 	errcode_t	retval;
-	int	old_desc_blocks = 0;
-	int	count = 0;
-	int	cmp_block = 0;
 	int	redo_flag = 0;
-	blk64_t	super_blk, old_desc_blk, new_desc_blk;
 	char *actual_buf, *bitmap_buf;
 
 	actual_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize,
diff --git a/lib/ext2fs/ext_attr.c b/lib/ext2fs/ext_attr.c
index fc191f5..f9b9208 100644
--- a/lib/ext2fs/ext_attr.c
+++ b/lib/ext2fs/ext_attr.c
@@ -302,8 +302,7 @@ errcode_t ext2fs_free_ext_attr(ext2_filsys fs, ext2_ino_t ino,
 {
 	struct ext2_ext_attr_header *header;
 	void *block_buf = NULL;
-	dgrp_t grp;
-	blk64_t blk, goal;
+	blk64_t blk;
 	errcode_t err;
 	struct ext2_inode_large i;
 
@@ -621,7 +620,6 @@ static errcode_t read_xattrs_from_buffer(struct ext2_xattr_handle *handle,
 	struct ext2_xattr *x;
 	struct ext2_ext_attr_entry *entry;
 	const char *prefix;
-	void *ptr;
 	unsigned int remain, prefix_len;
 	errcode_t err;
 	unsigned int values_size = storage_size +
@@ -719,7 +717,6 @@ static void xattrs_free_keys(struct ext2_xattr_handle *h)
 
 errcode_t ext2fs_xattrs_read(struct ext2_xattr_handle *handle)
 {
-	struct ext2_xattr *attrs = NULL, *x;
 	struct ext2_inode_large *inode;
 	struct ext2_ext_attr_header *header;
 	__u32 ea_inode_magic;
@@ -822,7 +819,6 @@ errcode_t ext2fs_xattrs_iterate(struct ext2_xattr_handle *h,
 				void *data)
 {
 	struct ext2_xattr *x;
-	errcode_t err;
 	int ret;
 
 	EXT2_CHECK_MAGIC(h, EXT2_ET_MAGIC_EA_HANDLE);
@@ -869,11 +865,10 @@ errcode_t ext2fs_xattr_get(struct ext2_xattr_handle *h, const char *key,
 errcode_t ext2fs_xattr_inode_max_size(ext2_filsys fs, ext2_ino_t ino,
 				      size_t *size)
 {
-	struct ext2_ext_attr_header *header;
 	struct ext2_ext_attr_entry *entry;
 	struct ext2_inode_large *inode;
 	__u32 ea_inode_magic;
-	unsigned int storage_size, freesize, minoff;
+	unsigned int minoff;
 	void *start;
 	int i;
 	errcode_t err;
@@ -903,9 +898,6 @@ errcode_t ext2fs_xattr_inode_max_size(ext2_filsys fs, ext2_ino_t ino,
 	       inode->i_extra_isize, sizeof(__u32));
 	if (ea_inode_magic == EXT2_EXT_ATTR_MAGIC) {
 		/* has xattrs.  calculate the size */
-		storage_size = EXT2_INODE_SIZE(fs->super) -
-			EXT2_GOOD_OLD_INODE_SIZE - inode->i_extra_isize -
-			sizeof(__u32);
 		start= ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
 			inode->i_extra_isize + sizeof(__u32);
 		entry = start;
@@ -1003,7 +995,6 @@ errcode_t ext2fs_xattr_remove(struct ext2_xattr_handle *handle,
 			      const char *key)
 {
 	struct ext2_xattr *x;
-	errcode_t err;
 
 	EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE);
 	for (x = handle->attrs; x < handle->attrs + handle->length; x++) {
diff --git a/lib/ext2fs/newdir.c b/lib/ext2fs/newdir.c
index 506d609..f9bf8fc 100644
--- a/lib/ext2fs/newdir.c
+++ b/lib/ext2fs/newdir.c
@@ -102,9 +102,7 @@ errcode_t ext2fs_new_dir_inline_data(ext2_filsys fs, ext2_ino_t dir_ino,
 {
 	struct ext2_dir_entry 	*dir = NULL;
 	errcode_t		retval;
-	char			*buf;
 	int			rec_len;
-	int			filetype = 0;
 
 	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
 
diff --git a/misc/create_inode.c b/misc/create_inode.c
index 4d56719..7f57979 100644
--- a/misc/create_inode.c
+++ b/misc/create_inode.c
@@ -288,8 +288,6 @@ errcode_t do_symlink_internal(ext2_filsys fs, ext2_ino_t cwd, const char *name,
 	char			*cp;
 	ext2_ino_t		parent_ino;
 	errcode_t		retval;
-	struct ext2_inode	inode;
-	struct stat		st;
 
 	cp = strrchr(name, '/');
 	if (cp) {
@@ -324,9 +322,8 @@ errcode_t do_mkdir_internal(ext2_filsys fs, ext2_ino_t cwd, const char *name,
 			    struct stat *st, ext2_ino_t root)
 {
 	char			*cp;
-	ext2_ino_t		parent_ino, ino;
+	ext2_ino_t		parent_ino;
 	errcode_t		retval;
-	struct ext2_inode	inode;
 
 
 	cp = strrchr(name, '/');
diff --git a/misc/e2fuzz.c b/misc/e2fuzz.c
index 5794f97..c08e3df 100644
--- a/misc/e2fuzz.c
+++ b/misc/e2fuzz.c
@@ -52,7 +52,8 @@ int getseed(void)
 		perror("open");
 		exit(0);
 	}
-	read(fd, &r, sizeof(r));
+	if (read(fd, &r, sizeof(r)) != sizeof(r))
+		printf("Unable to read random seed!\n");
 	close(fd);
 	return r;
 }
diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index 75a2735..ee47c04 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -186,7 +186,6 @@ static __u32 clear_ok_features[3] = {
 static int get_journal_sb(ext2_filsys jfs, char buf[SUPERBLOCK_SIZE])
 {
 	int retval;
-	int start;
 	journal_superblock_t *jsb;
 
 	if (!(jfs->super->s_feature_incompat &
@@ -805,7 +804,7 @@ static void enable_uninit_bg(ext2_filsys fs)
 static errcode_t zero_empty_inodes(ext2_filsys fs)
 {
 	int length = EXT2_INODE_SIZE(fs->super);
-	struct ext2_inode *inode;
+	struct ext2_inode *inode = NULL;
 	ext2_inode_scan	scan;
 	errcode_t	retval;
 	ext2_ino_t	ino;
@@ -845,7 +844,6 @@ static void disable_uninit_bg(ext2_filsys fs, __u32 csum_feature_flag)
 	dgrp_t i;
 	errcode_t retval;
 	blk64_t b, c, d;
-	int has_super;
 
 	/* Load bitmaps to ensure that the uninit ones get written out */
 	fs->super->s_feature_ro_compat |= csum_feature_flag;


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 03/27] libext2fs: byteswap inode when performing the sanity scan
  2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
  2014-08-16 23:45 ` [PATCH 01/27] e2fuzz: fix pwrite64/pwrite usage Darrick J. Wong
  2014-08-16 23:46 ` [PATCH 02/27] misc: fix gcc warnings Darrick J. Wong
@ 2014-08-16 23:46 ` Darrick J. Wong
  2014-08-25  2:01   ` Theodore Ts'o
  2014-08-16 23:46 ` [PATCH 04/27] libext2fs: fix problems with LE<->BE conversions on BE platforms Darrick J. Wong
                   ` (24 subsequent siblings)
  27 siblings, 1 reply; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-16 23:46 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

On BE platforms, we need to swap the inode bytes after doing the
checksum verification but before looking at i_blocks.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 lib/ext2fs/inode.c |   22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)


diff --git a/lib/ext2fs/inode.c b/lib/ext2fs/inode.c
index 6c766af..4310b82 100644
--- a/lib/ext2fs/inode.c
+++ b/lib/ext2fs/inode.c
@@ -406,7 +406,7 @@ static void check_inode_block_sanity(ext2_inode_scan scan, blk64_t num_blocks)
 	void		*p;
 	struct ext2_inode_large *inode;
 	char		*block_status;
-	unsigned int	blk;
+	unsigned int	blk, bad_csum;
 
 	if (!(scan->scan_flags & EXT2_SF_WARN_GARBAGE_INODES))
 		return;
@@ -423,12 +423,26 @@ static void check_inode_block_sanity(ext2_inode_scan scan, blk64_t num_blocks)
 	memset(block_status, 0, scan->inode_buffer_blocks);
 	inodes_per_block = EXT2_INODES_PER_BLOCK(scan->fs->super);
 
+#ifdef WORDS_BIGENDIAN
+	if (ext2fs_get_mem(EXT2_INODE_SIZE(scan->fs->super), &inode))
+		return;
+#endif
+
 	while (inodes_to_scan > 0) {
 		blk = (p - (void *)scan->inode_buffer) / scan->fs->blocksize;
+		bad_csum = ext2fs_inode_csum_verify(scan->fs, ino, p) == 0;
+
+#ifdef WORDS_BIGENDIAN
+		ext2fs_swap_inode_full(scan->fs,
+			       (struct ext2_inode_large *) inode,
+			       (struct ext2_inode_large *) p,
+			       0, EXT2_INODE_SIZE(scan->fs->super));
+#else
 		inode = p;
+#endif
 
 		/* Is this inode insane? */
-		if (!ext2fs_inode_csum_verify(scan->fs, ino, inode)) {
+		if (bad_csum) {
 			checksum_failures++;
 			badness++;
 		} else if (extent_head_looks_insane(inode) ||
@@ -460,6 +474,10 @@ static void check_inode_block_sanity(ext2_inode_scan scan, blk64_t num_blocks)
 		p += scan->inode_size;
 		ino++;
 	};
+
+#ifdef WORDS_BIGENDIAN
+	ext2fs_free_mem(&inode);
+#endif
 }
 
 /*


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 04/27] libext2fs: fix problems with LE<->BE conversions on BE platforms
  2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
                   ` (2 preceding siblings ...)
  2014-08-16 23:46 ` [PATCH 03/27] libext2fs: byteswap inode when performing the sanity scan Darrick J. Wong
@ 2014-08-16 23:46 ` Darrick J. Wong
  2014-08-25  2:01   ` Theodore Ts'o
  2014-08-16 23:46 ` [PATCH 05/27] e2fsck: on BE, re-swap everything after a damaged dirent so salvage works correctly Darrick J. Wong
                   ` (23 subsequent siblings)
  27 siblings, 1 reply; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-16 23:46 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

Fix more problems that I found when testing on ppc64:

- Inode swap cut and paste error leads to immutable inodes being
  detected as inlinedata inodes, leading to e2fsck incorrectly barfing
  on i_block[] contents.

- Superblock csum/verify must be aware of the fs->super byte order
  when checking for metadata_csum feature flag.  (Hint: in _openfs(),
  fs->super is in LE order for the first csum verification)

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 lib/ext2fs/csum.c   |   26 ++++++++++++++++++--------
 lib/ext2fs/swapfs.c |    2 +-
 2 files changed, 19 insertions(+), 9 deletions(-)


diff --git a/lib/ext2fs/csum.c b/lib/ext2fs/csum.c
index d7dbca8..12f6fe9 100644
--- a/lib/ext2fs/csum.c
+++ b/lib/ext2fs/csum.c
@@ -81,12 +81,17 @@ static __u32 ext2fs_superblock_csum(ext2_filsys fs EXT2FS_ATTR((unused)),
 	return ext2fs_crc32c_le(~0, (unsigned char *)sb, offset);
 }
 
+/* NOTE: The input to this function MUST be in LE order */
 int ext2fs_superblock_csum_verify(ext2_filsys fs, struct ext2_super_block *sb)
 {
-	__u32 calculated;
+	__u32 flag, calculated;
 
-	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-					EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (fs->flags & EXT2_FLAG_SWAP_BYTES)
+		flag = EXT4_FEATURE_RO_COMPAT_METADATA_CSUM;
+	else
+		flag = ext2fs_cpu_to_le32(EXT4_FEATURE_RO_COMPAT_METADATA_CSUM);
+
+	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super, flag))
 		return 1;
 
 	calculated = ext2fs_superblock_csum(fs, sb);
@@ -94,13 +99,18 @@ int ext2fs_superblock_csum_verify(ext2_filsys fs, struct ext2_super_block *sb)
 	return ext2fs_le32_to_cpu(sb->s_checksum) == calculated;
 }
 
+/* NOTE: The input to this function MUST be in LE order */
 errcode_t ext2fs_superblock_csum_set(ext2_filsys fs,
 				     struct ext2_super_block *sb)
 {
-	__u32 crc;
+	__u32 flag, crc;
 
-	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-		EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+	if (fs->flags & EXT2_FLAG_SWAP_BYTES)
+		flag = EXT4_FEATURE_RO_COMPAT_METADATA_CSUM;
+	else
+		flag = ext2fs_cpu_to_le32(EXT4_FEATURE_RO_COMPAT_METADATA_CSUM);
+
+	if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super, flag))
 		return 0;
 
 	crc = ext2fs_superblock_csum(fs, sb);
@@ -756,8 +766,8 @@ __u16 ext2fs_group_desc_csum(ext2_filsys fs, dgrp_t group)
 #ifdef WORDS_BIGENDIAN
 		if (save_size > ext4_bg_size)
 			crc32 = ext2fs_crc32c_le(crc32,
-					   (char *)save_desc + ext4_bg_size,
-					   save_size - ext4_bg_size);
+				     (unsigned char *)save_desc + ext4_bg_size,
+	                             save_size - ext4_bg_size);
 #endif
 		crc = crc32 & 0xFFFF;
 		goto out;
diff --git a/lib/ext2fs/swapfs.c b/lib/ext2fs/swapfs.c
index e2aa41d..ee7a455 100644
--- a/lib/ext2fs/swapfs.c
+++ b/lib/ext2fs/swapfs.c
@@ -243,7 +243,7 @@ void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t,
 	t->i_flags = ext2fs_swab32(f->i_flags);
 	if (!hostorder && (t->i_flags & EXT4_EXTENTS_FL))
 		has_extents = 1;
-	if (!hostorder && (f->i_flags & EXT4_INLINE_DATA_FL))
+	if (!hostorder && (t->i_flags & EXT4_INLINE_DATA_FL))
 		has_inline_data = 1;
 	t->i_dir_acl = ext2fs_swab32(f->i_dir_acl);
 	/*


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 05/27] e2fsck: on BE, re-swap everything after a damaged dirent so salvage works correctly
  2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
                   ` (3 preceding siblings ...)
  2014-08-16 23:46 ` [PATCH 04/27] libext2fs: fix problems with LE<->BE conversions on BE platforms Darrick J. Wong
@ 2014-08-16 23:46 ` Darrick J. Wong
  2014-08-25  2:03   ` Theodore Ts'o
  2014-08-16 23:46 ` [PATCH 06/27] libext2fs: create inlinedata symlinks Darrick J. Wong
                   ` (22 subsequent siblings)
  27 siblings, 1 reply; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-16 23:46 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

On big-endian systems, if the dirent swap routine finds a rec_len that
it doesn't like, it continues processing the block as if rec_len == 8.
This means that the name field gets byte swapped, which means that
salvage will not detect the correct name length (unless the name has a
length that's an exact multiple of four bytes), and it'll discard the
entry (unnecessarily) and the rest of the dirent block.  Therefore,
swap the rest of the block back to disk order, run salvage, and
re-swap anything after the salvaged dirent.

The test case for this is f_inlinedata_repair if you run it on a BE
system.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 e2fsck/pass2.c |   38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)


diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c
index 23310f1..0b9c5c5 100644
--- a/e2fsck/pass2.c
+++ b/e2fsck/pass2.c
@@ -1058,9 +1058,47 @@ skip_checksum:
 			    ((ext2fs_dirent_name_len(dirent) + 8) > rec_len)) {
 				if (fix_problem(ctx, PR_2_DIR_CORRUPTED,
 						&cd->pctx)) {
+#ifdef WORDS_BIGENDIAN
+					/*
+					 * On big-endian systems, if the dirent
+					 * swap routine finds a rec_len that it
+					 * doesn't like, it continues
+					 * processing the block as if rec_len
+					 * == 8.  This means that the name
+					 * field gets byte swapped, which means
+					 * that salvage will not detect the
+					 * correct name length (unless the name
+					 * has a length that's an exact
+					 * multiple of four bytes), and it'll
+					 * discard the entry (unnecessarily)
+					 * and the rest of the dirent block.
+					 * Therefore, swap the rest of the
+					 * block back to disk order, run
+					 * salvage, and re-swap anything after
+					 * the salvaged dirent.
+					 */
+					int need_reswab = 0;
+					if (rec_len < 8 || rec_len % 4) {
+						need_reswab = 1;
+						ext2fs_dirent_swab_in2(fs,
+							((char *)dirent) + 8,
+							max_block_size - offset - 8,
+							0);
+					}
+#endif
 					salvage_directory(fs, dirent, prev,
 							  &offset,
 							  max_block_size);
+#ifdef WORDS_BIGENDIAN
+					if (need_reswab) {
+						(void) ext2fs_get_rec_len(fs,
+							dirent, &rec_len);
+						ext2fs_dirent_swab_in2(fs,
+							((char *)dirent) + offset + rec_len,
+							max_block_size - offset - rec_len,
+							0);
+					}
+#endif
 					dir_modified++;
 					continue;
 				} else


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 06/27] libext2fs: create inlinedata symlinks
  2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
                   ` (4 preceding siblings ...)
  2014-08-16 23:46 ` [PATCH 05/27] e2fsck: on BE, re-swap everything after a damaged dirent so salvage works correctly Darrick J. Wong
@ 2014-08-16 23:46 ` Darrick J. Wong
  2014-08-25  2:05   ` Theodore Ts'o
  2014-08-16 23:46 ` [PATCH 07/27] contrib: add script to help resync journal code with kernel Darrick J. Wong
                   ` (21 subsequent siblings)
  27 siblings, 1 reply; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-16 23:46 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4, Pu Hou

Add to ext2fs_symlink the ability to create inline data symlinks.

Suggested-by: Pu Hou <houpu.hp@alibaba-inc.com>
Cc: Pu Hou <houpu.hp@alibaba-inc.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 lib/ext2fs/symlink.c           |   34 ++++++++++++++++++++---
 tests/f_create_symlinks/expect |   36 ++++++++++++++++++++++++
 tests/f_create_symlinks/name   |    1 +
 tests/f_create_symlinks/script |   59 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 125 insertions(+), 5 deletions(-)
 create mode 100644 tests/f_create_symlinks/expect
 create mode 100644 tests/f_create_symlinks/name
 create mode 100644 tests/f_create_symlinks/script


diff --git a/lib/ext2fs/symlink.c b/lib/ext2fs/symlink.c
index ba8ed8e..f6eb6b6 100644
--- a/lib/ext2fs/symlink.c
+++ b/lib/ext2fs/symlink.c
@@ -35,7 +35,7 @@ errcode_t ext2fs_symlink(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t ino,
 	struct ext2_inode	inode;
 	ext2_ino_t		scratch_ino;
 	blk64_t			blk;
-	int			fastlink;
+	int			fastlink, inlinelink;
 	unsigned int		target_len;
 	char			*block_buf = 0;
 
@@ -77,15 +77,36 @@ errcode_t ext2fs_symlink(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t ino,
 	memset(&inode, 0, sizeof(struct ext2_inode));
 	inode.i_mode = LINUX_S_IFLNK | 0777;
 	inode.i_uid = inode.i_gid = 0;
-	ext2fs_iblk_set(fs, &inode, fastlink ? 0 : 1);
 	inode.i_links_count = 1;
 	ext2fs_inode_size_set(fs, &inode, target_len);
 	/* The time fields are set by ext2fs_write_new_inode() */
 
+	inlinelink = !fastlink &&
+		     (fs->super->s_feature_incompat &
+					EXT4_FEATURE_INCOMPAT_INLINE_DATA) &&
+		     (target_len < fs->blocksize);
 	if (fastlink) {
 		/* Fast symlinks, target stored in inode */
 		strcpy((char *)&inode.i_block, target);
+	} else if (inlinelink) {
+		/* Try inserting an inline data symlink */
+		inode.i_flags |= EXT4_INLINE_DATA_FL;
+		retval = ext2fs_write_new_inode(fs, ino, &inode);
+		if (retval)
+			goto cleanup;
+		retval = ext2fs_inline_data_set(fs, ino, &inode, target,
+						target_len);
+		if (retval) {
+			inode.i_flags &= ~EXT4_INLINE_DATA_FL;
+			inlinelink = 0;
+			goto need_block;
+		}
+		retval = ext2fs_read_inode(fs, ino, &inode);
+		if (retval)
+			goto cleanup;
 	} else {
+need_block:
+		ext2fs_iblk_set(fs, &inode, 1);
 		/* Slow symlinks, target stored in the first block */
 		memset(block_buf, 0, fs->blocksize);
 		strcpy(block_buf, target);
@@ -104,11 +125,14 @@ errcode_t ext2fs_symlink(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t ino,
 	 * number is assigned by write_new_inode, which means that the
 	 * operations using ino must come after it.
 	 */
-	retval = ext2fs_write_new_inode(fs, ino, &inode);
+	if (inlinelink)
+		retval = ext2fs_write_inode(fs, ino, &inode);
+	else
+		retval = ext2fs_write_new_inode(fs, ino, &inode);
 	if (retval)
 		goto cleanup;
 
-	if (!fastlink) {
+	if (!fastlink && !inlinelink) {
 		retval = ext2fs_bmap2(fs, ino, &inode, NULL, BMAP_SET, 0, NULL,
 				      &blk);
 		if (retval)
@@ -139,7 +163,7 @@ errcode_t ext2fs_symlink(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t ino,
 	/*
 	 * Update accounting....
 	 */
-	if (!fastlink)
+	if (!fastlink && !inlinelink)
 		ext2fs_block_alloc_stats2(fs, blk, +1);
 	ext2fs_inode_alloc_stats2(fs, ino, +1, 0);
 
diff --git a/tests/f_create_symlinks/expect b/tests/f_create_symlinks/expect
new file mode 100644
index 0000000..847e092
--- /dev/null
+++ b/tests/f_create_symlinks/expect
@@ -0,0 +1,36 @@
+mke2fs -q -F -o Linux -b 1024 -g 256 -O inline_data,extents -I 256 test.img 1024
+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), 441/1024 blocks
+Exit status is 0
+stat /l_30
+Inode: 12   Type: symlink    Mode:  0777   Flags: 0x0
+User:     0   Group:     0   Size: 31
+Links: 1   Blockcount: 0
+Fragment:  Address: 0    Number: 0    Size: 0
+Fast link dest: "/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+stat /l_70
+Inode: 13   Type: symlink    Mode:  0777   Flags: 0x10000000
+User:     0   Group:     0   Size: 71
+Links: 1   Blockcount: 0
+Fragment:  Address: 0    Number: 0    Size: 0
+Extended attributes:
+  system.data (11)
+Fast link dest: "/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+stat /l_500
+Inode: 14   Type: symlink    Mode:  0777   Flags: 0x80000
+User:     0   Group:     0   Size: 501
+Links: 1   Blockcount: 2
+Fragment:  Address: 0    Number: 0    Size: 0
+stat /l_1500
+/l_1500: File not found by ext2_lookup 
+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: 14/128 files (0.0% non-contiguous), 442/1024 blocks
+Exit status is 0
diff --git a/tests/f_create_symlinks/name b/tests/f_create_symlinks/name
new file mode 100644
index 0000000..0930e79
--- /dev/null
+++ b/tests/f_create_symlinks/name
@@ -0,0 +1 @@
+create fast, inlinedata, and regular symlinks
diff --git a/tests/f_create_symlinks/script b/tests/f_create_symlinks/script
new file mode 100644
index 0000000..c49825a
--- /dev/null
+++ b/tests/f_create_symlinks/script
@@ -0,0 +1,59 @@
+if test -x $DEBUGFS_EXE; then
+
+FSCK_OPT=-yf
+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
+
+dd if=/dev/zero of=$TMPFILE bs=1k count=512 > /dev/null 2>&1
+
+echo mke2fs -q -F -o Linux -b 1024 -g 256 -O inline_data,extents -I 256 test.img 1024 >> $OUT
+$MKE2FS -q -F -o Linux -b 1024 -g 256 -O inline_data,extents -I 256 $TMPFILE 1024 2>&1 |
+	sed -f $cmd_dir/filter.sed -e "s;$TMPFILE;test.img;" >> $OUT
+
+$FSCK $FSCK_OPT  -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
+
+for i in 30 70 500 1500; do
+	echo "symlink /l_$i /$(perl -e "print 'x' x $i;")"
+done | $DEBUGFS -w $TMPFILE >/dev/null 2>&1
+
+for i in 30 70 500 1500; do
+	echo "stat /l_$i" >> $OUT
+	$DEBUGFS -R "stat /l_$i" $TMPFILE 2>&1 | egrep '(File not found|^Inode|^Fast link dest|Blockcount:|^Extended attributes:|system.data|Size:)' >> $OUT
+done
+
+$FSCK $FSCK_OPT  -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 -a -x $DEBUGFS_EXE; then
+	echo "$test_name: $test_description: skipped"
+fi


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 07/27] contrib: add script to help resync journal code with kernel
  2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
                   ` (5 preceding siblings ...)
  2014-08-16 23:46 ` [PATCH 06/27] libext2fs: create inlinedata symlinks Darrick J. Wong
@ 2014-08-16 23:46 ` Darrick J. Wong
  2014-08-27  3:44   ` Theodore Ts'o
  2014-08-16 23:46 ` [PATCH 08/27] e2fsck: resync jbd2 recovery code from Linux 3.16 Darrick J. Wong
                   ` (20 subsequent siblings)
  27 siblings, 1 reply; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-16 23:46 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

Add a script that handles (most) of the code massaging necessary to resync
{recovery,revoke}.c from the Linux kernel into e2fsprogs.

Usage: jbd2-resync.sh linux/fs/jbd2/revoke.c e2fsprogs/e2fsck/revoke.c

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 contrib/jbd2-resync.sh |   19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
 create mode 100755 contrib/jbd2-resync.sh


diff --git a/contrib/jbd2-resync.sh b/contrib/jbd2-resync.sh
new file mode 100755
index 0000000..4133b63
--- /dev/null
+++ b/contrib/jbd2-resync.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+if [ -z "$1" -o -z "$2" ]; then
+	echo "Usage: $0 kernel-file e2fsprogs-file"
+	exit 0
+fi
+
+# Transform a few things to fit the compatibility things defined in jfs_user.h.
+# Use the ext2fs_ endian conversion functions because they truncate oversized
+# inputs (e.g. passing a u32 to cpu_to_be16()) like the kernel versions and
+# unlike the libc6 versions.
+exec sed -e 's/JBD_/JFS_/g' \
+	 -e 's/JBD2_/JFS_/g' \
+	 -e 's/jbd2_journal_/journal_/g' \
+	 -e 's/__be/__u/g' \
+	 -e 's/struct kmem_cache/lkmem_cache_t/g' \
+	 -e 's/cpu_to_be/ext2fs_cpu_to_be/g' \
+	 -e 's/be\([0-9][0-9]\)_to_cpu/ext2fs_be\1_to_cpu/g' \
+	 < "$1" > "$2"


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 08/27] e2fsck: resync jbd2 recovery code from Linux 3.16
  2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
                   ` (6 preceding siblings ...)
  2014-08-16 23:46 ` [PATCH 07/27] contrib: add script to help resync journal code with kernel Darrick J. Wong
@ 2014-08-16 23:46 ` Darrick J. Wong
  2014-08-27  3:44   ` Theodore Ts'o
  2014-08-16 23:46 ` [PATCH 09/27] e2fsck: resync jbd2 revoke " Darrick J. Wong
                   ` (19 subsequent siblings)
  27 siblings, 1 reply; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-16 23:46 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

Synchronize e2fsck's copy of recovery.c with the kernel's copy in
fs/jbd2.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 e2fsck/jfs_user.h       |    2 
 e2fsck/journal.c        |    8 +-
 e2fsck/recovery.c       |  209 +++++++++++++++++++++--------------------------
 lib/ext2fs/jfs_compat.h |   18 ++++
 4 files changed, 120 insertions(+), 117 deletions(-)


diff --git a/e2fsck/jfs_user.h b/e2fsck/jfs_user.h
index 3cccd3f..799c6da 100644
--- a/e2fsck/jfs_user.h
+++ b/e2fsck/jfs_user.h
@@ -123,7 +123,7 @@ _INLINE_ void do_cache_destroy(lkmem_cache_t *cache)
  */
 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);
-void sync_blockdev(kdev_t kdev);
+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);
diff --git a/e2fsck/journal.c b/e2fsck/journal.c
index 206685a..533b1d6 100644
--- a/e2fsck/journal.c
+++ b/e2fsck/journal.c
@@ -144,7 +144,7 @@ struct buffer_head *getblk(kdev_t kdev, blk64_t blocknr, int blocksize)
 	return bh;
 }
 
-void sync_blockdev(kdev_t kdev)
+int sync_blockdev(kdev_t kdev)
 {
 	io_channel	io;
 
@@ -153,7 +153,7 @@ void sync_blockdev(kdev_t kdev)
 	else
 		io = kdev->k_ctx->journal_io;
 
-	io_channel_flush(io);
+	return io_channel_flush(io) ? EIO : 0;
 }
 
 void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
@@ -632,6 +632,10 @@ 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))
+		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. */
diff --git a/e2fsck/recovery.c b/e2fsck/recovery.c
index 66d02b2..e4c7519 100644
--- a/e2fsck/recovery.c
+++ b/e2fsck/recovery.c
@@ -1,5 +1,5 @@
 /*
- * linux/fs/jbd/recovery.c
+ * linux/fs/jbd2/recovery.c
  *
  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
  *
@@ -14,14 +14,14 @@
  */
 
 #ifndef __KERNEL__
-#include "config.h"
 #include "jfs_user.h"
 #else
 #include <linux/time.h>
 #include <linux/fs.h>
-#include <linux/jbd.h>
+#include <linux/jbd2.h>
 #include <linux/errno.h>
-#include <linux/slab.h>
+#include <linux/crc32.h>
+#include <linux/blkdev.h>
 #endif
 
 /*
@@ -90,7 +90,7 @@ static int do_readahead(journal_t *journal, unsigned int start)
 		err = journal_bmap(journal, next, &blocknr);
 
 		if (err) {
-			printk (KERN_ERR "JBD: bad block at offset %u\n",
+			printk(KERN_ERR "JBD2: bad block at offset %u\n",
 				next);
 			goto failed;
 		}
@@ -139,14 +139,14 @@ static int jread(struct buffer_head **bhp, journal_t *journal,
 	*bhp = NULL;
 
 	if (offset >= journal->j_maxlen) {
-		printk(KERN_ERR "JBD: corrupted journal superblock\n");
+		printk(KERN_ERR "JBD2: corrupted journal superblock\n");
 		return -EIO;
 	}
 
 	err = journal_bmap(journal, offset, &blocknr);
 
 	if (err) {
-		printk (KERN_ERR "JBD: bad block at offset %u\n",
+		printk(KERN_ERR "JBD2: bad block at offset %u\n",
 			offset);
 		return err;
 	}
@@ -164,7 +164,7 @@ static int jread(struct buffer_head **bhp, journal_t *journal,
 	}
 
 	if (!buffer_uptodate(bh)) {
-		printk (KERN_ERR "JBD: Failed to read block at offset %u\n",
+		printk(KERN_ERR "JBD2: Failed to read block at offset %u\n",
 			offset);
 		brelse(bh);
 		return -EIO;
@@ -178,22 +178,20 @@ static int jbd2_descr_block_csum_verify(journal_t *j,
 					void *buf)
 {
 	struct journal_block_tail *tail;
-	__u32 provided, calculated;
+	__u32 provided;
+	__u32 calculated;
 
 	if (!JFS_HAS_INCOMPAT_FEATURE(j, JFS_FEATURE_INCOMPAT_CSUM_V2))
 		return 1;
 
-	tail = (struct journal_block_tail *)((char *)buf + j->j_blocksize -
+	tail = (struct journal_block_tail *)(buf + j->j_blocksize -
 			sizeof(struct journal_block_tail));
 	provided = tail->t_checksum;
 	tail->t_checksum = 0;
-	calculated = ext2fs_crc32c_le(~0, j->j_superblock->s_uuid,
-				      sizeof(j->j_superblock->s_uuid));
-	calculated = ext2fs_crc32c_le(calculated, buf, j->j_blocksize);
+	calculated = jbd2_chksum(j, j->j_csum_seed, buf, j->j_blocksize);
 	tail->t_checksum = provided;
 
-	provided = ext2fs_be32_to_cpu(provided);
-	return provided == calculated;
+	return provided == ext2fs_cpu_to_be32(calculated);
 }
 
 /*
@@ -217,10 +215,10 @@ static int count_tags(journal_t *journal, struct buffer_head *bh)
 
 		nr++;
 		tagp += tag_bytes;
-		if (!(tag->t_flags & cpu_to_be16(JFS_FLAG_SAME_UUID)))
+		if (!(tag->t_flags & ext2fs_cpu_to_be16(JFS_FLAG_SAME_UUID)))
 			tagp += 16;
 
-		if (tag->t_flags & cpu_to_be16(JFS_FLAG_LAST_TAG))
+		if (tag->t_flags & ext2fs_cpu_to_be16(JFS_FLAG_LAST_TAG))
 			break;
 	}
 
@@ -249,7 +247,7 @@ do {									\
  */
 int journal_recover(journal_t *journal)
 {
-	int			err;
+	int			err, err2;
 	journal_superblock_t *	sb;
 
 	struct recovery_info	info;
@@ -265,8 +263,8 @@ int journal_recover(journal_t *journal)
 
 	if (!sb->s_start) {
 		jbd_debug(1, "No recovery required, last transaction %d\n",
-			  be32_to_cpu(sb->s_sequence));
-		journal->j_transaction_sequence = be32_to_cpu(sb->s_sequence) + 1;
+			  ext2fs_be32_to_cpu(sb->s_sequence));
+		journal->j_transaction_sequence = ext2fs_be32_to_cpu(sb->s_sequence) + 1;
 		return 0;
 	}
 
@@ -276,10 +274,10 @@ int journal_recover(journal_t *journal)
 	if (!err)
 		err = do_one_pass(journal, &info, PASS_REPLAY);
 
-	jbd_debug(1, "JBD: recovery, exit status %d, "
+	jbd_debug(1, "JBD2: recovery, exit status %d, "
 		  "recovered transactions %u to %u\n",
 		  err, info.start_transaction, info.end_transaction);
-	jbd_debug(1, "JBD: Replayed %d and revoked %d/%d blocks\n",
+	jbd_debug(1, "JBD2: Replayed %d and revoked %d/%d blocks\n",
 		  info.nr_replays, info.nr_revoke_hits, info.nr_revokes);
 
 	/* Restart the log at the next transaction ID, thus invalidating
@@ -287,7 +285,15 @@ int journal_recover(journal_t *journal)
 	journal->j_transaction_sequence = ++info.end_transaction;
 
 	journal_clear_revoke(journal);
-	sync_blockdev(journal->j_fs_dev);
+	err2 = sync_blockdev(journal->j_fs_dev);
+	if (!err)
+		err = err2;
+	/* Make sure all replayed data is on permanent storage */
+	if (journal->j_flags & JFS_BARRIER) {
+		err2 = blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL);
+		if (!err)
+			err = err2;
+	}
 	return err;
 }
 
@@ -307,6 +313,7 @@ int journal_recover(journal_t *journal)
 int journal_skip_recovery(journal_t *journal)
 {
 	int			err;
+
 	struct recovery_info	info;
 
 	memset (&info, 0, sizeof(info));
@@ -314,17 +321,16 @@ int journal_skip_recovery(journal_t *journal)
 	err = do_one_pass(journal, &info, PASS_SCAN);
 
 	if (err) {
-		printk(KERN_ERR "JBD: error %d scanning journal\n", err);
+		printk(KERN_ERR "JBD2: error %d scanning journal\n", err);
 		++journal->j_transaction_sequence;
 	} else {
-#ifdef CONFIG_JBD_DEBUG
-		journal_superblock_t *sb = journal->j_superblock;
-
-		int dropped = info.end_transaction - be32_to_cpu(sb->s_sequence);
-#endif
+#ifdef CONFIG_JFS_DEBUG
+		int dropped = info.end_transaction - 
+			ext2fs_be32_to_cpu(journal->j_superblock->s_sequence);
 		jbd_debug(1,
-			  "JBD: ignoring %d transaction%s from the journal.\n",
+			  "JBD2: ignoring %d transaction%s from the journal.\n",
 			  dropped, (dropped == 1) ? "" : "s");
+#endif
 		journal->j_transaction_sequence = ++info.end_transaction;
 	}
 
@@ -334,9 +340,9 @@ int journal_skip_recovery(journal_t *journal)
 
 static inline unsigned long long read_tag_block(int tag_bytes, journal_block_tag_t *tag)
 {
-	unsigned long long block = be32_to_cpu(tag->t_blocknr);
-	if (tag_bytes > JBD_TAG_SIZE32)
-		block |= (__u64)be32_to_cpu(tag->t_blocknr_high) << 32;
+	unsigned long long block = ext2fs_be32_to_cpu(tag->t_blocknr);
+	if (tag_bytes > JFS_TAG_SIZE32)
+		block |= (u64)ext2fs_be32_to_cpu(tag->t_blocknr_high) << 32;
 	return block;
 }
 
@@ -345,31 +351,29 @@ static inline unsigned long long read_tag_block(int tag_bytes, journal_block_tag
  * descriptor block.
  */
 static int calc_chksums(journal_t *journal, struct buffer_head *bh,
-			unsigned long long *next_log_block, __u32 *crc32_sum)
+			unsigned long *next_log_block, __u32 *crc32_sum)
 {
 	int i, num_blks, err;
-	unsigned long long io_block;
+	unsigned long io_block;
 	struct buffer_head *obh;
 
 	num_blks = count_tags(journal, bh);
 	/* Calculate checksum of the descriptor block. */
-	*crc32_sum = ext2fs_crc32_be(*crc32_sum, (void *)bh->b_data,
-				     bh->b_size);
+	*crc32_sum = crc32_be(*crc32_sum, (void *)bh->b_data, bh->b_size);
 
 	for (i = 0; i < num_blks; i++) {
 		io_block = (*next_log_block)++;
 		wrap(journal, *next_log_block);
 		err = jread(&obh, journal, io_block);
 		if (err) {
-			printk(KERN_ERR "JBD: IO error %d recovering block "
-				"%llu in log\n", err, io_block);
+			printk(KERN_ERR "JBD2: IO error %d recovering block "
+				"%lu in log\n", err, io_block);
 			return 1;
 		} else {
-			*crc32_sum = ext2fs_crc32_be(*crc32_sum,
-						     (void *)obh->b_data,
-						     obh->b_size);
+			*crc32_sum = crc32_be(*crc32_sum, (void *)obh->b_data,
+				     obh->b_size);
 		}
-		brelse(obh);
+		put_bh(obh);
 	}
 	return 0;
 }
@@ -377,7 +381,8 @@ static int calc_chksums(journal_t *journal, struct buffer_head *bh,
 static int jbd2_commit_block_csum_verify(journal_t *j, void *buf)
 {
 	struct commit_header *h;
-	__u32 provided, calculated;
+	__u32 provided;
+	__u32 calculated;
 
 	if (!JFS_HAS_INCOMPAT_FEATURE(j, JFS_FEATURE_INCOMPAT_CSUM_V2))
 		return 1;
@@ -385,41 +390,33 @@ static int jbd2_commit_block_csum_verify(journal_t *j, void *buf)
 	h = buf;
 	provided = h->h_chksum[0];
 	h->h_chksum[0] = 0;
-	calculated = ext2fs_crc32c_le(~0, j->j_superblock->s_uuid,
-				      sizeof(j->j_superblock->s_uuid));
-	calculated = ext2fs_crc32c_le(calculated, buf, j->j_blocksize);
+	calculated = jbd2_chksum(j, j->j_csum_seed, buf, j->j_blocksize);
 	h->h_chksum[0] = provided;
 
-	provided = ext2fs_be32_to_cpu(provided);
-	return provided == calculated;
+	return provided == ext2fs_cpu_to_be32(calculated);
 }
 
 static int jbd2_block_tag_csum_verify(journal_t *j, journal_block_tag_t *tag,
 				      void *buf, __u32 sequence)
 {
-	__u32 calculated;
-	__u16 provided, crc;
+	__u32 csum32;
+	__u32 seq;
 
 	if (!JFS_HAS_INCOMPAT_FEATURE(j, JFS_FEATURE_INCOMPAT_CSUM_V2))
 		return 1;
 
-	sequence = ext2fs_cpu_to_be32(sequence);
-	calculated = ext2fs_crc32c_le(~0, j->j_superblock->s_uuid,
-				      sizeof(j->j_superblock->s_uuid));
-	calculated = ext2fs_crc32c_le(calculated, (__u8 *)&sequence,
-				      sizeof(sequence));
-	calculated = ext2fs_crc32c_le(calculated, buf, j->j_blocksize) & 0xffff;
-	crc = calculated & 0xFFFF;
-	provided = ext2fs_be16_to_cpu(tag->t_checksum);
+	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);
 
-	return provided == crc;
+	return tag->t_checksum == ext2fs_cpu_to_be16(csum32);
 }
 
 static int do_one_pass(journal_t *journal,
 			struct recovery_info *info, enum passtype pass)
 {
 	unsigned int		first_commit_ID, next_commit_ID;
-	unsigned long long	next_log_block;
+	unsigned long		next_log_block;
 	int			err, success = 0;
 	journal_superblock_t *	sb;
 	journal_header_t *	tmp;
@@ -437,8 +434,8 @@ static int do_one_pass(journal_t *journal,
 	 */
 
 	sb = journal->j_superblock;
-	next_commit_ID = be32_to_cpu(sb->s_sequence);
-	next_log_block = be32_to_cpu(sb->s_start);
+	next_commit_ID = ext2fs_be32_to_cpu(sb->s_sequence);
+	next_log_block = ext2fs_be32_to_cpu(sb->s_start);
 
 	first_commit_ID = next_commit_ID;
 	if (pass == PASS_SCAN)
@@ -470,14 +467,14 @@ static int do_one_pass(journal_t *journal,
 			if (tid_geq(next_commit_ID, info->end_transaction))
 				break;
 
-		jbd_debug(2, "Scanning for sequence ID %u at %llu/%lu\n",
+		jbd_debug(2, "Scanning for sequence ID %u at %lu/%lu\n",
 			  next_commit_ID, next_log_block, journal->j_last);
 
 		/* Skip over each chunk of the transaction looking
 		 * either the next descriptor block or the final commit
 		 * record. */
 
-		jbd_debug(3, "JBD: checking block %llu\n", next_log_block);
+		jbd_debug(3, "JBD2: checking block %ld\n", next_log_block);
 		err = jread(&bh, journal, next_log_block);
 		if (err)
 			goto failed;
@@ -493,13 +490,13 @@ static int do_one_pass(journal_t *journal,
 
 		tmp = (journal_header_t *)bh->b_data;
 
-		if (tmp->h_magic != cpu_to_be32(JFS_MAGIC_NUMBER)) {
+		if (tmp->h_magic != ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER)) {
 			brelse(bh);
 			break;
 		}
 
-		blocktype = be32_to_cpu(tmp->h_blocktype);
-		sequence = be32_to_cpu(tmp->h_sequence);
+		blocktype = ext2fs_be32_to_cpu(tmp->h_blocktype);
+		sequence = ext2fs_be32_to_cpu(tmp->h_sequence);
 		jbd_debug(3, "Found magic %d, sequence %d\n",
 			  blocktype, sequence);
 
@@ -523,7 +520,6 @@ static int do_one_pass(journal_t *journal,
 			    !jbd2_descr_block_csum_verify(journal,
 							  bh->b_data)) {
 				err = -EIO;
-				brelse(bh);
 				goto failed;
 			}
 
@@ -539,15 +535,15 @@ static int do_one_pass(journal_t *journal,
 					if (calc_chksums(journal, bh,
 							&next_log_block,
 							&crc32_sum)) {
-						brelse(bh);
+						put_bh(bh);
 						break;
 					}
-					brelse(bh);
+					put_bh(bh);
 					continue;
 				}
 				next_log_block += count_tags(journal, bh);
 				wrap(journal, next_log_block);
-				brelse(bh);
+				put_bh(bh);
 				continue;
 			}
 
@@ -558,10 +554,10 @@ static int do_one_pass(journal_t *journal,
 			tagp = &bh->b_data[sizeof(journal_header_t)];
 			while ((tagp - bh->b_data + tag_bytes)
 			       <= journal->j_blocksize - descr_csum_size) {
-				unsigned long long io_block;
+				unsigned long io_block;
 
 				tag = (journal_block_tag_t *) tagp;
-				flags = be16_to_cpu(tag->t_flags);
+				flags = ext2fs_be16_to_cpu(tag->t_flags);
 
 				io_block = next_log_block++;
 				wrap(journal, next_log_block);
@@ -570,9 +566,9 @@ static int do_one_pass(journal_t *journal,
 					/* Recover what we can, but
 					 * report failure at the end. */
 					success = err;
-					printk (KERN_ERR
-						"JBD: IO error %d recovering "
-						"block %llu in log\n",
+					printk(KERN_ERR
+						"JBD2: IO error %d recovering "
+						"block %ld in log\n",
 						err, io_block);
 				} else {
 					unsigned long long blocknr;
@@ -595,12 +591,12 @@ static int do_one_pass(journal_t *journal,
 					/* Look for block corruption */
 					if (!jbd2_block_tag_csum_verify(
 						journal, tag, obh->b_data,
-						be32_to_cpu(tmp->h_sequence))) {
+						ext2fs_be32_to_cpu(tmp->h_sequence))) {
 						brelse(obh);
 						success = -EIO;
-						printk(KERN_ERR "JBD: Invalid "
+						printk(KERN_ERR "JBD2: Invalid "
 						       "checksum recovering "
-						       "block %lld in log\n",
+						       "block %llu in log\n",
 						       blocknr);
 						continue;
 					}
@@ -612,7 +608,7 @@ static int do_one_pass(journal_t *journal,
 							journal->j_blocksize);
 					if (nbh == NULL) {
 						printk(KERN_ERR
-						       "JBD: Out of memory "
+						       "JBD2: Out of memory "
 						       "during recovery.\n");
 						err = -ENOMEM;
 						brelse(bh);
@@ -624,10 +620,8 @@ static int do_one_pass(journal_t *journal,
 					memcpy(nbh->b_data, obh->b_data,
 							journal->j_blocksize);
 					if (flags & JFS_FLAG_ESCAPE) {
-						journal_header_t *header;
-
-						header = (journal_header_t *) &nbh->b_data[0];
-						header->h_magic = cpu_to_be32(JFS_MAGIC_NUMBER);
+						*((__u32 *)nbh->b_data) =
+						ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER);
 					}
 
 					BUFFER_TRACE(nbh, "marking dirty");
@@ -654,8 +648,6 @@ static int do_one_pass(journal_t *journal,
 			continue;
 
 		case JFS_COMMIT_BLOCK:
-			jbd_debug(3, "Commit block for #%u found\n",
-				  next_commit_ID);
 			/*     How to differentiate between interrupted commit
 			 *               and journal corruption ?
 			 *
@@ -698,12 +690,10 @@ static int do_one_pass(journal_t *journal,
 				struct commit_header *cbh =
 					(struct commit_header *)bh->b_data;
 				unsigned found_chksum =
-					be32_to_cpu(cbh->h_chksum[0]);
+					ext2fs_be32_to_cpu(cbh->h_chksum[0]);
 
 				chksum_err = chksum_seen = 0;
 
-				jbd_debug(3, "Checksums %x %x\n",
-					  crc32_sum, found_chksum);
 				if (info->end_transaction) {
 					journal->j_failed_commit =
 						info->end_transaction;
@@ -712,9 +702,9 @@ static int do_one_pass(journal_t *journal,
 				}
 
 				if (crc32_sum == found_chksum &&
-				    cbh->h_chksum_type == JBD2_CRC32_CHKSUM &&
+				    cbh->h_chksum_type == JFS_CRC32_CHKSUM &&
 				    cbh->h_chksum_size ==
-						JBD2_CRC32_CHKSUM_SIZE)
+						JFS_CRC32_CHKSUM_SIZE)
 				       chksum_seen = 1;
 				else if (!(cbh->h_chksum_type == 0 &&
 					     cbh->h_chksum_size == 0 &&
@@ -734,8 +724,7 @@ static int do_one_pass(journal_t *journal,
 
 				if (chksum_err) {
 					info->end_transaction = next_commit_ID;
-					jbd_debug(1, "Checksum_err %x %x\n",
-						  crc32_sum, found_chksum);
+
 					if (!JFS_HAS_INCOMPAT_FEATURE(journal,
 					   JFS_FEATURE_INCOMPAT_ASYNC_COMMIT)){
 						journal->j_failed_commit =
@@ -801,7 +790,7 @@ static int do_one_pass(journal_t *journal,
 		/* It's really bad news if different passes end up at
 		 * different places (but possible due to IO errors). */
 		if (info->end_transaction != next_commit_ID) {
-			printk (KERN_ERR "JBD: recovery pass %d ended at "
+			printk(KERN_ERR "JBD2: recovery pass %d ended at "
 				"transaction %u, expected %u\n",
 				pass, next_commit_ID, info->end_transaction);
 			if (!success)
@@ -819,22 +808,20 @@ static int jbd2_revoke_block_csum_verify(journal_t *j,
 					 void *buf)
 {
 	struct journal_revoke_tail *tail;
-	__u32 provided, calculated;
+	__u32 provided;
+	__u32 calculated;
 
 	if (!JFS_HAS_INCOMPAT_FEATURE(j, JFS_FEATURE_INCOMPAT_CSUM_V2))
 		return 1;
 
-	tail = (struct journal_revoke_tail *)((char *)buf + j->j_blocksize -
+	tail = (struct journal_revoke_tail *)(buf + j->j_blocksize -
 			sizeof(struct journal_revoke_tail));
 	provided = tail->r_checksum;
 	tail->r_checksum = 0;
-	calculated = ext2fs_crc32c_le(~0, j->j_superblock->s_uuid,
-				      sizeof(j->j_superblock->s_uuid));
-	calculated = ext2fs_crc32c_le(calculated, buf, j->j_blocksize);
+	calculated = jbd2_chksum(j, j->j_csum_seed, buf, j->j_blocksize);
 	tail->r_checksum = provided;
 
-	provided = ext2fs_be32_to_cpu(provided);
-	return provided == calculated;
+	return provided == ext2fs_cpu_to_be32(calculated);
 }
 
 /* Scan a revoke record, marking all blocks mentioned as revoked. */
@@ -848,7 +835,7 @@ static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
 
 	header = (journal_revoke_header_t *) bh->b_data;
 	offset = sizeof(journal_revoke_header_t);
-	max = be32_to_cpu(header->r_count);
+	max = ext2fs_be32_to_cpu(header->r_count);
 
 	if (!jbd2_revoke_block_csum_verify(journal, header))
 		return -EINVAL;
@@ -856,20 +843,14 @@ static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
 	if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_64BIT))
 		record_len = 8;
 
-	while (offset < max) {
+	while (offset + record_len <= max) {
 		unsigned long long blocknr;
 		int err;
 
-		if (record_len == 4) {
-			__be32 b;
-			memcpy(&b, bh->b_data + offset, sizeof(__be32));
-			blocknr = ext2fs_be32_to_cpu(b);
-		} else {
-			__be64 b;
-			memcpy(&b, bh->b_data + offset, sizeof(__be64));
-			blocknr = ext2fs_be64_to_cpu(b);
-		}
-
+		if (record_len == 4)
+			blocknr = ext2fs_be32_to_cpu(* ((__u32 *) (bh->b_data+offset)));
+		else
+			blocknr = ext2fs_be64_to_cpu(* ((__u64 *) (bh->b_data+offset)));
 		offset += record_len;
 		err = journal_set_revoke(journal, blocknr, sequence);
 		if (err)
diff --git a/lib/ext2fs/jfs_compat.h b/lib/ext2fs/jfs_compat.h
index 7947ef5..2638c31 100644
--- a/lib/ext2fs/jfs_compat.h
+++ b/lib/ext2fs/jfs_compat.h
@@ -7,6 +7,7 @@
 #ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
+#include <arpa/inet.h>
 
 #define printk printf
 #define KERN_ERR ""
@@ -26,6 +27,22 @@ typedef struct journal_s journal_t;
 struct buffer_head;
 struct inode;
 
+#define GFP_KERNEL	0
+#define JFS_TAG_SIZE32	JBD_TAG_SIZE32
+#define JFS_BARRIER	0
+typedef __u64 u64;
+#define JFS_CRC32_CHKSUM	JBD2_CRC32_CHKSUM
+#define JFS_CRC32_CHKSUM_SIZE	JBD2_CRC32_CHKSUM_SIZE
+#define put_bh(x)	brelse(x)
+#define be64_to_cpu(x)	ext2fs_be64_to_cpu(x)
+
+static inline __u32 jbd2_chksum(journal_t *j, __u32 crc, const void *address,
+			unsigned int length)
+{
+	return ext2fs_crc32c_le(crc, address, length);
+}
+#define crc32_be(x, y, z)	ext2fs_crc32_be((x), (y), (z))
+
 struct journal_s
 {
 	unsigned long		j_flags;
@@ -48,6 +65,7 @@ struct journal_s
 	__u8			j_uuid[16];
 	struct jbd_revoke_table_s *j_revoke;
 	tid_t			j_failed_commit;
+	__u32			j_csum_seed;
 };
 
 #define J_ASSERT(assert)						\


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 09/27] e2fsck: resync jbd2 revoke code from Linux 3.16
  2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
                   ` (7 preceding siblings ...)
  2014-08-16 23:46 ` [PATCH 08/27] e2fsck: resync jbd2 recovery code from Linux 3.16 Darrick J. Wong
@ 2014-08-16 23:46 ` Darrick J. Wong
  2014-08-27  3:44   ` Theodore Ts'o
  2014-08-16 23:46 ` [PATCH 10/27] e2fsck: fix infinite loop when recovering corrupt journal blocks Darrick J. Wong
                   ` (18 subsequent siblings)
  27 siblings, 1 reply; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-16 23:46 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

Synchronize e2fsck's copy of revoke.c with the kernel's copy in
fs/jbd2.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 e2fsck/jfs_user.h       |    2 
 e2fsck/revoke.c         |  477 ++++++++++++++++++++++++++++++-----------------
 lib/ext2fs/jfs_compat.h |   15 +
 lib/ext2fs/kernel-jbd.h |    5 
 4 files changed, 320 insertions(+), 179 deletions(-)


diff --git a/e2fsck/jfs_user.h b/e2fsck/jfs_user.h
index 799c6da..9405e47 100644
--- a/e2fsck/jfs_user.h
+++ b/e2fsck/jfs_user.h
@@ -54,7 +54,7 @@ typedef struct {
 
 #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,d) do_cache_create(len)
+#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)
diff --git a/e2fsck/revoke.c b/e2fsck/revoke.c
index 38c265e..383164e 100644
--- a/e2fsck/revoke.c
+++ b/e2fsck/revoke.c
@@ -1,5 +1,5 @@
 /*
- * linux/fs/revoke.c
+ * linux/fs/jbd2/revoke.c
  *
  * Written by Stephen C. Tweedie <sct@redhat.com>, 2000
  *
@@ -47,6 +47,10 @@
  *   overwriting the new data.  We don't even need to clear the revoke
  *   bit here.
  *
+ * We cache revoke status of a buffer in the current transaction in b_states
+ * bits.  As the name says, revokevalid flag indicates that the cached revoke
+ * status of a buffer is valid and we can rely on the cached status.
+ *
  * Revoke information on buffers is a tri-state value:
  *
  * RevokeValid clear:	no cached revoke status, need to look it up
@@ -55,40 +59,58 @@
  *			need do nothing.
  * RevokeValid set, Revoked set:
  *			buffer has been revoked.
+ *
+ * Locking rules:
+ * We keep two hash tables of revoke records. One hashtable belongs to the
+ * running transaction (is pointed to by journal->j_revoke), the other one
+ * belongs to the committing transaction. Accesses to the second hash table
+ * happen only from the kjournald and no other thread touches this table.  Also
+ * journal_switch_revoke_table() which switches which hashtable belongs to the
+ * running and which to the committing transaction is called only from
+ * kjournald. Therefore we need no locks when accessing the hashtable belonging
+ * to the committing transaction.
+ *
+ * All users operating on the hash table belonging to the running transaction
+ * have a handle to the transaction. Therefore they are safe from kjournald
+ * switching hash tables under them. For operations on the lists of entries in
+ * the hash table j_revoke_lock is used.
+ *
+ * Finally, also replay code uses the hash tables but at this moment no one else
+ * can touch them (filesystem isn't mounted yet) and hence no locking is
+ * needed.
  */
 
 #ifndef __KERNEL__
-#include "config.h"
 #include "jfs_user.h"
 #else
-#include <linux/sched.h>
+#include <linux/time.h>
 #include <linux/fs.h>
-#include <linux/jbd.h>
+#include <linux/jbd2.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
-#include <linux/locks.h>
 #include <linux/list.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
+#include <linux/bio.h>
+#include <linux/log2.h>
 #endif
 
-static lkmem_cache_t *revoke_record_cache;
-static lkmem_cache_t *revoke_table_cache;
+static lkmem_cache_t *jbd2_revoke_record_cache;
+static lkmem_cache_t *jbd2_revoke_table_cache;
 
 /* Each revoke record represents one single revoked block.  During
    journal replay, this involves recording the transaction ID of the
    last transaction to revoke this block. */
 
-struct jbd_revoke_record_s
+struct jbd2_revoke_record_s
 {
 	struct list_head  hash;
 	tid_t		  sequence;	/* Used for recovery only */
-	unsigned long	  blocknr;
+	unsigned long long	  blocknr;
 };
 
 
 /* The revoke table is just a simple hash table of revoke records. */
-struct jbd_revoke_table_s
+struct jbd2_revoke_table_s
 {
 	/* It is conceivable that we might want a larger hash table
 	 * for recovery.  Must be a power of two. */
@@ -100,159 +122,187 @@ struct jbd_revoke_table_s
 
 #ifdef __KERNEL__
 static void write_one_revoke_record(journal_t *, transaction_t *,
-				    struct journal_head **, int *,
-				    struct jbd_revoke_record_s *);
-static void flush_descriptor(journal_t *, struct journal_head *, int);
+				    struct list_head *,
+				    struct buffer_head **, int *,
+				    struct jbd2_revoke_record_s *, int);
+static void flush_descriptor(journal_t *, struct buffer_head *, int, int);
 #endif
 
 /* Utility functions to maintain the revoke table */
 
 /* Borrowed from buffer.c: this is a tried and tested block hash function */
-static inline int hash(journal_t *journal, unsigned long block)
+static inline int hash(journal_t *journal, unsigned long long block)
 {
-	struct jbd_revoke_table_s *table = journal->j_revoke;
+	struct jbd2_revoke_table_s *table = journal->j_revoke;
 	int hash_shift = table->hash_shift;
+	int hash = (int)block ^ (int)((block >> 31) >> 1);
 
-	return ((block << (hash_shift - 6)) ^
-		(block >> 13) ^
-		(block << (hash_shift - 12))) & (table->hash_size - 1);
+	return ((hash << (hash_shift - 6)) ^
+		(hash >> 13) ^
+		(hash << (hash_shift - 12))) & (table->hash_size - 1);
 }
 
-static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
+static int insert_revoke_hash(journal_t *journal, unsigned long long blocknr,
 			      tid_t seq)
 {
 	struct list_head *hash_list;
-	struct jbd_revoke_record_s *record;
+	struct jbd2_revoke_record_s *record;
 
-#ifdef __KERNEL__
 repeat:
-#endif
-	record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
+	record = kmem_cache_alloc(jbd2_revoke_record_cache, GFP_NOFS);
 	if (!record)
 		goto oom;
 
 	record->sequence = seq;
 	record->blocknr = blocknr;
 	hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
+	spin_lock(&journal->j_revoke_lock);
 	list_add(&record->hash, hash_list);
+	spin_unlock(&journal->j_revoke_lock);
 	return 0;
 
 oom:
-#ifdef __KERNEL__
 	if (!journal_oom_retry)
 		return -ENOMEM;
-	jbd_debug(1, "ENOMEM in " __FUNCTION__ ", retrying.\n");
-	current->policy |= SCHED_YIELD;
-	schedule();
+	jbd_debug(1, "ENOMEM in %s, retrying\n", __func__);
+	yield();
 	goto repeat;
-#else
-	return -ENOMEM;
-#endif
 }
 
 /* Find a revoke record in the journal's hash table. */
 
-static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
-						      unsigned long blocknr)
+static struct jbd2_revoke_record_s *find_revoke_record(journal_t *journal,
+						      unsigned long long blocknr)
 {
 	struct list_head *hash_list;
-	struct jbd_revoke_record_s *record;
+	struct jbd2_revoke_record_s *record;
 
 	hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
 
-	record = (struct jbd_revoke_record_s *) hash_list->next;
+	spin_lock(&journal->j_revoke_lock);
+	record = (struct jbd2_revoke_record_s *) hash_list->next;
 	while (&(record->hash) != hash_list) {
-		if (record->blocknr == blocknr)
+		if (record->blocknr == blocknr) {
+			spin_unlock(&journal->j_revoke_lock);
 			return record;
-		record = (struct jbd_revoke_record_s *) record->hash.next;
+		}
+		record = (struct jbd2_revoke_record_s *) record->hash.next;
 	}
+	spin_unlock(&journal->j_revoke_lock);
 	return NULL;
 }
 
-int __init journal_init_revoke_caches(void)
+void journal_destroy_revoke_caches(void)
 {
-	revoke_record_cache = kmem_cache_create("revoke_record",
-					   sizeof(struct jbd_revoke_record_s),
-					   0, SLAB_HWCACHE_ALIGN, NULL, NULL);
-	if (revoke_record_cache == 0)
-		return -ENOMEM;
-
-	revoke_table_cache = kmem_cache_create("revoke_table",
-					   sizeof(struct jbd_revoke_table_s),
-					   0, 0, NULL, NULL);
-	if (revoke_table_cache == 0) {
-		kmem_cache_destroy(revoke_record_cache);
-		revoke_record_cache = NULL;
-		return -ENOMEM;
+	if (jbd2_revoke_record_cache) {
+		kmem_cache_destroy(jbd2_revoke_record_cache);
+		jbd2_revoke_record_cache = NULL;
+	}
+	if (jbd2_revoke_table_cache) {
+		kmem_cache_destroy(jbd2_revoke_table_cache);
+		jbd2_revoke_table_cache = NULL;
 	}
-	return 0;
 }
 
-void journal_destroy_revoke_caches(void)
+int __init journal_init_revoke_caches(void)
 {
-	kmem_cache_destroy(revoke_record_cache);
-	revoke_record_cache = 0;
-	kmem_cache_destroy(revoke_table_cache);
-	revoke_table_cache = 0;
+	J_ASSERT(!jbd2_revoke_record_cache);
+	J_ASSERT(!jbd2_revoke_table_cache);
+
+	jbd2_revoke_record_cache = KMEM_CACHE(jbd2_revoke_record_s,
+					SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY);
+	if (!jbd2_revoke_record_cache)
+		goto record_cache_failure;
+
+	jbd2_revoke_table_cache = KMEM_CACHE(jbd2_revoke_table_s,
+					     SLAB_TEMPORARY);
+	if (!jbd2_revoke_table_cache)
+		goto table_cache_failure;
+	return 0;
+table_cache_failure:
+	journal_destroy_revoke_caches();
+record_cache_failure:
+		return -ENOMEM;
 }
 
-/* Initialise the revoke table for a given journal to a given size. */
-
-int journal_init_revoke(journal_t *journal, int hash_size)
+static struct jbd2_revoke_table_s *journal_init_revoke_table(int hash_size)
 {
-	int shift, tmp;
+	int shift = 0;
+	int tmp = hash_size;
+	struct jbd2_revoke_table_s *table;
 
-	J_ASSERT (journal->j_revoke == NULL);
-
-	journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
-	if (!journal->j_revoke)
-		return -ENOMEM;
-
-	/* Check that the hash_size is a power of two */
-	J_ASSERT ((hash_size & (hash_size-1)) == 0);
-
-	journal->j_revoke->hash_size = hash_size;
+	table = kmem_cache_alloc(jbd2_revoke_table_cache, GFP_KERNEL);
+	if (!table)
+		goto out;
 
-	shift = 0;
-	tmp = hash_size;
 	while((tmp >>= 1UL) != 0UL)
 		shift++;
-	journal->j_revoke->hash_shift = shift;
 
-	journal->j_revoke->hash_table =
+	table->hash_size = hash_size;
+	table->hash_shift = shift;
+	table->hash_table =
 		kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL);
-	if (!journal->j_revoke->hash_table) {
-		kmem_cache_free(revoke_table_cache, journal->j_revoke);
-		journal->j_revoke = NULL;
-		return -ENOMEM;
+	if (!table->hash_table) {
+		kmem_cache_free(jbd2_revoke_table_cache, table);
+		table = NULL;
+		goto out;
 	}
 
 	for (tmp = 0; tmp < hash_size; tmp++)
-		INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
+		INIT_LIST_HEAD(&table->hash_table[tmp]);
 
-	return 0;
+out:
+	return table;
 }
 
-/* Destoy a journal's revoke table.  The table must already be empty! */
-
-void journal_destroy_revoke(journal_t *journal)
+static void journal_destroy_revoke_table(struct jbd2_revoke_table_s *table)
 {
-	struct jbd_revoke_table_s *table;
-	struct list_head *hash_list;
 	int i;
+	struct list_head *hash_list;
 
-	table = journal->j_revoke;
-	if (!table)
-		return;
-
-	for (i=0; i<table->hash_size; i++) {
+	for (i = 0; i < table->hash_size; i++) {
 		hash_list = &table->hash_table[i];
-		J_ASSERT (list_empty(hash_list));
+		J_ASSERT(list_empty(hash_list));
 	}
 
 	kfree(table->hash_table);
-	kmem_cache_free(revoke_table_cache, table);
+	kmem_cache_free(jbd2_revoke_table_cache, table);
+}
+
+/* Initialise the revoke table for a given journal to a given size. */
+int journal_init_revoke(journal_t *journal, int hash_size)
+{
+	J_ASSERT(journal->j_revoke_table[0] == NULL);
+	J_ASSERT(is_power_of_2(hash_size));
+
+	journal->j_revoke_table[0] = journal_init_revoke_table(hash_size);
+	if (!journal->j_revoke_table[0])
+		goto fail0;
+
+	journal->j_revoke_table[1] = journal_init_revoke_table(hash_size);
+	if (!journal->j_revoke_table[1])
+		goto fail1;
+
+	journal->j_revoke = journal->j_revoke_table[1];
+
+	spin_lock_init(&journal->j_revoke_lock);
+
+	return 0;
+
+fail1:
+	journal_destroy_revoke_table(journal->j_revoke_table[0]);
+fail0:
+	return -ENOMEM;
+}
+
+/* Destroy a journal's revoke table.  The table must already be empty! */
+void journal_destroy_revoke(journal_t *journal)
+{
 	journal->j_revoke = NULL;
+	if (journal->j_revoke_table[0])
+		journal_destroy_revoke_table(journal->j_revoke_table[0]);
+	if (journal->j_revoke_table[1])
+		journal_destroy_revoke_table(journal->j_revoke_table[1]);
 }
 
 
@@ -282,14 +332,15 @@ void journal_destroy_revoke(journal_t *journal)
  * by one.
  */
 
-int journal_revoke(handle_t *handle, unsigned long blocknr,
+int journal_revoke(handle_t *handle, unsigned long long blocknr,
 		   struct buffer_head *bh_in)
 {
 	struct buffer_head *bh = NULL;
 	journal_t *journal;
-	kdev_t dev;
+	struct block_device *bdev;
 	int err;
 
+	might_sleep();
 	if (bh_in)
 		BUFFER_TRACE(bh_in, "enter");
 
@@ -299,34 +350,32 @@ int journal_revoke(handle_t *handle, unsigned long blocknr,
 		return -EINVAL;
 	}
 
-	dev = journal->j_fs_dev;
+	bdev = journal->j_fs_dev;
 	bh = bh_in;
 
 	if (!bh) {
-		bh = get_hash_table(dev, blocknr, journal->j_blocksize);
+		bh = __find_get_block(bdev, blocknr, journal->j_blocksize);
 		if (bh)
 			BUFFER_TRACE(bh, "found on hash");
 	}
-#ifdef JBD_EXPENSIVE_CHECKING
+#ifdef JFS_EXPENSIVE_CHECKING
 	else {
 		struct buffer_head *bh2;
 
 		/* If there is a different buffer_head lying around in
 		 * memory anywhere... */
-		bh2 = get_hash_table(dev, blocknr, journal->j_blocksize);
+		bh2 = __find_get_block(bdev, blocknr, journal->j_blocksize);
 		if (bh2) {
 			/* ... and it has RevokeValid status... */
-			if ((bh2 != bh) &&
-			    test_bit(BH_RevokeValid, &bh2->b_state))
+			if (bh2 != bh && buffer_revokevalid(bh2))
 				/* ...then it better be revoked too,
 				 * since it's illegal to create a revoke
 				 * record against a buffer_head which is
 				 * not marked revoked --- that would
 				 * risk missing a subsequent revoke
 				 * cancel. */
-				J_ASSERT_BH(bh2, test_bit(BH_Revoked, &
-							  bh2->b_state));
-			__brelse(bh2);
+				J_ASSERT_BH(bh2, buffer_revoked(bh2));
+			put_bh(bh2);
 		}
 	}
 #endif
@@ -335,9 +384,14 @@ int journal_revoke(handle_t *handle, unsigned long blocknr,
            first having the revoke cancelled: it's illegal to free a
            block twice without allocating it in between! */
 	if (bh) {
-		J_ASSERT_BH(bh, !test_bit(BH_Revoked, &bh->b_state));
-		set_bit(BH_Revoked, &bh->b_state);
-		set_bit(BH_RevokeValid, &bh->b_state);
+		if (!J_EXPECT_BH(bh, !buffer_revoked(bh),
+				 "inconsistent data on disk")) {
+			if (!bh_in)
+				brelse(bh);
+			return -EIO;
+		}
+		set_buffer_revoked(bh);
+		set_buffer_revokevalid(bh);
 		if (bh_in) {
 			BUFFER_TRACE(bh_in, "call journal_forget");
 			journal_forget(handle, bh_in);
@@ -347,11 +401,9 @@ int journal_revoke(handle_t *handle, unsigned long blocknr,
 		}
 	}
 
-	lock_journal(journal);
-	jbd_debug(2, "insert revoke for block %lu, bh_in=%p\n", blocknr, bh_in);
+	jbd_debug(2, "insert revoke for block %llu, bh_in=%p\n",blocknr, bh_in);
 	err = insert_revoke_hash(journal, blocknr,
 				handle->h_transaction->t_tid);
-	unlock_journal(journal);
 	BUFFER_TRACE(bh_in, "exit");
 	return err;
 }
@@ -360,7 +412,7 @@ int journal_revoke(handle_t *handle, unsigned long blocknr,
  * Cancel an outstanding revoke.  For use only internally by the
  * journaling code (called from journal_get_write_access).
  *
- * We trust the BH_Revoked bit on the buffer if the buffer is already
+ * We trust buffer_revoked() on the buffer if the buffer is already
  * being journaled: if there is no revoke pending on the buffer, then we
  * don't do anything here.
  *
@@ -370,12 +422,10 @@ int journal_revoke(handle_t *handle, unsigned long blocknr,
  * the second time we would still have a pending revoke to cancel.  So,
  * do not trust the Revoked bit on buffers unless RevokeValid is also
  * set.
- *
- * The caller must have the journal locked.
  */
 int journal_cancel_revoke(handle_t *handle, struct journal_head *jh)
 {
-	struct jbd_revoke_record_s *record;
+	struct jbd2_revoke_record_s *record;
 	journal_t *journal = handle->h_transaction->t_journal;
 	int need_cancel;
 	int did_revoke = 0;	/* akpm: debug */
@@ -387,25 +437,27 @@ int journal_cancel_revoke(handle_t *handle, struct journal_head *jh)
 	 * only perform the full cancel if the revoke bit is set.  If
 	 * not, we can't trust the revoke bit, and we need to do the
 	 * full search for a revoke record. */
-	if (test_and_set_bit(BH_RevokeValid, &bh->b_state))
-		need_cancel = (test_and_clear_bit(BH_Revoked, &bh->b_state));
-	else {
+	if (test_set_buffer_revokevalid(bh)) {
+		need_cancel = test_clear_buffer_revoked(bh);
+	} else {
 		need_cancel = 1;
-		clear_bit(BH_Revoked, &bh->b_state);
+		clear_buffer_revoked(bh);
 	}
 
 	if (need_cancel) {
 		record = find_revoke_record(journal, bh->b_blocknr);
 		if (record) {
 			jbd_debug(4, "cancelled existing revoke on "
-				  "blocknr %lu\n", bh->b_blocknr);
+				  "blocknr %llu\n", (unsigned long long)bh->b_blocknr);
+			spin_lock(&journal->j_revoke_lock);
 			list_del(&record->hash);
-			kmem_cache_free(revoke_record_cache, record);
+			spin_unlock(&journal->j_revoke_lock);
+			kmem_cache_free(jbd2_revoke_record_cache, record);
 			did_revoke = 1;
 		}
 	}
 
-#ifdef JBD_EXPENSIVE_CHECKING
+#ifdef JFS_EXPENSIVE_CHECKING
 	/* There better not be one left behind by now! */
 	record = find_revoke_record(journal, bh->b_blocknr);
 	J_ASSERT_JH(jh, record == NULL);
@@ -415,56 +467,104 @@ int journal_cancel_revoke(handle_t *handle, struct journal_head *jh)
 	 * buffer_head?  If so, we'd better make sure we clear the
 	 * revoked status on any hashed alias too, otherwise the revoke
 	 * state machine will get very upset later on. */
-	if (need_cancel && !bh->b_pprev) {
+	if (need_cancel) {
 		struct buffer_head *bh2;
-		bh2 = get_hash_table(bh->b_dev, bh->b_blocknr, bh->b_size);
+		bh2 = __find_get_block(bh->b_bdev, bh->b_blocknr, bh->b_size);
 		if (bh2) {
-			clear_bit(BH_Revoked, &bh2->b_state);
+			if (bh2 != bh)
+				clear_buffer_revoked(bh2);
 			__brelse(bh2);
 		}
 	}
-
 	return did_revoke;
 }
 
+/*
+ * journal_clear_revoked_flag clears revoked flag of buffers in
+ * revoke table to reflect there is no revoked buffers in the next
+ * transaction which is going to be started.
+ */
+void jbd2_clear_buffer_revoked_flags(journal_t *journal)
+{
+	struct jbd2_revoke_table_s *revoke = journal->j_revoke;
+	int i = 0;
+
+	for (i = 0; i < revoke->hash_size; i++) {
+		struct list_head *hash_list;
+		struct list_head *list_entry;
+		hash_list = &revoke->hash_table[i];
+
+		list_for_each(list_entry, hash_list) {
+			struct jbd2_revoke_record_s *record;
+			struct buffer_head *bh;
+			record = (struct jbd2_revoke_record_s *)list_entry;
+			bh = __find_get_block(journal->j_fs_dev,
+					      record->blocknr,
+					      journal->j_blocksize);
+			if (bh) {
+				clear_buffer_revoked(bh);
+				__brelse(bh);
+			}
+		}
+	}
+}
+
+/* journal_switch_revoke table select j_revoke for next transaction
+ * we do not want to suspend any processing until all revokes are
+ * written -bzzz
+ */
+void journal_switch_revoke_table(journal_t *journal)
+{
+	int i;
+
+	if (journal->j_revoke == journal->j_revoke_table[0])
+		journal->j_revoke = journal->j_revoke_table[1];
+	else
+		journal->j_revoke = journal->j_revoke_table[0];
+
+	for (i = 0; i < journal->j_revoke->hash_size; i++)
+		INIT_LIST_HEAD(&journal->j_revoke->hash_table[i]);
+}
 
 /*
  * Write revoke records to the journal for all entries in the current
  * revoke hash, deleting the entries as we go.
- *
- * Called with the journal lock held.
  */
-
 void journal_write_revoke_records(journal_t *journal,
-				  transaction_t *transaction)
+				       transaction_t *transaction,
+				       struct list_head *log_bufs,
+				       int write_op)
 {
-	struct journal_head *descriptor;
-	struct jbd_revoke_record_s *record;
-	struct jbd_revoke_table_s *revoke;
+	struct buffer_head *descriptor;
+	struct jbd2_revoke_record_s *record;
+	struct jbd2_revoke_table_s *revoke;
 	struct list_head *hash_list;
 	int i, offset, count;
 
 	descriptor = NULL;
 	offset = 0;
 	count = 0;
-	revoke = journal->j_revoke;
+
+	/* select revoke table for committing transaction */
+	revoke = journal->j_revoke == journal->j_revoke_table[0] ?
+		journal->j_revoke_table[1] : journal->j_revoke_table[0];
 
 	for (i = 0; i < revoke->hash_size; i++) {
 		hash_list = &revoke->hash_table[i];
 
 		while (!list_empty(hash_list)) {
-			record = (struct jbd_revoke_record_s *)
+			record = (struct jbd2_revoke_record_s *)
 				hash_list->next;
-			write_one_revoke_record(journal, transaction,
+			write_one_revoke_record(journal, transaction, log_bufs,
 						&descriptor, &offset,
-						record);
+						record, write_op);
 			count++;
 			list_del(&record->hash);
-			kmem_cache_free(revoke_record_cache, record);
+			kmem_cache_free(jbd2_revoke_record_cache, record);
 		}
 	}
 	if (descriptor)
-		flush_descriptor(journal, descriptor, offset);
+		flush_descriptor(journal, descriptor, offset, write_op);
 	jbd_debug(1, "Wrote %d revoke records\n", count);
 }
 
@@ -475,11 +575,14 @@ void journal_write_revoke_records(journal_t *journal,
 
 static void write_one_revoke_record(journal_t *journal,
 				    transaction_t *transaction,
-				    struct journal_head **descriptorp,
+				    struct list_head *log_bufs,
+				    struct buffer_head **descriptorp,
 				    int *offsetp,
-				    struct jbd_revoke_record_s *record)
+				    struct jbd2_revoke_record_s *record,
+				    int write_op)
 {
-	struct journal_head *descriptor;
+	int csum_size = 0;
+	struct buffer_head *descriptor;
 	int offset;
 	journal_header_t *header;
 
@@ -493,10 +596,14 @@ static void write_one_revoke_record(journal_t *journal,
 	descriptor = *descriptorp;
 	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))
+		csum_size = sizeof(struct journal_revoke_tail);
+
 	/* Make sure we have a descriptor with space left for the record */
 	if (descriptor) {
-		if (offset == journal->j_blocksize) {
-			flush_descriptor(journal, descriptor, offset);
+		if (offset >= journal->j_blocksize - csum_size) {
+			flush_descriptor(journal, descriptor, offset, write_op);
 			descriptor = NULL;
 		}
 	}
@@ -505,25 +612,48 @@ static void write_one_revoke_record(journal_t *journal,
 		descriptor = journal_get_descriptor_buffer(journal);
 		if (!descriptor)
 			return;
-		header = (journal_header_t *) &jh2bh(descriptor)->b_data[0];
-		header->h_magic     = htonl(JFS_MAGIC_NUMBER);
-		header->h_blocktype = htonl(JFS_REVOKE_BLOCK);
-		header->h_sequence  = htonl(transaction->t_tid);
+		header = (journal_header_t *)descriptor->b_data;
+		header->h_magic     = ext2fs_cpu_to_be32(JFS_MAGIC_NUMBER);
+		header->h_blocktype = ext2fs_cpu_to_be32(JFS_REVOKE_BLOCK);
+		header->h_sequence  = ext2fs_cpu_to_be32(transaction->t_tid);
 
 		/* Record it so that we can wait for IO completion later */
-		JBUFFER_TRACE(descriptor, "file as BJ_LogCtl");
-		journal_file_buffer(descriptor, transaction, BJ_LogCtl);
+		BUFFER_TRACE(descriptor, "file in log_bufs");
+		jbd2_file_log_bh(log_bufs, descriptor);
 
 		offset = sizeof(journal_revoke_header_t);
 		*descriptorp = descriptor;
 	}
 
-	* ((unsigned int *)(&jh2bh(descriptor)->b_data[offset])) =
-		htonl(record->blocknr);
-	offset += 4;
+	if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_64BIT)) {
+		* ((__u64 *)(&descriptor->b_data[offset])) =
+			ext2fs_cpu_to_be64(record->blocknr);
+		offset += 8;
+
+	} else {
+		* ((__u32 *)(&descriptor->b_data[offset])) =
+			ext2fs_cpu_to_be32(record->blocknr);
+		offset += 4;
+	}
+
 	*offsetp = offset;
 }
 
+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))
+		return;
+
+	tail = (struct journal_revoke_tail *)(bh->b_data + j->j_blocksize -
+			sizeof(struct journal_revoke_tail));
+	tail->r_checksum = 0;
+	csum = jbd2_chksum(j, j->j_csum_seed, bh->b_data, j->j_blocksize);
+	tail->r_checksum = ext2fs_cpu_to_be32(csum);
+}
+
 /*
  * Flush a revoke descriptor out to the journal.  If we are aborting,
  * this is a noop; otherwise we are generating a buffer which needs to
@@ -532,27 +662,25 @@ static void write_one_revoke_record(journal_t *journal,
  */
 
 static void flush_descriptor(journal_t *journal,
-			     struct journal_head *descriptor,
-			     int offset)
+			     struct buffer_head *descriptor,
+			     int offset, int write_op)
 {
 	journal_revoke_header_t *header;
 
 	if (is_journal_aborted(journal)) {
-		JBUFFER_TRACE(descriptor, "brelse");
-		__brelse(jh2bh(descriptor));
+		put_bh(descriptor);
 		return;
 	}
 
-	header = (journal_revoke_header_t *) jh2bh(descriptor)->b_data;
-	header->r_count = htonl(offset);
-	set_bit(BH_JWrite, &jh2bh(descriptor)->b_state);
-	{
-		struct buffer_head *bh = jh2bh(descriptor);
-		BUFFER_TRACE(bh, "write");
-		ll_rw_block (WRITE, 1, &bh);
-	}
-}
+	header = (journal_revoke_header_t *)descriptor->b_data;
+	header->r_count = ext2fs_cpu_to_be32(offset);
+	jbd2_revoke_csum_set(journal, descriptor);
 
+	set_buffer_jwrite(descriptor);
+	BUFFER_TRACE(descriptor, "write");
+	set_buffer_dirty(descriptor);
+	write_dirty_buffer(descriptor, write_op);
+}
 #endif
 
 /*
@@ -578,14 +706,14 @@ static void flush_descriptor(journal_t *journal,
  */
 
 int journal_set_revoke(journal_t *journal,
-		       unsigned long blocknr,
+		       unsigned long long blocknr,
 		       tid_t sequence)
 {
-	struct jbd_revoke_record_s *record;
+	struct jbd2_revoke_record_s *record;
 
 	record = find_revoke_record(journal, blocknr);
 	if (record) {
-		/* If we have multiple occurences, only record the
+		/* If we have multiple occurrences, only record the
 		 * latest sequence number in the hashed record */
 		if (tid_gt(sequence, record->sequence))
 			record->sequence = sequence;
@@ -602,10 +730,10 @@ int journal_set_revoke(journal_t *journal,
  */
 
 int journal_test_revoke(journal_t *journal,
-			unsigned long blocknr,
+			unsigned long long blocknr,
 			tid_t sequence)
 {
-	struct jbd_revoke_record_s *record;
+	struct jbd2_revoke_record_s *record;
 
 	record = find_revoke_record(journal, blocknr);
 	if (!record)
@@ -624,18 +752,17 @@ void journal_clear_revoke(journal_t *journal)
 {
 	int i;
 	struct list_head *hash_list;
-	struct jbd_revoke_record_s *record;
-	struct jbd_revoke_table_s *revoke;
+	struct jbd2_revoke_record_s *record;
+	struct jbd2_revoke_table_s *revoke;
 
 	revoke = journal->j_revoke;
 
 	for (i = 0; i < revoke->hash_size; i++) {
 		hash_list = &revoke->hash_table[i];
 		while (!list_empty(hash_list)) {
-			record = (struct jbd_revoke_record_s*) hash_list->next;
+			record = (struct jbd2_revoke_record_s*) hash_list->next;
 			list_del(&record->hash);
-			kmem_cache_free(revoke_record_cache, record);
+			kmem_cache_free(jbd2_revoke_record_cache, record);
 		}
 	}
 }
-
diff --git a/lib/ext2fs/jfs_compat.h b/lib/ext2fs/jfs_compat.h
index 2638c31..d92f931 100644
--- a/lib/ext2fs/jfs_compat.h
+++ b/lib/ext2fs/jfs_compat.h
@@ -42,6 +42,18 @@ static inline __u32 jbd2_chksum(journal_t *j, __u32 crc, const void *address,
 	return ext2fs_crc32c_le(crc, address, length);
 }
 #define crc32_be(x, y, z)	ext2fs_crc32_be((x), (y), (z))
+#define spin_lock_init(x)
+#define spin_lock(x)
+#define spin_unlock(x)
+#define yield()
+#define SLAB_HWCACHE_ALIGN	0
+#define SLAB_TEMPORARY		0
+#define KMEM_CACHE(__struct, __flags) kmem_cache_create(#__struct,\
+                sizeof(struct __struct), __alignof__(struct __struct),\
+                (__flags), NULL)
+
+#define blkdev_issue_flush(kdev, a, b)	sync_blockdev(kdev)
+#define is_power_of_2(x)	((x) != 0 && (((x) & ((x) - 1)) == 0))
 
 struct journal_s
 {
@@ -63,7 +75,8 @@ struct journal_s
 	tid_t			j_tail_sequence;
 	tid_t			j_transaction_sequence;
 	__u8			j_uuid[16];
-	struct jbd_revoke_table_s *j_revoke;
+	struct jbd2_revoke_table_s *j_revoke;
+	struct jbd2_revoke_table_s *j_revoke_table[2];
 	tid_t			j_failed_commit;
 	__u32			j_csum_seed;
 };
diff --git a/lib/ext2fs/kernel-jbd.h b/lib/ext2fs/kernel-jbd.h
index a9cdc30..407f4a5 100644
--- a/lib/ext2fs/kernel-jbd.h
+++ b/lib/ext2fs/kernel-jbd.h
@@ -365,6 +365,7 @@ static inline struct journal_head *bh2jh(struct buffer_head *bh)
 }
 
 struct jbd_revoke_table_s;
+struct jbd2_revoke_table_s;
 
 /* The handle_t type represents a single atomic update being performed
  * by some process.  All filesystem modifications made by the process go
@@ -892,8 +893,8 @@ extern void	   journal_destroy_revoke_caches(void);
 extern int	   journal_init_revoke_caches(void);
 
 /* Recovery revoke support */
-extern int	   journal_set_revoke(journal_t *, unsigned long, tid_t);
-extern int	   journal_test_revoke(journal_t *, unsigned long, tid_t);
+extern int	   journal_set_revoke(journal_t *, unsigned long long, tid_t);
+extern int	   journal_test_revoke(journal_t *, unsigned long long, tid_t);
 extern void	   journal_clear_revoke(journal_t *);
 extern void	   journal_brelse_array(struct buffer_head *b[], int n);
 


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 10/27] e2fsck: fix infinite loop when recovering corrupt journal blocks
  2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
                   ` (8 preceding siblings ...)
  2014-08-16 23:46 ` [PATCH 09/27] e2fsck: resync jbd2 revoke " Darrick J. Wong
@ 2014-08-16 23:46 ` Darrick J. Wong
  2014-08-27  3:45   ` Theodore Ts'o
  2014-08-16 23:47 ` [PATCH 11/27] e2fsck/debugfs: fix descriptor block size handling errors with journal_csum Darrick J. Wong
                   ` (17 subsequent siblings)
  27 siblings, 1 reply; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-16 23:46 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

When recovering the journal, don't fall into an infinite loop if we
encounter a corrupt journal block.  Instead, just skip the block and
proceed with the full filesystem fsck.

The test case for this will be "j_corrupt_journal_block" further on
in the patch series.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 e2fsck/recovery.c |    7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)


diff --git a/e2fsck/recovery.c b/e2fsck/recovery.c
index e4c7519..0e194be 100644
--- a/e2fsck/recovery.c
+++ b/e2fsck/recovery.c
@@ -426,6 +426,7 @@ static int do_one_pass(journal_t *journal,
 	int			tag_bytes = journal_tag_bytes(journal);
 	__u32			crc32_sum = ~0; /* Transactional Checksums */
 	int			descr_csum_size = 0;
+	int			block_error = 0;
 
 	/*
 	 * First thing is to establish what we expect to find in the log
@@ -598,7 +599,8 @@ static int do_one_pass(journal_t *journal,
 						       "checksum recovering "
 						       "block %llu in log\n",
 						       blocknr);
-						continue;
+						block_error = 1;
+						goto skip_write;
 					}
 
 					/* Find a buffer for the new
@@ -797,7 +799,8 @@ static int do_one_pass(journal_t *journal,
 				success = -EIO;
 		}
 	}

^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 11/27] e2fsck/debugfs: fix descriptor block size handling errors with journal_csum
  2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
                   ` (9 preceding siblings ...)
  2014-08-16 23:46 ` [PATCH 10/27] e2fsck: fix infinite loop when recovering corrupt journal blocks Darrick J. Wong
@ 2014-08-16 23:47 ` Darrick J. Wong
  2014-08-28  1:15   ` Theodore Ts'o
  2014-08-16 23:47 ` [PATCH 12/27] debugfs: create journal handling routines Darrick J. Wong
                   ` (16 subsequent siblings)
  27 siblings, 1 reply; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-16 23:47 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4, TR Reardon

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 <darrick.wong@oracle.com>
Reported-by: TR Reardon <thomas_reardon@hotmail.com>
---
 debugfs/jfs_user.h      |   21 +++++++++++++++++++++
 debugfs/logdump.c       |   12 +++++++-----
 e2fsck/journal.c        |   14 +++++++++-----
 e2fsck/recovery.c       |   26 +++++++++++++++-----------
 e2fsck/revoke.c         |    4 ++--
 lib/e2p/feature.c       |    2 ++
 lib/ext2fs/kernel-jbd.h |   44 ++++++++++++++++++++++++++++++++++----------
 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..f287553 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;
+	else
+		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..84e3a26 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);
@@ -624,15 +624,19 @@ static errcode_t e2fsck_journal_load(journal_t *journal)
 		return EXT2_ET_RO_UNSUPP_FEATURE;
 
 	/* Checksum v1 and v2 are mutually exclusive features. */
-	if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_CSUM_V2) &&
+	if (journal_has_csum_v2or3(journal) &&
 	    JFS_HAS_COMPAT_FEATURE(journal, JFS_FEATURE_COMPAT_CHECKSUM))
 		return EXT2_ET_CORRUPT_SUPERBLOCK;
 
+	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 (!e2fsck_journal_verify_csum_type(journal, jsb) ||
 	    !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 0e194be..b63bbb8 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,17 +400,21 @@ 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);
 
-	return tag->t_checksum == ext2fs_cpu_to_be16(csum32);
+	if (JFS_HAS_INCOMPAT_FEATURE(j, JFS_FEATURE_INCOMPAT_CSUM_V3))
+		return tag3->t_checksum == ext2fs_cpu_to_be32(csum32);
+	else
+		return tag->t_checksum == ext2fs_cpu_to_be16(csum32);
 }
 
 static int do_one_pass(journal_t *journal,
@@ -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..28a7a10 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;
+		return sz;
 	else
-		return x + JBD_TAG_SIZE32;
+		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 7cbb99b..9924285 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_V2)) ||
+	    (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_V2)) ||
+	    (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),


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 12/27] debugfs: create journal handling routines
  2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
                   ` (10 preceding siblings ...)
  2014-08-16 23:47 ` [PATCH 11/27] e2fsck/debugfs: fix descriptor block size handling errors with journal_csum Darrick J. Wong
@ 2014-08-16 23:47 ` Darrick J. Wong
  2014-08-16 23:47 ` [PATCH 13/27] e2fsck: set journal superblock s_sequence to tail_sequence Darrick J. Wong
                   ` (15 subsequent siblings)
  27 siblings, 0 replies; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-16 23:47 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

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 <darrick.wong@oracle.com>
---
 debugfs/Makefile.in       |   54 +++
 debugfs/jfs_user.h        |  143 +++++++
 debugfs/journal.c         |  911 +++++++++++++++++++++++++++++++++++++++++++++
 lib/ext2fs/Makefile.in    |   20 +
 lib/ext2fs/ext2_err.et.in |    3 
 lib/ext2fs/ext2fs.h       |    3 
 6 files changed, 1128 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 f287553..02664f8 100644
--- a/debugfs/jfs_user.h
+++ b/debugfs/jfs_user.h
@@ -1,10 +1,151 @@
+/*
+ * 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..97fbce6
--- /dev/null
+++ b/debugfs/journal.c
@@ -0,0 +1,911 @@
+/*
+ * 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;
+
+		if ((retval = ext2fs_read_inode(fs,
+						sb->s_journal_inum,
+						&j_inode->i_ext2))) {
+		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;
+		if ((retval = (errcode_t) journal_bmap(journal, 0, &start)) != 0)
+			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,
+				      &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);
+		if ((retval = bh->b_err) != 0) {
+			brelse(bh);
+			goto errout;
+		}
+		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);
+#endif
+		if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
+		    !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
+			retval = EXT2_ET_LOAD_EXT_JOURNAL;
+			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;
+			goto errout;
+		}
+
+		maxlen = ext2fs_blocks_count(&jsuper);
+		journal->j_maxlen = (maxlen < 1ULL << 32) ? maxlen : (1ULL << 32) - 1;
+		start++;
+	}
+
+	if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
+		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 and v2 are mutually exclusive features. */
+	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..e9c16e7 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


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 13/27] e2fsck: set journal superblock s_sequence to tail_sequence
  2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
                   ` (11 preceding siblings ...)
  2014-08-16 23:47 ` [PATCH 12/27] debugfs: create journal handling routines Darrick J. Wong
@ 2014-08-16 23:47 ` Darrick J. Wong
  2014-08-16 23:47 ` [PATCH 14/27] debugfs: add the ability to write transactions to the journal Darrick J. Wong
                   ` (14 subsequent siblings)
  27 siblings, 0 replies; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-16 23:47 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

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 <darrick.wong@oracle.com>
---
 e2fsck/journal.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)


diff --git a/e2fsck/journal.c b/e2fsck/journal.c
index 84e3a26..414f2d8 100644
--- a/e2fsck/journal.c
+++ b/e2fsck/journal.c
@@ -745,7 +745,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);


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 14/27] debugfs: add the ability to write transactions to the journal
  2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
                   ` (12 preceding siblings ...)
  2014-08-16 23:47 ` [PATCH 13/27] e2fsck: set journal superblock s_sequence to tail_sequence Darrick J. Wong
@ 2014-08-16 23:47 ` Darrick J. Wong
  2014-09-06  5:52   ` Darrick J. Wong
  2014-08-16 23:47 ` [PATCH 15/27] tests: test writing and recovering checksum-free 32/64bit journals Darrick J. Wong
                   ` (13 subsequent siblings)
  27 siblings, 1 reply; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-16 23:47 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

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.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 debugfs/Makefile.in    |   16 +
 debugfs/debug_cmds.ct  |   11 +
 debugfs/debugfs.h      |    1 
 debugfs/do_journal.c   |  975 ++++++++++++++++++++++++++++++++++++++++++++++++
 debugfs/util.c         |   35 ++
 lib/ext2fs/Makefile.in |    9 
 6 files changed, 1043 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..b85c2d7
--- /dev/null
+++ b/debugfs/do_journal.c
@@ -0,0 +1,975 @@
+/*
+ * 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);
+
+#define 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_inode->i_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_inode->i_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_inode->i_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 = 1;
+	} 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_inode->i_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_inode->i_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_inode->i_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_inode->i_fs->super,
+				       EXT4_FEATURE_INCOMPAT_64BIT))
+		return;
+
+	if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_64BIT) &&
+	    EXT2_HAS_INCOMPAT_FEATURE(journal->j_inode->i_fs->super,
+				      EXT4_FEATURE_INCOMPAT_64BIT))
+		return;
+
+	if (journal->j_tail != 0 ||
+	    EXT2_HAS_INCOMPAT_FEATURE(journal->j_inode->i_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:")) != -1) {
+		switch (opt) {
+		case 'c':
+			enable_csum = 1;
+			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..470f5fb 100644
--- a/debugfs/util.c
+++ b/debugfs/util.c
@@ -497,3 +497,38 @@ 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;
+
+		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 $@


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 15/27] tests: test writing and recovering checksum-free 32/64bit journals
  2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
                   ` (13 preceding siblings ...)
  2014-08-16 23:47 ` [PATCH 14/27] debugfs: add the ability to write transactions to the journal Darrick J. Wong
@ 2014-08-16 23:47 ` Darrick J. Wong
  2014-08-16 23:47 ` [PATCH 16/27] tests: test writing and recovering 64bit csum_v3 journals Darrick J. Wong
                   ` (12 subsequent siblings)
  27 siblings, 0 replies; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-16 23:47 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

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 <darrick.wong@oracle.com>
---
 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:      \b\b\b\b\bdone                            
+Writing inode tables:      \b\b\b\b\bdone                            
+Creating journal (8192 blocks): done
+Writing superblocks and filesystem accounting information:      \b\b\b\b\bdone
+
+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:      \b\b\b\b\bdone                            
+Writing inode tables:      \b\b\b\b\bdone                            
+Creating journal (8192 blocks): done
+Writing superblocks and filesystem accounting information:      \b\b\b\b\bdone
+
+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:    \b\b\bdone                            
+Writing inode tables:    \b\b\bdone                            
+Creating journal (4096 blocks): done
+Writing superblocks and filesystem accounting information:    \b\b\bdone
+
+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:    \b\b\bdone                            
+Writing inode tables:    \b\b\bdone                            
+Creating journal (4096 blocks): done
+Writing superblocks and filesystem accounting information:    \b\b\bdone
+
+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:    \b\b\bdone                            
+Writing inode tables:    \b\b\bdone                            
+Creating journal (4096 blocks): done
+Writing superblocks and filesystem accounting information:    \b\b\bdone
+
+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:    \b\b\bdone                            
+Writing inode tables:    \b\b\bdone                            
+Creating journal (4096 blocks): done
+Writing superblocks and filesystem accounting information:    \b\b\bdone
+
+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:    \b\b\bdone                            
+Writing inode tables:    \b\b\bdone                            
+Creating journal (4096 blocks): done
+Writing superblocks and filesystem accounting information:    \b\b\bdone
+
+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:    \b\b\bdone                            
+Writing inode tables:    \b\b\bdone                            
+Creating journal (4096 blocks): done
+Writing superblocks and filesystem accounting information:    \b\b\bdone
+
+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


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 16/27] tests: test writing and recovering 64bit csum_v3 journals
  2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
                   ` (14 preceding siblings ...)
  2014-08-16 23:47 ` [PATCH 15/27] tests: test writing and recovering checksum-free 32/64bit journals Darrick J. Wong
@ 2014-08-16 23:47 ` Darrick J. Wong
  2014-08-16 23:47 ` [PATCH 17/27] tests: test writing and recovering 32bit " Darrick J. Wong
                   ` (11 subsequent siblings)
  27 siblings, 0 replies; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-16 23:47 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

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 <darrick.wong@oracle.com>
---
 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:      \b\b\b\b\bdone                            
+Writing inode tables:      \b\b\b\b\bdone                            
+Creating journal (16384 blocks): done
+Writing superblocks and filesystem accounting information:      \b\b\b\b\bdone
+
+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:      \b\b\b\b\bdone                            
+Writing inode tables:      \b\b\b\b\bdone                            
+Creating journal (16384 blocks): done
+Writing superblocks and filesystem accounting information:      \b\b\b\b\bdone
+
+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:    \b\b\bdone                            
+Writing inode tables:    \b\b\bdone                            
+Creating journal (4096 blocks): done
+Writing superblocks and filesystem accounting information:    \b\b\bdone
+
+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:    \b\b\bdone                            
+Writing inode tables:    \b\b\bdone                            
+Creating journal (4096 blocks): done
+Writing superblocks and filesystem accounting information:    \b\b\bdone
+
+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:    \b\b\bdone                            
+Writing inode tables:    \b\b\bdone                            
+Creating journal (4096 blocks): done
+Writing superblocks and filesystem accounting information:    \b\b\bdone
+
+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:    \b\b\bdone                            
+Writing inode tables:    \b\b\bdone                            
+Creating journal (4096 blocks): done
+Writing superblocks and filesystem accounting information:    \b\b\bdone
+
+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


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 17/27] tests: test writing and recovering 32bit csum_v3 journals
  2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
                   ` (15 preceding siblings ...)
  2014-08-16 23:47 ` [PATCH 16/27] tests: test writing and recovering 64bit csum_v3 journals Darrick J. Wong
@ 2014-08-16 23:47 ` Darrick J. Wong
  2014-08-16 23:47 ` [PATCH 18/27] tests: write and replay blocks with the old journal checksum Darrick J. Wong
                   ` (10 subsequent siblings)
  27 siblings, 0 replies; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-16 23:47 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

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 <darrick.wong@oracle.com>
---
 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:      \b\b\b\b\bdone                            
+Writing inode tables:      \b\b\b\b\bdone                            
+Creating journal (16384 blocks): done
+Writing superblocks and filesystem accounting information:      \b\b\b\b\bdone
+
+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:      \b\b\b\b\bdone                            
+Writing inode tables:      \b\b\b\b\bdone                            
+Creating journal (16384 blocks): done
+Writing superblocks and filesystem accounting information:      \b\b\b\b\bdone
+
+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


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 18/27] tests: write and replay blocks with the old journal checksum
  2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
                   ` (16 preceding siblings ...)
  2014-08-16 23:47 ` [PATCH 17/27] tests: test writing and recovering 32bit " Darrick J. Wong
@ 2014-08-16 23:47 ` Darrick J. Wong
  2014-08-16 23:47 ` [PATCH 19/27] tests: test recovery of 32 and 64-bit journals with checksum v2 Darrick J. Wong
                   ` (9 subsequent siblings)
  27 siblings, 0 replies; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-16 23:47 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

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

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 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:    \b\b\bdone                            
+Writing inode tables:    \b\b\bdone                            
+Creating journal (4096 blocks): done
+Writing superblocks and filesystem accounting information:    \b\b\bdone
+
+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


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 19/27] tests: test recovery of 32 and 64-bit journals with checksum v2
  2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
                   ` (17 preceding siblings ...)
  2014-08-16 23:47 ` [PATCH 18/27] tests: write and replay blocks with the old journal checksum Darrick J. Wong
@ 2014-08-16 23:47 ` Darrick J. Wong
  2014-08-16 23:48 ` [PATCH 20/27] tests: test how e2fsck recovers from corrupt journal superblocks Darrick J. Wong
                   ` (8 subsequent siblings)
  27 siblings, 0 replies; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-16 23:47 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

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

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 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


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 20/27] tests: test how e2fsck recovers from corrupt journal superblocks
  2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
                   ` (18 preceding siblings ...)
  2014-08-16 23:47 ` [PATCH 19/27] tests: test recovery of 32 and 64-bit journals with checksum v2 Darrick J. Wong
@ 2014-08-16 23:48 ` Darrick J. Wong
  2014-08-16 23:48 ` [PATCH 21/27] tests: test e2fsck recovery of corrupt revoke blocks Darrick J. Wong
                   ` (7 subsequent siblings)
  27 siblings, 0 replies; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-16 23:48 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

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

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 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


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 21/27] tests: test e2fsck recovery of corrupt revoke blocks
  2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
                   ` (19 preceding siblings ...)
  2014-08-16 23:48 ` [PATCH 20/27] tests: test how e2fsck recovers from corrupt journal superblocks Darrick J. Wong
@ 2014-08-16 23:48 ` Darrick J. Wong
  2014-08-16 23:48 ` [PATCH 22/27] tests: test e2fsck recovery with broken commit blocks Darrick J. Wong
                   ` (6 subsequent siblings)
  27 siblings, 0 replies; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-16 23:48 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

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 <darrick.wong@oracle.com>
---
 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


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 22/27] tests: test e2fsck recovery with broken commit blocks
  2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
                   ` (20 preceding siblings ...)
  2014-08-16 23:48 ` [PATCH 21/27] tests: test e2fsck recovery of corrupt revoke blocks Darrick J. Wong
@ 2014-08-16 23:48 ` Darrick J. Wong
  2014-08-16 23:48 ` [PATCH 23/27] tests: test e2fsck recovery of corrupt descriptor blocks Darrick J. Wong
                   ` (5 subsequent siblings)
  27 siblings, 0 replies; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-16 23:48 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

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

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 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


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 23/27] tests: test e2fsck recovery of corrupt descriptor blocks
  2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
                   ` (21 preceding siblings ...)
  2014-08-16 23:48 ` [PATCH 22/27] tests: test e2fsck recovery with broken commit blocks Darrick J. Wong
@ 2014-08-16 23:48 ` Darrick J. Wong
  2014-08-16 23:48 ` [PATCH 24/27] mke2fs: set block_validity as a default mount option Darrick J. Wong
                   ` (4 subsequent siblings)
  27 siblings, 0 replies; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-16 23:48 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

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 <darrick.wong@oracle.com>
---
 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


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 24/27] mke2fs: set block_validity as a default mount option
  2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
                   ` (22 preceding siblings ...)
  2014-08-16 23:48 ` [PATCH 23/27] tests: test e2fsck recovery of corrupt descriptor blocks Darrick J. Wong
@ 2014-08-16 23:48 ` Darrick J. Wong
  2014-08-16 23:48 ` [PATCH 25/27] ext2fs: add readahead method to improve scanning Darrick J. Wong
                   ` (3 subsequent siblings)
  27 siblings, 0 replies; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-16 23:48 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

The block_validity mount option spot-checks block allocations against
a bitmap of known group metadata blocks.  This helps us to prevent
self-inflicted catastrophic failures such as trying to "share"
critical metadata (think bitmaps) with file data, which usually
results in filesystem destruction.

In order to test the overhead of the mount option, I re-used the speed
tests in the metadata checksum testing script.  In short, the program
creates what looks like 15 copies of a kernel source tree, except that
it uses fallocate to strip out the overhead of writing the file data
so that we can focus on metadata overhead.  On a 64G RAM disk, the
overhead was generally about 0.9% and at most 1.6%.  On a 160G USB
disk, the overhead was about 0.8% and peaked at 1.2%.

When I changed the test to write out files instead of merely
fallocating space, the overhead was negligible.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 misc/mke2fs.conf.in |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)


diff --git a/misc/mke2fs.conf.in b/misc/mke2fs.conf.in
index 4c5dba7..de0250d 100644
--- a/misc/mke2fs.conf.in
+++ b/misc/mke2fs.conf.in
@@ -1,6 +1,6 @@
 [defaults]
 	base_features = sparse_super,filetype,resize_inode,dir_index,ext_attr
-	default_mntopts = acl,user_xattr
+	default_mntopts = acl,user_xattr,block_validity
 	enable_periodic_fsck = 0
 	blocksize = 4096
 	inode_size = 256


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 25/27] ext2fs: add readahead method to improve scanning
  2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
                   ` (23 preceding siblings ...)
  2014-08-16 23:48 ` [PATCH 24/27] mke2fs: set block_validity as a default mount option Darrick J. Wong
@ 2014-08-16 23:48 ` Darrick J. Wong
  2014-08-16 23:48 ` [PATCH 26/27] libext2fs/e2fsck: provide routines to read-ahead metadata Darrick J. Wong
                   ` (2 subsequent siblings)
  27 siblings, 0 replies; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-16 23:48 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4, Andreas Dilger

Frøm: Andreas Dilger <adilger@whamcloud.com>

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.

[darrick.wong@oracle.com]
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 <andreas.dilger@intel.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 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;

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

^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 26/27] libext2fs/e2fsck: provide routines to read-ahead metadata
  2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
                   ` (24 preceding siblings ...)
  2014-08-16 23:48 ` [PATCH 25/27] ext2fs: add readahead method to improve scanning Darrick J. Wong
@ 2014-08-16 23:48 ` Darrick J. Wong
  2014-08-16 23:48 ` [PATCH 27/27] e2fsck: read-ahead metadata during passes 1, 2, and 4 Darrick J. Wong
  2014-08-17 17:23 ` [PATCH 28/27] libext2fs: write_journal_inode should check iterate return value Darrick J. Wong
  27 siblings, 0 replies; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-16 23:48 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

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 <darrick.wong@oracle.com>
---
 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..3a9d7b5 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
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 e9c16e7..d57dc32 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,


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 27/27] e2fsck: read-ahead metadata during passes 1, 2, and 4
  2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
                   ` (25 preceding siblings ...)
  2014-08-16 23:48 ` [PATCH 26/27] libext2fs/e2fsck: provide routines to read-ahead metadata Darrick J. Wong
@ 2014-08-16 23:48 ` Darrick J. Wong
  2014-08-17 17:23 ` [PATCH 28/27] libext2fs: write_journal_inode should check iterate return value Darrick J. Wong
  27 siblings, 0 replies; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-16 23:48 UTC (permalink / raw)
  To: tytso, darrick.wong; +Cc: linux-ext4

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 <darrick.wong@oracle.com>
---
 e2fsck/e2fsck.8.in      |    7 +++++
 e2fsck/e2fsck.conf.5.in |   15 +++++++++++
 e2fsck/e2fsck.h         |    3 ++
 e2fsck/pass1.c          |   64 +++++++++++++++++++++++++++++++++++++++++++++++
 e2fsck/pass2.c          |   38 +++++++++++++++++++++++++++-
 e2fsck/pass4.c          |    9 +++++++
 e2fsck/unix.c           |   28 +++++++++++++++++++++
 7 files changed, 163 insertions(+), 1 deletion(-)


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..015d55b 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -867,6 +867,59 @@ 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 : 8) *
+				    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 +942,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 +1134,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))


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH 28/27] libext2fs: write_journal_inode should check iterate return value
  2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
                   ` (26 preceding siblings ...)
  2014-08-16 23:48 ` [PATCH 27/27] e2fsck: read-ahead metadata during passes 1, 2, and 4 Darrick J. Wong
@ 2014-08-17 17:23 ` Darrick J. Wong
  27 siblings, 0 replies; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-17 17:23 UTC (permalink / raw)
  To: tytso; +Cc: linux-ext4

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
(re)creating broken journals.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 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 e2e9ce7..de30a7d 100644
--- a/lib/ext2fs/mkjournal.c
+++ b/lib/ext2fs/mkjournal.c
@@ -371,6 +371,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

^ permalink raw reply related	[flat|nested] 42+ messages in thread

* Re: [PATCH 01/27] e2fuzz: fix pwrite64/pwrite usage
  2014-08-16 23:45 ` [PATCH 01/27] e2fuzz: fix pwrite64/pwrite usage Darrick J. Wong
@ 2014-08-24 23:56   ` Theodore Ts'o
  0 siblings, 0 replies; 42+ messages in thread
From: Theodore Ts'o @ 2014-08-24 23:56 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-ext4

On Sat, Aug 16, 2014 at 04:45:57PM -0700, Darrick J. Wong wrote:
> Select pwrite64 or pwrite depending on what autoconf finds.  This
> makes e2fuzz find a suitable pwrite variant regardless of platform.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Applied, thanks.

					- Ted

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 02/27] misc: fix gcc warnings
  2014-08-16 23:46 ` [PATCH 02/27] misc: fix gcc warnings Darrick J. Wong
@ 2014-08-24 23:56   ` Theodore Ts'o
  0 siblings, 0 replies; 42+ messages in thread
From: Theodore Ts'o @ 2014-08-24 23:56 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-ext4

On Sat, Aug 16, 2014 at 04:46:03PM -0700, Darrick J. Wong wrote:
> Fix a number of warnings about unneeded variables, uninitialized
> variables, and ignored return values.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

This patch is identical to http://patchwork.ozlabs.org/patch/378713/,
which I've already applied.

					- Ted

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 03/27] libext2fs: byteswap inode when performing the sanity scan
  2014-08-16 23:46 ` [PATCH 03/27] libext2fs: byteswap inode when performing the sanity scan Darrick J. Wong
@ 2014-08-25  2:01   ` Theodore Ts'o
  0 siblings, 0 replies; 42+ messages in thread
From: Theodore Ts'o @ 2014-08-25  2:01 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-ext4

On Sat, Aug 16, 2014 at 04:46:10PM -0700, Darrick J. Wong wrote:
> On BE platforms, we need to swap the inode bytes after doing the
> checksum verification but before looking at i_blocks.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Thanks, applied.

					- Ted

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 04/27] libext2fs: fix problems with LE<->BE conversions on BE platforms
  2014-08-16 23:46 ` [PATCH 04/27] libext2fs: fix problems with LE<->BE conversions on BE platforms Darrick J. Wong
@ 2014-08-25  2:01   ` Theodore Ts'o
  0 siblings, 0 replies; 42+ messages in thread
From: Theodore Ts'o @ 2014-08-25  2:01 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-ext4

On Sat, Aug 16, 2014 at 04:46:16PM -0700, Darrick J. Wong wrote:
> Fix more problems that I found when testing on ppc64:
> 
> - Inode swap cut and paste error leads to immutable inodes being
>   detected as inlinedata inodes, leading to e2fsck incorrectly barfing
>   on i_block[] contents.
> 
> - Superblock csum/verify must be aware of the fs->super byte order
>   when checking for metadata_csum feature flag.  (Hint: in _openfs(),
>   fs->super is in LE order for the first csum verification)
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Thanks, applied.

					- Ted

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 05/27] e2fsck: on BE, re-swap everything after a damaged dirent so salvage works correctly
  2014-08-16 23:46 ` [PATCH 05/27] e2fsck: on BE, re-swap everything after a damaged dirent so salvage works correctly Darrick J. Wong
@ 2014-08-25  2:03   ` Theodore Ts'o
  0 siblings, 0 replies; 42+ messages in thread
From: Theodore Ts'o @ 2014-08-25  2:03 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-ext4

On Sat, Aug 16, 2014 at 04:46:23PM -0700, Darrick J. Wong wrote:
> On big-endian systems, if the dirent swap routine finds a rec_len that
> it doesn't like, it continues processing the block as if rec_len == 8.
> This means that the name field gets byte swapped, which means that
> salvage will not detect the correct name length (unless the name has a
> length that's an exact multiple of four bytes), and it'll discard the
> entry (unnecessarily) and the rest of the dirent block.  Therefore,
> swap the rest of the block back to disk order, run salvage, and
> re-swap anything after the salvaged dirent.
> 
> The test case for this is f_inlinedata_repair if you run it on a BE
> system.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Thanks, applied.

					- Ted

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 06/27] libext2fs: create inlinedata symlinks
  2014-08-16 23:46 ` [PATCH 06/27] libext2fs: create inlinedata symlinks Darrick J. Wong
@ 2014-08-25  2:05   ` Theodore Ts'o
  0 siblings, 0 replies; 42+ messages in thread
From: Theodore Ts'o @ 2014-08-25  2:05 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-ext4, Pu Hou

On Sat, Aug 16, 2014 at 04:46:29PM -0700, Darrick J. Wong wrote:
> Add to ext2fs_symlink the ability to create inline data symlinks.
> 
> Suggested-by: Pu Hou <houpu.hp@alibaba-inc.com>
> Cc: Pu Hou <houpu.hp@alibaba-inc.com>
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

This is identical to the already applied:

     http://patchwork.ozlabs.org/patch/378712/

							- Ted

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 07/27] contrib: add script to help resync journal code with kernel
  2014-08-16 23:46 ` [PATCH 07/27] contrib: add script to help resync journal code with kernel Darrick J. Wong
@ 2014-08-27  3:44   ` Theodore Ts'o
  0 siblings, 0 replies; 42+ messages in thread
From: Theodore Ts'o @ 2014-08-27  3:44 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-ext4

On Sat, Aug 16, 2014 at 04:46:35PM -0700, Darrick J. Wong wrote:
> Add a script that handles (most) of the code massaging necessary to resync
> {recovery,revoke}.c from the Linux kernel into e2fsprogs.
> 
> Usage: jbd2-resync.sh linux/fs/jbd2/revoke.c e2fsprogs/e2fsck/revoke.c
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Applied, thanks.

					- Ted

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 08/27] e2fsck: resync jbd2 recovery code from Linux 3.16
  2014-08-16 23:46 ` [PATCH 08/27] e2fsck: resync jbd2 recovery code from Linux 3.16 Darrick J. Wong
@ 2014-08-27  3:44   ` Theodore Ts'o
  0 siblings, 0 replies; 42+ messages in thread
From: Theodore Ts'o @ 2014-08-27  3:44 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-ext4

On Sat, Aug 16, 2014 at 04:46:42PM -0700, Darrick J. Wong wrote:
> Synchronize e2fsck's copy of recovery.c with the kernel's copy in
> fs/jbd2.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Applied, thanks.

					- Ted

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 09/27] e2fsck: resync jbd2 revoke code from Linux 3.16
  2014-08-16 23:46 ` [PATCH 09/27] e2fsck: resync jbd2 revoke " Darrick J. Wong
@ 2014-08-27  3:44   ` Theodore Ts'o
  0 siblings, 0 replies; 42+ messages in thread
From: Theodore Ts'o @ 2014-08-27  3:44 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-ext4

On Sat, Aug 16, 2014 at 04:46:48PM -0700, Darrick J. Wong wrote:
> Synchronize e2fsck's copy of revoke.c with the kernel's copy in
> fs/jbd2.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Applied, thanks.

					- Ted

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 10/27] e2fsck: fix infinite loop when recovering corrupt journal blocks
  2014-08-16 23:46 ` [PATCH 10/27] e2fsck: fix infinite loop when recovering corrupt journal blocks Darrick J. Wong
@ 2014-08-27  3:45   ` Theodore Ts'o
  0 siblings, 0 replies; 42+ messages in thread
From: Theodore Ts'o @ 2014-08-27  3:45 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-ext4

On Sat, Aug 16, 2014 at 04:46:55PM -0700, Darrick J. Wong wrote:
> When recovering the journal, don't fall into an infinite loop if we
> encounter a corrupt journal block.  Instead, just skip the block and
> proceed with the full filesystem fsck.
> 
> The test case for this will be "j_corrupt_journal_block" further on
> in the patch series.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Applied, thanks.

					- Ted

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 11/27] e2fsck/debugfs: fix descriptor block size handling errors with journal_csum
  2014-08-16 23:47 ` [PATCH 11/27] e2fsck/debugfs: fix descriptor block size handling errors with journal_csum Darrick J. Wong
@ 2014-08-28  1:15   ` Theodore Ts'o
  2014-08-28  1:33     ` Darrick J. Wong
  0 siblings, 1 reply; 42+ messages in thread
From: Theodore Ts'o @ 2014-08-28  1:15 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-ext4, TR Reardon

On Sat, Aug 16, 2014 at 04:47:01PM -0700, Darrick J. Wong wrote:
> diff --git a/misc/dumpe2fs.c b/misc/dumpe2fs.c
> index 7cbb99b..9924285 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_V2)) ||
> +	    (jsb->s_feature_incompat &
> +	     ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_CSUM_V2)))

I assume this should really be: 

+	if ((jsb->s_feature_incompat &
+	     ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_CSUM_V2)) ||
+	    (jsb->s_feature_incompat &
+	     ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_CSUM_V3)))
                                                         ^^^^

amd similarly below in the next if statement?

					- Ted

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 11/27] e2fsck/debugfs: fix descriptor block size handling errors with journal_csum
  2014-08-28  1:15   ` Theodore Ts'o
@ 2014-08-28  1:33     ` Darrick J. Wong
  0 siblings, 0 replies; 42+ messages in thread
From: Darrick J. Wong @ 2014-08-28  1:33 UTC (permalink / raw)
  To: Theodore Ts'o; +Cc: linux-ext4, TR Reardon

On Wed, Aug 27, 2014 at 09:15:46PM -0400, Theodore Ts'o wrote:
> On Sat, Aug 16, 2014 at 04:47:01PM -0700, Darrick J. Wong wrote:
> > diff --git a/misc/dumpe2fs.c b/misc/dumpe2fs.c
> > index 7cbb99b..9924285 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_V2)) ||
> > +	    (jsb->s_feature_incompat &
> > +	     ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_CSUM_V2)))
> 
> I assume this should really be: 
> 
> +	if ((jsb->s_feature_incompat &
> +	     ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_CSUM_V2)) ||
> +	    (jsb->s_feature_incompat &
> +	     ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_CSUM_V3)))
>                                                          ^^^^
> 
> amd similarly below in the next if statement?

Err... oops.  Yes, you are correct.  Thank you for catching this.

--D

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

^ permalink raw reply	[flat|nested] 42+ messages in thread

* Re: [PATCH 14/27] debugfs: add the ability to write transactions to the journal
  2014-08-16 23:47 ` [PATCH 14/27] debugfs: add the ability to write transactions to the journal Darrick J. Wong
@ 2014-09-06  5:52   ` Darrick J. Wong
  0 siblings, 0 replies; 42+ messages in thread
From: Darrick J. Wong @ 2014-09-06  5:52 UTC (permalink / raw)
  To: tytso; +Cc: linux-ext4

On Sat, Aug 16, 2014 at 04:47:23PM -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.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> ---

<snip>

> +#define DEBUG

Probably ought to be #undef DEBUG...

<snip>

> +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_inode->i_fs->super)) {

This (and all other journal->j_inode dereference chains) ought to be
journal->j_fs_dev->k_fs->super because j_inode is NULL if we have an
external journal.

Will send out updated patch (with more test cases) shortly.

--D

> +			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_inode->i_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_inode->i_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 = 1;
> +	} 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_inode->i_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_inode->i_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_inode->i_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_inode->i_fs->super,
> +				       EXT4_FEATURE_INCOMPAT_64BIT))
> +		return;
> +
> +	if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_64BIT) &&
> +	    EXT2_HAS_INCOMPAT_FEATURE(journal->j_inode->i_fs->super,
> +				      EXT4_FEATURE_INCOMPAT_64BIT))
> +		return;
> +
> +	if (journal->j_tail != 0 ||
> +	    EXT2_HAS_INCOMPAT_FEATURE(journal->j_inode->i_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:")) != -1) {
> +		switch (opt) {
> +		case 'c':
> +			enable_csum = 1;
> +			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..470f5fb 100644
> --- a/debugfs/util.c
> +++ b/debugfs/util.c
> @@ -497,3 +497,38 @@ 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;
> +
> +		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 $@
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 42+ messages in thread

end of thread, other threads:[~2014-09-06  5:53 UTC | newest]

Thread overview: 42+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-16 23:45 [PATCH 00/27] e2fsprogs Summer 2014 patchbomb, part 5.1 Darrick J. Wong
2014-08-16 23:45 ` [PATCH 01/27] e2fuzz: fix pwrite64/pwrite usage Darrick J. Wong
2014-08-24 23:56   ` Theodore Ts'o
2014-08-16 23:46 ` [PATCH 02/27] misc: fix gcc warnings Darrick J. Wong
2014-08-24 23:56   ` Theodore Ts'o
2014-08-16 23:46 ` [PATCH 03/27] libext2fs: byteswap inode when performing the sanity scan Darrick J. Wong
2014-08-25  2:01   ` Theodore Ts'o
2014-08-16 23:46 ` [PATCH 04/27] libext2fs: fix problems with LE<->BE conversions on BE platforms Darrick J. Wong
2014-08-25  2:01   ` Theodore Ts'o
2014-08-16 23:46 ` [PATCH 05/27] e2fsck: on BE, re-swap everything after a damaged dirent so salvage works correctly Darrick J. Wong
2014-08-25  2:03   ` Theodore Ts'o
2014-08-16 23:46 ` [PATCH 06/27] libext2fs: create inlinedata symlinks Darrick J. Wong
2014-08-25  2:05   ` Theodore Ts'o
2014-08-16 23:46 ` [PATCH 07/27] contrib: add script to help resync journal code with kernel Darrick J. Wong
2014-08-27  3:44   ` Theodore Ts'o
2014-08-16 23:46 ` [PATCH 08/27] e2fsck: resync jbd2 recovery code from Linux 3.16 Darrick J. Wong
2014-08-27  3:44   ` Theodore Ts'o
2014-08-16 23:46 ` [PATCH 09/27] e2fsck: resync jbd2 revoke " Darrick J. Wong
2014-08-27  3:44   ` Theodore Ts'o
2014-08-16 23:46 ` [PATCH 10/27] e2fsck: fix infinite loop when recovering corrupt journal blocks Darrick J. Wong
2014-08-27  3:45   ` Theodore Ts'o
2014-08-16 23:47 ` [PATCH 11/27] e2fsck/debugfs: fix descriptor block size handling errors with journal_csum Darrick J. Wong
2014-08-28  1:15   ` Theodore Ts'o
2014-08-28  1:33     ` Darrick J. Wong
2014-08-16 23:47 ` [PATCH 12/27] debugfs: create journal handling routines Darrick J. Wong
2014-08-16 23:47 ` [PATCH 13/27] e2fsck: set journal superblock s_sequence to tail_sequence Darrick J. Wong
2014-08-16 23:47 ` [PATCH 14/27] debugfs: add the ability to write transactions to the journal Darrick J. Wong
2014-09-06  5:52   ` Darrick J. Wong
2014-08-16 23:47 ` [PATCH 15/27] tests: test writing and recovering checksum-free 32/64bit journals Darrick J. Wong
2014-08-16 23:47 ` [PATCH 16/27] tests: test writing and recovering 64bit csum_v3 journals Darrick J. Wong
2014-08-16 23:47 ` [PATCH 17/27] tests: test writing and recovering 32bit " Darrick J. Wong
2014-08-16 23:47 ` [PATCH 18/27] tests: write and replay blocks with the old journal checksum Darrick J. Wong
2014-08-16 23:47 ` [PATCH 19/27] tests: test recovery of 32 and 64-bit journals with checksum v2 Darrick J. Wong
2014-08-16 23:48 ` [PATCH 20/27] tests: test how e2fsck recovers from corrupt journal superblocks Darrick J. Wong
2014-08-16 23:48 ` [PATCH 21/27] tests: test e2fsck recovery of corrupt revoke blocks Darrick J. Wong
2014-08-16 23:48 ` [PATCH 22/27] tests: test e2fsck recovery with broken commit blocks Darrick J. Wong
2014-08-16 23:48 ` [PATCH 23/27] tests: test e2fsck recovery of corrupt descriptor blocks Darrick J. Wong
2014-08-16 23:48 ` [PATCH 24/27] mke2fs: set block_validity as a default mount option Darrick J. Wong
2014-08-16 23:48 ` [PATCH 25/27] ext2fs: add readahead method to improve scanning Darrick J. Wong
2014-08-16 23:48 ` [PATCH 26/27] libext2fs/e2fsck: provide routines to read-ahead metadata Darrick J. Wong
2014-08-16 23:48 ` [PATCH 27/27] e2fsck: read-ahead metadata during passes 1, 2, and 4 Darrick J. Wong
2014-08-17 17:23 ` [PATCH 28/27] libext2fs: write_journal_inode should check iterate return value Darrick J. Wong

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.