[PATCH] file-posix: Fix handling of APFS clones

Mohamed Akram posted 1 patch 1 month ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/AFE31528-83DE-4395-815C-C319E7B1B4DC@outlook.com
Maintainers: Kevin Wolf <kwolf@redhat.com>, Hanna Reitz <hreitz@redhat.com>
block/file-posix.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
[PATCH] file-posix: Fix handling of APFS clones
Posted by Mohamed Akram 1 month ago
On macOS, lseek may not always report a trailing hole, in which case
seeking with SEEK_HOLE or SEEK_DATA will fail with ENXIO. Detect this
condition by checking if errno is set to ENXIO even with a valid offset
and return ENOTSUP instead so that it can be correctly handled rather
than the file being considered empty.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3124
Signed-off-by: Mohamed Akram <mohd.akram@outlook.com>
---
 block/file-posix.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/block/file-posix.c b/block/file-posix.c
index 8c738674c..89b3e338c 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -3190,6 +3190,20 @@ static int find_allocation(BlockDriverState *bs, off_t start,
     BDRVRawState *s = bs->opaque;
     off_t offs;
 
+    /*
+     * When using SEEK_HOLE on macOS, if errno is ENXIO even if start is not
+     * beyond EOF, then SEEK_HOLE and SEEK_DATA aren't supported for this file.
+     */
+#ifdef __APPLE__
+    offs = lseek(s->fd, start, SEEK_HOLE);
+    if (offs < 0) {
+        if (errno == ENXIO && start < bs->total_sectors * BDRV_SECTOR_SIZE) {
+            return -ENOTSUP;
+        }
+        return -errno;
+    }
+#endif
+
     /*
      * SEEK_DATA cases:
      * D1. offs == start: start is in data
-- 
2.51.0