提交 eb6f0dde 编写于 作者: E Eric Whitney 提交者: Joseph Qi

ext4: adjust reserved cluster count when removing extents

commit 9fe671496b6c286f9033aedfc1718d67721da0ae upstream.

Modify ext4_ext_remove_space() and the code it calls to correct the
reserved cluster count for pending reservations (delayed allocated
clusters shared with allocated blocks) when a block range is removed
from the extent tree.  Pending reservations may be found for the clusters
at the ends of written or unwritten extents when a block range is removed.
If a physical cluster at the end of an extent is freed, it's necessary
to increment the reserved cluster count to maintain correct accounting
if the corresponding logical cluster is shared with at least one
delayed and unwritten extent as found in the extents status tree.

Add a new function, ext4_rereserve_cluster(), to reapply a reservation
on a delayed allocated cluster sharing blocks with a freed allocated
cluster.  To avoid ENOSPC on reservation, a flag is applied to
ext4_free_blocks() to briefly defer updating the freeclusters counter
when an allocated cluster is freed.  This prevents another thread
from allocating the freed block before the reservation can be reapplied.

Redefine the partial cluster object as a struct to carry more state
information and to clarify the code using it.

Adjust the conditional code structure in ext4_ext_remove_space to
reduce the indentation level in the main body of the code to improve
readability.
Signed-off-by: NEric Whitney <enwlinux@gmail.com>
Signed-off-by: NTheodore Ts'o <tytso@mit.edu>
Signed-off-by: NJoseph Qi <joseph.qi@linux.alibaba.com>
Reviewed-by: NJiufei Xue <jiufei.xue@linux.alibaba.com>
上级 b9d79899
...@@ -631,6 +631,7 @@ enum { ...@@ -631,6 +631,7 @@ enum {
#define EXT4_FREE_BLOCKS_NO_QUOT_UPDATE 0x0008 #define EXT4_FREE_BLOCKS_NO_QUOT_UPDATE 0x0008
#define EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER 0x0010 #define EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER 0x0010
#define EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER 0x0020 #define EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER 0x0020
#define EXT4_FREE_BLOCKS_RERESERVE_CLUSTER 0x0040
/* /*
* ioctl commands * ioctl commands
......
...@@ -119,6 +119,19 @@ struct ext4_ext_path { ...@@ -119,6 +119,19 @@ struct ext4_ext_path {
struct buffer_head *p_bh; struct buffer_head *p_bh;
}; };
/*
* Used to record a portion of a cluster found at the beginning or end
* of an extent while traversing the extent tree during space removal.
* A partial cluster may be removed if it does not contain blocks shared
* with extents that aren't being deleted (tofree state). Otherwise,
* it cannot be removed (nofree state).
*/
struct partial_cluster {
ext4_fsblk_t pclu; /* physical cluster number */
ext4_lblk_t lblk; /* logical block number within logical cluster */
enum {initial, tofree, nofree} state;
};
/* /*
* structure for external API * structure for external API
*/ */
......
...@@ -2490,106 +2490,157 @@ static inline int get_default_free_blocks_flags(struct inode *inode) ...@@ -2490,106 +2490,157 @@ static inline int get_default_free_blocks_flags(struct inode *inode)
return 0; return 0;
} }
/*
* ext4_rereserve_cluster - increment the reserved cluster count when
* freeing a cluster with a pending reservation
*
* @inode - file containing the cluster
* @lblk - logical block in cluster to be reserved
*
* Increments the reserved cluster count and adjusts quota in a bigalloc
* file system when freeing a partial cluster containing at least one
* delayed and unwritten block. A partial cluster meeting that
* requirement will have a pending reservation. If so, the
* RERESERVE_CLUSTER flag is used when calling ext4_free_blocks() to
* defer reserved and allocated space accounting to a subsequent call
* to this function.
*/
static void ext4_rereserve_cluster(struct inode *inode, ext4_lblk_t lblk)
{
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
struct ext4_inode_info *ei = EXT4_I(inode);
dquot_reclaim_block(inode, EXT4_C2B(sbi, 1));
spin_lock(&ei->i_block_reservation_lock);
ei->i_reserved_data_blocks++;
percpu_counter_add(&sbi->s_dirtyclusters_counter, 1);
spin_unlock(&ei->i_block_reservation_lock);
percpu_counter_add(&sbi->s_freeclusters_counter, 1);
ext4_remove_pending(inode, lblk);
}
static int ext4_remove_blocks(handle_t *handle, struct inode *inode, static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
struct ext4_extent *ex, struct ext4_extent *ex,
long long *partial_cluster, struct partial_cluster *partial,
ext4_lblk_t from, ext4_lblk_t to) ext4_lblk_t from, ext4_lblk_t to)
{ {
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
unsigned short ee_len = ext4_ext_get_actual_len(ex); unsigned short ee_len = ext4_ext_get_actual_len(ex);
ext4_fsblk_t pblk; ext4_fsblk_t last_pblk, pblk;
int flags = get_default_free_blocks_flags(inode); ext4_lblk_t num;
int flags;
/* only extent tail removal is allowed */
if (from < le32_to_cpu(ex->ee_block) ||
to != le32_to_cpu(ex->ee_block) + ee_len - 1) {
ext4_error(sbi->s_sb,
"strange request: removal(2) %u-%u from %u:%u",
from, to, le32_to_cpu(ex->ee_block), ee_len);
return 0;
}
#ifdef EXTENTS_STATS
spin_lock(&sbi->s_ext_stats_lock);
sbi->s_ext_blocks += ee_len;
sbi->s_ext_extents++;
if (ee_len < sbi->s_ext_min)
sbi->s_ext_min = ee_len;
if (ee_len > sbi->s_ext_max)
sbi->s_ext_max = ee_len;
if (ext_depth(inode) > sbi->s_depth_max)
sbi->s_depth_max = ext_depth(inode);
spin_unlock(&sbi->s_ext_stats_lock);
#endif
trace_ext4_remove_blocks(inode, ex, from, to, partial);
/* /*
* For bigalloc file systems, we never free a partial cluster * if we have a partial cluster, and it's different from the
* at the beginning of the extent. Instead, we make a note * cluster of the last block in the extent, we free it
* that we tried freeing the cluster, and check to see if we
* need to free it on a subsequent call to ext4_remove_blocks,
* or at the end of ext4_ext_rm_leaf or ext4_ext_remove_space.
*/ */
flags |= EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER; last_pblk = ext4_ext_pblock(ex) + ee_len - 1;
if (partial->state != initial &&
partial->pclu != EXT4_B2C(sbi, last_pblk)) {
if (partial->state == tofree) {
flags = get_default_free_blocks_flags(inode);
if (ext4_is_pending(inode, partial->lblk))
flags |= EXT4_FREE_BLOCKS_RERESERVE_CLUSTER;
ext4_free_blocks(handle, inode, NULL,
EXT4_C2B(sbi, partial->pclu),
sbi->s_cluster_ratio, flags);
if (flags & EXT4_FREE_BLOCKS_RERESERVE_CLUSTER)
ext4_rereserve_cluster(inode, partial->lblk);
}
partial->state = initial;
}
num = le32_to_cpu(ex->ee_block) + ee_len - from;
pblk = ext4_ext_pblock(ex) + ee_len - num;
trace_ext4_remove_blocks(inode, ex, from, to, *partial_cluster);
/* /*
* If we have a partial cluster, and it's different from the * We free the partial cluster at the end of the extent (if any),
* cluster of the last block, we need to explicitly free the * unless the cluster is used by another extent (partial_cluster
* partial cluster here. * state is nofree). If a partial cluster exists here, it must be
* shared with the last block in the extent.
*/ */
pblk = ext4_ext_pblock(ex) + ee_len - 1; flags = get_default_free_blocks_flags(inode);
if (*partial_cluster > 0 &&
*partial_cluster != (long long) EXT4_B2C(sbi, pblk)) { /* partial, left end cluster aligned, right end unaligned */
if ((EXT4_LBLK_COFF(sbi, to) != sbi->s_cluster_ratio - 1) &&
(EXT4_LBLK_CMASK(sbi, to) >= from) &&
(partial->state != nofree)) {
if (ext4_is_pending(inode, to))
flags |= EXT4_FREE_BLOCKS_RERESERVE_CLUSTER;
ext4_free_blocks(handle, inode, NULL, ext4_free_blocks(handle, inode, NULL,
EXT4_C2B(sbi, *partial_cluster), EXT4_PBLK_CMASK(sbi, last_pblk),
sbi->s_cluster_ratio, flags); sbi->s_cluster_ratio, flags);
*partial_cluster = 0; if (flags & EXT4_FREE_BLOCKS_RERESERVE_CLUSTER)
ext4_rereserve_cluster(inode, to);
partial->state = initial;
flags = get_default_free_blocks_flags(inode);
} }
#ifdef EXTENTS_STATS flags |= EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER;
{
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
spin_lock(&sbi->s_ext_stats_lock);
sbi->s_ext_blocks += ee_len;
sbi->s_ext_extents++;
if (ee_len < sbi->s_ext_min)
sbi->s_ext_min = ee_len;
if (ee_len > sbi->s_ext_max)
sbi->s_ext_max = ee_len;
if (ext_depth(inode) > sbi->s_depth_max)
sbi->s_depth_max = ext_depth(inode);
spin_unlock(&sbi->s_ext_stats_lock);
}
#endif
if (from >= le32_to_cpu(ex->ee_block)
&& to == le32_to_cpu(ex->ee_block) + ee_len - 1) {
/* tail removal */
ext4_lblk_t num;
long long first_cluster;
num = le32_to_cpu(ex->ee_block) + ee_len - from;
pblk = ext4_ext_pblock(ex) + ee_len - num;
/*
* Usually we want to free partial cluster at the end of the
* extent, except for the situation when the cluster is still
* used by any other extent (partial_cluster is negative).
*/
if (*partial_cluster < 0 &&
*partial_cluster == -(long long) EXT4_B2C(sbi, pblk+num-1))
flags |= EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER;
ext_debug("free last %u blocks starting %llu partial %lld\n", /*
num, pblk, *partial_cluster); * For bigalloc file systems, we never free a partial cluster
ext4_free_blocks(handle, inode, NULL, pblk, num, flags); * at the beginning of the extent. Instead, we check to see if we
/* * need to free it on a subsequent call to ext4_remove_blocks,
* If the block range to be freed didn't start at the * or at the end of ext4_ext_rm_leaf or ext4_ext_remove_space.
* beginning of a cluster, and we removed the entire */
* extent and the cluster is not used by any other extent, flags |= EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER;
* save the partial cluster here, since we might need to ext4_free_blocks(handle, inode, NULL, pblk, num, flags);
* delete if we determine that the truncate or punch hole
* operation has removed all of the blocks in the cluster. /* reset the partial cluster if we've freed past it */
* If that cluster is used by another extent, preserve its if (partial->state != initial && partial->pclu != EXT4_B2C(sbi, pblk))
* negative value so it isn't freed later on. partial->state = initial;
*
* If the whole extent wasn't freed, we've reached the /*
* start of the truncated/punched region and have finished * If we've freed the entire extent but the beginning is not left
* removing blocks. If there's a partial cluster here it's * cluster aligned and is not marked as ineligible for freeing we
* shared with the remainder of the extent and is no longer * record the partial cluster at the beginning of the extent. It
* a candidate for removal. * wasn't freed by the preceding ext4_free_blocks() call, and we
*/ * need to look farther to the left to determine if it's to be freed
if (EXT4_PBLK_COFF(sbi, pblk) && ee_len == num) { * (not shared with another extent). Else, reset the partial
first_cluster = (long long) EXT4_B2C(sbi, pblk); * cluster - we're either done freeing or the beginning of the
if (first_cluster != -*partial_cluster) * extent is left cluster aligned.
*partial_cluster = first_cluster; */
} else { if (EXT4_LBLK_COFF(sbi, from) && num == ee_len) {
*partial_cluster = 0; if (partial->state == initial) {
partial->pclu = EXT4_B2C(sbi, pblk);
partial->lblk = from;
partial->state = tofree;
} }
} else } else {
ext4_error(sbi->s_sb, "strange request: removal(2) " partial->state = initial;
"%u-%u from %u:%u", }
from, to, le32_to_cpu(ex->ee_block), ee_len);
return 0; return 0;
} }
/* /*
* ext4_ext_rm_leaf() Removes the extents associated with the * ext4_ext_rm_leaf() Removes the extents associated with the
* blocks appearing between "start" and "end". Both "start" * blocks appearing between "start" and "end". Both "start"
...@@ -2608,7 +2659,7 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode, ...@@ -2608,7 +2659,7 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
static int static int
ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
struct ext4_ext_path *path, struct ext4_ext_path *path,
long long *partial_cluster, struct partial_cluster *partial,
ext4_lblk_t start, ext4_lblk_t end) ext4_lblk_t start, ext4_lblk_t end)
{ {
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
...@@ -2640,7 +2691,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, ...@@ -2640,7 +2691,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
ex_ee_block = le32_to_cpu(ex->ee_block); ex_ee_block = le32_to_cpu(ex->ee_block);
ex_ee_len = ext4_ext_get_actual_len(ex); ex_ee_len = ext4_ext_get_actual_len(ex);
trace_ext4_ext_rm_leaf(inode, start, ex, *partial_cluster); trace_ext4_ext_rm_leaf(inode, start, ex, partial);
while (ex >= EXT_FIRST_EXTENT(eh) && while (ex >= EXT_FIRST_EXTENT(eh) &&
ex_ee_block + ex_ee_len > start) { ex_ee_block + ex_ee_len > start) {
...@@ -2671,8 +2722,8 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, ...@@ -2671,8 +2722,8 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
*/ */
if (sbi->s_cluster_ratio > 1) { if (sbi->s_cluster_ratio > 1) {
pblk = ext4_ext_pblock(ex); pblk = ext4_ext_pblock(ex);
*partial_cluster = partial->pclu = EXT4_B2C(sbi, pblk);
-(long long) EXT4_B2C(sbi, pblk); partial->state = nofree;
} }
ex--; ex--;
ex_ee_block = le32_to_cpu(ex->ee_block); ex_ee_block = le32_to_cpu(ex->ee_block);
...@@ -2714,8 +2765,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, ...@@ -2714,8 +2765,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
if (err) if (err)
goto out; goto out;
err = ext4_remove_blocks(handle, inode, ex, partial_cluster, err = ext4_remove_blocks(handle, inode, ex, partial, a, b);
a, b);
if (err) if (err)
goto out; goto out;
...@@ -2769,18 +2819,23 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, ...@@ -2769,18 +2819,23 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
* If there's a partial cluster and at least one extent remains in * If there's a partial cluster and at least one extent remains in
* the leaf, free the partial cluster if it isn't shared with the * the leaf, free the partial cluster if it isn't shared with the
* current extent. If it is shared with the current extent * current extent. If it is shared with the current extent
* we zero partial_cluster because we've reached the start of the * we reset the partial cluster because we've reached the start of the
* truncated/punched region and we're done removing blocks. * truncated/punched region and we're done removing blocks.
*/ */
if (*partial_cluster > 0 && ex >= EXT_FIRST_EXTENT(eh)) { if (partial->state == tofree && ex >= EXT_FIRST_EXTENT(eh)) {
pblk = ext4_ext_pblock(ex) + ex_ee_len - 1; pblk = ext4_ext_pblock(ex) + ex_ee_len - 1;
if (*partial_cluster != (long long) EXT4_B2C(sbi, pblk)) { if (partial->pclu != EXT4_B2C(sbi, pblk)) {
int flags = get_default_free_blocks_flags(inode);
if (ext4_is_pending(inode, partial->lblk))
flags |= EXT4_FREE_BLOCKS_RERESERVE_CLUSTER;
ext4_free_blocks(handle, inode, NULL, ext4_free_blocks(handle, inode, NULL,
EXT4_C2B(sbi, *partial_cluster), EXT4_C2B(sbi, partial->pclu),
sbi->s_cluster_ratio, sbi->s_cluster_ratio, flags);
get_default_free_blocks_flags(inode)); if (flags & EXT4_FREE_BLOCKS_RERESERVE_CLUSTER)
ext4_rereserve_cluster(inode, partial->lblk);
} }
*partial_cluster = 0; partial->state = initial;
} }
/* if this leaf is free, then we should /* if this leaf is free, then we should
...@@ -2819,10 +2874,14 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, ...@@ -2819,10 +2874,14 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
int depth = ext_depth(inode); int depth = ext_depth(inode);
struct ext4_ext_path *path = NULL; struct ext4_ext_path *path = NULL;
long long partial_cluster = 0; struct partial_cluster partial;
handle_t *handle; handle_t *handle;
int i = 0, err = 0; int i = 0, err = 0;
partial.pclu = 0;
partial.lblk = 0;
partial.state = initial;
ext_debug("truncate since %u to %u\n", start, end); ext_debug("truncate since %u to %u\n", start, end);
/* probably first extent we're gonna free will be last in block */ /* probably first extent we're gonna free will be last in block */
...@@ -2882,8 +2941,8 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, ...@@ -2882,8 +2941,8 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
*/ */
if (sbi->s_cluster_ratio > 1) { if (sbi->s_cluster_ratio > 1) {
pblk = ext4_ext_pblock(ex) + end - ee_block + 2; pblk = ext4_ext_pblock(ex) + end - ee_block + 2;
partial_cluster = partial.pclu = EXT4_B2C(sbi, pblk);
-(long long) EXT4_B2C(sbi, pblk); partial.state = nofree;
} }
/* /*
...@@ -2911,9 +2970,10 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, ...@@ -2911,9 +2970,10 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
&ex); &ex);
if (err) if (err)
goto out; goto out;
if (pblk) if (pblk) {
partial_cluster = partial.pclu = EXT4_B2C(sbi, pblk);
-(long long) EXT4_B2C(sbi, pblk); partial.state = nofree;
}
} }
} }
/* /*
...@@ -2948,8 +3008,7 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, ...@@ -2948,8 +3008,7 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
if (i == depth) { if (i == depth) {
/* this is leaf block */ /* this is leaf block */
err = ext4_ext_rm_leaf(handle, inode, path, err = ext4_ext_rm_leaf(handle, inode, path,
&partial_cluster, start, &partial, start, end);
end);
/* root level has p_bh == NULL, brelse() eats this */ /* root level has p_bh == NULL, brelse() eats this */
brelse(path[i].p_bh); brelse(path[i].p_bh);
path[i].p_bh = NULL; path[i].p_bh = NULL;
...@@ -3021,21 +3080,24 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, ...@@ -3021,21 +3080,24 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
} }
} }
trace_ext4_ext_remove_space_done(inode, start, end, depth, trace_ext4_ext_remove_space_done(inode, start, end, depth, &partial,
partial_cluster, path->p_hdr->eh_entries); path->p_hdr->eh_entries);
/* /*
* If we still have something in the partial cluster and we have removed * if there's a partial cluster and we have removed the first extent
* even the first extent, then we should free the blocks in the partial * in the file, then we also free the partial cluster, if any
* cluster as well. (This code will only run when there are no leaves
* to the immediate left of the truncated/punched region.)
*/ */
if (partial_cluster > 0 && err == 0) { if (partial.state == tofree && err == 0) {
/* don't zero partial_cluster since it's not used afterwards */ int flags = get_default_free_blocks_flags(inode);
if (ext4_is_pending(inode, partial.lblk))
flags |= EXT4_FREE_BLOCKS_RERESERVE_CLUSTER;
ext4_free_blocks(handle, inode, NULL, ext4_free_blocks(handle, inode, NULL,
EXT4_C2B(sbi, partial_cluster), EXT4_C2B(sbi, partial.pclu),
sbi->s_cluster_ratio, sbi->s_cluster_ratio, flags);
get_default_free_blocks_flags(inode)); if (flags & EXT4_FREE_BLOCKS_RERESERVE_CLUSTER)
ext4_rereserve_cluster(inode, partial.lblk);
partial.state = initial;
} }
/* TODO: flexible tree reduction should be here */ /* TODO: flexible tree reduction should be here */
......
...@@ -4915,9 +4915,17 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, ...@@ -4915,9 +4915,17 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
&sbi->s_flex_groups[flex_group].free_clusters); &sbi->s_flex_groups[flex_group].free_clusters);
} }
if (!(flags & EXT4_FREE_BLOCKS_NO_QUOT_UPDATE)) /*
dquot_free_block(inode, EXT4_C2B(sbi, count_clusters)); * on a bigalloc file system, defer the s_freeclusters_counter
percpu_counter_add(&sbi->s_freeclusters_counter, count_clusters); * update to the caller (ext4_remove_space and friends) so they
* can determine if a cluster freed here should be rereserved
*/
if (!(flags & EXT4_FREE_BLOCKS_RERESERVE_CLUSTER)) {
if (!(flags & EXT4_FREE_BLOCKS_NO_QUOT_UPDATE))
dquot_free_block(inode, EXT4_C2B(sbi, count_clusters));
percpu_counter_add(&sbi->s_freeclusters_counter,
count_clusters);
}
ext4_mb_unload_buddy(&e4b); ext4_mb_unload_buddy(&e4b);
......
...@@ -17,6 +17,7 @@ struct mpage_da_data; ...@@ -17,6 +17,7 @@ struct mpage_da_data;
struct ext4_map_blocks; struct ext4_map_blocks;
struct extent_status; struct extent_status;
struct ext4_fsmap; struct ext4_fsmap;
struct partial_cluster;
#define EXT4_I(inode) (container_of(inode, struct ext4_inode_info, vfs_inode)) #define EXT4_I(inode) (container_of(inode, struct ext4_inode_info, vfs_inode))
...@@ -2055,21 +2056,23 @@ TRACE_EVENT(ext4_ext_show_extent, ...@@ -2055,21 +2056,23 @@ TRACE_EVENT(ext4_ext_show_extent,
); );
TRACE_EVENT(ext4_remove_blocks, TRACE_EVENT(ext4_remove_blocks,
TP_PROTO(struct inode *inode, struct ext4_extent *ex, TP_PROTO(struct inode *inode, struct ext4_extent *ex,
ext4_lblk_t from, ext4_fsblk_t to, ext4_lblk_t from, ext4_fsblk_t to,
long long partial_cluster), struct partial_cluster *pc),
TP_ARGS(inode, ex, from, to, partial_cluster), TP_ARGS(inode, ex, from, to, pc),
TP_STRUCT__entry( TP_STRUCT__entry(
__field( dev_t, dev ) __field( dev_t, dev )
__field( ino_t, ino ) __field( ino_t, ino )
__field( ext4_lblk_t, from ) __field( ext4_lblk_t, from )
__field( ext4_lblk_t, to ) __field( ext4_lblk_t, to )
__field( long long, partial )
__field( ext4_fsblk_t, ee_pblk ) __field( ext4_fsblk_t, ee_pblk )
__field( ext4_lblk_t, ee_lblk ) __field( ext4_lblk_t, ee_lblk )
__field( unsigned short, ee_len ) __field( unsigned short, ee_len )
__field( ext4_fsblk_t, pc_pclu )
__field( ext4_lblk_t, pc_lblk )
__field( int, pc_state)
), ),
TP_fast_assign( TP_fast_assign(
...@@ -2077,14 +2080,16 @@ TRACE_EVENT(ext4_remove_blocks, ...@@ -2077,14 +2080,16 @@ TRACE_EVENT(ext4_remove_blocks,
__entry->ino = inode->i_ino; __entry->ino = inode->i_ino;
__entry->from = from; __entry->from = from;
__entry->to = to; __entry->to = to;
__entry->partial = partial_cluster;
__entry->ee_pblk = ext4_ext_pblock(ex); __entry->ee_pblk = ext4_ext_pblock(ex);
__entry->ee_lblk = le32_to_cpu(ex->ee_block); __entry->ee_lblk = le32_to_cpu(ex->ee_block);
__entry->ee_len = ext4_ext_get_actual_len(ex); __entry->ee_len = ext4_ext_get_actual_len(ex);
__entry->pc_pclu = pc->pclu;
__entry->pc_lblk = pc->lblk;
__entry->pc_state = pc->state;
), ),
TP_printk("dev %d,%d ino %lu extent [%u(%llu), %u]" TP_printk("dev %d,%d ino %lu extent [%u(%llu), %u]"
"from %u to %u partial_cluster %lld", "from %u to %u partial [pclu %lld lblk %u state %d]",
MAJOR(__entry->dev), MINOR(__entry->dev), MAJOR(__entry->dev), MINOR(__entry->dev),
(unsigned long) __entry->ino, (unsigned long) __entry->ino,
(unsigned) __entry->ee_lblk, (unsigned) __entry->ee_lblk,
...@@ -2092,45 +2097,53 @@ TRACE_EVENT(ext4_remove_blocks, ...@@ -2092,45 +2097,53 @@ TRACE_EVENT(ext4_remove_blocks,
(unsigned short) __entry->ee_len, (unsigned short) __entry->ee_len,
(unsigned) __entry->from, (unsigned) __entry->from,
(unsigned) __entry->to, (unsigned) __entry->to,
(long long) __entry->partial) (long long) __entry->pc_pclu,
(unsigned int) __entry->pc_lblk,
(int) __entry->pc_state)
); );
TRACE_EVENT(ext4_ext_rm_leaf, TRACE_EVENT(ext4_ext_rm_leaf,
TP_PROTO(struct inode *inode, ext4_lblk_t start, TP_PROTO(struct inode *inode, ext4_lblk_t start,
struct ext4_extent *ex, struct ext4_extent *ex,
long long partial_cluster), struct partial_cluster *pc),
TP_ARGS(inode, start, ex, partial_cluster), TP_ARGS(inode, start, ex, pc),
TP_STRUCT__entry( TP_STRUCT__entry(
__field( dev_t, dev ) __field( dev_t, dev )
__field( ino_t, ino ) __field( ino_t, ino )
__field( long long, partial )
__field( ext4_lblk_t, start ) __field( ext4_lblk_t, start )
__field( ext4_lblk_t, ee_lblk ) __field( ext4_lblk_t, ee_lblk )
__field( ext4_fsblk_t, ee_pblk ) __field( ext4_fsblk_t, ee_pblk )
__field( short, ee_len ) __field( short, ee_len )
__field( ext4_fsblk_t, pc_pclu )
__field( ext4_lblk_t, pc_lblk )
__field( int, pc_state)
), ),
TP_fast_assign( TP_fast_assign(
__entry->dev = inode->i_sb->s_dev; __entry->dev = inode->i_sb->s_dev;
__entry->ino = inode->i_ino; __entry->ino = inode->i_ino;
__entry->partial = partial_cluster;
__entry->start = start; __entry->start = start;
__entry->ee_lblk = le32_to_cpu(ex->ee_block); __entry->ee_lblk = le32_to_cpu(ex->ee_block);
__entry->ee_pblk = ext4_ext_pblock(ex); __entry->ee_pblk = ext4_ext_pblock(ex);
__entry->ee_len = ext4_ext_get_actual_len(ex); __entry->ee_len = ext4_ext_get_actual_len(ex);
__entry->pc_pclu = pc->pclu;
__entry->pc_lblk = pc->lblk;
__entry->pc_state = pc->state;
), ),
TP_printk("dev %d,%d ino %lu start_lblk %u last_extent [%u(%llu), %u]" TP_printk("dev %d,%d ino %lu start_lblk %u last_extent [%u(%llu), %u]"
"partial_cluster %lld", "partial [pclu %lld lblk %u state %d]",
MAJOR(__entry->dev), MINOR(__entry->dev), MAJOR(__entry->dev), MINOR(__entry->dev),
(unsigned long) __entry->ino, (unsigned long) __entry->ino,
(unsigned) __entry->start, (unsigned) __entry->start,
(unsigned) __entry->ee_lblk, (unsigned) __entry->ee_lblk,
(unsigned long long) __entry->ee_pblk, (unsigned long long) __entry->ee_pblk,
(unsigned short) __entry->ee_len, (unsigned short) __entry->ee_len,
(long long) __entry->partial) (long long) __entry->pc_pclu,
(unsigned int) __entry->pc_lblk,
(int) __entry->pc_state)
); );
TRACE_EVENT(ext4_ext_rm_idx, TRACE_EVENT(ext4_ext_rm_idx,
...@@ -2188,9 +2201,9 @@ TRACE_EVENT(ext4_ext_remove_space, ...@@ -2188,9 +2201,9 @@ TRACE_EVENT(ext4_ext_remove_space,
TRACE_EVENT(ext4_ext_remove_space_done, TRACE_EVENT(ext4_ext_remove_space_done,
TP_PROTO(struct inode *inode, ext4_lblk_t start, ext4_lblk_t end, TP_PROTO(struct inode *inode, ext4_lblk_t start, ext4_lblk_t end,
int depth, long long partial, __le16 eh_entries), int depth, struct partial_cluster *pc, __le16 eh_entries),
TP_ARGS(inode, start, end, depth, partial, eh_entries), TP_ARGS(inode, start, end, depth, pc, eh_entries),
TP_STRUCT__entry( TP_STRUCT__entry(
__field( dev_t, dev ) __field( dev_t, dev )
...@@ -2198,7 +2211,9 @@ TRACE_EVENT(ext4_ext_remove_space_done, ...@@ -2198,7 +2211,9 @@ TRACE_EVENT(ext4_ext_remove_space_done,
__field( ext4_lblk_t, start ) __field( ext4_lblk_t, start )
__field( ext4_lblk_t, end ) __field( ext4_lblk_t, end )
__field( int, depth ) __field( int, depth )
__field( long long, partial ) __field( ext4_fsblk_t, pc_pclu )
__field( ext4_lblk_t, pc_lblk )
__field( int, pc_state )
__field( unsigned short, eh_entries ) __field( unsigned short, eh_entries )
), ),
...@@ -2208,18 +2223,23 @@ TRACE_EVENT(ext4_ext_remove_space_done, ...@@ -2208,18 +2223,23 @@ TRACE_EVENT(ext4_ext_remove_space_done,
__entry->start = start; __entry->start = start;
__entry->end = end; __entry->end = end;
__entry->depth = depth; __entry->depth = depth;
__entry->partial = partial; __entry->pc_pclu = pc->pclu;
__entry->pc_lblk = pc->lblk;
__entry->pc_state = pc->state;
__entry->eh_entries = le16_to_cpu(eh_entries); __entry->eh_entries = le16_to_cpu(eh_entries);
), ),
TP_printk("dev %d,%d ino %lu since %u end %u depth %d partial %lld " TP_printk("dev %d,%d ino %lu since %u end %u depth %d "
"partial [pclu %lld lblk %u state %d] "
"remaining_entries %u", "remaining_entries %u",
MAJOR(__entry->dev), MINOR(__entry->dev), MAJOR(__entry->dev), MINOR(__entry->dev),
(unsigned long) __entry->ino, (unsigned long) __entry->ino,
(unsigned) __entry->start, (unsigned) __entry->start,
(unsigned) __entry->end, (unsigned) __entry->end,
__entry->depth, __entry->depth,
(long long) __entry->partial, (long long) __entry->pc_pclu,
(unsigned int) __entry->pc_lblk,
(int) __entry->pc_state,
(unsigned short) __entry->eh_entries) (unsigned short) __entry->eh_entries)
); );
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册