From patchwork Thu Jul 2 08:49:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 11638311 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 834EE618 for ; Thu, 2 Jul 2020 08:49:25 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6B8EE2088E for ; Thu, 2 Jul 2020 08:49:25 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b="QRLMMTFs" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726739AbgGBItY (ORCPT ); Thu, 2 Jul 2020 04:49:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51060 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725287AbgGBItY (ORCPT ); Thu, 2 Jul 2020 04:49:24 -0400 Received: from casper.infradead.org (casper.infradead.org [IPv6:2001:8b0:10b:1236::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5D2F9C08C5C1 for ; Thu, 2 Jul 2020 01:49:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To: Content-Type:Content-ID:Content-Description; bh=A/I1vcnEOWPovRd4d32sgJlzY0F1UatPERDEAW8X52Y=; b=QRLMMTFsc/svpBXpLjllssJp1+ whFAtpb9cPFE4gbAjV4byQETZOpwy3yZvBZ4JIJBVXghoI94dPMpwNB4OCJgn9TMwUK+2SrfNdG1V jg3MUWomq0PB6yRCaGhCr3y9oLJ+gd9mVmb4/xJOpZI30a6+amM0i0x6vyu4EkFzsFSDUXxz2jg4A F7S74CrHKkNuDx6oSX9Z+zzkQMWfwAovDr3STOEhc/o72IJYGP43Rn3Kk+hIITZeGRUqM2denlMIY dPyCwGA4swE1ZlBFvgC+GlREIv7cpBDa1rO6rY2q3SDKfs7hv0wuRNiBsJSOOq4Py/8LJXcuMmvRO wWj4GAuA==; Received: from [213.208.157.36] (helo=localhost) by casper.infradead.org with esmtpsa (Exim 4.92.3 #3 (Red Hat Linux)) id 1jquuH-0001VR-Ql; Thu, 02 Jul 2020 08:49:22 +0000 From: Christoph Hellwig To: Jens Axboe Cc: Tejun Heo , linux-block@vger.kernel.org Subject: [PATCH 1/4] block: simplify the restart case in __blkdev_get Date: Thu, 2 Jul 2020 10:49:16 +0200 Message-Id: <20200702084919.3720275-2-hch@lst.de> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200702084919.3720275-1-hch@lst.de> References: <20200702084919.3720275-1-hch@lst.de> MIME-Version: 1.0 X-SRS-Rewrite: SMTP reverse-path rewritten from by casper.infradead.org. See http://www.infradead.org/rpr.html Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org Insted of duplicating all the cleanup logic jump to the code that cleans up anyway, and restart after that. Signed-off-by: Christoph Hellwig --- fs/block_dev.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/fs/block_dev.c b/fs/block_dev.c index 2d2fcb50e78eac..175161359664ca 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1533,7 +1533,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) int ret; int partno; int perm = 0; - bool first_open = false; + bool first_open = false, need_restart; if (mode & FMODE_READ) perm |= MAY_READ; @@ -1549,7 +1549,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) } restart: - + need_restart = false; ret = -ENXIO; disk = bdev_get_gendisk(bdev, &partno); if (!disk) @@ -1572,19 +1572,12 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) ret = 0; if (disk->fops->open) { ret = disk->fops->open(bdev, mode); - if (ret == -ERESTARTSYS) { - /* Lost a race with 'disk' being - * deleted, try again. - * See md.c - */ - disk_put_part(bdev->bd_part); - bdev->bd_part = NULL; - bdev->bd_disk = NULL; - mutex_unlock(&bdev->bd_mutex); - disk_unblock_events(disk); - put_disk_and_module(disk); - goto restart; - } + /* + * If we lost a race with 'disk' being deleted, + * try again. See md.c + */ + if (ret == -ERESTARTSYS) + need_restart = true; } if (!ret) { @@ -1663,6 +1656,8 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) mutex_unlock(&bdev->bd_mutex); disk_unblock_events(disk); put_disk_and_module(disk); + if (need_restart) + goto restart; out: return ret; From patchwork Thu Jul 2 08:49:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 11638313 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C0499618 for ; Thu, 2 Jul 2020 08:49:26 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id AA31420899 for ; Thu, 2 Jul 2020 08:49:26 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b="dP0MTDkN" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726795AbgGBIt0 (ORCPT ); Thu, 2 Jul 2020 04:49:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51064 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726756AbgGBItZ (ORCPT ); Thu, 2 Jul 2020 04:49:25 -0400 Received: from casper.infradead.org (casper.infradead.org [IPv6:2001:8b0:10b:1236::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9436EC08C5C1 for ; Thu, 2 Jul 2020 01:49:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To: Content-Type:Content-ID:Content-Description; bh=/+bs9PLAAXK7prLaqGkUBN2MMIOC32HFr2vxtRpOOnE=; b=dP0MTDkN0D6tzNfpTfMqtRtBdY hfEE/KS2tt4XTuHhhxDikudPnyFrTG8+K3yYnN8NC3uJtT/v6hDidlWYca4DGVkY2RXFltCLy2tpH k1s402YCwH/SpH6SY/NGflqp6ftj45/s3hJJi2I8UvwaagT9JdtxdT2NEM83D7v9LhowG1Lyu9qEg PqcpXFU5BqbAAqilzgWsSn1hDNS7WZ1YKWZUe0oLCdNdLx1cnjFQKCmWHOEjLYERg+rj2jDu2/j6y S63F93tGbDv+s2rSErO162VT3swMXpcMC874IaHiTomSukMIkoANqHmZyq1zDNioev5fkecnypnhP AY99tLAg==; Received: from [213.208.157.36] (helo=localhost) by casper.infradead.org with esmtpsa (Exim 4.92.3 #3 (Red Hat Linux)) id 1jquuJ-0001Va-Aa; Thu, 02 Jul 2020 08:49:23 +0000 From: Christoph Hellwig To: Jens Axboe Cc: Tejun Heo , linux-block@vger.kernel.org Subject: [PATCH 2/4] block: refactor bd_start_claiming Date: Thu, 2 Jul 2020 10:49:17 +0200 Message-Id: <20200702084919.3720275-3-hch@lst.de> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200702084919.3720275-1-hch@lst.de> References: <20200702084919.3720275-1-hch@lst.de> MIME-Version: 1.0 X-SRS-Rewrite: SMTP reverse-path rewritten from by casper.infradead.org. See http://www.infradead.org/rpr.html Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org Move the locking and assignment of bd_claiming from bd_start_claiming to bd_prepare_to_claim. Signed-off-by: Christoph Hellwig --- fs/block_dev.c | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/fs/block_dev.c b/fs/block_dev.c index 175161359664ca..1c9da1f08011b0 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1015,19 +1015,14 @@ static bool bd_may_claim(struct block_device *bdev, struct block_device *whole, } /** - * bd_prepare_to_claim - prepare to claim a block device + * bd_prepare_to_claim - claim a block device * @bdev: block device of interest * @whole: the whole device containing @bdev, may equal @bdev * @holder: holder trying to claim @bdev * - * Prepare to claim @bdev. This function fails if @bdev is already - * claimed by another holder and waits if another claiming is in - * progress. This function doesn't actually claim. On successful - * return, the caller has ownership of bd_claiming and bd_holder[s]. - * - * CONTEXT: - * spin_lock(&bdev_lock). Might release bdev_lock, sleep and regrab - * it multiple times. + * Claim @bdev. This function fails if @bdev is already claimed by another + * holder and waits if another claiming is in progress. return, the caller + * has ownership of bd_claiming and bd_holder[s]. * * RETURNS: * 0 if @bdev can be claimed, -EBUSY otherwise. @@ -1036,9 +1031,12 @@ static int bd_prepare_to_claim(struct block_device *bdev, struct block_device *whole, void *holder) { retry: + spin_lock(&bdev_lock); /* if someone else claimed, fail */ - if (!bd_may_claim(bdev, whole, holder)) + if (!bd_may_claim(bdev, whole, holder)) { + spin_unlock(&bdev_lock); return -EBUSY; + } /* if claiming is already in progress, wait for it to finish */ if (whole->bd_claiming) { @@ -1049,11 +1047,12 @@ static int bd_prepare_to_claim(struct block_device *bdev, spin_unlock(&bdev_lock); schedule(); finish_wait(wq, &wait); - spin_lock(&bdev_lock); goto retry; } /* yay, all mine */ + whole->bd_claiming = holder; + spin_unlock(&bdev_lock); return 0; } @@ -1134,19 +1133,13 @@ struct block_device *bd_start_claiming(struct block_device *bdev, void *holder) if (!whole) return ERR_PTR(-ENOMEM); - /* prepare to claim, if successful, mark claiming in progress */ - spin_lock(&bdev_lock); - err = bd_prepare_to_claim(bdev, whole, holder); - if (err == 0) { - whole->bd_claiming = holder; - spin_unlock(&bdev_lock); - return whole; - } else { - spin_unlock(&bdev_lock); + if (err) { bdput(whole); return ERR_PTR(err); } + + return whole; } EXPORT_SYMBOL(bd_start_claiming); From patchwork Thu Jul 2 08:49:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 11638315 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1CFA914E3 for ; Thu, 2 Jul 2020 08:49:28 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 056162089D for ; Thu, 2 Jul 2020 08:49:28 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b="GKRGdjgj" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726810AbgGBIt1 (ORCPT ); Thu, 2 Jul 2020 04:49:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51068 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726734AbgGBIt1 (ORCPT ); Thu, 2 Jul 2020 04:49:27 -0400 Received: from casper.infradead.org (casper.infradead.org [IPv6:2001:8b0:10b:1236::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 00C0FC08C5C1 for ; Thu, 2 Jul 2020 01:49:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To: Content-Type:Content-ID:Content-Description; bh=4Iz3kyrsqepii29Qm0LnEjOG9fd7tYe4JKIIweGOp1w=; b=GKRGdjgjAryYqzZ4LhVzinVSlc Zx+3cWIxAbnBWiici0qGuS3cRs1r39r6ECP4c/GJv9YbHdTtZU/GWCiEQ/xdUeawungwcn2sfnGKZ WDKLu8yOKQZ39y+I/WKtkDn91A/dq8cDzi8JvkRtE7aNHJeZLPM7dPERjLZFZD6iwKuYKRGQDAJr7 1wSDxKgeHbubYC0VyjEMZeAy2mg5+RhIQxSVmdAHCRe3ML29U8A/FLZh8XJBV7mLVFN8lVcUHM81V 1YAO1y8u9lwdDq5OGBvFzB0/ooVx7eMMWR0rIzfR24G3DXzryWGhxi2krJ2HbAN8R7OF/8Q0jn9bK bxUiOLIg==; Received: from [213.208.157.36] (helo=localhost) by casper.infradead.org with esmtpsa (Exim 4.92.3 #3 (Red Hat Linux)) id 1jquuK-0001Vg-PU; Thu, 02 Jul 2020 08:49:25 +0000 From: Christoph Hellwig To: Jens Axboe Cc: Tejun Heo , linux-block@vger.kernel.org Subject: [PATCH 3/4] block: use bd_prepare_to_claim directly in the loop driver Date: Thu, 2 Jul 2020 10:49:18 +0200 Message-Id: <20200702084919.3720275-4-hch@lst.de> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200702084919.3720275-1-hch@lst.de> References: <20200702084919.3720275-1-hch@lst.de> MIME-Version: 1.0 X-SRS-Rewrite: SMTP reverse-path rewritten from by casper.infradead.org. See http://www.infradead.org/rpr.html Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org The arcane magic in bd_start_claiming is only needed to be able to claim a block_device that hasn't been fully set up. Switch the loop driver that claims from the ioctl path with a fully set up struct block_device to just use the much simpler bd_prepare_to_claim directly. Signed-off-by: Christoph Hellwig --- drivers/block/loop.c | 7 +++---- fs/block_dev.c | 9 +++++---- include/linux/blkdev.h | 3 ++- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index a943207705ddf1..d181601462260b 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1090,11 +1090,10 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, * here to avoid changing device under exclusive owner. */ if (!(mode & FMODE_EXCL)) { - claimed_bdev = bd_start_claiming(bdev, loop_configure); - if (IS_ERR(claimed_bdev)) { - error = PTR_ERR(claimed_bdev); + claimed_bdev = bdev->bd_contains; + error = bd_prepare_to_claim(bdev, claimed_bdev, loop_configure); + if (error) goto out_putf; - } } error = mutex_lock_killable(&loop_ctl_mutex); diff --git a/fs/block_dev.c b/fs/block_dev.c index 1c9da1f08011b0..7075004d36997b 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1027,8 +1027,8 @@ static bool bd_may_claim(struct block_device *bdev, struct block_device *whole, * RETURNS: * 0 if @bdev can be claimed, -EBUSY otherwise. */ -static int bd_prepare_to_claim(struct block_device *bdev, - struct block_device *whole, void *holder) +int bd_prepare_to_claim(struct block_device *bdev, struct block_device *whole, + void *holder) { retry: spin_lock(&bdev_lock); @@ -1055,6 +1055,7 @@ static int bd_prepare_to_claim(struct block_device *bdev, spin_unlock(&bdev_lock); return 0; } +EXPORT_SYMBOL_GPL(bd_prepare_to_claim); /* only for the loop driver */ static struct gendisk *bdev_get_gendisk(struct block_device *bdev, int *partno) { @@ -1100,7 +1101,8 @@ static struct gendisk *bdev_get_gendisk(struct block_device *bdev, int *partno) * Pointer to the block device containing @bdev on success, ERR_PTR() * value on failure. */ -struct block_device *bd_start_claiming(struct block_device *bdev, void *holder) +static struct block_device *bd_start_claiming(struct block_device *bdev, + void *holder) { struct gendisk *disk; struct block_device *whole; @@ -1141,7 +1143,6 @@ struct block_device *bd_start_claiming(struct block_device *bdev, void *holder) return whole; } -EXPORT_SYMBOL(bd_start_claiming); static void bd_clear_claiming(struct block_device *whole, void *holder) { diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 408eb66a82fdc7..6489a0c478165b 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1921,7 +1921,8 @@ int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder); struct block_device *blkdev_get_by_path(const char *path, fmode_t mode, void *holder); struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder); -struct block_device *bd_start_claiming(struct block_device *bdev, void *holder); +int bd_prepare_to_claim(struct block_device *bdev, struct block_device *whole, + void *holder); void bd_abort_claiming(struct block_device *bdev, struct block_device *whole, void *holder); void blkdev_put(struct block_device *bdev, fmode_t mode); From patchwork Thu Jul 2 08:49:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 11638317 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id BAC976C1 for ; Thu, 2 Jul 2020 08:49:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9D51F20899 for ; Thu, 2 Jul 2020 08:49:29 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b="gtb/PEgm" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726734AbgGBIt3 (ORCPT ); Thu, 2 Jul 2020 04:49:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51076 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725263AbgGBIt2 (ORCPT ); Thu, 2 Jul 2020 04:49:28 -0400 Received: from casper.infradead.org (casper.infradead.org [IPv6:2001:8b0:10b:1236::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9C05AC08C5C1 for ; Thu, 2 Jul 2020 01:49:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To: Content-Type:Content-ID:Content-Description; bh=f3DHxMMy6/nMa2BH8zbmQwyeGcm+NETqoF9rsJb21rg=; b=gtb/PEgmwE+yTuG+TGZ2ZdH3x/ VdF6Vjr3FWHhFEgVRQ1jdToS3BMxtlpRIvpJclFx2mYOl2lOco7c5uxxShTjiGRUUf7L9wQY9zRcp UEXER1Cg0bR6W+GV4PyU6vQDV6NUPg514pf++BER4mMt/m1pC9C19ngHslXWMOwgVjSj3VQGT56Ri N4HY+nNCToeENYlmm5f4CzxL+g5WyqeUBcuJ3V0yyX4RswNNiyEfEpjRPBxCNfYggPvr+65byPFh9 pHIieIdI7qS74nGWO0jIAOMvVkt35FlX/0oWxf5he+a8ssP0Uqyu5dXmM+36IKd3fEvs5p4tMD/q7 peR8Twsg==; Received: from [213.208.157.36] (helo=localhost) by casper.infradead.org with esmtpsa (Exim 4.92.3 #3 (Red Hat Linux)) id 1jquuL-0001Vs-VQ; Thu, 02 Jul 2020 08:49:26 +0000 From: Christoph Hellwig To: Jens Axboe Cc: Tejun Heo , linux-block@vger.kernel.org Subject: [PATCH 4/4] block: integrate bd_start_claiming into __blkdev_get Date: Thu, 2 Jul 2020 10:49:19 +0200 Message-Id: <20200702084919.3720275-5-hch@lst.de> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200702084919.3720275-1-hch@lst.de> References: <20200702084919.3720275-1-hch@lst.de> MIME-Version: 1.0 X-SRS-Rewrite: SMTP reverse-path rewritten from by casper.infradead.org. See http://www.infradead.org/rpr.html Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org bd_start_claiming duplicates a lot of the work done in __blkdev_get. Integrate the two functions to avoid the duplicate work, and to do the right thing for the md -ERESTARTSYS corner case. Signed-off-by: Christoph Hellwig --- fs/block_dev.c | 177 +++++++++++++++---------------------------------- 1 file changed, 55 insertions(+), 122 deletions(-) diff --git a/fs/block_dev.c b/fs/block_dev.c index 7075004d36997b..6fa987c77e0a1b 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1078,72 +1078,6 @@ static struct gendisk *bdev_get_gendisk(struct block_device *bdev, int *partno) return disk; } -/** - * bd_start_claiming - start claiming a block device - * @bdev: block device of interest - * @holder: holder trying to claim @bdev - * - * @bdev is about to be opened exclusively. Check @bdev can be opened - * exclusively and mark that an exclusive open is in progress. Each - * successful call to this function must be matched with a call to - * either bd_finish_claiming() or bd_abort_claiming() (which do not - * fail). - * - * This function is used to gain exclusive access to the block device - * without actually causing other exclusive open attempts to fail. It - * should be used when the open sequence itself requires exclusive - * access but may subsequently fail. - * - * CONTEXT: - * Might sleep. - * - * RETURNS: - * Pointer to the block device containing @bdev on success, ERR_PTR() - * value on failure. - */ -static struct block_device *bd_start_claiming(struct block_device *bdev, - void *holder) -{ - struct gendisk *disk; - struct block_device *whole; - int partno, err; - - might_sleep(); - - /* - * @bdev might not have been initialized properly yet, look up - * and grab the outer block device the hard way. - */ - disk = bdev_get_gendisk(bdev, &partno); - if (!disk) - return ERR_PTR(-ENXIO); - - /* - * Normally, @bdev should equal what's returned from bdget_disk() - * if partno is 0; however, some drivers (floppy) use multiple - * bdev's for the same physical device and @bdev may be one of the - * aliases. Keep @bdev if partno is 0. This means claimer - * tracking is broken for those devices but it has always been that - * way. - */ - if (partno) - whole = bdget_disk(disk, 0); - else - whole = bdgrab(bdev); - - put_disk_and_module(disk); - if (!whole) - return ERR_PTR(-ENOMEM); - - err = bd_prepare_to_claim(bdev, whole, holder); - if (err) { - bdput(whole); - return ERR_PTR(err); - } - - return whole; -} - static void bd_clear_claiming(struct block_device *whole, void *holder) { lockdep_assert_held(&bdev_lock); @@ -1156,7 +1090,7 @@ static void bd_clear_claiming(struct block_device *whole, void *holder) /** * bd_finish_claiming - finish claiming of a block device * @bdev: block device of interest - * @whole: whole block device (returned from bd_start_claiming()) + * @whole: whole block device * @holder: holder that has claimed @bdev * * Finish exclusive open of a block device. Mark the device as exlusively @@ -1182,7 +1116,7 @@ static void bd_finish_claiming(struct block_device *bdev, /** * bd_abort_claiming - abort claiming of a block device * @bdev: block device of interest - * @whole: whole block device (returned from bd_start_claiming()) + * @whole: whole block device * @holder: holder that has claimed @bdev * * Abort claiming of a block device when the exclusive open failed. This can be @@ -1521,13 +1455,15 @@ EXPORT_SYMBOL_GPL(bdev_disk_changed); * mutex_lock_nested(whole->bd_mutex, 1) */ -static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) +static int __blkdev_get(struct block_device *bdev, fmode_t mode, void *holder, + int for_part) { + struct block_device *whole = NULL, *claiming = NULL; struct gendisk *disk; int ret; int partno; int perm = 0; - bool first_open = false, need_restart; + bool first_open = false, unblock_events = true, need_restart; if (mode & FMODE_READ) perm |= MAY_READ; @@ -1549,6 +1485,25 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) if (!disk) goto out; + if (partno) { + whole = bdget_disk(disk, 0); + if (!whole) { + ret = -ENOMEM; + goto out_put_disk; + } + } + + if (!for_part && (mode & FMODE_EXCL)) { + WARN_ON_ONCE(!holder); + if (whole) + claiming = whole; + else + claiming = bdev; + ret = bd_prepare_to_claim(bdev, claiming, holder); + if (ret) + goto out_put_whole; + } + disk_block_events(disk); mutex_lock_nested(&bdev->bd_mutex, for_part); if (!bdev->bd_openers) { @@ -1592,18 +1547,11 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) if (ret) goto out_clear; } else { - struct block_device *whole; - whole = bdget_disk(disk, 0); - ret = -ENOMEM; - if (!whole) - goto out_clear; BUG_ON(for_part); - ret = __blkdev_get(whole, mode, 1); - if (ret) { - bdput(whole); + ret = __blkdev_get(whole, mode, NULL, 1); + if (ret) goto out_clear; - } - bdev->bd_contains = whole; + bdev->bd_contains = bdgrab(whole); bdev->bd_part = disk_get_part(disk, partno); if (!(disk->flags & GENHD_FL_UP) || !bdev->bd_part || !bdev->bd_part->nr_sects) { @@ -1632,11 +1580,30 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) bdev->bd_openers++; if (for_part) bdev->bd_part_count++; + if (claiming) + bd_finish_claiming(bdev, claiming, holder); + + /* + * Block event polling for write claims if requested. Any write holder + * makes the write_holder state stick until all are released. This is + * good enough and tracking individual writeable reference is too + * fragile given the way @mode is used in blkdev_get/put(). + */ + if (claiming && (mode & FMODE_WRITE) && !bdev->bd_write_holder && + (disk->flags & GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE)) { + bdev->bd_write_holder = true; + unblock_events = false; + } mutex_unlock(&bdev->bd_mutex); - disk_unblock_events(disk); + + if (unblock_events) + disk_unblock_events(disk); + /* only one opener holds refs to the module and disk */ if (!first_open) put_disk_and_module(disk); + if (whole) + bdput(whole); return 0; out_clear: @@ -1647,13 +1614,18 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) __blkdev_put(bdev->bd_contains, mode, 1); bdev->bd_contains = NULL; out_unlock_bdev: + if (claiming) + bd_abort_claiming(bdev, claiming, holder); mutex_unlock(&bdev->bd_mutex); disk_unblock_events(disk); + out_put_whole: + if (whole) + bdput(whole); + out_put_disk: put_disk_and_module(disk); if (need_restart) goto restart; out: - return ret; } @@ -1678,50 +1650,11 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) */ int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder) { - struct block_device *whole = NULL; int res; - WARN_ON_ONCE((mode & FMODE_EXCL) && !holder); - - if ((mode & FMODE_EXCL) && holder) { - whole = bd_start_claiming(bdev, holder); - if (IS_ERR(whole)) { - bdput(bdev); - return PTR_ERR(whole); - } - } - - res = __blkdev_get(bdev, mode, 0); - - if (whole) { - struct gendisk *disk = whole->bd_disk; - - /* finish claiming */ - mutex_lock(&bdev->bd_mutex); - if (!res) - bd_finish_claiming(bdev, whole, holder); - else - bd_abort_claiming(bdev, whole, holder); - /* - * Block event polling for write claims if requested. Any - * write holder makes the write_holder state stick until - * all are released. This is good enough and tracking - * individual writeable reference is too fragile given the - * way @mode is used in blkdev_get/put(). - */ - if (!res && (mode & FMODE_WRITE) && !bdev->bd_write_holder && - (disk->flags & GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE)) { - bdev->bd_write_holder = true; - disk_block_events(disk); - } - - mutex_unlock(&bdev->bd_mutex); - bdput(whole); - } - + res =__blkdev_get(bdev, mode, holder, 0); if (res) bdput(bdev); - return res; } EXPORT_SYMBOL(blkdev_get);