Manually merge commit 'b406ffa' into stage-aosp-master

* commit 'b406ffa':
  Add support for creating ext4 images with mke2fs

BUG:33304034
diff --git a/BenchmarkGen.h b/BenchmarkGen.h
index 3e86608..8a4f68b 100644
--- a/BenchmarkGen.h
+++ b/BenchmarkGen.h
@@ -220,7 +220,7 @@
 t3450f22 = TEMP_FAILURE_RETRY(open("file14", O_RDONLY|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC));
 close(t3450f22);
 t3450f22 = TEMP_FAILURE_RETRY(open("file15", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE));
-TEMP_FAILURE_RETRY(read(t3450f22, buf, 1));
+TEMP_FAILURE_RETRY(write(t3450f22, buf, 1));
 TEMP_FAILURE_RETRY(fsync(t3450f22));
 close(t3450f22);
 close(t3450f18);
@@ -405,7 +405,7 @@
 t3455f19 = TEMP_FAILURE_RETRY(open("file14", O_RDONLY|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC));
 close(t3455f19);
 t3455f19 = TEMP_FAILURE_RETRY(open("file15", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE));
-TEMP_FAILURE_RETRY(read(t3455f19, buf, 1));
+TEMP_FAILURE_RETRY(write(t3455f19, buf, 1));
 TEMP_FAILURE_RETRY(fsync(t3455f19));
 close(t3455f19);
 close(t3455f18);
@@ -1944,7 +1944,7 @@
 TEMP_FAILURE_RETRY(pwrite(t3499f55, buf, 28, 0));
 TEMP_FAILURE_RETRY(fdatasync(t3499f55));
 close(t3499f55);
-TEMP_FAILURE_RETRY(read(t3505f56, buf, 20552));
+TEMP_FAILURE_RETRY(write(t3505f56, buf, 20552));
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 30, 35601253));
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 36, 35601283));
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 3224, 35598336)); // mmap2
@@ -1969,11 +1969,11 @@
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 30, 35513539));
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 37, 35513569));
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 1673, 35512320)); // mmap2
-TEMP_FAILURE_RETRY(read(t3505f56, buf, 16008));
+TEMP_FAILURE_RETRY(write(t3505f56, buf, 16008));
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 30, 31153857));
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 48, 31153887));
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 4461, 31150080)); // mmap2
-TEMP_FAILURE_RETRY(read(t3505f56, buf, 10864));
+TEMP_FAILURE_RETRY(write(t3505f56, buf, 10864));
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 30, 34907552));
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 39, 34907582));
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 2551, 34906112)); // mmap2
@@ -1986,7 +1986,7 @@
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 30, 30431338));
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 42, 30431368));
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 4400, 30429184)); // mmap2
-TEMP_FAILURE_RETRY(read(t3505f56, buf, 14320));
+TEMP_FAILURE_RETRY(write(t3505f56, buf, 14320));
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 30, 34416128));
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 43, 34416158));
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 1855, 34414592)); // mmap2
@@ -1996,18 +1996,18 @@
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 30, 29892892));
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 58, 29892922));
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 755, 29892608)); // mmap2
-TEMP_FAILURE_RETRY(read(t3505f56, buf, 12208));
-TEMP_FAILURE_RETRY(read(t3505f56, buf, 20736));
+TEMP_FAILURE_RETRY(write(t3505f56, buf, 12208));
+TEMP_FAILURE_RETRY(write(t3505f56, buf, 20736));
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 30, 36353719));
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 43, 36353749));
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 2179, 36352000)); // mmap2
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 30, 35512004));
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 33, 35512034));
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 4299, 35508224)); // mmap2
-TEMP_FAILURE_RETRY(read(t3505f56, buf, 8936));
-TEMP_FAILURE_RETRY(read(t3505f56, buf, 2800));
-TEMP_FAILURE_RETRY(read(t3505f56, buf, 20216));
-TEMP_FAILURE_RETRY(read(t3505f56, buf, 16912));
+TEMP_FAILURE_RETRY(write(t3505f56, buf, 8936));
+TEMP_FAILURE_RETRY(write(t3505f56, buf, 2800));
+TEMP_FAILURE_RETRY(write(t3505f56, buf, 20216));
+TEMP_FAILURE_RETRY(write(t3505f56, buf, 16912));
 close(t3505f56);
 t3505f56 = TEMP_FAILURE_RETRY(open("file31", O_RDONLY|O_LARGEFILE|O_CLOEXEC));
 TEMP_FAILURE_RETRY(pread(t3505f56, buf, 1, 0));
