add patch initialize-retries-variable-in-ext4_da_write_inline_begin
[ext4-patch-queue.git] / adjust-reserved-cluster-accounting-when-removing-extents
blob233106e94421ba7f2d080eacea0dedf0ff77ddc4
1 ext4: adjust reserved cluster count when removing extents
3 From: Eric Whitney <enwlinux@gmail.com>
5 Modify ext4_ext_remove_space() and the code it calls to correct the
6 reserved cluster count for pending reservations (delayed allocated
7 clusters shared with allocated blocks) when a block range is removed
8 from the extent tree.  Pending reservations may be found for the clusters
9 at the ends of written or unwritten extents when a block range is removed.
10 If a physical cluster at the end of an extent is freed, it's necessary
11 to increment the reserved cluster count to maintain correct accounting
12 if the corresponding logical cluster is shared with at least one
13 delayed and unwritten extent as found in the extents status tree.
15 Add a new function, ext4_rereserve_cluster(), to reapply a reservation
16 on a delayed allocated cluster sharing blocks with a freed allocated
17 cluster.  To avoid ENOSPC on reservation, a flag is applied to
18 ext4_free_blocks() to briefly defer updating the freeclusters counter
19 when an allocated cluster is freed.  This prevents another thread
20 from allocating the freed block before the reservation can be reapplied.
22 Redefine the partial cluster object as a struct to carry more state
23 information and to clarify the code using it.
25 Adjust the conditional code structure in ext4_ext_remove_space to
26 reduce the indentation level in the main body of the code to improve
27 readability.
29 Signed-off-by: Eric Whitney <enwlinux@gmail.com>
30 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
31 ---
32  fs/ext4/ext4.h              |   1 +
33  fs/ext4/ext4_extents.h      |  13 ++
34  fs/ext4/extents.c           | 284 +++++++++++++++++++++++++++-----------------
35  fs/ext4/mballoc.c           |  14 ++-
36  include/trace/events/ext4.h |  60 ++++++----
37  5 files changed, 238 insertions(+), 134 deletions(-)
39 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
40 index d85fd5c8a2c4..0bdbbd151d2c 100644
41 --- a/fs/ext4/ext4.h
42 +++ b/fs/ext4/ext4.h
43 @@ -628,6 +628,7 @@ enum {
44  #define EXT4_FREE_BLOCKS_NO_QUOT_UPDATE                0x0008
45  #define EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER  0x0010
46  #define EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER   0x0020
47 +#define EXT4_FREE_BLOCKS_RERESERVE_CLUSTER      0x0040
49  /*
50   * ioctl commands
51 diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h
52 index adf6668b596f..98bd0e9ee7df 100644
53 --- a/fs/ext4/ext4_extents.h
54 +++ b/fs/ext4/ext4_extents.h
55 @@ -120,6 +120,19 @@ struct ext4_ext_path {
56  };
58  /*
59 + * Used to record a portion of a cluster found at the beginning or end
60 + * of an extent while traversing the extent tree during space removal.
61 + * A partial cluster may be removed if it does not contain blocks shared
62 + * with extents that aren't being deleted (tofree state).  Otherwise,
63 + * it cannot be removed (nofree state).
64 + */
65 +struct partial_cluster {
66 +       ext4_fsblk_t pclu;  /* physical cluster number */
67 +       ext4_lblk_t lblk;   /* logical block number within logical cluster */
68 +       enum {initial, tofree, nofree} state;
69 +};
71 +/*
72   * structure for external API
73   */
75 diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
76 index b52ac813ca20..240b6dea5441 100644
77 --- a/fs/ext4/extents.c
78 +++ b/fs/ext4/extents.c
79 @@ -2490,106 +2490,157 @@ static inline int get_default_free_blocks_flags(struct inode *inode)
80         return 0;
81  }
83 +/*
84 + * ext4_rereserve_cluster - increment the reserved cluster count when
85 + *                          freeing a cluster with a pending reservation
86 + *
87 + * @inode - file containing the cluster
88 + * @lblk - logical block in cluster to be reserved
89 + *
90 + * Increments the reserved cluster count and adjusts quota in a bigalloc
91 + * file system when freeing a partial cluster containing at least one
92 + * delayed and unwritten block.  A partial cluster meeting that
93 + * requirement will have a pending reservation.  If so, the
94 + * RERESERVE_CLUSTER flag is used when calling ext4_free_blocks() to
95 + * defer reserved and allocated space accounting to a subsequent call
96 + * to this function.
97 + */
98 +static void ext4_rereserve_cluster(struct inode *inode, ext4_lblk_t lblk)
100 +       struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
101 +       struct ext4_inode_info *ei = EXT4_I(inode);
103 +       dquot_reclaim_block(inode, EXT4_C2B(sbi, 1));
105 +       spin_lock(&ei->i_block_reservation_lock);
106 +       ei->i_reserved_data_blocks++;
107 +       percpu_counter_add(&sbi->s_dirtyclusters_counter, 1);
108 +       spin_unlock(&ei->i_block_reservation_lock);
110 +       percpu_counter_add(&sbi->s_freeclusters_counter, 1);
111 +       ext4_remove_pending(inode, lblk);
114  static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
115                               struct ext4_extent *ex,
116 -                             long long *partial_cluster,
117 +                             struct partial_cluster *partial,
118                               ext4_lblk_t from, ext4_lblk_t to)
120         struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
121         unsigned short ee_len = ext4_ext_get_actual_len(ex);
122 -       ext4_fsblk_t pblk;
123 -       int flags = get_default_free_blocks_flags(inode);
124 +       ext4_fsblk_t last_pblk, pblk;
125 +       ext4_lblk_t num;
126 +       int flags;
128 +       /* only extent tail removal is allowed */
129 +       if (from < le32_to_cpu(ex->ee_block) ||
130 +           to != le32_to_cpu(ex->ee_block) + ee_len - 1) {
131 +               ext4_error(sbi->s_sb,
132 +                          "strange request: removal(2) %u-%u from %u:%u",
133 +                          from, to, le32_to_cpu(ex->ee_block), ee_len);
134 +               return 0;
135 +       }
137 +#ifdef EXTENTS_STATS
138 +       spin_lock(&sbi->s_ext_stats_lock);
139 +       sbi->s_ext_blocks += ee_len;
140 +       sbi->s_ext_extents++;
141 +       if (ee_len < sbi->s_ext_min)
142 +               sbi->s_ext_min = ee_len;
143 +       if (ee_len > sbi->s_ext_max)
144 +               sbi->s_ext_max = ee_len;
145 +       if (ext_depth(inode) > sbi->s_depth_max)
146 +               sbi->s_depth_max = ext_depth(inode);
147 +       spin_unlock(&sbi->s_ext_stats_lock);
148 +#endif
150 +       trace_ext4_remove_blocks(inode, ex, from, to, partial);
152         /*
153 -        * For bigalloc file systems, we never free a partial cluster
154 -        * at the beginning of the extent.  Instead, we make a note
155 -        * that we tried freeing the cluster, and check to see if we
156 -        * need to free it on a subsequent call to ext4_remove_blocks,
157 -        * or at the end of ext4_ext_rm_leaf or ext4_ext_remove_space.
158 +        * if we have a partial cluster, and it's different from the
159 +        * cluster of the last block in the extent, we free it
160          */
161 -       flags |= EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER;
162 +       last_pblk = ext4_ext_pblock(ex) + ee_len - 1;
164 +       if (partial->state != initial &&
165 +           partial->pclu != EXT4_B2C(sbi, last_pblk)) {
166 +               if (partial->state == tofree) {
167 +                       flags = get_default_free_blocks_flags(inode);
168 +                       if (ext4_is_pending(inode, partial->lblk))
169 +                               flags |= EXT4_FREE_BLOCKS_RERESERVE_CLUSTER;
170 +                       ext4_free_blocks(handle, inode, NULL,
171 +                                        EXT4_C2B(sbi, partial->pclu),
172 +                                        sbi->s_cluster_ratio, flags);
173 +                       if (flags & EXT4_FREE_BLOCKS_RERESERVE_CLUSTER)
174 +                               ext4_rereserve_cluster(inode, partial->lblk);
175 +               }
176 +               partial->state = initial;
177 +       }
179 +       num = le32_to_cpu(ex->ee_block) + ee_len - from;
180 +       pblk = ext4_ext_pblock(ex) + ee_len - num;
182 -       trace_ext4_remove_blocks(inode, ex, from, to, *partial_cluster);
183         /*
184 -        * If we have a partial cluster, and it's different from the
185 -        * cluster of the last block, we need to explicitly free the
186 -        * partial cluster here.
187 +        * We free the partial cluster at the end of the extent (if any),
188 +        * unless the cluster is used by another extent (partial_cluster
189 +        * state is nofree).  If a partial cluster exists here, it must be
190 +        * shared with the last block in the extent.
191          */
192 -       pblk = ext4_ext_pblock(ex) + ee_len - 1;
193 -       if (*partial_cluster > 0 &&
194 -           *partial_cluster != (long long) EXT4_B2C(sbi, pblk)) {
195 +       flags = get_default_free_blocks_flags(inode);
197 +       /* partial, left end cluster aligned, right end unaligned */
198 +       if ((EXT4_LBLK_COFF(sbi, to) != sbi->s_cluster_ratio - 1) &&
199 +           (EXT4_LBLK_CMASK(sbi, to) >= from) &&
200 +           (partial->state != nofree)) {
201 +               if (ext4_is_pending(inode, to))
202 +                       flags |= EXT4_FREE_BLOCKS_RERESERVE_CLUSTER;
203                 ext4_free_blocks(handle, inode, NULL,
204 -                                EXT4_C2B(sbi, *partial_cluster),
205 +                                EXT4_PBLK_CMASK(sbi, last_pblk),
206                                  sbi->s_cluster_ratio, flags);
207 -               *partial_cluster = 0;
208 +               if (flags & EXT4_FREE_BLOCKS_RERESERVE_CLUSTER)
209 +                       ext4_rereserve_cluster(inode, to);
210 +               partial->state = initial;
211 +               flags = get_default_free_blocks_flags(inode);
212         }
214 -#ifdef EXTENTS_STATS
215 -       {
216 -               struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
217 -               spin_lock(&sbi->s_ext_stats_lock);
218 -               sbi->s_ext_blocks += ee_len;
219 -               sbi->s_ext_extents++;
220 -               if (ee_len < sbi->s_ext_min)
221 -                       sbi->s_ext_min = ee_len;
222 -               if (ee_len > sbi->s_ext_max)
223 -                       sbi->s_ext_max = ee_len;
224 -               if (ext_depth(inode) > sbi->s_depth_max)
225 -                       sbi->s_depth_max = ext_depth(inode);
226 -               spin_unlock(&sbi->s_ext_stats_lock);
227 -       }
228 -#endif
229 -       if (from >= le32_to_cpu(ex->ee_block)
230 -           && to == le32_to_cpu(ex->ee_block) + ee_len - 1) {
231 -               /* tail removal */
232 -               ext4_lblk_t num;
233 -               long long first_cluster;
235 -               num = le32_to_cpu(ex->ee_block) + ee_len - from;
236 -               pblk = ext4_ext_pblock(ex) + ee_len - num;
237 -               /*
238 -                * Usually we want to free partial cluster at the end of the
239 -                * extent, except for the situation when the cluster is still
240 -                * used by any other extent (partial_cluster is negative).
241 -                */
242 -               if (*partial_cluster < 0 &&
243 -                   *partial_cluster == -(long long) EXT4_B2C(sbi, pblk+num-1))
244 -                       flags |= EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER;
245 +       flags |= EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER;
247 -               ext_debug("free last %u blocks starting %llu partial %lld\n",
248 -                         num, pblk, *partial_cluster);
249 -               ext4_free_blocks(handle, inode, NULL, pblk, num, flags);
250 -               /*
251 -                * If the block range to be freed didn't start at the
252 -                * beginning of a cluster, and we removed the entire
253 -                * extent and the cluster is not used by any other extent,
254 -                * save the partial cluster here, since we might need to
255 -                * delete if we determine that the truncate or punch hole
256 -                * operation has removed all of the blocks in the cluster.
257 -                * If that cluster is used by another extent, preserve its
258 -                * negative value so it isn't freed later on.
259 -                *
260 -                * If the whole extent wasn't freed, we've reached the
261 -                * start of the truncated/punched region and have finished
262 -                * removing blocks.  If there's a partial cluster here it's
263 -                * shared with the remainder of the extent and is no longer
264 -                * a candidate for removal.
265 -                */
266 -               if (EXT4_PBLK_COFF(sbi, pblk) && ee_len == num) {
267 -                       first_cluster = (long long) EXT4_B2C(sbi, pblk);
268 -                       if (first_cluster != -*partial_cluster)
269 -                               *partial_cluster = first_cluster;
270 -               } else {
271 -                       *partial_cluster = 0;
272 +       /*
273 +        * For bigalloc file systems, we never free a partial cluster
274 +        * at the beginning of the extent.  Instead, we check to see if we
275 +        * need to free it on a subsequent call to ext4_remove_blocks,
276 +        * or at the end of ext4_ext_rm_leaf or ext4_ext_remove_space.
277 +        */
278 +       flags |= EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER;
279 +       ext4_free_blocks(handle, inode, NULL, pblk, num, flags);
281 +       /* reset the partial cluster if we've freed past it */
282 +       if (partial->state != initial && partial->pclu != EXT4_B2C(sbi, pblk))
283 +               partial->state = initial;
285 +       /*
286 +        * If we've freed the entire extent but the beginning is not left
287 +        * cluster aligned and is not marked as ineligible for freeing we
288 +        * record the partial cluster at the beginning of the extent.  It
289 +        * wasn't freed by the preceding ext4_free_blocks() call, and we
290 +        * need to look farther to the left to determine if it's to be freed
291 +        * (not shared with another extent). Else, reset the partial
292 +        * cluster - we're either  done freeing or the beginning of the
293 +        * extent is left cluster aligned.
294 +        */
295 +       if (EXT4_LBLK_COFF(sbi, from) && num == ee_len) {
296 +               if (partial->state == initial) {
297 +                       partial->pclu = EXT4_B2C(sbi, pblk);
298 +                       partial->lblk = from;
299 +                       partial->state = tofree;
300                 }
301 -       } else
302 -               ext4_error(sbi->s_sb, "strange request: removal(2) "
303 -                          "%u-%u from %u:%u",
304 -                          from, to, le32_to_cpu(ex->ee_block), ee_len);
305 +       } else {
306 +               partial->state = initial;
307 +       }
309         return 0;
313  /*
314   * ext4_ext_rm_leaf() Removes the extents associated with the
315   * blocks appearing between "start" and "end".  Both "start"
316 @@ -2608,7 +2659,7 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
317  static int
318  ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
319                  struct ext4_ext_path *path,
320 -                long long *partial_cluster,
321 +                struct partial_cluster *partial,
322                  ext4_lblk_t start, ext4_lblk_t end)
324         struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
325 @@ -2640,7 +2691,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
326         ex_ee_block = le32_to_cpu(ex->ee_block);
327         ex_ee_len = ext4_ext_get_actual_len(ex);
329 -       trace_ext4_ext_rm_leaf(inode, start, ex, *partial_cluster);
330 +       trace_ext4_ext_rm_leaf(inode, start, ex, partial);
332         while (ex >= EXT_FIRST_EXTENT(eh) &&
333                         ex_ee_block + ex_ee_len > start) {
334 @@ -2671,8 +2722,8 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
335                          */
336                         if (sbi->s_cluster_ratio > 1) {
337                                 pblk = ext4_ext_pblock(ex);
338 -                               *partial_cluster =
339 -                                       -(long long) EXT4_B2C(sbi, pblk);
340 +                               partial->pclu = EXT4_B2C(sbi, pblk);
341 +                               partial->state = nofree;
342                         }
343                         ex--;
344                         ex_ee_block = le32_to_cpu(ex->ee_block);
345 @@ -2714,8 +2765,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
346                 if (err)
347                         goto out;
349 -               err = ext4_remove_blocks(handle, inode, ex, partial_cluster,
350 -                                        a, b);
351 +               err = ext4_remove_blocks(handle, inode, ex, partial, a, b);
352                 if (err)
353                         goto out;
355 @@ -2769,18 +2819,23 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
356          * If there's a partial cluster and at least one extent remains in
357          * the leaf, free the partial cluster if it isn't shared with the
358          * current extent.  If it is shared with the current extent
359 -        * we zero partial_cluster because we've reached the start of the
360 +        * we reset the partial cluster because we've reached the start of the
361          * truncated/punched region and we're done removing blocks.
362          */
363 -       if (*partial_cluster > 0 && ex >= EXT_FIRST_EXTENT(eh)) {
364 +       if (partial->state == tofree && ex >= EXT_FIRST_EXTENT(eh)) {
365                 pblk = ext4_ext_pblock(ex) + ex_ee_len - 1;
366 -               if (*partial_cluster != (long long) EXT4_B2C(sbi, pblk)) {
367 +               if (partial->pclu != EXT4_B2C(sbi, pblk)) {
368 +                       int flags = get_default_free_blocks_flags(inode);
370 +                       if (ext4_is_pending(inode, partial->lblk))
371 +                               flags |= EXT4_FREE_BLOCKS_RERESERVE_CLUSTER;
372                         ext4_free_blocks(handle, inode, NULL,
373 -                                        EXT4_C2B(sbi, *partial_cluster),
374 -                                        sbi->s_cluster_ratio,
375 -                                        get_default_free_blocks_flags(inode));
376 +                                        EXT4_C2B(sbi, partial->pclu),
377 +                                        sbi->s_cluster_ratio, flags);
378 +                       if (flags & EXT4_FREE_BLOCKS_RERESERVE_CLUSTER)
379 +                               ext4_rereserve_cluster(inode, partial->lblk);
380                 }
381 -               *partial_cluster = 0;
382 +               partial->state = initial;
383         }
385         /* if this leaf is free, then we should
386 @@ -2819,10 +2874,14 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
387         struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
388         int depth = ext_depth(inode);
389         struct ext4_ext_path *path = NULL;
390 -       long long partial_cluster = 0;
391 +       struct partial_cluster partial;
392         handle_t *handle;
393         int i = 0, err = 0;
395 +       partial.pclu = 0;
396 +       partial.lblk = 0;
397 +       partial.state = initial;
399         ext_debug("truncate since %u to %u\n", start, end);
401         /* probably first extent we're gonna free will be last in block */
402 @@ -2882,8 +2941,8 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
403                          */
404                         if (sbi->s_cluster_ratio > 1) {
405                                 pblk = ext4_ext_pblock(ex) + end - ee_block + 2;
406 -                               partial_cluster =
407 -                                       -(long long) EXT4_B2C(sbi, pblk);
408 +                               partial.pclu = EXT4_B2C(sbi, pblk);
409 +                               partial.state = nofree;
410                         }
412                         /*
413 @@ -2911,9 +2970,10 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
414                                                     &ex);
415                         if (err)
416                                 goto out;
417 -                       if (pblk)
418 -                               partial_cluster =
419 -                                       -(long long) EXT4_B2C(sbi, pblk);
420 +                       if (pblk) {
421 +                               partial.pclu = EXT4_B2C(sbi, pblk);
422 +                               partial.state = nofree;
423 +                       }
424                 }
425         }
426         /*
427 @@ -2948,8 +3008,7 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
428                 if (i == depth) {
429                         /* this is leaf block */
430                         err = ext4_ext_rm_leaf(handle, inode, path,
431 -                                              &partial_cluster, start,
432 -                                              end);
433 +                                              &partial, start, end);
434                         /* root level has p_bh == NULL, brelse() eats this */
435                         brelse(path[i].p_bh);
436                         path[i].p_bh = NULL;
437 @@ -3021,21 +3080,24 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
438                 }
439         }
441 -       trace_ext4_ext_remove_space_done(inode, start, end, depth,
442 -                       partial_cluster, path->p_hdr->eh_entries);
443 +       trace_ext4_ext_remove_space_done(inode, start, end, depth, &partial,
444 +                                        path->p_hdr->eh_entries);
446         /*
447 -        * If we still have something in the partial cluster and we have removed
448 -        * even the first extent, then we should free the blocks in the partial
449 -        * cluster as well.  (This code will only run when there are no leaves
450 -        * to the immediate left of the truncated/punched region.)
451 +        * if there's a partial cluster and we have removed the first extent
452 +        * in the file, then we also free the partial cluster, if any
453          */
454 -       if (partial_cluster > 0 && err == 0) {
455 -               /* don't zero partial_cluster since it's not used afterwards */
456 +       if (partial.state == tofree && err == 0) {
457 +               int flags = get_default_free_blocks_flags(inode);
459 +               if (ext4_is_pending(inode, partial.lblk))
460 +                       flags |= EXT4_FREE_BLOCKS_RERESERVE_CLUSTER;
461                 ext4_free_blocks(handle, inode, NULL,
462 -                                EXT4_C2B(sbi, partial_cluster),
463 -                                sbi->s_cluster_ratio,
464 -                                get_default_free_blocks_flags(inode));
465 +                                EXT4_C2B(sbi, partial.pclu),
466 +                                sbi->s_cluster_ratio, flags);
467 +               if (flags & EXT4_FREE_BLOCKS_RERESERVE_CLUSTER)
468 +                       ext4_rereserve_cluster(inode, partial.lblk);
469 +               partial.state = initial;
470         }
472         /* TODO: flexible tree reduction should be here */
473 diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
474 index e29fce2fbf25..e2248083cdca 100644
475 --- a/fs/ext4/mballoc.c
476 +++ b/fs/ext4/mballoc.c
477 @@ -4915,9 +4915,17 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
478                              &sbi->s_flex_groups[flex_group].free_clusters);
479         }
481 -       if (!(flags & EXT4_FREE_BLOCKS_NO_QUOT_UPDATE))
482 -               dquot_free_block(inode, EXT4_C2B(sbi, count_clusters));
483 -       percpu_counter_add(&sbi->s_freeclusters_counter, count_clusters);
484 +       /*
485 +        * on a bigalloc file system, defer the s_freeclusters_counter
486 +        * update to the caller (ext4_remove_space and friends) so they
487 +        * can determine if a cluster freed here should be rereserved
488 +        */
489 +       if (!(flags & EXT4_FREE_BLOCKS_RERESERVE_CLUSTER)) {
490 +               if (!(flags & EXT4_FREE_BLOCKS_NO_QUOT_UPDATE))
491 +                       dquot_free_block(inode, EXT4_C2B(sbi, count_clusters));
492 +               percpu_counter_add(&sbi->s_freeclusters_counter,
493 +                                  count_clusters);
494 +       }
496         ext4_mb_unload_buddy(&e4b);
498 diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
499 index 6d7a943f849c..698e0d8a5ca4 100644
500 --- a/include/trace/events/ext4.h
501 +++ b/include/trace/events/ext4.h
502 @@ -17,6 +17,7 @@ struct mpage_da_data;
503  struct ext4_map_blocks;
504  struct extent_status;
505  struct ext4_fsmap;
506 +struct partial_cluster;
508  #define EXT4_I(inode) (container_of(inode, struct ext4_inode_info, vfs_inode))
510 @@ -2035,21 +2036,23 @@ TRACE_EVENT(ext4_ext_show_extent,
511  );
513  TRACE_EVENT(ext4_remove_blocks,
514 -           TP_PROTO(struct inode *inode, struct ext4_extent *ex,
515 -               ext4_lblk_t from, ext4_fsblk_t to,
516 -               long long partial_cluster),
517 +       TP_PROTO(struct inode *inode, struct ext4_extent *ex,
518 +                ext4_lblk_t from, ext4_fsblk_t to,
519 +                struct partial_cluster *pc),
521 -       TP_ARGS(inode, ex, from, to, partial_cluster),
522 +       TP_ARGS(inode, ex, from, to, pc),
524         TP_STRUCT__entry(
525                 __field(        dev_t,          dev     )
526                 __field(        ino_t,          ino     )
527                 __field(        ext4_lblk_t,    from    )
528                 __field(        ext4_lblk_t,    to      )
529 -               __field(        long long,      partial )
530                 __field(        ext4_fsblk_t,   ee_pblk )
531                 __field(        ext4_lblk_t,    ee_lblk )
532                 __field(        unsigned short, ee_len  )
533 +               __field(        ext4_fsblk_t,   pc_pclu )
534 +               __field(        ext4_lblk_t,    pc_lblk )
535 +               __field(        int,            pc_state)
536         ),
538         TP_fast_assign(
539 @@ -2057,14 +2060,16 @@ TRACE_EVENT(ext4_remove_blocks,
540                 __entry->ino            = inode->i_ino;
541                 __entry->from           = from;
542                 __entry->to             = to;
543 -               __entry->partial        = partial_cluster;
544                 __entry->ee_pblk        = ext4_ext_pblock(ex);
545                 __entry->ee_lblk        = le32_to_cpu(ex->ee_block);
546                 __entry->ee_len         = ext4_ext_get_actual_len(ex);
547 +               __entry->pc_pclu        = pc->pclu;
548 +               __entry->pc_lblk        = pc->lblk;
549 +               __entry->pc_state       = pc->state;
550         ),
552         TP_printk("dev %d,%d ino %lu extent [%u(%llu), %u]"
553 -                 "from %u to %u partial_cluster %lld",
554 +                 "from %u to %u partial [pclu %lld lblk %u state %d]",
555                   MAJOR(__entry->dev), MINOR(__entry->dev),
556                   (unsigned long) __entry->ino,
557                   (unsigned) __entry->ee_lblk,
558 @@ -2072,45 +2077,53 @@ TRACE_EVENT(ext4_remove_blocks,
559                   (unsigned short) __entry->ee_len,
560                   (unsigned) __entry->from,
561                   (unsigned) __entry->to,
562 -                 (long long) __entry->partial)
563 +                 (long long) __entry->pc_pclu,
564 +                 (unsigned int) __entry->pc_lblk,
565 +                 (int) __entry->pc_state)
566  );
568  TRACE_EVENT(ext4_ext_rm_leaf,
569         TP_PROTO(struct inode *inode, ext4_lblk_t start,
570                  struct ext4_extent *ex,
571 -                long long partial_cluster),
572 +                struct partial_cluster *pc),
574 -       TP_ARGS(inode, start, ex, partial_cluster),
575 +       TP_ARGS(inode, start, ex, pc),
577         TP_STRUCT__entry(
578                 __field(        dev_t,          dev     )
579                 __field(        ino_t,          ino     )
580 -               __field(        long long,      partial )
581                 __field(        ext4_lblk_t,    start   )
582                 __field(        ext4_lblk_t,    ee_lblk )
583                 __field(        ext4_fsblk_t,   ee_pblk )
584                 __field(        short,          ee_len  )
585 +               __field(        ext4_fsblk_t,   pc_pclu )
586 +               __field(        ext4_lblk_t,    pc_lblk )
587 +               __field(        int,            pc_state)
588         ),
590         TP_fast_assign(
591                 __entry->dev            = inode->i_sb->s_dev;
592                 __entry->ino            = inode->i_ino;
593 -               __entry->partial        = partial_cluster;
594                 __entry->start          = start;
595                 __entry->ee_lblk        = le32_to_cpu(ex->ee_block);
596                 __entry->ee_pblk        = ext4_ext_pblock(ex);
597                 __entry->ee_len         = ext4_ext_get_actual_len(ex);
598 +               __entry->pc_pclu        = pc->pclu;
599 +               __entry->pc_lblk        = pc->lblk;
600 +               __entry->pc_state       = pc->state;
601         ),
603         TP_printk("dev %d,%d ino %lu start_lblk %u last_extent [%u(%llu), %u]"
604 -                 "partial_cluster %lld",
605 +                 "partial [pclu %lld lblk %u state %d]",
606                   MAJOR(__entry->dev), MINOR(__entry->dev),
607                   (unsigned long) __entry->ino,
608                   (unsigned) __entry->start,
609                   (unsigned) __entry->ee_lblk,
610                   (unsigned long long) __entry->ee_pblk,
611                   (unsigned short) __entry->ee_len,
612 -                 (long long) __entry->partial)
613 +                 (long long) __entry->pc_pclu,
614 +                 (unsigned int) __entry->pc_lblk,
615 +                 (int) __entry->pc_state)
616  );
618  TRACE_EVENT(ext4_ext_rm_idx,
619 @@ -2168,9 +2181,9 @@ TRACE_EVENT(ext4_ext_remove_space,
621  TRACE_EVENT(ext4_ext_remove_space_done,
622         TP_PROTO(struct inode *inode, ext4_lblk_t start, ext4_lblk_t end,
623 -                int depth, long long partial, __le16 eh_entries),
624 +                int depth, struct partial_cluster *pc, __le16 eh_entries),
626 -       TP_ARGS(inode, start, end, depth, partial, eh_entries),
627 +       TP_ARGS(inode, start, end, depth, pc, eh_entries),
629         TP_STRUCT__entry(
630                 __field(        dev_t,          dev             )
631 @@ -2178,7 +2191,9 @@ TRACE_EVENT(ext4_ext_remove_space_done,
632                 __field(        ext4_lblk_t,    start           )
633                 __field(        ext4_lblk_t,    end             )
634                 __field(        int,            depth           )
635 -               __field(        long long,      partial         )
636 +               __field(        ext4_fsblk_t,   pc_pclu         )
637 +               __field(        ext4_lblk_t,    pc_lblk         )
638 +               __field(        int,            pc_state        )
639                 __field(        unsigned short, eh_entries      )
640         ),
642 @@ -2188,18 +2203,23 @@ TRACE_EVENT(ext4_ext_remove_space_done,
643                 __entry->start          = start;
644                 __entry->end            = end;
645                 __entry->depth          = depth;
646 -               __entry->partial        = partial;
647 +               __entry->pc_pclu        = pc->pclu;
648 +               __entry->pc_lblk        = pc->lblk;
649 +               __entry->pc_state       = pc->state;
650                 __entry->eh_entries     = le16_to_cpu(eh_entries);
651         ),
653 -       TP_printk("dev %d,%d ino %lu since %u end %u depth %d partial %lld "
654 +       TP_printk("dev %d,%d ino %lu since %u end %u depth %d "
655 +                 "partial [pclu %lld lblk %u state %d] "
656                   "remaining_entries %u",
657                   MAJOR(__entry->dev), MINOR(__entry->dev),
658                   (unsigned long) __entry->ino,
659                   (unsigned) __entry->start,
660                   (unsigned) __entry->end,
661                   __entry->depth,
662 -                 (long long) __entry->partial,
663 +                 (long long) __entry->pc_pclu,
664 +                 (unsigned int) __entry->pc_lblk,
665 +                 (int) __entry->pc_state,
666                   (unsigned short) __entry->eh_entries)
667  );
669 -- 
670 2.11.0