tags 989630 +pending
thanks

I finally had time to investigate this problem.  It turns out the only
time this bug manifests is when creating an file system smaller than
(blocksize)**2 bytes (e.g., 16 megabytes when the is block size is
4k).

The bug was introduced almost ten years ago (September 2011), and
apparently no one noticed until you did!

Thanks for providing a repro, BTW; I had initially tried reproducing
this with a file system size larger than 16MB, and I couldn't see the
problem.  But when I used your precise reproduction instructions, I
finally figured out what was going on.

The patch to fix this is attached below.

                                                - Ted

commit 6568ba325e54a2ae1d2617c5175936c819ab4c8c
Author: Theodore Ts'o <ty...@mit.edu>
Date:   Sun Jul 18 09:15:28 2021 -0400

    mke2fs: only try discarding a single block to test if discard works
    
    Commit d2bfdc7ff15c ("Use punch hole as "discard" on regular files")
    added a test to see if the storage device actually supports discard.
    The intent was to try discarding the first block but since
    io_channel_discard() interprets the offset and count arguments in
    blocks, and not bytes, mke2fs was actually discarding the first 16
    megabytes (when the block size is 4k).  This is normally not a
    problem, since most file systems are larger than that, and requests to
    discard beyond the end of the block device are ignored.
    
    However, when creating a small file system as part of a image
    containing multiple partitions, the initial test discard can end up
    discarding data beyond the file system being created.
    
    Addresses-Debian-Bug: #989630
    Reported-by: Josh Triplett <j...@joshtriplett.org>
    Fixes: d2bfdc7ff15c ("Use punch hole as "discard" on regular files")
    Signed-off-by: Theodore Ts'o <ty...@mit.edu>

diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index 9fa6eaa7..5a35e9ef 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -2794,7 +2794,7 @@ static int mke2fs_discard_device(ext2_filsys fs)
        struct ext2fs_numeric_progress_struct progress;
        blk64_t blocks = ext2fs_blocks_count(fs->super);
        blk64_t count = DISCARD_STEP_MB;
-       blk64_t cur;
+       blk64_t cur = 0;
        int retval = 0;
 
        /*
@@ -2802,10 +2802,9 @@ static int mke2fs_discard_device(ext2_filsys fs)
         * we do not print numeric progress resulting in failure
         * afterwards.
         */
-       retval = io_channel_discard(fs->io, 0, fs->blocksize);
+       retval = io_channel_discard(fs->io, 0, 1);
        if (retval)
                return retval;
-       cur = fs->blocksize;
 
        count *= (1024 * 1024);
        count /= fs->blocksize;

Reply via email to