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

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

Issue 1072133006: Add granular file tracing. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@do-initialize
Patch Set: add async file tracing Created 5 years, 8 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/file.h" 5 #include "base/files/file.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #include <sys/stat.h> 9 #include <sys/stat.h>
10 #include <unistd.h> 10 #include <unistd.h>
11 11
12 #include "base/files/file_path.h"
13 #include "base/files/file_posix_hooks_internal.h" 12 #include "base/files/file_posix_hooks_internal.h"
14 #include "base/logging.h" 13 #include "base/logging.h"
15 #include "base/metrics/sparse_histogram.h" 14 #include "base/metrics/sparse_histogram.h"
16 #include "base/posix/eintr_wrapper.h" 15 #include "base/posix/eintr_wrapper.h"
17 #include "base/strings/utf_string_conversions.h" 16 #include "base/strings/utf_string_conversions.h"
18 #include "base/threading/thread_restrictions.h" 17 #include "base/threading/thread_restrictions.h"
18 #include "base/trace_event/scoped_file_trace.h"
19 19
20 #if defined(OS_ANDROID) 20 #if defined(OS_ANDROID)
21 #include "base/os_compat_android.h" 21 #include "base/os_compat_android.h"
22 #endif 22 #endif
23 23
24 namespace base { 24 namespace base {
25 25
26 // Make sure our Whence mappings match the system headers. 26 // Make sure our Whence mappings match the system headers.
27 COMPILE_ASSERT(File::FROM_BEGIN == SEEK_SET && 27 COMPILE_ASSERT(File::FROM_BEGIN == SEEK_SET &&
28 File::FROM_CURRENT == SEEK_CUR && 28 File::FROM_CURRENT == SEEK_CUR &&
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 return file_.get(); 174 return file_.get();
175 } 175 }
176 176
177 PlatformFile File::TakePlatformFile() { 177 PlatformFile File::TakePlatformFile() {
178 if (IsValid()) 178 if (IsValid())
179 UnprotectFileDescriptor(GetPlatformFile()); 179 UnprotectFileDescriptor(GetPlatformFile());
180 return file_.release(); 180 return file_.release();
181 } 181 }
182 182
183 void File::Close() { 183 void File::Close() {
184 ScopedFileTrace trace(path_, "Close", 0);
184 if (!IsValid()) 185 if (!IsValid())
185 return; 186 return;
186 187
187 ThreadRestrictions::AssertIOAllowed(); 188 ThreadRestrictions::AssertIOAllowed();
188 UnprotectFileDescriptor(GetPlatformFile()); 189 UnprotectFileDescriptor(GetPlatformFile());
189 file_.reset(); 190 file_.reset();
190 } 191 }
191 192
192 int64 File::Seek(Whence whence, int64 offset) { 193 int64 File::Seek(Whence whence, int64 offset) {
193 ThreadRestrictions::AssertIOAllowed(); 194 ThreadRestrictions::AssertIOAllowed();
194 DCHECK(IsValid()); 195 DCHECK(IsValid());
195 196
196 #if defined(OS_ANDROID) 197 #if defined(OS_ANDROID)
197 COMPILE_ASSERT(sizeof(int64) == sizeof(off64_t), off64_t_64_bit); 198 COMPILE_ASSERT(sizeof(int64) == sizeof(off64_t), off64_t_64_bit);
198 return lseek64(file_.get(), static_cast<off64_t>(offset), 199 return lseek64(file_.get(), static_cast<off64_t>(offset),
199 static_cast<int>(whence)); 200 static_cast<int>(whence));
200 #else 201 #else
201 COMPILE_ASSERT(sizeof(int64) == sizeof(off_t), off_t_64_bit); 202 COMPILE_ASSERT(sizeof(int64) == sizeof(off_t), off_t_64_bit);
202 return lseek(file_.get(), static_cast<off_t>(offset), 203 return lseek(file_.get(), static_cast<off_t>(offset),
203 static_cast<int>(whence)); 204 static_cast<int>(whence));
204 #endif 205 #endif
205 } 206 }
206 207
207 int File::Read(int64 offset, char* data, int size) { 208 int File::Read(int64 offset, char* data, int size) {
208 ThreadRestrictions::AssertIOAllowed(); 209 ThreadRestrictions::AssertIOAllowed();
209 DCHECK(IsValid()); 210 DCHECK(IsValid());
210 if (size < 0) 211 if (size < 0)
211 return -1; 212 return -1;
212 213
214 ScopedFileTrace trace(path_, "Read", size);
215
213 int bytes_read = 0; 216 int bytes_read = 0;
214 int rv; 217 int rv;
215 do { 218 do {
216 rv = HANDLE_EINTR(pread(file_.get(), data + bytes_read, 219 rv = HANDLE_EINTR(pread(file_.get(), data + bytes_read,
217 size - bytes_read, offset + bytes_read)); 220 size - bytes_read, offset + bytes_read));
218 if (rv <= 0) 221 if (rv <= 0)
219 break; 222 break;
220 223
221 bytes_read += rv; 224 bytes_read += rv;
222 } while (bytes_read < size); 225 } while (bytes_read < size);
223 226
224 return bytes_read ? bytes_read : rv; 227 return bytes_read ? bytes_read : rv;
225 } 228 }
226 229
227 int File::ReadAtCurrentPos(char* data, int size) { 230 int File::ReadAtCurrentPos(char* data, int size) {
228 ThreadRestrictions::AssertIOAllowed(); 231 ThreadRestrictions::AssertIOAllowed();
229 DCHECK(IsValid()); 232 DCHECK(IsValid());
230 if (size < 0) 233 if (size < 0)
231 return -1; 234 return -1;
232 235
236 ScopedFileTrace trace(path_, "ReadAtCurrentPos", size);
237
233 int bytes_read = 0; 238 int bytes_read = 0;
234 int rv; 239 int rv;
235 do { 240 do {
236 rv = HANDLE_EINTR(read(file_.get(), data + bytes_read, size - bytes_read)); 241 rv = HANDLE_EINTR(read(file_.get(), data + bytes_read, size - bytes_read));
237 if (rv <= 0) 242 if (rv <= 0)
238 break; 243 break;
239 244
240 bytes_read += rv; 245 bytes_read += rv;
241 } while (bytes_read < size); 246 } while (bytes_read < size);
242 247
243 return bytes_read ? bytes_read : rv; 248 return bytes_read ? bytes_read : rv;
244 } 249 }
245 250
246 int File::ReadNoBestEffort(int64 offset, char* data, int size) { 251 int File::ReadNoBestEffort(int64 offset, char* data, int size) {
247 ThreadRestrictions::AssertIOAllowed(); 252 ThreadRestrictions::AssertIOAllowed();
248 DCHECK(IsValid()); 253 DCHECK(IsValid());
249 254 ScopedFileTrace trace(path_, "ReadNoBestEffort", size);
250 return HANDLE_EINTR(pread(file_.get(), data, size, offset)); 255 return HANDLE_EINTR(pread(file_.get(), data, size, offset));
251 } 256 }
252 257
253 int File::ReadAtCurrentPosNoBestEffort(char* data, int size) { 258 int File::ReadAtCurrentPosNoBestEffort(char* data, int size) {
254 ThreadRestrictions::AssertIOAllowed(); 259 ThreadRestrictions::AssertIOAllowed();
255 DCHECK(IsValid()); 260 DCHECK(IsValid());
256 if (size < 0) 261 if (size < 0)
257 return -1; 262 return -1;
258 263
264 ScopedFileTrace trace(path_, "ReadAtCurrentPosNoBestEffort", size);
259 return HANDLE_EINTR(read(file_.get(), data, size)); 265 return HANDLE_EINTR(read(file_.get(), data, size));
260 } 266 }
261 267
262 int File::Write(int64 offset, const char* data, int size) { 268 int File::Write(int64 offset, const char* data, int size) {
263 ThreadRestrictions::AssertIOAllowed(); 269 ThreadRestrictions::AssertIOAllowed();
264 270
265 if (IsOpenAppend(file_.get())) 271 if (IsOpenAppend(file_.get()))
266 return WriteAtCurrentPos(data, size); 272 return WriteAtCurrentPos(data, size);
267 273
268 DCHECK(IsValid()); 274 DCHECK(IsValid());
269 if (size < 0) 275 if (size < 0)
270 return -1; 276 return -1;
271 277
278 ScopedFileTrace trace(path_, "Write", size);
279
272 int bytes_written = 0; 280 int bytes_written = 0;
273 int rv; 281 int rv;
274 do { 282 do {
275 rv = HANDLE_EINTR(pwrite(file_.get(), data + bytes_written, 283 rv = HANDLE_EINTR(pwrite(file_.get(), data + bytes_written,
276 size - bytes_written, offset + bytes_written)); 284 size - bytes_written, offset + bytes_written));
277 if (rv <= 0) 285 if (rv <= 0)
278 break; 286 break;
279 287
280 bytes_written += rv; 288 bytes_written += rv;
281 } while (bytes_written < size); 289 } while (bytes_written < size);
282 290
283 return bytes_written ? bytes_written : rv; 291 return bytes_written ? bytes_written : rv;
284 } 292 }
285 293
286 int File::WriteAtCurrentPos(const char* data, int size) { 294 int File::WriteAtCurrentPos(const char* data, int size) {
287 ThreadRestrictions::AssertIOAllowed(); 295 ThreadRestrictions::AssertIOAllowed();
288 DCHECK(IsValid()); 296 DCHECK(IsValid());
289 if (size < 0) 297 if (size < 0)
290 return -1; 298 return -1;
291 299
300 ScopedFileTrace trace(path_, "WriteAtCurrentPos", size);
301
292 int bytes_written = 0; 302 int bytes_written = 0;
293 int rv; 303 int rv;
294 do { 304 do {
295 rv = HANDLE_EINTR(write(file_.get(), data + bytes_written, 305 rv = HANDLE_EINTR(write(file_.get(), data + bytes_written,
296 size - bytes_written)); 306 size - bytes_written));
297 if (rv <= 0) 307 if (rv <= 0)
298 break; 308 break;
299 309
300 bytes_written += rv; 310 bytes_written += rv;
301 } while (bytes_written < size); 311 } while (bytes_written < size);
302 312
303 return bytes_written ? bytes_written : rv; 313 return bytes_written ? bytes_written : rv;
304 } 314 }
305 315
306 int File::WriteAtCurrentPosNoBestEffort(const char* data, int size) { 316 int File::WriteAtCurrentPosNoBestEffort(const char* data, int size) {
307 ThreadRestrictions::AssertIOAllowed(); 317 ThreadRestrictions::AssertIOAllowed();
308 DCHECK(IsValid()); 318 DCHECK(IsValid());
309 if (size < 0) 319 if (size < 0)
310 return -1; 320 return -1;
311 321
322 ScopedFileTrace trace(path_, "WriteAtCurrentPosNoBestEffort", size);
312 return HANDLE_EINTR(write(file_.get(), data, size)); 323 return HANDLE_EINTR(write(file_.get(), data, size));
313 } 324 }
314 325
315 int64 File::GetLength() { 326 int64 File::GetLength() {
316 DCHECK(IsValid()); 327 DCHECK(IsValid());
317 328
329 ScopedFileTrace trace(path_, "GetLength", 0);
330
318 stat_wrapper_t file_info; 331 stat_wrapper_t file_info;
319 if (CallFstat(file_.get(), &file_info)) 332 if (CallFstat(file_.get(), &file_info))
320 return false; 333 return false;
321 334
322 return file_info.st_size; 335 return file_info.st_size;
323 } 336 }
324 337
325 bool File::SetLength(int64 length) { 338 bool File::SetLength(int64 length) {
326 ThreadRestrictions::AssertIOAllowed(); 339 ThreadRestrictions::AssertIOAllowed();
327 DCHECK(IsValid()); 340 DCHECK(IsValid());
341
342 ScopedFileTrace trace(path_, "SetLength", 0);
328 return !CallFtruncate(file_.get(), length); 343 return !CallFtruncate(file_.get(), length);
329 } 344 }
330 345
331 bool File::SetTimes(Time last_access_time, Time last_modified_time) { 346 bool File::SetTimes(Time last_access_time, Time last_modified_time) {
332 ThreadRestrictions::AssertIOAllowed(); 347 ThreadRestrictions::AssertIOAllowed();
333 DCHECK(IsValid()); 348 DCHECK(IsValid());
334 349
335 timeval times[2]; 350 timeval times[2];
336 times[0] = last_access_time.ToTimeVal(); 351 times[0] = last_access_time.ToTimeVal();
337 times[1] = last_modified_time.ToTimeVal(); 352 times[1] = last_modified_time.ToTimeVal();
338 353
354 ScopedFileTrace trace(path_, "SetTimes", 0);
339 return !CallFutimes(file_.get(), times); 355 return !CallFutimes(file_.get(), times);
340 } 356 }
341 357
342 bool File::GetInfo(Info* info) { 358 bool File::GetInfo(Info* info) {
343 DCHECK(IsValid()); 359 DCHECK(IsValid());
344 360
361 ScopedFileTrace trace(path_, "GetInfo", 0);
362
345 stat_wrapper_t file_info; 363 stat_wrapper_t file_info;
346 if (CallFstat(file_.get(), &file_info)) 364 if (CallFstat(file_.get(), &file_info))
347 return false; 365 return false;
348 366
349 info->FromStat(file_info); 367 info->FromStat(file_info);
350 return true; 368 return true;
351 } 369 }
352 370
353 File::Error File::Lock() { 371 File::Error File::Lock() {
372 ScopedFileTrace trace(path_, "Lock", 0);
354 return CallFctnlFlock(file_.get(), true); 373 return CallFctnlFlock(file_.get(), true);
355 } 374 }
356 375
357 File::Error File::Unlock() { 376 File::Error File::Unlock() {
377 ScopedFileTrace trace(path_, "Unlock", 0);
358 return CallFctnlFlock(file_.get(), false); 378 return CallFctnlFlock(file_.get(), false);
359 } 379 }
360 380
361 File File::Duplicate() { 381 File File::Duplicate() {
362 if (!IsValid()) 382 if (!IsValid())
363 return File(); 383 return File();
364 384
385 ScopedFileTrace trace(path_, "Duplicate", 0);
386
365 PlatformFile other_fd = dup(GetPlatformFile()); 387 PlatformFile other_fd = dup(GetPlatformFile());
366 if (other_fd == -1) 388 if (other_fd == -1)
367 return File(OSErrorToFileError(errno)); 389 return File(OSErrorToFileError(errno));
368 390
369 File other(other_fd); 391 File other(other_fd);
370 if (async()) 392 if (async())
371 other.async_ = true; 393 other.async_ = true;
372 return other.Pass(); 394 return other.Pass();
373 } 395 }
374 396
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 CHECK_EQ(file_memory_checksum_, computed_checksum) << "corrupted fd memory"; 469 CHECK_EQ(file_memory_checksum_, computed_checksum) << "corrupted fd memory";
448 } 470 }
449 471
450 void File::MemoryCheckingScopedFD::UpdateChecksum() { 472 void File::MemoryCheckingScopedFD::UpdateChecksum() {
451 ComputeMemoryChecksum(&file_memory_checksum_); 473 ComputeMemoryChecksum(&file_memory_checksum_);
452 } 474 }
453 475
454 // NaCl doesn't implement system calls to open files directly. 476 // NaCl doesn't implement system calls to open files directly.
455 #if !defined(OS_NACL) 477 #if !defined(OS_NACL)
456 // TODO(erikkay): does it make sense to support FLAG_EXCLUSIVE_* here? 478 // TODO(erikkay): does it make sense to support FLAG_EXCLUSIVE_* here?
457 void File::DoInitialize(const FilePath& name, uint32 flags) { 479 void File::DoInitialize(uint32 flags) {
458 ThreadRestrictions::AssertIOAllowed(); 480 ThreadRestrictions::AssertIOAllowed();
459 DCHECK(!IsValid()); 481 DCHECK(!IsValid());
460 482
483 ScopedFileTrace trace(path_, "Initialize", 0);
484
461 int open_flags = 0; 485 int open_flags = 0;
462 if (flags & FLAG_CREATE) 486 if (flags & FLAG_CREATE)
463 open_flags = O_CREAT | O_EXCL; 487 open_flags = O_CREAT | O_EXCL;
464 488
465 created_ = false; 489 created_ = false;
466 490
467 if (flags & FLAG_CREATE_ALWAYS) { 491 if (flags & FLAG_CREATE_ALWAYS) {
468 DCHECK(!open_flags); 492 DCHECK(!open_flags);
469 DCHECK(flags & FLAG_WRITE); 493 DCHECK(flags & FLAG_WRITE);
470 open_flags = O_CREAT | O_TRUNC; 494 open_flags = O_CREAT | O_TRUNC;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
502 else if (flags & FLAG_APPEND) 526 else if (flags & FLAG_APPEND)
503 open_flags |= O_APPEND | O_WRONLY; 527 open_flags |= O_APPEND | O_WRONLY;
504 528
505 COMPILE_ASSERT(O_RDONLY == 0, O_RDONLY_must_equal_zero); 529 COMPILE_ASSERT(O_RDONLY == 0, O_RDONLY_must_equal_zero);
506 530
507 int mode = S_IRUSR | S_IWUSR; 531 int mode = S_IRUSR | S_IWUSR;
508 #if defined(OS_CHROMEOS) 532 #if defined(OS_CHROMEOS)
509 mode |= S_IRGRP | S_IROTH; 533 mode |= S_IRGRP | S_IROTH;
510 #endif 534 #endif
511 535
512 int descriptor = HANDLE_EINTR(open(name.value().c_str(), open_flags, mode)); 536 int descriptor = HANDLE_EINTR(open(path_.value().c_str(), open_flags, mode));
513 537
514 if (flags & FLAG_OPEN_ALWAYS) { 538 if (flags & FLAG_OPEN_ALWAYS) {
515 if (descriptor < 0) { 539 if (descriptor < 0) {
516 open_flags |= O_CREAT; 540 open_flags |= O_CREAT;
517 if (flags & FLAG_EXCLUSIVE_READ || flags & FLAG_EXCLUSIVE_WRITE) 541 if (flags & FLAG_EXCLUSIVE_READ || flags & FLAG_EXCLUSIVE_WRITE)
518 open_flags |= O_EXCL; // together with O_CREAT implies O_NOFOLLOW 542 open_flags |= O_EXCL; // together with O_CREAT implies O_NOFOLLOW
519 543
520 descriptor = HANDLE_EINTR(open(name.value().c_str(), open_flags, mode)); 544 descriptor = HANDLE_EINTR(open(path_.value().c_str(), open_flags, mode));
521 if (descriptor >= 0) 545 if (descriptor >= 0)
522 created_ = true; 546 created_ = true;
523 } 547 }
524 } 548 }
525 549
526 if (descriptor < 0) { 550 if (descriptor < 0) {
527 error_details_ = File::OSErrorToFileError(errno); 551 error_details_ = File::OSErrorToFileError(errno);
528 return; 552 return;
529 } 553 }
530 554
531 if (flags & (FLAG_CREATE_ALWAYS | FLAG_CREATE)) 555 if (flags & (FLAG_CREATE_ALWAYS | FLAG_CREATE))
532 created_ = true; 556 created_ = true;
533 557
534 if (flags & FLAG_DELETE_ON_CLOSE) 558 if (flags & FLAG_DELETE_ON_CLOSE)
535 unlink(name.value().c_str()); 559 unlink(path_.value().c_str());
536 560
537 async_ = ((flags & FLAG_ASYNC) == FLAG_ASYNC); 561 async_ = ((flags & FLAG_ASYNC) == FLAG_ASYNC);
538 error_details_ = FILE_OK; 562 error_details_ = FILE_OK;
539 file_.reset(descriptor); 563 file_.reset(descriptor);
540 ProtectFileDescriptor(descriptor); 564 ProtectFileDescriptor(descriptor);
541 } 565 }
542 #endif // !defined(OS_NACL) 566 #endif // !defined(OS_NACL)
543 567
544 bool File::DoFlush() { 568 bool File::DoFlush() {
545 ThreadRestrictions::AssertIOAllowed(); 569 ThreadRestrictions::AssertIOAllowed();
546 DCHECK(IsValid()); 570 DCHECK(IsValid());
571
547 #if defined(OS_NACL) 572 #if defined(OS_NACL)
548 NOTIMPLEMENTED(); // NaCl doesn't implement fsync. 573 NOTIMPLEMENTED(); // NaCl doesn't implement fsync.
549 return true; 574 return true;
550 #elif defined(OS_LINUX) || defined(OS_ANDROID) 575 #else
576 ScopedFileTrace trace(path_, "Flush", 0);
577 #if defined(OS_LINUX) || defined(OS_ANDROID)
551 return !HANDLE_EINTR(fdatasync(file_.get())); 578 return !HANDLE_EINTR(fdatasync(file_.get()));
552 #else 579 #else
553 return !HANDLE_EINTR(fsync(file_.get())); 580 return !HANDLE_EINTR(fsync(file_.get()));
554 #endif 581 #endif // defined(OS_LINUX) || defined(OS_ANDROID)
582 #endif // defined(OS_NACL)
555 } 583 }
556 584
557 void File::SetPlatformFile(PlatformFile file) { 585 void File::SetPlatformFile(PlatformFile file) {
558 CHECK(!file_.is_valid()); 586 CHECK(!file_.is_valid());
559 file_.reset(file); 587 file_.reset(file);
560 if (file_.is_valid()) 588 if (file_.is_valid())
561 ProtectFileDescriptor(GetPlatformFile()); 589 ProtectFileDescriptor(GetPlatformFile());
562 } 590 }
563 591
564 } // namespace base 592 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698