Note: This bug is displayed in read-only format because the product is no longer active in Red Hat Bugzilla.

Bug 1828252

Summary: auto-read-only doesn't work with read-only logical volumes
Product: Red Hat Enterprise Linux Advanced Virtualization Reporter: Peter Krempa <pkrempa>
Component: qemu-kvmAssignee: Kevin Wolf <kwolf>
qemu-kvm sub component: Storage QA Contact: qing.wang <qinwang>
Status: CLOSED ERRATA Docs Contact:
Severity: medium    
Priority: medium CC: aliang, coli, ddepaula, jinzhao, juzhang, qinwang, virt-maint
Version: 8.2Keywords: Regression, Triaged
Target Milestone: rcFlags: pm-rhel: mirror+
Target Release: 8.3   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: qemu-kvm-5.1.0-2.module+el8.3.0+7652+b30e6901 Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2020-11-17 17:48:27 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Peter Krempa 2020-04-27 12:52:42 UTC
Description of problem:
'auto-read-only' used on a 'host_device' backend doesn't properly set the node to read-only if the logical-volume itself is read-only.

VM start then fails with the following error:
qemu-system-x86_64: -blockdev {"driver":"host_device","filename":"/dev/angien/ro-test","node-name":"libvirt-3-storage","cache":{"direct":true,"no-flush":false},"auto-read-only":true,"discard":"unmap"}: The device is not writable: Permission denied

Version-Release number of selected component (if applicable):
observed on current upstream

How reproducible:
always

Steps to Reproduce:
1. Create read-only logical volume

lvcreate --size 10M --name ro-test --permission r $VG

2. start qemu:

qemu-system-x86_64 -blockdev '{"driver":"host_device","filename":"/dev/angien/ro-test","node-name":"libvirt-3-storage","cache":{"direct":true,"no-flush":false},"auto-read-only":true,"discard":"unmap"}'


Actual results:

qemu-system-x86_64: -blockdev {"driver":"host_device","filename":"/dev/angien/ro-test","node-name":"libvirt-3-storage","cache":{"direct":true,"no-flush":false},"auto-read-only":true,"discard":"unmap"}: The device is not writable: Permission denied

Expected results:
qemu starts

Additional info:
Note that while it may seem that in the above situation 'read-only' should be used but note that the logical volume may be a backing image for a qcow2 image and the user may turn the logical volume to read-write using lvchange. Using read-only would then prevent libvirt from doing blockjobs.

See also:
https://bugs.launchpad.net/qemu/+bug/1875139

Comment 1 qing.wang 2020-04-28 07:34:39 UTC
Reproduce on
4.18.0-193.el8.x86_64
qemu-kvm-core-4.2.0-17.module+el8.2.0+6141+0f540f16.x86_64


1.create lvm
lvname=/dev/vg_scsi_debug/ro-test

lvremove -f ${lvname} 
vgremove -f vg_scsi_debug

modprobe -r scsi_debug; modprobe scsi_debug  lbpu=1 lbpws=1 lbprz=0 dev_size_mb=512
devname=`lsscsi |grep scsi|awk '{ print $6 }'`

echo "${devname}"
pvcreate ${devname}
vgcreate vg_scsi_debug ${devname}
lvcreate --size 128M --name ro-test --permission r vg_scsi_debug

