From 70c1991f225c137abf769111086b6c61abc0ece3 Mon Sep 17 00:00:00 2001 From: Ilya Dryomov Date: Fri, 8 Dec 2023 15:19:02 +0100 Subject: [PATCH] librbd: OBJECT_PENDING should always be treated as dirty OBJECT_PENDING is a transition state which normally isn't encountered in (snapshot) object maps. In case it's encountered, for example when a snapshot is taken after losing power at the time a discard was being handled, the object should be treated as dirty and produce a diff as a result. Assuming an object is marked OBJECT_PENDING, theoretically there are four cases with respect to object's state in the next snapshot: 1. OBJECT_NONEXISTENT 2. OBJECT_EXISTS 3. OBJECT_PENDING 4. OBJECT_EXISTS_CLEAN Prior to commit b81cd2460de7 ("librbd/object_map: diff state machine should track object existence"), (3) was handled incorrectly (diff set to DIFF_STATE_NONE instead of DIFF_STATE_UPDATED). Post commit 399a45e11332 ("librbd/object_map: rbd diff between two snapshots lists entire image content"), (4) is handled incorrectly (diff set to DIFF_STATE_DATA instead of DIFF_STATE_DATA_UPDATED). Signed-off-by: Ilya Dryomov --- src/librbd/object_map/DiffRequest.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/librbd/object_map/DiffRequest.cc b/src/librbd/object_map/DiffRequest.cc index 8820aacc87bbb..5b785aeaf3c7d 100644 --- a/src/librbd/object_map/DiffRequest.cc +++ b/src/librbd/object_map/DiffRequest.cc @@ -266,7 +266,11 @@ void DiffRequest::handle_load_object_map(int r) { } } else { // diffing against a snapshot, this is its object map - *diff_it = DIFF_STATE_DATA; + if (object_map_state != OBJECT_PENDING) { + *diff_it = DIFF_STATE_DATA; + } else { + *diff_it = DIFF_STATE_DATA_UPDATED; + } } ldout(cct, 20) << "object state: " << i << " "