xref: /spdk/module/blob/bdev/blob_bdev.c (revision 927f1fd57bd004df581518466ec4c1b8083e5d23)
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 "spdk/blob_bdev.h"
37 #include "spdk/blob.h"
38 #include "spdk/thread.h"
39 #include "spdk/log.h"
40 #include "spdk/endian.h"
41 #define __SPDK_BDEV_MODULE_ONLY
42 #include "spdk/bdev_module.h"
43 
44 struct blob_bdev {
45 	struct spdk_bs_dev	bs_dev;
46 	struct spdk_bdev	*bdev;
47 	struct spdk_bdev_desc	*desc;
48 	bool			claimed;
49 };
50 
51 struct blob_resubmit {
52 	struct spdk_bdev_io_wait_entry bdev_io_wait;
53 	enum spdk_bdev_io_type io_type;
54 	struct spdk_bs_dev *dev;
55 	struct spdk_io_channel *channel;
56 	void *payload;
57 	int iovcnt;
58 	uint64_t lba;
59 	uint32_t lba_count;
60 	struct spdk_bs_dev_cb_args *cb_args;
61 	struct spdk_blob_ext_io_opts *ext_io_opts;
62 };
63 static void bdev_blob_resubmit(void *);
64 
65 static inline struct spdk_bdev_desc *
66 __get_desc(struct spdk_bs_dev *dev)
67 {
68 	return ((struct blob_bdev *)dev)->desc;
69 }
70 
71 static inline struct spdk_bdev *
72 __get_bdev(struct spdk_bs_dev *dev)
73 {
74 	return ((struct blob_bdev *)dev)->bdev;
75 }
76 
77 static void
78 bdev_blob_io_complete(struct spdk_bdev_io *bdev_io, bool success, void *arg)
79 {
80 	struct spdk_bs_dev_cb_args *cb_args = arg;
81 	int bserrno;
82 
83 	if (success) {
84 		bserrno = 0;
85 	} else {
86 		bserrno = -EIO;
87 	}
88 	cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, bserrno);
89 	spdk_bdev_free_io(bdev_io);
90 }
91 
92 static void
93 bdev_blob_queue_io(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *payload,
94 		   int iovcnt, uint64_t lba, uint32_t lba_count, enum spdk_bdev_io_type io_type,
95 		   struct spdk_bs_dev_cb_args *cb_args, struct spdk_blob_ext_io_opts *ext_io_opts)
96 {
97 	int rc;
98 	struct spdk_bdev *bdev = __get_bdev(dev);
99 	struct blob_resubmit *ctx;
100 
101 	ctx = calloc(1, sizeof(struct blob_resubmit));
102 
103 	if (ctx == NULL) {
104 		SPDK_ERRLOG("Not enough memory to queue io\n");
105 		cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, -ENOMEM);
106 		return;
107 	}
108 
109 	ctx->io_type = io_type;
110 	ctx->dev = dev;
111 	ctx->channel = channel;
112 	ctx->payload = payload;
113 	ctx->iovcnt = iovcnt;
114 	ctx->lba = lba;
115 	ctx->lba_count = lba_count;
116 	ctx->cb_args = cb_args;
117 	ctx->bdev_io_wait.bdev = bdev;
118 	ctx->bdev_io_wait.cb_fn = bdev_blob_resubmit;
119 	ctx->bdev_io_wait.cb_arg = ctx;
120 	ctx->ext_io_opts = ext_io_opts;
121 
122 	rc = spdk_bdev_queue_io_wait(bdev, channel, &ctx->bdev_io_wait);
123 	if (rc != 0) {
124 		SPDK_ERRLOG("Queue io failed, rc=%d\n", rc);
125 		cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
126 		free(ctx);
127 		assert(false);
128 	}
129 }
130 
131 static void
132 bdev_blob_read(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *payload,
133 	       uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args)
134 {
135 	int rc;
136 
137 	rc = spdk_bdev_read_blocks(__get_desc(dev), channel, payload, lba,
138 				   lba_count, bdev_blob_io_complete, cb_args);
139 	if (rc == -ENOMEM) {
140 		bdev_blob_queue_io(dev, channel, payload, 0, lba,
141 				   lba_count, SPDK_BDEV_IO_TYPE_READ, cb_args, NULL);
142 	} else if (rc != 0) {
143 		cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
144 	}
145 }
146 
147 static void
148 bdev_blob_write(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *payload,
149 		uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args)
150 {
151 	int rc;
152 
153 	rc = spdk_bdev_write_blocks(__get_desc(dev), channel, payload, lba,
154 				    lba_count, bdev_blob_io_complete, cb_args);
155 	if (rc == -ENOMEM) {
156 		bdev_blob_queue_io(dev, channel, payload, 0, lba,
157 				   lba_count, SPDK_BDEV_IO_TYPE_WRITE, cb_args, NULL);
158 	} else if (rc != 0) {
159 		cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
160 	}
161 }
162 
163 static void
164 bdev_blob_readv(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
165 		struct iovec *iov, int iovcnt,
166 		uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args)
167 {
168 	int rc;
169 
170 	rc = spdk_bdev_readv_blocks(__get_desc(dev), channel, iov, iovcnt, lba,
171 				    lba_count, bdev_blob_io_complete, cb_args);
172 	if (rc == -ENOMEM) {
173 		bdev_blob_queue_io(dev, channel, iov, iovcnt, lba,
174 				   lba_count, SPDK_BDEV_IO_TYPE_READ, cb_args, NULL);
175 	} else if (rc != 0) {
176 		cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
177 	}
178 }
179 
180 static void
181 bdev_blob_writev(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
182 		 struct iovec *iov, int iovcnt,
183 		 uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args)
184 {
185 	int rc;
186 
187 	rc = spdk_bdev_writev_blocks(__get_desc(dev), channel, iov, iovcnt, lba,
188 				     lba_count, bdev_blob_io_complete, cb_args);
189 	if (rc == -ENOMEM) {
190 		bdev_blob_queue_io(dev, channel, iov, iovcnt, lba,
191 				   lba_count, SPDK_BDEV_IO_TYPE_WRITE, cb_args, NULL);
192 	} else if (rc != 0) {
193 		cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
194 	}
195 }
196 
197 static void
198 bdev_blob_readv_ext(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
199 		    struct iovec *iov, int iovcnt,
200 		    uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args,
201 		    struct spdk_blob_ext_io_opts *io_opts)
202 {
203 	struct spdk_bdev_ext_io_opts *bdev_io_opts = NULL;
204 	int rc;
205 
206 	if (io_opts) {
207 		/* bdev ext API requires ext_io_opts to be allocated by the user, we don't have enough context to allocate
208 		 * bdev ext_opts structure here. Also blob and bdev ext_opts are not API/ABI compatible, so we can't use the given
209 		 * io_opts. Restore ext_opts passed by the user of this bs_dev */
210 		bdev_io_opts = io_opts->user_ctx;
211 		assert(bdev_io_opts);
212 	}
213 
214 	rc = spdk_bdev_readv_blocks_ext(__get_desc(dev), channel, iov, iovcnt, lba, lba_count,
215 					bdev_blob_io_complete, cb_args, bdev_io_opts);
216 	if (rc == -ENOMEM) {
217 		bdev_blob_queue_io(dev, channel, iov, iovcnt, lba, lba_count, SPDK_BDEV_IO_TYPE_READ, cb_args,
218 				   io_opts);
219 	} else if (rc != 0) {
220 		cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
221 	}
222 }
223 
224 static void
225 bdev_blob_writev_ext(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
226 		     struct iovec *iov, int iovcnt,
227 		     uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args,
228 		     struct spdk_blob_ext_io_opts *io_opts)
229 {
230 	struct spdk_bdev_ext_io_opts *bdev_io_opts = NULL;
231 	int rc;
232 
233 	if (io_opts) {
234 		/* bdev ext API requires ext_io_opts to be allocated by the user, we don't have enough context to allocate
235 		 * bdev ext_opts structure here. Also blob and bdev ext_opts are not API/ABI compatible, so we can't use the given
236 		 * io_opts. Restore ext_opts passed by the user of this bs_dev */
237 		bdev_io_opts = io_opts->user_ctx;
238 		assert(bdev_io_opts);
239 	}
240 
241 	rc = spdk_bdev_writev_blocks_ext(__get_desc(dev), channel, iov, iovcnt, lba, lba_count,
242 					 bdev_blob_io_complete, cb_args, bdev_io_opts);
243 	if (rc == -ENOMEM) {
244 		bdev_blob_queue_io(dev, channel, iov, iovcnt, lba, lba_count, SPDK_BDEV_IO_TYPE_WRITE, cb_args,
245 				   io_opts);
246 	} else if (rc != 0) {
247 		cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
248 	}
249 }
250 
251 static void
252 bdev_blob_write_zeroes(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, uint64_t lba,
253 		       uint64_t lba_count, struct spdk_bs_dev_cb_args *cb_args)
254 {
255 	int rc;
256 
257 	rc = spdk_bdev_write_zeroes_blocks(__get_desc(dev), channel, lba,
258 					   lba_count, bdev_blob_io_complete, cb_args);
259 	if (rc == -ENOMEM) {
260 		bdev_blob_queue_io(dev, channel, NULL, 0, lba,
261 				   lba_count, SPDK_BDEV_IO_TYPE_WRITE_ZEROES, cb_args, NULL);
262 	} else if (rc != 0) {
263 		cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
264 	}
265 }
266 
267 static void
268 bdev_blob_unmap(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, uint64_t lba,
269 		uint64_t lba_count, struct spdk_bs_dev_cb_args *cb_args)
270 {
271 	struct blob_bdev *blob_bdev = (struct blob_bdev *)dev;
272 	int rc;
273 
274 	if (spdk_bdev_io_type_supported(blob_bdev->bdev, SPDK_BDEV_IO_TYPE_UNMAP)) {
275 		rc = spdk_bdev_unmap_blocks(__get_desc(dev), channel, lba, lba_count,
276 					    bdev_blob_io_complete, cb_args);
277 		if (rc == -ENOMEM) {
278 			bdev_blob_queue_io(dev, channel, NULL, 0, lba,
279 					   lba_count, SPDK_BDEV_IO_TYPE_UNMAP, cb_args, NULL);
280 		} else if (rc != 0) {
281 			cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
282 		}
283 	} else {
284 		/*
285 		 * If the device doesn't support unmap, immediately complete
286 		 * the request. Blobstore does not rely on unmap zeroing
287 		 * data.
288 		 */
289 		cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, 0);
290 	}
291 }
292 
293 static void
294 bdev_blob_resubmit(void *arg)
295 {
296 	struct blob_resubmit *ctx = (struct blob_resubmit *) arg;
297 
298 	switch (ctx->io_type) {
299 	case SPDK_BDEV_IO_TYPE_READ:
300 		if (ctx->iovcnt > 0) {
301 			bdev_blob_readv_ext(ctx->dev, ctx->channel, (struct iovec *) ctx->payload, ctx->iovcnt,
302 					    ctx->lba, ctx->lba_count, ctx->cb_args, ctx->ext_io_opts);
303 		} else {
304 			bdev_blob_read(ctx->dev, ctx->channel, ctx->payload,
305 				       ctx->lba, ctx->lba_count, ctx->cb_args);
306 		}
307 		break;
308 	case SPDK_BDEV_IO_TYPE_WRITE:
309 		if (ctx->iovcnt > 0) {
310 			bdev_blob_writev_ext(ctx->dev, ctx->channel, (struct iovec *) ctx->payload, ctx->iovcnt,
311 					     ctx->lba, ctx->lba_count, ctx->cb_args, ctx->ext_io_opts);
312 		} else {
313 			bdev_blob_write(ctx->dev, ctx->channel, ctx->payload,
314 					ctx->lba, ctx->lba_count, ctx->cb_args);
315 		}
316 		break;
317 	case SPDK_BDEV_IO_TYPE_UNMAP:
318 		bdev_blob_unmap(ctx->dev, ctx->channel,
319 				ctx->lba, ctx->lba_count, ctx->cb_args);
320 		break;
321 	case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
322 		bdev_blob_write_zeroes(ctx->dev, ctx->channel,
323 				       ctx->lba, ctx->lba_count, ctx->cb_args);
324 		break;
325 	default:
326 		SPDK_ERRLOG("Unsupported io type %d\n", ctx->io_type);
327 		assert(false);
328 		break;
329 	}
330 	free(ctx);
331 }
332 
333 int
334 spdk_bs_bdev_claim(struct spdk_bs_dev *bs_dev, struct spdk_bdev_module *module)
335 {
336 	struct blob_bdev *blob_bdev = (struct blob_bdev *)bs_dev;
337 	int rc;
338 
339 	rc = spdk_bdev_module_claim_bdev(blob_bdev->bdev, NULL, module);
340 	if (rc != 0) {
341 		SPDK_ERRLOG("could not claim bs dev\n");
342 		return rc;
343 	}
344 
345 	blob_bdev->claimed = true;
346 
347 	return rc;
348 }
349 
350 static struct spdk_io_channel *
351 bdev_blob_create_channel(struct spdk_bs_dev *dev)
352 {
353 	struct blob_bdev *blob_bdev = (struct blob_bdev *)dev;
354 
355 	return spdk_bdev_get_io_channel(blob_bdev->desc);
356 }
357 
358 static void
359 bdev_blob_destroy_channel(struct spdk_bs_dev *dev, struct spdk_io_channel *channel)
360 {
361 	spdk_put_io_channel(channel);
362 }
363 
364 static void
365 bdev_blob_destroy(struct spdk_bs_dev *bs_dev)
366 {
367 	struct spdk_bdev_desc *desc = __get_desc(bs_dev);
368 	struct blob_bdev *blob_bdev = (struct blob_bdev *)bs_dev;
369 
370 	if (blob_bdev->claimed) {
371 		spdk_bdev_module_release_bdev(blob_bdev->bdev);
372 	}
373 
374 	spdk_bdev_close(desc);
375 	free(bs_dev);
376 }
377 
378 static struct spdk_bdev *
379 bdev_blob_get_base_bdev(struct spdk_bs_dev *bs_dev)
380 {
381 	return __get_bdev(bs_dev);
382 }
383 
384 static void
385 blob_bdev_init(struct blob_bdev *b, struct spdk_bdev_desc *desc)
386 {
387 	struct spdk_bdev *bdev;
388 
389 	bdev = spdk_bdev_desc_get_bdev(desc);
390 	assert(bdev != NULL);
391 
392 	b->bdev = bdev;
393 	b->desc = desc;
394 	b->bs_dev.blockcnt = spdk_bdev_get_num_blocks(bdev);
395 	b->bs_dev.blocklen = spdk_bdev_get_block_size(bdev);
396 	b->bs_dev.create_channel = bdev_blob_create_channel;
397 	b->bs_dev.destroy_channel = bdev_blob_destroy_channel;
398 	b->bs_dev.destroy = bdev_blob_destroy;
399 	b->bs_dev.read = bdev_blob_read;
400 	b->bs_dev.write = bdev_blob_write;
401 	b->bs_dev.readv = bdev_blob_readv;
402 	b->bs_dev.writev = bdev_blob_writev;
403 	b->bs_dev.readv_ext = bdev_blob_readv_ext;
404 	b->bs_dev.writev_ext = bdev_blob_writev_ext;
405 	b->bs_dev.write_zeroes = bdev_blob_write_zeroes;
406 	b->bs_dev.unmap = bdev_blob_unmap;
407 	b->bs_dev.get_base_bdev = bdev_blob_get_base_bdev;
408 }
409 
410 int
411 spdk_bdev_create_bs_dev_ext(const char *bdev_name, spdk_bdev_event_cb_t event_cb,
412 			    void *event_ctx, struct spdk_bs_dev **_bs_dev)
413 {
414 	struct blob_bdev *b;
415 	struct spdk_bdev_desc *desc;
416 	int rc;
417 
418 	b = calloc(1, sizeof(*b));
419 
420 	if (b == NULL) {
421 		SPDK_ERRLOG("could not allocate blob_bdev\n");
422 		return -ENOMEM;
423 	}
424 
425 	rc = spdk_bdev_open_ext(bdev_name, true, event_cb, event_ctx, &desc);
426 	if (rc != 0) {
427 		free(b);
428 		return rc;
429 	}
430 
431 	blob_bdev_init(b, desc);
432 
433 	*_bs_dev = &b->bs_dev;
434 
435 	return 0;
436 }
437