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) &&
                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);
 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;
         */
        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);
                }
 
                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
                 * 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
                                                         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);
                }
        }
        /*
                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;
        }