Commit 1a0a5dad authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Christian Brauner
Browse files

xfs: document the invalidate_bdev call in invalidate_bdev



Copy and paste the commit message from Darrick into a comment to explain
the seemingly odd invalidate_bdev in xfs_shutdown_devices.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatar"Darrick J. Wong" <djwong@kernel.org>
Message-Id: <20230809220545.1308228-8-hch@lst.de>
Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
parent 35a93b14
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -410,6 +410,32 @@ STATIC void
xfs_shutdown_devices(
	struct xfs_mount	*mp)
{
	/*
	 * Udev is triggered whenever anyone closes a block device or unmounts
	 * a file systemm on a block device.
	 * The default udev rules invoke blkid to read the fs super and create
	 * symlinks to the bdev under /dev/disk.  For this, it uses buffered
	 * reads through the page cache.
	 *
	 * xfs_db also uses buffered reads to examine metadata.  There is no
	 * coordination between xfs_db and udev, which means that they can run
	 * concurrently.  Note there is no coordination between the kernel and
	 * blkid either.
	 *
	 * On a system with 64k pages, the page cache can cache the superblock
	 * and the root inode (and hence the root directory) with the same 64k
	 * page.  If udev spawns blkid after the mkfs and the system is busy
	 * enough that it is still running when xfs_db starts up, they'll both
	 * read from the same page in the pagecache.
	 *
	 * The unmount writes updated inode metadata to disk directly.  The XFS
	 * buffer cache does not use the bdev pagecache, so it needs to
	 * invalidate that pagecache on unmount.  If the above scenario occurs,
	 * the pagecache no longer reflects what's on disk, xfs_db reads the
	 * stale metadata, and fails to find /a.  Most of the time this succeeds
	 * because closing a bdev invalidates the page cache, but when processes
	 * race, everyone loses.
	 */
	if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp) {
		blkdev_issue_flush(mp->m_logdev_targp->bt_bdev);
		invalidate_bdev(mp->m_logdev_targp->bt_bdev);