Hello community,

here is the log from the commit of package e2fsprogs for openSUSE:Leap:15.2 
checked in at 2020-04-14 14:18:54
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Leap:15.2/e2fsprogs (Old)
 and      /work/SRC/openSUSE:Leap:15.2/.e2fsprogs.new.3248 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "e2fsprogs"

Tue Apr 14 14:18:54 2020 rev:31 rq:793118 version:1.43.8

Changes:
--------
--- /work/SRC/openSUSE:Leap:15.2/e2fsprogs/e2fsprogs.changes    2020-02-16 
18:25:32.266630602 +0100
+++ /work/SRC/openSUSE:Leap:15.2/.e2fsprogs.new.3248/e2fsprogs.changes  
2020-04-14 14:18:55.253182227 +0200
@@ -1,0 +2,14 @@
+Fri Mar 27 16:00:29 UTC 2020 - Jan Kara <j...@suse.cz>
+
+- e2fsck-clarify-overflow-link-count-error-message.patch: e2fsck: clarify
+  overflow link count error message (bsc#1160979)
+- ext2fs-update-allocation-info-earlier-in-ext2fs_mkdi.patch: ext2fs: update
+  allocation info earlier in ext2fs_mkdir() (bsc#1160979)
+- ext2fs-implement-dir-entry-creation-in-htree-directo.patch: ext2fs: implement
+  dir entry creation in htree directories (bsc#1160979)
+- tests-add-test-to-excercise-indexed-directories-with.patch: tests: add test
+  to excercise indexed directories with metadata_csum (bsc#1160979)
+- tune2fs-update-dir-checksums-when-clearing-dir_index.patch: tune2fs: update
+  dir checksums when clearing dir_index feature (bsc#1160979)
+
+-------------------------------------------------------------------

New:
----
  e2fsck-clarify-overflow-link-count-error-message.patch
  ext2fs-implement-dir-entry-creation-in-htree-directo.patch
  ext2fs-update-allocation-info-earlier-in-ext2fs_mkdi.patch
  tests-add-test-to-excercise-indexed-directories-with.patch
  tune2fs-update-dir-checksums-when-clearing-dir_index.patch

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ e2fsprogs.spec ++++++
--- /var/tmp/diff_new_pack.XAw0Po/_old  2020-04-14 14:18:56.073182840 +0200
+++ /var/tmp/diff_new_pack.XAw0Po/_new  2020-04-14 14:18:56.077182842 +0200
@@ -88,6 +88,11 @@
 Patch10:        resize2fs-Make-minimum-size-estimates-more-reliable.patch
 Patch11:        e2fsck-abort-if-there-is-a-corrupted-directory-block.patch
 Patch12:        e2fsck-don-t-try-to-rehash-a-deleted-directory.patch
+Patch13:        e2fsck-clarify-overflow-link-count-error-message.patch
+Patch14:        ext2fs-update-allocation-info-earlier-in-ext2fs_mkdi.patch
+Patch15:        ext2fs-implement-dir-entry-creation-in-htree-directo.patch
+Patch16:        tests-add-test-to-excercise-indexed-directories-with.patch
+Patch17:        tune2fs-update-dir-checksums-when-clearing-dir_index.patch
 # Do not suppress make commands
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
 
@@ -239,6 +244,11 @@
 %patch10 -p1
 %patch11 -p1
 %patch12 -p1
+%patch13 -p1
+%patch14 -p1
+%patch15 -p1
+%patch16 -p1
+%patch17 -p1
 cp %{SOURCE2} .
 
 %build

++++++ e2fsck-clarify-overflow-link-count-error-message.patch ++++++
>From 125850eb92f042c76b6f001bf63833ffc15e7916 Mon Sep 17 00:00:00 2001
From: Jan Kara <j...@suse.cz>
Date: Thu, 13 Feb 2020 11:15:56 +0100
Subject: [PATCH] e2fsck: clarify overflow link count error message
References: bsc#1160979

When directory link count is set to overflow value (1) but during pass 4
we find out the exact link count would fit, we either silently fix this
(which is not great because e2fsck then reports the fs was modified but
output doesn't indicate why in any way), or we report that link count is
wrong and ask whether we should fix it (in case -n option was
specified). The second case is even more misleading because it suggests
non-trivial fs corruption which then gets silently fixed on the next
run. Similarly to how we fix up other non-problems, just create a new
error message for the case directory link count is not overflown anymore
and always report it to clarify what is going on.

Reviewed-by: Andreas Dilger <adil...@dilger.ca>
Signed-off-by: Jan Kara <j...@suse.cz>
Signed-off-by: Theodore Ts'o <ty...@mit.edu>
(cherry picked from commit 4ebce13292f54c96f43dcb1bd1d5b8df5dc8749d)
Acked-by: Jan Kara <j...@suse.cz>
---
 e2fsck/pass4.c   | 20 ++++++++++++++++----
 e2fsck/problem.c |  5 +++++
 e2fsck/problem.h |  3 +++
 3 files changed, 24 insertions(+), 4 deletions(-)

Index: e2fsprogs-1.43.8/e2fsck/pass4.c
===================================================================
--- e2fsprogs-1.43.8.orig/e2fsck/pass4.c
+++ e2fsprogs-1.43.8/e2fsck/pass4.c
@@ -169,6 +169,8 @@ void e2fsck_pass4(e2fsck_t ctx)
                if (isdir && (link_counted > EXT2_LINK_MAX))
                        link_counted = 1;
                if (link_counted != link_count) {
+                       int fix_nlink = 0;
+
                        e2fsck_read_inode_full(ctx, i, EXT2_INODE(inode),
                                               inode_size, "pass4");
                        pctx.ino = i;
@@ -182,10 +184,20 @@ void e2fsck_pass4(e2fsck_t ctx)
                        pctx.num = link_counted;
                        /* i_link_count was previously exceeded, but no longer
                         * is, fix this but don't consider it an error */
-                       if ((isdir && link_counted > 1 &&
-                            (inode->i_flags & EXT2_INDEX_FL) &&
-                            link_count == 1 && !(ctx->options & E2F_OPT_NO)) ||
-                           fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
+                       if (isdir && link_counted > 1 &&
+                           (inode->i_flags & EXT2_INDEX_FL) &&
+                           link_count == 1) {
+                               if ((ctx->options & E2F_OPT_READONLY) == 0) {
+                                       fix_nlink =
+                                               fix_problem(ctx,
+                                                       
PR_4_DIR_OVERFLOW_REF_COUNT,
+                                                       &pctx);
+                               }
+                       } else {
+                               fix_nlink = fix_problem(ctx, PR_4_BAD_REF_COUNT,
+                                               &pctx);
+                       }
+                       if (fix_nlink) {
                                inode->i_links_count = link_counted;
                                e2fsck_write_inode_full(ctx, i,
                                                        EXT2_INODE(inode),
Index: e2fsprogs-1.43.8/e2fsck/problem.c
===================================================================
--- e2fsprogs-1.43.8.orig/e2fsck/problem.c
+++ e2fsprogs-1.43.8/e2fsck/problem.c
@@ -1857,6 +1857,11 @@ static struct e2fsck_problem problem_tab
          "They @s the same!\n"),
          PROMPT_NONE, 0 },
 
+       /* Directory inode ref count set to overflow but could be exact value */
+       { PR_4_DIR_OVERFLOW_REF_COUNT,
+         N_("@d @i %i ref count set to overflow but could be exact value %N.  
"),
+         PROMPT_FIX, PR_PREEN_OK, 0, 0, 0 },
+
        /* Pass 5 errors */
 
        /* Pass 5: Checking group summary information */
Index: e2fsprogs-1.43.8/e2fsck/problem.h
===================================================================
--- e2fsprogs-1.43.8.orig/e2fsck/problem.h
+++ e2fsprogs-1.43.8/e2fsck/problem.h
@@ -1123,6 +1123,9 @@ struct problem_context {
 /* Inconsistent inode count information cached */
 #define PR_4_INCONSISTENT_COUNT                0x040004
 
+/* Directory ref count set to overflow but it doesn't have to be */
+#define PR_4_DIR_OVERFLOW_REF_COUNT    0x040007
+
 /*
  * Pass 5 errors
  */
++++++ ext2fs-implement-dir-entry-creation-in-htree-directo.patch ++++++
++++ 616 lines (skipped)

++++++ ext2fs-update-allocation-info-earlier-in-ext2fs_mkdi.patch ++++++
>From a25a84c6aa2a19987b0aeced363c4bf1dcc89ec8 Mon Sep 17 00:00:00 2001
From: Jan Kara <j...@suse.cz>
Date: Thu, 13 Feb 2020 11:15:58 +0100
Subject: [PATCH 1/5] ext2fs: update allocation info earlier in ext2fs_mkdir()
 and ext2fs_symlink()
References: bsc#1160979

Currently, ext2fs_mkdir() and ext2fs_symlink() update allocation bitmaps
and other information only close to the end of the function, in
particular after calling to ext2fs_link(). When ext2fs_link() will
support indexed directories, it will also need to allocate blocks and
that would cause filesystem corruption in case allocation info isn't
properly updated. So make sure ext2fs_mkdir() and ext2fs_symlink()
update allocation info before calling into ext2fs_link().

[ Added error handling so the calls to ext2fs_{block,inode}_alloc_stats()
  can be undone if the newly created directory or symlink can not be linked
  into the directory. -- TYT ]

Signed-off-by: Jan Kara <j...@suse.cz>
Signed-off-by: Theodore Ts'o <ty...@mit.edu>
Acked-by: Jan Kara <j...@suse.cz>
---
 lib/ext2fs/mkdir.c   | 22 +++++++++++++++-------
 lib/ext2fs/symlink.c | 22 +++++++++++++++-------
 2 files changed, 30 insertions(+), 14 deletions(-)

Index: e2fsprogs-1.43.8/lib/ext2fs/mkdir.c
===================================================================
--- e2fsprogs-1.43.8.orig/lib/ext2fs/mkdir.c
+++ e2fsprogs-1.43.8/lib/ext2fs/mkdir.c
@@ -43,6 +43,7 @@ errcode_t ext2fs_mkdir(ext2_filsys fs, e
        blk64_t                 blk;
        char                    *block = 0;
        int                     inline_data = 0;
+       int                     drop_refcount = 0;
 
        EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
 
@@ -144,6 +145,14 @@ errcode_t ext2fs_mkdir(ext2_filsys fs, e
        }
 
        /*
+        * Update accounting....
+        */
+       if (!inline_data)
+               ext2fs_block_alloc_stats2(fs, blk, +1);
+       ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
+       drop_refcount = 1;
+
+       /*
         * Link the directory into the filesystem hierarchy
         */
        if (name) {
@@ -174,17 +183,16 @@ errcode_t ext2fs_mkdir(ext2_filsys fs, e
                if (retval)
                        goto cleanup;
        }
-
-       /*
-        * Update accounting....
-        */
-       if (!inline_data)
-               ext2fs_block_alloc_stats2(fs, blk, +1);
-       ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
+       drop_refcount = 0;
 
 cleanup:
        if (block)
                ext2fs_free_mem(&block);
+       if (drop_refcount) {
+               if (!inline_data)
+                       ext2fs_block_alloc_stats2(fs, blk, -1);
+               ext2fs_inode_alloc_stats2(fs, ino, -1, 1);
+       }
        return retval;
 
 }
Index: e2fsprogs-1.43.8/lib/ext2fs/symlink.c
===================================================================
--- e2fsprogs-1.43.8.orig/lib/ext2fs/symlink.c
+++ e2fsprogs-1.43.8/lib/ext2fs/symlink.c
@@ -38,6 +38,7 @@ errcode_t ext2fs_symlink(ext2_filsys fs,
        int                     fastlink, inlinelink;
        unsigned int            target_len;
        char                    *block_buf = 0;
+       int                     drop_refcount = 0;
 
        EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
 
@@ -146,6 +147,14 @@ need_block:
        }
 
        /*
+        * Update accounting....
+        */
+       if (!fastlink && !inlinelink)
+               ext2fs_block_alloc_stats2(fs, blk, +1);
+       ext2fs_inode_alloc_stats2(fs, ino, +1, 0);
+       drop_refcount = 1;
+
+       /*
         * Link the symlink into the filesystem hierarchy
         */
        if (name) {
@@ -161,16 +170,15 @@ need_block:
                if (retval)
                        goto cleanup;
        }
-
-       /*
-        * Update accounting....
-        */
-       if (!fastlink && !inlinelink)
-               ext2fs_block_alloc_stats2(fs, blk, +1);
-       ext2fs_inode_alloc_stats2(fs, ino, +1, 0);
+       drop_refcount = 0;
 
 cleanup:
        if (block_buf)
                ext2fs_free_mem(&block_buf);
+       if (drop_refcount) {
+               if (!fastlink && !inlinelink)
+                       ext2fs_block_alloc_stats2(fs, blk, -1);
+               ext2fs_inode_alloc_stats2(fs, ino, -1, 0);
+       }
        return retval;
 }
++++++ tests-add-test-to-excercise-indexed-directories-with.patch ++++++
>From 4ed27a5bb9bfabaf437b45aaad315f028da5a6f1 Mon Sep 17 00:00:00 2001
From: Jan Kara <j...@suse.cz>
Date: Thu, 13 Feb 2020 11:16:01 +0100
Subject: [PATCH 4/5] tests: add test to excercise indexed directories with
 metadata_csum
References: bsc#1160979

Indexed directories have somewhat different format when metadata_csum is
enabled. Add test to excercise linking in indexed directories and e2fsck
rehash code in this case.

Reviewed-by: Andreas Dilger <adil...@dilger.ca>
Signed-off-by: Jan Kara <j...@suse.cz>
Signed-off-by: Theodore Ts'o <ty...@mit.edu>
Acked-by: Jan Kara <j...@suse.cz>
---
 tests/f_large_dir_csum/expect       | 32 ++++++++++++++
 tests/f_large_dir_csum/is_slow_test |  0
 tests/f_large_dir_csum/name         |  1 +
 tests/f_large_dir_csum/script       | 84 +++++++++++++++++++++++++++++++++++++
 4 files changed, 117 insertions(+)
 create mode 100644 tests/f_large_dir_csum/expect
 create mode 100644 tests/f_large_dir_csum/is_slow_test
 create mode 100644 tests/f_large_dir_csum/name
 create mode 100644 tests/f_large_dir_csum/script

Index: e2fsprogs-1.43.8/tests/f_large_dir_csum/expect
===================================================================
--- /dev/null
+++ e2fsprogs-1.43.8/tests/f_large_dir_csum/expect
@@ -0,0 +1,32 @@
+Creating filesystem with 30996 1k blocks and 64 inodes
+Superblock backups stored on blocks: 
+       8193, 24577
+
+Allocating group tables:    done                            
+Writing inode tables:    done                            
+Writing superblocks and filesystem accounting information:    done
+
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 3A: Optimizing directories
+Pass 4: Checking reference counts
+Inode 13 ref count is 1, should be 5.  Fix? yes
+
+Pass 5: Checking group summary information
+
+test.img: ***** FILE SYSTEM WAS MODIFIED *****
+test.img: 13/64 files (0.0% non-contiguous), 766/30996 blocks
+Exit status is 1
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 3A: Optimizing directories
+Pass 4: Checking reference counts
+Inode 13 ref count is 5, should be 15499.  Fix? yes
+
+Pass 5: Checking group summary information
+
+test.img: ***** FILE SYSTEM WAS MODIFIED *****
+test.img: 13/64 files (0.0% non-contiguous), 5971/30996 blocks
+Exit status is 1
Index: e2fsprogs-1.43.8/tests/f_large_dir_csum/name
===================================================================
--- /dev/null
+++ e2fsprogs-1.43.8/tests/f_large_dir_csum/name
@@ -0,0 +1 @@
+optimize 3 level htree directories with metadata checksums
Index: e2fsprogs-1.43.8/tests/f_large_dir_csum/script
===================================================================
--- /dev/null
+++ e2fsprogs-1.43.8/tests/f_large_dir_csum/script
@@ -0,0 +1,84 @@
+OUT=$test_name.log
+EXP=$test_dir/expect
+E2FSCK=../e2fsck/e2fsck
+
+NAMELEN=255
+DIRENT_SZ=8
+BLOCKSZ=1024
+INODESZ=128
+CSUM_SZ=8
+CSUM_TAIL_SZ=12
+DIRENT_PER_LEAF=$(((BLOCKSZ - CSUM_TAIL_SZ) / (NAMELEN + DIRENT_SZ)))
+HEADER=32
+INDEX_SZ=8
+INDEX_L1=$(((BLOCKSZ - HEADER - CSUM_SZ) / INDEX_SZ))
+INDEX_L2=$(((BLOCKSZ - DIRENT_SZ - CSUM_SZ) / INDEX_SZ))
+DIRBLK=$((INDEX_L1 * INDEX_L2))
+ENTRIES=$((DIRBLK * DIRENT_PER_LEAF / 3))
+# directory leaf blocks - get twice as much because the leaves won't be full
+# and there are also other filesystem blocks.
+FSIZE=$((DIRBLK * 2))
+
+$MKE2FS -b 1024 -O extents,64bit,uninit_bg,metadata_csum -N 50 \
+       -I $INODESZ -F $TMPFILE $FSIZE > $OUT.new 2>&1
+RC=$?
+if [ $RC -eq 0 ]; then
+{
+       # First some initial fs setup to create indexed dir
+       echo "mkdir /foo"
+       echo "cd /foo"
+       touch $TMPFILE.tmp
+       echo "write $TMPFILE.tmp foofile"
+       i=0
+       while test $i -lt $DIRENT_PER_LEAF ; do
+               printf "ln foofile f%0254u\n" $i
+               i=$((i + 1));
+       done
+       echo "expand ./"
+       printf "ln foofile f%0254u\n" $i
+} | $DEBUGFS -w $TMPFILE > /dev/null 2>> $OUT.new
+       RC=$?
+       # e2fsck should optimize the dir to become indexed
+       $E2FSCK -yfD $TMPFILE >> $OUT.new 2>&1
+       status=$?
+       echo Exit status is $status >> $OUT.new
+fi
+
+if [ $RC -eq 0 ]; then
+{
+       START=$SECONDS
+       i=$(($DIRENT_PER_LEAF+1))
+       last=$i
+       echo "cd /foo"
+       while test $i -lt $ENTRIES ; do
+           ELAPSED=$((SECONDS - START))
+           if test $((i % 5000)) -eq 0 -a $ELAPSED -gt 10; then
+               RATE=$(((i - last) / ELAPSED))
+               echo "$test_name: $i/$ENTRIES links, ${ELAPSED}s @ $RATE/s" >&2
+               START=$SECONDS
+               last=$i
+           fi
+           printf "ln foofile f%0254u\n" $i
+           i=$((i + 1))
+       done
+} | $DEBUGFS -w $TMPFILE > /dev/null 2>> $OUT.new
+       RC=$?
+fi
+
+if [ $RC -eq 0 ]; then
+       $E2FSCK -yfD $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
+
+       cmp -s $OUT $EXP
+       RC=$?
+fi
+if [ $RC -eq 0 ]; then
+       echo "$test_name: $test_description: ok"
+       touch $test_name.ok
+else
+       echo "$test_name: $test_description: failed"
+       diff -u $EXP $OUT > $test_name.failed
+fi
++++++ tune2fs-update-dir-checksums-when-clearing-dir_index.patch ++++++
>From 514fde0296c2085fb11685820f3d396d5c41026e Mon Sep 17 00:00:00 2001
From: Jan Kara <j...@suse.cz>
Date: Thu, 13 Feb 2020 11:16:02 +0100
Subject: [PATCH 5/5] tune2fs: update dir checksums when clearing dir_index
 feature
References: bsc#1160979

When clearing dir_index feature while metadata_csum is enabled, we have
to rewrite checksums of all indexed directories to update checksums of
internal tree nodes.

Signed-off-by: Jan Kara <j...@suse.cz>
Signed-off-by: Theodore Ts'o <ty...@mit.edu>
Acked-by: Jan Kara <j...@suse.cz>
---
 misc/tune2fs.c | 143 ++++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 95 insertions(+), 48 deletions(-)

Index: e2fsprogs-1.43.8/misc/tune2fs.c
===================================================================
--- e2fsprogs-1.43.8.orig/misc/tune2fs.c
+++ e2fsprogs-1.43.8/misc/tune2fs.c
@@ -553,7 +553,8 @@ struct rewrite_dir_context {
        char *buf;
        errcode_t errcode;
        ext2_ino_t dir;
-       int is_htree;
+       int is_htree:1;
+       int clear_htree:1;
 };
 
 static int rewrite_dir_block(ext2_filsys fs,
@@ -572,8 +573,13 @@ static int rewrite_dir_block(ext2_filsys
        if (ctx->errcode)
                return BLOCK_ABORT;
 
-       /* if htree node... */
-       if (ctx->is_htree)
+       /*
+        * if htree node... Note that if we are clearing htree structures from
+        * the directory, we treat the htree internal block as an ordinary leaf.
+        * The code below will do the right thing and make space for checksum
+        * there.
+        */
+       if (ctx->is_htree && !ctx->clear_htree)
                ext2fs_get_dx_countlimit(fs, (struct ext2_dir_entry *)ctx->buf,
                                         &dcl, &dcl_offset);
        if (dcl) {
@@ -702,7 +708,8 @@ static errcode_t rewrite_directory(ext2_
        if (retval)
                return retval;
 
-       ctx.is_htree = (inode->i_flags & EXT2_INDEX_FL);
+       ctx.is_htree = !!(inode->i_flags & EXT2_INDEX_FL);
+       ctx.clear_htree = !ext2fs_has_feature_dir_index(fs->super);
        ctx.dir = dir;
        ctx.errcode = 0;
        retval = ext2fs_block_iterate3(fs, dir, BLOCK_FLAG_READ_ONLY |
@@ -713,121 +720,169 @@ static errcode_t rewrite_directory(ext2_
        if (retval)
                return retval;
 
+       if (ctx.is_htree && ctx.clear_htree) {
+               inode->i_flags &= ~EXT2_INDEX_FL;
+               retval = ext2fs_write_inode(fs, dir, inode);
+               if (retval)
+                       return retval;
+       }
+
        return ctx.errcode;
 }
 
-/*
- * Forcibly set checksums in all inodes.
- */
-static void rewrite_inodes(ext2_filsys fs)
+struct rewrite_context {
+       ext2_filsys fs;
+       struct ext2_inode *zero_inode;
+       char *ea_buf;
+       int inode_size;
+};
+
+static void rewrite_one_inode(struct rewrite_context *ctx, ext2_ino_t ino,
+                             struct ext2_inode *inode)
 {
-       int length = EXT2_INODE_SIZE(fs->super);
-       struct ext2_inode *inode, *zero;
-       char            *ea_buf;
-       ext2_inode_scan scan;
-       errcode_t       retval;
-       ext2_ino_t      ino;
-       blk64_t         file_acl_block;
-       int             inode_dirty;
+       ext2_filsys fs = ctx->fs;
+       int inode_dirty;
+       errcode_t retval;
+       blk64_t file_acl_block;
 
-       if (fs->super->s_creator_os == EXT2_OS_HURD)
-               return;
+       if (ext2fs_test_inode_bitmap2(fs->inode_map, ino)) {
+               inode_dirty = 1;
+       } else {
+               if (memcmp(inode, ctx->zero_inode, ctx->inode_size) != 0) {
+                       memset(inode, 0, ctx->inode_size);
+                       inode_dirty = 1;
+               } else {
+                       inode_dirty = 0;
+               }
+       }
 
-       retval = ext2fs_open_inode_scan(fs, 0, &scan);
+       if (inode_dirty) {
+               retval = ext2fs_write_inode_full(fs, ino, inode,
+                                                ctx->inode_size);
+               if (retval) {
+                       com_err("set_csum", retval, "while writing "
+                               "inode");
+                       exit(1);
+               }
+       }
+
+       retval = rewrite_extents(fs, ino, inode);
        if (retval) {
-               com_err("set_csum", retval, "while opening inode scan");
+               com_err("rewrite_extents", retval,
+                       "while rewriting extents");
                exit(1);
        }
 
-       retval = ext2fs_get_mem(length, &inode);
+       if (LINUX_S_ISDIR(inode->i_mode) &&
+           ext2fs_inode_has_valid_blocks2(fs, inode)) {
+               retval = rewrite_directory(fs, ino, inode);
+               if (retval) {
+                       com_err("rewrite_directory", retval,
+                               "while rewriting directories");
+                       exit(1);
+               }
+       }
+
+       file_acl_block = ext2fs_file_acl_block(fs, inode);
+       if (!file_acl_block)
+               return;
+       retval = ext2fs_read_ext_attr3(fs, file_acl_block, ctx->ea_buf, ino);
        if (retval) {
-               com_err("set_csum", retval, "while allocating memory");
+               com_err("rewrite_eablock", retval,
+                       "while rewriting extended attribute");
+               exit(1);
+       }
+       retval = ext2fs_write_ext_attr3(fs, file_acl_block, ctx->ea_buf,
+                                       ino);
+       if (retval) {
+               com_err("rewrite_eablock", retval,
+                       "while rewriting extended attribute");
                exit(1);
        }
+}
+
+#define REWRITE_DIR_FL         0x02    /* Rewrite directories */
+#define REWRITE_NONDIR_FL      0x04    /* Rewrite other inodes */
+#define REWRITE_ALL (REWRITE_DIR_FL | REWRITE_NONDIR_FL)
+
+static void rewrite_inodes_pass(struct rewrite_context *ctx, unsigned int 
flags)
+{
+       ext2_filsys fs = ctx->fs;
+       struct ext2_inode *inode;
+       ext2_inode_scan scan;
+       errcode_t       retval;
+       ext2_ino_t      ino;
+       int rewrite;
 
-       retval = ext2fs_get_memzero(length, &zero);
+       if (fs->super->s_creator_os == EXT2_OS_HURD)
+               return;
+
+       retval = ext2fs_open_inode_scan(fs, 0, &scan);
        if (retval) {
-               com_err("set_csum", retval, "while allocating memory");
+               com_err("set_csum", retval, "while opening inode scan");
                exit(1);
        }
 
-       retval = ext2fs_get_mem(fs->blocksize, &ea_buf);
+       retval = ext2fs_get_mem(ctx->inode_size, &inode);
        if (retval) {
                com_err("set_csum", retval, "while allocating memory");
                exit(1);
        }
 
        do {
-               retval = ext2fs_get_next_inode_full(scan, &ino, inode, length);
+               retval = ext2fs_get_next_inode_full(scan, &ino, inode, 
ctx->inode_size);
                if (retval) {
                        com_err("set_csum", retval, "while getting next inode");
                        exit(1);
                }
                if (!ino)
                        break;
-               if (ext2fs_test_inode_bitmap2(fs->inode_map, ino)) {
-                       inode_dirty = 1;
+               rewrite = 0;
+               if (LINUX_S_ISDIR(inode->i_mode)) {
+                       if (flags & REWRITE_DIR_FL)
+                               rewrite = 1;
                } else {
-                       if (memcmp(inode, zero, length) != 0) {
-                               memset(inode, 0, length);
-                               inode_dirty = 1;
-                       } else {
-                               inode_dirty = 0;
-                       }
+                       if (flags & REWRITE_NONDIR_FL)
+                               rewrite = 1;
                }
+               if (rewrite)
+                       rewrite_one_inode(ctx, ino, inode);
+       } while (ino);
 
-               if (inode_dirty) {
-                       retval = ext2fs_write_inode_full(fs, ino, inode,
-                                                        length);
-                       if (retval) {
-                               com_err("set_csum", retval, "while writing "
-                                       "inode");
-                               exit(1);
-                       }
-               }
+       ext2fs_free_mem(&inode);
+       ext2fs_close_inode_scan(scan);
+}
 
-               retval = rewrite_extents(fs, ino, inode);
-               if (retval) {
-                       com_err("rewrite_extents", retval,
-                               "while rewriting extents");
-                       exit(1);
-               }
+/*
+ * Forcibly rewrite checksums in inodes specified by 'flags'
+ */
+static void rewrite_inodes(ext2_filsys fs, unsigned int flags)
+{
+       struct rewrite_context ctx = {
+               .fs = fs,
+               .inode_size = EXT2_INODE_SIZE(fs->super),
+       };
+       errcode_t retval;
 
-               if (LINUX_S_ISDIR(inode->i_mode) &&
-                   ext2fs_inode_has_valid_blocks2(fs, inode)) {
-                       retval = rewrite_directory(fs, ino, inode);
-                       if (retval) {
-                               com_err("rewrite_directory", retval,
-                                       "while rewriting directories");
-                               exit(1);
-                       }
-               }
+       retval = ext2fs_get_memzero(ctx.inode_size, &ctx.zero_inode);
+       if (retval) {
+               com_err("set_csum", retval, "while allocating memory");
+               exit(1);
+       }
 
-               file_acl_block = ext2fs_file_acl_block(fs, inode);
-               if (!file_acl_block)
-                       continue;
-               retval = ext2fs_read_ext_attr3(fs, file_acl_block, ea_buf, ino);
-               if (retval) {
-                       com_err("rewrite_eablock", retval,
-                               "while rewriting extended attribute");
-                       exit(1);
-               }
-               retval = ext2fs_write_ext_attr3(fs, file_acl_block, ea_buf,
-                                               ino);
-               if (retval) {
-                       com_err("rewrite_eablock", retval,
-                               "while rewriting extended attribute");
-                       exit(1);
-               }
-       } while (ino);
+       retval = ext2fs_get_mem(fs->blocksize, &ctx.ea_buf);
+       if (retval) {
+               com_err("set_csum", retval, "while allocating memory");
+               exit(1);
+       }
 
-       ext2fs_free_mem(&zero);
-       ext2fs_free_mem(&inode);
-       ext2fs_free_mem(&ea_buf);
-       ext2fs_close_inode_scan(scan);
+       rewrite_inodes_pass(&ctx, flags);
+
+       ext2fs_free_mem(&ctx.zero_inode);
+       ext2fs_free_mem(&ctx.ea_buf);
 }
 
-static void rewrite_metadata_checksums(ext2_filsys fs)
+static void rewrite_metadata_checksums(ext2_filsys fs, unsigned int flags)
 {
        errcode_t retval;
        dgrp_t i;
@@ -842,7 +897,7 @@ static void rewrite_metadata_checksums(e
                        "while reading bitmaps");
                exit(1);
        }
-       rewrite_inodes(fs);
+       rewrite_inodes(fs, flags);
        ext2fs_mark_ib_dirty(fs);
        ext2fs_mark_bb_dirty(fs);
        ext2fs_mmp_update2(fs, 1);
@@ -1141,6 +1196,23 @@ mmp_error:
                        uuid_generate((unsigned char *) sb->s_hash_seed);
        }
 
+       if (FEATURE_OFF(E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_INDEX) &&
+           ext2fs_has_feature_metadata_csum(sb)) {
+               check_fsck_needed(fs,
+                       _("Disabling directory index on filesystem with "
+                         "checksums could take some time."));
+               if (mount_flags & EXT2_MF_MOUNTED) {
+                       fputs(_("Cannot disable dir_index on a mounted "
+                               "filesystem!\n"), stderr);
+                       exit(1);
+               }
+               /*
+                * Clearing dir_index on checksummed filesystem requires
+                * rewriting all directories to update checksums.
+                */
+               rewrite_checksums |= REWRITE_DIR_FL;
+       }
+
        if (FEATURE_OFF(E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
                if (ext2fs_check_desc(fs)) {
                        fputs(_("Clearing the flex_bg flag would "
@@ -1184,7 +1256,7 @@ mmp_error:
                                 "The larger fields afforded by this feature "
                                 "enable full-strength checksumming.  "
                                 "Run resize2fs -b to rectify.\n"));
-               rewrite_checksums = 1;
+               rewrite_checksums = REWRITE_ALL;
                /* metadata_csum supersedes uninit_bg */
                ext2fs_clear_feature_gdt_csum(fs->super);
 
@@ -1212,7 +1284,7 @@ mmp_error:
                                "filesystem!\n"), stderr);
                        exit(1);
                }
-               rewrite_checksums = 1;
+               rewrite_checksums = REWRITE_ALL;
 
                /* Enable uninit_bg unless the user expressly turned it off */
                memcpy(test_features, old_features, sizeof(test_features));
@@ -1375,7 +1447,7 @@ mmp_error:
                        return 1;
                }
 
-               rewrite_checksums = 1;
+               rewrite_checksums = REWRITE_ALL;
        }
 
        if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
@@ -3148,7 +3220,7 @@ retry_open:
                ext2fs_mark_super_dirty(fs);
                if (ext2fs_has_feature_metadata_csum(fs->super) &&
                    !ext2fs_has_feature_csum_seed(fs->super))
-                       rewrite_checksums = 1;
+                       rewrite_checksums = REWRITE_ALL;
        }
 
        if (I_flag) {
@@ -3180,7 +3252,7 @@ retry_open:
                if (retval == 0) {
                        printf(_("Setting inode size %lu\n"),
                                                        new_inode_size);
-                       rewrite_checksums = 1;
+                       rewrite_checksums = REWRITE_ALL;
                } else {
                        printf("%s", _("Failed to change inode size\n"));
                        rc = 1;
@@ -3189,7 +3261,7 @@ retry_open:
        }
 
        if (rewrite_checksums)
-               rewrite_metadata_checksums(fs);
+               rewrite_metadata_checksums(fs, rewrite_checksums);
 
        if (l_flag)
                list_super(sb);

Reply via email to