Commit adbb4555 authored by Vladimir Neyelov's avatar Vladimir Neyelov Committed by Greg Kroah-Hartman

IB/iser: Fix connection teardown race condition

commit c8c16d3b upstream.

Under heavy iser target(scst) start/stop stress during login/logout
on iser intitiator side happened trace call provided below.

The function iscsi_iser_slave_alloc iser_conn pointer could be NULL,
due to the fact that function iscsi_iser_conn_stop can be called before
and free iser connection. Let's protect that flow by introducing global mutex.

BUG: unable to handle kernel paging request at 0000000000001018
IP: [<ffffffffc0426f7e>] iscsi_iser_slave_alloc+0x1e/0x50 [ib_iser]
Call Trace:
? scsi_alloc_sdev+0x242/0x300
scsi_probe_and_add_lun+0x9e1/0xea0
? kfree_const+0x21/0x30
? kobject_set_name_vargs+0x76/0x90
? __pm_runtime_resume+0x5b/0x70
__scsi_scan_target+0xf6/0x250
scsi_scan_target+0xea/0x100
iscsi_user_scan_session.part.13+0x101/0x130 [scsi_transport_iscsi]
? iscsi_user_scan_session.part.13+0x130/0x130 [scsi_transport_iscsi]
iscsi_user_scan_session+0x1e/0x30 [scsi_transport_iscsi]
device_for_each_child+0x50/0x90
iscsi_user_scan+0x44/0x60 [scsi_transport_iscsi]
store_scan+0xa8/0x100
? common_file_perm+0x5d/0x1c0
dev_attr_store+0x18/0x30
sysfs_kf_write+0x37/0x40
kernfs_fop_write+0x12c/0x1c0
__vfs_write+0x18/0x40
vfs_write+0xb5/0x1a0
SyS_write+0x55/0xc0

Fixes: 318d311e ("iser: Accept arbitrary sg lists mapping if the device supports it")
Signed-off-by: default avatarVladimir Neyelov <vladimirn@mellanox.com>
Signed-off-by: default avatarLeon Romanovsky <leon@kernel.org>
Reviewed-by: default avatarSagi Grimberg <sagi@grimbeg.me>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 6c0d8c2a
...@@ -83,6 +83,7 @@ static struct scsi_host_template iscsi_iser_sht; ...@@ -83,6 +83,7 @@ static struct scsi_host_template iscsi_iser_sht;
static struct iscsi_transport iscsi_iser_transport; static struct iscsi_transport iscsi_iser_transport;
static struct scsi_transport_template *iscsi_iser_scsi_transport; static struct scsi_transport_template *iscsi_iser_scsi_transport;
static struct workqueue_struct *release_wq; static struct workqueue_struct *release_wq;
static DEFINE_MUTEX(unbind_iser_conn_mutex);
struct iser_global ig; struct iser_global ig;
int iser_debug_level = 0; int iser_debug_level = 0;
...@@ -550,12 +551,14 @@ iscsi_iser_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) ...@@ -550,12 +551,14 @@ iscsi_iser_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
*/ */
if (iser_conn) { if (iser_conn) {
mutex_lock(&iser_conn->state_mutex); mutex_lock(&iser_conn->state_mutex);
mutex_lock(&unbind_iser_conn_mutex);
iser_conn_terminate(iser_conn); iser_conn_terminate(iser_conn);
iscsi_conn_stop(cls_conn, flag); iscsi_conn_stop(cls_conn, flag);
/* unbind */ /* unbind */
iser_conn->iscsi_conn = NULL; iser_conn->iscsi_conn = NULL;
conn->dd_data = NULL; conn->dd_data = NULL;
mutex_unlock(&unbind_iser_conn_mutex);
complete(&iser_conn->stop_completion); complete(&iser_conn->stop_completion);
mutex_unlock(&iser_conn->state_mutex); mutex_unlock(&iser_conn->state_mutex);
...@@ -977,13 +980,21 @@ static int iscsi_iser_slave_alloc(struct scsi_device *sdev) ...@@ -977,13 +980,21 @@ static int iscsi_iser_slave_alloc(struct scsi_device *sdev)
struct iser_conn *iser_conn; struct iser_conn *iser_conn;
struct ib_device *ib_dev; struct ib_device *ib_dev;
mutex_lock(&unbind_iser_conn_mutex);
session = starget_to_session(scsi_target(sdev))->dd_data; session = starget_to_session(scsi_target(sdev))->dd_data;
iser_conn = session->leadconn->dd_data; iser_conn = session->leadconn->dd_data;
if (!iser_conn) {
mutex_unlock(&unbind_iser_conn_mutex);
return -ENOTCONN;
}
ib_dev = iser_conn->ib_conn.device->ib_device; ib_dev = iser_conn->ib_conn.device->ib_device;
if (!(ib_dev->attrs.device_cap_flags & IB_DEVICE_SG_GAPS_REG)) if (!(ib_dev->attrs.device_cap_flags & IB_DEVICE_SG_GAPS_REG))
blk_queue_virt_boundary(sdev->request_queue, ~MASK_4K); blk_queue_virt_boundary(sdev->request_queue, ~MASK_4K);
mutex_unlock(&unbind_iser_conn_mutex);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment