On 05.05.26 13:01, Fiona Ebner wrote:
Am 05.05.26 um 11:03 AM schrieb Fiona Ebner:
Am 30.04.26 um 4:20 PM schrieb Fiona Ebner:
Dear Maintainers,

Am 10.03.26 um 6:33 PM schrieb Kevin Wolf:
From: Hanna Czenczek <[email protected]>

In fuse_open(), set these flags:
- direct_io: We probably actually don't want to have the host page cache
   be used for our exports.  QEMU block exports are supposed to represent
   the image as-is (and thus potentially changing).
   This causes a change in iotest 308's reference output.

- parallel_direct_writes: We can (now) cope with parallel writes, so we
   should set this flag.  For some reason, it doesn't seem to make an
   actual performance difference with libfuse, but it does make a
   difference without it, so let's set it.
   (See "fuse: Copy write buffer content before polling" for further
   discussion.)

Reviewed-by: Stefan Hajnoczi <[email protected]>
Signed-off-by: Hanna Czenczek <[email protected]>
Message-ID: <[email protected]>
Reviewed-by: Kevin Wolf <[email protected]>
Signed-off-by: Kevin Wolf <[email protected]>
---
  block/export/fuse.c        | 2 ++
  tests/qemu-iotests/308.out | 2 +-
  2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/block/export/fuse.c b/block/export/fuse.c
index 0422cf4b8af..d0e3c6bf61f 100644
--- a/block/export/fuse.c
+++ b/block/export/fuse.c
@@ -582,6 +582,8 @@ static void fuse_setattr(fuse_req_t req, fuse_ino_t inode, 
struct stat *statbuf,
  static void fuse_open(fuse_req_t req, fuse_ino_t inode,
                        struct fuse_file_info *fi)
  {
+    fi->direct_io = true;
unfortunately, turning on direct IO here breaks a use case with swtpm.
Reproducer below [0], which fails with an error message
   /usr/bin/swtpm exit with status 256:
after this commit.

Dropping the FOPEN_DIRECT_IO flag in current master makes the reproducer
work again.

Should there be a BlockExportOptionsFuse property to control the direct
IO flag and have it be opt-in to avoid this breakage (and potentially
others)?

Best Regards,
Fiona

[0]:

#!/bin/bash
rm /tmp/disk.qcow2
rm /tmp/export.fuse
./qemu-img create -f qcow2 /tmp/disk.qcow2 4M
touch /tmp/export.fuse
(
./storage-daemon/qemu-storage-daemon \
     --blockdev 
qcow2,node-name=node0,file.driver=file,file.filename=/tmp/disk.qcow2 \
     --export 
fuse,id=exp0,mountpoint=/tmp/export.fuse,node-name=node0,writable=true \
     --chardev socket,id=qmp,path=/run/qsd.qmp,server=on,wait=off \
     --monitor chardev=qmp,mode=control
) &
sleep 1 # too lazy to do proper synchronization for the reproducer here
swtpm_setup --tpmstate file:///tmp/export.fuse --createek
echo '{"execute": "qmp_capabilities"}{"execute": "quit"}' | socat - /run/qsd.qmp
Self-contained version modeling the relevant part of swtpm_setup:

#!/bin/bash

cat - > /tmp/mmap.c <<EOF
#include <assert.h>
#include <fcntl.h>
#include <stddef.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc, char **argv)
{
     struct stat st;
     int fd;
     void *ptr;

     assert(argc == 2);
     fd = open(argv[1], O_RDWR|O_CREAT, 0x640);
     assert(fd > 0);
     fstat(fd, &st);
     ptr = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
     assert(ptr != MAP_FAILED);
     return 0;
}
EOF
gcc /tmp/mmap.c -o /tmp/mmap

rm /tmp/disk.qcow2
rm /tmp/export.fuse
./qemu-img create -f qcow2 /tmp/disk.qcow2 4M
touch /tmp/export.fuse

(
./storage-daemon/qemu-storage-daemon \
     --blockdev 
qcow2,node-name=node0,file.driver=file,file.filename=/tmp/disk.qcow2 \
     --export 
fuse,id=exp0,mountpoint=/tmp/export.fuse,node-name=node0,writable=true \
     --chardev socket,id=qmp,path=/run/qsd.qmp,server=on,wait=off \
     --monitor chardev=qmp,mode=control
) &

sleep 1 # too lazy to do proper synchronization for the reproducer here
/tmp/mmap /tmp/export.fuse
echo '{"execute": "qmp_capabilities"}{"execute": "quit"}' | socat - /run/qsd.qmp
The kernel docs [0] mention:

"In direct-io mode the page cache is completely bypassed for reads and
writes. No read-ahead takes place. Shared mmap is disabled by default.
To allow shared mmap, the FUSE_DIRECT_IO_ALLOW_MMAP flag may be enabled
in the FUSE_INIT reply."

I quickly tested with setting FUSE_DIRECT_IO_ALLOW_MMAP in
fuse_co_init() (it's part of the flags2 ones, so also requires
FUSE_INIT_EXT to be set in the flags) and this makes the swtpm use case
work again :)

So, should that flag be set by default (if supported by the kernel) for
backwards compatibility? Or what should we do about the issue?

I see no reason not to set the flag (FUSE_DIRECT_IO_ALLOW_MMAP). Sounds very good to me!

Hanna


Reply via email to