summaryrefslogtreecommitdiffstats
path: root/Ext4.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Ext4.cpp')
-rw-r--r--Ext4.cpp112
1 files changed, 92 insertions, 20 deletions
diff --git a/Ext4.cpp b/Ext4.cpp
index f5a964a..42d6cd3 100644
--- a/Ext4.cpp
+++ b/Ext4.cpp
@@ -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;