The entire thing needs to be reworked. Either the code needs to be reworked to integrate it better with UMA (in particular so that it knows how to reclaim free vnodes) OR it needs to rely on the allocator to a lesser degree. I have a WIP patch for the former case which adds a callback to UMA.
In the meantime:
The vnode free list lock is only needed to reclaim free vnodes or kick the vnlru thread (or to block and not miss a wake up (but note the sleep has a timeout so this would not be a correctness issue)). Try to get away without the lock by just doing an atomic increment.
The lock is contended e.g., during poudriere -j 104 where about half of all acquires come from vnode allocation code.
I can change this to a fcmpset loop if fetchadd seems too lax. The patch can be split into 2 - new routines + the atomic part. While I don't expect the code to stay in this form in the long run, the benefit is that the change is eligible to be MFCed to stable/12.