From: Darrick J. Wong <djwong@xxxxxxxxxx> Create a CLI option so that we can adjust the disk cache size, and set it to 32MB by default. Signed-off-by: "Darrick J. Wong" <djwong@xxxxxxxxxx> --- misc/Makefile.in | 7 ++++--- misc/fuse2fs.1.in | 6 ++++++ misc/fuse2fs.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/misc/Makefile.in b/misc/Makefile.in index 2d5be8c627c5e1..ce4a24d5151c81 100644 --- a/misc/Makefile.in +++ b/misc/Makefile.in @@ -422,11 +422,11 @@ filefrag.profiled: $(FILEFRAG_OBJS) $(PROFILED_FILEFRAG_OBJS) fuse2fs: $(FUSE2FS_OBJS) $(DEPLIBS) $(DEPLIBBLKID) $(DEPLIBUUID) \ - $(LIBEXT2FS) + $(LIBEXT2FS) $(DEPLIBS_E2P) $(E) " LD $@" $(Q) $(CC) $(ALL_LDFLAGS) -o fuse2fs $(FUSE2FS_OBJS) $(LIBS) \ $(LIBFUSE) $(LIBBLKID) $(LIBUUID) $(LIBEXT2FS) $(LIBINTL) \ - $(CLOCK_GETTIME_LIB) $(SYSLIBS) + $(CLOCK_GETTIME_LIB) $(SYSLIBS) $(LIBS_E2P) journal.o: $(srcdir)/../debugfs/journal.c $(E) " CC $<" @@ -875,7 +875,8 @@ fuse2fs.o: $(srcdir)/fuse2fs.c $(top_builddir)/lib/config.h \ $(top_srcdir)/lib/ext2fs/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \ $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/hashmap.h \ - $(top_srcdir)/lib/ext2fs/bitops.h $(top_srcdir)/version.h + $(top_srcdir)/lib/ext2fs/bitops.h $(top_srcdir)/version.h \ + $(top_srcdir)/lib/e2p/e2p.h e2fuzz.o: $(srcdir)/e2fuzz.c $(top_builddir)/lib/config.h \ $(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \ $(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/lib/ext2fs/ext2fs.h \ diff --git a/misc/fuse2fs.1.in b/misc/fuse2fs.1.in index 43678a1c1971c5..d485ccbdc02f34 100644 --- a/misc/fuse2fs.1.in +++ b/misc/fuse2fs.1.in @@ -65,6 +65,12 @@ .SS "fuse2fs options:" .TP .BR -o direct Use O_DIRECT to access the block device. +.TP +.BR -o cache_size +Set the disk cache size to this quantity. +The quantity may contain the suffixes k, m, or g. +By default, the size is 32MB. +The size may not be larger than 2GB. .SS "FUSE options:" .TP \fB-d -o\fR debug diff --git a/misc/fuse2fs.c b/misc/fuse2fs.c index 6aac84a2b4340b..da5a9ae252ae96 100644 --- a/misc/fuse2fs.c +++ b/misc/fuse2fs.c @@ -53,6 +53,7 @@ #include "../version.h" #include "uuid/uuid.h" +#include "e2p/e2p.h" #ifdef ENABLE_NLS #include <libintl.h> @@ -161,6 +162,7 @@ struct fuse2fs { int directio; unsigned long offset; unsigned int next_generation; + unsigned long long cache_size; }; #define FUSE2FS_CHECK_MAGIC(fs, ptr, num) do {if ((ptr)->magic != (num)) \ @@ -3760,6 +3762,7 @@ enum { FUSE2FS_VERSION, FUSE2FS_HELP, FUSE2FS_HELPFULL, + FUSE2FS_CACHE_SIZE, }; #define FUSE2FS_OPT(t, p, v) { t, offsetof(struct fuse2fs, p), v } @@ -3782,6 +3785,7 @@ static struct fuse_opt fuse2fs_opts[] = { FUSE_OPT_KEY("acl", FUSE2FS_IGNORED), FUSE_OPT_KEY("user_xattr", FUSE2FS_IGNORED), FUSE_OPT_KEY("noblock_validity", FUSE2FS_IGNORED), + FUSE_OPT_KEY("cache_size=%s", FUSE2FS_CACHE_SIZE), FUSE_OPT_KEY("-V", FUSE2FS_VERSION), FUSE_OPT_KEY("--version", FUSE2FS_VERSION), @@ -3804,6 +3808,16 @@ static int fuse2fs_opt_proc(void *data, const char *arg, return 0; } return 1; + case FUSE2FS_CACHE_SIZE: + ff->cache_size = parse_num_blocks2(arg + 12, -1); + if (ff->cache_size < 1 || ff->cache_size > INT32_MAX) { + fprintf(stderr, "%s: %s\n", arg, + _("cache size must be between 1 block and 2GB.")); + return -1; + } + + /* do not pass through to libfuse */ + return 0; case FUSE2FS_IGNORED: return 0; case FUSE2FS_HELP: @@ -3827,6 +3841,7 @@ static int fuse2fs_opt_proc(void *data, const char *arg, " -o kernel run this as if it were the kernel, which sets:\n" " allow_others,default_permissions,suid,dev\n" " -o directio use O_DIRECT to read and write the disk\n" + " -o cache_size=N[KMG] use a disk cache of this size\n" "\n", outargs->argv[0]); if (key == FUSE2FS_HELPFULL) { @@ -3865,6 +3880,25 @@ static const char *get_subtype(const char *argv0) return "ext4"; } +/* Figure out a reasonable default size for the disk cache */ +static unsigned long long default_cache_size(void) +{ + long pages = 0, pagesize = 0; + +#ifdef _SC_PHYS_PAGES + pages = sysconf(_SC_PHYS_PAGES); +#endif +#ifdef _SC_PAGESIZE + pagesize = sysconf(_SC_PAGESIZE); +#endif + long long max_cache = (long long)pagesize * pages / 20; + unsigned long long ret = 32ULL << 20; /* 32 MB */ + + if (max_cache > 0 && ret > max_cache) + return max_cache; + return ret; +} + int main(int argc, char *argv[]) { struct fuse_args args = FUSE_ARGS_INIT(argc, argv); @@ -3944,6 +3978,23 @@ int main(int argc, char *argv[]) fctx.fs = global_fs; global_fs->priv_data = &fctx; + if (!fctx.cache_size) + fctx.cache_size = default_cache_size(); + if (fctx.cache_size) { + char buf[55]; + + snprintf(buf, sizeof(buf), "cache_blocks=%llu", + fctx.cache_size / global_fs->blocksize); + err = io_channel_set_options(global_fs->io, buf); + if (err) { + err_printf(&fctx, "%s %lluk: %s\n", + _("cannot set disk cache size to"), + fctx.cache_size >> 10, + error_message(err)); + goto out; + } + } + ret = 3; if (ext2fs_has_feature_quota(global_fs->super)) {