xref: /spdk/module/blob/bdev/blob_bdev.c (revision 2f5c602574a98ede645991abe279a96e19c50196)
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 };
62 static void bdev_blob_resubmit(void *);
63 
64 static inline struct spdk_bdev_desc *
65 __get_desc(struct spdk_bs_dev *dev)
66 {
67 	return ((struct blob_bdev *)dev)->desc;
68 }
69 
70 static inline struct spdk_bdev *
71 __get_bdev(struct spdk_bs_dev *dev)
72 {
73 	return ((struct blob_bdev *)dev)->bdev;
74 }
75 
76 static void
77 bdev_blob_io_complete(struct spdk_bdev_io *bdev_io, bool success, void *arg)
78 {
79 	struct spdk_bs_dev_cb_args *cb_args = arg;
80 	int bserrno;
81 
82 	if (success) {
83 		bserrno = 0;
84 	} else {
85 		bserrno = -EIO;
86 	}
87 	cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, bserrno);
88 	spdk_bdev_free_io(bdev_io);
89 }
90 
91 static void
92 bdev_blob_queue_io(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *payload,
93 		   int iovcnt,
94 		   uint64_t lba, uint32_t lba_count, enum spdk_bdev_io_type io_type,
95 		   struct spdk_bs_dev_cb_args *cb_args)
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 
121 	rc = spdk_bdev_queue_io_wait(bdev, channel, &ctx->bdev_io_wait);
122 	if (rc != 0) {
123 		SPDK_ERRLOG("Queue io failed, rc=%d\n", rc);
124 		cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
125 		free(ctx);
126 		assert(false);
127 	}
128 }
129 
130 static void
131 bdev_blob_read(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *payload,
132 	       uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args)
133 {
134 	int rc;
135 
136 	rc = spdk_bdev_read_blocks(__get_desc(dev), channel, payload, lba,
137 				   lba_count, bdev_blob_io_complete, cb_args);
138 	if (rc == -ENOMEM) {
139 		bdev_blob_queue_io(dev, channel, payload, 0, lba,
140 				   lba_count, SPDK_BDEV_IO_TYPE_READ, cb_args);
141 	} else if (rc != 0) {
142 		cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
143 	}
144 }
145 
146 static void
147 bdev_blob_write(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *payload,
148 		uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args)
149 {
150 	int rc;
151 
152 	rc = spdk_bdev_write_blocks(__get_desc(dev), channel, payload, lba,
153 				    lba_count, bdev_blob_io_complete, cb_args);
154 	if (rc == -ENOMEM) {
155 		bdev_blob_queue_io(dev, channel, payload, 0, lba,
156 				   lba_count, SPDK_BDEV_IO_TYPE_WRITE, cb_args);
157 	} else if (rc != 0) {
158 		cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
159 	}
160 }
161 
162 static void
163 bdev_blob_readv(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
164 		struct iovec *iov, int iovcnt,
165 		uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args)
166 {
167 	int rc;
168 
169 	rc = spdk_bdev_readv_blocks(__get_desc(dev), channel, iov, iovcnt, lba,
170 				    lba_count, bdev_blob_io_complete, cb_args);
171 	if (rc == -ENOMEM) {
172 		bdev_blob_queue_io(dev, channel, iov, iovcnt, lba,
173 				   lba_count, SPDK_BDEV_IO_TYPE_READ, cb_args);
174 	} else if (rc != 0) {
175 		cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
176 	}
177 }
178 
179 static void
180 bdev_blob_writev(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
181 		 struct iovec *iov, int iovcnt,
182 		 uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args)
183 {
184 	int rc;
185 
186 	rc = spdk_bdev_writev_blocks(__get_desc(dev), channel, iov, iovcnt, lba,
187 				     lba_count, bdev_blob_io_complete, cb_args);
188 	if (rc == -ENOMEM) {
189 		bdev_blob_queue_io(dev, channel, iov, iovcnt, lba,
190 				   lba_count, SPDK_BDEV_IO_TYPE_WRITE, cb_args);
191 	} else if (rc != 0) {
192 		cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
193 	}
194 }
195 
196 static void
197 bdev_blob_write_zeroes(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, uint64_t lba,
198 		       uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args)
199 {
200 	int rc;
201 
202 	rc = spdk_bdev_write_zeroes_blocks(__get_desc(dev), channel, lba,
203 					   lba_count, bdev_blob_io_complete, cb_args);
204 	if (rc == -ENOMEM) {
205 		bdev_blob_queue_io(dev, channel, NULL, 0, lba,
206 				   lba_count, SPDK_BDEV_IO_TYPE_WRITE_ZEROES, cb_args);
207 	} else if (rc != 0) {
208 		cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
209 	}
210 }
211 
212 static void
213 bdev_blob_unmap(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, uint64_t lba,
214 		uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args)
215 {
216 	struct blob_bdev *blob_bdev = (struct blob_bdev *)dev;
217 	int rc;
218 
219 	if (spdk_bdev_io_type_supported(blob_bdev->bdev, SPDK_BDEV_IO_TYPE_UNMAP)) {
220 		rc = spdk_bdev_unmap_blocks(__get_desc(dev), channel, lba, lba_count,
221 					    bdev_blob_io_complete, cb_args);
222 		if (rc == -ENOMEM) {
223 			bdev_blob_queue_io(dev, channel, NULL, 0, lba,
224 					   lba_count, SPDK_BDEV_IO_TYPE_UNMAP, cb_args);
225 		} else if (rc != 0) {
226 			cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
227 		}
228 	} else {
229 		/*
230 		 * If the device doesn't support unmap, immediately complete
231 		 * the request. Blobstore does not rely on unmap zeroing
232 		 * data.
233 		 */
234 		cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, 0);
235 	}
236 }
237 
238 static void
239 bdev_blob_resubmit(void *arg)
240 {
241 	struct blob_resubmit *ctx = (struct blob_resubmit *) arg;
242 
243 	switch (ctx->io_type) {
244 	case SPDK_BDEV_IO_TYPE_READ:
245 		if (ctx->iovcnt > 0) {
246 			bdev_blob_readv(ctx->dev, ctx->channel, (struct iovec *)ctx->payload, ctx->iovcnt,
247 					ctx->lba, ctx->lba_count, ctx->cb_args);
248 		} else {
249 			bdev_blob_read(ctx->dev, ctx->channel, ctx->payload,
250 				       ctx->lba, ctx->lba_count, ctx->cb_args);
251 		}
252 		break;
253 	case SPDK_BDEV_IO_TYPE_WRITE:
254 		if (ctx->iovcnt > 0) {
255 			bdev_blob_writev(ctx->dev, ctx->channel, (struct iovec *)ctx->payload, ctx->iovcnt,
256 					 ctx->lba, ctx->lba_count, ctx->cb_args);
257 		} else {
258 			bdev_blob_write(ctx->dev, ctx->channel, ctx->payload,
259 					ctx->lba, ctx->lba_count, ctx->cb_args);
260 		}
261 		break;
262 	case SPDK_BDEV_IO_TYPE_UNMAP:
263 		bdev_blob_unmap(ctx->dev, ctx->channel,
264 				ctx->lba, ctx->lba_count, ctx->cb_args);
265 		break;
266 	case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
267 		bdev_blob_write_zeroes(ctx->dev, ctx->channel,
268 				       ctx->lba, ctx->lba_count, ctx->cb_args);
269 		break;
270 	default:
271 		SPDK_ERRLOG("Unsupported io type %d\n", ctx->io_type);
272 		assert(false);
273 		break;
274 	}
275 	free(ctx);
276 }
277 
278 int
279 spdk_bs_bdev_claim(struct spdk_bs_dev *bs_dev, struct spdk_bdev_module *module)
280 {
281 	struct blob_bdev *blob_bdev = (struct blob_bdev *)bs_dev;
282 	int rc;
283 
284 	rc = spdk_bdev_module_claim_bdev(blob_bdev->bdev, NULL, module);
285 	if (rc != 0) {
286 		SPDK_ERRLOG("could not claim bs dev\n");
287 		return rc;
288 	}
289 
290 	blob_bdev->claimed = true;
291 
292 	return rc;
293 }
294 
295 static struct spdk_io_channel *
296 bdev_blob_create_channel(struct spdk_bs_dev *dev)
297 {
298 	struct blob_bdev *blob_bdev = (struct blob_bdev *)dev;
299 
300 	return spdk_bdev_get_io_channel(blob_bdev->desc);
301 }
302 
303 static void
304 bdev_blob_destroy_channel(struct spdk_bs_dev *dev, struct spdk_io_channel *channel)
305 {
306 	spdk_put_io_channel(channel);
307 }
308 
309 static void
310 bdev_blob_destroy(struct spdk_bs_dev *bs_dev)
311 {
312 	struct spdk_bdev_desc *desc = __get_desc(bs_dev);
313 	struct blob_bdev *blob_bdev = (struct blob_bdev *)bs_dev;
314 
315 	if (blob_bdev->claimed) {
316 		spdk_bdev_module_release_bdev(blob_bdev->bdev);
317 	}
318 
319 	spdk_bdev_close(desc);
320 	free(bs_dev);
321 }
322 
323 static struct spdk_bdev *
324 bdev_blob_get_base_bdev(struct spdk_bs_dev *bs_dev)
325 {
326 	return __get_bdev(bs_dev);
327 }
328 
329 static void
330 blob_bdev_init(struct blob_bdev *b, struct spdk_bdev_desc *desc)
331 {
332 	struct spdk_bdev *bdev;
333 
334 	bdev = spdk_bdev_desc_get_bdev(desc);
335 	assert(bdev != NULL);
336 
337 	b->bdev = bdev;
338 	b->desc = desc;
339 	b->bs_dev.blockcnt = spdk_bdev_get_num_blocks(bdev);
340 	b->bs_dev.blocklen = spdk_bdev_get_block_size(bdev);
341 	b->bs_dev.create_channel = bdev_blob_create_channel;
342 	b->bs_dev.destroy_channel = bdev_blob_destroy_channel;
343 	b->bs_dev.destroy = bdev_blob_destroy;
344 	b->bs_dev.read = bdev_blob_read;
345 	b->bs_dev.write = bdev_blob_write;
346 	b->bs_dev.readv = bdev_blob_readv;
347 	b->bs_dev.writev = bdev_blob_writev;
348 	b->bs_dev.write_zeroes = bdev_blob_write_zeroes;
349 	b->bs_dev.unmap = bdev_blob_unmap;
350 	b->bs_dev.get_base_bdev = bdev_blob_get_base_bdev;
351 }
352 
353 int
354 spdk_bdev_create_bs_dev_ext(const char *bdev_name, spdk_bdev_event_cb_t event_cb,
355 			    void *event_ctx, struct spdk_bs_dev **_bs_dev)
356 {
357 	struct blob_bdev *b;
358 	struct spdk_bdev_desc *desc;
359 	int rc;
360 
361 	b = calloc(1, sizeof(*b));
362 
363 	if (b == NULL) {
364 		SPDK_ERRLOG("could not allocate blob_bdev\n");
365 		return -ENOMEM;
366 	}
367 
368 	rc = spdk_bdev_open_ext(bdev_name, true, event_cb, event_ctx, &desc);
369 	if (rc != 0) {
370 		free(b);
371 		return rc;
372 	}
373 
374 	blob_bdev_init(b, desc);
375 
376 	*_bs_dev = &b->bs_dev;
377 
378 	return 0;
379 }
380