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
This commit is contained in:
parent
bdefcb6959
commit
158cc900bb
@ -402,6 +402,7 @@ int tmpfs_alloc_dirent(struct tmpfs_mount *, struct tmpfs_node *,
|
||||
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 *);
|
||||
|
@ -429,6 +429,36 @@ tmpfs_free_dirent(struct tmpfs_mount *tmp, struct tmpfs_dirent *de)
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
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;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user