aboutsummaryrefslogtreecommitdiff
path: root/fs/xfs
diff options
context:
space:
mode:
authorGravatar Christoph Hellwig <hch@lst.de> 2023-08-09 15:05:39 -0700
committerGravatar Christian Brauner <brauner@kernel.org> 2023-08-10 10:34:55 +0200
commit1a0a5dad67b60250dce151c9533ccbecdfd822d4 (patch)
treed80fabda3a4f0d82b958bfba022377ef0654cc67 /fs/xfs
parentxfs: close the external block devices in xfs_mount_free (diff)
downloadlinux-1a0a5dad67b60250dce151c9533ccbecdfd822d4.tar.gz
linux-1a0a5dad67b60250dce151c9533ccbecdfd822d4.tar.bz2
linux-1a0a5dad67b60250dce151c9533ccbecdfd822d4.zip
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: Christoph Hellwig <hch@lst.de> Reviewed-by: "Darrick J. Wong" <djwong@kernel.org> Message-Id: <20230809220545.1308228-8-hch@lst.de> Signed-off-by: Christian Brauner <brauner@kernel.org>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_super.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 18d34e802aac..46d0cbe2b5f8 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -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);