From owner-svn-src-all@FreeBSD.ORG Thu May 2 18:44:32 2013 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id E2AD2FDF; Thu, 2 May 2013 18:44:32 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id D3A2A2000; Thu, 2 May 2013 18:44:32 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.6/8.14.6) with ESMTP id r42IiWEO072438; Thu, 2 May 2013 18:44:32 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.6/8.14.5/Submit) id r42IiWL1072432; Thu, 2 May 2013 18:44:32 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <201305021844.r42IiWL1072432@svn.freebsd.org> From: Konstantin Belousov Date: Thu, 2 May 2013 18:44:32 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r250189 - head/sys/fs/tmpfs X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 02 May 2013 18:44:33 -0000 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);