From patchwork Fri Jan 29 23:17:40 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bart Van Assche X-Patchwork-Id: 8168681 Return-Path: X-Original-To: patchwork-linux-rdma@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 7695A9F96D for ; Fri, 29 Jan 2016 23:18:39 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D19C320340 for ; Fri, 29 Jan 2016 23:18:37 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 29B4620328 for ; Fri, 29 Jan 2016 23:18:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755086AbcA2XSf (ORCPT ); Fri, 29 Jan 2016 18:18:35 -0500 Received: from mail-bn1bon0061.outbound.protection.outlook.com ([157.56.111.61]:5856 "EHLO na01-bn1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753397AbcA2XSe (ORCPT ); Fri, 29 Jan 2016 18:18:34 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sandiskcorp.onmicrosoft.com; s=selector1-sandisk-com; h=From:To:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=n30ffM6Ouz9FxxcNNgJ2RHhwgnSLkyKMXftCsyAdZRA=; b=ZJYKBUcAZZf4GqW2w7zaFcp2LsI32wDs55PFI6Jjv6pdqjhYCsDZ/KgcNjyJmSSL2lcm51KGeb6day8uo5nVyitxDnoCkEpPINUi3ScgL2hV6mkvdS9XT/6BVeOVHbXBsjsqAZKlTCTGrb1jIffAwDn0AvnTyMTgmNw+JLr2xQ4= Received: from CY1PR0201CA0013.namprd02.prod.outlook.com (10.163.30.151) by DM2PR0201MB0831.namprd02.prod.outlook.com (10.160.95.152) with Microsoft SMTP Server (TLS) id 15.1.390.13; Fri, 29 Jan 2016 23:18:31 +0000 Received: from BN1AFFO11FD005.protection.gbl (2a01:111:f400:7c10::140) by CY1PR0201CA0013.outlook.office365.com (2a01:111:e400:58b9::23) with Microsoft SMTP Server (TLS) id 15.1.396.15 via Frontend Transport; Fri, 29 Jan 2016 23:18:31 +0000 Authentication-Results: spf=pass (sender IP is 63.163.107.174) smtp.mailfrom=sandisk.com; vger.kernel.org; dkim=none (message not signed) header.d=none;vger.kernel.org; dmarc=bestguesspass action=none header.from=sandisk.com; Received-SPF: Pass (protection.outlook.com: domain of sandisk.com designates 63.163.107.174 as permitted sender) receiver=protection.outlook.com; client-ip=63.163.107.174; helo=milsmgep12.sandisk.com; Received: from milsmgep12.sandisk.com (63.163.107.174) by BN1AFFO11FD005.mail.protection.outlook.com (10.58.52.65) with Microsoft SMTP Server id 15.1.355.15 via Frontend Transport; Fri, 29 Jan 2016 23:18:30 +0000 Received: from MILHUBIP03.sdcorp.global.sandisk.com ( [172.22.12.162]) by (Symantec Messaging Gateway) with SMTP id B0.C8.25823.543FBA65; Fri, 29 Jan 2016 15:18:29 -0800 (PST) Received: from milsmgip12.sandisk.com (10.177.8.100) by MILHUBIP03.sdcorp.global.sandisk.com (10.177.9.96) with Microsoft SMTP Server id 14.3.248.2; Fri, 29 Jan 2016 15:17:40 -0800 X-AuditID: ac160a69-a17cc980000064df-12-56abf3458af5 Received: from [10.60.52.49] ( [10.177.8.100]) by (Symantec Messaging Gateway) with SMTP id 9D.9C.03910.413FBA65; Fri, 29 Jan 2016 15:17:40 -0800 (PST) Subject: [PATCH v2 18/22] IB/srpt: Detect session shutdown reliably To: Doug Ledford References: <56ABF16E.7070006@sandisk.com> CC: Christoph Hellwig , Sagi Grimberg , "Alex Estrin" , "linux-rdma@vger.kernel.org" From: Bart Van Assche Message-ID: <56ABF314.4040408@sandisk.com> Date: Fri, 29 Jan 2016 15:17:40 -0800 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.5.1 MIME-Version: 1.0 In-Reply-To: <56ABF16E.7070006@sandisk.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrOLMWRmVeSWpSXmKPExsWyRoxnka7r59VhBrNPcFpcePqdyeLl+Q+s FitXH2WyeHaol8XiRtsDNgdWj8V7XjJ57L7ZwObxbPphJo/3+66yeXzeJBfAGsVlk5Kak1mW WqRvl8CV8atvO2NBT23FhRnvmBoYr6V0MXJySAiYSPxcfYili5GLQ0hgE6PEzKdtUM4ORomv 6/axwVRdaz3ICpGYwyjx9uNGFpCEsICzRMPWz4wgtoiAmsSmV4vYQWwhAS2Jcxe+sIM0MAus YZSYOGMr2CQ2ASOJb+9ngjXzAhVNmXwVrIFFQFWitaEFbJCoQITE4c4udogaQYmTM5+A1XMK aEssmX0ByOYAGqopsX6XPkiYWUBeYvvbOcwQh25jldjXWg5xg7rEySXzmSYwCs9CMmkWQvcs JN0LGJlXMYrlZuYU56anFhga6RUn5qVkFmfrJefnbmIERwdX5g7GFZPMDzEKcDAq8fAuWLE6 TIg1say4MvcQowQHs5IIb90LoBBvSmJlVWpRfnxRaU5q8SFGaQ4WJXFe6xa1MCGB9MSS1OzU 1ILUIpgsEwenVAOjfejz3VIdGleKvQsPxmpqvZT7yXFU9NrpLJvcJwfC+NdYf/52aKeCdOUD s+SUh/uKuVm3mpb9frvGJptf+BDrBw0vpwl8W63em6u8rRbdlPryxQS7x/Kye/TfOqgr7nxh 1ldSWGr/l9+j7m1aPsOGyNC4MqGAGu//05Ouu37I581pZgr4ZKTEUpyRaKjFXFScCACMDlLg igIAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrPJMWRmVeSWpSXmKPExsXCtZEjRVfk8+owg6dT9C0uPP3OZPHy/AdW i5WrjzJZPDvUy2Jxo+0BmwOrx+I9L5k8dt9sYPN4Nv0wk8f7fVfZPD5vkgtgjeKySUnNySxL LdK3S+DK+NW3nbGgp7biwox3TA2M11K6GDk5JARMJK61HmTtYuTiEBKYxSjxq3EqG0hCWMBZ omHrZ0YQW0RATWLTq0XsILaQgJbEuQtf2EEamAVWMUr8XvkBrIFNwEji2/uZLCA2L1DRlMlX wRpYBFQlWhtawAaJCkRIHO7sYoeoEZQ4OfMJWD2ngLbEktkXwGxmAXWJP/MuMUPY8hLb385h nsDINwtJyywkZbOQlC1gZF7FKJabmVOcm55ZYGikV5yYl5JZnK2XnJ+7iREcpJxROxivTzQ/ xMjEwSnVwDiLTWHqDvvvuppGTprTim58E11unpenn55ye1I/+08pq0OvxeNO73riOGn3ipOz +5RdQj6sz9+SH5uzm9uq2EMg/lGSa1an/vSo902/epMyuV4lZcrkvb67+mUA819ri2OJf9iM l3+IefTMWdrkTtMsdvO52nvZVbatElP5sXTNvYN8fLUJzEosxRmJhlrMRcWJAJZVcxkCAgAA X-EOPAttributedMessage: 0 X-Microsoft-Exchange-Diagnostics: 1; BN1AFFO11FD005; 1:sxCNyHvZlwU6KO0JvV2+Pd093Etrj8BF83+2ma+wIF4PUozMp9Pr1618VxSJwTQ30CmMT68V3RRO5EDs5dVlZ+dzZucfH0aGcUwyVMt8kjv6J48oJsscnubaIwCpD61oiYoNx2hGivPDzYVICLfPbXi/Bd2q3M2B3uHte634qFSLjhBKeV7YPIT5MSLqTyTvcaknbNBRKCvOxPGVaqSxdekm9mQsioKnelPINZwD2vvsr3kdFtTSrlW98QLIVjG06pAx+SXzuu4E7iix9Oxzl1sKRfkwU3VGxEQoNUVlftZg7zxX89ncAFy9aR/gaZ5pAIlRc7J1CvoJ8LZ5pHTN9GI30J7KXeZgNoQrh1MeyXvJzLelCaJTrd0zbTGuzcMI9nZAPTsXcTuHuJpc0uR6g9fjxYLHcB8HCx+KUCZaHqi4xnVm5zUseoncOiGbndrA X-Forefront-Antispam-Report: CIP:63.163.107.174; CTRY:US; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(10009020)(6009001)(2980300002)(438002)(189002)(199003)(23676002)(11100500001)(64126003)(33656002)(36756003)(5008740100001)(586003)(4326007)(1096002)(92566002)(2906002)(1220700001)(106466001)(77096005)(80316001)(76176999)(19580405001)(110136002)(54356999)(19580395003)(4001350100001)(47776003)(87936001)(65816999)(87266999)(50466002)(65956001)(65806001)(575784001)(50986999)(2950100001)(230700001)(189998001)(229853001)(86362001)(83506001)(5001960100002); DIR:OUT; SFP:1101; SCL:1; SRVR:DM2PR0201MB0831; H:milsmgep12.sandisk.com; FPR:; SPF:Pass; MLV:sfv; MX:1; A:1; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; DM2PR0201MB0831; 2:JeJlPXTeTE/kQoRG3AmnsbX0rlPwT+wz2OCsn00hlcDAIIyL+L9yAo6pr1VWFghOq6HFQybKcAaBGY7eehU3NVlMnk4nhlPsSpOsledIoNyZGNKIfuojCAyMKszIGAEXkKSZ3NO7/4LW+Iyb70hI5w==; 3:oW0lAyLVHmSXGa6Yj8UG72pXmZPuzMqfI4YynaP7kMIqWYzeMtzUWjqoUfTSVl7kz1bvKpLzxIzHp0nVgBUdNouNf1Ld7ZTa7P7T4T2oUXSXXUQKuG0tzUR9PjV3kf39hPq6VS378oz7mgjwGCi1kUzoESoVt3ox8Utaflv89HvgxGIMi4MQhq/sTF4v5RylUL9LvRxNQUm+tRGf5CH1TBWu8gw4rj9Lsy5lBeJ3Al5fd1FNRlGnzuvi+7Rfr9iTR1EXemv+BD/B8d3ob3Flrg==; 25:YL2fICbDVcZk2yocIxS+125N91s5Y/jL3hcgdB13LfQNyGr/X8p4nXsyfFoAkSBSG2xKjT3LqvXsoBUPkC48B0bD1eFma7S16T7CmM9M451VV8Dd1T+H2JXEiWpIdrjXhn0GvZjNDoJ25sWQTqHrZUuyurATgYMPqjkdh06xDGFA4/eQpUfWLjIqGdXxV97/7/EKO47b19D01OahGRBMNF+BRI1qFvBGKhOjERD4NeLFH65PFdDI6G2KFbi42FvB X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(8251501001); SRVR:DM2PR0201MB0831; X-MS-Office365-Filtering-Correlation-Id: 91df8583-8e39-4b48-fad6-08d329028030 X-Microsoft-Exchange-Diagnostics: 1; DM2PR0201MB0831; 20:le/u6PTi8m2FZF3Xgs0pQNwf058hA3kHYThlQKRZVJSjoOdKqmcfxR9RT503eiI75pGBzMbJfFqog7iIoj2dhlr8PGl5fg9zpORO8LtRfXtRD9HoIakG42TJwOzQIh595atLbc0UNIkbcn1xiPv40gj/uL+AtIIgPLnRy2QBdOS1GUcYfZYJ61OW2z+h6aTSvqa/LLZ4+nyFDg1fIpVuskT7WAuRHyO6YjOcOpHPxgRCX+Fqmj/pfq1mrC9KSVlm4MDWg1mG3H9UExWgxZ97fHKlIaVZu3NJTOtW7BtX340fBTOOqW1b5yNKe3TUVOjjKPNmaLeBe4Q1mwbcQzJEKe34Q+oeBk3rCL95plpTIgrSluqW+jQzvt39a8D+RrUs4RfkKnZWF5lhma4Nm8b+4NXJAAK5xD+uVCBR5KPB1L5y3YKJQrJb3LuXneGJVpddqd5ZjTQH3tlB1SdbRYx2fW8BKNcEIiLQUdHkkMc992bzhlQ6s/ZJWoIywpS7GQMr X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(34787635062028)(42932892334569); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(2401047)(13024025)(13017025)(8121501046)(13018025)(5005006)(13015025)(13023025)(10201501046)(3002001); SRVR:DM2PR0201MB0831; BCL:0; PCL:0; RULEID:; SRVR:DM2PR0201MB0831; X-Microsoft-Exchange-Diagnostics: 1; DM2PR0201MB0831; 4:19r20s0RJL0mGkMRvnCGulsThgR5MASiNCWjmbCsW7e996F3kUqfGKtxAWcJ5rKVx4Wra0/FOomT8q1QqXkRjF/px01Z8Ol0j3QBw7Bt1f9KxuFpsHc75bPKTm1nEFVsmOyWYR7sVXQVjddnxUWiDI/Fv7YKH4lQtQduwjo+KRE4EOjEj7eQ9ChV7ssaYu5tPVjJiSzJ9AlSvxBlJNxmv4ar1S1svK+IF+bfsdR6Yo7i+yYuuZ82j+CM+E/DXYEWG1z0vwNv3cmSkb80OdJOCIba8hAvVAzCYqCDHFfS2jm3GEYuAiAOt/nE7bNH+BGHiyQFf0bYvO9Qr5/qnWXofF12SSe5x3V4KFeHc3ndT5a1OWqNXuzQ9ZmNNo/meXvif/BpMqasgKPSwBYvLRViAyR2fbl1vsZ2dudLVt4BFldmn8SWl5MtR9W2CqLA7dbZriTkDwrWyknF3RyXcK6YV3falOVvCpCKhy5AEv3oy19Xk83PGd9oPVei3ErUIAJdMT0/5GjzJUHMlhHCYhNatUXfRKt3sQ7L898CL9SEMjw= X-Forefront-PRVS: 083691450C X-Microsoft-Exchange-Diagnostics: =?utf-8?B?MTtETTJQUjAyMDFNQjA4MzE7MjM6Sm9VZmxoMG11VzdBL0dZS054WmxwWGlv?= =?utf-8?B?eHVrK0o5QmdyNUpTcGFFcE9JS1JFS3lmbUtMd2lqcnRBSjdQT2dqVmRoY0F0?= =?utf-8?B?VCtUei9aV1R3R2xHSkpuWStSVmZOQUVraVkyaURoZHRVVDRNWCtxeTJ5WmY0?= =?utf-8?B?RVhzeCt1QVowaXllcnlCVERkNU1EUm1zVkdSdkpTMys2Rk9WUXVsbkVKOWw5?= =?utf-8?B?QldEQUJPNWNPS21MRU1TZ1V5bm5IaVJRUVRlQlRDL3cwYmRZbHY0b1l5bXND?= =?utf-8?B?M2JaL1NrRGNacEJndlc3WmdNTUJHbmlyK0hUeDRZcFZCMmRROGZMY3pxR01S?= =?utf-8?B?c3VVQzlzYmoxYWF0R0lsL1lrNkxZY0dyL1pMcHMzSUtrTzFidkZONTVDNERu?= =?utf-8?B?R3VBSS8yRURZZllodEREOWNWcjYrL0c2S1BuQzFkZFhjYUp1ejQyQ09wQTdi?= =?utf-8?B?K1dYaGR5RzVQTEttQmFKUzhmbGc0OEpGaVVvdXR6NUhvWENiVktkdUptWDJr?= =?utf-8?B?VlNTcXFnWnErWXU3aDdkUUNDdTRPUDNUR2JVMUpVZkVZMktxVnZvT0RHNVRp?= =?utf-8?B?NHVJK2FJVkQzVXFaSDN2M0dGUUFSbHpuZzlHSHkwTm8xa0dBNGcvVkE1RWgw?= =?utf-8?B?emxnZ3pjUkJBVXE5eGRSbnl4V0NtRXcxV3lLOXdGdE1pR3l6Wk1jc0ZxSXIw?= =?utf-8?B?N1dzclpDNEFOMzB2NzlCeWFiM0lSdmNET2d0WFRhZU5zakFtYkx2Sy9laXg2?= =?utf-8?B?azBnbUJ2MHAwMmlVQ1AxWUtENUxoeDJOcWFLNjJkTC9EUWJESHlRZmdNMmdR?= =?utf-8?B?R3dqNU9ya3lCQ2czOWx1OFhsTXRlWWhKaHBiMFFlK3lyQlBNWDVLTFloa3RN?= =?utf-8?B?dWZBYWs0SzR1ZCtURjhkeDB5THJDZ2hTUUkyaVIwL0F3cXh0bXRJbFNMaG03?= =?utf-8?B?b1AreWZ2eHd2bFJ0MkQ5REoybUZxdklzQi8zVUUrNHZvQXZnOWNsOUczWFZi?= =?utf-8?B?MGdodnR3cmZnOXRVQVQvcHYrazh4ZG1VNXVTNXlkV0ExTVZtd3BSWlBnNGN5?= =?utf-8?B?Zy8yTmdIL2pSME5wSGhiNmw5RnQ5ZHpEOVg1Z3dnNEV3cG5OY2dKL2h2Y08r?= =?utf-8?B?aS9iNkwwRUQreWUrcitrNWM2THcrRXNCczNpUVNsaWx4cURVdy9nd3lqZmZu?= =?utf-8?B?NzdWSVBtTXVYQ3FJdXZybmlaUG8rMUJwQ01WU2xvWG9RWXRuTTlIWjNzN3Bp?= =?utf-8?B?NnNWK2g0NDNiOTc1dlZ2aVgvcnFaL3N2UnlWOXZrZ29oR1BaL0dZZ3o0Y01B?= =?utf-8?B?REhlc2E0QnZnUE5naENYVy9qZ3JnUzNGMkRpZE0wMFlYK2hDYnBjUjVvbDhq?= =?utf-8?B?YlZESVVmLy9kY1ZUYXlEUDBoUyt4K29qYlNxNS9pOU9aN1RIWTBzaUZPdWwy?= =?utf-8?B?Q0kyWVFsTGFsMGdSbDhTRE5ocStGZWViNEcvK3ZWd2EzdzIxSlB5RkRRVUJW?= =?utf-8?B?aERzY0tBPT0=?= X-Microsoft-Exchange-Diagnostics: 1; DM2PR0201MB0831; 5:FE7htLwZtkVxLLk2BxMkjOB1iCVykiQNt7SbdIEyMUgMMAAysLfmYQr3WEeA69Ewiagp3mbn6prbzUXGqnA2+lnLAlL04r0eV4R2WHDkHASxSy8KWbk6QPtbul7s38TP9lzL16QvgBqhH8D9z0ouOQ==; 24:xod//hV+f56dCFlD7/H5a1Itr2D4myGxTHERctMFwP+VleCH/NbQpzzCr9YDTf/K3AQlyQPAGBQc1oGL3OfC5kqTelLdHSWxNu4f0wDg9Cw=; 20:RahaGBnZg5m9nAFxjHqxINYXhc4j2IZcR8H1VHGIb+dT+gDHtS3zJFHgwlzBExGvSQ6THGDTEGDVBDLq5BUEfmW+dCuDYnEXXf6HodSf+1Wp6+V464IRd70IYvs48ESRQSvmCV2nYp/dT/ppHm9BNp6mWE9sEKGE3r3AjO+PJH+qUJYuDfi69WXstDEA7j7iFOSK6saO401A8c2/XFtzUC1VNeY+XSadMGZdwL6m4nkm6YK96/g+zU8+rjuLZAqy SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: sandisk.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 29 Jan 2016 23:18:30.1434 (UTC) X-MS-Exchange-CrossTenant-Id: fcd9ea9c-ae8c-460c-ab3c-3db42d7ac64d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=fcd9ea9c-ae8c-460c-ab3c-3db42d7ac64d; Ip=[63.163.107.174]; Helo=[milsmgep12.sandisk.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM2PR0201MB0831 Sender: linux-rdma-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rdma@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The Last WQE Reached event is only generated after one or more work requests have been queued on the QP associated with a session. Since session shutdown can start before any work requests have been queued, use a zero-length RDMA write to wait until a QP has been drained. Additionally, rework the code for closing and disconnecting a session. Signed-off-by: Bart Van Assche Reviewed-by: Christoph Hellwig Cc: Sagi Grimberg --- drivers/infiniband/ulp/srpt/ib_srpt.c | 282 +++++++++++++++++----------------- drivers/infiniband/ulp/srpt/ib_srpt.h | 18 ++- 2 files changed, 150 insertions(+), 150 deletions(-) diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index 26aeb0b..e9c3067 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -92,10 +92,11 @@ MODULE_PARM_DESC(srpt_service_guid, static struct ib_client srpt_client; static void srpt_release_cmd(struct se_cmd *se_cmd); -static void srpt_release_channel(struct srpt_rdma_ch *ch); +static void srpt_free_ch(struct kref *kref); static int srpt_queue_status(struct se_cmd *cmd); static void srpt_recv_done(struct ib_cq *cq, struct ib_wc *wc); static void srpt_send_done(struct ib_cq *cq, struct ib_wc *wc); +static void srpt_zerolength_write_done(struct ib_cq *cq, struct ib_wc *wc); /* * The only allowed channel state changes are those that change the channel @@ -175,6 +176,23 @@ static void srpt_srq_event(struct ib_event *event, void *ctx) pr_info("SRQ event %d\n", event->event); } +static const char *get_ch_state_name(enum rdma_ch_state s) +{ + switch (s) { + case CH_CONNECTING: + return "connecting"; + case CH_LIVE: + return "live"; + case CH_DISCONNECTING: + return "disconnecting"; + case CH_DRAINING: + return "draining"; + case CH_DISCONNECTED: + return "disconnected"; + } + return "???"; +} + /** * srpt_qp_event() - QP event callback function. */ @@ -188,11 +206,9 @@ static void srpt_qp_event(struct ib_event *event, struct srpt_rdma_ch *ch) ib_cm_notify(ch->cm_id, event->event); break; case IB_EVENT_QP_LAST_WQE_REACHED: - if (srpt_set_ch_state(ch, CH_RELEASING)) - srpt_release_channel(ch); - else - pr_debug("%s: state %d - ignored LAST_WQE.\n", - ch->sess_name, ch->state); + pr_debug("%s-%d, state %s: received Last WQE event.\n", + ch->sess_name, ch->qp->qp_num, + get_ch_state_name(ch->state)); break; default: pr_err("received unrecognized IB QP event %d\n", event->event); @@ -795,6 +811,37 @@ out: } /** + * srpt_zerolength_write() - Perform a zero-length RDMA write. + * + * A quote from the InfiniBand specification: C9-88: For an HCA responder + * using Reliable Connection service, for each zero-length RDMA READ or WRITE + * request, the R_Key shall not be validated, even if the request includes + * Immediate data. + */ +static int srpt_zerolength_write(struct srpt_rdma_ch *ch) +{ + struct ib_send_wr wr, *bad_wr; + + memset(&wr, 0, sizeof(wr)); + wr.opcode = IB_WR_RDMA_WRITE; + wr.wr_cqe = &ch->zw_cqe; + wr.send_flags = IB_SEND_SIGNALED; + return ib_post_send(ch->qp, &wr, &bad_wr); +} + +static void srpt_zerolength_write_done(struct ib_cq *cq, struct ib_wc *wc) +{ + struct srpt_rdma_ch *ch = cq->cq_context; + + WARN(wc->status == IB_WC_SUCCESS, "%s-%d: QP not in error state\n", + ch->sess_name, ch->qp->qp_num); + if (srpt_set_ch_state(ch, CH_DISCONNECTED)) + schedule_work(&ch->release_work); + else + WARN_ONCE("%s-%d\n", ch->sess_name, ch->qp->qp_num); +} + +/** * srpt_get_desc_tbl() - Parse the data descriptors of an SRP_CMD request. * @ioctx: Pointer to the I/O context associated with the request. * @srp_cmd: Pointer to the SRP_CMD request data. @@ -1816,110 +1863,102 @@ static void srpt_destroy_ch_ib(struct srpt_rdma_ch *ch) } /** - * __srpt_close_ch() - Close an RDMA channel by setting the QP error state. + * srpt_close_ch() - Close an RDMA channel. * - * Reset the QP and make sure all resources associated with the channel will - * be deallocated at an appropriate time. + * Make sure all resources associated with the channel will be deallocated at + * an appropriate time. * - * Note: The caller must hold ch->sport->sdev->spinlock. + * Returns true if and only if the channel state has been modified into + * CH_DRAINING. */ -static void __srpt_close_ch(struct srpt_rdma_ch *ch) +static bool srpt_close_ch(struct srpt_rdma_ch *ch) { - enum rdma_ch_state prev_state; - unsigned long flags; + int ret; - spin_lock_irqsave(&ch->spinlock, flags); - prev_state = ch->state; - switch (prev_state) { - case CH_CONNECTING: - case CH_LIVE: - ch->state = CH_DISCONNECTING; - break; - default: - break; + if (!srpt_set_ch_state(ch, CH_DRAINING)) { + pr_debug("%s-%d: already closed\n", ch->sess_name, + ch->qp->qp_num); + return false; } - spin_unlock_irqrestore(&ch->spinlock, flags); - switch (prev_state) { - case CH_CONNECTING: - ib_send_cm_rej(ch->cm_id, IB_CM_REJ_NO_RESOURCES, NULL, 0, - NULL, 0); - /* fall through */ - case CH_LIVE: - if (ib_send_cm_dreq(ch->cm_id, NULL, 0) < 0) - pr_err("sending CM DREQ failed.\n"); - break; - case CH_DISCONNECTING: - break; - case CH_DRAINING: - case CH_RELEASING: - break; - } -} + kref_get(&ch->kref); -/** - * srpt_close_ch() - Close an RDMA channel. - */ -static void srpt_close_ch(struct srpt_rdma_ch *ch) -{ - struct srpt_device *sdev = ch->sport->sdev; + ret = srpt_ch_qp_err(ch); + if (ret < 0) + pr_err("%s-%d: changing queue pair into error state failed: %d\n", + ch->sess_name, ch->qp->qp_num, ret); - mutex_lock(&sdev->mutex); - __srpt_close_ch(ch); - mutex_unlock(&sdev->mutex); -} + pr_debug("%s-%d: queued zerolength write\n", ch->sess_name, + ch->qp->qp_num); + ret = srpt_zerolength_write(ch); + if (ret < 0) { + pr_err("%s-%d: queuing zero-length write failed: %d\n", + ch->sess_name, ch->qp->qp_num, ret); + if (srpt_set_ch_state(ch, CH_DISCONNECTED)) + schedule_work(&ch->release_work); + else + WARN_ON_ONCE(true); + } -/** - * srpt_shutdown_session() - Whether or not a session may be shut down. - */ -static int srpt_shutdown_session(struct se_session *se_sess) -{ - return 1; + kref_put(&ch->kref, srpt_free_ch); + + return true; } -/** - * srpt_drain_channel() - Drain a channel by resetting the IB queue pair. - * @cm_id: Pointer to the CM ID of the channel to be drained. - * - * Note: Must be called from inside srpt_cm_handler to avoid a race between - * accessing sdev->spinlock and the call to kfree(sdev) in srpt_remove_one() - * (the caller of srpt_cm_handler holds the cm_id spinlock; srpt_remove_one() - * waits until all target sessions for the associated IB device have been - * unregistered and target session registration involves a call to - * ib_destroy_cm_id(), which locks the cm_id spinlock and hence waits until - * this function has finished). +/* + * Change the channel state into CH_DISCONNECTING. If a channel has not yet + * reached the connected state, close it. If a channel is in the connected + * state, send a DREQ. If a DREQ has been received, send a DREP. Note: it is + * the responsibility of the caller to ensure that this function is not + * invoked concurrently with the code that accepts a connection. This means + * that this function must either be invoked from inside a CM callback + * function or that it must be invoked with the srpt_port.mutex held. */ -static void srpt_drain_channel(struct srpt_rdma_ch *ch) +static int srpt_disconnect_ch(struct srpt_rdma_ch *ch) { int ret; - bool do_reset = false; - WARN_ON_ONCE(irqs_disabled()); + if (!srpt_set_ch_state(ch, CH_DISCONNECTING)) + return -ENOTCONN; + + ret = ib_send_cm_dreq(ch->cm_id, NULL, 0); + if (ret < 0) + ret = ib_send_cm_drep(ch->cm_id, NULL, 0); + + if (ret < 0 && srpt_close_ch(ch)) + ret = 0; + + return ret; +} - do_reset = srpt_set_ch_state(ch, CH_DRAINING); +static void __srpt_close_all_ch(struct srpt_device *sdev) +{ + struct srpt_rdma_ch *ch; - if (do_reset) { - if (ch->sess) - srpt_shutdown_session(ch->sess); + lockdep_assert_held(&sdev->mutex); - ret = srpt_ch_qp_err(ch); - if (ret < 0) - pr_err("Setting queue pair in error state" - " failed: %d\n", ret); + list_for_each_entry(ch, &sdev->rch_list, list) { + if (srpt_disconnect_ch(ch) >= 0) + pr_info("Closing channel %s-%d because target %s has been disabled\n", + ch->sess_name, ch->qp->qp_num, + sdev->device->name); + srpt_close_ch(ch); } } /** - * srpt_release_channel() - Release channel resources. - * - * Schedules the actual release because: - * - Calling the ib_destroy_cm_id() call from inside an IB CM callback would - * trigger a deadlock. - * - It is not safe to call TCM transport_* functions from interrupt context. + * srpt_shutdown_session() - Whether or not a session may be shut down. */ -static void srpt_release_channel(struct srpt_rdma_ch *ch) +static int srpt_shutdown_session(struct se_session *se_sess) +{ + return 1; +} + +static void srpt_free_ch(struct kref *kref) { - schedule_work(&ch->release_work); + struct srpt_rdma_ch *ch = container_of(kref, struct srpt_rdma_ch, kref); + + kfree_rcu(ch, rcu); } static void srpt_release_channel_work(struct work_struct *w) @@ -1961,7 +2000,7 @@ static void srpt_release_channel_work(struct work_struct *w) wake_up(&sdev->ch_releaseQ); - kfree_rcu(ch, rcu); + kref_put(&ch->kref, srpt_free_ch); } /** @@ -2045,17 +2084,10 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, && param->port == ch->sport->port && param->listen_id == ch->sport->sdev->cm_id && ch->cm_id) { - if (ch->state != CH_CONNECTING - && ch->state != CH_LIVE) + if (srpt_disconnect_ch(ch) < 0) continue; - - /* found an existing channel */ - pr_debug("Found existing channel %s" - " cm_id= %p state= %d\n", - ch->sess_name, ch->cm_id, ch->state); - - __srpt_close_ch(ch); - + pr_info("Relogin - closed existing channel %s\n", + ch->sess_name); rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_TERMINATED; } @@ -2086,6 +2118,8 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, goto reject; } + kref_init(&ch->kref); + ch->zw_cqe.done = srpt_zerolength_write_done; INIT_WORK(&ch->release_work, srpt_release_channel_work); memcpy(ch->i_port_id, req->initiator_port_id, 16); memcpy(ch->t_port_id, req->target_port_id, 16); @@ -2209,7 +2243,7 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id, goto out; release_channel: - srpt_set_ch_state(ch, CH_RELEASING); + srpt_disconnect_ch(ch); transport_deregister_session_configfs(ch->sess); transport_deregister_session(ch->sess); ch->sess = NULL; @@ -2257,7 +2291,6 @@ static void srpt_cm_rej_recv(struct srpt_rdma_ch *ch, pr_info("Received CM REJ for ch %s-%d; reason %d; private data %s.\n", ch->sess_name, ch->qp->qp_num, reason, priv ? : "(?)"); kfree(priv); - srpt_drain_channel(ch); } /** @@ -2286,40 +2319,6 @@ static void srpt_cm_rtu_recv(struct srpt_rdma_ch *ch) } /** - * srpt_cm_dreq_recv() - Process reception of a DREQ message. - */ -static void srpt_cm_dreq_recv(struct srpt_rdma_ch *ch) -{ - unsigned long flags; - bool send_drep = false; - - pr_debug("ch %s-%d state %d\n", ch->sess_name, ch->qp->qp_num, - ch->state); - - spin_lock_irqsave(&ch->spinlock, flags); - switch (ch->state) { - case CH_CONNECTING: - case CH_LIVE: - send_drep = true; - ch->state = CH_DISCONNECTING; - break; - case CH_DISCONNECTING: - case CH_DRAINING: - case CH_RELEASING: - WARN(true, "unexpected channel state %d\n", ch->state); - break; - } - spin_unlock_irqrestore(&ch->spinlock, flags); - - if (send_drep) { - if (ib_send_cm_drep(ch->cm_id, NULL, 0) < 0) - pr_err("Sending IB DREP failed.\n"); - pr_info("Received DREQ and sent DREP for session %s.\n", - ch->sess_name); - } -} - -/** * srpt_cm_handler() - IB connection manager callback function. * * A non-zero return value will cause the caller destroy the CM ID. @@ -2350,22 +2349,21 @@ static int srpt_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event) srpt_cm_rtu_recv(ch); break; case IB_CM_DREQ_RECEIVED: - srpt_cm_dreq_recv(ch); + srpt_disconnect_ch(ch); break; case IB_CM_DREP_RECEIVED: pr_info("Received InfiniBand DREP message for ch %s-%d.\n", ch->sess_name, ch->qp->qp_num); - srpt_drain_channel(ch); + srpt_close_ch(ch); break; case IB_CM_TIMEWAIT_EXIT: pr_info("Received CM TimeWait exit for ch %s-%d.\n", ch->sess_name, ch->qp->qp_num); - srpt_drain_channel(ch); + srpt_close_ch(ch); break; case IB_CM_REP_ERROR: pr_info("Received CM REP error for ch %s-%d.\n", ch->sess_name, ch->qp->qp_num); - srpt_drain_channel(ch); break; case IB_CM_DREQ_ERROR: pr_info("Received IB DREQ ERROR event.\n"); @@ -2505,7 +2503,7 @@ static int srpt_write_pending(struct se_cmd *se_cmd) break; case CH_DISCONNECTING: case CH_DRAINING: - case CH_RELEASING: + case CH_DISCONNECTED: pr_debug("cmd with tag %lld: channel disconnecting\n", ioctx->cmd.tag); srpt_set_cmd_state(ioctx, SRPT_STATE_DATA_IN); @@ -2662,16 +2660,16 @@ static int srpt_ch_list_empty(struct srpt_device *sdev) */ static int srpt_release_sdev(struct srpt_device *sdev) { - struct srpt_rdma_ch *ch, *tmp_ch; - int res; + int i, res; WARN_ON_ONCE(irqs_disabled()); BUG_ON(!sdev); mutex_lock(&sdev->mutex); - list_for_each_entry_safe(ch, tmp_ch, &sdev->rch_list, list) - __srpt_close_ch(ch); + for (i = 0; i < ARRAY_SIZE(sdev->port); i++) + sdev->port[i].enabled = false; + __srpt_close_all_ch(sdev); mutex_unlock(&sdev->mutex); res = wait_event_interruptible(sdev->ch_releaseQ, @@ -2968,7 +2966,7 @@ static void srpt_close_session(struct se_session *se_sess) BUG_ON(ch->release_done); ch->release_done = &release_done; wait = !list_empty(&ch->list); - __srpt_close_ch(ch); + srpt_disconnect_ch(ch); mutex_unlock(&sdev->mutex); if (!wait) diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.h b/drivers/infiniband/ulp/srpt/ib_srpt.h index d1f2877..a3cc0a9 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.h +++ b/drivers/infiniband/ulp/srpt/ib_srpt.h @@ -218,20 +218,20 @@ struct srpt_send_ioctx { /** * enum rdma_ch_state - SRP channel state. - * @CH_CONNECTING: QP is in RTR state; waiting for RTU. - * @CH_LIVE: QP is in RTS state. - * @CH_DISCONNECTING: DREQ has been received; waiting for DREP - * or DREQ has been send and waiting for DREP - * or . - * @CH_DRAINING: QP is in ERR state; waiting for last WQE event. - * @CH_RELEASING: Last WQE event has been received; releasing resources. + * @CH_CONNECTING: QP is in RTR state; waiting for RTU. + * @CH_LIVE: QP is in RTS state. + * @CH_DISCONNECTING: DREQ has been sent and waiting for DREP or DREQ has + * been received. + * @CH_DRAINING: DREP has been received or waiting for DREP timed out + * and last work request has been queued. + * @CH_DISCONNECTED: Last completion has been received. */ enum rdma_ch_state { CH_CONNECTING, CH_LIVE, CH_DISCONNECTING, CH_DRAINING, - CH_RELEASING + CH_DISCONNECTED, }; /** @@ -267,6 +267,8 @@ struct srpt_rdma_ch { struct ib_cm_id *cm_id; struct ib_qp *qp; struct ib_cq *cq; + struct ib_cqe zw_cqe; + struct kref kref; struct rcu_head rcu; int rq_size; u32 rsp_size;