This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[gold] RFC: Add options for controlling mmap and fallocate of output file
- From: Cary Coutant <ccoutant at google dot com>
- To: Ian Lance Taylor <iant at google dot com>, Binutils <binutils at sourceware dot org>
- Date: Tue, 5 Jun 2012 17:11:01 -0700
- Subject: [gold] RFC: Add options for controlling mmap and fallocate of output file
This patch adds --[no-]mmap-output-file and --[no-]posix-fallocate
options to gold, to enable experimentation with alternative ways of
writing the output file. On file systems that don't support the Linux
fallocate() system call, posix_fallocate() resorts to single-byte
writes to every block of the file, which is unacceptably slow for
large output files. The --no-posix-fallocate option will disable this,
and gold will instead try the fallocate() system call directly,
falling back to ftruncate() when that fails. The --no-mmap-output-file
option tells gold to use an anonymous block of memory to build the
output file and use fwrite at the end of the link to write it to disk.
In some preliminary experiments, this has actually shown to be faster
than writing directly to the memory mapped file.
Comments?
-cary
2012-06-05 Cary Coutant <ccoutant@google.com>
* configure.ac: Add check for <linux/falloc.h>.
* configure: Regenerate.
* config.in: Regenerate.
* options.h (class General_options): Add --mmap-output-file and
--posix-fallocate options.
* output.cc: Include linux/falloc.h.
(posix_fallocate): Remove; replace with...
(gold_fallocate): New function.
(Output_file::map_no_anonymous): Call gold_fallocate.
(Output_file::map): Check --mmap-output-file option.
commit 438f13c845cdf90ad8b84b3d1243b6a3ccce1ee7
Author: Cary Coutant <ccoutant@google.com>
Date: Tue Jun 5 17:00:35 2012 -0700
Add --mmap-output-file and --posix-fallocate options.
diff --git a/gold/configure.ac b/gold/configure.ac
index a2c4875..dc096f7 100644
--- a/gold/configure.ac
+++ b/gold/configure.ac
@@ -468,6 +468,7 @@ LFS_CFLAGS="-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
AC_SUBST(LFS_CFLAGS)
AC_CHECK_HEADERS(sys/mman.h)
+AC_CHECK_HEADERS(linux/falloc.h)
AC_CHECK_FUNCS(chsize mmap)
AC_REPLACE_FUNCS(pread ftruncate ffsll)
diff --git a/gold/options.h b/gold/options.h
index b244bd5..6463b80 100644
--- a/gold/options.h
+++ b/gold/options.h
@@ -889,6 +889,10 @@ class General_options
DEFINE_string(m, options::EXACTLY_ONE_DASH, 'm', "",
N_("Set GNU linker emulation; obsolete"), N_("EMULATION"));
+ DEFINE_bool(mmap_output_file, options::TWO_DASHES, '\0', true,
+ N_("Map the output file for writing (default)."),
+ N_("Do not map the output file for writing."));
+
DEFINE_bool(print_map, options::TWO_DASHES, 'M', false,
N_("Write map file on standard output"), NULL);
DEFINE_string(Map, options::ONE_DASH, '\0', NULL, N_("Write map file"),
@@ -939,6 +943,11 @@ class General_options
N_("Pass an option to the plugin"), N_("OPTION"));
#endif
+ DEFINE_bool(posix_fallocate, options::TWO_DASHES, '\0', true,
+ N_("Use posix_fallocate to reserve space in the output file"
+ " (default)."),
+ N_("Use fallocate or ftruncate to reserve space."));
+
DEFINE_bool(preread_archive_symbols, options::TWO_DASHES, '\0', false,
N_("Preread archive symbols when multi-threaded"), NULL);
diff --git a/gold/output.cc b/gold/output.cc
index 2236916..69ca8f2 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -34,6 +34,10 @@
#include <sys/mman.h>
#endif
+#ifdef HAVE_LINUX_FALLOC_H
+#include <linux/falloc.h>
+#endif
+
#include "libiberty.h"
#include "dwarf.h"
@@ -111,20 +115,6 @@ extern "C" void *gold_mremap(void *, size_t, size_t, int);
# define MREMAP_MAYMOVE 1
#endif
-#ifndef HAVE_POSIX_FALLOCATE
-// A dummy, non general, version of posix_fallocate. Here we just set
-// the file size and hope that there is enough disk space. FIXME: We
-// could allocate disk space by walking block by block and writing a
-// zero byte into each block.
-static int
-posix_fallocate(int o, off_t offset, off_t len)
-{
- if (ftruncate(o, offset + len) < 0)
- return errno;
- return 0;
-}
-#endif // !defined(HAVE_POSIX_FALLOCATE)
-
// Mingw does not have S_ISLNK.
#ifndef S_ISLNK
# define S_ISLNK(mode) 0
@@ -133,6 +123,27 @@ posix_fallocate(int o, off_t offset, off_t len)
namespace gold
{
+// A wrapper around posix_fallocate. If we don't have posix_fallocate,
+// or the --no-posix-fallocate option is set, we try the fallocate
+// system call directly. If that fails, we use ftruncate to set
+// the file size and hope that there is enough disk space.
+
+static int
+gold_fallocate(int o, off_t offset, off_t len)
+{
+#ifdef HAVE_POSIX_FALLOCATE
+ if (parameters->options().posix_fallocate())
+ return ::posix_fallocate(o, offset, len);
+#endif // !defined(HAVE_POSIX_FALLOCATE)
+#ifdef FALLOC_FL_KEEP_SIZE
+ if (::fallocate(o, FALLOC_FL_KEEP_SIZE, offset, len) == 0)
+ return 0;
+#endif // defined(FALLOC_FL_KEEP_SIZE)
+ if (ftruncate(o, offset + len) < 0)
+ return errno;
+ return 0;
+}
+
// Output_data variables.
bool Output_data::allocated_sizes_are_fixed;
@@ -5014,7 +5025,7 @@ Output_file::map_no_anonymous(bool writable)
// but that would be a more significant performance hit.
if (writable)
{
- int err = ::posix_fallocate(o, 0, this->file_size_);
+ int err = gold_fallocate(o, 0, this->file_size_);
if (err != 0)
gold_fatal(_("%s: %s"), this->name_, strerror(err));
}
@@ -5041,7 +5052,8 @@ Output_file::map_no_anonymous(bool writable)
void
Output_file::map()
{
- if (this->map_no_anonymous(true))
+ if (parameters->options().mmap_output_file()
+ && this->map_no_anonymous(true))
return;
// The mmap call might fail because of file system issues: the file