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.
This commit is contained in:
Akira TAGOH 2012-04-11 19:52:35 +09:00
parent f30a5d7637
commit 7d65f9f514
3 changed files with 116 additions and 5 deletions

View File

@ -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,8 +133,28 @@ 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
#

View File

@ -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)

View File

@ -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);