aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2021-01-30 02:10:34 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2021-02-24 07:40:04 +0000
commit750252612dad72149832fac62645919c73cbf5d2 (patch)
treed72f38bc948e3ed0521a4db625dc8c8281a0930e
parent7f73db6d04d0fcfe52dde537ba1495886f34762d (diff)
buf SU hooks: track buf_start() calls with B_IOSTARTED flag
(cherry picked from commit bf0db19339e770a82236b74f523be4b572bde15d)
-rw-r--r--sys/kern/vfs_bio.c14
-rw-r--r--sys/sys/buf.h16
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c4
3 files changed, 27 insertions, 7 deletions
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index 2f18221e9270..9264388e9a3e 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -2639,6 +2639,13 @@ brelse(struct buf *bp)
return;
}
+ if (LIST_EMPTY(&bp->b_dep)) {
+ bp->b_flags &= ~B_IOSTARTED;
+ } else {
+ KASSERT((bp->b_flags & B_IOSTARTED) == 0,
+ ("brelse: SU io not finished bp %p", bp));
+ }
+
if ((bp->b_vflags & (BV_BKGRDINPROG | BV_BKGRDERR)) == BV_BKGRDERR) {
BO_LOCK(bp->b_bufobj);
bp->b_vflags &= ~BV_BKGRDERR;
@@ -2826,6 +2833,13 @@ bqrelse(struct buf *bp)
bp->b_flags &= ~(B_ASYNC | B_NOCACHE | B_AGE | B_RELBUF);
bp->b_xflags &= ~(BX_CVTENXIO);
+ if (LIST_EMPTY(&bp->b_dep)) {
+ bp->b_flags &= ~B_IOSTARTED;
+ } else {
+ KASSERT((bp->b_flags & B_IOSTARTED) == 0,
+ ("bqrelse: SU io not finished bp %p", bp));
+ }
+
if (bp->b_flags & B_MANAGED) {
if (bp->b_flags & B_REMFREE)
bremfreef(bp);
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
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index 60d4dad57d03..04afbfd4d6e4 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -2393,10 +2393,10 @@ ffs_backgroundwritedone(struct buf *bp)
#endif
/*
* This buffer is marked B_NOCACHE so when it is released
- * by biodone it will be tossed.
+ * by biodone it will be tossed. Clear B_IOSTARTED in case of error.
*/
bp->b_flags |= B_NOCACHE;
- bp->b_flags &= ~B_CACHE;
+ bp->b_flags &= ~(B_CACHE | B_IOSTARTED);
pbrelvp(bp);
/*