xref: /spdk/lib/blob/request.c (revision 88e3ffd7b6c5ec1ea1a660354d25f02c766092e1)
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/thread.h"
40  #include "spdk/queue.h"
41  
42  #include "spdk/log.h"
43  
44  void
45  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  				       bserrno == 0 ? cpl->u.bs_handle.bs : NULL,
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  				    bserrno == 0 ? cpl->u.blobid.blobid : SPDK_BLOBID_INVALID,
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  					 bserrno == 0 ? cpl->u.blob_handle.blob : NULL,
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  	case SPDK_BS_CPL_TYPE_NONE:
77  		/* this completion's callback is handled elsewhere */
78  		break;
79  	}
80  }
81  
82  static void
83  bs_request_set_complete(struct spdk_bs_request_set *set)
84  {
85  	struct spdk_bs_cpl cpl = set->cpl;
86  	int bserrno = set->bserrno;
87  
88  	TAILQ_INSERT_TAIL(&set->channel->reqs, set, link);
89  
90  	bs_call_cpl(&cpl, bserrno);
91  }
92  
93  static void
94  bs_sequence_completion(struct spdk_io_channel *channel, void *cb_arg, int bserrno)
95  {
96  	struct spdk_bs_request_set *set = cb_arg;
97  
98  	set->bserrno = bserrno;
99  	set->u.sequence.cb_fn((spdk_bs_sequence_t *)set, set->u.sequence.cb_arg, bserrno);
100  }
101  
102  spdk_bs_sequence_t *
103  bs_sequence_start(struct spdk_io_channel *_channel,
104  		  struct spdk_bs_cpl *cpl)
105  {
106  	struct spdk_bs_channel		*channel;
107  	struct spdk_bs_request_set	*set;
108  
109  	channel = spdk_io_channel_get_ctx(_channel);
110  	assert(channel != NULL);
111  	set = TAILQ_FIRST(&channel->reqs);
112  	if (!set) {
113  		return NULL;
114  	}
115  	TAILQ_REMOVE(&channel->reqs, set, link);
116  
117  	set->cpl = *cpl;
118  	set->bserrno = 0;
119  	set->channel = channel;
120  
121  	set->cb_args.cb_fn = bs_sequence_completion;
122  	set->cb_args.cb_arg = set;
123  	set->cb_args.channel = channel->dev_channel;
124  
125  	return (spdk_bs_sequence_t *)set;
126  }
127  
128  void
129  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)
132  {
133  	struct spdk_bs_request_set      *set = (struct spdk_bs_request_set *)seq;
134  	struct spdk_bs_channel       *channel = set->channel;
135  
136  	SPDK_DEBUGLOG(blob_rw, "Reading %" PRIu32 " blocks from LBA %" PRIu64 "\n", lba_count,
137  		      lba);
138  
139  	set->u.sequence.cb_fn = cb_fn;
140  	set->u.sequence.cb_arg = cb_arg;
141  
142  	bs_dev->read(bs_dev, spdk_io_channel_from_ctx(channel), payload, lba, lba_count, &set->cb_args);
143  }
144  
145  void
146  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)
149  {
150  	struct spdk_bs_request_set      *set = (struct spdk_bs_request_set *)seq;
151  	struct spdk_bs_channel       *channel = set->channel;
152  
153  	SPDK_DEBUGLOG(blob_rw, "Reading %" PRIu32 " blocks from LBA %" PRIu64 "\n", lba_count,
154  		      lba);
155  
156  	set->u.sequence.cb_fn = cb_fn;
157  	set->u.sequence.cb_arg = cb_arg;
158  
159  	channel->dev->read(channel->dev, channel->dev_channel, payload, lba, lba_count, &set->cb_args);
160  }
161  
162  void
163  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)
166  {
167  	struct spdk_bs_request_set      *set = (struct spdk_bs_request_set *)seq;
168  	struct spdk_bs_channel       *channel = set->channel;
169  
170  	SPDK_DEBUGLOG(blob_rw, "Writing %" PRIu32 " blocks from LBA %" PRIu64 "\n", lba_count,
171  		      lba);
172  
173  	set->u.sequence.cb_fn = cb_fn;
174  	set->u.sequence.cb_arg = cb_arg;
175  
176  	channel->dev->write(channel->dev, channel->dev_channel, payload, lba, lba_count,
177  			    &set->cb_args);
178  }
179  
180  void
181  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)
184  {
185  	struct spdk_bs_request_set      *set = (struct spdk_bs_request_set *)seq;
186  	struct spdk_bs_channel       *channel = set->channel;
187  
188  	SPDK_DEBUGLOG(blob_rw, "Reading %" PRIu32 " blocks from LBA %" PRIu64 "\n", lba_count,
189  		      lba);
190  
191  	set->u.sequence.cb_fn = cb_fn;
192  	set->u.sequence.cb_arg = cb_arg;
193  
194  	bs_dev->readv(bs_dev, spdk_io_channel_from_ctx(channel), iov, iovcnt, lba, lba_count,
195  		      &set->cb_args);
196  }
197  
198  void
199  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)
201  {
202  	struct spdk_bs_request_set      *set = (struct spdk_bs_request_set *)seq;
203  	struct spdk_bs_channel       *channel = set->channel;
204  
205  	SPDK_DEBUGLOG(blob_rw, "Reading %" PRIu32 " blocks from LBA %" PRIu64 "\n", lba_count,
206  		      lba);
207  
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,
211  			    &set->cb_args);
212  }
213  
214  void
215  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)
218  {
219  	struct spdk_bs_request_set      *set = (struct spdk_bs_request_set *)seq;
220  	struct spdk_bs_channel       *channel = set->channel;
221  
222  	SPDK_DEBUGLOG(blob_rw, "Writing %" PRIu32 " blocks from LBA %" PRIu64 "\n", lba_count,
223  		      lba);
224  
225  	set->u.sequence.cb_fn = cb_fn;
226  	set->u.sequence.cb_arg = cb_arg;
227  
228  	channel->dev->writev(channel->dev, channel->dev_channel, iov, iovcnt, lba, lba_count,
229  			     &set->cb_args);
230  }
231  
232  void
233  bs_sequence_write_zeroes_dev(spdk_bs_sequence_t *seq,
234  			     uint64_t lba, uint32_t lba_count,
235  			     spdk_bs_sequence_cpl cb_fn, void *cb_arg)
236  {
237  	struct spdk_bs_request_set      *set = (struct spdk_bs_request_set *)seq;
238  	struct spdk_bs_channel       *channel = set->channel;
239  
240  	SPDK_DEBUGLOG(blob_rw, "writing zeroes to %" PRIu32 " blocks at LBA %" PRIu64 "\n",
241  		      lba_count, lba);
242  
243  	set->u.sequence.cb_fn = cb_fn;
244  	set->u.sequence.cb_arg = cb_arg;
245  
246  	channel->dev->write_zeroes(channel->dev, channel->dev_channel, lba, lba_count,
247  				   &set->cb_args);
248  }
249  
250  void
251  bs_sequence_finish(spdk_bs_sequence_t *seq, int bserrno)
252  {
253  	if (bserrno != 0) {
254  		seq->bserrno = bserrno;
255  	}
256  	bs_request_set_complete((struct spdk_bs_request_set *)seq);
257  }
258  
259  void
260  bs_user_op_sequence_finish(void *cb_arg, int bserrno)
261  {
262  	spdk_bs_sequence_t *seq = cb_arg;
263  
264  	bs_sequence_finish(seq, bserrno);
265  }
266  
267  static void
268  bs_batch_completion(struct spdk_io_channel *_channel,
269  		    void *cb_arg, int bserrno)
270  {
271  	struct spdk_bs_request_set	*set = cb_arg;
272  
273  	set->u.batch.outstanding_ops--;
274  	if (bserrno != 0) {
275  		set->bserrno = bserrno;
276  	}
277  
278  	if (set->u.batch.outstanding_ops == 0 && set->u.batch.batch_closed) {
279  		if (set->u.batch.cb_fn) {
280  			set->cb_args.cb_fn = bs_sequence_completion;
281  			set->u.batch.cb_fn((spdk_bs_sequence_t *)set, set->u.batch.cb_arg, bserrno);
282  		} else {
283  			bs_request_set_complete(set);
284  		}
285  	}
286  }
287  
288  spdk_bs_batch_t *
289  bs_batch_open(struct spdk_io_channel *_channel,
290  	      struct spdk_bs_cpl *cpl)
291  {
292  	struct spdk_bs_channel		*channel;
293  	struct spdk_bs_request_set	*set;
294  
295  	channel = spdk_io_channel_get_ctx(_channel);
296  	assert(channel != NULL);
297  	set = TAILQ_FIRST(&channel->reqs);
298  	if (!set) {
299  		return NULL;
300  	}
301  	TAILQ_REMOVE(&channel->reqs, set, link);
302  
303  	set->cpl = *cpl;
304  	set->bserrno = 0;
305  	set->channel = channel;
306  
307  	set->u.batch.cb_fn = NULL;
308  	set->u.batch.cb_arg = NULL;
309  	set->u.batch.outstanding_ops = 0;
310  	set->u.batch.batch_closed = 0;
311  
312  	set->cb_args.cb_fn = bs_batch_completion;
313  	set->cb_args.cb_arg = set;
314  	set->cb_args.channel = channel->dev_channel;
315  
316  	return (spdk_bs_batch_t *)set;
317  }
318  
319  void
320  bs_batch_read_bs_dev(spdk_bs_batch_t *batch, struct spdk_bs_dev *bs_dev,
321  		     void *payload, uint64_t lba, uint32_t lba_count)
322  {
323  	struct spdk_bs_request_set	*set = (struct spdk_bs_request_set *)batch;
324  	struct spdk_bs_channel		*channel = set->channel;
325  
326  	SPDK_DEBUGLOG(blob_rw, "Reading %" PRIu32 " blocks from LBA %" PRIu64 "\n", lba_count,
327  		      lba);
328  
329  	set->u.batch.outstanding_ops++;
330  	bs_dev->read(bs_dev, spdk_io_channel_from_ctx(channel), payload, lba, lba_count, &set->cb_args);
331  }
332  
333  void
334  bs_batch_read_dev(spdk_bs_batch_t *batch, void *payload,
335  		  uint64_t lba, uint32_t lba_count)
336  {
337  	struct spdk_bs_request_set	*set = (struct spdk_bs_request_set *)batch;
338  	struct spdk_bs_channel		*channel = set->channel;
339  
340  	SPDK_DEBUGLOG(blob_rw, "Reading %" PRIu32 " blocks from LBA %" PRIu64 "\n", lba_count,
341  		      lba);
342  
343  	set->u.batch.outstanding_ops++;
344  	channel->dev->read(channel->dev, channel->dev_channel, payload, lba, lba_count, &set->cb_args);
345  }
346  
347  void
348  bs_batch_write_dev(spdk_bs_batch_t *batch, void *payload,
349  		   uint64_t lba, uint32_t lba_count)
350  {
351  	struct spdk_bs_request_set	*set = (struct spdk_bs_request_set *)batch;
352  	struct spdk_bs_channel		*channel = set->channel;
353  
354  	SPDK_DEBUGLOG(blob_rw, "Writing %" PRIu32 " blocks to LBA %" PRIu64 "\n", lba_count, lba);
355  
356  	set->u.batch.outstanding_ops++;
357  	channel->dev->write(channel->dev, channel->dev_channel, payload, lba, lba_count,
358  			    &set->cb_args);
359  }
360  
361  void
362  bs_batch_unmap_dev(spdk_bs_batch_t *batch,
363  		   uint64_t lba, uint32_t lba_count)
364  {
365  	struct spdk_bs_request_set	*set = (struct spdk_bs_request_set *)batch;
366  	struct spdk_bs_channel		*channel = set->channel;
367  
368  	SPDK_DEBUGLOG(blob_rw, "Unmapping %" PRIu32 " blocks at LBA %" PRIu64 "\n", lba_count,
369  		      lba);
370  
371  	set->u.batch.outstanding_ops++;
372  	channel->dev->unmap(channel->dev, channel->dev_channel, lba, lba_count,
373  			    &set->cb_args);
374  }
375  
376  void
377  bs_batch_write_zeroes_dev(spdk_bs_batch_t *batch,
378  			  uint64_t lba, uint32_t lba_count)
379  {
380  	struct spdk_bs_request_set	*set = (struct spdk_bs_request_set *)batch;
381  	struct spdk_bs_channel		*channel = set->channel;
382  
383  	SPDK_DEBUGLOG(blob_rw, "Zeroing %" PRIu32 " blocks at LBA %" PRIu64 "\n", lba_count, lba);
384  
385  	set->u.batch.outstanding_ops++;
386  	channel->dev->write_zeroes(channel->dev, channel->dev_channel, lba, lba_count,
387  				   &set->cb_args);
388  }
389  
390  void
391  bs_batch_close(spdk_bs_batch_t *batch)
392  {
393  	struct spdk_bs_request_set	*set = (struct spdk_bs_request_set *)batch;
394  
395  	set->u.batch.batch_closed = 1;
396  
397  	if (set->u.batch.outstanding_ops == 0) {
398  		if (set->u.batch.cb_fn) {
399  			set->cb_args.cb_fn = bs_sequence_completion;
400  			set->u.batch.cb_fn((spdk_bs_sequence_t *)set, set->u.batch.cb_arg, set->bserrno);
401  		} else {
402  			bs_request_set_complete(set);
403  		}
404  	}
405  }
406  
407  spdk_bs_batch_t *
408  bs_sequence_to_batch(spdk_bs_sequence_t *seq, spdk_bs_sequence_cpl cb_fn, void *cb_arg)
409  {
410  	struct spdk_bs_request_set *set = (struct spdk_bs_request_set *)seq;
411  
412  	set->u.batch.cb_fn = cb_fn;
413  	set->u.batch.cb_arg = cb_arg;
414  	set->u.batch.outstanding_ops = 0;
415  	set->u.batch.batch_closed = 0;
416  
417  	set->cb_args.cb_fn = bs_batch_completion;
418  
419  	return set;
420  }
421  
422  spdk_bs_user_op_t *
423  bs_user_op_alloc(struct spdk_io_channel *_channel, struct spdk_bs_cpl *cpl,
424  		 enum spdk_blob_op_type op_type, struct spdk_blob *blob,
425  		 void *payload, int iovcnt, uint64_t offset, uint64_t length)
426  {
427  	struct spdk_bs_channel		*channel;
428  	struct spdk_bs_request_set	*set;
429  	struct spdk_bs_user_op_args	*args;
430  
431  	channel = spdk_io_channel_get_ctx(_channel);
432  	assert(channel != NULL);
433  	set = TAILQ_FIRST(&channel->reqs);
434  	if (!set) {
435  		return NULL;
436  	}
437  	TAILQ_REMOVE(&channel->reqs, set, link);
438  
439  	set->cpl = *cpl;
440  	set->channel = channel;
441  
442  	args = &set->u.user_op;
443  
444  	args->type = op_type;
445  	args->iovcnt = iovcnt;
446  	args->blob = blob;
447  	args->offset = offset;
448  	args->length = length;
449  	args->payload = payload;
450  
451  	return (spdk_bs_user_op_t *)set;
452  }
453  
454  void
455  bs_user_op_execute(spdk_bs_user_op_t *op)
456  {
457  	struct spdk_bs_request_set	*set;
458  	struct spdk_bs_user_op_args	*args;
459  	struct spdk_io_channel		*ch;
460  
461  	set = (struct spdk_bs_request_set *)op;
462  	args = &set->u.user_op;
463  	ch = spdk_io_channel_from_ctx(set->channel);
464  
465  	switch (args->type) {
466  	case SPDK_BLOB_READ:
467  		spdk_blob_io_read(args->blob, ch, args->payload, args->offset, args->length,
468  				  set->cpl.u.blob_basic.cb_fn, set->cpl.u.blob_basic.cb_arg);
469  		break;
470  	case SPDK_BLOB_WRITE:
471  		spdk_blob_io_write(args->blob, ch, args->payload, args->offset, args->length,
472  				   set->cpl.u.blob_basic.cb_fn, set->cpl.u.blob_basic.cb_arg);
473  		break;
474  	case SPDK_BLOB_UNMAP:
475  		spdk_blob_io_unmap(args->blob, ch, args->offset, args->length,
476  				   set->cpl.u.blob_basic.cb_fn, set->cpl.u.blob_basic.cb_arg);
477  		break;
478  	case SPDK_BLOB_WRITE_ZEROES:
479  		spdk_blob_io_write_zeroes(args->blob, ch, args->offset, args->length,
480  					  set->cpl.u.blob_basic.cb_fn, set->cpl.u.blob_basic.cb_arg);
481  		break;
482  	case SPDK_BLOB_READV:
483  		spdk_blob_io_readv(args->blob, ch, args->payload, args->iovcnt,
484  				   args->offset, args->length,
485  				   set->cpl.u.blob_basic.cb_fn, set->cpl.u.blob_basic.cb_arg);
486  		break;
487  	case SPDK_BLOB_WRITEV:
488  		spdk_blob_io_writev(args->blob, ch, args->payload, args->iovcnt,
489  				    args->offset, args->length,
490  				    set->cpl.u.blob_basic.cb_fn, set->cpl.u.blob_basic.cb_arg);
491  		break;
492  	}
493  	TAILQ_INSERT_TAIL(&set->channel->reqs, set, link);
494  }
495  
496  void
497  bs_user_op_abort(spdk_bs_user_op_t *op)
498  {
499  	struct spdk_bs_request_set	*set;
500  
501  	set = (struct spdk_bs_request_set *)op;
502  
503  	set->cpl.u.blob_basic.cb_fn(set->cpl.u.blob_basic.cb_arg, -EIO);
504  	TAILQ_INSERT_TAIL(&set->channel->reqs, set, link);
505  }
506  
507  void
508  bs_sequence_to_batch_completion(void *cb_arg, int bserrno)
509  {
510  	struct spdk_bs_request_set *set = (struct spdk_bs_request_set *)cb_arg;
511  
512  	set->u.batch.outstanding_ops--;
513  
514  	if (set->u.batch.outstanding_ops == 0 && set->u.batch.batch_closed) {
515  		if (set->cb_args.cb_fn) {
516  			set->cb_args.cb_fn(set->cb_args.channel, set->cb_args.cb_arg, bserrno);
517  		}
518  	}
519  }
520  
521  SPDK_LOG_REGISTER_COMPONENT(blob_rw)
522