diff options
author | mckusick <mckusick@FreeBSD.org> | 2013-02-16 14:51:30 +0000 |
---|---|---|
committer | mckusick <mckusick@FreeBSD.org> | 2013-02-16 14:51:30 +0000 |
commit | c04f4382b34d7ae4606db6e725d3613fd952a0e4 (patch) | |
tree | 818f7322d46b65c6033f7e8e58cf52d3ebff3771 /sys/kern/vfs_bio.c | |
parent | dcbeb7acb186d90fbec3caed228b522c0b41ad64 (diff) | |
download | FreeBSD-src-c04f4382b34d7ae4606db6e725d3613fd952a0e4.zip FreeBSD-src-c04f4382b34d7ae4606db6e725d3613fd952a0e4.tar.gz |
Add barrier write capability to the VFS buffer interface. A barrier
write is a disk write request that tells the disk that the buffer
being written must be committed to the media along with any writes
that preceeded it before any future blocks may be written to the drive.
Barrier writes are provided by adding the functions bbarrierwrite
(bwrite with barrier) and babarrierwrite (bawrite with barrier).
Following a bbarrierwrite the client knows that the requested buffer
is on the media. It does not ensure that buffers written before that
buffer are on the media. It only ensure that buffers written before
that buffer will get to the media before any buffers written after
that buffer. A flush command must be sent to the disk to ensure that
all earlier written buffers are on the media.
Reviewed by: kib
Tested by: Peter Holm
Diffstat (limited to 'sys/kern/vfs_bio.c')
-rw-r--r-- | sys/kern/vfs_bio.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index 96c8442..6393399 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -206,6 +206,9 @@ SYSCTL_INT(_vfs, OID_AUTO, flushbufqtarget, CTLFLAG_RW, &flushbufqtarget, 0, static long notbufdflashes; SYSCTL_LONG(_vfs, OID_AUTO, notbufdflashes, CTLFLAG_RD, ¬bufdflashes, 0, "Number of dirty buffer flushes done by the bufdaemon helpers"); +static long barrierwrites; +SYSCTL_LONG(_vfs, OID_AUTO, barrierwrites, CTLFLAG_RW, &barrierwrites, 0, + "Number of barrier writes"); /* * Wakeup point for bufdaemon, as well as indicator of whether it is already @@ -888,6 +891,9 @@ bufwrite(struct buf *bp) return (0); } + if (bp->b_flags & B_BARRIER) + barrierwrites++; + oldflags = bp->b_flags; BUF_ASSERT_HELD(bp); @@ -1007,6 +1013,8 @@ bdwrite(struct buf *bp) CTR3(KTR_BUF, "bdwrite(%p) vp %p flags %X", bp, bp->b_vp, bp->b_flags); KASSERT(bp->b_bufobj != NULL, ("No b_bufobj %p", bp)); + KASSERT((bp->b_flags & B_BARRIER) == 0, + ("Barrier request in delayed write %p", bp)); BUF_ASSERT_HELD(bp); if (bp->b_flags & B_INVAL) { @@ -1167,6 +1175,40 @@ bawrite(struct buf *bp) } /* + * babarrierwrite: + * + * Asynchronous barrier write. Start output on a buffer, but do not + * wait for it to complete. Place a write barrier after this write so + * that this buffer and all buffers written before it are committed to + * the disk before any buffers written after this write are committed + * to the disk. The buffer is released when the output completes. + */ +void +babarrierwrite(struct buf *bp) +{ + + bp->b_flags |= B_ASYNC | B_BARRIER; + (void) bwrite(bp); +} + +/* + * bbarrierwrite: + * + * Synchronous barrier write. Start output on a buffer and wait for + * it to complete. Place a write barrier after this write so that + * this buffer and all buffers written before it are committed to + * the disk before any buffers written after this write are committed + * to the disk. The buffer is released when the output completes. + */ +int +bbarrierwrite(struct buf *bp) +{ + + bp->b_flags |= B_BARRIER; + return (bwrite(bp)); +} + +/* * bwillwrite: * * Called prior to the locking of any vnodes when we are expecting to |