bool is_zero_reserved() const {
     return !is_indirect() && get_val().is_zero();
   }
+  bool is_real() const {
+    return !is_indirect() && !get_val().is_zero();
+  }
 
   extent_len_t get_length() const {
     assert(!is_null());
 
     extent_len_t>(overwrite_range.aligned_begin);
   return ctx.tm.remove_mappings_in_range(
     ctx.t, overwrite_range.aligned_begin,
-    unaligned_len, std::move(first_mapping));
+    unaligned_len, std::move(first_mapping), {});
 }
 
 // The last step in the multi-mapping-hole-punching scenario: remap
     }
     return ctx.tm.get_pin(ctx.t, object_data.get_reserved_data_base()
     ).si_then([this, &object_data, &d_object_data, ctx](auto mapping) {
+      auto old_base = object_data.get_reserved_data_base();
+      auto old_len = object_data.get_reserved_data_len();
       return prepare_data_reservation(
        ctx,
        d_object_data,
            object_data.get_reserved_data_len());
          return ctx.tm.remove(ctx.t, std::move(*mapping));
        });
-      }).si_then([ctx, &object_data,
-                 mapping=std::move(mapping)](auto pos) mutable {
+      }).si_then([ctx, &object_data, mapping](auto pos) mutable {
        auto base = object_data.get_reserved_data_base();
        auto len = object_data.get_reserved_data_len();
        return ctx.tm.clone_range(
          ctx.t, base, len, std::move(pos), std::move(mapping), false);
+      }).si_then([ctx, mapping, old_base, old_len] {
+       return ctx.tm.remove_mappings_in_range(
+         ctx.t, old_base, old_len, std::move(mapping), {false, true}
+       ).discard_result();
       });
     }).handle_error_interruptible(
       clone_iertr::pass_further{},
 
     });
   }
 
+  struct remove_mappings_param_t {
+    bool cascade_remove_on_indirect = true;
+    bool skip_direct_mapping = false;
+  };
   /*
    * remove_mappings_in_range
    *
     Transaction &t,
     laddr_t start,
     objaddr_t unaligned_len,
-    LBAMapping first_mapping)
+    LBAMapping first_mapping,
+    remove_mappings_param_t params)
   {
     LOG_PREFIX(TransactionManager::remove_mappings_in_range);
     SUBDEBUGT(seastore_tm, "{}~{}, first_mapping: {}",
     auto mapping = co_await first_mapping.refresh();
     while (!mapping.is_end()) {
       assert(mapping.get_key() >= start);
-      auto mapping_end =
-       (mapping.get_key() + mapping.get_length()).checked_to_laddr();
+      auto mapping_end = (mapping.get_key() + mapping.get_length()
+       ).checked_to_laddr();
       if (mapping_end > start + unaligned_len) {
        break;
       }
-      mapping = co_await remove(t, std::move(mapping)
-      ).handle_error_interruptible(
-       punch_mappings_iertr::pass_further{},
-       crimson::ct_error::assert_all{
-         "remove_mappings_in_range hit invalid error"
-       }
-      );
+      if (params.skip_direct_mapping && mapping.is_real()) {
+       mapping = co_await mapping.next();
+       continue;
+      }
+      if (params.cascade_remove_on_indirect ||
+         mapping.is_zero_reserved()) {
+       mapping = co_await remove(t, std::move(mapping)
+       ).handle_error_interruptible(
+         punch_mappings_iertr::pass_further{},
+         crimson::ct_error::assert_all{
+           "remove_mappings_in_range hit invalid error"
+         }
+       );
+      } else {
+       mapping = co_await _remove_indirect_mapping_only(
+         t, std::move(mapping)
+       ).handle_error_interruptible(
+         punch_mappings_iertr::pass_further{},
+         crimson::ct_error::assert_all{
+           "remove_mappings_in_range hit invalid error"
+         }
+       );
+      }
     }
-    co_return std::move(mapping);
+    co_return mapping;
   }
 
   ~TransactionManager();