Author: kib
Date: Thu May  2 18:44:31 2013
New Revision: 250189
URL: http://svnweb.freebsd.org/changeset/base/250189

Log:
  For the new regular tmpfs vnode, v_object is initialized before
  insmntque() is called.  The standard insmntque destructor resets the
  vop vector to deadfs one, and calls vgone() on the vnode.  As result,
  v_object is kept unchanged, which triggers an assertion in the reclaim
  code, on instmntque() failure.  Also, in this case, OBJ_TMPFS flag on
  the backed vm object is not cleared.
  
  Provide the tmpfs insmntque() destructor which properly clears
  OBJ_TMPFS flag and resets v_object.
  
  Reported and tested by:       pho
  Sponsored by: The FreeBSD Foundation

Modified:
  head/sys/fs/tmpfs/tmpfs.h
  head/sys/fs/tmpfs/tmpfs_subr.c
  head/sys/fs/tmpfs/tmpfs_vnops.c

Modified: head/sys/fs/tmpfs/tmpfs.h
==============================================================================
--- head/sys/fs/tmpfs/tmpfs.h   Thu May  2 18:36:52 2013        (r250188)
+++ head/sys/fs/tmpfs/tmpfs.h   Thu May  2 18:44:31 2013        (r250189)
@@ -402,6 +402,7 @@ int tmpfs_alloc_dirent(struct tmpfs_moun
            const char *, u_int, struct tmpfs_dirent **);
 void   tmpfs_free_dirent(struct tmpfs_mount *, struct tmpfs_dirent *);
 void   tmpfs_dirent_init(struct tmpfs_dirent *, const char *, u_int);
+void   tmpfs_destroy_vobject(struct vnode *vp, vm_object_t obj);
 int    tmpfs_alloc_vp(struct mount *, struct tmpfs_node *, int,
            struct vnode **);
 void   tmpfs_free_vp(struct vnode *);

Modified: head/sys/fs/tmpfs/tmpfs_subr.c
==============================================================================
--- head/sys/fs/tmpfs/tmpfs_subr.c      Thu May  2 18:36:52 2013        
(r250188)
+++ head/sys/fs/tmpfs/tmpfs_subr.c      Thu May  2 18:44:31 2013        
(r250189)
@@ -429,6 +429,36 @@ tmpfs_free_dirent(struct tmpfs_mount *tm
 
 /* --------------------------------------------------------------------- */
 
+void
+tmpfs_destroy_vobject(struct vnode *vp, vm_object_t obj)
+{
+
+       if (vp->v_type != VREG || obj == NULL)
+               return;
+
+       VM_OBJECT_WLOCK(obj);
+       VI_LOCK(vp);
+       vm_object_clear_flag(obj, OBJ_TMPFS);
+       obj->un_pager.swp.swp_tmpfs = NULL;
+       VI_UNLOCK(vp);
+       VM_OBJECT_WUNLOCK(obj);
+}
+
+/*
+ * Need to clear v_object for insmntque failure.
+ */
+static void
+tmpfs_insmntque_dtr(struct vnode *vp, void *dtr_arg)
+{
+
+       tmpfs_destroy_vobject(vp, vp->v_object);
+       vp->v_object = NULL;
+       vp->v_data = NULL;
+       vp->v_op = &dead_vnodeops;
+       vgone(vp);
+       vput(vp);
+}
+
 /*
  * Allocates a new vnode for the node node or returns a new reference to
  * an existing one if the node had already a vnode referencing it.  The
@@ -540,7 +570,7 @@ loop:
                panic("tmpfs_alloc_vp: type %p %d", node, (int)node->tn_type);
        }
 
-       error = insmntque(vp, mp);
+       error = insmntque1(vp, mp, tmpfs_insmntque_dtr, NULL);
        if (error)
                vp = NULL;
 

Modified: head/sys/fs/tmpfs/tmpfs_vnops.c
==============================================================================
--- head/sys/fs/tmpfs/tmpfs_vnops.c     Thu May  2 18:36:52 2013        
(r250188)
+++ head/sys/fs/tmpfs/tmpfs_vnops.c     Thu May  2 18:44:31 2013        
(r250189)
@@ -1468,23 +1468,12 @@ tmpfs_reclaim(struct vop_reclaim_args *v
 
        struct tmpfs_mount *tmp;
        struct tmpfs_node *node;
-       vm_object_t obj;
 
        node = VP_TO_TMPFS_NODE(vp);
        tmp = VFS_TO_TMPFS(vp->v_mount);
 
-       if (node->tn_type == VREG) {
-               obj = node->tn_reg.tn_aobj;
-               if (obj != NULL) {
-                       /* Instead of vnode_destroy_vobject() */
-                       VM_OBJECT_WLOCK(obj);
-                       VI_LOCK(vp);
-                       vm_object_clear_flag(obj, OBJ_TMPFS);
-                       obj->un_pager.swp.swp_tmpfs = NULL;
-                       VI_UNLOCK(vp);
-                       VM_OBJECT_WUNLOCK(obj);
-               }
-       }
+       if (vp->v_type == VREG)
+               tmpfs_destroy_vobject(vp, node->tn_reg.tn_aobj);
        vp->v_object = NULL;
        cache_purge(vp);
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to