1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/stdinc.h" 35 36 #include "blobstore.h" 37 #include "request.h" 38 39 #include "spdk/io_channel.h" 40 #include "spdk/queue.h" 41 42 #include "spdk_internal/log.h" 43 44 void 45 spdk_bs_call_cpl(struct spdk_bs_cpl *cpl, int bserrno) 46 { 47 switch (cpl->type) { 48 case SPDK_BS_CPL_TYPE_BS_BASIC: 49 cpl->u.bs_basic.cb_fn(cpl->u.bs_basic.cb_arg, 50 bserrno); 51 break; 52 case SPDK_BS_CPL_TYPE_BS_HANDLE: 53 cpl->u.bs_handle.cb_fn(cpl->u.bs_handle.cb_arg, 54 cpl->u.bs_handle.bs, 55 bserrno); 56 break; 57 case SPDK_BS_CPL_TYPE_BLOB_BASIC: 58 cpl->u.blob_basic.cb_fn(cpl->u.blob_basic.cb_arg, 59 bserrno); 60 break; 61 case SPDK_BS_CPL_TYPE_BLOBID: 62 cpl->u.blobid.cb_fn(cpl->u.blobid.cb_arg, 63 cpl->u.blobid.blobid, 64 bserrno); 65 break; 66 case SPDK_BS_CPL_TYPE_BLOB_HANDLE: 67 cpl->u.blob_handle.cb_fn(cpl->u.blob_handle.cb_arg, 68 cpl->u.blob_handle.blob, 69 bserrno); 70 break; 71 case SPDK_BS_CPL_TYPE_NESTED_SEQUENCE: 72 cpl->u.nested_seq.cb_fn(cpl->u.nested_seq.cb_arg, 73 cpl->u.nested_seq.parent, 74 bserrno); 75 break; 76 } 77 } 78 79 static void 80 spdk_bs_request_set_complete(struct spdk_bs_request_set *set) 81 { 82 struct spdk_bs_cpl cpl = set->cpl; 83 int bserrno = set->bserrno; 84 85 TAILQ_INSERT_TAIL(&set->channel->reqs, set, link); 86 87 spdk_bs_call_cpl(&cpl, bserrno); 88 } 89 90 static void 91 spdk_bs_sequence_completion(struct spdk_io_channel *channel, void *cb_arg, int bserrno) 92 { 93 struct spdk_bs_request_set *set = cb_arg; 94 95 set->bserrno = bserrno; 96 set->u.sequence.cb_fn((spdk_bs_sequence_t *)set, set->u.sequence.cb_arg, bserrno); 97 } 98 99 spdk_bs_sequence_t * 100 spdk_bs_sequence_start(struct spdk_io_channel *_channel, 101 struct spdk_bs_cpl *cpl) 102 { 103 struct spdk_bs_channel *channel; 104 struct spdk_bs_request_set *set; 105 106 channel = spdk_io_channel_get_ctx(_channel); 107 108 set = TAILQ_FIRST(&channel->reqs); 109 if (!set) { 110 return NULL; 111 } 112 TAILQ_REMOVE(&channel->reqs, set, link); 113 114 set->cpl = *cpl; 115 set->bserrno = 0; 116 set->channel = channel; 117 118 set->cb_args.cb_fn = spdk_bs_sequence_completion; 119 set->cb_args.cb_arg = set; 120 set->cb_args.channel = channel->dev_channel; 121 122 return (spdk_bs_sequence_t *)set; 123 } 124 125 void 126 spdk_bs_sequence_read(spdk_bs_sequence_t *seq, void *payload, 127 uint64_t lba, uint32_t lba_count, 128 spdk_bs_sequence_cpl cb_fn, void *cb_arg) 129 { 130 struct spdk_bs_request_set *set = (struct spdk_bs_request_set *)seq; 131 struct spdk_bs_channel *channel = set->channel; 132 133 SPDK_DEBUGLOG(SPDK_TRACE_BLOB_RW, "Reading %u blocks from LBA %lu\n", lba_count, lba); 134 135 set->u.sequence.cb_fn = cb_fn; 136 set->u.sequence.cb_arg = cb_arg; 137 138 channel->dev->read(channel->dev, channel->dev_channel, payload, lba, lba_count, 139 &set->cb_args); 140 } 141 142 void 143 spdk_bs_sequence_write(spdk_bs_sequence_t *seq, void *payload, 144 uint64_t lba, uint32_t lba_count, 145 spdk_bs_sequence_cpl cb_fn, void *cb_arg) 146 { 147 struct spdk_bs_request_set *set = (struct spdk_bs_request_set *)seq; 148 struct spdk_bs_channel *channel = set->channel; 149 150 SPDK_DEBUGLOG(SPDK_TRACE_BLOB_RW, "Writing %u blocks to LBA %lu\n", lba_count, lba); 151 152 set->u.sequence.cb_fn = cb_fn; 153 set->u.sequence.cb_arg = cb_arg; 154 155 channel->dev->write(channel->dev, channel->dev_channel, payload, lba, lba_count, 156 &set->cb_args); 157 } 158 159 void 160 spdk_bs_sequence_readv(spdk_bs_sequence_t *seq, struct iovec *iov, int iovcnt, 161 uint64_t lba, uint32_t lba_count, 162 spdk_bs_sequence_cpl cb_fn, void *cb_arg) 163 { 164 struct spdk_bs_request_set *set = (struct spdk_bs_request_set *)seq; 165 struct spdk_bs_channel *channel = set->channel; 166 167 SPDK_DEBUGLOG(SPDK_TRACE_BLOB_RW, "Reading %u blocks from LBA %lu\n", lba_count, lba); 168 169 set->u.sequence.cb_fn = cb_fn; 170 set->u.sequence.cb_arg = cb_arg; 171 172 channel->dev->readv(channel->dev, channel->dev_channel, iov, iovcnt, lba, lba_count, 173 &set->cb_args); 174 } 175 176 void 177 spdk_bs_sequence_writev(spdk_bs_sequence_t *seq, struct iovec *iov, int iovcnt, 178 uint64_t lba, uint32_t lba_count, 179 spdk_bs_sequence_cpl cb_fn, void *cb_arg) 180 { 181 struct spdk_bs_request_set *set = (struct spdk_bs_request_set *)seq; 182 struct spdk_bs_channel *channel = set->channel; 183 184 SPDK_DEBUGLOG(SPDK_TRACE_BLOB_RW, "Writing %u blocks to LBA %lu\n", lba_count, lba); 185 186 set->u.sequence.cb_fn = cb_fn; 187 set->u.sequence.cb_arg = cb_arg; 188 189 channel->dev->writev(channel->dev, channel->dev_channel, iov, iovcnt, lba, lba_count, 190 &set->cb_args); 191 } 192 193 void 194 spdk_bs_sequence_flush(spdk_bs_sequence_t *seq, 195 spdk_bs_sequence_cpl cb_fn, void *cb_arg) 196 { 197 struct spdk_bs_request_set *set = (struct spdk_bs_request_set *)seq; 198 struct spdk_bs_channel *channel = set->channel; 199 200 SPDK_DEBUGLOG(SPDK_TRACE_BLOB_RW, "Flushing\n"); 201 202 set->u.sequence.cb_fn = cb_fn; 203 set->u.sequence.cb_arg = cb_arg; 204 205 channel->dev->flush(channel->dev, channel->dev_channel, 206 &set->cb_args); 207 } 208 209 void 210 spdk_bs_sequence_unmap(spdk_bs_sequence_t *seq, 211 uint64_t lba, uint32_t lba_count, 212 spdk_bs_sequence_cpl cb_fn, void *cb_arg) 213 { 214 struct spdk_bs_request_set *set = (struct spdk_bs_request_set *)seq; 215 struct spdk_bs_channel *channel = set->channel; 216 217 SPDK_DEBUGLOG(SPDK_TRACE_BLOB_RW, "Unmapping %u blocks at LBA %lu\n", lba_count, lba); 218 219 set->u.sequence.cb_fn = cb_fn; 220 set->u.sequence.cb_arg = cb_arg; 221 222 channel->dev->unmap(channel->dev, channel->dev_channel, lba, lba_count, 223 &set->cb_args); 224 } 225 226 void 227 spdk_bs_sequence_finish(spdk_bs_sequence_t *seq, int bserrno) 228 { 229 if (bserrno != 0) { 230 seq->bserrno = bserrno; 231 } 232 spdk_bs_request_set_complete((struct spdk_bs_request_set *)seq); 233 } 234 235 static void 236 spdk_bs_batch_completion(struct spdk_io_channel *_channel, 237 void *cb_arg, int bserrno) 238 { 239 struct spdk_bs_request_set *set = cb_arg; 240 241 set->u.batch.outstanding_ops--; 242 if (bserrno != 0) { 243 set->bserrno = bserrno; 244 } 245 246 if (set->u.batch.outstanding_ops == 0 && set->u.batch.batch_closed) { 247 if (set->u.batch.cb_fn) { 248 set->cb_args.cb_fn = spdk_bs_sequence_completion; 249 set->u.batch.cb_fn((spdk_bs_sequence_t *)set, set->u.batch.cb_arg, bserrno); 250 } else { 251 spdk_bs_request_set_complete(set); 252 } 253 } 254 } 255 256 spdk_bs_batch_t * 257 spdk_bs_batch_open(struct spdk_io_channel *_channel, 258 struct spdk_bs_cpl *cpl) 259 { 260 struct spdk_bs_channel *channel; 261 struct spdk_bs_request_set *set; 262 263 channel = spdk_io_channel_get_ctx(_channel); 264 265 set = TAILQ_FIRST(&channel->reqs); 266 if (!set) { 267 return NULL; 268 } 269 TAILQ_REMOVE(&channel->reqs, set, link); 270 271 set->cpl = *cpl; 272 set->bserrno = 0; 273 set->channel = channel; 274 275 set->u.batch.cb_fn = NULL; 276 set->u.batch.cb_arg = NULL; 277 set->u.batch.outstanding_ops = 0; 278 set->u.batch.batch_closed = 0; 279 280 set->cb_args.cb_fn = spdk_bs_batch_completion; 281 set->cb_args.cb_arg = set; 282 set->cb_args.channel = channel->dev_channel; 283 284 return (spdk_bs_batch_t *)set; 285 } 286 287 void 288 spdk_bs_batch_read(spdk_bs_batch_t *batch, void *payload, 289 uint64_t lba, uint32_t lba_count) 290 { 291 struct spdk_bs_request_set *set = (struct spdk_bs_request_set *)batch; 292 struct spdk_bs_channel *channel = set->channel; 293 294 SPDK_DEBUGLOG(SPDK_TRACE_BLOB_RW, "Reading %u blocks from LBA %lu\n", lba_count, lba); 295 296 set->u.batch.outstanding_ops++; 297 channel->dev->read(channel->dev, channel->dev_channel, payload, lba, lba_count, 298 &set->cb_args); 299 } 300 301 void 302 spdk_bs_batch_write(spdk_bs_batch_t *batch, void *payload, 303 uint64_t lba, uint32_t lba_count) 304 { 305 struct spdk_bs_request_set *set = (struct spdk_bs_request_set *)batch; 306 struct spdk_bs_channel *channel = set->channel; 307 308 SPDK_DEBUGLOG(SPDK_TRACE_BLOB_RW, "Writing %u blocks to LBA %lu\n", lba_count, lba); 309 310 set->u.batch.outstanding_ops++; 311 channel->dev->write(channel->dev, channel->dev_channel, payload, lba, lba_count, 312 &set->cb_args); 313 } 314 315 void 316 spdk_bs_batch_flush(spdk_bs_batch_t *batch) 317 { 318 struct spdk_bs_request_set *set = (struct spdk_bs_request_set *)batch; 319 struct spdk_bs_channel *channel = set->channel; 320 321 SPDK_DEBUGLOG(SPDK_TRACE_BLOB_RW, "Flushing\n"); 322 323 set->u.batch.outstanding_ops++; 324 channel->dev->flush(channel->dev, channel->dev_channel, 325 &set->cb_args); 326 } 327 328 void 329 spdk_bs_batch_unmap(spdk_bs_batch_t *batch, 330 uint64_t lba, uint32_t lba_count) 331 { 332 struct spdk_bs_request_set *set = (struct spdk_bs_request_set *)batch; 333 struct spdk_bs_channel *channel = set->channel; 334 335 SPDK_DEBUGLOG(SPDK_TRACE_BLOB_RW, "Unmapping %u blocks at LBA %lu\n", lba_count, lba); 336 337 set->u.batch.outstanding_ops++; 338 channel->dev->unmap(channel->dev, channel->dev_channel, lba, lba_count, 339 &set->cb_args); 340 } 341 342 void 343 spdk_bs_batch_close(spdk_bs_batch_t *batch) 344 { 345 struct spdk_bs_request_set *set = (struct spdk_bs_request_set *)batch; 346 347 set->u.batch.batch_closed = 1; 348 349 if (set->u.batch.outstanding_ops == 0) { 350 if (set->u.batch.cb_fn) { 351 set->cb_args.cb_fn = spdk_bs_sequence_completion; 352 set->u.batch.cb_fn((spdk_bs_sequence_t *)set, set->u.batch.cb_arg, set->bserrno); 353 } else { 354 spdk_bs_request_set_complete(set); 355 } 356 } 357 } 358 359 spdk_bs_batch_t * 360 spdk_bs_sequence_to_batch(spdk_bs_sequence_t *seq, spdk_bs_sequence_cpl cb_fn, void *cb_arg) 361 { 362 struct spdk_bs_request_set *set = (struct spdk_bs_request_set *)seq; 363 364 set->u.batch.cb_fn = cb_fn; 365 set->u.batch.cb_arg = cb_arg; 366 set->u.batch.outstanding_ops = 0; 367 set->u.batch.batch_closed = 0; 368 369 set->cb_args.cb_fn = spdk_bs_batch_completion; 370 371 return set; 372 } 373 374 SPDK_LOG_REGISTER_TRACE_FLAG("blob_rw", SPDK_TRACE_BLOB_RW); 375