diff mbox series

[v2,1/3] util: validate whether O_DIRECT is supported after failure

Message ID 20200702125612.2176194-2-berrange@redhat.com (mailing list archive)
State New, archived
Headers show
Series block: improve error reporting for unsupported O_DIRECT | expand

Commit Message

Daniel P. Berrangé July 2, 2020, 12:56 p.m. UTC
Currently we suggest that a filesystem may not support O_DIRECT after
seeing an EINVAL. Other things can cause EINVAL though, so it is better
to do an explicit check, and then report a definitive error message.

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 util/osdep.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

Comments

Philippe Mathieu-Daudé July 2, 2020, 3:29 p.m. UTC | #1
On 7/2/20 2:56 PM, Daniel P. Berrangé wrote:
> Currently we suggest that a filesystem may not support O_DIRECT after
> seeing an EINVAL. Other things can cause EINVAL though, so it is better
> to do an explicit check, and then report a definitive error message.
> 
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
>  util/osdep.c | 15 +++++++++++----
>  1 file changed, 11 insertions(+), 4 deletions(-)
> 
> diff --git a/util/osdep.c b/util/osdep.c
> index 4829c07ff6..e2b7507ee2 100644
> --- a/util/osdep.c
> +++ b/util/osdep.c
> @@ -332,9 +332,11 @@ int qemu_open(const char *name, int flags, ...)
>      }
>  
>  #ifdef O_CLOEXEC
> -    ret = open(name, flags | O_CLOEXEC, mode);
> -#else
> +    flags |= O_CLOEXEC;
> +#endif
>      ret = open(name, flags, mode);
> +
> +#ifndef O_CLOEXEC
>      if (ret >= 0) {
>          qemu_set_cloexec(ret);
>      }
> @@ -342,8 +344,13 @@ int qemu_open(const char *name, int flags, ...)

Too bad the git-diff removed 2 lines of context to add a comment instead.

In case it helps other reviewers, what was stripped out of the
context is this single line:

   #endif

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>

>  
>  #ifdef O_DIRECT
>      if (ret == -1 && errno == EINVAL && (flags & O_DIRECT)) {
> -        error_report("file system may not support O_DIRECT");
> -        errno = EINVAL; /* in case it was clobbered */
> +        int newflags = flags & ~O_DIRECT;
> +        ret = open(name, newflags, mode);
> +        if (ret != -1) {
> +            close(ret);
> +            error_report("file system does not support O_DIRECT");
> +            errno = EINVAL;
> +        }
>      }
>  #endif /* O_DIRECT */
>  
>
Markus Armbruster July 8, 2020, 6:45 a.m. UTC | #2
Daniel P. Berrangé <berrange@redhat.com> writes:

> Currently we suggest that a filesystem may not support O_DIRECT after
> seeing an EINVAL. Other things can cause EINVAL though, so it is better
> to do an explicit check, and then report a definitive error message.
>
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
>  util/osdep.c | 15 +++++++++++----
>  1 file changed, 11 insertions(+), 4 deletions(-)
>
> diff --git a/util/osdep.c b/util/osdep.c
> index 4829c07ff6..e2b7507ee2 100644
> --- a/util/osdep.c
> +++ b/util/osdep.c
> @@ -332,9 +332,11 @@ int qemu_open(const char *name, int flags, ...)
>      }
>  
>  #ifdef O_CLOEXEC
> -    ret = open(name, flags | O_CLOEXEC, mode);
> -#else
> +    flags |= O_CLOEXEC;
> +#endif
>      ret = open(name, flags, mode);
> +
> +#ifndef O_CLOEXEC
>      if (ret >= 0) {
>          qemu_set_cloexec(ret);
>      }

I'd prefer something like

   #ifdef O_CLOEXEC
       flags |= O_CLOEXEC;
       ret = open(name, flags, mode);
   #else
       ret = open(name, flags, mode);
       if (ret >= 0) {
           qemu_set_cloexec(ret);
       }
   #endif

Continues to duplicate open(), but spares me the effort to fuse two
#ifdef sections in my head to understand what is being done in each
case.

> @@ -342,8 +344,13 @@ int qemu_open(const char *name, int flags, ...)
>  
>  #ifdef O_DIRECT
>      if (ret == -1 && errno == EINVAL && (flags & O_DIRECT)) {
> -        error_report("file system may not support O_DIRECT");
> -        errno = EINVAL; /* in case it was clobbered */
> +        int newflags = flags & ~O_DIRECT;
> +        ret = open(name, newflags, mode);

I'd prefer the more concise

           ret = open(name, flags & ~O_DIRECT, mode);

> +        if (ret != -1) {
> +            close(ret);
> +            error_report("file system does not support O_DIRECT");
> +            errno = EINVAL;
> +        }
>      }
>  #endif /* O_DIRECT */

The function now reports to stderr in just one of many failure modes.
That's wrong.  Looks like the next patch fixes this defect.  I'd swap
the two.
diff mbox series

Patch

diff --git a/util/osdep.c b/util/osdep.c
index 4829c07ff6..e2b7507ee2 100644
--- a/util/osdep.c
+++ b/util/osdep.c
@@ -332,9 +332,11 @@  int qemu_open(const char *name, int flags, ...)
     }
 
 #ifdef O_CLOEXEC
-    ret = open(name, flags | O_CLOEXEC, mode);
-#else
+    flags |= O_CLOEXEC;
+#endif
     ret = open(name, flags, mode);
+
+#ifndef O_CLOEXEC
     if (ret >= 0) {
         qemu_set_cloexec(ret);
     }
@@ -342,8 +344,13 @@  int qemu_open(const char *name, int flags, ...)
 
 #ifdef O_DIRECT
     if (ret == -1 && errno == EINVAL && (flags & O_DIRECT)) {
-        error_report("file system may not support O_DIRECT");
-        errno = EINVAL; /* in case it was clobbered */
+        int newflags = flags & ~O_DIRECT;
+        ret = open(name, newflags, mode);
+        if (ret != -1) {
+            close(ret);
+            error_report("file system does not support O_DIRECT");
+            errno = EINVAL;
+        }
     }
 #endif /* O_DIRECT */