vhost: set timeout for session's stop_poller

If there is still some inflight IO which prevents
vhost_session_stop_done(), stop_poller can try
within 4 seconds, and then call vhost_session_stop_done
with -ETIMEDOUT.

This can avoid endless blocking in ctrl pthread if there
is no response from vhost session or its backend bdev.
Then spdk vhost target can still serve all other vhost
devices and operations besides the error one.

Change-Id: I2fc78b4da926c936a2e42dc0e66ce1c60001330d
Signed-off-by: Liu Xiaodong <xiaodong.liu@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/10393
Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Liu Xiaodong 2021-11-24 15:05:55 -05:00 committed by Jim Harris
parent d39038e1b6
commit ba32ee2b29
4 changed files with 31 additions and 9 deletions

View File

@ -1564,6 +1564,10 @@ vhost_destroy_connection_cb(int vid)
if (vsession->started) {
rc = _stop_session(vsession);
if (rc != 0) {
pthread_mutex_unlock(&g_vhost_mutex);
return rc;
}
}
TAILQ_REMOVE(&vsession->vdev->vsessions, vsession, tailq);
@ -1571,7 +1575,7 @@ vhost_destroy_connection_cb(int vid)
free(vsession);
pthread_mutex_unlock(&g_vhost_mutex);
return rc;
return 0;
}
void

View File

@ -1346,11 +1346,16 @@ destroy_session_poller_cb(void *arg)
struct spdk_vhost_session *vsession = &bvsession->vsession;
int i;
if (vsession->task_cnt > 0) {
return SPDK_POLLER_BUSY;
}
if (vsession->task_cnt > 0 || spdk_vhost_trylock() != 0) {
assert(vsession->stop_retry_count > 0);
vsession->stop_retry_count--;
if (vsession->stop_retry_count == 0) {
SPDK_ERRLOG("%s: Timedout when destroy session (task_cnt %d)\n", vsession->name,
vsession->task_cnt);
spdk_poller_unregister(&bvsession->stop_poller);
vhost_session_stop_done(vsession, -ETIMEDOUT);
}
if (spdk_vhost_trylock() != 0) {
return SPDK_POLLER_BUSY;
}
@ -1387,6 +1392,8 @@ vhost_blk_stop_cb(struct spdk_vhost_dev *vdev,
vhost_blk_session_unregister_interrupts(bvsession);
}
/* vhost_session_send_event timeout is 3 seconds, here set retry within 4 seconds */
bvsession->vsession.stop_retry_count = 4000;
bvsession->stop_poller = SPDK_POLLER_REGISTER(destroy_session_poller_cb,
bvsession, 1000);
return 0;

View File

@ -166,6 +166,9 @@ struct spdk_vhost_session {
/* Interval used for event coalescing checking. */
uint64_t stats_check_interval;
/* Session's stop poller will only try limited times to destroy the session. */
uint32_t stop_retry_count;
struct spdk_vhost_virtqueue virtqueue[SPDK_VHOST_MAX_VQUEUES];
TAILQ_ENTRY(spdk_vhost_session) tailq;

View File

@ -1443,11 +1443,16 @@ destroy_session_poller_cb(void *arg)
struct spdk_scsi_dev_session_state *state;
uint32_t i;
if (vsession->task_cnt > 0) {
return SPDK_POLLER_BUSY;
}
if (vsession->task_cnt > 0 || spdk_vhost_trylock() != 0) {
assert(vsession->stop_retry_count > 0);
vsession->stop_retry_count--;
if (vsession->stop_retry_count == 0) {
SPDK_ERRLOG("%s: Timedout when destroy session (task_cnt %d)\n", vsession->name,
vsession->task_cnt);
spdk_poller_unregister(&svsession->stop_poller);
vhost_session_stop_done(vsession, -ETIMEDOUT);
}
if (spdk_vhost_trylock() != 0) {
return SPDK_POLLER_BUSY;
}
@ -1506,6 +1511,9 @@ vhost_scsi_stop_cb(struct spdk_vhost_dev *vdev,
*/
spdk_poller_unregister(&svsession->mgmt_poller);
/* vhost_session_send_event timeout is 3 seconds, here set retry within 4 seconds */
svsession->vsession.stop_retry_count = 4000;
/* Wait for all pending I/Os to complete, then process all the
* remaining hotremove events one last time.
*/