Skip to content

Commit fffb273

Browse files
jankaratytso
authored andcommitted
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 <[email protected]> Signed-off-by: Jan Kara <[email protected]> Signed-off-by: "Theodore Ts'o" <[email protected]>
1 parent fa55a0e commit fffb273

File tree

3 files changed

+35
-46
lines changed

3 files changed

+35
-46
lines changed

fs/ext4/ext4.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2596,8 +2596,7 @@ struct ext4_extent;
25962596

25972597
extern int ext4_ext_tree_init(handle_t *handle, struct inode *);
25982598
extern int ext4_ext_writepage_trans_blocks(struct inode *, int);
2599-
extern int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks,
2600-
int chunk);
2599+
extern int ext4_ext_index_trans_blocks(struct inode *inode, int extents);
26012600
extern int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
26022601
struct ext4_map_blocks *map, int flags);
26032602
extern void ext4_ext_truncate(handle_t *, struct inode *);

fs/ext4/extents.c

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2328,17 +2328,15 @@ int ext4_ext_calc_credits_for_single_extent(struct inode *inode, int nrblocks,
23282328
}
23292329

23302330
/*
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?
23322332
*
2333-
* if nrblocks are fit in a single extent (chunk flag is 1), then
2334-
* in the worse case, each tree level index/leaf need to be changed
2335-
* if the tree split due to insert a new extent, then the old tree
2336-
* index/leaf need to be updated too
2333+
* If we add a single extent, then in the worse case, each tree level
2334+
* index/leaf need to be changed in case of the tree split.
23372335
*
2338-
* If the nrblocks are discontiguous, they could cause
2339-
* the whole tree split more than once, but this is really rare.
2336+
* If more extents are inserted, they could cause the whole tree split more
2337+
* than once, but this is really rare.
23402338
*/
2341-
int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks, int chunk)
2339+
int ext4_ext_index_trans_blocks(struct inode *inode, int extents)
23422340
{
23432341
int index;
23442342
int depth;
@@ -2349,7 +2347,7 @@ int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks, int chunk)
23492347

23502348
depth = ext_depth(inode);
23512349

2352-
if (chunk)
2350+
if (extents <= 1)
23532351
index = depth * 2;
23542352
else
23552353
index = depth * 3;

fs/ext4/inode.c

Lines changed: 27 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ static void ext4_invalidatepage(struct page *page, unsigned int offset,
136136
unsigned int length);
137137
static int __ext4_journalled_writepage(struct page *page, unsigned int len);
138138
static int ext4_bh_delay_or_unwritten(handle_t *handle, struct buffer_head *bh);
139+
static int ext4_meta_trans_blocks(struct inode *inode, int lblocks,
140+
int pextents);
139141

140142
/*
141143
* Test whether an inode is a fast symlink.
@@ -2203,28 +2205,25 @@ static int ext4_writepage(struct page *page,
22032205
}
22042206

22052207
/*
2206-
* This is called via ext4_da_writepages() to
2207-
* calculate the total number of credits to reserve to fit
2208-
* a single extent allocation into a single transaction,
2209-
* ext4_da_writpeages() will loop calling this before
2210-
* the block allocation.
2208+
* mballoc gives us at most this number of blocks...
2209+
* XXX: That seems to be only a limitation of ext4_mb_normalize_request().
2210+
* The rest of mballoc seems to handle chunks upto full group size.
22112211
*/
2212+
#define MAX_WRITEPAGES_EXTENT_LEN 2048
22122213

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+
*/
22132221
static int ext4_da_writepages_trans_blocks(struct inode *inode)
22142222
{
2215-
int max_blocks = EXT4_I(inode)->i_reserved_data_blocks;
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;
2223+
int bpp = ext4_journal_blocks_per_page(inode);
22262224

2227-
return ext4_chunk_trans_blocks(inode, max_blocks);
2225+
return ext4_meta_trans_blocks(inode,
2226+
MAX_WRITEPAGES_EXTENT_LEN + bpp - 1, bpp);
22282227
}
22292228

22302229
/*
@@ -4650,11 +4649,12 @@ int ext4_getattr(struct vfsmount *mnt, struct dentry *dentry,
46504649
return 0;
46514650
}
46524651

4653-
static int ext4_index_trans_blocks(struct inode *inode, int nrblocks, int chunk)
4652+
static int ext4_index_trans_blocks(struct inode *inode, int lblocks,
4653+
int pextents)
46544654
{
46554655
if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
4656-
return ext4_ind_trans_blocks(inode, nrblocks);
4657-
return ext4_ext_index_trans_blocks(inode, nrblocks, chunk);
4656+
return ext4_ind_trans_blocks(inode, lblocks);
4657+
return ext4_ext_index_trans_blocks(inode, pextents);
46584658
}
46594659

46604660
/*
@@ -4668,35 +4668,27 @@ static int ext4_index_trans_blocks(struct inode *inode, int nrblocks, int chunk)
46684668
*
46694669
* Also account for superblock, inode, quota and xattr blocks
46704670
*/
4671-
static int ext4_meta_trans_blocks(struct inode *inode, int nrblocks, int chunk)
4671+
static int ext4_meta_trans_blocks(struct inode *inode, int lblocks,
4672+
int pextents)
46724673
{
46734674
ext4_group_t groups, ngroups = ext4_get_groups_count(inode->i_sb);
46744675
int gdpblocks;
46754676
int idxblocks;
46764677
int ret = 0;
46774678

46784679
/*
4679-
* How many index blocks need to touch to modify nrblocks?
4680-
* The "Chunk" flag indicating whether the nrblocks is
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
4680+
* How many index blocks need to touch to map @lblocks logical blocks
4681+
* to @pextents physical extents?
46854682
*/
4686-
idxblocks = ext4_index_trans_blocks(inode, nrblocks, chunk);
4683+
idxblocks = ext4_index_trans_blocks(inode, lblocks, pextents);
46874684

46884685
ret = idxblocks;
46894686

46904687
/*
46914688
* Now let's see how many group bitmaps and group descriptors need
46924689
* to account
46934690
*/
4694-
groups = idxblocks;
4695-
if (chunk)
4696-
groups += 1;
4697-
else
4698-
groups += nrblocks;
4699-
4691+
groups = idxblocks + pextents;
47004692
gdpblocks = groups;
47014693
if (groups > ngroups)
47024694
groups = ngroups;
@@ -4727,7 +4719,7 @@ int ext4_writepage_trans_blocks(struct inode *inode)
47274719
int bpp = ext4_journal_blocks_per_page(inode);
47284720
int ret;
47294721

4730-
ret = ext4_meta_trans_blocks(inode, bpp, 0);
4722+
ret = ext4_meta_trans_blocks(inode, bpp, bpp);
47314723

47324724
/* Account for data blocks for journalled mode */
47334725
if (ext4_should_journal_data(inode))

0 commit comments

Comments
 (0)