This is the mail archive of the binutils@sourceware.org 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 patch committed: If file mmap fails, try anonymous mmap


In some cases the file system does not support mmap of a file with
PROT_WRITE set.  Reportedly this happens on some FUSE file systems.  I
committed this gold patch from Elliott Hughes at Google to use an
anonymous mmap if the regular mmap fails.

Ian


2009-03-24  Elliott Hughes  <enh@google.com>

	* output.cc (Output_file::map_anonymous): Define.
	(Output_file::map): Use map_anonymous.  If the regular mmap fails,
	try an anonymous one.  Report the size if the mmap fails.
	* output.h (class Output_file): Declare map_anonymous.


Index: output.cc
===================================================================
RCS file: /cvs/src/src/gold/output.cc,v
retrieving revision 1.88
diff -u -p -r1.88 output.cc
--- output.cc	24 Mar 2009 00:31:28 -0000	1.88
+++ output.cc	24 Mar 2009 18:02:08 -0000
@@ -3380,6 +3380,17 @@ Output_file::resize(off_t file_size)
     }
 }
 
+// Map a block of memory which will later be written to the file.
+// Return a pointer to the memory.
+
+void*
+Output_file::map_anonymous()
+{
+  this->map_is_anonymous_ = true;
+  return ::mmap(NULL, this->file_size_, PROT_READ | PROT_WRITE,
+		MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+}
+
 // Map the file into memory.
 
 void
@@ -3396,11 +3407,7 @@ Output_file::map()
       || ::fstat(o, &statbuf) != 0
       || !S_ISREG(statbuf.st_mode)
       || this->is_temporary_)
-    {
-      this->map_is_anonymous_ = true;
-      base = ::mmap(NULL, this->file_size_, PROT_READ | PROT_WRITE,
-                    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-    }
+    base = this->map_anonymous();
   else
     {
       // Ensure that we have disk space available for the file.  If we
@@ -3418,9 +3425,19 @@ Output_file::map()
       this->map_is_anonymous_ = false;
       base = ::mmap(NULL, this->file_size_, PROT_READ | PROT_WRITE,
                     MAP_SHARED, o, 0);
+
+      // The mmap call might fail because of file system issues: the
+      // file system might not support mmap at all, or it might not
+      // support mmap with PROT_WRITE.  I'm not sure which errno
+      // values we will see in all cases, so if the mmap fails for any
+      // reason try for an anonymous map.
+      if (base == MAP_FAILED)
+	base = this->map_anonymous();
     }
   if (base == MAP_FAILED)
-    gold_fatal(_("%s: mmap: %s"), this->name_, strerror(errno));
+    gold_fatal(_("%s: mmap: failed to allocate %lu bytes for output file: %s"),
+	       this->name_, static_cast<unsigned long>(this->file_size_),
+	       strerror(errno));
   this->base_ = static_cast<unsigned char*>(base);
 }
 
Index: output.h
===================================================================
RCS file: /cvs/src/src/gold/output.h,v
retrieving revision 1.77
diff -u -p -r1.77 output.h
--- output.h	28 Feb 2009 00:12:26 -0000	1.77
+++ output.h	24 Mar 2009 18:02:08 -0000
@@ -3115,10 +3115,14 @@ class Output_file
   { }
 
  private:
-  // Map the file into memory and return a pointer to the map.
+  // Map the file into memory.
   void
   map();
 
+  // Allocate anonymous memory for the file.
+  void*
+  map_anonymous();
+
   // Unmap the file from memory (and flush to disk buffers).
   void
   unmap();

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