Move UNIX domain sockets garbage collector out of `unp_lock.
authormvs <mvs@openbsd.org>
Tue, 16 Nov 2021 08:56:19 +0000 (08:56 +0000)
committermvs <mvs@openbsd.org>
Tue, 16 Nov 2021 08:56:19 +0000 (08:56 +0000)
commit7429db109c10a5df9f7d3067e1d6de09f03a98b2
treea78690c6dee800c2911fcf521d09409761b54c2f
parent48b5580491f3b0355d402c50087e539b75f3f9a3
Move UNIX domain sockets garbage collector out of `unp_lock.

Except `unp_ino' this leaves only per-socket data protected by
`unp_lock'. The `unp_ino' protection is not the big deal and will be
done with mutex(9) in the future diff.

The garbage collector flags moved from from `unp_flags' to unp_gcflags'.

The two new locks introduced to protect garbage collector data. The
`unp_gc_lock' rwlock(9) protects `unp_defer', `unp_gcing', `unp_gcflags'
and `unp_link' list. The `unp_df_lock' protects `ud_link' list.

We need to simultaneously lock `unp_gc_lock' and `unp_lock'. When we
perform unp_attach() or unp_detach() we link PCB to `unp_link' list with
`unp_lock' held. But when unp_gc() does `unp_link' list walkthrough with
the `unp_gc_lock' lock held it should lock socket while performs
`so_rcv' buffer scan and the lock order should be the opposite.

In the future diff `unp_lock' will be replaced by per-socket `so_lock'
so it's better to enforce `unp_gc_lock' -> `unp_lock' (solock()) lock
order and release `unp_lock' in the unp_attach() and unp_detach() paths.
The previously committed diffs made this safe.

The `unp_df_lock' introduced because the `unp_lock' and `unp_gc_lock'
state are unknown when unp_discard() called. Since it touches only
`ud_link' list the re-lock dances are unwanted in this path. Also this
keeps M_WAITOK allocation outside rwlock(9) when unp_discard() called
from unp_externalize() error path.

ok bluhm@
sys/kern/uipc_usrreq.c
sys/sys/unpcb.h