diff mbox series

[v8,09/11] block: check availablity for preadv/pwritev on mac

Message ID 20210123045632.18482-10-j@getutm.app (mailing list archive)
State New, archived
Headers show
Series iOS and Apple Silicon host support | expand

Commit Message

Joelle van Dyne Jan. 23, 2021, 4:56 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 | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

Comments

Peter Maydell Jan. 23, 2021, 1:52 p.m. UTC | #1
On Sat, 23 Jan 2021 at 05:03, Joelle van Dyne <j@getutm.app> 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.

If you make the preadv check be a meson.build has_function()
test, I think (but have not tested) that it ought to correctly
fail the link in the targeting-lower-OS-version case, because
meson.build's has_function() implementation for clang
https://github.com/mesonbuild/meson/blob/bad0e95caec4cf49165572df3cf2edc4832280fa/mesonbuild/compilers/mixins/clang.py#L89
adds -Wl,-no-weak-imports when it's building the test-case
exactly to force that linker visibility obeys the minimum
version targets for OSX.

If that works I think it would be neater than delaying the
check to runtime (and it would also mean another test moved
out of configure and into meson.build, which is the direction
we're heading anyway).

thanks
-- PMM
Joelle van Dyne Jan. 23, 2021, 8 p.m. UTC | #2
The problem here is that we would like to compile on macOS 11 and be
able to run the built binaries on macOS 10.15 or lower. Without the
runtime checks, you'll have a crash when calling preadv/pwritev.

-j

On Sat, Jan 23, 2021 at 5:53 AM Peter Maydell <peter.maydell@linaro.org> wrote:
>
> On Sat, 23 Jan 2021 at 05:03, Joelle van Dyne <j@getutm.app> 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.
>
> If you make the preadv check be a meson.build has_function()
> test, I think (but have not tested) that it ought to correctly
> fail the link in the targeting-lower-OS-version case, because
> meson.build's has_function() implementation for clang
> https://github.com/mesonbuild/meson/blob/bad0e95caec4cf49165572df3cf2edc4832280fa/mesonbuild/compilers/mixins/clang.py#L89
> adds -Wl,-no-weak-imports when it's building the test-case
> exactly to force that linker visibility obeys the minimum
> version targets for OSX.
>
> If that works I think it would be neater than delaying the
> check to runtime (and it would also mean another test moved
> out of configure and into meson.build, which is the direction
> we're heading anyway).
>
> thanks
> -- PMM
Joelle van Dyne Jan. 23, 2021, 8:04 p.m. UTC | #3
Sorry to rephrase this, we would like a single binary to work on both
macOS 10.15 and macOS 11 as well as on both iOS 13 and iOS 14 while
ALSO supporting preadv/pwritev when running on the newer OS.

-j

On Sat, Jan 23, 2021 at 12:00 PM Joelle van Dyne <j@getutm.app> wrote:
>
> The problem here is that we would like to compile on macOS 11 and be
> able to run the built binaries on macOS 10.15 or lower. Without the
> runtime checks, you'll have a crash when calling preadv/pwritev.
>
> -j
>
> On Sat, Jan 23, 2021 at 5:53 AM Peter Maydell <peter.maydell@linaro.org> wrote:
> >
> > On Sat, 23 Jan 2021 at 05:03, Joelle van Dyne <j@getutm.app> 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.
> >
> > If you make the preadv check be a meson.build has_function()
> > test, I think (but have not tested) that it ought to correctly
> > fail the link in the targeting-lower-OS-version case, because
> > meson.build's has_function() implementation for clang
> > https://github.com/mesonbuild/meson/blob/bad0e95caec4cf49165572df3cf2edc4832280fa/mesonbuild/compilers/mixins/clang.py#L89
> > adds -Wl,-no-weak-imports when it's building the test-case
> > exactly to force that linker visibility obeys the minimum
> > version targets for OSX.
> >
> > If that works I think it would be neater than delaying the
> > check to runtime (and it would also mean another test moved
> > out of configure and into meson.build, which is the direction
> > we're heading anyway).
> >
> > thanks
> > -- PMM
diff mbox series

Patch

diff --git a/block/file-posix.c b/block/file-posix.c
index 666d3e7504..6473f84db8 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -1386,17 +1386,50 @@  static int handle_aiocb_flush(void *opaque)
 #ifdef CONFIG_PREADV
 
 static bool preadv_present = true;
+static bool preadv_checked;
 
 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 (unlikely(!preadv_checked)) {
+        if (__builtin_available(macOS 11, iOS 14, watchOS 7, tvOS 14, *)) {
+            preadv_checked = true;
+        } else {
+            preadv_present = false;
+            return -ENOSYS;
+        }
+    }
+    /* Now we suppress the availability warning since we use the cached check */
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunguarded-availability-new"
+    return preadv(fd, iov, nr_iov, offset);
+#pragma clang diagnostic pop
+#else /* CONFIG_DARWIN */
     return preadv(fd, iov, nr_iov, offset);
+#endif
 }
 
 static ssize_t
 qemu_pwritev(int fd, const struct iovec *iov, int nr_iov, off_t offset)
 {
+#ifdef CONFIG_DARWIN /* preadv introduced in macOS 11 */
+    if (unlikely(!preadv_checked)) {
+        if (__builtin_available(macOS 11, iOS 14, watchOS 7, tvOS 14, *)) {
+            preadv_checked = true;
+        } else {
+            preadv_present = false;
+            return -ENOSYS;
+        }
+    }
+    /* Now we suppress the availability warning since we use the cached check */
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunguarded-availability-new"
+    return pwritev(fd, iov, nr_iov, offset);
+#pragma clang diagnostic pop
+#else /* CONFIG_DARWIN */
     return pwritev(fd, iov, nr_iov, offset);
+#endif
 }
 
 #else