Attempt to mount block device even if postinstall is disabled
Bug: 198787355
Test: th
Change-Id: I42b0425fad5ead8629d0a824f6355ea051f670b8
diff --git a/payload_consumer/postinstall_runner_action.cc b/payload_consumer/postinstall_runner_action.cc
index c3b8c6b..1d2da43 100644
--- a/payload_consumer/postinstall_runner_action.cc
+++ b/payload_consumer/postinstall_runner_action.cc
@@ -121,6 +121,52 @@
PerformPartitionPostinstall();
}
+bool PostinstallRunnerAction::MountPartition(
+ const InstallPlan::Partition& partition) noexcept {
+ // Perform post-install for the current_partition_ partition. At this point we
+ // need to call CompletePartitionPostinstall to complete the operation and
+ // cleanup.
+ const auto mountable_device = partition.readonly_target_path;
+ if (!utils::FileExists(mountable_device.c_str())) {
+ LOG(ERROR) << "Mountable device " << mountable_device << " for partition "
+ << partition.name << " does not exist";
+ return false;
+ }
+
+ if (!utils::FileExists(fs_mount_dir_.c_str())) {
+ LOG(ERROR) << "Mount point " << fs_mount_dir_
+ << " does not exist, mount call will fail";
+ return false;
+ }
+ // Double check that the fs_mount_dir is not busy with a previous mounted
+ // filesystem from a previous crashed postinstall step.
+ if (utils::IsMountpoint(fs_mount_dir_)) {
+ LOG(INFO) << "Found previously mounted filesystem at " << fs_mount_dir_;
+ utils::UnmountFilesystem(fs_mount_dir_);
+ }
+
+#ifdef __ANDROID__
+ // In Chromium OS, the postinstall step is allowed to write to the block
+ // device on the target image, so we don't mark it as read-only and should
+ // be read-write since we just wrote to it during the update.
+
+ // Mark the block device as read-only before mounting for post-install.
+ if (!utils::SetBlockDeviceReadOnly(mountable_device, true)) {
+ return false;
+ }
+#endif // __ANDROID__
+
+ if (!utils::MountFilesystem(
+ mountable_device,
+ fs_mount_dir_,
+ MS_RDONLY,
+ partition.filesystem_type,
+ hardware_->GetPartitionMountOptions(partition.name))) {
+ return false;
+ }
+ return true;
+}
+
void PostinstallRunnerAction::PerformPartitionPostinstall() {
if (install_plan_.download_url.empty()) {
LOG(INFO) << "Skipping post-install during rollback";
@@ -132,6 +178,26 @@
!install_plan_.partitions[current_partition_].run_postinstall) {
VLOG(1) << "Skipping post-install on partition "
<< install_plan_.partitions[current_partition_].name;
+ // Attempt to mount a device if it has postinstall script configured, even
+ // if we want to skip running postinstall script.
+ // This is because we've seen bugs like b/198787355 which is only triggered
+ // when you attempt to mount a device. If device fails to mount, it will
+ // likely fail to mount during boot anyway, so it's better to catch any
+ // issues earlier.
+ // It's possible that some of the partitions aren't mountable, but these
+ // partitions shouldn't have postinstall configured. Therefore we guard this
+ // logic with |postinstall_path.empty()|.
+ const auto& partition = install_plan_.partitions[current_partition_];
+ if (!partition.postinstall_path.empty()) {
+ const auto mountable_device = partition.readonly_target_path;
+ if (!MountPartition(partition)) {
+ return CompletePostinstall(ErrorCode::kPostInstallMountError);
+ }
+ if (!utils::UnmountFilesystem(fs_mount_dir_)) {
+ return CompletePartitionPostinstall(
+ 1, "Error unmounting the device " + mountable_device);
+ }
+ }
current_partition_++;
}
if (current_partition_ == install_plan_.partitions.size())
@@ -141,27 +207,14 @@
install_plan_.partitions[current_partition_];
const string mountable_device = partition.readonly_target_path;
- if (mountable_device.empty()) {
- LOG(ERROR) << "Cannot make mountable device from " << partition.target_path;
- return CompletePostinstall(ErrorCode::kPostinstallRunnerError);
- }
-
// Perform post-install for the current_partition_ partition. At this point we
// need to call CompletePartitionPostinstall to complete the operation and
// cleanup.
- if (!utils::FileExists(fs_mount_dir_.c_str())) {
- LOG(ERROR) << "Mount point " << fs_mount_dir_
- << " does not exist, mount call will fail";
- return CompletePostinstall(ErrorCode::kPostinstallRunnerError);
+ if (!MountPartition(partition)) {
+ CompletePostinstall(ErrorCode::kPostInstallMountError);
+ return;
}
- // Double check that the fs_mount_dir is not busy with a previous mounted
- // filesystem from a previous crashed postinstall step.
- if (utils::IsMountpoint(fs_mount_dir_)) {
- LOG(INFO) << "Found previously mounted filesystem at " << fs_mount_dir_;
- utils::UnmountFilesystem(fs_mount_dir_);
- }
-
base::FilePath postinstall_path(partition.postinstall_path);
if (postinstall_path.IsAbsolute()) {
LOG(ERROR) << "Invalid absolute path passed to postinstall, use a relative"
@@ -179,28 +232,6 @@
return CompletePostinstall(ErrorCode::kPostinstallRunnerError);
}
-#ifdef __ANDROID__
- // In Chromium OS, the postinstall step is allowed to write to the block
- // device on the target image, so we don't mark it as read-only and should
- // be read-write since we just wrote to it during the update.
-
- // Mark the block device as read-only before mounting for post-install.
- if (!utils::SetBlockDeviceReadOnly(mountable_device, true)) {
- return CompletePartitionPostinstall(
- 1, "Error marking the device " + mountable_device + " read only.");
- }
-#endif // __ANDROID__
-
- if (!utils::MountFilesystem(
- mountable_device,
- fs_mount_dir_,
- MS_RDONLY,
- partition.filesystem_type,
- hardware_->GetPartitionMountOptions(partition.name))) {
- return CompletePartitionPostinstall(
- 1, "Error mounting the device " + mountable_device);
- }
-
LOG(INFO) << "Performing postinst (" << partition.postinstall_path << " at "
<< abs_path << ") installed on mountable device "
<< mountable_device;