]> Git Repo - linux.git/commitdiff
fuse: support clients that don't implement 'opendir'
authorChad Austin <[email protected]>
Tue, 8 Jan 2019 00:53:17 +0000 (16:53 -0800)
committerMiklos Szeredi <[email protected]>
Wed, 13 Feb 2019 12:15:15 +0000 (13:15 +0100)
Allow filesystems to return ENOSYS from opendir, preventing the kernel from
sending opendir and releasedir messages in the future. This avoids
userspace transitions when filesystems don't need to keep track of state
per directory handle.

A new capability flag, FUSE_NO_OPENDIR_SUPPORT, parallels
FUSE_NO_OPEN_SUPPORT, indicating the new semantics for returning ENOSYS
from opendir.

Signed-off-by: Chad Austin <[email protected]>
Signed-off-by: Miklos Szeredi <[email protected]>
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/fuse/inode.c
include/uapi/linux/fuse.h

index 8ee0446a8322a5de096064a89a302ddc0c641f2d..cc6ffd23b80f75e2a5e069bb44a1572baff164c0 100644 (file)
@@ -90,7 +90,7 @@ static void fuse_file_put(struct fuse_file *ff, bool sync, bool isdir)
        if (refcount_dec_and_test(&ff->count)) {
                struct fuse_req *req = ff->reserved_req;
 
-               if (ff->fc->no_open && !isdir) {
+               if (isdir ? ff->fc->no_opendir : ff->fc->no_open) {
                        /*
                         * Drop the release request when client does not
                         * implement 'open'
@@ -125,7 +125,7 @@ int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
 
        ff->fh = 0;
        ff->open_flags = FOPEN_KEEP_CACHE; /* Default for no-open */
-       if (!fc->no_open || isdir) {
+       if (isdir ? !fc->no_opendir : !fc->no_open) {
                struct fuse_open_out outarg;
                int err;
 
@@ -134,11 +134,14 @@ int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
                        ff->fh = outarg.fh;
                        ff->open_flags = outarg.open_flags;
 
-               } else if (err != -ENOSYS || isdir) {
+               } else if (err != -ENOSYS) {
                        fuse_file_free(ff);
                        return err;
                } else {
-                       fc->no_open = 1;
+                       if (isdir)
+                               fc->no_opendir = 1;
+                       else
+                               fc->no_open = 1;
                }
        }
 
index 033e30af519f75449219020bfcbbbaa816cc31bd..0920c0c032a087e5a8a08c0e6566a4001174ccc5 100644 (file)
@@ -630,6 +630,9 @@ struct fuse_conn {
        /** Is open/release not implemented by fs? */
        unsigned no_open:1;
 
+       /** Is opendir/releasedir not implemented by fs? */
+       unsigned no_opendir:1;
+
        /** Is fsync not implemented by fs? */
        unsigned no_fsync:1;
 
index 2bbb7c59d6da3d69c0cce666cf36c288ae62b6e0..1b3f3b67d9f0270382b8b498b500b78d7797859c 100644 (file)
@@ -972,7 +972,8 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)
                FUSE_DO_READDIRPLUS | FUSE_READDIRPLUS_AUTO | FUSE_ASYNC_DIO |
                FUSE_WRITEBACK_CACHE | FUSE_NO_OPEN_SUPPORT |
                FUSE_PARALLEL_DIROPS | FUSE_HANDLE_KILLPRIV | FUSE_POSIX_ACL |
-               FUSE_ABORT_ERROR | FUSE_MAX_PAGES | FUSE_CACHE_SYMLINKS;
+               FUSE_ABORT_ERROR | FUSE_MAX_PAGES | FUSE_CACHE_SYMLINKS |
+               FUSE_NO_OPENDIR_SUPPORT;
        req->in.h.opcode = FUSE_INIT;
        req->in.numargs = 1;
        req->in.args[0].size = sizeof(*arg);
index b4967d48bfdaf90ec19d3767a61c91157855678f..2ac598614a8fc7a8db337168c32bf1a4c376519c 100644 (file)
  *  - add FOPEN_CACHE_DIR
  *  - add FUSE_MAX_PAGES, add max_pages to init_out
  *  - add FUSE_CACHE_SYMLINKS
+ *
+ *  7.29
+ *  - add FUSE_NO_OPENDIR_SUPPORT flag
  */
 
 #ifndef _LINUX_FUSE_H
 #define FUSE_KERNEL_VERSION 7
 
 /** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 28
+#define FUSE_KERNEL_MINOR_VERSION 29
 
 /** The node ID of the root inode */
 #define FUSE_ROOT_ID 1
@@ -259,6 +262,7 @@ struct fuse_file_lock {
  * FUSE_ABORT_ERROR: reading the device after abort returns ECONNABORTED
  * FUSE_MAX_PAGES: init_out.max_pages contains the max number of req pages
  * FUSE_CACHE_SYMLINKS: cache READLINK responses
+ * FUSE_NO_OPENDIR_SUPPORT: kernel supports zero-message opendir
  */
 #define FUSE_ASYNC_READ                (1 << 0)
 #define FUSE_POSIX_LOCKS       (1 << 1)
@@ -284,6 +288,7 @@ struct fuse_file_lock {
 #define FUSE_ABORT_ERROR       (1 << 21)
 #define FUSE_MAX_PAGES         (1 << 22)
 #define FUSE_CACHE_SYMLINKS    (1 << 23)
+#define FUSE_NO_OPENDIR_SUPPORT (1 << 24)
 
 /**
  * CUSE INIT request/reply flags
This page took 0.0714 seconds and 4 git commands to generate.