]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd/cache/pwl:fix clean vs bytes_dirty cache state inconsistency 49055/head
authorYin Congmin <congmin.yin@intel.com>
Wed, 19 Oct 2022 02:47:35 +0000 (10:47 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Fri, 25 Nov 2022 11:11:43 +0000 (12:11 +0100)
The space of the pwl is pre allocated. In check_allocation(), the space
is reserved, and then the op is completed after a period of process.
When checking resource is successful and the resource is reserved,
dirty_bytes has been increased. But new entry will not be added
to m_dirty_log_entries until the op is finished. This time gap
leads to inconsistencies.

Put update_image_cache_state() in check_allocation() to fix this
issue. It is now considered that as long as space is reserved
and the op is started, the cache is dirty.

Fixes: https://tracker.ceph.com/issues/57872
Signed-off-by: Yin Congmin <congmin.yin@intel.com>
(cherry picked from commit e2b079137473d4c819d58ef6466450a5c4a8b8af)

src/librbd/cache/pwl/AbstractWriteLog.cc

index 713fc3caf0837acca22756d363c6f0a8a3d928ce..a59a59d1ca03d7d90a767eb9fbcc2eb1fcd37b72 100644 (file)
@@ -1307,7 +1307,6 @@ void AbstractWriteLog<I>::complete_op_log_entries(GenericLogOperations &&ops,
 {
   GenericLogEntries dirty_entries;
   int published_reserves = 0;
-  bool need_update_state = false;
   ldout(m_image_ctx.cct, 20) << __func__ << ": completing" << dendl;
   for (auto &op : ops) {
     utime_t now = ceph_clock_now();
@@ -1327,11 +1326,6 @@ void AbstractWriteLog<I>::complete_op_log_entries(GenericLogOperations &&ops,
       std::lock_guard locker(m_lock);
       m_unpublished_reserves -= published_reserves;
       m_dirty_log_entries.splice(m_dirty_log_entries.end(), dirty_entries);
-      if (m_cache_state->clean && !this->m_dirty_log_entries.empty()) {
-        m_cache_state->clean = false;
-        update_image_cache_state();
-        need_update_state = true;
-      }
     }
     op->complete(result);
     m_perfcounter->tinc(l_librbd_pwl_log_op_dis_to_app_t,
@@ -1346,10 +1340,6 @@ void AbstractWriteLog<I>::complete_op_log_entries(GenericLogOperations &&ops,
                       log_entry->ram_entry.write_bytes);
     m_perfcounter->tinc(l_librbd_pwl_log_op_app_to_cmp_t, now - op->log_append_start_time);
   }
-  if (need_update_state) {
-    std::unique_lock locker(m_lock);
-    write_image_cache_state(locker);
-  }
   // New entries may be flushable
   {
     std::lock_guard locker(m_lock);
@@ -1539,7 +1529,7 @@ bool AbstractWriteLog<I>::check_allocation(
   }
 
   if (alloc_succeeds) {
-    std::lock_guard locker(m_lock);
+    std::unique_lock locker(m_lock);
     /* We need one free log entry per extent (each is a separate entry), and
      * one free "lane" for remote replication. */
     if ((m_free_lanes >= num_lanes) &&
@@ -1551,6 +1541,11 @@ bool AbstractWriteLog<I>::check_allocation(
       m_bytes_allocated += bytes_allocated;
       m_bytes_cached += bytes_cached;
       m_bytes_dirty += bytes_dirtied;
+      if (m_cache_state->clean && bytes_dirtied > 0) {
+        m_cache_state->clean = false;
+        update_image_cache_state();
+        write_image_cache_state(locker);
+      }
     } else {
       alloc_succeeds = false;
     }