diff --git a/sys/vm/vm_vmspace.c b/sys/vm/vm_vmspace.c --- a/sys/vm/vm_vmspace.c +++ b/sys/vm/vm_vmspace.c @@ -223,8 +223,24 @@ error = ENOENT; if ((ve = vkernel_find_vmspace(vkp, uap->id, 1)) != NULL) { error = vmspace_entry_delete(ve, vkp, 1); + /* + * DF-0952: vkernel_find_vmspace() bumped ve->refs by 1 + * (documented "caller must drop"). On success + * vmspace_entry_delete() consumes that ref atomically + * via the cmpset that installs VKE_REF_DELETED, and we + * then drop the on-tree cache ref via cache_drop. + * + * On EBUSY the cmpset did NOT consume the find's ref, so + * we must drop it explicitly here. Previously we leaked + * one ref per failed destroy, permanently inflating + * ve->refs until proc-exit's rb_vmspace_delete() called + * vmspace_entry_delete(ve, vkp, 0) and panicked with + * "rb_vmspace_delete: invalid refs N". + */ if (error == 0) vmspace_entry_cache_drop(ve); + else + vmspace_entry_drop(ve); } lwkt_reltoken(&vkp->token);