From patchwork Tue Feb 7 22:10:53 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 9561485 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 3502260413 for ; Tue, 7 Feb 2017 23:13:25 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2AB902849A for ; Tue, 7 Feb 2017 23:13:25 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1F5D62849D; Tue, 7 Feb 2017 23:13:25 +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 5568F2849A for ; Tue, 7 Feb 2017 23:13:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932077AbdBGXNW (ORCPT ); Tue, 7 Feb 2017 18:13:22 -0500 Received: from mx0a-00082601.pphosted.com ([67.231.145.42]:44334 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932728AbdBGXNU (ORCPT ); Tue, 7 Feb 2017 18:13:20 -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 v17M4PrM014448; Tue, 7 Feb 2017 14:11:00 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fb.com; h=from : to : subject : date : message-id : mime-version : content-type; s=facebook; bh=DQwjoNfzgBbmHq7jWvVOW/OEA90ylSv9EK8oPRcvMyY=; b=aTocBRXhyWF9lt18T8ET6XtVPnWjpjeACeFjkELMiHp3WwGclm1ibATga2h8yqgIi2Pc NK9cLPtyymN4AMQK201T3h5BtW0bY21iz/wJzmfPtxE2e2ehzCuO48bwpxcMEAnf4hpA vSfeIqwwy1jr7oYJTHrmpjdsQKGJIrvVSHo= Received: from mail.thefacebook.com ([199.201.64.23]) by mx0a-00082601.pphosted.com with ESMTP id 28ffenhsgk-2 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Tue, 07 Feb 2017 14:11:00 -0800 Received: from NAM01-SN1-obe.outbound.protection.outlook.com (192.168.54.28) by o365-in.thefacebook.com (192.168.16.14) with Microsoft SMTP Server (TLS) id 14.3.294.0; Tue, 7 Feb 2017 14:10:58 -0800 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=DQwjoNfzgBbmHq7jWvVOW/OEA90ylSv9EK8oPRcvMyY=; b=QcM2S1SbPXiI+2o7VS42YernfAmoxGju7VkOk0lqoXJjmjASL+5SJDzPG4aHXq6Frmju81rzZDVT76LsSa4xLNHffCbPS7J4EGIAFHr+Y0AsSla+0Yhl4esFa56q3A7doBXnmsHDBi3fqrTgYezXPHQ//Ij5wwmNgsAsveXKVfw= Received: from localhost (2606:a000:4381:1201:225:22ff:feb3:e51a) by DM5PR15MB1915.namprd15.prod.outlook.com (10.174.247.143) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.888.16; Tue, 7 Feb 2017 22:10:56 +0000 From: Josef Bacik To: , , , Subject: [PATCH] nbd: ref count the socks array Date: Tue, 7 Feb 2017 17:10:53 -0500 Message-ID: <1486505453-2976-1-git-send-email-jbacik@fb.com> X-Mailer: git-send-email 2.7.4 MIME-Version: 1.0 X-Originating-IP: [2606:a000:4381:1201:225:22ff:feb3:e51a] X-ClientProxiedBy: DM5PR13CA0007.namprd13.prod.outlook.com (10.168.112.17) To DM5PR15MB1915.namprd15.prod.outlook.com (10.174.247.143) X-MS-Office365-Filtering-Correlation-Id: beb8e521-3978-48c6-8209-08d44fa630d6 X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001); SRVR:DM5PR15MB1915; X-Microsoft-Exchange-Diagnostics: 1; DM5PR15MB1915; 3:NZmDQA3KMG4EqyI6I+QJsHwGpgR6AA63tHl2RYOfYuBNEKA53Nv+JoDbIZWn+1NcuFflEJLEGnlFlv0ihxS749gD0tVFjq+9vkX8NR0bet8Q8w83d9BU6l4qqNadBnTB3t3dobvaxtiWbyQWJaKbLnn2DShDJjAIs22EYuYEgCr/Ppq1YiRPzWLmW9XHa6HuLJigPo3YnUaM7YXXEwW2MtsOk7au6GCQfWCN+Pth86EZTeyE4ETdkxCWqlPBBP9oZiQg86DDHudJ75ILTy+n2g==; 25:TLoeCJRqXy/ysFe7loidxUfUpO1WtlnXlSRYUmfonkY7SYQiUtgweUbioVwg5gNj9dKs3Vi+jIeHjOSRshyDYtsXfKGqQqRcsgSeZ1Es5h+WEpwfTTTFlDUNgQU2p3ylpPNK16X7ksCdbGerHkf4YXZ3CWr+l/PBLHCAiwmrbJw6SzieKYT42Opama6JXlCAiP2M30mM04QFabJ1jv+/y4DvKd3v4LhPOeyxkG/rf9oLTSNr8egEjBThICL+voJAEHYsaAbwLeoNXzMo/vPbL2n/iL/ubR0gsF0xZcgoCkO98JbOoGfiah03dWcY4KTxiDrOjbecK1+bSGw0m9GK2ICoGCep7kMM0EubWrSS7kM3Esko26uHQj+globtitgmjKZjgvSPNtreqpoIS2MYZXgumP4jF6ojsYK8ySXVClKJcrqv0Vf4KoShMjCdejlCFSmZuJBmXEqKcSqOgc4nMQ== X-Microsoft-Exchange-Diagnostics: 1; DM5PR15MB1915; 31:/A5AXtw6JuHslYe+UtuYY6zhsx38miuYn6MZHnFp25SuEMh/xVXqdE/EV5tznCoNLtZbTXfTbHpVbB228IItmF2cgiQUMJRHe6dxolS4pri0iG32okEhrsCmFMU4541wofmUXr2aNMT69AnPH8d5KIEYREpV9yODUCA/Ys1P0xWW3d83GqRhcWaVbbaCVliGv1Npsviug5Lac7zEzuc9+DKbQyhc/prZ2hmt/F05FHcdTB0BU6FTwrWKwaZuuJBj; 20:dlMFuh9riczFaKnLmPkTf6UB8FD/aARhRl2J5YrEGiOuRtcbcdJzvHx7YFUoPVhEV/6oiRHp15E9ZJ7g8mOiIETBOT4/wT/Zx5MspeKfKrolxrYfVX/xccxk1sL4Nu6q/W+kuWAouCi2v6AGn45xDAKxFKfhg1BA9DXEYGWVWWQycHr4ILv4mA9ImjB0zWZ4RQTvbUkMJvhPHe9cigvGDt9Thojd1xDOFp2C1B5+w8u341f8OTuxwgF2bKDgaGIGGg+gMqMxJnNkMNPr5Qfq13uxXC/+CvKwfBGj4jWUBZeYZ5U+Rc0ZvDCgiQu3fL8lnW3hrnJlk/wPitna4gaL1xLEE+m1jHUzBjqtNG/Uu+i7a1ru71wE+lsa+A8aNiLrDO88mAWfFNnkdzvyLF4AAJBekV4rQ8998aspArzH0axbF7yE8+v5LPBZI2mrxoseJougmJzPUxYfEuaWy6kDk8E84wLV94SY6sPatG/fgDcPloRgv4sI+FgO2iShNaMw 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)(2017020603029)(20170203043)(8121501046)(5005006)(3002001)(10201501046)(6041248)(20161123562025)(20161123555025)(20161123558025)(20161123560025)(20161123564025)(6072148); SRVR:DM5PR15MB1915; BCL:0; PCL:0; RULEID:; SRVR:DM5PR15MB1915; X-Microsoft-Exchange-Diagnostics: 1; DM5PR15MB1915; 4:7qp5s/cZZK2CA3GJTCxH79lIaX193FjgIxg2wdn1cPIegMVDc/KgDn3vIGzVxrFzSk84LX4vUAu8cBfjSBIHLcSwlSNs4d0v20QjGyeULUNRkd8I6r0+dp4L+CskPwUTWJkMPdBRLDYPaPTihqtu8pn69mdvDJizLe9ykmoNJMKhHEu/G5bKZbIo5MVUa6/PRuYx38UKj2G7wajzU62Ty0nQ8AbIl+pKvdIuo4PUOoIRA2AqAquRmwzlS36RtB4vaEJ1lqQ8nzzxocWzrqmTYrfi/UG3nV5g3R0Q9cZ6pekzk1jwDPL0C/zcnCHIs2DKMhCXt9+3F0f1cKVpIaXAs06ZRACUD5LGVHIXczLQx1WMQhtd7FrpqeDHlwn3Lm/RRN5oUYIMUhbPOz0RsAIpmdLBkvxk59qezHpVMsBfnLmw4ErUwBGBRzkYDyUchQjaCetJe+hi4MQJVJ/9xKEoNO9pocVldQsqrYD1DcW1oU12evH63JS3rLRx/e8Iy/o+CKgXLsazEdrseeuBcaaORRMPn4SOF64TnmUTq4Wb91UAICK/zNF+O42a3XUXmNgW1s4P/Af2xrM0sf19rphQEbIy/5dt4s8CxH7bai9a4eFb9bx9J3lLueP1C0bq8lWONH7OU9TMa+gvXq6uFSfC/1ZiLOHnEprFmXIeyMYPWeEGGujEIBusquyPvPjo9OtLg+fRScUqCB2xDbz16ls5lA== X-Forefront-PRVS: 0211965D06 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10019020)(4630300001)(6009001)(6069001)(7916002)(39450400003)(189002)(45904002)(199003)(6486002)(2201001)(86362001)(5003940100001)(2906002)(97736004)(92566002)(50986999)(47776003)(101416001)(42186005)(7736002)(305945005)(5660300001)(189998001)(6666003)(36756003)(33646002)(48376002)(25786008)(6496005)(50226002)(105586002)(50466002)(68736007)(106356001)(8676002)(53936002)(6116002)(81166006)(38730400002)(81156014)(76506005); DIR:OUT; SFP:1102; SCL:1; SRVR:DM5PR15MB1915; 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; DM5PR15MB1915; 23:UAOfkYDIhP9T04XqX0aGIN4RyEjfLZt2WcZFV6SQF?= =?us-ascii?Q?7FX+NNxgcTzXtw1wbBON9bHDCfs/PjrYhVu5AHy1n9HBKyAbG99n4YPvQ8yq?= =?us-ascii?Q?+y8dP/WnDj+31BMtrhxldERLrPLtdHLEW8VbKNnpQDej7e/RGBXseT43HPvU?= =?us-ascii?Q?tChpOzXWcwqwj7C6cOQi9khLXpqB5FA3Bfy1oszil9vG4JqqLlEbj0DzXhel?= =?us-ascii?Q?fP+Ty8pROgL3vvCkFBqQ9BVV+7TWbvRQFpEgqp0T7AhH2eW/jnFsZBExBusc?= =?us-ascii?Q?28cKpqbKusapqFz5NbsT9rixfmyRcQYHRtK8IPbai2Xums91t1GvHlkfsm62?= =?us-ascii?Q?N7fkBeGaWyebVOkSRZkNcs9nH8PbNjuyeok5t7M3Rcv32V5yRkhQTazt/Vmm?= =?us-ascii?Q?lf0doXY/IEaTYhuQ9p+XHjGNcptGp5kRlG1uqWQ38QfFV9PqsHxBo98cI2Ve?= =?us-ascii?Q?e2sjTENCBM8VVMIUMcgOgg7kt1nvRJZai8rHj6vibnVUB5p5/Uaixk6wndTa?= =?us-ascii?Q?KiolvbsSB4TmEVSXhiV1mcQJ20/MFCaofz6zvYUs+IuNv9IgB3VGkOrV65V+?= =?us-ascii?Q?nCyup95WkeiijXyYbHxj0DExZV45CbEGAvSM2xckeH1o/nbGbOhIZsFfpQ2H?= =?us-ascii?Q?BgZcb49W+b/mgyW+MkzoQb6+FgmAhyI8xWKfeWoZ/ApWxykOBKMvgTgutQms?= =?us-ascii?Q?TRmzyH5L+MY5chFp1uKi286Ajd+r22wMHBOqGSYSJijkeoFHpsdW1pfBa+dQ?= =?us-ascii?Q?qfTIAlrGcY0f+jB/Asfn77pNU5wgpwXLvb8F/CsRnzkmUwPtw11KuIxFgIsj?= =?us-ascii?Q?zrWU8Nugagza7Ar0OvqDM66dwVqIwghWje1i0UcuhF392rM+pilSYhOZ4ybg?= =?us-ascii?Q?EA6MnGZnu/NE6Ho4UtF6RF1O+BiMwrcqXYSqbtXKcfb5OYXf4BGcsVMoF8+c?= =?us-ascii?Q?YxGrnzBVa4gIqYjKZ1UL7J4EI3pOGtjD38WpxVn5EPKl6PTMgVH0eMB4x/+D?= =?us-ascii?Q?IXfKACHMAu33+/niOZmDmu8?= X-Microsoft-Exchange-Diagnostics: 1; DM5PR15MB1915; 6:T9AqcyEj1f61aT/5uFms/onHL9K81E3U9rGPj63XN1+1l2ve0BgZDPDLpAa2+RRtvhImCZBDA68ImW3LdqCZpl9LI55pKp7AAZAJaMKP7LS9NN2I+VTzm3aqYRdlR3qx6OxNp5jJbWqxOIF8Qs+QPdDrw2zQ39QtjCYYKPn3fXtCdAgT4T0C6183QyiRuIHSGV631Hfx8D+BaX7559ffV260lzMK1ltjmjbwtefCI61YOJpBcv++/O6GWykmMZMicoD+vHwmpuZM2TjnAPbmSxp3QmWHq7UAmZ2/qAH32t7vcpCWcxHjHCq/6+TRnVhC5wILSg9WjGNAeA97WO02mwqVKV+uj37FlpyMGKzXML/NmYKApC8jmDI/z+8w1d42gIuEVw6P2aqC9T8Rs1YP9w==; 5:Makub1hZDV68jNS8QrQx2Q57Ky8mHQ0CFhPcugr/ecJWZ9haUunqhb9WFPPNMHUk0k9U3UMLuELJBAU2MifZr7berGjBfOiO7utmHQATHd/k0CAijLOMw7DckFL9qBiwopMRZOycTfVJMmTByuyEow==; 24:zRQ0QiI0aQ7hdk6RMRUl+lMbAkNqeys5w/gmIw/AUdReP9JGo/ak/64/XcYUBI0dgozTwTS6fvaA6AvEWo9TbM9PDOI+tHnhaD2nqE+v/HE= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; DM5PR15MB1915; 7:BWjr+C/dXAHU4F+KjeBA6APc8W1zSLt+qS/LADUn3Azw839eY/jn4vT9ik6po1cjsVJuU4ad5OAqXQWaBQdfofZt2EUX+5T+pP/YQY8JMwH51fzW24cEt65xiIP+Wq0CoakRBg5cjL7k5mO377YfMThQ2FjI4l8DErcwB67Drw9hSeq9E8IrkU6W8ggYbkTVm8z6+xbueLrihXGwn29aLl0pd1EipX5Um7PMv4HNZJbwGjZ6igd6BAypXx/VBuHdRaig+KQp4H3bICQ1fbBbJiXode8M8Q43xF/z+UaPDYn9u+0ZZYJd9rl4Uqw8GVSW8JmUjK+0ixrKRoZQ5lPVvBJpnM+l4vsT6yUXmRuB9jAKPvdN1nspP6cfOXjkWd8Z1/deagh5Ymj4HmPxlpBcBb0xEPvctJYQSwHTvbOVKNJ6EWZAY7dFmGhk8vFoCUdodO+JnIRtGc6nCt72sGfZ9lasBrAyQwpzflmd03Cp72nbQHffmqh3phymIN448dkXgaR/V9UPjgBLUJBmuslyYA==; 20:zgCHuuJMDd0EijAu/6aDOYow1ib5PDuwFKboKrh16anjZFvnNQwh3XMrfDCSNnuHMfjeYopMH3/6q1APCF0YYsbJfqRXLRdZk/11viYSLpKGGHpCfGj3ieHtn59ODJxWBC9n5VyS9+GEvZftIsecBEz3j6SkHg2783XWMGBGxvE= X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Feb 2017 22:10:56.6940 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM5PR15MB1915 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-07_12:, , 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 --- drivers/block/nbd.c | 126 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 91 insertions(+), 35 deletions(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 1914ba2..3dc2f1d 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,6 +226,9 @@ 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)) + return BLK_EH_HANDLED; + if (nbd->num_connections > 1) { dev_err_ratelimited(nbd_to_dev(nbd), "Connection timed out, retrying\n"); @@ -219,6 +248,7 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req, } 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); @@ -228,10 +258,9 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req, } 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 +552,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 +628,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 +645,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 +666,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 +695,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 +726,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 +761,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 +820,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 +840,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 +863,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 +886,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 +903,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 +1202,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;