blob: cef6275386a2c3a79c0f8325bfd9bf1e9f2adf19 [file] [log] [blame]
// 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 "zstd-seekable-blob-collection.h"
#include <lib/zx/vmo.h>
#include <zircon/device/block.h>
#include <zircon/errors.h>
#include <zircon/status.h>
#include <zircon/types.h>
#include <blobfs/format.h>
#include <blobfs/node-finder.h>
#include <fs/trace.h>
#include <storage/buffer/owned_vmoid.h>
#include <storage/buffer/vmoid_registry.h>
#include "allocator/allocator.h"
#include "zstd-compressed-block-collection.h"
#include "zstd-seekable-blob.h"
namespace blobfs {
zx_status_t ZSTDSeekableBlobCollection::Create(storage::VmoidRegistry* vmoid_registry,
SpaceManager* space_manager,
fs::LegacyTransactionHandler* txn_handler,
NodeFinder* node_finder,
std::unique_ptr<ZSTDSeekableBlobCollection>* out) {
// |space_manager|, |txn_handler|, |node_finder| passed through on |Read()|.
std::unique_ptr<ZSTDSeekableBlobCollection> cbc(
new ZSTDSeekableBlobCollection(vmoid_registry, space_manager, txn_handler, node_finder));
// Initialize shared transfer buffer.
zx_status_t status = zx::vmo::create(kCompressedTransferBufferBytes, 0, &cbc->transfer_vmo_);
if (status != ZX_OK) {
FS_TRACE_ERROR("[blobfs][compressed] Failed to initialize transfer VMO: %s\n",
zx_status_get_string(status));
return status;
}
// Map shared transfer buffer.
fzl::VmoMapper mapper;
status = cbc->mapped_vmo_.Map(cbc->transfer_vmo_, 0, kCompressedTransferBufferBytes,
ZX_VM_PERM_READ | ZX_VM_PERM_WRITE);
if (status != ZX_OK) {
FS_TRACE_ERROR("[blobfs][compressed] Failed to map transfer VMO: %s\n",
zx_status_get_string(status));
return status;
}
// Attach shared transfer buffer to block device.
status = cbc->vmoid_.AttachVmo(cbc->transfer_vmo_);
if (status != ZX_OK) {
FS_TRACE_ERROR("[blobfs][compressed] Failed to register transfer VMO: %s\n",
zx_status_get_string(status));
return status;
}
*out = std::move(cbc);
return ZX_OK;
}
ZSTDSeekableBlobCollection::ZSTDSeekableBlobCollection(storage::VmoidRegistry* vmoid_registry,
SpaceManager* space_manager,
fs::LegacyTransactionHandler* txn_handler,
NodeFinder* node_finder)
: space_manager_(space_manager),
txn_handler_(txn_handler),
node_finder_(node_finder),
vmoid_(vmoid_registry) {}
zx_status_t ZSTDSeekableBlobCollection::Read(uint32_t node_index, uint8_t* buf,
uint64_t data_byte_offset, uint64_t num_bytes) {
InodePtr node = node_finder_->GetNode(node_index);
if (!node) {
FS_TRACE_ERROR("[blobfs][compressed] Invalid node index: %u\n", node_index);
return ZX_ERR_INVALID_ARGS;
}
// Currently, only ZSTD seekable is supported.
if ((node->header.flags & kBlobFlagZSTDSeekableCompressed) == 0) {
FS_TRACE_ERROR("[blobfs][compressed] Blob is not zstd-seekable compressed\n");
return ZX_ERR_NOT_SUPPORTED;
}
// Create -> Read -> Destroy appropriate
// RandomAccessCompressedBlob(ZSTDCompressedBlockCollectionImpl) composition.
uint32_t num_merkle_blocks = ComputeNumMerkleTreeBlocks(*node);
auto blocks = std::make_unique<ZSTDCompressedBlockCollectionImpl>(
&vmoid_, kCompressedTransferBufferBlocks, space_manager_, txn_handler_, node_finder_,
node_index, num_merkle_blocks);
std::unique_ptr<ZSTDSeekableBlob> blob;
zx_status_t status = ZSTDSeekableBlob::Create(&mapped_vmo_, std::move(blocks), &blob);
if (status != ZX_OK) {
FS_TRACE_ERROR("[blobfs][compressed] Failed to construct ZSTDSeekableBlob: %s\n",
zx_status_get_string(status));
return status;
}
status = blob->Read(buf, data_byte_offset, num_bytes);
if (status != ZX_OK) {
FS_TRACE_ERROR(
"[blobfs][compressed] Failed to Read from blob: node_index=%u, data_byte_offset=%lu, "
"num_bytes=%lu: %s\n",
node_index, data_byte_offset, num_bytes, zx_status_get_string(status));
return status;
}
return ZX_OK;
}
} // namespace blobfs