vio: Fix signal handling and locking in sysctl path
Commits
f0b002d01d5 "Release the netlock when sleeping for control
messages in in vioioctl()" and
126b881f71 "Insert a workaround for
per-ifp ioctl being called w/o NET_LOCK()." in vio(4) fixed a deadlock
but may cause a crash with a protection fault trap if addresses are
added/removed concurrently.
The actual issue is that signals are not handled correctly while
sleeping. After a signal, there is a race condition where sc_ctrl_inuse
is first set to FREE and then the interrupt handler sets it to DONE,
causing a hang in the next vio_wait_ctrl() call.
To fix it:
* Revert the NET_LOCK unlocking work-around.
* Remove PCATCH from the sleep call when we wait for control queue,
avoiding the race with vio_ctrleof(). To ensure that we don't hang
forever, use a 5 second timeout.
* If the timeout is hit, or if the hypervisor has set the
DEVICE_NEEDS_RESET status bit, do not try to use the control queue
until the next ifconfig down/up which resets the device.
* In order to allow reading the device status from device drivers, add a
new interface to the virtio transport drivers.
* Avoid a crash if there is outgoing traffic while doing ifconfig down.
OK bluhm@