diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2020-09-16 16:25:30 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2020-09-16 16:25:30 +0100 |
commit | 525009d04fa49567b0eba43f9ff3c17e560dabb7 (patch) | |
tree | 90efbde052569b8bbc71cdd5611ea9ba006d75e1 /util | |
parent | 8ee612722dc08830761516e761dde934c3753a14 (diff) | |
parent | b18a24a9f889bcf722754046130507d744a1b0b9 (diff) | |
download | qemu-525009d04fa49567b0eba43f9ff3c17e560dabb7.zip qemu-525009d04fa49567b0eba43f9ff3c17e560dabb7.tar.gz qemu-525009d04fa49567b0eba43f9ff3c17e560dabb7.tar.bz2 |
Merge remote-tracking branch 'remotes/berrange/tags/block-odirect-pull-request' into staging
block: improve error reporting for unsupported O_DIRECT
# gpg: Signature made Wed 16 Sep 2020 10:45:48 BST
# gpg: using RSA key DAF3A6FDB26B62912D0E8E3FBE86EBB415104FDF
# gpg: Good signature from "Daniel P. Berrange <dan@berrange.com>" [full]
# gpg: aka "Daniel P. Berrange <berrange@redhat.com>" [full]
# Primary key fingerprint: DAF3 A6FD B26B 6291 2D0E 8E3F BE86 EBB4 1510 4FDF
* remotes/berrange/tags/block-odirect-pull-request:
block/file: switch to use qemu_open/qemu_create for improved errors
util: give a specific error message when O_DIRECT doesn't work
util: introduce qemu_open and qemu_create with error reporting
util: add Error object for qemu_open_internal error reporting
util: refactor qemu_open_old to split off variadic args handling
util: rename qemu_open() to qemu_open_old()
util: split off a helper for dealing with O_CLOEXEC flag
monitor: simplify functions for getting a dup'd fdset entry
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'util')
-rw-r--r-- | util/osdep.c | 104 | ||||
-rw-r--r-- | util/oslib-posix.c | 2 |
2 files changed, 75 insertions, 31 deletions
diff --git a/util/osdep.c b/util/osdep.c index 4829c07..8ea7a80 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. */ @@ -122,7 +123,7 @@ static int fcntl_op_getlk = -1; /* * Dups an fd and sets the flags */ -static int qemu_dup_flags(int fd, int flags) +int qemu_dup_flags(int fd, int flags) { int ret; int serrno; @@ -279,13 +280,27 @@ int qemu_lock_fd_test(int fd, int64_t start, int64_t len, bool exclusive) } #endif +static int qemu_open_cloexec(const char *name, int flags, mode_t mode) +{ + int ret; +#ifdef O_CLOEXEC + ret = open(name, flags | O_CLOEXEC, mode); +#else + ret = open(name, flags, mode); + if (ret >= 0) { + qemu_set_cloexec(ret); + } +#endif + return ret; +} + /* * Opens a file with FD_CLOEXEC set */ -int qemu_open(const char *name, int flags, ...) +static int +qemu_open_internal(const char *name, int flags, mode_t mode, Error **errp) { int ret; - int mode = 0; #ifndef _WIN32 const char *fdset_id_str; @@ -293,29 +308,19 @@ int qemu_open(const char *name, int flags, ...) /* Attempt dup of fd from fd set */ if (strstart(name, "/dev/fdset/", &fdset_id_str)) { int64_t fdset_id; - int fd, dupfd; + int dupfd; fdset_id = qemu_parse_fdset(fdset_id_str); if (fdset_id == -1) { + error_setg(errp, "Could not parse fdset %s", name); errno = EINVAL; return -1; } - fd = monitor_fdset_get_fd(fdset_id, flags); - if (fd < 0) { - errno = -fd; - return -1; - } - - dupfd = qemu_dup_flags(fd, flags); + dupfd = monitor_fdset_dup_fd_add(fdset_id, flags); if (dupfd == -1) { - return -1; - } - - ret = monitor_fdset_dup_fd_add(fdset_id, dupfd); - if (ret == -1) { - close(dupfd); - errno = EINVAL; + error_setg_errno(errp, errno, "Could not dup FD for %s flags %x", + name, flags); return -1; } @@ -323,22 +328,61 @@ int qemu_open(const char *name, int flags, ...) } #endif - if (flags & O_CREAT) { - va_list ap; + ret = qemu_open_cloexec(name, flags, mode); - va_start(ap, flags); - mode = va_arg(ap, int); - va_end(ap); + if (ret == -1) { + const char *action = flags & O_CREAT ? "create" : "open"; +#ifdef O_DIRECT + /* Give more helpful error message for O_DIRECT */ + if (errno == EINVAL && (flags & O_DIRECT)) { + ret = open(name, flags & ~O_DIRECT, mode); + if (ret != -1) { + close(ret); + error_setg(errp, "Could not %s '%s': " + "filesystem does not support O_DIRECT", + action, name); + errno = EINVAL; /* restore first open()'s errno */ + return -1; + } + } +#endif /* O_DIRECT */ + error_setg_errno(errp, errno, "Could not %s '%s'", + action, name); } -#ifdef O_CLOEXEC - ret = open(name, flags | O_CLOEXEC, mode); -#else - ret = open(name, flags, mode); - if (ret >= 0) { - qemu_set_cloexec(ret); + return ret; +} + + +int qemu_open(const char *name, int flags, Error **errp) +{ + assert(!(flags & O_CREAT)); + + return qemu_open_internal(name, flags, 0, errp); +} + + +int qemu_create(const char *name, int flags, mode_t mode, Error **errp) +{ + assert(!(flags & O_CREAT)); + + return qemu_open_internal(name, flags | O_CREAT, mode, errp); +} + + +int qemu_open_old(const char *name, int flags, ...) +{ + va_list ap; + mode_t mode = 0; + int ret; + + va_start(ap, flags); + if (flags & O_CREAT) { + mode = va_arg(ap, int); } -#endif + va_end(ap); + + ret = qemu_open_internal(name, flags, mode, NULL); #ifdef O_DIRECT if (ret == -1 && errno == EINVAL && (flags & O_DIRECT)) { diff --git a/util/oslib-posix.c b/util/oslib-posix.c index ad8001a..f5f676f 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -125,7 +125,7 @@ bool qemu_write_pidfile(const char *path, Error **errp) .l_len = 0, }; - fd = qemu_open(path, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR); + fd = qemu_open_old(path, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR); if (fd == -1) { error_setg_errno(errp, errno, "Cannot open pid file"); return false; |