xref: /spdk/lib/blob/request.c (revision c6c1234de9e0015e670dd0b51bf6ce39ee0e07bd)
1488570ebSJim Harris /*   SPDX-License-Identifier: BSD-3-Clause
2a6dbe372Spaul luse  *   Copyright (C) 2017 Intel Corporation.
3d89352a9SBen Walker  *   All rights reserved.
431c2852bSMike Gerdts  *   Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
5d89352a9SBen Walker  */
6d89352a9SBen Walker 
7b961d9ccSBen Walker #include "spdk/stdinc.h"
8d89352a9SBen Walker 
9d89352a9SBen Walker #include "blobstore.h"
10d89352a9SBen Walker #include "request.h"
11d89352a9SBen Walker 
12a83f91c2SBen Walker #include "spdk/thread.h"
13d89352a9SBen Walker #include "spdk/queue.h"
14*c6c1234dSxupeng-mingtu #include "spdk/trace.h"
15d89352a9SBen Walker 
16*c6c1234dSxupeng-mingtu #include "spdk_internal/trace_defs.h"
174e8e97c8STomasz Zawadzki #include "spdk/log.h"
18d89352a9SBen Walker 
19d89352a9SBen Walker void
20ad7fdd12SSeth Howell bs_call_cpl(struct spdk_bs_cpl *cpl, int bserrno)
21d89352a9SBen Walker {
22d89352a9SBen Walker 	switch (cpl->type) {
23d89352a9SBen Walker 	case SPDK_BS_CPL_TYPE_BS_BASIC:
24d89352a9SBen Walker 		cpl->u.bs_basic.cb_fn(cpl->u.bs_basic.cb_arg,
25d89352a9SBen Walker 				      bserrno);
26d89352a9SBen Walker 		break;
27d89352a9SBen Walker 	case SPDK_BS_CPL_TYPE_BS_HANDLE:
28d89352a9SBen Walker 		cpl->u.bs_handle.cb_fn(cpl->u.bs_handle.cb_arg,
296ff6f6d6SJim Harris 				       bserrno == 0 ? cpl->u.bs_handle.bs : NULL,
30d89352a9SBen Walker 				       bserrno);
31d89352a9SBen Walker 		break;
32d89352a9SBen Walker 	case SPDK_BS_CPL_TYPE_BLOB_BASIC:
33d89352a9SBen Walker 		cpl->u.blob_basic.cb_fn(cpl->u.blob_basic.cb_arg,
34d89352a9SBen Walker 					bserrno);
35d89352a9SBen Walker 		break;
36d89352a9SBen Walker 	case SPDK_BS_CPL_TYPE_BLOBID:
37d89352a9SBen Walker 		cpl->u.blobid.cb_fn(cpl->u.blobid.cb_arg,
386ff6f6d6SJim Harris 				    bserrno == 0 ? cpl->u.blobid.blobid : SPDK_BLOBID_INVALID,
39d89352a9SBen Walker 				    bserrno);
40d89352a9SBen Walker 		break;
41d89352a9SBen Walker 	case SPDK_BS_CPL_TYPE_BLOB_HANDLE:
42d89352a9SBen Walker 		cpl->u.blob_handle.cb_fn(cpl->u.blob_handle.cb_arg,
436ff6f6d6SJim Harris 					 bserrno == 0 ? cpl->u.blob_handle.blob : NULL,
44d89352a9SBen Walker 					 bserrno);
45d89352a9SBen Walker 		break;
46d89352a9SBen Walker 	case SPDK_BS_CPL_TYPE_NESTED_SEQUENCE:
47d89352a9SBen Walker 		cpl->u.nested_seq.cb_fn(cpl->u.nested_seq.cb_arg,
48d89352a9SBen Walker 					cpl->u.nested_seq.parent,
49d89352a9SBen Walker 					bserrno);
50d89352a9SBen Walker 		break;
51130d278aSPaul Luse 	case SPDK_BS_CPL_TYPE_NONE:
52130d278aSPaul Luse 		/* this completion's callback is handled elsewhere */
53130d278aSPaul Luse 		break;
54d89352a9SBen Walker 	}
55d89352a9SBen Walker }
56d89352a9SBen Walker 
57d89352a9SBen Walker static void
583456377bSSeth Howell bs_request_set_complete(struct spdk_bs_request_set *set)
59d89352a9SBen Walker {
60d89352a9SBen Walker 	struct spdk_bs_cpl cpl = set->cpl;
61d89352a9SBen Walker 	int bserrno = set->bserrno;
62d89352a9SBen Walker 
63*c6c1234dSxupeng-mingtu 	spdk_trace_record(TRACE_BLOB_REQ_SET_COMPLETE, 0, 0, (uintptr_t)&set->cb_args,
64*c6c1234dSxupeng-mingtu 			  (uintptr_t)set->cpl.u.blob_basic.cb_arg);
65*c6c1234dSxupeng-mingtu 
66d89352a9SBen Walker 	TAILQ_INSERT_TAIL(&set->channel->reqs, set, link);
67d89352a9SBen Walker 
68ad7fdd12SSeth Howell 	bs_call_cpl(&cpl, bserrno);
69d89352a9SBen Walker }
70d89352a9SBen Walker 
71d89352a9SBen Walker static void
723456377bSSeth Howell bs_sequence_completion(struct spdk_io_channel *channel, void *cb_arg, int bserrno)
73d89352a9SBen Walker {
74d89352a9SBen Walker 	struct spdk_bs_request_set *set = cb_arg;
75d89352a9SBen Walker 
76d89352a9SBen Walker 	set->bserrno = bserrno;
77d89352a9SBen Walker 	set->u.sequence.cb_fn((spdk_bs_sequence_t *)set, set->u.sequence.cb_arg, bserrno);
78d89352a9SBen Walker }
79d89352a9SBen Walker 
80b47cee6cSMike Gerdts static inline spdk_bs_sequence_t *
81b47cee6cSMike Gerdts bs_sequence_start(struct spdk_io_channel *_channel, struct spdk_bs_cpl *cpl,
82b47cee6cSMike Gerdts 		  struct spdk_io_channel *back_channel)
83d89352a9SBen Walker {
84d89352a9SBen Walker 	struct spdk_bs_channel		*channel;
85d89352a9SBen Walker 	struct spdk_bs_request_set	*set;
86d89352a9SBen Walker 
87d89352a9SBen Walker 	channel = spdk_io_channel_get_ctx(_channel);
8804ce0e12Syidong0635 	assert(channel != NULL);
89d89352a9SBen Walker 	set = TAILQ_FIRST(&channel->reqs);
90d89352a9SBen Walker 	if (!set) {
91d89352a9SBen Walker 		return NULL;
92d89352a9SBen Walker 	}
93d89352a9SBen Walker 	TAILQ_REMOVE(&channel->reqs, set, link);
94d89352a9SBen Walker 
95*c6c1234dSxupeng-mingtu 	spdk_trace_record(TRACE_BLOB_REQ_SET_START, 0, 0, (uintptr_t)&set->cb_args,
96*c6c1234dSxupeng-mingtu 			  (uintptr_t)cpl->u.blob_basic.cb_arg);
97*c6c1234dSxupeng-mingtu 
98d89352a9SBen Walker 	set->cpl = *cpl;
99d89352a9SBen Walker 	set->bserrno = 0;
100d89352a9SBen Walker 	set->channel = channel;
101b47cee6cSMike Gerdts 	set->back_channel = back_channel;
102d89352a9SBen Walker 
1033456377bSSeth Howell 	set->cb_args.cb_fn = bs_sequence_completion;
104d89352a9SBen Walker 	set->cb_args.cb_arg = set;
105d89352a9SBen Walker 	set->cb_args.channel = channel->dev_channel;
106a2360845SAlexey Marchuk 	set->ext_io_opts = NULL;
107d89352a9SBen Walker 
108d89352a9SBen Walker 	return (spdk_bs_sequence_t *)set;
109d89352a9SBen Walker }
110d89352a9SBen Walker 
1112948183fSMike Gerdts /* Use when performing IO directly on the blobstore (e.g. metadata - not a blob). */
1122948183fSMike Gerdts spdk_bs_sequence_t *
1132948183fSMike Gerdts bs_sequence_start_bs(struct spdk_io_channel *_channel, struct spdk_bs_cpl *cpl)
1142948183fSMike Gerdts {
115b47cee6cSMike Gerdts 	return bs_sequence_start(_channel, cpl, _channel);
1162948183fSMike Gerdts }
1172948183fSMike Gerdts 
1182948183fSMike Gerdts /* Use when performing IO on a blob. */
1192948183fSMike Gerdts spdk_bs_sequence_t *
1202948183fSMike Gerdts bs_sequence_start_blob(struct spdk_io_channel *_channel, struct spdk_bs_cpl *cpl,
1212948183fSMike Gerdts 		       struct spdk_blob *blob)
1222948183fSMike Gerdts {
123b47cee6cSMike Gerdts 	struct spdk_io_channel	*esnap_ch = _channel;
124b47cee6cSMike Gerdts 
125b47cee6cSMike Gerdts 	if (spdk_blob_is_esnap_clone(blob)) {
126b47cee6cSMike Gerdts 		esnap_ch = blob_esnap_get_io_channel(_channel, blob);
127b47cee6cSMike Gerdts 		if (esnap_ch == NULL) {
128b47cee6cSMike Gerdts 			/*
129b47cee6cSMike Gerdts 			 * The most likely reason we are here is because of some logic error
130b47cee6cSMike Gerdts 			 * elsewhere that caused channel allocations to fail. We could get here due
131b47cee6cSMike Gerdts 			 * to being out of memory as well. If we are out of memory, the process is
132b47cee6cSMike Gerdts 			 * this will be just one of many problems that this process will be having.
133b47cee6cSMike Gerdts 			 * Killing it off debug builds now due to logic errors is the right thing to
134b47cee6cSMike Gerdts 			 * do and killing it off due to ENOMEM is no big loss.
135b47cee6cSMike Gerdts 			 */
136b47cee6cSMike Gerdts 			assert(false);
137b47cee6cSMike Gerdts 			return NULL;
138b47cee6cSMike Gerdts 		}
139b47cee6cSMike Gerdts 	}
140b47cee6cSMike Gerdts 	return bs_sequence_start(_channel, cpl, esnap_ch);
1412948183fSMike Gerdts }
1422948183fSMike Gerdts 
143d89352a9SBen Walker void
144ad7fdd12SSeth Howell bs_sequence_read_bs_dev(spdk_bs_sequence_t *seq, struct spdk_bs_dev *bs_dev,
1450e917256SMaciej Szwed 			void *payload, uint64_t lba, uint32_t lba_count,
146d89352a9SBen Walker 			spdk_bs_sequence_cpl cb_fn, void *cb_arg)
147d89352a9SBen Walker {
148d89352a9SBen Walker 	struct spdk_bs_request_set	*set = (struct spdk_bs_request_set *)seq;
14931c2852bSMike Gerdts 	struct spdk_io_channel		*back_channel = set->back_channel;
150d89352a9SBen Walker 
1512172c432STomasz Zawadzki 	SPDK_DEBUGLOG(blob_rw, "Reading %" PRIu32 " blocks from LBA %" PRIu64 "\n", lba_count,
1523e717065STomasz Kulasek 		      lba);
153d89352a9SBen Walker 
154d89352a9SBen Walker 	set->u.sequence.cb_fn = cb_fn;
155d89352a9SBen Walker 	set->u.sequence.cb_arg = cb_arg;
156d89352a9SBen Walker 
15731c2852bSMike Gerdts 	bs_dev->read(bs_dev, back_channel, payload, lba, lba_count, &set->cb_args);
1580e917256SMaciej Szwed }
1590e917256SMaciej Szwed 
1600e917256SMaciej Szwed void
161ad7fdd12SSeth Howell bs_sequence_read_dev(spdk_bs_sequence_t *seq, void *payload,
1620e917256SMaciej Szwed 		     uint64_t lba, uint32_t lba_count,
1630e917256SMaciej Szwed 		     spdk_bs_sequence_cpl cb_fn, void *cb_arg)
1640e917256SMaciej Szwed {
1650e917256SMaciej Szwed 	struct spdk_bs_request_set      *set = (struct spdk_bs_request_set *)seq;
1660e917256SMaciej Szwed 	struct spdk_bs_channel       *channel = set->channel;
1670e917256SMaciej Szwed 
1682172c432STomasz Zawadzki 	SPDK_DEBUGLOG(blob_rw, "Reading %" PRIu32 " blocks from LBA %" PRIu64 "\n", lba_count,
1693e717065STomasz Kulasek 		      lba);
1703e717065STomasz Kulasek 
1714dc04dc6SPiotr Pelplinski 	set->u.sequence.cb_fn = cb_fn;
1724dc04dc6SPiotr Pelplinski 	set->u.sequence.cb_arg = cb_arg;
1734dc04dc6SPiotr Pelplinski 
1744dc04dc6SPiotr Pelplinski 	channel->dev->read(channel->dev, channel->dev_channel, payload, lba, lba_count, &set->cb_args);
175d89352a9SBen Walker }
176d89352a9SBen Walker 
177d89352a9SBen Walker void
178ad7fdd12SSeth Howell bs_sequence_write_dev(spdk_bs_sequence_t *seq, void *payload,
179d89352a9SBen Walker 		      uint64_t lba, uint32_t lba_count,
180d89352a9SBen Walker 		      spdk_bs_sequence_cpl cb_fn, void *cb_arg)
181d89352a9SBen Walker {
182d89352a9SBen Walker 	struct spdk_bs_request_set      *set = (struct spdk_bs_request_set *)seq;
183d89352a9SBen Walker 	struct spdk_bs_channel       *channel = set->channel;
184d89352a9SBen Walker 
1852172c432STomasz Zawadzki 	SPDK_DEBUGLOG(blob_rw, "Writing %" PRIu32 " blocks from LBA %" PRIu64 "\n", lba_count,
1863e717065STomasz Kulasek 		      lba);
187d89352a9SBen Walker 
188d89352a9SBen Walker 	set->u.sequence.cb_fn = cb_fn;
189d89352a9SBen Walker 	set->u.sequence.cb_arg = cb_arg;
190d89352a9SBen Walker 
191d89352a9SBen Walker 	channel->dev->write(channel->dev, channel->dev_channel, payload, lba, lba_count,
192d89352a9SBen Walker 			    &set->cb_args);
193d89352a9SBen Walker }
194d89352a9SBen Walker 
195d89352a9SBen Walker void
196ad7fdd12SSeth Howell bs_sequence_readv_bs_dev(spdk_bs_sequence_t *seq, struct spdk_bs_dev *bs_dev,
1970e917256SMaciej Szwed 			 struct iovec *iov, int iovcnt, uint64_t lba, uint32_t lba_count,
198179ed697SJim Harris 			 spdk_bs_sequence_cpl cb_fn, void *cb_arg)
199179ed697SJim Harris {
200179ed697SJim Harris 	struct spdk_bs_request_set      *set = (struct spdk_bs_request_set *)seq;
20131c2852bSMike Gerdts 	struct spdk_io_channel		*back_channel = set->back_channel;
202179ed697SJim Harris 
2032172c432STomasz Zawadzki 	SPDK_DEBUGLOG(blob_rw, "Reading %" PRIu32 " blocks from LBA %" PRIu64 "\n", lba_count,
2043e717065STomasz Kulasek 		      lba);
205179ed697SJim Harris 
206179ed697SJim Harris 	set->u.sequence.cb_fn = cb_fn;
207179ed697SJim Harris 	set->u.sequence.cb_arg = cb_arg;
208179ed697SJim Harris 
209a2360845SAlexey Marchuk 	if (set->ext_io_opts) {
210a2360845SAlexey Marchuk 		assert(bs_dev->readv_ext);
21131c2852bSMike Gerdts 		bs_dev->readv_ext(bs_dev, back_channel, iov, iovcnt, lba, lba_count,
212a2360845SAlexey Marchuk 				  &set->cb_args, set->ext_io_opts);
213a2360845SAlexey Marchuk 	} else {
21431c2852bSMike Gerdts 		bs_dev->readv(bs_dev, back_channel, iov, iovcnt, lba, lba_count, &set->cb_args);
215179ed697SJim Harris 	}
216a2360845SAlexey Marchuk }
217179ed697SJim Harris 
218179ed697SJim Harris void
219ad7fdd12SSeth Howell bs_sequence_readv_dev(spdk_bs_sequence_t *seq, struct iovec *iov, int iovcnt,
2200e917256SMaciej Szwed 		      uint64_t lba, uint32_t lba_count, spdk_bs_sequence_cpl cb_fn, void *cb_arg)
2210e917256SMaciej Szwed {
2220e917256SMaciej Szwed 	struct spdk_bs_request_set      *set = (struct spdk_bs_request_set *)seq;
2230e917256SMaciej Szwed 	struct spdk_bs_channel       *channel = set->channel;
2240e917256SMaciej Szwed 
2252172c432STomasz Zawadzki 	SPDK_DEBUGLOG(blob_rw, "Reading %" PRIu32 " blocks from LBA %" PRIu64 "\n", lba_count,
2263e717065STomasz Kulasek 		      lba);
2273e717065STomasz Kulasek 
2284dc04dc6SPiotr Pelplinski 	set->u.sequence.cb_fn = cb_fn;
2294dc04dc6SPiotr Pelplinski 	set->u.sequence.cb_arg = cb_arg;
230a2360845SAlexey Marchuk 	if (set->ext_io_opts) {
231a2360845SAlexey Marchuk 		assert(channel->dev->readv_ext);
232a2360845SAlexey Marchuk 		channel->dev->readv_ext(channel->dev, channel->dev_channel, iov, iovcnt, lba, lba_count,
233a2360845SAlexey Marchuk 					&set->cb_args, set->ext_io_opts);
234a2360845SAlexey Marchuk 	} else {
235a2360845SAlexey Marchuk 		channel->dev->readv(channel->dev, channel->dev_channel, iov, iovcnt, lba, lba_count, &set->cb_args);
236a2360845SAlexey Marchuk 	}
2370e917256SMaciej Szwed }
2380e917256SMaciej Szwed 
2390e917256SMaciej Szwed void
240ad7fdd12SSeth Howell bs_sequence_writev_dev(spdk_bs_sequence_t *seq, struct iovec *iov, int iovcnt,
241179ed697SJim Harris 		       uint64_t lba, uint32_t lba_count,
242179ed697SJim Harris 		       spdk_bs_sequence_cpl cb_fn, void *cb_arg)
243179ed697SJim Harris {
244179ed697SJim Harris 	struct spdk_bs_request_set      *set = (struct spdk_bs_request_set *)seq;
245179ed697SJim Harris 	struct spdk_bs_channel       *channel = set->channel;
246179ed697SJim Harris 
2472172c432STomasz Zawadzki 	SPDK_DEBUGLOG(blob_rw, "Writing %" PRIu32 " blocks from LBA %" PRIu64 "\n", lba_count,
2483e717065STomasz Kulasek 		      lba);
249179ed697SJim Harris 
250179ed697SJim Harris 	set->u.sequence.cb_fn = cb_fn;
251179ed697SJim Harris 	set->u.sequence.cb_arg = cb_arg;
252179ed697SJim Harris 
253a2360845SAlexey Marchuk 	if (set->ext_io_opts) {
254a2360845SAlexey Marchuk 		assert(channel->dev->writev_ext);
255a2360845SAlexey Marchuk 		channel->dev->writev_ext(channel->dev, channel->dev_channel, iov, iovcnt, lba, lba_count,
256a2360845SAlexey Marchuk 					 &set->cb_args, set->ext_io_opts);
257a2360845SAlexey Marchuk 	} else {
258179ed697SJim Harris 		channel->dev->writev(channel->dev, channel->dev_channel, iov, iovcnt, lba, lba_count,
259179ed697SJim Harris 				     &set->cb_args);
260179ed697SJim Harris 	}
261a2360845SAlexey Marchuk }
262179ed697SJim Harris 
263179ed697SJim Harris void
264ad7fdd12SSeth Howell bs_sequence_write_zeroes_dev(spdk_bs_sequence_t *seq,
265f01146aeSJim Harris 			     uint64_t lba, uint64_t lba_count,
2663f9cbe51SSeth Howell 			     spdk_bs_sequence_cpl cb_fn, void *cb_arg)
2673f9cbe51SSeth Howell {
2683f9cbe51SSeth Howell 	struct spdk_bs_request_set      *set = (struct spdk_bs_request_set *)seq;
2693f9cbe51SSeth Howell 	struct spdk_bs_channel       *channel = set->channel;
2703f9cbe51SSeth Howell 
271f01146aeSJim Harris 	SPDK_DEBUGLOG(blob_rw, "writing zeroes to %" PRIu64 " blocks at LBA %" PRIu64 "\n",
2723e717065STomasz Kulasek 		      lba_count, lba);
2733f9cbe51SSeth Howell 
2743f9cbe51SSeth Howell 	set->u.sequence.cb_fn = cb_fn;
2753f9cbe51SSeth Howell 	set->u.sequence.cb_arg = cb_arg;
2763f9cbe51SSeth Howell 
2773f9cbe51SSeth Howell 	channel->dev->write_zeroes(channel->dev, channel->dev_channel, lba, lba_count,
2783f9cbe51SSeth Howell 				   &set->cb_args);
2793f9cbe51SSeth Howell }
2803f9cbe51SSeth Howell 
2813f9cbe51SSeth Howell void
282b7bfa504SEvgeniy Kochetov bs_sequence_copy_dev(spdk_bs_sequence_t *seq, uint64_t dst_lba, uint64_t src_lba,
283b7bfa504SEvgeniy Kochetov 		     uint64_t lba_count, spdk_bs_sequence_cpl cb_fn, void *cb_arg)
284b7bfa504SEvgeniy Kochetov {
285b7bfa504SEvgeniy Kochetov 	struct spdk_bs_request_set *set = (struct spdk_bs_request_set *)seq;
286b7bfa504SEvgeniy Kochetov 	struct spdk_bs_channel     *channel = set->channel;
287b7bfa504SEvgeniy Kochetov 
288b7bfa504SEvgeniy Kochetov 	SPDK_DEBUGLOG(blob_rw, "Copying %" PRIu64 " blocks from LBA %" PRIu64 " to LBA %" PRIu64 "\n",
289b7bfa504SEvgeniy Kochetov 		      lba_count, src_lba, dst_lba);
290b7bfa504SEvgeniy Kochetov 
291b7bfa504SEvgeniy Kochetov 	set->u.sequence.cb_fn = cb_fn;
292b7bfa504SEvgeniy Kochetov 	set->u.sequence.cb_arg = cb_arg;
293b7bfa504SEvgeniy Kochetov 
294b7bfa504SEvgeniy Kochetov 	channel->dev->copy(channel->dev, channel->dev_channel, dst_lba, src_lba, lba_count, &set->cb_args);
295b7bfa504SEvgeniy Kochetov }
296b7bfa504SEvgeniy Kochetov 
297b7bfa504SEvgeniy Kochetov void
298ad7fdd12SSeth Howell bs_sequence_finish(spdk_bs_sequence_t *seq, int bserrno)
299d89352a9SBen Walker {
300d89352a9SBen Walker 	if (bserrno != 0) {
301d89352a9SBen Walker 		seq->bserrno = bserrno;
302d89352a9SBen Walker 	}
3033456377bSSeth Howell 	bs_request_set_complete((struct spdk_bs_request_set *)seq);
304d89352a9SBen Walker }
305d89352a9SBen Walker 
3064132ac52SMaciej Szwed void
307ad7fdd12SSeth Howell bs_user_op_sequence_finish(void *cb_arg, int bserrno)
3084132ac52SMaciej Szwed {
3094132ac52SMaciej Szwed 	spdk_bs_sequence_t *seq = cb_arg;
3104132ac52SMaciej Szwed 
311ad7fdd12SSeth Howell 	bs_sequence_finish(seq, bserrno);
3124132ac52SMaciej Szwed }
3134132ac52SMaciej Szwed 
314d89352a9SBen Walker static void
3153456377bSSeth Howell bs_batch_completion(struct spdk_io_channel *_channel,
316d89352a9SBen Walker 		    void *cb_arg, int bserrno)
317d89352a9SBen Walker {
318d89352a9SBen Walker 	struct spdk_bs_request_set	*set = cb_arg;
319d89352a9SBen Walker 
320d89352a9SBen Walker 	set->u.batch.outstanding_ops--;
321d89352a9SBen Walker 	if (bserrno != 0) {
322d89352a9SBen Walker 		set->bserrno = bserrno;
323d89352a9SBen Walker 	}
324d89352a9SBen Walker 
325d89352a9SBen Walker 	if (set->u.batch.outstanding_ops == 0 && set->u.batch.batch_closed) {
326d89352a9SBen Walker 		if (set->u.batch.cb_fn) {
3273456377bSSeth Howell 			set->cb_args.cb_fn = bs_sequence_completion;
328d89352a9SBen Walker 			set->u.batch.cb_fn((spdk_bs_sequence_t *)set, set->u.batch.cb_arg, bserrno);
329d89352a9SBen Walker 		} else {
3303456377bSSeth Howell 			bs_request_set_complete(set);
331d89352a9SBen Walker 		}
332d89352a9SBen Walker 	}
333d89352a9SBen Walker }
334d89352a9SBen Walker 
335d89352a9SBen Walker spdk_bs_batch_t *
336b47cee6cSMike Gerdts bs_batch_open(struct spdk_io_channel *_channel, struct spdk_bs_cpl *cpl, struct spdk_blob *blob)
337d89352a9SBen Walker {
338d89352a9SBen Walker 	struct spdk_bs_channel		*channel;
339d89352a9SBen Walker 	struct spdk_bs_request_set	*set;
340b47cee6cSMike Gerdts 	struct spdk_io_channel		*back_channel = _channel;
341b47cee6cSMike Gerdts 
342b47cee6cSMike Gerdts 	if (spdk_blob_is_esnap_clone(blob)) {
343b47cee6cSMike Gerdts 		back_channel = blob_esnap_get_io_channel(_channel, blob);
344b47cee6cSMike Gerdts 		if (back_channel == NULL) {
345b47cee6cSMike Gerdts 			return NULL;
346b47cee6cSMike Gerdts 		}
347b47cee6cSMike Gerdts 	}
348d89352a9SBen Walker 
349d89352a9SBen Walker 	channel = spdk_io_channel_get_ctx(_channel);
35004ce0e12Syidong0635 	assert(channel != NULL);
351d89352a9SBen Walker 	set = TAILQ_FIRST(&channel->reqs);
352d89352a9SBen Walker 	if (!set) {
353d89352a9SBen Walker 		return NULL;
354d89352a9SBen Walker 	}
355d89352a9SBen Walker 	TAILQ_REMOVE(&channel->reqs, set, link);
356d89352a9SBen Walker 
357*c6c1234dSxupeng-mingtu 	spdk_trace_record(TRACE_BLOB_REQ_SET_START, 0, 0, (uintptr_t)&set->cb_args,
358*c6c1234dSxupeng-mingtu 			  (uintptr_t)cpl->u.blob_basic.cb_arg);
359*c6c1234dSxupeng-mingtu 
360d89352a9SBen Walker 	set->cpl = *cpl;
361d89352a9SBen Walker 	set->bserrno = 0;
362d89352a9SBen Walker 	set->channel = channel;
363b47cee6cSMike Gerdts 	set->back_channel = back_channel;
364d89352a9SBen Walker 
365d89352a9SBen Walker 	set->u.batch.cb_fn = NULL;
366d89352a9SBen Walker 	set->u.batch.cb_arg = NULL;
367d89352a9SBen Walker 	set->u.batch.outstanding_ops = 0;
368d89352a9SBen Walker 	set->u.batch.batch_closed = 0;
369d89352a9SBen Walker 
3703456377bSSeth Howell 	set->cb_args.cb_fn = bs_batch_completion;
371d89352a9SBen Walker 	set->cb_args.cb_arg = set;
372d89352a9SBen Walker 	set->cb_args.channel = channel->dev_channel;
373d89352a9SBen Walker 
374d89352a9SBen Walker 	return (spdk_bs_batch_t *)set;
375d89352a9SBen Walker }
376d89352a9SBen Walker 
377d89352a9SBen Walker void
378964463e4SSeth Howell bs_batch_read_bs_dev(spdk_bs_batch_t *batch, struct spdk_bs_dev *bs_dev,
3790e917256SMaciej Szwed 		     void *payload, uint64_t lba, uint32_t lba_count)
380d89352a9SBen Walker {
381d89352a9SBen Walker 	struct spdk_bs_request_set	*set = (struct spdk_bs_request_set *)batch;
38231c2852bSMike Gerdts 	struct spdk_io_channel		*back_channel = set->back_channel;
383d89352a9SBen Walker 
3842172c432STomasz Zawadzki 	SPDK_DEBUGLOG(blob_rw, "Reading %" PRIu32 " blocks from LBA %" PRIu64 "\n", lba_count,
3853e717065STomasz Kulasek 		      lba);
386d89352a9SBen Walker 
387d89352a9SBen Walker 	set->u.batch.outstanding_ops++;
38831c2852bSMike Gerdts 	bs_dev->read(bs_dev, back_channel, payload, lba, lba_count, &set->cb_args);
3890e917256SMaciej Szwed }
3900e917256SMaciej Szwed 
3910e917256SMaciej Szwed void
392ad7fdd12SSeth Howell bs_batch_read_dev(spdk_bs_batch_t *batch, void *payload,
3930e917256SMaciej Szwed 		  uint64_t lba, uint32_t lba_count)
3940e917256SMaciej Szwed {
3950e917256SMaciej Szwed 	struct spdk_bs_request_set	*set = (struct spdk_bs_request_set *)batch;
3960e917256SMaciej Szwed 	struct spdk_bs_channel		*channel = set->channel;
3970e917256SMaciej Szwed 
3982172c432STomasz Zawadzki 	SPDK_DEBUGLOG(blob_rw, "Reading %" PRIu32 " blocks from LBA %" PRIu64 "\n", lba_count,
3993e717065STomasz Kulasek 		      lba);
4003e717065STomasz Kulasek 
4014dc04dc6SPiotr Pelplinski 	set->u.batch.outstanding_ops++;
4024dc04dc6SPiotr Pelplinski 	channel->dev->read(channel->dev, channel->dev_channel, payload, lba, lba_count, &set->cb_args);
403d89352a9SBen Walker }
404d89352a9SBen Walker 
405d89352a9SBen Walker void
406ad7fdd12SSeth Howell bs_batch_write_dev(spdk_bs_batch_t *batch, void *payload,
407d89352a9SBen Walker 		   uint64_t lba, uint32_t lba_count)
408d89352a9SBen Walker {
409d89352a9SBen Walker 	struct spdk_bs_request_set	*set = (struct spdk_bs_request_set *)batch;
410d89352a9SBen Walker 	struct spdk_bs_channel		*channel = set->channel;
411d89352a9SBen Walker 
4122172c432STomasz Zawadzki 	SPDK_DEBUGLOG(blob_rw, "Writing %" PRIu32 " blocks to LBA %" PRIu64 "\n", lba_count, lba);
413d89352a9SBen Walker 
414d89352a9SBen Walker 	set->u.batch.outstanding_ops++;
415d89352a9SBen Walker 	channel->dev->write(channel->dev, channel->dev_channel, payload, lba, lba_count,
416d89352a9SBen Walker 			    &set->cb_args);
417d89352a9SBen Walker }
418d89352a9SBen Walker 
419d89352a9SBen Walker void
420ad7fdd12SSeth Howell bs_batch_unmap_dev(spdk_bs_batch_t *batch,
421f01146aeSJim Harris 		   uint64_t lba, uint64_t lba_count)
422d89352a9SBen Walker {
423d89352a9SBen Walker 	struct spdk_bs_request_set	*set = (struct spdk_bs_request_set *)batch;
424d89352a9SBen Walker 	struct spdk_bs_channel		*channel = set->channel;
425d89352a9SBen Walker 
426f01146aeSJim Harris 	SPDK_DEBUGLOG(blob_rw, "Unmapping %" PRIu64 " blocks at LBA %" PRIu64 "\n", lba_count,
4273e717065STomasz Kulasek 		      lba);
428d89352a9SBen Walker 
429d89352a9SBen Walker 	set->u.batch.outstanding_ops++;
430d89352a9SBen Walker 	channel->dev->unmap(channel->dev, channel->dev_channel, lba, lba_count,
431d89352a9SBen Walker 			    &set->cb_args);
432d89352a9SBen Walker }
433d89352a9SBen Walker 
434d89352a9SBen Walker void
435ad7fdd12SSeth Howell bs_batch_write_zeroes_dev(spdk_bs_batch_t *batch,
436f01146aeSJim Harris 			  uint64_t lba, uint64_t lba_count)
4373f9cbe51SSeth Howell {
4383f9cbe51SSeth Howell 	struct spdk_bs_request_set	*set = (struct spdk_bs_request_set *)batch;
4393f9cbe51SSeth Howell 	struct spdk_bs_channel		*channel = set->channel;
4403f9cbe51SSeth Howell 
441f01146aeSJim Harris 	SPDK_DEBUGLOG(blob_rw, "Zeroing %" PRIu64 " blocks at LBA %" PRIu64 "\n", lba_count, lba);
4423f9cbe51SSeth Howell 
4433f9cbe51SSeth Howell 	set->u.batch.outstanding_ops++;
4443f9cbe51SSeth Howell 	channel->dev->write_zeroes(channel->dev, channel->dev_channel, lba, lba_count,
4453f9cbe51SSeth Howell 				   &set->cb_args);
4463f9cbe51SSeth Howell }
4473f9cbe51SSeth Howell 
4484132ac52SMaciej Szwed void
449ad7fdd12SSeth Howell bs_batch_close(spdk_bs_batch_t *batch)
450d89352a9SBen Walker {
451d89352a9SBen Walker 	struct spdk_bs_request_set	*set = (struct spdk_bs_request_set *)batch;
452d89352a9SBen Walker 
453d89352a9SBen Walker 	set->u.batch.batch_closed = 1;
454d89352a9SBen Walker 
455d89352a9SBen Walker 	if (set->u.batch.outstanding_ops == 0) {
456d89352a9SBen Walker 		if (set->u.batch.cb_fn) {
4573456377bSSeth Howell 			set->cb_args.cb_fn = bs_sequence_completion;
458d89352a9SBen Walker 			set->u.batch.cb_fn((spdk_bs_sequence_t *)set, set->u.batch.cb_arg, set->bserrno);
459d89352a9SBen Walker 		} else {
4603456377bSSeth Howell 			bs_request_set_complete(set);
461d89352a9SBen Walker 		}
462d89352a9SBen Walker 	}
463d89352a9SBen Walker }
464d89352a9SBen Walker 
465d89352a9SBen Walker spdk_bs_batch_t *
466ad7fdd12SSeth Howell bs_sequence_to_batch(spdk_bs_sequence_t *seq, spdk_bs_sequence_cpl cb_fn, void *cb_arg)
467d89352a9SBen Walker {
468d89352a9SBen Walker 	struct spdk_bs_request_set *set = (struct spdk_bs_request_set *)seq;
469d89352a9SBen Walker 
470d89352a9SBen Walker 	set->u.batch.cb_fn = cb_fn;
471d89352a9SBen Walker 	set->u.batch.cb_arg = cb_arg;
472d89352a9SBen Walker 	set->u.batch.outstanding_ops = 0;
473d89352a9SBen Walker 	set->u.batch.batch_closed = 0;
474d89352a9SBen Walker 
4753456377bSSeth Howell 	set->cb_args.cb_fn = bs_batch_completion;
476d89352a9SBen Walker 
477d89352a9SBen Walker 	return set;
478d89352a9SBen Walker }
479d89352a9SBen Walker 
480b2503cb3SJim Harris spdk_bs_user_op_t *
481ad7fdd12SSeth Howell bs_user_op_alloc(struct spdk_io_channel *_channel, struct spdk_bs_cpl *cpl,
482b2503cb3SJim Harris 		 enum spdk_blob_op_type op_type, struct spdk_blob *blob,
483b2503cb3SJim Harris 		 void *payload, int iovcnt, uint64_t offset, uint64_t length)
484b2503cb3SJim Harris {
485b2503cb3SJim Harris 	struct spdk_bs_channel		*channel;
486b2503cb3SJim Harris 	struct spdk_bs_request_set	*set;
487b2503cb3SJim Harris 	struct spdk_bs_user_op_args	*args;
488b2503cb3SJim Harris 
489b2503cb3SJim Harris 	channel = spdk_io_channel_get_ctx(_channel);
49004ce0e12Syidong0635 	assert(channel != NULL);
491b2503cb3SJim Harris 	set = TAILQ_FIRST(&channel->reqs);
492b2503cb3SJim Harris 	if (!set) {
493b2503cb3SJim Harris 		return NULL;
494b2503cb3SJim Harris 	}
495b2503cb3SJim Harris 	TAILQ_REMOVE(&channel->reqs, set, link);
496b2503cb3SJim Harris 
497*c6c1234dSxupeng-mingtu 	spdk_trace_record(TRACE_BLOB_REQ_SET_START, 0, 0, (uintptr_t)&set->cb_args,
498*c6c1234dSxupeng-mingtu 			  (uintptr_t)cpl->u.blob_basic.cb_arg);
499*c6c1234dSxupeng-mingtu 
500b2503cb3SJim Harris 	set->cpl = *cpl;
501b2503cb3SJim Harris 	set->channel = channel;
50231c2852bSMike Gerdts 	set->back_channel = NULL;
503a2360845SAlexey Marchuk 	set->ext_io_opts = NULL;
504b2503cb3SJim Harris 
505b2503cb3SJim Harris 	args = &set->u.user_op;
506b2503cb3SJim Harris 
507b2503cb3SJim Harris 	args->type = op_type;
50868b8237cSMaciej Szwed 	args->iovcnt = iovcnt;
509b2503cb3SJim Harris 	args->blob = blob;
510b2503cb3SJim Harris 	args->offset = offset;
511b2503cb3SJim Harris 	args->length = length;
512b2503cb3SJim Harris 	args->payload = payload;
513b2503cb3SJim Harris 
514b2503cb3SJim Harris 	return (spdk_bs_user_op_t *)set;
515b2503cb3SJim Harris }
516b2503cb3SJim Harris 
517b2503cb3SJim Harris void
518ad7fdd12SSeth Howell bs_user_op_execute(spdk_bs_user_op_t *op)
519b2503cb3SJim Harris {
520b2503cb3SJim Harris 	struct spdk_bs_request_set	*set;
521b2503cb3SJim Harris 	struct spdk_bs_user_op_args	*args;
522b2503cb3SJim Harris 	struct spdk_io_channel		*ch;
523b2503cb3SJim Harris 
524b2503cb3SJim Harris 	set = (struct spdk_bs_request_set *)op;
525b2503cb3SJim Harris 	args = &set->u.user_op;
526b2503cb3SJim Harris 	ch = spdk_io_channel_from_ctx(set->channel);
527b2503cb3SJim Harris 
528b2503cb3SJim Harris 	switch (args->type) {
529b2503cb3SJim Harris 	case SPDK_BLOB_READ:
53066fc591fSJim Harris 		spdk_blob_io_read(args->blob, ch, args->payload, args->offset, args->length,
531b2503cb3SJim Harris 				  set->cpl.u.blob_basic.cb_fn, set->cpl.u.blob_basic.cb_arg);
532b2503cb3SJim Harris 		break;
533b2503cb3SJim Harris 	case SPDK_BLOB_WRITE:
53466fc591fSJim Harris 		spdk_blob_io_write(args->blob, ch, args->payload, args->offset, args->length,
535b2503cb3SJim Harris 				   set->cpl.u.blob_basic.cb_fn, set->cpl.u.blob_basic.cb_arg);
536b2503cb3SJim Harris 		break;
537b2503cb3SJim Harris 	case SPDK_BLOB_UNMAP:
53866fc591fSJim Harris 		spdk_blob_io_unmap(args->blob, ch, args->offset, args->length,
539b2503cb3SJim Harris 				   set->cpl.u.blob_basic.cb_fn, set->cpl.u.blob_basic.cb_arg);
540b2503cb3SJim Harris 		break;
541b2503cb3SJim Harris 	case SPDK_BLOB_WRITE_ZEROES:
54266fc591fSJim Harris 		spdk_blob_io_write_zeroes(args->blob, ch, args->offset, args->length,
543b2503cb3SJim Harris 					  set->cpl.u.blob_basic.cb_fn, set->cpl.u.blob_basic.cb_arg);
544b2503cb3SJim Harris 		break;
545b2503cb3SJim Harris 	case SPDK_BLOB_READV:
546a2360845SAlexey Marchuk 		spdk_blob_io_readv_ext(args->blob, ch, args->payload, args->iovcnt,
547b2503cb3SJim Harris 				       args->offset, args->length,
548a2360845SAlexey Marchuk 				       set->cpl.u.blob_basic.cb_fn, set->cpl.u.blob_basic.cb_arg,
549a2360845SAlexey Marchuk 				       set->ext_io_opts);
550b2503cb3SJim Harris 		break;
551b2503cb3SJim Harris 	case SPDK_BLOB_WRITEV:
552a2360845SAlexey Marchuk 		spdk_blob_io_writev_ext(args->blob, ch, args->payload, args->iovcnt,
553b2503cb3SJim Harris 					args->offset, args->length,
554a2360845SAlexey Marchuk 					set->cpl.u.blob_basic.cb_fn, set->cpl.u.blob_basic.cb_arg,
555a2360845SAlexey Marchuk 					set->ext_io_opts);
556b2503cb3SJim Harris 		break;
557b2503cb3SJim Harris 	}
558b2503cb3SJim Harris 	TAILQ_INSERT_TAIL(&set->channel->reqs, set, link);
559b2503cb3SJim Harris }
560b2503cb3SJim Harris 
561b2503cb3SJim Harris void
5620b034da1STomasz Zawadzki bs_user_op_abort(spdk_bs_user_op_t *op, int bserrno)
563b2503cb3SJim Harris {
564b2503cb3SJim Harris 	struct spdk_bs_request_set	*set;
565b2503cb3SJim Harris 
566b2503cb3SJim Harris 	set = (struct spdk_bs_request_set *)op;
567b2503cb3SJim Harris 
5680b034da1STomasz Zawadzki 	set->cpl.u.blob_basic.cb_fn(set->cpl.u.blob_basic.cb_arg, bserrno);
569b2503cb3SJim Harris 	TAILQ_INSERT_TAIL(&set->channel->reqs, set, link);
570b2503cb3SJim Harris }
571b2503cb3SJim Harris 
5722172c432STomasz Zawadzki SPDK_LOG_REGISTER_COMPONENT(blob_rw)
573