}
 
 /*
- * If the page has delalloc blocks on it, we need to punch them out before we
- * invalidate the page.  If we don't, we leave a stale delalloc mapping on the
- * inode that can trip up a later direct I/O read operation on the same region.
+ * If the folio has delalloc blocks on it, the caller is asking us to punch them
+ * out. If we don't, we can leave a stale delalloc mapping covered by a clean
+ * page that needs to be dirtied again before the delalloc mapping can be
+ * converted. This stale delalloc mapping can trip up a later direct I/O read
+ * operation on the same region.
  *
- * We prevent this by truncating away the delalloc regions on the page.  Because
+ * We prevent this by truncating away the delalloc regions on the folio. Because
  * they are delalloc, we can do this without needing a transaction. Indeed - if
  * we get ENOSPC errors, we have to be able to do this truncation without a
- * transaction as there is no space left for block reservation (typically why we
- * see a ENOSPC in writeback).
+ * transaction as there is no space left for block reservation (typically why
+ * we see a ENOSPC in writeback).
  */
 static void
 xfs_discard_folio(
                "page discard on page "PTR_FMT", inode 0x%llx, pos %llu.",
                        folio, ip->i_ino, pos);
 
+       /*
+        * The end of the punch range is always the offset of the the first
+        * byte of the next folio. Hence the end offset is only dependent on the
+        * folio itself and not the start offset that is passed in.
+        */
        error = xfs_bmap_punch_delalloc_range(ip, pos,
-                       round_up(pos, folio_size(folio)));
+                               folio_pos(folio) + folio_size(folio));
 
        if (error && !xfs_is_shutdown(mp))
                xfs_alert(mp, "page discard unable to remove delalloc mapping.");