blob: 41818c5eebd720b454187d3fe3e1bdb02508f58c [file] [log] [blame]
// Copyright 2018 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.
#pragma once
#ifndef __Fuchsia__
#error Fuchsia-only Header
#endif
#include <utility>
#include <blobfs/transaction-manager.h>
#include <blobfs/write-txn.h>
#include <lib/fzl/owned-vmo-mapper.h>
namespace blobfs {
// In-memory data buffer.
// This class is thread-compatible.
class Buffer {
public:
DISALLOW_COPY_ASSIGN_AND_MOVE(Buffer);
~Buffer();
// Initializes the buffer VMO with |blocks| blocks of size kBlobfsBlockSize.
static zx_status_t Create(TransactionManager* transaction_manager, const size_t blocks,
const char* label, std::unique_ptr<Buffer>* out);
// Adds a transaction to |txn| which reads all data into buffer
// starting from |disk_start| on disk.
void Load(fs::ReadTxn* txn, size_t disk_start) {
txn->Enqueue(vmoid_, 0, disk_start, capacity_);
}
// Returns true if there is space available for |blocks| blocks within the buffer.
bool IsSpaceAvailable(size_t blocks) const;
// Copies a write transaction to the buffer.
// Also updates the in-memory offsets of the WriteTxn's requests so they point
// to the correct offsets in the in-memory buffer instead of their original VMOs.
//
// |IsSpaceAvailable| should be called before invoking this function to
// safely guarantee that space exists within the buffer.
void CopyTransaction(WriteTxn* txn);
// Adds a transaction to |work| with buffer offset |start| and length |length|,
// starting at block |disk_start| on disk.
void AddTransaction(size_t start, size_t disk_start, size_t length, WritebackWork* work);
// Returns true if |txn| belongs to this buffer, and if so verifies
// that it owns the next valid set of blocks within the buffer.
bool VerifyTransaction(WriteTxn* txn) const;
// Given a transaction |txn|, verifies that all requests belong to this buffer
// and then sets the transaction's buffer accordingly (if it is not already set).
void ValidateTransaction(WriteTxn* txn);
// Frees the first |blocks| blocks in the buffer.
void FreeSpace(size_t blocks);
// Frees all space within the buffer.
void FreeAllSpace() {
FreeSpace(length_);
}
size_t start() const { return start_; }
size_t length() const { return length_; }
size_t capacity() const { return capacity_; }
// Reserves the next index in the buffer.
size_t ReserveIndex() {
return (start_ + length_++) % capacity_;
}
// Returns data starting at block |index| in the buffer.
void* MutableData(size_t index) {
ZX_DEBUG_ASSERT(index < capacity_);
return reinterpret_cast<char*>(mapper_.start()) + (index * kBlobfsBlockSize);
}
private:
Buffer(TransactionManager* transaction_manager, fzl::OwnedVmoMapper mapper)
: transaction_manager_(transaction_manager), mapper_(std::move(mapper)), start_(0),
length_(0), capacity_(mapper_.size() / kBlobfsBlockSize) {}
TransactionManager* transaction_manager_;
fzl::OwnedVmoMapper mapper_;
vmoid_t vmoid_ = VMOID_INVALID;
// The units of all the following are "Blobfs blocks".
size_t start_ = 0;
size_t length_ = 0;
const size_t capacity_;
};
} // namespace blobfs