add patch pass-inode-pointer-instead-of-file-pointer-to-punch-hole
[ext4-patch-queue.git] / better-estimate-credits-needed-for-ext4_da_writepages
blob992a20b987bdfb1b6d83ab7bf759d9c2d30e6cdf
1 ext4: better estimate credits needed for ext4_da_writepages()
3 From: Jan Kara <jack@suse.cz>
5 We limit the number of blocks written in a single loop of
6 ext4_da_writepages() to 64 when inode uses indirect blocks.  That is
7 unnecessary as credit estimates for mapping logically continguous run
8 of blocks is rather low even for inode with indirect blocks.  So just
9 lift this limitation and properly calculate the number of necessary
10 credits.
12 This better credit estimate will also later allow us to always write
13 at least a single page in one iteration.
15 Reviewed-by: Zheng Liu <wenqing.lz@taobao.com>
16 Signed-off-by: Jan Kara <jack@suse.cz>
17 Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
18 ---
19  fs/ext4/ext4.h    |  3 +--
20  fs/ext4/extents.c | 16 +++++++---------
21  fs/ext4/inode.c   | 62 +++++++++++++++++++++++++++-----------------------------------
22  3 files changed, 35 insertions(+), 46 deletions(-)
24 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
25 index 25e261d..2ebfcde 100644
26 --- a/fs/ext4/ext4.h
27 +++ b/fs/ext4/ext4.h
28 @@ -2596,8 +2596,7 @@ struct ext4_extent;
30  extern int ext4_ext_tree_init(handle_t *handle, struct inode *);
31  extern int ext4_ext_writepage_trans_blocks(struct inode *, int);
32 -extern int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks,
33 -                                      int chunk);
34 +extern int ext4_ext_index_trans_blocks(struct inode *inode, int extents);
35  extern int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
36                                struct ext4_map_blocks *map, int flags);
37  extern void ext4_ext_truncate(handle_t *, struct inode *);
38 diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
39 index 299ee9d..94283d0 100644
40 --- a/fs/ext4/extents.c
41 +++ b/fs/ext4/extents.c
42 @@ -2328,17 +2328,15 @@ int ext4_ext_calc_credits_for_single_extent(struct inode *inode, int nrblocks,
43  }
45  /*
46 - * How many index/leaf blocks need to change/allocate to modify nrblocks?
47 + * How many index/leaf blocks need to change/allocate to add @extents extents?
48   *
49 - * if nrblocks are fit in a single extent (chunk flag is 1), then
50 - * in the worse case, each tree level index/leaf need to be changed
51 - * if the tree split due to insert a new extent, then the old tree
52 - * index/leaf need to be updated too
53 + * If we add a single extent, then in the worse case, each tree level
54 + * index/leaf need to be changed in case of the tree split.
55   *
56 - * If the nrblocks are discontiguous, they could cause
57 - * the whole tree split more than once, but this is really rare.
58 + * If more extents are inserted, they could cause the whole tree split more
59 + * than once, but this is really rare.
60   */
61 -int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks, int chunk)
62 +int ext4_ext_index_trans_blocks(struct inode *inode, int extents)
63  {
64         int index;
65         int depth;
66 @@ -2349,7 +2347,7 @@ int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks, int chunk)
68         depth = ext_depth(inode);
70 -       if (chunk)
71 +       if (extents <= 1)
72                 index = depth * 2;
73         else
74                 index = depth * 3;
75 diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
76 index 23d9a44..2b777e5 100644
77 --- a/fs/ext4/inode.c
78 +++ b/fs/ext4/inode.c
79 @@ -136,6 +136,8 @@ static void ext4_invalidatepage(struct page *page, unsigned int offset,
80                                 unsigned int length);
81  static int __ext4_journalled_writepage(struct page *page, unsigned int len);
82  static int ext4_bh_delay_or_unwritten(handle_t *handle, struct buffer_head *bh);
83 +static int ext4_meta_trans_blocks(struct inode *inode, int lblocks,
84 +                                 int pextents);
86  /*
87   * Test whether an inode is a fast symlink.
88 @@ -2203,28 +2205,25 @@ static int ext4_writepage(struct page *page,
89  }
91  /*
92 - * This is called via ext4_da_writepages() to
93 - * calculate the total number of credits to reserve to fit
94 - * a single extent allocation into a single transaction,
95 - * ext4_da_writpeages() will loop calling this before
96 - * the block allocation.
97 + * mballoc gives us at most this number of blocks...
98 + * XXX: That seems to be only a limitation of ext4_mb_normalize_request().
99 + * The rest of mballoc seems to handle chunks upto full group size.
100   */
101 +#define MAX_WRITEPAGES_EXTENT_LEN 2048
104 + * Calculate the total number of credits to reserve for one writepages
105 + * iteration. This is called from ext4_da_writepages(). We map an extent of
106 + * upto MAX_WRITEPAGES_EXTENT_LEN blocks and then we go on and finish mapping
107 + * the last partial page. So in total we can map MAX_WRITEPAGES_EXTENT_LEN +
108 + * bpp - 1 blocks in bpp different extents.
109 + */
110  static int ext4_da_writepages_trans_blocks(struct inode *inode)
112 -       int max_blocks = EXT4_I(inode)->i_reserved_data_blocks;
114 -       /*
115 -        * With non-extent format the journal credit needed to
116 -        * insert nrblocks contiguous block is dependent on
117 -        * number of contiguous block. So we will limit
118 -        * number of contiguous block to a sane value
119 -        */
120 -       if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) &&
121 -           (max_blocks > EXT4_MAX_TRANS_DATA))
122 -               max_blocks = EXT4_MAX_TRANS_DATA;
123 +       int bpp = ext4_journal_blocks_per_page(inode);
125 -       return ext4_chunk_trans_blocks(inode, max_blocks);
126 +       return ext4_meta_trans_blocks(inode,
127 +                               MAX_WRITEPAGES_EXTENT_LEN + bpp - 1, bpp);
130  /*
131 @@ -4650,11 +4649,12 @@ int ext4_getattr(struct vfsmount *mnt, struct dentry *dentry,
132         return 0;
135 -static int ext4_index_trans_blocks(struct inode *inode, int nrblocks, int chunk)
136 +static int ext4_index_trans_blocks(struct inode *inode, int lblocks,
137 +                                  int pextents)
139         if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
140 -               return ext4_ind_trans_blocks(inode, nrblocks);
141 -       return ext4_ext_index_trans_blocks(inode, nrblocks, chunk);
142 +               return ext4_ind_trans_blocks(inode, lblocks);
143 +       return ext4_ext_index_trans_blocks(inode, pextents);
146  /*
147 @@ -4668,7 +4668,8 @@ static int ext4_index_trans_blocks(struct inode *inode, int nrblocks, int chunk)
148   *
149   * Also account for superblock, inode, quota and xattr blocks
150   */
151 -static int ext4_meta_trans_blocks(struct inode *inode, int nrblocks, int chunk)
152 +static int ext4_meta_trans_blocks(struct inode *inode, int lblocks,
153 +                                 int pextents)
155         ext4_group_t groups, ngroups = ext4_get_groups_count(inode->i_sb);
156         int gdpblocks;
157 @@ -4676,14 +4677,10 @@ static int ext4_meta_trans_blocks(struct inode *inode, int nrblocks, int chunk)
158         int ret = 0;
160         /*
161 -        * How many index blocks need to touch to modify nrblocks?
162 -        * The "Chunk" flag indicating whether the nrblocks is
163 -        * physically contiguous on disk
164 -        *
165 -        * For Direct IO and fallocate, they calls get_block to allocate
166 -        * one single extent at a time, so they could set the "Chunk" flag
167 +        * How many index blocks need to touch to map @lblocks logical blocks
168 +        * to @pextents physical extents?
169          */
170 -       idxblocks = ext4_index_trans_blocks(inode, nrblocks, chunk);
171 +       idxblocks = ext4_index_trans_blocks(inode, lblocks, pextents);
173         ret = idxblocks;
175 @@ -4691,12 +4688,7 @@ static int ext4_meta_trans_blocks(struct inode *inode, int nrblocks, int chunk)
176          * Now let's see how many group bitmaps and group descriptors need
177          * to account
178          */
179 -       groups = idxblocks;
180 -       if (chunk)
181 -               groups += 1;
182 -       else
183 -               groups += nrblocks;
185 +       groups = idxblocks + pextents;
186         gdpblocks = groups;
187         if (groups > ngroups)
188                 groups = ngroups;
189 @@ -4727,7 +4719,7 @@ int ext4_writepage_trans_blocks(struct inode *inode)
190         int bpp = ext4_journal_blocks_per_page(inode);
191         int ret;
193 -       ret = ext4_meta_trans_blocks(inode, bpp, 0);
194 +       ret = ext4_meta_trans_blocks(inode, bpp, bpp);
196         /* Account for data blocks for journalled mode */
197         if (ext4_should_journal_data(inode))