diff mbox

[2/2] file-posix: Do runtime check for ofd lock API

Message ID 20170721102059.14663-3-famz@redhat.com
State New
Headers show

Commit Message

Fam Zheng July 21, 2017, 10:20 a.m. UTC
It is reported that on Windows Subsystem for Linux, ofd operations fail
with -EINVAL. In other words, QEMU binary built with system headers that
exports F_OFD_SETLK doesn't necessarily run in an environment that
actually supports it:

$ qemu-system-aarch64 ... -drive file=test.vhdx,if=none,id=hd0 \
    -device virtio-blk-pci,drive=hd0
qemu-system-aarch64: -drive file=test.vhdx,if=none,id=hd0: Failed to unlock byte 100
qemu-system-aarch64: -drive file=test.vhdx,if=none,id=hd0: Failed to unlock byte 100
qemu-system-aarch64: -drive file=test.vhdx,if=none,id=hd0: Failed to lock byte 100

Let's do a runtime check to cope with that.

Reported-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
Signed-off-by: Fam Zheng <famz@redhat.com>
---
 block/file-posix.c | 19 ++++++++-----------
 1 file changed, 8 insertions(+), 11 deletions(-)

Comments

Eric Blake July 21, 2017, 12:36 p.m. UTC | #1
On 07/21/2017 05:20 AM, Fam Zheng wrote:
> It is reported that on Windows Subsystem for Linux, ofd operations fail
> with -EINVAL. In other words, QEMU binary built with system headers that
> exports F_OFD_SETLK doesn't necessarily run in an environment that
> actually supports it:
> 
> $ qemu-system-aarch64 ... -drive file=test.vhdx,if=none,id=hd0 \
>     -device virtio-blk-pci,drive=hd0
> qemu-system-aarch64: -drive file=test.vhdx,if=none,id=hd0: Failed to unlock byte 100
> qemu-system-aarch64: -drive file=test.vhdx,if=none,id=hd0: Failed to unlock byte 100
> qemu-system-aarch64: -drive file=test.vhdx,if=none,id=hd0: Failed to lock byte 100
> 
> Let's do a runtime check to cope with that.

You may want to mention that the same is possible on a system with old
kernel but new glibc (ie. this issue is not necessarily specific to WSL).

> 
> Reported-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
> Signed-off-by: Fam Zheng <famz@redhat.com>
> ---
>  block/file-posix.c | 19 ++++++++-----------
>  1 file changed, 8 insertions(+), 11 deletions(-)
> 

Reviewed-by: Eric Blake <eblake@redhat.com>
Cameron Esfahani via July 21, 2017, 5:23 p.m. UTC | #2
> From: Fam Zheng [mailto:famz@redhat.com]
> Sent: Friday, 21 July 2017 3:21
> 
> It is reported that on Windows Subsystem for Linux, ofd operations fail
> with -EINVAL. In other words, QEMU binary built with system headers that
> exports F_OFD_SETLK doesn't necessarily run in an environment that
> actually supports it:
> 
> $ qemu-system-aarch64 ... -drive file=test.vhdx,if=none,id=hd0 \
>     -device virtio-blk-pci,drive=hd0
> qemu-system-aarch64: -drive file=test.vhdx,if=none,id=hd0: Failed to unlock
> byte 100
> qemu-system-aarch64: -drive file=test.vhdx,if=none,id=hd0: Failed to unlock
> byte 100
> qemu-system-aarch64: -drive file=test.vhdx,if=none,id=hd0: Failed to lock
> byte 100
> 
> Let's do a runtime check to cope with that.
> 
> Reported-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
> Signed-off-by: Fam Zheng <famz@redhat.com>
> ---
>  block/file-posix.c | 19 ++++++++-----------
>  1 file changed, 8 insertions(+), 11 deletions(-)

If it helps:
Tested-By: Andrew Baumann <andrew.baumann@microsoft.com>

Thanks!
Andrew
Christian Ehrhardt Aug. 10, 2017, 8:16 a.m. UTC | #3
On Fri, Jul 21, 2017 at 2:36 PM, Eric Blake <eblake@redhat.com> wrote:

> On 07/21/2017 05:20 AM, Fam Zheng wrote:
> > It is reported that on Windows Subsystem for Linux, ofd operations fail
> > with -EINVAL. In other words, QEMU binary built with system headers that
> > exports F_OFD_SETLK doesn't necessarily run in an environment that
> > actually supports it:
> >
> > $ qemu-system-aarch64 ... -drive file=test.vhdx,if=none,id=hd0 \
> >     -device virtio-blk-pci,drive=hd0
> > qemu-system-aarch64: -drive file=test.vhdx,if=none,id=hd0: Failed to
> unlock byte 100
> > qemu-system-aarch64: -drive file=test.vhdx,if=none,id=hd0: Failed to
> unlock byte 100
> > qemu-system-aarch64: -drive file=test.vhdx,if=none,id=hd0: Failed to
> lock byte 100
> >
> > Let's do a runtime check to cope with that.
>
> You may want to mention that the same is possible on a system with old
> kernel but new glibc (ie. this issue is not necessarily specific to WSL).
>

I first thought that this combination hitting me as I run KVM in containers
which can diverge glibc (in container) a lot from kernel (in host).

My issue turned out to be an apparmor block instead.
But since I clearly see how my case could lead to the mentioned
old kernel but new glibc I wanted to ping here to refresh/reconsider
this change as well.

Also the reply might be worth as documentation if people search for the
error
message and get here that the following apparmor block leads to the same.

apparmor="DENIED" operation="file_lock"
namespace="root//lxd-testkvm-artful-from_<var-lib-lxd>"
profile="libvirt-f687a9b3-5bca-41bc-b206-6e616720cc5e"
name="/var/lib/uvtool/libvirt/images/kvmguest-artful-normal.qcow" pid=7001
comm="qemu-system-x86" requested_mask="k" denied_mask="k" fsuid=0 ouid=0

I'll work on libvirt's virt-aa-helper to generate a rule appropriate for
the new behavior.
diff mbox

Patch

diff --git a/block/file-posix.c b/block/file-posix.c
index cfbb236f6f..5ddf2729eb 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -457,22 +457,19 @@  static int raw_open_common(BlockDriverState *bs, QDict *options,
     switch (locking) {
     case ON_OFF_AUTO_ON:
         s->use_lock = true;
-#ifndef F_OFD_SETLK
-        fprintf(stderr,
-                "File lock requested but OFD locking syscall is unavailable, "
-                "falling back to POSIX file locks.\n"
-                "Due to the implementation, locks can be lost unexpectedly.\n");
-#endif
+        if (!qemu_has_ofd_lock()) {
+            fprintf(stderr,
+                    "File lock requested but OFD locking syscall is "
+                    "unavailable, falling back to POSIX file locks.\n"
+                    "Due to the implementation, locks can be lost "
+                    "unexpectedly.\n");
+        }
         break;
     case ON_OFF_AUTO_OFF:
         s->use_lock = false;
         break;
     case ON_OFF_AUTO_AUTO:
-#ifdef F_OFD_SETLK
-        s->use_lock = true;
-#else
-        s->use_lock = false;
-#endif
+        s->use_lock = qemu_has_ofd_lock();
         break;
     default:
         abort();