ext4: do not normalize block requests from fallocate()
authorVivek Haldar <haldar@google.com>
Wed, 25 May 2011 11:41:54 +0000 (07:41 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Wed, 25 May 2011 11:41:54 +0000 (07:41 -0400)
Currently, an fallocate request of size slightly larger than a power of
2 is turned into two block requests, each a power of 2, with the extra
blocks pre-allocated for future use. When an application calls
fallocate, it already has an idea about how large the file may grow so
there is usually little benefit to reserve extra blocks on the
preallocation list. This reduces disk fragmentation.

Tested: fsstress. Also verified manually that fallocat'ed files are
contiguously laid out with this change (whereas without it they begin at
power-of-2 boundaries, leaving blocks in between). CPU usage of
fallocate is not appreciably higher.  In a tight fallocate loop, CPU
usage hovers between 5%-8% with this change, and 5%-7% without it.

Using a simulated file system aging program which the file system to
70%, the percentage of free extents larger than 8MB (as measured by
e2freefrag) increased from 38.8% without this change, to 69.4% with
this change.

Signed-off-by: Vivek Haldar <haldar@google.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
fs/ext4/ext4.h
fs/ext4/extents.c

index 7bc7c724805d7fd794b6d509187c72da0f179b4e..a74b89c09f90f1dcc587b9e5b81b0dfc222257db 100644 (file)
@@ -517,6 +517,8 @@ struct ext4_new_group_data {
                                         EXT4_GET_BLOCKS_CREATE_UNINIT_EXT)
        /* Punch out blocks of an extent */
 #define EXT4_GET_BLOCKS_PUNCH_OUT_EXT          0x0020
+       /* Don't normalize allocation size (used for fallocate) */
+#define EXT4_GET_BLOCKS_NO_NORMALIZE           0x0040
 
 /*
  * Flags used by ext4_free_blocks
index 88ff3a74787b1063e4d2cb150777b785c2f2cf1f..ae65f247ceda63c29c640208ca3e85a205346e9b 100644 (file)
@@ -3554,6 +3554,8 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
        else
                /* disable in-core preallocation for non-regular files */
                ar.flags = 0;
+       if (flags & EXT4_GET_BLOCKS_NO_NORMALIZE)
+               ar.flags |= EXT4_MB_HINT_NOPREALLOC;
        newblock = ext4_mb_new_blocks(handle, &ar, &err);
        if (!newblock)
                goto out2;
@@ -3807,7 +3809,8 @@ retry:
                        break;
                }
                ret = ext4_map_blocks(handle, inode, &map,
-                                     EXT4_GET_BLOCKS_CREATE_UNINIT_EXT);
+                                     EXT4_GET_BLOCKS_CREATE_UNINIT_EXT |
+                                     EXT4_GET_BLOCKS_NO_NORMALIZE);
                if (ret <= 0) {
 #ifdef EXT4FS_DEBUG
                        WARN_ON(ret <= 0);
This page took 0.032644 seconds and 5 git commands to generate.