crimson/osd: erroratorize the do_op_call() path more.

Signed-off-by: Radoslaw Zarzynski <rzarzyns@redhat.com>
This commit is contained in:
Radoslaw Zarzynski 2019-09-18 17:25:55 +02:00
parent 7a1eb3d4c5
commit d8d0ab1a69
3 changed files with 61 additions and 36 deletions

View File

@ -13,7 +13,9 @@ namespace _impl {
invarg, invarg,
enodata, enodata,
input_output_error, input_output_error,
object_corrupted object_corrupted,
permission_denied,
operation_not_supported
}; };
} }
@ -590,6 +592,8 @@ namespace ct_error {
using invarg = unthrowable_wrapper<_impl::ct_error, _impl::ct_error::invarg>; using invarg = unthrowable_wrapper<_impl::ct_error, _impl::ct_error::invarg>;
using input_output_error = unthrowable_wrapper<_impl::ct_error, _impl::ct_error::input_output_error>; using input_output_error = unthrowable_wrapper<_impl::ct_error, _impl::ct_error::input_output_error>;
using object_corrupted = unthrowable_wrapper<_impl::ct_error, _impl::ct_error::object_corrupted>; using object_corrupted = unthrowable_wrapper<_impl::ct_error, _impl::ct_error::object_corrupted>;
using permission_denied = unthrowable_wrapper<_impl::ct_error, _impl::ct_error::permission_denied>;
using operation_not_supported = unthrowable_wrapper<_impl::ct_error, _impl::ct_error::operation_not_supported>;
} }
using stateful_errc = stateful_error_t<std::errc>; using stateful_errc = stateful_error_t<std::errc>;

View File

