From patchwork Wed Feb 8 15:05:05 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 9562745 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id BA393601E5 for ; Wed, 8 Feb 2017 16:16:55 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 901CC284B4 for ; Wed, 8 Feb 2017 16:16:55 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 84DD8284C2; Wed, 8 Feb 2017 16:16:55 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A639A284B4 for ; Wed, 8 Feb 2017 16:16:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752061AbdBHQPl (ORCPT ); Wed, 8 Feb 2017 11:15:41 -0500 Received: from mx0a-00082601.pphosted.com ([67.231.145.42]:57400 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752087AbdBHQPW (ORCPT ); Wed, 8 Feb 2017 11:15:22 -0500 Received: from pps.filterd (m0044010.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.20/8.16.0.20) with SMTP id v18F4SNC010816; Wed, 8 Feb 2017 07:05:26 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fb.com; h=from : to : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=facebook; bh=jJqzXuavIf/lTTlyhWwL+u4VRHLGochL98UYZldjo3g=; b=ammYLq35aVOmAYdp0qVn0k7X9EHTTUax6aVu4EzLLVBV5iuqEOzIp/Mn89Bw75Zia1Ck sNJAUw3D6WnfCqtOBcEKsDycMxGlB3ovvCkcyf0o7yvZjkUrqHRTUIxEtjJKQnI9BMvh hCJ9DltDRb0iIUk4uUSEW39v3TlpEXEc8Wg= Received: from maileast.thefacebook.com ([199.201.65.23]) by mx0a-00082601.pphosted.com with ESMTP id 28g2y8gfg6-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Wed, 08 Feb 2017 07:05:26 -0800 Received: from NAM02-SN1-obe.outbound.protection.outlook.com (192.168.183.28) by o365-in.thefacebook.com (192.168.177.22) with Microsoft SMTP Server (TLS) id 14.3.294.0; Wed, 8 Feb 2017 10:05:25 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fb.onmicrosoft.com; s=selector1-fb-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=jJqzXuavIf/lTTlyhWwL+u4VRHLGochL98UYZldjo3g=; b=Qa3/D/9IAJCiKKbGOojMNM9E3wtQ9TxZl4MbI5rxJWwVS5Db47jmsVdXy2oJ8/RbPn3jaaKI+oirWCTmze7MMsnJF2IjhGcEI2GQEFk7R0w/XsA1GWpwfwjWvccyfaIbeXsFD+ZUrtvxBlAD7YTikrpvNhRFfCmFgZZWsewO/uU= Received: from localhost (2606:a000:4381:1201:225:22ff:feb3:e51a) by DM5PR15MB1916.namprd15.prod.outlook.com (10.174.247.144) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.888.16; Wed, 8 Feb 2017 15:05:09 +0000 From: Josef Bacik To: , , , Subject: [PATCH V2] nbd: ref count the socks array Date: Wed, 8 Feb 2017 10:05:05 -0500 Message-ID: <1486566305-10039-1-git-send-email-jbacik@fb.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1486505453-2976-1-git-send-email-jbacik@fb.com> References: <1486505453-2976-1-git-send-email-jbacik@fb.com> MIME-Version: 1.0 X-Originating-IP: [2606:a000:4381:1201:225:22ff:feb3:e51a] X-ClientProxiedBy: DM5PR13CA0009.namprd13.prod.outlook.com (10.168.112.19) To DM5PR15MB1916.namprd15.prod.outlook.com (10.174.247.144) X-MS-Office365-Filtering-Correlation-Id: 6f3793c7-8961-4426-edb5-08d45033dfab X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001); SRVR:DM5PR15MB1916; X-Microsoft-Exchange-Diagnostics: 1; DM5PR15MB1916; 3:RSkASiWVP6VK4+P5QpjFdoF7rTy2U8Q7ccRfuKfNjeJP0Sm44/C+9pQHZpV+WpJBXRiNKd6cU7DgUExrnsGRwX39TGFv0LxSzWJ0vyn2Lf+FM41X6m4oxhYLjkL7oYtF41XBBvP6ypahDnXbHPH3Fbu5L0UxmUoT5TRpjW8ut5MPtZ2XhU+SlALkkuyLlxd5oLksFIQHXYC8Mch+V+BP1huYeECUO4r2yaIdj023mFIWP4bs79KLlVOMlYPXADDk+oHTSgnBmZt/2PC6lHEh+A==; 25:jRH2X3HWDb6IobEbsXn0EcaLt+BAX+zKykb/bNhOWIAWVFDbM1acyZLx2q6b05tlX3oyoH0K+Pmq+rCCALheD4Z1+Rpq+aKcB1/r6Gpb4oGC4PzglFJbVX+d4uQNsUe+hAclcDCuB7kAca5j2yoFR2ZnZE0gKqBz/pudr97Et58DrBpH1Qi2UvtG9dnPUw1cCPBfvOnDa/weYVVcaGu+gh9sUo7NuJcpf+NjNnTsEniUee+2IE2pvOrj6NAndhzctgtaG0lVHBsVXo853AY5W75zxjtmJOBb++/MzX/Juj54Zdh/UdB6biCHJ1RfUlvkvj+9u9hblnDCxYeusIA3RURSmTvOsbx0dLCe7p4xWjOpsJKetJBTcEAoa8KWSXMNlIafd6edP3rQLNgkaOXomoijOU53GQV2riPIwwusBSAsCldVGRtxiGyw7LFSMQWcBLML87RXUOEzxCkDVmaaqw== X-Microsoft-Exchange-Diagnostics: 1; DM5PR15MB1916; 31:FtpcI1jNKloTwj363D0+7lnFIvnCnwFQlfb9dFr9ddUTos3cIM+ZDBex3Ouq3USgV4Jwdhbml5ATUcB2MxGge4Ast9nEriaTGHFWbkYh97GckyNZZW+H+eW08YtR4jIKz6JnYLKpHkC+7tlXzQH08ESxj8mqGqBMpzUPLxdeRb+yBSGdiKvejSLfDyE+tr2gtSubNaTe1E4OCO3R58Y+UjWK9LUbTRnx7803cROp8Tp05/Gt0o5kqg777tCnIE8Z4sGrG2FcZJNjKo1d7wWGgQ==; 20:dLUHrJjgRTbDwkan0H9yVxIen8HLHMg8ubPJwvtEaiHeTBkmmCZGehl3cJesDYTPAFLpaKtJtkkD5BRCzJDvoF7KO9nMLhLN39W08QQX5MrEfcmdt9kfjuODVDsiM9JtP+1TTmN0knoQ4XpFU6lf+tCuX2wK0L2G/QHM653pVjV3HcggUAzf/ZtK2WTf9IIQ1bBnTtKV4dpc/ZNLoZXjkqSK3HDExBNxd8gHwX4dqsrp9hq9S0K+4Ugfx7lkSHaY1Yf5PGkGHmXrA78qXCVcAvg563cUPlNs2d9imwRJCi9r294pCO1katjfHBzBmDEByLX7x/MHirkHC4lUdwAeerO0iYq9UjGcHoXai40BlhfxLEI/2liHSqfV4CX4aJZCapug2GMLSP1sKrJLfzDSo0t6oyB8Nl7AV/Q8bq6MBdLKa8642mpbzH+S1WO74uf4L0h1Biw/x3TRuqPmNgO2TuDVQx/O5McGCCW7lJoML3BgIS9OUujjmim/eOl9Rh9r X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(67672495146484); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040375)(601004)(2401047)(8121501046)(5005006)(2017020702029)(20170203043)(10201501046)(3002001)(6041248)(20161123562025)(20161123564025)(20161123558025)(20161123560025)(20161123555025)(6072148); SRVR:DM5PR15MB1916; BCL:0; PCL:0; RULEID:; SRVR:DM5PR15MB1916; X-Microsoft-Exchange-Diagnostics: 1; DM5PR15MB1916; 4:WIj+PWTyO9Q9MbWFDrFSIImsEXe2KxKWKgwNcikFn+ex0UQvbYOOxrQkacOIyAU4K4+KkJw1QqHVtIeXobWJaOWL5EJcHfo48NcQL57+bpxztVMw2PCcTiGmmytq+tY1blOg+ZQV+4BkJKW8/hdQRbFnUD4MB2tkZkZrgu2C0JITmsmLlglQEfpWT6kuOz8CzD2aOjOwILziZ1nteYzdxI9LR7HGwxspHZZWoeD7E2cYLMsq9gfbOnopgF134rVVAzyIvrNRyDZhEI1URQ3guDn7qXfC2+3IEY4jzo0b4wVEYQizl3AFqgbw2Rg5jGtTl4/mp1F/71D7mInWXpDdQeDmGiJ+WCzRe4LdKvDRiGFFgW7Wko6nWCxxDzDWeO8ilPLqn/r4S4PyQvxxO8cSGKSrqxwntSyJOveCW5wgaFbhah0ENyj36S+lu0MWUZn1HzAKZDkQzRKDPFMzQyyWm/vY0wrEyy58pq7d1kX/by6sr5CzkKkjfaSXov7iLfSXBJXfsffKiA9izyKepup0J7AlFeGh5T0hct4YEEZdr8+MBWUgKtwJaTTUgYQG+fXMQt8XA98a84ssT0hCArGRWHof9Ou5qKUii31JYfs0hWQvhWzPeIaBI37ryU2k5KmyEHkItomV0cb9xJzVAkiAuv/JOjO0W6mYCiRgBskMeWLOa+cbK2V4Hk17dlJlmZ2Ulg/1xllU72k0d/vreJ7viw== X-Forefront-PRVS: 0212BDE3BE X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10019020)(4630300001)(6009001)(6069001)(7916002)(39450400003)(189002)(199003)(45904002)(2906002)(42186005)(92566002)(33646002)(106356001)(6486002)(50226002)(38730400002)(47776003)(97736004)(76506005)(105586002)(6496005)(50466002)(101416001)(36756003)(48376002)(50986999)(76176999)(53936002)(5660300001)(25786008)(2201001)(2950100002)(68736007)(6116002)(6666003)(305945005)(86362001)(81166006)(5003940100001)(8676002)(81156014)(189998001)(7736002); DIR:OUT; SFP:1102; SCL:1; SRVR:DM5PR15MB1916; H:localhost; FPR:; SPF:None; PTR:InfoNoRecords; MX:1; A:1; LANG:en; Received-SPF: None (protection.outlook.com: fb.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; DM5PR15MB1916; 23:jg8A4qzYajcOCNxh22oGD5LQDoT+kX+FEWu3MmCSF?= =?us-ascii?Q?MB7Wr+JWNlKRJHFDymbH7WWF7izSVNxfXFL9rMz4ffH4gl9OuWU7Wd4zmlsN?= =?us-ascii?Q?uvaK4q5vGB41QaIQpHlBvNgjJIGqheSTJvhxj4CPp2KMLgX9Y+OdniK3Fkdp?= =?us-ascii?Q?hGHszAwOwrsIShTuFi1azros1Du0VeD8B7EvxXKeTZGJjtdh1ej2WozBUA7G?= =?us-ascii?Q?fkqkNYoKvfy/en2Fig1yJHDwA+nL+eGU3JthTpuURWIK2FGP4FCDJcUVVab1?= =?us-ascii?Q?PlU1MmuClcRPjzvMkxpaccjSm2bgrGI6X4wC2cLM/rDd8VUqmc7LpEtptxlP?= =?us-ascii?Q?597lIuV8TUP5eMNk/jKjQWDV2VchlkutjeBkAIpn+ChaXAtjPToSrzjfkCF1?= =?us-ascii?Q?OB45o/wom2nxT3mGmbvG92s8rr1tPhVg7gbfWk54Bhmv97QYFaVi4Sug+cKL?= =?us-ascii?Q?aGcDbf2+XIE/qzkMA80uBo1RZUhfpve49QDeHsM/MI1td1lSckg6aF4Oizql?= =?us-ascii?Q?SCNjBJWb5IrdG7yaqv/QBS1JASAQTLE0Gkgq72LAigZI/AU8tLUMXwFF/vYP?= =?us-ascii?Q?1+D0YLLHrfbpCMlNV7mb2dK6c5b+cS5NGI+6UeRiQJLfuWbPIXlyYXFo/C7H?= =?us-ascii?Q?Y1PHQBFeGLWzEJvBapNEZePCvpuxM0H5l0EMJxEz8pgX+jZn8RdMSEPAeVwD?= =?us-ascii?Q?ZXRyyU1JqJio+6MeWE17kJen4qzyQP2fFnurKBnZzraVFBEOfBnwGDXOW2h7?= =?us-ascii?Q?IDoNcfEHFuCNFDpBVhUnxymVz6qKZjBsEgWed0Usr/DKHQBIgcSKd2dPwiRm?= =?us-ascii?Q?ujs1m0C3HAhy2DOVHFSkhQ9x9tDbWZfl51lOFU0JoMediOZWMtRbj4f2efoA?= =?us-ascii?Q?4A8J/C5l0DGVx68x0OQOyKS3/2Z0Z08gybu+XKqD4zwCEpt56XZxjx1hOCbh?= =?us-ascii?Q?80h7kOR4Z6h4FZ0bdCY8w/H+THTxBBcsY7jNjIM8P+QcUWn1GCPI1mQgiSWJ?= =?us-ascii?Q?c4y4IbyTxL50ux/RChrOitjskn/t+dES8KEzHPW4FVfqbpy0UR3HyqFJJEn7?= =?us-ascii?Q?VmTECw=3D?= X-Microsoft-Exchange-Diagnostics: 1; DM5PR15MB1916; 6:lYSFzlx4GqiHhTCk9otuUbvzyuc0rXtofFWjrkOWcp98ak8+h35RZ49wijsFFlo7jEyE1RxcO86TNHkRCFz4WC5xdgyot7QqmDMZvtGH92ne090TawGYt4KSAPk1Foi64TIH2VED4q3WxzZ48UD1NzD+KdkYRCUCwu14Q8DvSgrGacQ9SOB4DNvYGhYX2ldWiWBneRwHBvgyVw3wCjhjkBvFAqWOIaUFwB1Q7WallYsCG/Yn+aWt1LO7ylaZWdVripdWY8sC8ITaQGFXxdbCOyZuwj4pDQ3KRG/fInYaNGXhBEpSO9NNjvg9jYFaDq5nrSe55OIZRjMPloWcfY+OGbzMljraBfZG0MhfE/PyTSx30n1W/W9trXDPVr9eAWjDBZrvMaYV9dHYLcO/vR7Wrg==; 5:D4DnZeCaGNc0UTr4hoUNuPG6Ufy1d8ZMhfNsmfNRkb+zBko7MEs4HcnKlI5RivCmBXEGag8hSmxUu8WmwSrYtv5a/lPudwYqf84dE6qQBr8BF1LncyTOCXJS3Xwa2F6FcxzGqlRnv5nYqqQQuZ3b6g==; 24:h7ipfLGhtfTmgOV1rtyAbeUQZX2+yi2SQ2astvRY71/baDvuu1dqD587/AsEQcfwvFHanvRChlJIfc9EXIy95fMu3aDjvoxCdjRXBetvgz4= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; DM5PR15MB1916; 7:ePikiRU5Hy23CjUD3hteLS+VMDlbHxHl/+PsWwYkM79YDs2eqWGVnypcTUgKXXJvTYKjwXStG7w4x2f1DHSmrHZoUR5zyL9qVNP3mQv2tbbnLwJRz0VgyIAegu30Z5a5ueEIP53Q3m265da6DSA7NMLA9Q2WP8MxuvFScLaB4PmCroKoOwgKuASzpvEBj/jp7KRx+3oiKIwUH9fjEQv6xNGueMaYejADdqj+SkzicjFZ7lqfCr0BGi46PF/ZZnj7WCDOiedi5yYh9rfJYToWOwHtu2Gk1m2dfP1Ttqxl95oq1Qt+FNxSz9ZFw2lSMkm6jg+Gs3t0eaRjQUwY19/2IsYPd8I0QQ2ZGX9pYVGK53/3VmgDwbZryvH75zbt3QHhbuMBv78SpdGwP862LxTEbexR/U11dm3HM2Qv0wbGZLJ2f+pzF3tn+QjKevyFjP5t6U32neBtBaMVZaBo189ygKnaZsMYgvhk0rUZ2nbvQjDPx3rKWJkA/JK7QeXXgfDJE61/IDWbgqs+y+GfJMUsvw==; 20:m0nn/PDrM+IcBucTll83fmUF7SIzTk/0V3h8vgivahOYJJGY2Uci8AuSWNX4bVhf4esWPoWhRqmn3/S+3eoD69QW7fMASlIy9vD3QwGC9wk7nLoRenU9tCivZ9E9Ll9Meyxjt/Qd8diuYIbarNmpbrTfv+T8B9yoSdNyTIWTYf0= X-MS-Exchange-CrossTenant-OriginalArrivalTime: 08 Feb 2017 15:05:09.0672 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM5PR15MB1916 X-OriginatorOrg: fb.com X-Proofpoint-Spam-Reason: safe X-FB-Internal: Safe X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-02-08_10:, , signatures=0 Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP In preparation for allowing seamless reconnects we need a way to make sure that we don't free the socks array out from underneath ourselves. So a socks_ref counter in order to keep track of who is using the socks array, and only free it and change num_connections once our reference reduces to zero. We also need to make sure that somebody calling SET_SOCK isn't coming in before we're done with our socks array, so add a waitqueue to wait on previous users of the socks array before initiating a new socks array. Signed-off-by: Josef Bacik --- V1->V2: -req->errors++ in the timeout handler if we can't get a ref on our socks. -drop another use of nbd->config_lock in the timeout handler I missed. drivers/block/nbd.c | 131 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 93 insertions(+), 38 deletions(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 1914ba2..afb1353 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -54,19 +54,24 @@ struct nbd_sock { #define NBD_TIMEDOUT 0 #define NBD_DISCONNECT_REQUESTED 1 #define NBD_DISCONNECTED 2 -#define NBD_RUNNING 3 +#define NBD_HAS_SOCKS_REF 3 struct nbd_device { u32 flags; unsigned long runtime_flags; + + struct mutex socks_lock; struct nbd_sock **socks; + atomic_t socks_ref; + wait_queue_head_t socks_wq; + int num_connections; + int magic; struct blk_mq_tag_set tag_set; struct mutex config_lock; struct gendisk *disk; - int num_connections; atomic_t recv_threads; wait_queue_head_t recv_wq; loff_t blksize; @@ -102,7 +107,6 @@ static int part_shift; static int nbd_dev_dbg_init(struct nbd_device *nbd); static void nbd_dev_dbg_close(struct nbd_device *nbd); - static inline struct device *nbd_to_dev(struct nbd_device *nbd) { return disk_to_dev(nbd->disk); @@ -125,6 +129,27 @@ static const char *nbdcmd_to_ascii(int cmd) return "invalid"; } +static int nbd_socks_get_unless_zero(struct nbd_device *nbd) +{ + return atomic_add_unless(&nbd->socks_ref, 1, 0); +} + +static void nbd_socks_put(struct nbd_device *nbd) +{ + if (atomic_dec_and_test(&nbd->socks_ref)) { + mutex_lock(&nbd->socks_lock); + if (nbd->num_connections) { + int i; + for (i = 0; i < nbd->num_connections; i++) + kfree(nbd->socks[i]); + kfree(nbd->socks); + nbd->num_connections = 0; + nbd->socks = NULL; + } + mutex_unlock(&nbd->socks_lock); + } +} + static int nbd_size_clear(struct nbd_device *nbd, struct block_device *bdev) { bdev->bd_inode->i_size = 0; @@ -190,6 +215,7 @@ static void sock_shutdown(struct nbd_device *nbd) mutex_lock(&nsock->tx_lock); kernel_sock_shutdown(nsock->sock, SHUT_RDWR); mutex_unlock(&nsock->tx_lock); + nsock->dead = true; } dev_warn(disk_to_dev(nbd->disk), "shutting down sockets\n"); } @@ -200,10 +226,14 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req, struct nbd_cmd *cmd = blk_mq_rq_to_pdu(req); struct nbd_device *nbd = cmd->nbd; + if (!nbd_socks_get_unless_zero(nbd)) { + req->errors++; + return BLK_EH_HANDLED; + } + if (nbd->num_connections > 1) { dev_err_ratelimited(nbd_to_dev(nbd), "Connection timed out, retrying\n"); - mutex_lock(&nbd->config_lock); /* * Hooray we have more connections, requeue this IO, the submit * path will put it on a real connection. @@ -217,21 +247,19 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req, kernel_sock_shutdown(nsock->sock, SHUT_RDWR); mutex_unlock(&nsock->tx_lock); } - mutex_unlock(&nbd->config_lock); blk_mq_requeue_request(req, true); + nbd_socks_put(nbd); return BLK_EH_RESET_TIMER; } - mutex_unlock(&nbd->config_lock); } else { dev_err_ratelimited(nbd_to_dev(nbd), "Connection timed out\n"); } set_bit(NBD_TIMEDOUT, &nbd->runtime_flags); req->errors++; - - mutex_lock(&nbd->config_lock); sock_shutdown(nbd); - mutex_unlock(&nbd->config_lock); + nbd_socks_put(nbd); + return BLK_EH_HANDLED; } @@ -523,6 +551,7 @@ static void recv_work(struct work_struct *work) nbd_end_request(cmd); } + nbd_socks_put(nbd); atomic_dec(&nbd->recv_threads); wake_up(&nbd->recv_wq); } @@ -598,9 +627,16 @@ static int nbd_handle_cmd(struct nbd_cmd *cmd, int index) struct nbd_sock *nsock; int ret; + if (!nbd_socks_get_unless_zero(nbd)) { + dev_err_ratelimited(disk_to_dev(nbd->disk), + "Socks array is empty\n"); + return -EINVAL; + } + if (index >= nbd->num_connections) { dev_err_ratelimited(disk_to_dev(nbd->disk), "Attempted send on invalid socket\n"); + nbd_socks_put(nbd); return -EINVAL; } req->errors = 0; @@ -608,8 +644,10 @@ static int nbd_handle_cmd(struct nbd_cmd *cmd, int index) nsock = nbd->socks[index]; if (nsock->dead) { index = find_fallback(nbd, index); - if (index < 0) + if (index < 0) { + nbd_socks_put(nbd); return -EIO; + } nsock = nbd->socks[index]; } @@ -627,7 +665,7 @@ static int nbd_handle_cmd(struct nbd_cmd *cmd, int index) goto again; } mutex_unlock(&nsock->tx_lock); - + nbd_socks_put(nbd); return ret; } @@ -656,6 +694,25 @@ static int nbd_queue_rq(struct blk_mq_hw_ctx *hctx, return BLK_MQ_RQ_QUEUE_OK; } +static int nbd_wait_for_socks(struct nbd_device *nbd) +{ + int ret; + + if (!atomic_read(&nbd->socks_ref)) + return 0; + + do { + mutex_unlock(&nbd->socks_lock); + mutex_unlock(&nbd->config_lock); + ret = wait_event_interruptible(nbd->socks_wq, + atomic_read(&nbd->socks_ref) == 0); + mutex_lock(&nbd->config_lock); + mutex_lock(&nbd->socks_lock); + } while (!ret && atomic_read(&nbd->socks_ref)); + + return ret; +} + static int nbd_add_socket(struct nbd_device *nbd, struct block_device *bdev, unsigned long arg) { @@ -668,21 +725,30 @@ static int nbd_add_socket(struct nbd_device *nbd, struct block_device *bdev, if (!sock) return err; - if (!nbd->task_setup) + err = -EINVAL; + mutex_lock(&nbd->socks_lock); + if (!nbd->task_setup) { nbd->task_setup = current; + if (nbd_wait_for_socks(nbd)) + goto out; + atomic_inc(&nbd->socks_ref); + set_bit(NBD_HAS_SOCKS_REF, &nbd->runtime_flags); + } + if (nbd->task_setup != current) { dev_err(disk_to_dev(nbd->disk), "Device being setup by another task"); - return -EINVAL; + goto out; } + err = -ENOMEM; socks = krealloc(nbd->socks, (nbd->num_connections + 1) * sizeof(struct nbd_sock *), GFP_KERNEL); if (!socks) - return -ENOMEM; + goto out; nsock = kzalloc(sizeof(struct nbd_sock), GFP_KERNEL); if (!nsock) - return -ENOMEM; + goto out; nbd->socks = socks; @@ -694,7 +760,10 @@ static int nbd_add_socket(struct nbd_device *nbd, struct block_device *bdev, if (max_part) bdev->bd_invalidated = 1; - return 0; + err = 0; +out: + mutex_unlock(&nbd->socks_lock); + return err; } /* Reset all properties of an NBD device */ @@ -750,20 +819,17 @@ static void send_disconnects(struct nbd_device *nbd) static int nbd_disconnect(struct nbd_device *nbd, struct block_device *bdev) { dev_info(disk_to_dev(nbd->disk), "NBD_DISCONNECT\n"); - if (!nbd->socks) + if (!nbd_socks_get_unless_zero(nbd)) return -EINVAL; mutex_unlock(&nbd->config_lock); fsync_bdev(bdev); mutex_lock(&nbd->config_lock); - /* Check again after getting mutex back. */ - if (!nbd->socks) - return -EINVAL; - if (!test_and_set_bit(NBD_DISCONNECT_REQUESTED, &nbd->runtime_flags)) send_disconnects(nbd); + nbd_socks_put(nbd); return 0; } @@ -773,22 +839,9 @@ static int nbd_clear_sock(struct nbd_device *nbd, struct block_device *bdev) nbd_clear_que(nbd); kill_bdev(bdev); nbd_bdev_reset(bdev); - /* - * We want to give the run thread a chance to wait for everybody - * to clean up and then do it's own cleanup. - */ - if (!test_bit(NBD_RUNNING, &nbd->runtime_flags) && - nbd->num_connections) { - int i; - - for (i = 0; i < nbd->num_connections; i++) - kfree(nbd->socks[i]); - kfree(nbd->socks); - nbd->socks = NULL; - nbd->num_connections = 0; - } nbd->task_setup = NULL; - + if (test_and_clear_bit(NBD_HAS_SOCKS_REF, &nbd->runtime_flags)) + nbd_socks_put(nbd); return 0; } @@ -809,7 +862,6 @@ static int nbd_start_device(struct nbd_device *nbd, struct block_device *bdev) goto out_err; } - set_bit(NBD_RUNNING, &nbd->runtime_flags); blk_mq_update_nr_hw_queues(&nbd->tag_set, nbd->num_connections); args = kcalloc(num_connections, sizeof(*args), GFP_KERNEL); if (!args) { @@ -833,6 +885,7 @@ static int nbd_start_device(struct nbd_device *nbd, struct block_device *bdev) for (i = 0; i < num_connections; i++) { sk_set_memalloc(nbd->socks[i]->sock->sk); atomic_inc(&nbd->recv_threads); + atomic_inc(&nbd->socks_ref); INIT_WORK(&args[i].work, recv_work); args[i].nbd = nbd; args[i].index = i; @@ -849,7 +902,6 @@ static int nbd_start_device(struct nbd_device *nbd, struct block_device *bdev) mutex_lock(&nbd->config_lock); nbd->task_recv = NULL; out_err: - clear_bit(NBD_RUNNING, &nbd->runtime_flags); nbd_clear_sock(nbd, bdev); /* user requested, ignore socket errors */ @@ -1149,12 +1201,15 @@ static int nbd_dev_add(int index) nbd->magic = NBD_MAGIC; mutex_init(&nbd->config_lock); + mutex_init(&nbd->socks_lock); + atomic_set(&nbd->socks_ref, 0); disk->major = NBD_MAJOR; disk->first_minor = index << part_shift; disk->fops = &nbd_fops; disk->private_data = nbd; sprintf(disk->disk_name, "nbd%d", index); init_waitqueue_head(&nbd->recv_wq); + init_waitqueue_head(&nbd->socks_wq); nbd_reset(nbd); add_disk(disk); return index;