dumpstate: report per-partition MMC performance
(Cherry pick from commit 540e3de99f
)
Change-Id: If5cabe186d8377056effa1c0672a90e277cd7221
This commit is contained in:
parent
ba9e1f4241
commit
326842fca4
@ -99,6 +99,67 @@ static void dump_dev_files(const char *title, const char *driverpath, const char
|
|||||||
closedir(d);
|
closedir(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool skip_not_stat(const char *path) {
|
||||||
|
static const char stat[] = "/stat";
|
||||||
|
size_t len = strlen(path);
|
||||||
|
if (path[len - 1] == '/') { /* Directory? */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char mmcblk0[] = "/sys/block/mmcblk0/";
|
||||||
|
|
||||||
|
static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
|
||||||
|
unsigned long fields[11], read_perf, write_perf;
|
||||||
|
bool z;
|
||||||
|
char *cp, *buffer = NULL;
|
||||||
|
size_t i = 0;
|
||||||
|
FILE *fp = fdopen(fd, "rb");
|
||||||
|
getline(&buffer, &i, fp);
|
||||||
|
fclose(fp);
|
||||||
|
if (!buffer) {
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
i = strlen(buffer);
|
||||||
|
while ((i > 0) && (buffer[i - 1] == '\n')) {
|
||||||
|
buffer[--i] = '\0';
|
||||||
|
}
|
||||||
|
if (!*buffer) {
|
||||||
|
free(buffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
z = true;
|
||||||
|
for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
|
||||||
|
fields[i] = strtol(cp, &cp, 0);
|
||||||
|
if (fields[i] != 0) {
|
||||||
|
z = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (z) { /* never accessed */
|
||||||
|
free(buffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strncmp(path, mmcblk0, sizeof(mmcblk0) - 1)) {
|
||||||
|
path += sizeof(mmcblk0) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s: %s\n", path, buffer);
|
||||||
|
free(buffer);
|
||||||
|
|
||||||
|
read_perf = 0;
|
||||||
|
if (fields[3]) {
|
||||||
|
read_perf = 512 * fields[2] / fields[3];
|
||||||
|
}
|
||||||
|
write_perf = 0;
|
||||||
|
if (fields[7]) {
|
||||||
|
write_perf = 512 * fields[6] / fields[7];
|
||||||
|
}
|
||||||
|
printf("%s: read: %luKB/s write: %luKB/s\n", path, read_perf, write_perf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* dumps the current system state to stdout */
|
/* dumps the current system state to stdout */
|
||||||
static void dumpstate() {
|
static void dumpstate() {
|
||||||
time_t now = time(NULL);
|
time_t now = time(NULL);
|
||||||
@ -133,7 +194,7 @@ static void dumpstate() {
|
|||||||
|
|
||||||
dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
|
dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
|
||||||
run_command("UPTIME", 10, "uptime", NULL);
|
run_command("UPTIME", 10, "uptime", NULL);
|
||||||
dump_file("MMC PERF", "/sys/block/mmcblk0/stat");
|
dump_files("UPTIME MMC PERF", mmcblk0, skip_not_stat, dump_stat_from_fd);
|
||||||
dump_file("MEMORY INFO", "/proc/meminfo");
|
dump_file("MEMORY INFO", "/proc/meminfo");
|
||||||
run_command("CPU INFO", 10, "top", "-n", "1", "-d", "1", "-m", "30", "-t", NULL);
|
run_command("CPU INFO", 10, "top", "-n", "1", "-d", "1", "-m", "30", "-t", NULL);
|
||||||
run_command("PROCRANK", 20, "procrank", NULL);
|
run_command("PROCRANK", 20, "procrank", NULL);
|
||||||
|
@ -35,6 +35,16 @@ int dump_file(const char *title, const char *path);
|
|||||||
*/
|
*/
|
||||||
int dump_file_from_fd(const char *title, const char *path, int fd);
|
int dump_file_from_fd(const char *title, const char *path, int fd);
|
||||||
|
|
||||||
|
/* calls skip to gate calling dump_from_fd recursively
|
||||||
|
* in the specified directory. dump_from_fd defaults to
|
||||||
|
* dump_file_from_fd above when set to NULL. skip defaults
|
||||||
|
* to false when set to NULL. dump_from_fd will always be
|
||||||
|
* called with title NULL.
|
||||||
|
*/
|
||||||
|
int dump_files(const char *title, const char *dir,
|
||||||
|
bool (*skip)(const char *path),
|
||||||
|
int (*dump_from_fd)(const char *title, const char *path, int fd));
|
||||||
|
|
||||||
/* forks a command and waits for it to finish -- terminate args with NULL */
|
/* forks a command and waits for it to finish -- terminate args with NULL */
|
||||||
int run_command(const char *title, int timeout_seconds, const char *command, ...);
|
int run_command(const char *title, int timeout_seconds, const char *command, ...);
|
||||||
|
|
||||||
|
@ -310,6 +310,75 @@ int dump_file(const char *title, const char *path) {
|
|||||||
return _dump_file_from_fd(title, path, fd);
|
return _dump_file_from_fd(title, path, fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* calls skip to gate calling dump_from_fd recursively
|
||||||
|
* in the specified directory. dump_from_fd defaults to
|
||||||
|
* dump_file_from_fd above when set to NULL. skip defaults
|
||||||
|
* to false when set to NULL. dump_from_fd will always be
|
||||||
|
* called with title NULL.
|
||||||
|
*/
|
||||||
|
int dump_files(const char *title, const char *dir,
|
||||||
|
bool (*skip)(const char *path),
|
||||||
|
int (*dump_from_fd)(const char *title, const char *path, int fd)) {
|
||||||
|
DIR *dirp;
|
||||||
|
struct dirent *d;
|
||||||
|
char *newpath = NULL;
|
||||||
|
char *slash = "/";
|
||||||
|
int fd, retval = 0;
|
||||||
|
|
||||||
|
if (title) {
|
||||||
|
printf("------ %s (%s) ------\n", title, dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dir[strlen(dir) - 1] == '/') {
|
||||||
|
++slash;
|
||||||
|
}
|
||||||
|
dirp = opendir(dir);
|
||||||
|
if (dirp == NULL) {
|
||||||
|
retval = -errno;
|
||||||
|
fprintf(stderr, "%s: %s\n", dir, strerror(errno));
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dump_from_fd) {
|
||||||
|
dump_from_fd = dump_file_from_fd;
|
||||||
|
}
|
||||||
|
for (; ((d = readdir(dirp))); free(newpath), newpath = NULL) {
|
||||||
|
if ((d->d_name[0] == '.')
|
||||||
|
&& (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
|
||||||
|
|| (d->d_name[1] == '\0'))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
|
||||||
|
(d->d_type == DT_DIR) ? "/" : "");
|
||||||
|
if (!newpath) {
|
||||||
|
retval = -errno;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (skip && (*skip)(newpath)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (d->d_type == DT_DIR) {
|
||||||
|
int ret = dump_files(NULL, newpath, skip, dump_from_fd);
|
||||||
|
if (ret < 0) {
|
||||||
|
retval = ret;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
fd = TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
|
||||||
|
if (fd < 0) {
|
||||||
|
retval = fd;
|
||||||
|
printf("*** %s: %s\n", newpath, strerror(errno));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
(*dump_from_fd)(NULL, newpath, fd);
|
||||||
|
}
|
||||||
|
closedir(dirp);
|
||||||
|
if (title) {
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
|
/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
|
||||||
* it's possible to avoid issues where opening the file itself can get
|
* it's possible to avoid issues where opening the file itself can get
|
||||||
* stuck.
|
* stuck.
|
||||||
|
Loading…
Reference in New Issue
Block a user