]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mon: OSDMonitor: disallow nonsensical cache-mode transitions
authorJoao Eduardo Luis <joao.luis@inktank.com>
Sat, 3 May 2014 02:42:19 +0000 (03:42 +0100)
committerSage Weil <sage@redhat.com>
Fri, 1 Aug 2014 23:40:43 +0000 (16:40 -0700)
Fixes: 8155
Signed-off-by: Joao Eduardo Luis <joao.luis@inktank.com>
(cherry picked from commit fd970bbc95d89bf66c9551feca17ac0afbf4d1e2)

PendingReleaseNotes
qa/workunits/cephtool/test.sh
src/mon/OSDMonitor.cc

index 39d8f4b5fae8bf9645a3d125ce209ad196102a1d..34103ec4ae39d5b0c10409e1b917327e881854b0 100644 (file)
@@ -2,3 +2,7 @@
 v0.81
 -----
 
+- Disallow nonsensical 'tier cache-mode' transitions.  From this point
+  onward, 'writeback' can only transition to 'forward' and 'forward'
+  can transition to 1) 'writeback' if there are dirty objects, or 2) any if
+  there are no dirty objects.
index a07dd61b7605a4acbf6caf0a45bbebab4b6bf879..4786514138634b2c40871da1f4f829637d3f2e8d 100755 (executable)
@@ -83,7 +83,31 @@ ceph osd pool create cache2 2
 ceph osd tier add data cache
 ceph osd tier add data cache2
 expect_false ceph osd tier add metadata cache
+# test some state transitions
 ceph osd tier cache-mode cache writeback
+ceph osd tier cache-mode cache forward
+ceph osd tier cache-mode cache readonly
+ceph osd tier cache-mode cache forward
+ceph osd tier cache-mode cache none
+ceph osd tier cache-mode cache writeback
+expect_false ceph osd tier cache-mode cache none
+expect_false ceph osd tier cache-mode cache readonly
+# test with dirty objects in the tier pool
+# tier pool currently set to 'writeback'
+rados -p cache put /etc/passwd /etc/passwd
+ceph tell osd.* flush_pg_stats || true
+# 1 dirty object in pool 'cache'
+ceph osd tier cache-mode cache forward
+expect_false ceph osd tier cache-mode cache none
+expect_false ceph osd tier cache-mode cache readonly
+ceph osd tier cache-mode cache writeback
+# remove object from tier pool
+rados -p cache rm /etc/passwd
+rados -p cache cache-flush-evict-all
+ceph tell osd.* flush_pg_stats || true
+# no dirty objects in pool 'cache'
+ceph osd tier cache-mode cache forward
+ceph osd tier cache-mode cache none
 ceph osd tier cache-mode cache readonly
 TRIES=0
 while ! ceph osd pool set cache pg_num 3 --yes-i-really-mean-it 2>$TMPFILE
index 7c4f198a51c19ddfe1b17ebd515a0b6db6d12a0d..a1651c4ab479793a2f6e0c07d958a2a109cfe34a 100644 (file)
@@ -5193,6 +5193,50 @@ done:
       goto reply;
     }
 
+    /* Mode description:
+     *
+     *  none:       No cache-mode defined
+     *  forward:    Forward all reads and writes to base pool
+     *  writeback:  Cache writes, promote reads from base pool
+     *  readonly:   Forward writes to base pool
+     *
+     * Hence, these are the allowed transitions:
+     *
+     *  none -> any
+     *  forward -> writeback || any IF num_objects_dirty == 0
+     *  writeback -> forward
+     *  readonly -> any
+     */
+
+    // We check if the transition is valid against the current pool mode, as
+    // it is the only committed state thus far.  We will blantly squash
+    // whatever mode is on the pending state.
+
+    if (p->cache_mode == pg_pool_t::CACHEMODE_WRITEBACK &&
+        mode != pg_pool_t::CACHEMODE_FORWARD) {
+      ss << "unable to set cache-mode '" << pg_pool_t::get_cache_mode_name(mode)
+         << "' on a '" << pg_pool_t::get_cache_mode_name(p->cache_mode)
+         << "' pool; only '"
+         << pg_pool_t::get_cache_mode_name(pg_pool_t::CACHEMODE_FORWARD)
+        << "' allowed.";
+      err = -EINVAL;
+      goto reply;
+    }
+    if (p->cache_mode == pg_pool_t::CACHEMODE_FORWARD &&
+               mode != pg_pool_t::CACHEMODE_WRITEBACK) {
+
+      const pool_stat_t& tier_stats =
+        mon->pgmon()->pg_map.get_pg_pool_sum_stat(pool_id);
+
+      if (tier_stats.stats.sum.num_objects_dirty > 0) {
+        ss << "unable to set cache-mode '"
+           << pg_pool_t::get_cache_mode_name(mode) << "' on pool '" << poolstr
+           << "': dirty objects found";
+        err = -EBUSY;
+        goto reply;
+      }
+    }
+
     // go
     pending_inc.get_new_pool(pool_id, p)->cache_mode = mode;
     ss << "set cache-mode for pool '" << poolstr