mirror of
https://github.com/ceph/ceph
synced 2025-03-11 02:39:05 +00:00
osd/ReplicatedPG: implement cache_evict
Signed-off-by: Sage Weil <sage@inktank.com>
This commit is contained in:
parent
8b9b7136ba
commit
4c014eddbe
@ -2483,6 +2483,7 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
|
||||
switch (op.op) {
|
||||
// non user-visible modifications
|
||||
case CEPH_OSD_OP_WATCH:
|
||||
case CEPH_OSD_OP_CACHE_EVICT:
|
||||
case CEPH_OSD_OP_UNDIRTY:
|
||||
break;
|
||||
default:
|
||||
@ -2761,6 +2762,21 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
|
||||
}
|
||||
break;
|
||||
|
||||
case CEPH_OSD_OP_CACHE_EVICT:
|
||||
++ctx->num_write;
|
||||
{
|
||||
if (pool.info.cache_mode == pg_pool_t::CACHEMODE_NONE) {
|
||||
result = -EINVAL;
|
||||
break;
|
||||
}
|
||||
if (oi.is_dirty()) {
|
||||
result = -EBUSY;
|
||||
break;
|
||||
}
|
||||
result = _delete_head(ctx, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case CEPH_OSD_OP_GETXATTR:
|
||||
++ctx->num_read;
|
||||
{
|
||||
@ -3249,7 +3265,7 @@ int ReplicatedPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
|
||||
// Cannot delete an object with watchers
|
||||
result = -EBUSY;
|
||||
} else {
|
||||
result = _delete_head(ctx);
|
||||
result = _delete_head(ctx, false);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -3795,7 +3811,7 @@ int ReplicatedPG::_get_tmap(OpContext *ctx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline int ReplicatedPG::_delete_head(OpContext *ctx)
|
||||
inline int ReplicatedPG::_delete_head(OpContext *ctx, bool no_whiteout)
|
||||
{
|
||||
SnapSet& snapset = ctx->new_snapset;
|
||||
ObjectState& obs = ctx->new_obs;
|
||||
@ -3803,7 +3819,7 @@ inline int ReplicatedPG::_delete_head(OpContext *ctx)
|
||||
const hobject_t& soid = oi.soid;
|
||||
ObjectStore::Transaction& t = ctx->op_t;
|
||||
|
||||
if (!obs.exists || obs.oi.is_whiteout())
|
||||
if (!obs.exists || (obs.oi.is_whiteout() && !no_whiteout))
|
||||
return -ENOENT;
|
||||
|
||||
if (oi.size > 0) {
|
||||
@ -3817,7 +3833,7 @@ inline int ReplicatedPG::_delete_head(OpContext *ctx)
|
||||
oi.size = 0;
|
||||
|
||||
// cache: writeback: set whiteout on delete?
|
||||
if (pool.info.cache_mode == pg_pool_t::CACHEMODE_WRITEBACK) {
|
||||
if (pool.info.cache_mode == pg_pool_t::CACHEMODE_WRITEBACK && !no_whiteout) {
|
||||
dout(20) << __func__ << " setting whiteout on " << soid << dendl;
|
||||
oi.set_flag(object_info_t::FLAG_WHITEOUT);
|
||||
t.truncate(coll, soid, 0);
|
||||
@ -3858,7 +3874,7 @@ int ReplicatedPG::_rollback_to(OpContext *ctx, ceph_osd_op& op)
|
||||
// Cannot delete an object with watchers
|
||||
ret = -EBUSY;
|
||||
} else {
|
||||
_delete_head(ctx);
|
||||
_delete_head(ctx, false);
|
||||
ret = 0;
|
||||
}
|
||||
} else if (-EAGAIN == ret) {
|
||||
|
@ -1116,7 +1116,7 @@ private:
|
||||
|
||||
int _get_tmap(OpContext *ctx, map<string, bufferlist> *out,
|
||||
bufferlist *header);
|
||||
int _delete_head(OpContext *ctx);
|
||||
int _delete_head(OpContext *ctx, bool no_whiteout);
|
||||
int _rollback_to(OpContext *ctx, ceph_osd_op& op);
|
||||
public:
|
||||
bool same_for_read_since(epoch_t e);
|
||||
|
@ -250,6 +250,120 @@ TEST(LibRadosTier, Whiteout) {
|
||||
ASSERT_EQ(0, destroy_one_pool_pp(base_pool_name, cluster));
|
||||
}
|
||||
|
||||
TEST(LibRadosTier, Evict) {
|
||||
Rados cluster;
|
||||
std::string base_pool_name = get_temp_pool_name();
|
||||
std::string cache_pool_name = base_pool_name + "-cache";
|
||||
ASSERT_EQ("", create_one_pool_pp(base_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 base_ioctx;
|
||||
ASSERT_EQ(0, cluster.ioctx_create(base_pool_name.c_str(), base_ioctx));
|
||||
|
||||
// create object
|
||||
{
|
||||
bufferlist bl;
|
||||
bl.append("hi there");
|
||||
ObjectWriteOperation op;
|
||||
op.write_full(bl);
|
||||
ASSERT_EQ(0, base_ioctx.operate("foo", &op));
|
||||
}
|
||||
|
||||
// configure cache
|
||||
bufferlist inbl;
|
||||
ASSERT_EQ(0, cluster.mon_command(
|
||||
"{\"prefix\": \"osd tier add\", \"pool\": \"" + base_pool_name +
|
||||
"\", \"tierpool\": \"" + cache_pool_name + "\"}",
|
||||
inbl, NULL, NULL));
|
||||
ASSERT_EQ(0, cluster.mon_command(
|
||||
"{\"prefix\": \"osd tier set-overlay\", \"pool\": \"" + base_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));
|
||||
|
||||
// wait for maps to settle
|
||||
cluster.wait_for_latest_osdmap();
|
||||
|
||||
// read, trigger a promote
|
||||
{
|
||||
bufferlist bl;
|
||||
ASSERT_EQ(1, base_ioctx.read("foo", bl, 1, 0));
|
||||
}
|
||||
|
||||
// read, trigger a whiteout, and a dirty object
|
||||
{
|
||||
bufferlist bl;
|
||||
ASSERT_EQ(-ENOENT, base_ioctx.read("bar", bl, 1, 0));
|
||||
ASSERT_EQ(-ENOENT, base_ioctx.read("bar", bl, 1, 0));
|
||||
ASSERT_EQ(0, base_ioctx.write("bar", bl, bl.length(), 0));
|
||||
}
|
||||
|
||||
// verify the object is present in the cache tier
|
||||
{
|
||||
ObjectIterator it = cache_ioctx.objects_begin();
|
||||
ASSERT_TRUE(it != cache_ioctx.objects_end());
|
||||
ASSERT_TRUE(it->first == string("foo") || it->first == string("bar"));
|
||||
++it;
|
||||
ASSERT_TRUE(it->first == string("foo") || it->first == string("bar"));
|
||||
++it;
|
||||
ASSERT_TRUE(it == cache_ioctx.objects_end());
|
||||
}
|
||||
|
||||
// evict
|
||||
{
|
||||
ObjectWriteOperation op;
|
||||
op.cache_evict();
|
||||
librados::AioCompletion *completion = cluster.aio_create_completion();
|
||||
ASSERT_EQ(0, cache_ioctx.aio_operate(
|
||||
"foo", completion, &op, librados::OPERATION_IGNORE_OVERLAY));
|
||||
completion->wait_for_safe();
|
||||
ASSERT_EQ(0, completion->get_return_value());
|
||||
completion->release();
|
||||
}
|
||||
{
|
||||
ObjectWriteOperation op;
|
||||
op.cache_evict();
|
||||
librados::AioCompletion *completion = cluster.aio_create_completion();
|
||||
ASSERT_EQ(0, cache_ioctx.aio_operate(
|
||||
"fooberdoodle", completion, &op,
|
||||
librados::OPERATION_IGNORE_OVERLAY));
|
||||
completion->wait_for_safe();
|
||||
ASSERT_EQ(-ENOENT, completion->get_return_value());
|
||||
completion->release();
|
||||
}
|
||||
{
|
||||
ObjectWriteOperation op;
|
||||
op.cache_evict();
|
||||
librados::AioCompletion *completion = cluster.aio_create_completion();
|
||||
ASSERT_EQ(0, cache_ioctx.aio_operate(
|
||||
"bar", completion, &op,
|
||||
librados::OPERATION_IGNORE_OVERLAY));
|
||||
completion->wait_for_safe();
|
||||
ASSERT_EQ(-EBUSY, completion->get_return_value());
|
||||
completion->release();
|
||||
}
|
||||
|
||||
// tear down tiers
|
||||
ASSERT_EQ(0, cluster.mon_command(
|
||||
"{\"prefix\": \"osd tier remove-overlay\", \"pool\": \"" + base_pool_name +
|
||||
"\"}",
|
||||
inbl, NULL, NULL));
|
||||
ASSERT_EQ(0, cluster.mon_command(
|
||||
"{\"prefix\": \"osd tier remove\", \"pool\": \"" + base_pool_name +
|
||||
"\", \"tierpool\": \"" + cache_pool_name + "\"}",
|
||||
inbl, NULL, NULL));
|
||||
|
||||
base_ioctx.close();
|
||||
cache_ioctx.close();
|
||||
|
||||
cluster.pool_delete(cache_pool_name.c_str());
|
||||
ASSERT_EQ(0, destroy_one_pool_pp(base_pool_name, cluster));
|
||||
}
|
||||
|
||||
TEST(LibRadosTier, HitSetNone) {
|
||||
Rados cluster;
|
||||
std::string pool_name = get_temp_pool_name();
|
||||
|
Loading…
Reference in New Issue
Block a user