xref: /spdk/module/bdev/nvme/vbdev_opal.c (revision 488570ebd418ba07c9e69e65106dcc964f3bb41b)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (c) Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 #include "spdk/opal.h"
7 #include "spdk/bdev_module.h"
8 #include "vbdev_opal.h"
9 #include "spdk/log.h"
10 #include "spdk/string.h"
11 
12 /* OPAL locking range only supports operations on nsid=1 for now */
13 #define NSID_SUPPORTED		1
14 
15 struct opal_vbdev {
16 	char *name;
17 	struct nvme_ctrlr *nvme_ctrlr;
18 	struct spdk_opal_dev *opal_dev;
19 	struct spdk_bdev_part *bdev_part;
20 
21 	uint8_t locking_range_id;
22 	uint64_t range_start;
23 	uint64_t range_length;
24 	struct vbdev_opal_part_base *opal_base;
25 
26 	TAILQ_ENTRY(opal_vbdev) tailq;
27 };
28 
29 static TAILQ_HEAD(, opal_vbdev) g_opal_vbdev =
30 	TAILQ_HEAD_INITIALIZER(g_opal_vbdev);
31 
32 struct vbdev_opal_bdev_io {
33 	struct spdk_io_channel *ch;
34 	struct spdk_bdev_io *bdev_io;
35 	struct spdk_bdev_io_wait_entry bdev_io_wait;
36 };
37 
38 struct vbdev_opal_channel {
39 	struct spdk_bdev_part_channel part_ch;
40 };
41 
42 struct vbdev_opal_part_base {
43 	char *nvme_ctrlr_name;
44 	struct spdk_bdev_part_base *part_base;
45 	SPDK_BDEV_PART_TAILQ part_tailq;
46 	TAILQ_ENTRY(vbdev_opal_part_base) tailq;
47 };
48 
49 static TAILQ_HEAD(, vbdev_opal_part_base) g_opal_base = TAILQ_HEAD_INITIALIZER(g_opal_base);
50 
51 static void _vbdev_opal_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io);
52 
53 static void vbdev_opal_examine(struct spdk_bdev *bdev);
54 
55 static void
56 vbdev_opal_delete(struct opal_vbdev *opal_bdev)
57 {
58 	TAILQ_REMOVE(&g_opal_vbdev, opal_bdev, tailq);
59 	free(opal_bdev->name);
60 	free(opal_bdev);
61 	opal_bdev = NULL;
62 }
63 
64 static void
65 vbdev_opal_clear(void)
66 {
67 	struct opal_vbdev *opal_bdev, *tmp;
68 
69 	TAILQ_FOREACH_SAFE(opal_bdev, &g_opal_vbdev, tailq, tmp) {
70 		vbdev_opal_delete(opal_bdev);
71 	}
72 }
73 
74 static int
75 vbdev_opal_init(void)
76 {
77 	/* TODO */
78 	return 0;
79 }
80 
81 static void
82 vbdev_opal_fini(void)
83 {
84 	vbdev_opal_clear();
85 }
86 
87 static int
88 vbdev_opal_get_ctx_size(void)
89 {
90 	return sizeof(struct vbdev_opal_bdev_io);
91 }
92 
93 /* delete all the config of the same base bdev */
94 static void
95 vbdev_opal_delete_all_base_config(struct vbdev_opal_part_base *base)
96 {
97 	char *nvme_ctrlr_name = base->nvme_ctrlr_name;
98 	struct opal_vbdev *bdev, *tmp_bdev;
99 
100 	TAILQ_FOREACH_SAFE(bdev, &g_opal_vbdev, tailq, tmp_bdev) {
101 		if (!strcmp(nvme_ctrlr_name, bdev->nvme_ctrlr->nbdev_ctrlr->name)) {
102 			vbdev_opal_delete(bdev);
103 		}
104 	}
105 }
106 
107 static int
108 _vbdev_opal_destruct(void *ctx)
109 {
110 	struct spdk_bdev_part *part = ctx;
111 
112 	return spdk_bdev_part_free(part);
113 }
114 
115 static void
116 vbdev_opal_base_free(void *ctx)
117 {
118 	struct vbdev_opal_part_base *base = ctx;
119 
120 	TAILQ_REMOVE(&g_opal_base, base, tailq);
121 
122 	free(base->nvme_ctrlr_name);
123 	free(base);
124 }
125 
126 static void
127 vbdev_opal_resubmit_io(void *arg)
128 {
129 	struct vbdev_opal_bdev_io *io_ctx = (struct vbdev_opal_bdev_io *)arg;
130 
131 	_vbdev_opal_submit_request(io_ctx->ch, io_ctx->bdev_io);
132 }
133 
134 static void
135 vbdev_opal_queue_io(struct vbdev_opal_bdev_io *io_ctx)
136 {
137 	struct vbdev_opal_channel *ch = spdk_io_channel_get_ctx(io_ctx->ch);
138 	int rc;
139 
140 	io_ctx->bdev_io_wait.bdev = io_ctx->bdev_io->bdev;
141 	io_ctx->bdev_io_wait.cb_fn = vbdev_opal_resubmit_io;
142 	io_ctx->bdev_io_wait.cb_arg = io_ctx;
143 
144 	rc = spdk_bdev_queue_io_wait(io_ctx->bdev_io->bdev, ch->part_ch.base_ch, &io_ctx->bdev_io_wait);
145 
146 	if (rc != 0) {
147 		SPDK_ERRLOG("Queue io failed in vbdev_opal_queue_io: %d\n", rc);
148 		spdk_bdev_io_complete(io_ctx->bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
149 	}
150 }
151 
152 static void
153 _vbdev_opal_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io)
154 {
155 	struct vbdev_opal_channel *ch = spdk_io_channel_get_ctx(_ch);
156 	struct vbdev_opal_bdev_io *io_ctx = (struct vbdev_opal_bdev_io *)bdev_io->driver_ctx;
157 	int rc;
158 
159 	rc = spdk_bdev_part_submit_request(&ch->part_ch, bdev_io);
160 	if (rc) {
161 		if (rc == -ENOMEM) {
162 			SPDK_DEBUGLOG(vbdev_opal, "opal: no memory, queue io.\n");
163 			io_ctx->ch = _ch;
164 			io_ctx->bdev_io = bdev_io;
165 			vbdev_opal_queue_io(io_ctx);
166 		} else {
167 			SPDK_ERRLOG("opal: error on io submission, rc=%d.\n", rc);
168 			spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
169 		}
170 	}
171 }
172 
173 static void
174 vbdev_opal_io_get_buf_cb(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io, bool success)
175 {
176 	if (!success) {
177 		spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
178 		return;
179 	}
180 
181 	_vbdev_opal_submit_request(ch, bdev_io);
182 }
183 
184 static void
185 vbdev_opal_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
186 {
187 	switch (bdev_io->type) {
188 	case SPDK_BDEV_IO_TYPE_READ:
189 		spdk_bdev_io_get_buf(bdev_io, vbdev_opal_io_get_buf_cb,
190 				     bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen);
191 		break;
192 	default:
193 		_vbdev_opal_submit_request(ch, bdev_io);
194 		break;
195 	}
196 }
197 
198 struct spdk_opal_locking_range_info *
199 vbdev_opal_get_info_from_bdev(const char *opal_bdev_name, const char *password)
200 {
201 	struct opal_vbdev *vbdev;
202 	struct nvme_ctrlr *nvme_ctrlr;
203 	int locking_range_id;
204 	int rc;
205 
206 	TAILQ_FOREACH(vbdev, &g_opal_vbdev, tailq) {
207 		if (strcmp(vbdev->name, opal_bdev_name) == 0) {
208 			break;
209 		}
210 	}
211 
212 	if (vbdev == NULL) {
213 		SPDK_ERRLOG("%s not found\n", opal_bdev_name);
214 		return NULL;
215 	}
216 
217 	nvme_ctrlr = vbdev->nvme_ctrlr;
218 	if (nvme_ctrlr == NULL) {
219 		SPDK_ERRLOG("can't find nvme_ctrlr of %s\n", vbdev->name);
220 		return NULL;
221 	}
222 
223 	locking_range_id = vbdev->locking_range_id;
224 	rc = spdk_opal_cmd_get_locking_range_info(nvme_ctrlr->opal_dev, password,
225 			OPAL_ADMIN1, locking_range_id);
226 	if (rc) {
227 		SPDK_ERRLOG("Get locking range info error: %d\n", rc);
228 		return NULL;
229 	}
230 
231 	return spdk_opal_get_locking_range_info(nvme_ctrlr->opal_dev, locking_range_id);
232 }
233 
234 static int
235 vbdev_opal_dump_info_json(void *ctx, struct spdk_json_write_ctx *w)
236 {
237 	struct spdk_bdev_part *part = ctx;
238 	struct spdk_bdev *base_bdev = spdk_bdev_part_get_base_bdev(part);
239 	uint64_t offset = spdk_bdev_part_get_offset_blocks(part);
240 
241 	spdk_json_write_named_object_begin(w, "opal");
242 
243 	spdk_json_write_named_string(w, "base_bdev", spdk_bdev_get_name(base_bdev));
244 	spdk_json_write_named_uint64(w, "offset_blocks", offset);
245 
246 	spdk_json_write_object_end(w);
247 
248 	return 0;
249 }
250 
251 static void
252 vbdev_opal_base_bdev_hotremove_cb(void *_part_base)
253 {
254 	struct spdk_bdev_part_base *part_base = _part_base;
255 	struct vbdev_opal_part_base *base = spdk_bdev_part_base_get_ctx(part_base);
256 
257 	spdk_bdev_part_base_hotremove(part_base, spdk_bdev_part_base_get_tailq(part_base));
258 	vbdev_opal_delete_all_base_config(base);
259 }
260 
261 static bool
262 vbdev_opal_io_type_supported(void *ctx, enum spdk_bdev_io_type io_type)
263 {
264 	struct spdk_bdev_part *part = ctx;
265 	struct spdk_bdev *base_bdev = spdk_bdev_part_get_base_bdev(part);
266 
267 	return spdk_bdev_io_type_supported(base_bdev, io_type);
268 }
269 
270 static struct spdk_bdev_fn_table opal_vbdev_fn_table = {
271 	.destruct           = _vbdev_opal_destruct,
272 	.submit_request     = vbdev_opal_submit_request,
273 	.io_type_supported  = vbdev_opal_io_type_supported,
274 	.dump_info_json     = vbdev_opal_dump_info_json,
275 	.write_config_json  = NULL,
276 };
277 
278 static struct spdk_bdev_module opal_if = {
279 	.name           = "opal",
280 	.module_init    = vbdev_opal_init,
281 	.module_fini    = vbdev_opal_fini,
282 	.get_ctx_size   = vbdev_opal_get_ctx_size,
283 	.examine_config = vbdev_opal_examine,
284 	.config_json    = NULL,
285 };
286 
287 SPDK_BDEV_MODULE_REGISTER(opal, &opal_if)
288 
289 int
290 vbdev_opal_create(const char *nvme_ctrlr_name, uint32_t nsid, uint8_t locking_range_id,
291 		  uint64_t range_start, uint64_t range_length, const char *password)
292 {
293 	int rc;
294 	char *opal_vbdev_name;
295 	char *base_bdev_name;
296 	struct nvme_ctrlr *nvme_ctrlr;
297 	struct opal_vbdev *opal_bdev;
298 	struct vbdev_opal_part_base *opal_part_base = NULL;
299 	struct spdk_bdev_part *part_bdev;
300 	struct nvme_bdev *nvme_bdev;
301 	struct nvme_ns *nvme_ns;
302 
303 	if (nsid != NSID_SUPPORTED) {
304 		SPDK_ERRLOG("nsid %d not supported", nsid);
305 		return -EINVAL;
306 	}
307 
308 	nvme_ctrlr = nvme_ctrlr_get_by_name(nvme_ctrlr_name);
309 	if (!nvme_ctrlr) {
310 		SPDK_ERRLOG("get nvme ctrlr failed\n");
311 		return -ENODEV;
312 	}
313 
314 	if (!nvme_ctrlr->opal_dev) {
315 		SPDK_ERRLOG("Opal not supported\n");
316 		return -ENOTSUP;
317 	}
318 
319 	opal_bdev = calloc(1, sizeof(struct opal_vbdev));
320 	if (!opal_bdev) {
321 		SPDK_ERRLOG("allocation for opal_bdev failed\n");
322 		return -ENOMEM;
323 	}
324 
325 	opal_bdev->locking_range_id = locking_range_id;
326 	opal_bdev->range_start = range_start;
327 	opal_bdev->range_length = range_length;
328 
329 	opal_bdev->nvme_ctrlr = nvme_ctrlr;
330 	opal_bdev->opal_dev = nvme_ctrlr->opal_dev;
331 
332 	nvme_ns = nvme_ctrlr_get_ns(nvme_ctrlr, nsid);
333 	if (nvme_ns == NULL) {
334 		free(opal_bdev);
335 		return -ENODEV;
336 	}
337 
338 	nvme_bdev = nvme_ns->bdev;
339 	assert(nvme_bdev != NULL);
340 	base_bdev_name = nvme_bdev->disk.name;
341 
342 	/* traverse base list to see if part_base is already create for this base bdev */
343 	TAILQ_FOREACH(opal_part_base, &g_opal_base, tailq) {
344 		if (!strcmp(spdk_bdev_part_base_get_bdev_name(opal_part_base->part_base), base_bdev_name)) {
345 			break;
346 		}
347 	}
348 
349 	/* If there is not a corresponding opal_part_base, a new opal_part_base will be created.
350 	   For each new part_base, there will be one tailq to store all the parts of this base */
351 	if (opal_part_base == NULL) {
352 		opal_part_base = calloc(1, sizeof(*opal_part_base));
353 		if (opal_part_base == NULL) {
354 			SPDK_ERRLOG("Could not allocate opal_part_base\n");
355 			free(opal_bdev);
356 			return -ENOMEM;
357 		}
358 		TAILQ_INIT(&opal_part_base->part_tailq);
359 
360 		rc = spdk_bdev_part_base_construct_ext(base_bdev_name,
361 						       vbdev_opal_base_bdev_hotremove_cb, &opal_if,
362 						       &opal_vbdev_fn_table, &opal_part_base->part_tailq,
363 						       vbdev_opal_base_free, opal_part_base,
364 						       sizeof(struct vbdev_opal_channel), NULL, NULL,
365 						       &opal_part_base->part_base);
366 		if (rc != 0) {
367 			if (rc != -ENODEV) {
368 				SPDK_ERRLOG("Could not allocate part_base\n");
369 			}
370 			free(opal_bdev);
371 			free(opal_part_base);
372 			return rc;
373 		}
374 		opal_part_base->nvme_ctrlr_name = strdup(nvme_ctrlr_name);
375 		if (opal_part_base->nvme_ctrlr_name == NULL) {
376 			free(opal_bdev);
377 			spdk_bdev_part_base_free(opal_part_base->part_base);
378 			return -ENOMEM;
379 		}
380 
381 		TAILQ_INSERT_TAIL(&g_opal_base, opal_part_base, tailq);
382 	}
383 	assert(opal_part_base != NULL);
384 	opal_bdev->opal_base = opal_part_base;
385 
386 	part_bdev = calloc(1, sizeof(struct spdk_bdev_part));
387 	if (!part_bdev) {
388 		SPDK_ERRLOG("Could not allocate part_bdev\n");
389 		free(opal_bdev);
390 		return -ENOMEM;
391 	}
392 
393 	TAILQ_INSERT_TAIL(&g_opal_vbdev, opal_bdev, tailq);
394 	opal_vbdev_name = spdk_sprintf_alloc("%sr%" PRIu8, base_bdev_name,
395 					     opal_bdev->locking_range_id);  /* e.g.: nvme0n1r1 */
396 	if (opal_vbdev_name == NULL) {
397 		SPDK_ERRLOG("Could not allocate opal_vbdev_name\n");
398 		rc = -ENOMEM;
399 		goto err;
400 	}
401 
402 	opal_bdev->name = opal_vbdev_name;
403 	rc = spdk_opal_cmd_setup_locking_range(opal_bdev->opal_dev, OPAL_ADMIN1,
404 					       opal_bdev->locking_range_id, opal_bdev->range_start,
405 					       opal_bdev->range_length, password);
406 	if (rc) {
407 		SPDK_ERRLOG("Error construct %s\n", opal_vbdev_name);
408 		goto err;
409 	}
410 
411 	rc = spdk_bdev_part_construct(part_bdev, opal_bdev->opal_base->part_base, opal_vbdev_name,
412 				      opal_bdev->range_start, opal_bdev->range_length, "Opal locking range");
413 	if (rc) {
414 		SPDK_ERRLOG("Could not allocate bdev part\n");
415 		goto err;
416 	}
417 
418 	/* lock this bdev initially */
419 	rc = spdk_opal_cmd_lock_unlock(opal_bdev->opal_dev, OPAL_ADMIN1, OPAL_RWLOCK, locking_range_id,
420 				       password);
421 	if (rc) {
422 		SPDK_ERRLOG("Error lock %s\n", opal_vbdev_name);
423 		goto err;
424 	}
425 
426 	opal_bdev->bdev_part = part_bdev;
427 	return 0;
428 
429 err:
430 	vbdev_opal_delete(opal_bdev);
431 	free(part_bdev);
432 	return rc;
433 }
434 
435 static void
436 vbdev_opal_destruct_bdev(struct opal_vbdev *opal_bdev)
437 {
438 	struct spdk_bdev_part *part = opal_bdev->bdev_part;
439 
440 	assert(opal_bdev->opal_base != NULL);
441 	assert(part != NULL);
442 
443 	if (opal_bdev->range_start == spdk_bdev_part_get_offset_blocks(part)) {
444 		spdk_bdev_unregister(spdk_bdev_part_get_bdev(part), NULL, NULL);
445 	}
446 	vbdev_opal_delete(opal_bdev);
447 }
448 
449 int
450 vbdev_opal_destruct(const char *bdev_name, const char *password)
451 {
452 	struct nvme_ctrlr *nvme_ctrlr;
453 	int locking_range_id;
454 	int rc;
455 	struct opal_vbdev *opal_bdev;
456 
457 	TAILQ_FOREACH(opal_bdev, &g_opal_vbdev, tailq) {
458 		if (strcmp(opal_bdev->name, bdev_name) == 0) {
459 			break;
460 		}
461 	}
462 
463 	if (opal_bdev == NULL) {
464 		SPDK_ERRLOG("%s not found\n", bdev_name);
465 		rc = -ENODEV;
466 		goto err;
467 	}
468 
469 	locking_range_id = opal_bdev->locking_range_id;
470 
471 	nvme_ctrlr = opal_bdev->nvme_ctrlr;
472 	if (nvme_ctrlr == NULL) {
473 		SPDK_ERRLOG("can't find nvme_ctrlr of %s\n", bdev_name);
474 		return -ENODEV;
475 	}
476 
477 	/* secure erase locking range */
478 	rc = spdk_opal_cmd_secure_erase_locking_range(nvme_ctrlr->opal_dev, OPAL_ADMIN1, locking_range_id,
479 			password);
480 	if (rc) {
481 		SPDK_ERRLOG("opal erase locking range failed\n");
482 		goto err;
483 	}
484 
485 	/* reset the locking range to 0 */
486 	rc = spdk_opal_cmd_setup_locking_range(nvme_ctrlr->opal_dev, OPAL_ADMIN1, locking_range_id, 0,
487 					       0, password);
488 	if (rc) {
489 		SPDK_ERRLOG("opal reset locking range failed\n");
490 		goto err;
491 	}
492 
493 	spdk_opal_free_locking_range_info(opal_bdev->opal_dev, locking_range_id);
494 	vbdev_opal_destruct_bdev(opal_bdev);
495 	return 0;
496 
497 err:
498 	return rc;
499 }
500 
501 static void
502 vbdev_opal_examine(struct spdk_bdev *bdev)
503 {
504 	/* TODO */
505 	spdk_bdev_module_examine_done(&opal_if);
506 }
507 
508 int
509 vbdev_opal_set_lock_state(const char *bdev_name, uint16_t user_id, const char *password,
510 			  const char *lock_state)
511 {
512 	struct nvme_ctrlr *nvme_ctrlr;
513 	int locking_range_id;
514 	int rc;
515 	enum spdk_opal_lock_state state_flag;
516 	struct opal_vbdev *opal_bdev;
517 
518 	TAILQ_FOREACH(opal_bdev, &g_opal_vbdev, tailq) {
519 		if (strcmp(opal_bdev->name, bdev_name) == 0) {
520 			break;
521 		}
522 	}
523 
524 	if (opal_bdev == NULL) {
525 		SPDK_ERRLOG("%s not found\n", bdev_name);
526 		return -ENODEV;
527 	}
528 
529 	nvme_ctrlr = opal_bdev->nvme_ctrlr;
530 	if (nvme_ctrlr == NULL) {
531 		SPDK_ERRLOG("can't find nvme_ctrlr of %s\n", opal_bdev->name);
532 		return -ENODEV;
533 	}
534 
535 	if (strcasecmp(lock_state, "READWRITE") == 0) {
536 		state_flag = OPAL_READWRITE;
537 	} else if (strcasecmp(lock_state, "READONLY") == 0) {
538 		state_flag = OPAL_READONLY;
539 	} else if (strcasecmp(lock_state, "RWLOCK") == 0) {
540 		state_flag = OPAL_RWLOCK;
541 	} else {
542 		SPDK_ERRLOG("Invalid OPAL lock state input\n");
543 		return -EINVAL;
544 	}
545 
546 	locking_range_id = opal_bdev->locking_range_id;
547 	rc = spdk_opal_cmd_lock_unlock(nvme_ctrlr->opal_dev, user_id, state_flag, locking_range_id,
548 				       password);
549 	if (rc) {
550 		SPDK_ERRLOG("%s lock/unlock failure: %d\n", bdev_name, rc);
551 	}
552 
553 	return rc;
554 }
555 
556 int
557 vbdev_opal_enable_new_user(const char *bdev_name, const char *admin_password, uint16_t user_id,
558 			   const char *user_password)
559 {
560 	struct nvme_ctrlr *nvme_ctrlr;
561 	int locking_range_id;
562 	int rc;
563 	struct opal_vbdev *opal_bdev;
564 
565 	TAILQ_FOREACH(opal_bdev, &g_opal_vbdev, tailq) {
566 		if (strcmp(opal_bdev->name, bdev_name) == 0) {
567 			break;
568 		}
569 	}
570 
571 	if (opal_bdev == NULL) {
572 		SPDK_ERRLOG("%s not found\n", bdev_name);
573 		return -ENODEV;
574 	}
575 
576 	nvme_ctrlr = opal_bdev->nvme_ctrlr;
577 	if (nvme_ctrlr == NULL) {
578 		SPDK_ERRLOG("can't find nvme_ctrlr of %s\n", opal_bdev->name);
579 		return -ENODEV;
580 	}
581 
582 	rc = spdk_opal_cmd_enable_user(nvme_ctrlr->opal_dev, user_id, admin_password);
583 	if (rc) {
584 		SPDK_ERRLOG("%s enable user error: %d\n", bdev_name, rc);
585 		return rc;
586 	}
587 
588 	rc = spdk_opal_cmd_set_new_passwd(nvme_ctrlr->opal_dev, user_id, user_password, admin_password,
589 					  true);
590 	if (rc) {
591 		SPDK_ERRLOG("%s set user password error: %d\n", bdev_name, rc);
592 		return rc;
593 	}
594 
595 	locking_range_id = opal_bdev->locking_range_id;
596 	rc = spdk_opal_cmd_add_user_to_locking_range(nvme_ctrlr->opal_dev, user_id, locking_range_id,
597 			OPAL_READONLY, admin_password);
598 	if (rc) {
599 		SPDK_ERRLOG("%s add user READONLY priority error: %d\n", bdev_name, rc);
600 		return rc;
601 	}
602 
603 	rc = spdk_opal_cmd_add_user_to_locking_range(nvme_ctrlr->opal_dev, user_id, locking_range_id,
604 			OPAL_READWRITE, admin_password);
605 	if (rc) {
606 		SPDK_ERRLOG("%s add user READWRITE priority error: %d\n", bdev_name, rc);
607 		return rc;
608 	}
609 
610 	return 0;
611 }
612 
613 SPDK_LOG_REGISTER_COMPONENT(vbdev_opal)
614