blob: c732aeb40c824ee126c57b3faff04da15a8c0362 [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.
#ifndef SRC_STORAGE_BLOBFS_TRANSFER_BUFFER_H_
#define SRC_STORAGE_BLOBFS_TRANSFER_BUFFER_H_
#ifndef __Fuchsia__
#error Fuchsia-only Header
#endif
#include <lib/zx/status.h>
#include <lib/zx/vmo.h>
#include <memory>
#include <fbl/macros.h>
#include <storage/buffer/owned_vmoid.h>
#include "src/storage/blobfs/blobfs_metrics.h"
#include "src/storage/blobfs/iterator/block_iterator_provider.h"
#include "src/storage/blobfs/loader_info.h"
#include "src/storage/blobfs/node_finder.h"
#include "src/storage/blobfs/transaction_manager.h"
namespace blobfs {
// The size of the transfer buffer for reading from storage.
//
// The decision to use a single global transfer buffer is arbitrary; a pool of them could also be
// available in the future for more fine-grained access. Moreover, the blobfs pager uses a single
// thread at the moment, so a global buffer should be sufficient.
//
// 256 MB; but the size is arbitrary, since pages will become decommitted as they are moved to
// destination VMOS.
constexpr uint64_t kTransferBufferSize = 256 * (1ull << 20);
// The size of the scratch buffer used for decompression.
//
// The decision to use a single global transfer buffer is arbitrary; a pool of them could also be
// available in the future for more fine-grained access. Moreover, the blobfs pager uses a single
// thread at the moment, so a global buffer should be sufficient.
//
// 256 MB; but the size is arbitrary, since pages will become decommitted as they are moved to
// destination VMOS.
constexpr uint64_t kDecompressionBufferSize = 256 * (1ull << 20);
// Make sure blocks are page-aligned.
static_assert(kBlobfsBlockSize % PAGE_SIZE == 0);
// Make sure the pager transfer buffer is block-aligned.
static_assert(kTransferBufferSize % kBlobfsBlockSize == 0);
// Make sure the decompression scratch buffer is block-aligned.
static_assert(kDecompressionBufferSize % kBlobfsBlockSize == 0);
// Make sure the pager transfer buffer and decompression buffer are sized per the worst case
// compression ratio of 1.
static_assert(kTransferBufferSize >= kDecompressionBufferSize);
// TransferBuffer is an interface representing a transfer buffer which can be loaded with data from
// the underlying storage device.
//
// The VMO returned by |TransferBuffer::vmo()| is guaranteed to never be mapped by the instance,
// which makes the VMO suitable for use with |zx_pager_supply_pages|.
class TransferBuffer {
public:
virtual ~TransferBuffer() = default;
// Loads the buffer with data from the inode corresponding to |info.identifier|, at the byte range
// specified by [|offset|, |offset| + |length|).
// |offset| must be block aligned. |length| may be rounded up to a block-aligned offset.
[[nodiscard]] virtual zx::status<> Populate(uint64_t offset, uint64_t length,
const LoaderInfo& info) = 0;
// Accesses the underlying VMO.
// Must be preceded with a call to |TransferBuffer::Populate()|. The contents of the returned
// VMO are only defined up to |length| bytes (the value passed to the last call to
// |TransferBuffer::Populate()|).
virtual const zx::vmo& GetVmo() const = 0;
// Returns the size of the underlying VMO.
virtual size_t GetSize() const = 0;
};
// StorageBackedTransferBuffer is an instance of |TransferBuffer| which can be loaded with data from
// the underlying storage device.
class StorageBackedTransferBuffer : public TransferBuffer {
public:
DISALLOW_COPY_ASSIGN_AND_MOVE(StorageBackedTransferBuffer);
// Creates an instance of |StorageBackedTransferBuffer| with a VMO of size |size| bytes.
// |size| must be a multiple of the block size of the underlying storage device.
[[nodiscard]] static zx::status<std::unique_ptr<StorageBackedTransferBuffer>> Create(
size_t size, TransactionManager* txn_manager, BlockIteratorProvider* block_iter_provider,
BlobfsMetrics* metrics);
[[nodiscard]] zx::status<> Populate(uint64_t offset, uint64_t length,
const LoaderInfo& info) final;
const zx::vmo& GetVmo() const final { return vmo_; }
size_t GetSize() const final { return size_; }
private:
StorageBackedTransferBuffer(zx::vmo vmo, size_t size, storage::OwnedVmoid vmoid,
TransactionManager* txn_manager,
BlockIteratorProvider* block_iter_provider, BlobfsMetrics* metrics);
TransactionManager* txn_manager_ = nullptr;
BlockIteratorProvider* block_iter_provider_ = nullptr;
zx::vmo vmo_;
const size_t size_;
storage::OwnedVmoid vmoid_;
BlobfsMetrics* metrics_ = nullptr;
};
} // namespace blobfs
#endif // SRC_STORAGE_BLOBFS_TRANSFER_BUFFER_H_