mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-19 03:31:26 +00:00
ib_srpt: Avoid that module unloading races with closing sessions (merge r4446 from trunk)
Fixed issue:
BUG: unable to handle kernel paging request at ffffffffa04dc479
IP: [<ffffffffa04dc479>] 0xffffffffa04dc478
Oops: 0010 [#1] SMP
Pid: 29313, comm: srpt_mlx4_0-2 Tainted: G O 3.6.0-rc1-debug+ #1
Process srpt_mlx4_0-2
Call Trace:
[<ffffffff8106254e>] ? kthread+0xae/0xc0
[<ffffffff81418464>] ? kernel_thread_helper+0x4/0x10
[<ffffffff8140f080>] ? _raw_spin_unlock_irq+0x30/0x50
[<ffffffff810983ad>] ? trace_hardirqs_on+0xd/0x10
[<ffffffff8140f359>] ? retint_restore_args+0xe/0xe
[<ffffffff810624a0>] ? __init_kthread_worker+0x70/0x70
[<ffffffff81418460>] ? gs_change+0xb/0xb
Code: Bad RIP value.
git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/2.2.x@4625 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -2016,10 +2016,51 @@ static void srpt_free_ch(struct kref *kref)
|
||||
kfree(ch);
|
||||
}
|
||||
|
||||
static void srpt_unreg_sess(struct scst_session *scst_sess)
|
||||
{
|
||||
struct srpt_rdma_ch *ch = scst_sess_get_tgt_priv(scst_sess);
|
||||
struct srpt_device *sdev = ch->sport->sdev;
|
||||
|
||||
kthread_stop(ch->thread);
|
||||
|
||||
srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_ring,
|
||||
sdev, ch->rq_size,
|
||||
ch->max_rsp_size, DMA_TO_DEVICE);
|
||||
|
||||
/*
|
||||
* Note: if a DREQ is received after ch->dreq_received has been read,
|
||||
* ib_destroy_cm_id() will send a DREP.
|
||||
*
|
||||
*/
|
||||
if (ch->dreq_received) {
|
||||
if (ib_send_cm_drep(ch->cm_id, NULL, 0) >= 0)
|
||||
PRINT_INFO("Received DREQ and sent DREP for session %s",
|
||||
ch->sess_name);
|
||||
else
|
||||
PRINT_ERROR("%s", "Sending DREP failed");
|
||||
}
|
||||
|
||||
/*
|
||||
* If the connection is still established, ib_destroy_cm_id() will
|
||||
* send a DREQ.
|
||||
*/
|
||||
ib_destroy_cm_id(ch->cm_id);
|
||||
|
||||
/*
|
||||
* Invoke wake_up() inside the lock to avoid that sdev disappears
|
||||
* after list_del() and before wake_up() has been invoked.
|
||||
*/
|
||||
spin_lock_irq(&sdev->spinlock);
|
||||
list_del(&ch->list);
|
||||
wake_up(&sdev->ch_releaseQ);
|
||||
spin_unlock_irq(&sdev->spinlock);
|
||||
|
||||
kref_put(&ch->kref, srpt_free_ch);
|
||||
}
|
||||
|
||||
static int srpt_compl_thread(void *arg)
|
||||
{
|
||||
struct srpt_rdma_ch *ch;
|
||||
struct srpt_device *sdev;
|
||||
|
||||
/* Hibernation / freezing of the SRPT kernel thread is not supported. */
|
||||
current->flags |= PF_NOFREEZE;
|
||||
@@ -2066,34 +2107,10 @@ static int srpt_compl_thread(void *arg)
|
||||
|
||||
TRACE_DBG("ch %s: about to invoke scst_unregister_session()",
|
||||
ch->sess_name);
|
||||
scst_unregister_session(ch->scst_sess, true, NULL);
|
||||
scst_unregister_session(ch->scst_sess, false, srpt_unreg_sess);
|
||||
|
||||
sdev = ch->sport->sdev;
|
||||
srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_ring,
|
||||
sdev, ch->rq_size,
|
||||
ch->max_rsp_size, DMA_TO_DEVICE);
|
||||
|
||||
spin_lock_irq(&sdev->spinlock);
|
||||
list_del(&ch->list);
|
||||
spin_unlock_irq(&sdev->spinlock);
|
||||
|
||||
if (ch->dreq_received) {
|
||||
if (ib_send_cm_drep(ch->cm_id, NULL, 0) >= 0)
|
||||
PRINT_INFO("Received DREQ and sent DREP for session %s",
|
||||
ch->sess_name);
|
||||
else
|
||||
PRINT_ERROR("%s", "Sending DREP failed");
|
||||
}
|
||||
|
||||
/*
|
||||
* If the connection is still established, ib_destroy_cm_id() will
|
||||
* send a DREQ.
|
||||
*/
|
||||
ib_destroy_cm_id(ch->cm_id);
|
||||
|
||||
kref_put(&ch->kref, srpt_free_ch);
|
||||
|
||||
wake_up(&sdev->ch_releaseQ);
|
||||
while (!kthread_should_stop())
|
||||
schedule_timeout(DIV_ROUND_UP(HZ, 10));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user