multipath -u: test socket connection in non-blocking mode
authorMartin Wilck <mwilck@suse.com>
Wed, 24 Apr 2019 09:07:59 +0000 (11:07 +0200)
committerChristophe Varoqui <christophe.varoqui@opensvc.com>
Wed, 3 Jul 2019 05:59:48 +0000 (07:59 +0200)
commit37506787f609cba6980f2022482a2eebb4ed0605
treea4a004f7821a5981828f22ad7c4c1583ff915d8d
parentebbb56f28d56816423133b3d679b658c725c4685
multipath -u: test socket connection in non-blocking mode

Since commit d7188fcd "multipathd: start daemon after udev trigger",
multipathd startup is delayed during boot until after "udev settle"
terminates. But "multipath -u" is run by udev workers for storage devices,
and attempts to connect to the multipathd socket. This causes a start job
for multipathd to be scheduled by systemd, but that job won't be started
until "udev settle" finishes. This is not a problem on systems with 129 or
less storage units, because the connect() call of "multipath -u" will
succeed anyway. But on larger systems, the listen backlog of the systemd
socket can be exceeded, which causes connect() calls for the socket to
block until multipathd starts up and begins calling accept(). This creates
a deadlock situation, because "multipath -u" (called by udev workers)
blocks, and thus "udev settle" doesn't finish, delaying multipathd
startup. This situation then persists until either the workers or "udev
settle" time out. In the former case, path devices might be misclassified
as non-multipath devices by "multipath -u".

Fix this by using a non-blocking socket fd for connect() and interpret the
errno appropriately.

This patch reverts most of the changes from commit 8cdf6661 "multipath:
check on multipathd without starting it". Instead, "multipath -u" does
access the socket and start multipath again (which is what we want IMO),
but it is now able to detect and handle the "full backlog" situation.

Signed-off-by: Martin Wilck <mwilck@suse.com>
V2:

Use same error reporting convention in __mpath_connect() as in
mpath_connect() (Hannes Reinecke). We can't easily change the latter,
because it's part of the "public" libmpathcmd API.
libmpathcmd/mpath_cmd.c
libmpathcmd/mpath_cmd.h
multipath/main.c