diff mbox series

[v3,7/7] block: check availablity for preadv/pwritev on mac

Message ID 20201028030701.14086-8-j@getutm.app
State New
Headers show
Series iOS and Apple Silicon host support | expand

Commit Message

Joelle van Dyne Oct. 28, 2020, 3:07 a.m. UTC
macOS 11/iOS 14 added preadv/pwritev APIs. Due to weak linking, configure
will succeed with CONFIG_PREADV even when targeting a lower OS version. We
therefore need to check at run time if we can actually use these APIs.

Signed-off-by: Joelle van Dyne <j@getutm.app>
---
 block/file-posix.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

Comments

Stefan Hajnoczi Oct. 28, 2020, 11:59 a.m. UTC | #1
On Tue, Oct 27, 2020 at 08:07:01PM -0700, Joelle van Dyne wrote:
> macOS 11/iOS 14 added preadv/pwritev APIs. Due to weak linking, configure
> will succeed with CONFIG_PREADV even when targeting a lower OS version. We
> therefore need to check at run time if we can actually use these APIs.
> 
> Signed-off-by: Joelle van Dyne <j@getutm.app>
> ---
>  block/file-posix.c | 12 ++++++++++++
>  1 file changed, 12 insertions(+)

What happens when preadv() is called prior to macOS 11/iOS 14?

If I understand correctly the runtime check is preferrable because
otherwise a binary compiled on recent macOS/iOS would ship with preadv()
support but fail when executed on an older macOS/iOS?
Joelle van Dyne Oct. 29, 2020, 1:07 a.m. UTC | #2
If built with Xcode 11 (or below), a compile time error will occur due
to symbol not found. (QEMU's ./configure detects this and doesn't
enable it)
If built with Xcode 12 without the checks, a runtime error will occur.

-j

On Wed, Oct 28, 2020 at 5:23 AM Stefan Hajnoczi <stefanha@redhat.com> wrote:
>
> On Tue, Oct 27, 2020 at 08:07:01PM -0700, Joelle van Dyne wrote:
> > macOS 11/iOS 14 added preadv/pwritev APIs. Due to weak linking, configure
> > will succeed with CONFIG_PREADV even when targeting a lower OS version. We
> > therefore need to check at run time if we can actually use these APIs.
> >
> > Signed-off-by: Joelle van Dyne <j@getutm.app>
> > ---
> >  block/file-posix.c | 12 ++++++++++++
> >  1 file changed, 12 insertions(+)
>
> What happens when preadv() is called prior to macOS 11/iOS 14?
>
> If I understand correctly the runtime check is preferrable because
> otherwise a binary compiled on recent macOS/iOS would ship with preadv()
> support but fail when executed on an older macOS/iOS?
Stefan Hajnoczi Oct. 29, 2020, 7:53 a.m. UTC | #3
On Wed, Oct 28, 2020 at 06:07:16PM -0700, Joelle van Dyne wrote:
> If built with Xcode 12 without the checks, a runtime error will occur.

If that runtime error is ENOSYS then it's handled by existing code:

  if (preadv_present) {
      nbytes = handle_aiocb_rw_vector(aiocb);
      if (nbytes == aiocb->aio_nbytes ||
          (nbytes < 0 && nbytes != -ENOSYS)) {
          goto out;
      }
      preadv_present = false;
  }

Why is additional code needed for iOS?

Stefan
Joelle van Dyne Oct. 29, 2020, 8:33 a.m. UTC | #4
No it doesn't return ENOSYS. Dyld calls abort() when a weak link is
not resolved at the time of call.

-j

On Thu, Oct 29, 2020 at 12:54 AM Stefan Hajnoczi <stefanha@gmail.com> wrote:
>
> On Wed, Oct 28, 2020 at 06:07:16PM -0700, Joelle van Dyne wrote:
> > If built with Xcode 12 without the checks, a runtime error will occur.
>
> If that runtime error is ENOSYS then it's handled by existing code:
>
>   if (preadv_present) {
>       nbytes = handle_aiocb_rw_vector(aiocb);
>       if (nbytes == aiocb->aio_nbytes ||
>           (nbytes < 0 && nbytes != -ENOSYS)) {
>           goto out;
>       }
>       preadv_present = false;
>   }
>
> Why is additional code needed for iOS?
>
> Stefan
diff mbox series

Patch

diff --git a/block/file-posix.c b/block/file-posix.c
index 5560fd20ac..b5a7ce483d 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -1394,12 +1394,24 @@  static bool preadv_present = true;
 static ssize_t
 qemu_preadv(int fd, const struct iovec *iov, int nr_iov, off_t offset)
 {
+#ifdef CONFIG_DARWIN /* preadv introduced in macOS 11 */
+    if (!__builtin_available(macOS 11, iOS 14, watchOS 7, tvOS 14, *)) {
+        preadv_present = false;
+        return -ENOSYS;
+    } else
+#endif
     return preadv(fd, iov, nr_iov, offset);
 }
 
 static ssize_t
 qemu_pwritev(int fd, const struct iovec *iov, int nr_iov, off_t offset)
 {
+#ifdef CONFIG_DARWIN /* pwritev introduced in macOS 11 */
+    if (!__builtin_available(macOS 11, iOS 14, watchOS 7, tvOS 14, *)) {
+        preadv_present = false;
+        return -ENOSYS;
+    } else
+#endif
     return pwritev(fd, iov, nr_iov, offset);
 }