@@ -2409,9 +2409,9 @@
 int  t3519f75 = TEMP_FAILURE_RETRY(open("file128", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE));
 close(t3526f70);
 t3526f70 = TEMP_FAILURE_RETRY(open("file129", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE));
-TEMP_FAILURE_RETRY(read(t3519f75, buf, 2991));
+TEMP_FAILURE_RETRY(write(t3519f75, buf, 2991));
 close(t3519f75);
-TEMP_FAILURE_RETRY(read(t3526f70, buf, 3974));
+TEMP_FAILURE_RETRY(write(t3526f70, buf, 3974));
 close(t3526f70);
 t3519f67 = TEMP_FAILURE_RETRY(open("file130", O_RDONLY|O_LARGEFILE));
 TEMP_FAILURE_RETRY(read(t3519f67, buf, 16384));
@@ -2444,18 +2444,18 @@
 t3526f70 = TEMP_FAILURE_RETRY(open("file131", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE));
 close(t3526f70);
 t3526f70 = TEMP_FAILURE_RETRY(open("file131", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE));
-TEMP_FAILURE_RETRY(read(t3526f70, buf, 4622));
+TEMP_FAILURE_RETRY(write(t3526f70, buf, 4622));
 close(t3526f70);
 int  t3526f72 = TEMP_FAILURE_RETRY(open("file132", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE));
 close(t3526f72);
 t3526f72 = TEMP_FAILURE_RETRY(open("file132", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE));
-TEMP_FAILURE_RETRY(read(t3526f72, buf, 16384));
-TEMP_FAILURE_RETRY(read(t3526f72, buf, 6849));
+TEMP_FAILURE_RETRY(write(t3526f72, buf, 16384));
+TEMP_FAILURE_RETRY(write(t3526f72, buf, 6849));
 close(t3526f72);
 t3526f70 = TEMP_FAILURE_RETRY(open("file133", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE));
 close(t3526f70);
 int  t3526f75 = TEMP_FAILURE_RETRY(open("file133", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE));
-TEMP_FAILURE_RETRY(read(t3526f75, buf, 13332));
+TEMP_FAILURE_RETRY(write(t3526f75, buf, 13332));
 close(t3526f75);
 int  t3495f70 = TEMP_FAILURE_RETRY(open("file31", O_RDONLY|O_LARGEFILE|O_CLOEXEC));
 TEMP_FAILURE_RETRY(pread(t3495f70, buf, 1, 0));
@@ -2484,7 +2484,7 @@
 int  t3526f93 = TEMP_FAILURE_RETRY(open("file134", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE));
 close(t3526f93);
 int  t3526f88 = TEMP_FAILURE_RETRY(open("file134", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE));
-TEMP_FAILURE_RETRY(read(t3526f88, buf, 15056));
+TEMP_FAILURE_RETRY(write(t3526f88, buf, 15056));
 close(t3526f88);
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 30, 34433108));
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 56, 34433138));
@@ -2546,13 +2546,13 @@
 int  t3526f64 = TEMP_FAILURE_RETRY(open("file135", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE));
 close(t3526f64);
 t3526f64 = TEMP_FAILURE_RETRY(open("file135", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE));
-TEMP_FAILURE_RETRY(read(t3526f64, buf, 16384));
-TEMP_FAILURE_RETRY(read(t3526f64, buf, 4873));
+TEMP_FAILURE_RETRY(write(t3526f64, buf, 16384));
+TEMP_FAILURE_RETRY(write(t3526f64, buf, 4873));
 close(t3526f64);
 int  t3526f90 = TEMP_FAILURE_RETRY(open("file136", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE));
 close(t3526f90);
 t3526f90 = TEMP_FAILURE_RETRY(open("file136", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE));
-TEMP_FAILURE_RETRY(read(t3526f90, buf, 4199));
+TEMP_FAILURE_RETRY(write(t3526f90, buf, 4199));
 close(t3526f90);
 int  t3499f90 = TEMP_FAILURE_RETRY(open("file18", O_RDONLY|O_LARGEFILE|O_CLOEXEC));
 TEMP_FAILURE_RETRY(pread(t3499f90, buf, 1, 0));
@@ -2759,8 +2759,8 @@
 TEMP_FAILURE_RETRY(read(t3526f70, buf, 16384));
 TEMP_FAILURE_RETRY(read(t3526f70, buf, 16384));
 close(t3526f70);
