1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) Intel Corporation. 3 * All rights reserved. 4 * Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 5 */ 6 7 #include "spdk/stdinc.h" 8 #include "spdk/blob.h" 9 #include "spdk/log.h" 10 #include "blobstore.h" 11 12 static void 13 blob_bs_dev_write(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *payload, 14 uint64_t lba, uint32_t lba_count, 15 struct spdk_bs_dev_cb_args *cb_args) 16 { 17 cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, -EPERM); 18 assert(false); 19 } 20 21 static void 22 blob_bs_dev_writev(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, 23 struct iovec *iov, int iovcnt, 24 uint64_t lba, uint32_t lba_count, 25 struct spdk_bs_dev_cb_args *cb_args) 26 { 27 cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, -EPERM); 28 assert(false); 29 } 30 31 static void 32 blob_bs_dev_writev_ext(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, 33 struct iovec *iov, int iovcnt, 34 uint64_t lba, uint32_t lba_count, 35 struct spdk_bs_dev_cb_args *cb_args, 36 struct spdk_blob_ext_io_opts *ext_opts) 37 { 38 cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, -EPERM); 39 assert(false); 40 } 41 42 static void 43 blob_bs_dev_write_zeroes(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, 44 uint64_t lba, uint64_t lba_count, 45 struct spdk_bs_dev_cb_args *cb_args) 46 { 47 cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, -EPERM); 48 assert(false); 49 } 50 51 static void 52 blob_bs_dev_unmap(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, 53 uint64_t lba, uint64_t lba_count, 54 struct spdk_bs_dev_cb_args *cb_args) 55 { 56 cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, -EPERM); 57 assert(false); 58 } 59 60 static void 61 blob_bs_dev_read_cpl(void *cb_arg, int bserrno) 62 { 63 struct spdk_bs_dev_cb_args *cb_args = (struct spdk_bs_dev_cb_args *)cb_arg; 64 65 cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, bserrno); 66 } 67 68 static inline void 69 blob_bs_dev_read(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *payload, 70 uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args) 71 { 72 struct spdk_blob_bs_dev *b = (struct spdk_blob_bs_dev *)dev; 73 74 spdk_blob_io_read(b->blob, channel, payload, lba, lba_count, 75 blob_bs_dev_read_cpl, cb_args); 76 } 77 78 static inline void 79 blob_bs_dev_readv(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, 80 struct iovec *iov, int iovcnt, 81 uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args) 82 { 83 struct spdk_blob_bs_dev *b = (struct spdk_blob_bs_dev *)dev; 84 85 spdk_blob_io_readv(b->blob, channel, iov, iovcnt, lba, lba_count, 86 blob_bs_dev_read_cpl, cb_args); 87 } 88 89 static inline void 90 blob_bs_dev_readv_ext(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, 91 struct iovec *iov, int iovcnt, 92 uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args, 93 struct spdk_blob_ext_io_opts *ext_opts) 94 { 95 struct spdk_blob_bs_dev *b = (struct spdk_blob_bs_dev *)dev; 96 97 spdk_blob_io_readv_ext(b->blob, channel, iov, iovcnt, lba, lba_count, 98 blob_bs_dev_read_cpl, cb_args, ext_opts); 99 } 100 101 static void 102 blob_bs_dev_destroy_cpl(void *cb_arg, int bserrno) 103 { 104 if (bserrno != 0) { 105 SPDK_ERRLOG("Error on blob_bs_dev destroy: %d", bserrno); 106 } 107 108 /* Free blob_bs_dev */ 109 free(cb_arg); 110 } 111 112 static void 113 blob_bs_dev_destroy(struct spdk_bs_dev *bs_dev) 114 { 115 struct spdk_blob_bs_dev *b = (struct spdk_blob_bs_dev *)bs_dev; 116 117 spdk_blob_close(b->blob, blob_bs_dev_destroy_cpl, b); 118 } 119 120 static bool 121 blob_bs_is_zeroes(struct spdk_bs_dev *dev, uint64_t lba, uint64_t lba_count) 122 { 123 struct spdk_blob_bs_dev *b = (struct spdk_blob_bs_dev *)dev; 124 struct spdk_blob *blob = b->blob; 125 126 assert(lba == bs_cluster_to_lba(blob->bs, bs_lba_to_cluster(blob->bs, lba))); 127 assert(lba_count == bs_dev_byte_to_lba(dev, blob->bs->cluster_sz)); 128 129 if (bs_io_unit_is_allocated(blob, lba)) { 130 return false; 131 } 132 133 assert(blob->back_bs_dev != NULL); 134 return blob->back_bs_dev->is_zeroes(blob->back_bs_dev, 135 bs_io_unit_to_back_dev_lba(blob, lba), 136 bs_io_unit_to_back_dev_lba(blob, lba_count)); 137 } 138 139 struct spdk_bs_dev * 140 bs_create_blob_bs_dev(struct spdk_blob *blob) 141 { 142 struct spdk_blob_bs_dev *b; 143 144 b = calloc(1, sizeof(*b)); 145 if (b == NULL) { 146 return NULL; 147 } 148 /* snapshot blob */ 149 b->bs_dev.blockcnt = blob->active.num_clusters * 150 blob->bs->pages_per_cluster * bs_io_unit_per_page(blob->bs); 151 b->bs_dev.blocklen = spdk_bs_get_io_unit_size(blob->bs); 152 b->bs_dev.create_channel = NULL; 153 b->bs_dev.destroy_channel = NULL; 154 b->bs_dev.destroy = blob_bs_dev_destroy; 155 b->bs_dev.write = blob_bs_dev_write; 156 b->bs_dev.writev = blob_bs_dev_writev; 157 b->bs_dev.writev_ext = blob_bs_dev_writev_ext; 158 b->bs_dev.read = blob_bs_dev_read; 159 b->bs_dev.readv = blob_bs_dev_readv; 160 b->bs_dev.readv_ext = blob_bs_dev_readv_ext; 161 b->bs_dev.write_zeroes = blob_bs_dev_write_zeroes; 162 b->bs_dev.unmap = blob_bs_dev_unmap; 163 b->bs_dev.is_zeroes = blob_bs_is_zeroes; 164 b->blob = blob; 165 166 return &b->bs_dev; 167 } 168