1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "storaged" 18 19 #include <dirent.h> 20 #include <fcntl.h> 21 #include <inttypes.h> 22 #include <linux/time.h> 23 #include <stdint.h> 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <sys/stat.h> 28 #include <time.h> 29 #include <unistd.h> 30 31 #include <iomanip> 32 #include <sstream> 33 #include <string> 34 #include <unordered_map> 35 36 #include <android-base/file.h> 37 #include <android-base/logging.h> 38 #include <android-base/stringprintf.h> 39 #include <android-base/strings.h> 40 #include <log/log_event_list.h> 41 42 #include <storaged.h> 43 #include <storaged_utils.h> 44 45 bool cmp_uid_info(const UidInfo& l, const UidInfo& r) { 46 // Compare background I/O first. 47 for (int i = UID_STATS - 1; i >= 0; i--) { 48 uint64_t l_bytes = l.io[i].read_bytes + l.io[i].write_bytes; 49 uint64_t r_bytes = r.io[i].read_bytes + r.io[i].write_bytes; 50 uint64_t l_chars = l.io[i].rchar + l.io[i].wchar; 51 uint64_t r_chars = r.io[i].rchar + r.io[i].wchar; 52 53 if (l_bytes != r_bytes) { 54 return l_bytes > r_bytes; 55 } 56 if (l_chars != r_chars) { 57 return l_chars > r_chars; 58 } 59 } 60 61 return l.name < r.name; 62 } 63 64 void sort_running_uids_info(std::vector<UidInfo> &uids) { 65 std::sort(uids.begin(), uids.end(), cmp_uid_info); 66 } 67 68 // Logging functions 69 void log_console_running_uids_info(const std::vector<UidInfo>& uids, bool flag_dump_task) { 70 printf("name/uid fg_rchar fg_wchar fg_rbytes fg_wbytes " 71 "bg_rchar bg_wchar bg_rbytes bg_wbytes fg_fsync bg_fsync\n"); 72 73 for (const auto& uid : uids) { 74 printf("%s %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 75 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 "\n", 76 uid.name.c_str(), 77 uid.io[0].rchar, uid.io[0].wchar, uid.io[0].read_bytes, uid.io[0].write_bytes, 78 uid.io[1].rchar, uid.io[1].wchar, uid.io[1].read_bytes, uid.io[1].write_bytes, 79 uid.io[0].fsync, uid.io[1].fsync); 80 if (flag_dump_task) { 81 for (const auto& task_it : uid.tasks) { 82 const task_info& task = task_it.second; 83 printf("-> %s %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 84 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 "\n", 85 task.comm.c_str(), 86 task.io[0].rchar, task.io[0].wchar, task.io[0].read_bytes, task.io[0].write_bytes, 87 task.io[1].rchar, task.io[1].wchar, task.io[1].read_bytes, task.io[1].write_bytes, 88 task.io[0].fsync, task.io[1].fsync); 89 } 90 } 91 } 92 fflush(stdout); 93 } 94 95 void log_console_perf_history(const vector<int>& perf_history) { 96 if (perf_history.size() < 3 || 97 perf_history.size() != perf_history[0] + 98 perf_history[1] + 99 perf_history[2] + (size_t)3) { 100 return; 101 } 102 103 printf("\nI/O perf history (KB/s) : most_recent <--------- least_recent \n"); 104 105 std::stringstream line; 106 int start = 3; 107 int end = 3 + perf_history[0]; 108 std::copy(perf_history.begin() + start, perf_history.begin() + end, 109 std::ostream_iterator<int>(line, " ")); 110 printf("last 24 hours : %s\n", line.str().c_str()); 111 112 line.str(""); 113 start = end; 114 end += perf_history[1]; 115 std::copy(perf_history.begin() + start, perf_history.begin() + end, 116 std::ostream_iterator<int>(line, " ")); 117 printf("last 7 days : %s\n", line.str().c_str()); 118 119 line.str(""); 120 start = end; 121 std::copy(perf_history.begin() + start, perf_history.end(), 122 std::ostream_iterator<int>(line, " ")); 123 printf("last 52 weeks : %s\n", line.str().c_str()); 124 } 125 126 map<string, io_usage> merge_io_usage(const vector<uid_record>& entries) { 127 map<string, io_usage> merged_entries; 128 for (const auto& record : entries) { 129 merged_entries[record.name] += record.ios.uid_ios; 130 } 131 return merged_entries; 132 } 133