-TEMP_FAILURE_RETRY(read(t3505f66, buf, 10432));
-TEMP_FAILURE_RETRY(read(t3505f66, buf, 4464));
+TEMP_FAILURE_RETRY(write(t3505f66, buf, 10432));
+TEMP_FAILURE_RETRY(write(t3505f66, buf, 4464));
 t3495f70 = TEMP_FAILURE_RETRY(open("file31", O_RDONLY|O_LARGEFILE|O_CLOEXEC));
 TEMP_FAILURE_RETRY(pread(t3495f70, buf, 1, 0));
 close(t3495f70);
@@ -2785,26 +2785,26 @@
 TEMP_FAILURE_RETRY(pwrite(t3495f70, buf, 28, 0));
 TEMP_FAILURE_RETRY(fdatasync(t3495f70));
 close(t3495f70);
-TEMP_FAILURE_RETRY(read(t3505f66, buf, 10592));
+TEMP_FAILURE_RETRY(write(t3505f66, buf, 10592));
 int  t3533f70 = TEMP_FAILURE_RETRY(open("file140", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE));
 close(t3533f70);
 t3533f70 = TEMP_FAILURE_RETRY(open("file140", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE));
-TEMP_FAILURE_RETRY(read(t3533f70, buf, 4042));
+TEMP_FAILURE_RETRY(write(t3533f70, buf, 4042));
 close(t3533f70);
-TEMP_FAILURE_RETRY(read(t3505f66, buf, 9664));
-TEMP_FAILURE_RETRY(read(t3505f66, buf, 23656));
+TEMP_FAILURE_RETRY(write(t3505f66, buf, 9664));
+TEMP_FAILURE_RETRY(write(t3505f66, buf, 23656));
 t3533f70 = TEMP_FAILURE_RETRY(open("file141", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE));
 close(t3533f70);
 t3526f70 = TEMP_FAILURE_RETRY(open("file142", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE));
 int  t3533f72 = TEMP_FAILURE_RETRY(open("file141", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE));
 close(t3526f70);
 t3526f70 = TEMP_FAILURE_RETRY(open("file142", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE));
-TEMP_FAILURE_RETRY(read(t3526f70, buf, 5057));
-TEMP_FAILURE_RETRY(read(t3533f72, buf, 4595));
+TEMP_FAILURE_RETRY(write(t3526f70, buf, 5057));
+TEMP_FAILURE_RETRY(write(t3533f72, buf, 4595));
 close(t3526f70);
 close(t3533f72);
-TEMP_FAILURE_RETRY(read(t3505f66, buf, 19744));
-TEMP_FAILURE_RETRY(read(t3505f66, buf, 9344));
+TEMP_FAILURE_RETRY(write(t3505f66, buf, 19744));
+TEMP_FAILURE_RETRY(write(t3505f66, buf, 9344));
 t3499f70 = TEMP_FAILURE_RETRY(open("file18", O_RDONLY|O_LARGEFILE|O_CLOEXEC));
 TEMP_FAILURE_RETRY(pread(t3499f70, buf, 1, 0));
 close(t3499f70);
@@ -2821,7 +2821,7 @@
 TEMP_FAILURE_RETRY(pwrite(t3499f70, buf, 4, 12820));
 TEMP_FAILURE_RETRY(pread(t3499f70, buf, 8, 13312));
 TEMP_FAILURE_RETRY(fdatasync(t3499f70));
-TEMP_FAILURE_RETRY(read(t3505f66, buf, 24672));
+TEMP_FAILURE_RETRY(write(t3505f66, buf, 24672));
 t3499f72 = TEMP_FAILURE_RETRY(open("file22", O_RDONLY|O_LARGEFILE|O_CLOEXEC));
 TEMP_FAILURE_RETRY(fdatasync(t3499f72));
 close(t3499f72);
@@ -2830,8 +2830,8 @@
 TEMP_FAILURE_RETRY(pwrite(t3499f70, buf, 28, 0));
 TEMP_FAILURE_RETRY(fdatasync(t3499f70));
 close(t3499f70);
-TEMP_FAILURE_RETRY(read(t3505f66, buf, 7584));
-TEMP_FAILURE_RETRY(read(t3505f66, buf, 10736));
+TEMP_FAILURE_RETRY(write(t3505f66, buf, 7584));
+TEMP_FAILURE_RETRY(write(t3505f66, buf, 10736));
 close(t3505f66);
 t3505f66 = TEMP_FAILURE_RETRY(open("file31", O_RDONLY|O_LARGEFILE|O_CLOEXEC));
 TEMP_FAILURE_RETRY(pread(t3505f66, buf, 1, 0));
