Author: bdrewery
Date: Mon Aug 28 19:29:51 2017
New Revision: 322978
URL: https://svnweb.freebsd.org/changeset/base/322978

Log:
  Allow vdrop() of a vnode not yet on the per-mount list after r306512.
  
  The old code allowed calling vdrop() before insmntque() to place the vnode 
back
  onto the freelist for later recycling.  Some downstream consumers may rely on
  this support.  Normally insmntque() failing is fine since is uses vgone() and
  immediately frees the vnode rather than attempting to add it to the freelist 
if
  vdrop() were used instead.
  
  Also assert that vhold() cannot be used on such a vnode.
  
  Reviewed by:  kib, cem, markj
  Sponsored by: Dell EMC Isilon
  Differential Revision:        https://reviews.freebsd.org/D12126

Modified:
  head/sys/kern/vfs_subr.c

Modified: head/sys/kern/vfs_subr.c
==============================================================================
--- head/sys/kern/vfs_subr.c    Mon Aug 28 19:27:33 2017        (r322977)
+++ head/sys/kern/vfs_subr.c    Mon Aug 28 19:29:51 2017        (r322978)
@@ -2861,6 +2861,8 @@ _vhold(struct vnode *vp, bool locked)
         * Remove a vnode from the free list, mark it as in use,
         * and put it on the active list.
         */
+       VNASSERT(vp->v_mount != NULL, vp,
+           ("_vhold: vnode not on per mount vnode list"));
        mp = vp->v_mount;
        mtx_lock(&mp->mnt_listmtx);
        if ((vp->v_mflag & VMP_TMPMNTFREELIST) != 0) {
@@ -2935,21 +2937,35 @@ _vdrop(struct vnode *vp, bool locked)
                if ((vp->v_iflag & VI_OWEINACT) == 0) {
                        vp->v_iflag &= ~VI_ACTIVE;
                        mp = vp->v_mount;
-                       mtx_lock(&mp->mnt_listmtx);
-                       if (active) {
-                               TAILQ_REMOVE(&mp->mnt_activevnodelist, vp,
+                       if (mp != NULL) {
+                               mtx_lock(&mp->mnt_listmtx);
+                               if (active) {
+                                       TAILQ_REMOVE(&mp->mnt_activevnodelist,
+                                           vp, v_actfreelist);
+                                       mp->mnt_activevnodelistsize--;
+                               }
+                               TAILQ_INSERT_TAIL(&mp->mnt_tmpfreevnodelist,
+                                   vp, v_actfreelist);
+                               mp->mnt_tmpfreevnodelistsize++;
+                               vp->v_iflag |= VI_FREE;
+                               vp->v_mflag |= VMP_TMPMNTFREELIST;
+                               VI_UNLOCK(vp);
+                               if (mp->mnt_tmpfreevnodelistsize >=
+                                   mnt_free_list_batch)
+                                       vnlru_return_batch_locked(mp);
+                               mtx_unlock(&mp->mnt_listmtx);
+                       } else {
+                               VNASSERT(active == 0, vp,
+                                   ("vdropl: active vnode not on per mount "
+                                   "vnode list"));
+                               mtx_lock(&vnode_free_list_mtx);
+                               TAILQ_INSERT_TAIL(&vnode_free_list, vp,
                                    v_actfreelist);
-                               mp->mnt_activevnodelistsize--;
+                               freevnodes++;
+                               vp->v_iflag |= VI_FREE;
+                               VI_UNLOCK(vp);
+                               mtx_unlock(&vnode_free_list_mtx);
                        }
-                       TAILQ_INSERT_TAIL(&mp->mnt_tmpfreevnodelist, vp,
-                           v_actfreelist);
-                       mp->mnt_tmpfreevnodelistsize++;
-                       vp->v_iflag |= VI_FREE;
-                       vp->v_mflag |= VMP_TMPMNTFREELIST;
-                       VI_UNLOCK(vp);
-                       if (mp->mnt_tmpfreevnodelistsize >= mnt_free_list_batch)
-                               vnlru_return_batch_locked(mp);
-                       mtx_unlock(&mp->mnt_listmtx);
                } else {
                        VI_UNLOCK(vp);
                        counter_u64_add(free_owe_inact, 1);
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to