diff options
author | Konstantin Belousov <kib@FreeBSD.org> | 2021-01-30 02:10:34 +0000 |
---|---|---|
committer | Konstantin Belousov <kib@FreeBSD.org> | 2021-02-12 01:02:19 +0000 |
commit | bf0db19339e770a82236b74f523be4b572bde15d (patch) | |
tree | 680eadebf82726c79c04c22fc4f258a813b9ea98 /sys/sys | |
parent | 0281f88e5dbc8d6f819bf3f22dd11239ff5374ea (diff) | |
download | src-bf0db19339e770a82236b74f523be4b572bde15d.tar.gz src-bf0db19339e770a82236b74f523be4b572bde15d.zip |
buf SU hooks: track buf_start() calls with B_IOSTARTED flag
and only call buf_complete() if previously started. Some error paths,
like CoW failire, might skip buf_start() and do bufdone(), which itself
call buf_complete().
Various SU handle_written_XXX() functions check that io was started
and incomplete parts of the buffer data reverted before restoring them.
This is a useful invariant that B_IO_STARTED on buffer layer allows to
keep instead of changing check and panic into check and return.
Reported by: pho
Reviewed by: chs, mckusick
Tested by: pho
MFC after: 2 weeks
Sponsored by: The FreeBSD Foundations
Diffstat (limited to 'sys/sys')
-rw-r--r-- | sys/sys/buf.h | 16 |
1 files changed, 11 insertions, 5 deletions
diff --git a/sys/sys/buf.h b/sys/sys/buf.h index 50fa0f35491e..2997560b9ab3 100644 --- a/sys/sys/buf.h +++ b/sys/sys/buf.h @@ -232,7 +232,7 @@ struct buf { #define B_MALLOC 0x00010000 /* malloced b_data */ #define B_CLUSTEROK 0x00020000 /* Pagein op, so swap() can count it. */ #define B_INVALONERR 0x00040000 /* Invalidate on write error. */ -#define B_00080000 0x00080000 /* Available flag. */ +#define B_IOSTARTED 0x00080000 /* buf_start() called */ #define B_00100000 0x00100000 /* Available flag. */ #define B_MAXPHYS 0x00200000 /* nitems(b_pages[]) = atop(MAXPHYS). */ #define B_RELBUF 0x00400000 /* Release VMIO buffer. */ @@ -248,8 +248,8 @@ struct buf { #define PRINT_BUF_FLAGS "\20\40remfree\37cluster\36vmio\35ram\34managed" \ "\33paging\32infreecnt\31nocopy\30b23\27relbuf\26maxphys\25b20" \ - "\24b19\23invalonerr\22clusterok\21malloc\20nocache\17b14\16inval" \ - "\15reuse\14noreuse\13eintr\12done\11b8\10delwri" \ + "\24iostarted\23invalonerr\22clusterok\21malloc\20nocache\17b14" \ + "\16inval\15reuse\14noreuse\13eintr\12done\11b8\10delwri" \ "\7validsuspwrt\6cache\5deferred\4direct\3async\2needcommit\1age" /* @@ -434,6 +434,9 @@ bstrategy(struct buf *bp) static __inline void buf_start(struct buf *bp) { + KASSERT((bp->b_flags & B_IOSTARTED) == 0, + ("recursed buf_start %p", bp)); + bp->b_flags |= B_IOSTARTED; if (bioops.io_start) (*bioops.io_start)(bp); } @@ -441,8 +444,11 @@ buf_start(struct buf *bp) static __inline void buf_complete(struct buf *bp) { - if (bioops.io_complete) - (*bioops.io_complete)(bp); + if ((bp->b_flags & B_IOSTARTED) != 0) { + bp->b_flags &= ~B_IOSTARTED; + if (bioops.io_complete) + (*bioops.io_complete)(bp); + } } static __inline void |