• Alex Elder's avatar
    libceph: requeue only sent requests when kicking · e02493c0
    Alex Elder authored
    The osd expects incoming requests for a given object from a given
    client to arrive in order, with the tid for each request being
    greater than the tid for requests that have already arrived.  This
    patch fixes two places the osd client might not maintain that
    ordering.
    
    For the osd client, the connection fault method is osd_reset().
    That function calls __reset_osd() to close and re-open the
    connection, then calls __kick_osd_requests() to cause all
    outstanding requests for the affected osd to be re-sent after
    the connection has been re-established.
    
    When an osd is reset, any in-flight messages will need to be
    re-sent.  An osd client maintains distinct lists for unsent and
    in-flight messages.  Meanwhile, an osd maintains a single list of
    all its requests (both sent and un-sent).  (Each message is linked
    into two lists--one for the osd client and one list for the osd.)
    
    To process an osd "kick" operation, the request list for the *osd*
    is traversed, and each request is moved off whichever osd *client*
    list it was on (unsent or sent) and placed onto the osd client's
    unsent list.  (It remains where it is on the osd's request list.)
    
    When that is done, osd_reset() calls __send_queued() to cause each
    of the osd client's unsent messages to be sent.
    
    OK, with that background...
    
    As the osd request list is traversed each request is prepended to
    the osd client's unsent list in the order they're seen.  The effect
    of this is to reverse the order of these requests as they are put
    (back) onto the unsent list.
    
    Instead, build up a list of only the requests for an osd that have
    already been sent (by checking their r_sent flag values).  Once an
    unsent request is found, stop examining requests and prepend the
    requests that need re-sending to the osd client's unsent list.
    
    Preserve the original order of requests in the process (previously
    re-queued requests were reversed in this process).  Because they
    have already been sent, they will have lower tids than any request
    already present on the unsent list.
    
    Just below that, traverse the linger list in forward order as
    before, but add them to the *tail* of the list rather than the head.
    These requests get re-registered, and in the process are give a new
    (higher) tid, so the should go at the end.
    
    This partially resolves:
        http://tracker.ceph.com/issues/4392Signed-off-by: default avatarAlex Elder <elder@inktank.com>
    Reviewed-off-by: default avatarSage Weil <sage@inktank.com>
    e02493c0
osd_client.c 58.9 KB