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 * This driver reads a GPT partition table from a bdev and exposes a virtual block device for
41 #include "spdk/conf.h"
42 #include "spdk/endian.h"
44 #include "spdk/thread.h"
46 #include "spdk/string.h"
47 #include "spdk/util.h"
49 #include "spdk/bdev_module.h"
50 #include "spdk_internal/log.h"
52 static int vbdev_gpt_init(void);
53 static void vbdev_gpt_examine(struct spdk_bdev
*bdev
);
54 static int vbdev_gpt_get_ctx_size(void);
56 static struct spdk_bdev_module gpt_if
= {
58 .module_init
= vbdev_gpt_init
,
59 .get_ctx_size
= vbdev_gpt_get_ctx_size
,
60 .examine_disk
= vbdev_gpt_examine
,
63 SPDK_BDEV_MODULE_REGISTER(&gpt_if
)
65 /* Base block device gpt context */
68 struct spdk_bdev_part_base
*part_base
;
70 /* This channel is only used for reading the partition table. */
71 struct spdk_io_channel
*ch
;
74 /* Context for each gpt virtual bdev */
76 struct spdk_bdev_part part
;
77 uint32_t partition_index
;
81 struct spdk_bdev_part_channel part_ch
;
85 struct spdk_io_channel
*ch
;
86 struct spdk_bdev_io
*bdev_io
;
88 /* for bdev_io_wait */
89 struct spdk_bdev_io_wait_entry bdev_io_wait
;
92 static SPDK_BDEV_PART_TAILQ g_gpt_disks
= TAILQ_HEAD_INITIALIZER(g_gpt_disks
);
94 static bool g_gpt_disabled
;
97 spdk_gpt_base_free(void *ctx
)
99 struct gpt_base
*gpt_base
= ctx
;
101 spdk_dma_free(gpt_base
->gpt
.buf
);
106 spdk_gpt_base_bdev_hotremove_cb(void *_base_bdev
)
108 spdk_bdev_part_base_hotremove(_base_bdev
, &g_gpt_disks
);
111 static int vbdev_gpt_destruct(void *ctx
);
112 static void vbdev_gpt_submit_request(struct spdk_io_channel
*_ch
, struct spdk_bdev_io
*bdev_io
);
113 static int vbdev_gpt_dump_info_json(void *ctx
, struct spdk_json_write_ctx
*w
);
115 static struct spdk_bdev_fn_table vbdev_gpt_fn_table
= {
116 .destruct
= vbdev_gpt_destruct
,
117 .submit_request
= vbdev_gpt_submit_request
,
118 .dump_info_json
= vbdev_gpt_dump_info_json
,
121 static struct gpt_base
*
122 spdk_gpt_base_bdev_init(struct spdk_bdev
*bdev
)
124 struct gpt_base
*gpt_base
;
125 struct spdk_gpt
*gpt
;
127 gpt_base
= calloc(1, sizeof(*gpt_base
));
129 SPDK_ERRLOG("Cannot alloc memory for gpt_base pointer\n");
133 gpt_base
->part_base
= spdk_bdev_part_base_construct(bdev
,
134 spdk_gpt_base_bdev_hotremove_cb
,
135 &gpt_if
, &vbdev_gpt_fn_table
,
136 &g_gpt_disks
, spdk_gpt_base_free
, gpt_base
,
137 sizeof(struct gpt_channel
), NULL
, NULL
);
138 if (!gpt_base
->part_base
) {
140 SPDK_ERRLOG("cannot construct gpt_base");
144 gpt
= &gpt_base
->gpt
;
145 gpt
->buf_size
= spdk_max(SPDK_GPT_BUFFER_SIZE
, bdev
->blocklen
);
146 gpt
->buf
= spdk_dma_zmalloc(gpt
->buf_size
, spdk_bdev_get_buf_align(bdev
), NULL
);
148 SPDK_ERRLOG("Cannot alloc buf\n");
149 spdk_bdev_part_base_free(gpt_base
->part_base
);
153 gpt
->sector_size
= bdev
->blocklen
;
154 gpt
->total_sectors
= bdev
->blockcnt
;
156 gpt
->lba_end
= gpt
->total_sectors
- 1;
162 vbdev_gpt_destruct(void *ctx
)
164 struct gpt_disk
*gpt_disk
= ctx
;
166 return spdk_bdev_part_free(&gpt_disk
->part
);
170 vbdev_gpt_resubmit_request(void *arg
)
172 struct gpt_io
*io
= (struct gpt_io
*)arg
;
174 vbdev_gpt_submit_request(io
->ch
, io
->bdev_io
);
178 vbdev_gpt_queue_io(struct gpt_io
*io
)
182 io
->bdev_io_wait
.bdev
= io
->bdev_io
->bdev
;
183 io
->bdev_io_wait
.cb_fn
= vbdev_gpt_resubmit_request
;
184 io
->bdev_io_wait
.cb_arg
= io
;
186 rc
= spdk_bdev_queue_io_wait(io
->bdev_io
->bdev
,
187 io
->ch
, &io
->bdev_io_wait
);
189 SPDK_ERRLOG("Queue io failed in vbdev_gpt_queue_io, rc=%d.\n", rc
);
190 spdk_bdev_io_complete(io
->bdev_io
, SPDK_BDEV_IO_STATUS_FAILED
);
195 vbdev_gpt_submit_request(struct spdk_io_channel
*_ch
, struct spdk_bdev_io
*bdev_io
)
197 struct gpt_channel
*ch
= spdk_io_channel_get_ctx(_ch
);
198 struct gpt_io
*io
= (struct gpt_io
*)bdev_io
->driver_ctx
;
201 rc
= spdk_bdev_part_submit_request(&ch
->part_ch
, bdev_io
);
204 SPDK_DEBUGLOG(SPDK_LOG_VBDEV_GPT
, "gpt: no memory, queue io\n");
206 io
->bdev_io
= bdev_io
;
207 vbdev_gpt_queue_io(io
);
209 SPDK_ERRLOG("gpt: error on bdev_io submission, rc=%d.\n", rc
);
210 spdk_bdev_io_complete(bdev_io
, SPDK_BDEV_IO_STATUS_FAILED
);
216 write_guid(struct spdk_json_write_ctx
*w
, const struct spdk_gpt_guid
*guid
)
218 spdk_json_write_string_fmt(w
, "%08x-%04x-%04x-%04x-%04x%08x",
219 from_le32(&guid
->raw
[0]),
220 from_le16(&guid
->raw
[4]),
221 from_le16(&guid
->raw
[6]),
222 from_be16(&guid
->raw
[8]),
223 from_be16(&guid
->raw
[10]),
224 from_be32(&guid
->raw
[12]));
228 write_string_utf16le(struct spdk_json_write_ctx
*w
, const uint16_t *str
, size_t max_len
)
233 for (len
= 0, p
= str
; len
< max_len
&& *p
; p
++) {
237 spdk_json_write_string_utf16le_raw(w
, str
, len
);
241 vbdev_gpt_dump_info_json(void *ctx
, struct spdk_json_write_ctx
*w
)
243 struct gpt_disk
*gpt_disk
= SPDK_CONTAINEROF(ctx
, struct gpt_disk
, part
);
244 struct spdk_bdev_part_base
*base_bdev
= spdk_bdev_part_get_base(&gpt_disk
->part
);
245 struct gpt_base
*gpt_base
= spdk_bdev_part_base_get_ctx(base_bdev
);
246 struct spdk_bdev
*part_base_bdev
= spdk_bdev_part_base_get_bdev(base_bdev
);
247 struct spdk_gpt
*gpt
= &gpt_base
->gpt
;
248 struct spdk_gpt_partition_entry
*gpt_entry
= &gpt
->partitions
[gpt_disk
->partition_index
];
249 uint64_t offset_blocks
= spdk_bdev_part_get_offset_blocks(&gpt_disk
->part
);
251 spdk_json_write_name(w
, "gpt");
252 spdk_json_write_object_begin(w
);
254 spdk_json_write_name(w
, "base_bdev");
255 spdk_json_write_string(w
, spdk_bdev_get_name(part_base_bdev
));
257 spdk_json_write_name(w
, "offset_blocks");
258 spdk_json_write_uint64(w
, offset_blocks
);
260 spdk_json_write_name(w
, "partition_type_guid");
261 write_guid(w
, &gpt_entry
->part_type_guid
);
263 spdk_json_write_name(w
, "unique_partition_guid");
264 write_guid(w
, &gpt_entry
->unique_partition_guid
);
266 spdk_json_write_name(w
, "partition_name");
267 write_string_utf16le(w
, gpt_entry
->partition_name
, SPDK_COUNTOF(gpt_entry
->partition_name
));
269 spdk_json_write_object_end(w
);
275 vbdev_gpt_create_bdevs(struct gpt_base
*gpt_base
)
277 uint32_t num_partition_entries
;
278 uint64_t i
, head_lba_start
, head_lba_end
;
279 uint32_t num_partitions
;
280 struct spdk_gpt_partition_entry
*p
;
282 struct spdk_gpt
*gpt
;
284 struct spdk_bdev
*base_bdev
;
287 gpt
= &gpt_base
->gpt
;
288 num_partition_entries
= from_le32(&gpt
->header
->num_partition_entries
);
289 head_lba_start
= from_le64(&gpt
->header
->first_usable_lba
);
290 head_lba_end
= from_le64(&gpt
->header
->last_usable_lba
);
293 for (i
= 0; i
< num_partition_entries
; i
++) {
294 p
= &gpt
->partitions
[i
];
295 uint64_t lba_start
= from_le64(&p
->starting_lba
);
296 uint64_t lba_end
= from_le64(&p
->ending_lba
);
298 if (!SPDK_GPT_GUID_EQUAL(&gpt
->partitions
[i
].part_type_guid
,
299 &SPDK_GPT_PART_TYPE_GUID
) ||
303 if (lba_start
< head_lba_start
|| lba_end
> head_lba_end
) {
307 d
= calloc(1, sizeof(*d
));
309 SPDK_ERRLOG("Memory allocation failure\n");
313 /* index start at 1 instead of 0 to match the existing style */
314 base_bdev
= spdk_bdev_part_base_get_bdev(gpt_base
->part_base
);
315 name
= spdk_sprintf_alloc("%sp%" PRIu64
, spdk_bdev_get_name(base_bdev
), i
+ 1);
317 SPDK_ERRLOG("name allocation failure\n");
322 rc
= spdk_bdev_part_construct(&d
->part
, gpt_base
->part_base
, name
,
323 lba_start
, lba_end
- lba_start
, "GPT Disk");
326 SPDK_ERRLOG("could not construct bdev part\n");
327 /* spdk_bdev_part_construct will free name on failure */
332 d
->partition_index
= i
;
335 return num_partitions
;
339 spdk_gpt_bdev_complete(struct spdk_bdev_io
*bdev_io
, bool status
, void *arg
)
341 struct gpt_base
*gpt_base
= (struct gpt_base
*)arg
;
342 struct spdk_bdev
*bdev
= spdk_bdev_part_base_get_bdev(gpt_base
->part_base
);
343 int rc
, num_partitions
= 0;
345 spdk_bdev_free_io(bdev_io
);
346 spdk_put_io_channel(gpt_base
->ch
);
349 if (status
!= SPDK_BDEV_IO_STATUS_SUCCESS
) {
350 SPDK_ERRLOG("Gpt: bdev=%s io error status=%d\n",
351 spdk_bdev_get_name(bdev
), status
);
355 rc
= spdk_gpt_parse(&gpt_base
->gpt
);
357 SPDK_DEBUGLOG(SPDK_LOG_VBDEV_GPT
, "Failed to parse gpt\n");
361 num_partitions
= vbdev_gpt_create_bdevs(gpt_base
);
362 if (num_partitions
< 0) {
363 SPDK_DEBUGLOG(SPDK_LOG_VBDEV_GPT
, "Failed to split dev=%s by gpt table\n",
364 spdk_bdev_get_name(bdev
));
369 * Notify the generic bdev layer that the actions related to the original examine
370 * callback are now completed.
372 spdk_bdev_module_examine_done(&gpt_if
);
375 * vbdev_gpt_create_bdevs returns the number of bdevs created upon success.
376 * We can branch on this value.
378 if (num_partitions
<= 0) {
379 /* If no gpt_disk instances were created, free the base context */
380 spdk_bdev_part_base_free(gpt_base
->part_base
);
385 vbdev_gpt_read_gpt(struct spdk_bdev
*bdev
)
387 struct gpt_base
*gpt_base
;
388 struct spdk_bdev_desc
*part_base_desc
;
391 gpt_base
= spdk_gpt_base_bdev_init(bdev
);
393 SPDK_ERRLOG("Cannot allocated gpt_base\n");
397 part_base_desc
= spdk_bdev_part_base_get_desc(gpt_base
->part_base
);
398 gpt_base
->ch
= spdk_bdev_get_io_channel(part_base_desc
);
399 if (gpt_base
->ch
== NULL
) {
400 SPDK_ERRLOG("Failed to get an io_channel.\n");
401 spdk_bdev_part_base_free(gpt_base
->part_base
);
405 rc
= spdk_bdev_read(part_base_desc
, gpt_base
->ch
, gpt_base
->gpt
.buf
, 0,
406 gpt_base
->gpt
.buf_size
, spdk_gpt_bdev_complete
, gpt_base
);
408 spdk_put_io_channel(gpt_base
->ch
);
409 spdk_bdev_part_base_free(gpt_base
->part_base
);
410 SPDK_ERRLOG("Failed to send bdev_io command\n");
420 struct spdk_conf_section
*sp
= spdk_conf_find_section(NULL
, "Gpt");
422 if (sp
&& spdk_conf_section_get_boolval(sp
, "Disable", false)) {
423 /* Disable Gpt probe */
424 g_gpt_disabled
= true;
431 vbdev_gpt_get_ctx_size(void)
433 return sizeof(struct gpt_io
);
437 vbdev_gpt_examine(struct spdk_bdev
*bdev
)
441 /* A bdev with fewer than 2 blocks cannot have a GPT. Block 0 has
442 * the MBR and block 1 has the GPT header.
444 if (g_gpt_disabled
|| spdk_bdev_get_num_blocks(bdev
) < 2) {
445 spdk_bdev_module_examine_done(&gpt_if
);
449 if (spdk_bdev_get_block_size(bdev
) % 512 != 0) {
450 SPDK_ERRLOG("GPT module does not support block size %" PRIu32
" for bdev %s\n",
451 spdk_bdev_get_block_size(bdev
), spdk_bdev_get_name(bdev
));
452 spdk_bdev_module_examine_done(&gpt_if
);
456 rc
= vbdev_gpt_read_gpt(bdev
);
458 spdk_bdev_module_examine_done(&gpt_if
);
459 SPDK_ERRLOG("Failed to read info from bdev %s\n", spdk_bdev_get_name(bdev
));
463 SPDK_LOG_REGISTER_COMPONENT("vbdev_gpt", SPDK_LOG_VBDEV_GPT
)