Skip to content

Commit 870611e

Browse files
committed
rbd: get snapshot context after exclusive lock is ensured to be held
Move capturing the snapshot context into the image request state machine, after exclusive lock is ensured to be held for the duration of dealing with the image request. This is needed to ensure correctness of fast-diff states (OBJECT_EXISTS vs OBJECT_EXISTS_CLEAN) and object deltas computed based off of them. Otherwise the object map that is forked for the snapshot isn't guaranteed to accurately reflect the contents of the snapshot when the snapshot is taken under I/O. This breaks differential backup and snapshot-based mirroring use cases with fast-diff enabled: since some object deltas may be incomplete, the destination image may get corrupted. Cc: stable@vger.kernel.org Link: https://tracker.ceph.com/issues/61472 Signed-off-by: Ilya Dryomov <idryomov@gmail.com> Reviewed-by: Dongsheng Yang <dongsheng.yang@easystack.cn>
1 parent 09fe05c commit 870611e

File tree

1 file changed

+23
-7
lines changed

1 file changed

+23
-7
lines changed

drivers/block/rbd.c

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1336,6 +1336,8 @@ static bool rbd_obj_is_tail(struct rbd_obj_request *obj_req)
13361336
*/
13371337
static void rbd_obj_set_copyup_enabled(struct rbd_obj_request *obj_req)
13381338
{
1339+
rbd_assert(obj_req->img_request->snapc);
1340+
13391341
if (obj_req->img_request->op_type == OBJ_OP_DISCARD) {
13401342
dout("%s %p objno %llu discard\n", __func__, obj_req,
13411343
obj_req->ex.oe_objno);
@@ -1456,6 +1458,7 @@ __rbd_obj_add_osd_request(struct rbd_obj_request *obj_req,
14561458
static struct ceph_osd_request *
14571459
rbd_obj_add_osd_request(struct rbd_obj_request *obj_req, int num_ops)
14581460
{
1461+
rbd_assert(obj_req->img_request->snapc);
14591462
return __rbd_obj_add_osd_request(obj_req, obj_req->img_request->snapc,
14601463
num_ops);
14611464
}
@@ -1592,15 +1595,18 @@ static void rbd_img_request_init(struct rbd_img_request *img_request,
15921595
mutex_init(&img_request->state_mutex);
15931596
}
15941597

1598+
/*
1599+
* Only snap_id is captured here, for reads. For writes, snapshot
1600+
* context is captured in rbd_img_object_requests() after exclusive
1601+
* lock is ensured to be held.
1602+
*/
15951603
static void rbd_img_capture_header(struct rbd_img_request *img_req)
15961604
{
15971605
struct rbd_device *rbd_dev = img_req->rbd_dev;
15981606

15991607
lockdep_assert_held(&rbd_dev->header_rwsem);
16001608

1601-
if (rbd_img_is_write(img_req))
1602-
img_req->snapc = ceph_get_snap_context(rbd_dev->header.snapc);
1603-
else
1609+
if (!rbd_img_is_write(img_req))
16041610
img_req->snap_id = rbd_dev->spec->snap_id;
16051611

16061612
if (rbd_dev_parent_get(rbd_dev))
@@ -3482,9 +3488,19 @@ static int rbd_img_exclusive_lock(struct rbd_img_request *img_req)
34823488

34833489
static void rbd_img_object_requests(struct rbd_img_request *img_req)
34843490
{
3491+
struct rbd_device *rbd_dev = img_req->rbd_dev;
34853492
struct rbd_obj_request *obj_req;
34863493

34873494
rbd_assert(!img_req->pending.result && !img_req->pending.num_pending);
3495+
rbd_assert(!need_exclusive_lock(img_req) ||
3496+
__rbd_is_lock_owner(rbd_dev));
3497+
3498+
if (rbd_img_is_write(img_req)) {
3499+
rbd_assert(!img_req->snapc);
3500+
down_read(&rbd_dev->header_rwsem);
3501+
img_req->snapc = ceph_get_snap_context(rbd_dev->header.snapc);
3502+
up_read(&rbd_dev->header_rwsem);
3503+
}
34883504

34893505
for_each_obj_request(img_req, obj_req) {
34903506
int result = 0;
@@ -3502,7 +3518,6 @@ static void rbd_img_object_requests(struct rbd_img_request *img_req)
35023518

35033519
static bool rbd_img_advance(struct rbd_img_request *img_req, int *result)
35043520
{
3505-
struct rbd_device *rbd_dev = img_req->rbd_dev;
35063521
int ret;
35073522

35083523
again:
@@ -3523,9 +3538,6 @@ static bool rbd_img_advance(struct rbd_img_request *img_req, int *result)
35233538
if (*result)
35243539
return true;
35253540

3526-
rbd_assert(!need_exclusive_lock(img_req) ||
3527-
__rbd_is_lock_owner(rbd_dev));
3528-
35293541
rbd_img_object_requests(img_req);
35303542
if (!img_req->pending.num_pending) {
35313543
*result = img_req->pending.result;
@@ -3987,6 +3999,10 @@ static int rbd_post_acquire_action(struct rbd_device *rbd_dev)
39873999
{
39884000
int ret;
39894001

4002+
ret = rbd_dev_refresh(rbd_dev);
4003+
if (ret)
4004+
return ret;
4005+
39904006
if (rbd_dev->header.features & RBD_FEATURE_OBJECT_MAP) {
39914007
ret = rbd_object_map_open(rbd_dev);
39924008
if (ret)

0 commit comments

Comments
 (0)