bdev: Add support for hot plug in generic bdev layer.

Change-Id: Iac724518fb82b1b1bcafa7610210b0000c2063aa
Signed-off-by: Cunyin Chang <cunyin.chang@intel.com>
This commit is contained in:
Cunyin Chang 2017-01-25 09:04:14 +08:00 committed by cunyinch
parent b9ca539390
commit 77183f9722
10 changed files with 77 additions and 20 deletions

View File

@ -55,10 +55,20 @@
#define SPDK_BDEV_MAX_NAME_LENGTH 16
#define SPDK_BDEV_MAX_PRODUCT_NAME_LENGTH 50
typedef void (*spdk_bdev_remove_cb_t)(void *remove_ctx);
struct spdk_bdev_io;
struct spdk_bdev_fn_table;
struct spdk_json_write_ctx;
/** Blockdev status */
enum spdk_bdev_status {
SPDK_BDEV_STATUS_INVALID,
SPDK_BDEV_STATUS_UNCLAIMED,
SPDK_BDEV_STATUS_CLAIMED,
SPDK_BDEV_STATUS_REMOVING,
};
/**
* \brief SPDK block device.
*
@ -104,8 +114,14 @@ struct spdk_bdev {
/** Mutex protecting claimed */
pthread_mutex_t mutex;
/** True if another blockdev or a LUN is using this device */
bool claimed;
/** The bdev status */
enum spdk_bdev_status status;
/** Remove callback function pointer to upper level stack */
spdk_bdev_remove_cb_t remove_cb;
/** Callback context for hot remove the device */
void *remove_ctx;
TAILQ_ENTRY(spdk_bdev) link;
};
@ -305,9 +321,11 @@ struct spdk_bdev *spdk_bdev_next(struct spdk_bdev *prev);
* When the ownership of the bdev is no longer needed, the user should call spdk_bdev_unclaim().
*
* \param bdev Block device to claim.
* \param remove_cb callback function for hot remove the device.
* \param remove_ctx param for hot removal callback function.
* \return true if the caller claimed the bdev, or false if it was already claimed by another user.
*/
bool spdk_bdev_claim(struct spdk_bdev *bdev);
bool spdk_bdev_claim(struct spdk_bdev *bdev, spdk_bdev_remove_cb_t remove_cb, void *remove_ctx);
/**
* Release claim of ownership of a block device.

View File

@ -546,6 +546,7 @@ spdk_bdev_read(struct spdk_bdev *bdev, struct spdk_io_channel *ch,
struct spdk_bdev_io *bdev_io;
int rc;
assert(bdev->status != SPDK_BDEV_STATUS_UNCLAIMED);
if (spdk_bdev_io_valid(bdev, offset, nbytes) != 0) {
return NULL;
}
@ -585,6 +586,7 @@ spdk_bdev_readv(struct spdk_bdev *bdev, struct spdk_io_channel *ch,
struct spdk_bdev_io *bdev_io;
int rc;
assert(bdev->status != SPDK_BDEV_STATUS_UNCLAIMED);
if (spdk_bdev_io_valid(bdev, offset, nbytes) != 0) {
return NULL;
}
@ -621,6 +623,7 @@ spdk_bdev_write(struct spdk_bdev *bdev, struct spdk_io_channel *ch,
struct spdk_bdev_io *bdev_io;
int rc;
assert(bdev->status != SPDK_BDEV_STATUS_UNCLAIMED);
if (spdk_bdev_io_valid(bdev, offset, nbytes) != 0) {
return NULL;
}
@ -659,6 +662,7 @@ spdk_bdev_writev(struct spdk_bdev *bdev, struct spdk_io_channel *ch,
struct spdk_bdev_io *bdev_io;
int rc;
assert(bdev->status != SPDK_BDEV_STATUS_UNCLAIMED);
if (spdk_bdev_io_valid(bdev, offset, len) != 0) {
return NULL;
}
@ -695,6 +699,7 @@ spdk_bdev_unmap(struct spdk_bdev *bdev, struct spdk_io_channel *ch,
struct spdk_bdev_io *bdev_io;
int rc;
assert(bdev->status != SPDK_BDEV_STATUS_UNCLAIMED);
if (bdesc_count == 0) {
SPDK_ERRLOG("Invalid bdesc_count 0\n");
return NULL;
@ -735,6 +740,7 @@ spdk_bdev_flush(struct spdk_bdev *bdev, struct spdk_io_channel *ch,
struct spdk_bdev_io *bdev_io;
int rc;
assert(bdev->status != SPDK_BDEV_STATUS_UNCLAIMED);
bdev_io = spdk_bdev_get_io();
if (!bdev_io) {
SPDK_ERRLOG("bdev_io memory allocation failed duing flush\n");
@ -763,6 +769,7 @@ spdk_bdev_reset(struct spdk_bdev *bdev, enum spdk_bdev_reset_type reset_type,
struct spdk_bdev_io *bdev_io;
int rc;
assert(bdev->status != SPDK_BDEV_STATUS_UNCLAIMED);
bdev_io = spdk_bdev_get_io();
if (!bdev_io) {
SPDK_ERRLOG("bdev_io memory allocation failed duing reset\n");
@ -921,8 +928,7 @@ spdk_bdev_register(struct spdk_bdev *bdev)
bdev->gencnt = 0;
pthread_mutex_init(&bdev->mutex, NULL);
bdev->claimed = false;
bdev->status = SPDK_BDEV_STATUS_UNCLAIMED;
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "Inserting bdev %s into list\n", bdev->name);
TAILQ_INSERT_TAIL(&spdk_bdev_list, bdev, link);
}
@ -933,7 +939,22 @@ spdk_bdev_unregister(struct spdk_bdev *bdev)
int rc;
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "Removing bdev %s from list\n", bdev->name);
pthread_mutex_lock(&bdev->mutex);
assert(bdev->status == SPDK_BDEV_STATUS_CLAIMED || bdev->status == SPDK_BDEV_STATUS_UNCLAIMED);
if (bdev->status == SPDK_BDEV_STATUS_CLAIMED) {
if (bdev->remove_cb) {
bdev->status = SPDK_BDEV_STATUS_REMOVING;
pthread_mutex_unlock(&bdev->mutex);
bdev->remove_cb(bdev->remove_ctx);
return;
} else {
bdev->status = SPDK_BDEV_STATUS_UNCLAIMED;
}
}
TAILQ_REMOVE(&spdk_bdev_list, bdev, link);
pthread_mutex_unlock(&bdev->mutex);
pthread_mutex_destroy(&bdev->mutex);
@ -944,15 +965,18 @@ spdk_bdev_unregister(struct spdk_bdev *bdev)
}
bool
spdk_bdev_claim(struct spdk_bdev *bdev)
spdk_bdev_claim(struct spdk_bdev *bdev, spdk_bdev_remove_cb_t remove_cb,
void *remove_ctx)
{
bool success;
pthread_mutex_lock(&bdev->mutex);
if (!bdev->claimed) {
if (bdev->status != SPDK_BDEV_STATUS_CLAIMED) {
/* Take ownership of bdev. */
bdev->claimed = true;
bdev->remove_cb = remove_cb;
bdev->remove_ctx = remove_ctx;
bdev->status = SPDK_BDEV_STATUS_CLAIMED;
success = true;
} else {
/* bdev is already claimed. */
@ -967,12 +991,21 @@ spdk_bdev_claim(struct spdk_bdev *bdev)
void
spdk_bdev_unclaim(struct spdk_bdev *bdev)
{
bool do_unregister = false;
pthread_mutex_lock(&bdev->mutex);
assert(bdev->claimed);
bdev->claimed = false;
assert(bdev->status == SPDK_BDEV_STATUS_CLAIMED || bdev->status == SPDK_BDEV_STATUS_REMOVING);
if (bdev->status == SPDK_BDEV_STATUS_REMOVING) {
do_unregister = true;
}
bdev->remove_cb = NULL;
bdev->remove_ctx = NULL;
bdev->status = SPDK_BDEV_STATUS_UNCLAIMED;
pthread_mutex_unlock(&bdev->mutex);
if (do_unregister == true) {
spdk_bdev_unregister(bdev);
}
}
void

View File

@ -72,7 +72,11 @@ spdk_rpc_get_bdevs(struct spdk_jsonrpc_server_conn *conn,
spdk_json_write_uint64(w, bdev->blockcnt);
spdk_json_write_name(w, "claimed");
spdk_json_write_bool(w, bdev->claimed);
if (bdev->status == SPDK_BDEV_STATUS_CLAIMED) {
spdk_json_write_bool(w, true);
} else {
spdk_json_write_bool(w, false);
}
spdk_json_write_name(w, "driver_specific");
spdk_json_write_object_begin(w);

View File

@ -241,7 +241,7 @@ vbdev_split_create(struct spdk_bdev *base_bdev, uint64_t split_count, uint64_t s
int rc;
struct split_base *split_base;
if (!spdk_bdev_claim(base_bdev)) {
if (!spdk_bdev_claim(base_bdev, NULL, NULL)) {
SPDK_ERRLOG("Split bdev %s is already claimed\n", base_bdev->name);
return -1;
}

View File

@ -412,7 +412,7 @@ spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bd
{
int i = 0;
if (!spdk_bdev_claim(bdev)) {
if (!spdk_bdev_claim(bdev, NULL, NULL)) {
SPDK_ERRLOG("Subsystem %s: bdev %s is already claimed\n",
subsystem->subnqn, bdev->name);
return -1;

View File

@ -290,7 +290,7 @@ spdk_scsi_lun_construct(const char *name, struct spdk_bdev *bdev)
return NULL;
}
if (!spdk_bdev_claim(bdev)) {
if (!spdk_bdev_claim(bdev, NULL, NULL)) {
SPDK_ERRLOG("LUN %s: bdev %s is already claimed\n", name, bdev->name);
free(lun);
return NULL;

View File

@ -112,7 +112,7 @@ bdevio_construct_targets(void)
bdev = spdk_bdev_first();
while (bdev != NULL) {
if (!spdk_bdev_claim(bdev)) {
if (!spdk_bdev_claim(bdev, NULL, NULL)) {
bdev = spdk_bdev_next(bdev);
continue;
}

View File

@ -122,7 +122,7 @@ bdevperf_construct_targets(void)
bdev = spdk_bdev_first();
while (bdev != NULL) {
if (!spdk_bdev_claim(bdev)) {
if (!spdk_bdev_claim(bdev, NULL, NULL)) {
bdev = spdk_bdev_next(bdev);
continue;
}

View File

@ -161,7 +161,8 @@ spdk_nvmf_session_poll(struct spdk_nvmf_session *session)
}
bool
spdk_bdev_claim(struct spdk_bdev *bdev)
spdk_bdev_claim(struct spdk_bdev *bdev, spdk_bdev_remove_cb_t remove_cb,
void *remove_ctx)
{
return true;
}

View File

@ -109,7 +109,8 @@ spdk_bdev_free_io(struct spdk_bdev_io *bdev_io)
}
bool
spdk_bdev_claim(struct spdk_bdev *bdev)
spdk_bdev_claim(struct spdk_bdev *bdev, spdk_bdev_remove_cb_t remove_cb,
void *remove_ctx)
{
return true;
}