From 5909ce545db415ae8c26e849df862e8cc1acf571 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 30 Apr 2012 12:51:50 -0700 Subject: [PATCH] IB/uverbs: Lock SRQ / CQ / PD objects in a consistent order Since XRC support was added, the uverbs code has locked SRQ, CQ and PD objects needed during QP and SRQ creation in different orders depending on the the code path. This leads to the (at least theoretical) possibility of deadlock, and triggers the lockdep splat below. Fix this by making sure we always lock the SRQ first, then CQs and finally the PD. ====================================================== [ INFO: possible circular locking dependency detected ] 3.4.0-rc5+ #34 Not tainted ------------------------------------------------------- ibv_srq_pingpon/2484 is trying to acquire lock: (SRQ-uobj){+++++.}, at: [] idr_read_uobj+0x2f/0x4d [ib_uverbs] but task is already holding lock: (CQ-uobj){+++++.}, at: [] idr_read_uobj+0x2f/0x4d [ib_uverbs] which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #2 (CQ-uobj){+++++.}: [] lock_acquire+0xbf/0xfe [] down_read+0x34/0x43 [] idr_read_uobj+0x2f/0x4d [ib_uverbs] [] idr_read_obj+0x9/0x19 [ib_uverbs] [] ib_uverbs_create_qp+0x180/0x684 [ib_uverbs] [] ib_uverbs_write+0xb7/0xc2 [ib_uverbs] [] vfs_write+0xa7/0xee [] sys_write+0x45/0x69 [] system_call_fastpath+0x16/0x1b -> #1 (PD-uobj){++++++}: [] lock_acquire+0xbf/0xfe [] down_read+0x34/0x43 [] idr_read_uobj+0x2f/0x4d [ib_uverbs] [] idr_read_obj+0x9/0x19 [ib_uverbs] [] __uverbs_create_xsrq+0x96/0x386 [ib_uverbs] [] ib_uverbs_detach_mcast+0x1cd/0x1e6 [ib_uverbs] [] ib_uverbs_write+0xb7/0xc2 [ib_uverbs] [] vfs_write+0xa7/0xee [] sys_write+0x45/0x69 [] system_call_fastpath+0x16/0x1b -> #0 (SRQ-uobj){+++++.}: [] __lock_acquire+0xa29/0xd06 [] lock_acquire+0xbf/0xfe [] down_read+0x34/0x43 [] idr_read_uobj+0x2f/0x4d [ib_uverbs] [] idr_read_obj+0x9/0x19 [ib_uverbs] [] ib_uverbs_create_qp+0x1e5/0x684 [ib_uverbs] [] ib_uverbs_write+0xb7/0xc2 [ib_uverbs] [] vfs_write+0xa7/0xee [] sys_write+0x45/0x69 [] system_call_fastpath+0x16/0x1b other info that might help us debug this: Chain exists of: SRQ-uobj --> PD-uobj --> CQ-uobj Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(CQ-uobj); lock(PD-uobj); lock(CQ-uobj); lock(SRQ-uobj); *** DEADLOCK *** 3 locks held by ibv_srq_pingpon/2484: #0: (QP-uobj){+.+...}, at: [] ib_uverbs_create_qp+0xe9/0x684 [ib_uverbs] #1: (PD-uobj){++++++}, at: [] idr_read_uobj+0x2f/0x4d [ib_uverbs] #2: (CQ-uobj){+++++.}, at: [] idr_read_uobj+0x2f/0x4d [ib_uverbs] stack backtrace: Pid: 2484, comm: ibv_srq_pingpon Not tainted 3.4.0-rc5+ #34 Call Trace: [] print_circular_bug+0x1f8/0x209 [] __lock_acquire+0xa29/0xd06 [] ? __idr_get_uobj+0x20/0x5e [ib_uverbs] [] ? idr_read_uobj+0x2f/0x4d [ib_uverbs] [] lock_acquire+0xbf/0xfe [] ? idr_read_uobj+0x2f/0x4d [ib_uverbs] [] ? lock_release+0x166/0x189 [] down_read+0x34/0x43 [] ? idr_read_uobj+0x2f/0x4d [ib_uverbs] [] idr_read_uobj+0x2f/0x4d [ib_uverbs] [] idr_read_obj+0x9/0x19 [ib_uverbs] [] ib_uverbs_create_qp+0x1e5/0x684 [ib_uverbs] [] ? lock_acquire+0xdb/0xfe [] ? lock_release_non_nested+0x94/0x213 [] ? might_fault+0x40/0x90 [] ? might_fault+0x40/0x90 [] ib_uverbs_write+0xb7/0xc2 [ib_uverbs] [] vfs_write+0xa7/0xee [] ? fget_light+0x3b/0x99 [] sys_write+0x45/0x69 [] system_call_fastpath+0x16/0x1b Reported-by: Or Gerlitz Signed-off-by: Roland Dreier --- drivers/infiniband/core/uverbs_cmd.c | 66 +++++++++++++++------------- 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 85231e2bdeef..ad750f3c6ca0 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -1423,13 +1423,6 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, } device = xrcd->device; } else { - pd = idr_read_pd(cmd.pd_handle, file->ucontext); - scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, 0); - if (!pd || !scq) { - ret = -EINVAL; - goto err_put; - } - if (cmd.qp_type == IB_QPT_XRC_INI) { cmd.max_recv_wr = cmd.max_recv_sge = 0; } else { @@ -1440,13 +1433,24 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, goto err_put; } } - rcq = (cmd.recv_cq_handle == cmd.send_cq_handle) ? - scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext, 1); - if (!rcq) { - ret = -EINVAL; - goto err_put; + + if (cmd.recv_cq_handle != cmd.send_cq_handle) { + rcq = idr_read_cq(cmd.recv_cq_handle, file->ucontext, 0); + if (!rcq) { + ret = -EINVAL; + goto err_put; + } } } + + scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, !!rcq); + rcq = rcq ?: scq; + pd = idr_read_pd(cmd.pd_handle, file->ucontext); + if (!pd || !scq) { + ret = -EINVAL; + goto err_put; + } + device = pd->device; } @@ -2484,27 +2488,27 @@ static int __uverbs_create_xsrq(struct ib_uverbs_file *file, init_uobj(&obj->uevent.uobject, cmd->user_handle, file->ucontext, &srq_lock_class); down_write(&obj->uevent.uobject.mutex); - pd = idr_read_pd(cmd->pd_handle, file->ucontext); - if (!pd) { - ret = -EINVAL; - goto err; - } - if (cmd->srq_type == IB_SRQT_XRC) { - attr.ext.xrc.cq = idr_read_cq(cmd->cq_handle, file->ucontext, 0); - if (!attr.ext.xrc.cq) { - ret = -EINVAL; - goto err_put_pd; - } - attr.ext.xrc.xrcd = idr_read_xrcd(cmd->xrcd_handle, file->ucontext, &xrcd_uobj); if (!attr.ext.xrc.xrcd) { ret = -EINVAL; - goto err_put_cq; + goto err; } obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object, uobject); atomic_inc(&obj->uxrcd->refcnt); + + attr.ext.xrc.cq = idr_read_cq(cmd->cq_handle, file->ucontext, 0); + if (!attr.ext.xrc.cq) { + ret = -EINVAL; + goto err_put_xrcd; + } + } + + pd = idr_read_pd(cmd->pd_handle, file->ucontext); + if (!pd) { + ret = -EINVAL; + goto err_put_cq; } attr.event_handler = ib_uverbs_srq_event_handler; @@ -2581,17 +2585,17 @@ static int __uverbs_create_xsrq(struct ib_uverbs_file *file, ib_destroy_srq(srq); err_put: - if (cmd->srq_type == IB_SRQT_XRC) { - atomic_dec(&obj->uxrcd->refcnt); - put_uobj_read(xrcd_uobj); - } + put_pd_read(pd); err_put_cq: if (cmd->srq_type == IB_SRQT_XRC) put_cq_read(attr.ext.xrc.cq); -err_put_pd: - put_pd_read(pd); +err_put_xrcd: + if (cmd->srq_type == IB_SRQT_XRC) { + atomic_dec(&obj->uxrcd->refcnt); + put_uobj_read(xrcd_uobj); + } err: put_uobj_write(&obj->uevent.uobject); -- GitLab