Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/ufs/lfs Use a marker node to iterate lfs_dchainhd / i_lf...



details:   https://anonhg.NetBSD.org/src/rev/10ee0b8679bc
branches:  trunk
changeset: 849182:10ee0b8679bc
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Sun Feb 23 08:38:58 2020 +0000

description:
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.

diffstat:

 sys/ufs/lfs/lfs_inode.h |   3 ++-
 sys/ufs/lfs/lfs_subr.c  |  40 +++++++++++++++++++++++++++++++---------
 sys/ufs/lfs/lfs_vnops.c |  32 +++++++++++++++++++++++++++-----
 3 files changed, 60 insertions(+), 15 deletions(-)

diffs (189 lines):

diff -r d5eaebc44980 -r 10ee0b8679bc sys/ufs/lfs/lfs_inode.h
--- a/sys/ufs/lfs/lfs_inode.h   Sun Feb 23 07:17:01 2020 +0000
+++ b/sys/ufs/lfs/lfs_inode.h   Sun Feb 23 08:38:58 2020 +0000
@@ -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 @@
 /*        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)
diff -r d5eaebc44980 -r 10ee0b8679bc sys/ufs/lfs/lfs_subr.c
--- a/sys/ufs/lfs/lfs_subr.c    Sun Feb 23 07:17:01 2020 +0000
+++ b/sys/ufs/lfs/lfs_subr.c    Sun Feb 23 08:38:58 2020 +0000
@@ -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 @@
 
 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 @@
        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;
-       }
+
+       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;
 
-       for (ip = TAILQ_FIRST(&fs->lfs_dchainhd); ip != NULL; ip = nip) {
-               nip = TAILQ_NEXT(ip, i_lfs_dchain);
+       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 @@
                        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
diff -r d5eaebc44980 -r 10ee0b8679bc sys/ufs/lfs/lfs_vnops.c
--- a/sys/ufs/lfs/lfs_vnops.c   Sun Feb 23 07:17:01 2020 +0000
+++ b/sys/ufs/lfs/lfs_vnops.c   Sun Feb 23 08:38:58 2020 +0000
@@ -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 @@
        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 @@
 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 @@
        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 @@
         *
         */
        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 @@
                /* 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 @@
        (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;
 }
 



Home | Main Index | Thread Index | Old Index