The branch stable/13 has been updated by kib:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=2622570aeb3d162812d72f7ef192c322cd8b73ef

commit 2622570aeb3d162812d72f7ef192c322cd8b73ef
Author:     Konstantin Belousov <[email protected]>
AuthorDate: 2021-05-01 21:53:21 +0000
Commit:     Konstantin Belousov <[email protected]>
CommitDate: 2021-07-07 10:50:13 +0000

    softdep_prelink(): only do sync if other thread changed the vnode metadata 
since previous prelink
    
    FreeBSD_version is bumped due to struct namei size change
    
    (cherry picked from commit 64b494a1050ae2cf2412edc19b57dc80f49eeda1)
---
 sys/sys/namei.h           | 12 +++++++++++-
 sys/sys/param.h           |  2 +-
 sys/ufs/ffs/ffs_extern.h  |  3 ++-
 sys/ufs/ffs/ffs_softdep.c | 32 +++++++++++++++++++++++++++-----
 sys/ufs/ufs/ufs_vnops.c   | 12 ++++++------
 5 files changed, 47 insertions(+), 14 deletions(-)

diff --git a/sys/sys/namei.h b/sys/sys/namei.h
index b4db0e758e2b..9e0a82ea1659 100644
--- a/sys/sys/namei.h
+++ b/sys/sys/namei.h
@@ -38,6 +38,7 @@
 #include <sys/caprights.h>
 #include <sys/filedesc.h>
 #include <sys/queue.h>
+#include <sys/_seqc.h>
 #include <sys/_uio.h>
 
 enum nameiop { LOOKUP, CREATE, DELETE, RENAME };
@@ -111,6 +112,12 @@ struct nameidata {
         */
        struct componentname ni_cnd;
        struct nameicap_tracker_head ni_cap_tracker;
+       /*
+        * Private helper data for UFS, must be at the end.  See
+        * NDINIT_PREFILL().
+        */
+       seqc_t  ni_dvp_seqc;
+       seqc_t  ni_vp_seqc;
 };
 
 #ifdef _KERNEL
@@ -224,7 +231,8 @@ int cache_fplookup(struct nameidata *ndp, enum 
cache_fpl_status *status,
  * Note the constant pattern may *hide* bugs.
  */
 #ifdef INVARIANTS
-#define NDINIT_PREFILL(arg)    memset(arg, 0xff, sizeof(*arg))
+#define NDINIT_PREFILL(arg)    memset(arg, 0xff, offsetof(struct nameidata,    
\
+    ni_dvp_seqc))
 #define NDINIT_DBG(arg)                { (arg)->ni_debugflags = 
NAMEI_DBG_INITED; }
 #define NDREINIT_DBG(arg)      {                                               
\
        if (((arg)->ni_debugflags & NAMEI_DBG_INITED) == 0)                     
\
@@ -266,6 +274,8 @@ do {                                                        
                        \
 } while (0)
 
 #define        NDPREINIT(ndp) do {                                             
        \
+       (ndp)->ni_dvp_seqc = SEQC_MOD;                                          
\
+       (ndp)->ni_vp_seqc = SEQC_MOD;                                           
\
 } while (0)
 
 #define NDF_NO_DVP_RELE                0x00000001
diff --git a/sys/sys/param.h b/sys/sys/param.h
index 41db9a1675f7..4c43839c297e 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -60,7 +60,7 @@
  *             in the range 5 to 9.
  */
 #undef __FreeBSD_version
-#define __FreeBSD_version 1300510      /* Master, propagated to newvers */
+#define __FreeBSD_version 1300511      /* Master, propagated to newvers */
 
 /*
  * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h
index 544012089046..0365cb76601e 100644
--- a/sys/ufs/ffs/ffs_extern.h
+++ b/sys/ufs/ffs/ffs_extern.h
@@ -178,7 +178,8 @@ int softdep_request_cleanup(struct fs *, struct vnode *,
            struct ucred *, int);
 int    softdep_prerename(struct vnode *, struct vnode *, struct vnode *,
            struct vnode *);
-int    softdep_prelink(struct vnode *, struct vnode *);
+int    softdep_prelink(struct vnode *, struct vnode *,
+           struct componentname *);
 void   softdep_setup_freeblocks(struct inode *, off_t, int);
 void   softdep_setup_inomapdep(struct buf *, struct inode *, ino_t, int);
 void   softdep_setup_blkmapdep(struct buf *, struct mount *, ufs2_daddr_t,
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index dbd08905d953..f6dd5c776611 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -621,9 +621,10 @@ softdep_prerename(fdvp, fvp, tdvp, tvp)
 }
 
 int
-softdep_prelink(dvp, vp)
+softdep_prelink(dvp, vp, cnp)
        struct vnode *dvp;
        struct vnode *vp;
+       struct componentname *cnp;
 {
 
        panic("softdep_prelink called");
@@ -3361,11 +3362,13 @@ softdep_prerename(fdvp, fvp, tdvp, tvp)
  * syscall must be restarted at top level from the lookup.
  */
 int
