From: Bernd Schubert Date: Thu, 12 Sep 2024 14:06:09 +0000 (+0200) Subject: example/passthrough_hp: No auto FOPEN_DIRECT_IO in passthrough mode X-Git-Tag: fuse-3.17.1-rc0~75 X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=c00c9fd831ecbc17522271ba887f1c35ed61867c;p=qemu-gpiodev%2Flibfuse.git example/passthrough_hp: No auto FOPEN_DIRECT_IO in passthrough mode sfs_open and sfs_create set fi->direct_io (FOPEN_DIRECT_IO) when O_DIRECT is given, in order to benefit from a shared inode lock in kernel, i.e. to get parallel DIO writes. However, kernel side disabled passthrough when FOPEN_DIRECT_IO is set. Reads/writes had been totally failing in this case for O_DIRECT as sfs_write_buf() and sfs_read() have a sanity check. That sanity check could be modified, but for performance passthrough is better than parallel DIO, hence, we only want automatic FOPEN_DIRECT_IO for O_DIRECT when passthrough is not enabled. Fixes: https://github.com/libfuse/libfuse/issues/1027 This also fixes automatically switching to FOPEN_DIRECT_IO for O_DIRECT in sfs_create(). --- diff --git a/example/passthrough_hp.cc b/example/passthrough_hp.cc index e75c749..4f0dd5e 100644 --- a/example/passthrough_hp.cc +++ b/example/passthrough_hp.cc @@ -851,6 +851,28 @@ static void do_passthrough_open(fuse_req_t req, fuse_ino_t ino, int fd, fi->keep_cache = false; } +static void sfs_create_open_flags(fuse_file_info *fi) +{ + if (fs.direct_io) + fi->direct_io = 1; + + /* + * fi->direct_io (FOPEN_DIRECT_IO) is set to benefit from + * parallel_direct_writes, which kernel cannot do for plain O_DIRECT. + * However, passthrough is preferred, but which is not possible when + * FOPEN_DIRECT_IO is set. + */ + if (!fs.passthrough) { + if (fi->flags & O_DIRECT) + fi->direct_io = 1; + } + + /* parallel_direct_writes feature depends on direct_io features. + To make parallel_direct_writes valid, need set fi->direct_io + in current function. */ + fi->parallel_direct_writes = 1; +} + static void sfs_create(fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode, fuse_file_info *fi) { Inode& inode_p = get_inode(parent); @@ -872,20 +894,15 @@ static void sfs_create(fuse_req_t req, fuse_ino_t parent, const char *name, if (err == ENFILE || err == EMFILE) cerr << "ERROR: Reached maximum number of file descriptors." << endl; fuse_reply_err(req, err); - return; + return; } - if (fs.direct_io) - fi->direct_io = 1; - - /* parallel_direct_writes feature depends on direct_io features. - To make parallel_direct_writes valid, need set fi->direct_io - in current function. */ - fi->parallel_direct_writes = 1; - Inode& inode = get_inode(e.ino); lock_guard g {inode.m}; inode.nopen++; + + sfs_create_open_flags(fi); + if (fs.passthrough) do_passthrough_open(req, e.ino, fd, fi); fuse_reply_create(req, &e, fi); @@ -942,19 +959,7 @@ static void sfs_open(fuse_req_t req, fuse_ino_t ino, fuse_file_info *fi) { fi->keep_cache = (fs.timeout != 0); fi->noflush = (fs.timeout == 0 && (fi->flags & O_ACCMODE) == O_RDONLY); - if (fs.direct_io) - fi->direct_io = 1; - - /* Enable direct_io when open has flags O_DIRECT to enjoy the feature - parallel_direct_writes (i.e., to get a shared lock, not exclusive lock, - for writes to the same file). */ - if (fi->flags & O_DIRECT) - fi->direct_io = 1; - - /* parallel_direct_writes feature depends on direct_io features. - To make parallel_direct_writes valid, need set fi->direct_io - in current function. */ - fi->parallel_direct_writes = 1; + sfs_create_open_flags(fi); fi->fh = fd; if (fs.passthrough)