4 * Copyright (c) Intel Corporation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
35 * Common code for partition-like virtual bdevs.
38 #include "spdk/bdev.h"
40 #include "spdk/string.h"
42 #include "spdk/bdev_module.h"
44 struct spdk_bdev_part_base
{
45 struct spdk_bdev
*bdev
;
46 struct spdk_bdev_desc
*desc
;
48 uint32_t channel_size
;
49 spdk_bdev_part_base_free_fn base_free_fn
;
52 struct spdk_bdev_module
*module
;
53 struct spdk_bdev_fn_table
*fn_table
;
54 struct bdev_part_tailq
*tailq
;
55 spdk_io_channel_create_cb ch_create_cb
;
56 spdk_io_channel_destroy_cb ch_destroy_cb
;
60 spdk_bdev_part_base_get_bdev(struct spdk_bdev_part_base
*part_base
)
62 return part_base
->bdev
;
65 struct spdk_bdev_desc
*
66 spdk_bdev_part_base_get_desc(struct spdk_bdev_part_base
*part_base
)
68 return part_base
->desc
;
71 struct bdev_part_tailq
*
72 spdk_bdev_part_base_get_tailq(struct spdk_bdev_part_base
*part_base
)
74 return part_base
->tailq
;
78 spdk_bdev_part_base_get_ctx(struct spdk_bdev_part_base
*part_base
)
80 return part_base
->ctx
;
84 spdk_bdev_part_base_free(struct spdk_bdev_part_base
*base
)
87 spdk_bdev_close(base
->desc
);
91 if (base
->base_free_fn
!= NULL
) {
92 base
->base_free_fn(base
->ctx
);
99 spdk_bdev_part_free_cb(void *io_device
)
101 struct spdk_bdev_part
*part
= io_device
;
102 struct spdk_bdev_part_base
*base
;
105 assert(part
->internal
.base
);
107 base
= part
->internal
.base
;
109 TAILQ_REMOVE(base
->tailq
, part
, tailq
);
111 if (__sync_sub_and_fetch(&base
->ref
, 1) == 0) {
112 spdk_bdev_module_release_bdev(base
->bdev
);
113 spdk_bdev_part_base_free(base
);
116 spdk_bdev_destruct_done(&part
->internal
.bdev
, 0);
117 free(part
->internal
.bdev
.name
);
118 free(part
->internal
.bdev
.product_name
);
123 spdk_bdev_part_free(struct spdk_bdev_part
*part
)
125 spdk_io_device_unregister(part
, spdk_bdev_part_free_cb
);
127 /* Return 1 to indicate that this is an asynchronous operation that isn't complete
128 * until spdk_bdev_destruct_done is called */
133 spdk_bdev_part_base_hotremove(struct spdk_bdev
*base_bdev
, struct bdev_part_tailq
*tailq
)
135 struct spdk_bdev_part
*part
, *tmp
;
137 TAILQ_FOREACH_SAFE(part
, tailq
, tailq
, tmp
) {
138 if (part
->internal
.base
->bdev
== base_bdev
) {
139 spdk_bdev_unregister(&part
->internal
.bdev
, NULL
, NULL
);
145 spdk_bdev_part_io_type_supported(void *_part
, enum spdk_bdev_io_type io_type
)
147 struct spdk_bdev_part
*part
= _part
;
149 return part
->internal
.base
->bdev
->fn_table
->io_type_supported(part
->internal
.base
->bdev
->ctxt
,
153 static struct spdk_io_channel
*
154 spdk_bdev_part_get_io_channel(void *_part
)
156 struct spdk_bdev_part
*part
= _part
;
158 return spdk_get_io_channel(part
);
162 spdk_bdev_part_get_bdev(struct spdk_bdev_part
*part
)
164 return &part
->internal
.bdev
;
167 struct spdk_bdev_part_base
*
168 spdk_bdev_part_get_base(struct spdk_bdev_part
*part
)
170 return part
->internal
.base
;
174 spdk_bdev_part_get_base_bdev(struct spdk_bdev_part
*part
)
176 return part
->internal
.base
->bdev
;
180 spdk_bdev_part_get_offset_blocks(struct spdk_bdev_part
*part
)
182 return part
->internal
.offset_blocks
;
186 spdk_bdev_part_complete_io(struct spdk_bdev_io
*bdev_io
, bool success
, void *cb_arg
)
188 struct spdk_bdev_io
*part_io
= cb_arg
;
189 int status
= success
? SPDK_BDEV_IO_STATUS_SUCCESS
: SPDK_BDEV_IO_STATUS_FAILED
;
191 spdk_bdev_io_complete(part_io
, status
);
192 spdk_bdev_free_io(bdev_io
);
196 spdk_bdev_part_submit_request(struct spdk_bdev_part_channel
*ch
, struct spdk_bdev_io
*bdev_io
)
198 struct spdk_bdev_part
*part
= ch
->part
;
199 struct spdk_io_channel
*base_ch
= ch
->base_ch
;
200 struct spdk_bdev_desc
*base_desc
= part
->internal
.base
->desc
;
204 /* Modify the I/O to adjust for the offset within the base bdev. */
205 switch (bdev_io
->type
) {
206 case SPDK_BDEV_IO_TYPE_READ
:
207 offset
= bdev_io
->u
.bdev
.offset_blocks
+ part
->internal
.offset_blocks
;
208 rc
= spdk_bdev_readv_blocks(base_desc
, base_ch
, bdev_io
->u
.bdev
.iovs
,
209 bdev_io
->u
.bdev
.iovcnt
, offset
,
210 bdev_io
->u
.bdev
.num_blocks
, spdk_bdev_part_complete_io
,
213 case SPDK_BDEV_IO_TYPE_WRITE
:
214 offset
= bdev_io
->u
.bdev
.offset_blocks
+ part
->internal
.offset_blocks
;
215 rc
= spdk_bdev_writev_blocks(base_desc
, base_ch
, bdev_io
->u
.bdev
.iovs
,
216 bdev_io
->u
.bdev
.iovcnt
, offset
,
217 bdev_io
->u
.bdev
.num_blocks
, spdk_bdev_part_complete_io
,
220 case SPDK_BDEV_IO_TYPE_WRITE_ZEROES
:
221 offset
= bdev_io
->u
.bdev
.offset_blocks
+ part
->internal
.offset_blocks
;
222 rc
= spdk_bdev_write_zeroes_blocks(base_desc
, base_ch
, offset
, bdev_io
->u
.bdev
.num_blocks
,
223 spdk_bdev_part_complete_io
, bdev_io
);
225 case SPDK_BDEV_IO_TYPE_UNMAP
:
226 offset
= bdev_io
->u
.bdev
.offset_blocks
+ part
->internal
.offset_blocks
;
227 rc
= spdk_bdev_unmap_blocks(base_desc
, base_ch
, offset
, bdev_io
->u
.bdev
.num_blocks
,
228 spdk_bdev_part_complete_io
, bdev_io
);
230 case SPDK_BDEV_IO_TYPE_FLUSH
:
231 offset
= bdev_io
->u
.bdev
.offset_blocks
+ part
->internal
.offset_blocks
;
232 rc
= spdk_bdev_flush_blocks(base_desc
, base_ch
, offset
, bdev_io
->u
.bdev
.num_blocks
,
233 spdk_bdev_part_complete_io
, bdev_io
);
235 case SPDK_BDEV_IO_TYPE_RESET
:
236 rc
= spdk_bdev_reset(base_desc
, base_ch
,
237 spdk_bdev_part_complete_io
, bdev_io
);
240 SPDK_ERRLOG("split: unknown I/O type %d\n", bdev_io
->type
);
241 return SPDK_BDEV_IO_STATUS_FAILED
;
248 spdk_bdev_part_channel_create_cb(void *io_device
, void *ctx_buf
)
250 struct spdk_bdev_part
*part
= (struct spdk_bdev_part
*)io_device
;
251 struct spdk_bdev_part_channel
*ch
= ctx_buf
;
254 ch
->base_ch
= spdk_bdev_get_io_channel(part
->internal
.base
->desc
);
255 if (ch
->base_ch
== NULL
) {
259 if (part
->internal
.base
->ch_create_cb
) {
260 return part
->internal
.base
->ch_create_cb(io_device
, ctx_buf
);
267 spdk_bdev_part_channel_destroy_cb(void *io_device
, void *ctx_buf
)
269 struct spdk_bdev_part
*part
= (struct spdk_bdev_part
*)io_device
;
270 struct spdk_bdev_part_channel
*ch
= ctx_buf
;
272 if (part
->internal
.base
->ch_destroy_cb
) {
273 part
->internal
.base
->ch_destroy_cb(io_device
, ctx_buf
);
275 spdk_put_io_channel(ch
->base_ch
);
278 struct spdk_bdev_part_base
*
279 spdk_bdev_part_base_construct(struct spdk_bdev
*bdev
,
280 spdk_bdev_remove_cb_t remove_cb
, struct spdk_bdev_module
*module
,
281 struct spdk_bdev_fn_table
*fn_table
, struct bdev_part_tailq
*tailq
,
282 spdk_bdev_part_base_free_fn free_fn
, void *ctx
,
283 uint32_t channel_size
, spdk_io_channel_create_cb ch_create_cb
,
284 spdk_io_channel_destroy_cb ch_destroy_cb
)
287 struct spdk_bdev_part_base
*base
;
289 base
= calloc(1, sizeof(*base
));
291 SPDK_ERRLOG("Memory allocation failure\n");
294 fn_table
->get_io_channel
= spdk_bdev_part_get_io_channel
;
295 fn_table
->io_type_supported
= spdk_bdev_part_io_type_supported
;
300 base
->module
= module
;
301 base
->fn_table
= fn_table
;
303 base
->base_free_fn
= free_fn
;
305 base
->claimed
= false;
306 base
->channel_size
= channel_size
;
307 base
->ch_create_cb
= ch_create_cb
;
308 base
->ch_destroy_cb
= ch_destroy_cb
;
310 rc
= spdk_bdev_open(bdev
, false, remove_cb
, bdev
, &base
->desc
);
312 spdk_bdev_part_base_free(base
);
313 SPDK_ERRLOG("could not open bdev %s\n", spdk_bdev_get_name(bdev
));
321 spdk_bdev_part_construct(struct spdk_bdev_part
*part
, struct spdk_bdev_part_base
*base
,
322 char *name
, uint64_t offset_blocks
, uint64_t num_blocks
,
325 part
->internal
.bdev
.blocklen
= base
->bdev
->blocklen
;
326 part
->internal
.bdev
.blockcnt
= num_blocks
;
327 part
->internal
.offset_blocks
= offset_blocks
;
329 part
->internal
.bdev
.write_cache
= base
->bdev
->write_cache
;
330 part
->internal
.bdev
.need_aligned_buffer
= base
->bdev
->need_aligned_buffer
;
331 part
->internal
.bdev
.ctxt
= part
;
332 part
->internal
.bdev
.module
= base
->module
;
333 part
->internal
.bdev
.fn_table
= base
->fn_table
;
335 part
->internal
.bdev
.name
= strdup(name
);
336 part
->internal
.bdev
.product_name
= strdup(product_name
);
338 if (part
->internal
.bdev
.name
== NULL
) {
339 SPDK_ERRLOG("Failed to allocate name for new part of bdev %s\n", spdk_bdev_get_name(base
->bdev
));
341 } else if (part
->internal
.bdev
.product_name
== NULL
) {
342 free(part
->internal
.bdev
.name
);
343 SPDK_ERRLOG("Failed to allocate product name for new part of bdev %s\n",
344 spdk_bdev_get_name(base
->bdev
));
348 __sync_fetch_and_add(&base
->ref
, 1);
349 part
->internal
.base
= base
;
351 if (!base
->claimed
) {
354 rc
= spdk_bdev_module_claim_bdev(base
->bdev
, base
->desc
, base
->module
);
356 SPDK_ERRLOG("could not claim bdev %s\n", spdk_bdev_get_name(base
->bdev
));
357 free(part
->internal
.bdev
.name
);
358 free(part
->internal
.bdev
.product_name
);
361 base
->claimed
= true;
364 spdk_io_device_register(part
, spdk_bdev_part_channel_create_cb
,
365 spdk_bdev_part_channel_destroy_cb
,
369 spdk_vbdev_register(&part
->internal
.bdev
, &base
->bdev
, 1);
370 TAILQ_INSERT_TAIL(base
->tailq
, part
, tailq
);