Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Side by Side Diff: base/files/memory_mapped_file_posix.cc

Issue 2939073002: Don't realize existing parts of an extended memory-mapped file. (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/files/memory_mapped_file.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/files/memory_mapped_file.h" 5 #include "base/files/memory_mapped_file.h"
6 6
7 #include <fcntl.h> 7 #include <fcntl.h>
8 #include <stddef.h> 8 #include <stddef.h>
9 #include <stdint.h> 9 #include <stdint.h>
10 #include <sys/mman.h> 10 #include <sys/mman.h>
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 flags |= PROT_READ; 77 flags |= PROT_READ;
78 break; 78 break;
79 79
80 case READ_WRITE: 80 case READ_WRITE:
81 flags |= PROT_READ | PROT_WRITE; 81 flags |= PROT_READ | PROT_WRITE;
82 break; 82 break;
83 83
84 case READ_WRITE_EXTEND: 84 case READ_WRITE_EXTEND:
85 flags |= PROT_READ | PROT_WRITE; 85 flags |= PROT_READ | PROT_WRITE;
86 86
87 const int64_t new_file_len = region.offset + region.size;
88
87 // POSIX won't auto-extend the file when it is written so it must first 89 // POSIX won't auto-extend the file when it is written so it must first
88 // be explicitly extended to the maximum size. Zeros will fill the new 90 // be explicitly extended to the maximum size. Zeros will fill the new
89 // space. 91 // space. It is assumed that the existing file is fully realized as
92 // otherwise the entire file would have to be read and possibly written.
90 const int64_t original_file_len = file_.GetLength(); 93 const int64_t original_file_len = file_.GetLength();
91 if (original_file_len < 0) { 94 if (original_file_len < 0) {
92 DPLOG(ERROR) << "fstat " << file_.GetPlatformFile(); 95 DPLOG(ERROR) << "fstat " << file_.GetPlatformFile();
93 return false; 96 return false;
94 } 97 }
95 98
96 // Increase the actual length of the file, if necessary. This can fail if 99 // Increase the actual length of the file, if necessary. This can fail if
97 // the disk is full and the OS doesn't support sparse files. 100 // the disk is full and the OS doesn't support sparse files.
98 if (!file_.SetLength( 101 if (!file_.SetLength(std::max(original_file_len, new_file_len))) {
99 std::max(original_file_len, region.offset + region.size))) {
100 DPLOG(ERROR) << "ftruncate " << file_.GetPlatformFile(); 102 DPLOG(ERROR) << "ftruncate " << file_.GetPlatformFile();
101 return false; 103 return false;
102 } 104 }
103 105
104 // Realize the extent of the file so that it can't fail (and crash) later 106 // Realize the extent of the file so that it can't fail (and crash) later
105 // when trying to write to a memory page that can't be created. This can 107 // when trying to write to a memory page that can't be created. This can
106 // fail if the disk is full and the file is sparse. 108 // fail if the disk is full and the file is sparse.
107 // 109 //
108 // Only Android API>=21 supports the fallocate call. Older versions need 110 // Only Android API>=21 supports the fallocate call. Older versions need
109 // to manually extend the file by writing zeros at block intervals. 111 // to manually extend the file by writing zeros at block intervals.
110 // 112 //
111 // Mac OSX doesn't support this call but the primary filesystem doesn't 113 // Mac OSX doesn't support this call but the primary filesystem doesn't
112 // support sparse files so is unneeded. 114 // support sparse files so is unneeded.
113 bool do_manual_extension = false; 115 bool do_manual_extension = false;
114 116
115 #if defined(OS_ANDROID) && __ANDROID_API__ < 21 117 #if defined(OS_ANDROID) && __ANDROID_API__ < 21
116 do_manual_extension = true; 118 do_manual_extension = true;
117 #elif !defined(OS_MACOSX) 119 #elif !defined(OS_MACOSX)
118 if (posix_fallocate(file_.GetPlatformFile(), region.offset, 120 if (posix_fallocate(file_.GetPlatformFile(), region.offset,
119 region.size) != 0) { 121 region.size) != 0) {
120 DPLOG(ERROR) << "posix_fallocate " << file_.GetPlatformFile(); 122 DPLOG(ERROR) << "posix_fallocate " << file_.GetPlatformFile();
121 // This can fail because the filesystem doesn't support it so don't 123 // This can fail because the filesystem doesn't support it so don't
122 // give up just yet. Try the manual method below. 124 // give up just yet. Try the manual method below.
123 do_manual_extension = true; 125 do_manual_extension = true;
124 } 126 }
125 #endif 127 #endif
126 128
127 // Manually realize the entire file by writing bytes to it at intervals. 129 // Manually realize the extended file by writing bytes to it at intervals.
128 if (do_manual_extension) { 130 if (do_manual_extension) {
129 int64_t block_size = 1024; // Start with something safe. 131 int64_t block_size = 512; // Start with something safe.
130 struct stat statbuf; 132 struct stat statbuf;
131 if (fstat(file_.GetPlatformFile(), &statbuf) == 0) 133 if (fstat(file_.GetPlatformFile(), &statbuf) == 0 &&
134 statbuf.st_blksize > 0) {
132 block_size = statbuf.st_blksize; 135 block_size = statbuf.st_blksize;
133 #if defined(OS_FUCHSIA) 136 }
134 // TODO(fuchsia): Fuchsia stat() currently returns 0 for st_blksize, 137
135 // which hangs the loop below. Remove this after the next SDK update. 138 // Write starting at the next block boundary after the old file length.
136 // https://crbug.com/706592 and MG-815. 139 const int64_t extension_start =
137 if (block_size == 0) 140 (original_file_len + block_size - 1) & ~(block_size - 1);
138 block_size = 512; 141 for (int64_t i = extension_start; i < new_file_len; i += block_size) {
139 #endif // defined(OS_FUCHSIA)
140 const off_t map_end = map_start + static_cast<off_t>(map_size);
141 for (off_t i = map_start; i < map_end; i += block_size) {
142 char existing_byte; 142 char existing_byte;
143 if (pread(file_.GetPlatformFile(), &existing_byte, 1, i) != 1) 143 if (pread(file_.GetPlatformFile(), &existing_byte, 1, i) != 1)
144 return false; // Can't read? Not viable. 144 return false; // Can't read? Not viable.
145 if (existing_byte != 0) 145 if (existing_byte != 0)
146 continue; // Block has data so must already exist. 146 continue; // Block has data so must already exist.
147 if (pwrite(file_.GetPlatformFile(), &existing_byte, 1, i) != 1) 147 if (pwrite(file_.GetPlatformFile(), &existing_byte, 1, i) != 1)
148 return false; // Can't write? Not viable. 148 return false; // Can't write? Not viable.
Mark Mentovai 2017/06/15 15:31:23 If we hit this, does something cause the file to b
bcwhite 2017/06/15 15:38:19 With regard to persistent histograms, the unused f
149 } 149 }
150 } 150 }
151 151
152 break; 152 break;
153 } 153 }
154 154
155 data_ = static_cast<uint8_t*>(mmap(NULL, map_size, flags, MAP_SHARED, 155 data_ = static_cast<uint8_t*>(mmap(NULL, map_size, flags, MAP_SHARED,
156 file_.GetPlatformFile(), map_start)); 156 file_.GetPlatformFile(), map_start));
157 if (data_ == MAP_FAILED) { 157 if (data_ == MAP_FAILED) {
158 DPLOG(ERROR) << "mmap " << file_.GetPlatformFile(); 158 DPLOG(ERROR) << "mmap " << file_.GetPlatformFile();
(...skipping 10 matching lines...) Expand all
169 169
170 if (data_ != NULL) 170 if (data_ != NULL)
171 munmap(data_, length_); 171 munmap(data_, length_);
172 file_.Close(); 172 file_.Close();
173 173
174 data_ = NULL; 174 data_ = NULL;
175 length_ = 0; 175 length_ = 0;
176 } 176 }
177 177
178 } // namespace base 178 } // namespace base
OLDNEW
« no previous file with comments | « base/files/memory_mapped_file.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698