Merge "Adding wait for a device file before mount" into rvc-dev
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index e7ddf70..1dcc9e4 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -1120,8 +1120,28 @@
                 }
 
                 android::dm::DmTable table;
-                if (!table.AddTarget(std::make_unique<android::dm::DmTargetBow>(
-                            0, size, entry->blk_device))) {
+                auto bowTarget =
+                        std::make_unique<android::dm::DmTargetBow>(0, size, entry->blk_device);
+
+                // dm-bow uses the first block as a log record, and relocates the real first block
+                // elsewhere. For metadata encrypted devices, dm-bow sits below dm-default-key, and
+                // for post Android Q devices dm-default-key uses a block size of 4096 always.
+                // So if dm-bow's block size, which by default is the block size of the underlying
+                // hardware, is less than dm-default-key's, blocks will get broken up and I/O will
+                // fail as it won't be data_unit_size aligned.
+                // However, since it is possible there is an already shipping non
+                // metadata-encrypted device with smaller blocks, we must not change this for
+                // devices shipped with Q or earlier unless they explicitly selected dm-default-key
+                // v2
+                constexpr unsigned int pre_gki_level = __ANDROID_API_Q__;
+                unsigned int options_format_version = android::base::GetUintProperty<unsigned int>(
+                        "ro.crypto.dm_default_key.options_format.version",
+                        (android::fscrypt::GetFirstApiLevel() <= pre_gki_level ? 1 : 2));
+                if (options_format_version > 1) {
+                    bowTarget->SetBlockSize(4096);
+                }
+
+                if (!table.AddTarget(std::move(bowTarget))) {
                     LERROR << "Failed to add bow target";
                     return false;
                 }
diff --git a/fs_mgr/libdm/dm_target.cpp b/fs_mgr/libdm/dm_target.cpp
index a594198..250cb82 100644
--- a/fs_mgr/libdm/dm_target.cpp
+++ b/fs_mgr/libdm/dm_target.cpp
@@ -120,6 +120,11 @@
     return keyid_ + " " + block_device_;
 }
 
+std::string DmTargetBow::GetParameterString() const {
+    if (!block_size_) return target_string_;
+    return target_string_ + " 1 block_size:" + std::to_string(block_size_);
+}
+
 std::string DmTargetSnapshot::name() const {
     if (mode_ == SnapshotStorageMode::Merge) {
         return "snapshot-merge";
diff --git a/fs_mgr/libdm/include/libdm/dm_target.h b/fs_mgr/libdm/include/libdm/dm_target.h
index 57096ce..f986cfe 100644
--- a/fs_mgr/libdm/include/libdm/dm_target.h
+++ b/fs_mgr/libdm/include/libdm/dm_target.h
@@ -175,11 +175,14 @@
     DmTargetBow(uint64_t start, uint64_t length, const std::string& target_string)
         : DmTarget(start, length), target_string_(target_string) {}
 
+    void SetBlockSize(uint32_t block_size) { block_size_ = block_size; }
+
     std::string name() const override { return "bow"; }
-    std::string GetParameterString() const override { return target_string_; }
+    std::string GetParameterString() const override;
 
   private:
     std::string target_string_;
+    uint32_t block_size_ = 0;
 };
 
 enum class SnapshotStorageMode {
diff --git a/libkeyutils/keyutils.cpp b/libkeyutils/keyutils.cpp
index 8f63f70..1c5acc9 100644
--- a/libkeyutils/keyutils.cpp
+++ b/libkeyutils/keyutils.cpp
@@ -32,17 +32,7 @@
 #include <sys/syscall.h>
 #include <unistd.h>
 
-// Deliberately not exposed. Callers should use the typed APIs instead.
-static long keyctl(int cmd, ...) {
-  va_list va;
-  va_start(va, cmd);
-  unsigned long arg2 = va_arg(va, unsigned long);
-  unsigned long arg3 = va_arg(va, unsigned long);
-  unsigned long arg4 = va_arg(va, unsigned long);
-  unsigned long arg5 = va_arg(va, unsigned long);
-  va_end(va);
-  return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5);
-}
+// keyctl(2) is deliberately not exposed. Callers should use the typed APIs instead.
 
 key_serial_t add_key(const char* type, const char* description, const void* payload,
                      size_t payload_length, key_serial_t ring_id) {
@@ -50,30 +40,30 @@
 }
 
 key_serial_t keyctl_get_keyring_ID(key_serial_t id, int create) {
-  return keyctl(KEYCTL_GET_KEYRING_ID, id, create);
+  return syscall(__NR_keyctl, KEYCTL_GET_KEYRING_ID, id, create);
 }
 
 long keyctl_revoke(key_serial_t id) {
-  return keyctl(KEYCTL_REVOKE, id);
+  return syscall(__NR_keyctl, KEYCTL_REVOKE, id);
 }
 
 long keyctl_search(key_serial_t ring_id, const char* type, const char* description,
                    key_serial_t dest_ring_id) {
-  return keyctl(KEYCTL_SEARCH, ring_id, type, description, dest_ring_id);
+  return syscall(__NR_keyctl, KEYCTL_SEARCH, ring_id, type, description, dest_ring_id);
 }
 
 long keyctl_setperm(key_serial_t id, int permissions) {
-  return keyctl(KEYCTL_SETPERM, id, permissions);
+  return syscall(__NR_keyctl, KEYCTL_SETPERM, id, permissions);
 }
 
 long keyctl_unlink(key_serial_t key, key_serial_t keyring) {
-  return keyctl(KEYCTL_UNLINK, key, keyring);
+  return syscall(__NR_keyctl, KEYCTL_UNLINK, key, keyring);
 }
 
 long keyctl_restrict_keyring(key_serial_t keyring, const char* type, const char* restriction) {
-  return keyctl(KEYCTL_RESTRICT_KEYRING, keyring, type, restriction);
+  return syscall(__NR_keyctl, KEYCTL_RESTRICT_KEYRING, keyring, type, restriction);
 }
 
 long keyctl_get_security(key_serial_t id, char* buffer, size_t buflen) {
-  return keyctl(KEYCTL_GET_SECURITY, id, buffer, buflen);
+  return syscall(__NR_keyctl, KEYCTL_GET_SECURITY, id, buffer, buflen);
 }