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