blob: 085a05de59dd460726cc7406b5e2d883c4186687 [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
#include <inttypes.h>
#include <memory>
#include <fbl/macros.h>
#include <lib/ftl/ndm-driver.h>
#include <zircon/types.h>
struct XfsVol;
namespace ftl {
// Interface for an upper-layer (block device) view of an FTL.
class FtlInstance {
public:
virtual ~FtlInstance() {}
// Notified when an FTL volume is created. A block device can be created
// with up to num_pages blocks of page_size bytes each. The implementation
// should return true to acknowledge the success of the operation.
virtual bool OnVolumeAdded(uint32_t page_size, uint32_t num_pages) = 0;
};
// Exposes the upper layer (block device) interface of the FTL.
class Volume {
public:
// Basic stats about the state of the device.
struct Stats {
size_t ram_used;
uint32_t wear_count;
int garbage_level; // Percentage of free space that can be garbage-collected.
};
Volume() {}
virtual ~Volume() {}
// Performs the object initialization. Returns an error string, or nullptr
// on success. Will synchronously call FtlInstance::OnVolumeAdded on success.
// The |driver| must be fully initialized when passed to this method.
virtual const char* Init(std::unique_ptr<NdmDriver> driver) = 0;
// Removes the volume and re-attaches to it. This is roughly equivalent to
// what a shutdown / restart would to in the real world (this functionality
// is basically intended for testing). Returns an error string, or nullptr
// on success. Will synchronously call FtlInstance::OnVolumeAdded on success.
virtual const char* ReAttach() = 0;
// Synchronously Read or Write num_pages starting at first_page.
virtual zx_status_t Read(uint32_t first_page, int num_pages, void* buffer) = 0;
virtual zx_status_t Write(uint32_t first_page, int num_pages, const void* buffer) = 0;
// Issues a command to format the FTL (aka, delete all data).
virtual zx_status_t Format() = 0;
// Marks the volume as in use (Mount) or not (Unmount).
virtual zx_status_t Mount() = 0;
virtual zx_status_t Unmount() = 0;
// Flushes all data to the device.
virtual zx_status_t Flush() = 0;
// Marks num_pages starting from first_page as not-needed.
virtual zx_status_t Trim(uint32_t first_page, uint32_t num_pages) = 0;
// Goes through one cycle of synchronous garbage collection. Returns ZX_OK
// on success and ZX_ERR_STOP where there is no more work to do.
virtual zx_status_t GarbageCollect() = 0;
// Returns basic stats about the device.
virtual zx_status_t GetStats(Stats* stats) = 0;
};
// Implementation of the Volume interface.
class VolumeImpl : public Volume {
public:
VolumeImpl(FtlInstance* owner) : owner_(owner) {}
~VolumeImpl() final {}
// Volume interface.
const char* Init(std::unique_ptr<NdmDriver> driver) final;
const char* ReAttach() final;
zx_status_t Read(uint32_t first_page, int num_pages, void* buffer) final;
zx_status_t Write(uint32_t first_page, int num_pages, const void* buffer) final;
zx_status_t Format() final;
zx_status_t Mount() final;
zx_status_t Unmount() final;
zx_status_t Flush() final;
zx_status_t Trim(uint32_t first_page, uint32_t num_pages) final;
zx_status_t GarbageCollect() final;
zx_status_t GetStats(Stats* stats) final;
// Internal notification of added volumes. This is forwarded to
// FtlInstance::OnVolumeAdded.
bool OnVolumeAdded(const XfsVol* ftl);
DISALLOW_COPY_ASSIGN_AND_MOVE(VolumeImpl);
private:
// Returns true if the volume was created successfully.
bool Created() const;
// Creates the underlying NDM volume and mounts it. If successful, |owner_|
// will be notified about the new volume inside this call.
const char* Attach();
// Members that are initialized when the volume is created (OnVolumeAdded):
void* vol_ = nullptr; // FTL volume handle for callbacks.
const char* name_ = nullptr; // Volume name from driver.
int (*report_)(void* vol, uint32_t msg, ...) = nullptr;
int (*write_pages_)(const void* buffer, uint32_t first_page, int count, void* vol) = nullptr;
int (*read_pages_)(void* buffer, uint32_t first_page, int count, void* vol) = nullptr;
FtlInstance* owner_;
std::unique_ptr<NdmDriver> driver_;
};
} // namespace ftl