summaryrefslogtreecommitdiff
path: root/block
diff options
context:
space:
mode:
authorChristian Brauner <brauner@kernel.org>2024-03-14 15:24:13 +0100
committerChristian Brauner <brauner@kernel.org>2024-03-18 10:32:44 +0100
commit59a55a63c24624c7ad268f12c8f82d142ef6a6d4 (patch)
tree95f2bb37ccdb6db29f06645c68946f3f2c7d4c8c /block
parentb74c02a37987d3ea755f96119c527f5e91950592 (diff)
fs,block: get holder during claim
Now that we open block devices as files we need to deal with the realities that closing is a deferred operation. An operation on the block device such as e.g., freeze, thaw, or removal that runs concurrently with umount, tries to acquire a stable reference on the holder. The holder might already be gone though. Make that reliable by grabbing a passive reference to the holder during bdev_open() and releasing it during bdev_release(). Fixes: f3a608827d1f ("bdev: open block device as files") # mainline only Reported-by: Christoph Hellwig <hch@infradead.org> Link: https://lore.kernel.org/r/ZfEQQ9jZZVes0WCZ@infradead.org Reviewed-by: Jan Kara <jack@suse.cz> Reviewed-by: Christoph Hellwig <hch@infradead.org> Tested-by: Yi Zhang <yi.zhang@redhat.com> Reported-by: https://lore.kernel.org/r/CAHj4cs8tbDwKRwfS1=DmooP73ysM__xAb2PQc6XsAmWR+VuYmg@mail.gmail.com Link: https://lore.kernel.org/r/20240315-freibad-annehmbar-ca68c375af91@brauner Signed-off-by: Christian Brauner <brauner@kernel.org>
Diffstat (limited to 'block')
-rw-r--r--block/bdev.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/block/bdev.c b/block/bdev.c
index e7adaaf1c219..7a5f611c3d2e 100644
--- a/block/bdev.c
+++ b/block/bdev.c
@@ -583,6 +583,9 @@ static void bd_finish_claiming(struct block_device *bdev, void *holder,
mutex_unlock(&bdev->bd_holder_lock);
bd_clear_claiming(whole, holder);
mutex_unlock(&bdev_lock);
+
+ if (hops && hops->get_holder)
+ hops->get_holder(holder);
}
/**
@@ -605,6 +608,7 @@ EXPORT_SYMBOL(bd_abort_claiming);
static void bd_end_claim(struct block_device *bdev, void *holder)
{
struct block_device *whole = bdev_whole(bdev);
+ const struct blk_holder_ops *hops = bdev->bd_holder_ops;
bool unblock = false;
/*
@@ -627,6 +631,9 @@ static void bd_end_claim(struct block_device *bdev, void *holder)
whole->bd_holder = NULL;
mutex_unlock(&bdev_lock);
+ if (hops && hops->put_holder)
+ hops->put_holder(holder);
+
/*
* If this was the last claim, remove holder link and unblock evpoll if
* it was a write holder.