@ -37,7 +37,7 @@ OpsExecuter::call_errorator::future<> OpsExecuter::do_op_call(OSDOp& osd_op)
bp.copy(osd_op.op.cls.indata_len, indata); bp.copy(osd_op.op.cls.indata_len, indata);
} catch (buffer::error&) { } catch (buffer::error&) {
logger().warn("call unable to decode class + method + indata"); logger().warn("call unable to decode class + method + indata");
throw crimson::osd::invalid_argument{}; return crimson::ct_error::invarg::make();
} }
// NOTE: opening a class can actually result in dlopen(), and thus // NOTE: opening a class can actually result in dlopen(), and thus
@ -48,23 +48,23 @@ OpsExecuter::call_errorator::future<> OpsExecuter::do_op_call(OSDOp& osd_op)
if (r) { if (r) {
logger().warn("class {} open got {}", cname, cpp_strerror(r)); logger().warn("class {} open got {}", cname, cpp_strerror(r));
if (r == -ENOENT) { if (r == -ENOENT) {
throw crimson::osd::operation_not_supported{}; return crimson::ct_error::operation_not_supported::make();
} else if (r == -EPERM) { } else if (r == -EPERM) {
// propagate permission errors // propagate permission errors
throw crimson::osd::permission_denied{}; return crimson::ct_error::permission_denied::make();
} }
throw crimson::osd::input_output_error{}; return crimson::ct_error::input_output_error::make();
} }
ClassHandler::ClassMethod* method = cls->get_method(mname); ClassHandler::ClassMethod* method = cls->get_method(mname);
if (!method) { if (!method) {
logger().warn("call method {}.{} does not exist", cname, mname); logger().warn("call method {}.{} does not exist", cname, mname);
throw crimson::osd::operation_not_supported{}; return crimson::ct_error::operation_not_supported::make();
} }
const auto flags = method->get_flags(); const auto flags = method->get_flags();
if (!os->exists && (flags & CLS_METHOD_WR) == 0) { if (!os->exists && (flags & CLS_METHOD_WR) == 0) {
throw crimson::osd::object_not_found{}; return crimson::ct_error::enoent::make();
} }
#if 0 #if 0
@ -74,19 +74,27 @@ OpsExecuter::call_errorator::future<> OpsExecuter::do_op_call(OSDOp& osd_op)
#endif #endif
logger().debug("calling method {}.{}", cname, mname); logger().debug("calling method {}.{}", cname, mname);
return seastar::async([this, &osd_op, flags, method, indata=std::move(indata)]() mutable { return seastar::async(
[this, method, indata=std::move(indata)]() mutable {
ceph::bufferlist outdata; ceph::bufferlist outdata;
const auto prev_rd = num_read; auto cls_context = reinterpret_cast<cls_method_context_t>(this);
const auto prev_wr = num_write; const auto ret = method->exec(cls_context, indata, outdata);
const auto ret = method->exec(reinterpret_cast<cls_method_context_t>(this), return std::make_pair(ret, std::move(outdata));
indata, outdata); }
).then(
[prev_rd = num_read, prev_wr = num_write, this, &osd_op, flags]
(auto outcome) {
auto& [ret, outdata] = outcome;
if (num_read > prev_rd && !(flags & CLS_METHOD_RD)) { if (num_read > prev_rd && !(flags & CLS_METHOD_RD)) {
logger().error("method tried to read object but is not marked RD"); logger().error("method tried to read object but is not marked RD");
throw crimson::osd::input_output_error{}; return call_errorator::make_plain_exception_future<>(
crimson::ct_error::input_output_error::make());
} }
if (num_write > prev_wr && !(flags & CLS_METHOD_WR)) { if (num_write > prev_wr && !(flags & CLS_METHOD_WR)) {
logger().error("method tried to update object but is not marked WR"); logger().error("method tried to update object but is not marked WR");
throw crimson::osd::input_output_error{}; return call_errorator::make_plain_exception_future<>(
crimson::ct_error::input_output_error::make());
} }
// for write calls we never return data expect errors. For details refer // for write calls we never return data expect errors. For details refer
@ -96,14 +104,13 @@ OpsExecuter::call_errorator::future<> OpsExecuter::do_op_call(OSDOp& osd_op)
osd_op.op.extent.length = outdata.length(); osd_op.op.extent.length = outdata.length();
osd_op.outdata.claim_append(outdata); osd_op.outdata.claim_append(outdata);
} }
return ret;
}).then([] (const int ret) {
if (ret < 0) { if (ret < 0) {
return call_errorator::make_plain_exception_future<>( return call_errorator::make_plain_exception_future<>(
ceph::stateful_errint{ ret }); crimson::stateful_errint{ ret });
} }
return seastar::now(); return seastar::now();
}); }
);
} }
static inline std::unique_ptr<const PGLSFilter> get_pgls_filter( static inline std::unique_ptr<const PGLSFilter> get_pgls_filter(
@ -416,7 +423,15 @@ OpsExecuter::execute_osd_op(OSDOp& osd_op)
return seastar::now(); return seastar::now();
}, ceph::stateful_errint::handle([] (int err) { }, ceph::stateful_errint::handle([] (int err) {
// TODO: implement the handler. NOP for now. // TODO: implement the handler. NOP for now.
})); }), crimson::ct_error::input_output_error::handle([] {
// TODO: implement the handler. NOP for now.
}),
crimson::errorator<crimson::ct_error::enoent,
crimson::ct_error::input_output_error,
crimson::ct_error::operation_not_supported,
crimson::ct_error::permission_denied,
crimson::ct_error::invarg>::discard_all{}
);
case CEPH_OSD_OP_STAT: case CEPH_OSD_OP_STAT:
// note: stat does not require RD // note: stat does not require RD
return do_const_op([&osd_op] (/* const */auto& backend, const auto& os) { return do_const_op([&osd_op] (/* const */auto& backend, const auto& os) {

View File

@ -65,7 +65,13 @@ class OpsExecuter {
template <class Context, class MainFunc, class EffectFunc> template <class Context, class MainFunc, class EffectFunc>
auto with_effect(Context&& ctx, MainFunc&& main_func, EffectFunc&& effect_func); auto with_effect(Context&& ctx, MainFunc&& main_func, EffectFunc&& effect_func);
using call_errorator = ceph::errorator<ceph::stateful_errint>; using call_errorator = crimson::errorator<
crimson::stateful_errint,
crimson::ct_error::enoent,
crimson::ct_error::invarg,
crimson::ct_error::permission_denied,
crimson::ct_error::operation_not_supported,
crimson::ct_error::input_output_error>;
call_errorator::future<> do_op_call(class OSDOp& osd_op); call_errorator::future<> do_op_call(class OSDOp& osd_op);
template <class Func> template <class Func>