]> 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)
committerPrashant D <pdhange@redhat.com>
Mon, 29 Apr 2019 07:01:45 +0000 (03:01 -0400)
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>
(cherry picked from commit de18c592259816ad013ac82983cdec71bbfa51a0)

Conflicts:
src/osd/PGLog.h : Resolved for ceph_assert

src/osd/PGLog.cc
src/osd/PGLog.h
src/test/osd/TestPGLog.cc

index 8a6648c33eec5362a3bdddb935657ad84bff2da4..88fc1a2bcfc5d0b5680839db6da5102d206f456d 100644 (file)
@@ -264,6 +264,7 @@ void PGLog::proc_replica_log(
     divergent,
     oinfo,
     olog.get_can_rollback_to(),
+    olog.get_can_rollback_to(),
     omissing,
     0,
     this);
@@ -306,7 +307,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;
 
@@ -324,6 +329,7 @@ void PGLog::rewind_divergent_log(eversion_t newhead,
     divergent,
     info,
     log.get_can_rollback_to(),
+    original_crt,
     missing,
     rollbacker,
     this);
@@ -445,6 +451,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 2c7a1c992a850912a0aa89976b2b74e9fc60fb77..dc282b183f2848ea2eabf9f728f3a6fb792dc052 100644 (file)
@@ -844,6 +844,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
@@ -907,6 +908,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
@@ -1009,7 +1012,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;
@@ -1022,7 +1028,7 @@ protected:
       for (list<pg_log_entry_t>::const_reverse_iterator i = entries.rbegin();
           i != entries.rend();
           ++i) {
-       assert(i->can_rollback() && i->version > olog_can_rollback_to);
+       assert(i->can_rollback() && i->version > original_can_rollback_to);
        ldpp_dout(dpp, 10) << __func__ << ": hoid " << hoid
                           << " rolling back " << *i << dendl;
        if (rollbacker)
@@ -1059,6 +1065,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
@@ -1074,6 +1081,7 @@ protected:
        i->second,
        oinfo,
        olog_can_rollback_to,
+        original_can_rollback_to,
        omissing,
        rollbacker,
        dpp);
@@ -1097,6 +1105,7 @@ protected:
       entries,
       info,
       log.get_can_rollback_to(),
+      log.get_can_rollback_to(),
       missing,
       rollbacker,
       this);
index cdae317ae86fc56cd446cfd53158935d303aa176..9076784f416e36196187956517550961a89d8a98 100644 (file)
@@ -2938,6 +2938,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
@@ -2964,6 +2965,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