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 #define LOG_TAG "storaged" 18 #define KLOG_LEVEL 6 19 20 #include <fcntl.h> 21 #include <getopt.h> 22 #include <pthread.h> 23 #include <stdio.h> 24 #include <sys/stat.h> 25 #include <sys/types.h> 26 #include <vector> 27 28 #include <android-base/macros.h> 29 #include <android-base/logging.h> 30 #include <android-base/stringprintf.h> 31 #include <binder/ProcessState.h> 32 #include <binder/IServiceManager.h> 33 #include <binder/IPCThreadState.h> 34 #include <cutils/android_get_control_file.h> 35 #include <cutils/sched_policy.h> 36 #include <private/android_filesystem_config.h> 37 38 #include <storaged.h> 39 #include <storaged_service.h> 40 #include <storaged_utils.h> 41 42 using namespace std; 43 using namespace android; 44 45 sp<storaged_t> storaged_sp; 46 47 // Function of storaged's main thread 48 void* storaged_main(void* /* unused */) { 49 LOG(INFO) << "storaged: Start"; 50 51 for (;;) { 52 storaged_sp->event_checked(); 53 storaged_sp->pause(); 54 } 55 return NULL; 56 } 57 58 void help_message(void) { 59 printf("usage: storaged [OPTION]\n"); 60 printf(" -u --uid Dump uid I/O usage to stdout\n"); 61 printf(" -t --task Dump task I/O usage to stdout\n"); 62 printf(" -p --perf Dump I/O perf history to stdout\n"); 63 printf(" -s --start Start storaged (default)\n"); 64 fflush(stdout); 65 } 66 67 int main(int argc, char** argv) { 68 bool flag_main_service = false; 69 bool flag_dump_uid = false; 70 bool flag_dump_task = false; 71 bool flag_dump_perf = false; 72 int opt; 73 74 signal(SIGPIPE, SIG_IGN); 75 android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM)); 76 77 for (;;) { 78 int opt_idx = 0; 79 static struct option long_options[] = { 80 {"perf", no_argument, nullptr, 'p'}, 81 {"start", no_argument, nullptr, 's'}, 82 {"task", no_argument, nullptr, 't'}, 83 {"uid", no_argument, nullptr, 'u'}, 84 {nullptr, 0, nullptr, 0} 85 }; 86 opt = getopt_long(argc, argv, ":pstu", long_options, &opt_idx); 87 if (opt == -1) { 88 break; 89 } 90 91 switch (opt) { 92 case 'p': 93 flag_dump_perf = true; 94 break; 95 case 's': 96 flag_main_service = true; 97 break; 98 case 't': 99 flag_dump_task = true; 100 break; 101 case 'u': 102 flag_dump_uid = true; 103 break; 104 default: 105 help_message(); 106 return 0; 107 } 108 } 109 110 if (argc == 1) { 111 flag_main_service = true; 112 } 113 114 if (flag_main_service && (flag_dump_uid || flag_dump_task)) { 115 fprintf(stderr, "Invalid arguments. Option \"start\" and \"dump\" cannot be used together.\n"); 116 help_message(); 117 return -1; 118 } 119 120 if (flag_main_service) { // start main thread 121 // Start the main thread of storaged 122 storaged_sp = new storaged_t(); 123 storaged_sp->init(); 124 storaged_sp->report_storage_info(); 125 pthread_t storaged_main_thread; 126 errno = pthread_create(&storaged_main_thread, NULL, storaged_main, NULL); 127 if (errno != 0) { 128 PLOG(ERROR) << "Failed to create main thread"; 129 return -1; 130 } 131 132 if (StoragedService::start() != android::OK || 133 StoragedPrivateService::start() != android::OK) { 134 PLOG(ERROR) << "Failed to start storaged service"; 135 return -1; 136 } 137 138 android::ProcessState::self()->startThreadPool(); 139 IPCThreadState::self()->joinThreadPool(); 140 pthread_join(storaged_main_thread, NULL); 141 142 return 0; 143 } 144 145 sp<IStoragedPrivate> storaged_service = get_storaged_pri_service(); 146 if (storaged_service == NULL) { 147 fprintf(stderr, "Cannot find storaged service.\nMaybe run storaged --start first?\n"); 148 return -1; 149 } 150 151 if (flag_dump_uid || flag_dump_task) { 152 vector<UidInfo> uid_io; 153 binder::Status status = storaged_service->dumpUids(&uid_io); 154 if (!status.isOk() || uid_io.size() == 0) { 155 fprintf(stderr, "UID I/O info is not available.\n"); 156 return 0; 157 } 158 159 sort_running_uids_info(uid_io); 160 log_console_running_uids_info(uid_io, flag_dump_task); 161 } 162 163 if (flag_dump_perf) { 164 vector<int> perf_history; 165 binder::Status status = storaged_service->dumpPerfHistory(&perf_history); 166 if (!status.isOk() || perf_history.size() == 0) { 167 fprintf(stderr, "I/O perf history is not available.\n"); 168 return 0; 169 } 170 171 log_console_perf_history(perf_history); 172 } 173 174 return 0; 175 } 176