OSDN Git Service

Enable dynamic read logs buffer sizing for incfs
authorYurii Zubrytskyi <zyy@google.com>
Thu, 28 Oct 2021 21:37:12 +0000 (14:37 -0700)
committerYurii Zubrytskyi <zyy@google.com>
Fri, 29 Oct 2021 20:37:52 +0000 (13:37 -0700)
Default buffer size of 4 pages causes many missed log records
because of ring buffer overflows. This change adds a dynamic
sizing, up to 32 pages, that has shown to decrease dropped
records pretty much to nil

Fallback code automatically decreases the buffer size in case
of kernel memory fragmentation - some logs are still much
better than no logs at all

Bug: 203551890
Test: manual, adb install <Apk>; checked for fallback by
  increasing max size to 1024 pages
Change-Id: I0ea46c1ad2534b1dbb5faaead52afab88b66747b
Merged-In: I0ea46c1ad2534b1dbb5faaead52afab88b66747b

VoldNativeService.cpp

index ef26fb6..46fc7e2 100644 (file)
@@ -1039,16 +1039,30 @@ binder::Status VoldNativeService::setIncFsMountOptions(
     };
     auto cleanup =
             std::unique_ptr<incfs::Control, decltype(cleanupFunc)>(&incfsControl, cleanupFunc);
-    if (auto error = incfs::setOptions(
-                incfsControl,
-                {.defaultReadTimeoutMs =
-                         enableReadTimeouts ? INCFS_DEFAULT_READ_TIMEOUT_MS : kIncFsReadNoTimeoutMs,
-                 .readLogBufferPages = enableReadLogs ? INCFS_DEFAULT_PAGE_READ_BUFFER_PAGES : 0,
-                 .sysfsName = sysfsName.c_str()});
-        error < 0) {
-        return binder::Status::fromServiceSpecificError(error);
-    }
 
+    constexpr auto minReadLogBufferPages = INCFS_DEFAULT_PAGE_READ_BUFFER_PAGES;
+    constexpr auto maxReadLogBufferPages = 8 * INCFS_DEFAULT_PAGE_READ_BUFFER_PAGES;
+    auto options = incfs::MountOptions{
+            .defaultReadTimeoutMs =
+                    enableReadTimeouts ? INCFS_DEFAULT_READ_TIMEOUT_MS : kIncFsReadNoTimeoutMs,
+            .readLogBufferPages = enableReadLogs ? maxReadLogBufferPages : 0,
+            .sysfsName = sysfsName.c_str()};
+
+    for (;;) {
+        const auto error = incfs::setOptions(incfsControl, options);
+        if (!error) {
+            return Ok();
+        }
+        if (!enableReadLogs || error != -ENOMEM) {
+            return binder::Status::fromServiceSpecificError(error);
+        }
+        // In case of memory allocation error retry with a smaller buffer.
+        options.readLogBufferPages /= 2;
+        if (options.readLogBufferPages < minReadLogBufferPages) {
+            return binder::Status::fromServiceSpecificError(error);
+        }
+    }
+    // unreachable, but makes the compiler happy
     return Ok();
 }