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:
parent
b9ca539390
commit
77183f9722
@ -55,10 +55,20 @@
|
|||||||
#define SPDK_BDEV_MAX_NAME_LENGTH 16
|
#define SPDK_BDEV_MAX_NAME_LENGTH 16
|
||||||
#define SPDK_BDEV_MAX_PRODUCT_NAME_LENGTH 50
|
#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_io;
|
||||||
struct spdk_bdev_fn_table;
|
struct spdk_bdev_fn_table;
|
||||||
struct spdk_json_write_ctx;
|
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.
|
* \brief SPDK block device.
|
||||||
*
|
*
|
||||||
@ -104,8 +114,14 @@ struct spdk_bdev {
|
|||||||
/** Mutex protecting claimed */
|
/** Mutex protecting claimed */
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
|
|
||||||
/** True if another blockdev or a LUN is using this device */
|
/** The bdev status */
|
||||||
bool claimed;
|
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;
|
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().
|
* When the ownership of the bdev is no longer needed, the user should call spdk_bdev_unclaim().
|
||||||
*
|
*
|
||||||
* \param bdev Block device to claim.
|
* \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.
|
* \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.
|
* Release claim of ownership of a block device.
|
||||||
|
@ -546,6 +546,7 @@ spdk_bdev_read(struct spdk_bdev *bdev, struct spdk_io_channel *ch,
|
|||||||
struct spdk_bdev_io *bdev_io;
|
struct spdk_bdev_io *bdev_io;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
assert(bdev->status != SPDK_BDEV_STATUS_UNCLAIMED);
|
||||||
if (spdk_bdev_io_valid(bdev, offset, nbytes) != 0) {
|
if (spdk_bdev_io_valid(bdev, offset, nbytes) != 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -585,6 +586,7 @@ spdk_bdev_readv(struct spdk_bdev *bdev, struct spdk_io_channel *ch,
|
|||||||
struct spdk_bdev_io *bdev_io;
|
struct spdk_bdev_io *bdev_io;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
assert(bdev->status != SPDK_BDEV_STATUS_UNCLAIMED);
|
||||||
if (spdk_bdev_io_valid(bdev, offset, nbytes) != 0) {
|
if (spdk_bdev_io_valid(bdev, offset, nbytes) != 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -621,6 +623,7 @@ spdk_bdev_write(struct spdk_bdev *bdev, struct spdk_io_channel *ch,
|
|||||||
struct spdk_bdev_io *bdev_io;
|
struct spdk_bdev_io *bdev_io;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
assert(bdev->status != SPDK_BDEV_STATUS_UNCLAIMED);
|
||||||
if (spdk_bdev_io_valid(bdev, offset, nbytes) != 0) {
|
if (spdk_bdev_io_valid(bdev, offset, nbytes) != 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -659,6 +662,7 @@ spdk_bdev_writev(struct spdk_bdev *bdev, struct spdk_io_channel *ch,
|
|||||||
struct spdk_bdev_io *bdev_io;
|
struct spdk_bdev_io *bdev_io;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
assert(bdev->status != SPDK_BDEV_STATUS_UNCLAIMED);
|
||||||
if (spdk_bdev_io_valid(bdev, offset, len) != 0) {
|
if (spdk_bdev_io_valid(bdev, offset, len) != 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -695,6 +699,7 @@ spdk_bdev_unmap(struct spdk_bdev *bdev, struct spdk_io_channel *ch,
|
|||||||
struct spdk_bdev_io *bdev_io;
|
struct spdk_bdev_io *bdev_io;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
assert(bdev->status != SPDK_BDEV_STATUS_UNCLAIMED);
|
||||||
if (bdesc_count == 0) {
|
if (bdesc_count == 0) {
|
||||||
SPDK_ERRLOG("Invalid bdesc_count 0\n");
|
SPDK_ERRLOG("Invalid bdesc_count 0\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -735,6 +740,7 @@ spdk_bdev_flush(struct spdk_bdev *bdev, struct spdk_io_channel *ch,
|
|||||||
struct spdk_bdev_io *bdev_io;
|
struct spdk_bdev_io *bdev_io;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
assert(bdev->status != SPDK_BDEV_STATUS_UNCLAIMED);
|
||||||
bdev_io = spdk_bdev_get_io();
|
bdev_io = spdk_bdev_get_io();
|
||||||
if (!bdev_io) {
|
if (!bdev_io) {
|
||||||
SPDK_ERRLOG("bdev_io memory allocation failed duing flush\n");
|
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;
|
struct spdk_bdev_io *bdev_io;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
assert(bdev->status != SPDK_BDEV_STATUS_UNCLAIMED);
|
||||||
bdev_io = spdk_bdev_get_io();
|
bdev_io = spdk_bdev_get_io();
|
||||||
if (!bdev_io) {
|
if (!bdev_io) {
|
||||||
SPDK_ERRLOG("bdev_io memory allocation failed duing reset\n");
|
SPDK_ERRLOG("bdev_io memory allocation failed duing reset\n");
|
||||||
@ -921,8 +928,7 @@ spdk_bdev_register(struct spdk_bdev *bdev)
|
|||||||
bdev->gencnt = 0;
|
bdev->gencnt = 0;
|
||||||
|
|
||||||
pthread_mutex_init(&bdev->mutex, NULL);
|
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);
|
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "Inserting bdev %s into list\n", bdev->name);
|
||||||
TAILQ_INSERT_TAIL(&spdk_bdev_list, bdev, link);
|
TAILQ_INSERT_TAIL(&spdk_bdev_list, bdev, link);
|
||||||
}
|
}
|
||||||
@ -933,7 +939,22 @@ spdk_bdev_unregister(struct spdk_bdev *bdev)
|
|||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "Removing bdev %s from list\n", bdev->name);
|
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);
|
TAILQ_REMOVE(&spdk_bdev_list, bdev, link);
|
||||||
|
pthread_mutex_unlock(&bdev->mutex);
|
||||||
|
|
||||||
pthread_mutex_destroy(&bdev->mutex);
|
pthread_mutex_destroy(&bdev->mutex);
|
||||||
|
|
||||||
@ -944,15 +965,18 @@ spdk_bdev_unregister(struct spdk_bdev *bdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
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;
|
bool success;
|
||||||
|
|
||||||
pthread_mutex_lock(&bdev->mutex);
|
pthread_mutex_lock(&bdev->mutex);
|
||||||
|
|
||||||
if (!bdev->claimed) {
|
if (bdev->status != SPDK_BDEV_STATUS_CLAIMED) {
|
||||||
/* Take ownership of bdev. */
|
/* 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;
|
success = true;
|
||||||
} else {
|
} else {
|
||||||
/* bdev is already claimed. */
|
/* bdev is already claimed. */
|
||||||
@ -967,12 +991,21 @@ spdk_bdev_claim(struct spdk_bdev *bdev)
|
|||||||
void
|
void
|
||||||
spdk_bdev_unclaim(struct spdk_bdev *bdev)
|
spdk_bdev_unclaim(struct spdk_bdev *bdev)
|
||||||
{
|
{
|
||||||
|
bool do_unregister = false;
|
||||||
|
|
||||||
pthread_mutex_lock(&bdev->mutex);
|
pthread_mutex_lock(&bdev->mutex);
|
||||||
|
assert(bdev->status == SPDK_BDEV_STATUS_CLAIMED || bdev->status == SPDK_BDEV_STATUS_REMOVING);
|
||||||
assert(bdev->claimed);
|
if (bdev->status == SPDK_BDEV_STATUS_REMOVING) {
|
||||||
bdev->claimed = false;
|
do_unregister = true;
|
||||||
|
}
|
||||||
|
bdev->remove_cb = NULL;
|
||||||
|
bdev->remove_ctx = NULL;
|
||||||
|
bdev->status = SPDK_BDEV_STATUS_UNCLAIMED;
|
||||||
pthread_mutex_unlock(&bdev->mutex);
|
pthread_mutex_unlock(&bdev->mutex);
|
||||||
|
|
||||||
|
if (do_unregister == true) {
|
||||||
|
spdk_bdev_unregister(bdev);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -72,7 +72,11 @@ spdk_rpc_get_bdevs(struct spdk_jsonrpc_server_conn *conn,
|
|||||||
spdk_json_write_uint64(w, bdev->blockcnt);
|
spdk_json_write_uint64(w, bdev->blockcnt);
|
||||||
|
|
||||||
spdk_json_write_name(w, "claimed");
|
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_name(w, "driver_specific");
|
||||||
spdk_json_write_object_begin(w);
|
spdk_json_write_object_begin(w);
|
||||||
|
@ -241,7 +241,7 @@ vbdev_split_create(struct spdk_bdev *base_bdev, uint64_t split_count, uint64_t s
|
|||||||
int rc;
|
int rc;
|
||||||
struct split_base *split_base;
|
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);
|
SPDK_ERRLOG("Split bdev %s is already claimed\n", base_bdev->name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -412,7 +412,7 @@ spdk_nvmf_subsystem_add_ns(struct spdk_nvmf_subsystem *subsystem, struct spdk_bd
|
|||||||
{
|
{
|
||||||
int i = 0;
|
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",
|
SPDK_ERRLOG("Subsystem %s: bdev %s is already claimed\n",
|
||||||
subsystem->subnqn, bdev->name);
|
subsystem->subnqn, bdev->name);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -290,7 +290,7 @@ spdk_scsi_lun_construct(const char *name, struct spdk_bdev *bdev)
|
|||||||
return NULL;
|
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);
|
SPDK_ERRLOG("LUN %s: bdev %s is already claimed\n", name, bdev->name);
|
||||||
free(lun);
|
free(lun);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -112,7 +112,7 @@ bdevio_construct_targets(void)
|
|||||||
bdev = spdk_bdev_first();
|
bdev = spdk_bdev_first();
|
||||||
while (bdev != NULL) {
|
while (bdev != NULL) {
|
||||||
|
|
||||||
if (!spdk_bdev_claim(bdev)) {
|
if (!spdk_bdev_claim(bdev, NULL, NULL)) {
|
||||||
bdev = spdk_bdev_next(bdev);
|
bdev = spdk_bdev_next(bdev);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ bdevperf_construct_targets(void)
|
|||||||
bdev = spdk_bdev_first();
|
bdev = spdk_bdev_first();
|
||||||
while (bdev != NULL) {
|
while (bdev != NULL) {
|
||||||
|
|
||||||
if (!spdk_bdev_claim(bdev)) {
|
if (!spdk_bdev_claim(bdev, NULL, NULL)) {
|
||||||
bdev = spdk_bdev_next(bdev);
|
bdev = spdk_bdev_next(bdev);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -161,7 +161,8 @@ spdk_nvmf_session_poll(struct spdk_nvmf_session *session)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,8 @@ spdk_bdev_free_io(struct spdk_bdev_io *bdev_io)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user