Module Name:    src
Committed By:   riastradh
Date:           Sun Feb 23 08:39:28 UTC 2020

Modified Files:
        src/sys/ufs/lfs: lfs_bio.c

Log Message:
Prevent new dirops while we issue lfs_flush_dirops.

lfs_flush_dirops assumes (by KASSERT((ip->i_state & IN_ADIROP) == 0))
that vnodes on the dchain will not become involved in active dirops
even while holding no other locks (lfs_lock, v_interlock), so we must
set lfs_writer here.  All other callers already set lfs_writer.

We set fs->lfs_writer++ without explicitly doing lfs_writer_enter
because

(a) we already waited for the dirops to drain, and
(b) we hold lfs_lock and cannot drop it before setting lfs_writer.


To generate a diff of this commit:
cvs rdiff -u -r1.145 -r1.146 src/sys/ufs/lfs/lfs_bio.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/ufs/lfs/lfs_bio.c
diff -u src/sys/ufs/lfs/lfs_bio.c:1.145 src/sys/ufs/lfs/lfs_bio.c:1.146
--- src/sys/ufs/lfs/lfs_bio.c:1.145	Tue Feb 18 20:23:17 2020
+++ src/sys/ufs/lfs/lfs_bio.c	Sun Feb 23 08:39:28 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: lfs_bio.c,v 1.145 2020/02/18 20:23:17 chs Exp $	*/
+/*	$NetBSD: lfs_bio.c,v 1.146 2020/02/23 08:39:28 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2002, 2003, 2008 The NetBSD Foundation, Inc.
@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_bio.c,v 1.145 2020/02/18 20:23:17 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_bio.c,v 1.146 2020/02/23 08:39:28 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -653,9 +653,14 @@ lfs_check(struct vnode *vp, daddr_t blkn
 	/* If there are too many pending dirops, we have to flush them. */
 	if (fs->lfs_dirvcount > LFS_MAX_FSDIROP(fs) ||
 	    lfs_dirvcount > LFS_MAX_DIROP || fs->lfs_diropwait > 0) {
+		KASSERT(fs->lfs_dirops == 0);
+		fs->lfs_writer++;
 		mutex_exit(&lfs_lock);
 		lfs_flush_dirops(fs);
 		mutex_enter(&lfs_lock);
+		if (--fs->lfs_writer == 0)
+			cv_broadcast(&fs->lfs_diropscv);
+		KASSERT(fs->lfs_dirops == 0);
 	} else if (locked_queue_count + INOCOUNT(fs) > LFS_MAX_BUFS ||
 	    locked_queue_bytes + INOBYTES(fs) > LFS_MAX_BYTES ||
 	    lfs_subsys_pages > LFS_MAX_PAGES ||

Reply via email to