• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     std::unique_ptr<storage_info_t> storage_info;
260 public:
261     storaged_t(void);
~storaged_t()262     ~storaged_t() {}
263     void event(void);
264     void event_checked(void);
pause(void)265     void pause(void) {
266         sleep(mConfig.periodic_chores_interval_unit);
267     }
268 
get_starttime(void)269     time_t get_starttime(void) {
270         return mStarttime;
271     }
272 
get_uids(void)273     std::unordered_map<uint32_t, struct uid_info> get_uids(void) {
274         return mUidm.get_uid_io_stats();
275     }
get_uid_records(double hours,uint64_t threshold,bool force_report)276     std::map<uint64_t, struct uid_records> get_uid_records(
277             double hours, uint64_t threshold, bool force_report) {
278         return mUidm.dump(hours, threshold, force_report);
279     }
update_uid_io_interval(int interval)280     void update_uid_io_interval(int interval) {
281         if (interval >= DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO_LIMIT) {
282             mConfig.periodic_chores_interval_uid_io = interval;
283         }
284     }
285 
286     void init_battery_service();
287     virtual void batteryPropertiesChanged(struct BatteryProperties props);
288     void binderDied(const wp<IBinder>& who);
289 
290     void report_storage_info();
291 };
292 
293 // Eventlog tag
294 // The content must match the definition in EventLogTags.logtags
295 #define EVENTLOGTAG_DISKSTATS ( 2732 )
296 #define EVENTLOGTAG_EMMCINFO ( 2733 )
297 #define EVENTLOGTAG_UID_IO_ALERT ( 2734 )
298 
299 #endif /* _STORAGED_H_ */
300