-softdep_prelink(dvp, vp)
+softdep_prelink(dvp, vp, cnp)
        struct vnode *dvp;
        struct vnode *vp;
+       struct componentname *cnp;
 {
        struct ufsmount *ump;
+       struct nameidata *ndp;
 
        ASSERT_VOP_ELOCKED(dvp, "prelink dvp");
        if (vp != NULL)
@@ -3381,13 +3384,28 @@ softdep_prelink(dvp, vp)
        if (journal_space(ump, 0) || (vp != NULL && IS_SNAPSHOT(VTOI(vp))))
                return (0);
 
+       /*
+        * Check if the journal space consumption can in theory be
+        * accounted on dvp and vp.  If the vnodes metadata was not
+        * changed comparing with the previous round-trip into
+        * softdep_prelink(), as indicated by the seqc generation
+        * recorded in the nameidata, then there is no point in
+        * starting the sync.
+        */
+       ndp = __containerof(cnp, struct nameidata, ni_cnd);
+       if (!seqc_in_modify(ndp->ni_dvp_seqc) &&
+           vn_seqc_consistent(dvp, ndp->ni_dvp_seqc) &&
+           (vp == NULL || (!seqc_in_modify(ndp->ni_vp_seqc) &&
+           vn_seqc_consistent(vp, ndp->ni_vp_seqc))))
+               return (0);
+
        stat_journal_low++;
        if (vp != NULL) {
                VOP_UNLOCK(dvp);
                ffs_syncvnode(vp, MNT_NOWAIT, 0);
                vn_lock_pair(dvp, false, vp, true);
                if (dvp->v_data == NULL)
-                       return (ERELOOKUP);
+                       goto out;
        }
        if (vp != NULL)
                VOP_UNLOCK(vp);
@@ -3398,7 +3416,7 @@ softdep_prelink(dvp, vp)
                vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                if (vp->v_data == NULL) {
                        vn_lock_pair(dvp, false, vp, true);
-                       return (ERELOOKUP);
+                       goto out;
                }
                ACQUIRE_LOCK(ump);
                process_removes(vp);
@@ -3408,7 +3426,7 @@ softdep_prelink(dvp, vp)
                vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
                if (dvp->v_data == NULL) {
                        vn_lock_pair(dvp, true, vp, false);
-                       return (ERELOOKUP);
+                       goto out;
                }
        }
 
@@ -3427,6 +3445,10 @@ softdep_prelink(dvp, vp)
        FREE_LOCK(ump);
 
        vn_lock_pair(dvp, false, vp, false);
+out:
+       ndp->ni_dvp_seqc = vn_seqc_read_any(dvp);
+       if (vp != NULL)
+               ndp->ni_vp_seqc = vn_seqc_read_any(vp);
        return (ERELOOKUP);
 }
 
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
index b0fb1b74b900..2dfc2e24f772 100644
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -1010,7 +1010,7 @@ ufs_remove(ap)
            (VTOI(dvp)->i_flags & APPEND))
                return (EPERM);
        if (DOINGSUJ(dvp)) {
-               error = softdep_prelink(dvp, vp);
+               error = softdep_prelink(dvp, vp, ap->a_cnp);
                if (error != 0) {
                        MPASS(error == ERELOOKUP);
                        return (error);
@@ -1075,7 +1075,7 @@ ufs_link(ap)
 #endif
 
        if (DOINGSUJ(tdvp)) {
-               error = softdep_prelink(tdvp, vp);
+               error = softdep_prelink(tdvp, vp, cnp);
                if (error != 0) {
                        MPASS(error == ERELOOKUP);
                        return (error);
@@ -1147,7 +1147,7 @@ ufs_whiteout(ap)
 
        if (DOINGSUJ(dvp) && (ap->a_flags == CREATE ||
            ap->a_flags == DELETE)) {
-               error = softdep_prelink(dvp, NULL);
+               error = softdep_prelink(dvp, NULL, cnp);
                if (error != 0) {
                        MPASS(error == ERELOOKUP);
                        return (error);
@@ -1962,7 +1962,7 @@ ufs_mkdir(ap)
        }
 
        if (DOINGSUJ(dvp)) {
-               error = softdep_prelink(dvp, NULL);
+               error = softdep_prelink(dvp, NULL, cnp);
                if (error != 0) {
                        MPASS(error == ERELOOKUP);
                        return (error);
@@ -2226,7 +2226,7 @@ ufs_rmdir(ap)
                goto out;
        }
        if (DOINGSUJ(dvp)) {
-               error = softdep_prelink(dvp, vp);
+               error = softdep_prelink(dvp, vp, cnp);
                if (error != 0) {
                        MPASS(error == ERELOOKUP);
                        return (error);
@@ -2751,7 +2751,7 @@ ufs_makeinode(mode, dvp, vpp, cnp, callfunc)
                return (EINVAL);
        }
        if (DOINGSUJ(dvp)) {
-               error = softdep_prelink(dvp, NULL);
+               error = softdep_prelink(dvp, NULL, cnp);
                if (error != 0) {
                        MPASS(error == ERELOOKUP);
                        return (error);
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to