librbd error type

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Currently, the error type of librbd is int, which contains an error code of system_error category.

Each function uses their own meaning for different error codes,
also a code can be used for different situations,
e.g. PreRemoveRequest returns EBUSY when an image has watchers,
on acquiring a lock, or when the image is being migrated.

Librados uses the same int as an error type,
however neorados uses boost::system::error_code.

Latest version of boost::system::error_code is {std::error_code, std::source_location*}.
And std::error_code is {int, error_category*} (in stdlibc++ and libcxx).

It is possible to use custom error types, internally,
however user-facing API have to use a popular type such as std or boost error_code,
otherwise users would have to convert error types.
As std::error_code is the standard error type, and boost::system::error_code is convertible to it

Various alternative approaches to errors, such as  Boost.LEAF,
Boost.Outcome and the corresponding std::error p1028 proposal,
all of them are compatible with std(boost)::error_code.

As std::error_code is a pair of an int and a pointer, it fits into two registers (eax:rdx),
so changing result type from int to std::error_code basically adds one instruction:

std::error_code f() {
    return SomeErrEnum::Code1;
}

with properly defined std::is_error_code_enum<SomeErrEnum> trait,
and a SomeErrCategory type with a corresponding error category global value,
compiles to

f():
        mov     edx, OFFSET some_category_var
        mov     eax, 1
        ret

Full code - https://godbolt.org/z/K7vv5h8oo

Although there are corner cases such as surprisingly ineffective
error_category& cat() { static SomeErrCategory c; return c; }
where "static" requires branching for a guard variable,
it is possible to keep overhead to adding single instruction for the error category.

Back to the librbd.

It is indeed not possible to simply change it's C++ API from returning int to error_code.
Also, we cannot add overloads with different return types, we'd have to also change arguments.
Passing error_code as an output parameter works

int flatten(); // current API
void flatten(std::error_code& ec); // alternative API

but it doesn't look great, ideally we'd rather use 
"std::expected<T, error_code> f()" and not
"void f(T& out, error_code& ec)".  

We can also add asynchronous API like in neorados,
with CompletionTokens and callbacks that receive error_code.
However, much of librbd code is synchronous (Operations),
so rewriting it to an async code would needlessly complicate things.

Is there a way to make librbd return std::error_code,
so that we could use different error categories, enums, for more distinct error codes?
_______________________________________________
Dev mailing list -- dev@xxxxxxx
To unsubscribe send an email to dev-leave@xxxxxxx



[Index of Archives]     [CEPH Users]     [Ceph Devel]     [Ceph Large]     [Information on CEPH]     [Linux BTRFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux