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

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: asdf Created 5 years, 7 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" 12 #include "base/files/file_path.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/metrics/sparse_histogram.h" 14 #include "base/metrics/sparse_histogram.h"
15 #include "base/posix/eintr_wrapper.h" 15 #include "base/posix/eintr_wrapper.h"
16 #include "base/strings/utf_string_conversions.h" 16 #include "base/strings/utf_string_conversions.h"
17 #include "base/threading/thread_restrictions.h" 17 #include "base/threading/thread_restrictions.h"
18 #include "base/trace_event/trace_event.h"
18 19
19 #if defined(OS_ANDROID) 20 #if defined(OS_ANDROID)
20 #include "base/os_compat_android.h" 21 #include "base/os_compat_android.h"
21 #endif 22 #endif
22 23
23 namespace base { 24 namespace base {
24 25
25 // Make sure our Whence mappings match the system headers. 26 // Make sure our Whence mappings match the system headers.
26 COMPILE_ASSERT(File::FROM_BEGIN == SEEK_SET && 27 COMPILE_ASSERT(File::FROM_BEGIN == SEEK_SET &&
27 File::FROM_CURRENT == SEEK_CUR && 28 File::FROM_CURRENT == SEEK_CUR &&
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 } 167 }
167 168
168 PlatformFile File::TakePlatformFile() { 169 PlatformFile File::TakePlatformFile() {
169 return file_.release(); 170 return file_.release();
170 } 171 }
171 172
172 void File::Close() { 173 void File::Close() {
173 if (!IsValid()) 174 if (!IsValid())
174 return; 175 return;
175 176
177 TRACE_EVENT_NESTABLE_ASYNC0(kTraceGroup, "base::File::Close", this);
176 ThreadRestrictions::AssertIOAllowed(); 178 ThreadRestrictions::AssertIOAllowed();
177 file_.reset(); 179 file_.reset();
178 } 180 }
179 181
180 int64 File::Seek(Whence whence, int64 offset) { 182 int64 File::Seek(Whence whence, int64 offset) {
181 ThreadRestrictions::AssertIOAllowed(); 183 ThreadRestrictions::AssertIOAllowed();
182 DCHECK(IsValid()); 184 DCHECK(IsValid());
183 185
186 TRACE_EVENT_NESTABLE_ASYNC1(kTraceGroup, "base::File::Seek", this,
187 "path", unsafe_path_.AsUTF8Unsafe());
188
184 #if defined(OS_ANDROID) 189 #if defined(OS_ANDROID)
185 COMPILE_ASSERT(sizeof(int64) == sizeof(off64_t), off64_t_64_bit); 190 COMPILE_ASSERT(sizeof(int64) == sizeof(off64_t), off64_t_64_bit);
186 return lseek64(file_.get(), static_cast<off64_t>(offset), 191 return lseek64(file_.get(), static_cast<off64_t>(offset),
187 static_cast<int>(whence)); 192 static_cast<int>(whence));
188 #else 193 #else
189 COMPILE_ASSERT(sizeof(int64) == sizeof(off_t), off_t_64_bit); 194 COMPILE_ASSERT(sizeof(int64) == sizeof(off_t), off_t_64_bit);
190 return lseek(file_.get(), static_cast<off_t>(offset), 195 return lseek(file_.get(), static_cast<off_t>(offset),
191 static_cast<int>(whence)); 196 static_cast<int>(whence));
192 #endif 197 #endif
193 } 198 }
194 199
195 int File::Read(int64 offset, char* data, int size) { 200 int File::Read(int64 offset, char* data, int size) {
196 ThreadRestrictions::AssertIOAllowed(); 201 ThreadRestrictions::AssertIOAllowed();
197 DCHECK(IsValid()); 202 DCHECK(IsValid());
198 if (size < 0) 203 if (size < 0)
199 return -1; 204 return -1;
200 205
206 TRACE_EVENT_NESTABLE_ASYNC2(kTraceGroup, "base::File::Read", this,
207 "path", unsafe_path_.AsUTF8Unsafe(), "size", size);
208
201 int bytes_read = 0; 209 int bytes_read = 0;
202 int rv; 210 int rv;
203 do { 211 do {
204 rv = HANDLE_EINTR(pread(file_.get(), data + bytes_read, 212 rv = HANDLE_EINTR(pread(file_.get(), data + bytes_read,
205 size - bytes_read, offset + bytes_read)); 213 size - bytes_read, offset + bytes_read));
206 if (rv <= 0) 214 if (rv <= 0)
207 break; 215 break;
208 216
209 bytes_read += rv; 217 bytes_read += rv;
210 } while (bytes_read < size); 218 } while (bytes_read < size);
211 219
212 return bytes_read ? bytes_read : rv; 220 return bytes_read ? bytes_read : rv;
213 } 221 }
214 222
215 int File::ReadAtCurrentPos(char* data, int size) { 223 int File::ReadAtCurrentPos(char* data, int size) {
216 ThreadRestrictions::AssertIOAllowed(); 224 ThreadRestrictions::AssertIOAllowed();
217 DCHECK(IsValid()); 225 DCHECK(IsValid());
218 if (size < 0) 226 if (size < 0)
219 return -1; 227 return -1;
220 228
229 TRACE_EVENT_NESTABLE_ASYNC2(kTraceGroup, "base::File::ReadAtCurrentPos", this,
230 "path", unsafe_path_.AsUTF8Unsafe(), "size", size);
231
221 int bytes_read = 0; 232 int bytes_read = 0;
222 int rv; 233 int rv;
223 do { 234 do {
224 rv = HANDLE_EINTR(read(file_.get(), data + bytes_read, size - bytes_read)); 235 rv = HANDLE_EINTR(read(file_.get(), data + bytes_read, size - bytes_read));
225 if (rv <= 0) 236 if (rv <= 0)
226 break; 237 break;
227 238
228 bytes_read += rv; 239 bytes_read += rv;
229 } while (bytes_read < size); 240 } while (bytes_read < size);
230 241
231 return bytes_read ? bytes_read : rv; 242 return bytes_read ? bytes_read : rv;
232 } 243 }
233 244
234 int File::ReadNoBestEffort(int64 offset, char* data, int size) { 245 int File::ReadNoBestEffort(int64 offset, char* data, int size) {
235 ThreadRestrictions::AssertIOAllowed(); 246 ThreadRestrictions::AssertIOAllowed();
236 DCHECK(IsValid()); 247 DCHECK(IsValid());
237 248 TRACE_EVENT_NESTABLE_ASYNC2(kTraceGroup, "base::File::ReadNoBestEffort", this,
249 "path", unsafe_path_.AsUTF8Unsafe(), "size", size);
238 return HANDLE_EINTR(pread(file_.get(), data, size, offset)); 250 return HANDLE_EINTR(pread(file_.get(), data, size, offset));
239 } 251 }
240 252
241 int File::ReadAtCurrentPosNoBestEffort(char* data, int size) { 253 int File::ReadAtCurrentPosNoBestEffort(char* data, int size) {
242 ThreadRestrictions::AssertIOAllowed(); 254 ThreadRestrictions::AssertIOAllowed();
243 DCHECK(IsValid()); 255 DCHECK(IsValid());
244 if (size < 0) 256 if (size < 0)
245 return -1; 257 return -1;
246 258
259 TRACE_EVENT_NESTABLE_ASYNC2(
260 kTraceGroup, "base::File::ReadAtCurrentPosNoBestEffort", this,
261 "path", unsafe_path_.AsUTF8Unsafe(), "size", size);
247 return HANDLE_EINTR(read(file_.get(), data, size)); 262 return HANDLE_EINTR(read(file_.get(), data, size));
248 } 263 }
249 264
250 int File::Write(int64 offset, const char* data, int size) { 265 int File::Write(int64 offset, const char* data, int size) {
251 ThreadRestrictions::AssertIOAllowed(); 266 ThreadRestrictions::AssertIOAllowed();
252 267
253 if (IsOpenAppend(file_.get())) 268 if (IsOpenAppend(file_.get()))
254 return WriteAtCurrentPos(data, size); 269 return WriteAtCurrentPos(data, size);
255 270
256 DCHECK(IsValid()); 271 DCHECK(IsValid());
257 if (size < 0) 272 if (size < 0)
258 return -1; 273 return -1;
259 274
275 TRACE_EVENT_NESTABLE_ASYNC2(kTraceGroup, "base::File::Write", this,
276 "path", unsafe_path_.AsUTF8Unsafe(), "size", size);
277
260 int bytes_written = 0; 278 int bytes_written = 0;
261 int rv; 279 int rv;
262 do { 280 do {
263 rv = HANDLE_EINTR(pwrite(file_.get(), data + bytes_written, 281 rv = HANDLE_EINTR(pwrite(file_.get(), data + bytes_written,
264 size - bytes_written, offset + bytes_written)); 282 size - bytes_written, offset + bytes_written));
265 if (rv <= 0) 283 if (rv <= 0)
266 break; 284 break;
267 285
268 bytes_written += rv; 286 bytes_written += rv;
269 } while (bytes_written < size); 287 } while (bytes_written < size);
270 288
271 return bytes_written ? bytes_written : rv; 289 return bytes_written ? bytes_written : rv;
272 } 290 }
273 291
274 int File::WriteAtCurrentPos(const char* data, int size) { 292 int File::WriteAtCurrentPos(const char* data, int size) {
275 ThreadRestrictions::AssertIOAllowed(); 293 ThreadRestrictions::AssertIOAllowed();
276 DCHECK(IsValid()); 294 DCHECK(IsValid());
277 if (size < 0) 295 if (size < 0)
278 return -1; 296 return -1;
279 297
298 TRACE_EVENT_NESTABLE_ASYNC2(
299 kTraceGroup, "base::File::WriteAtCurrentPos", this,
300 "path", unsafe_path_.AsUTF8Unsafe(), "size", size);
301
280 int bytes_written = 0; 302 int bytes_written = 0;
281 int rv; 303 int rv;
282 do { 304 do {
283 rv = HANDLE_EINTR(write(file_.get(), data + bytes_written, 305 rv = HANDLE_EINTR(write(file_.get(), data + bytes_written,
284 size - bytes_written)); 306 size - bytes_written));
285 if (rv <= 0) 307 if (rv <= 0)
286 break; 308 break;
287 309
288 bytes_written += rv; 310 bytes_written += rv;
289 } while (bytes_written < size); 311 } while (bytes_written < size);
290 312
291 return bytes_written ? bytes_written : rv; 313 return bytes_written ? bytes_written : rv;
292 } 314 }
293 315
294 int File::WriteAtCurrentPosNoBestEffort(const char* data, int size) { 316 int File::WriteAtCurrentPosNoBestEffort(const char* data, int size) {
295 ThreadRestrictions::AssertIOAllowed(); 317 ThreadRestrictions::AssertIOAllowed();
296 DCHECK(IsValid()); 318 DCHECK(IsValid());
297 if (size < 0) 319 if (size < 0)
298 return -1; 320 return -1;
299 321
322 TRACE_EVENT_NESTABLE_ASYNC2(
323 kTraceGroup, "base::File::WriteAtCurrentPosNoBestEffort", this,
324 "path", unsafe_path_.AsUTF8Unsafe(), "size", size);
300 return HANDLE_EINTR(write(file_.get(), data, size)); 325 return HANDLE_EINTR(write(file_.get(), data, size));
301 } 326 }
302 327
303 int64 File::GetLength() { 328 int64 File::GetLength() {
304 DCHECK(IsValid()); 329 DCHECK(IsValid());
305 330
331 TRACE_EVENT_NESTABLE_ASYNC1(kTraceGroup, "base::File::GetLength", this,
332 "path", unsafe_path_.AsUTF8Unsafe());
333
306 stat_wrapper_t file_info; 334 stat_wrapper_t file_info;
307 if (CallFstat(file_.get(), &file_info)) 335 if (CallFstat(file_.get(), &file_info))
308 return false; 336 return false;
309 337
310 return file_info.st_size; 338 return file_info.st_size;
311 } 339 }
312 340
313 bool File::SetLength(int64 length) { 341 bool File::SetLength(int64 length) {
314 ThreadRestrictions::AssertIOAllowed(); 342 ThreadRestrictions::AssertIOAllowed();
315 DCHECK(IsValid()); 343 DCHECK(IsValid());
344
345 TRACE_EVENT_NESTABLE_ASYNC2(kTraceGroup, "base::File::SetLength", this,
346 "path", unsafe_path_.AsUTF8Unsafe(), "length", length);
316 return !CallFtruncate(file_.get(), length); 347 return !CallFtruncate(file_.get(), length);
317 } 348 }
318 349
350 bool File::Flush() {
351 ThreadRestrictions::AssertIOAllowed();
352 DCHECK(IsValid());
353
354 #if defined(OS_NACL)
355 NOTIMPLEMENTED(); // NaCl doesn't implement fsync.
356 return true;
357 #else
358 TRACE_EVENT_NESTABLE_ASYNC1(kTraceGroup, "base::File::Flush", this,
359 "path", unsafe_path_.AsUTF8Unsafe());
360 #if defined(OS_LINUX) || defined(OS_ANDROID)
361 return !HANDLE_EINTR(fdatasync(file_.get()));
362 #else
363 return !HANDLE_EINTR(fsync(file_.get()));
364 #endif // defined(OS_LINUX) || defined(OS_ANDROID)
365 #endif // defined(OS_NACL)
366 }
367
368 void File::SetPlatformFile(PlatformFile file) {
369 DCHECK(!file_.is_valid());
370 file_.reset(file);
371 }
372
319 bool File::SetTimes(Time last_access_time, Time last_modified_time) { 373 bool File::SetTimes(Time last_access_time, Time last_modified_time) {
320 ThreadRestrictions::AssertIOAllowed(); 374 ThreadRestrictions::AssertIOAllowed();
321 DCHECK(IsValid()); 375 DCHECK(IsValid());
322 376
377 TRACE_EVENT_NESTABLE_ASYNC1(kTraceGroup, "base::File::SetTimes", this,
378 "path", unsafe_path_.AsUTF8Unsafe());
379
323 timeval times[2]; 380 timeval times[2];
324 times[0] = last_access_time.ToTimeVal(); 381 times[0] = last_access_time.ToTimeVal();
325 times[1] = last_modified_time.ToTimeVal(); 382 times[1] = last_modified_time.ToTimeVal();
326 383
327 return !CallFutimes(file_.get(), times); 384 return !CallFutimes(file_.get(), times);
328 } 385 }
329 386
330 bool File::GetInfo(Info* info) { 387 bool File::GetInfo(Info* info) {
331 DCHECK(IsValid()); 388 DCHECK(IsValid());
332 389
390 TRACE_EVENT_NESTABLE_ASYNC1(kTraceGroup, "base::File::GetInfo", this,
391 "path", unsafe_path_.AsUTF8Unsafe());
392
333 stat_wrapper_t file_info; 393 stat_wrapper_t file_info;
334 if (CallFstat(file_.get(), &file_info)) 394 if (CallFstat(file_.get(), &file_info))
335 return false; 395 return false;
336 396
337 info->FromStat(file_info); 397 info->FromStat(file_info);
338 return true; 398 return true;
339 } 399 }
340 400
341 File::Error File::Lock() { 401 File::Error File::Lock() {
402 TRACE_EVENT_NESTABLE_ASYNC1(kTraceGroup, "base::File::Lock", this,
403 "path", unsafe_path_.AsUTF8Unsafe());
342 return CallFctnlFlock(file_.get(), true); 404 return CallFctnlFlock(file_.get(), true);
343 } 405 }
344 406
345 File::Error File::Unlock() { 407 File::Error File::Unlock() {
408 TRACE_EVENT_NESTABLE_ASYNC1(kTraceGroup, "base::File::Unlock", this,
409 "path", unsafe_path_.AsUTF8Unsafe());
346 return CallFctnlFlock(file_.get(), false); 410 return CallFctnlFlock(file_.get(), false);
347 } 411 }
348 412
349 File File::Duplicate() { 413 File File::Duplicate() {
350 if (!IsValid()) 414 if (!IsValid())
351 return File(); 415 return File();
352 416
417 TRACE_EVENT_NESTABLE_ASYNC1(kTraceGroup, "base::File::Duplicate", this,
418 "path", unsafe_path_.AsUTF8Unsafe());
419
353 PlatformFile other_fd = dup(GetPlatformFile()); 420 PlatformFile other_fd = dup(GetPlatformFile());
354 if (other_fd == -1) 421 if (other_fd == -1)
355 return File(OSErrorToFileError(errno)); 422 return File(OSErrorToFileError(errno));
356 423
357 File other(other_fd); 424 File other(other_fd);
358 if (async()) 425 if (async())
359 other.async_ = true; 426 other.async_ = true;
360 return other.Pass(); 427 return other.Pass();
361 } 428 }
362 429
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
435 CHECK_EQ(file_memory_checksum_, computed_checksum) << "corrupted fd memory"; 502 CHECK_EQ(file_memory_checksum_, computed_checksum) << "corrupted fd memory";
436 } 503 }
437 504
438 void File::MemoryCheckingScopedFD::UpdateChecksum() { 505 void File::MemoryCheckingScopedFD::UpdateChecksum() {
439 ComputeMemoryChecksum(&file_memory_checksum_); 506 ComputeMemoryChecksum(&file_memory_checksum_);
440 } 507 }
441 508
442 // NaCl doesn't implement system calls to open files directly. 509 // NaCl doesn't implement system calls to open files directly.
443 #if !defined(OS_NACL) 510 #if !defined(OS_NACL)
444 // TODO(erikkay): does it make sense to support FLAG_EXCLUSIVE_* here? 511 // TODO(erikkay): does it make sense to support FLAG_EXCLUSIVE_* here?
445 void File::DoInitialize(const FilePath& name, uint32 flags) { 512 void File::DoInitialize(uint32 flags) {
446 ThreadRestrictions::AssertIOAllowed(); 513 ThreadRestrictions::AssertIOAllowed();
447 DCHECK(!IsValid()); 514 DCHECK(!IsValid());
448 515
516 TRACE_EVENT_NESTABLE_ASYNC1(kTraceGroup, "base::File::Initialize", this,
517 "path", unsafe_path_.AsUTF8Unsafe());
518
449 int open_flags = 0; 519 int open_flags = 0;
450 if (flags & FLAG_CREATE) 520 if (flags & FLAG_CREATE)
451 open_flags = O_CREAT | O_EXCL; 521 open_flags = O_CREAT | O_EXCL;
452 522
453 created_ = false; 523 created_ = false;
454 524
455 if (flags & FLAG_CREATE_ALWAYS) { 525 if (flags & FLAG_CREATE_ALWAYS) {
456 DCHECK(!open_flags); 526 DCHECK(!open_flags);
457 DCHECK(flags & FLAG_WRITE); 527 DCHECK(flags & FLAG_WRITE);
458 open_flags = O_CREAT | O_TRUNC; 528 open_flags = O_CREAT | O_TRUNC;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
490 else if (flags & FLAG_APPEND) 560 else if (flags & FLAG_APPEND)
491 open_flags |= O_APPEND | O_WRONLY; 561 open_flags |= O_APPEND | O_WRONLY;
492 562
493 COMPILE_ASSERT(O_RDONLY == 0, O_RDONLY_must_equal_zero); 563 COMPILE_ASSERT(O_RDONLY == 0, O_RDONLY_must_equal_zero);
494 564
495 int mode = S_IRUSR | S_IWUSR; 565 int mode = S_IRUSR | S_IWUSR;
496 #if defined(OS_CHROMEOS) 566 #if defined(OS_CHROMEOS)
497 mode |= S_IRGRP | S_IROTH; 567 mode |= S_IRGRP | S_IROTH;
498 #endif 568 #endif
499 569
500 int descriptor = HANDLE_EINTR(open(name.value().c_str(), open_flags, mode)); 570 int descriptor =
571 HANDLE_EINTR(open(unsafe_path_.value().c_str(), open_flags, mode));
501 572
502 if (flags & FLAG_OPEN_ALWAYS) { 573 if (flags & FLAG_OPEN_ALWAYS) {
503 if (descriptor < 0) { 574 if (descriptor < 0) {
504 open_flags |= O_CREAT; 575 open_flags |= O_CREAT;
505 if (flags & FLAG_EXCLUSIVE_READ || flags & FLAG_EXCLUSIVE_WRITE) 576 if (flags & FLAG_EXCLUSIVE_READ || flags & FLAG_EXCLUSIVE_WRITE)
506 open_flags |= O_EXCL; // together with O_CREAT implies O_NOFOLLOW 577 open_flags |= O_EXCL; // together with O_CREAT implies O_NOFOLLOW
507 578
508 descriptor = HANDLE_EINTR(open(name.value().c_str(), open_flags, mode)); 579 descriptor =
580 HANDLE_EINTR(open(unsafe_path_.value().c_str(), open_flags, mode));
509 if (descriptor >= 0) 581 if (descriptor >= 0)
510 created_ = true; 582 created_ = true;
511 } 583 }
512 } 584 }
513 585
514 if (descriptor < 0) { 586 if (descriptor < 0) {
515 error_details_ = File::OSErrorToFileError(errno); 587 error_details_ = File::OSErrorToFileError(errno);
516 return; 588 return;
517 } 589 }
518 590
519 if (flags & (FLAG_CREATE_ALWAYS | FLAG_CREATE)) 591 if (flags & (FLAG_CREATE_ALWAYS | FLAG_CREATE))
520 created_ = true; 592 created_ = true;
521 593
522 if (flags & FLAG_DELETE_ON_CLOSE) 594 if (flags & FLAG_DELETE_ON_CLOSE)
523 unlink(name.value().c_str()); 595 unlink(unsafe_path_.value().c_str());
524 596
525 async_ = ((flags & FLAG_ASYNC) == FLAG_ASYNC); 597 async_ = ((flags & FLAG_ASYNC) == FLAG_ASYNC);
526 error_details_ = FILE_OK; 598 error_details_ = FILE_OK;
527 file_.reset(descriptor); 599 file_.reset(descriptor);
528 } 600 }
529 #endif // !defined(OS_NACL) 601 #endif // !defined(OS_NACL)
530 602
531 bool File::DoFlush() {
532 ThreadRestrictions::AssertIOAllowed();
533 DCHECK(IsValid());
534 #if defined(OS_NACL)
535 NOTIMPLEMENTED(); // NaCl doesn't implement fsync.
536 return true;
537 #elif defined(OS_LINUX) || defined(OS_ANDROID)
538 return !HANDLE_EINTR(fdatasync(file_.get()));
539 #else
540 return !HANDLE_EINTR(fsync(file_.get()));
541 #endif
542 }
543
544 void File::SetPlatformFile(PlatformFile file) {
545 DCHECK(!file_.is_valid());
546 file_.reset(file);
547 }
548
549 } // namespace base 603 } // namespace base
OLDNEW
« no previous file with comments | « base/files/file.cc ('k') | base/files/file_win.cc » ('j') | base/trace_event/trace_event.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698