Skip to content

Commit

Permalink
fuse: support clients that don't implement 'opendir'
Browse files Browse the repository at this point in the history
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 <chadaustin@fb.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
  • Loading branch information
chadaustin authored and Miklos Szeredi committed Feb 13, 2019
1 parent 2f7b6f5 commit d9a9ea9
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 6 deletions.
11 changes: 7 additions & 4 deletions fs/fuse/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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;

Expand All @@ -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;
}
}

Expand Down
3 changes: 3 additions & 0 deletions fs/fuse/fuse_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
3 changes: 2 additions & 1 deletion fs/fuse/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
7 changes: 6 additions & 1 deletion include/uapi/linux/fuse.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@
* - 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
Expand Down Expand Up @@ -157,7 +160,7 @@
#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
Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand Down

0 comments on commit d9a9ea9

Please sign in to comment.