Merge "Change the remount command to be more container-friendly" am: d24c8484c8
am: 677288c80a

Change-Id: I96fdf4c334626649ca0e7437a0d9296758a9b062
diff --git a/adb/remount_service.cpp b/adb/remount_service.cpp
index 32ed28f..a4c7a5a 100644
--- a/adb/remount_service.cpp
+++ b/adb/remount_service.cpp
@@ -62,9 +62,9 @@
 
 // The proc entry for / is full of lies, so check fstab instead.
 // /proc/mounts lists rootfs and /dev/root, neither of which is what we want.
-static std::string find_mount(const char* dir) {
-    if (strcmp(dir, "/") == 0) {
-       return find_fstab_mount(dir);
+static std::string find_mount(const char* dir, bool is_root) {
+    if (is_root) {
+        return find_fstab_mount(dir);
     } else {
        return find_proc_mount(dir);
     }
@@ -86,17 +86,29 @@
     if (!directory_exists(dir)) {
         return true;
     }
-    std::string dev = find_mount(dir);
-    if (dev.empty()) {
+    bool is_root = strcmp(dir, "/") == 0;
+    std::string dev = find_mount(dir, is_root);
+    // Even if the device for the root is not found, we still try to remount it
+    // as rw. This typically only happens when running Android in a container:
+    // the root will almost always be in a loop device, which is dynamic, so
+    // it's not convenient to put in the fstab.
+    if (dev.empty() && !is_root) {
         return true;
     }
-    if (!make_block_device_writable(dev)) {
+    if (!dev.empty() && !make_block_device_writable(dev)) {
         WriteFdFmt(fd, "remount of %s failed; couldn't make block device %s writable: %s\n",
                    dir, dev.c_str(), strerror(errno));
         return false;
     }
+    if (mount(dev.c_str(), dir, "none", MS_REMOUNT | MS_BIND, nullptr) == -1) {
+        // This is useful for cases where the superblock is already marked as
+        // read-write, but the mount itself is read-only, such as containers
+        // where the remount with just MS_REMOUNT is forbidden by the kernel.
+        WriteFdFmt(fd, "remount of the %s mount failed: %s.\n", dir, strerror(errno));
+        return false;
+    }
     if (mount(dev.c_str(), dir, "none", MS_REMOUNT, nullptr) == -1) {
-        WriteFdFmt(fd, "remount of %s failed: %s\n", dir, strerror(errno));
+        WriteFdFmt(fd, "remount of the %s superblock failed: %s\n", dir, strerror(errno));
         return false;
     }
     return true;