This is the mail archive of the mailing list for the binutils project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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.



2012-06-05  Cary Coutant  <>

	* Add check for <linux/falloc.h>.
	* configure: Regenerate.
	* Regenerate.

	* options.h (class General_options): Add --mmap-output-file and
	--posix-fallocate options.
	* 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 <>
Date:   Tue Jun 5 17:00:35 2012 -0700

    Add --mmap-output-file and --posix-fallocate options.

diff --git a/gold/ b/gold/
index a2c4875..dc096f7 100644
--- a/gold/
+++ b/gold/

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

+  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/ b/gold/
index 2236916..69ca8f2 100644
--- a/gold/
+++ b/gold/
@@ -34,6 +34,10 @@
 #include <sys/mman.h>

+#include <linux/falloc.h>
 #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

-// 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)
+  if (parameters->options().posix_fallocate())
+    return ::posix_fallocate(o, offset, len);
+#endif // !defined(HAVE_POSIX_FALLOCATE)
+  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)
-  if (this->map_no_anonymous(true))
+  if (parameters->options().mmap_output_file()
+      && this->map_no_anonymous(true))

   // The mmap call might fail because of file system issues: the file

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]