/* * Copyright (C) 2016 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. */ #define LOG_TAG "storaged" #define KLOG_LEVEL 6 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace android; sp storaged_sp; // Function of storaged's main thread void* storaged_main(void* /* unused */) { LOG(INFO) << "storaged: Start"; for (;;) { storaged_sp->event_checked(); storaged_sp->pause(); } return NULL; } void help_message(void) { printf("usage: storaged [OPTION]\n"); printf(" -u --uid Dump uid I/O usage to stdout\n"); printf(" -t --task Dump task I/O usage to stdout\n"); printf(" -p --perf Dump I/O perf history to stdout\n"); printf(" -s --start Start storaged (default)\n"); fflush(stdout); } int main(int argc, char** argv) { bool flag_main_service = false; bool flag_dump_uid = false; bool flag_dump_task = false; bool flag_dump_perf = false; int opt; android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM)); for (;;) { int opt_idx = 0; static struct option long_options[] = { {"perf", no_argument, nullptr, 'p'}, {"start", no_argument, nullptr, 's'}, {"task", no_argument, nullptr, 't'}, {"uid", no_argument, nullptr, 'u'}, {nullptr, 0, nullptr, 0} }; opt = getopt_long(argc, argv, ":pstu", long_options, &opt_idx); if (opt == -1) { break; } switch (opt) { case 'p': flag_dump_perf = true; break; case 's': flag_main_service = true; break; case 't': flag_dump_task = true; break; case 'u': flag_dump_uid = true; break; default: help_message(); return 0; } } if (argc == 1) { flag_main_service = true; } if (flag_main_service && (flag_dump_uid || flag_dump_task)) { fprintf(stderr, "Invalid arguments. Option \"start\" and \"dump\" cannot be used together.\n"); help_message(); return -1; } if (flag_main_service) { // start main thread // Start the main thread of storaged storaged_sp = new storaged_t(); storaged_sp->init(); storaged_sp->report_storage_info(); pthread_t storaged_main_thread; errno = pthread_create(&storaged_main_thread, NULL, storaged_main, NULL); if (errno != 0) { PLOG(ERROR) << "Failed to create main thread"; return -1; } if (StoragedService::start() != android::OK || StoragedPrivateService::start() != android::OK) { PLOG(ERROR) << "Failed to start storaged service"; return -1; } android::ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); pthread_join(storaged_main_thread, NULL); return 0; } sp storaged_service = get_storaged_pri_service(); if (storaged_service == NULL) { fprintf(stderr, "Cannot find storaged service.\nMaybe run storaged --start first?\n"); return -1; } if (flag_dump_uid || flag_dump_task) { vector uid_io; binder::Status status = storaged_service->dumpUids(&uid_io); if (!status.isOk() || uid_io.size() == 0) { fprintf(stderr, "UID I/O info is not available.\n"); return 0; } sort_running_uids_info(uid_io); log_console_running_uids_info(uid_io, flag_dump_task); } if (flag_dump_perf) { vector perf_history; binder::Status status = storaged_service->dumpPerfHistory(&perf_history); if (!status.isOk() || perf_history.size() == 0) { fprintf(stderr, "I/O perf history is not available.\n"); return 0; } log_console_perf_history(perf_history); } return 0; }