]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #ifndef CEPH_LIBRBD_CACHE_PWL_LOG_ENTRY_H | |
5 | #define CEPH_LIBRBD_CACHE_PWL_LOG_ENTRY_H | |
6 | ||
7 | #include "common/ceph_mutex.h" | |
8 | #include "librbd/Utils.h" | |
9 | #include "librbd/cache/pwl/Types.h" | |
10 | #include <atomic> | |
11 | #include <memory> | |
12 | ||
13 | namespace librbd { | |
14 | namespace cache { | |
15 | class ImageWritebackInterface; | |
16 | namespace pwl { | |
17 | ||
18 | class SyncPointLogEntry; | |
19 | class GenericWriteLogEntry; | |
20 | class WriteLogEntry; | |
21 | ||
22 | typedef std::list<std::shared_ptr<GenericWriteLogEntry>> GenericWriteLogEntries; | |
23 | ||
24 | class GenericLogEntry { | |
25 | public: | |
26 | WriteLogCacheEntry ram_entry; | |
27 | WriteLogCacheEntry *cache_entry = nullptr; | |
a4b75251 | 28 | uint64_t log_entry_index = 0; |
f67539c2 | 29 | bool completed = false; |
20effc67 | 30 | BlockGuardCell* m_cell = nullptr; |
f67539c2 TL |
31 | GenericLogEntry(uint64_t image_offset_bytes = 0, uint64_t write_bytes = 0) |
32 | : ram_entry(image_offset_bytes, write_bytes) { | |
33 | }; | |
34 | virtual ~GenericLogEntry() { }; | |
35 | GenericLogEntry(const GenericLogEntry&) = delete; | |
36 | GenericLogEntry &operator=(const GenericLogEntry&) = delete; | |
37 | virtual bool can_writeback() const { | |
38 | return false; | |
39 | } | |
40 | virtual bool can_retire() const { | |
41 | return false; | |
42 | } | |
43 | virtual void set_flushed(bool flushed) { | |
44 | ceph_assert(false); | |
45 | } | |
46 | virtual unsigned int write_bytes() const { | |
47 | return 0; | |
48 | }; | |
49 | virtual unsigned int bytes_dirty() const { | |
50 | return 0; | |
51 | }; | |
52 | virtual std::shared_ptr<SyncPointLogEntry> get_sync_point_entry() { | |
53 | return nullptr; | |
54 | } | |
55 | virtual void writeback(librbd::cache::ImageWritebackInterface &image_writeback, | |
56 | Context *ctx) { | |
57 | ceph_assert(false); | |
58 | }; | |
59 | virtual void writeback_bl(librbd::cache::ImageWritebackInterface &image_writeback, | |
60 | Context *ctx, ceph::bufferlist &&bl) { | |
61 | ceph_assert(false); | |
62 | } | |
63 | virtual bool is_write_entry() const { | |
64 | return false; | |
65 | } | |
66 | virtual bool is_writesame_entry() const { | |
67 | return false; | |
68 | } | |
69 | virtual bool is_sync_point() const { | |
70 | return false; | |
71 | } | |
72 | virtual unsigned int get_aligned_data_size() const { | |
73 | return 0; | |
74 | } | |
75 | virtual void remove_cache_bl() {} | |
76 | virtual std::ostream& format(std::ostream &os) const; | |
77 | friend std::ostream &operator<<(std::ostream &os, | |
78 | const GenericLogEntry &entry); | |
79 | }; | |
80 | ||
81 | class SyncPointLogEntry : public GenericLogEntry { | |
82 | public: | |
83 | /* Writing entries using this sync gen number */ | |
84 | std::atomic<unsigned int> writes = {0}; | |
85 | /* Total bytes for all writing entries using this sync gen number */ | |
86 | std::atomic<uint64_t> bytes = {0}; | |
87 | /* Writing entries using this sync gen number that have completed */ | |
88 | std::atomic<unsigned int> writes_completed = {0}; | |
89 | /* Writing entries using this sync gen number that have completed flushing to the writeback interface */ | |
90 | std::atomic<unsigned int> writes_flushed = {0}; | |
91 | /* All writing entries using all prior sync gen numbers have been flushed */ | |
92 | std::atomic<bool> prior_sync_point_flushed = {true}; | |
93 | std::shared_ptr<SyncPointLogEntry> next_sync_point_entry = nullptr; | |
94 | SyncPointLogEntry(uint64_t sync_gen_number) { | |
95 | ram_entry.sync_gen_number = sync_gen_number; | |
96 | ram_entry.sync_point = 1; | |
97 | }; | |
98 | ~SyncPointLogEntry() override {}; | |
99 | SyncPointLogEntry(const SyncPointLogEntry&) = delete; | |
100 | SyncPointLogEntry &operator=(const SyncPointLogEntry&) = delete; | |
101 | bool can_retire() const override { | |
102 | return this->completed; | |
103 | } | |
104 | bool is_sync_point() const override { | |
105 | return true; | |
106 | } | |
107 | std::ostream& format(std::ostream &os) const; | |
108 | friend std::ostream &operator<<(std::ostream &os, | |
109 | const SyncPointLogEntry &entry); | |
110 | }; | |
111 | ||
112 | class GenericWriteLogEntry : public GenericLogEntry { | |
113 | public: | |
114 | uint32_t referring_map_entries = 0; | |
115 | std::shared_ptr<SyncPointLogEntry> sync_point_entry; | |
116 | GenericWriteLogEntry(std::shared_ptr<SyncPointLogEntry> sync_point_entry, | |
117 | uint64_t image_offset_bytes, uint64_t write_bytes) | |
118 | : GenericLogEntry(image_offset_bytes, write_bytes), sync_point_entry(sync_point_entry) { } | |
119 | GenericWriteLogEntry(uint64_t image_offset_bytes, uint64_t write_bytes) | |
120 | : GenericLogEntry(image_offset_bytes, write_bytes), sync_point_entry(nullptr) { } | |
121 | ~GenericWriteLogEntry() override {}; | |
122 | GenericWriteLogEntry(const GenericWriteLogEntry&) = delete; | |
123 | GenericWriteLogEntry &operator=(const GenericWriteLogEntry&) = delete; | |
124 | unsigned int write_bytes() const override { | |
125 | /* The valid bytes in this ops data buffer. Discard and WS override. */ | |
126 | return ram_entry.write_bytes; | |
127 | }; | |
128 | unsigned int bytes_dirty() const override { | |
129 | /* The bytes in the image this op makes dirty. Discard and WS override. */ | |
130 | return write_bytes(); | |
131 | }; | |
132 | BlockExtent block_extent() { | |
133 | return ram_entry.block_extent(); | |
134 | } | |
135 | uint32_t get_map_ref() { | |
136 | return(referring_map_entries); | |
137 | } | |
138 | void inc_map_ref() { referring_map_entries++; } | |
139 | void dec_map_ref() { referring_map_entries--; } | |
140 | bool can_writeback() const override; | |
141 | std::shared_ptr<SyncPointLogEntry> get_sync_point_entry() override { | |
142 | return sync_point_entry; | |
143 | } | |
144 | virtual void copy_cache_bl(bufferlist *out_bl) = 0; | |
145 | void set_flushed(bool flushed) override { | |
146 | m_flushed = flushed; | |
147 | } | |
148 | bool get_flushed() const { | |
149 | return m_flushed; | |
150 | } | |
151 | std::ostream &format(std::ostream &os) const; | |
152 | friend std::ostream &operator<<(std::ostream &os, | |
153 | const GenericWriteLogEntry &entry); | |
154 | ||
155 | private: | |
156 | bool m_flushed = false; /* or invalidated */ | |
157 | }; | |
158 | ||
159 | class WriteLogEntry : public GenericWriteLogEntry { | |
160 | protected: | |
161 | bool is_writesame = false; | |
162 | buffer::ptr cache_bp; | |
163 | buffer::list cache_bl; | |
164 | std::atomic<int> bl_refs = {0}; /* The refs held on cache_bp by cache_bl */ | |
165 | /* Used in WriteLogEntry::get_cache_bl() to syncronize between threads making entries readable */ | |
166 | mutable ceph::mutex m_entry_bl_lock; | |
167 | ||
168 | virtual void init_cache_bp() {} | |
169 | ||
170 | virtual void init_bl(buffer::ptr &bp, buffer::list &bl) {} | |
171 | public: | |
172 | uint8_t *cache_buffer = nullptr; | |
173 | WriteLogEntry(std::shared_ptr<SyncPointLogEntry> sync_point_entry, | |
174 | uint64_t image_offset_bytes, uint64_t write_bytes) | |
175 | : GenericWriteLogEntry(sync_point_entry, image_offset_bytes, write_bytes), | |
176 | m_entry_bl_lock(ceph::make_mutex(pwl::unique_lock_name( | |
177 | "librbd::cache::pwl::WriteLogEntry::m_entry_bl_lock", this))) | |
178 | { } | |
179 | WriteLogEntry(uint64_t image_offset_bytes, uint64_t write_bytes) | |
180 | : GenericWriteLogEntry(nullptr, image_offset_bytes, write_bytes), | |
181 | m_entry_bl_lock(ceph::make_mutex(pwl::unique_lock_name( | |
182 | "librbd::cache::pwl::WriteLogEntry::m_entry_bl_lock", this))) | |
183 | { } | |
184 | WriteLogEntry(std::shared_ptr<SyncPointLogEntry> sync_point_entry, | |
185 | uint64_t image_offset_bytes, uint64_t write_bytes, | |
186 | uint32_t data_length) | |
187 | : WriteLogEntry(sync_point_entry, image_offset_bytes, write_bytes) { | |
188 | ram_entry.writesame = 1; | |
189 | ram_entry.ws_datalen = data_length; | |
190 | is_writesame = true; | |
191 | }; | |
192 | WriteLogEntry(uint64_t image_offset_bytes, uint64_t write_bytes, | |
193 | uint32_t data_length) | |
194 | : WriteLogEntry(nullptr, image_offset_bytes, write_bytes) { | |
195 | ram_entry.writesame = 1; | |
196 | ram_entry.ws_datalen = data_length; | |
197 | is_writesame = true; | |
198 | }; | |
199 | ~WriteLogEntry() override {}; | |
200 | WriteLogEntry(const WriteLogEntry&) = delete; | |
201 | WriteLogEntry &operator=(const WriteLogEntry&) = delete; | |
202 | unsigned int write_bytes() const override { | |
203 | // The valid bytes in this ops data buffer. | |
204 | if(is_writesame) { | |
205 | return ram_entry.ws_datalen; | |
206 | } | |
207 | return ram_entry.write_bytes; | |
208 | }; | |
209 | unsigned int bytes_dirty() const override { | |
210 | // The bytes in the image this op makes dirty. | |
211 | return ram_entry.write_bytes; | |
212 | }; | |
213 | void init(bool has_data, | |
214 | uint64_t current_sync_gen, uint64_t last_op_sequence_num, bool persist_on_flush); | |
215 | virtual void init_cache_buffer(std::vector<WriteBufferAllocation>::iterator allocation) {} | |
216 | virtual void init_cache_bl(bufferlist &src_bl, uint64_t off, uint64_t len) {} | |
217 | /* Returns a ref to a bl containing bufferptrs to the entry cache buffer */ | |
218 | virtual buffer::list &get_cache_bl() = 0; | |
219 | ||
220 | BlockExtent block_extent(); | |
a4b75251 | 221 | virtual unsigned int reader_count() const = 0; |
f67539c2 | 222 | /* Constructs a new bl containing copies of cache_bp */ |
f67539c2 TL |
223 | bool can_retire() const override { |
224 | return (this->completed && this->get_flushed() && (0 == reader_count())); | |
225 | } | |
226 | bool is_write_entry() const override { | |
227 | return true; | |
228 | } | |
229 | bool is_writesame_entry() const override { | |
230 | return is_writesame; | |
231 | } | |
232 | std::ostream &format(std::ostream &os) const; | |
233 | friend std::ostream &operator<<(std::ostream &os, | |
234 | const WriteLogEntry &entry); | |
235 | }; | |
236 | ||
237 | class DiscardLogEntry : public GenericWriteLogEntry { | |
238 | public: | |
239 | DiscardLogEntry(std::shared_ptr<SyncPointLogEntry> sync_point_entry, | |
240 | uint64_t image_offset_bytes, uint64_t write_bytes, | |
241 | uint32_t discard_granularity_bytes) | |
242 | : GenericWriteLogEntry(sync_point_entry, image_offset_bytes, write_bytes), | |
243 | m_discard_granularity_bytes(discard_granularity_bytes) { | |
244 | ram_entry.discard = 1; | |
245 | }; | |
246 | DiscardLogEntry(uint64_t image_offset_bytes, uint64_t write_bytes) | |
247 | : GenericWriteLogEntry(nullptr, image_offset_bytes, write_bytes) { | |
248 | ram_entry.discard = 1; | |
249 | }; | |
250 | DiscardLogEntry(const DiscardLogEntry&) = delete; | |
251 | DiscardLogEntry &operator=(const DiscardLogEntry&) = delete; | |
252 | unsigned int write_bytes() const override { | |
253 | /* The valid bytes in this ops data buffer. */ | |
254 | return 0; | |
255 | }; | |
256 | unsigned int bytes_dirty() const override { | |
257 | /* The bytes in the image this op makes dirty. */ | |
258 | return ram_entry.write_bytes; | |
259 | }; | |
260 | bool can_retire() const override { | |
261 | return this->completed; | |
262 | } | |
263 | void copy_cache_bl(bufferlist *out_bl) override { | |
264 | ceph_assert(false); | |
265 | } | |
266 | void writeback(librbd::cache::ImageWritebackInterface &image_writeback, | |
267 | Context *ctx) override; | |
268 | void init(uint64_t current_sync_gen, bool persist_on_flush, uint64_t last_op_sequence_num); | |
269 | std::ostream &format(std::ostream &os) const; | |
270 | friend std::ostream &operator<<(std::ostream &os, | |
271 | const DiscardLogEntry &entry); | |
272 | private: | |
273 | uint32_t m_discard_granularity_bytes; | |
274 | }; | |
275 | ||
276 | } // namespace pwl | |
277 | } // namespace cache | |
278 | } // namespace librbd | |
279 | ||
280 | #endif // CEPH_LIBRBD_CACHE_PWL_LOG_ENTRY_H |