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_TRACELOG(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_TRACELOG(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_flush(spdk_bs_sequence_t *seq, 161 spdk_bs_sequence_cpl cb_fn, void *cb_arg) 162 { 163 struct spdk_bs_request_set *set = (struct spdk_bs_request_set *)seq; 164 struct spdk_bs_channel *channel = set->channel; 165 166 SPDK_TRACELOG(SPDK_TRACE_BLOB_RW, "Flushing\n"); 167 168 set->u.sequence.cb_fn = cb_fn; 169 set->u.sequence.cb_arg = cb_arg; 170 171 channel->dev->flush(channel->dev, channel->dev_channel, 172 &set->cb_args); 173 } 174 175 void 176 spdk_bs_sequence_unmap(spdk_bs_sequence_t *seq, 177 uint64_t lba, uint32_t lba_count, 178 spdk_bs_sequence_cpl cb_fn, void *cb_arg) 179 { 180 struct spdk_bs_request_set *set = (struct spdk_bs_request_set *)seq; 181 struct spdk_bs_channel *channel = set->channel; 182 183 SPDK_TRACELOG(SPDK_TRACE_BLOB_RW, "Unmapping %u blocks at LBA %lu\n", lba_count, lba); 184 185 set->u.sequence.cb_fn = cb_fn; 186 set->u.sequence.cb_arg = cb_arg; 187 188 channel->dev->unmap(channel->dev, channel->dev_channel, lba, lba_count, 189 &set->cb_args); 190 } 191 192 void 193 spdk_bs_sequence_finish(spdk_bs_sequence_t *seq, int bserrno) 194 { 195 if (bserrno != 0) { 196 seq->bserrno = bserrno; 197 } 198 spdk_bs_request_set_complete((struct spdk_bs_request_set *)seq); 199 } 200 201 static void 202 spdk_bs_batch_completion(struct spdk_io_channel *_channel, 203 void *cb_arg, int bserrno) 204 { 205 struct spdk_bs_request_set *set = cb_arg; 206 207 set->u.batch.outstanding_ops--; 208 if (bserrno != 0) { 209 set->bserrno = bserrno; 210 } 211 212 if (set->u.batch.outstanding_ops == 0 && set->u.batch.batch_closed) { 213 if (set->u.batch.cb_fn) { 214 set->cb_args.cb_fn = spdk_bs_sequence_completion; 215 set->u.batch.cb_fn((spdk_bs_sequence_t *)set, set->u.batch.cb_arg, bserrno); 216 } else { 217 spdk_bs_request_set_complete(set); 218 } 219 } 220 } 221 222 spdk_bs_batch_t * 223 spdk_bs_batch_open(struct spdk_io_channel *_channel, 224 struct spdk_bs_cpl *cpl) 225 { 226 struct spdk_bs_channel *channel; 227 struct spdk_bs_request_set *set; 228 229 channel = spdk_io_channel_get_ctx(_channel); 230 231 set = TAILQ_FIRST(&channel->reqs); 232 if (!set) { 233 return NULL; 234 } 235 TAILQ_REMOVE(&channel->reqs, set, link); 236 237 set->cpl = *cpl; 238 set->bserrno = 0; 239 set->channel = channel; 240 241 set->u.batch.cb_fn = NULL; 242 set->u.batch.cb_arg = NULL; 243 set->u.batch.outstanding_ops = 0; 244 set->u.batch.batch_closed = 0; 245 246 set->cb_args.cb_fn = spdk_bs_batch_completion; 247 set->cb_args.cb_arg = set; 248 set->cb_args.channel = channel->dev_channel; 249 250 return (spdk_bs_batch_t *)set; 251 } 252 253 void 254 spdk_bs_batch_read(spdk_bs_batch_t *batch, void *payload, 255 uint64_t lba, uint32_t lba_count) 256 { 257 struct spdk_bs_request_set *set = (struct spdk_bs_request_set *)batch; 258 struct spdk_bs_channel *channel = set->channel; 259 260 SPDK_TRACELOG(SPDK_TRACE_BLOB_RW, "Reading %u blocks from LBA %lu\n", lba_count, lba); 261 262 set->u.batch.outstanding_ops++; 263 channel->dev->read(channel->dev, channel->dev_channel, payload, lba, lba_count, 264 &set->cb_args); 265 } 266 267 void 268 spdk_bs_batch_write(spdk_bs_batch_t *batch, void *payload, 269 uint64_t lba, uint32_t lba_count) 270 { 271 struct spdk_bs_request_set *set = (struct spdk_bs_request_set *)batch; 272 struct spdk_bs_channel *channel = set->channel; 273 274 SPDK_TRACELOG(SPDK_TRACE_BLOB_RW, "Writing %u blocks to LBA %lu\n", lba_count, lba); 275 276 set->u.batch.outstanding_ops++; 277 channel->dev->write(channel->dev, channel->dev_channel, payload, lba, lba_count, 278 &set->cb_args); 279 } 280 281 void 282 spdk_bs_batch_flush(spdk_bs_batch_t *batch) 283 { 284 struct spdk_bs_request_set *set = (struct spdk_bs_request_set *)batch; 285 struct spdk_bs_channel *channel = set->channel; 286 287 SPDK_TRACELOG(SPDK_TRACE_BLOB_RW, "Flushing\n"); 288 289 set->u.batch.outstanding_ops++; 290 channel->dev->flush(channel->dev, channel->dev_channel, 291 &set->cb_args); 292 } 293 294 void 295 spdk_bs_batch_unmap(spdk_bs_batch_t *batch, 296 uint64_t lba, uint32_t lba_count) 297 { 298 struct spdk_bs_request_set *set = (struct spdk_bs_request_set *)batch; 299 struct spdk_bs_channel *channel = set->channel; 300 301 SPDK_TRACELOG(SPDK_TRACE_BLOB_RW, "Unmapping %u blocks at LBA %lu\n", lba_count, lba); 302 303 set->u.batch.outstanding_ops++; 304 channel->dev->unmap(channel->dev, channel->dev_channel, lba, lba_count, 305 &set->cb_args); 306 } 307 308 void 309 spdk_bs_batch_close(spdk_bs_batch_t *batch) 310 { 311 struct spdk_bs_request_set *set = (struct spdk_bs_request_set *)batch; 312 313 set->u.batch.batch_closed = 1; 314 315 if (set->u.batch.outstanding_ops == 0) { 316 if (set->u.batch.cb_fn) { 317 set->cb_args.cb_fn = spdk_bs_sequence_completion; 318 set->u.batch.cb_fn((spdk_bs_sequence_t *)set, set->u.batch.cb_arg, set->bserrno); 319 } else { 320 spdk_bs_request_set_complete(set); 321 } 322 } 323 } 324 325 spdk_bs_batch_t * 326 spdk_bs_sequence_to_batch(spdk_bs_sequence_t *seq, spdk_bs_sequence_cpl cb_fn, void *cb_arg) 327 { 328 struct spdk_bs_request_set *set = (struct spdk_bs_request_set *)seq; 329 330 set->u.batch.cb_fn = cb_fn; 331 set->u.batch.cb_arg = cb_arg; 332 set->u.batch.outstanding_ops = 0; 333 set->u.batch.batch_closed = 0; 334 335 set->cb_args.cb_fn = spdk_bs_batch_completion; 336 337 return set; 338 } 339 340 SPDK_LOG_REGISTER_TRACE_FLAG("blob_rw", SPDK_TRACE_BLOB_RW); 341