blob: 2ea5136a1bd9fcbcb5899c7d4ba5d5d1631b0f0a [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/storage/f2fs/f2fs.h"
namespace f2fs {
Reader::Reader(BcacheMapper *bc, size_t capacity) : bc_(bc) {
buffer_ = std::make_unique<StorageBuffer>(bc, capacity, kBlockSize, "ReadBuffer",
kDefaultAllocationUnit_);
}
zx::result<> Reader::ReadBlocks(zx::vmo &vmo, std::vector<block_t> &addrs) {
auto operation_or = buffer_->MakeReadOperations(addrs);
if (operation_or.is_error()) {
FX_LOGS(ERROR) << "failed to make ReadOperations. "
<< zx_status_get_string(operation_or.status_value());
return operation_or.take_error();
} else {
// If every addr is set to either kNullAddr or kNewAddr, the size of
// |*operations_or| is zero.
if (auto status = RunIO(*operation_or,
[&](const StorageOperations &operation, zx_status_t io_status) {
if (io_status == ZX_OK) {
auto &keys = operation.VmoKeys();
auto key = keys.begin();
uint32_t allocate_index = 0;
for (size_t i = 0; i < addrs.size(); ++i) {
if (addrs[i] != kNullAddr && addrs[i] != kNewAddr) {
vmo.write(buffer_->Data(key->GetKey() + allocate_index),
i * kBlockSize, kBlockSize);
if ((++allocate_index) == kDefaultAllocationUnit_) {
allocate_index = 0;
++key;
}
}
}
}
});
status != ZX_OK) {
return zx::error(status);
}
}
return zx::ok();
}
zx::result<> Reader::ReadBlocks(std::vector<LockedPage> &pages, std::vector<block_t> &addrs) {
auto operation_or = buffer_->MakeReadOperations(addrs);
if (operation_or.is_error()) {
FX_LOGS(ERROR) << "failed to make ReadOperations. "
<< zx_status_get_string(operation_or.status_value());
return operation_or.take_error();
} else {
// If every addr is set to either kNullAddr or kNewAddr, the size of
// |*operations_or| is zero.
if (auto status = RunIO(*operation_or,
[&](const StorageOperations &operation, zx_status_t io_status) {
if (io_status == ZX_OK) {
auto &keys = operation.VmoKeys();
auto key = keys.begin();
uint32_t allocate_index = 0;
for (size_t i = 0; i < addrs.size(); ++i) {
if (addrs[i] == kNullAddr || pages[i]->IsUptodate()) {
continue;
}
if (addrs[i] == kNewAddr) {
pages[i].Zero();
} else {
pages[i]->Write(buffer_->Data(key->GetKey() + allocate_index));
if ((++allocate_index) == kDefaultAllocationUnit_) {
allocate_index = 0;
++key;
}
}
pages[i]->SetUptodate();
}
}
});
status != ZX_OK) {
return zx::error(status);
}
}
return zx::ok();
}
zx_status_t Reader::RunIO(StorageOperations &operation, OperationCallback callback) {
zx_status_t ret = ZX_OK;
if (!operation.IsEmpty()) {
ret = bc_->RunRequests(operation.TakeOperations());
}
return operation.Completion(ret, std::move(callback));
}
} // namespace f2fs
// namespace f2fs