• Johannes Berg's avatar
    um: virtio: Keep reading on -EAGAIN · 7e607460
    Johannes Berg authored
    When we get an interrupt from the socket getting readable,
    and start reading, there's a possibility for a race. This
    depends on the implementation of the device, but e.g. with
    qemu's libvhost-user, we can see:
    
     device                 virtio_uml
    ---------------------------------------
      write header
                             get interrupt
                             read header
                             read body -> returns -EAGAIN
      write body
    
    The -EAGAIN return is because the socket is non-blocking,
    and then this leads us to abandon this message.
    
    In fact, we've already read the header, so when the get
    another signal/interrupt for the body, we again read it
    as though it's a new message header, and also abandon it
    for the same reason (wrong size etc.)
    
    This essentially breaks things, and if that message was
    one that required a response, it leads to a deadlock as
    the device is waiting for the response but we'll never
    reply.
    
    Fix this by spinning on -EAGAIN as well when we read the
    message body. We need to handle -EAGAIN as "no message"
    while reading the header, since we share an interrupt.
    
    Note that this situation is highly unlikely to occur in
    normal usage, since there will be very few messages and
    only in the startup phase. With the inband call feature
    this does tend to happen (eventually) though.
    Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
    Signed-off-by: default avatarRichard Weinberger <richard@nod.at>
    7e607460
virtio_uml.c 29.5 KB