* arbitrarily block. The scanning code guarentees consistency of operation
* even if the slow function deletes or moves the node, or blocks and some
* other thread deletes or moves the node.
+ *
+ * NOTE: We hold vmobj_token to prevent a VM object from being destroyed
+ * out from under the fastfunc()'s vnode test. It will not prevent
+ * v_object from getting NULL'd out but it will ensure that the
+ * pointer (if we race) will remain stable.
*/
int
vmntvnodescan(
int count = 0;
lwkt_gettoken(&mntvnode_token);
+ lwkt_gettoken(&vmobj_token);
/*
* If asked to do one pass stop after iterating available vnodes.
info.vp = TAILQ_NEXT(vp, v_nmntvnodes);
}
TAILQ_REMOVE(&mntvnodescan_list, &info, entry);
+ lwkt_reltoken(&vmobj_token);
lwkt_reltoken(&mntvnode_token);
return(r);
}
/*
* Returns non-zero if the vnode is a candidate for lazy msyncing.
+ *
+ * NOTE: v_object is not stable (this scan can race), however the
+ * mntvnodescan code holds vmobj_token so any VM object we
+ * do find will remain stable storage.
*/
static __inline int
vshouldmsync(struct vnode *vp)
{
+ vm_object_t object;
+
if (vp->v_auxrefs != 0 || vp->v_sysref.refcnt > 0)
return (0); /* other holders */
- if (vp->v_object &&
- (vp->v_object->ref_count || vp->v_object->resident_page_count)) {
- return (0);
- }
+ object = vp->v_object;
+ cpu_ccfence();
+ if (object && (object->ref_count || object->resident_page_count))
+ return(0);
return (1);
}