aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
authorAlex Elder <elder@inktank.com>2013-04-15 12:20:42 -0400
committerSage Weil <sage@inktank.com>2013-05-02 00:18:52 -0400
commit26be88087ae8a04a5b576aa2f490597b649fc132 (patch)
treede16ba5b5b9fe678546fe82f0d6801a2ef441b0d /include/linux
parent7d7d51ce14fde491a6d0677d9bded9b3bd0d21d9 (diff)
libceph: change how "safe" callback is used
An osd request currently has two callbacks. They inform the initiator of the request when we've received confirmation for the target osd that a request was received, and when the osd indicates all changes described by the request are durable. The only time the second callback is used is in the ceph file system for a synchronous write. There's a race that makes some handling of this case unsafe. This patch addresses this problem. The error handling for this callback is also kind of gross, and this patch changes that as well. In ceph_sync_write(), if a safe callback is requested we want to add the request on the ceph inode's unsafe items list. Because items on this list must have their tid set (by ceph_osd_start_request()), the request added *after* the call to that function returns. The problem with this is that there's a race between starting the request and adding it to the unsafe items list; the request may already be complete before ceph_sync_write() even begins to put it on the list. To address this, we change the way the "safe" callback is used. Rather than just calling it when the request is "safe", we use it to notify the initiator the bounds (start and end) of the period during which the request is *unsafe*. So the initiator gets notified just before the request gets sent to the osd (when it is "unsafe"), and again when it's known the results are durable (it's no longer unsafe). The first call will get made in __send_request(), just before the request message gets sent to the messenger for the first time. That function is only called by __send_queued(), which is always called with the osd client's request mutex held. We then have this callback function insert the request on the ceph inode's unsafe list when we're told the request is unsafe. This will avoid the race because this call will be made under protection of the osd client's request mutex. It also nicely groups the setup and cleanup of the state associated with managing unsafe requests. The name of the "safe" callback field is changed to "unsafe" to better reflect its new purpose. It has a Boolean "unsafe" parameter to indicate whether the request is becoming unsafe or is now safe. Because the "msg" parameter wasn't used, we drop that. This resolves the original problem reportedin: http://tracker.ceph.com/issues/4706 Reported-by: Yan, Zheng <zheng.z.yan@intel.com> Signed-off-by: Alex Elder <elder@inktank.com> Reviewed-by: Yan, Zheng <zheng.z.yan@intel.com> Reviewed-by: Sage Weil <sage@inktank.com>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/ceph/osd_client.h4
1 files changed, 3 insertions, 1 deletions
diff --git a/include/linux/ceph/osd_client.h b/include/linux/ceph/osd_client.h
index 2a68a7465c18..0d3358ef5285 100644
--- a/include/linux/ceph/osd_client.h
+++ b/include/linux/ceph/osd_client.h
@@ -29,6 +29,7 @@ struct ceph_authorizer;
29 */ 29 */
30typedef void (*ceph_osdc_callback_t)(struct ceph_osd_request *, 30typedef void (*ceph_osdc_callback_t)(struct ceph_osd_request *,
31 struct ceph_msg *); 31 struct ceph_msg *);
32typedef void (*ceph_osdc_unsafe_callback_t)(struct ceph_osd_request *, bool);
32 33
33/* a given osd we're communicating with */ 34/* a given osd we're communicating with */
34struct ceph_osd { 35struct ceph_osd {
@@ -149,7 +150,8 @@ struct ceph_osd_request {
149 struct kref r_kref; 150 struct kref r_kref;
150 bool r_mempool; 151 bool r_mempool;
151 struct completion r_completion, r_safe_completion; 152 struct completion r_completion, r_safe_completion;
152 ceph_osdc_callback_t r_callback, r_safe_callback; 153 ceph_osdc_callback_t r_callback;
154 ceph_osdc_unsafe_callback_t r_unsafe_callback;
153 struct ceph_eversion r_reassert_version; 155 struct ceph_eversion r_reassert_version;
154 struct list_head r_unsafe_item; 156 struct list_head r_unsafe_item;
155 157