diff options
Diffstat (limited to 'Ext4.cpp')
-rw-r--r-- | Ext4.cpp | 112 |
1 files changed, 92 insertions, 20 deletions
@@ -23,6 +23,8 @@ #include <dirent.h> #include <errno.h> #include <fcntl.h> +#include <vector> +#include <string> #include <sys/types.h> #include <sys/stat.h> @@ -35,17 +37,92 @@ #define LOG_TAG "Vold" +#include <base/stringprintf.h> #include <cutils/log.h> #include <cutils/properties.h> - #include <logwrap/logwrap.h> #include "Ext4.h" +#include "Utils.h" #include "VoldUtil.h" -#define MKEXT4FS_PATH "/system/bin/make_ext4fs" #define RESIZE2FS_PATH "/system/bin/resize2fs" +using android::base::StringPrintf; + +static const char* kMkfsPath = "/system/bin/make_ext4fs"; + +static const char* kFsckPath = "/system/bin/e2fsck"; +static const char* kFsckLogFile = "/dev/fscklogs/log"; + +int Ext4::check(const char *fsPath, const char *mountPoint) { + // The following is shamelessly borrowed from fs_mgr.c, so it should be + // kept in sync with any changes over there. + + char* blk_device = (char*) fsPath; + char* target = (char*) mountPoint; + + int status; + int ret; + long tmpmnt_flags = MS_NOATIME | MS_NOEXEC | MS_NOSUID; + char *tmpmnt_opts = (char*) "nomblk_io_submit,errors=remount-ro"; + char *e2fsck_argv[] = { + (char*) kFsckPath, + (char*) "-y", + blk_device + }; + + /* + * First try to mount and unmount the filesystem. We do this because + * the kernel is more efficient than e2fsck in running the journal and + * processing orphaned inodes, and on at least one device with a + * performance issue in the emmc firmware, it can take e2fsck 2.5 minutes + * to do what the kernel does in about a second. + * + * After mounting and unmounting the filesystem, run e2fsck, and if an + * error is recorded in the filesystem superblock, e2fsck will do a full + * check. Otherwise, it does nothing. If the kernel cannot mount the + * filesytsem due to an error, e2fsck is still run to do a full check + * fix the filesystem. + */ + ret = mount(blk_device, target, "ext4", tmpmnt_flags, tmpmnt_opts); + if (!ret) { + int i; + for (i = 0; i < 5; i++) { + // Try to umount 5 times before continuing on. + // Should we try rebooting if all attempts fail? + int result = umount(target); + if (result == 0) { + break; + } + ALOGW("%s(): umount(%s)=%d: %s\n", __func__, target, result, strerror(errno)); + sleep(1); + } + } + + /* + * Some system images do not have e2fsck for licensing reasons + * (e.g. recent SDK system images). Detect these and skip the check. + */ + if (access(kFsckPath, X_OK)) { + ALOGD("Not running %s on %s (executable not in system image)\n", + kFsckPath, blk_device); + } else { + ALOGD("Running %s on %s\n", kFsckPath, blk_device); + + ret = android_fork_execvp(ARRAY_SIZE(e2fsck_argv), e2fsck_argv, + &status, false, true); + + if (ret < 0) { + /* No need to check for error in fork, we can't really handle it now */ + ALOGW("Failed trying to run %s\n", kFsckPath); + return -1; + } + } + + return 0; +} + int Ext4::doMount(const char *fsPath, const char *mountPoint, bool ro, bool remount, bool executable) { int rc; @@ -112,28 +189,23 @@ int Ext4::resize(const char *fspath, unsigned int numSectors) { } int Ext4::format(const char *fsPath, unsigned int numSectors, const char *mountpoint) { - const char *args[7]; - int rc; int status; - args[0] = MKEXT4FS_PATH; - args[1] = "-J"; - args[2] = "-a"; - args[3] = mountpoint; + std::vector<std::string> cmd; + cmd.push_back(kMkfsPath); + cmd.push_back("-J"); + + cmd.push_back("-a"); + cmd.push_back(mountpoint); + if (numSectors) { - char tmp[32]; - snprintf(tmp, sizeof(tmp), "%u", numSectors * 512); - const char *size = tmp; - args[4] = "-l"; - args[5] = size; - args[6] = fsPath; - rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, true); - } else { - args[4] = fsPath; - rc = android_fork_execvp(5, (char **)args, &status, false, true); + cmd.push_back("-l"); + cmd.push_back(StringPrintf("%u", numSectors * 512)); } - rc = android_fork_execvp(ARRAY_SIZE(args), (char **)args, &status, false, - true); + + cmd.push_back(fsPath); + + int rc = android::vold::ForkExecvp(cmd, &status, false, true); if (rc != 0) { SLOGE("Filesystem (ext4) format failed due to logwrap error"); errno = EIO; |