The mapping size is changed only very infrequently, so we don't need to take the header mutex for checking; using READ_ONCE() is sufficient here. And it avoids having to take a mutex in the hot path. Signed-off-by: Hannes Reinecke <hare@xxxxxxx> --- drivers/block/rbd.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index db80b964d8ea..792180548e89 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -4788,13 +4788,13 @@ static void rbd_queue_workfn(struct work_struct *work) blk_mq_start_request(rq); - down_read(&rbd_dev->header_rwsem); - mapping_size = rbd_dev->mapping.size; + mapping_size = READ_ONCE(rbd_dev->mapping.size); if (op_type != OBJ_OP_READ) { + down_read(&rbd_dev->header_rwsem); snapc = rbd_dev->header.snapc; ceph_get_snap_context(snapc); + up_read(&rbd_dev->header_rwsem); } - up_read(&rbd_dev->header_rwsem); if (offset + length > mapping_size) { rbd_warn(rbd_dev, "beyond EOD (%llu~%llu > %llu)", offset, @@ -4981,9 +4981,9 @@ static int rbd_dev_refresh(struct rbd_device *rbd_dev) u64 mapping_size; int ret; - down_write(&rbd_dev->header_rwsem); - mapping_size = rbd_dev->mapping.size; + mapping_size = READ_ONCE(rbd_dev->mapping.size); + down_write(&rbd_dev->header_rwsem); ret = rbd_dev_header_info(rbd_dev); if (ret) goto out; @@ -4999,7 +4999,7 @@ static int rbd_dev_refresh(struct rbd_device *rbd_dev) } rbd_assert(!rbd_is_snap(rbd_dev)); - rbd_dev->mapping.size = rbd_dev->header.image_size; + WRITE_ONCE(rbd_dev->mapping.size, rbd_dev->header.image_size); out: up_write(&rbd_dev->header_rwsem); -- 2.16.4