Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2017 Intel Corporation.
3 : : * All rights reserved.
4 : : * Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
5 : : */
6 : :
7 : : #ifndef SPDK_BLOBSTORE_H
8 : : #define SPDK_BLOBSTORE_H
9 : :
10 : : #include "spdk/assert.h"
11 : : #include "spdk/blob.h"
12 : : #include "spdk/queue.h"
13 : : #include "spdk/util.h"
14 : : #include "spdk/tree.h"
15 : : #include "spdk/thread.h"
16 : :
17 : : #include "request.h"
18 : :
19 : : /* In Memory Data Structures
20 : : *
21 : : * The following data structures exist only in memory.
22 : : */
23 : :
24 : : #define SPDK_BLOB_OPTS_CLUSTER_SZ (1024 * 1024)
25 : : #define SPDK_BLOB_OPTS_NUM_MD_PAGES UINT32_MAX
26 : : #define SPDK_BLOB_OPTS_MAX_MD_OPS 32
27 : : #define SPDK_BLOB_OPTS_DEFAULT_CHANNEL_OPS 512
28 : : #define SPDK_BLOB_BLOBID_HIGH_BIT (1ULL << 32)
29 : :
30 : : struct spdk_xattr {
31 : : uint32_t index;
32 : : uint16_t value_len;
33 : : char *name;
34 : : void *value;
35 : : TAILQ_ENTRY(spdk_xattr) link;
36 : : };
37 : :
38 : : /* The mutable part of the blob data that is sync'd to
39 : : * disk. The data in here is both mutable and persistent.
40 : : */
41 : : struct spdk_blob_mut_data {
42 : : /* Number of data clusters in the blob */
43 : : uint64_t num_clusters;
44 : :
45 : : /* Array LBAs that are the beginning of a cluster, in
46 : : * the order they appear in the blob.
47 : : */
48 : : uint64_t *clusters;
49 : :
50 : : /* The size of the clusters array. This is greater than or
51 : : * equal to 'num_clusters'.
52 : : */
53 : : size_t cluster_array_size;
54 : :
55 : : /* Number of extent pages */
56 : : uint64_t num_extent_pages;
57 : :
58 : : /* Array of page offsets into the metadata region,
59 : : * containing extents. Can contain entries for not yet
60 : : * allocated pages. */
61 : : uint32_t *extent_pages;
62 : :
63 : : /* The size of the extent page array. This is greater than or
64 : : * equal to 'num_extent_pages'. */
65 : : size_t extent_pages_array_size;
66 : :
67 : : /* Number of metadata pages */
68 : : uint32_t num_pages;
69 : :
70 : : /* Array of page offsets into the metadata region, in
71 : : * the order of the metadata page sequence.
72 : : */
73 : : uint32_t *pages;
74 : : };
75 : :
76 : : enum spdk_blob_state {
77 : : /* The blob in-memory version does not match the on-disk
78 : : * version.
79 : : */
80 : : SPDK_BLOB_STATE_DIRTY,
81 : :
82 : : /* The blob in memory version of the blob matches the on disk
83 : : * version.
84 : : */
85 : : SPDK_BLOB_STATE_CLEAN,
86 : :
87 : : /* The in-memory state being synchronized with the on-disk
88 : : * blob state. */
89 : : SPDK_BLOB_STATE_LOADING,
90 : : };
91 : :
92 : : TAILQ_HEAD(spdk_xattr_tailq, spdk_xattr);
93 : :
94 : : struct spdk_blob_list {
95 : : spdk_blob_id id;
96 : : size_t clone_count;
97 : : TAILQ_HEAD(, spdk_blob_list) clones;
98 : : TAILQ_ENTRY(spdk_blob_list) link;
99 : : };
100 : :
101 : : struct spdk_blob {
102 : : struct spdk_blob_store *bs;
103 : :
104 : : uint32_t open_ref;
105 : :
106 : : spdk_blob_id id;
107 : : spdk_blob_id parent_id;
108 : :
109 : : enum spdk_blob_state state;
110 : :
111 : : /* Two copies of the mutable data. One is a version
112 : : * that matches the last known data on disk (clean).
113 : : * The other (active) is the current data. Syncing
114 : : * a blob makes the clean match the active.
115 : : */
116 : : struct spdk_blob_mut_data clean;
117 : : struct spdk_blob_mut_data active;
118 : :
119 : : bool invalid;
120 : : bool data_ro;
121 : : bool md_ro;
122 : :
123 : : uint64_t invalid_flags;
124 : : uint64_t data_ro_flags;
125 : : uint64_t md_ro_flags;
126 : :
127 : : struct spdk_bs_dev *back_bs_dev;
128 : :
129 : : /* TODO: The xattrs are mutable, but we don't want to be
130 : : * copying them unnecessarily. Figure this out.
131 : : */
132 : : struct spdk_xattr_tailq xattrs;
133 : : struct spdk_xattr_tailq xattrs_internal;
134 : :
135 : : RB_ENTRY(spdk_blob) link;
136 : :
137 : : uint32_t frozen_refcnt;
138 : : bool locked_operation_in_progress;
139 : : enum blob_clear_method clear_method;
140 : : bool extent_rle_found;
141 : : bool extent_table_found;
142 : : bool use_extent_table;
143 : :
144 : : /* A list of pending metadata pending_persists */
145 : : TAILQ_HEAD(, spdk_blob_persist_ctx) pending_persists;
146 : : TAILQ_HEAD(, spdk_blob_persist_ctx) persists_to_complete;
147 : :
148 : : /* Number of data clusters retrieved from extent table,
149 : : * that many have to be read from extent pages. */
150 : : uint64_t remaining_clusters_in_et;
151 : : };
152 : :
153 : : struct spdk_blob_store {
154 : : uint64_t md_start; /* Offset from beginning of disk, in pages */
155 : : uint32_t md_len; /* Count, in pages */
156 : :
157 : : struct spdk_io_channel *md_channel;
158 : : uint32_t max_channel_ops;
159 : :
160 : : struct spdk_thread *md_thread;
161 : :
162 : : struct spdk_bs_dev *dev;
163 : :
164 : : struct spdk_bit_array *used_md_pages; /* Protected by used_lock */
165 : : struct spdk_bit_pool *used_clusters; /* Protected by used_lock */
166 : : struct spdk_bit_array *used_blobids;
167 : : struct spdk_bit_array *open_blobids;
168 : :
169 : : struct spdk_spinlock used_lock;
170 : :
171 : : uint32_t cluster_sz;
172 : : uint64_t total_clusters;
173 : : uint64_t total_data_clusters;
174 : : uint64_t num_free_clusters; /* Protected by used_lock */
175 : : uint64_t pages_per_cluster;
176 : : uint8_t pages_per_cluster_shift;
177 : : uint32_t io_unit_size;
178 : :
179 : : spdk_blob_id super_blob;
180 : : struct spdk_bs_type bstype;
181 : :
182 : : struct spdk_bs_cpl unload_cpl;
183 : : int unload_err;
184 : :
185 : : RB_HEAD(spdk_blob_tree, spdk_blob) open_blobs;
186 : : TAILQ_HEAD(, spdk_blob_list) snapshots;
187 : :
188 : : bool clean;
189 : :
190 : : spdk_bs_esnap_dev_create esnap_bs_dev_create;
191 : : void *esnap_ctx;
192 : :
193 : : /* If external snapshot channels are being destroyed while
194 : : * the blobstore is unloaded, the unload is deferred until
195 : : * after the channel destruction completes.
196 : : */
197 : : uint32_t esnap_channels_unloading;
198 : : spdk_bs_op_complete esnap_unload_cb_fn;
199 : : void *esnap_unload_cb_arg;
200 : : };
201 : :
202 : : struct spdk_bs_channel {
203 : : struct spdk_bs_request_set *req_mem;
204 : : TAILQ_HEAD(, spdk_bs_request_set) reqs;
205 : :
206 : : struct spdk_blob_store *bs;
207 : :
208 : : struct spdk_bs_dev *dev;
209 : : struct spdk_io_channel *dev_channel;
210 : :
211 : : /* This page is only used during insert of a new cluster. */
212 : : struct spdk_blob_md_page *new_cluster_page;
213 : :
214 : : TAILQ_HEAD(, spdk_bs_request_set) need_cluster_alloc;
215 : : TAILQ_HEAD(, spdk_bs_request_set) queued_io;
216 : :
217 : : RB_HEAD(blob_esnap_channel_tree, blob_esnap_channel) esnap_channels;
218 : : };
219 : :
220 : : /** operation type */
221 : : enum spdk_blob_op_type {
222 : : SPDK_BLOB_WRITE,
223 : : SPDK_BLOB_READ,
224 : : SPDK_BLOB_UNMAP,
225 : : SPDK_BLOB_WRITE_ZEROES,
226 : : SPDK_BLOB_WRITEV,
227 : : SPDK_BLOB_READV,
228 : : };
229 : :
230 : : /* back bs_dev */
231 : :
232 : : #define BLOB_SNAPSHOT "SNAP"
233 : : #define SNAPSHOT_IN_PROGRESS "SNAPTMP"
234 : : #define SNAPSHOT_PENDING_REMOVAL "SNAPRM"
235 : : #define BLOB_EXTERNAL_SNAPSHOT_ID "EXTSNAP"
236 : :
237 : : struct spdk_blob_bs_dev {
238 : : struct spdk_bs_dev bs_dev;
239 : : struct spdk_blob *blob;
240 : : };
241 : :
242 : : /* On-Disk Data Structures
243 : : *
244 : : * The following data structures exist on disk.
245 : : */
246 : : #define SPDK_BS_INITIAL_VERSION 1
247 : : #define SPDK_BS_VERSION 3 /* current version */
248 : :
249 : : #pragma pack(push, 1)
250 : :
251 : : #define SPDK_MD_MASK_TYPE_USED_PAGES 0
252 : : #define SPDK_MD_MASK_TYPE_USED_CLUSTERS 1
253 : : #define SPDK_MD_MASK_TYPE_USED_BLOBIDS 2
254 : :
255 : : struct spdk_bs_md_mask {
256 : : uint8_t type;
257 : : uint32_t length; /* In bits */
258 : : uint8_t mask[0];
259 : : };
260 : :
261 : : #define SPDK_MD_DESCRIPTOR_TYPE_PADDING 0
262 : : #define SPDK_MD_DESCRIPTOR_TYPE_XATTR 2
263 : : #define SPDK_MD_DESCRIPTOR_TYPE_FLAGS 3
264 : : #define SPDK_MD_DESCRIPTOR_TYPE_XATTR_INTERNAL 4
265 : :
266 : : /* Following descriptors define cluster layout in a blob.
267 : : * EXTENT_RLE cannot be present in blobs metadata,
268 : : * at the same time as EXTENT_TABLE and EXTENT_PAGE descriptors. */
269 : :
270 : : /* EXTENT_RLE descriptor holds an array of LBA that points to
271 : : * beginning of allocated clusters. The array is run-length encoded,
272 : : * with 0's being unallocated clusters. It is part of serialized
273 : : * metadata chain for a blob. */
274 : : #define SPDK_MD_DESCRIPTOR_TYPE_EXTENT_RLE 1
275 : : /* EXTENT_TABLE descriptor holds array of md page offsets that
276 : : * point to pages with EXTENT_PAGE descriptor. The 0's in the array
277 : : * are run-length encoded, non-zero values are unallocated pages.
278 : : * It is part of serialized metadata chain for a blob. */
279 : : #define SPDK_MD_DESCRIPTOR_TYPE_EXTENT_TABLE 5
280 : : /* EXTENT_PAGE descriptor holds an array of LBAs that point to
281 : : * beginning of allocated clusters. The array is run-length encoded,
282 : : * with 0's being unallocated clusters. It is NOT part of
283 : : * serialized metadata chain for a blob. */
284 : : #define SPDK_MD_DESCRIPTOR_TYPE_EXTENT_PAGE 6
285 : :
286 : : struct spdk_blob_md_descriptor_xattr {
287 : : uint8_t type;
288 : : uint32_t length;
289 : :
290 : : uint16_t name_length;
291 : : uint16_t value_length;
292 : :
293 : : char name[0];
294 : : /* String name immediately followed by string value. */
295 : : };
296 : :
297 : : struct spdk_blob_md_descriptor_extent_rle {
298 : : uint8_t type;
299 : : uint32_t length;
300 : :
301 : : struct {
302 : : uint32_t cluster_idx;
303 : : uint32_t length; /* In units of clusters */
304 : : } extents[0];
305 : : };
306 : :
307 : : struct spdk_blob_md_descriptor_extent_table {
308 : : uint8_t type;
309 : : uint32_t length;
310 : :
311 : : /* Number of data clusters in the blob */
312 : : uint64_t num_clusters;
313 : :
314 : : struct {
315 : : uint32_t page_idx;
316 : : uint32_t num_pages; /* In units of pages */
317 : : } extent_page[0];
318 : : };
319 : :
320 : : struct spdk_blob_md_descriptor_extent_page {
321 : : uint8_t type;
322 : : uint32_t length;
323 : :
324 : : /* First cluster index in this extent page */
325 : : uint32_t start_cluster_idx;
326 : :
327 : : uint32_t cluster_idx[0];
328 : : };
329 : :
330 : : #define SPDK_BLOB_THIN_PROV (1ULL << 0)
331 : : #define SPDK_BLOB_INTERNAL_XATTR (1ULL << 1)
332 : : #define SPDK_BLOB_EXTENT_TABLE (1ULL << 2)
333 : : #define SPDK_BLOB_EXTERNAL_SNAPSHOT (1ULL << 3)
334 : : #define SPDK_BLOB_INVALID_FLAGS_MASK (SPDK_BLOB_THIN_PROV | SPDK_BLOB_INTERNAL_XATTR | \
335 : : SPDK_BLOB_EXTENT_TABLE | SPDK_BLOB_EXTERNAL_SNAPSHOT)
336 : :
337 : : #define SPDK_BLOB_READ_ONLY (1ULL << 0)
338 : : #define SPDK_BLOB_DATA_RO_FLAGS_MASK SPDK_BLOB_READ_ONLY
339 : :
340 : : #define SPDK_BLOB_CLEAR_METHOD_SHIFT 0
341 : : #define SPDK_BLOB_CLEAR_METHOD (3ULL << SPDK_BLOB_CLEAR_METHOD_SHIFT)
342 : : #define SPDK_BLOB_MD_RO_FLAGS_MASK SPDK_BLOB_CLEAR_METHOD
343 : :
344 : : struct spdk_blob_md_descriptor_flags {
345 : : uint8_t type;
346 : : uint32_t length;
347 : :
348 : : /*
349 : : * If a flag in invalid_flags is set that the application is not aware of,
350 : : * it will not allow the blob to be opened.
351 : : */
352 : : uint64_t invalid_flags;
353 : :
354 : : /*
355 : : * If a flag in data_ro_flags is set that the application is not aware of,
356 : : * allow the blob to be opened in data_read_only and md_read_only mode.
357 : : */
358 : : uint64_t data_ro_flags;
359 : :
360 : : /*
361 : : * If a flag in md_ro_flags is set the application is not aware of,
362 : : * allow the blob to be opened in md_read_only mode.
363 : : */
364 : : uint64_t md_ro_flags;
365 : : };
366 : :
367 : : struct spdk_blob_md_descriptor {
368 : : uint8_t type;
369 : : uint32_t length;
370 : : };
371 : :
372 : : #define SPDK_INVALID_MD_PAGE UINT32_MAX
373 : :
374 : : struct spdk_blob_md_page {
375 : : spdk_blob_id id;
376 : :
377 : : uint32_t sequence_num;
378 : : uint32_t reserved0;
379 : :
380 : : /* Descriptors here */
381 : : uint8_t descriptors[4072];
382 : :
383 : : uint32_t next;
384 : : uint32_t crc;
385 : : };
386 : : #define SPDK_BS_PAGE_SIZE 0x1000
387 : : SPDK_STATIC_ASSERT(SPDK_BS_PAGE_SIZE == sizeof(struct spdk_blob_md_page), "Invalid md page size");
388 : :
389 : : #define SPDK_BS_MAX_DESC_SIZE SPDK_SIZEOF_MEMBER(struct spdk_blob_md_page, descriptors)
390 : :
391 : : /* Maximum number of extents a single Extent Page can fit.
392 : : * For an SPDK_BS_PAGE_SIZE of 4K SPDK_EXTENTS_PER_EP would be 512. */
393 : : #define SPDK_EXTENTS_PER_EP_MAX ((SPDK_BS_MAX_DESC_SIZE - sizeof(struct spdk_blob_md_descriptor_extent_page)) / sizeof(uint32_t))
394 : : #define SPDK_EXTENTS_PER_EP (spdk_align64pow2(SPDK_EXTENTS_PER_EP_MAX + 1) >> 1u)
395 : :
396 : : #define SPDK_BS_SUPER_BLOCK_SIG "SPDKBLOB"
397 : :
398 : : struct spdk_bs_super_block {
399 : : uint8_t signature[8];
400 : : uint32_t version;
401 : : uint32_t length;
402 : : uint32_t clean; /* If there was a clean shutdown, this is 1. */
403 : : spdk_blob_id super_blob;
404 : :
405 : : uint32_t cluster_size; /* In bytes */
406 : :
407 : : uint32_t used_page_mask_start; /* Offset from beginning of disk, in pages */
408 : : uint32_t used_page_mask_len; /* Count, in pages */
409 : :
410 : : uint32_t used_cluster_mask_start; /* Offset from beginning of disk, in pages */
411 : : uint32_t used_cluster_mask_len; /* Count, in pages */
412 : :
413 : : uint32_t md_start; /* Offset from beginning of disk, in pages */
414 : : uint32_t md_len; /* Count, in pages */
415 : :
416 : : struct spdk_bs_type bstype; /* blobstore type */
417 : :
418 : : uint32_t used_blobid_mask_start; /* Offset from beginning of disk, in pages */
419 : : uint32_t used_blobid_mask_len; /* Count, in pages */
420 : :
421 : : uint64_t size; /* size of blobstore in bytes */
422 : : uint32_t io_unit_size; /* Size of io unit in bytes */
423 : :
424 : : uint8_t reserved[4000];
425 : : uint32_t crc;
426 : : };
427 : : SPDK_STATIC_ASSERT(sizeof(struct spdk_bs_super_block) == 0x1000, "Invalid super block size");
428 : :
429 : : #pragma pack(pop)
430 : :
431 : : struct spdk_bs_dev *bs_create_zeroes_dev(void);
432 : : struct spdk_bs_dev *bs_create_blob_bs_dev(struct spdk_blob *blob);
433 : : struct spdk_io_channel *blob_esnap_get_io_channel(struct spdk_io_channel *ch,
434 : : struct spdk_blob *blob);
435 : :
436 : : /* Unit Conversions
437 : : *
438 : : * The blobstore works with several different units:
439 : : * - Byte: Self explanatory
440 : : * - LBA: The logical blocks on the backing storage device.
441 : : * - Page: The read/write units of blobs and metadata. This is
442 : : * an offset into a blob in units of 4KiB.
443 : : * - Cluster Index: The disk is broken into a sequential list of
444 : : * clusters. This is the offset from the beginning.
445 : : *
446 : : * NOTE: These conversions all act on simple magnitudes, not with any sort
447 : : * of knowledge about the blobs themselves. For instance, converting
448 : : * a page to an lba with the conversion function below simply converts
449 : : * a number of pages to an equivalent number of lbas, but that
450 : : * lba certainly isn't the right lba that corresponds to a page offset
451 : : * for a particular blob.
452 : : */
453 : : static inline uint64_t
454 : 983815 : bs_byte_to_lba(struct spdk_blob_store *bs, uint64_t length)
455 : : {
456 [ - + - + ]: 983815 : assert(length % bs->dev->blocklen == 0);
457 : :
458 [ - + ]: 983815 : return length / bs->dev->blocklen;
459 : : }
460 : :
461 : : static inline uint64_t
462 : 32413 : bs_dev_byte_to_lba(struct spdk_bs_dev *bs_dev, uint64_t length)
463 : : {
464 [ - + - + ]: 32413 : assert(length % bs_dev->blocklen == 0);
465 : :
466 [ - + ]: 32413 : return length / bs_dev->blocklen;
467 : : }
468 : :
469 : : static inline uint64_t
470 : 511356 : bs_page_to_lba(struct spdk_blob_store *bs, uint64_t page)
471 : : {
472 [ - + ]: 511356 : return page * SPDK_BS_PAGE_SIZE / bs->dev->blocklen;
473 : : }
474 : :
475 : : static inline uint64_t
476 : 453481 : bs_md_page_to_lba(struct spdk_blob_store *bs, uint32_t page)
477 : : {
478 [ - + ]: 453481 : assert(page < bs->md_len);
479 : 453481 : return bs_page_to_lba(bs, page + bs->md_start);
480 : : }
481 : :
482 : : static inline uint64_t
483 : 57727 : bs_dev_page_to_lba(struct spdk_bs_dev *bs_dev, uint64_t page)
484 : : {
485 [ - + ]: 57727 : return page * SPDK_BS_PAGE_SIZE / bs_dev->blocklen;
486 : : }
487 : :
488 : : static inline uint64_t
489 : 88064297 : bs_io_unit_per_page(struct spdk_blob_store *bs)
490 : : {
491 [ - + ]: 88064297 : return SPDK_BS_PAGE_SIZE / bs->io_unit_size;
492 : : }
493 : :
494 : : static inline uint64_t
495 : 43972817 : bs_io_unit_to_page(struct spdk_blob_store *bs, uint64_t io_unit)
496 : : {
497 [ - + ]: 43972817 : return io_unit / bs_io_unit_per_page(bs);
498 : : }
499 : :
500 : : static inline uint64_t
501 : 207 : bs_cluster_to_page(struct spdk_blob_store *bs, uint32_t cluster)
502 : : {
503 : 207 : return (uint64_t)cluster * bs->pages_per_cluster;
504 : : }
505 : :
506 : : static inline uint32_t
507 : 1877 : bs_page_to_cluster(struct spdk_blob_store *bs, uint64_t page)
508 : : {
509 [ - + - + ]: 1877 : assert(page % bs->pages_per_cluster == 0);
510 : :
511 [ - + ]: 1877 : return page / bs->pages_per_cluster;
512 : : }
513 : :
514 : : static inline uint64_t
515 : 39941445 : bs_cluster_to_lba(struct spdk_blob_store *bs, uint32_t cluster)
516 : : {
517 [ - + - + ]: 39941445 : assert(bs->cluster_sz / bs->dev->blocklen > 0);
518 : :
519 [ - + ]: 39941445 : return (uint64_t)cluster * (bs->cluster_sz / bs->dev->blocklen);
520 : : }
521 : :
522 : : static inline uint32_t
523 : 9227494 : bs_lba_to_cluster(struct spdk_blob_store *bs, uint64_t lba)
524 : : {
525 [ - + - + : 9227494 : assert(lba % (bs->cluster_sz / bs->dev->blocklen) == 0);
- + ]
526 : :
527 [ - + - + ]: 9227494 : return lba / (bs->cluster_sz / bs->dev->blocklen);
528 : : }
529 : :
530 : : static inline uint64_t
531 : 1971554 : bs_io_unit_to_back_dev_lba(struct spdk_blob *blob, uint64_t io_unit)
532 : : {
533 [ - + ]: 1971554 : return io_unit * (blob->bs->io_unit_size / blob->back_bs_dev->blocklen);
534 : : }
535 : :
536 : : static inline uint64_t
537 : 2448770 : bs_cluster_to_extent_table_id(uint64_t cluster_num)
538 : : {
539 [ - + ]: 2448770 : return cluster_num / SPDK_EXTENTS_PER_EP;
540 : : }
541 : :
542 : : static inline uint32_t *
543 : 2448770 : bs_cluster_to_extent_page(struct spdk_blob *blob, uint64_t cluster_num)
544 : : {
545 : 2448770 : uint64_t extent_table_id = bs_cluster_to_extent_table_id(cluster_num);
546 : :
547 [ - + - + ]: 2448770 : assert(blob->use_extent_table);
548 [ - + ]: 2448770 : assert(extent_table_id < blob->active.extent_pages_array_size);
549 : :
550 : 2448770 : return &blob->active.extent_pages[extent_table_id];
551 : : }
552 : :
553 : : static inline uint64_t
554 : 22580871 : bs_io_units_per_cluster(struct spdk_blob *blob)
555 : : {
556 : : uint64_t io_units_per_cluster;
557 : 22580871 : uint8_t shift = blob->bs->pages_per_cluster_shift;
558 : :
559 [ + - ]: 22580871 : if (shift != 0) {
560 [ - + ]: 22580871 : io_units_per_cluster = bs_io_unit_per_page(blob->bs) << shift;
561 : : } else {
562 : 0 : io_units_per_cluster = bs_io_unit_per_page(blob->bs) * blob->bs->pages_per_cluster;
563 : : }
564 : :
565 : 22580871 : return io_units_per_cluster;
566 : : }
567 : :
568 : : /* End basic conversions */
569 : :
570 : : static inline uint64_t
571 : 566594 : bs_blobid_to_page(spdk_blob_id id)
572 : : {
573 : 566594 : return id & 0xFFFFFFFF;
574 : : }
575 : :
576 : : /* The blob id is a 64 bit number. The lower 32 bits are the page_idx. The upper
577 : : * 32 bits are not currently used. Stick a 1 there just to catch bugs where the
578 : : * code assumes blob id == page_idx.
579 : : */
580 : : static inline spdk_blob_id
581 : 24399 : bs_page_to_blobid(uint64_t page_idx)
582 : : {
583 [ - + ]: 24399 : if (page_idx > UINT32_MAX) {
584 : 0 : return SPDK_BLOBID_INVALID;
585 : : }
586 : 24399 : return SPDK_BLOB_BLOBID_HIGH_BIT | page_idx;
587 : : }
588 : :
589 : : /* Given an io unit offset into a blob, look up the LBA for the
590 : : * start of that io unit.
591 : : */
592 : : static inline uint64_t
593 : 21478409 : bs_blob_io_unit_to_lba(struct spdk_blob *blob, uint64_t io_unit)
594 : : {
595 : : uint64_t lba;
596 : : uint64_t pages_per_cluster;
597 : : uint8_t shift;
598 : : uint64_t io_units_per_cluster;
599 : : uint64_t io_units_per_page;
600 : : uint64_t page;
601 : :
602 : 21478409 : page = bs_io_unit_to_page(blob->bs, io_unit);
603 : :
604 : 21478409 : pages_per_cluster = blob->bs->pages_per_cluster;
605 : 21478409 : shift = blob->bs->pages_per_cluster_shift;
606 : 21478409 : io_units_per_page = bs_io_unit_per_page(blob->bs);
607 : :
608 [ - + ]: 21478409 : assert(page < blob->active.num_clusters * pages_per_cluster);
609 : :
610 [ + - ]: 21478409 : if (shift != 0) {
611 [ - + ]: 21478409 : io_units_per_cluster = io_units_per_page << shift;
612 [ - + ]: 21478409 : lba = blob->active.clusters[page >> shift];
613 : : } else {
614 : 0 : io_units_per_cluster = io_units_per_page * pages_per_cluster;
615 [ # # ]: 0 : lba = blob->active.clusters[page / pages_per_cluster];
616 : : }
617 [ - + ]: 21478409 : lba += io_unit % io_units_per_cluster;
618 : 21478409 : return lba;
619 : : }
620 : :
621 : : /* Given an io_unit offset into a blob, look up the number of io_units until the
622 : : * next cluster boundary.
623 : : */
624 : : static inline uint32_t
625 : 22580847 : bs_num_io_units_to_cluster_boundary(struct spdk_blob *blob, uint64_t io_unit)
626 : : {
627 : : uint64_t io_units_per_cluster;
628 : :
629 : 22580847 : io_units_per_cluster = bs_io_units_per_cluster(blob);
630 : :
631 [ - + ]: 22580847 : return io_units_per_cluster - (io_unit % io_units_per_cluster);
632 : : }
633 : :
634 : : /* Given an io_unit offset into a blob, look up the number of pages into blob to beginning of current cluster */
635 : : static inline uint32_t
636 : 28273 : bs_io_unit_to_cluster_start(struct spdk_blob *blob, uint64_t io_unit)
637 : : {
638 : : uint64_t pages_per_cluster;
639 : : uint64_t page;
640 : :
641 : 28273 : pages_per_cluster = blob->bs->pages_per_cluster;
642 : 28273 : page = bs_io_unit_to_page(blob->bs, io_unit);
643 : :
644 [ - + ]: 28273 : return page - (page % pages_per_cluster);
645 : : }
646 : :
647 : : /* Given an io_unit offset into a blob, look up the number of pages into blob to beginning of current cluster */
648 : : static inline uint32_t
649 : 28273 : bs_io_unit_to_cluster_number(struct spdk_blob *blob, uint64_t io_unit)
650 : : {
651 : 28273 : uint64_t pages_per_cluster = blob->bs->pages_per_cluster;
652 : 28273 : uint8_t shift = blob->bs->pages_per_cluster_shift;
653 : : uint32_t page_offset;
654 : :
655 [ - + ]: 28273 : page_offset = io_unit / bs_io_unit_per_page(blob->bs);
656 [ + - ]: 28273 : if (shift != 0) {
657 [ - + ]: 28273 : return page_offset >> shift;
658 : : } else {
659 [ # # ]: 0 : return page_offset / pages_per_cluster;
660 : : }
661 : : }
662 : :
663 : : /* Given an io unit offset into a blob, look up if it is from allocated cluster. */
664 : : static inline bool
665 : 22466135 : bs_io_unit_is_allocated(struct spdk_blob *blob, uint64_t io_unit)
666 : : {
667 : : uint64_t lba;
668 : : uint64_t page;
669 : : uint64_t pages_per_cluster;
670 : : uint8_t shift;
671 : :
672 : 22466135 : shift = blob->bs->pages_per_cluster_shift;
673 : 22466135 : pages_per_cluster = blob->bs->pages_per_cluster;
674 : 22466135 : page = bs_io_unit_to_page(blob->bs, io_unit);
675 : :
676 [ - + ]: 22466135 : assert(page < blob->active.num_clusters * pages_per_cluster);
677 : :
678 [ + - ]: 22466135 : if (shift != 0) {
679 [ - + ]: 22466135 : lba = blob->active.clusters[page >> shift];
680 : : } else {
681 [ # # ]: 0 : lba = blob->active.clusters[page / pages_per_cluster];
682 : : }
683 : :
684 [ + + ]: 22466135 : if (lba == 0) {
685 [ - + ]: 986148 : assert(spdk_blob_is_thin_provisioned(blob));
686 : 986148 : return false;
687 : : } else {
688 : 21479987 : return true;
689 : : }
690 : : }
691 : :
692 : : #endif
|