Commit 53db2893 authored by Miklos Szeredi's avatar Miklos Szeredi

fuse: extend init flags

FUSE_INIT flags are close to running out, so add another 32bits worth of
space.

Add FUSE_INIT_EXT flag to the old flags field in fuse_init_in.  If this
flag is set, then fuse_init_in is extended by 48bytes, in which a flags_hi
field is allocated to contain the high 32bits of the flags.

A flags_hi field is also added to fuse_init_out, allocated out of the
remaining unused fields.

Known userspace implementations of the fuse protocol have been checked to
accept the extended FUSE_INIT request, but this might cause problems with
other implementations.  If that happens to be the case, the protocol
negotiation will have to be extended with an extra initialization request
roundtrip.
Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
parent 47344172
...@@ -1109,72 +1109,74 @@ static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args, ...@@ -1109,72 +1109,74 @@ static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args,
process_init_limits(fc, arg); process_init_limits(fc, arg);
if (arg->minor >= 6) { if (arg->minor >= 6) {
u64 flags = arg->flags | (u64) arg->flags2 << 32;
ra_pages = arg->max_readahead / PAGE_SIZE; ra_pages = arg->max_readahead / PAGE_SIZE;
if (arg->flags & FUSE_ASYNC_READ) if (flags & FUSE_ASYNC_READ)
fc->async_read = 1; fc->async_read = 1;
if (!(arg->flags & FUSE_POSIX_LOCKS)) if (!(flags & FUSE_POSIX_LOCKS))
fc->no_lock = 1; fc->no_lock = 1;
if (arg->minor >= 17) { if (arg->minor >= 17) {
if (!(arg->flags & FUSE_FLOCK_LOCKS)) if (!(flags & FUSE_FLOCK_LOCKS))
fc->no_flock = 1; fc->no_flock = 1;
} else { } else {
if (!(arg->flags & FUSE_POSIX_LOCKS)) if (!(flags & FUSE_POSIX_LOCKS))
fc->no_flock = 1; fc->no_flock = 1;
} }
if (arg->flags & FUSE_ATOMIC_O_TRUNC) if (flags & FUSE_ATOMIC_O_TRUNC)
fc->atomic_o_trunc = 1; fc->atomic_o_trunc = 1;
if (arg->minor >= 9) { if (arg->minor >= 9) {
/* LOOKUP has dependency on proto version */ /* LOOKUP has dependency on proto version */
if (arg->flags & FUSE_EXPORT_SUPPORT) if (flags & FUSE_EXPORT_SUPPORT)
fc->export_support = 1; fc->export_support = 1;
} }
if (arg->flags & FUSE_BIG_WRITES) if (flags & FUSE_BIG_WRITES)
fc->big_writes = 1; fc->big_writes = 1;
if (arg->flags & FUSE_DONT_MASK) if (flags & FUSE_DONT_MASK)
fc->dont_mask = 1; fc->dont_mask = 1;
if (arg->flags & FUSE_AUTO_INVAL_DATA) if (flags & FUSE_AUTO_INVAL_DATA)
fc->auto_inval_data = 1; fc->auto_inval_data = 1;
else if (arg->flags & FUSE_EXPLICIT_INVAL_DATA) else if (flags & FUSE_EXPLICIT_INVAL_DATA)
fc->explicit_inval_data = 1; fc->explicit_inval_data = 1;
if (arg->flags & FUSE_DO_READDIRPLUS) { if (flags & FUSE_DO_READDIRPLUS) {
fc->do_readdirplus = 1; fc->do_readdirplus = 1;
if (arg->flags & FUSE_READDIRPLUS_AUTO) if (flags & FUSE_READDIRPLUS_AUTO)
fc->readdirplus_auto = 1; fc->readdirplus_auto = 1;
} }
if (arg->flags & FUSE_ASYNC_DIO) if (flags & FUSE_ASYNC_DIO)
fc->async_dio = 1; fc->async_dio = 1;
if (arg->flags & FUSE_WRITEBACK_CACHE) if (flags & FUSE_WRITEBACK_CACHE)
fc->writeback_cache = 1; fc->writeback_cache = 1;
if (arg->flags & FUSE_PARALLEL_DIROPS) if (flags & FUSE_PARALLEL_DIROPS)
fc->parallel_dirops = 1; fc->parallel_dirops = 1;
if (arg->flags & FUSE_HANDLE_KILLPRIV) if (flags & FUSE_HANDLE_KILLPRIV)
fc->handle_killpriv = 1; fc->handle_killpriv = 1;
if (arg->time_gran && arg->time_gran <= 1000000000) if (arg->time_gran && arg->time_gran <= 1000000000)
fm->sb->s_time_gran = arg->time_gran; fm->sb->s_time_gran = arg->time_gran;
if ((arg->flags & FUSE_POSIX_ACL)) { if ((flags & FUSE_POSIX_ACL)) {
fc->default_permissions = 1; fc->default_permissions = 1;
fc->posix_acl = 1; fc->posix_acl = 1;
fm->sb->s_xattr = fuse_acl_xattr_handlers; fm->sb->s_xattr = fuse_acl_xattr_handlers;
} }
if (arg->flags & FUSE_CACHE_SYMLINKS) if (flags & FUSE_CACHE_SYMLINKS)
fc->cache_symlinks = 1; fc->cache_symlinks = 1;
if (arg->flags & FUSE_ABORT_ERROR) if (flags & FUSE_ABORT_ERROR)
fc->abort_err = 1; fc->abort_err = 1;
if (arg->flags & FUSE_MAX_PAGES) { if (flags & FUSE_MAX_PAGES) {
fc->max_pages = fc->max_pages =
min_t(unsigned int, fc->max_pages_limit, min_t(unsigned int, fc->max_pages_limit,
max_t(unsigned int, arg->max_pages, 1)); max_t(unsigned int, arg->max_pages, 1));
} }
if (IS_ENABLED(CONFIG_FUSE_DAX) && if (IS_ENABLED(CONFIG_FUSE_DAX) &&
arg->flags & FUSE_MAP_ALIGNMENT && flags & FUSE_MAP_ALIGNMENT &&
!fuse_dax_check_alignment(fc, arg->map_alignment)) { !fuse_dax_check_alignment(fc, arg->map_alignment)) {
ok = false; ok = false;
} }
if (arg->flags & FUSE_HANDLE_KILLPRIV_V2) { if (flags & FUSE_HANDLE_KILLPRIV_V2) {
fc->handle_killpriv_v2 = 1; fc->handle_killpriv_v2 = 1;
fm->sb->s_flags |= SB_NOSEC; fm->sb->s_flags |= SB_NOSEC;
} }
if (arg->flags & FUSE_SETXATTR_EXT) if (flags & FUSE_SETXATTR_EXT)
fc->setxattr_ext = 1; fc->setxattr_ext = 1;
} else { } else {
ra_pages = fc->max_read / PAGE_SIZE; ra_pages = fc->max_read / PAGE_SIZE;
...@@ -1203,13 +1205,14 @@ static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args, ...@@ -1203,13 +1205,14 @@ static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args,
void fuse_send_init(struct fuse_mount *fm) void fuse_send_init(struct fuse_mount *fm)
{ {
struct fuse_init_args *ia; struct fuse_init_args *ia;
u64 flags;
ia = kzalloc(sizeof(*ia), GFP_KERNEL | __GFP_NOFAIL); ia = kzalloc(sizeof(*ia), GFP_KERNEL | __GFP_NOFAIL);
ia->in.major = FUSE_KERNEL_VERSION; ia->in.major = FUSE_KERNEL_VERSION;
ia->in.minor = FUSE_KERNEL_MINOR_VERSION; ia->in.minor = FUSE_KERNEL_MINOR_VERSION;
ia->in.max_readahead = fm->sb->s_bdi->ra_pages * PAGE_SIZE; ia->in.max_readahead = fm->sb->s_bdi->ra_pages * PAGE_SIZE;
ia->in.flags |= flags =
FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC | FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC |
FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK | FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK |
FUSE_SPLICE_WRITE | FUSE_SPLICE_MOVE | FUSE_SPLICE_READ | FUSE_SPLICE_WRITE | FUSE_SPLICE_MOVE | FUSE_SPLICE_READ |
...@@ -1219,13 +1222,16 @@ void fuse_send_init(struct fuse_mount *fm) ...@@ -1219,13 +1222,16 @@ void fuse_send_init(struct fuse_mount *fm)
FUSE_PARALLEL_DIROPS | FUSE_HANDLE_KILLPRIV | FUSE_POSIX_ACL | 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 | FUSE_EXPLICIT_INVAL_DATA | FUSE_NO_OPENDIR_SUPPORT | FUSE_EXPLICIT_INVAL_DATA |
FUSE_HANDLE_KILLPRIV_V2 | FUSE_SETXATTR_EXT; FUSE_HANDLE_KILLPRIV_V2 | FUSE_SETXATTR_EXT | FUSE_INIT_EXT;
#ifdef CONFIG_FUSE_DAX #ifdef CONFIG_FUSE_DAX
if (fm->fc->dax) if (fm->fc->dax)
ia->in.flags |= FUSE_MAP_ALIGNMENT; flags |= FUSE_MAP_ALIGNMENT;
#endif #endif
if (fm->fc->auto_submounts) if (fm->fc->auto_submounts)
ia->in.flags |= FUSE_SUBMOUNTS; flags |= FUSE_SUBMOUNTS;
ia->in.flags = flags;
ia->in.flags2 = flags >> 32;
ia->args.opcode = FUSE_INIT; ia->args.opcode = FUSE_INIT;
ia->args.in_numargs = 1; ia->args.in_numargs = 1;
......
...@@ -187,6 +187,10 @@ ...@@ -187,6 +187,10 @@
* *
* 7.35 * 7.35
* - add FOPEN_NOFLUSH * - add FOPEN_NOFLUSH
*
* 7.36
* - extend fuse_init_in with reserved fields, add FUSE_INIT_EXT init flag
* - add flags2 to fuse_init_in and fuse_init_out
*/ */
#ifndef _LINUX_FUSE_H #ifndef _LINUX_FUSE_H
...@@ -222,7 +226,7 @@ ...@@ -222,7 +226,7 @@
#define FUSE_KERNEL_VERSION 7 #define FUSE_KERNEL_VERSION 7
/** Minor version number of this interface */ /** Minor version number of this interface */
#define FUSE_KERNEL_MINOR_VERSION 35 #define FUSE_KERNEL_MINOR_VERSION 36
/** The node ID of the root inode */ /** The node ID of the root inode */
#define FUSE_ROOT_ID 1 #define FUSE_ROOT_ID 1
...@@ -341,6 +345,8 @@ struct fuse_file_lock { ...@@ -341,6 +345,8 @@ struct fuse_file_lock {
* write/truncate sgid is killed only if file has group * write/truncate sgid is killed only if file has group
* execute permission. (Same as Linux VFS behavior). * execute permission. (Same as Linux VFS behavior).
* FUSE_SETXATTR_EXT: Server supports extended struct fuse_setxattr_in * FUSE_SETXATTR_EXT: Server supports extended struct fuse_setxattr_in
* FUSE_INIT_EXT: extended fuse_init_in request
* FUSE_INIT_RESERVED: reserved, do not use
*/ */
#define FUSE_ASYNC_READ (1 << 0) #define FUSE_ASYNC_READ (1 << 0)
#define FUSE_POSIX_LOCKS (1 << 1) #define FUSE_POSIX_LOCKS (1 << 1)
...@@ -372,6 +378,9 @@ struct fuse_file_lock { ...@@ -372,6 +378,9 @@ struct fuse_file_lock {
#define FUSE_SUBMOUNTS (1 << 27) #define FUSE_SUBMOUNTS (1 << 27)
#define FUSE_HANDLE_KILLPRIV_V2 (1 << 28) #define FUSE_HANDLE_KILLPRIV_V2 (1 << 28)
#define FUSE_SETXATTR_EXT (1 << 29) #define FUSE_SETXATTR_EXT (1 << 29)
#define FUSE_INIT_EXT (1 << 30)
#define FUSE_INIT_RESERVED (1 << 31)
/* bits 32..63 get shifted down 32 bits into the flags2 field */
/** /**
* CUSE INIT request/reply flags * CUSE INIT request/reply flags
...@@ -741,6 +750,8 @@ struct fuse_init_in { ...@@ -741,6 +750,8 @@ struct fuse_init_in {
uint32_t minor; uint32_t minor;
uint32_t max_readahead; uint32_t max_readahead;
uint32_t flags; uint32_t flags;
uint32_t flags2;
uint32_t unused[11];
}; };
#define FUSE_COMPAT_INIT_OUT_SIZE 8 #define FUSE_COMPAT_INIT_OUT_SIZE 8
...@@ -757,7 +768,8 @@ struct fuse_init_out { ...@@ -757,7 +768,8 @@ struct fuse_init_out {
uint32_t time_gran; uint32_t time_gran;
uint16_t max_pages; uint16_t max_pages;
uint16_t map_alignment; uint16_t map_alignment;
uint32_t unused[8]; uint32_t flags2;
uint32_t unused[7];
}; };
#define CUSE_INIT_INFO_MAX 4096 #define CUSE_INIT_INFO_MAX 4096
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment