Merge pull request #7617 from liewegas/wip-14745

osd: fix forced prmootion for CALL ops

Reviewed-by: Sage Weil <sage@redhat.com>
This commit is contained in:
Sage Weil 2016-02-24 10:45:59 -08:00
commit 48d007f659
2 changed files with 124 additions and 6 deletions

View File

@ -2147,11 +2147,13 @@ ReplicatedPG::cache_result_t ReplicatedPG::maybe_handle_cache_detail(
return cache_result_t::BLOCKED_FULL;
}
if (!hit_set && (must_promote || !op->need_skip_promote()) ) {
if (must_promote || (!hit_set && !op->need_skip_promote())) {
promote_object(obc, missing_oid, oloc, op, promote_obc);
return cache_result_t::BLOCKED_PROMOTE;
} else if (op->may_write() || op->may_cache()) {
if (can_proxy_write && !must_promote) {
}
if (op->may_write() || op->may_cache()) {
if (can_proxy_write) {
do_proxy_write(op, missing_oid);
} else {
// promote if can't proxy the write
@ -2170,7 +2172,7 @@ ReplicatedPG::cache_result_t ReplicatedPG::maybe_handle_cache_detail(
return cache_result_t::HANDLED_PROXY;
} else {
bool did_proxy_read = false;
if (can_proxy_read && !must_promote) {
if (can_proxy_read) {
do_proxy_read(op);
did_proxy_read = true;
} else {
@ -2228,7 +2230,7 @@ ReplicatedPG::cache_result_t ReplicatedPG::maybe_handle_cache_detail(
case pg_pool_t::CACHEMODE_READFORWARD:
// Do writeback to the cache tier for writes
if (op->may_write() || write_ordered) {
if (op->may_write() || write_ordered || must_promote) {
if (agent_state &&
agent_state->evict_mode == TierAgentState::EVICT_MODE_FULL) {
dout(20) << __func__ << " cache pool full, waiting" << dendl;
@ -2245,7 +2247,7 @@ ReplicatedPG::cache_result_t ReplicatedPG::maybe_handle_cache_detail(
case pg_pool_t::CACHEMODE_READPROXY:
// Do writeback to the cache tier for writes
if (op->may_write() || write_ordered) {
if (op->may_write() || write_ordered || must_promote) {
if (agent_state &&
agent_state->evict_mode == TierAgentState::EVICT_MODE_FULL) {
dout(20) << __func__ << " cache pool full, waiting" << dendl;

View File

@ -4637,6 +4637,122 @@ TEST_F(LibRadosTwoPoolsECPP, TryFlushReadRace) {
test_lock.Unlock();
}
TEST_F(LibRadosTierECPP, CallForcesPromote) {
Rados cluster;
std::string pool_name = get_temp_pool_name();
std::string cache_pool_name = pool_name + "-cache";
ASSERT_EQ("", create_one_ec_pool_pp(pool_name, cluster));
ASSERT_EQ(0, cluster.pool_create(cache_pool_name.c_str()));
IoCtx cache_ioctx;
ASSERT_EQ(0, cluster.ioctx_create(cache_pool_name.c_str(), cache_ioctx));
IoCtx ioctx;
ASSERT_EQ(0, cluster.ioctx_create(pool_name.c_str(), ioctx));
// configure cache
bufferlist inbl;
ASSERT_EQ(0, cluster.mon_command(
"{\"prefix\": \"osd tier add\", \"pool\": \"" + pool_name +
"\", \"tierpool\": \"" + cache_pool_name + "\"}",
inbl, NULL, NULL));
ASSERT_EQ(0, cluster.mon_command(
"{\"prefix\": \"osd tier set-overlay\", \"pool\": \"" + pool_name +
"\", \"overlaypool\": \"" + cache_pool_name + "\"}",
inbl, NULL, NULL));
ASSERT_EQ(0, cluster.mon_command(
"{\"prefix\": \"osd tier cache-mode\", \"pool\": \"" + cache_pool_name +
"\", \"mode\": \"writeback\"}",
inbl, NULL, NULL));
// set things up such that the op would normally be proxied
ASSERT_EQ(0, cluster.mon_command(
set_pool_str(cache_pool_name, "hit_set_count", 2),
inbl, NULL, NULL));
ASSERT_EQ(0, cluster.mon_command(
set_pool_str(cache_pool_name, "hit_set_period", 600),
inbl, NULL, NULL));
ASSERT_EQ(0, cluster.mon_command(
set_pool_str(cache_pool_name, "hit_set_type",
"explicit_object"),
inbl, NULL, NULL));
ASSERT_EQ(0, cluster.mon_command(
set_pool_str(cache_pool_name, "min_read_recency_for_promote",
"4"),
inbl, NULL, NULL));
// wait for maps to settle
cluster.wait_for_latest_osdmap();
// create/dirty object
bufferlist bl;
bl.append("hi there");
{
ObjectWriteOperation op;
op.write_full(bl);
ASSERT_EQ(0, ioctx.operate("foo", &op));
}
// flush
{
ObjectReadOperation op;
op.cache_flush();
librados::AioCompletion *completion = cluster.aio_create_completion();
ASSERT_EQ(0, cache_ioctx.aio_operate(
"foo", completion, &op,
librados::OPERATION_IGNORE_OVERLAY, NULL));
completion->wait_for_safe();
ASSERT_EQ(0, completion->get_return_value());
completion->release();
}
// evict
{
ObjectReadOperation op;
op.cache_evict();
librados::AioCompletion *completion = cluster.aio_create_completion();
ASSERT_EQ(0, cache_ioctx.aio_operate("foo", completion, &op,
librados::OPERATION_IGNORE_CACHE,
NULL));
completion->wait_for_safe();
ASSERT_EQ(0, completion->get_return_value());
completion->release();
}
// call
{
ObjectReadOperation op;
bufferlist bl;
op.exec("rbd", "get_id", bl);
bufferlist out;
// should get EIO (not an rbd object), not -EOPNOTSUPP (we didn't promote)
ASSERT_EQ(-5, ioctx.operate("foo", &op, &out));
}
// make sure foo is back in the cache tier
{
NObjectIterator it = cache_ioctx.nobjects_begin();
ASSERT_TRUE(it != cache_ioctx.nobjects_end());
ASSERT_TRUE(it->get_oid() == string("foo"));
++it;
ASSERT_TRUE(it == cache_ioctx.nobjects_end());
}
// tear down tiers
ASSERT_EQ(0, cluster.mon_command(
"{\"prefix\": \"osd tier remove-overlay\", \"pool\": \"" + pool_name +
"\"}",
inbl, NULL, NULL));
ASSERT_EQ(0, cluster.mon_command(
"{\"prefix\": \"osd tier remove\", \"pool\": \"" + pool_name +
"\", \"tierpool\": \"" + cache_pool_name + "\"}",
inbl, NULL, NULL));
// wait for maps to settle before next test
cluster.wait_for_latest_osdmap();
ASSERT_EQ(0, cluster.pool_delete(cache_pool_name.c_str()));
ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
}
TEST_F(LibRadosTierECPP, HitSetNone) {
{
list< pair<time_t,time_t> > ls;