2.boot vm:
/usr/libexec/qemu-kvm \
    -name 'avocado-vt-vm1'  \
    -sandbox on  \
    -machine q35 \
    -device pcie-root-port,id=pcie-root-port-0,multifunction=on,bus=pcie.0,addr=0x1,chassis=1 \
    -device pcie-pci-bridge,id=pcie-pci-bridge-0,addr=0x0,bus=pcie-root-port-0  \
    -nodefaults \
    -device VGA,bus=pcie.0,addr=0x2 \
    -m 2048  \
    -device pcie-root-port,id=pcie-root-port-1,port=0x1,addr=0x1.0x1,bus=pcie.0,chassis=2 \
    -device qemu-xhci,id=usb1,bus=pcie-root-port-1,addr=0x0 \
    -device usb-tablet,id=usb-tablet1,bus=usb1.0,port=1 \
    -device pcie-root-port,id=pcie-root-port-2,port=0x2,addr=0x1.0x2,bus=pcie.0,chassis=3 \
    -device virtio-scsi-pci,id=virtio_scsi_pci0,bus=pcie-root-port-2,addr=0x0 \
    -blockdev node-name=file_image1,driver=file,aio=threads,filename=/home/kvm_autotest_root/images/rhel821-64-virtio-scsi.qcow2,cache.direct=on,cache.no-flush=off \
    -blockdev node-name=drive_image1,driver=qcow2,cache.direct=on,cache.no-flush=off,file=file_image1 \
    -device scsi-hd,id=image1,drive=drive_image1,write-cache=on \
    \
    -blockdev node-name=file_stg1,driver=host_device,aio=threads,filename=${lvname},cache.direct=on,cache.no-flush=off,auto-read-only=on,discard=unmap \
    -blockdev node-name=drive_stg1,driver=raw,cache.direct=on,cache.no-flush=off,file=file_stg1,discard=unmap,auto-read-only=on \
    -device scsi-hd,id=stg1,drive=drive_stg1,scsi-id=12 \
    \
    -device pcie-root-port,id=pcie-root-port-3,port=0x3,addr=0x1.0x3,bus=pcie.0,chassis=4 \
    -device virtio-net-pci,mac=9a:5b:4f:9b:c3:b0,id=idg2bFqS,netdev=ida2LQKm,bus=pcie-root-port-3,addr=0x0  \
    -netdev tap,id=ida2LQKm,vhost=on  \
    -vnc :6  \
    -qmp tcp:0:5956,server,nowait  \
    -rtc base=utc,clock=host,driftfix=slew  \
    -boot menu=off,order=cdn,once=c,strict=off \
    -enable-kvm -monitor stdio \
    -device pcie-root-port,id=pcie_extra_root_port_0,multifunction=on,bus=pcie.0,addr=0x3,chassis=5 \
    -device virtio-serial-pci,disable-legacy=on,disable-modern=off,id=virtio-serial0 \
    -chardev socket,path=/tmp/qga.sock,server,nowait,id=qga0 \
    -device virtserialport,bus=virtio-serial0.0,nr=1,chardev=qga0,id=channel1,name=org.qemu.guest_agent.0 \


result:
qemu-kvm: -blockdev node-name=file_stg1,driver=host_device,aio=threads,filename=/dev/vg_scsi_debug/ro-test,cache.direct=on,cache.no-flush=off,auto-read-only=on,discard=unmap: The device is not writable: Permission denied

Comment 2 qing.wang 2020-04-28 08:00:50 UTC
BTW, it works with on with read-only command

/usr/libexec/qemu-kvm -blockdev '{"driver":"host_device","filename":"/dev/vg_scsi_debug/ro-test","node-name":"libvirt-3-storage","cache":{"direct":true,"no-flush":false},"auto-read-only":true,"read-only":true,"discard":"unmap"}'

Comment 3 Peter Krempa 2020-04-29 05:04:07 UTC
Yes, read-only works, but unfortunately that will prevent libvirt from using blockjobs.

Comment 8 Kevin Wolf 2020-05-18 15:32:40 UTC
hdev_open() has an explicit check whether the block device is read-only and this will fail. As commit da888d37 explains, this is because the file permissions of the device node and whether the block device is read-only are two independent properties.

I guess we could move the check to whenever we first try to reopen the file-posix node read-write, though by that point it would be too late for a good error message without auto-read-only.

