All of lore.kernel.org
 help / color / mirror / Atom feed
From: Zhao Liu <zhao1.liu@intel.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: qemu-devel@nongnu.org, kwolf@redhat.com
Subject: Re: [PATCH v3 2/2] rust: add module to convert between success/-errno and io::Result
Date: Fri, 21 Feb 2025 19:01:07 +0800	[thread overview]
Message-ID: <Z7hc8+h+mGnT7CSh@intel.com> (raw)
In-Reply-To: <20250220113659.863332-3-pbonzini@redhat.com>

Hi Paolo,

> It is a common convention in QEMU to return a positive value in case of
> success, and a negated errno value in case of error.  Unfortunately,
> using errno portably in Rust is a bit complicated; on Unix the errno
> values are supported natively by io::Error, but on Windows they are not;
> so, use the libc crate.

I'm a bit confused. The doc of error.h just said the negative value for
failure:

• integer-valued functions return non-negative / negative.

Why do we need to using libc's -errno for Windows as well?

Converting `io::Error::last_os_error().raw_os_error().unwrap()` to a
negative value seems compatible with Windows, except it returns Windows
error codes.

> This is a set of utility functions that are used by both chardev and
> block layer bindings.

...

> +// On Unix, from_raw_os_error takes an errno value and OS errors
> +// are printed using strerror.  On Windows however it takes a
> +// GetLastError() value; therefore we need to convert errno values
> +// into io::Error by hand.  This is the same mapping that the
> +// standard library uses to retrieve the kind of OS errors
> +// (`std::sys::pal::unix::decode_error_kind`).
> +impl From<Errno> for ErrorKind {
> +    fn from(value: Errno) -> ErrorKind {

What about `use ErrorKind::*;` to oimt the following "ErrorKind::"
prefix?

> +        let Errno(errno) = value;
> +        match i32::from(errno) {

Maybe `match i32::from(errno.0)` ?

> +            libc::EPERM | libc::EACCES => ErrorKind::PermissionDenied,
> +            libc::ENOENT => ErrorKind::NotFound,
> +            libc::EINTR => ErrorKind::Interrupted,
> +            x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => ErrorKind::WouldBlock,
> +            libc::ENOMEM => ErrorKind::OutOfMemory,
> +            libc::EEXIST => ErrorKind::AlreadyExists,
> +            libc::EINVAL => ErrorKind::InvalidInput,
> +            libc::EPIPE => ErrorKind::BrokenPipe,
> +            libc::EADDRINUSE => ErrorKind::AddrInUse,
> +            libc::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
> +            libc::ECONNABORTED => ErrorKind::ConnectionAborted,
> +            libc::ECONNREFUSED => ErrorKind::ConnectionRefused,
> +            libc::ECONNRESET => ErrorKind::ConnectionReset,
> +            libc::ENOTCONN => ErrorKind::NotConnected,
> +            libc::ENOTSUP => ErrorKind::Unsupported,
> +            libc::ETIMEDOUT => ErrorKind::TimedOut,
> +            _ => ErrorKind::Other,

Are these errno cases specifically selected? It seems to have fewer than
`decode_error_kind` lists. Why not support all the cases `decode_error_kind`
mentions? Or do we need to try to cover as many errno cases as possible
from rust/kernel/error.rs?

> +        }
> +    }
> +}
> +
> +// This is used on Windows for all io::Errors, but also on Unix if the
> +// io::Error does not have a raw OS error.  This is the reversed
> +// mapping of the above.

Maybe:

This is the "almost" reversed (except the default case) mapping

?

> +impl From<io::ErrorKind> for Errno {
> +    fn from(value: io::ErrorKind) -> Errno {

`use ErrorKind::*;` could save some words, too.

> +        let errno = match value {
> +            // can be both EPERM or EACCES :( pick one
> +            ErrorKind::PermissionDenied => libc::EPERM,
> +            ErrorKind::NotFound => libc::ENOENT,
> +            ErrorKind::Interrupted => libc::EINTR,
> +            ErrorKind::WouldBlock => libc::EAGAIN,
> +            ErrorKind::OutOfMemory => libc::ENOMEM,
> +            ErrorKind::AlreadyExists => libc::EEXIST,
> +            ErrorKind::InvalidInput => libc::EINVAL,
> +            ErrorKind::BrokenPipe => libc::EPIPE,
> +            ErrorKind::AddrInUse => libc::EADDRINUSE,
> +            ErrorKind::AddrNotAvailable => libc::EADDRNOTAVAIL,
> +            ErrorKind::ConnectionAborted => libc::ECONNABORTED,
> +            ErrorKind::ConnectionRefused => libc::ECONNREFUSED,
> +            ErrorKind::ConnectionReset => libc::ECONNRESET,
> +            ErrorKind::NotConnected => libc::ENOTCONN,
> +            ErrorKind::Unsupported => libc::ENOTSUP,
> +            ErrorKind::TimedOut => libc::ETIMEDOUT,
> +            _ => libc::EIO,
> +        };
> +        Errno(errno as u16)
> +    }
> +}
> +
> +impl From<Errno> for io::Error {
> +    #[cfg(unix)]
> +    fn from(value: Errno) -> io::Error {
> +        let Errno(errno) = value;
> +        io::Error::from_raw_os_error(errno.into())

Maybe `io::Error::from_raw_os_error(value.0.into())`?

> +    }
> +
> +    #[cfg(windows)]
> +    fn from(value: Errno) -> io::Error {
> +        let error_kind: ErrorKind = value.into();
> +        error_kind.into()

Even this works:

     fn from(value: Errno) -> io::Error {
-        let error_kind: ErrorKind = value.into();
-        error_kind.into()
+        value.into()

However, it's less readability, so I still prefer your current codes.
:-)

Thanks,
Zhao




  reply	other threads:[~2025-02-21 10:42 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-02-20 11:36 [PATCH v3 0/2] rust: add module to convert between success/-errno and io::Result conventions Paolo Bonzini
2025-02-20 11:36 ` [PATCH v3 1/2] rust: subprojects: add libc crate Paolo Bonzini
2025-02-20 11:36 ` [PATCH v3 2/2] rust: add module to convert between success/-errno and io::Result Paolo Bonzini
2025-02-21 11:01   ` Zhao Liu [this message]
2025-02-25 13:21     ` Paolo Bonzini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Z7hc8+h+mGnT7CSh@intel.com \
    --to=zhao1.liu@intel.com \
    --cc=kwolf@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.