OSDN Git Service

HACK: Retry/reboot when mount reports busy.
authorPaul Lawrence <paullawrence@google.com>
Mon, 8 Sep 2014 17:11:17 +0000 (10:11 -0700)
committerPaul Lawrence <paullawrence@google.com>
Fri, 12 Sep 2014 18:06:03 +0000 (11:06 -0700)
This is a hack because we don't know why mount() reports busy.

Requires dependent change in syste/core:
  https://googleplex-android-review.git.corp.google.com/#/c/543125/

Bug: 17358530

Change-Id: I8d3078bc68f8c450adce2c3a4101b6a958f1c4a0

cryptfs.c

index f6e6eba..197bf1e 100644 (file)
--- a/cryptfs.c
+++ b/cryptfs.c
@@ -80,6 +80,9 @@
 #define RSA_KEY_SIZE_BYTES (RSA_KEY_SIZE / 8)
 #define RSA_EXPONENT 0x10001
 
+#define RETRY_MOUNT_ATTEMPTS 10
+#define RETRY_MOUNT_DELAY_SECONDS 1
+
 char *me = "cryptfs";
 
 static unsigned char saved_master_key[KEY_LEN_BYTES];
@@ -1519,6 +1522,7 @@ static void cryptfs_trigger_restart_min_framework()
     }
 }
 
+/* returns < 0 on failure */
 static int cryptfs_restart_internal(int restart_main)
 {
     char fs_type[32];
@@ -1593,12 +1597,31 @@ static int cryptfs_restart_internal(int restart_main)
         }
 
         /* If that succeeded, then mount the decrypted filesystem */
-        if (fs_mgr_do_mount(fstab, DATA_MNT_POINT, crypto_blkdev, 0)) {
-            SLOGE("Failed to mount decrypted data");
-            cryptfs_set_corrupt();
-            cryptfs_trigger_restart_min_framework();
-            SLOGI("Started framework to offer wipe");
-            return -1;
+        int retries = RETRY_MOUNT_ATTEMPTS;
+        int mount_rc;
+        while ((mount_rc = fs_mgr_do_mount(fstab, DATA_MNT_POINT,
+                                           crypto_blkdev, 0))
+               != 0) {
+            if (mount_rc == FS_MGR_DOMNT_BUSY) {
+                /* TODO: invoke something similar to
+                   Process::killProcessWithOpenFiles(DATA_MNT_POINT,
+                                   retries > RETRY_MOUNT_ATTEMPT/2 ? 1 : 2 ) */
+                SLOGI("Failed to mount %s because it is busy - waiting",
+                      crypto_blkdev);
+                if (--retries) {
+                    sleep(RETRY_MOUNT_DELAY_SECONDS);
+                } else {
+                    /* Let's hope that a reboot clears away whatever is keeping
+                       the mount busy */
+                    cryptfs_reboot(reboot);
+                }
+            } else {
+                SLOGE("Failed to mount decrypted data");
+                cryptfs_set_corrupt();
+                cryptfs_trigger_restart_min_framework();
+                SLOGI("Started framework to offer wipe");
+                return -1;
+            }
         }
 
         property_set("vold.decrypt", "trigger_load_persist_props");