ocf: adopt examine to asynchronous construct
Make examine work with asynchronous bdev startup.
We need to count references of bdevs that are being examined,
for the case when single cache bdev is referenced by multiple OCF
vbdevs.
The construct function is not in fact asynchronous yet,
but will be after adopting "trylock" API. Adopting trylock
requires a lot of changes, so this patch is really to split
implementation.
Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/450033 (master)
(cherry picked from commit ac2b06c809
)
Change-Id: I6ac091f2dd48462e74aa89cf54acb0306c30673b
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/457207
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
This commit is contained in:
parent
18a977f289
commit
d5aeeaf2f7
@ -53,6 +53,52 @@ static struct spdk_bdev_module ocf_if;
|
||||
static TAILQ_HEAD(, vbdev_ocf) g_ocf_vbdev_head
|
||||
= TAILQ_HEAD_INITIALIZER(g_ocf_vbdev_head);
|
||||
|
||||
static TAILQ_HEAD(, examining_bdev) g_ocf_examining_bdevs_head
|
||||
= TAILQ_HEAD_INITIALIZER(g_ocf_examining_bdevs_head);
|
||||
|
||||
/* Structure for keeping list of bdevs that are claimed but not used yet */
|
||||
struct examining_bdev {
|
||||
struct spdk_bdev *bdev;
|
||||
TAILQ_ENTRY(examining_bdev) tailq;
|
||||
};
|
||||
|
||||
/* Add bdev to list of claimed */
|
||||
static void
|
||||
examine_start(struct spdk_bdev *bdev)
|
||||
{
|
||||
struct examining_bdev *entry = malloc(sizeof(*entry));
|
||||
|
||||
assert(entry);
|
||||
entry->bdev = bdev;
|
||||
TAILQ_INSERT_TAIL(&g_ocf_examining_bdevs_head, entry, tailq);
|
||||
}
|
||||
|
||||
/* Find bdev on list of claimed bdevs, then remove it,
|
||||
* if it was the last one on list then report examine done */
|
||||
static void
|
||||
examine_done(int status, struct vbdev_ocf *vbdev, void *cb_arg)
|
||||
{
|
||||
struct spdk_bdev *bdev = cb_arg;
|
||||
struct examining_bdev *entry, *safe, *found = NULL;
|
||||
|
||||
TAILQ_FOREACH_SAFE(entry, &g_ocf_examining_bdevs_head, tailq, safe) {
|
||||
if (entry->bdev == bdev) {
|
||||
if (found) {
|
||||
goto remove;
|
||||
} else {
|
||||
found = entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert(found);
|
||||
spdk_bdev_module_examine_done(&ocf_if);
|
||||
|
||||
remove:
|
||||
TAILQ_REMOVE(&g_ocf_examining_bdevs_head, found, tailq);
|
||||
free(found);
|
||||
}
|
||||
|
||||
/* Free allocated strings and structure itself
|
||||
* Used at shutdown only */
|
||||
static void
|
||||
@ -731,25 +777,26 @@ io_device_destroy_cb(void *io_device, void *ctx_buf)
|
||||
}
|
||||
|
||||
/* Start OCF cache and register vbdev_ocf at bdev layer */
|
||||
static int
|
||||
register_vbdev(struct vbdev_ocf *vbdev)
|
||||
static void
|
||||
register_vbdev(struct vbdev_ocf *vbdev, void (*cb)(int, struct vbdev_ocf *, void *), void *cb_arg)
|
||||
{
|
||||
int result;
|
||||
|
||||
if (!vbdev->cache.attached || !vbdev->core.attached) {
|
||||
return -EPERM;
|
||||
if (!vbdev->cache.attached || !vbdev->core.attached || vbdev->state.started) {
|
||||
result = -EPERM;
|
||||
goto callback;
|
||||
}
|
||||
|
||||
result = start_cache(vbdev);
|
||||
if (result) {
|
||||
SPDK_ERRLOG("Failed to start cache instance\n");
|
||||
return result;
|
||||
goto callback;
|
||||
}
|
||||
|
||||
result = add_core(vbdev);
|
||||
if (result) {
|
||||
SPDK_ERRLOG("Failed to add core to cache instance\n");
|
||||
return result;
|
||||
goto callback;
|
||||
}
|
||||
|
||||
/* Create exported spdk object */
|
||||
@ -773,12 +820,13 @@ register_vbdev(struct vbdev_ocf *vbdev)
|
||||
result = spdk_bdev_register(&vbdev->exp_bdev);
|
||||
if (result) {
|
||||
SPDK_ERRLOG("Could not register exposed bdev\n");
|
||||
return result;
|
||||
goto callback;
|
||||
}
|
||||
|
||||
vbdev->state.started = true;
|
||||
|
||||
return result;
|
||||
callback:
|
||||
cb(result, vbdev, cb_arg);
|
||||
}
|
||||
|
||||
/* Init OCF configuration options
|
||||
@ -1042,12 +1090,11 @@ attach_base(struct vbdev_ocf_base *base)
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Attach base bdevs
|
||||
* If they attached, start vbdev
|
||||
* otherwise wait for them to appear at examine */
|
||||
/* Attach base bdevs */
|
||||
static int
|
||||
create_from_bdevs(struct vbdev_ocf *vbdev,
|
||||
struct spdk_bdev *cache_bdev, struct spdk_bdev *core_bdev)
|
||||
attach_base_bdevs(struct vbdev_ocf *vbdev,
|
||||
struct spdk_bdev *cache_bdev,
|
||||
struct spdk_bdev *core_bdev)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
@ -1061,10 +1108,6 @@ create_from_bdevs(struct vbdev_ocf *vbdev,
|
||||
rc |= attach_base(&vbdev->core);
|
||||
}
|
||||
|
||||
if (rc == 0 && vbdev->core.attached && vbdev->cache.attached) {
|
||||
rc = register_vbdev(vbdev);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -1103,14 +1146,22 @@ vbdev_ocf_construct(const char *vbdev_name,
|
||||
vbdev->name, core_name);
|
||||
}
|
||||
|
||||
rc = create_from_bdevs(vbdev, cache_bdev, core_bdev);
|
||||
cb(rc, vbdev, cb_arg);
|
||||
rc = attach_base_bdevs(vbdev, cache_bdev, core_bdev);
|
||||
if (rc) {
|
||||
cb(rc, vbdev, cb_arg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (core_bdev && cache_bdev) {
|
||||
register_vbdev(vbdev, cb, cb_arg);
|
||||
} else {
|
||||
cb(0, vbdev, cb_arg);
|
||||
}
|
||||
}
|
||||
|
||||
/* This called if new device is created in SPDK application
|
||||
* If that device named as one of base bdevs of cache_vbdev,
|
||||
* attach them
|
||||
* If last device attached here, vbdev starts here */
|
||||
* If that device named as one of base bdevs of OCF vbdev,
|
||||
* claim and open them */
|
||||
static void
|
||||
vbdev_ocf_examine(struct spdk_bdev *bdev)
|
||||
{
|
||||
@ -1123,17 +1174,49 @@ vbdev_ocf_examine(struct spdk_bdev *bdev)
|
||||
}
|
||||
|
||||
if (!strcmp(bdev_name, vbdev->cache.name)) {
|
||||
create_from_bdevs(vbdev, bdev, NULL);
|
||||
attach_base_bdevs(vbdev, bdev, NULL);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(bdev_name, vbdev->core.name)) {
|
||||
create_from_bdevs(vbdev, NULL, bdev);
|
||||
attach_base_bdevs(vbdev, NULL, bdev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
spdk_bdev_module_examine_done(&ocf_if);
|
||||
}
|
||||
|
||||
/* This is called after vbdev_ocf_examine
|
||||
* It allows to delay application initialization
|
||||
* until all OCF bdevs get registered
|
||||
* If vbdev has all of its base devices it starts asynchronously here */
|
||||
static void
|
||||
vbdev_ocf_examine_disk(struct spdk_bdev *bdev)
|
||||
{
|
||||
const char *bdev_name = spdk_bdev_get_name(bdev);
|
||||
struct vbdev_ocf *vbdev;
|
||||
|
||||
examine_start(bdev);
|
||||
|
||||
TAILQ_FOREACH(vbdev, &g_ocf_vbdev_head, tailq) {
|
||||
if (vbdev->state.doing_finish || vbdev->state.started) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(bdev_name, vbdev->cache.name)) {
|
||||
examine_start(bdev);
|
||||
register_vbdev(vbdev, examine_done, bdev);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(bdev_name, vbdev->core.name)) {
|
||||
examine_start(bdev);
|
||||
register_vbdev(vbdev, examine_done, bdev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
examine_done(0, NULL, bdev);
|
||||
}
|
||||
|
||||
static int
|
||||
vbdev_ocf_get_ctx_size(void)
|
||||
{
|
||||
@ -1150,6 +1233,7 @@ static struct spdk_bdev_module ocf_if = {
|
||||
.config_text = NULL,
|
||||
.get_ctx_size = vbdev_ocf_get_ctx_size,
|
||||
.examine_config = vbdev_ocf_examine,
|
||||
.examine_disk = vbdev_ocf_examine_disk,
|
||||
};
|
||||
SPDK_BDEV_MODULE_REGISTER(ocf, &ocf_if);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user