Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 377573
b: refs/heads/master
c: d23142c
h: refs/heads/master
i:
  377571: a68d604
v: v3
  • Loading branch information
Lukas Czerner authored and Theodore Ts'o committed May 28, 2013
1 parent 3c5d7aa commit 931f518
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 31 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 61801325f790ea15ba0630a7a26bd80a0741813f
refs/heads/master: d23142c6271c499d913d0d5e668b5a4eb6dafcb0
69 changes: 51 additions & 18 deletions trunk/fs/ext4/extents.c
Original file line number Diff line number Diff line change
Expand Up @@ -2359,7 +2359,7 @@ int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks, int chunk)

static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
struct ext4_extent *ex,
ext4_fsblk_t *partial_cluster,
long long *partial_cluster,
ext4_lblk_t from, ext4_lblk_t to)
{
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
Expand Down Expand Up @@ -2388,7 +2388,8 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
* partial cluster here.
*/
pblk = ext4_ext_pblock(ex) + ee_len - 1;
if (*partial_cluster && (EXT4_B2C(sbi, pblk) != *partial_cluster)) {
if ((*partial_cluster > 0) &&
(EXT4_B2C(sbi, pblk) != *partial_cluster)) {
ext4_free_blocks(handle, inode, NULL,
EXT4_C2B(sbi, *partial_cluster),
sbi->s_cluster_ratio, flags);
Expand All @@ -2414,23 +2415,41 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
&& to == le32_to_cpu(ex->ee_block) + ee_len - 1) {
/* tail removal */
ext4_lblk_t num;
unsigned int unaligned;

num = le32_to_cpu(ex->ee_block) + ee_len - from;
pblk = ext4_ext_pblock(ex) + ee_len - num;
ext_debug("free last %u blocks starting %llu\n", num, pblk);
/*
* 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) == 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);
ext4_free_blocks(handle, inode, NULL, pblk, num, flags);
/*
* If the block range to be freed didn't start at the
* beginning of a cluster, and we removed the entire
* extent, save the partial cluster here, since we
* might need to delete if we determine that the
* truncate operation has removed all of the blocks in
* the cluster.
* extent and the cluster is not used by any other extent,
* save the partial cluster here, since we might need to
* delete if we determine that the truncate operation has
* removed all of the blocks in the cluster.
*
* On the other hand, if we did not manage to free the whole
* extent, we have to mark the cluster as used (store negative
* cluster number in partial_cluster).
*/
if (pblk & (sbi->s_cluster_ratio - 1) &&
(ee_len == num))
unaligned = pblk & (sbi->s_cluster_ratio - 1);
if (unaligned && (ee_len == num) &&
(*partial_cluster != -((long long)EXT4_B2C(sbi, pblk))))
*partial_cluster = EXT4_B2C(sbi, pblk);
else
else if (unaligned)
*partial_cluster = -((long long)EXT4_B2C(sbi, pblk));
else if (*partial_cluster > 0)
*partial_cluster = 0;
} else
ext4_error(sbi->s_sb, "strange request: removal(2) "
Expand All @@ -2448,12 +2467,16 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode,
* @handle: The journal handle
* @inode: The files inode
* @path: The path to the leaf
* @partial_cluster: The cluster which we'll have to free if all extents
* has been released from it. It gets negative in case
* that the cluster is still used.
* @start: The first block to remove
* @end: The last block to remove
*/
static int
ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
struct ext4_ext_path *path, ext4_fsblk_t *partial_cluster,
struct ext4_ext_path *path,
long long *partial_cluster,
ext4_lblk_t start, ext4_lblk_t end)
{
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
Expand All @@ -2466,6 +2489,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
unsigned short ex_ee_len;
unsigned uninitialized = 0;
struct ext4_extent *ex;
ext4_fsblk_t pblk;

/* the header must be checked already in ext4_ext_remove_space() */
ext_debug("truncate since %u in leaf to %u\n", start, end);
Expand Down Expand Up @@ -2504,6 +2528,16 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,

/* If this extent is beyond the end of the hole, skip it */
if (end < ex_ee_block) {
/*
* We're going to skip this extent and move to another,
* so if this extent is not cluster aligned we have
* to mark the current cluster as used to avoid
* accidentally freeing it later on
*/
pblk = ext4_ext_pblock(ex);
if (pblk & (sbi->s_cluster_ratio - 1))
*partial_cluster =
-((long long)EXT4_B2C(sbi, pblk));
ex--;
ex_ee_block = le32_to_cpu(ex->ee_block);
ex_ee_len = ext4_ext_get_actual_len(ex);
Expand Down Expand Up @@ -2579,7 +2613,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
sizeof(struct ext4_extent));
}
le16_add_cpu(&eh->eh_entries, -1);
} else
} else if (*partial_cluster > 0)
*partial_cluster = 0;

err = ext4_ext_dirty(handle, inode, path + depth);
Expand All @@ -2597,11 +2631,10 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
err = ext4_ext_correct_indexes(handle, inode, path);

