All of lore.kernel.org
 help / color / mirror / Atom feed
From: Yan-Jie Wang <jaywang0.tw@gmail.com>
To: qemu-devel@nongnu.org
Cc: Yan-Jie Wang <jaywang0.tw@gmail.com>, qemu-stable@nongnu.org
Subject: [Qemu-devel] [PATCH] block/file-posix: fix the wrong result of find_allocation() in macOS.
Date: Sat,  8 Sep 2018 22:15:28 +0800	[thread overview]
Message-ID: <20180908141528.71260-1-jaywang0.tw@gmail.com> (raw)

In macOS, lseek with SEEK_DATA behaves differently.
It seeks to the next data region even though offset is in the middle of
a data region. In addition, there may be many data regions without any
hole among them, like this: |---Data---|---Data---|

Because of this, qemu-img convert with raw images as input may create
corrupted images in macOS especially for large files, and qemu-img
map may also report wrong things. This patch fixes this undesired
behaviors.

Signed-off-by: Yan-Jie Wang <jaywang0.tw@gmail.com>
---
 block/file-posix.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)

diff --git a/block/file-posix.c b/block/file-posix.c
index fe83cbf0eb..5c208580e6 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -2325,6 +2325,7 @@ static int find_allocation(BlockDriverState *bs, off_t start,
     BDRVRawState *s = bs->opaque;
     off_t offs;
 
+#if !(defined(__APPLE__) && defined(__MACH__))
     /*
      * SEEK_DATA cases:
      * D1. offs == start: start is in data
@@ -2395,6 +2396,64 @@ static int find_allocation(BlockDriverState *bs, off_t start,
         *hole = offs;
         return 0;
     }
+#else
+    /*
+     * In macOS, lseek with SEEK_DATA seeks to the next data region
+     * even though the offset is in the middle of a data region.
+     * In addition, there may be many data regions without any holes among
+     * them, like this:  |----Data----|----Data----|
+     *
+     * Although the behavior of lseek with SEEK_DATA is different in macOS,
+     * the behavior of lseek with SEEK_HOLE in macOS is the same as the one in
+     * Linux.
+     *
+     * Therefore, the cases D1, D2 and H2 are changed to the followings
+     * for macOS:
+     *  D1. offs == start: start is at the beginning of a data region.
+     *  D2. offs > start: either start is in a hole, next data at offs
+     *      or start is in the middle of a data region,
+     *      next data at offs.
+     *  H2. offs > start: start is in data, next hole at offs
+     */
+
+    offs = lseek(s->fd, start, SEEK_HOLE);
+    if (offs < 0) {
+        return -errno;  /* H3 or H4 */
+    }
+
+    if (offs < start) {
+        /* This is not a valid return by lseek().  We are safe to just return
+         * -EIO in this case, and we'll treat it like D4. */
+        return -EIO;
+    }
+
+    if (offs > start) {
+        /* H2: start is in data, next hole at offs */
+        *data = start;
+        *hole = offs;
+        return 0;
+    }
+
+    /* H1: start is in a hole */
+    offs = lseek(s->fd, start, SEEK_DATA);
+
+    if (offs < 0) {
+        return -errno;  /* H1 and (D3 or D4) */
+    }
+
+    if (offs < start) {
+        /* This is not a valid return by lseek().  We are safe to just return
+         * -EIO in this case, and we'll treat it like D4. */
+        return -EIO;
+    }
+
+    if (offs > start) {
+        /* H1 and D2: start is in a hole, next data at offs */
+        *hole = start;
+        *data = offs;
+        return 0;
+    }
+#endif
 
     /* D1 and H1 */
     return -EBUSY;
-- 
2.18.0

             reply	other threads:[~2018-09-08 14:15 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-09-08 14:15 Yan-Jie Wang [this message]
2018-09-08 15:34 ` [Qemu-devel] [PATCH] block/file-posix: fix the wrong result of find_allocation() in macOS Peter Maydell
2018-09-10 15:10   ` Eric Blake
2018-09-11  2:01   ` 王彥傑

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180908141528.71260-1-jaywang0.tw@gmail.com \
    --to=jaywang0.tw@gmail.com \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-stable@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.