IB/qib: fix mcast detach when qp not attached
commit 09dc9cd6528f5b52bcbd3292a6312e762c85260f upstream. The code produces the following trace: [1750924.419007] general protection fault: 0000 [#3] SMP [1750924.420364] Modules linked in: nfnetlink autofs4 rpcsec_gss_krb5 nfsv4 dcdbas rfcomm bnep bluetooth nfsd auth_rpcgss nfs_acl dm_multipath nfs lockd scsi_dh sunrpc fscache radeon ttm drm_kms_helper drm serio_raw parport_pc ppdev i2c_algo_bit lpc_ich ipmi_si ib_mthca ib_qib dca lp parport ib_ipoib mac_hid ib_cm i3000_edac ib_sa ib_uverbs edac_core ib_umad ib_mad ib_core ib_addr tg3 ptp dm_mirror dm_region_hash dm_log psmouse pps_core [1750924.420364] CPU: 1 PID: 8401 Comm: python Tainted: G D 3.13.0-39-generic #66-Ubuntu [1750924.420364] Hardware name: Dell Computer Corporation PowerEdge 860/0XM089, BIOS A04 07/24/2007 [1750924.420364] task: ffff8800366a9800 ti: ffff88007af1c000 task.ti: ffff88007af1c000 [1750924.420364] RIP: 0010:[<ffffffffa0131d51>] [<ffffffffa0131d51>] qib_mcast_qp_free+0x11/0x50 [ib_qib] [1750924.420364] RSP: 0018:ffff88007af1dd70 EFLAGS: 00010246 [1750924.420364] RAX: 0000000000000001 RBX: ffff88007b822688 RCX: 000000000000000f [1750924.420364] RDX: ffff88007b822688 RSI: ffff8800366c15a0 RDI: 6764697200000000 [1750924.420364] RBP: ffff88007af1dd78 R08: 0000000000000001 R09: 0000000000000000 [1750924.420364] R10: 0000000000000011 R11: 0000000000000246 R12: ffff88007baa1d98 [1750924.420364] R13: ffff88003ecab000 R14: ffff88007b822660 R15: 0000000000000000 [1750924.420364] FS: 00007ffff7fd8740(0000) GS:ffff88007fc80000(0000) knlGS:0000000000000000 [1750924.420364] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [1750924.420364] CR2: 00007ffff597c750 CR3: 000000006860b000 CR4: 00000000000007e0 [1750924.420364] Stack: [1750924.420364] ffff88007b822688 ffff88007af1ddf0 ffffffffa0132429 000000007af1de20 [1750924.420364] ffff88007baa1dc8 ffff88007baa0000 ffff88007af1de70 ffffffffa00cb313 [1750924.420364] 00007fffffffde88 0000000000000000 0000000000000008 ffff88003ecab000 [1750924.420364] Call Trace: [1750924.420364] [<ffffffffa0132429>] qib_multicast_detach+0x1e9/0x350 [ib_qib] [1750924.568035] [<ffffffffa00cb313>] ? ib_uverbs_modify_qp+0x323/0x3d0 [ib_uverbs] [1750924.568035] [<ffffffffa0092d61>] ib_detach_mcast+0x31/0x50 [ib_core] [1750924.568035] [<ffffffffa00cc213>] ib_uverbs_detach_mcast+0x93/0x170 [ib_uverbs] [1750924.568035] [<ffffffffa00c61f6>] ib_uverbs_write+0xc6/0x2c0 [ib_uverbs] [1750924.568035] [<ffffffff81312e68>] ? apparmor_file_permission+0x18/0x20 [1750924.568035] [<ffffffff812d4cd3>] ? security_file_permission+0x23/0xa0 [1750924.568035] [<ffffffff811bd214>] vfs_write+0xb4/0x1f0 [1750924.568035] [<ffffffff811bdc49>] SyS_write+0x49/0xa0 [1750924.568035] [<ffffffff8172f7ed>] system_call_fastpath+0x1a/0x1f [1750924.568035] Code: 66 2e 0f 1f 84 00 00 00 00 00 31 c0 5d c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 0f 1f 44 00 00 55 48 89 e5 53 48 89 fb 48 8b 7f 10 <f0> ff 8f 40 01 00 00 74 0e 48 89 df e8 8e f8 06 e1 5b 5d c3 0f [1750924.568035] RIP [<ffffffffa0131d51>] qib_mcast_qp_free+0x11/0x50 [ib_qib] [1750924.568035] RSP <ffff88007af1dd70> [1750924.650439] ---[ end trace 73d5d4b3f8ad4851 ] The fix is to note the qib_mcast_qp that was found. If none is found, then return EINVAL indicating the error. Reviewed-by: Dennis Dalessandro <dennis.dalessandro@intel.com> Reported-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com> Signed-off-by: Doug Ledford <dledford@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
a81bfc00a3
commit
b6c92a436f
|
@ -286,15 +286,13 @@ int qib_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
|
||||||
struct qib_ibdev *dev = to_idev(ibqp->device);
|
struct qib_ibdev *dev = to_idev(ibqp->device);
|
||||||
struct qib_ibport *ibp = to_iport(ibqp->device, qp->port_num);
|
struct qib_ibport *ibp = to_iport(ibqp->device, qp->port_num);
|
||||||
struct qib_mcast *mcast = NULL;
|
struct qib_mcast *mcast = NULL;
|
||||||
struct qib_mcast_qp *p, *tmp;
|
struct qib_mcast_qp *p, *tmp, *delp = NULL;
|
||||||
struct rb_node *n;
|
struct rb_node *n;
|
||||||
int last = 0;
|
int last = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (ibqp->qp_num <= 1 || qp->state == IB_QPS_RESET) {
|
if (ibqp->qp_num <= 1 || qp->state == IB_QPS_RESET)
|
||||||
ret = -EINVAL;
|
return -EINVAL;
|
||||||
goto bail;
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_lock_irq(&ibp->lock);
|
spin_lock_irq(&ibp->lock);
|
||||||
|
|
||||||
|
@ -303,8 +301,7 @@ int qib_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
|
||||||
while (1) {
|
while (1) {
|
||||||
if (n == NULL) {
|
if (n == NULL) {
|
||||||
spin_unlock_irq(&ibp->lock);
|
spin_unlock_irq(&ibp->lock);
|
||||||
ret = -EINVAL;
|
return -EINVAL;
|
||||||
goto bail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mcast = rb_entry(n, struct qib_mcast, rb_node);
|
mcast = rb_entry(n, struct qib_mcast, rb_node);
|
||||||
|
@ -328,6 +325,7 @@ int qib_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
|
||||||
*/
|
*/
|
||||||
list_del_rcu(&p->list);
|
list_del_rcu(&p->list);
|
||||||
mcast->n_attached--;
|
mcast->n_attached--;
|
||||||
|
delp = p;
|
||||||
|
|
||||||
/* If this was the last attached QP, remove the GID too. */
|
/* If this was the last attached QP, remove the GID too. */
|
||||||
if (list_empty(&mcast->qp_list)) {
|
if (list_empty(&mcast->qp_list)) {
|
||||||
|
@ -338,15 +336,16 @@ int qib_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irq(&ibp->lock);
|
spin_unlock_irq(&ibp->lock);
|
||||||
|
/* QP not attached */
|
||||||
|
if (!delp)
|
||||||
|
return -EINVAL;
|
||||||
|
/*
|
||||||
|
* Wait for any list walkers to finish before freeing the
|
||||||
|
* list element.
|
||||||
|
*/
|
||||||
|
wait_event(mcast->wait, atomic_read(&mcast->refcount) <= 1);
|
||||||
|
qib_mcast_qp_free(delp);
|
||||||
|
|
||||||
if (p) {
|
|
||||||
/*
|
|
||||||
* Wait for any list walkers to finish before freeing the
|
|
||||||
* list element.
|
|
||||||
*/
|
|
||||||
wait_event(mcast->wait, atomic_read(&mcast->refcount) <= 1);
|
|
||||||
qib_mcast_qp_free(p);
|
|
||||||
}
|
|
||||||
if (last) {
|
if (last) {
|
||||||
atomic_dec(&mcast->refcount);
|
atomic_dec(&mcast->refcount);
|
||||||
wait_event(mcast->wait, !atomic_read(&mcast->refcount));
|
wait_event(mcast->wait, !atomic_read(&mcast->refcount));
|
||||||
|
@ -355,11 +354,7 @@ int qib_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
|
||||||
dev->n_mcast_grps_allocated--;
|
dev->n_mcast_grps_allocated--;
|
||||||
spin_unlock_irq(&dev->n_mcast_grps_lock);
|
spin_unlock_irq(&dev->n_mcast_grps_lock);
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
bail:
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int qib_mcast_tree_empty(struct qib_ibport *ibp)
|
int qib_mcast_tree_empty(struct qib_ibport *ibp)
|
||||||
|
|
Loading…
Reference in New Issue