svn commit: r352453 - head/sys/kern

Kirk McKusick mckusick at FreeBSD.org
Tue Sep 17 17:44:51 UTC 2019


Author: mckusick
Date: Tue Sep 17 17:44:50 2019
New Revision: 352453
URL: https://svnweb.freebsd.org/changeset/base/352453

Log:
  The VFS-level clustering code collects together sequential blocks
  by issuing delayed-writes (bdwrite()) until a non-sequential block
  is written or the maximum cluster size is reached. At that point
  it collects the delayed buffers together (using bread()) to write
  them in a single operation. The assumption was that since we just
  looked at them they will still be in memory so there is no need to
  check for a read error from bread(). Very occationally (apparently
  every 10-hours or so when being pounded by Peter Holm's tests)
  this assumption is wrong.
  
  The fix is to check for errors from bread() and fail the cluster
  write thus falling back to the default individual flushing of any
  still dirty buffers.
  
  Reported by: Peter Holm and Chuck Silvers
  Reviewed by: kib
  MFC after:   3 days

Modified:
  head/sys/kern/vfs_cluster.c

Modified: head/sys/kern/vfs_cluster.c
==============================================================================
--- head/sys/kern/vfs_cluster.c	Tue Sep 17 17:28:44 2019	(r352452)
+++ head/sys/kern/vfs_cluster.c	Tue Sep 17 17:44:50 2019	(r352453)
@@ -718,6 +718,14 @@ cluster_write(struct vnode *vp, struct buf *bp, u_quad
 				struct cluster_save *buflist;
 
 				buflist = cluster_collectbufs(vp, bp, gbflags);
+				if (buflist == NULL) {
+					/*
+					 * Cluster build failed so just write
+					 * it now.
+					 */
+					bawrite(bp);
+					return;
+				}
 				endbp = &buflist->bs_children
 				    [buflist->bs_nchildren - 1];
 				if (VOP_REALLOCBLKS(vp, buflist)) {
@@ -1056,7 +1064,7 @@ cluster_collectbufs(struct vnode *vp, struct buf *last
 	struct cluster_save *buflist;
 	struct buf *bp;
 	daddr_t lbn;
-	int i, len;
+	int i, j, len, error;
 
 	len = vp->v_lastw - vp->v_cstart + 1;
 	buflist = malloc(sizeof(struct buf *) * (len + 1) + sizeof(*buflist),
@@ -1064,8 +1072,18 @@ cluster_collectbufs(struct vnode *vp, struct buf *last
 	buflist->bs_nchildren = 0;
 	buflist->bs_children = (struct buf **) (buflist + 1);
 	for (lbn = vp->v_cstart, i = 0; i < len; lbn++, i++) {
-		(void)bread_gb(vp, lbn, last_bp->b_bcount, NOCRED,
+		error = bread_gb(vp, lbn, last_bp->b_bcount, NOCRED,
 		    gbflags, &bp);
+		if (error != 0) {
+			/*
+			 * If read fails, release collected buffers
+			 * and return failure.
+			 */
+			for (j = 0; j < i; j++)
+				brelse(buflist->bs_children[j]);
+			free(buflist, M_SEGMENT);
+			return (NULL);
+		}
 		buflist->bs_children[i] = bp;
 		if (bp->b_blkno == bp->b_lblkno)
 			VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno,


More information about the svn-src-head mailing list