configure.in | 24 +++++++++++++- doc/fontconfig-user.sgml | 20 +++++++++++- src/fccache.c | 77 +++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 116 insertions(+), 5 deletions(-) New commits: commit 7d65f9f514e33305bdeafd0d34140da46259e57f Author: Akira TAGOH <akira at tagoh.org> Date: Wed Apr 11 19:52:35 2012 +0900 Bug 39278 - make usage of mmap optional Stop using mmap() if the cache file is stored on NFS. also added FONTCONFIG_USE_MMAP environment variable to enforce the use of or not the use of mmap(2) regardless of what the filesystem the cache files are stored on. diff --git a/configure.in b/configure.in index a176ce5..b77c52a 100644 --- a/configure.in +++ b/configure.in @@ -123,7 +123,7 @@ dnl ========================================================================= # Checks for header files. AC_HEADER_DIRENT AC_HEADER_STDC -AC_CHECK_HEADERS([fcntl.h regex.h stdlib.h string.h unistd.h]) +AC_CHECK_HEADERS([fcntl.h regex.h stdlib.h string.h unistd.h sys/vfs.h sys/statfs.h sys/param.h sys/mount.h]) # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST @@ -133,9 +133,29 @@ AC_TYPE_PID_T # Checks for library functions. AC_FUNC_VPRINTF AC_FUNC_MMAP -AC_CHECK_FUNCS([geteuid getuid link memmove memset mkstemp strchr strrchr strtol getopt getopt_long sysconf ftruncate chsize rand random lrand48 random_r rand_r regcomp regerror regexec regfree posix_fadvise]) +AC_CHECK_FUNCS([geteuid getuid link memmove memset mkstemp strchr strrchr strtol getopt getopt_long sysconf ftruncate chsize rand random lrand48 random_r rand_r regcomp regerror regexec regfree posix_fadvise fstatvfs fstatfs]) # +if test "x$ac_cv_func_fstatvfs" = "xyes"; then + AC_CHECK_MEMBERS([struct statvfs.f_basetype, struct statvfs.f_fstypename],,, + [#include <sys/statvfs.h>]) +fi +if test "x$ac_cv_func_fstatfs" = "xyes"; then + AC_CHECK_MEMBERS([struct statfs.f_flags, struct statfs.f_fstypename],,, [ +#ifdef HAVE_SYS_VFS_H +#include <sys/vfs.h> +#endif +#ifdef HAVE_SYS_STATFS_H +#include <sys/statfs.h> +#endif +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif +#ifdef HAVE_SYS_MOUNT_H +#include <sys/mount.h> +#endif]) +fi +# # regex # if test "x$ac_cv_func_regcomp" = "xyes" -a "x$ac_cv_func_regerror" = "xyes" -a "x$ac_cv_func_regexec" = "xyes" -a "x$ac_cv_func_regfree"; then diff --git a/doc/fontconfig-user.sgml b/doc/fontconfig-user.sgml index 14fdc79..86f2b32 100644 --- a/doc/fontconfig-user.sgml +++ b/doc/fontconfig-user.sgml @@ -224,7 +224,7 @@ values as the font name is read. </para> </refsect2> </refsect1> -<refsect1><title>Debugging Applications</title> +<refsect1 id="debug"><title>Debugging Applications</title> <para> To help diagnose font and applications problems, fontconfig is built with a large amount of internal debugging left enabled. It is controlled by means @@ -692,6 +692,24 @@ is the conventional repository of font information that isn''t found in the per-directory caches. This file is automatically maintained by fontconfig. </para> </refsect1> +<refsect1><title>Environment variables</title> + <para> +<emphasis>FONTCONFIG_FILE</emphasis> +is used to override the default configuration file. + </para> + <para> +<emphasis>FONTCONFIG_PATH</emphasis> +is used to override the default configuration directory. + </para> + <para> +<emphasis>FC_DEBUG</emphasis> +is used to output the detailed debugging messages. see <link linkend="debug">Debugging Applications</link> section for more details. + </para> + <para> +<emphasis>FONTCONFIG_USE_MMAP</emphasis> +is used to control the use of mmap(2) for the cache files if available. this take a boolean value. fontconfig will checks if the cache files are stored on the filesystem that is safe to use mmap(2). explicitly setting this environment variable will causes skipping this check and enforce to use or not use mmap(2) anyway. + </para> +</refsect1> <refsect1><title>See Also</title> <para> fc-cat(1), fc-cache(1), fc-list(1), fc-match(1), fc-query(1) diff --git a/src/fccache.c b/src/fccache.c index fbe2d5c..882dd3e 100644 --- a/src/fccache.c +++ b/src/fccache.c @@ -37,6 +37,21 @@ # include <unistd.h> # include <sys/mman.h> #endif +#ifdef HAVE_SYS_VFS_H +#include <sys/vfs.h> +#endif +#ifdef HAVE_SYS_STATFS_H +#include <sys/statfs.h> +#endif +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif +#ifdef HAVE_SYS_MOUNT_H +#include <sys/mount.h> +#endif +#ifdef HAVE_MNTENT_H +#include <mntent.h> +#endif #ifndef O_BINARY #define O_BINARY 0 @@ -144,6 +159,64 @@ FcStat (const FcChar8 *file, struct stat *statb) #endif +static FcBool +FcCacheIsMmapSafe (int fd) +{ + FcBool retval = FcTrue; + static FcBool is_initialized = FcFalse; + static FcBool is_env_available = FcFalse; + static FcBool use_mmap = FcFalse; + + if (!is_initialized) + { + const char *env; + + env = getenv ("FONTCONFIG_USE_MMAP"); + if (env) + { + if (FcNameBool ((const FcChar8 *)env, &use_mmap)) + is_env_available = FcTrue; + } + is_initialized = FcTrue; + } + if (is_env_available) + return use_mmap; +#if defined(HAVE_FSTATVFS) && (defined(HAVE_STRUCT_STATVFS_F_BASETYPE) || defined(HAVE_STRUCT_STATVFS_F_FSTYPENAME)) + struct statvfs buf; + + if (fstatvfs (fd, &buf) == 0) + { + const char *p; +#if defined(HAVE_STRUCT_STATVFS_F_BASETYPE) + p = buf.f_basetype; +#elif defined(HAVE_STRUCT_STATVFS_F_FSTYPENAME) + p = buf.f_fstypename; +#endif + + if (strcmp (p, "nfs") == 0) + retval = FcFalse; + } +#elif defined(HAVE_FSTATFS) && (defined(HAVE_STRUCT_STATFS_F_FLAGS) || defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) || defined(__linux__)) + struct statfs buf; + + if (fstatfs (fd, &buf) == 0) + { +# if defined(HAVE_STRUCT_STATFS_F_FLAGS) && defined(MNT_LOCAL) + if (!(buf.f_flags & MNT_LOCAL)) +# elif defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) + if (strcmp (buf.f_fstypename, "nfs") == 0) +# elif defined(__linux__) + if (buf.f_type == 0x6969) /* nfs */ +# else +# error "BUG: No way to figure out with fstatfs()" +# endif + retval = FcFalse; + } +#endif + + return retval; +} + static const char bin2hex[] = { ''0'', ''1'', ''2'', ''3'', ''4'', ''5'', ''6'', ''7'', ''8'', ''9'', ''a'', ''b'', @@ -602,10 +675,10 @@ FcDirCacheMapFd (int fd, struct stat *fd_stat, struct stat *dir_stat) } /* - * Lage cache files are mmap''ed, smaller cache files are read. This + * Large cache files are mmap''ed, smaller cache files are read. This * balances the system cost of mmap against per-process memory usage. */ - if (fd_stat->st_size >= FC_CACHE_MIN_MMAP) + if (FcCacheIsMmapSafe (fd) && fd_stat->st_size >= FC_CACHE_MIN_MMAP) { #if defined(HAVE_MMAP) || defined(__CYGWIN__) cache = mmap (0, fd_stat->st_size, PROT_READ, MAP_SHARED, fd, 0);