Control: tags -1 -moreinfo thanks On Sun, Jun 06, 2021 at 06:18:27AM +0200, Paul Gevers wrote: > On 03-06-2021 22:06, Paul Gevers wrote: > > As I can't judge this myself, I'll take your word for it. If the upload > > can happen in the next couple of days, let's have this in unstable and > > if nothing is reported, have it in bullseye. > > Please removed the moreinfo tag once the package is available.
I've just uploaded the package to unstable. The debdiff is attached for your convenience. - Ted
diff -Nru e2fsprogs-1.46.2/debian/changelog e2fsprogs-1.46.2/debian/changelog --- e2fsprogs-1.46.2/debian/changelog 2021-02-28 21:24:34.000000000 -0500 +++ e2fsprogs-1.46.2/debian/changelog 2021-06-07 07:27:15.000000000 -0400 @@ -1,3 +1,18 @@ +e2fsprogs (1.46.2-2) unstable; urgency=medium + + * Fix FTBFS on arm32 when building on a system with an arm64 kernel. + This also fixes a portability problem when replaying a fast-commit + journal on an arm64 kernel when using an arm32 userspace. + (Closes: #987641) + * Fix additional fast-commit portability problems on non-x86 systems + which don't allow non-aligned pointer dereferences (for example, on a + sparc64 system). + * Fix a missing mutex unlock on an error path which can cause e2fsck + to hang on I/O errors. + * Clean up and improve the man page for e2image + + -- Theodore Y. Ts'o <ty...@mit.edu> Mon, 07 Jun 2021 07:27:15 -0400 + e2fsprogs (1.46.2-1) unstable; urgency=medium * New upstream release diff -Nru e2fsprogs-1.46.2/debian/patches/0001-e2fsck-fix-portability-problems-caused-by-unaligned-.patch e2fsprogs-1.46.2/debian/patches/0001-e2fsck-fix-portability-problems-caused-by-unaligned-.patch --- e2fsprogs-1.46.2/debian/patches/0001-e2fsck-fix-portability-problems-caused-by-unaligned-.patch 1969-12-31 19:00:00.000000000 -0500 +++ e2fsprogs-1.46.2/debian/patches/0001-e2fsck-fix-portability-problems-caused-by-unaligned-.patch 2021-06-07 07:27:15.000000000 -0400 @@ -0,0 +1,326 @@ +From 40960a7118171498448870b26d1c867f92fa430e Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o <ty...@mit.edu> +Date: Mon, 3 May 2021 15:37:33 -0400 +Subject: [PATCH 1/5] e2fsck: fix portability problems caused by unaligned + accesses + +The on-disk format for the ext4 journal can have unaigned 32-bit +integers. This can happen when replaying a journal using a obsolete +checksum format (which was never popularly used, since the v3 format +replaced v2 while the metadata checksum feature was being stablized), +and in the fast commit feature (which landed in the 5.10 kernel, +although it is not enabled by default). + +This commit fixes the following regression tests on some platforms +(such as running 32-bit arm architectures on a 64-bit arm kernel): +j_recover_csum2_32bit, j_recover_csum2_64bit, j_recover_fast_commit. + +https://github.com/tytso/e2fsprogs/issues/65 + +Addresses-Debian-Bug: #987641 +Signed-off-by: Theodore Ts'o <ty...@mit.edu> +--- + e2fsck/journal.c | 83 ++++++++++++++++-------------- + e2fsck/recovery.c | 22 ++++---- + tests/j_recover_fast_commit/script | 1 - + 3 files changed, 56 insertions(+), 50 deletions(-) + +diff --git a/e2fsck/journal.c b/e2fsck/journal.c +index a425bbd1..bd0e4f31 100644 +--- a/e2fsck/journal.c ++++ b/e2fsck/journal.c +@@ -286,9 +286,9 @@ static int ext4_fc_replay_scan(journal_t *j, struct buffer_head *bh, + int ret = JBD2_FC_REPLAY_CONTINUE; + struct ext4_fc_add_range *ext; + struct ext4_fc_tl *tl; +- struct ext4_fc_tail *tail; ++ struct ext4_fc_tail tail; + __u8 *start, *end; +- struct ext4_fc_head *head; ++ struct ext4_fc_head head; + struct ext2fs_extent ext2fs_ex = {0}; + + state = &ctx->fc_replay_state; +@@ -338,16 +338,15 @@ static int ext4_fc_replay_scan(journal_t *j, struct buffer_head *bh, + break; + case EXT4_FC_TAG_TAIL: + state->fc_cur_tag++; +- tail = (struct ext4_fc_tail *)ext4_fc_tag_val(tl); ++ memcpy(&tail, ext4_fc_tag_val(tl), sizeof(tail)); + state->fc_crc = jbd2_chksum(j, state->fc_crc, tl, + sizeof(*tl) + + offsetof(struct ext4_fc_tail, + fc_crc)); + jbd_debug(1, "tail tid %d, expected %d\n", +- le32_to_cpu(tail->fc_tid), +- expected_tid); +- if (le32_to_cpu(tail->fc_tid) == expected_tid && +- le32_to_cpu(tail->fc_crc) == state->fc_crc) { ++ le32_to_cpu(tail.fc_tid), expected_tid); ++ if (le32_to_cpu(tail.fc_tid) == expected_tid && ++ le32_to_cpu(tail.fc_crc) == state->fc_crc) { + state->fc_replay_num_tags = state->fc_cur_tag; + } else { + ret = state->fc_replay_num_tags ? +@@ -356,13 +355,13 @@ static int ext4_fc_replay_scan(journal_t *j, struct buffer_head *bh, + state->fc_crc = 0; + break; + case EXT4_FC_TAG_HEAD: +- head = (struct ext4_fc_head *)ext4_fc_tag_val(tl); +- if (le32_to_cpu(head->fc_features) & +- ~EXT4_FC_SUPPORTED_FEATURES) { ++ memcpy(&head, ext4_fc_tag_val(tl), sizeof(head)); ++ if (le32_to_cpu(head.fc_features) & ++ ~EXT4_FC_SUPPORTED_FEATURES) { + ret = -EOPNOTSUPP; + break; + } +- if (le32_to_cpu(head->fc_tid) != expected_tid) { ++ if (le32_to_cpu(head.fc_tid) != expected_tid) { + ret = -EINVAL; + break; + } +@@ -612,27 +611,31 @@ struct dentry_info_args { + char *dname; + }; + +-static inline void tl_to_darg(struct dentry_info_args *darg, ++static inline int tl_to_darg(struct dentry_info_args *darg, + struct ext4_fc_tl *tl) + { +- struct ext4_fc_dentry_info *fcd; ++ struct ext4_fc_dentry_info fcd; + int tag = le16_to_cpu(tl->fc_tag); + +- fcd = (struct ext4_fc_dentry_info *)ext4_fc_tag_val(tl); ++ memcpy(&fcd, ext4_fc_tag_val(tl), sizeof(fcd)); + +- darg->parent_ino = le32_to_cpu(fcd->fc_parent_ino); +- darg->ino = le32_to_cpu(fcd->fc_ino); +- darg->dname = (char *) fcd->fc_dname; ++ darg->parent_ino = le32_to_cpu(fcd.fc_parent_ino); ++ darg->ino = le32_to_cpu(fcd.fc_ino); + darg->dname_len = ext4_fc_tag_len(tl) - + sizeof(struct ext4_fc_dentry_info); + darg->dname = malloc(darg->dname_len + 1); +- memcpy(darg->dname, fcd->fc_dname, darg->dname_len); ++ if (!darg->dname) ++ return -ENOMEM; ++ memcpy(darg->dname, ++ ext4_fc_tag_val(tl) + sizeof(struct ext4_fc_dentry_info), ++ darg->dname_len); + darg->dname[darg->dname_len] = 0; + jbd_debug(1, "%s: %s, ino %d, parent %d\n", + tag == EXT4_FC_TAG_CREAT ? "create" : + (tag == EXT4_FC_TAG_LINK ? "link" : + (tag == EXT4_FC_TAG_UNLINK ? "unlink" : "error")), + darg->dname, darg->ino, darg->parent_ino); ++ return 0; + } + + static int ext4_fc_handle_unlink(e2fsck_t ctx, struct ext4_fc_tl *tl) +@@ -642,7 +645,9 @@ static int ext4_fc_handle_unlink(e2fsck_t ctx, struct ext4_fc_tl *tl) + ext2_filsys fs = ctx->fs; + int ret; + +- tl_to_darg(&darg, tl); ++ ret = tl_to_darg(&darg, tl); ++ if (ret) ++ return ret; + ext4_fc_flush_extents(ctx, darg.ino); + ret = errcode_to_errno( + ext2fs_unlink(ctx->fs, darg.parent_ino, +@@ -659,7 +664,9 @@ static int ext4_fc_handle_link_and_create(e2fsck_t ctx, struct ext4_fc_tl *tl) + struct ext2_inode_large inode_large; + int ret, filetype, mode; + +- tl_to_darg(&darg, tl); ++ ret = tl_to_darg(&darg, tl); ++ if (ret) ++ return ret; + ext4_fc_flush_extents(ctx, 0); + ret = errcode_to_errno(ext2fs_read_inode(fs, darg.ino, + (struct ext2_inode *)&inode_large)); +@@ -730,17 +737,18 @@ static int ext4_fc_handle_inode(e2fsck_t ctx, struct ext4_fc_tl *tl) + struct e2fsck_fc_replay_state *state = &ctx->fc_replay_state; + int ino, inode_len = EXT2_GOOD_OLD_INODE_SIZE; + struct ext2_inode_large *inode = NULL, *fc_inode = NULL; +- struct ext4_fc_inode *fc_inode_val; ++ __le32 fc_ino; ++ __u8 *fc_raw_inode; + errcode_t err; + blk64_t blks; + +- fc_inode_val = (struct ext4_fc_inode *)ext4_fc_tag_val(tl); +- ino = le32_to_cpu(fc_inode_val->fc_ino); ++ memcpy(&fc_ino, ext4_fc_tag_val(tl), sizeof(fc_ino)); ++ fc_raw_inode = ext4_fc_tag_val(tl) + sizeof(fc_ino); ++ ino = le32_to_cpu(fc_ino); + + if (EXT2_INODE_SIZE(ctx->fs->super) > EXT2_GOOD_OLD_INODE_SIZE) + inode_len += ext2fs_le16_to_cpu( +- ((struct ext2_inode_large *)fc_inode_val->fc_raw_inode) +- ->i_extra_isize); ++ ((struct ext2_inode_large *)fc_raw_inode)->i_extra_isize); + err = ext2fs_get_mem(inode_len, &inode); + if (err) + goto out; +@@ -755,10 +763,10 @@ static int ext4_fc_handle_inode(e2fsck_t ctx, struct ext4_fc_tl *tl) + goto out; + #ifdef WORDS_BIGENDIAN + ext2fs_swap_inode_full(ctx->fs, fc_inode, +- (struct ext2_inode_large *)fc_inode_val->fc_raw_inode, ++ (struct ext2_inode_large *)fc_raw_inode, + 0, sizeof(*inode)); + #else +- memcpy(fc_inode, fc_inode_val->fc_raw_inode, inode_len); ++ memcpy(fc_inode, fc_raw_inode, inode_len); + #endif + memcpy(inode, fc_inode, offsetof(struct ext2_inode_large, i_block)); + memcpy(&inode->i_generation, &fc_inode->i_generation, +@@ -792,12 +800,11 @@ out: + static int ext4_fc_handle_add_extent(e2fsck_t ctx, struct ext4_fc_tl *tl) + { + struct ext2fs_extent extent; +- struct ext4_fc_add_range *add_range; +- struct ext4_fc_del_range *del_range; ++ struct ext4_fc_add_range add_range; + int ret = 0, ino; + +- add_range = (struct ext4_fc_add_range *)ext4_fc_tag_val(tl); +- ino = le32_to_cpu(add_range->fc_ino); ++ memcpy(&add_range, ext4_fc_tag_val(tl), sizeof(add_range)); ++ ino = le32_to_cpu(add_range.fc_ino); + ext4_fc_flush_extents(ctx, ino); + + ret = ext4_fc_read_extents(ctx, ino); +@@ -805,8 +812,8 @@ static int ext4_fc_handle_add_extent(e2fsck_t ctx, struct ext4_fc_tl *tl) + return ret; + memset(&extent, 0, sizeof(extent)); + ret = errcode_to_errno(ext2fs_decode_extent( +- &extent, (void *)(add_range->fc_ex), +- sizeof(add_range->fc_ex))); ++ &extent, (void *)add_range.fc_ex, ++ sizeof(add_range.fc_ex))); + if (ret) + return ret; + return ext4_add_extent_to_list(ctx, +@@ -819,16 +826,16 @@ static int ext4_fc_handle_add_extent(e2fsck_t ctx, struct ext4_fc_tl *tl) + static int ext4_fc_handle_del_range(e2fsck_t ctx, struct ext4_fc_tl *tl) + { + struct ext2fs_extent extent; +- struct ext4_fc_del_range *del_range; ++ struct ext4_fc_del_range del_range; + int ret, ino; + +- del_range = (struct ext4_fc_del_range *)ext4_fc_tag_val(tl); +- ino = le32_to_cpu(del_range->fc_ino); ++ memcpy(&del_range, ext4_fc_tag_val(tl), sizeof(del_range)); ++ ino = le32_to_cpu(del_range.fc_ino); + ext4_fc_flush_extents(ctx, ino); + + memset(&extent, 0, sizeof(extent)); +- extent.e_lblk = ext2fs_le32_to_cpu(del_range->fc_lblk); +- extent.e_len = ext2fs_le32_to_cpu(del_range->fc_len); ++ extent.e_lblk = le32_to_cpu(del_range.fc_lblk); ++ extent.e_len = le32_to_cpu(del_range.fc_len); + ret = ext4_fc_read_extents(ctx, ino); + if (ret) + return ret; +diff --git a/e2fsck/recovery.c b/e2fsck/recovery.c +index dc0694fc..02694d2c 100644 +--- a/e2fsck/recovery.c ++++ b/e2fsck/recovery.c +@@ -196,7 +196,7 @@ static int jbd2_descriptor_block_csum_verify(journal_t *j, void *buf) + static int count_tags(journal_t *journal, struct buffer_head *bh) + { + char * tagp; +- journal_block_tag_t * tag; ++ journal_block_tag_t tag; + int nr = 0, size = journal->j_blocksize; + int tag_bytes = journal_tag_bytes(journal); + +@@ -206,14 +206,14 @@ static int count_tags(journal_t *journal, struct buffer_head *bh) + tagp = &bh->b_data[sizeof(journal_header_t)]; + + while ((tagp - bh->b_data + tag_bytes) <= size) { +- tag = (journal_block_tag_t *) tagp; ++ memcpy(&tag, tagp, sizeof(tag)); + + nr++; + tagp += tag_bytes; +- if (!(tag->t_flags & cpu_to_be16(JBD2_FLAG_SAME_UUID))) ++ if (!(tag.t_flags & cpu_to_be16(JBD2_FLAG_SAME_UUID))) + tagp += 16; + +- if (tag->t_flags & cpu_to_be16(JBD2_FLAG_LAST_TAG)) ++ if (tag.t_flags & cpu_to_be16(JBD2_FLAG_LAST_TAG)) + break; + } + +@@ -434,9 +434,9 @@ 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, ++ journal_block_tag3_t *tag3, + void *buf, __u32 sequence) + { +- journal_block_tag3_t *tag3 = (journal_block_tag3_t *)tag; + __u32 csum32; + __be32 seq; + +@@ -497,7 +497,7 @@ static int do_one_pass(journal_t *journal, + while (1) { + int flags; + char * tagp; +- journal_block_tag_t * tag; ++ journal_block_tag_t tag; + struct buffer_head * obh; + struct buffer_head * nbh; + +@@ -614,8 +614,8 @@ static int do_one_pass(journal_t *journal, + <= journal->j_blocksize - descr_csum_size) { + unsigned long io_block; + +- tag = (journal_block_tag_t *) tagp; +- flags = be16_to_cpu(tag->t_flags); ++ memcpy(&tag, tagp, sizeof(tag)); ++ flags = be16_to_cpu(tag.t_flags); + + io_block = next_log_block++; + wrap(journal, next_log_block); +@@ -633,7 +633,7 @@ static int do_one_pass(journal_t *journal, + + J_ASSERT(obh != NULL); + blocknr = read_tag_block(journal, +- tag); ++ &tag); + + /* If the block has been + * revoked, then we're all done +@@ -648,8 +648,8 @@ 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))) { ++ journal, &tag, (journal_block_tag3_t *)tagp, ++ obh->b_data, be32_to_cpu(tmp->h_sequence))) { + brelse(obh); + success = -EFSBADCRC; + printk(KERN_ERR "JBD2: Invalid " +diff --git a/tests/j_recover_fast_commit/script b/tests/j_recover_fast_commit/script +index 22ef6325..05c40cc5 100755 +--- a/tests/j_recover_fast_commit/script ++++ b/tests/j_recover_fast_commit/script +@@ -10,7 +10,6 @@ gunzip < $IMAGE > $TMPFILE + EXP=$test_dir/expect + OUT=$test_name.log + +-cp $TMPFILE /tmp/debugthis + $FSCK $FSCK_OPT -E journal_only -N test_filesys $TMPFILE 2>/dev/null | head -n 1000 | tail -n +2 > $OUT + echo "Exit status is $?" >> $OUT + +-- +2.31.0 + diff -Nru e2fsprogs-1.46.2/debian/patches/0002-e2fsck-fix-unaligned-accesses-to-ext4_fc_tl-struct.patch e2fsprogs-1.46.2/debian/patches/0002-e2fsck-fix-unaligned-accesses-to-ext4_fc_tl-struct.patch --- e2fsprogs-1.46.2/debian/patches/0002-e2fsck-fix-unaligned-accesses-to-ext4_fc_tl-struct.patch 1969-12-31 19:00:00.000000000 -0500 +++ e2fsprogs-1.46.2/debian/patches/0002-e2fsck-fix-unaligned-accesses-to-ext4_fc_tl-struct.patch 2021-06-07 07:27:15.000000000 -0400 @@ -0,0 +1,389 @@ +From 440e465618f080b2742fccc3b6ae327e306aeab0 Mon Sep 17 00:00:00 2001 +From: Harshad Shirwadkar <harshadshirwad...@gmail.com> +Date: Thu, 6 May 2021 17:21:10 -0700 +Subject: [PATCH 2/5] e2fsck: fix unaligned accesses to ext4_fc_tl struct + +Fast commit related struct ext4_fc_tl can be unaligned on disk. So, +while accessing that we should ensure that the pointers are +aligned. This patch fixes unaligned accesses to ext4_fc_tl and also +gets rid of macros fc_for_each_tl and ext4_fc_tag_val that may result +in unaligned accesses to struct ext4_fc_tl. + +Signed-off-by: Harshad Shirwadkar <harshadshirwad...@gmail.com> +Signed-off-by: Theodore Ts'o <ty...@mit.edu> +--- + debugfs/logdump.c | 42 ++++++++++---------- + e2fsck/journal.c | 82 +++++++++++++++++++++------------------- + lib/ext2fs/fast_commit.h | 13 ------- + 3 files changed, 65 insertions(+), 72 deletions(-) + +diff --git a/debugfs/logdump.c b/debugfs/logdump.c +index 27e2e72d..6aee1a12 100644 +--- a/debugfs/logdump.c ++++ b/debugfs/logdump.c +@@ -551,24 +551,28 @@ static inline size_t journal_super_tag_bytes(journal_superblock_t *jsb) + static void dump_fc_block(FILE *out_file, char *buf, int blocksize, + int transaction, int *fc_done, int dump_old) + { +- struct ext4_fc_tl *tl; ++ struct ext4_fc_tl tl; + struct ext4_fc_head *head; + struct ext4_fc_add_range *add_range; + struct ext4_fc_del_range *del_range; + struct ext4_fc_dentry_info *dentry_info; + struct ext4_fc_tail *tail; + struct ext3_extent *ex; ++ __u8 *cur, *val; + + *fc_done = 0; +- fc_for_each_tl(buf, buf + blocksize, tl) { +- switch (le16_to_cpu(tl->fc_tag)) { ++ for (cur = (__u8 *)buf; cur < (__u8 *)buf + blocksize; ++ cur = cur + sizeof(tl) + le16_to_cpu(tl.fc_len)) { ++ memcpy(&tl, cur, sizeof(tl)); ++ val = cur + sizeof(tl); ++ ++ switch (le16_to_cpu(tl.fc_tag)) { + case EXT4_FC_TAG_ADD_RANGE: +- add_range = +- (struct ext4_fc_add_range *)ext4_fc_tag_val(tl); ++ add_range = (struct ext4_fc_add_range *)val; + ex = (struct ext3_extent *)add_range->fc_ex; + fprintf(out_file, + "tag %s, inode %d, lblk %u, pblk %llu, len %lu\n", +- tag2str(tl->fc_tag), ++ tag2str(tl.fc_tag), + le32_to_cpu(add_range->fc_ino), + le32_to_cpu(ex->ee_block), + le32_to_cpu(ex->ee_start) + +@@ -578,10 +582,9 @@ static void dump_fc_block(FILE *out_file, char *buf, int blocksize, + le16_to_cpu(ex->ee_len)); + break; + case EXT4_FC_TAG_DEL_RANGE: +- del_range = +- (struct ext4_fc_del_range *)ext4_fc_tag_val(tl); ++ del_range = (struct ext4_fc_del_range *)val; + fprintf(out_file, "tag %s, inode %d, lblk %d, len %d\n", +- tag2str(tl->fc_tag), ++ tag2str(tl.fc_tag), + le32_to_cpu(del_range->fc_ino), + le32_to_cpu(del_range->fc_lblk), + le32_to_cpu(del_range->fc_len)); +@@ -589,29 +592,26 @@ static void dump_fc_block(FILE *out_file, char *buf, int blocksize, + case EXT4_FC_TAG_LINK: + case EXT4_FC_TAG_UNLINK: + case EXT4_FC_TAG_CREAT: +- dentry_info = +- (struct ext4_fc_dentry_info *) +- ext4_fc_tag_val(tl); ++ dentry_info = (struct ext4_fc_dentry_info *)val; + fprintf(out_file, + "tag %s, parent %d, ino %d, name \"%s\"\n", +- tag2str(tl->fc_tag), ++ tag2str(tl.fc_tag), + le32_to_cpu(dentry_info->fc_parent_ino), + le32_to_cpu(dentry_info->fc_ino), + dentry_info->fc_dname); + break; + case EXT4_FC_TAG_INODE: + fprintf(out_file, "tag %s, inode %d\n", +- tag2str(tl->fc_tag), +- le32_to_cpu(((struct ext4_fc_inode *) +- ext4_fc_tag_val(tl))->fc_ino)); ++ tag2str(tl.fc_tag), ++ le32_to_cpu(((struct ext4_fc_inode *)val)->fc_ino)); + break; + case EXT4_FC_TAG_PAD: +- fprintf(out_file, "tag %s\n", tag2str(tl->fc_tag)); ++ fprintf(out_file, "tag %s\n", tag2str(tl.fc_tag)); + break; + case EXT4_FC_TAG_TAIL: +- tail = (struct ext4_fc_tail *)ext4_fc_tag_val(tl); ++ tail = (struct ext4_fc_tail *)val; + fprintf(out_file, "tag %s, tid %d\n", +- tag2str(tl->fc_tag), ++ tag2str(tl.fc_tag), + le32_to_cpu(tail->fc_tid)); + if (!dump_old && + le32_to_cpu(tail->fc_tid) < transaction) { +@@ -621,9 +621,9 @@ static void dump_fc_block(FILE *out_file, char *buf, int blocksize, + break; + case EXT4_FC_TAG_HEAD: + fprintf(out_file, "\n*** Fast Commit Area ***\n"); +- head = (struct ext4_fc_head *)ext4_fc_tag_val(tl); ++ head = (struct ext4_fc_head *)val; + fprintf(out_file, "tag %s, features 0x%x, tid %d\n", +- tag2str(tl->fc_tag), ++ tag2str(tl.fc_tag), + le32_to_cpu(head->fc_features), + le32_to_cpu(head->fc_tid)); + if (!dump_old && +diff --git a/e2fsck/journal.c b/e2fsck/journal.c +index bd0e4f31..ae3df800 100644 +--- a/e2fsck/journal.c ++++ b/e2fsck/journal.c +@@ -285,9 +285,9 @@ static int ext4_fc_replay_scan(journal_t *j, struct buffer_head *bh, + struct e2fsck_fc_replay_state *state; + int ret = JBD2_FC_REPLAY_CONTINUE; + struct ext4_fc_add_range *ext; +- struct ext4_fc_tl *tl; ++ struct ext4_fc_tl tl; + struct ext4_fc_tail tail; +- __u8 *start, *end; ++ __u8 *start, *cur, *end, *val; + struct ext4_fc_head head; + struct ext2fs_extent ext2fs_ex = {0}; + +@@ -313,12 +313,15 @@ static int ext4_fc_replay_scan(journal_t *j, struct buffer_head *bh, + } + + state->fc_replay_expected_off++; +- fc_for_each_tl(start, end, tl) { ++ for (cur = start; cur < end; cur = cur + le16_to_cpu(tl.fc_len) + sizeof(tl)) { ++ memcpy(&tl, cur, sizeof(tl)); ++ val = cur + sizeof(tl); ++ + jbd_debug(3, "Scan phase, tag:%s, blk %lld\n", +- tag2str(le16_to_cpu(tl->fc_tag)), bh->b_blocknr); +- switch (le16_to_cpu(tl->fc_tag)) { ++ tag2str(le16_to_cpu(tl.fc_tag)), bh->b_blocknr); ++ switch (le16_to_cpu(tl.fc_tag)) { + case EXT4_FC_TAG_ADD_RANGE: +- ext = (struct ext4_fc_add_range *)ext4_fc_tag_val(tl); ++ ext = (struct ext4_fc_add_range *)val; + ret = ext2fs_decode_extent(&ext2fs_ex, (void *)&ext->fc_ex, + sizeof(ext->fc_ex)); + if (ret) +@@ -333,14 +336,14 @@ static int ext4_fc_replay_scan(journal_t *j, struct buffer_head *bh, + case EXT4_FC_TAG_INODE: + case EXT4_FC_TAG_PAD: + state->fc_cur_tag++; +- state->fc_crc = jbd2_chksum(j, state->fc_crc, tl, +- sizeof(*tl) + ext4_fc_tag_len(tl)); ++ state->fc_crc = jbd2_chksum(j, state->fc_crc, cur, ++ sizeof(tl) + ext4_fc_tag_len(&tl)); + break; + case EXT4_FC_TAG_TAIL: + state->fc_cur_tag++; +- memcpy(&tail, ext4_fc_tag_val(tl), sizeof(tail)); +- state->fc_crc = jbd2_chksum(j, state->fc_crc, tl, +- sizeof(*tl) + ++ memcpy(&tail, val, sizeof(tail)); ++ state->fc_crc = jbd2_chksum(j, state->fc_crc, cur, ++ sizeof(tl) + + offsetof(struct ext4_fc_tail, + fc_crc)); + jbd_debug(1, "tail tid %d, expected %d\n", +@@ -355,7 +358,7 @@ static int ext4_fc_replay_scan(journal_t *j, struct buffer_head *bh, + state->fc_crc = 0; + break; + case EXT4_FC_TAG_HEAD: +- memcpy(&head, ext4_fc_tag_val(tl), sizeof(head)); ++ memcpy(&head, val, sizeof(head)); + if (le32_to_cpu(head.fc_features) & + ~EXT4_FC_SUPPORTED_FEATURES) { + ret = -EOPNOTSUPP; +@@ -366,8 +369,8 @@ static int ext4_fc_replay_scan(journal_t *j, struct buffer_head *bh, + break; + } + state->fc_cur_tag++; +- state->fc_crc = jbd2_chksum(j, state->fc_crc, tl, +- sizeof(*tl) + ext4_fc_tag_len(tl)); ++ state->fc_crc = jbd2_chksum(j, state->fc_crc, cur, ++ sizeof(tl) + ext4_fc_tag_len(&tl)); + break; + default: + ret = state->fc_replay_num_tags ? +@@ -612,12 +615,12 @@ struct dentry_info_args { + }; + + static inline int tl_to_darg(struct dentry_info_args *darg, +- struct ext4_fc_tl *tl) ++ struct ext4_fc_tl *tl, __u8 *val) + { + struct ext4_fc_dentry_info fcd; + int tag = le16_to_cpu(tl->fc_tag); + +- memcpy(&fcd, ext4_fc_tag_val(tl), sizeof(fcd)); ++ memcpy(&fcd, val, sizeof(fcd)); + + darg->parent_ino = le32_to_cpu(fcd.fc_parent_ino); + darg->ino = le32_to_cpu(fcd.fc_ino); +@@ -627,7 +630,7 @@ static inline int tl_to_darg(struct dentry_info_args *darg, + if (!darg->dname) + return -ENOMEM; + memcpy(darg->dname, +- ext4_fc_tag_val(tl) + sizeof(struct ext4_fc_dentry_info), ++ val + sizeof(struct ext4_fc_dentry_info), + darg->dname_len); + darg->dname[darg->dname_len] = 0; + jbd_debug(1, "%s: %s, ino %d, parent %d\n", +@@ -638,14 +641,14 @@ static inline int tl_to_darg(struct dentry_info_args *darg, + return 0; + } + +-static int ext4_fc_handle_unlink(e2fsck_t ctx, struct ext4_fc_tl *tl) ++static int ext4_fc_handle_unlink(e2fsck_t ctx, struct ext4_fc_tl *tl, __u8 *val) + { + struct ext2_inode inode; + struct dentry_info_args darg; + ext2_filsys fs = ctx->fs; + int ret; + +- ret = tl_to_darg(&darg, tl); ++ ret = tl_to_darg(&darg, tl, val); + if (ret) + return ret; + ext4_fc_flush_extents(ctx, darg.ino); +@@ -657,14 +660,14 @@ static int ext4_fc_handle_unlink(e2fsck_t ctx, struct ext4_fc_tl *tl) + return ret; + } + +-static int ext4_fc_handle_link_and_create(e2fsck_t ctx, struct ext4_fc_tl *tl) ++static int ext4_fc_handle_link_and_create(e2fsck_t ctx, struct ext4_fc_tl *tl, __u8 *val) + { + struct dentry_info_args darg; + ext2_filsys fs = ctx->fs; + struct ext2_inode_large inode_large; + int ret, filetype, mode; + +- ret = tl_to_darg(&darg, tl); ++ ret = tl_to_darg(&darg, tl, val); + if (ret) + return ret; + ext4_fc_flush_extents(ctx, 0); +@@ -732,7 +735,7 @@ static void ext4_fc_replay_fixup_iblocks(struct ext2_inode_large *ondisk_inode, + } + } + +-static int ext4_fc_handle_inode(e2fsck_t ctx, struct ext4_fc_tl *tl) ++static int ext4_fc_handle_inode(e2fsck_t ctx, __u8 *val) + { + struct e2fsck_fc_replay_state *state = &ctx->fc_replay_state; + int ino, inode_len = EXT2_GOOD_OLD_INODE_SIZE; +@@ -742,8 +745,8 @@ static int ext4_fc_handle_inode(e2fsck_t ctx, struct ext4_fc_tl *tl) + errcode_t err; + blk64_t blks; + +- memcpy(&fc_ino, ext4_fc_tag_val(tl), sizeof(fc_ino)); +- fc_raw_inode = ext4_fc_tag_val(tl) + sizeof(fc_ino); ++ memcpy(&fc_ino, val, sizeof(fc_ino)); ++ fc_raw_inode = val + sizeof(fc_ino); + ino = le32_to_cpu(fc_ino); + + if (EXT2_INODE_SIZE(ctx->fs->super) > EXT2_GOOD_OLD_INODE_SIZE) +@@ -797,13 +800,13 @@ out: + /* + * Handle add extent replay tag. + */ +-static int ext4_fc_handle_add_extent(e2fsck_t ctx, struct ext4_fc_tl *tl) ++static int ext4_fc_handle_add_extent(e2fsck_t ctx, __u8 *val) + { + struct ext2fs_extent extent; + struct ext4_fc_add_range add_range; + int ret = 0, ino; + +- memcpy(&add_range, ext4_fc_tag_val(tl), sizeof(add_range)); ++ memcpy(&add_range, val, sizeof(add_range)); + ino = le32_to_cpu(add_range.fc_ino); + ext4_fc_flush_extents(ctx, ino); + +@@ -823,13 +826,13 @@ static int ext4_fc_handle_add_extent(e2fsck_t ctx, struct ext4_fc_tl *tl) + /* + * Handle delete logical range replay tag. + */ +-static int ext4_fc_handle_del_range(e2fsck_t ctx, struct ext4_fc_tl *tl) ++static int ext4_fc_handle_del_range(e2fsck_t ctx, __u8 *val) + { + struct ext2fs_extent extent; + struct ext4_fc_del_range del_range; + int ret, ino; + +- memcpy(&del_range, ext4_fc_tag_val(tl), sizeof(del_range)); ++ memcpy(&del_range, val, sizeof(del_range)); + ino = le32_to_cpu(del_range.fc_ino); + ext4_fc_flush_extents(ctx, ino); + +@@ -854,8 +857,8 @@ static int ext4_fc_replay(journal_t *journal, struct buffer_head *bh, + e2fsck_t ctx = journal->j_fs_dev->k_ctx; + struct e2fsck_fc_replay_state *state = &ctx->fc_replay_state; + int ret = JBD2_FC_REPLAY_CONTINUE; +- struct ext4_fc_tl *tl; +- __u8 *start, *end; ++ struct ext4_fc_tl tl; ++ __u8 *start, *end, *cur, *val; + + if (pass == PASS_SCAN) { + state->fc_current_pass = PASS_SCAN; +@@ -891,28 +894,31 @@ static int ext4_fc_replay(journal_t *journal, struct buffer_head *bh, + start = (__u8 *)bh->b_data; + end = (__u8 *)bh->b_data + journal->j_blocksize - 1; + +- fc_for_each_tl(start, end, tl) { ++ for (cur = start; cur < end; cur = cur + le16_to_cpu(tl.fc_len) + sizeof(tl)) { ++ memcpy(&tl, cur, sizeof(tl)); ++ val = cur + sizeof(tl); ++ + if (state->fc_replay_num_tags == 0) + goto replay_done; + jbd_debug(3, "Replay phase processing %s tag\n", +- tag2str(le16_to_cpu(tl->fc_tag))); ++ tag2str(le16_to_cpu(tl.fc_tag))); + state->fc_replay_num_tags--; +- switch (le16_to_cpu(tl->fc_tag)) { ++ switch (le16_to_cpu(tl.fc_tag)) { + case EXT4_FC_TAG_CREAT: + case EXT4_FC_TAG_LINK: +- ret = ext4_fc_handle_link_and_create(ctx, tl); ++ ret = ext4_fc_handle_link_and_create(ctx, &tl, val); + break; + case EXT4_FC_TAG_UNLINK: +- ret = ext4_fc_handle_unlink(ctx, tl); ++ ret = ext4_fc_handle_unlink(ctx, &tl, val); + break; + case EXT4_FC_TAG_ADD_RANGE: +- ret = ext4_fc_handle_add_extent(ctx, tl); ++ ret = ext4_fc_handle_add_extent(ctx, val); + break; + case EXT4_FC_TAG_DEL_RANGE: +- ret = ext4_fc_handle_del_range(ctx, tl); ++ ret = ext4_fc_handle_del_range(ctx, val); + break; + case EXT4_FC_TAG_INODE: +- ret = ext4_fc_handle_inode(ctx, tl); ++ ret = ext4_fc_handle_inode(ctx, val); + break; + case EXT4_FC_TAG_TAIL: + ext4_fc_flush_extents(ctx, 0); +diff --git a/lib/ext2fs/fast_commit.h b/lib/ext2fs/fast_commit.h +index b83e1810..4ad38f12 100644 +--- a/lib/ext2fs/fast_commit.h ++++ b/lib/ext2fs/fast_commit.h +@@ -155,13 +155,6 @@ struct ext4_fc_replay_state { + #define region_last(__region) (((__region)->lblk) + ((__region)->len) - 1) + #endif + +-#define fc_for_each_tl(__start, __end, __tl) \ +- for (tl = (struct ext4_fc_tl *)(__start); \ +- (__u8 *)tl < (__u8 *)(__end); \ +- tl = (struct ext4_fc_tl *)((__u8 *)tl + \ +- sizeof(struct ext4_fc_tl) + \ +- + le16_to_cpu(tl->fc_len))) +- + static inline const char *tag2str(__u16 tag) + { + switch (tag) { +@@ -194,10 +187,4 @@ static inline int ext4_fc_tag_len(struct ext4_fc_tl *tl) + return le16_to_cpu(tl->fc_len); + } + +-/* Get a pointer to "value" of a tlv */ +-static inline __u8 *ext4_fc_tag_val(struct ext4_fc_tl *tl) +-{ +- return (__u8 *)tl + sizeof(*tl); +-} +- + #endif /* __FAST_COMMIT_H__ */ +-- +2.31.0 + diff -Nru e2fsprogs-1.46.2/debian/patches/0003-e2fsck-fix-unaligned-accesses-to-ext4_fc_add_range-a.patch e2fsprogs-1.46.2/debian/patches/0003-e2fsck-fix-unaligned-accesses-to-ext4_fc_add_range-a.patch --- e2fsprogs-1.46.2/debian/patches/0003-e2fsck-fix-unaligned-accesses-to-ext4_fc_add_range-a.patch 1969-12-31 19:00:00.000000000 -0500 +++ e2fsprogs-1.46.2/debian/patches/0003-e2fsck-fix-unaligned-accesses-to-ext4_fc_add_range-a.patch 2021-06-07 07:27:15.000000000 -0400 @@ -0,0 +1,63 @@ +From 8188d943e51290e7edce0b6e462021504afdf3e6 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o <ty...@mit.edu> +Date: Thu, 6 May 2021 22:40:57 -0400 +Subject: [PATCH 3/5] e2fsck: fix unaligned accesses to ext4_fc_add_range and + fc_raw_inode + +These fast commit related structures can be unaligned on disk. So we +need to avoid accessing these structures directly, and first copy +them to memory which we know is appropriately aligned. + +This fixes an e2fsck crash while running the j_recovery_fast_commit +regression test on a sparc64 system. + +Signed-off-by: Theodore Ts'o <ty...@mit.edu> +--- + e2fsck/journal.c | 16 +++++++--------- + 1 file changed, 7 insertions(+), 9 deletions(-) + +diff --git a/e2fsck/journal.c b/e2fsck/journal.c +index ae3df800..0128fbd3 100644 +--- a/e2fsck/journal.c ++++ b/e2fsck/journal.c +@@ -284,7 +284,7 @@ static int ext4_fc_replay_scan(journal_t *j, struct buffer_head *bh, + e2fsck_t ctx = j->j_fs_dev->k_ctx; + struct e2fsck_fc_replay_state *state; + int ret = JBD2_FC_REPLAY_CONTINUE; +- struct ext4_fc_add_range *ext; ++ struct ext4_fc_add_range ext; + struct ext4_fc_tl tl; + struct ext4_fc_tail tail; + __u8 *start, *cur, *end, *val; +@@ -321,9 +321,10 @@ static int ext4_fc_replay_scan(journal_t *j, struct buffer_head *bh, + tag2str(le16_to_cpu(tl.fc_tag)), bh->b_blocknr); + switch (le16_to_cpu(tl.fc_tag)) { + case EXT4_FC_TAG_ADD_RANGE: +- ext = (struct ext4_fc_add_range *)val; +- ret = ext2fs_decode_extent(&ext2fs_ex, (void *)&ext->fc_ex, +- sizeof(ext->fc_ex)); ++ memcpy(&ext, val, sizeof(ext)); ++ ret = ext2fs_decode_extent(&ext2fs_ex, ++ (void *)&ext.fc_ex, ++ sizeof(ext.fc_ex)); + if (ret) + ret = JBD2_FC_REPLAY_STOP; + else +@@ -764,12 +765,9 @@ static int ext4_fc_handle_inode(e2fsck_t ctx, __u8 *val) + inode_len); + if (err) + goto out; +-#ifdef WORDS_BIGENDIAN +- ext2fs_swap_inode_full(ctx->fs, fc_inode, +- (struct ext2_inode_large *)fc_raw_inode, +- 0, sizeof(*inode)); +-#else + memcpy(fc_inode, fc_raw_inode, inode_len); ++#ifdef WORDS_BIGENDIAN ++ ext2fs_swap_inode_full(ctx->fs, fc_inode, fc_inode, 0, inode_len); + #endif + memcpy(inode, fc_inode, offsetof(struct ext2_inode_large, i_block)); + memcpy(&inode->i_generation, &fc_inode->i_generation, +-- +2.31.0 + diff -Nru e2fsprogs-1.46.2/debian/patches/0004-libext2fs-fix-missing-mutex-unlock-in-an-error-path-.patch e2fsprogs-1.46.2/debian/patches/0004-libext2fs-fix-missing-mutex-unlock-in-an-error-path-.patch --- e2fsprogs-1.46.2/debian/patches/0004-libext2fs-fix-missing-mutex-unlock-in-an-error-path-.patch 1969-12-31 19:00:00.000000000 -0500 +++ e2fsprogs-1.46.2/debian/patches/0004-libext2fs-fix-missing-mutex-unlock-in-an-error-path-.patch 2021-06-07 07:27:15.000000000 -0400 @@ -0,0 +1,30 @@ +From c9b85b3453d54181cf0bb9beab4056ccff7d1733 Mon Sep 17 00:00:00 2001 +From: Alexander Kanavin <alex.kana...@gmail.com> +Date: Fri, 30 Apr 2021 23:45:56 +0200 +Subject: [PATCH 4/5] libext2fs: fix missing mutex unlock in an error path of + the Unix I/O manager + +Originally from https://github.com/tytso/e2fsprogs/pull/68 + +Signed-off-by: Alexander Kanavin <alex.kana...@gmail.com> +Signed-off-by: Theodore Ts'o <ty...@mit.edu> +--- + lib/ext2fs/unix_io.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c +index 64eee342..528c2fbc 100644 +--- a/lib/ext2fs/unix_io.c ++++ b/lib/ext2fs/unix_io.c +@@ -398,7 +398,7 @@ static errcode_t raw_write_blk(io_channel channel, + mutex_lock(data, BOUNCE_MTX); + if (ext2fs_llseek(data->dev, location, SEEK_SET) < 0) { + retval = errno ? errno : EXT2_ET_LLSEEK_FAILED; +- goto error_out; ++ goto error_unlock; + } + actual = write(data->dev, buf, size); + mutex_unlock(data, BOUNCE_MTX); +-- +2.31.0 + diff -Nru e2fsprogs-1.46.2/debian/patches/0005-e2image-add-OPTIONS-section-to-man-page.patch e2fsprogs-1.46.2/debian/patches/0005-e2image-add-OPTIONS-section-to-man-page.patch --- e2fsprogs-1.46.2/debian/patches/0005-e2image-add-OPTIONS-section-to-man-page.patch 1969-12-31 19:00:00.000000000 -0500 +++ e2fsprogs-1.46.2/debian/patches/0005-e2image-add-OPTIONS-section-to-man-page.patch 2021-06-07 07:27:15.000000000 -0400 @@ -0,0 +1,504 @@ +From 040cf161ae70c375218ca47ef7e4d3b37316df71 Mon Sep 17 00:00:00 2001 +From: Andreas Dilger <adil...@dilger.ca> +Date: Tue, 9 Mar 2021 01:35:08 -0700 +Subject: [PATCH 5/5] e2image: add OPTIONS section to man page + +Reorganize the e2image.8 man page so that the command-line options +are listed in a dedicated OPTIONS section, rather than being +interspersed among the text in the DESCRIPTION section. Otherwise, +it is difficult to determine which options are available, and to +find where each option is described. + +Signed-off-by: Andreas Dilger <adil...@dilger.ca> +Signed-off-by: Theodore Ts'o <ty...@mit.edu> +--- + misc/e2image.8.in | 350 ++++++++++++++++++++++++---------------------- + 1 file changed, 184 insertions(+), 166 deletions(-) + +diff --git a/misc/e2image.8.in b/misc/e2image.8.in +index ef124867..cb176f5d 100644 +--- a/misc/e2image.8.in ++++ b/misc/e2image.8.in +@@ -1,18 +1,14 @@ + .\" -*- nroff -*- + .\" Copyright 2001 by Theodore Ts'o. All Rights Reserved. + .\" This file may be copied under the terms of the GNU Public License. +-.\" ++.\" + .TH E2IMAGE 8 "@E2FSPROGS_MONTH@ @E2FSPROGS_YEAR@" "E2fsprogs version @E2FSPROGS_VERSION@" + .SH NAME + e2image \- Save critical ext2/ext3/ext4 filesystem metadata to a file ++ + .SH SYNOPSIS + .B e2image +-[ +-.B \-r|\-Q +-] +-[ +-.B \-f +-] ++.RB [ \-r | \-Q " [" \-af ]] + [ + .B \-b + .I superblock +@@ -21,18 +17,8 @@ e2image \- Save critical ext2/ext3/ext4 filesystem metadata to a file + .B \-B + .I blocksize + ] +-.I device +-.I image-file +-.br +-.B e2image +-.B \-I +-.I device +-.I image-file +-.br +-.B e2image +-.B \-ra + [ +-.B \-cfnp ++.B \-cnps + ] + [ + .B \-o +@@ -42,10 +28,14 @@ e2image \- Save critical ext2/ext3/ext4 filesystem metadata to a file + .B \-O + .I dest_offset + ] +-.I src_fs +-[ +-.I dest_fs +-] ++.I device ++.I image-file ++.br ++.B e2image ++.B \-I ++.I device ++.I image-file ++ + .SH DESCRIPTION + The + .B e2image +@@ -59,40 +49,11 @@ and + .BR debugfs , + by using the + .B \-i +-option to those programs. This can assist an expert in +-recovering catastrophically corrupted filesystems. In the future, +-e2fsck will be enhanced to be able to use the image file to help +-recover a badly damaged filesystem. ++option to those programs. This can assist an expert in recovering ++catastrophically corrupted filesystems. + .PP +-When saving an e2image for debugging purposes, using either the +-.B \-r +-or +-.B \-Q +-options, the filesystem must be unmounted or be mounted read/only, in order +-for the image file to be in a consistent state. This requirement can be +-overridden using the +-.B \-f +-option, but the resulting image file is very likely not going to be useful. +-.PP +-If +-.I image-file +-is \-, then the output of +-.B e2image +-will be sent to standard output, so that the output can be piped to +-another program, such as +-.BR gzip (1). +-(Note that this is currently only supported when +-creating a raw image file using the +-.B \-r +-option, since the process of creating a normal image file, or QCOW2 +-image currently +-requires random access to the file, which cannot be done using a +-pipe. This restriction will hopefully be lifted in a future version of +-.BR e2image .) +-.PP +-It is a very good idea to create image files for all of +-filesystems on a system and save the partition +-layout (which can be generated using the ++It is a very good idea to create image files for all filesystems on a ++system and save the partition layout (which can be generated using the + .B fdisk \-l + command) at regular intervals --- at boot time, and/or every week or so. + The image file should be stored on some filesystem other than +@@ -101,31 +62,95 @@ accessible in the case where the filesystem has been badly damaged. + .PP + To save disk space, + .B e2image +-creates the image file as a sparse file, or in QCOW2 format. +-Hence, if the sparse image file +-needs to be copied to another location, it should ++creates the image file as a sparse file, or in QCOW2 format. Hence, if ++the sparse image file needs to be copied to another location, it should + either be compressed first or copied using the + .B \-\-sparse=always + option to the GNU version of +-.BR cp . ++.BR cp (1). + This does not apply to the QCOW2 image, which is not sparse. + .PP + The size of an ext2 image file depends primarily on the size of the +-filesystems and how many inodes are in use. For a typical 10 gigabyte +-filesystem, with 200,000 inodes in use out of 1.2 million inodes, the +-image file will be approximately 35 megabytes; a 4 gigabyte filesystem with +-15,000 inodes in use out of 550,000 inodes will result in a 3 megabyte +-image file. Image files tend to be quite +-compressible; an image file taking up 32 megabytes of space on +-disk will generally compress down to 3 or 4 megabytes. ++filesystems and how many inodes are in use. For a typical 10 Gigabyte ++filesystem, with 200,000 inodes in use out of 1.2 million inodes, the image ++file will be approximately 35 Megabytes; a 4 Gigabyte filesystem with 15,000 ++inodes in use out of 550,000 inodes will result in a 3 Megabyte image file. ++Image files tend to be quite compressible; an image file taking up 32 Megabytes ++of space on disk will generally compress down to 3 or 4 Megabytes. + .PP +-.SH RESTORING FILESYSTEM METADATA USING AN IMAGE FILE +-.PP +-The ++If ++.I image-file ++is ++.BR \- , ++then the output of ++.B e2image ++will be sent to standard output, so that the output can be piped to ++another program, such as ++.BR gzip (1). ++(Note that this is currently only supported when ++creating a raw image file using the ++.B \-r ++option, since the process of creating a normal image file, or QCOW2 ++image currently ++requires random access to the file, which cannot be done using a ++pipe. ++ ++.SH OPTIONS ++.TP ++.B \-a ++Include file data in the image file. Normally ++.B e2image ++only includes fs metadata, not regular file data. This option will ++produce an image that is suitable to use to clone the entire FS or ++for backup purposes. Note that this option only works with the ++raw ++.RI ( \-r ) ++or QCOW2 ++.RI ( \-Q ) ++formats. In conjunction with the ++.B \-r ++option it is possible to clone all and only the used blocks of one ++filesystem to another device/image file. ++.TP ++.BI \-b " superblock" ++Get image from partition with broken primary superblock by using ++the superblock located at filesystem block number ++.IR superblock . ++The partition is copied as-is including broken primary superblock. ++.TP ++.BI \-B " blocksize" ++Set the filesystem blocksize in bytes. Normally, ++.B e2image ++will search for the superblock at various different block sizes in an ++attempt to find the appropriate blocksize. This search can be fooled in ++some cases. This option forces e2fsck to only try locating the superblock ++with a particular blocksize. If the superblock is not found, e2image will ++terminate with a fatal error. ++.TP ++.BI \-c ++Compare each block to be copied from the source ++.I device ++to the corresponding block in the target ++.IR image-file . ++If both are already the same, the write will be skipped. This is ++useful if the file system is being cloned to a flash-based storage device ++(where reads are very fast and where it is desirable to avoid unnecessary ++writes to reduce write wear on the device). ++.TP ++.B \-f ++Override the read-only requirement for the source filesystem when saving ++the image file using the ++.B \-r ++and ++.B \-Q ++options. Normally, if the source filesystem is in use, the resulting image ++file is very likely not going to be useful. In some cases where the source ++filesystem is in constant use this may be better than no image at all. ++.TP + .B \-I +-option will cause e2image to install the metadata stored in the image +-file back to the device. It can be used to restore the filesystem metadata +-back to the device in emergency situations. ++install the metadata stored in the image file back to the device. ++It can be used to restore the filesystem metadata back to the device ++in emergency situations. + .PP + .B WARNING!!!! + The +@@ -134,29 +159,76 @@ option should only be used as a desperation measure when other + alternatives have failed. If the filesystem has changed since the image + file was created, data + .B will +-be lost. In general, you should make a full image +-backup of the filesystem first, in case you wish to try other recovery +-strategies afterwards. +-.PP ++be lost. In general, you should make another full image backup of the ++filesystem first, in case you wish to try other recovery strategies afterward. ++.TP ++.B \-n ++Cause all image writes to be skipped, and instead only print the block ++numbers that would have been written. ++.TP ++.BI \-o " src_offset" ++Specify offset of the image to be read from the start of the source ++.I device ++in bytes. See ++.B OFFSETS ++for more details. ++.TP ++.BI \-O " tgt_offset" ++Specify offset of the image to be written from the start of the target ++.I image-file ++in bytes. See ++.B OFFSETS ++for more details. ++.TP ++.B \-p ++Show progress of image-file creation. ++.TP ++.B \-Q ++Create a QCOW2-format image file instead of a normal image file, suitable ++for use by virtual machine images, and other tools that can use the ++.B .qcow ++image format. See ++.B QCOW2 IMAGE FILES ++below for details. ++.TP ++.B \-r ++Create a raw image file instead of a normal image file. See ++.B RAW IMAGE FILES ++below for details. ++.TP ++.B \-s ++Scramble directory entries and zero out unused portions of the directory ++blocks in the written image file to avoid revealing information about ++the contents of the filesystem. However, this will prevent analysis of ++problems related to hash-tree indexed directories. ++ + .SH RAW IMAGE FILES + The + .B \-r +-option will create a raw image file instead of a normal image file. +-A raw image file differs ++option will create a raw image file, which differs + from a normal image file in two ways. First, the filesystem metadata is +-placed in the proper position so that e2fsck, dumpe2fs, debugfs, +-etc.\& can be run directly on the raw image file. In order to minimize +-the amount of disk space consumed by a raw image file, the file is ++placed in the same relative offset within ++.I image-file ++as it is in the ++.I device ++so that ++.BR debugfs (8), ++.BR dumpe2fs (8), ++.BR e2fsck (8), ++.BR losetup (8), ++etc. and can be run directly on the raw image file. In order to minimize ++the amount of disk space consumed by the raw image file, it is + created as a sparse file. (Beware of copying or + compressing/decompressing this file with utilities that don't understand + how to create sparse files; the file will become as large as the + filesystem itself!) Secondly, the raw image file also includes indirect +-blocks and directory blocks, which the standard image file does not have, +-although this may change in the future. ++blocks and directory blocks, which the standard image file does not have. + .PP + Raw image files are sometimes used when sending filesystems to the maintainer + as part of bug reports to e2fsprogs. When used in this capacity, the +-recommended command is as follows (replace hda1 with the appropriate device): ++recommended command is as follows (replace ++.B hda1 ++with the appropriate device for your system): + .PP + .br + \fBe2image \-r /dev/hda1 \- | bzip2 > hda1.e2i.bz2\fR +@@ -166,46 +238,27 @@ However, the filenames in the directory blocks can still reveal + information about the contents of the filesystem that the bug reporter + may wish to keep confidential. To address this concern, the + .B \-s +-option can be specified. This will cause +-.B e2image +-to scramble directory entries and zero out any unused portions +-of the directory blocks before writing the image file. However, +-the +-.B \-s +-option will prevent analysis of problems related to hash-tree indexed +-directories. ++option can be specified to scramble the filenames in the image. + .PP +-Option +-.B \-b +-.I superblock +-can be used to get image from partition with broken primary superblock. +-The partition is copied as-is including broken primary superblock. +-.PP +-Option +-.B \-B +-.I blocksize +-can be used to set superblock block size. Normally, e2fsck will search +-for the superblock at various different block sizes in an attempt to find +-the appropriate blocksize. This search can be fooled in some cases. This +-option forces e2fsck to only try locating the superblock at a particular +-blocksize. If the superblock is not found, e2fsck will terminate with a +-fatal error. +-.PP +-Note that this will work even if you substitute "/dev/hda1" for another raw ++Note that this will work even if you substitute ++.B /dev/hda1 ++for another raw + disk image, or QCOW2 image previously created by + .BR e2image . +-.PP ++ + .SH QCOW2 IMAGE FILES + The + .B \-Q + option will create a QCOW2 image file instead of a normal, or raw image file. + A QCOW2 image contains all the information the raw image does, however unlike +-the raw image it is not sparse. The QCOW2 image minimize the amount of disk +-space by storing data in special format with pack data closely together, hence +-avoiding holes while still minimizing size. ++the raw image it is not sparse. The QCOW2 image minimize the amount of space ++used by the image by storing it in special format which packs data closely ++together, hence avoiding holes while still minimizing size. + .PP + In order to send filesystem to the maintainer as a part of bug report to +-e2fsprogs, use following commands (replace hda1 with the appropriate device): ++e2fsprogs, use following commands (replace ++.B hda1 ++with the appropriate device for your system): + .PP + .br + \ \fBe2image \-Q /dev/hda1 hda1.qcow2\fR +@@ -213,66 +266,28 @@ e2fsprogs, use following commands (replace hda1 with the appropriate device): + \ \fBbzip2 -z hda1.qcow2\fR + .PP + This will only send the metadata information, without any data blocks. +-However, the filenames in the directory blocks can still reveal +-information about the contents of the filesystem that the bug reporter +-may wish to keep confidential. To address this concern, the +-.B \-s +-option can be specified. This will cause +-.B e2image +-to scramble directory entries and zero out any unused portions +-of the directory blocks before writing the image file. However, the ++As described for ++.B RAW IMAGE FILES ++the + .B \-s +-option will prevent analysis of problems related to hash-tree indexed +-directories. ++option can be specified to scramble the filesystem names in the image. + .PP +-Note that QCOW2 image created by ++Note that the QCOW2 image created by + .B e2image +-is regular QCOW2 image and can be processed by tools aware of QCOW2 format ++is a regular QCOW2 image and can be processed by tools aware of QCOW2 format + such as for example + .BR qemu-img . + .PP +-You can convert a qcow2 image into a raw image with: ++You can convert a .qcow2 image into a raw image with: + .PP + .br + \ \fBe2image \-r hda1.qcow2 hda1.raw\fR + .br + .PP +-This can be useful to write a qcow2 image containing all data to a ++This can be useful to write a QCOW2 image containing all data to a + sparse image file where it can be loop mounted, or to a disk partition. +-Note that this may not work with qcow2 images not generated by e2image. +-.PP +-Options +-.B \-b +-.I superblock +-and +-.B \-B +-.I blocksize +-can be used same way as for raw images. +-.PP +-.SH INCLUDING DATA +-Normally +-.B e2image +-only includes fs metadata, not regular file data. The +-.B \-a +-option can be specified to include all data. This will +-give an image that is suitable to use to clone the entire FS or +-for backup purposes. Note that this option only works with the +-raw or QCOW2 formats. The +-.B \-p +-switch may be given to show progress. If the file system is being +-cloned to a flash-based storage device (where reads are very fast and +-where it is desirable to avoid unnecessary writes to reduce write wear +-on the device), the +-.B \-c +-option which cause e2image to try reading a block from the destination +-to see if it is identical to the block which +-.B e2image +-is about to copy. If the block is already the same, the write can be +-skipped. The +-.B \-n +-option will cause all of the writes to be no-ops, and print the blocks +-that would have been written. +-.PP ++Note that this may not work with QCOW2 images not generated by e2image. ++ + .SH OFFSETS + Normally a filesystem starts at the beginning of a partition, and + .B e2image +@@ -288,14 +303,14 @@ before writing the filesystem. + For example, if you have a + .B dd + image of a whole hard drive that contains an ext2 fs in a partition +-starting at 1 MiB, you can clone that fs with: ++starting at 1 MiB, you can clone that image to a block device with: + .PP + .br + \ \fBe2image \-aro 1048576 img /dev/sda1\fR + .br + .PP +-Or you can clone a fs into an image file, leaving room in the first +-MiB for a partition table with: ++Or you can clone a filesystem from a block device into an image file, ++leaving room in the first MiB for a partition table with: + .PP + .br + \ \fBe2image -arO 1048576 /dev/sda1 img\fR +@@ -304,14 +319,17 @@ MiB for a partition table with: + If you specify at least one offset, and only one file, an in-place + move will be performed, allowing you to safely move the filesystem + from one offset to another. ++ + .SH AUTHOR + .B e2image + was written by Theodore Ts'o (ty...@mit.edu). ++ + .SH AVAILABILITY + .B e2image + is part of the e2fsprogs package and is available from + http://e2fsprogs.sourceforge.net. ++ + .SH SEE ALSO + .BR dumpe2fs (8), + .BR debugfs (8) +- ++.BR e2fsck (8) +-- +2.31.0 + diff -Nru e2fsprogs-1.46.2/debian/patches/series e2fsprogs-1.46.2/debian/patches/series --- e2fsprogs-1.46.2/debian/patches/series 1969-12-31 19:00:00.000000000 -0500 +++ e2fsprogs-1.46.2/debian/patches/series 2021-06-07 07:27:15.000000000 -0400 @@ -0,0 +1,5 @@ +0001-e2fsck-fix-portability-problems-caused-by-unaligned-.patch +0002-e2fsck-fix-unaligned-accesses-to-ext4_fc_tl-struct.patch +0003-e2fsck-fix-unaligned-accesses-to-ext4_fc_add_range-a.patch +0004-libext2fs-fix-missing-mutex-unlock-in-an-error-path-.patch +0005-e2image-add-OPTIONS-section-to-man-page.patch