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 30312 : bs_byte_to_lba(struct spdk_blob_store *bs, uint64_t length)
455 : {
456 30312 : assert(length % bs->dev->blocklen == 0);
457 :
458 30312 : return length / bs->dev->blocklen;
459 : }
460 :
461 : static inline uint64_t
462 1264 : bs_dev_byte_to_lba(struct spdk_bs_dev *bs_dev, uint64_t length)
463 : {
464 1264 : assert(length % bs_dev->blocklen == 0);
465 :
466 1264 : return length / bs_dev->blocklen;
467 : }
468 :
469 : static inline uint64_t
470 25860 : bs_page_to_lba(struct spdk_blob_store *bs, uint64_t page)
471 : {
472 25860 : return page * SPDK_BS_PAGE_SIZE / bs->dev->blocklen;
473 : }
474 :
475 : static inline uint64_t
476 17632 : bs_md_page_to_lba(struct spdk_blob_store *bs, uint32_t page)
477 : {
478 17632 : assert(page < bs->md_len);
479 17632 : return bs_page_to_lba(bs, page + bs->md_start);
480 : }
481 :
482 : static inline uint64_t
483 1404 : bs_dev_page_to_lba(struct spdk_bs_dev *bs_dev, uint64_t page)
484 : {
485 1404 : return page * SPDK_BS_PAGE_SIZE / bs_dev->blocklen;
486 : }
487 :
488 : static inline uint64_t
489 109360 : bs_io_unit_per_page(struct spdk_blob_store *bs)
490 : {
491 109360 : return SPDK_BS_PAGE_SIZE / bs->io_unit_size;
492 : }
493 :
494 : static inline uint64_t
495 53620 : bs_io_unit_to_page(struct spdk_blob_store *bs, uint64_t io_unit)
496 : {
497 53620 : return io_unit / bs_io_unit_per_page(bs);
498 : }
499 :
500 : static inline uint64_t
501 28 : bs_cluster_to_page(struct spdk_blob_store *bs, uint32_t cluster)
502 : {
503 28 : return (uint64_t)cluster * bs->pages_per_cluster;
504 : }
505 :
506 : static inline uint32_t
507 296 : bs_page_to_cluster(struct spdk_blob_store *bs, uint64_t page)
508 : {
509 296 : assert(page % bs->pages_per_cluster == 0);
510 :
511 296 : return page / bs->pages_per_cluster;
512 : }
513 :
514 : static inline uint64_t
515 1122044 : bs_cluster_to_lba(struct spdk_blob_store *bs, uint32_t cluster)
516 : {
517 1122044 : assert(bs->cluster_sz / bs->dev->blocklen > 0);
518 :
519 1122044 : return (uint64_t)cluster * (bs->cluster_sz / bs->dev->blocklen);
520 : }
521 :
522 : static inline uint32_t
523 1069211 : bs_lba_to_cluster(struct spdk_blob_store *bs, uint64_t lba)
524 : {
525 1069211 : assert(lba % (bs->cluster_sz / bs->dev->blocklen) == 0);
526 :
527 1069211 : return lba / (bs->cluster_sz / bs->dev->blocklen);
528 : }
529 :
530 : static inline uint64_t
531 5880 : bs_io_unit_to_back_dev_lba(struct spdk_blob *blob, uint64_t io_unit)
532 : {
533 5880 : return io_unit * (blob->bs->io_unit_size / blob->back_bs_dev->blocklen);
534 : }
535 :
536 : static inline uint64_t
537 4420 : bs_cluster_to_extent_table_id(uint64_t cluster_num)
538 : {
539 4420 : return cluster_num / SPDK_EXTENTS_PER_EP;
540 : }
541 :
542 : static inline uint32_t *
543 4420 : bs_cluster_to_extent_page(struct spdk_blob *blob, uint64_t cluster_num)
544 : {
545 4420 : uint64_t extent_table_id = bs_cluster_to_extent_table_id(cluster_num);
546 :
547 4420 : assert(blob->use_extent_table);
548 4420 : assert(extent_table_id < blob->active.extent_pages_array_size);
549 :
550 4420 : return &blob->active.extent_pages[extent_table_id];
551 : }
552 :
553 : static inline uint64_t
554 29622 : bs_io_units_per_cluster(struct spdk_blob *blob)
555 : {
556 : uint64_t io_units_per_cluster;
557 29622 : uint8_t shift = blob->bs->pages_per_cluster_shift;
558 :
559 29622 : if (shift != 0) {
560 29622 : 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 29622 : return io_units_per_cluster;
566 : }
567 :
568 : /* End basic conversions */
569 :
570 : static inline uint64_t
571 28565 : bs_blobid_to_page(spdk_blob_id id)
572 : {
573 28565 : 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 2426 : bs_page_to_blobid(uint64_t page_idx)
582 : {
583 2426 : if (page_idx > UINT32_MAX) {
584 0 : return SPDK_BLOBID_INVALID;
585 : }
586 2426 : 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 24890 : 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 24890 : page = bs_io_unit_to_page(blob->bs, io_unit);
603 :
604 24890 : pages_per_cluster = blob->bs->pages_per_cluster;
605 24890 : shift = blob->bs->pages_per_cluster_shift;
606 24890 : io_units_per_page = bs_io_unit_per_page(blob->bs);
607 :
608 24890 : assert(page < blob->active.num_clusters * pages_per_cluster);
609 :
610 24890 : if (shift != 0) {
611 24890 : io_units_per_cluster = io_units_per_page << shift;
612 24890 : 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 24890 : lba += io_unit % io_units_per_cluster;
618 24890 : 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 29618 : 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 29618 : io_units_per_cluster = bs_io_units_per_cluster(blob);
630 :
631 29618 : 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 608 : 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 608 : pages_per_cluster = blob->bs->pages_per_cluster;
642 608 : page = bs_io_unit_to_page(blob->bs, io_unit);
643 :
644 608 : 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 608 : bs_io_unit_to_cluster_number(struct spdk_blob *blob, uint64_t io_unit)
650 : {
651 608 : uint64_t pages_per_cluster = blob->bs->pages_per_cluster;
652 608 : uint8_t shift = blob->bs->pages_per_cluster_shift;
653 : uint32_t page_offset;
654 :
655 608 : page_offset = io_unit / bs_io_unit_per_page(blob->bs);
656 608 : if (shift != 0) {
657 608 : 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 28122 : 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 28122 : shift = blob->bs->pages_per_cluster_shift;
673 28122 : pages_per_cluster = blob->bs->pages_per_cluster;
674 28122 : page = bs_io_unit_to_page(blob->bs, io_unit);
675 :
676 28122 : assert(page < blob->active.num_clusters * pages_per_cluster);
677 :
678 28122 : if (shift != 0) {
679 28122 : lba = blob->active.clusters[page >> shift];
680 : } else {
681 0 : lba = blob->active.clusters[page / pages_per_cluster];
682 : }
683 :
684 28122 : if (lba == 0) {
685 2992 : assert(spdk_blob_is_thin_provisioned(blob));
686 2992 : return false;
687 : } else {
688 25130 : return true;
689 : }
690 : }
691 :
692 : #endif
|