Skip to content

Commit 59a55a6

Browse files
committed
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: f3a6088 ("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>
1 parent b74c02a commit 59a55a6

File tree

3 files changed

+35
-0
lines changed

3 files changed

+35
-0
lines changed

block/bdev.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,9 @@ static void bd_finish_claiming(struct block_device *bdev, void *holder,
583583
mutex_unlock(&bdev->bd_holder_lock);
584584
bd_clear_claiming(whole, holder);
585585
mutex_unlock(&bdev_lock);
586+
587+
if (hops && hops->get_holder)
588+
hops->get_holder(holder);
586589
}
587590

588591
/**
@@ -605,6 +608,7 @@ EXPORT_SYMBOL(bd_abort_claiming);
605608
static void bd_end_claim(struct block_device *bdev, void *holder)
606609
{
607610
struct block_device *whole = bdev_whole(bdev);
611+
const struct blk_holder_ops *hops = bdev->bd_holder_ops;
608612
bool unblock = false;
609613

610614
/*
@@ -627,6 +631,9 @@ static void bd_end_claim(struct block_device *bdev, void *holder)
627631
whole->bd_holder = NULL;
628632
mutex_unlock(&bdev_lock);
629633

634+
if (hops && hops->put_holder)
635+
hops->put_holder(holder);
636+
630637
/*
631638
* If this was the last claim, remove holder link and unblock evpoll if
632639
* it was a write holder.

fs/super.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1515,11 +1515,29 @@ static int fs_bdev_thaw(struct block_device *bdev)
15151515
return error;
15161516
}
15171517

1518+
static void fs_bdev_super_get(void *data)
1519+
{
1520+
struct super_block *sb = data;
1521+
1522+
spin_lock(&sb_lock);
1523+
sb->s_count++;
1524+
spin_unlock(&sb_lock);
1525+
}
1526+
1527+
static void fs_bdev_super_put(void *data)
1528+
{
1529+
struct super_block *sb = data;
1530+
1531+
put_super(sb);
1532+
}
1533+
15181534
const struct blk_holder_ops fs_holder_ops = {
15191535
.mark_dead = fs_bdev_mark_dead,
15201536
.sync = fs_bdev_sync,
15211537
.freeze = fs_bdev_freeze,
15221538
.thaw = fs_bdev_thaw,
1539+
.get_holder = fs_bdev_super_get,
1540+
.put_holder = fs_bdev_super_put,
15231541
};
15241542
EXPORT_SYMBOL_GPL(fs_holder_ops);
15251543

include/linux/blkdev.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1505,6 +1505,16 @@ struct blk_holder_ops {
15051505
* Thaw the file system mounted on the block device.
15061506
*/
15071507
int (*thaw)(struct block_device *bdev);
1508+
1509+
/*
1510+
* If needed, get a reference to the holder.
1511+
*/
1512+
void (*get_holder)(void *holder);
1513+
1514+
/*
1515+
* Release the holder.
1516+
*/
1517+
void (*put_holder)(void *holder);
15081518
};
15091519

15101520
/*

0 commit comments

Comments
 (0)