aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorVivek Haldar <haldar@google.com>2011-05-25 07:41:54 -0400
committerTheodore Ts'o <tytso@mit.edu>2011-05-25 07:41:54 -0400
commit556b27abf73833923d5cd4be80006292e1b31662 (patch)
tree588fa7c3db66afb545921cdfc894f0a41e66dc49 /fs/ext4
parenta4bb6b64e39abc0e41ca077725f2a72c868e7622 (diff)
ext4: do not normalize block requests from fallocate()
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>
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/ext4.h2
-rw-r--r--fs/ext4/extents.c5
2 files changed, 6 insertions, 1 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 7bc7c724805d..a74b89c09f90 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -517,6 +517,8 @@ struct ext4_new_group_data {
517 EXT4_GET_BLOCKS_CREATE_UNINIT_EXT) 517 EXT4_GET_BLOCKS_CREATE_UNINIT_EXT)
518 /* Punch out blocks of an extent */ 518 /* Punch out blocks of an extent */
519#define EXT4_GET_BLOCKS_PUNCH_OUT_EXT 0x0020 519#define EXT4_GET_BLOCKS_PUNCH_OUT_EXT 0x0020
520 /* Don't normalize allocation size (used for fallocate) */
521#define EXT4_GET_BLOCKS_NO_NORMALIZE 0x0040
520 522
521/* 523/*
522 * Flags used by ext4_free_blocks 524 * Flags used by ext4_free_blocks
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 88ff3a74787b..ae65f247ceda 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -3554,6 +3554,8 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
3554 else 3554 else
3555 /* disable in-core preallocation for non-regular files */ 3555 /* disable in-core preallocation for non-regular files */
3556 ar.flags = 0; 3556 ar.flags = 0;
3557 if (flags & EXT4_GET_BLOCKS_NO_NORMALIZE)
3558 ar.flags |= EXT4_MB_HINT_NOPREALLOC;
3557 newblock = ext4_mb_new_blocks(handle, &ar, &err); 3559 newblock = ext4_mb_new_blocks(handle, &ar, &err);
3558 if (!newblock) 3560 if (!newblock)
3559 goto out2; 3561 goto out2;
@@ -3807,7 +3809,8 @@ retry:
3807 break; 3809 break;
3808 } 3810 }
3809 ret = ext4_map_blocks(handle, inode, &map, 3811 ret = ext4_map_blocks(handle, inode, &map,
3810 EXT4_GET_BLOCKS_CREATE_UNINIT_EXT); 3812 EXT4_GET_BLOCKS_CREATE_UNINIT_EXT |
3813 EXT4_GET_BLOCKS_NO_NORMALIZE);
3811 if (ret <= 0) { 3814 if (ret <= 0) {
3812#ifdef EXT4FS_DEBUG 3815#ifdef EXT4FS_DEBUG
3813 WARN_ON(ret <= 0); 3816 WARN_ON(ret <= 0);