From 043fa8d904920278dd6269f45a9a22d7bac7f7b2 Mon Sep 17 00:00:00 2001 From: ItIsMrLaG Date: Mon, 24 Jul 2023 11:29:52 +0000 Subject: [PATCH 1/9] 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 c6e31ea2ca2..58808b8280e 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 9b0acdc9306b053e3b073b84127c58ffdd18058a Mon Sep 17 00:00:00 2001 From: juliakononov Date: Mon, 24 Jul 2023 12:28:58 +0000 Subject: [PATCH 2/9] 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 58808b8280e..e595257f620 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++) @@ -198,6 +195,20 @@ void raid_bdev_write_info_json(struct raid_bdev *raid_bdev, struct spdk_json_wri int raid_bdev_remove_base_bdev(struct spdk_bdev *base_bdev, raid_bdev_remove_base_bdev_cb cb_fn, void *cb_ctx); +/* +* 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 54cf3b7ca616e0dfc1e0a391d33b2aedd6460662 Mon Sep 17 00:00:00 2001 From: ItIsMrLaG Date: Mon, 24 Jul 2023 12:40:42 +0000 Subject: [PATCH 3/9] 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 d1c8ea8e240..10ff62a7ceb 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 e595257f620..7a02b1957b8 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; @@ -195,19 +223,6 @@ void raid_bdev_write_info_json(struct raid_bdev *raid_bdev, struct spdk_json_wri int raid_bdev_remove_base_bdev(struct spdk_bdev *base_bdev, raid_bdev_remove_base_bdev_cb cb_fn, void *cb_ctx); -/* -* 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 38de49340eb69c47ea6107284dbacd6315903a4b Mon Sep 17 00:00:00 2001 From: ItIsMrLaG Date: Sat, 16 Sep 2023 18:07:16 +0000 Subject: [PATCH 4/9] 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 10ff62a7ceb..be1d722000d 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 7a02b1957b8..e5526cc6f62 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 8fc78ee48285f38904ed9e3d88f5de36e707b745 Mon Sep 17 00:00:00 2001 From: juliakononov Date: Sun, 17 Sep 2023 21:52:23 +0000 Subject: [PATCH 5/9] 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 be1d722000d..847ce61411e 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 e5526cc6f62..21af090d3d9 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; }; /* @@ -223,7 +221,6 @@ void raid_bdev_write_info_json(struct raid_bdev *raid_bdev, struct spdk_json_wri int raid_bdev_remove_base_bdev(struct spdk_bdev *base_bdev, raid_bdev_remove_base_bdev_cb cb_fn, void *cb_ctx); - /* * 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 7d77fa8e69f5f91f3c90f9096515b41c0fd2ac3a Mon Sep 17 00:00:00 2001 From: juliakononov Date: Mon, 18 Dec 2023 03:04:28 +0000 Subject: [PATCH 6/9] 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 7915f2ab155c72340d806a5bc7200210c02317f5 Mon Sep 17 00:00:00 2001 From: juliakononov Date: Mon, 18 Dec 2023 03:05:50 +0000 Subject: [PATCH 7/9] 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 ad1de2d743e70c03ae1b1a3a08197068efcc4651 Mon Sep 17 00:00:00 2001 From: juliakononov Date: Mon, 18 Dec 2023 03:26:06 +0000 Subject: [PATCH 8/9] bdev/raid: Rewrite to atomics --- module/bdev/raid/bdev_raid.h | 11 ++++++----- module/bdev/raid/raid1.c | 22 +++------------------- 2 files changed, 9 insertions(+), 24 deletions(-) diff --git a/module/bdev/raid/bdev_raid.h b/module/bdev/raid/bdev_raid.h index 21af090d3d9..3c6e97d317c 100644 --- a/module/bdev/raid/bdev_raid.h +++ b/module/bdev/raid/bdev_raid.h @@ -10,13 +10,14 @@ #include "spdk/bdev_module.h" #include "spdk/uuid.h" +#include "atomic_raid.h" enum rebuild_flag { /* rebuild flag set during initialization */ - REBUILD_FLAG_INIT_CONFIGURATION = 0, - + REBUILD_FLAG_INIT_CONFIGURATION = 0UL, + /* if there is at least one broken area in rbm(rebuild_matrix) */ - REBUILD_FLAG_NEED_REBUILD = 1, + REBUILD_FLAG_NEED_REBUILD = 1UL, }; enum raid_level { @@ -58,7 +59,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]; + raid_atomic64 rebuild_matrix[MATRIX_REBUILD_SIZE]; /* number of memory areas */ uint64_t num_memory_areas; @@ -67,7 +68,7 @@ struct raid_rebuild { uint64_t strips_per_area; /* rebuild flag */ - uint64_t rebuild_flag; + raid_atomic64 rebuild_flag; }; /* diff --git a/module/bdev/raid/raid1.c b/module/bdev/raid/raid1.c index 4fb08cfbc4e..bd17b7bb119 100644 --- a/module/bdev/raid/raid1.c +++ b/module/bdev/raid/raid1.c @@ -55,29 +55,14 @@ static void write_in_rbm_broken_block(struct spdk_bdev_io *bdev_io, struct raid_bdev_io *raid_io, uint32_t bdev_idx) { + raid_atomic64_set(&raid_io->raid_bdev->rebuild->rebuild_flag, REBUILD_FLAG_NEED_REBUILD); 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]; - SPDK_SET_BIT(area, bdev_idx); - } -} - -/* Determine if a device needs a rebuild or not */ -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; - 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 (SPDK_TEST_BIT(&area, bdev_idx)) { - SPDK_SET_BIT(&(raid_bdev->rebuild->rebuild_flag), REBUILD_FLAG_NEED_REBUILD); - } + raid_atomic64 *area = &raid_io->raid_bdev->rebuild->rebuild_matrix[i]; + raid_atomic64_set_bit(area, bdev_idx); } } @@ -135,7 +120,6 @@ 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) { - get_bdev_rebuild_status(raid_bdev, bdev_io, idx); if (raid_bdev->rebuild->rebuild_flag != REBUILD_FLAG_INIT_CONFIGURATION) { break; } From 45863ab10d24e2d7a1f4ca89258e9b78809093e7 Mon Sep 17 00:00:00 2001 From: juliakononov Date: Thu, 21 Dec 2023 17:30:02 +0000 Subject: [PATCH 9/9] bdev/raid: fix work of atomics --- module/bdev/raid/atomic_raid.h | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/module/bdev/raid/atomic_raid.h b/module/bdev/raid/atomic_raid.h index fe818aac676..f4e2378f2d9 100644 --- a/module/bdev/raid/atomic_raid.h +++ b/module/bdev/raid/atomic_raid.h @@ -19,7 +19,9 @@ typedef uint64_t raid_atomic64; #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 +#define atomic_cmpxchg_bool __sync_bool_compare_and_swap +#define atomic_cmpxchg_val __sync_val_compare_and_swap + static inline uint64_t @@ -82,10 +84,16 @@ raid_atomic64_dec_return(raid_atomic64 *a) return raid_atomic64_sub_return(1, a); } +static inline bool +raid_atomic64_cmpxchg_bool(raid_atomic64 *a, uint64_t old_val, uint64_t new_val) +{ + return atomic_cmpxchg_bool(a, old_val, new_val); +} + static inline uint64_t -raid_atomic64_cmpxchg(raid_atomic64 *a, uint64_t old_val, uint64_t new_val) +raid_atomic64_cmpxchg_val(raid_atomic64 *a, uint64_t old_val, uint64_t new_val) { - return atomic_cmpxchg(a, old_val, new_val); + return atomic_cmpxchg_val(a, old_val, new_val); } static inline void @@ -98,7 +106,7 @@ raid_atomic64_set_bit(raid_atomic64 *atomic_ptr, uint64_t shift_size) 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)); + } while (raid_atomic64_cmpxchg_bool(atomic_ptr, old_val, new_val)); } static inline void @@ -111,7 +119,7 @@ raid_atomic64_remove_bit(raid_atomic64 *atomic_ptr, uint64_t shift_size) 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)); + } while (raid_atomic64_cmpxchg_bool(atomic_ptr, old_val, new_val)); } #endif /* SPDK_ATOMIC_RAID_INTERNAL_H */ \ No newline at end of file