]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: retry list_snap_orders() once instead of failing sort_snaps() 64099/head
authorVinayBhaskar-V <vvarada@redhat.com>
Thu, 15 May 2025 14:18:30 +0000 (19:48 +0530)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 23 Jun 2025 07:26:40 +0000 (09:26 +0200)
If snapshot listing races with snapshot creation, rbd group snap ls
may spuriously return an unsorted listing and internal fail_if_not_sorted=true
consumers may generate a spurious EINVAL error. This is because snap orders
are listed before snaps themselves and the "missing order for snap" check in
sort_snaps() is driven by the list of snaps.
This can be improved by grabbing snap order keys one more time, adding the newly
discovered snap orders to m_snap_orders and retrying instead of immediately failing the sort.

Fixes: https://tracker.ceph.com/issues/67984
Signed-off-by: VinayBhaskar-V <vvarada@redhat.com>
(cherry picked from commit 3c21aec85e986f5206e83fcdcf5b1e0441b35f56)

src/librbd/group/ListSnapshotsRequest.cc
src/librbd/group/ListSnapshotsRequest.h

index bbd3759ff2b4c839c0e0c04e85aa8f3552e1f8b0..4765f373881fe7128a4d03d0789f2f8fd054d209 100644 (file)
@@ -92,7 +92,11 @@ void ListSnapshotsRequest<I>::handle_list_snap_orders(int r) {
 
   m_snap_orders.insert(snap_orders.begin(), snap_orders.end());
   if (snap_orders.size() < MAX_RETURN) {
-    list_snaps();
+    if (m_retried_snap_orders) {
+      sort_snaps();
+    } else {
+      list_snaps();
+    }
     return;
   }
 
@@ -158,7 +162,18 @@ void ListSnapshotsRequest<I>::sort_snaps() {
   for (const auto& snap : *m_snaps) {
     if (m_snap_orders.find(snap.id) == m_snap_orders.end()) {
       ldout(cct, 10) << "Missing order for snap_id=" << snap.id << dendl;
-      finish(m_fail_if_not_sorted ? -EINVAL : 0);
+      if (m_fail_if_not_sorted) {
+        if (!m_retried_snap_orders) {
+          ldout(cct, 10) << "Retrying to fetch missing snap orders..." << dendl;
+          m_retried_snap_orders = true;
+          m_start_after_order = "";
+          list_snap_orders();
+        } else {
+          finish(-EINVAL);
+        }
+      } else {
+        finish(0);
+      }
       return;
     }
   }
index 7152dd981ab7de77ec17beb3250ed643df8fc79c..4c5a1d047ed28adab832709f3a74fb43940f1465 100644 (file)
@@ -44,16 +44,24 @@ private:
    * @verbatim
    *
    * <start>    /--------\
-   *    |       |        | (if required. repeat if more
+   *    |       |        | (if requested, repeat if more
    *    v       v        |  entries)
    *  LIST_SNAP_ORDERS --/
+   *    |
    *    |       /--------\
    *    |       |        | (repeat if more
    *    v       v        |  snapshots)
    *  LIST_SNAPS --------/
    *    |
-   *    v
-   *  SORT_SNAPS (if required)  
+   *    |                          /--------\
+   *    |/-------<--------\        |        | (repeat if more
+   *    |                 |        v        |  entries)
+   *    |                LIST_SNAP_ORDERS --/
+   *    |                 ^
+   *    |                 | (retry if ordering is required and
+   *    |                 |  an entry is missing for a snapshot)
+   *    v (if requested)  |
+   *  SORT_SNAPS ---------/
    *    |
    *    v
    *  <finish>
@@ -73,6 +81,7 @@ private:
   cls::rbd::GroupSnapshot m_start_after;
   std::string m_start_after_order;
   bufferlist m_out_bl;
+  bool m_retried_snap_orders = false;
 
   void list_snaps();
   void handle_list_snaps(int r);