@@ -2928,9 +2928,9 @@
 t3533f91 = TEMP_FAILURE_RETRY(open("file143", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE));
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 30, 31210525));
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 44, 31210555));
-TEMP_FAILURE_RETRY(read(t3533f91, buf, 16384));
+TEMP_FAILURE_RETRY(write(t3533f91, buf, 16384));
 TEMP_FAILURE_RETRY(pread(t3455f17, buf, 3673, 31207424)); // mmap2
-TEMP_FAILURE_RETRY(read(t3533f91, buf, 2024));
+TEMP_FAILURE_RETRY(write(t3533f91, buf, 2024));
 close(t3533f91);
 int  t3499f91 = TEMP_FAILURE_RETRY(open("file18", O_RDONLY|O_LARGEFILE|O_CLOEXEC));
 TEMP_FAILURE_RETRY(pread(t3499f91, buf, 1, 0));
@@ -2983,40 +2983,40 @@
 int  t3533f102 = TEMP_FAILURE_RETRY(open("file144", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE));
 close(t3533f102);
 t3533f72 = TEMP_FAILURE_RETRY(open("file144", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE));
-TEMP_FAILURE_RETRY(read(t3533f72, buf, 5550));
+TEMP_FAILURE_RETRY(write(t3533f72, buf, 5550));
 close(t3533f72);
 int  t3526f84 = TEMP_FAILURE_RETRY(open("file145", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE));
 close(t3526f84);
 int  t3526f101 = TEMP_FAILURE_RETRY(open("file145", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE));
-TEMP_FAILURE_RETRY(read(t3526f101, buf, 3612));
+TEMP_FAILURE_RETRY(write(t3526f101, buf, 3612));
 close(t3526f101);
 t3526f90 = TEMP_FAILURE_RETRY(open("file146", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE));
 close(t3526f90);
 t3526f90 = TEMP_FAILURE_RETRY(open("file146", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE));
-TEMP_FAILURE_RETRY(read(t3526f90, buf, 5414));
+TEMP_FAILURE_RETRY(write(t3526f90, buf, 5414));
 int  t3533f96 = TEMP_FAILURE_RETRY(open("file147", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE));
 close(t3533f96);
 t3533f96 = TEMP_FAILURE_RETRY(open("file147", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE));
 close(t3526f90);
-TEMP_FAILURE_RETRY(read(t3533f96, buf, 3834));
+TEMP_FAILURE_RETRY(write(t3533f96, buf, 3834));
 close(t3533f96);
 int  t3519f90 = TEMP_FAILURE_RETRY(open("file148", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE));
 close(t3519f90);
 t3519f90 = TEMP_FAILURE_RETRY(open("file148", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE));
-TEMP_FAILURE_RETRY(read(t3519f90, buf, 3461));
+TEMP_FAILURE_RETRY(write(t3519f90, buf, 3461));
 int  t3526f96 = TEMP_FAILURE_RETRY(open("file149", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE));
 close(t3526f96);
 close(t3519f90);
 t3526f90 = TEMP_FAILURE_RETRY(open("file149", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE));
-TEMP_FAILURE_RETRY(read(t3526f90, buf, 16384));
-TEMP_FAILURE_RETRY(read(t3526f90, buf, 12766));
+TEMP_FAILURE_RETRY(write(t3526f90, buf, 16384));
+TEMP_FAILURE_RETRY(write(t3526f90, buf, 12766));
 close(t3526f90);
 int  t3533f90 = TEMP_FAILURE_RETRY(open("file150", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE));
 close(t3533f90);
 t3533f90 = TEMP_FAILURE_RETRY(open("file150", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE));
 int  t3505f96 = TEMP_FAILURE_RETRY(open("file151", O_RDWR|O_CREAT|O_LARGEFILE|O_CLOEXEC));
 TEMP_FAILURE_RETRY(pread(t3505f96, buf, 100, 0));
-TEMP_FAILURE_RETRY(read(t3533f90, buf, 10056));
+TEMP_FAILURE_RETRY(write(t3533f90, buf, 10056));
 close(t3533f90);
 t3505f90 = TEMP_FAILURE_RETRY(open("file152", O_RDONLY|O_LARGEFILE|O_CLOEXEC));
 TEMP_FAILURE_RETRY(pread(t3505f90, buf, 1, 0));
@@ -3042,7 +3042,7 @@
 close(t3505f90);
 t3533f90 = TEMP_FAILURE_RETRY(open("file153", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE));
 TEMP_FAILURE_RETRY(pread(t3505f96, buf, 16, 24));
-TEMP_FAILURE_RETRY(read(t3533f90, buf, 13271));
+TEMP_FAILURE_RETRY(write(t3533f90, buf, 13271));
 close(t3533f90);
 TEMP_FAILURE_RETRY(pread(t3505f96, buf, 4096, 16384));
 TEMP_FAILURE_RETRY(pread(t3505f96, buf, 4096, 12288));
