Module Name:    src
Committed By:   riastradh
Date:           Sun Feb 23 08:38:58 UTC 2020

Modified Files:
        src/sys/ufs/lfs: lfs_inode.h lfs_subr.c lfs_vnops.c

Log Message:
Use a marker node to iterate lfs_dchainhd / i_lfs_dchain.

I believe elements can be removed while the lock is dropped,
including the next node we're hanging on to.


To generate a diff of this commit:
cvs rdiff -u -r1.24 -r1.25 src/sys/ufs/lfs/lfs_inode.h
cvs rdiff -u -r1.97 -r1.98 src/sys/ufs/lfs/lfs_subr.c
cvs rdiff -u -r1.325 -r1.326 src/sys/ufs/lfs/lfs_vnops.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_inode.h
diff -u src/sys/ufs/lfs/lfs_inode.h:1.24 src/sys/ufs/lfs/lfs_inode.h:1.25
--- src/sys/ufs/lfs/lfs_inode.h:1.24	Tue Feb 18 20:23:17 2020
+++ src/sys/ufs/lfs/lfs_inode.h	Sun Feb 23 08:38:58 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: lfs_inode.h,v 1.24 2020/02/18 20:23:17 chs Exp $	*/
+/*	$NetBSD: lfs_inode.h,v 1.25 2020/02/23 08:38:58 riastradh Exp $	*/
 /*  from NetBSD: ulfs_inode.h,v 1.5 2013/06/06 00:51:50 dholland Exp  */
 /*  from NetBSD: inode.h,v 1.72 2016/06/03 15:36:03 christos Exp  */
 
