Whamcloud - gitweb
libext2fs: batch calls to ext2fs_zero_blocks2()
authorTheodore Ts'o <tytso@mit.edu>
Sat, 25 Apr 2020 15:41:24 +0000 (11:41 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Sat, 25 Apr 2020 15:46:07 +0000 (11:46 -0400)
When allocating blocks for an indirect block mapped file, accumulate
blocks to be zero'ed and then call ext2fs_zero_blocks2() to zero them
in large chunks instead of block by block.

This significantly speeds up mkfs.ext3 since we don't send a large
number of ZERO_RANGE requests to the kernel, and while the kernel does
batch write requests, it is not batching ZERO_RANGE requests.  It's
more efficient to batch in userspace in any case, since it avoids
unnecessary system calls.

Reported-by: Mario Schuknecht <mario.schuknecht@dresearch-fe.de>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
lib/ext2fs/fallocate.c

index 31e47f8..5cde7d5 100644 (file)
@@ -805,7 +805,8 @@ errcode_t ext2fs_fallocate(ext2_filsys fs, int flags, ext2_ino_t ino,
                           blk64_t start, blk64_t len)
 {
        struct ext2_inode       inode_buf;
-       blk64_t                 blk, x;
+       blk64_t                 blk, x, zero_blk, last = 0;
+       int                     zero_len = 0;
        errcode_t               err;
 
        if (((flags & EXT2_FALLOCATE_FORCE_INIT) &&
@@ -841,15 +842,32 @@ errcode_t ext2fs_fallocate(ext2_filsys fs, int flags, ext2_ino_t ino,
                if (x)
                        continue;
 
-               err = ext2fs_bmap2(fs, ino, inode, NULL,
-                                  BMAP_ALLOC | BMAP_UNINIT | BMAP_ZERO, blk,
-                                  0, &x);
+               err = ext2fs_bmap2(fs, ino, inode, NULL, BMAP_ALLOC,
+                                  blk, 0, &x);
                if (err)
-                       return err;
+                       goto errout;
+               if ((zero_len && (x != last+1)) ||
+                   (zero_len >= 65536)) {
+                       err = ext2fs_zero_blocks2(fs, zero_blk, zero_len,
+                                                 NULL, NULL);
+                       zero_len = 0;
+                       if (err)
+                               goto errout;
+               }
+               if (zero_len == 0) {
+                       zero_blk = x;
+                       zero_len = 1;
+               } else {
+                       zero_len++;
+               }
+               last = x;
        }
 
 out:
        if (inode == &inode_buf)
                ext2fs_write_inode(fs, ino, inode);
+errout:
+       if (zero_len)
+               ext2fs_zero_blocks2(fs, zero_blk, zero_len, NULL, NULL);
        return err;
 }