Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f538d4da authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Nathan Scott
Browse files

[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: default avatarChristoph Hellwig <hch@sgi.com>
Signed-off-by: default avatarNathan Scott <nathans@sgi.com>
parent 739cafd3
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -1295,6 +1295,11 @@ _pagebuf_ioapply(
		rw = (pb->pb_flags & PBF_READ) ? READ : WRITE;
	}

	if (pb->pb_flags & PBF_ORDERED) {
		ASSERT(!(pb->pb_flags & PBF_READ));
		rw = WRITE_BARRIER;
	}

	/* Special code path for reading a sub page size pagebuf in --
	 * we populate up the whole page, and hence the other metadata
	 * in the same page.  This optimization is only valid when the
+4 −4
Original line number Diff line number Diff line
@@ -74,7 +74,7 @@ typedef enum page_buf_flags_e { /* pb_flags values */
	PBF_DELWRI = (1 << 6),  /* buffer has dirty pages                  */
	PBF_STALE = (1 << 7),	/* buffer has been staled, do not find it  */
	PBF_FS_MANAGED = (1 << 8),  /* filesystem controls freeing memory  */
	PBF_FLUSH = (1 << 11),	    /* flush disk write cache		   */
 	PBF_ORDERED = (1 << 11),    /* use ordered writes		   */
	PBF_READ_AHEAD = (1 << 12), /* asynchronous read-ahead		   */

	/* flags used only as arguments to access routines */
@@ -383,9 +383,9 @@ extern void pagebuf_trace(
#define XFS_BUF_UNASYNC(x)	 ((x)->pb_flags &= ~PBF_ASYNC)
#define XFS_BUF_ISASYNC(x)	 ((x)->pb_flags & PBF_ASYNC)

#define XFS_BUF_FLUSH(x)	 ((x)->pb_flags |= PBF_FLUSH)
#define XFS_BUF_UNFLUSH(x)	 ((x)->pb_flags &= ~PBF_FLUSH)
#define XFS_BUF_ISFLUSH(x)	 ((x)->pb_flags & PBF_FLUSH)
#define XFS_BUF_ORDERED(x)	 ((x)->pb_flags |= PBF_ORDERED)
#define XFS_BUF_UNORDERED(x)	 ((x)->pb_flags &= ~PBF_ORDERED)
#define XFS_BUF_ISORDERED(x)	 ((x)->pb_flags & PBF_ORDERED)

#define XFS_BUF_SHUT(x)		 printk("XFS_BUF_SHUT not implemented yet\n")
#define XFS_BUF_UNSHUT(x)	 printk("XFS_BUF_UNSHUT not implemented yet\n")
+66 −0
Original line number Diff line number Diff line
@@ -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(
+1 −0
Original line number Diff line number Diff line
@@ -132,6 +132,7 @@ extern void xfs_flush_device(struct xfs_inode *);
extern int  xfs_blkdev_get(struct xfs_mount *, const char *,
				struct block_device **);
extern void xfs_blkdev_put(struct block_device *);
extern void xfs_blkdev_issue_flush(struct xfs_buftarg *);

extern struct export_operations linvfs_export_ops;

+1 −1
Original line number Diff line number Diff line
@@ -99,7 +99,7 @@ struct xfs_mount_args {
						 * enforcement */
#define XFSMNT_NOUUID		0x01000000	/* Ignore fs uuid */
#define XFSMNT_DMAPI		0x02000000	/* enable dmapi/xdsm */
#define XFSMNT_NOLOGFLUSH	0x04000000	/* Don't flush for log blocks */
#define XFSMNT_BARRIER		0x04000000	/* use write barriers */
#define XFSMNT_IDELETE		0x08000000	/* inode cluster delete */
#define XFSMNT_SWALLOC		0x10000000	/* turn on stripe width
						 * allocation */
Loading