diff options
author | Fam Zheng <famz@redhat.com> | 2017-08-11 19:44:46 +0800 |
---|---|---|
committer | Kevin Wolf <kwolf@redhat.com> | 2017-08-11 14:12:44 +0200 |
commit | ca749954b09b89e22cd69c4949fb7e689b057963 (patch) | |
tree | 48118b0486719b09f272cda9d720e4d0ab96bf2a /util/osdep.c | |
parent | d0d5d0e31a874d592741a088c2c5071bae164dbf (diff) |
osdep: Add runtime OFD lock detection
Build time check of OFD lock is not sufficient and can cause image open
errors when the runtime environment doesn't support it.
Add a helper function to probe it at runtime, additionally. Also provide
a qemu_has_ofd_lock() for callers to check the status.
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'util/osdep.c')
-rw-r--r-- | util/osdep.c | 66 |
1 files changed, 56 insertions, 10 deletions
diff --git a/util/osdep.c b/util/osdep.c index a2863c8e53..a479fedc4a 100644 --- a/util/osdep.c +++ b/util/osdep.c @@ -38,14 +38,6 @@ extern int madvise(caddr_t, size_t, int); #include "qemu/error-report.h" #include "monitor/monitor.h" -#ifdef F_OFD_SETLK -#define QEMU_SETLK F_OFD_SETLK -#define QEMU_GETLK F_OFD_GETLK -#else -#define QEMU_SETLK F_SETLK -#define QEMU_GETLK F_GETLK -#endif - static bool fips_enabled = false; static const char *hw_version = QEMU_HW_VERSION; @@ -82,6 +74,10 @@ int qemu_madvise(void *addr, size_t len, int advice) } #ifndef _WIN32 + +static int fcntl_op_setlk = -1; +static int fcntl_op_getlk = -1; + /* * Dups an fd and sets the flags */ @@ -149,6 +145,54 @@ static int qemu_parse_fdset(const char *param) return qemu_parse_fd(param); } +static void qemu_probe_lock_ops(void) +{ + if (fcntl_op_setlk == -1) { +#ifdef F_OFD_SETLK + int fd; + int ret; + struct flock fl = { + .l_whence = SEEK_SET, + .l_start = 0, + .l_len = 0, + .l_type = F_WRLCK, + }; + + fd = open("/dev/null", O_RDWR); + if (fd < 0) { + fprintf(stderr, + "Failed to open /dev/null for OFD lock probing: %s\n", + strerror(errno)); + fcntl_op_setlk = F_SETLK; + fcntl_op_getlk = F_GETLK; + return; + } + ret = fcntl(fd, F_OFD_GETLK, &fl); + close(fd); + if (!ret) { + fcntl_op_setlk = F_OFD_SETLK; + fcntl_op_getlk = F_OFD_GETLK; + } else { + fcntl_op_setlk = F_SETLK; + fcntl_op_getlk = F_GETLK; + } +#else + fcntl_op_setlk = F_SETLK; + fcntl_op_getlk = F_GETLK; +#endif + } +} + +bool qemu_has_ofd_lock(void) +{ + qemu_probe_lock_ops(); +#ifdef F_OFD_SETLK + return fcntl_op_setlk == F_OFD_SETLK; +#else + return false; +#endif +} + static int qemu_lock_fcntl(int fd, int64_t start, int64_t len, int fl_type) { int ret; @@ -158,7 +202,8 @@ static int qemu_lock_fcntl(int fd, int64_t start, int64_t len, int fl_type) .l_len = len, .l_type = fl_type, }; - ret = fcntl(fd, QEMU_SETLK, &fl); + qemu_probe_lock_ops(); + ret = fcntl(fd, fcntl_op_setlk, &fl); return ret == -1 ? -errno : 0; } @@ -181,7 +226,8 @@ int qemu_lock_fd_test(int fd, int64_t start, int64_t len, bool exclusive) .l_len = len, .l_type = exclusive ? F_WRLCK : F_RDLCK, }; - ret = fcntl(fd, QEMU_GETLK, &fl); + qemu_probe_lock_ops(); + ret = fcntl(fd, fcntl_op_getlk, &fl); if (ret == -1) { return -errno; } else { |