cryptfs: kill processes with open files on tmpfs /data

cryptfs will fail to remount /data at boot if any processes (e.g.
dex2oat) have files open on the tmpfs /data partition.  Since these
files are about to be destroyed anyway, just kill the offending
processes: first with SIGHUP and finally with SIGKILL.

Also remove a stray i++ that effectively cut the number of retries in
half.

Bug: 17576594

Change-Id: I76fb90ce2e52846ffb9de706e52b7bde98b4186a
Signed-off-by: Greg Hackmann <ghackmann@google.com>
diff --git a/cryptfs.c b/cryptfs.c
index 2878b20..606b9f1 100644
--- a/cryptfs.c
+++ b/cryptfs.c
@@ -1427,26 +1427,38 @@
     return encrypt_master_key(passwd, salt, key_buf, master_key, crypt_ftr);
 }
 
-static int wait_and_unmount(char *mountpoint)
+static int wait_and_unmount(char *mountpoint, bool kill)
 {
     int i, err, rc;
 #define WAIT_UNMOUNT_COUNT 20
 
     /*  Now umount the tmpfs filesystem */
     for (i=0; i<WAIT_UNMOUNT_COUNT; i++) {
-        if (umount(mountpoint)) {
-            if (errno == EINVAL) {
-                /* EINVAL is returned if the directory is not a mountpoint,
-                 * i.e. there is no filesystem mounted there.  So just get out.
-                 */
-                break;
-            }
-            err = errno;
-            sleep(1);
-            i++;
-        } else {
-          break;
+        if (umount(mountpoint) == 0) {
+            break;
         }
+
+        if (errno == EINVAL) {
+            /* EINVAL is returned if the directory is not a mountpoint,
+             * i.e. there is no filesystem mounted there.  So just get out.
+             */
+            break;
+        }
+
+        err = errno;
+
+        /* If allowed, be increasingly aggressive before the last two retries */
+        if (kill) {
+            if (i == (WAIT_UNMOUNT_COUNT - 3)) {
+                SLOGW("sending SIGHUP to processes with open files\n");
+                vold_killProcessesWithOpenFiles(mountpoint, 1);
+            } else if (i == (WAIT_UNMOUNT_COUNT - 2)) {
+                SLOGW("sending SIGKILL to processes with open files\n");
+                vold_killProcessesWithOpenFiles(mountpoint, 2);
+            }
+        }
+
+        sleep(1);
     }
 
     if (i < WAIT_UNMOUNT_COUNT) {
@@ -1588,7 +1600,7 @@
         return -1;
     }
 
-    if (! (rc = wait_and_unmount(DATA_MNT_POINT)) ) {
+    if (! (rc = wait_and_unmount(DATA_MNT_POINT, true)) ) {
         /* If ro.crypto.readonly is set to 1, mount the decrypted
          * filesystem readonly.  This is used when /data is mounted by
          * recovery mode.
@@ -2886,13 +2898,13 @@
          * above, so just unmount it now.  We must do this _AFTER_ killing the framework,
          * unlike the case for vold managed devices above.
          */
-        if (wait_and_unmount(sd_mnt_point)) {
+        if (wait_and_unmount(sd_mnt_point, false)) {
             goto error_shutting_down;
         }
     }
 
     /* Now unmount the /data partition. */
-    if (wait_and_unmount(DATA_MNT_POINT)) {
+    if (wait_and_unmount(DATA_MNT_POINT, false)) {
         if (allow_reboot) {
             goto error_shutting_down;
         } else {