Merge "init: Wait for daemon to fully spin up all threads"
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 10d2f18..961db02 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -1498,6 +1498,7 @@
if (UpdateUsesUserSnapshots(lock) && !device()->IsTestDevice()) {
if (snapuserd_client_) {
snapuserd_client_->DetachSnapuserd();
+ snapuserd_client_->RemoveTransitionedDaemonIndicator();
snapuserd_client_ = nullptr;
}
}
diff --git a/fs_mgr/libsnapshot/snapuserd/Android.bp b/fs_mgr/libsnapshot/snapuserd/Android.bp
index 64e0b8a..a67e37c 100644
--- a/fs_mgr/libsnapshot/snapuserd/Android.bp
+++ b/fs_mgr/libsnapshot/snapuserd/Android.bp
@@ -37,11 +37,13 @@
cc_library_static {
name: "libsnapshot_snapuserd",
defaults: [
+ "fs_mgr_defaults",
"libsnapshot_snapuserd_defaults",
],
recovery_available: true,
static_libs: [
"libcutils_sockets",
+ "libfs_mgr",
],
shared_libs: [
"libbase",
@@ -49,6 +51,7 @@
],
export_include_dirs: ["include"],
ramdisk_available: true,
+ vendor_ramdisk_available: true,
}
cc_defaults {
@@ -86,6 +89,7 @@
"libgflags",
"liblog",
"libsnapshot_cow",
+ "libsnapshot_snapuserd",
"libz",
"liblz4",
"libext4_utils",
diff --git a/fs_mgr/libsnapshot/snapuserd/include/snapuserd/snapuserd_client.h b/fs_mgr/libsnapshot/snapuserd/include/snapuserd/snapuserd_client.h
index 4b62b20..fb2251e 100644
--- a/fs_mgr/libsnapshot/snapuserd/include/snapuserd/snapuserd_client.h
+++ b/fs_mgr/libsnapshot/snapuserd/include/snapuserd/snapuserd_client.h
@@ -32,6 +32,7 @@
static constexpr char kSnapuserdSocket[] = "snapuserd";
static constexpr char kSnapuserdSocketProxy[] = "snapuserd_proxy";
+static constexpr char kDaemonAliveIndicator[] = "daemon-alive-indicator";
// Ensure that the second-stage daemon for snapuserd is running.
bool EnsureSnapuserdStarted();
@@ -44,9 +45,11 @@
std::string Receivemsg();
bool ValidateConnection();
+ std::string GetDaemonAliveIndicatorPath();
public:
explicit SnapuserdClient(android::base::unique_fd&& sockfd);
+ SnapuserdClient(){};
static std::unique_ptr<SnapuserdClient> Connect(const std::string& socket_name,
std::chrono::milliseconds timeout_ms);
@@ -91,6 +94,17 @@
// Check the update verification status - invoked by update_verifier during
// boot
bool QueryUpdateVerification();
+
+ // Check if Snapuser daemon is ready post selinux transition after OTA boot
+ // This is invoked only by init as there is no sockets setup yet during
+ // selinux transition
+ bool IsTransitionedDaemonReady();
+
+ // Remove the daemon-alive-indicator path post snapshot merge
+ bool RemoveTransitionedDaemonIndicator();
+
+ // Notify init that snapuserd daemon is ready post selinux transition
+ void NotifyTransitionDaemonIsReady();
};
} // namespace snapshot
diff --git a/fs_mgr/libsnapshot/snapuserd/snapuserd_client.cpp b/fs_mgr/libsnapshot/snapuserd/snapuserd_client.cpp
index e08cf9b..695b581 100644
--- a/fs_mgr/libsnapshot/snapuserd/snapuserd_client.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/snapuserd_client.cpp
@@ -29,10 +29,12 @@
#include <chrono>
#include <sstream>
+#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/properties.h>
#include <android-base/strings.h>
+#include <fs_mgr/file_wait.h>
#include <snapuserd/snapuserd_client.h>
namespace android {
@@ -279,5 +281,42 @@
return response == "success";
}
+std::string SnapuserdClient::GetDaemonAliveIndicatorPath() {
+ return "/metadata/ota/" + std::string(kDaemonAliveIndicator);
+}
+
+bool SnapuserdClient::IsTransitionedDaemonReady() {
+ if (!android::fs_mgr::WaitForFile(GetDaemonAliveIndicatorPath(), 10s)) {
+ LOG(ERROR) << "Timed out waiting for daemon indicator path: "
+ << GetDaemonAliveIndicatorPath();
+ return false;
+ }
+
+ return true;
+}
+
+bool SnapuserdClient::RemoveTransitionedDaemonIndicator() {
+ std::string error;
+ std::string filePath = GetDaemonAliveIndicatorPath();
+ if (!android::base::RemoveFileIfExists(filePath, &error)) {
+ LOG(ERROR) << "Failed to remove DaemonAliveIndicatorPath - error: " << error;
+ return false;
+ }
+
+ if (!android::fs_mgr::WaitForFileDeleted(filePath, 5s)) {
+ LOG(ERROR) << "Timed out waiting for " << filePath << " to unlink";
+ return false;
+ }
+
+ return true;
+}
+
+void SnapuserdClient::NotifyTransitionDaemonIsReady() {
+ if (!android::base::WriteStringToFile("1", GetDaemonAliveIndicatorPath())) {
+ PLOG(ERROR) << "Unable to write daemon alive indicator path: "
+ << GetDaemonAliveIndicatorPath();
+ }
+}
+
} // namespace snapshot
} // namespace android
diff --git a/fs_mgr/libsnapshot/snapuserd/snapuserd_daemon.cpp b/fs_mgr/libsnapshot/snapuserd/snapuserd_daemon.cpp
index 2f7775c..bfe93eb 100644
--- a/fs_mgr/libsnapshot/snapuserd/snapuserd_daemon.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/snapuserd_daemon.cpp
@@ -119,6 +119,12 @@
}
}
+ // We reach this point only during selinux transition during device boot.
+ // At this point, all threads are spin up and are ready to serve the I/O
+ // requests for dm-user. Lets inform init.
+ auto client = std::make_unique<SnapuserdClient>();
+ client->NotifyTransitionDaemonIsReady();
+
// Skip the accept() call to avoid spurious log spam. The server will still
// run until all handlers have completed.
return user_server_.WaitForSocket();
diff --git a/init/snapuserd_transition.cpp b/init/snapuserd_transition.cpp
index 6972f30..3a9ff5b 100644
--- a/init/snapuserd_transition.cpp
+++ b/init/snapuserd_transition.cpp
@@ -112,6 +112,10 @@
setenv(kSnapuserdFirstStagePidVar, std::to_string(pid).c_str(), 1);
+ if (!client->RemoveTransitionedDaemonIndicator()) {
+ LOG(ERROR) << "RemoveTransitionedDaemonIndicator failed";
+ }
+
LOG(INFO) << "Relaunched snapuserd with pid: " << pid;
}
@@ -263,6 +267,19 @@
* we may see audit logs.
*/
bool SnapuserdSelinuxHelper::TestSnapuserdIsReady() {
+ // Wait for the daemon to be fully up. Daemon will write to path
+ // /metadata/ota/daemon-alive-indicator only when all the threads
+ // are ready and attached to dm-user.
+ //
+ // This check will fail for GRF devices with vendor on Android S.
+ // snapuserd binary from Android S won't be able to communicate
+ // and hence, we will fallback and issue I/O to verify
+ // the presence of daemon.
+ auto client = std::make_unique<SnapuserdClient>();
+ if (!client->IsTransitionedDaemonReady()) {
+ LOG(ERROR) << "IsTransitionedDaemonReady failed";
+ }
+
std::string dev = "/dev/block/mapper/system"s + fs_mgr_get_slot_suffix();
android::base::unique_fd fd(open(dev.c_str(), O_RDONLY | O_DIRECT));
if (fd < 0) {