mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-18 22:14:16 +00:00
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 <joannelkoong@gmail.com> Reviewed-by: Josef Bacik <josef@toxicpanda.com> Reviewed-by: Sweet Tea Dorminy <sweettea-kernel@dorminy.me> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
parent
d34a5575e6
commit
2b3933b1e0
6 changed files with 75 additions and 5 deletions
|
|
@ -332,3 +332,13 @@ Each "watch" costs roughly 90 bytes on a 32-bit kernel, and roughly 160 bytes
|
|||
on a 64-bit one.
|
||||
The current default value for ``max_user_watches`` is 4% of the
|
||||
available low memory, divided by the "watch" cost in bytes.
|
||||
|
||||
5. /proc/sys/fs/fuse - Configuration options for FUSE filesystems
|
||||
=====================================================================
|
||||
|
||||
This directory contains the following configuration options for FUSE
|
||||
filesystems:
|
||||
|
||||
``/proc/sys/fs/fuse/max_pages_limit`` is a read/write file for
|
||||
setting/getting the maximum number of pages that can be used for servicing
|
||||
requests in FUSE.
|
||||
|
|
|
|||
|
|
@ -14,5 +14,6 @@ fuse-y := dev.o dir.o file.o inode.o control.o xattr.o acl.o readdir.o ioctl.o
|
|||
fuse-y += iomode.o
|
||||
fuse-$(CONFIG_FUSE_DAX) += dax.o
|
||||
fuse-$(CONFIG_FUSE_PASSTHROUGH) += passthrough.o
|
||||
fuse-$(CONFIG_SYSCTL) += sysctl.o
|
||||
|
||||
virtiofs-y := virtio_fs.o
|
||||
|
|
|
|||
|
|
@ -35,9 +35,6 @@
|
|||
/** Default max number of pages that can be used in a single read request */
|
||||
#define FUSE_DEFAULT_MAX_PAGES_PER_REQ 32
|
||||
|
||||
/** Maximum of max_pages received in init_out */
|
||||
#define FUSE_MAX_MAX_PAGES 256
|
||||
|
||||
/** Bias for fi->writectr, meaning new writepages must not be sent */
|
||||
#define FUSE_NOWRITE INT_MIN
|
||||
|
||||
|
|
@ -47,6 +44,9 @@
|
|||
/** Number of dentries for each connection in the control filesystem */
|
||||
#define FUSE_CTL_NUM_DENTRIES 5
|
||||
|
||||
/** Maximum of max_pages received in init_out */
|
||||
extern unsigned int fuse_max_pages_limit;
|
||||
|
||||
/** List of active connections */
|
||||
extern struct list_head fuse_conn_list;
|
||||
|
||||
|
|
@ -1480,4 +1480,12 @@ ssize_t fuse_passthrough_splice_write(struct pipe_inode_info *pipe,
|
|||
size_t len, unsigned int flags);
|
||||
ssize_t fuse_passthrough_mmap(struct file *file, struct vm_area_struct *vma);
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
extern int fuse_sysctl_register(void);
|
||||
extern void fuse_sysctl_unregister(void);
|
||||
#else
|
||||
#define fuse_sysctl_register() (0)
|
||||
#define fuse_sysctl_unregister() do { } while (0)
|
||||
#endif /* CONFIG_SYSCTL */
|
||||
|
||||
#endif /* _FS_FUSE_I_H */
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ DEFINE_MUTEX(fuse_mutex);
|
|||
|
||||
static int set_global_limit(const char *val, const struct kernel_param *kp);
|
||||
|
||||
unsigned int fuse_max_pages_limit = 256;
|
||||
|
||||
unsigned max_user_bgreq;
|
||||
module_param_call(max_user_bgreq, set_global_limit, param_get_uint,
|
||||
&max_user_bgreq, 0644);
|
||||
|
|
@ -944,7 +946,7 @@ void fuse_conn_init(struct fuse_conn *fc, struct fuse_mount *fm,
|
|||
fc->pid_ns = get_pid_ns(task_active_pid_ns(current));
|
||||
fc->user_ns = get_user_ns(user_ns);
|
||||
fc->max_pages = FUSE_DEFAULT_MAX_PAGES_PER_REQ;
|
||||
fc->max_pages_limit = FUSE_MAX_MAX_PAGES;
|
||||
fc->max_pages_limit = fuse_max_pages_limit;
|
||||
|
||||
if (IS_ENABLED(CONFIG_FUSE_PASSTHROUGH))
|
||||
fuse_backing_files_init(fc);
|
||||
|
|
@ -2063,8 +2065,14 @@ static int __init fuse_fs_init(void)
|
|||
if (err)
|
||||
goto out3;
|
||||
|
||||
err = fuse_sysctl_register();
|
||||
if (err)
|
||||
goto out4;
|
||||
|
||||
return 0;
|
||||
|
||||
out4:
|
||||
unregister_filesystem(&fuse_fs_type);
|
||||
out3:
|
||||
unregister_fuseblk();
|
||||
out2:
|
||||
|
|
@ -2075,6 +2083,7 @@ static int __init fuse_fs_init(void)
|
|||
|
||||
static void fuse_fs_cleanup(void)
|
||||
{
|
||||
fuse_sysctl_unregister();
|
||||
unregister_filesystem(&fuse_fs_type);
|
||||
unregister_fuseblk();
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@
|
|||
#include <linux/fileattr.h>
|
||||
#include <linux/fsverity.h>
|
||||
|
||||
#define FUSE_VERITY_ENABLE_ARG_MAX_PAGES 256
|
||||
|
||||
static ssize_t fuse_send_ioctl(struct fuse_mount *fm, struct fuse_args *args,
|
||||
struct fuse_ioctl_out *outarg)
|
||||
{
|
||||
|
|
@ -140,7 +142,7 @@ static int fuse_setup_enable_verity(unsigned long arg, struct iovec *iov,
|
|||
{
|
||||
struct fsverity_enable_arg enable;
|
||||
struct fsverity_enable_arg __user *uarg = (void __user *)arg;
|
||||
const __u32 max_buffer_len = FUSE_MAX_MAX_PAGES * PAGE_SIZE;
|
||||
const __u32 max_buffer_len = FUSE_VERITY_ENABLE_ARG_MAX_PAGES * PAGE_SIZE;
|
||||
|
||||
if (copy_from_user(&enable, uarg, sizeof(enable)))
|
||||
return -EFAULT;
|
||||
|
|
|
|||
40
fs/fuse/sysctl.c
Normal file
40
fs/fuse/sysctl.c
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* linux/fs/fuse/fuse_sysctl.c
|
||||
*
|
||||
* Sysctl interface to fuse parameters
|
||||
*/
|
||||
#include <linux/sysctl.h>
|
||||
|
||||
#include "fuse_i.h"
|
||||
|
||||
static struct ctl_table_header *fuse_table_header;
|
||||
|
||||
/* Bound by fuse_init_out max_pages, which is a u16 */
|
||||
static unsigned int sysctl_fuse_max_pages_limit = 65535;
|
||||
|
||||
static struct ctl_table fuse_sysctl_table[] = {
|
||||
{
|
||||
.procname = "max_pages_limit",
|
||||
.data = &fuse_max_pages_limit,
|
||||
.maxlen = sizeof(fuse_max_pages_limit),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_douintvec_minmax,
|
||||
.extra1 = SYSCTL_ONE,
|
||||
.extra2 = &sysctl_fuse_max_pages_limit,
|
||||
},
|
||||
};
|
||||
|
||||
int fuse_sysctl_register(void)
|
||||
{
|
||||
fuse_table_header = register_sysctl("fs/fuse", fuse_sysctl_table);
|
||||
if (!fuse_table_header)
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fuse_sysctl_unregister(void)
|
||||
{
|
||||
unregister_sysctl_table(fuse_table_header);
|
||||
fuse_table_header = NULL;
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue