]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commit
librbd: Append one journal event per image request
authorJoshua Baergen <jbaergen@digitalocean.com>
Thu, 9 Nov 2023 16:43:22 +0000 (09:43 -0700)
committerJoshua Baergen <jbaergen@digitalocean.com>
Wed, 6 Dec 2023 21:17:09 +0000 (14:17 -0700)
commita315d0a680f5d77620a5c98a56abfce7d31d1344
treebf3ba91771e2ae05ee7e024aa40440ac83d485e5
parent7c0a956cd77dda7827ed59312eb85f26945a5ce7
librbd: Append one journal event per image request

In the case where an image request is split across multiple object
extents and journaling is enabled, multiple journal events are appended.
Prior to this change, all object requests would wait for the last
journal event to complete, since journal events complete in order and
thus the last one completing implies that all prior journal events were
safe at that point.

The issue with this is that there's nothing stopping that last journal
event from being cleaned up before all object requests have stopped
referring to it. Thus, it's entirely possible for the following sequence
to occur:
1. An image request gets split into two image extents and two object
   requests. Journal events are appended (one per image extent).
2. The first object request gets delayed due to an overlap, but the
   second object request gets submitted and starts waiting on the last
   journal event (which also causes a C_CommitIOEvent to be instantiated
   against that journal event).
3. Journaling completes, and the C_CommitIOEvent fires. The
   C_CommitIOEvent covers the entire range of data that was journaled in
   this event, and so the event is cleaned up.
4. The first object request from above is allowed to make progress; it
   tries to wait for the journal event that was just cleaned up which
   causes the assert in wait_event() to fire.

As far as I can tell, this is only possible on the discard path today,
and only recently. Up until 21a26a752843295ff946d1543c2f5f9fac764593
(librbd: Fix local rbd mirror journals growing forever), m_image_extents
always contained a single extent for all I/O types; this commit changed
the discard path so that if discard granularity changed the discard
request, m_image_extents would be repopulated, and if the request
happened to cross objects then there would be multiple m_image_extents.

It appears that the intent here was that there should be one journal
event per image request and the pending_extents kept track of what had
completed thus far. This commit restores that 1:1 relationship.

Fixes: https://tracker.ceph.com/issues/63422
Signed-off-by: Joshua Baergen <jbaergen@digitalocean.com>
(cherry picked from commit 4a8fa2da72fe64109073fddca0d4cfd99aeb9c77)
src/librbd/Journal.cc
src/librbd/Journal.h
src/librbd/io/ImageRequest.cc
src/test/librbd/io/test_mock_ImageRequest.cc
src/test/librbd/journal/test_Entries.cc
src/test/librbd/test_mock_Journal.cc