blob: 486a01b29ee29da6d3abab286a8a937e815d997e [file] [log] [blame] [edit]
// Copyright 2020 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 "fs_block_client.h"
#include "src/storage/blobfs/format.h"
using block_client::BlockDevice;
zx_status_t FsBlockClient::Create(std::unique_ptr<BlockDevice> device,
std::unique_ptr<FsBlockClient>* out) {
fuchsia_hardware_block_BlockInfo block_info;
zx_status_t status = device->BlockGetInfo(&block_info);
if (status != ZX_OK) {
return status;
}
zx::vmo vmo;
status = zx::vmo::create(blobfs::kBlobfsBlockSize, 0, &vmo);
if (status != ZX_OK) {
return status;
}
storage::Vmoid vmoid;
status = device->BlockAttachVmo(vmo, &vmoid);
if (status != ZX_OK) {
return status;
}
out->reset(new FsBlockClient(std::move(device), block_info, std::move(vmo), std::move(vmoid)));
return ZX_OK;
}
uint64_t FsBlockClient::BlockCount() const {
return block_info_.block_count / device_blocks_per_blobfs_block();
}
zx_status_t FsBlockClient::ReadBlock(uint64_t block, void* data) {
block_fifo_request_t request = {};
request.opcode = BLOCKIO_READ;
request.vmoid = vmoid_.get();
request.length = static_cast<uint32_t>(fs_block_to_device_block(1));
request.vmo_offset = 0;
request.dev_offset = fs_block_to_device_block(block);
zx_status_t status = device_->FifoTransaction(&request, 1);
if (status != ZX_OK) {
return status;
}
return vmo_.read(data, 0, blobfs::kBlobfsBlockSize);
}
zx_status_t FsBlockClient::WriteBlock(uint64_t block, const void* data) {
zx_status_t status = vmo_.write(data, 0, blobfs::kBlobfsBlockSize);
if (status != ZX_OK) {
return status;
}
block_fifo_request_t request = {};
request.opcode = BLOCKIO_WRITE;
request.vmoid = vmoid_.get();
request.length = static_cast<uint32_t>(fs_block_to_device_block(1));
request.vmo_offset = 0;
request.dev_offset = fs_block_to_device_block(block);
return device_->FifoTransaction(&request, 1);
}
FsBlockClient::FsBlockClient(std::unique_ptr<BlockDevice> device,
fuchsia_hardware_block_BlockInfo block_info, zx::vmo vmo,
storage::Vmoid vmoid)
: device_(std::move(device)),
block_info_(block_info),
vmo_(std::move(vmo)),
vmoid_(std::move(vmoid)) {}
FsBlockClient::~FsBlockClient() {
zx_status_t status = device_->BlockDetachVmo(std::move(vmoid_));
ZX_DEBUG_ASSERT(status == ZX_OK);
}
uint64_t FsBlockClient::device_blocks_per_blobfs_block() const {
return blobfs::kBlobfsBlockSize / block_info_.block_size;
}
uint64_t FsBlockClient::fs_block_to_device_block(uint64_t block) const {
return block * device_blocks_per_blobfs_block();
}