aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorJosh Durgin <josh.durgin@inktank.com>2014-04-04 15:06:32 -0400
committerIlya Dryomov <idryomov@redhat.com>2014-10-14 13:03:32 -0400
commit3c5df89367761d09d76454a2c4301a73bf2d46ce (patch)
tree2e03d9e6e1d75a8558610fcee226f6e1f9fe6fc4 /drivers/block
parent90e98c5229c0adfadf2c2ad2c91d72902bf61bc4 (diff)
rbd: read image size for discard check safely
In rbd_img_request_fill() the image size is only checked to determine whether we can truncate an object instead of zeroing it for discard requests. Take rbd_dev->header_rwsem while reading the image size, and move this read into the discard check, so that non-discard ops don't need to take the semaphore in this function. Signed-off-by: Josh Durgin <josh.durgin@inktank.com>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/rbd.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index e2f7a708e20d..31ace3dd33e4 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -2332,7 +2332,6 @@ static int rbd_img_request_fill(struct rbd_img_request *img_request,
2332 (int)type, data_desc); 2332 (int)type, data_desc);
2333 2333
2334 img_offset = img_request->offset; 2334 img_offset = img_request->offset;
2335 img_end = rbd_dev->header.image_size;
2336 resid = img_request->length; 2335 resid = img_request->length;
2337 rbd_assert(resid > 0); 2336 rbd_assert(resid > 0);
2338 2337
@@ -2397,13 +2396,20 @@ static int rbd_img_request_fill(struct rbd_img_request *img_request,
2397 if (!offset && (length == object_size) 2396 if (!offset && (length == object_size)
2398 && (!img_request_layered_test(img_request) || 2397 && (!img_request_layered_test(img_request) ||
2399 (rbd_dev->parent_overlap <= 2398 (rbd_dev->parent_overlap <=
2400 obj_request->img_offset))) 2399 obj_request->img_offset))) {
2401 opcode = CEPH_OSD_OP_DELETE; 2400 opcode = CEPH_OSD_OP_DELETE;
2402 else if ((offset + length == object_size) || 2401 } else if ((offset + length == object_size)) {
2403 (obj_request->img_offset + length == img_end))
2404 opcode = CEPH_OSD_OP_TRUNCATE; 2402 opcode = CEPH_OSD_OP_TRUNCATE;
2405 else 2403 } else {
2406 opcode = CEPH_OSD_OP_ZERO; 2404 down_read(&rbd_dev->header_rwsem);
2405 img_end = rbd_dev->header.image_size;
2406 up_read(&rbd_dev->header_rwsem);
2407
2408 if (obj_request->img_offset + length == img_end)
2409 opcode = CEPH_OSD_OP_TRUNCATE;
2410 else
2411 opcode = CEPH_OSD_OP_ZERO;
2412 }
2407 } else if (img_request_write_test(img_request)) { 2413 } else if (img_request_write_test(img_request)) {
2408 op_type = OBJ_OP_WRITE; 2414 op_type = OBJ_OP_WRITE;
2409 opcode = CEPH_OSD_OP_WRITE; 2415 opcode = CEPH_OSD_OP_WRITE;