storaged: track fsync calls

Change-Id: Ibdb6a1703245a5de04cb4a2ee5b8ecfbed8b86fc
diff --git a/storaged/include/storaged_uid_monitor.h b/storaged/include/storaged_uid_monitor.h
index b32c9a0..901a872 100644
--- a/storaged/include/storaged_uid_monitor.h
+++ b/storaged/include/storaged_uid_monitor.h
@@ -46,6 +46,7 @@
     uint64_t wchar;                 // characters written
     uint64_t read_bytes;            // bytes read (from storage layer)
     uint64_t write_bytes;           // bytes written (to storage layer)
+    uint64_t fsync;                 // number of fsync syscalls
 };
 
 struct uid_info {
diff --git a/storaged/storaged_uid_monitor.cpp b/storaged/storaged_uid_monitor.cpp
index 78e0a83..8bb6bf3 100644
--- a/storaged/storaged_uid_monitor.cpp
+++ b/storaged/storaged_uid_monitor.cpp
@@ -20,12 +20,12 @@
 #include <time.h>
 
 #include <string>
-#include <sstream>
 #include <unordered_map>
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/macros.h>
+#include <android-base/strings.h>
 #include <android-base/stringprintf.h>
 #include <log/log_event_list.h>
 #include <packagelistparser/packagelistparser.h>
@@ -64,19 +64,33 @@
         return uid_io_stats;
     }
 
-    std::stringstream ss(buffer);
+    std::vector<std::string> io_stats = android::base::Split(buffer, "\n");
     struct uid_info u;
     bool refresh_uid = false;
 
-    while (ss >> u.uid) {
-        ss >> u.io[FOREGROUND].rchar >> u.io[FOREGROUND].wchar
-           >> u.io[FOREGROUND].read_bytes >> u.io[FOREGROUND].write_bytes
-           >> u.io[BACKGROUND].rchar >> u.io[BACKGROUND].wchar
-           >> u.io[BACKGROUND].read_bytes >> u.io[BACKGROUND].write_bytes;
+    for (uint32_t i = 0; i < io_stats.size(); i++) {
+        if (io_stats[i].empty()) {
+            continue;
+        }
+        std::vector<std::string> fields = android::base::Split(io_stats[i], " ");
+        if (fields.size() < 9) {
+            LOG_TO(SYSTEM, WARNING) << "Invalid io stats: \""
+                                    << io_stats[i] << "\"";
+            continue;
+        }
+        u.uid = stoul(fields[0]);
+        u.io[FOREGROUND].rchar = stoull(fields[1]);
+        u.io[FOREGROUND].wchar = stoull(fields[2]);
+        u.io[FOREGROUND].read_bytes = stoull(fields[3]);
+        u.io[FOREGROUND].write_bytes = stoull(fields[4]);
+        u.io[BACKGROUND].rchar = stoull(fields[5]);
+        u.io[BACKGROUND].wchar = stoull(fields[6]);
+        u.io[BACKGROUND].read_bytes = stoull(fields[7]);
+        u.io[BACKGROUND].write_bytes = stoull(fields[8]);
 
-        if (!ss.good()) {
-            ss.clear(std::ios_base::badbit);
-            break;
+        if (fields.size() == 11) {
+            u.io[FOREGROUND].fsync = stoull(fields[9]);
+            u.io[BACKGROUND].fsync = stoull(fields[10]);
         }
 
         if (last_uid_io_stats.find(u.uid) == last_uid_io_stats.end()) {
@@ -88,11 +102,6 @@
         uid_io_stats[u.uid] = u;
     }
 
-    if (!ss.eof() || ss.bad()) {
-        uid_io_stats.clear();
-        LOG_TO(SYSTEM, ERROR) << "read UID IO stats failed";
-    }
-
     if (refresh_uid) {
         packagelist_parse(packagelist_parse_cb, &uid_io_stats);
     }
diff --git a/storaged/storaged_utils.cpp b/storaged/storaged_utils.cpp
index 1ef89af..5df0185 100644
--- a/storaged/storaged_utils.cpp
+++ b/storaged/storaged_utils.cpp
@@ -281,14 +281,15 @@
 
     // Title
     printf("Per-UID I/O stats\n");
-    printf("                                       Application        FG Read       FG Write        FG Read       FG Write        BG Read       BG Write        BG Read       BG Write\n"
-           "                                          NAME/UID     Characters     Characters          Bytes          Bytes     Characters     Characters          Bytes          Bytes\n"
-           "                                        ----------     ----------     ----------     ----------     ----------     ----------     ----------     ----------     ----------\n");
+    printf("                                       Application        FG Read       FG Write        FG Read       FG Write        BG Read       BG Write        BG Read       BG Write       FG fsync       BG fsync\n"
+           "                                          NAME/UID     Characters     Characters          Bytes          Bytes     Characters     Characters          Bytes          Bytes                              \n"
+           "                                        ----------     ----------     ----------     ----------     ----------     ----------     ----------     ----------     ----------     ----------     ----------\n");
 
     for (const auto& uid : uids) {
-        printf("%50s%15ju%15ju%15ju%15ju%15ju%15ju%15ju%15ju\n", uid.name.c_str(),
+        printf("%50s%15ju%15ju%15ju%15ju%15ju%15ju%15ju%15ju%15ju%15ju\n", uid.name.c_str(),
             uid.io[0].rchar, uid.io[0].wchar, uid.io[0].read_bytes, uid.io[0].write_bytes,
-            uid.io[1].rchar, uid.io[1].wchar, uid.io[1].read_bytes, uid.io[1].write_bytes);
+            uid.io[1].rchar, uid.io[1].wchar, uid.io[1].read_bytes, uid.io[1].write_bytes,
+            uid.io[0].fsync, uid.io[1].fsync);
     }
     fflush(stdout);
 }