From 50529593c4cad4c6113b38d14e8cafdf8a80493a Mon Sep 17 00:00:00 2001 From: Ben Walker Date: Mon, 30 Mar 2020 15:07:14 -0700 Subject: [PATCH] bdev/iscsi: Release lun poller on correct thread. If thread A is the first to grab a channel, the poller will be on thread A. But then if the shutdown happens such that thread B is the final channel to release it's channel, it will attempt to free the lun poller from thread B and crash. Change-Id: I354f9f28d55e5e82cb6c737c734acadbd80e283d Signed-off-by: Ben Walker Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/1590 Community-CI: Broadcom CI Tested-by: SPDK CI Jenkins Reviewed-by: Jim Harris Reviewed-by: Shuhei Matsumoto --- module/bdev/iscsi/bdev_iscsi.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/module/bdev/iscsi/bdev_iscsi.c b/module/bdev/iscsi/bdev_iscsi.c index 45cd89c94..3b6ad82ca 100644 --- a/module/bdev/iscsi/bdev_iscsi.c +++ b/module/bdev/iscsi/bdev_iscsi.c @@ -521,16 +521,50 @@ bdev_iscsi_create_cb(void *io_device, void *ctx_buf) return 0; } +static void +_iscsi_destroy_cb(void *ctx) +{ + struct bdev_iscsi_lun *lun = ctx; + + pthread_mutex_lock(&lun->mutex); + + assert(lun->master_td == spdk_get_thread()); + assert(lun->ch_count > 0); + + lun->ch_count--; + if (lun->ch_count > 0) { + pthread_mutex_unlock(&lun->mutex); + return; + } + + lun->master_td = NULL; + spdk_poller_unregister(&lun->poller); + + pthread_mutex_unlock(&lun->mutex); +} + static void bdev_iscsi_destroy_cb(void *io_device, void *ctx_buf) { struct bdev_iscsi_lun *lun = io_device; + struct spdk_thread *thread; pthread_mutex_lock(&lun->mutex); lun->ch_count--; if (lun->ch_count == 0) { assert(lun->master_td != NULL); + if (lun->master_td != spdk_get_thread()) { + /* The final channel was destroyed on a different thread + * than where the first channel was created. Pass a message + * to the master thread to unregister the poller. */ + lun->ch_count++; + thread = lun->master_td; + pthread_mutex_unlock(&lun->mutex); + spdk_thread_send_msg(thread, _iscsi_destroy_cb, lun); + return; + } + lun->master_td = NULL; spdk_poller_unregister(&lun->poller); }