libceph: complete lingering requests only once
authorAlex Elder <elder@inktank.com>
Wed, 27 Feb 2013 16:26:25 +0000 (10:26 -0600)
committerSage Weil <sage@inktank.com>
Thu, 2 May 2013 04:16:12 +0000 (21:16 -0700)
An osd request marked to linger will be re-submitted in the event
a connection to the target osd gets dropped.  Currently, if there
is a callback function associated with a request it will be called
each time a request is submitted--which for lingering requests can
be more than once.

Change it so a request--including lingering ones--will get completed
(from the perspective of the user of the osd client) exactly once.

This resolves:
    http://tracker.ceph.com/issues/3967

Signed-off-by: Alex Elder <elder@inktank.com>
Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
include/linux/ceph/osd_client.h
net/ceph/osd_client.c

index 1dd5d466b6f9f01980c8e3efb7d905395f6b3fde..a79f833bba4a8576620c6e45285f52f1e3c75ca5 100644 (file)
@@ -85,6 +85,7 @@ struct ceph_osd_request {
        s32               r_reply_op_result[CEPH_OSD_MAX_OP];
        int               r_got_reply;
        int               r_linger;
+       int               r_completed;
 
        struct ceph_osd_client *r_osdc;
        struct kref       r_kref;
index 1d9ebf967b00f426843a99199a07339953b7dc7e..a28c976ae3aebdfceefbe7d288a5e821d43123bf 100644 (file)
@@ -1174,6 +1174,7 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
        u32 reassert_epoch;
        u64 reassert_version;
        u32 osdmap_epoch;
+       int already_completed;
        int i;
 
        tid = le64_to_cpu(msg->hdr.tid);
@@ -1282,7 +1283,11 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
            ((flags & CEPH_OSD_FLAG_WRITE) == 0))
                __unregister_request(osdc, req);
 
+       already_completed = req->r_completed;
+       req->r_completed = 1;
        mutex_unlock(&osdc->request_mutex);
+       if (already_completed)
+               goto done;
 
        if (req->r_callback)
                req->r_callback(req, msg);