Handle NO_OPEN/NO_OPENDIR support automatically (#949)
authorJosef Bacik <josef@toxicpanda.com>
Fri, 10 May 2024 15:52:20 +0000 (11:52 -0400)
committerGitHub <noreply@github.com>
Fri, 10 May 2024 15:52:20 +0000 (17:52 +0200)
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>
include/fuse_common.h
include/fuse_lowlevel.h
lib/fuse_lowlevel.c

index bafcda07642436eb7b83a999e969bfa3d6e2946e..8803b68177e7502ab3c808581c63237fd2ab1f9d 100644 (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)
 
index 330d40e5416a22189e83f6c36a70f9935512029f..8ff111a70a5b3a5359678ff967a42178c9331d03 100644 (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
index 5129a3b21b386feb6b3c94f9c93caaede29a3c30..46aef98815a722d78907a027bbaf7fdb5017c898 100644 (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);
 }