fastbootd: use O_DIRECT for write partition

Direct writes for partition flashing significantly increase performance.
Use O_DIRECT flag when opening partition for flashing. Additionally use
a 4096b aligned buffer which is required for O_DIRECT.
Switch from using 8MB write buffer to 1MB write buffer, as the extra
allocation has no performance impact.

Test: flash locally and reach home screen
Bug: 205151372
Signed-off-by: Konstantin Vyshetsky <vkon@google.com>
Change-Id: I060f438cf698d0fda1e59e35338bb5dc1cd05b51
diff --git a/fastboot/device/flashing.cpp b/fastboot/device/flashing.cpp
index 9b5d2cd..3f9bcdc 100644
--- a/fastboot/device/flashing.cpp
+++ b/fastboot/device/flashing.cpp
@@ -16,6 +16,7 @@
 #include "flashing.h"
 
 #include <fcntl.h>
+#include <string.h>
 #include <sys/stat.h>
 #include <unistd.h>
 
@@ -77,9 +78,20 @@
 
 int FlashRawDataChunk(int fd, const char* data, size_t len) {
     size_t ret = 0;
+    const size_t max_write_size = 1048576;
+    void* aligned_buffer;
+
+    if (posix_memalign(&aligned_buffer, 4096, max_write_size)) {
+        PLOG(ERROR) << "Failed to allocate write buffer";
+        return -ENOMEM;
+    }
+
+    auto aligned_buffer_unique_ptr = std::unique_ptr<void, decltype(&free)>{aligned_buffer, free};
+
     while (ret < len) {
-        int this_len = std::min(static_cast<size_t>(1048576UL * 8), len - ret);
-        int this_ret = write(fd, data, this_len);
+        int this_len = std::min(max_write_size, len - ret);
+        memcpy(aligned_buffer_unique_ptr.get(), data, this_len);
+        int this_ret = write(fd, aligned_buffer_unique_ptr.get(), this_len);
         if (this_ret < 0) {
             PLOG(ERROR) << "Failed to flash data of len " << len;
             return -1;
@@ -147,7 +159,7 @@
 
 int Flash(FastbootDevice* device, const std::string& partition_name) {
     PartitionHandle handle;
-    if (!OpenPartition(device, partition_name, &handle)) {
+    if (!OpenPartition(device, partition_name, &handle, O_WRONLY | O_DIRECT)) {
         return -ENOENT;
     }