Hello All,

I've been trying to track down the cause of some soft lockups with
call traces involving the iscsi initiator.  I believe I have found a
locking error in __iscsi_conn_send_pdu that is responsible.

A previous commit (4fa507992f0a ("scsi: libiscsi: Fix locking in
__iscsi_conn_send_pdu") changed the way that __iscsi_conn_send_pdu
acquires session->back_lock, from using spin_lock_bh to using
spin_lock.  However, half a dozen lines up the function is still using
spin_lock_bh to acquire conn->taskqueuelock.  I think the locking for
conn->taskqueuelock should be changed in the same way the locking for
conn->session->back_lock was changed.  A patch to do so follows.

Furthermore, I think that the message for the previous commit
understates the impact of the improper use of spin_lock_bh.  It states
that the use of spin_lock_bh here can trigger a WARN_ONCE.  I believe
it creates the possibility of deadlocks involving session->frwd_lock
and/or queue_lock, and that I have observed such a deadlock.

Here is the call trace from one soft lockup I have seen:

    Call Trace:
     <IRQ>
     do_raw_spin_lock+0xb2/0xc0
     _raw_spin_lock+0x55/0x70
     iscsi_check_transport_timeouts+0x24/0x1a0 [libiscsi]
     call_timer_fn+0xb9/0x3a0
     ? iscsi_complete_pdu+0x60/0x60 [libiscsi]
     run_timer_softirq+0x254/0x650
     __do_softirq+0xc5/0x4eb
     ? __iscsi_conn_send_pdu+0x1e3/0x420 [libiscsi]
     irq_exit+0xff/0x110
     smp_apic_timer_interrupt+0x3d/0x50
     apic_timer_interrupt+0x9d/0xb0
    RIP: 0010:__local_bh_enable_ip+0x74/0xa0
    RSP: 0018:ffffb0a60a26bc98 EFLAGS: 00000246 ORIG_RAX: ffffffffffffff10
    RAX: ffff901985f30000 RBX: 00000000fffffe00 RCX: 0000000000000002
    RDX: ffff901985f30000 RSI: 0000000000000001 RDI: ffffffffa9837ed4
    RBP: ffffb0a60a26bca8 R08: 0000000000000000 R09: 0000000000000000
    R10: ffff901985f30000 R11: 0000000000000002 R12: ffffffffc01b1ca3
    R13: ffff90198d8916a0 R14: ffff90199207d480 R15: ffff90199207d400
     </IRQ>
     ? __iscsi_conn_send_pdu+0x1e3/0x420 [libiscsi]
     ? dump_stack+0xaa/0xc6
     ? __local_bh_enable_ip+0x70/0xa0
     _raw_spin_unlock_bh+0x35/0x40
     __iscsi_conn_send_pdu+0x1e3/0x420 [libiscsi]
     iscsi_send_nopout+0xbe/0x110 [libiscsi]
     iscsi_eh_cmd_timed_out+0x2b7/0x2c0 [libiscsi]
     scsi_times_out+0x86/0x2b0
     blk_rq_timed_out+0x1f/0x60
     blk_timeout_work+0x11b/0x170
     process_one_work+0x250/0x690
     worker_thread+0x4e/0x3c0
     kthread+0x117/0x150
     ? process_one_work+0x690/0x690
     ? kthread_create_on_node+0x70/0x70
     ret_from_fork+0x2a/0x40

blk_timeout_work calls blk_rq_timed_out inside a spin_lock_irqsave, so
it should not be possible to take the softirq at this point.  I
believe, but would like to someone to confirm, that it is the use of
spin_lock_bh/spin_unlock_bh that makes it possible to take the irq
here.  A deadlock results from spin_lock of session->frwd_lock in the
softirq while it is already held by same cpu, having been acquired in
iscsi_eh_cmd_timed_out.

I have seen another similar soft lockup trace:

    <IRQ>
    queued_spin_lock_slowpath
    _raw_spin_lock
    iscsi_complete_pdu
    iscsi_tcp_process_data_in
    ... network driver and tcp stack ...
    net_rx_action
    __do_softirq
    do_softirq_own_stack
    <EOI>
    do_softirq
    __local_bh_enable_ip
    _raw_spin_unlock_bh
    __iscsi_conn_send_pdu
    iscsi_eh_cmd_timed_out
    scsi_times_out
    blk_rq_timed_out
    blk_timeout_work
    ...

Which I think is also a deadlock involving the spin_lock of
session->frwd_lock, in this instance following case ISCSI_OP_NOOP_IN:
in __iscsi_complete_pdu.


Feedback on the proposed change, patch, and whether it would be
expected to address the soft lockups I have seen are most welcome.


Best regards,

  --Chris

Reply via email to