Commit 560e20e4 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Christian Brauner
Browse files

block: consolidate __invalidate_device and fsync_bdev



We currently have two interfaces that take a block_devices and the find
a mounted file systems to flush or invaldidate data on it.  Both are a
bit problematic because they only work for the "main" block devices
that is used as s_dev for the super_block, and because they don't call
into the file system at all.

Merge the two into a new bdev_mark_dead helper that does both the
syncing and invalidation and which is properly documented.  This is
in preparation of merging the functionality into the ->mark_dead
holder operation so that it will work on additional block devices
used by a file systems and give us a single entry point for invalidation
of dead devices or media.

Note that a single standalone fsync_bdev call for an obscure ioctl
remains for now, but that one will also be deal with in a bit.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarJosef Bacik <josef@toxicpanda.com>
Message-Id: <20230811100828.1897174-14-hch@lst.de>
Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
parent 127a5093
Loading
Loading
Loading
Loading
+28 −5
Original line number Diff line number Diff line
@@ -221,7 +221,6 @@ int fsync_bdev(struct block_device *bdev)
	}
	return sync_blockdev(bdev);
}
EXPORT_SYMBOL(fsync_bdev);

/**
 * freeze_bdev - lock a filesystem and force it into a consistent state
@@ -960,12 +959,27 @@ int lookup_bdev(const char *pathname, dev_t *dev)
}
EXPORT_SYMBOL(lookup_bdev);

int __invalidate_device(struct block_device *bdev, bool kill_dirty)
/**
 * bdev_mark_dead - mark a block device as dead
 * @bdev: block device to operate on
 * @surprise: indicate a surprise removal
 *
 * Tell the file system that this devices or media is dead.  If @surprise is set
 * to %true the device or media is already gone, if not we are preparing for an
 * orderly removal.
 *
 * This syncs out all dirty data and writes back inodes and then invalidates any
 * cached data in the inodes on the file system, the inodes themselves and the
 * block device mapping.
 */
void bdev_mark_dead(struct block_device *bdev, bool surprise)
{
	struct super_block *sb = get_super(bdev);
	int res = 0;

	if (sb) {
		if (!surprise)
			sync_filesystem(sb);
		/*
		 * no need to lock the super, get_super holds the
		 * read mutex so the filesystem cannot go away
@@ -973,13 +987,22 @@ int __invalidate_device(struct block_device *bdev, bool kill_dirty)
		 * hold).
		 */
		shrink_dcache_sb(sb);
		res = invalidate_inodes(sb, kill_dirty);
		res = invalidate_inodes(sb, true);
		drop_super(sb);
	} else {
		if (!surprise)
			sync_blockdev(bdev);
	}
	invalidate_bdev(bdev);
	return res;
}
EXPORT_SYMBOL(__invalidate_device);
#ifdef CONFIG_DASD_MODULE
/*
 * Drivers should not use this directly, but the DASD driver has historically
 * had a shutdown to offline mode that doesn't actually remove the gendisk
 * that otherwise looks a lot like a safe device removal.
 */
EXPORT_SYMBOL_GPL(bdev_mark_dead);
#endif

void sync_bdevs(bool wait)
{
+2 −2
Original line number Diff line number Diff line
@@ -281,7 +281,7 @@ bool disk_check_media_change(struct gendisk *disk)
	if (!(events & DISK_EVENT_MEDIA_CHANGE))
		return false;

	__invalidate_device(disk->part0, true);
	bdev_mark_dead(disk->part0, true);
	set_bit(GD_NEED_PART_SCAN, &disk->state);
	return true;
}
@@ -300,7 +300,7 @@ void disk_force_media_change(struct gendisk *disk)
{
	disk_event_uevent(disk, DISK_EVENT_MEDIA_CHANGE);
	inc_diskseq(disk);
	__invalidate_device(disk->part0, true);
	bdev_mark_dead(disk->part0, true);
	set_bit(GD_NEED_PART_SCAN, &disk->state);
}
EXPORT_SYMBOL_GPL(disk_force_media_change);
+1 −2
Original line number Diff line number Diff line
@@ -647,8 +647,7 @@ void del_gendisk(struct gendisk *disk)
	mutex_lock(&disk->open_mutex);
	xa_for_each(&disk->part_tbl, idx, part) {
		remove_inode_hash(part->bd_inode);
		fsync_bdev(part);
		__invalidate_device(part, true);
		bdev_mark_dead(part, false);
	}
	mutex_unlock(&disk->open_mutex);

+1 −4
Original line number Diff line number Diff line
@@ -281,10 +281,7 @@ static void delete_partition(struct block_device *part)
	 * looked up any more even when openers still hold references.
	 */
	remove_inode_hash(part->bd_inode);

	fsync_bdev(part);
	__invalidate_device(part, true);

	bdev_mark_dead(part, false);
	drop_partition(part);
}

+2 −4
Original line number Diff line number Diff line
@@ -3626,10 +3626,8 @@ int dasd_generic_set_offline(struct ccw_device *cdev)
		 * so sync bdev first and then wait for our queues to become
		 * empty
		 */
		if (device->block) {
			fsync_bdev(device->block->bdev);
			__invalidate_device(device->block->bdev, true);
		}
		if (device->block)
			bdev_mark_dead(device->block->bdev, false);
		dasd_schedule_device_bh(device);
		rc = wait_event_interruptible(shutdown_waitq,
					      _wait_for_empty_queues(device));
Loading