DM-Devel Archive on lore.kernel.org
 help / color / Atom feed
From: Christoph Hellwig <hch@lst.de>
To: Jens Axboe <axboe@kernel.dk>
Cc: linux-bcache@vger.kernel.org, Jan Kara <jack@suse.cz>,
	Mike Snitzer <snitzer@redhat.com>,
	linux-mm@kvack.org,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Jan Kara <jack@suse.com>, Josef Bacik <josef@toxicpanda.com>,
	Coly Li <colyli@suse.de>,
	linux-block@vger.kernel.org, linux-fsdevel@vger.kernel.org,
	dm-devel@redhat.com, linux-mtd@lists.infradead.org,
	Johannes Thumshirn <johannes.thumshirn@wdc.com>,
	Tejun Heo <tj@kernel.org>
Subject: [dm-devel] [PATCH 21/45] block: refactor blkdev_get
Date: Sat, 28 Nov 2020 17:14:46 +0100
Message-ID: <20201128161510.347752-22-hch@lst.de> (raw)
In-Reply-To: <20201128161510.347752-1-hch@lst.de>

Move more code that is only run on the outer open but not the open of
the underlying whole device when opening a partition into blkdev_get,
which leads to a much easier to follow structure.

This allows to simplify the disk and module refcounting so that one
reference is held for each open, similar to what we do with normal
file operations.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Acked-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
---
 fs/block_dev.c | 185 +++++++++++++++++++++++--------------------------
 1 file changed, 86 insertions(+), 99 deletions(-)

diff --git a/fs/block_dev.c b/fs/block_dev.c
index 6016777b648336..0c533ac92e2492 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1407,46 +1407,12 @@ EXPORT_SYMBOL_GPL(bdev_disk_changed);
  *  mutex_lock(part->bd_mutex)
  *    mutex_lock_nested(whole->bd_mutex, 1)
  */
-
-static int __blkdev_get(struct block_device *bdev, fmode_t mode, void *holder,
-		int for_part)
+static int __blkdev_get(struct block_device *bdev, struct gendisk *disk,
+		int partno, fmode_t mode)
 {
-	struct block_device *whole = NULL, *claiming = NULL;
-	struct gendisk *disk;
 	int ret;
-	int partno;
-	bool first_open = false, unblock_events = true, need_restart;
-
- restart:
-	need_restart = false;
-	ret = -ENXIO;
-	disk = bdev_get_gendisk(bdev, &partno);
-	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) {
-		first_open = true;
 		bdev->bd_disk = disk;
 		bdev->bd_contains = bdev;
 		bdev->bd_partno = partno;
@@ -1458,15 +1424,8 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, void *holder,
 				goto out_clear;
 
 			ret = 0;
-			if (disk->fops->open) {
+			if (disk->fops->open)
 				ret = disk->fops->open(bdev, mode);
-				/*
-				 * If we lost a race with 'disk' being deleted,
-				 * try again.  See md.c
-				 */
-				if (ret == -ERESTARTSYS)
-					need_restart = true;
-			}
 
 			if (!ret) {
 				bd_set_nr_sectors(bdev, get_capacity(disk));
@@ -1486,14 +1445,23 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, void *holder,
 			if (ret)
 				goto out_clear;
 		} else {
-			BUG_ON(for_part);
-			ret = __blkdev_get(whole, mode, NULL, 1);
-			if (ret)
+			struct block_device *whole = bdget_disk(disk, 0);
+
+			mutex_lock_nested(&whole->bd_mutex, 1);
+			ret = __blkdev_get(whole, disk, 0, mode);
+			if (ret) {
+				mutex_unlock(&whole->bd_mutex);
+				bdput(whole);
 				goto out_clear;
-			bdev->bd_contains = bdgrab(whole);
+			}
+			whole->bd_part_count++;
+			mutex_unlock(&whole->bd_mutex);
+
+			bdev->bd_contains = whole;
 			bdev->bd_part = disk_get_part(disk, partno);
 			if (!(disk->flags & GENHD_FL_UP) ||
 			    !bdev->bd_part || !bdev->bd_part->nr_sects) {
+				__blkdev_put(whole, mode, 1);
 				ret = -ENXIO;
 				goto out_clear;
 			}
@@ -1513,58 +1481,17 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, void *holder,
 			    (!ret || ret == -ENOMEDIUM))
 				bdev_disk_changed(bdev, ret == -ENOMEDIUM);
 			if (ret)
-				goto out_unlock_bdev;
+				return ret;
 		}
 	}
 	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);
-
-	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:
 	disk_put_part(bdev->bd_part);
 	bdev->bd_disk = NULL;
 	bdev->bd_part = NULL;
-	if (bdev != bdev->bd_contains)
-		__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;
 }
 
