2016-09-20 04:12:45 +00:00
|
|
|
/*-
|
|
|
|
* BSD LICENSE
|
|
|
|
*
|
|
|
|
* Copyright (c) Intel Corporation.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
*
|
|
|
|
* * Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in
|
|
|
|
* the documentation and/or other materials provided with the
|
|
|
|
* distribution.
|
|
|
|
* * Neither the name of Intel Corporation nor the names of its
|
|
|
|
* contributors may be used to endorse or promote products derived
|
|
|
|
* from this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2017-05-02 18:18:25 +00:00
|
|
|
#include "spdk/stdinc.h"
|
|
|
|
|
2017-07-13 04:08:53 +00:00
|
|
|
#include "bdev_rbd.h"
|
2016-10-10 01:01:47 +00:00
|
|
|
|
2016-09-20 04:12:45 +00:00
|
|
|
#include <rbd/librbd.h>
|
|
|
|
#include <rados/librados.h>
|
|
|
|
|
2016-11-07 17:08:11 +00:00
|
|
|
#include "spdk/env.h"
|
2016-09-20 04:12:45 +00:00
|
|
|
#include "spdk/bdev.h"
|
2018-06-11 20:32:15 +00:00
|
|
|
#include "spdk/thread.h"
|
2017-08-09 00:54:26 +00:00
|
|
|
#include "spdk/json.h"
|
2017-06-02 17:25:43 +00:00
|
|
|
#include "spdk/string.h"
|
2017-10-13 00:20:10 +00:00
|
|
|
#include "spdk/util.h"
|
2020-09-09 15:38:46 +00:00
|
|
|
#include "spdk/likely.h"
|
2016-09-20 04:12:45 +00:00
|
|
|
|
2018-05-23 21:01:03 +00:00
|
|
|
#include "spdk/bdev_module.h"
|
2020-10-06 16:16:26 +00:00
|
|
|
#include "spdk/log.h"
|
2016-09-20 04:12:45 +00:00
|
|
|
|
2017-07-13 04:08:53 +00:00
|
|
|
static int bdev_rbd_count = 0;
|
2016-09-20 04:12:45 +00:00
|
|
|
|
2017-07-13 04:08:53 +00:00
|
|
|
struct bdev_rbd {
|
2016-09-20 04:12:45 +00:00
|
|
|
struct spdk_bdev disk;
|
2016-10-14 11:17:54 +00:00
|
|
|
char *rbd_name;
|
2018-10-26 12:06:15 +00:00
|
|
|
char *user_id;
|
2016-11-08 18:25:29 +00:00
|
|
|
char *pool_name;
|
2018-10-26 12:06:15 +00:00
|
|
|
char **config;
|
2021-03-09 16:50:21 +00:00
|
|
|
|
2021-04-23 12:30:43 +00:00
|
|
|
rados_t cluster;
|
2021-04-22 13:51:42 +00:00
|
|
|
rados_t *cluster_p;
|
|
|
|
char *cluster_name;
|
2021-03-09 16:50:21 +00:00
|
|
|
|
|
|
|
rados_ioctx_t io_ctx;
|
|
|
|
rbd_image_t image;
|
|
|
|
|
2016-09-20 04:12:45 +00:00
|
|
|
rbd_image_info_t info;
|
2021-03-09 16:50:21 +00:00
|
|
|
pthread_mutex_t mutex;
|
|
|
|
struct spdk_thread *main_td;
|
2021-08-06 14:19:27 +00:00
|
|
|
struct spdk_thread *destruct_td;
|
2021-03-09 16:50:21 +00:00
|
|
|
uint32_t ch_count;
|
2021-08-30 15:53:54 +00:00
|
|
|
struct spdk_io_channel *group_ch;
|
2021-03-09 16:50:21 +00:00
|
|
|
|
2017-07-13 04:08:53 +00:00
|
|
|
TAILQ_ENTRY(bdev_rbd) tailq;
|
2018-02-23 23:51:20 +00:00
|
|
|
struct spdk_poller *reset_timer;
|
|
|
|
struct spdk_bdev_io *reset_bdev_io;
|
2016-09-20 04:12:45 +00:00
|
|
|
};
|
|
|
|
|
2017-07-13 04:08:53 +00:00
|
|
|
struct bdev_rbd_io_channel {
|
|
|
|
struct bdev_rbd *disk;
|
2016-09-20 04:12:45 +00:00
|
|
|
};
|
|
|
|
|
2017-10-13 00:20:10 +00:00
|
|
|
struct bdev_rbd_io {
|
2021-08-30 15:53:54 +00:00
|
|
|
struct spdk_thread *submit_td;
|
|
|
|
enum spdk_bdev_io_status status;
|
|
|
|
rbd_completion_t comp;
|
|
|
|
size_t total_len;
|
2017-10-13 00:20:10 +00:00
|
|
|
};
|
|
|
|
|
2021-04-21 12:58:01 +00:00
|
|
|
struct bdev_rbd_cluster {
|
|
|
|
char *name;
|
|
|
|
char *user_id;
|
|
|
|
char **config_param;
|
|
|
|
char *config_file;
|
2021-12-01 09:13:32 +00:00
|
|
|
char *key_file;
|
2021-04-21 12:58:01 +00:00
|
|
|
rados_t cluster;
|
|
|
|
uint32_t ref;
|
|
|
|
STAILQ_ENTRY(bdev_rbd_cluster) link;
|
|
|
|
};
|
|
|
|
|
|
|
|
static STAILQ_HEAD(, bdev_rbd_cluster) g_map_bdev_rbd_cluster = STAILQ_HEAD_INITIALIZER(
|
|
|
|
g_map_bdev_rbd_cluster);
|
|
|
|
static pthread_mutex_t g_map_bdev_rbd_cluster_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
|
|
|
|
static void
|
|
|
|
bdev_rbd_cluster_free(struct bdev_rbd_cluster *entry)
|
|
|
|
{
|
|
|
|
assert(entry != NULL);
|
|
|
|
|
|
|
|
bdev_rbd_free_config(entry->config_param);
|
|
|
|
free(entry->config_file);
|
2021-12-01 09:13:32 +00:00
|
|
|
free(entry->key_file);
|
2021-04-21 12:58:01 +00:00
|
|
|
free(entry->user_id);
|
|
|
|
free(entry->name);
|
|
|
|
free(entry);
|
|
|
|
}
|
|
|
|
|
2016-10-14 11:17:54 +00:00
|
|
|
static void
|
2021-04-22 13:51:42 +00:00
|
|
|
bdev_rbd_put_cluster(rados_t **cluster)
|
2016-10-14 11:17:54 +00:00
|
|
|
{
|
2021-04-22 13:51:42 +00:00
|
|
|
struct bdev_rbd_cluster *entry;
|
|
|
|
|
|
|
|
assert(cluster != NULL);
|
|
|
|
|
|
|
|
/* No need go through the map if *cluster equals to NULL */
|
|
|
|
if (*cluster == NULL) {
|
2016-10-14 11:17:54 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-04-22 13:51:42 +00:00
|
|
|
pthread_mutex_lock(&g_map_bdev_rbd_cluster_mutex);
|
|
|
|
STAILQ_FOREACH(entry, &g_map_bdev_rbd_cluster, link) {
|
|
|
|
if (*cluster != &entry->cluster) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(entry->ref > 0);
|
|
|
|
entry->ref--;
|
|
|
|
*cluster = NULL;
|
|
|
|
pthread_mutex_unlock(&g_map_bdev_rbd_cluster_mutex);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pthread_mutex_unlock(&g_map_bdev_rbd_cluster_mutex);
|
|
|
|
SPDK_ERRLOG("Cannot find the entry for cluster=%p\n", cluster);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bdev_rbd_free(struct bdev_rbd *rbd)
|
|
|
|
{
|
|
|
|
if (!rbd) {
|
|
|
|
return;
|
2021-04-23 12:30:43 +00:00
|
|
|
}
|
|
|
|
|
2017-06-02 17:25:43 +00:00
|
|
|
free(rbd->disk.name);
|
2016-10-14 11:17:54 +00:00
|
|
|
free(rbd->rbd_name);
|
2018-10-26 12:06:15 +00:00
|
|
|
free(rbd->user_id);
|
2016-11-08 18:25:29 +00:00
|
|
|
free(rbd->pool_name);
|
2020-05-10 08:14:45 +00:00
|
|
|
bdev_rbd_free_config(rbd->config);
|
2021-04-22 13:51:42 +00:00
|
|
|
|
2021-03-09 16:50:21 +00:00
|
|
|
if (rbd->io_ctx) {
|
|
|
|
rados_ioctx_destroy(rbd->io_ctx);
|
|
|
|
}
|
|
|
|
|
2021-04-22 13:51:42 +00:00
|
|
|
if (rbd->cluster_name) {
|
|
|
|
bdev_rbd_put_cluster(&rbd->cluster_p);
|
|
|
|
free(rbd->cluster_name);
|
|
|
|
} else if (rbd->cluster) {
|
|
|
|
rados_shutdown(rbd->cluster);
|
|
|
|
}
|
|
|
|
|
2021-03-09 16:50:21 +00:00
|
|
|
pthread_mutex_destroy(&rbd->mutex);
|
2016-10-14 11:17:54 +00:00
|
|
|
free(rbd);
|
|
|
|
}
|
|
|
|
|
2018-10-26 12:06:15 +00:00
|
|
|
void
|
2020-05-10 08:14:45 +00:00
|
|
|
bdev_rbd_free_config(char **config)
|
2018-10-26 12:06:15 +00:00
|
|
|
{
|
|
|
|
char **entry;
|
|
|
|
|
|
|
|
if (config) {
|
|
|
|
for (entry = config; *entry; entry++) {
|
|
|
|
free(*entry);
|
|
|
|
}
|
|
|
|
free(config);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
char **
|
2020-05-10 08:14:45 +00:00
|
|
|
bdev_rbd_dup_config(const char *const *config)
|
2018-10-26 12:06:15 +00:00
|
|
|
{
|
|
|
|
size_t count;
|
|
|
|
char **copy;
|
|
|
|
|
|
|
|
if (!config) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
for (count = 0; config[count]; count++) {}
|
|
|
|
copy = calloc(count + 1, sizeof(*copy));
|
|
|
|
if (!copy) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
for (count = 0; config[count]; count++) {
|
|
|
|
if (!(copy[count] = strdup(config[count]))) {
|
2020-05-10 08:14:45 +00:00
|
|
|
bdev_rbd_free_config(copy);
|
2018-10-26 12:06:15 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return copy;
|
|
|
|
}
|
|
|
|
|
2016-09-20 04:12:45 +00:00
|
|
|
static int
|
2021-04-23 12:30:43 +00:00
|
|
|
bdev_rados_cluster_init(const char *user_id, const char *const *config,
|
|
|
|
rados_t *cluster)
|
2016-09-20 04:12:45 +00:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
2018-10-26 12:06:15 +00:00
|
|
|
ret = rados_create(cluster, user_id);
|
2016-09-20 04:12:45 +00:00
|
|
|
if (ret < 0) {
|
|
|
|
SPDK_ERRLOG("Failed to create rados_t struct\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2018-10-26 12:06:15 +00:00
|
|
|
if (config) {
|
|
|
|
const char *const *entry = config;
|
|
|
|
while (*entry) {
|
|
|
|
ret = rados_conf_set(*cluster, entry[0], entry[1]);
|
|
|
|
if (ret < 0) {
|
|
|
|
SPDK_ERRLOG("Failed to set %s = %s\n", entry[0], entry[1]);
|
|
|
|
rados_shutdown(*cluster);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
entry += 2;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ret = rados_conf_read_file(*cluster, NULL);
|
|
|
|
if (ret < 0) {
|
|
|
|
SPDK_ERRLOG("Failed to read conf file\n");
|
|
|
|
rados_shutdown(*cluster);
|
|
|
|
return -1;
|
|
|
|
}
|
2016-09-20 04:12:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ret = rados_connect(*cluster);
|
|
|
|
if (ret < 0) {
|
2018-10-24 07:46:12 +00:00
|
|
|
SPDK_ERRLOG("Failed to connect to rbd_pool\n");
|
2016-09-20 04:12:45 +00:00
|
|
|
rados_shutdown(*cluster);
|
2018-10-24 07:46:12 +00:00
|
|
|
return -1;
|
2016-09-20 04:12:45 +00:00
|
|
|
}
|
|
|
|
|
2021-04-23 12:30:43 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2016-09-20 04:12:45 +00:00
|
|
|
|
2021-04-22 13:51:42 +00:00
|
|
|
static int
|
|
|
|
bdev_rbd_get_cluster(const char *cluster_name, rados_t **cluster)
|
|
|
|
{
|
|
|
|
struct bdev_rbd_cluster *entry;
|
|
|
|
|
|
|
|
if (cluster == NULL) {
|
|
|
|
SPDK_ERRLOG("cluster should not be NULL\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
pthread_mutex_lock(&g_map_bdev_rbd_cluster_mutex);
|
|
|
|
STAILQ_FOREACH(entry, &g_map_bdev_rbd_cluster, link) {
|
2021-05-21 16:14:28 +00:00
|
|
|
if (strcmp(cluster_name, entry->name) == 0) {
|
2021-04-22 13:51:42 +00:00
|
|
|
entry->ref++;
|
|
|
|
*cluster = &entry->cluster;
|
|
|
|
pthread_mutex_unlock(&g_map_bdev_rbd_cluster_mutex);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pthread_mutex_unlock(&g_map_bdev_rbd_cluster_mutex);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
bdev_rbd_shared_cluster_init(const char *cluster_name, rados_t **cluster)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = bdev_rbd_get_cluster(cluster_name, cluster);
|
|
|
|
if (ret < 0) {
|
|
|
|
SPDK_ERRLOG("Failed to create rados_t struct\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2021-04-23 12:30:43 +00:00
|
|
|
static void *
|
|
|
|
bdev_rbd_cluster_handle(void *arg)
|
|
|
|
{
|
|
|
|
void *ret = arg;
|
2021-04-22 13:51:42 +00:00
|
|
|
struct bdev_rbd *rbd = arg;
|
2021-04-23 12:30:43 +00:00
|
|
|
int rc;
|
|
|
|
|
|
|
|
rc = bdev_rados_cluster_init(rbd->user_id, (const char *const *)rbd->config,
|
|
|
|
&rbd->cluster);
|
|
|
|
if (rc < 0) {
|
|
|
|
SPDK_ERRLOG("Failed to create rados cluster for user_id=%s and rbd_pool=%s\n",
|
|
|
|
rbd->user_id ? rbd->user_id : "admin (the default)", rbd->pool_name);
|
|
|
|
ret = NULL;
|
2016-09-20 04:12:45 +00:00
|
|
|
}
|
|
|
|
|
2021-04-23 12:30:43 +00:00
|
|
|
return ret;
|
2016-09-20 04:12:45 +00:00
|
|
|
}
|
|
|
|
|
2021-03-09 16:50:21 +00:00
|
|
|
static void *
|
|
|
|
bdev_rbd_init_context(void *arg)
|
|
|
|
{
|
|
|
|
struct bdev_rbd *rbd = arg;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
if (rados_ioctx_create(*(rbd->cluster_p), rbd->pool_name, &rbd->io_ctx) < 0) {
|
|
|
|
SPDK_ERRLOG("Failed to create ioctx on rbd=%p\n", rbd);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = rbd_open(rbd->io_ctx, rbd->rbd_name, &rbd->image, NULL);
|
|
|
|
if (rc < 0) {
|
|
|
|
SPDK_ERRLOG("Failed to open specified rbd device\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = rbd_stat(rbd->image, &rbd->info, sizeof(rbd->info));
|
|
|
|
rbd_close(rbd->image);
|
|
|
|
if (rc < 0) {
|
|
|
|
SPDK_ERRLOG("Failed to stat specified rbd device\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return arg;
|
|
|
|
}
|
|
|
|
|
2016-09-20 04:12:45 +00:00
|
|
|
static int
|
2021-04-22 13:36:03 +00:00
|
|
|
bdev_rbd_init(struct bdev_rbd *rbd)
|
2016-09-20 04:12:45 +00:00
|
|
|
{
|
2021-04-16 15:57:24 +00:00
|
|
|
int ret = 0;
|
2016-09-20 04:12:45 +00:00
|
|
|
|
2021-04-22 13:51:42 +00:00
|
|
|
if (!rbd->cluster_name) {
|
|
|
|
rbd->cluster_p = &rbd->cluster;
|
|
|
|
/* Cluster should be created in non-SPDK thread to avoid conflict between
|
|
|
|
* Rados and SPDK thread */
|
|
|
|
if (spdk_call_unaffinitized(bdev_rbd_cluster_handle, rbd) == NULL) {
|
|
|
|
SPDK_ERRLOG("Cannot create the rados object on rbd=%p\n", rbd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ret = bdev_rbd_shared_cluster_init(rbd->cluster_name, &rbd->cluster_p);
|
|
|
|
if (ret < 0) {
|
|
|
|
SPDK_ERRLOG("Failed to create rados object for rbd =%p on cluster_name=%s\n",
|
|
|
|
rbd, rbd->cluster_name);
|
|
|
|
return -1;
|
|
|
|
}
|
2021-04-23 12:30:43 +00:00
|
|
|
}
|
|
|
|
|
2021-03-09 16:50:21 +00:00
|
|
|
if (spdk_call_unaffinitized(bdev_rbd_init_context, rbd) == NULL) {
|
|
|
|
SPDK_ERRLOG("Cannot init rbd context for rbd=%p\n", rbd);
|
2016-09-20 04:12:45 +00:00
|
|
|
}
|
|
|
|
|
2021-04-16 15:57:24 +00:00
|
|
|
return ret;
|
2016-09-20 04:12:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-07-13 04:08:53 +00:00
|
|
|
bdev_rbd_exit(rbd_image_t image)
|
2016-09-20 04:12:45 +00:00
|
|
|
{
|
|
|
|
rbd_flush(image);
|
|
|
|
rbd_close(image);
|
|
|
|
}
|
|
|
|
|
2021-03-10 12:32:08 +00:00
|
|
|
static void
|
2021-03-09 16:50:21 +00:00
|
|
|
_bdev_rbd_io_complete(void *_rbd_io)
|
|
|
|
{
|
|
|
|
struct bdev_rbd_io *rbd_io = _rbd_io;
|
|
|
|
|
|
|
|
spdk_bdev_io_complete(spdk_bdev_io_from_ctx(rbd_io), rbd_io->status);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bdev_rbd_io_complete(struct spdk_bdev_io *bdev_io, enum spdk_bdev_io_status status)
|
|
|
|
{
|
|
|
|
struct bdev_rbd_io *rbd_io = (struct bdev_rbd_io *)bdev_io->driver_ctx;
|
2021-09-23 10:15:37 +00:00
|
|
|
struct spdk_thread *current_thread = spdk_get_thread();
|
2021-03-09 16:50:21 +00:00
|
|
|
|
|
|
|
rbd_io->status = status;
|
2021-09-23 10:15:37 +00:00
|
|
|
assert(rbd_io->submit_td != NULL);
|
|
|
|
if (rbd_io->submit_td != current_thread) {
|
2021-03-09 16:50:21 +00:00
|
|
|
spdk_thread_send_msg(rbd_io->submit_td, _bdev_rbd_io_complete, rbd_io);
|
|
|
|
} else {
|
|
|
|
_bdev_rbd_io_complete(rbd_io);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-30 15:53:54 +00:00
|
|
|
static void
|
|
|
|
bdev_rbd_finish_aiocb(rbd_completion_t cb, void *arg)
|
|
|
|
{
|
|
|
|
int io_status;
|
|
|
|
struct spdk_bdev_io *bdev_io;
|
|
|
|
struct bdev_rbd_io *rbd_io;
|
|
|
|
enum spdk_bdev_io_status bio_status;
|
|
|
|
|
|
|
|
bdev_io = rbd_aio_get_arg(cb);
|
|
|
|
rbd_io = (struct bdev_rbd_io *)bdev_io->driver_ctx;
|
|
|
|
io_status = rbd_aio_get_return_value(cb);
|
|
|
|
bio_status = SPDK_BDEV_IO_STATUS_SUCCESS;
|
|
|
|
|
|
|
|
if (bdev_io->type == SPDK_BDEV_IO_TYPE_READ) {
|
|
|
|
if ((int)rbd_io->total_len != io_status) {
|
|
|
|
bio_status = SPDK_BDEV_IO_STATUS_FAILED;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* For others, 0 means success */
|
|
|
|
if (io_status != 0) {
|
|
|
|
bio_status = SPDK_BDEV_IO_STATUS_FAILED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rbd_aio_release(cb);
|
|
|
|
|
|
|
|
bdev_rbd_io_complete(bdev_io, bio_status);
|
|
|
|
}
|
|
|
|
|
2021-03-09 16:50:21 +00:00
|
|
|
static void
|
|
|
|
bdev_rbd_start_aio(struct bdev_rbd *disk, struct spdk_bdev_io *bdev_io,
|
2020-08-09 18:48:50 +00:00
|
|
|
struct iovec *iov, int iovcnt, uint64_t offset, size_t len)
|
2016-09-20 04:12:45 +00:00
|
|
|
{
|
|
|
|
int ret;
|
2021-08-30 15:53:54 +00:00
|
|
|
struct bdev_rbd_io *rbd_io = (struct bdev_rbd_io *)bdev_io->driver_ctx;
|
2021-03-09 16:50:21 +00:00
|
|
|
rbd_image_t image = disk->image;
|
2020-08-11 12:18:44 +00:00
|
|
|
|
2017-07-20 14:47:34 +00:00
|
|
|
ret = rbd_aio_create_completion(bdev_io, bdev_rbd_finish_aiocb,
|
2021-08-30 15:53:54 +00:00
|
|
|
&rbd_io->comp);
|
2016-09-20 04:12:45 +00:00
|
|
|
if (ret < 0) {
|
2021-03-10 12:32:08 +00:00
|
|
|
goto err;
|
2016-09-20 04:12:45 +00:00
|
|
|
}
|
|
|
|
|
2016-11-08 20:03:40 +00:00
|
|
|
if (bdev_io->type == SPDK_BDEV_IO_TYPE_READ) {
|
2020-08-09 18:48:50 +00:00
|
|
|
rbd_io->total_len = len;
|
2020-09-09 15:38:46 +00:00
|
|
|
if (spdk_likely(iovcnt == 1)) {
|
2021-08-30 15:53:54 +00:00
|
|
|
ret = rbd_aio_read(image, offset, iov[0].iov_len, iov[0].iov_base, rbd_io->comp);
|
2020-09-09 15:38:46 +00:00
|
|
|
} else {
|
2021-08-30 15:53:54 +00:00
|
|
|
ret = rbd_aio_readv(image, iov, iovcnt, offset, rbd_io->comp);
|
2020-09-09 15:38:46 +00:00
|
|
|
}
|
2016-11-08 20:03:40 +00:00
|
|
|
} else if (bdev_io->type == SPDK_BDEV_IO_TYPE_WRITE) {
|
2020-09-09 15:38:46 +00:00
|
|
|
if (spdk_likely(iovcnt == 1)) {
|
2021-08-30 15:53:54 +00:00
|
|
|
ret = rbd_aio_write(image, offset, iov[0].iov_len, iov[0].iov_base, rbd_io->comp);
|
2020-09-09 15:38:46 +00:00
|
|
|
} else {
|
2021-08-30 15:53:54 +00:00
|
|
|
ret = rbd_aio_writev(image, iov, iovcnt, offset, rbd_io->comp);
|
2020-09-09 15:38:46 +00:00
|
|
|
}
|
2016-11-08 20:03:40 +00:00
|
|
|
} else if (bdev_io->type == SPDK_BDEV_IO_TYPE_FLUSH) {
|
2021-08-30 15:53:54 +00:00
|
|
|
ret = rbd_aio_flush(image, rbd_io->comp);
|
2016-09-20 04:12:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ret < 0) {
|
2021-08-30 15:53:54 +00:00
|
|
|
rbd_aio_release(rbd_io->comp);
|
2021-03-10 12:32:08 +00:00
|
|
|
goto err;
|
2016-09-20 04:12:45 +00:00
|
|
|
}
|
|
|
|
|
2021-03-10 12:32:08 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
err:
|
2021-03-09 16:50:21 +00:00
|
|
|
bdev_rbd_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
|
2016-09-20 04:12:45 +00:00
|
|
|
}
|
|
|
|
|
2017-07-13 17:36:19 +00:00
|
|
|
static int bdev_rbd_library_init(void);
|
2020-08-09 19:16:06 +00:00
|
|
|
static void bdev_rbd_library_fini(void);
|
|
|
|
|
2017-10-13 00:20:10 +00:00
|
|
|
static int
|
|
|
|
bdev_rbd_get_ctx_size(void)
|
|
|
|
{
|
|
|
|
return sizeof(struct bdev_rbd_io);
|
|
|
|
}
|
|
|
|
|
2018-03-09 22:20:21 +00:00
|
|
|
static struct spdk_bdev_module rbd_if = {
|
2018-03-06 18:52:46 +00:00
|
|
|
.name = "rbd",
|
|
|
|
.module_init = bdev_rbd_library_init,
|
2020-08-09 19:16:06 +00:00
|
|
|
.module_fini = bdev_rbd_library_fini,
|
2018-03-06 18:52:46 +00:00
|
|
|
.get_ctx_size = bdev_rbd_get_ctx_size,
|
|
|
|
|
|
|
|
};
|
2019-02-05 10:46:48 +00:00
|
|
|
SPDK_BDEV_MODULE_REGISTER(rbd, &rbd_if)
|
2016-09-20 04:12:45 +00:00
|
|
|
|
2018-03-13 00:16:47 +00:00
|
|
|
static int
|
2018-02-23 23:51:20 +00:00
|
|
|
bdev_rbd_reset_timer(void *arg)
|
|
|
|
{
|
|
|
|
struct bdev_rbd *disk = arg;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* TODO: This should check if any I/O is still in flight before completing the reset.
|
|
|
|
* For now, just complete after the timer expires.
|
|
|
|
*/
|
2021-03-09 16:50:21 +00:00
|
|
|
bdev_rbd_io_complete(disk->reset_bdev_io, SPDK_BDEV_IO_STATUS_SUCCESS);
|
2018-02-23 23:51:20 +00:00
|
|
|
spdk_poller_unregister(&disk->reset_timer);
|
|
|
|
disk->reset_bdev_io = NULL;
|
2018-03-13 00:16:47 +00:00
|
|
|
|
2020-05-04 09:51:27 +00:00
|
|
|
return SPDK_POLLER_BUSY;
|
2018-02-23 23:51:20 +00:00
|
|
|
}
|
|
|
|
|
2021-03-10 12:32:08 +00:00
|
|
|
static void
|
2018-02-23 23:51:20 +00:00
|
|
|
bdev_rbd_reset(struct bdev_rbd *disk, struct spdk_bdev_io *bdev_io)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* HACK: Since librbd doesn't provide any way to cancel outstanding aio, just kick off a
|
|
|
|
* timer to wait for in-flight I/O to complete.
|
|
|
|
*/
|
|
|
|
assert(disk->reset_bdev_io == NULL);
|
|
|
|
disk->reset_bdev_io = bdev_io;
|
2020-04-14 06:49:46 +00:00
|
|
|
disk->reset_timer = SPDK_POLLER_REGISTER(bdev_rbd_reset_timer, disk, 1 * 1000 * 1000);
|
2018-02-23 23:51:20 +00:00
|
|
|
}
|
|
|
|
|
2021-04-23 12:30:43 +00:00
|
|
|
static void
|
2021-08-06 14:19:27 +00:00
|
|
|
_bdev_rbd_destruct_done(void *io_device)
|
2021-04-23 12:30:43 +00:00
|
|
|
{
|
|
|
|
struct bdev_rbd *rbd = io_device;
|
|
|
|
|
|
|
|
assert(rbd != NULL);
|
2021-08-11 20:23:43 +00:00
|
|
|
assert(rbd->ch_count == 0);
|
2021-04-23 12:30:43 +00:00
|
|
|
|
2021-08-06 14:19:27 +00:00
|
|
|
spdk_bdev_destruct_done(&rbd->disk, 0);
|
2021-08-11 20:23:43 +00:00
|
|
|
bdev_rbd_free(rbd);
|
|
|
|
}
|
2021-03-09 16:50:21 +00:00
|
|
|
|
2021-08-06 14:19:27 +00:00
|
|
|
static void
|
|
|
|
bdev_rbd_free_cb(void *io_device)
|
|
|
|
{
|
|
|
|
struct bdev_rbd *rbd = io_device;
|
|
|
|
|
|
|
|
/* The io device has been unregistered. Send a message back to the
|
|
|
|
* original thread that started the destruct operation, so that the
|
|
|
|
* bdev unregister callback is invoked on the same thread that started
|
|
|
|
* this whole process.
|
|
|
|
*/
|
|
|
|
spdk_thread_send_msg(rbd->destruct_td, _bdev_rbd_destruct_done, rbd);
|
|
|
|
}
|
|
|
|
|
2021-08-11 20:23:43 +00:00
|
|
|
static void
|
|
|
|
_bdev_rbd_destruct(void *ctx)
|
|
|
|
{
|
|
|
|
struct bdev_rbd *rbd = ctx;
|
|
|
|
|
|
|
|
spdk_io_device_unregister(rbd, bdev_rbd_free_cb);
|
2021-04-23 12:30:43 +00:00
|
|
|
}
|
|
|
|
|
2016-09-20 04:12:45 +00:00
|
|
|
static int
|
2017-07-13 04:08:53 +00:00
|
|
|
bdev_rbd_destruct(void *ctx)
|
2016-09-20 04:12:45 +00:00
|
|
|
{
|
2017-12-02 00:34:20 +00:00
|
|
|
struct bdev_rbd *rbd = ctx;
|
2021-08-11 20:23:43 +00:00
|
|
|
struct spdk_thread *td;
|
2017-12-02 00:34:20 +00:00
|
|
|
|
2021-08-11 20:23:43 +00:00
|
|
|
if (rbd->main_td == NULL) {
|
|
|
|
td = spdk_get_thread();
|
|
|
|
} else {
|
|
|
|
td = rbd->main_td;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Start the destruct operation on the rbd bdev's
|
|
|
|
* main thread. This guarantees it will only start
|
|
|
|
* executing after any messages related to channel
|
|
|
|
* deletions have finished completing. *Always*
|
|
|
|
* send a message, even if this function gets called
|
|
|
|
* from the main thread, in case there are pending
|
|
|
|
* channel delete messages in flight to this thread.
|
|
|
|
*/
|
2021-08-06 14:19:27 +00:00
|
|
|
assert(rbd->destruct_td == NULL);
|
|
|
|
rbd->destruct_td = td;
|
2021-08-11 20:23:43 +00:00
|
|
|
spdk_thread_send_msg(td, _bdev_rbd_destruct, rbd);
|
2018-08-31 13:39:27 +00:00
|
|
|
|
2021-08-06 14:19:27 +00:00
|
|
|
/* Return 1 to indicate the destruct path is asynchronous. */
|
|
|
|
return 1;
|
2016-09-20 04:12:45 +00:00
|
|
|
}
|
|
|
|
|
bdev: Not assert but pass completion status to spdk_bdev_io_get_buf_cb
When the specified buffer size to spdk_bdev_io_get_buf() is greater
than the permitted maximum, spdk_bdev_io_get_buf() asserts simply and
doesn't call the specified callback function.
SPDK SCSI library doesn't allocate read buffer and specifies
expected read buffer size, and expects that it is allocated by
spdk_bdev_io_get_buf().
Bdev perf tool also doesn't allocate read buffer and specifies
expected read buffer size, and expects that it is allocated by
spdk_bdev_io_get_buf().
When we support DIF insert and strip in iSCSI target, the read
buffer size iSCSI initiator requests and the read buffer size iSCSI target
requests will become different.
Even after that, iSCSI initiator and iSCSI target will negotiate correctly
not to cause buffer overflow in spdk_bdev_io_get_buf(), but if iSCSI
initiator ignores the result of negotiation, iSCSI initiator can request
read buffer size larger than the permitted maximum, and can cause
failure in iSCSI target. This is very flagile and should be avoided.
This patch do the following
- Add the completion status of spdk_bdev_io_get_buf() to
spdk_bdev_io_get_buf_cb(),
- spdk_bdev_io_get_buf() calls spdk_bdev_io_get_buf_cb() by setting
success to false, and return.
- spdk_bdev_io_get_buf_cb() in each bdev module calls assert if success
is false.
Subsequent patches will process the case that success is false
in spdk_bdev_io_get_buf_cb().
Change-Id: I76429a86e18a69aa085a353ac94743296d270b82
Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/c/446045
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Ziye Yang <ziye.yang@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-02-25 00:34:28 +00:00
|
|
|
static void
|
|
|
|
bdev_rbd_get_buf_cb(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io,
|
|
|
|
bool success)
|
2016-09-20 04:12:45 +00:00
|
|
|
{
|
2021-03-09 16:50:21 +00:00
|
|
|
struct bdev_rbd *disk = (struct bdev_rbd *)bdev_io->bdev->ctxt;
|
|
|
|
|
2019-02-25 01:43:13 +00:00
|
|
|
if (!success) {
|
2021-03-09 16:50:21 +00:00
|
|
|
bdev_rbd_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
|
2019-02-25 01:43:13 +00:00
|
|
|
return;
|
|
|
|
}
|
bdev: Not assert but pass completion status to spdk_bdev_io_get_buf_cb
When the specified buffer size to spdk_bdev_io_get_buf() is greater
than the permitted maximum, spdk_bdev_io_get_buf() asserts simply and
doesn't call the specified callback function.
SPDK SCSI library doesn't allocate read buffer and specifies
expected read buffer size, and expects that it is allocated by
spdk_bdev_io_get_buf().
Bdev perf tool also doesn't allocate read buffer and specifies
expected read buffer size, and expects that it is allocated by
spdk_bdev_io_get_buf().
When we support DIF insert and strip in iSCSI target, the read
buffer size iSCSI initiator requests and the read buffer size iSCSI target
requests will become different.
Even after that, iSCSI initiator and iSCSI target will negotiate correctly
not to cause buffer overflow in spdk_bdev_io_get_buf(), but if iSCSI
initiator ignores the result of negotiation, iSCSI initiator can request
read buffer size larger than the permitted maximum, and can cause
failure in iSCSI target. This is very flagile and should be avoided.
This patch do the following
- Add the completion status of spdk_bdev_io_get_buf() to
spdk_bdev_io_get_buf_cb(),
- spdk_bdev_io_get_buf() calls spdk_bdev_io_get_buf_cb() by setting
success to false, and return.
- spdk_bdev_io_get_buf_cb() in each bdev module calls assert if success
is false.
Subsequent patches will process the case that success is false
in spdk_bdev_io_get_buf_cb().
Change-Id: I76429a86e18a69aa085a353ac94743296d270b82
Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/c/446045
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Ziye Yang <ziye.yang@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
2019-02-25 00:34:28 +00:00
|
|
|
|
2021-03-09 16:50:21 +00:00
|
|
|
bdev_rbd_start_aio(disk,
|
2021-03-10 12:32:08 +00:00
|
|
|
bdev_io,
|
|
|
|
bdev_io->u.bdev.iovs,
|
|
|
|
bdev_io->u.bdev.iovcnt,
|
|
|
|
bdev_io->u.bdev.offset_blocks * bdev_io->bdev->blocklen,
|
|
|
|
bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen);
|
2016-09-20 04:12:45 +00:00
|
|
|
}
|
|
|
|
|
2021-03-10 12:32:08 +00:00
|
|
|
static void
|
2021-03-09 16:50:21 +00:00
|
|
|
_bdev_rbd_submit_request(void *ctx)
|
2016-09-20 04:12:45 +00:00
|
|
|
{
|
2021-03-09 16:50:21 +00:00
|
|
|
struct spdk_bdev_io *bdev_io = ctx;
|
|
|
|
struct bdev_rbd *disk = (struct bdev_rbd *)bdev_io->bdev->ctxt;
|
|
|
|
|
2016-09-20 04:12:45 +00:00
|
|
|
switch (bdev_io->type) {
|
|
|
|
case SPDK_BDEV_IO_TYPE_READ:
|
2017-09-22 20:59:55 +00:00
|
|
|
spdk_bdev_io_get_buf(bdev_io, bdev_rbd_get_buf_cb,
|
|
|
|
bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen);
|
2021-03-10 12:32:08 +00:00
|
|
|
break;
|
2016-09-20 04:12:45 +00:00
|
|
|
|
|
|
|
case SPDK_BDEV_IO_TYPE_WRITE:
|
2016-10-11 23:47:27 +00:00
|
|
|
case SPDK_BDEV_IO_TYPE_FLUSH:
|
2021-03-09 16:50:21 +00:00
|
|
|
bdev_rbd_start_aio(disk,
|
2021-03-10 12:32:08 +00:00
|
|
|
bdev_io,
|
|
|
|
bdev_io->u.bdev.iovs,
|
|
|
|
bdev_io->u.bdev.iovcnt,
|
|
|
|
bdev_io->u.bdev.offset_blocks * bdev_io->bdev->blocklen,
|
|
|
|
bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen);
|
|
|
|
break;
|
2018-02-23 23:51:20 +00:00
|
|
|
|
|
|
|
case SPDK_BDEV_IO_TYPE_RESET:
|
2021-03-10 12:32:08 +00:00
|
|
|
bdev_rbd_reset((struct bdev_rbd *)bdev_io->bdev->ctxt,
|
|
|
|
bdev_io);
|
|
|
|
break;
|
2018-02-23 23:51:20 +00:00
|
|
|
|
2016-09-20 04:12:45 +00:00
|
|
|
default:
|
2021-03-10 12:32:08 +00:00
|
|
|
SPDK_ERRLOG("Unsupported IO type =%d\n", bdev_io->type);
|
2021-03-09 16:50:21 +00:00
|
|
|
bdev_rbd_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
|
2021-03-10 12:32:08 +00:00
|
|
|
break;
|
2016-09-20 04:12:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-09 16:50:21 +00:00
|
|
|
static void
|
|
|
|
bdev_rbd_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
|
|
|
|
{
|
|
|
|
struct spdk_thread *submit_td = spdk_io_channel_get_thread(ch);
|
|
|
|
struct bdev_rbd_io *rbd_io = (struct bdev_rbd_io *)bdev_io->driver_ctx;
|
|
|
|
struct bdev_rbd *disk = (struct bdev_rbd *)bdev_io->bdev->ctxt;
|
|
|
|
|
2021-09-23 10:15:37 +00:00
|
|
|
rbd_io->submit_td = submit_td;
|
2021-03-09 16:50:21 +00:00
|
|
|
if (disk->main_td != submit_td) {
|
|
|
|
spdk_thread_send_msg(disk->main_td, _bdev_rbd_submit_request, bdev_io);
|
|
|
|
} else {
|
|
|
|
_bdev_rbd_submit_request(bdev_io);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-20 04:12:45 +00:00
|
|
|
static bool
|
2017-07-13 04:08:53 +00:00
|
|
|
bdev_rbd_io_type_supported(void *ctx, enum spdk_bdev_io_type io_type)
|
2016-09-20 04:12:45 +00:00
|
|
|
{
|
|
|
|
switch (io_type) {
|
|
|
|
case SPDK_BDEV_IO_TYPE_READ:
|
|
|
|
case SPDK_BDEV_IO_TYPE_WRITE:
|
2016-10-11 23:47:27 +00:00
|
|
|
case SPDK_BDEV_IO_TYPE_FLUSH:
|
2018-02-23 23:51:20 +00:00
|
|
|
case SPDK_BDEV_IO_TYPE_RESET:
|
2016-09-20 04:12:45 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-08 05:09:01 +00:00
|
|
|
static void
|
2021-03-09 16:50:21 +00:00
|
|
|
bdev_rbd_free_channel_resources(struct bdev_rbd *disk)
|
2016-10-08 05:09:01 +00:00
|
|
|
{
|
2021-03-09 16:50:21 +00:00
|
|
|
assert(disk != NULL);
|
|
|
|
assert(disk->main_td == spdk_get_thread());
|
|
|
|
assert(disk->ch_count == 0);
|
2016-10-08 05:09:01 +00:00
|
|
|
|
2021-08-30 15:53:54 +00:00
|
|
|
spdk_put_io_channel(disk->group_ch);
|
2021-03-09 16:50:21 +00:00
|
|
|
if (disk->image) {
|
|
|
|
bdev_rbd_exit(disk->image);
|
2016-10-08 05:09:01 +00:00
|
|
|
}
|
|
|
|
|
2021-03-09 16:50:21 +00:00
|
|
|
disk->main_td = NULL;
|
|
|
|
disk->group_ch = NULL;
|
2016-09-20 04:12:45 +00:00
|
|
|
}
|
|
|
|
|
2016-11-07 17:08:11 +00:00
|
|
|
static void *
|
2017-07-13 04:08:53 +00:00
|
|
|
bdev_rbd_handle(void *arg)
|
2016-11-07 17:08:11 +00:00
|
|
|
{
|
2021-03-09 16:50:21 +00:00
|
|
|
struct bdev_rbd *disk = arg;
|
2016-11-07 17:08:11 +00:00
|
|
|
void *ret = arg;
|
2020-08-10 12:15:27 +00:00
|
|
|
|
2021-03-09 16:50:21 +00:00
|
|
|
if (rbd_open(disk->io_ctx, disk->rbd_name, &disk->image, NULL) < 0) {
|
2016-11-07 17:08:11 +00:00
|
|
|
SPDK_ERRLOG("Failed to open specified rbd device\n");
|
|
|
|
ret = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-09-20 04:12:45 +00:00
|
|
|
static int
|
2021-03-09 16:50:21 +00:00
|
|
|
_bdev_rbd_create_cb(struct bdev_rbd *disk)
|
2016-09-20 04:12:45 +00:00
|
|
|
{
|
2021-08-30 15:53:54 +00:00
|
|
|
disk->group_ch = spdk_get_io_channel(&rbd_if);
|
2021-03-09 16:50:21 +00:00
|
|
|
assert(disk->group_ch != NULL);
|
2016-09-20 04:12:45 +00:00
|
|
|
|
2021-03-09 16:50:21 +00:00
|
|
|
if (spdk_call_unaffinitized(bdev_rbd_handle, disk) == NULL) {
|
2021-08-30 15:53:54 +00:00
|
|
|
bdev_rbd_free_channel_resources(disk);
|
|
|
|
return -1;
|
2020-08-09 19:16:06 +00:00
|
|
|
}
|
2016-09-20 04:12:45 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-03-09 16:50:21 +00:00
|
|
|
static int
|
|
|
|
bdev_rbd_create_cb(void *io_device, void *ctx_buf)
|
2016-09-20 04:12:45 +00:00
|
|
|
{
|
2021-03-09 16:50:21 +00:00
|
|
|
struct bdev_rbd_io_channel *ch = ctx_buf;
|
|
|
|
struct bdev_rbd *disk = io_device;
|
2020-08-09 19:16:06 +00:00
|
|
|
int rc;
|
2016-09-20 04:12:45 +00:00
|
|
|
|
2021-03-09 16:50:21 +00:00
|
|
|
ch->disk = disk;
|
|
|
|
pthread_mutex_lock(&disk->mutex);
|
|
|
|
if (disk->ch_count == 0) {
|
|
|
|
assert(disk->main_td == NULL);
|
|
|
|
rc = _bdev_rbd_create_cb(disk);
|
|
|
|
if (rc) {
|
|
|
|
SPDK_ERRLOG("Cannot create channel for disk=%p\n", disk);
|
|
|
|
pthread_mutex_unlock(&disk->mutex);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
disk->main_td = spdk_get_thread();
|
|
|
|
}
|
|
|
|
|
|
|
|
disk->ch_count++;
|
|
|
|
pthread_mutex_unlock(&disk->mutex);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_bdev_rbd_destroy_cb(void *ctx)
|
|
|
|
{
|
|
|
|
struct bdev_rbd *disk = ctx;
|
|
|
|
|
|
|
|
pthread_mutex_lock(&disk->mutex);
|
|
|
|
assert(disk->ch_count > 0);
|
|
|
|
disk->ch_count--;
|
|
|
|
|
|
|
|
if (disk->ch_count > 0) {
|
|
|
|
/* A new channel was created between when message was sent and this function executed */
|
|
|
|
pthread_mutex_unlock(&disk->mutex);
|
|
|
|
return;
|
2020-08-09 19:16:06 +00:00
|
|
|
}
|
2016-09-20 04:12:45 +00:00
|
|
|
|
2021-03-09 16:50:21 +00:00
|
|
|
bdev_rbd_free_channel_resources(disk);
|
|
|
|
pthread_mutex_unlock(&disk->mutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bdev_rbd_destroy_cb(void *io_device, void *ctx_buf)
|
|
|
|
{
|
|
|
|
struct bdev_rbd *disk = io_device;
|
|
|
|
struct spdk_thread *thread;
|
|
|
|
|
|
|
|
pthread_mutex_lock(&disk->mutex);
|
|
|
|
assert(disk->ch_count > 0);
|
|
|
|
disk->ch_count--;
|
|
|
|
if (disk->ch_count == 0) {
|
|
|
|
assert(disk->main_td != NULL);
|
|
|
|
if (disk->main_td != spdk_get_thread()) {
|
|
|
|
/* The final channel was destroyed on a different thread
|
|
|
|
* than where the first channel was created. Pass a message
|
|
|
|
* to the main thread to unregister the poller. */
|
|
|
|
disk->ch_count++;
|
|
|
|
thread = disk->main_td;
|
|
|
|
pthread_mutex_unlock(&disk->mutex);
|
|
|
|
spdk_thread_send_msg(thread, _bdev_rbd_destroy_cb, disk);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bdev_rbd_free_channel_resources(disk);
|
|
|
|
}
|
|
|
|
pthread_mutex_unlock(&disk->mutex);
|
2016-09-20 04:12:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct spdk_io_channel *
|
2017-07-13 04:08:53 +00:00
|
|
|
bdev_rbd_get_io_channel(void *ctx)
|
2016-09-20 04:12:45 +00:00
|
|
|
{
|
2017-07-13 04:08:53 +00:00
|
|
|
struct bdev_rbd *rbd_bdev = ctx;
|
2016-09-20 04:12:45 +00:00
|
|
|
|
2018-02-19 22:28:16 +00:00
|
|
|
return spdk_get_io_channel(rbd_bdev);
|
2016-09-20 04:12:45 +00:00
|
|
|
}
|
|
|
|
|
2021-04-22 13:51:42 +00:00
|
|
|
static void
|
|
|
|
bdev_rbd_cluster_dump_entry(const char *cluster_name, struct spdk_json_write_ctx *w)
|
|
|
|
{
|
|
|
|
struct bdev_rbd_cluster *entry;
|
|
|
|
|
|
|
|
pthread_mutex_lock(&g_map_bdev_rbd_cluster_mutex);
|
|
|
|
STAILQ_FOREACH(entry, &g_map_bdev_rbd_cluster, link) {
|
2021-05-21 16:14:28 +00:00
|
|
|
if (strcmp(cluster_name, entry->name)) {
|
2021-04-22 13:51:42 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (entry->user_id) {
|
|
|
|
spdk_json_write_named_string(w, "user_id", entry->user_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (entry->config_param) {
|
|
|
|
char **config_entry = entry->config_param;
|
|
|
|
|
|
|
|
spdk_json_write_named_object_begin(w, "config_param");
|
|
|
|
while (*config_entry) {
|
|
|
|
spdk_json_write_named_string(w, config_entry[0], config_entry[1]);
|
|
|
|
config_entry += 2;
|
|
|
|
}
|
|
|
|
spdk_json_write_object_end(w);
|
2021-12-15 04:31:29 +00:00
|
|
|
}
|
|
|
|
if (entry->config_file) {
|
2021-04-22 13:51:42 +00:00
|
|
|
spdk_json_write_named_string(w, "config_file", entry->config_file);
|
|
|
|
}
|
2021-12-01 09:13:32 +00:00
|
|
|
if (entry->key_file) {
|
|
|
|
spdk_json_write_named_string(w, "key_file", entry->key_file);
|
|
|
|
}
|
2021-04-22 13:51:42 +00:00
|
|
|
|
|
|
|
pthread_mutex_unlock(&g_map_bdev_rbd_cluster_mutex);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pthread_mutex_unlock(&g_map_bdev_rbd_cluster_mutex);
|
|
|
|
}
|
|
|
|
|
2017-08-09 00:54:26 +00:00
|
|
|
static int
|
2018-02-22 12:48:13 +00:00
|
|
|
bdev_rbd_dump_info_json(void *ctx, struct spdk_json_write_ctx *w)
|
2017-08-09 00:54:26 +00:00
|
|
|
{
|
|
|
|
struct bdev_rbd *rbd_bdev = ctx;
|
|
|
|
|
2019-02-01 05:34:45 +00:00
|
|
|
spdk_json_write_named_object_begin(w, "rbd");
|
2017-08-09 00:54:26 +00:00
|
|
|
|
2019-02-01 05:34:45 +00:00
|
|
|
spdk_json_write_named_string(w, "pool_name", rbd_bdev->pool_name);
|
2017-08-09 00:54:26 +00:00
|
|
|
|
2019-02-01 05:34:45 +00:00
|
|
|
spdk_json_write_named_string(w, "rbd_name", rbd_bdev->rbd_name);
|
2017-08-09 00:54:26 +00:00
|
|
|
|
2021-04-22 13:51:42 +00:00
|
|
|
if (rbd_bdev->cluster_name) {
|
|
|
|
bdev_rbd_cluster_dump_entry(rbd_bdev->cluster_name, w);
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2018-10-26 12:06:15 +00:00
|
|
|
if (rbd_bdev->user_id) {
|
|
|
|
spdk_json_write_named_string(w, "user_id", rbd_bdev->user_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rbd_bdev->config) {
|
|
|
|
char **entry = rbd_bdev->config;
|
|
|
|
|
2019-02-01 05:34:45 +00:00
|
|
|
spdk_json_write_named_object_begin(w, "config");
|
2018-10-26 12:06:15 +00:00
|
|
|
while (*entry) {
|
|
|
|
spdk_json_write_named_string(w, entry[0], entry[1]);
|
|
|
|
entry += 2;
|
|
|
|
}
|
|
|
|
spdk_json_write_object_end(w);
|
|
|
|
}
|
|
|
|
|
2021-04-22 13:51:42 +00:00
|
|
|
end:
|
2017-08-09 00:54:26 +00:00
|
|
|
spdk_json_write_object_end(w);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-02-23 19:05:47 +00:00
|
|
|
static void
|
|
|
|
bdev_rbd_write_config_json(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w)
|
|
|
|
{
|
|
|
|
struct bdev_rbd *rbd = bdev->ctxt;
|
2021-10-19 08:56:18 +00:00
|
|
|
char uuid_str[SPDK_UUID_STRING_LEN];
|
2018-02-23 19:05:47 +00:00
|
|
|
|
|
|
|
spdk_json_write_object_begin(w);
|
|
|
|
|
2019-09-11 06:27:20 +00:00
|
|
|
spdk_json_write_named_string(w, "method", "bdev_rbd_create");
|
2018-02-23 19:05:47 +00:00
|
|
|
|
|
|
|
spdk_json_write_named_object_begin(w, "params");
|
|
|
|
spdk_json_write_named_string(w, "name", bdev->name);
|
|
|
|
spdk_json_write_named_string(w, "pool_name", rbd->pool_name);
|
|
|
|
spdk_json_write_named_string(w, "rbd_name", rbd->rbd_name);
|
2018-04-05 16:57:37 +00:00
|
|
|
spdk_json_write_named_uint32(w, "block_size", bdev->blocklen);
|
2018-10-26 12:06:15 +00:00
|
|
|
if (rbd->user_id) {
|
|
|
|
spdk_json_write_named_string(w, "user_id", rbd->user_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rbd->config) {
|
|
|
|
char **entry = rbd->config;
|
|
|
|
|
2019-02-01 05:34:45 +00:00
|
|
|
spdk_json_write_named_object_begin(w, "config");
|
2018-10-26 12:06:15 +00:00
|
|
|
while (*entry) {
|
|
|
|
spdk_json_write_named_string(w, entry[0], entry[1]);
|
|
|
|
entry += 2;
|
|
|
|
}
|
|
|
|
spdk_json_write_object_end(w);
|
|
|
|
}
|
|
|
|
|
2021-10-19 08:56:18 +00:00
|
|
|
spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &bdev->uuid);
|
|
|
|
spdk_json_write_named_string(w, "uuid", uuid_str);
|
|
|
|
|
2018-02-23 19:05:47 +00:00
|
|
|
spdk_json_write_object_end(w);
|
|
|
|
|
|
|
|
spdk_json_write_object_end(w);
|
|
|
|
}
|
|
|
|
|
2021-05-21 11:24:44 +00:00
|
|
|
static void
|
|
|
|
dump_single_cluster_entry(struct bdev_rbd_cluster *entry, struct spdk_json_write_ctx *w)
|
|
|
|
{
|
|
|
|
assert(entry != NULL);
|
|
|
|
|
|
|
|
spdk_json_write_object_begin(w);
|
|
|
|
spdk_json_write_named_string(w, "cluster_name", entry->name);
|
|
|
|
|
|
|
|
if (entry->user_id) {
|
|
|
|
spdk_json_write_named_string(w, "user_id", entry->user_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (entry->config_param) {
|
|
|
|
char **config_entry = entry->config_param;
|
|
|
|
|
|
|
|
spdk_json_write_named_object_begin(w, "config_param");
|
|
|
|
while (*config_entry) {
|
|
|
|
spdk_json_write_named_string(w, config_entry[0], config_entry[1]);
|
|
|
|
config_entry += 2;
|
|
|
|
}
|
|
|
|
spdk_json_write_object_end(w);
|
2021-12-15 04:31:29 +00:00
|
|
|
}
|
|
|
|
if (entry->config_file) {
|
2021-05-21 11:24:44 +00:00
|
|
|
spdk_json_write_named_string(w, "config_file", entry->config_file);
|
|
|
|
}
|
2021-12-01 09:13:32 +00:00
|
|
|
if (entry->key_file) {
|
|
|
|
spdk_json_write_named_string(w, "key_file", entry->key_file);
|
|
|
|
}
|
2021-05-21 11:24:44 +00:00
|
|
|
|
|
|
|
spdk_json_write_object_end(w);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
bdev_rbd_get_clusters_info(struct spdk_jsonrpc_request *request, const char *name)
|
|
|
|
{
|
|
|
|
struct bdev_rbd_cluster *entry;
|
|
|
|
struct spdk_json_write_ctx *w;
|
|
|
|
|
|
|
|
pthread_mutex_lock(&g_map_bdev_rbd_cluster_mutex);
|
|
|
|
|
|
|
|
if (STAILQ_EMPTY(&g_map_bdev_rbd_cluster)) {
|
|
|
|
pthread_mutex_unlock(&g_map_bdev_rbd_cluster_mutex);
|
|
|
|
return -ENOENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If cluster name is provided */
|
|
|
|
if (name) {
|
|
|
|
STAILQ_FOREACH(entry, &g_map_bdev_rbd_cluster, link) {
|
|
|
|
if (strcmp(name, entry->name) == 0) {
|
|
|
|
w = spdk_jsonrpc_begin_result(request);
|
|
|
|
dump_single_cluster_entry(entry, w);
|
|
|
|
spdk_jsonrpc_end_result(request, w);
|
|
|
|
|
|
|
|
pthread_mutex_unlock(&g_map_bdev_rbd_cluster_mutex);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pthread_mutex_unlock(&g_map_bdev_rbd_cluster_mutex);
|
|
|
|
return -ENOENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
w = spdk_jsonrpc_begin_result(request);
|
|
|
|
spdk_json_write_array_begin(w);
|
|
|
|
STAILQ_FOREACH(entry, &g_map_bdev_rbd_cluster, link) {
|
|
|
|
dump_single_cluster_entry(entry, w);
|
|
|
|
}
|
|
|
|
spdk_json_write_array_end(w);
|
|
|
|
spdk_jsonrpc_end_result(request, w);
|
|
|
|
pthread_mutex_unlock(&g_map_bdev_rbd_cluster_mutex);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-09-20 04:12:45 +00:00
|
|
|
static const struct spdk_bdev_fn_table rbd_fn_table = {
|
2017-07-13 04:08:53 +00:00
|
|
|
.destruct = bdev_rbd_destruct,
|
|
|
|
.submit_request = bdev_rbd_submit_request,
|
|
|
|
.io_type_supported = bdev_rbd_io_type_supported,
|
|
|
|
.get_io_channel = bdev_rbd_get_io_channel,
|
2018-02-22 12:48:13 +00:00
|
|
|
.dump_info_json = bdev_rbd_dump_info_json,
|
2018-02-23 19:05:47 +00:00
|
|
|
.write_config_json = bdev_rbd_write_config_json,
|
2016-09-20 04:12:45 +00:00
|
|
|
};
|
|
|
|
|
2021-04-21 12:58:01 +00:00
|
|
|
static int
|
|
|
|
rbd_register_cluster(const char *name, const char *user_id, const char *const *config_param,
|
2021-12-01 09:13:32 +00:00
|
|
|
const char *config_file, const char *key_file)
|
2021-04-21 12:58:01 +00:00
|
|
|
{
|
|
|
|
struct bdev_rbd_cluster *entry;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
pthread_mutex_lock(&g_map_bdev_rbd_cluster_mutex);
|
|
|
|
STAILQ_FOREACH(entry, &g_map_bdev_rbd_cluster, link) {
|
2021-05-21 16:14:28 +00:00
|
|
|
if (strcmp(name, entry->name) == 0) {
|
2021-04-21 12:58:01 +00:00
|
|
|
SPDK_ERRLOG("Cluster name=%s already exists\n", name);
|
|
|
|
pthread_mutex_unlock(&g_map_bdev_rbd_cluster_mutex);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
entry = calloc(1, sizeof(*entry));
|
|
|
|
if (!entry) {
|
|
|
|
SPDK_ERRLOG("Cannot allocate an entry for name=%s\n", name);
|
|
|
|
pthread_mutex_unlock(&g_map_bdev_rbd_cluster_mutex);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
entry->name = strdup(name);
|
|
|
|
if (entry->name == NULL) {
|
|
|
|
SPDK_ERRLOG("Failed to save the name =%s on entry =%p\n", name, entry);
|
|
|
|
goto err_handle;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (user_id) {
|
|
|
|
entry->user_id = strdup(user_id);
|
|
|
|
if (entry->user_id == NULL) {
|
|
|
|
SPDK_ERRLOG("Failed to save the str =%s on entry =%p\n", user_id, entry);
|
|
|
|
goto err_handle;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-15 04:31:29 +00:00
|
|
|
/* Support specify config_param or config_file separately, or both of them. */
|
2021-04-21 12:58:01 +00:00
|
|
|
if (config_param) {
|
|
|
|
entry->config_param = bdev_rbd_dup_config(config_param);
|
|
|
|
if (entry->config_param == NULL) {
|
|
|
|
SPDK_ERRLOG("Failed to save the config_param=%p on entry = %p\n", config_param, entry);
|
|
|
|
goto err_handle;
|
|
|
|
}
|
2021-12-15 04:31:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (config_file) {
|
2021-04-21 12:58:01 +00:00
|
|
|
entry->config_file = strdup(config_file);
|
|
|
|
if (entry->config_file == NULL) {
|
|
|
|
SPDK_ERRLOG("Failed to save the config_file=%s on entry = %p\n", config_file, entry);
|
|
|
|
goto err_handle;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-01 09:13:32 +00:00
|
|
|
if (key_file) {
|
|
|
|
entry->key_file = strdup(key_file);
|
|
|
|
if (entry->key_file == NULL) {
|
|
|
|
SPDK_ERRLOG("Failed to save the key_file=%s on entry = %p\n", key_file, entry);
|
|
|
|
goto err_handle;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-21 12:58:01 +00:00
|
|
|
rc = rados_create(&entry->cluster, user_id);
|
|
|
|
if (rc < 0) {
|
|
|
|
SPDK_ERRLOG("Failed to create rados_t struct\n");
|
|
|
|
goto err_handle;
|
|
|
|
}
|
|
|
|
|
2021-12-15 04:31:29 +00:00
|
|
|
/* Try default location when entry->config_file is NULL, but ignore failure when it is NULL */
|
|
|
|
rc = rados_conf_read_file(entry->cluster, entry->config_file);
|
|
|
|
if (entry->config_file && rc < 0) {
|
|
|
|
SPDK_ERRLOG("Failed to read conf file %s\n", entry->config_file);
|
|
|
|
rados_shutdown(entry->cluster);
|
|
|
|
goto err_handle;
|
|
|
|
}
|
|
|
|
|
2021-04-21 12:58:01 +00:00
|
|
|
if (config_param) {
|
|
|
|
const char *const *config_entry = config_param;
|
|
|
|
while (*config_entry) {
|
|
|
|
rc = rados_conf_set(entry->cluster, config_entry[0], config_entry[1]);
|
|
|
|
if (rc < 0) {
|
|
|
|
SPDK_ERRLOG("Failed to set %s = %s\n", config_entry[0], config_entry[1]);
|
|
|
|
rados_shutdown(entry->cluster);
|
|
|
|
goto err_handle;
|
|
|
|
}
|
|
|
|
config_entry += 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-01 09:13:32 +00:00
|
|
|
if (key_file) {
|
|
|
|
rc = rados_conf_set(entry->cluster, "keyring", key_file);
|
|
|
|
if (rc < 0) {
|
|
|
|
SPDK_ERRLOG("Failed to set keyring = %s\n", key_file);
|
|
|
|
rados_shutdown(entry->cluster);
|
|
|
|
goto err_handle;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-21 12:58:01 +00:00
|
|
|
rc = rados_connect(entry->cluster);
|
|
|
|
if (rc < 0) {
|
|
|
|
SPDK_ERRLOG("Failed to connect to rbd_pool on cluster=%p\n", entry->cluster);
|
|
|
|
rados_shutdown(entry->cluster);
|
|
|
|
goto err_handle;
|
|
|
|
}
|
|
|
|
|
|
|
|
STAILQ_INSERT_TAIL(&g_map_bdev_rbd_cluster, entry, link);
|
|
|
|
pthread_mutex_unlock(&g_map_bdev_rbd_cluster_mutex);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
err_handle:
|
|
|
|
bdev_rbd_cluster_free(entry);
|
|
|
|
pthread_mutex_unlock(&g_map_bdev_rbd_cluster_mutex);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
bdev_rbd_unregister_cluster(const char *name)
|
|
|
|
{
|
|
|
|
struct bdev_rbd_cluster *entry;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
if (name == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
pthread_mutex_lock(&g_map_bdev_rbd_cluster_mutex);
|
|
|
|
STAILQ_FOREACH(entry, &g_map_bdev_rbd_cluster, link) {
|
2021-05-21 16:14:28 +00:00
|
|
|
if (strcmp(name, entry->name) == 0) {
|
2021-04-21 12:58:01 +00:00
|
|
|
if (entry->ref == 0) {
|
|
|
|
STAILQ_REMOVE(&g_map_bdev_rbd_cluster, entry, bdev_rbd_cluster, link);
|
|
|
|
rados_shutdown(entry->cluster);
|
|
|
|
bdev_rbd_cluster_free(entry);
|
|
|
|
} else {
|
|
|
|
SPDK_ERRLOG("Cluster with name=%p is still used and we cannot delete it\n",
|
|
|
|
entry->name);
|
|
|
|
rc = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
pthread_mutex_unlock(&g_map_bdev_rbd_cluster_mutex);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pthread_mutex_unlock(&g_map_bdev_rbd_cluster_mutex);
|
|
|
|
|
|
|
|
SPDK_ERRLOG("Could not find the cluster name =%p\n", name);
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *
|
|
|
|
_bdev_rbd_register_cluster(void *arg)
|
|
|
|
{
|
|
|
|
struct cluster_register_info *info = arg;
|
|
|
|
void *ret = arg;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
rc = rbd_register_cluster((const char *)info->name, (const char *)info->user_id,
|
2021-12-01 09:13:32 +00:00
|
|
|
(const char *const *)info->config_param, (const char *)info->config_file,
|
|
|
|
(const char *)info->key_file);
|
2021-04-21 12:58:01 +00:00
|
|
|
if (rc) {
|
|
|
|
ret = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
bdev_rbd_register_cluster(struct cluster_register_info *info)
|
|
|
|
{
|
|
|
|
assert(info != NULL);
|
|
|
|
|
|
|
|
/* Rados cluster info need to be created in non SPDK-thread to avoid CPU
|
|
|
|
* resource contention */
|
|
|
|
if (spdk_call_unaffinitized(_bdev_rbd_register_cluster, info) == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-07-15 12:08:29 +00:00
|
|
|
int
|
2020-05-10 08:14:45 +00:00
|
|
|
bdev_rbd_create(struct spdk_bdev **bdev, const char *name, const char *user_id,
|
|
|
|
const char *pool_name,
|
|
|
|
const char *const *config,
|
|
|
|
const char *rbd_name,
|
2021-04-22 13:51:42 +00:00
|
|
|
uint32_t block_size,
|
2021-10-19 08:56:18 +00:00
|
|
|
const char *cluster_name,
|
|
|
|
const struct spdk_uuid *uuid)
|
2016-10-10 01:01:47 +00:00
|
|
|
{
|
2017-07-13 04:08:53 +00:00
|
|
|
struct bdev_rbd *rbd;
|
2016-10-10 01:01:47 +00:00
|
|
|
int ret;
|
|
|
|
|
2016-10-14 11:17:54 +00:00
|
|
|
if ((pool_name == NULL) || (rbd_name == NULL)) {
|
2019-07-15 12:08:29 +00:00
|
|
|
return -EINVAL;
|
2016-10-14 11:17:54 +00:00
|
|
|
}
|
|
|
|
|
2017-07-13 04:08:53 +00:00
|
|
|
rbd = calloc(1, sizeof(struct bdev_rbd));
|
2016-10-10 01:01:47 +00:00
|
|
|
if (rbd == NULL) {
|
2017-07-13 04:08:53 +00:00
|
|
|
SPDK_ERRLOG("Failed to allocate bdev_rbd struct\n");
|
2019-07-15 12:08:29 +00:00
|
|
|
return -ENOMEM;
|
2016-10-10 01:01:47 +00:00
|
|
|
}
|
|
|
|
|
2021-03-09 16:50:21 +00:00
|
|
|
ret = pthread_mutex_init(&rbd->mutex, NULL);
|
|
|
|
if (ret) {
|
|
|
|
SPDK_ERRLOG("Cannot init mutex on rbd=%p\n", rbd->disk.name);
|
|
|
|
free(rbd);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-10-14 11:17:54 +00:00
|
|
|
rbd->rbd_name = strdup(rbd_name);
|
|
|
|
if (!rbd->rbd_name) {
|
2017-07-13 04:08:53 +00:00
|
|
|
bdev_rbd_free(rbd);
|
2019-07-15 12:08:29 +00:00
|
|
|
return -ENOMEM;
|
2016-10-14 11:17:54 +00:00
|
|
|
}
|
|
|
|
|
2018-10-26 12:06:15 +00:00
|
|
|
if (user_id) {
|
|
|
|
rbd->user_id = strdup(user_id);
|
|
|
|
if (!rbd->user_id) {
|
|
|
|
bdev_rbd_free(rbd);
|
2019-07-15 12:08:29 +00:00
|
|
|
return -ENOMEM;
|
2018-10-26 12:06:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-22 13:51:42 +00:00
|
|
|
if (cluster_name) {
|
|
|
|
rbd->cluster_name = strdup(cluster_name);
|
|
|
|
if (!rbd->cluster_name) {
|
|
|
|
bdev_rbd_free(rbd);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
}
|
2016-11-08 18:25:29 +00:00
|
|
|
rbd->pool_name = strdup(pool_name);
|
|
|
|
if (!rbd->pool_name) {
|
2017-07-13 04:08:53 +00:00
|
|
|
bdev_rbd_free(rbd);
|
2019-07-15 12:08:29 +00:00
|
|
|
return -ENOMEM;
|
2016-11-08 18:25:29 +00:00
|
|
|
}
|
|
|
|
|
2020-05-10 08:14:45 +00:00
|
|
|
if (config && !(rbd->config = bdev_rbd_dup_config(config))) {
|
2018-10-26 12:06:15 +00:00
|
|
|
bdev_rbd_free(rbd);
|
2019-07-15 12:08:29 +00:00
|
|
|
return -ENOMEM;
|
2018-10-26 12:06:15 +00:00
|
|
|
}
|
|
|
|
|
2021-04-22 13:36:03 +00:00
|
|
|
ret = bdev_rbd_init(rbd);
|
2016-10-10 01:01:47 +00:00
|
|
|
if (ret < 0) {
|
2017-07-13 04:08:53 +00:00
|
|
|
bdev_rbd_free(rbd);
|
2016-10-10 01:01:47 +00:00
|
|
|
SPDK_ERRLOG("Failed to init rbd device\n");
|
2019-07-15 12:08:29 +00:00
|
|
|
return ret;
|
2016-10-10 01:01:47 +00:00
|
|
|
}
|
|
|
|
|
2021-10-19 08:56:18 +00:00
|
|
|
if (uuid) {
|
|
|
|
rbd->disk.uuid = *uuid;
|
|
|
|
} else {
|
|
|
|
spdk_uuid_generate(&rbd->disk.uuid);
|
|
|
|
}
|
|
|
|
|
2018-02-23 19:05:47 +00:00
|
|
|
if (name) {
|
|
|
|
rbd->disk.name = strdup(name);
|
|
|
|
} else {
|
|
|
|
rbd->disk.name = spdk_sprintf_alloc("Ceph%d", bdev_rbd_count);
|
|
|
|
}
|
2017-06-02 17:25:43 +00:00
|
|
|
if (!rbd->disk.name) {
|
2017-07-13 04:08:53 +00:00
|
|
|
bdev_rbd_free(rbd);
|
2019-07-15 12:08:29 +00:00
|
|
|
return -ENOMEM;
|
2017-06-02 17:25:43 +00:00
|
|
|
}
|
|
|
|
rbd->disk.product_name = "Ceph Rbd Disk";
|
2017-07-13 04:08:53 +00:00
|
|
|
bdev_rbd_count++;
|
2016-10-10 01:01:47 +00:00
|
|
|
|
|
|
|
rbd->disk.write_cache = 0;
|
|
|
|
rbd->disk.blocklen = block_size;
|
|
|
|
rbd->disk.blockcnt = rbd->info.size / rbd->disk.blocklen;
|
|
|
|
rbd->disk.ctxt = rbd;
|
|
|
|
rbd->disk.fn_table = &rbd_fn_table;
|
2018-03-06 18:52:46 +00:00
|
|
|
rbd->disk.module = &rbd_if;
|
2016-10-10 01:01:47 +00:00
|
|
|
|
|
|
|
SPDK_NOTICELOG("Add %s rbd disk to lun\n", rbd->disk.name);
|
|
|
|
|
2018-02-19 22:28:16 +00:00
|
|
|
spdk_io_device_register(rbd, bdev_rbd_create_cb,
|
2017-07-13 04:08:53 +00:00
|
|
|
bdev_rbd_destroy_cb,
|
2018-08-30 20:26:50 +00:00
|
|
|
sizeof(struct bdev_rbd_io_channel),
|
|
|
|
rbd_name);
|
2017-11-20 09:31:39 +00:00
|
|
|
ret = spdk_bdev_register(&rbd->disk);
|
|
|
|
if (ret) {
|
2018-02-19 22:28:16 +00:00
|
|
|
spdk_io_device_unregister(rbd, NULL);
|
2017-11-20 09:31:39 +00:00
|
|
|
bdev_rbd_free(rbd);
|
2019-07-15 12:08:29 +00:00
|
|
|
return ret;
|
2017-11-20 09:31:39 +00:00
|
|
|
}
|
|
|
|
|
2019-07-15 12:08:29 +00:00
|
|
|
*bdev = &(rbd->disk);
|
|
|
|
|
|
|
|
return ret;
|
2016-10-10 01:01:47 +00:00
|
|
|
}
|
|
|
|
|
2018-06-22 11:51:35 +00:00
|
|
|
void
|
2020-05-10 08:14:45 +00:00
|
|
|
bdev_rbd_delete(struct spdk_bdev *bdev, spdk_delete_rbd_complete cb_fn, void *cb_arg)
|
2018-06-22 11:51:35 +00:00
|
|
|
{
|
|
|
|
if (!bdev || bdev->module != &rbd_if) {
|
|
|
|
cb_fn(cb_arg, -ENODEV);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
spdk_bdev_unregister(bdev, cb_fn, cb_arg);
|
|
|
|
}
|
|
|
|
|
2020-04-08 06:45:55 +00:00
|
|
|
int
|
2020-05-10 08:14:45 +00:00
|
|
|
bdev_rbd_resize(struct spdk_bdev *bdev, const uint64_t new_size_in_mb)
|
2020-04-08 06:45:55 +00:00
|
|
|
{
|
|
|
|
struct spdk_io_channel *ch;
|
|
|
|
struct bdev_rbd_io_channel *rbd_io_ch;
|
|
|
|
int rc;
|
|
|
|
uint64_t new_size_in_byte;
|
|
|
|
uint64_t current_size_in_mb;
|
|
|
|
|
|
|
|
if (bdev->module != &rbd_if) {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
current_size_in_mb = bdev->blocklen * bdev->blockcnt / (1024 * 1024);
|
|
|
|
if (current_size_in_mb > new_size_in_mb) {
|
|
|
|
SPDK_ERRLOG("The new bdev size must be lager than current bdev size.\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ch = bdev_rbd_get_io_channel(bdev);
|
|
|
|
rbd_io_ch = spdk_io_channel_get_ctx(ch);
|
|
|
|
new_size_in_byte = new_size_in_mb * 1024 * 1024;
|
|
|
|
|
2021-03-09 16:50:21 +00:00
|
|
|
rc = rbd_resize(rbd_io_ch->disk->image, new_size_in_byte);
|
2021-04-19 12:07:56 +00:00
|
|
|
spdk_put_io_channel(ch);
|
2020-04-08 06:45:55 +00:00
|
|
|
if (rc != 0) {
|
|
|
|
SPDK_ERRLOG("failed to resize the ceph bdev.\n");
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = spdk_bdev_notify_blockcnt_change(bdev, new_size_in_byte / bdev->blocklen);
|
|
|
|
if (rc != 0) {
|
|
|
|
SPDK_ERRLOG("failed to notify block cnt change.\n");
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2020-08-09 19:16:06 +00:00
|
|
|
static int
|
|
|
|
bdev_rbd_group_create_cb(void *io_device, void *ctx_buf)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bdev_rbd_group_destroy_cb(void *io_device, void *ctx_buf)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2017-07-13 17:36:19 +00:00
|
|
|
static int
|
2017-07-13 04:08:53 +00:00
|
|
|
bdev_rbd_library_init(void)
|
2016-09-20 04:12:45 +00:00
|
|
|
{
|
2020-08-09 19:16:06 +00:00
|
|
|
spdk_io_device_register(&rbd_if, bdev_rbd_group_create_cb, bdev_rbd_group_destroy_cb,
|
2021-08-30 15:53:54 +00:00
|
|
|
0, "bdev_rbd_poll_groups");
|
2020-10-14 14:51:18 +00:00
|
|
|
return 0;
|
2016-09-20 04:12:45 +00:00
|
|
|
}
|
2017-08-25 21:22:46 +00:00
|
|
|
|
2020-08-09 19:16:06 +00:00
|
|
|
static void
|
|
|
|
bdev_rbd_library_fini(void)
|
|
|
|
{
|
|
|
|
spdk_io_device_unregister(&rbd_if, NULL);
|
|
|
|
}
|
|
|
|
|
2020-09-04 11:27:29 +00:00
|
|
|
SPDK_LOG_REGISTER_COMPONENT(bdev_rbd)
|