Handle NO_OPEN/NO_OPENDIR support automatically (#949)

If the file system doesn't provide a ->open or an ->opendir, and the
kernel supports FUSE_CAP_NO_OPEN_SUPPORT or FUSE_CAP_NO_OPENDIR_SUPPORT,
allow the implementation to set FUSE_CAP_NO_OPEN*_SUPPORT on conn->want
in order to automatically get this behavior.  Expand the documentation
to be more explicit about the behavior of libfuse in the different cases
WRT this capability.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
This commit is contained in:
Josef Bacik 2024-05-10 11:52:20 -04:00 committed by GitHub
parent 0128f5efe8
commit 2bdec0bc22
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 26 additions and 3 deletions

View File

@ -325,8 +325,10 @@ struct fuse_loop_config_v1 {
* kernel. (If this flag is not set, returning ENOSYS will be treated
* as an error and signaled to the caller).
*
* Setting (or unsetting) this flag in the `want` field has *no
* effect*.
* Setting this flag in the `want` field enables this behavior automatically
* within libfuse for low level API users. If non-low level users wish to have
* this behavior you must return `ENOSYS` from the open() handler on supporting
* kernels.
*/
#define FUSE_CAP_NO_OPEN_SUPPORT (1 << 17)
@ -404,7 +406,10 @@ struct fuse_loop_config_v1 {
* 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*.
* Setting this flag in the `want` field enables this behavior automatically
* within libfuse for low level API users. If non-low level users with to have
* this behavior you must return `ENOSYS` from the opendir() handler on
* supporting kernels.
*/
#define FUSE_CAP_NO_OPENDIR_SUPPORT (1 << 24)

View File

@ -532,6 +532,13 @@ struct fuse_lowlevel_ops {
* future calls to open and release will also succeed without being
* sent to the filesystem process.
*
* To get this behavior without providing an opendir handler, you may
* set FUSE_CAP_NO_OPEN_SUPPORT in `fuse_conn_info.want` on supported
* kernels to automatically get the zero message open().
*
* If this callback is not provided and FUSE_CAP_NO_OPEN_SUPPORT is not
* set in `fuse_conn_info.want` then an empty reply will be sent.
*
* Valid replies:
* fuse_reply_open
* fuse_reply_err
@ -705,6 +712,13 @@ struct fuse_lowlevel_ops {
* process. In addition, the kernel will cache readdir results
* as if opendir returned FOPEN_KEEP_CACHE | FOPEN_CACHE_DIR.
*
* To get this behavior without providing an opendir handler, you may
* set FUSE_CAP_NO_OPENDIR_SUPPORT in `fuse_conn_info.want` on supported
* kernels to automatically get the zero message opendir().
*
* If this callback is not provided and FUSE_CAP_NO_OPENDIR_SUPPORT is
* not set in `fuse_conn_info.want` then an empty reply will be sent.
*
* Valid replies:
* fuse_reply_open
* fuse_reply_err

View File

@ -1351,6 +1351,8 @@ static void do_open(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
if (req->se->op.open)
req->se->op.open(req, nodeid, &fi);
else if (req->se->conn.want & FUSE_CAP_NO_OPEN_SUPPORT)
fuse_reply_err(req, ENOSYS);
else
fuse_reply_open(req, &fi);
}
@ -1507,6 +1509,8 @@ static void do_opendir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
if (req->se->op.opendir)
req->se->op.opendir(req, nodeid, &fi);
else if (req->se->conn.want & FUSE_CAP_NO_OPENDIR_SUPPORT)
fuse_reply_err(req, ENOSYS);
else
fuse_reply_open(req, &fi);
}