Skip to content

Commit d9a9ea9

Browse files
chadaustinMiklos Szeredi
authored andcommitted
fuse: support clients that don't implement 'opendir'
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>
1 parent 2f7b6f5 commit d9a9ea9

File tree

4 files changed

+18
-6
lines changed

4 files changed

+18
-6
lines changed

fs/fuse/file.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ static void fuse_file_put(struct fuse_file *ff, bool sync, bool isdir)
9090
if (refcount_dec_and_test(&ff->count)) {
9191
struct fuse_req *req = ff->reserved_req;
9292

93-
if (ff->fc->no_open && !isdir) {
93+
if (isdir ? ff->fc->no_opendir : ff->fc->no_open) {
9494
/*
9595
* Drop the release request when client does not
9696
* implement 'open'
@@ -125,7 +125,7 @@ int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
125125

126126
ff->fh = 0;
127127
ff->open_flags = FOPEN_KEEP_CACHE; /* Default for no-open */
128-
if (!fc->no_open || isdir) {
128+
if (isdir ? !fc->no_opendir : !fc->no_open) {
129129
struct fuse_open_out outarg;
130130
int err;
131131

@@ -134,11 +134,14 @@ int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
134134
ff->fh = outarg.fh;
135135
ff->open_flags = outarg.open_flags;
136136

137-
} else if (err != -ENOSYS || isdir) {
137+
} else if (err != -ENOSYS) {
138138
fuse_file_free(ff);
139139
return err;
140140
} else {
141-
fc->no_open = 1;
141+
if (isdir)
142+
fc->no_opendir = 1;
143+
else
144+
fc->no_open = 1;
142145
}
143146
}
144147

fs/fuse/fuse_i.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,9 @@ struct fuse_conn {
630630
/** Is open/release not implemented by fs? */
631631
unsigned no_open:1;
632632

633+
/** Is opendir/releasedir not implemented by fs? */
634+
unsigned no_opendir:1;
635+
633636
/** Is fsync not implemented by fs? */
634637
unsigned no_fsync:1;
635638

fs/fuse/inode.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -972,7 +972,8 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)
972972
FUSE_DO_READDIRPLUS | FUSE_READDIRPLUS_AUTO | FUSE_ASYNC_DIO |
973973
FUSE_WRITEBACK_CACHE | FUSE_NO_OPEN_SUPPORT |
974974
FUSE_PARALLEL_DIROPS | FUSE_HANDLE_KILLPRIV | FUSE_POSIX_ACL |
975-
FUSE_ABORT_ERROR | FUSE_MAX_PAGES | FUSE_CACHE_SYMLINKS;
975+
FUSE_ABORT_ERROR | FUSE_MAX_PAGES | FUSE_CACHE_SYMLINKS |
976+
FUSE_NO_OPENDIR_SUPPORT;
976977
req->in.h.opcode = FUSE_INIT;
977978
req->in.numargs = 1;
978979
req->in.args[0].size = sizeof(*arg);

include/uapi/linux/fuse.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@
122122
* - add FOPEN_CACHE_DIR
123123
* - add FUSE_MAX_PAGES, add max_pages to init_out
124124
* - add FUSE_CACHE_SYMLINKS
125+
*
126+
* 7.29
127+
* - add FUSE_NO_OPENDIR_SUPPORT flag
125128
*/
126129

127130
#ifndef _LINUX_FUSE_H
@@ -157,7 +160,7 @@
157160
#define FUSE_KERNEL_VERSION 7
158161

159162
/** Minor version number of this interface */
160-
#define FUSE_KERNEL_MINOR_VERSION 28
163+
#define FUSE_KERNEL_MINOR_VERSION 29
161164

162165
/** The node ID of the root inode */
163166
#define FUSE_ROOT_ID 1
@@ -259,6 +262,7 @@ struct fuse_file_lock {
259262
* FUSE_ABORT_ERROR: reading the device after abort returns ECONNABORTED
260263
* FUSE_MAX_PAGES: init_out.max_pages contains the max number of req pages
261264
* FUSE_CACHE_SYMLINKS: cache READLINK responses
265+
* FUSE_NO_OPENDIR_SUPPORT: kernel supports zero-message opendir
262266
*/
263267
#define FUSE_ASYNC_READ (1 << 0)
264268
#define FUSE_POSIX_LOCKS (1 << 1)
@@ -284,6 +288,7 @@ struct fuse_file_lock {
284288
#define FUSE_ABORT_ERROR (1 << 21)
285289
#define FUSE_MAX_PAGES (1 << 22)
286290
#define FUSE_CACHE_SYMLINKS (1 << 23)
291+
#define FUSE_NO_OPENDIR_SUPPORT (1 << 24)
287292

288293
/**
289294
* CUSE INIT request/reply flags

0 commit comments

Comments
 (0)