diff --git a/include/spdk/ftl.h b/include/spdk/ftl.h index ff9b1cf3d..a4a5ab6ee 100644 --- a/include/spdk/ftl.h +++ b/include/spdk/ftl.h @@ -141,6 +141,8 @@ struct spdk_ftl_attrs { size_t lbk_size; /* Write buffer cache */ struct spdk_bdev_desc *cache_bdev_desc; + /* Allow partial recovery after dirty shutdown */ + bool allow_open_bands; }; struct ftl_module_init_opts { diff --git a/lib/bdev/nvme/bdev_ftl.c b/lib/bdev/nvme/bdev_ftl.c index 32657320d..396c83da1 100644 --- a/lib/bdev/nvme/bdev_ftl.c +++ b/lib/bdev/nvme/bdev_ftl.c @@ -436,6 +436,8 @@ bdev_ftl_write_config_json(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w spdk_json_write_named_string(w, "cache", cache_bdev); } + spdk_json_write_named_bool(w, "allow_open_bands", attrs.allow_open_bands); + spdk_json_write_object_end(w); spdk_json_write_object_end(w); } @@ -749,8 +751,13 @@ bdev_ftl_create(struct spdk_nvme_ctrlr *ctrlr, const struct ftl_bdev_init_opts * struct spdk_bdev *cache_bdev = NULL; struct nvme_bdev_ctrlr *ftl_ctrlr; struct spdk_ftl_dev_init_opts opts = {}; + struct spdk_ftl_conf conf = {}; int rc; + spdk_ftl_conf_init_defaults(&conf); + + conf.allow_open_bands = bdev_opts->allow_open_bands; + ftl_ctrlr = bdev_ftl_add_ctrlr(ctrlr, &bdev_opts->trid); if (!ftl_ctrlr) { spdk_nvme_detach(ctrlr); @@ -804,7 +811,7 @@ bdev_ftl_create(struct spdk_nvme_ctrlr *ctrlr, const struct ftl_bdev_init_opts * opts.uuid = bdev_opts->uuid; opts.name = ftl_bdev->bdev.name; opts.cache_bdev_desc = ftl_bdev->cache_bdev_desc; - opts.conf = NULL; + opts.conf = &conf; /* TODO: set threads based on config */ opts.core_thread = opts.read_thread = spdk_get_thread(); diff --git a/lib/bdev/nvme/bdev_ftl.h b/lib/bdev/nvme/bdev_ftl.h index ad5d91584..cea59cec3 100644 --- a/lib/bdev/nvme/bdev_ftl.h +++ b/lib/bdev/nvme/bdev_ftl.h @@ -64,6 +64,8 @@ struct ftl_bdev_init_opts { uint32_t mode; /* UUID if device is restored from SSD */ struct spdk_uuid uuid; + /* Allow for partial restore after dirty shutdown */ + bool allow_open_bands; }; typedef void (*ftl_bdev_init_fn)(const struct ftl_bdev_info *, void *, int); diff --git a/lib/bdev/nvme/bdev_ftl_rpc.c b/lib/bdev/nvme/bdev_ftl_rpc.c index f4b732674..f9821e696 100644 --- a/lib/bdev/nvme/bdev_ftl_rpc.c +++ b/lib/bdev/nvme/bdev_ftl_rpc.c @@ -46,6 +46,7 @@ struct rpc_construct_ftl { char *punits; char *uuid; char *cache_bdev; + bool allow_open_bands; }; static void @@ -66,6 +67,10 @@ static const struct spdk_json_object_decoder rpc_construct_ftl_decoders[] = { {"punits", offsetof(struct rpc_construct_ftl, punits), spdk_json_decode_string}, {"uuid", offsetof(struct rpc_construct_ftl, uuid), spdk_json_decode_string, true}, {"cache", offsetof(struct rpc_construct_ftl, cache_bdev), spdk_json_decode_string, true}, + { + "allow_open_bands", offsetof(struct rpc_construct_ftl, allow_open_bands), + spdk_json_decode_bool, true + }, }; #define FTL_RANGE_MAX_LENGTH 32 @@ -123,6 +128,7 @@ spdk_rpc_construct_ftl_bdev(struct spdk_jsonrpc_request *request, opts.name = req.name; opts.mode = SPDK_FTL_MODE_CREATE; opts.cache_bdev = req.cache_bdev; + opts.allow_open_bands = req.allow_open_bands; /* Parse trtype */ rc = spdk_nvme_transport_id_parse_trtype(&opts.trid.trtype, req.trtype); diff --git a/lib/ftl/ftl_core.c b/lib/ftl/ftl_core.c index 921cc7c90..aba090a9c 100644 --- a/lib/ftl/ftl_core.c +++ b/lib/ftl/ftl_core.c @@ -1643,6 +1643,7 @@ spdk_ftl_dev_get_attrs(const struct spdk_ftl_dev *dev, struct spdk_ftl_attrs *at attrs->lbk_size = FTL_BLOCK_SIZE; attrs->range = dev->range; attrs->cache_bdev_desc = dev->nv_cache.bdev_desc; + attrs->allow_open_bands = dev->conf.allow_open_bands; } static void diff --git a/scripts/rpc.py b/scripts/rpc.py index 676b2a848..e52eb81ae 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -1298,7 +1298,8 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse traddr=args.traddr, punits=args.punits, uuid=args.uuid, - cache=args.cache)) + cache=args.cache, + allow_open_bands=args.allow_open_bands)) p = subparsers.add_parser('construct_ftl_bdev', help='Add FTL bdev') @@ -1312,6 +1313,8 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse p.add_argument('-u', '--uuid', help='UUID of restored bdev (not applicable when creating new ' 'instance): e.g. b286d19a-0059-4709-abcd-9f7732b1567d (optional)') p.add_argument('-c', '--cache', help='Name of the bdev to be used as a write buffer cache (optional)') + p.add_argument('-o', '--allow_open_bands', help='Restoring after dirty shutdown without cache will' + ' result in partial data recovery, instead of error', action='store_true') p.set_defaults(func=construct_ftl_bdev) def delete_ftl_bdev(args): diff --git a/scripts/rpc/bdev.py b/scripts/rpc/bdev.py index 7b95a6211..d75ca9d79 100644 --- a/scripts/rpc/bdev.py +++ b/scripts/rpc/bdev.py @@ -586,7 +586,7 @@ def destruct_split_vbdev(client, base_bdev): return client.call('destruct_split_vbdev', params) -def construct_ftl_bdev(client, name, trtype, traddr, punits, uuid=None, cache=None): +def construct_ftl_bdev(client, name, trtype, traddr, punits, allow_open_bands, uuid=None, cache=None): """Construct FTL bdev Args: @@ -596,11 +596,13 @@ def construct_ftl_bdev(client, name, trtype, traddr, punits, uuid=None, cache=No punit: parallel unit range uuid: UUID of the device cache: name of the write buffer bdev + allow_open_bands: allow for partial restore after dirty shutdown """ params = {'name': name, 'trtype': trtype, 'traddr': traddr, - 'punits': punits} + 'punits': punits, + 'allow_open_bands': allow_open_bands} if uuid: params['uuid'] = uuid if cache: