Skip to content

Commit d8530de

Browse files
Christoph Hellwigbrauner
authored andcommitted
block: call into the file system for bdev_mark_dead
Combine the newly merged bdev_mark_dead helper with the existing mark_dead holder operation so that all operations that invalidate a device that is dead or being removed now go through the holder ops. This allows file systems to explicitly shutdown either ASAP (for a surprise removal) or after writing back data (for an orderly removal), and do so not only for the main device. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Josef Bacik <josef@toxicpanda.com> Message-Id: <20230811100828.1897174-15-hch@lst.de> Signed-off-by: Christian Brauner <brauner@kernel.org>
1 parent 560e20e commit d8530de

4 files changed

Lines changed: 40 additions & 44 deletions

File tree

block/bdev.c

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -968,31 +968,19 @@ EXPORT_SYMBOL(lookup_bdev);
968968
* to %true the device or media is already gone, if not we are preparing for an
969969
* orderly removal.
970970
*
971-
* This syncs out all dirty data and writes back inodes and then invalidates any
972-
* cached data in the inodes on the file system, the inodes themselves and the
973-
* block device mapping.
971+
* This calls into the file system, which then typicall syncs out all dirty data
972+
* and writes back inodes and then invalidates any cached data in the inodes on
973+
* the file system. In addition we also invalidate the block device mapping.
974974
*/
975975
void bdev_mark_dead(struct block_device *bdev, bool surprise)
976976
{
977-
struct super_block *sb = get_super(bdev);
978-
int res = 0;
977+
mutex_lock(&bdev->bd_holder_lock);
978+
if (bdev->bd_holder_ops && bdev->bd_holder_ops->mark_dead)
979+
bdev->bd_holder_ops->mark_dead(bdev, surprise);
980+
else
981+
sync_blockdev(bdev);
982+
mutex_unlock(&bdev->bd_holder_lock);
979983

980-
if (sb) {
981-
if (!surprise)
982-
sync_filesystem(sb);
983-
/*
984-
* no need to lock the super, get_super holds the
985-
* read mutex so the filesystem cannot go away
986-
* under us (->put_super runs with the write lock
987-
* hold).
988-
*/
989-
shrink_dcache_sb(sb);
990-
res = invalidate_inodes(sb, true);
991-
drop_super(sb);
992-
} else {
993-
if (!surprise)
994-
sync_blockdev(bdev);
995-
}
996984
invalidate_bdev(bdev);
997985
}
998986
#ifdef CONFIG_DASD_MODULE

block/genhd.c

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,7 @@ int __must_check device_add_disk(struct device *parent, struct gendisk *disk,
554554
}
555555
EXPORT_SYMBOL(device_add_disk);
556556

557-
static void blk_report_disk_dead(struct gendisk *disk)
557+
static void blk_report_disk_dead(struct gendisk *disk, bool surprise)
558558
{
559559
struct block_device *bdev;
560560
unsigned long idx;
@@ -565,25 +565,15 @@ static void blk_report_disk_dead(struct gendisk *disk)
565565
continue;
566566
rcu_read_unlock();
567567

568-
mutex_lock(&bdev->bd_holder_lock);
569-
if (bdev->bd_holder_ops && bdev->bd_holder_ops->mark_dead)
570-
bdev->bd_holder_ops->mark_dead(bdev);
571-
mutex_unlock(&bdev->bd_holder_lock);
568+
bdev_mark_dead(bdev, surprise);
572569

573570
put_device(&bdev->bd_device);
574571
rcu_read_lock();
575572
}
576573
rcu_read_unlock();
577574
}
578575

579-
/**
580-
* blk_mark_disk_dead - mark a disk as dead
581-
* @disk: disk to mark as dead
582-
*
583-
* Mark as disk as dead (e.g. surprise removed) and don't accept any new I/O
584-
* to this disk.
585-
*/
586-
void blk_mark_disk_dead(struct gendisk *disk)
576+
static void __blk_mark_disk_dead(struct gendisk *disk)
587577
{
588578
/*
589579
* Fail any new I/O.
@@ -603,8 +593,19 @@ void blk_mark_disk_dead(struct gendisk *disk)
603593
* Prevent new I/O from crossing bio_queue_enter().
604594
*/
605595
blk_queue_start_drain(disk->queue);
596+
}
606597

607-
blk_report_disk_dead(disk);
598+
/**
599+
* blk_mark_disk_dead - mark a disk as dead
600+
* @disk: disk to mark as dead
601+
*
602+
* Mark as disk as dead (e.g. surprise removed) and don't accept any new I/O
603+
* to this disk.
604+
*/
605+
void blk_mark_disk_dead(struct gendisk *disk)
606+
{
607+
__blk_mark_disk_dead(disk);
608+
blk_report_disk_dead(disk, true);
608609
}
609610
EXPORT_SYMBOL_GPL(blk_mark_disk_dead);
610611

@@ -641,17 +642,20 @@ void del_gendisk(struct gendisk *disk)
641642
disk_del_events(disk);
642643

643644
/*
644-
* Prevent new openers by unlinked the bdev inode, and write out
645-
* dirty data before marking the disk dead and stopping all I/O.
645+
* Prevent new openers by unlinked the bdev inode.
646646
*/
647647
mutex_lock(&disk->open_mutex);
648-
xa_for_each(&disk->part_tbl, idx, part) {
648+
xa_for_each(&disk->part_tbl, idx, part)
649649
remove_inode_hash(part->bd_inode);
650-
bdev_mark_dead(part, false);
651-
}
652650
mutex_unlock(&disk->open_mutex);
653651

654-
blk_mark_disk_dead(disk);
652+
/*
653+
* Tell the file system to write back all dirty data and shut down if
654+
* it hasn't been notified earlier.
655+
*/
656+
if (!test_bit(GD_DEAD, &disk->state))
657+
blk_report_disk_dead(disk, false);
658+
__blk_mark_disk_dead(disk);
655659

656660
/*
657661
* Drop all partitions now that the disk is marked dead.

fs/super.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,7 +1228,7 @@ static bool lock_active_super(struct super_block *sb)
12281228
return true;
12291229
}
12301230

1231-
static void fs_mark_dead(struct block_device *bdev)
1231+
static void fs_bdev_mark_dead(struct block_device *bdev, bool surprise)
12321232
{
12331233
struct super_block *sb = bdev->bd_holder;
12341234

@@ -1238,14 +1238,18 @@ static void fs_mark_dead(struct block_device *bdev)
12381238
if (!lock_active_super(sb))
12391239
return;
12401240

1241+
if (!surprise)
1242+
sync_filesystem(sb);
1243+
shrink_dcache_sb(sb);
1244+
invalidate_inodes(sb, true);
12411245
if (sb->s_op->shutdown)
12421246
sb->s_op->shutdown(sb);
12431247

12441248
up_read(&sb->s_umount);
12451249
}
12461250

12471251
const struct blk_holder_ops fs_holder_ops = {
1248-
.mark_dead = fs_mark_dead,
1252+
.mark_dead = fs_bdev_mark_dead,
12491253
};
12501254
EXPORT_SYMBOL_GPL(fs_holder_ops);
12511255

include/linux/blkdev.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1461,7 +1461,7 @@ void blkdev_show(struct seq_file *seqf, off_t offset);
14611461
#endif
14621462

14631463
struct blk_holder_ops {
1464-
void (*mark_dead)(struct block_device *bdev);
1464+
void (*mark_dead)(struct block_device *bdev, bool surprise);
14651465
};
14661466

14671467
extern const struct blk_holder_ops fs_holder_ops;

0 commit comments

Comments
 (0)