From: Xuehan Xu Date: Tue, 20 Apr 2021 07:47:51 +0000 (+0800) Subject: crimson/os/seastore: allow upper layer to set attrs other than OI_ATTR and SS_ATTR X-Git-Tag: v17.1.0~2072^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=c0f6c28e8702a332a43e6ea15805617d4949f01f;p=ceph.git crimson/os/seastore: allow upper layer to set attrs other than OI_ATTR and SS_ATTR Signed-off-by: Xuehan Xu --- diff --git a/src/crimson/os/seastore/omap_manager.h b/src/crimson/os/seastore/omap_manager.h index 43e4b25a172..1f5f0522d66 100644 --- a/src/crimson/os/seastore/omap_manager.h +++ b/src/crimson/os/seastore/omap_manager.h @@ -71,6 +71,13 @@ public: const std::string &key, const ceph::bufferlist &value) = 0; + using omap_set_keys_ertr = base_ertr; + using omap_set_keys_ret = omap_set_keys_ertr::future<>; + virtual omap_set_keys_ret omap_set_keys( + omap_root_t &omap_root, + Transaction &t, + std::map&& keys) = 0; + /** * remove key value mapping in omap tree * diff --git a/src/crimson/os/seastore/omap_manager/btree/btree_omap_manager.cc b/src/crimson/os/seastore/omap_manager/btree/btree_omap_manager.cc index b9422d26c1b..e4fa724fff7 100644 --- a/src/crimson/os/seastore/omap_manager/btree/btree_omap_manager.cc +++ b/src/crimson/os/seastore/omap_manager/btree/btree_omap_manager.cc @@ -106,6 +106,22 @@ BtreeOMapManager::omap_get_value( }); } +BtreeOMapManager::omap_set_keys_ret +BtreeOMapManager::omap_set_keys( + omap_root_t &omap_root, + Transaction &t, + std::map&& keys) +{ + return seastar::do_with(std::move(keys), [&, this](auto& keys) { + return crimson::do_for_each( + keys.begin(), + keys.end(), + [&, this](auto &p) { + return omap_set_key(omap_root, t, p.first, p.second); + }); + }); +} + BtreeOMapManager::omap_set_key_ret BtreeOMapManager::omap_set_key( omap_root_t &omap_root, diff --git a/src/crimson/os/seastore/omap_manager/btree/btree_omap_manager.h b/src/crimson/os/seastore/omap_manager/btree/btree_omap_manager.h index 7e43de2af2c..331ebf60310 100644 --- a/src/crimson/os/seastore/omap_manager/btree/btree_omap_manager.h +++ b/src/crimson/os/seastore/omap_manager/btree/btree_omap_manager.h @@ -77,6 +77,11 @@ public: Transaction &t, const std::string &key, const ceph::bufferlist &value) final; + omap_set_keys_ret omap_set_keys( + omap_root_t &omap_root, + Transaction &t, + std::map&& keys) final; + omap_rm_key_ret omap_rm_key( omap_root_t &omap_root, Transaction &t, diff --git a/src/crimson/os/seastore/onode.h b/src/crimson/os/seastore/onode.h index 955d3a9d802..e7d515c2d04 100644 --- a/src/crimson/os/seastore/onode.h +++ b/src/crimson/os/seastore/onode.h @@ -32,6 +32,7 @@ struct onode_layout_t { ceph_le32 oi_size{0}; ceph_le32 ss_size{0}; omap_root_le_t omap_root; + omap_root_le_t xattr_root; object_data_le_t object_data; diff --git a/src/crimson/os/seastore/seastore.cc b/src/crimson/os/seastore/seastore.cc index e526ff3da89..ad2bd1c8c4e 100644 --- a/src/crimson/os/seastore/seastore.cc +++ b/src/crimson/os/seastore/seastore.cc @@ -194,6 +194,8 @@ SeaStore::read_errorator::future SeaStore::readv( return read_errorator::make_ready_future(); } +using crimson::os::seastore::omap_manager::BtreeOMapManager; + SeaStore::get_attr_errorator::future SeaStore::get_attr( CollectionRef ch, const ghobject_t& oid, @@ -201,8 +203,44 @@ SeaStore::get_attr_errorator::future SeaStore::get_attr( { auto c = static_cast(ch.get()); logger().debug("{} {} {}", - __func__, c->get_cid(), oid); - return crimson::ct_error::enoent::make(); + __func__, c->get_cid(), oid); + using get_attr_ertr = TransactionManager::base_ertr::extend< + crimson::ct_error::enodata>; + return repeat_with_onode( + c, oid, [=](auto &t, auto& onode) + -> get_attr_ertr::future { + auto& layout = onode.get_layout(); + if (name == OI_ATTR && layout.oi_size) { + ceph::bufferlist bl; + bl.append(ceph::bufferptr(&layout.oi[0], layout.oi_size)); + return seastar::make_ready_future(std::move(bl)); + } + if (name == SS_ATTR && layout.ss_size) { + ceph::bufferlist bl; + bl.append(ceph::bufferptr(&layout.ss[0], layout.ss_size)); + return seastar::make_ready_future(std::move(bl)); + } + return seastar::do_with( + BtreeOMapManager(*transaction_manager), + layout.xattr_root.get(), + std::string(name), + [&t, this](auto &manager, auto& root, auto& name) { + if (root.is_null()) { + return get_attr_ertr::make_ready_future( + ceph::bufferlist()); + } + return manager.omap_get_value(root, t, name).safe_then([](auto opt) + -> get_attr_ertr::future { + if (!opt) { + return crimson::ct_error::enodata::make(); + } + return seastar::make_ready_future(std::move(*opt)); + }); + }); + }).handle_error(crimson::ct_error::input_output_error::handle([this] { + logger().error("EIO when getting attrs"); + abort(); + }), crimson::ct_error::pass_further_all{}); } SeaStore::get_attrs_ertr::future SeaStore::get_attrs( @@ -215,10 +253,22 @@ SeaStore::get_attrs_ertr::future SeaStore::get_attrs( return repeat_with_onode( c, oid, [=](auto &t, auto& onode) { auto& layout = onode.get_layout(); - SeaStore::attrs_t attrs; - attrs[OI_ATTR] = ceph::bufferptr(&layout.oi[0], layout.oi_size); - attrs[SS_ATTR] = ceph::bufferptr(&layout.ss[0], layout.ss_size); - return attrs; + return _omap_list(layout.xattr_root, t, std::nullopt, + OMapManager::omap_list_config_t::with_inclusive(false)).safe_then( + [&layout](auto p) { + auto& attrs = p.second; + ceph::bufferlist bl; + if (layout.oi_size) { + bl.append(ceph::bufferptr(&layout.oi[0], layout.oi_size)); + attrs.emplace(OI_ATTR, std::move(bl)); + } + if (layout.ss_size) { + bl.clear(); + bl.append(ceph::bufferptr(&layout.ss[0], layout.ss_size)); + attrs.emplace(SS_ATTR, std::move(bl)); + } + return seastar::make_ready_future(std::move(attrs)); + }); }).handle_error(crimson::ct_error::input_output_error::handle([this] { logger().error("EIO when getting attrs"); abort(); @@ -247,8 +297,6 @@ seastar::future SeaStore::stat( ); } -using crimson::os::seastore::omap_manager::BtreeOMapManager; - using omap_int_ertr_t = OMapManager::base_ertr::extend< crimson::ct_error::enoent >; @@ -310,6 +358,28 @@ SeaStore::omap_get_values( } }); } +OMapManager::omap_list_ret SeaStore::_omap_list( + const omap_root_le_t& omap_root, + Transaction& t, + const std::optional& start, + OMapManager::omap_list_config_t config) +{ + using ret_bare_t = std::pair; + using int_ret_t = OMapManager::omap_list_ertr::future; + auto root = omap_root.get(); + if (root.is_null()) { + return seastar::make_ready_future( + true, omap_values_t{} + ); + } + return seastar::do_with( + BtreeOMapManager(*transaction_manager), + root, + start, + [&t, config, this](auto &manager, auto& root, auto& start) -> int_ret_t { + return manager.omap_list(root, t, start, config); + }); +} SeaStore::omap_get_values_ret_t SeaStore::omap_list( CollectionRef ch, @@ -327,28 +397,11 @@ SeaStore::omap_get_values_ret_t SeaStore::omap_list( c, oid, [this, config, &oid, &start](auto &t, auto &onode) -> int_ret_t { - auto omap_root = onode.get_layout().omap_root.get(); - if (omap_root.is_null()) { - return seastar::make_ready_future( - true, omap_values_t{} - ); - } else { - return seastar::do_with( - BtreeOMapManager(*transaction_manager), - omap_root, - [&, config, this](auto &manager, auto &root) -> int_ret_t { - return manager.omap_list( - root, - t, - start, - config - ).safe_then([](auto &&p) { - return seastar::make_ready_future( - p.first, p.second - ); - }); - }); - } + return _omap_list(onode.get_layout().omap_root, t, start, config) + .safe_then([](auto&& p) { + return seastar::make_ready_future( + p.first, p.second); + }); }); } @@ -357,9 +410,12 @@ SeaStore::omap_get_values_ret_t SeaStore::omap_get_values( const ghobject_t &oid, const std::optional &start) { - return omap_list( - ch, oid, start, - OMapManager::omap_list_config_t::with_inclusive(false)); + return seastar::do_with(oid, start, + [this, ch=std::move(ch)](auto& oid, auto& start) { + return omap_list( + ch, oid, start, + OMapManager::omap_list_config_t::with_inclusive(false)); + }); } class SeaStoreOmapIterator : public FuturizedStore::OmapIterator { @@ -678,6 +734,38 @@ SeaStore::tm_ret SeaStore::_write( }); } +SeaStore::omap_set_kvs_ret +SeaStore::__omap_set_kvs( + const omap_root_le_t& omap_root, + Transaction& t, + omap_root_le_t& mutable_omap_root, + std::map&& kvs) +{ + return seastar::do_with( + BtreeOMapManager(*transaction_manager), + omap_root.get(), + [&t, this, keys=std::move(kvs)](auto &omap_manager, auto &root) { + tm_ertr::future<> maybe_create_root = + !root.is_null() ? + tm_ertr::now() : + omap_manager.initialize_omap(t) + .safe_then([&root](auto new_root) { + root = new_root; + }); + + return maybe_create_root.safe_then( + [&, keys=std::move(keys), this]() mutable { + return omap_manager.omap_set_keys(root, t, std::move(keys)); + }).safe_then([&, this] { + return tm_ertr::make_ready_future(std::move(root)); + }); + }).safe_then([this, &mutable_omap_root](auto root) { + if (root.must_update()) { + mutable_omap_root.update(root); + } + }); +} + SeaStore::tm_ret SeaStore::_omap_set_values( internal_context_t &ctx, OnodeRef &onode, @@ -686,43 +774,11 @@ SeaStore::tm_ret SeaStore::_omap_set_values( logger().debug( "{}: {} {} keys", __func__, *onode, aset.size()); - - return seastar::do_with( - BtreeOMapManager(*transaction_manager), - onode->get_layout().omap_root.get(), - std::move(aset), - [&ctx, &onode, this]( - auto &omap_manager, - auto &onode_omap_root, - auto &keys - ) { - - tm_ertr::future<> maybe_create_root = - !onode_omap_root.is_null() ? - tm_ertr::now() : - omap_manager.initialize_omap(*ctx.transaction - ).safe_then([&onode_omap_root](auto new_root) { - onode_omap_root = new_root; - }); - - return maybe_create_root.safe_then([&, this] { - return crimson::do_for_each( - keys.begin(), - keys.end(), - [&, this](auto &p) { - return omap_manager.omap_set_key( - onode_omap_root, - *ctx.transaction, - p.first, - p.second); - }); - }).safe_then([&, this] { - if (onode_omap_root.must_update()) { - onode->get_mutable_layout(*ctx.transaction - ).omap_root.update(onode_omap_root); - } - }); - }); + return __omap_set_kvs( + onode->get_layout().omap_root, + *ctx.transaction, + onode->get_mutable_layout(*ctx.transaction).omap_root, + std::move(aset)); } SeaStore::tm_ret SeaStore::_omap_set_header( @@ -813,31 +869,45 @@ SeaStore::tm_ret SeaStore::_setattrs( logger().debug("{} onode={}", __func__, *onode); auto& layout = onode->get_mutable_layout(*ctx.transaction); - for (auto& [key, val] : aset) { - if (key == OI_ATTR) { - if (__builtin_expect( - val.length() > onode_layout_t::MAX_OI_LENGTH, - false)) { - logger().error("{} onode={} oi attr too long!"); - return crimson::ct_error::input_output_error::make(); - } + if (auto it = aset.find(OI_ATTR); it != aset.end()) { + auto& val = it->second; + if (likely(val.length() <= onode_layout_t::MAX_OI_LENGTH)) { layout.oi_size = val.length(); - val.copy_out(0, val.length(), &layout.oi[0]); - } else if (key == SS_ATTR) { - if (__builtin_expect( - val.length() > onode_layout_t::MAX_SS_LENGTH, - false)) { - logger().error("{} onode={} oi attr too long!"); - return crimson::ct_error::input_output_error::make(); - } + maybe_inline_memcpy( + &layout.oi[0], + val.c_str(), + val.length(), + onode_layout_t::MAX_OI_LENGTH); + aset.erase(it); + } else { + layout.oi_size = 0; + } + } + + if (auto it = aset.find(SS_ATTR); it != aset.end()) { + auto& val = it->second; + if (likely(val.length() <= onode_layout_t::MAX_SS_LENGTH)) { layout.ss_size = val.length(); - val.copy_out(0, val.length(), &layout.ss[0]); + maybe_inline_memcpy( + &layout.ss[0], + val.c_str(), + val.length(), + onode_layout_t::MAX_SS_LENGTH); + it = aset.erase(it); } else { - //FIXME: right now, only OI_ATTR and SS_ATTR are supported - assert(0 == "only OI_ATTR and SS_ATTR are supported for now"); + layout.ss_size = 0; } } - return tm_ertr::now(); + + if (aset.empty()) { + return tm_ertr::now(); + } + + return __omap_set_kvs( + onode->get_layout().xattr_root, + *ctx.transaction, + layout.xattr_root, + std::move(aset)); } SeaStore::tm_ret SeaStore::_create_collection( diff --git a/src/crimson/os/seastore/seastore.h b/src/crimson/os/seastore/seastore.h index a84c479e7e5..f53ad97dcc5 100644 --- a/src/crimson/os/seastore/seastore.h +++ b/src/crimson/os/seastore/seastore.h @@ -200,12 +200,46 @@ private: } + template + auto repeat_with_onode( + CollectionRef ch, + const ghobject_t &oid, + F &&f) const { + return seastar::do_with( + oid, + Ret{}, + TransactionRef(), + OnodeRef(), + std::forward(f), + [=](auto &oid, auto &ret, auto &t, auto &onode, auto &f) { + return repeat_eagain([&, this] { + t = transaction_manager->create_transaction(); + return onode_manager->get_onode( + *t, oid + ).safe_then([&, this](auto onode_ret) { + onode = std::move(onode_ret); + return f(*t, *onode); + }).safe_then([&ret](auto _ret) { + ret = _ret; + }); + }).safe_then([&ret] { + return seastar::make_ready_future(ret); + }); + }); + } + + friend class SeaStoreOmapIterator; omap_get_values_ret_t omap_list( CollectionRef ch, const ghobject_t &oid, const std::optional &_start, OMapManager::omap_list_config_t config); + OMapManager::omap_list_ret _omap_list( + const omap_root_le_t& omap_root, + Transaction& t, + const std::optional& start, + OMapManager::omap_list_config_t config); TransactionManagerRef transaction_manager; CollectionManagerRef collection_manager; @@ -261,6 +295,12 @@ private: tm_ret _remove_collection( internal_context_t &ctx, const coll_t& cid); + using omap_set_kvs_ret = tm_ertr::future<>; + omap_set_kvs_ret __omap_set_kvs( + const omap_root_le_t& omap_root, + Transaction& t, + omap_root_le_t& mutable_omap_root, + std::map&& kvs); boost::intrusive_ptr _get_collection(const coll_t& cid); };