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;
}