}
break;
case Transaction::OP_TOUCH:
+ case Transaction::OP_TOUCH_TEMP:
case Transaction::OP_CREATE:
{
coll_t cid = i.get_cid(op->cid);
assert(is_viewable());
assert(is_indirect());
assert(!is_end());
- return iter.get_val().pladdr.build_laddr(key);
+ if (likely(!hobject_t::is_temp_pool(get_key().get_pool()))) {
+ return iter.get_val().pladdr.build_laddr(key);
+ } else {
+ auto k = key;
+ k.set_pool(hobject_t::POOL_TEMP_START - key.get_pool());
+ return iter.get_val().pladdr.build_laddr(k);
+ }
}
checksum_t get_checksum() const {
assert(is_viewable());
extent_len_t get_intermediate_offset() const {
assert(is_indirect());
assert(get_intermediate_base() <= get_intermediate_key());
- assert(get_intermediate_key() + get_length() <=
- get_intermediate_base() + get_intermediate_length());
+ if (likely(!hobject_t::is_temp_pool(get_key().get_pool()))) {
+ assert(get_intermediate_key() + get_length() <=
+ get_intermediate_base() + get_intermediate_length());
+ }
return get_intermediate_base().get_byte_distance<
extent_len_t>(get_intermediate_key());
}
local_object_id_t object_id,
extent_len_t block_size,
bool is_metadata) const = 0;
+ virtual laddr_hint_t generate_temp_hint(
+ local_object_id_t object_id,
+ extent_len_t block_size,
+ bool is_metadata) const = 0;
laddr_hint_t get_hint(extent_len_t block_size, bool is_metadata) const {
assert(block_size >= laddr_t::UNIT_SIZE);
auto prefix = get_clone_prefix();
return laddr_hint_t::create_object_data_hint(*prefix, block_size);
}
} else if (sibling_object_id) {
- return generate_clone_hint(
- *sibling_object_id, block_size, is_metadata);
+ if (get_hobj().is_temp()) {
+ return generate_temp_hint(
+ *sibling_object_id, block_size, is_metadata);
+ } else {
+ return generate_clone_hint(
+ *sibling_object_id, block_size, is_metadata);
+ }
} else {
return init_hint(block_size, is_metadata);
}
}
return std::nullopt;
}
+ bool maybe_set_sibling_object_id(local_object_id_t id) {
+ if (sibling_object_id) {
+ return false;
+ }
+ set_sibling_object_id(id);
+ return true;
+ }
void set_sibling_object_id(local_object_id_t id) {
assert(!sibling_object_id);
sibling_object_id = id;
}
+ // should only be used for unittest
+ void reset_sibling_object_id() {
+ sibling_object_id.reset();
+ }
friend std::ostream& operator<<(std::ostream &out, const Onode &rhs);
};
LOG_PREFIX(FLTreeOnodeManager::get_onode);
return tree.find(
trans, hoid
- ).si_then([this, &hoid, &trans, FNAME](auto cursor)
- -> get_onode_ret {
+ ).si_then([this, &hoid, &trans, FNAME](auto cursor) -> get_onode_ret {
if (cursor == tree.end()) {
DEBUGT("no entry for {}", trans, hoid);
return crimson::ct_error::enoent::make();
return LADDR_HINT_NULL;
}
+ laddr_hint_t generate_temp_hint(
+ local_object_id_t object_id,
+ extent_len_t block_size,
+ bool is_metadata) const final {
+ ceph_abort("impossible");
+ return LADDR_HINT_NULL;
+ }
+
bool is_alive() const final { return true; }
const onode_layout_t &get_layout() const final {
return layout;
bool is_metadata) const final {
return Value::generate_clone_hint(object_id, block_size, is_metadata);
}
+ laddr_hint_t generate_temp_hint(
+ local_object_id_t object_id,
+ extent_len_t block_size,
+ bool is_metadata) const final {
+ return Value::generate_temp_hint(
+ object_id, block_size, is_metadata);
+ }
+
~FLTreeOnode() final {}
};
pool_t pool() const {
return ghobj.hobj.pool;
}
+ pool_t logical_pool() const {
+ return ghobj.hobj.get_logical_pool();
+ }
crush_hash_t crush() const {
// Note: this is the reversed version of the object hash
return ghobj.hobj.get_bitwise_key_u32();
return laddr_hint_t::create_fresh_object_md_hint(
shard(), pool(), crush(), block_size);
}
+ laddr_hint_t create_temp_object_data_hint(
+ local_object_id_t object_id,
+ extent_len_t block_size) const {
+ return laddr_hint_t::create_temp_object_data_hint(
+ shard(), pool(), crush(), object_id, block_size);
+ }
+ laddr_hint_t create_temp_object_md_hint(
+ local_object_id_t object_id,
+ extent_len_t block_size) const {
+ return laddr_hint_t::create_temp_object_md_hint(
+ shard(), pool(), crush(), object_id, block_size);
+ }
laddr_hint_t create_clone_object_data_hint(
local_object_id_t object_id,
extent_len_t block_size) const {
*/
inline shard_t shard() const;
inline pool_t pool() const;
+ inline pool_t logical_pool() const;
inline crush_hash_t crush() const;
laddr_hint_t create_onode_hint(
extent_len_t block_size = laddr_t::UNIT_SIZE) const {
return laddr_hint_t::create_fresh_object_md_hint(
shard(), pool(), crush(), block_size);
}
+ laddr_hint_t create_temp_object_data_hint(
+ local_object_id_t object_id,
+ extent_len_t block_size) const {
+ return laddr_hint_t::create_temp_object_data_hint(
+ shard(), pool(), crush(), object_id, block_size);
+ }
+ laddr_hint_t create_temp_object_md_hint(
+ local_object_id_t object_id,
+ extent_len_t block_size) const {
+ return laddr_hint_t::create_temp_object_md_hint(
+ shard(), pool(), crush(), object_id, block_size);
+ }
laddr_hint_t create_clone_object_data_hint(
local_object_id_t object_id,
extent_len_t block_size) const {
return shard_pool_packed().pool();
}
+pool_t key_view_t::logical_pool() const {
+ auto pool = shard_pool_packed().pool();
+ if (unlikely(hobject_t::is_temp_pool(pool))) {
+ return hobject_t::get_temp_pool(pool);
+ }
+ return pool;
+}
+
crush_hash_t key_view_t::crush() const {
return crush_packed().crush;
}
}
}
+laddr_hint_t Value::generate_temp_hint(
+ local_object_id_t object_id,
+ extent_len_t block_size,
+ bool is_metadata) const
+{
+ if (is_metadata) {
+ return p_cursor->get_key_view(vb.get_header_magic())
+ .create_temp_object_md_hint(object_id, block_size);
+ } else {
+ return p_cursor->get_key_view(vb.get_header_magic())
+ .create_temp_object_data_hint(object_id, block_size);
+ }
+}
+
laddr_hint_t Value::generate_clone_hint(
local_object_id_t object_id,
extent_len_t block_size,
local_object_id_t object_id,
extent_len_t block_size,
bool is_metadata) const;
+ laddr_hint_t generate_temp_hint(
+ local_object_id_t object_id,
+ extent_len_t block_size,
+ bool is_metadata) const;
+
bool operator==(const Value& v) const { return p_cursor == v.p_cursor; }
bool operator!=(const Value& v) const { return !(*this == v); }
auto fut = onode_iertr::make_ready_future<OnodeRef>(OnodeRef());
bool create = false;
if (op->op == Transaction::OP_TOUCH ||
+ op->op == Transaction::OP_TOUCH_TEMP ||
op->op == Transaction::OP_CREATE ||
op->op == Transaction::OP_WRITE ||
op->op == Transaction::OP_ZERO) {
fut = onode_manager->get_or_create_onode(*ctx.transaction, oid);
}
}
- return fut.si_then([&, op, this, FNAME](auto get_onode) {
+ return fut.si_then([&, op, this, FNAME](auto get_onode)
+ -> OnodeManager::get_or_create_onode_iertr::future<> {
OnodeRef& onode = onodes[op->oid];
if (!onode) {
assert(get_onode);
d_onode = dest_onode;
return seastar::now();
});
+ } else if (op->op == Transaction::OP_TOUCH_TEMP && !d_onode) {
+ const ghobject_t& dest_oid = i.get_oid(op->dest_oid);
+ DEBUGT("op {}, get_onode dest oid={} ...",
+ *ctx.transaction, (uint32_t)op->op, dest_oid);
+ return onode_manager->get_or_create_onode(*ctx.transaction, dest_oid
+ ).si_then([&d_onode](auto target_onode) {
+ d_onode = target_onode;
+ });
} else {
return OnodeManager::get_or_create_onode_iertr::now();
}
oid);
return _touch(ctx, *onode);
}
+ case Transaction::OP_TOUCH_TEMP:
+ {
+ const auto &dest_oid = i.get_oid(op->dest_oid);
+ DEBUGT("op {}, temp oid={}, oid={} ...",
+ *ctx.transaction,
+ "TOUCH_TEMP",
+ oid,
+ dest_oid);
+ OnodeRef& d_onode = onodes[op->dest_oid];
+ assert(d_onode);
+ assert(d_onode->get_hobj() == dest_oid.hobj);
+ assert(!dest_oid.hobj.is_temp());
+ assert(oid.hobj.is_temp());
+ return _touch(ctx, *d_onode
+ ).si_then([&onode, this, &ctx, &d_onode] {
+ assert(d_onode);
+ auto prefix = d_onode->get_clone_prefix();
+ assert(prefix);
+ prefix->set_pool(onode->get_hobj().pool);
+ auto object_id = prefix->get_local_object_id();
+ onode->set_sibling_object_id(object_id);
+ return _touch(ctx, *onode);
+ });
+ }
case Transaction::OP_WRITE:
{
uint64_t off = op->off;
DEBUGT("op COLL_MOVE_RENAME, oid={}, dest oid={} ...",
*ctx.transaction, oid, i.get_oid(op->dest_oid));
ceph_assert(op->cid == op->dest_cid);
+ auto &target_onode = onodes[op->dest_oid];
return _rename(
- ctx, onode, onodes[op->dest_oid]
+ ctx, onode, target_onode
).si_then([&onode] {
onode.reset();
});
Transaction &t, Onode &src, Onode &dst)
{
auto src_prefix = *src.get_clone_prefix();
- auto dst_prefix = *dst.get_clone_prefix();
-
+ auto dst_prefix = src_prefix;
+ if (auto prefix = dst.get_clone_prefix(); prefix) {
+ dst_prefix = *prefix;
+ }
auto rename_root = [&src, &dst, src_prefix, dst_prefix](omap_type_t type) {
auto root = src.get_root(type).get(dst.get_metadata_hint());
if (root.is_null()) {
OnodeRef &onode,
OnodeRef &d_onode)
{
- auto &objHandler = ObjectDataHandler(max_object_size);
- co_await objHanlder.rename(ObjectDataHandler::context_t{
+ auto prefix = onode->get_clone_prefix();
+ assert(prefix);
+ prefix->set_pool(onode->get_hobj().get_logical_pool());
+ auto object_id = prefix->get_local_object_id();
+ std::ignore = d_onode->maybe_set_sibling_object_id(object_id);
+ auto olayout = onode->get_layout();
+ ObjectDataHandler objHandler(max_object_size);
+ co_await objHandler.rename(ObjectDataHandler::context_t{
*transaction_manager, *ctx.transaction, *onode, d_onode.get()
});
- auto olayout = onode->get_layout();
+
uint32_t size = olayout.size;
auto oi_bl = ceph::bufferlist::static_from_mem(
&olayout.oi[0],
return hint;
}
+laddr_hint_t laddr_hint_t::create_temp_object_data_hint(
+ laddr_shard_t shard,
+ laddr_pool_t pool,
+ laddr_crush_hash_t crush,
+ local_object_id_t id,
+ extent_len_t block_size)
+{
+ laddr_hint_t hint{
+ L_ADDR_MIN,
+ laddr_conflict_condition_t::clone_prefix_at_clone_id,
+ laddr_conflict_policy_t::gen_random,
+ block_size
+ };
+ hint.addr.set_shard(shard);
+ hint.addr.set_pool(pool);
+ hint.addr.set_reversed_hash(crush);
+ hint.addr.set_local_object_id(id);
+
+ CHECK_OBJECT_INFO(hint.addr, shard, pool, crush);
+ assert(hint.addr.get_local_object_id() == id);
+ assert(!hint.addr.is_metadata());
+ assert(hint.addr.get_offset_bytes() == 0);
+ return hint;
+}
+
+laddr_hint_t laddr_hint_t::create_temp_object_md_hint(
+ laddr_shard_t shard,
+ laddr_pool_t pool,
+ laddr_crush_hash_t crush,
+ local_object_id_t id,
+ extent_len_t block_size)
+{
+ auto hint = create_temp_object_data_hint(
+ shard, pool, crush, id, block_size);
+ auto addr = hint.addr;
+
+ hint.addr.set_metadata(true);
+
+ CHECK_OBJECT_INFO(hint.addr, shard, pool, crush);
+ assert(hint.addr.get_clone_prefix() == addr.get_clone_prefix());
+ assert(hint.addr.is_metadata());
+ boost::ignore_unused(addr);
+ return hint;
+}
+
+
laddr_hint_t laddr_hint_t::create_clone_object_data_hint(
laddr_shard_t shard,
laddr_pool_t pool,
laddr_t clone_prefix,
extent_len_t block_size);
+ static laddr_hint_t create_temp_object_data_hint(
+ laddr_shard_t shard,
+ laddr_pool_t pool,
+ laddr_crush_hash_t crush,
+ local_object_id_t object_id,
+ extent_len_t block_size);
+ static laddr_hint_t create_temp_object_md_hint(
+ laddr_shard_t shard,
+ laddr_pool_t pool,
+ laddr_crush_hash_t crush,
+ local_object_id_t id,
+ extent_len_t block_size);
+
void find_next_random();
bool conflict_with(laddr_t other) const {
f->dump_stream("oid") << oid;
}
break;
-
+
+#ifdef WITH_CRIMSON
+ case Transaction::OP_TOUCH_TEMP:
+ {
+ coll_t cid = i.get_cid(op->cid);
+ const ghobject_t &oid = i.get_oid(op->oid);
+ const ghobject_t &dest_oid = i.get_oid(op->dest_oid);
+ f->dump_string("op_name", "touch_temp");
+ f->dump_stream("collection") << cid;
+ f->dump_stream("temp oid") << oid;
+ f->dump_stream("oid") << dest_oid;
+ }
+ break;
+#endif
+
case Transaction::OP_WRITE:
{
coll_t cid = i.get_cid(op->cid);
// these operations implicity create the object
bool create = false;
if (op->op == Transaction::OP_TOUCH ||
+#ifdef WITH_CRIMSON
+ op->op == Transaction::OP_TOUCH_TEMP ||
+#endif
op->op == Transaction::OP_CREATE ||
op->op == Transaction::OP_WRITE ||
op->op == Transaction::OP_ZERO) {
switch (op->op) {
case Transaction::OP_CREATE:
case Transaction::OP_TOUCH:
+#ifdef WITH_CRIMSON
+ case Transaction::OP_TOUCH_TEMP:
+#endif
r = _touch(txc, c, o);
break;
std::swap(layout.xattr_root, o_mlayout.xattr_root);
});
}
- laddr_hint_t get_hint() const {
+ laddr_hint_t init_hint(
+ extent_len_t block_size,
+ bool is_metadata) const final {
laddr_hint_t hint;
hint.addr = laddr_t::from_byte_offset(0);
+ hint.addr.set_pool(1);
hint.condition = laddr_conflict_condition_t::all_at_object_content;
hint.policy = laddr_conflict_policy_t::linear_search;
hint.block_size = laddr_t::UNIT_SIZE;
return hint;
}
- laddr_hint_t init_hint(
+ laddr_hint_t generate_temp_hint(
+ local_object_id_t object_id,
extent_len_t block_size,
bool is_metadata) const final {
- return get_hint();
+ ceph_abort("impossible for now");
+ return laddr_hint_t{};
}
laddr_hint_t generate_clone_hint(
local_object_id_t object_id,
extent_len_t block_size,
bool is_metadata) const final {
- return get_hint();
+ laddr_hint_t hint;
+ hint.addr = laddr_t::from_byte_offset(0);
+ hint.addr.set_pool(1);
+ hint.condition = laddr_conflict_condition_t::clone_prefix_at_clone_id;
+ hint.policy = laddr_conflict_policy_t::gen_random;
+ hint.block_size = laddr_t::UNIT_SIZE;
+ return hint;
}
~TestOnode() final = default;
ObjectDataHandler objhandler(MAX_OBJECT_SIZE);
auto &target = get_object(target_snap);
target.clone_from(head);
+ auto id = head.onode->get_layout()
+ .object_data
+ .get()
+ .get_reserved_data_base()
+ .get_local_object_id();
head.onode->swap_layout(t, *(target.onode));
+ head.onode->reset_sibling_object_id();
+ head.onode->set_sibling_object_id(id);
co_await objhandler.clone(
ObjectDataHandler::context_t{
*tm, t, *(target.onode), &*(head.onode)