}
cls_rgw_obj_key dest_key = op.key;
- if (dest_key.instance == "null") {
- dest_key.instance.clear();
- }
BIVerObjEntry obj(hctx, dest_key);
BIOLHEntry olh(hctx, dest_key);
rgw_bucket_entry_ver ver;
ver.epoch = (op.olh_epoch ? op.olh_epoch : olh.get_epoch());
+ if (op.null_verid) {
+ op.bilog_flags = op.bilog_flags | RGW_BILOG_FLAG_VERSIONED_OP | RGW_BILOG_NULL_VERSION;
+ } else {
+ op.bilog_flags = op.bilog_flags | RGW_BILOG_FLAG_VERSIONED_OP;
+ }
+
real_time mtime = obj.mtime(); /* mtime has no real meaning in
* instance removal context */
ret = log_index_operation(hctx, op.key, CLS_RGW_OP_UNLINK_INSTANCE, op.op_tag,
mtime, ver,
CLS_RGW_STATE_COMPLETE, header.ver, header.max_marker,
- op.bilog_flags | RGW_BILOG_FLAG_VERSIONED_OP, NULL, NULL, &op.zones_trace);
+ op.bilog_flags, NULL, NULL, &op.zones_trace);
if (ret < 0)
return ret;
int cls_rgw_bucket_unlink_instance(librados::IoCtx& io_ctx, const string& oid,
const cls_rgw_obj_key& key, const string& op_tag,
- const string& olh_tag, uint64_t olh_epoch, bool log_op, const rgw_zone_set& zones_trace)
+ const string& olh_tag, uint64_t olh_epoch, bool log_op,
+ bool null_verid, const rgw_zone_set& zones_trace)
{
librados::ObjectWriteOperation op;
- cls_rgw_bucket_unlink_instance(op, key, op_tag, olh_tag, olh_epoch, log_op, zones_trace);
+ cls_rgw_bucket_unlink_instance(op, key, op_tag, olh_tag, olh_epoch, log_op, null_verid, zones_trace);
int r = io_ctx.operate(oid, &op);
if (r < 0)
return r;
void cls_rgw_bucket_unlink_instance(librados::ObjectWriteOperation& op,
const cls_rgw_obj_key& key, const string& op_tag,
- const string& olh_tag, uint64_t olh_epoch, bool log_op, const rgw_zone_set& zones_trace)
+ const string& olh_tag, uint64_t olh_epoch, bool log_op,
+ bool null_verid, const rgw_zone_set& zones_trace)
{
bufferlist in, out;
rgw_cls_unlink_instance_op call;
call.olh_tag = olh_tag;
call.log_op = log_op;
call.zones_trace = zones_trace;
+ call.null_verid = null_verid;
encode(call, in);
op.exec(RGW_CLASS, RGW_BUCKET_UNLINK_INSTANCE, in);
}
uint64_t olh_epoch, ceph::real_time unmod_since, bool high_precision_time, bool log_op, const rgw_zone_set& zones_trace);
void cls_rgw_bucket_unlink_instance(librados::ObjectWriteOperation& op,
const cls_rgw_obj_key& key, const std::string& op_tag,
- const std::string& olh_tag, uint64_t olh_epoch, bool log_op, const rgw_zone_set& zones_trace);
+ const std::string& olh_tag, uint64_t olh_epoch, bool log_op, bool null_verid, const rgw_zone_set& zones_trace);
void cls_rgw_get_olh_log(librados::ObjectReadOperation& op, const cls_rgw_obj_key& olh, uint64_t ver_marker, const std::string& olh_tag, rgw_cls_read_olh_log_ret& log_ret, int& op_ret);
void cls_rgw_trim_olh_log(librados::ObjectWriteOperation& op, const cls_rgw_obj_key& olh, uint64_t ver, const std::string& olh_tag);
void cls_rgw_clear_olh(librados::ObjectWriteOperation& op, const cls_rgw_obj_key& olh, const std::string& olh_tag);
uint64_t olh_epoch, ceph::real_time unmod_since, bool high_precision_time, bool log_op, const rgw_zone_set& zones_trace);
int cls_rgw_bucket_unlink_instance(librados::IoCtx& io_ctx, const std::string& oid,
const cls_rgw_obj_key& key, const std::string& op_tag,
- const std::string& olh_tag, uint64_t olh_epoch, bool log_op, const rgw_zone_set& zones_trace);
+ const std::string& olh_tag, uint64_t olh_epoch, bool log_op,
+ bool null_verid, const rgw_zone_set& zones_trace);
int cls_rgw_get_olh_log(librados::IoCtx& io_ctx, std::string& oid, const cls_rgw_obj_key& olh, uint64_t ver_marker,
const std::string& olh_tag, rgw_cls_read_olh_log_ret& log_ret);
int cls_rgw_clear_olh(librados::IoCtx& io_ctx, std::string& oid, const cls_rgw_obj_key& olh, const std::string& olh_tag);
uint16_t bilog_flags;
std::string olh_tag;
rgw_zone_set zones_trace;
+ bool null_verid;
rgw_cls_unlink_instance_op() : olh_epoch(0), log_op(false), bilog_flags(0) {}
void encode(ceph::buffer::list& bl) const {
- ENCODE_START(3, 1, bl);
+ ENCODE_START(4, 1, bl);
encode(key, bl);
encode(op_tag, bl);
encode(olh_epoch, bl);
encode(bilog_flags, bl);
encode(olh_tag, bl);
encode(zones_trace, bl);
+ encode(null_verid, bl);
ENCODE_FINISH(bl);
}
void decode(ceph::buffer::list::const_iterator& bl) {
- DECODE_START(3, bl);
+ DECODE_START(4, bl);
decode(key, bl);
decode(op_tag, bl);
decode(olh_epoch, bl);
if (struct_v >= 3) {
decode(zones_trace, bl);
}
+ if (struct_v >= 4) {
+ decode(null_verid, bl);
+ }
DECODE_FINISH(bl);
}
enum RGWBILogFlags {
RGW_BILOG_FLAG_VERSIONED_OP = 0x1,
+ RGW_BILOG_NULL_VERSION = 0X2,
};
enum RGWCheckMTimeType {
bool is_versioned() {
return ((bilog_flags & RGW_BILOG_FLAG_VERSIONED_OP) != 0);
}
+
+ bool is_null_verid() {
+ return ((bilog_flags & RGW_BILOG_NULL_VERSION) != 0);
+ }
+
};
WRITE_CLASS_ENCODER(rgw_bi_log_entry)
int rgw_remove_object(const DoutPrefixProvider *dpp, rgw::sal::Driver* driver, rgw::sal::Bucket* bucket, rgw_obj_key& key, optional_yield y)
{
- if (key.instance.empty()) {
- key.instance = "null";
- }
std::unique_ptr<rgw::sal::Object> object = bucket->get_object(key);
if (versioned) {
del_op->params.versioning_status = BUCKET_VERSIONED;
}
+
del_op->params.olh_epoch = versioned_epoch;
del_op->params.marker_version_id = marker_version_id;
del_op->params.obj_owner.id = rgw_user(owner);
del_op->params.mtime = timestamp;
del_op->params.high_precision_time = true;
del_op->params.zones_trace = &zones_trace;
+ del_op->params.null_verid = false;
ret = del_op->delete_obj(dpp, null_yield, true);
if (ret < 0) {
rgw_obj_key key;
bool versioned;
+ bool null_verid;
std::optional<uint64_t> versioned_epoch;
rgw_bucket_entry_owner owner;
real_time timestamp;
RGWBucketSyncSingleEntryCR(RGWDataSyncCtx *_sc,
rgw_bucket_sync_pipe& _sync_pipe,
const rgw_obj_key& _key, bool _versioned,
+ bool _null_verid,
std::optional<uint64_t> _versioned_epoch,
real_time& _timestamp,
const rgw_bucket_entry_owner& _owner,
RGWSyncTraceNodeRef& _tn_parent) : RGWCoroutine(_sc->cct),
sc(_sc), sync_env(_sc->env),
sync_pipe(_sync_pipe), bs(_sync_pipe.info.source_bs),
- key(_key), versioned(_versioned), versioned_epoch(_versioned_epoch),
+ key(_key), versioned(_versioned),
+ null_verid(_null_verid),versioned_epoch(_versioned_epoch),
owner(_owner),
timestamp(_timestamp), op(_op),
op_state(_op_state),
if (op == CLS_RGW_OP_UNLINK_INSTANCE) {
versioned = true;
}
+ if (null_verid) {
+ key.instance = "null";
+ }
tn->log(10, SSTR("removing obj: " << sc->source_zone << "/" << bs.bucket << "/" << key << "[" << versioned_epoch.value_or(0) << "]"));
call(data_sync_module->remove_object(dpp, sc, sync_pipe, key, timestamp, versioned, versioned_epoch.value_or(0), &zones_trace));
// our copy of the object is more recent, continue as if it succeeded
using SyncCR = RGWBucketSyncSingleEntryCR<rgw_obj_key, rgw_obj_key>;
yield spawn(new SyncCR(sc, sync_pipe, entry->key,
false, /* versioned, only matters for object removal */
+ false,
entry->versioned_epoch, entry->mtime,
entry->owner, entry->get_modify_op(), CLS_RGW_STATE_COMPLETE,
entry->key, &marker_tracker, zones_trace, tn),
tn->log(20, SSTR("entry->timestamp=" << entry->timestamp));
using SyncCR = RGWBucketSyncSingleEntryCR<string, rgw_obj_key>;
spawn(new SyncCR(sc, sync_pipe, key,
- entry->is_versioned(), versioned_epoch,
+ entry->is_versioned(), entry->is_null_verid(), versioned_epoch,
entry->timestamp, owner, entry->op, entry->state,
cur_id, &marker_tracker, entry->zones_trace, tn),
false);
/* Need to remove the archived copy. */
ret = delete_obj(dpp, obj_ctx, archive_binfo, archive_obj,
- archive_binfo.versioning_status(), y);
+ archive_binfo.versioning_status(), y, false);
return ret;
};
}
result.delete_marker = dirent.is_delete_marker();
r = store->unlink_obj_instance(dpp, target->get_ctx(), target->get_bucket_info(), obj, params.olh_epoch,
- y, params.zones_trace, add_log);
+ y, params.null_verid, params.zones_trace, add_log);
if (r < 0) {
return r;
}
index_op.set_zones_trace(params.zones_trace);
index_op.set_bilog_flags(params.bilog_flags);
+ if (params.null_verid) {
+ index_op.set_bilog_flags(params.bilog_flags | RGW_BILOG_NULL_VERSION);
+ }
+
+
r = index_op.prepare(dpp, CLS_RGW_OP_DEL, &state->write_tag, y, log_op);
if (r < 0)
return r;
const RGWBucketInfo& bucket_info,
const rgw_obj& obj,
int versioning_status, optional_yield y,// versioning flags defined in enum RGWBucketFlags
+ bool null_verid,
uint16_t bilog_flags,
const real_time& expiration_time,
rgw_zone_set *zones_trace,
del_op.params.bilog_flags = bilog_flags;
del_op.params.expiration_time = expiration_time;
del_op.params.zones_trace = zones_trace;
+ del_op.params.null_verid = null_verid;
return del_op.delete_obj(y, dpp, log_op ? rgw::sal::FLAG_LOG_OP : 0);
}
RGWBucketInfo& bucket_info,
const rgw_obj& obj_instance,
const string& op_tag, const string& olh_tag,
- uint64_t olh_epoch, optional_yield y,
+ uint64_t olh_epoch, optional_yield y, bool null_verid,
rgw_zone_set *_zones_trace, bool log_op)
{
rgw_rados_ref ref;
op.assert_exists(); // bucket index shard must exist
cls_rgw_guard_bucket_resharding(op, -ERR_BUSY_RESHARDING);
cls_rgw_bucket_unlink_instance(op, key, op_tag,
- olh_tag, olh_epoch, log_op, zones_trace);
+ olh_tag, olh_epoch, log_op, null_verid, zones_trace);
return rgw_rados_operate(dpp, ref.ioctx, ref.obj.oid, &op, y);
}, y);
if (r < 0) {
bufferlist& olh_tag,
std::map<uint64_t, std::vector<rgw_bucket_olh_log_entry> >& log,
uint64_t *plast_ver,
- optional_yield y, rgw_zone_set* zones_trace,
- bool log_op)
+ optional_yield y,
+ bool null_verid,
+ rgw_zone_set* zones_trace,
+ bool log_op)
{
if (log.empty()) {
return 0;
liter != remove_instances.end(); ++liter) {
cls_rgw_obj_key& key = *liter;
rgw_obj obj_instance(bucket, key);
- int ret = delete_obj(dpp, obj_ctx, bucket_info, obj_instance, 0, y, RGW_BILOG_FLAG_VERSIONED_OP, ceph::real_time(), zones_trace, log_op);
+ int ret = delete_obj(dpp, obj_ctx, bucket_info, obj_instance, 0, y, null_verid, RGW_BILOG_FLAG_VERSIONED_OP, ceph::real_time(), zones_trace, log_op);
if (ret < 0 && ret != -ENOENT) {
ldpp_dout(dpp, 0) << "ERROR: delete_obj() returned " << ret << " obj_instance=" << obj_instance << dendl;
return ret;
/*
* read olh log and apply it
*/
-int RGWRados::update_olh(const DoutPrefixProvider *dpp, RGWObjectCtx& obj_ctx, RGWObjState *state, RGWBucketInfo& bucket_info, const rgw_obj& obj, optional_yield y, rgw_zone_set *zones_trace, bool log_op)
+int RGWRados::update_olh(const DoutPrefixProvider *dpp, RGWObjectCtx& obj_ctx, RGWObjState *state, RGWBucketInfo& bucket_info, const rgw_obj& obj, optional_yield y, rgw_zone_set *zones_trace, bool null_verid, bool log_op)
{
map<uint64_t, vector<rgw_bucket_olh_log_entry> > log;
bool is_truncated;
if (ret < 0) {
return ret;
}
- ret = apply_olh_log(dpp, obj_ctx, *state, bucket_info, obj, state->olh_tag, log, &ver_marker, y, zones_trace, log_op);
+ ret = apply_olh_log(dpp, obj_ctx, *state, bucket_info, obj, state->olh_tag, log, &ver_marker, y, null_verid, zones_trace, log_op);
if (ret < 0) {
return ret;
}
}
int RGWRados::unlink_obj_instance(const DoutPrefixProvider *dpp, RGWObjectCtx& obj_ctx, RGWBucketInfo& bucket_info, const rgw_obj& target_obj,
- uint64_t olh_epoch, optional_yield y, rgw_zone_set *zones_trace, bool log_op)
+ uint64_t olh_epoch, optional_yield y, bool null_verid, rgw_zone_set *zones_trace, bool log_op)
{
string op_tag;
std::this_thread::sleep_for(cct->_conf->rgw_debug_inject_latency_bi_unlink * std::chrono::seconds{1});
}
- ret = bucket_index_unlink_instance(dpp, bucket_info, target_obj, op_tag, olh_tag, olh_epoch, y, zones_trace, log_op);
+ ret = bucket_index_unlink_instance(dpp, bucket_info, target_obj, op_tag, olh_tag, olh_epoch, y, null_verid, zones_trace, log_op);
if (ret < 0) {
olh_cancel_modification(dpp, bucket_info, *state, olh_obj, op_tag, y);
ldpp_dout(dpp, 20) << "bucket_index_unlink_instance() target_obj=" << target_obj << " returned " << ret << dendl;
// it's possible that the pending xattr from this op prevented the olh
// object from being cleaned by another thread that was deleting the last
// existing version. We invoke a best-effort update_olh here to handle this case.
- int r = update_olh(dpp, obj_ctx, state, bucket_info, olh_obj, y, zones_trace, log_op);
+ int r = update_olh(dpp, obj_ctx, state, bucket_info, olh_obj, y, zones_trace, null_verid, log_op);
if (r < 0 && r != -ECANCELED) {
ldpp_dout(dpp, 20) << "update_olh() target_obj=" << olh_obj << " returned " << r << dendl;
}
return -EIO;
}
- ret = update_olh(dpp, obj_ctx, state, bucket_info, olh_obj, y, zones_trace, log_op);
+ ret = update_olh(dpp, obj_ctx, state, bucket_info, olh_obj, y, zones_trace, null_verid, log_op);
if (ret == -ECANCELED) { /* already did what we needed, no need to retry, raced with another user */
return 0;
}
struct DeleteParams {
rgw_owner bucket_owner; // for quota stats update
int versioning_status; // versioning flags defined in enum RGWBucketFlags
+ bool null_verid;
ACLOwner obj_owner; // needed for creation of deletion marker
uint64_t olh_epoch;
std::string marker_version_id;
uint64_t parts_accounted_size;
obj_version *check_objv;
- DeleteParams() : versioning_status(0), olh_epoch(0), bilog_flags(0), remove_objs(NULL), high_precision_time(false), zones_trace(nullptr), abortmp(false), parts_accounted_size(0), check_objv(nullptr) {}
+ DeleteParams() : versioning_status(0), null_verid(false), olh_epoch(0), bilog_flags(0), remove_objs(NULL), high_precision_time(false), zones_trace(nullptr), abortmp(false), parts_accounted_size(0), check_objv(nullptr) {}
} params;
struct DeleteResult {
bilog_flags = flags;
}
+ int get_bilog_flags() {
+ return bilog_flags;
+ }
+
void set_zones_trace(rgw_zone_set *_zones_trace) {
zones_trace = _zones_trace;
}
const RGWBucketInfo& bucket_info,
const rgw_obj& obj,
int versioning_status, optional_yield y, // versioning flags defined in enum RGWBucketFlags
+ bool null_verid,
uint16_t bilog_flags = 0,
const ceph::real_time& expiration_time = ceph::real_time(),
rgw_zone_set *zones_trace = nullptr,
const rgw_obj& obj_instance,
const std::string& op_tag, const std::string& olh_tag,
uint64_t olh_epoch, optional_yield y,
+ bool null_verid,
rgw_zone_set *zones_trace = nullptr,
bool log_op = true);
int bucket_index_read_olh_log(const DoutPrefixProvider *dpp,
int bucket_index_clear_olh(const DoutPrefixProvider *dpp, RGWBucketInfo& bucket_info, const std::string& olh_tag, const rgw_obj& obj_instance, optional_yield y);
int apply_olh_log(const DoutPrefixProvider *dpp, RGWObjectCtx& obj_ctx, RGWObjState& obj_state, RGWBucketInfo& bucket_info, const rgw_obj& obj,
bufferlist& obj_tag, std::map<uint64_t, std::vector<rgw_bucket_olh_log_entry> >& log,
- uint64_t *plast_ver, optional_yield y, rgw_zone_set *zones_trace = nullptr, bool log_op = true);
+ uint64_t *plast_ver, optional_yield y, bool null_verid, rgw_zone_set *zones_trace = nullptr, bool log_op = true);
int update_olh(const DoutPrefixProvider *dpp, RGWObjectCtx& obj_ctx, RGWObjState *state, RGWBucketInfo& bucket_info, const rgw_obj& obj, optional_yield y,
- rgw_zone_set *zones_trace = nullptr, bool log_op = true);
+ rgw_zone_set *zones_trace = nullptr, bool null_verid = false, bool log_op = true);
int clear_olh(const DoutPrefixProvider *dpp,
RGWObjectCtx& obj_ctx,
const rgw_obj& obj,
int repair_olh(const DoutPrefixProvider *dpp, RGWObjState* state, const RGWBucketInfo& bucket_info,
const rgw_obj& obj, optional_yield y);
int unlink_obj_instance(const DoutPrefixProvider *dpp, RGWObjectCtx& obj_ctx, RGWBucketInfo& bucket_info, const rgw_obj& target_obj,
- uint64_t olh_epoch, optional_yield y, rgw_zone_set *zones_trace = nullptr, bool log_op = true);
+ uint64_t olh_epoch, optional_yield y, bool null_verid, rgw_zone_set *zones_trace = nullptr, bool log_op = true);
void check_pending_olh_entries(const DoutPrefixProvider *dpp, std::map<std::string, bufferlist>& pending_entries, std::map<std::string, bufferlist> *rm_pending_entries);
int remove_olh_pending_entries(const DoutPrefixProvider *dpp, const RGWBucketInfo& bucket_info, RGWObjState& state, const rgw_obj& olh_obj, std::map<std::string, bufferlist>& pending_attrs, optional_yield y);
parent_op.params.zones_trace = params.zones_trace;
parent_op.params.abortmp = params.abortmp;
parent_op.params.parts_accounted_size = params.parts_accounted_size;
- if (params.objv_tracker) {
- parent_op.params.check_objv = params.objv_tracker->version_for_check();
- }
+ parent_op.params.null_verid = params.null_verid;
int ret = parent_op.delete_obj(y, dpp, flags & FLAG_LOG_OP);
if (ret < 0)
if (!rgw::sal::Object::empty(s->object.get())) {
uint64_t obj_size = 0;
std::string etag;
+ bool null_verid;
{
RGWObjState* astate = nullptr;
bool check_obj_lock = s->object->have_instance() && s->bucket->get_info().obj_lock_enabled();
+ op_ret = s->object->get_obj_state(this, &astate, s->yield, true);
+ if (s->object->get_instance() == "null") {
+ null_verid = 1;
+ } else {
+ null_verid = 0;
+ }
+
op_ret = s->object->get_obj_state(this, &astate, s->yield, true);
if (op_ret < 0) {
if (need_object_expiration() || multipart_delete) {
del_op->params.high_precision_time = s->system_request;
del_op->params.olh_epoch = epoch;
del_op->params.marker_version_id = version_id;
+ del_op->params.null_verid = null_verid;
+ ldpp_dout(this, 1) << "del_op->params.null_verid " << del_op->params.null_verid << dendl;
op_ret = del_op->delete_obj(this, y, rgw::sal::FLAG_LOG_OP);
if (op_ret >= 0) {
delete_marker = del_op->result.delete_marker;
rgw_owner bucket_owner; //< bucket owner for usage/quota accounting
ACLOwner obj_owner; //< acl owner for delete marker if necessary
int versioning_status{0};
+ bool null_verid{false};
uint64_t olh_epoch{0};
std::string marker_version_id;
uint32_t bilog_flags{0};