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