diff options
Diffstat (limited to 'storage')
-rw-r--r-- | storage/Android.bp | 18 | ||||
-rw-r--r-- | storage/dump_storage.cpp | 244 | ||||
-rw-r--r-- | storage/dump_storage.sh | 68 | ||||
-rw-r--r-- | storage/init.storage.rc | 1 | ||||
-rw-r--r-- | storage/sepolicy/dump_storage.te | 10 | ||||
-rw-r--r-- | storage/sepolicy/file.te | 3 | ||||
-rw-r--r-- | storage/sepolicy/file_contexts | 5 | ||||
-rw-r--r-- | storage/sepolicy/vendor_init.te | 1 | ||||
-rw-r--r-- | storage/storage.mk | 2 |
9 files changed, 277 insertions, 75 deletions
diff --git a/storage/Android.bp b/storage/Android.bp index c8671d1..3a06113 100644 --- a/storage/Android.bp +++ b/storage/Android.bp @@ -2,10 +2,20 @@ package { default_applicable_licenses: ["Android-Apache-2.0"], } -sh_binary { - name: "dump_storage.sh", - src: "dump_storage.sh", +cc_binary { + name: "dump_storage", + srcs: ["dump_storage.cpp"], init_rc: ["init.storage.rc"], + cflags: [ + "-Wall", + "-Wextra", + "-Werror", + ], + shared_libs: [ + "libbase", + "libdump", + "liblog", + ], vendor: true, - sub_dir: "dump", + relative_install_path: "dump", } diff --git a/storage/dump_storage.cpp b/storage/dump_storage.cpp new file mode 100644 index 0000000..e6b3e4c --- /dev/null +++ b/storage/dump_storage.cpp @@ -0,0 +1,244 @@ +/* + * Copyright 2023 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. + */ + +#include <dump/pixel_dump.h> +#include <android-base/file.h> +#include <android-base/stringprintf.h> +#include <android-base/properties.h> +#include <string.h> +#include <stdio.h> +#include <log/log.h> +#include <regex> +#include <fstream> +#include <map> + +#define F2FS_FSCK_TIME_PROPERTY "ro.boottime.init.fsck.data" +#define F2FS_MNT_TIME_PROPERTY "ro.boottime.init.mount.data" +#define BOOTDEVICE_PROPERTY "ro.boot.bootdevice" +#define BUILD_TYPE_PROPERTY "ro.build.type" + +void read_buffer(int buf_id, int total_len, const char* path) +{ + int i, len; + system("mkdir -m 0770 -p /data/vendor/storage/"); + auto cmd = android::base::StringPrintf("rm -f /data/vendor/storage/%s\n", path); + system(cmd.c_str()); + + for (i=0;i<=total_len;i+=524288) { + if (total_len-i < 524288) { + len = total_len-i; + printf("/vendor/bin/sg_read_buffer -m 0x1c -i %d -l %d -o %d -r /dev/sg3 >> /data/vendor/storage/%s\n", + buf_id, len, i, path); + auto cmd = android::base::StringPrintf( + "/vendor/bin/sg_read_buffer -m 0x1c -i %d -l %d -o %d -r /dev/sg3 >> /data/vendor/storage/%s\n", + buf_id, len, i, path); + system(cmd.c_str()); + break; + } + len = 524288; + printf("/vendor/bin/sg_read_buffer -m 0x1c -i %d -l %d -o %d -r /dev/sg3 >> /data/vendor/storage/%s\n", + buf_id, len, i, path); + auto cmd = android::base::StringPrintf( + "/vendor/bin/sg_read_buffer -m 0x1c -i %d -l %d -o %d -r /dev/sg3 >> /data/vendor/storage/%s\n", + buf_id, len, i, path); + system(cmd.c_str()); + } +} + +int main() { + //F2FS + dumpFileContent("F2FS status", "/sys/kernel/debug/f2fs/status"); + dumpFileContent("F2FS fsck", "/dev/fscklogs/fsck"); + + int fsck_time = android::base::GetIntProperty(F2FS_FSCK_TIME_PROPERTY, 0); + printf("--- F2FS - fsck time (ms) ---\n%d\n\n", fsck_time); + int mnt_time = android::base::GetIntProperty(F2FS_MNT_TIME_PROPERTY, 0); + printf("--- F2FS - checkpoint=disable time (ms) ---\n%d\n\n", mnt_time); + + //UFS + dumpFileContent("UFS model", "/sys/block/sda/device/model"); + dumpFileContent("UFS rev", "/sys/block/sda/device/rev"); + dumpFileContent("UFS size", "/sys/block/sda/size"); + + dumpFileContent("UFS Slow IO Read", + "/dev/sys/block/bootdevice/slowio_read_cnt"); + dumpFileContent("UFS Slow IO Write", + "/dev/sys/block/bootdevice/slowio_write_cnt"); + dumpFileContent("UFS Slow IO Unmap", + "/dev/sys/block/bootdevice/slowio_unmap_cnt"); + dumpFileContent("UFS Slow IO Sync", + "/dev/sys/block/bootdevice/slowio_sync_cnt"); + + printf("------ UFS err_stats ------\n"); + const std::string ufs_err_stats_path( + "/dev/sys/block/bootdevice/err_stats/"); + std::unique_ptr<DIR, decltype(&closedir)> statdir( + opendir(ufs_err_stats_path.c_str()), closedir); + if (statdir) { + dirent *stat_entry; + while ((stat_entry = readdir(statdir.get())) != nullptr) { + std::string ufs_err_stats_path(stat_entry->d_name); + if (!strcmp(ufs_err_stats_path.c_str(), ".") + || !strcmp(ufs_err_stats_path.c_str(), "..")) + continue; + std::string bootdevice = android::base::GetProperty( + BOOTDEVICE_PROPERTY, ""); + std::string err_stat_path = "/sys/devices/platform/"; + err_stat_path.append(bootdevice.c_str()); + err_stat_path.append("/err_stats/"); + err_stat_path.append(ufs_err_stats_path.c_str()); + std::ifstream err_stat_file(err_stat_path); + if (err_stat_file.is_open()) { + std::string err_stat_atom; + err_stat_file >> err_stat_atom; + printf("%s:%s\n", ufs_err_stats_path.c_str(), + err_stat_atom.c_str()); + err_stat_file.close(); + } + } + } + + printf("\n------ UFS io_stats ------\n"); + printf("\t\t%-12s %-12s %-12s %-12s %-12s %-12s\n", "ReadCnt", "ReadBytes", + "WriteCnt", "WriteBytes", "RWCnt", "RWBytes"); + const std::string ufs_io_stats = "/dev/sys/block/bootdevice/io_stats/"; + const std::string iostats_seq[3] = {"_start", "_complete", "_maxdiff"}; + const std::string iostats[6] = {"rcnt", "rbyte", "wcnt", "wbyte", "rwcnt", + "rwbyte"}; + + for (int i = 0; i < 3; i++) { + const std::string header[3] = {"Started: \t", "Completed: \t", + "MaxDiff: \t"}; + printf("%s", header[i].c_str()); + for (int j = 0; j < 6; j++) { + std::string iostat_path = ufs_io_stats.c_str(); + iostat_path.append(iostats[j].c_str()); + iostat_path.append(iostats_seq[i].c_str()); + std::ifstream io_stats_file(iostat_path.c_str()); + unsigned long io_stat_atom = 0; + if (io_stats_file.is_open()) { + io_stats_file >> io_stat_atom; + printf("%-12lu ", io_stat_atom); + io_stats_file.close(); + } + } + printf("\n"); + } + + printf("\n------ UFS req_stats ------\n"); + printf("\t%-12s %-12s %-12s %-12s %-12s %-12s\n", "All", "Write", "Read", + "Security", "Flush", "Discard"); + const std::string ufs_req_stats = "/dev/sys/block/bootdevice/req_stats/"; + const std::string reqstats_seq[4] = {"_min", "_max", "_avg", "_sum"}; + const std::string reqstats[6] = {"all", "write", "read", "security", + "flush", "discard"}; + + for (int i = 0; i < 4; i++) { + const std::string header[4] = {"Min:\t", "Max: \t", "Avg: \t", + "Count: \t"}; + printf("%s", header[i].c_str()); + for (int j = 0; j < 6; j++) { + std::string reqstat_path = ufs_req_stats.c_str(); + reqstat_path.append(reqstats[j].c_str()); + reqstat_path.append(reqstats_seq[i].c_str()); + std::ifstream req_stats_file(reqstat_path.c_str()); + unsigned long req_stat_atom = 0; + if (req_stats_file.is_open()) { + req_stats_file >> req_stat_atom; + printf("%-12lu ", req_stat_atom); + req_stats_file.close(); + } + } + printf("\n"); + } + + printf("\n------ UFS health ------\n"); + dumpFileContent( + "", + "/dev/sys/block/bootdevice/health_descriptor/life_time_estimation_a"); + dumpFileContent( + "", + "/dev/sys/block/bootdevice/health_descriptor/life_time_estimation_b"); + dumpFileContent("", "/dev/sys/block/bootdevice/health_descriptor/eol_info"); + dumpFileContent( + "", + "/dev/sys/block/bootdevice/health_descriptor/life_time_estimation_c"); + + printf("\n------ UFS error history ------\n"); + std::string build_type = android::base::GetProperty(BUILD_TYPE_PROPERTY, ""); + if (build_type == "userdebug") { + std::string sg_read_buffer = "/vendor/bin/sg_read_buffer"; + std::ifstream sg_read_buffer_file(sg_read_buffer.c_str()); + if (sg_read_buffer_file.is_open()) { + const std::string ufs_ver_path( + "/dev/sys/block/bootdevice/device_descriptor/specification_version"); + std::ifstream ufs_ver_file(ufs_ver_path); + std::string ufs_ver; + if (ufs_ver_file.is_open()) { + ufs_ver_file >> ufs_ver; + ufs_ver_file.close(); + } + if (strcmp(ufs_ver.c_str(), "0x0210")) { + const std::string ufs_brand_path("/sys/block/sda/device/vendor"); + std::ifstream ufs_brand_file(ufs_brand_path); + std::string ufs_brand; + if (ufs_brand_file.is_open()) { + ufs_brand_file >> ufs_brand; + ufs_brand_file.close(); + } + + std::map<std::string, int> const table = + { + {"MICRON", 0x12C}, + {"KIOXIA", 0x198}, + {"SKhynix", 0x1AD}, + {"SAMSUNG", 0x1CE} + }; + auto ufs_vendor_id = table.find(ufs_brand); + if (ufs_vendor_id != table.end()) { + switch(ufs_vendor_id->second){ + case 0x12C: //MICRON + read_buffer(16, 2097152, "micron_10_ufs_err_history.dat"); + read_buffer(18, 10485760, "micron_12_ufs_err_history.dat"); + read_buffer(19, 10485760, "micron_13_ufs_err_history.dat"); + break; + case 0x198: //KIOXIA + read_buffer(16, 16773120, "kioxia_10_ufs_err_history.dat"); + read_buffer(17, 2097152, "kioxia_11_ufs_err_history.dat"); + read_buffer(18, 131072, "kioxia_12_ufs_err_history.dat"); + break; + case 0x1AD: //SKhynix + read_buffer(0, 4096, "hynix_00_ufs_err_history.dat"); + read_buffer(16, 131072, "skhynix_10_ufs_err_history.dat"); + read_buffer(17, 131072, "skhynix_11_ufs_err_history.dat"); + read_buffer(18, 131072, "skhynix_12_ufs_err_history.dat"); + read_buffer(19, 131072, "skhynix_13_ufs_err_history.dat"); + break; + case 0x1CE: //SAMSUNG + read_buffer(16, 8404992, "samsung_10_ufs_err_history.dat"); + break; + default: + break; + } + } + sg_read_buffer_file.close(); + } + } else + printf("sg_read_buffer does not exist\n"); + } + + return 0; +} diff --git a/storage/dump_storage.sh b/storage/dump_storage.sh deleted file mode 100644 index 5f08fc1..0000000 --- a/storage/dump_storage.sh +++ /dev/null @@ -1,68 +0,0 @@ -#!/vendor/bin/sh -# F2FS -echo "--- F2FS status---" -cat "/sys/kernel/debug/f2fs/status" -echo "\n--- F2FS fsck ---" -cat "/dev/fscklogs/fsck" -echo "\n--- F2FS - fsck time (ms) ---" -getprop ro.boottime.init.fsck.data -echo "\n--- F2FS - checkpoint=disable time (ms) ---" -getprop ro.boottime.init.mount.data - -# UFS -echo "\n------ UFS model (/sys/block/sda/device/model) ------" -cat "/sys/block/sda/device/model" -echo "\n------ UFS rev (/sys/block/sda/device/rev) ------" -cat "/sys/block/sda/device/rev" -echo "\n------ UFS size (/sys/block/sda/size) ------" -cat "/sys/block/sda/size" - -echo "\n------ UFS Slow IO Read (/dev/sys/block/bootdevice/slowio_read_cnt) ------" -cat "/dev/sys/block/bootdevice/slowio_read_cnt" -echo "\n------ UFS Slow IO Write (/dev/sys/block/bootdevice/slowio_write_cnt) ------" -cat "/dev/sys/block/bootdevice/slowio_write_cnt" -echo "\n------ UFS Slow IO Unmap (/dev/sys/block/bootdevice/slowio_unmap_cnt) ------" -cat "/dev/sys/block/bootdevice/slowio_unmap_cnt" -echo "\n------ UFS Slow IO Sync (/dev/sys/block/bootdevice/slowio_sync_cnt) ------" -cat "/dev/sys/block/bootdevice/slowio_sync_cnt" - -echo "\n------ UFS err_stats ------" -path="/dev/sys/block/bootdevice/err_stats"; -for node in `ls $path/* | grep -v reset_err_status` -do - printf "%s:%d\n" $(basename $node) $(cat $node) -done - - -echo "\n------ UFS io_stats ------" -path="/dev/sys/block/bootdevice/io_stats" -printf "\t\t%-12s %-12s %-12s %-12s %-12s %-12s\n" ReadCnt ReadBytes WriteCnt WriteBytes RWCnt RWBytes -str=$(cat $path/*_start); arr=($str); -printf "Started: \t%-12s %-12s %-12s %-12s %-12s %-12s\n" ${arr[1]} ${arr[0]} ${arr[5]} ${arr[4]} ${arr[3]} ${arr[2]} -str=$(cat $path/*_complete); arr=($str); -printf "Completed: \t%-12s %-12s %-12s %-12s %-12s %-12s\n" ${arr[1]} ${arr[0]} ${arr[5]} ${arr[4]} ${arr[3]} ${arr[2]} -str=$(cat $path/*_maxdiff); arr=($str); -printf "MaxDiff: \t%-12s %-12s %-12s %-12s %-12s %-12s\n\n" ${arr[1]} ${arr[0]} ${arr[5]} ${arr[4]} ${arr[3]} ${arr[2]} - -echo "\n------ UFS req_stats ------" -path="/dev/sys/block/bootdevice/req_stats" -printf "\t%-12s %-12s %-12s %-12s %-12s %-12s\n" All Write Read Security Flush Discard -str=$(cat $path/*_min); arr=($str); -printf "Min:\t%-12s %-12s %-12s %-12s %-12s %-12s\n" ${arr[0]} ${arr[5]} ${arr[3]} ${arr[4]} ${arr[2]} ${arr[1]} -str=$(cat $path/*_max); arr=($str); -printf "Max:\t%-12s %-12s %-12s %-12s %-12s %-12s\n" ${arr[0]} ${arr[5]} ${arr[3]} ${arr[4]} ${arr[2]} ${arr[1]} -str=$(cat $path/*_avg); arr=($str); -printf "Avg.:\t%-12s %-12s %-12s %-12s %-12s %-12s\n" ${arr[0]} ${arr[5]} ${arr[3]} ${arr[4]} ${arr[2]} ${arr[1]} -str=$(cat $path/*_sum); arr=($str); -printf "Count:\t%-12s %-12s %-12s %-12s %-12s %-12s\n\n" ${arr[0]} ${arr[5]} ${arr[3]} ${arr[4]} ${arr[2]} ${arr[1]} - -echo "\n------ UFS health ------" -for f in $(find /dev/sys/block/bootdevice/health_descriptor -type f) -do - if [[ -r $f && -f $f ]]; then - echo --- $f - cat $f - echo '' - fi -done - diff --git a/storage/init.storage.rc b/storage/init.storage.rc index 445f74b..56e8e4f 100644 --- a/storage/init.storage.rc +++ b/storage/init.storage.rc @@ -1,2 +1,3 @@ on property:ro.build.type=userdebug write /dev/sys/block/bootdevice/pixel/enable_pixel_ufs_logging 1 + chown system /dev/sg3 diff --git a/storage/sepolicy/dump_storage.te b/storage/sepolicy/dump_storage.te index 9411f8e..5324c17 100644 --- a/storage/sepolicy/dump_storage.te +++ b/storage/sepolicy/dump_storage.te @@ -1,12 +1,20 @@ pixel_bugreport(dump_storage) -allow dump_storage vendor_toolbox_exec:file execute_no_trans; allow dump_storage sysfs_scsi_devices_0000:dir r_dir_perms; allow dump_storage sysfs_scsi_devices_0000:file r_file_perms; userdebug_or_eng(` allow dump_storage debugfs_f2fs:dir r_dir_perms; allow dump_storage debugfs_f2fs:file r_file_perms; + allow dump_storage sg_device:chr_file rw_file_perms; + allow dump_storage proc:file r_file_perms; + allow dump_storage vendor_shell_exec:file execute_no_trans; + allow dump_storage vendor_toolbox_exec:file execute_no_trans; + allow dump_storage sg_util_exec:file execute_no_trans; + allow dump_storage vendor_data_file:dir create_dir_perms; + allow dump_storage vendor_data_file:file create_file_perms; + allow dump_storage dump_storage_data_file:dir rw_dir_perms; + allow dump_storage dump_storage_data_file:file create_file_perms; ') get_prop(dump_storage, boottime_public_prop) diff --git a/storage/sepolicy/file.te b/storage/sepolicy/file.te index 64b6b4e..ed4f925 100644 --- a/storage/sepolicy/file.te +++ b/storage/sepolicy/file.te @@ -1 +1,4 @@ type debugfs_f2fs, debugfs_type, fs_type; +type dump_storage_data_file, file_type, data_file_type; +type sg_device, dev_type; +type sg_util_exec, exec_type, vendor_file_type, file_type; diff --git a/storage/sepolicy/file_contexts b/storage/sepolicy/file_contexts index a0efd28..ecca954 100644 --- a/storage/sepolicy/file_contexts +++ b/storage/sepolicy/file_contexts @@ -1,2 +1,5 @@ -/vendor/bin/dump/dump_storage\.sh u:object_r:dump_storage_exec:s0 +/vendor/bin/dump/dump_storage u:object_r:dump_storage_exec:s0 /sys/devices/platform/[0-9]+\.ufs/pixel/enable_pixel_ufs_logging u:object_r:sysfs_scsi_devices_0000:s0 +/dev/sg[0-9] u:object_r:sg_device:s0 +/data/vendor/storage(/.*)? u:object_r:dump_storage_data_file:s0 +/vendor/bin/sg_read_buffer u:object_r:sg_util_exec:s0 diff --git a/storage/sepolicy/vendor_init.te b/storage/sepolicy/vendor_init.te new file mode 100644 index 0000000..da4fcba --- /dev/null +++ b/storage/sepolicy/vendor_init.te @@ -0,0 +1 @@ +allow vendor_init sg_device:chr_file r_file_perms; diff --git a/storage/storage.mk b/storage/storage.mk index cd0556d..ee7110c 100644 --- a/storage/storage.mk +++ b/storage/storage.mk @@ -1,6 +1,6 @@ BOARD_VENDOR_SEPOLICY_DIRS += device/google/gs-common/storage/sepolicy -PRODUCT_PACKAGES += dump_storage.sh +PRODUCT_PACKAGES += dump_storage # Pixel storage tool PRODUCT_PACKAGES_DEBUG += \ |