diff --git a/sys/vm/vm_swap.c b/sys/vm/vm_swap.c index 0000000..1111111 100644 --- a/sys/vm/vm_swap.c +++ b/sys/vm/vm_swap.c @@ -411,6 +411,17 @@ if (error) return (error); + /* + * Acquire vm_token before swap_mtx to serialize blist tree + * mutations against the swap pager's swp_pager_getswapspace()/ + * swp_pager_freeswapspace(), which also hold vm_token. Without + * this, swapoff_one()'s blist_fill()/blist_destroy()/blist_resize() + * race with concurrent blist_allocat()/blist_free() and corrupt + * the global swapblist radix tree. + * + * Lock order matches swaponvp(): vm_token outer, swap_mtx inner. + */ + lwkt_gettoken(&vm_token); mtx_lock(&swap_mtx); vp = NULL; error = nlookup_init(&nd, uap->name, UIO_USERSPACE, NLC_FOLLOW); @@ -434,6 +445,7 @@ done: mtx_unlock(&swap_mtx); + lwkt_reltoken(&vm_token); return (error); }