4 * Copyright (c) Intel Corporation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
34 #include "spdk/stdinc.h"
36 #include "blobstore.h"
39 #include "spdk/thread.h"
40 #include "spdk/queue.h"
42 #include "spdk_internal/log.h"
45 spdk_bs_call_cpl(struct spdk_bs_cpl
*cpl
, int bserrno
)
48 case SPDK_BS_CPL_TYPE_BS_BASIC
:
49 cpl
->u
.bs_basic
.cb_fn(cpl
->u
.bs_basic
.cb_arg
,
52 case SPDK_BS_CPL_TYPE_BS_HANDLE
:
53 cpl
->u
.bs_handle
.cb_fn(cpl
->u
.bs_handle
.cb_arg
,
57 case SPDK_BS_CPL_TYPE_BLOB_BASIC
:
58 cpl
->u
.blob_basic
.cb_fn(cpl
->u
.blob_basic
.cb_arg
,
61 case SPDK_BS_CPL_TYPE_BLOBID
:
62 cpl
->u
.blobid
.cb_fn(cpl
->u
.blobid
.cb_arg
,
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
,
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
,
76 case SPDK_BS_CPL_TYPE_NONE
:
77 /* this completion's callback is handled elsewhere */
83 spdk_bs_request_set_complete(struct spdk_bs_request_set
*set
)
85 struct spdk_bs_cpl cpl
= set
->cpl
;
86 int bserrno
= set
->bserrno
;
88 TAILQ_INSERT_TAIL(&set
->channel
->reqs
, set
, link
);
90 spdk_bs_call_cpl(&cpl
, bserrno
);
94 spdk_bs_sequence_completion(struct spdk_io_channel
*channel
, void *cb_arg
, int bserrno
)
96 struct spdk_bs_request_set
*set
= cb_arg
;
98 set
->bserrno
= bserrno
;
99 set
->u
.sequence
.cb_fn((spdk_bs_sequence_t
*)set
, set
->u
.sequence
.cb_arg
, bserrno
);
103 spdk_bs_sequence_start(struct spdk_io_channel
*_channel
,
104 struct spdk_bs_cpl
*cpl
)
106 struct spdk_bs_channel
*channel
;
107 struct spdk_bs_request_set
*set
;
109 channel
= spdk_io_channel_get_ctx(_channel
);
111 set
= TAILQ_FIRST(&channel
->reqs
);
115 TAILQ_REMOVE(&channel
->reqs
, set
, link
);
119 set
->channel
= channel
;
121 set
->cb_args
.cb_fn
= spdk_bs_sequence_completion
;
122 set
->cb_args
.cb_arg
= set
;
123 set
->cb_args
.channel
= channel
->dev_channel
;
125 return (spdk_bs_sequence_t
*)set
;
129 spdk_bs_sequence_read_bs_dev(spdk_bs_sequence_t
*seq
, struct spdk_bs_dev
*bs_dev
,
130 void *payload
, uint64_t lba
, uint32_t lba_count
,
131 spdk_bs_sequence_cpl cb_fn
, void *cb_arg
)
133 struct spdk_bs_request_set
*set
= (struct spdk_bs_request_set
*)seq
;
134 struct spdk_bs_channel
*channel
= set
->channel
;
136 SPDK_DEBUGLOG(SPDK_LOG_BLOB_RW
, "Reading %" PRIu32
" blocks from LBA %" PRIu64
"\n", lba_count
,
139 set
->u
.sequence
.cb_fn
= cb_fn
;
140 set
->u
.sequence
.cb_arg
= cb_arg
;
142 bs_dev
->read(bs_dev
, spdk_io_channel_from_ctx(channel
), payload
, lba
, lba_count
, &set
->cb_args
);
146 spdk_bs_sequence_read_dev(spdk_bs_sequence_t
*seq
, void *payload
,
147 uint64_t lba
, uint32_t lba_count
,
148 spdk_bs_sequence_cpl cb_fn
, void *cb_arg
)
150 struct spdk_bs_request_set
*set
= (struct spdk_bs_request_set
*)seq
;
151 struct spdk_bs_channel
*channel
= set
->channel
;
153 SPDK_DEBUGLOG(SPDK_LOG_BLOB_RW
, "Reading %" PRIu32
" blocks from LBA %" PRIu64
"\n", lba_count
,
156 set
->u
.sequence
.cb_fn
= cb_fn
;
157 set
->u
.sequence
.cb_arg
= cb_arg
;
159 channel
->dev
->read(channel
->dev
, channel
->dev_channel
, payload
, lba
, lba_count
, &set
->cb_args
);
163 spdk_bs_sequence_write_dev(spdk_bs_sequence_t
*seq
, void *payload
,
164 uint64_t lba
, uint32_t lba_count
,
165 spdk_bs_sequence_cpl cb_fn
, void *cb_arg
)
167 struct spdk_bs_request_set
*set
= (struct spdk_bs_request_set
*)seq
;
168 struct spdk_bs_channel
*channel
= set
->channel
;
170 SPDK_DEBUGLOG(SPDK_LOG_BLOB_RW
, "Writing %" PRIu32
" blocks from LBA %" PRIu64
"\n", lba_count
,
173 set
->u
.sequence
.cb_fn
= cb_fn
;
174 set
->u
.sequence
.cb_arg
= cb_arg
;
176 channel
->dev
->write(channel
->dev
, channel
->dev_channel
, payload
, lba
, lba_count
,
181 spdk_bs_sequence_readv_bs_dev(spdk_bs_sequence_t
*seq
, struct spdk_bs_dev
*bs_dev
,
182 struct iovec
*iov
, int iovcnt
, uint64_t lba
, uint32_t lba_count
,
183 spdk_bs_sequence_cpl cb_fn
, void *cb_arg
)
185 struct spdk_bs_request_set
*set
= (struct spdk_bs_request_set
*)seq
;
186 struct spdk_bs_channel
*channel
= set
->channel
;
188 SPDK_DEBUGLOG(SPDK_LOG_BLOB_RW
, "Reading %" PRIu32
" blocks from LBA %" PRIu64
"\n", lba_count
,
191 set
->u
.sequence
.cb_fn
= cb_fn
;
192 set
->u
.sequence
.cb_arg
= cb_arg
;
194 bs_dev
->readv(bs_dev
, spdk_io_channel_from_ctx(channel
), iov
, iovcnt
, lba
, lba_count
,
199 spdk_bs_sequence_readv_dev(spdk_bs_sequence_t
*seq
, struct iovec
*iov
, int iovcnt
,
200 uint64_t lba
, uint32_t lba_count
, spdk_bs_sequence_cpl cb_fn
, void *cb_arg
)
202 struct spdk_bs_request_set
*set
= (struct spdk_bs_request_set
*)seq
;
203 struct spdk_bs_channel
*channel
= set
->channel
;
205 SPDK_DEBUGLOG(SPDK_LOG_BLOB_RW
, "Reading %" PRIu32
" blocks from LBA %" PRIu64
"\n", lba_count
,
208 set
->u
.sequence
.cb_fn
= cb_fn
;
209 set
->u
.sequence
.cb_arg
= cb_arg
;
210 channel
->dev
->readv(channel
->dev
, channel
->dev_channel
, iov
, iovcnt
, lba
, lba_count
,
215 spdk_bs_sequence_writev_dev(spdk_bs_sequence_t
*seq
, struct iovec
*iov
, int iovcnt
,
216 uint64_t lba
, uint32_t lba_count
,
217 spdk_bs_sequence_cpl cb_fn
, void *cb_arg
)
219 struct spdk_bs_request_set
*set
= (struct spdk_bs_request_set
*)seq
;
220 struct spdk_bs_channel
*channel
= set
->channel
;
222 SPDK_DEBUGLOG(SPDK_LOG_BLOB_RW
, "Writing %" PRIu32
" blocks from LBA %" PRIu64
"\n", lba_count
,
225 set
->u
.sequence
.cb_fn
= cb_fn
;
226 set
->u
.sequence
.cb_arg
= cb_arg
;
228 channel
->dev
->writev(channel
->dev
, channel
->dev_channel
, iov
, iovcnt
, lba
, lba_count
,
233 spdk_bs_sequence_unmap_dev(spdk_bs_sequence_t
*seq
,
234 uint64_t lba
, uint32_t lba_count
,
235 spdk_bs_sequence_cpl cb_fn
, void *cb_arg
)
237 struct spdk_bs_request_set
*set
= (struct spdk_bs_request_set
*)seq
;
238 struct spdk_bs_channel
*channel
= set
->channel
;
240 SPDK_DEBUGLOG(SPDK_LOG_BLOB_RW
, "Unmapping %" PRIu32
" blocks at LBA %" PRIu64
"\n", lba_count
,
243 set
->u
.sequence
.cb_fn
= cb_fn
;
244 set
->u
.sequence
.cb_arg
= cb_arg
;
246 channel
->dev
->unmap(channel
->dev
, channel
->dev_channel
, lba
, lba_count
,
251 spdk_bs_sequence_write_zeroes_dev(spdk_bs_sequence_t
*seq
,
252 uint64_t lba
, uint32_t lba_count
,
253 spdk_bs_sequence_cpl cb_fn
, void *cb_arg
)
255 struct spdk_bs_request_set
*set
= (struct spdk_bs_request_set
*)seq
;
256 struct spdk_bs_channel
*channel
= set
->channel
;
258 SPDK_DEBUGLOG(SPDK_LOG_BLOB_RW
, "writing zeroes to %" PRIu32
" blocks at LBA %" PRIu64
"\n",
261 set
->u
.sequence
.cb_fn
= cb_fn
;
262 set
->u
.sequence
.cb_arg
= cb_arg
;
264 channel
->dev
->write_zeroes(channel
->dev
, channel
->dev_channel
, lba
, lba_count
,
269 spdk_bs_sequence_finish(spdk_bs_sequence_t
*seq
, int bserrno
)
272 seq
->bserrno
= bserrno
;
274 spdk_bs_request_set_complete((struct spdk_bs_request_set
*)seq
);
278 spdk_bs_user_op_sequence_finish(void *cb_arg
, int bserrno
)
280 spdk_bs_sequence_t
*seq
= cb_arg
;
282 spdk_bs_sequence_finish(seq
, bserrno
);
286 spdk_bs_batch_completion(struct spdk_io_channel
*_channel
,
287 void *cb_arg
, int bserrno
)
289 struct spdk_bs_request_set
*set
= cb_arg
;
291 set
->u
.batch
.outstanding_ops
--;
293 set
->bserrno
= bserrno
;
296 if (set
->u
.batch
.outstanding_ops
== 0 && set
->u
.batch
.batch_closed
) {
297 if (set
->u
.batch
.cb_fn
) {
298 set
->cb_args
.cb_fn
= spdk_bs_sequence_completion
;
299 set
->u
.batch
.cb_fn((spdk_bs_sequence_t
*)set
, set
->u
.batch
.cb_arg
, bserrno
);
301 spdk_bs_request_set_complete(set
);
307 spdk_bs_batch_open(struct spdk_io_channel
*_channel
,
308 struct spdk_bs_cpl
*cpl
)
310 struct spdk_bs_channel
*channel
;
311 struct spdk_bs_request_set
*set
;
313 channel
= spdk_io_channel_get_ctx(_channel
);
315 set
= TAILQ_FIRST(&channel
->reqs
);
319 TAILQ_REMOVE(&channel
->reqs
, set
, link
);
323 set
->channel
= channel
;
325 set
->u
.batch
.cb_fn
= NULL
;
326 set
->u
.batch
.cb_arg
= NULL
;
327 set
->u
.batch
.outstanding_ops
= 0;
328 set
->u
.batch
.batch_closed
= 0;
330 set
->cb_args
.cb_fn
= spdk_bs_batch_completion
;
331 set
->cb_args
.cb_arg
= set
;
332 set
->cb_args
.channel
= channel
->dev_channel
;
334 return (spdk_bs_batch_t
*)set
;
338 spdk_bs_batch_read_bs_dev(spdk_bs_batch_t
*batch
, struct spdk_bs_dev
*bs_dev
,
339 void *payload
, uint64_t lba
, uint32_t lba_count
)
341 struct spdk_bs_request_set
*set
= (struct spdk_bs_request_set
*)batch
;
342 struct spdk_bs_channel
*channel
= set
->channel
;
344 SPDK_DEBUGLOG(SPDK_LOG_BLOB_RW
, "Reading %" PRIu32
" blocks from LBA %" PRIu64
"\n", lba_count
,
347 set
->u
.batch
.outstanding_ops
++;
348 bs_dev
->read(bs_dev
, spdk_io_channel_from_ctx(channel
), payload
, lba
, lba_count
, &set
->cb_args
);
352 spdk_bs_batch_read_dev(spdk_bs_batch_t
*batch
, void *payload
,
353 uint64_t lba
, uint32_t lba_count
)
355 struct spdk_bs_request_set
*set
= (struct spdk_bs_request_set
*)batch
;
356 struct spdk_bs_channel
*channel
= set
->channel
;
358 SPDK_DEBUGLOG(SPDK_LOG_BLOB_RW
, "Reading %" PRIu32
" blocks from LBA %" PRIu64
"\n", lba_count
,
361 set
->u
.batch
.outstanding_ops
++;
362 channel
->dev
->read(channel
->dev
, channel
->dev_channel
, payload
, lba
, lba_count
, &set
->cb_args
);
366 spdk_bs_batch_write_dev(spdk_bs_batch_t
*batch
, void *payload
,
367 uint64_t lba
, uint32_t lba_count
)
369 struct spdk_bs_request_set
*set
= (struct spdk_bs_request_set
*)batch
;
370 struct spdk_bs_channel
*channel
= set
->channel
;
372 SPDK_DEBUGLOG(SPDK_LOG_BLOB_RW
, "Writing %" PRIu32
" blocks to LBA %" PRIu64
"\n", lba_count
, lba
);
374 set
->u
.batch
.outstanding_ops
++;
375 channel
->dev
->write(channel
->dev
, channel
->dev_channel
, payload
, lba
, lba_count
,
380 spdk_bs_batch_unmap_dev(spdk_bs_batch_t
*batch
,
381 uint64_t lba
, uint32_t lba_count
)
383 struct spdk_bs_request_set
*set
= (struct spdk_bs_request_set
*)batch
;
384 struct spdk_bs_channel
*channel
= set
->channel
;
386 SPDK_DEBUGLOG(SPDK_LOG_BLOB_RW
, "Unmapping %" PRIu32
" blocks at LBA %" PRIu64
"\n", lba_count
,
389 set
->u
.batch
.outstanding_ops
++;
390 channel
->dev
->unmap(channel
->dev
, channel
->dev_channel
, lba
, lba_count
,
395 spdk_bs_batch_write_zeroes_dev(spdk_bs_batch_t
*batch
,
396 uint64_t lba
, uint32_t lba_count
)
398 struct spdk_bs_request_set
*set
= (struct spdk_bs_request_set
*)batch
;
399 struct spdk_bs_channel
*channel
= set
->channel
;
401 SPDK_DEBUGLOG(SPDK_LOG_BLOB_RW
, "Zeroing %" PRIu32
" blocks at LBA %" PRIu64
"\n", lba_count
, lba
);
403 set
->u
.batch
.outstanding_ops
++;
404 channel
->dev
->write_zeroes(channel
->dev
, channel
->dev_channel
, lba
, lba_count
,
409 spdk_bs_batch_close(spdk_bs_batch_t
*batch
)
411 struct spdk_bs_request_set
*set
= (struct spdk_bs_request_set
*)batch
;
413 set
->u
.batch
.batch_closed
= 1;
415 if (set
->u
.batch
.outstanding_ops
== 0) {
416 if (set
->u
.batch
.cb_fn
) {
417 set
->cb_args
.cb_fn
= spdk_bs_sequence_completion
;
418 set
->u
.batch
.cb_fn((spdk_bs_sequence_t
*)set
, set
->u
.batch
.cb_arg
, set
->bserrno
);
420 spdk_bs_request_set_complete(set
);
426 spdk_bs_sequence_to_batch(spdk_bs_sequence_t
*seq
, spdk_bs_sequence_cpl cb_fn
, void *cb_arg
)
428 struct spdk_bs_request_set
*set
= (struct spdk_bs_request_set
*)seq
;
430 set
->u
.batch
.cb_fn
= cb_fn
;
431 set
->u
.batch
.cb_arg
= cb_arg
;
432 set
->u
.batch
.outstanding_ops
= 0;
433 set
->u
.batch
.batch_closed
= 0;
435 set
->cb_args
.cb_fn
= spdk_bs_batch_completion
;
441 spdk_bs_batch_to_sequence(spdk_bs_batch_t
*batch
)
443 struct spdk_bs_request_set
*set
= (struct spdk_bs_request_set
*)batch
;
445 set
->u
.batch
.outstanding_ops
++;
447 set
->cpl
.type
= SPDK_BS_CPL_TYPE_BLOB_BASIC
;
448 set
->cpl
.u
.blob_basic
.cb_fn
= spdk_bs_sequence_to_batch_completion
;
449 set
->cpl
.u
.blob_basic
.cb_arg
= set
;
452 set
->cb_args
.cb_fn
= spdk_bs_sequence_completion
;
453 set
->cb_args
.cb_arg
= set
;
454 set
->cb_args
.channel
= set
->channel
->dev_channel
;
456 return (spdk_bs_sequence_t
*)set
;
460 spdk_bs_user_op_alloc(struct spdk_io_channel
*_channel
, struct spdk_bs_cpl
*cpl
,
461 enum spdk_blob_op_type op_type
, struct spdk_blob
*blob
,
462 void *payload
, int iovcnt
, uint64_t offset
, uint64_t length
)
464 struct spdk_bs_channel
*channel
;
465 struct spdk_bs_request_set
*set
;
466 struct spdk_bs_user_op_args
*args
;
468 channel
= spdk_io_channel_get_ctx(_channel
);
470 set
= TAILQ_FIRST(&channel
->reqs
);
474 TAILQ_REMOVE(&channel
->reqs
, set
, link
);
477 set
->channel
= channel
;
479 args
= &set
->u
.user_op
;
481 args
->type
= op_type
;
482 args
->iovcnt
= iovcnt
;
484 args
->offset
= offset
;
485 args
->length
= length
;
486 args
->payload
= payload
;
488 return (spdk_bs_user_op_t
*)set
;
492 spdk_bs_user_op_execute(spdk_bs_user_op_t
*op
)
494 struct spdk_bs_request_set
*set
;
495 struct spdk_bs_user_op_args
*args
;
496 struct spdk_io_channel
*ch
;
498 set
= (struct spdk_bs_request_set
*)op
;
499 args
= &set
->u
.user_op
;
500 ch
= spdk_io_channel_from_ctx(set
->channel
);
502 switch (args
->type
) {
504 spdk_blob_io_read(args
->blob
, ch
, args
->payload
, args
->offset
, args
->length
,
505 set
->cpl
.u
.blob_basic
.cb_fn
, set
->cpl
.u
.blob_basic
.cb_arg
);
507 case SPDK_BLOB_WRITE
:
508 spdk_blob_io_write(args
->blob
, ch
, args
->payload
, args
->offset
, args
->length
,
509 set
->cpl
.u
.blob_basic
.cb_fn
, set
->cpl
.u
.blob_basic
.cb_arg
);
511 case SPDK_BLOB_UNMAP
:
512 spdk_blob_io_unmap(args
->blob
, ch
, args
->offset
, args
->length
,
513 set
->cpl
.u
.blob_basic
.cb_fn
, set
->cpl
.u
.blob_basic
.cb_arg
);
515 case SPDK_BLOB_WRITE_ZEROES
:
516 spdk_blob_io_write_zeroes(args
->blob
, ch
, args
->offset
, args
->length
,
517 set
->cpl
.u
.blob_basic
.cb_fn
, set
->cpl
.u
.blob_basic
.cb_arg
);
519 case SPDK_BLOB_READV
:
520 spdk_blob_io_readv(args
->blob
, ch
, args
->payload
, args
->iovcnt
,
521 args
->offset
, args
->length
,
522 set
->cpl
.u
.blob_basic
.cb_fn
, set
->cpl
.u
.blob_basic
.cb_arg
);
524 case SPDK_BLOB_WRITEV
:
525 spdk_blob_io_writev(args
->blob
, ch
, args
->payload
, args
->iovcnt
,
526 args
->offset
, args
->length
,
527 set
->cpl
.u
.blob_basic
.cb_fn
, set
->cpl
.u
.blob_basic
.cb_arg
);
530 TAILQ_INSERT_TAIL(&set
->channel
->reqs
, set
, link
);
534 spdk_bs_user_op_abort(spdk_bs_user_op_t
*op
)
536 struct spdk_bs_request_set
*set
;
538 set
= (struct spdk_bs_request_set
*)op
;
540 set
->cpl
.u
.blob_basic
.cb_fn(set
->cpl
.u
.blob_basic
.cb_arg
, -EIO
);
541 TAILQ_INSERT_TAIL(&set
->channel
->reqs
, set
, link
);
545 spdk_bs_sequence_to_batch_completion(void *cb_arg
, int bserrno
)
547 struct spdk_bs_request_set
*set
= (struct spdk_bs_request_set
*)cb_arg
;
549 set
->u
.batch
.outstanding_ops
--;
551 if (set
->u
.batch
.outstanding_ops
== 0 && set
->u
.batch
.batch_closed
) {
552 if (set
->cb_args
.cb_fn
) {
553 set
->cb_args
.cb_fn(set
->cb_args
.channel
, set
->cb_args
.cb_arg
, bserrno
);
558 SPDK_LOG_REGISTER_COMPONENT("blob_rw", SPDK_LOG_BLOB_RW
)