Skip to content

Commit 9b6ef4b

Browse files
fuse: make fuse max-write, max-read params tunable
Since kernel 4.20, the FUSE driver introduced the max-pages feature. To enhance write performance, this patch exports two mount options fuse-max-write and fuse-max-read to let users specify the maximum write/read bytes for FUSE connection. By ajudging fuse-max-writef/fuse-max-read, the max-pages parameter for fuse connection will be changed accordingly. It helps to avoid IO splits when IO size is larger than 128K. Updates: #4500 Signed-off-by: chenjinhao <[email protected]>
1 parent a9f3973 commit 9b6ef4b

File tree

7 files changed

+99
-6
lines changed

7 files changed

+99
-6
lines changed

contrib/fuse-include/fuse_kernel.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,8 @@ struct fuse_file_lock {
285285
#define FUSE_MAX_PAGES (1 << 22)
286286
#define FUSE_CACHE_SYMLINKS (1 << 23)
287287

288+
#define FUSE_MAX_MAX_PAGES 256
289+
288290
/**
289291
* CUSE INIT request/reply flags
290292
*

glusterfsd/src/glusterfsd.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,10 @@ static struct argp_option gf_options[] = {
271271
{"fuse-handle-copy_file_range", ARGP_FUSE_HANDLE_COPY_FILE_RANGE, "BOOL",
272272
OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
273273
"enable the handler of the FUSE_COPY_FILE_RANGE message"},
274+
{"fuse-max-write", ARGP_FUSE_MAX_WRITE_KEY, "INTEGER", OPTION_ARG_OPTIONAL,
275+
"set fuse max-write bytes"},
276+
{"fuse-max-read", ARGP_FUSE_MAX_READ_KEY, "INTEGER", OPTION_ARG_OPTIONAL,
277+
"set fuse max-read bytes"},
274278
{0, 0, 0, 0, "Miscellaneous Options:"},
275279
{
276280
0,
@@ -566,6 +570,16 @@ set_fuse_mount_options(glusterfs_ctx_t *ctx, dict_t *options)
566570
break;
567571
}
568572

573+
if (cmd_args->fuse_max_write) {
574+
DICT_SET_VAL(dict_set_uint32, options, "fuse-max-write",
575+
cmd_args->fuse_max_write, glusterfsd_msg_3);
576+
}
577+
578+
if (cmd_args->fuse_max_read) {
579+
DICT_SET_VAL(dict_set_uint32, options, "fuse-max-read",
580+
cmd_args->fuse_max_read, glusterfsd_msg_3);
581+
}
582+
569583
if (cmd_args->fs_display_name) {
570584
DICT_SET_VAL(dict_set_dynstr, options, "fs-display-name",
571585
cmd_args->fs_display_name, glusterfsd_msg_3);
@@ -1463,6 +1477,33 @@ parse_opts(int key, char *arg, struct argp_state *state)
14631477
"unknown fuse handle copy_file_range setting \"%s\"",
14641478
arg);
14651479
break;
1480+
case ARGP_FUSE_MAX_WRITE_KEY:
1481+
if (gf_string2uint32(arg, &cmd_args->fuse_max_write)) {
1482+
argp_failure(state, -1, 0, "unknown fuse max-write option %s",
1483+
arg);
1484+
} else if ((cmd_args->fuse_max_write < 4096) ||
1485+
(cmd_args->fuse_max_write > 1048576)) {
1486+
argp_failure(state, -1, 0,
1487+
"Invalid fuse max-write bytes %s. "
1488+
"Valid range: [\"4096, 1048576\"]",
1489+
arg);
1490+
}
1491+
1492+
break;
1493+
case ARGP_FUSE_MAX_READ_KEY:
1494+
if (gf_string2uint32(arg, &cmd_args->fuse_max_read)) {
1495+
argp_failure(state, -1, 0, "unknown fuse max-read option %s",
1496+
arg);
1497+
} else if ((cmd_args->fuse_max_read < 4096) ||
1498+
(cmd_args->fuse_max_read > 1048576)) {
1499+
argp_failure(state, -1, 0,
1500+
"Invalid fuse max-read bytes %s. "
1501+
"Valid range: [\"4096, 1048576\"]",
1502+
arg);
1503+
}
1504+
1505+
break;
1506+
14661507
}
14671508
return 0;
14681509
}

glusterfsd/src/glusterfsd.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ enum argp_option_keys {
118118
ARGP_FUSE_INODE_TABLESIZE_KEY = 198,
119119
ARGP_FUSE_SETLK_HANDLE_INTERRUPT_KEY = 199,
120120
ARGP_FUSE_HANDLE_COPY_FILE_RANGE = 200,
121+
ARGP_FUSE_MAX_WRITE_KEY = 201,
122+
ARGP_FUSE_MAX_READ_KEY = 202,
121123
};
122124

123125
int

libglusterfs/src/glusterfs/glusterfs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,8 @@ struct _cmd_args {
592592
int fuse_auto_inval;
593593

594594
uint32_t fuse_dev_eperm_ratelimit_ns;
595+
uint32_t fuse_max_write;
596+
uint32_t fuse_max_read;
595597

596598
bool global_threading;
597599
bool brick_mux;

xlators/mount/fuse/src/fuse-bridge.c

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5154,6 +5154,15 @@ fuse_init(xlator_t *this, fuse_in_header_t *finh, void *msg,
51545154
fino.max_readahead = 1 << 17;
51555155
fino.max_write = 1 << 17;
51565156
fino.flags = FUSE_ASYNC_READ | FUSE_POSIX_LOCKS;
5157+
#if FUSE_KERNEL_MINOR_VERSION >= 28
5158+
if (fini->minor >= 28) {
5159+
fino.max_readahead = priv->fuse_max_read;
5160+
fino.max_write = priv->fuse_max_write;
5161+
fino.max_pages = max(priv->fuse_max_write, priv->fuse_max_read) / sysconf(_SC_PAGESIZE);
5162+
if (fino.max_pages == FUSE_MAX_MAX_PAGES)
5163+
fino.flags |= FUSE_MAX_PAGES;
5164+
}
5165+
#endif
51575166
#if FUSE_KERNEL_MINOR_VERSION >= 17
51585167
if (fini->minor >= 17)
51595168
fino.flags |= FUSE_FLOCK_LOCKS;
@@ -6090,14 +6099,12 @@ fuse_thread_proc(void *data)
60906099
struct pollfd pfd[2] = {{
60916100
0,
60926101
}};
6093-
uint32_t psize;
60946102

60956103
this = data;
60966104
priv = this->private;
60976105

60986106
THIS = this;
60996107

6100-
psize = ((struct iobuf_pool *)this->ctx->iobuf_pool)->default_page_size;
61016108
priv->msg0_len_p = &msg0_size;
61026109

61036110
for (;;) {
@@ -6153,7 +6160,8 @@ fuse_thread_proc(void *data)
61536160
size from 'fuse', which is as of today 128KB. If we bring in
61546161
support for higher block sizes support, then we should be
61556162
changing this one too */
6156-
iobuf = iobuf_get(this->ctx->iobuf_pool);
6163+
iobuf = iobuf_get2(this->ctx->iobuf_pool,
6164+
max(priv->fuse_max_write, priv->fuse_max_read));
61576165

61586166
/* Add extra 512 byte to the first iov so that it can
61596167
* accommodate "ordinary" non-write requests. It's not
@@ -6177,7 +6185,7 @@ fuse_thread_proc(void *data)
61776185
iov_in[1].iov_base = iobuf->ptr;
61786186

61796187
iov_in[0].iov_len = msg0_size;
6180-
iov_in[1].iov_len = psize;
6188+
iov_in[1].iov_len = max(priv->fuse_max_write, priv->fuse_max_read);
61816189

61826190
res = sys_readv(priv->fd, iov_in, 2);
61836191

@@ -6910,6 +6918,12 @@ init(xlator_t *this_xl)
69106918
GF_OPTION_INIT("fuse-dev-eperm-ratelimit-ns",
69116919
priv->fuse_dev_eperm_ratelimit_ns, uint32, cleanup_exit);
69126920

6921+
GF_OPTION_INIT("fuse-max-write", priv->fuse_max_write, uint32,
6922+
cleanup_exit);
6923+
6924+
GF_OPTION_INIT("fuse-max-read", priv->fuse_max_read, uint32,
6925+
cleanup_exit);
6926+
69136927
/* user has set only background-qlen, not congestion-threshold,
69146928
use the fuse kernel driver formula to set congestion. ie, 75% */
69156929
if (dict_get(this_xl->options, "background-qlen") &&
@@ -6954,11 +6968,11 @@ init(xlator_t *this_xl)
69546968
goto cleanup_exit;
69556969
}
69566970

6957-
gf_asprintf(&mnt_args, "%s%s%s%sallow_other,max_read=131072",
6971+
gf_asprintf(&mnt_args, "%s%s%s%sallow_other,max_read=%lu",
69586972
priv->acl ? "" : "default_permissions,",
69596973
priv->read_only ? "ro," : "",
69606974
priv->fuse_mountopts ? priv->fuse_mountopts : "",
6961-
priv->fuse_mountopts ? "," : "");
6975+
priv->fuse_mountopts ? "," : "", priv->fuse_max_read);
69626976
if (!mnt_args)
69636977
goto cleanup_exit;
69646978

@@ -7198,6 +7212,22 @@ struct volume_options options[] = {
71987212
.max = 64,
71997213
.description = "Sets fuse reader thread count.",
72007214
},
7215+
{
7216+
.key = {"fuse-max-write"},
7217+
.type = GF_OPTION_TYPE_INT,
7218+
.default_value = "131072",
7219+
.min = 4096,
7220+
.max = 1048576,
7221+
.description = "Sets fuse max-write bytes.",
7222+
},
7223+
{
7224+
.key = {"fuse-max-read"},
7225+
.type = GF_OPTION_TYPE_INT,
7226+
.default_value = "131072",
7227+
.min = 4096,
7228+
.max = 1048576,
7229+
.description = "Sets fuse max-read bytes.",
7230+
},
72017231
{
72027232
.key = {"kernel-writeback-cache"},
72037233
.type = GF_OPTION_TYPE_BOOL,

xlators/mount/fuse/src/fuse-bridge.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@ struct fuse_private {
176176
uint32_t inode_table_size;
177177
uint32_t invalidate_limit;
178178
uint32_t fuse_dev_eperm_ratelimit_ns;
179+
uint32_t fuse_max_write;
180+
uint32_t fuse_max_read;
179181

180182
/* counters for fusdev errnos */
181183
uint8_t fusedev_errno_cnt[FUSEDEV_EMAXPLUS];

xlators/mount/fuse/utils/mount.glusterfs.in

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,14 @@ start_glusterfs ()
332332
cmd_line=$(echo "$cmd_line --fuse-handle-copy_file_range=$fuse_handle_copy_file_range");
333333
fi
334334

335+
if [ -n "$fuse_max_write" ]; then
336+
cmd_line=$(echo "$cmd_line --fuse-max-write=$fuse_max_write");
337+
fi
338+
339+
if [ -n "$fuse_max_read" ]; then
340+
cmd_line=$(echo "$cmd_line --fuse-max-read=$fuse_max_read");
341+
fi
342+
335343
if [ -n "$process_name" ]; then
336344
cmd_line=$(echo "$cmd_line --process-name fuse.$process_name");
337345
else
@@ -641,6 +649,12 @@ with_options()
641649
"fuse-dev-eperm-ratelimit-ns")
642650
fuse_dev_eperm_ratelimit_ns=$value
643651
;;
652+
"fuse-max-write")
653+
fuse_max_write=$value
654+
;;
655+
"fuse-max-read")
656+
fuse_max_read=$value
657+
;;
644658
"context"|"fscontext"|"defcontext"|"rootcontext")
645659
# standard SElinux mount options to pass to the kernel
646660
[ -z "$fuse_mountopts" ] || fuse_mountopts="$fuse_mountopts,"

0 commit comments

Comments
 (0)