Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bee7b8c8 authored by Nikita Ioffe's avatar Nikita Ioffe
Browse files

Add basic support for remounting ext4 userdata into checkpoint

Metadata encrypted ext4 userdata and v2 encryption keys will be
supported in follow up CLs.

Test: adb shell /system/bin/vdc checkpoint startCheckpoint 1
Test: adb reboot userspace
Bug: 135984674
Bug: 143970043
Change-Id: I8dbf3bddd811cf54d3f2b2ee2c1ea64159d8c6e0
parent 57d7bb69
Loading
Loading
Loading
Loading
+27 −3
Original line number Diff line number Diff line
@@ -1118,6 +1118,12 @@ int fs_mgr_mount_all(Fstab* fstab, int mount_mode) {
            continue;
        }

        // Terrible hack to make it possible to remount /data.
        // TODO: refact fs_mgr_mount_all and get rid of this.
        if (mount_mode == MOUNT_MODE_ONLY_USERDATA && current_entry.mount_point != "/data") {
            continue;
        }

        // Translate LABEL= file system labels into block devices.
        if (is_extfs(current_entry.fs_type)) {
            if (!TranslateExtLabels(&current_entry)) {
@@ -1351,6 +1357,7 @@ int fs_mgr_umount_all(android::fs_mgr::Fstab* fstab) {
    return ret;
}

// TODO(b/143970043): return different error codes based on which step failed.
int fs_mgr_remount_userdata_into_checkpointing(Fstab* fstab) {
    auto entry = GetMountedEntryForUserdata(fstab);
    if (entry == nullptr) {
@@ -1374,12 +1381,29 @@ int fs_mgr_remount_userdata_into_checkpointing(Fstab* fstab) {
        }
        if (mount(entry->blk_device.c_str(), entry->mount_point.c_str(), "none",
                  MS_REMOUNT | entry->flags, entry->fs_options.c_str()) != 0) {
            LERROR << "Failed to remount userdata in checkpointing mode";
            PERROR << "Failed to remount userdata in checkpointing mode";
            return -1;
        }
    } else {
        // STOPSHIP(b/143970043): support remounting for ext4.
        LWARNING << "Remounting into checkpointing is not supported for ex4. Proceed with caution";
        // STOPSHIP(b/143970043): support remounting for ext4 + metadata encryption.
        if (should_use_metadata_encryption(*entry)) {
            LWARNING << "Remounting into checkpointing is not supported for metadata encrypted "
                     << "ext4 userdata. Proceed with caution";
            return 0;
        }
        if (umount2("/data", UMOUNT_NOFOLLOW) != 0) {
            PERROR << "Failed to umount /data";
            return -1;
        }
        DeviceMapper& dm = DeviceMapper::Instance();
        // TODO(b/143970043): need to delete every dm-device under the one userdata is mounted on.
        if (!dm.DeleteDeviceIfExists("bow")) {
            LERROR << "Failed to delete dm-bow";
            return -1;
        }
        // TODO(b/143970043): remove this hack after fs_mgr_mount_all is refactored.
        int result = fs_mgr_mount_all(fstab, MOUNT_MODE_ONLY_USERDATA);
        return result == FS_MGR_MNTALL_FAIL ? -1 : 0;
    }
    return 0;
}
+3 −1
Original line number Diff line number Diff line
@@ -46,7 +46,9 @@ enum verity_mode {
enum mount_mode {
    MOUNT_MODE_DEFAULT = 0,
    MOUNT_MODE_EARLY = 1,
    MOUNT_MODE_LATE = 2
    MOUNT_MODE_LATE = 2,
    // TODO(b/135984674): remove this after refactoring fs_mgr_mount_all.
    MOUNT_MODE_ONLY_USERDATA = 3
};

#define FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED 7
+11 −7
Original line number Diff line number Diff line
@@ -186,17 +186,17 @@ static void TurnOffBacklight() {
    }
}

static Result<void> ShutdownVold() {
    const char* vdc_argv[] = {"/system/bin/vdc", "volume", "shutdown"};
static Result<void> CallVdc(const std::string& system, const std::string& cmd) {
    const char* vdc_argv[] = {"/system/bin/vdc", system.c_str(), cmd.c_str()};
    int status;
    if (logwrap_fork_execvp(arraysize(vdc_argv), vdc_argv, &status, false, LOG_KLOG, true,
                            nullptr) != 0) {
        return ErrnoError() << "Failed to call 'vdc volume shutdown'";
        return ErrnoError() << "Failed to call '/system/bin/vdc " << system << " " << cmd << "'";
    }
    if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
        return {};
    }
    return Error() << "'vdc volume shutdown' failed : " << status;
    return Error() << "'/system/bin/vdc " << system << " " << cmd << "' failed : " << status;
}

static void LogShutdownTime(UmountStat stat, Timer* t) {
@@ -658,7 +658,7 @@ static void DoReboot(unsigned int cmd, const std::string& reason, const std::str
    // 3. send volume shutdown to vold
    Service* vold_service = ServiceList::GetInstance().FindService("vold");
    if (vold_service != nullptr && vold_service->IsRunning()) {
        ShutdownVold();
        CallVdc("volume", "shutdown");
        vold_service->Stop();
    } else {
        LOG(INFO) << "vold not running, skipping vold shutdown";
@@ -774,8 +774,12 @@ static Result<void> DoUserspaceReboot() {
        // TODO(b/135984674): store information about offending services for debugging.
        return Error() << r << " post-data services are still running";
    }
    // TODO(b/143970043): in case of ext4 we probably we will need to restart vold and kill zram
    //  backing device.
    if (auto result = KillZramBackingDevice(); !result) {
        return result;
    }
    if (auto result = CallVdc("volume", "reset"); !result) {
        return result;
    }
    if (int r = StopServicesAndLogViolations(GetDebuggingServices(true /* only_post_data */), 5s,
                                             false /* SIGKILL */);
        r > 0) {