From: Darrick J. Wong <djwong@xxxxxxxxxx> fuse2fs is involved in the filesystem I/O path and can allocate memory while processing I/O requests. Therefore, we need to register that fact with the kernel so that memory allocations done by libext2fs don't start a round of filesystem memory reclaim, which could cause more writeout to get dumped on fuse2fs. Signed-off-by: "Darrick J. Wong" <djwong@xxxxxxxxxx> --- configure | 37 +++++++++++++++++++++++++++++++++++++ configure.ac | 19 +++++++++++++++++++ lib/config.h.in | 3 +++ misc/fuse2fs.c | 15 +++++++++++++++ 4 files changed, 74 insertions(+) diff --git a/configure b/configure index f9a7aa4e2e864c..dfc6bb4a5daa2e 100755 --- a/configure +++ b/configure @@ -14551,6 +14551,43 @@ then printf "%s\n" "#define FUSE_USE_VERSION $FUSE_USE_VERSION" >>confdefs.h fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for PR_SET_IO_FLUSHER" >&5 +printf %s "checking for PR_SET_IO_FLUSHER... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#define _GNU_SOURCE +#include <sys/prctl.h> + +int +main (void) +{ + +prctl(PR_SET_IO_FLUSHER, 0, 0, 0, 0); + + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + have_pr_set_io_flusher=yes + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +if test "$have_pr_set_io_flusher" = yes; then + +printf "%s\n" "#define HAVE_PR_SET_IO_FLUSHER 1" >>confdefs.h + +fi + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for optreset" >&5 printf %s "checking for optreset... " >&6; } if test ${ac_cv_have_optreset+y} diff --git a/configure.ac b/configure.ac index 1f67604036b528..7f28701534a905 100644 --- a/configure.ac +++ b/configure.ac @@ -1434,6 +1434,25 @@ then AC_DEFINE_UNQUOTED(FUSE_USE_VERSION, $FUSE_USE_VERSION, [Define to the version of FUSE to use]) fi + +dnl +dnl see if PR_SET_IO_FLUSHER exists +dnl +AC_MSG_CHECKING(for PR_SET_IO_FLUSHER) +AC_LINK_IFELSE( +[ AC_LANG_PROGRAM([[ +#define _GNU_SOURCE +#include <sys/prctl.h> + ]], [[ +prctl(PR_SET_IO_FLUSHER, 0, 0, 0, 0); + ]]) +], have_pr_set_io_flusher=yes + AC_MSG_RESULT(yes), + AC_MSG_RESULT(no)) +if test "$have_pr_set_io_flusher" = yes; then + AC_DEFINE(HAVE_PR_SET_IO_FLUSHER, 1, [Define to 1 if PR_SET_IO_FLUSHER is present]) +fi + dnl dnl See if optreset exists dnl diff --git a/lib/config.h.in b/lib/config.h.in index 819c4331379247..6cd9751baab9d1 100644 --- a/lib/config.h.in +++ b/lib/config.h.in @@ -70,6 +70,9 @@ /* Define to 1 if you have the BSD-style 'qsort_r' function. */ #undef HAVE_BSD_QSORT_R +/* Define to 1 if PR_SET_IO_FLUSHER is present */ +#undef HAVE_PR_SET_IO_FLUSHER + /* Define to 1 if you have the Mac OS X function CFLocaleCopyPreferredLanguages in the CoreFoundation framework. */ #undef HAVE_CFLOCALECOPYPREFERREDLANGUAGES diff --git a/misc/fuse2fs.c b/misc/fuse2fs.c index 51f703267462b4..cbe9afd4ba1290 100644 --- a/misc/fuse2fs.c +++ b/misc/fuse2fs.c @@ -17,6 +17,7 @@ # include <linux/fs.h> # include <linux/falloc.h> # include <linux/xattr.h> +# include <sys/prctl.h> #endif #include <sys/ioctl.h> #include <unistd.h> @@ -4792,6 +4793,20 @@ int main(int argc, char *argv[]) } } +#ifdef HAVE_PR_SET_IO_FLUSHER + /* + * Register as a filesystem I/O server process so that our memory + * allocations don't cause fs reclaim. + */ + ret = prctl(PR_SET_IO_FLUSHER, 1, 0, 0, 0); + if (ret < 0) { + err_printf(&fctx, "%s: %s.\n", + _("Could not register as IO flusher thread"), + strerror(errno)); + ret = 0; + } +#endif + /* Will we allow users to allocate every last block? */ if (getenv("FUSE2FS_ALLOC_ALL_BLOCKS")) { log_printf(&fctx, "%s\n",