From: Radoslaw Zarzynski Date: Thu, 25 Apr 2019 14:39:56 +0000 (+0200) Subject: crimson: handle hot CaynStore exceptions without throwing. X-Git-Tag: v15.1.0~2730^2~11 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=c3473cdbc06dd0f58a0020024b59668da21fc94b;p=ceph.git crimson: handle hot CaynStore exceptions without throwing. Signed-off-by: Radoslaw Zarzynski --- diff --git a/src/crimson/os/cyan_store.cc b/src/crimson/os/cyan_store.cc index 0cb7160a57a1..493b4a8da61f 100644 --- a/src/crimson/os/cyan_store.cc +++ b/src/crimson/os/cyan_store.cc @@ -164,7 +164,8 @@ seastar::future CyanStore::get_attr(CollectionRef c, __func__, c->cid, oid); auto o = c->get_object(oid); if (!o) { - throw std::runtime_error(fmt::format("object does not exist: {}", oid)); + return seastar::make_exception_future( + EnoentException(fmt::format("object does not exist: {}", oid))); } if (auto found = o->xattr.find(name); found != o->xattr.end()) { return seastar::make_ready_future(found->second); diff --git a/src/crimson/os/cyan_store.h b/src/crimson/os/cyan_store.h index 4315650667de..56ab6d9abb75 100644 --- a/src/crimson/os/cyan_store.h +++ b/src/crimson/os/cyan_store.h @@ -6,8 +6,11 @@ #include #include #include +#include #include + #include + #include "osd/osd_types.h" #include "include/uuid.h" @@ -26,6 +29,33 @@ class CyanStore { uuid_d osd_fsid; public: + template + class Exception : public std::logic_error { + public: + using std::logic_error::logic_error; + + // Throwing an exception isn't the sole way to signalize an error + // with it. This approach nicely fits cold, infrequent issues but + // when applied to a hot one (like ENOENT on write path), it will + // likely hurt performance. + // Alternative approach for hot errors is to create exception_ptr + // on our own and place it in the future via make_exception_future. + // When ::handle_exception is called, handler would inspect stored + // exception whether it's hot-or-cold before rethrowing it. + // The main advantage is both types flow through very similar path + // based on future::handle_exception. + static bool is_class_of(const std::exception_ptr& ep) { + // Seastar offers hacks for making throwing lock-less but stack + // unwinding still can be a problem so painful to justify going + // with non-standard, obscure things like this one. + return *ep.__cxa_exception_type() == typeid(ConcreteExceptionT); + } + }; + + struct EnoentException : public Exception { + using Exception::Exception; + }; + CyanStore(const std::string& path); ~CyanStore(); diff --git a/src/crimson/osd/pg_backend.cc b/src/crimson/osd/pg_backend.cc index ec1aa3495bf7..813f84b4f3b5 100644 --- a/src/crimson/osd/pg_backend.cc +++ b/src/crimson/osd/pg_backend.cc @@ -98,11 +98,19 @@ PGBackend::_load_oi(const hobject_t& oid) } return store->get_attr(coll, ghobject_t{oid, ghobject_t::NO_GEN, shard}, - OI_ATTR).then([oid, this](auto bp) { + OI_ATTR).then_wrapped([oid, this](auto fut) { auto oi = std::make_unique(); - bufferlist bl; - bl.push_back(std::move(bp)); - oi->decode(bl); + if (fut.failed()) { + auto ep = std::move(fut).get_exception(); + if (!ceph::os::CyanStore::EnoentException::is_class_of(ep)) { + std::rethrow_exception(ep); + } + } else { + // decode existing OI_ATTR's value + ceph::bufferlist bl; + bl.push_back(std::move(fut).get0()); + oi->decode(bl); + } return seastar::make_ready_future( oi_cache.insert(oid, std::move(oi))); }); @@ -116,10 +124,21 @@ PGBackend::_load_ss(const hobject_t& oid) } return store->get_attr(coll, ghobject_t{oid, ghobject_t::NO_GEN, shard}, - SS_ATTR).then([oid, this](auto bp) { - bufferlist bl; - bl.push_back(std::move(bp)); - auto snapset = std::make_unique(bl); + SS_ATTR).then_wrapped([oid, this](auto fut) { + std::unique_ptr snapset; + if (fut.failed()) { + auto ep = std::move(fut).get_exception(); + if (!ceph::os::CyanStore::EnoentException::is_class_of(ep)) { + std::rethrow_exception(ep); + } else { + snapset = std::make_unique(); + } + } else { + // decode existing SS_ATTR's value + ceph::bufferlist bl; + bl.push_back(std::move(fut).get0()); + snapset = std::make_unique(bl); + } return seastar::make_ready_future( ss_cache.insert(oid, std::move(snapset))); });