| // 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 |