Merge "Add support for checkpointing"
diff --git a/Benchmark.cpp b/Benchmark.cpp
index 7fbf92e..b0a3b85 100644
--- a/Benchmark.cpp
+++ b/Benchmark.cpp
@@ -137,12 +137,12 @@
     // Only drop when we haven't aborted
     if (res == OK) {
         android::base::Timer timer;
-        LOG(VERBOSE) << "Before drop_caches";
+        LOG(DEBUG) << "Before drop_caches";
         if (!WriteStringToFile("3", "/proc/sys/vm/drop_caches")) {
             PLOG(ERROR) << "Failed to drop_caches";
             res = -1;
         }
-        LOG(VERBOSE) << "After drop_caches";
+        LOG(DEBUG) << "After drop_caches";
         sync();
         if (res == OK) extras->putLong(String16("drop"), timer.duration().count());
     }
diff --git a/Devmapper.cpp b/Devmapper.cpp
index e5c7e37..b42467c 100644
--- a/Devmapper.cpp
+++ b/Devmapper.cpp
@@ -252,7 +252,7 @@
                 }
             }
         } else {
-            LOG(VERBOSE) << "Found unmanaged dm device named " << name;
+            LOG(DEBUG) << "Found unmanaged dm device named " << name;
         }
         nxt = n->next;
     } while (nxt);
diff --git a/EncryptInplace.cpp b/EncryptInplace.cpp
index 7f0d770..d559bff 100644
--- a/EncryptInplace.cpp
+++ b/EncryptInplace.cpp
@@ -145,7 +145,7 @@
         return 0;
     }
 
-    LOG(VERBOSE) << "Copying " << data->count << " blocks at offset " << data->offset;
+    LOG(DEBUG) << "Copying " << data->count << " blocks at offset " << data->offset;
 
     if (pread64(data->realfd, data->buffer, info.block_size * data->count, data->offset) <= 0) {
         LOG(ERROR) << "Error reading real_blkdev " << data->real_blkdev << " for inplace encrypt";
diff --git a/Loop.cpp b/Loop.cpp
index 92f1e97..4926ea8 100644
--- a/Loop.cpp
+++ b/Loop.cpp
@@ -146,7 +146,7 @@
                 PLOG(WARNING) << "Failed to LOOP_CLR_FD " << path;
             }
         } else {
-            LOG(VERBOSE) << "Found unmanaged loop device at " << path << " named " << id;
+            LOG(DEBUG) << "Found unmanaged loop device at " << path << " named " << id;
         }
     }
 
diff --git a/MetadataCrypt.cpp b/MetadataCrypt.cpp
index 6edc0a4..0934563 100644
--- a/MetadataCrypt.cpp
+++ b/MetadataCrypt.cpp
@@ -102,20 +102,10 @@
 }
 
 static bool get_number_of_sectors(const std::string& real_blkdev, uint64_t* nr_sec) {
-    android::base::unique_fd dev_fd(
-        TEMP_FAILURE_RETRY(open(real_blkdev.c_str(), O_RDONLY | O_CLOEXEC, 0)));
-    if (dev_fd == -1) {
-        PLOG(ERROR) << "Unable to open " << real_blkdev << " to measure size";
-        return false;
-    }
-    unsigned long res;
-    // TODO: should use BLKGETSIZE64
-    get_blkdev_size(dev_fd.get(), &res);
-    if (res == 0) {
+    if (android::vold::GetBlockDev512Sectors(real_blkdev, nr_sec) != android::OK) {
         PLOG(ERROR) << "Unable to measure size of " << real_blkdev;
         return false;
     }
-    *nr_sec = res;
     return true;
 }
 
diff --git a/Utils.cpp b/Utils.cpp
index f085c22..9773cc0 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -265,9 +265,9 @@
     for (size_t i = 0; i < argc; i++) {
         argv[i] = (char*)args[i].c_str();
         if (i == 0) {
-            LOG(VERBOSE) << args[i];
+            LOG(DEBUG) << args[i];
         } else {
-            LOG(VERBOSE) << "    " << args[i];
+            LOG(DEBUG) << "    " << args[i];
         }
     }
 
@@ -300,9 +300,9 @@
     for (size_t i = 0; i < args.size(); i++) {
         cmd += args[i] + " ";
         if (i == 0) {
-            LOG(VERBOSE) << args[i];
+            LOG(DEBUG) << args[i];
         } else {
-            LOG(VERBOSE) << "    " << args[i];
+            LOG(DEBUG) << "    " << args[i];
         }
     }
     output.clear();
@@ -327,7 +327,7 @@
     }
     char line[1024];
     while (fgets(line, sizeof(line), fp) != nullptr) {
-        LOG(VERBOSE) << line;
+        LOG(DEBUG) << line;
         output.push_back(std::string(line));
     }
     if (pclose(fp) != 0) {
@@ -344,9 +344,9 @@
     for (size_t i = 0; i < argc; i++) {
         argv[i] = (char*)args[i].c_str();
         if (i == 0) {
-            LOG(VERBOSE) << args[i];
+            LOG(DEBUG) << args[i];
         } else {
-            LOG(VERBOSE) << "    " << args[i];
+            LOG(DEBUG) << "    " << args[i];
         }
     }
 
@@ -476,6 +476,42 @@
     return StrToHex(tmp, out);
 }
 
