xref: /aosp_15_r20/system/extras/boottime_tools/bootio/bootio.cpp (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker  * Copyright (C) 2016 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker  *
4*288bf522SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*288bf522SAndroid Build Coastguard Worker  *
8*288bf522SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker  *
10*288bf522SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker  * limitations under the License.
15*288bf522SAndroid Build Coastguard Worker  */
16*288bf522SAndroid Build Coastguard Worker 
17*288bf522SAndroid Build Coastguard Worker // The bootio tool provides options to collect I/O stats for processes during boot.
18*288bf522SAndroid Build Coastguard Worker 
19*288bf522SAndroid Build Coastguard Worker #include <vector>
20*288bf522SAndroid Build Coastguard Worker #include <getopt.h>
21*288bf522SAndroid Build Coastguard Worker #include <unistd.h>
22*288bf522SAndroid Build Coastguard Worker #include <android-base/file.h>
23*288bf522SAndroid Build Coastguard Worker #include <android-base/logging.h>
24*288bf522SAndroid Build Coastguard Worker #include <android-base/strings.h>
25*288bf522SAndroid Build Coastguard Worker #include <log/log.h>
26*288bf522SAndroid Build Coastguard Worker 
27*288bf522SAndroid Build Coastguard Worker #include "bootio_collector.h"
28*288bf522SAndroid Build Coastguard Worker 
29*288bf522SAndroid Build Coastguard Worker namespace android {
30*288bf522SAndroid Build Coastguard Worker 
31*288bf522SAndroid Build Coastguard Worker #define LOG_ROOT           "/data/misc/bootio"
32*288bf522SAndroid Build Coastguard Worker #define LOG_START_FILE      LOG_ROOT"/start"
33*288bf522SAndroid Build Coastguard Worker #define SELF_IO            "/proc/self/io"
34*288bf522SAndroid Build Coastguard Worker 
35*288bf522SAndroid Build Coastguard Worker static const int LOG_TIMEOUT_INDEX = 0;
36*288bf522SAndroid Build Coastguard Worker static const int LOG_SAMPLES_INDEX = 1;
37*288bf522SAndroid Build Coastguard Worker static const int LOG_MAX_TIMEOUT = 120;
38*288bf522SAndroid Build Coastguard Worker static const int LOG_MAX_SAMPLES = 30;
39*288bf522SAndroid Build Coastguard Worker 
ShowHelp(const char * cmd)40*288bf522SAndroid Build Coastguard Worker void ShowHelp(const char *cmd) {
41*288bf522SAndroid Build Coastguard Worker     fprintf(stderr, "Usage: %s [options]\n", cmd);
42*288bf522SAndroid Build Coastguard Worker     fprintf(stderr,
43*288bf522SAndroid Build Coastguard Worker             "options include:\n"
44*288bf522SAndroid Build Coastguard Worker                     "  -h, --help            Show this help\n"
45*288bf522SAndroid Build Coastguard Worker                     "  -p, --print           Dump the boot io data to the console\n"
46*288bf522SAndroid Build Coastguard Worker                     "\nNo options will start data collection process.\n");
47*288bf522SAndroid Build Coastguard Worker }
48*288bf522SAndroid Build Coastguard Worker 
PrintBootIo()49*288bf522SAndroid Build Coastguard Worker void PrintBootIo() {
50*288bf522SAndroid Build Coastguard Worker     printf("Boot I/O:\n");
51*288bf522SAndroid Build Coastguard Worker     printf("------------\n");
52*288bf522SAndroid Build Coastguard Worker     std::unique_ptr <BootioCollector> collector(new BootioCollector(LOG_ROOT));
53*288bf522SAndroid Build Coastguard Worker     if (collector.get() == NULL) {
54*288bf522SAndroid Build Coastguard Worker         LOG(ERROR) << "Failed to create data collector";
55*288bf522SAndroid Build Coastguard Worker         return;
56*288bf522SAndroid Build Coastguard Worker     }
57*288bf522SAndroid Build Coastguard Worker     collector->Print();
58*288bf522SAndroid Build Coastguard Worker }
59*288bf522SAndroid Build Coastguard Worker 
StartDataCollection()60*288bf522SAndroid Build Coastguard Worker void StartDataCollection() {
61*288bf522SAndroid Build Coastguard Worker     if (access(SELF_IO, F_OK) == -1) {
62*288bf522SAndroid Build Coastguard Worker         LOG(ERROR) << "Kernel doesn't support I/O profiling.";
63*288bf522SAndroid Build Coastguard Worker         printf("Kernel doesn't support I/O profiling.");
64*288bf522SAndroid Build Coastguard Worker         return;
65*288bf522SAndroid Build Coastguard Worker     }
66*288bf522SAndroid Build Coastguard Worker 
67*288bf522SAndroid Build Coastguard Worker     int timeout = 0;
68*288bf522SAndroid Build Coastguard Worker     int samples = 0;
69*288bf522SAndroid Build Coastguard Worker 
70*288bf522SAndroid Build Coastguard Worker     std::string start;
71*288bf522SAndroid Build Coastguard Worker     android::base::ReadFileToString(LOG_START_FILE, &start);
72*288bf522SAndroid Build Coastguard Worker 
73*288bf522SAndroid Build Coastguard Worker     if (!start.empty()) {
74*288bf522SAndroid Build Coastguard Worker         std::vector <std::string> components = android::base::Split(start, " ");
75*288bf522SAndroid Build Coastguard Worker         if (components.size() != 2) {
76*288bf522SAndroid Build Coastguard Worker             LOG(ERROR) << "Invalid value in start file." << start;
77*288bf522SAndroid Build Coastguard Worker             return;
78*288bf522SAndroid Build Coastguard Worker         }
79*288bf522SAndroid Build Coastguard Worker         timeout = atoi(components.at(LOG_TIMEOUT_INDEX).c_str());
80*288bf522SAndroid Build Coastguard Worker         samples = atoi(components.at(LOG_SAMPLES_INDEX).c_str());
81*288bf522SAndroid Build Coastguard Worker     } else {
82*288bf522SAndroid Build Coastguard Worker         LOG(INFO) << "No profiling requested. Exiting";
83*288bf522SAndroid Build Coastguard Worker         printf("Boot I/O: no profiling requested. Exiting.\n");
84*288bf522SAndroid Build Coastguard Worker         return;
85*288bf522SAndroid Build Coastguard Worker     }
86*288bf522SAndroid Build Coastguard Worker     if (timeout <= 0 || samples <= 0) {
87*288bf522SAndroid Build Coastguard Worker         LOG(ERROR) << "Boot I/O: failed to parse string:" << start;
88*288bf522SAndroid Build Coastguard Worker         printf("Boot I/O: failed to parse string: %s\n", start.c_str());
89*288bf522SAndroid Build Coastguard Worker         return;
90*288bf522SAndroid Build Coastguard Worker     }
91*288bf522SAndroid Build Coastguard Worker     if (samples > timeout || samples > LOG_MAX_SAMPLES || timeout > LOG_MAX_TIMEOUT) {
92*288bf522SAndroid Build Coastguard Worker         LOG(ERROR) << "Bad values for bootio. timeout=" << timeout <<
93*288bf522SAndroid Build Coastguard Worker         " samples=" << samples << " Max timeout=" << LOG_MAX_TIMEOUT <<
94*288bf522SAndroid Build Coastguard Worker         " Max samples=" << LOG_MAX_SAMPLES;
95*288bf522SAndroid Build Coastguard Worker         return;
96*288bf522SAndroid Build Coastguard Worker     }
97*288bf522SAndroid Build Coastguard Worker     LOG(INFO) << "Boot I/O: collecting data. samples=" << samples << "timeout=" << timeout;
98*288bf522SAndroid Build Coastguard Worker     printf("Boot I/O: collecting data\ntimeout=%d, samples=%d\n",
99*288bf522SAndroid Build Coastguard Worker            timeout, samples);
100*288bf522SAndroid Build Coastguard Worker     std::unique_ptr <BootioCollector> collector(new BootioCollector(LOG_ROOT));
101*288bf522SAndroid Build Coastguard Worker     if (collector.get() == NULL) {
102*288bf522SAndroid Build Coastguard Worker         LOG(ERROR) << "Failed to create data collector";
103*288bf522SAndroid Build Coastguard Worker         return;
104*288bf522SAndroid Build Coastguard Worker     }
105*288bf522SAndroid Build Coastguard Worker     collector->StartDataCollection(timeout, samples);
106*288bf522SAndroid Build Coastguard Worker }
107*288bf522SAndroid Build Coastguard Worker 
108*288bf522SAndroid Build Coastguard Worker }
109*288bf522SAndroid Build Coastguard Worker 
main(int argc,char ** argv)110*288bf522SAndroid Build Coastguard Worker int main(int argc, char **argv) {
111*288bf522SAndroid Build Coastguard Worker     android::base::InitLogging(argv);
112*288bf522SAndroid Build Coastguard Worker 
113*288bf522SAndroid Build Coastguard Worker     LOG(INFO) << "Bootio started";
114*288bf522SAndroid Build Coastguard Worker 
115*288bf522SAndroid Build Coastguard Worker     int optionIndex = 0;
116*288bf522SAndroid Build Coastguard Worker     static const struct option longOptions[] = {
117*288bf522SAndroid Build Coastguard Worker             {"help",  no_argument, NULL, 'h'},
118*288bf522SAndroid Build Coastguard Worker             {"print", no_argument, NULL, 'p'},
119*288bf522SAndroid Build Coastguard Worker             {NULL,    0,           NULL, 0}
120*288bf522SAndroid Build Coastguard Worker     };
121*288bf522SAndroid Build Coastguard Worker 
122*288bf522SAndroid Build Coastguard Worker     int opt = 0;
123*288bf522SAndroid Build Coastguard Worker     bool startCollection = true;
124*288bf522SAndroid Build Coastguard Worker     while ((opt = getopt_long(argc, argv, "hlpr:", longOptions, &optionIndex)) != -1) {
125*288bf522SAndroid Build Coastguard Worker         switch (opt) {
126*288bf522SAndroid Build Coastguard Worker             case 0: {
127*288bf522SAndroid Build Coastguard Worker                 const std::string option_name = longOptions[optionIndex].name;
128*288bf522SAndroid Build Coastguard Worker                 LOG(ERROR) << "Invalid option: " << option_name;
129*288bf522SAndroid Build Coastguard Worker                 break;
130*288bf522SAndroid Build Coastguard Worker             }
131*288bf522SAndroid Build Coastguard Worker 
132*288bf522SAndroid Build Coastguard Worker             case 'h': {
133*288bf522SAndroid Build Coastguard Worker                 android::ShowHelp(argv[0]);
134*288bf522SAndroid Build Coastguard Worker                 startCollection = false;
135*288bf522SAndroid Build Coastguard Worker                 break;
136*288bf522SAndroid Build Coastguard Worker             }
137*288bf522SAndroid Build Coastguard Worker 
138*288bf522SAndroid Build Coastguard Worker             case 'p': {
139*288bf522SAndroid Build Coastguard Worker                 android::PrintBootIo();
140*288bf522SAndroid Build Coastguard Worker                 startCollection = false;
141*288bf522SAndroid Build Coastguard Worker                 break;
142*288bf522SAndroid Build Coastguard Worker             }
143*288bf522SAndroid Build Coastguard Worker 
144*288bf522SAndroid Build Coastguard Worker             default: {
145*288bf522SAndroid Build Coastguard Worker                 DCHECK_EQ(opt, '?');
146*288bf522SAndroid Build Coastguard Worker 
147*288bf522SAndroid Build Coastguard Worker                 // |optopt| is an external variable set by getopt representing
148*288bf522SAndroid Build Coastguard Worker                 // the value of the invalid option.
149*288bf522SAndroid Build Coastguard Worker                 LOG(ERROR) << "Invalid option: " << optopt;
150*288bf522SAndroid Build Coastguard Worker                 android::ShowHelp(argv[0]);
151*288bf522SAndroid Build Coastguard Worker                 return EXIT_FAILURE;
152*288bf522SAndroid Build Coastguard Worker             }
153*288bf522SAndroid Build Coastguard Worker         }
154*288bf522SAndroid Build Coastguard Worker     }
155*288bf522SAndroid Build Coastguard Worker 
156*288bf522SAndroid Build Coastguard Worker     if (startCollection) {
157*288bf522SAndroid Build Coastguard Worker         android::StartDataCollection();
158*288bf522SAndroid Build Coastguard Worker     }
159*288bf522SAndroid Build Coastguard Worker 
160*288bf522SAndroid Build Coastguard Worker     return 0;
161*288bf522SAndroid Build Coastguard Worker }
162*288bf522SAndroid Build Coastguard Worker 
163