1344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root/*
2344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root * Copyright (C) 2012 The Android Open Source Project
3344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root *
4344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root * Licensed under the Apache License, Version 2.0 (the "License");
5344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root * you may not use this file except in compliance with the License.
6344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root * You may obtain a copy of the License at
7344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root *
8344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root *      http://www.apache.org/licenses/LICENSE-2.0
9344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root *
10344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root * Unless required by applicable law or agreed to in writing, software
11344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root * distributed under the License is distributed on an "AS IS" BASIS,
12344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root * See the License for the specific language governing permissions and
14344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root * limitations under the License.
15344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root */
16344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
17344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#include <stdio.h>
18344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#include <stdlib.h>
19344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#include <fcntl.h>
20344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#include <unistd.h>
21344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#include <errno.h>
22344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#include <string.h>
23344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#include <dirent.h>
24344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#include <errno.h>
25344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#include <fcntl.h>
269c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey#include <vector>
279c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey#include <string>
28344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
29344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#include <sys/types.h>
30344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#include <sys/stat.h>
31344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#include <sys/types.h>
32344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#include <sys/mman.h>
33344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#include <sys/mount.h>
342ba45aafc22ff2fed91f8cd191beb85578b7b9bcRom Lemarchand#include <sys/wait.h>
35344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
36344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#include <linux/kdev_t.h>
37344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
38344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#define LOG_TAG "Vold"
39344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
407e128fbe212c64492afa98bfd6d7fab6f1956831Elliott Hughes#include <android-base/logging.h>
4195a92f9203ca68ab446a7cffd23450f04930fe38Jeff Sharkey#include <android-base/properties.h>
427e128fbe212c64492afa98bfd6d7fab6f1956831Elliott Hughes#include <android-base/stringprintf.h>
43344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#include <cutils/log.h>
44344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#include <cutils/properties.h>
452ba45aafc22ff2fed91f8cd191beb85578b7b9bcRom Lemarchand#include <logwrap/logwrap.h>
4695c87cce353ca2da79aa57a3a5336b45b6f1d018Jeff Sharkey#include <selinux/selinux.h>
472ba45aafc22ff2fed91f8cd191beb85578b7b9bcRom Lemarchand
48344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#include "Ext4.h"
4946bb69f49a8630cc97e84976d0327495b7dd5708Jeff Sharkey#include "Ext4Crypt.h"
509c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey#include "Utils.h"
515593c856f49684f149116a6f2f28ddf9338b8557Rom Lemarchand#include "VoldUtil.h"
52344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
539c48498f4529f623650c56d03e63324c8d813032Jeff Sharkeyusing android::base::StringPrintf;
549c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
55d0640f6358041f7e2657167560b357078db73526Jeff Sharkeynamespace android {
56d0640f6358041f7e2657167560b357078db73526Jeff Sharkeynamespace vold {
57d0640f6358041f7e2657167560b357078db73526Jeff Sharkeynamespace ext4 {
58d0640f6358041f7e2657167560b357078db73526Jeff Sharkey
59ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkeystatic const char* kResizefsPath = "/system/bin/resize2fs";
60e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknechtstatic const char* kMkfsPath = "/system/bin/mke2fs";
619c48498f4529f623650c56d03e63324c8d813032Jeff Sharkeystatic const char* kFsckPath = "/system/bin/e2fsck";
629c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
63d0640f6358041f7e2657167560b357078db73526Jeff Sharkeybool IsSupported() {
64d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    return access(kMkfsPath, X_OK) == 0
65d0640f6358041f7e2657167560b357078db73526Jeff Sharkey            && access(kFsckPath, X_OK) == 0
66d0640f6358041f7e2657167560b357078db73526Jeff Sharkey            && IsFilesystemSupported("ext4");
67d0640f6358041f7e2657167560b357078db73526Jeff Sharkey}
68d0640f6358041f7e2657167560b357078db73526Jeff Sharkey
69d0640f6358041f7e2657167560b357078db73526Jeff Sharkeystatus_t Check(const std::string& source, const std::string& target) {
709c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    // The following is shamelessly borrowed from fs_mgr.c, so it should be
719c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    // kept in sync with any changes over there.
729c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
73d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    const char* c_source = source.c_str();
74d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    const char* c_target = target.c_str();
759c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
769c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    int status;
779c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    int ret;
789c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    long tmpmnt_flags = MS_NOATIME | MS_NOEXEC | MS_NOSUID;
799c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    char *tmpmnt_opts = (char*) "nomblk_io_submit,errors=remount-ro";
809c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
819c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    /*
829c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey     * First try to mount and unmount the filesystem.  We do this because
839c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey     * the kernel is more efficient than e2fsck in running the journal and
849c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey     * processing orphaned inodes, and on at least one device with a
859c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey     * performance issue in the emmc firmware, it can take e2fsck 2.5 minutes
869c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey     * to do what the kernel does in about a second.
879c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey     *
889c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey     * After mounting and unmounting the filesystem, run e2fsck, and if an
899c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey     * error is recorded in the filesystem superblock, e2fsck will do a full
909c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey     * check.  Otherwise, it does nothing.  If the kernel cannot mount the
919c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey     * filesytsem due to an error, e2fsck is still run to do a full check
929c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey     * fix the filesystem.
939c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey     */
94d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    ret = mount(c_source, c_target, "ext4", tmpmnt_flags, tmpmnt_opts);
959c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    if (!ret) {
969c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        int i;
979c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        for (i = 0; i < 5; i++) {
989c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey            // Try to umount 5 times before continuing on.
999c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey            // Should we try rebooting if all attempts fail?
100d0640f6358041f7e2657167560b357078db73526Jeff Sharkey            int result = umount(c_target);
1019c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey            if (result == 0) {
1029c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey                break;
1039c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey            }
104d0640f6358041f7e2657167560b357078db73526Jeff Sharkey            ALOGW("%s(): umount(%s)=%d: %s\n", __func__, c_target, result, strerror(errno));
1059c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey            sleep(1);
1069c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        }
1079c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    }
1089c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
1099c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    /*
1109c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey     * Some system images do not have e2fsck for licensing reasons
1119c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey     * (e.g. recent SDK system images). Detect these and skip the check.
1129c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey     */
1139c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    if (access(kFsckPath, X_OK)) {
1149c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        ALOGD("Not running %s on %s (executable not in system image)\n",
115d0640f6358041f7e2657167560b357078db73526Jeff Sharkey                kFsckPath, c_source);
1169c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    } else {
117d0640f6358041f7e2657167560b357078db73526Jeff Sharkey        ALOGD("Running %s on %s\n", kFsckPath, c_source);
1189c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
119ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey        std::vector<std::string> cmd;
120ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey        cmd.push_back(kFsckPath);
121ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey        cmd.push_back("-y");
122d0640f6358041f7e2657167560b357078db73526Jeff Sharkey        cmd.push_back(c_source);
1239c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
124d0640f6358041f7e2657167560b357078db73526Jeff Sharkey        // ext4 devices are currently always trusted
125d0640f6358041f7e2657167560b357078db73526Jeff Sharkey        return ForkExecvp(cmd, sFsckContext);
1269c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    }
1279c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
1289c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    return 0;
1299c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey}
1309c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
131d0640f6358041f7e2657167560b357078db73526Jeff Sharkeystatus_t Mount(const std::string& source, const std::string& target, bool ro,
132d0640f6358041f7e2657167560b357078db73526Jeff Sharkey        bool remount, bool executable) {
133344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    int rc;
134344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    unsigned long flags;
135344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
136d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    const char* c_source = source.c_str();
137d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    const char* c_target = target.c_str();
138d0640f6358041f7e2657167560b357078db73526Jeff Sharkey
139344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    flags = MS_NOATIME | MS_NODEV | MS_NOSUID | MS_DIRSYNC;
140344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
141344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    flags |= (executable ? 0 : MS_NOEXEC);
142344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    flags |= (ro ? MS_RDONLY : 0);
143344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    flags |= (remount ? MS_REMOUNT : 0);
144344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
145d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    rc = mount(c_source, c_target, "ext4", flags, NULL);
146344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
147344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (rc && errno == EROFS) {
148d0640f6358041f7e2657167560b357078db73526Jeff Sharkey        SLOGE("%s appears to be a read only filesystem - retrying mount RO", c_source);
149344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        flags |= MS_RDONLY;
150d0640f6358041f7e2657167560b357078db73526Jeff Sharkey        rc = mount(c_source, c_target, "ext4", flags, NULL);
151344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
152344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
153344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    return rc;
154344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root}
155344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
156a4f48d0f44d09b6a9a3b16f6c0121ffd5123eef3Mateusz Nowakstatus_t Resize(const std::string& source, unsigned long numSectors) {
157ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    std::vector<std::string> cmd;
158ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    cmd.push_back(kResizefsPath);
159ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    cmd.push_back("-f");
160d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    cmd.push_back(source);
161a4f48d0f44d09b6a9a3b16f6c0121ffd5123eef3Mateusz Nowak    cmd.push_back(StringPrintf("%lu", numSectors));
162fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
163d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    return ForkExecvp(cmd);
164fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg}
165fcd34a0ddd45db83b7bc71ff47cba9b789089fddDaniel Rosenberg
166a4f48d0f44d09b6a9a3b16f6c0121ffd5123eef3Mateusz Nowakstatus_t Format(const std::string& source, unsigned long numSectors,
167d0640f6358041f7e2657167560b357078db73526Jeff Sharkey        const std::string& target) {
1689c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    std::vector<std::string> cmd;
1699c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    cmd.push_back(kMkfsPath);
170e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknecht
171e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknecht    cmd.push_back("-b");
172e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknecht    cmd.push_back("4096");
173e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknecht
174e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknecht    cmd.push_back("-t");
175e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknecht    cmd.push_back("ext4");
176e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknecht
177e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknecht    cmd.push_back("-M");
178e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknecht    cmd.push_back(target);
179e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknecht
18095a92f9203ca68ab446a7cffd23450f04930fe38Jeff Sharkey    std::string options("has_journal");
18195a92f9203ca68ab446a7cffd23450f04930fe38Jeff Sharkey    if (android::base::GetBoolProperty("vold.has_quota", false)) {
18295a92f9203ca68ab446a7cffd23450f04930fe38Jeff Sharkey        options += ",quota";
18395a92f9203ca68ab446a7cffd23450f04930fe38Jeff Sharkey    }
18446bb69f49a8630cc97e84976d0327495b7dd5708Jeff Sharkey    if (e4crypt_is_native()) {
18546bb69f49a8630cc97e84976d0327495b7dd5708Jeff Sharkey        options += ",encrypt";
18646bb69f49a8630cc97e84976d0327495b7dd5708Jeff Sharkey    }
18746bb69f49a8630cc97e84976d0327495b7dd5708Jeff Sharkey
188e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknecht    cmd.push_back("-O");
18946bb69f49a8630cc97e84976d0327495b7dd5708Jeff Sharkey    cmd.push_back(options);
190e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknecht
191e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknecht    cmd.push_back(source);
192e0f409ca32b4bb434c30557a2ed28cf1957098c0Adrien Schildknecht
1936a74dcaa6e646fea8e00b7c04332fc60fe7e017cDaniel Rosenberg    if (numSectors) {
194d794526962c385af307597f27d26aeb43703e6a1Jeff Sharkey        cmd.push_back(StringPrintf("%lu", numSectors * (4096 / 512)));
1956a74dcaa6e646fea8e00b7c04332fc60fe7e017cDaniel Rosenberg    }
1969c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
197d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    return ForkExecvp(cmd);
198344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root}
199d0640f6358041f7e2657167560b357078db73526Jeff Sharkey
200d0640f6358041f7e2657167560b357078db73526Jeff Sharkey}  // namespace ext4
201d0640f6358041f7e2657167560b357078db73526Jeff Sharkey}  // namespace vold
202d0640f6358041f7e2657167560b357078db73526Jeff Sharkey}  // namespace android
203