Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 11 Jul 2015 11:21:57 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r285384 - head/sys/kern
Message-ID:  <201507111121.t6BBLvaF022898@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Sat Jul 11 11:21:56 2015
New Revision: 285384
URL: https://svnweb.freebsd.org/changeset/base/285384

Log:
  Do not allow creation of the dirty buffers for the dead buffer
  objects, i.e. for buffer objects which vnode was reclaimed.  Buffer
  cache cannot write such buffers.  Return the error and discard the
  buffer immediately on write attempt.
  
  BO_DIRTY now always set during vnode reclamation, since it is used not
  only for the INVARIANTS checks.  Do allow placement of the clean
  buffers on dead bufobj list, otherwise filesystems cannot use bufcache
  at all after the devvp reclaim.
  
  Reported and tested by:	trasz
  Sponsored by:	The FreeBSD Foundation
  MFC after:	2 weeks

Modified:
  head/sys/kern/vfs_bio.c
  head/sys/kern/vfs_subr.c

Modified: head/sys/kern/vfs_bio.c
==============================================================================
--- head/sys/kern/vfs_bio.c	Sat Jul 11 04:55:01 2015	(r285383)
+++ head/sys/kern/vfs_bio.c	Sat Jul 11 11:21:56 2015	(r285384)
@@ -1205,6 +1205,12 @@ bufwrite(struct buf *bp)
 	int vp_md;
 
 	CTR3(KTR_BUF, "bufwrite(%p) vp %p flags %X", bp, bp->b_vp, bp->b_flags);
+	if ((bp->b_bufobj->bo_flag & BO_DEAD) != 0) {
+		bp->b_flags |= B_INVAL | B_RELBUF;
+		bp->b_flags &= ~B_CACHE;
+		brelse(bp);
+		return (ENXIO);
+	}
 	if (bp->b_flags & B_INVAL) {
 		brelse(bp);
 		return (0);

Modified: head/sys/kern/vfs_subr.c
==============================================================================
--- head/sys/kern/vfs_subr.c	Sat Jul 11 04:55:01 2015	(r285383)
+++ head/sys/kern/vfs_subr.c	Sat Jul 11 11:21:56 2015	(r285384)
@@ -1584,7 +1584,8 @@ buf_vlist_add(struct buf *bp, struct buf
 	int error;
 
 	ASSERT_BO_WLOCKED(bo);
-	KASSERT((bo->bo_flag & BO_DEAD) == 0, ("dead bo %p", bo));
+	KASSERT((xflags & BX_VNDIRTY) == 0 || (bo->bo_flag & BO_DEAD) == 0,
+	    ("dead bo %p", bo));
 	KASSERT((bp->b_xflags & (BX_VNDIRTY|BX_VNCLEAN)) == 0,
 	    ("buf_vlist_add: Buf %p has existing xflags %d", bp, bp->b_xflags));
 	bp->b_xflags |= xflags;
@@ -2841,7 +2842,7 @@ vgonel(struct vnode *vp)
 		while (vinvalbuf(vp, 0, 0, 0) != 0)
 			;
 	}
-#ifdef INVARIANTS
+
 	BO_LOCK(&vp->v_bufobj);
 	KASSERT(TAILQ_EMPTY(&vp->v_bufobj.bo_dirty.bv_hd) &&
 	    vp->v_bufobj.bo_dirty.bv_cnt == 0 &&
@@ -2850,7 +2851,6 @@ vgonel(struct vnode *vp)
 	    ("vp %p bufobj not invalidated", vp));
 	vp->v_bufobj.bo_flag |= BO_DEAD;
 	BO_UNLOCK(&vp->v_bufobj);
-#endif
 
 	/*
 	 * Reclaim the vnode.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201507111121.t6BBLvaF022898>