Download raw body.
Relax sockets splicing locking
> On 4 Jan 2025, at 16:34, Alexander Bluhm <bluhm@openbsd.org> wrote:
>
> On Sat, Jan 04, 2025 at 02:06:14PM +0300, Vitaliy Makkoveev wrote:
>> On Fri, Jan 03, 2025 at 05:22:51PM +0300, Vitaliy Makkoveev wrote:
>>> Sockets splicing works around sockets buffers which have their own locks
>>> for all socket types, especially sblock() on `so_snd' which keeps
>>> sockets being spliced.
>>>
>>> - sosplice() does read-only sockets options and state checks, the only
>>> modification is `so_sp' assignment. The SB_SPLICE bit modification,
>>> `ssp_socket' and `ssp_soback' assignment protected with `sb_mtx'
>>> mutex(9). PCB layer does corresponding checks with `sb_mtx' held, so
>>> shared solock() is pretty enough in sosplice() path. Introduce
>>> special sosplice_solock_pair() for that purpose.
>>>
>>> - sounsplice() requires shared socket lock only around so{r,w}wakeup
>>> calls.
>>>
>>> - Push exclusive solock() down to tcp(4) case of somove(). Such sockets
>>> are not ready do unlocked somove() yet.
>>>
>>
>> A little bit updated. The "Make WITNESS happy..." comment is not MP
>> specific, so rewrite it as XXX:
>>
>> + /*
>> + * XXX: Make WITNESS happy. AF_INET and AF_INET6 sockets could be
>> + * spliced together.
>> + */
>>
>> Also whitespace fixed.
>
> You have this construct several times:
>
>> + sosp = soref(so->so_sp->ssp_socket);
>> sounsplice(so, so->so_sp->ssp_socket, 0);
>> + sorele(sosp);
>
> Would it be nicer to use the refed socket in sounsplice()?
> sounsplice(so, sosp, 0);
> I practice it should make no difference.
>
We need the extra reference to to the first socket while dying
socket is spliced back, meanwhile the extra reference for
second socket is not required:
if (issplicedback(so)) {
int freeing = SOSP_FREEING_WRITE;
if (so->so_sp->ssp_soback == so)
freeing |= SOSP_FREEING_READ;
sounsplice(so->so_sp->ssp_soback, so, freeing);
}
sbunlock(&soback->so_rcv);
sorele(soback);
Anyway, this is not the last touch to sounsplice(). I suspect
sowwakeup() could be done lockless.
> I have tested it with my regress and netlink setup. My perform
> testing machines are currently busy with other tests.
>
> We have no propper regression tests for splicing and unsplicing
> under heavy load. I am currently trying to write a test.
>
We need something like multithreaded attempts of simultaneous
splicing and unsplicing one socket to itself. Or the same but
for two sockets.
Relax sockets splicing locking