All of lore.kernel.org
 help / color / mirror / Atom feed
From: Markus Armbruster <armbru@redhat.com>
To: "Daniel P. Berrangé" <berrange@redhat.com>
Cc: Kevin Wolf <kwolf@redhat.com>,
	qemu-block@nongnu.org, qemu-devel@nongnu.org,
	Max Reitz <mreitz@redhat.com>,
	Stefan Hajnoczi <stefanha@redhat.com>, P J P <ppandit@redhat.com>
Subject: Re: [PATCH 2/3] util: support detailed error reporting for qemu_open
Date: Thu, 02 Jul 2020 07:13:08 +0200	[thread overview]
Message-ID: <87a70i7b4r.fsf@dusky.pond.sub.org> (raw)
In-Reply-To: <20200701160509.1523847-3-berrange@redhat.com> ("Daniel P. Berrangé"'s message of "Wed, 1 Jul 2020 17:05:08 +0100")

Daniel P. Berrangé <berrange@redhat.com> writes:

> Create a "qemu_open_err" method which does the same as "qemu_open",
> but with a "Error **errp" for error reporting. There should be no
> behavioural difference for existing callers at this stage.
>
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
>  include/qemu/osdep.h |  1 +
>  util/osdep.c         | 71 +++++++++++++++++++++++++++++++++++---------
>  2 files changed, 58 insertions(+), 14 deletions(-)
>
> diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
> index 0d26a1b9bd..e41701a308 100644
> --- a/include/qemu/osdep.h
> +++ b/include/qemu/osdep.h
> @@ -483,6 +483,7 @@ int qemu_madvise(void *addr, size_t len, int advice);
>  int qemu_mprotect_rwx(void *addr, size_t size);
>  int qemu_mprotect_none(void *addr, size_t size);
>  
> +int qemu_open_err(const char *name, int flags, Error **errp, ...);
>  int qemu_open(const char *name, int flags, ...);
>  int qemu_close(int fd);
>  int qemu_unlink(const char *name);
> diff --git a/util/osdep.c b/util/osdep.c
> index 4bdbe81cec..450b3a5da3 100644
> --- a/util/osdep.c
> +++ b/util/osdep.c
> @@ -22,6 +22,7 @@
>   * THE SOFTWARE.
>   */
>  #include "qemu/osdep.h"
> +#include "qapi/error.h"
>  
>  /* Needed early for CONFIG_BSD etc. */
>  
> @@ -282,7 +283,7 @@ int qemu_lock_fd_test(int fd, int64_t start, int64_t len, bool exclusive)
>  /*
>   * Opens a file with FD_CLOEXEC set
>   */
> -int qemu_open(const char *name, int flags, ...)
> +static int qemu_openv(const char *name, int flags, Error **errp, va_list ap)
>  {
>      int ret;
>      int mode = 0;
> @@ -297,24 +298,31 @@ int qemu_open(const char *name, int flags, ...)
>  
>          fdset_id = qemu_parse_fdset(fdset_id_str);
>          if (fdset_id == -1) {
> +            error_setg(errp, "Unable to parse fdset %s", name);
>              errno = EINVAL;
>              return -1;
>          }
>  
>          fd = monitor_fdset_get_fd(fdset_id, flags);
>          if (fd < 0) {
> +            error_setg_errno(errp, -fd, "Unable acquire FD for %s flags %x",
> +                             name, flags);
>              errno = -fd;
>              return -1;
>          }
>  
>          dupfd = qemu_dup_flags(fd, flags);
>          if (dupfd == -1) {
> +            error_setg_errno(errp, errno, "Unable dup FD for %s flags %x",
> +                             name, flags);
>              return -1;
>          }
>  
>          ret = monitor_fdset_dup_fd_add(fdset_id, dupfd);
>          if (ret == -1) {
>              close(dupfd);
> +            error_setg(errp, "Unable save FD for %s flags %x",
> +                       name, flags);
>              errno = EINVAL;
>              return -1;
>          }
> @@ -324,11 +332,7 @@ int qemu_open(const char *name, int flags, ...)
>  #endif
>  
>      if (flags & O_CREAT) {
> -        va_list ap;
> -
> -        va_start(ap, flags);
>          mode = va_arg(ap, int);
> -        va_end(ap);
>      }
>  
>  #ifdef O_CLOEXEC
> @@ -340,25 +344,64 @@ int qemu_open(const char *name, int flags, ...)
>      }
>  #endif
>  
> +    if (ret == -1) {
> +        const char *action = "open";
> +        if (flags & O_CREAT) {
> +            action = "create";
> +        }
>  #ifdef O_DIRECT
> -    if (ret == -1 && errno == EINVAL && (flags & O_DIRECT)) {
> -        int newflags = flags & ~O_DIRECT;
> +        if (errno == EINVAL && (flags & O_DIRECT)) {
> +            int newflags = flags & ~O_DIRECT;
>  # ifdef O_CLOEXEC
> -        ret = open(name, newflags | O_CLOEXEC, mode);
> +            ret = open(name, newflags | O_CLOEXEC, mode);
>  # else
> -        ret = open(name, newflags, mode);
> +            ret = open(name, newflags, mode);
>  # endif
> -        if (ret != -1) {
> -            close(ret);
> -            error_report("file system does not support O_DIRECT");
> -            errno = EINVAL;
> +            if (ret != -1) {
> +                close(ret);
> +                error_setg(errp, "Unable to %s '%s' flags 0x%x: "
> +                           "filesystem does not support O_DIRECT",
> +                           action, name, flags);
> +                if (!errp) {

If the caller ignores errors, ...

> +                    error_report("file system does not support O_DIRECT");

... we report this error to stderr (but not any of the other ones).
This is weird.  I figure you do it here to reproduce the weirdness of
qemu_open() before the patch.  Goes back to

    commit a5813077aac7865f69b7ee46a594f3705429f7cd
    Author: Stefan Hajnoczi <stefanha@redhat.com>
    Date:   Thu Aug 22 11:29:03 2013 +0200

        osdep: warn if open(O_DIRECT) on fails with EINVAL

        Print a warning when opening a file O_DIRECT fails with EINVAL.  This
        saves users a lot of time trying to figure out the EINVAL error, which
        is typical when attempting to open a file O_DIRECT on Linux tmpfs.

        Reported-by: Deepak C Shetty <deepakcs@linux.vnet.ibm.com>
        Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
        Reviewed-by: Eric Blake <eblake@redhat.com>

The message isn't phrased as a warning, though.  Should it use
warn_report()?  Stefan?

Regardless, since use of error_report() in a function that returns
errors through its Error ** parameter is an anti-pattern, this use needs
a comment.  I'd make it a TODO comment: convert all callers where the
warning is wanted to qemu_open_err(), then drop it.

> +                }
> +                errno = EINVAL;
> +                return -1;
> +            }
>          }
> -    }
>  #endif /* O_DIRECT */
> +        error_setg_errno(errp, errno, "Unable to %s '%s' flags 0x%x",
> +                         action, name, flags);
> +    }
> +
>  
>      return ret;
>  }
>  
> +int qemu_open_err(const char *name, int flags, Error **errp, ...)
> +{
> +    va_list ap;
> +    int rv;
> +
> +    va_start(ap, errp);
> +    rv = qemu_openv(name, flags, errp, ap);
> +    va_end(ap);
> +
> +    return rv;
> +}
> +
> +int qemu_open(const char *name, int flags, ...)
> +{
> +    va_list ap;
> +    int rv;
> +
> +    va_start(ap, flags);
> +    rv = qemu_openv(name, flags, NULL, ap);
> +    va_end(ap);
> +
> +    return rv;
> +}

I'd rename this to qemu_open_with_bad_error_messages().

For better ones, callers can use

    if (qemu_open_err(name, flags, &err) < 0) {
        error_report_err(err);
        ...
    }

or, where the error is fatal
    
    qemu_open_err(name, flags, &error_fatal);

If you prefer not to rename it now, please add a comment why it should
not be used in new code, and existing uses should be converted.

If you rename, call the new one qemu_open().

> +
>  int qemu_close(int fd)
>  {
>      int64_t fdset_id;



  reply	other threads:[~2020-07-02  5:19 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-07-01 16:05 [PATCH 0/3] block: improve error reporting for unsupported O_DIRECT Daniel P. Berrangé
2020-07-01 16:05 ` [PATCH 1/3] util: validate whether O_DIRECT is supported after failure Daniel P. Berrangé
2020-07-02 10:10   ` Philippe Mathieu-Daudé
2020-07-01 16:05 ` [PATCH 2/3] util: support detailed error reporting for qemu_open Daniel P. Berrangé
2020-07-02  5:13   ` Markus Armbruster [this message]
2020-07-02  9:30     ` Daniel P. Berrangé
2020-07-01 16:05 ` [PATCH 3/3] block: switch to use qemu_open_err for improved errors Daniel P. Berrangé
2020-07-01 16:58 ` [PATCH 0/3] block: improve error reporting for unsupported O_DIRECT no-reply

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=87a70i7b4r.fsf@dusky.pond.sub.org \
    --to=armbru@redhat.com \
    --cc=berrange@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=mreitz@redhat.com \
    --cc=ppandit@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    /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.