aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/rbd.c
diff options
context:
space:
mode:
authorAlex Elder <elder@inktank.com>2013-05-10 17:29:22 -0400
committerAlex Elder <elder@inktank.com>2013-05-13 15:09:01 -0400
commitebda6408f2227a774343c3cc2861384942143ff3 (patch)
tree557776350c36146f227651ca5797196ed972e138 /drivers/block/rbd.c
parentc10ebbf55b40503a46fb8b29824c9ca1ca089826 (diff)
rbd: fix parent request size assumption
The code that reads object data from the parent for a copyup on write request currently assumes that the size of that request is the size of a "full" object from the original target image. That is not necessarily the case. The parent overlap could reduce the request size below that. To fix that assumption we need to record the number of pages in the copyup_pages array, for both an image request and an object request. Rename a local variable in rbd_img_obj_parent_read_full_callback() to reflect we're recording the length of the parent read request, not the size of the target object. This resolves: http://tracker.ceph.com/issues/5038 Signed-off-by: Alex Elder <elder@inktank.com> Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
Diffstat (limited to 'drivers/block/rbd.c')
-rw-r--r--drivers/block/rbd.c31
1 files changed, 20 insertions, 11 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 51c45e793354..597b9bbe2fc7 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -224,6 +224,7 @@ struct rbd_obj_request {
224 }; 224 };
225 }; 225 };
226 struct page **copyup_pages; 226 struct page **copyup_pages;
227 u32 copyup_page_count;
227 228
228 struct ceph_osd_request *osd_req; 229 struct ceph_osd_request *osd_req;
229 230
@@ -256,6 +257,7 @@ struct rbd_img_request {
256 struct rbd_obj_request *obj_request; /* obj req initiator */ 257 struct rbd_obj_request *obj_request; /* obj req initiator */
257 }; 258 };
258 struct page **copyup_pages; 259 struct page **copyup_pages;
260 u32 copyup_page_count;
259 spinlock_t completion_lock;/* protects next_completion */ 261 spinlock_t completion_lock;/* protects next_completion */
260 u32 next_completion; 262 u32 next_completion;
261 rbd_img_callback_t callback; 263 rbd_img_callback_t callback;
@@ -2119,7 +2121,7 @@ rbd_img_obj_copyup_callback(struct rbd_obj_request *obj_request)
2119{ 2121{
2120 struct rbd_img_request *img_request; 2122 struct rbd_img_request *img_request;
2121 struct rbd_device *rbd_dev; 2123 struct rbd_device *rbd_dev;
2122 u64 length; 2124 struct page **pages;
2123 u32 page_count; 2125 u32 page_count;
2124 2126
2125 rbd_assert(obj_request->type == OBJ_REQUEST_BIO); 2127 rbd_assert(obj_request->type == OBJ_REQUEST_BIO);
@@ -2129,12 +2131,14 @@ rbd_img_obj_copyup_callback(struct rbd_obj_request *obj_request)
2129 2131
2130 rbd_dev = img_request->rbd_dev; 2132 rbd_dev = img_request->rbd_dev;
2131 rbd_assert(rbd_dev); 2133 rbd_assert(rbd_dev);
2132 length = (u64)1 << rbd_dev->header.obj_order;
2133 page_count = (u32)calc_pages_for(0, length);
2134 2134
2135 rbd_assert(obj_request->copyup_pages); 2135 pages = obj_request->copyup_pages;
2136 ceph_release_page_vector(obj_request->copyup_pages, page_count); 2136 rbd_assert(pages != NULL);
2137 obj_request->copyup_pages = NULL; 2137 obj_request->copyup_pages = NULL;
2138 page_count = obj_request->copyup_page_count;
2139 rbd_assert(page_count);
2140 obj_request->copyup_page_count = 0;
2141 ceph_release_page_vector(pages, page_count);
2138 2142
2139 /* 2143 /*
2140 * We want the transfer count to reflect the size of the 2144 * We want the transfer count to reflect the size of the
@@ -2158,9 +2162,9 @@ rbd_img_obj_parent_read_full_callback(struct rbd_img_request *img_request)
2158 struct ceph_osd_client *osdc; 2162 struct ceph_osd_client *osdc;
2159 struct rbd_device *rbd_dev; 2163 struct rbd_device *rbd_dev;
2160 struct page **pages; 2164 struct page **pages;
2165 u32 page_count;
2161 int result; 2166 int result;
2162 u64 obj_size; 2167 u64 parent_length;
2163 u64 xferred;
2164 2168
2165 rbd_assert(img_request_child_test(img_request)); 2169 rbd_assert(img_request_child_test(img_request));
2166 2170
@@ -2169,19 +2173,21 @@ rbd_img_obj_parent_read_full_callback(struct rbd_img_request *img_request)
2169 pages = img_request->copyup_pages; 2173 pages = img_request->copyup_pages;
2170 rbd_assert(pages != NULL); 2174 rbd_assert(pages != NULL);
2171 img_request->copyup_pages = NULL; 2175 img_request->copyup_pages = NULL;
2176 page_count = img_request->copyup_page_count;
2177 rbd_assert(page_count);
2178 img_request->copyup_page_count = 0;
2172 2179
2173 orig_request = img_request->obj_request; 2180 orig_request = img_request->obj_request;
2174 rbd_assert(orig_request != NULL); 2181 rbd_assert(orig_request != NULL);
2175 rbd_assert(orig_request->type == OBJ_REQUEST_BIO); 2182 rbd_assert(orig_request->type == OBJ_REQUEST_BIO);
2176 result = img_request->result; 2183 result = img_request->result;
2177 obj_size = img_request->length; 2184 parent_length = img_request->length;
2178 xferred = img_request->xferred; 2185 rbd_assert(parent_length == img_request->xferred);
2179 rbd_img_request_put(img_request); 2186 rbd_img_request_put(img_request);
2180 2187
2181 rbd_assert(orig_request->img_request); 2188 rbd_assert(orig_request->img_request);
2182 rbd_dev = orig_request->img_request->rbd_dev; 2189 rbd_dev = orig_request->img_request->rbd_dev;
2183 rbd_assert(rbd_dev); 2190 rbd_assert(rbd_dev);
2184 rbd_assert(obj_size == (u64)1 << rbd_dev->header.obj_order);
2185 2191
2186 if (result) 2192 if (result)
2187 goto out_err; 2193 goto out_err;
@@ -2195,11 +2201,12 @@ rbd_img_obj_parent_read_full_callback(struct rbd_img_request *img_request)
2195 goto out_err; 2201 goto out_err;
2196 orig_request->osd_req = osd_req; 2202 orig_request->osd_req = osd_req;
2197 orig_request->copyup_pages = pages; 2203 orig_request->copyup_pages = pages;
2204 orig_request->copyup_page_count = page_count;
2198 2205
2199 /* Initialize the copyup op */ 2206 /* Initialize the copyup op */
2200 2207
2201 osd_req_op_cls_init(osd_req, 0, CEPH_OSD_OP_CALL, "rbd", "copyup"); 2208 osd_req_op_cls_init(osd_req, 0, CEPH_OSD_OP_CALL, "rbd", "copyup");
2202 osd_req_op_cls_request_data_pages(osd_req, 0, pages, obj_size, 0, 2209 osd_req_op_cls_request_data_pages(osd_req, 0, pages, parent_length, 0,
2203 false, false); 2210 false, false);
2204 2211
2205 /* Then the original write request op */ 2212 /* Then the original write request op */
@@ -2312,6 +2319,7 @@ static int rbd_img_obj_parent_read_full(struct rbd_obj_request *obj_request)
2312 if (result) 2319 if (result)
2313 goto out_err; 2320 goto out_err;
2314 parent_request->copyup_pages = pages; 2321 parent_request->copyup_pages = pages;
2322 parent_request->copyup_page_count = page_count;
2315 2323
2316 parent_request->callback = rbd_img_obj_parent_read_full_callback; 2324 parent_request->callback = rbd_img_obj_parent_read_full_callback;
2317 result = rbd_img_request_submit(parent_request); 2325 result = rbd_img_request_submit(parent_request);
@@ -2319,6 +2327,7 @@ static int rbd_img_obj_parent_read_full(struct rbd_obj_request *obj_request)
2319 return 0; 2327 return 0;
2320 2328
2321 parent_request->copyup_pages = NULL; 2329 parent_request->copyup_pages = NULL;
2330 parent_request->copyup_page_count = 0;
2322 parent_request->obj_request = NULL; 2331 parent_request->obj_request = NULL;
2323 rbd_obj_request_put(obj_request); 2332 rbd_obj_request_put(obj_request);
2324out_err: 2333out_err: