2022-11-28 14:35:25 +00:00
|
|
|
/* SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
* Copyright (C) 2022 Intel Corporation.
|
|
|
|
* All rights reserved.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "bdev_raid.h"
|
|
|
|
|
2022-12-19 09:47:41 +00:00
|
|
|
#include "spdk/likely.h"
|
2022-11-28 14:35:25 +00:00
|
|
|
#include "spdk/log.h"
|
|
|
|
|
|
|
|
struct raid1_info {
|
|
|
|
/* The parent raid bdev */
|
|
|
|
struct raid_bdev *raid_bdev;
|
|
|
|
};
|
|
|
|
|
2022-12-19 09:47:41 +00:00
|
|
|
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;
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void raid1_submit_rw_request(struct raid_bdev_io *raid_io);
|
|
|
|
|
|
|
|
static void
|
|
|
|
_raid1_submit_rw_request(void *_raid_io)
|
|
|
|
{
|
|
|
|
struct raid_bdev_io *raid_io = _raid_io;
|
|
|
|
|
|
|
|
raid1_submit_rw_request(raid_io);
|
|
|
|
}
|
|
|
|
|
bdev: remove spdk_bdev_ext_io_opts from spdk_bdev_io
The spdk_bdev_ext_io_opts structure is used to pass extra options when
submitting a bdev IO request, without having to modify/add functions to
handle new options. Additionally, the structure has a size field to
allow adding new fields without breaking the ABI (and thus having to
bump up the major version of a library).
It is also a part of spdk_bdev_io and there are several reasons for
removing it from that structure:
1. The size field only makes sense in structures that are passed
through pointers. And spdk_bdev_ext_io_opts is indeed passed as a
pointer to spdk_bdev_{readv,writev}_blocks_ext(), however it is
also embedded in spdk_bdev_io (internal.ext_opts_copy), which is
also part of the API. It means that each time a new field is added
to spdk_bdev_ext_io_opts, the size of spdk_bdev_io will also
change, so we will need to bump the major version of libspdk_bdev
anyway, thus making spdk_bdev_ext_io_opts.size useless.
2. The size field also makes internal.ext_opts cumbersome to use, as
each time one of its fields is accessed, we need to check the size.
Currently the code doesn't do that, because all of the existing
spdk_bdev_ext_io_opts fields were present when this structure was
initially introduced, but we'd need to do check the size before
accessing any new fields.
3. spdk_bdev_ext_io_opts has a metadata field, while spdk_bdev_io
already has u.bdev.md_buf, which means that we store the same thing
in several different places in spdk_bdev_io (u.bdev.md_buf,
u.bdev.ext_opts->metadata, internal.ext_opts->metadata).
Therefore, this patch removes all references to spdk_bdev_ext_io_opts
from spdk_bdev_io and replaces them with fields (memory_domain,
memory_domain_ctx) that were missing in spdk_bdev_io. Unfortunately,
this change breaks the API and requires changes in bdev modules that
supported spdk_bdev_io.u.bdev.ext_opts.
Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com>
Change-Id: I49b7524eb84d1d4d7f12b7ab025fec36da1ee01f
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16773
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
2023-02-10 15:22:51 +00:00
|
|
|
static void
|
|
|
|
raid1_init_ext_io_opts(struct spdk_bdev_io *bdev_io, struct spdk_bdev_ext_io_opts *opts)
|
|
|
|
{
|
|
|
|
memset(opts, 0, sizeof(*opts));
|
|
|
|
opts->size = sizeof(*opts);
|
|
|
|
opts->memory_domain = bdev_io->u.bdev.memory_domain;
|
|
|
|
opts->memory_domain_ctx = bdev_io->u.bdev.memory_domain_ctx;
|
|
|
|
opts->metadata = bdev_io->u.bdev.md_buf;
|
|
|
|
}
|
|
|
|
|
2022-12-19 09:47:41 +00:00
|
|
|
static int
|
|
|
|
raid1_submit_read_request(struct raid_bdev_io *raid_io)
|
|
|
|
{
|
|
|
|
struct raid_bdev *raid_bdev = raid_io->raid_bdev;
|
|
|
|
struct spdk_bdev_io *bdev_io = spdk_bdev_io_from_ctx(raid_io);
|
bdev: remove spdk_bdev_ext_io_opts from spdk_bdev_io
The spdk_bdev_ext_io_opts structure is used to pass extra options when
submitting a bdev IO request, without having to modify/add functions to
handle new options. Additionally, the structure has a size field to
allow adding new fields without breaking the ABI (and thus having to
bump up the major version of a library).
It is also a part of spdk_bdev_io and there are several reasons for
removing it from that structure:
1. The size field only makes sense in structures that are passed
through pointers. And spdk_bdev_ext_io_opts is indeed passed as a
pointer to spdk_bdev_{readv,writev}_blocks_ext(), however it is
also embedded in spdk_bdev_io (internal.ext_opts_copy), which is
also part of the API. It means that each time a new field is added
to spdk_bdev_ext_io_opts, the size of spdk_bdev_io will also
change, so we will need to bump the major version of libspdk_bdev
anyway, thus making spdk_bdev_ext_io_opts.size useless.
2. The size field also makes internal.ext_opts cumbersome to use, as
each time one of its fields is accessed, we need to check the size.
Currently the code doesn't do that, because all of the existing
spdk_bdev_ext_io_opts fields were present when this structure was
initially introduced, but we'd need to do check the size before
accessing any new fields.
3. spdk_bdev_ext_io_opts has a metadata field, while spdk_bdev_io
already has u.bdev.md_buf, which means that we store the same thing
in several different places in spdk_bdev_io (u.bdev.md_buf,
u.bdev.ext_opts->metadata, internal.ext_opts->metadata).
Therefore, this patch removes all references to spdk_bdev_ext_io_opts
from spdk_bdev_io and replaces them with fields (memory_domain,
memory_domain_ctx) that were missing in spdk_bdev_io. Unfortunately,
this change breaks the API and requires changes in bdev modules that
supported spdk_bdev_io.u.bdev.ext_opts.
Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com>
Change-Id: I49b7524eb84d1d4d7f12b7ab025fec36da1ee01f
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16773
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
2023-02-10 15:22:51 +00:00
|
|
|
struct spdk_bdev_ext_io_opts io_opts;
|
2022-12-19 09:47:41 +00:00
|
|
|
uint8_t ch_idx = 0;
|
|
|
|
struct raid_base_bdev_info *base_info = &raid_bdev->base_bdev_info[ch_idx];
|
|
|
|
struct spdk_io_channel *base_ch = raid_io->raid_ch->base_channel[ch_idx];
|
|
|
|
uint64_t pd_lba, pd_blocks;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
pd_lba = bdev_io->u.bdev.offset_blocks;
|
|
|
|
pd_blocks = bdev_io->u.bdev.num_blocks;
|
|
|
|
|
|
|
|
raid_io->base_bdev_io_remaining = 1;
|
|
|
|
|
bdev: remove spdk_bdev_ext_io_opts from spdk_bdev_io
The spdk_bdev_ext_io_opts structure is used to pass extra options when
submitting a bdev IO request, without having to modify/add functions to
handle new options. Additionally, the structure has a size field to
allow adding new fields without breaking the ABI (and thus having to
bump up the major version of a library).
It is also a part of spdk_bdev_io and there are several reasons for
removing it from that structure:
1. The size field only makes sense in structures that are passed
through pointers. And spdk_bdev_ext_io_opts is indeed passed as a
pointer to spdk_bdev_{readv,writev}_blocks_ext(), however it is
also embedded in spdk_bdev_io (internal.ext_opts_copy), which is
also part of the API. It means that each time a new field is added
to spdk_bdev_ext_io_opts, the size of spdk_bdev_io will also
change, so we will need to bump the major version of libspdk_bdev
anyway, thus making spdk_bdev_ext_io_opts.size useless.
2. The size field also makes internal.ext_opts cumbersome to use, as
each time one of its fields is accessed, we need to check the size.
Currently the code doesn't do that, because all of the existing
spdk_bdev_ext_io_opts fields were present when this structure was
initially introduced, but we'd need to do check the size before
accessing any new fields.
3. spdk_bdev_ext_io_opts has a metadata field, while spdk_bdev_io
already has u.bdev.md_buf, which means that we store the same thing
in several different places in spdk_bdev_io (u.bdev.md_buf,
u.bdev.ext_opts->metadata, internal.ext_opts->metadata).
Therefore, this patch removes all references to spdk_bdev_ext_io_opts
from spdk_bdev_io and replaces them with fields (memory_domain,
memory_domain_ctx) that were missing in spdk_bdev_io. Unfortunately,
this change breaks the API and requires changes in bdev modules that
supported spdk_bdev_io.u.bdev.ext_opts.
Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com>
Change-Id: I49b7524eb84d1d4d7f12b7ab025fec36da1ee01f
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16773
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
2023-02-10 15:22:51 +00:00
|
|
|
raid1_init_ext_io_opts(bdev_io, &io_opts);
|
|
|
|
ret = spdk_bdev_readv_blocks_ext(base_info->desc, base_ch,
|
|
|
|
bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt,
|
|
|
|
pd_lba, pd_blocks, raid1_bdev_io_completion,
|
|
|
|
raid_io, &io_opts);
|
2022-12-19 09:47:41 +00:00
|
|
|
|
|
|
|
if (spdk_likely(ret == 0)) {
|
|
|
|
raid_io->base_bdev_io_submitted++;
|
|
|
|
} else if (spdk_unlikely(ret == -ENOMEM)) {
|
|
|
|
raid_bdev_queue_io_wait(raid_io, base_info->bdev, base_ch,
|
|
|
|
_raid1_submit_rw_request);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
raid1_submit_write_request(struct raid_bdev_io *raid_io)
|
|
|
|
{
|
|
|
|
struct raid_bdev *raid_bdev = raid_io->raid_bdev;
|
|
|
|
struct spdk_bdev_io *bdev_io = spdk_bdev_io_from_ctx(raid_io);
|
bdev: remove spdk_bdev_ext_io_opts from spdk_bdev_io
The spdk_bdev_ext_io_opts structure is used to pass extra options when
submitting a bdev IO request, without having to modify/add functions to
handle new options. Additionally, the structure has a size field to
allow adding new fields without breaking the ABI (and thus having to
bump up the major version of a library).
It is also a part of spdk_bdev_io and there are several reasons for
removing it from that structure:
1. The size field only makes sense in structures that are passed
through pointers. And spdk_bdev_ext_io_opts is indeed passed as a
pointer to spdk_bdev_{readv,writev}_blocks_ext(), however it is
also embedded in spdk_bdev_io (internal.ext_opts_copy), which is
also part of the API. It means that each time a new field is added
to spdk_bdev_ext_io_opts, the size of spdk_bdev_io will also
change, so we will need to bump the major version of libspdk_bdev
anyway, thus making spdk_bdev_ext_io_opts.size useless.
2. The size field also makes internal.ext_opts cumbersome to use, as
each time one of its fields is accessed, we need to check the size.
Currently the code doesn't do that, because all of the existing
spdk_bdev_ext_io_opts fields were present when this structure was
initially introduced, but we'd need to do check the size before
accessing any new fields.
3. spdk_bdev_ext_io_opts has a metadata field, while spdk_bdev_io
already has u.bdev.md_buf, which means that we store the same thing
in several different places in spdk_bdev_io (u.bdev.md_buf,
u.bdev.ext_opts->metadata, internal.ext_opts->metadata).
Therefore, this patch removes all references to spdk_bdev_ext_io_opts
from spdk_bdev_io and replaces them with fields (memory_domain,
memory_domain_ctx) that were missing in spdk_bdev_io. Unfortunately,
this change breaks the API and requires changes in bdev modules that
supported spdk_bdev_io.u.bdev.ext_opts.
Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com>
Change-Id: I49b7524eb84d1d4d7f12b7ab025fec36da1ee01f
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16773
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
2023-02-10 15:22:51 +00:00
|
|
|
struct spdk_bdev_ext_io_opts io_opts;
|
2022-12-19 09:47:41 +00:00
|
|
|
struct raid_base_bdev_info *base_info;
|
|
|
|
struct spdk_io_channel *base_ch;
|
|
|
|
uint64_t pd_lba, pd_blocks;
|
|
|
|
uint16_t idx = raid_io->base_bdev_io_submitted;
|
|
|
|
uint64_t base_bdev_io_not_submitted;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
pd_lba = bdev_io->u.bdev.offset_blocks;
|
|
|
|
pd_blocks = bdev_io->u.bdev.num_blocks;
|
|
|
|
|
|
|
|
if (raid_io->base_bdev_io_submitted == 0) {
|
|
|
|
raid_io->base_bdev_io_remaining = raid_bdev->num_base_bdevs;
|
|
|
|
}
|
|
|
|
|
bdev: remove spdk_bdev_ext_io_opts from spdk_bdev_io
The spdk_bdev_ext_io_opts structure is used to pass extra options when
submitting a bdev IO request, without having to modify/add functions to
handle new options. Additionally, the structure has a size field to
allow adding new fields without breaking the ABI (and thus having to
bump up the major version of a library).
It is also a part of spdk_bdev_io and there are several reasons for
removing it from that structure:
1. The size field only makes sense in structures that are passed
through pointers. And spdk_bdev_ext_io_opts is indeed passed as a
pointer to spdk_bdev_{readv,writev}_blocks_ext(), however it is
also embedded in spdk_bdev_io (internal.ext_opts_copy), which is
also part of the API. It means that each time a new field is added
to spdk_bdev_ext_io_opts, the size of spdk_bdev_io will also
change, so we will need to bump the major version of libspdk_bdev
anyway, thus making spdk_bdev_ext_io_opts.size useless.
2. The size field also makes internal.ext_opts cumbersome to use, as
each time one of its fields is accessed, we need to check the size.
Currently the code doesn't do that, because all of the existing
spdk_bdev_ext_io_opts fields were present when this structure was
initially introduced, but we'd need to do check the size before
accessing any new fields.
3. spdk_bdev_ext_io_opts has a metadata field, while spdk_bdev_io
already has u.bdev.md_buf, which means that we store the same thing
in several different places in spdk_bdev_io (u.bdev.md_buf,
u.bdev.ext_opts->metadata, internal.ext_opts->metadata).
Therefore, this patch removes all references to spdk_bdev_ext_io_opts
from spdk_bdev_io and replaces them with fields (memory_domain,
memory_domain_ctx) that were missing in spdk_bdev_io. Unfortunately,
this change breaks the API and requires changes in bdev modules that
supported spdk_bdev_io.u.bdev.ext_opts.
Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com>
Change-Id: I49b7524eb84d1d4d7f12b7ab025fec36da1ee01f
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16773
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
2023-02-10 15:22:51 +00:00
|
|
|
raid1_init_ext_io_opts(bdev_io, &io_opts);
|
2022-12-19 09:47:41 +00:00
|
|
|
for (; idx < raid_bdev->num_base_bdevs; idx++) {
|
|
|
|
base_info = &raid_bdev->base_bdev_info[idx];
|
|
|
|
base_ch = raid_io->raid_ch->base_channel[idx];
|
|
|
|
|
bdev: remove spdk_bdev_ext_io_opts from spdk_bdev_io
The spdk_bdev_ext_io_opts structure is used to pass extra options when
submitting a bdev IO request, without having to modify/add functions to
handle new options. Additionally, the structure has a size field to
allow adding new fields without breaking the ABI (and thus having to
bump up the major version of a library).
It is also a part of spdk_bdev_io and there are several reasons for
removing it from that structure:
1. The size field only makes sense in structures that are passed
through pointers. And spdk_bdev_ext_io_opts is indeed passed as a
pointer to spdk_bdev_{readv,writev}_blocks_ext(), however it is
also embedded in spdk_bdev_io (internal.ext_opts_copy), which is
also part of the API. It means that each time a new field is added
to spdk_bdev_ext_io_opts, the size of spdk_bdev_io will also
change, so we will need to bump the major version of libspdk_bdev
anyway, thus making spdk_bdev_ext_io_opts.size useless.
2. The size field also makes internal.ext_opts cumbersome to use, as
each time one of its fields is accessed, we need to check the size.
Currently the code doesn't do that, because all of the existing
spdk_bdev_ext_io_opts fields were present when this structure was
initially introduced, but we'd need to do check the size before
accessing any new fields.
3. spdk_bdev_ext_io_opts has a metadata field, while spdk_bdev_io
already has u.bdev.md_buf, which means that we store the same thing
in several different places in spdk_bdev_io (u.bdev.md_buf,
u.bdev.ext_opts->metadata, internal.ext_opts->metadata).
Therefore, this patch removes all references to spdk_bdev_ext_io_opts
from spdk_bdev_io and replaces them with fields (memory_domain,
memory_domain_ctx) that were missing in spdk_bdev_io. Unfortunately,
this change breaks the API and requires changes in bdev modules that
supported spdk_bdev_io.u.bdev.ext_opts.
Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com>
Change-Id: I49b7524eb84d1d4d7f12b7ab025fec36da1ee01f
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16773
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
2023-02-10 15:22:51 +00:00
|
|
|
ret = spdk_bdev_writev_blocks_ext(base_info->desc, base_ch,
|
|
|
|
bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt,
|
|
|
|
pd_lba, pd_blocks, raid1_bdev_io_completion,
|
|
|
|
raid_io, &io_opts);
|
2022-12-19 09:47:41 +00:00
|
|
|
if (spdk_unlikely(ret != 0)) {
|
|
|
|
if (spdk_unlikely(ret == -ENOMEM)) {
|
|
|
|
raid_bdev_queue_io_wait(raid_io, base_info->bdev, base_ch,
|
|
|
|
_raid1_submit_rw_request);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
base_bdev_io_not_submitted = raid_bdev->num_base_bdevs -
|
|
|
|
raid_io->base_bdev_io_submitted;
|
|
|
|
raid_bdev_io_complete_part(raid_io, base_bdev_io_not_submitted,
|
|
|
|
SPDK_BDEV_IO_STATUS_FAILED);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
raid_io->base_bdev_io_submitted++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-11-28 14:35:25 +00:00
|
|
|
static void
|
|
|
|
raid1_submit_rw_request(struct raid_bdev_io *raid_io)
|
|
|
|
{
|
2022-12-19 09:47:41 +00:00
|
|
|
struct spdk_bdev_io *bdev_io = spdk_bdev_io_from_ctx(raid_io);
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
switch (bdev_io->type) {
|
|
|
|
case SPDK_BDEV_IO_TYPE_READ:
|
|
|
|
ret = raid1_submit_read_request(raid_io);
|
|
|
|
break;
|
|
|
|
case SPDK_BDEV_IO_TYPE_WRITE:
|
|
|
|
ret = raid1_submit_write_request(raid_io);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ret = -EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (spdk_unlikely(ret != 0)) {
|
|
|
|
raid_bdev_io_complete(raid_io, SPDK_BDEV_IO_STATUS_FAILED);
|
|
|
|
}
|
2022-11-28 14:35:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
raid1_start(struct raid_bdev *raid_bdev)
|
|
|
|
{
|
|
|
|
uint64_t min_blockcnt = UINT64_MAX;
|
|
|
|
struct raid_base_bdev_info *base_info;
|
|
|
|
struct raid1_info *r1info;
|
|
|
|
|
|
|
|
r1info = calloc(1, sizeof(*r1info));
|
|
|
|
if (!r1info) {
|
|
|
|
SPDK_ERRLOG("Failed to allocate RAID1 info device structure\n");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
r1info->raid_bdev = raid_bdev;
|
|
|
|
|
|
|
|
RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
|
|
|
|
min_blockcnt = spdk_min(min_blockcnt, base_info->bdev->blockcnt);
|
|
|
|
}
|
|
|
|
|
|
|
|
raid_bdev->bdev.blockcnt = min_blockcnt;
|
|
|
|
raid_bdev->module_private = r1info;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
raid1_stop(struct raid_bdev *raid_bdev)
|
|
|
|
{
|
|
|
|
struct raid1_info *r1info = raid_bdev->module_private;
|
|
|
|
|
|
|
|
free(r1info);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct raid_bdev_module g_raid1_module = {
|
|
|
|
.level = RAID1,
|
|
|
|
.base_bdevs_min = 2,
|
|
|
|
.base_bdevs_constraint = {CONSTRAINT_MIN_BASE_BDEVS_OPERATIONAL, 1},
|
|
|
|
.start = raid1_start,
|
|
|
|
.stop = raid1_stop,
|
|
|
|
.submit_rw_request = raid1_submit_rw_request,
|
|
|
|
};
|
|
|
|
RAID_MODULE_REGISTER(&g_raid1_module)
|
|
|
|
|
|
|
|
SPDK_LOG_REGISTER_COMPONENT(bdev_raid1)
|