Anyway, does this really affect the libvirt use case? I thought libvirt was more concerned with permissions than whether the device is read-only per se. If I test a writable LV for which I only have read permissions, QEMU correctly opens the file with auto-read-only (and I assume the same is true for SELinux permission, though I didn't test it). On the other hand, opening a read-only LV fails with auto-read-only, no matter whether or not I have the right file permissions.

Not trying to discuss the problem away, it clearly seems that file-posix doesn't fully implement auto-read-only for all cases yet even though it should.

Comment 12 qing.wang 2020-08-13 07:54:01 UTC
Test Failed on 
4.18.0-227.el8.x86_64
qemu-kvm-core-5.1.0-2.module+el8.3.0+7652+b30e6901.x86_64
seabios-1.14.0-1.module+el8.3.0+7638+07cf13d2.x86_64

Test step
1.create read only lvm
lvname=/dev/vg_scsi_debug/ro-test

lvremove -f ${lvname}
vgremove -f vg_scsi_debug

modprobe -r scsi_debug; modprobe scsi_debug  lbpu=1 lbpws=1 lbprz=0 dev_size_mb=512
devname=`lsscsi |grep scsi|awk '{ print $6 }'`

echo "${devname}"
pvcreate ${devname}
vgcreate vg_scsi_debug ${devname}
lvcreate --size 128M --name ro-test --permission r vg_scsi_debug

2.boot vm with read-only lvm 
/usr/libexec/qemu-kvm \
    -name 'avocado-vt-vm1'  \
    -sandbox on  \
    -machine q35 \
    -device pcie-root-port,id=pcie-root-port-0,multifunction=on,bus=pcie.0,addr=0x1,chassis=1 \
    -device pcie-pci-bridge,id=pcie-pci-bridge-0,addr=0x0,bus=pcie-root-port-0  \
    -nodefaults \
    -device VGA,bus=pcie.0,addr=0x2 \
    -m 2048  \
    -device pcie-root-port,id=pcie-root-port-1,port=0x1,addr=0x1.0x1,bus=pcie.0,chassis=2 \
    -device qemu-xhci,id=usb1,bus=pcie-root-port-1,addr=0x0 \
    -device usb-tablet,id=usb-tablet1,bus=usb1.0,port=1 \
    -device pcie-root-port,id=pcie-root-port-2,port=0x2,addr=0x1.0x2,bus=pcie.0,chassis=3 \
    -device virtio-scsi-pci,id=virtio_scsi_pci0,bus=pcie-root-port-2,addr=0x0 \
    -blockdev node-name=file_image1,driver=file,aio=threads,filename=/home/kvm_autotest_root/images/rhel830-64-virtio-scsi.qcow2,cache.direct=on,cache.no-flush=off \
    -blockdev node-name=drive_image1,driver=qcow2,cache.direct=on,cache.no-flush=off,file=file_image1 \
    -device scsi-hd,id=image1,drive=drive_image1,write-cache=on \
    \
   -blockdev node-name=file_stg1,driver=host_device,aio=threads,filename=${lvname},cache.direct=on,cache.no-flush=off,auto-read-only=on,discard=unmap \
   -blockdev node-name=drive_stg1,driver=raw,cache.direct=on,cache.no-flush=off,file=file_stg1,discard=unmap,auto-read-only=on \
   -device scsi-hd,id=stg1,drive=drive_stg1 \
    \
     -device pcie-root-port,id=pcie-root-port-3,port=0x3,addr=0x1.0x3,bus=pcie.0,chassis=4 \
    -device virtio-net-pci,mac=9a:5b:4f:9b:c3:b0,id=idg2bFqS,netdev=ida2LQKm,bus=pcie-root-port-3,addr=0x0  \
    -netdev tap,id=ida2LQKm,vhost=on  \
    -vnc :6  \
    -qmp tcp:0:5956,server,nowait  \
    -rtc base=utc,clock=host,driftfix=slew  \
    -boot menu=off,order=cdn,once=c,strict=off \
    -enable-kvm -monitor stdio \
    -device pcie-root-port,id=pcie_extra_root_port_0,multifunction=on,bus=pcie.0,addr=0x3,chassis=5 \
    -device virtio-serial-pci,disable-legacy=on,disable-modern=off,id=virtio-serial0 \
    -chardev socket,path=/tmp/qga.sock,server,nowait,id=qga0 \
    -device virtserialport,bus=virtio-serial0.0,nr=1,chardev=qga0,id=channel1,name=org.qemu.guest_agent.0 \


Actual result:
qemu-kvm: -device scsi-hd,id=stg1,drive=drive_stg1: The device is not writable: Permission denied

Comment 13 Kevin Wolf 2020-08-13 10:21:16 UTC
(In reply to qing.wang from comment #12)
> Actual result:
> qemu-kvm: -device scsi-hd,id=stg1,drive=drive_stg1: The device is not
> writable: Permission denied

This is expected. If auto-read-only makes QEMU fall back to read-only for the volume, you can't attach this volume to a read-write guest device.

Compare the original error message in comment 0 with this one: Previously, -blockdev would fail, now it is only using the block device in -device for a read-write scsi-hd.

If you don't use the block node in -device, or only for a read-only device (e.g. scsi-cd), you would get a failure previously and it should succeed now.

Comment 14 qing.wang 2020-08-17 09:43:29 UTC
It works on "auto-read-only=on,read-only=on" and for the device.

  -blockdev node-name=file_stg1,driver=host_device,aio=threads,filename=${lvname},cache.direct=on,cache.no-flush=off,auto-read-only=on,read-only=on,discard=unmap \
   -blockdev node-name=drive_stg1,driver=raw,cache.direct=on,cache.no-flush=off,file=file_stg1,discard=unmap,auto-read-only=on,read-only=on \
   -device scsi-hd,id=stg1,drive=drive_stg1 \

or delete device scs-hd

  -blockdev node-name=file_stg1,driver=host_device,aio=threads,filename=${lvname},cache.direct=on,cache.no-flush=off,auto-read-only=on,discard=unmap \
   -blockdev node-name=drive_stg1,driver=raw,cache.direct=on,cache.no-flush=off,file=file_stg1,discard=unmap,auto-read-only=on \



/usr/libexec/qemu-kvm \
    -name 'avocado-vt-vm1'  \
    -sandbox on  \
    -machine q35 \
    -device pcie-root-port,id=pcie-root-port-0,multifunction=on,bus=pcie.0,addr=0x1,chassis=1 \
    -device pcie-pci-bridge,id=pcie-pci-bridge-0,addr=0x0,bus=pcie-root-port-0  \
    -nodefaults \
    -device VGA,bus=pcie.0,addr=0x2 \
    -m 2048  \
    -device pcie-root-port,id=pcie-root-port-1,port=0x1,addr=0x1.0x1,bus=pcie.0,chassis=2 \
    -device qemu-xhci,id=usb1,bus=pcie-root-port-1,addr=0x0 \
    -device usb-tablet,id=usb-tablet1,bus=usb1.0,port=1 \
    -device pcie-root-port,id=pcie-root-port-2,port=0x2,addr=0x1.0x2,bus=pcie.0,chassis=3 \
    -device virtio-scsi-pci,id=virtio_scsi_pci0,bus=pcie-root-port-2,addr=0x0 \
    -blockdev node-name=file_image1,driver=file,aio=threads,filename=/home/kvm_autotest_root/images/rhel830-64-virtio-scsi.qcow2,cache.direct=on,cache.no-flush=off \
    -blockdev node-name=drive_image1,driver=qcow2,cache.direct=on,cache.no-flush=off,file=file_image1 \
    -device scsi-hd,id=image1,drive=drive_image1,write-cache=on \
    \
   -blockdev node-name=file_stg1,driver=host_device,aio=threads,filename=${lvname},cache.direct=on,cache.no-flush=off,auto-read-only=on,read-only=on,discard=unmap \
   -blockdev node-name=drive_stg1,driver=raw,cache.direct=on,cache.no-flush=off,file=file_stg1,discard=unmap,auto-read-only=on,read-only=on \
   -device scsi-hd,id=stg1,drive=drive_stg1 \
    \
     -device pcie-root-port,id=pcie-root-port-3,port=0x3,addr=0x1.0x3,bus=pcie.0,chassis=4 \
    -device virtio-net-pci,mac=9a:5b:4f:9b:c3:b0,id=idg2bFqS,netdev=ida2LQKm,bus=pcie-root-port-3,addr=0x0  \
    -netdev tap,id=ida2LQKm,vhost=on  \
    -vnc :6  \
    -qmp tcp:0:5956,server,nowait  \
    -rtc base=utc,clock=host,driftfix=slew  \
    -boot menu=off,order=cdn,once=c,strict=off \
    -enable-kvm -monitor stdio \
    -device pcie-root-port,id=pcie_extra_root_port_0,multifunction=on,bus=pcie.0,addr=0x3,chassis=5 \
    -device virtio-serial-pci,disable-legacy=on,disable-modern=off,id=virtio-serial0 \
    -chardev socket,path=/tmp/qga.sock,server,nowait,id=qga0 \
    -device virtserialport,bus=virtio-serial0.0,nr=1,chardev=qga0,id=channel1,name=org.qemu.guest_agent.0 \



or remove

Comment 17 errata-xmlrpc 2020-11-17 17:48:27 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory (virt:8.3 bug fix and enhancement update), and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHBA-2020:5137