1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #pragma once
6 
7 #include <inttypes.h>
8 #include <memory>
9 
10 #include <fbl/macros.h>
11 #include <lib/ftl/ndm-driver.h>
12 #include <zircon/types.h>
13 
14 struct XfsVol;
15 
16 namespace ftl {
17 
18 // Interface for an upper-layer (block device) view of an FTL.
19 class FtlInstance {
20   public:
~FtlInstance()21     virtual ~FtlInstance() {}
22 
23     // Notified when an FTL volume is created. A block device can be created
24     // with up to num_pages blocks of page_size bytes each. The implementation
25     // should return true to acknowledge the success of the operation.
26     virtual bool OnVolumeAdded(uint32_t page_size, uint32_t num_pages) = 0;
27 };
28 
29 // Exposes the upper layer (block device) interface of the FTL.
30 class Volume {
31   public:
32     // Basic stats about the state of the device.
33     struct Stats {
34         size_t ram_used;
35         uint32_t wear_count;
36         int garbage_level;  // Percentage of free space that can be garbage-collected.
37     };
38 
Volume()39     Volume() {}
~Volume()40     virtual ~Volume() {}
41 
42     // Performs the object initialization. Returns an error string, or nullptr
43     // on success. Will synchronously call FtlInstance::OnVolumeAdded on success.
44     virtual const char* Init(std::unique_ptr<NdmDriver> driver) = 0;
45 
46     // Removes the volume and re-attaches to it. This is roughly equivalent to
47     // what a shutdown / restart would to in the real world (this functionality
48     // is basically intended for testing). Returns an error string, or nullptr
49     // on success. Will synchronously call FtlInstance::OnVolumeAdded on success.
50     virtual const char* ReAttach() = 0;
51 
52     // Synchronously Read or Write num_pages starting at first_page.
53     virtual zx_status_t Read(uint32_t first_page, int num_pages, void* buffer) = 0;
54     virtual zx_status_t Write(uint32_t first_page, int num_pages, const void* buffer) = 0;
55 
56     // Issues a command to format the FTL (aka, delete all data).
57     virtual zx_status_t Format() = 0;
58 
59     // Marks the volume as in use (Mount) or not (Unmount).
60     virtual zx_status_t Mount() = 0;
61     virtual zx_status_t Unmount() = 0;
62 
63     // Flushes all data to the device.
64     virtual zx_status_t Flush() = 0;
65 
66     // Marks num_pages starting from first_page as not-needed.
67     virtual zx_status_t Trim(uint32_t first_page, uint32_t num_pages) = 0;
68 
69     // Goes through one cycle of synchronous garbage collection. Returns ZX_OK
70     // on success and ZX_ERR_STOP where there is no more work to do.
71     virtual zx_status_t GarbageCollect() = 0;
72 
73     // Returns basic stats about the device.
74     virtual zx_status_t GetStats(Stats* stats) = 0;
75 };
76 
77 // Implementation of the Volume interface.
78 class VolumeImpl : public Volume {
79   public:
VolumeImpl(FtlInstance * owner)80     VolumeImpl(FtlInstance* owner) : owner_(owner) {}
~VolumeImpl()81     ~VolumeImpl() final {}
82 
83     // Volume interface.
84     const char* Init(std::unique_ptr<NdmDriver> driver) final;
85     const char* ReAttach() final;
86     zx_status_t Read(uint32_t first_page, int num_pages, void* buffer) final;
87     zx_status_t Write(uint32_t first_page, int num_pages, const void* buffer) final;
88     zx_status_t Format() final;
89     zx_status_t Mount() final;
90     zx_status_t Unmount() final;
91     zx_status_t Flush() final;
92     zx_status_t Trim(uint32_t first_page, uint32_t num_pages) final;
93     zx_status_t GarbageCollect() final;
94     zx_status_t GetStats(Stats* stats) final;
95 
96     // Internal notification of added volumes. This is forwarded to
97     // FtlInstance::OnVolumeAdded.
98     bool OnVolumeAdded(const XfsVol* ftl);
99 
100     DISALLOW_COPY_ASSIGN_AND_MOVE(VolumeImpl);
101 
102   private:
103     // Returns true if the volume was created successfully.
104     bool Created() const;
105 
106     // Creates the underlying NDM volume and mounts it. If successful, |owner_|
107     // will be notified about the new volume inside this call.
108     const char* Attach();
109 
110     // Members that are initialized when the volume is created (OnVolumeAdded):
111     void* vol_ = nullptr;                // FTL volume handle for callbacks.
112     const char* name_ = nullptr;         // Volume name from driver.
113     int (*report_)(void* vol, uint32_t msg, ...) = nullptr;
114     int (*write_pages_)(const void* buffer, uint32_t first_page, int count, void* vol) = nullptr;
115     int (*read_pages_)(void* buffer, uint32_t first_page, int count, void* vol) = nullptr;
116 
117     FtlInstance* owner_;
118     std::unique_ptr<NdmDriver> driver_;
119 };
120 
121 }  // namespace ftl
122