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 #ifndef _STORAGED_H_ 18 #define _STORAGED_H_ 19 20 #include <semaphore.h> 21 #include <stdint.h> 22 #include <time.h> 23 24 #include <queue> 25 #include <string> 26 #include <unordered_map> 27 #include <vector> 28 29 #include <batteryservice/IBatteryPropertiesListener.h> 30 #include <batteryservice/IBatteryPropertiesRegistrar.h> 31 32 #include "storaged_info.h" 33 #include "storaged_uid_monitor.h" 34 35 using namespace android; 36 37 #define FRIEND_TEST(test_case_name, test_name) \ 38 friend class test_case_name##_##test_name##_Test 39 40 /* For debug */ 41 #ifdef DEBUG 42 #define debuginfo(fmt, ...) \ 43 do {printf("%s():\t" fmt "\t[%s:%d]\n", __FUNCTION__, ##__VA_ARGS__, __FILE__, __LINE__);} \ 44 while(0) 45 #else 46 #define debuginfo(...) 47 #endif 48 49 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 50 51 #define SECTOR_SIZE ( 512 ) 52 #define SEC_TO_MSEC ( 1000 ) 53 #define MSEC_TO_USEC ( 1000 ) 54 #define USEC_TO_NSEC ( 1000 ) 55 #define SEC_TO_USEC ( 1000000 ) 56 #define HOUR_TO_SEC ( 3600 ) 57 #define DAY_TO_SEC ( 3600 * 24 ) 58 59 // number of attributes diskstats has 60 #define DISK_STATS_SIZE ( 11 ) 61 // maximum size limit of a stats file 62 #define DISK_STATS_FILE_MAX_SIZE ( 256 ) 63 #define DISK_STATS_IO_IN_FLIGHT_IDX ( 8 ) 64 struct disk_stats { 65 /* It will be extremely unlikely for any of the following entries to overflow. 66 * For read_bytes(which will be greater than any of the following entries), it 67 * will take 27 years to overflow uint64_t at the reading rate of 20GB/s, which 68 * is the peak memory transfer rate for current memory. 69 * The diskstats entries (first 11) need to be at top in this structure _after_ 70 * compiler's optimization. 71 */ 72 uint64_t read_ios; // number of read I/Os processed 73 uint64_t read_merges; // number of read I/Os merged with in-queue I/Os 74 uint64_t read_sectors; // number of sectors read 75 uint64_t read_ticks; // total wait time for read requests 76 uint64_t write_ios; // number of write I/Os processed 77 uint64_t write_merges; // number of write I/Os merged with in-queue I/Os 78 uint64_t write_sectors; // number of sectors written 79 uint64_t write_ticks; // total wait time for write requests 80 uint64_t io_in_flight; // number of I/Os currently in flight 81 uint64_t io_ticks; // total time this block device has been active 82 uint64_t io_in_queue; // total wait time for all requests 83 84 uint64_t start_time; // monotonic time accounting starts 85 uint64_t end_time; // monotonic time accounting ends 86 uint32_t counter; // private counter for accumulate calculations 87 double io_avg; // average io_in_flight for accumulate calculations 88 }; 89 90 91 92 struct disk_perf { 93 uint32_t read_perf; // read speed (kbytes/s) 94 uint32_t read_ios; // read I/Os per second 95 uint32_t write_perf; // write speed (kbytes/s) 96 uint32_t write_ios; // write I/Os per second 97 uint32_t queue; // I/Os in queue 98 }; 99 100 #define CMD_MAX_LEN ( 64 ) 101 struct task_info { 102 uint32_t pid; // task id 103 uint64_t rchar; // characters read 104 uint64_t wchar; // characters written 105 uint64_t syscr; // read syscalls 106 uint64_t syscw; // write syscalls 107 uint64_t read_bytes; // bytes read (from storage layer) 108 uint64_t write_bytes; // bytes written (to storage layer) 109 uint64_t cancelled_write_bytes; // cancelled write byte by truncate 110 111 uint64_t starttime; // start time of task 112 113 char cmd[CMD_MAX_LEN]; // filename of the executable 114 }; 115 116 class lock_t { 117 sem_t* mSem; 118 public: lock_t(sem_t * sem)119 lock_t(sem_t* sem) { 120 mSem = sem; 121 sem_wait(mSem); 122 } ~lock_t()123 ~lock_t() { 124 sem_post(mSem); 125 } 126 }; 127 128 class stream_stats { 129 private: 130 double mSum; 131 double mSquareSum; 132 uint32_t mCnt; 133 public: stream_stats()134 stream_stats() : mSum(0), mSquareSum(0), mCnt(0) {}; ~stream_stats()135 ~stream_stats() {}; get_mean()136 double get_mean() { 137 return mSum / mCnt; 138 } get_std()139 double get_std() { 140 return sqrt(mSquareSum / mCnt - mSum * mSum / (mCnt * mCnt)); 141 } add(uint32_t num)142 void add(uint32_t num) { 143 mSum += (double)num; 144 mSquareSum += (double)num * (double)num; 145 mCnt++; 146 } evict(uint32_t num)147 void evict(uint32_t num) { 148 if (mSum < num || mSquareSum < (double)num * (double)num) return; 149 mSum -= (double)num; 150 mSquareSum -= (double)num * (double)num; 151 mCnt--; 152 } 153 }; 154 155 #define MMC_DISK_STATS_PATH "/sys/block/mmcblk0/stat" 156 #define SDA_DISK_STATS_PATH "/sys/block/sda/stat" 157 #define EMMC_ECSD_PATH "/d/mmc0/mmc0:0001/ext_csd" 158 #define UID_IO_STATS_PATH "/proc/uid_io/stats" 159 160 class disk_stats_monitor { 161 private: 162 FRIEND_TEST(storaged_test, disk_stats_monitor); 163 const char* DISK_STATS_PATH; 164 struct disk_stats mPrevious; 165 struct disk_stats mAccumulate; 166 bool mStall; 167 std::queue<struct disk_perf> mBuffer; 168 struct { 169 stream_stats read_perf; // read speed (bytes/s) 170 stream_stats read_ios; // read I/Os per second 171 stream_stats write_perf; // write speed (bytes/s) 172 stream_stats write_ios; // write I/O per second 173 stream_stats queue; // I/Os in queue 174 } mStats; 175 bool mValid; 176 const uint32_t mWindow; 177 const double mSigma; 178 struct disk_perf mMean; 179 struct disk_perf mStd; 180 181 void update_mean(); 182 void update_std(); 183 void add(struct disk_perf* perf); 184 void evict(struct disk_perf* perf); 185 bool detect(struct disk_perf* perf); 186 187 void update(struct disk_stats* stats); 188 189 public: 190 disk_stats_monitor(uint32_t window_size = 5, double sigma = 1.0) : mStall(false)191 mStall(false), 192 mValid(false), 193 mWindow(window_size), 194 mSigma(sigma) { 195 memset(&mPrevious, 0, sizeof(mPrevious)); 196 memset(&mMean, 0, sizeof(mMean)); 197 memset(&mStd, 0, sizeof(mStd)); 198 199 if (access(MMC_DISK_STATS_PATH, R_OK) >= 0) { 200 DISK_STATS_PATH = MMC_DISK_STATS_PATH; 201 } else { 202 DISK_STATS_PATH = SDA_DISK_STATS_PATH; 203 } 204 } 205 void update(void); 206 }; 207 208 class disk_stats_publisher { 209 private: 210 FRIEND_TEST(storaged_test, disk_stats_publisher); 211 const char* DISK_STATS_PATH; 212 struct disk_stats mAccumulate; 213 struct disk_stats mPrevious; 214 public: disk_stats_publisher(void)215 disk_stats_publisher(void) { 216 memset(&mAccumulate, 0, sizeof(struct disk_stats)); 217 memset(&mPrevious, 0, sizeof(struct disk_stats)); 218 219 if (access(MMC_DISK_STATS_PATH, R_OK) >= 0) { 220 DISK_STATS_PATH = MMC_DISK_STATS_PATH; 221 } else { 222 DISK_STATS_PATH = SDA_DISK_STATS_PATH; 223 } 224 } 225 ~disk_stats_publisher(void)226 ~disk_stats_publisher(void) {} 227 void publish(void); 228 void update(void); 229 }; 230 231 // Periodic chores intervals in seconds 232 #define DEFAULT_PERIODIC_CHORES_INTERVAL_UNIT ( 60 ) 233 #define DEFAULT_PERIODIC_CHORES_INTERVAL_DISK_STATS_PUBLISH ( 3600 ) 234 #define DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO ( 3600 ) 235 #define DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO_LIMIT (300) 236 237 // UID IO threshold in bytes 238 #define DEFAULT_PERIODIC_CHORES_UID_IO_THRESHOLD ( 1024 * 1024 * 1024ULL ) 239 240 struct storaged_config { 241 int periodic_chores_interval_unit; 242 int periodic_chores_interval_disk_stats_publish; 243 int periodic_chores_interval_uid_io; 244 bool proc_uid_io_available; // whether uid_io is accessible 245 bool diskstats_available; // whether diskstats is accessible 246 int event_time_check_usec; // check how much cputime spent in event loop 247 }; 248 249 class storaged_t : public BnBatteryPropertiesListener, 250 public IBinder::DeathRecipient { 251 private: 252 time_t mTimer; 253 storaged_config mConfig; 254 disk_stats_publisher mDiskStats; 255 disk_stats_monitor mDsm; 256 uid_monitor mUidm; 257 time_t mStarttime; 258 sp<IBatteryPropertiesRegistrar> battery_properties; 259 public: 260 storaged_t(void); ~storaged_t()261 ~storaged_t() {} 262 void event(void); 263 void event_checked(void); pause(void)264 void pause(void) { 265 sleep(mConfig.periodic_chores_interval_unit); 266 } 267 get_starttime(void)268 time_t get_starttime(void) { 269 return mStarttime; 270 } 271 get_uids(void)272 std::unordered_map<uint32_t, struct uid_info> get_uids(void) { 273 return mUidm.get_uid_io_stats(); 274 } get_uid_records(double hours,uint64_t threshold,bool force_report)275 std::map<uint64_t, struct uid_records> get_uid_records( 276 double hours, uint64_t threshold, bool force_report) { 277 return mUidm.dump(hours, threshold, force_report); 278 } update_uid_io_interval(int interval)279 void update_uid_io_interval(int interval) { 280 if (interval >= DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO_LIMIT) { 281 mConfig.periodic_chores_interval_uid_io = interval; 282 } 283 } 284 285 void init_battery_service(); 286 virtual void batteryPropertiesChanged(struct BatteryProperties props); 287 void binderDied(const wp<IBinder>& who); 288 }; 289 290 // Eventlog tag 291 // The content must match the definition in EventLogTags.logtags 292 #define EVENTLOGTAG_DISKSTATS ( 2732 ) 293 #define EVENTLOGTAG_EMMCINFO ( 2733 ) 294 #define EVENTLOGTAG_UID_IO_ALERT ( 2734 ) 295 296 #endif /* _STORAGED_H_ */ 297