Loading storaged/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ cc_library_static { srcs: [ "storaged.cpp", "storaged_diskstats.cpp", "storaged_info.cpp", "storaged_service.cpp", "storaged_utils.cpp", Loading storaged/include/storaged.h +4 −171 Original line number Diff line number Diff line Loading @@ -29,23 +29,15 @@ #include <batteryservice/IBatteryPropertiesListener.h> #include <batteryservice/IBatteryPropertiesRegistrar.h> #define FRIEND_TEST(test_case_name, test_name) \ friend class test_case_name##_##test_name##_Test #include "storaged_diskstats.h" #include "storaged_info.h" #include "storaged_uid_monitor.h" using namespace android; #define FRIEND_TEST(test_case_name, test_name) \ friend class test_case_name##_##test_name##_Test /* For debug */ #ifdef DEBUG #define debuginfo(fmt, ...) \ do {printf("%s():\t" fmt "\t[%s:%d]\n", __FUNCTION__, ##__VA_ARGS__, __FILE__, __LINE__);} \ while(0) #else #define debuginfo(...) #endif #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #define SECTOR_SIZE ( 512 ) Loading @@ -56,162 +48,6 @@ friend class test_case_name##_##test_name##_Test #define HOUR_TO_SEC ( 3600 ) #define DAY_TO_SEC ( 3600 * 24 ) // number of attributes diskstats has #define DISK_STATS_SIZE ( 11 ) // maximum size limit of a stats file #define DISK_STATS_FILE_MAX_SIZE ( 256 ) #define DISK_STATS_IO_IN_FLIGHT_IDX ( 8 ) struct disk_stats { /* It will be extremely unlikely for any of the following entries to overflow. * For read_bytes(which will be greater than any of the following entries), it * will take 27 years to overflow uint64_t at the reading rate of 20GB/s, which * is the peak memory transfer rate for current memory. * The diskstats entries (first 11) need to be at top in this structure _after_ * compiler's optimization. */ uint64_t read_ios; // number of read I/Os processed uint64_t read_merges; // number of read I/Os merged with in-queue I/Os uint64_t read_sectors; // number of sectors read uint64_t read_ticks; // total wait time for read requests uint64_t write_ios; // number of write I/Os processed uint64_t write_merges; // number of write I/Os merged with in-queue I/Os uint64_t write_sectors; // number of sectors written uint64_t write_ticks; // total wait time for write requests uint64_t io_in_flight; // number of I/Os currently in flight uint64_t io_ticks; // total time this block device has been active uint64_t io_in_queue; // total wait time for all requests uint64_t start_time; // monotonic time accounting starts uint64_t end_time; // monotonic time accounting ends uint32_t counter; // private counter for accumulate calculations double io_avg; // average io_in_flight for accumulate calculations }; struct disk_perf { uint32_t read_perf; // read speed (kbytes/s) uint32_t read_ios; // read I/Os per second uint32_t write_perf; // write speed (kbytes/s) uint32_t write_ios; // write I/Os per second uint32_t queue; // I/Os in queue }; class lock_t { sem_t* mSem; public: lock_t(sem_t* sem) { mSem = sem; sem_wait(mSem); } ~lock_t() { sem_post(mSem); } }; class stream_stats { private: double mSum; double mSquareSum; uint32_t mCnt; public: stream_stats() : mSum(0), mSquareSum(0), mCnt(0) {}; ~stream_stats() {}; double get_mean() { return mSum / mCnt; } double get_std() { return sqrt(mSquareSum / mCnt - mSum * mSum / (mCnt * mCnt)); } void add(uint32_t num) { mSum += (double)num; mSquareSum += (double)num * (double)num; mCnt++; } void evict(uint32_t num) { if (mSum < num || mSquareSum < (double)num * (double)num) return; mSum -= (double)num; mSquareSum -= (double)num * (double)num; mCnt--; } }; #define MMC_DISK_STATS_PATH "/sys/block/mmcblk0/stat" #define SDA_DISK_STATS_PATH "/sys/block/sda/stat" #define EMMC_ECSD_PATH "/d/mmc0/mmc0:0001/ext_csd" #define UID_IO_STATS_PATH "/proc/uid_io/stats" class disk_stats_monitor { private: FRIEND_TEST(storaged_test, disk_stats_monitor); const char* DISK_STATS_PATH; struct disk_stats mPrevious; struct disk_stats mAccumulate; bool mStall; std::queue<struct disk_perf> mBuffer; struct { stream_stats read_perf; // read speed (bytes/s) stream_stats read_ios; // read I/Os per second stream_stats write_perf; // write speed (bytes/s) stream_stats write_ios; // write I/O per second stream_stats queue; // I/Os in queue } mStats; bool mValid; const uint32_t mWindow; const double mSigma; struct disk_perf mMean; struct disk_perf mStd; void update_mean(); void update_std(); void add(struct disk_perf* perf); void evict(struct disk_perf* perf); bool detect(struct disk_perf* perf); void update(struct disk_stats* stats); public: disk_stats_monitor(uint32_t window_size = 5, double sigma = 1.0) : mStall(false), mValid(false), mWindow(window_size), mSigma(sigma) { memset(&mPrevious, 0, sizeof(mPrevious)); memset(&mMean, 0, sizeof(mMean)); memset(&mStd, 0, sizeof(mStd)); if (access(MMC_DISK_STATS_PATH, R_OK) >= 0) { DISK_STATS_PATH = MMC_DISK_STATS_PATH; } else { DISK_STATS_PATH = SDA_DISK_STATS_PATH; } } void update(void); }; class disk_stats_publisher { private: FRIEND_TEST(storaged_test, disk_stats_publisher); const char* DISK_STATS_PATH; struct disk_stats mAccumulate; struct disk_stats mPrevious; public: disk_stats_publisher(void) { memset(&mAccumulate, 0, sizeof(struct disk_stats)); memset(&mPrevious, 0, sizeof(struct disk_stats)); if (access(MMC_DISK_STATS_PATH, R_OK) >= 0) { DISK_STATS_PATH = MMC_DISK_STATS_PATH; } else { DISK_STATS_PATH = SDA_DISK_STATS_PATH; } } ~disk_stats_publisher(void) {} void publish(void); void update(void); }; // Periodic chores intervals in seconds #define DEFAULT_PERIODIC_CHORES_INTERVAL_UNIT ( 60 ) #define DEFAULT_PERIODIC_CHORES_INTERVAL_DISK_STATS_PUBLISH ( 3600 ) Loading @@ -225,8 +61,6 @@ struct storaged_config { int periodic_chores_interval_unit; int periodic_chores_interval_disk_stats_publish; int periodic_chores_interval_uid_io; bool proc_uid_io_available; // whether uid_io is accessible bool diskstats_available; // whether diskstats is accessible int event_time_check_usec; // check how much cputime spent in event loop }; Loading @@ -235,7 +69,6 @@ class storaged_t : public BnBatteryPropertiesListener, private: time_t mTimer; storaged_config mConfig; disk_stats_publisher mDiskStats; disk_stats_monitor mDsm; uid_monitor mUidm; time_t mStarttime; Loading storaged/include/storaged_diskstats.h 0 → 100644 +190 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef _STORAGED_DISKSTATS_H_ #define _STORAGED_DISKSTATS_H_ #include <stdint.h> // number of attributes diskstats has #define DISK_STATS_SIZE ( 11 ) #define MMC_DISK_STATS_PATH "/sys/block/mmcblk0/stat" #define SDA_DISK_STATS_PATH "/sys/block/sda/stat" struct disk_stats { /* It will be extremely unlikely for any of the following entries to overflow. * For read_bytes(which will be greater than any of the following entries), it * will take 27 years to overflow uint64_t at the reading rate of 20GB/s, which * is the peak memory transfer rate for current memory. * The diskstats entries (first 11) need to be at top in this structure _after_ * compiler's optimization. */ uint64_t read_ios; // number of read I/Os processed uint64_t read_merges; // number of read I/Os merged with in-queue I/Os uint64_t read_sectors; // number of sectors read uint64_t read_ticks; // total wait time for read requests uint64_t write_ios; // number of write I/Os processed uint64_t write_merges; // number of write I/Os merged with in-queue I/Os uint64_t write_sectors; // number of sectors written uint64_t write_ticks; // total wait time for write requests uint64_t io_in_flight; // number of I/Os currently in flight uint64_t io_ticks; // total time this block device has been active uint64_t io_in_queue; // total wait time for all requests uint64_t start_time; // monotonic time accounting starts uint64_t end_time; // monotonic time accounting ends uint32_t counter; // private counter for accumulate calculations double io_avg; // average io_in_flight for accumulate calculations bool is_zero() { return read_ios == 0 && write_ios == 0 && io_in_flight == 0 && io_ticks == 0 && io_in_queue == 0; } friend disk_stats operator- (disk_stats curr, const disk_stats& prev) { curr.read_ios -= prev.read_ios; curr.read_merges -= prev.read_merges; curr.read_sectors -= prev.read_sectors; curr.read_ticks -= prev.read_ticks; curr.write_ios -= prev.write_ios; curr.write_merges -= prev.write_merges; curr.write_sectors -= prev.write_sectors; curr.write_ticks -= prev.write_ticks; /* skips io_in_flight, use current value */ curr.io_ticks -= prev.io_ticks; curr.io_in_queue -= prev.io_in_queue; return curr; } friend bool operator== (const disk_stats& a, const disk_stats& b) { return a.read_ios == b.read_ios && a.read_merges == b.read_merges && a.read_sectors == b.read_sectors && a.read_ticks == b.read_ticks && a.write_ios == b.write_ios && a.write_merges == b.write_merges && a.write_sectors == b.write_sectors && a.write_ticks == b.write_ticks && /* skips io_in_flight */ a.io_ticks == b.io_ticks && a.io_in_queue == b.io_in_queue; } disk_stats& operator+= (const disk_stats& stats) { read_ios += stats.read_ios; read_merges += stats.read_merges; read_sectors += stats.read_sectors; read_ticks += stats.read_ticks; write_ios += stats.write_ios; write_merges += stats.write_merges; write_sectors += stats.write_sectors; write_ticks += stats.write_ticks; /* skips io_in_flight, use current value */ io_ticks += stats.io_ticks; io_in_queue += stats.io_in_queue; return *this; } }; struct disk_perf { uint32_t read_perf; // read speed (kbytes/s) uint32_t read_ios; // read I/Os per second uint32_t write_perf; // write speed (kbytes/s) uint32_t write_ios; // write I/Os per second uint32_t queue; // I/Os in queue bool is_zero() { return read_perf == 0 && read_ios == 0 && write_perf == 0 && write_ios == 0 && queue == 0; } }; class stream_stats { private: double mSum; double mSquareSum; uint32_t mCnt; public: stream_stats() : mSum(0), mSquareSum(0), mCnt(0) {}; ~stream_stats() {}; double get_mean() { return mSum / mCnt; } double get_std() { return sqrt(mSquareSum / mCnt - mSum * mSum / (mCnt * mCnt)); } void add(uint32_t num) { mSum += (double)num; mSquareSum += (double)num * (double)num; mCnt++; } void evict(uint32_t num) { if (mSum < num || mSquareSum < (double)num * (double)num) return; mSum -= (double)num; mSquareSum -= (double)num * (double)num; mCnt--; } }; class disk_stats_monitor { private: FRIEND_TEST(storaged_test, disk_stats_monitor); const char* const DISK_STATS_PATH; struct disk_stats mPrevious; struct disk_stats mAccumulate; /* reset after stall */ struct disk_stats mAccumulate_pub; /* reset after publish */ bool mStall; std::queue<struct disk_perf> mBuffer; struct { stream_stats read_perf; // read speed (bytes/s) stream_stats read_ios; // read I/Os per second stream_stats write_perf; // write speed (bytes/s) stream_stats write_ios; // write I/O per second stream_stats queue; // I/Os in queue } mStats; bool mValid; const uint32_t mWindow; const double mSigma; struct disk_perf mMean; struct disk_perf mStd; void update_mean(); void update_std(); void add(struct disk_perf* perf); void evict(struct disk_perf* perf); bool detect(struct disk_perf* perf); void update(struct disk_stats* stats); public: disk_stats_monitor(uint32_t window_size = 5, double sigma = 1.0) : DISK_STATS_PATH(access(MMC_DISK_STATS_PATH, R_OK) ? (access(SDA_DISK_STATS_PATH, R_OK) ? nullptr : SDA_DISK_STATS_PATH) : MMC_DISK_STATS_PATH), mPrevious(), mAccumulate(), mAccumulate_pub(), mStall(false), mValid(false), mWindow(window_size), mSigma(sigma), mMean(), mStd() {} bool enabled() { return DISK_STATS_PATH != nullptr; } void update(void); void publish(void); }; #endif /* _STORAGED_DISKSTATS_H_ */ No newline at end of file storaged/include/storaged_uid_monitor.h +15 −0 Original line number Diff line number Diff line Loading @@ -85,6 +85,18 @@ struct uid_records { std::vector<struct uid_record> entries; }; class lock_t { sem_t* mSem; public: lock_t(sem_t* sem) { mSem = sem; sem_wait(mSem); } ~lock_t() { sem_post(mSem); } }; class uid_monitor { private: // last dump from /proc/uid_io/stats, uid -> uid_info Loading @@ -99,6 +111,8 @@ private: sem_t um_lock; // start time for IO records uint64_t start_ts; // true if UID_IO_STATS_PATH is accessible const bool enable; // protobuf file for io_history static const std::string io_history_proto_file; Loading Loading @@ -126,6 +140,7 @@ public: // called by battery properties listener void set_charger_state(charger_stat_t stat); // called by storaged periodic_chore or dump with force_report bool enabled() { return enable; }; void report(); }; Loading storaged/include/storaged_utils.h +1 −6 Original line number Diff line number Diff line Loading @@ -27,9 +27,8 @@ // Diskstats bool parse_disk_stats(const char* disk_stats_path, struct disk_stats* stats); struct disk_perf get_disk_perf(struct disk_stats* stats); struct disk_stats get_inc_disk_stats(struct disk_stats* prev, struct disk_stats* curr); void get_inc_disk_stats(const struct disk_stats* prev, const struct disk_stats* curr, struct disk_stats* inc); void add_disk_stats(struct disk_stats* src, struct disk_stats* dst); bool parse_emmc_ecsd(int ext_csd_fd, struct emmc_info* info); // UID I/O void sort_running_uids_info(std::vector<struct uid_info> &uids); Loading @@ -37,8 +36,4 @@ void sort_running_uids_info(std::vector<struct uid_info> &uids); // Logging void log_console_running_uids_info(const std::vector<struct uid_info>& uids, bool flag_dump_task); void log_debug_disk_perf(struct disk_perf* perf, const char* type); void log_event_disk_stats(struct disk_stats* stats, const char* type); void log_event_emmc_info(struct emmc_info* info_); #endif /* _STORAGED_UTILS_H_ */ Loading
storaged/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ cc_library_static { srcs: [ "storaged.cpp", "storaged_diskstats.cpp", "storaged_info.cpp", "storaged_service.cpp", "storaged_utils.cpp", Loading
storaged/include/storaged.h +4 −171 Original line number Diff line number Diff line Loading @@ -29,23 +29,15 @@ #include <batteryservice/IBatteryPropertiesListener.h> #include <batteryservice/IBatteryPropertiesRegistrar.h> #define FRIEND_TEST(test_case_name, test_name) \ friend class test_case_name##_##test_name##_Test #include "storaged_diskstats.h" #include "storaged_info.h" #include "storaged_uid_monitor.h" using namespace android; #define FRIEND_TEST(test_case_name, test_name) \ friend class test_case_name##_##test_name##_Test /* For debug */ #ifdef DEBUG #define debuginfo(fmt, ...) \ do {printf("%s():\t" fmt "\t[%s:%d]\n", __FUNCTION__, ##__VA_ARGS__, __FILE__, __LINE__);} \ while(0) #else #define debuginfo(...) #endif #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #define SECTOR_SIZE ( 512 ) Loading @@ -56,162 +48,6 @@ friend class test_case_name##_##test_name##_Test #define HOUR_TO_SEC ( 3600 ) #define DAY_TO_SEC ( 3600 * 24 ) // number of attributes diskstats has #define DISK_STATS_SIZE ( 11 ) // maximum size limit of a stats file #define DISK_STATS_FILE_MAX_SIZE ( 256 ) #define DISK_STATS_IO_IN_FLIGHT_IDX ( 8 ) struct disk_stats { /* It will be extremely unlikely for any of the following entries to overflow. * For read_bytes(which will be greater than any of the following entries), it * will take 27 years to overflow uint64_t at the reading rate of 20GB/s, which * is the peak memory transfer rate for current memory. * The diskstats entries (first 11) need to be at top in this structure _after_ * compiler's optimization. */ uint64_t read_ios; // number of read I/Os processed uint64_t read_merges; // number of read I/Os merged with in-queue I/Os uint64_t read_sectors; // number of sectors read uint64_t read_ticks; // total wait time for read requests uint64_t write_ios; // number of write I/Os processed uint64_t write_merges; // number of write I/Os merged with in-queue I/Os uint64_t write_sectors; // number of sectors written uint64_t write_ticks; // total wait time for write requests uint64_t io_in_flight; // number of I/Os currently in flight uint64_t io_ticks; // total time this block device has been active uint64_t io_in_queue; // total wait time for all requests uint64_t start_time; // monotonic time accounting starts uint64_t end_time; // monotonic time accounting ends uint32_t counter; // private counter for accumulate calculations double io_avg; // average io_in_flight for accumulate calculations }; struct disk_perf { uint32_t read_perf; // read speed (kbytes/s) uint32_t read_ios; // read I/Os per second uint32_t write_perf; // write speed (kbytes/s) uint32_t write_ios; // write I/Os per second uint32_t queue; // I/Os in queue }; class lock_t { sem_t* mSem; public: lock_t(sem_t* sem) { mSem = sem; sem_wait(mSem); } ~lock_t() { sem_post(mSem); } }; class stream_stats { private: double mSum; double mSquareSum; uint32_t mCnt; public: stream_stats() : mSum(0), mSquareSum(0), mCnt(0) {}; ~stream_stats() {}; double get_mean() { return mSum / mCnt; } double get_std() { return sqrt(mSquareSum / mCnt - mSum * mSum / (mCnt * mCnt)); } void add(uint32_t num) { mSum += (double)num; mSquareSum += (double)num * (double)num; mCnt++; } void evict(uint32_t num) { if (mSum < num || mSquareSum < (double)num * (double)num) return; mSum -= (double)num; mSquareSum -= (double)num * (double)num; mCnt--; } }; #define MMC_DISK_STATS_PATH "/sys/block/mmcblk0/stat" #define SDA_DISK_STATS_PATH "/sys/block/sda/stat" #define EMMC_ECSD_PATH "/d/mmc0/mmc0:0001/ext_csd" #define UID_IO_STATS_PATH "/proc/uid_io/stats" class disk_stats_monitor { private: FRIEND_TEST(storaged_test, disk_stats_monitor); const char* DISK_STATS_PATH; struct disk_stats mPrevious; struct disk_stats mAccumulate; bool mStall; std::queue<struct disk_perf> mBuffer; struct { stream_stats read_perf; // read speed (bytes/s) stream_stats read_ios; // read I/Os per second stream_stats write_perf; // write speed (bytes/s) stream_stats write_ios; // write I/O per second stream_stats queue; // I/Os in queue } mStats; bool mValid; const uint32_t mWindow; const double mSigma; struct disk_perf mMean; struct disk_perf mStd; void update_mean(); void update_std(); void add(struct disk_perf* perf); void evict(struct disk_perf* perf); bool detect(struct disk_perf* perf); void update(struct disk_stats* stats); public: disk_stats_monitor(uint32_t window_size = 5, double sigma = 1.0) : mStall(false), mValid(false), mWindow(window_size), mSigma(sigma) { memset(&mPrevious, 0, sizeof(mPrevious)); memset(&mMean, 0, sizeof(mMean)); memset(&mStd, 0, sizeof(mStd)); if (access(MMC_DISK_STATS_PATH, R_OK) >= 0) { DISK_STATS_PATH = MMC_DISK_STATS_PATH; } else { DISK_STATS_PATH = SDA_DISK_STATS_PATH; } } void update(void); }; class disk_stats_publisher { private: FRIEND_TEST(storaged_test, disk_stats_publisher); const char* DISK_STATS_PATH; struct disk_stats mAccumulate; struct disk_stats mPrevious; public: disk_stats_publisher(void) { memset(&mAccumulate, 0, sizeof(struct disk_stats)); memset(&mPrevious, 0, sizeof(struct disk_stats)); if (access(MMC_DISK_STATS_PATH, R_OK) >= 0) { DISK_STATS_PATH = MMC_DISK_STATS_PATH; } else { DISK_STATS_PATH = SDA_DISK_STATS_PATH; } } ~disk_stats_publisher(void) {} void publish(void); void update(void); }; // Periodic chores intervals in seconds #define DEFAULT_PERIODIC_CHORES_INTERVAL_UNIT ( 60 ) #define DEFAULT_PERIODIC_CHORES_INTERVAL_DISK_STATS_PUBLISH ( 3600 ) Loading @@ -225,8 +61,6 @@ struct storaged_config { int periodic_chores_interval_unit; int periodic_chores_interval_disk_stats_publish; int periodic_chores_interval_uid_io; bool proc_uid_io_available; // whether uid_io is accessible bool diskstats_available; // whether diskstats is accessible int event_time_check_usec; // check how much cputime spent in event loop }; Loading @@ -235,7 +69,6 @@ class storaged_t : public BnBatteryPropertiesListener, private: time_t mTimer; storaged_config mConfig; disk_stats_publisher mDiskStats; disk_stats_monitor mDsm; uid_monitor mUidm; time_t mStarttime; Loading
storaged/include/storaged_diskstats.h 0 → 100644 +190 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef _STORAGED_DISKSTATS_H_ #define _STORAGED_DISKSTATS_H_ #include <stdint.h> // number of attributes diskstats has #define DISK_STATS_SIZE ( 11 ) #define MMC_DISK_STATS_PATH "/sys/block/mmcblk0/stat" #define SDA_DISK_STATS_PATH "/sys/block/sda/stat" struct disk_stats { /* It will be extremely unlikely for any of the following entries to overflow. * For read_bytes(which will be greater than any of the following entries), it * will take 27 years to overflow uint64_t at the reading rate of 20GB/s, which * is the peak memory transfer rate for current memory. * The diskstats entries (first 11) need to be at top in this structure _after_ * compiler's optimization. */ uint64_t read_ios; // number of read I/Os processed uint64_t read_merges; // number of read I/Os merged with in-queue I/Os uint64_t read_sectors; // number of sectors read uint64_t read_ticks; // total wait time for read requests uint64_t write_ios; // number of write I/Os processed uint64_t write_merges; // number of write I/Os merged with in-queue I/Os uint64_t write_sectors; // number of sectors written uint64_t write_ticks; // total wait time for write requests uint64_t io_in_flight; // number of I/Os currently in flight uint64_t io_ticks; // total time this block device has been active uint64_t io_in_queue; // total wait time for all requests uint64_t start_time; // monotonic time accounting starts uint64_t end_time; // monotonic time accounting ends uint32_t counter; // private counter for accumulate calculations double io_avg; // average io_in_flight for accumulate calculations bool is_zero() { return read_ios == 0 && write_ios == 0 && io_in_flight == 0 && io_ticks == 0 && io_in_queue == 0; } friend disk_stats operator- (disk_stats curr, const disk_stats& prev) { curr.read_ios -= prev.read_ios; curr.read_merges -= prev.read_merges; curr.read_sectors -= prev.read_sectors; curr.read_ticks -= prev.read_ticks; curr.write_ios -= prev.write_ios; curr.write_merges -= prev.write_merges; curr.write_sectors -= prev.write_sectors; curr.write_ticks -= prev.write_ticks; /* skips io_in_flight, use current value */ curr.io_ticks -= prev.io_ticks; curr.io_in_queue -= prev.io_in_queue; return curr; } friend bool operator== (const disk_stats& a, const disk_stats& b) { return a.read_ios == b.read_ios && a.read_merges == b.read_merges && a.read_sectors == b.read_sectors && a.read_ticks == b.read_ticks && a.write_ios == b.write_ios && a.write_merges == b.write_merges && a.write_sectors == b.write_sectors && a.write_ticks == b.write_ticks && /* skips io_in_flight */ a.io_ticks == b.io_ticks && a.io_in_queue == b.io_in_queue; } disk_stats& operator+= (const disk_stats& stats) { read_ios += stats.read_ios; read_merges += stats.read_merges; read_sectors += stats.read_sectors; read_ticks += stats.read_ticks; write_ios += stats.write_ios; write_merges += stats.write_merges; write_sectors += stats.write_sectors; write_ticks += stats.write_ticks; /* skips io_in_flight, use current value */ io_ticks += stats.io_ticks; io_in_queue += stats.io_in_queue; return *this; } }; struct disk_perf { uint32_t read_perf; // read speed (kbytes/s) uint32_t read_ios; // read I/Os per second uint32_t write_perf; // write speed (kbytes/s) uint32_t write_ios; // write I/Os per second uint32_t queue; // I/Os in queue bool is_zero() { return read_perf == 0 && read_ios == 0 && write_perf == 0 && write_ios == 0 && queue == 0; } }; class stream_stats { private: double mSum; double mSquareSum; uint32_t mCnt; public: stream_stats() : mSum(0), mSquareSum(0), mCnt(0) {}; ~stream_stats() {}; double get_mean() { return mSum / mCnt; } double get_std() { return sqrt(mSquareSum / mCnt - mSum * mSum / (mCnt * mCnt)); } void add(uint32_t num) { mSum += (double)num; mSquareSum += (double)num * (double)num; mCnt++; } void evict(uint32_t num) { if (mSum < num || mSquareSum < (double)num * (double)num) return; mSum -= (double)num; mSquareSum -= (double)num * (double)num; mCnt--; } }; class disk_stats_monitor { private: FRIEND_TEST(storaged_test, disk_stats_monitor); const char* const DISK_STATS_PATH; struct disk_stats mPrevious; struct disk_stats mAccumulate; /* reset after stall */ struct disk_stats mAccumulate_pub; /* reset after publish */ bool mStall; std::queue<struct disk_perf> mBuffer; struct { stream_stats read_perf; // read speed (bytes/s) stream_stats read_ios; // read I/Os per second stream_stats write_perf; // write speed (bytes/s) stream_stats write_ios; // write I/O per second stream_stats queue; // I/Os in queue } mStats; bool mValid; const uint32_t mWindow; const double mSigma; struct disk_perf mMean; struct disk_perf mStd; void update_mean(); void update_std(); void add(struct disk_perf* perf); void evict(struct disk_perf* perf); bool detect(struct disk_perf* perf); void update(struct disk_stats* stats); public: disk_stats_monitor(uint32_t window_size = 5, double sigma = 1.0) : DISK_STATS_PATH(access(MMC_DISK_STATS_PATH, R_OK) ? (access(SDA_DISK_STATS_PATH, R_OK) ? nullptr : SDA_DISK_STATS_PATH) : MMC_DISK_STATS_PATH), mPrevious(), mAccumulate(), mAccumulate_pub(), mStall(false), mValid(false), mWindow(window_size), mSigma(sigma), mMean(), mStd() {} bool enabled() { return DISK_STATS_PATH != nullptr; } void update(void); void publish(void); }; #endif /* _STORAGED_DISKSTATS_H_ */ No newline at end of file
storaged/include/storaged_uid_monitor.h +15 −0 Original line number Diff line number Diff line Loading @@ -85,6 +85,18 @@ struct uid_records { std::vector<struct uid_record> entries; }; class lock_t { sem_t* mSem; public: lock_t(sem_t* sem) { mSem = sem; sem_wait(mSem); } ~lock_t() { sem_post(mSem); } }; class uid_monitor { private: // last dump from /proc/uid_io/stats, uid -> uid_info Loading @@ -99,6 +111,8 @@ private: sem_t um_lock; // start time for IO records uint64_t start_ts; // true if UID_IO_STATS_PATH is accessible const bool enable; // protobuf file for io_history static const std::string io_history_proto_file; Loading Loading @@ -126,6 +140,7 @@ public: // called by battery properties listener void set_charger_state(charger_stat_t stat); // called by storaged periodic_chore or dump with force_report bool enabled() { return enable; }; void report(); }; Loading
storaged/include/storaged_utils.h +1 −6 Original line number Diff line number Diff line Loading @@ -27,9 +27,8 @@ // Diskstats bool parse_disk_stats(const char* disk_stats_path, struct disk_stats* stats); struct disk_perf get_disk_perf(struct disk_stats* stats); struct disk_stats get_inc_disk_stats(struct disk_stats* prev, struct disk_stats* curr); void get_inc_disk_stats(const struct disk_stats* prev, const struct disk_stats* curr, struct disk_stats* inc); void add_disk_stats(struct disk_stats* src, struct disk_stats* dst); bool parse_emmc_ecsd(int ext_csd_fd, struct emmc_info* info); // UID I/O void sort_running_uids_info(std::vector<struct uid_info> &uids); Loading @@ -37,8 +36,4 @@ void sort_running_uids_info(std::vector<struct uid_info> &uids); // Logging void log_console_running_uids_info(const std::vector<struct uid_info>& uids, bool flag_dump_task); void log_debug_disk_perf(struct disk_perf* perf, const char* type); void log_event_disk_stats(struct disk_stats* stats, const char* type); void log_event_emmc_info(struct emmc_info* info_); #endif /* _STORAGED_UTILS_H_ */