osd/,rados/: modify TIER_FLUSH to implicitly make an object a manifest object

Existing object-dedup command always creates temporary object and
perform set-chunk to make the input object manifest---this is because
current tier-flush, which is called by object-dedup, works only if
the target object is manifest, otherwise it just return 0.

So, object-dedup may not work if the target is already manifest.
Moreover, it causes unnecessary overhead if the target object is not manifest.

To solve these, this commit makes existing tier-flush to
change object's state to manifest implicitly.

With this change, the only required operation when calling object-dedup
is a tier-flush and object-dedup can work with the manifest object.

Signed-off-by: Myoungwon Oh <myoungwon.oh@samsung.com>
This commit is contained in:
myoungwon oh 2022-05-01 22:48:14 +09:00
parent 23eace17e0
commit ea749df517
5 changed files with 33 additions and 58 deletions

View File

@ -316,6 +316,17 @@ function test_dedup_object()
die "Scrub failed expecting bar is removed"
fi
CHUNK_OID=$(echo -n "There HIHIHI" | sha1sum | awk '{print $1}')
RESULT=$($DEDUP_TOOL --op dump-chunk-refs --chunk-pool $CHUNK_POOL --object $CHUNK_OID | grep bar)
if [ -z "$RESULT" ] ; then
$CEPH_TOOL osd pool delete $POOL $POOL --yes-i-really-really-mean-it
$CEPH_TOOL osd pool delete $CHUNK_POOL $CHUNK_POOL --yes-i-really-really-mean-it
die "Scrub failed expecting bar is removed"
fi
# rerun tier-flush
RESULT=$($DEDUP_TOOL --pool $POOL --op object-dedup --object bar --chunk-pool $CHUNK_POOL --fingerprint-algorithm sha1 --dedup-cdc-chunk-size 4096)
CHUNK_OID=$(echo -n "There HIHIHI" | sha1sum | awk '{print $1}')
RESULT=$($DEDUP_TOOL --op dump-chunk-refs --chunk-pool $CHUNK_POOL --object $CHUNK_OID | grep bar)
if [ -z "$RESULT" ] ; then

View File

