summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2013-06-04 13:01:11 -0400
committerTheodore Ts'o <tytso@mit.edu>2013-06-04 13:01:11 -0400
commitfffb273997cc52f255bde5f18e7f6b4686c914fb (patch)
tree7a5e338c8b2d0a7a3e1d6ac565b157471cb2ca54
parentfa55a0ed0386e1fcbb8a229a06a5c70477d0d6e5 (diff)
ext4: better estimate credits needed for ext4_da_writepages()
We limit the number of blocks written in a single loop of ext4_da_writepages() to 64 when inode uses indirect blocks. That is unnecessary as credit estimates for mapping logically continguous run of blocks is rather low even for inode with indirect blocks. So just lift this limitation and properly calculate the number of necessary credits. This better credit estimate will also later allow us to always write at least a single page in one iteration. Reviewed-by: Zheng Liu <wenqing.lz@taobao.com> Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
-rw-r--r--fs/ext4/ext4.h3
-rw-r--r--fs/ext4/extents.c16
-rw-r--r--fs/ext4/inode.c62
3 files changed, 35 insertions, 46 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 25e261da871f..2ebfcde5a156 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2596,8 +2596,7 @@ struct ext4_extent;
2596 2596
2597extern int ext4_ext_tree_init(handle_t *handle, struct inode *); 2597extern int ext4_ext_tree_init(handle_t *handle, struct inode *);
2598extern int ext4_ext_writepage_trans_blocks(struct inode *, int); 2598extern int ext4_ext_writepage_trans_blocks(struct inode *, int);
2599extern int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks, 2599extern int ext4_ext_index_trans_blocks(struct inode *inode, int extents);
2600 int chunk);
2601extern int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, 2600extern int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
2602 struct ext4_map_blocks *map, int flags); 2601 struct ext4_map_blocks *map, int flags);
2603extern void ext4_ext_truncate(handle_t *, struct inode *); 2602extern void ext4_ext_truncate(handle_t *, struct inode *);
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 299ee9df546f..94283d06cace 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -2328,17 +2328,15 @@ int ext4_ext_calc_credits_for_single_extent(struct inode *inode, int nrblocks,
2328} 2328}
2329 2329
2330/* 2330/*
2331 * How many index/leaf blocks need to change/allocate to modify nrblocks? 2331 * How many index/leaf blocks need to change/allocate to add @extents extents?
2332 * 2332 *
2333 * if nrblocks are fit in a single extent (chunk flag is 1), then 2333 * If we add a single extent, then in the worse case, each tree level
2334 * in the worse case, each tree level index/leaf need to be changed 2334 * index/leaf need to be changed in case of the tree split.
2335 * if the tree split due to insert a new extent, then the old tree
2336 * index/leaf need to be updated too
2337 * 2335 *
2338 * If the nrblocks are discontiguous, they could cause 2336 * If more extents are inserted, they could cause the whole tree split more
2339 * the whole tree split more than once, but this is really rare. 2337 * than once, but this is really rare.
2340 */ 2338 */
2341int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks, int chunk) 2339int ext4_ext_index_trans_blocks(struct inode *inode, int extents)
2342{ 2340{
2343 int index; 2341 int index;
2344 int depth; 2342 int depth;
@@ -2349,7 +2347,7 @@ int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks, int chunk)
2349 2347
2350 depth = ext_depth(inode); 2348 depth = ext_depth(inode);
2351 2349
2352 if (chunk) 2350 if (extents <= 1)
2353 index = depth * 2; 2351 index = depth * 2;
2354 else 2352 else
2355 index = depth * 3; 2353 index = depth * 3;
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 23d9a44d721a..2b777e51b677 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -136,6 +136,8 @@ static void ext4_invalidatepage(struct page *page, unsigned int offset,
136 unsigned int length); 136 unsigned int length);
137static int __ext4_journalled_writepage(struct page *page, unsigned int len); 137static int __ext4_journalled_writepage(struct page *page, unsigned int len);
138static int ext4_bh_delay_or_unwritten(handle_t *handle, struct buffer_head *bh); 138static int ext4_bh_delay_or_unwritten(handle_t *handle, struct buffer_head *bh);
139static int ext4_meta_trans_blocks(struct inode *inode, int lblocks,
140 int pextents);
139 141
140/* 142/*
141 * Test whether an inode is a fast symlink. 143 * Test whether an inode is a fast symlink.
@@ -2203,28 +2205,25 @@ static int ext4_writepage(struct page *page,
2203} 2205}
2204 2206
2205/* 2207/*
2206 * This is called via ext4_da_writepages() to 2208 * mballoc gives us at most this number of blocks...
2207 * calculate the total number of credits to reserve to fit 2209 * XXX: That seems to be only a limitation of ext4_mb_normalize_request().
2208 * a single extent allocation into a single transaction, 2210 * The rest of mballoc seems to handle chunks upto full group size.
2209 * ext4_da_writpeages() will loop calling this before
2210 * the block allocation.
2211 */ 2211 */
2212#define MAX_WRITEPAGES_EXTENT_LEN 2048
2212 2213
2214/*
2215 * Calculate the total number of credits to reserve for one writepages
2216 * iteration. This is called from ext4_da_writepages(). We map an extent of
2217 * upto MAX_WRITEPAGES_EXTENT_LEN blocks and then we go on and finish mapping
2218 * the last partial page. So in total we can map MAX_WRITEPAGES_EXTENT_LEN +
2219 * bpp - 1 blocks in bpp different extents.
2220 */
2213static int ext4_da_writepages_trans_blocks(struct inode *inode) 2221static int ext4_da_writepages_trans_blocks(struct inode *inode)
2214{ 2222{
2215 int max_blocks = EXT4_I(inode)->i_reserved_data_blocks; 2223 int bpp = ext4_journal_blocks_per_page(inode);
2216
2217 /*
2218 * With non-extent format the journal credit needed to
2219 * insert nrblocks contiguous block is dependent on
2220 * number of contiguous block. So we will limit
2221 * number of contiguous block to a sane value
2222 */
2223 if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) &&
2224 (max_blocks > EXT4_MAX_TRANS_DATA))
2225 max_blocks = EXT4_MAX_TRANS_DATA;
2226 2224
2227 return ext4_chunk_trans_blocks(inode, max_blocks); 2225 return ext4_meta_trans_blocks(inode,
2226 MAX_WRITEPAGES_EXTENT_LEN + bpp - 1, bpp);
2228} 2227}
2229 2228
2230/* 2229/*
@@ -4650,11 +4649,12 @@ int ext4_getattr(struct vfsmount *mnt, struct dentry *dentry,
4650 return 0; 4649 return 0;
4651} 4650}
4652 4651
4653static int ext4_index_trans_blocks(struct inode *inode, int nrblocks, int chunk) 4652static int ext4_index_trans_blocks(struct inode *inode, int lblocks,
4653 int pextents)
4654{ 4654{
4655 if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) 4655 if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
4656 return ext4_ind_trans_blocks(inode, nrblocks); 4656 return ext4_ind_trans_blocks(inode, lblocks);
4657 return ext4_ext_index_trans_blocks(inode, nrblocks, chunk); 4657 return ext4_ext_index_trans_blocks(inode, pextents);
4658} 4658}
4659 4659
4660/* 4660/*
@@ -4668,7 +4668,8 @@ static int ext4_index_trans_blocks(struct inode *inode, int nrblocks, int chunk)
4668 * 4668 *
4669 * Also account for superblock, inode, quota and xattr blocks 4669 * Also account for superblock, inode, quota and xattr blocks
4670 */ 4670 */
4671static int ext4_meta_trans_blocks(struct inode *inode, int nrblocks, int chunk) 4671static int ext4_meta_trans_blocks(struct inode *inode, int lblocks,
4672 int pextents)
4672{ 4673{
4673 ext4_group_t groups, ngroups = ext4_get_groups_count(inode->i_sb); 4674 ext4_group_t groups, ngroups = ext4_get_groups_count(inode->i_sb);
4674 int gdpblocks; 4675 int gdpblocks;
@@ -4676,14 +4677,10 @@ static int ext4_meta_trans_blocks(struct inode *inode, int nrblocks, int chunk)
4676 int ret = 0; 4677 int ret = 0;
4677 4678
4678 /* 4679 /*
4679 * How many index blocks need to touch to modify nrblocks? 4680 * How many index blocks need to touch to map @lblocks logical blocks
4680 * The "Chunk" flag indicating whether the nrblocks is 4681 * to @pextents physical extents?
4681 * physically contiguous on disk
4682 *
4683 * For Direct IO and fallocate, they calls get_block to allocate
4684 * one single extent at a time, so they could set the "Chunk" flag
4685 */ 4682 */
4686 idxblocks = ext4_index_trans_blocks(inode, nrblocks, chunk); 4683 idxblocks = ext4_index_trans_blocks(inode, lblocks, pextents);
4687 4684
4688 ret = idxblocks; 4685 ret = idxblocks;
4689 4686
@@ -4691,12 +4688,7 @@ static int ext4_meta_trans_blocks(struct inode *inode, int nrblocks, int chunk)
4691 * Now let's see how many group bitmaps and group descriptors need 4688 * Now let's see how many group bitmaps and group descriptors need
4692 * to account 4689 * to account
4693 */ 4690 */
4694 groups = idxblocks; 4691 groups = idxblocks + pextents;
4695 if (chunk)
4696 groups += 1;
4697 else
4698 groups += nrblocks;
4699
4700 gdpblocks = groups; 4692 gdpblocks = groups;
4701 if (groups > ngroups) 4693 if (groups > ngroups)
4702 groups = ngroups; 4694 groups = ngroups;
@@ -4727,7 +4719,7 @@ int ext4_writepage_trans_blocks(struct inode *inode)
4727 int bpp = ext4_journal_blocks_per_page(inode); 4719 int bpp = ext4_journal_blocks_per_page(inode);
4728 int ret; 4720 int ret;
4729 4721
4730 ret = ext4_meta_trans_blocks(inode, bpp, 0); 4722 ret = ext4_meta_trans_blocks(inode, bpp, bpp);
4731 4723
4732 /* Account for data blocks for journalled mode */ 4724 /* Account for data blocks for journalled mode */
4733 if (ext4_should_journal_data(inode)) 4725 if (ext4_should_journal_data(inode))