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

Commit 77b37c9f authored by Thurston Dang's avatar Thurston Dang Committed by Automerger Merge Worker
Browse files

storageproxyd: discard writes when checkpointing, if necessary am: 98e7f427

Original change: https://googleplex-android-review.googlesource.com/c/platform/system/core/+/16049468

Change-Id: I8b0d1da6d516313b5e672bc3a6c0ea8075e01c17
parents cb1fabef 98e7f427
Loading
Loading
Loading
Loading
+22 −18
Original line number Diff line number Diff line
@@ -115,7 +115,7 @@ enum storage_file_open_flag {
 * @STORAGE_MSG_FLAG_BATCH:                 if set, command belongs to a batch transaction.
 *                                          No response will be sent by the server until
 *                                          it receives a command with this flag unset, at
 *                                      which point a cummulative result for all messages
 *                                          which point a cumulative result for all messages
 *                                          sent with STORAGE_MSG_FLAG_BATCH will be sent.
 *                                          This is only supported by the non-secure disk proxy
 *                                          server.
@@ -126,12 +126,16 @@ enum storage_file_open_flag {
 * @STORAGE_MSG_FLAG_TRANSACT_COMPLETE:     if set, indicates that server need to commit
 *                                          current transaction after processing this message.
 *                                          It is an alias for STORAGE_MSG_FLAG_POST_COMMIT.
 * @STORAGE_MSG_FLAG_PRE_COMMIT_CHECKPOINT: if set, indicates that server needs to ensure
 *                                          that there is not a pending checkpoint for
 *                                          userdata before processing this message.
 */
enum storage_msg_flag {
    STORAGE_MSG_FLAG_BATCH = 0x1,
    STORAGE_MSG_FLAG_PRE_COMMIT = 0x2,
    STORAGE_MSG_FLAG_POST_COMMIT = 0x4,
    STORAGE_MSG_FLAG_TRANSACT_COMPLETE = STORAGE_MSG_FLAG_POST_COMMIT,
    STORAGE_MSG_FLAG_PRE_COMMIT_CHECKPOINT = 0x8,
};

/*
+3 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ cc_binary {
    vendor: true,

    srcs: [
        "checkpoint_handling.cpp",
        "ipc.c",
        "rpmb.c",
        "storage.c",
@@ -30,12 +31,14 @@ cc_binary {
    ],

    shared_libs: [
        "libbase",
        "liblog",
        "libhardware_legacy",
    ],
    header_libs: ["libcutils_headers"],

    static_libs: [
        "libfstab",
        "libtrustystorageinterface",
        "libtrusty",
    ],
+77 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "checkpoint_handling.h"
#include "log.h"

#include <fstab/fstab.h>
#include <cstring>
#include <string>

namespace {

bool checkpointingDoneForever = false;

}  // namespace

int is_data_checkpoint_active(bool* active) {
    if (!active) {
        ALOGE("active out parameter is null");
        return 0;
    }

    *active = false;

    if (checkpointingDoneForever) {
        return 0;
    }

    android::fs_mgr::Fstab procMounts;
    bool success = android::fs_mgr::ReadFstabFromFile("/proc/mounts", &procMounts);
    if (!success) {
        ALOGE("Could not parse /proc/mounts\n");
        /* Really bad. Tell the caller to abort the write. */
        return -1;
    }

    android::fs_mgr::FstabEntry* dataEntry =
            android::fs_mgr::GetEntryForMountPoint(&procMounts, "/data");
    if (dataEntry == NULL) {
        ALOGE("/data is not mounted yet\n");
        return 0;
    }

    /* We can't handle e.g., ext4. Nothing we can do about it for now. */
    if (dataEntry->fs_type != "f2fs") {
        ALOGW("Checkpoint status not supported for filesystem %s\n", dataEntry->fs_type.c_str());
        checkpointingDoneForever = true;
        return 0;
    }

    /*
     * The data entry looks like "... blah,checkpoint=disable:0,blah ...".
     * checkpoint=disable means checkpointing is on (yes, arguably reversed).
     */
    size_t checkpointPos = dataEntry->fs_options.find("checkpoint=disable");
    if (checkpointPos == std::string::npos) {
        /* Assumption is that once checkpointing turns off, it stays off */
        checkpointingDoneForever = true;
    } else {
        *active = true;
    }

    return 0;
}
+37 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
 * is_data_checkpoint_active() - Check for an active, uncommitted checkpoint of
 * /data. If a checkpoint is active, storage should not commit any
 * rollback-protected writes to /data.
 * @active: Out parameter that will be set to the result of the check.
 *
 * Return: 0 if active was set and is valid, non-zero otherwise.
 */
int is_data_checkpoint_active(bool* active);

#ifdef __cplusplus
}
#endif
+16 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@

#include <cutils/android_filesystem_config.h>

#include "checkpoint_handling.h"
#include "ipc.h"
#include "log.h"
#include "rpmb.h"
@@ -130,6 +131,21 @@ static int handle_req(struct storage_msg* msg, const void* req, size_t req_len)
        }
    }

    if (msg->flags & STORAGE_MSG_FLAG_PRE_COMMIT_CHECKPOINT) {
        bool is_checkpoint_active = false;

        rc = is_data_checkpoint_active(&is_checkpoint_active);
        if (rc != 0) {
            ALOGE("is_data_checkpoint_active failed in an unexpected way. Aborting.\n");
            msg->result = STORAGE_ERR_GENERIC;
            return ipc_respond(msg, NULL, 0);
        } else if (is_checkpoint_active) {
            ALOGE("Checkpoint in progress, dropping write ...\n");
            msg->result = STORAGE_ERR_GENERIC;
            return ipc_respond(msg, NULL, 0);
        }
    }

    switch (msg->cmd) {
        case STORAGE_FILE_DELETE:
            rc = storage_file_delete(msg, req, req_len);