test: fix TierFlushDuringFlush to wait until dedup_tier is set on base pool

When start_dedup() is called while the base pool is not set the dedup_tier,
it is not possible to know the target pool of the chunk object.

1. User set the dedup_tier on a base pool by mon_command().
2. User issues tier_flush on the object which has a manifest (base pool)
  before the dedup_tier is applied on the base pool.
3. OSD calls start_dedup() to flush the chunk objects to chunk pool.
4. OSD calls get_dedup_tier() to get the chunk pool of the base pool,
  but it is not possible to know the chunk pool.
5. get_dedup_tier() returns 0 because it is not applied on the base pool yet.
6. This makes refcount_manifest() lost it's way to chunk pool.

To prevent this issue, start_dedup() has to be called after dedup_tier is set
on the base pool. To do so, this commit prohibits getting chunk pool id if
dedup_tier is not set.

Fixes: http://tracker.ceph.com/issues/53855

Signed-off-by: Sungmin Lee <sung_min.lee@samsung.com>
This commit is contained in:
Sungmin Lee 2022-02-14 14:15:00 +09:00
parent 9596630073
commit 66ad91eb1e
2 changed files with 75 additions and 1 deletions

View File

@ -10457,7 +10457,11 @@ int PrimaryLogPG::start_dedup(OpRequestRef op, ObjectContextRef obc)
if (pool.info.get_fingerprint_type() == pg_pool_t::TYPE_FINGERPRINT_NONE) {
dout(0) << " fingerprint algorithm is not set " << dendl;
return -EINVAL;
}
}
if (pool.info.get_dedup_tier() <= 0) {
dout(10) << " dedup tier is not set " << dendl;
return -EINVAL;
}
/*
* The operations to make dedup chunks are tracked by a ManifestOp.
@ -10593,6 +10597,8 @@ hobject_t PrimaryLogPG::get_fpoid_from_chunk(const hobject_t soid, bufferlist& c
pg_t raw_pg;
object_locator_t oloc(soid);
oloc.pool = pool.info.get_dedup_tier();
// check if dedup_tier isn't set
ceph_assert(oloc.pool > 0);
get_osdmap()->object_locator_to_pg(fp_oid, oloc, raw_pg);
hobject_t target(fp_oid, oloc.key, snapid_t(),
raw_pg.ps(), raw_pg.pool(),

View File

@ -5659,6 +5659,9 @@ TEST_F(LibRadosTwoPoolsPP, TierFlushDuringFlush) {
ASSERT_EQ(0, ioctx.operate("bar", &op));
}
// wait for maps to settle
cluster.wait_for_latest_osdmap();
// set-chunk to set manifest object
{
ObjectReadOperation op;
@ -9143,3 +9146,68 @@ TEST_F(LibRadosTwoPoolsPP, HelloWriteReturn) {
ASSERT_EQ("", std::string(out.c_str(), out.length()));
}
}
TEST_F(LibRadosTwoPoolsPP, TierFlushDuringUnsetDedupTier) {
// skip test if not yet octopus
if (_get_required_osd_release(cluster) < "octopus") {
cout << "cluster is not yet octopus, skipping test" << std::endl;
return;
}
bufferlist inbl;
// set dedup parameters without dedup_tier
ASSERT_EQ(0, cluster.mon_command(
set_pool_str(cache_pool_name, "fingerprint_algorithm", "sha1"),
inbl, NULL, NULL));
ASSERT_EQ(0, cluster.mon_command(
set_pool_str(cache_pool_name, "dedup_chunk_algorithm", "fastcdc"),
inbl, NULL, NULL));
ASSERT_EQ(0, cluster.mon_command(
set_pool_str(cache_pool_name, "dedup_cdc_chunk_size", 1024),
inbl, NULL, NULL));
// create object
bufferlist gbl;
{
generate_buffer(1024*8, &gbl);
ObjectWriteOperation op;
op.write_full(gbl);
ASSERT_EQ(0, cache_ioctx.operate("foo", &op));
}
{
bufferlist bl;
bl.append("there hiHI");
ObjectWriteOperation op;
op.write_full(bl);
ASSERT_EQ(0, ioctx.operate("bar", &op));
}
// wait for maps to settle
cluster.wait_for_latest_osdmap();
// set-chunk to set manifest object
{
ObjectReadOperation op;
op.set_chunk(0, 2, ioctx, "bar", 0, CEPH_OSD_OP_FLAG_WITH_REFERENCE);
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_complete();
ASSERT_EQ(0, completion->get_return_value());
completion->release();
}
// flush to check if proper error is returned
{
ObjectReadOperation op;
op.tier_flush();
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_complete();
ASSERT_EQ(-EINVAL, completion->get_return_value());
completion->release();
}
}