Author: kib
Date: Thu Aug 29 07:45:23 2019
New Revision: 351597
URL: https://svnweb.freebsd.org/changeset/base/351597

Log:
  UFS: stop reusing the vnode for reallocated inode.
  
  In ffs_valloc(), force reclaim existing vnode on inode reuse, instead
  of trying to re-initialize the same vnode for new purposes.  This is
  done in preparation of changes to the vp->v_object lifecycle handling.
  
  A new FFSV_REPLACE flag to ffs_vgetf() directs the function to
  vgone(9) the vnode if found in vfs hash, instead of returning it.
  
  Reviewed by:  markj, mckusick
  Tested by:    pho
  Sponsored by: The FreeBSD Foundation
  Differential revision:        https://reviews.freebsd.org/D21412

Modified:
  head/sys/ufs/ffs/ffs_alloc.c
  head/sys/ufs/ffs/ffs_extern.h
  head/sys/ufs/ffs/ffs_vfsops.c

Modified: head/sys/ufs/ffs/ffs_alloc.c
==============================================================================
--- head/sys/ufs/ffs/ffs_alloc.c        Thu Aug 29 07:39:31 2019        
(r351596)
+++ head/sys/ufs/ffs/ffs_alloc.c        Thu Aug 29 07:45:23 2019        
(r351597)
@@ -1137,10 +1137,15 @@ retry:
                                        (allocfcn_t *)ffs_nodealloccg);
        if (ino == 0)
                goto noinodes;
-       error = ffs_vget(pvp->v_mount, ino, LK_EXCLUSIVE, vpp);
+
+       /*
+        * Get rid of the cached old vnode, force allocation of a new vnode
+        * for this inode.
+        */
+       error = ffs_vgetf(pvp->v_mount, ino, LK_EXCLUSIVE, vpp, FFSV_REPLACE);
        if (error) {
                error1 = ffs_vgetf(pvp->v_mount, ino, LK_EXCLUSIVE, vpp,
-                   FFSV_FORCEINSMQ);
+                   FFSV_FORCEINSMQ | FFSV_REPLACE);
                ffs_vfree(pvp, ino, mode);
                if (error1 == 0) {
                        ip = VTOI(*vpp);
@@ -1176,7 +1181,6 @@ dup_alloc:
                ip->i_din2->di_birthtime = ts.tv_sec;
                ip->i_din2->di_birthnsec = ts.tv_nsec;
        }
-       ufs_prepare_reclaim(*vpp);
        ip->i_flag = 0;
        (*vpp)->v_vflag = 0;
        (*vpp)->v_type = VNON;

Modified: head/sys/ufs/ffs/ffs_extern.h
==============================================================================
--- head/sys/ufs/ffs/ffs_extern.h       Thu Aug 29 07:39:31 2019        
(r351596)
+++ head/sys/ufs/ffs/ffs_extern.h       Thu Aug 29 07:45:23 2019        
(r351597)
@@ -121,6 +121,7 @@ void        process_deferred_inactive(struct mount *mp);
  * Flags to ffs_vgetf
  */
 #define        FFSV_FORCEINSMQ 0x0001
+#define        FFSV_REPLACE    0x0002
 
 /*
  * Flags to ffs_reload

Modified: head/sys/ufs/ffs/ffs_vfsops.c
==============================================================================
--- head/sys/ufs/ffs/ffs_vfsops.c       Thu Aug 29 07:39:31 2019        
(r351596)
+++ head/sys/ufs/ffs/ffs_vfsops.c       Thu Aug 29 07:45:23 2019        
(r351597)
@@ -1671,9 +1671,17 @@ ffs_vgetf(mp, ino, flags, vpp, ffs_flags)
        struct vnode *vp;
        int error;
 
+       MPASS((ffs_flags & FFSV_REPLACE) == 0 || (flags & LK_EXCLUSIVE) != 0);
+
        error = vfs_hash_get(mp, ino, flags, curthread, vpp, NULL, NULL);
-       if (error || *vpp != NULL)
+       if (error != 0)
                return (error);
+       if (*vpp != NULL) {
+               if ((ffs_flags & FFSV_REPLACE) == 0)
+                       return (0);
+               vgone(*vpp);
+               vput(*vpp);
+       }
 
        /*
         * We must promote to an exclusive lock for vnode creation.  This
@@ -1735,8 +1743,19 @@ ffs_vgetf(mp, ino, flags, vpp, ffs_flags)
        }
        vp->v_vflag &= ~VV_FORCEINSMQ;
        error = vfs_hash_insert(vp, ino, flags, curthread, vpp, NULL, NULL);
-       if (error || *vpp != NULL)
+       if (error != 0)
                return (error);
+       if (*vpp != NULL) {
+               /*
+                * Calls from ffs_valloc() (i.e. FFSV_REPLACE set)
+                * operate on empty inode, which must not be found by
+                * other threads until fully filled.  Vnode for empty
+                * inode must be not re-inserted on the hash by other
+                * thread, after removal by us at the beginning.
+                */
+               MPASS((ffs_flags & FFSV_REPLACE) == 0);
+               return (0);
+       }
 
        /* Read in the disk contents for the inode, copy into the inode. */
        error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to