bdev/virtio: add rescan safety checks
Don't allow starting full device rescan if such scan is already in progress. This patch also makes it possible to start a full scan while only particular targets are being rescanned. Change-Id: I8677f640a4e5d9d8c486dfe1e9a58331e941a461 Signed-off-by: Dariusz Stojaczyk <dariuszx.stojaczyk@intel.com> Reviewed-on: https://review.gerrithub.io/392373 Tested-by: SPDK Automated Test System <sys_sgsw@intel.com> Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
parent
5eea99fc57
commit
166f6e9cb8
@ -130,6 +130,9 @@ struct virtio_scsi_scan_base {
|
|||||||
/** Scan all targets on the device. */
|
/** Scan all targets on the device. */
|
||||||
bool full_scan;
|
bool full_scan;
|
||||||
|
|
||||||
|
/** Start a full rescan after receiving next scan I/O response. */
|
||||||
|
bool restart;
|
||||||
|
|
||||||
/** Additional targets to be (re)scanned. */
|
/** Additional targets to be (re)scanned. */
|
||||||
TAILQ_HEAD(, virtio_scsi_scan_info) scan_queue;
|
TAILQ_HEAD(, virtio_scsi_scan_info) scan_queue;
|
||||||
|
|
||||||
@ -697,6 +700,7 @@ bdev_virtio_poll(void *arg)
|
|||||||
{
|
{
|
||||||
struct bdev_virtio_io_channel *ch = arg;
|
struct bdev_virtio_io_channel *ch = arg;
|
||||||
struct virtio_scsi_dev *svdev = ch->svdev;
|
struct virtio_scsi_dev *svdev = ch->svdev;
|
||||||
|
struct virtio_scsi_scan_base *scan_ctx = svdev->scan_ctx;
|
||||||
void *io[32];
|
void *io[32];
|
||||||
uint32_t io_len[32];
|
uint32_t io_len[32];
|
||||||
uint16_t i, cnt;
|
uint16_t i, cnt;
|
||||||
@ -704,34 +708,41 @@ bdev_virtio_poll(void *arg)
|
|||||||
|
|
||||||
cnt = virtio_recv_pkts(ch->vq, (void **)io, io_len, SPDK_COUNTOF(io));
|
cnt = virtio_recv_pkts(ch->vq, (void **)io, io_len, SPDK_COUNTOF(io));
|
||||||
for (i = 0; i < cnt; ++i) {
|
for (i = 0; i < cnt; ++i) {
|
||||||
if (spdk_unlikely(svdev->scan_ctx && io[i] == &svdev->scan_ctx->io_ctx)) {
|
if (spdk_unlikely(scan_ctx && io[i] == &scan_ctx->io_ctx)) {
|
||||||
if (svdev->removed) {
|
if (svdev->removed) {
|
||||||
_virtio_scsi_dev_scan_finish(svdev->scan_ctx, -EINTR);
|
_virtio_scsi_dev_scan_finish(scan_ctx, -EINTR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
process_scan_resp(svdev->scan_ctx);
|
if (scan_ctx->restart) {
|
||||||
|
scan_ctx->restart = false;
|
||||||
|
scan_ctx->full_scan = true;
|
||||||
|
_virtio_scsi_dev_scan_tgt(scan_ctx, 0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
process_scan_resp(scan_ctx);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdev_virtio_io_cpl(io[i]);
|
bdev_virtio_io_cpl(io[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spdk_unlikely(svdev->scan_ctx && svdev->scan_ctx->needs_resend)) {
|
if (spdk_unlikely(scan_ctx && scan_ctx->needs_resend)) {
|
||||||
if (svdev->removed) {
|
if (svdev->removed) {
|
||||||
_virtio_scsi_dev_scan_finish(svdev->scan_ctx, -EINTR);
|
_virtio_scsi_dev_scan_finish(scan_ctx, -EINTR);
|
||||||
return;
|
return;
|
||||||
} else if (cnt == 0) {
|
} else if (cnt == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = send_scan_io(svdev->scan_ctx);
|
rc = send_scan_io(scan_ctx);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
assert(svdev->scan_ctx->retries > 0);
|
assert(scan_ctx->retries > 0);
|
||||||
svdev->scan_ctx->retries--;
|
scan_ctx->retries--;
|
||||||
if (svdev->scan_ctx->retries == 0) {
|
if (scan_ctx->retries == 0) {
|
||||||
SPDK_ERRLOG("Target scan failed unrecoverably with rc = %d.\n", rc);
|
SPDK_ERRLOG("Target scan failed unrecoverably with rc = %d.\n", rc);
|
||||||
_virtio_scsi_dev_scan_finish(svdev->scan_ctx, rc);
|
_virtio_scsi_dev_scan_finish(scan_ctx, rc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1511,8 +1522,28 @@ virtio_scsi_dev_scan(struct virtio_scsi_dev *svdev, bdev_virtio_create_cb cb_fn,
|
|||||||
void *cb_arg)
|
void *cb_arg)
|
||||||
{
|
{
|
||||||
struct virtio_scsi_scan_base *base;
|
struct virtio_scsi_scan_base *base;
|
||||||
|
struct virtio_scsi_scan_info *tgt, *next_tgt;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
if (svdev->scan_ctx) {
|
||||||
|
if (svdev->scan_ctx->full_scan) {
|
||||||
|
return -EEXIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We're about to start a full rescan, so there's no need
|
||||||
|
* to scan particular targets afterwards.
|
||||||
|
*/
|
||||||
|
TAILQ_FOREACH_SAFE(tgt, &svdev->scan_ctx->scan_queue, tailq, next_tgt) {
|
||||||
|
TAILQ_REMOVE(&svdev->scan_ctx->scan_queue, tgt, tailq);
|
||||||
|
free(tgt);
|
||||||
|
}
|
||||||
|
|
||||||
|
svdev->scan_ctx->cb_fn = cb_fn;
|
||||||
|
svdev->scan_ctx->cb_arg = cb_arg;
|
||||||
|
svdev->scan_ctx->restart = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
rc = _virtio_scsi_dev_scan_init(svdev);
|
rc = _virtio_scsi_dev_scan_init(svdev);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
return rc;
|
return rc;
|
||||||
|
Loading…
Reference in New Issue
Block a user