@@ -1589,7 +1516,12 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, void *holder,
  */
 static int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder)
 {
-	int ret, perm = 0;
+	struct block_device *claiming;
+	bool unblock_events = true;
+	struct gendisk *disk;
+	int perm = 0;
+	int partno;
+	int ret;
 
 	if (mode & FMODE_READ)
 		perm |= MAY_READ;
@@ -1599,13 +1531,67 @@ static int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder)
 	if (ret)
 		goto bdput;
 
-	ret =__blkdev_get(bdev, mode, holder, 0);
-	if (ret)
+	/*
+	 * If we lost a race with 'disk' being deleted, try again.  See md.c.
+	 */
+retry:
+	ret = -ENXIO;
+	disk = bdev_get_gendisk(bdev, &partno);
+	if (!disk)
 		goto bdput;
-	return 0;
 
+	if (mode & FMODE_EXCL) {
+		WARN_ON_ONCE(!holder);
+	
+		ret = -ENOMEM;
+		claiming = bdget_disk(disk, 0);
+		if (!claiming)
+			goto put_disk;
+		ret = bd_prepare_to_claim(bdev, claiming, holder);
+		if (ret)
+			goto put_claiming;
+	}
+
+	disk_block_events(disk);
+
+	mutex_lock(&bdev->bd_mutex);
+	ret =__blkdev_get(bdev, disk, partno, mode);
+	if (!(mode & FMODE_EXCL)) {
+		; /* nothing to do here */
+	} else if (ret) {
+		bd_abort_claiming(bdev, claiming, holder);
+	} else {
+		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 ((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);
+
+	if (unblock_events)
+		disk_unblock_events(disk);
+
+put_claiming:
+	if (mode & FMODE_EXCL)
+		bdput(claiming);
+put_disk:
+	if (ret)
+		put_disk_and_module(disk);
+	if (ret == -ERESTARTSYS)
+		goto retry;
 bdput:
-	bdput(bdev);
+	if (ret)
+		bdput(bdev);
 	return ret;
 }
 
@@ -1753,8 +1739,6 @@ static void __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)
 		if (bdev_is_partition(bdev))
 			victim = bdev->bd_contains;
 		bdev->bd_contains = NULL;
-
-		put_disk_and_module(disk);
 	} else {
 		if (!bdev_is_partition(bdev) && disk->fops->release)
 			disk->fops->release(disk, mode);
@@ -1767,6 +1751,8 @@ static void __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)
 
 void blkdev_put(struct block_device *bdev, fmode_t mode)
 {
+	struct gendisk *disk = bdev->bd_disk;
+
 	mutex_lock(&bdev->bd_mutex);
 
 	if (mode & FMODE_EXCL) {
@@ -1795,7 +1781,7 @@ void blkdev_put(struct block_device *bdev, fmode_t mode)
 		 * unblock evpoll if it was a write holder.
 		 */
 		if (bdev_free && bdev->bd_write_holder) {
-			disk_unblock_events(bdev->bd_disk);
+			disk_unblock_events(disk);
 			bdev->bd_write_holder = false;
 		}
 	}
@@ -1805,11 +1791,12 @@ void blkdev_put(struct block_device *bdev, fmode_t mode)
 	 * event.  This is to ensure detection of media removal commanded
 	 * from userland - e.g. eject(1).
 	 */
-	disk_flush_events(bdev->bd_disk, DISK_EVENT_MEDIA_CHANGE);
+	disk_flush_events(disk, DISK_EVENT_MEDIA_CHANGE);
 
 	mutex_unlock(&bdev->bd_mutex);
 
 	__blkdev_put(bdev, mode, 0);
+	put_disk_and_module(disk);
 }
 EXPORT_SYMBOL(blkdev_put);
 
-- 
2.29.2

--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel


  parent reply index

