OTA: update SetBlockDeviceReadOnly am: fc20b67da1 am: dd09e617cb am: a4c97254d1 am: 0159ec976d

Original change: https://android-review.googlesource.com/c/platform/system/update_engine/+/2745153

Change-Id: Ib00030026441dd8bcf2d6077c485131220b7ae4f
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/common/utils.cc b/common/utils.cc
index 9723c8f..15ee05c 100644
--- a/common/utils.cc
+++ b/common/utils.cc
@@ -601,6 +601,53 @@
                 << " as read_only=" << expected_flag;
     return false;
   }
+
+  /*
+   * Read back the value to check if it is configured successfully.
+   * If fail, use the second method, set the file
+   * /sys/block/<partition_name>/force_ro
+   * to config the read only property.
+   */
+  rc = ioctl(fd, BLKROGET, &read_only_flag);
+  if (rc != 0) {
+    PLOG(ERROR) << "Failed to read back block device read-only value:" << device;
+    return false;
+  }
+  if (read_only_flag == expected_flag) {
+    return true;
+  }
+
+  std::array<char, PATH_MAX> device_name;
+  char *pdevice = realpath(device.c_str(), device_name.data());
+  TEST_AND_RETURN_FALSE_ERRNO(pdevice);
+
+  std::string real_path(pdevice);
+  std::size_t offset = real_path.find_last_of('/');
+  if (offset == std::string::npos){
+    LOG(ERROR) << "Could not find partition name from " << real_path;
+    return false;
+  }
+  const std::string partition_name = real_path.substr(offset + 1);
+
+  std::string force_ro_file = "/sys/block/" + partition_name + "/force_ro";
+  android::base::unique_fd fd_force_ro {
+    HANDLE_EINTR(open(force_ro_file.c_str(), O_WRONLY | O_CLOEXEC))};
+  TEST_AND_RETURN_FALSE_ERRNO(fd_force_ro >= 0);
+
+  rc = write(fd_force_ro, expected_flag ? "1" : "0", 1);
+  TEST_AND_RETURN_FALSE_ERRNO(rc > 0);
+
+  // Read back again
+  rc = ioctl(fd, BLKROGET, &read_only_flag);
+  if (rc != 0) {
+    PLOG(ERROR) << "Failed to read back block device read-only value:" << device;
+    return false;
+  }
+  if (read_only_flag != expected_flag) {
+    LOG(ERROR) << "After modifying force_ro, marking block device " << device
+                << " as read_only=" << expected_flag;
+    return false;
+  }
   return true;
 }