From: Joao Eduardo Luis Date: Sat, 3 May 2014 02:42:19 +0000 (+0100) Subject: mon: OSDMonitor: disallow nonsensical cache-mode transitions X-Git-Tag: v0.81~73^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F1740%2Fhead;p=ceph.git mon: OSDMonitor: disallow nonsensical cache-mode transitions Fixes: 8155 Signed-off-by: Joao Eduardo Luis --- diff --git a/PendingReleaseNotes b/PendingReleaseNotes index 39d8f4b5fae8..34103ec4ae39 100644 --- a/PendingReleaseNotes +++ b/PendingReleaseNotes @@ -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. diff --git a/qa/workunits/cephtool/test.sh b/qa/workunits/cephtool/test.sh index d5e9cef486f6..8ed6bd12c015 100755 --- a/qa/workunits/cephtool/test.sh +++ b/qa/workunits/cephtool/test.sh @@ -58,7 +58,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 diff --git a/src/mon/OSDMonitor.cc b/src/mon/OSDMonitor.cc index 5877e4ab9f7c..cc417c4f4355 100644 --- a/src/mon/OSDMonitor.cc +++ b/src/mon/OSDMonitor.cc @@ -5140,6 +5140,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