summaryrefslogtreecommitdiffstats
path: root/fs/xfs/linux-2.6/xfs_super.c
diff options
context:
space:
mode:
authorChristoph Hellwig2005-11-02 00:26:59 +0100
committerNathan Scott2005-11-02 00:26:59 +0100
commitf538d4da8d521746ca5ebf8c1a8105eb49bfb45e (patch)
tree5516e1d2df01e412709284e379085b348122c501 /fs/xfs/linux-2.6/xfs_super.c
parent[XFS] fix PBF_NONE handling (diff)
downloadkernel-qcow2-linux-f538d4da8d521746ca5ebf8c1a8105eb49bfb45e.tar.gz
kernel-qcow2-linux-f538d4da8d521746ca5ebf8c1a8105eb49bfb45e.tar.xz
kernel-qcow2-linux-f538d4da8d521746ca5ebf8c1a8105eb49bfb45e.zip
[XFS] write barrier support Issue all log sync operations as ordered
writes. In addition flush the disk cache on fsync if the sync cached operation didn't sync the log to disk (this requires some additional bookeping in the transaction and log code). If the device doesn't claim to support barriers, the filesystem has an extern log volume or the trial superblock write with barriers enabled failed we disable barriers and print a warning. We should probably fail the mount completely, but that could lead to nasty boot failures for the root filesystem. Not enabled by default yet, needs more destructive testing first. SGI-PV: 912426 SGI-Modid: xfs-linux:xfs-kern:198723a Signed-off-by: Christoph Hellwig <hch@sgi.com> Signed-off-by: Nathan Scott <nathans@sgi.com>
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_super.c')
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 2302454d8d47..d2701cc624b9 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -278,6 +278,72 @@ xfs_blkdev_put(
close_bdev_excl(bdev);
}
+/*
+ * Try to write out the superblock using barriers.
+ */
+STATIC int
+xfs_barrier_test(
+ xfs_mount_t *mp)
+{
+ xfs_buf_t *sbp = xfs_getsb(mp, 0);
+ int error;
+
+ XFS_BUF_UNDONE(sbp);
+ XFS_BUF_UNREAD(sbp);
+ XFS_BUF_UNDELAYWRITE(sbp);
+ XFS_BUF_WRITE(sbp);
+ XFS_BUF_UNASYNC(sbp);
+ XFS_BUF_ORDERED(sbp);
+
+ xfsbdstrat(mp, sbp);
+ error = xfs_iowait(sbp);
+
+ /*
+ * Clear all the flags we set and possible error state in the
+ * buffer. We only did the write to try out whether barriers
+ * worked and shouldn't leave any traces in the superblock
+ * buffer.
+ */
+ XFS_BUF_DONE(sbp);
+ XFS_BUF_ERROR(sbp, 0);
+ XFS_BUF_UNORDERED(sbp);
+
+ xfs_buf_relse(sbp);
+ return error;
+}
+
+void
+xfs_mountfs_check_barriers(xfs_mount_t *mp)
+{
+ int error;
+
+ if (mp->m_logdev_targp != mp->m_ddev_targp) {
+ xfs_fs_cmn_err(CE_NOTE, mp,
+ "Disabling barriers, not supported with external log device");
+ mp->m_flags &= ~XFS_MOUNT_BARRIER;
+ }
+
+ if (mp->m_ddev_targp->pbr_bdev->bd_disk->queue->ordered ==
+ QUEUE_ORDERED_NONE) {
+ xfs_fs_cmn_err(CE_NOTE, mp,
+ "Disabling barriers, not supported by the underlying device");
+ mp->m_flags &= ~XFS_MOUNT_BARRIER;
+ }
+
+ error = xfs_barrier_test(mp);
+ if (error) {
+ xfs_fs_cmn_err(CE_NOTE, mp,
+ "Disabling barriers, trial barrier write failed");
+ mp->m_flags &= ~XFS_MOUNT_BARRIER;
+ }
+}
+
+void
+xfs_blkdev_issue_flush(
+ xfs_buftarg_t *buftarg)
+{
+ blkdev_issue_flush(buftarg->pbr_bdev, NULL);
+}
STATIC struct inode *
linvfs_alloc_inode(