Skip to content

Commit b023958

Browse files
joannekoongbsbernd
authored andcommitted
fuse: enable dynamic configuration of fuse max pages limit (FUSE_MAX_MAX_PAGES)
Introduce the capability to dynamically configure the max pages limit (FUSE_MAX_MAX_PAGES) through a sysctl. This allows system administrators to dynamically set the maximum number of pages that can be used for servicing requests in fuse. Previously, this is gated by FUSE_MAX_MAX_PAGES which is statically set to 256 pages. One result of this is that the buffer size for a write request is limited to 1 MiB on a 4k-page system. The default value for this sysctl is the original limit (256 pages). $ sysctl -a | grep max_pages_limit fs.fuse.max_pages_limit = 256 $ sysctl -n fs.fuse.max_pages_limit 256 $ echo 1024 | sudo tee /proc/sys/fs/fuse/max_pages_limit 1024 $ sysctl -n fs.fuse.max_pages_limit 1024 $ echo 65536 | sudo tee /proc/sys/fs/fuse/max_pages_limit tee: /proc/sys/fs/fuse/max_pages_limit: Invalid argument $ echo 0 | sudo tee /proc/sys/fs/fuse/max_pages_limit tee: /proc/sys/fs/fuse/max_pages_limit: Invalid argument $ echo 65535 | sudo tee /proc/sys/fs/fuse/max_pages_limit 65535 $ sysctl -n fs.fuse.max_pages_limit 65535 Signed-off-by: Joanne Koong <[email protected]> Reviewed-by: Josef Bacik <[email protected]> Reviewed-by: Sweet Tea Dorminy <[email protected]> Signed-off-by: Miklos Szeredi <[email protected]> (cherry picked from commit 2b3933b)
1 parent 95a52d5 commit b023958

File tree

6 files changed

+74
-4
lines changed

6 files changed

+74
-4
lines changed

Documentation/admin-guide/sysctl/fs.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,3 +332,13 @@ Each "watch" costs roughly 90 bytes on a 32-bit kernel, and roughly 160 bytes
332332
on a 64-bit one.
333333
The current default value for ``max_user_watches`` is 4% of the
334334
available low memory, divided by the "watch" cost in bytes.
335+
336+
5. /proc/sys/fs/fuse - Configuration options for FUSE filesystems
337+
=====================================================================
338+
339+
This directory contains the following configuration options for FUSE
340+
filesystems:
341+
342+
``/proc/sys/fs/fuse/max_pages_limit`` is a read/write file for
343+
setting/getting the maximum number of pages that can be used for servicing
344+
requests in FUSE.

fs/fuse/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@ obj-$(CONFIG_VIRTIO_FS) += virtiofs.o
1010
fuse-y := dev.o dir.o file.o inode.o control.o xattr.o acl.o readdir.o ioctl.o
1111
fuse-$(CONFIG_FUSE_DAX) += dax.o
1212
fuse-$(CONFIG_FUSE_IO_URING) += dev_uring.o
13+
fuse-$(CONFIG_SYSCTL) += sysctl.o
1314

1415
virtiofs-y := virtio_fs.o

fs/fuse/fuse_i.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,6 @@
3535
/** Default max number of pages that can be used in a single read request */
3636
#define FUSE_DEFAULT_MAX_PAGES_PER_REQ 32
3737

38-
/** Maximum of max_pages received in init_out */
39-
#define FUSE_MAX_MAX_PAGES 256
40-
4138
/** Bias for fi->writectr, meaning new writepages must not be sent */
4239
#define FUSE_NOWRITE INT_MIN
4340

@@ -47,6 +44,9 @@
4744
/** Number of dentries for each connection in the control filesystem */
4845
#define FUSE_CTL_NUM_DENTRIES 5
4946

47+
/** Maximum of max_pages received in init_out */
48+
extern unsigned int fuse_max_pages_limit;
49+
5050
/** List of active connections */
5151
extern struct list_head fuse_conn_list;
5252

