+
+int kinfo_vdebug = 1;
+int kinfo_vgetfailed;
+#define KINFO_VNODESLOP 10
+/*
+ * Dump vnode list (via kinfo).
+ * Copyout address of vnode followed by vnode.
+ */
+kinfo_vnode(op, where, acopysize, arg, aneeded)
+ char *where;
+ int *acopysize, *aneeded;
+{
+ register struct mount *mp = rootfs;
+ struct mount *omp;
+ struct vnode *vp;
+ register needed = 0;
+ register char *bp = where, *savebp;
+ char *ewhere = where + *acopysize;
+ int error;
+
+#define VPTRSZ sizeof (struct vnode *)
+#define VNODESZ sizeof (struct vnode)
+ if (where == NULL) {
+ *aneeded = (numvnodes + KINFO_VNODESLOP) * (VPTRSZ + VNODESZ);
+ return (0);
+ }
+
+ do {
+ if (vfs_busy(mp)) {
+ mp = mp->mnt_next;
+ continue;
+ }
+ savebp = bp;
+again:
+ for (vp = mp->mnt_mounth; vp; vp = vp->v_mountf) {
+ /*
+ * Check that the vp is still associated with
+ * this filesystem. RACE: could have been
+ * recycled onto the same filesystem.
+ */
+ if (vp->v_mount != mp) {
+ if (kinfo_vdebug)
+ printf("kinfo: vp changed\n");
+ bp = savebp;
+ goto again;
+ }
+ if ((bp + VPTRSZ + VNODESZ <= ewhere) &&
+ ((error = copyout((caddr_t)&vp, bp, VPTRSZ)) ||
+ (error = copyout((caddr_t)vp, bp + VPTRSZ,
+ VNODESZ))))
+ return (error);
+ bp += VPTRSZ + VNODESZ;
+ }
+ omp = mp;
+ mp = mp->mnt_next;
+ vfs_unbusy(omp);
+ } while (mp != rootfs);
+
+ *aneeded = bp - where;
+ if (bp > ewhere)
+ *acopysize = ewhere - where;
+ else
+ *acopysize = bp - where;
+ return (0);
+}