&smap))
smap.br_startoff = end_fsb; /* fake hole until EOF */
if (smap.br_startoff > offset_fsb) {
- /*
- * We never need to allocate blocks for zeroing a hole.
- */
- if (flags & IOMAP_ZERO) {
- xfs_hole_to_iomap(ip, iomap, offset_fsb,
- smap.br_startoff);
- goto out_unlock;
- }
end_fsb = min(end_fsb, smap.br_startoff);
} else {
end_fsb = min(end_fsb,
count_fsb = min3(end_fsb - offset_fsb, XFS_MAX_BMBT_EXTLEN,
XFS_B_TO_FSB(mp, 1024 * PAGE_SIZE));
+ /*
+ * When zeroing, don't allocate blocks for holes as they are already
+ * zeroes, but we need to ensure that no extents exist in both the data
+ * and COW fork to ensure this really is a hole.
+ */
+ if ((flags & IOMAP_ZERO) && srcmap->type == IOMAP_HOLE) {
+ xfs_hole_to_iomap(ip, iomap, offset_fsb, end_fsb);
+ goto out_unlock;
+ }
+
/*
* The block reservation is supposed to cover all blocks that the
* operation could possible write, but there is a nasty corner case