blob: 7f4a3d309cb3f1f7faa97af8a5d8350a07bc7e97 [file] [log] [blame] [edit]
// Copyright 2024 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 "src/storage/lib/block_server/fake_server.h"
#include <span>
namespace block_server {
/// Implementation of Interface backed by a VMO.
class FakeServer::FakeInterface : public Interface {
public:
FakeInterface(const FakeServer& server, zx::vmo data, uint64_t block_size)
: server_(server), data_(std::move(data)), block_size_(block_size) {
uint64_t size;
ZX_ASSERT(data_.get_size(&size) == ZX_OK);
ZX_ASSERT(size % block_size_ == 0);
}
FakeInterface(const FakeServer& server, uint64_t blocks, uint64_t block_size)
: server_(server), block_size_(block_size) {
ZX_ASSERT(zx::vmo::create(blocks * block_size, 0, &data_) == ZX_OK);
}
FakeInterface(const FakeInterface&) = delete;
FakeInterface& operator=(const FakeInterface&) = delete;
void StartThread(Thread thread) override {
std::thread([thread = std::move(thread)]() mutable { thread.Run(); }).detach();
}
void OnNewSession(Session session) override {
std::thread([session = std::move(session)]() mutable { session.Run(); }).detach();
}
void OnRequests(std::span<Request> requests) override {
std::vector<uint8_t> buf;
size_t len;
for (const Request& request : requests) {
switch (request.operation.tag) {
case Operation::Tag::Read:
len = request.operation.read.block_count * block_size_;
buf.reserve(len);
ZX_ASSERT(data_.read(buf.data(), request.operation.read.device_block_offset * block_size_,
len) == ZX_OK);
ZX_ASSERT(request.vmo->write(buf.data(), request.operation.read.vmo_offset, len) ==
ZX_OK);
break;
case Operation::Tag::Write:
len = request.operation.write.block_count * block_size_;
buf.reserve(len);
ZX_ASSERT(request.vmo->read(buf.data(), request.operation.write.vmo_offset, len) ==
ZX_OK);
ZX_ASSERT(data_.write(buf.data(),
request.operation.write.device_block_offset * block_size_,
len) == ZX_OK);
break;
case Operation::Tag::Flush:
case Operation::Tag::Trim:
case Operation::Tag::CloseVmo:
break;
}
const BlockServer* server = server_.server_.get();
if (server) {
server->SendReply(request.request_id, zx::ok());
}
}
}
const zx::vmo& vmo() const { return data_; }
private:
const FakeServer& server_;
zx::vmo data_;
uint64_t block_size_;
};
FakeServer::FakeServer(const PartitionInfo& info, zx::vmo data) {
uint64_t size;
interface_ = data ? std::make_unique<FakeInterface>(*this, std::move(data),
static_cast<uint64_t>(info.block_size))
: std::make_unique<FakeInterface>(*this, info.block_count,
static_cast<uint64_t>(info.block_size));
ZX_ASSERT(interface_->vmo().get_size(&size) == ZX_OK);
server_ = std::make_unique<BlockServer>(info, interface_.get());
ZX_ASSERT(info.block_size * info.block_count == size);
}
FakeServer::~FakeServer() = default;
FakeServer::FakeServer(FakeServer&&) = default;
FakeServer& FakeServer::operator=(FakeServer&&) = default;
} // namespace block_server