From 6439231f9ba8af9c0eab8dcda54a8fc31e63ae99 Mon Sep 17 00:00:00 2001 From: Chad Austin Date: Tue, 16 Apr 2019 11:44:59 -0700 Subject: [PATCH] Add documentation for opting out of opendir and releasedir (#391) --- ChangeLog.rst | 1 + example/printcap.c | 2 ++ include/fuse_common.h | 12 ++++++++++++ include/fuse_lowlevel.h | 7 +++++++ lib/fuse_lowlevel.c | 2 ++ 5 files changed, 24 insertions(+) diff --git a/ChangeLog.rst b/ChangeLog.rst index d1bbbec..a32d9ec 100644 --- a/ChangeLog.rst +++ b/ChangeLog.rst @@ -8,6 +8,7 @@ libfuse 3.5.0 (UNRELEASED) on mountpoints within SMB 2.0 filesystems). * Added a new `cache_readdir` flag to `fuse_file_info` to enable caching of readdir results. Supported by kernels 4.20 and newer. +* Add support and documentation for FUSE_CAP_NO_OPENDIR_SUPPORT. libfuse 3.4.2 (2019-03-09) ========================== diff --git a/example/printcap.c b/example/printcap.c index 77dea14..580f52c 100644 --- a/example/printcap.c +++ b/example/printcap.c @@ -77,6 +77,8 @@ static void pc_init(void *userdata, printf("\tFUSE_CAP_PARALLEL_DIROPS\n"); if(conn->capable & FUSE_CAP_POSIX_ACL) printf("\tFUSE_CAP_POSIX_ACL\n"); + if(conn->capable & FUSE_CAP_NO_OPENDIR_SUPPORT) + printf("\tFUSE_CAP_NO_OPENDIR_SUPPORT\n"); fuse_session_exit(se); } diff --git a/include/fuse_common.h b/include/fuse_common.h index 823a37d..0481aac 100644 --- a/include/fuse_common.h +++ b/include/fuse_common.h @@ -335,6 +335,18 @@ struct fuse_loop_config { */ #define FUSE_CAP_HANDLE_KILLPRIV (1 << 20) +/** + * Indicates support for zero-message opendirs. If this flag is set in + * the `capable` field of the `fuse_conn_info` structure, then the filesystem + * may return `ENOSYS` from the opendir() handler to indicate success. Further + * opendir and releasedir messages will be handled in the kernel. (If this + * flag is not set, returning ENOSYS will be treated as an error and signalled + * to the caller.) + * + * Setting (or unsetting) this flag in the `want` field has *no effect*. + */ +#define FUSE_CAP_NO_OPENDIR_SUPPORT (1 << 24) + /** * Ioctl flags * diff --git a/include/fuse_lowlevel.h b/include/fuse_lowlevel.h index 87c362a..b7afe16 100644 --- a/include/fuse_lowlevel.h +++ b/include/fuse_lowlevel.h @@ -665,6 +665,13 @@ struct fuse_lowlevel_ops { * etc) in fi->fh, and use this in other all other directory * stream operations (readdir, releasedir, fsyncdir). * + * If this request is answered with an error code of ENOSYS and + * FUSE_CAP_NO_OPENDIR_SUPPORT is set in `fuse_conn_info.capable`, + * this is treated as success and future calls to opendir and + * releasedir will also succeed without being sent to the filesystem + * process. In addition, the kernel will cache readdir results + * as if opendir returned FOPEN_KEEP_CACHE | FOPEN_CACHE_DIR. + * * Valid replies: * fuse_reply_open * fuse_reply_err diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index 50fff4d..ec0daaf 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -1907,6 +1907,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) se->conn.capable |= FUSE_CAP_POSIX_ACL; if (arg->flags & FUSE_HANDLE_KILLPRIV) se->conn.capable |= FUSE_CAP_HANDLE_KILLPRIV; + if (arg->flags & FUSE_NO_OPENDIR_SUPPORT) + se->conn.capable |= FUSE_CAP_NO_OPENDIR_SUPPORT; } else { se->conn.max_readahead = 0; }