+status_t GetBlockDevSize(int fd, uint64_t* size) {
+    if (ioctl(fd, BLKGETSIZE64, size)) {
+        return -errno;
+    }
+
+    return OK;
+}
+
+status_t GetBlockDevSize(const std::string& path, uint64_t* size) {
+    int fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
+    status_t res = OK;
+
+    if (fd < 0) {
+        return -errno;
+    }
+
+    res = GetBlockDevSize(fd, size);
+
+    close(fd);
+
+    return res;
+}
+
+status_t GetBlockDev512Sectors(const std::string& path, uint64_t* nr_sec) {
+    uint64_t size;
+    status_t res = GetBlockDevSize(path, &size);
+
+    if (res != OK) {
+        return res;
+    }
+
+    *nr_sec = size / 512;
+
+    return OK;
+}
+
 uint64_t GetFreeBytes(const std::string& path) {
     struct statvfs sb;
     if (statvfs(path.c_str(), &sb) == 0) {
@@ -560,8 +596,7 @@
 status_t WipeBlockDevice(const std::string& path) {
     status_t res = -1;
     const char* c_path = path.c_str();
-    unsigned long nr_sec = 0;
-    unsigned long long range[2];
+    uint64_t range[2] = {0, 0};
 
     int fd = TEMP_FAILURE_RETRY(open(c_path, O_RDWR | O_CLOEXEC));
     if (fd == -1) {
@@ -569,14 +604,11 @@
         goto done;
     }
 
-    if ((ioctl(fd, BLKGETSIZE, &nr_sec)) == -1) {
+    if (GetBlockDevSize(fd, &range[1]) != OK) {
         PLOG(ERROR) << "Failed to determine size of " << path;
         goto done;
     }
 
-    range[0] = 0;
-    range[1] = (unsigned long long)nr_sec * 512;
-
     LOG(INFO) << "About to discard " << range[1] << " on " << path;
     if (ioctl(fd, BLKDISCARD, &range) == 0) {
         LOG(INFO) << "Discard success on " << path;
@@ -686,7 +718,7 @@
 }
 
 status_t RestoreconRecursive(const std::string& path) {
-    LOG(VERBOSE) << "Starting restorecon of " << path;
+    LOG(DEBUG) << "Starting restorecon of " << path;
 
     static constexpr const char* kRestoreconString = "selinux.restorecon_recursive";
 
@@ -695,7 +727,7 @@
 
     android::base::WaitForProperty(kRestoreconString, path);
 
-    LOG(VERBOSE) << "Finished restorecon of " << path;
+    LOG(DEBUG) << "Finished restorecon of " << path;
     return OK;
 }
 
diff --git a/Utils.h b/Utils.h
index 09ce8fa..40f4d0a 100644
--- a/Utils.h
+++ b/Utils.h
@@ -76,6 +76,12 @@
 
 pid_t ForkExecvpAsync(const std::vector<std::string>& args);
 
+/* Gets block device size in bytes */
+status_t GetBlockDevSize(int fd, uint64_t* size);
+status_t GetBlockDevSize(const std::string& path, uint64_t* size);
+/* Gets block device size in 512 byte sectors */
+status_t GetBlockDev512Sectors(const std::string& path, uint64_t* nr_sec);
+
 status_t ReadRandomBytes(size_t bytes, std::string& out);
 status_t ReadRandomBytes(size_t bytes, char* buffer);
 status_t GenerateRandomUuid(std::string& out);
diff --git a/VoldUtil.cpp b/VoldUtil.cpp
index 26c817c..4b980be 100644
--- a/VoldUtil.cpp
+++ b/VoldUtil.cpp
@@ -18,9 +18,3 @@
 #include <sys/ioctl.h>
 
 struct fstab* fstab_default;
-
-void get_blkdev_size(int fd, unsigned long* nr_sec) {
-    if ((ioctl(fd, BLKGETSIZE, nr_sec)) == -1) {
-        *nr_sec = 0;
-    }
-}
diff --git a/VoldUtil.h b/VoldUtil.h
index 4311586..782e36d 100644
--- a/VoldUtil.h
+++ b/VoldUtil.h
@@ -24,6 +24,4 @@
 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
 
-void get_blkdev_size(int fd, unsigned long* nr_sec);
-
 #endif
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index f0b742e..53380af 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -176,8 +176,8 @@
     std::lock_guard<std::mutex> lock(mLock);
 
     if (mDebug) {
-        LOG(VERBOSE) << "----------------";
-        LOG(VERBOSE) << "handleBlockEvent with action " << (int)evt->getAction();
+        LOG(DEBUG) << "----------------";
+        LOG(DEBUG) << "handleBlockEvent with action " << (int)evt->getAction();
         evt->dump();
     }
 
diff --git a/cryptfs.cpp b/cryptfs.cpp
index 383bbe8..4a76fb7 100644
--- a/cryptfs.cpp
+++ b/cryptfs.cpp
@@ -394,10 +394,10 @@
     return get_crypto_type().get_crypto_name();
 }
 
-static unsigned int get_fs_size(char* dev) {
+static uint64_t get_fs_size(char* dev) {
     int fd, block_size;
     struct ext4_super_block sb;
-    off64_t len;
+    uint64_t len;
 
     if ((fd = open(dev, O_RDONLY | O_CLOEXEC)) < 0) {
         SLOGE("Cannot open device to get filesystem size ");
@@ -422,17 +422,16 @@
     }
     block_size = 1024 << sb.s_log_block_size;
     /* compute length in bytes */
-    len = (((off64_t)sb.s_blocks_count_hi << 32) + sb.s_blocks_count_lo) * block_size;
+    len = (((uint64_t)sb.s_blocks_count_hi << 32) + sb.s_blocks_count_lo) * block_size;
 
     /* return length in sectors */
-    return (unsigned int)(len / 512);
+    return len / 512;
 }
 
 static int get_crypt_ftr_info(char** metadata_fname, off64_t* off) {
     static int cached_data = 0;
-    static off64_t cached_off = 0;
+    static uint64_t cached_off = 0;
     static char cached_metadata_fname[PROPERTY_VALUE_MAX] = "";
-    int fd;
     char key_loc[PROPERTY_VALUE_MAX];
     char real_blkdev[PROPERTY_VALUE_MAX];
     int rc = -1;
@@ -441,25 +440,17 @@
         fs_mgr_get_crypt_info(fstab_default, key_loc, real_blkdev, sizeof(key_loc));
 
         if (!strcmp(key_loc, KEY_IN_FOOTER)) {
-            if ((fd = open(real_blkdev, O_RDWR | O_CLOEXEC)) < 0) {
-                SLOGE("Cannot open real block device %s\n", real_blkdev);
-                return -1;
-            }
-
-            unsigned long nr_sec = 0;
-            get_blkdev_size(fd, &nr_sec);
-            if (nr_sec != 0) {
+            if (android::vold::GetBlockDevSize(real_blkdev, &cached_off) == android::OK) {
                 /* If it's an encrypted Android partition, the last 16 Kbytes contain the
                  * encryption info footer and key, and plenty of bytes to spare for future
                  * growth.
                  */
                 strlcpy(cached_metadata_fname, real_blkdev, sizeof(cached_metadata_fname));
-                cached_off = ((off64_t)nr_sec * 512) - CRYPT_FOOTER_OFFSET;
+                cached_off -= CRYPT_FOOTER_OFFSET;
                 cached_data = 1;
             } else {
                 SLOGE("Cannot get size of block device %s\n", real_blkdev);
             }
-            close(fd);
         } else {
             strlcpy(cached_metadata_fname, key_loc, sizeof(cached_metadata_fname));
             cached_off = 0;
@@ -1819,17 +1810,8 @@
  */
 int cryptfs_setup_ext_volume(const char* label, const char* real_blkdev, const unsigned char* key,
                              char* out_crypto_blkdev) {
-    int fd = open(real_blkdev, O_RDONLY | O_CLOEXEC);
-    if (fd == -1) {
-        SLOGE("Failed to open %s: %s", real_blkdev, strerror(errno));
-        return -1;
-    }
-
-    unsigned long nr_sec = 0;
-    get_blkdev_size(fd, &nr_sec);
-    close(fd);
-
-    if (nr_sec == 0) {
+    uint64_t nr_sec = 0;
+    if (android::vold::GetBlockDev512Sectors(real_blkdev, &nr_sec) != android::OK) {
         SLOGE("Failed to get size of %s: %s", real_blkdev, strerror(errno));
         return -1;
     }
@@ -2093,7 +2075,6 @@
     off64_t previously_encrypted_upto = 0;
     bool rebootEncryption = false;
     bool onlyCreateHeader = false;
-    int fd = -1;
 
     if (get_crypt_ftr_and_key(&crypt_ftr) == 0) {
         if (crypt_ftr.flags & CRYPT_ENCRYPTION_IN_PROGRESS) {
@@ -2137,22 +2118,15 @@
     fs_mgr_get_crypt_info(fstab_default, 0, real_blkdev, sizeof(real_blkdev));
 
     /* Get the size of the real block device */
-    fd = open(real_blkdev, O_RDONLY | O_CLOEXEC);
-    if (fd == -1) {
-        SLOGE("Cannot open block device %s\n", real_blkdev);
-        goto error_unencrypted;
-    }
-    unsigned long nr_sec;
-    get_blkdev_size(fd, &nr_sec);
-    if (nr_sec == 0) {
+    uint64_t nr_sec;
+    if (android::vold::GetBlockDev512Sectors(real_blkdev, &nr_sec) != android::OK) {
         SLOGE("Cannot get size of block device %s\n", real_blkdev);
         goto error_unencrypted;
     }
-    close(fd);
 
     /* If doing inplace encryption, make sure the orig fs doesn't include the crypto footer */
     if (!strcmp(key_loc, KEY_IN_FOOTER)) {
-        unsigned int fs_size_sec, max_fs_size_sec;
+        uint64_t fs_size_sec, max_fs_size_sec;
         fs_size_sec = get_fs_size(real_blkdev);
         if (fs_size_sec == 0) fs_size_sec = get_f2fs_filesystem_size_sec(real_blkdev);
 
diff --git a/main.cpp b/main.cpp
index 52abf20..e1f8404 100644
--- a/main.cpp
+++ b/main.cpp
@@ -53,17 +53,17 @@
 
 int main(int argc, char** argv) {
     atrace_set_tracing_enabled(false);
-    setenv("ANDROID_LOG_TAGS", "*:v", 1);
+    setenv("ANDROID_LOG_TAGS", "*:d", 1);
     android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM));
 
     LOG(INFO) << "Vold 3.0 (the awakening) firing up";
 
     ATRACE_BEGIN("main");
 
-    LOG(VERBOSE) << "Detected support for:"
-                 << (android::vold::IsFilesystemSupported("ext4") ? " ext4" : "")
-                 << (android::vold::IsFilesystemSupported("f2fs") ? " f2fs" : "")
-                 << (android::vold::IsFilesystemSupported("vfat") ? " vfat" : "");
+    LOG(DEBUG) << "Detected support for:"
+               << (android::vold::IsFilesystemSupported("ext4") ? " ext4" : "")
+               << (android::vold::IsFilesystemSupported("f2fs") ? " f2fs" : "")
+               << (android::vold::IsFilesystemSupported("vfat") ? " vfat" : "");
 
     VolumeManager* vm;
     NetlinkManager* nm;
diff --git a/model/Disk.cpp b/model/Disk.cpp
index 13cb1c7..2b6773d 100644
--- a/model/Disk.cpp
+++ b/model/Disk.cpp
@@ -243,12 +243,8 @@
     mSize = -1;
     mLabel.clear();
 
-    int fd = open(mDevPath.c_str(), O_RDONLY | O_CLOEXEC);
-    if (fd != -1) {
-        if (ioctl(fd, BLKGETSIZE64, &mSize)) {
-            mSize = -1;
-        }
-        close(fd);
+    if (GetBlockDevSize(mDevPath, &mSize) != OK) {
+        mSize = -1;
     }
 
     unsigned int majorId = major(mDevice);
diff --git a/model/EmulatedVolume.cpp b/model/EmulatedVolume.cpp
index 7ec109c..8d9ac74 100644
--- a/model/EmulatedVolume.cpp
+++ b/model/EmulatedVolume.cpp
@@ -105,7 +105,7 @@
 
     nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME);
     while (before == GetDevice(mFuseWrite)) {
-        LOG(VERBOSE) << "Waiting for FUSE to spin up...";
+        LOG(DEBUG) << "Waiting for FUSE to spin up...";
         usleep(50000);  // 50ms
 
         nsecs_t now = systemTime(SYSTEM_TIME_BOOTTIME);
diff --git a/model/ObbVolume.cpp b/model/ObbVolume.cpp
index ec3d267..21479c4 100644
--- a/model/ObbVolume.cpp
+++ b/model/ObbVolume.cpp
@@ -23,7 +23,6 @@
 
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
-#include <android-base/unique_fd.h>
 #include <cutils/fs.h>
 #include <private/android_filesystem_config.h>
 
@@ -36,7 +35,6 @@
 #include <sys/wait.h>
 
 using android::base::StringPrintf;
-using android::base::unique_fd;
 
 namespace android {
 namespace vold {
@@ -59,19 +57,10 @@
     }
 
     if (!mSourceKey.empty()) {
-        unsigned long nr_sec = 0;
-        {
-            unique_fd loop_fd(open(mLoopPath.c_str(), O_RDWR | O_CLOEXEC));
-            if (loop_fd.get() == -1) {
-                PLOG(ERROR) << getId() << " failed to open loop";
-                return -1;
-            }
-
-            get_blkdev_size(loop_fd.get(), &nr_sec);
-            if (nr_sec == 0) {
-                PLOG(ERROR) << getId() << " failed to get loop size";
-                return -1;
-            }
+        uint64_t nr_sec = 0;
+        if (GetBlockDev512Sectors(mLoopPath, &nr_sec) != OK) {
+            PLOG(ERROR) << getId() << " failed to get loop size";
+            return -1;
         }
 
         char tmp[PATH_MAX];
diff --git a/model/PublicVolume.cpp b/model/PublicVolume.cpp
index 7420c79..8ed4356 100644
--- a/model/PublicVolume.cpp
+++ b/model/PublicVolume.cpp
@@ -202,7 +202,7 @@
 
     nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME);
     while (before == GetDevice(mFuseWrite)) {
-        LOG(VERBOSE) << "Waiting for FUSE to spin up...";
+        LOG(DEBUG) << "Waiting for FUSE to spin up...";
         usleep(50000);  // 50ms
 
         nsecs_t now = systemTime(SYSTEM_TIME_BOOTTIME);
@@ -246,28 +246,53 @@
 }
 
 status_t PublicVolume::doFormat(const std::string& fsType) {
-    if ((fsType == "vfat" || fsType == "auto") && vfat::IsSupported()) {
-        if (WipeBlockDevice(mDevPath) != OK) {
-            LOG(WARNING) << getId() << " failed to wipe";
+    bool useVfat = vfat::IsSupported();
+    bool useExfat = exfat::IsSupported();
+    status_t res = OK;
+
+    // Resolve the target filesystem type
+    if (fsType == "auto" && useVfat && useExfat) {
+        uint64_t size = 0;
+
+        res = GetBlockDevSize(mDevPath, &size);
+        if (res != OK) {
+            LOG(ERROR) << "Couldn't get device size " << mDevPath;
+            return res;
         }
-        if (vfat::Format(mDevPath, 0)) {
-            LOG(ERROR) << getId() << " failed to format";
-            return -errno;
+
+        // If both vfat & exfat are supported use exfat for SDXC (>~32GiB) cards
+        if (size > 32896LL * 1024 * 1024) {
+            useVfat = false;
+        } else {
+            useExfat = false;
         }
-    } else if ((fsType == "exfat" || fsType == "auto") && exfat::IsSupported()) {
-        if (WipeBlockDevice(mDevPath) != OK) {
-            LOG(WARNING) << getId() << " failed to wipe";
-        }
-        if (exfat::Format(mDevPath)) {
-            LOG(ERROR) << getId() << " failed to format";
-            return -errno;
-        }
-    } else {
+    } else if (fsType == "vfat") {
+        useExfat = false;
+    } else if (fsType == "exfat") {
+        useVfat = false;
+    }
+
+    if (!useVfat && !useExfat) {
         LOG(ERROR) << "Unsupported filesystem " << fsType;
         return -EINVAL;
     }
 
-    return OK;
+    if (WipeBlockDevice(mDevPath) != OK) {
+        LOG(WARNING) << getId() << " failed to wipe";
+    }
+
+    if (useVfat) {
+        res = vfat::Format(mDevPath, 0);
+    } else if (useExfat) {
+        res = exfat::Format(mDevPath);
+    }
+
+    if (res != OK) {
+        LOG(ERROR) << getId() << " failed to format";
+        res = -errno;
+    }
+
+    return res;
 }
 
 }  // namespace vold