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>
This commit is contained in:
parent
d0d5d0e31a
commit
ca749954b0
@ -357,6 +357,7 @@ int qemu_dup(int fd);
|
||||
int qemu_lock_fd(int fd, int64_t start, int64_t len, bool exclusive);
|
||||
int qemu_unlock_fd(int fd, int64_t start, int64_t len);
|
||||
int qemu_lock_fd_test(int fd, int64_t start, int64_t len, bool exclusive);
|
||||
bool qemu_has_ofd_lock(void);
|
||||
|
||||
#if defined(__HAIKU__) && defined(__i386__)
|
||||
#define FMT_pid "%ld"
|
||||
|
66
util/osdep.c
66
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 {
|
||||
|
Loading…
Reference in New Issue
Block a user