@@ -1392,4 +1392,12 @@ struct fuse_file *fuse_file_open(struct fuse_mount *fm, u64 nodeid,
13921392
void fuse_file_release(struct inode *inode, struct fuse_file *ff,
13931393
unsigned int open_flags, fl_owner_t id, bool isdir);
13941394

1395+
#ifdef CONFIG_SYSCTL
1396+
extern int fuse_sysctl_register(void);
1397+
extern void fuse_sysctl_unregister(void);
1398+
#else
1399+
#define fuse_sysctl_register() (0)
1400+
#define fuse_sysctl_unregister() do { } while (0)
1401+
#endif /* CONFIG_SYSCTL */
1402+
13951403
#endif /* _FS_FUSE_I_H */

fs/fuse/inode.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ DEFINE_MUTEX(fuse_mutex);
3636

3737
static int set_global_limit(const char *val, const struct kernel_param *kp);
3838

39+
unsigned int fuse_max_pages_limit = 256;
40+
3941
unsigned max_user_bgreq;
4042
module_param_call(max_user_bgreq, set_global_limit, param_get_uint,
4143
&max_user_bgreq, 0644);
@@ -973,7 +975,7 @@ void fuse_conn_init(struct fuse_conn *fc, struct fuse_mount *fm,
973975
fc->pid_ns = get_pid_ns(task_active_pid_ns(current));
974976
fc->user_ns = get_user_ns(user_ns);
975977
fc->max_pages = FUSE_DEFAULT_MAX_PAGES_PER_REQ;
976-
fc->max_pages_limit = FUSE_MAX_MAX_PAGES;
978+
fc->max_pages_limit = fuse_max_pages_limit;
977979

978980
INIT_LIST_HEAD(&fc->mounts);
979981
list_add(&fm->fc_entry, &fc->mounts);
@@ -2058,8 +2060,14 @@ static int __init fuse_fs_init(void)
20582060
if (err)
20592061
goto out3;
20602062

2063+
err = fuse_sysctl_register();
2064+
if (err)
2065+
goto out4;
2066+
20612067
return 0;
20622068

2069+
out4:
2070+
unregister_filesystem(&fuse_fs_type);
20632071
out3:
20642072
unregister_fuseblk();
20652073
out2:
@@ -2070,6 +2078,7 @@ static int __init fuse_fs_init(void)
20702078

20712079
static void fuse_fs_cleanup(void)
20722080
{
2081+
fuse_sysctl_unregister();
20732082
unregister_filesystem(&fuse_fs_type);
20742083
unregister_fuseblk();
20752084

fs/fuse/ioctl.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include <linux/compat.h>
1010
#include <linux/fileattr.h>
1111

12+
#define FUSE_VERITY_ENABLE_ARG_MAX_PAGES 256
13+
1214
static ssize_t fuse_send_ioctl(struct fuse_mount *fm, struct fuse_args *args,
1315
struct fuse_ioctl_out *outarg)
1416
{

fs/fuse/sysctl.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* linux/fs/fuse/fuse_sysctl.c
4+
*
5+
* Sysctl interface to fuse parameters
6+
*/
7+
#include <linux/sysctl.h>
8+
9+
#include "fuse_i.h"
10+
11+
static struct ctl_table_header *fuse_table_header;
12+
13+
/* Bound by fuse_init_out max_pages, which is a u16 */
14+
static unsigned int sysctl_fuse_max_pages_limit = 65535;
15+
16+
static struct ctl_table fuse_sysctl_table[] = {
17+
{
18+
.procname = "max_pages_limit",
19+
.data = &fuse_max_pages_limit,
20+
.maxlen = sizeof(fuse_max_pages_limit),
21+
.mode = 0644,
22+
.proc_handler = proc_douintvec_minmax,
23+
.extra1 = SYSCTL_ONE,
24+
.extra2 = &sysctl_fuse_max_pages_limit,
25+
},
26+
};
27+
28+
int fuse_sysctl_register(void)
29+
{
30+
fuse_table_header = register_sysctl("fs/fuse", fuse_sysctl_table);
31+
if (!fuse_table_header)
32+
return -ENOMEM;
33+
return 0;
34+
}
35+
36+
void fuse_sysctl_unregister(void)
37+
{
38+
unregister_sysctl_table(fuse_table_header);
39+
fuse_table_header = NULL;
40+
}

0 commit comments

Comments
 (0)