• Alex Elder's avatar
    libceph: move linger requests sooner in kick_requests() · ab60b16d
    Alex Elder authored
    The kick_requests() function is called by ceph_osdc_handle_map()
    when an osd map change has been indicated.  Its purpose is to
    re-queue any request whose target osd is different from what it
    was when it was originally sent.
    
    It is structured as two loops, one for incomplete but registered
    requests, and a second for handling completed linger requests.
    As a special case, in the first loop if a request marked to linger
    has not yet completed, it is moved from the request list to the
    linger list.  This is as a quick and dirty way to have the second
    loop handle sending the request along with all the other linger
    requests.
    
    Because of the way it's done now, however, this quick and dirty
    solution can result in these incomplete linger requests never
    getting re-sent as desired.  The problem lies in the fact that
    the second loop only arranges for a linger request to be sent
    if it appears its target osd has changed.  This is the proper
    handling for *completed* linger requests (it avoids issuing
    the same linger request twice to the same osd).
    
    But although the linger requests added to the list in the first loop
    may have been sent, they have not yet completed, so they need to be
    re-sent regardless of whether their target osd has changed.
    
    The first required fix is we need to avoid calling __map_request()
    on any incomplete linger request.  Otherwise the subsequent
    __map_request() call in the second loop will find the target osd
    has not changed and will therefore not re-send the request.
    
    Second, we need to be sure that a sent but incomplete linger request
    gets re-sent.  If the target osd is the same with the new osd map as
    it was when the request was originally sent, this won't happen.
    This can be fixed through careful handling when we move these
    requests from the request list to the linger list, by unregistering
    the request *before* it is registered as a linger request.  This
    works because a side-effect of unregistering the request is to make
    the request's r_osd pointer be NULL, and *that* will ensure the
    second loop actually re-sends the linger request.
    
    Processing of such a request is done at that point, so continue with
    the next one once it's been moved.
    Signed-off-by: default avatarAlex Elder <elder@inktank.com>
    Reviewed-by: default avatarSage Weil <sage@inktank.com>
    ab60b16d
osd_client.c 55.8 KB