|
@@ -2621,27 +2621,6 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
|
|
|
ex_ee_block = le32_to_cpu(ex->ee_block);
|
|
|
ex_ee_len = ext4_ext_get_actual_len(ex);
|
|
|
|
|
|
- /*
|
|
|
- * If we're starting with an extent other than the last one in the
|
|
|
- * node, we need to see if it shares a cluster with the extent to
|
|
|
- * the right (towards the end of the file). If its leftmost cluster
|
|
|
- * is this extent's rightmost cluster and it is not cluster aligned,
|
|
|
- * we'll mark it as a partial that is not to be deallocated.
|
|
|
- */
|
|
|
-
|
|
|
- if (ex != EXT_LAST_EXTENT(eh)) {
|
|
|
- ext4_fsblk_t current_pblk, right_pblk;
|
|
|
- long long current_cluster, right_cluster;
|
|
|
-
|
|
|
- current_pblk = ext4_ext_pblock(ex) + ex_ee_len - 1;
|
|
|
- current_cluster = (long long)EXT4_B2C(sbi, current_pblk);
|
|
|
- right_pblk = ext4_ext_pblock(ex + 1);
|
|
|
- right_cluster = (long long)EXT4_B2C(sbi, right_pblk);
|
|
|
- if (current_cluster == right_cluster &&
|
|
|
- EXT4_PBLK_COFF(sbi, right_pblk))
|
|
|
- *partial_cluster = -right_cluster;
|
|
|
- }
|
|
|
-
|
|
|
trace_ext4_ext_rm_leaf(inode, start, ex, *partial_cluster);
|
|
|
|
|
|
while (ex >= EXT_FIRST_EXTENT(eh) &&
|
|
@@ -2666,14 +2645,16 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
|
|
|
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
|
|
|
+ * so note that its first cluster is in use to avoid
|
|
|
+ * freeing it when removing blocks. Eventually, the
|
|
|
+ * right edge of the truncated/punched region will
|
|
|
+ * be just to the left.
|
|
|
*/
|
|
|
- pblk = ext4_ext_pblock(ex);
|
|
|
- if (EXT4_PBLK_COFF(sbi, pblk))
|
|
|
+ if (sbi->s_cluster_ratio > 1) {
|
|
|
+ pblk = ext4_ext_pblock(ex);
|
|
|
*partial_cluster =
|
|
|
- -((long long)EXT4_B2C(sbi, pblk));
|
|
|
+ -(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);
|
|
@@ -2819,7 +2800,7 @@ ext4_ext_more_to_rm(struct ext4_ext_path *path)
|
|
|
int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
|
|
|
ext4_lblk_t end)
|
|
|
{
|
|
|
- struct super_block *sb = inode->i_sb;
|
|
|
+ struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
|
|
|
int depth = ext_depth(inode);
|
|
|
struct ext4_ext_path *path = NULL;
|
|
|
long long partial_cluster = 0;
|
|
@@ -2845,9 +2826,10 @@ again:
|
|
|
*/
|
|
|
if (end < EXT_MAX_BLOCKS - 1) {
|
|
|
struct ext4_extent *ex;
|
|
|
- ext4_lblk_t ee_block;
|
|
|
+ ext4_lblk_t ee_block, ex_end, lblk;
|
|
|
+ ext4_fsblk_t pblk;
|
|
|
|
|
|
- /* find extent for this block */
|
|
|
+ /* find extent for or closest extent to this block */
|
|
|
path = ext4_find_extent(inode, end, NULL, EXT4_EX_NOCACHE);
|
|
|
if (IS_ERR(path)) {
|
|
|
ext4_journal_stop(handle);
|
|
@@ -2867,6 +2849,7 @@ again:
|
|
|
}
|
|
|
|
|
|
ee_block = le32_to_cpu(ex->ee_block);
|
|
|
+ ex_end = ee_block + ext4_ext_get_actual_len(ex) - 1;
|
|
|
|
|
|
/*
|
|
|
* See if the last block is inside the extent, if so split
|
|
@@ -2874,8 +2857,19 @@ again:
|
|
|
* tail of the first part of the split extent in
|
|
|
* ext4_ext_rm_leaf().
|
|
|
*/
|
|
|
- if (end >= ee_block &&
|
|
|
- end < ee_block + ext4_ext_get_actual_len(ex) - 1) {
|
|
|
+ if (end >= ee_block && end < ex_end) {
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If we're going to split the extent, note that
|
|
|
+ * the cluster containing the block after 'end' is
|
|
|
+ * in use to avoid freeing it when removing blocks.
|
|
|
+ */
|
|
|
+ if (sbi->s_cluster_ratio > 1) {
|
|
|
+ pblk = ext4_ext_pblock(ex) + end - ee_block + 2;
|
|
|
+ partial_cluster =
|
|
|
+ -(long long) EXT4_B2C(sbi, pblk);
|
|
|
+ }
|
|
|
+
|
|
|
/*
|
|
|
* Split the extent in two so that 'end' is the last
|
|
|
* block in the first new extent. Also we should not
|
|
@@ -2886,6 +2880,24 @@ again:
|
|
|
end + 1, 1);
|
|
|
if (err < 0)
|
|
|
goto out;
|
|
|
+
|
|
|
+ } else if (sbi->s_cluster_ratio > 1 && end >= ex_end) {
|
|
|
+ /*
|
|
|
+ * If there's an extent to the right its first cluster
|
|
|
+ * contains the immediate right boundary of the
|
|
|
+ * truncated/punched region. Set partial_cluster to
|
|
|
+ * its negative value so it won't be freed if shared
|
|
|
+ * with the current extent. The end < ee_block case
|
|
|
+ * is handled in ext4_ext_rm_leaf().
|
|
|
+ */
|
|
|
+ lblk = ex_end + 1;
|
|
|
+ err = ext4_ext_search_right(inode, path, &lblk, &pblk,
|
|
|
+ &ex);
|
|
|
+ if (err)
|
|
|
+ goto out;
|
|
|
+ if (pblk)
|
|
|
+ partial_cluster =
|
|
|
+ -(long long) EXT4_B2C(sbi, pblk);
|
|
|
}
|
|
|
}
|
|
|
/*
|
|
@@ -3003,8 +3015,8 @@ again:
|
|
|
int flags = get_default_free_blocks_flags(inode);
|
|
|
|
|
|
ext4_free_blocks(handle, inode, NULL,
|
|
|
- EXT4_C2B(EXT4_SB(sb), partial_cluster),
|
|
|
- EXT4_SB(sb)->s_cluster_ratio, flags);
|
|
|
+ EXT4_C2B(sbi, partial_cluster),
|
|
|
+ sbi->s_cluster_ratio, flags);
|
|
|
partial_cluster = 0;
|
|
|
}
|
|
|
|