@@ -3461,7 +3461,7 @@
 TEMP_FAILURE_RETRY(fdatasync(t3545f97));
 close(t3545f97);
 int  t3575f29 = TEMP_FAILURE_RETRY(open("file16", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE));
-TEMP_FAILURE_RETRY(read(t3575f29, buf, 17344));
+TEMP_FAILURE_RETRY(write(t3575f29, buf, 17344));
 close(t3575f29);
 t3545f97 = TEMP_FAILURE_RETRY(open("file155", O_RDONLY|O_LARGEFILE|O_CLOEXEC));
 TEMP_FAILURE_RETRY(pread(t3545f97, buf, 1, 0));
@@ -3801,11 +3801,11 @@
 TEMP_FAILURE_RETRY(fdatasync(t3499f103));
 t3499f105 = TEMP_FAILURE_RETRY(open("file22", O_RDONLY|O_LARGEFILE|O_CLOEXEC));
 TEMP_FAILURE_RETRY(fdatasync(t3499f105));
-TEMP_FAILURE_RETRY(read(t3496f28, buf, 8188));
+TEMP_FAILURE_RETRY(write(t3496f28, buf, 8188));
 close(t3499f105);
 TEMP_FAILURE_RETRY(pwrite(t3499f103, buf, 12, 0));
 TEMP_FAILURE_RETRY(fdatasync(t3499f103));
-TEMP_FAILURE_RETRY(read(t3496f28, buf, 3166));
+TEMP_FAILURE_RETRY(write(t3496f28, buf, 3166));
 TEMP_FAILURE_RETRY(pwrite(t3499f103, buf, 28, 0));
 TEMP_FAILURE_RETRY(fdatasync(t3499f103));
 close(t3499f103);
diff --git a/Disk.cpp b/Disk.cpp
index eedec42..6562d96 100644
--- a/Disk.cpp
+++ b/Disk.cpp
@@ -21,6 +21,7 @@
 #include "VolumeBase.h"
 #include "VolumeManager.h"
 #include "ResponseCode.h"
+#include "Ext4Crypt.h"
 
 #include <android-base/file.h>
 #include <android-base/stringprintf.h>
@@ -438,6 +439,11 @@
 status_t Disk::partitionMixed(int8_t ratio) {
     int res;
 
+    if (e4crypt_is_native()) {
+        LOG(ERROR) << "Private volumes not yet supported on FBE devices";
+        return -EINVAL;
+    }
+
     destroyAllVolumes();
     mJustPartitioned = true;
 
diff --git a/Ext4Crypt.cpp b/Ext4Crypt.cpp
index 0531aba..0063bef 100644
--- a/Ext4Crypt.cpp
+++ b/Ext4Crypt.cpp
@@ -169,6 +169,7 @@
     }
     LOG(DEBUG) << "Added key " << key_id << " (" << ref << ") to keyring " << device_keyring
                << " in process " << getpid();
+
     return true;
 }
 
