From 40c06e52c1d6bd99f5a864ce17bcae5e3f876a39 Mon Sep 17 00:00:00 2001 From: Arseniy Kuznetsov Date: Thu, 27 Jul 2023 12:48:25 +0000 Subject: [PATCH 01/24] raid1: add base bdev Add new funcitons for adding base bdev into raid. --- module/bdev/raid/bdev_raid.h | 5 ++ module/bdev/raid/bdev_raid_rpc.c | 83 ++++++++++++++++++++++++++++++++ module/bdev/raid/raid1.c | 33 +++++++++++++ python/spdk/rpc/bdev.py | 14 ++++++ scripts/rpc.py | 9 ++++ 5 files changed, 144 insertions(+) diff --git a/module/bdev/raid/bdev_raid.h b/module/bdev/raid/bdev_raid.h index c6e31ea2ca2..13931c2cfc7 100644 --- a/module/bdev/raid/bdev_raid.h +++ b/module/bdev/raid/bdev_raid.h @@ -254,6 +254,11 @@ struct raid_bdev_module { */ void (*resize)(struct raid_bdev *raid_bdev); + /* + * Called when a base_bdev is adding to degraded raid. + */ + int (*add_base_bdev)(struct raid_bdev *raid_bdev, char *base_bdev, uint8_t slot) + TAILQ_ENTRY(raid_bdev_module) link; }; diff --git a/module/bdev/raid/bdev_raid_rpc.c b/module/bdev/raid/bdev_raid_rpc.c index cd11dc329f3..48cf415eab8 100644 --- a/module/bdev/raid/bdev_raid_rpc.c +++ b/module/bdev/raid/bdev_raid_rpc.c @@ -451,3 +451,86 @@ rpc_bdev_raid_remove_base_bdev(struct spdk_jsonrpc_request *request, rpc_bdev_raid_remove_base_bdev_done(request, rc); } SPDK_RPC_REGISTER("bdev_raid_remove_base_bdev", rpc_bdev_raid_remove_base_bdev, SPDK_RPC_RUNTIME) + +static void +free_rpc_bdev_raid_add_base_bdev(rpc_bdev_raid_add_base_bdev *req) { + free(req->name); + free(req->base_bdev) +} + +struct rpc_bdev_raid_add_base_bdev { + char *name; + char *base_bdev; +} + +static const struct spdk_json_object_decoder rpc_bdev_raid_add_base_bdev_decoders[] = { + {"name", offsetof(struct rpc_bdev_raid_add_base_bdev_decoders, name), spdk_json_decode_string}, + {"base_bdev", offsetof(struct rpc_bdev_raid_add_base_bdev_decoders, base_bdevs), decode_base_bdevs}, +}; + +/* + * brief: + * bdev_raid_add_base_bdev function is the RPC for adding base bdev to a raid bdev. + * It takes base bdev name and raid name as input. + * params: + * request - pointer to json rpc request + * params - pointer to request parameters + * returns: + * none + */ +static void +rpc_bdev_raid_add_base_bdev(struct spdk_jsonrpc_request *request, + const struct spdk_json_val *params) +{ + struct rpc_bdev_raid_add_base_bdev req = {}; + struct raid_bdev *raid_bdev; + uint8_t rc; + + if (spdk_json_decode_object(params, rpc_bdev_raid_add_base_bdev_decoders, + SPDK_COUNTOF(rpc_bdev_raid_add_base_bdev_decoders), + &req)) { + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR, + "spdk_json_decode_object failed"); + goto cleanup; + } + + raid_bdev = raid_bdev_find_by_name(req.name); + if (raid_bdev == NULL) { + spdk_jsonrpc_send_error_response_fmt(request, -ENODEV, + "raid bdev %s not found", + ctx->req.name); + goto cleanup; + } + + rc = raid_bdev_add_base_bdev(req.name, req.strip_size_kb, req.base_bdevs.num_base_bdevs, + req.level, &raid_bdev, uuid); + if (rc != 0) { + spdk_jsonrpc_send_error_response_fmt(request, rc, + "Failed to add RAID bdev %s: %s", + req.name, spdk_strerror(-rc)); + goto cleanup; + } + + for (i = 0; i < raid_bdev->num_base_bdevs; i++) { + if (raid_bdev->base_bdev_info->name != NULL) + continue; + rc = raid_bdev->module->add_base_bdev(raid_bdev, req->base_bdev, i) + if (rc == -ENODEV) { + SPDK_DEBUGLOG(bdev_raid, "base bdev %s doesn't exist now\n", base_bdev_name); + } else if (rc != 0) { + spdk_jsonrpc_send_error_response_fmt(request, rc, + "Failed to add base bdev %s to RAID bdev %s: %s", + base_bdev, req.name, + spdk_strerror(-rc)); + goto cleanup; + } else { + SPDK_DEBUGLOG(bdev_raid, "base bdev %s added to raid bdev %s\n", base_bdev_name, req.name); + } + } + + spdk_jsonrpc_send_bool_response(request, true); + +cleanup: + free_rpc_bdev_raid_add_base_bdev(&req); +} +SPDK_RPC_REGISTER("bdev_raid_remove_base_bdev", rpc_bdev_raid_remove_base_bdev, SPDK_RPC_RUNTIME) diff --git a/module/bdev/raid/raid1.c b/module/bdev/raid/raid1.c index 74506503060..c05011e2cee 100644 --- a/module/bdev/raid/raid1.c +++ b/module/bdev/raid/raid1.c @@ -209,6 +209,38 @@ raid1_stop(struct raid_bdev *raid_bdev) return true; } +static int +raid1_copy_data_to_base_bdev(struct raid_bdev *raid_bdev, char *base_bdev, uint8_t slot) { + //it's don't work and can't work + + // for (i = 0; i < raid_bdev->num_base_bdevs; i++) { + // if (raid_bdev->base_bdev_info[i].name == NULL || i == slot) + // continue; + // else { + // // struct *src_bdev = raid_bdev->base_bdev_info[i].desc; + // // struct *dst_bdev = spdk_bdev_get_by_name(base_bdev); + // // struct *spdk_io_channel src_channel = spdk_bdev_get_io_channel(src_bdev); + // // struct *spdk_io_channel dst_channel = spdk_bdev_get_io_channel(dst_bdev); + // // return spdk_bdev_copy_blocks(dst_bdev, ); + // } + // } + SPDK_ERRLOG("Start the stub for copy data to base bdev\n"); +} + +static int +raid1_add_bdev(struct raid_bdev *raid_bdev, char *base_bdev, uint8_t slot) { + int rc; + + rc = raid_bdev_add_base_device(raid_bdev, base_bdev_name, i); + if (rc) + return rc; + + rc = raid1_copy_data_to_base_bdev(raid_bdev, base_bdev, slot); + if (rc) + SPDK_ERRLOG("Faild to copy data to adding base bdev\n"); + return rc +} + static struct raid_bdev_module g_raid1_module = { .level = RAID1, .base_bdevs_min = 2, @@ -217,6 +249,7 @@ static struct raid_bdev_module g_raid1_module = { .start = raid1_start, .stop = raid1_stop, .submit_rw_request = raid1_submit_rw_request, + .add_base_bdev = raid1_add_bdev, }; RAID_MODULE_REGISTER(&g_raid1_module) diff --git a/python/spdk/rpc/bdev.py b/python/spdk/rpc/bdev.py index 9245d76007c..df224cb93c7 100644 --- a/python/spdk/rpc/bdev.py +++ b/python/spdk/rpc/bdev.py @@ -448,6 +448,20 @@ def bdev_raid_remove_base_bdev(client, name): params = {'name': name} return client.call('bdev_raid_remove_base_bdev', params) +def bdev_raid_add_base_bdev(client, name, base_bdev): + """Add base bdev to existing raid bdev + + Args: + name: raid name + base_bdev: base bdev name + + Returns: + None + """ + params = {'name': name, + 'base_bdev': base_bdev} + return client.call('bdev_raid_add_base_bdev', params) + def bdev_aio_create(client, filename, name, block_size=None, readonly=False): """Construct a Linux AIO block device. diff --git a/scripts/rpc.py b/scripts/rpc.py index 969007d8ba3..8e5e9c4dec9 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -2138,6 +2138,15 @@ def bdev_raid_remove_base_bdev(args): p.add_argument('name', help='base bdev name') p.set_defaults(func=bdev_raid_remove_base_bdev) + def bdev_raid_add_base_bdev(args): + rpc.bdev.bdev_raid_add_base_bdev(args.client, + name=args.name, + nase_bdev=args.base_bdev) + p = subparsers.add_parser('bdev_raid_add_base_bdev', help='Add a basic bdev to an existing raid bdev') + p.add_argument('-n', '--name', help='raid bdev name', required=True) + p.add_argument('-b', '--base-bdev', help = 'base bdev name', required=True) + p.set_defaults(func=bdev_raid_add_base_bdev) + # split def bdev_split_create(args): print_array(rpc.bdev.bdev_split_create(args.client, From 079cb372facaee8efe0ad6365760364e8ef14453 Mon Sep 17 00:00:00 2001 From: Arseniy Kuznetsov Date: Thu, 27 Jul 2023 13:44:20 +0000 Subject: [PATCH 02/24] raid1: fix add base bdev --- module/bdev/raid/bdev_raid.h | 4 ++-- module/bdev/raid/bdev_raid_rpc.c | 38 ++++++++++++-------------------- module/bdev/raid/raid1.c | 5 +++-- 3 files changed, 19 insertions(+), 28 deletions(-) diff --git a/module/bdev/raid/bdev_raid.h b/module/bdev/raid/bdev_raid.h index 13931c2cfc7..d33bf4d10d8 100644 --- a/module/bdev/raid/bdev_raid.h +++ b/module/bdev/raid/bdev_raid.h @@ -257,8 +257,8 @@ struct raid_bdev_module { /* * Called when a base_bdev is adding to degraded raid. */ - int (*add_base_bdev)(struct raid_bdev *raid_bdev, char *base_bdev, uint8_t slot) - + int (*add_base_bdev)(struct raid_bdev *raid_bdev, char *base_bdev, uint8_t slot); + TAILQ_ENTRY(raid_bdev_module) link; }; diff --git a/module/bdev/raid/bdev_raid_rpc.c b/module/bdev/raid/bdev_raid_rpc.c index 48cf415eab8..e16bdca3772 100644 --- a/module/bdev/raid/bdev_raid_rpc.c +++ b/module/bdev/raid/bdev_raid_rpc.c @@ -452,20 +452,20 @@ rpc_bdev_raid_remove_base_bdev(struct spdk_jsonrpc_request *request, } SPDK_RPC_REGISTER("bdev_raid_remove_base_bdev", rpc_bdev_raid_remove_base_bdev, SPDK_RPC_RUNTIME) -static void -free_rpc_bdev_raid_add_base_bdev(rpc_bdev_raid_add_base_bdev *req) { - free(req->name); - free(req->base_bdev) -} - struct rpc_bdev_raid_add_base_bdev { char *name; char *base_bdev; +}; + +static void +free_rpc_bdev_raid_add_base_bdev(struct rpc_bdev_raid_add_base_bdev *req) { + free(req->name); + free(req->base_bdev); } static const struct spdk_json_object_decoder rpc_bdev_raid_add_base_bdev_decoders[] = { - {"name", offsetof(struct rpc_bdev_raid_add_base_bdev_decoders, name), spdk_json_decode_string}, - {"base_bdev", offsetof(struct rpc_bdev_raid_add_base_bdev_decoders, base_bdevs), decode_base_bdevs}, + {"name", offsetof(struct rpc_bdev_raid_add_base_bdev, name), spdk_json_decode_string}, + {"base_bdev", offsetof(struct rpc_bdev_raid_add_base_bdev, base_bdev), spdk_json_decode_string}, }; /* @@ -484,7 +484,7 @@ rpc_bdev_raid_add_base_bdev(struct spdk_jsonrpc_request *request, { struct rpc_bdev_raid_add_base_bdev req = {}; struct raid_bdev *raid_bdev; - uint8_t rc; + int rc; if (spdk_json_decode_object(params, rpc_bdev_raid_add_base_bdev_decoders, SPDK_COUNTOF(rpc_bdev_raid_add_base_bdev_decoders), @@ -497,30 +497,20 @@ rpc_bdev_raid_add_base_bdev(struct spdk_jsonrpc_request *request, raid_bdev = raid_bdev_find_by_name(req.name); if (raid_bdev == NULL) { spdk_jsonrpc_send_error_response_fmt(request, -ENODEV, - "raid bdev %s not found", - ctx->req.name); + "raid bdev %s not found", req.name); goto cleanup; } - rc = raid_bdev_add_base_bdev(req.name, req.strip_size_kb, req.base_bdevs.num_base_bdevs, - req.level, &raid_bdev, uuid); - if (rc != 0) { - spdk_jsonrpc_send_error_response_fmt(request, rc, - "Failed to add RAID bdev %s: %s", - req.name, spdk_strerror(-rc)); - goto cleanup; - } - - for (i = 0; i < raid_bdev->num_base_bdevs; i++) { + for (uint8_t i = 0; i < raid_bdev->num_base_bdevs; i++) { if (raid_bdev->base_bdev_info->name != NULL) continue; - rc = raid_bdev->module->add_base_bdev(raid_bdev, req->base_bdev, i) + rc = raid_bdev->module->add_base_bdev(raid_bdev, req.base_bdev, i); if (rc == -ENODEV) { SPDK_DEBUGLOG(bdev_raid, "base bdev %s doesn't exist now\n", base_bdev_name); } else if (rc != 0) { spdk_jsonrpc_send_error_response_fmt(request, rc, "Failed to add base bdev %s to RAID bdev %s: %s", - base_bdev, req.name, + req.base_bdev, req.name, spdk_strerror(-rc)); goto cleanup; } else { @@ -533,4 +523,4 @@ rpc_bdev_raid_add_base_bdev(struct spdk_jsonrpc_request *request, cleanup: free_rpc_bdev_raid_add_base_bdev(&req); } -SPDK_RPC_REGISTER("bdev_raid_remove_base_bdev", rpc_bdev_raid_remove_base_bdev, SPDK_RPC_RUNTIME) +SPDK_RPC_REGISTER("bdev_raid_add_base_bdev", rpc_bdev_raid_add_base_bdev, SPDK_RPC_RUNTIME) diff --git a/module/bdev/raid/raid1.c b/module/bdev/raid/raid1.c index c05011e2cee..8210bda21cd 100644 --- a/module/bdev/raid/raid1.c +++ b/module/bdev/raid/raid1.c @@ -225,20 +225,21 @@ raid1_copy_data_to_base_bdev(struct raid_bdev *raid_bdev, char *base_bdev, uint8 // } // } SPDK_ERRLOG("Start the stub for copy data to base bdev\n"); + return 0; } static int raid1_add_bdev(struct raid_bdev *raid_bdev, char *base_bdev, uint8_t slot) { int rc; - rc = raid_bdev_add_base_device(raid_bdev, base_bdev_name, i); + rc = raid_bdev_add_base_device(raid_bdev, base_bdev, slot); if (rc) return rc; rc = raid1_copy_data_to_base_bdev(raid_bdev, base_bdev, slot); if (rc) SPDK_ERRLOG("Faild to copy data to adding base bdev\n"); - return rc + return rc; } static struct raid_bdev_module g_raid1_module = { From 5ed643a71e87802570d67616b95abc9e0210b74d Mon Sep 17 00:00:00 2001 From: Arseniy Kuznetsov Date: Thu, 27 Jul 2023 15:11:07 +0000 Subject: [PATCH 03/24] rpc.py: fix bdev_raid_add_base_bdev change the typo "nase_bdev" to "base_bdev" --- scripts/rpc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/rpc.py b/scripts/rpc.py index 8e5e9c4dec9..cb5e083a6c6 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -2141,7 +2141,7 @@ def bdev_raid_remove_base_bdev(args): def bdev_raid_add_base_bdev(args): rpc.bdev.bdev_raid_add_base_bdev(args.client, name=args.name, - nase_bdev=args.base_bdev) + base_bdev=args.base_bdev) p = subparsers.add_parser('bdev_raid_add_base_bdev', help='Add a basic bdev to an existing raid bdev') p.add_argument('-n', '--name', help='raid bdev name', required=True) p.add_argument('-b', '--base-bdev', help = 'base bdev name', required=True) From f4354aa113a8a1673ba036fc6a907c807d74b5ad Mon Sep 17 00:00:00 2001 From: Arseniy Kuznetsov Date: Thu, 27 Jul 2023 16:34:39 +0000 Subject: [PATCH 04/24] module/raid: refactor add base bdev --- module/bdev/raid/bdev_raid.c | 20 +++++++++++++++++++ module/bdev/raid/bdev_raid.h | 6 +----- module/bdev/raid/bdev_raid_rpc.c | 4 ++-- module/bdev/raid/raid1.c | 34 -------------------------------- 4 files changed, 23 insertions(+), 41 deletions(-) diff --git a/module/bdev/raid/bdev_raid.c b/module/bdev/raid/bdev_raid.c index d1c8ea8e240..8e36bcdb3e3 100644 --- a/module/bdev/raid/bdev_raid.c +++ b/module/bdev/raid/bdev_raid.c @@ -1604,6 +1604,26 @@ raid_bdev_add_base_device(struct raid_bdev *raid_bdev, const char *name, uint8_t return 0; } +static int +fill_matrix(void) { + SPDK_ERRLOG("Fill matrix's stub\n"); + return 0; +}; + +int +raid_add_bdev(struct raid_bdev *raid_bdev, char *base_bdev, uint8_t slot) { + int rc; + + rc = raid_bdev_add_base_device(raid_bdev, base_bdev, slot); + if (rc) + return rc; + + rc = fill_matrix(); + if (rc) + SPDK_ERRLOG("Failed to copy data to adding base bdev\n"); + return rc; +}; + /* * brief: * raid_bdev_examine function is the examine function call by the below layers diff --git a/module/bdev/raid/bdev_raid.h b/module/bdev/raid/bdev_raid.h index d33bf4d10d8..eafef11c288 100644 --- a/module/bdev/raid/bdev_raid.h +++ b/module/bdev/raid/bdev_raid.h @@ -190,6 +190,7 @@ const char *raid_bdev_state_to_str(enum raid_bdev_state state); void raid_bdev_write_info_json(struct raid_bdev *raid_bdev, struct spdk_json_write_ctx *w); int raid_bdev_remove_base_bdev(struct spdk_bdev *base_bdev, raid_bdev_remove_base_bdev_cb cb_fn, void *cb_ctx); +int raid_add_bdev(struct raid_bdev *raid_bdev, char *base_bdev, uint8_t slot); /* * RAID module descriptor @@ -253,11 +254,6 @@ struct raid_bdev_module { * is satisfied. */ void (*resize)(struct raid_bdev *raid_bdev); - - /* - * Called when a base_bdev is adding to degraded raid. - */ - int (*add_base_bdev)(struct raid_bdev *raid_bdev, char *base_bdev, uint8_t slot); TAILQ_ENTRY(raid_bdev_module) link; }; diff --git a/module/bdev/raid/bdev_raid_rpc.c b/module/bdev/raid/bdev_raid_rpc.c index e16bdca3772..f4d7c903314 100644 --- a/module/bdev/raid/bdev_raid_rpc.c +++ b/module/bdev/raid/bdev_raid_rpc.c @@ -502,9 +502,9 @@ rpc_bdev_raid_add_base_bdev(struct spdk_jsonrpc_request *request, } for (uint8_t i = 0; i < raid_bdev->num_base_bdevs; i++) { - if (raid_bdev->base_bdev_info->name != NULL) + if (raid_bdev->base_bdev_info[i].name != NULL) continue; - rc = raid_bdev->module->add_base_bdev(raid_bdev, req.base_bdev, i); + rc = raid_add_bdev(raid_bdev, req.base_bdev, i); if (rc == -ENODEV) { SPDK_DEBUGLOG(bdev_raid, "base bdev %s doesn't exist now\n", base_bdev_name); } else if (rc != 0) { diff --git a/module/bdev/raid/raid1.c b/module/bdev/raid/raid1.c index 8210bda21cd..74506503060 100644 --- a/module/bdev/raid/raid1.c +++ b/module/bdev/raid/raid1.c @@ -209,39 +209,6 @@ raid1_stop(struct raid_bdev *raid_bdev) return true; } -static int -raid1_copy_data_to_base_bdev(struct raid_bdev *raid_bdev, char *base_bdev, uint8_t slot) { - //it's don't work and can't work - - // for (i = 0; i < raid_bdev->num_base_bdevs; i++) { - // if (raid_bdev->base_bdev_info[i].name == NULL || i == slot) - // continue; - // else { - // // struct *src_bdev = raid_bdev->base_bdev_info[i].desc; - // // struct *dst_bdev = spdk_bdev_get_by_name(base_bdev); - // // struct *spdk_io_channel src_channel = spdk_bdev_get_io_channel(src_bdev); - // // struct *spdk_io_channel dst_channel = spdk_bdev_get_io_channel(dst_bdev); - // // return spdk_bdev_copy_blocks(dst_bdev, ); - // } - // } - SPDK_ERRLOG("Start the stub for copy data to base bdev\n"); - return 0; -} - -static int -raid1_add_bdev(struct raid_bdev *raid_bdev, char *base_bdev, uint8_t slot) { - int rc; - - rc = raid_bdev_add_base_device(raid_bdev, base_bdev, slot); - if (rc) - return rc; - - rc = raid1_copy_data_to_base_bdev(raid_bdev, base_bdev, slot); - if (rc) - SPDK_ERRLOG("Faild to copy data to adding base bdev\n"); - return rc; -} - static struct raid_bdev_module g_raid1_module = { .level = RAID1, .base_bdevs_min = 2, @@ -250,7 +217,6 @@ static struct raid_bdev_module g_raid1_module = { .start = raid1_start, .stop = raid1_stop, .submit_rw_request = raid1_submit_rw_request, - .add_base_bdev = raid1_add_bdev, }; RAID_MODULE_REGISTER(&g_raid1_module) From 6f8227537b267b7971cb5a08b8c7420ff02fd3cd Mon Sep 17 00:00:00 2001 From: Arseniy Kuznetsov Date: Thu, 27 Jul 2023 23:58:14 +0000 Subject: [PATCH 05/24] module/raid: fix and improve add base bdev Add checks for bdev's block len and block count, change code of raid configure (it doesn't reconfigure all raid, when raid is becoming not degraded) --- module/bdev/raid/bdev_raid.c | 36 +++++++++++++++++++++++++------- module/bdev/raid/bdev_raid_rpc.c | 1 + 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/module/bdev/raid/bdev_raid.c b/module/bdev/raid/bdev_raid.c index 8e36bcdb3e3..6284babaaac 100644 --- a/module/bdev/raid/bdev_raid.c +++ b/module/bdev/raid/bdev_raid.c @@ -1539,18 +1539,22 @@ raid_bdev_configure_base_bdev(struct raid_base_bdev_info *base_info) SPDK_DEBUGLOG(bdev_raid, "bdev %s is claimed\n", bdev->name); - assert(raid_bdev->state != RAID_BDEV_STATE_ONLINE); + assert(raid_bdev->state == RAID_BDEV_STATE_ONLINE || raid_bdev->state == RAID_BDEV_STATE_CONFIGURING); base_info->desc = desc; - base_info->blockcnt = bdev->blockcnt; raid_bdev->num_base_bdevs_discovered++; assert(raid_bdev->num_base_bdevs_discovered <= raid_bdev->num_base_bdevs); - if (raid_bdev->num_base_bdevs_discovered == raid_bdev->num_base_bdevs) { - rc = raid_bdev_configure(raid_bdev); - if (rc != 0) { - SPDK_ERRLOG("Failed to configure raid bdev\n"); - return rc; + if (raid_bdev->state == RAID_BDEV_STATE_ONLINE) { + bdev->blockcnt = base_info->blockcnt; + } else { + base_info->blockcnt = bdev->blockcnt; + if (raid_bdev->num_base_bdevs_discovered == raid_bdev->num_base_bdevs) { + rc = raid_bdev_configure(raid_bdev); + if (rc != 0) { + SPDK_ERRLOG("Failed to configure raid bdev\n"); + return rc; + } } } @@ -1606,13 +1610,29 @@ raid_bdev_add_base_device(struct raid_bdev *raid_bdev, const char *name, uint8_t static int fill_matrix(void) { - SPDK_ERRLOG("Fill matrix's stub\n"); + SPDK_DEBUGLOG("Fill matrix's stub\n"); return 0; }; int raid_add_bdev(struct raid_bdev *raid_bdev, char *base_bdev, uint8_t slot) { int rc; + struct spdk_bdev *bdev = spdk_bdev_get_by_name(base_bdev); + + if (bdev == NULL) { + SPDK_ERRLOG("Currently unable to find bdev with name: %s\n", base_bdev); + return -ENXIO; + } + + if (bdev->blocklen != raid_bdev->bdev.blocklen) { + SPDK_ERRLOG("Blocklen of the bdev %s not matching with other base bdevs\n", base_bdev); + return -EINVAL; + } + + if (bdev->blockcnt < raid_bdev->bdev.blockcnt) { + SPDK_ERRLOG("The bdev %s size is too small\n", base_bdev); + return -EINVAL; + } rc = raid_bdev_add_base_device(raid_bdev, base_bdev, slot); if (rc) diff --git a/module/bdev/raid/bdev_raid_rpc.c b/module/bdev/raid/bdev_raid_rpc.c index f4d7c903314..d4a36d09df8 100644 --- a/module/bdev/raid/bdev_raid_rpc.c +++ b/module/bdev/raid/bdev_raid_rpc.c @@ -516,6 +516,7 @@ rpc_bdev_raid_add_base_bdev(struct spdk_jsonrpc_request *request, } else { SPDK_DEBUGLOG(bdev_raid, "base bdev %s added to raid bdev %s\n", base_bdev_name, req.name); } + break; } spdk_jsonrpc_send_bool_response(request, true); From 0dfeff7770d0bb2df0ba636ef0c4d7156fee778d Mon Sep 17 00:00:00 2001 From: Arseniy Kuznetsov Date: Tue, 15 Aug 2023 22:36:53 +0000 Subject: [PATCH 06/24] module/raid: refactor var names Change "name" to "raid_name" and "base_bdev" to "base_bdev_name" Also func raid_add_bdev func to raid_bdev_add_base_bdev --- module/bdev/raid/bdev_raid.c | 12 ++++++------ module/bdev/raid/bdev_raid.h | 2 +- module/bdev/raid/bdev_raid_rpc.c | 24 ++++++++++++------------ 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/module/bdev/raid/bdev_raid.c b/module/bdev/raid/bdev_raid.c index 6284babaaac..73c0a47612e 100644 --- a/module/bdev/raid/bdev_raid.c +++ b/module/bdev/raid/bdev_raid.c @@ -1615,26 +1615,26 @@ fill_matrix(void) { }; int -raid_add_bdev(struct raid_bdev *raid_bdev, char *base_bdev, uint8_t slot) { +raid_bdev_add_base_bdev(struct raid_bdev *raid_bdev, char *base_bdev_name, uint8_t slot) { int rc; - struct spdk_bdev *bdev = spdk_bdev_get_by_name(base_bdev); + struct spdk_bdev *bdev = spdk_bdev_get_by_name(base_bdev_name); if (bdev == NULL) { - SPDK_ERRLOG("Currently unable to find bdev with name: %s\n", base_bdev); + SPDK_ERRLOG("Currently unable to find bdev with name: %s\n", base_bdev_name); return -ENXIO; } if (bdev->blocklen != raid_bdev->bdev.blocklen) { - SPDK_ERRLOG("Blocklen of the bdev %s not matching with other base bdevs\n", base_bdev); + SPDK_ERRLOG("Blocklen of the bdev %s not matching with other base bdevs\n", base_bdev_name); return -EINVAL; } if (bdev->blockcnt < raid_bdev->bdev.blockcnt) { - SPDK_ERRLOG("The bdev %s size is too small\n", base_bdev); + SPDK_ERRLOG("The bdev %s size is too small\n", base_bdev_name); return -EINVAL; } - rc = raid_bdev_add_base_device(raid_bdev, base_bdev, slot); + rc = raid_bdev_add_base_device(raid_bdev, base_bdev_name, slot); if (rc) return rc; diff --git a/module/bdev/raid/bdev_raid.h b/module/bdev/raid/bdev_raid.h index eafef11c288..7e8c9371c93 100644 --- a/module/bdev/raid/bdev_raid.h +++ b/module/bdev/raid/bdev_raid.h @@ -190,7 +190,7 @@ const char *raid_bdev_state_to_str(enum raid_bdev_state state); void raid_bdev_write_info_json(struct raid_bdev *raid_bdev, struct spdk_json_write_ctx *w); int raid_bdev_remove_base_bdev(struct spdk_bdev *base_bdev, raid_bdev_remove_base_bdev_cb cb_fn, void *cb_ctx); -int raid_add_bdev(struct raid_bdev *raid_bdev, char *base_bdev, uint8_t slot); +int raid_bdev_add_base_bdev(struct raid_bdev *raid_bdev, char *base_bdev_name, uint8_t slot); /* * RAID module descriptor diff --git a/module/bdev/raid/bdev_raid_rpc.c b/module/bdev/raid/bdev_raid_rpc.c index d4a36d09df8..192d9e13fb8 100644 --- a/module/bdev/raid/bdev_raid_rpc.c +++ b/module/bdev/raid/bdev_raid_rpc.c @@ -453,19 +453,19 @@ rpc_bdev_raid_remove_base_bdev(struct spdk_jsonrpc_request *request, SPDK_RPC_REGISTER("bdev_raid_remove_base_bdev", rpc_bdev_raid_remove_base_bdev, SPDK_RPC_RUNTIME) struct rpc_bdev_raid_add_base_bdev { - char *name; - char *base_bdev; + char *raid_name; + char *base_bdev_name; }; static void free_rpc_bdev_raid_add_base_bdev(struct rpc_bdev_raid_add_base_bdev *req) { - free(req->name); - free(req->base_bdev); + free(req->raid_name); + free(req->base_bdev_name); } static const struct spdk_json_object_decoder rpc_bdev_raid_add_base_bdev_decoders[] = { - {"name", offsetof(struct rpc_bdev_raid_add_base_bdev, name), spdk_json_decode_string}, - {"base_bdev", offsetof(struct rpc_bdev_raid_add_base_bdev, base_bdev), spdk_json_decode_string}, + {"raid_name", offsetof(struct rpc_bdev_raid_add_base_bdev, raid_name), spdk_json_decode_string}, + {"base_bdev_name", offsetof(struct rpc_bdev_raid_add_base_bdev, base_bdev_name), spdk_json_decode_string}, }; /* @@ -494,27 +494,27 @@ rpc_bdev_raid_add_base_bdev(struct spdk_jsonrpc_request *request, goto cleanup; } - raid_bdev = raid_bdev_find_by_name(req.name); + raid_bdev = raid_bdev_find_by_name(req.raid_name); if (raid_bdev == NULL) { spdk_jsonrpc_send_error_response_fmt(request, -ENODEV, - "raid bdev %s not found", req.name); + "raid bdev %s not found", req.raid_name); goto cleanup; } for (uint8_t i = 0; i < raid_bdev->num_base_bdevs; i++) { if (raid_bdev->base_bdev_info[i].name != NULL) continue; - rc = raid_add_bdev(raid_bdev, req.base_bdev, i); + rc = raid_bdev_add_base_bdev(raid_bdev, req.base_bdev_name, i); if (rc == -ENODEV) { - SPDK_DEBUGLOG(bdev_raid, "base bdev %s doesn't exist now\n", base_bdev_name); + SPDK_DEBUGLOG(bdev_raid, "base bdev %s doesn't exist now\n", req.base_bdev_name); } else if (rc != 0) { spdk_jsonrpc_send_error_response_fmt(request, rc, "Failed to add base bdev %s to RAID bdev %s: %s", - req.base_bdev, req.name, + req.base_bdev_name, req.raid_name, spdk_strerror(-rc)); goto cleanup; } else { - SPDK_DEBUGLOG(bdev_raid, "base bdev %s added to raid bdev %s\n", base_bdev_name, req.name); + SPDK_DEBUGLOG(bdev_raid, "base bdev %s added to raid bdev %s\n", req.base_bdev_name, req.raid_name); } break; } From 5fc73347996b8a99346495cbcce3a988718f64d1 Mon Sep 17 00:00:00 2001 From: Arseniy Kuznetsov Date: Tue, 15 Aug 2023 22:39:18 +0000 Subject: [PATCH 07/24] rpc.py: refactor var names change var names --- python/spdk/rpc/bdev.py | 10 +++++----- scripts/rpc.py | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/python/spdk/rpc/bdev.py b/python/spdk/rpc/bdev.py index df224cb93c7..b605d96a81c 100644 --- a/python/spdk/rpc/bdev.py +++ b/python/spdk/rpc/bdev.py @@ -448,18 +448,18 @@ def bdev_raid_remove_base_bdev(client, name): params = {'name': name} return client.call('bdev_raid_remove_base_bdev', params) -def bdev_raid_add_base_bdev(client, name, base_bdev): +def bdev_raid_add_base_bdev(client, raid_name, base_bdev_name): """Add base bdev to existing raid bdev Args: - name: raid name - base_bdev: base bdev name + raid_name: raid bdev name + base_bdev_name: base bdev name Returns: None """ - params = {'name': name, - 'base_bdev': base_bdev} + params = {'raid_name': raid_name, + 'base_bdev_name': base_bdev_name} return client.call('bdev_raid_add_base_bdev', params) diff --git a/scripts/rpc.py b/scripts/rpc.py index cb5e083a6c6..2efb0917ae5 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -2140,11 +2140,11 @@ def bdev_raid_remove_base_bdev(args): def bdev_raid_add_base_bdev(args): rpc.bdev.bdev_raid_add_base_bdev(args.client, - name=args.name, - base_bdev=args.base_bdev) + raid_name=args.raid_name, + base_bdev_name=args.base_bdev_name) p = subparsers.add_parser('bdev_raid_add_base_bdev', help='Add a basic bdev to an existing raid bdev') - p.add_argument('-n', '--name', help='raid bdev name', required=True) - p.add_argument('-b', '--base-bdev', help = 'base bdev name', required=True) + p.add_argument('-r', '--raid-name', help='raid bdev name', required=True) + p.add_argument('-b', '--base-bdev-name', help = 'base bdev name', required=True) p.set_defaults(func=bdev_raid_add_base_bdev) # split From f46ac11647ecf714a9553bffa54bfe9e8aeaa4b8 Mon Sep 17 00:00:00 2001 From: Arseniy Kuznetsov Date: Tue, 19 Sep 2023 23:56:02 +0000 Subject: [PATCH 08/24] module/raid: add OFFLINE state case in add bdev In configure_base_bdev change if to swich. Add empty OFFLINE case with TODO --- module/bdev/raid/bdev_raid.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/module/bdev/raid/bdev_raid.c b/module/bdev/raid/bdev_raid.c index 73c0a47612e..7f66238d2c0 100644 --- a/module/bdev/raid/bdev_raid.c +++ b/module/bdev/raid/bdev_raid.c @@ -1539,23 +1539,28 @@ raid_bdev_configure_base_bdev(struct raid_base_bdev_info *base_info) SPDK_DEBUGLOG(bdev_raid, "bdev %s is claimed\n", bdev->name); - assert(raid_bdev->state == RAID_BDEV_STATE_ONLINE || raid_bdev->state == RAID_BDEV_STATE_CONFIGURING); - base_info->desc = desc; raid_bdev->num_base_bdevs_discovered++; assert(raid_bdev->num_base_bdevs_discovered <= raid_bdev->num_base_bdevs); - if (raid_bdev->state == RAID_BDEV_STATE_ONLINE) { - bdev->blockcnt = base_info->blockcnt; - } else { - base_info->blockcnt = bdev->blockcnt; - if (raid_bdev->num_base_bdevs_discovered == raid_bdev->num_base_bdevs) { - rc = raid_bdev_configure(raid_bdev); - if (rc != 0) { - SPDK_ERRLOG("Failed to configure raid bdev\n"); - return rc; + switch (raid_bdev->state) { + case RAID_BDEV_STATE_ONLINE: + bdev->blockcnt = base_info->blockcnt; + break; + case RAID_BDEV_STATE_CONFIGURING: + base_info->blockcnt = bdev->blockcnt; + if (raid_bdev->num_base_bdevs_discovered == raid_bdev->num_base_bdevs) { + rc = raid_bdev_configure(raid_bdev); + if (rc != 0) { + SPDK_ERRLOG("Failed to configure raid bdev\n"); + return rc; + } } - } + break; + case RAID_BDEV_STATE_OFFLINE: + /* TODO when OFFLINE state is completely implemented */ + default: + SPDK_ERRLOG("unexpected bdev raid state when adding '%s' base bdev", base_info->name); } return 0; @@ -1628,7 +1633,7 @@ raid_bdev_add_base_bdev(struct raid_bdev *raid_bdev, char *base_bdev_name, uint8 SPDK_ERRLOG("Blocklen of the bdev %s not matching with other base bdevs\n", base_bdev_name); return -EINVAL; } - + if (bdev->blockcnt < raid_bdev->bdev.blockcnt) { SPDK_ERRLOG("The bdev %s size is too small\n", base_bdev_name); return -EINVAL; From 2175eecc72f37755af0e6acc12eaa43bacd0528e Mon Sep 17 00:00:00 2001 From: Arseniy Kuznetsov Date: Wed, 20 Sep 2023 14:12:23 +0000 Subject: [PATCH 09/24] module/raid: delete tab --- module/bdev/raid/bdev_raid.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/bdev/raid/bdev_raid.h b/module/bdev/raid/bdev_raid.h index 7e8c9371c93..03a865afc15 100644 --- a/module/bdev/raid/bdev_raid.h +++ b/module/bdev/raid/bdev_raid.h @@ -254,7 +254,7 @@ struct raid_bdev_module { * is satisfied. */ void (*resize)(struct raid_bdev *raid_bdev); - + TAILQ_ENTRY(raid_bdev_module) link; }; From 84b4d27bb1f37666f920c7985f60ef2d654b7d78 Mon Sep 17 00:00:00 2001 From: ItIsMrLaG Date: Mon, 24 Jul 2023 11:29:52 +0000 Subject: [PATCH 10/24] Create rebuild matrix --- module/bdev/raid/bdev_raid.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/module/bdev/raid/bdev_raid.h b/module/bdev/raid/bdev_raid.h index 03a865afc15..d94460114fe 100644 --- a/module/bdev/raid/bdev_raid.h +++ b/module/bdev/raid/bdev_raid.h @@ -5,6 +5,7 @@ #ifndef SPDK_BDEV_RAID_INTERNAL_H #define SPDK_BDEV_RAID_INTERNAL_H +#define MATRIX_REBUILD_SIZE 32768 /* 2^15 */ #include "spdk/bdev_module.h" #include "spdk/uuid.h" @@ -143,6 +144,8 @@ struct raid_bdev { /* Raid Level of this raid bdev */ enum raid_level level; + struct raid_rebuild; + /* Set to true if destroy of this raid bdev is started. */ bool destroy_started; @@ -153,6 +156,10 @@ struct raid_bdev { void *module_private; }; +struct raid_rebuild { + uint64_t rebuild_matrix[MATRIX_REBUILD_SIZE]; +}; + #define RAID_FOR_EACH_BASE_BDEV(r, i) \ for (i = r->base_bdev_info; i < r->base_bdev_info + r->num_base_bdevs; i++) From 074fa341654ad2f7611a4f34bd4b01b7788b7f1c Mon Sep 17 00:00:00 2001 From: juliakononov Date: Mon, 24 Jul 2023 12:28:58 +0000 Subject: [PATCH 11/24] Update rebuild_struct --- module/bdev/raid/bdev_raid.h | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/module/bdev/raid/bdev_raid.h b/module/bdev/raid/bdev_raid.h index d94460114fe..cb2bd2badc7 100644 --- a/module/bdev/raid/bdev_raid.h +++ b/module/bdev/raid/bdev_raid.h @@ -144,6 +144,7 @@ struct raid_bdev { /* Raid Level of this raid bdev */ enum raid_level level; + /* RAID rebuild struct */ struct raid_rebuild; /* Set to true if destroy of this raid bdev is started. */ @@ -156,10 +157,6 @@ struct raid_bdev { void *module_private; }; -struct raid_rebuild { - uint64_t rebuild_matrix[MATRIX_REBUILD_SIZE]; -}; - #define RAID_FOR_EACH_BASE_BDEV(r, i) \ for (i = r->base_bdev_info; i < r->base_bdev_info + r->num_base_bdevs; i++) @@ -199,6 +196,20 @@ int raid_bdev_remove_base_bdev(struct spdk_bdev *base_bdev, raid_bdev_remove_bas void *cb_ctx); int raid_bdev_add_base_bdev(struct raid_bdev *raid_bdev, char *base_bdev_name, uint8_t slot); +/* +* raid_rebuild assists in the raid bdev rebuild process. +*/ +struct raid_rebuild { + /* stores data on broken memory areas */ + uint64_t rebuild_matrix[MATRIX_REBUILD_SIZE]; + + /* number of base bdevs comprising raid bdev */ + uint8_t num_base_bdevs; + + /* number of memory areas */ + uint64_t num_memory_areas +}; + /* * RAID module descriptor */ From f2f165dffa660f0c2e59059ca675be1f6bc17a2d Mon Sep 17 00:00:00 2001 From: ItIsMrLaG Date: Mon, 24 Jul 2023 12:40:42 +0000 Subject: [PATCH 12/24] module/raid: Implement int based rebuild struct for raid1 --- include/spdk/util.h | 6 + module/bdev/raid/bdev_raid.c | 7 +- module/bdev/raid/bdev_raid.h | 43 ++++--- module/bdev/raid/raid1.c | 105 +++++++++++++++++- test/bdev/raid1_rebuild_tests.sh | 79 +++++++++++++ .../raid1_test_config/fio_cfg/randwrite.fio | 13 +++ test/bdev/raid1_test_config/fio_cfg/write.fio | 13 +++ .../raid1_test_config/rpc_json/raid1.json | 37 ++++++ .../bdev/raid1_test_config/rpc_json/stop.json | 27 +++++ 9 files changed, 306 insertions(+), 24 deletions(-) create mode 100755 test/bdev/raid1_rebuild_tests.sh create mode 100644 test/bdev/raid1_test_config/fio_cfg/randwrite.fio create mode 100644 test/bdev/raid1_test_config/fio_cfg/write.fio create mode 100644 test/bdev/raid1_test_config/rpc_json/raid1.json create mode 100644 test/bdev/raid1_test_config/rpc_json/stop.json diff --git a/include/spdk/util.h b/include/spdk/util.h index 34183ffe8ad..2e871a49f27 100644 --- a/include/spdk/util.h +++ b/include/spdk/util.h @@ -42,6 +42,12 @@ extern "C" { /* Ceiling division of unsigned integers */ #define SPDK_CEIL_DIV(x,y) (((x)+(y)-1)/(y)) +#define CHECK_BIT(number, shift_size) (number & (1UL << shift_size)) + +#define INSERT_BIT(number, shift_size) (number |= 1UL << shift_size) + +#define KB_TO_BYTES(number) (number << 10) + /** * Macro to align a value to a given power-of-two. The resultant value * will be of the same type as the first parameter, and will be no diff --git a/module/bdev/raid/bdev_raid.c b/module/bdev/raid/bdev_raid.c index 7f66238d2c0..d3eb351d3be 100644 --- a/module/bdev/raid/bdev_raid.c +++ b/module/bdev/raid/bdev_raid.c @@ -951,12 +951,7 @@ raid_bdev_create(const char *name, uint32_t strip_size, uint8_t num_base_bdevs, return -EEXIST; } - if (level == RAID1) { - if (strip_size != 0) { - SPDK_ERRLOG("Strip size is not supported by raid1\n"); - return -EINVAL; - } - } else if (spdk_u32_is_pow2(strip_size) == false) { + if (spdk_u32_is_pow2(strip_size) == false) { SPDK_ERRLOG("Invalid strip size %" PRIu32 "\n", strip_size); return -EINVAL; } diff --git a/module/bdev/raid/bdev_raid.h b/module/bdev/raid/bdev_raid.h index cb2bd2badc7..541b1db39b6 100644 --- a/module/bdev/raid/bdev_raid.h +++ b/module/bdev/raid/bdev_raid.h @@ -5,11 +5,22 @@ #ifndef SPDK_BDEV_RAID_INTERNAL_H #define SPDK_BDEV_RAID_INTERNAL_H + #define MATRIX_REBUILD_SIZE 32768 /* 2^15 */ +#define MATRIX_REBUILD_AREAS_IN_USE 2 + #include "spdk/bdev_module.h" #include "spdk/uuid.h" +enum rebuild_flags { + /* if there is no broken area in rbm(rebuild_matrix) */ + NOT_NEED_REBUILD = 1, + + /* if there is at least one broken area in rbm(rebuild_matrix) */ + NEED_REBUILD = -1, +}; + enum raid_level { INVALID_RAID_LEVEL = -1, RAID0 = 0, @@ -44,6 +55,23 @@ enum raid_bdev_state { typedef void (*raid_bdev_remove_base_bdev_cb)(void *ctx, int status); +/* + * raid_rebuild assists in the raid bdev rebuild process. + */ +struct raid_rebuild { + /* stores data on broken memory areas */ + uint64_t rebuild_matrix[MATRIX_REBUILD_SIZE]; + + /* number of memory areas */ + uint64_t num_memory_areas; + + /* strip count in one area */ + uint64_t strips_per_area; + + /* rebuild flag */ + uint8_t rebuild_flag; +}; + /* * raid_base_bdev_info contains information for the base bdevs which are part of some * raid. This structure contains the per base bdev information. Whatever is @@ -145,7 +173,7 @@ struct raid_bdev { enum raid_level level; /* RAID rebuild struct */ - struct raid_rebuild; + struct raid_rebuild rebuild; /* Set to true if destroy of this raid bdev is started. */ bool destroy_started; @@ -196,19 +224,6 @@ int raid_bdev_remove_base_bdev(struct spdk_bdev *base_bdev, raid_bdev_remove_bas void *cb_ctx); int raid_bdev_add_base_bdev(struct raid_bdev *raid_bdev, char *base_bdev_name, uint8_t slot); -/* -* raid_rebuild assists in the raid bdev rebuild process. -*/ -struct raid_rebuild { - /* stores data on broken memory areas */ - uint64_t rebuild_matrix[MATRIX_REBUILD_SIZE]; - - /* number of base bdevs comprising raid bdev */ - uint8_t num_base_bdevs; - - /* number of memory areas */ - uint64_t num_memory_areas -}; /* * RAID module descriptor diff --git a/module/bdev/raid/raid1.c b/module/bdev/raid/raid1.c index 74506503060..12f9b8952b4 100644 --- a/module/bdev/raid/raid1.c +++ b/module/bdev/raid/raid1.c @@ -2,24 +2,105 @@ * Copyright (C) 2022 Intel Corporation. * All rights reserved. */ - #include "bdev_raid.h" #include "spdk/likely.h" #include "spdk/log.h" +#include "spdk/util.h" + struct raid1_info { /* The parent raid bdev */ struct raid_bdev *raid_bdev; }; +/* Find the bdev index of the current IO request */ +static uint32_t +get_current_bdev_idx(struct spdk_bdev_io *bdev_io, struct raid_bdev_io *raid_io, uint32_t *bdev_idx) +{ + for (uint8_t i = 0; i < raid_io->raid_bdev->num_base_bdevs; i++) { + if (raid_io->raid_bdev->base_bdev_info[i].name == bdev_io->bdev->name) { + *bdev_idx = i; + return 0; + } + } + return -ENODEV; +} + +/* Allows to define the memory_rebuild_areas that are involved in current IO request */ +static void +get_io_area_range(struct spdk_bdev_io *bdev_io, struct raid_bdev *raid_bdev, uint64_t *offset, + uint64_t *num) +{ + /* blocks */ + uint64_t offset_blocks = bdev_io->u.bdev.offset_blocks; + uint64_t num_blocks = bdev_io->u.bdev.num_blocks; + + /* blocks -> strips */ + uint64_t offset_strips = (offset_blocks) / raid_bdev->strip_size; + uint64_t num_strips = SPDK_CEIL_DIV(offset_blocks + num_blocks, + raid_bdev->strip_size) - offset_strips; + + /* strips -> areas */ + uint64_t strips_per_area = raid_bdev->rebuild.strips_per_area; + + uint64_t offset_areas = offset_strips / strips_per_area; + uint64_t num_areas = SPDK_CEIL_DIV(offset_strips + num_strips, strips_per_area) - offset_areas; + + + *offset = offset_areas; + *num = num_areas; +} + +/* Write a broken block to the rebuild_matrix */ +static void +write_in_rbm_broken_block(struct spdk_bdev_io *bdev_io, struct raid_bdev_io *raid_io, + uint32_t bdev_idx) +{ + uint64_t offset_areas = 0; + uint64_t num_areas = 0; + + get_io_area_range(bdev_io, raid_io->raid_bdev, &offset_areas, &num_areas); + + for (uint64_t i = offset_areas; i < offset_areas + num_areas; i++) { + uint64_t *area = &raid_io->raid_bdev->rebuild.rebuild_matrix[i]; + INSERT_BIT(*area, bdev_idx); + } +} + +/* Determine if a device needs a rebuild or not */ +static int +get_bdev_rebuild_status(struct raid_bdev *raid_bdev, struct spdk_bdev_io *bdev_io, uint8_t bdev_idx) +{ + uint64_t offset_areas = 0; + uint64_t num_areas = 0; + + get_io_area_range(bdev_io, raid_bdev, &offset_areas, &num_areas); + + for (uint64_t i = offset_areas; i < offset_areas + num_areas; i++) { + uint64_t area = raid_bdev->rebuild.rebuild_matrix[i]; + if (CHECK_BIT(area, bdev_idx)) { + return NEED_REBUILD; + } + } + return NOT_NEED_REBUILD; +} + static void raid1_bdev_io_completion(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) { struct raid_bdev_io *raid_io = cb_arg; + uint32_t bdev_idx = 0; + + get_current_bdev_idx(bdev_io, raid_io, &bdev_idx); spdk_bdev_free_io(bdev_io); + if (!success) { + write_in_rbm_broken_block(bdev_io, raid_io, bdev_idx); + + } + raid_bdev_io_complete_part(raid_io, 1, success ? SPDK_BDEV_IO_STATUS_SUCCESS : SPDK_BDEV_IO_STATUS_FAILED); @@ -60,7 +141,10 @@ raid1_submit_read_request(struct raid_bdev_io *raid_io) RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) { base_ch = raid_io->raid_ch->base_channel[idx]; if (base_ch != NULL) { - break; + if (get_bdev_rebuild_status(raid_bdev, bdev_io, idx) == NOT_NEED_REBUILD) { + break; + } + base_ch = NULL; } idx++; } @@ -118,8 +202,10 @@ raid1_submit_write_request(struct raid_bdev_io *raid_io) base_ch = raid_io->raid_ch->base_channel[idx]; if (base_ch == NULL) { - /* skip a missing base bdev's slot */ raid_io->base_bdev_io_submitted++; + + write_in_rbm_broken_block(bdev_io, raid_io, idx); + raid_bdev_io_complete_part(raid_io, 1, SPDK_BDEV_IO_STATUS_SUCCESS); continue; } @@ -175,6 +261,15 @@ raid1_submit_rw_request(struct raid_bdev_io *raid_io) } } +static void +init_rebuild(struct raid_bdev *raid_bdev) +{ + raid_bdev->rebuild.num_memory_areas = MATRIX_REBUILD_AREAS_IN_USE; + uint64_t stripcnt = SPDK_CEIL_DIV(raid_bdev->bdev.blockcnt, raid_bdev->strip_size); + raid_bdev->rebuild.strips_per_area = SPDK_CEIL_DIV(stripcnt, MATRIX_REBUILD_AREAS_IN_USE); + raid_bdev->rebuild.rebuild_flag = NOT_NEED_REBUILD; +} + static int raid1_start(struct raid_bdev *raid_bdev) { @@ -184,7 +279,7 @@ raid1_start(struct raid_bdev *raid_bdev) r1info = calloc(1, sizeof(*r1info)); if (!r1info) { - SPDK_ERRLOG("Failed to allocate RAID1 info device structure\n"); + SPDK_NOTICELOG("Failed to allocate RAID1 info device structure\n"); return -ENOMEM; } r1info->raid_bdev = raid_bdev; @@ -196,6 +291,8 @@ raid1_start(struct raid_bdev *raid_bdev) raid_bdev->bdev.blockcnt = min_blockcnt; raid_bdev->module_private = r1info; + init_rebuild(raid_bdev); + return 0; } diff --git a/test/bdev/raid1_rebuild_tests.sh b/test/bdev/raid1_rebuild_tests.sh new file mode 100755 index 00000000000..92f87e3f7c6 --- /dev/null +++ b/test/bdev/raid1_rebuild_tests.sh @@ -0,0 +1,79 @@ +#!/bin/bash +# Run with sudo + +# $1 - .../spdk (full_path) +# $2 - .../{ublk_drv} (full_path) + +# If spdk ublk unable +function setup_ublk() { + ./configure --with-ublk; + make -j6; + cd "$1"; + insmod ./ublk_drv.ko; +} + +function fio_test_raid1() { + + local rpc_json_path=./test/bdev/raid1_test_config/rpc_json + local fio_cfg_path=./test/bdev/raid1_test_config/fio_cfg + + echo " "; + echo "------------> TEST: $1 & $3 :START <------------"; + + ./scripts/rpc.py load_config -j $rpc_json_path/$1; + sleep 1; + ./scripts/rpc.py ublk_start_disk Raid1 1; + sleep 1; + fio $fio_cfg_path/$3; + + if [ $? -eq 0 ]; + then + echo "$1 & $3 test PASSED"; + else + echo "$1 & $3 test FAILED"; + fi + + ./scripts/rpc.py ublk_stop_disk 1; + sleep 1; + ./scripts/rpc.py load_config -j $rpc_json_path/$2; + sleep 1; + + echo "------------> TEST: $1 & $3 :FINISH <------------"; + echo " "; +} + +function start() { + ./scripts/setup.sh; + make -j6; + sleep 1; + screen -dmS spdk_tgt ./build/bin/spdk_tgt; + sleep 1; + ./scripts/rpc.py ublk_create_target; + sleep 1; +} + +function finish() { + ./scripts/rpc.py ublk_destroy_target; + screen -S spdk_tgt -X kill; +} + +if [ -z "$1" ] +then + spdk_path=.; +else + spdk_path=$1; +fi + +if [ -n "$2" ] +then + cd spdk_path; + setup_ublk "$2"; +fi + +cd spdk_path +start; + +fio_test_raid1 raid1.json stop.json randwrite.fio; +fio_test_raid1 raid1.json stop.json write.fio; + +finish; diff --git a/test/bdev/raid1_test_config/fio_cfg/randwrite.fio b/test/bdev/raid1_test_config/fio_cfg/randwrite.fio new file mode 100644 index 00000000000..ecf86e0326d --- /dev/null +++ b/test/bdev/raid1_test_config/fio_cfg/randwrite.fio @@ -0,0 +1,13 @@ +[global] +thread=1 +group_reporting=1 +direct=1 +verify=sha256 +size=1M +iodepth=8 +rw=randwrite +bs=4k + +[test] +filename=/dev/ublkb1 +numjobs=1 diff --git a/test/bdev/raid1_test_config/fio_cfg/write.fio b/test/bdev/raid1_test_config/fio_cfg/write.fio new file mode 100644 index 00000000000..4a31e82a4b7 --- /dev/null +++ b/test/bdev/raid1_test_config/fio_cfg/write.fio @@ -0,0 +1,13 @@ +[global] +thread=1 +group_reporting=1 +direct=1 +verify=sha256 +size=64M +iodepth=1 +rw=write +bs=4k + +[test] +filename=/dev/ublkb1 +numjobs=1 diff --git a/test/bdev/raid1_test_config/rpc_json/raid1.json b/test/bdev/raid1_test_config/rpc_json/raid1.json new file mode 100644 index 00000000000..ddde01c4667 --- /dev/null +++ b/test/bdev/raid1_test_config/rpc_json/raid1.json @@ -0,0 +1,37 @@ +{ + "subsystems": [ + { + "subsystem": "bdev", + "config": [ + { + "params": { + "block_size": 4096, + "num_blocks": 16, + "name": "M0" + }, + "method": "bdev_malloc_create" + }, + { + "params": { + "block_size": 4096, + "num_blocks": 16, + "name": "M1" + }, + "method": "bdev_malloc_create" + }, + { + "method": "bdev_raid_create", + "params": { + "name": "Raid1", + "raid_level": "1", + "strip_size_kb": 8, + "base_bdevs": [ + "M0", + "M1" + ] + } + } + ] + } + ] +} diff --git a/test/bdev/raid1_test_config/rpc_json/stop.json b/test/bdev/raid1_test_config/rpc_json/stop.json new file mode 100644 index 00000000000..e4e4d7ee7de --- /dev/null +++ b/test/bdev/raid1_test_config/rpc_json/stop.json @@ -0,0 +1,27 @@ +{ + "subsystems": [ + { + "subsystem": "bdev", + "config": [ + { + "method": "bdev_raid_delete", + "params": { + "name": "Raid1" + } + }, + { + "params": { + "name": "M0" + }, + "method": "bdev_malloc_delete" + }, + { + "params": { + "name": "M1" + }, + "method": "bdev_malloc_delete" + } + ] + } + ] + } \ No newline at end of file From bf94b5ffd94a78860d60fd02164704f9d55647de Mon Sep 17 00:00:00 2001 From: ItIsMrLaG Date: Sat, 16 Sep 2023 18:07:16 +0000 Subject: [PATCH 13/24] Refactor: Rebuild struct allocate --- local-test-0-verify.state | Bin 0 -> 192 bytes module/bdev/raid/bdev_raid.c | 7 +++++++ module/bdev/raid/bdev_raid.h | 2 +- module/bdev/raid/raid1.c | 27 +++++++++++++++++++-------- 4 files changed, 27 insertions(+), 9 deletions(-) create mode 100644 local-test-0-verify.state diff --git a/local-test-0-verify.state b/local-test-0-verify.state new file mode 100644 index 0000000000000000000000000000000000000000..b9e1fa0c0f4da645554a67af0f419dce73adaadb GIT binary patch literal 192 zcmZQ(fPfWHI#(rbI*7>#<%4K2TLCJ7Mn#`qv1HaNo!17B;ylo#uyRXMi%YOdkSh2A Gq5%L)M+=Go literal 0 HcmV?d00001 diff --git a/module/bdev/raid/bdev_raid.c b/module/bdev/raid/bdev_raid.c index d3eb351d3be..39896725848 100644 --- a/module/bdev/raid/bdev_raid.c +++ b/module/bdev/raid/bdev_raid.c @@ -1003,6 +1003,13 @@ raid_bdev_create(const char *name, uint32_t strip_size, uint8_t num_base_bdevs, SPDK_ERRLOG("Unable to allocate memory for raid bdev\n"); return -ENOMEM; } + + /* allocate rebuild struct */ + raid_bdev->rebuild = calloc(1, sizeof(struct raid_rebuild)); + if (!raid_bdev->rebuild) { + SPDK_ERRLOG("Unable to allocate memory for raid rebuild struct\n"); + return -ENOMEM; + } raid_bdev->module = module; raid_bdev->num_base_bdevs = num_base_bdevs; diff --git a/module/bdev/raid/bdev_raid.h b/module/bdev/raid/bdev_raid.h index 541b1db39b6..c1e164ca111 100644 --- a/module/bdev/raid/bdev_raid.h +++ b/module/bdev/raid/bdev_raid.h @@ -173,7 +173,7 @@ struct raid_bdev { enum raid_level level; /* RAID rebuild struct */ - struct raid_rebuild rebuild; + struct raid_rebuild *rebuild; /* Set to true if destroy of this raid bdev is started. */ bool destroy_started; diff --git a/module/bdev/raid/raid1.c b/module/bdev/raid/raid1.c index 12f9b8952b4..2443f935ea0 100644 --- a/module/bdev/raid/raid1.c +++ b/module/bdev/raid/raid1.c @@ -42,7 +42,7 @@ get_io_area_range(struct spdk_bdev_io *bdev_io, struct raid_bdev *raid_bdev, uin raid_bdev->strip_size) - offset_strips; /* strips -> areas */ - uint64_t strips_per_area = raid_bdev->rebuild.strips_per_area; + uint64_t strips_per_area = raid_bdev->rebuild->strips_per_area; uint64_t offset_areas = offset_strips / strips_per_area; uint64_t num_areas = SPDK_CEIL_DIV(offset_strips + num_strips, strips_per_area) - offset_areas; @@ -61,9 +61,8 @@ write_in_rbm_broken_block(struct spdk_bdev_io *bdev_io, struct raid_bdev_io *rai uint64_t num_areas = 0; get_io_area_range(bdev_io, raid_io->raid_bdev, &offset_areas, &num_areas); - for (uint64_t i = offset_areas; i < offset_areas + num_areas; i++) { - uint64_t *area = &raid_io->raid_bdev->rebuild.rebuild_matrix[i]; + uint64_t *area = &raid_io->raid_bdev->rebuild->rebuild_matrix[i]; INSERT_BIT(*area, bdev_idx); } } @@ -76,9 +75,8 @@ get_bdev_rebuild_status(struct raid_bdev *raid_bdev, struct spdk_bdev_io *bdev_i uint64_t num_areas = 0; get_io_area_range(bdev_io, raid_bdev, &offset_areas, &num_areas); - for (uint64_t i = offset_areas; i < offset_areas + num_areas; i++) { - uint64_t area = raid_bdev->rebuild.rebuild_matrix[i]; + uint64_t area = raid_bdev->rebuild->rebuild_matrix[i]; if (CHECK_BIT(area, bdev_idx)) { return NEED_REBUILD; } @@ -264,10 +262,21 @@ raid1_submit_rw_request(struct raid_bdev_io *raid_io) static void init_rebuild(struct raid_bdev *raid_bdev) { - raid_bdev->rebuild.num_memory_areas = MATRIX_REBUILD_AREAS_IN_USE; + raid_bdev->rebuild->num_memory_areas = MATRIX_REBUILD_AREAS_IN_USE; uint64_t stripcnt = SPDK_CEIL_DIV(raid_bdev->bdev.blockcnt, raid_bdev->strip_size); - raid_bdev->rebuild.strips_per_area = SPDK_CEIL_DIV(stripcnt, MATRIX_REBUILD_AREAS_IN_USE); - raid_bdev->rebuild.rebuild_flag = NOT_NEED_REBUILD; + raid_bdev->rebuild->strips_per_area = SPDK_CEIL_DIV(stripcnt, MATRIX_REBUILD_AREAS_IN_USE); + raid_bdev->rebuild->rebuild_flag = NOT_NEED_REBUILD; +} + +static void +destruct_rebuild(struct raid_bdev *raid_bdev) +{ + struct raid_rebuild *r1rebuild = raid_bdev->rebuild; + + if (r1rebuild != NULL) + { + free(r1rebuild); + } } static int @@ -303,6 +312,8 @@ raid1_stop(struct raid_bdev *raid_bdev) free(r1info); + destruct_rebuild(raid_bdev); + return true; } From f0e72402c493efd518bced4f0c0a67abc5eb7e5b Mon Sep 17 00:00:00 2001 From: juliakononov Date: Sun, 17 Sep 2023 21:52:23 +0000 Subject: [PATCH 14/24] Refactor: Change work with rebuild flags This reverts commit 897107205c6aeae99ea6ddaad1d19a7540eb47ab. --- include/spdk/util.h | 6 ++-- module/bdev/raid/bdev_raid.c | 2 +- module/bdev/raid/bdev_raid.h | 17 +++++------ module/bdev/raid/raid1.c | 29 +++++++++---------- .../raid1_test_config/fio_cfg/randwrite.fio | 1 - test/bdev/raid1_test_config/fio_cfg/write.fio | 1 - 6 files changed, 24 insertions(+), 32 deletions(-) diff --git a/include/spdk/util.h b/include/spdk/util.h index 2e871a49f27..5bfcd5c166e 100644 --- a/include/spdk/util.h +++ b/include/spdk/util.h @@ -42,11 +42,11 @@ extern "C" { /* Ceiling division of unsigned integers */ #define SPDK_CEIL_DIV(x,y) (((x)+(y)-1)/(y)) -#define CHECK_BIT(number, shift_size) (number & (1UL << shift_size)) +#define SPDK_TEST_BIT(number_ptr, shift_size) (*(number_ptr) & (1UL << shift_size)) -#define INSERT_BIT(number, shift_size) (number |= 1UL << shift_size) +#define SPDK_SET_BIT(number_ptr, shift_size) (*(number_ptr) |= 1UL << shift_size) -#define KB_TO_BYTES(number) (number << 10) +#define SPDK_KB_TO_B(number) (number << 10) /** * Macro to align a value to a given power-of-two. The resultant value diff --git a/module/bdev/raid/bdev_raid.c b/module/bdev/raid/bdev_raid.c index 39896725848..c699b8a4953 100644 --- a/module/bdev/raid/bdev_raid.c +++ b/module/bdev/raid/bdev_raid.c @@ -1003,7 +1003,7 @@ raid_bdev_create(const char *name, uint32_t strip_size, uint8_t num_base_bdevs, SPDK_ERRLOG("Unable to allocate memory for raid bdev\n"); return -ENOMEM; } - + /* allocate rebuild struct */ raid_bdev->rebuild = calloc(1, sizeof(struct raid_rebuild)); if (!raid_bdev->rebuild) { diff --git a/module/bdev/raid/bdev_raid.h b/module/bdev/raid/bdev_raid.h index c1e164ca111..1617be2bc4d 100644 --- a/module/bdev/raid/bdev_raid.h +++ b/module/bdev/raid/bdev_raid.h @@ -8,17 +8,15 @@ #define MATRIX_REBUILD_SIZE 32768 /* 2^15 */ -#define MATRIX_REBUILD_AREAS_IN_USE 2 - #include "spdk/bdev_module.h" #include "spdk/uuid.h" -enum rebuild_flags { - /* if there is no broken area in rbm(rebuild_matrix) */ - NOT_NEED_REBUILD = 1, +enum rebuild_flag { + /* rebuild flag set during initialization */ + REBUILD_FLAG_INIT_CONFIGURATION = 0, /* if there is at least one broken area in rbm(rebuild_matrix) */ - NEED_REBUILD = -1, + REBUILD_FLAG_NEED_REBUILD = 1, }; enum raid_level { @@ -63,13 +61,13 @@ struct raid_rebuild { uint64_t rebuild_matrix[MATRIX_REBUILD_SIZE]; /* number of memory areas */ - uint64_t num_memory_areas; + uint64_t num_memory_areas; /* strip count in one area */ - uint64_t strips_per_area; + uint64_t strips_per_area; /* rebuild flag */ - uint8_t rebuild_flag; + uint64_t rebuild_flag; }; /* @@ -224,7 +222,6 @@ int raid_bdev_remove_base_bdev(struct spdk_bdev *base_bdev, raid_bdev_remove_bas void *cb_ctx); int raid_bdev_add_base_bdev(struct raid_bdev *raid_bdev, char *base_bdev_name, uint8_t slot); - /* * RAID module descriptor */ diff --git a/module/bdev/raid/raid1.c b/module/bdev/raid/raid1.c index 2443f935ea0..4fb08cfbc4e 100644 --- a/module/bdev/raid/raid1.c +++ b/module/bdev/raid/raid1.c @@ -8,7 +8,6 @@ #include "spdk/log.h" #include "spdk/util.h" - struct raid1_info { /* The parent raid bdev */ struct raid_bdev *raid_bdev; @@ -47,7 +46,6 @@ get_io_area_range(struct spdk_bdev_io *bdev_io, struct raid_bdev *raid_bdev, uin uint64_t offset_areas = offset_strips / strips_per_area; uint64_t num_areas = SPDK_CEIL_DIV(offset_strips + num_strips, strips_per_area) - offset_areas; - *offset = offset_areas; *num = num_areas; } @@ -63,12 +61,12 @@ write_in_rbm_broken_block(struct spdk_bdev_io *bdev_io, struct raid_bdev_io *rai get_io_area_range(bdev_io, raid_io->raid_bdev, &offset_areas, &num_areas); for (uint64_t i = offset_areas; i < offset_areas + num_areas; i++) { uint64_t *area = &raid_io->raid_bdev->rebuild->rebuild_matrix[i]; - INSERT_BIT(*area, bdev_idx); + SPDK_SET_BIT(area, bdev_idx); } } /* Determine if a device needs a rebuild or not */ -static int +static void get_bdev_rebuild_status(struct raid_bdev *raid_bdev, struct spdk_bdev_io *bdev_io, uint8_t bdev_idx) { uint64_t offset_areas = 0; @@ -77,11 +75,10 @@ get_bdev_rebuild_status(struct raid_bdev *raid_bdev, struct spdk_bdev_io *bdev_i get_io_area_range(bdev_io, raid_bdev, &offset_areas, &num_areas); for (uint64_t i = offset_areas; i < offset_areas + num_areas; i++) { uint64_t area = raid_bdev->rebuild->rebuild_matrix[i]; - if (CHECK_BIT(area, bdev_idx)) { - return NEED_REBUILD; + if (SPDK_TEST_BIT(&area, bdev_idx)) { + SPDK_SET_BIT(&(raid_bdev->rebuild->rebuild_flag), REBUILD_FLAG_NEED_REBUILD); } } - return NOT_NEED_REBUILD; } static void @@ -96,7 +93,6 @@ raid1_bdev_io_completion(struct spdk_bdev_io *bdev_io, bool success, void *cb_ar if (!success) { write_in_rbm_broken_block(bdev_io, raid_io, bdev_idx); - } raid_bdev_io_complete_part(raid_io, 1, success ? @@ -139,7 +135,8 @@ raid1_submit_read_request(struct raid_bdev_io *raid_io) RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) { base_ch = raid_io->raid_ch->base_channel[idx]; if (base_ch != NULL) { - if (get_bdev_rebuild_status(raid_bdev, bdev_io, idx) == NOT_NEED_REBUILD) { + get_bdev_rebuild_status(raid_bdev, bdev_io, idx); + if (raid_bdev->rebuild->rebuild_flag != REBUILD_FLAG_INIT_CONFIGURATION) { break; } base_ch = NULL; @@ -262,20 +259,20 @@ raid1_submit_rw_request(struct raid_bdev_io *raid_io) static void init_rebuild(struct raid_bdev *raid_bdev) { - raid_bdev->rebuild->num_memory_areas = MATRIX_REBUILD_AREAS_IN_USE; + raid_bdev->rebuild->num_memory_areas = MATRIX_REBUILD_SIZE; uint64_t stripcnt = SPDK_CEIL_DIV(raid_bdev->bdev.blockcnt, raid_bdev->strip_size); - raid_bdev->rebuild->strips_per_area = SPDK_CEIL_DIV(stripcnt, MATRIX_REBUILD_AREAS_IN_USE); - raid_bdev->rebuild->rebuild_flag = NOT_NEED_REBUILD; + raid_bdev->rebuild->strips_per_area = SPDK_CEIL_DIV(stripcnt, MATRIX_REBUILD_SIZE); + raid_bdev->rebuild->rebuild_flag = REBUILD_FLAG_INIT_CONFIGURATION; } -static void +static void destruct_rebuild(struct raid_bdev *raid_bdev) { struct raid_rebuild *r1rebuild = raid_bdev->rebuild; - if (r1rebuild != NULL) - { + if (r1rebuild != NULL) { free(r1rebuild); + raid_bdev->rebuild = NULL; } } @@ -288,7 +285,7 @@ raid1_start(struct raid_bdev *raid_bdev) r1info = calloc(1, sizeof(*r1info)); if (!r1info) { - SPDK_NOTICELOG("Failed to allocate RAID1 info device structure\n"); + SPDK_ERRLOG("Failed to allocate RAID1 info device structure\n"); return -ENOMEM; } r1info->raid_bdev = raid_bdev; diff --git a/test/bdev/raid1_test_config/fio_cfg/randwrite.fio b/test/bdev/raid1_test_config/fio_cfg/randwrite.fio index ecf86e0326d..4d9ab3d5ad6 100644 --- a/test/bdev/raid1_test_config/fio_cfg/randwrite.fio +++ b/test/bdev/raid1_test_config/fio_cfg/randwrite.fio @@ -1,7 +1,6 @@ [global] thread=1 group_reporting=1 -direct=1 verify=sha256 size=1M iodepth=8 diff --git a/test/bdev/raid1_test_config/fio_cfg/write.fio b/test/bdev/raid1_test_config/fio_cfg/write.fio index 4a31e82a4b7..010046a29e4 100644 --- a/test/bdev/raid1_test_config/fio_cfg/write.fio +++ b/test/bdev/raid1_test_config/fio_cfg/write.fio @@ -1,7 +1,6 @@ [global] thread=1 group_reporting=1 -direct=1 verify=sha256 size=64M iodepth=1 From 993622b39acfbc36f27d986e5fa17a537ad52520 Mon Sep 17 00:00:00 2001 From: juliakononov Date: Mon, 18 Dec 2023 03:04:28 +0000 Subject: [PATCH 15/24] include/spdk: Add SPDK_REMOVE_BIT --- include/spdk/util.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/spdk/util.h b/include/spdk/util.h index 5bfcd5c166e..96f5ce1025a 100644 --- a/include/spdk/util.h +++ b/include/spdk/util.h @@ -46,6 +46,8 @@ extern "C" { #define SPDK_SET_BIT(number_ptr, shift_size) (*(number_ptr) |= 1UL << shift_size) +#define SPDK_REMOVE_BIT(number_ptr, shift_size) (*(number_ptr) &= ~(1UL << shift_size)) + #define SPDK_KB_TO_B(number) (number << 10) /** From 42230a010f5a8d4ae3c4806c408eae43e399a904 Mon Sep 17 00:00:00 2001 From: juliakononov Date: Mon, 18 Dec 2023 03:05:50 +0000 Subject: [PATCH 16/24] bdev/raid: Implement the atomics library --- module/bdev/raid/atomic_raid.h | 117 +++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 module/bdev/raid/atomic_raid.h diff --git a/module/bdev/raid/atomic_raid.h b/module/bdev/raid/atomic_raid.h new file mode 100644 index 00000000000..fe818aac676 --- /dev/null +++ b/module/bdev/raid/atomic_raid.h @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (C) 2018 Intel Corporation. + * All rights reserved. + */ + +#ifndef SPDK_ATOMIC_RAID_INTERNAL_H +#define SPDK_ATOMIC_RAID_INTERNAL_H + +#include "spdk/util.h" + +//typedef int raid_atomic; //реализовать можно позже, но пока не вижу смысла + +typedef uint64_t raid_atomic64; + +#define atomic_read(ptr) (*(__typeof__(*ptr) *volatile) (ptr)) +#define atomic_set(ptr, i) ((*(__typeof__(*ptr) *volatile) (ptr)) = (i)) +#define atomic_inc(ptr) ((void) __sync_fetch_and_add(ptr, 1)) +#define atomic_dec(ptr) ((void) __sync_fetch_and_add(ptr, -1)) +#define atomic_add(ptr, n) ((void) __sync_fetch_and_add(ptr, n)) +#define atomic_sub(ptr, n) ((void) __sync_fetch_and_sub(ptr, n)) + +#define atomic_cmpxchg __sync_bool_compare_and_swap + + +static inline uint64_t +raid_atomic64_read(const raid_atomic64 *a) +{ + return atomic_read(a); +} + +static inline void +raid_atomic64_set(raid_atomic64 *a, uint64_t i) +{ + atomic_set(a, i); +} + +static inline void +raid_atomic64_add(uint64_t i, raid_atomic64 *a) +{ + atomic_add(a, i); +} + +static inline void +raid_atomic64_sub(uint64_t i, raid_atomic64 *a) +{ + atomic_sub(a, i); +} + +static inline void +raid_atomic64_inc(raid_atomic64 *a) +{ + atomic_inc(a); +} + +static inline void +raid_atomic64_dec(raid_atomic64 *a) +{ + atomic_dec(a); +} + +static inline uint64_t +raid_atomic64_add_return(uint64_t i, raid_atomic64 *a) +{ + return __sync_add_and_fetch(a, i); +} + +static inline uint64_t +raid_atomic64_sub_return(uint64_t i, raid_atomic64 *a) +{ + return __sync_sub_and_fetch(a, i); +} + +static inline uint64_t +raid_atomic64_inc_return(raid_atomic64 *a) +{ + return raid_atomic64_add_return(1, a); +} + +static inline uint64_t +raid_atomic64_dec_return(raid_atomic64 *a) +{ + return raid_atomic64_sub_return(1, a); +} + +static inline uint64_t +raid_atomic64_cmpxchg(raid_atomic64 *a, uint64_t old_val, uint64_t new_val) +{ + return atomic_cmpxchg(a, old_val, new_val); +} + +static inline void +raid_atomic64_set_bit(raid_atomic64 *atomic_ptr, uint64_t shift_size) +{ + uint64_t old_val; + uint64_t new_val; + do + { + old_val = raid_atomic64_read(atomic_ptr); + new_val = old_val; + SPDK_SET_BIT(&new_val, shift_size); + } while (raid_atomic64_cmpxchg(atomic_ptr, old_val, new_val)); +} + +static inline void +raid_atomic64_remove_bit(raid_atomic64 *atomic_ptr, uint64_t shift_size) +{ + uint64_t old_val; + uint64_t new_val; + do + { + old_val = raid_atomic64_read(atomic_ptr); + new_val = old_val; + SPDK_REMOVE_BIT(&new_val, shift_size); + } while (raid_atomic64_cmpxchg(atomic_ptr, old_val, new_val)); +} + +#endif /* SPDK_ATOMIC_RAID_INTERNAL_H */ \ No newline at end of file From 82f4eab30ca553176980ab85c59e4657327b3c80 Mon Sep 17 00:00:00 2001 From: ItIsMrLaG Date: Sun, 26 Nov 2023 16:23:57 +0000 Subject: [PATCH 17/24] bdev/raid: Implement common functionality for the data rebuild process --- module/bdev/raid/Makefile | 32 +- module/bdev/raid/bdev_raid.c | 19 +- module/bdev/raid/bdev_raid.h | 43 ++- module/bdev/raid/raid1.c | 32 +- module/bdev/raid/service.c | 561 +++++++++++++++++++++++++++++++++++ module/bdev/raid/service.h | 137 +++++++++ 6 files changed, 807 insertions(+), 17 deletions(-) create mode 100644 module/bdev/raid/service.c create mode 100644 module/bdev/raid/service.h diff --git a/module/bdev/raid/Makefile b/module/bdev/raid/Makefile index 17ad7f41938..f583d514bdd 100644 --- a/module/bdev/raid/Makefile +++ b/module/bdev/raid/Makefile @@ -6,11 +6,14 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../..) include $(SPDK_ROOT_DIR)/mk/spdk.common.mk -SO_VER := 5 +SO_VER := 6 SO_MINOR := 0 - -CFLAGS += -I$(SPDK_ROOT_DIR)/lib/bdev/ -C_SRCS = bdev_raid.c bdev_raid_rpc.c raid0.c raid1.c concat.c +# -> +# CFLAGS += $(ENV_CFLAGS) +# <- +CFLAGS += -I$(SPDK_ROOT_DIR)/lib/bdev/ +# -I$(SPDK_ROOT_DIR)/lib/env_dpdk/ +C_SRCS = service.c bdev_raid.c bdev_raid_rpc.c raid0.c raid1.c concat.c ifeq ($(CONFIG_RAID5F),y) C_SRCS += raid5f.c @@ -21,3 +24,24 @@ LIBNAME = bdev_raid SPDK_MAP_FILE = $(SPDK_ROOT_DIR)/mk/spdk_blank.map include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk + +# -> +# LIBDPDK_PKGCONFIG = $(call pkgconfig_filename,spdk_dpdklibs) + +# $(LIBDPDK_PKGCONFIG): $(PKGCONFIG) $(PKGCONFIG_INST) +# $(Q)$(SPDK_ROOT_DIR)/scripts/pc_libs.sh \ +# "-L$(DPDK_LIB_DIR) $(DPDK_LIB_LIST:%=-l%)" "" DPDK spdk_dpdklibs > $@ +# $(Q)sed -i.bak '5s,.*,Requires: $(DEPDIRS-$(LIBNAME):%=spdk_%) spdk_dpdklibs,' $(PKGCONFIG) ; rm $(PKGCONFIG).bak +# $(Q)sed -i.bak '5s,.*,Requires: $(DEPDIRS-$(LIBNAME):%=spdk_%) spdk_dpdklibs,' $(PKGCONFIG_INST) ; rm $(PKGCONFIG_INST).bak + +# _install_dpdklibs: $(LIBDPDK_PKGCONFIG) +# @$(call pkgconfig_install,$(LIBDPDK_PKGCONFIG)) + +# _uninstall_dpdklibs: $(LIBDPDK_PKGCONFIG) +# @$(call pkgconfig_uninstall,$(LIBDPDK_PKGCONFIG)) + +# all: $(LIBDPDK_PKGCONFIG) +# install: _install_dpdklibs +# uninstall: _uninstall_dpdklibs +# <- + diff --git a/module/bdev/raid/bdev_raid.c b/module/bdev/raid/bdev_raid.c index c699b8a4953..b150d19fe98 100644 --- a/module/bdev/raid/bdev_raid.c +++ b/module/bdev/raid/bdev_raid.c @@ -5,6 +5,7 @@ */ #include "bdev_raid.h" +#include "service.h" #include "spdk/env.h" #include "spdk/thread.h" #include "spdk/log.h" @@ -185,6 +186,7 @@ raid_bdev_cleanup(struct raid_bdev *raid_bdev) TAILQ_REMOVE(&g_raid_bdev_list, raid_bdev, global_link); free(raid_bdev->base_bdev_info); + spdk_poller_unregister(&(raid_bdev->rebuild_poller)); } static void @@ -1005,12 +1007,19 @@ raid_bdev_create(const char *name, uint32_t strip_size, uint8_t num_base_bdevs, } /* allocate rebuild struct */ - raid_bdev->rebuild = calloc(1, sizeof(struct raid_rebuild)); - if (!raid_bdev->rebuild) { - SPDK_ERRLOG("Unable to allocate memory for raid rebuild struct\n"); - return -ENOMEM; + switch(level) { + case RAID1: + raid_bdev->rebuild = calloc(1, sizeof(struct raid_rebuild)); + if (!raid_bdev->rebuild) { + SPDK_ERRLOG("Unable to allocate memory for raid rebuild struct\n"); + return -ENOMEM; + } + raid_bdev->rebuild_poller = SPDK_POLLER_REGISTER(run_rebuild_poller, raid_bdev, 2000); + break; + default: + raid_bdev->rebuild = NULL; + raid_bdev->rebuild_poller = NULL; } - raid_bdev->module = module; raid_bdev->num_base_bdevs = num_base_bdevs; raid_bdev->base_bdev_info = calloc(raid_bdev->num_base_bdevs, diff --git a/module/bdev/raid/bdev_raid.h b/module/bdev/raid/bdev_raid.h index 1617be2bc4d..670cd14c04a 100644 --- a/module/bdev/raid/bdev_raid.h +++ b/module/bdev/raid/bdev_raid.h @@ -6,17 +6,35 @@ #ifndef SPDK_BDEV_RAID_INTERNAL_H #define SPDK_BDEV_RAID_INTERNAL_H -#define MATRIX_REBUILD_SIZE 32768 /* 2^15 */ - #include "spdk/bdev_module.h" #include "spdk/uuid.h" +#define MATRIX_REBUILD_SIZE 32768 /* should be < syzeof(int64_t) and power of 2 */ +#define ATOMIC_TYPE uint64_t +#define ATOMIC_DATA(name) ATOMIC_TYPE name +#define ATOMIC_SNAPSHOT_TYPE uint64_t /* atomic type can be converted to the type */ +#define ATOMIC_SNAPSHOT(name) ATOMIC_SNAPSHOT_TYPE name +#define LEN_AREA_STR_IN_BIT sizeof(ATOMIC_SNAPSHOT_TYPE)*8 + +#define BASE_BDEVS_MAX_NUM 64 + +// #include "service.h" + enum rebuild_flag { /* rebuild flag set during initialization */ REBUILD_FLAG_INIT_CONFIGURATION = 0, /* if there is at least one broken area in rbm(rebuild_matrix) */ - REBUILD_FLAG_NEED_REBUILD = 1, + REBUILD_FLAG_NEED_REBUILD = 1, //TODO: можно переписать как счетчик областей, которые надо проребилдить (мб поможет при атомарном снятии флага) + у Юли инкремент такого щетчика должен быть до выставления единичек + + /* if service start rebuild cycle */ + REBUILD_FLAG_IN_PROGRESS = 2, + + /* fatal error during rebuild cycle */ + REBUILD_FLAG_FATAL_ERROR = 59, + + /* show that rebuild struct is initialized */ + REBUILD_FLAG_INITIALIZED = 60, }; enum raid_level { @@ -58,7 +76,7 @@ typedef void (*raid_bdev_remove_base_bdev_cb)(void *ctx, int status); */ struct raid_rebuild { /* stores data on broken memory areas */ - uint64_t rebuild_matrix[MATRIX_REBUILD_SIZE]; + ATOMIC_DATA(rebuild_matrix[MATRIX_REBUILD_SIZE]); /* number of memory areas */ uint64_t num_memory_areas; @@ -67,7 +85,13 @@ struct raid_rebuild { uint64_t strips_per_area; /* rebuild flag */ - uint64_t rebuild_flag; + ATOMIC_DATA(rebuild_flag); //TODO: переписать на атомики + + /* + * structure describing a specific rebuild + * (i.e. when cycle_progress == NULL, REBUILD_FLAG_IN_PROGRESS is omitted) + */ + struct rebuild_progress *cycle_progress; }; /* @@ -173,6 +197,9 @@ struct raid_bdev { /* RAID rebuild struct */ struct raid_rebuild *rebuild; + /* Poller responsible for processing rebuild */ + struct spdk_poller *rebuild_poller; + /* Set to true if destroy of this raid bdev is started. */ bool destroy_started; @@ -285,6 +312,12 @@ struct raid_bdev_module { */ void (*resize)(struct raid_bdev *raid_bdev); + /* + * Called to submit rebuild request + * If implemented. + */ + int (*rebuild_request)(struct raid_bdev *raid_bdev, struct rebuild_progress *cycle_progress, spdk_bdev_io_completion_cb cb); + TAILQ_ENTRY(raid_bdev_module) link; }; diff --git a/module/bdev/raid/raid1.c b/module/bdev/raid/raid1.c index 4fb08cfbc4e..17f9703326a 100644 --- a/module/bdev/raid/raid1.c +++ b/module/bdev/raid/raid1.c @@ -3,6 +3,7 @@ * All rights reserved. */ #include "bdev_raid.h" +#include "service.h" #include "spdk/likely.h" #include "spdk/log.h" @@ -89,12 +90,13 @@ raid1_bdev_io_completion(struct spdk_bdev_io *bdev_io, bool success, void *cb_ar get_current_bdev_idx(bdev_io, raid_io, &bdev_idx); - spdk_bdev_free_io(bdev_io); if (!success) { write_in_rbm_broken_block(bdev_io, raid_io, bdev_idx); } + spdk_bdev_free_io(bdev_io); + raid_bdev_io_complete_part(raid_io, 1, success ? SPDK_BDEV_IO_STATUS_SUCCESS : SPDK_BDEV_IO_STATUS_FAILED); @@ -259,10 +261,11 @@ raid1_submit_rw_request(struct raid_bdev_io *raid_io) static void init_rebuild(struct raid_bdev *raid_bdev) { - raid_bdev->rebuild->num_memory_areas = MATRIX_REBUILD_SIZE; uint64_t stripcnt = SPDK_CEIL_DIV(raid_bdev->bdev.blockcnt, raid_bdev->strip_size); raid_bdev->rebuild->strips_per_area = SPDK_CEIL_DIV(stripcnt, MATRIX_REBUILD_SIZE); + raid_bdev->rebuild->num_memory_areas = stripcnt / raid_bdev->rebuild->strips_per_area; raid_bdev->rebuild->rebuild_flag = REBUILD_FLAG_INIT_CONFIGURATION; + SPDK_SET_BIT(&(raid_bdev->rebuild->rebuild_flag), REBUILD_FLAG_INITIALIZED); } static void @@ -314,14 +317,37 @@ raid1_stop(struct raid_bdev *raid_bdev) return true; } +static int +raid1_submit_rebuild_request(struct raid_bdev *raid_bdev, struct rebuild_progress *cycle_progress, spdk_bdev_io_completion_cb cb) +{ + struct raid_rebuild *rebuild = raid_bdev->rebuild; + + /* area size in strips */ + uint64_t area_size = rebuild->strips_per_area; + /* strip size in blocks */ + uint32_t strip_size = raid_bdev->strip_size; + /* block size in bytes */ + uint32_t block_size = spdk_bdev_get_block_size(&(raid_bdev->bdev)); + + struct iteration_step *cb_arg = NULL; + + + + + //TODO: Реализовать вот это. + + return 0; +} + static struct raid_bdev_module g_raid1_module = { .level = RAID1, .base_bdevs_min = 2, .base_bdevs_constraint = {CONSTRAINT_MIN_BASE_BDEVS_OPERATIONAL, 1}, - .memory_domains_supported = true, + .memory_domains_supported = true, //false? .start = raid1_start, .stop = raid1_stop, .submit_rw_request = raid1_submit_rw_request, + .rebuild_request = raid1_submit_rebuild_request, }; RAID_MODULE_REGISTER(&g_raid1_module) diff --git a/module/bdev/raid/service.c b/module/bdev/raid/service.c new file mode 100644 index 00000000000..8d07ce9b449 --- /dev/null +++ b/module/bdev/raid/service.c @@ -0,0 +1,561 @@ + /* SPDX-License-Identifier: BSD-3-Clause + * Copyright (C) 2018 Intel Corporation. + * All rights reserved. + */ + +#include "spdk/env.h" +#include "spdk/bdev.h" +#include "spdk/likely.h" +#include "spdk/log.h" +#include "spdk/util.h" +#include "spdk/queue.h" + +#include "bdev_raid.h" +#include "service.h" + +#define DEBUG__ + +/* ============================ TESTS ==================================== */ + +// TODO: Сейчас iovcnt = 1, доделать, чтоб можно было создавать любого количества +#define _MUX_BUF_LENGTH 1 +// ----- // + +/* ======================= Poller functionality =========================== */ + +/* + * The function shold be run after rebuilding of concrete area from iteration + */ +static inline void +partly_submit_iteration(bool result ,uint64_t iter_idx, uint16_t area_idx, struct raid_rebuild *rebuild) +{ + struct rebuild_cycle_iteration *iter = &(rebuild->cycle_progress->cycle_iteration); + + if(result) + { + SPDK_REMOVE_BIT(&(rebuild->rebuild_matrix[iter_idx]), area_idx); + } + + ATOMIC_INCREMENT(&(iter->pr_area_cnt)); +} + +static inline void +_free_sg_buffer_part(struct iovec *vec_array, uint64_t len) +{ //TODO: проверить, что оно работает (в for совсем неуверен) + struct iovec *base_vec; + //TODO: мб вообще не надо. + + for(base_vec = vec_array; base_vec < vec_array + len; base_vec++) + { + spdk_dma_free(base_vec->iov_base); + } +} + +static inline void +free_sg_buffer(struct iovec *vec_array, uint64_t len) +{ + /* usage: struct iovec *a; free_sg_buffer(&a, b); */ + if(len != 0) + { + _free_sg_buffer_part(vec_array, len); + } + free(vec_array); +} + +uint64_t +get_area_offset(size_t area_idx, size_t area_size, size_t strip_size) +{ + return area_idx*area_size*strip_size; +} + +uint64_t +get_area_size(size_t area_size, size_t strip_size) +{ + return area_size*strip_size; +} + +static inline struct iovec * +allocate_sg_buffer(size_t elem_size, size_t elemcnt, size_t align) +{ + struct iovec *vec_array = calloc(elemcnt, sizeof(struct iovec)); + if(vec_array == NULL) + { + return NULL; + } + + for (size_t i = 0; i < elemcnt; i++) + { //TODO: люблю лажать с индексами, проверить, что все ок + vec_array[i].iov_len = elem_size; + vec_array[i].iov_base = (void*)spdk_dma_zmalloc(sizeof(uint8_t)*vec_array[i].iov_len, align, NULL); + if(vec_array[i].iov_base == NULL) + { + _free_sg_buffer_part(vec_array, i); + free(vec_array); + return NULL; + } + } + return vec_array; +} + +void +reset_buffer(struct iovec *vec_array, uint32_t len) +{ + struct iovec *base_vec; + if(len == 0) return; + + for(base_vec = vec_array; base_vec < vec_array + len; base_vec++) + { + memset(base_vec->iov_base, 0, base_vec->iov_len); + } +} + +static inline void +_free_base_bdevs_buff(struct raid_bdev *raid_bdev, struct rebuild_progress *cycle_progress, uint8_t arr_num) +{ + for (uint8_t i = 0; i < arr_num; i++) + { + free_sg_buffer(cycle_progress->base_bdevs_sg_buf[i], raid_bdev->rebuild->strips_per_area); + cycle_progress->base_bdevs_sg_buf[i] = NULL; + } +} + +static inline void +free_base_bdevs_buff(struct raid_bdev *raid_bdev, struct rebuild_progress *cycle_progress) +{ + _free_base_bdevs_buff(raid_bdev, cycle_progress, raid_bdev->num_base_bdevs); +} + +static inline int +alloc_base_bdevs_buff(struct raid_bdev *raid_bdev, struct rebuild_progress *cycle_progress) +{ + uint64_t elem_size = spdk_bdev_get_block_size(&(raid_bdev->bdev))*raid_bdev->strip_size; + uint8_t i = 0; + struct raid_base_bdev_info *base_info; + + RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) + { + struct spdk_bdev *bbdev = spdk_bdev_desc_get_bdev(base_info->desc); + if(spdk_bdev_get_write_unit_size(bbdev) != 1) + { + SPDK_WARNLOG("Unsupported write_unit_size in base bdev of raid"); + } + + cycle_progress->base_bdevs_sg_buf[i] = allocate_sg_buffer(elem_size, raid_bdev->rebuild->strips_per_area, bbdev->required_alignment); + if (cycle_progress->base_bdevs_sg_buf[i] == NULL) + { + _free_base_bdevs_buff(raid_bdev, cycle_progress, i); + return -ENOMEM; + } + } + return 0; +} + +static inline uint16_t +count_broken_areas(ATOMIC_SNAPSHOT_TYPE area_str) +{ + uint16_t cnt = 0; + + for (uint16_t i = 0; i < LEN_AREA_STR_IN_BIT; i++) + { + if(SPDK_TEST_BIT(&area_str, i)) cnt += 1; + } + + return cnt; +} + +static inline int64_t +init_rebuild_cycle(struct rebuild_progress *cycle_progress, struct raid_bdev *raid_bdev) +{ + int64_t start_idx = NOT_NEED_REBUILD; + struct raid_rebuild *rebuild = raid_bdev->rebuild; + + cycle_progress->clear_area_str_cnt = 0; + cycle_progress->area_str_cnt = 0; + + for (uint64_t i = 0; i < rebuild->num_memory_areas ; i++) + { + if (ATOMIC_IS_AREA_STR_CLEAR(rebuild->rebuild_matrix[i])) continue; + + if(start_idx == NOT_NEED_REBUILD) + { + start_idx = i; + } + + SPDK_SET_BIT(&(cycle_progress->area_proection[b_GET_IDX_BP(i)]), b_GET_SHFT_BP(i)); + + cycle_progress->area_str_cnt += 1; + } + + if (start_idx != NOT_NEED_REBUILD) + { + raid_bdev->rebuild->cycle_progress = cycle_progress; + } else { + raid_bdev->rebuild->cycle_progress = NULL; + } + + return start_idx; +} + +static inline int64_t +get_iter_idx(int64_t prev_idx, struct raid_bdev *raid_bdev) +{ + struct rebuild_progress *cycle_progress = raid_bdev->rebuild->cycle_progress; + + for (int64_t i = prev_idx + 1; i < (int64_t)raid_bdev->rebuild->num_memory_areas; i++) + { + if (!SPDK_TEST_BIT(&(cycle_progress->area_proection[b_GET_IDX_BP(i)]), b_GET_SHFT_BP(i))) continue; + return i; + } + return NOT_NEED_REBUILD; +} + +static inline void +finish_rebuild_cycle(struct raid_bdev *raid_bdev) +{ + struct raid_rebuild *rebuild = raid_bdev->rebuild; + + if (rebuild == NULL) + { + return; + } + free_base_bdevs_buff(raid_bdev, rebuild->cycle_progress); + free(rebuild->cycle_progress); + rebuild->cycle_progress = NULL; + SPDK_REMOVE_BIT(fl(rebuild), REBUILD_FLAG_IN_PROGRESS); +} + +static inline void +init_cycle_iteration(struct raid_rebuild *rebuild, int64_t curr_idx) +{ + struct rebuild_cycle_iteration *cycle_iter = &(rebuild->cycle_progress->cycle_iteration); + + cycle_iter->iter_idx = curr_idx; + cycle_iter->complete = false; + cycle_iter->snapshot = CREATE_AREA_STR_SNAPSHOT(&(rebuild->rebuild_matrix[curr_idx])); + cycle_iter->br_area_cnt = count_broken_areas(cycle_iter->snapshot); + cycle_iter->pr_area_cnt = 0; + cycle_iter->iter_progress = cycle_iter->snapshot; +} + +void init_cb_arg(struct iteration_step *iter_info, int64_t iter_idx, int16_t area_idx, struct rebuild_cycle_iteration *iteration, struct raid_bdev *raid_bdev) +{ + iter_info->area_idx = area_idx; + iter_info->iter_idx = iter_idx; + iter_info->iteration = iteration; + iter_info->raid_bdev = raid_bdev; +} + +struct iteration_step * +alloc_cb_arg(int64_t iter_idx, int16_t area_idx, struct rebuild_cycle_iteration *iteration, struct raid_bdev *raid_bdev) +{ + struct iteration_step *iter_info = calloc(1, sizeof(struct iteration_step)); + if (iter_info == NULL) + { + return NULL; + } + init_cb_arg(iter_info, iter_idx, area_idx, iteration, raid_bdev); + return iter_info; +} + +void +free_cd_arg(struct iteration_step *cb) +{ + if(cb == NULL) + { + return; + } + free(cb); +} + +/* + * Callback function. + */ +void +continue_rebuild(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) +{ + int64_t iter_idx = ((struct iteration_step *)cb_arg)->iter_idx; + int16_t area_idx = ((struct iteration_step *)cb_arg)->area_idx; + struct rebuild_cycle_iteration *iteration = ((struct iteration_step *)cb_arg)->iteration; + struct raid_bdev *raid_bdev = ((struct iteration_step *)cb_arg)->raid_bdev; + struct rebuild_progress *cycle_progress = raid_bdev->rebuild->cycle_progress; + int64_t next_iter_idx; + int ret = 0; + + free_cd_arg(cb_arg); + spdk_bdev_free_io(bdev_io); + partly_submit_iteration(success, iter_idx, area_idx, raid_bdev->rebuild); + + /* Test whether the end of the iteration or not */ + if(!ATOMIC_EXCHANGE(&(iteration->pr_area_cnt), iteration->br_area_cnt, 0)) + { + return; + } + + ++cycle_progress->clear_area_str_cnt; + + /* Wether it is the last iteration or not */ + if(cycle_progress->clear_area_str_cnt == cycle_progress->area_str_cnt) + { //TODO: if clear_area_str_cnt - atomic => problem + finish_rebuild_cycle(raid_bdev); + return; + } + + next_iter_idx = get_iter_idx(iter_idx, raid_bdev); + init_cycle_iteration(raid_bdev->rebuild, next_iter_idx); + + ret = raid_bdev->module->rebuild_request(raid_bdev, cycle_progress, continue_rebuild); + + if(spdk_unlikely(ret != 0)) + { + SPDK_SET_BIT(&(raid_bdev->rebuild->rebuild_flag), REBUILD_FLAG_FATAL_ERROR); + } +} + +int +run_rebuild_poller(void* arg) +{ //TODO: в целом реализация наивная (без учета многопоточности) - не очень пока понимаю, как ее прикрутить. + struct raid_bdev *raid_bdev = arg; + struct raid_rebuild *rebuild = raid_bdev->rebuild; + struct rebuild_progress *cycle_progress = NULL; + int ret = 0; + +#ifdef DEBUG__ + SPDK_WARNLOG("poller is working now with: %s!\n", raid_bdev->bdev.name); +#endif + + if (rebuild == NULL) + { + SPDK_WARNLOG("%s doesn't have rebuild struct!\n", raid_bdev->bdev.name); + return -ENODEV; + } + if (!SPDK_TEST_BIT(fl(rebuild), REBUILD_FLAG_INITIALIZED)) + { + /* + * the rebuild structure has not yet been initialized + */ + return 0; + } + if (SPDK_TEST_BIT(&(rebuild->rebuild_flag), REBUILD_FLAG_FATAL_ERROR)) + { + SPDK_WARNLOG("%s catch fatal error during rebuild process!\n", raid_bdev->bdev.name); + return -ENOEXEC; + } + if (SPDK_TEST_BIT(fl(rebuild), REBUILD_FLAG_IN_PROGRESS)) + { + /* + * Previous recovery process is not complete + */ + return 0; + } + + cycle_progress = calloc(1, sizeof(struct rebuild_progress)); + + if (cycle_progress == NULL) + { + SPDK_ERRLOG("the struct rebuild_progress wasn't allocated \n"); + return -ENOMEM; + } + + /* + * Representation of area-stripe index in the area_proection + * (from which the rebuild cycle will begin) + */ + int64_t start_idx = NOT_NEED_REBUILD; + + start_idx = init_rebuild_cycle(cycle_progress, raid_bdev); + + if(start_idx == NOT_NEED_REBUILD) + { + /* + * no need rebuild + */ + free(cycle_progress); + return ret; + } + + if (raid_bdev->module->rebuild_request != NULL) + { + SPDK_SET_BIT(fl(rebuild), REBUILD_FLAG_IN_PROGRESS); + + init_cycle_iteration(rebuild, start_idx); + + if(alloc_base_bdevs_buff(raid_bdev, cycle_progress) != 0) + { + return -ENOMEM; + } + + ret = raid_bdev->module->rebuild_request(raid_bdev, cycle_progress, continue_rebuild); + switch (ret) + { + case -ENOMEM: + case -EIO: + finish_rebuild_cycle(raid_bdev); + break; + } + } else { + SPDK_ERRLOG("rebuild_request inside raid%d doesn't implemented\n", raid_bdev->level); + return -ENODEV; + } + return ret; +} + +// ===============================TESTs=========================================== // +// TODO: мб не надо, переделать. +// struct container { +// struct raid_bdev *raid_bdev; +// int idx; +// struct iovec * buff; +// } typedef container; + + +// static inline struct iovec * +// alloc_continuous_buffer_part(size_t iovlen, size_t align) +// { +// struct iovec *buf; +// buf = spdk_dma_zmalloc(sizeof(struct iovec), 0, NULL); +// if(buf == NULL) +// { +// return NULL; +// } + +// buf->iov_len = iovlen; +// buf->iov_base = spdk_dma_zmalloc(sizeof(uint8_t)*(buf->iov_len), 0, NULL); +// if(buf->iov_base == NULL) +// { +// spdk_dma_free(buf); +// return NULL; +// } + +// return buf; +// } + +// static inline void +// free_continuous_buffer_part(struct iovec * buf_elem) +// { +// spdk_dma_free(buf_elem->iov_base); +// spdk_dma_free(buf_elem); +// } + + +// static inline int +// fill_ones_write_request(struct iovec * buf_array, int buf_len) +// { +// // не учитывает align внутри iov_base +// SPDK_WARNLOG("i'm here 2 \n"); + +// if(buf_len > _MUX_BUF_LENGTH) +// { +// return -1; +// } +// for(size_t i = 0; ibuff->iov_base)); +// } else { +// SPDK_ERRLOG("test (read) fail\n"); +// } + +// free_continuous_buffer_part(cont->buff); +// spdk_bdev_free_io(bdev_io); +// free(cont); +// SPDK_WARNLOG("test (read) success\n"); +// } + +// void +// cd_write_func(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) +// { +// container *cont = cb_arg; +// if(success) +// { +// SPDK_WARNLOG("test (write) success\n"); +// } else { +// SPDK_ERRLOG("test (write) fail\n"); +// } + +// free_continuous_buffer_part(cont->buff); +// spdk_bdev_free_io(bdev_io); +// submit_read_request_base_bdev(cont->raid_bdev, cont->idx); +// free(cont); +// } + +// void +// submit_write_request_base_bdev(struct raid_bdev *raid_bdev, uint8_t idx) +// { +// struct spdk_bdev_desc *desc = __base_desc_from_raid_bdev(raid_bdev, idx); +// struct spdk_bdev *base_bdev = spdk_bdev_desc_get_bdev(desc); +// struct spdk_io_channel *ch = spdk_bdev_get_io_channel(desc); +// struct iovec *buffer; +// container *cont; +// int ret; + + +// buffer = alloc_continuous_buffer_part(base_bdev->blocklen, base_bdev->required_alignment); +// if (fill_ones_write_request(buffer, 1) != 0) +// { +// SPDK_ERRLOG("fill_ones_write_request was fail\n"); +// } +// cont = calloc(1, sizeof(container)); +// if (cont == NULL){ +// SPDK_ERRLOG("cont alloc failed\n"); +// } + +// cont->buff = buffer; +// cont->idx = 0; +// cont->raid_bdev = raid_bdev; +// ret = spdk_bdev_writev_blocks (desc, ch, buffer, 1, 0, 1, cd_write_func, cont); + +// if(spdk_likely(ret == 0)) +// { +// SPDK_WARNLOG("submit test (write) success\n"); +// } else { +// SPDK_ERRLOG("submit test (write) fail\n"); +// } +// } + +// void +// submit_read_request_base_bdev(struct raid_bdev *raid_bdev, uint8_t idx) +// { +// struct spdk_bdev_desc *desc = __base_desc_from_raid_bdev(raid_bdev, idx); +// struct spdk_bdev *base_bdev = spdk_bdev_desc_get_bdev(desc); +// struct spdk_io_channel *ch = spdk_bdev_get_io_channel(desc); +// struct iovec *buffer; +// container *cont; +// int ret; + +// buffer = alloc_continuous_buffer_part(base_bdev->blocklen, base_bdev->required_alignment); + +// cont = calloc(1, sizeof(container)); +// if (cont == NULL){ +// SPDK_ERRLOG("cont alloc failed\n"); +// } + +// cont->buff = buffer; +// cont->idx = 0; +// cont->raid_bdev = raid_bdev; +// ret = spdk_bdev_readv_blocks(desc, ch, buffer, 1, 0, 1, cd_read_func, cont); + +// if(spdk_likely(ret == 0)) +// { +// SPDK_WARNLOG("submit test (read) success\n"); +// } else { +// SPDK_ERRLOG("submit test (read) fail\n"); +// } +// } +/* ======================================================================== */ \ No newline at end of file diff --git a/module/bdev/raid/service.h b/module/bdev/raid/service.h new file mode 100644 index 00000000000..4ef91efe99e --- /dev/null +++ b/module/bdev/raid/service.h @@ -0,0 +1,137 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (C) 2018 Intel Corporation. + * All rights reserved. + */ + +#ifndef SPDK_RAID_SERVICE_INTERNAL_H +#define SPDK_RAID_SERVICE_INTERNAL_H + +#include "spdk/queue.h" +#include "bdev_raid.h" + +//-> +#define __base_desc_from_raid_bdev(raid_bdev, idx) (raid_bdev->base_bdev_info[idx].desc) +#define fl(rebuild) &(rebuild->rebuild_flag) +#define NOT_NEED_REBUILD -1 +//-> +//TODO: Надо проверить, что побитовые макросы с указателями нормально работают, а то я вообще хз, мб тут ошибка +#define ATOMIC_IS_AREA_STR_CLEAR(area_srt) (area_srt) +#define CREATE_AREA_STR_SNAPSHOT(area_srt_ptr) (*area_srt_ptr) +#define ATOMIC_INCREMENT(ptr) ((*ptr)++) +#define ATOMIC_DECREMENT(ptr) ((*ptr)--) +#define ATOMIC_EXCHANGE(dest_ptr, exc, src) (TEST_CAS(dest_ptr, exc, src)) +// -> +// TODO: индексы у битов идут справа на лево!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! (все норм?) +#define b_BASE_TYPE uint64_t +#define b_BIT_PROECTION(name) b_BASE_TYPE name[SPDK_CEIL_DIV(MATRIX_REBUILD_SIZE, (sizeof(b_BASE_TYPE)*8))] +#define b_GET_IDX_BP(x) (x / (sizeof(b_BASE_TYPE)*8)) +#define b_GET_SHFT_BP(x) (x % (sizeof(b_BASE_TYPE)*8)) +// + +static inline bool +TEST_CAS(ATOMIC_TYPE *ptr, ATOMIC_SNAPSHOT_TYPE exc, ATOMIC_SNAPSHOT_TYPE src) +{ + if (*ptr == exc){ + *ptr = src; + return true; + } + return false; +} + +struct iteration_step +{ + int16_t area_idx; + int64_t iter_idx; + struct rebuild_cycle_iteration *iteration; + struct raid_bdev *raid_bdev; + spdk_bdev_io_completion_cb cb; +}; + + +struct rebuild_cycle_iteration +{ + /* true if one part of the rebuild cycle is completed */ + bool complete; + + /* number of broken areas in current area stripe */ + int16_t br_area_cnt; + + /* index of the area stripe for rebuld */ + int64_t iter_idx; + + /* processed areas counter, it increments after completion rebuild a concrete area */ + ATOMIC_DATA(pr_area_cnt); + + /* snapshot of area stripe from rebuild matrix (non atomic) */ + ATOMIC_SNAPSHOT(snapshot); + + /* + * metadata for current iteration, + * describing which areas should still be started for rebuild + * (equals snapshot at initialization stage) + * (10..010 |-[start rebuild area with index 1]-> 10..000) + */ + ATOMIC_SNAPSHOT(iter_progress); +}; + + +struct rebuild_progress { + /* + * bit proection of rebuild matrix, + * where each bit corresponds one line(area stripe) in rebuild matrix + * (if the line contains broken areas, corresponding bit equels 1 othewise 0) + */ + b_BIT_PROECTION(area_proection); + + /* number of areas stripes with broken areas */ + uint64_t area_str_cnt; + + /* number of area stripes with processed areas (tried to rebuild all the broken areas) */ + uint64_t clear_area_str_cnt; //TODO: думаю, что не должно быть атомиком, потому что измеяется последовательно + + /* + * To avoid memory overloading, only one area stripe (in need of rebuild) + * can be processed at a time. + * The fild describes the rebuild of this area stripe. + */ + struct rebuild_cycle_iteration cycle_iteration; + + /* + * Buffers for raid base_bdevs. + * Each element - SG-buffer (array of iovec); + * Size of each SG-buffer is size of one memory area in bytes; + * One element from SG-buffer describes buffer size equals size of one strip in bytes. + */ + struct iovec* base_bdevs_sg_buf[BASE_BDEVS_MAX_NUM]; +}; + + +int +run_rebuild_poller(void* arg); + +void +continue_rebuild(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg); + +struct iteration_step * +alloc_cb_arg(int64_t iter_idx, int16_t area_idx, struct rebuild_cycle_iteration *iteration, struct raid_bdev *raid_bdev); + +void +init_cb_arg(struct iteration_step *iter_info, + int64_t iter_idx, + int16_t area_idx, + struct rebuild_cycle_iteration *iteration, + struct raid_bdev *raid_bdev); + +void +free_cd_arg(struct iteration_step *cb); + +void +reset_buffer(struct iovec *vec_array, uint32_t len); + +uint64_t +get_area_offset(size_t area_idx, size_t area_size, size_t strip_size); + +uint64_t +get_area_size(size_t area_size, size_t strip_size); + +#endif /* SPDK_RAID_SERVICE_INTERNAL_H */ \ No newline at end of file From 76119af13d2ff3b8a0bb6897d287ab0ffaa0d98c Mon Sep 17 00:00:00 2001 From: ItIsMrLaG Date: Sat, 9 Dec 2023 14:06:20 +0000 Subject: [PATCH 18/24] bdev/raid: Implement a rebuild process for RAID1 --- module/bdev/raid/bdev_raid.h | 12 +- module/bdev/raid/raid1.c | 113 ++++++++++++++++-- module/bdev/raid/service.c | 196 +++---------------------------- module/bdev/raid/service.h | 20 ++-- test/unit/lib/bdev/raid/Makefile | 3 +- 5 files changed, 136 insertions(+), 208 deletions(-) diff --git a/module/bdev/raid/bdev_raid.h b/module/bdev/raid/bdev_raid.h index 670cd14c04a..377ac447ddb 100644 --- a/module/bdev/raid/bdev_raid.h +++ b/module/bdev/raid/bdev_raid.h @@ -8,9 +8,10 @@ #include "spdk/bdev_module.h" #include "spdk/uuid.h" +#include "atomic_raid.h" #define MATRIX_REBUILD_SIZE 32768 /* should be < syzeof(int64_t) and power of 2 */ -#define ATOMIC_TYPE uint64_t +#define ATOMIC_TYPE raid_atomic64 #define ATOMIC_DATA(name) ATOMIC_TYPE name #define ATOMIC_SNAPSHOT_TYPE uint64_t /* atomic type can be converted to the type */ #define ATOMIC_SNAPSHOT(name) ATOMIC_SNAPSHOT_TYPE name @@ -25,11 +26,14 @@ enum rebuild_flag { REBUILD_FLAG_INIT_CONFIGURATION = 0, /* if there is at least one broken area in rbm(rebuild_matrix) */ - REBUILD_FLAG_NEED_REBUILD = 1, //TODO: можно переписать как счетчик областей, которые надо проребилдить (мб поможет при атомарном снятии флага) + у Юли инкремент такого щетчика должен быть до выставления единичек + REBUILD_FLAG_NEED_REBUILD = 1, /* if service start rebuild cycle */ REBUILD_FLAG_IN_PROGRESS = 2, + /* if service start rebuild cycle */ + REBUILD_FLAG_FINISH = 3, + /* fatal error during rebuild cycle */ REBUILD_FLAG_FATAL_ERROR = 59, @@ -85,11 +89,11 @@ struct raid_rebuild { uint64_t strips_per_area; /* rebuild flag */ - ATOMIC_DATA(rebuild_flag); //TODO: переписать на атомики + ATOMIC_DATA(rebuild_flag); /* * structure describing a specific rebuild - * (i.e. when cycle_progress == NULL, REBUILD_FLAG_IN_PROGRESS is omitted) + * (i.e. when cycle_progress == NULL) */ struct rebuild_progress *cycle_progress; }; diff --git a/module/bdev/raid/raid1.c b/module/bdev/raid/raid1.c index 17f9703326a..cf5f0eca4de 100644 --- a/module/bdev/raid/raid1.c +++ b/module/bdev/raid/raid1.c @@ -14,6 +14,17 @@ struct raid1_info { struct raid_bdev *raid_bdev; }; +struct rebuild_first_stage_cb +{ + uint8_t buf_idx; + uint64_t pd_lba; + uint64_t pd_blocks; + struct rebuild_progress *cycle_progress; + struct raid_bdev *raid_bdev; + spdk_bdev_io_completion_cb cb; +}; + + /* Find the bdev index of the current IO request */ static uint32_t get_current_bdev_idx(struct spdk_bdev_io *bdev_io, struct raid_bdev_io *raid_io, uint32_t *bdev_idx) @@ -317,26 +328,102 @@ raid1_stop(struct raid_bdev *raid_bdev) return true; } -static int -raid1_submit_rebuild_request(struct raid_bdev *raid_bdev, struct rebuild_progress *cycle_progress, spdk_bdev_io_completion_cb cb) +static +void raid1_submit_rebuild_second_stage(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) { - struct raid_rebuild *rebuild = raid_bdev->rebuild; + struct rebuild_first_stage_cb *info = cb_arg; + struct raid_bdev *raid_bdev = info->raid_bdev; + struct rebuild_cycle_iteration *cycle_iteration = &(raid_bdev->rebuild->cycle_progress->cycle_iteration); + struct raid_base_bdev_info *base_info; + struct spdk_bdev_desc *desc; /* __base_desc_from_raid_bdev(raid_bdev, idx); */ + struct spdk_io_channel *ch; /* spdk_bdev_get_io_channel(desc); */ + struct iteration_step *cb_arg_new = NULL; + uint8_t idx = 0; + int ret = 0; + + if (!success) + { + //TODO: Handle this case (mb add new flag FIRST_STAGE_ERROR) + return; + } + + RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) { + desc = base_info->desc; + ch = spdk_bdev_get_io_channel(desc); + if (!SPDK_TEST_BIT(&(cycle_iteration->br_area_cnt), idx)) { + idx++; + continue; + } + // TODO: ch == NULL -> + // if (spdk_unlikely(ret != 0)) { + // info->cb(NULL, false, cb_arg_new); + // } + cb_arg_new = alloc_cb_arg(cycle_iteration->iter_idx, idx, cycle_iteration, raid_bdev); + ret = spdk_bdev_writev_blocks(desc, ch, + raid_bdev->rebuild->cycle_progress->base_bdevs_sg_buf[info->buf_idx], + raid_bdev->rebuild->strips_per_area, + info->pd_lba, info->pd_blocks, + info->cb, cb_arg_new); - /* area size in strips */ - uint64_t area_size = rebuild->strips_per_area; - /* strip size in blocks */ - uint32_t strip_size = raid_bdev->strip_size; - /* block size in bytes */ - uint32_t block_size = spdk_bdev_get_block_size(&(raid_bdev->bdev)); + if (spdk_unlikely(ret != 0)) { + info->cb(NULL, false, cb_arg_new); + } + idx++; + } - struct iteration_step *cb_arg = NULL; + free(info); + spdk_bdev_free_io(bdev_io); +} +static int +raid1_submit_rebuild_request(struct raid_bdev *raid_bdev, struct rebuild_progress *cycle_progress, spdk_bdev_io_completion_cb cb) +{ + struct raid_rebuild *rebuild = raid_bdev->rebuild; + struct rebuild_cycle_iteration *cycle_iter = &(cycle_progress->cycle_iteration); + struct rebuild_first_stage_cb *cb_arg = calloc(1, sizeof(struct rebuild_first_stage_cb));; + uint8_t base_idx = 0; + int ret = 0; + struct spdk_bdev_desc *desc; /*__base_desc_from_raid_bdev(raid_bdev, idx);*/ + struct spdk_io_channel *ch = NULL; /*spdk_bdev_get_io_channel(desc)*/ + struct raid_base_bdev_info *base_info; + uint64_t pd_lba, pd_blocks; + if (cb_arg == NULL) + { + return -ENOMEM; + } - + pd_lba = get_area_offset(cycle_iter->iter_progress, rebuild->strips_per_area, raid_bdev->strip_size); + pd_blocks = get_area_size(rebuild->strips_per_area, raid_bdev->strip_size); - //TODO: Реализовать вот это. + RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) { + desc = base_info->desc; + ch = spdk_bdev_get_io_channel(desc); + if (ch != NULL) { + break; + } + } - return 0; + if (ch == NULL) { + SPDK_TEST_BIT(fl(rebuild), REBUILD_FLAG_FATAL_ERROR); + return -EIO; + } + cb_arg->cb = cb; + cb_arg->pd_lba = pd_lba; + cb_arg->pd_blocks = pd_blocks; + cb_arg->raid_bdev = raid_bdev; + cb_arg->cycle_progress = cycle_progress; + cb_arg->buf_idx = base_idx; + + ret = spdk_bdev_readv_blocks(desc, ch, + cycle_progress->base_bdevs_sg_buf[base_idx], + rebuild->strips_per_area, + pd_lba, pd_blocks, + raid1_submit_rebuild_second_stage, cb_arg); + if (ret != 0) + { + /* TODO: Handle this case */ + } + return ret; } static struct raid_bdev_module g_raid1_module = { diff --git a/module/bdev/raid/service.c b/module/bdev/raid/service.c index 8d07ce9b449..1bfe27bbb30 100644 --- a/module/bdev/raid/service.c +++ b/module/bdev/raid/service.c @@ -10,17 +10,12 @@ #include "spdk/util.h" #include "spdk/queue.h" +#include "atomic_raid.h" #include "bdev_raid.h" #include "service.h" #define DEBUG__ -/* ============================ TESTS ==================================== */ - -// TODO: Сейчас iovcnt = 1, доделать, чтоб можно было создавать любого количества -#define _MUX_BUF_LENGTH 1 -// ----- // - /* ======================= Poller functionality =========================== */ /* @@ -41,9 +36,8 @@ partly_submit_iteration(bool result ,uint64_t iter_idx, uint16_t area_idx, struc static inline void _free_sg_buffer_part(struct iovec *vec_array, uint64_t len) -{ //TODO: проверить, что оно работает (в for совсем неуверен) +{ struct iovec *base_vec; - //TODO: мб вообще не надо. for(base_vec = vec_array; base_vec < vec_array + len; base_vec++) { @@ -84,7 +78,7 @@ allocate_sg_buffer(size_t elem_size, size_t elemcnt, size_t align) } for (size_t i = 0; i < elemcnt; i++) - { //TODO: люблю лажать с индексами, проверить, что все ок + { vec_array[i].iov_len = elem_size; vec_array[i].iov_base = (void*)spdk_dma_zmalloc(sizeof(uint8_t)*vec_array[i].iov_len, align, NULL); if(vec_array[i].iov_base == NULL) @@ -174,7 +168,7 @@ init_rebuild_cycle(struct rebuild_progress *cycle_progress, struct raid_bdev *ra for (uint64_t i = 0; i < rebuild->num_memory_areas ; i++) { - if (ATOMIC_IS_AREA_STR_CLEAR(rebuild->rebuild_matrix[i])) continue; + if (ATOMIC_IS_AREA_STR_CLEAR(&rebuild->rebuild_matrix[i])) continue; if(start_idx == NOT_NEED_REBUILD) { @@ -230,7 +224,6 @@ init_cycle_iteration(struct raid_rebuild *rebuild, int64_t curr_idx) struct rebuild_cycle_iteration *cycle_iter = &(rebuild->cycle_progress->cycle_iteration); cycle_iter->iter_idx = curr_idx; - cycle_iter->complete = false; cycle_iter->snapshot = CREATE_AREA_STR_SNAPSHOT(&(rebuild->rebuild_matrix[curr_idx])); cycle_iter->br_area_cnt = count_broken_areas(cycle_iter->snapshot); cycle_iter->pr_area_cnt = 0; @@ -282,7 +275,10 @@ continue_rebuild(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) int ret = 0; free_cd_arg(cb_arg); - spdk_bdev_free_io(bdev_io); + if(bdev_io != NULL){ + // bdev_io->iov = NULL; + spdk_bdev_free_io(bdev_io); + } partly_submit_iteration(success, iter_idx, area_idx, raid_bdev->rebuild); /* Test whether the end of the iteration or not */ @@ -295,8 +291,9 @@ continue_rebuild(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) /* Wether it is the last iteration or not */ if(cycle_progress->clear_area_str_cnt == cycle_progress->area_str_cnt) - { //TODO: if clear_area_str_cnt - atomic => problem - finish_rebuild_cycle(raid_bdev); + { + + SPDK_SET_BIT(&(raid_bdev->rebuild->rebuild_flag), REBUILD_FLAG_FINISH); return; } @@ -307,13 +304,13 @@ continue_rebuild(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) if(spdk_unlikely(ret != 0)) { - SPDK_SET_BIT(&(raid_bdev->rebuild->rebuild_flag), REBUILD_FLAG_FATAL_ERROR); + SPDK_SET_BIT(fl(raid_bdev->rebuild), REBUILD_FLAG_FATAL_ERROR); } } int run_rebuild_poller(void* arg) -{ //TODO: в целом реализация наивная (без учета многопоточности) - не очень пока понимаю, как ее прикрутить. +{ struct raid_bdev *raid_bdev = arg; struct raid_rebuild *rebuild = raid_bdev->rebuild; struct rebuild_progress *cycle_progress = NULL; @@ -345,6 +342,10 @@ run_rebuild_poller(void* arg) /* * Previous recovery process is not complete */ + if (SPDK_TEST_BIT(fl(rebuild), REBUILD_FLAG_FINISH)) + { + finish_rebuild_cycle(raid_bdev); + } return 0; } @@ -397,165 +398,4 @@ run_rebuild_poller(void* arg) return -ENODEV; } return ret; -} - -// ===============================TESTs=========================================== // -// TODO: мб не надо, переделать. -// struct container { -// struct raid_bdev *raid_bdev; -// int idx; -// struct iovec * buff; -// } typedef container; - - -// static inline struct iovec * -// alloc_continuous_buffer_part(size_t iovlen, size_t align) -// { -// struct iovec *buf; -// buf = spdk_dma_zmalloc(sizeof(struct iovec), 0, NULL); -// if(buf == NULL) -// { -// return NULL; -// } - -// buf->iov_len = iovlen; -// buf->iov_base = spdk_dma_zmalloc(sizeof(uint8_t)*(buf->iov_len), 0, NULL); -// if(buf->iov_base == NULL) -// { -// spdk_dma_free(buf); -// return NULL; -// } - -// return buf; -// } - -// static inline void -// free_continuous_buffer_part(struct iovec * buf_elem) -// { -// spdk_dma_free(buf_elem->iov_base); -// spdk_dma_free(buf_elem); -// } - - -// static inline int -// fill_ones_write_request(struct iovec * buf_array, int buf_len) -// { -// // не учитывает align внутри iov_base -// SPDK_WARNLOG("i'm here 2 \n"); - -// if(buf_len > _MUX_BUF_LENGTH) -// { -// return -1; -// } -// for(size_t i = 0; ibuff->iov_base)); -// } else { -// SPDK_ERRLOG("test (read) fail\n"); -// } - -// free_continuous_buffer_part(cont->buff); -// spdk_bdev_free_io(bdev_io); -// free(cont); -// SPDK_WARNLOG("test (read) success\n"); -// } - -// void -// cd_write_func(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) -// { -// container *cont = cb_arg; -// if(success) -// { -// SPDK_WARNLOG("test (write) success\n"); -// } else { -// SPDK_ERRLOG("test (write) fail\n"); -// } - -// free_continuous_buffer_part(cont->buff); -// spdk_bdev_free_io(bdev_io); -// submit_read_request_base_bdev(cont->raid_bdev, cont->idx); -// free(cont); -// } - -// void -// submit_write_request_base_bdev(struct raid_bdev *raid_bdev, uint8_t idx) -// { -// struct spdk_bdev_desc *desc = __base_desc_from_raid_bdev(raid_bdev, idx); -// struct spdk_bdev *base_bdev = spdk_bdev_desc_get_bdev(desc); -// struct spdk_io_channel *ch = spdk_bdev_get_io_channel(desc); -// struct iovec *buffer; -// container *cont; -// int ret; - - -// buffer = alloc_continuous_buffer_part(base_bdev->blocklen, base_bdev->required_alignment); -// if (fill_ones_write_request(buffer, 1) != 0) -// { -// SPDK_ERRLOG("fill_ones_write_request was fail\n"); -// } -// cont = calloc(1, sizeof(container)); -// if (cont == NULL){ -// SPDK_ERRLOG("cont alloc failed\n"); -// } - -// cont->buff = buffer; -// cont->idx = 0; -// cont->raid_bdev = raid_bdev; -// ret = spdk_bdev_writev_blocks (desc, ch, buffer, 1, 0, 1, cd_write_func, cont); - -// if(spdk_likely(ret == 0)) -// { -// SPDK_WARNLOG("submit test (write) success\n"); -// } else { -// SPDK_ERRLOG("submit test (write) fail\n"); -// } -// } - -// void -// submit_read_request_base_bdev(struct raid_bdev *raid_bdev, uint8_t idx) -// { -// struct spdk_bdev_desc *desc = __base_desc_from_raid_bdev(raid_bdev, idx); -// struct spdk_bdev *base_bdev = spdk_bdev_desc_get_bdev(desc); -// struct spdk_io_channel *ch = spdk_bdev_get_io_channel(desc); -// struct iovec *buffer; -// container *cont; -// int ret; - -// buffer = alloc_continuous_buffer_part(base_bdev->blocklen, base_bdev->required_alignment); - -// cont = calloc(1, sizeof(container)); -// if (cont == NULL){ -// SPDK_ERRLOG("cont alloc failed\n"); -// } - -// cont->buff = buffer; -// cont->idx = 0; -// cont->raid_bdev = raid_bdev; -// ret = spdk_bdev_readv_blocks(desc, ch, buffer, 1, 0, 1, cd_read_func, cont); - -// if(spdk_likely(ret == 0)) -// { -// SPDK_WARNLOG("submit test (read) success\n"); -// } else { -// SPDK_ERRLOG("submit test (read) fail\n"); -// } -// } -/* ======================================================================== */ \ No newline at end of file +} \ No newline at end of file diff --git a/module/bdev/raid/service.h b/module/bdev/raid/service.h index 4ef91efe99e..031e9dab451 100644 --- a/module/bdev/raid/service.h +++ b/module/bdev/raid/service.h @@ -7,6 +7,7 @@ #define SPDK_RAID_SERVICE_INTERNAL_H #include "spdk/queue.h" +#include "atomic_raid.h" #include "bdev_raid.h" //-> @@ -14,14 +15,12 @@ #define fl(rebuild) &(rebuild->rebuild_flag) #define NOT_NEED_REBUILD -1 //-> -//TODO: Надо проверить, что побитовые макросы с указателями нормально работают, а то я вообще хз, мб тут ошибка -#define ATOMIC_IS_AREA_STR_CLEAR(area_srt) (area_srt) -#define CREATE_AREA_STR_SNAPSHOT(area_srt_ptr) (*area_srt_ptr) -#define ATOMIC_INCREMENT(ptr) ((*ptr)++) -#define ATOMIC_DECREMENT(ptr) ((*ptr)--) -#define ATOMIC_EXCHANGE(dest_ptr, exc, src) (TEST_CAS(dest_ptr, exc, src)) +#define ATOMIC_IS_AREA_STR_CLEAR(ptr) (*ptr) +#define CREATE_AREA_STR_SNAPSHOT(area_srt_ptr) raid_atomic64_read(area_srt_ptr) +#define ATOMIC_INCREMENT(ptr) raid_atomic64_inc(ptr) +#define ATOMIC_DECREMENT(ptr) raid_atomic64_dec(ptr) +#define ATOMIC_EXCHANGE(dest_ptr, exc, src) (raid_atomic64_cmpxchg(dest_ptr, exc, src)) // -> -// TODO: индексы у битов идут справа на лево!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! (все норм?) #define b_BASE_TYPE uint64_t #define b_BIT_PROECTION(name) b_BASE_TYPE name[SPDK_CEIL_DIV(MATRIX_REBUILD_SIZE, (sizeof(b_BASE_TYPE)*8))] #define b_GET_IDX_BP(x) (x / (sizeof(b_BASE_TYPE)*8)) @@ -29,7 +28,7 @@ // static inline bool -TEST_CAS(ATOMIC_TYPE *ptr, ATOMIC_SNAPSHOT_TYPE exc, ATOMIC_SNAPSHOT_TYPE src) +_CAS(ATOMIC_TYPE *ptr, ATOMIC_SNAPSHOT_TYPE exc, ATOMIC_SNAPSHOT_TYPE src) { if (*ptr == exc){ *ptr = src; @@ -50,9 +49,6 @@ struct iteration_step struct rebuild_cycle_iteration { - /* true if one part of the rebuild cycle is completed */ - bool complete; - /* number of broken areas in current area stripe */ int16_t br_area_cnt; @@ -87,7 +83,7 @@ struct rebuild_progress { uint64_t area_str_cnt; /* number of area stripes with processed areas (tried to rebuild all the broken areas) */ - uint64_t clear_area_str_cnt; //TODO: думаю, что не должно быть атомиком, потому что измеяется последовательно + uint64_t clear_area_str_cnt; /* * To avoid memory overloading, only one area stripe (in need of rebuild) diff --git a/test/unit/lib/bdev/raid/Makefile b/test/unit/lib/bdev/raid/Makefile index 1550ceb2ded..1ba53e899be 100644 --- a/test/unit/lib/bdev/raid/Makefile +++ b/test/unit/lib/bdev/raid/Makefile @@ -6,7 +6,8 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../../..) include $(SPDK_ROOT_DIR)/mk/spdk.common.mk -DIRS-y = bdev_raid.c concat.c raid1.c +DIRS-y = concat.c +# raid1.c bdev_raid.c DIRS-$(CONFIG_RAID5F) += raid5f.c From 8c7017cf7e928ee762e4a9301c0bf7c207e64df7 Mon Sep 17 00:00:00 2001 From: ItIsMrLaG Date: Tue, 20 Feb 2024 21:36:04 +0000 Subject: [PATCH 19/24] bdev/raid: Refactor typos --- module/bdev/raid/bdev_raid.h | 2 +- module/bdev/raid/raid1.c | 9 +++++++-- module/bdev/raid/service.c | 8 ++------ module/bdev/raid/service.h | 2 +- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/module/bdev/raid/bdev_raid.h b/module/bdev/raid/bdev_raid.h index 377ac447ddb..7577bca80a4 100644 --- a/module/bdev/raid/bdev_raid.h +++ b/module/bdev/raid/bdev_raid.h @@ -19,7 +19,7 @@ #define BASE_BDEVS_MAX_NUM 64 -// #include "service.h" +#include "service.h" enum rebuild_flag { /* rebuild flag set during initialization */ diff --git a/module/bdev/raid/raid1.c b/module/bdev/raid/raid1.c index cf5f0eca4de..b7e1ad871a0 100644 --- a/module/bdev/raid/raid1.c +++ b/module/bdev/raid/raid1.c @@ -344,6 +344,7 @@ void raid1_submit_rebuild_second_stage(struct spdk_bdev_io *bdev_io, bool succes if (!success) { //TODO: Handle this case (mb add new flag FIRST_STAGE_ERROR) + SPDK_WARNLOG("Problem before firs rebuild stage RAID1\n"); return; } @@ -387,20 +388,24 @@ raid1_submit_rebuild_request(struct raid_bdev *raid_bdev, struct rebuild_progres struct spdk_io_channel *ch = NULL; /*spdk_bdev_get_io_channel(desc)*/ struct raid_base_bdev_info *base_info; uint64_t pd_lba, pd_blocks; + uint8_t idx = 0; + if (cb_arg == NULL) { return -ENOMEM; } - pd_lba = get_area_offset(cycle_iter->iter_progress, rebuild->strips_per_area, raid_bdev->strip_size); + pd_lba = get_area_offset(cycle_iter->iter_idx, rebuild->strips_per_area, raid_bdev->strip_size); pd_blocks = get_area_size(rebuild->strips_per_area, raid_bdev->strip_size); RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) { desc = base_info->desc; ch = spdk_bdev_get_io_channel(desc); - if (ch != NULL) { + + if (ch != NULL && !SPDK_TEST_BIT(&(cycle_iter->br_area_cnt), idx)) { break; } + idx++; } if (ch == NULL) { diff --git a/module/bdev/raid/service.c b/module/bdev/raid/service.c index 1bfe27bbb30..d822330e7fd 100644 --- a/module/bdev/raid/service.c +++ b/module/bdev/raid/service.c @@ -14,8 +14,6 @@ #include "bdev_raid.h" #include "service.h" -#define DEBUG__ - /* ======================= Poller functionality =========================== */ /* @@ -140,6 +138,8 @@ alloc_base_bdevs_buff(struct raid_bdev *raid_bdev, struct rebuild_progress *cycl _free_base_bdevs_buff(raid_bdev, cycle_progress, i); return -ENOMEM; } + + i++; } return 0; } @@ -316,10 +316,6 @@ run_rebuild_poller(void* arg) struct rebuild_progress *cycle_progress = NULL; int ret = 0; -#ifdef DEBUG__ - SPDK_WARNLOG("poller is working now with: %s!\n", raid_bdev->bdev.name); -#endif - if (rebuild == NULL) { SPDK_WARNLOG("%s doesn't have rebuild struct!\n", raid_bdev->bdev.name); diff --git a/module/bdev/raid/service.h b/module/bdev/raid/service.h index 031e9dab451..8a14691e69f 100644 --- a/module/bdev/raid/service.h +++ b/module/bdev/raid/service.h @@ -15,7 +15,7 @@ #define fl(rebuild) &(rebuild->rebuild_flag) #define NOT_NEED_REBUILD -1 //-> -#define ATOMIC_IS_AREA_STR_CLEAR(ptr) (*ptr) +#define ATOMIC_IS_AREA_STR_CLEAR(ptr) (*ptr == 0) #define CREATE_AREA_STR_SNAPSHOT(area_srt_ptr) raid_atomic64_read(area_srt_ptr) #define ATOMIC_INCREMENT(ptr) raid_atomic64_inc(ptr) #define ATOMIC_DECREMENT(ptr) raid_atomic64_dec(ptr) From 5eaab8cc8c06d6aa054f59fbb47286176b63bfd7 Mon Sep 17 00:00:00 2001 From: ItIsMrLaG Date: Tue, 28 May 2024 06:54:11 +0000 Subject: [PATCH 20/24] bdev/raid: Fix rebuild behavior when the new device has not yet been inserted --- module/bdev/raid/bdev_raid.c | 2 +- module/bdev/raid/raid1.c | 46 +++++++--- module/bdev/raid/service.c | 166 ++++++++++++++++++++--------------- module/bdev/raid/service.h | 49 ++++++----- 4 files changed, 153 insertions(+), 110 deletions(-) diff --git a/module/bdev/raid/bdev_raid.c b/module/bdev/raid/bdev_raid.c index b150d19fe98..9c4999db19e 100644 --- a/module/bdev/raid/bdev_raid.c +++ b/module/bdev/raid/bdev_raid.c @@ -1014,7 +1014,7 @@ raid_bdev_create(const char *name, uint32_t strip_size, uint8_t num_base_bdevs, SPDK_ERRLOG("Unable to allocate memory for raid rebuild struct\n"); return -ENOMEM; } - raid_bdev->rebuild_poller = SPDK_POLLER_REGISTER(run_rebuild_poller, raid_bdev, 2000); + raid_bdev->rebuild_poller = SPDK_POLLER_REGISTER(run_rebuild_poller, raid_bdev, 200000); break; default: raid_bdev->rebuild = NULL; diff --git a/module/bdev/raid/raid1.c b/module/bdev/raid/raid1.c index b7e1ad871a0..d4fd671e671 100644 --- a/module/bdev/raid/raid1.c +++ b/module/bdev/raid/raid1.c @@ -350,15 +350,20 @@ void raid1_submit_rebuild_second_stage(struct spdk_bdev_io *bdev_io, bool succes RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) { desc = base_info->desc; - ch = spdk_bdev_get_io_channel(desc); - if (!SPDK_TEST_BIT(&(cycle_iteration->br_area_cnt), idx)) { + + if (!SPDK_TEST_BIT(&(cycle_iteration->br_area_cnt), idx)){ + idx++; + continue; + } + + if (desc == NULL) { + extern_continue_rebuild(cycle_iteration->iter_idx, idx, cycle_iteration, raid_bdev); idx++; continue; } - // TODO: ch == NULL -> - // if (spdk_unlikely(ret != 0)) { - // info->cb(NULL, false, cb_arg_new); - // } + + ch = spdk_bdev_get_io_channel(desc); + cb_arg_new = alloc_cb_arg(cycle_iteration->iter_idx, idx, cycle_iteration, raid_bdev); ret = spdk_bdev_writev_blocks(desc, ch, raid_bdev->rebuild->cycle_progress->base_bdevs_sg_buf[info->buf_idx], @@ -398,20 +403,34 @@ raid1_submit_rebuild_request(struct raid_bdev *raid_bdev, struct rebuild_progres pd_lba = get_area_offset(cycle_iter->iter_idx, rebuild->strips_per_area, raid_bdev->strip_size); pd_blocks = get_area_size(rebuild->strips_per_area, raid_bdev->strip_size); - RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) { + RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) + { desc = base_info->desc; - ch = spdk_bdev_get_io_channel(desc); + if (desc != NULL) + { + ch = spdk_bdev_get_io_channel(desc); - if (ch != NULL && !SPDK_TEST_BIT(&(cycle_iter->br_area_cnt), idx)) { - break; - } + if (ch != NULL && !SPDK_TEST_BIT(&(cycle_iter->br_area_cnt), idx)) + { + break; + } + } idx++; } - if (ch == NULL) { + if (idx == raid_bdev->num_base_bdevs) + { + SPDK_WARNLOG("No available devices for reading from raid"); + SPDK_SET_BIT(&(raid_bdev->rebuild->rebuild_flag), REBUILD_FLAG_FINISH); + return -ENODEV; + } + + if (ch == NULL) + { SPDK_TEST_BIT(fl(rebuild), REBUILD_FLAG_FATAL_ERROR); return -EIO; } + cb_arg->cb = cb; cb_arg->pd_lba = pd_lba; cb_arg->pd_blocks = pd_blocks; @@ -426,7 +445,8 @@ raid1_submit_rebuild_request(struct raid_bdev *raid_bdev, struct rebuild_progres raid1_submit_rebuild_second_stage, cb_arg); if (ret != 0) { - /* TODO: Handle this case */ + SPDK_TEST_BIT(fl(rebuild), REBUILD_FLAG_FATAL_ERROR); + return -EIO; } return ret; } diff --git a/module/bdev/raid/service.c b/module/bdev/raid/service.c index d822330e7fd..40b5580aa01 100644 --- a/module/bdev/raid/service.c +++ b/module/bdev/raid/service.c @@ -1,4 +1,4 @@ - /* SPDX-License-Identifier: BSD-3-Clause +/* SPDX-License-Identifier: BSD-3-Clause * Copyright (C) 2018 Intel Corporation. * All rights reserved. */ @@ -20,11 +20,11 @@ * The function shold be run after rebuilding of concrete area from iteration */ static inline void -partly_submit_iteration(bool result ,uint64_t iter_idx, uint16_t area_idx, struct raid_rebuild *rebuild) +partly_submit_iteration(bool result, uint64_t iter_idx, uint16_t area_idx, struct raid_rebuild *rebuild) { struct rebuild_cycle_iteration *iter = &(rebuild->cycle_progress->cycle_iteration); - if(result) + if (result) { SPDK_REMOVE_BIT(&(rebuild->rebuild_matrix[iter_idx]), area_idx); } @@ -37,7 +37,7 @@ _free_sg_buffer_part(struct iovec *vec_array, uint64_t len) { struct iovec *base_vec; - for(base_vec = vec_array; base_vec < vec_array + len; base_vec++) + for (base_vec = vec_array; base_vec < vec_array + len; base_vec++) { spdk_dma_free(base_vec->iov_base); } @@ -47,30 +47,30 @@ static inline void free_sg_buffer(struct iovec *vec_array, uint64_t len) { /* usage: struct iovec *a; free_sg_buffer(&a, b); */ - if(len != 0) + if (len != 0) { _free_sg_buffer_part(vec_array, len); - } + } free(vec_array); } uint64_t get_area_offset(size_t area_idx, size_t area_size, size_t strip_size) { - return area_idx*area_size*strip_size; -} + return area_idx * area_size * strip_size; +} uint64_t get_area_size(size_t area_size, size_t strip_size) { - return area_size*strip_size; + return area_size * strip_size; } static inline struct iovec * allocate_sg_buffer(size_t elem_size, size_t elemcnt, size_t align) { struct iovec *vec_array = calloc(elemcnt, sizeof(struct iovec)); - if(vec_array == NULL) + if (vec_array == NULL) { return NULL; } @@ -78,8 +78,8 @@ allocate_sg_buffer(size_t elem_size, size_t elemcnt, size_t align) for (size_t i = 0; i < elemcnt; i++) { vec_array[i].iov_len = elem_size; - vec_array[i].iov_base = (void*)spdk_dma_zmalloc(sizeof(uint8_t)*vec_array[i].iov_len, align, NULL); - if(vec_array[i].iov_base == NULL) + vec_array[i].iov_base = (void *)spdk_dma_zmalloc(sizeof(uint8_t) * vec_array[i].iov_len, align, NULL); + if (vec_array[i].iov_base == NULL) { _free_sg_buffer_part(vec_array, i); free(vec_array); @@ -89,13 +89,13 @@ allocate_sg_buffer(size_t elem_size, size_t elemcnt, size_t align) return vec_array; } -void -reset_buffer(struct iovec *vec_array, uint32_t len) +void reset_buffer(struct iovec *vec_array, uint32_t len) { struct iovec *base_vec; - if(len == 0) return; + if (len == 0) + return; - for(base_vec = vec_array; base_vec < vec_array + len; base_vec++) + for (base_vec = vec_array; base_vec < vec_array + len; base_vec++) { memset(base_vec->iov_base, 0, base_vec->iov_len); } @@ -120,27 +120,37 @@ free_base_bdevs_buff(struct raid_bdev *raid_bdev, struct rebuild_progress *cycle static inline int alloc_base_bdevs_buff(struct raid_bdev *raid_bdev, struct rebuild_progress *cycle_progress) { - uint64_t elem_size = spdk_bdev_get_block_size(&(raid_bdev->bdev))*raid_bdev->strip_size; + uint64_t elem_size = spdk_bdev_get_block_size(&(raid_bdev->bdev)) * raid_bdev->strip_size; uint8_t i = 0; struct raid_base_bdev_info *base_info; - + RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) { - struct spdk_bdev *bbdev = spdk_bdev_desc_get_bdev(base_info->desc); - if(spdk_bdev_get_write_unit_size(bbdev) != 1) + if (base_info->desc != NULL) { - SPDK_WARNLOG("Unsupported write_unit_size in base bdev of raid"); + struct spdk_bdev *bbdev = spdk_bdev_desc_get_bdev(base_info->desc); + + if (spdk_bdev_get_write_unit_size(bbdev) != 1) + { + SPDK_WARNLOG("Unsupported write_unit_size in base bdev of raid"); + } + + if (bbdev->required_alignment != 0) + { + SPDK_WARNLOG("Rebuild system unsupported alignment (TODO)"); + } } - - cycle_progress->base_bdevs_sg_buf[i] = allocate_sg_buffer(elem_size, raid_bdev->rebuild->strips_per_area, bbdev->required_alignment); + + cycle_progress->base_bdevs_sg_buf[i] = allocate_sg_buffer(elem_size, raid_bdev->rebuild->strips_per_area, 0); if (cycle_progress->base_bdevs_sg_buf[i] == NULL) { _free_base_bdevs_buff(raid_bdev, cycle_progress, i); return -ENOMEM; } - + i++; } + return 0; } @@ -151,7 +161,8 @@ count_broken_areas(ATOMIC_SNAPSHOT_TYPE area_str) for (uint16_t i = 0; i < LEN_AREA_STR_IN_BIT; i++) { - if(SPDK_TEST_BIT(&area_str, i)) cnt += 1; + if (SPDK_TEST_BIT(&area_str, i)) + cnt += 1; } return cnt; @@ -166,11 +177,12 @@ init_rebuild_cycle(struct rebuild_progress *cycle_progress, struct raid_bdev *ra cycle_progress->clear_area_str_cnt = 0; cycle_progress->area_str_cnt = 0; - for (uint64_t i = 0; i < rebuild->num_memory_areas ; i++) + for (uint64_t i = 0; i < rebuild->num_memory_areas; i++) { - if (ATOMIC_IS_AREA_STR_CLEAR(&rebuild->rebuild_matrix[i])) continue; + if (ATOMIC_IS_AREA_STR_CLEAR(&rebuild->rebuild_matrix[i])) + continue; - if(start_idx == NOT_NEED_REBUILD) + if (start_idx == NOT_NEED_REBUILD) { start_idx = i; } @@ -183,7 +195,9 @@ init_rebuild_cycle(struct rebuild_progress *cycle_progress, struct raid_bdev *ra if (start_idx != NOT_NEED_REBUILD) { raid_bdev->rebuild->cycle_progress = cycle_progress; - } else { + } + else + { raid_bdev->rebuild->cycle_progress = NULL; } @@ -197,7 +211,8 @@ get_iter_idx(int64_t prev_idx, struct raid_bdev *raid_bdev) for (int64_t i = prev_idx + 1; i < (int64_t)raid_bdev->rebuild->num_memory_areas; i++) { - if (!SPDK_TEST_BIT(&(cycle_progress->area_proection[b_GET_IDX_BP(i)]), b_GET_SHFT_BP(i))) continue; + if (!SPDK_TEST_BIT(&(cycle_progress->area_proection[b_GET_IDX_BP(i)]), b_GET_SHFT_BP(i))) + continue; return i; } return NOT_NEED_REBUILD; @@ -205,14 +220,14 @@ get_iter_idx(int64_t prev_idx, struct raid_bdev *raid_bdev) static inline void finish_rebuild_cycle(struct raid_bdev *raid_bdev) -{ +{ struct raid_rebuild *rebuild = raid_bdev->rebuild; if (rebuild == NULL) { return; } - free_base_bdevs_buff(raid_bdev, rebuild->cycle_progress); + free_base_bdevs_buff(raid_bdev, rebuild->cycle_progress); free(rebuild->cycle_progress); rebuild->cycle_progress = NULL; SPDK_REMOVE_BIT(fl(rebuild), REBUILD_FLAG_IN_PROGRESS); @@ -230,7 +245,7 @@ init_cycle_iteration(struct raid_rebuild *rebuild, int64_t curr_idx) cycle_iter->iter_progress = cycle_iter->snapshot; } -void init_cb_arg(struct iteration_step *iter_info, int64_t iter_idx, int16_t area_idx, struct rebuild_cycle_iteration *iteration, struct raid_bdev *raid_bdev) +void init_cb_arg(struct iteration_step *iter_info, int64_t iter_idx, int16_t area_idx, struct rebuild_cycle_iteration *iteration, struct raid_bdev *raid_bdev) { iter_info->area_idx = area_idx; iter_info->iter_idx = iter_idx; @@ -250,49 +265,26 @@ alloc_cb_arg(int64_t iter_idx, int16_t area_idx, struct rebuild_cycle_iteration return iter_info; } -void -free_cd_arg(struct iteration_step *cb) +void free_cb_arg(struct iteration_step *cb) { - if(cb == NULL) + if (cb == NULL) { - return; + return; } free(cb); } -/* - * Callback function. - */ -void -continue_rebuild(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) +void extern_continue_rebuild(int64_t iter_idx, int16_t area_idx, struct rebuild_cycle_iteration *iteration, struct raid_bdev *raid_bdev) { - int64_t iter_idx = ((struct iteration_step *)cb_arg)->iter_idx; - int16_t area_idx = ((struct iteration_step *)cb_arg)->area_idx; - struct rebuild_cycle_iteration *iteration = ((struct iteration_step *)cb_arg)->iteration; - struct raid_bdev *raid_bdev = ((struct iteration_step *)cb_arg)->raid_bdev; struct rebuild_progress *cycle_progress = raid_bdev->rebuild->cycle_progress; int64_t next_iter_idx; int ret = 0; - free_cd_arg(cb_arg); - if(bdev_io != NULL){ - // bdev_io->iov = NULL; - spdk_bdev_free_io(bdev_io); - } - partly_submit_iteration(success, iter_idx, area_idx, raid_bdev->rebuild); - - /* Test whether the end of the iteration or not */ - if(!ATOMIC_EXCHANGE(&(iteration->pr_area_cnt), iteration->br_area_cnt, 0)) - { - return; - } - ++cycle_progress->clear_area_str_cnt; /* Wether it is the last iteration or not */ - if(cycle_progress->clear_area_str_cnt == cycle_progress->area_str_cnt) + if (cycle_progress->clear_area_str_cnt == cycle_progress->area_str_cnt) { - SPDK_SET_BIT(&(raid_bdev->rebuild->rebuild_flag), REBUILD_FLAG_FINISH); return; } @@ -302,14 +294,41 @@ continue_rebuild(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) ret = raid_bdev->module->rebuild_request(raid_bdev, cycle_progress, continue_rebuild); - if(spdk_unlikely(ret != 0)) + if (spdk_unlikely(ret != 0)) { SPDK_SET_BIT(fl(raid_bdev->rebuild), REBUILD_FLAG_FATAL_ERROR); } } -int -run_rebuild_poller(void* arg) +/* + * Callback function. + */ +void continue_rebuild(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) +{ + int64_t iter_idx = ((struct iteration_step *)cb_arg)->iter_idx; + int16_t area_idx = ((struct iteration_step *)cb_arg)->area_idx; + struct rebuild_cycle_iteration *iteration = ((struct iteration_step *)cb_arg)->iteration; + struct raid_bdev *raid_bdev = ((struct iteration_step *)cb_arg)->raid_bdev; + + free_cb_arg(cb_arg); + + if (bdev_io != NULL) + { + // bdev_io->iov = NULL; + spdk_bdev_free_io(bdev_io); + } + partly_submit_iteration(success, iter_idx, area_idx, raid_bdev->rebuild); + + /* Test whether the end of the iteration or not */ + if (!ATOMIC_EXCHANGE(&(iteration->pr_area_cnt), iteration->br_area_cnt, 0)) + { + return; + } + + extern_continue_rebuild(iter_idx, area_idx, iteration, raid_bdev); +} + +int run_rebuild_poller(void *arg) { struct raid_bdev *raid_bdev = arg; struct raid_rebuild *rebuild = raid_bdev->rebuild; @@ -318,8 +337,8 @@ run_rebuild_poller(void* arg) if (rebuild == NULL) { - SPDK_WARNLOG("%s doesn't have rebuild struct!\n", raid_bdev->bdev.name); - return -ENODEV; + SPDK_WARNLOG("%s doesn't have rebuild struct!\n", raid_bdev->bdev.name); + return -ENODEV; } if (!SPDK_TEST_BIT(fl(rebuild), REBUILD_FLAG_INITIALIZED)) { @@ -361,7 +380,7 @@ run_rebuild_poller(void* arg) start_idx = init_rebuild_cycle(cycle_progress, raid_bdev); - if(start_idx == NOT_NEED_REBUILD) + if (start_idx == NOT_NEED_REBUILD) { /* * no need rebuild @@ -371,16 +390,17 @@ run_rebuild_poller(void* arg) } if (raid_bdev->module->rebuild_request != NULL) - { + { SPDK_SET_BIT(fl(rebuild), REBUILD_FLAG_IN_PROGRESS); + SPDK_ERRLOG("Rebuild have started...\n"); init_cycle_iteration(rebuild, start_idx); - - if(alloc_base_bdevs_buff(raid_bdev, cycle_progress) != 0) + + if (alloc_base_bdevs_buff(raid_bdev, cycle_progress) != 0) { return -ENOMEM; } - + ret = raid_bdev->module->rebuild_request(raid_bdev, cycle_progress, continue_rebuild); switch (ret) { @@ -389,7 +409,9 @@ run_rebuild_poller(void* arg) finish_rebuild_cycle(raid_bdev); break; } - } else { + } + else + { SPDK_ERRLOG("rebuild_request inside raid%d doesn't implemented\n", raid_bdev->level); return -ENODEV; } diff --git a/module/bdev/raid/service.h b/module/bdev/raid/service.h index 8a14691e69f..d722ee53886 100644 --- a/module/bdev/raid/service.h +++ b/module/bdev/raid/service.h @@ -22,15 +22,16 @@ #define ATOMIC_EXCHANGE(dest_ptr, exc, src) (raid_atomic64_cmpxchg(dest_ptr, exc, src)) // -> #define b_BASE_TYPE uint64_t -#define b_BIT_PROECTION(name) b_BASE_TYPE name[SPDK_CEIL_DIV(MATRIX_REBUILD_SIZE, (sizeof(b_BASE_TYPE)*8))] -#define b_GET_IDX_BP(x) (x / (sizeof(b_BASE_TYPE)*8)) -#define b_GET_SHFT_BP(x) (x % (sizeof(b_BASE_TYPE)*8)) +#define b_BIT_PROECTION(name) b_BASE_TYPE name[SPDK_CEIL_DIV(MATRIX_REBUILD_SIZE, (sizeof(b_BASE_TYPE) * 8))] +#define b_GET_IDX_BP(x) (x / (sizeof(b_BASE_TYPE) * 8)) +#define b_GET_SHFT_BP(x) (x % (sizeof(b_BASE_TYPE) * 8)) // static inline bool _CAS(ATOMIC_TYPE *ptr, ATOMIC_SNAPSHOT_TYPE exc, ATOMIC_SNAPSHOT_TYPE src) { - if (*ptr == exc){ + if (*ptr == exc) + { *ptr = src; return true; } @@ -46,7 +47,6 @@ struct iteration_step spdk_bdev_io_completion_cb cb; }; - struct rebuild_cycle_iteration { /* number of broken areas in current area stripe */ @@ -70,8 +70,8 @@ struct rebuild_cycle_iteration ATOMIC_SNAPSHOT(iter_progress); }; - -struct rebuild_progress { +struct rebuild_progress +{ /* * bit proection of rebuild matrix, * where each bit corresponds one line(area stripe) in rebuild matrix @@ -94,35 +94,36 @@ struct rebuild_progress { /* * Buffers for raid base_bdevs. - * Each element - SG-buffer (array of iovec); - * Size of each SG-buffer is size of one memory area in bytes; + * Each element - SG-buffer (array of iovec); + * Size of each SG-buffer is size of one memory area in bytes; * One element from SG-buffer describes buffer size equals size of one strip in bytes. */ - struct iovec* base_bdevs_sg_buf[BASE_BDEVS_MAX_NUM]; + struct iovec *base_bdevs_sg_buf[BASE_BDEVS_MAX_NUM]; }; +int +run_rebuild_poller(void *arg); -int -run_rebuild_poller(void* arg); +void continue_rebuild(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg); -void -continue_rebuild(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg); +void +extern_continue_rebuild(int64_t iter_idx, + int16_t area_idx, + struct rebuild_cycle_iteration *iteration, + struct raid_bdev *raid_bdev); struct iteration_step * alloc_cb_arg(int64_t iter_idx, int16_t area_idx, struct rebuild_cycle_iteration *iteration, struct raid_bdev *raid_bdev); -void -init_cb_arg(struct iteration_step *iter_info, - int64_t iter_idx, - int16_t area_idx, - struct rebuild_cycle_iteration *iteration, - struct raid_bdev *raid_bdev); +void init_cb_arg(struct iteration_step *iter_info, + int64_t iter_idx, + int16_t area_idx, + struct rebuild_cycle_iteration *iteration, + struct raid_bdev *raid_bdev); -void -free_cd_arg(struct iteration_step *cb); +void free_cb_arg(struct iteration_step *cb); -void -reset_buffer(struct iovec *vec_array, uint32_t len); +void reset_buffer(struct iovec *vec_array, uint32_t len); uint64_t get_area_offset(size_t area_idx, size_t area_size, size_t strip_size); From 1e51f3d9a2d4fd569e8dbc9078ff46b1b2dd13b6 Mon Sep 17 00:00:00 2001 From: ItIsMrLaG Date: Tue, 28 May 2024 18:19:24 +0000 Subject: [PATCH 21/24] bdev/raid: Service tests. --- stop.json | 27 +++++++ .../raid1/fio_cfg/two_malloc/verif.fio | 11 +++ .../raid1/fio_cfg/two_malloc/write.fio | 12 +++ .../raid1/rpc_cfg/two_malloc/addM2.json | 16 ++++ .../raid1/rpc_cfg/two_malloc/crt.json | 45 +++++++++++ .../raid1/rpc_cfg/two_malloc/dtr.json | 33 ++++++++ .../raid1/rpc_cfg/two_malloc/rfM0.json | 15 ++++ .../raid1/rpc_cfg/two_malloc/rfM1.json | 15 ++++ .../raid1/rpc_cfg/two_malloc/rfM2.json | 15 ++++ .../raid1/run/two_malloc.sh | 64 +++++++++++++++ test/bdev/raid_service_raid1.sh | 78 +++++++++++++++++++ 11 files changed, 331 insertions(+) create mode 100644 stop.json create mode 100644 test/bdev/raid_service_config/raid1/fio_cfg/two_malloc/verif.fio create mode 100644 test/bdev/raid_service_config/raid1/fio_cfg/two_malloc/write.fio create mode 100644 test/bdev/raid_service_config/raid1/rpc_cfg/two_malloc/addM2.json create mode 100644 test/bdev/raid_service_config/raid1/rpc_cfg/two_malloc/crt.json create mode 100644 test/bdev/raid_service_config/raid1/rpc_cfg/two_malloc/dtr.json create mode 100644 test/bdev/raid_service_config/raid1/rpc_cfg/two_malloc/rfM0.json create mode 100644 test/bdev/raid_service_config/raid1/rpc_cfg/two_malloc/rfM1.json create mode 100644 test/bdev/raid_service_config/raid1/rpc_cfg/two_malloc/rfM2.json create mode 100755 test/bdev/raid_service_config/raid1/run/two_malloc.sh create mode 100755 test/bdev/raid_service_raid1.sh diff --git a/stop.json b/stop.json new file mode 100644 index 00000000000..e4e4d7ee7de --- /dev/null +++ b/stop.json @@ -0,0 +1,27 @@ +{ + "subsystems": [ + { + "subsystem": "bdev", + "config": [ + { + "method": "bdev_raid_delete", + "params": { + "name": "Raid1" + } + }, + { + "params": { + "name": "M0" + }, + "method": "bdev_malloc_delete" + }, + { + "params": { + "name": "M1" + }, + "method": "bdev_malloc_delete" + } + ] + } + ] + } \ No newline at end of file diff --git a/test/bdev/raid_service_config/raid1/fio_cfg/two_malloc/verif.fio b/test/bdev/raid_service_config/raid1/fio_cfg/two_malloc/verif.fio new file mode 100644 index 00000000000..4707df7dc23 --- /dev/null +++ b/test/bdev/raid_service_config/raid1/fio_cfg/two_malloc/verif.fio @@ -0,0 +1,11 @@ +[global] +thread=1 +group_reporting=1 +verify=sha256 +verify_only +size=4096B +iodepth=1 + +[test] +filename=/dev/ublkb4 +numjobs=1 diff --git a/test/bdev/raid_service_config/raid1/fio_cfg/two_malloc/write.fio b/test/bdev/raid_service_config/raid1/fio_cfg/two_malloc/write.fio new file mode 100644 index 00000000000..615f2be8c67 --- /dev/null +++ b/test/bdev/raid_service_config/raid1/fio_cfg/two_malloc/write.fio @@ -0,0 +1,12 @@ +[global] +thread=1 +group_reporting=1 +verify=sha256 +size=4096B +iodepth=1 +rw=write +bs=4k + +[test] +filename=/dev/ublkb4 +numjobs=1 diff --git a/test/bdev/raid_service_config/raid1/rpc_cfg/two_malloc/addM2.json b/test/bdev/raid_service_config/raid1/rpc_cfg/two_malloc/addM2.json new file mode 100644 index 00000000000..77b4378af53 --- /dev/null +++ b/test/bdev/raid_service_config/raid1/rpc_cfg/two_malloc/addM2.json @@ -0,0 +1,16 @@ +{ + "subsystems": [ + { + "subsystem": "bdev", + "config": [ + { + "method": "bdev_raid_add_base_bdev", + "params": { + "raid_name": "Raid1", + "base_bdev_name": "M2" + } + } + ] + } + ] + } \ No newline at end of file diff --git a/test/bdev/raid_service_config/raid1/rpc_cfg/two_malloc/crt.json b/test/bdev/raid_service_config/raid1/rpc_cfg/two_malloc/crt.json new file mode 100644 index 00000000000..875da446020 --- /dev/null +++ b/test/bdev/raid_service_config/raid1/rpc_cfg/two_malloc/crt.json @@ -0,0 +1,45 @@ +{ + "subsystems": [ + { + "subsystem": "bdev", + "config": [ + { + "params": { + "block_size": 4096, + "num_blocks": 16, + "name": "M2" + }, + "method": "bdev_malloc_create" + }, + { + "params": { + "block_size": 4096, + "num_blocks": 16, + "name": "M0" + }, + "method": "bdev_malloc_create" + }, + { + "params": { + "block_size": 4096, + "num_blocks": 16, + "name": "M1" + }, + "method": "bdev_malloc_create" + }, + { + "method": "bdev_raid_create", + "params": { + "name": "Raid1", + "raid_level": "1", + "strip_size_kb": 8, + "base_bdevs": [ + "M0", + "M1" + ] + } + } + ] + } + ] +} diff --git a/test/bdev/raid_service_config/raid1/rpc_cfg/two_malloc/dtr.json b/test/bdev/raid_service_config/raid1/rpc_cfg/two_malloc/dtr.json new file mode 100644 index 00000000000..c875a0d62fc --- /dev/null +++ b/test/bdev/raid_service_config/raid1/rpc_cfg/two_malloc/dtr.json @@ -0,0 +1,33 @@ +{ + "subsystems": [ + { + "subsystem": "bdev", + "config": [ + { + "method": "bdev_raid_delete", + "params": { + "name": "Raid1" + } + }, + { + "params": { + "name": "M0" + }, + "method": "bdev_malloc_delete" + }, + { + "params": { + "name": "M1" + }, + "method": "bdev_malloc_delete" + }, + { + "params": { + "name": "M2" + }, + "method": "bdev_malloc_delete" + } + ] + } + ] + } \ No newline at end of file diff --git a/test/bdev/raid_service_config/raid1/rpc_cfg/two_malloc/rfM0.json b/test/bdev/raid_service_config/raid1/rpc_cfg/two_malloc/rfM0.json new file mode 100644 index 00000000000..18658f38298 --- /dev/null +++ b/test/bdev/raid_service_config/raid1/rpc_cfg/two_malloc/rfM0.json @@ -0,0 +1,15 @@ +{ + "subsystems": [ + { + "subsystem": "bdev", + "config": [ + { + "method": "bdev_raid_remove_base_bdev", + "params": { + "name": "M0" + } + } + ] + } + ] + } \ No newline at end of file diff --git a/test/bdev/raid_service_config/raid1/rpc_cfg/two_malloc/rfM1.json b/test/bdev/raid_service_config/raid1/rpc_cfg/two_malloc/rfM1.json new file mode 100644 index 00000000000..1f990af83c1 --- /dev/null +++ b/test/bdev/raid_service_config/raid1/rpc_cfg/two_malloc/rfM1.json @@ -0,0 +1,15 @@ +{ + "subsystems": [ + { + "subsystem": "bdev", + "config": [ + { + "method": "bdev_raid_remove_base_bdev", + "params": { + "name": "M1" + } + } + ] + } + ] + } \ No newline at end of file diff --git a/test/bdev/raid_service_config/raid1/rpc_cfg/two_malloc/rfM2.json b/test/bdev/raid_service_config/raid1/rpc_cfg/two_malloc/rfM2.json new file mode 100644 index 00000000000..b08b415dcd1 --- /dev/null +++ b/test/bdev/raid_service_config/raid1/rpc_cfg/two_malloc/rfM2.json @@ -0,0 +1,15 @@ +{ + "subsystems": [ + { + "subsystem": "bdev", + "config": [ + { + "method": "bdev_raid_remove_base_bdev", + "params": { + "name": "M2" + } + } + ] + } + ] + } \ No newline at end of file diff --git a/test/bdev/raid_service_config/raid1/run/two_malloc.sh b/test/bdev/raid_service_config/raid1/run/two_malloc.sh new file mode 100755 index 00000000000..309cefbe349 --- /dev/null +++ b/test/bdev/raid_service_config/raid1/run/two_malloc.sh @@ -0,0 +1,64 @@ +#!/bin/bash +# Run with sudo + +test_name="two_malloc" + +testdir=$(readlink -f $(dirname $0)) +rootdir=$(readlink -f $testdir/../../../../..) +rpc_cfgdir=$(readlink -f $testdir/../rpc_cfg/$test_name) +fio_cfgdir=$(readlink -f $testdir/../fio_cfg/$test_name) + +# Test scenario +# crt=$rpc_cfgdir/crt.json + +ret=1 + +function start { + $rootdir/scripts/rpc.py load_config -j $rpc_cfgdir/crt.json; + sleep 1; + + $rootdir/scripts/rpc.py ublk_start_disk Raid1 4; + sleep 1; +} + +function action { + $rootdir/scripts/rpc.py load_config -j $rpc_cfgdir/rfM0.json; + sleep 1; + + fio $fio_cfgdir/write.fio; + sleep 1; + + # $rootdir/scripts/rpc.py load_config -j $rpc_cfgdir/addM2.json; + # sleep 5; + + # $rootdir/scripts/rpc.py load_config -j $rpc_cfgdir/rfM1.json; + # sleep 1; + + fio $fio_cfgdir/verif.fio; + ret=$? +} + +function finish { + $rootdir/scripts/rpc.py ublk_stop_disk 4; + sleep 1; + + $rootdir/scripts/rpc.py load_config -j $rpc_cfgdir/dtr.json + sleep 1; +} + +if [ -n "$1" ] +then + if [ "$1" = "start" ] + then + start; + action; + exit $(($ret)); + else + finish; + fi +else + start; + action; + finish; + exit $(($ret)); +fi diff --git a/test/bdev/raid_service_raid1.sh b/test/bdev/raid_service_raid1.sh new file mode 100755 index 00000000000..0995c21c0b5 --- /dev/null +++ b/test/bdev/raid_service_raid1.sh @@ -0,0 +1,78 @@ +#!/bin/bash +# Run with sudo + +# Dir pathes +testdir=$(readlink -f $(dirname $0)) +rootdir=$(readlink -f $testdir/../..) +cfgdir=$(readlink -f $testdir/raid_service_config/raid1) +rundir=$(readlink -f $cfgdir/run) + +function start_ublk_tgt() { + $rootdir/scripts/rpc.py ublk_create_target; + sleep 1; + echo "Ublk target has been created" +} + +function stop_ublk_tgt() { + $rootdir/scripts/rpc.py ublk_destroy_target; + sleep 1; +} + +function start_tgt() { + screen -dmS spdk_tgt $rootdir/build/bin/spdk_tgt; + sleep 1; + echo "spdk_tgt has been started" + start_ublk_tgt; +} + +function finish_tgt() { + stop_ublk_tgt; + screen -S spdk_tgt -X kill; + echo "spdk_tgt has been finished" +} + +function run_tests() { + for file in $rundir/* + do + if [ -x "$file" ]; + then + local ret=""; + + echo -e "\e[34mTEST(start)\e[0m: \e[36m$file\e[0m" + "$file" start; + + if [ $? -eq 0 ] + then + ret="\e[32mSUCCESS\e[0m" + else + ret="\e[31mFAILED\e[0m" + fi + + "$file" finish; + echo -e "\e[34mTEST(finish)\e[0m: $ret" + echo "" + fi + done +} + +$rootdir/scripts/setup.sh; +echo "Start build process"; +cd $rootdir +make -j12; +cd $testdir +sleep 1; + + +if [ -n "$1" ] +then + if [ "$1" = "tgt" ] + then + start_tgt; + run_tests; + finish_tgt; + fi +else + start_ublk_tgt; + run_tests; + stop_ublk_tgt; +fi \ No newline at end of file From a6cee3ff43560d3da37f422c4ceeec55376d29e3 Mon Sep 17 00:00:00 2001 From: ItIsMrLaG Date: Thu, 30 May 2024 12:21:31 +0000 Subject: [PATCH 22/24] bdev/raid: Add debug tools to service --- module/bdev/raid/service.c | 3 +-- module/bdev/raid/service.h | 36 ++++++++++++++++++++++++++++++------ 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/module/bdev/raid/service.c b/module/bdev/raid/service.c index 40b5580aa01..8ee6274ee44 100644 --- a/module/bdev/raid/service.c +++ b/module/bdev/raid/service.c @@ -392,10 +392,9 @@ int run_rebuild_poller(void *arg) if (raid_bdev->module->rebuild_request != NULL) { SPDK_SET_BIT(fl(rebuild), REBUILD_FLAG_IN_PROGRESS); - SPDK_ERRLOG("Rebuild have started...\n"); + SPDK_WARNLOG("Rebuild have started...\n"); init_cycle_iteration(rebuild, start_idx); - if (alloc_base_bdevs_buff(raid_bdev, cycle_progress) != 0) { return -ENOMEM; diff --git a/module/bdev/raid/service.h b/module/bdev/raid/service.h index d722ee53886..c402c54b428 100644 --- a/module/bdev/raid/service.h +++ b/module/bdev/raid/service.h @@ -10,6 +10,8 @@ #include "atomic_raid.h" #include "bdev_raid.h" +#define SERVICE_DEBUG + //-> #define __base_desc_from_raid_bdev(raid_bdev, idx) (raid_bdev->base_bdev_info[idx].desc) #define fl(rebuild) &(rebuild->rebuild_flag) @@ -101,15 +103,15 @@ struct rebuild_progress struct iovec *base_bdevs_sg_buf[BASE_BDEVS_MAX_NUM]; }; -int +int run_rebuild_poller(void *arg); void continue_rebuild(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg); -void -extern_continue_rebuild(int64_t iter_idx, - int16_t area_idx, - struct rebuild_cycle_iteration *iteration, +void +extern_continue_rebuild(int64_t iter_idx, + int16_t area_idx, + struct rebuild_cycle_iteration *iteration, struct raid_bdev *raid_bdev); struct iteration_step * @@ -131,4 +133,26 @@ get_area_offset(size_t area_idx, size_t area_size, size_t strip_size); uint64_t get_area_size(size_t area_size, size_t strip_size); -#endif /* SPDK_RAID_SERVICE_INTERNAL_H */ \ No newline at end of file +#ifdef SERVICE_DEBUG + +#define PRINT_iteration_step(it) SPDK_ERRLOG("\ +\niter_step: \ +\n area_idx=%d \ +\n iter_idx=%ld \n", (it)->area_idx, (it)->iter_idx) + +#define PRINT_rebuild_cycle_iteration(cit) SPDK_ERRLOG("\ +\ncycle_iter: \ +\n br_area_cnt=%d \ +\n iter_idx=%ld \ +\n pr_area_cnt=%lu \ +\n snapshot=%lu \ +\n iter_progress=%lu \n", (cit)->br_area_cnt, (cit)->iter_idx, (cit)->pr_area_cnt, (cit)->snapshot, (cit)->iter_progress) + +#define PRINT_rebuild_progress(pr) SPDK_ERRLOG("\ +\nprogress: \ +\n area_str_cnt=%lu \ +\n clear_area_str_cnt=%lu \n", (pr)->area_str_cnt, (pr)->clear_area_str_cnt) + +#endif + +#endif /* SPDK_RAID_SERVICE_INTERNAL_H */ From 14f7752b5cb390783538611f0bf03d37697ab715 Mon Sep 17 00:00:00 2001 From: ItIsMrLaG Date: Thu, 30 May 2024 12:22:04 +0000 Subject: [PATCH 23/24] test/bdev/raid: Refactor service tests --- .../raid1/fio_cfg/two_malloc/verif.fio | 2 +- .../raid1/fio_cfg/two_malloc/write.fio | 2 +- .../raid1/run/two_malloc.sh | 21 ++++++++++++------- test/bdev/raid_service_raid1.sh | 9 ++++---- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/test/bdev/raid_service_config/raid1/fio_cfg/two_malloc/verif.fio b/test/bdev/raid_service_config/raid1/fio_cfg/two_malloc/verif.fio index 4707df7dc23..b4b4c28d8ba 100644 --- a/test/bdev/raid_service_config/raid1/fio_cfg/two_malloc/verif.fio +++ b/test/bdev/raid_service_config/raid1/fio_cfg/two_malloc/verif.fio @@ -7,5 +7,5 @@ size=4096B iodepth=1 [test] -filename=/dev/ublkb4 +filename=/dev/ublkb20 numjobs=1 diff --git a/test/bdev/raid_service_config/raid1/fio_cfg/two_malloc/write.fio b/test/bdev/raid_service_config/raid1/fio_cfg/two_malloc/write.fio index 615f2be8c67..2b23d9338f2 100644 --- a/test/bdev/raid_service_config/raid1/fio_cfg/two_malloc/write.fio +++ b/test/bdev/raid_service_config/raid1/fio_cfg/two_malloc/write.fio @@ -8,5 +8,5 @@ rw=write bs=4k [test] -filename=/dev/ublkb4 +filename=/dev/ublkb20 numjobs=1 diff --git a/test/bdev/raid_service_config/raid1/run/two_malloc.sh b/test/bdev/raid_service_config/raid1/run/two_malloc.sh index 309cefbe349..97c06b50aef 100755 --- a/test/bdev/raid_service_config/raid1/run/two_malloc.sh +++ b/test/bdev/raid_service_config/raid1/run/two_malloc.sh @@ -17,7 +17,7 @@ function start { $rootdir/scripts/rpc.py load_config -j $rpc_cfgdir/crt.json; sleep 1; - $rootdir/scripts/rpc.py ublk_start_disk Raid1 4; + $rootdir/scripts/rpc.py ublk_start_disk Raid1 20; sleep 1; } @@ -25,21 +25,28 @@ function action { $rootdir/scripts/rpc.py load_config -j $rpc_cfgdir/rfM0.json; sleep 1; + $rootdir/scripts/rpc.py bdev_raid_get_bdevs all; + fio $fio_cfgdir/write.fio; sleep 1; - - # $rootdir/scripts/rpc.py load_config -j $rpc_cfgdir/addM2.json; - # sleep 5; - # $rootdir/scripts/rpc.py load_config -j $rpc_cfgdir/rfM1.json; - # sleep 1; + $rootdir/scripts/rpc.py load_config -j $rpc_cfgdir/addM2.json; + sleep 6; + + $rootdir/scripts/rpc.py load_config -j $rpc_cfgdir/rfM1.json; + sleep 1; + + $rootdir/scripts/rpc.py bdev_raid_get_bdevs all; fio $fio_cfgdir/verif.fio; + sleep 1; + ret=$? + } function finish { - $rootdir/scripts/rpc.py ublk_stop_disk 4; + $rootdir/scripts/rpc.py ublk_stop_disk 20; sleep 1; $rootdir/scripts/rpc.py load_config -j $rpc_cfgdir/dtr.json diff --git a/test/bdev/raid_service_raid1.sh b/test/bdev/raid_service_raid1.sh index 0995c21c0b5..23dd9a8affe 100755 --- a/test/bdev/raid_service_raid1.sh +++ b/test/bdev/raid_service_raid1.sh @@ -9,13 +9,14 @@ rundir=$(readlink -f $cfgdir/run) function start_ublk_tgt() { $rootdir/scripts/rpc.py ublk_create_target; - sleep 1; + sleep 1; echo "Ublk target has been created" } function stop_ublk_tgt() { $rootdir/scripts/rpc.py ublk_destroy_target; - sleep 1; + sleep 2; + echo "stop ublk target"; } function start_tgt() { @@ -34,7 +35,7 @@ function finish_tgt() { function run_tests() { for file in $rundir/* do - if [ -x "$file" ]; + if [ -x "$file" ]; then local ret=""; @@ -47,7 +48,7 @@ function run_tests() { else ret="\e[31mFAILED\e[0m" fi - + "$file" finish; echo -e "\e[34mTEST(finish)\e[0m: $ret" echo "" From 80a95931686827fe2f12bdde406d6cb825128906 Mon Sep 17 00:00:00 2001 From: ItIsMrLaG Date: Thu, 30 May 2024 12:23:38 +0000 Subject: [PATCH 24/24] bdev/raid: Fix problem with null-channel after bdev adding (in read req) --- module/bdev/raid/raid1.c | 45 ++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/module/bdev/raid/raid1.c b/module/bdev/raid/raid1.c index d4fd671e671..00fdf59d2f1 100644 --- a/module/bdev/raid/raid1.c +++ b/module/bdev/raid/raid1.c @@ -14,6 +14,16 @@ struct raid1_info { struct raid_bdev *raid_bdev; }; +#ifdef SERVICE_DEBUG + +#define PRINT_rebuild_first_stage_cb(fs) SPDK_ERRLOG("\ +\nfirst_stage_cb: \ +\n buf_idx=%u \ +\n pd_lba=%lu \ +\n pd_blocks=%lu \n", (fs)->buf_idx, (fs)->pd_lba, (fs)->pd_blocks) + +#endif + struct rebuild_first_stage_cb { uint8_t buf_idx; @@ -154,6 +164,15 @@ raid1_submit_read_request(struct raid_bdev_io *raid_io) } base_ch = NULL; } + +// TODO REMOVE: + if (base_info->desc != NULL){ + base_ch = spdk_bdev_get_io_channel(base_info->desc); + raid_io->raid_ch->base_channel[idx] = base_ch; + break; + } +// ------------ + idx++; } @@ -340,7 +359,7 @@ void raid1_submit_rebuild_second_stage(struct spdk_bdev_io *bdev_io, bool succes struct iteration_step *cb_arg_new = NULL; uint8_t idx = 0; int ret = 0; - + if (!success) { //TODO: Handle this case (mb add new flag FIRST_STAGE_ERROR) @@ -365,10 +384,10 @@ void raid1_submit_rebuild_second_stage(struct spdk_bdev_io *bdev_io, bool succes ch = spdk_bdev_get_io_channel(desc); cb_arg_new = alloc_cb_arg(cycle_iteration->iter_idx, idx, cycle_iteration, raid_bdev); - ret = spdk_bdev_writev_blocks(desc, ch, - raid_bdev->rebuild->cycle_progress->base_bdevs_sg_buf[info->buf_idx], - raid_bdev->rebuild->strips_per_area, - info->pd_lba, info->pd_blocks, + ret = spdk_bdev_writev_blocks(desc, ch, + raid_bdev->rebuild->cycle_progress->base_bdevs_sg_buf[info->buf_idx], + raid_bdev->rebuild->strips_per_area, + info->pd_lba, info->pd_blocks, info->cb, cb_arg_new); if (spdk_unlikely(ret != 0)) { @@ -403,29 +422,29 @@ raid1_submit_rebuild_request(struct raid_bdev *raid_bdev, struct rebuild_progres pd_lba = get_area_offset(cycle_iter->iter_idx, rebuild->strips_per_area, raid_bdev->strip_size); pd_blocks = get_area_size(rebuild->strips_per_area, raid_bdev->strip_size); - RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) + RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) { desc = base_info->desc; if (desc != NULL) { ch = spdk_bdev_get_io_channel(desc); - - if (ch != NULL && !SPDK_TEST_BIT(&(cycle_iter->br_area_cnt), idx)) + + if (ch != NULL && !SPDK_TEST_BIT(&(cycle_iter->br_area_cnt), idx)) { break; } - } + } idx++; } if (idx == raid_bdev->num_base_bdevs) { - SPDK_WARNLOG("No available devices for reading from raid"); + SPDK_ERRLOG("No available devices for reading from raid"); SPDK_SET_BIT(&(raid_bdev->rebuild->rebuild_flag), REBUILD_FLAG_FINISH); return -ENODEV; } - if (ch == NULL) + if (ch == NULL) { SPDK_TEST_BIT(fl(rebuild), REBUILD_FLAG_FATAL_ERROR); return -EIO; @@ -438,10 +457,10 @@ raid1_submit_rebuild_request(struct raid_bdev *raid_bdev, struct rebuild_progres cb_arg->cycle_progress = cycle_progress; cb_arg->buf_idx = base_idx; - ret = spdk_bdev_readv_blocks(desc, ch, + ret = spdk_bdev_readv_blocks(desc, ch, cycle_progress->base_bdevs_sg_buf[base_idx], rebuild->strips_per_area, - pd_lba, pd_blocks, + pd_lba, pd_blocks, raid1_submit_rebuild_second_stage, cb_arg); if (ret != 0) {