/*
* If there is still a entry in the leaf node, check to see if
* it references the partial cluster. This is the only place
* where it could; if it doesn't, we can free the cluster.
* Free the partial cluster only if the current extent does not
* reference it. Otherwise we might free used cluster.
*/
if (*partial_cluster && ex >= EXT_FIRST_EXTENT(eh) &&
if (*partial_cluster > 0 &&
(EXT4_B2C(sbi, ext4_ext_pblock(ex) + ex_ee_len - 1) !=
*partial_cluster)) {
int flags = EXT4_FREE_BLOCKS_FORGET;
Expand Down Expand Up @@ -2651,7 +2684,7 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
struct super_block *sb = inode->i_sb;
int depth = ext_depth(inode);
struct ext4_ext_path *path = NULL;
ext4_fsblk_t partial_cluster = 0;
long long partial_cluster = 0;
handle_t *handle;
int i = 0, err = 0;

Expand Down Expand Up @@ -2837,7 +2870,7 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
/* If we still have something in the partial cluster and we have removed
* even the first extent, then we should free the blocks in the partial
* cluster as well. */
if (partial_cluster && path->p_hdr->eh_entries == 0) {
if (partial_cluster > 0 && path->p_hdr->eh_entries == 0) {
int flags = EXT4_FREE_BLOCKS_FORGET;

if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
Expand Down
25 changes: 13 additions & 12 deletions trunk/include/trace/events/ext4.h
Original file line number Diff line number Diff line change
Expand Up @@ -1928,7 +1928,7 @@ TRACE_EVENT(ext4_ext_show_extent,
TRACE_EVENT(ext4_remove_blocks,
TP_PROTO(struct inode *inode, struct ext4_extent *ex,
ext4_lblk_t from, ext4_fsblk_t to,
ext4_fsblk_t partial_cluster),
long long partial_cluster),

TP_ARGS(inode, ex, from, to, partial_cluster),

Expand All @@ -1937,7 +1937,7 @@ TRACE_EVENT(ext4_remove_blocks,
__field( ino_t, ino )
__field( ext4_lblk_t, from )
__field( ext4_lblk_t, to )
__field( ext4_fsblk_t, partial )
__field( long long, partial )
__field( ext4_fsblk_t, ee_pblk )
__field( ext4_lblk_t, ee_lblk )
__field( unsigned short, ee_len )
Expand All @@ -1955,27 +1955,28 @@ TRACE_EVENT(ext4_remove_blocks,
),

TP_printk("dev %d,%d ino %lu extent [%u(%llu), %u]"
"from %u to %u partial_cluster %u",
"from %u to %u partial_cluster %lld",
MAJOR(__entry->dev), MINOR(__entry->dev),
(unsigned long) __entry->ino,
(unsigned) __entry->ee_lblk,
(unsigned long long) __entry->ee_pblk,
(unsigned short) __entry->ee_len,
(unsigned) __entry->from,
(unsigned) __entry->to,
(unsigned) __entry->partial)
(long long) __entry->partial)
);

TRACE_EVENT(ext4_ext_rm_leaf,
TP_PROTO(struct inode *inode, ext4_lblk_t start,
struct ext4_extent *ex, ext4_fsblk_t partial_cluster),
struct ext4_extent *ex,
long long partial_cluster),

TP_ARGS(inode, start, ex, partial_cluster),

TP_STRUCT__entry(
__field( dev_t, dev )
__field( ino_t, ino )
__field( ext4_fsblk_t, partial )
__field( long long, partial )
__field( ext4_lblk_t, start )
__field( ext4_lblk_t, ee_lblk )
__field( ext4_fsblk_t, ee_pblk )
Expand All @@ -1993,14 +1994,14 @@ TRACE_EVENT(ext4_ext_rm_leaf,
),

TP_printk("dev %d,%d ino %lu start_lblk %u last_extent [%u(%llu), %u]"
"partial_cluster %u",
"partial_cluster %lld",
MAJOR(__entry->dev), MINOR(__entry->dev),
(unsigned long) __entry->ino,
(unsigned) __entry->start,
(unsigned) __entry->ee_lblk,
(unsigned long long) __entry->ee_pblk,
(unsigned short) __entry->ee_len,
(unsigned) __entry->partial)
(long long) __entry->partial)
);

TRACE_EVENT(ext4_ext_rm_idx,
Expand Down Expand Up @@ -2058,7 +2059,7 @@ TRACE_EVENT(ext4_ext_remove_space,

TRACE_EVENT(ext4_ext_remove_space_done,
TP_PROTO(struct inode *inode, ext4_lblk_t start, ext4_lblk_t end,
int depth, ext4_lblk_t partial, __le16 eh_entries),
int depth, long long partial, __le16 eh_entries),

TP_ARGS(inode, start, end, depth, partial, eh_entries),

Expand All @@ -2068,7 +2069,7 @@ TRACE_EVENT(ext4_ext_remove_space_done,
__field( ext4_lblk_t, start )
__field( ext4_lblk_t, end )
__field( int, depth )
__field( ext4_lblk_t, partial )
__field( long long, partial )
__field( unsigned short, eh_entries )
),

Expand All @@ -2082,14 +2083,14 @@ TRACE_EVENT(ext4_ext_remove_space_done,
__entry->eh_entries = le16_to_cpu(eh_entries);
),

TP_printk("dev %d,%d ino %lu since %u end %u depth %d partial %u "
TP_printk("dev %d,%d ino %lu since %u end %u depth %d partial %lld "
"remaining_entries %u",
MAJOR(__entry->dev), MINOR(__entry->dev),
(unsigned long) __entry->ino,
(unsigned) __entry->start,
(unsigned) __entry->end,
__entry->depth,
(unsigned) __entry->partial,
(long long) __entry->partial,
(unsigned short) __entry->eh_entries)
);

Expand Down

0 comments on commit 931f518

Please sign in to comment.