@@ -372,7 +373,9 @@
 }
 
 static bool ensure_policy(const std::string& raw_ref, const std::string& path) {
-    if (e4crypt_policy_ensure(path.c_str(), raw_ref.data(), raw_ref.size()) != 0) {
+    if (e4crypt_policy_ensure(path.c_str(),
+                              raw_ref.data(), raw_ref.size(),
+                              cryptfs_get_file_encryption_mode()) != 0) {
         LOG(ERROR) << "Failed to set policy on: " << path;
         return false;
     }
@@ -431,6 +434,13 @@
         return true;
     }
 
+    std::string mode_filename = std::string("/data") + e4crypt_key_mode;
+    std::string mode = cryptfs_get_file_encryption_mode();
+    if (!android::base::WriteStringToFile(mode, mode_filename)) {
+        PLOG(ERROR) << "Cannot save type";
+        return false;
+    }
+
     std::string device_key;
     if (path_exists(device_key_path)) {
         if (!android::vold::retrieveKey(device_key_path,
@@ -506,19 +516,6 @@
     return true;
 }
 
-static bool evict_key(const std::string& raw_ref) {
-    auto ref = keyname(raw_ref);
-    key_serial_t device_keyring;
-    if (!e4crypt_keyring(&device_keyring)) return false;
-    auto key_serial = keyctl_search(device_keyring, "logon", ref.c_str(), 0);
-    if (keyctl_revoke(key_serial) != 0) {
-        PLOG(ERROR) << "Failed to revoke key with serial " << key_serial << " ref " << ref;
-        return false;
-    }
-    LOG(DEBUG) << "Revoked key with serial " << key_serial << " ref " << ref;
-    return true;
-}
-
 bool e4crypt_destroy_user_key(userid_t user_id) {
     LOG(DEBUG) << "e4crypt_destroy_user_key(" << user_id << ")";
     if (!e4crypt_is_native()) {
@@ -527,12 +524,7 @@
     bool success = true;
     s_ce_keys.erase(user_id);
     std::string raw_ref;
-    // If we haven't loaded the CE key, no need to evict it.
-    if (lookup_key_ref(s_ce_key_raw_refs, user_id, &raw_ref)) {
-        success &= evict_key(raw_ref);
-    }
     s_ce_key_raw_refs.erase(user_id);
-    success &= lookup_key_ref(s_de_key_raw_refs, user_id, &raw_ref) && evict_key(raw_ref);
     s_de_key_raw_refs.erase(user_id);
     auto it = s_ephemeral_users.find(user_id);
     if (it != s_ephemeral_users.end()) {
@@ -541,7 +533,12 @@
         for (auto const path: get_ce_key_paths(get_ce_key_directory_path(user_id))) {
             success &= android::vold::destroyKey(path);
         }
-        success &= android::vold::destroyKey(get_de_key_path(user_id));
+        auto de_key_path = get_de_key_path(user_id);
+        if (path_exists(de_key_path)) {
+            success &= android::vold::destroyKey(de_key_path);
+        } else {
+            LOG(INFO) << "Not present so not erasing: " << de_key_path;
+        }
     }
     return success;
 }
@@ -616,6 +613,7 @@
 bool e4crypt_fixate_newest_user_key_auth(userid_t user_id) {
     LOG(DEBUG) << "e4crypt_fixate_newest_user_key_auth " << user_id;
     if (!e4crypt_is_native()) return true;
+    if (s_ephemeral_users.count(user_id) != 0) return true;
     auto const directory_path = get_ce_key_directory_path(user_id);
     auto const paths = get_ce_key_paths(directory_path);
     if (paths.empty()) {
@@ -736,6 +734,12 @@
             if (!ensure_policy(ce_raw_ref, misc_ce_path)) return false;
             if (!ensure_policy(ce_raw_ref, media_ce_path)) return false;
             if (!ensure_policy(ce_raw_ref, user_ce_path)) return false;
+
+            // Now that credentials have been installed, we can run restorecon
+            // over these paths
+            // NOTE: these paths need to be kept in sync with libselinux
+            android::vold::RestoreconRecursive(system_ce_path);
+            android::vold::RestoreconRecursive(misc_ce_path);
         }
     }
 
diff --git a/KeyStorage.cpp b/KeyStorage.cpp
index 5234c56..986f403 100644
--- a/KeyStorage.cpp
+++ b/KeyStorage.cpp
@@ -314,9 +314,13 @@
     return true;
 }
 
-static bool secdiscardSecdiscardable(const std::string& dir) {
+static bool runSecdiscard(const std::string& dir) {
     if (ForkExecvp(
-            std::vector<std::string>{kSecdiscardPath, "--", dir + "/" + kFn_secdiscardable}) != 0) {
+            std::vector<std::string>{kSecdiscardPath, "--",
+                dir + "/" + kFn_encrypted_key,
+                dir + "/" + kFn_keymaster_key_blob,
+                dir + "/" + kFn_secdiscardable,
+                }) != 0) {
         LOG(ERROR) << "secdiscard failed";
         return false;
     }
@@ -335,7 +339,7 @@
     bool success = true;
     // Try each thing, even if previous things failed.
     success &= deleteKey(dir);
-    success &= secdiscardSecdiscardable(dir);
+    success &= runSecdiscard(dir);
     success &= recursiveDeleteKey(dir);
     return success;
 }
diff --git a/MoveTask.cpp b/MoveTask.cpp
index a6e5fed..0a60c4e 100644
--- a/MoveTask.cpp
+++ b/MoveTask.cpp
@@ -182,8 +182,11 @@
 
     // Step 1: tear down volumes and mount silently without making
     // visible to userspace apps
-    bringOffline(mFrom);
-    bringOffline(mTo);
+    {
+        std::lock_guard<std::mutex> lock(VolumeManager::Instance()->getLock());
+        bringOffline(mFrom);
+        bringOffline(mTo);
+    }
 
     fromPath = mFrom->getInternalPath();
     toPath = mTo->getInternalPath();
@@ -195,14 +198,17 @@
 
     // Step 3: perform actual copy
     if (execCp(fromPath, toPath, 20, 60) != OK) {
-        goto fail;
+        goto copy_fail;
     }
 
     // NOTE: MountService watches for this magic value to know
     // that move was successful
     notifyProgress(82);
-    bringOnline(mFrom);
-    bringOnline(mTo);
+    {
+        std::lock_guard<std::mutex> lock(VolumeManager::Instance()->getLock());
+        bringOnline(mFrom);
+        bringOnline(mTo);
+    }
 
     // Step 4: clean up old data
     if (execRm(fromPath, 85, 15) != OK) {
@@ -212,9 +218,18 @@
     notifyProgress(kMoveSucceeded);
     release_wake_lock(kWakeLock);
     return;
+
+copy_fail:
+    // if we failed to copy the data we should not leave it laying around
+    // in target location. Do not check return value, we can not do any
+    // useful anyway.
+    execRm(toPath, 80, 1);
 fail:
-    bringOnline(mFrom);
-    bringOnline(mTo);
+    {
+        std::lock_guard<std::mutex> lock(VolumeManager::Instance()->getLock());
+        bringOnline(mFrom);
+        bringOnline(mTo);
+    }
     notifyProgress(kMoveFailedInternalError);
     release_wake_lock(kWakeLock);
     return;
diff --git a/PrivateVolume.cpp b/PrivateVolume.cpp
index 21746b2..e5809fb 100644
--- a/PrivateVolume.cpp
+++ b/PrivateVolume.cpp
@@ -137,23 +137,7 @@
         return -EIO;
     }
 
-    LOG(VERBOSE) << "Starting restorecon of " << mPath;
-
-    // TODO: find a cleaner way of waiting for restorecon to finish
-    property_set("selinux.restorecon_recursive", "");
-    property_set("selinux.restorecon_recursive", mPath.c_str());
-
-    char value[PROPERTY_VALUE_MAX];
-    while (true) {
-        property_get("selinux.restorecon_recursive", value, "");
-        if (strcmp(mPath.c_str(), value) == 0) {
-            break;
-        }
-        sleep(1);
-        LOG(VERBOSE) << "Waiting for restorecon...";
-    }
-
-    LOG(VERBOSE) << "Finished restorecon of " << mPath;
+    RestoreconRecursive(mPath);
 
     // Verify that common directories are ready to roll
     if (PrepareDir(mPath + "/app", 0771, AID_SYSTEM, AID_SYSTEM) ||
diff --git a/Utils.cpp b/Utils.cpp
index bf6f477..17e9ffd 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -646,6 +646,27 @@
     return StringPrintf("/fstab.%s", hardware);
 }
 
+status_t RestoreconRecursive(const std::string& path) {
+    LOG(VERBOSE) << "Starting restorecon of " << path;
+
+    // TODO: find a cleaner way of waiting for restorecon to finish
+    const char* cpath = path.c_str();
+    property_set("selinux.restorecon_recursive", "");
+    property_set("selinux.restorecon_recursive", cpath);
+
+    char value[PROPERTY_VALUE_MAX];
+    while (true) {
+        property_get("selinux.restorecon_recursive", value, "");
+        if (strcmp(cpath, value) == 0) {
+            break;
+        }
+        usleep(100000); // 100ms
+    }
+
+    LOG(VERBOSE) << "Finished restorecon of " << path;
+    return OK;
+}
+
 status_t SaneReadLinkAt(int dirfd, const char* path, char* buf, size_t bufsiz) {
     ssize_t len = readlinkat(dirfd, path, buf, bufsiz);
     if (len < 0) {
diff --git a/Utils.h b/Utils.h
index 9abd322..4bfd8e9 100644
--- a/Utils.h
+++ b/Utils.h
@@ -114,6 +114,8 @@
 
 std::string DefaultFstabPath();
 
+status_t RestoreconRecursive(const std::string& path);
+
 status_t SaneReadLinkAt(int dirfd, const char* path, char* buf, size_t bufsiz);
 
 class ScopedFd {
diff --git a/bench/benchgen.py b/bench/benchgen.py
index d529332..9a2bcd7 100644
--- a/bench/benchgen.py
+++ b/bench/benchgen.py
@@ -216,7 +216,7 @@
                 # TODO: track actual file size instead of guessing
                 count = min(int(e.args[2]), bufsize)
                 f.size += count
-                print >>bench, 'TEMP_FAILURE_RETRY(read(%s, buf, %d));' % (handle, count)
+                print >>bench, 'TEMP_FAILURE_RETRY(write(%s, buf, %d));' % (handle, count)
                 nwrite += 1
 
         elif e.call == "pread64":
diff --git a/cryptfs.c b/cryptfs.c
index 4baa2db..f6698f6 100644
--- a/cryptfs.c
+++ b/cryptfs.c
@@ -3869,3 +3869,9 @@
     return encrypt_master_key(password, ftr->salt, master_key, ftr->master_key,
                               ftr);
 }
+
+const char* cryptfs_get_file_encryption_mode()
+{
+    struct fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab, DATA_MNT_POINT);
+    return fs_mgr_get_file_encryption_mode(rec);
+}
diff --git a/cryptfs.h b/cryptfs.h
index c713067..bf158de 100644
--- a/cryptfs.h
+++ b/cryptfs.h
@@ -252,6 +252,7 @@
                              unsigned char* master_key);
   int cryptfs_set_password(struct crypt_mnt_ftr* ftr, const char* password,
                            const unsigned char* master_key);
+  const char* cryptfs_get_file_encryption_mode();
 
 #ifdef __cplusplus
 }
diff --git a/secdiscard.cpp b/secdiscard.cpp
index 5c12cdd..fe51990 100644
--- a/secdiscard.cpp
+++ b/secdiscard.cpp
@@ -43,11 +43,12 @@
 
 bool read_command_line(int argc, const char * const argv[], Options &options);
 void usage(const char *progname);
-int secdiscard_path(const std::string &path);
+bool secdiscard_path(const std::string &path);
 std::unique_ptr<struct fiemap> path_fiemap(const std::string &path, uint32_t extent_count);
 bool check_fiemap(const struct fiemap &fiemap, const std::string &path);
 std::unique_ptr<struct fiemap> alloc_fiemap(uint32_t extent_count);
 std::string block_device_for_path(const std::string &path);
+bool overwrite_with_zeros(int fd, off64_t start, off64_t length);
 
 }
 
@@ -58,9 +59,11 @@
         usage(argv[0]);
         return -1;
     }
