lib/iscsi: Wait until all PDUs are flushed for LUN hotplug
We ensure current pending tasks are aborted and no new task or PDU is pending after LUN is unplugged now. Then we have to ensure all task completions and aborts are sent to initiator. However, we had removed pending tasks without any notification to initiator. For this implementation, we are not surprised if initiator waits for in-flight commands for a long time. Due to recent refinements of LUN hotplug, we can wait safely that all existing tasks complete or abort. In _iscsi_conn_hotremove_lun(), after aborting R2Ts, start a poller to wait until all PDUs for the LUN are flushed. Then close the LUN. We can safely free deferred PDUs for the LUN because they are already flushed. Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Change-Id: I869b79a7c93d2e8a4a1577cc20d3b466548dfaaa Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/476033 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:
parent
081153a82c
commit
27d79ee367
@ -447,6 +447,7 @@ iscsi_conn_close_lun(struct spdk_iscsi_conn *conn, int lun_id)
|
||||
|
||||
spdk_scsi_lun_free_io_channel(iscsi_lun->desc);
|
||||
spdk_scsi_lun_close(iscsi_lun->desc);
|
||||
spdk_poller_unregister(&iscsi_lun->remove_poller);
|
||||
free(iscsi_lun);
|
||||
|
||||
conn->luns[lun_id] = NULL;
|
||||
@ -462,13 +463,62 @@ iscsi_conn_close_luns(struct spdk_iscsi_conn *conn)
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
iscsi_conn_check_tasks_for_lun(struct spdk_iscsi_conn *conn,
|
||||
struct spdk_scsi_lun *lun)
|
||||
{
|
||||
struct spdk_iscsi_pdu *pdu, *tmp_pdu;
|
||||
struct spdk_iscsi_task *task;
|
||||
|
||||
assert(lun != NULL);
|
||||
|
||||
/* We can remove deferred PDUs safely because they are already flushed. */
|
||||
TAILQ_FOREACH_SAFE(pdu, &conn->snack_pdu_list, tailq, tmp_pdu) {
|
||||
if (lun == pdu->task->scsi.lun) {
|
||||
TAILQ_REMOVE(&conn->snack_pdu_list, pdu, tailq);
|
||||
spdk_iscsi_conn_free_pdu(conn, pdu);
|
||||
}
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(task, &conn->queued_datain_tasks, link) {
|
||||
if (lun == task->scsi.lun) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* This check loop works even when connection exits in the middle of LUN hotplug
|
||||
* because all PDUs in write_pdu_list are removed in iscsi_conn_free_tasks().
|
||||
*/
|
||||
TAILQ_FOREACH(pdu, &conn->write_pdu_list, tailq) {
|
||||
if (pdu->task && lun == pdu->task->scsi.lun) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
iscsi_conn_remove_lun(void *ctx)
|
||||
{
|
||||
struct spdk_iscsi_lun *iscsi_lun = ctx;
|
||||
struct spdk_iscsi_conn *conn = iscsi_lun->conn;
|
||||
struct spdk_scsi_lun *lun = iscsi_lun->lun;
|
||||
int lun_id = spdk_scsi_lun_get_id(lun);
|
||||
|
||||
if (!iscsi_conn_check_tasks_for_lun(conn, lun)) {
|
||||
return -1;
|
||||
}
|
||||
iscsi_conn_close_lun(conn, lun_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
_iscsi_conn_hotremove_lun(void *ctx)
|
||||
{
|
||||
struct spdk_iscsi_lun *iscsi_lun = ctx;
|
||||
struct spdk_iscsi_conn *conn = iscsi_lun->conn;
|
||||
struct spdk_scsi_lun *lun = iscsi_lun->lun;
|
||||
int lun_id = spdk_scsi_lun_get_id(lun);
|
||||
|
||||
assert(spdk_io_channel_get_thread(spdk_io_channel_from_ctx(conn->pg)) ==
|
||||
spdk_get_thread());
|
||||
@ -479,9 +529,9 @@ _iscsi_conn_hotremove_lun(void *ctx)
|
||||
}
|
||||
|
||||
spdk_clear_all_transfer_task(conn, lun, NULL);
|
||||
_iscsi_conn_free_tasks(conn, lun);
|
||||
|
||||
iscsi_conn_close_lun(conn, lun_id);
|
||||
iscsi_lun->remove_poller = spdk_poller_register(iscsi_conn_remove_lun, iscsi_lun,
|
||||
1000);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -88,6 +88,7 @@ struct spdk_iscsi_lun {
|
||||
struct spdk_iscsi_conn *conn;
|
||||
struct spdk_scsi_lun *lun;
|
||||
struct spdk_scsi_lun_desc *desc;
|
||||
struct spdk_poller *remove_poller;
|
||||
};
|
||||
|
||||
struct spdk_iscsi_conn {
|
||||
|
Loading…
Reference in New Issue
Block a user