From b2503cb335374930c187b78b1c905d708bc4d512 Mon Sep 17 00:00:00 2001 From: Jim Harris Date: Wed, 29 Nov 2017 13:14:51 -0700 Subject: [PATCH] blob: add spdk_bs_user_op_t This allows a channel's request_set resources to be used for queuing I/O requests. This is needed for upcoming thin provisioning functionality, where we must queue I/O requests that need to allocate a cluster, if another cluster allocation is in progress. Signed-off-by: Jim Harris Change-Id: Ie8d3e799afc0b56bc95ba5ecab11253d8bc8608f Reviewed-on: https://review.gerrithub.io/395037 Tested-by: SPDK Automated Test System Reviewed-by: Ben Walker Reviewed-by: Daniel Verkamp --- lib/blob/blobstore.c | 8 +++++ lib/blob/blobstore.h | 2 ++ lib/blob/request.c | 85 ++++++++++++++++++++++++++++++++++++++++++++ lib/blob/request.h | 26 +++++++++++++- 4 files changed, 120 insertions(+), 1 deletion(-) diff --git a/lib/blob/blobstore.c b/lib/blob/blobstore.c index 6f60a181d..29310c90f 100644 --- a/lib/blob/blobstore.c +++ b/lib/blob/blobstore.c @@ -1233,6 +1233,10 @@ _spdk_blob_request_submit_op_split(struct spdk_io_channel *ch, struct spdk_blob case SPDK_BLOB_WRITE_ZEROES: spdk_bs_batch_write_zeroes_blob(batch, _blob, offset, op_length); break; + case SPDK_BLOB_READV: + case SPDK_BLOB_WRITEV: + SPDK_ERRLOG("readv/write not valid for %s\n", __func__); + break; } length -= op_length; @@ -1284,6 +1288,10 @@ _spdk_blob_request_submit_op_single(struct spdk_io_channel *_ch, struct spdk_blo case SPDK_BLOB_WRITE_ZEROES: spdk_bs_batch_write_zeroes_dev(batch, lba, lba_count); break; + case SPDK_BLOB_READV: + case SPDK_BLOB_WRITEV: + SPDK_ERRLOG("readv/write not valid for %s\n", __func__); + break; } spdk_bs_batch_close(batch); diff --git a/lib/blob/blobstore.h b/lib/blob/blobstore.h index 5879f6570..4b11d075b 100644 --- a/lib/blob/blobstore.h +++ b/lib/blob/blobstore.h @@ -188,6 +188,8 @@ enum spdk_blob_op_type { SPDK_BLOB_READ, SPDK_BLOB_UNMAP, SPDK_BLOB_WRITE_ZEROES, + SPDK_BLOB_WRITEV, + SPDK_BLOB_READV, }; /* On-Disk Data Structures diff --git a/lib/blob/request.c b/lib/blob/request.c index a26c6dec2..0405c5132 100644 --- a/lib/blob/request.c +++ b/lib/blob/request.c @@ -470,4 +470,89 @@ spdk_bs_sequence_to_batch(spdk_bs_sequence_t *seq, spdk_bs_sequence_cpl cb_fn, v return set; } +spdk_bs_user_op_t * +spdk_bs_user_op_alloc(struct spdk_io_channel *_channel, struct spdk_bs_cpl *cpl, + enum spdk_blob_op_type op_type, struct spdk_blob *blob, + void *payload, int iovcnt, uint64_t offset, uint64_t length) +{ + struct spdk_bs_channel *channel; + struct spdk_bs_request_set *set; + struct spdk_bs_user_op_args *args; + + channel = spdk_io_channel_get_ctx(_channel); + + set = TAILQ_FIRST(&channel->reqs); + if (!set) { + return NULL; + } + TAILQ_REMOVE(&channel->reqs, set, link); + + set->cpl = *cpl; + set->channel = channel; + + args = &set->u.user_op; + + args->type = op_type; + args->iovcnt = 0; + args->blob = blob; + args->offset = offset; + args->length = length; + args->payload = payload; + + return (spdk_bs_user_op_t *)set; +} + +void +spdk_bs_user_op_execute(spdk_bs_user_op_t *op) +{ + struct spdk_bs_request_set *set; + struct spdk_bs_user_op_args *args; + struct spdk_io_channel *ch; + + set = (struct spdk_bs_request_set *)op; + args = &set->u.user_op; + ch = spdk_io_channel_from_ctx(set->channel); + + switch (args->type) { + case SPDK_BLOB_READ: + spdk_bs_io_read_blob(args->blob, ch, args->payload, args->offset, args->length, + set->cpl.u.blob_basic.cb_fn, set->cpl.u.blob_basic.cb_arg); + break; + case SPDK_BLOB_WRITE: + spdk_bs_io_write_blob(args->blob, ch, args->payload, args->offset, args->length, + set->cpl.u.blob_basic.cb_fn, set->cpl.u.blob_basic.cb_arg); + break; + case SPDK_BLOB_UNMAP: + spdk_bs_io_unmap_blob(args->blob, ch, args->offset, args->length, + set->cpl.u.blob_basic.cb_fn, set->cpl.u.blob_basic.cb_arg); + break; + case SPDK_BLOB_WRITE_ZEROES: + spdk_bs_io_write_zeroes_blob(args->blob, ch, args->offset, args->length, + set->cpl.u.blob_basic.cb_fn, set->cpl.u.blob_basic.cb_arg); + break; + case SPDK_BLOB_READV: + spdk_bs_io_readv_blob(args->blob, ch, args->payload, args->iovcnt, + args->offset, args->length, + set->cpl.u.blob_basic.cb_fn, set->cpl.u.blob_basic.cb_arg); + break; + case SPDK_BLOB_WRITEV: + spdk_bs_io_writev_blob(args->blob, ch, args->payload, args->iovcnt, + args->offset, args->length, + set->cpl.u.blob_basic.cb_fn, set->cpl.u.blob_basic.cb_arg); + break; + } + TAILQ_INSERT_TAIL(&set->channel->reqs, set, link); +} + +void +spdk_bs_user_op_abort(spdk_bs_user_op_t *op) +{ + struct spdk_bs_request_set *set; + + set = (struct spdk_bs_request_set *)op; + + set->cpl.u.blob_basic.cb_fn(set->cpl.u.blob_basic.cb_arg, -EIO); + TAILQ_INSERT_TAIL(&set->channel->reqs, set, link); +} + SPDK_LOG_REGISTER_COMPONENT("blob_rw", SPDK_LOG_BLOB_RW) diff --git a/lib/blob/request.h b/lib/blob/request.h index c6f2941fa..f23fdb3fa 100644 --- a/lib/blob/request.h +++ b/lib/blob/request.h @@ -48,6 +48,8 @@ enum spdk_bs_cpl_type { SPDK_BS_CPL_TYPE_NESTED_SEQUENCE, }; +enum spdk_blob_op_type; + struct spdk_bs_request_set; /* Use a sequence to submit a set of requests serially */ @@ -56,6 +58,9 @@ typedef struct spdk_bs_request_set spdk_bs_sequence_t; /* Use a batch to submit a set of requests in parallel */ typedef struct spdk_bs_request_set spdk_bs_batch_t; +/* Use a user_op to queue a user operation for later execution */ +typedef struct spdk_bs_request_set spdk_bs_user_op_t; + typedef void (*spdk_bs_nested_seq_complete)(void *cb_arg, spdk_bs_sequence_t *parent, int bserrno); struct spdk_bs_cpl { @@ -100,7 +105,7 @@ struct spdk_bs_cpl { typedef void (*spdk_bs_sequence_cpl)(spdk_bs_sequence_t *sequence, void *cb_arg, int bserrno); -/* A generic request set. Can be a sequence or a batch. */ +/* A generic request set. Can be a sequence, batch or a user_op. */ struct spdk_bs_request_set { struct spdk_bs_cpl cpl; @@ -122,6 +127,17 @@ struct spdk_bs_request_set { spdk_bs_sequence_cpl cb_fn; void *cb_arg; } batch; + + struct spdk_bs_user_op_args { + int type; + int iovcnt; + struct spdk_blob *blob; + uint64_t offset; + uint64_t length; + spdk_blob_op_complete cb_fn; + void *cb_arg; + void *payload; /* cast to iov for readv/writev */ + } user_op; } u; TAILQ_ENTRY(spdk_bs_request_set) link; @@ -202,4 +218,12 @@ spdk_bs_batch_t *spdk_bs_sequence_to_batch(spdk_bs_sequence_t *seq, spdk_bs_sequence_cpl cb_fn, void *cb_arg); +spdk_bs_user_op_t *spdk_bs_user_op_alloc(struct spdk_io_channel *channel, struct spdk_bs_cpl *cpl, + enum spdk_blob_op_type op_type, struct spdk_blob *blob, + void *payload, int iovcnt, uint64_t offset, uint64_t length); + +void spdk_bs_user_op_execute(spdk_bs_user_op_t *op); + +void spdk_bs_user_op_abort(spdk_bs_user_op_t *op); + #endif