[RFC PATCH 0/3] ipc/mqueue: add fcntl(F_MQ_PEEK) for non-destructive message inspection
From: Shaurya Rane
Date: Wed Mar 25 2026 - 15:03:32 EST
POSIX message queues currently have no way to inspect queued messages
without consuming them. mq_receive() always dequeues the message it
returns. This makes it impossible for checkpoint/restore tools such as
CRIU to save and replay message queue contents without first destroying
the queue state.
This series adds F_MQ_PEEK, a new fcntl command that reads a message
from a POSIX message queue by index (0 = highest priority, matching
mq_receive dequeue order) without removing it.
Background
----------
CRIU (Checkpoint/Restore In Userspace) supports live container migration
and process checkpoint/restore. It handles SysV message queues, shared
memory, semaphores, pipes, and sockets, but POSIX mqueues remain
unsupported because there is no kernel interface to inspect queued
messages non-destructively.
The SysV analogue for this problem was solved in 2012: the MSG_COPY flag
was added to msgrcv() in commit 4a674f34ba04 ("ipc: introduce message
queue copy feature") specifically for CRIU. This series does the same
for POSIX mqueues.
Why fcntl and not a new syscall
---------------------------------
POSIX mqueue file descriptors are first-class Linux file descriptors.
fcntl() is the established interface for per-fd operations beyond
read/write: F_GETPIPE_SZ queries pipe capacity, F_ADD_SEALS/F_GET_SEALS
control memfd sealing, F_GETDELEG manages file delegations. F_MQ_PEEK
follows this same pattern.
Adding a flag to mq_timedreceive() is not possible without ABI breakage:
the POSIX signature has no flags parameter. A new syscall is unnecessary
when fcntl() covers the use case cleanly.
Series overview
---------------
Patch 1 adds struct mq_peek_attr and F_MQ_PEEK to the UAPI headers.
Patch 2 moves struct msg_msgseg and DATALEN_MSG/DATALEN_SEG from the
private ipc/msgutil.c to include/linux/msg.h. This is a pure
refactoring (no functional change) that allows ipc/mqueue.c to walk
multi-segment message chains under a spinlock using only memcpy()
(copy_to_user() cannot be called under a spinlock).
Patch 3 implements do_mq_peek() in ipc/mqueue.c and dispatches it from
fs/fcntl.c. The implementation holds info->lock for the tree traversal
and kernel-buffer copy, then releases the lock before copy_to_user().
A corresponding CRIU userspace patch will be sent to the CRIU mailing
list separately. It uses F_MQ_PEEK when the kernel supports it,
falling back to a ptrace-safe intrusive drain/re-enqueue on older
kernels.
Link: https://github.com/checkpoint-restore/criu/issues/2285
Shaurya Rane (3):
mqueue: uapi: add struct mq_peek_attr and F_MQ_PEEK
msg: move struct msg_msgseg and DATALEN_* to include/linux/msg.h
ipc/mqueue: implement fcntl(F_MQ_PEEK) for non-destructive message inspection
fs/fcntl.c | 3 +
include/linux/mqueue.h | 19 ++++++
include/linux/msg.h | 13 ++++
include/uapi/linux/fcntl.h | 7 ++
include/uapi/linux/mqueue.h | 20 ++++++
ipc/mqueue.c | 130 ++++++++++++++++++++++++++++++++++++
ipc/msgutil.c | 7 --
7 files changed, 192 insertions(+), 7 deletions(-)
--
2.43.0