]> git.proxmox.com Git - ceph.git/blob - ceph/src/os/bluestore/bluefs_types.h
b53000188ae77e57ffd8a9ca370a65ca1620ea7c
[ceph.git] / ceph / src / os / bluestore / bluefs_types.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 #ifndef CEPH_OS_BLUESTORE_BLUEFS_TYPES_H
4 #define CEPH_OS_BLUESTORE_BLUEFS_TYPES_H
5
6 #include <optional>
7
8 #include "bluestore_types.h"
9 #include "include/utime.h"
10 #include "include/encoding.h"
11 #include "include/denc.h"
12
13 class bluefs_extent_t {
14 public:
15 uint64_t offset = 0;
16 uint32_t length = 0;
17 uint8_t bdev;
18
19 bluefs_extent_t(uint8_t b = 0, uint64_t o = 0, uint32_t l = 0)
20 : offset(o), length(l), bdev(b) {}
21
22 uint64_t end() const { return offset + length; }
23 DENC(bluefs_extent_t, v, p) {
24 DENC_START(1, 1, p);
25 denc_lba(v.offset, p);
26 denc_varint_lowz(v.length, p);
27 denc(v.bdev, p);
28 DENC_FINISH(p);
29 }
30
31 void dump(ceph::Formatter *f) const;
32 static void generate_test_instances(std::list<bluefs_extent_t*>&);
33 };
34 WRITE_CLASS_DENC(bluefs_extent_t)
35
36 std::ostream& operator<<(std::ostream& out, const bluefs_extent_t& e);
37
38 struct bluefs_fnode_delta_t {
39 uint64_t ino;
40 uint64_t size;
41 utime_t mtime;
42 uint64_t offset; // Contains offset in file of extents.
43 // Equal to 'allocated' when created.
44 // Used for consistency checking.
45 mempool::bluefs::vector<bluefs_extent_t> extents;
46
47 DENC(bluefs_fnode_delta_t, v, p) {
48 DENC_START(1, 1, p);
49 denc_varint(v.ino, p);
50 denc_varint(v.size, p);
51 denc(v.mtime, p);
52 denc(v.offset, p);
53 denc(v.extents, p);
54 DENC_FINISH(p);
55 }
56 };
57 WRITE_CLASS_DENC(bluefs_fnode_delta_t)
58
59 std::ostream& operator<<(std::ostream& out, const bluefs_fnode_delta_t& delta);
60
61 struct bluefs_fnode_t {
62 uint64_t ino;
63 uint64_t size;
64 utime_t mtime;
65 uint8_t __unused__; // was prefer_bdev
66 mempool::bluefs::vector<bluefs_extent_t> extents;
67
68 // precalculated logical offsets for extents vector entries
69 // allows fast lookup for extent index by the offset value via upper_bound()
70 mempool::bluefs::vector<uint64_t> extents_index;
71
72 uint64_t allocated;
73 uint64_t allocated_commited;
74
75 bluefs_fnode_t() : ino(0), size(0), __unused__(0), allocated(0), allocated_commited(0) {}
76
77 uint64_t get_allocated() const {
78 return allocated;
79 }
80
81 void recalc_allocated() {
82 allocated = 0;
83 extents_index.reserve(extents.size());
84 for (auto& p : extents) {
85 extents_index.emplace_back(allocated);
86 allocated += p.length;
87 }
88 allocated_commited = allocated;
89 }
90
91 DENC_HELPERS
92 void bound_encode(size_t& p) const {
93 _denc_friend(*this, p);
94 }
95 void encode(ceph::buffer::list::contiguous_appender& p) const {
96 DENC_DUMP_PRE(bluefs_fnode_t);
97 _denc_friend(*this, p);
98 }
99 void decode(ceph::buffer::ptr::const_iterator& p) {
100 _denc_friend(*this, p);
101 recalc_allocated();
102 }
103 template<typename T, typename P>
104 friend std::enable_if_t<std::is_same_v<bluefs_fnode_t, std::remove_const_t<T>>>
105 _denc_friend(T& v, P& p) {
106 DENC_START(1, 1, p);
107 denc_varint(v.ino, p);
108 denc_varint(v.size, p);
109 denc(v.mtime, p);
110 denc(v.__unused__, p);
111 denc(v.extents, p);
112 DENC_FINISH(p);
113 }
114
115 void reset_delta() {
116 allocated_commited = allocated;
117 }
118 void claim_extents(mempool::bluefs::vector<bluefs_extent_t>& extents) {
119 for (const auto& p : extents) {
120 append_extent(p);
121 }
122 extents.clear();
123 }
124 void append_extent(const bluefs_extent_t& ext) {
125 if (!extents.empty() &&
126 extents.back().end() == ext.offset &&
127 extents.back().bdev == ext.bdev &&
128 (uint64_t)extents.back().length + (uint64_t)ext.length < 0xffffffff) {
129 extents.back().length += ext.length;
130 } else {
131 extents_index.emplace_back(allocated);
132 extents.push_back(ext);
133 }
134 allocated += ext.length;
135 }
136
137 void pop_front_extent() {
138 auto it = extents.begin();
139 allocated -= it->length;
140 extents_index.erase(extents_index.begin());
141 for (auto& i: extents_index) {
142 i -= it->length;
143 }
144 extents.erase(it);
145 }
146
147 void swap_extents(bluefs_fnode_t& other) {
148 other.extents.swap(extents);
149 other.extents_index.swap(extents_index);
150 std::swap(allocated, other.allocated);
151 std::swap(allocated_commited, other.allocated_commited);
152 }
153 void clear_extents() {
154 extents_index.clear();
155 extents.clear();
156 allocated = 0;
157 allocated_commited = 0;
158 }
159
160 mempool::bluefs::vector<bluefs_extent_t>::iterator seek(
161 uint64_t off, uint64_t *x_off);
162 bluefs_fnode_delta_t* make_delta(bluefs_fnode_delta_t* delta);
163
164 void dump(ceph::Formatter *f) const;
165 static void generate_test_instances(std::list<bluefs_fnode_t*>& ls);
166
167 };
168 WRITE_CLASS_DENC(bluefs_fnode_t)
169
170 std::ostream& operator<<(std::ostream& out, const bluefs_fnode_t& file);
171
172 struct bluefs_layout_t {
173 unsigned shared_bdev = 0; ///< which bluefs bdev we are sharing
174 bool dedicated_db = false; ///< whether block.db is present
175 bool dedicated_wal = false; ///< whether block.wal is present
176
177 bool single_shared_device() const {
178 return !dedicated_db && !dedicated_wal;
179 }
180
181 bool operator==(const bluefs_layout_t& other) const {
182 return shared_bdev == other.shared_bdev &&
183 dedicated_db == other.dedicated_db &&
184 dedicated_wal == other.dedicated_wal;
185 }
186
187 void encode(ceph::buffer::list& bl) const;
188 void decode(ceph::buffer::list::const_iterator& p);
189 void dump(ceph::Formatter *f) const;
190 };
191 WRITE_CLASS_ENCODER(bluefs_layout_t)
192
193 struct bluefs_super_t {
194 uuid_d uuid; ///< unique to this bluefs instance
195 uuid_d osd_uuid; ///< matches the osd that owns us
196 uint64_t version;
197 uint32_t block_size;
198
199 bluefs_fnode_t log_fnode;
200
201 std::optional<bluefs_layout_t> memorized_layout;
202
203 bluefs_super_t()
204 : version(0),
205 block_size(4096) { }
206
207 uint64_t block_mask() const {
208 return ~((uint64_t)block_size - 1);
209 }
210
211 void encode(ceph::buffer::list& bl) const;
212 void decode(ceph::buffer::list::const_iterator& p);
213 void dump(ceph::Formatter *f) const;
214 static void generate_test_instances(std::list<bluefs_super_t*>& ls);
215 };
216 WRITE_CLASS_ENCODER(bluefs_super_t)
217
218 std::ostream& operator<<(std::ostream&, const bluefs_super_t& s);
219
220
221 struct bluefs_transaction_t {
222 typedef enum {
223 OP_NONE = 0,
224 OP_INIT, ///< initial (empty) file system marker
225 OP_ALLOC_ADD, ///< OBSOLETE: add extent to available block storage (extent)
226 OP_ALLOC_RM, ///< OBSOLETE: remove extent from available block storage (extent)
227 OP_DIR_LINK, ///< (re)set a dir entry (dirname, filename, ino)
228 OP_DIR_UNLINK, ///< remove a dir entry (dirname, filename)
229 OP_DIR_CREATE, ///< create a dir (dirname)
230 OP_DIR_REMOVE, ///< remove a dir (dirname)
231 OP_FILE_UPDATE, ///< set/update file metadata (file)
232 OP_FILE_REMOVE, ///< remove file (ino)
233 OP_JUMP, ///< jump the seq # and offset
234 OP_JUMP_SEQ, ///< jump the seq #
235 OP_FILE_UPDATE_INC, ///< incremental update file metadata (file)
236 } op_t;
237
238 uuid_d uuid; ///< fs uuid
239 uint64_t seq; ///< sequence number
240 ceph::buffer::list op_bl; ///< encoded transaction ops
241
242 bluefs_transaction_t() : seq(0) {}
243
244 void clear() {
245 *this = bluefs_transaction_t();
246 }
247 bool empty() const {
248 return op_bl.length() == 0;
249 }
250
251 void op_init() {
252 using ceph::encode;
253 encode((__u8)OP_INIT, op_bl);
254 }
255 void op_dir_create(std::string_view dir) {
256 using ceph::encode;
257 encode((__u8)OP_DIR_CREATE, op_bl);
258 encode(dir, op_bl);
259 }
260 void op_dir_remove(std::string_view dir) {
261 using ceph::encode;
262 encode((__u8)OP_DIR_REMOVE, op_bl);
263 encode(dir, op_bl);
264 }
265 void op_dir_link(std::string_view dir, std::string_view file, uint64_t ino) {
266 using ceph::encode;
267 encode((__u8)OP_DIR_LINK, op_bl);
268 encode(dir, op_bl);
269 encode(file, op_bl);
270 encode(ino, op_bl);
271 }
272 void op_dir_unlink(std::string_view dir, std::string_view file) {
273 using ceph::encode;
274 encode((__u8)OP_DIR_UNLINK, op_bl);
275 encode(dir, op_bl);
276 encode(file, op_bl);
277 }
278 void op_file_update(bluefs_fnode_t& file) {
279 using ceph::encode;
280 encode((__u8)OP_FILE_UPDATE, op_bl);
281 encode(file, op_bl);
282 file.reset_delta();
283 }
284 /* streams update to bufferlist and clears update state */
285 void op_file_update_inc(bluefs_fnode_t& file) {
286 using ceph::encode;
287 bluefs_fnode_delta_t delta;
288 file.make_delta(&delta); //also resets delta to zero
289 encode((__u8)OP_FILE_UPDATE_INC, op_bl);
290 encode(delta, op_bl);
291 }
292 void op_file_remove(uint64_t ino) {
293 using ceph::encode;
294 encode((__u8)OP_FILE_REMOVE, op_bl);
295 encode(ino, op_bl);
296 }
297 void op_jump(uint64_t next_seq, uint64_t offset) {
298 using ceph::encode;
299 encode((__u8)OP_JUMP, op_bl);
300 encode(next_seq, op_bl);
301 encode(offset, op_bl);
302 }
303 void op_jump_seq(uint64_t next_seq) {
304 using ceph::encode;
305 encode((__u8)OP_JUMP_SEQ, op_bl);
306 encode(next_seq, op_bl);
307 }
308 void claim_ops(bluefs_transaction_t& from) {
309 op_bl.claim_append(from.op_bl);
310 }
311
312 void encode(ceph::buffer::list& bl) const;
313 void decode(ceph::buffer::list::const_iterator& p);
314 void dump(ceph::Formatter *f) const;
315 static void generate_test_instances(std::list<bluefs_transaction_t*>& ls);
316 };
317 WRITE_CLASS_ENCODER(bluefs_transaction_t)
318
319 std::ostream& operator<<(std::ostream& out, const bluefs_transaction_t& t);
320 #endif