From 3790f5bfafc52ca881b9350b922ffe94e6a537bb Mon Sep 17 00:00:00 2001 From: Jin Qian Date: Mon, 23 Jan 2017 14:38:47 -0800 Subject: [PATCH] storaged: replace cmd arguments with properties Add properties to control event intervals. Add a property to check time spent in event loop. Bug: 34612341 Bug: 34198239 Change-Id: I01f64c84e17153377ece7ae530be106e3f55287e --- storaged/README.properties | 6 ++ storaged/include/storaged.h | 25 ++++---- storaged/include/storaged_uid_monitor.h | 5 +- storaged/main.cpp | 77 +------------------------ storaged/storaged.cpp | 47 +++++++++++++-- storaged/storaged_uid_monitor.cpp | 4 +- storaged/storaged_utils.cpp | 5 -- 7 files changed, 67 insertions(+), 102 deletions(-) create mode 100644 storaged/README.properties diff --git a/storaged/README.properties b/storaged/README.properties new file mode 100644 index 000000000..70e6026f0 --- /dev/null +++ b/storaged/README.properties @@ -0,0 +1,6 @@ +ro.storaged.event.interval # interval storaged scans for IO stats, in seconds +ro.storaged.event.perf_check # check for time spent in event loop, in microseconds +ro.storaged.disk_stats_pub # interval storaged publish disk stats, in seconds +ro.storaged.emmc_info_pub # interval storaged publish emmc info, in seconds +ro.storaged.uid_io.interval # interval storaged checks Per UID IO usage, in seconds +ro.storaged.uid_io.threshold # Per UID IO usage limit, in bytes diff --git a/storaged/include/storaged.h b/storaged/include/storaged.h index 7fa9958bd..d3e6b7140 100644 --- a/storaged/include/storaged.h +++ b/storaged/include/storaged.h @@ -40,6 +40,12 @@ friend class test_case_name##_##test_name##_Test #define debuginfo(...) #endif +#define SECTOR_SIZE ( 512 ) +#define SEC_TO_MSEC ( 1000 ) +#define MSEC_TO_USEC ( 1000 ) +#define USEC_TO_NSEC ( 1000 ) +#define SEC_TO_USEC ( 1000000 ) + // number of attributes diskstats has #define DISK_STATS_SIZE ( 11 ) // maximum size limit of a stats file @@ -266,7 +272,10 @@ public: #define DEFAULT_PERIODIC_CHORES_INTERVAL_UNIT ( 60 ) #define DEFAULT_PERIODIC_CHORES_INTERVAL_DISK_STATS_PUBLISH ( 3600 ) #define DEFAULT_PERIODIC_CHORES_INTERVAL_EMMC_INFO_PUBLISH ( 86400 ) -#define DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO_ALERT ( 3600 ) +#define DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO ( 3600 ) + +// UID IO threshold in bytes +#define DEFAULT_PERIODIC_CHORES_UID_IO_THRESHOLD ( 1024 * 1024 * 1024ULL ) struct storaged_config { int periodic_chores_interval_unit; @@ -277,6 +286,7 @@ struct storaged_config { bool proc_uid_io_available; // whether uid_io is accessible bool emmc_available; // whether eMMC est_csd file is readable bool diskstats_available; // whether diskstats is accessible + int event_time_check_usec; // check how much cputime spent in event loop }; class storaged_t { @@ -293,21 +303,10 @@ public: storaged_t(void); ~storaged_t() {} void event(void); + void event_checked(void); void pause(void) { sleep(mConfig.periodic_chores_interval_unit); } - void set_unit_interval(int unit) { - mConfig.periodic_chores_interval_unit = unit; - } - void set_diskstats_interval(int disk_stats) { - mConfig.periodic_chores_interval_disk_stats_publish = disk_stats; - } - void set_emmc_interval(int emmc_info) { - mConfig.periodic_chores_interval_emmc_info_publish = emmc_info; - } - void set_uid_io_interval(int uid_io) { - mUidm.set_periodic_chores_interval(uid_io); - } std::vector get_tasks(void) { // There could be a race when get_tasks() and the main thread is updating at the same time // While update_running_tasks() is updating the critical sections at the end of the function diff --git a/storaged/include/storaged_uid_monitor.h b/storaged/include/storaged_uid_monitor.h index eceb7fd34..9f95c5188 100644 --- a/storaged/include/storaged_uid_monitor.h +++ b/storaged/include/storaged_uid_monitor.h @@ -46,11 +46,12 @@ class uid_monitor { private: std::unordered_map last_uids; void set_last_uids(std::unordered_map&& uids, uint64_t ts); - int interval; // monitor interval in seconds + int interval; // monitor interval in seconds + int threshold; // monitor threshold in bytes uint64_t last_report_ts; // timestamp of last report in nsec public: uid_monitor(); - void set_periodic_chores_interval(int t) { interval = t; } + void set_periodic_chores_params(int intvl, int thold) { interval = intvl; threshold = thold; } int get_periodic_chores_interval() { return interval; } std::unordered_map get_uids(); void report(); diff --git a/storaged/main.cpp b/storaged/main.cpp index 915157493..c7f3dff5c 100644 --- a/storaged/main.cpp +++ b/storaged/main.cpp @@ -96,7 +96,7 @@ void* storaged_main(void* s) { LOG_TO(SYSTEM, INFO) << "storaged: Start"; for (;;) { - storaged->event(); + storaged->event_checked(); storaged->pause(); } return NULL; @@ -107,10 +107,6 @@ static void help_message(void) { printf(" -d --dump Dump task I/O usage to stdout\n"); printf(" -u --uid Dump uid I/O usage to stdout\n"); printf(" -s --start Start storaged (default)\n"); - printf(" --emmc=INTERVAL Set publish interval of emmc lifetime information (in days)\n"); - printf(" --diskstats=INTERVAL Set publish interval of diskstats (in hours)\n"); - printf(" --uidio=INTERVAL Set publish interval of uid io (in hours)\n"); - printf(" --unit=INTERVAL Set storaged's refresh interval (in seconds)\n"); fflush(stdout); } @@ -121,11 +117,6 @@ int main(int argc, char** argv) { int flag_main_service = 0; int flag_dump_task = 0; int flag_dump_uid = 0; - int flag_config = 0; - int unit_interval = DEFAULT_PERIODIC_CHORES_INTERVAL_UNIT; - int diskstats_interval = DEFAULT_PERIODIC_CHORES_INTERVAL_DISK_STATS_PUBLISH; - int emmc_interval = DEFAULT_PERIODIC_CHORES_INTERVAL_EMMC_INFO_PUBLISH; - int uid_io_interval = DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO_ALERT; int fd_emmc = -1; int opt; @@ -136,11 +127,7 @@ int main(int argc, char** argv) { {"kill", no_argument, 0, 'k'}, {"dump", no_argument, 0, 'd'}, {"uid", no_argument, 0, 'u'}, - {"help", no_argument, 0, 'h'}, - {"unit", required_argument, 0, 0 }, - {"diskstats", required_argument, 0, 0 }, - {"emmc", required_argument, 0, 0 }, - {"uidio", required_argument, 0, 0 } + {"help", no_argument, 0, 'h'} }; opt = getopt_long(argc, argv, ":skdhu0", long_options, &opt_idx); if (opt == -1) { @@ -148,53 +135,6 @@ int main(int argc, char** argv) { } switch (opt) { - case 0: - printf("option %s", long_options[opt_idx].name); - if (optarg) { - printf(" with arg %s", optarg); - if (strcmp(long_options[opt_idx].name, "unit") == 0) { - unit_interval = atoi(optarg); - if (unit_interval == 0) { - fprintf(stderr, "Invalid argument. Option %s requires an integer argument greater than 0.\n", - long_options[opt_idx].name); - help_message(); - return -1; - } - } else if (strcmp(long_options[opt_idx].name, "diskstats") == 0) { - diskstats_interval = atoi(optarg) * HOUR_TO_SEC; - if (diskstats_interval == 0) { - fprintf(stderr, "Invalid argument. Option %s requires an integer argument greater than 0.\n", - long_options[opt_idx].name); - help_message(); - return -1; - } - - } else if (strcmp(long_options[opt_idx].name, "emmc") == 0) { - emmc_interval = atoi(optarg) * DAY_TO_SEC; - if (emmc_interval == 0) { - fprintf(stderr, "Invalid argument. Option %s requires an integer argument greater than 0.\n", - long_options[opt_idx].name); - help_message(); - return -1; - } - } else if (strcmp(long_options[opt_idx].name, "uidio") == 0) { - uid_io_interval = atoi(optarg) * HOUR_TO_SEC; - if (uid_io_interval == 0) { - fprintf(stderr, "Invalid argument. Option %s requires an integer argument greater than 0.\n", - long_options[opt_idx].name); - help_message(); - return -1; - } - } - flag_config = 1; - } else { - fprintf(stderr, "Invalid argument. Option %s requires an argument.\n", - long_options[opt_idx].name); - help_message(); - return -1; - } - printf("\n"); - break; case 's': flag_main_service = 1; break; @@ -225,12 +165,6 @@ int main(int argc, char** argv) { return -1; } - if (flag_config && flag_dump_task) { - fprintf(stderr, "Invalid arguments. Cannot set configs in \'dump\' option.\n"); - help_message(); - return -1; - } - if (flag_main_service) { // start main thread static const char mmc0_ext_csd[] = "/d/mmc0/mmc0:0001/ext_csd"; fd_emmc = android_get_control_file(mmc0_ext_csd); @@ -243,13 +177,6 @@ int main(int argc, char** argv) { storaged.set_privileged_fds(fd_emmc); - if (flag_config) { - storaged.set_unit_interval(unit_interval); - storaged.set_diskstats_interval(diskstats_interval); - storaged.set_emmc_interval(emmc_interval); - storaged.set_uid_io_interval(uid_io_interval); - } - // Start the main thread of storaged pthread_t storaged_main_thread; errno = pthread_create(&storaged_main_thread, NULL, storaged_main, &storaged); diff --git a/storaged/storaged.cpp b/storaged/storaged.cpp index 0c53f4482..1950c217a 100644 --- a/storaged/storaged.cpp +++ b/storaged/storaged.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -176,10 +177,21 @@ storaged_t::storaged_t(void) { mConfig.proc_uid_io_available = (access(UID_IO_STATS_PATH, R_OK) == 0); - mConfig.periodic_chores_interval_unit = DEFAULT_PERIODIC_CHORES_INTERVAL_UNIT; - mConfig.periodic_chores_interval_disk_stats_publish = DEFAULT_PERIODIC_CHORES_INTERVAL_DISK_STATS_PUBLISH; - mConfig.periodic_chores_interval_emmc_info_publish = DEFAULT_PERIODIC_CHORES_INTERVAL_EMMC_INFO_PUBLISH; - mUidm.set_periodic_chores_interval(DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO_ALERT); + mConfig.periodic_chores_interval_unit = + property_get_int32("ro.storaged.event.interval", DEFAULT_PERIODIC_CHORES_INTERVAL_UNIT); + + mConfig.event_time_check_usec = + property_get_int32("ro.storaged.event.perf_check", 0); + + mConfig.periodic_chores_interval_disk_stats_publish = + property_get_int32("ro.storaged.disk_stats_pub", DEFAULT_PERIODIC_CHORES_INTERVAL_DISK_STATS_PUBLISH); + + mConfig.periodic_chores_interval_emmc_info_publish = + property_get_int32("ro.storaged.emmc_info_pub", DEFAULT_PERIODIC_CHORES_INTERVAL_EMMC_INFO_PUBLISH); + + mUidm.set_periodic_chores_params( + property_get_int32("ro.storaged.uid_io.interval", DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO), + property_get_int32("ro.storaged.uid_io.threshold", DEFAULT_PERIODIC_CHORES_UID_IO_THRESHOLD)); mStarttime = time(NULL); } @@ -212,3 +224,30 @@ void storaged_t::event(void) { mTimer += mConfig.periodic_chores_interval_unit; } + +void storaged_t::event_checked(void) { + struct timespec start_ts, end_ts; + bool check_time = true; + + if (mConfig.event_time_check_usec && + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start_ts) < 0) { + check_time = false; + PLOG_TO(SYSTEM, ERROR) << "clock_gettime() failed"; + } + + event(); + + if (mConfig.event_time_check_usec) { + if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end_ts) < 0) { + PLOG_TO(SYSTEM, ERROR) << "clock_gettime() failed"; + return; + } + int64_t cost = (end_ts.tv_sec - start_ts.tv_sec) * SEC_TO_USEC + + (end_ts.tv_nsec - start_ts.tv_nsec) / USEC_TO_NSEC; + if (cost > mConfig.event_time_check_usec) { + LOG_TO(SYSTEM, ERROR) + << "event loop spent " << cost << " usec, threshold " + << mConfig.event_time_check_usec << " usec"; + } + } +} diff --git a/storaged/storaged_uid_monitor.cpp b/storaged/storaged_uid_monitor.cpp index 4105dae8f..2a84a0c40 100644 --- a/storaged/storaged_uid_monitor.cpp +++ b/storaged/storaged_uid_monitor.cpp @@ -33,8 +33,6 @@ #include "storaged.h" #include "storaged_uid_monitor.h" -static const uint64_t io_alert_threshold = 1024 * 1024 * 1024; // 1GB - using namespace android; using namespace android::base; @@ -116,7 +114,7 @@ void uid_monitor::report() uint64_t curr_ts = ts.tv_sec * NS_PER_SEC + ts.tv_nsec; uint64_t ts_delta = curr_ts - last_report_ts; - uint64_t adjusted_threshold = io_alert_threshold * ((double)ts_delta / interval / NS_PER_SEC); + uint64_t adjusted_threshold = threshold * ((double)ts_delta / interval / NS_PER_SEC); std::unordered_map uids = get_uids(); if (uids.empty()) { diff --git a/storaged/storaged_utils.cpp b/storaged/storaged_utils.cpp index 6e4ddb66c..1dcd0ffcf 100644 --- a/storaged/storaged_utils.cpp +++ b/storaged/storaged_utils.cpp @@ -41,11 +41,6 @@ #include #include -#define SECTOR_SIZE ( 512 ) -#define SEC_TO_MSEC ( 1000 ) -#define MSEC_TO_USEC ( 1000 ) -#define USEC_TO_NSEC ( 1000 ) - bool parse_disk_stats(const char* disk_stats_path, struct disk_stats* stats) { // Get time struct timespec ts;