Index: base/files/memory_mapped_file_posix.cc |
diff --git a/base/files/memory_mapped_file_posix.cc b/base/files/memory_mapped_file_posix.cc |
index f0b391e2d0b887782ec1a5f0f59260ba971124cd..b1efe887a05a77d23965d6789147797213574f69 100644 |
--- a/base/files/memory_mapped_file_posix.cc |
+++ b/base/files/memory_mapped_file_posix.cc |
@@ -84,9 +84,12 @@ bool MemoryMappedFile::MapFileRegionToMemory( |
case READ_WRITE_EXTEND: |
flags |= PROT_READ | PROT_WRITE; |
+ const int64_t new_file_len = region.offset + region.size; |
+ |
// POSIX won't auto-extend the file when it is written so it must first |
// be explicitly extended to the maximum size. Zeros will fill the new |
- // space. |
+ // space. It is assumed that the existing file is fully realized as |
+ // otherwise the entire file would have to be read and possibly written. |
const int64_t original_file_len = file_.GetLength(); |
if (original_file_len < 0) { |
DPLOG(ERROR) << "fstat " << file_.GetPlatformFile(); |
@@ -95,8 +98,7 @@ bool MemoryMappedFile::MapFileRegionToMemory( |
// Increase the actual length of the file, if necessary. This can fail if |
// the disk is full and the OS doesn't support sparse files. |
- if (!file_.SetLength( |
- std::max(original_file_len, region.offset + region.size))) { |
+ if (!file_.SetLength(std::max(original_file_len, new_file_len))) { |
DPLOG(ERROR) << "ftruncate " << file_.GetPlatformFile(); |
return false; |
} |
@@ -124,21 +126,19 @@ bool MemoryMappedFile::MapFileRegionToMemory( |
} |
#endif |
- // Manually realize the entire file by writing bytes to it at intervals. |
+ // Manually realize the extended file by writing bytes to it at intervals. |
if (do_manual_extension) { |
- int64_t block_size = 1024; // Start with something safe. |
+ int64_t block_size = 512; // Start with something safe. |
struct stat statbuf; |
- if (fstat(file_.GetPlatformFile(), &statbuf) == 0) |
+ if (fstat(file_.GetPlatformFile(), &statbuf) == 0 && |
+ statbuf.st_blksize > 0) { |
block_size = statbuf.st_blksize; |
-#if defined(OS_FUCHSIA) |
- // TODO(fuchsia): Fuchsia stat() currently returns 0 for st_blksize, |
- // which hangs the loop below. Remove this after the next SDK update. |
- // https://crbug.com/706592 and MG-815. |
- if (block_size == 0) |
- block_size = 512; |
-#endif // defined(OS_FUCHSIA) |
- const off_t map_end = map_start + static_cast<off_t>(map_size); |
- for (off_t i = map_start; i < map_end; i += block_size) { |
+ } |
+ |
+ // Write starting at the next block boundary after the old file length. |
+ const int64_t extension_start = |
+ (original_file_len + block_size - 1) & ~(block_size - 1); |
+ for (int64_t i = extension_start; i < new_file_len; i += block_size) { |
char existing_byte; |
if (pread(file_.GetPlatformFile(), &existing_byte, 1, i) != 1) |
return false; // Can't read? Not viable. |