@ -758,8 +758,11 @@ inline namespace v14_2_0 {
void set_chunk(uint64_t src_offset, uint64_t src_length, const IoCtx& tgt_ioctx,
std::string tgt_oid, uint64_t tgt_offset, int flag = 0);
/**
* flush a manifest tier object to backing tier; will block racing
* updates.
* flush a manifest tier object to backing tier, performing deduplication;
* will block racing updates.
*
* Invoking tier_flush() implicitly makes a manifest object even if
* the target object is not manifest.
*/
void tier_flush();
/**

View File

@ -7388,13 +7388,9 @@ int PrimaryLogPG::do_osd_ops(OpContext *ctx, vector<OSDOp>& ops)
result = -EOPNOTSUPP;
break;
}
if (!obs.oi.has_manifest()) {
result = 0;
break;
}
if (oi.is_dirty()) {
result = start_flush(ctx->op, ctx->obc, true, NULL, std::nullopt);
if (oi.is_dirty() || !obs.oi.has_manifest()) {
result = start_flush(ctx->op, ctx->obc, true, NULL, std::nullopt, true);
if (result == -EINPROGRESS)
result = -EAGAIN;
} else {
@ -10675,6 +10671,11 @@ int PrimaryLogPG::finish_set_dedup(hobject_t oid, int r, ceph_tid_t tid, uint64_
ctx->new_obs = obc->obs;
ctx->new_obs.oi.clear_flag(object_info_t::FLAG_DIRTY);
--ctx->delta_stats.num_objects_dirty;
if (!ctx->obs->oi.has_manifest()) {
ctx->delta_stats.num_objects_manifest++;
ctx->new_obs.oi.set_flag(object_info_t::FLAG_MANIFEST);
ctx->new_obs.oi.manifest.type = object_manifest_t::TYPE_CHUNKED;
}
/*
* Let's assume that there is a manifest snapshotted object, and we issue tier_flush() to head.
@ -10756,7 +10757,8 @@ int PrimaryLogPG::finish_set_manifest_refcount(hobject_t oid, int r, ceph_tid_t
int PrimaryLogPG::start_flush(
OpRequestRef op, ObjectContextRef obc,
bool blocking, hobject_t *pmissing,
std::optional<std::function<void()>> &&on_flush)
std::optional<std::function<void()>> &&on_flush,
bool force_dedup)
{
const object_info_t& oi = obc->obs.oi;
const hobject_t& soid = oi.soid;
@ -10778,7 +10780,8 @@ int PrimaryLogPG::start_flush(
snapset = obc->ssc->snapset;
}
if (obc->obs.oi.has_manifest() && obc->obs.oi.manifest.is_chunked()) {
if ((obc->obs.oi.has_manifest() && obc->obs.oi.manifest.is_chunked())
|| force_dedup) {
// current dedup tier only supports blocking operation
if (!blocking) {
return -EOPNOTSUPP;
@ -10854,7 +10857,8 @@ int PrimaryLogPG::start_flush(
osd->objecter->op_cancel(tids, -ECANCELED);
}
if (obc->obs.oi.has_manifest() && obc->obs.oi.manifest.is_chunked()) {
if ((obc->obs.oi.has_manifest() && obc->obs.oi.manifest.is_chunked())
|| force_dedup) {
int r = start_dedup(op, obc);
if (r != -EINPROGRESS) {
if (blocking)

View File

@ -1356,7 +1356,8 @@ protected:
int start_flush(
OpRequestRef op, ObjectContextRef obc,
bool blocking, hobject_t *pmissing,
std::optional<std::function<void()>> &&on_flush);
std::optional<std::function<void()>> &&on_flush,
bool force_dedup = false);
void finish_flush(hobject_t oid, ceph_tid_t tid, int r);
int try_flush_mark_clean(FlushOpRef fop);
void cancel_flush(FlushOpRef fop, bool requeue, std::vector<ceph_tid_t> *tids);

View File

@ -1126,61 +1126,17 @@ int make_dedup_object(const po::variables_map &opts)
return ret;
}
/*
* TODO: add a better way to make an object a manifest object.
* We're using set_chunk with an incorrect object here simply to make
* the object a manifest object, the tier_flush() will remove
* it and replace it with the real contents.
*/
// convert object to manifest object
auto create_new_deduped_object =
[&chunk_io_ctx, &io_ctx](string object_name) -> int {
int ret = 0;
ObjectWriteOperation op;
bufferlist temp;
temp.append("temp");
op.write_full(temp);
auto gen_r_num = [] () -> string {
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<uint64_t> dist;
uint64_t r_num = dist(gen);
return to_string(r_num);
};
string temp_oid = gen_r_num();
// create temp chunk object for set-chunk
ret = chunk_io_ctx.operate(temp_oid, &op);
if (ret == -EEXIST) {
// one more try
temp_oid = gen_r_num();
ret = chunk_io_ctx.operate(temp_oid, &op);
}
if (ret < 0) {
cerr << " operate fail : " << cpp_strerror(ret) << std::endl;
return ret;
}
// set-chunk to make manifest object
ObjectReadOperation chunk_op;
chunk_op.set_chunk(0, 4, chunk_io_ctx, temp_oid, 0,
CEPH_OSD_OP_FLAG_WITH_REFERENCE);
ret = io_ctx.operate(object_name, &chunk_op, NULL);
if (ret < 0) {
cerr << " set_chunk fail : " << cpp_strerror(ret) << std::endl;
return ret;
}
[&io_ctx](string object_name) -> int {
// tier-flush to perform deduplication
ObjectReadOperation flush_op;
flush_op.tier_flush();
ret = io_ctx.operate(object_name, &flush_op, NULL);
int ret = io_ctx.operate(object_name, &flush_op, NULL);
if (ret < 0) {
cerr << " tier_flush fail : " << cpp_strerror(ret) << std::endl;
return ret;
}
// tier-evict
ObjectReadOperation evict_op;
evict_op.tier_evict();