1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2018 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 static bool 140 blob_bs_translate_lba(struct spdk_bs_dev *dev, uint64_t lba, uint64_t *base_lba) 141 { 142 struct spdk_blob_bs_dev *b = (struct spdk_blob_bs_dev *)dev; 143 struct spdk_blob *blob = b->blob; 144 145 assert(base_lba != NULL); 146 if (bs_io_unit_is_allocated(blob, lba)) { 147 *base_lba = bs_blob_io_unit_to_lba(blob, lba); 148 return true; 149 } 150 151 assert(blob->back_bs_dev != NULL); 152 return blob->back_bs_dev->translate_lba(blob->back_bs_dev, 153 bs_io_unit_to_back_dev_lba(blob, lba), 154 base_lba); 155 } 156 157 static bool 158 blob_bs_is_degraded(struct spdk_bs_dev *dev) 159 { 160 struct spdk_blob_bs_dev *b = (struct spdk_blob_bs_dev *)dev; 161 162 return spdk_blob_is_degraded(b->blob); 163 } 164 165 struct spdk_bs_dev * 166 bs_create_blob_bs_dev(struct spdk_blob *blob) 167 { 168 struct spdk_blob_bs_dev *b; 169 170 b = calloc(1, sizeof(*b)); 171 if (b == NULL) { 172 return NULL; 173 } 174 /* snapshot blob */ 175 b->bs_dev.blockcnt = blob->active.num_clusters * 176 blob->bs->pages_per_cluster * bs_io_unit_per_page(blob->bs); 177 b->bs_dev.blocklen = spdk_bs_get_io_unit_size(blob->bs); 178 b->bs_dev.create_channel = NULL; 179 b->bs_dev.destroy_channel = NULL; 180 b->bs_dev.destroy = blob_bs_dev_destroy; 181 b->bs_dev.write = blob_bs_dev_write; 182 b->bs_dev.writev = blob_bs_dev_writev; 183 b->bs_dev.writev_ext = blob_bs_dev_writev_ext; 184 b->bs_dev.read = blob_bs_dev_read; 185 b->bs_dev.readv = blob_bs_dev_readv; 186 b->bs_dev.readv_ext = blob_bs_dev_readv_ext; 187 b->bs_dev.write_zeroes = blob_bs_dev_write_zeroes; 188 b->bs_dev.unmap = blob_bs_dev_unmap; 189 b->bs_dev.is_zeroes = blob_bs_is_zeroes; 190 b->bs_dev.translate_lba = blob_bs_translate_lba; 191 b->bs_dev.is_degraded = blob_bs_is_degraded; 192 b->blob = blob; 193 194 return &b->bs_dev; 195 } 196