Home | History | Annotate | Download | only in include
      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:
    119     lock_t(sem_t* sem) {
    120         mSem = sem;
    121         sem_wait(mSem);
    122     }
    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:
    134     stream_stats() : mSum(0), mSquareSum(0), mCnt(0) {};
    135     ~stream_stats() {};
    136     double get_mean() {
    137         return mSum / mCnt;
    138     }
    139     double get_std() {
    140         return sqrt(mSquareSum / mCnt - mSum * mSum / (mCnt * mCnt));
    141     }
    142     void add(uint32_t num) {
    143         mSum += (double)num;
    144         mSquareSum += (double)num * (double)num;
    145         mCnt++;
    146     }
    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) :
    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:
    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 
    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);
    261     ~storaged_t() {}
    262     void event(void);
    263     void event_checked(void);
    264     void pause(void) {
    265         sleep(mConfig.periodic_chores_interval_unit);
    266     }
    267 
    268     time_t get_starttime(void) {
    269         return mStarttime;
    270     }
    271 
    272     std::unordered_map<uint32_t, struct uid_info> get_uids(void) {
    273         return mUidm.get_uid_io_stats();
    274     }
    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     }
    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