Index: base/process/process_metrics_linux.cc |
diff --git a/base/process/process_metrics_linux.cc b/base/process/process_metrics_linux.cc |
index 0e0d0124c5f4d57b84cadf2ae19af6fc9a7a7fe5..3abbd53082f3972c2e327c6e529560df0aff6eed 100644 |
--- a/base/process/process_metrics_linux.cc |
+++ b/base/process/process_metrics_linux.cc |
@@ -421,6 +421,57 @@ const size_t kMemInactiveAnonIndex = 25; |
const size_t kMemActiveFileIndex = 28; |
const size_t kMemInactiveFileIndex = 31; |
+// The format of /proc/diskstats is: |
+// Device major number |
+// Device minor number |
+// Device name |
+// Field 1 -- # of reads completed |
+// This is the total number of reads completed successfully. |
+// Field 2 -- # of reads merged, field 6 -- # of writes merged |
+// Reads and writes which are adjacent to each other may be merged for |
+// efficiency. Thus two 4K reads may become one 8K read before it is |
+// ultimately handed to the disk, and so it will be counted (and queued) |
+// as only one I/O. This field lets you know how often this was done. |
+// Field 3 -- # of sectors read |
+// This is the total number of sectors read successfully. |
+// Field 4 -- # of milliseconds spent reading |
+// This is the total number of milliseconds spent by all reads (as |
+// measured from __make_request() to end_that_request_last()). |
+// Field 5 -- # of writes completed |
+// This is the total number of writes completed successfully. |
+// Field 6 -- # of writes merged |
+// See the description of field 2. |
+// Field 7 -- # of sectors written |
+// This is the total number of sectors written successfully. |
+// Field 8 -- # of milliseconds spent writing |
+// This is the total number of milliseconds spent by all writes (as |
+// measured from __make_request() to end_that_request_last()). |
+// Field 9 -- # of I/Os currently in progress |
+// The only field that should go to zero. Incremented as requests are |
+// given to appropriate struct request_queue and decremented as they |
+// finish. |
+// Field 10 -- # of milliseconds spent doing I/Os |
+// This field increases so long as field 9 is nonzero. |
+// Field 11 -- weighted # of milliseconds spent doing I/Os |
+// This field is incremented at each I/O start, I/O completion, I/O |
+// merge, or read of these stats by the number of I/Os in progress |
+// (field 9) times the number of milliseconds spent doing I/O since the |
+// last update of this field. This can provide an easy measure of both |
+// I/O completion time and the backlog that may be accumulating. |
+ |
+const size_t kDiskDriveName = 2; |
+const size_t kDiskReads = 3; |
+const size_t kDiskReadsMerged = 4; |
+const size_t kDiskSectorsRead = 5; |
+const size_t kDiskReadTime = 6; |
+const size_t kDiskWrites = 7; |
+const size_t kDiskWritesMerged = 8; |
+const size_t kDiskSectorsWritten = 9; |
+const size_t kDiskWriteTime = 10; |
+const size_t kDiskIO = 11; |
+const size_t kDiskIOTime = 12; |
+const size_t kDiskWeightedIOTime = 13; |
+ |
} // namespace |
SystemMemoryInfoKB::SystemMemoryInfoKB() |
@@ -527,6 +578,124 @@ bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) { |
return true; |
} |
+SystemDiskInfo::SystemDiskInfo() { |
+ reads = 0; |
+ reads_merged = 0; |
+ sectors_read = 0; |
+ read_time = 0; |
+ writes = 0; |
+ writes_merged = 0; |
+ sectors_written = 0; |
+ write_time = 0; |
+ io = 0; |
+ io_time = 0; |
+ weighted_io_time = 0; |
+} |
+ |
+bool IsValidDiskName(const std::string& candidate) { |
+ if (candidate.length() < 3) |
+ return false; |
+ if (candidate.substr(0,2) == "sd" || candidate.substr(0,2) == "hd") { |
+ // [sh]d[a-z]+ case |
+ for (size_t i = 2; i < candidate.length(); i++) { |
+ if (!islower(candidate[i])) |
+ return false; |
+ } |
+ } else { |
+ if (candidate.length() < 7) { |
+ return false; |
+ } |
+ if (candidate.substr(0,6) == "mmcblk") { |
+ // mmcblk[0-9]+ case |
+ for (size_t i = 6; i < candidate.length(); i++) { |
+ if (!isdigit(candidate[i])) |
+ return false; |
+ } |
+ } else { |
+ return false; |
+ } |
+ } |
+ |
+ return true; |
+} |
+ |
+bool GetSystemDiskInfo(SystemDiskInfo* diskinfo) { |
+ // Synchronously reading files in /proc is safe. |
+ ThreadRestrictions::ScopedAllowIO allow_io; |
+ |
+ FilePath diskinfo_file("/proc/diskstats"); |
+ std::string diskinfo_data; |
+ if (!ReadFileToString(diskinfo_file, &diskinfo_data)) { |
+ DLOG(WARNING) << "Failed to open " << diskinfo_file.value(); |
+ return false; |
+ } |
+ |
+ std::vector<std::string> diskinfo_lines; |
+ size_t line_count = Tokenize(diskinfo_data, "\n", &diskinfo_lines); |
+ if (line_count == 0) { |
+ DLOG(WARNING) << "No lines found"; |
+ return false; |
+ } |
+ |
+ diskinfo->reads = 0; |
+ diskinfo->reads_merged = 0; |
+ diskinfo->sectors_read = 0; |
+ diskinfo->read_time = 0; |
+ diskinfo->writes = 0; |
+ diskinfo->writes_merged = 0; |
+ diskinfo->sectors_written = 0; |
+ diskinfo->write_time = 0; |
+ diskinfo->io = 0; |
+ diskinfo->io_time = 0; |
+ diskinfo->weighted_io_time = 0; |
+ |
+ uint64 reads = 0; |
+ uint64 reads_merged = 0; |
+ uint64 sectors_read = 0; |
+ uint64 read_time = 0; |
+ uint64 writes = 0; |
+ uint64 writes_merged = 0; |
+ uint64 sectors_written = 0; |
+ uint64 write_time = 0; |
+ uint64 io = 0; |
+ uint64 io_time = 0; |
+ uint64 weighted_io_time = 0; |
+ |
+ for (size_t i = 0; i < line_count; i++) { |
+ std::vector<std::string> disk_fields; |
+ SplitStringAlongWhitespace(diskinfo_lines[i], &disk_fields); |
+ |
+ // Fields may have overflowed and reset to zero. |
+ if (IsValidDiskName(disk_fields[kDiskDriveName])) { |
+ StringToUint64(disk_fields[kDiskReads], &reads); |
+ StringToUint64(disk_fields[kDiskReadsMerged], &reads_merged); |
+ StringToUint64(disk_fields[kDiskSectorsRead], §ors_read); |
+ StringToUint64(disk_fields[kDiskReadTime], &read_time); |
+ StringToUint64(disk_fields[kDiskWrites], &writes); |
+ StringToUint64(disk_fields[kDiskWritesMerged], &writes_merged); |
+ StringToUint64(disk_fields[kDiskSectorsWritten], §ors_written); |
+ StringToUint64(disk_fields[kDiskWriteTime], &write_time); |
+ StringToUint64(disk_fields[kDiskIO], &io); |
+ StringToUint64(disk_fields[kDiskIOTime], &io_time); |
+ StringToUint64(disk_fields[kDiskWeightedIOTime], &weighted_io_time); |
+ |
+ diskinfo->reads += reads; |
+ diskinfo->reads_merged += reads_merged; |
+ diskinfo->sectors_read += sectors_read; |
+ diskinfo->read_time += read_time; |
+ diskinfo->writes += writes; |
+ diskinfo->writes_merged += writes_merged; |
+ diskinfo->sectors_written += sectors_written; |
+ diskinfo->write_time += write_time; |
+ diskinfo->io += io; |
+ diskinfo->io_time += io_time; |
+ diskinfo->weighted_io_time += weighted_io_time; |
+ } |
+ } |
+ |
+ return true; |
+} |
+ |
#if defined(OS_CHROMEOS) |
void GetSwapInfo(SwapInfo* swap_info) { |
// Synchronously reading files in /sys/block/zram0 is safe. |