@@ -123,6 +123,7 @@ struct inode {
 /* 	   unused	0x0400 */	/* was FFS-only IN_SPACECOUNTED */
 #define	IN_PAGING       0x1000		/* LFS: file is on paging queue */
 #define IN_CDIROP       0x4000          /* LFS: dirop completed pending i/o */
+#define	IN_MARKER	0x00010000	/* LFS: marker inode for iteration */
 
 /* XXX this is missing some of the flags */
 #define IN_ALLMOD (IN_MODIFIED|IN_ACCESS|IN_CHANGE|IN_UPDATE|IN_MODIFY|IN_ACCESSED|IN_CLEANING)

Index: src/sys/ufs/lfs/lfs_subr.c
diff -u src/sys/ufs/lfs/lfs_subr.c:1.97 src/sys/ufs/lfs/lfs_subr.c:1.98
--- src/sys/ufs/lfs/lfs_subr.c:1.97	Wed Jul 26 16:42:37 2017
+++ src/sys/ufs/lfs/lfs_subr.c	Sun Feb 23 08:38:58 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: lfs_subr.c,v 1.97 2017/07/26 16:42:37 maya Exp $	*/
+/*	$NetBSD: lfs_subr.c,v 1.98 2020/02/23 08:38:58 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_subr.c,v 1.97 2017/07/26 16:42:37 maya Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_subr.c,v 1.98 2020/02/23 08:38:58 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -337,10 +337,14 @@ lfs_seglock(struct lfs *fs, unsigned lon
 
 static void lfs_unmark_dirop(struct lfs *);
 
+static struct evcnt lfs_dchain_marker_pass_dirop =
+    EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "lfs", "dchain marker pass dirop");
+EVCNT_ATTACH_STATIC(lfs_dchain_marker_pass_dirop);
+
 static void
 lfs_unmark_dirop(struct lfs *fs)
 {
-	struct inode *ip, *nip;
+	struct inode *ip, *marker;
 	struct vnode *vp;
 	int doit;
 
@@ -349,13 +353,28 @@ lfs_unmark_dirop(struct lfs *fs)
 	doit = !(fs->lfs_flags & LFS_UNDIROP);
 	if (doit)
 		fs->lfs_flags |= LFS_UNDIROP;
-	if (!doit) {
-		mutex_exit(&lfs_lock);
+	mutex_exit(&lfs_lock);
+
+	if (!doit)
 		return;
-	}
 
-	for (ip = TAILQ_FIRST(&fs->lfs_dchainhd); ip != NULL; ip = nip) {
-		nip = TAILQ_NEXT(ip, i_lfs_dchain);
+	marker = pool_get(&lfs_inode_pool, PR_WAITOK);
+	KASSERT(fs != NULL);
+	memset(marker, 0, sizeof(*marker));
+	marker->inode_ext.lfs = pool_get(&lfs_inoext_pool, PR_WAITOK);
+	memset(marker->inode_ext.lfs, 0, sizeof(*marker->inode_ext.lfs));
+	marker->i_state |= IN_MARKER;
+
+	mutex_enter(&lfs_lock);
+	TAILQ_INSERT_HEAD(&fs->lfs_dchainhd, marker, i_lfs_dchain);
+	while ((ip = TAILQ_NEXT(marker, i_lfs_dchain)) != NULL) {
+		TAILQ_REMOVE(&fs->lfs_dchainhd, marker, i_lfs_dchain);
+		TAILQ_INSERT_AFTER(&fs->lfs_dchainhd, ip, marker,
+		    i_lfs_dchain);
+		if (ip->i_state & IN_MARKER) {
+			lfs_dchain_marker_pass_dirop.ev_count++;
+			continue;
+		}
 		vp = ITOV(ip);
 		if ((ip->i_state & (IN_ADIROP | IN_CDIROP)) == IN_CDIROP) {
 			--lfs_dirvcount;
@@ -371,10 +390,13 @@ lfs_unmark_dirop(struct lfs *fs)
 			ip->i_state &= ~IN_CDIROP;
 		}
 	}
-
+	TAILQ_REMOVE(&fs->lfs_dchainhd, marker, i_lfs_dchain);
 	fs->lfs_flags &= ~LFS_UNDIROP;
 	wakeup(&fs->lfs_flags);
 	mutex_exit(&lfs_lock);
+
+	pool_put(&lfs_inoext_pool, marker->inode_ext.lfs);
+	pool_put(&lfs_inode_pool, marker);
 }
 
 static void

Index: src/sys/ufs/lfs/lfs_vnops.c
diff -u src/sys/ufs/lfs/lfs_vnops.c:1.325 src/sys/ufs/lfs/lfs_vnops.c:1.326
--- src/sys/ufs/lfs/lfs_vnops.c:1.325	Wed Sep 18 17:59:15 2019
+++ src/sys/ufs/lfs/lfs_vnops.c	Sun Feb 23 08:38:58 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: lfs_vnops.c,v 1.325 2019/09/18 17:59:15 christos Exp $	*/
+/*	$NetBSD: lfs_vnops.c,v 1.326 2020/02/23 08:38:58 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
@@ -125,7 +125,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_vnops.c,v 1.325 2019/09/18 17:59:15 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_vnops.c,v 1.326 2020/02/23 08:38:58 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_compat_netbsd.h"
@@ -1595,6 +1595,10 @@ lfs_strategy(void *v)
 	return VOP_STRATEGY(vp, bp);
 }
 
+static struct evcnt lfs_dchain_marker_pass_flush =
+    EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "lfs", "dchain marker pass flush");
+EVCNT_ATTACH_STATIC(lfs_dchain_marker_pass_flush);
+
 /*
  * Inline lfs_segwrite/lfs_writevnodes, but just for dirops.
  * Technically this is a checkpoint (the on-disk state is valid)
@@ -1603,7 +1607,7 @@ lfs_strategy(void *v)
 int
 lfs_flush_dirops(struct lfs *fs)
 {
-	struct inode *ip, *nip;
+	struct inode *ip, *marker;
 	struct vnode *vp;
 	extern int lfs_dostats; /* XXX this does not belong here */
 	struct segment *sp;
@@ -1627,6 +1631,12 @@ lfs_flush_dirops(struct lfs *fs)
 	if (lfs_dostats)
 		++lfs_stats.flush_invoked;
 
+	marker = pool_get(&lfs_inode_pool, PR_WAITOK);
+	memset(marker, 0, sizeof(*marker));
+	marker->inode_ext.lfs = pool_get(&lfs_inoext_pool, PR_WAITOK);
+	memset(marker->inode_ext.lfs, 0, sizeof(*marker->inode_ext.lfs));
+	marker->i_state = IN_MARKER;
+
 	lfs_imtime(fs);
 	lfs_seglock(fs, flags);
 	sp = fs->lfs_sp;
@@ -1645,8 +1655,15 @@ lfs_flush_dirops(struct lfs *fs)
 	 *
 	 */
 	mutex_enter(&lfs_lock);
-	for (ip = TAILQ_FIRST(&fs->lfs_dchainhd); ip != NULL; ip = nip) {
-		nip = TAILQ_NEXT(ip, i_lfs_dchain);
+	TAILQ_INSERT_HEAD(&fs->lfs_dchainhd, marker, i_lfs_dchain);
+	while ((ip = TAILQ_NEXT(marker, i_lfs_dchain)) != NULL) {
+		TAILQ_REMOVE(&fs->lfs_dchainhd, marker, i_lfs_dchain);
+		TAILQ_INSERT_AFTER(&fs->lfs_dchainhd, ip, marker,
+		    i_lfs_dchain);
+		if (ip->i_state & IN_MARKER) {
+			lfs_dchain_marker_pass_flush.ev_count++;
+			continue;
+		}
 		mutex_exit(&lfs_lock);
 		vp = ITOV(ip);
 		mutex_enter(vp->v_interlock);
@@ -1705,7 +1722,9 @@ lfs_flush_dirops(struct lfs *fs)
 		/* XXX only for non-directories? --KS */
 		LFS_SET_UINO(ip, IN_MODIFIED);
 	}
+	TAILQ_REMOVE(&fs->lfs_dchainhd, marker, i_lfs_dchain);
 	mutex_exit(&lfs_lock);
+
 	/* We've written all the dirops there are */
 	ssp = (SEGSUM *)sp->segsum;
 	lfs_ss_setflags(fs, ssp, lfs_ss_getflags(fs, ssp) & ~(SS_CONT));
@@ -1713,6 +1732,9 @@ lfs_flush_dirops(struct lfs *fs)
 	(void) lfs_writeseg(fs, sp);
 	lfs_segunlock(fs);
 
+	pool_put(&lfs_inoext_pool, marker->inode_ext.lfs);
+	pool_put(&lfs_inode_pool, marker);
+
 	return error;
 }
 

Reply via email to