diff options
-rw-r--r-- | fs/ext4/ext4.h | 3 | ||||
-rw-r--r-- | fs/ext4/extents.c | 16 | ||||
-rw-r--r-- | fs/ext4/inode.c | 62 |
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 | ||
2597 | extern int ext4_ext_tree_init(handle_t *handle, struct inode *); | 2597 | extern int ext4_ext_tree_init(handle_t *handle, struct inode *); |
2598 | extern int ext4_ext_writepage_trans_blocks(struct inode *, int); | 2598 | extern int ext4_ext_writepage_trans_blocks(struct inode *, int); |
2599 | extern int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks, | 2599 | extern int ext4_ext_index_trans_blocks(struct inode *inode, int extents); |
2600 | int chunk); | ||
2601 | extern int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, | 2600 | extern 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); |
2603 | extern void ext4_ext_truncate(handle_t *, struct inode *); | 2602 | extern 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 | */ |
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) |
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); |
137 | static int __ext4_journalled_writepage(struct page *page, unsigned int len); | 137 | static int __ext4_journalled_writepage(struct page *page, unsigned int len); |
138 | static int ext4_bh_delay_or_unwritten(handle_t *handle, struct buffer_head *bh); | 138 | 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); | ||
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 | */ | ||
2213 | static int ext4_da_writepages_trans_blocks(struct inode *inode) | 2221 | static 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 | ||
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) | ||
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 | */ |
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) | ||
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)) |