diff options
author | Josh Durgin <josh.durgin@inktank.com> | 2014-04-04 15:06:32 -0400 |
---|---|---|
committer | Ilya Dryomov <idryomov@redhat.com> | 2014-10-14 13:03:32 -0400 |
commit | 3c5df89367761d09d76454a2c4301a73bf2d46ce (patch) | |
tree | 2e03d9e6e1d75a8558610fcee226f6e1f9fe6fc4 /drivers/block | |
parent | 90e98c5229c0adfadf2c2ad2c91d72902bf61bc4 (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.c | 18 |
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; |