}
break;
case Transaction::OP_TOUCH:
+ case Transaction::OP_CREATE:
{
coll_t cid = i.get_cid(op->cid);
ghobject_t oid = i.get_oid(op->oid);
return backend.setxattr(os, osd_op, txn, delta_stats);
});
case CEPH_OSD_OP_DELETE:
- return do_write_op([this](auto& backend, auto& os, auto& txn) {
- return backend.remove(os, txn, delta_stats);
+ {
+ bool whiteout = false;
+ if (!obc->ssc->snapset.clones.empty() ||
+ (snapc.snaps.size() && // there are snaps
+ snapc.snaps[0] > obc->ssc->snapset.seq)) { // existing obj is old
+ logger().debug("{} has or will have clones, will whiteout {}",
+ __func__, obc->obs.oi.soid);
+ whiteout = true;
+ }
+ return do_write_op([this, whiteout](auto& backend, auto& os, auto& txn) {
+ return backend.remove(os, txn, delta_stats, whiteout);
});
+ }
case CEPH_OSD_OP_CALL:
return this->do_op_call(osd_op);
case CEPH_OSD_OP_STAT:
static_snap_oi.version = osd_op_params->at_version;
static_snap_oi.prior_version = obc->obs.oi.version;
static_snap_oi.copy_user_bits(obc->obs.oi);
+ if (static_snap_oi.is_whiteout()) {
+ // clone shouldn't be marked as whiteout
+ static_snap_oi.clear_flag(object_info_t::FLAG_WHITEOUT);
+ }
if (pg->is_primary()) {
// lookup_or_create
assert(!oid.is_head());
return with_head_obc<RWState::RWREAD>(oid.get_head(),
[oid, func=std::move(func), this](auto head) -> load_obc_iertr::future<> {
+ if (!head->obs.exists) {
+ logger().error("with_clone_obc: {} head doesn't exist", head->obs.oi.soid);
+ return load_obc_iertr::future<>{crimson::ct_error::object_corrupted::make()};
+ }
auto coid = resolve_oid(head->get_ro_ss(), oid);
if (!coid) {
logger().error("with_clone_obc: {} clone not found", coid);
logger().debug("with_clone_obc: found {} in cache", clone->get_oid());
} else {
logger().debug("with_clone_obc: cache miss on {}", clone->get_oid());
+ //TODO: generalize load_head_obc -> load_obc (support head/clone obc)
loaded = clone->template with_promoted_lock<State, IOInterruptCondition>(
[clone, head, this] {
return backend->load_metadata(clone->get_oid()).safe_then_interruptible(
}
}
maybe_create_new_object(os, txn, delta_stats);
- txn.nop();
+ txn.create(coll->get_cid(),
+ ghobject_t{os.oi.soid, ghobject_t::NO_GEN, shard});
return seastar::now();
}
PGBackend::remove_iertr::future<>
PGBackend::remove(ObjectState& os, ceph::os::Transaction& txn,
- object_stat_sum_t& delta_stats)
+ object_stat_sum_t& delta_stats, bool whiteout)
{
if (!os.exists) {
return crimson::ct_error::enoent::make();
}
- // todo: snapset
+
+ if (whiteout && os.oi.is_whiteout()) {
+ logger().debug("{} whiteout set on {} ",__func__, os.oi.soid);
+ return seastar::now();
+ }
txn.remove(coll->get_cid(),
ghobject_t{os.oi.soid, ghobject_t::NO_GEN, shard});
delta_stats.num_bytes -= os.oi.size;
os.oi.size = 0;
os.oi.new_object();
- os.exists = false;
+
+ // todo: clone_overlap
+ if (whiteout) {
+ logger().debug("{} setting whiteout on {} ",__func__, os.oi.soid);
+ os.oi.set_flag(object_info_t::FLAG_WHITEOUT);
+ delta_stats.num_whiteouts++;
+ txn.create(coll->get_cid(),
+ ghobject_t{os.oi.soid, ghobject_t::NO_GEN, shard});
+ return seastar::now();
+ }
// todo: update watchers
if (os.oi.is_whiteout()) {
os.oi.clear_flag(object_info_t::FLAG_WHITEOUT);
delta_stats.num_whiteouts--;
}
delta_stats.num_objects--;
+ os.exists = false;
return seastar::now();
}
remove_iertr::future<> remove(
ObjectState& os,
ceph::os::Transaction& txn,
- object_stat_sum_t& delta_stats);
+ object_stat_sum_t& delta_stats,
+ bool whiteout);
interruptible_future<> remove(
ObjectState& os,
ceph::os::Transaction& txn);