Chromium Code Reviews
|
| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/fragmentation_checker_win.h" | |
| 6 | |
| 7 #include <windows.h> | |
| 8 #include <winioctl.h> | |
| 9 | |
| 10 #include "base/at_exit.h" | |
| 11 #include "base/basictypes.h" | |
| 12 #include "base/command_line.h" | |
| 13 #include "base/file_util.h" | |
| 14 #include "base/logging.h" | |
| 15 #include "base/metrics/histogram.h" | |
| 16 #include "base/path_service.h" | |
| 17 | |
| 18 namespace { | |
| 19 | |
| 20 size_t kMaxBufferSize = 1 << 20; | |
|
grt (UTC plus 2)
2011/09/30 18:44:14
const size_t...
robertshield
2011/09/30 19:53:00
Done.
| |
| 21 | |
| 22 struct FileExtentData { | |
| 23 int number_of_extents; | |
| 24 int64 virtual_cluster_span; | |
| 25 }; | |
| 26 | |
| 27 size_t ComputeRetrievalPointersBufferSize(int number_of_extents) { | |
| 28 return sizeof(RETRIEVAL_POINTERS_BUFFER) + | |
| 29 (number_of_extents - 1) * (sizeof(LARGE_INTEGER) * 2); | |
|
grt (UTC plus 2)
2011/09/30 18:44:14
indentation
grt (UTC plus 2)
2011/09/30 18:44:14
is it possible to replace sizeof(LARGE_INTEGER) *
robertshield
2011/09/30 19:53:00
Done.
robertshield
2011/09/30 19:53:00
Done.
| |
| 30 } | |
| 31 | |
| 32 bool DumpFileExtents(const FilePath& file_path, | |
| 33 FileExtentData* file_extent_data) { | |
| 34 DCHECK(file_extent_data); | |
| 35 if (!file_util::PathExists(file_path)) { | |
|
grt (UTC plus 2)
2011/09/30 18:44:14
why do this extra check? CreatePlatformFile shoul
robertshield
2011/09/30 19:53:00
Done.
| |
| 36 LOG(ERROR) << "File not found."; | |
| 37 return false; | |
| 38 } | |
| 39 | |
| 40 bool success = false; | |
| 41 | |
| 42 base::PlatformFileError error_code = base::PLATFORM_FILE_ERROR_FAILED; | |
| 43 bool created = false; | |
| 44 base::PlatformFile file_handle = CreatePlatformFile( | |
| 45 file_path, | |
| 46 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ, | |
| 47 &created, | |
| 48 &error_code); | |
| 49 if (error_code == base::PLATFORM_FILE_OK && !created) { | |
| 50 STARTING_VCN_INPUT_BUFFER starting_vcn_input_buffer = {0}; | |
| 51 | |
| 52 // Compute an output size capable of holding 16 extents at first. This may | |
| 53 // fail when the number of extents exceeds 16, in which case we make | |
| 54 // a bigger buffer up to kMaxBufferSize. | |
| 55 int number_of_extents = 16; | |
| 56 std::vector<BYTE> retrieval_pointers_buffer; | |
|
grt (UTC plus 2)
2011/09/30 18:44:14
uint8 rather than win-specific BYTE?
robertshield
2011/09/30 19:53:00
Done, although this file is (and can only be) Wind
| |
| 57 | |
| 58 size_t output_size = ComputeRetrievalPointersBufferSize(number_of_extents); | |
|
grt (UTC plus 2)
2011/09/30 18:44:14
do this computation before line 56, then change li
robertshield
2011/09/30 19:53:00
Done.
| |
| 59 retrieval_pointers_buffer.resize(output_size); | |
| 60 | |
| 61 DWORD bytes_returned = 0; | |
| 62 | |
| 63 bool result = false; | |
| 64 do { | |
| 65 SetLastError(ERROR_SUCCESS); | |
|
grt (UTC plus 2)
2011/09/30 18:44:14
this is extremely odd. please document why this i
robertshield
2011/09/30 19:53:00
rejiggered as discussed.
| |
| 66 result = DeviceIoControl( | |
|
grt (UTC plus 2)
2011/09/30 18:44:14
MSDN says that the call fails (returns 0) if the b
robertshield
2011/09/30 19:53:00
I found documentation suggesting using the GLE cod
| |
| 67 file_handle, | |
| 68 FSCTL_GET_RETRIEVAL_POINTERS, | |
| 69 reinterpret_cast<void*>(&starting_vcn_input_buffer), | |
| 70 sizeof(starting_vcn_input_buffer), | |
| 71 reinterpret_cast<void*>(&retrieval_pointers_buffer[0]), | |
| 72 retrieval_pointers_buffer.size(), | |
| 73 &bytes_returned, | |
| 74 NULL) == TRUE; | |
|
grt (UTC plus 2)
2011/09/30 18:44:14
== TRUE -> != 0
MSDN says it returns zero/non-zero
robertshield
2011/09/30 19:53:00
My version of WinBase.h says it returns FALSE/TRUE
| |
| 75 | |
| 76 DWORD last_error = GetLastError(); | |
|
grt (UTC plus 2)
2011/09/30 18:44:14
this is extremely odd. according to MSDN, you wou
robertshield
2011/09/30 19:53:00
Changed as discussed.
| |
| 77 if (last_error == ERROR_MORE_DATA) { | |
| 78 // Grow the extents we can handle | |
| 79 number_of_extents *= 2; | |
| 80 output_size = ComputeRetrievalPointersBufferSize(number_of_extents); | |
| 81 | |
| 82 if (output_size > kMaxBufferSize) { | |
| 83 LOG(ERROR) << "FSCTL_GET_RETRIEVAL_POINTERS output buffer exceeded " | |
| 84 "maximum size."; | |
| 85 result = false; | |
| 86 break; | |
| 87 } | |
| 88 | |
| 89 retrieval_pointers_buffer.clear(); | |
| 90 retrieval_pointers_buffer.resize(output_size); | |
|
grt (UTC plus 2)
2011/09/30 18:44:14
replace these two lines with a call to .assign(out
robertshield
2011/09/30 19:53:00
Done.
| |
| 91 } else { | |
| 92 if (!result) { | |
| 93 LOG(ERROR) << "FSCTL_GET_RETRIEVAL_POINTERS failed. gle = " | |
|
grt (UTC plus 2)
2011/09/30 18:44:14
PLOG(ERROR) << "FSCTL_GET_RETRIEVAL_POINTERS faile
robertshield
2011/09/30 19:53:00
Done.
| |
| 94 << last_error; | |
| 95 } | |
| 96 break; | |
| 97 } | |
| 98 } while (true); | |
| 99 | |
| 100 if (result) { | |
| 101 RETRIEVAL_POINTERS_BUFFER* retrieval_pointers = | |
| 102 reinterpret_cast<RETRIEVAL_POINTERS_BUFFER*>( | |
| 103 &retrieval_pointers_buffer[0]); | |
| 104 DWORD extent_count = retrieval_pointers->ExtentCount; | |
| 105 LARGE_INTEGER extent_cluster_range = {0}; | |
| 106 if (extent_count > 0) { | |
| 107 extent_cluster_range.QuadPart = | |
| 108 retrieval_pointers->Extents[extent_count - 1].NextVcn.QuadPart; | |
| 109 extent_cluster_range.QuadPart -= | |
| 110 retrieval_pointers->StartingVcn.QuadPart; | |
| 111 } | |
| 112 | |
| 113 file_extent_data->number_of_extents = extent_count; | |
|
grt (UTC plus 2)
2011/09/30 18:44:14
this does (in essence) a uint32 -> int conversion.
robertshield
2011/09/30 19:53:00
Done.
| |
| 114 file_extent_data->virtual_cluster_span = extent_cluster_range.QuadPart; | |
| 115 success = true; | |
| 116 } else { | |
| 117 LOG(ERROR) << "Failed to retrieve extents."; | |
| 118 } | |
| 119 } | |
| 120 | |
| 121 return success; | |
| 122 } | |
| 123 | |
| 124 } // namespace | |
| 125 | |
| 126 namespace fragmentation_checker { | |
| 127 | |
| 128 void RecordFragmentationMetricForCurrentModule() { | |
| 129 FilePath module_path; | |
|
grt (UTC plus 2)
2011/09/30 18:44:14
#include "base/file_path.h" for this
robertshield
2011/09/30 19:53:00
Done.
| |
| 130 if (PathService::Get(base::FILE_MODULE, &module_path)) { | |
| 131 FileExtentData file_extent_data = {0}; | |
| 132 if (DumpFileExtents(module_path, &file_extent_data)) { | |
| 133 UMA_HISTOGRAM_COUNTS("Fragmentation.ModuleExtents", | |
| 134 file_extent_data.number_of_extents); | |
| 135 UMA_HISTOGRAM_COUNTS("Fragmentation.ModuleSpan", | |
| 136 file_extent_data.virtual_cluster_span); | |
|
grt (UTC plus 2)
2011/09/30 18:44:14
1) this macro sets the max sample to 1000000, whic
robertshield
2011/09/30 19:53:00
As discussed, while reading the documentation agai
| |
| 137 } | |
| 138 } else { | |
| 139 NOTREACHED() << "Could not get path to current module."; | |
| 140 } | |
| 141 } | |
| 142 | |
| 143 } // namespace fragmentation_checker | |
| OLD | NEW |