Thread overview: 100+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-11-28 16:14 [dm-devel] merge struct block_device and struct hd_struct v4 Christoph Hellwig
2020-11-28 16:14 ` [dm-devel] [PATCH 01/45] blk-cgroup: fix a hd_struct leak in blkcg_fill_root_iostats Christoph Hellwig
2020-11-28 16:14 ` [dm-devel] [PATCH 02/45] filemap: consistently use ->f_mapping over ->i_mapping Christoph Hellwig
2020-11-30  9:20   ` Johannes Thumshirn
2020-11-28 16:14 ` [dm-devel] [PATCH 03/45] fs: remove get_super_thawed and get_super_exclusive_thawed Christoph Hellwig
2020-11-28 16:14 ` [dm-devel] [PATCH 04/45] fs: simplify freeze_bdev/thaw_bdev Christoph Hellwig
2020-11-30 17:55   ` Darrick J. Wong
2020-11-28 16:14 ` [dm-devel] [PATCH 05/45] mtip32xx: remove the call to fsync_bdev on removal Christoph Hellwig
2020-11-30  7:07   ` Hannes Reinecke
2020-11-30 14:48   ` Johannes Thumshirn
2020-11-28 16:14 ` [dm-devel] [PATCH 06/45] zram: do not call set_blocksize Christoph Hellwig
2020-11-28 16:14 ` [dm-devel] [PATCH 07/45] loop: " Christoph Hellwig
2020-11-30  7:07   ` Hannes Reinecke
2020-11-30 11:26   ` Johannes Thumshirn
2020-11-28 16:14 ` [dm-devel] [PATCH 08/45] dm: simplify flush_bio initialization in __send_empty_flush Christoph Hellwig
2020-11-30  7:08   ` Hannes Reinecke
2020-11-28 16:14 ` [dm-devel] [PATCH 09/45] dm: remove the block_device reference in struct mapped_device Christoph Hellwig
2020-11-28 16:14 ` [dm-devel] [PATCH 10/45] block: remove a duplicate __disk_get_part prototype Christoph Hellwig
2020-11-28 16:14 ` [dm-devel] [PATCH 11/45] block: remove a superflous check in blkpg_do_ioctl Christoph Hellwig
2020-11-30  9:20   ` Johannes Thumshirn
2020-11-28 16:14 ` [dm-devel] [PATCH 12/45] block: add a bdev_kobj helper Christoph Hellwig
2020-11-28 16:14 ` [dm-devel] [PATCH 13/45] block: use disk_part_iter_exit in disk_part_iter_next Christoph Hellwig
2020-11-28 16:14 ` [dm-devel] [PATCH 14/45] block: use put_device in put_disk Christoph Hellwig
2020-11-30  7:09   ` Hannes Reinecke
2020-11-28 16:14 ` [dm-devel] [PATCH 15/45] block: change the hash used for looking up block devices Christoph Hellwig
2020-11-30  7:10   ` Hannes Reinecke
2020-11-28 16:14 ` [dm-devel] [PATCH 16/45] block: switch bdgrab to use igrab Christoph Hellwig
2020-11-30  7:14   ` Hannes Reinecke
2020-11-30  9:09   ` Jan Kara
2020-11-30 14:52   ` Johannes Thumshirn
2020-11-28 16:14 ` [dm-devel] [PATCH 17/45] init: refactor name_to_dev_t Christoph Hellwig
2020-11-30  7:15   ` Hannes Reinecke
2020-11-28 16:14 ` [dm-devel] [PATCH 18/45] init: refactor devt_from_partuuid Christoph Hellwig
2020-11-30  7:16   ` Hannes Reinecke
2020-11-28 16:14 ` [dm-devel] [PATCH 19/45] init: cleanup match_dev_by_uuid and match_dev_by_label Christoph Hellwig
2020-11-30  7:17   ` Hannes Reinecke
2020-11-28 16:14 ` [dm-devel] [PATCH 20/45] block: refactor __blkdev_put Christoph Hellwig
2020-11-30  7:17   ` Hannes Reinecke
2020-11-28 16:14 ` Christoph Hellwig [this message]
2020-11-30  7:28   ` [dm-devel] [PATCH 21/45] block: refactor blkdev_get Hannes Reinecke
2020-11-28 16:14 ` [dm-devel] [PATCH 22/45] block: move bdput() to the callers of __blkdev_get Christoph Hellwig
2020-11-30  7:29   ` Hannes Reinecke
2020-11-28 16:14 ` [dm-devel] [PATCH 23/45] block: opencode devcgroup_inode_permission Christoph Hellwig
2020-11-30  7:30   ` Hannes Reinecke
2020-11-28 16:14 ` [dm-devel] [PATCH 24/45] block: remove i_bdev Christoph Hellwig
2020-11-30  7:31   ` Hannes Reinecke
2020-11-28 16:14 ` [dm-devel] [PATCH 25/45] block: simplify bdev/disk lookup in blkdev_get Christoph Hellwig
2020-11-30  7:36   ` Hannes Reinecke
2020-11-30  9:24   ` Jan Kara
2020-12-02 21:52   ` Tejun Heo
2020-11-28 16:14 ` [dm-devel] [PATCH 26/45] block: remove ->bd_contains Christoph Hellwig
2020-11-30  7:37   ` Hannes Reinecke
2020-11-28 16:14 ` [dm-devel] [PATCH 27/45] block: simplify the block device claiming interface Christoph Hellwig
2020-11-30  7:37   ` Hannes Reinecke
2020-11-28 16:14 ` [dm-devel] [PATCH 28/45] block: simplify part_to_disk Christoph Hellwig
2020-11-30  7:38   ` Hannes Reinecke
2020-11-28 16:14 ` [dm-devel] [PATCH 29/45] block: initialize struct block_device in bdev_alloc Christoph Hellwig
2020-11-30  7:38   ` Hannes Reinecke
2020-11-28 16:14 ` [dm-devel] [PATCH 30/45] block: remove the nr_sects field in struct hd_struct Christoph Hellwig
2020-11-30  7:39   ` Hannes Reinecke
2020-11-30  9:44   ` Jan Kara
2020-11-30 14:51     ` Christoph Hellwig
2020-11-30 15:17       ` Jan Kara
2020-11-28 16:14 ` [dm-devel] [PATCH 31/45] block: move disk stat accounting to struct block_device Christoph Hellwig
2020-11-30  7:40   ` Hannes Reinecke
2020-11-28 16:14 ` [dm-devel] [PATCH 32/45] block: move the start_sect field " Christoph Hellwig
2020-11-30  7:41   ` Hannes Reinecke
2020-11-28 16:14 ` [dm-devel] [PATCH 33/45] block: move the partition_meta_info " Christoph Hellwig
2020-11-30  7:41   ` Hannes Reinecke
2020-11-28 16:14 ` [dm-devel] [PATCH 34/45] block: move holder_dir " Christoph Hellwig
2020-11-30  7:42   ` Hannes Reinecke
2020-11-28 16:15 ` [dm-devel] [PATCH 35/45] block: move make_it_fail " Christoph Hellwig
2020-11-30  7:43   ` Hannes Reinecke
2020-11-28 16:15 ` [dm-devel] [PATCH 36/45] block: move the policy field " Christoph Hellwig
2020-11-30  7:44   ` Hannes Reinecke
2020-11-28 16:15 ` [dm-devel] [PATCH 37/45] block: allocate struct hd_struct as part of struct bdev_inode Christoph Hellwig
2020-11-30  7:46   ` Hannes Reinecke
2020-11-30  9:53   ` Jan Kara
2020-11-28 16:15 ` [dm-devel] [PATCH 38/45] block: switch partition lookup to use struct block_device Christoph Hellwig
2020-11-30  7:47   ` Hannes Reinecke
2020-11-28 16:15 ` [dm-devel] [PATCH 39/45] block: remove the partno field from struct hd_struct Christoph Hellwig
2020-11-30  7:47   ` Hannes Reinecke
2020-11-28 16:15 ` [dm-devel] [PATCH 40/45] block: pass a block_device to blk_alloc_devt Christoph Hellwig
2020-11-30  7:48   ` Hannes Reinecke
2020-11-28 16:15 ` [dm-devel] [PATCH 41/45] block: pass a block_device to invalidate_partition Christoph Hellwig
2020-11-30  7:49   ` Hannes Reinecke
2020-11-28 16:15 ` [dm-devel] [PATCH 42/45] block: switch disk_part_iter_* to use a struct block_device Christoph Hellwig
2020-11-30  7:50   ` Hannes Reinecke
2020-11-30 10:20   ` Jan Kara
2020-11-28 16:15 ` [dm-devel] [PATCH 43/45] f2fs: remove a few bd_part checks Christoph Hellwig
2020-11-30  7:50   ` Hannes Reinecke
2020-11-28 16:15 ` [dm-devel] [PATCH 44/45] block: merge struct block_device and struct hd_struct Christoph Hellwig
2020-11-30  7:51   ` Hannes Reinecke
2020-11-30 10:29   ` Jan Kara
2020-11-28 16:15 ` [dm-devel] [PATCH 45/45] block: stop using bdget_disk for partition 0 Christoph Hellwig
2020-11-30  7:51   ` Hannes Reinecke
2020-11-30 17:19 ` [dm-devel] merge struct block_device and struct hd_struct v4 Christoph Hellwig
2020-11-30 17:51   ` Jens Axboe
  -- strict thread matches above, loose matches on Subject: below --
2020-11-24 13:27 [dm-devel] merge struct block_device and struct hd_struct v2 Christoph Hellwig
2020-11-24 13:27 ` [dm-devel] [PATCH 21/45] block: refactor blkdev_get Christoph Hellwig
2020-11-24 18:03   ` Tejun Heo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201128161510.347752-22-hch@lst.de \
    --to=hch@lst.de \
    --cc=axboe@kernel.dk \
    --cc=colyli@suse.de \
    --cc=dm-devel@redhat.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=jack@suse.com \
    --cc=jack@suse.cz \
    --cc=johannes.thumshirn@wdc.com \
    --cc=josef@toxicpanda.com \
    --cc=linux-bcache@vger.kernel.org \
    --cc=linux-block@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=linux-mtd@lists.infradead.org \
    --cc=snitzer@redhat.com \
    --cc=tj@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

DM-Devel Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/dm-devel/0 dm-devel/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 dm-devel dm-devel/ https://lore.kernel.org/dm-devel \
		dm-devel@redhat.com
	public-inbox-index dm-devel

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/com.redhat.dm-devel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git