]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
osd/PGLog: should not rollback further than deleted object version
authorNeha Ojha <nojha@redhat.com>
Wed, 6 Feb 2019 03:23:21 +0000 (19:23 -0800)
committerNeha Ojha <nojha@redhat.com>
Mon, 25 Mar 2019 18:33:47 +0000 (11:33 -0700)
When a deleted object becomes a divergent entry in the pg log,
we should not be able to rollback to a version of the deleted
object that doesn't exist.

To avoid this, we need to preserve the original crt of the pg log,
before we update it in rewind_from_head() and use that to decide whether
we can rollback or not in _merge_object_divergent_entries().

Fixes: http://tracker.ceph.com/issues/36739
Signed-off-by: Neha Ojha <nojha@redhat.com>
src/osd/PGLog.cc
src/osd/PGLog.h
src/test/osd/TestPGLog.cc

index ab9ead3fb924ac22c25cfda1c69f5bf7c0f48714..b0bf4deb5257ac1f399838712b7346eb12ca09a7 100644 (file)
@@ -276,6 +276,7 @@ void PGLog::proc_replica_log(
     divergent,
     oinfo,
     olog.get_can_rollback_to(),
+    olog.get_can_rollback_to(),
     omissing,
     0,
     this);
@@ -318,7 +319,11 @@ void PGLog::rewind_divergent_log(eversion_t newhead,
   dout(10) << "rewind_divergent_log truncate divergent future " <<
     newhead << dendl;
 
-
+  // We need to preserve the original crt before it gets updated in rewind_from_head().
+  // Later, in merge_object_divergent_entries(), we use it to check whether we can rollback
+  // a divergent entry or not.
+  eversion_t original_crt = log.get_can_rollback_to();
+  dout(20) << __func__ << " original_crt = " << original_crt << dendl;
   if (info.last_complete > newhead)
     info.last_complete = newhead;
 
@@ -336,6 +341,7 @@ void PGLog::rewind_divergent_log(eversion_t newhead,
     divergent,
     info,
     log.get_can_rollback_to(),
+    original_crt,
     missing,
     rollbacker,
     this);
@@ -457,6 +463,7 @@ void PGLog::merge_log(pg_info_t &oinfo, pg_log_t &olog, pg_shard_t fromosd,
       divergent,
       info,
       log.get_can_rollback_to(),
+      log.get_can_rollback_to(),
       missing,
       rollbacker,
       this);
index 1a4a5a5428e600cbcb8ae71cb75268203abd666f..862ca5f4139a7398e643bde47935c0fc2c892616 100644 (file)
@@ -867,6 +867,7 @@ protected:
     const mempool::osd_pglog::list<pg_log_entry_t> &orig_entries, ///< [in] entries for hoid to merge
     const pg_info_t &info,              ///< [in] info for merging entries
     eversion_t olog_can_rollback_to,     ///< [in] rollback boundary
+    eversion_t original_can_rollback_to,     ///< [in] original rollback boundary
     missing_type &missing,               ///< [in,out] missing to adjust, use
     LogEntryHandler *rollbacker,         ///< [in] optional rollbacker object
     const DoutPrefixProvider *dpp        ///< [in] logging provider
@@ -930,6 +931,8 @@ protected:
     const bool object_not_in_store =
       !missing.is_missing(hoid) &&
       entries.rbegin()->is_delete();
+    ldpp_dout(dpp, 10) << __func__ << ": hoid " << " object_not_in_store: "
+                       << object_not_in_store << dendl;
     ldpp_dout(dpp, 10) << __func__ << ": hoid " << hoid
                       << " prior_version: " << prior_version
                       << " first_divergent_update: " << first_divergent_update
@@ -1032,7 +1035,10 @@ protected:
     for (list<pg_log_entry_t>::const_reverse_iterator i = entries.rbegin();
         i != entries.rend();
         ++i) {
-      if (!i->can_rollback() || i->version <= olog_can_rollback_to) {
+      /// Use original_can_rollback_to instead of olog_can_rollback_to to check
+      //  if we can rollback or not. This is to ensure that we don't try to rollback
+      //  to an object that has been deleted and doesn't exist.
+      if (!i->can_rollback() || i->version <= original_can_rollback_to) {
        ldpp_dout(dpp, 10) << __func__ << ": hoid " << hoid << " cannot rollback "
                           << *i << dendl;
        can_rollback = false;
@@ -1045,7 +1051,7 @@ protected:
       for (list<pg_log_entry_t>::const_reverse_iterator i = entries.rbegin();
           i != entries.rend();
           ++i) {
-       ceph_assert(i->can_rollback() && i->version > olog_can_rollback_to);
+       ceph_assert(i->can_rollback() && i->version > original_can_rollback_to);
        ldpp_dout(dpp, 10) << __func__ << ": hoid " << hoid
                           << " rolling back " << *i << dendl;
        if (rollbacker)
@@ -1082,6 +1088,7 @@ protected:
     mempool::osd_pglog::list<pg_log_entry_t> &entries,       ///< [in] entries to merge
     const pg_info_t &oinfo,              ///< [in] info for merging entries
     eversion_t olog_can_rollback_to,     ///< [in] rollback boundary
+    eversion_t original_can_rollback_to, ///< [in] original rollback boundary
     missing_type &omissing,              ///< [in,out] missing to adjust, use
     LogEntryHandler *rollbacker,         ///< [in] optional rollbacker object
     const DoutPrefixProvider *dpp        ///< [in] logging provider
@@ -1097,6 +1104,7 @@ protected:
        i->second,
        oinfo,
        olog_can_rollback_to,
+        original_can_rollback_to,
        omissing,
        rollbacker,
        dpp);
@@ -1120,6 +1128,7 @@ protected:
       entries,
       info,
       log.get_can_rollback_to(),
+      log.get_can_rollback_to(),
       missing,
       rollbacker,
       this);
index 3514489a97dae567cadb15ea640d7bccfdf19fdd..c8a9cbc75a172aa526d8bc6c03bc94eb7268b456 100644 (file)
@@ -2939,6 +2939,7 @@ TEST_F(PGLogTest, _merge_object_divergent_entries) {
     _merge_object_divergent_entries(log, hoid,
                                     orig_entries, oinfo,
                                     log.get_can_rollback_to(),
+                                    log.get_can_rollback_to(),
                                     missing, &rollbacker,
                                     this);
     // No core dump
@@ -2965,6 +2966,7 @@ TEST_F(PGLogTest, _merge_object_divergent_entries) {
     _merge_object_divergent_entries(log, hoid,
                                     orig_entries, oinfo,
                                     log.get_can_rollback_to(),
+                                    log.get_can_rollback_to(),
                                     missing, &rollbacker,
                                     this);
     // No core dump