The new 'posix' value for the 'locking' property of file-based block
devices forces the use of traditional POSIX locks (F_SETLK/F_GETLK)
instead of OFD (Open File Descriptor) locks.
While OFD locks are preferred when available — they are per file descriptor and
thus survive QEMU-internal fd operations such as hot-plug and block jobs — some
userspace filesystem implementations (e.g. FUSE) handle POSIX locks correctly
but do not fully support OFD lock semantics. Issues with OFD support detection
on underlying file systems and some OFD guarantees not being fully supported
can prohibit users from using the default OFD locking.
Previously, users in this situation had no way to force POSIX locks without
disabling locking entirely; 'locking=on' would silently fall back to POSIX only
when OFD was unavailable.
The new 'posix' option makes the choice explicit and allows users to set up a
clear POSIX config, allowing users to control the locking setup for any scenario
where OFD locking is not advisable.
Note that the known shortcoming of POSIX locks still applies: locks
can be silently lost when QEMU closes and reopens file descriptors
during hot-plug or block job operations.
Signed-off-by: Silvan Kaiser <silvan@quobyte.com>
---
block/file-posix.c | 18 +++++++++++-------
include/qemu/osdep.h | 1 +
qapi/block-core.json | 18 ++++++++++++++++--
util/osdep.c | 9 +++++++--
4 files changed, 35 insertions(+), 11 deletions(-)
diff --git a/block/file-posix.c b/block/file-posix.c
index e49b13d6ab..c99974000d 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -625,7 +625,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
BlockdevAioOptions aio, aio_default;
int fd, ret;
struct stat st;
- OnOffAuto locking;
+ BlockdevLockingOptions locking;
opts = qemu_opts_create(&raw_runtime_opts, NULL, 0, &error_abort);
if (!qemu_opts_absorb_qdict(opts, options, errp)) {
@@ -666,16 +666,16 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
s->aio_max_batch = qemu_opt_get_number(opts, "aio-max-batch", 0);
- locking = qapi_enum_parse(&OnOffAuto_lookup,
- qemu_opt_get(opts, "locking"),
- ON_OFF_AUTO_AUTO, &local_err);
+ locking = qapi_enum_parse(&BlockdevLockingOptions_lookup,
+ qemu_opt_get(opts, "locking"),
+ BLOCKDEV_LOCKING_OPTIONS_AUTO, &local_err);
if (local_err) {
error_propagate(errp, local_err);
ret = -EINVAL;
goto fail;
}
switch (locking) {
- case ON_OFF_AUTO_ON:
+ case BLOCKDEV_LOCKING_OPTIONS_ON:
s->use_lock = true;
if (!qemu_has_ofd_lock()) {
warn_report("File lock requested but OFD locking syscall is "
@@ -684,12 +684,16 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
"unexpectedly.\n");
}
break;
- case ON_OFF_AUTO_OFF:
+ case BLOCKDEV_LOCKING_OPTIONS_OFF:
s->use_lock = false;
break;
- case ON_OFF_AUTO_AUTO:
+ case BLOCKDEV_LOCKING_OPTIONS_AUTO:
s->use_lock = qemu_has_ofd_lock();
break;
+ case BLOCKDEV_LOCKING_OPTIONS_POSIX:
+ s->use_lock = true;
+ qemu_use_posix_locks();
+ break;
default:
abort();
}
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
index f151578b5c..8ea506e462 100644
--- a/include/qemu/osdep.h
+++ b/include/qemu/osdep.h
@@ -634,6 +634,7 @@ 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);
int qemu_fcntl_addfl(int fd, int flag);
+void qemu_use_posix_locks(void);
#endif
bool qemu_has_direct_io(void);
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 508b081ac1..cec369f0fe 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -3362,6 +3362,19 @@
{ 'name': 'virtio-blk-vhost-vdpa', 'if': 'CONFIG_BLKIO' },
'vmdk', 'vpc', 'vvfat' ] }
+##
+# @BlockdevLockingOptions:
+#
+# @off: Disable locking.
+# @on: Enable locking (prefer OFD).
+# @auto: Use locking if OFD is available.
+# @posix: Force use of traditional POSIX locks.
+#
+# Since: 10.3
+##
+{ 'enum': 'BlockdevLockingOptions',
+ 'data': [ 'off', 'on', 'auto', 'posix' ] }
+
##
# @BlockdevOptionsFile:
#
@@ -3382,7 +3395,8 @@
# automatically. (default: 0, since 6.2)
#
# @locking: whether to enable file locking. If set to 'auto', only
-# enable when Open File Descriptor (OFD) locking API is available
+# enable when Open File Descriptor (OFD) locking API is available.
+# 'posix' forces use of POSIX locks.
# (default: auto, since 2.10)
#
# @drop-cache: invalidate page cache during live migration. This
@@ -3412,7 +3426,7 @@
{ 'struct': 'BlockdevOptionsFile',
'data': { 'filename': 'str',
'*pr-manager': 'str',
- '*locking': 'OnOffAuto',
+ '*locking': 'BlockdevLockingOptions',
'*aio': 'BlockdevAioOptions',
'*aio-max-batch': 'int',
'*drop-cache': {'type': 'bool',
diff --git a/util/osdep.c b/util/osdep.c
index 000e7daac8..76495282cc 100644
--- a/util/osdep.c
+++ b/util/osdep.c
@@ -223,8 +223,7 @@ static void qemu_probe_lock_ops(void)
fcntl_op_getlk = F_GETLK;
}
#else
- fcntl_op_setlk = F_SETLK;
- fcntl_op_getlk = F_GETLK;
+ qemu_use_posix_locks();
#endif
}
}
@@ -239,6 +238,12 @@ bool qemu_has_ofd_lock(void)
#endif
}
+void qemu_use_posix_locks(void)
+{
+ fcntl_op_setlk = F_SETLK;
+ fcntl_op_getlk = F_GETLK;
+}
+
static int qemu_lock_fcntl(int fd, int64_t start, int64_t len, int fl_type)
{
int ret;
--
2.47.3
--
Quobyte GmbH, Berlin, AG Charlottenburg HRB 149012 B, Dr. Felix Hupfeld,
Dr. Bjoern Kolbeck
© 2016 - 2026 Red Hat, Inc.