Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2017 Intel Corporation.
3 : : * All rights reserved.
4 : : * Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
5 : : */
6 : :
7 : : #include "spdk/stdinc.h"
8 : :
9 : : #include "spdk/blob_bdev.h"
10 : : #include "spdk/blob.h"
11 : : #include "spdk/thread.h"
12 : : #include "spdk/log.h"
13 : : #include "spdk/endian.h"
14 : : #define __SPDK_BDEV_MODULE_ONLY
15 : : #include "spdk/bdev_module.h"
16 : :
17 : : struct blob_bdev {
18 : : struct spdk_bs_dev bs_dev;
19 : : struct spdk_bdev *bdev;
20 : : struct spdk_bdev_desc *desc;
21 : : bool write;
22 : : int32_t refs;
23 : : struct spdk_spinlock lock;
24 : : };
25 : :
26 : : struct blob_resubmit {
27 : : struct spdk_bdev_io_wait_entry bdev_io_wait;
28 : : enum spdk_bdev_io_type io_type;
29 : : struct spdk_bs_dev *dev;
30 : : struct spdk_io_channel *channel;
31 : : void *payload;
32 : : int iovcnt;
33 : : uint64_t lba;
34 : : uint64_t src_lba;
35 : : uint32_t lba_count;
36 : : struct spdk_bs_dev_cb_args *cb_args;
37 : : struct spdk_blob_ext_io_opts *ext_io_opts;
38 : : };
39 : : static void bdev_blob_resubmit(void *);
40 : :
41 : : static inline struct spdk_bdev_desc *
42 : 21217968 : __get_desc(struct spdk_bs_dev *dev)
43 : : {
44 [ + - + - ]: 21217968 : return ((struct blob_bdev *)dev)->desc;
45 : : }
46 : :
47 : : static inline struct spdk_bdev *
48 : 235905 : __get_bdev(struct spdk_bs_dev *dev)
49 : : {
50 [ # # # # ]: 235905 : return ((struct blob_bdev *)dev)->bdev;
51 : : }
52 : :
53 : : static void
54 : 20989519 : bdev_blob_io_complete(struct spdk_bdev_io *bdev_io, bool success, void *arg)
55 : : {
56 : 20989519 : struct spdk_bs_dev_cb_args *cb_args = arg;
57 : : int bserrno;
58 : :
59 [ + - + - ]: 20989519 : if (success) {
60 : 20989519 : bserrno = 0;
61 : 377 : } else {
62 : 0 : bserrno = -EIO;
63 : : }
64 [ + - + - : 20989519 : cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, bserrno);
- + + - +
- + - + -
+ - ]
65 : 20989519 : spdk_bdev_free_io(bdev_io);
66 : 20989519 : }
67 : :
68 : : static void
69 : 228449 : bdev_blob_queue_io(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *payload,
70 : : int iovcnt, uint64_t lba, uint64_t src_lba, uint32_t lba_count,
71 : : enum spdk_bdev_io_type io_type, struct spdk_bs_dev_cb_args *cb_args,
72 : : struct spdk_blob_ext_io_opts *ext_io_opts)
73 : : {
74 : : int rc;
75 : 228449 : struct spdk_bdev *bdev = __get_bdev(dev);
76 : : struct blob_resubmit *ctx;
77 : :
78 : 228449 : ctx = calloc(1, sizeof(struct blob_resubmit));
79 : :
80 [ - + ]: 228449 : if (ctx == NULL) {
81 : 0 : SPDK_ERRLOG("Not enough memory to queue io\n");
82 [ # # # # : 0 : cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, -ENOMEM);
# # # # #
# # # # #
# # ]
83 : 0 : return;
84 : : }
85 : :
86 [ # # # # ]: 228449 : ctx->io_type = io_type;
87 [ # # # # ]: 228449 : ctx->dev = dev;
88 [ # # # # ]: 228449 : ctx->channel = channel;
89 [ # # # # ]: 228449 : ctx->payload = payload;
90 [ # # # # ]: 228449 : ctx->iovcnt = iovcnt;
91 [ # # # # ]: 228449 : ctx->lba = lba;
92 [ # # # # ]: 228449 : ctx->src_lba = src_lba;
93 [ # # # # ]: 228449 : ctx->lba_count = lba_count;
94 [ # # # # ]: 228449 : ctx->cb_args = cb_args;
95 [ # # # # : 228449 : ctx->bdev_io_wait.bdev = bdev;
# # ]
96 [ # # # # : 228449 : ctx->bdev_io_wait.cb_fn = bdev_blob_resubmit;
# # ]
97 [ # # # # : 228449 : ctx->bdev_io_wait.cb_arg = ctx;
# # ]
98 [ # # # # ]: 228449 : ctx->ext_io_opts = ext_io_opts;
99 : :
100 [ # # ]: 228449 : rc = spdk_bdev_queue_io_wait(bdev, channel, &ctx->bdev_io_wait);
101 [ - + ]: 228449 : if (rc != 0) {
102 : 0 : SPDK_ERRLOG("Queue io failed, rc=%d\n", rc);
103 [ # # # # : 0 : cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
# # # # #
# # # # #
# # ]
104 : 0 : free(ctx);
105 [ # # ]: 0 : assert(false);
106 : : }
107 : 0 : }
108 : :
109 : : static void
110 : 3927823 : bdev_blob_read(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *payload,
111 : : uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args)
112 : : {
113 : : int rc;
114 : :
115 : 3928155 : rc = spdk_bdev_read_blocks(__get_desc(dev), channel, payload, lba,
116 : 332 : lba_count, bdev_blob_io_complete, cb_args);
117 [ - + ]: 3927823 : if (rc == -ENOMEM) {
118 : 0 : bdev_blob_queue_io(dev, channel, payload, 0, lba, 0,
119 : 0 : lba_count, SPDK_BDEV_IO_TYPE_READ, cb_args, NULL);
120 [ - + ]: 3927823 : } else if (rc != 0) {
121 [ # # # # : 0 : cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
# # # # #
# # # # #
# # ]
122 : 0 : }
123 : 3927823 : }
124 : :
125 : : static void
126 : 1035538 : bdev_blob_write(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, void *payload,
127 : : uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args)
128 : : {
129 : : int rc;
130 : :
131 : 1035555 : rc = spdk_bdev_write_blocks(__get_desc(dev), channel, payload, lba,
132 : 17 : lba_count, bdev_blob_io_complete, cb_args);
133 [ - + ]: 1035538 : if (rc == -ENOMEM) {
134 : 0 : bdev_blob_queue_io(dev, channel, payload, 0, lba, 0,
135 : 0 : lba_count, SPDK_BDEV_IO_TYPE_WRITE, cb_args, NULL);
136 [ - + ]: 1035538 : } else if (rc != 0) {
137 [ # # # # : 0 : cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
# # # # #
# # # # #
# # ]
138 : 0 : }
139 : 1035538 : }
140 : :
141 : : static void
142 : 0 : bdev_blob_readv(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
143 : : struct iovec *iov, int iovcnt,
144 : : uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args)
145 : : {
146 : : int rc;
147 : :
148 : 0 : rc = spdk_bdev_readv_blocks(__get_desc(dev), channel, iov, iovcnt, lba,
149 : 0 : lba_count, bdev_blob_io_complete, cb_args);
150 [ # # ]: 0 : if (rc == -ENOMEM) {
151 : 0 : bdev_blob_queue_io(dev, channel, iov, iovcnt, lba, 0,
152 : 0 : lba_count, SPDK_BDEV_IO_TYPE_READ, cb_args, NULL);
153 [ # # ]: 0 : } else if (rc != 0) {
154 [ # # # # : 0 : cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
# # # # #
# # # # #
# # ]
155 : 0 : }
156 : 0 : }
157 : :
158 : : static void
159 : 2699 : bdev_blob_writev(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
160 : : struct iovec *iov, int iovcnt,
161 : : uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args)
162 : : {
163 : : int rc;
164 : :
165 : 2699 : rc = spdk_bdev_writev_blocks(__get_desc(dev), channel, iov, iovcnt, lba,
166 : 0 : lba_count, bdev_blob_io_complete, cb_args);
167 [ - + ]: 2699 : if (rc == -ENOMEM) {
168 : 0 : bdev_blob_queue_io(dev, channel, iov, iovcnt, lba, 0,
169 : 0 : lba_count, SPDK_BDEV_IO_TYPE_WRITE, cb_args, NULL);
170 [ - + ]: 2699 : } else if (rc != 0) {
171 [ # # # # : 0 : cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
# # # # #
# # # # #
# # ]
172 : 0 : }
173 : 2699 : }
174 : :
175 : : static inline void
176 : 16156890 : blob_ext_io_opts_to_bdev_opts(struct spdk_bdev_ext_io_opts *dst, struct spdk_blob_ext_io_opts *src)
177 : : {
178 [ - + ]: 16156890 : memset(dst, 0, sizeof(*dst));
179 [ # # # # ]: 16156890 : dst->size = sizeof(*dst);
180 [ # # # # : 16156890 : dst->memory_domain = src->memory_domain;
# # # # ]
181 [ # # # # : 16156890 : dst->memory_domain_ctx = src->memory_domain_ctx;
# # # # ]
182 : 16156890 : }
183 : :
184 : : static void
185 : 6817345 : bdev_blob_readv_ext(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
186 : : struct iovec *iov, int iovcnt,
187 : : uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args,
188 : : struct spdk_blob_ext_io_opts *io_opts)
189 : : {
190 : 6817327 : struct spdk_bdev_ext_io_opts bdev_io_opts;
191 : : int rc;
192 : :
193 : 6817345 : blob_ext_io_opts_to_bdev_opts(&bdev_io_opts, io_opts);
194 : 6817363 : rc = spdk_bdev_readv_blocks_ext(__get_desc(dev), channel, iov, iovcnt, lba, lba_count,
195 : 18 : bdev_blob_io_complete, cb_args, &bdev_io_opts);
196 [ + + ]: 6817345 : if (rc == -ENOMEM) {
197 : 144359 : bdev_blob_queue_io(dev, channel, iov, iovcnt, lba, 0, lba_count, SPDK_BDEV_IO_TYPE_READ, cb_args,
198 : 0 : io_opts);
199 [ - + ]: 6672986 : } else if (rc != 0) {
200 [ # # # # : 0 : cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
# # # # #
# # # # #
# # ]
201 : 0 : }
202 : 6817345 : }
203 : :
204 : : static void
205 : 9339545 : bdev_blob_writev_ext(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
206 : : struct iovec *iov, int iovcnt,
207 : : uint64_t lba, uint32_t lba_count, struct spdk_bs_dev_cb_args *cb_args,
208 : : struct spdk_blob_ext_io_opts *io_opts)
209 : : {
210 : 9339545 : struct spdk_bdev_ext_io_opts bdev_io_opts;
211 : : int rc;
212 : :
213 : 9339545 : blob_ext_io_opts_to_bdev_opts(&bdev_io_opts, io_opts);
214 : 9339545 : rc = spdk_bdev_writev_blocks_ext(__get_desc(dev), channel, iov, iovcnt, lba, lba_count,
215 : 0 : bdev_blob_io_complete, cb_args, &bdev_io_opts);
216 [ + + ]: 9339545 : if (rc == -ENOMEM) {
217 : 84090 : bdev_blob_queue_io(dev, channel, iov, iovcnt, lba, 0, lba_count, SPDK_BDEV_IO_TYPE_WRITE, cb_args,
218 : 0 : io_opts);
219 [ - + ]: 9255455 : } else if (rc != 0) {
220 [ # # # # : 0 : cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
# # # # #
# # # # #
# # ]
221 : 0 : }
222 : 9339545 : }
223 : :
224 : : static void
225 : 8618 : bdev_blob_write_zeroes(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, uint64_t lba,
226 : : uint64_t lba_count, struct spdk_bs_dev_cb_args *cb_args)
227 : : {
228 : : int rc;
229 : :
230 : 8626 : rc = spdk_bdev_write_zeroes_blocks(__get_desc(dev), channel, lba,
231 : 8 : lba_count, bdev_blob_io_complete, cb_args);
232 [ - + ]: 8618 : if (rc == -ENOMEM) {
233 : 0 : bdev_blob_queue_io(dev, channel, NULL, 0, lba, 0,
234 : 0 : lba_count, SPDK_BDEV_IO_TYPE_WRITE_ZEROES, cb_args, NULL);
235 [ - + ]: 8618 : } else if (rc != 0) {
236 [ # # # # : 0 : cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
# # # # #
# # # # #
# # ]
237 : 0 : }
238 : 8618 : }
239 : :
240 : : static void
241 : 239215 : bdev_blob_unmap(struct spdk_bs_dev *dev, struct spdk_io_channel *channel, uint64_t lba,
242 : : uint64_t lba_count, struct spdk_bs_dev_cb_args *cb_args)
243 : : {
244 : 239215 : struct blob_bdev *blob_bdev = (struct blob_bdev *)dev;
245 : : int rc;
246 : :
247 [ + + # # : 239215 : if (spdk_bdev_io_type_supported(blob_bdev->bdev, SPDK_BDEV_IO_TYPE_UNMAP)) {
# # ]
248 : 86348 : rc = spdk_bdev_unmap_blocks(__get_desc(dev), channel, lba, lba_count,
249 : 2 : bdev_blob_io_complete, cb_args);
250 [ - + ]: 86346 : if (rc == -ENOMEM) {
251 : 0 : bdev_blob_queue_io(dev, channel, NULL, 0, lba, 0,
252 : 0 : lba_count, SPDK_BDEV_IO_TYPE_UNMAP, cb_args, NULL);
253 [ - + ]: 86346 : } else if (rc != 0) {
254 [ # # # # : 0 : cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
# # # # #
# # # # #
# # ]
255 : 0 : }
256 : 2 : } else {
257 : : /*
258 : : * If the device doesn't support unmap, immediately complete
259 : : * the request. Blobstore does not rely on unmap zeroing
260 : : * data.
261 : : */
262 [ # # # # : 152869 : cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, 0);
# # # # #
# # # # #
# # ]
263 : : }
264 : 239215 : }
265 : :
266 : : static void
267 : 54 : bdev_blob_copy(struct spdk_bs_dev *dev, struct spdk_io_channel *channel,
268 : : uint64_t dst_lba, uint64_t src_lba, uint64_t lba_count,
269 : : struct spdk_bs_dev_cb_args *cb_args)
270 : : {
271 : : int rc;
272 : :
273 : 54 : rc = spdk_bdev_copy_blocks(__get_desc(dev), channel,
274 : 0 : dst_lba, src_lba, lba_count,
275 : 0 : bdev_blob_io_complete, cb_args);
276 [ - + ]: 54 : if (rc == -ENOMEM) {
277 : 0 : bdev_blob_queue_io(dev, channel, NULL, 0, dst_lba, src_lba,
278 : 0 : lba_count, SPDK_BDEV_IO_TYPE_COPY, cb_args, NULL);
279 [ - + ]: 54 : } else if (rc != 0) {
280 [ # # # # : 0 : cb_args->cb_fn(cb_args->channel, cb_args->cb_arg, rc);
# # # # #
# # # # #
# # ]
281 : 0 : }
282 : 54 : }
283 : :
284 : : static void
285 : 228449 : bdev_blob_resubmit(void *arg)
286 : : {
287 : 228449 : struct blob_resubmit *ctx = (struct blob_resubmit *) arg;
288 : :
289 [ + + - - : 228449 : switch (ctx->io_type) {
- - # # #
# ]
290 : 144359 : case SPDK_BDEV_IO_TYPE_READ:
291 [ + - # # : 144359 : if (ctx->iovcnt > 0) {
# # ]
292 [ + - # # : 144359 : if (ctx->ext_io_opts) {
# # ]
293 [ # # # # : 144359 : bdev_blob_readv_ext(ctx->dev, ctx->channel, (struct iovec *) ctx->payload, ctx->iovcnt,
# # # # #
# # # # #
# # ]
294 [ # # # # : 0 : ctx->lba, ctx->lba_count, ctx->cb_args, ctx->ext_io_opts);
# # # # #
# # # # #
# # ]
295 : 0 : } else {
296 [ # # # # : 0 : bdev_blob_readv(ctx->dev, ctx->channel, (struct iovec *) ctx->payload, ctx->iovcnt,
# # # # #
# # # # #
# # ]
297 [ # # # # : 0 : ctx->lba, ctx->lba_count, ctx->cb_args);
# # # # #
# # # ]
298 : : }
299 : 0 : } else {
300 [ # # # # : 0 : bdev_blob_read(ctx->dev, ctx->channel, ctx->payload,
# # # # #
# # # ]
301 [ # # # # : 0 : ctx->lba, ctx->lba_count, ctx->cb_args);
# # # # #
# # # ]
302 : : }
303 : 144359 : break;
304 : 84090 : case SPDK_BDEV_IO_TYPE_WRITE:
305 [ + - # # : 84090 : if (ctx->iovcnt > 0) {
# # ]
306 [ + - # # : 84090 : if (ctx->ext_io_opts) {
# # ]
307 [ # # # # : 84090 : bdev_blob_writev_ext(ctx->dev, ctx->channel, (struct iovec *) ctx->payload, ctx->iovcnt,
# # # # #
# # # # #
# # ]
308 [ # # # # : 0 : ctx->lba, ctx->lba_count, ctx->cb_args, ctx->ext_io_opts);
# # # # #
# # # # #
# # ]
309 : 0 : } else {
310 [ # # # # : 0 : bdev_blob_writev(ctx->dev, ctx->channel, (struct iovec *) ctx->payload, ctx->iovcnt,
# # # # #
# # # # #
# # ]
311 [ # # # # : 0 : ctx->lba, ctx->lba_count, ctx->cb_args);
# # # # #
# # # ]
312 : : }
313 : 0 : } else {
314 [ # # # # : 0 : bdev_blob_write(ctx->dev, ctx->channel, ctx->payload,
# # # # #
# # # ]
315 [ # # # # : 0 : ctx->lba, ctx->lba_count, ctx->cb_args);
# # # # #
# # # ]
316 : : }
317 : 84090 : break;
318 : 0 : case SPDK_BDEV_IO_TYPE_UNMAP:
319 [ # # # # : 0 : bdev_blob_unmap(ctx->dev, ctx->channel,
# # # # ]
320 [ # # # # : 0 : ctx->lba, ctx->lba_count, ctx->cb_args);
# # # # #
# # # ]
321 : 0 : break;
322 : 0 : case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
323 [ # # # # : 0 : bdev_blob_write_zeroes(ctx->dev, ctx->channel,
# # # # ]
324 [ # # # # : 0 : ctx->lba, ctx->lba_count, ctx->cb_args);
# # # # #
# # # ]
325 : 0 : break;
326 : 0 : case SPDK_BDEV_IO_TYPE_COPY:
327 [ # # # # : 0 : bdev_blob_copy(ctx->dev, ctx->channel,
# # # # ]
328 [ # # # # : 0 : ctx->lba, ctx->src_lba, ctx->lba_count, ctx->cb_args);
# # # # #
# # # # #
# # ]
329 : 0 : break;
330 : 0 : default:
331 [ # # # # ]: 0 : SPDK_ERRLOG("Unsupported io type %d\n", ctx->io_type);
332 [ # # ]: 0 : assert(false);
333 : : break;
334 : : }
335 : 228449 : free(ctx);
336 : 228449 : }
337 : :
338 : : int
339 : 335 : spdk_bs_bdev_claim(struct spdk_bs_dev *bs_dev, struct spdk_bdev_module *module)
340 : : {
341 : 335 : struct blob_bdev *blob_bdev = (struct blob_bdev *)bs_dev;
342 [ # # # # ]: 335 : struct spdk_bdev_desc *desc = blob_bdev->desc;
343 : : enum spdk_bdev_claim_type claim_type;
344 : : int rc;
345 : :
346 [ - + + + : 335 : claim_type = blob_bdev->write ? SPDK_BDEV_CLAIM_READ_MANY_WRITE_ONE :
# # ]
347 : : SPDK_BDEV_CLAIM_READ_MANY_WRITE_NONE;
348 : 335 : rc = spdk_bdev_module_claim_bdev_desc(desc, claim_type, NULL, module);
349 [ + + ]: 335 : if (rc != 0) {
350 : 4 : SPDK_ERRLOG("could not claim bs dev\n");
351 : 4 : return rc;
352 : : }
353 : :
354 : 331 : return rc;
355 : 5 : }
356 : :
357 : : static struct spdk_io_channel *
358 : 6362 : bdev_blob_create_channel(struct spdk_bs_dev *dev)
359 : : {
360 : 6362 : struct blob_bdev *blob_bdev = (struct blob_bdev *)dev;
361 : : struct spdk_io_channel *ch;
362 : :
363 [ + - + - ]: 6362 : ch = spdk_bdev_get_io_channel(blob_bdev->desc);
364 [ + + ]: 6362 : if (ch != NULL) {
365 [ + - ]: 6358 : spdk_spin_lock(&blob_bdev->lock);
366 [ + - + - ]: 6358 : blob_bdev->refs++;
367 [ + - ]: 6358 : spdk_spin_unlock(&blob_bdev->lock);
368 : 291 : }
369 : :
370 : 6362 : return ch;
371 : : }
372 : :
373 : : static void
374 : 6262 : bdev_blob_free(struct blob_bdev *blob_bdev)
375 : : {
376 [ + + + - : 6262 : assert(blob_bdev->refs == 0);
+ - # # ]
377 : :
378 [ + - ]: 6262 : spdk_spin_destroy(&blob_bdev->lock);
379 : 6262 : free(blob_bdev);
380 : 6262 : }
381 : :
382 : : static void
383 : 6358 : bdev_blob_destroy_channel(struct spdk_bs_dev *dev, struct spdk_io_channel *channel)
384 : : {
385 : 6358 : struct blob_bdev *blob_bdev = (struct blob_bdev *)dev;
386 : : int32_t refs;
387 : :
388 [ + - ]: 6358 : spdk_spin_lock(&blob_bdev->lock);
389 : :
390 [ + + + - : 6358 : assert(blob_bdev->refs > 0);
+ - # # ]
391 [ + - + - ]: 6358 : blob_bdev->refs--;
392 [ + - + - ]: 6358 : refs = blob_bdev->refs;
393 : :
394 [ + - ]: 6358 : spdk_spin_unlock(&blob_bdev->lock);
395 : :
396 : 6358 : spdk_put_io_channel(channel);
397 : :
398 : : /*
399 : : * If the value of blob_bdev->refs taken while holding blob_bdev->refs is zero, the blob and
400 : : * this channel have been destroyed. This means that dev->destroy() has been called and it
401 : : * would be an error (akin to use after free) if dev is dereferenced after destroying it.
402 : : * Thus, there should be no race with bdev_blob_create_channel().
403 : : *
404 : : * Because the value of blob_bdev->refs was taken while holding the lock here and the same
405 : : * is done in bdev_blob_destroy(), there is no race with bdev_blob_destroy().
406 : : */
407 [ + + ]: 6358 : if (refs == 0) {
408 : 8 : bdev_blob_free(blob_bdev);
409 : 2 : }
410 : 6358 : }
411 : :
412 : : static void
413 : 6262 : bdev_blob_destroy(struct spdk_bs_dev *bs_dev)
414 : : {
415 : 6262 : struct blob_bdev *blob_bdev = (struct blob_bdev *)bs_dev;
416 : : struct spdk_bdev_desc *desc;
417 : : int32_t refs;
418 : :
419 [ + - ]: 6262 : spdk_spin_lock(&blob_bdev->lock);
420 : :
421 [ + - + - ]: 6262 : desc = blob_bdev->desc;
422 [ + - + - ]: 6262 : blob_bdev->desc = NULL;
423 [ + - + - ]: 6262 : blob_bdev->refs--;
424 [ + - + - ]: 6262 : refs = blob_bdev->refs;
425 : :
426 [ + - ]: 6262 : spdk_spin_unlock(&blob_bdev->lock);
427 : :
428 : 6262 : spdk_bdev_close(desc);
429 : :
430 : : /*
431 : : * If the value of blob_bdev->refs taken while holding blob_bdev->refs is zero,
432 : : * bs_dev->destroy() has been called and all the channels have been destroyed. It would be
433 : : * an error (akin to use after free) if bs_dev is dereferenced after destroying it. Thus,
434 : : * there should be no race with bdev_blob_create_channel().
435 : : *
436 : : * Because the value of blob_bdev->refs was taken while holding the lock here and the same
437 : : * is done in bdev_blob_destroy_channel(), there is no race with
438 : : * bdev_blob_destroy_channel().
439 : : */
440 [ + + ]: 6262 : if (refs == 0) {
441 : 6254 : bdev_blob_free(blob_bdev);
442 : 295 : }
443 : 6262 : }
444 : :
445 : : static struct spdk_bdev *
446 : 7448 : bdev_blob_get_base_bdev(struct spdk_bs_dev *bs_dev)
447 : : {
448 : 7448 : return __get_bdev(bs_dev);
449 : : }
450 : :
451 : : static bool
452 : 8 : bdev_blob_is_zeroes(struct spdk_bs_dev *dev, uint64_t lba, uint64_t lba_count)
453 : : {
454 : 8 : return false;
455 : : }
456 : :
457 : : static bool
458 : 8 : bdev_blob_is_range_valid(struct spdk_bs_dev *dev, uint64_t lba, uint64_t lba_count)
459 : : {
460 : 8 : struct spdk_bdev *bdev = __get_bdev(dev);
461 : :
462 : : /* The lba requested should be within the bounds of this bs_dev. */
463 [ - + ]: 8 : if (lba >= spdk_bdev_get_num_blocks(bdev)) {
464 : 0 : return false;
465 [ - + ]: 8 : } else if (lba + lba_count > spdk_bdev_get_num_blocks(bdev)) {
466 : : /* bdevs used for esnaps must currently be an exact multiple of the
467 : : * blobstore cluster size (see spdk_lvol_create_esnap_clone()), but if that
468 : : * ever changes this code here needs to be updated to account for it. */
469 : 0 : SPDK_ERRLOG("Entire range must be within the bs_dev bounds for CoW.\n"
470 : : "lba(lba_count): %lu(%lu), num_blks: %lu\n", lba, lba_count, spdk_bdev_get_num_blocks(bdev));
471 [ # # ]: 0 : assert(false);
472 : : return false;
473 : : }
474 : :
475 : 8 : return true;
476 : 0 : }
477 : :
478 : : static bool
479 : 0 : bdev_blob_translate_lba(struct spdk_bs_dev *dev, uint64_t lba, uint64_t *base_lba)
480 : : {
481 [ # # ]: 0 : *base_lba = lba;
482 : 0 : return true;
483 : : }
484 : :
485 : : static void
486 : 6262 : blob_bdev_init(struct blob_bdev *b, struct spdk_bdev_desc *desc)
487 : : {
488 : : struct spdk_bdev *bdev;
489 : :
490 : 6262 : bdev = spdk_bdev_desc_get_bdev(desc);
491 [ + + # # ]: 6262 : assert(bdev != NULL);
492 : :
493 [ + - + - ]: 6262 : b->bdev = bdev;
494 [ + - + - ]: 6262 : b->desc = desc;
495 [ + - + - : 6262 : b->bs_dev.blockcnt = spdk_bdev_get_num_blocks(bdev);
+ - ]
496 [ + - + - : 6262 : b->bs_dev.blocklen = spdk_bdev_get_block_size(bdev);
+ - ]
497 [ + - + - : 6262 : b->bs_dev.create_channel = bdev_blob_create_channel;
+ - ]
498 [ + - + - : 6262 : b->bs_dev.destroy_channel = bdev_blob_destroy_channel;
+ - ]
499 [ + - + - : 6262 : b->bs_dev.destroy = bdev_blob_destroy;
+ - ]
500 [ + - + - : 6262 : b->bs_dev.read = bdev_blob_read;
+ - ]
501 [ + - + - : 6262 : b->bs_dev.write = bdev_blob_write;
+ - ]
502 [ + - + - : 6262 : b->bs_dev.readv = bdev_blob_readv;
+ - ]
503 [ + - + - : 6262 : b->bs_dev.writev = bdev_blob_writev;
+ - ]
504 [ + - + - : 6262 : b->bs_dev.readv_ext = bdev_blob_readv_ext;
+ - ]
505 [ + - + - : 6262 : b->bs_dev.writev_ext = bdev_blob_writev_ext;
+ - ]
506 [ + - + - : 6262 : b->bs_dev.write_zeroes = bdev_blob_write_zeroes;
+ - ]
507 [ + - + - : 6262 : b->bs_dev.unmap = bdev_blob_unmap;
+ - ]
508 [ + + ]: 6262 : if (spdk_bdev_io_type_supported(bdev, SPDK_BDEV_IO_TYPE_COPY)) {
509 [ + - + - : 3971 : b->bs_dev.copy = bdev_blob_copy;
+ - ]
510 : 242 : }
511 [ + - + - : 6262 : b->bs_dev.get_base_bdev = bdev_blob_get_base_bdev;
+ - ]
512 [ + - + - : 6262 : b->bs_dev.is_zeroes = bdev_blob_is_zeroes;
+ - ]
513 [ + - + - : 6262 : b->bs_dev.is_range_valid = bdev_blob_is_range_valid;
+ - ]
514 [ + - + - : 6262 : b->bs_dev.translate_lba = bdev_blob_translate_lba;
+ - ]
515 : 6262 : }
516 : :
517 : : void
518 : 2 : spdk_bdev_update_bs_blockcnt(struct spdk_bs_dev *bs_dev)
519 : : {
520 : 2 : struct blob_bdev *blob_bdev = (struct blob_bdev *)bs_dev;
521 : :
522 [ - + # # : 2 : assert(bs_dev->blocklen == spdk_bdev_get_block_size(blob_bdev->bdev));
# # # # #
# # # ]
523 [ # # # # : 2 : bs_dev->blockcnt = spdk_bdev_get_num_blocks(blob_bdev->bdev);
# # # # ]
524 : 2 : }
525 : :
526 : : int
527 : 6295 : spdk_bdev_create_bs_dev(const char *bdev_name, bool write,
528 : : struct spdk_bdev_bs_dev_opts *opts, size_t opts_size,
529 : : spdk_bdev_event_cb_t event_cb, void *event_ctx,
530 : : struct spdk_bs_dev **bs_dev)
531 : : {
532 : : struct blob_bdev *b;
533 : 5994 : struct spdk_bdev_desc *desc;
534 : : int rc;
535 : :
536 [ + + # # ]: 6295 : assert(spdk_get_thread() != NULL);
537 : :
538 [ + + + + ]: 6295 : if (opts != NULL && opts_size != sizeof(*opts)) {
539 : 4 : SPDK_ERRLOG("bdev name '%s': unsupported options\n", bdev_name);
540 : 4 : return -EINVAL;
541 : : }
542 : :
543 : 6291 : b = calloc(1, sizeof(*b));
544 : :
545 [ + + ]: 6291 : if (b == NULL) {
546 : 0 : SPDK_ERRLOG("could not allocate blob_bdev\n");
547 : 0 : return -ENOMEM;
548 : : }
549 : :
550 [ + - ]: 6291 : rc = spdk_bdev_open_ext(bdev_name, write, event_cb, event_ctx, &desc);
551 [ + + ]: 6291 : if (rc != 0) {
552 : 29 : free(b);
553 : 29 : return rc;
554 : : }
555 : :
556 : 6262 : blob_bdev_init(b, desc);
557 : :
558 [ + - + - ]: 6262 : *bs_dev = &b->bs_dev;
559 [ + - + - : 6262 : b->write = write;
+ - ]
560 [ + - + - ]: 6262 : b->refs = 1;
561 [ + - ]: 6262 : spdk_spin_init(&b->lock);
562 : :
563 : 6262 : return 0;
564 : 301 : }
565 : :
566 : : int
567 : 6217 : spdk_bdev_create_bs_dev_ext(const char *bdev_name, spdk_bdev_event_cb_t event_cb,
568 : : void *event_ctx, struct spdk_bs_dev **bs_dev)
569 : : {
570 : 6217 : return spdk_bdev_create_bs_dev(bdev_name, true, NULL, 0, event_cb, event_ctx, bs_dev);
571 : : }
|