Skip to content

Commit 53db289

Browse files
author
Miklos Szeredi
committed
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: Miklos Szeredi <[email protected]>
1 parent 4734417 commit 53db289

File tree

2 files changed

+47
-29
lines changed

2 files changed

+47
-29
lines changed

fs/fuse/inode.c

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,72 +1109,74 @@ static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args,
11091109
process_init_limits(fc, arg);
11101110

11111111
if (arg->minor >= 6) {
1112+
u64 flags = arg->flags | (u64) arg->flags2 << 32;
1113+
11121114
ra_pages = arg->max_readahead / PAGE_SIZE;
1113-
if (arg->flags & FUSE_ASYNC_READ)
1115+
if (flags & FUSE_ASYNC_READ)
11141116
fc->async_read = 1;
1115-
if (!(arg->flags & FUSE_POSIX_LOCKS))
1117+
if (!(flags & FUSE_POSIX_LOCKS))
11161118
fc->no_lock = 1;
11171119
if (arg->minor >= 17) {
1118-
if (!(arg->flags & FUSE_FLOCK_LOCKS))
1120+
if (!(flags & FUSE_FLOCK_LOCKS))
11191121
fc->no_flock = 1;
11201122
} else {
1121-
if (!(arg->flags & FUSE_POSIX_LOCKS))
1123+
if (!(flags & FUSE_POSIX_LOCKS))
11221124
fc->no_flock = 1;
11231125
}
1124-
if (arg->flags & FUSE_ATOMIC_O_TRUNC)
1126+
if (flags & FUSE_ATOMIC_O_TRUNC)
11251127
fc->atomic_o_trunc = 1;
11261128
if (arg->minor >= 9) {
11271129
/* LOOKUP has dependency on proto version */
1128-
if (arg->flags & FUSE_EXPORT_SUPPORT)
1130+
if (flags & FUSE_EXPORT_SUPPORT)
11291131
fc->export_support = 1;
11301132
}
1131-
if (arg->flags & FUSE_BIG_WRITES)
1133+
if (flags & FUSE_BIG_WRITES)
11321134
fc->big_writes = 1;
1133-
if (arg->flags & FUSE_DONT_MASK)
1135+
if (flags & FUSE_DONT_MASK)
11341136
fc->dont_mask = 1;
1135-
if (arg->flags & FUSE_AUTO_INVAL_DATA)
1137+
if (flags & FUSE_AUTO_INVAL_DATA)
11361138
fc->auto_inval_data = 1;
1137-
else if (arg->flags & FUSE_EXPLICIT_INVAL_DATA)
1139+
else if (flags & FUSE_EXPLICIT_INVAL_DATA)
11381140
fc->explicit_inval_data = 1;
1139-
if (arg->flags & FUSE_DO_READDIRPLUS) {
1141+
if (flags & FUSE_DO_READDIRPLUS) {
11401142
fc->do_readdirplus = 1;
1141-
if (arg->flags & FUSE_READDIRPLUS_AUTO)
1143+
if (flags & FUSE_READDIRPLUS_AUTO)
11421144
fc->readdirplus_auto = 1;
11431145
}
1144-
if (arg->flags & FUSE_ASYNC_DIO)
1146+
if (flags & FUSE_ASYNC_DIO)
11451147
fc->async_dio = 1;
1146-
if (arg->flags & FUSE_WRITEBACK_CACHE)
1148+
if (flags & FUSE_WRITEBACK_CACHE)
11471149
fc->writeback_cache = 1;
1148-
if (arg->flags & FUSE_PARALLEL_DIROPS)
1150+
if (flags & FUSE_PARALLEL_DIROPS)
11491151
fc->parallel_dirops = 1;
1150-
if (arg->flags & FUSE_HANDLE_KILLPRIV)
1152+
if (flags & FUSE_HANDLE_KILLPRIV)
11511153
fc->handle_killpriv = 1;
11521154
if (arg->time_gran && arg->time_gran <= 1000000000)
11531155
fm->sb->s_time_gran = arg->time_gran;
1154-
if ((arg->flags & FUSE_POSIX_ACL)) {
1156+
if ((flags & FUSE_POSIX_ACL)) {
11551157
fc->default_permissions = 1;
11561158
fc->posix_acl = 1;
11571159
fm->sb->s_xattr = fuse_acl_xattr_handlers;
11581160
}
1159-
if (arg->flags & FUSE_CACHE_SYMLINKS)
1161+
if (flags & FUSE_CACHE_SYMLINKS)
11601162
fc->cache_symlinks = 1;
1161-
if (arg->flags & FUSE_ABORT_ERROR)
1163+
if (flags & FUSE_ABORT_ERROR)
11621164
fc->abort_err = 1;
1163-
if (arg->flags & FUSE_MAX_PAGES) {
1165+
if (flags & FUSE_MAX_PAGES) {
11641166
fc->max_pages =
11651167
min_t(unsigned int, fc->max_pages_limit,
11661168
max_t(unsigned int, arg->max_pages, 1));
11671169
}
11681170
if (IS_ENABLED(CONFIG_FUSE_DAX) &&
1169-
arg->flags & FUSE_MAP_ALIGNMENT &&
1171+
flags & FUSE_MAP_ALIGNMENT &&
11701172
!fuse_dax_check_alignment(fc, arg->map_alignment)) {
11711173
ok = false;
11721174
}
1173-
if (arg->flags & FUSE_HANDLE_KILLPRIV_V2) {
1175+
if (flags & FUSE_HANDLE_KILLPRIV_V2) {
11741176
fc->handle_killpriv_v2 = 1;
11751177
fm->sb->s_flags |= SB_NOSEC;
11761178
}
1177-
if (arg->flags & FUSE_SETXATTR_EXT)
1179+
if (flags & FUSE_SETXATTR_EXT)
11781180
fc->setxattr_ext = 1;
11791181
} else {
11801182
ra_pages = fc->max_read / PAGE_SIZE;
@@ -1203,13 +1205,14 @@ static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args,
12031205
void fuse_send_init(struct fuse_mount *fm)
12041206
{
12051207
struct fuse_init_args *ia;
1208+
u64 flags;
12061209

12071210
ia = kzalloc(sizeof(*ia), GFP_KERNEL | __GFP_NOFAIL);
12081211

12091212
ia->in.major = FUSE_KERNEL_VERSION;
12101213
ia->in.minor = FUSE_KERNEL_MINOR_VERSION;
12111214
ia->in.max_readahead = fm->sb->s_bdi->ra_pages * PAGE_SIZE;
1212-
ia->in.flags |=
1215+
flags =
12131216
FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC |
12141217
FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK |
12151218
FUSE_SPLICE_WRITE | FUSE_SPLICE_MOVE | FUSE_SPLICE_READ |
@@ -1219,13 +1222,16 @@ void fuse_send_init(struct fuse_mount *fm)
12191222
FUSE_PARALLEL_DIROPS | FUSE_HANDLE_KILLPRIV | FUSE_POSIX_ACL |
12201223
FUSE_ABORT_ERROR | FUSE_MAX_PAGES | FUSE_CACHE_SYMLINKS |
12211224
FUSE_NO_OPENDIR_SUPPORT | FUSE_EXPLICIT_INVAL_DATA |
1222-
FUSE_HANDLE_KILLPRIV_V2 | FUSE_SETXATTR_EXT;
1225+
FUSE_HANDLE_KILLPRIV_V2 | FUSE_SETXATTR_EXT | FUSE_INIT_EXT;
12231226
#ifdef CONFIG_FUSE_DAX
12241227
if (fm->fc->dax)
1225-
ia->in.flags |= FUSE_MAP_ALIGNMENT;
1228+
flags |= FUSE_MAP_ALIGNMENT;
12261229
#endif
12271230
if (fm->fc->auto_submounts)
1228-
ia->in.flags |= FUSE_SUBMOUNTS;
1231+
flags |= FUSE_SUBMOUNTS;
1232+
1233+
ia->in.flags = flags;
1234+
ia->in.flags2 = flags >> 32;
12291235

12301236
ia->args.opcode = FUSE_INIT;
12311237
ia->args.in_numargs = 1;

include/uapi/linux/fuse.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,10 @@
187187
*
188188
* 7.35
189189
* - add FOPEN_NOFLUSH
190+
*
191+
* 7.36
192+
* - extend fuse_init_in with reserved fields, add FUSE_INIT_EXT init flag
193+
* - add flags2 to fuse_init_in and fuse_init_out
190194
*/
191195

192196
#ifndef _LINUX_FUSE_H
@@ -222,7 +226,7 @@
222226
#define FUSE_KERNEL_VERSION 7
223227

224228
/** Minor version number of this interface */
225-
#define FUSE_KERNEL_MINOR_VERSION 35
229+
#define FUSE_KERNEL_MINOR_VERSION 36
226230

227231
/** The node ID of the root inode */
228232
#define FUSE_ROOT_ID 1
@@ -341,6 +345,8 @@ struct fuse_file_lock {
341345
* write/truncate sgid is killed only if file has group
342346
* execute permission. (Same as Linux VFS behavior).
343347
* FUSE_SETXATTR_EXT: Server supports extended struct fuse_setxattr_in
348+
* FUSE_INIT_EXT: extended fuse_init_in request
349+
* FUSE_INIT_RESERVED: reserved, do not use
344350
*/
345351
#define FUSE_ASYNC_READ (1 << 0)
346352
#define FUSE_POSIX_LOCKS (1 << 1)
@@ -372,6 +378,9 @@ struct fuse_file_lock {
372378
#define FUSE_SUBMOUNTS (1 << 27)
373379
#define FUSE_HANDLE_KILLPRIV_V2 (1 << 28)
374380
#define FUSE_SETXATTR_EXT (1 << 29)
381+
#define FUSE_INIT_EXT (1 << 30)
382+
#define FUSE_INIT_RESERVED (1 << 31)
383+
/* bits 32..63 get shifted down 32 bits into the flags2 field */
375384

376385
/**
377386
* CUSE INIT request/reply flags
@@ -741,6 +750,8 @@ struct fuse_init_in {
741750
uint32_t minor;
742751
uint32_t max_readahead;
743752
uint32_t flags;
753+
uint32_t flags2;
754+
uint32_t unused[11];
744755
};
745756

746757
#define FUSE_COMPAT_INIT_OUT_SIZE 8
@@ -757,7 +768,8 @@ struct fuse_init_out {
757768
uint32_t time_gran;
758769
uint16_t max_pages;
759770
uint16_t map_alignment;
760-
uint32_t unused[8];
771+
uint32_t flags2;
772+
uint32_t unused[7];
761773
};
762774

763775
#define CUSE_INIT_INFO_MAX 4096

0 commit comments

Comments
 (0)