From owner-dev-commits-src-all@freebsd.org Fri Feb 12 01:07:01 2021 Return-Path: Delivered-To: dev-commits-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 5B4F453D231; Fri, 12 Feb 2021 01:07:01 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4DcFhP2B33z3N7r; Fri, 12 Feb 2021 01:07:01 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 3AD3D1AFCD; Fri, 12 Feb 2021 01:07:01 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 11C171ZG070390; Fri, 12 Feb 2021 01:07:01 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 11C171c7070389; Fri, 12 Feb 2021 01:07:01 GMT (envelope-from git) Date: Fri, 12 Feb 2021 01:07:01 GMT Message-Id: <202102120107.11C171c7070389@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Konstantin Belousov Subject: git: bf0db19339e7 - main - buf SU hooks: track buf_start() calls with B_IOSTARTED flag MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kib X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: bf0db19339e770a82236b74f523be4b572bde15d Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-all@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for all branches of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 12 Feb 2021 01:07:01 -0000 The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=bf0db19339e770a82236b74f523be4b572bde15d commit bf0db19339e770a82236b74f523be4b572bde15d Author: Konstantin Belousov AuthorDate: 2021-01-30 02:10:34 +0000 Commit: Konstantin Belousov CommitDate: 2021-02-12 01:02:19 +0000 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 --- sys/kern/vfs_bio.c | 14 ++++++++++++++ sys/sys/buf.h | 16 +++++++++++----- sys/ufs/ffs/ffs_vfsops.c | 4 ++-- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index ff25e5b0043c..45be14b47207 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); /*