-    for (auto target: options.targets) {
+    for (auto const &target: options.targets) {
         LOG(DEBUG) << "Securely discarding '" << target << "' unlink=" << options.unlink;
-        secdiscard_path(target);
+        if (!secdiscard_path(target)) {
+            LOG(ERROR) << "Secure discard failed for: " << target;
+        }
         if (options.unlink) {
             if (unlink(target.c_str()) != 0 && errno != ENOENT) {
                 PLOG(ERROR) << "Unable to unlink: " << target;
@@ -95,19 +98,19 @@
 }
 
 // BLKSECDISCARD all content in "path", if it's small enough.
-int secdiscard_path(const std::string &path) {
+bool secdiscard_path(const std::string &path) {
     auto fiemap = path_fiemap(path, max_extents);
     if (!fiemap || !check_fiemap(*fiemap, path)) {
-        return -1;
+        return false;
     }
     auto block_device = block_device_for_path(path);
     if (block_device.empty()) {
-        return -1;
+        return false;
     }
     AutoCloseFD fs_fd(block_device, O_RDWR | O_LARGEFILE);
     if (!fs_fd) {
         PLOG(ERROR) << "Failed to open device " << block_device;
-        return -1;
+        return false;
     }
     for (uint32_t i = 0; i < fiemap->fm_mapped_extents; i++) {
         uint64_t range[2];
@@ -115,10 +118,11 @@
         range[1] = fiemap->fm_extents[i].fe_length;
         if (ioctl(fs_fd.get(), BLKSECDISCARD, range) == -1) {
             PLOG(ERROR) << "Unable to BLKSECDISCARD " << path;
-            return -1;
+            if (!overwrite_with_zeros(fs_fd.get(), range[0], range[1])) return false;
+            LOG(DEBUG) << "Used zero overwrite";
         }
     }
-    return 0;
+    return true;
 }
 
 // Read the file's FIEMAP
@@ -206,4 +210,23 @@
     return result;
 }
 
+bool overwrite_with_zeros(int fd, off64_t start, off64_t length) {
+    if (lseek64(fd, start, SEEK_SET) != start) {
+        PLOG(ERROR) << "Seek failed for zero overwrite";
+        return false;
+    }
+    char buf[BUFSIZ];
+    memset(buf, 0, sizeof(buf));
+    while (length > 0) {
+        size_t wlen = static_cast<size_t>(std::min(static_cast<off64_t>(sizeof(buf)), length));
+        auto written = write(fd, buf, wlen);
+        if (written < 1) {
+            PLOG(ERROR) << "Write of zeroes failed";
+            return false;
+        }
+        length -= written;
+    }
+    return true;
+}
+
 }