summary refs log tree commit diff
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2011-06-03 09:37:09 -0700
committerSage Weil <sage@newdream.net>2011-06-07 21:34:13 -0700
commit2584547230ae49b8de91ab3bb5e0a81898905b45 (patch)
tree1f00818bc7075e0898998d4e05c0cd08dd3d85d0
parent70b666c3b4cb2b96098d80e6f515e4bc6d37db5a (diff)
downloadlinux-2584547230ae49b8de91ab3bb5e0a81898905b45.tar.gz
ceph: fix sync vs canceled write
If we cancel a write, trigger the safe completions to prevent a sync from
blocking indefinitely in ceph_osdc_sync().

Signed-off-by: Sage Weil <sage@newdream.net>
-rw-r--r--net/ceph/osd_client.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index 6ea2b892f44b..9cb627a4073a 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -1144,6 +1144,13 @@ static void handle_osds_timeout(struct work_struct *work)
 			      round_jiffies_relative(delay));
 }
 
+static void complete_request(struct ceph_osd_request *req)
+{
+	if (req->r_safe_callback)
+		req->r_safe_callback(req, NULL);
+	complete_all(&req->r_safe_completion);  /* fsync waiter */
+}
+
 /*
  * handle osd op reply.  either call the callback if it is specified,
  * or do the completion to wake up the waiting thread.
@@ -1226,11 +1233,8 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
 	else
 		complete_all(&req->r_completion);
 
-	if (flags & CEPH_OSD_FLAG_ONDISK) {
-		if (req->r_safe_callback)
-			req->r_safe_callback(req, msg);
-		complete_all(&req->r_safe_completion);  /* fsync waiter */
-	}
+	if (flags & CEPH_OSD_FLAG_ONDISK)
+		complete_request(req);
 
 done:
 	dout("req=%p req->r_linger=%d\n", req, req->r_linger);
@@ -1732,6 +1736,7 @@ int ceph_osdc_wait_request(struct ceph_osd_client *osdc,
 		__cancel_request(req);
 		__unregister_request(osdc, req);
 		mutex_unlock(&osdc->request_mutex);
+		complete_request(req);
 		dout("wait_request tid %llu canceled/timed out\n", req->r_tid);
 		return rc;
 	}