1488570ebSJim Harris /* SPDX-License-Identifier: BSD-3-Clause
2*a6dbe372Spaul luse * Copyright (C) 2019 Intel Corporation.
38466e2c6SChunyang Hui * All rights reserved.
48466e2c6SChunyang Hui */
58466e2c6SChunyang Hui
68466e2c6SChunyang Hui #include "spdk/opal.h"
78466e2c6SChunyang Hui #include "spdk/bdev_module.h"
88466e2c6SChunyang Hui #include "vbdev_opal.h"
94e8e97c8STomasz Zawadzki #include "spdk/log.h"
108466e2c6SChunyang Hui #include "spdk/string.h"
118466e2c6SChunyang Hui
128466e2c6SChunyang Hui /* OPAL locking range only supports operations on nsid=1 for now */
138466e2c6SChunyang Hui #define NSID_SUPPORTED 1
148466e2c6SChunyang Hui
158466e2c6SChunyang Hui struct opal_vbdev {
168466e2c6SChunyang Hui char *name;
17a3dcdc05SShuhei Matsumoto struct nvme_ctrlr *nvme_ctrlr;
188466e2c6SChunyang Hui struct spdk_opal_dev *opal_dev;
198466e2c6SChunyang Hui struct spdk_bdev_part *bdev_part;
20021ebb35SChangpeng Liu
21021ebb35SChangpeng Liu uint8_t locking_range_id;
22021ebb35SChangpeng Liu uint64_t range_start;
23021ebb35SChangpeng Liu uint64_t range_length;
24021ebb35SChangpeng Liu struct vbdev_opal_part_base *opal_base;
258466e2c6SChunyang Hui
268466e2c6SChunyang Hui TAILQ_ENTRY(opal_vbdev) tailq;
278466e2c6SChunyang Hui };
288466e2c6SChunyang Hui
298466e2c6SChunyang Hui static TAILQ_HEAD(, opal_vbdev) g_opal_vbdev =
308466e2c6SChunyang Hui TAILQ_HEAD_INITIALIZER(g_opal_vbdev);
318466e2c6SChunyang Hui
328466e2c6SChunyang Hui struct vbdev_opal_bdev_io {
338466e2c6SChunyang Hui struct spdk_io_channel *ch;
348466e2c6SChunyang Hui struct spdk_bdev_io *bdev_io;
358466e2c6SChunyang Hui struct spdk_bdev_io_wait_entry bdev_io_wait;
368466e2c6SChunyang Hui };
378466e2c6SChunyang Hui
388466e2c6SChunyang Hui struct vbdev_opal_channel {
398466e2c6SChunyang Hui struct spdk_bdev_part_channel part_ch;
408466e2c6SChunyang Hui };
418466e2c6SChunyang Hui
428466e2c6SChunyang Hui struct vbdev_opal_part_base {
438466e2c6SChunyang Hui char *nvme_ctrlr_name;
448466e2c6SChunyang Hui struct spdk_bdev_part_base *part_base;
45021ebb35SChangpeng Liu SPDK_BDEV_PART_TAILQ part_tailq;
468466e2c6SChunyang Hui TAILQ_ENTRY(vbdev_opal_part_base) tailq;
478466e2c6SChunyang Hui };
488466e2c6SChunyang Hui
498466e2c6SChunyang Hui static TAILQ_HEAD(, vbdev_opal_part_base) g_opal_base = TAILQ_HEAD_INITIALIZER(g_opal_base);
508466e2c6SChunyang Hui
518466e2c6SChunyang Hui static void _vbdev_opal_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io);
528466e2c6SChunyang Hui
538466e2c6SChunyang Hui static void vbdev_opal_examine(struct spdk_bdev *bdev);
548466e2c6SChunyang Hui
558466e2c6SChunyang Hui static void
vbdev_opal_delete(struct opal_vbdev * opal_bdev)568466e2c6SChunyang Hui vbdev_opal_delete(struct opal_vbdev *opal_bdev)
578466e2c6SChunyang Hui {
588466e2c6SChunyang Hui TAILQ_REMOVE(&g_opal_vbdev, opal_bdev, tailq);
598466e2c6SChunyang Hui free(opal_bdev->name);
608466e2c6SChunyang Hui free(opal_bdev);
618466e2c6SChunyang Hui opal_bdev = NULL;
628466e2c6SChunyang Hui }
638466e2c6SChunyang Hui
648466e2c6SChunyang Hui static void
vbdev_opal_clear(void)658466e2c6SChunyang Hui vbdev_opal_clear(void)
668466e2c6SChunyang Hui {
678466e2c6SChunyang Hui struct opal_vbdev *opal_bdev, *tmp;
688466e2c6SChunyang Hui
698466e2c6SChunyang Hui TAILQ_FOREACH_SAFE(opal_bdev, &g_opal_vbdev, tailq, tmp) {
708466e2c6SChunyang Hui vbdev_opal_delete(opal_bdev);
718466e2c6SChunyang Hui }
728466e2c6SChunyang Hui }
738466e2c6SChunyang Hui
748466e2c6SChunyang Hui static int
vbdev_opal_init(void)758466e2c6SChunyang Hui vbdev_opal_init(void)
768466e2c6SChunyang Hui {
778466e2c6SChunyang Hui /* TODO */
788466e2c6SChunyang Hui return 0;
798466e2c6SChunyang Hui }
808466e2c6SChunyang Hui
818466e2c6SChunyang Hui static void
vbdev_opal_fini(void)828466e2c6SChunyang Hui vbdev_opal_fini(void)
838466e2c6SChunyang Hui {
848466e2c6SChunyang Hui vbdev_opal_clear();
858466e2c6SChunyang Hui }
868466e2c6SChunyang Hui
878466e2c6SChunyang Hui static int
vbdev_opal_get_ctx_size(void)888466e2c6SChunyang Hui vbdev_opal_get_ctx_size(void)
898466e2c6SChunyang Hui {
908466e2c6SChunyang Hui return sizeof(struct vbdev_opal_bdev_io);
918466e2c6SChunyang Hui }
928466e2c6SChunyang Hui
938466e2c6SChunyang Hui /* delete all the config of the same base bdev */
948466e2c6SChunyang Hui static void
vbdev_opal_delete_all_base_config(struct vbdev_opal_part_base * base)958466e2c6SChunyang Hui vbdev_opal_delete_all_base_config(struct vbdev_opal_part_base *base)
968466e2c6SChunyang Hui {
978466e2c6SChunyang Hui char *nvme_ctrlr_name = base->nvme_ctrlr_name;
988466e2c6SChunyang Hui struct opal_vbdev *bdev, *tmp_bdev;
998466e2c6SChunyang Hui
1008466e2c6SChunyang Hui TAILQ_FOREACH_SAFE(bdev, &g_opal_vbdev, tailq, tmp_bdev) {
10175f1d648SShuhei Matsumoto if (!strcmp(nvme_ctrlr_name, bdev->nvme_ctrlr->nbdev_ctrlr->name)) {
1028466e2c6SChunyang Hui vbdev_opal_delete(bdev);
1038466e2c6SChunyang Hui }
1048466e2c6SChunyang Hui }
1058466e2c6SChunyang Hui }
1068466e2c6SChunyang Hui
1078466e2c6SChunyang Hui static int
_vbdev_opal_destruct(void * ctx)108b95421d4SSeth Howell _vbdev_opal_destruct(void *ctx)
1098466e2c6SChunyang Hui {
1108466e2c6SChunyang Hui struct spdk_bdev_part *part = ctx;
1118466e2c6SChunyang Hui
1128466e2c6SChunyang Hui return spdk_bdev_part_free(part);
1138466e2c6SChunyang Hui }
1148466e2c6SChunyang Hui
1158466e2c6SChunyang Hui static void
vbdev_opal_base_free(void * ctx)1168466e2c6SChunyang Hui vbdev_opal_base_free(void *ctx)
1178466e2c6SChunyang Hui {
1188466e2c6SChunyang Hui struct vbdev_opal_part_base *base = ctx;
1198466e2c6SChunyang Hui
120c3ace4f4SChangpeng Liu TAILQ_REMOVE(&g_opal_base, base, tailq);
121c3ace4f4SChangpeng Liu
1228466e2c6SChunyang Hui free(base->nvme_ctrlr_name);
1238466e2c6SChunyang Hui free(base);
1248466e2c6SChunyang Hui }
1258466e2c6SChunyang Hui
1268466e2c6SChunyang Hui static void
vbdev_opal_resubmit_io(void * arg)1278466e2c6SChunyang Hui vbdev_opal_resubmit_io(void *arg)
1288466e2c6SChunyang Hui {
1298466e2c6SChunyang Hui struct vbdev_opal_bdev_io *io_ctx = (struct vbdev_opal_bdev_io *)arg;
1308466e2c6SChunyang Hui
1318466e2c6SChunyang Hui _vbdev_opal_submit_request(io_ctx->ch, io_ctx->bdev_io);
1328466e2c6SChunyang Hui }
1338466e2c6SChunyang Hui
1348466e2c6SChunyang Hui static void
vbdev_opal_queue_io(struct vbdev_opal_bdev_io * io_ctx)1358466e2c6SChunyang Hui vbdev_opal_queue_io(struct vbdev_opal_bdev_io *io_ctx)
1368466e2c6SChunyang Hui {
137223108d1Spaul luse struct vbdev_opal_channel *ch = spdk_io_channel_get_ctx(io_ctx->ch);
1388466e2c6SChunyang Hui int rc;
1398466e2c6SChunyang Hui
1408466e2c6SChunyang Hui io_ctx->bdev_io_wait.bdev = io_ctx->bdev_io->bdev;
1418466e2c6SChunyang Hui io_ctx->bdev_io_wait.cb_fn = vbdev_opal_resubmit_io;
1428466e2c6SChunyang Hui io_ctx->bdev_io_wait.cb_arg = io_ctx;
1438466e2c6SChunyang Hui
144223108d1Spaul luse rc = spdk_bdev_queue_io_wait(io_ctx->bdev_io->bdev, ch->part_ch.base_ch, &io_ctx->bdev_io_wait);
1458466e2c6SChunyang Hui
1468466e2c6SChunyang Hui if (rc != 0) {
1478466e2c6SChunyang Hui SPDK_ERRLOG("Queue io failed in vbdev_opal_queue_io: %d\n", rc);
1488466e2c6SChunyang Hui spdk_bdev_io_complete(io_ctx->bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
1498466e2c6SChunyang Hui }
1508466e2c6SChunyang Hui }
1518466e2c6SChunyang Hui
1528466e2c6SChunyang Hui static void
_vbdev_opal_submit_request(struct spdk_io_channel * _ch,struct spdk_bdev_io * bdev_io)1538466e2c6SChunyang Hui _vbdev_opal_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io)
1548466e2c6SChunyang Hui {
1558466e2c6SChunyang Hui struct vbdev_opal_channel *ch = spdk_io_channel_get_ctx(_ch);
1568466e2c6SChunyang Hui struct vbdev_opal_bdev_io *io_ctx = (struct vbdev_opal_bdev_io *)bdev_io->driver_ctx;
1578466e2c6SChunyang Hui int rc;
1588466e2c6SChunyang Hui
1598466e2c6SChunyang Hui rc = spdk_bdev_part_submit_request(&ch->part_ch, bdev_io);
1608466e2c6SChunyang Hui if (rc) {
1618466e2c6SChunyang Hui if (rc == -ENOMEM) {
1622172c432STomasz Zawadzki SPDK_DEBUGLOG(vbdev_opal, "opal: no memory, queue io.\n");
1638466e2c6SChunyang Hui io_ctx->ch = _ch;
1648466e2c6SChunyang Hui io_ctx->bdev_io = bdev_io;
1658466e2c6SChunyang Hui vbdev_opal_queue_io(io_ctx);
1668466e2c6SChunyang Hui } else {
1678466e2c6SChunyang Hui SPDK_ERRLOG("opal: error on io submission, rc=%d.\n", rc);
1688466e2c6SChunyang Hui spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
1698466e2c6SChunyang Hui }
1708466e2c6SChunyang Hui }
1718466e2c6SChunyang Hui }
1728466e2c6SChunyang Hui
1738466e2c6SChunyang Hui static void
vbdev_opal_io_get_buf_cb(struct spdk_io_channel * ch,struct spdk_bdev_io * bdev_io,bool success)1748466e2c6SChunyang Hui vbdev_opal_io_get_buf_cb(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io, bool success)
1758466e2c6SChunyang Hui {
1768466e2c6SChunyang Hui if (!success) {
1778466e2c6SChunyang Hui spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
1788466e2c6SChunyang Hui return;
1798466e2c6SChunyang Hui }
1808466e2c6SChunyang Hui
1818466e2c6SChunyang Hui _vbdev_opal_submit_request(ch, bdev_io);
1828466e2c6SChunyang Hui }
1838466e2c6SChunyang Hui
1848466e2c6SChunyang Hui static void
vbdev_opal_submit_request(struct spdk_io_channel * ch,struct spdk_bdev_io * bdev_io)1858466e2c6SChunyang Hui vbdev_opal_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
1868466e2c6SChunyang Hui {
1878466e2c6SChunyang Hui switch (bdev_io->type) {
1888466e2c6SChunyang Hui case SPDK_BDEV_IO_TYPE_READ:
1898466e2c6SChunyang Hui spdk_bdev_io_get_buf(bdev_io, vbdev_opal_io_get_buf_cb,
1908466e2c6SChunyang Hui bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen);
1918466e2c6SChunyang Hui break;
1928466e2c6SChunyang Hui default:
1938466e2c6SChunyang Hui _vbdev_opal_submit_request(ch, bdev_io);
1948466e2c6SChunyang Hui break;
1958466e2c6SChunyang Hui }
1968466e2c6SChunyang Hui }
1978466e2c6SChunyang Hui
19836c9ac2dSChunyang Hui struct spdk_opal_locking_range_info *
vbdev_opal_get_info_from_bdev(const char * opal_bdev_name,const char * password)199b95421d4SSeth Howell vbdev_opal_get_info_from_bdev(const char *opal_bdev_name, const char *password)
20036c9ac2dSChunyang Hui {
20136c9ac2dSChunyang Hui struct opal_vbdev *vbdev;
202a3dcdc05SShuhei Matsumoto struct nvme_ctrlr *nvme_ctrlr;
20336c9ac2dSChunyang Hui int locking_range_id;
20436c9ac2dSChunyang Hui int rc;
20536c9ac2dSChunyang Hui
20636c9ac2dSChunyang Hui TAILQ_FOREACH(vbdev, &g_opal_vbdev, tailq) {
20736c9ac2dSChunyang Hui if (strcmp(vbdev->name, opal_bdev_name) == 0) {
20836c9ac2dSChunyang Hui break;
20936c9ac2dSChunyang Hui }
21036c9ac2dSChunyang Hui }
21136c9ac2dSChunyang Hui
21236c9ac2dSChunyang Hui if (vbdev == NULL) {
21336c9ac2dSChunyang Hui SPDK_ERRLOG("%s not found\n", opal_bdev_name);
21436c9ac2dSChunyang Hui return NULL;
21536c9ac2dSChunyang Hui }
21636c9ac2dSChunyang Hui
21736c9ac2dSChunyang Hui nvme_ctrlr = vbdev->nvme_ctrlr;
21836c9ac2dSChunyang Hui if (nvme_ctrlr == NULL) {
21936c9ac2dSChunyang Hui SPDK_ERRLOG("can't find nvme_ctrlr of %s\n", vbdev->name);
22036c9ac2dSChunyang Hui return NULL;
22136c9ac2dSChunyang Hui }
22236c9ac2dSChunyang Hui
223021ebb35SChangpeng Liu locking_range_id = vbdev->locking_range_id;
22436c9ac2dSChunyang Hui rc = spdk_opal_cmd_get_locking_range_info(nvme_ctrlr->opal_dev, password,
22536c9ac2dSChunyang Hui OPAL_ADMIN1, locking_range_id);
22636c9ac2dSChunyang Hui if (rc) {
22736c9ac2dSChunyang Hui SPDK_ERRLOG("Get locking range info error: %d\n", rc);
22836c9ac2dSChunyang Hui return NULL;
22936c9ac2dSChunyang Hui }
23036c9ac2dSChunyang Hui
23136c9ac2dSChunyang Hui return spdk_opal_get_locking_range_info(nvme_ctrlr->opal_dev, locking_range_id);
23236c9ac2dSChunyang Hui }
23336c9ac2dSChunyang Hui
2348466e2c6SChunyang Hui static int
vbdev_opal_dump_info_json(void * ctx,struct spdk_json_write_ctx * w)2358466e2c6SChunyang Hui vbdev_opal_dump_info_json(void *ctx, struct spdk_json_write_ctx *w)
2368466e2c6SChunyang Hui {
2378466e2c6SChunyang Hui struct spdk_bdev_part *part = ctx;
2388466e2c6SChunyang Hui struct spdk_bdev *base_bdev = spdk_bdev_part_get_base_bdev(part);
2398466e2c6SChunyang Hui uint64_t offset = spdk_bdev_part_get_offset_blocks(part);
2408466e2c6SChunyang Hui
2418466e2c6SChunyang Hui spdk_json_write_named_object_begin(w, "opal");
2428466e2c6SChunyang Hui
2438466e2c6SChunyang Hui spdk_json_write_named_string(w, "base_bdev", spdk_bdev_get_name(base_bdev));
2448466e2c6SChunyang Hui spdk_json_write_named_uint64(w, "offset_blocks", offset);
2458466e2c6SChunyang Hui
2468466e2c6SChunyang Hui spdk_json_write_object_end(w);
2478466e2c6SChunyang Hui
2488466e2c6SChunyang Hui return 0;
2498466e2c6SChunyang Hui }
2508466e2c6SChunyang Hui
2518466e2c6SChunyang Hui static void
vbdev_opal_base_bdev_hotremove_cb(void * _part_base)2528466e2c6SChunyang Hui vbdev_opal_base_bdev_hotremove_cb(void *_part_base)
2538466e2c6SChunyang Hui {
2548466e2c6SChunyang Hui struct spdk_bdev_part_base *part_base = _part_base;
2558466e2c6SChunyang Hui struct vbdev_opal_part_base *base = spdk_bdev_part_base_get_ctx(part_base);
2568466e2c6SChunyang Hui
2578466e2c6SChunyang Hui spdk_bdev_part_base_hotremove(part_base, spdk_bdev_part_base_get_tailq(part_base));
2588466e2c6SChunyang Hui vbdev_opal_delete_all_base_config(base);
2598466e2c6SChunyang Hui }
2608466e2c6SChunyang Hui
2618466e2c6SChunyang Hui static bool
vbdev_opal_io_type_supported(void * ctx,enum spdk_bdev_io_type io_type)2628466e2c6SChunyang Hui vbdev_opal_io_type_supported(void *ctx, enum spdk_bdev_io_type io_type)
2638466e2c6SChunyang Hui {
2648466e2c6SChunyang Hui struct spdk_bdev_part *part = ctx;
2658466e2c6SChunyang Hui struct spdk_bdev *base_bdev = spdk_bdev_part_get_base_bdev(part);
2668466e2c6SChunyang Hui
2678466e2c6SChunyang Hui return spdk_bdev_io_type_supported(base_bdev, io_type);
2688466e2c6SChunyang Hui }
2698466e2c6SChunyang Hui
2708466e2c6SChunyang Hui static struct spdk_bdev_fn_table opal_vbdev_fn_table = {
271b95421d4SSeth Howell .destruct = _vbdev_opal_destruct,
2728466e2c6SChunyang Hui .submit_request = vbdev_opal_submit_request,
2738466e2c6SChunyang Hui .io_type_supported = vbdev_opal_io_type_supported,
2748466e2c6SChunyang Hui .dump_info_json = vbdev_opal_dump_info_json,
2758466e2c6SChunyang Hui .write_config_json = NULL,
2768466e2c6SChunyang Hui };
2778466e2c6SChunyang Hui
2788466e2c6SChunyang Hui static struct spdk_bdev_module opal_if = {
2798466e2c6SChunyang Hui .name = "opal",
2808466e2c6SChunyang Hui .module_init = vbdev_opal_init,
2818466e2c6SChunyang Hui .module_fini = vbdev_opal_fini,
2828466e2c6SChunyang Hui .get_ctx_size = vbdev_opal_get_ctx_size,
2838466e2c6SChunyang Hui .examine_config = vbdev_opal_examine,
2848466e2c6SChunyang Hui .config_json = NULL,
2858466e2c6SChunyang Hui };
2868466e2c6SChunyang Hui
2878466e2c6SChunyang Hui SPDK_BDEV_MODULE_REGISTER(opal, &opal_if)
2888466e2c6SChunyang Hui
2898466e2c6SChunyang Hui int
vbdev_opal_create(const char * nvme_ctrlr_name,uint32_t nsid,uint8_t locking_range_id,uint64_t range_start,uint64_t range_length,const char * password)290b95421d4SSeth Howell vbdev_opal_create(const char *nvme_ctrlr_name, uint32_t nsid, uint8_t locking_range_id,
2918466e2c6SChunyang Hui uint64_t range_start, uint64_t range_length, const char *password)
2928466e2c6SChunyang Hui {
2938466e2c6SChunyang Hui int rc;
2948466e2c6SChunyang Hui char *opal_vbdev_name;
2958466e2c6SChunyang Hui char *base_bdev_name;
296a3dcdc05SShuhei Matsumoto struct nvme_ctrlr *nvme_ctrlr;
2978466e2c6SChunyang Hui struct opal_vbdev *opal_bdev;
298021ebb35SChangpeng Liu struct vbdev_opal_part_base *opal_part_base = NULL;
2998466e2c6SChunyang Hui struct spdk_bdev_part *part_bdev;
300c30609c9SMaciej Szwed struct nvme_bdev *nvme_bdev;
301c93b5564SBen Walker struct nvme_ns *nvme_ns;
3028466e2c6SChunyang Hui
3038466e2c6SChunyang Hui if (nsid != NSID_SUPPORTED) {
3048466e2c6SChunyang Hui SPDK_ERRLOG("nsid %d not supported", nsid);
3058466e2c6SChunyang Hui return -EINVAL;
3068466e2c6SChunyang Hui }
3078466e2c6SChunyang Hui
308a3dcdc05SShuhei Matsumoto nvme_ctrlr = nvme_ctrlr_get_by_name(nvme_ctrlr_name);
3098466e2c6SChunyang Hui if (!nvme_ctrlr) {
3108466e2c6SChunyang Hui SPDK_ERRLOG("get nvme ctrlr failed\n");
3118466e2c6SChunyang Hui return -ENODEV;
3128466e2c6SChunyang Hui }
3138466e2c6SChunyang Hui
314b2947f52SChangpeng Liu if (!nvme_ctrlr->opal_dev) {
3158466e2c6SChunyang Hui SPDK_ERRLOG("Opal not supported\n");
316366fc577SChangpeng Liu return -ENOTSUP;
3178466e2c6SChunyang Hui }
3188466e2c6SChunyang Hui
3198466e2c6SChunyang Hui opal_bdev = calloc(1, sizeof(struct opal_vbdev));
3208466e2c6SChunyang Hui if (!opal_bdev) {
3218466e2c6SChunyang Hui SPDK_ERRLOG("allocation for opal_bdev failed\n");
3228466e2c6SChunyang Hui return -ENOMEM;
3238466e2c6SChunyang Hui }
3248466e2c6SChunyang Hui
325021ebb35SChangpeng Liu opal_bdev->locking_range_id = locking_range_id;
326021ebb35SChangpeng Liu opal_bdev->range_start = range_start;
327021ebb35SChangpeng Liu opal_bdev->range_length = range_length;
3288466e2c6SChunyang Hui
3298466e2c6SChunyang Hui opal_bdev->nvme_ctrlr = nvme_ctrlr;
3308466e2c6SChunyang Hui opal_bdev->opal_dev = nvme_ctrlr->opal_dev;
331c30609c9SMaciej Szwed
332c93b5564SBen Walker nvme_ns = nvme_ctrlr_get_ns(nvme_ctrlr, nsid);
333c93b5564SBen Walker if (nvme_ns == NULL) {
334c93b5564SBen Walker free(opal_bdev);
335c93b5564SBen Walker return -ENODEV;
336c93b5564SBen Walker }
337c93b5564SBen Walker
338c93b5564SBen Walker nvme_bdev = nvme_ns->bdev;
339c30609c9SMaciej Szwed assert(nvme_bdev != NULL);
340c30609c9SMaciej Szwed base_bdev_name = nvme_bdev->disk.name;
3418466e2c6SChunyang Hui
3428466e2c6SChunyang Hui /* traverse base list to see if part_base is already create for this base bdev */
3438466e2c6SChunyang Hui TAILQ_FOREACH(opal_part_base, &g_opal_base, tailq) {
3448466e2c6SChunyang Hui if (!strcmp(spdk_bdev_part_base_get_bdev_name(opal_part_base->part_base), base_bdev_name)) {
345021ebb35SChangpeng Liu break;
3468466e2c6SChunyang Hui }
3478466e2c6SChunyang Hui }
3488466e2c6SChunyang Hui
3498466e2c6SChunyang Hui /* If there is not a corresponding opal_part_base, a new opal_part_base will be created.
3508466e2c6SChunyang Hui For each new part_base, there will be one tailq to store all the parts of this base */
351021ebb35SChangpeng Liu if (opal_part_base == NULL) {
3528466e2c6SChunyang Hui opal_part_base = calloc(1, sizeof(*opal_part_base));
3538466e2c6SChunyang Hui if (opal_part_base == NULL) {
3548466e2c6SChunyang Hui SPDK_ERRLOG("Could not allocate opal_part_base\n");
355021ebb35SChangpeng Liu free(opal_bdev);
3568466e2c6SChunyang Hui return -ENOMEM;
3578466e2c6SChunyang Hui }
358021ebb35SChangpeng Liu TAILQ_INIT(&opal_part_base->part_tailq);
3598466e2c6SChunyang Hui
360186c834fSShuhei Matsumoto rc = spdk_bdev_part_base_construct_ext(base_bdev_name,
3618466e2c6SChunyang Hui vbdev_opal_base_bdev_hotremove_cb, &opal_if,
362186c834fSShuhei Matsumoto &opal_vbdev_fn_table, &opal_part_base->part_tailq,
363186c834fSShuhei Matsumoto vbdev_opal_base_free, opal_part_base,
364186c834fSShuhei Matsumoto sizeof(struct vbdev_opal_channel), NULL, NULL,
365186c834fSShuhei Matsumoto &opal_part_base->part_base);
366186c834fSShuhei Matsumoto if (rc != 0) {
367186c834fSShuhei Matsumoto if (rc != -ENODEV) {
3688466e2c6SChunyang Hui SPDK_ERRLOG("Could not allocate part_base\n");
369186c834fSShuhei Matsumoto }
370021ebb35SChangpeng Liu free(opal_bdev);
3718466e2c6SChunyang Hui free(opal_part_base);
372186c834fSShuhei Matsumoto return rc;
3738466e2c6SChunyang Hui }
374021ebb35SChangpeng Liu opal_part_base->nvme_ctrlr_name = strdup(nvme_ctrlr_name);
37571a1bbddSChunyang Hui if (opal_part_base->nvme_ctrlr_name == NULL) {
376021ebb35SChangpeng Liu free(opal_bdev);
37771a1bbddSChunyang Hui spdk_bdev_part_base_free(opal_part_base->part_base);
37871a1bbddSChunyang Hui return -ENOMEM;
37971a1bbddSChunyang Hui }
3808466e2c6SChunyang Hui
3818466e2c6SChunyang Hui TAILQ_INSERT_TAIL(&g_opal_base, opal_part_base, tailq);
3828466e2c6SChunyang Hui }
383021ebb35SChangpeng Liu assert(opal_part_base != NULL);
384021ebb35SChangpeng Liu opal_bdev->opal_base = opal_part_base;
3858466e2c6SChunyang Hui
3868466e2c6SChunyang Hui part_bdev = calloc(1, sizeof(struct spdk_bdev_part));
3878466e2c6SChunyang Hui if (!part_bdev) {
3888466e2c6SChunyang Hui SPDK_ERRLOG("Could not allocate part_bdev\n");
389021ebb35SChangpeng Liu free(opal_bdev);
3908466e2c6SChunyang Hui return -ENOMEM;
3918466e2c6SChunyang Hui }
3928466e2c6SChunyang Hui
3938466e2c6SChunyang Hui TAILQ_INSERT_TAIL(&g_opal_vbdev, opal_bdev, tailq);
3948466e2c6SChunyang Hui opal_vbdev_name = spdk_sprintf_alloc("%sr%" PRIu8, base_bdev_name,
395021ebb35SChangpeng Liu opal_bdev->locking_range_id); /* e.g.: nvme0n1r1 */
3968466e2c6SChunyang Hui if (opal_vbdev_name == NULL) {
3978466e2c6SChunyang Hui SPDK_ERRLOG("Could not allocate opal_vbdev_name\n");
3988466e2c6SChunyang Hui rc = -ENOMEM;
3998466e2c6SChunyang Hui goto err;
4008466e2c6SChunyang Hui }
4018466e2c6SChunyang Hui
4028466e2c6SChunyang Hui opal_bdev->name = opal_vbdev_name;
4038466e2c6SChunyang Hui rc = spdk_opal_cmd_setup_locking_range(opal_bdev->opal_dev, OPAL_ADMIN1,
404021ebb35SChangpeng Liu opal_bdev->locking_range_id, opal_bdev->range_start,
405021ebb35SChangpeng Liu opal_bdev->range_length, password);
4068466e2c6SChunyang Hui if (rc) {
4078466e2c6SChunyang Hui SPDK_ERRLOG("Error construct %s\n", opal_vbdev_name);
4088466e2c6SChunyang Hui goto err;
4098466e2c6SChunyang Hui }
4108466e2c6SChunyang Hui
411021ebb35SChangpeng Liu rc = spdk_bdev_part_construct(part_bdev, opal_bdev->opal_base->part_base, opal_vbdev_name,
412021ebb35SChangpeng Liu opal_bdev->range_start, opal_bdev->range_length, "Opal locking range");
4138466e2c6SChunyang Hui if (rc) {
4148466e2c6SChunyang Hui SPDK_ERRLOG("Could not allocate bdev part\n");
4158466e2c6SChunyang Hui goto err;
4168466e2c6SChunyang Hui }
4178466e2c6SChunyang Hui
4188466e2c6SChunyang Hui /* lock this bdev initially */
4198466e2c6SChunyang Hui rc = spdk_opal_cmd_lock_unlock(opal_bdev->opal_dev, OPAL_ADMIN1, OPAL_RWLOCK, locking_range_id,
4208466e2c6SChunyang Hui password);
4218466e2c6SChunyang Hui if (rc) {
4228466e2c6SChunyang Hui SPDK_ERRLOG("Error lock %s\n", opal_vbdev_name);
4238466e2c6SChunyang Hui goto err;
4248466e2c6SChunyang Hui }
4258466e2c6SChunyang Hui
4268466e2c6SChunyang Hui opal_bdev->bdev_part = part_bdev;
4278466e2c6SChunyang Hui return 0;
4288466e2c6SChunyang Hui
4298466e2c6SChunyang Hui err:
4308466e2c6SChunyang Hui vbdev_opal_delete(opal_bdev);
4318466e2c6SChunyang Hui free(part_bdev);
4328466e2c6SChunyang Hui return rc;
4338466e2c6SChunyang Hui }
4348466e2c6SChunyang Hui
4358466e2c6SChunyang Hui static void
vbdev_opal_destruct_bdev(struct opal_vbdev * opal_bdev)4368466e2c6SChunyang Hui vbdev_opal_destruct_bdev(struct opal_vbdev *opal_bdev)
4378466e2c6SChunyang Hui {
438c3ace4f4SChangpeng Liu struct spdk_bdev_part *part = opal_bdev->bdev_part;
4398466e2c6SChunyang Hui
440021ebb35SChangpeng Liu assert(opal_bdev->opal_base != NULL);
441c3ace4f4SChangpeng Liu assert(part != NULL);
4428466e2c6SChunyang Hui
443021ebb35SChangpeng Liu if (opal_bdev->range_start == spdk_bdev_part_get_offset_blocks(part)) {
4448466e2c6SChunyang Hui spdk_bdev_unregister(spdk_bdev_part_get_bdev(part), NULL, NULL);
4458466e2c6SChunyang Hui }
4468466e2c6SChunyang Hui vbdev_opal_delete(opal_bdev);
4478466e2c6SChunyang Hui }
4488466e2c6SChunyang Hui
4498466e2c6SChunyang Hui int
vbdev_opal_destruct(const char * bdev_name,const char * password)450b95421d4SSeth Howell vbdev_opal_destruct(const char *bdev_name, const char *password)
4518466e2c6SChunyang Hui {
452a3dcdc05SShuhei Matsumoto struct nvme_ctrlr *nvme_ctrlr;
4538466e2c6SChunyang Hui int locking_range_id;
4548466e2c6SChunyang Hui int rc;
4558466e2c6SChunyang Hui struct opal_vbdev *opal_bdev;
4568466e2c6SChunyang Hui
4578466e2c6SChunyang Hui TAILQ_FOREACH(opal_bdev, &g_opal_vbdev, tailq) {
4588466e2c6SChunyang Hui if (strcmp(opal_bdev->name, bdev_name) == 0) {
4598466e2c6SChunyang Hui break;
4608466e2c6SChunyang Hui }
4618466e2c6SChunyang Hui }
4628466e2c6SChunyang Hui
4638466e2c6SChunyang Hui if (opal_bdev == NULL) {
4648466e2c6SChunyang Hui SPDK_ERRLOG("%s not found\n", bdev_name);
4658466e2c6SChunyang Hui rc = -ENODEV;
4668466e2c6SChunyang Hui goto err;
4678466e2c6SChunyang Hui }
4688466e2c6SChunyang Hui
469021ebb35SChangpeng Liu locking_range_id = opal_bdev->locking_range_id;
4708466e2c6SChunyang Hui
4718466e2c6SChunyang Hui nvme_ctrlr = opal_bdev->nvme_ctrlr;
4728466e2c6SChunyang Hui if (nvme_ctrlr == NULL) {
4738466e2c6SChunyang Hui SPDK_ERRLOG("can't find nvme_ctrlr of %s\n", bdev_name);
4748466e2c6SChunyang Hui return -ENODEV;
4758466e2c6SChunyang Hui }
4768466e2c6SChunyang Hui
4778466e2c6SChunyang Hui /* secure erase locking range */
478ebb01092SChangpeng Liu rc = spdk_opal_cmd_secure_erase_locking_range(nvme_ctrlr->opal_dev, OPAL_ADMIN1, locking_range_id,
4798466e2c6SChunyang Hui password);
4808466e2c6SChunyang Hui if (rc) {
4818466e2c6SChunyang Hui SPDK_ERRLOG("opal erase locking range failed\n");
4828466e2c6SChunyang Hui goto err;
4838466e2c6SChunyang Hui }
4848466e2c6SChunyang Hui
4858466e2c6SChunyang Hui /* reset the locking range to 0 */
4868466e2c6SChunyang Hui rc = spdk_opal_cmd_setup_locking_range(nvme_ctrlr->opal_dev, OPAL_ADMIN1, locking_range_id, 0,
4878466e2c6SChunyang Hui 0, password);
4888466e2c6SChunyang Hui if (rc) {
4898466e2c6SChunyang Hui SPDK_ERRLOG("opal reset locking range failed\n");
4908466e2c6SChunyang Hui goto err;
4918466e2c6SChunyang Hui }
4928466e2c6SChunyang Hui
49336c9ac2dSChunyang Hui spdk_opal_free_locking_range_info(opal_bdev->opal_dev, locking_range_id);
4948466e2c6SChunyang Hui vbdev_opal_destruct_bdev(opal_bdev);
4958466e2c6SChunyang Hui return 0;
4968466e2c6SChunyang Hui
4978466e2c6SChunyang Hui err:
4988466e2c6SChunyang Hui return rc;
4998466e2c6SChunyang Hui }
5008466e2c6SChunyang Hui
5018466e2c6SChunyang Hui static void
vbdev_opal_examine(struct spdk_bdev * bdev)5028466e2c6SChunyang Hui vbdev_opal_examine(struct spdk_bdev *bdev)
5038466e2c6SChunyang Hui {
5048466e2c6SChunyang Hui /* TODO */
5058466e2c6SChunyang Hui spdk_bdev_module_examine_done(&opal_if);
5068466e2c6SChunyang Hui }
5078466e2c6SChunyang Hui
508bc40f5f6SChunyang Hui int
vbdev_opal_set_lock_state(const char * bdev_name,uint16_t user_id,const char * password,const char * lock_state)509b95421d4SSeth Howell vbdev_opal_set_lock_state(const char *bdev_name, uint16_t user_id, const char *password,
510bc40f5f6SChunyang Hui const char *lock_state)
511bc40f5f6SChunyang Hui {
512a3dcdc05SShuhei Matsumoto struct nvme_ctrlr *nvme_ctrlr;
513bc40f5f6SChunyang Hui int locking_range_id;
514bc40f5f6SChunyang Hui int rc;
515bc40f5f6SChunyang Hui enum spdk_opal_lock_state state_flag;
516bc40f5f6SChunyang Hui struct opal_vbdev *opal_bdev;
517bc40f5f6SChunyang Hui
518bc40f5f6SChunyang Hui TAILQ_FOREACH(opal_bdev, &g_opal_vbdev, tailq) {
519bc40f5f6SChunyang Hui if (strcmp(opal_bdev->name, bdev_name) == 0) {
520bc40f5f6SChunyang Hui break;
521bc40f5f6SChunyang Hui }
522bc40f5f6SChunyang Hui }
523bc40f5f6SChunyang Hui
524bc40f5f6SChunyang Hui if (opal_bdev == NULL) {
525bc40f5f6SChunyang Hui SPDK_ERRLOG("%s not found\n", bdev_name);
526bc40f5f6SChunyang Hui return -ENODEV;
527bc40f5f6SChunyang Hui }
528bc40f5f6SChunyang Hui
529bc40f5f6SChunyang Hui nvme_ctrlr = opal_bdev->nvme_ctrlr;
530bc40f5f6SChunyang Hui if (nvme_ctrlr == NULL) {
531bc40f5f6SChunyang Hui SPDK_ERRLOG("can't find nvme_ctrlr of %s\n", opal_bdev->name);
532bc40f5f6SChunyang Hui return -ENODEV;
533bc40f5f6SChunyang Hui }
534bc40f5f6SChunyang Hui
535bc40f5f6SChunyang Hui if (strcasecmp(lock_state, "READWRITE") == 0) {
536bc40f5f6SChunyang Hui state_flag = OPAL_READWRITE;
537bc40f5f6SChunyang Hui } else if (strcasecmp(lock_state, "READONLY") == 0) {
538bc40f5f6SChunyang Hui state_flag = OPAL_READONLY;
539bc40f5f6SChunyang Hui } else if (strcasecmp(lock_state, "RWLOCK") == 0) {
540bc40f5f6SChunyang Hui state_flag = OPAL_RWLOCK;
541bc40f5f6SChunyang Hui } else {
542bc40f5f6SChunyang Hui SPDK_ERRLOG("Invalid OPAL lock state input\n");
543bc40f5f6SChunyang Hui return -EINVAL;
544bc40f5f6SChunyang Hui }
545bc40f5f6SChunyang Hui
546021ebb35SChangpeng Liu locking_range_id = opal_bdev->locking_range_id;
547bc40f5f6SChunyang Hui rc = spdk_opal_cmd_lock_unlock(nvme_ctrlr->opal_dev, user_id, state_flag, locking_range_id,
548bc40f5f6SChunyang Hui password);
549bc40f5f6SChunyang Hui if (rc) {
550bc40f5f6SChunyang Hui SPDK_ERRLOG("%s lock/unlock failure: %d\n", bdev_name, rc);
551bc40f5f6SChunyang Hui }
552bc40f5f6SChunyang Hui
553bc40f5f6SChunyang Hui return rc;
554bc40f5f6SChunyang Hui }
555bc40f5f6SChunyang Hui
556bc40f5f6SChunyang Hui int
vbdev_opal_enable_new_user(const char * bdev_name,const char * admin_password,uint16_t user_id,const char * user_password)557b95421d4SSeth Howell vbdev_opal_enable_new_user(const char *bdev_name, const char *admin_password, uint16_t user_id,
558bc40f5f6SChunyang Hui const char *user_password)
559bc40f5f6SChunyang Hui {
560a3dcdc05SShuhei Matsumoto struct nvme_ctrlr *nvme_ctrlr;
561bc40f5f6SChunyang Hui int locking_range_id;
562bc40f5f6SChunyang Hui int rc;
563bc40f5f6SChunyang Hui struct opal_vbdev *opal_bdev;
564bc40f5f6SChunyang Hui
565bc40f5f6SChunyang Hui TAILQ_FOREACH(opal_bdev, &g_opal_vbdev, tailq) {
566bc40f5f6SChunyang Hui if (strcmp(opal_bdev->name, bdev_name) == 0) {
567bc40f5f6SChunyang Hui break;
568bc40f5f6SChunyang Hui }
569bc40f5f6SChunyang Hui }
570bc40f5f6SChunyang Hui
571bc40f5f6SChunyang Hui if (opal_bdev == NULL) {
572bc40f5f6SChunyang Hui SPDK_ERRLOG("%s not found\n", bdev_name);
573bc40f5f6SChunyang Hui return -ENODEV;
574bc40f5f6SChunyang Hui }
575bc40f5f6SChunyang Hui
576bc40f5f6SChunyang Hui nvme_ctrlr = opal_bdev->nvme_ctrlr;
577bc40f5f6SChunyang Hui if (nvme_ctrlr == NULL) {
578bc40f5f6SChunyang Hui SPDK_ERRLOG("can't find nvme_ctrlr of %s\n", opal_bdev->name);
579bc40f5f6SChunyang Hui return -ENODEV;
580bc40f5f6SChunyang Hui }
581bc40f5f6SChunyang Hui
582bc40f5f6SChunyang Hui rc = spdk_opal_cmd_enable_user(nvme_ctrlr->opal_dev, user_id, admin_password);
583bc40f5f6SChunyang Hui if (rc) {
584bc40f5f6SChunyang Hui SPDK_ERRLOG("%s enable user error: %d\n", bdev_name, rc);
585bc40f5f6SChunyang Hui return rc;
586bc40f5f6SChunyang Hui }
587bc40f5f6SChunyang Hui
588bc40f5f6SChunyang Hui rc = spdk_opal_cmd_set_new_passwd(nvme_ctrlr->opal_dev, user_id, user_password, admin_password,
589bc40f5f6SChunyang Hui true);
590bc40f5f6SChunyang Hui if (rc) {
591bc40f5f6SChunyang Hui SPDK_ERRLOG("%s set user password error: %d\n", bdev_name, rc);
592bc40f5f6SChunyang Hui return rc;
593bc40f5f6SChunyang Hui }
594bc40f5f6SChunyang Hui
595021ebb35SChangpeng Liu locking_range_id = opal_bdev->locking_range_id;
596bc40f5f6SChunyang Hui rc = spdk_opal_cmd_add_user_to_locking_range(nvme_ctrlr->opal_dev, user_id, locking_range_id,
597bc40f5f6SChunyang Hui OPAL_READONLY, admin_password);
598bc40f5f6SChunyang Hui if (rc) {
599bc40f5f6SChunyang Hui SPDK_ERRLOG("%s add user READONLY priority error: %d\n", bdev_name, rc);
600bc40f5f6SChunyang Hui return rc;
601bc40f5f6SChunyang Hui }
602bc40f5f6SChunyang Hui
603bc40f5f6SChunyang Hui rc = spdk_opal_cmd_add_user_to_locking_range(nvme_ctrlr->opal_dev, user_id, locking_range_id,
604bc40f5f6SChunyang Hui OPAL_READWRITE, admin_password);
605bc40f5f6SChunyang Hui if (rc) {
606bc40f5f6SChunyang Hui SPDK_ERRLOG("%s add user READWRITE priority error: %d\n", bdev_name, rc);
607bc40f5f6SChunyang Hui return rc;
608bc40f5f6SChunyang Hui }
609bc40f5f6SChunyang Hui
610bc40f5f6SChunyang Hui return 0;
611bc40f5f6SChunyang Hui }
612bc40f5f6SChunyang Hui
6132172c432STomasz Zawadzki SPDK_LOG_REGISTER_COMPONENT(vbdev_opal)
614