* [PATCH liburing 3/3] man: Convert manpages to markdown
2026-07-06 21:41 [PATCH liburing 0/3] Convert manpages to markdown Gabriel Krisman Bertazi
2026-07-06 21:41 ` [PATCH liburing 1/3] man: Generate aliases during compilation Gabriel Krisman Bertazi
2026-07-06 21:41 ` [PATCH liburing 2/3] man: Introduce rules to convert Markdown to groff Gabriel Krisman Bertazi
@ 2026-07-06 21:41 ` Gabriel Krisman Bertazi
2026-07-07 12:27 ` [PATCH liburing 0/3] " Jeff Moyer
3 siblings, 0 replies; 9+ messages in thread
From: Gabriel Krisman Bertazi @ 2026-07-06 21:41 UTC (permalink / raw)
To: axboe; +Cc: io-uring, ammarfaizi2, Gabriel Krisman Bertazi
Fully automated conversion of groff manpages to MD. Care is taken to
preserve copyright notices. This patch can be regenerated with the following script:
mkdir orig; mv *.1 *.2 *.3 *.4 *.5 *.6 *.7 *.8 orig/
for i in $(basename -a orig/*) ; do
sed -n '/\.\\"/p' <orig/$i > $i.md
sed -E '/.BI/ s/"//g' orig/$i | sed -E 's/^.BI(.*)/\1/' | \
pandoc -p --wrap=auto --columns=72 --standalone \
--lua-filter=indent-to-code.lua -f man -t markdown >> $i.md
done
rm -r orig
This the lua filter invoked above, required to fix the code blocks. It
is the sole part of this patchset generated with AI:
local function indent_content(text)
local indented = " " .. text
indented = string.gsub(indented, "\n", "\n ")
return indented
end
function CodeBlock(elem)
elem.text = indent_content(elem.text)
elem.classes = { "text" }
return elem
end
function Para(elem)
if #elem.content < 1 then return nil end
if elem.content[1].t == 'Str' then
local text = elem.content[1].text
if string.sub(text, 1, 4) == " " then
elem.content[1].text = string.sub(text, 5)
local code_content = pandoc.utils.stringify(elem.content)
local indented_content = indent_content(code_content)
return pandoc.CodeBlock(indented_content, { "", { "text" }, {} })
end
end
end
Signed-off-by: Gabriel Krisman Bertazi <krisman@suse.de>
---
man/io_uring.7 | 919 -------
man/io_uring.7.md | 779 ++++++
man/io_uring_buf_ring_add.3 | 64 -
man/io_uring_buf_ring_add.3.md | 65 +
man/io_uring_buf_ring_advance.3 | 31 -
man/io_uring_buf_ring_advance.3.md | 41 +
man/io_uring_buf_ring_available.3 | 47 -
man/io_uring_buf_ring_available.3.md | 57 +
man/io_uring_buf_ring_cq_advance.3 | 55 -
man/io_uring_buf_ring_cq_advance.3.md | 56 +
man/io_uring_buf_ring_init.3 | 36 -
man/io_uring_buf_ring_init.3.md | 45 +
man/io_uring_buf_ring_mask.3 | 27 -
man/io_uring_buf_ring_mask.3.md | 37 +
man/io_uring_cancelation.7 | 324 ---
man/io_uring_cancelation.7.md | 288 +++
man/io_uring_check_version.3 | 72 -
man/io_uring_check_version.3.md | 53 +
man/io_uring_clone_buffers.3 | 165 --
man/io_uring_clone_buffers.3.md | 133 +
man/io_uring_close_ring_fd.3 | 43 -
man/io_uring_close_ring_fd.3.md | 55 +
man/io_uring_cq_advance.3 | 49 -
man/io_uring_cq_advance.3.md | 53 +
man/io_uring_cq_eventfd_enabled.3 | 38 -
man/io_uring_cq_eventfd_enabled.3.md | 45 +
man/io_uring_cq_eventfd_toggle.3 | 48 -
man/io_uring_cq_eventfd_toggle.3.md | 53 +
man/io_uring_cq_has_overflow.3 | 31 -
man/io_uring_cq_has_overflow.3.md | 46 +
man/io_uring_cq_ready.3 | 26 -
man/io_uring_cq_ready.3.md | 37 +
man/io_uring_cqe_get_data.3 | 53 -
man/io_uring_cqe_get_data.3.md | 50 +
man/io_uring_cqe_nr.3 | 35 -
man/io_uring_cqe_nr.3.md | 42 +
man/io_uring_cqe_seen.3 | 41 -
man/io_uring_cqe_seen.3.md | 47 +
man/io_uring_enable_rings.3 | 40 -
man/io_uring_enable_rings.3.md | 48 +
man/io_uring_enter.2 | 2208 -----------------
man/io_uring_enter.2.md | 1466 +++++++++++
man/io_uring_for_each_cqe.3 | 63 -
man/io_uring_for_each_cqe.3.md | 68 +
man/io_uring_free_buf_ring.3 | 53 -
man/io_uring_free_buf_ring.3.md | 55 +
man/io_uring_free_probe.3 | 27 -
man/io_uring_free_probe.3.md | 36 +
man/io_uring_get_events.3 | 33 -
man/io_uring_get_events.3.md | 43 +
man/io_uring_get_probe.3 | 30 -
man/io_uring_get_probe.3.md | 43 +
man/io_uring_get_probe_ring.3 | 39 -
man/io_uring_get_probe_ring.3.md | 45 +
man/io_uring_get_sqe.3 | 57 -
man/io_uring_get_sqe.3.md | 55 +
man/io_uring_get_sqe128.3 | 67 -
man/io_uring_get_sqe128.3.md | 59 +
man/io_uring_linked_requests.7 | 271 --
man/io_uring_linked_requests.7.md | 261 ++
man/io_uring_memory_size_params.3 | 45 -
man/io_uring_memory_size_params.3.md | 51 +
man/io_uring_mlock_size.3 | 42 -
man/io_uring_mlock_size.3.md | 47 +
man/io_uring_mlock_size_params.3 | 48 -
man/io_uring_mlock_size_params.3.md | 49 +
man/io_uring_multishot.7 | 246 --
man/io_uring_multishot.7.md | 235 ++
man/io_uring_opcode_supported.3 | 30 -
man/io_uring_opcode_supported.3.md | 39 +
man/io_uring_peek_cqe.3 | 59 -
man/io_uring_peek_cqe.3.md | 55 +
man/io_uring_prep_accept.3 | 203 --
man/io_uring_prep_accept.3.md | 161 ++
man/io_uring_prep_bind.3 | 54 -
man/io_uring_prep_bind.3.md | 52 +
man/io_uring_prep_cancel.3 | 136 -
man/io_uring_prep_cancel.3.md | 138 ++
man/io_uring_prep_close.3 | 67 -
man/io_uring_prep_close.3.md | 62 +
man/io_uring_prep_cmd_discard.3 | 64 -
man/io_uring_prep_cmd_discard.3.md | 62 +
man/io_uring_prep_cmd_getsockname.3 | 79 -
man/io_uring_prep_cmd_getsockname.3.md | 64 +
man/io_uring_prep_cmd_sock.3 | 219 --
man/io_uring_prep_cmd_sock.3.md | 159 ++
man/io_uring_prep_connect.3 | 66 -
man/io_uring_prep_connect.3.md | 65 +
man/io_uring_prep_epoll_ctl.3 | 74 -
man/io_uring_prep_epoll_ctl.3.md | 68 +
man/io_uring_prep_epoll_wait.3 | 64 -
man/io_uring_prep_epoll_wait.3.md | 61 +
man/io_uring_prep_fadvise.3 | 76 -
man/io_uring_prep_fadvise.3.md | 68 +
man/io_uring_prep_fallocate.3 | 59 -
man/io_uring_prep_fallocate.3.md | 54 +
man/io_uring_prep_files_update.3 | 92 -
man/io_uring_prep_files_update.3.md | 93 +
man/io_uring_prep_fixed_fd_install.3 | 70 -
man/io_uring_prep_fixed_fd_install.3.md | 71 +
man/io_uring_prep_fsync.3 | 70 -
man/io_uring_prep_fsync.3.md | 62 +
man/io_uring_prep_ftruncate.3 | 54 -
man/io_uring_prep_ftruncate.3.md | 51 +
man/io_uring_prep_futex_wait.3 | 94 -
man/io_uring_prep_futex_wait.3.md | 79 +
man/io_uring_prep_futex_waitv.3 | 78 -
man/io_uring_prep_futex_waitv.3.md | 71 +
man/io_uring_prep_futex_wake.3 | 86 -
man/io_uring_prep_futex_wake.3.md | 71 +
man/io_uring_prep_getxattr.3 | 61 -
man/io_uring_prep_getxattr.3.md | 57 +
man/io_uring_prep_link_timeout.3 | 98 -
man/io_uring_prep_link_timeout.3.md | 104 +
man/io_uring_prep_linkat.3 | 91 -
man/io_uring_prep_linkat.3.md | 80 +
man/io_uring_prep_listen.3 | 52 -
man/io_uring_prep_listen.3.md | 53 +
man/io_uring_prep_madvise.3 | 72 -
man/io_uring_prep_madvise.3.md | 66 +
man/io_uring_prep_mkdirat.3 | 83 -
man/io_uring_prep_mkdirat.3.md | 75 +
man/io_uring_prep_msg_ring.3 | 92 -
man/io_uring_prep_msg_ring.3.md | 85 +
man/io_uring_prep_msg_ring_fd.3 | 83 -
man/io_uring_prep_msg_ring_fd.3.md | 86 +
man/io_uring_prep_nop.3 | 28 -
man/io_uring_prep_nop.3.md | 41 +
man/io_uring_prep_nop128.3 | 30 -
man/io_uring_prep_nop128.3.md | 42 +
man/io_uring_prep_openat.3 | 138 --
man/io_uring_prep_openat.3.md | 117 +
man/io_uring_prep_openat2.3 | 119 -
man/io_uring_prep_openat2.3.md | 104 +
man/io_uring_prep_pipe.3 | 91 -
man/io_uring_prep_pipe.3.md | 76 +
man/io_uring_prep_poll_add.3 | 72 -
man/io_uring_prep_poll_add.3.md | 68 +
man/io_uring_prep_poll_remove.3 | 55 -
man/io_uring_prep_poll_remove.3.md | 66 +
man/io_uring_prep_poll_update.3 | 101 -
man/io_uring_prep_poll_update.3.md | 101 +
man/io_uring_prep_provide_buffers.3 | 140 --
man/io_uring_prep_provide_buffers.3.md | 116 +
man/io_uring_prep_read.3 | 76 -
man/io_uring_prep_read.3.md | 72 +
man/io_uring_prep_read_fixed.3 | 79 -
man/io_uring_prep_read_fixed.3.md | 71 +
man/io_uring_prep_read_multishot.3 | 107 -
man/io_uring_prep_read_multishot.3.md | 92 +
man/io_uring_prep_readv.3 | 92 -
man/io_uring_prep_readv.3.md | 86 +
man/io_uring_prep_readv2.3 | 118 -
man/io_uring_prep_readv2.3.md | 110 +
man/io_uring_prep_readv_fixed.3 | 74 -
man/io_uring_prep_readv_fixed.3.md | 72 +
man/io_uring_prep_recv.3 | 147 --
man/io_uring_prep_recv.3.md | 130 +
man/io_uring_prep_recvmsg.3 | 130 -
man/io_uring_prep_recvmsg.3.md | 113 +
man/io_uring_prep_remove_buffers.3 | 52 -
man/io_uring_prep_remove_buffers.3.md | 59 +
man/io_uring_prep_renameat.3 | 95 -
man/io_uring_prep_renameat.3.md | 80 +
man/io_uring_prep_send.3 | 197 --
man/io_uring_prep_send.3.md | 154 ++
man/io_uring_prep_send_set_addr.3 | 38 -
man/io_uring_prep_send_set_addr.3.md | 42 +
man/io_uring_prep_send_zc.3 | 140 --
man/io_uring_prep_send_zc.3.md | 110 +
man/io_uring_prep_sendmsg.3 | 136 -
man/io_uring_prep_sendmsg.3.md | 111 +
man/io_uring_prep_sendmsg_zc_fixed.3 | 69 -
man/io_uring_prep_sendmsg_zc_fixed.3.md | 70 +
man/io_uring_prep_setxattr.3 | 64 -
man/io_uring_prep_setxattr.3.md | 59 +
man/io_uring_prep_shutdown.3 | 53 -
man/io_uring_prep_shutdown.3.md | 51 +
man/io_uring_prep_socket.3 | 118 -
man/io_uring_prep_socket.3.md | 94 +
man/io_uring_prep_splice.3 | 126 -
man/io_uring_prep_splice.3.md | 88 +
man/io_uring_prep_statx.3 | 74 -
man/io_uring_prep_statx.3.md | 70 +
man/io_uring_prep_symlinkat.3 | 85 -
man/io_uring_prep_symlinkat.3.md | 76 +
man/io_uring_prep_sync_file_range.3 | 59 -
man/io_uring_prep_sync_file_range.3.md | 54 +
man/io_uring_prep_tee.3 | 80 -
man/io_uring_prep_tee.3.md | 69 +
man/io_uring_prep_timeout.3 | 121 -
man/io_uring_prep_timeout.3.md | 124 +
man/io_uring_prep_timeout_update.3 | 85 -
man/io_uring_prep_timeout_update.3.md | 95 +
man/io_uring_prep_unlinkat.3 | 82 -
man/io_uring_prep_unlinkat.3.md | 75 +
man/io_uring_prep_uring_cmd.3 | 37 -
man/io_uring_prep_uring_cmd.3.md | 47 +
man/io_uring_prep_uring_cmd128.3 | 38 -
man/io_uring_prep_uring_cmd128.3.md | 48 +
man/io_uring_prep_waitid.3 | 67 -
man/io_uring_prep_waitid.3.md | 60 +
man/io_uring_prep_write.3 | 70 -
man/io_uring_prep_write.3.md | 69 +
man/io_uring_prep_write_fixed.3 | 75 -
man/io_uring_prep_write_fixed.3.md | 69 +
man/io_uring_prep_writev.3 | 89 -
man/io_uring_prep_writev.3.md | 84 +
man/io_uring_prep_writev2.3 | 115 -
man/io_uring_prep_writev2.3.md | 108 +
man/io_uring_prep_writev_fixed.3 | 71 -
man/io_uring_prep_writev_fixed.3.md | 72 +
man/io_uring_provided_buffers.7 | 266 --
man/io_uring_provided_buffers.7.md | 255 ++
man/io_uring_queue_exit.3 | 30 -
man/io_uring_queue_exit.3.md | 44 +
man/io_uring_queue_init.3 | 144 --
man/io_uring_queue_init.3.md | 109 +
man/io_uring_queue_mmap.3 | 49 -
man/io_uring_queue_mmap.3.md | 48 +
man/io_uring_recvmsg_out.3 | 82 -
man/io_uring_recvmsg_out.3.md | 82 +
man/io_uring_register.2 | 1375 ----------
man/io_uring_register.2.md | 932 +++++++
man/io_uring_register_bpf_filter.3 | 411 ---
man/io_uring_register_bpf_filter.3.md | 358 +++
man/io_uring_register_buf_ring.3 | 165 --
man/io_uring_register_buf_ring.3.md | 135 +
man/io_uring_register_buffers.3 | 105 -
man/io_uring_register_buffers.3.md | 86 +
man/io_uring_register_clock.3 | 72 -
man/io_uring_register_clock.3.md | 71 +
man/io_uring_register_eventfd.3 | 50 -
man/io_uring_register_eventfd.3.md | 62 +
man/io_uring_register_file_alloc_range.3 | 52 -
man/io_uring_register_file_alloc_range.3.md | 58 +
man/io_uring_register_files.3 | 120 -
man/io_uring_register_files.3.md | 99 +
man/io_uring_register_ifq.3 | 49 -
man/io_uring_register_ifq.3.md | 49 +
man/io_uring_register_iowq_aff.3 | 67 -
man/io_uring_register_iowq_aff.3.md | 68 +
man/io_uring_register_iowq_max_workers.3 | 71 -
man/io_uring_register_iowq_max_workers.3.md | 77 +
man/io_uring_register_napi.3 | 40 -
man/io_uring_register_napi.3.md | 43 +
man/io_uring_register_personality.3 | 34 -
man/io_uring_register_personality.3.md | 43 +
man/io_uring_register_probe.3 | 47 -
man/io_uring_register_probe.3.md | 51 +
man/io_uring_register_query.3 | 114 -
man/io_uring_register_query.3.md | 99 +
man/io_uring_register_region.3 | 124 -
man/io_uring_register_region.3.md | 101 +
man/io_uring_register_restrictions.3 | 53 -
man/io_uring_register_restrictions.3.md | 53 +
man/io_uring_register_ring_fd.3 | 51 -
man/io_uring_register_ring_fd.3.md | 61 +
man/io_uring_register_sync_cancel.3 | 73 -
man/io_uring_register_sync_cancel.3.md | 65 +
man/io_uring_register_sync_msg.3 | 74 -
man/io_uring_register_sync_msg.3.md | 71 +
man/io_uring_register_wait_reg.3 | 45 -
man/io_uring_register_wait_reg.3.md | 49 +
man/io_uring_register_zcrx_ctrl.3 | 84 -
man/io_uring_register_zcrx_ctrl.3.md | 77 +
man/io_uring_registered_buffers.7 | 238 --
man/io_uring_registered_buffers.7.md | 215 ++
man/io_uring_registered_files.7 | 228 --
man/io_uring_registered_files.7.md | 216 ++
man/io_uring_resize_rings.3 | 116 -
man/io_uring_resize_rings.3.md | 110 +
man/io_uring_ring_dontfork.3 | 36 -
man/io_uring_ring_dontfork.3.md | 43 +
man/io_uring_set_iowait.3 | 57 -
man/io_uring_set_iowait.3.md | 57 +
man/io_uring_setup.2 | 820 ------
man/io_uring_setup.2.md | 664 +++++
man/io_uring_setup_buf_ring.3 | 94 -
man/io_uring_setup_buf_ring.3.md | 85 +
man/io_uring_setup_flags.7 | 451 ----
man/io_uring_setup_flags.7.md | 373 +++
man/io_uring_sq_ready.3 | 31 -
man/io_uring_sq_ready.3.md | 42 +
man/io_uring_sq_space_left.3 | 25 -
man/io_uring_sq_space_left.3.md | 36 +
man/io_uring_sqe_set_buf_group.3 | 32 -
man/io_uring_sqe_set_buf_group.3.md | 41 +
man/io_uring_sqe_set_data.3 | 57 -
man/io_uring_sqe_set_data.3.md | 56 +
man/io_uring_sqe_set_flags.3 | 87 -
man/io_uring_sqe_set_flags.3.md | 103 +
man/io_uring_sqpoll.7 | 259 --
man/io_uring_sqpoll.7.md | 244 ++
man/io_uring_sqring_wait.3 | 34 -
man/io_uring_sqring_wait.3.md | 44 +
man/io_uring_submit.3 | 51 -
man/io_uring_submit.3.md | 59 +
man/io_uring_submit_and_get_events.3 | 31 -
man/io_uring_submit_and_get_events.3.md | 41 +
man/io_uring_submit_and_wait.3 | 44 -
man/io_uring_submit_and_wait.3.md | 50 +
man/io_uring_submit_and_wait_min_timeout.3 | 119 -
man/io_uring_submit_and_wait_min_timeout.3.md | 94 +
man/io_uring_submit_and_wait_reg.3 | 64 -
man/io_uring_submit_and_wait_reg.3.md | 62 +
man/io_uring_submit_and_wait_timeout.3 | 74 -
man/io_uring_submit_and_wait_timeout.3.md | 70 +
man/io_uring_unregister_buf_ring.3 | 30 -
man/io_uring_unregister_buf_ring.3.md | 40 +
man/io_uring_unregister_buffers.3 | 27 -
man/io_uring_unregister_buffers.3.md | 38 +
man/io_uring_unregister_files.3 | 27 -
man/io_uring_unregister_files.3.md | 37 +
man/io_uring_unregister_napi.3 | 27 -
man/io_uring_unregister_napi.3.md | 35 +
man/io_uring_unregister_personality.3 | 33 -
man/io_uring_unregister_personality.3.md | 41 +
man/io_uring_unregister_ring_fd.3 | 32 -
man/io_uring_unregister_ring_fd.3.md | 43 +
man/io_uring_wait_cqe.3 | 41 -
man/io_uring_wait_cqe.3.md | 47 +
man/io_uring_wait_cqe_nr.3 | 49 -
man/io_uring_wait_cqe_nr.3.md | 54 +
man/io_uring_wait_cqe_timeout.3 | 62 -
man/io_uring_wait_cqe_timeout.3.md | 56 +
man/io_uring_wait_cqes.3 | 82 -
man/io_uring_wait_cqes.3.md | 67 +
man/io_uring_wait_cqes_min_timeout.3 | 76 -
man/io_uring_wait_cqes_min_timeout.3.md | 68 +
330 files changed, 16747 insertions(+), 18913 deletions(-)
delete mode 100644 man/io_uring.7
create mode 100644 man/io_uring.7.md
delete mode 100644 man/io_uring_buf_ring_add.3
create mode 100644 man/io_uring_buf_ring_add.3.md
delete mode 100644 man/io_uring_buf_ring_advance.3
create mode 100644 man/io_uring_buf_ring_advance.3.md
delete mode 100644 man/io_uring_buf_ring_available.3
create mode 100644 man/io_uring_buf_ring_available.3.md
delete mode 100644 man/io_uring_buf_ring_cq_advance.3
create mode 100644 man/io_uring_buf_ring_cq_advance.3.md
delete mode 100644 man/io_uring_buf_ring_init.3
create mode 100644 man/io_uring_buf_ring_init.3.md
delete mode 100644 man/io_uring_buf_ring_mask.3
create mode 100644 man/io_uring_buf_ring_mask.3.md
delete mode 100644 man/io_uring_cancelation.7
create mode 100644 man/io_uring_cancelation.7.md
delete mode 100644 man/io_uring_check_version.3
create mode 100644 man/io_uring_check_version.3.md
delete mode 100644 man/io_uring_clone_buffers.3
create mode 100644 man/io_uring_clone_buffers.3.md
delete mode 100644 man/io_uring_close_ring_fd.3
create mode 100644 man/io_uring_close_ring_fd.3.md
delete mode 100644 man/io_uring_cq_advance.3
create mode 100644 man/io_uring_cq_advance.3.md
delete mode 100644 man/io_uring_cq_eventfd_enabled.3
create mode 100644 man/io_uring_cq_eventfd_enabled.3.md
delete mode 100644 man/io_uring_cq_eventfd_toggle.3
create mode 100644 man/io_uring_cq_eventfd_toggle.3.md
delete mode 100644 man/io_uring_cq_has_overflow.3
create mode 100644 man/io_uring_cq_has_overflow.3.md
delete mode 100644 man/io_uring_cq_ready.3
create mode 100644 man/io_uring_cq_ready.3.md
delete mode 100644 man/io_uring_cqe_get_data.3
create mode 100644 man/io_uring_cqe_get_data.3.md
delete mode 100644 man/io_uring_cqe_nr.3
create mode 100644 man/io_uring_cqe_nr.3.md
delete mode 100644 man/io_uring_cqe_seen.3
create mode 100644 man/io_uring_cqe_seen.3.md
delete mode 100644 man/io_uring_enable_rings.3
create mode 100644 man/io_uring_enable_rings.3.md
delete mode 100644 man/io_uring_enter.2
create mode 100644 man/io_uring_enter.2.md
delete mode 100644 man/io_uring_for_each_cqe.3
create mode 100644 man/io_uring_for_each_cqe.3.md
delete mode 100644 man/io_uring_free_buf_ring.3
create mode 100644 man/io_uring_free_buf_ring.3.md
delete mode 100644 man/io_uring_free_probe.3
create mode 100644 man/io_uring_free_probe.3.md
delete mode 100644 man/io_uring_get_events.3
create mode 100644 man/io_uring_get_events.3.md
delete mode 100644 man/io_uring_get_probe.3
create mode 100644 man/io_uring_get_probe.3.md
delete mode 100644 man/io_uring_get_probe_ring.3
create mode 100644 man/io_uring_get_probe_ring.3.md
delete mode 100644 man/io_uring_get_sqe.3
create mode 100644 man/io_uring_get_sqe.3.md
delete mode 100644 man/io_uring_get_sqe128.3
create mode 100644 man/io_uring_get_sqe128.3.md
delete mode 100644 man/io_uring_linked_requests.7
create mode 100644 man/io_uring_linked_requests.7.md
delete mode 100644 man/io_uring_memory_size_params.3
create mode 100644 man/io_uring_memory_size_params.3.md
delete mode 100644 man/io_uring_mlock_size.3
create mode 100644 man/io_uring_mlock_size.3.md
delete mode 100644 man/io_uring_mlock_size_params.3
create mode 100644 man/io_uring_mlock_size_params.3.md
delete mode 100644 man/io_uring_multishot.7
create mode 100644 man/io_uring_multishot.7.md
delete mode 100644 man/io_uring_opcode_supported.3
create mode 100644 man/io_uring_opcode_supported.3.md
delete mode 100644 man/io_uring_peek_cqe.3
create mode 100644 man/io_uring_peek_cqe.3.md
delete mode 100644 man/io_uring_prep_accept.3
create mode 100644 man/io_uring_prep_accept.3.md
delete mode 100644 man/io_uring_prep_bind.3
create mode 100644 man/io_uring_prep_bind.3.md
delete mode 100644 man/io_uring_prep_cancel.3
create mode 100644 man/io_uring_prep_cancel.3.md
delete mode 100644 man/io_uring_prep_close.3
create mode 100644 man/io_uring_prep_close.3.md
delete mode 100644 man/io_uring_prep_cmd_discard.3
create mode 100644 man/io_uring_prep_cmd_discard.3.md
delete mode 100644 man/io_uring_prep_cmd_getsockname.3
create mode 100644 man/io_uring_prep_cmd_getsockname.3.md
delete mode 100644 man/io_uring_prep_cmd_sock.3
create mode 100644 man/io_uring_prep_cmd_sock.3.md
delete mode 100644 man/io_uring_prep_connect.3
create mode 100644 man/io_uring_prep_connect.3.md
delete mode 100644 man/io_uring_prep_epoll_ctl.3
create mode 100644 man/io_uring_prep_epoll_ctl.3.md
delete mode 100644 man/io_uring_prep_epoll_wait.3
create mode 100644 man/io_uring_prep_epoll_wait.3.md
delete mode 100644 man/io_uring_prep_fadvise.3
create mode 100644 man/io_uring_prep_fadvise.3.md
delete mode 100644 man/io_uring_prep_fallocate.3
create mode 100644 man/io_uring_prep_fallocate.3.md
delete mode 100644 man/io_uring_prep_files_update.3
create mode 100644 man/io_uring_prep_files_update.3.md
delete mode 100644 man/io_uring_prep_fixed_fd_install.3
create mode 100644 man/io_uring_prep_fixed_fd_install.3.md
delete mode 100644 man/io_uring_prep_fsync.3
create mode 100644 man/io_uring_prep_fsync.3.md
delete mode 100644 man/io_uring_prep_ftruncate.3
create mode 100644 man/io_uring_prep_ftruncate.3.md
delete mode 100644 man/io_uring_prep_futex_wait.3
create mode 100644 man/io_uring_prep_futex_wait.3.md
delete mode 100644 man/io_uring_prep_futex_waitv.3
create mode 100644 man/io_uring_prep_futex_waitv.3.md
delete mode 100644 man/io_uring_prep_futex_wake.3
create mode 100644 man/io_uring_prep_futex_wake.3.md
delete mode 100644 man/io_uring_prep_getxattr.3
create mode 100644 man/io_uring_prep_getxattr.3.md
delete mode 100644 man/io_uring_prep_link_timeout.3
create mode 100644 man/io_uring_prep_link_timeout.3.md
delete mode 100644 man/io_uring_prep_linkat.3
create mode 100644 man/io_uring_prep_linkat.3.md
delete mode 100644 man/io_uring_prep_listen.3
create mode 100644 man/io_uring_prep_listen.3.md
delete mode 100644 man/io_uring_prep_madvise.3
create mode 100644 man/io_uring_prep_madvise.3.md
delete mode 100644 man/io_uring_prep_mkdirat.3
create mode 100644 man/io_uring_prep_mkdirat.3.md
delete mode 100644 man/io_uring_prep_msg_ring.3
create mode 100644 man/io_uring_prep_msg_ring.3.md
delete mode 100644 man/io_uring_prep_msg_ring_fd.3
create mode 100644 man/io_uring_prep_msg_ring_fd.3.md
delete mode 100644 man/io_uring_prep_nop.3
create mode 100644 man/io_uring_prep_nop.3.md
delete mode 100644 man/io_uring_prep_nop128.3
create mode 100644 man/io_uring_prep_nop128.3.md
delete mode 100644 man/io_uring_prep_openat.3
create mode 100644 man/io_uring_prep_openat.3.md
delete mode 100644 man/io_uring_prep_openat2.3
create mode 100644 man/io_uring_prep_openat2.3.md
delete mode 100644 man/io_uring_prep_pipe.3
create mode 100644 man/io_uring_prep_pipe.3.md
delete mode 100644 man/io_uring_prep_poll_add.3
create mode 100644 man/io_uring_prep_poll_add.3.md
delete mode 100644 man/io_uring_prep_poll_remove.3
create mode 100644 man/io_uring_prep_poll_remove.3.md
delete mode 100644 man/io_uring_prep_poll_update.3
create mode 100644 man/io_uring_prep_poll_update.3.md
delete mode 100644 man/io_uring_prep_provide_buffers.3
create mode 100644 man/io_uring_prep_provide_buffers.3.md
delete mode 100644 man/io_uring_prep_read.3
create mode 100644 man/io_uring_prep_read.3.md
delete mode 100644 man/io_uring_prep_read_fixed.3
create mode 100644 man/io_uring_prep_read_fixed.3.md
delete mode 100644 man/io_uring_prep_read_multishot.3
create mode 100644 man/io_uring_prep_read_multishot.3.md
delete mode 100644 man/io_uring_prep_readv.3
create mode 100644 man/io_uring_prep_readv.3.md
delete mode 100644 man/io_uring_prep_readv2.3
create mode 100644 man/io_uring_prep_readv2.3.md
delete mode 100644 man/io_uring_prep_readv_fixed.3
create mode 100644 man/io_uring_prep_readv_fixed.3.md
delete mode 100644 man/io_uring_prep_recv.3
create mode 100644 man/io_uring_prep_recv.3.md
delete mode 100644 man/io_uring_prep_recvmsg.3
create mode 100644 man/io_uring_prep_recvmsg.3.md
delete mode 100644 man/io_uring_prep_remove_buffers.3
create mode 100644 man/io_uring_prep_remove_buffers.3.md
delete mode 100644 man/io_uring_prep_renameat.3
create mode 100644 man/io_uring_prep_renameat.3.md
delete mode 100644 man/io_uring_prep_send.3
create mode 100644 man/io_uring_prep_send.3.md
delete mode 100644 man/io_uring_prep_send_set_addr.3
create mode 100644 man/io_uring_prep_send_set_addr.3.md
delete mode 100644 man/io_uring_prep_send_zc.3
create mode 100644 man/io_uring_prep_send_zc.3.md
delete mode 100644 man/io_uring_prep_sendmsg.3
create mode 100644 man/io_uring_prep_sendmsg.3.md
delete mode 100644 man/io_uring_prep_sendmsg_zc_fixed.3
create mode 100644 man/io_uring_prep_sendmsg_zc_fixed.3.md
delete mode 100644 man/io_uring_prep_setxattr.3
create mode 100644 man/io_uring_prep_setxattr.3.md
delete mode 100644 man/io_uring_prep_shutdown.3
create mode 100644 man/io_uring_prep_shutdown.3.md
delete mode 100644 man/io_uring_prep_socket.3
create mode 100644 man/io_uring_prep_socket.3.md
delete mode 100644 man/io_uring_prep_splice.3
create mode 100644 man/io_uring_prep_splice.3.md
delete mode 100644 man/io_uring_prep_statx.3
create mode 100644 man/io_uring_prep_statx.3.md
delete mode 100644 man/io_uring_prep_symlinkat.3
create mode 100644 man/io_uring_prep_symlinkat.3.md
delete mode 100644 man/io_uring_prep_sync_file_range.3
create mode 100644 man/io_uring_prep_sync_file_range.3.md
delete mode 100644 man/io_uring_prep_tee.3
create mode 100644 man/io_uring_prep_tee.3.md
delete mode 100644 man/io_uring_prep_timeout.3
create mode 100644 man/io_uring_prep_timeout.3.md
delete mode 100644 man/io_uring_prep_timeout_update.3
create mode 100644 man/io_uring_prep_timeout_update.3.md
delete mode 100644 man/io_uring_prep_unlinkat.3
create mode 100644 man/io_uring_prep_unlinkat.3.md
delete mode 100644 man/io_uring_prep_uring_cmd.3
create mode 100644 man/io_uring_prep_uring_cmd.3.md
delete mode 100644 man/io_uring_prep_uring_cmd128.3
create mode 100644 man/io_uring_prep_uring_cmd128.3.md
delete mode 100644 man/io_uring_prep_waitid.3
create mode 100644 man/io_uring_prep_waitid.3.md
delete mode 100644 man/io_uring_prep_write.3
create mode 100644 man/io_uring_prep_write.3.md
delete mode 100644 man/io_uring_prep_write_fixed.3
create mode 100644 man/io_uring_prep_write_fixed.3.md
delete mode 100644 man/io_uring_prep_writev.3
create mode 100644 man/io_uring_prep_writev.3.md
delete mode 100644 man/io_uring_prep_writev2.3
create mode 100644 man/io_uring_prep_writev2.3.md
delete mode 100644 man/io_uring_prep_writev_fixed.3
create mode 100644 man/io_uring_prep_writev_fixed.3.md
delete mode 100644 man/io_uring_provided_buffers.7
create mode 100644 man/io_uring_provided_buffers.7.md
delete mode 100644 man/io_uring_queue_exit.3
create mode 100644 man/io_uring_queue_exit.3.md
delete mode 100644 man/io_uring_queue_init.3
create mode 100644 man/io_uring_queue_init.3.md
delete mode 100644 man/io_uring_queue_mmap.3
create mode 100644 man/io_uring_queue_mmap.3.md
delete mode 100644 man/io_uring_recvmsg_out.3
create mode 100644 man/io_uring_recvmsg_out.3.md
delete mode 100644 man/io_uring_register.2
create mode 100644 man/io_uring_register.2.md
delete mode 100644 man/io_uring_register_bpf_filter.3
create mode 100644 man/io_uring_register_bpf_filter.3.md
delete mode 100644 man/io_uring_register_buf_ring.3
create mode 100644 man/io_uring_register_buf_ring.3.md
delete mode 100644 man/io_uring_register_buffers.3
create mode 100644 man/io_uring_register_buffers.3.md
delete mode 100644 man/io_uring_register_clock.3
create mode 100644 man/io_uring_register_clock.3.md
delete mode 100644 man/io_uring_register_eventfd.3
create mode 100644 man/io_uring_register_eventfd.3.md
delete mode 100644 man/io_uring_register_file_alloc_range.3
create mode 100644 man/io_uring_register_file_alloc_range.3.md
delete mode 100644 man/io_uring_register_files.3
create mode 100644 man/io_uring_register_files.3.md
delete mode 100644 man/io_uring_register_ifq.3
create mode 100644 man/io_uring_register_ifq.3.md
delete mode 100644 man/io_uring_register_iowq_aff.3
create mode 100644 man/io_uring_register_iowq_aff.3.md
delete mode 100644 man/io_uring_register_iowq_max_workers.3
create mode 100644 man/io_uring_register_iowq_max_workers.3.md
delete mode 100644 man/io_uring_register_napi.3
create mode 100644 man/io_uring_register_napi.3.md
delete mode 100644 man/io_uring_register_personality.3
create mode 100644 man/io_uring_register_personality.3.md
delete mode 100644 man/io_uring_register_probe.3
create mode 100644 man/io_uring_register_probe.3.md
delete mode 100644 man/io_uring_register_query.3
create mode 100644 man/io_uring_register_query.3.md
delete mode 100644 man/io_uring_register_region.3
create mode 100644 man/io_uring_register_region.3.md
delete mode 100644 man/io_uring_register_restrictions.3
create mode 100644 man/io_uring_register_restrictions.3.md
delete mode 100644 man/io_uring_register_ring_fd.3
create mode 100644 man/io_uring_register_ring_fd.3.md
delete mode 100644 man/io_uring_register_sync_cancel.3
create mode 100644 man/io_uring_register_sync_cancel.3.md
delete mode 100644 man/io_uring_register_sync_msg.3
create mode 100644 man/io_uring_register_sync_msg.3.md
delete mode 100644 man/io_uring_register_wait_reg.3
create mode 100644 man/io_uring_register_wait_reg.3.md
delete mode 100644 man/io_uring_register_zcrx_ctrl.3
create mode 100644 man/io_uring_register_zcrx_ctrl.3.md
delete mode 100644 man/io_uring_registered_buffers.7
create mode 100644 man/io_uring_registered_buffers.7.md
delete mode 100644 man/io_uring_registered_files.7
create mode 100644 man/io_uring_registered_files.7.md
delete mode 100644 man/io_uring_resize_rings.3
create mode 100644 man/io_uring_resize_rings.3.md
delete mode 100644 man/io_uring_ring_dontfork.3
create mode 100644 man/io_uring_ring_dontfork.3.md
delete mode 100644 man/io_uring_set_iowait.3
create mode 100644 man/io_uring_set_iowait.3.md
delete mode 100644 man/io_uring_setup.2
create mode 100644 man/io_uring_setup.2.md
delete mode 100644 man/io_uring_setup_buf_ring.3
create mode 100644 man/io_uring_setup_buf_ring.3.md
delete mode 100644 man/io_uring_setup_flags.7
create mode 100644 man/io_uring_setup_flags.7.md
delete mode 100644 man/io_uring_sq_ready.3
create mode 100644 man/io_uring_sq_ready.3.md
delete mode 100644 man/io_uring_sq_space_left.3
create mode 100644 man/io_uring_sq_space_left.3.md
delete mode 100644 man/io_uring_sqe_set_buf_group.3
create mode 100644 man/io_uring_sqe_set_buf_group.3.md
delete mode 100644 man/io_uring_sqe_set_data.3
create mode 100644 man/io_uring_sqe_set_data.3.md
delete mode 100644 man/io_uring_sqe_set_flags.3
create mode 100644 man/io_uring_sqe_set_flags.3.md
delete mode 100644 man/io_uring_sqpoll.7
create mode 100644 man/io_uring_sqpoll.7.md
delete mode 100644 man/io_uring_sqring_wait.3
create mode 100644 man/io_uring_sqring_wait.3.md
delete mode 100644 man/io_uring_submit.3
create mode 100644 man/io_uring_submit.3.md
delete mode 100644 man/io_uring_submit_and_get_events.3
create mode 100644 man/io_uring_submit_and_get_events.3.md
delete mode 100644 man/io_uring_submit_and_wait.3
create mode 100644 man/io_uring_submit_and_wait.3.md
delete mode 100644 man/io_uring_submit_and_wait_min_timeout.3
create mode 100644 man/io_uring_submit_and_wait_min_timeout.3.md
delete mode 100644 man/io_uring_submit_and_wait_reg.3
create mode 100644 man/io_uring_submit_and_wait_reg.3.md
delete mode 100644 man/io_uring_submit_and_wait_timeout.3
create mode 100644 man/io_uring_submit_and_wait_timeout.3.md
delete mode 100644 man/io_uring_unregister_buf_ring.3
create mode 100644 man/io_uring_unregister_buf_ring.3.md
delete mode 100644 man/io_uring_unregister_buffers.3
create mode 100644 man/io_uring_unregister_buffers.3.md
delete mode 100644 man/io_uring_unregister_files.3
create mode 100644 man/io_uring_unregister_files.3.md
delete mode 100644 man/io_uring_unregister_napi.3
create mode 100644 man/io_uring_unregister_napi.3.md
delete mode 100644 man/io_uring_unregister_personality.3
create mode 100644 man/io_uring_unregister_personality.3.md
delete mode 100644 man/io_uring_unregister_ring_fd.3
create mode 100644 man/io_uring_unregister_ring_fd.3.md
delete mode 100644 man/io_uring_wait_cqe.3
create mode 100644 man/io_uring_wait_cqe.3.md
delete mode 100644 man/io_uring_wait_cqe_nr.3
create mode 100644 man/io_uring_wait_cqe_nr.3.md
delete mode 100644 man/io_uring_wait_cqe_timeout.3
create mode 100644 man/io_uring_wait_cqe_timeout.3.md
delete mode 100644 man/io_uring_wait_cqes.3
create mode 100644 man/io_uring_wait_cqes.3.md
delete mode 100644 man/io_uring_wait_cqes_min_timeout.3
create mode 100644 man/io_uring_wait_cqes_min_timeout.3.md
diff --git a/man/io_uring.7 b/man/io_uring.7
deleted file mode 100644
index 723d7d0f..00000000
--- a/man/io_uring.7
+++ /dev/null
@@ -1,919 +0,0 @@
-.\" Copyright (C) 2020 Shuveb Hussain <shuveb@gmail.com>
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-
-.TH io_uring 7 "July 26, 2020" "Linux" "Linux Programmer's Manual"
-.SH NAME
-io_uring \- Asynchronous I/O facility
-.SH SYNOPSIS
-.nf
-.B "#include <linux/io_uring.h>"
-.fi
-.PP
-.SH DESCRIPTION
-.PP
-.B io_uring
-is a Linux-specific API for asynchronous I/O.
-It allows the user to submit one or more I/O requests,
-which are processed asynchronously without blocking the calling process.
-.B io_uring
-gets its name from ring buffers which are shared between user space and
-kernel space. This arrangement allows for efficient I/O,
-while avoiding the overhead of copying buffers between them,
-where possible.
-This interface makes
-.B io_uring
-different from other UNIX I/O APIs,
-wherein,
-rather than just communicate between kernel and user space with system calls,
-ring buffers are used as the main mode of communication.
-This arrangement has various performance benefits which are discussed in a
-separate section below.
-This man page uses the terms shared buffers, shared ring buffers and
-queues interchangeably.
-.PP
-The general programming model you need to follow for
-.B io_uring
-is outlined below
-.IP \(bu
-Set up shared buffers with
-.BR io_uring_setup (2)
-and
-.BR mmap (2),
-mapping into user space shared buffers for the submission queue (SQ) and the
-completion queue (CQ).
-You place I/O requests you want to make on the SQ,
-while the kernel places the results of those operations on the CQ.
-.IP \(bu
-For every I/O request you need to make (like to read a file, write a file,
-accept a socket connection, etc), you create a submission queue entry,
-or SQE,
-describe the I/O operation you need to get done and add it to the tail of
-the submission queue (SQ).
-Each I/O operation is,
-in essence,
-the equivalent of a system call you would have made otherwise,
-if you were not using
-.BR io_uring .
-For instance,
-a SQE with the
-.I opcode
-set to
-.B IORING_OP_READ
-will request a read operation to be issued that is similar to the
-.BR read (2)
-system call. Refer to the opcode documentation in
-.BR io_uring_enter (2)
-for all supported opcodes and their properties.
-You can add more than one SQE to the queue depending on the number of
-operations you want to request.
-.IP \(bu
-After you add one or more SQEs,
-you need to call
-.BR io_uring_enter (2)
-to tell the kernel to dequeue your I/O requests off the SQ and begin
-processing them.
-.IP \(bu
-For each SQE you submit,
-once it is done processing the request,
-the kernel places a completion queue event or CQE at the tail of the
-completion queue or CQ.
-The kernel places exactly one matching CQE in the CQ for every SQE you
-submit on the SQ.
-After you retrieve a CQE,
-minimally,
-you might be interested in checking the
-.I res
-field of the CQE structure,
-which corresponds to the return value of the system
-call's equivalent,
-had you used it directly without using
-.BR io_uring .
-Given that
-.B io_uring
-is an async interface,
-.I errno
-is never used for passing back error information. Instead,
-.I res
-will contain what the equivalent system call would have returned in case
-of success, and in case of error
-.I res
-will contain
-.IR -errno .
-For example, if the normal read system call would have returned -1 and set
-.I errno
-to
-.BR EINVAL ,
-then
-.I res
-would contain
-.BR -EINVAL .
-If the normal system call would have returned a read size of 1024, then
-.I res
-would contain 1024.
-.IP \(bu
-Optionally,
-.BR io_uring_enter (2)
-can also wait for a specified number of requests to be processed by the kernel
-before it returns.
-If you specified a certain number of completions to wait for,
-the kernel would have placed at least those many number of CQEs on the CQ,
-which you can then readily read,
-right after the return from
-.BR io_uring_enter (2).
-.IP \(bu
-It is important to remember that I/O requests submitted to the kernel can
-complete in any order.
-It is not necessary for the kernel to process one request after another,
-in the order you placed them.
-Given that the interface is a ring,
-the requests are attempted in order,
-however that doesn't imply any sort of ordering on their execution or
-completion.
-When more than one request is in flight,
-it is not possible to determine which one will execute or complete first.
-When you dequeue CQEs off the CQ,
-you should always check which submitted request it corresponds to.
-The most common method for doing so is utilizing the
-.I user_data
-field in the request, which is passed back on the completion side.
-.IP \(bu
-Concretely, for operations where strict ordering is required,
-such as for sends and receives on a stream-oriented TCP socket,
-it is generally unsafe to have more than one outstanding send,
-or more than one outstanding receive (the two directions are independent)
-on a given socket at a time, as the kernel may reorder their execution
-if poll arming or other background kernel activities are involved.
-However,
-.B io_uring
-provides various facilities to enable applications to efficiently
-pipeline their operations safely. If the requests are submitted in a
-single batch, the application may use
-.B IOSQE_IO_LINK
-to enforce an execution order in the kernel. Otherwise,
-.B io_uring
-provides advanced features like
-.I multi shot
-and send/receive
-.I bundles
-to allow applications to provide more data in fewer, more efficient trips
-to the kernel. Even if these features are used, applications must still
-ensure they do not overlap different sends or different receives on a
-given file.
-.PP
-Adding to and reading from the queues:
-.IP \(bu
-You add SQEs to the tail of the SQ.
-The kernel reads SQEs off the head of the queue.
-.IP \(bu
-The kernel adds CQEs to the tail of the CQ.
-You read CQEs off the head of the queue.
-.PP
-It should be noted that depending on the configuration io_uring's behavior
-can deviate from the behavior outlined above, like not posting a CQE for
-every SQE when setting
-.B IOSQE_CQE_SKIP_SUCCESS
-in the SQE or posting multiple CQEs for a single SQE for multi shot operations
-or requiring an
-.BR io_uring_enter (2)
-syscall to make the kernel begin processing newly added SQEs when using
-submission queue polling.
-
-.SS Submission queue polling
-One of the goals of
-.B io_uring
-is to provide a means for efficient I/O.
-To this end,
-.B io_uring
-supports a polling mode that lets you avoid the call to
-.BR io_uring_enter (2),
-which you use to inform the kernel that you have queued SQEs on to the SQ.
-With SQ Polling,
-.B io_uring
-starts a kernel thread that polls the submission queue for any I/O
-requests you submit by adding SQEs.
-With SQ Polling enabled,
-there is no need for you to call
-.BR io_uring_enter (2),
-letting you avoid the overhead of system calls.
-A designated kernel thread dequeues SQEs off the SQ as you add them and
-dispatches them for asynchronous processing.
-.SS Setting up io_uring
-.PP
-The main steps in setting up
-.B io_uring
-consist of mapping in the shared buffers with
-.BR mmap (2)
-calls.
-In the example program included in this man page,
-the function
-.BR app_setup_uring ()
-sets up
-.B io_uring
-with a QUEUE_DEPTH deep submission queue.
-Pay attention to the 2
-.BR mmap (2)
-calls that set up the shared submission and completion queues.
-If your kernel is older than version 5.4,
-three
-.BR mmap(2)
-calls are required.
-.PP
-.SS Submitting I/O requests
-The process of submitting a request consists of describing the I/O
-operation you need to get done using an
-.B io_uring_sqe
-structure instance.
-These details describe the equivalent system call and its parameters.
-Because the range of I/O operations Linux supports are very varied and the
-.B io_uring_sqe
-structure needs to be able to describe them,
-it has several fields,
-some packed into unions for space efficiency.
-Here is a simplified version of struct
-.B io_uring_sqe
-with some of the most often used fields:
-.PP
-.in +4n
-.EX
-struct io_uring_sqe {
- __u8 opcode; /* type of operation for this sqe */
- __s32 fd; /* file descriptor to do IO on */
- __u64 off; /* offset into file */
- __u64 addr; /* pointer to buffer or iovecs */
- __u32 len; /* buffer size or number of iovecs */
- __u64 user_data; /* data to be passed back at completion time */
- __u8 flags; /* IOSQE_ flags */
- ...
-};
-.EE
-.in
-
-Here is struct
-.B io_uring_sqe
-in full:
-
-.in +4n
-.EX
-struct io_uring_sqe {
- __u8 opcode; /* type of operation for this sqe */
- __u8 flags; /* IOSQE_ flags */
- __u16 ioprio; /* ioprio for the request */
- __s32 fd; /* file descriptor to do IO on */
- union {
- __u64 off; /* offset into file */
- __u64 addr2;
- struct {
- __u32 cmd_op;
- __u32 __pad1;
- };
- };
- union {
- __u64 addr; /* pointer to buffer or iovecs */
- __u64 splice_off_in;
- struct {
- __u32 level;
- __u32 optname;
- };
- };
- __u32 len; /* buffer size or number of iovecs */
- union {
- __kernel_rwf_t rw_flags;
- __u32 fsync_flags;
- __u16 poll_events; /* compatibility */
- __u32 poll32_events; /* word-reversed for BE */
- __u32 sync_range_flags;
- __u32 msg_flags;
- __u32 timeout_flags;
- __u32 accept_flags;
- __u32 cancel_flags;
- __u32 open_flags;
- __u32 statx_flags;
- __u32 fadvise_advice;
- __u32 splice_flags;
- __u32 rename_flags;
- __u32 unlink_flags;
- __u32 hardlink_flags;
- __u32 xattr_flags;
- __u32 msg_ring_flags;
- __u32 uring_cmd_flags;
- __u32 waitid_flags;
- __u32 futex_flags;
- __u32 install_fd_flags;
- __u32 nop_flags;
- };
- __u64 user_data; /* data to be passed back at completion time */
- /* pack this to avoid bogus arm OABI complaints */
- union {
- /* index into fixed buffers, if used */
- __u16 buf_index;
- /* for grouped buffer selection */
- __u16 buf_group;
- } __attribute__((packed));
- /* personality to use, if used */
- __u16 personality;
- union {
- __s32 splice_fd_in;
- __u32 file_index;
- __u32 optlen;
- struct {
- __u16 addr_len;
- __u16 __pad3[1];
- };
- };
- union {
- struct {
- __u64 addr3;
- __u64 __pad2[1];
- };
- __u64 optval;
- /*
- * If the ring is initialized with IORING_SETUP_SQE128, then
- * this field is used for 80 bytes of arbitrary command data
- */
- __u8 cmd[0];
- };
-};
-.EE
-.in
-.PP
-To submit an I/O request to
-.BR io_uring ,
-you need to acquire a submission queue entry (SQE) from the submission
-queue (SQ),
-fill it up with details of the operation you want to submit and call
-.BR io_uring_enter (2).
-There are helper functions of the form io_uring_prep_X to enable proper
-setup of the SQE. If you want to avoid calling
-.BR io_uring_enter (2),
-you have the option of setting up Submission Queue Polling.
-.PP
-SQEs are added to the tail of the submission queue.
-The kernel picks up SQEs off the head of the SQ.
-The general algorithm to get the next available SQE and update the tail is
-as follows.
-.PP
-.in +4n
-.EX
-struct io_uring_sqe *sqe;
-unsigned tail, index;
-tail = *sqring->tail;
-index = tail & (*sqring->ring_mask);
-sqe = &sqring->sqes[index];
-/* fill up details about this I/O request */
-describe_io(sqe);
-/* fill the sqe index into the SQ ring array */
-sqring->array[index] = index;
-tail++;
-atomic_store_explicit(sqring->tail, tail, memory_order_release);
-.EE
-.in
-.PP
-To get the index of an entry,
-the application must mask the current tail index with the size mask of the
-ring.
-This holds true for both SQs and CQs.
-Once the SQE is acquired,
-the necessary fields are filled in,
-describing the request.
-While the CQ ring directly indexes the shared array of CQEs,
-the submission side has an indirection array between them.
-The submission side ring buffer is an index into this array,
-which in turn contains the index into the SQEs.
-.PP
-The following code snippet demonstrates how a read operation,
-an equivalent of a
-.BR preadv2 (2)
-system call is described by filling up an SQE with the necessary
-parameters.
-.PP
-.in +4n
-.EX
-struct iovec iovecs[16];
- ...
-sqe->opcode = IORING_OP_READV;
-sqe->fd = fd;
-sqe->addr = (unsigned long) iovecs;
-sqe->len = 16;
-sqe->off = offset;
-sqe->flags = 0;
-.EE
-.in
-.TP
-.B Memory ordering
-Modern compilers and CPUs freely reorder reads and writes without
-affecting the program's outcome to optimize performance.
-Some aspects of this need to be kept in mind on SMP systems since
-.B io_uring
-involves buffers shared between kernel and user space.
-These buffers are both visible and modifiable from kernel and user space.
-As heads and tails belonging to these shared buffers are updated by kernel
-and user space,
-changes need to be coherently visible on either side,
-irrespective of whether a CPU switch took place after the kernel-user mode
-switch happened.
-We use memory barriers to enforce this coherency.
-Being significantly large subjects on their own,
-memory barriers are out of scope for further discussion on this man page.
-For more information on modern memory models the reader may refer to the
-Documentation/memory-barriers.txt in the kernel tree or to the documentation
-of the formal C11 or kernel memory model.
-.TP
-.B Letting the kernel know about I/O submissions
-Once you place one or more SQEs on to the SQ,
-you need to let the kernel know that you've done so.
-You can do this by calling the
-.BR io_uring_enter (2)
-system call.
-This system call is also capable of waiting for a specified count of
-events to complete.
-This way,
-you can be sure to find completion events in the completion queue without
-having to poll it for events later.
-.SS SQE pointer lifetimes & data stability
-Due to the fixed size of the submission queue entry (SQE) some data you
-provide in order to perform a desired operation will be passed in the
-form of a pointer rather than value. In this situation, you may free
-the memory backing the pointer once the succeeding
-.BR io_uring_enter (2)
-call has completed; providing it is only required by the operation when submitting.
-
-When
-.B IORING_SETUP_SQPOLL
-is not enabled, this is done when you call
-.BR io_uring_submit (3)
-In The event
-.B IORING_SETUP_SQPOLL
-is enabled, you must ensure any provided pointers remain valid until completion.
-
-However, very early kernels (5.4 and earlier) required state to be
- stable until the completion occurred regardless. Applications can test for this
- behavior by inspecting the
-.B IORING_FEAT_SUBMIT_STABLE
-flag passed back from
-.BR io_uring_queue_init_params (3).
-
-As an example, the
-.B IORING_OP_TIMEOUT
-operation takes a pointer to a __kernel_timespec struct. This struct is
-then read by the kernel when you submit the submission queue entries,
-once submitted, you may free the backing memory of the __kernel_timespec
-as it will not be read again by the kernel.
-
-It should be noted that this behaviour does not apply to data that is read
-or written while the operation is inflight. For example, the pointers to
-a buffer used as part of a
-.B IORING_OP_WRITE
-or
-.B IORING_OP_READ
-operation must remain valid until completion.
-.SS Reading completion events
-Similar to the submission queue (SQ),
-the completion queue (CQ) is a shared buffer between the kernel and user
-space.
-Whereas you placed submission queue entries on the tail of the SQ and the
-kernel read off the head,
-when it comes to the CQ,
-the kernel places completion queue events or CQEs on the tail of the CQ and
-you read off its head.
-.PP
-Submission is flexible (and thus a bit more complicated) since it needs to
-be able to encode different types of system calls that take various
-parameters.
-Completion,
-on the other hand is simpler since we're looking only for a return value
-back from the kernel.
-This is easily understood by looking at the completion queue event
-structure,
-struct
-.BR io_uring_cqe :
-.PP
-.in +4n
-.EX
-struct io_uring_cqe {
- __u64 user_data; /* sqe->data submission passed back */
- __s32 res; /* result code for this event */
- __u32 flags;
-};
-.EE
-.in
-.PP
-Here,
-.I user_data
-is custom data that is passed unchanged from submission to completion.
-That is,
-from SQEs to CQEs.
-This field can be used to set context,
-uniquely identifying submissions that got completed.
-Given that I/O requests can complete in any order,
-this field can be used to correlate a submission with a completion.
-.I res
-is the result from the system call that was performed as part of the
-submission;
-its return value.
-
-The
-.I flags
-field carries request-specific information. As of the 6.12 kernel,
-the following flags are defined:
-
-.TP
-.B IORING_CQE_F_BUFFER
-If set, the upper 16 bits of the flags field carries the buffer ID that was
-chosen for this request. The request must have been issued with
-.B IOSQE_BUFFER_SELECT
-set, and used with a request type that supports buffer selection. Additionally,
-buffers must have been provided upfront either via the
-.B IORING_OP_PROVIDE_BUFFERS
-or the
-.B IORING_REGISTER_PBUF_RING
-methods.
-.TP
-.B IORING_CQE_F_MORE
-If set, the application should expect more completions from the request. This
-is used for requests that can generate multiple completions, such as multi-shot
-requests, receive, or accept.
-.TP
-.B IORING_CQE_F_SOCK_NONEMPTY
-If set, upon receiving the data from the socket in the current request, the
-socket still had data left on completion of this request.
-.TP
-.B IORING_CQE_F_NOTIF
-Set for notification CQEs, as seen with the zero-copy networking send and
-receive support.
-.TP
-.B IORING_CQE_F_BUF_MORE
-If set, the buffer ID set in the completion will get more completions. This
-means that the provided buffer has been partially consumed and there's more
-buffer space left, and hence the application should expect more completions
-with this buffer ID. Each completion will continue where the previous one
-left off. This can only happen if the provided buffer ring has been setup
-with
-.B IOU_PBUF_RING_INC
-to allow for incremental / partial consumption of buffers.
-.TP
-.B IORING_CQE_F_SKIP
-If the ring has been configured with
-.B IORING_SETUP_CQE_MIXED ,
-then CQEs may be posted which has this flag set. This can happen if the ring
-is a single 16b CQE entry away from wrapping, but someone needs to post a 32b
-CQE. As CQEs must be contiguous in memory, a filler/pad CQE needs to get
-posted to allow posting of the 32b CQE. CQEs with this flag set should simply
-be skipped and ignored, they serve no other purpose than to fill a gap in the
-CQ ring.
-.TP
-.B IORING_CQE_F_32
-If the ring has been configured with
-.B IORING_SETUP_CQE_MIXED ,
-this flag is set when the CQE is of the 32b type. This tells the application
-that there's an extra 16b of space in this CQE, and that to get to the next
-CQE the CQ ring must be advanced by twice as much as for a normal 16b CQE.
-.PP
-The general sequence to read completion events off the completion queue is
-as follows:
-.PP
-.in +4n
-.EX
-unsigned head;
-head = *cqring->head;
-if (head != atomic_load_acquire(cqring->tail)) {
- struct io_uring_cqe *cqe;
- unsigned index;
- index = head & (cqring->mask);
- cqe = &cqring->cqes[index];
- /* process completed CQE */
- process_cqe(cqe);
- /* CQE consumption complete */
- head++;
-}
-atomic_store_explicit(cqring->head, head, memory_order_release);
-.EE
-.in
-.PP
-It helps to be reminded that the kernel adds CQEs to the tail of the CQ,
-while you need to dequeue them off the head.
-To get the index of an entry at the head,
-the application must mask the current head index with the size mask of the
-ring.
-Once the CQE has been consumed or processed,
-the head needs to be updated to reflect the consumption of the CQE.
-Attention should be paid to the read and write barriers to ensure
-successful read and update of the head.
-.SS io_uring performance
-Because of the shared ring buffers between kernel and user space,
-.B io_uring
-can be a zero-copy system.
-Copying buffers to and from becomes necessary when system calls that
-transfer data between kernel and user space are involved.
-But since the bulk of the communication in
-.B io_uring
-is via buffers shared between the kernel and user space,
-this huge performance overhead is completely avoided.
-.PP
-While system calls may not seem like a significant overhead,
-in high performance applications,
-making a lot of them will begin to matter.
-While workarounds the operating system has in place to deal with Spectre
-and Meltdown are ideally best done away with,
-unfortunately,
-some of these workarounds are around the system call interface,
-making system calls not as cheap as before on affected hardware.
-While newer hardware should not need these workarounds,
-hardware with these vulnerabilities can be expected to be in the wild for a
-long time.
-While using synchronous programming interfaces or even when using
-asynchronous programming interfaces under Linux,
-there is at least one system call involved in the submission of each
-request.
-In
-.BR io_uring ,
-on the other hand,
-you can batch several requests in one go,
-simply by queueing up multiple SQEs,
-each describing an I/O operation you want and make a single call to
-.BR io_uring_enter (2).
-This is possible due to
-.BR io_uring 's
-shared buffers based design.
-.PP
-While this batching in itself can avoid the overhead associated with
-potentially multiple and frequent system calls,
-you can reduce even this overhead further with Submission Queue Polling,
-by having the kernel poll and pick up your SQEs for processing as you add
-them to the submission queue. This avoids the
-.BR io_uring_enter (2)
-call you need to make to tell the kernel to pick SQEs up.
-For high-performance applications,
-this means even fewer system call overheads.
-.SH CONFORMING TO
-.B io_uring
-is Linux-specific.
-.SH EXAMPLES
-The following example uses
-.B io_uring
-to copy stdin to stdout.
-Using shell redirection,
-you should be able to copy files with this example.
-Because it uses a queue depth of only one,
-this example processes I/O requests one after the other.
-It is purposefully kept this way to aid understanding.
-In real-world scenarios however,
-you'll want to have a larger queue depth to parallelize I/O request
-processing so as to gain the kind of performance benefits
-.B io_uring
-provides with its asynchronous processing of requests.
-.PP
-.EX
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <sys/syscall.h>
-#include <sys/mman.h>
-#include <sys/uio.h>
-#include <linux/fs.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdatomic.h>
-#include <errno.h>
-
-#include <linux/io_uring.h>
-
-#define QUEUE_DEPTH 1
-#define BLOCK_SZ 1024
-
-/* Macros for barriers needed by io_uring */
-#define io_uring_smp_store_release(p, v) \\
- atomic_store_explicit((_Atomic typeof(*(p)) *)(p), (v), \\
- memory_order_release)
-#define io_uring_smp_load_acquire(p) \\
- atomic_load_explicit((_Atomic typeof(*(p)) *)(p), \\
- memory_order_acquire)
-
-int ring_fd;
-unsigned *sring_tail, *sring_mask, *sring_array,
- *cring_head, *cring_tail, *cring_mask;
-struct io_uring_sqe *sqes;
-struct io_uring_cqe *cqes;
-char buff[BLOCK_SZ];
-off_t offset;
-
-/*
- * System call wrappers provided since glibc does not yet
- * provide wrappers for io_uring system calls.
-* */
-
-int io_uring_setup(unsigned entries, struct io_uring_params *p)
-{
- int ret;
- ret = syscall(__NR_io_uring_setup, entries, p);
- return (ret < 0) ? -errno : ret;
-}
-
-int io_uring_enter(int ring_fd, unsigned int to_submit,
- unsigned int min_complete, unsigned int flags)
-{
- int ret;
- ret = syscall(__NR_io_uring_enter, ring_fd, to_submit,
- min_complete, flags, NULL, 0);
- return (ret < 0) ? -errno : ret;
-}
-
-int app_setup_uring(void) {
- struct io_uring_params p;
- void *sq_ptr, *cq_ptr;
-
- /* See io_uring_setup(2) for io_uring_params.flags you can set */
- memset(&p, 0, sizeof(p));
- ring_fd = io_uring_setup(QUEUE_DEPTH, &p);
- if (ring_fd < 0) {
- perror("io_uring_setup");
- return 1;
- }
-
- /*
- * io_uring communication happens via 2 shared kernel-user space ring
- * buffers, which can be jointly mapped with a single mmap() call in
- * kernels >= 5.4.
- */
-
- int sring_sz = p.sq_off.array + p.sq_entries * sizeof(unsigned);
- int cring_sz = p.cq_off.cqes + p.cq_entries * sizeof(struct io_uring_cqe);
-
- /* Rather than check for kernel version, the recommended way is to
- * check the features field of the io_uring_params structure, which is a
- * bitmask. If IORING_FEAT_SINGLE_MMAP is set, we can do away with the
- * second mmap() call to map in the completion ring separately.
- */
- if (p.features & IORING_FEAT_SINGLE_MMAP) {
- if (cring_sz > sring_sz)
- sring_sz = cring_sz;
- cring_sz = sring_sz;
- }
-
- /* Map in the submission and completion queue ring buffers.
- * Kernels < 5.4 only map in the submission queue, though.
- */
- sq_ptr = mmap(0, sring_sz, PROT_READ | PROT_WRITE,
- MAP_SHARED | MAP_POPULATE,
- ring_fd, IORING_OFF_SQ_RING);
- if (sq_ptr == MAP_FAILED) {
- perror("mmap");
- return 1;
- }
-
- if (p.features & IORING_FEAT_SINGLE_MMAP) {
- cq_ptr = sq_ptr;
- } else {
- /* Map in the completion queue ring buffer in older kernels separately */
- cq_ptr = mmap(0, cring_sz, PROT_READ | PROT_WRITE,
- MAP_SHARED | MAP_POPULATE,
- ring_fd, IORING_OFF_CQ_RING);
- if (cq_ptr == MAP_FAILED) {
- perror("mmap");
- return 1;
- }
- }
- /* Save useful fields for later easy reference */
- sring_tail = sq_ptr + p.sq_off.tail;
- sring_mask = sq_ptr + p.sq_off.ring_mask;
- sring_array = sq_ptr + p.sq_off.array;
-
- /* Map in the submission queue entries array */
- sqes = mmap(0, p.sq_entries * sizeof(struct io_uring_sqe),
- PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE,
- ring_fd, IORING_OFF_SQES);
- if (sqes == MAP_FAILED) {
- perror("mmap");
- return 1;
- }
-
- /* Save useful fields for later easy reference */
- cring_head = cq_ptr + p.cq_off.head;
- cring_tail = cq_ptr + p.cq_off.tail;
- cring_mask = cq_ptr + p.cq_off.ring_mask;
- cqes = cq_ptr + p.cq_off.cqes;
-
- return 0;
-}
-
-/*
-* Read from completion queue.
-* In this function, we read completion events from the completion queue.
-* We dequeue the CQE, update and head and return the result of the operation.
-* */
-
-int read_from_cq() {
- struct io_uring_cqe *cqe;
- unsigned head;
-
- /* Read barrier */
- head = io_uring_smp_load_acquire(cring_head);
- /*
- * Remember, this is a ring buffer. If head == tail, it means that the
- * buffer is empty.
- * */
- if (head == *cring_tail)
- return -1;
-
- /* Get the entry */
- cqe = &cqes[head & (*cring_mask)];
- if (cqe->res < 0)
- fprintf(stderr, "Error: %s\\n", strerror(abs(cqe->res)));
-
- head++;
-
- /* Write barrier so that update to the head are made visible */
- io_uring_smp_store_release(cring_head, head);
-
- return cqe->res;
-}
-
-/*
-* Submit a read or a write request to the submission queue.
-* */
-
-int submit_to_sq(int fd, int op) {
- unsigned index, tail;
-
- /* Add our submission queue entry to the tail of the SQE ring buffer */
- tail = *sring_tail;
- index = tail & *sring_mask;
- struct io_uring_sqe *sqe = &sqes[index];
- /* Fill in the parameters required for the read or write operation */
- sqe->opcode = op;
- sqe->fd = fd;
- sqe->addr = (unsigned long) buff;
- if (op == IORING_OP_READ) {
- memset(buff, 0, sizeof(buff));
- sqe->len = BLOCK_SZ;
- }
- else {
- sqe->len = strlen(buff);
- }
- sqe->off = offset;
-
- sring_array[index] = index;
- tail++;
-
- /* Update the tail */
- io_uring_smp_store_release(sring_tail, tail);
-
- /*
- * Tell the kernel we have submitted events with the io_uring_enter()
- * system call. We also pass in the IORING_ENTER_GETEVENTS flag which
- * causes the io_uring_enter() call to wait until min_complete
- * (the 3rd param) events complete.
- * */
- int ret = io_uring_enter(ring_fd, 1,1,
- IORING_ENTER_GETEVENTS);
- if(ret < 0) {
- perror("io_uring_enter");
- return -1;
- }
-
- return ret;
-}
-
-int main(int argc, char *argv[]) {
- int res;
-
- /* Setup io_uring for use */
- if(app_setup_uring()) {
- fprintf(stderr, "Unable to setup uring!\\n");
- return 1;
- }
-
- /*
- * A while loop that reads from stdin and writes to stdout.
- * Breaks on EOF.
- */
- while (1) {
- /* Initiate read from stdin and wait for it to complete */
- submit_to_sq(STDIN_FILENO, IORING_OP_READ);
- /* Read completion queue entry */
- res = read_from_cq();
- if (res > 0) {
- /* Read successful. Write to stdout. */
- submit_to_sq(STDOUT_FILENO, IORING_OP_WRITE);
- read_from_cq();
- } else if (res == 0) {
- /* reached EOF */
- break;
- }
- else if (res < 0) {
- /* Error reading file */
- fprintf(stderr, "Error: %s\\n", strerror(abs(res)));
- break;
- }
- offset += res;
- }
-
- return 0;
-}
-.EE
-.SH SEE ALSO
-.BR io_uring_enter (2)
-.BR io_uring_register (2)
-.BR io_uring_setup (2)
diff --git a/man/io_uring.7.md b/man/io_uring.7.md
new file mode 100644
index 00000000..6f65ba18
--- /dev/null
+++ b/man/io_uring.7.md
@@ -0,0 +1,779 @@
+.\" Copyright (C) 2020 Shuveb Hussain <shuveb@gmail.com>
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: July 26, 2020
+footer: Linux
+header: Linux Programmer\'s Manual
+section: 7
+title: io_uring
+---
+
+# NAME
+
+io_uring - Asynchronous I/O facility
+
+# SYNOPSIS
+
+``` text
+#include <linux/io_uring.h>
+```
+
+# DESCRIPTION
+
+**io_uring** is a Linux-specific API for asynchronous I/O. It allows the
+user to submit one or more I/O requests, which are processed
+asynchronously without blocking the calling process. **io_uring** gets
+its name from ring buffers which are shared between user space and
+kernel space. This arrangement allows for efficient I/O, while avoiding
+the overhead of copying buffers between them, where possible. This
+interface makes **io_uring** different from other UNIX I/O APIs,
+wherein, rather than just communicate between kernel and user space with
+system calls, ring buffers are used as the main mode of communication.
+This arrangement has various performance benefits which are discussed in
+a separate section below. This man page uses the terms shared buffers,
+shared ring buffers and queues interchangeably.
+
+The general programming model you need to follow for **io_uring** is
+outlined below
+
+- Set up shared buffers with **io_uring_setup**(2) and **mmap**(2),
+ mapping into user space shared buffers for the submission queue (SQ)
+ and the completion queue (CQ). You place I/O requests you want to make
+ on the SQ, while the kernel places the results of those operations on
+ the CQ.
+
+- For every I/O request you need to make (like to read a file, write a
+ file, accept a socket connection, etc), you create a submission queue
+ entry, or SQE, describe the I/O operation you need to get done and add
+ it to the tail of the submission queue (SQ). Each I/O operation is, in
+ essence, the equivalent of a system call you would have made
+ otherwise, if you were not using **io_uring**. For instance, a SQE
+ with the *opcode* set to **IORING_OP_READ** will request a read
+ operation to be issued that is similar to the **read**(2) system call.
+ Refer to the opcode documentation in **io_uring_enter**(2) for all
+ supported opcodes and their properties. You can add more than one SQE
+ to the queue depending on the number of operations you want to
+ request.
+
+- After you add one or more SQEs, you need to call **io_uring_enter**(2)
+ to tell the kernel to dequeue your I/O requests off the SQ and begin
+ processing them.
+
+- For each SQE you submit, once it is done processing the request, the
+ kernel places a completion queue event or CQE at the tail of the
+ completion queue or CQ. The kernel places exactly one matching CQE in
+ the CQ for every SQE you submit on the SQ. After you retrieve a CQE,
+ minimally, you might be interested in checking the *res* field of the
+ CQE structure, which corresponds to the return value of the system
+ call\'s equivalent, had you used it directly without using
+ **io_uring**. Given that **io_uring** is an async interface, *errno*
+ is never used for passing back error information. Instead, *res* will
+ contain what the equivalent system call would have returned in case of
+ success, and in case of error *res* will contain *-errno*. For
+ example, if the normal read system call would have returned -1 and set
+ *errno* to **EINVAL**, then *res* would contain **-EINVAL**. If the
+ normal system call would have returned a read size of 1024, then *res*
+ would contain 1024.
+
+- Optionally, **io_uring_enter**(2) can also wait for a specified number
+ of requests to be processed by the kernel before it returns. If you
+ specified a certain number of completions to wait for, the kernel
+ would have placed at least those many number of CQEs on the CQ, which
+ you can then readily read, right after the return from
+ **io_uring_enter**(2).
+
+- It is important to remember that I/O requests submitted to the kernel
+ can complete in any order. It is not necessary for the kernel to
+ process one request after another, in the order you placed them. Given
+ that the interface is a ring, the requests are attempted in order,
+ however that doesn\'t imply any sort of ordering on their execution or
+ completion. When more than one request is in flight, it is not
+ possible to determine which one will execute or complete first. When
+ you dequeue CQEs off the CQ, you should always check which submitted
+ request it corresponds to. The most common method for doing so is
+ utilizing the *user_data* field in the request, which is passed back
+ on the completion side.
+
+- Concretely, for operations where strict ordering is required, such as
+ for sends and receives on a stream-oriented TCP socket, it is
+ generally unsafe to have more than one outstanding send, or more than
+ one outstanding receive (the two directions are independent) on a
+ given socket at a time, as the kernel may reorder their execution if
+ poll arming or other background kernel activities are involved.
+ However, **io_uring** provides various facilities to enable
+ applications to efficiently pipeline their operations safely. If the
+ requests are submitted in a single batch, the application may use
+ **IOSQE_IO_LINK** to enforce an execution order in the kernel.
+ Otherwise, **io_uring** provides advanced features like *multi shot*
+ and send/receive *bundles* to allow applications to provide more data
+ in fewer, more efficient trips to the kernel. Even if these features
+ are used, applications must still ensure they do not overlap different
+ sends or different receives on a given file.
+
+Adding to and reading from the queues:
+
+- You add SQEs to the tail of the SQ. The kernel reads SQEs off the head
+ of the queue.
+
+- The kernel adds CQEs to the tail of the CQ. You read CQEs off the head
+ of the queue.
+
+It should be noted that depending on the configuration io_uring\'s
+behavior can deviate from the behavior outlined above, like not posting
+a CQE for every SQE when setting **IOSQE_CQE_SKIP_SUCCESS** in the SQE
+or posting multiple CQEs for a single SQE for multi shot operations or
+requiring an **io_uring_enter**(2) syscall to make the kernel begin
+processing newly added SQEs when using submission queue polling.
+
+## Submission queue polling
+
+One of the goals of **io_uring** is to provide a means for efficient
+I/O. To this end, **io_uring** supports a polling mode that lets you
+avoid the call to **io_uring_enter**(2), which you use to inform the
+kernel that you have queued SQEs on to the SQ. With SQ Polling,
+**io_uring** starts a kernel thread that polls the submission queue for
+any I/O requests you submit by adding SQEs. With SQ Polling enabled,
+there is no need for you to call **io_uring_enter**(2), letting you
+avoid the overhead of system calls. A designated kernel thread dequeues
+SQEs off the SQ as you add them and dispatches them for asynchronous
+processing.
+
+## Setting up io_uring
+
+The main steps in setting up **io_uring** consist of mapping in the
+shared buffers with **mmap**(2) calls. In the example program included
+in this man page, the function **app_setup_uring**() sets up
+**io_uring** with a QUEUE_DEPTH deep submission queue. Pay attention to
+the 2 **mmap**(2) calls that set up the shared submission and completion
+queues. If your kernel is older than version 5.4, three **mmap(2)**
+calls are required.
+
+## Submitting I/O requests
+
+The process of submitting a request consists of describing the I/O
+operation you need to get done using an **io_uring_sqe** structure
+instance. These details describe the equivalent system call and its
+parameters. Because the range of I/O operations Linux supports are very
+varied and the **io_uring_sqe** structure needs to be able to describe
+them, it has several fields, some packed into unions for space
+efficiency. Here is a simplified version of struct **io_uring_sqe** with
+some of the most often used fields:
+
+``` text
+struct io_uring_sqe {
+ __u8 opcode; /* type of operation for this sqe */
+ __s32 fd; /* file descriptor to do IO on */
+ __u64 off; /* offset into file */
+ __u64 addr; /* pointer to buffer or iovecs */
+ __u32 len; /* buffer size or number of iovecs */
+ __u64 user_data; /* data to be passed back at completion time */
+ __u8 flags; /* IOSQE_ flags */
+ ...
+};
+```
+
+Here is struct **io_uring_sqe** in full:
+
+``` text
+struct io_uring_sqe {
+ __u8 opcode; /* type of operation for this sqe */
+ __u8 flags; /* IOSQE_ flags */
+ __u16 ioprio; /* ioprio for the request */
+ __s32 fd; /* file descriptor to do IO on */
+ union {
+ __u64 off; /* offset into file */
+ __u64 addr2;
+ struct {
+ __u32 cmd_op;
+ __u32 __pad1;
+ };
+ };
+ union {
+ __u64 addr; /* pointer to buffer or iovecs */
+ __u64 splice_off_in;
+ struct {
+ __u32 level;
+ __u32 optname;
+ };
+ };
+ __u32 len; /* buffer size or number of iovecs */
+ union {
+ __kernel_rwf_t rw_flags;
+ __u32 fsync_flags;
+ __u16 poll_events; /* compatibility */
+ __u32 poll32_events; /* word-reversed for BE */
+ __u32 sync_range_flags;
+ __u32 msg_flags;
+ __u32 timeout_flags;
+ __u32 accept_flags;
+ __u32 cancel_flags;
+ __u32 open_flags;
+ __u32 statx_flags;
+ __u32 fadvise_advice;
+ __u32 splice_flags;
+ __u32 rename_flags;
+ __u32 unlink_flags;
+ __u32 hardlink_flags;
+ __u32 xattr_flags;
+ __u32 msg_ring_flags;
+ __u32 uring_cmd_flags;
+ __u32 waitid_flags;
+ __u32 futex_flags;
+ __u32 install_fd_flags;
+ __u32 nop_flags;
+ };
+ __u64 user_data; /* data to be passed back at completion time */
+ /* pack this to avoid bogus arm OABI complaints */
+ union {
+ /* index into fixed buffers, if used */
+ __u16 buf_index;
+ /* for grouped buffer selection */
+ __u16 buf_group;
+ } __attribute__((packed));
+ /* personality to use, if used */
+ __u16 personality;
+ union {
+ __s32 splice_fd_in;
+ __u32 file_index;
+ __u32 optlen;
+ struct {
+ __u16 addr_len;
+ __u16 __pad3[1];
+ };
+ };
+ union {
+ struct {
+ __u64 addr3;
+ __u64 __pad2[1];
+ };
+ __u64 optval;
+ /*
+ * If the ring is initialized with IORING_SETUP_SQE128, then
+ * this field is used for 80 bytes of arbitrary command data
+ */
+ __u8 cmd[0];
+ };
+};
+```
+
+To submit an I/O request to **io_uring**, you need to acquire a
+submission queue entry (SQE) from the submission queue (SQ), fill it up
+with details of the operation you want to submit and call
+**io_uring_enter**(2). There are helper functions of the form
+io_uring_prep_X to enable proper setup of the SQE. If you want to avoid
+calling **io_uring_enter**(2), you have the option of setting up
+Submission Queue Polling.
+
+SQEs are added to the tail of the submission queue. The kernel picks up
+SQEs off the head of the SQ. The general algorithm to get the next
+available SQE and update the tail is as follows.
+
+``` text
+struct io_uring_sqe *sqe;
+unsigned tail, index;
+tail = *sqring->tail;
+index = tail & (*sqring->ring_mask);
+sqe = &sqring->sqes[index];
+/* fill up details about this I/O request */
+describe_io(sqe);
+/* fill the sqe index into the SQ ring array */
+sqring->array[index] = index;
+tail++;
+atomic_store_explicit(sqring->tail, tail, memory_order_release);
+```
+
+To get the index of an entry, the application must mask the current tail
+index with the size mask of the ring. This holds true for both SQs and
+CQs. Once the SQE is acquired, the necessary fields are filled in,
+describing the request. While the CQ ring directly indexes the shared
+array of CQEs, the submission side has an indirection array between
+them. The submission side ring buffer is an index into this array, which
+in turn contains the index into the SQEs.
+
+The following code snippet demonstrates how a read operation, an
+equivalent of a **preadv2**(2) system call is described by filling up an
+SQE with the necessary parameters.
+
+``` text
+struct iovec iovecs[16];
+ ...
+sqe->opcode = IORING_OP_READV;
+sqe->fd = fd;
+sqe->addr = (unsigned long) iovecs;
+sqe->len = 16;
+sqe->off = offset;
+sqe->flags = 0;
+```
+
+**Memory ordering**
+
+: Modern compilers and CPUs freely reorder reads and writes without
+ affecting the program\'s outcome to optimize performance. Some aspects
+ of this need to be kept in mind on SMP systems since **io_uring**
+ involves buffers shared between kernel and user space. These buffers
+ are both visible and modifiable from kernel and user space. As heads
+ and tails belonging to these shared buffers are updated by kernel and
+ user space, changes need to be coherently visible on either side,
+ irrespective of whether a CPU switch took place after the kernel-user
+ mode switch happened. We use memory barriers to enforce this
+ coherency. Being significantly large subjects on their own, memory
+ barriers are out of scope for further discussion on this man page. For
+ more information on modern memory models the reader may refer to the
+ Documentation/memory-barriers.txt in the kernel tree or to the
+ documentation of the formal C11 or kernel memory model.
+
+**Letting the kernel know about I/O submissions**
+
+: Once you place one or more SQEs on to the SQ, you need to let the
+ kernel know that you\'ve done so. You can do this by calling the
+ **io_uring_enter**(2) system call. This system call is also capable of
+ waiting for a specified count of events to complete. This way, you can
+ be sure to find completion events in the completion queue without
+ having to poll it for events later.
+
+## SQE pointer lifetimes & data stability
+
+Due to the fixed size of the submission queue entry (SQE) some data you
+provide in order to perform a desired operation will be passed in the
+form of a pointer rather than value. In this situation, you may free the
+memory backing the pointer once the succeeding **io_uring_enter**(2)
+call has completed; providing it is only required by the operation when
+submitting.
+
+When **IORING_SETUP_SQPOLL** is not enabled, this is done when you call
+**io_uring_submit**(3) In The event **IORING_SETUP_SQPOLL** is enabled,
+you must ensure any provided pointers remain valid until completion.
+
+However, very early kernels (5.4 and earlier) required state to be
+stable until the completion occurred regardless. Applications can test
+for this behavior by inspecting the **IORING_FEAT_SUBMIT_STABLE** flag
+passed back from **io_uring_queue_init_params**(3).
+
+As an example, the **IORING_OP_TIMEOUT** operation takes a pointer to a
+\_\_kernel_timespec struct. This struct is then read by the kernel when
+you submit the submission queue entries, once submitted, you may free
+the backing memory of the \_\_kernel_timespec as it will not be read
+again by the kernel.
+
+It should be noted that this behaviour does not apply to data that is
+read or written while the operation is inflight. For example, the
+pointers to a buffer used as part of a **IORING_OP_WRITE** or
+**IORING_OP_READ** operation must remain valid until completion.
+
+## Reading completion events
+
+Similar to the submission queue (SQ), the completion queue (CQ) is a
+shared buffer between the kernel and user space. Whereas you placed
+submission queue entries on the tail of the SQ and the kernel read off
+the head, when it comes to the CQ, the kernel places completion queue
+events or CQEs on the tail of the CQ and you read off its head.
+
+Submission is flexible (and thus a bit more complicated) since it needs
+to be able to encode different types of system calls that take various
+parameters. Completion, on the other hand is simpler since we\'re
+looking only for a return value back from the kernel. This is easily
+understood by looking at the completion queue event structure, struct
+**io_uring_cqe**:
+
+``` text
+struct io_uring_cqe {
+ __u64 user_data; /* sqe->data submission passed back */
+ __s32 res; /* result code for this event */
+ __u32 flags;
+};
+```
+
+Here, *user_data* is custom data that is passed unchanged from
+submission to completion. That is, from SQEs to CQEs. This field can be
+used to set context, uniquely identifying submissions that got
+completed. Given that I/O requests can complete in any order, this field
+can be used to correlate a submission with a completion. *res* is the
+result from the system call that was performed as part of the
+submission; its return value.
+
+The *flags* field carries request-specific information. As of the 6.12
+kernel, the following flags are defined:
+
+**IORING_CQE_F_BUFFER**
+
+: If set, the upper 16 bits of the flags field carries the buffer ID
+ that was chosen for this request. The request must have been issued
+ with **IOSQE_BUFFER_SELECT** set, and used with a request type that
+ supports buffer selection. Additionally, buffers must have been
+ provided upfront either via the **IORING_OP_PROVIDE_BUFFERS** or the
+ **IORING_REGISTER_PBUF_RING** methods.
+
+**IORING_CQE_F_MORE**
+
+: If set, the application should expect more completions from the
+ request. This is used for requests that can generate multiple
+ completions, such as multi-shot requests, receive, or accept.
+
+**IORING_CQE_F_SOCK_NONEMPTY**
+
+: If set, upon receiving the data from the socket in the current
+ request, the socket still had data left on completion of this request.
+
+**IORING_CQE_F_NOTIF**
+
+: Set for notification CQEs, as seen with the zero-copy networking send
+ and receive support.
+
+**IORING_CQE_F_BUF_MORE**
+
+: If set, the buffer ID set in the completion will get more completions.
+ This means that the provided buffer has been partially consumed and
+ there\'s more buffer space left, and hence the application should
+ expect more completions with this buffer ID. Each completion will
+ continue where the previous one left off. This can only happen if the
+ provided buffer ring has been setup with **IOU_PBUF_RING_INC** to
+ allow for incremental / partial consumption of buffers.
+
+**IORING_CQE_F_SKIP**
+
+: If the ring has been configured with **IORING_SETUP_CQE_MIXED ,** then
+ CQEs may be posted which has this flag set. This can happen if the
+ ring is a single 16b CQE entry away from wrapping, but someone needs
+ to post a 32b CQE. As CQEs must be contiguous in memory, a filler/pad
+ CQE needs to get posted to allow posting of the 32b CQE. CQEs with
+ this flag set should simply be skipped and ignored, they serve no
+ other purpose than to fill a gap in the CQ ring.
+
+**IORING_CQE_F_32**
+
+: If the ring has been configured with **IORING_SETUP_CQE_MIXED ,** this
+ flag is set when the CQE is of the 32b type. This tells the
+ application that there\'s an extra 16b of space in this CQE, and that
+ to get to the next CQE the CQ ring must be advanced by twice as much
+ as for a normal 16b CQE.
+
+The general sequence to read completion events off the completion queue
+is as follows:
+
+``` text
+unsigned head;
+head = *cqring->head;
+if (head != atomic_load_acquire(cqring->tail)) {
+ struct io_uring_cqe *cqe;
+ unsigned index;
+ index = head & (cqring->mask);
+ cqe = &cqring->cqes[index];
+ /* process completed CQE */
+ process_cqe(cqe);
+ /* CQE consumption complete */
+ head++;
+}
+atomic_store_explicit(cqring->head, head, memory_order_release);
+```
+
+It helps to be reminded that the kernel adds CQEs to the tail of the CQ,
+while you need to dequeue them off the head. To get the index of an
+entry at the head, the application must mask the current head index with
+the size mask of the ring. Once the CQE has been consumed or processed,
+the head needs to be updated to reflect the consumption of the CQE.
+Attention should be paid to the read and write barriers to ensure
+successful read and update of the head.
+
+## io_uring performance
+
+Because of the shared ring buffers between kernel and user space,
+**io_uring** can be a zero-copy system. Copying buffers to and from
+becomes necessary when system calls that transfer data between kernel
+and user space are involved. But since the bulk of the communication in
+**io_uring** is via buffers shared between the kernel and user space,
+this huge performance overhead is completely avoided.
+
+While system calls may not seem like a significant overhead, in high
+performance applications, making a lot of them will begin to matter.
+While workarounds the operating system has in place to deal with Spectre
+and Meltdown are ideally best done away with, unfortunately, some of
+these workarounds are around the system call interface, making system
+calls not as cheap as before on affected hardware. While newer hardware
+should not need these workarounds, hardware with these vulnerabilities
+can be expected to be in the wild for a long time. While using
+synchronous programming interfaces or even when using asynchronous
+programming interfaces under Linux, there is at least one system call
+involved in the submission of each request. In **io_uring**, on the
+other hand, you can batch several requests in one go, simply by queueing
+up multiple SQEs, each describing an I/O operation you want and make a
+single call to **io_uring_enter**(2). This is possible due to
+**io_uring**\'s shared buffers based design.
+
+While this batching in itself can avoid the overhead associated with
+potentially multiple and frequent system calls, you can reduce even this
+overhead further with Submission Queue Polling, by having the kernel
+poll and pick up your SQEs for processing as you add them to the
+submission queue. This avoids the **io_uring_enter**(2) call you need to
+make to tell the kernel to pick SQEs up. For high-performance
+applications, this means even fewer system call overheads.
+
+# CONFORMING TO
+
+**io_uring** is Linux-specific.
+
+# EXAMPLES
+
+The following example uses **io_uring** to copy stdin to stdout. Using
+shell redirection, you should be able to copy files with this example.
+Because it uses a queue depth of only one, this example processes I/O
+requests one after the other. It is purposefully kept this way to aid
+understanding. In real-world scenarios however, you\'ll want to have a
+larger queue depth to parallelize I/O request processing so as to gain
+the kind of performance benefits **io_uring** provides with its
+asynchronous processing of requests.
+
+``` text
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/syscall.h>
+#include <sys/mman.h>
+#include <sys/uio.h>
+#include <linux/fs.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdatomic.h>
+#include <errno.h>
+
+#include <linux/io_uring.h>
+
+#define QUEUE_DEPTH 1
+#define BLOCK_SZ 1024
+
+/* Macros for barriers needed by io_uring */
+#define io_uring_smp_store_release(p, v) \
+ atomic_store_explicit((_Atomic typeof(*(p)) *)(p), (v), \
+ memory_order_release)
+#define io_uring_smp_load_acquire(p) \
+ atomic_load_explicit((_Atomic typeof(*(p)) *)(p), \
+ memory_order_acquire)
+
+int ring_fd;
+unsigned *sring_tail, *sring_mask, *sring_array,
+ *cring_head, *cring_tail, *cring_mask;
+struct io_uring_sqe *sqes;
+struct io_uring_cqe *cqes;
+char buff[BLOCK_SZ];
+off_t offset;
+
+/*
+ * System call wrappers provided since glibc does not yet
+ * provide wrappers for io_uring system calls.
+* */
+
+int io_uring_setup(unsigned entries, struct io_uring_params *p)
+{
+ int ret;
+ ret = syscall(__NR_io_uring_setup, entries, p);
+ return (ret < 0) ? -errno : ret;
+}
+
+int io_uring_enter(int ring_fd, unsigned int to_submit,
+ unsigned int min_complete, unsigned int flags)
+{
+ int ret;
+ ret = syscall(__NR_io_uring_enter, ring_fd, to_submit,
+ min_complete, flags, NULL, 0);
+ return (ret < 0) ? -errno : ret;
+}
+
+int app_setup_uring(void) {
+ struct io_uring_params p;
+ void *sq_ptr, *cq_ptr;
+
+ /* See io_uring_setup(2) for io_uring_params.flags you can set */
+ memset(&p, 0, sizeof(p));
+ ring_fd = io_uring_setup(QUEUE_DEPTH, &p);
+ if (ring_fd < 0) {
+ perror("io_uring_setup");
+ return 1;
+ }
+
+ /*
+ * io_uring communication happens via 2 shared kernel-user space ring
+ * buffers, which can be jointly mapped with a single mmap() call in
+ * kernels >= 5.4.
+ */
+
+ int sring_sz = p.sq_off.array + p.sq_entries * sizeof(unsigned);
+ int cring_sz = p.cq_off.cqes + p.cq_entries * sizeof(struct io_uring_cqe);
+
+ /* Rather than check for kernel version, the recommended way is to
+ * check the features field of the io_uring_params structure, which is a
+ * bitmask. If IORING_FEAT_SINGLE_MMAP is set, we can do away with the
+ * second mmap() call to map in the completion ring separately.
+ */
+ if (p.features & IORING_FEAT_SINGLE_MMAP) {
+ if (cring_sz > sring_sz)
+ sring_sz = cring_sz;
+ cring_sz = sring_sz;
+ }
+
+ /* Map in the submission and completion queue ring buffers.
+ * Kernels < 5.4 only map in the submission queue, though.
+ */
+ sq_ptr = mmap(0, sring_sz, PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_POPULATE,
+ ring_fd, IORING_OFF_SQ_RING);
+ if (sq_ptr == MAP_FAILED) {
+ perror("mmap");
+ return 1;
+ }
+
+ if (p.features & IORING_FEAT_SINGLE_MMAP) {
+ cq_ptr = sq_ptr;
+ } else {
+ /* Map in the completion queue ring buffer in older kernels separately */
+ cq_ptr = mmap(0, cring_sz, PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_POPULATE,
+ ring_fd, IORING_OFF_CQ_RING);
+ if (cq_ptr == MAP_FAILED) {
+ perror("mmap");
+ return 1;
+ }
+ }
+ /* Save useful fields for later easy reference */
+ sring_tail = sq_ptr + p.sq_off.tail;
+ sring_mask = sq_ptr + p.sq_off.ring_mask;
+ sring_array = sq_ptr + p.sq_off.array;
+
+ /* Map in the submission queue entries array */
+ sqes = mmap(0, p.sq_entries * sizeof(struct io_uring_sqe),
+ PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE,
+ ring_fd, IORING_OFF_SQES);
+ if (sqes == MAP_FAILED) {
+ perror("mmap");
+ return 1;
+ }
+
+ /* Save useful fields for later easy reference */
+ cring_head = cq_ptr + p.cq_off.head;
+ cring_tail = cq_ptr + p.cq_off.tail;
+ cring_mask = cq_ptr + p.cq_off.ring_mask;
+ cqes = cq_ptr + p.cq_off.cqes;
+
+ return 0;
+}
+
+/*
+* Read from completion queue.
+* In this function, we read completion events from the completion queue.
+* We dequeue the CQE, update and head and return the result of the operation.
+* */
+
+int read_from_cq() {
+ struct io_uring_cqe *cqe;
+ unsigned head;
+
+ /* Read barrier */
+ head = io_uring_smp_load_acquire(cring_head);
+ /*
+ * Remember, this is a ring buffer. If head == tail, it means that the
+ * buffer is empty.
+ * */
+ if (head == *cring_tail)
+ return -1;
+
+ /* Get the entry */
+ cqe = &cqes[head & (*cring_mask)];
+ if (cqe->res < 0)
+ fprintf(stderr, "Error: %s\n", strerror(abs(cqe->res)));
+
+ head++;
+
+ /* Write barrier so that update to the head are made visible */
+ io_uring_smp_store_release(cring_head, head);
+
+ return cqe->res;
+}
+
+/*
+* Submit a read or a write request to the submission queue.
+* */
+
+int submit_to_sq(int fd, int op) {
+ unsigned index, tail;
+
+ /* Add our submission queue entry to the tail of the SQE ring buffer */
+ tail = *sring_tail;
+ index = tail & *sring_mask;
+ struct io_uring_sqe *sqe = &sqes[index];
+ /* Fill in the parameters required for the read or write operation */
+ sqe->opcode = op;
+ sqe->fd = fd;
+ sqe->addr = (unsigned long) buff;
+ if (op == IORING_OP_READ) {
+ memset(buff, 0, sizeof(buff));
+ sqe->len = BLOCK_SZ;
+ }
+ else {
+ sqe->len = strlen(buff);
+ }
+ sqe->off = offset;
+
+ sring_array[index] = index;
+ tail++;
+
+ /* Update the tail */
+ io_uring_smp_store_release(sring_tail, tail);
+
+ /*
+ * Tell the kernel we have submitted events with the io_uring_enter()
+ * system call. We also pass in the IORING_ENTER_GETEVENTS flag which
+ * causes the io_uring_enter() call to wait until min_complete
+ * (the 3rd param) events complete.
+ * */
+ int ret = io_uring_enter(ring_fd, 1,1,
+ IORING_ENTER_GETEVENTS);
+ if(ret < 0) {
+ perror("io_uring_enter");
+ return -1;
+ }
+
+ return ret;
+}
+
+int main(int argc, char *argv[]) {
+ int res;
+
+ /* Setup io_uring for use */
+ if(app_setup_uring()) {
+ fprintf(stderr, "Unable to setup uring!\n");
+ return 1;
+ }
+
+ /*
+ * A while loop that reads from stdin and writes to stdout.
+ * Breaks on EOF.
+ */
+ while (1) {
+ /* Initiate read from stdin and wait for it to complete */
+ submit_to_sq(STDIN_FILENO, IORING_OP_READ);
+ /* Read completion queue entry */
+ res = read_from_cq();
+ if (res > 0) {
+ /* Read successful. Write to stdout. */
+ submit_to_sq(STDOUT_FILENO, IORING_OP_WRITE);
+ read_from_cq();
+ } else if (res == 0) {
+ /* reached EOF */
+ break;
+ }
+ else if (res < 0) {
+ /* Error reading file */
+ fprintf(stderr, "Error: %s\n", strerror(abs(res)));
+ break;
+ }
+ offset += res;
+ }
+
+ return 0;
+}
+```
+
+# SEE ALSO
+
+**io_uring_enter**(2) **io_uring_register**(2) **io_uring_setup**(2)
diff --git a/man/io_uring_buf_ring_add.3 b/man/io_uring_buf_ring_add.3
deleted file mode 100644
index 8bbcf24f..00000000
--- a/man/io_uring_buf_ring_add.3
+++ /dev/null
@@ -1,64 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_buf_ring_add 3 "May 18, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_buf_ring_add \- add buffers to a shared buffer ring
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_buf_ring_add(struct io_uring_buf_ring *" br ",
-.BI " void *" addr ",
-.BI " unsigned int " len ",
-.BI " unsigned short " bid ",
-.BI " int " mask ",
-.BI " int " buf_offset ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_buf_ring_add (3)
-adds a new buffer to the shared buffer ring
-.IR br .
-The buffer address is indicated by
-.I addr
-and is of
-.I len
-bytes of length.
-.I bid
-is the buffer ID, which will be returned in the CQE.
-.I mask
-is the size mask of the ring, available from
-.BR io_uring_buf_ring_mask (3) .
-.I buf_offset
-is the offset to insert at from the current tail. If just one buffer is provided
-before the ring tail is committed with
-.BR io_uring_buf_ring_advance (3)
-or
-.BR io_uring_buf_ring_cq_advance (3),
-then
-.I buf_offset
-should be 0. If buffers are provided in a loop before being committed, the
-.I buf_offset
-must be incremented by one for each buffer added.
-
-.SH RETURN VALUE
-None
-.SH NOTES
-liburing (or the kernel, for that matter) doesn't care about what buffer ID maps
-to what buffer, and in fact when recycling buffers after use, the application is
-free to add a different buffer into the same buffer ID location. All that
-matters is that the application knows what a given buffer ID in time corresponds
-to in terms of virtual memory. There's no liburing or kernel assumption that
-these mappings are persistent over time, they can very well be different every
-time a given buffer ID is added to the provided buffer ring.
-
-Note that no uring functions can write more than INT_MAX bytes to a buffer in a
-single call. For details, see the man pages for individual functions.
-.SH SEE ALSO
-.BR io_uring_register_buf_ring (3),
-.BR io_uring_buf_ring_mask (3),
-.BR io_uring_buf_ring_advance (3),
-.BR io_uring_buf_ring_cq_advance (3)
diff --git a/man/io_uring_buf_ring_add.3.md b/man/io_uring_buf_ring_add.3.md
new file mode 100644
index 00000000..3de421d2
--- /dev/null
+++ b/man/io_uring_buf_ring_add.3.md
@@ -0,0 +1,65 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: May 18, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_buf_ring_add
+---
+
+# NAME
+
+io_uring_buf_ring_add - add buffers to a shared buffer ring
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_buf_ring_add(struct io_uring_buf_ring * br ,
+ void * addr ,
+ unsigned int len ,
+ unsigned short bid ,
+ int mask ,
+ int buf_offset );
+```
+
+# DESCRIPTION
+
+The **io_uring_buf_ring_add**(3) adds a new buffer to the shared buffer
+ring *br*. The buffer address is indicated by *addr* and is of *len*
+bytes of length. *bid* is the buffer ID, which will be returned in the
+CQE. *mask* is the size mask of the ring, available from
+**io_uring_buf_ring_mask**(3)**.** *buf_offset* is the offset to insert
+at from the current tail. If just one buffer is provided before the ring
+tail is committed with **io_uring_buf_ring_advance**(3) or
+**io_uring_buf_ring_cq_advance**(3), then *buf_offset* should be 0. If
+buffers are provided in a loop before being committed, the *buf_offset*
+must be incremented by one for each buffer added.
+
+# RETURN VALUE
+
+None
+
+# NOTES
+
+liburing (or the kernel, for that matter) doesn\'t care about what
+buffer ID maps to what buffer, and in fact when recycling buffers after
+use, the application is free to add a different buffer into the same
+buffer ID location. All that matters is that the application knows what
+a given buffer ID in time corresponds to in terms of virtual memory.
+There\'s no liburing or kernel assumption that these mappings are
+persistent over time, they can very well be different every time a given
+buffer ID is added to the provided buffer ring.
+
+Note that no uring functions can write more than INT_MAX bytes to a
+buffer in a single call. For details, see the man pages for individual
+functions.
+
+# SEE ALSO
+
+**io_uring_register_buf_ring**(3), **io_uring_buf_ring_mask**(3),
+**io_uring_buf_ring_advance**(3), **io_uring_buf_ring_cq_advance**(3)
diff --git a/man/io_uring_buf_ring_advance.3 b/man/io_uring_buf_ring_advance.3
deleted file mode 100644
index f2dc90b5..00000000
--- a/man/io_uring_buf_ring_advance.3
+++ /dev/null
@@ -1,31 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_buf_ring_advance 3 "May 18, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_buf_ring_advance \- advance index of provided buffer in buffer ring
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_buf_ring_advance(struct io_uring_buf_ring *" br ",
-.BI " int " count ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_buf_ring_advance (3)
-commits
-.I count
-previously added buffers to the shared buffer ring
-.IR br ,
-making them visible to the kernel and hence consumable. This passes ownership
-of the buffer to the ring.
-
-.SH RETURN VALUE
-None
-.SH SEE ALSO
-.BR io_uring_register_buf_ring (3),
-.BR io_uring_buf_ring_add (3),
-.BR io_uring_buf_ring_cq_advance (3)
diff --git a/man/io_uring_buf_ring_advance.3.md b/man/io_uring_buf_ring_advance.3.md
new file mode 100644
index 00000000..81ca6e14
--- /dev/null
+++ b/man/io_uring_buf_ring_advance.3.md
@@ -0,0 +1,41 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: May 18, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_buf_ring_advance
+---
+
+# NAME
+
+io_uring_buf_ring_advance - advance index of provided buffer in buffer
+ring
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_buf_ring_advance(struct io_uring_buf_ring * br ,
+ int count );
+```
+
+# DESCRIPTION
+
+The **io_uring_buf_ring_advance**(3) commits *count* previously added
+buffers to the shared buffer ring *br*, making them visible to the
+kernel and hence consumable. This passes ownership of the buffer to the
+ring.
+
+# RETURN VALUE
+
+None
+
+# SEE ALSO
+
+**io_uring_register_buf_ring**(3), **io_uring_buf_ring_add**(3),
+**io_uring_buf_ring_cq_advance**(3)
diff --git a/man/io_uring_buf_ring_available.3 b/man/io_uring_buf_ring_available.3
deleted file mode 100644
index c1dc8b80..00000000
--- a/man/io_uring_buf_ring_available.3
+++ /dev/null
@@ -1,47 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_buf_ring_available 3 "Jan 11, 2024" "liburing-2.6" "liburing Manual"
-.SH NAME
-io_uring_buf_ring_available \- return number of unconsumed provided ring buffer entries
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_buf_ring_available(struct io_uring *" ring ",
-.BI " struct io_uring_buf_ring *" br ",
-.BI " unsigned short " bgid ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_buf_ring_available (3)
-helper returns the number of unconsumed (by the kernel) entries in the
-.IR br
-provided buffer group belonging to the io_uring
-.IR ring
-and identified by the buffer group ID
-.IR bgid.
-
-Since the head of the provided buffer ring is only visible to the kernel, it's
-impossible to otherwise know how many unconsumed entries exist in the given
-provided buffer ring. This function query the kernel to return that number.
-Available since kernel 6.8.
-
-.SH NOTES
-The returned number of entries reflect the amount of unconsumed entries at the
-time that it was queried. If inflight IO exists that may consume provided
-buffers from this buffer group, then the returned value is inherently racy.
-.SH RETURN VALUE
-Returns the number of unconsumed entries on success, which may be 0. In case
-of error, may return
-.BR -ENOENT
-if the specified buffer group doesn't exist, or
-.BR -EINVAL
-if the buffer group isn't of the correct type, or if the kernel doesn't
-support this feature.
-.SH SEE ALSO
-.BR io_uring_register_buf_ring (3),
-.BR io_uring_buf_ring_add (3),
-.BR io_uring_buf_ring_cq_advance (3)
diff --git a/man/io_uring_buf_ring_available.3.md b/man/io_uring_buf_ring_available.3.md
new file mode 100644
index 00000000..afd968e1
--- /dev/null
+++ b/man/io_uring_buf_ring_available.3.md
@@ -0,0 +1,57 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: Jan 11, 2024
+footer: liburing-2.6
+header: liburing Manual
+section: 3
+title: io_uring_buf_ring_available
+---
+
+# NAME
+
+io_uring_buf_ring_available - return number of unconsumed provided ring
+buffer entries
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_buf_ring_available(struct io_uring * ring ,
+ struct io_uring_buf_ring * br ,
+ unsigned short bgid );
+```
+
+# DESCRIPTION
+
+The **io_uring_buf_ring_available**(3) helper returns the number of
+unconsumed (by the kernel) entries in the *br* provided buffer group
+belonging to the io_uring *ring* and identified by the buffer group ID
+*bgid.*
+
+Since the head of the provided buffer ring is only visible to the
+kernel, it\'s impossible to otherwise know how many unconsumed entries
+exist in the given provided buffer ring. This function query the kernel
+to return that number. Available since kernel 6.8.
+
+# NOTES
+
+The returned number of entries reflect the amount of unconsumed entries
+at the time that it was queried. If inflight IO exists that may consume
+provided buffers from this buffer group, then the returned value is
+inherently racy.
+
+# RETURN VALUE
+
+Returns the number of unconsumed entries on success, which may be 0. In
+case of error, may return **-ENOENT** if the specified buffer group
+doesn\'t exist, or **-EINVAL** if the buffer group isn\'t of the correct
+type, or if the kernel doesn\'t support this feature.
+
+# SEE ALSO
+
+**io_uring_register_buf_ring**(3), **io_uring_buf_ring_add**(3),
+**io_uring_buf_ring_cq_advance**(3)
diff --git a/man/io_uring_buf_ring_cq_advance.3 b/man/io_uring_buf_ring_cq_advance.3
deleted file mode 100644
index d7ada5d0..00000000
--- a/man/io_uring_buf_ring_cq_advance.3
+++ /dev/null
@@ -1,55 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_buf_ring_cq_advance 3 "May 18, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_buf_ring_cq_advance \- advance index of provided buffer and CQ ring
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_buf_ring_cq_advance(struct io_uring *" ring ",
-.BI " struct io_uring_buf_ring *" br ",
-.BI " int " count ");"
-.PP
-.BI "void __io_uring_buf_ring_cq_advance(struct io_uring *" ring ",
-.BI " struct io_uring_buf_ring *" br ",
-.BI " int " cq_count ",
-.BI " int " buf_count ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_buf_ring_cq_advance (3)
-commits
-.I count
-previously added buffers to the shared buffer ring
-.IR br ,
-making them visible to the kernel and hence consumable. This passes ownership
-of the buffer to the ring. At the same time, it advances the CQ ring of
-.I ring
-by
-.I count
-amount. This effectively bundles both a
-.BR io_uring_buf_ring_advance (3)
-call and a
-.BR io_uring_cq_advance (3)
-into one operation. Since updating either ring index entails a store memory
-barrier, doing both at once is more efficient.
-
-The
-.BR __io_uring_buf_ring_cq_advance (3)
-function performs the same operation, except it splits the counts into two
-separate values. It advances the CQ ring by
-.I cq_count
-entries, and the buffer ring by
-.I buf_count
-entries rather than increment both by the same value.
-
-.SH RETURN VALUE
-None
-.SH SEE ALSO
-.BR io_uring_register_buf_ring (3),
-.BR io_uring_buf_ring_add (3),
-.BR io_uring_buf_ring_advance (3)
diff --git a/man/io_uring_buf_ring_cq_advance.3.md b/man/io_uring_buf_ring_cq_advance.3.md
new file mode 100644
index 00000000..55ce53fd
--- /dev/null
+++ b/man/io_uring_buf_ring_cq_advance.3.md
@@ -0,0 +1,56 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: May 18, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_buf_ring_cq_advance
+---
+
+# NAME
+
+io_uring_buf_ring_cq_advance - advance index of provided buffer and CQ
+ring
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_buf_ring_cq_advance(struct io_uring * ring ,
+ struct io_uring_buf_ring * br ,
+ int count );
+
+ void __io_uring_buf_ring_cq_advance(struct io_uring * ring ,
+ struct io_uring_buf_ring * br ,
+ int cq_count ,
+ int buf_count );
+```
+
+# DESCRIPTION
+
+The **io_uring_buf_ring_cq_advance**(3) commits *count* previously added
+buffers to the shared buffer ring *br*, making them visible to the
+kernel and hence consumable. This passes ownership of the buffer to the
+ring. At the same time, it advances the CQ ring of *ring* by *count*
+amount. This effectively bundles both a **io_uring_buf_ring_advance**(3)
+call and a **io_uring_cq_advance**(3) into one operation. Since updating
+either ring index entails a store memory barrier, doing both at once is
+more efficient.
+
+The **\_\_io_uring_buf_ring_cq_advance**(3) function performs the same
+operation, except it splits the counts into two separate values. It
+advances the CQ ring by *cq_count* entries, and the buffer ring by
+*buf_count* entries rather than increment both by the same value.
+
+# RETURN VALUE
+
+None
+
+# SEE ALSO
+
+**io_uring_register_buf_ring**(3), **io_uring_buf_ring_add**(3),
+**io_uring_buf_ring_advance**(3)
diff --git a/man/io_uring_buf_ring_init.3 b/man/io_uring_buf_ring_init.3
deleted file mode 100644
index beabed8c..00000000
--- a/man/io_uring_buf_ring_init.3
+++ /dev/null
@@ -1,36 +0,0 @@
-.\" Copyright (C) 2022 Dylan Yudaken <dylany@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_buf_ring_init 3 "June 13, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_buf_ring_init \- Initialise a buffer ring
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_buf_ring_init(struct io_uring_buf_ring *" br ");"
-.fi
-.SH DESCRIPTION
-.PP
-.BR io_uring_buf_ring_init (3)
-initialises
-.IR br
-so that it is ready to be used. It may be called after
-.BR io_uring_register_buf_ring (3)
-but must be called before the buffer ring is used in any other way.
-
-.SH RETURN VALUE
-None
-
-.SH NOTES
-Unless manual setup is needed, it's recommended to use
-.BR io_uring_setup_buf_ring (3)
-as it provides a simpler way to setup a provided buffer ring.
-.
-.SH SEE ALSO
-.BR io_uring_register_buf_ring (3),
-.BR io_uring_setup_buf_ring (3),
-.BR io_uring_buf_ring_add (3)
-.BR io_uring_buf_ring_advance (3),
-.BR io_uring_buf_ring_cq_advance (3)
diff --git a/man/io_uring_buf_ring_init.3.md b/man/io_uring_buf_ring_init.3.md
new file mode 100644
index 00000000..c4f092ac
--- /dev/null
+++ b/man/io_uring_buf_ring_init.3.md
@@ -0,0 +1,45 @@
+.\" Copyright (C) 2022 Dylan Yudaken <dylany@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: June 13, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_buf_ring_init
+---
+
+# NAME
+
+io_uring_buf_ring_init - Initialise a buffer ring
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_buf_ring_init(struct io_uring_buf_ring * br );
+```
+
+# DESCRIPTION
+
+**io_uring_buf_ring_init**(3) initialises *br* so that it is ready to be
+used. It may be called after **io_uring_register_buf_ring**(3) but must
+be called before the buffer ring is used in any other way.
+
+# RETURN VALUE
+
+None
+
+# NOTES
+
+Unless manual setup is needed, it\'s recommended to use
+**io_uring_setup_buf_ring**(3) as it provides a simpler way to setup a
+provided buffer ring.
+
+# SEE ALSO
+
+**io_uring_register_buf_ring**(3), **io_uring_setup_buf_ring**(3),
+**io_uring_buf_ring_add**(3) **io_uring_buf_ring_advance**(3),
+**io_uring_buf_ring_cq_advance**(3)
diff --git a/man/io_uring_buf_ring_mask.3 b/man/io_uring_buf_ring_mask.3
deleted file mode 100644
index 91606630..00000000
--- a/man/io_uring_buf_ring_mask.3
+++ /dev/null
@@ -1,27 +0,0 @@
-.\" Copyright (C) 2022 Dylan Yudaken <dylany@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_buf_ring_mask 3 "June 13, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_buf_ring_mask \- Calculate buffer ring mask size
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_buf_ring_mask(__u32 " ring_entries ");"
-.fi
-.SH DESCRIPTION
-.PP
-.BR io_uring_buf_ring_mask (3)
-calculates the appropriate size mask for a buffer ring.
-.IR ring_entries
-is the ring entries as specified in
-.BR io_uring_register_buf_ring (3) .
-
-.SH RETURN VALUE
-Size mask for the buffer ring.
-
-.SH SEE ALSO
-.BR io_uring_register_buf_ring (3),
-.BR io_uring_buf_ring_add (3)
diff --git a/man/io_uring_buf_ring_mask.3.md b/man/io_uring_buf_ring_mask.3.md
new file mode 100644
index 00000000..e424c2ee
--- /dev/null
+++ b/man/io_uring_buf_ring_mask.3.md
@@ -0,0 +1,37 @@
+.\" Copyright (C) 2022 Dylan Yudaken <dylany@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: June 13, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_buf_ring_mask
+---
+
+# NAME
+
+io_uring_buf_ring_mask - Calculate buffer ring mask size
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_buf_ring_mask(__u32 ring_entries );
+```
+
+# DESCRIPTION
+
+**io_uring_buf_ring_mask**(3) calculates the appropriate size mask for a
+buffer ring. *ring_entries* is the ring entries as specified in
+**io_uring_register_buf_ring**(3)**.**
+
+# RETURN VALUE
+
+Size mask for the buffer ring.
+
+# SEE ALSO
+
+**io_uring_register_buf_ring**(3), **io_uring_buf_ring_add**(3)
diff --git a/man/io_uring_cancelation.7 b/man/io_uring_cancelation.7
deleted file mode 100644
index f74bed20..00000000
--- a/man/io_uring_cancelation.7
+++ /dev/null
@@ -1,324 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_cancelation 7 "January 18, 2025" "Linux" "Linux Programmer's Manual"
-.SH NAME
-io_uring_cancelation \- io_uring request cancelation overview
-.SH DESCRIPTION
-io_uring provides mechanisms to cancel in-flight requests before they
-complete naturally. This is useful for implementing timeouts, handling
-connection drops, closing connections that go away, or when a request is no
-longer needed.
-.SS Why cancel requests?
-Common scenarios requiring cancelation:
-.IP \(bu 2
-.B Timeouts:
-Cancel a read or accept that has been pending too long
-.IP \(bu
-.B Connection management:
-Cancel pending operations when a connection is closed
-.IP \(bu
-.B Resource cleanup:
-Cancel operations on a file descriptor being closed
-.IP \(bu
-.B Multishot termination:
-Stop a multishot operation that is no longer needed
-.SS Basic cancelation
-The primary cancelation mechanism is
-.B IORING_OP_ASYNC_CANCEL
-(set up with
-.BR io_uring_prep_cancel (3)
-or related functions). By default, it cancels a request matching a
-specific
-.IR user_data :
-.PP
-.in +4n
-.EX
-/* Submit a read with user_data = 1234 */
-sqe = io_uring_get_sqe(ring);
-io_uring_prep_read(sqe, fd, buf, len, 0);
-io_uring_sqe_set_data64(sqe, 1234);
-io_uring_submit(ring);
-
-/* Later, cancel it */
-sqe = io_uring_get_sqe(ring);
-io_uring_prep_cancel64(sqe, 1234, 0);
-io_uring_submit(ring);
-.EE
-.in
-.SS Cancelation results
-When a cancelation is submitted, two CQEs are generated:
-.PP
-.B The canceled request's CQE:
-.RS 4
-.IP \(bu 2
-.I res
-is set to
-.B -ECANCELED
-(or occasionally
-.B -EINTR
-if the operation was already in progress)
-.IP \(bu
-The
-.I user_data
-identifies which request was canceled
-.RE
-.PP
-.B The cancel request's CQE:
-.RS 4
-.IP \(bu 2
-.I res
-is 0 on success (request was found and canceled)
-.IP \(bu
-.I res
-is
-.B -ENOENT
-if no matching request was found
-.IP \(bu
-.I res
-is
-.B -EALREADY
-if the request was found but already completing
-.RE
-.PP
-The order of these CQEs is not guaranteed. The application may receive
-the cancel CQE before or after the canceled request's CQE.
-.SS Cancelation flags
-Various flags modify cancelation behavior:
-.PP
-.B IORING_ASYNC_CANCEL_ALL
-.RS 4
-Cancel all matching requests, not just the first one found. The cancel
-CQE's
-.I res
-indicates how many requests were canceled.
-.RE
-.PP
-.B IORING_ASYNC_CANCEL_FD
-.RS 4
-Match requests by file descriptor instead of
-.IR user_data .
-Cancels requests operating on the specified fd:
-.PP
-.in +4n
-.EX
-io_uring_prep_cancel_fd(sqe, fd, IORING_ASYNC_CANCEL_FD);
-.EE
-.in
-.RE
-.PP
-.B IORING_ASYNC_CANCEL_ANY
-.RS 4
-Cancel any single request, ignoring
-.I user_data
-matching. Useful for draining a ring of all pending requests when
-combined with
-.BR IORING_ASYNC_CANCEL_ALL .
-.RE
-.PP
-.B IORING_ASYNC_CANCEL_FD_FIXED
-.RS 4
-The file descriptor is a fixed file (registered file index) rather
-than a regular fd.
-.RE
-.PP
-Flags can be combined:
-.PP
-.in +4n
-.EX
-/* Cancel all requests on a specific fd */
-io_uring_prep_cancel_fd(sqe, fd,
- IORING_ASYNC_CANCEL_FD | IORING_ASYNC_CANCEL_ALL);
-
-/* Cancel all pending requests in the ring */
-io_uring_prep_cancel(sqe, NULL,
- IORING_ASYNC_CANCEL_ANY | IORING_ASYNC_CANCEL_ALL);
-.EE
-.in
-.SS Race conditions
-Cancelation is inherently racy. Between submitting the cancel request
-and the kernel processing it:
-.IP \(bu 2
-The target request may complete successfully
-.IP \(bu
-The target request may fail for another reason
-.IP \(bu
-The target request may already be in a non-cancelable state
-.PP
-Applications must handle these cases:
-.PP
-.in +4n
-.EX
-io_uring_wait_cqe(ring, &cqe);
-
-if (cqe->user_data == cancel_user_data) {
- /* This is the cancel operation's result */
- if (cqe->res == -ENOENT) {
- /* Request already completed or not found */
- } else if (cqe->res == -EALREADY) {
- /* Request was found but completing */
- } else if (cqe->res >= 0) {
- /* Successfully canceled res requests */
- }
-} else {
- /* This is the original request's result */
- if (cqe->res == -ECANCELED) {
- /* Request was canceled */
- } else {
- /* Request completed normally (or with error) */
- }
-}
-.EE
-.in
-.SS Link timeouts
-For timing out a single operation, link timeouts are often simpler
-than explicit cancelation. See
-.BR io_uring_linked_requests (7)
-for details:
-.PP
-.in +4n
-.EX
-sqe = io_uring_get_sqe(ring);
-io_uring_prep_read(sqe, fd, buf, len, 0);
-sqe->flags |= IOSQE_IO_LINK;
-
-sqe = io_uring_get_sqe(ring);
-io_uring_prep_link_timeout(sqe, &timeout, 0);
-.EE
-.in
-.PP
-The kernel handles the cancelation automatically if the timeout
-expires.
-.SS Canceling multishot requests
-Multishot requests (see
-.BR io_uring_multishot (7))
-continue generating completions until canceled or an error occurs.
-To stop a multishot request:
-.PP
-.in +4n
-.EX
-/* Cancel a multishot accept */
-io_uring_prep_cancel64(sqe, accept_user_data, 0);
-.EE
-.in
-.PP
-After cancelation:
-.IP \(bu 2
-The multishot generates a final CQE with
-.B -ECANCELED
-.IP \(bu
-The
-.B IORING_CQE_F_MORE
-flag is not set on this final CQE
-.IP \(bu
-The cancel CQE indicates success
-.SS Canceling by file descriptor
-When a file descriptor is closed (either via
-.BR close (2)
-or
-.BR IORING_OP_CLOSE ),
-pending requests operating on that fd are
-.B not
-automatically canceled. This differs from synchronous I/O behavior
-and is a common source of confusion.
-
-In synchronous I/O, closing a file descriptor is typically the last
-reference to the underlying file, so the close completes any pending
-operations. However, io_uring holds its own reference to the file for
-each pending request. Closing the application's fd does not release
-these references \(em the pending read, recv, or other operation
-continues to hold a reference and will not automatically complete or
-fail.
-
-If an application expects a pending read on an fd to post a completion
-when the fd is closed, that will not happen. The request must be
-explicitly canceled:
-.PP
-.in +4n
-.EX
-/* Cancel all operations on fd before closing */
-sqe = io_uring_get_sqe(ring);
-io_uring_prep_cancel_fd(sqe, fd,
- IORING_ASYNC_CANCEL_FD | IORING_ASYNC_CANCEL_ALL);
-io_uring_submit(ring);
-
-/* Wait for cancelations, then close */
-.EE
-.in
-.SS Shutdown cancelation
-When an io_uring instance is closed (via
-.BR io_uring_queue_exit (3)
-or closing the ring file descriptor), all pending requests are
-automatically canceled. Manual cancelation before shutdown is not
-required.
-
-However, if the application needs to ensure all requests are completed
-before proceeding (e.g., to process their results or free associated
-resources), explicit cancelation can be used:
-.PP
-.in +4n
-.EX
-/* Cancel everything */
-sqe = io_uring_get_sqe(ring);
-io_uring_prep_cancel(sqe, NULL,
- IORING_ASYNC_CANCEL_ANY | IORING_ASYNC_CANCEL_ALL);
-io_uring_submit(ring);
-
-/* Wait for all CQEs */
-while (pending_count > 0) {
- io_uring_wait_cqe(ring, &cqe);
- pending_count--;
- io_uring_cqe_seen(ring, cqe);
-}
-.EE
-.in
-.SS Synchronous cancelation
-For cases where the application needs to cancel requests and wait for
-the cancelation to complete in a single blocking call,
-.BR io_uring_register_sync_cancel (3)
-provides a synchronous interface:
-.PP
-.in +4n
-.EX
-struct io_uring_sync_cancel_reg reg = {
- .addr = user_data,
- .timeout.tv_sec = 5,
-};
-
-ret = io_uring_register_sync_cancel(ring, ®);
-.EE
-.in
-.PP
-This blocks until the matching request is canceled or the timeout
-expires. It is useful when the application cannot easily integrate
-asynchronous cancelation into its event loop.
-.SH NOTES
-.IP \(bu 2
-Not all operations are cancelable. Operations that have already
-been submitted to hardware (e.g., disk I/O in progress) typically
-cannot be canceled.
-.IP \(bu
-Cancelation is asynchronous. The cancel request itself may take
-time to complete.
-.IP \(bu
-When using
-.BR IORING_ASYNC_CANCEL_ALL ,
-the cancel CQE's
-.I res
-field contains the count of canceled requests.
-.IP \(bu
-Fixed files can be canceled using
-.B IORING_ASYNC_CANCEL_FD_FIXED
-with the file index instead of a regular fd.
-.IP \(bu
-Poll operations and multishot requests are generally good candidates
-for cancelation. Completed disk I/O is not.
-.SH SEE ALSO
-.BR io_uring (7),
-.BR io_uring_linked_requests (7),
-.BR io_uring_multishot (7),
-.BR io_uring_prep_cancel (3),
-.BR io_uring_prep_cancel64 (3),
-.BR io_uring_prep_cancel_fd (3),
-.BR io_uring_prep_link_timeout (3),
-.BR io_uring_register_sync_cancel (3)
diff --git a/man/io_uring_cancelation.7.md b/man/io_uring_cancelation.7.md
new file mode 100644
index 00000000..9a3fe8cb
--- /dev/null
+++ b/man/io_uring_cancelation.7.md
@@ -0,0 +1,288 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 18, 2025
+footer: Linux
+header: Linux Programmer\'s Manual
+section: 7
+title: io_uring_cancelation
+---
+
+# NAME
+
+io_uring_cancelation - io_uring request cancelation overview
+
+# DESCRIPTION
+
+io_uring provides mechanisms to cancel in-flight requests before they
+complete naturally. This is useful for implementing timeouts, handling
+connection drops, closing connections that go away, or when a request is
+no longer needed.
+
+## Why cancel requests?
+
+Common scenarios requiring cancelation:
+
+- **Timeouts:** Cancel a read or accept that has been pending too long
+
+- **Connection management:** Cancel pending operations when a connection
+ is closed
+
+- **Resource cleanup:** Cancel operations on a file descriptor being
+ closed
+
+- **Multishot termination:** Stop a multishot operation that is no
+ longer needed
+
+## Basic cancelation
+
+The primary cancelation mechanism is **IORING_OP_ASYNC_CANCEL** (set up
+with **io_uring_prep_cancel**(3) or related functions). By default, it
+cancels a request matching a specific *user_data*:
+
+``` text
+/* Submit a read with user_data = 1234 */
+sqe = io_uring_get_sqe(ring);
+io_uring_prep_read(sqe, fd, buf, len, 0);
+io_uring_sqe_set_data64(sqe, 1234);
+io_uring_submit(ring);
+
+/* Later, cancel it */
+sqe = io_uring_get_sqe(ring);
+io_uring_prep_cancel64(sqe, 1234, 0);
+io_uring_submit(ring);
+```
+
+## Cancelation results
+
+When a cancelation is submitted, two CQEs are generated:
+
+**The canceled request\'s CQE:**
+
+> - *res* is set to **-ECANCELED** (or occasionally **-EINTR** if the
+> operation was already in progress)
+>
+> - The *user_data* identifies which request was canceled
+
+**The cancel request\'s CQE:**
+
+> - *res* is 0 on success (request was found and canceled)
+>
+> - *res* is **-ENOENT** if no matching request was found
+>
+> - *res* is **-EALREADY** if the request was found but already
+> completing
+
+The order of these CQEs is not guaranteed. The application may receive
+the cancel CQE before or after the canceled request\'s CQE.
+
+## Cancelation flags
+
+Various flags modify cancelation behavior:
+
+**IORING_ASYNC_CANCEL_ALL**
+
+> Cancel all matching requests, not just the first one found. The cancel
+> CQE\'s *res* indicates how many requests were canceled.
+
+**IORING_ASYNC_CANCEL_FD**
+
+> Match requests by file descriptor instead of *user_data*. Cancels
+> requests operating on the specified fd:
+>
+> ``` text
+> io_uring_prep_cancel_fd(sqe, fd, IORING_ASYNC_CANCEL_FD);
+> ```
+
+**IORING_ASYNC_CANCEL_ANY**
+
+> Cancel any single request, ignoring *user_data* matching. Useful for
+> draining a ring of all pending requests when combined with
+> **IORING_ASYNC_CANCEL_ALL**.
+
+**IORING_ASYNC_CANCEL_FD_FIXED**
+
+> The file descriptor is a fixed file (registered file index) rather
+> than a regular fd.
+
+Flags can be combined:
+
+``` text
+/* Cancel all requests on a specific fd */
+io_uring_prep_cancel_fd(sqe, fd,
+ IORING_ASYNC_CANCEL_FD | IORING_ASYNC_CANCEL_ALL);
+
+/* Cancel all pending requests in the ring */
+io_uring_prep_cancel(sqe, NULL,
+ IORING_ASYNC_CANCEL_ANY | IORING_ASYNC_CANCEL_ALL);
+```
+
+## Race conditions
+
+Cancelation is inherently racy. Between submitting the cancel request
+and the kernel processing it:
+
+- The target request may complete successfully
+
+- The target request may fail for another reason
+
+- The target request may already be in a non-cancelable state
+
+Applications must handle these cases:
+
+``` text
+io_uring_wait_cqe(ring, &cqe);
+
+if (cqe->user_data == cancel_user_data) {
+ /* This is the cancel operation's result */
+ if (cqe->res == -ENOENT) {
+ /* Request already completed or not found */
+ } else if (cqe->res == -EALREADY) {
+ /* Request was found but completing */
+ } else if (cqe->res >= 0) {
+ /* Successfully canceled res requests */
+ }
+} else {
+ /* This is the original request's result */
+ if (cqe->res == -ECANCELED) {
+ /* Request was canceled */
+ } else {
+ /* Request completed normally (or with error) */
+ }
+}
+```
+
+## Link timeouts
+
+For timing out a single operation, link timeouts are often simpler than
+explicit cancelation. See **io_uring_linked_requests**(7) for details:
+
+``` text
+sqe = io_uring_get_sqe(ring);
+io_uring_prep_read(sqe, fd, buf, len, 0);
+sqe->flags |= IOSQE_IO_LINK;
+
+sqe = io_uring_get_sqe(ring);
+io_uring_prep_link_timeout(sqe, &timeout, 0);
+```
+
+The kernel handles the cancelation automatically if the timeout expires.
+
+## Canceling multishot requests
+
+Multishot requests (see **io_uring_multishot**(7)) continue generating
+completions until canceled or an error occurs. To stop a multishot
+request:
+
+``` text
+/* Cancel a multishot accept */
+io_uring_prep_cancel64(sqe, accept_user_data, 0);
+```
+
+After cancelation:
+
+- The multishot generates a final CQE with **-ECANCELED**
+
+- The **IORING_CQE_F_MORE** flag is not set on this final CQE
+
+- The cancel CQE indicates success
+
+## Canceling by file descriptor
+
+When a file descriptor is closed (either via **close**(2) or
+**IORING_OP_CLOSE**), pending requests operating on that fd are **not**
+automatically canceled. This differs from synchronous I/O behavior and
+is a common source of confusion.
+
+In synchronous I/O, closing a file descriptor is typically the last
+reference to the underlying file, so the close completes any pending
+operations. However, io_uring holds its own reference to the file for
+each pending request. Closing the application\'s fd does not release
+these references --- the pending read, recv, or other operation
+continues to hold a reference and will not automatically complete or
+fail.
+
+If an application expects a pending read on an fd to post a completion
+when the fd is closed, that will not happen. The request must be
+explicitly canceled:
+
+``` text
+/* Cancel all operations on fd before closing */
+sqe = io_uring_get_sqe(ring);
+io_uring_prep_cancel_fd(sqe, fd,
+ IORING_ASYNC_CANCEL_FD | IORING_ASYNC_CANCEL_ALL);
+io_uring_submit(ring);
+
+/* Wait for cancelations, then close */
+```
+
+## Shutdown cancelation
+
+When an io_uring instance is closed (via **io_uring_queue_exit**(3) or
+closing the ring file descriptor), all pending requests are
+automatically canceled. Manual cancelation before shutdown is not
+required.
+
+However, if the application needs to ensure all requests are completed
+before proceeding (e.g., to process their results or free associated
+resources), explicit cancelation can be used:
+
+``` text
+/* Cancel everything */
+sqe = io_uring_get_sqe(ring);
+io_uring_prep_cancel(sqe, NULL,
+ IORING_ASYNC_CANCEL_ANY | IORING_ASYNC_CANCEL_ALL);
+io_uring_submit(ring);
+
+/* Wait for all CQEs */
+while (pending_count > 0) {
+ io_uring_wait_cqe(ring, &cqe);
+ pending_count--;
+ io_uring_cqe_seen(ring, cqe);
+}
+```
+
+## Synchronous cancelation
+
+For cases where the application needs to cancel requests and wait for
+the cancelation to complete in a single blocking call,
+**io_uring_register_sync_cancel**(3) provides a synchronous interface:
+
+``` text
+struct io_uring_sync_cancel_reg reg = {
+ .addr = user_data,
+ .timeout.tv_sec = 5,
+};
+
+ret = io_uring_register_sync_cancel(ring, ®);
+```
+
+This blocks until the matching request is canceled or the timeout
+expires. It is useful when the application cannot easily integrate
+asynchronous cancelation into its event loop.
+
+# NOTES
+
+- Not all operations are cancelable. Operations that have already been
+ submitted to hardware (e.g., disk I/O in progress) typically cannot be
+ canceled.
+
+- Cancelation is asynchronous. The cancel request itself may take time
+ to complete.
+
+- When using **IORING_ASYNC_CANCEL_ALL**, the cancel CQE\'s *res* field
+ contains the count of canceled requests.
+
+- Fixed files can be canceled using **IORING_ASYNC_CANCEL_FD_FIXED**
+ with the file index instead of a regular fd.
+
+- Poll operations and multishot requests are generally good candidates
+ for cancelation. Completed disk I/O is not.
+
+# SEE ALSO
+
+**io_uring**(7), **io_uring_linked_requests**(7),
+**io_uring_multishot**(7), **io_uring_prep_cancel**(3),
+**io_uring_prep_cancel64**(3), **io_uring_prep_cancel_fd**(3),
+**io_uring_prep_link_timeout**(3), **io_uring_register_sync_cancel**(3)
diff --git a/man/io_uring_check_version.3 b/man/io_uring_check_version.3
deleted file mode 100644
index b7d771ab..00000000
--- a/man/io_uring_check_version.3
+++ /dev/null
@@ -1,72 +0,0 @@
-.\" Copyright (C) 2022 Christian Hergert <chergert@redhat.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_check_version 3 "December 1, 2022" "liburing-2.4" "liburing Manual"
-.SH NAME
-io_uring_check_version \- functions and macros to check the liburing version
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "bool io_uring_check_version(int " major ", int " minor ");"
-.BI "IO_URING_CHECK_VERSION(" major ", " minor ");"
-.PP
-.BI "int io_uring_major_version(void);"
-.BI "IO_URING_VERSION_MAJOR;"
-.PP
-.BI "int io_uring_minor_version(void);"
-.BI "IO_URING_VERSION_MINOR;"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_check_version (3)
-function returns
-.I false
-if the liburing library loaded by the dynamic linker is greater-than
-or equal-to the
-.I major
-and
-.I minor
-numbers provided.
-
-.PP
-The
-.BR IO_URING_CHECK_VERSION (3)
-macro returns
-.I 0
-if the liburing library being compiled against is greater-than or equal-to the
-.I major
-and
-.I minor
-numbers provided.
-
-.PP
-The
-.BR io_uring_major_version (3)
-function returns the
-.I major
-version number of the liburing library loaded by the dynamic linker.
-
-.PP
-The
-.BR IO_URING_VERSION_MAJOR (3)
-macro returns the
-.I major
-version number of the liburing library being compiled against.
-
-.PP
-The
-.BR io_uring_minor_version (3)
-function returns the
-.I minor
-version number of the liburing library loaded by the dynamic linker.
-
-.PP
-The
-.BR IO_URING_VERSION_MINOR (3)
-macro returns the
-.I minor
-version number of the liburing library being compiled against.
-
diff --git a/man/io_uring_check_version.3.md b/man/io_uring_check_version.3.md
new file mode 100644
index 00000000..cdfb45b4
--- /dev/null
+++ b/man/io_uring_check_version.3.md
@@ -0,0 +1,53 @@
+.\" Copyright (C) 2022 Christian Hergert <chergert@redhat.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: December 1, 2022
+footer: liburing-2.4
+header: liburing Manual
+section: 3
+title: io_uring_check_version
+---
+
+# NAME
+
+io_uring_check_version - functions and macros to check the liburing
+version
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ bool io_uring_check_version(int major , int minor );
+ IO_URING_CHECK_VERSION( major , minor );
+
+ int io_uring_major_version(void);
+ IO_URING_VERSION_MAJOR;
+
+ int io_uring_minor_version(void);
+ IO_URING_VERSION_MINOR;
+```
+
+# DESCRIPTION
+
+The **io_uring_check_version**(3) function returns *false* if the
+liburing library loaded by the dynamic linker is greater-than or
+equal-to the *major* and *minor* numbers provided.
+
+The **IO_URING_CHECK_VERSION**(3) macro returns *0* if the liburing
+library being compiled against is greater-than or equal-to the *major*
+and *minor* numbers provided.
+
+The **io_uring_major_version**(3) function returns the *major* version
+number of the liburing library loaded by the dynamic linker.
+
+The **IO_URING_VERSION_MAJOR**(3) macro returns the *major* version
+number of the liburing library being compiled against.
+
+The **io_uring_minor_version**(3) function returns the *minor* version
+number of the liburing library loaded by the dynamic linker.
+
+The **IO_URING_VERSION_MINOR**(3) macro returns the *minor* version
+number of the liburing library being compiled against.
diff --git a/man/io_uring_clone_buffers.3 b/man/io_uring_clone_buffers.3
deleted file mode 100644
index 4fd9c241..00000000
--- a/man/io_uring_clone_buffers.3
+++ /dev/null
@@ -1,165 +0,0 @@
-.\" Copyright (C) 2024 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_clone_buffers 3 "September 12, 2024" "liburing-2.9" "liburing Manual"
-.SH NAME
-io_uring_clone_buffers \- Clones registered buffers between rings
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_clone_buffers(struct io_uring *" dst ","
-.BI " struct io_uring * " src ");"
-.PP
-.BI "int __io_uring_clone_buffers(struct io_uring *" dst ","
-.BI " struct io_uring * " src ","
-.BI " unsigned int " flags ");"
-.PP
-.BI "int io_uring_clone_buffers_offset(struct io_uring *" dst ","
-.BI " struct io_uring * " src ","
-.BI " unsigned int " dst_off ","
-.BI " unsigned int " src_off ","
-.BI " unsigned int " nr ","
-.BI " unsigned int " flags ");"
-.PP
-.BI "int __io_uring_clone_buffers_offset(struct io_uring *" dst ","
-.BI " struct io_uring * " src ","
-.BI " unsigned int " dst_off ","
-.BI " unsigned int " src_off ","
-.BI " unsigned int " nr ","
-.BI " unsigned int " flags ");"
-.PP
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_clone_buffers (3)
-function clones registered buffers from the ring indicated by
-.IR src
-to the ring indicated by
-.IR dst .
-Upon successful completion of this operation,
-.IR src
-and
-.IR dst
-will have the same set of registered buffers. This operation is identical to
-performing a
-.BR io_uring_register_buffers (3)
-operation on the
-.IR dst
-ring, if the
-.IR src
-ring previously had that same buffer registration operating done.
-
-The
-.IR dst
-ring must not have any buffers currently registered. If buffers are currently
-registered on the destination ring, they must be unregistered with
-.BR io_uring_unregister_buffers (3)
-first.
-
-For
-.BR __io_uring_clone_buffers (3) ,
-the only difference is that it takes a
-.IR flags
-argument. By default, if the destination ring has a registered file descriptor
-through
-.BR io_uring_register_ring_fd (3)
-AND the calling application is not the thread that registered that ring, then
-the kernel doesn't know how to look up the destination. This is problematic
-as
-.BR io_uring_clone_buffers (3)
-defaults to using the registered index if the destination is setup as such.
-Use
-.BR __io_uring_clone_buffers (3)
-which doesn't set
-.B IORING_REGISTER_SRC_REGISTERED
-by default. This requires the application to still have the original ring file
-descriptor open. See below for the flag definition.
-
-Available since kernel 6.12.
-
-The
-.BR io_uring_clone_buffers_offset (3)
-function also clones buffers from the
-.IR src
-ring to the
-.IR dst
-ring, however it supports cloning only a subset of the buffers, where
-.BR io_uring_clone_buffers (3)
-always clones all of them.
-.IR dst_off
-indicates at what offset cloning should start in the destination,
-.IR src_off
-indicates at what offset cloning should start in the source, and
-.IR nr
-indicates how many buffers to clone at the given offset. If both
-.IR dst_off ,
-.IR src_off ,
-and
-.IR nr
-are given as
-.B 0 ,
-then
-.BR io_uring_clone_buffers_offset (3)
-performs the same action as
-.BR io_uring_clone_buffers (3) .
-
-While
-.BR io_uring_clone_buffers_offset (3)
-sets
-.B IORING_REGISTER_SRC_REGISTERED
-by default, the
-.BR __io_uring_clone_buffers_offset (3)
-does not. See the explanation for
-.BR __io_uring_clone_buffers (3)
-for details.
-
-.IR flags
-may be set to the following value:
-.TP
-.B IORING_REGISTER_SRC_REGISTERED
-If the source ring is registered AND the calling thread is the one that
-originally registered its ring fd, then this flag may be set to lookup the
-registered index rather than use the normal file descriptor. If the normal
-file descriptor wasn't closed after registering it, there's no need to set
-this flag.
-.TP
-.B IORING_REGISTER_DST_REPLACE
-If set, cloning may happen for a destination ring that already has a buffer
-table assigned. In that case, existing nodes that overlap with the specified
-range will be released and replaced.
-.PP
-
-Available since kernel 6.13.
-
-.SH NOTES
-The source and target ring must shared address spaces, and hence internal
-kernel accounting.
-.SH RETURN VALUE
-On success
-.BR io_uring_clone_buffers (3)
-and
-.BR io_uring_clone_buffers_offset (3)
-return 0.
-On failure, they returns
-.BR -errno ,
-specifically
-.TP
-.B -EBUSY
-The destination ring already has buffers registered, and
-.B IORING_REGISTER_DST_REPLACE
-wasn't set.
-.TP
-.B -ENOMEM
-The kernel ran out of memory.
-.TP
-.B -ENXIO
-The source ring doesn't have any buffers registered.
-.SH SEE ALSO
-.BR io_uring_register (2),
-.BR io_uring_unregister_buffers (3),
-.BR io_uring_register_buffers (3),
-.BR io_uring_prep_read_fixed (3),
-.BR io_uring_prep_write_fixed (3)
diff --git a/man/io_uring_clone_buffers.3.md b/man/io_uring_clone_buffers.3.md
new file mode 100644
index 00000000..36524885
--- /dev/null
+++ b/man/io_uring_clone_buffers.3.md
@@ -0,0 +1,133 @@
+.\" Copyright (C) 2024 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: September 12, 2024
+footer: liburing-2.9
+header: liburing Manual
+section: 3
+title: io_uring_clone_buffers
+---
+
+# NAME
+
+io_uring_clone_buffers - Clones registered buffers between rings
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_clone_buffers(struct io_uring * dst ,
+ struct io_uring * src );
+
+ int __io_uring_clone_buffers(struct io_uring * dst ,
+ struct io_uring * src ,
+ unsigned int flags );
+
+ int io_uring_clone_buffers_offset(struct io_uring * dst ,
+ struct io_uring * src ,
+ unsigned int dst_off ,
+ unsigned int src_off ,
+ unsigned int nr ,
+ unsigned int flags );
+
+ int __io_uring_clone_buffers_offset(struct io_uring * dst ,
+ struct io_uring * src ,
+ unsigned int dst_off ,
+ unsigned int src_off ,
+ unsigned int nr ,
+ unsigned int flags );
+```
+
+# DESCRIPTION
+
+The **io_uring_clone_buffers**(3) function clones registered buffers
+from the ring indicated by *src* to the ring indicated by *dst*. Upon
+successful completion of this operation, *src* and *dst* will have the
+same set of registered buffers. This operation is identical to
+performing a **io_uring_register_buffers**(3) operation on the *dst*
+ring, if the *src* ring previously had that same buffer registration
+operating done.
+
+The *dst* ring must not have any buffers currently registered. If
+buffers are currently registered on the destination ring, they must be
+unregistered with **io_uring_unregister_buffers**(3) first.
+
+For **\_\_io_uring_clone_buffers**(3)**,** the only difference is that
+it takes a *flags* argument. By default, if the destination ring has a
+registered file descriptor through **io_uring_register_ring_fd**(3) AND
+the calling application is not the thread that registered that ring,
+then the kernel doesn\'t know how to look up the destination. This is
+problematic as **io_uring_clone_buffers**(3) defaults to using the
+registered index if the destination is setup as such. Use
+**\_\_io_uring_clone_buffers**(3) which doesn\'t set
+**IORING_REGISTER_SRC_REGISTERED** by default. This requires the
+application to still have the original ring file descriptor open. See
+below for the flag definition.
+
+Available since kernel 6.12.
+
+The **io_uring_clone_buffers_offset**(3) function also clones buffers
+from the *src* ring to the *dst* ring, however it supports cloning only
+a subset of the buffers, where **io_uring_clone_buffers**(3) always
+clones all of them. *dst_off* indicates at what offset cloning should
+start in the destination, *src_off* indicates at what offset cloning
+should start in the source, and *nr* indicates how many buffers to clone
+at the given offset. If both *dst_off*, *src_off*, and *nr* are given as
+**0 ,** then **io_uring_clone_buffers_offset**(3) performs the same
+action as **io_uring_clone_buffers**(3)**.**
+
+While **io_uring_clone_buffers_offset**(3) sets
+**IORING_REGISTER_SRC_REGISTERED** by default, the
+**\_\_io_uring_clone_buffers_offset**(3) does not. See the explanation
+for **\_\_io_uring_clone_buffers**(3) for details.
+
+*flags* may be set to the following value:
+
+**IORING_REGISTER_SRC_REGISTERED**
+
+: If the source ring is registered AND the calling thread is the one
+ that originally registered its ring fd, then this flag may be set to
+ lookup the registered index rather than use the normal file
+ descriptor. If the normal file descriptor wasn\'t closed after
+ registering it, there\'s no need to set this flag.
+
+**IORING_REGISTER_DST_REPLACE**
+
+: If set, cloning may happen for a destination ring that already has a
+ buffer table assigned. In that case, existing nodes that overlap with
+ the specified range will be released and replaced.
+
+Available since kernel 6.13.
+
+# NOTES
+
+The source and target ring must shared address spaces, and hence
+internal kernel accounting.
+
+# RETURN VALUE
+
+On success **io_uring_clone_buffers**(3) and
+**io_uring_clone_buffers_offset**(3) return 0. On failure, they returns
+**-errno**, specifically
+
+**-EBUSY**
+
+: The destination ring already has buffers registered, and
+ **IORING_REGISTER_DST_REPLACE** wasn\'t set.
+
+**-ENOMEM**
+
+: The kernel ran out of memory.
+
+**-ENXIO**
+
+: The source ring doesn\'t have any buffers registered.
+
+# SEE ALSO
+
+**io_uring_register**(2), **io_uring_unregister_buffers**(3),
+**io_uring_register_buffers**(3), **io_uring_prep_read_fixed**(3),
+**io_uring_prep_write_fixed**(3)
diff --git a/man/io_uring_close_ring_fd.3 b/man/io_uring_close_ring_fd.3
deleted file mode 100644
index b5963c9d..00000000
--- a/man/io_uring_close_ring_fd.3
+++ /dev/null
@@ -1,43 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\" Copyright (C) 2022 Josh Triplett <josh@joshtriplett.org>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_close_ring_fd 3 "September 25, 2022" "liburing-2.4" "liburing Manual"
-.SH NAME
-io_uring_close_ring_fd \- close a ring file descriptor and use it only via registered index
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_close_ring_fd(struct io_uring *" ring ");"
-.fi
-.SH DESCRIPTION
-.PP
-.BR io_uring_close_ring_fd (3)
-closes the ring file descriptor, which must have been previously registered.
-The file will remain open, but accessible only via the registered index, not
-via any file descriptor. Subsequent liburing calls will continue to work, using
-the registered ring fd.
-
-The kernel must support
-.BR IORING_FEAT_REG_REG_RING .
-
-Libraries that must avoid disrupting their users' uses of file descriptors, and
-must continue working even in the face of
-.BR close_range (2)
-and similar, can use
-.BR io_uring_close_ring_fd (3)
-to work with liburing without having any open file descriptor.
-
-.SH NOTES
-Each thread that wants to make use of io_uring must register the fd. A library
-that may get called from arbitrary theads may need to detect when it gets
-called on a previously unseen thread and create and register a ring for that
-thread.
-.SH RETURN VALUE
-Returns 1 on success, or
-.BR -errno
-on error.
-.SH SEE ALSO
-.BR io_uring_register_ring_fd (3)
diff --git a/man/io_uring_close_ring_fd.3.md b/man/io_uring_close_ring_fd.3.md
new file mode 100644
index 00000000..565c9271
--- /dev/null
+++ b/man/io_uring_close_ring_fd.3.md
@@ -0,0 +1,55 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\" Copyright (C) 2022 Josh Triplett <josh@joshtriplett.org>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: September 25, 2022
+footer: liburing-2.4
+header: liburing Manual
+section: 3
+title: io_uring_close_ring_fd
+---
+
+# NAME
+
+io_uring_close_ring_fd - close a ring file descriptor and use it only
+via registered index
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_close_ring_fd(struct io_uring * ring );
+```
+
+# DESCRIPTION
+
+**io_uring_close_ring_fd**(3) closes the ring file descriptor, which
+must have been previously registered. The file will remain open, but
+accessible only via the registered index, not via any file descriptor.
+Subsequent liburing calls will continue to work, using the registered
+ring fd.
+
+The kernel must support **IORING_FEAT_REG_REG_RING**.
+
+Libraries that must avoid disrupting their users\' uses of file
+descriptors, and must continue working even in the face of
+**close_range**(2) and similar, can use **io_uring_close_ring_fd**(3) to
+work with liburing without having any open file descriptor.
+
+# NOTES
+
+Each thread that wants to make use of io_uring must register the fd. A
+library that may get called from arbitrary theads may need to detect
+when it gets called on a previously unseen thread and create and
+register a ring for that thread.
+
+# RETURN VALUE
+
+Returns 1 on success, or **-errno** on error.
+
+# SEE ALSO
+
+**io_uring_register_ring_fd**(3)
diff --git a/man/io_uring_cq_advance.3 b/man/io_uring_cq_advance.3
deleted file mode 100644
index fae25722..00000000
--- a/man/io_uring_cq_advance.3
+++ /dev/null
@@ -1,49 +0,0 @@
-.\" Copyright (C) 2022 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_cq_advance 3 "January 25, 2022" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_cq_advance \- mark one or more io_uring completion events as consumed
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_cq_advance(struct io_uring *" ring ","
-.BI " unsigned " nr ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_cq_advance (3)
-function marks
-.I nr
-IO completions belonging to the
-.I ring
-param as consumed.
-
-After the caller has submitted a request with
-.BR io_uring_submit (3),
-the application can retrieve the completion with
-.BR io_uring_wait_cqe (3),
-.BR io_uring_peek_cqe (3),
-or any of the other CQE retrieval helpers, and mark it as consumed with
-.BR io_uring_cqe_seen (3).
-
-The function
-.BR io_uring_cqe_seen (3)
-calls the function
-.BR io_uring_cq_advance (3).
-
-Completions must be marked as seen, so their slot can get reused. Failure to do
-so will result in the same completion being returned on the next invocation.
-
-.SH RETURN VALUE
-None
-.SH SEE ALSO
-.BR io_uring_submit (3),
-.BR io_uring_wait_cqe (3),
-.BR io_uring_peek_cqe (3),
-.BR io_uring_wait_cqes (3),
-.BR io_uring_wait_cqe_timeout (3),
-.BR io_uring_cqe_seen (3)
diff --git a/man/io_uring_cq_advance.3.md b/man/io_uring_cq_advance.3.md
new file mode 100644
index 00000000..84b3d353
--- /dev/null
+++ b/man/io_uring_cq_advance.3.md
@@ -0,0 +1,53 @@
+.\" Copyright (C) 2022 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 25, 2022
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_cq_advance
+---
+
+# NAME
+
+io_uring_cq_advance - mark one or more io_uring completion events as
+consumed
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_cq_advance(struct io_uring * ring ,
+ unsigned nr );
+```
+
+# DESCRIPTION
+
+The **io_uring_cq_advance**(3) function marks *nr* IO completions
+belonging to the *ring* param as consumed.
+
+After the caller has submitted a request with **io_uring_submit**(3),
+the application can retrieve the completion with
+**io_uring_wait_cqe**(3), **io_uring_peek_cqe**(3), or any of the other
+CQE retrieval helpers, and mark it as consumed with
+**io_uring_cqe_seen**(3).
+
+The function **io_uring_cqe_seen**(3) calls the function
+**io_uring_cq_advance**(3).
+
+Completions must be marked as seen, so their slot can get reused.
+Failure to do so will result in the same completion being returned on
+the next invocation.
+
+# RETURN VALUE
+
+None
+
+# SEE ALSO
+
+**io_uring_submit**(3), **io_uring_wait_cqe**(3),
+**io_uring_peek_cqe**(3), **io_uring_wait_cqes**(3),
+**io_uring_wait_cqe_timeout**(3), **io_uring_cqe_seen**(3)
diff --git a/man/io_uring_cq_eventfd_enabled.3 b/man/io_uring_cq_eventfd_enabled.3
deleted file mode 100644
index 455a5f51..00000000
--- a/man/io_uring_cq_eventfd_enabled.3
+++ /dev/null
@@ -1,38 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_cq_eventfd_enabled 3 "January 18, 2025" "liburing-2.4" "liburing Manual"
-.SH NAME
-io_uring_cq_eventfd_enabled \- check if eventfd notifications are enabled
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "bool io_uring_cq_eventfd_enabled(const struct io_uring *" ring ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_cq_eventfd_enabled (3)
-function returns whether eventfd notifications are currently enabled for
-the io_uring instance specified by
-.IR ring .
-
-An eventfd can be registered with a ring using
-.BR io_uring_register_eventfd (3)
-or
-.BR io_uring_register_eventfd_async (3).
-Once registered, notifications can be temporarily disabled using
-.BR io_uring_cq_eventfd_toggle (3).
-
-.SH RETURN VALUE
-Returns
-.B true
-if eventfd notifications are enabled, or
-.B false
-if disabled.
-.SH SEE ALSO
-.BR io_uring_register_eventfd (3),
-.BR io_uring_register_eventfd_async (3),
-.BR io_uring_cq_eventfd_toggle (3)
diff --git a/man/io_uring_cq_eventfd_enabled.3.md b/man/io_uring_cq_eventfd_enabled.3.md
new file mode 100644
index 00000000..4aa9b7cc
--- /dev/null
+++ b/man/io_uring_cq_eventfd_enabled.3.md
@@ -0,0 +1,45 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 18, 2025
+footer: liburing-2.4
+header: liburing Manual
+section: 3
+title: io_uring_cq_eventfd_enabled
+---
+
+# NAME
+
+io_uring_cq_eventfd_enabled - check if eventfd notifications are enabled
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ bool io_uring_cq_eventfd_enabled(const struct io_uring * ring );
+```
+
+# DESCRIPTION
+
+The **io_uring_cq_eventfd_enabled**(3) function returns whether eventfd
+notifications are currently enabled for the io_uring instance specified
+by *ring*.
+
+An eventfd can be registered with a ring using
+**io_uring_register_eventfd**(3) or
+**io_uring_register_eventfd_async**(3). Once registered, notifications
+can be temporarily disabled using **io_uring_cq_eventfd_toggle**(3).
+
+# RETURN VALUE
+
+Returns **true** if eventfd notifications are enabled, or **false** if
+disabled.
+
+# SEE ALSO
+
+**io_uring_register_eventfd**(3),
+**io_uring_register_eventfd_async**(3),
+**io_uring_cq_eventfd_toggle**(3)
diff --git a/man/io_uring_cq_eventfd_toggle.3 b/man/io_uring_cq_eventfd_toggle.3
deleted file mode 100644
index 21270607..00000000
--- a/man/io_uring_cq_eventfd_toggle.3
+++ /dev/null
@@ -1,48 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_cq_eventfd_toggle 3 "January 18, 2025" "liburing-2.4" "liburing Manual"
-.SH NAME
-io_uring_cq_eventfd_toggle \- toggle eventfd notifications on or off
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_cq_eventfd_toggle(struct io_uring *" ring ", bool " enabled ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_cq_eventfd_toggle (3)
-function toggles eventfd notifications for the io_uring instance specified by
-.IR ring .
-If
-.I enabled
-is
-.BR true ,
-eventfd notifications are enabled. If
-.I enabled
-is
-.BR false ,
-they are disabled.
-
-An eventfd must first be registered with the ring using
-.BR io_uring_register_eventfd (3)
-or
-.BR io_uring_register_eventfd_async (3)
-before this function can be used.
-
-This can be useful when the application wants to temporarily stop receiving
-eventfd notifications, for example during a batch processing phase.
-
-.SH RETURN VALUE
-Returns 0 on success. On error, a negative errno value is returned:
-.TP
-.B -EOPNOTSUPP
-The kernel does not support toggling eventfd notifications, or no eventfd
-is registered.
-.SH SEE ALSO
-.BR io_uring_register_eventfd (3),
-.BR io_uring_register_eventfd_async (3),
-.BR io_uring_cq_eventfd_enabled (3)
diff --git a/man/io_uring_cq_eventfd_toggle.3.md b/man/io_uring_cq_eventfd_toggle.3.md
new file mode 100644
index 00000000..6aaf316e
--- /dev/null
+++ b/man/io_uring_cq_eventfd_toggle.3.md
@@ -0,0 +1,53 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 18, 2025
+footer: liburing-2.4
+header: liburing Manual
+section: 3
+title: io_uring_cq_eventfd_toggle
+---
+
+# NAME
+
+io_uring_cq_eventfd_toggle - toggle eventfd notifications on or off
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_cq_eventfd_toggle(struct io_uring * ring , bool enabled );
+```
+
+# DESCRIPTION
+
+The **io_uring_cq_eventfd_toggle**(3) function toggles eventfd
+notifications for the io_uring instance specified by *ring*. If
+*enabled* is **true**, eventfd notifications are enabled. If *enabled*
+is **false**, they are disabled.
+
+An eventfd must first be registered with the ring using
+**io_uring_register_eventfd**(3) or
+**io_uring_register_eventfd_async**(3) before this function can be used.
+
+This can be useful when the application wants to temporarily stop
+receiving eventfd notifications, for example during a batch processing
+phase.
+
+# RETURN VALUE
+
+Returns 0 on success. On error, a negative errno value is returned:
+
+**-EOPNOTSUPP**
+
+: The kernel does not support toggling eventfd notifications, or no
+ eventfd is registered.
+
+# SEE ALSO
+
+**io_uring_register_eventfd**(3),
+**io_uring_register_eventfd_async**(3),
+**io_uring_cq_eventfd_enabled**(3)
diff --git a/man/io_uring_cq_has_overflow.3 b/man/io_uring_cq_has_overflow.3
deleted file mode 100644
index 8ca0ba86..00000000
--- a/man/io_uring_cq_has_overflow.3
+++ /dev/null
@@ -1,31 +0,0 @@
-.\" Copyright (C) 2022 Dylan Yudaken <dylany@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_cq_has_overflow 3 "September 5, 2022" "liburing-2.3" "liburing Manual"
-.SH NAME
-io_uring_cq_has_overflow \- returns if there are overflow entries waiting to move to the CQ ring
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "bool io_uring_cq_has_overflow(const struct io_uring *" ring ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_cq_has_overflow (3)
-function informs the application if CQ entries have overflowed and are waiting to be flushed to
-the CQ ring. For example using
-.BR io_uring_get_events (3)
-.SH NOTES
-Using this function is only valid if the ring has
-.B IORING_FEAT_NODROP
-set, as it's checking for a flag set by kernels supporting that feature. For
-really old kernels that don't support this feature, if CQE overflow is
-experienced the CQEs are lost. If that happens, the CQ ring overflow offset
-will get incremented.
-.SH RETURN VALUE
-True if there are CQ entries waiting to be flushed to the CQ ring.
-.SH SEE ALSO
-.BR io_uring_get_events (3)
diff --git a/man/io_uring_cq_has_overflow.3.md b/man/io_uring_cq_has_overflow.3.md
new file mode 100644
index 00000000..42681607
--- /dev/null
+++ b/man/io_uring_cq_has_overflow.3.md
@@ -0,0 +1,46 @@
+.\" Copyright (C) 2022 Dylan Yudaken <dylany@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: September 5, 2022
+footer: liburing-2.3
+header: liburing Manual
+section: 3
+title: io_uring_cq_has_overflow
+---
+
+# NAME
+
+io_uring_cq_has_overflow - returns if there are overflow entries waiting
+to move to the CQ ring
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ bool io_uring_cq_has_overflow(const struct io_uring * ring );
+```
+
+# DESCRIPTION
+
+The **io_uring_cq_has_overflow**(3) function informs the application if
+CQ entries have overflowed and are waiting to be flushed to the CQ ring.
+For example using **io_uring_get_events**(3)
+
+# NOTES
+
+Using this function is only valid if the ring has **IORING_FEAT_NODROP**
+set, as it\'s checking for a flag set by kernels supporting that
+feature. For really old kernels that don\'t support this feature, if CQE
+overflow is experienced the CQEs are lost. If that happens, the CQ ring
+overflow offset will get incremented.
+
+# RETURN VALUE
+
+True if there are CQ entries waiting to be flushed to the CQ ring.
+
+# SEE ALSO
+
+**io_uring_get_events**(3)
diff --git a/man/io_uring_cq_ready.3 b/man/io_uring_cq_ready.3
deleted file mode 100644
index 641828a8..00000000
--- a/man/io_uring_cq_ready.3
+++ /dev/null
@@ -1,26 +0,0 @@
-.\" Copyright (C) 2022 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_cq_ready 3 "January 25, 2022" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_cq_ready \- returns number of unconsumed ready entries in the CQ ring
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "unsigned io_uring_cq_ready(const struct io_uring *" ring ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_cq_ready (3)
-function returns the number of unconsumed entries that are ready belonging to the
-.I ring
-param.
-
-.SH RETURN VALUE
-Returns the number of unconsumed ready entries in the CQ ring.
-.SH SEE ALSO
-.BR io_uring_submit (3),
-.BR io_uring_wait_cqe (3)
diff --git a/man/io_uring_cq_ready.3.md b/man/io_uring_cq_ready.3.md
new file mode 100644
index 00000000..f049d6fd
--- /dev/null
+++ b/man/io_uring_cq_ready.3.md
@@ -0,0 +1,37 @@
+.\" Copyright (C) 2022 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 25, 2022
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_cq_ready
+---
+
+# NAME
+
+io_uring_cq_ready - returns number of unconsumed ready entries in the CQ
+ring
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ unsigned io_uring_cq_ready(const struct io_uring * ring );
+```
+
+# DESCRIPTION
+
+The **io_uring_cq_ready**(3) function returns the number of unconsumed
+entries that are ready belonging to the *ring* param.
+
+# RETURN VALUE
+
+Returns the number of unconsumed ready entries in the CQ ring.
+
+# SEE ALSO
+
+**io_uring_submit**(3), **io_uring_wait_cqe**(3)
diff --git a/man/io_uring_cqe_get_data.3 b/man/io_uring_cqe_get_data.3
deleted file mode 100644
index a4d2988a..00000000
--- a/man/io_uring_cqe_get_data.3
+++ /dev/null
@@ -1,53 +0,0 @@
-.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_cqe_get_data 3 "November 15, 2021" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_cqe_get_data \- get user data for completion event
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void *io_uring_cqe_get_data(struct io_uring_cqe *" cqe ");"
-.BI "
-.BI "__u64 io_uring_cqe_get_data64(struct io_uring_cqe *" cqe ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_cqe_get_data (3)
-function returns the user_data with the completion queue entry
-.IR cqe
-as a data pointer.
-
-The
-.BR io_uring_cqe_get_data64 (3)
-function returns the user_data with the completion queue entry
-.IR cqe
-as a 64-bit data value.
-
-After the caller has received a completion queue entry (CQE) with
-.BR io_uring_wait_cqe (3),
-the application can call
-.BR io_uring_cqe_get_data (3)
-or
-.BR io_uring_cqe_get_data64 (3)
-function to retrieve the
-.I user_data
-value. This requires that
-.I user_data
-has been set earlier with the function
-.BR io_uring_sqe_set_data (3)
-or
-.BR io_uring_sqe_set_data64 (3).
-
-.SH RETURN VALUE
-If the
-.I user_data
-value has been set before submitting the request, it will be returned.
-Otherwise, the return value is undefined.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_sqe_set_data (3),
-.BR io_uring_sqe_submit (3)
diff --git a/man/io_uring_cqe_get_data.3.md b/man/io_uring_cqe_get_data.3.md
new file mode 100644
index 00000000..a05d3490
--- /dev/null
+++ b/man/io_uring_cqe_get_data.3.md
@@ -0,0 +1,50 @@
+.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: November 15, 2021
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_cqe_get_data
+---
+
+# NAME
+
+io_uring_cqe_get_data - get user data for completion event
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void *io_uring_cqe_get_data(struct io_uring_cqe * cqe );
+
+ __u64 io_uring_cqe_get_data64(struct io_uring_cqe * cqe );
+```
+
+# DESCRIPTION
+
+The **io_uring_cqe_get_data**(3) function returns the user_data with the
+completion queue entry *cqe* as a data pointer.
+
+The **io_uring_cqe_get_data64**(3) function returns the user_data with
+the completion queue entry *cqe* as a 64-bit data value.
+
+After the caller has received a completion queue entry (CQE) with
+**io_uring_wait_cqe**(3), the application can call
+**io_uring_cqe_get_data**(3) or **io_uring_cqe_get_data64**(3) function
+to retrieve the *user_data* value. This requires that *user_data* has
+been set earlier with the function **io_uring_sqe_set_data**(3) or
+**io_uring_sqe_set_data64**(3).
+
+# RETURN VALUE
+
+If the *user_data* value has been set before submitting the request, it
+will be returned. Otherwise, the return value is undefined.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_sqe_set_data**(3),
+**io_uring_sqe_submit**(3)
diff --git a/man/io_uring_cqe_nr.3 b/man/io_uring_cqe_nr.3
deleted file mode 100644
index 75568083..00000000
--- a/man/io_uring_cqe_nr.3
+++ /dev/null
@@ -1,35 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_cqe_nr 3 "January 18, 2025" "liburing-2.12" "liburing Manual"
-.SH NAME
-io_uring_cqe_nr \- return the number of CQ ring slots consumed by a CQE
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "unsigned io_uring_cqe_nr(const struct io_uring_cqe *" cqe ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_cqe_nr (3)
-function returns the number of CQ ring slots consumed by
-.IR cqe .
-For normal 16-byte CQEs, this returns 1. For 32-byte CQEs (when
-.B IORING_CQE_F_32
-is set in the CQE flags), this returns 2.
-
-This function is useful when advancing the CQ ring with
-.BR io_uring_cq_advance (3)
-on rings that use
-.B IORING_SETUP_CQE_MIXED
-where both 16-byte and 32-byte CQEs may be present.
-
-.SH RETURN VALUE
-Returns 1 for normal CQEs, or 2 for 32-byte CQEs.
-.SH SEE ALSO
-.BR io_uring_cq_advance (3),
-.BR io_uring_cqe_seen (3),
-.BR io_uring_setup (2)
diff --git a/man/io_uring_cqe_nr.3.md b/man/io_uring_cqe_nr.3.md
new file mode 100644
index 00000000..0c5abe78
--- /dev/null
+++ b/man/io_uring_cqe_nr.3.md
@@ -0,0 +1,42 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 18, 2025
+footer: liburing-2.12
+header: liburing Manual
+section: 3
+title: io_uring_cqe_nr
+---
+
+# NAME
+
+io_uring_cqe_nr - return the number of CQ ring slots consumed by a CQE
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ unsigned io_uring_cqe_nr(const struct io_uring_cqe * cqe );
+```
+
+# DESCRIPTION
+
+The **io_uring_cqe_nr**(3) function returns the number of CQ ring slots
+consumed by *cqe*. For normal 16-byte CQEs, this returns 1. For 32-byte
+CQEs (when **IORING_CQE_F_32** is set in the CQE flags), this returns 2.
+
+This function is useful when advancing the CQ ring with
+**io_uring_cq_advance**(3) on rings that use **IORING_SETUP_CQE_MIXED**
+where both 16-byte and 32-byte CQEs may be present.
+
+# RETURN VALUE
+
+Returns 1 for normal CQEs, or 2 for 32-byte CQEs.
+
+# SEE ALSO
+
+**io_uring_cq_advance**(3), **io_uring_cqe_seen**(3),
+**io_uring_setup**(2)
diff --git a/man/io_uring_cqe_seen.3 b/man/io_uring_cqe_seen.3
deleted file mode 100644
index 5c9cd4e5..00000000
--- a/man/io_uring_cqe_seen.3
+++ /dev/null
@@ -1,41 +0,0 @@
-.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_cqe_seen 3 "November 15, 2021" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_cqe_seen \- mark io_uring completion event as consumed
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_cqe_seen(struct io_uring *" ring ","
-.BI " struct io_uring_cqe *" cqe ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_cqe_seen (3)
-function marks the IO completion
-.I cqe
-belonging to the
-.I ring
-param as consumed.
-
-After the caller has submitted a request with
-.BR io_uring_submit (3),
-the application can retrieve the completion with
-.BR io_uring_wait_cqe (3),
-.BR io_uring_peek_cqe (3),
-or any of the other CQE retrieval helpers, and mark it as consumed with
-.BR io_uring_cqe_seen (3).
-
-Completions must be marked as completed so their slot can get reused.
-.SH RETURN VALUE
-None
-.SH SEE ALSO
-.BR io_uring_submit (3),
-.BR io_uring_peek_cqe (3),
-.BR io_uring_wait_cqe (3),
-.BR io_uring_wait_cqes (3),
-.BR io_uring_wait_cqe_timeout (3)
diff --git a/man/io_uring_cqe_seen.3.md b/man/io_uring_cqe_seen.3.md
new file mode 100644
index 00000000..2416e806
--- /dev/null
+++ b/man/io_uring_cqe_seen.3.md
@@ -0,0 +1,47 @@
+.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: November 15, 2021
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_cqe_seen
+---
+
+# NAME
+
+io_uring_cqe_seen - mark io_uring completion event as consumed
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_cqe_seen(struct io_uring * ring ,
+ struct io_uring_cqe * cqe );
+```
+
+# DESCRIPTION
+
+The **io_uring_cqe_seen**(3) function marks the IO completion *cqe*
+belonging to the *ring* param as consumed.
+
+After the caller has submitted a request with **io_uring_submit**(3),
+the application can retrieve the completion with
+**io_uring_wait_cqe**(3), **io_uring_peek_cqe**(3), or any of the other
+CQE retrieval helpers, and mark it as consumed with
+**io_uring_cqe_seen**(3).
+
+Completions must be marked as completed so their slot can get reused.
+
+# RETURN VALUE
+
+None
+
+# SEE ALSO
+
+**io_uring_submit**(3), **io_uring_peek_cqe**(3),
+**io_uring_wait_cqe**(3), **io_uring_wait_cqes**(3),
+**io_uring_wait_cqe_timeout**(3)
diff --git a/man/io_uring_enable_rings.3 b/man/io_uring_enable_rings.3
deleted file mode 100644
index a01713be..00000000
--- a/man/io_uring_enable_rings.3
+++ /dev/null
@@ -1,40 +0,0 @@
-.\" Copyright (C) 2023 nick black <dankamongmen@gmail.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_enable_rings 3 "July 26, 2024" "liburing-2.7" "liburing Manual"
-.SH NAME
-io_uring_enable_rings \- enable a disabled ring
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_enable_rings(struct io_uring *" ring ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_enable_rings (3)
-function enables a ring after having created it with the
-.B IORING_SETUP_R_DISABLED
-flag to
-.BR io_uring_queue_init (3)
-
-It is not possible to submit work to such a ring until this
-function has been successfully called.
-
-.SH RETURN VALUE
-.BR io_uring_enable_rings (3)
-returns 0 on success. It otherwise returns a negative error code.
-It does not write to
-.BR errno .
-
-.SH ERRORS
-.TP
-.B EBADFD
-The ring was not disabled.
-
-.SH SEE ALSO
-.BR io_uring_queue_init (3),
-.BR io_uring_register (2),
-.BR io_uring_setup (2)
diff --git a/man/io_uring_enable_rings.3.md b/man/io_uring_enable_rings.3.md
new file mode 100644
index 00000000..cbe30b14
--- /dev/null
+++ b/man/io_uring_enable_rings.3.md
@@ -0,0 +1,48 @@
+.\" Copyright (C) 2023 nick black <dankamongmen@gmail.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: July 26, 2024
+footer: liburing-2.7
+header: liburing Manual
+section: 3
+title: io_uring_enable_rings
+---
+
+# NAME
+
+io_uring_enable_rings - enable a disabled ring
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_enable_rings(struct io_uring * ring );
+```
+
+# DESCRIPTION
+
+The **io_uring_enable_rings**(3) function enables a ring after having
+created it with the **IORING_SETUP_R_DISABLED** flag to
+**io_uring_queue_init**(3)
+
+It is not possible to submit work to such a ring until this function has
+been successfully called.
+
+# RETURN VALUE
+
+**io_uring_enable_rings**(3) returns 0 on success. It otherwise returns
+a negative error code. It does not write to **errno**.
+
+# ERRORS
+
+**EBADFD**
+
+: The ring was not disabled.
+
+# SEE ALSO
+
+**io_uring_queue_init**(3), **io_uring_register**(2),
+**io_uring_setup**(2)
diff --git a/man/io_uring_enter.2 b/man/io_uring_enter.2
deleted file mode 100644
index 7b99335e..00000000
--- a/man/io_uring_enter.2
+++ /dev/null
@@ -1,2208 +0,0 @@
-.\" Copyright (C) 2019 Jens Axboe <axboe@kernel.dk>
-.\" Copyright (C) 2019 Red Hat, Inc.
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_enter 2 "January 22, 2019" "Linux" "Linux Programmer's Manual"
-.SH NAME
-io_uring_enter \- initiate and/or complete asynchronous I/O
-.SH SYNOPSIS
-.nf
-.BR "#include <liburing.h>"
-.PP
-.BI "int io_uring_enter(unsigned int " fd ", unsigned int " to_submit ,
-.BI " unsigned int " min_complete ", unsigned int " flags ,
-.BI " sigset_t *" sig );
-.PP
-.BI "int io_uring_enter2(unsigned int " fd ", unsigned int " to_submit ,
-.BI " unsigned int " min_complete ", unsigned int " flags ,
-.BI " void *" arg ", size_t " sz );
-.fi
-.PP
-.SH DESCRIPTION
-.PP
-.BR io_uring_enter (2)
-is used to initiate and complete I/O using the shared submission and
-completion queues setup by a call to
-.BR io_uring_setup (2).
-A single call can both submit new I/O and wait for completions of I/O
-initiated by this call or previous calls to
-.BR io_uring_enter (2).
-
-.I fd
-is the file descriptor returned by
-.BR io_uring_setup (2).
-.I to_submit
-specifies the number of I/Os to submit from the submission queue.
-.I flags
-is a bitmask of the following values:
-.TP
-.B IORING_ENTER_GETEVENTS
-If this flag is set, then the system call will wait for the specified
-number of events in
-.I min_complete
-before returning. This flag can be set along with
-.I to_submit
-to both submit and complete events in a single system call.
-If this flag is set either the flag
-.B IORING_SETUP_DEFER_TASKRUN
-must not be set or the thread issuing the syscall must be the thread that
-created the io_uring associated with
-.I fd,
-or be the thread that enabled the ring originally created with
-.B IORING_SETUP_R_DISABLED
-via
-.BR io_uring_register (2)
-or
-.BR io_uring_enable_rings (3).
-.TP
-.B IORING_ENTER_SQ_WAKEUP
-If the ring has been created with
-.B IORING_SETUP_SQPOLL,
-then this flag asks the kernel to wakeup the SQ kernel thread to submit IO.
-.TP
-.B IORING_ENTER_SQ_WAIT
-If the ring has been created with
-.B IORING_SETUP_SQPOLL,
-then the application has no real insight into when the SQ kernel thread has
-consumed entries from the SQ ring. This can lead to a situation where the
-application can no longer get a free SQE entry to submit, without knowing
-when one will become available as the SQ kernel thread consumes them. If
-the system call is used with this flag set, then it will wait until at least
-one entry is free in the SQ ring.
-.TP
-.B IORING_ENTER_EXT_ARG
-By default,
-.I arg
-is a
-.I sigset_t
-pointer. If
-.B IORING_ENTER_EXT_ARG
-is set (supported since kernel 5.11), then
-.I arg
-is instead a pointer to a
-.I struct io_uring_getevents_arg
-and
-.I argsz
-must be set to the size of this structure. The definition is as follows:
-
-.nf
-.BI "struct io_uring_getevents_arg {
-.BI " __u64 sigmask;
-.BI " __u32 sigmask_sz;
-.BI " __u32 pad;
-.BI " __u64 ts;
-.BI "};
-.fi
-
-which allows passing in both a signal mask as well as pointer to a
-.I struct __kernel_timespec
-timeout value. If
-.I ts
-is set to a valid pointer, then this time value indicates the timeout for
-waiting on events. If an application is waiting on events and wishes to
-stop waiting after a specified amount of time, then this can be accomplished
-directly in version 5.11 and newer by using this feature.
-.TP
-.B IORING_ENTER_REGISTERED_RING
-If the ring file descriptor has been registered through use of
-.BR IORING_REGISTER_RING_FDS ,
-then setting this flag will tell the kernel that the
-.I ring_fd
-passed in is the registered ring offset rather than a normal file descriptor.
-
-.TP
-.B IORING_ENTER_ABS_TIMER
-
-When this flag is set, the timeout argument passed in
-.I struct io_uring_getevents_arg
-will be interpreted as an absolute
-time of the registered clock (see
-.BR IORING_REGISTER_CLOCK)
-until which the waiting should end.
-
-Available since 6.12
-
-.TP
-.B IORING_ENTER_EXT_ARG_REG
-
-When this flag is set,
-.IR arg
-is not a pointer to a
-.IR struct io_uring_getevents_arg ,
-but merely an offset into an area of wait regions previously registered with
-.BR io_uring_register (2)
-using the
-.B IORING_REGISTER_MEM_REGION
-operation.
-
-Available since 6.13
-
-.TP
-.B IORING_ENTER_NO_IOWAIT
-When this flag is set, the system call will not mark the waiting task as being
-in iowait if it is sleeping waiting on events and there are pending requests.
-This is useful if iowait isn't expected when waiting for events. It can also
-prevent extra power usage by allowing the CPU to enter lower sleep states.
-This flag is only available if the kernel supports the
-.B IORING_FEAT_NO_IOWAIT
-feature.
-
-Available since 6.15.
-
-.PP
-.PP
-If the io_uring instance was configured for polling, by specifying
-.B IORING_SETUP_IOPOLL
-in the call to
-.BR io_uring_setup (2),
-then min_complete has a slightly different meaning. Passing a value
-of 0 instructs the kernel to return any events which are already complete,
-without blocking. If
-.I min_complete
-is a non-zero value, the kernel will still return immediately if any
-completion events are available. If no event completions are
-available, then the call will poll either until one or more
-completions become available, or until the process has exceeded its
-scheduler time slice.
-
-Note that, for interrupt driven I/O (where
-.B IORING_SETUP_IOPOLL
-was not specified in the call to
-.BR io_uring_setup (2)),
-an application may check the completion queue for event completions
-without entering the kernel at all.
-.PP
-When the system call returns that a certain amount of SQEs have been
-consumed and submitted, it's safe to reuse SQE entries in the ring. This is
-true even if the actual IO submission had to be punted to async context,
-which means that the SQE may in fact not have been submitted yet. If the
-kernel requires later use of a particular SQE entry, it will have made a
-private copy of it.
-
-.I sig
-is a pointer to a signal mask (see
-.BR sigprocmask (2));
-if
-.I sig
-is not NULL,
-.BR io_uring_enter (2)
-first replaces the current signal mask by the one pointed to by
-.IR sig ,
-then waits for events to become available in the completion queue, and
-then restores the original signal mask. The following
-.BR io_uring_enter (2)
-call:
-.PP
-.in +4n
-.EX
-ret = io_uring_enter(fd, 0, 1, IORING_ENTER_GETEVENTS, &sig);
-.EE
-.in
-.PP
-is equivalent to
-.I atomically
-executing the following calls:
-.PP
-.in +4n
-.EX
-pthread_sigmask(SIG_SETMASK, &sig, &orig);
-ret = io_uring_enter(fd, 0, 1, IORING_ENTER_GETEVENTS, NULL);
-pthread_sigmask(SIG_SETMASK, &orig, NULL);
-.EE
-.in
-.PP
-See the description of
-.BR pselect (2)
-for an explanation of why the
-.I sig
-parameter is necessary.
-
-Submission queue entries are represented using the following data
-structure:
-.PP
-.in +4n
-.EX
-/*
- * IO submission data structure (Submission Queue Entry)
- */
-struct io_uring_sqe {
- __u8 opcode; /* type of operation for this sqe */
- __u8 flags; /* IOSQE_ flags */
- __u16 ioprio; /* ioprio for the request */
- __s32 fd; /* file descriptor to do IO on */
- union {
- __u64 off; /* offset into file */
- __u64 addr2;
- struct {
- __u32 cmd_op;
- __u32 __pad1;
- };
- };
- union {
- __u64 addr; /* pointer to buffer or iovecs */
- __u64 splice_off_in;
- struct {
- __u32 level;
- __u32 optname;
- };
- };
- __u32 len; /* buffer size or number of iovecs */
- union {
- __kernel_rwf_t rw_flags;
- __u32 fsync_flags;
- __u16 poll_events; /* compatibility */
- __u32 poll32_events; /* word-reversed for BE */
- __u32 sync_range_flags;
- __u32 msg_flags;
- __u32 timeout_flags;
- __u32 accept_flags;
- __u32 cancel_flags;
- __u32 open_flags;
- __u32 statx_flags;
- __u32 fadvise_advice;
- __u32 splice_flags;
- __u32 rename_flags;
- __u32 unlink_flags;
- __u32 hardlink_flags;
- __u32 xattr_flags;
- __u32 msg_ring_flags;
- __u32 uring_cmd_flags;
- __u32 waitid_flags;
- __u32 futex_flags;
- __u32 install_fd_flags;
- __u32 nop_flags;
- };
- __u64 user_data; /* data to be passed back at completion time */
- /* pack this to avoid bogus arm OABI complaints */
- union {
- /* index into fixed buffers, if used */
- __u16 buf_index;
- /* for grouped buffer selection */
- __u16 buf_group;
- } __attribute__((packed));
- /* personality to use, if used */
- __u16 personality;
- union {
- __s32 splice_fd_in;
- __u32 file_index;
- __u32 optlen;
- struct {
- __u16 addr_len;
- __u16 __pad3[1];
- };
- };
- union {
- struct {
- __u64 addr3;
- __u64 __pad2[1];
- };
- __u64 optval;
- /*
- * If the ring is initialized with IORING_SETUP_SQE128, then
- * this field is used for 80 bytes of arbitrary command data
- */
- __u8 cmd[0];
- };
-};
-.EE
-.in
-.PP
-The
-.I opcode
-describes the operation to be performed. It can be one of:
-.TP
-.B IORING_OP_NOP
-Do not perform any I/O. This is useful for testing the performance of
-the io_uring implementation itself.
-.TP
-.B IORING_OP_READV
-.TP
-.B IORING_OP_WRITEV
-Vectored read and write operations, similar to
-.BR preadv2 (2)
-and
-.BR pwritev2 (2).
-If the file is not seekable,
-.I off
-must be set to zero or -1.
-
-.TP
-.B IORING_OP_READ_FIXED
-.TP
-.B IORING_OP_WRITE_FIXED
-Read from or write to pre-mapped buffers. See
-.BR io_uring_register (2)
-for details on how to setup a context for fixed reads and writes.
-
-.TP
-.B IORING_OP_FSYNC
-File sync. See also
-.BR fsync (2).
-Optionally
-.I off
-and
-.I len
-can be used to specify a range within the file to be synced rather than
-syncing the entire file, which is the default behavior.
-Note that, while I/O is initiated in the order in which it appears in
-the submission queue, completions are unordered. For example, an
-application which places a write I/O followed by an fsync in the
-submission queue cannot expect the fsync to apply to the write. The
-two operations execute in parallel, so the fsync may complete before
-the write is issued to the storage. The same is also true for
-previously issued writes that have not completed prior to the fsync.
-To enforce ordering one may utilize linked SQEs,
-.B IOSQE_IO_DRAIN
-or wait for the arrival of CQEs of requests which have to be ordered
-before a given request before submitting its SQE.
-
-.TP
-.B IORING_OP_POLL_ADD
-Poll the
-.I fd
-specified in the submission queue entry for the events
-specified in the
-.I poll_events
-field. Unlike poll or epoll without
-.BR EPOLLONESHOT ,
-by default this interface always works in one shot mode. That is, once the poll
-operation is completed, it will have to be resubmitted.
-
-If
-.B IORING_POLL_ADD_MULTI
-is set in the SQE
-.I len
-field, then the poll will work in multi shot mode instead. That means it'll
-repatedly trigger when the requested event becomes true, and hence multiple
-CQEs can be generated from this single SQE. The CQE
-.I flags
-field will have
-.B IORING_CQE_F_MORE
-set on completion if the application should expect further CQE entries from
-the original request. If this flag isn't set on completion, then the poll
-request has been terminated and no further events will be generated. This mode
-is available since 5.13.
-
-This command works like
-an async
-.BR poll(2)
-and the completion event result is the returned mask of events.
-
-Without
-.B IORING_POLL_ADD_MULTI
-and the initial poll operation with
-.B IORING_POLL_ADD_MULTI
-the operation is level triggered, i.e. if there is data ready or events
-pending etc. at the time of submission a corresponding CQE will be posted.
-Potential further completions beyond the first caused by a
-.B IORING_POLL_ADD_MULTI
-are edge triggered.
-
-.TP
-.B IORING_OP_POLL_REMOVE
-Remove or update an existing poll request. If found, the
-.I res
-field of the
-.I "struct io_uring_cqe"
-will contain 0. If not found,
-.I res
-will contain
-.B -ENOENT,
-or
-.B -EALREADY
-if the poll request was in the process of completing already.
-
-If
-.B IORING_POLL_UPDATE_EVENTS
-is set in the SQE
-.I len
-field, then the request will update an existing poll request with the mask of
-events passed in with this request. The lookup is based on the
-.I user_data
-field of the original SQE submitted, and this values is passed in the
-.I addr
-field of the SQE.
-If
-.B IORING_POLL_UPDATE_USER_DATA
-is set in the SQE
-.I len
-field, then the request will update the
-.I user_data
-of an existing poll request based on the value passed in the
-.I off
-field. Updating an existing poll is available since 5.13.
-
-.TP
-.B IORING_OP_EPOLL_CTL
-Add, remove or modify entries in the interest list of
-.BR epoll (7).
-See
-.BR epoll_ctl (2)
-for details of the system call.
-.I fd
-holds the file descriptor that represents the epoll instance,
-.I off
-holds the file descriptor to add, remove or modify,
-.I len
-holds the operation (
-.BR EPOLL_CTL_ADD ,
-.BR EPOLL_CTL_DEL ,
-.BR EPOLL_CTL_MOD )
-to perform and,
-.I addr
-holds a pointer to the
-.I epoll_event
-structure. Available since 5.6.
-
-.TP
-.B IORING_OP_SYNC_FILE_RANGE
-Issue the equivalent of a \fBsync_file_range\fR (2) on the file descriptor. The
-.I fd
-field is the file descriptor to sync, the
-.I off
-field holds the offset in bytes, the
-.I len
-field holds the length in bytes, and the
-.I sync_range_flags
-field holds the flags for the command. See also
-.BR sync_file_range (2)
-for the general description of the related system call. Available since 5.2.
-
-.TP
-.B IORING_OP_SENDMSG
-Issue the equivalent of a
-.BR sendmsg(2)
-system call.
-.I fd
-must be set to the socket file descriptor,
-.I addr
-must contain a pointer to the msghdr structure, and
-.I msg_flags
-holds the flags associated with the system call. See also
-.BR sendmsg (2)
-for the general description of the related system call. Available since 5.3.
-
-This command also supports the following modifiers in
-.I ioprio:
-
-.PP
-.in +12
-.B IORING_RECVSEND_POLL_FIRST
-If set, io_uring will assume the socket is currently full and attempting to
-send data will be unsuccessful. For this case, io_uring will arm internal
-poll and trigger a send of the data when there is enough space available.
-This initial send attempt can be wasteful for the case where the socket
-is expected to be full, setting this flag will bypass the initial send
-attempt and go straight to arming poll. If poll does indicate that data can
-be sent, the operation will proceed.
-.EE
-.in
-.PP
-
-.TP
-.B IORING_OP_RECVMSG
-Works just like IORING_OP_SENDMSG, except for
-.BR recvmsg(2)
-instead. See the description of IORING_OP_SENDMSG. Available since 5.3.
-
-This command also supports the following modifiers in
-.I ioprio:
-
-.PP
-.in +12
-.B IORING_RECVSEND_POLL_FIRST
-If set, io_uring will assume the socket is currently empty and attempting to
-receive data will be unsuccessful. For this case, io_uring will arm internal
-poll and trigger a receive of the data when the socket has data to be read.
-This initial receive attempt can be wasteful for the case where the socket
-is expected to be empty, setting this flag will bypass the initial receive
-attempt and go straight to arming poll. If poll does indicate that data is
-ready to be received, the operation will proceed.
-.EE
-.in
-.PP
-
-.TP
-.B IORING_OP_SEND
-Issue the equivalent of a
-.BR send(2)
-system call.
-.I fd
-must be set to the socket file descriptor,
-.I addr
-must contain a pointer to the buffer,
-.I len
-denotes the length of the buffer to send, and
-.I msg_flags
-holds the flags associated with the system call. See also
-.BR send(2)
-for the general description of the related system call. Available since 5.6.
-
-This command also supports the following modifiers in
-.I ioprio:
-
-.PP
-.in +12
-.B IORING_RECVSEND_POLL_FIRST
-If set, io_uring will assume the socket is currently full and attempting to
-send data will be unsuccessful. For this case, io_uring will arm internal
-poll and trigger a send of the data when there is enough space available.
-This initial send attempt can be wasteful for the case where the socket
-is expected to be full, setting this flag will bypass the initial send
-attempt and go straight to arming poll. If poll does indicate that data can
-be sent, the operation will proceed.
-.EE
-.in
-.PP
-
-.TP
-.B IORING_OP_RECV
-Works just like IORING_OP_SEND, except for
-.BR recv(2)
-instead. See the description of IORING_OP_SEND. Available since 5.6.
-
-This command also supports the following modifiers in
-.I ioprio:
-
-.PP
-.in +12
-.B IORING_RECVSEND_POLL_FIRST
-If set, io_uring will assume the socket is currently empty and attempting to
-receive data will be unsuccessful. For this case, io_uring will arm internal
-poll and trigger a receive of the data when the socket has data to be read.
-This initial receive attempt can be wasteful for the case where the socket
-is expected to be empty, setting this flag will bypass the initial receive
-attempt and go straight to arming poll. If poll does indicate that data is
-ready to be received, the operation will proceed.
-.EE
-.in
-.PP
-
-.TP
-.B IORING_OP_TIMEOUT
-This command will register a timeout operation. The
-.I addr
-field must contain a pointer to a struct __kernel_timespec structure,
-.I len
-must contain 1 to signify one __kernel_timespec structure,
-.I timeout_flags
-may contain
-.B IORING_TIMEOUT_ABS
-for an absolute timeout value, or 0 for a relative timeout.
-.I off
-may contain a completion event count. A timeout
-will trigger a wakeup event on the completion ring for anyone waiting for
-events. A timeout condition is met when either the specified timeout expires,
-or the specified number of events have completed. Either condition will
-trigger the event. If set to 0, completed events are not counted, which
-effectively acts like a timer. io_uring timeouts use the
-.B CLOCK_MONOTONIC
-as the default clock source. The request will complete with
-.B -ETIME
-if the timeout got completed through expiration of the timer, or
-.I 0
-if the timeout got completed through requests completing on their own. If
-the timeout was canceled before it expired, the request will complete with
-.B -ECANCELED.
-Available since 5.4.
-
-Since 5.15, this command also supports the following modifiers in
-.I timeout_flags:
-
-.PP
-.in +12
-.B IORING_TIMEOUT_BOOTTIME
-If set, then the clocksource used is
-.B CLOCK_BOOTTIME
-instead of
-.BR CLOCK_MONOTONIC .
-This clocksource differs in that it includes time elapsed if the system was
-suspend while having a timeout request in-flight.
-
-.B IORING_TIMEOUT_REALTIME
-If set, then the clocksource used is
-.B CLOCK_REALTIME
-instead of
-.BR CLOCK_MONOTONIC .
-.EE
-.in
-.PP
-
-.PP
-.in +7
-Since 5.16,
-.B IORING_TIMEOUT_ETIME_SUCCESS
-can be set in
-.IR timeout_flags ,
-which will result in the expiration of the timer and subsequent completion
-with
-.B -ETIME
-not being interpreted as an error. This is mostly relevant for linked SQEs, as
-subsequent requests in the chain would not get canceled by the timeout, if
-this flag is set. See
-.B IOSQE_IO_LINK
-for more details on linked SQEs.
-.in
-.PP
-
-.PP
-.in +7
-Since 6.4,
-.B IORING_TIMEOUT_MULTISHOT
-can be set in
-.IR timeout_flags ,
-which will result in the timer producing multiple consecutive completions
-like other multi shot operations e.g.
-.B IORING_OP_READ_MULTISHOT
-or
-.BR IORING_POLL_ADD_MULTI .
-.I off
-must be set to the amount of desired completions.
-.B IORING_TIMEOUT_MULTISHOT
-must not be used with
-.BR IORING_TIMEOUT_ABS .
-.in
-.PP
-
-.PP
-.in +7
-Since kernel 7.1,
-.B IORING_TIMEOUT_IMMEDIATE_ARG
-can be set in
-.IR timeout_flags ,
-which causes the
-.I addr
-field to be interpreted as a timeout value in nanoseconds rather than a
-pointer to a
-.B struct __kernel_timespec.
-This avoids the need to keep a timespec structure valid in user memory until
-the request is submitted.
-.in
-.PP
-
-.TP
-.B IORING_OP_TIMEOUT_REMOVE
-If
-.I timeout_flags
-are zero, then it attempts to remove an existing timeout operation.
-.I addr
-must contain the
-.I user_data
-field of the previously issued timeout operation. If the specified timeout
-request is found and canceled successfully, this request will terminate
-with a result value of
-.I 0
-If the timeout request was found but expiration was already in progress,
-this request will terminate with a result value of
-.B -EBUSY
-If the timeout request wasn't found, the request will terminate with a result
-value of
-.B -ENOENT
-Available since 5.5.
-
-If
-.I timeout_flags
-contain
-.BR IORING_TIMEOUT_UPDATE ,
-instead of removing an existing operation, it updates it.
-.I addr
-and return values are same as before.
-.I addr2
-field must contain a pointer to a struct __kernel_timespec structure.
-.I timeout_flags
-may also contain IORING_TIMEOUT_ABS, in which case the value given is an
-absolute one, not a relative one.
-Available since 5.11.
-
-.TP
-.B IORING_OP_ACCEPT
-Issue the equivalent of an
-.BR accept4 (2)
-system call.
-.I fd
-must be set to the socket file descriptor,
-.I addr
-must contain the pointer to the sockaddr structure, and
-.I addr2
-must contain a pointer to the socklen_t addrlen field. Flags can be passed using
-the
-.I accept_flags
-field. See also
-.BR accept4 (2)
-for the general description of the related system call. Available since 5.5.
-
-If the
-.I file_index
-field is set to a positive number, the file won't be installed into the
-normal file table as usual but will be placed into the fixed file table at index
-.I file_index
-- 1.
-In this case, instead of returning a file descriptor, the result will contain
-either 0 on success or an error. If the index points to a valid empty slot, the
-installation is guaranteed to not fail. If there is already a file in the slot,
-it will be replaced, similar to
-.B IORING_OP_FILES_UPDATE.
-Please note that only io_uring has access to such files and no other syscall
-can use them. See
-.B IOSQE_FIXED_FILE
-and
-.BR IORING_REGISTER_FILES .
-
-Available since 5.5.
-
-.TP
-.B IORING_OP_ASYNC_CANCEL
-Attempt to cancel an already issued request.
-.I addr
-must contain the
-.I user_data
-field of the request that should be canceled. The cancelation request will
-complete with one of the following results codes. If found, the
-.I res
-field of the cqe will contain 0. If not found,
-.I res
-will contain
-.BR -ENOENT .
-If found and attempted canceled, the
-.I res
-field will contain
-.BR -EALREADY .
-In this case, the request may or may not
-terminate. In general, requests that are interruptible (like socket IO) will
-get canceled, while disk IO requests cannot be canceled if already started.
-Available since 5.5.
-
-.TP
-.B IORING_OP_LINK_TIMEOUT
-This request must be linked with another request through
-.B IOSQE_IO_LINK
-which is described below. Unlike
-.BR IORING_OP_TIMEOUT ,
-.B IORING_OP_LINK_TIMEOUT
-acts on the linked request, not the completion queue. The format of the command
-is otherwise like
-.BR IORING_OP_TIMEOUT ,
-except there's no completion event count as it's tied to a specific request.
-If used, the timeout specified in the command will cancel the linked command,
-unless the linked command completes before the timeout. The timeout will
-complete with
-.B -ETIME
-if the timer expired and the linked request was attempted canceled, or
-.B -ECANCELED
-if the timer got canceled because of completion of the linked request. Like
-.B IORING_OP_TIMEOUT
-the clock source used is
-.B CLOCK_MONOTONIC
-Available since 5.5.
-
-
-.TP
-.B IORING_OP_CONNECT
-Issue the equivalent of a
-.BR connect (2)
-system call.
-.I fd
-must be set to the socket file descriptor,
-.I addr
-must contain the const pointer to the sockaddr structure, and
-.I off
-must contain the socklen_t addrlen field. See also
-.BR connect (2)
-for the general description of the related system call. Available since 5.5.
-
-.TP
-.B IORING_OP_FALLOCATE
-Issue the equivalent of a
-.BR fallocate (2)
-system call.
-.I fd
-must be set to the file descriptor,
-.I len
-must contain the mode associated with the operation,
-.I off
-must contain the offset on which to operate, and
-.I addr
-must contain the length. See also
-.BR fallocate (2)
-for the general description of the related system call. Available since 5.6.
-
-.TP
-.B IORING_OP_FADVISE
-Issue the equivalent of a
-.BR posix_fadvise (2)
-system call.
-.I fd
-must be set to the file descriptor,
-.I off
-must contain the offset on which to operate,
-.I len
-must contain the length, and
-.I fadvise_advice
-must contain the advice associated with the operation. See also
-.BR posix_fadvise (2)
-for the general description of the related system call. Available since 5.6.
-
-.TP
-.B IORING_OP_MADVISE
-Issue the equivalent of a
-.BR madvise (2)
-system call.
-.I addr
-must contain the address to operate on,
-.I len
-must contain the length on which to operate,
-and
-.I fadvise_advice
-must contain the advice associated with the operation. See also
-.BR madvise (2)
-for the general description of the related system call. Available since 5.6.
-
-.TP
-.B IORING_OP_OPENAT
-Issue the equivalent of a
-.BR openat (2)
-system call.
-.I fd
-is the
-.I dirfd
-argument,
-.I addr
-must contain a pointer to the
-.I *pathname
-argument,
-.I open_flags
-should contain any flags passed in, and
-.I len
-is access mode of the file. See also
-.BR openat (2)
-for the general description of the related system call. Available since 5.6.
-
-If the
-.I file_index
-field is set to a positive number, the file won't be installed into the
-normal file table as usual but will be placed into the fixed file table at index
-.I file_index - 1.
-In this case, instead of returning a file descriptor, the result will contain
-either 0 on success or an error. If the index points to a valid empty slot, the
-installation is guaranteed to not fail. If there is already a file in the slot,
-it will be replaced, similar to
-.B IORING_OP_FILES_UPDATE.
-Please note that only io_uring has access to such files and no other syscall
-can use them. See
-.B IOSQE_FIXED_FILE
-and
-.BR IORING_REGISTER_FILES .
-
-Available since 5.15.
-
-.TP
-.B IORING_OP_OPENAT2
-Issue the equivalent of a
-.BR openat2 (2)
-system call.
-.I fd
-is the
-.I dirfd
-argument,
-.I addr
-must contain a pointer to the
-.I *pathname
-argument,
-.I len
-should contain the size of the open_how structure, and
-.I off
-should be set to the address of the open_how structure. See also
-.BR openat2 (2)
-for the general description of the related system call. Available since 5.6.
-
-If the
-.I file_index
-field is set to a positive number, the file won't be installed into the
-normal file table as usual but will be placed into the fixed file table at index
-.I file_index - 1.
-In this case, instead of returning a file descriptor, the result will contain
-either 0 on success or an error. If the index points to a valid empty slot, the
-installation is guaranteed to not fail. If there is already a file in the slot,
-it will be replaced, similar to
-.BR IORING_OP_FILES_UPDATE .
-Please note that only io_uring has access to such files and no other syscall
-can use them. See
-.B IOSQE_FIXED_FILE
-and
-.BR IORING_REGISTER_FILES .
-
-Available since 5.15.
-
-.TP
-.B IORING_OP_CLOSE
-Issue the equivalent of a
-.BR close (2)
-system call.
-.I fd
-is the file descriptor to be closed. See also
-.BR close (2)
-for the general description of the related system call. Available since 5.6.
-If the
-.I file_index
-field is set to a positive number, this command can be used to close files
-that were direct opened through
-.BR IORING_OP_OPENAT ,
-.BR IORING_OP_OPENAT2 ,
-or
-.B IORING_OP_ACCEPT
-using the io_uring specific direct descriptors. Note that only one of the
-descriptor fields may be set. The direct close feature is available since
-the 5.15 kernel, where direct descriptors were introduced.
-
-.TP
-.B IORING_OP_STATX
-Issue the equivalent of a
-.BR statx (2)
-system call.
-.I fd
-is the
-.I dirfd
-argument,
-.I addr
-must contain a pointer to the
-.I *pathname
-string,
-.I statx_flags
-is the
-.I flags
-argument,
-.I len
-should be the
-.I mask
-argument, and
-.I off
-must contain a pointer to the
-.I statxbuf
-to be filled in. See also
-.BR statx (2)
-for the general description of the related system call. Available since 5.6.
-
-.TP
-.B IORING_OP_READ
-.TP
-.B IORING_OP_WRITE
-Issue the equivalent of a
-.BR pread (2)
-or
-.BR pwrite (2)
-system call.
-.I fd
-is the file descriptor to be operated on,
-.I addr
-contains the buffer in question,
-.I len
-contains the length of the IO operation, and
-.I offs
-contains the read or write offset. If
-.I fd
-does not refer to a seekable file,
-.I off
-must be set to zero or -1. If
-.I offs
-is set to
-.B -1
-, the offset will use (and advance) the file position, like the
-.BR read (2)
-and
-.BR write (2)
-system calls. These are non-vectored versions of the
-.B IORING_OP_READV
-and
-.B IORING_OP_WRITEV
-opcodes. See also
-.BR read (2)
-and
-.BR write (2)
-for the general description of the related system call. Available since 5.6.
-
-.TP
-.B IORING_OP_SPLICE
-Issue the equivalent of a
-.BR splice (2)
-system call.
-.I splice_fd_in
-is the file descriptor to read from,
-.I splice_off_in
-is an offset to read from,
-.I fd
-is the file descriptor to write to,
-.I off
-is an offset from which to start writing to. A sentinel value of
-.B -1
-is used to pass the equivalent of a NULL for the offsets to
-.BR splice (2).
-.I len
-contains the number of bytes to copy.
-.I splice_flags
-contains a bit mask for the flag field associated with the system call.
-Please note that one of the file descriptors must refer to a pipe.
-See also
-.BR splice (2)
-for the general description of the related system call. Available since 5.7.
-
-.TP
-.B IORING_OP_TEE
-Issue the equivalent of a
-.BR tee (2)
-system call.
-.I splice_fd_in
-is the file descriptor to read from,
-.I fd
-is the file descriptor to write to,
-.I len
-contains the number of bytes to copy, and
-.I splice_flags
-contains a bit mask for the flag field associated with the system call.
-Please note that both of the file descriptors must refer to a pipe.
-See also
-.BR tee (2)
-for the general description of the related system call. Available since 5.8.
-
-.TP
-.B IORING_OP_FILES_UPDATE
-This command is an alternative to using
-.B IORING_REGISTER_FILES_UPDATE
-which then works in an async fashion, like the rest of the io_uring commands.
-The arguments passed in are the same.
-.I addr
-must contain a pointer to the array of file descriptors,
-.I len
-must contain the length of the array, and
-.I off
-must contain the offset at which to operate. Note that the array of file
-descriptors pointed to in
-.I addr
-must remain valid until this operation has completed. Available since 5.6.
-
-.TP
-.B IORING_OP_PROVIDE_BUFFERS
-This command allows an application to register a group of buffers to be used
-by commands that read/receive data. Using buffers in this manner can eliminate
-the need to separate the poll + read, which provides a convenient point in
-time to allocate a buffer for a given request. It's often infeasible to have
-as many buffers available as pending reads or receive. With this feature, the
-application can have its pool of buffers ready in the kernel, and when the
-file or socket is ready to read/receive data, a buffer can be selected for the
-operation.
-.I fd
-must contain the number of buffers to provide,
-.I addr
-must contain the starting address to add buffers from,
-.I len
-must contain the length of each buffer to add from the range,
-.I buf_group
-must contain the group ID of this range of buffers, and
-.I off
-must contain the starting buffer ID of this range of buffers. With that set,
-the kernel adds buffers starting with the memory address in
-.I addr,
-each with a length of
-.I len.
-Hence the application should provide
-.I len * fd
-worth of memory in
-.I addr.
-Buffers are grouped by the group ID, and each buffer within this group will be
-identical in size according to the above arguments. This allows the application
-to provide different groups of buffers, and this is often used to have
-differently sized buffers available depending on what the expectations are of
-the individual request. When submitting a request that should use a provided
-buffer, the
-.B IOSQE_BUFFER_SELECT
-flag must be set, and
-.I buf_group
-must be set to the desired buffer group ID where the buffer should be selected
-from. Available since 5.7.
-
-.TP
-.B IORING_OP_REMOVE_BUFFERS
-Remove buffers previously registered with
-.BR IORING_OP_PROVIDE_BUFFERS .
-.I fd
-must contain the number of buffers to remove, and
-.I buf_group
-must contain the buffer group ID from which to remove the buffers. Available
-since 5.7.
-
-.TP
-.B IORING_OP_SHUTDOWN
-Issue the equivalent of a
-.BR shutdown (2)
-system call.
-.I fd
-is the file descriptor to the socket being shutdown, and
-.I len
-must be set to the
-.I how
-argument. No no other fields should be set. Available since 5.11.
-
-.TP
-.B IORING_OP_RENAMEAT
-Issue the equivalent of a
-.BR renameat2 (2)
-system call.
-.I fd
-should be set to the
-.IR olddirfd ,
-.I addr
-should be set to the
-.IR oldpath ,
-.I len
-should be set to the
-.IR newdirfd ,
-.I addr
-should be set to the
-.IR oldpath ,
-.I addr2
-should be set to the
-.IR newpath ,
-and finally
-.I rename_flags
-should be set to the
-.I flags
-passed in to
-.BR renameat2 (2).
-Available since 5.11.
-
-.TP
-.B IORING_OP_UNLINKAT
-Issue the equivalent of a
-.BR unlinkat (2)
-system call.
-.I fd
-should be set to the
-.IR dirfd ,
-.I addr
-should be set to the
-.IR pathname ,
-and
-.I unlink_flags
-should be set to the
-.I flags
-being passed in to
-.BR unlinkat (2).
-Available since 5.11.
-
-.TP
-.B IORING_OP_MKDIRAT
-Issue the equivalent of a
-.BR mkdirat (2)
-system call.
-.I fd
-should be set to the
-.IR dirfd ,
-.I addr
-should be set to the
-.IR pathname ,
-and
-.I len
-should be set to the
-.I mode
-being passed in to
-.BR mkdirat (2).
-Available since 5.15.
-
-.TP
-.B IORING_OP_SYMLINKAT
-Issue the equivalent of a
-.BR symlinkat (2)
-system call.
-.I fd
-should be set to the
-.IR newdirfd ,
-.I addr
-should be set to the
-.I target
-and
-.I addr2
-should be set to the
-.I linkpath
-being passed in to
-.BR symlinkat (2).
-Available since 5.15.
-
-.TP
-.B IORING_OP_LINKAT
-Issue the equivalent of a
-.BR linkat (2)
-system call.
-.I fd
-should be set to the
-.IR olddirfd ,
-.I addr
-should be set to the
-.IR oldpath ,
-.I len
-should be set to the
-.IR newdirfd ,
-.I addr2
-should be set to the
-.IR newpath ,
-and
-.I hardlink_flags
-should be set to the
-.I flags
-being passed in to
-.BR linkat (2).
-Available since 5.15.
-
-.TP
-.B IORING_OP_MSG_RING
-Send a message to an io_uring.
-.I fd
-must be set to a file descriptor of a ring that the application has access to,
-.I len
-can be set to any 32-bit value that the application wishes to pass on, and
-.I off
-should be set any 64-bit value that the application wishes to send. On the
-target ring, a CQE will be posted with the
-.I res
-field matching the
-.I len
-set, and a
-.I user_data
-field matching the
-.I off
-value being passed in. This request type can be used to either just wake or
-interrupt anyone waiting for completions on the target ring, or it can be used
-to pass messages via the two fields. Available since 5.18.
-
-.TP
-.B IORING_OP_SOCKET
-Issue the equivalent of a
-.BR socket (2)
-system call.
-.I fd
-must contain the communication domain,
-.I off
-must contain the communication type,
-.I len
-must contain the protocol, and
-.I rw_flags
-is currently unused and must be set to zero. See also
-.BR socket (2)
-for the general description of the related system call. Available since 5.19.
-
-If the
-.I file_index
-field is set to a positive number, the file won't be installed into the
-normal file table as usual but will be placed into the fixed file table at index
-.I file_index
-- 1.
-In this case, instead of returning a file descriptor, the result will contain
-either 0 on success or an error. If the index points to a valid empty slot, the
-installation is guaranteed to not fail. If there is already a file in the slot,
-it will be replaced, similar to
-.BR IORING_OP_FILES_UPDATE .
-Please note that only io_uring has access to such files and no other syscall
-can use them. See
-.B IOSQE_FIXED_FILE
-and
-.BR IORING_REGISTER_FILES .
-
-Available since 5.19.
-
-.TP
-.B IORING_OP_URING_CMD
-Issues an asynchronous, per-file private operation, similar to
-.BR ioctl (2).
-Further information may be found in the dedicated man page of
-.BR IORING_OP_URING_CMD .
-
-Available since 5.19.
-
-.TP
-.B IORING_OP_SEND_ZC
-Issue the zerocopy equivalent of a
-.BR send(2)
-system call. Similar to
-.BR IORING_OP_SEND ,
-but tries to avoid making intermediate
-copies of data. Zerocopy execution is not guaranteed and may fall back to
-copying. The request may also fail with
-.BR -EOPNOTSUPP ,
-when a protocol doesn't support zerocopy, in which case users are recommended
-to use copying sends instead.
-
-The
-.I flags
-field of the first
-.I "struct io_uring_cqe"
-may likely contain
-.BR IORING_CQE_F_MORE ,
-which means that there will be a second completion event / notification for
-the request, with the
-.I user_data
-field set to the same value. The user must not modify the data buffer until the
-notification is posted. The first cqe follows the usual rules and so its
-.I res
-field will contain the number of bytes sent or a negative error code. The
-notification's
-.I res
-field will be set to zero and the
-.I flags
-field will contain
-.BR IORING_CQE_F_NOTIF .
-The two step model is needed because the kernel may hold on to buffers for a
-long time, e.g. waiting for a TCP ACK, and having a separate cqe for request
-completions allows userspace to push more data without extra delays. Note,
-notifications are only responsible for controlling the lifetime of the buffers,
-and as such don't mean anything about whether the data has atually been sent
-out or received by the other end. Even errored requests may generate a
-notification, and the user must check for
-.B IORING_CQE_F_MORE
-rather than relying on the result.
-
-.I fd
-must be set to the socket file descriptor,
-.I addr
-must contain a pointer to the buffer,
-.I len
-denotes the length of the buffer to send, and
-.I msg_flags
-holds the flags associated with the system call. When
-.I addr2
-is non-zero it points to the address of the target with
-.I addr_len
-specifying its size, turning the request into a
-.BR sendto (2)
-system call equivalent.
-
-Available since 6.0.
-
-This command also supports the following modifiers in
-.I ioprio:
-
-.PP
-.in +12
-.B IORING_RECVSEND_POLL_FIRST
-If set, io_uring will assume the socket is currently full and attempting to
-send data will be unsuccessful. For this case, io_uring will arm internal
-poll and trigger a send of the data when there is enough space available.
-This initial send attempt can be wasteful for the case where the socket
-is expected to be full, setting this flag will bypass the initial send
-attempt and go straight to arming poll. If poll does indicate that data can
-be sent, the operation will proceed.
-
-.B IORING_RECVSEND_FIXED_BUF
-If set, instructs io_uring to use a pre-mapped buffer. The
-.I buf_index
-field should contain an index into an array of fixed buffers. See
-.BR io_uring_register (2)
-for details on how to setup a context for fixed buffer I/O.
-.EE
-.in
-.PP
-
-.TP
-.B IORING_OP_SENDMSG_ZC
-Issue the zerocopy equivalent of a
-.BR sendmsg (2)
-system call.
-Works just like
-.BR IORING_OP_SENDMSG ,
-but like
-.B IORING_OP_SEND_ZC
-supports
-.BR IORING_RECVSEND_FIXED_BUF .
-For additional notes regarding zero copy see
-.BR IORING_OP_SEND_ZC .
-
-Available since 6.1
-
-.TP
-.B IORING_OP_WAITID
-Issue the equivalent of a
-.BR waitid (2)
-system call.
-.I len
-must contain the idtype being queried/waited for and
-.I fd
-must contain the 'pid' (or id) being waited for.
-.I file_index
-is the 'options' being set (the child state changes to wait for).
-.I addr2
-is a pointer to siginfo_t, if any, being filled in. See also
-.BR waitid (2)
-for the general description of the related system call. Available since 6.5.
-
-.TP
-.B IORING_OP_SETXATTR
-.TP
-.B IORING_OP_GETXATTR
-.TP
-.B IORING_OP_FSETXATTR
-.TP
-.B IORING_OP_FGETXATTR
-Issue the equivalent of a
-.BR setxattr (2)
-or
-.BR getxattr (2)
-or
-.BR fsetxattr (2)
-or
-.BR fgetxattr (2)
-system call.
-.I addr
-must contain a pointer to a buffer containing the name of the extended
-attribute.
-.I addr2
-must contain a pointer to a buffer of maximum length
-.IR len ,
-in which the value of the extended attribute is to be placed or is read from.
-Additional flags maybe provided in
-.IR xattr_flags .
-For
-.BR setxattr (2)
-or
-.BR getxattr (2)
-.I addr3
-must contain a pointer to the path of the file.
-For
-.BR fsetxattr (2)
-or
-.BR fgetxattr (2)
-.I fd
-must contain the file descriptor of the file.
-
-Available since 5.19.
-
-.TP
-.B IORING_OP_BIND
-Issues the equivalent of the
-.BR bind (2)
-system call.
-.I fd
-must contain the file descriptor of the socket,
-.I addr
-must contain a pointer to the sockaddr struct containing the address to assign
-and
-.I addr2
-must contain the length of the address.
-
-Available since 6.11.
-
-.TP
-.B IORING_OP_LISTEN
-Issues the equivalent of the
-.BR listen (2)
-system call.
-.I fd
-must contain the file descriptor of the socket and
-.I len
-must contain the backlog parameter, i.e. the maximum amount of pending
-queued connections.
-
-Available since 6.11.
-
-.TP
-.B IORING_OP_FTRUNCATE
-Issues the equivalent of the
-.BR ftruncate (2)
-system call.
-.I fd
-must contain the file descriptor of the file to truncate and
-.I off
-must contain the length to which the file will be truncated.
-
-Available since 6.9.
-
-.TP
-.B IORING_OP_READ_MULTISHOT
-Like
-.BR IORING_OP_READ ,
-but similar to requests prepared with
-.IR io_uring_prep_multishot_accept (3)
-additional reads and thus CQEs will be performed based on this single SQE once
-there is more data available.
-Is restricted to pollable files and will fall back to single shot if the file
-does not support
-.BR NOWAIT .
-Like other multishot type requests, the application should look at the CQE
-flags and see if
-.B IORING_CQE_F_MORE
-is set on completion as an indication of whether or not the read request will
-generate further CQEs. Available since 6.7.
-
-.TP
-.B IORING_OP_FUTEX_WAIT
-Issues the equivalent of the
-.BR futex_wait (2)
-system call.
-.I addr
-must hold a pointer to the futex,
-.I addr2
-must hold the value to which the futex has to be changed so this caller to
-.BR futex_wait (2)
-can be woken by a call to
-.BR futex_wake (2),
-.I addr3
-must hold the bitmask of this
-.BR futex_wait (2)
-caller.
-For a caller of
-.BR futex_wake (2)
-to wake a waiter additionally the bitmask of the waiter and waker must have
-at least one set bit in common.
-.I fd
-must contain additional flags passed in.
-
-Available since 6.7.
-
-.TP
-.B IORING_OP_FUTEX_WAKE
-Issues the equivalent of the
-.BR futex_wake (2)
-system call.
-.I addr
-must hold a pointer to the futex,
-.I addr2
-must hold the maximum number of waiters waiting on this futex to wake,
-.I addr3
-must hold the bitmask of this
-.BR futex_wake (2)
-call.
-To wake a waiter additionally the bitmask of the waiter and waker must have
-at least one set bit in common.
-.I fd
-must contain additional flags passed in.
-
-Available since 6.7.
-
-.TP
-.B IORING_OP_FUTEX_WAITV
-Issues the equivalent of the
-.BR futex_waitv (2)
-system call.
-.I addr
-must hold a pointer to the futexv struct,
-.I len
-must hold the length of the futexv struct, which may not be 0 and must be
-smaller than
-.B FUTEX_WAITV_MAX
-(as of 6.11 == 128).
-
-Available since 6.7.
-
-.TP
-.B IORING_OP_FIXED_FD_INSTALL
-This operation is used to insert a registered file into the regular process
-file table.
-Consequently
-.I fd
-must contain the file index and
-.B IOSQE_FIXED_FILE
-must be set.
-The resulting regular fd is returned via cqe->res.
-Additional flags may be passed in via
-.IR install_fd_flags .
-Currently supported flags are:
-.BR IORING_FIXED_FD_NO_CLOEXEC ,
-which overrides a potentially set
-.B O_CLOEXEC
-flag set on the initial file.
-
-Available since 6.8.
-
-.TP
-.B IORING_OP_PIPE
-This operation is used to create a pipe, a set of file descriptors that can be
-used for communication. The pipe may either be created as a set of normal
-file descriptors, or it can be created as fixed/direct descriptors.
-.I addr
-must contain a pointer to an array of two integers, where upon successful
-completion of the request, index 0 will contain the read side and index 1 the
-write side of the pipe.
-.I pipe_flags
-may contain flags associated with pipe creation. Currently
-.B O_CLOEXEC | O_NONBLOCK | O_DIRECT | O_NOTIFICATION_PIPE
-are supported.
-.I file_index
-may contain the the desired starting point for a fixed descriptor pipe
-creation. If this is set to
-.B 0,
-then regular file descriptors are used. If set to
-.B IORING_FILE_INDEX_ALLOC,
-then the kernel will allocate descriptors from the previously registered
-direct descriptor table. If set to any non-zero value, then it sets the
-exact direct descriptor value for index 0 of the pipe, and index 1 will be
-the following integer value.
-
-If used with direct descriptors rather than normal file descriptors, a
-direct descriptor table must have been previously registered with the kernel.
-
-Available since 6.16.
-
-.TP
-.B IORING_OP_RECV_ZC
-Receive data from a socket using zero-copy techniques. Unlike
-.BR IORING_OP_RECV ,
-this operation does not use a user-provided buffer. Instead, data is delivered
-through a pre-registered zero-copy RX interface queue.
-.I fd
-must be set to the socket file descriptor.
-.I zcrx_ifq_idx
-specifies the index of the registered zero-copy RX interface queue.
-.I len
-specifies the maximum amount of data to receive.
-.I ioprio
-can contain flags such as
-.B IORING_RECVSEND_POLL_FIRST
-and
-.BR IORING_RECV_MULTISHOT .
-This operation requires multishot mode.
-
-Before using this command, a zero-copy RX interface queue must be registered via
-.BR io_uring_register (2)
-using
-.BR IORING_REGISTER_ZCRX_IFQ .
-Data completions are posted as auxiliary CQEs.
-
-Available since 6.15.
-
-.TP
-.B IORING_OP_EPOLL_WAIT
-Wait for events on an epoll instance. This is an async version of
-.BR epoll_wait (2).
-.I fd
-must be set to the epoll file descriptor,
-.I addr
-must point to an array of
-.I struct epoll_event
-to receive the events, and
-.I len
-must contain the maximum number of events to return.
-
-The primary use case is for legacy event loops that still use epoll for some
-file descriptors. By using io_uring to wait on epoll events, the application
-can unify its event handling through io_uring while maintaining backwards
-compatibility with epoll-based components.
-
-Available since 6.15.
-
-.TP
-.B IORING_OP_READV_FIXED
-.TP
-.B IORING_OP_WRITEV_FIXED
-Vectored read and write operations using pre-registered buffers, combining the
-functionality of
-.BR IORING_OP_READV / IORING_OP_WRITEV
-with
-.BR IORING_OP_READ_FIXED / IORING_OP_WRITE_FIXED .
-The
-.I buf_index
-field specifies the index into the registered buffer table. Unlike the
-non-fixed vectored operations, the iovec entries point into the registered
-buffer region. This allows vectored I/O while still benefiting from the
-reduced overhead of pre-registered buffers.
-
-Available since 6.15.
-
-.TP
-.B IORING_OP_NOP128
-No operation, similar to
-.BR IORING_OP_NOP ,
-but explicitly uses a 128-byte SQE. This can be useful for testing or
-alignment purposes when using mixed 64/128-byte SQE rings
-.RB ( IORING_SETUP_SQE_MIXED ).
-
-Available since 6.19.
-
-.TP
-.B IORING_OP_URING_CMD128
-Passthrough command to the underlying file, identical to
-.BR IORING_OP_URING_CMD ,
-but explicitly uses a 128-byte SQE. The extra 64 bytes provide additional
-space for command-specific data. This is useful with
-.B IORING_SETUP_SQE_MIXED
-rings where some commands need the larger SQE size while others do not.
-
-See
-.BR IORING_OP_URING_CMD
-for general usage details.
-
-Available since 6.19.
-
-.PP
-The
-.I flags
-field is a bit mask. The supported flags are:
-.TP
-.B IOSQE_FIXED_FILE
-When this flag is specified,
-.I fd
-is an index into the files array registered with the io_uring instance (see the
-.B IORING_REGISTER_FILES
-section of the
-.BR io_uring_register (2)
-man page). Note that this isn't always available for all commands. If used on
-a command that doesn't support fixed files, the SQE will error with
-.BR -EBADF .
-Available since 5.1.
-.TP
-.B IOSQE_IO_DRAIN
-When this flag is specified, the SQE will not be started before previously
-submitted SQEs have completed, and new SQEs will not be started before this
-one completes. Available since 5.2.
-.TP
-.B IOSQE_IO_LINK
-When this flag is specified, the SQE forms a link with the next SQE in the
-submission ring. That next SQE will not be started before the previous request
-completes. This, in effect, forms a chain of SQEs, which can be arbitrarily
-long. The tail of the chain is denoted by the first SQE that does not have this
-flag set. Chains are not supported across submission boundaries. Even if the
-last SQE in a submission has this flag set, it will still terminate the current
-chain. This flag has no effect on previous SQE submissions, nor does it impact
-SQEs that are outside of the chain tail. This means that multiple chains can be
-executing in parallel, or chains and individual SQEs. Only members inside the
-chain are serialized. A chain of SQEs will be broken if any request in that
-chain ends in error. io_uring considers any unexpected result an error. This
-means that, eg, a short read will also terminate the remainder of the chain.
-If a chain of SQE links is broken, the remaining unstarted part of the chain
-will be terminated and completed with
-.B -ECANCELED
-as the error code. Available since 5.3.
-.TP
-.B IOSQE_IO_HARDLINK
-Like IOSQE_IO_LINK, but it doesn't sever regardless of the completion result.
-Note that the link will still sever if we fail submitting the parent request,
-hard links are only resilient in the presence of completion results for
-requests that did submit correctly.
-.B IOSQE_IO_HARDLINK
-implies
-.BR IOSQE_IO_LINK .
-Available since 5.5.
-.TP
-.B IOSQE_ASYNC
-Normal operation for io_uring is to try and issue an sqe as non-blocking first,
-and if that fails, execute it in an async manner. To support more efficient
-overlapped operation of requests that the application knows/assumes will
-always (or most of the time) block, the application can ask for an sqe to be
-issued async from the start. Available since 5.6.
-.TP
-.B IOSQE_BUFFER_SELECT
-Used in conjunction with the
-.B IORING_OP_PROVIDE_BUFFERS
-command, which registers a pool of buffers to be used by commands that read
-or receive data. When buffers are registered for this use case, and this
-flag is set in the command, io_uring will grab a buffer from this pool when
-the request is ready to receive or read data. If successful, the resulting CQE
-will have
-.B IORING_CQE_F_BUFFER
-set in the flags part of the struct, and the upper
-.B IORING_CQE_BUFFER_SHIFT
-bits will contain the ID of the selected buffers. This allows the application
-to know exactly which buffer was selected for the operation. If no buffers
-are available and this flag is set, then the request will fail with
-.B -ENOBUFS
-as the error code. Once a buffer has been used, it is no longer available in
-the kernel pool. The application must re-register the given buffer again when
-it is ready to recycle it (eg has completed using it). Available since 5.7.
-.TP
-.B IOSQE_CQE_SKIP_SUCCESS
-Don't generate a CQE if the request completes successfully. If the request
-fails, an appropriate CQE will be posted as usual and if there is no
-.B IOSQE_IO_HARDLINK,
-CQEs for all linked requests will be omitted. The notion of failure/success is
-opcode specific and is the same as with breaking chains of
-.BR IOSQE_IO_LINK .
-One special case is when the request has a linked timeout, then the CQE
-generation for the linked timeout is decided solely by whether it has
-.B IOSQE_CQE_SKIP_SUCCESS
-set, regardless whether it timed out or was canceled. In other words, if a
-linked timeout has the flag set, it's guaranteed to not post a CQE.
-
-The semantics are chosen to accommodate several use cases. First, when all but
-the last request of a normal link without linked timeouts are marked with the
-flag, only one CQE per link is posted. Additionally, it enables suppression of
-CQEs in cases where the side effects of a successfully executed operation is
-enough for userspace to know the state of the system. One such example would
-be writing to a synchronisation file.
-
-This flag is incompatible with
-.BR IOSQE_IO_DRAIN .
-Using both of them in a single ring is undefined behavior, even when they are
-not used together in a single request. Currently, after the first request with
-.BR IOSQE_CQE_SKIP_SUCCESS ,
-all subsequent requests marked with drain will be failed at submission time.
-Note that the error reporting is best effort only, and restrictions may change
-in the future.
-
-Available since 5.17.
-
-.PP
-.I ioprio
-specifies the I/O priority. See
-.BR ioprio_get (2)
-for a description of Linux I/O priorities.
-
-.I fd
-specifies the file descriptor against which the operation will be
-performed, with the exception noted above.
-
-If the operation is one of
-.B IORING_OP_READ_FIXED
-or
-.BR IORING_OP_WRITE_FIXED ,
-.I addr
-and
-.I len
-must fall within the buffer located at
-.I buf_index
-in the fixed buffer array. If the operation is either
-.B IORING_OP_READV
-or
-.BR IORING_OP_WRITEV ,
-then
-.I addr
-points to an iovec array of
-.I len
-entries.
-
-.IR rw_flags ,
-specified for read and write operations, contains a bitwise OR of
-per-I/O flags, as described in the
-.BR preadv2 (2)
-man page.
-
-The
-.I fsync_flags
-bit mask may contain either 0, for a normal file integrity sync, or
-.B IORING_FSYNC_DATASYNC
-to provide data sync only semantics. See the descriptions of
-.B O_SYNC
-and
-.B O_DSYNC
-in the
-.BR open (2)
-manual page for more information.
-
-The bits that may be set in
-.I poll_events
-are defined in \fI<poll.h>\fP, and documented in
-.BR poll (2).
-
-.I user_data
-is an application-supplied value that will be copied into
-the completion queue entry (see below).
-.I buf_index
-is an index into an array of fixed buffers, and is only valid if fixed
-buffers were registered.
-.I personality
-is the credentials id to use for this operation. See
-.BR io_uring_register (2)
-for how to register personalities with io_uring. If set to 0, the current
-personality of the submitting task is used.
-.PP
-Once the submission queue entry is initialized, I/O is submitted by
-placing the index of the submission queue entry into the tail of the
-submission queue. After one or more indexes are added to the queue,
-and the queue tail is advanced, the
-.BR io_uring_enter (2)
-system call can be invoked to initiate the I/O.
-
-Completions use the following data structure:
-.PP
-.in +4n
-.EX
-/*
- * IO completion data structure (Completion Queue Entry)
- */
-struct io_uring_cqe {
- __u64 user_data; /* sqe->data submission passed back */
- __s32 res; /* result code for this event */
- __u32 flags;
-};
-.EE
-.in
-.PP
-.I user_data
-is copied from the field of the same name in the submission queue
-entry. The primary use case is to store data that the application
-will need to access upon completion of this particular I/O. The
-.I flags
-is used for certain commands, like
-.B IORING_OP_POLL_ADD
-or in conjunction with
-.B IOSQE_BUFFER_SELECT
-or
-.BR IORING_OP_MSG_RING ,
-see those entries for details.
-.I res
-is the operation-specific result, but io_uring-specific errors
-(e.g. flags or opcode invalid) are returned through this field.
-They are described in section
-.B CQE
-.BR ERRORS .
-.PP
-For read and write opcodes, the
-return values match
-.I errno
-values documented in the
-.BR preadv2 (2)
-and
-.BR pwritev2 (2)
-man pages, with
-.I
-res
-holding the equivalent of
-.I -errno
-for error cases, or the transferred number of bytes in case the operation
-is successful. Hence both error and success return can be found in that
-field in the CQE. For other request types, the return values are documented
-in the matching man page for that type, or in the opcodes section above for
-io_uring-specific opcodes.
-.PP
-.SH RETURN VALUE
-.BR io_uring_enter (2)
-returns the number of I/Os successfully consumed. This can be zero
-if
-.I to_submit
-was zero or if the submission queue was empty. Note that if the ring was
-created with
-.B IORING_SETUP_SQPOLL
-specified, then the return value will generally be the same as
-.I to_submit
-as submission happens outside the context of the system call.
-
-The errors related to a submission queue entry will be returned through a
-completion queue entry (see section
-.B CQE
-.BR ERRORS ),
-rather than through the system call itself.
-
-Errors that occur not on behalf of a submission queue entry are returned via the
-system call directly. On such an error, a negative error code is returned. The
-caller should not rely on
-.I errno
-variable.
-.PP
-.SH ERRORS
-These are the errors returned by
-.BR io_uring_enter (2)
-system call.
-.TP
-.B EAGAIN
-The kernel was unable to allocate memory for the request, or otherwise ran out
-of resources to handle it. The application should wait for some completions and
-try again.
-.TP
-.B EBADF
-.I fd
-is not a valid file descriptor.
-.TP
-.B EBADFD
-.I fd
-is a valid file descriptor, but the io_uring ring is not in the right state
-(enabled). See
-.BR io_uring_register (2)
-for details on how to enable the ring.
-.TP
-.B EBADR
-At least one CQE was dropped even with the
-.B IORING_FEAT_NODROP
-feature, and there are no otherwise available CQEs. This clears the error state
-and so with no other changes the next call to
-.BR io_uring_enter (2)
-will not have this error. This error should be extremely rare and indicates the
-machine is running critically low on memory. It may be reasonable for the
-application to terminate running unless it is able to safely handle any CQE
-being lost.
-.TP
-.B EBUSY
-If the
-.B IORING_FEAT_NODROP
-feature flag is set, then
-.B EBUSY
-will be returned if there were overflow entries,
-.B IORING_ENTER_GETEVENTS
-flag is set and not all of the overflow entries were able to be flushed to
-the CQ ring.
-
-Without
-.B IORING_FEAT_NODROP
-the application is attempting to overcommit the number of requests it can have
-pending. The application should wait for some completions and try again. May
-occur if the application tries to queue more requests than we have room for in
-the CQ ring, or if the application attempts to wait for more events without
-having reaped the ones already present in the CQ ring.
-.TP
-.B EEXIST
-The thread submitting the work is invalid. This may occur if
-.B IORING_ENTER_GETEVENTS
-and
-.B IORING_SETUP_DEFER_TASKRUN
-is set, but the submitting thread is not the thread that initially created or
-enabled the io_uring associated with
-.I fd.
-.TP
-.B EINVAL
-Some bits in the
-.I flags
-argument are invalid.
-.TP
-.B EFAULT
-An invalid user space address was specified for the
-.I sig
-argument.
-.TP
-.B ENXIO
-The io_uring instance is in the process of being torn down.
-.TP
-.B EOPNOTSUPP
-.I fd
-does not refer to an io_uring instance.
-.TP
-.B EINTR
-The operation was interrupted by a delivery of a signal before it could
-complete; see
-.BR signal (7).
-Can happen while waiting for events with
-.B IORING_ENTER_GETEVENTS.
-.TP
-.B EOWNERDEAD
-The ring has been setup with
-.B IORING_SETUP_SQPOLL
-and the sq poll kernel thread has been killed.
-
-.SH CQE ERRORS
-These io_uring-specific errors are returned as a negative value in the
-.I res
-field of the completion queue entry.
-.TP
-.B EACCES
-The
-.I flags
-field or
-.I opcode
-in a submission queue entry is not allowed due to registered restrictions.
-See
-.BR io_uring_register (2)
-for details on how restrictions work.
-.TP
-.B EBADF
-The
-.I fd
-field in the submission queue entry is invalid, or the
-.B IOSQE_FIXED_FILE
-flag was set in the submission queue entry, but no files were registered
-with the io_uring instance.
-.TP
-.B EFAULT
-buffer is outside of the process' accessible address space
-.TP
-.B EFAULT
-.B IORING_OP_READ_FIXED
-or
-.B IORING_OP_WRITE_FIXED
-was specified in the
-.I opcode
-field of the submission queue entry, but either buffers were not
-registered for this io_uring instance, or the address range described
-by
-.I addr
-and
-.I len
-does not fit within the buffer registered at
-.IR buf_index .
-.TP
-.B EINVAL
-The
-.I flags
-field or
-.I opcode
-in a submission queue entry is invalid.
-.TP
-.B EINVAL
-The
-.I buf_index
-member of the submission queue entry is invalid.
-.TP
-.B EINVAL
-The
-.I personality
-field in a submission queue entry is invalid.
-.TP
-.B EINVAL
-.B IORING_OP_READV
-or
-.B IORING_OP_WRITEV
-was specified in the submission queue entry, but the io_uring instance
-has fixed buffers registered.
-.TP
-.B EINVAL
-.B IORING_OP_READ_FIXED
-or
-.B IORING_OP_WRITE_FIXED
-was specified in the submission queue entry, and the
-.I buf_index
-is invalid.
-.TP
-.B EINVAL
-.BR IORING_OP_READV ,
-.BR IORING_OP_WRITEV ,
-.BR IORING_OP_READ_FIXED ,
-.B IORING_OP_WRITE_FIXED
-or
-.B IORING_OP_FSYNC
-was specified in the submission queue entry, but the io_uring instance
-was configured for IOPOLLing, or any of
-.IR addr ,
-.IR ioprio ,
-.IR off ,
-.IR len ,
-or
-.I buf_index
-was set in the submission queue entry.
-.TP
-.B EINVAL
-.B IORING_OP_POLL_ADD
-or
-.B IORING_OP_POLL_REMOVE
-was specified in the
-.I opcode
-field of the submission queue entry, but the io_uring instance was
-configured for busy-wait polling
-.RB ( IORING_SETUP_IOPOLL ),
-or any of
-.IR ioprio ,
-.IR off ,
-.IR len ,
-or
-.I buf_index
-was non-zero in the submission queue entry.
-.TP
-.B EINVAL
-.B IORING_OP_POLL_ADD
-was specified in the
-.I opcode
-field of the submission queue entry, and the
-.I addr
-field was non-zero.
-.TP
-.B EOPNOTSUPP
-.I opcode
-is valid, but not supported by this kernel.
-.TP
-.B EOPNOTSUPP
-.B IOSQE_BUFFER_SELECT
-was set in the
-.I flags
-field of the submission queue entry, but the
-.I opcode
-doesn't support buffer selection.
-.TP
-.B EINVAL
-.B IORING_OP_TIMEOUT
-was specified, but
-.I timeout_flags
-specified more than one clock source or
-.B IORING_TIMEOUT_MULTISHOT
-was set alongside
-.BR IORING_TIMEOUT_ABS .
diff --git a/man/io_uring_enter.2.md b/man/io_uring_enter.2.md
new file mode 100644
index 00000000..fcbfe17d
--- /dev/null
+++ b/man/io_uring_enter.2.md
@@ -0,0 +1,1466 @@
+.\" Copyright (C) 2019 Jens Axboe <axboe@kernel.dk>
+.\" Copyright (C) 2019 Red Hat, Inc.
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 22, 2019
+footer: Linux
+header: Linux Programmer\'s Manual
+section: 2
+title: io_uring_enter
+---
+
+# NAME
+
+io_uring_enter - initiate and/or complete asynchronous I/O
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_enter(unsigned int fd , unsigned int to_submit ,
+ unsigned int min_complete , unsigned int flags ,
+ sigset_t * sig );
+
+ int io_uring_enter2(unsigned int fd , unsigned int to_submit ,
+ unsigned int min_complete , unsigned int flags ,
+ void * arg , size_t sz );
+```
+
+# DESCRIPTION
+
+**io_uring_enter**(2) is used to initiate and complete I/O using the
+shared submission and completion queues setup by a call to
+**io_uring_setup**(2). A single call can both submit new I/O and wait
+for completions of I/O initiated by this call or previous calls to
+**io_uring_enter**(2).
+
+*fd* is the file descriptor returned by **io_uring_setup**(2).
+*to_submit* specifies the number of I/Os to submit from the submission
+queue. *flags* is a bitmask of the following values:
+
+**IORING_ENTER_GETEVENTS**
+
+: If this flag is set, then the system call will wait for the specified
+ number of events in *min_complete* before returning. This flag can be
+ set along with *to_submit* to both submit and complete events in a
+ single system call. If this flag is set either the flag
+ **IORING_SETUP_DEFER_TASKRUN** must not be set or the thread issuing
+ the syscall must be the thread that created the io_uring associated
+ with *fd,* or be the thread that enabled the ring originally created
+ with **IORING_SETUP_R_DISABLED** via **io_uring_register**(2) or
+ **io_uring_enable_rings**(3).
+
+**IORING_ENTER_SQ_WAKEUP**
+
+: If the ring has been created with **IORING_SETUP_SQPOLL,** then this
+ flag asks the kernel to wakeup the SQ kernel thread to submit IO.
+
+**IORING_ENTER_SQ_WAIT**
+
+: If the ring has been created with **IORING_SETUP_SQPOLL,** then the
+ application has no real insight into when the SQ kernel thread has
+ consumed entries from the SQ ring. This can lead to a situation where
+ the application can no longer get a free SQE entry to submit, without
+ knowing when one will become available as the SQ kernel thread
+ consumes them. If the system call is used with this flag set, then it
+ will wait until at least one entry is free in the SQ ring.
+
+**IORING_ENTER_EXT_ARG**
+
+: By default, *arg* is a *sigset_t* pointer. If **IORING_ENTER_EXT_ARG**
+ is set (supported since kernel 5.11), then *arg* is instead a pointer
+ to a *struct io_uring_getevents_arg* and *argsz* must be set to the
+ size of this structure. The definition is as follows:
+
+ ``` text
+ struct io_uring_getevents_arg {
+ __u64 sigmask;
+ __u32 sigmask_sz;
+ __u32 pad;
+ __u64 ts;
+ };
+ ```
+
+ which allows passing in both a signal mask as well as pointer to a
+ *struct \_\_kernel_timespec* timeout value. If *ts* is set to a valid
+ pointer, then this time value indicates the timeout for waiting on
+ events. If an application is waiting on events and wishes to stop
+ waiting after a specified amount of time, then this can be
+ accomplished directly in version 5.11 and newer by using this feature.
+
+**IORING_ENTER_REGISTERED_RING**
+
+: If the ring file descriptor has been registered through use of
+ **IORING_REGISTER_RING_FDS**, then setting this flag will tell the
+ kernel that the *ring_fd* passed in is the registered ring offset
+ rather than a normal file descriptor.
+
+**IORING_ENTER_ABS_TIMER**
+
+: When this flag is set, the timeout argument passed in *struct
+ io_uring_getevents_arg* will be interpreted as an absolute time of the
+ registered clock (see **IORING_REGISTER_CLOCK)** until which the
+ waiting should end.
+
+ Available since 6.12
+
+**IORING_ENTER_EXT_ARG_REG**
+
+: When this flag is set, *arg* is not a pointer to a
+ *struct*io_uring_getevents_arg*,* but merely an offset into an area of
+ wait regions previously registered with **io_uring_register**(2) using
+ the **IORING_REGISTER_MEM_REGION** operation.
+
+ Available since 6.13
+
+**IORING_ENTER_NO_IOWAIT**
+
+: When this flag is set, the system call will not mark the waiting task
+ as being in iowait if it is sleeping waiting on events and there are
+ pending requests. This is useful if iowait isn\'t expected when
+ waiting for events. It can also prevent extra power usage by allowing
+ the CPU to enter lower sleep states. This flag is only available if
+ the kernel supports the **IORING_FEAT_NO_IOWAIT** feature.
+
+ Available since 6.15.
+
+If the io_uring instance was configured for polling, by specifying
+**IORING_SETUP_IOPOLL** in the call to **io_uring_setup**(2), then
+min_complete has a slightly different meaning. Passing a value of 0
+instructs the kernel to return any events which are already complete,
+without blocking. If *min_complete* is a non-zero value, the kernel will
+still return immediately if any completion events are available. If no
+event completions are available, then the call will poll either until
+one or more completions become available, or until the process has
+exceeded its scheduler time slice.
+
+Note that, for interrupt driven I/O (where **IORING_SETUP_IOPOLL** was
+not specified in the call to **io_uring_setup**(2)), an application may
+check the completion queue for event completions without entering the
+kernel at all.
+
+When the system call returns that a certain amount of SQEs have been
+consumed and submitted, it\'s safe to reuse SQE entries in the ring.
+This is true even if the actual IO submission had to be punted to async
+context, which means that the SQE may in fact not have been submitted
+yet. If the kernel requires later use of a particular SQE entry, it will
+have made a private copy of it.
+
+*sig* is a pointer to a signal mask (see **sigprocmask**(2)); if *sig*
+is not NULL, **io_uring_enter**(2) first replaces the current signal
+mask by the one pointed to by *sig*, then waits for events to become
+available in the completion queue, and then restores the original signal
+mask. The following **io_uring_enter**(2) call:
+
+``` text
+ret = io_uring_enter(fd, 0, 1, IORING_ENTER_GETEVENTS, &sig);
+```
+
+is equivalent to *atomically* executing the following calls:
+
+``` text
+pthread_sigmask(SIG_SETMASK, &sig, &orig);
+ret = io_uring_enter(fd, 0, 1, IORING_ENTER_GETEVENTS, NULL);
+pthread_sigmask(SIG_SETMASK, &orig, NULL);
+```
+
+See the description of **pselect**(2) for an explanation of why the
+*sig* parameter is necessary.
+
+Submission queue entries are represented using the following data
+structure:
+
+``` text
+/*
+ * IO submission data structure (Submission Queue Entry)
+ */
+struct io_uring_sqe {
+ __u8 opcode; /* type of operation for this sqe */
+ __u8 flags; /* IOSQE_ flags */
+ __u16 ioprio; /* ioprio for the request */
+ __s32 fd; /* file descriptor to do IO on */
+ union {
+ __u64 off; /* offset into file */
+ __u64 addr2;
+ struct {
+ __u32 cmd_op;
+ __u32 __pad1;
+ };
+ };
+ union {
+ __u64 addr; /* pointer to buffer or iovecs */
+ __u64 splice_off_in;
+ struct {
+ __u32 level;
+ __u32 optname;
+ };
+ };
+ __u32 len; /* buffer size or number of iovecs */
+ union {
+ __kernel_rwf_t rw_flags;
+ __u32 fsync_flags;
+ __u16 poll_events; /* compatibility */
+ __u32 poll32_events; /* word-reversed for BE */
+ __u32 sync_range_flags;
+ __u32 msg_flags;
+ __u32 timeout_flags;
+ __u32 accept_flags;
+ __u32 cancel_flags;
+ __u32 open_flags;
+ __u32 statx_flags;
+ __u32 fadvise_advice;
+ __u32 splice_flags;
+ __u32 rename_flags;
+ __u32 unlink_flags;
+ __u32 hardlink_flags;
+ __u32 xattr_flags;
+ __u32 msg_ring_flags;
+ __u32 uring_cmd_flags;
+ __u32 waitid_flags;
+ __u32 futex_flags;
+ __u32 install_fd_flags;
+ __u32 nop_flags;
+ };
+ __u64 user_data; /* data to be passed back at completion time */
+ /* pack this to avoid bogus arm OABI complaints */
+ union {
+ /* index into fixed buffers, if used */
+ __u16 buf_index;
+ /* for grouped buffer selection */
+ __u16 buf_group;
+ } __attribute__((packed));
+ /* personality to use, if used */
+ __u16 personality;
+ union {
+ __s32 splice_fd_in;
+ __u32 file_index;
+ __u32 optlen;
+ struct {
+ __u16 addr_len;
+ __u16 __pad3[1];
+ };
+ };
+ union {
+ struct {
+ __u64 addr3;
+ __u64 __pad2[1];
+ };
+ __u64 optval;
+ /*
+ * If the ring is initialized with IORING_SETUP_SQE128, then
+ * this field is used for 80 bytes of arbitrary command data
+ */
+ __u8 cmd[0];
+ };
+};
+```
+
+The *opcode* describes the operation to be performed. It can be one of:
+
+**IORING_OP_NOP**
+
+: Do not perform any I/O. This is useful for testing the performance of
+ the io_uring implementation itself.
+
+**IORING_OP_READV**
+
+:
+
+ **IORING_OP_WRITEV**
+
+ : Vectored read and write operations, similar to **preadv2**(2) and
+ **pwritev2**(2). If the file is not seekable, *off* must be set to
+ zero or -1.
+
+ **IORING_OP_READ_FIXED**
+
+ :
+
+ **IORING_OP_WRITE_FIXED**
+
+ : Read from or write to pre-mapped buffers. See
+ **io_uring_register**(2) for details on how to setup a context for
+ fixed reads and writes.
+
+ **IORING_OP_FSYNC**
+
+ : File sync. See also **fsync**(2). Optionally *off* and *len* can
+ be used to specify a range within the file to be synced rather
+ than syncing the entire file, which is the default behavior. Note
+ that, while I/O is initiated in the order in which it appears in
+ the submission queue, completions are unordered. For example, an
+ application which places a write I/O followed by an fsync in the
+ submission queue cannot expect the fsync to apply to the write.
+ The two operations execute in parallel, so the fsync may complete
+ before the write is issued to the storage. The same is also true
+ for previously issued writes that have not completed prior to the
+ fsync. To enforce ordering one may utilize linked SQEs,
+ **IOSQE_IO_DRAIN** or wait for the arrival of CQEs of requests
+ which have to be ordered before a given request before submitting
+ its SQE.
+
+ **IORING_OP_POLL_ADD**
+
+ : Poll the *fd* specified in the submission queue entry for the
+ events specified in the *poll_events* field. Unlike poll or epoll
+ without **EPOLLONESHOT**, by default this interface always works
+ in one shot mode. That is, once the poll operation is completed,
+ it will have to be resubmitted.
+
+ If **IORING_POLL_ADD_MULTI** is set in the SQE *len* field, then
+ the poll will work in multi shot mode instead. That means it\'ll
+ repatedly trigger when the requested event becomes true, and hence
+ multiple CQEs can be generated from this single SQE. The CQE
+ *flags* field will have **IORING_CQE_F_MORE** set on completion if
+ the application should expect further CQE entries from the
+ original request. If this flag isn\'t set on completion, then the
+ poll request has been terminated and no further events will be
+ generated. This mode is available since 5.13.
+
+ This command works like an async **poll(2)** and the completion
+ event result is the returned mask of events.
+
+ Without **IORING_POLL_ADD_MULTI** and the initial poll operation
+ with **IORING_POLL_ADD_MULTI** the operation is level triggered,
+ i.e. if there is data ready or events pending etc. at the time of
+ submission a corresponding CQE will be posted. Potential further
+ completions beyond the first caused by a **IORING_POLL_ADD_MULTI**
+ are edge triggered.
+
+ **IORING_OP_POLL_REMOVE**
+
+ : Remove or update an existing poll request. If found, the *res*
+ field of the *struct io_uring_cqe* will contain 0. If not found,
+ *res* will contain **-ENOENT,** or **-EALREADY** if the poll
+ request was in the process of completing already.
+
+ If **IORING_POLL_UPDATE_EVENTS** is set in the SQE *len* field,
+ then the request will update an existing poll request with the
+ mask of events passed in with this request. The lookup is based on
+ the *user_data* field of the original SQE submitted, and this
+ values is passed in the *addr* field of the SQE. If
+ **IORING_POLL_UPDATE_USER_DATA** is set in the SQE *len* field,
+ then the request will update the *user_data* of an existing poll
+ request based on the value passed in the *off* field. Updating an
+ existing poll is available since 5.13.
+
+ **IORING_OP_EPOLL_CTL**
+
+ : Add, remove or modify entries in the interest list of
+ **epoll**(7). See **epoll_ctl**(2) for details of the system call.
+ *fd* holds the file descriptor that represents the epoll instance,
+ *off* holds the file descriptor to add, remove or modify, *len*
+ holds the operation ( **EPOLL_CTL_ADD**, **EPOLL_CTL_DEL**,
+ **EPOLL_CTL_MOD**) to perform and, *addr* holds a pointer to the
+ *epoll_event* structure. Available since 5.6.
+
+ **IORING_OP_SYNC_FILE_RANGE**
+
+ : Issue the equivalent of a **sync_file_range** (2) on the file
+ descriptor. The *fd* field is the file descriptor to sync, the
+ *off* field holds the offset in bytes, the *len* field holds the
+ length in bytes, and the *sync_range_flags* field holds the flags
+ for the command. See also **sync_file_range**(2) for the general
+ description of the related system call. Available since 5.2.
+
+ **IORING_OP_SENDMSG**
+
+ : Issue the equivalent of a **sendmsg(2)** system call. *fd* must be
+ set to the socket file descriptor, *addr* must contain a pointer
+ to the msghdr structure, and *msg_flags* holds the flags
+ associated with the system call. See also **sendmsg**(2) for the
+ general description of the related system call. Available since
+ 5.3.
+
+ This command also supports the following modifiers in *ioprio:*
+
+**IORING_RECVSEND_POLL_FIRST** If set, io_uring will assume the socket
+is currently full and attempting to send data will be unsuccessful. For
+this case, io_uring will arm internal poll and trigger a send of the
+data when there is enough space available. This initial send attempt can
+be wasteful for the case where the socket is expected to be full,
+setting this flag will bypass the initial send attempt and go straight
+to arming poll. If poll does indicate that data can be sent, the
+operation will proceed.
+
+**IORING_OP_RECVMSG**
+
+: Works just like IORING_OP_SENDMSG, except for **recvmsg(2)** instead.
+ See the description of IORING_OP_SENDMSG. Available since 5.3.
+
+ This command also supports the following modifiers in *ioprio:*
+
+**IORING_RECVSEND_POLL_FIRST** If set, io_uring will assume the socket
+is currently empty and attempting to receive data will be unsuccessful.
+For this case, io_uring will arm internal poll and trigger a receive of
+the data when the socket has data to be read. This initial receive
+attempt can be wasteful for the case where the socket is expected to be
+empty, setting this flag will bypass the initial receive attempt and go
+straight to arming poll. If poll does indicate that data is ready to be
+received, the operation will proceed.
+
+**IORING_OP_SEND**
+
+: Issue the equivalent of a **send(2)** system call. *fd* must be set to
+ the socket file descriptor, *addr* must contain a pointer to the
+ buffer, *len* denotes the length of the buffer to send, and
+ *msg_flags* holds the flags associated with the system call. See also
+ **send(2)** for the general description of the related system call.
+ Available since 5.6.
+
+ This command also supports the following modifiers in *ioprio:*
+
+**IORING_RECVSEND_POLL_FIRST** If set, io_uring will assume the socket
+is currently full and attempting to send data will be unsuccessful. For
+this case, io_uring will arm internal poll and trigger a send of the
+data when there is enough space available. This initial send attempt can
+be wasteful for the case where the socket is expected to be full,
+setting this flag will bypass the initial send attempt and go straight
+to arming poll. If poll does indicate that data can be sent, the
+operation will proceed.
+
+**IORING_OP_RECV**
+
+: Works just like IORING_OP_SEND, except for **recv(2)** instead. See
+ the description of IORING_OP_SEND. Available since 5.6.
+
+ This command also supports the following modifiers in *ioprio:*
+
+**IORING_RECVSEND_POLL_FIRST** If set, io_uring will assume the socket
+is currently empty and attempting to receive data will be unsuccessful.
+For this case, io_uring will arm internal poll and trigger a receive of
+the data when the socket has data to be read. This initial receive
+attempt can be wasteful for the case where the socket is expected to be
+empty, setting this flag will bypass the initial receive attempt and go
+straight to arming poll. If poll does indicate that data is ready to be
+received, the operation will proceed.
+
+**IORING_OP_TIMEOUT**
+
+: This command will register a timeout operation. The *addr* field must
+ contain a pointer to a struct \_\_kernel_timespec structure, *len*
+ must contain 1 to signify one \_\_kernel_timespec structure,
+ *timeout_flags* may contain **IORING_TIMEOUT_ABS** for an absolute
+ timeout value, or 0 for a relative timeout. *off* may contain a
+ completion event count. A timeout will trigger a wakeup event on the
+ completion ring for anyone waiting for events. A timeout condition is
+ met when either the specified timeout expires, or the specified number
+ of events have completed. Either condition will trigger the event. If
+ set to 0, completed events are not counted, which effectively acts
+ like a timer. io_uring timeouts use the **CLOCK_MONOTONIC** as the
+ default clock source. The request will complete with **-ETIME** if the
+ timeout got completed through expiration of the timer, or *0* if the
+ timeout got completed through requests completing on their own. If the
+ timeout was canceled before it expired, the request will complete with
+ **-ECANCELED.** Available since 5.4.
+
+ Since 5.15, this command also supports the following modifiers in
+ *timeout_flags:*
+
+**IORING_TIMEOUT_BOOTTIME** If set, then the clocksource used is
+**CLOCK_BOOTTIME** instead of **CLOCK_MONOTONIC**. This clocksource
+differs in that it includes time elapsed if the system was suspend while
+having a timeout request in-flight.
+
+**IORING_TIMEOUT_REALTIME** If set, then the clocksource used is
+**CLOCK_REALTIME** instead of **CLOCK_MONOTONIC**.
+
+Since 5.16, **IORING_TIMEOUT_ETIME_SUCCESS** can be set in
+*timeout_flags*, which will result in the expiration of the timer and
+subsequent completion with **-ETIME** not being interpreted as an error.
+This is mostly relevant for linked SQEs, as subsequent requests in the
+chain would not get canceled by the timeout, if this flag is set. See
+**IOSQE_IO_LINK** for more details on linked SQEs.
+
+Since 6.4, **IORING_TIMEOUT_MULTISHOT** can be set in *timeout_flags*,
+which will result in the timer producing multiple consecutive
+completions like other multi shot operations e.g.
+**IORING_OP_READ_MULTISHOT** or **IORING_POLL_ADD_MULTI**. *off* must be
+set to the amount of desired completions. **IORING_TIMEOUT_MULTISHOT**
+must not be used with **IORING_TIMEOUT_ABS**.
+
+Since kernel 7.1, **IORING_TIMEOUT_IMMEDIATE_ARG** can be set in
+*timeout_flags*, which causes the *addr* field to be interpreted as a
+timeout value in nanoseconds rather than a pointer to a **struct
+\_\_kernel_timespec.** This avoids the need to keep a timespec structure
+valid in user memory until the request is submitted.
+
+**IORING_OP_TIMEOUT_REMOVE**
+
+: If *timeout_flags* are zero, then it attempts to remove an existing
+ timeout operation. *addr* must contain the *user_data* field of the
+ previously issued timeout operation. If the specified timeout request
+ is found and canceled successfully, this request will terminate with a
+ result value of *0* If the timeout request was found but expiration
+ was already in progress, this request will terminate with a result
+ value of **-EBUSY** If the timeout request wasn\'t found, the request
+ will terminate with a result value of **-ENOENT** Available since 5.5.
+
+ If *timeout_flags* contain **IORING_TIMEOUT_UPDATE**, instead of
+ removing an existing operation, it updates it. *addr* and return
+ values are same as before. *addr2* field must contain a pointer to a
+ struct \_\_kernel_timespec structure. *timeout_flags* may also contain
+ IORING_TIMEOUT_ABS, in which case the value given is an absolute one,
+ not a relative one. Available since 5.11.
+
+**IORING_OP_ACCEPT**
+
+: Issue the equivalent of an **accept4**(2) system call. *fd* must be
+ set to the socket file descriptor, *addr* must contain the pointer to
+ the sockaddr structure, and *addr2* must contain a pointer to the
+ socklen_t addrlen field. Flags can be passed using the *accept_flags*
+ field. See also **accept4**(2) for the general description of the
+ related system call. Available since 5.5.
+
+ If the *file_index* field is set to a positive number, the file won\'t
+ be installed into the normal file table as usual but will be placed
+ into the fixed file table at index *file_index* - 1. In this case,
+ instead of returning a file descriptor, the result will contain either
+ 0 on success or an error. If the index points to a valid empty slot,
+ the installation is guaranteed to not fail. If there is already a file
+ in the slot, it will be replaced, similar to
+ **IORING_OP_FILES_UPDATE.** Please note that only io_uring has access
+ to such files and no other syscall can use them. See
+ **IOSQE_FIXED_FILE** and **IORING_REGISTER_FILES**.
+
+ Available since 5.5.
+
+**IORING_OP_ASYNC_CANCEL**
+
+: Attempt to cancel an already issued request. *addr* must contain the
+ *user_data* field of the request that should be canceled. The
+ cancelation request will complete with one of the following results
+ codes. If found, the *res* field of the cqe will contain 0. If not
+ found, *res* will contain **-ENOENT**. If found and attempted
+ canceled, the *res* field will contain **-EALREADY**. In this case,
+ the request may or may not terminate. In general, requests that are
+ interruptible (like socket IO) will get canceled, while disk IO
+ requests cannot be canceled if already started. Available since 5.5.
+
+**IORING_OP_LINK_TIMEOUT**
+
+: This request must be linked with another request through
+ **IOSQE_IO_LINK** which is described below. Unlike
+ **IORING_OP_TIMEOUT**, **IORING_OP_LINK_TIMEOUT** acts on the linked
+ request, not the completion queue. The format of the command is
+ otherwise like **IORING_OP_TIMEOUT**, except there\'s no completion
+ event count as it\'s tied to a specific request. If used, the timeout
+ specified in the command will cancel the linked command, unless the
+ linked command completes before the timeout. The timeout will complete
+ with **-ETIME** if the timer expired and the linked request was
+ attempted canceled, or **-ECANCELED** if the timer got canceled
+ because of completion of the linked request. Like
+ **IORING_OP_TIMEOUT** the clock source used is **CLOCK_MONOTONIC**
+ Available since 5.5.
+
+**IORING_OP_CONNECT**
+
+: Issue the equivalent of a **connect**(2) system call. *fd* must be set
+ to the socket file descriptor, *addr* must contain the const pointer
+ to the sockaddr structure, and *off* must contain the socklen_t
+ addrlen field. See also **connect**(2) for the general description of
+ the related system call. Available since 5.5.
+
+**IORING_OP_FALLOCATE**
+
+: Issue the equivalent of a **fallocate**(2) system call. *fd* must be
+ set to the file descriptor, *len* must contain the mode associated
+ with the operation, *off* must contain the offset on which to operate,
+ and *addr* must contain the length. See also **fallocate**(2) for the
+ general description of the related system call. Available since 5.6.
+
+**IORING_OP_FADVISE**
+
+: Issue the equivalent of a **posix_fadvise**(2) system call. *fd* must
+ be set to the file descriptor, *off* must contain the offset on which
+ to operate, *len* must contain the length, and *fadvise_advice* must
+ contain the advice associated with the operation. See also
+ **posix_fadvise**(2) for the general description of the related system
+ call. Available since 5.6.
+
+**IORING_OP_MADVISE**
+
+: Issue the equivalent of a **madvise**(2) system call. *addr* must
+ contain the address to operate on, *len* must contain the length on
+ which to operate, and *fadvise_advice* must contain the advice
+ associated with the operation. See also **madvise**(2) for the general
+ description of the related system call. Available since 5.6.
+
+**IORING_OP_OPENAT**
+
+: Issue the equivalent of a **openat**(2) system call. *fd* is the
+ *dirfd* argument, *addr* must contain a pointer to the *\*pathname*
+ argument, *open_flags* should contain any flags passed in, and *len*
+ is access mode of the file. See also **openat**(2) for the general
+ description of the related system call. Available since 5.6.
+
+ If the *file_index* field is set to a positive number, the file won\'t
+ be installed into the normal file table as usual but will be placed
+ into the fixed file table at index *file_index - 1.* In this case,
+ instead of returning a file descriptor, the result will contain either
+ 0 on success or an error. If the index points to a valid empty slot,
+ the installation is guaranteed to not fail. If there is already a file
+ in the slot, it will be replaced, similar to
+ **IORING_OP_FILES_UPDATE.** Please note that only io_uring has access
+ to such files and no other syscall can use them. See
+ **IOSQE_FIXED_FILE** and **IORING_REGISTER_FILES**.
+
+ Available since 5.15.
+
+**IORING_OP_OPENAT2**
+
+: Issue the equivalent of a **openat2**(2) system call. *fd* is the
+ *dirfd* argument, *addr* must contain a pointer to the *\*pathname*
+ argument, *len* should contain the size of the open_how structure, and
+ *off* should be set to the address of the open_how structure. See also
+ **openat2**(2) for the general description of the related system call.
+ Available since 5.6.
+
+ If the *file_index* field is set to a positive number, the file won\'t
+ be installed into the normal file table as usual but will be placed
+ into the fixed file table at index *file_index - 1.* In this case,
+ instead of returning a file descriptor, the result will contain either
+ 0 on success or an error. If the index points to a valid empty slot,
+ the installation is guaranteed to not fail. If there is already a file
+ in the slot, it will be replaced, similar to
+ **IORING_OP_FILES_UPDATE**. Please note that only io_uring has access
+ to such files and no other syscall can use them. See
+ **IOSQE_FIXED_FILE** and **IORING_REGISTER_FILES**.
+
+ Available since 5.15.
+
+**IORING_OP_CLOSE**
+
+: Issue the equivalent of a **close**(2) system call. *fd* is the file
+ descriptor to be closed. See also **close**(2) for the general
+ description of the related system call. Available since 5.6. If the
+ *file_index* field is set to a positive number, this command can be
+ used to close files that were direct opened through
+ **IORING_OP_OPENAT**, **IORING_OP_OPENAT2**, or **IORING_OP_ACCEPT**
+ using the io_uring specific direct descriptors. Note that only one of
+ the descriptor fields may be set. The direct close feature is
+ available since the 5.15 kernel, where direct descriptors were
+ introduced.
+
+**IORING_OP_STATX**
+
+: Issue the equivalent of a **statx**(2) system call. *fd* is the
+ *dirfd* argument, *addr* must contain a pointer to the *\*pathname*
+ string, *statx_flags* is the *flags* argument, *len* should be the
+ *mask* argument, and *off* must contain a pointer to the *statxbuf* to
+ be filled in. See also **statx**(2) for the general description of the
+ related system call. Available since 5.6.
+
+**IORING_OP_READ**
+
+:
+
+ **IORING_OP_WRITE**
+
+ : Issue the equivalent of a **pread**(2) or **pwrite**(2) system call.
+ *fd* is the file descriptor to be operated on, *addr* contains the
+ buffer in question, *len* contains the length of the IO operation,
+ and *offs* contains the read or write offset. If *fd* does not refer
+ to a seekable file, *off* must be set to zero or -1. If *offs* is
+ set to **-1** , the offset will use (and advance) the file position,
+ like the **read**(2) and **write**(2) system calls. These are
+ non-vectored versions of the **IORING_OP_READV** and
+ **IORING_OP_WRITEV** opcodes. See also **read**(2) and **write**(2)
+ for the general description of the related system call. Available
+ since 5.6.
+
+ **IORING_OP_SPLICE**
+
+ : Issue the equivalent of a **splice**(2) system call. *splice_fd_in*
+ is the file descriptor to read from, *splice_off_in* is an offset to
+ read from, *fd* is the file descriptor to write to, *off* is an
+ offset from which to start writing to. A sentinel value of **-1** is
+ used to pass the equivalent of a NULL for the offsets to
+ **splice**(2). *len* contains the number of bytes to copy.
+ *splice_flags* contains a bit mask for the flag field associated
+ with the system call. Please note that one of the file descriptors
+ must refer to a pipe. See also **splice**(2) for the general
+ description of the related system call. Available since 5.7.
+
+ **IORING_OP_TEE**
+
+ : Issue the equivalent of a **tee**(2) system call. *splice_fd_in* is
+ the file descriptor to read from, *fd* is the file descriptor to
+ write to, *len* contains the number of bytes to copy, and
+ *splice_flags* contains a bit mask for the flag field associated
+ with the system call. Please note that both of the file descriptors
+ must refer to a pipe. See also **tee**(2) for the general
+ description of the related system call. Available since 5.8.
+
+ **IORING_OP_FILES_UPDATE**
+
+ : This command is an alternative to using
+ **IORING_REGISTER_FILES_UPDATE** which then works in an async
+ fashion, like the rest of the io_uring commands. The arguments
+ passed in are the same. *addr* must contain a pointer to the array
+ of file descriptors, *len* must contain the length of the array, and
+ *off* must contain the offset at which to operate. Note that the
+ array of file descriptors pointed to in *addr* must remain valid
+ until this operation has completed. Available since 5.6.
+
+ **IORING_OP_PROVIDE_BUFFERS**
+
+ : This command allows an application to register a group of buffers to
+ be used by commands that read/receive data. Using buffers in this
+ manner can eliminate the need to separate the poll + read, which
+ provides a convenient point in time to allocate a buffer for a given
+ request. It\'s often infeasible to have as many buffers available as
+ pending reads or receive. With this feature, the application can
+ have its pool of buffers ready in the kernel, and when the file or
+ socket is ready to read/receive data, a buffer can be selected for
+ the operation. *fd* must contain the number of buffers to provide,
+ *addr* must contain the starting address to add buffers from, *len*
+ must contain the length of each buffer to add from the range,
+ *buf_group* must contain the group ID of this range of buffers, and
+ *off* must contain the starting buffer ID of this range of buffers.
+ With that set, the kernel adds buffers starting with the memory
+ address in *addr,* each with a length of *len.* Hence the
+ application should provide *len \* fd* worth of memory in *addr.*
+ Buffers are grouped by the group ID, and each buffer within this
+ group will be identical in size according to the above arguments.
+ This allows the application to provide different groups of buffers,
+ and this is often used to have differently sized buffers available
+ depending on what the expectations are of the individual request.
+ When submitting a request that should use a provided buffer, the
+ **IOSQE_BUFFER_SELECT** flag must be set, and *buf_group* must be
+ set to the desired buffer group ID where the buffer should be
+ selected from. Available since 5.7.
+
+ **IORING_OP_REMOVE_BUFFERS**
+
+ : Remove buffers previously registered with
+ **IORING_OP_PROVIDE_BUFFERS**. *fd* must contain the number of
+ buffers to remove, and *buf_group* must contain the buffer group ID
+ from which to remove the buffers. Available since 5.7.
+
+ **IORING_OP_SHUTDOWN**
+
+ : Issue the equivalent of a **shutdown**(2) system call. *fd* is the
+ file descriptor to the socket being shutdown, and *len* must be set
+ to the *how* argument. No no other fields should be set. Available
+ since 5.11.
+
+ **IORING_OP_RENAMEAT**
+
+ : Issue the equivalent of a **renameat2**(2) system call. *fd* should
+ be set to the *olddirfd*, *addr* should be set to the *oldpath*,
+ *len* should be set to the *newdirfd*, *addr* should be set to the
+ *oldpath*, *addr2* should be set to the *newpath*, and finally
+ *rename_flags* should be set to the *flags* passed in to
+ **renameat2**(2). Available since 5.11.
+
+ **IORING_OP_UNLINKAT**
+
+ : Issue the equivalent of a **unlinkat**(2) system call. *fd* should
+ be set to the *dirfd*, *addr* should be set to the *pathname*, and
+ *unlink_flags* should be set to the *flags* being passed in to
+ **unlinkat**(2). Available since 5.11.
+
+ **IORING_OP_MKDIRAT**
+
+ : Issue the equivalent of a **mkdirat**(2) system call. *fd* should be
+ set to the *dirfd*, *addr* should be set to the *pathname*, and
+ *len* should be set to the *mode* being passed in to **mkdirat**(2).
+ Available since 5.15.
+
+ **IORING_OP_SYMLINKAT**
+
+ : Issue the equivalent of a **symlinkat**(2) system call. *fd* should
+ be set to the *newdirfd*, *addr* should be set to the *target* and
+ *addr2* should be set to the *linkpath* being passed in to
+ **symlinkat**(2). Available since 5.15.
+
+ **IORING_OP_LINKAT**
+
+ : Issue the equivalent of a **linkat**(2) system call. *fd* should be
+ set to the *olddirfd*, *addr* should be set to the *oldpath*, *len*
+ should be set to the *newdirfd*, *addr2* should be set to the
+ *newpath*, and *hardlink_flags* should be set to the *flags* being
+ passed in to **linkat**(2). Available since 5.15.
+
+ **IORING_OP_MSG_RING**
+
+ : Send a message to an io_uring. *fd* must be set to a file descriptor
+ of a ring that the application has access to, *len* can be set to
+ any 32-bit value that the application wishes to pass on, and *off*
+ should be set any 64-bit value that the application wishes to send.
+ On the target ring, a CQE will be posted with the *res* field
+ matching the *len* set, and a *user_data* field matching the *off*
+ value being passed in. This request type can be used to either just
+ wake or interrupt anyone waiting for completions on the target ring,
+ or it can be used to pass messages via the two fields. Available
+ since 5.18.
+
+ **IORING_OP_SOCKET**
+
+ : Issue the equivalent of a **socket**(2) system call. *fd* must
+ contain the communication domain, *off* must contain the
+ communication type, *len* must contain the protocol, and *rw_flags*
+ is currently unused and must be set to zero. See also **socket**(2)
+ for the general description of the related system call. Available
+ since 5.19.
+
+ If the *file_index* field is set to a positive number, the file
+ won\'t be installed into the normal file table as usual but will be
+ placed into the fixed file table at index *file_index* - 1. In this
+ case, instead of returning a file descriptor, the result will
+ contain either 0 on success or an error. If the index points to a
+ valid empty slot, the installation is guaranteed to not fail. If
+ there is already a file in the slot, it will be replaced, similar to
+ **IORING_OP_FILES_UPDATE**. Please note that only io_uring has
+ access to such files and no other syscall can use them. See
+ **IOSQE_FIXED_FILE** and **IORING_REGISTER_FILES**.
+
+ Available since 5.19.
+
+ **IORING_OP_URING_CMD**
+
+ : Issues an asynchronous, per-file private operation, similar to
+ **ioctl**(2). Further information may be found in the dedicated man
+ page of **IORING_OP_URING_CMD**.
+
+ Available since 5.19.
+
+ **IORING_OP_SEND_ZC**
+
+ : Issue the zerocopy equivalent of a **send(2)** system call. Similar
+ to **IORING_OP_SEND**, but tries to avoid making intermediate copies
+ of data. Zerocopy execution is not guaranteed and may fall back to
+ copying. The request may also fail with **-EOPNOTSUPP**, when a
+ protocol doesn\'t support zerocopy, in which case users are
+ recommended to use copying sends instead.
+
+ The *flags* field of the first *struct io_uring_cqe* may likely
+ contain **IORING_CQE_F_MORE**, which means that there will be a
+ second completion event / notification for the request, with the
+ *user_data* field set to the same value. The user must not modify
+ the data buffer until the notification is posted. The first cqe
+ follows the usual rules and so its *res* field will contain the
+ number of bytes sent or a negative error code. The notification\'s
+ *res* field will be set to zero and the *flags* field will contain
+ **IORING_CQE_F_NOTIF**. The two step model is needed because the
+ kernel may hold on to buffers for a long time, e.g. waiting for a
+ TCP ACK, and having a separate cqe for request completions allows
+ userspace to push more data without extra delays. Note,
+ notifications are only responsible for controlling the lifetime of
+ the buffers, and as such don\'t mean anything about whether the data
+ has atually been sent out or received by the other end. Even errored
+ requests may generate a notification, and the user must check for
+ **IORING_CQE_F_MORE** rather than relying on the result.
+
+ *fd* must be set to the socket file descriptor, *addr* must contain
+ a pointer to the buffer, *len* denotes the length of the buffer to
+ send, and *msg_flags* holds the flags associated with the system
+ call. When *addr2* is non-zero it points to the address of the
+ target with *addr_len* specifying its size, turning the request into
+ a **sendto**(2) system call equivalent.
+
+ Available since 6.0.
+
+ This command also supports the following modifiers in *ioprio:*
+
+**IORING_RECVSEND_POLL_FIRST** If set, io_uring will assume the socket
+is currently full and attempting to send data will be unsuccessful. For
+this case, io_uring will arm internal poll and trigger a send of the
+data when there is enough space available. This initial send attempt can
+be wasteful for the case where the socket is expected to be full,
+setting this flag will bypass the initial send attempt and go straight
+to arming poll. If poll does indicate that data can be sent, the
+operation will proceed.
+
+**IORING_RECVSEND_FIXED_BUF** If set, instructs io_uring to use a
+pre-mapped buffer. The *buf_index* field should contain an index into an
+array of fixed buffers. See **io_uring_register**(2) for details on how
+to setup a context for fixed buffer I/O.
+
+**IORING_OP_SENDMSG_ZC**
+
+: Issue the zerocopy equivalent of a **sendmsg**(2) system call. Works
+ just like **IORING_OP_SENDMSG**, but like **IORING_OP_SEND_ZC**
+ supports **IORING_RECVSEND_FIXED_BUF**. For additional notes regarding
+ zero copy see **IORING_OP_SEND_ZC**.
+
+ Available since 6.1
+
+**IORING_OP_WAITID**
+
+: Issue the equivalent of a **waitid**(2) system call. *len* must
+ contain the idtype being queried/waited for and *fd* must contain the
+ \'pid\' (or id) being waited for. *file_index* is the \'options\'
+ being set (the child state changes to wait for). *addr2* is a pointer
+ to siginfo_t, if any, being filled in. See also **waitid**(2) for the
+ general description of the related system call. Available since 6.5.
+
+**IORING_OP_SETXATTR**
+
+:
+
+ **IORING_OP_GETXATTR**
+
+ :
+
+ **IORING_OP_FSETXATTR**
+
+ :
+
+ **IORING_OP_FGETXATTR**
+
+ : Issue the equivalent of a **setxattr**(2) or **getxattr**(2) or
+ **fsetxattr**(2) or **fgetxattr**(2) system call. *addr* must
+ contain a pointer to a buffer containing the name of the
+ extended attribute. *addr2* must contain a pointer to a buffer
+ of maximum length *len*, in which the value of the extended
+ attribute is to be placed or is read from. Additional flags
+ maybe provided in *xattr_flags*. For **setxattr**(2) or
+ **getxattr**(2) *addr3* must contain a pointer to the path of
+ the file. For **fsetxattr**(2) or **fgetxattr**(2) *fd* must
+ contain the file descriptor of the file.
+
+ Available since 5.19.
+
+ **IORING_OP_BIND**
+
+ : Issues the equivalent of the **bind**(2) system call. *fd* must
+ contain the file descriptor of the socket, *addr* must contain a
+ pointer to the sockaddr struct containing the address to assign
+ and *addr2* must contain the length of the address.
+
+ Available since 6.11.
+
+ **IORING_OP_LISTEN**
+
+ : Issues the equivalent of the **listen**(2) system call. *fd*
+ must contain the file descriptor of the socket and *len* must
+ contain the backlog parameter, i.e. the maximum amount of
+ pending queued connections.
+
+ Available since 6.11.
+
+ **IORING_OP_FTRUNCATE**
+
+ : Issues the equivalent of the **ftruncate**(2) system call. *fd*
+ must contain the file descriptor of the file to truncate and
+ *off* must contain the length to which the file will be
+ truncated.
+
+ Available since 6.9.
+
+ **IORING_OP_READ_MULTISHOT**
+
+ : Like **IORING_OP_READ**, but similar to requests prepared with
+ *io_uring_prep_multishot_accept*(3) additional reads and thus
+ CQEs will be performed based on this single SQE once there is
+ more data available. Is restricted to pollable files and will
+ fall back to single shot if the file does not support
+ **NOWAIT**. Like other multishot type requests, the application
+ should look at the CQE flags and see if **IORING_CQE_F_MORE** is
+ set on completion as an indication of whether or not the read
+ request will generate further CQEs. Available since 6.7.
+
+ **IORING_OP_FUTEX_WAIT**
+
+ : Issues the equivalent of the **futex_wait**(2) system call.
+ *addr* must hold a pointer to the futex, *addr2* must hold the
+ value to which the futex has to be changed so this caller to
+ **futex_wait**(2) can be woken by a call to **futex_wake**(2),
+ *addr3* must hold the bitmask of this **futex_wait**(2) caller.
+ For a caller of **futex_wake**(2) to wake a waiter additionally
+ the bitmask of the waiter and waker must have at least one set
+ bit in common. *fd* must contain additional flags passed in.
+
+ Available since 6.7.
+
+ **IORING_OP_FUTEX_WAKE**
+
+ : Issues the equivalent of the **futex_wake**(2) system call.
+ *addr* must hold a pointer to the futex, *addr2* must hold the
+ maximum number of waiters waiting on this futex to wake, *addr3*
+ must hold the bitmask of this **futex_wake**(2) call. To wake a
+ waiter additionally the bitmask of the waiter and waker must
+ have at least one set bit in common. *fd* must contain
+ additional flags passed in.
+
+ Available since 6.7.
+
+ **IORING_OP_FUTEX_WAITV**
+
+ : Issues the equivalent of the **futex_waitv**(2) system call.
+ *addr* must hold a pointer to the futexv struct, *len* must hold
+ the length of the futexv struct, which may not be 0 and must be
+ smaller than **FUTEX_WAITV_MAX** (as of 6.11 == 128).
+
+ Available since 6.7.
+
+ **IORING_OP_FIXED_FD_INSTALL**
+
+ : This operation is used to insert a registered file into the
+ regular process file table. Consequently *fd* must contain the
+ file index and **IOSQE_FIXED_FILE** must be set. The resulting
+ regular fd is returned via cqe-\>res. Additional flags may be
+ passed in via *install_fd_flags*. Currently supported flags are:
+ **IORING_FIXED_FD_NO_CLOEXEC**, which overrides a potentially
+ set **O_CLOEXEC** flag set on the initial file.
+
+ Available since 6.8.
+
+ **IORING_OP_PIPE**
+
+ : This operation is used to create a pipe, a set of file
+ descriptors that can be used for communication. The pipe may
+ either be created as a set of normal file descriptors, or it can
+ be created as fixed/direct descriptors. *addr* must contain a
+ pointer to an array of two integers, where upon successful
+ completion of the request, index 0 will contain the read side
+ and index 1 the write side of the pipe. *pipe_flags* may contain
+ flags associated with pipe creation. Currently **O_CLOEXEC \|
+ O_NONBLOCK \| O_DIRECT \| O_NOTIFICATION_PIPE** are supported.
+ *file_index* may contain the the desired starting point for a
+ fixed descriptor pipe creation. If this is set to **0,** then
+ regular file descriptors are used. If set to
+ **IORING_FILE_INDEX_ALLOC,** then the kernel will allocate
+ descriptors from the previously registered direct descriptor
+ table. If set to any non-zero value, then it sets the exact
+ direct descriptor value for index 0 of the pipe, and index 1
+ will be the following integer value.
+
+ If used with direct descriptors rather than normal file
+ descriptors, a direct descriptor table must have been previously
+ registered with the kernel.
+
+ Available since 6.16.
+
+ **IORING_OP_RECV_ZC**
+
+ : Receive data from a socket using zero-copy techniques. Unlike
+ **IORING_OP_RECV**, this operation does not use a user-provided
+ buffer. Instead, data is delivered through a pre-registered
+ zero-copy RX interface queue. *fd* must be set to the socket
+ file descriptor. *zcrx_ifq_idx* specifies the index of the
+ registered zero-copy RX interface queue. *len* specifies the
+ maximum amount of data to receive. *ioprio* can contain flags
+ such as **IORING_RECVSEND_POLL_FIRST** and
+ **IORING_RECV_MULTISHOT**. This operation requires multishot
+ mode.
+
+ Before using this command, a zero-copy RX interface queue must
+ be registered via **io_uring_register**(2) using
+ **IORING_REGISTER_ZCRX_IFQ**. Data completions are posted as
+ auxiliary CQEs.
+
+ Available since 6.15.
+
+ **IORING_OP_EPOLL_WAIT**
+
+ : Wait for events on an epoll instance. This is an async version
+ of **epoll_wait**(2). *fd* must be set to the epoll file
+ descriptor, *addr* must point to an array of *struct
+ epoll_event* to receive the events, and *len* must contain the
+ maximum number of events to return.
+
+ The primary use case is for legacy event loops that still use
+ epoll for some file descriptors. By using io_uring to wait on
+ epoll events, the application can unify its event handling
+ through io_uring while maintaining backwards compatibility with
+ epoll-based components.
+
+ Available since 6.15.
+
+ **IORING_OP_READV_FIXED**
+
+ :
+
+ **IORING_OP_WRITEV_FIXED**
+
+ : Vectored read and write operations using pre-registered
+ buffers, combining the functionality of
+ **IORING_OP_READV**/**IORING_OP_WRITEV** with
+ **IORING_OP_READ_FIXED**/**IORING_OP_WRITE_FIXED**. The
+ *buf_index* field specifies the index into the registered
+ buffer table. Unlike the non-fixed vectored operations, the
+ iovec entries point into the registered buffer region. This
+ allows vectored I/O while still benefiting from the reduced
+ overhead of pre-registered buffers.
+
+ Available since 6.15.
+
+ **IORING_OP_NOP128**
+
+ : No operation, similar to **IORING_OP_NOP**, but explicitly
+ uses a 128-byte SQE. This can be useful for testing or
+ alignment purposes when using mixed 64/128-byte SQE rings
+ (**IORING_SETUP_SQE_MIXED**).
+
+ Available since 6.19.
+
+ **IORING_OP_URING_CMD128**
+
+ : Passthrough command to the underlying file, identical to
+ **IORING_OP_URING_CMD**, but explicitly uses a 128-byte SQE.
+ The extra 64 bytes provide additional space for
+ command-specific data. This is useful with
+ **IORING_SETUP_SQE_MIXED** rings where some commands need the
+ larger SQE size while others do not.
+
+ See **IORING_OP_URING_CMD** for general usage details.
+
+ Available since 6.19.
+
+The *flags* field is a bit mask. The supported flags are:
+
+**IOSQE_FIXED_FILE**
+
+: When this flag is specified, *fd* is an index into the files array
+ registered with the io_uring instance (see the
+ **IORING_REGISTER_FILES** section of the **io_uring_register**(2) man
+ page). Note that this isn\'t always available for all commands. If
+ used on a command that doesn\'t support fixed files, the SQE will
+ error with **-EBADF**. Available since 5.1.
+
+**IOSQE_IO_DRAIN**
+
+: When this flag is specified, the SQE will not be started before
+ previously submitted SQEs have completed, and new SQEs will not be
+ started before this one completes. Available since 5.2.
+
+**IOSQE_IO_LINK**
+
+: When this flag is specified, the SQE forms a link with the next SQE in
+ the submission ring. That next SQE will not be started before the
+ previous request completes. This, in effect, forms a chain of SQEs,
+ which can be arbitrarily long. The tail of the chain is denoted by the
+ first SQE that does not have this flag set. Chains are not supported
+ across submission boundaries. Even if the last SQE in a submission has
+ this flag set, it will still terminate the current chain. This flag
+ has no effect on previous SQE submissions, nor does it impact SQEs
+ that are outside of the chain tail. This means that multiple chains
+ can be executing in parallel, or chains and individual SQEs. Only
+ members inside the chain are serialized. A chain of SQEs will be
+ broken if any request in that chain ends in error. io_uring considers
+ any unexpected result an error. This means that, eg, a short read will
+ also terminate the remainder of the chain. If a chain of SQE links is
+ broken, the remaining unstarted part of the chain will be terminated
+ and completed with **-ECANCELED** as the error code. Available since
+ 5.3.
+
+**IOSQE_IO_HARDLINK**
+
+: Like IOSQE_IO_LINK, but it doesn\'t sever regardless of the completion
+ result. Note that the link will still sever if we fail submitting the
+ parent request, hard links are only resilient in the presence of
+ completion results for requests that did submit correctly.
+ **IOSQE_IO_HARDLINK** implies **IOSQE_IO_LINK**. Available since 5.5.
+
+**IOSQE_ASYNC**
+
+: Normal operation for io_uring is to try and issue an sqe as
+ non-blocking first, and if that fails, execute it in an async manner.
+ To support more efficient overlapped operation of requests that the
+ application knows/assumes will always (or most of the time) block, the
+ application can ask for an sqe to be issued async from the start.
+ Available since 5.6.
+
+**IOSQE_BUFFER_SELECT**
+
+: Used in conjunction with the **IORING_OP_PROVIDE_BUFFERS** command,
+ which registers a pool of buffers to be used by commands that read or
+ receive data. When buffers are registered for this use case, and this
+ flag is set in the command, io_uring will grab a buffer from this pool
+ when the request is ready to receive or read data. If successful, the
+ resulting CQE will have **IORING_CQE_F_BUFFER** set in the flags part
+ of the struct, and the upper **IORING_CQE_BUFFER_SHIFT** bits will
+ contain the ID of the selected buffers. This allows the application to
+ know exactly which buffer was selected for the operation. If no
+ buffers are available and this flag is set, then the request will fail
+ with **-ENOBUFS** as the error code. Once a buffer has been used, it
+ is no longer available in the kernel pool. The application must
+ re-register the given buffer again when it is ready to recycle it (eg
+ has completed using it). Available since 5.7.
+
+**IOSQE_CQE_SKIP_SUCCESS**
+
+: Don\'t generate a CQE if the request completes successfully. If the
+ request fails, an appropriate CQE will be posted as usual and if there
+ is no **IOSQE_IO_HARDLINK,** CQEs for all linked requests will be
+ omitted. The notion of failure/success is opcode specific and is the
+ same as with breaking chains of **IOSQE_IO_LINK**. One special case is
+ when the request has a linked timeout, then the CQE generation for the
+ linked timeout is decided solely by whether it has
+ **IOSQE_CQE_SKIP_SUCCESS** set, regardless whether it timed out or was
+ canceled. In other words, if a linked timeout has the flag set, it\'s
+ guaranteed to not post a CQE.
+
+ The semantics are chosen to accommodate several use cases. First, when
+ all but the last request of a normal link without linked timeouts are
+ marked with the flag, only one CQE per link is posted. Additionally,
+ it enables suppression of CQEs in cases where the side effects of a
+ successfully executed operation is enough for userspace to know the
+ state of the system. One such example would be writing to a
+ synchronisation file.
+
+ This flag is incompatible with **IOSQE_IO_DRAIN**. Using both of them
+ in a single ring is undefined behavior, even when they are not used
+ together in a single request. Currently, after the first request with
+ **IOSQE_CQE_SKIP_SUCCESS**, all subsequent requests marked with drain
+ will be failed at submission time. Note that the error reporting is
+ best effort only, and restrictions may change in the future.
+
+ Available since 5.17.
+
+*ioprio* specifies the I/O priority. See **ioprio_get**(2) for a
+description of Linux I/O priorities.
+
+*fd* specifies the file descriptor against which the operation will be
+performed, with the exception noted above.
+
+If the operation is one of **IORING_OP_READ_FIXED** or
+**IORING_OP_WRITE_FIXED**, *addr* and *len* must fall within the buffer
+located at *buf_index* in the fixed buffer array. If the operation is
+either **IORING_OP_READV** or **IORING_OP_WRITEV**, then *addr* points
+to an iovec array of *len* entries.
+
+*rw_flags*, specified for read and write operations, contains a bitwise
+OR of per-I/O flags, as described in the **preadv2**(2) man page.
+
+The *fsync_flags* bit mask may contain either 0, for a normal file
+integrity sync, or **IORING_FSYNC_DATASYNC** to provide data sync only
+semantics. See the descriptions of **O_SYNC** and **O_DSYNC** in the
+**open**(2) manual page for more information.
+
+The bits that may be set in *poll_events* are defined in *\<poll.h\>*,
+and documented in **poll**(2).
+
+*user_data* is an application-supplied value that will be copied into
+the completion queue entry (see below). *buf_index* is an index into an
+array of fixed buffers, and is only valid if fixed buffers were
+registered. *personality* is the credentials id to use for this
+operation. See **io_uring_register**(2) for how to register
+personalities with io_uring. If set to 0, the current personality of the
+submitting task is used.
+
+Once the submission queue entry is initialized, I/O is submitted by
+placing the index of the submission queue entry into the tail of the
+submission queue. After one or more indexes are added to the queue, and
+the queue tail is advanced, the **io_uring_enter**(2) system call can be
+invoked to initiate the I/O.
+
+Completions use the following data structure:
+
+``` text
+/*
+ * IO completion data structure (Completion Queue Entry)
+ */
+struct io_uring_cqe {
+ __u64 user_data; /* sqe->data submission passed back */
+ __s32 res; /* result code for this event */
+ __u32 flags;
+};
+```
+
+*user_data* is copied from the field of the same name in the submission
+queue entry. The primary use case is to store data that the application
+will need to access upon completion of this particular I/O. The *flags*
+is used for certain commands, like **IORING_OP_POLL_ADD** or in
+conjunction with **IOSQE_BUFFER_SELECT** or **IORING_OP_MSG_RING**, see
+those entries for details. *res* is the operation-specific result, but
+io_uring-specific errors (e.g. flags or opcode invalid) are returned
+through this field. They are described in section **CQE** **ERRORS**.
+
+For read and write opcodes, the return values match *errno* values
+documented in the **preadv2**(2) and **pwritev2**(2) man pages, with
+*res* holding the equivalent of *-errno* for error cases, or the
+transferred number of bytes in case the operation is successful. Hence
+both error and success return can be found in that field in the CQE. For
+other request types, the return values are documented in the matching
+man page for that type, or in the opcodes section above for
+io_uring-specific opcodes.
+
+# RETURN VALUE
+
+**io_uring_enter**(2) returns the number of I/Os successfully consumed.
+This can be zero if *to_submit* was zero or if the submission queue was
+empty. Note that if the ring was created with **IORING_SETUP_SQPOLL**
+specified, then the return value will generally be the same as
+*to_submit* as submission happens outside the context of the system
+call.
+
+The errors related to a submission queue entry will be returned through
+a completion queue entry (see section **CQE** **ERRORS**), rather than
+through the system call itself.
+
+Errors that occur not on behalf of a submission queue entry are returned
+via the system call directly. On such an error, a negative error code is
+returned. The caller should not rely on *errno* variable.
+
+# ERRORS
+
+These are the errors returned by **io_uring_enter**(2) system call.
+
+**EAGAIN**
+
+: The kernel was unable to allocate memory for the request, or otherwise
+ ran out of resources to handle it. The application should wait for
+ some completions and try again.
+
+**EBADF**
+
+: *fd* is not a valid file descriptor.
+
+**EBADFD**
+
+: *fd* is a valid file descriptor, but the io_uring ring is not in the
+ right state (enabled). See **io_uring_register**(2) for details on how
+ to enable the ring.
+
+**EBADR**
+
+: At least one CQE was dropped even with the **IORING_FEAT_NODROP**
+ feature, and there are no otherwise available CQEs. This clears the
+ error state and so with no other changes the next call to
+ **io_uring_enter**(2) will not have this error. This error should be
+ extremely rare and indicates the machine is running critically low on
+ memory. It may be reasonable for the application to terminate running
+ unless it is able to safely handle any CQE being lost.
+
+**EBUSY**
+
+: If the **IORING_FEAT_NODROP** feature flag is set, then **EBUSY** will
+ be returned if there were overflow entries, **IORING_ENTER_GETEVENTS**
+ flag is set and not all of the overflow entries were able to be
+ flushed to the CQ ring.
+
+ Without **IORING_FEAT_NODROP** the application is attempting to
+ overcommit the number of requests it can have pending. The application
+ should wait for some completions and try again. May occur if the
+ application tries to queue more requests than we have room for in the
+ CQ ring, or if the application attempts to wait for more events
+ without having reaped the ones already present in the CQ ring.
+
+**EEXIST**
+
+: The thread submitting the work is invalid. This may occur if
+ **IORING_ENTER_GETEVENTS** and **IORING_SETUP_DEFER_TASKRUN** is set,
+ but the submitting thread is not the thread that initially created or
+ enabled the io_uring associated with *fd.*
+
+**EINVAL**
+
+: Some bits in the *flags* argument are invalid.
+
+**EFAULT**
+
+: An invalid user space address was specified for the *sig* argument.
+
+**ENXIO**
+
+: The io_uring instance is in the process of being torn down.
+
+**EOPNOTSUPP**
+
+: *fd* does not refer to an io_uring instance.
+
+**EINTR**
+
+: The operation was interrupted by a delivery of a signal before it
+ could complete; see **signal**(7). Can happen while waiting for events
+ with **IORING_ENTER_GETEVENTS.**
+
+**EOWNERDEAD**
+
+: The ring has been setup with **IORING_SETUP_SQPOLL** and the sq poll
+ kernel thread has been killed.
+
+# CQE ERRORS
+
+These io_uring-specific errors are returned as a negative value in the
+*res* field of the completion queue entry.
+
+**EACCES**
+
+: The *flags* field or *opcode* in a submission queue entry is not
+ allowed due to registered restrictions. See **io_uring_register**(2)
+ for details on how restrictions work.
+
+**EBADF**
+
+: The *fd* field in the submission queue entry is invalid, or the
+ **IOSQE_FIXED_FILE** flag was set in the submission queue entry, but
+ no files were registered with the io_uring instance.
+
+**EFAULT**
+
+: buffer is outside of the process\' accessible address space
+
+**EFAULT**
+
+: **IORING_OP_READ_FIXED** or **IORING_OP_WRITE_FIXED** was specified in
+ the *opcode* field of the submission queue entry, but either buffers
+ were not registered for this io_uring instance, or the address range
+ described by *addr* and *len* does not fit within the buffer
+ registered at *buf_index*.
+
+**EINVAL**
+
+: The *flags* field or *opcode* in a submission queue entry is invalid.
+
+**EINVAL**
+
+: The *buf_index* member of the submission queue entry is invalid.
+
+**EINVAL**
+
+: The *personality* field in a submission queue entry is invalid.
+
+**EINVAL**
+
+: **IORING_OP_READV** or **IORING_OP_WRITEV** was specified in the
+ submission queue entry, but the io_uring instance has fixed buffers
+ registered.
+
+**EINVAL**
+
+: **IORING_OP_READ_FIXED** or **IORING_OP_WRITE_FIXED** was specified in
+ the submission queue entry, and the *buf_index* is invalid.
+
+**EINVAL**
+
+: **IORING_OP_READV**, **IORING_OP_WRITEV**, **IORING_OP_READ_FIXED**,
+ **IORING_OP_WRITE_FIXED** or **IORING_OP_FSYNC** was specified in the
+ submission queue entry, but the io_uring instance was configured for
+ IOPOLLing, or any of *addr*, *ioprio*, *off*, *len*, or *buf_index*
+ was set in the submission queue entry.
+
+**EINVAL**
+
+: **IORING_OP_POLL_ADD** or **IORING_OP_POLL_REMOVE** was specified in
+ the *opcode* field of the submission queue entry, but the io_uring
+ instance was configured for busy-wait polling
+ (**IORING_SETUP_IOPOLL**), or any of *ioprio*, *off*, *len*, or
+ *buf_index* was non-zero in the submission queue entry.
+
+**EINVAL**
+
+: **IORING_OP_POLL_ADD** was specified in the *opcode* field of the
+ submission queue entry, and the *addr* field was non-zero.
+
+**EOPNOTSUPP**
+
+: *opcode* is valid, but not supported by this kernel.
+
+**EOPNOTSUPP**
+
+: **IOSQE_BUFFER_SELECT** was set in the *flags* field of the submission
+ queue entry, but the *opcode* doesn\'t support buffer selection.
+
+**EINVAL**
+
+: **IORING_OP_TIMEOUT** was specified, but *timeout_flags* specified
+ more than one clock source or **IORING_TIMEOUT_MULTISHOT** was set
+ alongside **IORING_TIMEOUT_ABS**.
diff --git a/man/io_uring_for_each_cqe.3 b/man/io_uring_for_each_cqe.3
deleted file mode 100644
index 78d8f6fc..00000000
--- a/man/io_uring_for_each_cqe.3
+++ /dev/null
@@ -1,63 +0,0 @@
-.\" Copyright (C) 2023 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_for_each_cqe 3 "June 04, 2023" "liburing-2.4" "liburing Manual"
-.SH NAME
-io_uring_for_each_cqe \- iterate pending completion events
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "io_uring_for_each_cqe(struct io_uring *" ring ","
-.BI " unsigned " head ","
-.BI " struct io_uring_cqe *" cqe ") { }
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_for_each_cqe (3)
-is a macro helper that iterates completion events belonging to the
-.I ring
-using
-.I head
-as a temporary iterator, and points
-.I cqe
-to each pending event when iterating.
-
-This helper provides an efficient way to iterate all pending events in
-the ring, and then advancing the CQ ring by calling
-.BR io_uring_cq_advance (3)
-with the number of CQEs consumed when done. As updating the kernel visible
-CQ ring state involves an ordered write, doing it once for a number of
-events is more efficient than handling each completion separately and
-calling
-.BR io_uring_cqe_seen (3)
-for each of them.
-
-.SH EXAMPLE
-.EX
-void handle_cqes(struct io_uring *ring)
-{
- struct io_uring_cqe *cqe;
- unsigned head;
- unsigned i = 0;
-
- io_uring_for_each_cqe(ring, head, cqe) {
- /* handle completion */
- printf("cqe: %d\\n", cqe->res);
- i++;
- }
-
- io_uring_cq_advance(ring, i);
-}
-.EE
-
-.SH RETURN VALUE
-None
-.SH SEE ALSO
-.BR io_uring_wait_cqe_timeout (3),
-.BR io_uring_wait_cqe (3),
-.BR io_uring_wait_cqes (3),
-.BR io_uring_cqe_seen (3),
-.BR io_uring_buf_ring_cq_advance (3)
diff --git a/man/io_uring_for_each_cqe.3.md b/man/io_uring_for_each_cqe.3.md
new file mode 100644
index 00000000..747f77b5
--- /dev/null
+++ b/man/io_uring_for_each_cqe.3.md
@@ -0,0 +1,68 @@
+.\" Copyright (C) 2023 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: June 04, 2023
+footer: liburing-2.4
+header: liburing Manual
+section: 3
+title: io_uring_for_each_cqe
+---
+
+# NAME
+
+io_uring_for_each_cqe - iterate pending completion events
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ io_uring_for_each_cqe(struct io_uring * ring ,
+ unsigned head ,
+ struct io_uring_cqe * cqe ) { }
+```
+
+# DESCRIPTION
+
+The **io_uring_for_each_cqe**(3) is a macro helper that iterates
+completion events belonging to the *ring* using *head* as a temporary
+iterator, and points *cqe* to each pending event when iterating.
+
+This helper provides an efficient way to iterate all pending events in
+the ring, and then advancing the CQ ring by calling
+**io_uring_cq_advance**(3) with the number of CQEs consumed when done.
+As updating the kernel visible CQ ring state involves an ordered write,
+doing it once for a number of events is more efficient than handling
+each completion separately and calling **io_uring_cqe_seen**(3) for each
+of them.
+
+# EXAMPLE
+
+``` text
+void handle_cqes(struct io_uring *ring)
+{
+ struct io_uring_cqe *cqe;
+ unsigned head;
+ unsigned i = 0;
+
+ io_uring_for_each_cqe(ring, head, cqe) {
+ /* handle completion */
+ printf("cqe: %d\n", cqe->res);
+ i++;
+ }
+
+ io_uring_cq_advance(ring, i);
+}
+```
+
+# RETURN VALUE
+
+None
+
+# SEE ALSO
+
+**io_uring_wait_cqe_timeout**(3), **io_uring_wait_cqe**(3),
+**io_uring_wait_cqes**(3), **io_uring_cqe_seen**(3),
+**io_uring_buf_ring_cq_advance**(3)
diff --git a/man/io_uring_free_buf_ring.3 b/man/io_uring_free_buf_ring.3
deleted file mode 100644
index 649cabb3..00000000
--- a/man/io_uring_free_buf_ring.3
+++ /dev/null
@@ -1,53 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_free_buf_ring 3 "Mar 07, 2023" "liburing-2.4" "liburing Manual"
-.SH NAME
-io_uring_free_buf_ring \- register and free a buffer ring for provided buffers
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_free_buf_ring(struct io_uring *" ring ",
-.BI " struct io_uring_buf_ring *" br ",
-.BI " unsigned int " nentries ",
-.BI " int " bgid ");"
-.BI "
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_free_buf_ring (3)
-function unregisters a previously registered shared buffer ring. The ring must
-have heen previously returned from
-.BR io_uring_setup_buf_ring (3) .
-
-The
-.I ring
-argument must pointer to the ring for which the provided buffer ring is being
-registered,
-.I br
-must point to a buffer ring previously returned by
-.BR io_uring_setup_buf_ring (3) ,
-.I nentries
-is the number of entries requested in the buffer ring, and
-.I bgid
-is the buffer group ID that
-.I br
-was setup with.
-
-Under the covers, this function uses
-.BR io_uring_unregister_buf_ring (3)
-to unregister the ring, and handles the freeing of the ring rather than
-letting the application open code it.
-
-Available since 5.19.
-
-.SH RETURN VALUE
-On success
-.BR io_uring_free_buf_ring (3)
-returns zero. On failure it returns
-.BR -errno .
-.SH SEE ALSO
-.BR io_uring_setup_buf_ring (3)
diff --git a/man/io_uring_free_buf_ring.3.md b/man/io_uring_free_buf_ring.3.md
new file mode 100644
index 00000000..9669d892
--- /dev/null
+++ b/man/io_uring_free_buf_ring.3.md
@@ -0,0 +1,55 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: Mar 07, 2023
+footer: liburing-2.4
+header: liburing Manual
+section: 3
+title: io_uring_free_buf_ring
+---
+
+# NAME
+
+io_uring_free_buf_ring - register and free a buffer ring for provided
+buffers
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_free_buf_ring(struct io_uring * ring ,
+ struct io_uring_buf_ring * br ,
+ unsigned int nentries ,
+ int bgid );
+
+```
+
+# DESCRIPTION
+
+The **io_uring_free_buf_ring**(3) function unregisters a previously
+registered shared buffer ring. The ring must have heen previously
+returned from **io_uring_setup_buf_ring**(3)**.**
+
+The *ring* argument must pointer to the ring for which the provided
+buffer ring is being registered, *br* must point to a buffer ring
+previously returned by **io_uring_setup_buf_ring**(3)**,** *nentries* is
+the number of entries requested in the buffer ring, and *bgid* is the
+buffer group ID that *br* was setup with.
+
+Under the covers, this function uses **io_uring_unregister_buf_ring**(3)
+to unregister the ring, and handles the freeing of the ring rather than
+letting the application open code it.
+
+Available since 5.19.
+
+# RETURN VALUE
+
+On success **io_uring_free_buf_ring**(3) returns zero. On failure it
+returns **-errno**.
+
+# SEE ALSO
+
+**io_uring_setup_buf_ring**(3)
diff --git a/man/io_uring_free_probe.3 b/man/io_uring_free_probe.3
deleted file mode 100644
index 960fda39..00000000
--- a/man/io_uring_free_probe.3
+++ /dev/null
@@ -1,27 +0,0 @@
-.\" Copyright (C) 2022 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_free_probe 3 "January 25, 2022" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_free_probe \- free probe instance
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_free_probe(struct io_uring_probe *" probe ");"
-.fi
-.SH DESCRIPTION
-.PP
-The function
-.BR io_uring_free_probe (3)
-frees the
-.I probe
-instance allocated with the
-.BR io_uring_get_probe (3)
-function.
-
-.SH RETURN VALUE
-None
-.SH SEE ALSO
-.BR io_uring_get_probe (3)
diff --git a/man/io_uring_free_probe.3.md b/man/io_uring_free_probe.3.md
new file mode 100644
index 00000000..c53f746c
--- /dev/null
+++ b/man/io_uring_free_probe.3.md
@@ -0,0 +1,36 @@
+.\" Copyright (C) 2022 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 25, 2022
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_free_probe
+---
+
+# NAME
+
+io_uring_free_probe - free probe instance
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_free_probe(struct io_uring_probe * probe );
+```
+
+# DESCRIPTION
+
+The function **io_uring_free_probe**(3) frees the *probe* instance
+allocated with the **io_uring_get_probe**(3) function.
+
+# RETURN VALUE
+
+None
+
+# SEE ALSO
+
+**io_uring_get_probe**(3)
diff --git a/man/io_uring_get_events.3 b/man/io_uring_get_events.3
deleted file mode 100644
index f2415423..00000000
--- a/man/io_uring_get_events.3
+++ /dev/null
@@ -1,33 +0,0 @@
-.\" Copyright (C) 2022 Dylan Yudaken
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_get_events 3 "September 5, 2022" "liburing-2.3" "liburing Manual"
-.SH NAME
-io_uring_get_events \- Flush outstanding requests to CQE ring
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_get_events(struct io_uring *" ring ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_get_events (3)
-function runs outstanding work and flushes completion events to the CQE ring.
-
-There can be events needing to be flushed if the ring was full and had overflowed.
-Alternatively if the ring was setup with the
-.BR IORING_SETUP_DEFER_TASKRUN
-flag then this will process outstanding tasks, possibly resulting in more CQEs.
-
-.SH RETURN VALUE
-On success
-.BR io_uring_get_events (3)
-returns 0. On failure it returns
-.BR -errno .
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit_and_get_events (3),
-.BR io_uring_cq_has_overflow (3)
diff --git a/man/io_uring_get_events.3.md b/man/io_uring_get_events.3.md
new file mode 100644
index 00000000..0946fa0d
--- /dev/null
+++ b/man/io_uring_get_events.3.md
@@ -0,0 +1,43 @@
+.\" Copyright (C) 2022 Dylan Yudaken
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: September 5, 2022
+footer: liburing-2.3
+header: liburing Manual
+section: 3
+title: io_uring_get_events
+---
+
+# NAME
+
+io_uring_get_events - Flush outstanding requests to CQE ring
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_get_events(struct io_uring * ring );
+```
+
+# DESCRIPTION
+
+The **io_uring_get_events**(3) function runs outstanding work and
+flushes completion events to the CQE ring.
+
+There can be events needing to be flushed if the ring was full and had
+overflowed. Alternatively if the ring was setup with the
+**IORING_SETUP_DEFER_TASKRUN** flag then this will process outstanding
+tasks, possibly resulting in more CQEs.
+
+# RETURN VALUE
+
+On success **io_uring_get_events**(3) returns 0. On failure it returns
+**-errno**.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit_and_get_events**(3),
+**io_uring_cq_has_overflow**(3)
diff --git a/man/io_uring_get_probe.3 b/man/io_uring_get_probe.3
deleted file mode 100644
index 353cc731..00000000
--- a/man/io_uring_get_probe.3
+++ /dev/null
@@ -1,30 +0,0 @@
-.\" Copyright (C) 2022 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_get_probe 3 "January 25, 2022" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_get_probe \- get probe instance
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "io_uring_probe *io_uring_get_probe(void);"
-.fi
-.SH DESCRIPTION
-.PP
-The function
-.BR io_uring_get_probe (3)
-returns an allocated io_uring_probe structure to the caller. The caller is
-responsible for freeing the structure with the function
-.BR io_uring_free_probe (3).
-
-.SH NOTES
-Earlier versions of the Linux kernel do not support probe. If the kernel
-doesn't support probe, this function will return NULL.
-
-.SH RETURN VALUE
-On success it returns an allocated io_uring_probe structure, otherwise
-it returns NULL.
-.SH SEE ALSO
-.BR io_uring_free_probe (3)
diff --git a/man/io_uring_get_probe.3.md b/man/io_uring_get_probe.3.md
new file mode 100644
index 00000000..ed3f28f4
--- /dev/null
+++ b/man/io_uring_get_probe.3.md
@@ -0,0 +1,43 @@
+.\" Copyright (C) 2022 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 25, 2022
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_get_probe
+---
+
+# NAME
+
+io_uring_get_probe - get probe instance
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ io_uring_probe *io_uring_get_probe(void);
+```
+
+# DESCRIPTION
+
+The function **io_uring_get_probe**(3) returns an allocated
+io_uring_probe structure to the caller. The caller is responsible for
+freeing the structure with the function **io_uring_free_probe**(3).
+
+# NOTES
+
+Earlier versions of the Linux kernel do not support probe. If the kernel
+doesn\'t support probe, this function will return NULL.
+
+# RETURN VALUE
+
+On success it returns an allocated io_uring_probe structure, otherwise
+it returns NULL.
+
+# SEE ALSO
+
+**io_uring_free_probe**(3)
diff --git a/man/io_uring_get_probe_ring.3 b/man/io_uring_get_probe_ring.3
deleted file mode 100644
index 63490743..00000000
--- a/man/io_uring_get_probe_ring.3
+++ /dev/null
@@ -1,39 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_get_probe_ring 3 "January 18, 2025" "liburing-2.4" "liburing Manual"
-.SH NAME
-io_uring_get_probe_ring \- get probe information from an existing ring
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "struct io_uring_probe *io_uring_get_probe_ring(struct io_uring *" ring ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_get_probe_ring (3)
-function returns probe information for the io_uring instance specified by
-.IR ring .
-This allows the application to determine which opcodes are supported by
-the kernel.
-
-The returned probe structure and must be freed by the application using
-.BR io_uring_free_probe (3)
-when no longer needed.
-
-This function is similar to
-.BR io_uring_get_probe (3),
-except it uses an existing ring instead of creating a temporary one.
-
-.SH RETURN VALUE
-Returns a pointer to an allocated
-.I struct io_uring_probe
-on success, or NULL on failure.
-.SH SEE ALSO
-.BR io_uring_get_probe (3),
-.BR io_uring_free_probe (3),
-.BR io_uring_opcode_supported (3),
-.BR io_uring_register_probe (3)
diff --git a/man/io_uring_get_probe_ring.3.md b/man/io_uring_get_probe_ring.3.md
new file mode 100644
index 00000000..9d4b91de
--- /dev/null
+++ b/man/io_uring_get_probe_ring.3.md
@@ -0,0 +1,45 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 18, 2025
+footer: liburing-2.4
+header: liburing Manual
+section: 3
+title: io_uring_get_probe_ring
+---
+
+# NAME
+
+io_uring_get_probe_ring - get probe information from an existing ring
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ struct io_uring_probe *io_uring_get_probe_ring(struct io_uring * ring );
+```
+
+# DESCRIPTION
+
+The **io_uring_get_probe_ring**(3) function returns probe information
+for the io_uring instance specified by *ring*. This allows the
+application to determine which opcodes are supported by the kernel.
+
+The returned probe structure and must be freed by the application using
+**io_uring_free_probe**(3) when no longer needed.
+
+This function is similar to **io_uring_get_probe**(3), except it uses an
+existing ring instead of creating a temporary one.
+
+# RETURN VALUE
+
+Returns a pointer to an allocated *struct io_uring_probe* on success, or
+NULL on failure.
+
+# SEE ALSO
+
+**io_uring_get_probe**(3), **io_uring_free_probe**(3),
+**io_uring_opcode_supported**(3), **io_uring_register_probe**(3)
diff --git a/man/io_uring_get_sqe.3 b/man/io_uring_get_sqe.3
deleted file mode 100644
index b257ebb3..00000000
--- a/man/io_uring_get_sqe.3
+++ /dev/null
@@ -1,57 +0,0 @@
-.\" Copyright (C) 2020 Jens Axboe <axboe@kernel.dk>
-.\" Copyright (C) 2020 Red Hat, Inc.
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_get_sqe 3 "July 10, 2020" "liburing-0.7" "liburing Manual"
-.SH NAME
-io_uring_get_sqe \- get the next available submission queue entry from the
-submission queue
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "struct io_uring_sqe *io_uring_get_sqe(struct io_uring *" ring ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_get_sqe (3)
-function gets the next available submission queue entry from the submission
-queue belonging to the
-.I ring
-param.
-
-On success
-.BR io_uring_get_sqe (3)
-returns a pointer to the submission queue entry. On failure NULL is returned.
-
-If a submission queue entry is returned, it should be filled out via one of the
-prep functions such as
-.BR io_uring_prep_read (3)
-and submitted via
-.BR io_uring_submit (3).
-
-Note that neither
-.BR io_uring_get_sqe
-nor the prep functions set (or clear) the
-.B user_data
-field of the SQE. If the caller expects
-.BR io_uring_cqe_get_data (3)
-or
-.BR io_uring_cqe_get_data64 (3)
-to return valid data when reaping IO completions, either
-.BR io_uring_sqe_set_data (3)
-or
-.BR io_uring_sqe_set_data64 (3)
-.B MUST
-have been called before submitting the request.
-
-.SH RETURN VALUE
-.BR io_uring_get_sqe (3)
-returns a pointer to the next submission queue event on success and NULL on
-failure. If NULL is returned, the SQ ring is currently full and entries must
-be submitted for processing before new ones can get allocated.
-.SH SEE ALSO
-.BR io_uring_submit (3),
-.BR io_uring_sqe_set_data (3)
diff --git a/man/io_uring_get_sqe.3.md b/man/io_uring_get_sqe.3.md
new file mode 100644
index 00000000..f408050f
--- /dev/null
+++ b/man/io_uring_get_sqe.3.md
@@ -0,0 +1,55 @@
+.\" Copyright (C) 2020 Jens Axboe <axboe@kernel.dk>
+.\" Copyright (C) 2020 Red Hat, Inc.
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: July 10, 2020
+footer: liburing-0.7
+header: liburing Manual
+section: 3
+title: io_uring_get_sqe
+---
+
+# NAME
+
+io_uring_get_sqe - get the next available submission queue entry from
+the submission queue
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ struct io_uring_sqe *io_uring_get_sqe(struct io_uring * ring );
+```
+
+# DESCRIPTION
+
+The **io_uring_get_sqe**(3) function gets the next available submission
+queue entry from the submission queue belonging to the *ring* param.
+
+On success **io_uring_get_sqe**(3) returns a pointer to the submission
+queue entry. On failure NULL is returned.
+
+If a submission queue entry is returned, it should be filled out via one
+of the prep functions such as **io_uring_prep_read**(3) and submitted
+via **io_uring_submit**(3).
+
+Note that neither **io_uring_get_sqe** nor the prep functions set (or
+clear) the **user_data** field of the SQE. If the caller expects
+**io_uring_cqe_get_data**(3) or **io_uring_cqe_get_data64**(3) to return
+valid data when reaping IO completions, either
+**io_uring_sqe_set_data**(3) or **io_uring_sqe_set_data64**(3) **MUST**
+have been called before submitting the request.
+
+# RETURN VALUE
+
+**io_uring_get_sqe**(3) returns a pointer to the next submission queue
+event on success and NULL on failure. If NULL is returned, the SQ ring
+is currently full and entries must be submitted for processing before
+new ones can get allocated.
+
+# SEE ALSO
+
+**io_uring_submit**(3), **io_uring_sqe_set_data**(3)
diff --git a/man/io_uring_get_sqe128.3 b/man/io_uring_get_sqe128.3
deleted file mode 100644
index 1acc82f9..00000000
--- a/man/io_uring_get_sqe128.3
+++ /dev/null
@@ -1,67 +0,0 @@
-.\" Copyright (C) 2020 Jens Axboe <axboe@kernel.dk>
-.\" Copyright (C) 2020 Red Hat, Inc.
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_get_sqe128 3 "October 22, 2025" "liburing-2.13" "liburing Manual"
-.SH NAME
-io_uring_get_sqe128 \- get the next available 128-byte submission queue entry
-from the submission queue
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "struct io_uring_sqe *io_uring_get_sqe128(struct io_uring *" ring ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_get_sqe128 (3)
-function gets the next available 128-byte submission queue entry from the
-submission queue belonging to the
-.I ring
-param.
-
-On success
-.BR io_uring_get_sqe128 (3)
-returns a pointer to the submission queue entry. On failure
-.B NULL
-is returned.
-
-If a submission queue entry is returned, it should be filled out via one of the
-prep functions such as
-.BR io_uring_prep_uring_cmd128 (3)
-and submitted via
-.BR io_uring_submit (3).
-
-Note that neither
-.BR io_uring_get_sqe128 (3)
-nor the prep functions set (or clear) the
-.B user_data
-field of the SQE. If the caller expects
-.BR io_uring_cqe_get_data (3)
-or
-.BR io_uring_cqe_get_data64 (3)
-to return valid data when reaping IO completions, either
-.BR io_uring_sqe_set_data (3)
-or
-.BR io_uring_sqe_set_data64 (3)
-.B MUST
-have been called before submitting the request.
-
-.SH RETURN VALUE
-.BR io_uring_get_sqe128 (3)
-returns a pointer to the next submission queue event on success and NULL on
-failure. If
-.B NULL
-is returned, the SQ ring either wasn't created with support for 128-byte SQE
-entries (
-.B IORING_SETUP_SQE128
-or
-.B IORING_SETUP_SQE_MIXED
-) or is currently full and entries must be submitted for processing before new
-ones can get allocated.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_sqe_set_data (3)
diff --git a/man/io_uring_get_sqe128.3.md b/man/io_uring_get_sqe128.3.md
new file mode 100644
index 00000000..7a133565
--- /dev/null
+++ b/man/io_uring_get_sqe128.3.md
@@ -0,0 +1,59 @@
+.\" Copyright (C) 2020 Jens Axboe <axboe@kernel.dk>
+.\" Copyright (C) 2020 Red Hat, Inc.
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: October 22, 2025
+footer: liburing-2.13
+header: liburing Manual
+section: 3
+title: io_uring_get_sqe128
+---
+
+# NAME
+
+io_uring_get_sqe128 - get the next available 128-byte submission queue
+entry from the submission queue
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ struct io_uring_sqe *io_uring_get_sqe128(struct io_uring * ring );
+```
+
+# DESCRIPTION
+
+The **io_uring_get_sqe128**(3) function gets the next available 128-byte
+submission queue entry from the submission queue belonging to the *ring*
+param.
+
+On success **io_uring_get_sqe128**(3) returns a pointer to the
+submission queue entry. On failure **NULL** is returned.
+
+If a submission queue entry is returned, it should be filled out via one
+of the prep functions such as **io_uring_prep_uring_cmd128**(3) and
+submitted via **io_uring_submit**(3).
+
+Note that neither **io_uring_get_sqe128**(3) nor the prep functions set
+(or clear) the **user_data** field of the SQE. If the caller expects
+**io_uring_cqe_get_data**(3) or **io_uring_cqe_get_data64**(3) to return
+valid data when reaping IO completions, either
+**io_uring_sqe_set_data**(3) or **io_uring_sqe_set_data64**(3) **MUST**
+have been called before submitting the request.
+
+# RETURN VALUE
+
+**io_uring_get_sqe128**(3) returns a pointer to the next submission
+queue event on success and NULL on failure. If **NULL** is returned, the
+SQ ring either wasn\'t created with support for 128-byte SQE entries (
+**IORING_SETUP_SQE128** or **IORING_SETUP_SQE_MIXED** ) or is currently
+full and entries must be submitted for processing before new ones can
+get allocated.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_sqe_set_data**(3)
diff --git a/man/io_uring_linked_requests.7 b/man/io_uring_linked_requests.7
deleted file mode 100644
index 8f58ad13..00000000
--- a/man/io_uring_linked_requests.7
+++ /dev/null
@@ -1,271 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_linked_requests 7 "January 18, 2025" "Linux" "Linux Programmer's Manual"
-.SH NAME
-io_uring_linked_requests \- io_uring linked requests overview
-.SH DESCRIPTION
-Linked requests allow applications to chain multiple io_uring operations
-together, creating dependencies between them. When requests are linked,
-they execute sequentially rather than concurrently, with each request
-starting only after the previous one in the chain completes.
-.SS Why use linked requests?
-Normal io_uring submissions are independent and may execute in any order
-or concurrently. However, some operations have natural dependencies:
-.IP \(bu 2
-Read from one file, then write to another
-.IP \(bu
-Connect to a server, then send a request
-.IP \(bu
-Accept a connection, then receive data
-.IP \(bu
-Perform an operation with a timeout
-.PP
-Without linking, applications would need to wait for completions and
-submit follow-up requests manually. Linked requests allow the entire
-chain to be submitted at once, reducing round trips between user space
-and the kernel.
-
-Linked requests are most beneficial when:
-.IP \(bu 2
-Operations must execute in a specific order
-.IP \(bu
-Later operations depend on earlier ones succeeding
-.IP \(bu
-You want to attach a timeout to an operation
-.IP \(bu
-Reducing submission latency is important
-.SS Creating linked requests
-Requests are linked by setting the
-.B IOSQE_IO_LINK
-flag on a request. This links it to the next request in the submission.
-The chain continues until a request without the link flag is encountered.
-.PP
-.in +4n
-.EX
-struct io_uring_sqe *sqe;
-
-/* First request in chain */
-sqe = io_uring_get_sqe(ring);
-io_uring_prep_read(sqe, fd_in, buf, len, 0);
-sqe->flags |= IOSQE_IO_LINK;
-
-/* Second request, linked to first */
-sqe = io_uring_get_sqe(ring);
-io_uring_prep_write(sqe, fd_out, buf, len, 0);
-sqe->flags |= IOSQE_IO_LINK;
-
-/* Third request, end of chain (no link flag) */
-sqe = io_uring_get_sqe(ring);
-io_uring_prep_fsync(sqe, fd_out, 0);
-
-io_uring_submit(ring);
-.EE
-.in
-.PP
-In this example, the read completes first, then the write, then the
-fsync. Each operation waits for the previous one to complete before
-starting.
-.SS Soft links vs hard links
-There are two types of links, which differ in how they handle errors:
-.PP
-.B Soft links (IOSQE_IO_LINK)
-.RS 4
-If a request in the chain fails (returns a negative error code), all
-subsequent requests in the chain are canceled with
-.BR -ECANCELED .
-This is useful when later operations depend on earlier ones succeeding.
-.RE
-.PP
-.B Hard links (IOSQE_IO_HARDLINK)
-.RS 4
-The chain continues executing even if a request fails. Each request
-runs regardless of the outcome of previous requests. This is useful
-when you want to attempt all operations even if some fail.
-.RE
-.PP
-.in +4n
-.EX
-/* Soft link: write is canceled if read fails */
-sqe = io_uring_get_sqe(ring);
-io_uring_prep_read(sqe, fd, buf, len, 0);
-sqe->flags |= IOSQE_IO_LINK;
-
-sqe = io_uring_get_sqe(ring);
-io_uring_prep_write(sqe, fd2, buf, len, 0);
-
-/* Hard link: write runs even if read fails */
-sqe = io_uring_get_sqe(ring);
-io_uring_prep_read(sqe, fd, buf, len, 0);
-sqe->flags |= IOSQE_IO_HARDLINK;
-
-sqe = io_uring_get_sqe(ring);
-io_uring_prep_write(sqe, fd2, buf, len, 0);
-.EE
-.in
-.SS Link timeouts
-A common use of linked requests is to add a timeout to an operation.
-The
-.B IORING_OP_LINK_TIMEOUT
-operation (set up with
-.BR io_uring_prep_link_timeout (3))
-is designed specifically for this:
-.PP
-.in +4n
-.EX
-struct __kernel_timespec ts = { .tv_sec = 5, .tv_nsec = 0 };
-
-/* The operation to be timed */
-sqe = io_uring_get_sqe(ring);
-io_uring_prep_read(sqe, fd, buf, len, 0);
-sqe->flags |= IOSQE_IO_LINK;
-
-/* The timeout, linked to the read */
-sqe = io_uring_get_sqe(ring);
-io_uring_prep_link_timeout(sqe, &ts, 0);
-
-io_uring_submit(ring);
-.EE
-.in
-.PP
-If the read completes before the timeout:
-.IP \(bu 2
-The read CQE has the actual result
-.IP \(bu
-The timeout CQE has
-.B -ECANCELED
-.PP
-If the timeout expires first:
-.IP \(bu 2
-The read CQE has
-.B -ECANCELED
-(or
-.B -EINTR
-if it was in progress)
-.IP \(bu
-The timeout CQE has
-.B -ETIME
-.PP
-Link timeouts only apply to the immediately preceding request in the
-chain. To timeout an entire chain, the timeout must be linked after
-the last operation.
-.SS Completion ordering
-Each request in a linked chain generates its own CQE. Completions for
-linked requests are ordered \(em the CQE for an earlier request in the
-chain will be posted before the CQE for a later request.
-
-Applications can rely on this ordering when processing completions.
-However, if other unlinked requests are in flight, their completions
-may be interleaved with the chain's completions.
-.SS Error handling
-For soft-linked chains, error handling is straightforward:
-.IP \(bu 2
-Check each CQE's result
-.IP \(bu
-If a request failed, all subsequent requests will have
-.B -ECANCELED
-.IP \(bu
-The first non-canceled error indicates where the chain broke
-.PP
-.in +4n
-.EX
-/* Processing a linked chain's completions */
-for (int i = 0; i < chain_length; i++) {
- io_uring_wait_cqe(ring, &cqe);
-
- if (cqe->res == -ECANCELED) {
- /* Previous request in chain failed */
- } else if (cqe->res < 0) {
- /* This request failed, caused chain break */
- handle_error(cqe->res);
- } else {
- /* Success */
- handle_success(cqe->res);
- }
-
- io_uring_cqe_seen(ring, cqe);
-}
-.EE
-.in
-.SS Common patterns
-.PP
-.B Copy with sync:
-.RS 4
-Read data, write it elsewhere, then sync:
-.PP
-.in +4n
-.EX
-io_uring_prep_read(sqe1, src_fd, buf, len, 0);
-sqe1->flags |= IOSQE_IO_LINK;
-
-io_uring_prep_write(sqe2, dst_fd, buf, len, 0);
-sqe2->flags |= IOSQE_IO_LINK;
-
-io_uring_prep_fsync(sqe3, dst_fd, 0);
-.EE
-.in
-.RE
-.PP
-.B Connect with timeout:
-.RS 4
-Attempt connection with a time limit:
-.PP
-.in +4n
-.EX
-io_uring_prep_connect(sqe1, sockfd, addr, addrlen);
-sqe1->flags |= IOSQE_IO_LINK;
-
-io_uring_prep_link_timeout(sqe2, &timeout, 0);
-.EE
-.in
-.RE
-.PP
-.B Send after connect:
-.RS 4
-Connect then immediately send data:
-.PP
-.in +4n
-.EX
-io_uring_prep_connect(sqe1, sockfd, addr, addrlen);
-sqe1->flags |= IOSQE_IO_LINK;
-
-io_uring_prep_send(sqe2, sockfd, data, len, 0);
-.EE
-.in
-.RE
-.SH NOTES
-.IP \(bu 2
-Linked requests must be submitted together in the same
-.BR io_uring_submit (3)
-call. The chain is defined by the order of SQEs in the submission.
-.IP \(bu
-The link flag on the last request in a chain is ignored (it has
-nothing to link to).
-.IP \(bu
-Chains can be arbitrarily long, limited only by SQ ring size.
-.IP \(bu
-Mixing
-.B IOSQE_IO_LINK
-and
-.B IOSQE_IO_HARDLINK
-in the same chain is allowed. Each link's type determines what happens
-if that specific request fails.
-.IP \(bu
-Linked requests share the same
-.I personality
-if set, allowing credential inheritance through the chain.
-.IP \(bu
-If a request in a chain is canceled (e.g., via
-.BR io_uring_prep_cancel (3)),
-the chain breaks as if that request had failed.
-.IP \(bu
-Linked requests have performance implications: they force sequential
-execution, preventing the kernel from optimizing or parallelizing
-operations. Use links only when ordering is required. For independent
-operations, submitting them without links allows the kernel to execute
-them concurrently or reorder them for better performance.
-.SH SEE ALSO
-.BR io_uring (7),
-.BR io_uring_prep_link_timeout (3),
-.BR io_uring_prep_cancel (3),
-.BR io_uring_sqe_set_flags (3)
diff --git a/man/io_uring_linked_requests.7.md b/man/io_uring_linked_requests.7.md
new file mode 100644
index 00000000..576a27c7
--- /dev/null
+++ b/man/io_uring_linked_requests.7.md
@@ -0,0 +1,261 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 18, 2025
+footer: Linux
+header: Linux Programmer\'s Manual
+section: 7
+title: io_uring_linked_requests
+---
+
+# NAME
+
+io_uring_linked_requests - io_uring linked requests overview
+
+# DESCRIPTION
+
+Linked requests allow applications to chain multiple io_uring operations
+together, creating dependencies between them. When requests are linked,
+they execute sequentially rather than concurrently, with each request
+starting only after the previous one in the chain completes.
+
+## Why use linked requests?
+
+Normal io_uring submissions are independent and may execute in any order
+or concurrently. However, some operations have natural dependencies:
+
+- Read from one file, then write to another
+
+- Connect to a server, then send a request
+
+- Accept a connection, then receive data
+
+- Perform an operation with a timeout
+
+Without linking, applications would need to wait for completions and
+submit follow-up requests manually. Linked requests allow the entire
+chain to be submitted at once, reducing round trips between user space
+and the kernel.
+
+Linked requests are most beneficial when:
+
+- Operations must execute in a specific order
+
+- Later operations depend on earlier ones succeeding
+
+- You want to attach a timeout to an operation
+
+- Reducing submission latency is important
+
+## Creating linked requests
+
+Requests are linked by setting the **IOSQE_IO_LINK** flag on a request.
+This links it to the next request in the submission. The chain continues
+until a request without the link flag is encountered.
+
+``` text
+struct io_uring_sqe *sqe;
+
+/* First request in chain */
+sqe = io_uring_get_sqe(ring);
+io_uring_prep_read(sqe, fd_in, buf, len, 0);
+sqe->flags |= IOSQE_IO_LINK;
+
+/* Second request, linked to first */
+sqe = io_uring_get_sqe(ring);
+io_uring_prep_write(sqe, fd_out, buf, len, 0);
+sqe->flags |= IOSQE_IO_LINK;
+
+/* Third request, end of chain (no link flag) */
+sqe = io_uring_get_sqe(ring);
+io_uring_prep_fsync(sqe, fd_out, 0);
+
+io_uring_submit(ring);
+```
+
+In this example, the read completes first, then the write, then the
+fsync. Each operation waits for the previous one to complete before
+starting.
+
+## Soft links vs hard links
+
+There are two types of links, which differ in how they handle errors:
+
+**Soft links (IOSQE_IO_LINK)**
+
+> If a request in the chain fails (returns a negative error code), all
+> subsequent requests in the chain are canceled with **-ECANCELED**.
+> This is useful when later operations depend on earlier ones
+> succeeding.
+
+**Hard links (IOSQE_IO_HARDLINK)**
+
+> The chain continues executing even if a request fails. Each request
+> runs regardless of the outcome of previous requests. This is useful
+> when you want to attempt all operations even if some fail.
+
+``` text
+/* Soft link: write is canceled if read fails */
+sqe = io_uring_get_sqe(ring);
+io_uring_prep_read(sqe, fd, buf, len, 0);
+sqe->flags |= IOSQE_IO_LINK;
+
+sqe = io_uring_get_sqe(ring);
+io_uring_prep_write(sqe, fd2, buf, len, 0);
+
+/* Hard link: write runs even if read fails */
+sqe = io_uring_get_sqe(ring);
+io_uring_prep_read(sqe, fd, buf, len, 0);
+sqe->flags |= IOSQE_IO_HARDLINK;
+
+sqe = io_uring_get_sqe(ring);
+io_uring_prep_write(sqe, fd2, buf, len, 0);
+```
+
+## Link timeouts
+
+A common use of linked requests is to add a timeout to an operation. The
+**IORING_OP_LINK_TIMEOUT** operation (set up with
+**io_uring_prep_link_timeout**(3)) is designed specifically for this:
+
+``` text
+struct __kernel_timespec ts = { .tv_sec = 5, .tv_nsec = 0 };
+
+/* The operation to be timed */
+sqe = io_uring_get_sqe(ring);
+io_uring_prep_read(sqe, fd, buf, len, 0);
+sqe->flags |= IOSQE_IO_LINK;
+
+/* The timeout, linked to the read */
+sqe = io_uring_get_sqe(ring);
+io_uring_prep_link_timeout(sqe, &ts, 0);
+
+io_uring_submit(ring);
+```
+
+If the read completes before the timeout:
+
+- The read CQE has the actual result
+
+- The timeout CQE has **-ECANCELED**
+
+If the timeout expires first:
+
+- The read CQE has **-ECANCELED** (or **-EINTR** if it was in progress)
+
+- The timeout CQE has **-ETIME**
+
+Link timeouts only apply to the immediately preceding request in the
+chain. To timeout an entire chain, the timeout must be linked after the
+last operation.
+
+## Completion ordering
+
+Each request in a linked chain generates its own CQE. Completions for
+linked requests are ordered --- the CQE for an earlier request in the
+chain will be posted before the CQE for a later request.
+
+Applications can rely on this ordering when processing completions.
+However, if other unlinked requests are in flight, their completions may
+be interleaved with the chain\'s completions.
+
+## Error handling
+
+For soft-linked chains, error handling is straightforward:
+
+- Check each CQE\'s result
+
+- If a request failed, all subsequent requests will have **-ECANCELED**
+
+- The first non-canceled error indicates where the chain broke
+
+``` text
+/* Processing a linked chain's completions */
+for (int i = 0; i < chain_length; i++) {
+ io_uring_wait_cqe(ring, &cqe);
+
+ if (cqe->res == -ECANCELED) {
+ /* Previous request in chain failed */
+ } else if (cqe->res < 0) {
+ /* This request failed, caused chain break */
+ handle_error(cqe->res);
+ } else {
+ /* Success */
+ handle_success(cqe->res);
+ }
+
+ io_uring_cqe_seen(ring, cqe);
+}
+```
+
+## Common patterns
+
+**Copy with sync:**
+
+> Read data, write it elsewhere, then sync:
+>
+> ``` text
+> io_uring_prep_read(sqe1, src_fd, buf, len, 0);
+> sqe1->flags |= IOSQE_IO_LINK;
+>
+> io_uring_prep_write(sqe2, dst_fd, buf, len, 0);
+> sqe2->flags |= IOSQE_IO_LINK;
+>
+> io_uring_prep_fsync(sqe3, dst_fd, 0);
+> ```
+
+**Connect with timeout:**
+
+> Attempt connection with a time limit:
+>
+> ``` text
+> io_uring_prep_connect(sqe1, sockfd, addr, addrlen);
+> sqe1->flags |= IOSQE_IO_LINK;
+>
+> io_uring_prep_link_timeout(sqe2, &timeout, 0);
+> ```
+
+**Send after connect:**
+
+> Connect then immediately send data:
+>
+> ``` text
+> io_uring_prep_connect(sqe1, sockfd, addr, addrlen);
+> sqe1->flags |= IOSQE_IO_LINK;
+>
+> io_uring_prep_send(sqe2, sockfd, data, len, 0);
+> ```
+
+# NOTES
+
+- Linked requests must be submitted together in the same
+ **io_uring_submit**(3) call. The chain is defined by the order of SQEs
+ in the submission.
+
+- The link flag on the last request in a chain is ignored (it has
+ nothing to link to).
+
+- Chains can be arbitrarily long, limited only by SQ ring size.
+
+- Mixing **IOSQE_IO_LINK** and **IOSQE_IO_HARDLINK** in the same chain
+ is allowed. Each link\'s type determines what happens if that specific
+ request fails.
+
+- Linked requests share the same *personality* if set, allowing
+ credential inheritance through the chain.
+
+- If a request in a chain is canceled (e.g., via
+ **io_uring_prep_cancel**(3)), the chain breaks as if that request had
+ failed.
+
+- Linked requests have performance implications: they force sequential
+ execution, preventing the kernel from optimizing or parallelizing
+ operations. Use links only when ordering is required. For independent
+ operations, submitting them without links allows the kernel to execute
+ them concurrently or reorder them for better performance.
+
+# SEE ALSO
+
+**io_uring**(7), **io_uring_prep_link_timeout**(3),
+**io_uring_prep_cancel**(3), **io_uring_sqe_set_flags**(3)
diff --git a/man/io_uring_memory_size_params.3 b/man/io_uring_memory_size_params.3
deleted file mode 100644
index 49ea6c10..00000000
--- a/man/io_uring_memory_size_params.3
+++ /dev/null
@@ -1,45 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_memory_size_params 3 "January 18, 2025" "liburing-2.11" "liburing Manual"
-.SH NAME
-io_uring_memory_size_params \- get memory size needed for a ring with params
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "ssize_t io_uring_memory_size_params(unsigned " entries ", struct io_uring_params *" p ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_memory_size_params (3)
-function returns the total memory size needed for an io_uring ring with
-.I entries
-entries and the parameters specified in
-.IR p .
-
-This is useful for applications that want to pre-allocate memory for a ring
-or want to know the memory footprint before creating a ring.
-
-This function provides more control than
-.BR io_uring_memory_size (3)
-by allowing the caller to specify full ring parameters including CQ size
-via
-.I p->cq_entries
-when
-.B IORING_SETUP_CQSIZE
-is set in
-.IR p->flags .
-
-.SH RETURN VALUE
-Returns the required memory size in bytes on success, or a negative errno
-value on error.
-.TP
-.B -EINVAL
-Invalid entries value (0 or too large without IORING_SETUP_CLAMP).
-.SH SEE ALSO
-.BR io_uring_memory_size (3),
-.BR io_uring_mlock_size_params (3),
-.BR io_uring_queue_init_params (3)
diff --git a/man/io_uring_memory_size_params.3.md b/man/io_uring_memory_size_params.3.md
new file mode 100644
index 00000000..117f0892
--- /dev/null
+++ b/man/io_uring_memory_size_params.3.md
@@ -0,0 +1,51 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 18, 2025
+footer: liburing-2.11
+header: liburing Manual
+section: 3
+title: io_uring_memory_size_params
+---
+
+# NAME
+
+io_uring_memory_size_params - get memory size needed for a ring with
+params
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ ssize_t io_uring_memory_size_params(unsigned entries , struct io_uring_params * p );
+```
+
+# DESCRIPTION
+
+The **io_uring_memory_size_params**(3) function returns the total memory
+size needed for an io_uring ring with *entries* entries and the
+parameters specified in *p*.
+
+This is useful for applications that want to pre-allocate memory for a
+ring or want to know the memory footprint before creating a ring.
+
+This function provides more control than **io_uring_memory_size**(3) by
+allowing the caller to specify full ring parameters including CQ size
+via *p-\>cq_entries* when **IORING_SETUP_CQSIZE** is set in *p-\>flags*.
+
+# RETURN VALUE
+
+Returns the required memory size in bytes on success, or a negative
+errno value on error.
+
+**-EINVAL**
+
+: Invalid entries value (0 or too large without IORING_SETUP_CLAMP).
+
+# SEE ALSO
+
+**io_uring_memory_size**(3), **io_uring_mlock_size_params**(3),
+**io_uring_queue_init_params**(3)
diff --git a/man/io_uring_mlock_size.3 b/man/io_uring_mlock_size.3
deleted file mode 100644
index d75bb5e7..00000000
--- a/man/io_uring_mlock_size.3
+++ /dev/null
@@ -1,42 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_mlock_size 3 "January 18, 2025" "liburing-2.4" "liburing Manual"
-.SH NAME
-io_uring_mlock_size \- get required memlock size for a ring
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "ssize_t io_uring_mlock_size(unsigned " entries ", unsigned " flags ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_mlock_size (3)
-function returns the required
-.B RLIMIT_MEMLOCK
-memory size for an io_uring ring with
-.I entries
-entries and the specified setup
-.IR flags .
-
-On newer kernels (5.12+), io_uring no longer requires any memlock memory
-and this function will return 0. On older kernels (5.11 and prior), this
-returns the required memory so that the caller can ensure that enough
-.B RLIMIT_MEMLOCK
-space is available before setting up a ring.
-
-For more control over the ring parameters, use
-.BR io_uring_mlock_size_params (3)
-instead.
-
-.SH RETURN VALUE
-Returns the required memlock size in bytes on success, 0 if no memlock
-is needed, or a negative errno value on error.
-.SH SEE ALSO
-.BR io_uring_mlock_size_params (3),
-.BR io_uring_memory_size (3),
-.BR io_uring_queue_init (3),
-.BR getrlimit (2)
diff --git a/man/io_uring_mlock_size.3.md b/man/io_uring_mlock_size.3.md
new file mode 100644
index 00000000..2e5518fd
--- /dev/null
+++ b/man/io_uring_mlock_size.3.md
@@ -0,0 +1,47 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 18, 2025
+footer: liburing-2.4
+header: liburing Manual
+section: 3
+title: io_uring_mlock_size
+---
+
+# NAME
+
+io_uring_mlock_size - get required memlock size for a ring
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ ssize_t io_uring_mlock_size(unsigned entries , unsigned flags );
+```
+
+# DESCRIPTION
+
+The **io_uring_mlock_size**(3) function returns the required
+**RLIMIT_MEMLOCK** memory size for an io_uring ring with *entries*
+entries and the specified setup *flags*.
+
+On newer kernels (5.12+), io_uring no longer requires any memlock memory
+and this function will return 0. On older kernels (5.11 and prior), this
+returns the required memory so that the caller can ensure that enough
+**RLIMIT_MEMLOCK** space is available before setting up a ring.
+
+For more control over the ring parameters, use
+**io_uring_mlock_size_params**(3) instead.
+
+# RETURN VALUE
+
+Returns the required memlock size in bytes on success, 0 if no memlock
+is needed, or a negative errno value on error.
+
+# SEE ALSO
+
+**io_uring_mlock_size_params**(3), **io_uring_memory_size**(3),
+**io_uring_queue_init**(3), **getrlimit**(2)
diff --git a/man/io_uring_mlock_size_params.3 b/man/io_uring_mlock_size_params.3
deleted file mode 100644
index afb615d3..00000000
--- a/man/io_uring_mlock_size_params.3
+++ /dev/null
@@ -1,48 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_mlock_size_params 3 "January 18, 2025" "liburing-2.4" "liburing Manual"
-.SH NAME
-io_uring_mlock_size_params \- get required memlock size for a ring with params
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "ssize_t io_uring_mlock_size_params(unsigned " entries ", struct io_uring_params *" p ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_mlock_size_params (3)
-function returns the required
-.B RLIMIT_MEMLOCK
-memory size for an io_uring ring with
-.I entries
-entries and the parameters specified in
-.IR p .
-
-On newer kernels (5.12+), io_uring no longer requires any memlock memory
-and this function will return 0. On older kernels (5.11 and prior), this
-returns the required memory so that the caller can ensure that enough
-.B RLIMIT_MEMLOCK
-space is available before setting up a ring.
-
-This function provides more control than
-.BR io_uring_mlock_size (3)
-by allowing the caller to specify full ring parameters including CQ size
-via
-.I p->cq_entries
-when
-.B IORING_SETUP_CQSIZE
-is set in
-.IR p->flags .
-
-.SH RETURN VALUE
-Returns the required memlock size in bytes on success, 0 if no memlock
-is needed, or a negative errno value on error.
-.SH SEE ALSO
-.BR io_uring_mlock_size (3),
-.BR io_uring_memory_size_params (3),
-.BR io_uring_queue_init_params (3),
-.BR getrlimit (2)
diff --git a/man/io_uring_mlock_size_params.3.md b/man/io_uring_mlock_size_params.3.md
new file mode 100644
index 00000000..50964f81
--- /dev/null
+++ b/man/io_uring_mlock_size_params.3.md
@@ -0,0 +1,49 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 18, 2025
+footer: liburing-2.4
+header: liburing Manual
+section: 3
+title: io_uring_mlock_size_params
+---
+
+# NAME
+
+io_uring_mlock_size_params - get required memlock size for a ring with
+params
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ ssize_t io_uring_mlock_size_params(unsigned entries , struct io_uring_params * p );
+```
+
+# DESCRIPTION
+
+The **io_uring_mlock_size_params**(3) function returns the required
+**RLIMIT_MEMLOCK** memory size for an io_uring ring with *entries*
+entries and the parameters specified in *p*.
+
+On newer kernels (5.12+), io_uring no longer requires any memlock memory
+and this function will return 0. On older kernels (5.11 and prior), this
+returns the required memory so that the caller can ensure that enough
+**RLIMIT_MEMLOCK** space is available before setting up a ring.
+
+This function provides more control than **io_uring_mlock_size**(3) by
+allowing the caller to specify full ring parameters including CQ size
+via *p-\>cq_entries* when **IORING_SETUP_CQSIZE** is set in *p-\>flags*.
+
+# RETURN VALUE
+
+Returns the required memlock size in bytes on success, 0 if no memlock
+is needed, or a negative errno value on error.
+
+# SEE ALSO
+
+**io_uring_mlock_size**(3), **io_uring_memory_size_params**(3),
+**io_uring_queue_init_params**(3), **getrlimit**(2)
diff --git a/man/io_uring_multishot.7 b/man/io_uring_multishot.7
deleted file mode 100644
index 44ad2cec..00000000
--- a/man/io_uring_multishot.7
+++ /dev/null
@@ -1,246 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_multishot 7 "January 18, 2025" "Linux" "Linux Programmer's Manual"
-.SH NAME
-io_uring_multishot \- io_uring multishot requests overview
-.SH DESCRIPTION
-Multishot requests are a class of io_uring operations where a single
-submission queue entry (SQE) can generate multiple completion queue
-entries (CQEs). This is in contrast to normal "oneshot" operations where
-each SQE produces exactly one CQE.
-.SS Why use multishot requests?
-Traditional I/O operations require submitting a new request for each
-operation. For high-frequency operations like accepting connections or
-receiving data, this creates overhead:
-.IP \(bu 2
-CPU cycles spent preparing and submitting SQEs
-.IP \(bu
-Memory bandwidth for SQE/CQE processing
-.IP \(bu
-Potential for gaps between completions and new submissions
-.PP
-Multishot requests eliminate this overhead by keeping the operation
-active after each completion. The kernel automatically re-arms the
-operation, generating a new CQE when the next event occurs.
-Additionally, the internal poll mechanism remains persistent for the
-request, avoiding the need to manipulate poll state for each operation.
-
-Multishot operations are most beneficial for:
-.IP \(bu 2
-Network servers accepting many connections
-.IP \(bu
-Applications receiving data on long-lived connections
-.IP \(bu
-Event monitoring with poll
-.IP \(bu
-Any scenario with repeated identical operations
-.SS How multishot works
-When a multishot operation completes, the CQE has the
-.B IORING_CQE_F_MORE
-flag set in
-.IR cqe->flags .
-This indicates that the operation remains active and more completions
-will follow. The operation continues until:
-.IP \(bu 2
-An error occurs (the final CQE will not have
-.B IORING_CQE_F_MORE
-set)
-.IP \(bu
-The operation is explicitly canceled
-.IP \(bu
-A termination condition specific to the operation is met (e.g., buffer
-exhaustion for receives)
-.PP
-The final CQE for a multishot operation will not have
-.B IORING_CQE_F_MORE
-set, indicating the operation has terminated.
-.SS Multishot accept
-.BR io_uring_prep_multishot_accept (3)
-and
-.BR io_uring_prep_multishot_accept_direct (3)
-set up a multishot accept operation. Each incoming connection generates
-a CQE with the new file descriptor in
-.IR cqe->res .
-.PP
-.in +4n
-.EX
-struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
-io_uring_prep_multishot_accept(sqe, listen_fd, NULL, NULL, 0);
-.EE
-.in
-.PP
-The operation continues accepting connections until an error occurs or
-it is canceled. Using the direct variant with
-.B IORING_FILE_INDEX_ALLOC
-allows accepted sockets to be placed directly into the fixed file table.
-.SS Multishot receive
-.BR io_uring_prep_recv_multishot (3)
-sets up a multishot receive operation. Each time data arrives on the
-socket, a CQE is generated. This is typically used with provided buffers
-(see
-.BR io_uring_provided_buffers (7)):
-.PP
-.in +4n
-.EX
-struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
-io_uring_prep_recv_multishot(sqe, sockfd, NULL, 0, 0);
-sqe->buf_group = bgid;
-sqe->flags |= IOSQE_BUFFER_SELECT;
-.EE
-.in
-.PP
-Each completion includes:
-.IP \(bu 2
-.B IORING_CQE_F_MORE
-if more completions will follow
-.IP \(bu
-.B IORING_CQE_F_BUFFER
-indicating a buffer was selected
-.IP \(bu
-The buffer ID in the upper bits of
-.I cqe->flags
-.IP \(bu
-The number of bytes received in
-.I cqe->res
-.PP
-The multishot receive terminates when an error occurs, the connection
-closes, or the buffer ring is exhausted.
-.SS Multishot recvmsg
-.BR io_uring_prep_recvmsg_multishot (3)
-is similar to multishot receive but uses the
-.I msghdr
-structure for scatter/gather I/O and ancillary data. A provided buffer
-is used for each message, with the kernel writing a
-.I struct io_uring_recvmsg_out
-header at the start of the buffer containing the actual message
-parameters.
-.SS Multishot read
-.BR io_uring_prep_read_multishot (3)
-sets up a multishot read operation, typically used with pipes or other
-stream-oriented file descriptors. Like multishot receive, this is used
-with provided buffers:
-.PP
-.in +4n
-.EX
-struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
-io_uring_prep_read_multishot(sqe, fd, 0, 0, bgid);
-.EE
-.in
-.PP
-The operation generates a CQE each time data becomes available to read.
-.SS Multishot poll
-.BR io_uring_prep_poll_multishot (3)
-sets up a multishot poll operation, or it can be done manually by
-setting the
-.B IORING_POLL_ADD_MULTI
-flag:
-.PP
-.in +4n
-.EX
-struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
-io_uring_prep_poll_multishot(sqe, fd, POLLIN);
-/* or equivalently: */
-io_uring_prep_poll_add(sqe, fd, POLLIN);
-sqe->len |= IORING_POLL_ADD_MULTI;
-.EE
-.in
-.PP
-Each time the polled condition becomes true, a CQE is generated with
-the triggered events in
-.IR cqe->res .
-Unlike oneshot poll which is automatically removed after triggering,
-multishot poll remains active.
-
-For level-triggered events, the application should be careful to handle
-the event (e.g., read all available data) before the next poll
-completion, or spurious wakeups may occur.
-.SS Multishot waitid
-.BR io_uring_prep_waitid (3)
-can operate in multishot mode by setting
-.B IORING_ACCEPT_MULTISHOT
-in the flags. This allows waiting for multiple child process state
-changes with a single SQE.
-.SS Handling multishot completions
-Applications must check for
-.B IORING_CQE_F_MORE
-to determine if the operation is still active:
-.PP
-.in +4n
-.EX
-struct io_uring_cqe *cqe;
-
-while (io_uring_peek_cqe(ring, &cqe) == 0) {
- if (cqe->res < 0) {
- /* Error occurred, operation terminated */
- handle_error(cqe->res);
- } else {
- process_completion(cqe);
- }
-
- if (!(cqe->flags & IORING_CQE_F_MORE)) {
- /* Operation terminated, may need to resubmit */
- rearm_if_needed();
- }
-
- io_uring_cqe_seen(ring, cqe);
-}
-.EE
-.in
-.SS Canceling multishot operations
-Multishot operations can be canceled using
-.BR io_uring_prep_cancel (3)
-or related functions. The cancellation request generates its own CQE,
-and the multishot operation generates a final CQE (typically with
-.BR -ECANCELED )
-without
-.B IORING_CQE_F_MORE
-set.
-.PP
-.in +4n
-.EX
-struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
-io_uring_prep_cancel64(sqe, user_data, 0);
-.EE
-.in
-.SS Integration with provided buffers
-Multishot receive and read operations are designed to work with provided
-buffer rings (see
-.BR io_uring_provided_buffers (7)).
-Each completion consumes a buffer from the ring, and the application
-must return buffers to the ring to keep the operation running.
-
-If the buffer ring becomes empty, the multishot operation terminates
-with
-.BR -ENOBUFS .
-Applications should ensure adequate buffers are available and promptly
-return used buffers to the ring.
-.SH NOTES
-.IP \(bu 2
-Always check
-.B IORING_CQE_F_MORE
-to know if a multishot operation is still active.
-.IP \(bu
-Multishot operations may generate many CQEs quickly. Ensure the CQ ring
-is large enough to avoid overflow.
-.IP \(bu
-When using provided buffers with multishot receives, monitor buffer
-availability to prevent premature termination.
-.IP \(bu
-Multishot operations are edge-triggered conceptually \(em they generate
-completions when events occur, not continuously while conditions are
-true.
-.IP \(bu
-Error completions from multishot operations do not have
-.B IORING_CQE_F_MORE
-set, indicating termination.
-.SH SEE ALSO
-.BR io_uring (7),
-.BR io_uring_provided_buffers (7),
-.BR io_uring_prep_multishot_accept (3),
-.BR io_uring_prep_recv_multishot (3),
-.BR io_uring_prep_recvmsg_multishot (3),
-.BR io_uring_prep_read_multishot (3),
-.BR io_uring_prep_poll_add (3),
-.BR io_uring_prep_poll_multishot (3),
-.BR io_uring_prep_cancel (3)
diff --git a/man/io_uring_multishot.7.md b/man/io_uring_multishot.7.md
new file mode 100644
index 00000000..4a889c07
--- /dev/null
+++ b/man/io_uring_multishot.7.md
@@ -0,0 +1,235 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 18, 2025
+footer: Linux
+header: Linux Programmer\'s Manual
+section: 7
+title: io_uring_multishot
+---
+
+# NAME
+
+io_uring_multishot - io_uring multishot requests overview
+
+# DESCRIPTION
+
+Multishot requests are a class of io_uring operations where a single
+submission queue entry (SQE) can generate multiple completion queue
+entries (CQEs). This is in contrast to normal \"oneshot\" operations
+where each SQE produces exactly one CQE.
+
+## Why use multishot requests?
+
+Traditional I/O operations require submitting a new request for each
+operation. For high-frequency operations like accepting connections or
+receiving data, this creates overhead:
+
+- CPU cycles spent preparing and submitting SQEs
+
+- Memory bandwidth for SQE/CQE processing
+
+- Potential for gaps between completions and new submissions
+
+Multishot requests eliminate this overhead by keeping the operation
+active after each completion. The kernel automatically re-arms the
+operation, generating a new CQE when the next event occurs.
+Additionally, the internal poll mechanism remains persistent for the
+request, avoiding the need to manipulate poll state for each operation.
+
+Multishot operations are most beneficial for:
+
+- Network servers accepting many connections
+
+- Applications receiving data on long-lived connections
+
+- Event monitoring with poll
+
+- Any scenario with repeated identical operations
+
+## How multishot works
+
+When a multishot operation completes, the CQE has the
+**IORING_CQE_F_MORE** flag set in *cqe-\>flags*. This indicates that the
+operation remains active and more completions will follow. The operation
+continues until:
+
+- An error occurs (the final CQE will not have **IORING_CQE_F_MORE**
+ set)
+
+- The operation is explicitly canceled
+
+- A termination condition specific to the operation is met (e.g., buffer
+ exhaustion for receives)
+
+The final CQE for a multishot operation will not have
+**IORING_CQE_F_MORE** set, indicating the operation has terminated.
+
+## Multishot accept
+
+**io_uring_prep_multishot_accept**(3) and
+**io_uring_prep_multishot_accept_direct**(3) set up a multishot accept
+operation. Each incoming connection generates a CQE with the new file
+descriptor in *cqe-\>res*.
+
+``` text
+struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
+io_uring_prep_multishot_accept(sqe, listen_fd, NULL, NULL, 0);
+```
+
+The operation continues accepting connections until an error occurs or
+it is canceled. Using the direct variant with
+**IORING_FILE_INDEX_ALLOC** allows accepted sockets to be placed
+directly into the fixed file table.
+
+## Multishot receive
+
+**io_uring_prep_recv_multishot**(3) sets up a multishot receive
+operation. Each time data arrives on the socket, a CQE is generated.
+This is typically used with provided buffers (see
+**io_uring_provided_buffers**(7)):
+
+``` text
+struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
+io_uring_prep_recv_multishot(sqe, sockfd, NULL, 0, 0);
+sqe->buf_group = bgid;
+sqe->flags |= IOSQE_BUFFER_SELECT;
+```
+
+Each completion includes:
+
+- **IORING_CQE_F_MORE** if more completions will follow
+
+- **IORING_CQE_F_BUFFER** indicating a buffer was selected
+
+- The buffer ID in the upper bits of *cqe-\>flags*
+
+- The number of bytes received in *cqe-\>res*
+
+The multishot receive terminates when an error occurs, the connection
+closes, or the buffer ring is exhausted.
+
+## Multishot recvmsg
+
+**io_uring_prep_recvmsg_multishot**(3) is similar to multishot receive
+but uses the *msghdr* structure for scatter/gather I/O and ancillary
+data. A provided buffer is used for each message, with the kernel
+writing a *struct io_uring_recvmsg_out* header at the start of the
+buffer containing the actual message parameters.
+
+## Multishot read
+
+**io_uring_prep_read_multishot**(3) sets up a multishot read operation,
+typically used with pipes or other stream-oriented file descriptors.
+Like multishot receive, this is used with provided buffers:
+
+``` text
+struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
+io_uring_prep_read_multishot(sqe, fd, 0, 0, bgid);
+```
+
+The operation generates a CQE each time data becomes available to read.
+
+## Multishot poll
+
+**io_uring_prep_poll_multishot**(3) sets up a multishot poll operation,
+or it can be done manually by setting the **IORING_POLL_ADD_MULTI**
+flag:
+
+``` text
+struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
+io_uring_prep_poll_multishot(sqe, fd, POLLIN);
+/* or equivalently: */
+io_uring_prep_poll_add(sqe, fd, POLLIN);
+sqe->len |= IORING_POLL_ADD_MULTI;
+```
+
+Each time the polled condition becomes true, a CQE is generated with the
+triggered events in *cqe-\>res*. Unlike oneshot poll which is
+automatically removed after triggering, multishot poll remains active.
+
+For level-triggered events, the application should be careful to handle
+the event (e.g., read all available data) before the next poll
+completion, or spurious wakeups may occur.
+
+## Multishot waitid
+
+**io_uring_prep_waitid**(3) can operate in multishot mode by setting
+**IORING_ACCEPT_MULTISHOT** in the flags. This allows waiting for
+multiple child process state changes with a single SQE.
+
+## Handling multishot completions
+
+Applications must check for **IORING_CQE_F_MORE** to determine if the
+operation is still active:
+
+``` text
+struct io_uring_cqe *cqe;
+
+while (io_uring_peek_cqe(ring, &cqe) == 0) {
+ if (cqe->res < 0) {
+ /* Error occurred, operation terminated */
+ handle_error(cqe->res);
+ } else {
+ process_completion(cqe);
+ }
+
+ if (!(cqe->flags & IORING_CQE_F_MORE)) {
+ /* Operation terminated, may need to resubmit */
+ rearm_if_needed();
+ }
+
+ io_uring_cqe_seen(ring, cqe);
+}
+```
+
+## Canceling multishot operations
+
+Multishot operations can be canceled using **io_uring_prep_cancel**(3)
+or related functions. The cancellation request generates its own CQE,
+and the multishot operation generates a final CQE (typically with
+**-ECANCELED**) without **IORING_CQE_F_MORE** set.
+
+``` text
+struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
+io_uring_prep_cancel64(sqe, user_data, 0);
+```
+
+## Integration with provided buffers
+
+Multishot receive and read operations are designed to work with provided
+buffer rings (see **io_uring_provided_buffers**(7)). Each completion
+consumes a buffer from the ring, and the application must return buffers
+to the ring to keep the operation running.
+
+If the buffer ring becomes empty, the multishot operation terminates
+with **-ENOBUFS**. Applications should ensure adequate buffers are
+available and promptly return used buffers to the ring.
+
+# NOTES
+
+- Always check **IORING_CQE_F_MORE** to know if a multishot operation is
+ still active.
+
+- Multishot operations may generate many CQEs quickly. Ensure the CQ
+ ring is large enough to avoid overflow.
+
+- When using provided buffers with multishot receives, monitor buffer
+ availability to prevent premature termination.
+
+- Multishot operations are edge-triggered conceptually --- they generate
+ completions when events occur, not continuously while conditions are
+ true.
+
+- Error completions from multishot operations do not have
+ **IORING_CQE_F_MORE** set, indicating termination.
+
+# SEE ALSO
+
+**io_uring**(7), **io_uring_provided_buffers**(7),
+**io_uring_prep_multishot_accept**(3),
+**io_uring_prep_recv_multishot**(3),
+**io_uring_prep_recvmsg_multishot**(3),
+**io_uring_prep_read_multishot**(3), **io_uring_prep_poll_add**(3),
+**io_uring_prep_poll_multishot**(3), **io_uring_prep_cancel**(3)
diff --git a/man/io_uring_opcode_supported.3 b/man/io_uring_opcode_supported.3
deleted file mode 100644
index b981ed7d..00000000
--- a/man/io_uring_opcode_supported.3
+++ /dev/null
@@ -1,30 +0,0 @@
-.\" Copyright (C) 2022 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_opcode_supported 3 "January 25, 2022" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_opcode_supported \- is op code supported?
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_opcode_supported(struct io_uring_probe *" probe ","
-.BI " int " opcode ");"
-.fi
-.SH DESCRIPTION
-.PP
-The function
-.BR io_uring_opcode_supported (3)
-allows the caller to determine if the passed in
-.I opcode
-belonging to the
-.I probe
-param is supported. An instance of the io_uring_probe instance can be
-obtained by calling the function
-.BR io_uring_get_probe (3).
-
-.SH RETURN VALUE
-On success it returns 1, otherwise it returns 0.
-.SH SEE ALSO
-.BR io_uring_get_probe (3)
diff --git a/man/io_uring_opcode_supported.3.md b/man/io_uring_opcode_supported.3.md
new file mode 100644
index 00000000..9d9875d6
--- /dev/null
+++ b/man/io_uring_opcode_supported.3.md
@@ -0,0 +1,39 @@
+.\" Copyright (C) 2022 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 25, 2022
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_opcode_supported
+---
+
+# NAME
+
+io_uring_opcode_supported - is op code supported?
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_opcode_supported(struct io_uring_probe * probe ,
+ int opcode );
+```
+
+# DESCRIPTION
+
+The function **io_uring_opcode_supported**(3) allows the caller to
+determine if the passed in *opcode* belonging to the *probe* param is
+supported. An instance of the io_uring_probe instance can be obtained by
+calling the function **io_uring_get_probe**(3).
+
+# RETURN VALUE
+
+On success it returns 1, otherwise it returns 0.
+
+# SEE ALSO
+
+**io_uring_get_probe**(3)
diff --git a/man/io_uring_peek_cqe.3 b/man/io_uring_peek_cqe.3
deleted file mode 100644
index 4416e15a..00000000
--- a/man/io_uring_peek_cqe.3
+++ /dev/null
@@ -1,59 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_peek_cqe 3 "March 12, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_peek_cqe \- check if an io_uring completion event is available
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_peek_cqe(struct io_uring *" ring ","
-.BI " struct io_uring_cqe **" cqe_ptr ");"
-.PP
-.BI "unsigned io_uring_peek_batch_cqe(struct io_uring *" ring ","
-.BI " struct io_uring_cqe **" cqe_ptrs ","
-.BI " unsigned " count ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_peek_cqe (3)
-function returns an IO completion from the queue belonging to the
-.I ring
-param, if one is readily available. On successful return,
-.I cqe_ptr
-param is filled with a valid CQE entry.
-
-This function does not enter the kernel to wait for an event, an event
-is only returned if it's already available in the CQ ring.
-
-The
-.BR io_uring_peek_batch_cqe (3)
-function returns up to
-.I count
-request completions in
-.I cqe_ptrs
-belonging to the
-.I ring
-param, if they are readily available. It will not enter the kernel, unless the
-CQ ring is in an overflow condition. Upon successful return,
-.I cqe_ptrs
-are filled with the number of events indicated by the return value.
-
-.SH RETURN VALUE
-On success
-.BR io_uring_peek_cqe (3)
-returns
-.B 0
-and the cqe_ptr parameter is filled in. On success
-.BR io_uring_peek_batch_cqe (3)
-returns the number of completions filled in. On failure,
-.BR io_uring_peek_cqe (3)
-may return
-.BR -EAGAIN .
-.SH SEE ALSO
-.BR io_uring_submit (3),
-.BR io_uring_wait_cqes (3),
-.BR io_uring_wait_cqe (3)
diff --git a/man/io_uring_peek_cqe.3.md b/man/io_uring_peek_cqe.3.md
new file mode 100644
index 00000000..b6eba7e5
--- /dev/null
+++ b/man/io_uring_peek_cqe.3.md
@@ -0,0 +1,55 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 12, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_peek_cqe
+---
+
+# NAME
+
+io_uring_peek_cqe - check if an io_uring completion event is available
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_peek_cqe(struct io_uring * ring ,
+ struct io_uring_cqe ** cqe_ptr );
+
+ unsigned io_uring_peek_batch_cqe(struct io_uring * ring ,
+ struct io_uring_cqe ** cqe_ptrs ,
+ unsigned count );
+```
+
+# DESCRIPTION
+
+The **io_uring_peek_cqe**(3) function returns an IO completion from the
+queue belonging to the *ring* param, if one is readily available. On
+successful return, *cqe_ptr* param is filled with a valid CQE entry.
+
+This function does not enter the kernel to wait for an event, an event
+is only returned if it\'s already available in the CQ ring.
+
+The **io_uring_peek_batch_cqe**(3) function returns up to *count*
+request completions in *cqe_ptrs* belonging to the *ring* param, if they
+are readily available. It will not enter the kernel, unless the CQ ring
+is in an overflow condition. Upon successful return, *cqe_ptrs* are
+filled with the number of events indicated by the return value.
+
+# RETURN VALUE
+
+On success **io_uring_peek_cqe**(3) returns **0** and the cqe_ptr
+parameter is filled in. On success **io_uring_peek_batch_cqe**(3)
+returns the number of completions filled in. On failure,
+**io_uring_peek_cqe**(3) may return **-EAGAIN**.
+
+# SEE ALSO
+
+**io_uring_submit**(3), **io_uring_wait_cqes**(3),
+**io_uring_wait_cqe**(3)
diff --git a/man/io_uring_prep_accept.3 b/man/io_uring_prep_accept.3
deleted file mode 100644
index 950ab7d4..00000000
--- a/man/io_uring_prep_accept.3
+++ /dev/null
@@ -1,203 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_accept 3 "March 13, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_accept \- prepare an accept request
-.SH SYNOPSIS
-.nf
-.B #include <sys/socket.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_accept(struct io_uring_sqe *" sqe ","
-.BI " int " sockfd ","
-.BI " struct sockaddr *" addr ","
-.BI " socklen_t *" addrlen ","
-.BI " int " flags ");"
-.PP
-.BI "void io_uring_prep_accept_direct(struct io_uring_sqe *" sqe ","
-.BI " int " sockfd ","
-.BI " struct sockaddr *" addr ","
-.BI " socklen_t *" addrlen ","
-.BI " int " flags ","
-.BI " unsigned int " file_index ");"
-.PP
-.BI "void io_uring_prep_multishot_accept(struct io_uring_sqe *" sqe ","
-.BI " int " sockfd ","
-.BI " struct sockaddr *" addr ","
-.BI " socklen_t *" addrlen ","
-.BI " int " flags ");"
-.PP
-.BI "void io_uring_prep_multishot_accept_direct(struct io_uring_sqe *" sqe ","
-.BI " int " sockfd ","
-.BI " struct sockaddr *" addr ","
-.BI " socklen_t *" addrlen ","
-.BI " int " flags ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_accept (3)
-function and its three variants prepare an accept request similar to
-.BR accept4 (2).
-The submission queue entry
-.I sqe
-is setup to use the file descriptor
-.I sockfd
-to start accepting a connection request described by the socket address at
-.I addr
-and of structure length
-.I addrlen
-and using modifier flags in
-.IR flags .
-
-The three variants allow combining the direct file table and multishot features.
-
-Direct descriptors are io_uring private file descriptors. They
-avoid some of the overhead associated with thread shared file tables and
-can be used in any io_uring request that takes a file descriptor.
-The two direct variants here create such direct descriptors.
-Subsequent to their creation, they can be used by setting
-.B IOSQE_FIXED_FILE
-in the SQE
-.I flags
-member, and setting the SQE
-.I fd
-field to the direct descriptor value rather than the regular file
-descriptor. Direct descriptors are managed like registered files.
-
-To use an accept direct variant, the application must first have registered
-a file table of a desired size using
-.BR io_uring_register_files (3)
-or
-.BR io_uring_register_files_sparse (3).
-Once registered,
-.BR io_uring_prep_accept_direct (3)
-allows an entry in that table to be specifically selected through the
-.I file_index
-argument.
-If the specified entry already contains a file, the file will first be removed
-from the table and closed, consistent with the behavior of updating an
-existing file with
-.BR io_uring_register_files_update (3).
-.I file_index
-can also be set to
-.B IORING_FILE_INDEX_ALLOC
-for this variant and
-an unused table index will be dynamically chosen and returned.
-Likewise,
-.B io_uring_prep_multishot_accept_direct
-will have an unused table index dynamically chosen and returned for each connection accepted.
-If both forms of direct selection will be employed, specific and dynamic, see
-.BR io_uring_register_file_alloc_range (3)
-for setting up the table so dynamically chosen entries are made against
-a different range than that targeted by specific requests.
-
-Note that old kernels don't check the SQE
-.I file_index
-field meaning
-applications cannot rely on a
-.B -EINVAL
-CQE
-.I res
-being returned when the kernel is too old because older kernels
-may not recognize they are being asked to use a direct table slot.
-
-When a direct descriptor accept request asks for a table slot to be
-dynamically chosen but there are no free entries,
-.B -ENFILE
-is returned as the CQE
-.IR res .
-
-The multishot variants allow an application to issue
-a single accept request, which will repeatedly trigger a CQE when a connection
-request comes in. Like other multishot type requests, the application should
-look at the CQE
-.I flags
-and see if
-.B IORING_CQE_F_MORE
-is set on completion as an indication of whether or not the accept request
-will generate further CQEs. Note that for the multishot variants, setting
-.B addr
-and
-.B addrlen
-may not make a lot of sense, as the same value would be used for every
-accepted connection. This means that the data written to
-.B addr
-may be overwritten by a new connection before the application has had time
-to process a past connection. If the application knows that a new connection
-cannot come in before a previous one has been processed, it may be used as
-expected. The multishot variants are available since 5.19.
-
-See the man page
-.BR accept4 (2)
-for details of the accept function itself.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation.
-
-.BR io_uring_prep_accept (3)
-generates the installed file descriptor as its result.
-
-.BR io_uring_prep_accept_direct (3)
-and
-.I file_index
-set to a specific direct descriptor
-generates
-.B 0
-on success.
-The caller must remember which direct descriptor was picked for this request.
-
-.BR io_uring_prep_accept_direct (3)
-and
-.I file_index
-set to
-.B IORING_FILE_INDEX_ALLOC
-generates the dynamically chosen direct descriptor.
-
-.BR io_uring_prep_multishot_accept (3)
-generates the installed file descriptor in each result.
-
-.BR io_uring_prep_multishot_accept_direct (3),
-generates the dynamically chosen direct descriptor in each result.
-
-Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it generates the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH NOTES
-As with any request that passes in data in a struct, that data must remain
-valid until the request has been successfully submitted. It need not remain
-valid until completion. Once a request has been submitted, the in-kernel
-state is stable. Very early kernels (5.4 and earlier) required state to be
-stable until the completion occurred. Applications can test for this
-behavior by inspecting the
-.B IORING_FEAT_SUBMIT_STABLE
-flag passed back from
-.BR io_uring_queue_init_params (3).
-.P
-Note that the direct versions of accept do not accept
-.B SOCK_CLOEXEC ,
-and setting that flag will result in an
-.B -EINVAL
-error in the CQE.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_register_files (3),
-.BR io_uring_register_files_sparse (3),
-.BR io_uring_register_file_alloc_range (3),
-.BR io_uring_register (2),
-.BR accept4 (2)
diff --git a/man/io_uring_prep_accept.3.md b/man/io_uring_prep_accept.3.md
new file mode 100644
index 00000000..0909311c
--- /dev/null
+++ b/man/io_uring_prep_accept.3.md
@@ -0,0 +1,161 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 13, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_accept
+---
+
+# NAME
+
+io_uring_prep_accept - prepare an accept request
+
+# SYNOPSIS
+
+``` text
+#include <sys/socket.h>
+#include <liburing.h>
+
+ void io_uring_prep_accept(struct io_uring_sqe * sqe ,
+ int sockfd ,
+ struct sockaddr * addr ,
+ socklen_t * addrlen ,
+ int flags );
+
+ void io_uring_prep_accept_direct(struct io_uring_sqe * sqe ,
+ int sockfd ,
+ struct sockaddr * addr ,
+ socklen_t * addrlen ,
+ int flags ,
+ unsigned int file_index );
+
+ void io_uring_prep_multishot_accept(struct io_uring_sqe * sqe ,
+ int sockfd ,
+ struct sockaddr * addr ,
+ socklen_t * addrlen ,
+ int flags );
+
+ void io_uring_prep_multishot_accept_direct(struct io_uring_sqe * sqe ,
+ int sockfd ,
+ struct sockaddr * addr ,
+ socklen_t * addrlen ,
+ int flags );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_accept**(3) function and its three variants prepare
+an accept request similar to **accept4**(2). The submission queue entry
+*sqe* is setup to use the file descriptor *sockfd* to start accepting a
+connection request described by the socket address at *addr* and of
+structure length *addrlen* and using modifier flags in *flags*.
+
+The three variants allow combining the direct file table and multishot
+features.
+
+Direct descriptors are io_uring private file descriptors. They avoid
+some of the overhead associated with thread shared file tables and can
+be used in any io_uring request that takes a file descriptor. The two
+direct variants here create such direct descriptors. Subsequent to their
+creation, they can be used by setting **IOSQE_FIXED_FILE** in the SQE
+*flags* member, and setting the SQE *fd* field to the direct descriptor
+value rather than the regular file descriptor. Direct descriptors are
+managed like registered files.
+
+To use an accept direct variant, the application must first have
+registered a file table of a desired size using
+**io_uring_register_files**(3) or **io_uring_register_files_sparse**(3).
+Once registered, **io_uring_prep_accept_direct**(3) allows an entry in
+that table to be specifically selected through the *file_index*
+argument. If the specified entry already contains a file, the file will
+first be removed from the table and closed, consistent with the behavior
+of updating an existing file with **io_uring_register_files_update**(3).
+*file_index* can also be set to **IORING_FILE_INDEX_ALLOC** for this
+variant and an unused table index will be dynamically chosen and
+returned. Likewise, **io_uring_prep_multishot_accept_direct** will have
+an unused table index dynamically chosen and returned for each
+connection accepted. If both forms of direct selection will be employed,
+specific and dynamic, see **io_uring_register_file_alloc_range**(3) for
+setting up the table so dynamically chosen entries are made against a
+different range than that targeted by specific requests.
+
+Note that old kernels don\'t check the SQE *file_index* field meaning
+applications cannot rely on a **-EINVAL** CQE *res* being returned when
+the kernel is too old because older kernels may not recognize they are
+being asked to use a direct table slot.
+
+When a direct descriptor accept request asks for a table slot to be
+dynamically chosen but there are no free entries, **-ENFILE** is
+returned as the CQE *res*.
+
+The multishot variants allow an application to issue a single accept
+request, which will repeatedly trigger a CQE when a connection request
+comes in. Like other multishot type requests, the application should
+look at the CQE *flags* and see if **IORING_CQE_F_MORE** is set on
+completion as an indication of whether or not the accept request will
+generate further CQEs. Note that for the multishot variants, setting
+**addr** and **addrlen** may not make a lot of sense, as the same value
+would be used for every accepted connection. This means that the data
+written to **addr** may be overwritten by a new connection before the
+application has had time to process a past connection. If the
+application knows that a new connection cannot come in before a previous
+one has been processed, it may be used as expected. The multishot
+variants are available since 5.19.
+
+See the man page **accept4**(2) for details of the accept function
+itself.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation.
+
+**io_uring_prep_accept**(3) generates the installed file descriptor as
+its result.
+
+**io_uring_prep_accept_direct**(3) and *file_index* set to a specific
+direct descriptor generates **0** on success. The caller must remember
+which direct descriptor was picked for this request.
+
+**io_uring_prep_accept_direct**(3) and *file_index* set to
+**IORING_FILE_INDEX_ALLOC** generates the dynamically chosen direct
+descriptor.
+
+**io_uring_prep_multishot_accept**(3) generates the installed file
+descriptor in each result.
+
+**io_uring_prep_multishot_accept_direct**(3), generates the dynamically
+chosen direct descriptor in each result.
+
+Note that where synchronous system calls will return **-1** on failure
+and set *errno* to the actual error value, io_uring never uses *errno*.
+Instead it generates the negated *errno* directly in the CQE *res*
+field.
+
+# NOTES
+
+As with any request that passes in data in a struct, that data must
+remain valid until the request has been successfully submitted. It need
+not remain valid until completion. Once a request has been submitted,
+the in-kernel state is stable. Very early kernels (5.4 and earlier)
+required state to be stable until the completion occurred. Applications
+can test for this behavior by inspecting the
+**IORING_FEAT_SUBMIT_STABLE** flag passed back from
+**io_uring_queue_init_params**(3).
+
+Note that the direct versions of accept do not accept **SOCK_CLOEXEC ,**
+and setting that flag will result in an **-EINVAL** error in the CQE.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_register_files**(3), **io_uring_register_files_sparse**(3),
+**io_uring_register_file_alloc_range**(3), **io_uring_register**(2),
+**accept4**(2)
diff --git a/man/io_uring_prep_bind.3 b/man/io_uring_prep_bind.3
deleted file mode 100644
index b62905c4..00000000
--- a/man/io_uring_prep_bind.3
+++ /dev/null
@@ -1,54 +0,0 @@
-.\" Copyright (C) 2024 SUSE LLC
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_bind 3 "Jun 3, 2024" "liburing-2.7" "liburing Manual"
-.SH NAME
-io_uring_prep_bind \- prepare a bind request
-.SH SYNOPSIS
-.nf
-.B #include <sys/socket.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_bind(struct io_uring_sqe *" sqe ","
-.BI " int " sockfd ","
-.BI " const struct sockaddr *" addr ","
-.BI " socklen_t " addrlen ");"
-.fi
-.SH DESCRIPTION
-The
-.BR io_uring_prep_bind (3)
-function prepares a bind request. The submission queue entry
-.I sqe
-is setup to assign the network address at
-.IR addr ,
-of length
-.IR addrlen ,
-to the socket descriptor
-.IR sockfd.
-
-This function prepares an async
-.BR bind (2)
-request. See that man page for details.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR bind (2)
diff --git a/man/io_uring_prep_bind.3.md b/man/io_uring_prep_bind.3.md
new file mode 100644
index 00000000..ea0f4d4d
--- /dev/null
+++ b/man/io_uring_prep_bind.3.md
@@ -0,0 +1,52 @@
+.\" Copyright (C) 2024 SUSE LLC
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: Jun 3, 2024
+footer: liburing-2.7
+header: liburing Manual
+section: 3
+title: io_uring_prep_bind
+---
+
+# NAME
+
+io_uring_prep_bind - prepare a bind request
+
+# SYNOPSIS
+
+``` text
+#include <sys/socket.h>
+#include <liburing.h>
+
+ void io_uring_prep_bind(struct io_uring_sqe * sqe ,
+ int sockfd ,
+ const struct sockaddr * addr ,
+ socklen_t addrlen );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_bind**(3) function prepares a bind request. The
+submission queue entry *sqe* is setup to assign the network address at
+*addr*, of length *addrlen*, to the socket descriptor *sockfd.*
+
+This function prepares an async **bind**(2) request. See that man page
+for details.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3), **bind**(2)
diff --git a/man/io_uring_prep_cancel.3 b/man/io_uring_prep_cancel.3
deleted file mode 100644
index fa134d7a..00000000
--- a/man/io_uring_prep_cancel.3
+++ /dev/null
@@ -1,136 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_cancel 3 "March 12, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_cancel \- prepare a cancelation request
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_cancel64(struct io_uring_sqe *" sqe ","
-.BI " __u64 " user_data ","
-.BI " int " flags ");"
-.PP
-.BI "void io_uring_prep_cancel(struct io_uring_sqe *" sqe ","
-.BI " const void *" user_data ","
-.BI " int " flags ");"
-.PP
-.BI "void io_uring_prep_cancel_fd(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " unsigned int " flags ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_cancel (3)
-function prepares a cancelation request. The submission queue entry
-.I sqe
-is prepared to cancel an existing request identified by
-.IR user_data .
-For the
-.I flags
-argument, see below.
-
-.BR io_uring_prep_cancel64 (3)
-is identical to
-.BR io_uring_prep_cancel (3) ,
-except it takes a 64-bit integer rather than a pointer type.
-
-The cancelation request will attempt to find the previously issued request
-identified by
-.I user_data
-and cancel it. The identifier is what the previously issued request has in
-their
-.I user_data
-field in the SQE.
-
-The
-.BR io_uring_prep_cancel_fd (3)
-function prepares a cancelation request. The submission queue entry
-.I sqe
-is prepared to cancel an existing request that used the file descriptor
-.IR fd .
-For the
-.I flags
-argument, see below.
-
-The cancelation request will attempt to find the previously issued request
-that used
-.I fd
-as the file descriptor and cancel it.
-
-By default, the first request matching the criteria given will be canceled.
-This can be modified with any of the following flags passed in:
-.TP
-.B IORING_ASYNC_CANCEL_ALL
-Cancel all requests that match the given criteria, rather than just canceling
-the first one found. Available since 5.19.
-.TP
-.B IORING_ASYNC_CANCEL_FD
-Match based on the file descriptor used in the original request rather than
-the user_data. This is what
-.BR io_uring_prep_cancel_fd (3)
-sets up. Available since 5.19.
-.TP
-.B IORING_ASYNC_CANCEL_FD_FIXED
-Set in conjunction with
-.B IORING_ASYNC_CANCEL_FD ,
-indicating that the file descriptor given is a direct descriptor rather than
-a normal file descriptor. Available since 6.0.
-.TP
-.B IORING_ASYNC_CANCEL_ANY
-Match any request in the ring, regardless of user_data or file descriptor.
-Can be used to cancel any pending request in the ring. Available since 5.19.
-.TP
-.B IORING_ASYNC_CANCEL_USERDATA
-Match request based on the user data field set in the original request. This
-is the default lookup key, if no other key matching has been specified.
-Available since 6.6.
-.TP
-.B IORING_ASYNC_CANCEL_OP
-Use the original request opcode as the matching key. The opcopde requested
-must be set in the sqe
-.I len
-field after using one of the generic cancel preparation helpers. Available
-since 6.6.
-.P
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-These are the errors that are reported in the CQE
-.I res
-field. If no flags are used to cancel multiple requests,
-.B 0
-is returned on success. If flags are used to match multiple requests, then
-a positive value is returned indicating how many requests were found and
-canceled.
-.TP
-.B -ENOENT
-The request identified by
-.I user_data
-could not be located. This could be because it completed before the cancelation
-request was issued, or if an invalid identifier is used.
-.TP
-.B -EINVAL
-One of the fields set in the SQE was invalid.
-.TP
-.B -EALREADY
-The execution state of the request has progressed far enough that cancelation
-is no longer possible. This should normally mean that it will complete shortly,
-either successfully, or interrupted due to the cancelation.
-.SH NOTES
-Although the cancelation request uses async request syntax, the kernel side of
-the cancelation is always run synchronously. It is guaranteed that a CQE is
-always generated by the time the cancel request has been submitted. If the
-cancelation is successful, the completion for the request targeted for
-cancelation will have been posted by the time submission returns. For
-.B -EALREADY
-it may take a bit of time to do so. For this case, the caller must wait for the
-canceled request to post its completion event.
-.SH SEE ALSO
-.BR io_uring_prep_poll_remove (3),
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3)
diff --git a/man/io_uring_prep_cancel.3.md b/man/io_uring_prep_cancel.3.md
new file mode 100644
index 00000000..102d4e0e
--- /dev/null
+++ b/man/io_uring_prep_cancel.3.md
@@ -0,0 +1,138 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 12, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_cancel
+---
+
+# NAME
+
+io_uring_prep_cancel - prepare a cancelation request
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_cancel64(struct io_uring_sqe * sqe ,
+ __u64 user_data ,
+ int flags );
+
+ void io_uring_prep_cancel(struct io_uring_sqe * sqe ,
+ const void * user_data ,
+ int flags );
+
+ void io_uring_prep_cancel_fd(struct io_uring_sqe * sqe ,
+ int fd ,
+ unsigned int flags );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_cancel**(3) function prepares a cancelation request.
+The submission queue entry *sqe* is prepared to cancel an existing
+request identified by *user_data*. For the *flags* argument, see below.
+
+**io_uring_prep_cancel64**(3) is identical to
+**io_uring_prep_cancel**(3)**,** except it takes a 64-bit integer rather
+than a pointer type.
+
+The cancelation request will attempt to find the previously issued
+request identified by *user_data* and cancel it. The identifier is what
+the previously issued request has in their *user_data* field in the SQE.
+
+The **io_uring_prep_cancel_fd**(3) function prepares a cancelation
+request. The submission queue entry *sqe* is prepared to cancel an
+existing request that used the file descriptor *fd*. For the *flags*
+argument, see below.
+
+The cancelation request will attempt to find the previously issued
+request that used *fd* as the file descriptor and cancel it.
+
+By default, the first request matching the criteria given will be
+canceled. This can be modified with any of the following flags passed
+in:
+
+**IORING_ASYNC_CANCEL_ALL**
+
+: Cancel all requests that match the given criteria, rather than just
+ canceling the first one found. Available since 5.19.
+
+**IORING_ASYNC_CANCEL_FD**
+
+: Match based on the file descriptor used in the original request rather
+ than the user_data. This is what **io_uring_prep_cancel_fd**(3) sets
+ up. Available since 5.19.
+
+**IORING_ASYNC_CANCEL_FD_FIXED**
+
+: Set in conjunction with **IORING_ASYNC_CANCEL_FD ,** indicating that
+ the file descriptor given is a direct descriptor rather than a normal
+ file descriptor. Available since 6.0.
+
+**IORING_ASYNC_CANCEL_ANY**
+
+: Match any request in the ring, regardless of user_data or file
+ descriptor. Can be used to cancel any pending request in the ring.
+ Available since 5.19.
+
+**IORING_ASYNC_CANCEL_USERDATA**
+
+: Match request based on the user data field set in the original
+ request. This is the default lookup key, if no other key matching has
+ been specified. Available since 6.6.
+
+**IORING_ASYNC_CANCEL_OP**
+
+: Use the original request opcode as the matching key. The opcopde
+ requested must be set in the sqe *len* field after using one of the
+ generic cancel preparation helpers. Available since 6.6.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+These are the errors that are reported in the CQE *res* field. If no
+flags are used to cancel multiple requests, **0** is returned on
+success. If flags are used to match multiple requests, then a positive
+value is returned indicating how many requests were found and canceled.
+
+**-ENOENT**
+
+: The request identified by *user_data* could not be located. This could
+ be because it completed before the cancelation request was issued, or
+ if an invalid identifier is used.
+
+**-EINVAL**
+
+: One of the fields set in the SQE was invalid.
+
+**-EALREADY**
+
+: The execution state of the request has progressed far enough that
+ cancelation is no longer possible. This should normally mean that it
+ will complete shortly, either successfully, or interrupted due to the
+ cancelation.
+
+# NOTES
+
+Although the cancelation request uses async request syntax, the kernel
+side of the cancelation is always run synchronously. It is guaranteed
+that a CQE is always generated by the time the cancel request has been
+submitted. If the cancelation is successful, the completion for the
+request targeted for cancelation will have been posted by the time
+submission returns. For **-EALREADY** it may take a bit of time to do
+so. For this case, the caller must wait for the canceled request to post
+its completion event.
+
+# SEE ALSO
+
+**io_uring_prep_poll_remove**(3), **io_uring_get_sqe**(3),
+**io_uring_submit**(3)
diff --git a/man/io_uring_prep_close.3 b/man/io_uring_prep_close.3
deleted file mode 100644
index d7eac2e8..00000000
--- a/man/io_uring_prep_close.3
+++ /dev/null
@@ -1,67 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_close 3 "March 13, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_close \- prepare a file descriptor close request
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_close(struct io_uring_sqe *" sqe ","
-.BI " int " fd ");"
-.PP
-.BI "void io_uring_prep_close_direct(struct io_uring_sqe *" sqe ","
-.BI " unsigned " file_index ");"
-.PP
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_close (3)
-function prepares a close request. The submission queue entry
-.I sqe
-is setup to close the file descriptor indicated by
-.IR fd .
-
-For a direct descriptor close request, the offset is specified by the
-.I file_index
-argument instead of the
-.IR fd .
-This is identical to unregistering the direct descriptor, and is provided as
-a convenience. Note that even though it's closing a direct descriptor, the
-application must not set
-.B IOSQE_FIXED_FILE
-on the SQE. Otherwise the request will complete with
-.B -EBADF
-as the result.
-
-These functions prepare an async
-.BR close (2)
-request. See that man page for details.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. For closing of a direct descriptor, the only
-failure cases are the kernel running completely out of memory, or if the
-application has specified an invalid direct descriptor. Note that where
-synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR close (2)
diff --git a/man/io_uring_prep_close.3.md b/man/io_uring_prep_close.3.md
new file mode 100644
index 00000000..5b89346d
--- /dev/null
+++ b/man/io_uring_prep_close.3.md
@@ -0,0 +1,62 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 13, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_close
+---
+
+# NAME
+
+io_uring_prep_close - prepare a file descriptor close request
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_close(struct io_uring_sqe * sqe ,
+ int fd );
+
+ void io_uring_prep_close_direct(struct io_uring_sqe * sqe ,
+ unsigned file_index );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_close**(3) function prepares a close request. The
+submission queue entry *sqe* is setup to close the file descriptor
+indicated by *fd*.
+
+For a direct descriptor close request, the offset is specified by the
+*file_index* argument instead of the *fd*. This is identical to
+unregistering the direct descriptor, and is provided as a convenience.
+Note that even though it\'s closing a direct descriptor, the application
+must not set **IOSQE_FIXED_FILE** on the SQE. Otherwise the request will
+complete with **-EBADF** as the result.
+
+These functions prepare an async **close**(2) request. See that man page
+for details.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. For closing of a direct
+descriptor, the only failure cases are the kernel running completely out
+of memory, or if the application has specified an invalid direct
+descriptor. Note that where synchronous system calls will return **-1**
+on failure and set *errno* to the actual error value, io_uring never
+uses *errno*. Instead it returns the negated *errno* directly in the CQE
+*res* field.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3), **close**(2)
diff --git a/man/io_uring_prep_cmd_discard.3 b/man/io_uring_prep_cmd_discard.3
deleted file mode 100644
index 97786726..00000000
--- a/man/io_uring_prep_cmd_discard.3
+++ /dev/null
@@ -1,64 +0,0 @@
-.\" Copyright (C) 2024 Pavel Begunkov <asml.silence@gmail.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_cmd_discard 3 "Oct 13, 2024" "liburing-2.8" "liburing Manual"
-.SH NAME
-io_uring_prep_cmd_discard \- prepare a discard command
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_cmd_discard(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " uint64_t " offset ","
-.BI " uint64_t " nbytes ");"
-.fi
-.SH DESCRIPTION
-The
-.BR io_uring_prep_cmd_discard (3)
-function prepares a discard command request. The submission queue entry
-.I sqe
-is setup to use the file descriptor
-.IR fd
-to start discarding
-.I nbytes
-at the specified
-.IR offset .
-
-The command is an asynchronous equivalent of
-.B BLOCK_URING_CMD_DISCARD
-ioctl with a few differences. It allows multiple parallel discards, and it does
-not exclude concurrent writes and reads. As a result, it may lead to races for
-the data on the disk, if the application has IO inflight for the same ranges
-that the discard operates on. It's the user's responsibility to account for that.
-Furthermore, only best efforts are done to invalidate page caches. The user has
-to make sure that no other inflight requests are modifying or reading the
-range(s). If that is the case, it might result in stale page cache and data
-inconsistencies.
-
-Available since 6.12.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. On success, this field will be
-set to
-.B 0 .
-On error, a negative error value is returned. Note that where synchronous
-system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
diff --git a/man/io_uring_prep_cmd_discard.3.md b/man/io_uring_prep_cmd_discard.3.md
new file mode 100644
index 00000000..aa1d951d
--- /dev/null
+++ b/man/io_uring_prep_cmd_discard.3.md
@@ -0,0 +1,62 @@
+.\" Copyright (C) 2024 Pavel Begunkov <asml.silence@gmail.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: Oct 13, 2024
+footer: liburing-2.8
+header: liburing Manual
+section: 3
+title: io_uring_prep_cmd_discard
+---
+
+# NAME
+
+io_uring_prep_cmd_discard - prepare a discard command
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_cmd_discard(struct io_uring_sqe * sqe ,
+ int fd ,
+ uint64_t offset ,
+ uint64_t nbytes );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_cmd_discard**(3) function prepares a discard command
+request. The submission queue entry *sqe* is setup to use the file
+descriptor *fd* to start discarding *nbytes* at the specified *offset*.
+
+The command is an asynchronous equivalent of **BLOCK_URING_CMD_DISCARD**
+ioctl with a few differences. It allows multiple parallel discards, and
+it does not exclude concurrent writes and reads. As a result, it may
+lead to races for the data on the disk, if the application has IO
+inflight for the same ranges that the discard operates on. It\'s the
+user\'s responsibility to account for that. Furthermore, only best
+efforts are done to invalidate page caches. The user has to make sure
+that no other inflight requests are modifying or reading the range(s).
+If that is the case, it might result in stale page cache and data
+inconsistencies.
+
+Available since 6.12.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. On
+success, this field will be set to **0 .** On error, a negative error
+value is returned. Note that where synchronous system calls will return
+**-1** on failure and set *errno* to the actual error value, io_uring
+never uses *errno*. Instead it returns the negated *errno* directly in
+the CQE *res* field.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
diff --git a/man/io_uring_prep_cmd_getsockname.3 b/man/io_uring_prep_cmd_getsockname.3
deleted file mode 100644
index 221b49dc..00000000
--- a/man/io_uring_prep_cmd_getsockname.3
+++ /dev/null
@@ -1,79 +0,0 @@
-.\" Copyright (C) 2025 SUSE LLC.
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_cmd_getsockname 3 "December 3, 2025" "liburing-2.13" "liburing Manual"
-.SH NAME
-io_uring_prep_cmd_getsockname \- prepare a getsockname or getpeername request
-.SH SYNOPSIS
-.nf
-.B #include <sys/socket.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_cmd_getsockname(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " struct sockaddr *" sockaddr ","
-.BI " socklen_t *" sockaddr_len ","
-.BI " int " peer ");"
-.fi
-.SH DESCRIPTION
-The
-.BR io_uring_prep_cmd_getsockname (3)
-function prepares a getsockname/getpeername request.
-The submission queue entry
-.I sqe
-is setup to fetch the locally bound address or peer address of the socket
-file descriptor pointed by
-.IR sockfd .
-The parameter
-.IR sockaddr
-points to a region of size
-.IR sockaddr_len
-where the output is written.
-.IR sockaddr_len
-is modified by the kernel on return to indicate how many bytes were written.
-The output address is the locally bound address if
-.IR peer
-is set to
-.B 0
-or the peer address if
-.IR peer
-is set to
-.BR 1 .
-
-This function prepares an async
-.BR getsockname (2)
-or
-.BR getpeername (2)
-request. See those man pages for details.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.BR
-Differently from the equivalent system calls, if the user attempts to
-use this operation on a non-socket file descriptor, the CQE error result
-is
-.IR ENOTSUP
-instead of
-.IR ENOSOCK.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR getsockname (2),
-.BR getpeername (2)
diff --git a/man/io_uring_prep_cmd_getsockname.3.md b/man/io_uring_prep_cmd_getsockname.3.md
new file mode 100644
index 00000000..1bf5ed14
--- /dev/null
+++ b/man/io_uring_prep_cmd_getsockname.3.md
@@ -0,0 +1,64 @@
+.\" Copyright (C) 2025 SUSE LLC.
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: December 3, 2025
+footer: liburing-2.13
+header: liburing Manual
+section: 3
+title: io_uring_prep_cmd_getsockname
+---
+
+# NAME
+
+io_uring_prep_cmd_getsockname - prepare a getsockname or getpeername
+request
+
+# SYNOPSIS
+
+``` text
+#include <sys/socket.h>
+#include <liburing.h>
+
+ void io_uring_prep_cmd_getsockname(struct io_uring_sqe * sqe ,
+ int fd ,
+ struct sockaddr * sockaddr ,
+ socklen_t * sockaddr_len ,
+ int peer );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_cmd_getsockname**(3) function prepares a
+getsockname/getpeername request. The submission queue entry *sqe* is
+setup to fetch the locally bound address or peer address of the socket
+file descriptor pointed by *sockfd*. The parameter *sockaddr* points to
+a region of size *sockaddr_len* where the output is written.
+*sockaddr_len* is modified by the kernel on return to indicate how many
+bytes were written. The output address is the locally bound address if
+*peer* is set to **0** or the peer address if *peer* is set to **1**.
+
+This function prepares an async **getsockname**(2) or **getpeername**(2)
+request. See those man pages for details.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field. Differently
+from the equivalent system calls, if the user attempts to use this
+operation on a non-socket file descriptor, the CQE error result is
+*ENOTSUP* instead of *ENOSOCK.*
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3), **getsockname**(2),
+**getpeername**(2)
diff --git a/man/io_uring_prep_cmd_sock.3 b/man/io_uring_prep_cmd_sock.3
deleted file mode 100644
index 2cc77bce..00000000
--- a/man/io_uring_prep_cmd_sock.3
+++ /dev/null
@@ -1,219 +0,0 @@
-.\" Copyright (C) 2023 Breno Leitao <leitao@debian.org>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_cmd_sock 3 "July 27, 2023" "liburing-2.5" "liburing Manual"
-.SH NAME
-io_uring_prep_cmd_sock \- prepare a command request for a socket
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_cmd_sock(struct io_uring_sqe *" sqe ","
-.BI " int " cmd_op ","
-.BI " int " fd ","
-.BI " int " level ","
-.BI " int " optname ","
-.BI " void " *optval ","
-.BI " int " optlen ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_cmd_sock (3)
-function prepares an cmd request for a socket. The submission queue entry
-.I sqe
-is setup to use the socket file descriptor pointed to by
-.I fd
-to start an command operation defined by
-.I cmd_op.
-
-This is a generic function, and each command has their own individual
-.I level, optname, optval
-values. The optlen defines the size pointed by
-.I optval.
-
-.SH Available commands
-
-.TP
-.B SOCKET_URING_OP_SIOCINQ
-Returns the amount of queued unread data in the receive buffer.
-The socket must not be in LISTEN state, otherwise an error
-.B -EINVAL
-is returned in the CQE
-.I res
-field.
-The following arguments are not used for this command
-.I level, optname, optval
-and
-.I optlen.
-
-Negative return value means an error.
-
-For more information about this command, please check
-.BR unix(7).
-
-Available since 6.7.
-
-.TP
-.B SOCKET_URING_OP_SIOCOUTQ
-Returns the amount of unsent data in the socket send queue.
-The socket must not be in LISTEN state, otherwise an error
-.B -EINVAL
-is returned in the CQE
-.I res.
-field.
-The following arguments are not used for this command
-.I level, optname, optval
-and
-.I optlen.
-
-Negative return value means an error.
-
-For more information about this command, please check
-.BR unix(7).
-
-.TP
-.B SOCKET_URING_OP_GETSOCKOPT
-Command to get options for the socket referred to by the socket file descriptor
-.I fd.
-The arguments are similar to the
-.BR getsockopt(2)
-system call.
-
-The
-.BR SOCKET_URING_OP_GETSOCKOPT
-command is limited to
-.BR SOL_SOCKET
-.I level.
-
-Differently from the
-.BR getsockopt(2)
-system call, the updated
-.I optlen
-value is returned in the CQE
-.I res
-field, on success. On failure, the CQE
-.I res
-contains a negative error number.
-
-.TP
-.B SOCKET_URING_OP_SETSOCKOPT
-Command to set options for the socket referred to by the socket file descriptor
-.I fd.
-The arguments are similar to the
-.BR setsockopt(2)
-system call.
-
-Available since 6.7.
-
-.TP
-.B SOCKET_URING_OP_TX_TIMESTAMP
-Retrieve transmit timestamps from the socket's error queue. This provides an
-alternative to the traditional
-.BR recvmsg(2)
-error queue interface for obtaining TX timestamps.
-
-The command operates in a polled multishot mode: io_uring will poll the socket
-and keep posting timestamps as CQEs until the request is cancelled or fails.
-The ring must be created with
-.B IORING_SETUP_CQE32
-or
-.B IORING_SETUP_CQE_MIXED
-to provide space for the timestamp data.
-
-The socket must first be configured for timestamping via
-.BR setsockopt(2)
-with
-.B SO_TIMESTAMPING
-at the
-.B SOL_SOCKET
-level, specifying the desired timestamp types (e.g.
-.BR SOF_TIMESTAMPING_TX_SOFTWARE ,
-.BR SOF_TIMESTAMPING_TX_SCHED ,
-.BR SOF_TIMESTAMPING_TX_ACK )
-along with
-.B SOF_TIMESTAMPING_SOFTWARE
-and
-.BR SOF_TIMESTAMPING_OPT_TSONLY .
-
-The following arguments are not used for this command:
-.I level, optname, optval
-and
-.I optlen.
-
-Each timestamp is delivered as a CQE with
-.B IORING_CQE_F_MORE
-set in
-.I cqe->flags
-to indicate more timestamps may follow. The
-.I cqe->res
-field contains the timestamp key
-.RI ( tskey ),
-which corresponds to the byte offset (for TCP) or packet count (for UDP).
-The timestamp type
-.RI ( SCM_TSTAMP_SCHED ,
-.I SCM_TSTAMP_SND
-or
-.IR SCM_TSTAMP_ACK )
-is stored in the upper bits of
-.I cqe->flags
-at offset
-.BR IORING_TIMESTAMP_TYPE_SHIFT .
-If the timestamp is a hardware timestamp, the
-.B IORING_CQE_F_TSTAMP_HW
-flag is set.
-
-The actual timestamp value is stored in the extended CQE area as a
-.B struct io_timespec
-(with 64-bit
-.I tv_sec
-and
-.I tv_nsec
-fields), accessible at
-.IR "(cqe + 1)" .
-
-The final CQE will not have
-.B IORING_CQE_F_MORE
-set, and its
-.I cqe->res
-will contain 0 on success or a negative error code on failure.
-
-Available since 6.17.
-
-.TP
-.B SOCKET_URING_OP_GETSOCKNAME
-Returns the current address to which the socket is bound. The result is
-stored in the buffer pointed to by
-.I optval,
-which should be a pointer to a
-.I struct sockaddr
-(or appropriate variant). The
-.I optlen
-argument specifies the size of the buffer. On success, the CQE
-.I res
-field contains the actual size of the socket address. If the buffer is too
-small, the result is truncated.
-
-This is the io_uring equivalent of
-.BR getsockname (2).
-
-Available since 6.19.
-
-.SH NOTES
-The memory block pointed by
-.I optval
-needs to be valid/live until the CQE returns.
-
-.SH RETURN VALUE
-Dependent on the command.
-
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_register (2),
-.BR unix (7)
diff --git a/man/io_uring_prep_cmd_sock.3.md b/man/io_uring_prep_cmd_sock.3.md
new file mode 100644
index 00000000..0fc7c764
--- /dev/null
+++ b/man/io_uring_prep_cmd_sock.3.md
@@ -0,0 +1,159 @@
+.\" Copyright (C) 2023 Breno Leitao <leitao@debian.org>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: July 27, 2023
+footer: liburing-2.5
+header: liburing Manual
+section: 3
+title: io_uring_prep_cmd_sock
+---
+
+# NAME
+
+io_uring_prep_cmd_sock - prepare a command request for a socket
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_cmd_sock(struct io_uring_sqe * sqe ,
+ int cmd_op ,
+ int fd ,
+ int level ,
+ int optname ,
+ void *optval ,
+ int optlen );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_cmd_sock**(3) function prepares an cmd request for a
+socket. The submission queue entry *sqe* is setup to use the socket file
+descriptor pointed to by *fd* to start an command operation defined by
+*cmd_op.*
+
+This is a generic function, and each command has their own individual
+*level, optname, optval* values. The optlen defines the size pointed by
+*optval.*
+
+# Available commands
+
+**SOCKET_URING_OP_SIOCINQ**
+
+: Returns the amount of queued unread data in the receive buffer. The
+ socket must not be in LISTEN state, otherwise an error **-EINVAL** is
+ returned in the CQE *res* field. The following arguments are not used
+ for this command *level, optname, optval* and *optlen.*
+
+ Negative return value means an error.
+
+ For more information about this command, please check **unix(7).**
+
+ Available since 6.7.
+
+**SOCKET_URING_OP_SIOCOUTQ**
+
+: Returns the amount of unsent data in the socket send queue. The socket
+ must not be in LISTEN state, otherwise an error **-EINVAL** is
+ returned in the CQE *res.* field. The following arguments are not used
+ for this command *level, optname, optval* and *optlen.*
+
+ Negative return value means an error.
+
+ For more information about this command, please check **unix(7).**
+
+**SOCKET_URING_OP_GETSOCKOPT**
+
+: Command to get options for the socket referred to by the socket file
+ descriptor *fd.* The arguments are similar to the **getsockopt(2)**
+ system call.
+
+ The **SOCKET_URING_OP_GETSOCKOPT** command is limited to
+ **SOL_SOCKET** *level.*
+
+ Differently from the **getsockopt(2)** system call, the updated
+ *optlen* value is returned in the CQE *res* field, on success. On
+ failure, the CQE *res* contains a negative error number.
+
+**SOCKET_URING_OP_SETSOCKOPT**
+
+: Command to set options for the socket referred to by the socket file
+ descriptor *fd.* The arguments are similar to the **setsockopt(2)**
+ system call.
+
+ Available since 6.7.
+
+**SOCKET_URING_OP_TX_TIMESTAMP**
+
+: Retrieve transmit timestamps from the socket\'s error queue. This
+ provides an alternative to the traditional **recvmsg(2)** error queue
+ interface for obtaining TX timestamps.
+
+ The command operates in a polled multishot mode: io_uring will poll
+ the socket and keep posting timestamps as CQEs until the request is
+ cancelled or fails. The ring must be created with
+ **IORING_SETUP_CQE32** or **IORING_SETUP_CQE_MIXED** to provide space
+ for the timestamp data.
+
+ The socket must first be configured for timestamping via
+ **setsockopt(2)** with **SO_TIMESTAMPING** at the **SOL_SOCKET**
+ level, specifying the desired timestamp types (e.g.
+ **SOF_TIMESTAMPING_TX_SOFTWARE**, **SOF_TIMESTAMPING_TX_SCHED**,
+ **SOF_TIMESTAMPING_TX_ACK**) along with **SOF_TIMESTAMPING_SOFTWARE**
+ and **SOF_TIMESTAMPING_OPT_TSONLY**.
+
+ The following arguments are not used for this command: *level,
+ optname, optval* and *optlen.*
+
+ Each timestamp is delivered as a CQE with **IORING_CQE_F_MORE** set in
+ *cqe-\>flags* to indicate more timestamps may follow. The *cqe-\>res*
+ field contains the timestamp key (*tskey*), which corresponds to the
+ byte offset (for TCP) or packet count (for UDP). The timestamp type
+ (*SCM_TSTAMP_SCHED*, *SCM_TSTAMP_SND* or *SCM_TSTAMP_ACK*) is stored
+ in the upper bits of *cqe-\>flags* at offset
+ **IORING_TIMESTAMP_TYPE_SHIFT**. If the timestamp is a hardware
+ timestamp, the **IORING_CQE_F_TSTAMP_HW** flag is set.
+
+ The actual timestamp value is stored in the extended CQE area as a
+ **struct io_timespec** (with 64-bit *tv_sec* and *tv_nsec* fields),
+ accessible at *(cqe + 1)*.
+
+ The final CQE will not have **IORING_CQE_F_MORE** set, and its
+ *cqe-\>res* will contain 0 on success or a negative error code on
+ failure.
+
+ Available since 6.17.
+
+**SOCKET_URING_OP_GETSOCKNAME**
+
+: Returns the current address to which the socket is bound. The result
+ is stored in the buffer pointed to by *optval,* which should be a
+ pointer to a *struct sockaddr* (or appropriate variant). The *optlen*
+ argument specifies the size of the buffer. On success, the CQE *res*
+ field contains the actual size of the socket address. If the buffer is
+ too small, the result is truncated.
+
+ This is the io_uring equivalent of **getsockname**(2).
+
+ Available since 6.19.
+
+# NOTES
+
+The memory block pointed by *optval* needs to be valid/live until the
+CQE returns.
+
+# RETURN VALUE
+
+Dependent on the command.
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_register**(2), **unix**(7)
diff --git a/man/io_uring_prep_connect.3 b/man/io_uring_prep_connect.3
deleted file mode 100644
index 6a7c64a6..00000000
--- a/man/io_uring_prep_connect.3
+++ /dev/null
@@ -1,66 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_connect 3 "March 13, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_connect \- prepare a connect request
-.SH SYNOPSIS
-.nf
-.B #include <sys/types.h>
-.B #include <sys/socket.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_connect(struct io_uring_sqe *" sqe ","
-.BI " int " sockfd ","
-.BI " const struct sockaddr *" addr ","
-.BI " socklen_t " addrlen ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_connect (3)
-function prepares a connect request. The submission queue entry
-.I sqe
-is setup to use the file descriptor
-.I sockfd
-to start connecting to the destination described by the socket address at
-.I addr
-and of structure length
-.IR addrlen .
-
-This function prepares an async
-.BR connect (2)
-request. See that man page for details.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH NOTES
-As with any request that passes in data in a struct, that data must remain
-valid until the request has been successfully submitted. It need not remain
-valid until completion. Once a request has been submitted, the in-kernel
-state is stable. Very early kernels (5.4 and earlier) required state to be
-stable until the completion occurred. Applications can test for this
-behavior by inspecting the
-.B IORING_FEAT_SUBMIT_STABLE
-flag passed back from
-.BR io_uring_queue_init_params (3).
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR connect (2)
diff --git a/man/io_uring_prep_connect.3.md b/man/io_uring_prep_connect.3.md
new file mode 100644
index 00000000..93da3202
--- /dev/null
+++ b/man/io_uring_prep_connect.3.md
@@ -0,0 +1,65 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 13, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_connect
+---
+
+# NAME
+
+io_uring_prep_connect - prepare a connect request
+
+# SYNOPSIS
+
+``` text
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <liburing.h>
+
+ void io_uring_prep_connect(struct io_uring_sqe * sqe ,
+ int sockfd ,
+ const struct sockaddr * addr ,
+ socklen_t addrlen );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_connect**(3) function prepares a connect request.
+The submission queue entry *sqe* is setup to use the file descriptor
+*sockfd* to start connecting to the destination described by the socket
+address at *addr* and of structure length *addrlen*.
+
+This function prepares an async **connect**(2) request. See that man
+page for details.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# NOTES
+
+As with any request that passes in data in a struct, that data must
+remain valid until the request has been successfully submitted. It need
+not remain valid until completion. Once a request has been submitted,
+the in-kernel state is stable. Very early kernels (5.4 and earlier)
+required state to be stable until the completion occurred. Applications
+can test for this behavior by inspecting the
+**IORING_FEAT_SUBMIT_STABLE** flag passed back from
+**io_uring_queue_init_params**(3).
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3), **connect**(2)
diff --git a/man/io_uring_prep_epoll_ctl.3 b/man/io_uring_prep_epoll_ctl.3
deleted file mode 100644
index f709a9ac..00000000
--- a/man/io_uring_prep_epoll_ctl.3
+++ /dev/null
@@ -1,74 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_epoll_ctl 3 "January 18, 2025" "liburing-2.4" "liburing Manual"
-.SH NAME
-io_uring_prep_epoll_ctl \- prepare an epoll_ctl request
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_epoll_ctl(struct io_uring_sqe *" sqe ","
-.BI " int " epfd ","
-.BI " int " fd ","
-.BI " int " op ","
-.BI " const struct epoll_event *" ev ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_epoll_ctl (3)
-function prepares an epoll control request. The submission queue entry
-.I sqe
-is setup to use the epoll instance referred to by
-.IR epfd ,
-performing the operation
-.I op
-on the file descriptor
-.IR fd .
-The
-.I ev
-argument points to an
-.I epoll_event
-structure as defined in
-.BR epoll_ctl (2).
-
-The
-.I op
-argument can be one of:
-.TP
-.B EPOLL_CTL_ADD
-Add
-.I fd
-to the epoll instance.
-.TP
-.B EPOLL_CTL_MOD
-Modify the settings for
-.IR fd .
-.TP
-.B EPOLL_CTL_DEL
-Remove
-.I fd
-from the epoll instance.
-.I ev
-is ignored for this operation.
-
-This function prepares an async
-.BR epoll_ctl (2)
-request. See that man page for details.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation, 0 on success. On error,
-a negative errno value is returned. See
-.BR epoll_ctl (2)
-for possible error values.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_prep_epoll_wait (3),
-.BR epoll_ctl (2)
diff --git a/man/io_uring_prep_epoll_ctl.3.md b/man/io_uring_prep_epoll_ctl.3.md
new file mode 100644
index 00000000..f311046c
--- /dev/null
+++ b/man/io_uring_prep_epoll_ctl.3.md
@@ -0,0 +1,68 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 18, 2025
+footer: liburing-2.4
+header: liburing Manual
+section: 3
+title: io_uring_prep_epoll_ctl
+---
+
+# NAME
+
+io_uring_prep_epoll_ctl - prepare an epoll_ctl request
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_epoll_ctl(struct io_uring_sqe * sqe ,
+ int epfd ,
+ int fd ,
+ int op ,
+ const struct epoll_event * ev );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_epoll_ctl**(3) function prepares an epoll control
+request. The submission queue entry *sqe* is setup to use the epoll
+instance referred to by *epfd*, performing the operation *op* on the
+file descriptor *fd*. The *ev* argument points to an *epoll_event*
+structure as defined in **epoll_ctl**(2).
+
+The *op* argument can be one of:
+
+**EPOLL_CTL_ADD**
+
+: Add *fd* to the epoll instance.
+
+**EPOLL_CTL_MOD**
+
+: Modify the settings for *fd*.
+
+**EPOLL_CTL_DEL**
+
+: Remove *fd* from the epoll instance. *ev* is ignored for this
+ operation.
+
+ This function prepares an async **epoll_ctl**(2) request. See that man
+ page for details.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation, 0 on
+success. On error, a negative errno value is returned. See
+**epoll_ctl**(2) for possible error values.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_prep_epoll_wait**(3), **epoll_ctl**(2)
diff --git a/man/io_uring_prep_epoll_wait.3 b/man/io_uring_prep_epoll_wait.3
deleted file mode 100644
index 292f3974..00000000
--- a/man/io_uring_prep_epoll_wait.3
+++ /dev/null
@@ -1,64 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_epoll_wait 3 "March 6, 2025" "liburing-2.10" "liburing Manual"
-.SH NAME
-io_uring_prep_epoll_wait \- prepare an epoll wait request
-.SH SYNOPSIS
-.nf
-.B #include <sys/epoll.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_epoll_wait(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " struct epoll_event *" events ","
-.BI " int " maxevents ","
-.BI " unsigned flags ");"
-.PP
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_epoll_wait (3)
-function prepares an epoll_wait request. The submission queue entry
-.I sqe
-is setup to wait on a maximum of
-.IR maxevents
-events on the epoll file descriptor indicated by
-.IR fd ,
-and filling the received events into the memory pointed to by
-.IR events .
-
-This function prepares an async
-.BR epoll_wait (2)
-request. See that man page for details. The use case is mostly for legacy
-event loops, where certain file descriptors may still be using epoll for
-readiness notifications. Normally this would necessitate using epoll_wait
-with the io_uring fd added to that set as well, which is suboptimal as
-epoll doesn't provide the same kind of fine grained batch control and
-wakeup reductions that io_uring does. By using io_uring to read epoll events,
-the event loop can be entirely switched to io_uring, and reap the benefits
-of batch waiting and context switch reductions.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR epoll_wait (2)
diff --git a/man/io_uring_prep_epoll_wait.3.md b/man/io_uring_prep_epoll_wait.3.md
new file mode 100644
index 00000000..41b565cb
--- /dev/null
+++ b/man/io_uring_prep_epoll_wait.3.md
@@ -0,0 +1,61 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 6, 2025
+footer: liburing-2.10
+header: liburing Manual
+section: 3
+title: io_uring_prep_epoll_wait
+---
+
+# NAME
+
+io_uring_prep_epoll_wait - prepare an epoll wait request
+
+# SYNOPSIS
+
+``` text
+#include <sys/epoll.h>
+#include <liburing.h>
+
+ void io_uring_prep_epoll_wait(struct io_uring_sqe * sqe ,
+ int fd ,
+ struct epoll_event * events ,
+ int maxevents ,
+ unsigned flags );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_epoll_wait**(3) function prepares an epoll_wait
+request. The submission queue entry *sqe* is setup to wait on a maximum
+of *maxevents* events on the epoll file descriptor indicated by *fd*,
+and filling the received events into the memory pointed to by *events*.
+
+This function prepares an async **epoll_wait**(2) request. See that man
+page for details. The use case is mostly for legacy event loops, where
+certain file descriptors may still be using epoll for readiness
+notifications. Normally this would necessitate using epoll_wait with the
+io_uring fd added to that set as well, which is suboptimal as epoll
+doesn\'t provide the same kind of fine grained batch control and wakeup
+reductions that io_uring does. By using io_uring to read epoll events,
+the event loop can be entirely switched to io_uring, and reap the
+benefits of batch waiting and context switch reductions.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3), **epoll_wait**(2)
diff --git a/man/io_uring_prep_fadvise.3 b/man/io_uring_prep_fadvise.3
deleted file mode 100644
index 226eee59..00000000
--- a/man/io_uring_prep_fadvise.3
+++ /dev/null
@@ -1,76 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_fadvise 3 "March 13, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_fadvise \- prepare a fadvise request
-.SH SYNOPSIS
-.nf
-.B #include <fcntl.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_fadvise(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " __u64 " offset ","
-.BI " __u32 " len ","
-.BI " int " advice ");"
-.BI "
-.BI "void io_uring_prep_fadvise64(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " __u64 " offset ","
-.BI " off_t " len ","
-.BI " int " advice ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_fadvise (3)
-function prepares an fadvise request. The submission queue entry
-.I sqe
-is setup to use the file descriptor pointed to by
-.I fd
-to start an fadvise operation at
-.I offset
-and of
-.I len
-length in bytes, giving it the advise located in
-.IR advice .
-
-The
-.BR io_uring_prep_fadvise64 (3)
-function works like
-.BR io_uring_prep_fadvise (3)
-except that it takes a 64-bit length rather than just a 32-bit one. Older
-kernels may not support the 64-bit length variant. If this variant is attempted
-used on a kernel that doesn't support 64-bit lengths, then the request will get
-errored with
-.B -EINVAL
-in the results field of the CQE.
-
-This function prepares an async
-.BR posix_fadvise (2)
-request. See that man page for details.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_register (2),
-.BR posix_fadvise (2)
diff --git a/man/io_uring_prep_fadvise.3.md b/man/io_uring_prep_fadvise.3.md
new file mode 100644
index 00000000..a9b22aa2
--- /dev/null
+++ b/man/io_uring_prep_fadvise.3.md
@@ -0,0 +1,68 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 13, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_fadvise
+---
+
+# NAME
+
+io_uring_prep_fadvise - prepare a fadvise request
+
+# SYNOPSIS
+
+``` text
+#include <fcntl.h>
+#include <liburing.h>
+
+ void io_uring_prep_fadvise(struct io_uring_sqe * sqe ,
+ int fd ,
+ __u64 offset ,
+ __u32 len ,
+ int advice );
+
+ void io_uring_prep_fadvise64(struct io_uring_sqe * sqe ,
+ int fd ,
+ __u64 offset ,
+ off_t len ,
+ int advice );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_fadvise**(3) function prepares an fadvise request.
+The submission queue entry *sqe* is setup to use the file descriptor
+pointed to by *fd* to start an fadvise operation at *offset* and of
+*len* length in bytes, giving it the advise located in *advice*.
+
+The **io_uring_prep_fadvise64**(3) function works like
+**io_uring_prep_fadvise**(3) except that it takes a 64-bit length rather
+than just a 32-bit one. Older kernels may not support the 64-bit length
+variant. If this variant is attempted used on a kernel that doesn\'t
+support 64-bit lengths, then the request will get errored with
+**-EINVAL** in the results field of the CQE.
+
+This function prepares an async **posix_fadvise**(2) request. See that
+man page for details.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_register**(2), **posix_fadvise**(2)
diff --git a/man/io_uring_prep_fallocate.3 b/man/io_uring_prep_fallocate.3
deleted file mode 100644
index 426e1d52..00000000
--- a/man/io_uring_prep_fallocate.3
+++ /dev/null
@@ -1,59 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_fallocate 3 "March 13, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_fallocate \- prepare a fallocate request
-.SH SYNOPSIS
-.nf
-.B #include <fcntl.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_fallocate(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " int " mode ","
-.BI " __u64 " offset ","
-.BI " __u64 " len ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_fallocate (3)
-function prepares a fallocate request. The submission queue entry
-.I sqe
-is setup to use the file descriptor pointed to by
-.I fd
-to start a fallocate operation described by
-.I mode
-at offset
-.I offset
-and
-.I len
-length in bytes.
-
-This function prepares an async
-.BR fallocate (2)
-request. See that man page for details.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR fallocate (2)
diff --git a/man/io_uring_prep_fallocate.3.md b/man/io_uring_prep_fallocate.3.md
new file mode 100644
index 00000000..c9e4e1ac
--- /dev/null
+++ b/man/io_uring_prep_fallocate.3.md
@@ -0,0 +1,54 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 13, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_fallocate
+---
+
+# NAME
+
+io_uring_prep_fallocate - prepare a fallocate request
+
+# SYNOPSIS
+
+``` text
+#include <fcntl.h>
+#include <liburing.h>
+
+ void io_uring_prep_fallocate(struct io_uring_sqe * sqe ,
+ int fd ,
+ int mode ,
+ __u64 offset ,
+ __u64 len );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_fallocate**(3) function prepares a fallocate
+request. The submission queue entry *sqe* is setup to use the file
+descriptor pointed to by *fd* to start a fallocate operation described
+by *mode* at offset *offset* and *len* length in bytes.
+
+This function prepares an async **fallocate**(2) request. See that man
+page for details.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3), **fallocate**(2)
diff --git a/man/io_uring_prep_files_update.3 b/man/io_uring_prep_files_update.3
deleted file mode 100644
index bedb85e0..00000000
--- a/man/io_uring_prep_files_update.3
+++ /dev/null
@@ -1,92 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_files_update 3 "March 13, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_files_update \- prepare a registered file update request
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_files_update(struct io_uring_sqe *" sqe ","
-.BI " int *" fds ","
-.BI " unsigned " nr_fds ","
-.BI " int " offset ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_files_update (3)
-function prepares a request for updating a number of previously registered file
-descriptors. The submission queue entry
-.I sqe
-is setup to use the file descriptor array pointed to by
-.I fds
-and of
-.I nr_fds
-in length to update that amount of previously registered files starting at
-offset
-.IR offset .
-
-Once a previously registered file is updated with a new one, the existing
-entry is updated and then removed from the table. This operation is equivalent to
-first unregistering that entry and then inserting a new one, just bundled into
-one combined operation.
-
-If
-.I offset
-is specified as IORING_FILE_INDEX_ALLOC, io_uring will allocate free direct
-descriptors instead of having the application to pass, and store allocated
-direct descriptors into
-.I fds
-array,
-.I cqe->res
-will return the number of direct descriptors allocated.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-These are the errors that are reported in the CQE
-.I res
-field. On success,
-.I res
-will contain the number of successfully updated file descriptors. On error,
-the following errors can occur.
-.TP
-.B -ENOMEM
-The kernel was unable to allocate memory for the request.
-.TP
-.B -EINVAL
-One of the fields set in the SQE was invalid.
-.TP
-.B -EFAULT
-The kernel was unable to copy in the memory pointed to by
-.IR fds .
-.TP
-.B -EBADF
-On of the descriptors located in
-.I fds
-didn't refer to a valid file descriptor, or one of the file descriptors in
-the array referred to an io_uring instance.
-.TP
-.B -EOVERFLOW
-The product of
-.I offset
-and
-.I nr_fds
-exceed the valid amount or overflowed.
-.SH NOTES
-As with any request that passes in data in a struct, that data must remain
-valid until the request has been successfully submitted. It need not remain
-valid until completion. Once a request has been submitted, the in-kernel
-state is stable. Very early kernels (5.4 and earlier) required state to be
-stable until the completion occurred. Applications can test for this
-behavior by inspecting the
-.B IORING_FEAT_SUBMIT_STABLE
-flag passed back from
-.BR io_uring_queue_init_params (3).
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_register (2)
diff --git a/man/io_uring_prep_files_update.3.md b/man/io_uring_prep_files_update.3.md
new file mode 100644
index 00000000..04c59931
--- /dev/null
+++ b/man/io_uring_prep_files_update.3.md
@@ -0,0 +1,93 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 13, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_files_update
+---
+
+# NAME
+
+io_uring_prep_files_update - prepare a registered file update request
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_files_update(struct io_uring_sqe * sqe ,
+ int * fds ,
+ unsigned nr_fds ,
+ int offset );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_files_update**(3) function prepares a request for
+updating a number of previously registered file descriptors. The
+submission queue entry *sqe* is setup to use the file descriptor array
+pointed to by *fds* and of *nr_fds* in length to update that amount of
+previously registered files starting at offset *offset*.
+
+Once a previously registered file is updated with a new one, the
+existing entry is updated and then removed from the table. This
+operation is equivalent to first unregistering that entry and then
+inserting a new one, just bundled into one combined operation.
+
+If *offset* is specified as IORING_FILE_INDEX_ALLOC, io_uring will
+allocate free direct descriptors instead of having the application to
+pass, and store allocated direct descriptors into *fds* array,
+*cqe-\>res* will return the number of direct descriptors allocated.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+These are the errors that are reported in the CQE *res* field. On
+success, *res* will contain the number of successfully updated file
+descriptors. On error, the following errors can occur.
+
+**-ENOMEM**
+
+: The kernel was unable to allocate memory for the request.
+
+**-EINVAL**
+
+: One of the fields set in the SQE was invalid.
+
+**-EFAULT**
+
+: The kernel was unable to copy in the memory pointed to by *fds*.
+
+**-EBADF**
+
+: On of the descriptors located in *fds* didn\'t refer to a valid file
+ descriptor, or one of the file descriptors in the array referred to an
+ io_uring instance.
+
+**-EOVERFLOW**
+
+: The product of *offset* and *nr_fds* exceed the valid amount or
+ overflowed.
+
+# NOTES
+
+As with any request that passes in data in a struct, that data must
+remain valid until the request has been successfully submitted. It need
+not remain valid until completion. Once a request has been submitted,
+the in-kernel state is stable. Very early kernels (5.4 and earlier)
+required state to be stable until the completion occurred. Applications
+can test for this behavior by inspecting the
+**IORING_FEAT_SUBMIT_STABLE** flag passed back from
+**io_uring_queue_init_params**(3).
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_register**(2)
diff --git a/man/io_uring_prep_fixed_fd_install.3 b/man/io_uring_prep_fixed_fd_install.3
deleted file mode 100644
index 3300c450..00000000
--- a/man/io_uring_prep_fixed_fd_install.3
+++ /dev/null
@@ -1,70 +0,0 @@
-.\" Copyright (C) 2023 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_fixed_fd_install 3 "December 8, 2023" "liburing-2.6" "liburing Manual"
-.SH NAME
-io_uring_prep_fixed_fd_install \- prepare fixed file fd installation request
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_fixed_fd_install(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " unsigned int " flags ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_fixed_fd_install (3)
-helper prepares a fixed file descriptor installation. The submission queue entry
-.I sqe
-is setup to install the direct/fixed file descriptor
-.I fd
-with the specified
-.I flags
-file installation flags.
-
-One use case of direct/fixed file descriptors is to turn a regular file
-descriptor into a direct one, reducing the overhead of any request that
-needs to access this file. This helper provides a way to go the other way,
-turning a direct descriptor into a regular file descriptor that can then
-subsequently be used by regular system calls that take a normal file descriptor.
-This can be handy if no regular file descriptor exists for this direct
-descriptor. Either because it was instantiated directly as a fixed descriptor,
-or because the regular file was closed with
-.BR close (2)
-after being turned into a direct descriptor.
-
-Upon successful return of this request, both a normal and fixed file descriptor
-exists for the same file. Either one of them may be used to access the file.
-Either one of them may be closed without affecting the other one.
-
-.I flags
-may be either zero, or set to
-.B IORING_FIXED_FD_NO_CLOEXEC
-to indicate that the new regular file descriptor should not be closed during
-exec. By default,
-.B O_CLOEXEC
-will be set on the new descriptor otherwise. Setting this field to anything but
-those two values will result in the request being failed with
-.B -EINVAL
-in the CQE
-.I res
-field.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation, which in this case will be the
-value of the new regular file descriptor. In case of failure, a negative value
-is returned.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_register_files (3),
-.BR io_uring_unregister_files (3),
-.BR io_uring_prep_close_direct (3),
-.BR io_uring_prep_openat_direct (3)
diff --git a/man/io_uring_prep_fixed_fd_install.3.md b/man/io_uring_prep_fixed_fd_install.3.md
new file mode 100644
index 00000000..aec0272b
--- /dev/null
+++ b/man/io_uring_prep_fixed_fd_install.3.md
@@ -0,0 +1,71 @@
+.\" Copyright (C) 2023 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: December 8, 2023
+footer: liburing-2.6
+header: liburing Manual
+section: 3
+title: io_uring_prep_fixed_fd_install
+---
+
+# NAME
+
+io_uring_prep_fixed_fd_install - prepare fixed file fd installation
+request
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_fixed_fd_install(struct io_uring_sqe * sqe ,
+ int fd ,
+ unsigned int flags );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_fixed_fd_install**(3) helper prepares a fixed file
+descriptor installation. The submission queue entry *sqe* is setup to
+install the direct/fixed file descriptor *fd* with the specified *flags*
+file installation flags.
+
+One use case of direct/fixed file descriptors is to turn a regular file
+descriptor into a direct one, reducing the overhead of any request that
+needs to access this file. This helper provides a way to go the other
+way, turning a direct descriptor into a regular file descriptor that can
+then subsequently be used by regular system calls that take a normal
+file descriptor. This can be handy if no regular file descriptor exists
+for this direct descriptor. Either because it was instantiated directly
+as a fixed descriptor, or because the regular file was closed with
+**close**(2) after being turned into a direct descriptor.
+
+Upon successful return of this request, both a normal and fixed file
+descriptor exists for the same file. Either one of them may be used to
+access the file. Either one of them may be closed without affecting the
+other one.
+
+*flags* may be either zero, or set to **IORING_FIXED_FD_NO_CLOEXEC** to
+indicate that the new regular file descriptor should not be closed
+during exec. By default, **O_CLOEXEC** will be set on the new descriptor
+otherwise. Setting this field to anything but those two values will
+result in the request being failed with **-EINVAL** in the CQE *res*
+field.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation, which in
+this case will be the value of the new regular file descriptor. In case
+of failure, a negative value is returned.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_register_files**(3), **io_uring_unregister_files**(3),
+**io_uring_prep_close_direct**(3), **io_uring_prep_openat_direct**(3)
diff --git a/man/io_uring_prep_fsync.3 b/man/io_uring_prep_fsync.3
deleted file mode 100644
index a3259a0c..00000000
--- a/man/io_uring_prep_fsync.3
+++ /dev/null
@@ -1,70 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_fsync 3 "March 12, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_fsync \- prepare an fsync request
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_fsync(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " unsigned " flags ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_fsync (3)
-function prepares an fsync request. The submission queue entry
-.I sqe
-is setup to use the file descriptor
-.I fd
-that should get synced, with the modifier flags indicated by the
-.I flags
-argument.
-
-This function prepares an fsync request. It can act either like an
-.BR fsync (2)
-operation, which is the default behavior. If
-.B IORING_FSYNC_DATASYNC
-is set in the
-.I flags
-argument, then it behaves like
-.BR fdatasync (2).
-If no range is specified, the
-.I fd
-will be synced from 0 to end-of-file.
-
-It's possible to specify a range to sync, if one is desired. If the
-.I off
-field of the SQE is set to non-zero, then that indicates the offset to
-start syncing at. If
-.I len
-is set in the SQE, then that indicates the size in bytes to sync from the
-offset. Note that these fields are not accepted by this helper, so they have
-to be set manually in the SQE after calling this prep helper.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR fsync (2),
-.BR fdatasync (2)
diff --git a/man/io_uring_prep_fsync.3.md b/man/io_uring_prep_fsync.3.md
new file mode 100644
index 00000000..0f8eba4b
--- /dev/null
+++ b/man/io_uring_prep_fsync.3.md
@@ -0,0 +1,62 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 12, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_fsync
+---
+
+# NAME
+
+io_uring_prep_fsync - prepare an fsync request
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_fsync(struct io_uring_sqe * sqe ,
+ int fd ,
+ unsigned flags );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_fsync**(3) function prepares an fsync request. The
+submission queue entry *sqe* is setup to use the file descriptor *fd*
+that should get synced, with the modifier flags indicated by the *flags*
+argument.
+
+This function prepares an fsync request. It can act either like an
+**fsync**(2) operation, which is the default behavior. If
+**IORING_FSYNC_DATASYNC** is set in the *flags* argument, then it
+behaves like **fdatasync**(2). If no range is specified, the *fd* will
+be synced from 0 to end-of-file.
+
+It\'s possible to specify a range to sync, if one is desired. If the
+*off* field of the SQE is set to non-zero, then that indicates the
+offset to start syncing at. If *len* is set in the SQE, then that
+indicates the size in bytes to sync from the offset. Note that these
+fields are not accepted by this helper, so they have to be set manually
+in the SQE after calling this prep helper.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3), **fsync**(2),
+**fdatasync**(2)
diff --git a/man/io_uring_prep_ftruncate.3 b/man/io_uring_prep_ftruncate.3
deleted file mode 100644
index e3f1f7e0..00000000
--- a/man/io_uring_prep_ftruncate.3
+++ /dev/null
@@ -1,54 +0,0 @@
-.\" Copyright (C) 2024 Tony Solomonik <tony.solomonik@gmail.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_ftruncate 3 "January 23, 2024" "liburing-2.6" "liburing Manual"
-.SH NAME
-io_uring_prep_ftruncate \- prepare an ftruncate request
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_ftruncate(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " loff_t " len ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_ftruncate (3)
-function prepares an ftruncate request. The submission queue entry
-.I sqe
-is setup to use the file descriptor
-.I fd
-that should get truncated to the length indicated by the
-.I len
-argument.
-
-Applications must define
-.B _GNU_SOURCE
-to obtain the definition of this helper, as
-.I loff_t
-will not be defined without it.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR ftruncate (2),
diff --git a/man/io_uring_prep_ftruncate.3.md b/man/io_uring_prep_ftruncate.3.md
new file mode 100644
index 00000000..90520836
--- /dev/null
+++ b/man/io_uring_prep_ftruncate.3.md
@@ -0,0 +1,51 @@
+.\" Copyright (C) 2024 Tony Solomonik <tony.solomonik@gmail.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 23, 2024
+footer: liburing-2.6
+header: liburing Manual
+section: 3
+title: io_uring_prep_ftruncate
+---
+
+# NAME
+
+io_uring_prep_ftruncate - prepare an ftruncate request
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_ftruncate(struct io_uring_sqe * sqe ,
+ int fd ,
+ loff_t len );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_ftruncate**(3) function prepares an ftruncate
+request. The submission queue entry *sqe* is setup to use the file
+descriptor *fd* that should get truncated to the length indicated by the
+*len* argument.
+
+Applications must define **\_GNU_SOURCE** to obtain the definition of
+this helper, as *loff_t* will not be defined without it.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3), **ftruncate**(2),
diff --git a/man/io_uring_prep_futex_wait.3 b/man/io_uring_prep_futex_wait.3
deleted file mode 100644
index cf9bc455..00000000
--- a/man/io_uring_prep_futex_wait.3
+++ /dev/null
@@ -1,94 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_futex_wait 3 "Sep 29, 2023" "liburing-2.5" "liburing Manual"
-.SH NAME
-io_uring_prep_futex_wait \- prepare a futex wait request
-.SH SYNOPSIS
-.nf
-.B #include <linux/futex.h>
-.B #include <unistd.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_futex_wait(struct io_uring_sqe *" sqe ","
-.BI " const uint32_t *" futex ","
-.BI " uint64_t " val ","
-.BI " uint64_t " mask ","
-.BI " uint32_t " futex_flags ","
-.BI " unsigned int " flags ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_futex_wait (3)
-function prepares a futex wait request. The submission queue entry
-.I sqe
-is setup for waiting on a futex at address
-.I futex
-and which still has the value
-.I val
-and with
-.BR futex2 (2)
-flags of
-.I futex_flags
-and io_uring futex flags of
-.I flags .
-
-.I mask
-can be set to a specific bitset mask, which will be matched by the waking
-side to decide who to wake up. To always get woken, an application may use
-.B FUTEX_BITSET_MATCH_ANY .
-
-.I futex_flags
-follows the
-.BR futex2 (2)
-flags, not the
-.BR futex (2)
-v1 interface flags.
-
-.I flags
-are currently unused and hence
-.B 0
-must be passed.
-
-This function prepares an async
-.BR futex (2)
-wait request. See that man page for details. Note that the io_uring futex
-wait request is similar to the
-.B FUTEX_WAIT_BITSET
-operation, as
-.B FUTEX_WAIT
-is a strict subset of that.
-
-Available since kernel 6.7.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH NOTES
-Unlike the sync futex syscalls that wait on a futex, io_uring does not support
-passing in a timeout for the request. Instead, applications are encouraged
-to use a linked timeout to abort the futex request at a given time, if desired.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_prep_futex_waitv (3),
-.BR io_uring_prep_futex_wake (3),
-.BR io_uring_prep_link_timeout (3),
-.BR futex (2)
-.BR futex2 (2)
diff --git a/man/io_uring_prep_futex_wait.3.md b/man/io_uring_prep_futex_wait.3.md
new file mode 100644
index 00000000..56941f1f
--- /dev/null
+++ b/man/io_uring_prep_futex_wait.3.md
@@ -0,0 +1,79 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: Sep 29, 2023
+footer: liburing-2.5
+header: liburing Manual
+section: 3
+title: io_uring_prep_futex_wait
+---
+
+# NAME
+
+io_uring_prep_futex_wait - prepare a futex wait request
+
+# SYNOPSIS
+
+``` text
+#include <linux/futex.h>
+#include <unistd.h>
+#include <liburing.h>
+
+ void io_uring_prep_futex_wait(struct io_uring_sqe * sqe ,
+ const uint32_t * futex ,
+ uint64_t val ,
+ uint64_t mask ,
+ uint32_t futex_flags ,
+ unsigned int flags );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_futex_wait**(3) function prepares a futex wait
+request. The submission queue entry *sqe* is setup for waiting on a
+futex at address *futex* and which still has the value *val* and with
+**futex2**(2) flags of *futex_flags* and io_uring futex flags of *flags
+.*
+
+*mask* can be set to a specific bitset mask, which will be matched by
+the waking side to decide who to wake up. To always get woken, an
+application may use **FUTEX_BITSET_MATCH_ANY .**
+
+*futex_flags* follows the **futex2**(2) flags, not the **futex**(2) v1
+interface flags.
+
+*flags* are currently unused and hence **0** must be passed.
+
+This function prepares an async **futex**(2) wait request. See that man
+page for details. Note that the io_uring futex wait request is similar
+to the **FUTEX_WAIT_BITSET** operation, as **FUTEX_WAIT** is a strict
+subset of that.
+
+Available since kernel 6.7.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# NOTES
+
+Unlike the sync futex syscalls that wait on a futex, io_uring does not
+support passing in a timeout for the request. Instead, applications are
+encouraged to use a linked timeout to abort the futex request at a given
+time, if desired.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_prep_futex_waitv**(3), **io_uring_prep_futex_wake**(3),
+**io_uring_prep_link_timeout**(3), **futex**(2) **futex2**(2)
diff --git a/man/io_uring_prep_futex_waitv.3 b/man/io_uring_prep_futex_waitv.3
deleted file mode 100644
index d81fb9de..00000000
--- a/man/io_uring_prep_futex_waitv.3
+++ /dev/null
@@ -1,78 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_futex_waitv 3 "Sep 29, 2023" "liburing-2.5" "liburing Manual"
-.SH NAME
-io_uring_prep_futex_waitv \- prepare a futex waitv request
-.SH SYNOPSIS
-.nf
-.B #include <linux/futex.h>
-.B #include <unistd.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_futex_waitv(struct io_uring_sqe *" sqe ","
-.BI " const struct futex_waitv *" futexv ","
-.BI " uint32_t " nr_futex ","
-.BI " unsigned int " flags ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_futex_waitv (3)
-function prepares a futex wait request for multiple futexes at the same time.
-The submission queue entry
-.I sqe
-is setup for waiting on all futexes given by
-.I futexv
-and
-.I nr_futex
-is the number of futexes in that array.
-.I flags
-must be set to the io_uring specific futex flags.
-
-Unlike
-.BR io_uring_prep_futex_wait (3),
-the desired bitset mask and values are passed in
-.IR futexv .
-
-.I flags
-are currently unused and hence
-.B 0
-must be passed.
-
-This function prepares an async
-.BR futex (2)
-waitv request. See that man page for details.
-
-Available since kernel 6.7.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH NOTES
-Unlike the sync futex syscalls that wait on a futex, io_uring does not support
-passing in a timeout for the request. Instead, applications are encouraged
-to use a linked timeout to abort the futex request at a given time, if desired.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_prep_futex_wait (3),
-.BR io_uring_prep_futex_wake (3),
-.BR io_uring_prep_link_timeout (3),
-.BR futex (2)
-.BR futex2 (2)
diff --git a/man/io_uring_prep_futex_waitv.3.md b/man/io_uring_prep_futex_waitv.3.md
new file mode 100644
index 00000000..380ebf1f
--- /dev/null
+++ b/man/io_uring_prep_futex_waitv.3.md
@@ -0,0 +1,71 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: Sep 29, 2023
+footer: liburing-2.5
+header: liburing Manual
+section: 3
+title: io_uring_prep_futex_waitv
+---
+
+# NAME
+
+io_uring_prep_futex_waitv - prepare a futex waitv request
+
+# SYNOPSIS
+
+``` text
+#include <linux/futex.h>
+#include <unistd.h>
+#include <liburing.h>
+
+ void io_uring_prep_futex_waitv(struct io_uring_sqe * sqe ,
+ const struct futex_waitv * futexv ,
+ uint32_t nr_futex ,
+ unsigned int flags );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_futex_waitv**(3) function prepares a futex wait
+request for multiple futexes at the same time. The submission queue
+entry *sqe* is setup for waiting on all futexes given by *futexv* and
+*nr_futex* is the number of futexes in that array. *flags* must be set
+to the io_uring specific futex flags.
+
+Unlike **io_uring_prep_futex_wait**(3), the desired bitset mask and
+values are passed in *futexv*.
+
+*flags* are currently unused and hence **0** must be passed.
+
+This function prepares an async **futex**(2) waitv request. See that man
+page for details.
+
+Available since kernel 6.7.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# NOTES
+
+Unlike the sync futex syscalls that wait on a futex, io_uring does not
+support passing in a timeout for the request. Instead, applications are
+encouraged to use a linked timeout to abort the futex request at a given
+time, if desired.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_prep_futex_wait**(3), **io_uring_prep_futex_wake**(3),
+**io_uring_prep_link_timeout**(3), **futex**(2) **futex2**(2)
diff --git a/man/io_uring_prep_futex_wake.3 b/man/io_uring_prep_futex_wake.3
deleted file mode 100644
index 3bf646a5..00000000
--- a/man/io_uring_prep_futex_wake.3
+++ /dev/null
@@ -1,86 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_futex_wake 3 "Sep 29, 2023" "liburing-2.5" "liburing Manual"
-.SH NAME
-io_uring_prep_futex_wake \- prepare a futex wake request
-.SH SYNOPSIS
-.nf
-.B #include <linux/futex.h>
-.B #include <unistd.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_futex_wake(struct io_uring_sqe *" sqe ","
-.BI " const uint32_t *" futex ","
-.BI " uint64_t " val ","
-.BI " uint64_t " mask ","
-.BI " uint32_t " futex_flags ","
-.BI " unsigned int " flags ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_futex_wake (3)
-function prepares a futex wake request. The submission queue entry
-.I sqe
-is setup for waking any waiters on the futex indicated by
-.I futex
-and at most
-.I val
-futexes.
-.I futex_flags
-indicates the
-.BR futex2 (2)
-modifier flags, and io_uring futex flags of
-.I flags .
-
-If a given bitset for who to wake is desired, then that must be set in
-.I mask .
-Use
-.B FUTEX_BITSET_MATCH_ANY
-to match any waiter on the given futex.
-
-.I flags
-are currently unused and hence
-.B 0
-must be passed.
-
-This function prepares an async
-.BR futex (2)
-wake request. See that man page for details. Note that the io_uring futex
-wake request is similar to the
-.B FUTEX_WAKE_BITSET
-operation, as
-.B FUTEX_WAKE
-is a strict subset of that.
-
-Available since kernel 6.7.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. On success, the value will be
-the index into
-.I futexv
-which received a wakeup. See the related man page for details on possible
-values for errors. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_prep_futex_wait (3),
-.BR io_uring_prep_futex_waitv (3),
-.BR futex (2)
-.BR futex2 (2)
diff --git a/man/io_uring_prep_futex_wake.3.md b/man/io_uring_prep_futex_wake.3.md
new file mode 100644
index 00000000..46de7105
--- /dev/null
+++ b/man/io_uring_prep_futex_wake.3.md
@@ -0,0 +1,71 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: Sep 29, 2023
+footer: liburing-2.5
+header: liburing Manual
+section: 3
+title: io_uring_prep_futex_wake
+---
+
+# NAME
+
+io_uring_prep_futex_wake - prepare a futex wake request
+
+# SYNOPSIS
+
+``` text
+#include <linux/futex.h>
+#include <unistd.h>
+#include <liburing.h>
+
+ void io_uring_prep_futex_wake(struct io_uring_sqe * sqe ,
+ const uint32_t * futex ,
+ uint64_t val ,
+ uint64_t mask ,
+ uint32_t futex_flags ,
+ unsigned int flags );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_futex_wake**(3) function prepares a futex wake
+request. The submission queue entry *sqe* is setup for waking any
+waiters on the futex indicated by *futex* and at most *val* futexes.
+*futex_flags* indicates the **futex2**(2) modifier flags, and io_uring
+futex flags of *flags .*
+
+If a given bitset for who to wake is desired, then that must be set in
+*mask .* Use **FUTEX_BITSET_MATCH_ANY** to match any waiter on the given
+futex.
+
+*flags* are currently unused and hence **0** must be passed.
+
+This function prepares an async **futex**(2) wake request. See that man
+page for details. Note that the io_uring futex wake request is similar
+to the **FUTEX_WAKE_BITSET** operation, as **FUTEX_WAKE** is a strict
+subset of that.
+
+Available since kernel 6.7.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. On
+success, the value will be the index into *futexv* which received a
+wakeup. See the related man page for details on possible values for
+errors. Note that where synchronous system calls will return **-1** on
+failure and set *errno* to the actual error value, io_uring never uses
+*errno*. Instead it returns the negated *errno* directly in the CQE
+*res* field.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_prep_futex_wait**(3), **io_uring_prep_futex_waitv**(3),
+**futex**(2) **futex2**(2)
diff --git a/man/io_uring_prep_getxattr.3 b/man/io_uring_prep_getxattr.3
deleted file mode 100644
index 61274056..00000000
--- a/man/io_uring_prep_getxattr.3
+++ /dev/null
@@ -1,61 +0,0 @@
-.\" Copyright (C) 2023 Rutvik Patel <heyrutvik@gmail.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_getxattr 3 "January 23, 2023" "liburing-2.4" "liburing Manual"
-.SH NAME
-io_uring_prep_getxattr, io_uring_prep_fgetxattr \- prepare a request to get an
-extended attribute value
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_getxattr(struct io_uring_sqe *" sqe ","
-.BI " const char *" name ","
-.BI " char *" value ","
-.BI " const char *" path ","
-.BI " unsigned int " len ");"
-.PP
-.BI "void io_uring_prep_fgetxattr(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " const char *" name ","
-.BI " char *" value ","
-.BI " unsigned int " len ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_getxattr (3)
-function prepares a request to get an extended attribute value. The submission
-queue entry
-.I sqe
-is setup to get the
-.I value
-of the extended attribute identified by
-.I name
-and associated with the given
-.I path
-in the filesystem.
-The
-.I len
-argument specifies the size (in bytes) of
-.IR value .
-
-.BR io_uring_prep_fgetxattr (3)
-is identical to
-.BR io_uring_prep_getxattr (3),
-only the open file referred to by
-.I fd
-is interrogated in place of
-.IR path .
-
-This function prepares an async
-.BR getxattr (2)
-request. See that man page for details.
-
-.SH RETURN VALUE
-None
-
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR getxattr (2)
diff --git a/man/io_uring_prep_getxattr.3.md b/man/io_uring_prep_getxattr.3.md
new file mode 100644
index 00000000..8d902b13
--- /dev/null
+++ b/man/io_uring_prep_getxattr.3.md
@@ -0,0 +1,57 @@
+.\" Copyright (C) 2023 Rutvik Patel <heyrutvik@gmail.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 23, 2023
+footer: liburing-2.4
+header: liburing Manual
+section: 3
+title: io_uring_prep_getxattr
+---
+
+# NAME
+
+io_uring_prep_getxattr, io_uring_prep_fgetxattr - prepare a request to
+get an extended attribute value
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_getxattr(struct io_uring_sqe * sqe ,
+ const char * name ,
+ char * value ,
+ const char * path ,
+ unsigned int len );
+
+ void io_uring_prep_fgetxattr(struct io_uring_sqe * sqe ,
+ int fd ,
+ const char * name ,
+ char * value ,
+ unsigned int len );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_getxattr**(3) function prepares a request to get an
+extended attribute value. The submission queue entry *sqe* is setup to
+get the *value* of the extended attribute identified by *name* and
+associated with the given *path* in the filesystem. The *len* argument
+specifies the size (in bytes) of *value*.
+
+**io_uring_prep_fgetxattr**(3) is identical to
+**io_uring_prep_getxattr**(3), only the open file referred to by *fd* is
+interrogated in place of *path*.
+
+This function prepares an async **getxattr**(2) request. See that man
+page for details.
+
+# RETURN VALUE
+
+None
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **getxattr**(2)
diff --git a/man/io_uring_prep_link_timeout.3 b/man/io_uring_prep_link_timeout.3
deleted file mode 100644
index 3afbd728..00000000
--- a/man/io_uring_prep_link_timeout.3
+++ /dev/null
@@ -1,98 +0,0 @@
-.\" Copyright (C) 2023 Rutvik Patel <heyrutvik@gmail.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_link_timeout 3 "January 23, 2023" "liburing-2.4" "liburing Manual"
-.SH NAME
-io_uring_prep_link_timeout \- a timeout request for linked sqes
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_link_timeout(struct io_uring_sqe *" sqe ","
-.BI " const struct __kernel_timespec *" ts ","
-.BI " unsigned " flags ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_link_timeout (3)
-function prepares a timeout request for linked sqes. The submission queue entry
-.I sqe
-is setup for with timeout specified by
-.IR ts .
-The flags argument holds modifier
-.I flags
-for the timeout behaviour of the request.
-
-The
-.I ts
-argument must be filled in with the appropriate information for the timeout. It
-looks as follows:
-.PP
-.in +4n
-.EX
-struct __kernel_timespec {
- __kernel_time64_t tv_sec;
- long long tv_nsec;
-};
-.EE
-.in
-.PP
-
-The
-.I flags
-argument may contain:
-.TP
-.B IORING_TIMEOUT_ABS
-The value specified in
-.I ts
-is an absolute value rather than a relative one.
-.TP
-.B IORING_TIMEOUT_BOOTTIME
-The boottime clock source should be used.
-.TP
-.B IORING_TIMEOUT_REALTIME
-The realtime clock source should be used.
-.TP
-.B IORING_TIMEOUT_ETIME_SUCCESS
-Consider an expired timeout a success in terms of the posted completion.
-.PP
-
-It is invalid to create a chain (linked sqes) consisting only of a link timeout
-request. If all the requests in the chain are completed before timeout, then the
-link timeout request gets canceled. Upon timeout, all the uncompleted requests
-in the chain get canceled.
-
-.SH RETURN VALUE
-None
-
-.SH ERRORS
-.PP
-These are the errors that are reported in the CQE
-.I res
-field. On success,
-.B 0
-is returned.
-.TP
-.B -ETIME
-The specified timeout occurred and triggered the completion event.
-.TP
-.B -EINVAL
-One of the fields set in the SQE was invalid. For example, two clock sources
-where given, or the specified timeout seconds or nanoseconds where < 0.
-.TP
-.B -EFAULT
-io_uring was unable to access the data specified by ts.
-.TP
-.B -ECANCELED
-The timeout was canceled because all submitted requests were completed successfully
-or one of the requests resulted in failure.
-.TP
-.B -ENOENT
-The request to which the linked timeout was linked already completed and could
-not be found when the timer expired.
-
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_prep_timeout (3)
diff --git a/man/io_uring_prep_link_timeout.3.md b/man/io_uring_prep_link_timeout.3.md
new file mode 100644
index 00000000..4bc6bdf1
--- /dev/null
+++ b/man/io_uring_prep_link_timeout.3.md
@@ -0,0 +1,104 @@
+.\" Copyright (C) 2023 Rutvik Patel <heyrutvik@gmail.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 23, 2023
+footer: liburing-2.4
+header: liburing Manual
+section: 3
+title: io_uring_prep_link_timeout
+---
+
+# NAME
+
+io_uring_prep_link_timeout - a timeout request for linked sqes
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_link_timeout(struct io_uring_sqe * sqe ,
+ const struct __kernel_timespec * ts ,
+ unsigned flags );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_link_timeout**(3) function prepares a timeout
+request for linked sqes. The submission queue entry *sqe* is setup for
+with timeout specified by *ts*. The flags argument holds modifier
+*flags* for the timeout behaviour of the request.
+
+The *ts* argument must be filled in with the appropriate information for
+the timeout. It looks as follows:
+
+``` text
+struct __kernel_timespec {
+ __kernel_time64_t tv_sec;
+ long long tv_nsec;
+};
+```
+
+The *flags* argument may contain:
+
+**IORING_TIMEOUT_ABS**
+
+: The value specified in *ts* is an absolute value rather than a
+ relative one.
+
+**IORING_TIMEOUT_BOOTTIME**
+
+: The boottime clock source should be used.
+
+**IORING_TIMEOUT_REALTIME**
+
+: The realtime clock source should be used.
+
+**IORING_TIMEOUT_ETIME_SUCCESS**
+
+: Consider an expired timeout a success in terms of the posted
+ completion.
+
+It is invalid to create a chain (linked sqes) consisting only of a link
+timeout request. If all the requests in the chain are completed before
+timeout, then the link timeout request gets canceled. Upon timeout, all
+the uncompleted requests in the chain get canceled.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+These are the errors that are reported in the CQE *res* field. On
+success, **0** is returned.
+
+**-ETIME**
+
+: The specified timeout occurred and triggered the completion event.
+
+**-EINVAL**
+
+: One of the fields set in the SQE was invalid. For example, two clock
+ sources where given, or the specified timeout seconds or nanoseconds
+ where \< 0.
+
+**-EFAULT**
+
+: io_uring was unable to access the data specified by ts.
+
+**-ECANCELED**
+
+: The timeout was canceled because all submitted requests were completed
+ successfully or one of the requests resulted in failure.
+
+**-ENOENT**
+
+: The request to which the linked timeout was linked already completed
+ and could not be found when the timer expired.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_prep_timeout**(3)
diff --git a/man/io_uring_prep_linkat.3 b/man/io_uring_prep_linkat.3
deleted file mode 100644
index 0949e3b4..00000000
--- a/man/io_uring_prep_linkat.3
+++ /dev/null
@@ -1,91 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_linkat 3 "March 13, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_linkat \- prepare a linkat request
-.SH SYNOPSIS
-.nf
-.B #include <fcntl.h>
-.B #include <unistd.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_linkat(struct io_uring_sqe *" sqe ","
-.BI " int " olddirfd ","
-.BI " const char *" oldpath ","
-.BI " int " newdirfd ","
-.BI " const char *" newpath ","
-.BI " int " flags ");"
-.PP
-.BI "void io_uring_prep_link(struct io_uring_sqe *" sqe ","
-.BI " const char *" oldpath ","
-.BI " const char *" newpath ","
-.BI " int " flags ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_linkat (3)
-function prepares a linkat request. The submission queue entry
-.I sqe
-is setup to use the old directory file descriptor pointed to by
-.I olddirfd
-and old path pointed to by
-.I oldpath
-with the new directory file descriptor pointed to by
-.I newdirfd
-and the new path pointed to by
-.I newpath
-and using the specified flags in
-.IR flags .
-
-The
-.BR io_uring_prep_link (3)
-function prepares a link request. The submission queue entry
-.I sqe
-is setup to use the old path pointed to by
-.I oldpath
-and the new path pointed to by
-.IR newpath ,
-both relative to the current working directory and using the specified flags in
-.IR flags .
-
-These functions prepare an async
-.BR linkat (2)
-or
-.BR link (2)
-request. See those man pages for details.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH NOTES
-As with any request that passes in data in a struct, that data must remain
-valid until the request has been successfully submitted. It need not remain
-valid until completion. Once a request has been submitted, the in-kernel
-state is stable. Very early kernels (5.4 and earlier) required state to be
-stable until the completion occurred. Applications can test for this
-behavior by inspecting the
-.B IORING_FEAT_SUBMIT_STABLE
-flag passed back from
-.BR io_uring_queue_init_params (3).
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR linkat (2),
-.BR link (2)
diff --git a/man/io_uring_prep_linkat.3.md b/man/io_uring_prep_linkat.3.md
new file mode 100644
index 00000000..d0bfa4c7
--- /dev/null
+++ b/man/io_uring_prep_linkat.3.md
@@ -0,0 +1,80 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 13, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_linkat
+---
+
+# NAME
+
+io_uring_prep_linkat - prepare a linkat request
+
+# SYNOPSIS
+
+``` text
+#include <fcntl.h>
+#include <unistd.h>
+#include <liburing.h>
+
+ void io_uring_prep_linkat(struct io_uring_sqe * sqe ,
+ int olddirfd ,
+ const char * oldpath ,
+ int newdirfd ,
+ const char * newpath ,
+ int flags );
+
+ void io_uring_prep_link(struct io_uring_sqe * sqe ,
+ const char * oldpath ,
+ const char * newpath ,
+ int flags );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_linkat**(3) function prepares a linkat request. The
+submission queue entry *sqe* is setup to use the old directory file
+descriptor pointed to by *olddirfd* and old path pointed to by *oldpath*
+with the new directory file descriptor pointed to by *newdirfd* and the
+new path pointed to by *newpath* and using the specified flags in
+*flags*.
+
+The **io_uring_prep_link**(3) function prepares a link request. The
+submission queue entry *sqe* is setup to use the old path pointed to by
+*oldpath* and the new path pointed to by *newpath*, both relative to the
+current working directory and using the specified flags in *flags*.
+
+These functions prepare an async **linkat**(2) or **link**(2) request.
+See those man pages for details.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# NOTES
+
+As with any request that passes in data in a struct, that data must
+remain valid until the request has been successfully submitted. It need
+not remain valid until completion. Once a request has been submitted,
+the in-kernel state is stable. Very early kernels (5.4 and earlier)
+required state to be stable until the completion occurred. Applications
+can test for this behavior by inspecting the
+**IORING_FEAT_SUBMIT_STABLE** flag passed back from
+**io_uring_queue_init_params**(3).
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3), **linkat**(2),
+**link**(2)
diff --git a/man/io_uring_prep_listen.3 b/man/io_uring_prep_listen.3
deleted file mode 100644
index b765298a..00000000
--- a/man/io_uring_prep_listen.3
+++ /dev/null
@@ -1,52 +0,0 @@
-.\" Copyright (C) 2024 SUSE LLC.
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_listen 3 "Jun 3, 2024" "liburing-2.7" "liburing Manual"
-.SH NAME
-io_uring_prep_listen \- prepare a listen request
-.SH SYNOPSIS
-.nf
-.B #include <sys/socket.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_listen(struct io_uring_sqe *" sqe ","
-.BI " int " sockfd ","
-.BI " int" backlog ");"
-.fi
-.SH DESCRIPTION
-The
-.BR io_uring_prep_listen (3)
-function prepares a listen request. The submission queue entry
-.I sqe
-is setup to place the socket file descriptor pointed by
-.IR sockfd
-into a state to accept incoming connections. The parameter
-.IR backlog ,
-defines the maximum length of the queue of pending connections.
-
-This function prepares an async
-.BR listen (2)
-request. See that man page for details.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR listen (2)
diff --git a/man/io_uring_prep_listen.3.md b/man/io_uring_prep_listen.3.md
new file mode 100644
index 00000000..660de9eb
--- /dev/null
+++ b/man/io_uring_prep_listen.3.md
@@ -0,0 +1,53 @@
+.\" Copyright (C) 2024 SUSE LLC.
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: Jun 3, 2024
+footer: liburing-2.7
+header: liburing Manual
+section: 3
+title: io_uring_prep_listen
+---
+
+# NAME
+
+io_uring_prep_listen - prepare a listen request
+
+# SYNOPSIS
+
+``` text
+#include <sys/socket.h>
+#include <liburing.h>
+
+ void io_uring_prep_listen(struct io_uring_sqe * sqe ,
+ int sockfd ,
+ int backlog );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_listen**(3) function prepares a listen request. The
+submission queue entry *sqe* is setup to place the socket file
+descriptor pointed by *sockfd* into a state to accept incoming
+connections. The parameter *backlog*, defines the maximum length of the
+queue of pending connections.
+
+This function prepares an async **listen**(2) request. See that man page
+for details.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3), **listen**(2)
diff --git a/man/io_uring_prep_madvise.3 b/man/io_uring_prep_madvise.3
deleted file mode 100644
index f29fa920..00000000
--- a/man/io_uring_prep_madvise.3
+++ /dev/null
@@ -1,72 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_madvise 3 "March 13, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_madvise \- prepare a madvise request
-.SH SYNOPSIS
-.nf
-.B #include <sys/mman.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_madvise(struct io_uring_sqe *" sqe ","
-.BI " void *" addr ","
-.BI " __u32 " len ","
-.BI " int " advice ");"
-.BI "
-.BI "void io_uring_prep_madvise64(struct io_uring_sqe *" sqe ","
-.BI " void *" addr ","
-.BI " off_t " len ","
-.BI " int " advice ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_madvise (3)
-function prepares an madvise request. The submission queue entry
-.I sqe
-is setup to start an madvise operation at the virtual address of
-.I addr
-and of
-.I len
-length in bytes, giving it the advise located in
-.IR advice .
-
-The
-.BR io_uring_prep_madvise64 (3)
-function works like
-.BR io_uring_prep_madvise (3)
-except that it takes a 64-bit length rather than just a 32-bit one. Older
-kernels may not support the 64-bit length variant. If this variant is attempted
-used on a kernel that doesn't support 64-bit lengths, then the request will get
-errored with
-.B -EINVAL
-in the results field of the CQE.
-
-This function prepares an async
-.BR madvise (2)
-request. See that man page for details.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_register (2),
-.BR madvise (2)
diff --git a/man/io_uring_prep_madvise.3.md b/man/io_uring_prep_madvise.3.md
new file mode 100644
index 00000000..372f3f23
--- /dev/null
+++ b/man/io_uring_prep_madvise.3.md
@@ -0,0 +1,66 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 13, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_madvise
+---
+
+# NAME
+
+io_uring_prep_madvise - prepare a madvise request
+
+# SYNOPSIS
+
+``` text
+#include <sys/mman.h>
+#include <liburing.h>
+
+ void io_uring_prep_madvise(struct io_uring_sqe * sqe ,
+ void * addr ,
+ __u32 len ,
+ int advice );
+
+ void io_uring_prep_madvise64(struct io_uring_sqe * sqe ,
+ void * addr ,
+ off_t len ,
+ int advice );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_madvise**(3) function prepares an madvise request.
+The submission queue entry *sqe* is setup to start an madvise operation
+at the virtual address of *addr* and of *len* length in bytes, giving it
+the advise located in *advice*.
+
+The **io_uring_prep_madvise64**(3) function works like
+**io_uring_prep_madvise**(3) except that it takes a 64-bit length rather
+than just a 32-bit one. Older kernels may not support the 64-bit length
+variant. If this variant is attempted used on a kernel that doesn\'t
+support 64-bit lengths, then the request will get errored with
+**-EINVAL** in the results field of the CQE.
+
+This function prepares an async **madvise**(2) request. See that man
+page for details.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_register**(2), **madvise**(2)
diff --git a/man/io_uring_prep_mkdirat.3 b/man/io_uring_prep_mkdirat.3
deleted file mode 100644
index a98b4e35..00000000
--- a/man/io_uring_prep_mkdirat.3
+++ /dev/null
@@ -1,83 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_mkdirat 3 "March 13, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_mkdirat \- prepare an mkdirat request
-.SH SYNOPSIS
-.nf
-.B #include <fcntl.h>
-.B #include <sys/stat.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_mkdirat(struct io_uring_sqe *" sqe ","
-.BI " int " dirfd ","
-.BI " const char *" path ","
-.BI " mode_t " mode ");"
-.PP
-.BI "void io_uring_prep_mkdir(struct io_uring_sqe *" sqe ","
-.BI " const char *" path ","
-.BI " mode_t " mode ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_mkdirat (3)
-function prepares a mkdirat request. The submission queue entry
-.I sqe
-is setup to use the directory file descriptor pointed to by
-.I dirfd
-to start a mkdirat operation on the path identified by
-.I path
-with the mode given in
-.IR mode .
-
-The
-.BR io_uring_prep_mkdir (3)
-function prepares a mkdir request. The submission queue entry
-.I sqe
-is setup to use the current working directory to start a mkdir
-operation on the path identified by
-.I path
-with the mode given in
-.IR mode .
-
-These functions prepare an async
-.BR mkdir (2)
-or
-.BR mkdirat (2)
-request. See those man pages for details.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH NOTES
-As with any request that passes in data in a struct, that data must remain
-valid until the request has been successfully submitted. It need not remain
-valid until completion. Once a request has been submitted, the in-kernel
-state is stable. Very early kernels (5.4 and earlier) required state to be
-stable until the completion occurred. Applications can test for this
-behavior by inspecting the
-.B IORING_FEAT_SUBMIT_STABLE
-flag passed back from
-.BR io_uring_queue_init_params (3).
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR mkdirat (2),
-.BR mkdir (2)
diff --git a/man/io_uring_prep_mkdirat.3.md b/man/io_uring_prep_mkdirat.3.md
new file mode 100644
index 00000000..b295afae
--- /dev/null
+++ b/man/io_uring_prep_mkdirat.3.md
@@ -0,0 +1,75 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 13, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_mkdirat
+---
+
+# NAME
+
+io_uring_prep_mkdirat - prepare an mkdirat request
+
+# SYNOPSIS
+
+``` text
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <liburing.h>
+
+ void io_uring_prep_mkdirat(struct io_uring_sqe * sqe ,
+ int dirfd ,
+ const char * path ,
+ mode_t mode );
+
+ void io_uring_prep_mkdir(struct io_uring_sqe * sqe ,
+ const char * path ,
+ mode_t mode );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_mkdirat**(3) function prepares a mkdirat request.
+The submission queue entry *sqe* is setup to use the directory file
+descriptor pointed to by *dirfd* to start a mkdirat operation on the
+path identified by *path* with the mode given in *mode*.
+
+The **io_uring_prep_mkdir**(3) function prepares a mkdir request. The
+submission queue entry *sqe* is setup to use the current working
+directory to start a mkdir operation on the path identified by *path*
+with the mode given in *mode*.
+
+These functions prepare an async **mkdir**(2) or **mkdirat**(2) request.
+See those man pages for details.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# NOTES
+
+As with any request that passes in data in a struct, that data must
+remain valid until the request has been successfully submitted. It need
+not remain valid until completion. Once a request has been submitted,
+the in-kernel state is stable. Very early kernels (5.4 and earlier)
+required state to be stable until the completion occurred. Applications
+can test for this behavior by inspecting the
+**IORING_FEAT_SUBMIT_STABLE** flag passed back from
+**io_uring_queue_init_params**(3).
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3), **mkdirat**(2),
+**mkdir**(2)
diff --git a/man/io_uring_prep_msg_ring.3 b/man/io_uring_prep_msg_ring.3
deleted file mode 100644
index 70caebe7..00000000
--- a/man/io_uring_prep_msg_ring.3
+++ /dev/null
@@ -1,92 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_msg_ring 3 "March 10, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_msg_ring \- send a message to another ring
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_msg_ring(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " unsigned int " len ","
-.BI " __u64 " data ","
-.BI " unsigned int " flags ");"
-.PP
-.BI "void io_uring_prep_msg_ring_cqe_flags(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " unsigned int " len ","
-.BI " __u64 " data ","
-.BI " unsigned int " flags ","
-.BI " unsigned int " cqe_flags ");"
-.fi
-.SH DESCRIPTION
-.PP
-.BR io_uring_prep_msg_ring (3)
-prepares to send a CQE to an io_uring file descriptor. The submission queue
-entry
-.I sqe
-is setup to use the file descriptor
-.IR fd ,
-which must identify a io_uring context, to post a CQE on that ring where the
-target CQE
-.B res
-field will contain the content of
-.I len
-and the
-.B user_data
-of
-.I data
-with the request modifier flags set by
-.IR flags .
-Currently there are no valid flag modifiers, this field must contain
-.BR 0 .
-
-The targeted ring may be any ring that the user has access to, even the ring
-itself. This request can be used for simple message passing to another ring,
-allowing 32+64 bits of data to be transferred through the
-.I len
-and
-.I data
-fields. The use case may be anything from simply waking up someone waiting
-on the targeted ring, or it can be used to pass messages between the two
-rings.
-
-.BR io_uring_prep_msg_ring_cqe_flags (3)
-is similar to
-.BR io_uring_prep_msg_ring (3) .
-But has an addition
-.I cqe_flags
-parameter, which is used to set
-.I flags
-field on CQE side. That way, you can set the CQE flags field
-.I cqe->flags
-when sending a message. Be aware that io_uring could potentially set additional
-bits into this field.
-
-.SH RETURN VALUE
-None
-
-.SH ERRORS
-These are the errors that are reported in the CQE
-.I res
-field.
-.TP
-.B -ENOMEM
-The kernel was unable to allocate memory for the request.
-.TP
-.B -EINVAL
-One of the fields set in the SQE was invalid.
-.TP
-.B -EBADFD
-The descriptor passed in
-.I fd
-does not refer to an io_uring file descriptor, or the ring is in a disabled
-state.
-.TP
-.B -EOVERFLOW
-The kernel was unable to fill a CQE on the target ring. This can happen if
-the target CQ ring is in an overflow state and the kernel wasn't able to
-allocate memory for a new CQE entry.
diff --git a/man/io_uring_prep_msg_ring.3.md b/man/io_uring_prep_msg_ring.3.md
new file mode 100644
index 00000000..9395496d
--- /dev/null
+++ b/man/io_uring_prep_msg_ring.3.md
@@ -0,0 +1,85 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 10, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_msg_ring
+---
+
+# NAME
+
+io_uring_prep_msg_ring - send a message to another ring
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_msg_ring(struct io_uring_sqe * sqe ,
+ int fd ,
+ unsigned int len ,
+ __u64 data ,
+ unsigned int flags );
+
+ void io_uring_prep_msg_ring_cqe_flags(struct io_uring_sqe * sqe ,
+ int fd ,
+ unsigned int len ,
+ __u64 data ,
+ unsigned int flags ,
+ unsigned int cqe_flags );
+```
+
+# DESCRIPTION
+
+**io_uring_prep_msg_ring**(3) prepares to send a CQE to an io_uring file
+descriptor. The submission queue entry *sqe* is setup to use the file
+descriptor *fd*, which must identify a io_uring context, to post a CQE
+on that ring where the target CQE **res** field will contain the content
+of *len* and the **user_data** of *data* with the request modifier flags
+set by *flags*. Currently there are no valid flag modifiers, this field
+must contain **0**.
+
+The targeted ring may be any ring that the user has access to, even the
+ring itself. This request can be used for simple message passing to
+another ring, allowing 32+64 bits of data to be transferred through the
+*len* and *data* fields. The use case may be anything from simply waking
+up someone waiting on the targeted ring, or it can be used to pass
+messages between the two rings.
+
+**io_uring_prep_msg_ring_cqe_flags**(3) is similar to
+**io_uring_prep_msg_ring**(3)**.** But has an addition *cqe_flags*
+parameter, which is used to set *flags* field on CQE side. That way, you
+can set the CQE flags field *cqe-\>flags* when sending a message. Be
+aware that io_uring could potentially set additional bits into this
+field.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+These are the errors that are reported in the CQE *res* field.
+
+**-ENOMEM**
+
+: The kernel was unable to allocate memory for the request.
+
+**-EINVAL**
+
+: One of the fields set in the SQE was invalid.
+
+**-EBADFD**
+
+: The descriptor passed in *fd* does not refer to an io_uring file
+ descriptor, or the ring is in a disabled state.
+
+**-EOVERFLOW**
+
+: The kernel was unable to fill a CQE on the target ring. This can
+ happen if the target CQ ring is in an overflow state and the kernel
+ wasn\'t able to allocate memory for a new CQE entry.
diff --git a/man/io_uring_prep_msg_ring_fd.3 b/man/io_uring_prep_msg_ring_fd.3
deleted file mode 100644
index 39cd34aa..00000000
--- a/man/io_uring_prep_msg_ring_fd.3
+++ /dev/null
@@ -1,83 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_msg_ring_fd 3 "Mar 16, 2023" "liburing-2.4" "liburing Manual"
-.SH NAME
-io_uring_prep_msg_ring_fd \- send a direct descriptor to another ring
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_msg_ring_fd(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " int " source_fd ","
-.BI " int " target_fd ","
-.BI " __u64 " data ","
-.BI " unsigned int " flags ");"
-.PP
-.BI "void io_uring_prep_msg_ring_fd_alloc(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " int " source_fd ","
-.BI " __u64 " data ","
-.BI " unsigned int " flags ");"
-.fi
-.SH DESCRIPTION
-.PP
-.BR io_uring_prep_msg_ring_fd (3)
-prepares an SQE to send a direct file descriptor to another ring. The submission
-queue entry
-.I sqe
-is setup to use the file descriptor
-.IR fd ,
-which must identify a target io_uring context, to send the locally registered
-file descriptor with value
-.I source_fd
-to the destination ring into index
-.I target_fd
-and passing
-.I data
-as the user data in the target CQE with the request modifier flags set by
-.IR flags .
-Currently there are no valid flag modifiers, this field must contain
-.BR 0 .
-
-.BR io_uring_prep_msg_ring_fd_alloc (3)
-is similar to
-.BR io_uring_prep_msg_ring_fd (3) ,
-but doesn't specify a target index for the direct descriptor. Instead, this
-index is allocated in the target ring and returned in the CQE
-.IR res
-field.
-
-.SH RETURN VALUE
-None
-
-.SH ERRORS
-These are the errors that are reported in the CQE
-.I res
-field.
-.TP
-.B -ENOMEM
-The kernel was unable to allocate memory for the request.
-.TP
-.B -EINVAL
-One of the fields set in the SQE was invalid.
-.TP
-.B -EINVAL
-Target ring is identical to the source ring.
-.TP
-.B -EBADFD
-The descriptor passed in
-.I fd
-does not refer to an io_uring file descriptor, or the ring is in a disabled
-state.
-.TP
-.B -EOVERFLOW
-The kernel was unable to fill a CQE on the target ring. This can happen if
-the target CQ ring is in an overflow state and the kernel wasn't able to
-allocate memory for a new CQE entry.
-.TP
-.B -ENFILE
-The direct descriptor table in the target ring was full, no new descriptors
-could be successfully allocated.
diff --git a/man/io_uring_prep_msg_ring_fd.3.md b/man/io_uring_prep_msg_ring_fd.3.md
new file mode 100644
index 00000000..03ef5990
--- /dev/null
+++ b/man/io_uring_prep_msg_ring_fd.3.md
@@ -0,0 +1,86 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: Mar 16, 2023
+footer: liburing-2.4
+header: liburing Manual
+section: 3
+title: io_uring_prep_msg_ring_fd
+---
+
+# NAME
+
+io_uring_prep_msg_ring_fd - send a direct descriptor to another ring
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_msg_ring_fd(struct io_uring_sqe * sqe ,
+ int fd ,
+ int source_fd ,
+ int target_fd ,
+ __u64 data ,
+ unsigned int flags );
+
+ void io_uring_prep_msg_ring_fd_alloc(struct io_uring_sqe * sqe ,
+ int fd ,
+ int source_fd ,
+ __u64 data ,
+ unsigned int flags );
+```
+
+# DESCRIPTION
+
+**io_uring_prep_msg_ring_fd**(3) prepares an SQE to send a direct file
+descriptor to another ring. The submission queue entry *sqe* is setup to
+use the file descriptor *fd*, which must identify a target io_uring
+context, to send the locally registered file descriptor with value
+*source_fd* to the destination ring into index *target_fd* and passing
+*data* as the user data in the target CQE with the request modifier
+flags set by *flags*. Currently there are no valid flag modifiers, this
+field must contain **0**.
+
+**io_uring_prep_msg_ring_fd_alloc**(3) is similar to
+**io_uring_prep_msg_ring_fd**(3)**,** but doesn\'t specify a target
+index for the direct descriptor. Instead, this index is allocated in the
+target ring and returned in the CQE *res* field.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+These are the errors that are reported in the CQE *res* field.
+
+**-ENOMEM**
+
+: The kernel was unable to allocate memory for the request.
+
+**-EINVAL**
+
+: One of the fields set in the SQE was invalid.
+
+**-EINVAL**
+
+: Target ring is identical to the source ring.
+
+**-EBADFD**
+
+: The descriptor passed in *fd* does not refer to an io_uring file
+ descriptor, or the ring is in a disabled state.
+
+**-EOVERFLOW**
+
+: The kernel was unable to fill a CQE on the target ring. This can
+ happen if the target CQ ring is in an overflow state and the kernel
+ wasn\'t able to allocate memory for a new CQE entry.
+
+**-ENFILE**
+
+: The direct descriptor table in the target ring was full, no new
+ descriptors could be successfully allocated.
diff --git a/man/io_uring_prep_nop.3 b/man/io_uring_prep_nop.3
deleted file mode 100644
index 81853d77..00000000
--- a/man/io_uring_prep_nop.3
+++ /dev/null
@@ -1,28 +0,0 @@
-.\" Copyright (C) 2022 Samuel Williams
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_nop 3 "October 20, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_nop \- prepare a nop request
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_nop(struct io_uring_sqe *" sqe ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_nop (3)
-function prepares nop (no operation) request. The submission queue entry
-.I sqe
-does not require any additional setup.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-None
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
diff --git a/man/io_uring_prep_nop.3.md b/man/io_uring_prep_nop.3.md
new file mode 100644
index 00000000..6d117cb7
--- /dev/null
+++ b/man/io_uring_prep_nop.3.md
@@ -0,0 +1,41 @@
+.\" Copyright (C) 2022 Samuel Williams
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: October 20, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_nop
+---
+
+# NAME
+
+io_uring_prep_nop - prepare a nop request
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_nop(struct io_uring_sqe * sqe );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_nop**(3) function prepares nop (no operation)
+request. The submission queue entry *sqe* does not require any
+additional setup.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+None
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
diff --git a/man/io_uring_prep_nop128.3 b/man/io_uring_prep_nop128.3
deleted file mode 100644
index 1ff82e9a..00000000
--- a/man/io_uring_prep_nop128.3
+++ /dev/null
@@ -1,30 +0,0 @@
-.\" Copyright (C) 2022 Samuel Williams
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_nop128 3 "October 22, 2025" "liburing-2.13" "liburing Manual"
-.SH NAME
-io_uring_prep_nop128 \- prepare a nop request
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_nop128(struct io_uring_sqe *" sqe ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_nop128 (3)
-function prepares nop (no operation) request for a 128-byte entry. The
-submission queue entry
-.I sqe
-does not require any additional setup.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-None
-.SH SEE ALSO
-.BR io_uring_prep_nop (3),
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
diff --git a/man/io_uring_prep_nop128.3.md b/man/io_uring_prep_nop128.3.md
new file mode 100644
index 00000000..2c38d991
--- /dev/null
+++ b/man/io_uring_prep_nop128.3.md
@@ -0,0 +1,42 @@
+.\" Copyright (C) 2022 Samuel Williams
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: October 22, 2025
+footer: liburing-2.13
+header: liburing Manual
+section: 3
+title: io_uring_prep_nop128
+---
+
+# NAME
+
+io_uring_prep_nop128 - prepare a nop request
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_nop128(struct io_uring_sqe * sqe );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_nop128**(3) function prepares nop (no operation)
+request for a 128-byte entry. The submission queue entry *sqe* does not
+require any additional setup.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+None
+
+# SEE ALSO
+
+**io_uring_prep_nop**(3), **io_uring_get_sqe**(3),
+**io_uring_submit**(3),
diff --git a/man/io_uring_prep_openat.3 b/man/io_uring_prep_openat.3
deleted file mode 100644
index 071a9f83..00000000
--- a/man/io_uring_prep_openat.3
+++ /dev/null
@@ -1,138 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_openat 3 "March 13, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_openat \- prepare an openat request
-.SH SYNOPSIS
-.nf
-.B #include <sys/types.h>
-.B #include <sys/stat.h>
-.B #include <fcntl.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_open(struct io_uring_sqe *" sqe ","
-.BI " const char *" path ","
-.BI " int " flags ","
-.BI " mode_t " mode ");"
-.PP
-.BI "void io_uring_prep_open_direct(struct io_uring_sqe *" sqe ","
-.BI " const char *" path ","
-.BI " int " flags ","
-.BI " mode_t " mode ","
-.BI " unsigned " file_index ");"
-.PP
-.BI "void io_uring_prep_openat(struct io_uring_sqe *" sqe ","
-.BI " int " dfd ","
-.BI " const char *" path ","
-.BI " int " flags ","
-.BI " mode_t " mode ");"
-.PP
-.BI "void io_uring_prep_openat_direct(struct io_uring_sqe *" sqe ","
-.BI " int " dfd ","
-.BI " const char *" path ","
-.BI " int " flags ","
-.BI " mode_t " mode ","
-.BI " unsigned " file_index ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_openat (3)
-function prepares an openat request. The submission queue entry
-.I sqe
-is setup to use the directory file descriptor
-.I dfd
-to start opening a file described by
-.I path
-and using the open flags in
-.I flags
-and using the file mode bits specified in
-.IR mode .
-Similarly
-.BR io_uring_prep_open (3)
-prepares an open request.
-
-If the direct variant is used, the application must first have registered
-a file table using
-.BR io_uring_register_files (3)
-of the appropriate size. Once registered, a direct accept request may use any
-entry in that table and is specified in
-.I file_index
-, as long as it is within the size of the registered table.
-If a specified entry already contains a file, the file will first be removed
-from the table and closed. It's consistent with the behavior of updating an
-existing file with
-.BR io_uring_register_files_update (3).
-
-If
-.B IORING_FILE_INDEX_ALLOC
-is used as the
-.I file_index
-for a direct open, then io_uring will allocate a free direct descriptor in
-the existing table. The allocated descriptor is returned in the CQE
-.I res
-field just like it would be for a non-direct open request. If no more entries
-are available in the direct descriptor table,
-.B -ENFILE
-is returned instead.
-
-Direct descriptors are io_uring private file descriptors. They
-avoid some of the overhead associated with thread shared file tables, and
-can be used in any subsequent io_uring request that takes a file descriptor. To do so,
-.B IOSQE_FIXED_FILE
-must be set in the SQE
-.I flags
-member, and the SQE
-.I fd
-field should use the direct descriptor value rather than the regular file
-descriptor. Direct descriptors are managed like registered files.
-
-The directory file descriptor
-.I dfd
-is always a regular file descriptor.
-
-Note that old kernels don't check the SQE
-.I file_index
-field, which is not a problem for liburing helpers, but users of the raw
-io_uring interface need to zero SQEs to avoid unexpected behavior.
-
-These functions prepare an async
-.BR openat (2)
-or
-.BR open (2)
-request. See that man page for details.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH NOTES
-As with any request that passes in data in a struct, that data must remain
-valid until the request has been successfully submitted. It need not remain
-valid until completion. Once a request has been submitted, the in-kernel
-state is stable. Very early kernels (5.4 and earlier) required state to be
-stable until the completion occurred. Applications can test for this
-behavior by inspecting the
-.B IORING_FEAT_SUBMIT_STABLE
-flag passed back from
-.BR io_uring_queue_init_params (3).
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_register (2),
-.BR openat (2)
diff --git a/man/io_uring_prep_openat.3.md b/man/io_uring_prep_openat.3.md
new file mode 100644
index 00000000..66a76f40
--- /dev/null
+++ b/man/io_uring_prep_openat.3.md
@@ -0,0 +1,117 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 13, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_openat
+---
+
+# NAME
+
+io_uring_prep_openat - prepare an openat request
+
+# SYNOPSIS
+
+``` text
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <liburing.h>
+
+ void io_uring_prep_open(struct io_uring_sqe * sqe ,
+ const char * path ,
+ int flags ,
+ mode_t mode );
+
+ void io_uring_prep_open_direct(struct io_uring_sqe * sqe ,
+ const char * path ,
+ int flags ,
+ mode_t mode ,
+ unsigned file_index );
+
+ void io_uring_prep_openat(struct io_uring_sqe * sqe ,
+ int dfd ,
+ const char * path ,
+ int flags ,
+ mode_t mode );
+
+ void io_uring_prep_openat_direct(struct io_uring_sqe * sqe ,
+ int dfd ,
+ const char * path ,
+ int flags ,
+ mode_t mode ,
+ unsigned file_index );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_openat**(3) function prepares an openat request. The
+submission queue entry *sqe* is setup to use the directory file
+descriptor *dfd* to start opening a file described by *path* and using
+the open flags in *flags* and using the file mode bits specified in
+*mode*. Similarly **io_uring_prep_open**(3) prepares an open request.
+
+If the direct variant is used, the application must first have
+registered a file table using **io_uring_register_files**(3) of the
+appropriate size. Once registered, a direct accept request may use any
+entry in that table and is specified in *file_index* , as long as it is
+within the size of the registered table. If a specified entry already
+contains a file, the file will first be removed from the table and
+closed. It\'s consistent with the behavior of updating an existing file
+with **io_uring_register_files_update**(3).
+
+If **IORING_FILE_INDEX_ALLOC** is used as the *file_index* for a direct
+open, then io_uring will allocate a free direct descriptor in the
+existing table. The allocated descriptor is returned in the CQE *res*
+field just like it would be for a non-direct open request. If no more
+entries are available in the direct descriptor table, **-ENFILE** is
+returned instead.
+
+Direct descriptors are io_uring private file descriptors. They avoid
+some of the overhead associated with thread shared file tables, and can
+be used in any subsequent io_uring request that takes a file descriptor.
+To do so, **IOSQE_FIXED_FILE** must be set in the SQE *flags* member,
+and the SQE *fd* field should use the direct descriptor value rather
+than the regular file descriptor. Direct descriptors are managed like
+registered files.
+
+The directory file descriptor *dfd* is always a regular file descriptor.
+
+Note that old kernels don\'t check the SQE *file_index* field, which is
+not a problem for liburing helpers, but users of the raw io_uring
+interface need to zero SQEs to avoid unexpected behavior.
+
+These functions prepare an async **openat**(2) or **open**(2) request.
+See that man page for details.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# NOTES
+
+As with any request that passes in data in a struct, that data must
+remain valid until the request has been successfully submitted. It need
+not remain valid until completion. Once a request has been submitted,
+the in-kernel state is stable. Very early kernels (5.4 and earlier)
+required state to be stable until the completion occurred. Applications
+can test for this behavior by inspecting the
+**IORING_FEAT_SUBMIT_STABLE** flag passed back from
+**io_uring_queue_init_params**(3).
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_register**(2), **openat**(2)
diff --git a/man/io_uring_prep_openat2.3 b/man/io_uring_prep_openat2.3
deleted file mode 100644
index fe361699..00000000
--- a/man/io_uring_prep_openat2.3
+++ /dev/null
@@ -1,119 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_openat2 3 "March 13, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_openat2 \- prepare an openat2 request
-.SH SYNOPSIS
-.nf
-.B #include <sys/types.h>
-.B #include <sys/stat.h>
-.B #include <fcntl.h>
-.B #include <linux/openat2.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_openat2(struct io_uring_sqe *" sqe ","
-.BI " int " dfd ","
-.BI " const char *" path ","
-.BI " const struct open_how *" how ");"
-.PP
-.BI "void io_uring_prep_openat2_direct(struct io_uring_sqe *" sqe ","
-.BI " int " dfd ","
-.BI " const char *" path ","
-.BI " const struct open_how *" how ","
-.BI " unsigned " file_index ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_openat2 (3)
-function prepares an openat2 request. The submission queue entry
-.I sqe
-is setup to use the directory file descriptor
-.I dfd
-to start opening a file described by
-.I path
-and using the instructions on how to open the file given in
-.IR how .
-
-If the direct variant is used, the application must first have registered
-a file table using
-.BR io_uring_register_files (3)
-of the appropriate size. Once registered, a direct request may use any
-entry in that table and is specified in
-.I file_index
-, as long as it is within the size of the registered table.
-If the specified entry already contains a file, the file will first be removed
-from the table and closed. It's consistent with the behavior of updating an
-existing file with
-.BR io_uring_register_files_update (3).
-
-If
-.B IORING_FILE_INDEX_ALLOC
-is used as the
-.I file_index
-for a direct open, then io_uring will allocate a free direct descriptor in
-the existing table. The allocated descriptor is returned in the CQE
-.I res
-field just like it would be for a non-direct open request. If no more entries
-are available in the direct descriptor table,
-.B -ENFILE
-is returned instead.
-
-Direct descriptors are io_uring private file descriptors. They
-avoid some of the overhead associated with thread shared file tables, and
-can be used in any subsequent io_uring request that takes a file descriptor. To do so,
-.B IOSQE_FIXED_FILE
-must be set in the SQE
-.I flags
-member, and the SQE
-.I fd
-field should use the direct descriptor value rather than the regular file
-descriptor. Direct descriptors are managed like registered files.
-
-The directory file descriptor
-.I dfd
-is always a regular file descriptor.
-
-Note that old kernels don't check the SQE
-.I file_index
-field, which is not a problem for liburing helpers, but users of the raw
-io_uring interface need to zero SQEs to avoid unexpected behavior.
-
-These functions prepare an async
-.BR openat2 (2)
-request. See that man page for details.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH NOTES
-As with any request that passes in data in a struct, that data must remain
-valid until the request has been successfully submitted. It need not remain
-valid until completion. Once a request has been submitted, the in-kernel
-state is stable. Very early kernels (5.4 and earlier) required state to be
-stable until the completion occurred. Applications can test for this
-behavior by inspecting the
-.B IORING_FEAT_SUBMIT_STABLE
-flag passed back from
-.BR io_uring_queue_init_params (3).
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_register (2),
-.BR openat2 (2)
diff --git a/man/io_uring_prep_openat2.3.md b/man/io_uring_prep_openat2.3.md
new file mode 100644
index 00000000..ae1ba6c2
--- /dev/null
+++ b/man/io_uring_prep_openat2.3.md
@@ -0,0 +1,104 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 13, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_openat2
+---
+
+# NAME
+
+io_uring_prep_openat2 - prepare an openat2 request
+
+# SYNOPSIS
+
+``` text
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <linux/openat2.h>
+#include <liburing.h>
+
+ void io_uring_prep_openat2(struct io_uring_sqe * sqe ,
+ int dfd ,
+ const char * path ,
+ const struct open_how * how );
+
+ void io_uring_prep_openat2_direct(struct io_uring_sqe * sqe ,
+ int dfd ,
+ const char * path ,
+ const struct open_how * how ,
+ unsigned file_index );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_openat2**(3) function prepares an openat2 request.
+The submission queue entry *sqe* is setup to use the directory file
+descriptor *dfd* to start opening a file described by *path* and using
+the instructions on how to open the file given in *how*.
+
+If the direct variant is used, the application must first have
+registered a file table using **io_uring_register_files**(3) of the
+appropriate size. Once registered, a direct request may use any entry in
+that table and is specified in *file_index* , as long as it is within
+the size of the registered table. If the specified entry already
+contains a file, the file will first be removed from the table and
+closed. It\'s consistent with the behavior of updating an existing file
+with **io_uring_register_files_update**(3).
+
+If **IORING_FILE_INDEX_ALLOC** is used as the *file_index* for a direct
+open, then io_uring will allocate a free direct descriptor in the
+existing table. The allocated descriptor is returned in the CQE *res*
+field just like it would be for a non-direct open request. If no more
+entries are available in the direct descriptor table, **-ENFILE** is
+returned instead.
+
+Direct descriptors are io_uring private file descriptors. They avoid
+some of the overhead associated with thread shared file tables, and can
+be used in any subsequent io_uring request that takes a file descriptor.
+To do so, **IOSQE_FIXED_FILE** must be set in the SQE *flags* member,
+and the SQE *fd* field should use the direct descriptor value rather
+than the regular file descriptor. Direct descriptors are managed like
+registered files.
+
+The directory file descriptor *dfd* is always a regular file descriptor.
+
+Note that old kernels don\'t check the SQE *file_index* field, which is
+not a problem for liburing helpers, but users of the raw io_uring
+interface need to zero SQEs to avoid unexpected behavior.
+
+These functions prepare an async **openat2**(2) request. See that man
+page for details.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# NOTES
+
+As with any request that passes in data in a struct, that data must
+remain valid until the request has been successfully submitted. It need
+not remain valid until completion. Once a request has been submitted,
+the in-kernel state is stable. Very early kernels (5.4 and earlier)
+required state to be stable until the completion occurred. Applications
+can test for this behavior by inspecting the
+**IORING_FEAT_SUBMIT_STABLE** flag passed back from
+**io_uring_queue_init_params**(3).
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_register**(2), **openat2**(2)
diff --git a/man/io_uring_prep_pipe.3 b/man/io_uring_prep_pipe.3
deleted file mode 100644
index 948f345c..00000000
--- a/man/io_uring_prep_pipe.3
+++ /dev/null
@@ -1,91 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_pipe 3 "April 8, 2025" "liburing-2.10" "liburing Manual"
-.SH NAME
-io_uring_prep_pipe \- prepare a pipe creation request
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_pipe(struct io_uring_sqe *" sqe ","
-.BI " int *" fds ","
-.BI " int " pipe_flags ");"
-.BI "
-.BI "void io_uring_prep_pipe_direct(struct io_uring_sqe *" sqe ","
-.BI " int *" fds ","
-.BI " int " pipe_flags ","
-.BI " unsigned int " file_index ");"
-.PP
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_pipe (3)
-function prepares a pipe creation request. The submission queue entry
-.I sqe
-is setup to create a pipe with the created descriptors being copied to the
-array indicated by
-.I fds
-and using
-.I pipe_flags
-as the pipe creation flags. See
-.BR pipe2(2)
-for details on the flags accepted.
-
-The
-.BR io_uring_prep_pipe_direct (3)
-function works in the same way, however it uses fixed/registered file
-descriptors rather than normal file descriptors. This helper takes an
-additional
-.I file_index
-argument, which can set to either an explicit direct descriptor offset to create
-the two pipe file descriptors at, or it can be set to
-.B IORING_FILE_INDEX_ALLOC
-to let io_uring pick any available descriptors for the read and write side
-of the pipe. If a specific index is given, the read side of the pipe will
-be created at that offset, if free, and the write side will be created at
-the next (+1) index. Both of these must be currently unused, or the
-operation will fail. Also see
-.BR io_uring_prep_accept_direct (3)
-or
-.BR io_uring_prep_socket_direct (3)
-for details on the
-.I file_index
-parameter.
-
-For both the direct and normal file descriptor pipe request, the resulting
-input/read side of the pipe will be stored in
-.I fds[0]
-and the output/write side of the pipe will be stored in
-.I fds[1]
-upon successful completion of this request.
-
-This function prepares an async
-.BR pipe2 (2)
-request. See that man page for details.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR pipe2 (2),
-.BR io_uring_prep_accept_direct (3),
-.BR io_uring_prep_socket_direct (3)
diff --git a/man/io_uring_prep_pipe.3.md b/man/io_uring_prep_pipe.3.md
new file mode 100644
index 00000000..2dc9f00f
--- /dev/null
+++ b/man/io_uring_prep_pipe.3.md
@@ -0,0 +1,76 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: April 8, 2025
+footer: liburing-2.10
+header: liburing Manual
+section: 3
+title: io_uring_prep_pipe
+---
+
+# NAME
+
+io_uring_prep_pipe - prepare a pipe creation request
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_pipe(struct io_uring_sqe * sqe ,
+ int * fds ,
+ int pipe_flags );
+
+ void io_uring_prep_pipe_direct(struct io_uring_sqe * sqe ,
+ int * fds ,
+ int pipe_flags ,
+ unsigned int file_index );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_pipe**(3) function prepares a pipe creation request.
+The submission queue entry *sqe* is setup to create a pipe with the
+created descriptors being copied to the array indicated by *fds* and
+using *pipe_flags* as the pipe creation flags. See **pipe2(2)** for
+details on the flags accepted.
+
+The **io_uring_prep_pipe_direct**(3) function works in the same way,
+however it uses fixed/registered file descriptors rather than normal
+file descriptors. This helper takes an additional *file_index* argument,
+which can set to either an explicit direct descriptor offset to create
+the two pipe file descriptors at, or it can be set to
+**IORING_FILE_INDEX_ALLOC** to let io_uring pick any available
+descriptors for the read and write side of the pipe. If a specific index
+is given, the read side of the pipe will be created at that offset, if
+free, and the write side will be created at the next (+1) index. Both of
+these must be currently unused, or the operation will fail. Also see
+**io_uring_prep_accept_direct**(3) or **io_uring_prep_socket_direct**(3)
+for details on the *file_index* parameter.
+
+For both the direct and normal file descriptor pipe request, the
+resulting input/read side of the pipe will be stored in *fds\[0\]* and
+the output/write side of the pipe will be stored in *fds\[1\]* upon
+successful completion of this request.
+
+This function prepares an async **pipe2**(2) request. See that man page
+for details.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3), **pipe2**(2),
+**io_uring_prep_accept_direct**(3), **io_uring_prep_socket_direct**(3)
diff --git a/man/io_uring_prep_poll_add.3 b/man/io_uring_prep_poll_add.3
deleted file mode 100644
index 82539b9a..00000000
--- a/man/io_uring_prep_poll_add.3
+++ /dev/null
@@ -1,72 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_poll_add 3 "March 12, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_poll_add \- prepare a poll request
-.SH SYNOPSIS
-.nf
-.B #include <poll.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_poll_add(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " unsigned " poll_mask ");"
-.PP
-.BI "void io_uring_prep_poll_multishot(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " unsigned " poll_mask ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_poll_add (3)
-function prepares a poll request. The submission queue entry
-.I sqe
-is setup to use the file descriptor
-.I fd
-that should get polled, with the events desired specified in the
-.I poll_mask
-argument.
-
-The default behavior is a single-shot poll request. When the specified event
-has triggered, a completion CQE is posted and no more events will be generated
-by the poll request.
-.BR io_uring_prep_poll_multishot (3)
-behaves identically in terms of events, but it persists across notifications
-and will repeatedly post notifications for the same registration. A CQE
-posted from a multishot poll request will have
-.B IORING_CQE_F_MORE
-set in the CQE
-.I flags
-member, indicating that the application should expect more completions from
-this request. If the multishot poll request gets terminated or experiences
-an error, this flag will not be set in the CQE. If this happens, the application
-should not expect further CQEs from the original request and must reissue a
-new one if it still wishes to get notifications on this file descriptor.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation, which is a bitmask of the
-events notified. See the
-.BR poll (2)
-man page for details. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR poll (2),
-.BR epoll_ctl (3)
diff --git a/man/io_uring_prep_poll_add.3.md b/man/io_uring_prep_poll_add.3.md
new file mode 100644
index 00000000..34950958
--- /dev/null
+++ b/man/io_uring_prep_poll_add.3.md
@@ -0,0 +1,68 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 12, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_poll_add
+---
+
+# NAME
+
+io_uring_prep_poll_add - prepare a poll request
+
+# SYNOPSIS
+
+``` text
+#include <poll.h>
+#include <liburing.h>
+
+ void io_uring_prep_poll_add(struct io_uring_sqe * sqe ,
+ int fd ,
+ unsigned poll_mask );
+
+ void io_uring_prep_poll_multishot(struct io_uring_sqe * sqe ,
+ int fd ,
+ unsigned poll_mask );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_poll_add**(3) function prepares a poll request. The
+submission queue entry *sqe* is setup to use the file descriptor *fd*
+that should get polled, with the events desired specified in the
+*poll_mask* argument.
+
+The default behavior is a single-shot poll request. When the specified
+event has triggered, a completion CQE is posted and no more events will
+be generated by the poll request. **io_uring_prep_poll_multishot**(3)
+behaves identically in terms of events, but it persists across
+notifications and will repeatedly post notifications for the same
+registration. A CQE posted from a multishot poll request will have
+**IORING_CQE_F_MORE** set in the CQE *flags* member, indicating that the
+application should expect more completions from this request. If the
+multishot poll request gets terminated or experiences an error, this
+flag will not be set in the CQE. If this happens, the application should
+not expect further CQEs from the original request and must reissue a new
+one if it still wishes to get notifications on this file descriptor.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation, which is a
+bitmask of the events notified. See the **poll**(2) man page for
+details. Note that where synchronous system calls will return **-1** on
+failure and set *errno* to the actual error value, io_uring never uses
+*errno*. Instead it returns the negated *errno* directly in the CQE
+*res* field.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3), **poll**(2),
+**epoll_ctl**(3)
diff --git a/man/io_uring_prep_poll_remove.3 b/man/io_uring_prep_poll_remove.3
deleted file mode 100644
index b6f4b263..00000000
--- a/man/io_uring_prep_poll_remove.3
+++ /dev/null
@@ -1,55 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_poll_remove 3 "March 12, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_poll_remove \- prepare a poll deletion request
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_poll_remove(struct io_uring_sqe *" sqe ","
-.BI " __u64 " user_data ");"
-.BI "
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_poll_remove (3)
-function prepares a poll removal request. The submission queue entry
-.I sqe
-is setup to remove a poll request identified by
-.I user_data
-
-Works like
-.BR io_uring_prep_cancel (3)
-except only looks for poll requests. Apart from that, behavior is identical.
-See that man page for specific details.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-These are the errors that are reported in the CQE
-.I res
-field. On success,
-.B 0
-is returned.
-.TP
-.B -ENOENT
-The request identified by
-.I user_data
-could not be located. This could be because it completed before the cancelation
-request was issued, or if an invalid identifier is used.
-.TP
-.B -EINVAL
-One of the fields set in the SQE was invalid.
-.TP
-.B -EALREADY
-The execution state of the request has progressed far enough that cancelation
-is no longer possible. This should normally mean that it will complete shortly,
-either successfully, or interrupted due to the cancelation.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_prep_cancel (3)
diff --git a/man/io_uring_prep_poll_remove.3.md b/man/io_uring_prep_poll_remove.3.md
new file mode 100644
index 00000000..f3491c94
--- /dev/null
+++ b/man/io_uring_prep_poll_remove.3.md
@@ -0,0 +1,66 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 12, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_poll_remove
+---
+
+# NAME
+
+io_uring_prep_poll_remove - prepare a poll deletion request
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_poll_remove(struct io_uring_sqe * sqe ,
+ __u64 user_data );
+
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_poll_remove**(3) function prepares a poll removal
+request. The submission queue entry *sqe* is setup to remove a poll
+request identified by *user_data*
+
+Works like **io_uring_prep_cancel**(3) except only looks for poll
+requests. Apart from that, behavior is identical. See that man page for
+specific details.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+These are the errors that are reported in the CQE *res* field. On
+success, **0** is returned.
+
+**-ENOENT**
+
+: The request identified by *user_data* could not be located. This could
+ be because it completed before the cancelation request was issued, or
+ if an invalid identifier is used.
+
+**-EINVAL**
+
+: One of the fields set in the SQE was invalid.
+
+**-EALREADY**
+
+: The execution state of the request has progressed far enough that
+ cancelation is no longer possible. This should normally mean that it
+ will complete shortly, either successfully, or interrupted due to the
+ cancelation.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_prep_cancel**(3)
diff --git a/man/io_uring_prep_poll_update.3 b/man/io_uring_prep_poll_update.3
deleted file mode 100644
index 41cf7766..00000000
--- a/man/io_uring_prep_poll_update.3
+++ /dev/null
@@ -1,101 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_poll_update 3 "March 12, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_poll_update \- update an existing poll request
-.SH SYNOPSIS
-.nf
-.B #include <poll.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_poll_update(struct io_uring_sqe *" sqe ","
-.BI " __u64 " old_user_data ","
-.BI " __u64 " new_user_data ","
-.BI " unsigned " poll_mask ","
-.BI " unsigned " flags ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_poll_update (3)
-function prepares a poll update request. The submission queue entry
-.I sqe
-is setup to update a poll request identified by
-.IR old_user_data ,
-replacing it with the
-.I new_user_data
-information. The
-.I poll_mask
-arguments contains the new mask to use for the poll request, and
-.I flags
-argument contains modifier flags telling io_uring what fields to update.
-
-The
-.I flags
-modifier flags is a bitmask and may contain and OR'ed mask of:
-.TP
-.B IORING_POLL_UPDATE_EVENTS
-If set, the poll update request will replace the existing events being waited
-for with the ones specified in the
-.I poll_mask
-argument to the function. Note that only the lower 16 bits of events can
-be updated. This includes things like
-.B EPOLLIN
-and
-.B EPOLLOUT .
-Higher order masks/settings are included as internal state, and cannot be
-modified. That includes settings like
-.B EPOLLONESHOT ,
-.B EPOLLEXCLUSIVE ,
-and
-.B EPOLLET .
-If an application wishes to modify these, it must cancel/remove the existing
-poll request and arm a new one.
-.TP
-.B IORING_POLL_UPDATE_USER_DATA
-If set, the poll update request will update the existing user_data of the
-request with the value passed in as the
-.I new_user_data
-argument.
-.TP
-.B IORING_POLL_ADD_MULTI
-If set, this will change the poll request from a singleshot to a multishot
-request. This must be used along with
-.B IORING_POLL_UPDATE_EVENTS
-as the event field must be updated to enable multishot.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-These are the errors that are reported in the CQE
-.I res
-field. On success,
-.B 0
-is returned.
-.TP
-.B -ENOENT
-The request identified by
-.I user_data
-could not be located. This could be because it completed before the cancelation
-request was issued, or if an invalid identifier is used.
-.TP
-.B -EINVAL
-One of the fields set in the SQE was invalid.
-.TP
-.B -EALREADY
-The execution state of the request has progressed far enough that cancelation
-is no longer possible. This should normally mean that it will complete shortly,
-either successfully, or interrupted due to the cancelation.
-.TP
-.B -ECANCELED
-.B IORING_POLL_UPDATE_EVENTS
-was set and an error occurred re-arming the poll request with the new mask.
-The original poll request is terminated if this happens, and that termination
-CQE will contain the reason for the error re-arming.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_prep_poll_add (3),
-.BR io_uring_prep_poll_multishot (3)
diff --git a/man/io_uring_prep_poll_update.3.md b/man/io_uring_prep_poll_update.3.md
new file mode 100644
index 00000000..b64c88bb
--- /dev/null
+++ b/man/io_uring_prep_poll_update.3.md
@@ -0,0 +1,101 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 12, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_poll_update
+---
+
+# NAME
+
+io_uring_prep_poll_update - update an existing poll request
+
+# SYNOPSIS
+
+``` text
+#include <poll.h>
+#include <liburing.h>
+
+ void io_uring_prep_poll_update(struct io_uring_sqe * sqe ,
+ __u64 old_user_data ,
+ __u64 new_user_data ,
+ unsigned poll_mask ,
+ unsigned flags );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_poll_update**(3) function prepares a poll update
+request. The submission queue entry *sqe* is setup to update a poll
+request identified by *old_user_data*, replacing it with the
+*new_user_data* information. The *poll_mask* arguments contains the new
+mask to use for the poll request, and *flags* argument contains modifier
+flags telling io_uring what fields to update.
+
+The *flags* modifier flags is a bitmask and may contain and OR\'ed mask
+of:
+
+**IORING_POLL_UPDATE_EVENTS**
+
+: If set, the poll update request will replace the existing events being
+ waited for with the ones specified in the *poll_mask* argument to the
+ function. Note that only the lower 16 bits of events can be updated.
+ This includes things like **EPOLLIN** and **EPOLLOUT .** Higher order
+ masks/settings are included as internal state, and cannot be modified.
+ That includes settings like **EPOLLONESHOT ,** **EPOLLEXCLUSIVE ,**
+ and **EPOLLET .** If an application wishes to modify these, it must
+ cancel/remove the existing poll request and arm a new one.
+
+**IORING_POLL_UPDATE_USER_DATA**
+
+: If set, the poll update request will update the existing user_data of
+ the request with the value passed in as the *new_user_data* argument.
+
+**IORING_POLL_ADD_MULTI**
+
+: If set, this will change the poll request from a singleshot to a
+ multishot request. This must be used along with
+ **IORING_POLL_UPDATE_EVENTS** as the event field must be updated to
+ enable multishot.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+These are the errors that are reported in the CQE *res* field. On
+success, **0** is returned.
+
+**-ENOENT**
+
+: The request identified by *user_data* could not be located. This could
+ be because it completed before the cancelation request was issued, or
+ if an invalid identifier is used.
+
+**-EINVAL**
+
+: One of the fields set in the SQE was invalid.
+
+**-EALREADY**
+
+: The execution state of the request has progressed far enough that
+ cancelation is no longer possible. This should normally mean that it
+ will complete shortly, either successfully, or interrupted due to the
+ cancelation.
+
+**-ECANCELED**
+
+: **IORING_POLL_UPDATE_EVENTS** was set and an error occurred re-arming
+ the poll request with the new mask. The original poll request is
+ terminated if this happens, and that termination CQE will contain the
+ reason for the error re-arming.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_prep_poll_add**(3), **io_uring_prep_poll_multishot**(3)
diff --git a/man/io_uring_prep_provide_buffers.3 b/man/io_uring_prep_provide_buffers.3
deleted file mode 100644
index ae51c1dc..00000000
--- a/man/io_uring_prep_provide_buffers.3
+++ /dev/null
@@ -1,140 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_provide_buffers 3 "March 13, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_provide_buffers \- prepare a provide buffers request
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_provide_buffers(struct io_uring_sqe *" sqe ","
-.BI " void *" addr ","
-.BI " int " len ","
-.BI " int " nr ","
-.BI " int " bgid ","
-.BI " int " bid ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_provide_buffers (3)
-function prepares a request for providing the kernel with buffers. The
-submission queue entry
-.I sqe
-is setup to consume
-.I nr
-number of
-.I len
-sized buffers starting at
-.I addr
-and identified by the buffer group ID of
-.I bgid
-and numbered sequentially starting at
-.IR bid .
-
-This function sets up a request to provide buffers to the io_uring context
-that can be used by read or receive operations. This is done by filling in
-the SQE
-.I buf_group
-field and setting
-.B IOSQE_BUFFER_SELECT
-in the SQE
-.I flags
-member. If buffer selection is used for a request, no buffer should be provided
-in the address field. Instead, the group ID is set to match one that was
-previously provided to the kernel. The kernel will then select a buffer from
-this group for the IO operation. On successful completion of the IO request,
-the CQE
-.I flags
-field will have
-.B IORING_CQE_F_BUFFER
-set and the selected buffer ID will be indicated by the upper 16-bits of the
-.I flags
-field.
-
-Different buffer group IDs can be used by the application to have different
-sizes or types of buffers available. Once a buffer has been consumed for an
-operation, it is no longer known to io_uring. It must be re-provided if so
-desired or freed by the application if no longer needed.
-
-The buffer IDs are internally tracked from
-.I bid
-and sequentially ascending from that value. If
-.B 16
-buffers are provided and start with an initial
-.I bid
-of 0, then the buffer IDs will range from
-.BR 0..15 .
-The application must be aware of this to make sense of the buffer ID passed
-back in the CQE.
-
-Buffer IDs always range from
-.B 0
-to
-.B 65535 ,
-as there are only 16-bits available in the CQE to pass them back. This range
-is independent of how the buffer group initially got created. Attempting to
-add buffer IDs larger than that, or buffer IDs that will wrap when cast to
-a 16-bit value, will cause the request to fail with
-.B -E2BIG
-or
-.B -EINVAL .
-
-Not all requests support buffer selection, as it only really makes sense for
-requests that receive data from the kernel rather than write or provide data.
-Currently, this mode of operation is supported for any file read or socket
-receive request. Attempting to use
-.B IOSQE_BUFFER_SELECT
-with a command that doesn't support it will result in a CQE
-.I res
-error of
-.BR -EINVAL .
-Buffer selection will work with operations that take a
-.B struct iovec
-as its data destination, but only if 1 iovec is provided.
-.
-.SH RETURN VALUE
-None
-.SH ERRORS
-These are the errors that are reported in the CQE
-.I res
-field. On success,
-.I res
-will contain
-.B 0
-or the number of successfully provided buffers.
-.TP
-.B -ENOMEM
-The kernel was unable to allocate memory for the request.
-.TP
-.B -EINVAL
-One of the fields set in the SQE was invalid.
-.TP
-.B -E2BIG
-The number of buffers provided was too big, or the
-.I bid
-was too big. A max value of
-.B USHRT_MAX
-buffers can be specified.
-.TP
-.B -EFAULT
-Some of the user memory given was invalid for the application.
-.TP
-.B -EOVERFLOW
-The product of
-.I len
-and
-.I nr
-exceed the valid amount or overflowed, or the sum of
-.I addr
-and the length of buffers overflowed.
-.TP
-.B -EBUSY
-Attempt to update a slot that is already used.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_register (2),
-.BR io_uring_prep_remove_buffers (3)
diff --git a/man/io_uring_prep_provide_buffers.3.md b/man/io_uring_prep_provide_buffers.3.md
new file mode 100644
index 00000000..f055f052
--- /dev/null
+++ b/man/io_uring_prep_provide_buffers.3.md
@@ -0,0 +1,116 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 13, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_provide_buffers
+---
+
+# NAME
+
+io_uring_prep_provide_buffers - prepare a provide buffers request
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_provide_buffers(struct io_uring_sqe * sqe ,
+ void * addr ,
+ int len ,
+ int nr ,
+ int bgid ,
+ int bid );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_provide_buffers**(3) function prepares a request for
+providing the kernel with buffers. The submission queue entry *sqe* is
+setup to consume *nr* number of *len* sized buffers starting at *addr*
+and identified by the buffer group ID of *bgid* and numbered
+sequentially starting at *bid*.
+
+This function sets up a request to provide buffers to the io_uring
+context that can be used by read or receive operations. This is done by
+filling in the SQE *buf_group* field and setting **IOSQE_BUFFER_SELECT**
+in the SQE *flags* member. If buffer selection is used for a request, no
+buffer should be provided in the address field. Instead, the group ID is
+set to match one that was previously provided to the kernel. The kernel
+will then select a buffer from this group for the IO operation. On
+successful completion of the IO request, the CQE *flags* field will have
+**IORING_CQE_F_BUFFER** set and the selected buffer ID will be indicated
+by the upper 16-bits of the *flags* field.
+
+Different buffer group IDs can be used by the application to have
+different sizes or types of buffers available. Once a buffer has been
+consumed for an operation, it is no longer known to io_uring. It must be
+re-provided if so desired or freed by the application if no longer
+needed.
+
+The buffer IDs are internally tracked from *bid* and sequentially
+ascending from that value. If **16** buffers are provided and start with
+an initial *bid* of 0, then the buffer IDs will range from **0..15**.
+The application must be aware of this to make sense of the buffer ID
+passed back in the CQE.
+
+Buffer IDs always range from **0** to **65535 ,** as there are only
+16-bits available in the CQE to pass them back. This range is
+independent of how the buffer group initially got created. Attempting to
+add buffer IDs larger than that, or buffer IDs that will wrap when cast
+to a 16-bit value, will cause the request to fail with **-E2BIG** or
+**-EINVAL .**
+
+Not all requests support buffer selection, as it only really makes sense
+for requests that receive data from the kernel rather than write or
+provide data. Currently, this mode of operation is supported for any
+file read or socket receive request. Attempting to use
+**IOSQE_BUFFER_SELECT** with a command that doesn\'t support it will
+result in a CQE *res* error of **-EINVAL**. Buffer selection will work
+with operations that take a **struct iovec** as its data destination,
+but only if 1 iovec is provided.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+These are the errors that are reported in the CQE *res* field. On
+success, *res* will contain **0** or the number of successfully provided
+buffers.
+
+**-ENOMEM**
+
+: The kernel was unable to allocate memory for the request.
+
+**-EINVAL**
+
+: One of the fields set in the SQE was invalid.
+
+**-E2BIG**
+
+: The number of buffers provided was too big, or the *bid* was too big.
+ A max value of **USHRT_MAX** buffers can be specified.
+
+**-EFAULT**
+
+: Some of the user memory given was invalid for the application.
+
+**-EOVERFLOW**
+
+: The product of *len* and *nr* exceed the valid amount or overflowed,
+ or the sum of *addr* and the length of buffers overflowed.
+
+**-EBUSY**
+
+: Attempt to update a slot that is already used.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_register**(2), **io_uring_prep_remove_buffers**(3)
diff --git a/man/io_uring_prep_read.3 b/man/io_uring_prep_read.3
deleted file mode 100644
index 197e960a..00000000
--- a/man/io_uring_prep_read.3
+++ /dev/null
@@ -1,76 +0,0 @@
-.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_read 3 "November 15, 2021" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_prep_read \- prepare I/O read request
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_read(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " void *" buf ","
-.BI " unsigned " nbytes ","
-.BI " __u64 " offset ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_read (3)
-prepares an IO read request. The submission queue entry
-.I sqe
-is setup to use the file descriptor
-.I fd
-to start reading
-.I nbytes
-into the buffer
-.I buf
-at the specified
-.IR offset .
-
-On files that support seeking, if the offset is set to
-.BR -1 ,
-the read operation commences at the file offset, and the file offset is
-incremented by the number of bytes read. See
-.BR read (2)
-for more details. Note that for an async API, reading and updating the
-current file offset may result in unpredictable behavior, unless access
-to the file is serialized. It is not encouraged to use this feature, if it's
-possible to provide the desired IO offset from the application or library.
-
-On files that are not capable of seeking, the offset must be 0 or -1.
-
-After the read has been prepared it can be submitted with one of the submit
-functions.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH NOTES
-This function accepts an unsigned number of bytes, but io_uring_cqe's result
-code is an __s32 value, so in theory a short read with a large enough nbytes
-value could generate an ambiguous return. But the number of bytes actually
-transferred has the same limit as
-.BR read (2)
-so this cannot happen in practice.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_prep_readv (3),
-.BR io_uring_prep_readv2 (3),
-.BR io_uring_submit (3)
diff --git a/man/io_uring_prep_read.3.md b/man/io_uring_prep_read.3.md
new file mode 100644
index 00000000..e6cc9d1f
--- /dev/null
+++ b/man/io_uring_prep_read.3.md
@@ -0,0 +1,72 @@
+.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: November 15, 2021
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_prep_read
+---
+
+# NAME
+
+io_uring_prep_read - prepare I/O read request
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_read(struct io_uring_sqe * sqe ,
+ int fd ,
+ void * buf ,
+ unsigned nbytes ,
+ __u64 offset );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_read**(3) prepares an IO read request. The
+submission queue entry *sqe* is setup to use the file descriptor *fd* to
+start reading *nbytes* into the buffer *buf* at the specified *offset*.
+
+On files that support seeking, if the offset is set to **-1**, the read
+operation commences at the file offset, and the file offset is
+incremented by the number of bytes read. See **read**(2) for more
+details. Note that for an async API, reading and updating the current
+file offset may result in unpredictable behavior, unless access to the
+file is serialized. It is not encouraged to use this feature, if it\'s
+possible to provide the desired IO offset from the application or
+library.
+
+On files that are not capable of seeking, the offset must be 0 or -1.
+
+After the read has been prepared it can be submitted with one of the
+submit functions.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# NOTES
+
+This function accepts an unsigned number of bytes, but io_uring_cqe\'s
+result code is an \_\_s32 value, so in theory a short read with a large
+enough nbytes value could generate an ambiguous return. But the number
+of bytes actually transferred has the same limit as **read**(2) so this
+cannot happen in practice.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_prep_readv**(3),
+**io_uring_prep_readv2**(3), **io_uring_submit**(3)
diff --git a/man/io_uring_prep_read_fixed.3 b/man/io_uring_prep_read_fixed.3
deleted file mode 100644
index c351d092..00000000
--- a/man/io_uring_prep_read_fixed.3
+++ /dev/null
@@ -1,79 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_read_fixed 3 "February 13, 2022" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_prep_read_fixed \- prepare I/O read request with registered buffer
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_read_fixed(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " void *" buf ","
-.BI " unsigned " nbytes ","
-.BI " __u64 " offset ","
-.BI " int " buf_index ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_read_fixed (3)
-prepares an IO read request with a previously registered IO buffer. The
-submission queue entry
-.I sqe
-is setup to use the file descriptor
-.I fd
-to start reading
-.I nbytes
-into the buffer
-.I buf
-at the specified
-.IR offset ,
-and with the buffer matching the registered index of
-.IR buf_index .
-
-This works just like
-.BR io_uring_prep_read (3)
-except it requires the use of buffers that have been registered with
-.BR io_uring_register_buffers (3).
-The
-.I buf
-and
-.I nbytes
-arguments must fall within a region specified by
-.I buf_index
-in the previously registered buffer. The buffer need not be aligned with
-the start of the registered buffer.
-
-After the read has been prepared it can be submitted with one of the submit
-functions.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH NOTES
-This function accepts an unsigned number of bytes, but io_uring_cqe's result
-code is an __s32 value, so in theory a short read with a large enough nbytes
-value could generate an ambiguous return. But the number of bytes actually
-transferred has the same limit as
-.BR read (2)
-so this cannot happen in practice.
-.SH SEE ALSO
-.BR io_uring_prep_read (3),
-.BR io_uring_register_buffers (3)
diff --git a/man/io_uring_prep_read_fixed.3.md b/man/io_uring_prep_read_fixed.3.md
new file mode 100644
index 00000000..ff068e8f
--- /dev/null
+++ b/man/io_uring_prep_read_fixed.3.md
@@ -0,0 +1,71 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: February 13, 2022
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_prep_read_fixed
+---
+
+# NAME
+
+io_uring_prep_read_fixed - prepare I/O read request with registered
+buffer
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_read_fixed(struct io_uring_sqe * sqe ,
+ int fd ,
+ void * buf ,
+ unsigned nbytes ,
+ __u64 offset ,
+ int buf_index );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_read_fixed**(3) prepares an IO read request with a
+previously registered IO buffer. The submission queue entry *sqe* is
+setup to use the file descriptor *fd* to start reading *nbytes* into the
+buffer *buf* at the specified *offset*, and with the buffer matching the
+registered index of *buf_index*.
+
+This works just like **io_uring_prep_read**(3) except it requires the
+use of buffers that have been registered with
+**io_uring_register_buffers**(3). The *buf* and *nbytes* arguments must
+fall within a region specified by *buf_index* in the previously
+registered buffer. The buffer need not be aligned with the start of the
+registered buffer.
+
+After the read has been prepared it can be submitted with one of the
+submit functions.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# NOTES
+
+This function accepts an unsigned number of bytes, but io_uring_cqe\'s
+result code is an \_\_s32 value, so in theory a short read with a large
+enough nbytes value could generate an ambiguous return. But the number
+of bytes actually transferred has the same limit as **read**(2) so this
+cannot happen in practice.
+
+# SEE ALSO
+
+**io_uring_prep_read**(3), **io_uring_register_buffers**(3)
diff --git a/man/io_uring_prep_read_multishot.3 b/man/io_uring_prep_read_multishot.3
deleted file mode 100644
index ebad9346..00000000
--- a/man/io_uring_prep_read_multishot.3
+++ /dev/null
@@ -1,107 +0,0 @@
-.\" Copyright (C) 2023 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_read_multishot 3 "September 12, 2023" "liburing-2.5" "liburing Manual"
-.SH NAME
-io_uring_prep_read_multishot \- prepare I/O read multishot request
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_read_multishot(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " unsigned " nbytes ","
-.BI " __u64 " offset ","
-.BI " int " buf_group ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_read_multishot (3)
-helper prepares an IO read multishot request. The submission queue entry
-.I sqe
-is setup to use the file descriptor
-.I fd
-to start reading
-into a buffer from the provided buffer group with ID
-.I buf_group
-at the specified
-.IR offset .
-
-.I nbytes
-must be set to zero, as the size read will be given by the size of the
-buffers in the indicated buffer group IO.
-
-On files that are not capable of seeking, the offset must be 0 or -1.
-
-If
-.I nbytes
-exceeds the size of the buffers in the specified buffer group, or if
-.I nbytes
-is
-.B 0 ,
-then the size of the buffer in that group will be used for the transfer.
-
-A multishot read request will repeatedly trigger a completion event
-whenever data is available to read from the file. Because of that,
-this type of request can only be used with a file type that is pollable.
-Examples of that include pipes, tun devices, etc. If used with a regular
-file, or a wrong file type in general, the request will fail with
-.B -EBADFD
-in the CQE
-.I res
-field.
-
-Since multishot requests repeatedly trigger completion events as data
-arrives, it must be used with provided buffers. With provided buffers, the
-application provides buffers to io_uring upfront, and then the kernel picks
-a buffer from the specified group in
-.I buf_group
-when the request is ready to transfer data.
-
-A multishot request will persist as long as no errors are encountered
-doing handling of the request. For each CQE posted on behalf of this request,
-the CQE
-.I flags
-will have
-.B IORING_CQE_F_MORE
-set if the application should expect more completions from this request.
-If this flag isn't set, then that signifies termination of the multishot
-read request.
-
-After the read has been prepared it can be submitted with one of the submit
-functions.
-
-Available since 6.7.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-
-This function accepts an unsigned number of bytes, but io_uring_cqe's result
-code is an __s32 value, so in theory a short read with a large enough nbytes
-value could generate an ambiguous return. But the number of bytes actually
-transferred has the same limit as
-.BR read (2)
-so this cannot happen in practice.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_prep_read (3),
-.BR io_uring_buf_ring_init (3)
-.BR io_uring_buf_ring_add (3),
-.BR io_uring_submit (3)
diff --git a/man/io_uring_prep_read_multishot.3.md b/man/io_uring_prep_read_multishot.3.md
new file mode 100644
index 00000000..654aab08
--- /dev/null
+++ b/man/io_uring_prep_read_multishot.3.md
@@ -0,0 +1,92 @@
+.\" Copyright (C) 2023 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: September 12, 2023
+footer: liburing-2.5
+header: liburing Manual
+section: 3
+title: io_uring_prep_read_multishot
+---
+
+# NAME
+
+io_uring_prep_read_multishot - prepare I/O read multishot request
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_read_multishot(struct io_uring_sqe * sqe ,
+ int fd ,
+ unsigned nbytes ,
+ __u64 offset ,
+ int buf_group );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_read_multishot**(3) helper prepares an IO read
+multishot request. The submission queue entry *sqe* is setup to use the
+file descriptor *fd* to start reading into a buffer from the provided
+buffer group with ID *buf_group* at the specified *offset*.
+
+*nbytes* must be set to zero, as the size read will be given by the size
+of the buffers in the indicated buffer group IO.
+
+On files that are not capable of seeking, the offset must be 0 or -1.
+
+If *nbytes* exceeds the size of the buffers in the specified buffer
+group, or if *nbytes* is **0 ,** then the size of the buffer in that
+group will be used for the transfer.
+
+A multishot read request will repeatedly trigger a completion event
+whenever data is available to read from the file. Because of that, this
+type of request can only be used with a file type that is pollable.
+Examples of that include pipes, tun devices, etc. If used with a regular
+file, or a wrong file type in general, the request will fail with
+**-EBADFD** in the CQE *res* field.
+
+Since multishot requests repeatedly trigger completion events as data
+arrives, it must be used with provided buffers. With provided buffers,
+the application provides buffers to io_uring upfront, and then the
+kernel picks a buffer from the specified group in *buf_group* when the
+request is ready to transfer data.
+
+A multishot request will persist as long as no errors are encountered
+doing handling of the request. For each CQE posted on behalf of this
+request, the CQE *flags* will have **IORING_CQE_F_MORE** set if the
+application should expect more completions from this request. If this
+flag isn\'t set, then that signifies termination of the multishot read
+request.
+
+After the read has been prepared it can be submitted with one of the
+submit functions.
+
+Available since 6.7.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+This function accepts an unsigned number of bytes, but io_uring_cqe\'s
+result code is an \_\_s32 value, so in theory a short read with a large
+enough nbytes value could generate an ambiguous return. But the number
+of bytes actually transferred has the same limit as **read**(2) so this
+cannot happen in practice.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_prep_read**(3),
+**io_uring_buf_ring_init**(3) **io_uring_buf_ring_add**(3),
+**io_uring_submit**(3)
diff --git a/man/io_uring_prep_readv.3 b/man/io_uring_prep_readv.3
deleted file mode 100644
index a3693820..00000000
--- a/man/io_uring_prep_readv.3
+++ /dev/null
@@ -1,92 +0,0 @@
-.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_readv 3 "November 15, 2021" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_prep_readv \- prepare vector I/O read request
-.SH SYNOPSIS
-.nf
-.B #include <sys/uio.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_readv(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " const struct iovec *" iovecs ","
-.BI " unsigned " nr_vecs ","
-.BI " __u64 " offset ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_readv (3)
-prepares a vectored IO read request. The submission queue entry
-.I sqe
-is setup to use the file descriptor
-.I fd
-to start reading
-.I nr_vecs
-into the
-.I iovecs
-array at the specified
-.IR offset .
-
-On files that support seeking, if the offset is set to
-.BR -1 ,
-the read operation commences at the file offset, and the file offset is
-incremented by the number of bytes read. See
-.BR read (2)
-for more details. Note that for an async API, reading and updating the
-current file offset may result in unpredictable behavior, unless access
-to the file is serialized. It is not encouraged to use this feature, if it's
-possible to provide the desired IO offset from the application or library.
-
-On files that are not capable of seeking, the offset must be 0 or -1.
-
-After the read has been prepared it can be submitted with one of the submit
-functions.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH NOTES
-Unless an application explicitly needs to pass in more than one iovec, it
-is more efficient to use
-.BR io_uring_prep_read (3)
-rather than this function, as no state has to be maintained for a
-non-vectored IO request.
-As with any request that passes in data in a struct, that data must remain
-valid until the request has been successfully submitted. It need not remain
-valid until completion. Once a request has been submitted, the in-kernel
-state is stable. Very early kernels (5.4 and earlier) required state to be
-stable until the completion occurred. Applications can test for this
-behavior by inspecting the
-.B IORING_FEAT_SUBMIT_STABLE
-flag passed back from
-.BR io_uring_queue_init_params (3).
-
-This function accepts an array of iovec's with a size_t number of bytes each,
-but io_uring_cqe's result code is an __s32 value, so in theory a short read
-with a large enough iov_len value could generate an ambiguous return.
-But the number of bytes actually transferred has the same limit as
-.BR read (2)
-so this cannot happen in practice.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_prep_read (3),
-.BR io_uring_prep_readv2 (3),
-.BR io_uring_submit (3)
diff --git a/man/io_uring_prep_readv.3.md b/man/io_uring_prep_readv.3.md
new file mode 100644
index 00000000..ad02e322
--- /dev/null
+++ b/man/io_uring_prep_readv.3.md
@@ -0,0 +1,86 @@
+.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: November 15, 2021
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_prep_readv
+---
+
+# NAME
+
+io_uring_prep_readv - prepare vector I/O read request
+
+# SYNOPSIS
+
+``` text
+#include <sys/uio.h>
+#include <liburing.h>
+
+ void io_uring_prep_readv(struct io_uring_sqe * sqe ,
+ int fd ,
+ const struct iovec * iovecs ,
+ unsigned nr_vecs ,
+ __u64 offset );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_readv**(3) prepares a vectored IO read request. The
+submission queue entry *sqe* is setup to use the file descriptor *fd* to
+start reading *nr_vecs* into the *iovecs* array at the specified
+*offset*.
+
+On files that support seeking, if the offset is set to **-1**, the read
+operation commences at the file offset, and the file offset is
+incremented by the number of bytes read. See **read**(2) for more
+details. Note that for an async API, reading and updating the current
+file offset may result in unpredictable behavior, unless access to the
+file is serialized. It is not encouraged to use this feature, if it\'s
+possible to provide the desired IO offset from the application or
+library.
+
+On files that are not capable of seeking, the offset must be 0 or -1.
+
+After the read has been prepared it can be submitted with one of the
+submit functions.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# NOTES
+
+Unless an application explicitly needs to pass in more than one iovec,
+it is more efficient to use **io_uring_prep_read**(3) rather than this
+function, as no state has to be maintained for a non-vectored IO
+request. As with any request that passes in data in a struct, that data
+must remain valid until the request has been successfully submitted. It
+need not remain valid until completion. Once a request has been
+submitted, the in-kernel state is stable. Very early kernels (5.4 and
+earlier) required state to be stable until the completion occurred.
+Applications can test for this behavior by inspecting the
+**IORING_FEAT_SUBMIT_STABLE** flag passed back from
+**io_uring_queue_init_params**(3).
+
+This function accepts an array of iovec\'s with a size_t number of bytes
+each, but io_uring_cqe\'s result code is an \_\_s32 value, so in theory
+a short read with a large enough iov_len value could generate an
+ambiguous return. But the number of bytes actually transferred has the
+same limit as **read**(2) so this cannot happen in practice.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_prep_read**(3),
+**io_uring_prep_readv2**(3), **io_uring_submit**(3)
diff --git a/man/io_uring_prep_readv2.3 b/man/io_uring_prep_readv2.3
deleted file mode 100644
index bbdfe7c4..00000000
--- a/man/io_uring_prep_readv2.3
+++ /dev/null
@@ -1,118 +0,0 @@
-.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_readv2 3 "November 15, 2021" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_readv2 \- prepare vector I/O read request with flags
-.SH SYNOPSIS
-.nf
-.B #include <sys/uio.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_readv2(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " const struct iovec *" iovecs ","
-.BI " unsigned " nr_vecs ","
-.BI " __u64 " offset ","
-.BI " int " flags ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_readv2 (3)
-prepares a vectored IO read request. The submission queue entry
-.I sqe
-is setup to use the file descriptor
-.I fd
-to start reading
-.I nr_vecs
-into the
-.I iovecs
-array at the specified
-.IR offset .
-The behavior of the function can be controlled with the
-.I flags
-parameter.
-
-Supported values for
-.I flags
-are:
-.TP
-.B RWF_HIPRI
-High priority request, poll if possible
-.TP
-.B RWF_DSYNC
-per-IO O_DSYNC
-.TP
-.B RWF_SYNC
-per-IO O_SYNC
-.TP
-.B RWF_NOWAIT
-per-IO, return
-.B -EAGAIN
-if operation would block
-.TP
-.B RWF_APPEND
-per-IO O_APPEND
-
-.P
-On files that support seeking, if the offset is set to
-.BR -1 ,
-the read operation commences at the file offset, and the file offset is
-incremented by the number of bytes read. See
-.BR read (2)
-for more details. Note that for an async API, reading and updating the
-current file offset may result in unpredictable behavior, unless access
-to the file is serialized. It is not encouraged to use this feature, if it's
-possible to provide the desired IO offset from the application or library.
-
-On files that are not capable of seeking, the offset must be 0 or -1.
-
-After the read has been prepared, it can be submitted with one of the submit
-functions.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH NOTES
-Unless an application explicitly needs to pass in more than one iovec, it
-is more efficient to use
-.BR io_uring_prep_read (3)
-rather than this function, as no state has to be maintained for a
-non-vectored IO request.
-As with any request that passes in data in a struct, that data must remain
-valid until the request has been successfully submitted. It need not remain
-valid until completion. Once a request has been submitted, the in-kernel
-state is stable. Very early kernels (5.4 and earlier) required state to be
-stable until the completion occurred. Applications can test for this
-behavior by inspecting the
-.B IORING_FEAT_SUBMIT_STABLE
-flag passed back from
-.BR io_uring_queue_init_params (3).
-
-This function accepts an array of iovec's with a size_t number of bytes each,
-but io_uring_cqe's result code is an __s32 value, so in theory a short read
-with a large enough iov_len value could generate an ambiguous return.
-But the number of bytes actually transferred has the same limit as
-.BR read (2)
-so this cannot happen in practice.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_prep_read (3),
-.BR io_uring_prep_readv (3),
-.BR io_uring_submit (3)
diff --git a/man/io_uring_prep_readv2.3.md b/man/io_uring_prep_readv2.3.md
new file mode 100644
index 00000000..a16b59b8
--- /dev/null
+++ b/man/io_uring_prep_readv2.3.md
@@ -0,0 +1,110 @@
+.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: November 15, 2021
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_readv2
+---
+
+# NAME
+
+io_uring_prep_readv2 - prepare vector I/O read request with flags
+
+# SYNOPSIS
+
+``` text
+#include <sys/uio.h>
+#include <liburing.h>
+
+ void io_uring_prep_readv2(struct io_uring_sqe * sqe ,
+ int fd ,
+ const struct iovec * iovecs ,
+ unsigned nr_vecs ,
+ __u64 offset ,
+ int flags );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_readv2**(3) prepares a vectored IO read request. The
+submission queue entry *sqe* is setup to use the file descriptor *fd* to
+start reading *nr_vecs* into the *iovecs* array at the specified
+*offset*. The behavior of the function can be controlled with the
+*flags* parameter.
+
+Supported values for *flags* are:
+
+**RWF_HIPRI**
+
+: High priority request, poll if possible
+
+**RWF_DSYNC**
+
+: per-IO O_DSYNC
+
+**RWF_SYNC**
+
+: per-IO O_SYNC
+
+**RWF_NOWAIT**
+
+: per-IO, return **-EAGAIN** if operation would block
+
+**RWF_APPEND**
+
+: per-IO O_APPEND
+
+On files that support seeking, if the offset is set to **-1**, the read
+operation commences at the file offset, and the file offset is
+incremented by the number of bytes read. See **read**(2) for more
+details. Note that for an async API, reading and updating the current
+file offset may result in unpredictable behavior, unless access to the
+file is serialized. It is not encouraged to use this feature, if it\'s
+possible to provide the desired IO offset from the application or
+library.
+
+On files that are not capable of seeking, the offset must be 0 or -1.
+
+After the read has been prepared, it can be submitted with one of the
+submit functions.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# NOTES
+
+Unless an application explicitly needs to pass in more than one iovec,
+it is more efficient to use **io_uring_prep_read**(3) rather than this
+function, as no state has to be maintained for a non-vectored IO
+request. As with any request that passes in data in a struct, that data
+must remain valid until the request has been successfully submitted. It
+need not remain valid until completion. Once a request has been
+submitted, the in-kernel state is stable. Very early kernels (5.4 and
+earlier) required state to be stable until the completion occurred.
+Applications can test for this behavior by inspecting the
+**IORING_FEAT_SUBMIT_STABLE** flag passed back from
+**io_uring_queue_init_params**(3).
+
+This function accepts an array of iovec\'s with a size_t number of bytes
+each, but io_uring_cqe\'s result code is an \_\_s32 value, so in theory
+a short read with a large enough iov_len value could generate an
+ambiguous return. But the number of bytes actually transferred has the
+same limit as **read**(2) so this cannot happen in practice.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_prep_read**(3),
+**io_uring_prep_readv**(3), **io_uring_submit**(3)
diff --git a/man/io_uring_prep_readv_fixed.3 b/man/io_uring_prep_readv_fixed.3
deleted file mode 100644
index 6812869e..00000000
--- a/man/io_uring_prep_readv_fixed.3
+++ /dev/null
@@ -1,74 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_readv_fixed 3 "January 18, 2025" "liburing-2.10" "liburing Manual"
-.SH NAME
-io_uring_prep_readv_fixed \- prepare a vectored read using fixed buffers
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_readv_fixed(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " const struct iovec *" iovecs ","
-.BI " unsigned " nr_vecs ","
-.BI " __u64 " offset ","
-.BI " int " flags ","
-.BI " int " buf_index ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_readv_fixed (3)
-function prepares a vectored read request using fixed (registered) buffers.
-The submission queue entry
-.I sqe
-is setup to use the file descriptor
-.I fd
-to start reading
-.I nr_vecs
-iovecs from the file position
-.IR offset .
-
-The
-.I iovecs
-argument points to an array of iovec structures describing the read
-buffers. All buffers must be part of the registered buffer set at index
-.IR buf_index ,
-previously registered with
-.BR io_uring_register_buffers (3).
-
-The
-.I flags
-argument can contain any per-request flags, such as
-.B RWF_NOWAIT
-or other flags supported by
-.BR preadv2 (2).
-
-Using fixed buffers avoids the overhead of mapping buffers for each I/O
-operation, improving performance for applications that reuse the same
-buffers.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation, the number of bytes read
-on success. On error, a negative errno value is returned.
-.SH NOTES
-This function accepts an array of iovec's with a size_t number of bytes each,
-but io_uring_cqe's result code is an __s32 value, so in theory a short read
-with a large enough iov_len value could generate an ambiguous return.
-But the number of bytes actually transferred has the same limit as
-.BR read (2)
-so this cannot happen in practice.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_prep_readv (3),
-.BR io_uring_prep_readv2 (3),
-.BR io_uring_prep_read_fixed (3),
-.BR io_uring_prep_writev_fixed (3),
-.BR io_uring_register_buffers (3)
diff --git a/man/io_uring_prep_readv_fixed.3.md b/man/io_uring_prep_readv_fixed.3.md
new file mode 100644
index 00000000..066f69af
--- /dev/null
+++ b/man/io_uring_prep_readv_fixed.3.md
@@ -0,0 +1,72 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 18, 2025
+footer: liburing-2.10
+header: liburing Manual
+section: 3
+title: io_uring_prep_readv_fixed
+---
+
+# NAME
+
+io_uring_prep_readv_fixed - prepare a vectored read using fixed buffers
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_readv_fixed(struct io_uring_sqe * sqe ,
+ int fd ,
+ const struct iovec * iovecs ,
+ unsigned nr_vecs ,
+ __u64 offset ,
+ int flags ,
+ int buf_index );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_readv_fixed**(3) function prepares a vectored read
+request using fixed (registered) buffers. The submission queue entry
+*sqe* is setup to use the file descriptor *fd* to start reading
+*nr_vecs* iovecs from the file position *offset*.
+
+The *iovecs* argument points to an array of iovec structures describing
+the read buffers. All buffers must be part of the registered buffer set
+at index *buf_index*, previously registered with
+**io_uring_register_buffers**(3).
+
+The *flags* argument can contain any per-request flags, such as
+**RWF_NOWAIT** or other flags supported by **preadv2**(2).
+
+Using fixed buffers avoids the overhead of mapping buffers for each I/O
+operation, improving performance for applications that reuse the same
+buffers.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation, the number
+of bytes read on success. On error, a negative errno value is returned.
+
+# NOTES
+
+This function accepts an array of iovec\'s with a size_t number of bytes
+each, but io_uring_cqe\'s result code is an \_\_s32 value, so in theory
+a short read with a large enough iov_len value could generate an
+ambiguous return. But the number of bytes actually transferred has the
+same limit as **read**(2) so this cannot happen in practice.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_prep_readv**(3), **io_uring_prep_readv2**(3),
+**io_uring_prep_read_fixed**(3), **io_uring_prep_writev_fixed**(3),
+**io_uring_register_buffers**(3)
diff --git a/man/io_uring_prep_recv.3 b/man/io_uring_prep_recv.3
deleted file mode 100644
index 509b3552..00000000
--- a/man/io_uring_prep_recv.3
+++ /dev/null
@@ -1,147 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_recv 3 "March 12, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_recv \- prepare a recv request
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_recv(struct io_uring_sqe *" sqe ","
-.BI " int " sockfd ","
-.BI " void *" buf ","
-.BI " size_t " len ","
-.BI " int " flags ");"
-.PP
-.BI "void io_uring_prep_recv_multishot(struct io_uring_sqe *" sqe ","
-.BI " int " sockfd ","
-.BI " void *" buf ","
-.BI " size_t " len ","
-.BI " int " flags ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_recv (3)
-function prepares a recv request. The submission
-queue entry
-.I sqe
-is setup to use the file descriptor
-.I sockfd
-to start receiving the data into the destination buffer
-.I buf
-of size
-.I len
-and with modifier flags
-.IR flags .
-
-This function prepares an async
-.BR recv (2)
-request. See that man page for details on the arguments specified to this
-prep helper.
-
-The multishot version allows the application to issue a single receive request,
-which repeatedly posts a CQE when data is available. Length can either be set
-to 0, in which case there are no limits on how much data a single invocation
-of the receive will transfer, or it can be set to a positive value. If the
-latter is the case, then each trigger invocation of the receive multishot will
-transfer at most length bytes. This can be useful if the ring is handling many
-receive multishot operations on different sockets, to ensure fairness between
-them, particularly when used with bundles. The
-.B IOSQE_BUFFER_SELECT
-flag to be set and no
-.B MSG_WAITALL
-flag to be set.
-Therefore each CQE will take a buffer out of a provided buffer pool for receiving.
-The application should check the flags of each CQE, regardless of its result.
-If a posted CQE does not have the
-.B IORING_CQE_F_MORE
-flag set, then the multishot receive is done and the application must issue a
-new request if it still wishes to receive data from the socket.
-Multishot variants are available since kernel 6.0.
-
-
-After calling this function, additional io_uring internal modifier flags
-may be set in the SQE
-.I ioprio
-field. The following flags are supported:
-.TP
-.B IORING_RECVSEND_POLL_FIRST
-If set, io_uring will assume the socket is currently empty and attempting to
-receive data will be unsuccessful. For this case, io_uring will arm internal
-poll and trigger a receive of the data when the socket has data to be read.
-This initial receive attempt can be wasteful for the case where the socket
-is expected to be empty, setting this flag will bypass the initial receive
-attempt and go straight to arming poll. If poll does indicate that data is
-ready to be received, the operation will proceed.
-
-Can be used with the CQE
-.B IORING_CQE_F_SOCK_NONEMPTY
-flag, which io_uring will set on CQEs after a
-.BR recv (2)
-or
-.BR recvmsg (2)
-operation. If set, the socket still had data to be read after the operation
-completed. Both these flags are available since 5.19.
-
-.TP
-.B IORING_RECVSEND_BUNDLE
-If set and provided buffers are used with
-.B IOSQE_BUFFER_SELECT ,
-the receive operation will attempt to fill multiple buffers with rather than
-just pick a single buffer to fill. To receive multiple buffers in a single
-receive, the buffer group ID set in the SQE must be of the ring provided type.
-If set, the CQE
-.I res
-field indicates the total number of bytes received, and the buffer ID returned
-in the CQE
-.I flags
-field indicates the first buffer in the receive operation. The application must
-process the indicated initial buffer ID and until all
-.I res
-bytes have been seen to know which is the last buffer in the receive operation.
-The buffers consumed will be contiguous from the initial buffer, in the order
-in which they appear in the buffer ring. The CQE struct does not contain
-the position of the buffer in the buffer ring, therefore in order to identify
-buffers contained by the bundle, it is advised to maintain the cached head
-index per buffer ring. This uint16_t index represents the position of the next
-buffer to be consumed within the ring. Upon completion of a receive operation,
-the cached head index should be incremented accordingly.
-Receiving in bundles can improve performance when more than one chunk of
-data is available to receive,
-by eliminating redundant round trips through the networking stack. Receive
-bundles may be used by both single shot and multishot receive operations. Note
-that, internally, bundles rely on the networking stack passing back how much
-data is left in the socket after the initial receive. This means that the
-initial receive may contain less buffers than what is available, with the
-followup receive(s) containing more buffers. Available since 6.10.
-.P
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH NOTES
-Despite accepting a size_t number of bytes, these functions can transfer at most
-INT_MAX bytes per call (the maximum for the underlying syscall interface).
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_buf_ring_init (3),
-.BR io_uring_buf_ring_add (3),
-.BR recv (2)
diff --git a/man/io_uring_prep_recv.3.md b/man/io_uring_prep_recv.3.md
new file mode 100644
index 00000000..39dcdbfe
--- /dev/null
+++ b/man/io_uring_prep_recv.3.md
@@ -0,0 +1,130 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 12, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_recv
+---
+
+# NAME
+
+io_uring_prep_recv - prepare a recv request
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_recv(struct io_uring_sqe * sqe ,
+ int sockfd ,
+ void * buf ,
+ size_t len ,
+ int flags );
+
+ void io_uring_prep_recv_multishot(struct io_uring_sqe * sqe ,
+ int sockfd ,
+ void * buf ,
+ size_t len ,
+ int flags );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_recv**(3) function prepares a recv request. The
+submission queue entry *sqe* is setup to use the file descriptor
+*sockfd* to start receiving the data into the destination buffer *buf*
+of size *len* and with modifier flags *flags*.
+
+This function prepares an async **recv**(2) request. See that man page
+for details on the arguments specified to this prep helper.
+
+The multishot version allows the application to issue a single receive
+request, which repeatedly posts a CQE when data is available. Length can
+either be set to 0, in which case there are no limits on how much data a
+single invocation of the receive will transfer, or it can be set to a
+positive value. If the latter is the case, then each trigger invocation
+of the receive multishot will transfer at most length bytes. This can be
+useful if the ring is handling many receive multishot operations on
+different sockets, to ensure fairness between them, particularly when
+used with bundles. The **IOSQE_BUFFER_SELECT** flag to be set and no
+**MSG_WAITALL** flag to be set. Therefore each CQE will take a buffer
+out of a provided buffer pool for receiving. The application should
+check the flags of each CQE, regardless of its result. If a posted CQE
+does not have the **IORING_CQE_F_MORE** flag set, then the multishot
+receive is done and the application must issue a new request if it still
+wishes to receive data from the socket. Multishot variants are available
+since kernel 6.0.
+
+After calling this function, additional io_uring internal modifier flags
+may be set in the SQE *ioprio* field. The following flags are supported:
+
+**IORING_RECVSEND_POLL_FIRST**
+
+: If set, io_uring will assume the socket is currently empty and
+ attempting to receive data will be unsuccessful. For this case,
+ io_uring will arm internal poll and trigger a receive of the data when
+ the socket has data to be read. This initial receive attempt can be
+ wasteful for the case where the socket is expected to be empty,
+ setting this flag will bypass the initial receive attempt and go
+ straight to arming poll. If poll does indicate that data is ready to
+ be received, the operation will proceed.
+
+ Can be used with the CQE **IORING_CQE_F_SOCK_NONEMPTY** flag, which
+ io_uring will set on CQEs after a **recv**(2) or **recvmsg**(2)
+ operation. If set, the socket still had data to be read after the
+ operation completed. Both these flags are available since 5.19.
+
+**IORING_RECVSEND_BUNDLE**
+
+: If set and provided buffers are used with **IOSQE_BUFFER_SELECT ,**
+ the receive operation will attempt to fill multiple buffers with
+ rather than just pick a single buffer to fill. To receive multiple
+ buffers in a single receive, the buffer group ID set in the SQE must
+ be of the ring provided type. If set, the CQE *res* field indicates
+ the total number of bytes received, and the buffer ID returned in the
+ CQE *flags* field indicates the first buffer in the receive operation.
+ The application must process the indicated initial buffer ID and until
+ all *res* bytes have been seen to know which is the last buffer in the
+ receive operation. The buffers consumed will be contiguous from the
+ initial buffer, in the order in which they appear in the buffer ring.
+ The CQE struct does not contain the position of the buffer in the
+ buffer ring, therefore in order to identify buffers contained by the
+ bundle, it is advised to maintain the cached head index per buffer
+ ring. This uint16_t index represents the position of the next buffer
+ to be consumed within the ring. Upon completion of a receive
+ operation, the cached head index should be incremented accordingly.
+ Receiving in bundles can improve performance when more than one chunk
+ of data is available to receive, by eliminating redundant round trips
+ through the networking stack. Receive bundles may be used by both
+ single shot and multishot receive operations. Note that, internally,
+ bundles rely on the networking stack passing back how much data is
+ left in the socket after the initial receive. This means that the
+ initial receive may contain less buffers than what is available, with
+ the followup receive(s) containing more buffers. Available since 6.10.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# NOTES
+
+Despite accepting a size_t number of bytes, these functions can transfer
+at most INT_MAX bytes per call (the maximum for the underlying syscall
+interface).
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_buf_ring_init**(3), **io_uring_buf_ring_add**(3), **recv**(2)
diff --git a/man/io_uring_prep_recvmsg.3 b/man/io_uring_prep_recvmsg.3
deleted file mode 100644
index 74a0c9ef..00000000
--- a/man/io_uring_prep_recvmsg.3
+++ /dev/null
@@ -1,130 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_recvmsg 3 "March 12, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_recvmsg \- prepare a recvmsg request
-.SH SYNOPSIS
-.nf
-.B #include <sys/types.h>
-.B #include <sys/socket.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_recvmsg(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " struct msghdr *" msg ","
-.BI " unsigned " flags ");"
-.PP
-.BI "void io_uring_prep_recvmsg_multishot(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " struct msghdr *" msg ","
-.BI " unsigned " flags ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_recvmsg (3)
-function prepares a recvmsg request. The submission queue entry
-.I sqe
-is setup to use the file descriptor
-.I fd
-to start receiving the data indicated by
-.I msg
-with the
-.BR recvmsg (2)
-defined flags in the
-.I flags
-argument.
-
-This function prepares an async
-.BR recvmsg (2)
-request. See that man page for details on the arguments specified to this
-prep helper.
-
-The multishot version allows the application to issue a single receive request,
-which repeatedly posts a CQE when data is available. It requires the
-.B IOSQE_BUFFER_SELECT
-flag to be set and no
-.B MSG_WAITALL
-flag to be set.
-Therefore each CQE will take a buffer out of a provided buffer pool for receiving.
-The application should check the flags of each CQE, regardless of its result.
-If a posted CQE does not have the
-.B IORING_CQE_F_MORE
-flag set, then the multishot receive is done and the application must issue a
-new request if it still wishes to receive data from the socket.
-
-Unlike
-.BR recvmsg (2),
-multishot recvmsg will prepend a
-.I struct io_uring_recvmsg_out
-which describes the layout of the rest of the buffer in combination with the initial
-.I struct msghdr
-submitted with the request. See
-.BR io_uring_recvmsg_out (3)
-for more information on accessing the data.
-
-Multishot variants are available since kernel 6.0.
-
-After calling this function, additional io_uring internal modifier flags
-may be set in the SQE
-.I ioprio
-field. The following flags are supported:
-.TP
-.B IORING_RECVSEND_POLL_FIRST
-If set, io_uring will assume the socket is currently empty and attempting to
-receive data will be unsuccessful. For this case, io_uring will arm internal
-poll and trigger a receive of the data when the socket has data to be read.
-This initial receive attempt can be wasteful for the case where the socket
-is expected to be empty, setting this flag will bypass the initial receive
-attempt and go straight to arming poll. If poll does indicate that data is
-ready to be received, the operation will proceed.
-
-Can be used with the CQE
-.B IORING_CQE_F_SOCK_NONEMPTY
-flag, which io_uring will set on CQEs after a
-.BR recv (2)
-or
-.BR recvmsg (2)
-operation. If set, the socket still had data to be read after the operation
-completed. Both these flags are available since 5.19.
-.P
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH NOTES
-As with any request that passes in data in a struct, that data must remain
-valid until the request has been successfully submitted. It need not remain
-valid until completion. Once a request has been submitted, the in-kernel
-state is stable. Very early kernels (5.4 and earlier) required state to be
-stable until the completion occurred. Applications can test for this
-behavior by inspecting the
-.B IORING_FEAT_SUBMIT_STABLE
-flag passed back from
-.BR io_uring_queue_init_params (3).
-
-Despite accepting an array of iovec's with a size_t number of bytes each,
-these functions can transfer at most INT_MAX bytes per call (the maximum
-for the underlying syscall interface).
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_buf_ring_init (3),
-.BR io_uring_buf_ring_add (3),
-.BR recvmsg (2)
diff --git a/man/io_uring_prep_recvmsg.3.md b/man/io_uring_prep_recvmsg.3.md
new file mode 100644
index 00000000..5693b8a7
--- /dev/null
+++ b/man/io_uring_prep_recvmsg.3.md
@@ -0,0 +1,113 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 12, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_recvmsg
+---
+
+# NAME
+
+io_uring_prep_recvmsg - prepare a recvmsg request
+
+# SYNOPSIS
+
+``` text
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <liburing.h>
+
+ void io_uring_prep_recvmsg(struct io_uring_sqe * sqe ,
+ int fd ,
+ struct msghdr * msg ,
+ unsigned flags );
+
+ void io_uring_prep_recvmsg_multishot(struct io_uring_sqe * sqe ,
+ int fd ,
+ struct msghdr * msg ,
+ unsigned flags );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_recvmsg**(3) function prepares a recvmsg request.
+The submission queue entry *sqe* is setup to use the file descriptor
+*fd* to start receiving the data indicated by *msg* with the
+**recvmsg**(2) defined flags in the *flags* argument.
+
+This function prepares an async **recvmsg**(2) request. See that man
+page for details on the arguments specified to this prep helper.
+
+The multishot version allows the application to issue a single receive
+request, which repeatedly posts a CQE when data is available. It
+requires the **IOSQE_BUFFER_SELECT** flag to be set and no
+**MSG_WAITALL** flag to be set. Therefore each CQE will take a buffer
+out of a provided buffer pool for receiving. The application should
+check the flags of each CQE, regardless of its result. If a posted CQE
+does not have the **IORING_CQE_F_MORE** flag set, then the multishot
+receive is done and the application must issue a new request if it still
+wishes to receive data from the socket.
+
+Unlike **recvmsg**(2), multishot recvmsg will prepend a *struct
+io_uring_recvmsg_out* which describes the layout of the rest of the
+buffer in combination with the initial *struct msghdr* submitted with
+the request. See **io_uring_recvmsg_out**(3) for more information on
+accessing the data.
+
+Multishot variants are available since kernel 6.0.
+
+After calling this function, additional io_uring internal modifier flags
+may be set in the SQE *ioprio* field. The following flags are supported:
+
+**IORING_RECVSEND_POLL_FIRST**
+
+: If set, io_uring will assume the socket is currently empty and
+ attempting to receive data will be unsuccessful. For this case,
+ io_uring will arm internal poll and trigger a receive of the data when
+ the socket has data to be read. This initial receive attempt can be
+ wasteful for the case where the socket is expected to be empty,
+ setting this flag will bypass the initial receive attempt and go
+ straight to arming poll. If poll does indicate that data is ready to
+ be received, the operation will proceed.
+
+ Can be used with the CQE **IORING_CQE_F_SOCK_NONEMPTY** flag, which
+ io_uring will set on CQEs after a **recv**(2) or **recvmsg**(2)
+ operation. If set, the socket still had data to be read after the
+ operation completed. Both these flags are available since 5.19.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# NOTES
+
+As with any request that passes in data in a struct, that data must
+remain valid until the request has been successfully submitted. It need
+not remain valid until completion. Once a request has been submitted,
+the in-kernel state is stable. Very early kernels (5.4 and earlier)
+required state to be stable until the completion occurred. Applications
+can test for this behavior by inspecting the
+**IORING_FEAT_SUBMIT_STABLE** flag passed back from
+**io_uring_queue_init_params**(3).
+
+Despite accepting an array of iovec\'s with a size_t number of bytes
+each, these functions can transfer at most INT_MAX bytes per call (the
+maximum for the underlying syscall interface).
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_buf_ring_init**(3), **io_uring_buf_ring_add**(3),
+**recvmsg**(2)
diff --git a/man/io_uring_prep_remove_buffers.3 b/man/io_uring_prep_remove_buffers.3
deleted file mode 100644
index cf4f2264..00000000
--- a/man/io_uring_prep_remove_buffers.3
+++ /dev/null
@@ -1,52 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_remove_buffers 3 "March 13, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_remove_buffers \- prepare a remove buffers request
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_remove_buffers(struct io_uring_sqe *" sqe ","
-.BI " int " nr ","
-.BI " int " bgid ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_remove_buffers (3)
-function prepares a request for removing previously supplied buffers. The
-submission queue entry
-.I sqe
-is setup to remove
-.I nr
-number of buffers from the buffer group ID indicated by
-.IR bgid .
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-These are the errors that are reported in the CQE
-.I res
-field. On success,
-.I res
-will contain the number of successfully removed buffers. On error,
-the following errors can occur.
-.TP
-.B -ENOMEM
-The kernel was unable to allocate memory for the request.
-.TP
-.B -EINVAL
-One of the fields set in the SQE was invalid.
-.TP
-.B -ENOENT
-No buffers exist at the specified
-.I bgid
-buffer group ID.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_register (2),
-.BR io_uring_prep_provide_buffers (3)
diff --git a/man/io_uring_prep_remove_buffers.3.md b/man/io_uring_prep_remove_buffers.3.md
new file mode 100644
index 00000000..724db97d
--- /dev/null
+++ b/man/io_uring_prep_remove_buffers.3.md
@@ -0,0 +1,59 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 13, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_remove_buffers
+---
+
+# NAME
+
+io_uring_prep_remove_buffers - prepare a remove buffers request
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_remove_buffers(struct io_uring_sqe * sqe ,
+ int nr ,
+ int bgid );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_remove_buffers**(3) function prepares a request for
+removing previously supplied buffers. The submission queue entry *sqe*
+is setup to remove *nr* number of buffers from the buffer group ID
+indicated by *bgid*.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+These are the errors that are reported in the CQE *res* field. On
+success, *res* will contain the number of successfully removed buffers.
+On error, the following errors can occur.
+
+**-ENOMEM**
+
+: The kernel was unable to allocate memory for the request.
+
+**-EINVAL**
+
+: One of the fields set in the SQE was invalid.
+
+**-ENOENT**
+
+: No buffers exist at the specified *bgid* buffer group ID.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_register**(2), **io_uring_prep_provide_buffers**(3)
diff --git a/man/io_uring_prep_renameat.3 b/man/io_uring_prep_renameat.3
deleted file mode 100644
index 1ecdc2ab..00000000
--- a/man/io_uring_prep_renameat.3
+++ /dev/null
@@ -1,95 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_renameat 3 "March 13, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_renameat \- prepare a renameat request
-.SH SYNOPSIS
-.nf
-.B #include <fcntl.h>
-.B #include <stdio.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_renameat(struct io_uring_sqe *" sqe ","
-.BI " int " olddirfd ","
-.BI " const char *" oldpath ","
-.BI " int " newdirfd ","
-.BI " const char *" newpath ","
-.BI " unsigned int " flags ");"
-.PP
-.BI "void io_uring_prep_rename(struct io_uring_sqe *" sqe ","
-.BI " const char *" oldpath ","
-.BI " const char *" newpath ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_renameat (3)
-function prepares a renameat request. The submission queue entry
-.I sqe
-is setup to use the old directory file descriptor pointed to by
-.I olddirfd
-and old path pointed to by
-.I oldpath
-with the new directory file descriptor pointed to by
-.I newdirfd
-and the new path pointed to by
-.I newpath
-and using the specified flags in
-.IR flags .
-
-The
-.BR io_uring_prep_rename (3)
-function prepares a rename request. The submission queue entry
-.I sqe
-is setup to use the old path pointed to by
-.I oldpath
-with the new path pointed to by
-.IR newpath ,
-both relative to the current working directory and using the specified flags in
-.IR flags .
-
-These functions prepare an async
-.BR renameat2 (2)
-or
-.BR rename (2)
-request. If
-.I flags
-is zero, then this call is similar to the
-.BR renameat (2)
-system call. See those man pages for details.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH NOTES
-As with any request that passes in data in a struct, that data must remain
-valid until the request has been successfully submitted. It need not remain
-valid until completion. Once a request has been submitted, the in-kernel
-state is stable. Very early kernels (5.4 and earlier) required state to be
-stable until the completion occurred. Applications can test for this
-behavior by inspecting the
-.B IORING_FEAT_SUBMIT_STABLE
-flag passed back from
-.BR io_uring_queue_init_params (3).
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR renameat (2),
-.BR renameat2 (2),
-.BR rename (2)
diff --git a/man/io_uring_prep_renameat.3.md b/man/io_uring_prep_renameat.3.md
new file mode 100644
index 00000000..0e044703
--- /dev/null
+++ b/man/io_uring_prep_renameat.3.md
@@ -0,0 +1,80 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 13, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_renameat
+---
+
+# NAME
+
+io_uring_prep_renameat - prepare a renameat request
+
+# SYNOPSIS
+
+``` text
+#include <fcntl.h>
+#include <stdio.h>
+#include <liburing.h>
+
+ void io_uring_prep_renameat(struct io_uring_sqe * sqe ,
+ int olddirfd ,
+ const char * oldpath ,
+ int newdirfd ,
+ const char * newpath ,
+ unsigned int flags );
+
+ void io_uring_prep_rename(struct io_uring_sqe * sqe ,
+ const char * oldpath ,
+ const char * newpath );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_renameat**(3) function prepares a renameat request.
+The submission queue entry *sqe* is setup to use the old directory file
+descriptor pointed to by *olddirfd* and old path pointed to by *oldpath*
+with the new directory file descriptor pointed to by *newdirfd* and the
+new path pointed to by *newpath* and using the specified flags in
+*flags*.
+
+The **io_uring_prep_rename**(3) function prepares a rename request. The
+submission queue entry *sqe* is setup to use the old path pointed to by
+*oldpath* with the new path pointed to by *newpath*, both relative to
+the current working directory and using the specified flags in *flags*.
+
+These functions prepare an async **renameat2**(2) or **rename**(2)
+request. If *flags* is zero, then this call is similar to the
+**renameat**(2) system call. See those man pages for details.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# NOTES
+
+As with any request that passes in data in a struct, that data must
+remain valid until the request has been successfully submitted. It need
+not remain valid until completion. Once a request has been submitted,
+the in-kernel state is stable. Very early kernels (5.4 and earlier)
+required state to be stable until the completion occurred. Applications
+can test for this behavior by inspecting the
+**IORING_FEAT_SUBMIT_STABLE** flag passed back from
+**io_uring_queue_init_params**(3).
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3), **renameat**(2),
+**renameat2**(2), **rename**(2)
diff --git a/man/io_uring_prep_send.3 b/man/io_uring_prep_send.3
deleted file mode 100644
index f4470528..00000000
--- a/man/io_uring_prep_send.3
+++ /dev/null
@@ -1,197 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_send 3 "March 12, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_send \- prepare a send request
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_send(struct io_uring_sqe *" sqe ","
-.BI " int " sockfd ","
-.BI " const void *" buf ","
-.BI " size_t " len ","
-.BI " int " flags ");"
-.PP
-.BI "void io_uring_prep_sendto(struct io_uring_sqe *" sqe ","
-.BI " int " sockfd ","
-.BI " const void *" buf ","
-.BI " size_t " len ","
-.BI " int " flags ","
-.BI " const struct sockaddr *" addr ","
-.BI " socklen_t " addrlen ");"
-.PP
-.BI "void io_uring_prep_send_bundle(struct io_uring_sqe *" sqe ","
-.BI " int " sockfd ","
-.BI " size_t " len ","
-.BI " int " flags ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_send (3)
-function prepares a send request. The submission queue entry
-.I sqe
-is setup to use the file descriptor
-.I sockfd
-to start sending the data from
-.I buf
-of size
-.I len
-bytes and with modifier flags
-.IR flags .
-
-After calling this function, additional io_uring internal modifier flags
-may be set in the SQE
-.I ioprio
-field. The following flags are supported:
-.TP
-.B IORING_RECVSEND_POLL_FIRST
-If set, io_uring will assume the socket is currently full and attempting to
-send data will be unsuccessful. For this case, io_uring will arm internal
-poll and trigger a send of the data when the socket has space available.
-If poll does indicate that space is available in the socket, the operation
-will proceed immediately.
-
-.TP
-.B IORING_RECVSEND_BUNDLE
-If set, the send operation will attempt to fill multiple buffers with rather than
-just pick a single buffer to fill. To send multiple buffers in a single
-send, the buffer group ID set in the SQE must be of the ring provided type.
-If set, the CQE
-.I res
-field indicates the total number of bytes sent, and the buffer ID returned
-in the CQE
-.I flags
-field indicates the first buffer in the send operation. The application must
-process the indicated initial buffer ID and until all
-.I res
-bytes have been seen to know which is the last buffer in the send operation.
-The buffers consumed will be contiguous from the initial buffer, in the order
-in which they appear in the buffer ring. The CQE struct does not contain
-the position of the buffer in the buffer ring, therefore in order to identify
-buffers contained by the bundle, it is advised to maintain the cached head
-index per buffer ring. This uint16_t index represents the position of the next
-buffer to be consumed within the ring. Upon completion of a bundle send operation,
-the cached head index should be incremented accordingly.
-Sending in bundles can improve performance when more than one chunk of
-data is available by eliminating redundant round trips through the networking
-stack.
-.TP
-.B IORING_SEND_VECTORIZED
-If set,
-.I addr must point to an array of
-.I struct iovec
-and
-.I len
-must be the number of vectors in that array. This enables use of vectorized IO
-for a normal send operation, rather than needing a sendmsg variant to
-accomplish that.
-.P
-
-Note that using
-.B IOSQE_IO_LINK
-with this request type requires the setting of
-.B MSG_WAITALL
-in the
-.IR flags
-argument, as a short send isn't a considered an error condition without
-that being set.
-
-This function prepares an async
-.BR send (2)
-request. See that man page for details.
-
-The
-.BR io_uring_prep_sendto (3)
-function prepares a sendto request. The submission queue entry
-.I sqe
-is setup to use the file descriptor
-.I sockfd
-to start sending the data from
-.I buf
-of size
-.I len
-bytes and with modifier flags
-.IR flags .
-The destination address is specified by
-.I addr
-and
-.I addrlen
-and must be a valid address for the socket type.
-
-This function prepares an async
-.BR sendto (2)
-request. See that man page for details.
-
-Both of the above send variants may be used with provided buffers, where rather
-than pass a buffer in directly with the request,
-.B IOSQE_BUFFER_SELECT
-is set in the SQE
-.I flags
-field, and additionally a buffer group ID is set in the SQE
-.I buf_group
-field. By using provided buffers with send requests, the application can
-prevent any kind of reordering of the outgoing data which can otherwise
-occur if the application has more than one send request inflight for a single
-socket. This provides better pipelining of data, where previously the app
-needed to manually serialize sends.
-
-The bundle version allows the application to issue a single send request,
-with a buffer group ID given in the SQE
-.I buf_group
-field, which keeps sending from that buffer group until it runs out of buffers.
-As with any other request using provided buffers,
-.B IOSQE_BUFFER_SELECT
-must also be set in the SQE
-.I flags
-before submission. Currently
-.I len
-must be given as
-.B 0
-otherwise the request will be errored with
-.B -EINVAL
-as the result code. Future versions may allow setting
-.I
-to limit the transfer size. A single CQE is posted for the send, with the result
-being how many bytes were sent, on success. When used with provided buffers,
-send or send bundle will contain the starting buffer group ID in the CQE
-.I flags
-field. The number of bytes sent starts from there, and will be in contiguous
-buffer IDs after that. Send bundle, and send with provided buffers in general,
-are available since kernel 6.10, and can be further identified by checking for
-the
-.B IORING_FEAT_SEND_BUF_SELECT
-flag returned in when using
-.BR io_uring_queue_init_params (3)
-to setup the ring.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH NOTES
-Despite accepting a size_t number of bytes, these functions can transfer at most
-INT_MAX bytes per call (the maximum for the underlying syscall interface).
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_buf_ring_init (3),
-.BR io_uring_buf_ring_add (3),
-.BR send (2)
-.BR sendto (2)
diff --git a/man/io_uring_prep_send.3.md b/man/io_uring_prep_send.3.md
new file mode 100644
index 00000000..2d9f4076
--- /dev/null
+++ b/man/io_uring_prep_send.3.md
@@ -0,0 +1,154 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 12, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_send
+---
+
+# NAME
+
+io_uring_prep_send - prepare a send request
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_send(struct io_uring_sqe * sqe ,
+ int sockfd ,
+ const void * buf ,
+ size_t len ,
+ int flags );
+
+ void io_uring_prep_sendto(struct io_uring_sqe * sqe ,
+ int sockfd ,
+ const void * buf ,
+ size_t len ,
+ int flags ,
+ const struct sockaddr * addr ,
+ socklen_t addrlen );
+
+ void io_uring_prep_send_bundle(struct io_uring_sqe * sqe ,
+ int sockfd ,
+ size_t len ,
+ int flags );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_send**(3) function prepares a send request. The
+submission queue entry *sqe* is setup to use the file descriptor
+*sockfd* to start sending the data from *buf* of size *len* bytes and
+with modifier flags *flags*.
+
+After calling this function, additional io_uring internal modifier flags
+may be set in the SQE *ioprio* field. The following flags are supported:
+
+**IORING_RECVSEND_POLL_FIRST**
+
+: If set, io_uring will assume the socket is currently full and
+ attempting to send data will be unsuccessful. For this case, io_uring
+ will arm internal poll and trigger a send of the data when the socket
+ has space available. If poll does indicate that space is available in
+ the socket, the operation will proceed immediately.
+
+**IORING_RECVSEND_BUNDLE**
+
+: If set, the send operation will attempt to fill multiple buffers with
+ rather than just pick a single buffer to fill. To send multiple
+ buffers in a single send, the buffer group ID set in the SQE must be
+ of the ring provided type. If set, the CQE *res* field indicates the
+ total number of bytes sent, and the buffer ID returned in the CQE
+ *flags* field indicates the first buffer in the send operation. The
+ application must process the indicated initial buffer ID and until all
+ *res* bytes have been seen to know which is the last buffer in the
+ send operation. The buffers consumed will be contiguous from the
+ initial buffer, in the order in which they appear in the buffer ring.
+ The CQE struct does not contain the position of the buffer in the
+ buffer ring, therefore in order to identify buffers contained by the
+ bundle, it is advised to maintain the cached head index per buffer
+ ring. This uint16_t index represents the position of the next buffer
+ to be consumed within the ring. Upon completion of a bundle send
+ operation, the cached head index should be incremented accordingly.
+ Sending in bundles can improve performance when more than one chunk of
+ data is available by eliminating redundant round trips through the
+ networking stack.
+
+**IORING_SEND_VECTORIZED**
+
+: If set, *addr must point to an array of* *struct iovec* and *len* must
+ be the number of vectors in that array. This enables use of vectorized
+ IO for a normal send operation, rather than needing a sendmsg variant
+ to accomplish that.
+
+Note that using **IOSQE_IO_LINK** with this request type requires the
+setting of **MSG_WAITALL** in the *flags* argument, as a short send
+isn\'t a considered an error condition without that being set.
+
+This function prepares an async **send**(2) request. See that man page
+for details.
+
+The **io_uring_prep_sendto**(3) function prepares a sendto request. The
+submission queue entry *sqe* is setup to use the file descriptor
+*sockfd* to start sending the data from *buf* of size *len* bytes and
+with modifier flags *flags*. The destination address is specified by
+*addr* and *addrlen* and must be a valid address for the socket type.
+
+This function prepares an async **sendto**(2) request. See that man page
+for details.
+
+Both of the above send variants may be used with provided buffers, where
+rather than pass a buffer in directly with the request,
+**IOSQE_BUFFER_SELECT** is set in the SQE *flags* field, and
+additionally a buffer group ID is set in the SQE *buf_group* field. By
+using provided buffers with send requests, the application can prevent
+any kind of reordering of the outgoing data which can otherwise occur if
+the application has more than one send request inflight for a single
+socket. This provides better pipelining of data, where previously the
+app needed to manually serialize sends.
+
+The bundle version allows the application to issue a single send
+request, with a buffer group ID given in the SQE *buf_group* field,
+which keeps sending from that buffer group until it runs out of buffers.
+As with any other request using provided buffers,
+**IOSQE_BUFFER_SELECT** must also be set in the SQE *flags* before
+submission. Currently *len* must be given as **0** otherwise the request
+will be errored with **-EINVAL** as the result code. Future versions may
+allow setting *to limit the transfer size. A single CQE is posted for
+the send, with the result* being how many bytes were sent, on success.
+When used with provided buffers, send or send bundle will contain the
+starting buffer group ID in the CQE *flags* field. The number of bytes
+sent starts from there, and will be in contiguous buffer IDs after that.
+Send bundle, and send with provided buffers in general, are available
+since kernel 6.10, and can be further identified by checking for the
+**IORING_FEAT_SEND_BUF_SELECT** flag returned in when using
+**io_uring_queue_init_params**(3) to setup the ring.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# NOTES
+
+Despite accepting a size_t number of bytes, these functions can transfer
+at most INT_MAX bytes per call (the maximum for the underlying syscall
+interface).
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_buf_ring_init**(3), **io_uring_buf_ring_add**(3), **send**(2)
+**sendto**(2)
diff --git a/man/io_uring_prep_send_set_addr.3 b/man/io_uring_prep_send_set_addr.3
deleted file mode 100644
index 5adcdbc8..00000000
--- a/man/io_uring_prep_send_set_addr.3
+++ /dev/null
@@ -1,38 +0,0 @@
-.\" Copyright (C) 2023 Rutvik Patel <heyrutvik@gmail.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_send_set_addr 3 "January 23, 2023" "liburing-2.4" "liburing Manual"
-.SH NAME
-io_uring_prep_send_set_addr \- set address details for send requests
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_send_set_addr(struct io_uring_sqe *" sqe ","
-.BI " const struct sockaddr *" dest_addr ","
-.BI " __u16 " addr_len ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_send_set_addr (3)
-function sets a socket destination address specified by
-.I dest_addr
-and its length using
-.I addr_len
-parameters. It can be used once
-.I sqe
-is prepared using any of the
-.BR send (2)
-io_uring helpers. See man pages of
-.BR io_uring_prep_send (3)
-or
-.BR io_uring_prep_send_zc (3).
-.SH RETURN VALUE
-None
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_prep_send (3),
-.BR io_uring_prep_send_zc (3),
-.BR send (2)
diff --git a/man/io_uring_prep_send_set_addr.3.md b/man/io_uring_prep_send_set_addr.3.md
new file mode 100644
index 00000000..cf9bad6c
--- /dev/null
+++ b/man/io_uring_prep_send_set_addr.3.md
@@ -0,0 +1,42 @@
+.\" Copyright (C) 2023 Rutvik Patel <heyrutvik@gmail.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 23, 2023
+footer: liburing-2.4
+header: liburing Manual
+section: 3
+title: io_uring_prep_send_set_addr
+---
+
+# NAME
+
+io_uring_prep_send_set_addr - set address details for send requests
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_send_set_addr(struct io_uring_sqe * sqe ,
+ const struct sockaddr * dest_addr ,
+ __u16 addr_len );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_send_set_addr**(3) function sets a socket
+destination address specified by *dest_addr* and its length using
+*addr_len* parameters. It can be used once *sqe* is prepared using any
+of the **send**(2) io_uring helpers. See man pages of
+**io_uring_prep_send**(3) or **io_uring_prep_send_zc**(3).
+
+# RETURN VALUE
+
+None
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_prep_send**(3),
+**io_uring_prep_send_zc**(3), **send**(2)
diff --git a/man/io_uring_prep_send_zc.3 b/man/io_uring_prep_send_zc.3
deleted file mode 100644
index 8d96f07f..00000000
--- a/man/io_uring_prep_send_zc.3
+++ /dev/null
@@ -1,140 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_send_zc 3 "September 6, 2022" "liburing-2.3" "liburing Manual"
-.SH NAME
-io_uring_prep_send_zc \- prepare a zerocopy send request
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_send_zc(struct io_uring_sqe *" sqe ","
-.BI " int " sockfd ","
-.BI " const void *" buf ","
-.BI " size_t " len ","
-.BI " int " flags ","
-.BI " unsigned " zc_flags ");"
-.PP
-.BI "void io_uring_prep_send_zc_fixed(struct io_uring_sqe *" sqe ","
-.BI " int " sockfd ","
-.BI " const void *" buf ","
-.BI " size_t " len ","
-.BI " int " flags ","
-.BI " unsigned " zc_flags ");"
-.BI " unsigned " buf_index ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_send_zc (3)
-function prepares a zerocopy send request. The submission queue entry
-.I sqe
-is setup to use the file descriptor
-.I sockfd
-to start sending the data from
-.I buf
-of size
-.I len
-bytes with send modifier flags
-.I flags
-and zerocopy modifier flags
-.IR zc_flags .
-
-The
-.BR io_uring_prep_send_zc_fixed (3)
-works just like
-.BR io_uring_prep_send_zc (3)
-except it requires the use of buffers that have been registered with
-.BR io_uring_register_buffers (3).
-The
-.I buf
-and
-.I len
-arguments must fall within a region specified by
-.I buf_index
-in the previously registered buffer. The buffer need not be aligned with the
-start of the registered buffer.
-
-See
-.BR io_uring_prep_send (3)
-for a description of flags that can be set in the SQE
-.I ioprio
-field. In addition to those, the zero-copy send also supports setting
-.B IORING_SEND_ZC_REPORT_USAGE .
-If set, the notification CQE
-.I res
-field will report the number of bytes that were copied rather than sent with
-zero copy. A value of
-.B 0
-indicates success. If the value is
-.B IORING_NOTIF_USAGE_ZC_COPIED ,
-then data was copied.
-
-As opposed to non-zerocopy send requests, a zerocopy send will usually
-generate two CQEs. The first CQE holds the result of the send operation itself,
-and if that CQE has
-.B IORING_CQE_F_MORE
-set in the CQE
-.I flags
-field, then a second notification CQE will be posted for the operation. This
-second notification tells the application that the memory associated with the
-send is safe to get reused. The second CQE will have
-.B IORING_CQE_F_NOTIF
-set in the CQE
-.I flags
-field. Also see the
-.BR io_uring_enter (2)
-man page for a fuller description of the notification CQE.
-
-Note that using
-.B IOSQE_IO_LINK
-with this request type requires the setting of
-.B MSG_WAITALL
-in the
-.I flags
-argument, as a short send isn't considered an error condition without
-that being set.
-
-These functions prepare an async zerocopy
-.BR send (2)
-request. See that man page for details. For details on the zerocopy nature
-of it, see
-.BR io_uring_enter (2) .
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field. Some common error cases are:
-.TP
-.B -ENOMEM
-The
-.BR ulimit (1)
--l setting is too low to support the size of the attempted zero copy send.
-Increasing the limit may help
-.TP
-.B -ENOMEM
-The kernel ran out of memory.
-.P
-.SH NOTES
-Despite accepting a size_t number of bytes, these functions can transfer at most
-INT_MAX bytes per call (the maximum for the underlying syscall interface).
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_prep_send (3),
-.BR io_uring_enter (2),
-.BR send (2)
diff --git a/man/io_uring_prep_send_zc.3.md b/man/io_uring_prep_send_zc.3.md
new file mode 100644
index 00000000..4517f2cc
--- /dev/null
+++ b/man/io_uring_prep_send_zc.3.md
@@ -0,0 +1,110 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: September 6, 2022
+footer: liburing-2.3
+header: liburing Manual
+section: 3
+title: io_uring_prep_send_zc
+---
+
+# NAME
+
+io_uring_prep_send_zc - prepare a zerocopy send request
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_send_zc(struct io_uring_sqe * sqe ,
+ int sockfd ,
+ const void * buf ,
+ size_t len ,
+ int flags ,
+ unsigned zc_flags );
+
+ void io_uring_prep_send_zc_fixed(struct io_uring_sqe * sqe ,
+ int sockfd ,
+ const void * buf ,
+ size_t len ,
+ int flags ,
+ unsigned zc_flags );
+ unsigned buf_index );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_send_zc**(3) function prepares a zerocopy send
+request. The submission queue entry *sqe* is setup to use the file
+descriptor *sockfd* to start sending the data from *buf* of size *len*
+bytes with send modifier flags *flags* and zerocopy modifier flags
+*zc_flags*.
+
+The **io_uring_prep_send_zc_fixed**(3) works just like
+**io_uring_prep_send_zc**(3) except it requires the use of buffers that
+have been registered with **io_uring_register_buffers**(3). The *buf*
+and *len* arguments must fall within a region specified by *buf_index*
+in the previously registered buffer. The buffer need not be aligned with
+the start of the registered buffer.
+
+See **io_uring_prep_send**(3) for a description of flags that can be set
+in the SQE *ioprio* field. In addition to those, the zero-copy send also
+supports setting **IORING_SEND_ZC_REPORT_USAGE .** If set, the
+notification CQE *res* field will report the number of bytes that were
+copied rather than sent with zero copy. A value of **0** indicates
+success. If the value is **IORING_NOTIF_USAGE_ZC_COPIED ,** then data
+was copied.
+
+As opposed to non-zerocopy send requests, a zerocopy send will usually
+generate two CQEs. The first CQE holds the result of the send operation
+itself, and if that CQE has **IORING_CQE_F_MORE** set in the CQE *flags*
+field, then a second notification CQE will be posted for the operation.
+This second notification tells the application that the memory
+associated with the send is safe to get reused. The second CQE will have
+**IORING_CQE_F_NOTIF** set in the CQE *flags* field. Also see the
+**io_uring_enter**(2) man page for a fuller description of the
+notification CQE.
+
+Note that using **IOSQE_IO_LINK** with this request type requires the
+setting of **MSG_WAITALL** in the *flags* argument, as a short send
+isn\'t considered an error condition without that being set.
+
+These functions prepare an async zerocopy **send**(2) request. See that
+man page for details. For details on the zerocopy nature of it, see
+**io_uring_enter**(2)**.**
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field. Some common
+error cases are:
+
+**-ENOMEM**
+
+: The **ulimit**(1) -l setting is too low to support the size of the
+ attempted zero copy send. Increasing the limit may help
+
+**-ENOMEM**
+
+: The kernel ran out of memory.
+
+# NOTES
+
+Despite accepting a size_t number of bytes, these functions can transfer
+at most INT_MAX bytes per call (the maximum for the underlying syscall
+interface).
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_prep_send**(3), **io_uring_enter**(2), **send**(2)
diff --git a/man/io_uring_prep_sendmsg.3 b/man/io_uring_prep_sendmsg.3
deleted file mode 100644
index 7bb7a534..00000000
--- a/man/io_uring_prep_sendmsg.3
+++ /dev/null
@@ -1,136 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_sendmsg 3 "March 12, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_sendmsg \- prepare a sendmsg request
-.SH SYNOPSIS
-.nf
-.B #include <sys/types.h>
-.B #include <sys/socket.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_sendmsg(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " const struct msghdr *" msg ","
-.BI " unsigned " flags ");"
-.PP
-.BI "void io_uring_prep_sendmsg_zc(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " const struct msghdr *" msg ","
-.BI " unsigned " flags ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_sendmsg (3)
-function prepares a sendmsg request. The submission queue entry
-.I sqe
-is setup to use the file descriptor
-.I fd
-to start sending the data indicated by
-.I msg
-with the
-.BR sendmsg (2)
-defined flags in the
-.I flags
-argument.
-
-The
-.BR io_uring_prep_sendmsg_zc (3)
-accepts the same parameters as
-.BR io_uring_prep_sendmsg (3)
-but prepares a zerocopy sendmsg request.
-
-See
-.BR io_uring_prep_send (3)
-for a description of flags that can be set in the SQE
-.I ioprio
-field. In addition to those, the zero-copy send also supports setting
-.B IORING_SEND_ZC_REPORT_USAGE .
-If set, the notification CQE
-.I res
-field will report the number of bytes that were copied rather than sent with
-zero copy. A value of
-.B 0
-indicates success. If the value is
-.B IORING_NOTIF_USAGE_ZC_COPIED ,
-then data was copied.
-
-As opposed to non-zerocopy send requests, a zerocopy send will usually
-generate two CQEs. The first CQE holds the result of the send operation itself,
-and if that CQE has
-.B IORING_CQE_F_MORE
-set in the CQE
-.I flags
-field, then a second notification CQE will be posted for the operation. This
-second notification tells the application that the memory associated with the
-send is safe to get reused. The second CQE will have
-.B IORING_CQE_F_NOTIF
-set in the CQE
-.I flags
-field. Also see the
-.BR io_uring_enter (2)
-man page for a fuller description of the notification CQE.
-
-Note that using
-.B IOSQE_IO_LINK
-with this request type requires the setting of
-.B MSG_WAITALL
-in the
-.I flags
-argument, as a short send isn't considered an error condition without
-that being set.
-
-This function prepares an async
-.BR sendmsg (2)
-request. See that man page for details.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field. Some common error cases are:
-.TP
-.B -ENOMEM
-The
-.BR ulimit (1)
--l setting is too low to support the size of the attempted zero copy send.
-Increasing the limit may help
-.TP
-.B -ENOMEM
-The kernel ran out of memory.
-.P
-.SH NOTES
-As with any request that passes in data in a struct, that data must remain
-valid until the request has been successfully submitted. It need not remain
-valid until completion. Once a request has been submitted, the in-kernel
-state is stable. Very early kernels (5.4 and earlier) required state to be
-stable until the completion occurred. Applications can test for this
-behavior by inspecting the
-.B IORING_FEAT_SUBMIT_STABLE
-flag passed back from
-.BR io_uring_queue_init_params (3).
-
-Despite accepting an array of iovec's with a size_t number of bytes each,
-these functions can transfer at most INT_MAX bytes per call (the maximum
-for the underlying syscall interface).
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_buf_ring_init (3),
-.BR io_uring_buf_ring_add (3),
-.BR sendmsg (2)
diff --git a/man/io_uring_prep_sendmsg.3.md b/man/io_uring_prep_sendmsg.3.md
new file mode 100644
index 00000000..2dbacf93
--- /dev/null
+++ b/man/io_uring_prep_sendmsg.3.md
@@ -0,0 +1,111 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 12, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_sendmsg
+---
+
+# NAME
+
+io_uring_prep_sendmsg - prepare a sendmsg request
+
+# SYNOPSIS
+
+``` text
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <liburing.h>
+
+ void io_uring_prep_sendmsg(struct io_uring_sqe * sqe ,
+ int fd ,
+ const struct msghdr * msg ,
+ unsigned flags );
+
+ void io_uring_prep_sendmsg_zc(struct io_uring_sqe * sqe ,
+ int fd ,
+ const struct msghdr * msg ,
+ unsigned flags );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_sendmsg**(3) function prepares a sendmsg request.
+The submission queue entry *sqe* is setup to use the file descriptor
+*fd* to start sending the data indicated by *msg* with the
+**sendmsg**(2) defined flags in the *flags* argument.
+
+The **io_uring_prep_sendmsg_zc**(3) accepts the same parameters as
+**io_uring_prep_sendmsg**(3) but prepares a zerocopy sendmsg request.
+
+See **io_uring_prep_send**(3) for a description of flags that can be set
+in the SQE *ioprio* field. In addition to those, the zero-copy send also
+supports setting **IORING_SEND_ZC_REPORT_USAGE .** If set, the
+notification CQE *res* field will report the number of bytes that were
+copied rather than sent with zero copy. A value of **0** indicates
+success. If the value is **IORING_NOTIF_USAGE_ZC_COPIED ,** then data
+was copied.
+
+As opposed to non-zerocopy send requests, a zerocopy send will usually
+generate two CQEs. The first CQE holds the result of the send operation
+itself, and if that CQE has **IORING_CQE_F_MORE** set in the CQE *flags*
+field, then a second notification CQE will be posted for the operation.
+This second notification tells the application that the memory
+associated with the send is safe to get reused. The second CQE will have
+**IORING_CQE_F_NOTIF** set in the CQE *flags* field. Also see the
+**io_uring_enter**(2) man page for a fuller description of the
+notification CQE.
+
+Note that using **IOSQE_IO_LINK** with this request type requires the
+setting of **MSG_WAITALL** in the *flags* argument, as a short send
+isn\'t considered an error condition without that being set.
+
+This function prepares an async **sendmsg**(2) request. See that man
+page for details.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field. Some common
+error cases are:
+
+**-ENOMEM**
+
+: The **ulimit**(1) -l setting is too low to support the size of the
+ attempted zero copy send. Increasing the limit may help
+
+**-ENOMEM**
+
+: The kernel ran out of memory.
+
+# NOTES
+
+As with any request that passes in data in a struct, that data must
+remain valid until the request has been successfully submitted. It need
+not remain valid until completion. Once a request has been submitted,
+the in-kernel state is stable. Very early kernels (5.4 and earlier)
+required state to be stable until the completion occurred. Applications
+can test for this behavior by inspecting the
+**IORING_FEAT_SUBMIT_STABLE** flag passed back from
+**io_uring_queue_init_params**(3).
+
+Despite accepting an array of iovec\'s with a size_t number of bytes
+each, these functions can transfer at most INT_MAX bytes per call (the
+maximum for the underlying syscall interface).
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_buf_ring_init**(3), **io_uring_buf_ring_add**(3),
+**sendmsg**(2)
diff --git a/man/io_uring_prep_sendmsg_zc_fixed.3 b/man/io_uring_prep_sendmsg_zc_fixed.3
deleted file mode 100644
index f8baa12b..00000000
--- a/man/io_uring_prep_sendmsg_zc_fixed.3
+++ /dev/null
@@ -1,69 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_sendmsg_zc_fixed 3 "January 18, 2025" "liburing-2.10" "liburing Manual"
-.SH NAME
-io_uring_prep_sendmsg_zc_fixed \- prepare a zero-copy sendmsg using fixed buffers
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_sendmsg_zc_fixed(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " const struct msghdr *" msg ","
-.BI " unsigned " flags ","
-.BI " unsigned " buf_index ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_sendmsg_zc_fixed (3)
-function prepares a zero-copy sendmsg request using fixed (registered)
-buffers. The submission queue entry
-.I sqe
-is setup to send data on the socket indicated by the file descriptor
-.I fd
-using the message structure
-.IR msg .
-
-The
-.I flags
-argument contains flags for the sendmsg operation, as described in
-.BR sendmsg (2).
-
-The
-.I buf_index
-specifies the index of the registered buffer set to use. The buffers in
-.I msg
-must be part of the registered buffer set previously registered with
-.BR io_uring_register_buffers (3).
-
-Zero-copy sends avoid copying data from user to kernel space, improving
-performance for large transfers. Using fixed buffers additionally avoids
-the overhead of mapping buffers for each I/O operation.
-
-Note that zero-copy sends require the application to wait for a notification
-before reusing the buffer. See
-.BR io_uring_prep_send_zc (3)
-for more details on zero-copy semantics.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation, the number of bytes sent
-on success. On error, a negative errno value is returned.
-
-Despite accepting an array of iovec's with a size_t number of bytes each,
-this function can transfer at most INT_MAX bytes per call (the maximum
-for the underlying syscall interface).
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_prep_sendmsg_zc (3),
-.BR io_uring_prep_sendmsg (3),
-.BR io_uring_prep_send_zc_fixed (3),
-.BR io_uring_register_buffers (3),
-.BR sendmsg (2)
diff --git a/man/io_uring_prep_sendmsg_zc_fixed.3.md b/man/io_uring_prep_sendmsg_zc_fixed.3.md
new file mode 100644
index 00000000..9c1641ff
--- /dev/null
+++ b/man/io_uring_prep_sendmsg_zc_fixed.3.md
@@ -0,0 +1,70 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 18, 2025
+footer: liburing-2.10
+header: liburing Manual
+section: 3
+title: io_uring_prep_sendmsg_zc_fixed
+---
+
+# NAME
+
+io_uring_prep_sendmsg_zc_fixed - prepare a zero-copy sendmsg using fixed
+buffers
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_sendmsg_zc_fixed(struct io_uring_sqe * sqe ,
+ int fd ,
+ const struct msghdr * msg ,
+ unsigned flags ,
+ unsigned buf_index );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_sendmsg_zc_fixed**(3) function prepares a zero-copy
+sendmsg request using fixed (registered) buffers. The submission queue
+entry *sqe* is setup to send data on the socket indicated by the file
+descriptor *fd* using the message structure *msg*.
+
+The *flags* argument contains flags for the sendmsg operation, as
+described in **sendmsg**(2).
+
+The *buf_index* specifies the index of the registered buffer set to use.
+The buffers in *msg* must be part of the registered buffer set
+previously registered with **io_uring_register_buffers**(3).
+
+Zero-copy sends avoid copying data from user to kernel space, improving
+performance for large transfers. Using fixed buffers additionally avoids
+the overhead of mapping buffers for each I/O operation.
+
+Note that zero-copy sends require the application to wait for a
+notification before reusing the buffer. See **io_uring_prep_send_zc**(3)
+for more details on zero-copy semantics.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation, the number
+of bytes sent on success. On error, a negative errno value is returned.
+
+Despite accepting an array of iovec\'s with a size_t number of bytes
+each, this function can transfer at most INT_MAX bytes per call (the
+maximum for the underlying syscall interface).
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_prep_sendmsg_zc**(3), **io_uring_prep_sendmsg**(3),
+**io_uring_prep_send_zc_fixed**(3), **io_uring_register_buffers**(3),
+**sendmsg**(2)
diff --git a/man/io_uring_prep_setxattr.3 b/man/io_uring_prep_setxattr.3
deleted file mode 100644
index 5ccff752..00000000
--- a/man/io_uring_prep_setxattr.3
+++ /dev/null
@@ -1,64 +0,0 @@
-.\" Copyright (C) 2023 Rutvik Patel <heyrutvik@gmail.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_setxattr 3 "January 23, 2023" "liburing-2.4" "liburing Manual"
-.SH NAME
-io_uring_prep_setxattr, io_uring_prep_fsetxattr \- prepare a request to set an
-extended attribute value
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_setxattr(struct io_uring_sqe *" sqe ","
-.BI " const char *" name ","
-.BI " const char *" value ","
-.BI " const char *" path ","
-.BI " int " flags ","
-.BI " unsigned int " len ");"
-.PP
-.BI "void io_uring_prep_fsetxattr(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " const char *" name ","
-.BI " const char *" value ","
-.BI " int " flags ","
-.BI " unsigned int " len ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_setxattr (3)
-function prepares a request to set an extended attribute value. The submission
-queue entry
-.I sqe
-is setup to set the
-.I value
-of the extended attribute identified by
-.I name
-and associated with the given
-.I path
-in the filesystem with modifier flags
-.IR flags .
-The
-.I len
-argument specifies the size (in bytes) of
-.IR value .
-
-.BR io_uring_prep_fsetxattr (3)
-is identical to
-.BR io_uring_prep_setxattr (3),
-only the extended attribute is set on the open file referred to by
-.I fd
-in place of
-.IR path .
-
-This function prepares an async
-.BR setxattr (2)
-request. See that man page for details.
-
-.SH RETURN VALUE
-None
-
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR setxattr (2)
diff --git a/man/io_uring_prep_setxattr.3.md b/man/io_uring_prep_setxattr.3.md
new file mode 100644
index 00000000..c1044540
--- /dev/null
+++ b/man/io_uring_prep_setxattr.3.md
@@ -0,0 +1,59 @@
+.\" Copyright (C) 2023 Rutvik Patel <heyrutvik@gmail.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 23, 2023
+footer: liburing-2.4
+header: liburing Manual
+section: 3
+title: io_uring_prep_setxattr
+---
+
+# NAME
+
+io_uring_prep_setxattr, io_uring_prep_fsetxattr - prepare a request to
+set an extended attribute value
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_setxattr(struct io_uring_sqe * sqe ,
+ const char * name ,
+ const char * value ,
+ const char * path ,
+ int flags ,
+ unsigned int len );
+
+ void io_uring_prep_fsetxattr(struct io_uring_sqe * sqe ,
+ int fd ,
+ const char * name ,
+ const char * value ,
+ int flags ,
+ unsigned int len );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_setxattr**(3) function prepares a request to set an
+extended attribute value. The submission queue entry *sqe* is setup to
+set the *value* of the extended attribute identified by *name* and
+associated with the given *path* in the filesystem with modifier flags
+*flags*. The *len* argument specifies the size (in bytes) of *value*.
+
+**io_uring_prep_fsetxattr**(3) is identical to
+**io_uring_prep_setxattr**(3), only the extended attribute is set on the
+open file referred to by *fd* in place of *path*.
+
+This function prepares an async **setxattr**(2) request. See that man
+page for details.
+
+# RETURN VALUE
+
+None
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **setxattr**(2)
diff --git a/man/io_uring_prep_shutdown.3 b/man/io_uring_prep_shutdown.3
deleted file mode 100644
index 9125e95f..00000000
--- a/man/io_uring_prep_shutdown.3
+++ /dev/null
@@ -1,53 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_shutdown 3 "March 12, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_shutdown \- prepare a shutdown request
-.SH SYNOPSIS
-.nf
-.B #include <sys/socket.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_shutdown(struct io_uring_sqe *" sqe ","
-.BI " int " sockfd ","
-.BI " int " how ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_shutdown (3)
-function prepares a shutdown request. The submission queue entry
-.I sqe
-is setup to use the file descriptor
-.I sockfd
-that should be shutdown with the
-.I how
-argument.
-
-This function prepares an async
-.BR shutdown (2)
-request. See that man page for details.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR shutdown (2)
diff --git a/man/io_uring_prep_shutdown.3.md b/man/io_uring_prep_shutdown.3.md
new file mode 100644
index 00000000..be96fe9a
--- /dev/null
+++ b/man/io_uring_prep_shutdown.3.md
@@ -0,0 +1,51 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 12, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_shutdown
+---
+
+# NAME
+
+io_uring_prep_shutdown - prepare a shutdown request
+
+# SYNOPSIS
+
+``` text
+#include <sys/socket.h>
+#include <liburing.h>
+
+ void io_uring_prep_shutdown(struct io_uring_sqe * sqe ,
+ int sockfd ,
+ int how );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_shutdown**(3) function prepares a shutdown request.
+The submission queue entry *sqe* is setup to use the file descriptor
+*sockfd* that should be shutdown with the *how* argument.
+
+This function prepares an async **shutdown**(2) request. See that man
+page for details.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3), **shutdown**(2)
diff --git a/man/io_uring_prep_socket.3 b/man/io_uring_prep_socket.3
deleted file mode 100644
index 77dba66b..00000000
--- a/man/io_uring_prep_socket.3
+++ /dev/null
@@ -1,118 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_socket 3 "May 27, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_socket \- prepare a socket creation request
-.SH SYNOPSIS
-.nf
-.B #include <sys/socket.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_socket(struct io_uring_sqe *" sqe ","
-.BI " int " domain ","
-.BI " int " type ","
-.BI " int " protocol ","
-.BI " unsigned int " flags ");"
-.PP
-.BI "void io_uring_prep_socket_direct(struct io_uring_sqe *" sqe ","
-.BI " int " domain ","
-.BI " int " type ","
-.BI " int " protocol ","
-.BI " unsigned int " file_index ","
-.BI " unsigned int " flags ");"
-.PP
-.BI "void io_uring_prep_socket_direct_alloc(struct io_uring_sqe *" sqe ","
-.BI " int " domain ","
-.BI " int " type ","
-.BI " int " protocol ","
-.BI " unsigned int " flags ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_socket (3)
-function prepares a socket creation request. The submission queue entry
-.I sqe
-is setup to use the communication domain defined by
-.I domain
-and use the communication type defined by
-.I type
-and the protocol set by
-.IR protocol .
-The
-.I flags
-argument are currently unused.
-
-The
-.BR io_uring_prep_socket_direct (3)
-helper works just like
-.BR io_uring_prep_socket (3),
-except it maps the socket to a direct descriptor rather than return a normal
-file descriptor. The
-.I file_index
-argument should be set to the slot that should be used for this socket.
-
-The
-.BR io_uring_prep_socket_direct_alloc (3)
-helper works just like
-.BR io_uring_prep_socket_direct (3),
-except it allocates a new direct descriptor rather than pass a free slot in. It
-is equivalent to using
-.BR io_uring_prep_socket_direct (3)
-with
-.B IORING_FILE_INDEX_ALLOC
-as the
-.I
-file_index .
-Upon completion, the
-.I res
-field of the CQE will return the direct slot that was allocated for the
-socket.
-
-If the direct variants are used, the application must first have registered
-a file table using
-.BR io_uring_register_files (3)
-of the appropriate size. Once registered, a direct socket request may use any
-entry in that table, as long as it is within the size of the registered table.
-If a specified entry already contains a file, the file will first be removed
-from the table and closed. It's consistent with the behavior of updating an
-existing file with
-.BR io_uring_register_files_update (3).
-
-For a direct descriptor socket request, the
-.I file_index
-argument can be set to
-.BR IORING_FILE_INDEX_ALLOC ,
-In this case a free entry in io_uring file table will
-be used automatically and the file index will be returned as CQE
-.IR res .
-.B -ENFILE
-is otherwise returned if there is no free entries in the io_uring file table.
-
-These functions prepare an async
-.BR socket (2)
-request. See that man page for details.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR socket (2)
diff --git a/man/io_uring_prep_socket.3.md b/man/io_uring_prep_socket.3.md
new file mode 100644
index 00000000..a39becdb
--- /dev/null
+++ b/man/io_uring_prep_socket.3.md
@@ -0,0 +1,94 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: May 27, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_socket
+---
+
+# NAME
+
+io_uring_prep_socket - prepare a socket creation request
+
+# SYNOPSIS
+
+``` text
+#include <sys/socket.h>
+#include <liburing.h>
+
+ void io_uring_prep_socket(struct io_uring_sqe * sqe ,
+ int domain ,
+ int type ,
+ int protocol ,
+ unsigned int flags );
+
+ void io_uring_prep_socket_direct(struct io_uring_sqe * sqe ,
+ int domain ,
+ int type ,
+ int protocol ,
+ unsigned int file_index ,
+ unsigned int flags );
+
+ void io_uring_prep_socket_direct_alloc(struct io_uring_sqe * sqe ,
+ int domain ,
+ int type ,
+ int protocol ,
+ unsigned int flags );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_socket**(3) function prepares a socket creation
+request. The submission queue entry *sqe* is setup to use the
+communication domain defined by *domain* and use the communication type
+defined by *type* and the protocol set by *protocol*. The *flags*
+argument are currently unused.
+
+The **io_uring_prep_socket_direct**(3) helper works just like
+**io_uring_prep_socket**(3), except it maps the socket to a direct
+descriptor rather than return a normal file descriptor. The *file_index*
+argument should be set to the slot that should be used for this socket.
+
+The **io_uring_prep_socket_direct_alloc**(3) helper works just like
+**io_uring_prep_socket_direct**(3), except it allocates a new direct
+descriptor rather than pass a free slot in. It is equivalent to using
+**io_uring_prep_socket_direct**(3) with **IORING_FILE_INDEX_ALLOC** as
+the *file_index .* Upon completion, the *res* field of the CQE will
+return the direct slot that was allocated for the socket.
+
+If the direct variants are used, the application must first have
+registered a file table using **io_uring_register_files**(3) of the
+appropriate size. Once registered, a direct socket request may use any
+entry in that table, as long as it is within the size of the registered
+table. If a specified entry already contains a file, the file will first
+be removed from the table and closed. It\'s consistent with the behavior
+of updating an existing file with **io_uring_register_files_update**(3).
+
+For a direct descriptor socket request, the *file_index* argument can be
+set to **IORING_FILE_INDEX_ALLOC**, In this case a free entry in
+io_uring file table will be used automatically and the file index will
+be returned as CQE *res*. **-ENFILE** is otherwise returned if there is
+no free entries in the io_uring file table.
+
+These functions prepare an async **socket**(2) request. See that man
+page for details.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3), **socket**(2)
diff --git a/man/io_uring_prep_splice.3 b/man/io_uring_prep_splice.3
deleted file mode 100644
index b600249f..00000000
--- a/man/io_uring_prep_splice.3
+++ /dev/null
@@ -1,126 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_splice 3 "March 13, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_splice \- prepare an splice request
-.SH SYNOPSIS
-.nf
-.B #include <fcntl.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_splice(struct io_uring_sqe *" sqe ","
-.BI " int " fd_in ","
-.BI " int64_t " off_in ","
-.BI " int " fd_out ","
-.BI " int64_t " off_out ","
-.BI " unsigned int " nbytes ","
-.BI " unsigned int " splice_flags ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_splice (3)
-function prepares a splice request. The submission queue entry
-.I sqe
-is setup to use as input the file descriptor
-.I fd_in
-at offset
-.IR off_in ,
-splicing data to the file descriptor at
-.I fd_out
-and at offset
-.IR off_out .
-.I nbytes
-bytes of data should be spliced between the two descriptors.
-.I splice_flags
-are modifier flags for the operation. See
-.BR splice (2)
-for the generic splice flags.
-
-If
-.I fd_out
-is a direct descriptor,
-.B IOSQE_FIXED_FILE
-can be set in the SQE to indicate that. For the input file, the io_uring
-specific
-.B SPLICE_F_FD_IN_FIXED
-can be set in
-.I splice_flags
-and
-.I fd_in
-given as a registered file descriptor offset.
-
-If
-.I fd_in
-refers to a pipe,
-.I off_in
-is ignored and must be set to -1.
-
-If
-.I fd_in
-does not refer to a pipe and
-.I off_in
-is -1, then
-.I nbytes
-are read from
-.I fd_in
-starting from the file offset, which is incremented by the number of bytes read.
-
-If
-.I fd_in
-does not refer to a pipe and
-.I off_in
-is not -1, then the starting offset of
-.I fd_in
-will be
-.IR off_in .
-
-The same rules apply to
-.I fd_out
-and
-.IR off_out .
-
-This function prepares an async
-.BR splice (2)
-request. See that man page for details.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_register (2),
-.BR splice (2)
-
-.SH NOTES
-Note that even if
-.I fd_in
-or
-.I fd_out
-refers to a pipe, the splice operation can still fail with
-.B EINVAL
-if one of the fd doesn't explicitly support splice operation, e.g. reading from
-terminal is unsupported from kernel 5.7 to 5.11.
-
-Despite accepting an unsigned number of bytes, this function can transfer at most
-INT_MAX bytes per call (the maximum for the underlying syscall interface).
-In practice, limits as low as 65536 have been observed (just like with
-.BR splice (2)
-itself).
diff --git a/man/io_uring_prep_splice.3.md b/man/io_uring_prep_splice.3.md
new file mode 100644
index 00000000..dff5fc82
--- /dev/null
+++ b/man/io_uring_prep_splice.3.md
@@ -0,0 +1,88 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 13, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_splice
+---
+
+# NAME
+
+io_uring_prep_splice - prepare an splice request
+
+# SYNOPSIS
+
+``` text
+#include <fcntl.h>
+#include <liburing.h>
+
+ void io_uring_prep_splice(struct io_uring_sqe * sqe ,
+ int fd_in ,
+ int64_t off_in ,
+ int fd_out ,
+ int64_t off_out ,
+ unsigned int nbytes ,
+ unsigned int splice_flags );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_splice**(3) function prepares a splice request. The
+submission queue entry *sqe* is setup to use as input the file
+descriptor *fd_in* at offset *off_in*, splicing data to the file
+descriptor at *fd_out* and at offset *off_out*. *nbytes* bytes of data
+should be spliced between the two descriptors. *splice_flags* are
+modifier flags for the operation. See **splice**(2) for the generic
+splice flags.
+
+If *fd_out* is a direct descriptor, **IOSQE_FIXED_FILE** can be set in
+the SQE to indicate that. For the input file, the io_uring specific
+**SPLICE_F_FD_IN_FIXED** can be set in *splice_flags* and *fd_in* given
+as a registered file descriptor offset.
+
+If *fd_in* refers to a pipe, *off_in* is ignored and must be set to -1.
+
+If *fd_in* does not refer to a pipe and *off_in* is -1, then *nbytes*
+are read from *fd_in* starting from the file offset, which is
+incremented by the number of bytes read.
+
+If *fd_in* does not refer to a pipe and *off_in* is not -1, then the
+starting offset of *fd_in* will be *off_in*.
+
+The same rules apply to *fd_out* and *off_out*.
+
+This function prepares an async **splice**(2) request. See that man page
+for details.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_register**(2), **splice**(2)
+
+# NOTES
+
+Note that even if *fd_in* or *fd_out* refers to a pipe, the splice
+operation can still fail with **EINVAL** if one of the fd doesn\'t
+explicitly support splice operation, e.g. reading from terminal is
+unsupported from kernel 5.7 to 5.11.
+
+Despite accepting an unsigned number of bytes, this function can
+transfer at most INT_MAX bytes per call (the maximum for the underlying
+syscall interface). In practice, limits as low as 65536 have been
+observed (just like with **splice**(2) itself).
diff --git a/man/io_uring_prep_statx.3 b/man/io_uring_prep_statx.3
deleted file mode 100644
index d9d983a0..00000000
--- a/man/io_uring_prep_statx.3
+++ /dev/null
@@ -1,74 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_statx 3 "March 13, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_statx \- prepare a statx request
-.SH SYNOPSIS
-.nf
-.B #include <sys/types.h>
-.B #include <sys/stat.h>
-.B #include <unistd.h>
-.B #include <fcntl.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_statx(struct io_uring_sqe *" sqe ","
-.BI " int " dirfd ","
-.BI " const char *" path ","
-.BI " int " flags ","
-.BI " unsigned " mask ","
-.BI " struct statx *" statxbuf ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_statx (3)
-function prepares a statx request. The submission queue entry
-.I sqe
-is setup to use the directory file descriptor pointed to by
-.I dirfd
-to start a statx operation on the path identified by
-.I path
-and using the flags given in
-.I flags
-for the fields specified by
-.I mask
-and into the buffer located at
-.IR statxbuf .
-
-This function prepares an async
-.BR statx (2)
-request. See that man page for details.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH NOTES
-As with any request that passes in data in a struct, that data must remain
-valid until the request has been successfully submitted. It need not remain
-valid until completion. Once a request has been submitted, the in-kernel
-state is stable. Very early kernels (5.4 and earlier) required state to be
-stable until the completion occurred. Applications can test for this
-behavior by inspecting the
-.B IORING_FEAT_SUBMIT_STABLE
-flag passed back from
-.BR io_uring_queue_init_params (3).
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR statx (2)
diff --git a/man/io_uring_prep_statx.3.md b/man/io_uring_prep_statx.3.md
new file mode 100644
index 00000000..6d29ae21
--- /dev/null
+++ b/man/io_uring_prep_statx.3.md
@@ -0,0 +1,70 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 13, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_statx
+---
+
+# NAME
+
+io_uring_prep_statx - prepare a statx request
+
+# SYNOPSIS
+
+``` text
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <liburing.h>
+
+ void io_uring_prep_statx(struct io_uring_sqe * sqe ,
+ int dirfd ,
+ const char * path ,
+ int flags ,
+ unsigned mask ,
+ struct statx * statxbuf );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_statx**(3) function prepares a statx request. The
+submission queue entry *sqe* is setup to use the directory file
+descriptor pointed to by *dirfd* to start a statx operation on the path
+identified by *path* and using the flags given in *flags* for the fields
+specified by *mask* and into the buffer located at *statxbuf*.
+
+This function prepares an async **statx**(2) request. See that man page
+for details.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# NOTES
+
+As with any request that passes in data in a struct, that data must
+remain valid until the request has been successfully submitted. It need
+not remain valid until completion. Once a request has been submitted,
+the in-kernel state is stable. Very early kernels (5.4 and earlier)
+required state to be stable until the completion occurred. Applications
+can test for this behavior by inspecting the
+**IORING_FEAT_SUBMIT_STABLE** flag passed back from
+**io_uring_queue_init_params**(3).
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3), **statx**(2)
diff --git a/man/io_uring_prep_symlinkat.3 b/man/io_uring_prep_symlinkat.3
deleted file mode 100644
index b809f938..00000000
--- a/man/io_uring_prep_symlinkat.3
+++ /dev/null
@@ -1,85 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_symlinkat 3 "March 13, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_symlinkat \- prepare a symlinkat request
-.SH SYNOPSIS
-.nf
-.B #include <fcntl.h>
-.B #include <unistd.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_symlinkat(struct io_uring_sqe *" sqe ","
-.BI " const char *" target ","
-.BI " int " newdirfd ","
-.BI " const char *" linkpath ");"
-.PP
-.BI "void io_uring_prep_symlink(struct io_uring_sqe *" sqe ","
-.BI " const char *" target ","
-.BI " const char *" linkpath ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_symlinkat (3)
-function prepares a symlinkat request. The submission queue entry
-.I sqe
-is setup to symlink the target path pointed to by
-.I target
-to the new destination indicated by
-.I newdirfd
-and
-.IR linkpath .
-
-The
-.BR io_uring_prep_symlink (3)
-function prepares a symlink request. The submission queue entry
-.I sqe
-is setup to symlink the target path pointed to by
-.I target
-to the new destination indicated by
-.I linkpath
-relative to the current working directory. This function prepares an async
-.BR symlink (2)
-request. See that man page for details.
-
-These functions prepare an async
-.BR symlinkat (2)
-or
-.BR symlink (2)
-request. See those man pages for details.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH NOTES
-As with any request that passes in data in a struct, that data must remain
-valid until the request has been successfully submitted. It need not remain
-valid until completion. Once a request has been submitted, the in-kernel
-state is stable. Very early kernels (5.4 and earlier) required state to be
-stable until the completion occurred. Applications can test for this
-behavior by inspecting the
-.B IORING_FEAT_SUBMIT_STABLE
-flag passed back from
-.BR io_uring_queue_init_params (3).
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR symlinkat (2),
-.BR symlink (2)
diff --git a/man/io_uring_prep_symlinkat.3.md b/man/io_uring_prep_symlinkat.3.md
new file mode 100644
index 00000000..256508cf
--- /dev/null
+++ b/man/io_uring_prep_symlinkat.3.md
@@ -0,0 +1,76 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 13, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_symlinkat
+---
+
+# NAME
+
+io_uring_prep_symlinkat - prepare a symlinkat request
+
+# SYNOPSIS
+
+``` text
+#include <fcntl.h>
+#include <unistd.h>
+#include <liburing.h>
+
+ void io_uring_prep_symlinkat(struct io_uring_sqe * sqe ,
+ const char * target ,
+ int newdirfd ,
+ const char * linkpath );
+
+ void io_uring_prep_symlink(struct io_uring_sqe * sqe ,
+ const char * target ,
+ const char * linkpath );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_symlinkat**(3) function prepares a symlinkat
+request. The submission queue entry *sqe* is setup to symlink the target
+path pointed to by *target* to the new destination indicated by
+*newdirfd* and *linkpath*.
+
+The **io_uring_prep_symlink**(3) function prepares a symlink request.
+The submission queue entry *sqe* is setup to symlink the target path
+pointed to by *target* to the new destination indicated by *linkpath*
+relative to the current working directory. This function prepares an
+async **symlink**(2) request. See that man page for details.
+
+These functions prepare an async **symlinkat**(2) or **symlink**(2)
+request. See those man pages for details.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# NOTES
+
+As with any request that passes in data in a struct, that data must
+remain valid until the request has been successfully submitted. It need
+not remain valid until completion. Once a request has been submitted,
+the in-kernel state is stable. Very early kernels (5.4 and earlier)
+required state to be stable until the completion occurred. Applications
+can test for this behavior by inspecting the
+**IORING_FEAT_SUBMIT_STABLE** flag passed back from
+**io_uring_queue_init_params**(3).
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3), **symlinkat**(2),
+**symlink**(2)
diff --git a/man/io_uring_prep_sync_file_range.3 b/man/io_uring_prep_sync_file_range.3
deleted file mode 100644
index 830e4115..00000000
--- a/man/io_uring_prep_sync_file_range.3
+++ /dev/null
@@ -1,59 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_sync_file_range 3 "March 12, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_sync_file_range \- prepare a sync_file_range request
-.SH SYNOPSIS
-.nf
-.B #include <fcntl.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_sync_file_range(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " unsigned " len ","
-.BI " __u64 " offset ","
-.BI " int " flags ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_sync_file_range (3)
-function prepares a sync_file_range request. The submission queue entry
-.I sqe
-is setup to use the file descriptor
-.I fd
-that should get
-.I len
-bytes synced started at offset
-.I offset
-and with modifier flags in the
-.I flags
-argument.
-
-This function prepares an async
-.BR sync_file_range (2)
-request. See that man page for details on the arguments.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR sync_file_range (2)
diff --git a/man/io_uring_prep_sync_file_range.3.md b/man/io_uring_prep_sync_file_range.3.md
new file mode 100644
index 00000000..6e91eed3
--- /dev/null
+++ b/man/io_uring_prep_sync_file_range.3.md
@@ -0,0 +1,54 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 12, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_sync_file_range
+---
+
+# NAME
+
+io_uring_prep_sync_file_range - prepare a sync_file_range request
+
+# SYNOPSIS
+
+``` text
+#include <fcntl.h>
+#include <liburing.h>
+
+ void io_uring_prep_sync_file_range(struct io_uring_sqe * sqe ,
+ int fd ,
+ unsigned len ,
+ __u64 offset ,
+ int flags );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_sync_file_range**(3) function prepares a
+sync_file_range request. The submission queue entry *sqe* is setup to
+use the file descriptor *fd* that should get *len* bytes synced started
+at offset *offset* and with modifier flags in the *flags* argument.
+
+This function prepares an async **sync_file_range**(2) request. See that
+man page for details on the arguments.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3), **sync_file_range**(2)
diff --git a/man/io_uring_prep_tee.3 b/man/io_uring_prep_tee.3
deleted file mode 100644
index 10b57737..00000000
--- a/man/io_uring_prep_tee.3
+++ /dev/null
@@ -1,80 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_tee 3 "March 13, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_tee \- prepare a tee request
-.SH SYNOPSIS
-.nf
-.B #include <fcntl.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_tee(struct io_uring_sqe *" sqe ","
-.BI " int " fd_in ","
-.BI " int " fd_out ","
-.BI " unsigned int " nbytes ","
-.BI " unsigned int " splice_flags ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_tee (3)
-function prepares a tee request. The submission queue entry
-.I sqe
-is setup to use as input the file descriptor
-.I fd_in
-and as output the file descriptor
-.I fd_out
-duplicating up to
-.I nbytes
-bytes worth of data.
-.I splice_flags
-are modifier flags for the operation. See
-.BR tee (2)
-for the generic splice flags.
-
-If
-.I fd_out
-is a direct descriptor,
-.B IOSQE_FIXED_FILE
-can be set in the SQE to indicate that. For the input file, the io_uring
-specific
-.B SPLICE_F_FD_IN_FIXED
-can be set and
-.I fd_in
-given as a registered file descriptor offset.
-
-This function prepares an async
-.BR tee (2)
-request. See that man page for details.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH NOTES
-Despite accepting an unsigned number of bytes, this function can transfer at most
-INT_MAX bytes per call (the maximum for the underlying syscall interface).
-In practice, limits as low as 65536 have been observed (just like with
-.BR tee (2)
-itself).
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_register (2),
-.BR splice (2),
-.BR tee (2)
diff --git a/man/io_uring_prep_tee.3.md b/man/io_uring_prep_tee.3.md
new file mode 100644
index 00000000..7be6c2de
--- /dev/null
+++ b/man/io_uring_prep_tee.3.md
@@ -0,0 +1,69 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 13, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_tee
+---
+
+# NAME
+
+io_uring_prep_tee - prepare a tee request
+
+# SYNOPSIS
+
+``` text
+#include <fcntl.h>
+#include <liburing.h>
+
+ void io_uring_prep_tee(struct io_uring_sqe * sqe ,
+ int fd_in ,
+ int fd_out ,
+ unsigned int nbytes ,
+ unsigned int splice_flags );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_tee**(3) function prepares a tee request. The
+submission queue entry *sqe* is setup to use as input the file
+descriptor *fd_in* and as output the file descriptor *fd_out*
+duplicating up to *nbytes* bytes worth of data. *splice_flags* are
+modifier flags for the operation. See **tee**(2) for the generic splice
+flags.
+
+If *fd_out* is a direct descriptor, **IOSQE_FIXED_FILE** can be set in
+the SQE to indicate that. For the input file, the io_uring specific
+**SPLICE_F_FD_IN_FIXED** can be set and *fd_in* given as a registered
+file descriptor offset.
+
+This function prepares an async **tee**(2) request. See that man page
+for details.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# NOTES
+
+Despite accepting an unsigned number of bytes, this function can
+transfer at most INT_MAX bytes per call (the maximum for the underlying
+syscall interface). In practice, limits as low as 65536 have been
+observed (just like with **tee**(2) itself).
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_register**(2), **splice**(2), **tee**(2)
diff --git a/man/io_uring_prep_timeout.3 b/man/io_uring_prep_timeout.3
deleted file mode 100644
index 0c4a44e7..00000000
--- a/man/io_uring_prep_timeout.3
+++ /dev/null
@@ -1,121 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_timeout 3 "March 12, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_timeout \- prepare a timeout request
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_timeout(struct io_uring_sqe *" sqe ","
-.BI " const struct __kernel_timespec *" ts ","
-.BI " unsigned " count ","
-.BI " unsigned " flags ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_timeout (3)
-function prepares a timeout request. The submission queue entry
-.I sqe
-is setup to arm a timeout specified by
-.I ts
-and with a timeout count of
-.I count
-completion entries. The
-.I flags
-argument holds modifier flags for the request.
-
-This request type can be used as a timeout waking anyone sleeping
-for events on the CQ ring. The
-.I flags
-argument may contain:
-.TP
-.B IORING_TIMEOUT_ABS
-The value specified in
-.I ts
-is an absolute value rather than a relative one.
-.TP
-.B IORING_TIMEOUT_BOOTTIME
-The boottime clock source should be used.
-.TP
-.B IORING_TIMEOUT_REALTIME
-The realtime clock source should be used.
-.TP
-.B IORING_TIMEOUT_ETIME_SUCCESS
-Consider an expired timeout a success in terms of the posted completion. This
-means it will not sever dependent links, as a failed request normally would. The
-posted CQE result code will still contain
-.B -ETIME
-in the
-.I res
-value.
-.TP
-.B IORING_TIMEOUT_MULTISHOT
-The request will return multiple timeout completions. The completion flag
-IORING_CQE_F_MORE is set if more timeouts are expected. The value specified in
-.I count
-is the number of repeats. A value of 0 means the timeout is indefinite and can
-only be stopped by a removal request. Available since the 6.4 kernel.
-.TP
-.B IORING_TIMEOUT_IMMEDIATE_ARG
-The timeout value is stored directly in the SQE as a nanosecond value rather
-than as a pointer to a
-.B struct __kernel_timespec.
-When this flag is set, the
-.I ts
-argument to
-.BR io_uring_prep_timeout (3)
-is reinterpreted as a nanosecond value (cast to a
-.BR __u64 )
-rather than a pointer. This avoids the need to keep a timespec structure valid
-in user memory until the request is submitted.
-Available since the 7.1 kernel.
-.PP
-If no alternate clock source is given in the above flags, then
-.B CLOCK_MONOTONIC
-is used.
-
-The timeout completion event will trigger if either the specified timeout
-has occurred, or the specified number of events to wait for have been posted
-to the CQ ring.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-These are the errors that are reported in the CQE
-.I res
-field. On success,
-.B 0
-is returned.
-.TP
-.B -ETIME
-The specified timeout occurred and triggered the completion event.
-.TP
-.B -EINVAL
-One of the fields set in the SQE was invalid. For example, two clocksources
-were given, the specified timeout seconds or nanoseconds were < 0.
-.TP
-.B -EFAULT
-io_uring was unable to access the data specified by
-.IR ts .
-.TP
-.B -ECANCELED
-The timeout was canceled by a removal request.
-.SH NOTES
-As with any request that passes in data in a struct, that data must remain
-valid until the request has been successfully submitted. It need not remain
-valid until completion. Once a request has been submitted, the in-kernel
-state is stable. Very early kernels (5.4 and earlier) required state to be
-stable until the completion occurred. Applications can test for this
-behavior by inspecting the
-.B IORING_FEAT_SUBMIT_STABLE
-flag passed back from
-.BR io_uring_queue_init_params (3).
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_prep_timeout_remove (3),
-.BR io_uring_prep_timeout_update (3)
diff --git a/man/io_uring_prep_timeout.3.md b/man/io_uring_prep_timeout.3.md
new file mode 100644
index 00000000..bf494a77
--- /dev/null
+++ b/man/io_uring_prep_timeout.3.md
@@ -0,0 +1,124 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 12, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_timeout
+---
+
+# NAME
+
+io_uring_prep_timeout - prepare a timeout request
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_timeout(struct io_uring_sqe * sqe ,
+ const struct __kernel_timespec * ts ,
+ unsigned count ,
+ unsigned flags );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_timeout**(3) function prepares a timeout request.
+The submission queue entry *sqe* is setup to arm a timeout specified by
+*ts* and with a timeout count of *count* completion entries. The *flags*
+argument holds modifier flags for the request.
+
+This request type can be used as a timeout waking anyone sleeping for
+events on the CQ ring. The *flags* argument may contain:
+
+**IORING_TIMEOUT_ABS**
+
+: The value specified in *ts* is an absolute value rather than a
+ relative one.
+
+**IORING_TIMEOUT_BOOTTIME**
+
+: The boottime clock source should be used.
+
+**IORING_TIMEOUT_REALTIME**
+
+: The realtime clock source should be used.
+
+**IORING_TIMEOUT_ETIME_SUCCESS**
+
+: Consider an expired timeout a success in terms of the posted
+ completion. This means it will not sever dependent links, as a failed
+ request normally would. The posted CQE result code will still contain
+ **-ETIME** in the *res* value.
+
+**IORING_TIMEOUT_MULTISHOT**
+
+: The request will return multiple timeout completions. The completion
+ flag IORING_CQE_F_MORE is set if more timeouts are expected. The value
+ specified in *count* is the number of repeats. A value of 0 means the
+ timeout is indefinite and can only be stopped by a removal request.
+ Available since the 6.4 kernel.
+
+**IORING_TIMEOUT_IMMEDIATE_ARG**
+
+: The timeout value is stored directly in the SQE as a nanosecond value
+ rather than as a pointer to a **struct \_\_kernel_timespec.** When
+ this flag is set, the *ts* argument to **io_uring_prep_timeout**(3) is
+ reinterpreted as a nanosecond value (cast to a **\_\_u64**) rather
+ than a pointer. This avoids the need to keep a timespec structure
+ valid in user memory until the request is submitted. Available since
+ the 7.1 kernel.
+
+If no alternate clock source is given in the above flags, then
+**CLOCK_MONOTONIC** is used.
+
+The timeout completion event will trigger if either the specified
+timeout has occurred, or the specified number of events to wait for have
+been posted to the CQ ring.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+These are the errors that are reported in the CQE *res* field. On
+success, **0** is returned.
+
+**-ETIME**
+
+: The specified timeout occurred and triggered the completion event.
+
+**-EINVAL**
+
+: One of the fields set in the SQE was invalid. For example, two
+ clocksources were given, the specified timeout seconds or nanoseconds
+ were \< 0.
+
+**-EFAULT**
+
+: io_uring was unable to access the data specified by *ts*.
+
+**-ECANCELED**
+
+: The timeout was canceled by a removal request.
+
+# NOTES
+
+As with any request that passes in data in a struct, that data must
+remain valid until the request has been successfully submitted. It need
+not remain valid until completion. Once a request has been submitted,
+the in-kernel state is stable. Very early kernels (5.4 and earlier)
+required state to be stable until the completion occurred. Applications
+can test for this behavior by inspecting the
+**IORING_FEAT_SUBMIT_STABLE** flag passed back from
+**io_uring_queue_init_params**(3).
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_prep_timeout_remove**(3), **io_uring_prep_timeout_update**(3)
diff --git a/man/io_uring_prep_timeout_update.3 b/man/io_uring_prep_timeout_update.3
deleted file mode 100644
index ef4f8c75..00000000
--- a/man/io_uring_prep_timeout_update.3
+++ /dev/null
@@ -1,85 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_timeout_update 3 "March 12, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_timeout_update \- prepare a request to update an existing timeout
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_timeout_update(struct io_uring_sqe *" sqe ","
-.BI " const struct __kernel_timespec *" ts ","
-.BI " __u64 " user_data ","
-.BI " unsigned " flags ");"
-.PP
-.BI "void io_uring_prep_timeout_remove(struct io_uring_sqe *" sqe ","
-.BI " __u64 " user_data ","
-.BI " unsigned " flags ");"
-.fi
-.SH DESCRIPTION
-.PP
-These functions modify or cancel an existing timeout request. The submission
-queue entry
-.I sqe
-is setup to arm a timeout update or removal specified by
-.I user_data
-and with modifier flags given by
-.IR flags .
-Additionally, the update request includes a
-.I ts
-structure, which contains new timeout information.
-
-For an update request, the
-.I flags
-member may contain a bitmask of the following values:
-.TP
-.B IORING_TIMEOUT_ABS
-The value specified in
-.I ts
-is an absolute value rather than a relative one.
-.PP
-The timeout remove command does not currently accept any flags.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-These are the errors that are reported in the CQE
-.I res
-field. On success,
-.B 0
-is returned.
-.TP
-.B -ENOENT
-The timeout identified by
-.I user_data
-could not be found. It may be invalid, or triggered before the update or
-removal request was processed.
-.TP
-.B -EALREADY
-The timeout identified by
-.I user_data
-is already firing and cannot be canceled.
-.TP
-.B -EINVAL
-One of the fields set in the SQE was invalid. For example, two clocksources
-were given, or the specified timeout seconds or nanoseconds were < 0.
-.TP
-.B -EFAULT
-io_uring was unable to access the data specified by
-.IR ts .
-.SH NOTES
-As with any request that passes in data in a struct, that data must remain
-valid until the request has been successfully submitted. It need not remain
-valid until completion. Once a request has been submitted, the in-kernel
-state is stable. Very early kernels (5.4 and earlier) required state to be
-stable until the completion occurred. Applications can test for this
-behavior by inspecting the
-.B IORING_FEAT_SUBMIT_STABLE
-flag passed back from
-.BR io_uring_queue_init_params (3).
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_prep_timeout (3)
diff --git a/man/io_uring_prep_timeout_update.3.md b/man/io_uring_prep_timeout_update.3.md
new file mode 100644
index 00000000..f65d70c3
--- /dev/null
+++ b/man/io_uring_prep_timeout_update.3.md
@@ -0,0 +1,95 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 12, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_timeout_update
+---
+
+# NAME
+
+io_uring_prep_timeout_update - prepare a request to update an existing
+timeout
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_timeout_update(struct io_uring_sqe * sqe ,
+ const struct __kernel_timespec * ts ,
+ __u64 user_data ,
+ unsigned flags );
+
+ void io_uring_prep_timeout_remove(struct io_uring_sqe * sqe ,
+ __u64 user_data ,
+ unsigned flags );
+```
+
+# DESCRIPTION
+
+These functions modify or cancel an existing timeout request. The
+submission queue entry *sqe* is setup to arm a timeout update or removal
+specified by *user_data* and with modifier flags given by *flags*.
+Additionally, the update request includes a *ts* structure, which
+contains new timeout information.
+
+For an update request, the *flags* member may contain a bitmask of the
+following values:
+
+**IORING_TIMEOUT_ABS**
+
+: The value specified in *ts* is an absolute value rather than a
+ relative one.
+
+The timeout remove command does not currently accept any flags.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+These are the errors that are reported in the CQE *res* field. On
+success, **0** is returned.
+
+**-ENOENT**
+
+: The timeout identified by *user_data* could not be found. It may be
+ invalid, or triggered before the update or removal request was
+ processed.
+
+**-EALREADY**
+
+: The timeout identified by *user_data* is already firing and cannot be
+ canceled.
+
+**-EINVAL**
+
+: One of the fields set in the SQE was invalid. For example, two
+ clocksources were given, or the specified timeout seconds or
+ nanoseconds were \< 0.
+
+**-EFAULT**
+
+: io_uring was unable to access the data specified by *ts*.
+
+# NOTES
+
+As with any request that passes in data in a struct, that data must
+remain valid until the request has been successfully submitted. It need
+not remain valid until completion. Once a request has been submitted,
+the in-kernel state is stable. Very early kernels (5.4 and earlier)
+required state to be stable until the completion occurred. Applications
+can test for this behavior by inspecting the
+**IORING_FEAT_SUBMIT_STABLE** flag passed back from
+**io_uring_queue_init_params**(3).
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_prep_timeout**(3)
diff --git a/man/io_uring_prep_unlinkat.3 b/man/io_uring_prep_unlinkat.3
deleted file mode 100644
index ba2633cf..00000000
--- a/man/io_uring_prep_unlinkat.3
+++ /dev/null
@@ -1,82 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_unlinkat 3 "March 13, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_unlinkat \- prepare an unlinkat request
-.SH SYNOPSIS
-.nf
-.B #include <fcntl.h>
-.B #include <unistd.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_unlinkat(struct io_uring_sqe *" sqe ","
-.BI " int " dirfd ","
-.BI " const char *" path ","
-.BI " int " flags ");"
-.PP
-.BI "void io_uring_prep_unlink(struct io_uring_sqe *" sqe ","
-.BI " const char *" path ","
-.BI " int " flags ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_unlinkat (3)
-function prepares an unlinkat request. The submission queue entry
-.I sqe
-is setup to use the directory file descriptor pointed to by
-.I dirfd
-to start an unlinkat operation on the path identified by
-.I path
-and using the flags given in
-.IR flags .
-
-The
-.BR io_uring_prep_unlink (3)
-function prepares an unlink request. The submission queue entry
-.I sqe
-is setup to start an unlinkat operation on the path identified by
-.I path
-relative to the current working directory and using the flags given in
-.IR flags .
-
-These functions prepare an async
-.BR unlinkat (2)
-or
-.BR unlink (2)
-request. See those man pages for details.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH NOTES
-As with any request that passes in data in a struct, that data must remain
-valid until the request has been successfully submitted. It need not remain
-valid until completion. Once a request has been submitted, the in-kernel
-state is stable. Very early kernels (5.4 and earlier) required state to be
-stable until the completion occurred. Applications can test for this
-behavior by inspecting the
-.B IORING_FEAT_SUBMIT_STABLE
-flag passed back from
-.BR io_uring_queue_init_params (3).
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR unlinkat (2),
-.BR unlink (2)
diff --git a/man/io_uring_prep_unlinkat.3.md b/man/io_uring_prep_unlinkat.3.md
new file mode 100644
index 00000000..7c1b70a4
--- /dev/null
+++ b/man/io_uring_prep_unlinkat.3.md
@@ -0,0 +1,75 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 13, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_unlinkat
+---
+
+# NAME
+
+io_uring_prep_unlinkat - prepare an unlinkat request
+
+# SYNOPSIS
+
+``` text
+#include <fcntl.h>
+#include <unistd.h>
+#include <liburing.h>
+
+ void io_uring_prep_unlinkat(struct io_uring_sqe * sqe ,
+ int dirfd ,
+ const char * path ,
+ int flags );
+
+ void io_uring_prep_unlink(struct io_uring_sqe * sqe ,
+ const char * path ,
+ int flags );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_unlinkat**(3) function prepares an unlinkat request.
+The submission queue entry *sqe* is setup to use the directory file
+descriptor pointed to by *dirfd* to start an unlinkat operation on the
+path identified by *path* and using the flags given in *flags*.
+
+The **io_uring_prep_unlink**(3) function prepares an unlink request. The
+submission queue entry *sqe* is setup to start an unlinkat operation on
+the path identified by *path* relative to the current working directory
+and using the flags given in *flags*.
+
+These functions prepare an async **unlinkat**(2) or **unlink**(2)
+request. See those man pages for details.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# NOTES
+
+As with any request that passes in data in a struct, that data must
+remain valid until the request has been successfully submitted. It need
+not remain valid until completion. Once a request has been submitted,
+the in-kernel state is stable. Very early kernels (5.4 and earlier)
+required state to be stable until the completion occurred. Applications
+can test for this behavior by inspecting the
+**IORING_FEAT_SUBMIT_STABLE** flag passed back from
+**io_uring_queue_init_params**(3).
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3), **unlinkat**(2),
+**unlink**(2)
diff --git a/man/io_uring_prep_uring_cmd.3 b/man/io_uring_prep_uring_cmd.3
deleted file mode 100644
index b40369ef..00000000
--- a/man/io_uring_prep_uring_cmd.3
+++ /dev/null
@@ -1,37 +0,0 @@
-.\" Copyright (C) 2022 Samuel Williams
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_uring_cmd 3 "October 22, 2025" "liburing-2.13" "liburing Manual"
-.SH NAME
-io_uring_prep_uring_cmd \- prepare a uring_cmd request
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_uring_cmd(struct io_uring_sqe *" sqe ","
-.BI " int " cmd_op ","
-.BI " int " fd ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_uring_cmd (3)
-function prepares uring_cmd (fd specific) request. The submission queue entry
-.I sqe
-is setup to use the filedescriptor
-.I fd
-to send file descriptor specific
-.IR cmd_op .
-
-The reserved fields are initialized to 0. Otherwise the caller has to set up
-any submission queue entry's operation specific fields.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-None
-.SH SEE ALSO
-.BR io_uring_prep_uring_cmd128 (3),
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
diff --git a/man/io_uring_prep_uring_cmd.3.md b/man/io_uring_prep_uring_cmd.3.md
new file mode 100644
index 00000000..f3429ad1
--- /dev/null
+++ b/man/io_uring_prep_uring_cmd.3.md
@@ -0,0 +1,47 @@
+.\" Copyright (C) 2022 Samuel Williams
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: October 22, 2025
+footer: liburing-2.13
+header: liburing Manual
+section: 3
+title: io_uring_prep_uring_cmd
+---
+
+# NAME
+
+io_uring_prep_uring_cmd - prepare a uring_cmd request
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_uring_cmd(struct io_uring_sqe * sqe ,
+ int cmd_op ,
+ int fd );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_uring_cmd**(3) function prepares uring_cmd (fd
+specific) request. The submission queue entry *sqe* is setup to use the
+filedescriptor *fd* to send file descriptor specific *cmd_op*.
+
+The reserved fields are initialized to 0. Otherwise the caller has to
+set up any submission queue entry\'s operation specific fields.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+None
+
+# SEE ALSO
+
+**io_uring_prep_uring_cmd128**(3), **io_uring_get_sqe**(3),
+**io_uring_submit**(3),
diff --git a/man/io_uring_prep_uring_cmd128.3 b/man/io_uring_prep_uring_cmd128.3
deleted file mode 100644
index 63f263f0..00000000
--- a/man/io_uring_prep_uring_cmd128.3
+++ /dev/null
@@ -1,38 +0,0 @@
-.\" Copyright (C) 2022 Samuel Williams
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_uring_cmd128 3 "October 22, 2025" "liburing-2.13" "liburing Manual"
-.SH NAME
-io_uring_prep_uring_cmd128 \- prepare a uring_cmd request
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_uring_cmd128(struct io_uring_sqe *" sqe ","
-.BI " int " cmd_op ","
-.BI " int " fd ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_uring_cmd128 (3)
-function prepares uring_cmd (fd specific) request for a 128 byte submission
-queue entry. The submission queue entry
-.I sqe
-is setup to use the filedescriptor
-.I fd
-to send file descriptor specific
-.IR cmd_op .
-
-The reserved fields are initialized to 0. Otherwise the caller has to set up
-any submission queue entry's operation specific fields.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-None
-.SH SEE ALSO
-.BR io_uring_prep_uring_cmd (3),
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
diff --git a/man/io_uring_prep_uring_cmd128.3.md b/man/io_uring_prep_uring_cmd128.3.md
new file mode 100644
index 00000000..dad62f68
--- /dev/null
+++ b/man/io_uring_prep_uring_cmd128.3.md
@@ -0,0 +1,48 @@
+.\" Copyright (C) 2022 Samuel Williams
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: October 22, 2025
+footer: liburing-2.13
+header: liburing Manual
+section: 3
+title: io_uring_prep_uring_cmd128
+---
+
+# NAME
+
+io_uring_prep_uring_cmd128 - prepare a uring_cmd request
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_uring_cmd128(struct io_uring_sqe * sqe ,
+ int cmd_op ,
+ int fd );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_uring_cmd128**(3) function prepares uring_cmd (fd
+specific) request for a 128 byte submission queue entry. The submission
+queue entry *sqe* is setup to use the filedescriptor *fd* to send file
+descriptor specific *cmd_op*.
+
+The reserved fields are initialized to 0. Otherwise the caller has to
+set up any submission queue entry\'s operation specific fields.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+None
+
+# SEE ALSO
+
+**io_uring_prep_uring_cmd**(3), **io_uring_get_sqe**(3),
+**io_uring_submit**(3),
diff --git a/man/io_uring_prep_waitid.3 b/man/io_uring_prep_waitid.3
deleted file mode 100644
index 06bda74e..00000000
--- a/man/io_uring_prep_waitid.3
+++ /dev/null
@@ -1,67 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_waitid 3 "July 14, 2023" "liburing-2.5" "liburing Manual"
-.SH NAME
-io_uring_prep_waitid \- prepare a waitid request
-.SH SYNOPSIS
-.nf
-.B #include <sys/wait.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_waitid(struct io_uring_sqe *" sqe ","
-.BI " idtype_t " idtype ","
-.BI " id_t " id ","
-.BI " siginfo_t *" infop ","
-.BI " int " options ","
-.BI " unsigned int " flags ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_waitid (3)
-function prepares a waitid request. The submission queue entry
-.I sqe
-is setup to use the
-.I idtype
-and
-.I id
-arguments select the child(ren), and
-.I options
-to specify the child state changes to wait for. Upon successful
-return, it fills
-.I infop
-with information of the child process, if any.
-.I flags
-is io_uring specific modifier flags. They are currently unused, and hence
-.B 0
-should be passed.
-
-This function prepares an async
-.BR waitid (2)
-request. See that man page for details.
-
-Available since kernel 6.7.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR waitid (2)
diff --git a/man/io_uring_prep_waitid.3.md b/man/io_uring_prep_waitid.3.md
new file mode 100644
index 00000000..2da8bc8f
--- /dev/null
+++ b/man/io_uring_prep_waitid.3.md
@@ -0,0 +1,60 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: July 14, 2023
+footer: liburing-2.5
+header: liburing Manual
+section: 3
+title: io_uring_prep_waitid
+---
+
+# NAME
+
+io_uring_prep_waitid - prepare a waitid request
+
+# SYNOPSIS
+
+``` text
+#include <sys/wait.h>
+#include <liburing.h>
+
+ void io_uring_prep_waitid(struct io_uring_sqe * sqe ,
+ idtype_t idtype ,
+ id_t id ,
+ siginfo_t * infop ,
+ int options ,
+ unsigned int flags );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_waitid**(3) function prepares a waitid request. The
+submission queue entry *sqe* is setup to use the *idtype* and *id*
+arguments select the child(ren), and *options* to specify the child
+state changes to wait for. Upon successful return, it fills *infop* with
+information of the child process, if any. *flags* is io_uring specific
+modifier flags. They are currently unused, and hence **0** should be
+passed.
+
+This function prepares an async **waitid**(2) request. See that man page
+for details.
+
+Available since kernel 6.7.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3), **waitid**(2)
diff --git a/man/io_uring_prep_write.3 b/man/io_uring_prep_write.3
deleted file mode 100644
index fde22136..00000000
--- a/man/io_uring_prep_write.3
+++ /dev/null
@@ -1,70 +0,0 @@
-.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_write 3 "November 15, 2021" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_prep_write \- prepare I/O write request
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_write(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " const void *" buf ","
-.BI " unsigned " nbytes ","
-.BI " __u64 " offset ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_write (3)
-prepares an IO write request. The submission queue entry
-.I sqe
-is setup to use the file descriptor
-.I fd
-to start writing
-.I nbytes
-from the buffer
-.I buf
-at the specified
-.IR offset .
-
-On files that support seeking, if the offset is set to
-.BR -1 ,
-the write operation commences at the file offset, and the file offset is
-incremented by the number of bytes written. See
-.BR write (2)
-for more details. Note that for an async API, reading and updating the
-current file offset may result in unpredictable behavior, unless access
-to the file is serialized. It is not encouraged to use this feature if it's
-possible to provide the desired IO offset from the application or library.
-
-On files that are not capable of seeking, the offset must be 0 or -1.
-
-After the write has been prepared, it can be submitted with one of the submit
-functions.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH NOTES
-Despite accepting an unsigned number of bytes, this function can transfer at most
-INT_MAX bytes per call (the maximum for the underlying syscall interface).
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3)
diff --git a/man/io_uring_prep_write.3.md b/man/io_uring_prep_write.3.md
new file mode 100644
index 00000000..cc564332
--- /dev/null
+++ b/man/io_uring_prep_write.3.md
@@ -0,0 +1,69 @@
+.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: November 15, 2021
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_prep_write
+---
+
+# NAME
+
+io_uring_prep_write - prepare I/O write request
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_write(struct io_uring_sqe * sqe ,
+ int fd ,
+ const void * buf ,
+ unsigned nbytes ,
+ __u64 offset );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_write**(3) prepares an IO write request. The
+submission queue entry *sqe* is setup to use the file descriptor *fd* to
+start writing *nbytes* from the buffer *buf* at the specified *offset*.
+
+On files that support seeking, if the offset is set to **-1**, the write
+operation commences at the file offset, and the file offset is
+incremented by the number of bytes written. See **write**(2) for more
+details. Note that for an async API, reading and updating the current
+file offset may result in unpredictable behavior, unless access to the
+file is serialized. It is not encouraged to use this feature if it\'s
+possible to provide the desired IO offset from the application or
+library.
+
+On files that are not capable of seeking, the offset must be 0 or -1.
+
+After the write has been prepared, it can be submitted with one of the
+submit functions.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# NOTES
+
+Despite accepting an unsigned number of bytes, this function can
+transfer at most INT_MAX bytes per call (the maximum for the underlying
+syscall interface).
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3)
diff --git a/man/io_uring_prep_write_fixed.3 b/man/io_uring_prep_write_fixed.3
deleted file mode 100644
index 28f53282..00000000
--- a/man/io_uring_prep_write_fixed.3
+++ /dev/null
@@ -1,75 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_write_fixed 3 "February 13, 2022" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_prep_write_fixed \- prepare I/O write request with registered buffer
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_write_fixed(struct io_uring_sqe *" sqe ","
-.BI " int " fd ",
-.BI " const void *" buf ","
-.BI " unsigned " nbytes ","
-.BI " __u64 " offset ","
-.BI " int " buf_index ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_write_fixed (3)
-prepares an IO write request with a previously registered IO buffer. The
-submission queue entry
-.I sqe
-is setup to use the file descriptor
-.I fd
-to start writing
-.I nbytes
-from the buffer
-.I buf
-at the specified
-.I offset
-and with the buffer matching the registered index of
-.IR buf_index .
-
-This works just like
-.BR io_uring_prep_write (3)
-except it requires the use of buffers that have been registered with
-.BR io_uring_register_buffers (3).
-The
-.I buf
-and
-.I nbytes
-arguments must fall within a region specified by
-.I buf_index
-in the previously registered buffer. The buffer need not be aligned with
-the start of the registered buffer.
-
-After the write has been prepared it can be submitted with one of the submit
-functions.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH NOTES
-Despite accepting an unsigned number of bytes, this function can transfer at most
-INT_MAX bytes per call (the maximum for the underlying syscall interface).
-.SH SEE ALSO
-.BR io_uring_prep_write (3),
-.BR io_uring_register_buffers (3)
diff --git a/man/io_uring_prep_write_fixed.3.md b/man/io_uring_prep_write_fixed.3.md
new file mode 100644
index 00000000..b6f0c84e
--- /dev/null
+++ b/man/io_uring_prep_write_fixed.3.md
@@ -0,0 +1,69 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: February 13, 2022
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_prep_write_fixed
+---
+
+# NAME
+
+io_uring_prep_write_fixed - prepare I/O write request with registered
+buffer
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_write_fixed(struct io_uring_sqe * sqe ,
+ int fd ,
+ const void * buf ,
+ unsigned nbytes ,
+ __u64 offset ,
+ int buf_index );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_write_fixed**(3) prepares an IO write request with a
+previously registered IO buffer. The submission queue entry *sqe* is
+setup to use the file descriptor *fd* to start writing *nbytes* from the
+buffer *buf* at the specified *offset* and with the buffer matching the
+registered index of *buf_index*.
+
+This works just like **io_uring_prep_write**(3) except it requires the
+use of buffers that have been registered with
+**io_uring_register_buffers**(3). The *buf* and *nbytes* arguments must
+fall within a region specified by *buf_index* in the previously
+registered buffer. The buffer need not be aligned with the start of the
+registered buffer.
+
+After the write has been prepared it can be submitted with one of the
+submit functions.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# NOTES
+
+Despite accepting an unsigned number of bytes, this function can
+transfer at most INT_MAX bytes per call (the maximum for the underlying
+syscall interface).
+
+# SEE ALSO
+
+**io_uring_prep_write**(3), **io_uring_register_buffers**(3)
diff --git a/man/io_uring_prep_writev.3 b/man/io_uring_prep_writev.3
deleted file mode 100644
index 042ac398..00000000
--- a/man/io_uring_prep_writev.3
+++ /dev/null
@@ -1,89 +0,0 @@
-.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_writev 3 "November 15, 2021" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_prep_writev \- prepare vector I/O write request
-.SH SYNOPSIS
-.nf
-.B #include <sys/uio.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_writev(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " const struct iovec *" iovecs ","
-.BI " unsigned " nr_vecs ","
-.BI " __u64 " offset ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_writev (3)
-prepares a vectored IO write request. The submission queue entry
-.I sqe
-is setup to use the file descriptor
-.I fd
-to start writing
-.I nr_vecs
-from the
-.I iovecs
-array at the specified
-.IR offset .
-
-On files that support seeking, if the offset is set to
-.BR -1 ,
-the write operation commences at the file offset, and the file offset is
-incremented by the number of bytes written. See
-.BR write (2)
-for more details. Note that for an async API, reading and updating the
-current file offset may result in unpredictable behavior, unless access
-to the file is serialized. It is not encouraged to use this feature if it's
-possible to provide the desired IO offset from the application or library.
-
-On files that are not capable of seeking, the offset must be 0 or -1.
-
-After the write has been prepared it can be submitted with one of the submit
-functions.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH NOTES
-Unless an application explicitly needs to pass in more than one iovec, it
-is more efficient to use
-.BR io_uring_prep_write (3)
-rather than this function, as no state has to be maintained for a
-non-vectored IO request.
-As with any request that passes in data in a struct, that data must remain
-valid until the request has been successfully submitted. It need not remain
-valid until completion. Once a request has been submitted, the in-kernel
-state is stable. Very early kernels (5.4 and earlier) required state to be
-stable until the completion occurred. Applications can test for this
-behavior by inspecting the
-.B IORING_FEAT_SUBMIT_STABLE
-flag passed back from
-.BR io_uring_queue_init_params (3).
-
-Despite accepting an array of iovec's with a size_t number of bytes each,
-this function can transfer at most INT_MAX bytes per call (the maximum
-for the underlying syscall interface).
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_prep_write (3),
-.BR io_uring_prep_writev2 (3),
-.BR io_uring_submit (3)
diff --git a/man/io_uring_prep_writev.3.md b/man/io_uring_prep_writev.3.md
new file mode 100644
index 00000000..009980e6
--- /dev/null
+++ b/man/io_uring_prep_writev.3.md
@@ -0,0 +1,84 @@
+.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: November 15, 2021
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_prep_writev
+---
+
+# NAME
+
+io_uring_prep_writev - prepare vector I/O write request
+
+# SYNOPSIS
+
+``` text
+#include <sys/uio.h>
+#include <liburing.h>
+
+ void io_uring_prep_writev(struct io_uring_sqe * sqe ,
+ int fd ,
+ const struct iovec * iovecs ,
+ unsigned nr_vecs ,
+ __u64 offset );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_writev**(3) prepares a vectored IO write request.
+The submission queue entry *sqe* is setup to use the file descriptor
+*fd* to start writing *nr_vecs* from the *iovecs* array at the specified
+*offset*.
+
+On files that support seeking, if the offset is set to **-1**, the write
+operation commences at the file offset, and the file offset is
+incremented by the number of bytes written. See **write**(2) for more
+details. Note that for an async API, reading and updating the current
+file offset may result in unpredictable behavior, unless access to the
+file is serialized. It is not encouraged to use this feature if it\'s
+possible to provide the desired IO offset from the application or
+library.
+
+On files that are not capable of seeking, the offset must be 0 or -1.
+
+After the write has been prepared it can be submitted with one of the
+submit functions.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# NOTES
+
+Unless an application explicitly needs to pass in more than one iovec,
+it is more efficient to use **io_uring_prep_write**(3) rather than this
+function, as no state has to be maintained for a non-vectored IO
+request. As with any request that passes in data in a struct, that data
+must remain valid until the request has been successfully submitted. It
+need not remain valid until completion. Once a request has been
+submitted, the in-kernel state is stable. Very early kernels (5.4 and
+earlier) required state to be stable until the completion occurred.
+Applications can test for this behavior by inspecting the
+**IORING_FEAT_SUBMIT_STABLE** flag passed back from
+**io_uring_queue_init_params**(3).
+
+Despite accepting an array of iovec\'s with a size_t number of bytes
+each, this function can transfer at most INT_MAX bytes per call (the
+maximum for the underlying syscall interface).
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_prep_write**(3),
+**io_uring_prep_writev2**(3), **io_uring_submit**(3)
diff --git a/man/io_uring_prep_writev2.3 b/man/io_uring_prep_writev2.3
deleted file mode 100644
index 93659be9..00000000
--- a/man/io_uring_prep_writev2.3
+++ /dev/null
@@ -1,115 +0,0 @@
-.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_writev2 3 "November 15, 2021" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_prep_writev2 \- prepare vector I/O write request with flags
-.SH SYNOPSIS
-.nf
-.B #include <sys/uio.h>
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_writev2(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " const struct iovec *" iovecs ","
-.BI " unsigned " nr_vecs ","
-.BI " __u64 " offset ","
-.BI " int " flags ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_writev2 (3)
-prepares a vectored IO write request. The submission queue entry
-.I sqe
-is setup to use the file descriptor
-.I fd
-to start writing
-.I nr_vecs
-from the
-.I iovecs
-array at the specified
-.IR offset .
-The behavior of the function can be controlled with the
-.I flags
-parameter.
-
-Supported values for
-.I flags
-are:
-.TP
-.B RWF_HIPRI
-High priority request, poll if possible
-.TP
-.B RWF_DSYNC
-per-IO O_DSYNC
-.TP
-.B RWF_SYNC
-per-IO O_SYNC
-.TP
-.B RWF_NOWAIT
-per-IO, return
-.B -EAGAIN
-if operation would block
-.TP
-.B RWF_APPEND
-per-IO O_APPEND
-
-.P
-On files that support seeking, if the offset is set to
-.BR -1 ,
-the write operation commences at the file offset, and the file offset is
-incremented by the number of bytes written. See
-.BR write (2)
-for more details. Note that for an async API, reading and updating the
-current file offset may result in unpredictable behavior, unless access
-to the file is serialized. It is not encouraged to use this feature if it's
-possible to provide the desired IO offset from the application or library.
-
-On files that are not capable of seeking, the offset must be 0 or -1.
-
-After the write has been prepared, it can be submitted with one of the submit
-functions.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation. See the related man page for
-details on possible values. Note that where synchronous system calls will return
-.B -1
-on failure and set
-.I errno
-to the actual error value, io_uring never uses
-.IR errno .
-Instead it returns the negated
-.I errno
-directly in the CQE
-.I res
-field.
-.SH NOTES
-Unless an application explicitly needs to pass in more than one iovec, it
-is more efficient to use
-.BR io_uring_prep_write (3)
-rather than this function, as no state has to be maintained for a
-non-vectored IO request.
-As with any request that passes in data in a struct, that data must remain
-valid until the request has been successfully submitted. It need not remain
-valid until completion. Once a request has been submitted, the in-kernel
-state is stable. Very early kernels (5.4 and earlier) required state to be
-stable until the completion occurred. Applications can test for this
-behavior by inspecting the
-.B IORING_FEAT_SUBMIT_STABLE
-flag passed back from
-.BR io_uring_queue_init_params (3).
-
-Despite accepting an array of iovec's with a size_t number of bytes each,
-this function can transfer at most INT_MAX bytes per call (the maximum
-for the underlying syscall interface).
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_prep_write (3),
-.BR io_uring_prep_writev (3),
-.BR io_uring_submit (3)
diff --git a/man/io_uring_prep_writev2.3.md b/man/io_uring_prep_writev2.3.md
new file mode 100644
index 00000000..10838d9c
--- /dev/null
+++ b/man/io_uring_prep_writev2.3.md
@@ -0,0 +1,108 @@
+.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: November 15, 2021
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_prep_writev2
+---
+
+# NAME
+
+io_uring_prep_writev2 - prepare vector I/O write request with flags
+
+# SYNOPSIS
+
+``` text
+#include <sys/uio.h>
+#include <liburing.h>
+
+ void io_uring_prep_writev2(struct io_uring_sqe * sqe ,
+ int fd ,
+ const struct iovec * iovecs ,
+ unsigned nr_vecs ,
+ __u64 offset ,
+ int flags );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_writev2**(3) prepares a vectored IO write request.
+The submission queue entry *sqe* is setup to use the file descriptor
+*fd* to start writing *nr_vecs* from the *iovecs* array at the specified
+*offset*. The behavior of the function can be controlled with the
+*flags* parameter.
+
+Supported values for *flags* are:
+
+**RWF_HIPRI**
+
+: High priority request, poll if possible
+
+**RWF_DSYNC**
+
+: per-IO O_DSYNC
+
+**RWF_SYNC**
+
+: per-IO O_SYNC
+
+**RWF_NOWAIT**
+
+: per-IO, return **-EAGAIN** if operation would block
+
+**RWF_APPEND**
+
+: per-IO O_APPEND
+
+On files that support seeking, if the offset is set to **-1**, the write
+operation commences at the file offset, and the file offset is
+incremented by the number of bytes written. See **write**(2) for more
+details. Note that for an async API, reading and updating the current
+file offset may result in unpredictable behavior, unless access to the
+file is serialized. It is not encouraged to use this feature if it\'s
+possible to provide the desired IO offset from the application or
+library.
+
+On files that are not capable of seeking, the offset must be 0 or -1.
+
+After the write has been prepared, it can be submitted with one of the
+submit functions.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation. See the
+related man page for details on possible values. Note that where
+synchronous system calls will return **-1** on failure and set *errno*
+to the actual error value, io_uring never uses *errno*. Instead it
+returns the negated *errno* directly in the CQE *res* field.
+
+# NOTES
+
+Unless an application explicitly needs to pass in more than one iovec,
+it is more efficient to use **io_uring_prep_write**(3) rather than this
+function, as no state has to be maintained for a non-vectored IO
+request. As with any request that passes in data in a struct, that data
+must remain valid until the request has been successfully submitted. It
+need not remain valid until completion. Once a request has been
+submitted, the in-kernel state is stable. Very early kernels (5.4 and
+earlier) required state to be stable until the completion occurred.
+Applications can test for this behavior by inspecting the
+**IORING_FEAT_SUBMIT_STABLE** flag passed back from
+**io_uring_queue_init_params**(3).
+
+Despite accepting an array of iovec\'s with a size_t number of bytes
+each, this function can transfer at most INT_MAX bytes per call (the
+maximum for the underlying syscall interface).
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_prep_write**(3),
+**io_uring_prep_writev**(3), **io_uring_submit**(3)
diff --git a/man/io_uring_prep_writev_fixed.3 b/man/io_uring_prep_writev_fixed.3
deleted file mode 100644
index 3e62b230..00000000
--- a/man/io_uring_prep_writev_fixed.3
+++ /dev/null
@@ -1,71 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_prep_writev_fixed 3 "January 18, 2025" "liburing-2.10" "liburing Manual"
-.SH NAME
-io_uring_prep_writev_fixed \- prepare a vectored write using fixed buffers
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_prep_writev_fixed(struct io_uring_sqe *" sqe ","
-.BI " int " fd ","
-.BI " const struct iovec *" iovecs ","
-.BI " unsigned " nr_vecs ","
-.BI " __u64 " offset ","
-.BI " int " flags ","
-.BI " int " buf_index ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_writev_fixed (3)
-function prepares a vectored write request using fixed (registered) buffers.
-The submission queue entry
-.I sqe
-is setup to use the file descriptor
-.I fd
-to start writing
-.I nr_vecs
-iovecs from the file position
-.IR offset .
-
-The
-.I iovecs
-argument points to an array of iovec structures describing the write
-buffers. All buffers must be part of the registered buffer set at index
-.IR buf_index ,
-previously registered with
-.BR io_uring_register_buffers (3).
-
-The
-.I flags
-argument can contain any per-request flags, such as
-.B RWF_APPEND
-or other flags supported by
-.BR pwritev2 (2).
-
-Using fixed buffers avoids the overhead of mapping buffers for each I/O
-operation, improving performance for applications that reuse the same
-buffers.
-
-.SH RETURN VALUE
-None
-.SH ERRORS
-The CQE
-.I res
-field will contain the result of the operation, the number of bytes written
-on success. On error, a negative errno value is returned.
-.SH NOTES
-Despite accepting an array of iovec's with a size_t number of bytes each,
-this function can transfer at most INT_MAX bytes per call (the maximum
-for the underlying syscall interface).
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_prep_writev (3),
-.BR io_uring_prep_writev2 (3),
-.BR io_uring_prep_write_fixed (3),
-.BR io_uring_prep_readv_fixed (3),
-.BR io_uring_register_buffers (3)
diff --git a/man/io_uring_prep_writev_fixed.3.md b/man/io_uring_prep_writev_fixed.3.md
new file mode 100644
index 00000000..546bceed
--- /dev/null
+++ b/man/io_uring_prep_writev_fixed.3.md
@@ -0,0 +1,72 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 18, 2025
+footer: liburing-2.10
+header: liburing Manual
+section: 3
+title: io_uring_prep_writev_fixed
+---
+
+# NAME
+
+io_uring_prep_writev_fixed - prepare a vectored write using fixed
+buffers
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_prep_writev_fixed(struct io_uring_sqe * sqe ,
+ int fd ,
+ const struct iovec * iovecs ,
+ unsigned nr_vecs ,
+ __u64 offset ,
+ int flags ,
+ int buf_index );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_writev_fixed**(3) function prepares a vectored write
+request using fixed (registered) buffers. The submission queue entry
+*sqe* is setup to use the file descriptor *fd* to start writing
+*nr_vecs* iovecs from the file position *offset*.
+
+The *iovecs* argument points to an array of iovec structures describing
+the write buffers. All buffers must be part of the registered buffer set
+at index *buf_index*, previously registered with
+**io_uring_register_buffers**(3).
+
+The *flags* argument can contain any per-request flags, such as
+**RWF_APPEND** or other flags supported by **pwritev2**(2).
+
+Using fixed buffers avoids the overhead of mapping buffers for each I/O
+operation, improving performance for applications that reuse the same
+buffers.
+
+# RETURN VALUE
+
+None
+
+# ERRORS
+
+The CQE *res* field will contain the result of the operation, the number
+of bytes written on success. On error, a negative errno value is
+returned.
+
+# NOTES
+
+Despite accepting an array of iovec\'s with a size_t number of bytes
+each, this function can transfer at most INT_MAX bytes per call (the
+maximum for the underlying syscall interface).
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit**(3),
+**io_uring_prep_writev**(3), **io_uring_prep_writev2**(3),
+**io_uring_prep_write_fixed**(3), **io_uring_prep_readv_fixed**(3),
+**io_uring_register_buffers**(3)
diff --git a/man/io_uring_provided_buffers.7 b/man/io_uring_provided_buffers.7
deleted file mode 100644
index 57e91132..00000000
--- a/man/io_uring_provided_buffers.7
+++ /dev/null
@@ -1,266 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_provided_buffers 7 "January 18, 2025" "Linux" "Linux Programmer's Manual"
-.SH NAME
-io_uring_provided_buffers \- io_uring provided buffer rings overview
-.SH DESCRIPTION
-Provided buffer rings allow applications to supply a pool of buffers to
-the kernel that can be dynamically selected at operation completion time.
-This is particularly useful for operations where the buffer requirements
-are not known upfront, such as receiving data from network sockets or
-reading from pipes.
-.SS Why use provided buffers?
-Traditional I/O operations require the application to specify a buffer
-when submitting the request. For receive operations on sockets or reads
-from pipes, this presents a challenge: the application doesn't know how
-much data will arrive, so it must either:
-.IP \(bu 2
-Allocate a large buffer for each pending operation, wasting memory
-.IP \(bu
-Use small buffers and potentially require multiple operations
-.IP \(bu
-Limit the number of pending operations to control memory usage
-.PP
-Provided buffer rings solve this by letting the kernel select an
-appropriately-sized buffer from a shared pool at completion time.
-Multiple operations can share the same buffer pool, and buffers are only
-consumed when data actually arrives.
-
-Provided buffers are most beneficial for:
-.IP \(bu 2
-Network servers with many concurrent connections
-.IP \(bu
-Applications receiving variable-length messages
-.IP \(bu
-Scenarios where memory efficiency is important
-.SS Buffer ring concepts
-A provided buffer ring is a circular buffer shared between the
-application and kernel:
-.IP \(bu 2
-The application adds buffers to the ring by writing entries and
-advancing the tail
-.IP \(bu
-The kernel consumes buffers from the ring by reading entries and
-advancing the head
-.IP \(bu
-Each buffer has a unique buffer ID (bid) within its buffer group
-.IP \(bu
-Buffer groups are identified by a buffer group ID (bgid)
-.PP
-Multiple buffer rings can exist simultaneously, each with a different
-buffer group ID. Operations specify which buffer group to use.
-.SS Setting up a buffer ring
-Buffer rings are set up using
-.BR io_uring_setup_buf_ring (3),
-which handles allocation, registration, and initialization:
-.PP
-.in +4n
-.EX
-struct io_uring_buf_ring *br;
-int bgid = 1; /* buffer group ID */
-int err;
-
-br = io_uring_setup_buf_ring(ring, 128, bgid, 0, &err);
-if (!br) {
- fprintf(stderr, "buffer ring setup failed: %d\\n", err);
- return err;
-}
-.EE
-.in
-.PP
-The ring must have a power-of-two number of entries, up to a maximum of
-32768 (2^15).
-
-Alternatively, applications can use
-.BR io_uring_register_buf_ring (3)
-for more control over the setup process, including kernel-allocated
-rings using the
-.B IOU_PBUF_RING_MMAP
-flag.
-.SS Adding buffers to the ring
-Buffers are added using
-.BR io_uring_buf_ring_add (3)
-and made visible to the kernel with
-.BR io_uring_buf_ring_advance (3):
-.PP
-.in +4n
-.EX
-int mask = io_uring_buf_ring_mask(128);
-
-for (int i = 0; i < 128; i++) {
- void *buf = malloc(4096);
- io_uring_buf_ring_add(br, buf, 4096, i, mask, i);
-}
-io_uring_buf_ring_advance(br, 128);
-.EE
-.in
-.PP
-Each buffer is assigned a buffer ID (the third parameter). Buffer IDs
-should be unique within the buffer group but can be reused after a
-buffer is returned.
-.SS Using provided buffers in operations
-To use provided buffers, set the
-.B IOSQE_BUFFER_SELECT
-flag on the SQE and specify the buffer group ID:
-.PP
-.in +4n
-.EX
-struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
-io_uring_prep_recv(sqe, sockfd, NULL, 4096, 0);
-io_uring_sqe_set_flags(sqe, IOSQE_BUFFER_SELECT);
-io_uring_sqe_set_buf_group(sqe, bgid);
-.EE
-.in
-.PP
-Note that
-.I addr
-is set to NULL (or ignored) since the kernel will select the buffer.
-The
-.I len
-field specifies the maximum amount of data to receive.
-
-Operations that support provided buffers include:
-.IP \(bu 2
-.B IORING_OP_READ
-/
-.B IORING_OP_RECV
-.IP \(bu
-.B IORING_OP_READV
-(single vector only)
-.IP \(bu
-.B IORING_OP_RECVMSG
-.SS Handling completions
-When an operation using provided buffers completes, the CQE indicates
-which buffer was used:
-.IP \(bu 2
-.B IORING_CQE_F_BUFFER
-is set in
-.I cqe->flags
-.IP \(bu
-The buffer ID is in the upper 16 bits of
-.IR cqe->flags ,
-extractable via
-.B cqe->flags >> IORING_CQE_BUFFER_SHIFT
-.IP \(bu
-.I cqe->res
-contains the number of bytes transferred
-.PP
-.in +4n
-.EX
-struct io_uring_cqe *cqe;
-io_uring_wait_cqe(ring, &cqe);
-
-if (cqe->flags & IORING_CQE_F_BUFFER) {
- int bid = cqe->flags >> IORING_CQE_BUFFER_SHIFT;
- void *buf = buffers[bid]; /* application's buffer tracking */
- int len = cqe->res;
-
- /* process data in buf */
- process_data(buf, len);
-
- /* return buffer to ring for reuse */
- io_uring_buf_ring_add(br, buf, 4096, bid, mask, 0);
- io_uring_buf_ring_advance(br, 1);
-}
-io_uring_cqe_seen(ring, cqe);
-.EE
-.in
-.PP
-If no buffer was available when the operation completed, the operation
-fails with
-.BR -ENOBUFS .
-.SS Multishot operations
-Provided buffers are particularly powerful with multishot operations
-like
-.BR io_uring_prep_recv_multishot (3).
-A single SQE can generate multiple completions, each consuming a buffer
-from the ring:
-.PP
-.in +4n
-.EX
-struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
-io_uring_prep_recv_multishot(sqe, sockfd, NULL, 0, 0);
-io_uring_sqe_set_flags(sqe, IOSQE_BUFFER_SELECT);
-io_uring_sqe_set_buf_group(sqe, bgid);
-.EE
-.in
-.PP
-Completions with
-.B IORING_CQE_F_MORE
-set indicate more completions will follow. The multishot operation
-continues until an error occurs, the buffer ring is exhausted, or the
-operation is canceled.
-.SS Incremental buffer consumption
-Buffer rings can be set up with the
-.B IOU_PBUF_RING_INC
-flag to enable incremental consumption. With this mode, large buffers
-can be partially consumed across multiple operations:
-.IP \(bu 2
-Completions with
-.B IORING_CQE_F_BUF_MORE
-indicate the buffer will be used for more completions
-.IP \(bu
-Each completion picks up where the previous left off
-.IP \(bu
-The buffer is only returned when consumed completely or on error
-.PP
-This is useful for registering large buffer regions that are consumed
-in smaller chunks.
-.SS Returning buffers
-When finished with a buffer, return it to the ring using
-.BR io_uring_buf_ring_add (3)
-followed by
-.BR io_uring_buf_ring_advance (3).
-For efficiency when processing multiple CQEs, use
-.BR io_uring_buf_ring_cq_advance (3)
-to advance both the CQ and buffer ring in a single operation.
-.SS Buffer ring status
-Applications can query how many buffers are available using
-.BR io_uring_buf_ring_available (3),
-which returns the number of buffers the kernel has not yet consumed.
-The current kernel head position can be retrieved with
-.BR io_uring_buf_ring_head (3).
-.SS Cleaning up
-Buffer rings are freed using
-.BR io_uring_free_buf_ring (3),
-which unregisters the ring and frees the ring memory (if it was
-allocated by
-.BR io_uring_setup_buf_ring (3)).
-Applications must free the individual buffers themselves.
-.SH NOTES
-.IP \(bu 2
-Buffer ring entries must be a power of two, maximum 32768.
-.IP \(bu
-Buffer IDs are 16-bit values (0-65535).
-.IP \(bu
-If no buffer is available when an operation needs one, the operation
-fails with
-.BR -ENOBUFS .
-Applications should ensure the ring is adequately stocked.
-.IP \(bu
-Provided buffers cannot be used with registered (fixed) buffers. These
-are separate mechanisms.
-.IP \(bu
-For multishot receives, ensure buffers are returned to the ring promptly
-to avoid running out.
-.SS Legacy provided buffers
-Earlier kernels supported provided buffers via
-.B IORING_OP_PROVIDE_BUFFERS
-and
-.BR IORING_OP_REMOVE_BUFFERS .
-This mechanism required submitting SQEs to add or remove buffers,
-adding latency and overhead. The ring-based mechanism described above
-supersedes this approach and should be used for all new applications.
-The legacy interface remains for backwards compatibility.
-.SH SEE ALSO
-.BR io_uring (7),
-.BR io_uring_setup_buf_ring (3),
-.BR io_uring_free_buf_ring (3),
-.BR io_uring_register_buf_ring (3),
-.BR io_uring_unregister_buf_ring (3),
-.BR io_uring_buf_ring_add (3),
-.BR io_uring_buf_ring_advance (3),
-.BR io_uring_buf_ring_cq_advance (3),
-.BR io_uring_buf_ring_available (3),
-.BR io_uring_prep_recv_multishot (3)
diff --git a/man/io_uring_provided_buffers.7.md b/man/io_uring_provided_buffers.7.md
new file mode 100644
index 00000000..272c9a0c
--- /dev/null
+++ b/man/io_uring_provided_buffers.7.md
@@ -0,0 +1,255 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 18, 2025
+footer: Linux
+header: Linux Programmer\'s Manual
+section: 7
+title: io_uring_provided_buffers
+---
+
+# NAME
+
+io_uring_provided_buffers - io_uring provided buffer rings overview
+
+# DESCRIPTION
+
+Provided buffer rings allow applications to supply a pool of buffers to
+the kernel that can be dynamically selected at operation completion
+time. This is particularly useful for operations where the buffer
+requirements are not known upfront, such as receiving data from network
+sockets or reading from pipes.
+
+## Why use provided buffers?
+
+Traditional I/O operations require the application to specify a buffer
+when submitting the request. For receive operations on sockets or reads
+from pipes, this presents a challenge: the application doesn\'t know how
+much data will arrive, so it must either:
+
+- Allocate a large buffer for each pending operation, wasting memory
+
+- Use small buffers and potentially require multiple operations
+
+- Limit the number of pending operations to control memory usage
+
+Provided buffer rings solve this by letting the kernel select an
+appropriately-sized buffer from a shared pool at completion time.
+Multiple operations can share the same buffer pool, and buffers are only
+consumed when data actually arrives.
+
+Provided buffers are most beneficial for:
+
+- Network servers with many concurrent connections
+
+- Applications receiving variable-length messages
+
+- Scenarios where memory efficiency is important
+
+## Buffer ring concepts
+
+A provided buffer ring is a circular buffer shared between the
+application and kernel:
+
+- The application adds buffers to the ring by writing entries and
+ advancing the tail
+
+- The kernel consumes buffers from the ring by reading entries and
+ advancing the head
+
+- Each buffer has a unique buffer ID (bid) within its buffer group
+
+- Buffer groups are identified by a buffer group ID (bgid)
+
+Multiple buffer rings can exist simultaneously, each with a different
+buffer group ID. Operations specify which buffer group to use.
+
+## Setting up a buffer ring
+
+Buffer rings are set up using **io_uring_setup_buf_ring**(3), which
+handles allocation, registration, and initialization:
+
+``` text
+struct io_uring_buf_ring *br;
+int bgid = 1; /* buffer group ID */
+int err;
+
+br = io_uring_setup_buf_ring(ring, 128, bgid, 0, &err);
+if (!br) {
+ fprintf(stderr, "buffer ring setup failed: %d\n", err);
+ return err;
+}
+```
+
+The ring must have a power-of-two number of entries, up to a maximum of
+32768 (2\^15).
+
+Alternatively, applications can use **io_uring_register_buf_ring**(3)
+for more control over the setup process, including kernel-allocated
+rings using the **IOU_PBUF_RING_MMAP** flag.
+
+## Adding buffers to the ring
+
+Buffers are added using **io_uring_buf_ring_add**(3) and made visible to
+the kernel with **io_uring_buf_ring_advance**(3):
+
+``` text
+int mask = io_uring_buf_ring_mask(128);
+
+for (int i = 0; i < 128; i++) {
+ void *buf = malloc(4096);
+ io_uring_buf_ring_add(br, buf, 4096, i, mask, i);
+}
+io_uring_buf_ring_advance(br, 128);
+```
+
+Each buffer is assigned a buffer ID (the third parameter). Buffer IDs
+should be unique within the buffer group but can be reused after a
+buffer is returned.
+
+## Using provided buffers in operations
+
+To use provided buffers, set the **IOSQE_BUFFER_SELECT** flag on the SQE
+and specify the buffer group ID:
+
+``` text
+struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
+io_uring_prep_recv(sqe, sockfd, NULL, 4096, 0);
+io_uring_sqe_set_flags(sqe, IOSQE_BUFFER_SELECT);
+io_uring_sqe_set_buf_group(sqe, bgid);
+```
+
+Note that *addr* is set to NULL (or ignored) since the kernel will
+select the buffer. The *len* field specifies the maximum amount of data
+to receive.
+
+Operations that support provided buffers include:
+
+- **IORING_OP_READ** / **IORING_OP_RECV**
+
+- **IORING_OP_READV** (single vector only)
+
+- **IORING_OP_RECVMSG**
+
+## Handling completions
+
+When an operation using provided buffers completes, the CQE indicates
+which buffer was used:
+
+- **IORING_CQE_F_BUFFER** is set in *cqe-\>flags*
+
+- The buffer ID is in the upper 16 bits of *cqe-\>flags*, extractable
+ via **cqe-\>flags \>\> IORING_CQE_BUFFER_SHIFT**
+
+- *cqe-\>res* contains the number of bytes transferred
+
+``` text
+struct io_uring_cqe *cqe;
+io_uring_wait_cqe(ring, &cqe);
+
+if (cqe->flags & IORING_CQE_F_BUFFER) {
+ int bid = cqe->flags >> IORING_CQE_BUFFER_SHIFT;
+ void *buf = buffers[bid]; /* application's buffer tracking */
+ int len = cqe->res;
+
+ /* process data in buf */
+ process_data(buf, len);
+
+ /* return buffer to ring for reuse */
+ io_uring_buf_ring_add(br, buf, 4096, bid, mask, 0);
+ io_uring_buf_ring_advance(br, 1);
+}
+io_uring_cqe_seen(ring, cqe);
+```
+
+If no buffer was available when the operation completed, the operation
+fails with **-ENOBUFS**.
+
+## Multishot operations
+
+Provided buffers are particularly powerful with multishot operations
+like **io_uring_prep_recv_multishot**(3). A single SQE can generate
+multiple completions, each consuming a buffer from the ring:
+
+``` text
+struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
+io_uring_prep_recv_multishot(sqe, sockfd, NULL, 0, 0);
+io_uring_sqe_set_flags(sqe, IOSQE_BUFFER_SELECT);
+io_uring_sqe_set_buf_group(sqe, bgid);
+```
+
+Completions with **IORING_CQE_F_MORE** set indicate more completions
+will follow. The multishot operation continues until an error occurs,
+the buffer ring is exhausted, or the operation is canceled.
+
+## Incremental buffer consumption
+
+Buffer rings can be set up with the **IOU_PBUF_RING_INC** flag to enable
+incremental consumption. With this mode, large buffers can be partially
+consumed across multiple operations:
+
+- Completions with **IORING_CQE_F_BUF_MORE** indicate the buffer will be
+ used for more completions
+
+- Each completion picks up where the previous left off
+
+- The buffer is only returned when consumed completely or on error
+
+This is useful for registering large buffer regions that are consumed in
+smaller chunks.
+
+## Returning buffers
+
+When finished with a buffer, return it to the ring using
+**io_uring_buf_ring_add**(3) followed by
+**io_uring_buf_ring_advance**(3). For efficiency when processing
+multiple CQEs, use **io_uring_buf_ring_cq_advance**(3) to advance both
+the CQ and buffer ring in a single operation.
+
+## Buffer ring status
+
+Applications can query how many buffers are available using
+**io_uring_buf_ring_available**(3), which returns the number of buffers
+the kernel has not yet consumed. The current kernel head position can be
+retrieved with **io_uring_buf_ring_head**(3).
+
+## Cleaning up
+
+Buffer rings are freed using **io_uring_free_buf_ring**(3), which
+unregisters the ring and frees the ring memory (if it was allocated by
+**io_uring_setup_buf_ring**(3)). Applications must free the individual
+buffers themselves.
+
+# NOTES
+
+- Buffer ring entries must be a power of two, maximum 32768.
+
+- Buffer IDs are 16-bit values (0-65535).
+
+- If no buffer is available when an operation needs one, the operation
+ fails with **-ENOBUFS**. Applications should ensure the ring is
+ adequately stocked.
+
+- Provided buffers cannot be used with registered (fixed) buffers. These
+ are separate mechanisms.
+
+- For multishot receives, ensure buffers are returned to the ring
+ promptly to avoid running out.
+
+## Legacy provided buffers
+
+Earlier kernels supported provided buffers via
+**IORING_OP_PROVIDE_BUFFERS** and **IORING_OP_REMOVE_BUFFERS**. This
+mechanism required submitting SQEs to add or remove buffers, adding
+latency and overhead. The ring-based mechanism described above
+supersedes this approach and should be used for all new applications.
+The legacy interface remains for backwards compatibility.
+
+# SEE ALSO
+
+**io_uring**(7), **io_uring_setup_buf_ring**(3),
+**io_uring_free_buf_ring**(3), **io_uring_register_buf_ring**(3),
+**io_uring_unregister_buf_ring**(3), **io_uring_buf_ring_add**(3),
+**io_uring_buf_ring_advance**(3), **io_uring_buf_ring_cq_advance**(3),
+**io_uring_buf_ring_available**(3), **io_uring_prep_recv_multishot**(3)
diff --git a/man/io_uring_queue_exit.3 b/man/io_uring_queue_exit.3
deleted file mode 100644
index 6425ffcf..00000000
--- a/man/io_uring_queue_exit.3
+++ /dev/null
@@ -1,30 +0,0 @@
-.\" Copyright (C) 2020 Jens Axboe <axboe@kernel.dk>
-.\" Copyright (C) 2020 Red Hat, Inc.
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_queue_exit 3 "July 10, 2020" "liburing-0.7" "liburing Manual"
-.SH NAME
-io_uring_queue_exit \- tear down io_uring submission and completion queues
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_queue_exit(struct io_uring *" ring ");"
-.fi
-.SH DESCRIPTION
-.PP
-.BR io_uring_queue_exit (3)
-will release all resources acquired and initialized by
-.BR io_uring_queue_init (3).
-It first unmaps the memory shared between the application and the kernel and then closes the io_uring file descriptor.
-
-Some accounting is done asynchronously, so memory locked by
-.BR io_uring_queue_init (3)
-may remain locked for a few milliseconds after this function returns.
-.SH RETURN VALUE
-None
-.SH SEE ALSO
-.BR io_uring_setup (2),
-.BR mmap (2),
-.BR io_uring_queue_init (3)
diff --git a/man/io_uring_queue_exit.3.md b/man/io_uring_queue_exit.3.md
new file mode 100644
index 00000000..7db2fe48
--- /dev/null
+++ b/man/io_uring_queue_exit.3.md
@@ -0,0 +1,44 @@
+.\" Copyright (C) 2020 Jens Axboe <axboe@kernel.dk>
+.\" Copyright (C) 2020 Red Hat, Inc.
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: July 10, 2020
+footer: liburing-0.7
+header: liburing Manual
+section: 3
+title: io_uring_queue_exit
+---
+
+# NAME
+
+io_uring_queue_exit - tear down io_uring submission and completion
+queues
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_queue_exit(struct io_uring * ring );
+```
+
+# DESCRIPTION
+
+**io_uring_queue_exit**(3) will release all resources acquired and
+initialized by **io_uring_queue_init**(3). It first unmaps the memory
+shared between the application and the kernel and then closes the
+io_uring file descriptor.
+
+Some accounting is done asynchronously, so memory locked by
+**io_uring_queue_init**(3) may remain locked for a few milliseconds
+after this function returns.
+
+# RETURN VALUE
+
+None
+
+# SEE ALSO
+
+**io_uring_setup**(2), **mmap**(2), **io_uring_queue_init**(3)
diff --git a/man/io_uring_queue_init.3 b/man/io_uring_queue_init.3
deleted file mode 100644
index 24015d69..00000000
--- a/man/io_uring_queue_init.3
+++ /dev/null
@@ -1,144 +0,0 @@
-.\" Copyright (C) 2020 Jens Axboe <axboe@kernel.dk>
-.\" Copyright (C) 2020 Red Hat, Inc.
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_queue_init 3 "July 10, 2020" "liburing-0.7" "liburing Manual"
-.SH NAME
-io_uring_queue_init \- setup io_uring submission and completion queues
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_queue_init(unsigned " entries ","
-.BI " struct io_uring *" ring ","
-.BI " unsigned " flags ");"
-.PP
-.BI "int io_uring_queue_init_params(unsigned " entries ","
-.BI " struct io_uring *" ring ","
-.BI " struct io_uring_params *" params ");"
-.PP
-.BI "int io_uring_queue_init_mem(unsigned " entries ","
-.BI " struct io_uring *" ring ","
-.BI " struct io_uring_params *" params ","
-.BI " void *" buf ", size_t " buf_size ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_queue_init (3)
-function executes the
-.BR io_uring_setup (2)
-system call to initialize the submission and completion queues in the kernel
-with at least
-.I entries
-entries in the submission queue and then maps the resulting file descriptor to
-memory shared between the application and the kernel.
-
-By default, the CQ ring will have twice the number of entries as specified by
-.I entries
-for the SQ ring. This is adequate for regular file or storage workloads, but
-may be too small for networked workloads. The SQ ring entries do not impose a
-limit on the number of in-flight requests that the ring can support, it merely
-limits the number that can be submitted to the kernel in one go (batch). If the
-CQ ring overflows, e.g. more entries are generated than fits in the ring before
-the application can reap them, then if the kernel supports
-.B IORING_FEAT_NODROP
-the ring enters a CQ ring overflow state. Otherwise it drops the CQEs and
-increments
-.I cq.koverflow
-in
-.I struct io_uring
-with the number of CQEs dropped. The overflow state is indicated by
-.B IORING_SQ_CQ_OVERFLOW
-being set in the SQ ring flags. Unless the kernel runs out of available memory,
-entries are not dropped, but it is a much slower completion path and will slow
-down request processing. For that reason it should be avoided and the CQ
-ring sized appropriately for the workload. Setting
-.I cq_entries
-in
-.I struct io_uring_params
-will tell the kernel to allocate this many entries for the CQ ring, independent
-of the SQ ring size in given in
-.IR entries .
-If the value isn't a power of 2, it will be rounded up to the nearest power of
-2.
-
-On success,
-.BR io_uring_queue_init (3)
-returns 0 and
-.I ring
-will point to the shared memory containing the io_uring queues. On failure
-.BR -errno
-is returned.
-
-.I flags
-will be passed through to the io_uring_setup syscall (see
-.BR io_uring_setup (2)).
-
-The
-.BR io_uring_queue_init_params (3)
-and
-.BR io_uring_queue_init_mem (3)
-variants will pass the parameters indicated by
-.I params
-straight through to the
-.BR io_uring_setup (2)
-system call.
-
-The
-.BR io_uring_queue_init_mem (3)
-variant uses the provided
-.I buf
-with associated size
-.I buf_size
-as the memory for the ring, using the
-.B IORING_SETUP_NO_MMAP
-flag to
-.BR io_uring_setup (2).
-The buffer passed to
-.BR io_uring_queue_init_mem (3)
-must be page size aligned on the host, and must already be zeroed.
-Typically, the caller should allocate a huge page and pass that in to
-.BR io_uring_queue_init_mem (3).
-Pages allocated by mmap are already zeroed.
-.BR io_uring_queue_init_mem (3)
-returns the number of bytes used from the provided buffer, so that the app can
-reuse the buffer with the returned offset to put more rings in the same huge
-page.
-
-On success, the resources held by
-.I ring
-should be released via a corresponding call to
-.BR io_uring_queue_exit (3).
-.SH RETURN VALUE
-.BR io_uring_queue_init (3)
-and
-.BR io_uring_queue_init_params (3)
-return 0 on success and
-.BR -errno
-on failure.
-A return value of
-.BR -ENOMEM
-indicates there is not enough locked memory available to hold the specified
-number of entries.
-Reduce the number of entries, or call
-.BR setrlimit (2)
-to increase the maximum number of bytes of memory that may be locked into RAM.
-Be aware that calling
-.BR io_uring_queue_init (3)
-and
-.BR io_uring_queue_exit (3)
-in a loop will temporarily lock a lot of memory, because
-.BR io_uring_queue_exit (3)
-does some of its accounting asynchronously.
-
-.BR io_uring_queue_init_mem (3)
-returns the number of bytes used from the provided buffer on success, and
-.BR -errno
-on failure.
-.SH SEE ALSO
-.BR io_uring_setup (2),
-.BR io_uring_register_ring_fd (3),
-.BR mmap (2),
-.BR io_uring_queue_exit (3)
diff --git a/man/io_uring_queue_init.3.md b/man/io_uring_queue_init.3.md
new file mode 100644
index 00000000..5bf04136
--- /dev/null
+++ b/man/io_uring_queue_init.3.md
@@ -0,0 +1,109 @@
+.\" Copyright (C) 2020 Jens Axboe <axboe@kernel.dk>
+.\" Copyright (C) 2020 Red Hat, Inc.
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: July 10, 2020
+footer: liburing-0.7
+header: liburing Manual
+section: 3
+title: io_uring_queue_init
+---
+
+# NAME
+
+io_uring_queue_init - setup io_uring submission and completion queues
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_queue_init(unsigned entries ,
+ struct io_uring * ring ,
+ unsigned flags );
+
+ int io_uring_queue_init_params(unsigned entries ,
+ struct io_uring * ring ,
+ struct io_uring_params * params );
+
+ int io_uring_queue_init_mem(unsigned entries ,
+ struct io_uring * ring ,
+ struct io_uring_params * params ,
+ void * buf , size_t buf_size );
+```
+
+# DESCRIPTION
+
+The **io_uring_queue_init**(3) function executes the
+**io_uring_setup**(2) system call to initialize the submission and
+completion queues in the kernel with at least *entries* entries in the
+submission queue and then maps the resulting file descriptor to memory
+shared between the application and the kernel.
+
+By default, the CQ ring will have twice the number of entries as
+specified by *entries* for the SQ ring. This is adequate for regular
+file or storage workloads, but may be too small for networked workloads.
+The SQ ring entries do not impose a limit on the number of in-flight
+requests that the ring can support, it merely limits the number that can
+be submitted to the kernel in one go (batch). If the CQ ring overflows,
+e.g. more entries are generated than fits in the ring before the
+application can reap them, then if the kernel supports
+**IORING_FEAT_NODROP** the ring enters a CQ ring overflow state.
+Otherwise it drops the CQEs and increments *cq.koverflow* in *struct
+io_uring* with the number of CQEs dropped. The overflow state is
+indicated by **IORING_SQ_CQ_OVERFLOW** being set in the SQ ring flags.
+Unless the kernel runs out of available memory, entries are not dropped,
+but it is a much slower completion path and will slow down request
+processing. For that reason it should be avoided and the CQ ring sized
+appropriately for the workload. Setting *cq_entries* in *struct
+io_uring_params* will tell the kernel to allocate this many entries for
+the CQ ring, independent of the SQ ring size in given in *entries*. If
+the value isn\'t a power of 2, it will be rounded up to the nearest
+power of 2.
+
+On success, **io_uring_queue_init**(3) returns 0 and *ring* will point
+to the shared memory containing the io_uring queues. On failure
+**-errno** is returned.
+
+*flags* will be passed through to the io_uring_setup syscall (see
+**io_uring_setup**(2)).
+
+The **io_uring_queue_init_params**(3) and **io_uring_queue_init_mem**(3)
+variants will pass the parameters indicated by *params* straight through
+to the **io_uring_setup**(2) system call.
+
+The **io_uring_queue_init_mem**(3) variant uses the provided *buf* with
+associated size *buf_size* as the memory for the ring, using the
+**IORING_SETUP_NO_MMAP** flag to **io_uring_setup**(2). The buffer
+passed to **io_uring_queue_init_mem**(3) must be page size aligned on
+the host, and must already be zeroed. Typically, the caller should
+allocate a huge page and pass that in to **io_uring_queue_init_mem**(3).
+Pages allocated by mmap are already zeroed.
+**io_uring_queue_init_mem**(3) returns the number of bytes used from the
+provided buffer, so that the app can reuse the buffer with the returned
+offset to put more rings in the same huge page.
+
+On success, the resources held by *ring* should be released via a
+corresponding call to **io_uring_queue_exit**(3).
+
+# RETURN VALUE
+
+**io_uring_queue_init**(3) and **io_uring_queue_init_params**(3) return
+0 on success and **-errno** on failure. A return value of **-ENOMEM**
+indicates there is not enough locked memory available to hold the
+specified number of entries. Reduce the number of entries, or call
+**setrlimit**(2) to increase the maximum number of bytes of memory that
+may be locked into RAM. Be aware that calling **io_uring_queue_init**(3)
+and **io_uring_queue_exit**(3) in a loop will temporarily lock a lot of
+memory, because **io_uring_queue_exit**(3) does some of its accounting
+asynchronously.
+
+**io_uring_queue_init_mem**(3) returns the number of bytes used from the
+provided buffer on success, and **-errno** on failure.
+
+# SEE ALSO
+
+**io_uring_setup**(2), **io_uring_register_ring_fd**(3), **mmap**(2),
+**io_uring_queue_exit**(3)
diff --git a/man/io_uring_queue_mmap.3 b/man/io_uring_queue_mmap.3
deleted file mode 100644
index 43351253..00000000
--- a/man/io_uring_queue_mmap.3
+++ /dev/null
@@ -1,49 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_queue_mmap 3 "January 18, 2025" "liburing-2.4" "liburing Manual"
-.SH NAME
-io_uring_queue_mmap \- mmap io_uring ring after setup
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_queue_mmap(int " fd ", struct io_uring_params *" p ","
-.BI " struct io_uring *" ring ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_queue_mmap (3)
-function maps the io_uring ring file descriptor
-.I fd
-into memory using the parameters in
-.IR p .
-The resulting ring is stored in
-.IR ring .
-
-This function is a helper for applications that need to customize the ring
-setup process. Most applications should use
-.BR io_uring_queue_init (3)
-or
-.BR io_uring_queue_init_params (3)
-instead, which call
-.BR io_uring_setup (2)
-and this function automatically.
-
-The
-.I fd
-argument should be a file descriptor returned by
-.BR io_uring_setup (2),
-and
-.I p
-should contain the parameters returned by the setup call.
-
-.SH RETURN VALUE
-Returns 0 on success, or a negative errno value on error.
-.SH SEE ALSO
-.BR io_uring_setup (2),
-.BR io_uring_queue_init (3),
-.BR io_uring_queue_init_params (3),
-.BR io_uring_queue_exit (3)
diff --git a/man/io_uring_queue_mmap.3.md b/man/io_uring_queue_mmap.3.md
new file mode 100644
index 00000000..674c72a0
--- /dev/null
+++ b/man/io_uring_queue_mmap.3.md
@@ -0,0 +1,48 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 18, 2025
+footer: liburing-2.4
+header: liburing Manual
+section: 3
+title: io_uring_queue_mmap
+---
+
+# NAME
+
+io_uring_queue_mmap - mmap io_uring ring after setup
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_queue_mmap(int fd , struct io_uring_params * p ,
+ struct io_uring * ring );
+```
+
+# DESCRIPTION
+
+The **io_uring_queue_mmap**(3) function maps the io_uring ring file
+descriptor *fd* into memory using the parameters in *p*. The resulting
+ring is stored in *ring*.
+
+This function is a helper for applications that need to customize the
+ring setup process. Most applications should use
+**io_uring_queue_init**(3) or **io_uring_queue_init_params**(3) instead,
+which call **io_uring_setup**(2) and this function automatically.
+
+The *fd* argument should be a file descriptor returned by
+**io_uring_setup**(2), and *p* should contain the parameters returned by
+the setup call.
+
+# RETURN VALUE
+
+Returns 0 on success, or a negative errno value on error.
+
+# SEE ALSO
+
+**io_uring_setup**(2), **io_uring_queue_init**(3),
+**io_uring_queue_init_params**(3), **io_uring_queue_exit**(3)
diff --git a/man/io_uring_recvmsg_out.3 b/man/io_uring_recvmsg_out.3
deleted file mode 100644
index 8d605d81..00000000
--- a/man/io_uring_recvmsg_out.3
+++ /dev/null
@@ -1,82 +0,0 @@
-.\" Copyright (C), 2022 Dylan Yudaken <dylany@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_recvmsg_out 3 "July 26, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_recvmsg_out - access data from multishot recvmsg
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "struct io_uring_recvmsg_out *io_uring_recvmsg_validate(void *" buf ","
-.BI " int " buf_len ","
-.BI " struct msghdr *" msgh ");"
-.PP
-.BI "void *io_uring_recvmsg_name(struct io_uring_recvmsg_out *" o ");"
-.PP
-.BI "struct cmsghdr *io_uring_recvmsg_cmsg_firsthdr(struct io_uring_recvmsg_out *" o ","
-.BI " struct msghdr *" msgh ");"
-.BI "struct cmsghdr *io_uring_recvmsg_cmsg_nexthdr(struct io_uring_recvmsg_out *" o ","
-.BI " struct msghdr *" msgh ","
-.BI " struct cmsghdr *" cmsg ");"
-.PP
-.BI "void *io_uring_recvmsg_payload(struct io_uring_recvmsg_out *" o ","
-.BI " struct msghdr *" msgh ");"
-.BI "unsigned int io_uring_recvmsg_payload_length(struct io_uring_recvmsg_out *" o ","
-.BI " int " buf_len ","
-.BI " struct msghdr *" msgh ");"
-.PP
-.fi
-
-.SH DESCRIPTION
-
-These functions are used to access data in the payload delivered by
-.BR io_uring_prep_recvmsg_multishot (3).
-.PP
-.I msgh
-should point to the
-.I struct msghdr
-submitted with the request.
-.PP
-.BR io_uring_recvmsg_validate (3)
-will validate a buffer delivered by
-.BR io_uring_prep_recvmsg_multishot (3)
-and extract the
-.I io_uring_recvmsg_out
-if it is valid, returning a pointer to it or else NULL.
-.PP
-The structure is defined as follows:
-.PP
-.in +4n
-.EX
-
-struct io_uring_recvmsg_out {
- __u32 namelen; /* Name byte count as would have been populated
- * by recvmsg(2) */
- __u32 controllen; /* Control byte count */
- __u32 payloadlen; /* Payload byte count as would have been returned
- * by recvmsg(2) */
- __u32 flags; /* Flags result as would have been populated
- * by recvmsg(2) */
-};
-
-.IP * 3
-.BR io_uring_recvmsg_name (3)
-returns a pointer to the name in the buffer.
-.IP *
-.BR io_uring_recvmsg_cmsg_firsthdr (3)
-returns a pointer to the first cmsg in the buffer, or NULL.
-.IP *
-.BR io_uring_recvmsg_cmsg_nexthdr (3)
-returns a pointer to the next cmsg in the buffer, or NULL.
-.IP *
-.BR io_uring_recvmsg_payload (3)
-returns a pointer to the payload in the buffer.
-.IP *
-.BR io_uring_recvmsg_payload_length (3)
-Calculates the usable payload length in bytes.
-
-
-.SH "SEE ALSO"
-.BR io_uring_prep_recvmsg_multishot (3)
diff --git a/man/io_uring_recvmsg_out.3.md b/man/io_uring_recvmsg_out.3.md
new file mode 100644
index 00000000..fe1f9085
--- /dev/null
+++ b/man/io_uring_recvmsg_out.3.md
@@ -0,0 +1,82 @@
+.\" Copyright (C), 2022 Dylan Yudaken <dylany@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: July 26, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_recvmsg_out
+---
+
+# NAME
+
+io_uring_recvmsg_out - access data from multishot recvmsg
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ struct io_uring_recvmsg_out *io_uring_recvmsg_validate(void * buf ,
+ int buf_len ,
+ struct msghdr * msgh );
+
+ void *io_uring_recvmsg_name(struct io_uring_recvmsg_out * o );
+
+ struct cmsghdr *io_uring_recvmsg_cmsg_firsthdr(struct io_uring_recvmsg_out * o ,
+ struct msghdr * msgh );
+ struct cmsghdr *io_uring_recvmsg_cmsg_nexthdr(struct io_uring_recvmsg_out * o ,
+ struct msghdr * msgh ,
+ struct cmsghdr * cmsg );
+
+ void *io_uring_recvmsg_payload(struct io_uring_recvmsg_out * o ,
+ struct msghdr * msgh );
+ unsigned int io_uring_recvmsg_payload_length(struct io_uring_recvmsg_out * o ,
+ int buf_len ,
+ struct msghdr * msgh );
+```
+
+# DESCRIPTION
+
+These functions are used to access data in the payload delivered by
+**io_uring_prep_recvmsg_multishot**(3).
+
+*msgh* should point to the *struct msghdr* submitted with the request.
+
+**io_uring_recvmsg_validate**(3) will validate a buffer delivered by
+**io_uring_prep_recvmsg_multishot**(3) and extract the
+*io_uring_recvmsg_out* if it is valid, returning a pointer to it or else
+NULL.
+
+The structure is defined as follows:
+
+``` text
+
+struct io_uring_recvmsg_out {
+ __u32 namelen; /* Name byte count as would have been populated
+ * by recvmsg(2) */
+ __u32 controllen; /* Control byte count */
+ __u32 payloadlen; /* Payload byte count as would have been returned
+ * by recvmsg(2) */
+ __u32 flags; /* Flags result as would have been populated
+ * by recvmsg(2) */
+};
+
+io_uring_recvmsg_name(3)
+returns a pointer to the name in the buffer.
+io_uring_recvmsg_cmsg_firsthdr(3)
+returns a pointer to the first cmsg in the buffer, or NULL.
+io_uring_recvmsg_cmsg_nexthdr(3)
+returns a pointer to the next cmsg in the buffer, or NULL.
+io_uring_recvmsg_payload(3)
+returns a pointer to the payload in the buffer.
+io_uring_recvmsg_payload_length(3)
+Calculates the usable payload length in bytes.
+
+```
+
+# SEE ALSO
+
+**io_uring_prep_recvmsg_multishot**(3)
diff --git a/man/io_uring_register.2 b/man/io_uring_register.2
deleted file mode 100644
index 1b36ce1f..00000000
--- a/man/io_uring_register.2
+++ /dev/null
@@ -1,1375 +0,0 @@
-.\" Copyright (C) 2019 Jens Axboe <axboe@kernel.dk>
-.\" Copyright (C) 2019 Red Hat, Inc.
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_register 2 "January 17, 2019" "Linux" "Linux Programmer's Manual"
-.SH NAME
-io_uring_register \- register files or user buffers for asynchronous I/O
-.SH SYNOPSIS
-.nf
-.BR "#include <liburing.h>"
-.PP
-.BI "int io_uring_register(unsigned int " fd ", unsigned int " opcode ,
-.BI " void *" arg ", unsigned int " nr_args );
-.fi
-.PP
-.SH DESCRIPTION
-.PP
-
-The
-.BR io_uring_register (2)
-system call registers resources (e.g. user buffers, files, eventfd,
-personality, restrictions) for use in an
-.BR io_uring (7)
-instance referenced by
-.IR fd .
-Registering files or user buffers allows the kernel to take long term
-references to internal data structures or create long term mappings of
-application memory, greatly reducing per-I/O overhead.
-
-.I fd
-is the file descriptor returned by a call to
-.BR io_uring_setup (2).
-If
-.I opcode
-has the flag
-.B IORING_REGISTER_USE_REGISTERED_RING
-ored into it,
-.I fd
-is instead the index of a registered ring fd.
-
-.I opcode
-can be one of:
-
-.TP
-.B IORING_REGISTER_BUFFERS
-.I arg
-points to a
-.I struct iovec
-array of
-.I nr_args
-entries. The buffers associated with the iovecs will be locked in
-memory and charged against the user's
-.B RLIMIT_MEMLOCK
-resource limit. See
-.BR getrlimit (2)
-for more information. Additionally, there is a size limit of 1GiB per
-buffer. Currently, the buffers must be anonymous, non-file-backed
-memory, such as that returned by
-.BR malloc (3)
-or
-.BR mmap (2)
-with the
-.B MAP_ANONYMOUS
-flag set. It is expected that this limitation will be lifted in the
-future. Huge pages are supported as well. Note that the entire huge
-page will be pinned in the kernel, even if only a portion of it is
-used.
-
-After a successful call, the supplied buffers are mapped into the
-kernel and eligible for I/O. To make use of them, the application
-must specify the
-.B IORING_OP_READ_FIXED
-or
-.B IORING_OP_WRITE_FIXED
-opcodes in the submission queue entry (see the
-.I struct io_uring_sqe
-definition in
-.BR io_uring_enter (2)),
-and set the
-.I buf_index
-field to the desired buffer index. The memory range described by the
-submission queue entry's
-.I addr
-and
-.I len
-fields must fall within the indexed buffer.
-
-It is perfectly valid to setup a large buffer and then only use part
-of it for an I/O, as long as the range is within the originally mapped
-region.
-
-An application can increase or decrease the size or number of
-registered buffers by first unregistering the existing buffers, and
-then issuing a new call to
-.BR io_uring_register (2)
-with the new buffers.
-
-Note that before 5.13 registering buffers would wait for the ring to idle.
-If the application currently has requests in-flight, the registration will
-wait for those to finish before proceeding.
-
-An application need not unregister buffers explicitly before shutting
-down the io_uring instance. Note, however, that shutdown processing may run
-asynchronously within the kernel. As a result, it is not guaranteed that
-pages are immediately unpinned in this case. Available since 5.1.
-
-.TP
-.B IORING_REGISTER_BUFFERS2
-Register buffers for I/O. Similar to
-.B IORING_REGISTER_BUFFERS
-but aims to have a more extensible ABI.
-
-.I arg
-points to a
-.I struct
-.IR io_uring_rsrc_register ,
-and
-.I nr_args
-should be set to the number of bytes in the structure.
-
-.IP
-.in +4n
-.EX
-struct io_uring_rsrc_register {
- __u32 nr;
- __u32 flags;
- __u64 resv2;
- __aligned_u64 data;
- __aligned_u64 tags;
-};
-.EE
-.in
-.IP
-
-The
-.I data
-field contains a pointer to a
-.I struct iovec
-array of
-.I nr
-entries.
-The
-.I tags
-field should either be 0, then tagging is disabled, or point to an array
-of
-.I nr
-"tags" (unsigned 64 bit integers). If a tag is zero, then tagging for this
-particular resource (a buffer in this case) is disabled. Otherwise, after the
-resource had been unregistered and it's not used anymore, a CQE will be
-posted with
-.I user_data
-set to the specified tag and all other fields zeroed.
-
-The
-.I flags
-field supports the following flags:
-
-.IP
-.in +4n
-.B IORING_RSRC_REGISTER_SPARSE
-If set, io_uring will register
-.I nr
-empty buffers, which need to be updated before use. When this flag is set,
-.I data
-and
-.I tags
-must be NULL. Available since 5.19.
-.in
-.IP
-
-Note that resource updates, e.g.
-.BR IORING_REGISTER_BUFFERS_UPDATE ,
-don't necessarily deallocate resources by the time it returns, but they might
-be held alive until all requests using it complete.
-
-Available since 5.13.
-
-.TP
-.B IORING_REGISTER_BUFFERS_UPDATE
-Updates registered buffers with new ones, either turning a sparse entry into
-a real one, or replacing an existing entry.
-
-.I arg
-must contain a pointer to a
-.I struct
-.IR io_uring_rsrc_update2 ,
-which contains
-an offset on which to start the update, and an array of
-.I struct
-.IR iovec .
-.I tags
-points to an array of tags.
-.I nr
-must contain the number of descriptors in the passed in arrays.
-See
-.B IORING_REGISTER_BUFFERS2
-for the resource tagging description.
-
-.PP
-.in +8n
-.EX
-
-struct io_uring_rsrc_update2 {
- __u32 offset;
- __u32 resv;
- __aligned_u64 data;
- __aligned_u64 tags;
- __u32 nr;
- __u32 resv2;
-};
-.EE
-.in
-.PP
-
-.in +8n
-
-Available since 5.13.
-
-.TP
-.B IORING_UNREGISTER_BUFFERS
-This operation takes no argument, and
-.I arg
-must be passed as NULL. All previously registered buffers associated
-with the io_uring instance will be released synchronously. Available since 5.1.
-
-.TP
-.B IORING_REGISTER_FILES
-Register files for I/O.
-.I arg
-contains a pointer to an array of
-.I nr_args
-file descriptors (signed 32 bit integers).
-
-To make use of the registered files, the
-.B IOSQE_FIXED_FILE
-flag must be set in the
-.I flags
-member of the
-.IR "struct io_uring_sqe" ,
-and the
-.I fd
-member is set to the index of the file in the file descriptor array.
-
-The file set may be sparse, meaning that the
-.B fd
-field in the array may be set to
-.BR -1 .
-See
-.B IORING_REGISTER_FILES_UPDATE
-for how to update files in place.
-
-Note that before 5.13 registering files would wait for the ring to idle.
-If the application currently has requests in-flight, the registration will
-wait for those to finish before proceeding. See
-.B IORING_REGISTER_FILES_UPDATE
-for how to update an existing set without that limitation.
-
-Files are automatically unregistered when the io_uring instance is
-torn down. An application needs only unregister if it wishes to
-register a new set of fds. Available since 5.1.
-
-.TP
-.B IORING_REGISTER_FILES2
-Register files for I/O. Similar to
-.BR IORING_REGISTER_FILES .
-
-.I arg
-points to a
-.I struct
-.IR io_uring_rsrc_register ,
-and
-.I nr_args
-should be set to the number of bytes in the structure.
-
-The
-.I data
-field contains a pointer to an array of
-.I nr
-file descriptors (signed 32 bit integers).
-.I tags
-field should either be 0 or or point to an array of
-.I nr
-"tags" (unsigned 64 bit integers). See
-.B IORING_REGISTER_BUFFERS2
-for more info on resource tagging.
-
-Note that resource updates, e.g.
-.BR IORING_REGISTER_FILES_UPDATE ,
-don't necessarily deallocate resources, they might be held until all requests
-using that resource complete.
-
-Available since 5.13.
-
-.TP
-.B IORING_REGISTER_FILES_UPDATE
-This operation replaces existing files in the registered file set with new
-ones, either turning a sparse entry (one where fd is equal to
-.BR -1 )
-into a real one, removing an existing entry (new one is set to
-.BR -1 ),
-or replacing an existing entry with a new existing entry.
-
-.I arg
-must contain a pointer to a
-.I struct
-.IR io_uring_rsrc_update ,
-which contains
-an offset on which to start the update, and an array of file descriptors to
-use for the update.
-.I nr_args
-must contain the number of descriptors in the passed in array. Available
-since 5.5.
-
-File descriptors can be skipped if they are set to
-.BR IORING_REGISTER_FILES_SKIP .
-Skipping an fd will not touch the file associated with the previous
-fd at that index. Available since 5.12.
-
-.TP
-.B IORING_REGISTER_FILES_UPDATE2
-Similar to
-.BR IORING_REGISTER_FILES_UPDATE ,
-replaces existing files in the
-registered file set with new ones, either turning a sparse entry (one where
-fd is equal to
-.BR -1 )
-into a real one, removing an existing entry (new one is set to
-.BR -1 ),
-or replacing an existing entry with a new existing entry.
-
-.I arg
-must contain a pointer to a
-.I struct
-.IR io_uring_rsrc_update2 ,
-which contains
-an offset on which to start the update, and an array of file descriptors to
-use for the update stored in
-.IR data .
-.I tags
-points to an array of tags.
-.I nr
-must contain the number of descriptors in the passed in arrays.
-See
-.B IORING_REGISTER_BUFFERS2
-for the resource tagging description.
-
-Available since 5.13.
-
-.TP
-.B IORING_UNREGISTER_FILES
-This operation requires no argument, and
-.I arg
-must be passed as NULL. All previously registered files associated
-with the io_uring instance will be unregistered. Available since 5.1.
-
-.TP
-.B IORING_REGISTER_EVENTFD
-It's possible to use
-.BR eventfd (2)
-to get notified of completion events on an
-io_uring instance. If this is desired, an eventfd file descriptor can be
-registered through this operation.
-.I arg
-must contain a pointer to the eventfd file descriptor, and
-.I nr_args
-must be 1. Note that while io_uring generally takes care to avoid spurious
-events, they can occur. Similarly, batched completions of CQEs may only trigger
-a single eventfd notification even if multiple CQEs are posted. The application
-should make no assumptions on number of events being available having a direct
-correlation to eventfd notifications posted. An eventfd notification must thus
-only be treated as a hint to check the CQ ring for completions. Available since
-5.2.
-
-An application can temporarily disable notifications, coming through the
-registered eventfd, by setting the
-.B IORING_CQ_EVENTFD_DISABLED
-bit in the
-.I flags
-field of the CQ ring.
-Available since 5.8.
-
-.TP
-.B IORING_REGISTER_EVENTFD_ASYNC
-This works just like
-.BR IORING_REGISTER_EVENTFD ,
-except notifications are only posted for events that complete in an async
-manner. This means that events that complete inline while being submitted
-do not trigger a notification event. The arguments supplied are the same as
-for
-.BR IORING_REGISTER_EVENTFD .
-Available since 5.6.
-
-.TP
-.B IORING_UNREGISTER_EVENTFD
-Unregister an eventfd file descriptor to stop notifications. Since only one
-eventfd descriptor is currently supported, this operation takes no argument,
-and
-.I arg
-must be passed as NULL and
-.I nr_args
-must be zero. Available since 5.2.
-
-.TP
-.B IORING_REGISTER_PROBE
-This operation returns a structure, io_uring_probe, which contains information
-about the opcodes supported by io_uring on the running kernel.
-.I arg
-must contain a pointer to a struct io_uring_probe, and
-.I nr_args
-must contain the size of the ops array in that probe struct. The ops array
-is of the type io_uring_probe_op, which holds the value of the opcode and
-a flags field. If the flags field has
-.B IO_URING_OP_SUPPORTED
-set, then this opcode is supported on the running kernel. Available since 5.6.
-
-.TP
-.B IORING_REGISTER_PERSONALITY
-This operation registers credentials of the running application with io_uring,
-and returns an id associated with these credentials. Applications wishing to
-share a ring between separate users/processes can pass in this credential id
-in the sqe
-.B personality
-field. If set, that particular sqe will be issued with these credentials. Must
-be invoked with
-.I arg
-set to NULL and
-.I nr_args
-set to zero. Available since 5.6.
-
-.TP
-.B IORING_UNREGISTER_PERSONALITY
-This operation unregisters a previously registered personality with io_uring.
-.I nr_args
-must be set to the id in question, and
-.I arg
-must be set to NULL. Available since 5.6.
-
-.TP
-.B IORING_REGISTER_ENABLE_RINGS
-This operation enables an io_uring ring started in a disabled state
-.RB ( IORING_SETUP_R_DISABLED
-was specified in the call to
-.BR io_uring_setup (2)).
-While the io_uring ring is disabled, submissions are not allowed and
-registrations are not restricted.
-
-After the execution of this operation, the io_uring ring is enabled:
-submissions and registration are allowed, but they will
-be validated following the registered restrictions (if any).
-This operation takes no argument, must be invoked with
-.I arg
-set to NULL and
-.I nr_args
-set to zero. Available since 5.10.
-
-.TP
-.B IORING_REGISTER_RESTRICTIONS
-.I arg
-points to a
-.I struct io_uring_restriction
-array of
-.I nr_args
-entries.
-
-With an entry it is possible to allow an
-.BR io_uring_register (2)
-.IR opcode ,
-or specify which
-.I opcode
-and
-.I flags
-of the submission queue entry are allowed,
-or require certain
-.I flags
-to be specified (these flags must be set on each submission queue entry).
-
-All the restrictions must be submitted with a single
-.BR io_uring_register (2)
-call and they are handled as an allowlist (opcodes and flags not registered,
-are not allowed).
-
-Restrictions can be registered only if the io_uring ring started in a disabled
-state
-.RB ( IORING_SETUP_R_DISABLED
-must be specified in the call to
-.BR io_uring_setup (2)).
-
-Available since 5.10.
-
-.TP
-.B IORING_REGISTER_IOWQ_AFF
-By default, async workers created by io_uring will inherit the CPU mask of its
-parent. This is usually all the CPUs in the system, unless the parent is being
-run with a limited set. If this isn't the desired outcome, the application
-may explicitly tell io_uring what CPUs the async workers may run on.
-.I arg
-must point to a
-.B cpu_set_t
-mask, and
-.I nr_args
-the byte size of that mask.
-
-Available since 5.14.
-
-.TP
-.B IORING_UNREGISTER_IOWQ_AFF
-Undoes a CPU mask previously set with
-.BR IORING_REGISTER_IOWQ_AFF .
-Must not have
-.I arg
-or
-.I nr_args
-set.
-
-Available since 5.14.
-
-.TP
-.B IORING_REGISTER_IOWQ_MAX_WORKERS
-By default, io_uring limits the unbounded workers created to the maximum
-processor count set by
-.I RLIMIT_NPROC
-and the bounded workers is a function of the SQ ring size and the number
-of CPUs in the system. Sometimes this can be excessive (or too little, for
-bounded), and this command provides a way to change the count per ring (per NUMA
-node) instead.
-
-.I arg
-must be set to an
-.I unsigned int
-pointer to an array of two values, with the values in the array being set to
-the maximum count of workers per NUMA node. Index 0 holds the bounded worker
-count, and index 1 holds the unbounded worker count. On successful return, the
-passed in array will contain the previous maximum values for each type. If the
-count being passed in is 0, then this command returns the current maximum values
-and doesn't modify the current setting.
-.I nr_args
-must be set to 2, as the command takes two values.
-
-Available since 5.15.
-
-.TP
-.B IORING_REGISTER_RING_FDS
-Whenever
-.BR io_uring_enter (2)
-is called to submit request or wait for completions, the kernel must grab a
-reference to the file descriptor. If the application using io_uring is threaded,
-the file table is marked as shared, and the reference grab and put of the file
-descriptor count is more expensive than it is for a non-threaded application.
-
-Similarly to how io_uring allows registration of files, this allow registration
-of the ring file descriptor itself. This reduces the overhead of the
-.BR io_uring_enter (2)
-system call.
-
-.I arg
-must be set to a pointer to an array of type
-.I struct io_uring_rsrc_update
-of
-.I nr_args
-number of entries. The
-.B data
-field of this struct must contain an io_uring file descriptor, and the
-.B offset
-field can be either
-.B -1
-or an explicit offset desired for the registered file descriptor value. If
-.B -1
-is used, then upon successful return of this system call, the field will
-contain the value of the registered file descriptor to be used for future
-.BR io_uring_enter (2)
-system calls.
-
-On successful completion of this request, the returned descriptors may be used
-instead of the real file descriptor for
-.BR io_uring_enter (2),
-provided that
-.B IORING_ENTER_REGISTERED_RING
-is set in the
-.I flags
-for the system call. This flag tells the kernel that a registered descriptor
-is used rather than a real file descriptor.
-
-Each thread or process using a ring must register the file descriptor directly
-by issuing this request.
-
-The maximum number of supported registered ring descriptors is currently
-limited to
-.B 16.
-
-Available since 5.18.
-
-.TP
-.B IORING_UNREGISTER_RING_FDS
-Unregister descriptors previously registered with
-.BR IORING_REGISTER_RING_FDS .
-
-.I arg
-must be set to a pointer to an array of type
-.I struct io_uring_rsrc_update
-of
-.I nr_args
-number of entries. Only the
-.B offset
-field should be set in the structure, containing the registered file descriptor
-offset previously returned from
-.B IORING_REGISTER_RING_FDS
-that the application wishes to unregister.
-
-Note that this isn't done automatically on ring exit, if the thread or task
-that previously registered a ring file descriptor isn't exiting. It is
-recommended to manually unregister any previously registered ring descriptors
-if the ring is closed and the task persists. This will free up a registration
-slot, making it available for future use.
-
-Available since 5.18.
-
-.TP
-.B IORING_REGISTER_PBUF_RING
-Registers a shared buffer ring to be used with provided buffers. This is a
-newer alternative to using
-.B IORING_OP_PROVIDE_BUFFERS
-which is more efficient, to be used with request types that support the
-.B IOSQE_BUFFER_SELECT
-flag.
-
-The
-.I arg
-argument must be filled in with the appropriate information. It looks as
-follows:
-.PP
-.in +12n
-.EX
-struct io_uring_buf_reg {
- __u64 ring_addr;
- __u32 ring_entries;
- __u16 bgid;
- __u16 flags;
- __u32 min_left;
- __u32 resv[5];
-};
-.EE
-.in
-.PP
-.in +8n
-The
-.I ring_addr
-field must contain the address to the memory allocated to fit this ring.
-The memory must be page aligned and hence allocated appropriately using eg
-.BR posix_memalign (3)
-or similar. The size of the ring is the product of
-.I ring_entries
-and the size of
-.IR "struct io_uring_buf" .
-.I ring_entries
-is the desired size of the ring, and must be a power-of-2 in size. The maximum
-size allowed is 2^15 (32768).
-.I bgid
-is the buffer group ID associated with this ring. SQEs that select a buffer
-have a buffer group associated with them in their
-.I buf_group
-field, and the associated CQEs will have
-.B IORING_CQE_F_BUFFER
-set in their
-.I flags
-member, which will also contain the specific ID of the buffer selected.
-.I min_left
-is the minimum value that should be left in an incrementally consumed buffer
-ring for the buffer to be considered valid. If not set, defaults to a single
-byte. Only valid with
-.B IOU_PBUF_RING_INC
-set in
-.I flags .
-The rest of the fields are reserved and must be cleared to zero.
-
-.I nr_args
-must be set to 1.
-
-Also see
-.BR io_uring_register_buf_ring (3)
-for more details. Available since 5.19.
-
-.TP
-.B IORING_UNREGISTER_PBUF_RING
-Unregister a previously registered provided buffer ring.
-.I arg
-must be set to the address of a struct io_uring_buf_reg, with just the
-.I bgid
-field set to the buffer group ID of the previously registered provided buffer
-group.
-.I nr_args
-must be set to 1. Also see
-.BR IORING_REGISTER_PBUF_RING .
-
-Available since 5.19.
-
-.TP
-.B IORING_REGISTER_SYNC_CANCEL
-Performs a synchronous cancelation request, which works in a similar fashion to
-.B IORING_OP_ASYNC_CANCEL
-except it completes inline. This can be useful for scenarios where cancelations
-should happen synchronously, rather than needing to issue an SQE and wait for
-completion of that specific CQE.
-
-.I arg
-must be set to a pointer to a struct io_uring_sync_cancel_reg structure, with
-the details filled in for what request(s) to target for cancelation. See
-.BR io_uring_register_sync_cancel (3)
-for details on that. The return values are the same, except they are passed
-back synchronously rather than through the CQE
-.I res
-field.
-.I nr_args
-must be set to 1.
-
-Available since 6.0.
-
-.TP
-.B IORING_REGISTER_FILE_ALLOC_RANGE
-sets the allowable range for fixed file index allocations within the
-kernel. When requests that can instantiate a new fixed file are used with
-.BR IORING_FILE_INDEX_ALLOC ,
-the application is asking the kernel to allocate a new fixed file descriptor
-rather than pass in a specific value for one. By default, the kernel will
-pick any available fixed file descriptor within the range available.
-This effectively allows the application to set aside a range just for dynamic
-allocations, with the remainder being used for specific values.
-
-.I nr_args
-must be set to 1 and
-.I arg
-must be set to a pointer to a struct io_uring_file_index_range:
-.PP
-.in +12n
-.EX
-struct io_uring_file_index_range {
- __u32 off;
- __u32 len;
- __u64 resv;
-};
-.EE
-.in
-.PP
-.in +8n
-with
-.I off
-being set to the starting value for the range, and
-.I len
-being set to the number of descriptors. The reserved
-.I resv
-field must be cleared to zero.
-
-The application must have registered a file table first.
-
-Available since 6.0.
-
-.TP
-.B IORING_REGISTER_PBUF_STATUS
-Can be used to retrieve the current head of a ringbuffer provided earlier via
-.BR IORING_REGISTER_PBUF_RING .
-.I arg
-must point to a
-.PP
-.in +12
-.EX
-struct io_uring_buf_status {
- __u32 buf_group; /* input */
- __u32 head; /* output */
- __u32 resv[8];
-};
-.EE
-.in
-.PP
-.in +8
-of which
-.I arg->buf_group
-should contain the buffer group ID for the buffer ring in question,
-.I nr_args
-should be set to 1 and
-.I arg->resv
-should be zeroed out.
-The current head of the ringbuffer will be returned in
-.IR arg->head .
-
-Available since 6.8.
-
-.TP
-.B IORING_REGISTER_NAPI
-Registers a napi instance with the io_uring instance of
-.IR fd .
-.I arg
-should point to a
-.PP
-.in +12
-.EX
-struct io_uring_napi {
- __u32 busy_poll_to;
- __u8 prefer_busy_poll;
- __u8 pad[3];
- __u64 resv;
-};
-.EE
-.in
-.PP
-.in +8
-in which
-.I arg->busy_poll_to
-should contain the busy poll timeout in micro seconds and
-.I arg->prefer_busy_poll
-should specify whether busy polling should be used rather than IRQs.
-.I nr_args
-should be set to 1 and
-.I arg->pad
-and
-.I arg->resv
-should be zeroed out.
-On successful return the
-.I io_uring_napi
-struct pointed to by
-.I arg
-will contain the previously used settings.
-
-Available since 6.9.
-
-.TP
-.B IORING_UNREGISTER_NAPI
-Unregisters a napi instance previously registered via
-.B IORING_REGISTER_NAPI
-to the io_uring instance of
-.IR fd .
-.I arg
-should point to a
-.I struct
-.IR io_uring_napi .
-On successful return the
-.I io_uring_napi
-struct pointed to by
-.I arg
-will contain the previously used settings.
-
-Available since 6.9.
-
-.TP
-.B IORING_REGISTER_CLOCK
-Specifies which clock id io_uring will use for timers while waiting for
-completion events with
-.BR IORING_ENTER_GETEVENTS .
-It's only effective if the timeout argument in
-.I struct io_uring_getevents_arg
-is passed, ignored otherwise.
-When used in conjunction with
-.BR IORING_ENTER_ABS_TIMER ,
-interprets the timeout argument as absolute time of the specified clock.
-
-The default clock is
-.BR CLOCK_MONOTONIC .
-
-Available since 6.12 and supports
-.B CLOCK_MONOTONIC
-and
-.BR CLOCK_BOOTTIME .
-
-.TP
-.B IORING_REGISTER_CLONE_BUFFERS
-Supports cloning buffers from a source ring to a destination ring, duplicating
-previously registered buffers from source to destination.
-.IR arg
-must be set to a pointer to a
-.I struct io_uring_clone_buffers
-and
-.IR nr_args
-must be set to
-.B 1 .
-.I struct io_uring_buf_reg
-looks as follows:
-.PP
-.in +12n
-.EX
-struct io_uring_clone_buffers {
- __u32 src_fd;
- __u32 flags;
- __u32 src_off;
- __u32 dst_off;
- __u32 nr;
- __u32 pad[3];
-};
-.EE
-.in
-.TP
-.PP
-where
-.IR src_fd
-indicates the fd of the source ring,
-.IR flags
-are modifier flags for the operation,
-.IR src_off
-indicates the offset from where to start the cloning from the source ring,
-.IR dst_off
-indicates the offset from where to start the cloning into the destination ring,
-and
-.IR nr
-indicates the number of buffers to clone at the given offsets.
-.IR pad
-must be zero filled.
-Kernel 6.12 added support for full range cloning, where
-.IR src_off ,
-.IR dst_off ,
-and
-.IR nr
-must all be set to 0, indicating cloning of the entire table in source to
-destination. Kernel 6.13 added support for specifying the offsets and
-how many buffers to clone. Additionally, it added support for cloning into
-a previously registered table in the destination as well, 6.12 would fail
-that operation with
-.B -EBUSY
-if attempted. To replace existing nodes, or clone into an existing table,
-.B IORING_REGISTER_DST_REPLACE
-must be set in the
-.IR flags
-member.
-
-.TP
-.B IORING_REGISTER_SEND_MSG_RING
-Supports sending of the equivalent of a
-.B IORING_OP_MSG_RING
-request, but without having a source ring available. Takes a pointer to a
-.IR struct io_uring_sqe
-which must be prepared with
-.BR io_uring_prep_msg_ring (3)
-before being submitted. Only supports
-.B IORING_MSG_DATA
-type of requests. Available since kernel 6.13.
-
-.TP
-.B IORING_REGISTER_RESIZE_RINGS
-Supports resizing the SQ and CQ rings. Takes a pointer to a
-.IR struct io_uring_params
-as the argument, where
-.IR sq_entries
-and
-.IR cq_entries
-may be set to the desired values. Only supports a limited set of flags set
-in the
-.IR struct io_uring_params
-argument, notably
-.B IORING_SETUP_CQSIZE
-and
-.B IORING_SETUP_CLAMP
-to modify the CQ ring sizing. See
-.BR io_uring_resize_rings (3)
-for details. Note that while liburing takes care of the ring unmap and mapping
-for a resize operation, manual users of this register syscall must perform
-those operations, similarly to when a new ring is created. The
-.IR struct io_uring_params
-structure will get the necessary offsets copied back upon successful completion
-of this system call, which can be used to memory map the ring just like how
-a new ring would've been mapped. Available since kernel 6.13.
-
-.TP
-.B IORING_REGISTER_MEM_REGION
-Supports registering multiple purposes memory regions, avoiding unnecessary
-copying in of
-.IR struct io_uring_getevents_arg
-for wait operations that specify a timeout or minimum timeout. Takes a pointer
-to a
-.IR struct io_uring_mem_region_reg
-structure, which looks as follows:
-.PP
-.in +12n
-.EX
-struct io_uring_mem_region_reg {
- __u64 region_uptr;
- __u64 flags;
- __u64 __resv[2];
-};
-.EE
-.in
-.TP
-.PP
-where
-.IR region_uptr
-must be set to the region being registered as memory regions,
-.IR flags
-specifies modifier flags (must currently be
-.B IORING_MEM_REGION_REG_WAIT_ARG ). The pad fields must all be cleared to
-.B 0 .
-Each memory regions looks as follows:
-.PP
-.in +12n
-.EX
-struct io_uring_region_desc {
- __u64 user_addr;
- __u64 size;
- __u32 flags;
- __u32 id;
- __u64 mmap_offset;
- __u64 __resv[4];
-};
-.EE
-.in
-.TP
-.PP
-where
-.IR user_addr
-points to userspace memory mappings,
-.IR size
-is the size of userspace memory. Current supported userspace memory regions
-looks as follows:
-.PP
-.in +12n
-.EX
-struct io_uring_reg_wait {
- struct __kernel_timespec ts;
- __u32 min_wait_usec;
- __u32 flags;
- __u64 sigmask;
- __u32 sigmask_sz;
- __u32 pad[3];
- __u64 pad2[2];
-};
-.EE
-.in
-.TP
-.PP
-where
-.IR ts
-holds the timeout information for this region
-.IR flags
-holds information about the timeout region,
-.IR sigmask
-is a pointer to a signal mask, if used, and
-.IR sigmask_sz
-is the size of that signal mask. The pad fields must all be cleared to
-.B 0 .
-Currently the only valid flag is
-.B IORING_REG_WAIT_TS ,
-which, if set, says that the values in
-.IR ts
-are valid and should be used for a timeout operation. The
-.IR user_addr
-field of
-.IR struct io_uring_region_desc
-must be set to an address of
-.IR struct io_uring_reg_wait
-members, an up to a page size can be mapped. At the size of 64 bytes per
-region, that allows at least 64 individual regions on a 4k page size system.
-The offsets of these regions are used for an
-.BR io_uring_enter (2)
-system call, with the first one being 0, second one 1, and so forth. After
-registration of the wait regions,
-.BR io_uring_enter (2)
-may be used with the enter flag of
-.B IORING_ENTER_EXT_ARG_REG and an
-.IR argp
-set to the wait region offset, rather than a pointer to a
-.IR struct io_uring_getevent_arg
-structure. If used with
-.B IORING_ENTER_GETEVENTS ,
-then the wait operation will use the information in the registered wait
-region rather than needing a io_uring_getevent_arg structure copied for each
-operation. For high frequency waits, this can save considerable CPU cycles.
-Note: once a region has been registered, it cannot get unregistered. It lives
-for the life of the ring. Individual wait region offset may be modified before
-any
-.BR io_uring_enter (2)
-system call. Available since kernel 6.13.
-
-.TP
-.B IORING_REGISTER_ZCRX_IFQ
-Registers a zero-copy receive interface queue for network receive operations.
-Zero-copy receive allows the kernel to place incoming network data directly
-into application-provided memory without copying, reducing CPU overhead for
-high-bandwidth network workloads.
-.I arg
-must point to a
-.I struct io_uring_zcrx_ifq_reg
-structure, and
-.I nr_args
-must be set to 1.
-.PP
-.in +12n
-.EX
-struct io_uring_zcrx_ifq_reg {
- __u32 if_idx;
- __u32 if_rxq;
- __u32 rq_entries;
- __u32 flags;
- __u64 area_ptr;
- __u64 region_ptr;
- struct io_uring_zcrx_offsets offsets;
- __u32 zcrx_id;
- __u32 __resv2;
- __u64 __resv[3];
-};
-.EE
-.in
-.PP
-.in +8n
-where
-.I if_idx
-is the network interface index,
-.I if_rxq
-is the receive queue index,
-.I rq_entries
-is the number of entries in the refill queue (will be rounded up to a power
-of two),
-.I flags
-contains modifier flags,
-.I area_ptr
-points to a
-.I struct io_uring_zcrx_area_reg
-describing the memory area to use,
-.I region_ptr
-points to a
-.I struct io_uring_region_desc
-describing the memory region, and upon successful return
-.I zcrx_id
-will contain the ID of the registered zero-copy receive context.
-The
-.I offsets
-field is filled in by the kernel and contains the ring offsets for the refill
-queue.
-
-The io_uring ring must have been created with
-.B IORING_SETUP_DEFER_TASKRUN
-and either
-.B IORING_SETUP_CQE32
-or
-.B IORING_SETUP_CQE_MIXED
-flags set. The caller must have the
-.B CAP_NET_ADMIN
-capability.
-
-Available since kernel 6.15.
-
-.TP
-.B IORING_REGISTER_QUERY
-Queries io_uring capabilities and feature support. This operation does not
-require an io_uring ring and can be called with
-.I fd
-set to -1. It provides information about supported opcodes, flags, and
-subsystem-specific capabilities.
-.I arg
-must point to a
-.I struct io_uring_query_hdr
-and
-.I nr_args
-must be 0.
-.PP
-.in +12n
-.EX
-struct io_uring_query_hdr {
- __u64 next_entry;
- __u64 query_data;
- __u32 query_op;
- __u32 size;
- __s32 result;
- __u32 __resv[3];
-};
-.EE
-.in
-.PP
-.in +8n
-Multiple queries can be chained together via
-.I next_entry
-which points to the next
-.I struct io_uring_query_hdr
-(or 0 for the last entry).
-.I query_data
-points to a data structure appropriate for the query type.
-.I query_op
-specifies the query type and can be one of:
-.IP \[bu] 2
-.B IO_URING_QUERY_OPCODES
-\- Returns information about supported opcodes and flags in a
-.I struct io_uring_query_opcode
-.IP \[bu]
-.B IO_URING_QUERY_ZCRX
-\- Returns information about zero-copy receive support in a
-.I struct io_uring_query_zcrx
-.IP \[bu]
-.B IO_URING_QUERY_SCQ
-\- Returns information about the SQ/CQ ring layout in a
-.I struct io_uring_query_scq
-.PP
-.in +8n
-.I size
-should be set to the size of the data structure pointed to by
-.IR query_data .
-Upon return,
-.I result
-will be 0 on success, or a negative error code.
-
-Available since kernel 6.15.
-
-.TP
-.B IORING_REGISTER_ZCRX_CTRL
-Performs control operations on a previously registered zero-copy receive
-context.
-.I arg
-must point to a
-.I struct zcrx_ctrl
-and
-.I nr_args
-must be 0.
-.PP
-.in +12n
-.EX
-struct zcrx_ctrl {
- __u32 zcrx_id;
- __u32 op;
- __u64 __resv[2];
- union {
- struct zcrx_ctrl_export zc_export;
- struct zcrx_ctrl_flush_rq zc_flush;
- };
-};
-.EE
-.in
-.PP
-.in +8n
-where
-.I zcrx_id
-is the ID of the zero-copy receive context returned from
-.BR IORING_REGISTER_ZCRX_IFQ ,
-and
-.I op
-specifies the control operation:
-.IP \[bu] 2
-.B ZCRX_CTRL_FLUSH_RQ
-\- Flushes pending buffers from the refill queue
-.IP \[bu]
-.B ZCRX_CTRL_EXPORT
-\- Exports the zero-copy receive context for use by other rings
-
-Available since kernel 6.15.
-
-.SH RETURN VALUE
-On success,
-.BR io_uring_register (2)
-returns either 0 or a positive value, depending on the
-.I opcode
-used. On error, a negative error value is returned. The caller should not rely
-on the
-.I errno
-variable.
-
-.SH ERRORS
-.TP
-.B EACCES
-The
-.I opcode
-field is not allowed due to registered restrictions.
-.TP
-.B EBADF
-One or more fds in the
-.I fd
-array are invalid.
-.TP
-.B EBADFD
-.B IORING_REGISTER_ENABLE_RINGS
-or
-.B IORING_REGISTER_RESTRICTIONS
-was specified, but the io_uring ring is not disabled.
-.TP
-.B EBUSY
-.B IORING_REGISTER_BUFFERS
-or
-.B IORING_REGISTER_FILES
-or
-.B IORING_REGISTER_RESTRICTIONS
-was specified, but there were already buffers, files, or restrictions
-registered.
-.TP
-.B EEXIST
-The thread performing the registration is invalid.
-.TP
-.B EFAULT
-buffer is outside of the process' accessible address space, or
-.I iov_len
-is greater than 1GiB.
-.TP
-.B EINVAL
-.B IORING_REGISTER_BUFFERS
-or
-.B IORING_REGISTER_FILES
-was specified, but
-.I nr_args
-is 0.
-.TP
-.B EINVAL
-.B IORING_REGISTER_BUFFERS
-was specified, but
-.I nr_args
-exceeds
-.B UIO_MAXIOV
-.TP
-.B EINVAL
-.B IORING_UNREGISTER_BUFFERS
-or
-.B IORING_UNREGISTER_FILES
-was specified, and
-.I nr_args
-is non-zero or
-.I arg
-is non-NULL.
-.TP
-.B EINVAL
-.B IORING_REGISTER_RESTRICTIONS
-was specified, but
-.I nr_args
-exceeds the maximum allowed number of restrictions or restriction
-.I opcode
-is invalid.
-.TP
-.B EMFILE
-.B IORING_REGISTER_FILES
-was specified and
-.I nr_args
-exceeds the maximum allowed number of files in a fixed file set.
-.TP
-.B EMFILE
-.B IORING_REGISTER_FILES
-was specified and adding
-.I nr_args
-file references would exceed the maximum allowed number of files the user
-is allowed to have according to the
-.B RLIMIT_NOFILE
-resource limit and the caller does not have
-.B CAP_SYS_RESOURCE
-capability. Note that this is a per user limit, not per process.
-.TP
-.B ENOMEM
-Insufficient kernel resources are available, or the caller had a
-non-zero
-.B RLIMIT_MEMLOCK
-soft resource limit, but tried to lock more memory than the limit
-permitted. This limit is not enforced if the process is privileged
-.RB ( CAP_IPC_LOCK ).
-.TP
-.B ENXIO
-.B IORING_UNREGISTER_BUFFERS
-or
-.B IORING_UNREGISTER_FILES
-was specified, but there were no buffers or files registered.
-.TP
-.B ENXIO
-Attempt to register files or buffers on an io_uring instance that is already
-undergoing file or buffer registration, or is being torn down.
-.TP
-.B EOPNOTSUPP
-User buffers point to file-backed memory.
-.TP
-.B EFAULT
-User buffers point to file-backed memory (newer kernels).
-.TP
-.B ENOENT
-.B IORING_REGISTER_PBUF_STATUS
-was specified, but
-.I buf_group
-did not refer to a currently valid buffer group.
-.TP
-.B EINVAL
-.B IORING_REGISTER_PBUF_STATUS
-was specified, but the valid buffer group specified by
-.I buf_group
-did not refer to a buffer group registered via
-.BR IORING_REGISTER_PBUF_RING .
-.TP
-.B EINVAL
-.B IORING_REGISTER_NAPI
-was specified, but the ring associated with
-.I fd
-has not been created with
-.BR IORING_SETUP_IOPOLL .
diff --git a/man/io_uring_register.2.md b/man/io_uring_register.2.md
new file mode 100644
index 00000000..bce92159
--- /dev/null
+++ b/man/io_uring_register.2.md
@@ -0,0 +1,932 @@
+.\" Copyright (C) 2019 Jens Axboe <axboe@kernel.dk>
+.\" Copyright (C) 2019 Red Hat, Inc.
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 17, 2019
+footer: Linux
+header: Linux Programmer\'s Manual
+section: 2
+title: io_uring_register
+---
+
+# NAME
+
+io_uring_register - register files or user buffers for asynchronous I/O
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_register(unsigned int fd , unsigned int opcode ,
+ void * arg , unsigned int nr_args );
+```
+
+# DESCRIPTION
+
+The **io_uring_register**(2) system call registers resources (e.g. user
+buffers, files, eventfd, personality, restrictions) for use in an
+**io_uring**(7) instance referenced by *fd*. Registering files or user
+buffers allows the kernel to take long term references to internal data
+structures or create long term mappings of application memory, greatly
+reducing per-I/O overhead.
+
+*fd* is the file descriptor returned by a call to **io_uring_setup**(2).
+If *opcode* has the flag **IORING_REGISTER_USE_REGISTERED_RING** ored
+into it, *fd* is instead the index of a registered ring fd.
+
+*opcode* can be one of:
+
+**IORING_REGISTER_BUFFERS**
+
+: *arg* points to a *struct iovec* array of *nr_args* entries. The
+ buffers associated with the iovecs will be locked in memory and
+ charged against the user\'s **RLIMIT_MEMLOCK** resource limit. See
+ **getrlimit**(2) for more information. Additionally, there is a size
+ limit of 1GiB per buffer. Currently, the buffers must be anonymous,
+ non-file-backed memory, such as that returned by **malloc**(3) or
+ **mmap**(2) with the **MAP_ANONYMOUS** flag set. It is expected that
+ this limitation will be lifted in the future. Huge pages are supported
+ as well. Note that the entire huge page will be pinned in the kernel,
+ even if only a portion of it is used.
+
+ After a successful call, the supplied buffers are mapped into the
+ kernel and eligible for I/O. To make use of them, the application must
+ specify the **IORING_OP_READ_FIXED** or **IORING_OP_WRITE_FIXED**
+ opcodes in the submission queue entry (see the *struct io_uring_sqe*
+ definition in **io_uring_enter**(2)), and set the *buf_index* field to
+ the desired buffer index. The memory range described by the submission
+ queue entry\'s *addr* and *len* fields must fall within the indexed
+ buffer.
+
+ It is perfectly valid to setup a large buffer and then only use part
+ of it for an I/O, as long as the range is within the originally mapped
+ region.
+
+ An application can increase or decrease the size or number of
+ registered buffers by first unregistering the existing buffers, and
+ then issuing a new call to **io_uring_register**(2) with the new
+ buffers.
+
+ Note that before 5.13 registering buffers would wait for the ring to
+ idle. If the application currently has requests in-flight, the
+ registration will wait for those to finish before proceeding.
+
+ An application need not unregister buffers explicitly before shutting
+ down the io_uring instance. Note, however, that shutdown processing
+ may run asynchronously within the kernel. As a result, it is not
+ guaranteed that pages are immediately unpinned in this case. Available
+ since 5.1.
+
+**IORING_REGISTER_BUFFERS2** Register buffers for I/O. Similar to
+**IORING_REGISTER_BUFFERS** but aims to have a more extensible ABI.
+
+*arg* points to a *struct* *io_uring_rsrc_register*, and *nr_args*
+should be set to the number of bytes in the structure.
+
+``` text
+struct io_uring_rsrc_register {
+ __u32 nr;
+ __u32 flags;
+ __u64 resv2;
+ __aligned_u64 data;
+ __aligned_u64 tags;
+};
+```
+
+The *data* field contains a pointer to a *struct iovec* array of *nr*
+entries. The *tags* field should either be 0, then tagging is disabled,
+or point to an array of *nr* \"tags\" (unsigned 64 bit integers). If a
+tag is zero, then tagging for this particular resource (a buffer in this
+case) is disabled. Otherwise, after the resource had been unregistered
+and it\'s not used anymore, a CQE will be posted with *user_data* set to
+the specified tag and all other fields zeroed.
+
+The *flags* field supports the following flags:
+
+**IORING_RSRC_REGISTER_SPARSE** If set, io_uring will register *nr*
+empty buffers, which need to be updated before use. When this flag is
+set, *data* and *tags* must be NULL. Available since 5.19.
+
+Note that resource updates, e.g. **IORING_REGISTER_BUFFERS_UPDATE**,
+don\'t necessarily deallocate resources by the time it returns, but they
+might be held alive until all requests using it complete.
+
+Available since 5.13.
+
+**IORING_REGISTER_BUFFERS_UPDATE**
+
+: Updates registered buffers with new ones, either turning a sparse
+ entry into a real one, or replacing an existing entry.
+
+ *arg* must contain a pointer to a *struct* *io_uring_rsrc_update2*,
+ which contains an offset on which to start the update, and an array of
+ *struct* *iovec*. *tags* points to an array of tags. *nr* must contain
+ the number of descriptors in the passed in arrays. See
+ **IORING_REGISTER_BUFFERS2** for the resource tagging description.
+
+``` text
+
+struct io_uring_rsrc_update2 {
+ __u32 offset;
+ __u32 resv;
+ __aligned_u64 data;
+ __aligned_u64 tags;
+ __u32 nr;
+ __u32 resv2;
+};
+```
+
+Available since 5.13.
+
+**IORING_UNREGISTER_BUFFERS**
+
+: This operation takes no argument, and *arg* must be passed as NULL.
+ All previously registered buffers associated with the io_uring
+ instance will be released synchronously. Available since 5.1.
+
+**IORING_REGISTER_FILES**
+
+: Register files for I/O. *arg* contains a pointer to an array of
+ *nr_args* file descriptors (signed 32 bit integers).
+
+ To make use of the registered files, the **IOSQE_FIXED_FILE** flag
+ must be set in the *flags* member of the *struct io_uring_sqe*, and
+ the *fd* member is set to the index of the file in the file descriptor
+ array.
+
+ The file set may be sparse, meaning that the **fd** field in the array
+ may be set to **-1**. See **IORING_REGISTER_FILES_UPDATE** for how to
+ update files in place.
+
+ Note that before 5.13 registering files would wait for the ring to
+ idle. If the application currently has requests in-flight, the
+ registration will wait for those to finish before proceeding. See
+ **IORING_REGISTER_FILES_UPDATE** for how to update an existing set
+ without that limitation.
+
+ Files are automatically unregistered when the io_uring instance is
+ torn down. An application needs only unregister if it wishes to
+ register a new set of fds. Available since 5.1.
+
+**IORING_REGISTER_FILES2**
+
+: Register files for I/O. Similar to **IORING_REGISTER_FILES**.
+
+ *arg* points to a *struct* *io_uring_rsrc_register*, and *nr_args*
+ should be set to the number of bytes in the structure.
+
+ The *data* field contains a pointer to an array of *nr* file
+ descriptors (signed 32 bit integers). *tags* field should either be 0
+ or or point to an array of *nr* \"tags\" (unsigned 64 bit integers).
+ See **IORING_REGISTER_BUFFERS2** for more info on resource tagging.
+
+ Note that resource updates, e.g. **IORING_REGISTER_FILES_UPDATE**,
+ don\'t necessarily deallocate resources, they might be held until all
+ requests using that resource complete.
+
+ Available since 5.13.
+
+**IORING_REGISTER_FILES_UPDATE**
+
+: This operation replaces existing files in the registered file set with
+ new ones, either turning a sparse entry (one where fd is equal to
+ **-1**) into a real one, removing an existing entry (new one is set to
+ **-1**), or replacing an existing entry with a new existing entry.
+
+ *arg* must contain a pointer to a *struct* *io_uring_rsrc_update*,
+ which contains an offset on which to start the update, and an array of
+ file descriptors to use for the update. *nr_args* must contain the
+ number of descriptors in the passed in array. Available since 5.5.
+
+ File descriptors can be skipped if they are set to
+ **IORING_REGISTER_FILES_SKIP**. Skipping an fd will not touch the file
+ associated with the previous fd at that index. Available since 5.12.
+
+**IORING_REGISTER_FILES_UPDATE2**
+
+: Similar to **IORING_REGISTER_FILES_UPDATE**, replaces existing files
+ in the registered file set with new ones, either turning a sparse
+ entry (one where fd is equal to **-1**) into a real one, removing an
+ existing entry (new one is set to **-1**), or replacing an existing
+ entry with a new existing entry.
+
+ *arg* must contain a pointer to a *struct* *io_uring_rsrc_update2*,
+ which contains an offset on which to start the update, and an array of
+ file descriptors to use for the update stored in *data*. *tags* points
+ to an array of tags. *nr* must contain the number of descriptors in
+ the passed in arrays. See **IORING_REGISTER_BUFFERS2** for the
+ resource tagging description.
+
+ Available since 5.13.
+
+**IORING_UNREGISTER_FILES**
+
+: This operation requires no argument, and *arg* must be passed as NULL.
+ All previously registered files associated with the io_uring instance
+ will be unregistered. Available since 5.1.
+
+**IORING_REGISTER_EVENTFD**
+
+: It\'s possible to use **eventfd**(2) to get notified of completion
+ events on an io_uring instance. If this is desired, an eventfd file
+ descriptor can be registered through this operation. *arg* must
+ contain a pointer to the eventfd file descriptor, and *nr_args* must
+ be 1. Note that while io_uring generally takes care to avoid spurious
+ events, they can occur. Similarly, batched completions of CQEs may
+ only trigger a single eventfd notification even if multiple CQEs are
+ posted. The application should make no assumptions on number of events
+ being available having a direct correlation to eventfd notifications
+ posted. An eventfd notification must thus only be treated as a hint to
+ check the CQ ring for completions. Available since 5.2.
+
+ An application can temporarily disable notifications, coming through
+ the registered eventfd, by setting the **IORING_CQ_EVENTFD_DISABLED**
+ bit in the *flags* field of the CQ ring. Available since 5.8.
+
+**IORING_REGISTER_EVENTFD_ASYNC**
+
+: This works just like **IORING_REGISTER_EVENTFD**, except notifications
+ are only posted for events that complete in an async manner. This
+ means that events that complete inline while being submitted do not
+ trigger a notification event. The arguments supplied are the same as
+ for **IORING_REGISTER_EVENTFD**. Available since 5.6.
+
+**IORING_UNREGISTER_EVENTFD**
+
+: Unregister an eventfd file descriptor to stop notifications. Since
+ only one eventfd descriptor is currently supported, this operation
+ takes no argument, and *arg* must be passed as NULL and *nr_args* must
+ be zero. Available since 5.2.
+
+**IORING_REGISTER_PROBE**
+
+: This operation returns a structure, io_uring_probe, which contains
+ information about the opcodes supported by io_uring on the running
+ kernel. *arg* must contain a pointer to a struct io_uring_probe, and
+ *nr_args* must contain the size of the ops array in that probe struct.
+ The ops array is of the type io_uring_probe_op, which holds the value
+ of the opcode and a flags field. If the flags field has
+ **IO_URING_OP_SUPPORTED** set, then this opcode is supported on the
+ running kernel. Available since 5.6.
+
+**IORING_REGISTER_PERSONALITY**
+
+: This operation registers credentials of the running application with
+ io_uring, and returns an id associated with these credentials.
+ Applications wishing to share a ring between separate users/processes
+ can pass in this credential id in the sqe **personality** field. If
+ set, that particular sqe will be issued with these credentials. Must
+ be invoked with *arg* set to NULL and *nr_args* set to zero. Available
+ since 5.6.
+
+**IORING_UNREGISTER_PERSONALITY**
+
+: This operation unregisters a previously registered personality with
+ io_uring. *nr_args* must be set to the id in question, and *arg* must
+ be set to NULL. Available since 5.6.
+
+**IORING_REGISTER_ENABLE_RINGS**
+
+: This operation enables an io_uring ring started in a disabled state
+ (**IORING_SETUP_R_DISABLED** was specified in the call to
+ **io_uring_setup**(2)). While the io_uring ring is disabled,
+ submissions are not allowed and registrations are not restricted.
+
+ After the execution of this operation, the io_uring ring is enabled:
+ submissions and registration are allowed, but they will be validated
+ following the registered restrictions (if any). This operation takes
+ no argument, must be invoked with *arg* set to NULL and *nr_args* set
+ to zero. Available since 5.10.
+
+**IORING_REGISTER_RESTRICTIONS**
+
+: *arg* points to a *struct io_uring_restriction* array of *nr_args*
+ entries.
+
+ With an entry it is possible to allow an **io_uring_register**(2)
+ *opcode*, or specify which *opcode* and *flags* of the submission
+ queue entry are allowed, or require certain *flags* to be specified
+ (these flags must be set on each submission queue entry).
+
+ All the restrictions must be submitted with a single
+ **io_uring_register**(2) call and they are handled as an allowlist
+ (opcodes and flags not registered, are not allowed).
+
+ Restrictions can be registered only if the io_uring ring started in a
+ disabled state (**IORING_SETUP_R_DISABLED** must be specified in the
+ call to **io_uring_setup**(2)).
+
+ Available since 5.10.
+
+**IORING_REGISTER_IOWQ_AFF**
+
+: By default, async workers created by io_uring will inherit the CPU
+ mask of its parent. This is usually all the CPUs in the system, unless
+ the parent is being run with a limited set. If this isn\'t the desired
+ outcome, the application may explicitly tell io_uring what CPUs the
+ async workers may run on. *arg* must point to a **cpu_set_t** mask,
+ and *nr_args* the byte size of that mask.
+
+ Available since 5.14.
+
+**IORING_UNREGISTER_IOWQ_AFF**
+
+: Undoes a CPU mask previously set with **IORING_REGISTER_IOWQ_AFF**.
+ Must not have *arg* or *nr_args* set.
+
+ Available since 5.14.
+
+**IORING_REGISTER_IOWQ_MAX_WORKERS**
+
+: By default, io_uring limits the unbounded workers created to the
+ maximum processor count set by *RLIMIT_NPROC* and the bounded workers
+ is a function of the SQ ring size and the number of CPUs in the
+ system. Sometimes this can be excessive (or too little, for bounded),
+ and this command provides a way to change the count per ring (per NUMA
+ node) instead.
+
+ *arg* must be set to an *unsigned int* pointer to an array of two
+ values, with the values in the array being set to the maximum count of
+ workers per NUMA node. Index 0 holds the bounded worker count, and
+ index 1 holds the unbounded worker count. On successful return, the
+ passed in array will contain the previous maximum values for each
+ type. If the count being passed in is 0, then this command returns the
+ current maximum values and doesn\'t modify the current setting.
+ *nr_args* must be set to 2, as the command takes two values.
+
+ Available since 5.15.
+
+**IORING_REGISTER_RING_FDS**
+
+: Whenever **io_uring_enter**(2) is called to submit request or wait for
+ completions, the kernel must grab a reference to the file descriptor.
+ If the application using io_uring is threaded, the file table is
+ marked as shared, and the reference grab and put of the file
+ descriptor count is more expensive than it is for a non-threaded
+ application.
+
+ Similarly to how io_uring allows registration of files, this allow
+ registration of the ring file descriptor itself. This reduces the
+ overhead of the **io_uring_enter**(2) system call.
+
+ *arg* must be set to a pointer to an array of type *struct
+ io_uring_rsrc_update* of *nr_args* number of entries. The **data**
+ field of this struct must contain an io_uring file descriptor, and the
+ **offset** field can be either **-1** or an explicit offset desired
+ for the registered file descriptor value. If **-1** is used, then upon
+ successful return of this system call, the field will contain the
+ value of the registered file descriptor to be used for future
+ **io_uring_enter**(2) system calls.
+
+ On successful completion of this request, the returned descriptors may
+ be used instead of the real file descriptor for **io_uring_enter**(2),
+ provided that **IORING_ENTER_REGISTERED_RING** is set in the *flags*
+ for the system call. This flag tells the kernel that a registered
+ descriptor is used rather than a real file descriptor.
+
+ Each thread or process using a ring must register the file descriptor
+ directly by issuing this request.
+
+ The maximum number of supported registered ring descriptors is
+ currently limited to **16.**
+
+ Available since 5.18.
+
+**IORING_UNREGISTER_RING_FDS**
+
+: Unregister descriptors previously registered with
+ **IORING_REGISTER_RING_FDS**.
+
+ *arg* must be set to a pointer to an array of type *struct
+ io_uring_rsrc_update* of *nr_args* number of entries. Only the
+ **offset** field should be set in the structure, containing the
+ registered file descriptor offset previously returned from
+ **IORING_REGISTER_RING_FDS** that the application wishes to
+ unregister.
+
+ Note that this isn\'t done automatically on ring exit, if the thread
+ or task that previously registered a ring file descriptor isn\'t
+ exiting. It is recommended to manually unregister any previously
+ registered ring descriptors if the ring is closed and the task
+ persists. This will free up a registration slot, making it available
+ for future use.
+
+ Available since 5.18.
+
+**IORING_REGISTER_PBUF_RING**
+
+: Registers a shared buffer ring to be used with provided buffers. This
+ is a newer alternative to using **IORING_OP_PROVIDE_BUFFERS** which is
+ more efficient, to be used with request types that support the
+ **IOSQE_BUFFER_SELECT** flag.
+
+ The *arg* argument must be filled in with the appropriate information.
+ It looks as follows:
+
+``` text
+struct io_uring_buf_reg {
+ __u64 ring_addr;
+ __u32 ring_entries;
+ __u16 bgid;
+ __u16 flags;
+ __u32 min_left;
+ __u32 resv[5];
+};
+```
+
+The *ring_addr* field must contain the address to the memory allocated
+to fit this ring. The memory must be page aligned and hence allocated
+appropriately using eg **posix_memalign**(3) or similar. The size of the
+ring is the product of *ring_entries* and the size of *struct
+io_uring_buf*. *ring_entries* is the desired size of the ring, and must
+be a power-of-2 in size. The maximum size allowed is 2\^15 (32768).
+*bgid* is the buffer group ID associated with this ring. SQEs that
+select a buffer have a buffer group associated with them in their
+*buf_group* field, and the associated CQEs will have
+**IORING_CQE_F_BUFFER** set in their *flags* member, which will also
+contain the specific ID of the buffer selected. *min_left* is the
+minimum value that should be left in an incrementally consumed buffer
+ring for the buffer to be considered valid. If not set, defaults to a
+single byte. Only valid with **IOU_PBUF_RING_INC** set in *flags .* The
+rest of the fields are reserved and must be cleared to zero.
+
+*nr_args* must be set to 1.
+
+Also see **io_uring_register_buf_ring**(3) for more details. Available
+since 5.19.
+
+**IORING_UNREGISTER_PBUF_RING**
+
+: Unregister a previously registered provided buffer ring. *arg* must be
+ set to the address of a struct io_uring_buf_reg, with just the *bgid*
+ field set to the buffer group ID of the previously registered provided
+ buffer group. *nr_args* must be set to 1. Also see
+ **IORING_REGISTER_PBUF_RING**.
+
+ Available since 5.19.
+
+**IORING_REGISTER_SYNC_CANCEL**
+
+: Performs a synchronous cancelation request, which works in a similar
+ fashion to **IORING_OP_ASYNC_CANCEL** except it completes inline. This
+ can be useful for scenarios where cancelations should happen
+ synchronously, rather than needing to issue an SQE and wait for
+ completion of that specific CQE.
+
+ *arg* must be set to a pointer to a struct io_uring_sync_cancel_reg
+ structure, with the details filled in for what request(s) to target
+ for cancelation. See **io_uring_register_sync_cancel**(3) for details
+ on that. The return values are the same, except they are passed back
+ synchronously rather than through the CQE *res* field. *nr_args* must
+ be set to 1.
+
+ Available since 6.0.
+
+**IORING_REGISTER_FILE_ALLOC_RANGE**
+
+: sets the allowable range for fixed file index allocations within the
+ kernel. When requests that can instantiate a new fixed file are used
+ with **IORING_FILE_INDEX_ALLOC**, the application is asking the kernel
+ to allocate a new fixed file descriptor rather than pass in a specific
+ value for one. By default, the kernel will pick any available fixed
+ file descriptor within the range available. This effectively allows
+ the application to set aside a range just for dynamic allocations,
+ with the remainder being used for specific values.
+
+ *nr_args* must be set to 1 and *arg* must be set to a pointer to a
+ struct io_uring_file_index_range:
+
+``` text
+struct io_uring_file_index_range {
+ __u32 off;
+ __u32 len;
+ __u64 resv;
+};
+```
+
+with *off* being set to the starting value for the range, and *len*
+being set to the number of descriptors. The reserved *resv* field must
+be cleared to zero.
+
+The application must have registered a file table first.
+
+Available since 6.0.
+
+**IORING_REGISTER_PBUF_STATUS**
+
+: Can be used to retrieve the current head of a ringbuffer provided
+ earlier via **IORING_REGISTER_PBUF_RING**. *arg* must point to a
+
+``` text
+struct io_uring_buf_status {
+ __u32 buf_group; /* input */
+ __u32 head; /* output */
+ __u32 resv[8];
+};
+```
+
+of which *arg-\>buf_group* should contain the buffer group ID for the
+buffer ring in question, *nr_args* should be set to 1 and *arg-\>resv*
+should be zeroed out. The current head of the ringbuffer will be
+returned in *arg-\>head*.
+
+Available since 6.8.
+
+**IORING_REGISTER_NAPI**
+
+: Registers a napi instance with the io_uring instance of *fd*. *arg*
+ should point to a
+
+``` text
+struct io_uring_napi {
+ __u32 busy_poll_to;
+ __u8 prefer_busy_poll;
+ __u8 pad[3];
+ __u64 resv;
+};
+```
+
+in which *arg-\>busy_poll_to* should contain the busy poll timeout in
+micro seconds and *arg-\>prefer_busy_poll* should specify whether busy
+polling should be used rather than IRQs. *nr_args* should be set to 1
+and *arg-\>pad* and *arg-\>resv* should be zeroed out. On successful
+return the *io_uring_napi* struct pointed to by *arg* will contain the
+previously used settings.
+
+Available since 6.9.
+
+**IORING_UNREGISTER_NAPI**
+
+: Unregisters a napi instance previously registered via
+ **IORING_REGISTER_NAPI** to the io_uring instance of *fd*. *arg*
+ should point to a *struct* *io_uring_napi*. On successful return the
+ *io_uring_napi* struct pointed to by *arg* will contain the previously
+ used settings.
+
+ Available since 6.9.
+
+**IORING_REGISTER_CLOCK**
+
+: Specifies which clock id io_uring will use for timers while waiting
+ for completion events with **IORING_ENTER_GETEVENTS**. It\'s only
+ effective if the timeout argument in *struct io_uring_getevents_arg*
+ is passed, ignored otherwise. When used in conjunction with
+ **IORING_ENTER_ABS_TIMER**, interprets the timeout argument as
+ absolute time of the specified clock.
+
+ The default clock is **CLOCK_MONOTONIC**.
+
+ Available since 6.12 and supports **CLOCK_MONOTONIC** and
+ **CLOCK_BOOTTIME**.
+
+**IORING_REGISTER_CLONE_BUFFERS**
+
+: Supports cloning buffers from a source ring to a destination ring,
+ duplicating previously registered buffers from source to destination.
+ *arg* must be set to a pointer to a *struct io_uring_clone_buffers*
+ and *nr_args* must be set to **1 .** *struct io_uring_buf_reg* looks
+ as follows:
+
+``` text
+struct io_uring_clone_buffers {
+ __u32 src_fd;
+ __u32 flags;
+ __u32 src_off;
+ __u32 dst_off;
+ __u32 nr;
+ __u32 pad[3];
+};
+```
+
+where *src_fd* indicates the fd of the source ring, *flags* are modifier
+flags for the operation, *src_off* indicates the offset from where to
+start the cloning from the source ring, *dst_off* indicates the offset
+from where to start the cloning into the destination ring, and *nr*
+indicates the number of buffers to clone at the given offsets. *pad*
+must be zero filled. Kernel 6.12 added support for full range cloning,
+where *src_off*, *dst_off*, and *nr* must all be set to 0, indicating
+cloning of the entire table in source to destination. Kernel 6.13 added
+support for specifying the offsets and how many buffers to clone.
+Additionally, it added support for cloning into a previously registered
+table in the destination as well, 6.12 would fail that operation with
+**-EBUSY** if attempted. To replace existing nodes, or clone into an
+existing table, **IORING_REGISTER_DST_REPLACE** must be set in the
+*flags* member.
+
+**IORING_REGISTER_SEND_MSG_RING**
+
+: Supports sending of the equivalent of a **IORING_OP_MSG_RING**
+ request, but without having a source ring available. Takes a pointer
+ to a *struct*io_uring_sqe which must be prepared with
+ **io_uring_prep_msg_ring**(3) before being submitted. Only supports
+ **IORING_MSG_DATA** type of requests. Available since kernel 6.13.
+
+**IORING_REGISTER_RESIZE_RINGS**
+
+: Supports resizing the SQ and CQ rings. Takes a pointer to a
+ *struct*io_uring_params as the argument, where *sq_entries* and
+ *cq_entries* may be set to the desired values. Only supports a limited
+ set of flags set in the *struct*io_uring_params argument, notably
+ **IORING_SETUP_CQSIZE** and **IORING_SETUP_CLAMP** to modify the CQ
+ ring sizing. See **io_uring_resize_rings**(3) for details. Note that
+ while liburing takes care of the ring unmap and mapping for a resize
+ operation, manual users of this register syscall must perform those
+ operations, similarly to when a new ring is created. The
+ *struct*io_uring_params structure will get the necessary offsets
+ copied back upon successful completion of this system call, which can
+ be used to memory map the ring just like how a new ring would\'ve been
+ mapped. Available since kernel 6.13.
+
+**IORING_REGISTER_MEM_REGION**
+
+: Supports registering multiple purposes memory regions, avoiding
+ unnecessary copying in of *struct*io_uring_getevents_arg for wait
+ operations that specify a timeout or minimum timeout. Takes a pointer
+ to a *struct*io_uring_mem_region_reg structure, which looks as
+ follows:
+
+``` text
+struct io_uring_mem_region_reg {
+ __u64 region_uptr;
+ __u64 flags;
+ __u64 __resv[2];
+};
+```
+
+where *region_uptr* must be set to the region being registered as memory
+regions, *flags* specifies modifier flags (must currently be
+**IORING_MEM_REGION_REG_WAIT_ARG ). The pad fields must all be cleared
+to** **0 .** Each memory regions looks as follows:
+
+``` text
+struct io_uring_region_desc {
+ __u64 user_addr;
+ __u64 size;
+ __u32 flags;
+ __u32 id;
+ __u64 mmap_offset;
+ __u64 __resv[4];
+};
+```
+
+where *user_addr* points to userspace memory mappings, *size* is the
+size of userspace memory. Current supported userspace memory regions
+looks as follows:
+
+``` text
+struct io_uring_reg_wait {
+ struct __kernel_timespec ts;
+ __u32 min_wait_usec;
+ __u32 flags;
+ __u64 sigmask;
+ __u32 sigmask_sz;
+ __u32 pad[3];
+ __u64 pad2[2];
+};
+```
+
+where *ts* holds the timeout information for this region *flags* holds
+information about the timeout region, *sigmask* is a pointer to a signal
+mask, if used, and *sigmask_sz* is the size of that signal mask. The pad
+fields must all be cleared to **0 .** Currently the only valid flag is
+**IORING_REG_WAIT_TS ,** which, if set, says that the values in *ts* are
+valid and should be used for a timeout operation. The *user_addr* field
+of *struct*io_uring_region_desc must be set to an address of
+*struct*io_uring_reg_wait members, an up to a page size can be mapped.
+At the size of 64 bytes per region, that allows at least 64 individual
+regions on a 4k page size system. The offsets of these regions are used
+for an **io_uring_enter**(2) system call, with the first one being 0,
+second one 1, and so forth. After registration of the wait regions,
+**io_uring_enter**(2) may be used with the enter flag of
+**IORING_ENTER_EXT_ARG_REG and an** *argp* set to the wait region
+offset, rather than a pointer to a *struct*io_uring_getevent_arg
+structure. If used with **IORING_ENTER_GETEVENTS ,** then the wait
+operation will use the information in the registered wait region rather
+than needing a io_uring_getevent_arg structure copied for each
+operation. For high frequency waits, this can save considerable CPU
+cycles. Note: once a region has been registered, it cannot get
+unregistered. It lives for the life of the ring. Individual wait region
+offset may be modified before any **io_uring_enter**(2) system call.
+Available since kernel 6.13.
+
+**IORING_REGISTER_ZCRX_IFQ**
+
+: Registers a zero-copy receive interface queue for network receive
+ operations. Zero-copy receive allows the kernel to place incoming
+ network data directly into application-provided memory without
+ copying, reducing CPU overhead for high-bandwidth network workloads.
+ *arg* must point to a *struct io_uring_zcrx_ifq_reg* structure, and
+ *nr_args* must be set to 1.
+
+``` text
+struct io_uring_zcrx_ifq_reg {
+ __u32 if_idx;
+ __u32 if_rxq;
+ __u32 rq_entries;
+ __u32 flags;
+ __u64 area_ptr;
+ __u64 region_ptr;
+ struct io_uring_zcrx_offsets offsets;
+ __u32 zcrx_id;
+ __u32 __resv2;
+ __u64 __resv[3];
+};
+```
+
+where *if_idx* is the network interface index, *if_rxq* is the receive
+queue index, *rq_entries* is the number of entries in the refill queue
+(will be rounded up to a power of two), *flags* contains modifier flags,
+*area_ptr* points to a *struct io_uring_zcrx_area_reg* describing the
+memory area to use, *region_ptr* points to a *struct
+io_uring_region_desc* describing the memory region, and upon successful
+return *zcrx_id* will contain the ID of the registered zero-copy receive
+context. The *offsets* field is filled in by the kernel and contains the
+ring offsets for the refill queue.
+
+The io_uring ring must have been created with
+**IORING_SETUP_DEFER_TASKRUN** and either **IORING_SETUP_CQE32** or
+**IORING_SETUP_CQE_MIXED** flags set. The caller must have the
+**CAP_NET_ADMIN** capability.
+
+Available since kernel 6.15.
+
+**IORING_REGISTER_QUERY**
+
+: Queries io_uring capabilities and feature support. This operation does
+ not require an io_uring ring and can be called with *fd* set to -1. It
+ provides information about supported opcodes, flags, and
+ subsystem-specific capabilities. *arg* must point to a *struct
+ io_uring_query_hdr* and *nr_args* must be 0.
+
+``` text
+struct io_uring_query_hdr {
+ __u64 next_entry;
+ __u64 query_data;
+ __u32 query_op;
+ __u32 size;
+ __s32 result;
+ __u32 __resv[3];
+};
+```
+
+Multiple queries can be chained together via *next_entry* which points
+to the next *struct io_uring_query_hdr* (or 0 for the last entry).
+*query_data* points to a data structure appropriate for the query type.
+*query_op* specifies the query type and can be one of:
+
+- **IO_URING_QUERY_OPCODES** - Returns information about supported
+ opcodes and flags in a *struct io_uring_query_opcode*
+
+- **IO_URING_QUERY_ZCRX** - Returns information about zero-copy receive
+ support in a *struct io_uring_query_zcrx*
+
+- **IO_URING_QUERY_SCQ** - Returns information about the SQ/CQ ring
+ layout in a *struct io_uring_query_scq*
+
+*size* should be set to the size of the data structure pointed to by
+*query_data*. Upon return, *result* will be 0 on success, or a negative
+error code.
+
+Available since kernel 6.15.
+
+**IORING_REGISTER_ZCRX_CTRL**
+
+: Performs control operations on a previously registered zero-copy
+ receive context. *arg* must point to a *struct zcrx_ctrl* and
+ *nr_args* must be 0.
+
+``` text
+struct zcrx_ctrl {
+ __u32 zcrx_id;
+ __u32 op;
+ __u64 __resv[2];
+ union {
+ struct zcrx_ctrl_export zc_export;
+ struct zcrx_ctrl_flush_rq zc_flush;
+ };
+};
+```
+
+where *zcrx_id* is the ID of the zero-copy receive context returned from
+**IORING_REGISTER_ZCRX_IFQ**, and *op* specifies the control operation:
+
+- **ZCRX_CTRL_FLUSH_RQ** - Flushes pending buffers from the refill queue
+
+- **ZCRX_CTRL_EXPORT** - Exports the zero-copy receive context for use
+ by other rings
+
+ Available since kernel 6.15.
+
+# RETURN VALUE
+
+On success, **io_uring_register**(2) returns either 0 or a positive
+value, depending on the *opcode* used. On error, a negative error value
+is returned. The caller should not rely on the *errno* variable.
+
+# ERRORS
+
+**EACCES**
+
+: The *opcode* field is not allowed due to registered restrictions.
+
+**EBADF**
+
+: One or more fds in the *fd* array are invalid.
+
+**EBADFD**
+
+: **IORING_REGISTER_ENABLE_RINGS** or **IORING_REGISTER_RESTRICTIONS**
+ was specified, but the io_uring ring is not disabled.
+
+**EBUSY**
+
+: **IORING_REGISTER_BUFFERS** or **IORING_REGISTER_FILES** or
+ **IORING_REGISTER_RESTRICTIONS** was specified, but there were already
+ buffers, files, or restrictions registered.
+
+**EEXIST**
+
+: The thread performing the registration is invalid.
+
+**EFAULT**
+
+: buffer is outside of the process\' accessible address space, or
+ *iov_len* is greater than 1GiB.
+
+**EINVAL**
+
+: **IORING_REGISTER_BUFFERS** or **IORING_REGISTER_FILES** was
+ specified, but *nr_args* is 0.
+
+**EINVAL**
+
+: **IORING_REGISTER_BUFFERS** was specified, but *nr_args* exceeds
+ **UIO_MAXIOV**
+
+**EINVAL**
+
+: **IORING_UNREGISTER_BUFFERS** or **IORING_UNREGISTER_FILES** was
+ specified, and *nr_args* is non-zero or *arg* is non-NULL.
+
+**EINVAL**
+
+: **IORING_REGISTER_RESTRICTIONS** was specified, but *nr_args* exceeds
+ the maximum allowed number of restrictions or restriction *opcode* is
+ invalid.
+
+**EMFILE**
+
+: **IORING_REGISTER_FILES** was specified and *nr_args* exceeds the
+ maximum allowed number of files in a fixed file set.
+
+**EMFILE**
+
+: **IORING_REGISTER_FILES** was specified and adding *nr_args* file
+ references would exceed the maximum allowed number of files the user
+ is allowed to have according to the **RLIMIT_NOFILE** resource limit
+ and the caller does not have **CAP_SYS_RESOURCE** capability. Note
+ that this is a per user limit, not per process.
+
+**ENOMEM**
+
+: Insufficient kernel resources are available, or the caller had a
+ non-zero **RLIMIT_MEMLOCK** soft resource limit, but tried to lock
+ more memory than the limit permitted. This limit is not enforced if
+ the process is privileged (**CAP_IPC_LOCK**).
+
+**ENXIO**
+
+: **IORING_UNREGISTER_BUFFERS** or **IORING_UNREGISTER_FILES** was
+ specified, but there were no buffers or files registered.
+
+**ENXIO**
+
+: Attempt to register files or buffers on an io_uring instance that is
+ already undergoing file or buffer registration, or is being torn down.
+
+**EOPNOTSUPP**
+
+: User buffers point to file-backed memory.
+
+**EFAULT**
+
+: User buffers point to file-backed memory (newer kernels).
+
+**ENOENT**
+
+: **IORING_REGISTER_PBUF_STATUS** was specified, but *buf_group* did not
+ refer to a currently valid buffer group.
+
+**EINVAL**
+
+: **IORING_REGISTER_PBUF_STATUS** was specified, but the valid buffer
+ group specified by *buf_group* did not refer to a buffer group
+ registered via **IORING_REGISTER_PBUF_RING**.
+
+**EINVAL**
+
+: **IORING_REGISTER_NAPI** was specified, but the ring associated with
+ *fd* has not been created with **IORING_SETUP_IOPOLL**.
diff --git a/man/io_uring_register_bpf_filter.3 b/man/io_uring_register_bpf_filter.3
deleted file mode 100644
index 440b88bb..00000000
--- a/man/io_uring_register_bpf_filter.3
+++ /dev/null
@@ -1,411 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_register_bpf_filter 3 "January 18, 2026" "liburing-2.14" "liburing Manual"
-.SH NAME
-io_uring_register_bpf_filter, io_uring_register_bpf_filter_task \- register classic BPF filters for io_uring operations
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.B #include <liburing/io_uring/bpf_filter.h>
-.B #include <linux/filter.h>
-.PP
-.BI "int io_uring_register_bpf_filter(struct io_uring *" ring ","
-.BI " struct io_uring_bpf *" bpf ");"
-.PP
-.BI "int io_uring_register_bpf_filter_task(struct io_uring_bpf *" bpf ");"
-.fi
-.SH DESCRIPTION
-.PP
-These functions register classic BPF (cBPF) filters to restrict io_uring
-operations. Filters can be used to implement security policies by allowing
-or denying specific operations based on their parameters.
-.PP
-.BR io_uring_register_bpf_filter (3)
-registers a filter on a specific
-.IR ring .
-The filter only applies to operations submitted through that ring.
-.PP
-.BR io_uring_register_bpf_filter_task (3)
-registers a filter on the calling task. The filter applies to all io_uring
-rings created by the task after the filter is registered, and is inherited
-by child processes created via
-.BR fork (2).
-Rings that were created before the filter was registered are not affected.
-Task-level filters cannot be removed and child processes cannot loosen
-restrictions set by their parent.
-.PP
-The
-.I bpf
-argument is a pointer to a
-.B struct io_uring_bpf
-with
-.I cmd_type
-set to
-.BR IO_URING_BPF_CMD_FILTER .
-The embedded
-.B struct io_uring_bpf_filter
-describes the filter to register:
-.PP
-.in +4n
-.EX
-struct io_uring_bpf_filter {
- __u32 opcode; /* io_uring opcode to filter */
- __u32 flags; /* IO_URING_BPF_FILTER_* */
- __u32 filter_len; /* number of BPF instructions */
- __u8 pdu_size; /* expected pdu size for opcode */
- __u8 resv[3];
- __u64 filter_ptr; /* pointer to BPF filter */
- __u64 resv2[5];
-};
-.EE
-.in
-.PP
-.I opcode
-specifies which io_uring operation the filter applies to (e.g.,
-.BR IORING_OP_SOCKET ", " IORING_OP_NOP ", " IORING_OP_READ ).
-.PP
-.I filter_ptr
-points to an array of
-.I filter_len
-BPF instructions
-.RB ( "struct sock_filter" ).
-The filter is executed for each matching operation and must return non-zero
-to allow the operation or zero to deny it (resulting in
-.B -EACCES
-being returned to the application).
-.PP
-.I pdu_size
-specifies the expected size in bytes of the operation-specific payload data
-for the given opcode (e.g., the socket or open structs inside
-.BR "struct io_uring_bpf_ctx" ).
-For opcodes that have no extra payload, this should be zero. For
-.B IORING_OP_SOCKET
-this would be 12 (three 4-byte members), and for
-.BR IORING_OP_OPENAT " and " IORING_OP_OPENAT2
-this would be 24 (three 8-byte members).
-.PP
-If the application's
-.I pdu_size
-matches the kernel's expected size for the opcode, registration succeeds.
-If the sizes differ, the behavior depends on whether
-.B IO_URING_BPF_FILTER_SZ_STRICT
-is set in
-.IR flags :
-.RS
-.IP \(bu 2
-If
-.B IO_URING_BPF_FILTER_SZ_STRICT
-is set, registration fails with
-.B -EMSGSIZE
-if the sizes differ.
-.IP \(bu
-If
-.B IO_URING_BPF_FILTER_SZ_STRICT
-is not set, registration is allowed if the application's
-.I pdu_size
-is smaller than the kernel's. This permits older applications that were
-compiled against a smaller payload to still load filters, as the kernel
-can safely evaluate the filter on the subset of data the application
-expects.
-.IP \(bu
-Regardless of
-.BR IO_URING_BPF_FILTER_SZ_STRICT ,
-registration always fails with
-.B -EMSGSIZE
-if the application's
-.I pdu_size
-is larger than the kernel's, since the kernel cannot provide data that
-it does not support.
-.RE
-.PP
-On an
-.B -EMSGSIZE
-failure, the kernel writes back the kernel's expected
-.I pdu_size
-into the
-.B struct io_uring_bpf_filter
-passed by the application. This allows the application to discover the
-kernel's expected payload size and adjust or retry accordingly.
-.PP
-.I flags
-can be zero or a bitwise OR of the following:
-.TP
-.B IO_URING_BPF_FILTER_DENY_REST
-When set, any opcode that does not have a filter registered will be denied.
-This allows creating an allowlist of permitted operations.
-.TP
-.B IO_URING_BPF_FILTER_SZ_STRICT
-When set, registration of a filter will fail with
-.B -EMSGSIZE
-if the application's
-.I pdu_size
-does not exactly match the kernel's expected payload size for the opcode.
-Without this flag, the kernel permits filters where the application's
-.I pdu_size
-is smaller than or equal to the kernel's.
-.SS Filter Context
-The BPF filter receives a context structure that can be inspected using
-.B BPF_LD
-instructions with absolute addressing. The context layout is:
-.PP
-.in +4n
-.EX
-struct io_uring_bpf_ctx {
- __u64 user_data; /* offset 0: user_data from SQE */
- __u8 opcode; /* offset 8: io_uring opcode */
- __u8 sqe_flags; /* offset 9: SQE flags */
- __u8 pdu_size; /* offset 10: aux data size for filter */
- __u8 pad[5]; /* offset 11-15: padding */
- union {
- struct {
- __u32 family; /* offset 16: socket family */
- __u32 type; /* offset 20: socket type */
- __u32 protocol; /* offset 24: socket protocol */
- } socket;
- struct {
- __u64 flags; /* offset 16: open flags */
- __u64 mode; /* offset 24: file mode */
- __u64 resolve; /* offset 32: resolve flags */
- } open;
- };
-};
-.EE
-.in
-.PP
-The
-.I pdu_size
-field indicates the size in bytes of the operation-specific data passed in
-the union. A filter can check this value to verify it is receiving the
-expected payload. This is useful for forward compatibility: if a future
-kernel adds new members to an operation's context, the filter can inspect
-.I pdu_size
-to determine whether those fields are present.
-.PP
-For
-.B IORING_OP_SOCKET
-operations, the socket family, type, and protocol fields are populated
-and can be used to filter based on socket parameters.
-.I pdu_size
-is set to 12 (three 4-byte members).
-.PP
-For
-.BR IORING_OP_OPENAT " and " IORING_OP_OPENAT2
-operations, the open flags, mode, and resolve fields are populated.
-The flags field contains the open flags (e.g.,
-.BR O_RDONLY ", " O_CREAT ).
-The resolve field is only meaningful for
-.B IORING_OP_OPENAT2
-and contains resolve flags (e.g.,
-.BR RESOLVE_IN_ROOT ")."
-.I pdu_size
-is set to 24 (three 8-byte members).
-.SS Filter Stacking
-Multiple filters can be registered for the same opcode. When multiple
-filters exist, they are evaluated in order and all must return non-zero
-for the operation to be allowed. For task-level filters, the child's
-filters are evaluated before the parent's filters.
-.SH RETURN VALUE
-On success, these functions return 0. On failure, they return a negative
-error code.
-.SH ERRORS
-.TP
-.B -EINVAL
-Invalid filter, opcode, or flags specified.
-.TP
-.B -EMSGSIZE
-The application's
-.I pdu_size
-does not match the kernel's expected payload size for the opcode. This
-occurs when
-.B IO_URING_BPF_FILTER_SZ_STRICT
-is set and the sizes differ, or when the application's
-.I pdu_size
-is larger than the kernel's regardless of flags.
-.TP
-.B -ENOMEM
-Insufficient memory to register the filter.
-.TP
-.B -EFAULT
-The filter pointer is invalid.
-.TP
-.B -EACCES
-The caller does not have the
-.B CAP_SYS_ADMIN
-capability and the
-.B no_new_privs
-attribute is not set on the calling task. See
-.BR prctl (2)
-with
-.BR PR_SET_NO_NEW_PRIVS .
-.SH EXAMPLES
-.SS Deny all NOP operations
-.PP
-.in +4n
-.EX
-#include <sys/prctl.h>
-#include <linux/filter.h>
-#include <liburing.h>
-#include <liburing/io_uring/bpf_filter.h>
-
-struct sock_filter deny_filter[] = {
- BPF_STMT(BPF_RET | BPF_K, 0), /* return 0 (deny) */
-};
-
-struct io_uring_bpf bpf = {
- .cmd_type = IO_URING_BPF_CMD_FILTER,
- .filter = {
- .opcode = IORING_OP_NOP,
- .filter_len = 1,
- .filter_ptr = (unsigned long) deny_filter,
- },
-};
-
-/* Must set no_new_privs before registering task filters */
-prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-
-/* Register on a specific ring */
-io_uring_register_bpf_filter(&ring, &bpf);
-
-/* Or register on the task */
-io_uring_register_bpf_filter_task(&bpf);
-.EE
-.in
-.SS Allow only AF_INET sockets
-.PP
-.in +4n
-.EX
-#include <sys/prctl.h>
-#include <linux/filter.h>
-#include <sys/socket.h>
-#include <liburing.h>
-#include <liburing/io_uring/bpf_filter.h>
-
-#define CTX_OFF_SOCKET_FAMILY 16
-
-struct sock_filter inet_only_filter[] = {
- /* Load socket family from context */
- BPF_STMT(BPF_LD | BPF_W | BPF_ABS, CTX_OFF_SOCKET_FAMILY),
- /* If family == AF_INET, jump to allow */
- BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, AF_INET, 0, 1),
- /* Allow: return 1 */
- BPF_STMT(BPF_RET | BPF_K, 1),
- /* Deny: return 0 */
- BPF_STMT(BPF_RET | BPF_K, 0),
-};
-
-struct io_uring_bpf bpf = {
- .cmd_type = IO_URING_BPF_CMD_FILTER,
- .filter = {
- .opcode = IORING_OP_SOCKET,
- .filter_len = 4,
- .filter_ptr = (unsigned long) inet_only_filter,
- .pdu_size = 12, /* 3x __u32: family, type, protocol */
- },
-};
-
-prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-io_uring_register_bpf_filter_task(&bpf);
-.EE
-.in
-.SS Allow only NOP, deny everything else
-.PP
-.in +4n
-.EX
-struct sock_filter allow_filter[] = {
- BPF_STMT(BPF_RET | BPF_K, 1), /* return 1 (allow) */
-};
-
-struct io_uring_bpf bpf = {
- .cmd_type = IO_URING_BPF_CMD_FILTER,
- .filter = {
- .opcode = IORING_OP_NOP,
- .flags = IO_URING_BPF_FILTER_DENY_REST,
- .filter_len = 1,
- .filter_ptr = (unsigned long) allow_filter,
- },
-};
-
-prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-io_uring_register_bpf_filter_task(&bpf);
-.EE
-.in
-.SS Discover kernel pdu_size for an opcode
-This example demonstrates how to use the
-.B -EMSGSIZE
-write-back to discover the kernel's expected payload size.
-.PP
-.in +4n
-.EX
-struct sock_filter allow[] = {
- BPF_STMT(BPF_RET | BPF_K, 1),
-};
-
-struct io_uring_bpf bpf = {
- .cmd_type = IO_URING_BPF_CMD_FILTER,
- .filter = {
- .opcode = IORING_OP_SOCKET,
- .flags = IO_URING_BPF_FILTER_SZ_STRICT,
- .filter_len = 1,
- .filter_ptr = (unsigned long) allow,
- .pdu_size = 0, /* intentionally wrong */
- },
-};
-int ret;
-
-ret = io_uring_register_bpf_filter(&ring, &bpf);
-if (ret == -EMSGSIZE) {
- /* kernel wrote back expected size */
- printf("kernel pdu_size for SOCKET: %u\\n",
- bpf.filter.pdu_size);
- /* retry with correct size */
- ret = io_uring_register_bpf_filter(&ring, &bpf);
-}
-.EE
-.in
-.SH NOTES
-.SS Privilege Requirements
-Similar to
-.BR seccomp (2),
-registering BPF filters requires either the
-.B CAP_SYS_ADMIN
-capability or the
-.B no_new_privs
-attribute to be set on the calling task. This prevents an unprivileged
-process from installing a filter and then executing a setuid binary,
-which would run with elevated privileges but under the attacker-controlled
-filter.
-.PP
-To set the
-.B no_new_privs
-attribute, call:
-.PP
-.in +4n
-.EX
-prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
-.EE
-.in
-.PP
-Once set,
-.B no_new_privs
-cannot be unset and is inherited by child processes across
-.BR fork (2)
-and preserved across
-.BR execve (2).
-.SS Inheritance
-Task-level filters registered with
-.BR io_uring_register_bpf_filter_task (3)
-are inherited by child processes. This allows a parent process to
-establish security restrictions that apply to all descendants.
-Children can add additional restrictions but cannot remove or
-weaken filters set by their ancestors.
-.PP
-Ring-level filters registered with
-.BR io_uring_register_bpf_filter (3)
-only apply to that specific ring and are not inherited.
-.SH SEE ALSO
-.BR io_uring_register (2),
-.BR io_uring_setup (2),
-.BR bpf (2),
-.BR seccomp (2)
diff --git a/man/io_uring_register_bpf_filter.3.md b/man/io_uring_register_bpf_filter.3.md
new file mode 100644
index 00000000..d4226498
--- /dev/null
+++ b/man/io_uring_register_bpf_filter.3.md
@@ -0,0 +1,358 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 18, 2026
+footer: liburing-2.14
+header: liburing Manual
+section: 3
+title: io_uring_register_bpf_filter
+---
+
+# NAME
+
+io_uring_register_bpf_filter, io_uring_register_bpf_filter_task -
+register classic BPF filters for io_uring operations
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+#include <liburing/io_uring/bpf_filter.h>
+#include <linux/filter.h>
+
+ int io_uring_register_bpf_filter(struct io_uring * ring ,
+ struct io_uring_bpf * bpf );
+
+ int io_uring_register_bpf_filter_task(struct io_uring_bpf * bpf );
+```
+
+# DESCRIPTION
+
+These functions register classic BPF (cBPF) filters to restrict io_uring
+operations. Filters can be used to implement security policies by
+allowing or denying specific operations based on their parameters.
+
+**io_uring_register_bpf_filter**(3) registers a filter on a specific
+*ring*. The filter only applies to operations submitted through that
+ring.
+
+**io_uring_register_bpf_filter_task**(3) registers a filter on the
+calling task. The filter applies to all io_uring rings created by the
+task after the filter is registered, and is inherited by child processes
+created via **fork**(2). Rings that were created before the filter was
+registered are not affected. Task-level filters cannot be removed and
+child processes cannot loosen restrictions set by their parent.
+
+The *bpf* argument is a pointer to a **struct io_uring_bpf** with
+*cmd_type* set to **IO_URING_BPF_CMD_FILTER**. The embedded **struct
+io_uring_bpf_filter** describes the filter to register:
+
+``` text
+struct io_uring_bpf_filter {
+ __u32 opcode; /* io_uring opcode to filter */
+ __u32 flags; /* IO_URING_BPF_FILTER_* */
+ __u32 filter_len; /* number of BPF instructions */
+ __u8 pdu_size; /* expected pdu size for opcode */
+ __u8 resv[3];
+ __u64 filter_ptr; /* pointer to BPF filter */
+ __u64 resv2[5];
+};
+```
+
+*opcode* specifies which io_uring operation the filter applies to (e.g.,
+**IORING_OP_SOCKET**, **IORING_OP_NOP**, **IORING_OP_READ**).
+
+*filter_ptr* points to an array of *filter_len* BPF instructions
+(**struct sock_filter**). The filter is executed for each matching
+operation and must return non-zero to allow the operation or zero to
+deny it (resulting in **-EACCES** being returned to the application).
+
+*pdu_size* specifies the expected size in bytes of the
+operation-specific payload data for the given opcode (e.g., the socket
+or open structs inside **struct io_uring_bpf_ctx**). For opcodes that
+have no extra payload, this should be zero. For **IORING_OP_SOCKET**
+this would be 12 (three 4-byte members), and for **IORING_OP_OPENAT**
+and **IORING_OP_OPENAT2** this would be 24 (three 8-byte members).
+
+If the application\'s *pdu_size* matches the kernel\'s expected size for
+the opcode, registration succeeds. If the sizes differ, the behavior
+depends on whether **IO_URING_BPF_FILTER_SZ_STRICT** is set in *flags*:
+
+> - If **IO_URING_BPF_FILTER_SZ_STRICT** is set, registration fails with
+> **-EMSGSIZE** if the sizes differ.
+>
+> - If **IO_URING_BPF_FILTER_SZ_STRICT** is not set, registration is
+> allowed if the application\'s *pdu_size* is smaller than the
+> kernel\'s. This permits older applications that were compiled
+> against a smaller payload to still load filters, as the kernel can
+> safely evaluate the filter on the subset of data the application
+> expects.
+>
+> - Regardless of **IO_URING_BPF_FILTER_SZ_STRICT**, registration always
+> fails with **-EMSGSIZE** if the application\'s *pdu_size* is larger
+> than the kernel\'s, since the kernel cannot provide data that it
+> does not support.
+
+On an **-EMSGSIZE** failure, the kernel writes back the kernel\'s
+expected *pdu_size* into the **struct io_uring_bpf_filter** passed by
+the application. This allows the application to discover the kernel\'s
+expected payload size and adjust or retry accordingly.
+
+*flags* can be zero or a bitwise OR of the following:
+
+**IO_URING_BPF_FILTER_DENY_REST**
+
+: When set, any opcode that does not have a filter registered will be
+ denied. This allows creating an allowlist of permitted operations.
+
+**IO_URING_BPF_FILTER_SZ_STRICT**
+
+: When set, registration of a filter will fail with **-EMSGSIZE** if the
+ application\'s *pdu_size* does not exactly match the kernel\'s
+ expected payload size for the opcode. Without this flag, the kernel
+ permits filters where the application\'s *pdu_size* is smaller than or
+ equal to the kernel\'s.
+
+## Filter Context
+
+The BPF filter receives a context structure that can be inspected using
+**BPF_LD** instructions with absolute addressing. The context layout is:
+
+``` text
+struct io_uring_bpf_ctx {
+ __u64 user_data; /* offset 0: user_data from SQE */
+ __u8 opcode; /* offset 8: io_uring opcode */
+ __u8 sqe_flags; /* offset 9: SQE flags */
+ __u8 pdu_size; /* offset 10: aux data size for filter */
+ __u8 pad[5]; /* offset 11-15: padding */
+ union {
+ struct {
+ __u32 family; /* offset 16: socket family */
+ __u32 type; /* offset 20: socket type */
+ __u32 protocol; /* offset 24: socket protocol */
+ } socket;
+ struct {
+ __u64 flags; /* offset 16: open flags */
+ __u64 mode; /* offset 24: file mode */
+ __u64 resolve; /* offset 32: resolve flags */
+ } open;
+ };
+};
+```
+
+The *pdu_size* field indicates the size in bytes of the
+operation-specific data passed in the union. A filter can check this
+value to verify it is receiving the expected payload. This is useful for
+forward compatibility: if a future kernel adds new members to an
+operation\'s context, the filter can inspect *pdu_size* to determine
+whether those fields are present.
+
+For **IORING_OP_SOCKET** operations, the socket family, type, and
+protocol fields are populated and can be used to filter based on socket
+parameters. *pdu_size* is set to 12 (three 4-byte members).
+
+For **IORING_OP_OPENAT** and **IORING_OP_OPENAT2** operations, the open
+flags, mode, and resolve fields are populated. The flags field contains
+the open flags (e.g., **O_RDONLY**, **O_CREAT**). The resolve field is
+only meaningful for **IORING_OP_OPENAT2** and contains resolve flags
+(e.g., **RESOLVE_IN_ROOT**). *pdu_size* is set to 24 (three 8-byte
+members).
+
+## Filter Stacking
+
+Multiple filters can be registered for the same opcode. When multiple
+filters exist, they are evaluated in order and all must return non-zero
+for the operation to be allowed. For task-level filters, the child\'s
+filters are evaluated before the parent\'s filters.
+
+# RETURN VALUE
+
+On success, these functions return 0. On failure, they return a negative
+error code.
+
+# ERRORS
+
+**-EINVAL**
+
+: Invalid filter, opcode, or flags specified.
+
+**-EMSGSIZE**
+
+: The application\'s *pdu_size* does not match the kernel\'s expected
+ payload size for the opcode. This occurs when
+ **IO_URING_BPF_FILTER_SZ_STRICT** is set and the sizes differ, or when
+ the application\'s *pdu_size* is larger than the kernel\'s regardless
+ of flags.
+
+**-ENOMEM**
+
+: Insufficient memory to register the filter.
+
+**-EFAULT**
+
+: The filter pointer is invalid.
+
+**-EACCES**
+
+: The caller does not have the **CAP_SYS_ADMIN** capability and the
+ **no_new_privs** attribute is not set on the calling task. See
+ **prctl**(2) with **PR_SET_NO_NEW_PRIVS**.
+
+# EXAMPLES
+
+## Deny all NOP operations
+
+``` text
+#include <sys/prctl.h>
+#include <linux/filter.h>
+#include <liburing.h>
+#include <liburing/io_uring/bpf_filter.h>
+
+struct sock_filter deny_filter[] = {
+ BPF_STMT(BPF_RET | BPF_K, 0), /* return 0 (deny) */
+};
+
+struct io_uring_bpf bpf = {
+ .cmd_type = IO_URING_BPF_CMD_FILTER,
+ .filter = {
+ .opcode = IORING_OP_NOP,
+ .filter_len = 1,
+ .filter_ptr = (unsigned long) deny_filter,
+ },
+};
+
+/* Must set no_new_privs before registering task filters */
+prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+
+/* Register on a specific ring */
+io_uring_register_bpf_filter(&ring, &bpf);
+
+/* Or register on the task */
+io_uring_register_bpf_filter_task(&bpf);
+```
+
+## Allow only AF_INET sockets
+
+``` text
+#include <sys/prctl.h>
+#include <linux/filter.h>
+#include <sys/socket.h>
+#include <liburing.h>
+#include <liburing/io_uring/bpf_filter.h>
+
+#define CTX_OFF_SOCKET_FAMILY 16
+
+struct sock_filter inet_only_filter[] = {
+ /* Load socket family from context */
+ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, CTX_OFF_SOCKET_FAMILY),
+ /* If family == AF_INET, jump to allow */
+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, AF_INET, 0, 1),
+ /* Allow: return 1 */
+ BPF_STMT(BPF_RET | BPF_K, 1),
+ /* Deny: return 0 */
+ BPF_STMT(BPF_RET | BPF_K, 0),
+};
+
+struct io_uring_bpf bpf = {
+ .cmd_type = IO_URING_BPF_CMD_FILTER,
+ .filter = {
+ .opcode = IORING_OP_SOCKET,
+ .filter_len = 4,
+ .filter_ptr = (unsigned long) inet_only_filter,
+ .pdu_size = 12, /* 3x __u32: family, type, protocol */
+ },
+};
+
+prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+io_uring_register_bpf_filter_task(&bpf);
+```
+
+## Allow only NOP, deny everything else
+
+``` text
+struct sock_filter allow_filter[] = {
+ BPF_STMT(BPF_RET | BPF_K, 1), /* return 1 (allow) */
+};
+
+struct io_uring_bpf bpf = {
+ .cmd_type = IO_URING_BPF_CMD_FILTER,
+ .filter = {
+ .opcode = IORING_OP_NOP,
+ .flags = IO_URING_BPF_FILTER_DENY_REST,
+ .filter_len = 1,
+ .filter_ptr = (unsigned long) allow_filter,
+ },
+};
+
+prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+io_uring_register_bpf_filter_task(&bpf);
+```
+
+## Discover kernel pdu_size for an opcode
+
+This example demonstrates how to use the **-EMSGSIZE** write-back to
+discover the kernel\'s expected payload size.
+
+``` text
+struct sock_filter allow[] = {
+ BPF_STMT(BPF_RET | BPF_K, 1),
+};
+
+struct io_uring_bpf bpf = {
+ .cmd_type = IO_URING_BPF_CMD_FILTER,
+ .filter = {
+ .opcode = IORING_OP_SOCKET,
+ .flags = IO_URING_BPF_FILTER_SZ_STRICT,
+ .filter_len = 1,
+ .filter_ptr = (unsigned long) allow,
+ .pdu_size = 0, /* intentionally wrong */
+ },
+};
+int ret;
+
+ret = io_uring_register_bpf_filter(&ring, &bpf);
+if (ret == -EMSGSIZE) {
+ /* kernel wrote back expected size */
+ printf("kernel pdu_size for SOCKET: %u\n",
+ bpf.filter.pdu_size);
+ /* retry with correct size */
+ ret = io_uring_register_bpf_filter(&ring, &bpf);
+}
+```
+
+# NOTES
+
+## Privilege Requirements
+
+Similar to **seccomp**(2), registering BPF filters requires either the
+**CAP_SYS_ADMIN** capability or the **no_new_privs** attribute to be set
+on the calling task. This prevents an unprivileged process from
+installing a filter and then executing a setuid binary, which would run
+with elevated privileges but under the attacker-controlled filter.
+
+To set the **no_new_privs** attribute, call:
+
+``` text
+prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+```
+
+Once set, **no_new_privs** cannot be unset and is inherited by child
+processes across **fork**(2) and preserved across **execve**(2).
+
+## Inheritance
+
+Task-level filters registered with
+**io_uring_register_bpf_filter_task**(3) are inherited by child
+processes. This allows a parent process to establish security
+restrictions that apply to all descendants. Children can add additional
+restrictions but cannot remove or weaken filters set by their ancestors.
+
+Ring-level filters registered with **io_uring_register_bpf_filter**(3)
+only apply to that specific ring and are not inherited.
+
+# SEE ALSO
+
+**io_uring_register**(2), **io_uring_setup**(2), **bpf**(2),
+**seccomp**(2)
diff --git a/man/io_uring_register_buf_ring.3 b/man/io_uring_register_buf_ring.3
deleted file mode 100644
index 14f5cdec..00000000
--- a/man/io_uring_register_buf_ring.3
+++ /dev/null
@@ -1,165 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_register_buf_ring 3 "May 18, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_register_buf_ring \- register buffer ring for provided buffers
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_register_buf_ring(struct io_uring *" ring ",
-.BI " struct io_uring_buf_reg *" reg ",
-.BI " unsigned int " flags ");"
-.BI "
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_register_buf_ring (3)
-function registers a shared buffer ring to be used with provided buffers. For
-the request types that support it, provided buffers are given to the ring and
-one is selected by a request if it has
-.B IOSQE_BUFFER_SELECT
-set in the SQE
-.IR flags ,
-when the request is ready to receive data. This allows both clear ownership
-of the buffer lifetime, and a way to have more read/receive type of operations
-in flight than buffers available.
-
-The
-.I reg
-argument must be filled in with the appropriate information. It looks as
-follows:
-.PP
-.in +4n
-.EX
-struct io_uring_buf_reg {
- __u64 ring_addr;
- __u32 ring_entries;
- __u16 bgid;
- __u16 flags;
- __u32 min_left;
- __u32 resv[5];
-};
-.EE
-.in
-.PP
-The
-.I ring_addr
-field must contain the address to the memory allocated to fit this ring.
-The memory must be page aligned and hence allocated appropriately using eg
-.BR posix_memalign (3)
-or similar. The size of the ring is the product of
-.I ring_entries
-and the size of
-.IR "struct io_uring_buf" .
-.I ring_entries
-is the desired size of the ring, and must be a power-of-2 in size. The maximum
-size allowed is 2^15 (32768).
-.I bgid
-is the buffer group ID associated with this ring. SQEs that select a buffer
-have a buffer group associated with them in their
-.I buf_group
-field, and the associated CQEs will have
-.B IORING_CQE_F_BUFFER
-set in their
-.I flags
-member, which will also contain the specific ID of the buffer selected.
-.I min_left
-is the minimum value that should be left in an incrementally consumed buffer
-ring for the buffer to be considered valid. If not set, defaults to a single
-byte. Only valid with
-.B IOU_PBUF_RING_INC
-set in
-.I flags .
-The rest of the fields are reserved and must be cleared to zero.
-
-The
-.I flags
-argument can be set to one of the following values:
-.TP
-.B IOU_PBUF_RING_INC
-The buffers in this ring can be incrementally consumed. With partial
-consumption, each completion of a given buffer ID will continue where the
-previous one left off, or from the start if no completions have been seen yet.
-When more completions should be expected for a given buffer ID, the CQE will
-have
-.B IORING_CQE_F_BUF_MORE
-set in the
-.I flags
-member. Available since 6.12.
-.PP
-
-A shared buffer ring looks as follows:
-.PP
-.in +4n
-.EX
-struct io_uring_buf_ring {
- union {
- struct {
- __u64 resv1;
- __u32 resv2;
- __u16 resv3;
- __u16 tail;
- };
- struct io_uring_buf bufs[0];
- };
-};
-.EE
-.in
-.PP
-where
-.I tail
-is the index at which the application can insert new buffers for consumption
-by requests, and
-.I struct io_uring_buf
-is buffer definition:
-.PP
-.in +4n
-.EX
-struct io_uring_buf {
- __u64 addr;
- __u32 len;
- __u16 bid;
- __u16 resv;
-};
-.EE
-.in
-.PP
-where
-.I addr
-is the address for the buffer,
-.I len
-is the length of the buffer in bytes, and
-.I bid
-is the buffer ID that will be returned in the CQE once consumed.
-
-Reserved fields must not be touched. Applications must use
-.BR io_uring_buf_ring_init (3)
-to initialise the buffer ring before use. Applications may use
-.BR io_uring_buf_ring_add (3)
-and
-.BR io_uring_buf_ring_advance (3)
-or
-.BR io_uring_buf_ring_cq_advance (3)
-to provide buffers, which will set these fields and update the tail.
-
-Available since 5.19.
-
-.SH RETURN VALUE
-On success
-.BR io_uring_register_buf_ring (3)
-returns 0. On failure it returns
-.BR -errno .
-.SH NOTES
-Unless manual setup is needed, it's recommended to use
-.BR io_uring_setup_buf_ring (3)
-as it provides a simpler way to setup a provided buffer ring.
-.SH SEE ALSO
-.BR io_uring_buf_ring_init (3),
-.BR io_uring_buf_ring_add (3),
-.BR io_uring_setup_buf_ring (3),
-.BR io_uring_buf_ring_advance (3),
-.BR io_uring_buf_ring_cq_advance (3)
diff --git a/man/io_uring_register_buf_ring.3.md b/man/io_uring_register_buf_ring.3.md
new file mode 100644
index 00000000..86fe7b10
--- /dev/null
+++ b/man/io_uring_register_buf_ring.3.md
@@ -0,0 +1,135 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: May 18, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_register_buf_ring
+---
+
+# NAME
+
+io_uring_register_buf_ring - register buffer ring for provided buffers
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_register_buf_ring(struct io_uring * ring ,
+ struct io_uring_buf_reg * reg ,
+ unsigned int flags );
+
+```
+
+# DESCRIPTION
+
+The **io_uring_register_buf_ring**(3) function registers a shared buffer
+ring to be used with provided buffers. For the request types that
+support it, provided buffers are given to the ring and one is selected
+by a request if it has **IOSQE_BUFFER_SELECT** set in the SQE *flags*,
+when the request is ready to receive data. This allows both clear
+ownership of the buffer lifetime, and a way to have more read/receive
+type of operations in flight than buffers available.
+
+The *reg* argument must be filled in with the appropriate information.
+It looks as follows:
+
+``` text
+struct io_uring_buf_reg {
+ __u64 ring_addr;
+ __u32 ring_entries;
+ __u16 bgid;
+ __u16 flags;
+ __u32 min_left;
+ __u32 resv[5];
+};
+```
+
+The *ring_addr* field must contain the address to the memory allocated
+to fit this ring. The memory must be page aligned and hence allocated
+appropriately using eg **posix_memalign**(3) or similar. The size of the
+ring is the product of *ring_entries* and the size of *struct
+io_uring_buf*. *ring_entries* is the desired size of the ring, and must
+be a power-of-2 in size. The maximum size allowed is 2\^15 (32768).
+*bgid* is the buffer group ID associated with this ring. SQEs that
+select a buffer have a buffer group associated with them in their
+*buf_group* field, and the associated CQEs will have
+**IORING_CQE_F_BUFFER** set in their *flags* member, which will also
+contain the specific ID of the buffer selected. *min_left* is the
+minimum value that should be left in an incrementally consumed buffer
+ring for the buffer to be considered valid. If not set, defaults to a
+single byte. Only valid with **IOU_PBUF_RING_INC** set in *flags .* The
+rest of the fields are reserved and must be cleared to zero.
+
+The *flags* argument can be set to one of the following values:
+
+**IOU_PBUF_RING_INC**
+
+: The buffers in this ring can be incrementally consumed. With partial
+ consumption, each completion of a given buffer ID will continue where
+ the previous one left off, or from the start if no completions have
+ been seen yet. When more completions should be expected for a given
+ buffer ID, the CQE will have **IORING_CQE_F_BUF_MORE** set in the
+ *flags* member. Available since 6.12.
+
+A shared buffer ring looks as follows:
+
+``` text
+struct io_uring_buf_ring {
+ union {
+ struct {
+ __u64 resv1;
+ __u32 resv2;
+ __u16 resv3;
+ __u16 tail;
+ };
+ struct io_uring_buf bufs[0];
+ };
+};
+```
+
+where *tail* is the index at which the application can insert new
+buffers for consumption by requests, and *struct io_uring_buf* is buffer
+definition:
+
+``` text
+struct io_uring_buf {
+ __u64 addr;
+ __u32 len;
+ __u16 bid;
+ __u16 resv;
+};
+```
+
+where *addr* is the address for the buffer, *len* is the length of the
+buffer in bytes, and *bid* is the buffer ID that will be returned in the
+CQE once consumed.
+
+Reserved fields must not be touched. Applications must use
+**io_uring_buf_ring_init**(3) to initialise the buffer ring before use.
+Applications may use **io_uring_buf_ring_add**(3) and
+**io_uring_buf_ring_advance**(3) or **io_uring_buf_ring_cq_advance**(3)
+to provide buffers, which will set these fields and update the tail.
+
+Available since 5.19.
+
+# RETURN VALUE
+
+On success **io_uring_register_buf_ring**(3) returns 0. On failure it
+returns **-errno**.
+
+# NOTES
+
+Unless manual setup is needed, it\'s recommended to use
+**io_uring_setup_buf_ring**(3) as it provides a simpler way to setup a
+provided buffer ring.
+
+# SEE ALSO
+
+**io_uring_buf_ring_init**(3), **io_uring_buf_ring_add**(3),
+**io_uring_setup_buf_ring**(3), **io_uring_buf_ring_advance**(3),
+**io_uring_buf_ring_cq_advance**(3)
diff --git a/man/io_uring_register_buffers.3 b/man/io_uring_register_buffers.3
deleted file mode 100644
index dfb292da..00000000
--- a/man/io_uring_register_buffers.3
+++ /dev/null
@@ -1,105 +0,0 @@
-.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_register_buffers 3 "November 15, 2021" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_register_buffers \- register buffers for fixed buffer operations
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_register_buffers(struct io_uring *" ring ","
-.BI " const struct iovec *" iovecs ","
-.BI " unsigned " nr_iovecs ");"
-.PP
-.BI "int io_uring_register_buffers_tags(struct io_uring *" ring ","
-.BI " const struct iovec *" iovecs ","
-.BI " const __u64 *" tags ","
-.BI " unsigned " nr ");"
-.PP
-.BI "int io_uring_register_buffers_sparse(struct io_uring *" ring ","
-.BI " unsigned " nr_iovecs ");"
-.PP
-.BI "int io_uring_register_buffers_update_tag(struct io_uring *" ring ","
-.BI " unsigned " off ","
-.BI " const struct iovec *" iovecs ","
-.BI " const __u64 *" tags ","
-.BI " unsigned " nr ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_register_buffers (3)
-function registers
-.I nr_iovecs
-number of buffers defined by the array
-.I iovecs
-belonging to the
-.IR ring .
-
-The
-.BR io_uring_register_buffers_tags (3)
-function behaves the same as
-.BR io_uring_register_buffers (3)
-function but additionally takes
-.I tags
-parameter. See
-.B IORING_REGISTER_BUFFERS2
-for the resource tagging description.
-
-The
-.BR io_uring_register_buffers_sparse (3)
-function registers
-.I nr_iovecs
-empty buffers belonging to the
-.IR ring .
-These buffers must be updated before use, using eg
-.BR io_uring_register_buffers_update_tag (3).
-
-After the caller has registered the buffers, they can be used with one of the
-fixed buffers functions.
-
-Registered buffers is an optimization that is useful in conjunction with
-.B O_DIRECT
-reads and writes, where it maps the specified range into the kernel once when
-the buffer is registered rather than doing a map and unmap for each IO
-every time IO is performed to that region. Additionally, it also avoids
-manipulating the page reference counts for each IO.
-
-The
-.BR io_uring_register_buffers_update_tag (3)
-function updates registered buffers with new ones, either turning a sparse
-entry into a real one, or replacing an existing entry. The
-.I off
-is offset on which to start the update
-.I nr
-number of buffers defined by the array
-.I iovecs
-belonging to the
-.IR ring .
-The
-.I tags
-points to an array of tags. See
-.B IORING_REGISTER_BUFFERS2
-for the resource tagging description.
-
-.SH RETURN VALUE
-On success
-.BR io_uring_register_buffers (3),
-.BR io_uring_register_buffers_tags (3)
-and
-.BR io_uring_register_buffers_sparse (3)
-return 0.
-.BR io_uring_register_buffers_update_tag (3)
-return number of buffers updated.
-On failure they return
-.BR -errno .
-.SH SEE ALSO
-.BR io_uring_register (2),
-.BR io_uring_get_sqe (3),
-.BR io_uring_unregister_buffers (3),
-.BR io_uring_clone_buffers (3),
-.BR io_uring_register_buf_ring (3),
-.BR io_uring_prep_read_fixed (3),
-.BR io_uring_prep_write_fixed (3)
diff --git a/man/io_uring_register_buffers.3.md b/man/io_uring_register_buffers.3.md
new file mode 100644
index 00000000..00bde5e2
--- /dev/null
+++ b/man/io_uring_register_buffers.3.md
@@ -0,0 +1,86 @@
+.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: November 15, 2021
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_register_buffers
+---
+
+# NAME
+
+io_uring_register_buffers - register buffers for fixed buffer operations
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_register_buffers(struct io_uring * ring ,
+ const struct iovec * iovecs ,
+ unsigned nr_iovecs );
+
+ int io_uring_register_buffers_tags(struct io_uring * ring ,
+ const struct iovec * iovecs ,
+ const __u64 * tags ,
+ unsigned nr );
+
+ int io_uring_register_buffers_sparse(struct io_uring * ring ,
+ unsigned nr_iovecs );
+
+ int io_uring_register_buffers_update_tag(struct io_uring * ring ,
+ unsigned off ,
+ const struct iovec * iovecs ,
+ const __u64 * tags ,
+ unsigned nr );
+```
+
+# DESCRIPTION
+
+The **io_uring_register_buffers**(3) function registers *nr_iovecs*
+number of buffers defined by the array *iovecs* belonging to the *ring*.
+
+The **io_uring_register_buffers_tags**(3) function behaves the same as
+**io_uring_register_buffers**(3) function but additionally takes *tags*
+parameter. See **IORING_REGISTER_BUFFERS2** for the resource tagging
+description.
+
+The **io_uring_register_buffers_sparse**(3) function registers
+*nr_iovecs* empty buffers belonging to the *ring*. These buffers must be
+updated before use, using eg
+**io_uring_register_buffers_update_tag**(3).
+
+After the caller has registered the buffers, they can be used with one
+of the fixed buffers functions.
+
+Registered buffers is an optimization that is useful in conjunction with
+**O_DIRECT** reads and writes, where it maps the specified range into
+the kernel once when the buffer is registered rather than doing a map
+and unmap for each IO every time IO is performed to that region.
+Additionally, it also avoids manipulating the page reference counts for
+each IO.
+
+The **io_uring_register_buffers_update_tag**(3) function updates
+registered buffers with new ones, either turning a sparse entry into a
+real one, or replacing an existing entry. The *off* is offset on which
+to start the update *nr* number of buffers defined by the array *iovecs*
+belonging to the *ring*. The *tags* points to an array of tags. See
+**IORING_REGISTER_BUFFERS2** for the resource tagging description.
+
+# RETURN VALUE
+
+On success **io_uring_register_buffers**(3),
+**io_uring_register_buffers_tags**(3) and
+**io_uring_register_buffers_sparse**(3) return 0.
+**io_uring_register_buffers_update_tag**(3) return number of buffers
+updated. On failure they return **-errno**.
+
+# SEE ALSO
+
+**io_uring_register**(2), **io_uring_get_sqe**(3),
+**io_uring_unregister_buffers**(3), **io_uring_clone_buffers**(3),
+**io_uring_register_buf_ring**(3), **io_uring_prep_read_fixed**(3),
+**io_uring_prep_write_fixed**(3)
diff --git a/man/io_uring_register_clock.3 b/man/io_uring_register_clock.3
deleted file mode 100644
index 56ed1ac2..00000000
--- a/man/io_uring_register_clock.3
+++ /dev/null
@@ -1,72 +0,0 @@
-.\" Copyright (C) 2024 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_register_clock 3 "Aug 18, 2024" "liburing-2.8" "liburing Manual"
-.SH NAME
-io_uring_register_clock \- set clock source for event waiting
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_register_clock(struct io_uring *" ring ",
-.BI " struct io_uring_clock_register *" arg ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_register_clock (3)
-function registers which clock source should be used by io_uring, when an
-application waits for event completions. The
-.IR ring
-argument should point to the ring in question, and the
-.IR arg
-argument should be a pointer to a
-.B struct io_uring_clock_register .
-
-The
-.IR arg
-argument must be filled in with the appropriate information. It looks as
-follows:
-.PP
-.in +4n
-.EX
-struct io_uring_clock_register {
- __u32 clockid;
- __u32 __resv[3];
-};
-.EE
-.in
-.PP
-The
-.I clockid
-field must contain the clock source, with valid sources being:
-.TP
-.B CLOCK_MONOTONIC
-a nonsettable system-wide clock that represents monotonic time.
-.TP
-.B CLOCK_BOOTTIME
-A nonsettable system-wide clock that is identical to
-.B CLOCK_MONOTONIC ,
-except that is also icnludes any time that the system is suspended.
-.PP
-See
-.BR clock_gettime (3)
-for more details.
-
-The
-.I __resv
-fields must be filled with zeroes.
-
-Available since 6.12.
-
-.SH RETURN VALUE
-On success
-.BR io_uring_register_clock (3)
-returns 0. On failure it returns
-.BR -errno .
-.SH SEE ALSO
-.BR clock_gettime (3),
-.BR io_uring_register (2),
-.BR io_uring_wait_cqe (3),
-.BR io_uring_wait_cqe_timeout (3),
diff --git a/man/io_uring_register_clock.3.md b/man/io_uring_register_clock.3.md
new file mode 100644
index 00000000..42b1d26c
--- /dev/null
+++ b/man/io_uring_register_clock.3.md
@@ -0,0 +1,71 @@
+.\" Copyright (C) 2024 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: Aug 18, 2024
+footer: liburing-2.8
+header: liburing Manual
+section: 3
+title: io_uring_register_clock
+---
+
+# NAME
+
+io_uring_register_clock - set clock source for event waiting
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_register_clock(struct io_uring * ring ,
+ struct io_uring_clock_register * arg );
+```
+
+# DESCRIPTION
+
+The **io_uring_register_clock**(3) function registers which clock source
+should be used by io_uring, when an application waits for event
+completions. The *ring* argument should point to the ring in question,
+and the *arg* argument should be a pointer to a **struct
+io_uring_clock_register .**
+
+The *arg* argument must be filled in with the appropriate information.
+It looks as follows:
+
+``` text
+struct io_uring_clock_register {
+ __u32 clockid;
+ __u32 __resv[3];
+};
+```
+
+The *clockid* field must contain the clock source, with valid sources
+being:
+
+**CLOCK_MONOTONIC**
+
+: a nonsettable system-wide clock that represents monotonic time.
+
+**CLOCK_BOOTTIME**
+
+: A nonsettable system-wide clock that is identical to **CLOCK_MONOTONIC
+ ,** except that is also icnludes any time that the system is
+ suspended.
+
+See **clock_gettime**(3) for more details.
+
+The *\_\_resv* fields must be filled with zeroes.
+
+Available since 6.12.
+
+# RETURN VALUE
+
+On success **io_uring_register_clock**(3) returns 0. On failure it
+returns **-errno**.
+
+# SEE ALSO
+
+**clock_gettime**(3), **io_uring_register**(2),
+**io_uring_wait_cqe**(3), **io_uring_wait_cqe_timeout**(3),
diff --git a/man/io_uring_register_eventfd.3 b/man/io_uring_register_eventfd.3
deleted file mode 100644
index d9b4d44b..00000000
--- a/man/io_uring_register_eventfd.3
+++ /dev/null
@@ -1,50 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_register_eventfd 3 "April 16, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_register_eventfd \- register an eventfd with a ring
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_register_eventfd(struct io_uring *" ring ","
-.BI " int " fd ");"
-.PP
-.BI "int io_uring_register_eventfd_async(struct io_uring *" ring ","
-.BI " int " fd ");"
-.PP
-.BI "int io_uring_unregister_eventfd(struct io_uring *" ring ");"
-.fi
-.SH DESCRIPTION
-.PP
-.BR io_uring_register_eventfd (3)
-registers the eventfd file descriptor
-.I fd
-with the ring identified by
-.IR ring .
-
-Whenever completions are posted to the CQ ring, an eventfd notification
-is generated with the registered eventfd descriptor. If
-.BR io_uring_register_eventfd_async (3)
-is used, only events that completed out-of-line will trigger a notification.
-
-If notifications are no longer desired,
-.BR io_uring_unregister_eventfd (3)
-may be called to remove the eventfd registration. No eventfd argument is
-needed, as a ring can only have a single eventfd registered.
-
-.SH NOTES
-While io_uring generally takes care to avoid spurious events, they can occur.
-Similarly, batched completions of CQEs may only trigger a single eventfd
-notification even if multiple CQEs are posted. The application should make no
-assumptions on number of events being available having a direct correlation to
-eventfd notifications posted. An eventfd notification must thus only be treated
-as a hint to check the CQ ring for completions.
-.SH RETURN VALUE
-Returns 0 on success, or
-.BR -errno
-on error.
-.SH SEE ALSO
-.BR eventfd (2)
diff --git a/man/io_uring_register_eventfd.3.md b/man/io_uring_register_eventfd.3.md
new file mode 100644
index 00000000..eeddf2ca
--- /dev/null
+++ b/man/io_uring_register_eventfd.3.md
@@ -0,0 +1,62 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: April 16, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_register_eventfd
+---
+
+# NAME
+
+io_uring_register_eventfd - register an eventfd with a ring
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_register_eventfd(struct io_uring * ring ,
+ int fd );
+
+ int io_uring_register_eventfd_async(struct io_uring * ring ,
+ int fd );
+
+ int io_uring_unregister_eventfd(struct io_uring * ring );
+```
+
+# DESCRIPTION
+
+**io_uring_register_eventfd**(3) registers the eventfd file descriptor
+*fd* with the ring identified by *ring*.
+
+Whenever completions are posted to the CQ ring, an eventfd notification
+is generated with the registered eventfd descriptor. If
+**io_uring_register_eventfd_async**(3) is used, only events that
+completed out-of-line will trigger a notification.
+
+It notifications are no longer desired,
+**io_uring_unregister_eventfd**(3) may be called to remove the eventfd
+registration. No eventfd argument is needed, as a ring can only have a
+single eventfd registered.
+
+# NOTES
+
+While io_uring generally takes care to avoid spurious events, they can
+occur. Similarly, batched completions of CQEs may only trigger a single
+eventfd notification even if multiple CQEs are posted. The application
+should make no assumptions on number of events being available having a
+direct correlation to eventfd notifications posted. An eventfd
+notification must thus only be treated as a hint to check the CQ ring
+for completions.
+
+# RETURN VALUE
+
+Returns 0 on success, or **-errno** on error.
+
+# SEE ALSO
+
+**eventfd**(2)
diff --git a/man/io_uring_register_file_alloc_range.3 b/man/io_uring_register_file_alloc_range.3
deleted file mode 100644
index b4a42678..00000000
--- a/man/io_uring_register_file_alloc_range.3
+++ /dev/null
@@ -1,52 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_register_file_alloc_range 3 "Oct 21, 2022" "liburing-2.3" "liburing Manual"
-.SH NAME
-io_uring_register_file_alloc_range \- set range for fixed file allocations
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_register_file_alloc_range(struct io_uring *" ring ",
-.BI " unsigned " off ","
-.BI " unsigned " len ");"
-.BI "
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_register_file_alloc_range (3)
-function sets the allowable range for fixed file index allocations within the
-kernel. When requests that can instantiate a new fixed file are used with
-.B IORING_FILE_INDEX_ALLOC ,
-the application is asking the kernel to allocate a new fixed file descriptor
-rather than pass in a specific value for one. By default, the kernel will
-pick any available fixed file descriptor within the range available. Calling
-this function with
-.I off
-set to the starting offset and
-.I len
-set to the number of descriptors, the application can limit the allocated
-descriptors to that particular range. This effectively allows the application
-to set aside a range just for dynamic allocations, with the remainder being
-used for specific values.
-
-The application must have registered a fixed file table upfront, e.g. through
-.BR io_uring_register_files (3)
-or
-.BR io_uring_register_files_sparse (3) .
-
-Available since 6.0.
-
-.SH RETURN VALUE
-On success
-.BR io_uring_register_file_alloc_range (3)
-returns 0. On failure it returns
-.BR -errno .
-.SH SEE ALSO
-.BR io_uring_register_files (3)
-.BR io_uring_prep_accept_direct (3)
-.BR io_uring_prep_openat_direct (3)
-.BR io_uring_prep_socket_direct (3)
diff --git a/man/io_uring_register_file_alloc_range.3.md b/man/io_uring_register_file_alloc_range.3.md
new file mode 100644
index 00000000..07310278
--- /dev/null
+++ b/man/io_uring_register_file_alloc_range.3.md
@@ -0,0 +1,58 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: Oct 21, 2022
+footer: liburing-2.3
+header: liburing Manual
+section: 3
+title: io_uring_register_file_alloc_range
+---
+
+# NAME
+
+io_uring_register_file_alloc_range - set range for fixed file
+allocations
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_register_file_alloc_range(struct io_uring * ring ,
+ unsigned off ,
+ unsigned len );
+
+```
+
+# DESCRIPTION
+
+The **io_uring_register_file_alloc_range**(3) function sets the
+allowable range for fixed file index allocations within the kernel. When
+requests that can instantiate a new fixed file are used with
+**IORING_FILE_INDEX_ALLOC ,** the application is asking the kernel to
+allocate a new fixed file descriptor rather than pass in a specific
+value for one. By default, the kernel will pick any available fixed file
+descriptor within the range available. Calling this function with *off*
+set to the starting offset and *len* set to the number of descriptors,
+the application can limit the allocated descriptors to that particular
+range. This effectively allows the application to set aside a range just
+for dynamic allocations, with the remainder being used for specific
+values.
+
+The application must have registered a fixed file table upfront, e.g.
+through **io_uring_register_files**(3) or
+**io_uring_register_files_sparse**(3)**.**
+
+Available since 6.0.
+
+# RETURN VALUE
+
+On success **io_uring_register_file_alloc_range**(3) returns 0. On
+failure it returns **-errno**.
+
+# SEE ALSO
+
+**io_uring_register_files**(3) **io_uring_prep_accept_direct**(3)
+**io_uring_prep_openat_direct**(3) **io_uring_prep_socket_direct**(3)
diff --git a/man/io_uring_register_files.3 b/man/io_uring_register_files.3
deleted file mode 100644
index c7f73e92..00000000
--- a/man/io_uring_register_files.3
+++ /dev/null
@@ -1,120 +0,0 @@
-.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_register_files 3 "November 15, 2021" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_register_files \- register file descriptors
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_register_files(struct io_uring *" ring ","
-.BI " const int *" files ","
-.BI " unsigned " nr_files ");"
-.PP
-.BI "int io_uring_register_files_tags(struct io_uring *" ring ","
-.BI " const int *" files ","
-.BI " const __u64 *" tags ","
-.BI " unsigned " nr ");"
-.PP
-.BI "int io_uring_register_files_sparse(struct io_uring *" ring ","
-.BI " unsigned " nr_files ");"
-.PP
-.BI "int io_uring_register_files_update(struct io_uring *" ring ","
-.BI " unsigned " off ","
-.BI " const int *" files ","
-.BI " unsigned " nr_files ");"
-.PP
-.BI "int io_uring_register_files_update_tag(struct io_uring *" ring ","
-.BI " unsigned " off ","
-.BI " const int *" files ","
-.BI " const __u64 *" tags ","
-.BI " unsigned " nr_files ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_register_files (3)
-function registers
-.I nr_files
-number of file descriptors defined by the array
-.I files
-belonging to the
-.I ring
-for subsequent operations.
-
-The
-.BR io_uring_register_files_tags (3)
-function behaves the same as
-.BR io_uring_register_files (3)
-function but additionally takes
-.I tags
-parameter. See
-.B IORING_REGISTER_BUFFERS2
-for the resource tagging description.
-
-The
-.BR io_uring_register_files_sparse (3)
-function registers an empty file table of
-.I nr_files
-number of file descriptors. These files must be updated before use, using eg
-.BR io_uring_register_files_update_tag (3).
-Note that if the size of the sparse table exceeds what
-.B RLIMIT_NOFILE
-allows, then
-.BR io_uring_register_files_sparse (3)
-will attempt to raise the limit using
-.B setrlimit (2)
-and retry the operation. If the registration fails after doing that, then an
-error will be returned.
-The sparse variant is available in kernels 5.19 and later.
-
-Registering a file table is a prerequisite for using any request that uses
-direct descriptors.
-
-Registered files have less overhead per operation than normal files. This
-is due to the kernel grabbing a reference count on a file when an operation
-begins, and dropping it when it's done. When the process file table is
-shared, for example if the process has ever created any threads, then this
-cost goes up even more. Using registered files reduces the overhead of
-file reference management across requests that operate on a file.
-
-The
-.BR io_uring_register_files_update (3)
-function updates existing registered files. The
-.I off
-is offset on which to start the update
-.I nr_files
-number of files defined by the array
-.I files
-belonging to the
-.IR ring .
-
-The
-.BR io_uring_register_files_update_tag (3)
-function behaves the same as
-.BR io_uring_register_files_update (3)
-function but additionally takes
-.I tags
-parameter. See
-.B IORING_REGISTER_BUFFERS2
-for the resource tagging description.
-
-.SH RETURN VALUE
-On success
-.BR io_uring_register_files (3),
-.BR io_uring_register_files_tags (3)
-and
-.BR io_uring_register_files_sparse (3)
-return 0.
-.BR io_uring_register_files_update (3)
-and
-.BR io_uring_register_files_update_tag (3)
-return number of files updated.
-On failure they return
-.BR -errno .
-.SH SEE ALSO
-.BR io_uring_register (2),
-.BR io_uring_get_sqe (3),
-.BR io_uring_unregister_files (3)
diff --git a/man/io_uring_register_files.3.md b/man/io_uring_register_files.3.md
new file mode 100644
index 00000000..7da9e15d
--- /dev/null
+++ b/man/io_uring_register_files.3.md
@@ -0,0 +1,99 @@
+.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: November 15, 2021
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_register_files
+---
+
+# NAME
+
+io_uring_register_files - register file descriptors
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_register_files(struct io_uring * ring ,
+ const int * files ,
+ unsigned nr_files );
+
+ int io_uring_register_files_tags(struct io_uring * ring ,
+ const int * files ,
+ const __u64 * tags ,
+ unsigned nr );
+
+ int io_uring_register_files_sparse(struct io_uring * ring ,
+ unsigned nr_files );
+
+ int io_uring_register_files_update(struct io_uring * ring ,
+ unsigned off ,
+ const int * files ,
+ unsigned nr_files );
+
+ int io_uring_register_files_update_tag(struct io_uring * ring ,
+ unsigned off ,
+ const int * files ,
+ const __u64 * tags ,
+ unsigned nr_files );
+```
+
+# DESCRIPTION
+
+The **io_uring_register_files**(3) function registers *nr_files* number
+of file descriptors defined by the array *files* belonging to the *ring*
+for subsequent operations.
+
+The **io_uring_register_files_tags**(3) function behaves the same as
+**io_uring_register_files**(3) function but additionally takes *tags*
+parameter. See **IORING_REGISTER_BUFFERS2** for the resource tagging
+description.
+
+The **io_uring_register_files_sparse**(3) function registers an empty
+file table of *nr_files* number of file descriptors. These files must be
+updated before use, using eg **io_uring_register_files_update_tag**(3).
+Note that if the size of the sparse table exceeds what **RLIMIT_NOFILE**
+allows, then **io_uring_register_files_sparse**(3) will attempt to raise
+the limit using **setrlimit (2)** and retry the operation. If the
+registration fails after doing that, then an error will be returned. The
+sparse variant is available in kernels 5.19 and later.
+
+Registering a file table is a prerequisite for using any request that
+uses direct descriptors.
+
+Registered files have less overhead per operation than normal files.
+This is due to the kernel grabbing a reference count on a file when an
+operation begins, and dropping it when it\'s done. When the process file
+table is shared, for example if the process has ever created any
+threads, then this cost goes up even more. Using registered files
+reduces the overhead of file reference management across requests that
+operate on a file.
+
+The **io_uring_register_files_update**(3) function updates existing
+registered files. The *off* is offset on which to start the update
+*nr_files* number of files defined by the array *files* belonging to the
+*ring*.
+
+The **io_uring_register_files_update_tag**(3) function behaves the same
+as **io_uring_register_files_update**(3) function but additionally takes
+*tags* parameter. See **IORING_REGISTER_BUFFERS2** for the resource
+tagging description.
+
+# RETURN VALUE
+
+On success **io_uring_register_files**(3),
+**io_uring_register_files_tags**(3) and
+**io_uring_register_files_sparse**(3) return 0.
+**io_uring_register_files_update**(3) and
+**io_uring_register_files_update_tag**(3) return number of files
+updated. On failure they return **-errno**.
+
+# SEE ALSO
+
+**io_uring_register**(2), **io_uring_get_sqe**(3),
+**io_uring_unregister_files**(3)
diff --git a/man/io_uring_register_ifq.3 b/man/io_uring_register_ifq.3
deleted file mode 100644
index e9aa7aac..00000000
--- a/man/io_uring_register_ifq.3
+++ /dev/null
@@ -1,49 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_register_ifq 3 "January 18, 2025" "liburing-2.10" "liburing Manual"
-.SH NAME
-io_uring_register_ifq \- register a zero-copy receive interface queue
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_register_ifq(struct io_uring *" ring ","
-.BI " struct io_uring_zcrx_ifq_reg *" reg ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_register_ifq (3)
-function registers a zero-copy receive interface queue with the io_uring
-instance specified by
-.IR ring .
-Zero-copy receive allows the kernel to place incoming network data directly
-into application-provided memory without copying.
-
-The
-.I reg
-argument is a pointer to a
-.I struct io_uring_zcrx_ifq_reg
-that describes the interface queue to register. See
-.BR io_uring_register (2)
-for a description of the
-.B IORING_REGISTER_ZCRX_IFQ
-operation and the structure fields.
-
-The io_uring ring must have been created with
-.B IORING_SETUP_DEFER_TASKRUN
-and either
-.B IORING_SETUP_CQE32
-or
-.B IORING_SETUP_CQE_MIXED
-flags set. The caller must have the
-.B CAP_NET_ADMIN
-capability.
-
-.SH RETURN VALUE
-Returns 0 on success. On error, a negative errno value is returned.
-.SH SEE ALSO
-.BR io_uring_register (2),
-.BR io_uring_setup (2)
diff --git a/man/io_uring_register_ifq.3.md b/man/io_uring_register_ifq.3.md
new file mode 100644
index 00000000..6dd500ec
--- /dev/null
+++ b/man/io_uring_register_ifq.3.md
@@ -0,0 +1,49 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 18, 2025
+footer: liburing-2.10
+header: liburing Manual
+section: 3
+title: io_uring_register_ifq
+---
+
+# NAME
+
+io_uring_register_ifq - register a zero-copy receive interface queue
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_register_ifq(struct io_uring * ring ,
+ struct io_uring_zcrx_ifq_reg * reg );
+```
+
+# DESCRIPTION
+
+The **io_uring_register_ifq**(3) function registers a zero-copy receive
+interface queue with the io_uring instance specified by *ring*.
+Zero-copy receive allows the kernel to place incoming network data
+directly into application-provided memory without copying.
+
+The *reg* argument is a pointer to a *struct io_uring_zcrx_ifq_reg* that
+describes the interface queue to register. See **io_uring_register**(2)
+for a description of the **IORING_REGISTER_ZCRX_IFQ** operation and the
+structure fields.
+
+The io_uring ring must have been created with
+**IORING_SETUP_DEFER_TASKRUN** and either **IORING_SETUP_CQE32** or
+**IORING_SETUP_CQE_MIXED** flags set. The caller must have the
+**CAP_NET_ADMIN** capability.
+
+# RETURN VALUE
+
+Returns 0 on success. On error, a negative errno value is returned.
+
+# SEE ALSO
+
+**io_uring_register**(2), **io_uring_setup**(2)
diff --git a/man/io_uring_register_iowq_aff.3 b/man/io_uring_register_iowq_aff.3
deleted file mode 100644
index 686222c1..00000000
--- a/man/io_uring_register_iowq_aff.3
+++ /dev/null
@@ -1,67 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_register_iowq_aff 3 "March 13, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_register_iowq_aff \- register async worker CPU affinities
-.SH SYNOPSIS
-.nf
-.B #include <sched.h>
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_register_iowq_aff(struct io_uring *" ring ","
-.BI " size_t " cpusz ","
-.BI " const cpu_set_t *" mask ");
-.PP
-.BI "void io_uring_unregister_iowq_aff(struct io_uring *" ring ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_prep_register_iowq_aff (3)
-function registers a set of CPU affinities to be used by the io_uring async
-workers. By default, io_uring async workers are allowed to run on any CPU in
-the system. If this function is called with
-.I ring
-set to the ring in question and
-.I mask
-set to a pointer to a
-.B cpu_set_t
-value and
-.I cpusz
-set to the size of the CPU set, then async workers will only be allowed to run
-on the CPUs specified in the mask. Existing workers may need to hit a schedule
-point before they are migrated.
-
-For unregistration,
-.BR io_uring_unregister_iowq_aff (3)
-may be called to restore CPU affinities to the default.
-
-Applications must define
-.B _GNU_SOURCE
-to obtain the definition of this helper, as
-.I cpu_set_t
-will not be defined without it.
-
-.SH RETURN VALUE
-Returns
-.B 0
-on success, or any of the following values in case of error.
-.TP
-.B -EFAULT
-The kernel was unable to copy the memory pointer to by
-.I mask
-as it was invalid.
-.TP
-.B -ENOMEM
-The kernel was unable to allocate memory for the new CPU mask.
-.TP
-.B -EINVAL
-.I cpusz
-or
-.I mask
-was NULL/0, or any other value specified was invalid.
-.SH SEE ALSO
-.BR io_uring_queue_init (3),
-.BR io_uring_register (2)
diff --git a/man/io_uring_register_iowq_aff.3.md b/man/io_uring_register_iowq_aff.3.md
new file mode 100644
index 00000000..7cdcaf04
--- /dev/null
+++ b/man/io_uring_register_iowq_aff.3.md
@@ -0,0 +1,68 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 13, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_register_iowq_aff
+---
+
+# NAME
+
+io_uring_register_iowq_aff - register async worker CPU affinities
+
+# SYNOPSIS
+
+``` text
+#include <sched.h>
+#include <liburing.h>
+
+ int io_uring_register_iowq_aff(struct io_uring * ring ,
+ size_t cpusz ,
+ const cpu_set_t * mask );
+
+ void io_uring_unregister_iowq_aff(struct io_uring * ring );
+```
+
+# DESCRIPTION
+
+The **io_uring_prep_register_iowq_aff**(3) function registers a set of
+CPU affinities to be used by the io_uring async workers. By default,
+io_uring async workers are allowed to run on any CPU in the system. If
+this function is called with *ring* set to the ring in question and
+*mask* set to a pointer to a **cpu_set_t** value and *cpusz* set to the
+size of the CPU set, then async workers will only be allowed to run on
+the CPUs specified in the mask. Existing workers may need to hit a
+schedule point before they are migrated.
+
+For unregistration, **io_uring_unregister_iowq_aff**(3) may be called to
+restore CPU affinities to the default.
+
+Applications must define **\_GNU_SOURCE** to obtain the definition of
+this helper, as *cpu_set_t* will not be defined without it.
+
+# RETURN VALUE
+
+Returns **0** on success, or any of the following values in case of
+error.
+
+**-EFAULT**
+
+: The kernel was unable to copy the memory pointer to by *mask* as it
+ was invalid.
+
+**-ENOMEM**
+
+: The kernel was unable to allocate memory for the new CPU mask.
+
+**-EINVAL**
+
+: *cpusz* or *mask* was NULL/0, or any other value specified was
+ invalid.
+
+# SEE ALSO
+
+**io_uring_queue_init**(3), **io_uring_register**(2)
diff --git a/man/io_uring_register_iowq_max_workers.3 b/man/io_uring_register_iowq_max_workers.3
deleted file mode 100644
index 2557e216..00000000
--- a/man/io_uring_register_iowq_max_workers.3
+++ /dev/null
@@ -1,71 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_register_iowq_max_workers 3 "March 13, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_register_iowq_max_workers \- modify the maximum allowed async workers
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_register_iowq_max_workers(struct io_uring *" ring ","
-.BI " unsigned int *" values ");"
-.fi
-.SH DESCRIPTION
-.PP
-io_uring async workers are split into two types:
-.TP
-.B Bounded
-These workers have a bounded execution time. Examples of that are filesystem
-reads, which normally complete in a relatively short amount of time. In case
-of disk failures, they are still bounded by a timeout operation that will
-abort them if exceeded.
-.TP
-.B Unbounded
-Work items here may take an indefinite amount of time to complete. Examples
-include doing IO to sockets, pipes, or any other non-regular type of file.
-
-.PP
-By default, the amount of bounded IO workers is limited to how many SQ entries
-the ring was setup with, or 4 times the number of online CPUs in the system,
-whichever is smaller. Unbounded workers are only limited by the process task
-limit, as indicated by the rlimit
-.B RLIMIT_NPROC
-limit.
-
-This can be modified by calling
-.B io_uring_register_iowq_max_workers
-with
-.I ring
-set to the ring in question, and
-.I values
-pointing to an array of two values. The first element should contain the number
-of desired bounded workers, and the second element should contain the number
-of desired unbounded workers. These are both maximum values, io_uring will
-not maintain a high count of idle workers, they are reaped when they are not
-necessary anymore.
-
-If called with both values set to 0, the existing values are returned.
-
-.SH RETURN VALUE
-Returns
-.B 0
-on success, with
-.I values
-containing the previous values for the settings. On error, any of the following
-may be returned.
-.TP
-.B -EFAULT
-The kernel was unable to copy the memory pointer to by
-.I values
-as it was invalid.
-.TP
-.B -EINVAL
-.I values
-was
-.B NULL
-or the new values exceeded the maximum allowed value.
-.SH SEE ALSO
-.BR io_uring_queue_init (3),
-.BR io_uring_register (2)
diff --git a/man/io_uring_register_iowq_max_workers.3.md b/man/io_uring_register_iowq_max_workers.3.md
new file mode 100644
index 00000000..b0afb13b
--- /dev/null
+++ b/man/io_uring_register_iowq_max_workers.3.md
@@ -0,0 +1,77 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 13, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_register_iowq_max_workers
+---
+
+# NAME
+
+io_uring_register_iowq_max_workers - modify the maximum allowed async
+workers
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_register_iowq_max_workers(struct io_uring * ring ,
+ unsigned int * values );
+```
+
+# DESCRIPTION
+
+io_uring async workers are split into two types:
+
+**Bounded**
+
+: These workers have a bounded execution time. Examples of that are
+ filesystem reads, which normally complete in a relatively short amount
+ of time. In case of disk failures, they are still bounded by a timeout
+ operation that will abort them if exceeded.
+
+**Unbounded**
+
+: Work items here may take an indefinite amount of time to complete.
+ Examples include doing IO to sockets, pipes, or any other non-regular
+ type of file.
+
+By default, the amount of bounded IO workers is limited to how many SQ
+entries the ring was setup with, or 4 times the number of online CPUs in
+the system, whichever is smaller. Unbounded workers are only limited by
+the process task limit, as indicated by the rlimit **RLIMIT_NPROC**
+limit.
+
+This can be modified by calling **io_uring_register_iowq_max_workers**
+with *ring* set to the ring in question, and *values* pointing to an
+array of two values. The first element should contain the number of
+desired bounded workers, and the second element should contain the
+number of desired unbounded workers. These are both maximum values,
+io_uring will not maintain a high count of idle workers, they are reaped
+when they are not necessary anymore.
+
+If called with both values set to 0, the existing values are returned.
+
+# RETURN VALUE
+
+Returns **0** on success, with *values* containing the previous values
+for the settings. On error, any of the following may be returned.
+
+**-EFAULT**
+
+: The kernel was unable to copy the memory pointer to by *values* as it
+ was invalid.
+
+**-EINVAL**
+
+: *values* was **NULL** or the new values exceeded the maximum allowed
+ value.
+
+# SEE ALSO
+
+**io_uring_queue_init**(3), **io_uring_register**(2)
diff --git a/man/io_uring_register_napi.3 b/man/io_uring_register_napi.3
deleted file mode 100644
index 6ce8cfff..00000000
--- a/man/io_uring_register_napi.3
+++ /dev/null
@@ -1,40 +0,0 @@
-.\" Copyright (C) 2022 Stefan Roesch <shr@devkernel.io>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_register_napi 3 "November 16, 2022" "liburing-2.4" "liburing Manual"
-.SH NAME
-io_uring_register_napi \- register NAPI busy poll settings
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_register_napi(struct io_uring *" ring ","
-.BI " struct io_uring_napi *" napi)
-.PP
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_register_napi (3)
-function registers the NAPI settings for subsequent operations. The NAPI
-settings are specified in the structure that is passed in the
-.I napi
-parameter. The structure consists of the napi timeout
-.I busy_poll_to
-(napi busy poll timeout in us) and
-.IR prefer_busy_poll .
-
-Registering a NAPI settings sets the mode when calling the function
-napi_busy_loop and corresponds to the SO_PREFER_BUSY_POLL socket
-option.
-
-NAPI busy poll can reduce the network roundtrip time.
-
-
-.SH RETURN VALUE
-On success
-.BR io_uring_register_napi (3)
-return 0. On failure they return
-.BR -errno .
-It also updates the napi structure with the current values.
diff --git a/man/io_uring_register_napi.3.md b/man/io_uring_register_napi.3.md
new file mode 100644
index 00000000..d5dacc41
--- /dev/null
+++ b/man/io_uring_register_napi.3.md
@@ -0,0 +1,43 @@
+.\" Copyright (C) 2022 Stefan Roesch <shr@devkernel.io>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: November 16, 2022
+footer: liburing-2.4
+header: liburing Manual
+section: 3
+title: io_uring_register_napi
+---
+
+# NAME
+
+io_uring_register_napi - register NAPI busy poll settings
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_register_napi(struct io_uring * ring ,
+ struct io_uring_napi * napi)
+```
+
+# DESCRIPTION
+
+The **io_uring_register_napi**(3) function registers the NAPI settings
+for subsequent operations. The NAPI settings are specified in the
+structure that is passed in the *napi* parameter. The structure consists
+of the napi timeout *busy_poll_to* (napi busy poll timeout in us) and
+*prefer_busy_poll*.
+
+Registering a NAPI settings sets the mode when calling the function
+napi_busy_loop and corresponds to the SO_PREFER_BUSY_POLL socket option.
+
+NAPI busy poll can reduce the network roundtrip time.
+
+# RETURN VALUE
+
+On success **io_uring_register_napi**(3) return 0. On failure they
+return **-errno**. It also updates the napi structure with the current
+values.
diff --git a/man/io_uring_register_personality.3 b/man/io_uring_register_personality.3
deleted file mode 100644
index af3e1136..00000000
--- a/man/io_uring_register_personality.3
+++ /dev/null
@@ -1,34 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_register_personality 3 "January 18, 2025" "liburing-2.4" "liburing Manual"
-.SH NAME
-io_uring_register_personality \- register credentials with io_uring
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_register_personality(struct io_uring *" ring ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_register_personality (3)
-function registers the credentials of the calling application with the
-io_uring instance specified by
-.IR ring .
-This allows a ring to be shared between separate users or processes while
-maintaining credential separation.
-
-The returned personality ID can be used in the
-.I personality
-field of a submission queue entry to execute that request with the
-registered credentials.
-
-.SH RETURN VALUE
-Returns a positive personality ID on success that can be used in future
-operations. On error, a negative errno value is returned.
-.SH SEE ALSO
-.BR io_uring_unregister_personality (3),
-.BR io_uring_register (2)
diff --git a/man/io_uring_register_personality.3.md b/man/io_uring_register_personality.3.md
new file mode 100644
index 00000000..d3d2dd62
--- /dev/null
+++ b/man/io_uring_register_personality.3.md
@@ -0,0 +1,43 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 18, 2025
+footer: liburing-2.4
+header: liburing Manual
+section: 3
+title: io_uring_register_personality
+---
+
+# NAME
+
+io_uring_register_personality - register credentials with io_uring
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_register_personality(struct io_uring * ring );
+```
+
+# DESCRIPTION
+
+The **io_uring_register_personality**(3) function registers the
+credentials of the calling application with the io_uring instance
+specified by *ring*. This allows a ring to be shared between separate
+users or processes while maintaining credential separation.
+
+The returned personality ID can be used in the *personality* field of a
+submission queue entry to execute that request with the registered
+credentials.
+
+# RETURN VALUE
+
+Returns a positive personality ID on success that can be used in future
+operations. On error, a negative errno value is returned.
+
+# SEE ALSO
+
+**io_uring_unregister_personality**(3), **io_uring_register**(2)
diff --git a/man/io_uring_register_probe.3 b/man/io_uring_register_probe.3
deleted file mode 100644
index 587aa399..00000000
--- a/man/io_uring_register_probe.3
+++ /dev/null
@@ -1,47 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_register_probe 3 "January 18, 2025" "liburing-2.4" "liburing Manual"
-.SH NAME
-io_uring_register_probe \- register probe with io_uring
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_register_probe(struct io_uring *" ring ","
-.BI " struct io_uring_probe *" p ","
-.BI " unsigned " nr ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_register_probe (3)
-function queries the kernel for supported io_uring opcodes and fills in the
-probe structure
-.IR p .
-The
-.I ring
-argument specifies the io_uring instance to query, and
-.I nr
-specifies the maximum number of opcodes to query.
-
-The probe structure contains information about which opcodes are supported
-by the kernel. Applications can use
-.BR io_uring_opcode_supported (3)
-to check if a specific opcode is supported after calling this function.
-
-Most applications should use
-.BR io_uring_get_probe (3)
-or
-.BR io_uring_get_probe_ring (3)
-instead, which allocate and fill in the probe structure automatically.
-
-.SH RETURN VALUE
-Returns 0 on success. On error, a negative errno value is returned.
-.SH SEE ALSO
-.BR io_uring_get_probe (3),
-.BR io_uring_get_probe_ring (3),
-.BR io_uring_opcode_supported (3),
-.BR io_uring_free_probe (3),
-.BR io_uring_register (2)
diff --git a/man/io_uring_register_probe.3.md b/man/io_uring_register_probe.3.md
new file mode 100644
index 00000000..a7a17e17
--- /dev/null
+++ b/man/io_uring_register_probe.3.md
@@ -0,0 +1,51 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 18, 2025
+footer: liburing-2.4
+header: liburing Manual
+section: 3
+title: io_uring_register_probe
+---
+
+# NAME
+
+io_uring_register_probe - register probe with io_uring
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_register_probe(struct io_uring * ring ,
+ struct io_uring_probe * p ,
+ unsigned nr );
+```
+
+# DESCRIPTION
+
+The **io_uring_register_probe**(3) function queries the kernel for
+supported io_uring opcodes and fills in the probe structure *p*. The
+*ring* argument specifies the io_uring instance to query, and *nr*
+specifies the maximum number of opcodes to query.
+
+The probe structure contains information about which opcodes are
+supported by the kernel. Applications can use
+**io_uring_opcode_supported**(3) to check if a specific opcode is
+supported after calling this function.
+
+Most applications should use **io_uring_get_probe**(3) or
+**io_uring_get_probe_ring**(3) instead, which allocate and fill in the
+probe structure automatically.
+
+# RETURN VALUE
+
+Returns 0 on success. On error, a negative errno value is returned.
+
+# SEE ALSO
+
+**io_uring_get_probe**(3), **io_uring_get_probe_ring**(3),
+**io_uring_opcode_supported**(3), **io_uring_free_probe**(3),
+**io_uring_register**(2)
diff --git a/man/io_uring_register_query.3 b/man/io_uring_register_query.3
deleted file mode 100644
index e731910d..00000000
--- a/man/io_uring_register_query.3
+++ /dev/null
@@ -1,114 +0,0 @@
-.\" Copyright (C) 2026 Yitang Yang <yi1tang.yang@gmail.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_register_query 3 "March 26, 2026" "liburing-2.15" "liburing Manual"
-.SH NAME
-io_uring_register_query \- query io_uring capabilities and feature support
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_register_query(struct io_uring_query_hdr *" query ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_register_query (3)
-function queries io_uring capabilities and feature support. It provides
-information about supported opcodes, flags, and subsystem-specific
-capabilities.
-
-The
-.I query
-argument must point to a
-.I struct io_uring_query_hdr
-structure that describes the query to perform:
-
-.PP
-.in +4n
-.EX
-struct io_uring_query_hdr {
- __u64 next_entry;
- __u64 query_data;
- __u32 query_op;
- __u32 size;
- __s32 result;
- __u32 __resv[3];
-};
-.EE
-.in
-.PP
-
-The
-.I next_entry
-field can be used to chain multiple queries together. It should point to the
-next
-.I struct io_uring_query_hdr
-structure, or be set to 0 for the last entry in the chain.
-
-The
-.I query_data
-field must point to a data structure appropriate for the query type specified in
-.IR query_op .
-
-The
-.I query_op
-field specifies the type of query to perform and can be one of:
-
-.TP
-.B IO_URING_QUERY_OPCODES
-Returns information about supported opcodes and flags. The
-.I query_data
-field must point to a
-.I struct io_uring_query_opcode
-structure, which will be filled with information about supported request
-opcodes, register opcodes, feature flags, setup flags, enter flags, and SQE
-flags.
-
-.TP
-.B IO_URING_QUERY_ZCRX
-Returns information about zero-copy receive support. The
-.I query_data
-field must point to a
-.I struct io_uring_query_zcrx
-structure, which will be filled with information about supported zero-copy
-receive flags, features, and configuration details.
-
-.TP
-.B IO_URING_QUERY_SCQ
-Returns information about the SQ/CQ ring layout. The
-.I query_data
-field must point to a
-.I struct io_uring_query_scq
-structure, which will be filled with information about ring header size and
-alignment requirements.
-
-.PP
-The
-.I size
-field should be set to the size of the data structure pointed to by
-.IR query_data .
-
-Upon return, the
-.I result
-field will contain 0 on success, or a negative error code on failure.
-
-The reserved
-.I __resv
-fields must be cleared to zero.
-
-.SH RETURN VALUE
-Returns 0 on success. On error, a negative errno value is returned.
-
-.SH NOTES
-This function is available since Linux kernel 6.15.
-
-Multiple queries can be efficiently performed in a single system call by
-chaining them together using the
-.I next_entry
-field.
-
-.SH SEE ALSO
-.BR io_uring_register (2),
-.BR io_uring_setup (2)
diff --git a/man/io_uring_register_query.3.md b/man/io_uring_register_query.3.md
new file mode 100644
index 00000000..601b35fd
--- /dev/null
+++ b/man/io_uring_register_query.3.md
@@ -0,0 +1,99 @@
+.\" Copyright (C) 2026 Yitang Yang <yi1tang.yang@gmail.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 26, 2026
+footer: liburing-2.15
+header: liburing Manual
+section: 3
+title: io_uring_register_query
+---
+
+# NAME
+
+io_uring_register_query - query io_uring capabilities and feature
+support
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_register_query(struct io_uring_query_hdr * query );
+```
+
+# DESCRIPTION
+
+The **io_uring_register_query**(3) function queries io_uring
+capabilities and feature support. It provides information about
+supported opcodes, flags, and subsystem-specific capabilities.
+
+The *query* argument must point to a *struct io_uring_query_hdr*
+structure that describes the query to perform:
+
+``` text
+struct io_uring_query_hdr {
+ __u64 next_entry;
+ __u64 query_data;
+ __u32 query_op;
+ __u32 size;
+ __s32 result;
+ __u32 __resv[3];
+};
+```
+
+The *next_entry* field can be used to chain multiple queries together.
+It should point to the next *struct io_uring_query_hdr* structure, or be
+set to 0 for the last entry in the chain.
+
+The *query_data* field must point to a data structure appropriate for
+the query type specified in *query_op*.
+
+The *query_op* field specifies the type of query to perform and can be
+one of:
+
+**IO_URING_QUERY_OPCODES**
+
+: Returns information about supported opcodes and flags. The
+ *query_data* field must point to a *struct io_uring_query_opcode*
+ structure, which will be filled with information about supported
+ request opcodes, register opcodes, feature flags, setup flags, enter
+ flags, and SQE flags.
+
+**IO_URING_QUERY_ZCRX**
+
+: Returns information about zero-copy receive support. The *query_data*
+ field must point to a *struct io_uring_query_zcrx* structure, which
+ will be filled with information about supported zero-copy receive
+ flags, features, and configuration details.
+
+**IO_URING_QUERY_SCQ**
+
+: Returns information about the SQ/CQ ring layout. The *query_data*
+ field must point to a *struct io_uring_query_scq* structure, which
+ will be filled with information about ring header size and alignment
+ requirements.
+
+The *size* field should be set to the size of the data structure pointed
+to by *query_data*.
+
+Upon return, the *result* field will contain 0 on success, or a negative
+error code on failure.
+
+The reserved *\_\_resv* fields must be cleared to zero.
+
+# RETURN VALUE
+
+Returns 0 on success. On error, a negative errno value is returned.
+
+# NOTES
+
+This function is available since Linux kernel 6.15.
+
+Multiple queries can be efficiently performed in a single system call by
+chaining them together using the *next_entry* field.
+
+# SEE ALSO
+
+**io_uring_register**(2), **io_uring_setup**(2)
diff --git a/man/io_uring_register_region.3 b/man/io_uring_register_region.3
deleted file mode 100644
index 43a47766..00000000
--- a/man/io_uring_register_region.3
+++ /dev/null
@@ -1,124 +0,0 @@
-.\" Copyright (C) 2026 Pavel Begunkov <asml.silence@gmail.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_register_region 3 "Jan 13, 2026" "liburing-2.14" "liburing Manual"
-.SH NAME
-io_uring_register_region \- register a memory region
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_register_region(struct io_uring *" ring ",
-.BI " struct io_uring_mem_region_reg *" reg ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_register_region (3)
-function registers a memory region to io_uring. Upon successful completion, the
-memory region may then be used, for example, to pass waiting parameters to the
-.BR io_uring_enter (2)
-system call in a more efficient manner as it avoids copying wait related data
-for each wait event. The
-.IR ring
-argument should point to the ring in question, and the
-.IR reg
-argument should be a pointer to a
-.B struct io_uring_mem_region_reg .
-
-The
-.IR reg
-argument must be filled in with the appropriate information. It looks as
-follows:
-.PP
-.in +4n
-.EX
-struct io_uring_mem_region_reg {
- __u64 region_uptr;
- __u64 flags;
- __u64 __resv[2];
-};
-.EE
-.in
-.PP
-The
-.I region_uptr
-field must contain a pointer to an appropriately filled
-.B struct io_uring_region_desc.
-.PP
-The
-.I flags
-field must contain a bitmask of the following values:
-.TP
-.B IORING_MEM_REGION_REG_WAIT_ARG
-allows use of the region to pass waiting parameters to the
-.BR io_uring_enter (2)
-system call. If set, the registration is only allowed while the ring
-is in a disabled mode. See
-.B IORING_SETUP_R_DISABLED.
-.PP
-The __resv fields must be filled with zeroes.
-
-.PP
-.B struct io_uring_region_desc
-is defined as following:
-.PP
-.in +4n
-.EX
-struct io_uring_region_desc {
- __u64 user_addr;
- __u64 size;
- __u32 flags;
- __u32 id;
- __u64 mmap_offset;
- __u64 __resv[4];
-};
-.EE
-.in
-
-.PP
-The
-.I user_addr
-field must contain a pointer to the memory the user wants to register. It's
-valid only if
-.B IORING_MEM_REGION_TYPE_USER
-is set, and should be zero otherwise.
-
-.PP
-The
-.I size
-field should contain the size of the region.
-
-The
-.I flags
-field must contain a bitmask of the following values:
-.TP
-.B IORING_MEM_REGION_TYPE_USER
-tells the kernel to use memory specified by the
-.I user_addr
-field. If not set, the kernel will allocate memory for the region, which can
-then be mapped into the user space.
-
-.PP
-On successful registration of a region with kernel provided memory, the
-.I mmap_offset
-field will contain an offset that can be passed to the
-.B mmap(2)
-system call to map the region into the user space.
-
-The
-.I id
-field is reserved and must be set to zero.
-
-The
-.I __resv
-fields must be filled with zeroes.
-
-Available since kernel 6.13.
-
-.SH RETURN VALUE
-On success
-.BR io_uring_register_region (3)
-returns 0. On failure it returns
-.BR -errno .
diff --git a/man/io_uring_register_region.3.md b/man/io_uring_register_region.3.md
new file mode 100644
index 00000000..f59ea473
--- /dev/null
+++ b/man/io_uring_register_region.3.md
@@ -0,0 +1,101 @@
+.\" Copyright (C) 2026 Pavel Begunkov <asml.silence@gmail.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: Jan 13, 2026
+footer: liburing-2.14
+header: liburing Manual
+section: 3
+title: io_uring_register_region
+---
+
+# NAME
+
+io_uring_register_region - register a memory region
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_register_region(struct io_uring * ring ,
+ struct io_uring_mem_region_reg * reg );
+```
+
+# DESCRIPTION
+
+The **io_uring_register_region**(3) function registers a memory region
+to io_uring. Upon successful completion, the memory region may then be
+used, for example, to pass waiting parameters to the
+**io_uring_enter**(2) system call in a more efficient manner as it
+avoids copying wait related data for each wait event. The *ring*
+argument should point to the ring in question, and the *reg* argument
+should be a pointer to a **struct io_uring_mem_region_reg .**
+
+The *reg* argument must be filled in with the appropriate information.
+It looks as follows:
+
+``` text
+struct io_uring_mem_region_reg {
+ __u64 region_uptr;
+ __u64 flags;
+ __u64 __resv[2];
+};
+```
+
+The *region_uptr* field must contain a pointer to an appropriately
+filled **struct io_uring_region_desc.**
+
+The *flags* field must contain a bitmask of the following values:
+
+**IORING_MEM_REGION_REG_WAIT_ARG**
+
+: allows use of the region to pass waiting parameters to the
+ **io_uring_enter**(2) system call. If set, the registration is only
+ allowed while the ring is in a disabled mode. See
+ **IORING_SETUP_R_DISABLED.**
+
+The \_\_resv fields must be filled with zeroes.
+
+**struct io_uring_region_desc** is defined as following:
+
+``` text
+struct io_uring_region_desc {
+ __u64 user_addr;
+ __u64 size;
+ __u32 flags;
+ __u32 id;
+ __u64 mmap_offset;
+ __u64 __resv[4];
+};
+```
+
+The *user_addr* field must contain a pointer to the memory the user
+wants to register. It\'s valid only if **IORING_MEM_REGION_TYPE_USER**
+is set, and should be zero otherwise.
+
+The *size* field should contain the size of the region.
+
+The *flags* field must contain a bitmask of the following values:
+
+**IORING_MEM_REGION_TYPE_USER**
+
+: tells the kernel to use memory specified by the *user_addr* field. If
+ not set, the kernel will allocate memory for the region, which can
+ then be mapped into the user space.
+
+On successful registration of a region with kernel provided memory, the
+*mmap_offset* field will contain an offset that can be passed to the
+**mmap(2)** system call to map the region into the user space.
+
+The *id* field is reserved and must be set to zero.
+
+The *\_\_resv* fields must be filled with zeroes.
+
+Available since kernel 6.13.
+
+# RETURN VALUE
+
+On success **io_uring_register_region**(3) returns 0. On failure it
+returns **-errno**.
diff --git a/man/io_uring_register_restrictions.3 b/man/io_uring_register_restrictions.3
deleted file mode 100644
index d99bf881..00000000
--- a/man/io_uring_register_restrictions.3
+++ /dev/null
@@ -1,53 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_register_restrictions 3 "January 18, 2025" "liburing-2.4" "liburing Manual"
-.SH NAME
-io_uring_register_restrictions \- register restrictions with io_uring
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_register_restrictions(struct io_uring *" ring ","
-.BI " struct io_uring_restriction *" res ","
-.BI " unsigned int " nr_res ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_register_restrictions (3)
-function registers restrictions with the io_uring instance specified by
-.IR ring .
-The
-.I res
-argument is a pointer to an array of
-.I struct io_uring_restriction
-of
-.I nr_res
-entries.
-
-Restrictions allow limiting which opcodes, register operations, or SQE flags
-are allowed on a ring. This can be used to sandbox io_uring usage.
-
-Restrictions can only be registered if the io_uring ring was started in a
-disabled state (with
-.B IORING_SETUP_R_DISABLED
-specified in the call to
-.BR io_uring_setup (2)).
-All restrictions must be registered in a single call before enabling the
-ring with
-.BR io_uring_enable_rings (3).
-
-See
-.BR io_uring_register (2)
-for a description of the
-.B IORING_REGISTER_RESTRICTIONS
-operation and the restriction structure.
-
-.SH RETURN VALUE
-Returns 0 on success. On error, a negative errno value is returned.
-.SH SEE ALSO
-.BR io_uring_enable_rings (3),
-.BR io_uring_register (2),
-.BR io_uring_setup (2)
diff --git a/man/io_uring_register_restrictions.3.md b/man/io_uring_register_restrictions.3.md
new file mode 100644
index 00000000..9a3d46ea
--- /dev/null
+++ b/man/io_uring_register_restrictions.3.md
@@ -0,0 +1,53 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 18, 2025
+footer: liburing-2.4
+header: liburing Manual
+section: 3
+title: io_uring_register_restrictions
+---
+
+# NAME
+
+io_uring_register_restrictions - register restrictions with io_uring
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_register_restrictions(struct io_uring * ring ,
+ struct io_uring_restriction * res ,
+ unsigned int nr_res );
+```
+
+# DESCRIPTION
+
+The **io_uring_register_restrictions**(3) function registers
+restrictions with the io_uring instance specified by *ring*. The *res*
+argument is a pointer to an array of *struct io_uring_restriction* of
+*nr_res* entries.
+
+Restrictions allow limiting which opcodes, register operations, or SQE
+flags are allowed on a ring. This can be used to sandbox io_uring usage.
+
+Restrictions can only be registered if the io_uring ring was started in
+a disabled state (with **IORING_SETUP_R_DISABLED** specified in the call
+to **io_uring_setup**(2)). All restrictions must be registered in a
+single call before enabling the ring with **io_uring_enable_rings**(3).
+
+See **io_uring_register**(2) for a description of the
+**IORING_REGISTER_RESTRICTIONS** operation and the restriction
+structure.
+
+# RETURN VALUE
+
+Returns 0 on success. On error, a negative errno value is returned.
+
+# SEE ALSO
+
+**io_uring_enable_rings**(3), **io_uring_register**(2),
+**io_uring_setup**(2)
diff --git a/man/io_uring_register_ring_fd.3 b/man/io_uring_register_ring_fd.3
deleted file mode 100644
index 0284fe41..00000000
--- a/man/io_uring_register_ring_fd.3
+++ /dev/null
@@ -1,51 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_register_ring_fd 3 "March 11, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_register_ring_fd \- register a ring file descriptor
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_register_ring_fd(struct io_uring *" ring ");"
-.fi
-.SH DESCRIPTION
-.PP
-.BR io_uring_register_ring_fd (3)
-registers the file descriptor of the ring.
-
-Whenever
-.BR io_uring_enter (2)
-is called to submit request or wait for completions, the kernel must grab a
-reference to the file descriptor. If the application using io_uring is threaded,
-the file table is marked as shared, and the reference grab and put of the file
-descriptor count is more expensive than it is for a non-threaded application.
-
-Similarly to how io_uring allows registration of files, this allow registration
-of the ring file descriptor itself. This reduces the overhead of the
-.BR io_uring_enter (2)
-system call.
-
-If an application using liburing is threaded, then an application should call
-this function to register the ring descriptor when a ring is set up. See NOTES
-for restrictions when a ring is shared.
-
-Available since kernel 5.18.
-
-.SH NOTES
-When the ring descriptor is registered, it is stored internally in the
-.I struct io_uring
-structure. For applications that share a ring between threads, for example
-having one thread do submits and another reap events, then this optimization
-cannot be used as each thread may have a different index for the registered
-ring fd.
-.SH RETURN VALUE
-Returns 1 on success, indicating that one file descriptor was registered,
-or
-.BR -errno
-on error.
-.SH SEE ALSO
-.BR io_uring_unregister_ring_fd (3),
-.BR io_uring_register_files (3)
diff --git a/man/io_uring_register_ring_fd.3.md b/man/io_uring_register_ring_fd.3.md
new file mode 100644
index 00000000..5a769e48
--- /dev/null
+++ b/man/io_uring_register_ring_fd.3.md
@@ -0,0 +1,61 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 11, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_register_ring_fd
+---
+
+# NAME
+
+io_uring_register_ring_fd - register a ring file descriptor
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_register_ring_fd(struct io_uring * ring );
+```
+
+# DESCRIPTION
+
+**io_uring_register_ring_fd**(3) registers the file descriptor of the
+ring.
+
+Whenever **io_uring_enter**(2) is called to submit request or wait for
+completions, the kernel must grab a reference to the file descriptor. If
+the application using io_uring is threaded, the file table is marked as
+shared, and the reference grab and put of the file descriptor count is
+more expensive than it is for a non-threaded application.
+
+Similarly to how io_uring allows registration of files, this allow
+registration of the ring file descriptor itself. This reduces the
+overhead of the **io_uring_enter**(2) system call.
+
+If an application using liburing is threaded, then an application should
+call this function to register the ring descriptor when a ring is set
+up. See NOTES for restrictions when a ring is shared.
+
+Available since kernel 5.18.
+
+# NOTES
+
+When the ring descriptor is registered, it is stored internally in the
+*struct io_uring* structure. For applications that share a ring between
+threads, for example having one thread do submits and another reap
+events, then this optimization cannot be used as each thread may have a
+different index for the registered ring fd.
+
+# RETURN VALUE
+
+Returns 1 on success, indicating that one file descriptor was
+registered, or **-errno** on error.
+
+# SEE ALSO
+
+**io_uring_unregister_ring_fd**(3), **io_uring_register_files**(3)
diff --git a/man/io_uring_register_sync_cancel.3 b/man/io_uring_register_sync_cancel.3
deleted file mode 100644
index 449bc0ff..00000000
--- a/man/io_uring_register_sync_cancel.3
+++ /dev/null
@@ -1,73 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_register_sync_cancel 3 "September 21, 2022" "liburing-2.3" "liburing Manual"
-.SH NAME
-io_uring_register_sync_cancel \- issue a synchronous cancelation request
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_register_sync_cancel(struct io_uring *" ring ",
-.BI " struct io_uring_sync_cancel_reg *" reg ");
-.PP
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_register_sync_cancel (3)
-function performs a synchronous cancelation request based on the parameters
-specified in
-.I reg .
-
-The
-.I reg
-argument must be filled in with the appropriate information for the
-cancelation request. It looks as follows:
-.PP
-.in +4n
-.EX
-struct io_uring_sync_cancel_reg {
- __u64 addr;
- __s32 fd;
- __u32 flags;
- struct __kernel_timespec timeout;
- __u8 opcode;
- __u8 pad[7];
- __u64 pad2[3];
-};
-.EE
-.in
-.PP
-
-The arguments largely mirror what the async prep functions support, see
-.BR io_uring_prep_cancel (3)
-for details. Similarly, the return value is the same. The exception is the
-.I timeout
-argument, which can be used to limit the time that the kernel will wait for
-cancelations to be successful. If the
-.I tv_sec
-and
-.I tv_nsec
-values are set to anything but
-.B -1UL ,
-then they indicate a relative timeout upon which cancelations should be
-completed by.
-
-The
-.I pad
-values must be zero filled.
-
-.SH RETURN VALUE
-See
-.BR io_uring_prep_cancel (3)
-for details on the return value. If
-.I timeout
-is set to indicate a timeout, then
-.B -ETIME
-will be returned if exceeded. If an unknown value is set in the request,
-or if the pad values are not cleared to zero, then
-.I -EINVAL
-is returned.
-.SH SEE ALSO
-.BR io_uring_prep_cancel (3)
diff --git a/man/io_uring_register_sync_cancel.3.md b/man/io_uring_register_sync_cancel.3.md
new file mode 100644
index 00000000..74d44c0a
--- /dev/null
+++ b/man/io_uring_register_sync_cancel.3.md
@@ -0,0 +1,65 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: September 21, 2022
+footer: liburing-2.3
+header: liburing Manual
+section: 3
+title: io_uring_register_sync_cancel
+---
+
+# NAME
+
+io_uring_register_sync_cancel - issue a synchronous cancelation request
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_register_sync_cancel(struct io_uring * ring ,
+ struct io_uring_sync_cancel_reg * reg );
+```
+
+# DESCRIPTION
+
+The **io_uring_register_sync_cancel**(3) function performs a synchronous
+cancelation request based on the parameters specified in *reg .*
+
+The *reg* argument must be filled in with the appropriate information
+for the cancelation request. It looks as follows:
+
+``` text
+struct io_uring_sync_cancel_reg {
+ __u64 addr;
+ __s32 fd;
+ __u32 flags;
+ struct __kernel_timespec timeout;
+ __u8 opcode;
+ __u8 pad[7];
+ __u64 pad2[3];
+};
+```
+
+The arguments largely mirror what the async prep functions support, see
+**io_uring_prep_cancel**(3) for details. Similarly, the return value is
+the same. The exception is the *timeout* argument, which can be used to
+limit the time that the kernel will wait for cancelations to be
+successful. If the *tv_sec* and *tv_nsec* values are set to anything but
+**-1UL ,** then they indicate a relative timeout upon which cancelations
+should be completed by.
+
+The *pad* values must be zero filled.
+
+# RETURN VALUE
+
+See **io_uring_prep_cancel**(3) for details on the return value. If
+*timeout* is set to indicate a timeout, then **-ETIME** will be returned
+if exceeded. If an unknown value is set in the request, or if the pad
+values are not cleared to zero, then *-EINVAL* is returned.
+
+# SEE ALSO
+
+**io_uring_prep_cancel**(3)
diff --git a/man/io_uring_register_sync_msg.3 b/man/io_uring_register_sync_msg.3
deleted file mode 100644
index bef56814..00000000
--- a/man/io_uring_register_sync_msg.3
+++ /dev/null
@@ -1,74 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_register_sync_msg 3 "July 10, 2025" "liburing-2.11" "liburing Manual"
-.SH NAME
-io_uring_register_sync_msg \- send a synchronous message to another ring
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_register_sync_msg(struct io_uring_sqe *" sqe ");"
-.fi
-.SH DESCRIPTION
-.PP
-.BR io_uring_register_sync_msg (3)
-issues a synchronous MSG_RING request. The
-.I sqe
-parameter must have been cleared and initialized with
-.BR io_uring_prep_msg_ring (3) .
-
-Normally message requests are sent from one ring to another ring. But there
-are also cases where a source ring is not available, yet it would be
-convenient to send a message to a destination ring.
-.BR io_uring_register_sync_msg (3)
-exists for that purpose. A source ring is not required to send a message to
-another ring, instead the
-.I sqe
-parameter can be placed on the stack and filled in using the normal message
-helpers, and then
-.BR io_uring_register_sync_msg (3)
-can be called. Since a source ring does not exist, the results of the operation
-is returned directly rather than via a CQE. On the destination/receiving end,
-a CQE is posted, as it would have been with a non-sync request.
-
-Only data request are supported, sending files such as setup by
-.BR io_uring_prep_msg_ring_fd (3)
-is not supported. The given SQE should be initialized by
-.BR io_uring_prep_msg_ring (3)
-or
-.BR io_uring_prep_msg_ring_cqe_flags (3) ,
-or any other helper that sets up a non-fd message request.
-
-The targeted ring may be any ring that the user has access to, even the ring
-itself. This request can be used for simple message passing to another ring,
-allowing 32+64 bits of data to be transferred through the
-.I len
-and
-.I data
-fields. The use case may be anything from simply waking up someone waiting
-on the targeted ring, or it can be used to pass messages between the two
-rings.
-
-.BR io_uring_prep_msg_ring_cqe_flags (3)
-is similar to
-.BR io_uring_prep_msg_ring (3) .
-But has an addition
-.I cqe_flags
-parameter, which is used to set
-.I flags
-field on CQE side. That way, you can set the CQE flags field
-.I cqe->flags
-when sending a message. Be aware that io_uring could potentially set additional
-bits into this field.
-
-Available since kernel 6.13.
-
-.SH RETURN VALUE
-Returns 0 on success, or
-.BR -errno
-on error.
-.SH SEE ALSO
-.BR io_uring_prep_msg_ring_cqe_flags (3) ,
-.BR io_uring_prep_msg_ring (3)
diff --git a/man/io_uring_register_sync_msg.3.md b/man/io_uring_register_sync_msg.3.md
new file mode 100644
index 00000000..10b65486
--- /dev/null
+++ b/man/io_uring_register_sync_msg.3.md
@@ -0,0 +1,71 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: July 10, 2025
+footer: liburing-2.11
+header: liburing Manual
+section: 3
+title: io_uring_register_sync_msg
+---
+
+# NAME
+
+io_uring_register_sync_msg - send a synchronous message to another ring
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_register_sync_msg(struct io_uring_sqe * sqe );
+```
+
+# DESCRIPTION
+
+**io_uring_register_sync_msg**(3) issues a synchronous MSG_RING request.
+The *sqe* parameter must have been cleared and initialized with
+**io_uring_prep_msg_ring**(3)**.**
+
+Normally message requests are sent from one ring to another ring. But
+there are also cases where a source ring is not available, yet it would
+be convenient to send a message to a destination ring.
+**io_uring_register_sync_msg**(3) exists for that purpose. A source ring
+is not required to send a message to another ring, instead the *sqe*
+parameter can be placed on the stack and filled in using the normal
+message helpers, and then **io_uring_register_sync_msg**(3) can be
+called. Since a source ring does not exist, the results of the operation
+is returned directly rather than via a CQE. On the destination/receiving
+end, a CQE is posted, as it would have been with a non-sync request.
+
+Only data request are supported, sending files such as setup by
+**io_uring_prep_msg_ring_fd**(3) is not supported. The given SQE should
+be initialized by **io_uring_prep_msg_ring**(3) or
+**io_uring_prep_msg_ring_cqe_flags**(3)**,** or any other helper that
+sets up a non-fd message request.
+
+The targeted ring may be any ring that the user has access to, even the
+ring itself. This request can be used for simple message passing to
+another ring, allowing 32+64 bits of data to be transferred through the
+*len* and *data* fields. The use case may be anything from simply waking
+up someone waiting on the targeted ring, or it can be used to pass
+messages between the two rings.
+
+**io_uring_prep_msg_ring_cqe_flags**(3) is similar to
+**io_uring_prep_msg_ring**(3)**.** But has an addition *cqe_flags*
+parameter, which is used to set *flags* field on CQE side. That way, you
+can set the CQE flags field *cqe-\>flags* when sending a message. Be
+aware that io_uring could potentially set additional bits into this
+field.
+
+Available since kernel 6.13.
+
+# RETURN VALUE
+
+Returns 0 on success, or **-errno** on error.
+
+# SEE ALSO
+
+**io_uring_prep_msg_ring_cqe_flags**(3)**,**
+**io_uring_prep_msg_ring**(3)
diff --git a/man/io_uring_register_wait_reg.3 b/man/io_uring_register_wait_reg.3
deleted file mode 100644
index 122f00f0..00000000
--- a/man/io_uring_register_wait_reg.3
+++ /dev/null
@@ -1,45 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_register_wait_reg 3 "January 18, 2025" "liburing-2.9" "liburing Manual"
-.SH NAME
-io_uring_register_wait_reg \- register wait regions with io_uring
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_register_wait_reg(struct io_uring *" ring ","
-.BI " struct io_uring_reg_wait *" reg ","
-.BI " int " nr ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_register_wait_reg (3)
-function registers wait regions with the io_uring instance specified by
-.IR ring .
-The
-.I reg
-argument is a pointer to an array of
-.I struct io_uring_reg_wait
-of
-.I nr
-entries.
-
-Wait regions allow registering timeout and signal mask information that can
-be reused across multiple wait operations without copying the data for each
-call. This is used in conjunction with
-.BR io_uring_submit_and_wait_reg (3)
-to reduce the overhead of wait operations.
-
-See
-.BR io_uring_register_region (3)
-for registering the underlying memory region.
-
-.SH RETURN VALUE
-Returns 0 on success. On error, a negative errno value is returned.
-.SH SEE ALSO
-.BR io_uring_submit_and_wait_reg (3),
-.BR io_uring_register_region (3),
-.BR io_uring_register (2)
diff --git a/man/io_uring_register_wait_reg.3.md b/man/io_uring_register_wait_reg.3.md
new file mode 100644
index 00000000..d4a68c6e
--- /dev/null
+++ b/man/io_uring_register_wait_reg.3.md
@@ -0,0 +1,49 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 18, 2025
+footer: liburing-2.9
+header: liburing Manual
+section: 3
+title: io_uring_register_wait_reg
+---
+
+# NAME
+
+io_uring_register_wait_reg - register wait regions with io_uring
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_register_wait_reg(struct io_uring * ring ,
+ struct io_uring_reg_wait * reg ,
+ int nr );
+```
+
+# DESCRIPTION
+
+The **io_uring_register_wait_reg**(3) function registers wait regions
+with the io_uring instance specified by *ring*. The *reg* argument is a
+pointer to an array of *struct io_uring_reg_wait* of *nr* entries.
+
+Wait regions allow registering timeout and signal mask information that
+can be reused across multiple wait operations without copying the data
+for each call. This is used in conjunction with
+**io_uring_submit_and_wait_reg**(3) to reduce the overhead of wait
+operations.
+
+See **io_uring_register_region**(3) for registering the underlying
+memory region.
+
+# RETURN VALUE
+
+Returns 0 on success. On error, a negative errno value is returned.
+
+# SEE ALSO
+
+**io_uring_submit_and_wait_reg**(3), **io_uring_register_region**(3),
+**io_uring_register**(2)
diff --git a/man/io_uring_register_zcrx_ctrl.3 b/man/io_uring_register_zcrx_ctrl.3
deleted file mode 100644
index 64e3a913..00000000
--- a/man/io_uring_register_zcrx_ctrl.3
+++ /dev/null
@@ -1,84 +0,0 @@
-.\" Copyright (C) 2026 Yitang Yang <yi1tang.yang@gmail.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_register_zcrx_ctrl 3 "March 26, 2026" "liburing-2.15" "liburing Manual"
-.SH NAME
-io_uring_register_zcrx_ctrl \- perform control operations on a zero-copy receive context
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_register_zcrx_ctrl(struct io_uring *" ring ","
-.BI " struct zcrx_ctrl *" ctrl ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_register_zcrx_ctrl (3)
-function performs control operations on a previously registered zero-copy
-receive context. See
-.BR io_uring_register_ifq (3)
-for details on registering a zero-copy receive context.
-
-The
-.I ctrl
-argument must point to a
-.I struct zcrx_ctrl
-structure that describes the control operation to perform:
-
-.PP
-.in +4n
-.EX
-struct zcrx_ctrl {
- __u32 zcrx_id;
- __u32 op;
- __u64 __resv[2];
- union {
- struct zcrx_ctrl_export zc_export;
- struct zcrx_ctrl_flush_rq zc_flush;
- };
-};
-.EE
-.in
-.PP
-
-The
-.I zcrx_id
-field must be set to the ID of the zero-copy receive context returned from
-.BR io_uring_register_ifq (3).
-The
-.I op
-field specifies the control operation to perform and can be one of:
-
-.TP
-.B ZCRX_CTRL_FLUSH_RQ
-Flushes pending buffers from the refill queue. Uses the
-.I zc_flush
-member of the union.
-
-.TP
-.B ZCRX_CTRL_EXPORT
-Exports the zero-copy receive context for use by other rings. Uses the
-.I zc_export
-member of the union. Upon successful export, the
-.I zcrx_fd
-field in
-.I zc_export
-will contain the file descriptor that can be used to share this context
-with other io_uring instances.
-
-.PP
-The reserved
-.I __resv
-fields must be cleared to zero.
-
-.SH RETURN VALUE
-Returns 0 on success. On error, a negative errno value is returned.
-
-.SH NOTES
-This function is available since Linux kernel 6.15.
-
-.SH SEE ALSO
-.BR io_uring_register (2),
-.BR io_uring_register_ifq (3)
diff --git a/man/io_uring_register_zcrx_ctrl.3.md b/man/io_uring_register_zcrx_ctrl.3.md
new file mode 100644
index 00000000..8cb64a1c
--- /dev/null
+++ b/man/io_uring_register_zcrx_ctrl.3.md
@@ -0,0 +1,77 @@
+.\" Copyright (C) 2026 Yitang Yang <yi1tang.yang@gmail.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 26, 2026
+footer: liburing-2.15
+header: liburing Manual
+section: 3
+title: io_uring_register_zcrx_ctrl
+---
+
+# NAME
+
+io_uring_register_zcrx_ctrl - perform control operations on a zero-copy
+receive context
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_register_zcrx_ctrl(struct io_uring * ring ,
+ struct zcrx_ctrl * ctrl );
+```
+
+# DESCRIPTION
+
+The **io_uring_register_zcrx_ctrl**(3) function performs control
+operations on a previously registered zero-copy receive context. See
+**io_uring_register_ifq**(3) for details on registering a zero-copy
+receive context.
+
+The *ctrl* argument must point to a *struct zcrx_ctrl* structure that
+describes the control operation to perform:
+
+``` text
+struct zcrx_ctrl {
+ __u32 zcrx_id;
+ __u32 op;
+ __u64 __resv[2];
+ union {
+ struct zcrx_ctrl_export zc_export;
+ struct zcrx_ctrl_flush_rq zc_flush;
+ };
+};
+```
+
+The *zcrx_id* field must be set to the ID of the zero-copy receive
+context returned from **io_uring_register_ifq**(3). The *op* field
+specifies the control operation to perform and can be one of:
+
+**ZCRX_CTRL_FLUSH_RQ**
+
+: Flushes pending buffers from the refill queue. Uses the *zc_flush*
+ member of the union.
+
+**ZCRX_CTRL_EXPORT**
+
+: Exports the zero-copy receive context for use by other rings. Uses the
+ *zc_export* member of the union. Upon successful export, the *zcrx_fd*
+ field in *zc_export* will contain the file descriptor that can be used
+ to share this context with other io_uring instances.
+
+The reserved *\_\_resv* fields must be cleared to zero.
+
+# RETURN VALUE
+
+Returns 0 on success. On error, a negative errno value is returned.
+
+# NOTES
+
+This function is available since Linux kernel 6.15.
+
+# SEE ALSO
+
+**io_uring_register**(2), **io_uring_register_ifq**(3)
diff --git a/man/io_uring_registered_buffers.7 b/man/io_uring_registered_buffers.7
deleted file mode 100644
index a76ae7e5..00000000
--- a/man/io_uring_registered_buffers.7
+++ /dev/null
@@ -1,238 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_registered_buffers 7 "January 18, 2025" "Linux" "Linux Programmer's Manual"
-.SH NAME
-io_uring_registered_buffers \- io_uring registered buffers overview
-.SH DESCRIPTION
-Registered buffers are a performance optimization feature of
-.B io_uring
-that allows applications to pre-register a set of buffers with the kernel.
-When buffers are registered, the kernel pins the memory and creates
-long-term mappings, eliminating the overhead of mapping and unmapping
-buffer memory for each I/O operation.
-.SS Why use registered buffers?
-For every I/O operation that transfers data between user space and the
-kernel, the kernel must perform several operations on the buffer memory:
-.IP \(bu 2
-Verify the memory is accessible to the process
-.IP \(bu
-Pin the pages in memory to prevent them from being swapped out
-.IP \(bu
-Set up kernel mappings to access the memory
-.PP
-These operations, while individually fast, add up when performing many
-small I/O operations. By registering buffers once upfront, these costs
-are paid only once, and subsequent I/O operations can use the pre-mapped
-buffers directly.
-
-Registered buffers are most beneficial for applications that:
-.IP \(bu 2
-Perform many small I/O operations
-.IP \(bu
-Reuse the same buffers repeatedly
-.IP \(bu
-Need the lowest possible per-I/O overhead
-.SS Registering buffers
-Buffers are registered using
-.BR io_uring_register_buffers (3)
-or
-.BR io_uring_register_buffers_tags (3).
-The buffers are described using an array of
-.I struct iovec
-structures:
-.PP
-.in +4n
-.EX
-struct iovec iovecs[2];
-iovecs[0].iov_base = buf1;
-iovecs[0].iov_len = 4096;
-iovecs[1].iov_base = buf2;
-iovecs[1].iov_len = 8192;
-
-ret = io_uring_register_buffers(ring, iovecs, 2);
-.EE
-.in
-.PP
-The buffers must be anonymous memory (allocated via
-.BR malloc (3),
-.BR mmap (2)
-with
-.BR MAP_ANONYMOUS ,
-or similar). File-backed memory is not supported.
-
-There is a limit of 1 GiB per individual buffer. Huge pages are supported
-and the entire huge page will be pinned even if only part of it is used.
-
-The buffers are charged against the user's
-.B RLIMIT_MEMLOCK
-resource limit on kernels before 5.12. On kernel 5.12 and later with
-.B IORING_FEAT_NATIVE_WORKERS
-support, cgroup memory accounting is used instead and no memlock limit
-applies.
-.PP
-Unless running as root, if buffer registration fails with
-.BR ENOMEM ,
-the memlock limit may need to be increased. The current limit can be
-checked with:
-.PP
-.in +4n
-.EX
-ulimit -l
-.EE
-.in
-.PP
-The limit can be increased for the current shell session with:
-.PP
-.in +4n
-.EX
-ulimit -l unlimited
-.EE
-.in
-.PP
-For a permanent change, edit
-.I /etc/security/limits.conf
-or use
-.BR setrlimit (2)
-programmatically with
-.BR RLIMIT_MEMLOCK .
-.SS Using registered buffers
-To use a registered buffer in an I/O operation, use the fixed buffer
-variants of the prep functions:
-.IP \(bu 2
-.BR io_uring_prep_read_fixed (3)
-instead of
-.BR io_uring_prep_read (3)
-.IP \(bu
-.BR io_uring_prep_write_fixed (3)
-instead of
-.BR io_uring_prep_write (3)
-.IP \(bu
-.BR io_uring_prep_readv_fixed (3)
-instead of
-.BR io_uring_prep_readv (3)
-.IP \(bu
-.BR io_uring_prep_writev_fixed (3)
-instead of
-.BR io_uring_prep_writev (3)
-.PP
-Zero-copy send operations can also use registered buffers:
-.IP \(bu 2
-.BR io_uring_prep_send_zc (3)
-with
-.B IORING_RECVSEND_FIXED_BUF
-.IP \(bu
-.BR io_uring_prep_sendmsg_zc (3)
-with
-.B IORING_RECVSEND_FIXED_BUF
-.PP
-These functions take a
-.I buf_index
-parameter that specifies which registered buffer to use (0-indexed into
-the array passed to
-.BR io_uring_register_buffers (3)).
-
-The memory range used for the I/O operation must fall within the bounds
-of the registered buffer. It is valid to use only a portion of a
-registered buffer for an operation.
-.PP
-.in +4n
-.EX
-/* Use first 1024 bytes of registered buffer 0 */
-io_uring_prep_read_fixed(sqe, fd, buf1, 1024, offset, 0);
-
-/* Use registered buffer 1 */
-io_uring_prep_write_fixed(sqe, fd, buf2, 2048, offset, 1);
-.EE
-.in
-.SS Sparse buffer registration
-Applications can register a sparse buffer table using
-.BR io_uring_register_buffers_sparse (3).
-This creates a table with empty slots that can be filled in later using
-.BR io_uring_register_buffers_update_tag (3).
-This is useful when the full set of buffers is not known at registration
-time.
-.PP
-.in +4n
-.EX
-/* Create sparse table with 10 slots */
-ret = io_uring_register_buffers_sparse(ring, 10);
-
-/* Later, fill in slot 3 */
-struct iovec iov = { .iov_base = buf, .iov_len = 4096 };
-ret = io_uring_register_buffers_update_tag(ring, 3, &iov, NULL, 1);
-.EE
-.in
-.SS Buffer tagging
-When using
-.BR io_uring_register_buffers_tags (3)
-or
-.BR io_uring_register_buffers_update_tag (3),
-each buffer can be associated with a tag value. When a buffer is
-unregistered (either explicitly or by replacing it), and there are no
-more in-flight operations using that buffer, a completion queue entry
-is posted with
-.I user_data
-set to the tag value and all other fields zeroed.
-
-This allows applications to know when it is safe to free or reuse the
-buffer memory.
-.SS Updating registered buffers
-Registered buffers can be updated in place using
-.BR io_uring_register_buffers_update_tag (3).
-This can:
-.IP \(bu 2
-Replace an existing buffer with a new one
-.IP \(bu
-Fill in a sparse slot
-.IP \(bu
-Remove a buffer by setting the iovec to zero length
-.PP
-Updating buffers does not immediately free resources. The old buffer
-remains valid until all in-flight operations complete.
-.SS Unregistering buffers
-Buffers are unregistered using
-.BR io_uring_unregister_buffers (3).
-This releases all registered buffers. Buffers are also automatically
-unregistered when the io_uring instance is destroyed.
-
-Applications do not need to explicitly unregister buffers before
-shutting down the ring. However, page unpinning may happen asynchronously,
-so pages may not be immediately available after ring destruction.
-.SS Cloning buffers
-Registered buffers can be cloned from one ring to another using
-.BR io_uring_clone_buffers (3)
-or
-.BR io_uring_clone_buffers_offset (3).
-This allows multiple rings to share the same set of registered buffers
-without re-registering them.
-.SH NOTES
-.IP \(bu 2
-Registered buffers provide the most benefit for small, frequent I/O
-operations where the per-operation overhead is significant.
-.IP \(bu
-For large I/O operations, the buffer mapping overhead is small relative
-to the actual I/O time, so registered buffers may not provide much benefit.
-.IP \(bu
-The maximum number of registered buffers is limited by available kernel
-memory and the
-.B RLIMIT_MEMLOCK
-limit (on older kernels).
-.IP \(bu
-Registered buffers cannot be used with provided buffer rings
-.RB ( IOSQE_BUFFER_SELECT ).
-These are separate mechanisms for different use cases.
-.SH SEE ALSO
-.BR io_uring (7),
-.BR io_uring_registered_files (7),
-.BR setrlimit (2),
-.BR io_uring_register_buffers (3),
-.BR io_uring_register_buffers_tags (3),
-.BR io_uring_register_buffers_sparse (3),
-.BR io_uring_register_buffers_update_tag (3),
-.BR io_uring_unregister_buffers (3),
-.BR io_uring_prep_read_fixed (3),
-.BR io_uring_prep_write_fixed (3),
-.BR io_uring_prep_send_zc (3),
-.BR io_uring_prep_sendmsg_zc (3),
-.BR io_uring_clone_buffers (3)
diff --git a/man/io_uring_registered_buffers.7.md b/man/io_uring_registered_buffers.7.md
new file mode 100644
index 00000000..23ca796b
--- /dev/null
+++ b/man/io_uring_registered_buffers.7.md
@@ -0,0 +1,215 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 18, 2025
+footer: Linux
+header: Linux Programmer\'s Manual
+section: 7
+title: io_uring_registered_buffers
+---
+
+# NAME
+
+io_uring_registered_buffers - io_uring registered buffers overview
+
+# DESCRIPTION
+
+Registered buffers are a performance optimization feature of
+**io_uring** that allows applications to pre-register a set of buffers
+with the kernel. When buffers are registered, the kernel pins the memory
+and creates long-term mappings, eliminating the overhead of mapping and
+unmapping buffer memory for each I/O operation.
+
+## Why use registered buffers?
+
+For every I/O operation that transfers data between user space and the
+kernel, the kernel must perform several operations on the buffer memory:
+
+- Verify the memory is accessible to the process
+
+- Pin the pages in memory to prevent them from being swapped out
+
+- Set up kernel mappings to access the memory
+
+These operations, while individually fast, add up when performing many
+small I/O operations. By registering buffers once upfront, these costs
+are paid only once, and subsequent I/O operations can use the pre-mapped
+buffers directly.
+
+Registered buffers are most beneficial for applications that:
+
+- Perform many small I/O operations
+
+- Reuse the same buffers repeatedly
+
+- Need the lowest possible per-I/O overhead
+
+## Registering buffers
+
+Buffers are registered using **io_uring_register_buffers**(3) or
+**io_uring_register_buffers_tags**(3). The buffers are described using
+an array of *struct iovec* structures:
+
+``` text
+struct iovec iovecs[2];
+iovecs[0].iov_base = buf1;
+iovecs[0].iov_len = 4096;
+iovecs[1].iov_base = buf2;
+iovecs[1].iov_len = 8192;
+
+ret = io_uring_register_buffers(ring, iovecs, 2);
+```
+
+The buffers must be anonymous memory (allocated via **malloc**(3),
+**mmap**(2) with **MAP_ANONYMOUS**, or similar). File-backed memory is
+not supported.
+
+There is a limit of 1 GiB per individual buffer. Huge pages are
+supported and the entire huge page will be pinned even if only part of
+it is used.
+
+The buffers are charged against the user\'s **RLIMIT_MEMLOCK** resource
+limit on kernels before 5.12. On kernel 5.12 and later with
+**IORING_FEAT_NATIVE_WORKERS** support, cgroup memory accounting is used
+instead and no memlock limit applies.
+
+Unless running as root, if buffer registration fails with **ENOMEM**,
+the memlock limit may need to be increased. The current limit can be
+checked with:
+
+``` text
+ulimit -l
+```
+
+The limit can be increased for the current shell session with:
+
+``` text
+ulimit -l unlimited
+```
+
+For a permanent change, edit */etc/security/limits.conf* or use
+**setrlimit**(2) programmatically with **RLIMIT_MEMLOCK**.
+
+## Using registered buffers
+
+To use a registered buffer in an I/O operation, use the fixed buffer
+variants of the prep functions:
+
+- **io_uring_prep_read_fixed**(3) instead of **io_uring_prep_read**(3)
+
+- **io_uring_prep_write_fixed**(3) instead of **io_uring_prep_write**(3)
+
+- **io_uring_prep_readv_fixed**(3) instead of **io_uring_prep_readv**(3)
+
+- **io_uring_prep_writev_fixed**(3) instead of
+ **io_uring_prep_writev**(3)
+
+Zero-copy send operations can also use registered buffers:
+
+- **io_uring_prep_send_zc**(3) with **IORING_RECVSEND_FIXED_BUF**
+
+- **io_uring_prep_sendmsg_zc**(3) with **IORING_RECVSEND_FIXED_BUF**
+
+These functions take a *buf_index* parameter that specifies which
+registered buffer to use (0-indexed into the array passed to
+**io_uring_register_buffers**(3)).
+
+The memory range used for the I/O operation must fall within the bounds
+of the registered buffer. It is valid to use only a portion of a
+registered buffer for an operation.
+
+``` text
+/* Use first 1024 bytes of registered buffer 0 */
+io_uring_prep_read_fixed(sqe, fd, buf1, 1024, offset, 0);
+
+/* Use registered buffer 1 */
+io_uring_prep_write_fixed(sqe, fd, buf2, 2048, offset, 1);
+```
+
+## Sparse buffer registration
+
+Applications can register a sparse buffer table using
+**io_uring_register_buffers_sparse**(3). This creates a table with empty
+slots that can be filled in later using
+**io_uring_register_buffers_update_tag**(3). This is useful when the
+full set of buffers is not known at registration time.
+
+``` text
+/* Create sparse table with 10 slots */
+ret = io_uring_register_buffers_sparse(ring, 10);
+
+/* Later, fill in slot 3 */
+struct iovec iov = { .iov_base = buf, .iov_len = 4096 };
+ret = io_uring_register_buffers_update_tag(ring, 3, &iov, NULL, 1);
+```
+
+## Buffer tagging
+
+When using **io_uring_register_buffers_tags**(3) or
+**io_uring_register_buffers_update_tag**(3), each buffer can be
+associated with a tag value. When a buffer is unregistered (either
+explicitly or by replacing it), and there are no more in-flight
+operations using that buffer, a completion queue entry is posted with
+*user_data* set to the tag value and all other fields zeroed.
+
+This allows applications to know when it is safe to free or reuse the
+buffer memory.
+
+## Updating registered buffers
+
+Registered buffers can be updated in place using
+**io_uring_register_buffers_update_tag**(3). This can:
+
+- Replace an existing buffer with a new one
+
+- Fill in a sparse slot
+
+- Remove a buffer by setting the iovec to zero length
+
+Updating buffers does not immediately free resources. The old buffer
+remains valid until all in-flight operations complete.
+
+## Unregistering buffers
+
+Buffers are unregistered using **io_uring_unregister_buffers**(3). This
+releases all registered buffers. Buffers are also automatically
+unregistered when the io_uring instance is destroyed.
+
+Applications do not need to explicitly unregister buffers before
+shutting down the ring. However, page unpinning may happen
+asynchronously, so pages may not be immediately available after ring
+destruction.
+
+## Cloning buffers
+
+Registered buffers can be cloned from one ring to another using
+**io_uring_clone_buffers**(3) or **io_uring_clone_buffers_offset**(3).
+This allows multiple rings to share the same set of registered buffers
+without re-registering them.
+
+# NOTES
+
+- Registered buffers provide the most benefit for small, frequent I/O
+ operations where the per-operation overhead is significant.
+
+- For large I/O operations, the buffer mapping overhead is small
+ relative to the actual I/O time, so registered buffers may not provide
+ much benefit.
+
+- The maximum number of registered buffers is limited by available
+ kernel memory and the **RLIMIT_MEMLOCK** limit (on older kernels).
+
+- Registered buffers cannot be used with provided buffer rings
+ (**IOSQE_BUFFER_SELECT**). These are separate mechanisms for different
+ use cases.
+
+# SEE ALSO
+
+**io_uring**(7), **io_uring_registered_files**(7), **setrlimit**(2),
+**io_uring_register_buffers**(3), **io_uring_register_buffers_tags**(3),
+**io_uring_register_buffers_sparse**(3),
+**io_uring_register_buffers_update_tag**(3),
+**io_uring_unregister_buffers**(3), **io_uring_prep_read_fixed**(3),
+**io_uring_prep_write_fixed**(3), **io_uring_prep_send_zc**(3),
+**io_uring_prep_sendmsg_zc**(3), **io_uring_clone_buffers**(3)
diff --git a/man/io_uring_registered_files.7 b/man/io_uring_registered_files.7
deleted file mode 100644
index b280b009..00000000
--- a/man/io_uring_registered_files.7
+++ /dev/null
@@ -1,228 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_registered_files 7 "January 18, 2025" "Linux" "Linux Programmer's Manual"
-.SH NAME
-io_uring_registered_files \- io_uring registered files overview
-.SH DESCRIPTION
-Registered files (also known as fixed files) are a performance
-optimization feature of
-.B io_uring
-that allows applications to pre-register a set of file descriptors with
-the kernel. When files are registered, the kernel takes a reference to
-each file, avoiding the overhead of looking up file descriptors and
-taking references for each I/O operation.
-.SS Why use registered files?
-For every I/O operation that uses a file descriptor, the kernel must:
-.IP \(bu 2
-Look up the file descriptor in the process's file descriptor table
-.IP \(bu
-Take a reference to the file to ensure it remains valid during the
-operation
-.IP \(bu
-Release the reference when the operation completes
-.PP
-For applications performing many I/O operations, especially on threaded
-applications where the file table is shared (making reference counting
-more expensive), these overheads accumulate. By registering files once,
-the reference is held for the lifetime of the registration, and
-operations can use the file directly without per-operation lookups or
-reference counting.
-
-Registered files are most beneficial for applications that:
-.IP \(bu 2
-Perform many I/O operations on the same set of files
-.IP \(bu
-Are multi-threaded (where file table operations are more expensive)
-.IP \(bu
-Need the lowest possible per-I/O overhead
-.SS Registering files
-Files are registered using
-.BR io_uring_register_files (3)
-or
-.BR io_uring_register_files_tags (3).
-The files are described using an array of file descriptors:
-.PP
-.in +4n
-.EX
-int fds[3];
-fds[0] = open("file1", O_RDONLY);
-fds[1] = open("file2", O_RDONLY);
-fds[2] = open("file3", O_WRONLY | O_CREAT, 0644);
-
-ret = io_uring_register_files(ring, fds, 3);
-.EE
-.in
-.PP
-Once registered, the original file descriptors can be closed if desired.
-The kernel holds its own references to the underlying files.
-.SS Using registered files
-To use a registered file in an I/O operation, set the
-.B IOSQE_FIXED_FILE
-flag in the SQE's
-.I flags
-field, and use the index into the registered file array (not the original
-file descriptor) in the
-.I fd
-field:
-.PP
-.in +4n
-.EX
-struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
-io_uring_prep_read(sqe, 0, buf, len, offset); /* index 0, not fd */
-io_uring_sqe_set_flags(sqe, IOSQE_FIXED_FILE);
-.EE
-.in
-.PP
-The index is 0-based into the array passed to
-.BR io_uring_register_files (3).
-.SS Sparse file registration
-The file array can be sparse, meaning some slots can be empty. Empty
-slots are indicated by setting the file descriptor to \-1. Applications
-can create a fully sparse table using
-.BR io_uring_register_files_sparse (3)
-and fill in slots later:
-.PP
-.in +4n
-.EX
-/* Create sparse table with 100 slots */
-ret = io_uring_register_files_sparse(ring, 100);
-
-/* Later, fill in slot 5 */
-int fd = open("file", O_RDONLY);
-ret = io_uring_register_files_update(ring, 5, &fd, 1);
-.EE
-.in
-.SS Updating registered files
-Registered files can be updated using
-.BR io_uring_register_files_update (3)
-or
-.BR io_uring_register_files_update_tag (3).
-This can:
-.IP \(bu 2
-Replace an existing file with a new one
-.IP \(bu
-Fill in an empty slot
-.IP \(bu
-Remove a file by setting the descriptor to \-1
-.PP
-To skip updating certain slots while updating others, use the special
-value
-.BR IORING_REGISTER_FILES_SKIP .
-.PP
-.in +4n
-.EX
-int fds[3];
-fds[0] = new_fd; /* replace slot 0 */
-fds[1] = IORING_REGISTER_FILES_SKIP; /* leave slot 1 unchanged */
-fds[2] = -1; /* remove slot 2 */
-
-ret = io_uring_register_files_update(ring, 0, fds, 3);
-.EE
-.in
-.PP
-Updates do not require the ring to be idle on kernels 5.13 and later.
-On older kernels, updates would wait for in-flight operations to complete.
-.SS File tagging
-When using
-.BR io_uring_register_files_tags (3)
-or
-.BR io_uring_register_files_update_tag (3),
-each file can be associated with a tag value. When a file is unregistered
-(either explicitly or by replacement), and there are no more in-flight
-operations using that file, a completion queue entry is posted with
-.I user_data
-set to the tag value and all other fields zeroed.
-
-This notification mechanism allows applications to know when it is safe
-to perform cleanup actions associated with the file.
-.SS Direct file descriptors
-Some io_uring operations can allocate file descriptors directly into the
-registered file table, avoiding the regular file descriptor table
-entirely. This is done by setting the
-.I file_index
-field in the SQE (using
-.BR io_uring_sqe_set_target_fixed_file (3))
-to the desired slot, or using
-.B IORING_FILE_INDEX_ALLOC
-to have io_uring allocate the next available slot.
-
-Operations that support direct descriptors include:
-.IP \(bu 2
-.B IORING_OP_OPENAT
-/
-.B IORING_OP_OPENAT2
-.IP \(bu
-.B IORING_OP_ACCEPT
-.IP \(bu
-.B IORING_OP_SOCKET
-.IP \(bu
-.B IORING_OP_PIPE
-.PP
-When using
-.BR IORING_FILE_INDEX_ALLOC ,
-the application should use
-.BR io_uring_register_file_alloc_range (3)
-to specify which range of the file table should be used for allocations.
-.PP
-.in +4n
-.EX
-/* Reserve slots 50-99 for dynamic allocation */
-io_uring_register_file_alloc_range(ring, 50, 50);
-
-/* Accept with direct descriptor allocation */
-struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
-io_uring_prep_accept_direct(sqe, listen_fd, NULL, NULL, 0,
- IORING_FILE_INDEX_ALLOC);
-.EE
-.in
-.PP
-The allocated slot index is returned in the CQE
-.I res
-field on success.
-.SS Closing direct descriptors
-Direct descriptors (files that exist only in the registered file table)
-can be closed using
-.B IORING_OP_CLOSE
-with the
-.B IOSQE_FIXED_FILE
-flag set, or by updating the slot to \-1 using
-.BR io_uring_register_files_update (3).
-.SS Unregistering files
-Files are unregistered using
-.BR io_uring_unregister_files (3).
-This releases all registered files. Files are also automatically
-unregistered when the io_uring instance is destroyed.
-
-Applications do not need to explicitly unregister files before shutting
-down the ring.
-.SH NOTES
-.IP \(bu 2
-Registered files provide the most benefit for applications performing
-many operations on the same files, especially multi-threaded applications.
-.IP \(bu
-Direct descriptors (files that only exist in the registered table) are
-not visible to operations outside io_uring, such as
-.BR read (2)
-or
-.BR write (2).
-.IP \(bu
-The
-.B IOSQE_FIXED_FILE
-flag must be set when using a registered file index; without it, the
-.I fd
-field is interpreted as a regular file descriptor.
-.IP \(bu
-It is an error to use
-.B IOSQE_FIXED_FILE
-with an index that does not correspond to a registered file.
-.SH SEE ALSO
-.BR io_uring (7),
-.BR io_uring_registered_buffers (7),
-.BR io_uring_register_files (3),
-.BR io_uring_register_files_tags (3),
-.BR io_uring_register_files_sparse (3),
-.BR io_uring_register_files_update (3),
-.BR io_uring_register_files_update_tag (3),
-.BR io_uring_unregister_files (3),
-.BR io_uring_register_file_alloc_range (3)
diff --git a/man/io_uring_registered_files.7.md b/man/io_uring_registered_files.7.md
new file mode 100644
index 00000000..d1542334
--- /dev/null
+++ b/man/io_uring_registered_files.7.md
@@ -0,0 +1,216 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 18, 2025
+footer: Linux
+header: Linux Programmer\'s Manual
+section: 7
+title: io_uring_registered_files
+---
+
+# NAME
+
+io_uring_registered_files - io_uring registered files overview
+
+# DESCRIPTION
+
+Registered files (also known as fixed files) are a performance
+optimization feature of **io_uring** that allows applications to
+pre-register a set of file descriptors with the kernel. When files are
+registered, the kernel takes a reference to each file, avoiding the
+overhead of looking up file descriptors and taking references for each
+I/O operation.
+
+## Why use registered files?
+
+For every I/O operation that uses a file descriptor, the kernel must:
+
+- Look up the file descriptor in the process\'s file descriptor table
+
+- Take a reference to the file to ensure it remains valid during the
+ operation
+
+- Release the reference when the operation completes
+
+For applications performing many I/O operations, especially on threaded
+applications where the file table is shared (making reference counting
+more expensive), these overheads accumulate. By registering files once,
+the reference is held for the lifetime of the registration, and
+operations can use the file directly without per-operation lookups or
+reference counting.
+
+Registered files are most beneficial for applications that:
+
+- Perform many I/O operations on the same set of files
+
+- Are multi-threaded (where file table operations are more expensive)
+
+- Need the lowest possible per-I/O overhead
+
+## Registering files
+
+Files are registered using **io_uring_register_files**(3) or
+**io_uring_register_files_tags**(3). The files are described using an
+array of file descriptors:
+
+``` text
+int fds[3];
+fds[0] = open("file1", O_RDONLY);
+fds[1] = open("file2", O_RDONLY);
+fds[2] = open("file3", O_WRONLY | O_CREAT, 0644);
+
+ret = io_uring_register_files(ring, fds, 3);
+```
+
+Once registered, the original file descriptors can be closed if desired.
+The kernel holds its own references to the underlying files.
+
+## Using registered files
+
+To use a registered file in an I/O operation, set the
+**IOSQE_FIXED_FILE** flag in the SQE\'s *flags* field, and use the index
+into the registered file array (not the original file descriptor) in the
+*fd* field:
+
+``` text
+struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
+io_uring_prep_read(sqe, 0, buf, len, offset); /* index 0, not fd */
+io_uring_sqe_set_flags(sqe, IOSQE_FIXED_FILE);
+```
+
+The index is 0-based into the array passed to
+**io_uring_register_files**(3).
+
+## Sparse file registration
+
+The file array can be sparse, meaning some slots can be empty. Empty
+slots are indicated by setting the file descriptor to -1. Applications
+can create a fully sparse table using
+**io_uring_register_files_sparse**(3) and fill in slots later:
+
+``` text
+/* Create sparse table with 100 slots */
+ret = io_uring_register_files_sparse(ring, 100);
+
+/* Later, fill in slot 5 */
+int fd = open("file", O_RDONLY);
+ret = io_uring_register_files_update(ring, 5, &fd, 1);
+```
+
+## Updating registered files
+
+Registered files can be updated using
+**io_uring_register_files_update**(3) or
+**io_uring_register_files_update_tag**(3). This can:
+
+- Replace an existing file with a new one
+
+- Fill in an empty slot
+
+- Remove a file by setting the descriptor to -1
+
+To skip updating certain slots while updating others, use the special
+value **IORING_REGISTER_FILES_SKIP**.
+
+``` text
+int fds[3];
+fds[0] = new_fd; /* replace slot 0 */
+fds[1] = IORING_REGISTER_FILES_SKIP; /* leave slot 1 unchanged */
+fds[2] = -1; /* remove slot 2 */
+
+ret = io_uring_register_files_update(ring, 0, fds, 3);
+```
+
+Updates do not require the ring to be idle on kernels 5.13 and later. On
+older kernels, updates would wait for in-flight operations to complete.
+
+## File tagging
+
+When using **io_uring_register_files_tags**(3) or
+**io_uring_register_files_update_tag**(3), each file can be associated
+with a tag value. When a file is unregistered (either explicitly or by
+replacement), and there are no more in-flight operations using that
+file, a completion queue entry is posted with *user_data* set to the tag
+value and all other fields zeroed.
+
+This notification mechanism allows applications to know when it is safe
+to perform cleanup actions associated with the file.
+
+## Direct file descriptors
+
+Some io_uring operations can allocate file descriptors directly into the
+registered file table, avoiding the regular file descriptor table
+entirely. This is done by setting the *file_index* field in the SQE
+(using **io_uring_sqe_set_target_fixed_file**(3)) to the desired slot,
+or using **IORING_FILE_INDEX_ALLOC** to have io_uring allocate the next
+available slot.
+
+Operations that support direct descriptors include:
+
+- **IORING_OP_OPENAT** / **IORING_OP_OPENAT2**
+
+- **IORING_OP_ACCEPT**
+
+- **IORING_OP_SOCKET**
+
+- **IORING_OP_PIPE**
+
+When using **IORING_FILE_INDEX_ALLOC**, the application should use
+**io_uring_register_file_alloc_range**(3) to specify which range of the
+file table should be used for allocations.
+
+``` text
+/* Reserve slots 50-99 for dynamic allocation */
+io_uring_register_file_alloc_range(ring, 50, 50);
+
+/* Accept with direct descriptor allocation */
+struct io_uring_sqe *sqe = io_uring_get_sqe(ring);
+io_uring_prep_accept_direct(sqe, listen_fd, NULL, NULL, 0,
+ IORING_FILE_INDEX_ALLOC);
+```
+
+The allocated slot index is returned in the CQE *res* field on success.
+
+## Closing direct descriptors
+
+Direct descriptors (files that exist only in the registered file table)
+can be closed using **IORING_OP_CLOSE** with the **IOSQE_FIXED_FILE**
+flag set, or by updating the slot to -1 using
+**io_uring_register_files_update**(3).
+
+## Unregistering files
+
+Files are unregistered using **io_uring_unregister_files**(3). This
+releases all registered files. Files are also automatically unregistered
+when the io_uring instance is destroyed.
+
+Applications do not need to explicitly unregister files before shutting
+down the ring.
+
+# NOTES
+
+- Registered files provide the most benefit for applications performing
+ many operations on the same files, especially multi-threaded
+ applications.
+
+- Direct descriptors (files that only exist in the registered table) are
+ not visible to operations outside io_uring, such as **read**(2) or
+ **write**(2).
+
+- The **IOSQE_FIXED_FILE** flag must be set when using a registered file
+ index; without it, the *fd* field is interpreted as a regular file
+ descriptor.
+
+- It is an error to use **IOSQE_FIXED_FILE** with an index that does not
+ correspond to a registered file.
+
+# SEE ALSO
+
+**io_uring**(7), **io_uring_registered_buffers**(7),
+**io_uring_register_files**(3), **io_uring_register_files_tags**(3),
+**io_uring_register_files_sparse**(3),
+**io_uring_register_files_update**(3),
+**io_uring_register_files_update_tag**(3),
+**io_uring_unregister_files**(3),
+**io_uring_register_file_alloc_range**(3)
diff --git a/man/io_uring_resize_rings.3 b/man/io_uring_resize_rings.3
deleted file mode 100644
index 4d4a9286..00000000
--- a/man/io_uring_resize_rings.3
+++ /dev/null
@@ -1,116 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_resize_rings 3 "October 29, 2024" "liburing-2.9" "liburing Manual"
-.SH NAME
-io_uring_resize_rings \- resize the SQ and CQ rings
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_resize_rings(struct io_uring *" ring ",
-.BI " struct io_uring_params *" p ");
-.PP
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_resize_rings (3)
-function performs resizes the SQ and/or CQ ring associated with
-.I ring
-by the parameters specified in
-.I p .
-
-The
-.I p
-argument must be filled in with the appropriate information for the resize
-operations, most notably the
-.IR sq_entries
-and
-.IR cq_entries
-fields must be filled out. The
-.IR flags
-field can also be set, see below for potential values that may be used with
-a resize operation.
-
-It's fairly uncommon to need to resize the SQ ring, but not that uncommon
-that the CQ ring would need resizing. For networked workloads, it can be
-hard to appropriately size the CQ ring upfront, as it's not always known what
-load a given ring will see. If overflow conditions are seen for the CQ ring,
-then resizing it larger may be a good idea.
-
-When a ring is resized, any pending SQ or CQ entries are copied along the
-way. It is not legal to resize a CQ ring that is in an overflow condition,
-and attempting to do so will fail.
-
-Currently doesn't support resizing rings setup with
-.B IORING_SETUP_NO_MMAP .
-This is purely a liburing limitation, the kernel does support it.
-
-Also note that ring resizing is currently only supported on rings setup
-with
-.B IORING_SETUP_DEFER_TASKRUN .
-Attempting to resize differently configured rings will result in an
-.BR -EINVAL
-error.
-
-Valid flags in
-.IR flags :
-.TP
-.B IORING_SETUP_CQSIZE
-If this isn't set, then the CQ ring size is set based on the specified
-SQ ring size. The default is twice as many CQ ring entries as there are
-SQ ring entries. If set, then
-.IR cq_entries
-will be used to size the CQ ring.
-.TP
-.B IORING_SETUP_CLAMP
-If set, then SQ and CQ ring entries are clamped to the maximum allowable
-size, if they exceed that. If not set, setting sizes too large will cause
-the operation to fail.
-.PP
-
-Other flags are inherited from the way the ring was setup, that includes flags
-like
-.B IORING_SETUP_NO_SQARRAY ,
-.B IORING_SETUP_SQE128 ,
-.B IORING_SETUP_CQE32 ,
-and
-.B IORING_SETUP_NO_MMAP .
-
-Other fields in
-.IR p
-should be cleared to zero.
-
-Available since kernel 6.13.
-
-Also see
-.BR io_uring_setup (2)
-for a detailed description of the setup flags.
-
-.SH RETURN VALUE
-.PP
-Returns 0 on success, and < 0 on failure. Potential common failure cases:
-.TP
-.B -EEXIST
-Attempting to resize a ring setup with
-.B IORING_SETUP_SINGLE_ISSUER
-and the resizing task is different from the one that created/enabled the ring.
-.TP
-.B -EFAULT
-Copying of
-.I p
-was unsuccessful.
-.TP
-.B -EINVAL
-Invalid flags were specified for the operation
-.TP
-.B -EINVAL
-Attempt to resize a ring not setup with
-.BR IORING_SETUP_DEFER_TASKRUN .
-.TP
-.B -EOVERFLOW
-The values specified for SQ or CQ entries would cause an overflow.
-
-.SH SEE ALSO
-.BR io_uring_setup (2)
diff --git a/man/io_uring_resize_rings.3.md b/man/io_uring_resize_rings.3.md
new file mode 100644
index 00000000..dcdeebce
--- /dev/null
+++ b/man/io_uring_resize_rings.3.md
@@ -0,0 +1,110 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: October 29, 2024
+footer: liburing-2.9
+header: liburing Manual
+section: 3
+title: io_uring_resize_rings
+---
+
+# NAME
+
+io_uring_resize_rings - resize the SQ and CQ rings
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_resize_rings(struct io_uring * ring ,
+ struct io_uring_params * p );
+```
+
+# DESCRIPTION
+
+The **io_uring_resize_rings**(3) function performs resizes the SQ and/or
+CQ ring associated with *ring* by the parameters specified in *p .*
+
+The *p* argument must be filled in with the appropriate information for
+the resize operations, most notably the *sq_entries* and *cq_entries*
+fields must be filled out. The *flags* field can also be set, see below
+for potential values that may be used with a resize operation.
+
+It\'s fairly uncommon to need to resize the SQ ring, but not that
+uncommon that the CQ ring would need resizing. For networked workloads,
+it can be hard to appropriately size the CQ ring upfront, as it\'s not
+always known what load a given ring will see. If overflow conditions are
+seen for the CQ ring, then resizing it larger may be a good idea.
+
+When a ring is resized, any pending SQ or CQ entries are copied along
+the way. It is not legal to resize a CQ ring that is in an overflow
+condition, and attempting to do so will fail.
+
+Currently doesn\'t support resizing rings setup with
+**IORING_SETUP_NO_MMAP .** This is purely a liburing limitation, the
+kernel does support it.
+
+Also note that ring resizing is currently only supported on rings setup
+with **IORING_SETUP_DEFER_TASKRUN .** Attempting to resize differently
+configured rings will result in an **-EINVAL** error.
+
+Valid flags in *flags*:
+
+**IORING_SETUP_CQSIZE**
+
+: If this isn\'t set, then the CQ ring size is set based on the
+ specified SQ ring size. The default is twice as many CQ ring entries
+ as there are SQ ring entries. If set, then *cq_entries* will be used
+ to size the CQ ring.
+
+**IORING_SETUP_CLAMP**
+
+: If set, then SQ and CQ ring entries are clamped to the maximum
+ allowable size, if they exceed that. If not set, setting sizes too
+ large will cause the operation to fail.
+
+Other flags are inherited from the way the ring was setup, that includes
+flags like **IORING_SETUP_NO_SQARRAY ,** **IORING_SETUP_SQE128 ,**
+**IORING_SETUP_CQE32 ,** and **IORING_SETUP_NO_MMAP .**
+
+Other fields in *p* should be cleared to zero.
+
+Available since kernel 6.13.
+
+Also see **io_uring_setup**(2) for a detailed description of the setup
+flags.
+
+# RETURN VALUE
+
+Returns 0 on success, and \< 0 on failure. Potential common failure
+cases:
+
+**-EEXIST**
+
+: Attempting to resize a ring setup with **IORING_SETUP_SINGLE_ISSUER**
+ and the resizing task is different from the one that created/enabled
+ the ring.
+
+**-EFAULT**
+
+: Copying of *p* was unsuccessful.
+
+**-EINVAL**
+
+: Invalid flags were specified for the operation
+
+**-EINVAL**
+
+: Attempt to resize a ring not setup with
+ **IORING_SETUP_DEFER_TASKRUN**.
+
+**-EOVERFLOW**
+
+: The values specified for SQ or CQ entries would cause an overflow.
+
+# SEE ALSO
+
+**io_uring_setup**(2)
diff --git a/man/io_uring_ring_dontfork.3 b/man/io_uring_ring_dontfork.3
deleted file mode 100644
index 3fca48bf..00000000
--- a/man/io_uring_ring_dontfork.3
+++ /dev/null
@@ -1,36 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_ring_dontfork 3 "January 18, 2025" "liburing-2.4" "liburing Manual"
-.SH NAME
-io_uring_ring_dontfork \- prevent ring memory from being shared after fork
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_ring_dontfork(struct io_uring *" ring ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_ring_dontfork (3)
-function ensures that the mmap'ed rings for the io_uring instance
-.I ring
-are not available to a child process after a
-.BR fork (2).
-
-This function uses
-.BR madvise (2)
-with
-.B MADV_DONTFORK
-on the mmap'ed ranges to prevent them from being shared with child
-processes. This is useful when the parent wants exclusive access to the
-ring and doesn't want the child to be able to access or interfere with it.
-
-.SH RETURN VALUE
-Returns 0 on success. On error, a negative errno value is returned.
-.SH SEE ALSO
-.BR io_uring_queue_init (3),
-.BR madvise (2),
-.BR fork (2)
diff --git a/man/io_uring_ring_dontfork.3.md b/man/io_uring_ring_dontfork.3.md
new file mode 100644
index 00000000..c269cecd
--- /dev/null
+++ b/man/io_uring_ring_dontfork.3.md
@@ -0,0 +1,43 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 18, 2025
+footer: liburing-2.4
+header: liburing Manual
+section: 3
+title: io_uring_ring_dontfork
+---
+
+# NAME
+
+io_uring_ring_dontfork - prevent ring memory from being shared after
+fork
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_ring_dontfork(struct io_uring * ring );
+```
+
+# DESCRIPTION
+
+The **io_uring_ring_dontfork**(3) function ensures that the mmap\'ed
+rings for the io_uring instance *ring* are not available to a child
+process after a **fork**(2).
+
+This function uses **madvise**(2) with **MADV_DONTFORK** on the mmap\'ed
+ranges to prevent them from being shared with child processes. This is
+useful when the parent wants exclusive access to the ring and doesn\'t
+want the child to be able to access or interfere with it.
+
+# RETURN VALUE
+
+Returns 0 on success. On error, a negative errno value is returned.
+
+# SEE ALSO
+
+**io_uring_queue_init**(3), **madvise**(2), **fork**(2)
diff --git a/man/io_uring_set_iowait.3 b/man/io_uring_set_iowait.3
deleted file mode 100644
index 5caf0a3a..00000000
--- a/man/io_uring_set_iowait.3
+++ /dev/null
@@ -1,57 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\" Copyright (C) 2025 Ammar Faizi <ammarfaizi2@gnuweeb.org>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_set_iowait 3 "July 27, 2025" "liburing-2.12" "liburing Manual"
-.SH NAME
-io_uring_set_iowait \- toggle of iowait usage when waiting on CQEs
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_set_iowait(struct io_uring *" ring ",
-.BI " bool " enable_iowait ");"
-.fi
-.SH DESCRIPTION
-.PP
-By default, io_uring marks a waiting task as being in iowait if it's
-sleeping waiting on events and there are pending requests. This isn't
-necessarily always useful, and may be confusing on non-storage setups
-where iowait isn't expected. It can also cause extra power usage by
-preventing the CPU from entering lower sleep states.
-
-The
-.BR io_uring_set_iowait (3)
-function allows the user to toggle this behavior. If
-.BI enable_iowait
-is set to true, the iowait behavior is enabled. If it is set to false,
-the iowait behavior is disabled. The iowait behavior is enabled by
-default when a ring is created.
-
-If the iowait is disabled, the submit functions will set
-.B IORING_ENTER_NO_IOWAIT
-in the
-.BI flags
-argument to
-.BR io_uring_enter (2).
-
-If the kernel supports this feature, it will be marked by having
-the
-.B IORING_FEAT_NO_IOWAIT
-feature flag set.
-
-Available since kernel 6.15.
-
-
-.SH RETURN VALUE
-On success,
-.BR io_uring_set_iowait (3)
-returns 0. On failure, it returns
-.BR -EOPNOTSUPP .
-
-
-.SH SEE ALSO
-.BR io_uring_enter (2),
-.BR io_uring_submit (3),
-.BR io_uring_submit_and_wait (3)
diff --git a/man/io_uring_set_iowait.3.md b/man/io_uring_set_iowait.3.md
new file mode 100644
index 00000000..f40dbad6
--- /dev/null
+++ b/man/io_uring_set_iowait.3.md
@@ -0,0 +1,57 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\" Copyright (C) 2025 Ammar Faizi <ammarfaizi2@gnuweeb.org>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: July 27, 2025
+footer: liburing-2.12
+header: liburing Manual
+section: 3
+title: io_uring_set_iowait
+---
+
+# NAME
+
+io_uring_set_iowait - toggle of iowait usage when waiting on CQEs
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_set_iowait(struct io_uring * ring ,
+ bool enable_iowait );
+```
+
+# DESCRIPTION
+
+By default, io_uring marks a waiting task as being in iowait if it\'s
+sleeping waiting on events and there are pending requests. This isn\'t
+necessarily always useful, and may be confusing on non-storage setups
+where iowait isn\'t expected. It can also cause extra power usage by
+preventing the CPU from entering lower sleep states.
+
+The **io_uring_set_iowait**(3) function allows the user to toggle this
+behavior. If enable_iowait is set to true, the iowait behavior is
+enabled. If it is set to false, the iowait behavior is disabled. The
+iowait behavior is enabled by default when a ring is created.
+
+If the iowait is disabled, the submit functions will set
+**IORING_ENTER_NO_IOWAIT** in the flags argument to
+**io_uring_enter**(2).
+
+If the kernel supports this feature, it will be marked by having the
+**IORING_FEAT_NO_IOWAIT** feature flag set.
+
+Available since kernel 6.15.
+
+# RETURN VALUE
+
+On success, **io_uring_set_iowait**(3) returns 0. On failure, it returns
+**-EOPNOTSUPP**.
+
+# SEE ALSO
+
+**io_uring_enter**(2), **io_uring_submit**(3),
+**io_uring_submit_and_wait**(3)
diff --git a/man/io_uring_setup.2 b/man/io_uring_setup.2
deleted file mode 100644
index 66d302b2..00000000
--- a/man/io_uring_setup.2
+++ /dev/null
@@ -1,820 +0,0 @@
-.\" Copyright (C) 2019 Jens Axboe <axboe@kernel.dk>
-.\" Copyright (C) 2019 Jon Corbet <corbet@lwn.net>
-.\" Copyright (C) 2019 Red Hat, Inc.
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_setup 2 "January 29, 2019" "Linux" "Linux Programmer's Manual"
-.SH NAME
-io_uring_setup \- setup a context for performing asynchronous I/O
-.SH SYNOPSIS
-.nf
-.BR "#include <liburing.h>"
-.PP
-.BI "int io_uring_setup(u32 " entries ", struct io_uring_params *" params );
-.fi
-.PP
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_setup (2)
-system call sets up a submission queue (SQ) and completion queue (CQ) with at
-least
-.I entries
-entries, and returns a file descriptor which can be used to perform
-subsequent operations on the io_uring instance. The submission and
-completion queues are shared between userspace and the kernel, which
-eliminates the need to copy data when initiating and completing I/O.
-
-.I params
-is used by the application to pass options to the kernel, and by the
-kernel to convey information about the ring buffers.
-.PP
-.in +4n
-.EX
-struct io_uring_params {
- __u32 sq_entries;
- __u32 cq_entries;
- __u32 flags;
- __u32 sq_thread_cpu;
- __u32 sq_thread_idle;
- __u32 features;
- __u32 wq_fd;
- __u32 resv[3];
- struct io_sqring_offsets sq_off;
- struct io_cqring_offsets cq_off;
-};
-.EE
-.in
-.PP
-The
-.IR flags ,
-.IR sq_thread_cpu ,
-and
-.I sq_thread_idle
-fields are used to configure the io_uring instance.
-.I flags
-is a bit mask of 0 or more of the following values ORed
-together:
-.TP
-.B IORING_SETUP_IOPOLL
-Perform busy-waiting for an I/O completion, as opposed to getting
-notifications via an asynchronous IRQ (Interrupt Request). The file
-system (if any) and block device must support polling in order for
-this to work. Busy-waiting provides lower latency, but may consume
-more CPU resources than interrupt driven I/O. Currently, this feature
-is usable only on a file descriptor opened using the
-.B O_DIRECT
-flag
-(if using the
-.B IORING_OP_{READ,WRITE}(V)(_FIXED)
-opcodes). When a read or write is submitted to a polled context, the
-application must poll for completions on the CQ ring by calling
-.BR io_uring_enter (2).
-Most non-polled I/O requests are forbidden on
-.B IORING_SETUP_IOPOLL
-io_uring instances (see
-.BR io_uring_setup_flags (7)
-for the allowed opcodes).
-
-This is only applicable for storage devices for now, and the storage device
-must be configured for polling. How to do that depends on the device type
-in question. For NVMe devices, the nvme driver must be loaded with the
-.I poll_queues
-parameter set to the desired number of polling queues. The polling queues
-will be shared appropriately between the CPUs in the system, if the number
-is less than the number of online CPU threads.
-.TP
-.B IORING_SETUP_HYBRID_IOPOLL
-This flag must be used with
-.B IORING_SETUP_IOPOLL
-flag. Hybrid io polling is a feature based on iopoll, it differs from strict
-polling in that it will delay a bit before doing completion side polling, to
-avoid wasting too much CPU resources. Like
-.B IOPOLL
-, it requires that devices support polling.
-.TP
-.B IORING_SETUP_SQPOLL
-When this flag is specified, a kernel thread is created to perform
-submission queue polling. An io_uring instance configured in this way
-enables an application to issue I/O without ever context switching
-into the kernel. By using the submission queue to fill in new
-submission queue entries and watching for completions on the
-completion queue, the application can submit and reap I/Os without
-doing a single system call.
-
-If the kernel thread is idle for more than
-.I sq_thread_idle
-milliseconds, it will set the
-.B IORING_SQ_NEED_WAKEUP
-bit in the
-.I flags
-field of the
-.IR "struct io_sq_ring" .
-When this happens, the application must call
-.BR io_uring_enter (2)
-to wake the kernel thread. If I/O is kept busy, the kernel thread
-will never sleep. An application making use of this feature will need
-to guard the
-.BR io_uring_enter (2)
-call with the following code sequence:
-
-.in +4n
-.EX
-/*
- * Ensure that the wakeup flag is read after the tail pointer
- * has been written. It's important to use memory load acquire
- * semantics for the flags read, as otherwise the application
- * and the kernel might not agree on the consistency of the
- * wakeup flag.
- */
-unsigned flags = atomic_load_relaxed(sq_ring->flags);
-if (flags & IORING_SQ_NEED_WAKEUP)
- io_uring_enter(fd, 0, 0, IORING_ENTER_SQ_WAKEUP);
-.EE
-.in
-
-where
-.I sq_ring
-is a submission queue ring setup using the
-.I struct io_sqring_offsets
-described below.
-.TP
-.BR
-Note that, when using a ring setup with
-.BR IORING_SETUP_SQPOLL ,
-you never directly call the
-.BR io_uring_enter (2)
-system call. That is usually taken care of by liburing's
-.BR io_uring_submit (3)
-function. It automatically determines if you are using
-polling mode or not and deals with when your program needs to call
-.BR io_uring_enter (2)
-without you having to bother about it.
-.TP
-.BR
-Note that while this may sound immediately appealing
-as an automatic "go faster" flag, evaluations should be done on a case-by-case
-basis to check if it makes sense for the application.
-.TP
-.BR
-Before version 5.11 of the Linux kernel, to successfully use this feature, the
-application must register a set of files to be used for IO through
-.BR io_uring_register (2)
-using the
-.B IORING_REGISTER_FILES
-opcode. Failure to do so will result in submitted IO being errored with
-.BR EBADF .
-The presence of this feature can be detected by the
-.B IORING_FEAT_SQPOLL_NONFIXED
-feature flag.
-In version 5.11 and later, it is no longer necessary to register files to use
-this feature. 5.11 also allows using this as non-root, if the user has the
-.B CAP_SYS_NICE
-capability. In 5.13 this requirement was also relaxed, and no special privileges
-are needed for SQPOLL in newer kernels. Certain stable kernels older than 5.13
-may also support unprivileged SQPOLL.
-.TP
-.B IORING_SETUP_SQ_AFF
-If this flag is specified, then the poll thread will be bound to the
-cpu set in the
-.I sq_thread_cpu
-field of the
-.IR "struct io_uring_params" .
-This flag is only meaningful when
-.B IORING_SETUP_SQPOLL
-is specified. When cgroup setting
-.I cpuset.cpus
-changes (typically in container environment), the bounded cpu set may be
-changed as well.
-.TP
-.B IORING_SETUP_CQSIZE
-Create the completion queue with
-.I "struct io_uring_params.cq_entries"
-entries. The value must be greater than
-.IR entries ,
-and may be rounded up to the next power-of-two.
-.TP
-.B IORING_SETUP_CLAMP
-If this flag is specified, and if
-.IR entries
-exceeds
-.BR IORING_MAX_ENTRIES ,
-then
-.I entries
-will be clamped at
-.BR IORING_MAX_ENTRIES .
-If the flag
-.B IORING_SETUP_CQSIZE
-is set, and if the value of
-.I "struct io_uring_params.cq_entries"
-exceeds
-.BR IORING_MAX_CQ_ENTRIES ,
-then it will be clamped at
-.BR IORING_MAX_CQ_ENTRIES .
-.TP
-.B IORING_SETUP_ATTACH_WQ
-This flag should be set in conjunction with
-.I "struct io_uring_params.wq_fd"
-being set to an existing io_uring ring file descriptor. When set, the
-io_uring instance being created will share the asynchronous worker
-thread backend of the specified io_uring ring, rather than create a new
-separate thread pool. Additionally the sq polling thread will be shared,
-if
-.B IORING_SETUP_SQPOLL
-is set.
-.TP
-.B IORING_SETUP_R_DISABLED
-If this flag is specified, the io_uring ring starts in a disabled state.
-In this state, restrictions can be registered, but submissions are not allowed.
-See
-.BR io_uring_register (2)
-for details on how to enable the ring. Available since 5.10.
-.TP
-.B IORING_SETUP_SUBMIT_ALL
-Normally io_uring stops submitting a batch of requests, if one of these requests
-results in an error. This can cause submission of less than what is expected,
-if a request ends in error while being submitted. If the ring is created with
-this flag,
-.BR io_uring_enter (2)
-will continue submitting requests even if it encounters an error submitting
-a request. CQEs are still posted for errored request regardless of whether or
-not this flag is set at ring creation time, the only difference is if the
-submit sequence is halted or continued when an error is observed. Available
-since 5.18.
-.TP
-.B IORING_SETUP_COOP_TASKRUN
-By default, io_uring will interrupt a task running in userspace when a
-completion event comes in. This is to ensure that completions run in a timely
-manner. For a lot of use cases, this is overkill and can cause reduced
-performance from both the inter-processor interrupt used to do this, the
-kernel/user transition, the needless interruption of the tasks userspace
-activities, and reduced batching if completions come in at a rapid rate. Most
-applications don't need the forceful interruption, as the events are processed
-at any kernel/user transition. The exception are setups where the application
-uses multiple threads operating on the same ring, where the application
-waiting on completions isn't the one that submitted them. For most other
-use cases, setting this flag will improve performance. Available since 5.19.
-.TP
-.B IORING_SETUP_TASKRUN_FLAG
-Used in conjunction with
-.BR IORING_SETUP_COOP_TASKRUN
-or
-.BR IORING_SETUP_DEFER_TASKRUN ,
-this provides a flag,
-.BR IORING_SQ_TASKRUN ,
-which is set in the SQ ring
-.I flags
-whenever completions are pending that should be processed. liburing will check
-for this flag even when doing
-.BR io_uring_peek_cqe (3)
-and enter the kernel to process them, and applications can do the same. This
-makes
-.B IORING_SETUP_TASKRUN_FLAG
-safe to use even when applications rely on a peek style operation on the CQ
-ring to see if anything might be pending to reap. Available since 5.19.
-.TP
-.B IORING_SETUP_SQE128
-If set, io_uring will use 128-byte SQEs rather than the normal 64-byte sized
-variant. This is a requirement for using certain request types, as of 5.19
-only the
-.B IORING_OP_URING_CMD
-passthrough command for NVMe passthrough needs this. Available since 5.19.
-.TP
-.B IORING_SETUP_CQE32
-If set, io_uring will use 32-byte CQEs rather than the normal 16-byte sized
-variant. This is a requirement for using certain request types, as of 5.19
-only the
-.B IORING_OP_URING_CMD
-passthrough command for NVMe passthrough needs this. Also see
-.B IORING_SETUP_CQE_MIXED
-for an alternative to this flag. Available since 5.19.
-.TP
-.B IORING_SETUP_SINGLE_ISSUER
-A hint to the kernel that only a single task (or thread) will submit requests, which is
-used for internal optimisations. The submission task is either the task that created the
-ring, or if
-.B IORING_SETUP_R_DISABLED
-is specified then it is the task that enables the ring through
-.BR io_uring_register (2) .
-The kernel enforces this rule, failing requests with
-.B -EEXIST
-if the restriction is violated.
-Note that when
-.B IORING_SETUP_SQPOLL
-is set it is considered that the polling task is doing all submissions
-on behalf of the userspace and so it always complies with the rule disregarding
-how many userspace tasks do
-.BR io_uring_enter (2).
-Available since 6.0.
-.TP
-.B IORING_SETUP_DEFER_TASKRUN
-By default, io_uring will process all outstanding work at the end of any system
-call or thread interrupt. This can delay the application from making other progress.
-Setting this flag will hint to io_uring that it should defer work until an
-.BR io_uring_enter (2)
-call with the
-.B IORING_ENTER_GETEVENTS
-flag set. This allows the application to request work to run just before it wants to
-process completions.
-This flag requires the
-.B IORING_SETUP_SINGLE_ISSUER
-flag to be set, and also enforces that the call to
-.BR io_uring_enter (2)
-is called from the same thread that submitted requests.
-Note that if this flag is set then it is the application's responsibility to periodically
-trigger work (for example via any of the CQE waiting functions) or else completions may
-not be delivered.
-Available since 6.1.
-.TP
-.B IORING_SETUP_NO_MMAP
-By default, io_uring allocates kernel memory that callers must subsequently
-.BR mmap (2).
-If this flag is set, io_uring instead uses caller-allocated buffers;
-.I p->cq_off.user_addr
-must point to the memory for the sq/cq rings, and
-.I p->sq_off.user_addr
-must point to the memory for the sqes.
-Each allocation must be contiguous memory.
-Typically, callers should allocate this memory by using
-.BR mmap (2)
-to allocate a huge page.
-If this flag is set, a subsequent attempt to
-.BR mmap (2)
-the io_uring file descriptor will fail.
-Available since 6.5.
-.TP
-.B IORING_SETUP_REGISTERED_FD_ONLY
-If this flag is set, io_uring will register the ring file descriptor, and
-return the registered descriptor index, without ever allocating an unregistered
-file descriptor. The caller will need to use
-.B IORING_REGISTER_USE_REGISTERED_RING
-when calling
-.BR io_uring_register (2).
-This flag only makes sense when used alongside with
-.BR IORING_SETUP_NO_MMAP ,
-which also needs to be set.
-Available since 6.5.
-
-.TP
-.B IORING_SETUP_NO_SQARRAY
-If this flag is set, entries in the submission queue will be submitted in order,
-wrapping around to the first entry after reaching the end of the queue. In other
-words, there will be no more indirection via the array of submission entries,
-and the queue will be indexed directly by the submission queue tail and the
-range of indexed represented by it modulo queue size. Subsequently, the user
-should not map the array of submission queue entries, and the corresponding
-offset in
-.I struct io_sqring_offsets
-will be set to zero. Available since 6.6.
-
-.TP
-.B IORING_SETUP_CQE_MIXED
-If this flag is set, the ring supports posting both the normal 16b sized CQEs
-as well as the larger 32b CQEs. Normally a ring is setup to only allow posting
-of normal 16b CQEs, or if
-.B IORING_SETUP_CQE32
-has been set, only 32b CQEs. With this flag, the kernel may post both types.
-If a 32b CQE is posted, the CQE
-.I flags
-member will have
-.B IORING_CQE_F_32
-set to indicate that this CQE is of the larger type. The kernel may also set
-.B IORING_CQE_F_SKIP
-in the CQE
-.I flags
-member, in case it needs to post a filler 16b CQE. This will happen if a 32b
-CQE needs posting and the current CQ ring offset is such that the 32b CQE
-would wrap around. Applications should simply skip/ignore such CQEs, they
-contain no information and serve only as placeholder to facilitate advancing
-the CQ ring such that a large CQE can get posted. The use case of the
-.B IORING_SETUP_CQE_MIXED
-flag is to allow more efficient setups of workloads that may post both normal
-and large CQEs. Opcodes that previously required the use of
-.B IORING_SETUP_CQE32
-may now use this flag instead, and potentially save some memory for the CQ
-ring. If used with liburing 2.12 or newer, the handling of variably sized CQEs
-is fully transparent. Available since 6.18.
-
-.TP
-.B IORING_SETUP_SQ_REWIND
-If this flag is set, the kernel ignores the submission queue head and tail
-and instead fetches SQEs starting from index 0. The application places all
-SQEs at the beginning of the SQ ring before each submit call, and the
-.I sq_entries
-parameter to
-.BR io_uring_enter (2)
-determines how many SQEs are submitted. This is a non-circular queue mode
-where the kernel always starts from the beginning.
-.PP
-This flag requires
-.B IORING_SETUP_NO_SQARRAY
-to be set. It is not compatible with
-.BR IORING_SETUP_SQPOLL .
-.PP
-This mode helps keep SQEs hot in cache by always accessing the same memory
-locations at the start of the ring, which can improve performance for
-workloads that submit small batches frequently.
-Available since 7.0.
-
-.PP
-If no flags are specified, the io_uring instance is setup for
-interrupt driven I/O. I/O may be submitted using
-.BR io_uring_enter (2)
-and can be reaped by polling the completion queue.
-
-The
-.I resv
-array must be initialized to zero.
-
-.I features
-is filled in by the kernel, which specifies various features supported
-by current kernel version.
-.TP
-.B IORING_FEAT_SINGLE_MMAP
-If this flag is set, the two SQ and CQ rings can be mapped with a single
-.BR mmap (2)
-call. The SQEs must still be allocated separately. This brings the necessary
-.BR mmap (2)
-calls down from three to two. Available since kernel 5.4.
-.TP
-.B IORING_FEAT_NODROP
-If this flag is set, io_uring supports almost never dropping completion events.
-A dropped event can only occur if the kernel runs out of memory, in which case
-you have worse problems than a lost event. Your application and others will
-likely get OOM killed anyway. If a completion event occurs and the CQ ring is
-full, the kernel stores the event internally until such a time that the CQ ring
-has room for more entries. In earlier kernels, if this overflow condition is
-entered, attempting to submit more IO would fail with the
-.B -EBUSY
-error value, if it can't flush the overflown events to the CQ ring. If this
-happens, the application must reap events from the CQ ring and attempt the
-submit again. If the kernel has no free memory to store the event internally
-it will be visible by an increase in the overflow value on the cqring.
-Available since kernel 5.5. Additionally
-.BR io_uring_enter (2)
-will return
-.B -EBADR
-the next time it would otherwise sleep waiting for completions (since kernel 5.19).
-
-.TP
-.B IORING_FEAT_SUBMIT_STABLE
-If this flag is set, applications can be certain that any data for
-async offload has been consumed when the kernel has consumed the SQE. Available
-since kernel 5.5.
-.TP
-.B IORING_FEAT_RW_CUR_POS
-If this flag is set, applications can specify
-.I offset
-==
-.B -1
-with
-.BR IORING_OP_{READV,WRITEV} ,
-.BR IORING_OP_{READ,WRITE}_FIXED ,
-and
-.B IORING_OP_{READ,WRITE}
-to mean current file position, which behaves like
-.BR preadv2 (2)
-and
-.BR pwritev2 (2)
-with
-.I offset
-==
-.BR -1 .
-It'll use (and update) the current file position. This obviously comes
-with the caveat that if the application has multiple reads or writes in flight,
-then the end result will not be as expected. This is similar to threads sharing
-a file descriptor and doing IO using the current file position. Available since
-kernel 5.6.
-.TP
-.B IORING_FEAT_CUR_PERSONALITY
-If this flag is set, then io_uring guarantees that both sync and async
-execution of a request assumes the credentials of the task that called
-.BR io_uring_enter (2)
-to queue the requests. If this flag isn't set, then requests are issued with
-the credentials of the task that originally registered the io_uring. If only
-one task is using a ring, then this flag doesn't matter as the credentials
-will always be the same. Note that this is the default behavior, tasks can
-still register different personalities through
-.BR io_uring_register (2)
-with
-.B IORING_REGISTER_PERSONALITY
-and specify the personality to use in the sqe. Available since kernel 5.6.
-.TP
-.B IORING_FEAT_FAST_POLL
-If this flag is set, then io_uring supports using an internal poll mechanism
-to drive data/space readiness. This means that requests that cannot read or
-write data to a file no longer need to be punted to an async thread for
-handling, instead they will begin operation when the file is ready. This is
-similar to doing poll + read/write in userspace, but eliminates the need to do
-so. If this flag is set, requests waiting on space/data consume a lot less
-resources doing so as they are not blocking a thread. Available since kernel
-5.7.
-.TP
-.B IORING_FEAT_POLL_32BITS
-If this flag is set, the
-.B IORING_OP_POLL_ADD
-command accepts the full 32-bit range of epoll based flags. Most notably
-.B EPOLLEXCLUSIVE
-which allows exclusive (waking single waiters) behavior. Available since kernel
-5.9.
-.TP
-.B IORING_FEAT_SQPOLL_NONFIXED
-If this flag is set, the
-.B IORING_SETUP_SQPOLL
-feature no longer requires the use of fixed files. Any normal file descriptor
-can be used for IO commands without needing registration. Available since
-kernel 5.11.
-.TP
-.B IORING_FEAT_EXT_ARG
-If this flag is set, then the
-.BR io_uring_enter (2)
-system call supports passing in an extended argument instead of just the
-.I "sigset_t"
-of earlier kernels. This extended argument is of type
-.I "struct io_uring_getevents_arg"
-and allows the caller to pass in both a
-.I sigset_t
-and a timeout argument for waiting on events. The struct layout is as follows:
-.TP
-.in +8n
-.EX
-struct io_uring_getevents_arg {
- __u64 sigmask;
- __u32 sigmask_sz;
- __u32 pad;
- __u64 ts;
-};
-.EE
-
-and a pointer to this struct must be passed in if
-.B IORING_ENTER_EXT_ARG
-is set in the flags for the enter system call. Available since kernel 5.11.
-.TP
-.B IORING_FEAT_NATIVE_WORKERS
-If this flag is set, io_uring is using native workers for its async helpers.
-Previous kernels used kernel threads that assumed the identity of the
-original io_uring owning task, but later kernels will actively create what
-looks more like regular process threads instead. Available since kernel
-5.12.
-.TP
-.B IORING_FEAT_RSRC_TAGS
-If this flag is set, then io_uring supports a variety of features related
-to fixed files and buffers. In particular, it indicates that registered
-buffers can be updated in-place, whereas before the full set would have to
-be unregistered first. Available since kernel 5.13.
-.TP
-.B IORING_FEAT_CQE_SKIP
-If this flag is set, then io_uring supports setting
-.B IOSQE_CQE_SKIP_SUCCESS
-in the submitted SQE, indicating that no CQE should be generated for this
-SQE if it executes normally. If an error happens processing the SQE, a
-CQE with the appropriate error value will still be generated. Available since
-kernel 5.17.
-.TP
-.B IORING_FEAT_LINKED_FILE
-If this flag is set, then io_uring supports sane assignment of files for SQEs
-that have dependencies. For example, if a chain of SQEs are submitted with
-.BR IOSQE_IO_LINK ,
-then kernels without this flag will prepare the file for each link upfront.
-If a previous link opens a file with a known index, e.g. if direct descriptors
-are used with open or accept, then file assignment needs to happen post
-execution of that SQE. If this flag is set, then the kernel will defer
-file assignment until execution of a given request is started. Available since
-kernel 5.17.
-.TP
-.B IORING_FEAT_REG_REG_RING
-If this flag is set, then io_uring supports calling
-.BR io_uring_register (2)
-using a registered ring fd, via
-.BR IORING_REGISTER_USE_REGISTERED_RING .
-Available since kernel 6.3.
-.TP
-.B IORING_FEAT_MIN_TIMEOUT
-If this flag is set, then io_uring supports passing in a minimum batch wait
-timeout. See
-.BR io_uring_submit_and_wait_min_timeout (3)
-for more details.
-
-.TP
-.B IORING_FEAT_RECVSEND_BUNDLE
-If this flag is set, then io_uring supports bundled send and recv operations.
-See
-.BR io_uring_prep_send_bundle (3)
-for more information. Also implies support for provided buffers in send
-operations.
-.PP
-The rest of the fields in the
-.I struct io_uring_params
-are filled in by the kernel, and provide the information necessary to
-memory map the submission queue, completion queue, and the array of
-submission queue entries.
-.I sq_entries
-specifies the number of submission queue entries allocated.
-.I sq_off
-describes the offsets of various ring buffer fields:
-.PP
-.in +4n
-.EX
-struct io_sqring_offsets {
- __u32 head;
- __u32 tail;
- __u32 ring_mask;
- __u32 ring_entries;
- __u32 flags;
- __u32 dropped;
- __u32 array;
- __u32 resv1;
- __u64 user_addr;
-};
-.EE
-.in
-.PP
-Taken together,
-.I sq_entries
-and
-.I sq_off
-provide all of the information necessary for accessing the submission
-queue ring buffer and the submission queue entry array. The submission queue can
-be mapped with a call like:
-.PP
-.in +4n
-.EX
-ptr = mmap(0, sq_off.array + sq_entries * sizeof(__u32),
- PROT_READ|PROT_WRITE, MAP_SHARED|MAP_POPULATE,
- ring_fd, IORING_OFF_SQ_RING);
-.EE
-.in
-.PP
-where
-.I sq_off
-is the
-.I io_sqring_offsets
-structure, and
-.I ring_fd
-is the file descriptor returned from
-.BR io_uring_setup (2).
-The addition of
-.I sq_off.array
-to the length of the region accounts for the fact that the ring is
-located at the end of the data structure. As an example, the ring
-buffer head pointer can be accessed by adding
-.I sq_off.head
-to the address returned from
-.BR mmap (2):
-.PP
-.in +4n
-.EX
-head = ptr + sq_off.head;
-.EE
-.in
-
-The
-.I flags
-field is used by the kernel to communicate state information to the
-application. Currently, it is used to inform the application when a
-call to
-.BR io_uring_enter (2)
-is necessary. See the documentation for the
-.B IORING_SETUP_SQPOLL
-flag above.
-The
-.I dropped
-member is incremented for each invalid submission queue entry
-encountered in the ring buffer.
-
-The head and tail track the ring buffer state. The tail is
-incremented by the application when submitting new I/O, and the head
-is incremented by the kernel when the I/O has been successfully
-submitted. Determining the index of the head or tail into the ring is
-accomplished by applying a mask:
-.PP
-.in +4n
-.EX
-index = tail & ring_mask;
-.EE
-.in
-.PP
-The array of submission queue entries is mapped with:
-.PP
-.in +4n
-.EX
-sqentries = mmap(0, sq_entries * sizeof(struct io_uring_sqe),
- PROT_READ|PROT_WRITE, MAP_SHARED|MAP_POPULATE,
- ring_fd, IORING_OFF_SQES);
-.EE
-.in
-.PP
-The completion queue is described by
-.I cq_entries
-and
-.I cq_off
-shown here:
-.PP
-.in +4n
-.EX
-struct io_cqring_offsets {
- __u32 head;
- __u32 tail;
- __u32 ring_mask;
- __u32 ring_entries;
- __u32 overflow;
- __u32 cqes;
- __u32 flags;
- __u32 resv1;
- __u64 user_addr;
-};
-.EE
-.in
-.PP
-The completion queue is simpler, since the entries are not separated
-from the queue itself, and can be mapped with:
-.PP
-.in +4n
-.EX
-ptr = mmap(0, cq_off.cqes + cq_entries * sizeof(struct io_uring_cqe),
- PROT_READ|PROT_WRITE, MAP_SHARED|MAP_POPULATE, ring_fd,
- IORING_OFF_CQ_RING);
-.EE
-.in
-.PP
-Closing the file descriptor returned by
-.BR io_uring_setup (2)
-will free all resources associated with the io_uring context. Note that this
-may happen asynchronously within the kernel, so it is not guaranteed that
-resources are freed immediately.
-.PP
-.SH RETURN VALUE
-.BR io_uring_setup (2)
-returns a new file descriptor on success. The application may then
-provide the file descriptor in a subsequent
-.BR mmap (2)
-call to map the submission and completion queues, or to the
-.BR io_uring_register (2)
-or
-.BR io_uring_enter (2)
-system calls.
-
-On error, a negative error code is returned. The caller should not rely on
-.I errno
-variable.
-.PP
-.SH ERRORS
-.TP
-.B EFAULT
-.I params
-is outside your accessible address space.
-.TP
-.B EINVAL
-The resv array contains non-zero data, p.flags contains an unsupported
-flag,
-.I entries
-is out of bounds,
-.B IORING_SETUP_SQ_AFF
-was specified, but
-.B IORING_SETUP_SQPOLL
-was not, or
-.B IORING_SETUP_CQSIZE
-was specified, but
-.I io_uring_params.cq_entries
-was invalid.
-.B IORING_SETUP_REGISTERED_FD_ONLY
-was specified, but
-.B IORING_SETUP_NO_MMAP
-was not.
-.TP
-.B EMFILE
-The per-process limit on the number of open file descriptors has been
-reached (see the description of
-.B RLIMIT_NOFILE
-in
-.BR getrlimit (2)).
-.TP
-.B ENFILE
-The system-wide limit on the total number of open files has been
-reached.
-.TP
-.B ENOMEM
-Insufficient kernel resources are available.
-.TP
-.B EPERM
-.B IORING_SETUP_SQPOLL
-was specified, but the effective user ID of the caller did not have sufficient
-privileges.
-.TP
-.B EPERM
-.I /proc/sys/kernel/io_uring_disabled
-has the value 2, or it has the value 1 and the calling process does not hold the
-.B CAP_SYS_ADMIN
-capability or is not a member of
-.IR /proc/sys/kernel/io_uring_group .
-.TP
-.B ENXIO
-.B IORING_SETUP_ATTACH_WQ
-was set, but
-.I params.wq_fd
-did not refer to an io_uring instance or refers to an instance that is in the
-process of shutting down.
-.SH SEE ALSO
-.BR io_uring_register (2),
-.BR io_uring_enter (2)
diff --git a/man/io_uring_setup.2.md b/man/io_uring_setup.2.md
new file mode 100644
index 00000000..7866145c
--- /dev/null
+++ b/man/io_uring_setup.2.md
@@ -0,0 +1,664 @@
+.\" Copyright (C) 2019 Jens Axboe <axboe@kernel.dk>
+.\" Copyright (C) 2019 Jon Corbet <corbet@lwn.net>
+.\" Copyright (C) 2019 Red Hat, Inc.
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 29, 2019
+footer: Linux
+header: Linux Programmer\'s Manual
+section: 2
+title: io_uring_setup
+---
+
+# NAME
+
+io_uring_setup - setup a context for performing asynchronous I/O
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_setup(u32 entries , struct io_uring_params * params );
+```
+
+# DESCRIPTION
+
+The **io_uring_setup**(2) system call sets up a submission queue (SQ)
+and completion queue (CQ) with at least *entries* entries, and returns a
+file descriptor which can be used to perform subsequent operations on
+the io_uring instance. The submission and completion queues are shared
+between userspace and the kernel, which eliminates the need to copy data
+when initiating and completing I/O.
+
+*params* is used by the application to pass options to the kernel, and
+by the kernel to convey information about the ring buffers.
+
+``` text
+struct io_uring_params {
+ __u32 sq_entries;
+ __u32 cq_entries;
+ __u32 flags;
+ __u32 sq_thread_cpu;
+ __u32 sq_thread_idle;
+ __u32 features;
+ __u32 wq_fd;
+ __u32 resv[3];
+ struct io_sqring_offsets sq_off;
+ struct io_cqring_offsets cq_off;
+};
+```
+
+The *flags*, *sq_thread_cpu*, and *sq_thread_idle* fields are used to
+configure the io_uring instance. *flags* is a bit mask of 0 or more of
+the following values ORed together:
+
+**IORING_SETUP_IOPOLL**
+
+: Perform busy-waiting for an I/O completion, as opposed to getting
+ notifications via an asynchronous IRQ (Interrupt Request). The file
+ system (if any) and block device must support polling in order for
+ this to work. Busy-waiting provides lower latency, but may consume
+ more CPU resources than interrupt driven I/O. Currently, this feature
+ is usable only on a file descriptor opened using the **O_DIRECT** flag
+ (if using the **IORING_OP\_{READ,WRITE}(V)(\_FIXED)** opcodes). When a
+ read or write is submitted to a polled context, the application must
+ poll for completions on the CQ ring by calling **io_uring_enter**(2).
+ Most non-polled I/O requests are forbidden on **IORING_SETUP_IOPOLL**
+ io_uring instances (see **io_uring_setup_flags**(7) for the allowed
+ opcodes).
+
+ This is only applicable for storage devices for now, and the storage
+ device must be configured for polling. How to do that depends on the
+ device type in question. For NVMe devices, the nvme driver must be
+ loaded with the *poll_queues* parameter set to the desired number of
+ polling queues. The polling queues will be shared appropriately
+ between the CPUs in the system, if the number is less than the number
+ of online CPU threads.
+
+**IORING_SETUP_HYBRID_IOPOLL**
+
+: This flag must be used with **IORING_SETUP_IOPOLL** flag. Hybrid io
+ polling is a feature based on iopoll, it differs from strict polling
+ in that it will delay a bit before doing completion side polling, to
+ avoid wasting too much CPU resources. Like **IOPOLL** , it requires
+ that devices support polling.
+
+**IORING_SETUP_SQPOLL**
+
+: When this flag is specified, a kernel thread is created to perform
+ submission queue polling. An io_uring instance configured in this way
+ enables an application to issue I/O without ever context switching
+ into the kernel. By using the submission queue to fill in new
+ submission queue entries and watching for completions on the
+ completion queue, the application can submit and reap I/Os without
+ doing a single system call.
+
+ If the kernel thread is idle for more than *sq_thread_idle*
+ milliseconds, it will set the **IORING_SQ_NEED_WAKEUP** bit in the
+ *flags* field of the *struct io_sq_ring*. When this happens, the
+ application must call **io_uring_enter**(2) to wake the kernel thread.
+ If I/O is kept busy, the kernel thread will never sleep. An
+ application making use of this feature will need to guard the
+ **io_uring_enter**(2) call with the following code sequence:
+
+ ``` text
+ /*
+ * Ensure that the wakeup flag is read after the tail pointer
+ * has been written. It's important to use memory load acquire
+ * semantics for the flags read, as otherwise the application
+ * and the kernel might not agree on the consistency of the
+ * wakeup flag.
+ */
+ unsigned flags = atomic_load_relaxed(sq_ring->flags);
+ if (flags & IORING_SQ_NEED_WAKEUP)
+ io_uring_enter(fd, 0, 0, IORING_ENTER_SQ_WAKEUP);
+ ```
+
+ where *sq_ring* is a submission queue ring setup using the *struct
+ io_sqring_offsets* described below.
+
+: Note that, when using a ring setup with **IORING_SETUP_SQPOLL**, you
+ never directly call the **io_uring_enter**(2) system call. That is
+ usually taken care of by liburing\'s **io_uring_submit**(3) function.
+ It automatically determines if you are using polling mode or not and
+ deals with when your program needs to call **io_uring_enter**(2)
+ without you having to bother about it.
+
+: Note that while this may sound immediately appealing as an automatic
+ \"go faster\" flag, evaluations should be done on a case-by-case basis
+ to check if it makes sense for the application.
+
+: Before version 5.11 of the Linux kernel, to successfully use this
+ feature, the application must register a set of files to be used for
+ IO through **io_uring_register**(2) using the
+ **IORING_REGISTER_FILES** opcode. Failure to do so will result in
+ submitted IO being errored with **EBADF**. The presence of this
+ feature can be detected by the **IORING_FEAT_SQPOLL_NONFIXED** feature
+ flag. In version 5.11 and later, it is no longer necessary to register
+ files to use this feature. 5.11 also allows using this as non-root, if
+ the user has the **CAP_SYS_NICE** capability. In 5.13 this requirement
+ was also relaxed, and no special privileges are needed for SQPOLL in
+ newer kernels. Certain stable kernels older than 5.13 may also support
+ unprivileged SQPOLL.
+
+**IORING_SETUP_SQ_AFF**
+
+: If this flag is specified, then the poll thread will be bound to the
+ cpu set in the *sq_thread_cpu* field of the *struct io_uring_params*.
+ This flag is only meaningful when **IORING_SETUP_SQPOLL** is
+ specified. When cgroup setting *cpuset.cpus* changes (typically in
+ container environment), the bounded cpu set may be changed as well.
+
+**IORING_SETUP_CQSIZE**
+
+: Create the completion queue with *struct io_uring_params.cq_entries*
+ entries. The value must be greater than *entries*, and may be rounded
+ up to the next power-of-two.
+
+**IORING_SETUP_CLAMP**
+
+: If this flag is specified, and if *entries* exceeds
+ **IORING_MAX_ENTRIES**, then *entries* will be clamped at
+ **IORING_MAX_ENTRIES**. If the flag **IORING_SETUP_CQSIZE** is set,
+ and if the value of *struct io_uring_params.cq_entries* exceeds
+ **IORING_MAX_CQ_ENTRIES**, then it will be clamped at
+ **IORING_MAX_CQ_ENTRIES**.
+
+**IORING_SETUP_ATTACH_WQ**
+
+: This flag should be set in conjunction with *struct
+ io_uring_params.wq_fd* being set to an existing io_uring ring file
+ descriptor. When set, the io_uring instance being created will share
+ the asynchronous worker thread backend of the specified io_uring ring,
+ rather than create a new separate thread pool. Additionally the sq
+ polling thread will be shared, if **IORING_SETUP_SQPOLL** is set.
+
+**IORING_SETUP_R_DISABLED**
+
+: If this flag is specified, the io_uring ring starts in a disabled
+ state. In this state, restrictions can be registered, but submissions
+ are not allowed. See **io_uring_register**(2) for details on how to
+ enable the ring. Available since 5.10.
+
+**IORING_SETUP_SUBMIT_ALL**
+
+: Normally io_uring stops submitting a batch of requests, if one of
+ these requests results in an error. This can cause submission of less
+ than what is expected, if a request ends in error while being
+ submitted. If the ring is created with this flag,
+ **io_uring_enter**(2) will continue submitting requests even if it
+ encounters an error submitting a request. CQEs are still posted for
+ errored request regardless of whether or not this flag is set at ring
+ creation time, the only difference is if the submit sequence is halted
+ or continued when an error is observed. Available since 5.18.
+
+**IORING_SETUP_COOP_TASKRUN**
+
+: By default, io_uring will interrupt a task running in userspace when a
+ completion event comes in. This is to ensure that completions run in a
+ timely manner. For a lot of use cases, this is overkill and can cause
+ reduced performance from both the inter-processor interrupt used to do
+ this, the kernel/user transition, the needless interruption of the
+ tasks userspace activities, and reduced batching if completions come
+ in at a rapid rate. Most applications don\'t need the forceful
+ interruption, as the events are processed at any kernel/user
+ transition. The exception are setups where the application uses
+ multiple threads operating on the same ring, where the application
+ waiting on completions isn\'t the one that submitted them. For most
+ other use cases, setting this flag will improve performance. Available
+ since 5.19.
+
+**IORING_SETUP_TASKRUN_FLAG**
+
+: Used in conjunction with **IORING_SETUP_COOP_TASKRUN** or
+ **IORING_SETUP_DEFER_TASKRUN**, this provides a flag,
+ **IORING_SQ_TASKRUN**, which is set in the SQ ring *flags* whenever
+ completions are pending that should be processed. liburing will check
+ for this flag even when doing **io_uring_peek_cqe**(3) and enter the
+ kernel to process them, and applications can do the same. This makes
+ **IORING_SETUP_TASKRUN_FLAG** safe to use even when applications rely
+ on a peek style operation on the CQ ring to see if anything might be
+ pending to reap. Available since 5.19.
+
+**IORING_SETUP_SQE128**
+
+: If set, io_uring will use 128-byte SQEs rather than the normal 64-byte
+ sized variant. This is a requirement for using certain request types,
+ as of 5.19 only the **IORING_OP_URING_CMD** passthrough command for
+ NVMe passthrough needs this. Available since 5.19.
+
+**IORING_SETUP_CQE32**
+
+: If set, io_uring will use 32-byte CQEs rather than the normal 16-byte
+ sized variant. This is a requirement for using certain request types,
+ as of 5.19 only the **IORING_OP_URING_CMD** passthrough command for
+ NVMe passthrough needs this. Also see **IORING_SETUP_CQE_MIXED** for
+ an alternative to this flag. Available since 5.19.
+
+**IORING_SETUP_SINGLE_ISSUER**
+
+: A hint to the kernel that only a single task (or thread) will submit
+ requests, which is used for internal optimisations. The submission
+ task is either the task that created the ring, or if
+ **IORING_SETUP_R_DISABLED** is specified then it is the task that
+ enables the ring through **io_uring_register**(2)**.** The kernel
+ enforces this rule, failing requests with **-EEXIST** if the
+ restriction is violated. Note that when **IORING_SETUP_SQPOLL** is set
+ it is considered that the polling task is doing all submissions on
+ behalf of the userspace and so it always complies with the rule
+ disregarding how many userspace tasks do **io_uring_enter**(2).
+ Available since 6.0.
+
+**IORING_SETUP_DEFER_TASKRUN**
+
+: By default, io_uring will process all outstanding work at the end of
+ any system call or thread interrupt. This can delay the application
+ from making other progress. Setting this flag will hint to io_uring
+ that it should defer work until an **io_uring_enter**(2) call with the
+ **IORING_ENTER_GETEVENTS** flag set. This allows the application to
+ request work to run just before it wants to process completions. This
+ flag requires the **IORING_SETUP_SINGLE_ISSUER** flag to be set, and
+ also enforces that the call to **io_uring_enter**(2) is called from
+ the same thread that submitted requests. Note that if this flag is set
+ then it is the application\'s responsibility to periodically trigger
+ work (for example via any of the CQE waiting functions) or else
+ completions may not be delivered. Available since 6.1.
+
+**IORING_SETUP_NO_MMAP**
+
+: By default, io_uring allocates kernel memory that callers must
+ subsequently **mmap**(2). If this flag is set, io_uring instead uses
+ caller-allocated buffers; *p-\>cq_off.user_addr* must point to the
+ memory for the sq/cq rings, and *p-\>sq_off.user_addr* must point to
+ the memory for the sqes. Each allocation must be contiguous memory.
+ Typically, callers should allocate this memory by using **mmap**(2) to
+ allocate a huge page. If this flag is set, a subsequent attempt to
+ **mmap**(2) the io_uring file descriptor will fail. Available since
+ 6.5.
+
+**IORING_SETUP_REGISTERED_FD_ONLY**
+
+: If this flag is set, io_uring will register the ring file descriptor,
+ and return the registered descriptor index, without ever allocating an
+ unregistered file descriptor. The caller will need to use
+ **IORING_REGISTER_USE_REGISTERED_RING** when calling
+ **io_uring_register**(2). This flag only makes sense when used
+ alongside with **IORING_SETUP_NO_MMAP**, which also needs to be set.
+ Available since 6.5.
+
+**IORING_SETUP_NO_SQARRAY**
+
+: If this flag is set, entries in the submission queue will be submitted
+ in order, wrapping around to the first entry after reaching the end of
+ the queue. In other words, there will be no more indirection via the
+ array of submission entries, and the queue will be indexed directly by
+ the submission queue tail and the range of indexed represented by it
+ modulo queue size. Subsequently, the user should not map the array of
+ submission queue entries, and the corresponding offset in *struct
+ io_sqring_offsets* will be set to zero. Available since 6.6.
+
+**IORING_SETUP_CQE_MIXED**
+
+: If this flag is set, the ring supports posting both the normal 16b
+ sized CQEs as well as the larger 32b CQEs. Normally a ring is setup to
+ only allow posting of normal 16b CQEs, or if **IORING_SETUP_CQE32**
+ has been set, only 32b CQEs. With this flag, the kernel may post both
+ types. If a 32b CQE is posted, the CQE *flags* member will have
+ **IORING_CQE_F_32** set to indicate that this CQE is of the larger
+ type. The kernel may also set **IORING_CQE_F_SKIP** in the CQE *flags*
+ member, in case it needs to post a filler 16b CQE. This will happen if
+ a 32b CQE needs posting and the current CQ ring offset is such that
+ the 32b CQE would wrap around. Applications should simply skip/ignore
+ such CQEs, they contain no information and serve only as placeholder
+ to facilitate advancing the CQ ring such that a large CQE can get
+ posted. The use case of the **IORING_SETUP_CQE_MIXED** flag is to
+ allow more efficient setups of workloads that may post both normal and
+ large CQEs. Opcodes that previously required the use of
+ **IORING_SETUP_CQE32** may now use this flag instead, and potentially
+ save some memory for the CQ ring. If used with liburing 2.12 or newer,
+ the handling of variably sized CQEs is fully transparent. Available
+ since 6.18.
+
+**IORING_SETUP_SQ_REWIND**
+
+: If this flag is set, the kernel ignores the submission queue head and
+ tail and instead fetches SQEs starting from index 0. The application
+ places all SQEs at the beginning of the SQ ring before each submit
+ call, and the *sq_entries* parameter to **io_uring_enter**(2)
+ determines how many SQEs are submitted. This is a non-circular queue
+ mode where the kernel always starts from the beginning.
+
+This flag requires **IORING_SETUP_NO_SQARRAY** to be set. It is not
+compatible with **IORING_SETUP_SQPOLL**.
+
+This mode helps keep SQEs hot in cache by always accessing the same
+memory locations at the start of the ring, which can improve performance
+for workloads that submit small batches frequently. Available since 7.0.
+
+If no flags are specified, the io_uring instance is setup for interrupt
+driven I/O. I/O may be submitted using **io_uring_enter**(2) and can be
+reaped by polling the completion queue.
+
+The *resv* array must be initialized to zero.
+
+*features* is filled in by the kernel, which specifies various features
+supported by current kernel version.
+
+**IORING_FEAT_SINGLE_MMAP**
+
+: If this flag is set, the two SQ and CQ rings can be mapped with a
+ single **mmap**(2) call. The SQEs must still be allocated separately.
+ This brings the necessary **mmap**(2) calls down from three to two.
+ Available since kernel 5.4.
+
+**IORING_FEAT_NODROP**
+
+: If this flag is set, io_uring supports almost never dropping
+ completion events. A dropped event can only occur if the kernel runs
+ out of memory, in which case you have worse problems than a lost
+ event. Your application and others will likely get OOM killed anyway.
+ If a completion event occurs and the CQ ring is full, the kernel
+ stores the event internally until such a time that the CQ ring has
+ room for more entries. In earlier kernels, if this overflow condition
+ is entered, attempting to submit more IO would fail with the
+ **-EBUSY** error value, if it can\'t flush the overflown events to the
+ CQ ring. If this happens, the application must reap events from the CQ
+ ring and attempt the submit again. If the kernel has no free memory to
+ store the event internally it will be visible by an increase in the
+ overflow value on the cqring. Available since kernel 5.5. Additionally
+ **io_uring_enter**(2) will return **-EBADR** the next time it would
+ otherwise sleep waiting for completions (since kernel 5.19).
+
+**IORING_FEAT_SUBMIT_STABLE**
+
+: If this flag is set, applications can be certain that any data for
+ async offload has been consumed when the kernel has consumed the SQE.
+ Available since kernel 5.5.
+
+**IORING_FEAT_RW_CUR_POS**
+
+: If this flag is set, applications can specify *offset* == **-1** with
+ **IORING_OP\_{READV,WRITEV}**, **IORING_OP\_{READ,WRITE}\_FIXED**, and
+ **IORING_OP\_{READ,WRITE}** to mean current file position, which
+ behaves like **preadv2**(2) and **pwritev2**(2) with *offset* ==
+ **-1**. It\'ll use (and update) the current file position. This
+ obviously comes with the caveat that if the application has multiple
+ reads or writes in flight, then the end result will not be as
+ expected. This is similar to threads sharing a file descriptor and
+ doing IO using the current file position. Available since kernel 5.6.
+
+**IORING_FEAT_CUR_PERSONALITY**
+
+: If this flag is set, then io_uring guarantees that both sync and async
+ execution of a request assumes the credentials of the task that called
+ **io_uring_enter**(2) to queue the requests. If this flag isn\'t set,
+ then requests are issued with the credentials of the task that
+ originally registered the io_uring. If only one task is using a ring,
+ then this flag doesn\'t matter as the credentials will always be the
+ same. Note that this is the default behavior, tasks can still register
+ different personalities through **io_uring_register**(2) with
+ **IORING_REGISTER_PERSONALITY** and specify the personality to use in
+ the sqe. Available since kernel 5.6.
+
+**IORING_FEAT_FAST_POLL**
+
+: If this flag is set, then io_uring supports using an internal poll
+ mechanism to drive data/space readiness. This means that requests that
+ cannot read or write data to a file no longer need to be punted to an
+ async thread for handling, instead they will begin operation when the
+ file is ready. This is similar to doing poll + read/write in
+ userspace, but eliminates the need to do so. If this flag is set,
+ requests waiting on space/data consume a lot less resources doing so
+ as they are not blocking a thread. Available since kernel 5.7.
+
+**IORING_FEAT_POLL_32BITS**
+
+: If this flag is set, the **IORING_OP_POLL_ADD** command accepts the
+ full 32-bit range of epoll based flags. Most notably
+ **EPOLLEXCLUSIVE** which allows exclusive (waking single waiters)
+ behavior. Available since kernel 5.9.
+
+**IORING_FEAT_SQPOLL_NONFIXED**
+
+: If this flag is set, the **IORING_SETUP_SQPOLL** feature no longer
+ requires the use of fixed files. Any normal file descriptor can be
+ used for IO commands without needing registration. Available since
+ kernel 5.11.
+
+**IORING_FEAT_EXT_ARG**
+
+: If this flag is set, then the **io_uring_enter**(2) system call
+ supports passing in an extended argument instead of just the
+ *sigset_t* of earlier kernels. This extended argument is of type
+ *struct io_uring_getevents_arg* and allows the caller to pass in both
+ a *sigset_t* and a timeout argument for waiting on events. The struct
+ layout is as follows:
+
+``` text
+struct io_uring_getevents_arg {
+ __u64 sigmask;
+ __u32 sigmask_sz;
+ __u32 pad;
+ __u64 ts;
+};
+```
+
+and a pointer to this struct must be passed in if
+**IORING_ENTER_EXT_ARG** is set in the flags for the enter system call.
+Available since kernel 5.11.
+
+**IORING_FEAT_NATIVE_WORKERS**
+
+: If this flag is set, io_uring is using native workers for its async
+ helpers. Previous kernels used kernel threads that assumed the
+ identity of the original io_uring owning task, but later kernels will
+ actively create what looks more like regular process threads instead.
+ Available since kernel 5.12.
+
+**IORING_FEAT_RSRC_TAGS**
+
+: If this flag is set, then io_uring supports a variety of features
+ related to fixed files and buffers. In particular, it indicates that
+ registered buffers can be updated in-place, whereas before the full
+ set would have to be unregistered first. Available since kernel 5.13.
+
+**IORING_FEAT_CQE_SKIP**
+
+: If this flag is set, then io_uring supports setting
+ **IOSQE_CQE_SKIP_SUCCESS** in the submitted SQE, indicating that no
+ CQE should be generated for this SQE if it executes normally. If an
+ error happens processing the SQE, a CQE with the appropriate error
+ value will still be generated. Available since kernel 5.17.
+
+**IORING_FEAT_LINKED_FILE**
+
+: If this flag is set, then io_uring supports sane assignment of files
+ for SQEs that have dependencies. For example, if a chain of SQEs are
+ submitted with **IOSQE_IO_LINK**, then kernels without this flag will
+ prepare the file for each link upfront. If a previous link opens a
+ file with a known index, e.g. if direct descriptors are used with open
+ or accept, then file assignment needs to happen post execution of that
+ SQE. If this flag is set, then the kernel will defer file assignment
+ until execution of a given request is started. Available since kernel
+ 5.17.
+
+**IORING_FEAT_REG_REG_RING**
+
+: If this flag is set, then io_uring supports calling
+ **io_uring_register**(2) using a registered ring fd, via
+ **IORING_REGISTER_USE_REGISTERED_RING**. Available since kernel 6.3.
+
+**IORING_FEAT_MIN_TIMEOUT**
+
+: If this flag is set, then io_uring supports passing in a minimum batch
+ wait timeout. See **io_uring_submit_and_wait_min_timeout**(3) for more
+ details.
+
+**IORING_FEAT_RECVSEND_BUNDLE**
+
+: If this flag is set, then io_uring supports bundled send and recv
+ operations. See **io_uring_prep_send_bundle**(3) for more information.
+ Also implies support for provided buffers in send operations.
+
+The rest of the fields in the *struct io_uring_params* are filled in by
+the kernel, and provide the information necessary to memory map the
+submission queue, completion queue, and the array of submission queue
+entries. *sq_entries* specifies the number of submission queue entries
+allocated. *sq_off* describes the offsets of various ring buffer fields:
+
+``` text
+struct io_sqring_offsets {
+ __u32 head;
+ __u32 tail;
+ __u32 ring_mask;
+ __u32 ring_entries;
+ __u32 flags;
+ __u32 dropped;
+ __u32 array;
+ __u32 resv1;
+ __u64 user_addr;
+};
+```
+
+Taken together, *sq_entries* and *sq_off* provide all of the information
+necessary for accessing the submission queue ring buffer and the
+submission queue entry array. The submission queue can be mapped with a
+call like:
+
+``` text
+ptr = mmap(0, sq_off.array + sq_entries * sizeof(__u32),
+ PROT_READ|PROT_WRITE, MAP_SHARED|MAP_POPULATE,
+ ring_fd, IORING_OFF_SQ_RING);
+```
+
+where *sq_off* is the *io_sqring_offsets* structure, and *ring_fd* is
+the file descriptor returned from **io_uring_setup**(2). The addition of
+*sq_off.array* to the length of the region accounts for the fact that
+the ring is located at the end of the data structure. As an example, the
+ring buffer head pointer can be accessed by adding *sq_off.head* to the
+address returned from **mmap**(2):
+
+``` text
+head = ptr + sq_off.head;
+```
+
+The *flags* field is used by the kernel to communicate state information
+to the application. Currently, it is used to inform the application when
+a call to **io_uring_enter**(2) is necessary. See the documentation for
+the **IORING_SETUP_SQPOLL** flag above. The *dropped* member is
+incremented for each invalid submission queue entry encountered in the
+ring buffer.
+
+The head and tail track the ring buffer state. The tail is incremented
+by the application when submitting new I/O, and the head is incremented
+by the kernel when the I/O has been successfully submitted. Determining
+the index of the head or tail into the ring is accomplished by applying
+a mask:
+
+``` text
+index = tail & ring_mask;
+```
+
+The array of submission queue entries is mapped with:
+
+``` text
+sqentries = mmap(0, sq_entries * sizeof(struct io_uring_sqe),
+ PROT_READ|PROT_WRITE, MAP_SHARED|MAP_POPULATE,
+ ring_fd, IORING_OFF_SQES);
+```
+
+The completion queue is described by *cq_entries* and *cq_off* shown
+here:
+
+``` text
+struct io_cqring_offsets {
+ __u32 head;
+ __u32 tail;
+ __u32 ring_mask;
+ __u32 ring_entries;
+ __u32 overflow;
+ __u32 cqes;
+ __u32 flags;
+ __u32 resv1;
+ __u64 user_addr;
+};
+```
+
+The completion queue is simpler, since the entries are not separated
+from the queue itself, and can be mapped with:
+
+``` text
+ptr = mmap(0, cq_off.cqes + cq_entries * sizeof(struct io_uring_cqe),
+ PROT_READ|PROT_WRITE, MAP_SHARED|MAP_POPULATE, ring_fd,
+ IORING_OFF_CQ_RING);
+```
+
+Closing the file descriptor returned by **io_uring_setup**(2) will free
+all resources associated with the io_uring context. Note that this may
+happen asynchronously within the kernel, so it is not guaranteed that
+resources are freed immediately.
+
+# RETURN VALUE
+
+**io_uring_setup**(2) returns a new file descriptor on success. The
+application may then provide the file descriptor in a subsequent
+**mmap**(2) call to map the submission and completion queues, or to the
+**io_uring_register**(2) or **io_uring_enter**(2) system calls.
+
+On error, a negative error code is returned. The caller should not rely
+on *errno* variable.
+
+# ERRORS
+
+**EFAULT**
+
+: *params* is outside your accessible address space.
+
+**EINVAL**
+
+: The resv array contains non-zero data, p.flags contains an unsupported
+ flag, *entries* is out of bounds, **IORING_SETUP_SQ_AFF** was
+ specified, but **IORING_SETUP_SQPOLL** was not, or
+ **IORING_SETUP_CQSIZE** was specified, but
+ *io_uring_params.cq_entries* was invalid.
+ **IORING_SETUP_REGISTERED_FD_ONLY** was specified, but
+ **IORING_SETUP_NO_MMAP** was not.
+
+**EMFILE**
+
+: The per-process limit on the number of open file descriptors has been
+ reached (see the description of **RLIMIT_NOFILE** in
+ **getrlimit**(2)).
+
+**ENFILE**
+
+: The system-wide limit on the total number of open files has been
+ reached.
+
+**ENOMEM**
+
+: Insufficient kernel resources are available.
+
+**EPERM**
+
+: **IORING_SETUP_SQPOLL** was specified, but the effective user ID of
+ the caller did not have sufficient privileges.
+
+**EPERM**
+
+: */proc/sys/kernel/io_uring_disabled* has the value 2, or it has the
+ value 1 and the calling process does not hold the **CAP_SYS_ADMIN**
+ capability or is not a member of */proc/sys/kernel/io_uring_group*.
+
+**ENXIO**
+
+: **IORING_SETUP_ATTACH_WQ** was set, but *params.wq_fd* did not refer
+ to an io_uring instance or refers to an instance that is in the
+ process of shutting down.
+
+# SEE ALSO
+
+**io_uring_register**(2), **io_uring_enter**(2)
diff --git a/man/io_uring_setup_buf_ring.3 b/man/io_uring_setup_buf_ring.3
deleted file mode 100644
index 63175ee4..00000000
--- a/man/io_uring_setup_buf_ring.3
+++ /dev/null
@@ -1,94 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_setup_buf_ring 3 "Mar 07, 2023" "liburing-2.4" "liburing Manual"
-.SH NAME
-io_uring_setup_buf_ring \- setup and register buffer ring for provided buffers
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "struct io_uring_buf_ring *io_uring_setup_buf_ring(struct io_uring *" ring ",
-.BI " unsigned int " nentries ",
-.BI " int " bgid ",
-.BI " unsigned int " flags ",
-.BI " int *" err ");"
-.BI "
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_setup_buf_ring (3)
-function registers a shared buffer ring to be used with provided buffers. For
-the request types that support it, provided buffers are given to the ring and
-one is selected by a request if it has
-.B IOSQE_BUFFER_SELECT
-set in the SQE
-.IR flags ,
-when the request is ready to receive data. This allows both clear ownership
-of the buffer lifetime, and a way to have more read/receive type of operations
-in flight than buffers available.
-
-The
-.I ring
-argument must be a pointer to the ring for which the provided buffer ring is being
-registered,
-.I nentries
-is the number of entries requested in the buffer ring. This argument must be
-a power-of 2 in size, and can be up to 32768 in size.
-.I bgid
-is the chosen buffer group ID,
-.I flags
-are modifier flags for the operation, and
-.I *err
-is a pointer to an integer for the error value if any part of the ring
-allocation and registration fails.
-
-The
-.I flags
-argument can be set to one of the following values:
-.TP
-.B IOU_PBUF_RING_INC
-The buffers in this ring can be incrementally consumed. With partial
-consumption, each completion of a given buffer ID will continue where the
-previous one left off, or from the start if no completions have been seen yet.
-When more completions should be expected for a given buffer ID, the CQE will
-have
-.B IORING_CQE_F_BUF_MORE
-set in the
-.I flags
-member. Available since 6.12.
-.PP
-
-Under the covers, this function uses
-.BR io_uring_register_buf_ring (3)
-to register the ring, and handles the allocation of the ring rather than
-letting the application open code it.
-
-To unregister and free a buffer group ID setup with this function, the
-application must call
-.BR io_uring_free_buf_ring (3) .
-
-Available since 5.19.
-
-.SH RETURN VALUE
-On success
-.BR io_uring_setup_buf_ring (3)
-returns a pointer to the buffer ring. On failure it returns
-.BR NULL
-and sets
-.I *err
-to -errno.
-.SH NOTES
-Note that even if the kernel supports this feature, registering a provided
-buffer ring may still fail with
-.B -EINVAL
-if the host is a 32-bit architecture and the memory being passed in resides in
-high memory.
-.SH SEE ALSO
-.BR io_uring_register_buf_ring (3),
-.BR io_uring_buf_ring_init (3),
-.BR io_uring_buf_ring_add (3),
-.BR io_uring_buf_ring_advance (3),
-.BR io_uring_buf_ring_cq_advance (3)
diff --git a/man/io_uring_setup_buf_ring.3.md b/man/io_uring_setup_buf_ring.3.md
new file mode 100644
index 00000000..4e8366da
--- /dev/null
+++ b/man/io_uring_setup_buf_ring.3.md
@@ -0,0 +1,85 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: Mar 07, 2023
+footer: liburing-2.4
+header: liburing Manual
+section: 3
+title: io_uring_setup_buf_ring
+---
+
+# NAME
+
+io_uring_setup_buf_ring - setup and register buffer ring for provided
+buffers
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ struct io_uring_buf_ring *io_uring_setup_buf_ring(struct io_uring * ring ,
+ unsigned int nentries ,
+ int bgid ,
+ unsigned int flags ,
+ int * err );
+
+```
+
+# DESCRIPTION
+
+The **io_uring_setup_buf_ring**(3) function registers a shared buffer
+ring to be used with provided buffers. For the request types that
+support it, provided buffers are given to the ring and one is selected
+by a request if it has **IOSQE_BUFFER_SELECT** set in the SQE *flags*,
+when the request is ready to receive data. This allows both clear
+ownership of the buffer lifetime, and a way to have more read/receive
+type of operations in flight than buffers available.
+
+The *ring* argument must be a pointer to the ring for which the provided
+buffer ring is being registered, *nentries* is the number of entries
+requested in the buffer ring. This argument must be a power-of 2 in
+size, and can be up to 32768 in size. *bgid* is the chosen buffer group
+ID, *flags* are modifier flags for the operation, and *\*err* is a
+pointer to an integer for the error value if any part of the ring
+allocation and registration fails.
+
+The *flags* argument can be set to one of the following values:
+
+**IOU_PBUF_RING_INC**
+
+: The buffers in this ring can be incrementally consumed. With partial
+ consumption, each completion of a given buffer ID will continue where
+ the previous one left off, or from the start if no completions have
+ been seen yet. When more completions should be expected for a given
+ buffer ID, the CQE will have **IORING_CQE_F_BUF_MORE** set in the
+ *flags* member. Available since 6.12.
+
+Under the covers, this function uses **io_uring_register_buf_ring**(3)
+to register the ring, and handles the allocation of the ring rather than
+letting the application open code it.
+
+To unregister and free a buffer group ID setup with this function, the
+application must call **io_uring_free_buf_ring**(3)**.**
+
+Available since 5.19.
+
+# RETURN VALUE
+
+On success **io_uring_setup_buf_ring**(3) returns a pointer to the
+buffer ring. On failure it returns **NULL** and sets *\*err* to -errno.
+
+# NOTES
+
+Note that even if the kernel supports this feature, registering a
+provided buffer ring may still fail with **-EINVAL** if the host is a
+32-bit architecture and the memory being passed in resides in high
+memory.
+
+# SEE ALSO
+
+**io_uring_register_buf_ring**(3), **io_uring_buf_ring_init**(3),
+**io_uring_buf_ring_add**(3), **io_uring_buf_ring_advance**(3),
+**io_uring_buf_ring_cq_advance**(3)
diff --git a/man/io_uring_setup_flags.7 b/man/io_uring_setup_flags.7
deleted file mode 100644
index 7d117c47..00000000
--- a/man/io_uring_setup_flags.7
+++ /dev/null
@@ -1,451 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_setup_flags 7 "January 18, 2025" "Linux" "Linux Programmer's Manual"
-.SH NAME
-io_uring_setup_flags \- io_uring ring setup flags overview
-.SH DESCRIPTION
-When creating an io_uring instance with
-.BR io_uring_queue_init_params (3)
-or
-.BR io_uring_setup (2),
-various flags control the ring's behavior. These flags are set in the
-.I flags
-field of
-.IR "struct io_uring_params" .
-.PP
-Choosing the right flags can significantly impact performance. This page
-provides an overview of available flags, their purposes, and common
-combinations.
-.SS Polling flags
-These flags control how I/O completion and submission polling works.
-.PP
-.B IORING_SETUP_IOPOLL
-.RS 4
-Enable I/O polling mode for file descriptors that support it. Instead of
-relying on interrupts, the kernel polls for completions. This reduces
-latency for high-performance storage devices (NVMe, etc.) but requires:
-.IP \(bu 2
-Files opened with
-.B O_DIRECT
-(if using the
-.B IORING_OP_{READ,WRITE}(V)(_FIXED)
-opcodes)
-.IP \(bu
-Hardware and drivers that support polling
-.IP \(bu
-The application to call
-.BR io_uring_enter (2)
-to reap completions (busy-polling)
-.IP \(bu
-Storage device configuration for polling support
-.PP
-Only the following opcodes are allowed on IOPOLL rings:
-.IP \(bu 2
-.B IORING_OP_NOP(128)
-.IP \(bu
-.B IORING_OP_{READ,WRITE}(V)(_FIXED)
-(if the file supports busy-polling)
-.IP \(bu
-.B IORING_OP_FILES_UPDATE
-.IP \(bu
-.B IORING_OP_{PROVIDE,REMOVE}_BUFFERS
-.IP \(bu
-.B IORING_OP_MSG_RING
-.IP \(bu
-.B IORING_OP_URING_CMD(128)
-.PP
-Since kernel 7.1, an
-.B IORING_OP_URING_CMD(128)
-request will use busy-polling if the file supports it (i.e., NVMe passthrough
-I/O commands).
-Previously,
-.B IORING_OP_URING_CMD(128)
-was only allowed on files that supported busy-polling.
-.PP
-Using IOPOLL generally requires storage device setup. For NVMe devices,
-the kernel parameter
-.B nvme.poll_queues=X
-must be set, where X is the number of completion queues on the NVMe
-device to set aside for polling operations.
-.RE
-.PP
-.B IORING_SETUP_SQPOLL
-.RS 4
-Create a kernel thread that polls the submission queue. Eliminates the
-need for system calls to submit I/O. See
-.BR io_uring_sqpoll (7)
-for details.
-.RE
-.PP
-.B IORING_SETUP_SQ_AFF
-.RS 4
-Pin the SQPOLL thread to a specific CPU. Requires
-.BR IORING_SETUP_SQPOLL .
-The CPU is specified in
-.I sq_thread_cpu
-of
-.IR "struct io_uring_params" .
-.RE
-.PP
-.B IORING_SETUP_HYBRID_IOPOLL
-.RS 4
-Enable hybrid polling mode. Instead of pure busy-polling, the kernel
-uses an adaptive approach that may sleep briefly, reducing CPU usage
-while still providing low latency. This is a middle ground between
-interrupt-driven and pure polling modes.
-.RE
-.SS Task run flags
-These flags control when and how completion processing runs.
-.PP
-.B IORING_SETUP_COOP_TASKRUN
-.RS 4
-Disable interrupting the application for completion processing. Normally,
-the kernel signals the application when completions are ready, which can
-interrupt system calls. With this flag, completions are only processed
-when the application returns to userspace from any system call, not just
-io_uring-related ones. This means completions may be processed after
-.BR read (2),
-.BR write (2),
-.BR poll (2),
-or any other syscall returns.
-.PP
-This improves performance by eliminating asynchronous interrupts but
-requires the application to regularly enter the kernel to process
-completions. Recommended for most applications that have an event loop.
-.RE
-.PP
-.B IORING_SETUP_TASKRUN_FLAG
-.RS 4
-When completions are pending, set
-.B IORING_SQ_TASKRUN
-in the SQ ring flags. This allows applications to check if there is
-completion work to process without making a system call. Typically used
-with
-.BR IORING_SETUP_COOP_TASKRUN .
-.RE
-.PP
-.B IORING_SETUP_DEFER_TASKRUN
-.RS 4
-Defer completion task work to when the application explicitly enters the
-kernel via
-.BR io_uring_enter (2).
-Unlike
-.BR IORING_SETUP_COOP_TASKRUN ,
-completions are only processed during io_uring-related syscalls, not on
-return from arbitrary syscalls. This provides the tightest and most
-predictable control over when completion processing occurs, as well as
-optimal cache behavior since work runs in the application's context.
-.PP
-This flag should be considered the default mode for applications setting
-up a ring. It requires
-.B IORING_SETUP_SINGLE_ISSUER
-and a ring created per-thread. The application must regularly call
-.BR io_uring_enter (2)
-(via
-.BR io_uring_submit (3),
-.BR io_uring_wait_cqe (3),
-or similar) to process deferred work; failing to do so will stall
-completions.
-.PP
-Some features require this flag:
-.IP \(bu 2
-Ring resizing
-.RB ( io_uring_register_resize_rings (3))
-.IP \(bu
-Zero-copy receive
-.RB ( IORING_OP_RECV_ZC )
-.RE
-.PP
-.B IORING_SETUP_SINGLE_ISSUER
-.RS 4
-Hint that only one task will submit requests to this ring. Enables
-internal optimizations including reduced locking overhead. The first
-task to submit a request becomes the designated submitter; others
-attempting to submit will get
-.BR -EEXIST .
-.PP
-Each thread or task having its own ring is the idiomatic use case for
-io_uring. Sharing a ring between multiple threads or tasks is
-discouraged as it requires additional synchronization and prevents
-many optimizations. Applications should create a ring per thread rather
-than sharing rings.
-.RE
-.SS Ring sizing flags
-These flags control the size and layout of the submission and completion
-queues.
-.PP
-.B IORING_SETUP_CQSIZE
-.RS 4
-Override the default completion queue size. By default, the CQ has twice
-as many entries as the SQ. Set
-.I cq_entries
-in
-.I struct io_uring_params
-to specify a custom CQ size. Must be a power of 2.
-.PP
-Larger CQ sizes are useful when the application may submit many requests
-before processing completions, avoiding CQ overflow.
-.RE
-.PP
-.B IORING_SETUP_CLAMP
-.RS 4
-Clamp the SQ and CQ sizes to the maximum allowed values instead of
-returning
-.B -EINVAL
-if the requested sizes are too large. Useful when the application wants
-the largest possible rings without querying limits.
-.RE
-.PP
-.B IORING_SETUP_SQE128
-.RS 4
-Use 128-byte SQEs instead of the default 64 bytes. Required for some
-operations that need extra space, such as
-.B IORING_OP_URING_CMD
-passthrough commands.
-.RE
-.PP
-.B IORING_SETUP_CQE32
-.RS 4
-Use 32-byte CQEs instead of the default 16 bytes. Required for
-operations that return extra data, such as some passthrough commands
-or when using
-.BR IORING_OP_MSG_RING .
-.RE
-.PP
-.B IORING_SETUP_NO_SQARRAY
-.RS 4
-Do not create the SQ array. The SQ array is a level of indirection that
-allows SQEs to be submitted in a different order than they appear in
-the ring. Most applications submit SQEs in order and do not need this.
-This flag saves memory and is required for some modes like
-.BR IORING_SETUP_REGISTERED_FD_ONLY .
-.RE
-.PP
-.B IORING_SETUP_SQ_REWIND
-.RS 4
-Use non-circular submission queue mode. The kernel ignores the SQ head
-and tail pointers and instead fetches SQEs starting from index 0 on each
-submit. The application places all SQEs at the beginning of the ring
-before calling
-.BR io_uring_enter (2),
-and the
-.I sq_entries
-parameter determines how many SQEs are submitted.
-.PP
-Requires
-.BR IORING_SETUP_NO_SQARRAY .
-Not compatible with
-.BR IORING_SETUP_SQPOLL .
-.PP
-This mode keeps SQEs hot in cache by always accessing the same memory
-locations at the start of the ring, improving performance for workloads
-that submit small batches frequently.
-.RE
-.PP
-.B IORING_SETUP_CQE_MIXED
-.RS 4
-Allow the ring to return a mix of 16-byte and 32-byte CQEs, controlled
-per-request. When a request needs a 32-byte CQE, it sets
-.B IOSQE_BIG_CQE
-in its flags. Otherwise, a 16-byte CQE is used. Requires
-.BR IORING_SETUP_CQE32 .
-.PP
-This is useful when certain operations require 32-byte CQEs (such as
-some passthrough commands) but most operations do not. Using mixed mode
-instead of
-.B IORING_SETUP_CQE32
-alone provides efficiency benefits in terms of memory bandwidth and
-usage, since the smaller 16-byte CQEs are used for operations that do
-not need the extra space.
-.RE
-.PP
-.B IORING_SETUP_SQE_MIXED
-.RS 4
-Allow the ring to accept a mix of 64-byte and 128-byte SQEs. When a
-request needs a 128-byte SQE, it sets
-.B IOSQE_BIG_SQE
-in its flags. Requires
-.BR IORING_SETUP_SQE128 .
-.PP
-This is useful when certain operations require 128-byte SQEs (such as
-.BR IORING_OP_URING_CMD )
-but most operations do not. Using mixed mode instead of
-.B IORING_SETUP_SQE128
-alone provides efficiency benefits in terms of memory bandwidth and
-usage, since the smaller 64-byte SQEs are used for operations that do
-not need the extra space.
-.RE
-.SS Memory and setup flags
-These flags control memory allocation and ring initialization.
-.PP
-.B IORING_SETUP_NO_MMAP
-.RS 4
-The application provides its own memory for the rings instead of the
-kernel allocating and the application mmap'ing it. The application
-fills in
-.IR sq_off.user_addr ,
-.IR cq_off.user_addr ,
-and
-.I sq_sqes.user_addr
-in
-.I struct io_uring_params
-with addresses of application-allocated memory.
-.PP
-This is useful for placing rings in specific memory (huge pages, shared
-memory, etc.) or for creating rings without mmap.
-.RE
-.PP
-.B IORING_SETUP_REGISTERED_FD_ONLY
-.RS 4
-The ring file descriptor is not installed in the process's file
-descriptor table. Instead, a "registered ring" index is returned in
-.I ring_fd
-that can be used with
-.BR io_uring_enter (2)
-when
-.B IORING_ENTER_REGISTERED_RING
-is set. This reduces per-operation overhead.
-.PP
-Requires
-.BR IORING_SETUP_NO_SQARRAY .
-The application must use
-.BR io_uring_register_ring_fd (3)
-to use the ring or access it via the registered index.
-.RE
-.PP
-.B IORING_SETUP_R_DISABLED
-.RS 4
-Create the ring in a disabled state. The ring will not accept submissions
-until it is enabled via
-.BR io_uring_enable_rings (3).
-This is useful when setting up restrictions or registered resources
-before allowing I/O. See
-.BR io_uring_register_restrictions (3).
-.RE
-.SS Submission flags
-These flags control submission behavior.
-.PP
-.B IORING_SETUP_SUBMIT_ALL
-.RS 4
-Continue processing submissions even if one fails. Normally, if an
-SQE fails during submission (not execution), subsequent SQEs in the
-same submit call are not processed. With this flag, all SQEs are
-processed regardless of earlier failures.
-.PP
-The failed SQE still generates a CQE with the error; this flag only
-affects whether subsequent SQEs are submitted. This is probably the
-behavior most applications expect, since CQEs are generated for failed
-submissions anyway and the application must handle them regardless.
-.RE
-.SS Workqueue flags
-These flags control the async worker threads.
-.PP
-.B IORING_SETUP_ATTACH_WQ
-.RS 4
-Share the async worker thread pool with another ring. Set
-.I wq_fd
-in
-.I struct io_uring_params
-to the file descriptor of the ring to share with. This reduces resource
-usage when an application uses multiple rings.
-.PP
-When combined with
-.BR IORING_SETUP_SQPOLL ,
-the SQPOLL thread is also shared.
-.RE
-.SS Common flag combinations
-.PP
-.B High-performance single-threaded application:
-.RS 4
-.PP
-.in +4n
-.EX
-\&.flags = IORING_SETUP_SINGLE_ISSUER |
- IORING_SETUP_DEFER_TASKRUN |
- IORING_SETUP_COOP_TASKRUN
-.EE
-.in
-.PP
-This combination provides the best latency and throughput for applications
-where each thread has its own ring and processes completions in a dedicated
-event loop.
-.RE
-.PP
-.B Low-latency storage with polling:
-.RS 4
-.PP
-.in +4n
-.EX
-\&.flags = IORING_SETUP_IOPOLL |
- IORING_SETUP_SINGLE_ISSUER |
- IORING_SETUP_DEFER_TASKRUN
-.EE
-.in
-.PP
-For NVMe or other devices that support polling, this eliminates interrupt
-overhead. Combined with DEFER_TASKRUN for optimal completion handling.
-.RE
-.PP
-.B System call-free submission:
-.RS 4
-.PP
-.in +4n
-.EX
-\&.flags = IORING_SETUP_SQPOLL |
- IORING_SETUP_SQ_AFF
-\&.sq_thread_cpu = preferred_cpu
-\&.sq_thread_idle = 1000
-.EE
-.in
-.PP
-For workloads that benefit from eliminating submission syscall overhead.
-See
-.BR io_uring_sqpoll (7).
-.RE
-.PP
-.B Multiple rings sharing resources:
-.RS 4
-.PP
-.in +4n
-.EX
-/* First ring */
-p1.flags = IORING_SETUP_SQPOLL;
-
-/* Subsequent rings */
-p2.flags = IORING_SETUP_SQPOLL | IORING_SETUP_ATTACH_WQ;
-p2.wq_fd = ring1_fd;
-.EE
-.in
-.PP
-Reduces kernel thread and workqueue overhead when using multiple rings.
-.RE
-.SH NOTES
-.IP \(bu 2
-Not all flag combinations are valid. The kernel returns
-.B -EINVAL
-for incompatible combinations.
-.IP \(bu
-Some flags require specific kernel versions. Check
-.BR io_uring_setup (2)
-for version requirements.
-.IP \(bu
-The
-.BR io_uring_queue_init_params (3)
-function handles the complexity of ring setup. Using the raw
-.BR io_uring_setup (2)
-syscall requires careful mmap setup.
-.IP \(bu
-For most applications with a proper event loop,
-.B IORING_SETUP_DEFER_TASKRUN
-combined with
-.B IORING_SETUP_SINGLE_ISSUER
-is the recommended default. This provides the best control over when
-completion work runs and optimal cache locality.
-.SH SEE ALSO
-.BR io_uring (7),
-.BR io_uring_sqpoll (7),
-.BR io_uring_setup (2),
-.BR io_uring_queue_init_params (3),
-.BR io_uring_register_restrictions (3),
-.BR io_uring_enable_rings (3)
diff --git a/man/io_uring_setup_flags.7.md b/man/io_uring_setup_flags.7.md
new file mode 100644
index 00000000..3fc38bb7
--- /dev/null
+++ b/man/io_uring_setup_flags.7.md
@@ -0,0 +1,373 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 18, 2025
+footer: Linux
+header: Linux Programmer\'s Manual
+section: 7
+title: io_uring_setup_flags
+---
+
+# NAME
+
+io_uring_setup_flags - io_uring ring setup flags overview
+
+# DESCRIPTION
+
+When creating an io_uring instance with
+**io_uring_queue_init_params**(3) or **io_uring_setup**(2), various
+flags control the ring\'s behavior. These flags are set in the *flags*
+field of *struct io_uring_params*.
+
+Choosing the right flags can significantly impact performance. This page
+provides an overview of available flags, their purposes, and common
+combinations.
+
+## Polling flags
+
+These flags control how I/O completion and submission polling works.
+
+**IORING_SETUP_IOPOLL**
+
+> Enable I/O polling mode for file descriptors that support it. Instead
+> of relying on interrupts, the kernel polls for completions. This
+> reduces latency for high-performance storage devices (NVMe, etc.) but
+> requires:
+>
+> - Files opened with **O_DIRECT** (if using the
+> **IORING_OP\_{READ,WRITE}(V)(\_FIXED)** opcodes)
+>
+> - Hardware and drivers that support polling
+>
+> - The application to call **io_uring_enter**(2) to reap completions
+> (busy-polling)
+>
+> - Storage device configuration for polling support
+>
+> Only the following opcodes are allowed on IOPOLL rings:
+>
+> - **IORING_OP_NOP(128)**
+>
+> - **IORING_OP\_{READ,WRITE}(V)(\_FIXED)** (if the file supports
+> busy-polling)
+>
+> - **IORING_OP_FILES_UPDATE**
+>
+> - **IORING_OP\_{PROVIDE,REMOVE}\_BUFFERS**
+>
+> - **IORING_OP_MSG_RING**
+>
+> - **IORING_OP_URING_CMD(128)**
+>
+> Since kernel 7.1, an **IORING_OP_URING_CMD(128)** request will use
+> busy-polling if the file supports it (i.e., NVMe passthrough I/O
+> commands). Previously, **IORING_OP_URING_CMD(128)** was only allowed
+> on files that supported busy-polling.
+>
+> Using IOPOLL generally requires storage device setup. For NVMe
+> devices, the kernel parameter **nvme.poll_queues=X** must be set,
+> where X is the number of completion queues on the NVMe device to set
+> aside for polling operations.
+
+**IORING_SETUP_SQPOLL**
+
+> Create a kernel thread that polls the submission queue. Eliminates the
+> need for system calls to submit I/O. See **io_uring_sqpoll**(7) for
+> details.
+
+**IORING_SETUP_SQ_AFF**
+
+> Pin the SQPOLL thread to a specific CPU. Requires
+> **IORING_SETUP_SQPOLL**. The CPU is specified in *sq_thread_cpu* of
+> *struct io_uring_params*.
+
+**IORING_SETUP_HYBRID_IOPOLL**
+
+> Enable hybrid polling mode. Instead of pure busy-polling, the kernel
+> uses an adaptive approach that may sleep briefly, reducing CPU usage
+> while still providing low latency. This is a middle ground between
+> interrupt-driven and pure polling modes.
+
+## Task run flags
+
+These flags control when and how completion processing runs.
+
+**IORING_SETUP_COOP_TASKRUN**
+
+> Disable interrupting the application for completion processing.
+> Normally, the kernel signals the application when completions are
+> ready, which can interrupt system calls. With this flag, completions
+> are only processed when the application returns to userspace from any
+> system call, not just io_uring-related ones. This means completions
+> may be processed after **read**(2), **write**(2), **poll**(2), or any
+> other syscall returns.
+>
+> This improves performance by eliminating asynchronous interrupts but
+> requires the application to regularly enter the kernel to process
+> completions. Recommended for most applications that have an event
+> loop.
+
+**IORING_SETUP_TASKRUN_FLAG**
+
+> When completions are pending, set **IORING_SQ_TASKRUN** in the SQ ring
+> flags. This allows applications to check if there is completion work
+> to process without making a system call. Typically used with
+> **IORING_SETUP_COOP_TASKRUN**.
+
+**IORING_SETUP_DEFER_TASKRUN**
+
+> Defer completion task work to when the application explicitly enters
+> the kernel via **io_uring_enter**(2). Unlike
+> **IORING_SETUP_COOP_TASKRUN**, completions are only processed during
+> io_uring-related syscalls, not on return from arbitrary syscalls. This
+> provides the tightest and most predictable control over when
+> completion processing occurs, as well as optimal cache behavior since
+> work runs in the application\'s context.
+>
+> This flag should be considered the default mode for applications
+> setting up a ring. It requires **IORING_SETUP_SINGLE_ISSUER** and a
+> ring created per-thread. The application must regularly call
+> **io_uring_enter**(2) (via **io_uring_submit**(3),
+> **io_uring_wait_cqe**(3), or similar) to process deferred work;
+> failing to do so will stall completions.
+>
+> Some features require this flag:
+>
+> - Ring resizing (**io_uring_register_resize_rings**(3))
+>
+> - Zero-copy receive (**IORING_OP_RECV_ZC**)
+
+**IORING_SETUP_SINGLE_ISSUER**
+
+> Hint that only one task will submit requests to this ring. Enables
+> internal optimizations including reduced locking overhead. The first
+> task to submit a request becomes the designated submitter; others
+> attempting to submit will get **-EEXIST**.
+>
+> Each thread or task having its own ring is the idiomatic use case for
+> io_uring. Sharing a ring between multiple threads or tasks is
+> discouraged as it requires additional synchronization and prevents
+> many optimizations. Applications should create a ring per thread
+> rather than sharing rings.
+
+## Ring sizing flags
+
+These flags control the size and layout of the submission and completion
+queues.
+
+**IORING_SETUP_CQSIZE**
+
+> Override the default completion queue size. By default, the CQ has
+> twice as many entries as the SQ. Set *cq_entries* in *struct
+> io_uring_params* to specify a custom CQ size. Must be a power of 2.
+>
+> Larger CQ sizes are useful when the application may submit many
+> requests before processing completions, avoiding CQ overflow.
+
+**IORING_SETUP_CLAMP**
+
+> Clamp the SQ and CQ sizes to the maximum allowed values instead of
+> returning **-EINVAL** if the requested sizes are too large. Useful
+> when the application wants the largest possible rings without querying
+> limits.
+
+**IORING_SETUP_SQE128**
+
+> Use 128-byte SQEs instead of the default 64 bytes. Required for some
+> operations that need extra space, such as **IORING_OP_URING_CMD**
+> passthrough commands.
+
+**IORING_SETUP_CQE32**
+
+> Use 32-byte CQEs instead of the default 16 bytes. Required for
+> operations that return extra data, such as some passthrough commands
+> or when using **IORING_OP_MSG_RING**.
+
+**IORING_SETUP_NO_SQARRAY**
+
+> Do not create the SQ array. The SQ array is a level of indirection
+> that allows SQEs to be submitted in a different order than they appear
+> in the ring. Most applications submit SQEs in order and do not need
+> this. This flag saves memory and is required for some modes like
+> **IORING_SETUP_REGISTERED_FD_ONLY**.
+
+**IORING_SETUP_SQ_REWIND**
+
+> Use non-circular submission queue mode. The kernel ignores the SQ head
+> and tail pointers and instead fetches SQEs starting from index 0 on
+> each submit. The application places all SQEs at the beginning of the
+> ring before calling **io_uring_enter**(2), and the *sq_entries*
+> parameter determines how many SQEs are submitted.
+>
+> Requires **IORING_SETUP_NO_SQARRAY**. Not compatible with
+> **IORING_SETUP_SQPOLL**.
+>
+> This mode keeps SQEs hot in cache by always accessing the same memory
+> locations at the start of the ring, improving performance for
+> workloads that submit small batches frequently.
+
+**IORING_SETUP_CQE_MIXED**
+
+> Allow the ring to return a mix of 16-byte and 32-byte CQEs, controlled
+> per-request. When a request needs a 32-byte CQE, it sets
+> **IOSQE_BIG_CQE** in its flags. Otherwise, a 16-byte CQE is used.
+> Requires **IORING_SETUP_CQE32**.
+>
+> This is useful when certain operations require 32-byte CQEs (such as
+> some passthrough commands) but most operations do not. Using mixed
+> mode instead of **IORING_SETUP_CQE32** alone provides efficiency
+> benefits in terms of memory bandwidth and usage, since the smaller
+> 16-byte CQEs are used for operations that do not need the extra space.
+
+**IORING_SETUP_SQE_MIXED**
+
+> Allow the ring to accept a mix of 64-byte and 128-byte SQEs. When a
+> request needs a 128-byte SQE, it sets **IOSQE_BIG_SQE** in its flags.
+> Requires **IORING_SETUP_SQE128**.
+>
+> This is useful when certain operations require 128-byte SQEs (such as
+> **IORING_OP_URING_CMD**) but most operations do not. Using mixed mode
+> instead of **IORING_SETUP_SQE128** alone provides efficiency benefits
+> in terms of memory bandwidth and usage, since the smaller 64-byte SQEs
+> are used for operations that do not need the extra space.
+
+## Memory and setup flags
+
+These flags control memory allocation and ring initialization.
+
+**IORING_SETUP_NO_MMAP**
+
+> The application provides its own memory for the rings instead of the
+> kernel allocating and the application mmap\'ing it. The application
+> fills in *sq_off.user_addr*, *cq_off.user_addr*, and
+> *sq_sqes.user_addr* in *struct io_uring_params* with addresses of
+> application-allocated memory.
+>
+> This is useful for placing rings in specific memory (huge pages,
+> shared memory, etc.) or for creating rings without mmap.
+
+**IORING_SETUP_REGISTERED_FD_ONLY**
+
+> The ring file descriptor is not installed in the process\'s file
+> descriptor table. Instead, a \"registered ring\" index is returned in
+> *ring_fd* that can be used with **io_uring_enter**(2) when
+> **IORING_ENTER_REGISTERED_RING** is set. This reduces per-operation
+> overhead.
+>
+> Requires **IORING_SETUP_NO_SQARRAY**. The application must use
+> **io_uring_register_ring_fd**(3) to use the ring or access it via the
+> registered index.
+
+**IORING_SETUP_R_DISABLED**
+
+> Create the ring in a disabled state. The ring will not accept
+> submissions until it is enabled via **io_uring_enable_rings**(3). This
+> is useful when setting up restrictions or registered resources before
+> allowing I/O. See **io_uring_register_restrictions**(3).
+
+## Submission flags
+
+These flags control submission behavior.
+
+**IORING_SETUP_SUBMIT_ALL**
+
+> Continue processing submissions even if one fails. Normally, if an SQE
+> fails during submission (not execution), subsequent SQEs in the same
+> submit call are not processed. With this flag, all SQEs are processed
+> regardless of earlier failures.
+>
+> The failed SQE still generates a CQE with the error; this flag only
+> affects whether subsequent SQEs are submitted. This is probably the
+> behavior most applications expect, since CQEs are generated for failed
+> submissions anyway and the application must handle them regardless.
+
+## Workqueue flags
+
+These flags control the async worker threads.
+
+**IORING_SETUP_ATTACH_WQ**
+
+> Share the async worker thread pool with another ring. Set *wq_fd* in
+> *struct io_uring_params* to the file descriptor of the ring to share
+> with. This reduces resource usage when an application uses multiple
+> rings.
+>
+> When combined with **IORING_SETUP_SQPOLL**, the SQPOLL thread is also
+> shared.
+
+## Common flag combinations
+
+**High-performance single-threaded application:**
+
+> ``` text
+> .flags = IORING_SETUP_SINGLE_ISSUER |
+> IORING_SETUP_DEFER_TASKRUN |
+> IORING_SETUP_COOP_TASKRUN
+> ```
+>
+> This combination provides the best latency and throughput for
+> applications where each thread has its own ring and processes
+> completions in a dedicated event loop.
+
+**Low-latency storage with polling:**
+
+> ``` text
+> .flags = IORING_SETUP_IOPOLL |
+> IORING_SETUP_SINGLE_ISSUER |
+> IORING_SETUP_DEFER_TASKRUN
+> ```
+>
+> For NVMe or other devices that support polling, this eliminates
+> interrupt overhead. Combined with DEFER_TASKRUN for optimal completion
+> handling.
+
+**System call-free submission:**
+
+> ``` text
+> .flags = IORING_SETUP_SQPOLL |
+> IORING_SETUP_SQ_AFF
+> .sq_thread_cpu = preferred_cpu
+> .sq_thread_idle = 1000
+> ```
+>
+> For workloads that benefit from eliminating submission syscall
+> overhead. See **io_uring_sqpoll**(7).
+
+**Multiple rings sharing resources:**
+
+> ``` text
+> /* First ring */
+> p1.flags = IORING_SETUP_SQPOLL;
+>
+> /* Subsequent rings */
+> p2.flags = IORING_SETUP_SQPOLL | IORING_SETUP_ATTACH_WQ;
+> p2.wq_fd = ring1_fd;
+> ```
+>
+> Reduces kernel thread and workqueue overhead when using multiple
+> rings.
+
+# NOTES
+
+- Not all flag combinations are valid. The kernel returns **-EINVAL**
+ for incompatible combinations.
+
+- Some flags require specific kernel versions. Check
+ **io_uring_setup**(2) for version requirements.
+
+- The **io_uring_queue_init_params**(3) function handles the complexity
+ of ring setup. Using the raw **io_uring_setup**(2) syscall requires
+ careful mmap setup.
+
+- For most applications with a proper event loop,
+ **IORING_SETUP_DEFER_TASKRUN** combined with
+ **IORING_SETUP_SINGLE_ISSUER** is the recommended default. This
+ provides the best control over when completion work runs and optimal
+ cache locality.
+
+# SEE ALSO
+
+**io_uring**(7), **io_uring_sqpoll**(7), **io_uring_setup**(2),
+**io_uring_queue_init_params**(3),
+**io_uring_register_restrictions**(3), **io_uring_enable_rings**(3)
diff --git a/man/io_uring_sq_ready.3 b/man/io_uring_sq_ready.3
deleted file mode 100644
index ba155b32..00000000
--- a/man/io_uring_sq_ready.3
+++ /dev/null
@@ -1,31 +0,0 @@
-.\" Copyright (C) 2022 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_sq_ready 3 "January 25, 2022" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_sq_ready \- number of unconsumed or unsubmitted entries in the SQ ring
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "unsigned io_uring_sq_ready(const struct io_uring *" ring ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_sq_ready (3)
-function returns the number of unconsumed (if SQPOLL) or unsubmitted entries
-that exist in the SQ ring belonging to the
-.I ring
-param.
-
-Usage of this function only applies if the ring has been setup with
-.B IORING_SETUP_SQPOLL,
-where request submissions, and hence consumption from the SQ ring, happens
-through a polling thread.
-
-.SH RETURN VALUE
-Returns the number of unconsumed or unsubmitted entries in the SQ ring.
-.SH SEE ALSO
-.BR io_uring_cq_ready (3)
diff --git a/man/io_uring_sq_ready.3.md b/man/io_uring_sq_ready.3.md
new file mode 100644
index 00000000..c244fbbd
--- /dev/null
+++ b/man/io_uring_sq_ready.3.md
@@ -0,0 +1,42 @@
+.\" Copyright (C) 2022 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 25, 2022
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_sq_ready
+---
+
+# NAME
+
+io_uring_sq_ready - number of unconsumed or unsubmitted entries in the
+SQ ring
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ unsigned io_uring_sq_ready(const struct io_uring * ring );
+```
+
+# DESCRIPTION
+
+The **io_uring_sq_ready**(3) function returns the number of unconsumed
+(if SQPOLL) or unsubmitted entries that exist in the SQ ring belonging
+to the *ring* param.
+
+Usage of this function only applies if the ring has been setup with
+**IORING_SETUP_SQPOLL,** where request submissions, and hence
+consumption from the SQ ring, happens through a polling thread.
+
+# RETURN VALUE
+
+Returns the number of unconsumed or unsubmitted entries in the SQ ring.
+
+# SEE ALSO
+
+**io_uring_cq_ready**(3)
diff --git a/man/io_uring_sq_space_left.3 b/man/io_uring_sq_space_left.3
deleted file mode 100644
index 74872d8b..00000000
--- a/man/io_uring_sq_space_left.3
+++ /dev/null
@@ -1,25 +0,0 @@
-.\" Copyright (C) 2022 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_sq_space_left 3 "January 25, 2022" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_sq_space_left \- free space in the SQ ring
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "unsigned io_uring_sq_space_left(const struct io_uring *" ring ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_sq_space_left (3)
-function returns how much space is left in the SQ ring belonging to the
-.I ring
-param.
-
-.SH RETURN VALUE
-Returns the number of availables entries in the SQ ring.
-.SH SEE ALSO
-.BR io_uring_sq_ready (3)
diff --git a/man/io_uring_sq_space_left.3.md b/man/io_uring_sq_space_left.3.md
new file mode 100644
index 00000000..d95e13cd
--- /dev/null
+++ b/man/io_uring_sq_space_left.3.md
@@ -0,0 +1,36 @@
+.\" Copyright (C) 2022 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 25, 2022
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_sq_space_left
+---
+
+# NAME
+
+io_uring_sq_space_left - free space in the SQ ring
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ unsigned io_uring_sq_space_left(const struct io_uring * ring );
+```
+
+# DESCRIPTION
+
+The **io_uring_sq_space_left**(3) function returns how much space is
+left in the SQ ring belonging to the *ring* param.
+
+# RETURN VALUE
+
+Returns the number of availables entries in the SQ ring.
+
+# SEE ALSO
+
+**io_uring_sq_ready**(3)
diff --git a/man/io_uring_sqe_set_buf_group.3 b/man/io_uring_sqe_set_buf_group.3
deleted file mode 100644
index 5299051d..00000000
--- a/man/io_uring_sqe_set_buf_group.3
+++ /dev/null
@@ -1,32 +0,0 @@
-.\" Copyright (C) 2024 Christian Mazakas <christian.mazakas@gmail.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_sqe_set_buf_group 3 "December 9, 2024" "liburing-2.9" "liburing Manual"
-.SH NAME
-io_uring_sqe_set_buf_group \- set buf group for submission queue event
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_sqe_set_buf_group(struct io_uring_sqe *" sqe ","
-.BI " int " bgid ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_sqe_set_buf_group (3)
-function sets the associated buf_group of the
-.I sqe
-to
-.IR bgid .
-
-After the caller has requested a submission queue entry (SQE) with
-.BR io_uring_get_sqe (3) ,
-they can associate a buf_group with the SQE used for multishot operations.
-
-.SH RETURN VALUE
-None
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_cqe_set_data (3)
diff --git a/man/io_uring_sqe_set_buf_group.3.md b/man/io_uring_sqe_set_buf_group.3.md
new file mode 100644
index 00000000..c85ce6f6
--- /dev/null
+++ b/man/io_uring_sqe_set_buf_group.3.md
@@ -0,0 +1,41 @@
+.\" Copyright (C) 2024 Christian Mazakas <christian.mazakas@gmail.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: December 9, 2024
+footer: liburing-2.9
+header: liburing Manual
+section: 3
+title: io_uring_sqe_set_buf_group
+---
+
+# NAME
+
+io_uring_sqe_set_buf_group - set buf group for submission queue event
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_sqe_set_buf_group(struct io_uring_sqe * sqe ,
+ int bgid );
+```
+
+# DESCRIPTION
+
+The **io_uring_sqe_set_buf_group**(3) function sets the associated
+buf_group of the *sqe* to *bgid*.
+
+After the caller has requested a submission queue entry (SQE) with
+**io_uring_get_sqe**(3)**,** they can associate a buf_group with the SQE
+used for multishot operations.
+
+# RETURN VALUE
+
+None
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_cqe_set_data**(3)
diff --git a/man/io_uring_sqe_set_data.3 b/man/io_uring_sqe_set_data.3
deleted file mode 100644
index 0a91f57f..00000000
--- a/man/io_uring_sqe_set_data.3
+++ /dev/null
@@ -1,57 +0,0 @@
-.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_sqe_set_data 3 "November 15, 2021" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_sqe_set_data \- set user data for submission queue event
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_sqe_set_data(struct io_uring_sqe *" sqe ","
-.BI " void *" user_data ");"
-.BI "
-.BI "void io_uring_sqe_set_data64(struct io_uring_sqe *" sqe ","
-.BI " __u64 " data ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_sqe_set_data (3)
-function stores a
-.I user_data
-pointer with the submission queue entry
-.IR sqe .
-
-The
-.BR io_uring_sqe_set_data64 (3)
-function stores a 64-bit
-.I data
-value with the submission queue entry
-.IR sqe .
-
-After the caller has requested a submission queue entry (SQE) with
-.BR io_uring_get_sqe (3) ,
-they can associate a data pointer or value with the SQE. Once the completion
-arrives, the function
-.BR io_uring_cqe_get_data (3)
-or
-.BR io_uring_cqe_get_data64 (3)
-can be called to retrieve the data pointer or value associated with the
-submitted request.
-
-Note that if neither of these functions are called, or the
-.I user_data
-field in the
-.IR sqe
-isn't set manually either, then the field may contain a value from a previous
-use of this sqe. If an application relies on always having a valid
-.I user_data
-value present, it must always assign one to each sqe.
-
-.SH RETURN VALUE
-None
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_cqe_get_data (3)
diff --git a/man/io_uring_sqe_set_data.3.md b/man/io_uring_sqe_set_data.3.md
new file mode 100644
index 00000000..45e88149
--- /dev/null
+++ b/man/io_uring_sqe_set_data.3.md
@@ -0,0 +1,56 @@
+.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: November 15, 2021
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_sqe_set_data
+---
+
+# NAME
+
+io_uring_sqe_set_data - set user data for submission queue event
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_sqe_set_data(struct io_uring_sqe * sqe ,
+ void * user_data );
+
+ void io_uring_sqe_set_data64(struct io_uring_sqe * sqe ,
+ __u64 data );
+```
+
+# DESCRIPTION
+
+The **io_uring_sqe_set_data**(3) function stores a *user_data* pointer
+with the submission queue entry *sqe*.
+
+The **io_uring_sqe_set_data64**(3) function stores a 64-bit *data* value
+with the submission queue entry *sqe*.
+
+After the caller has requested a submission queue entry (SQE) with
+**io_uring_get_sqe**(3)**,** they can associate a data pointer or value
+with the SQE. Once the completion arrives, the function
+**io_uring_cqe_get_data**(3) or **io_uring_cqe_get_data64**(3) can be
+called to retrieve the data pointer or value associated with the
+submitted request.
+
+Note that if neither of these functions are called, or the *user_data*
+field in the *sqe* isn\'t set manually either, then the field may
+contain a value from a previous use of this sqe. If an application
+relies on always having a valid *user_data* value present, it must
+always assign one to each sqe.
+
+# RETURN VALUE
+
+None
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_cqe_get_data**(3)
diff --git a/man/io_uring_sqe_set_flags.3 b/man/io_uring_sqe_set_flags.3
deleted file mode 100644
index ab0bb8e7..00000000
--- a/man/io_uring_sqe_set_flags.3
+++ /dev/null
@@ -1,87 +0,0 @@
-.\" Copyright (C) 2022 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_sqe_set_flags 3 "January 25, 2022" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_sqe_set_flags \- set flags for submission queue entry
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "void io_uring_sqe_set_flags(struct io_uring_sqe *" sqe ","
-.BI " unsigned " flags ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_sqe_set_flags (3)
-function allows the caller to change the behavior of the submission queue entry
-by specifying flags. It enables the
-.I flags
-belonging to the
-.I sqe
-submission queue entry param.
-
-.I flags
-is a bit mask of 0 or more of the following values ORed together:
-.TP
-.B IOSQE_FIXED_FILE
-The file descriptor in the SQE refers to the index of a previously registered
-file or direct file descriptor, not a normal file descriptor.
-.TP
-.B IOSQE_ASYNC
-Normal operation for io_uring is to try and issue an sqe as non-blocking first,
-and if that fails, execute it in an async manner. To support more efficient
-overlapped operation of requests that the application knows/assumes will
-always (or most of the time) block, the application can ask for an sqe to be
-issued async from the start. Note that this flag immediately causes the SQE
-to be offloaded to an async helper thread with no initial non-blocking attempt.
-This may be less efficient and should not be used liberally or without
-understanding the performance and efficiency tradeoffs.
-.TP
-.B IOSQE_IO_LINK
-When this flag is specified, the SQE forms a link with the next SQE in the
-submission ring. That next SQE will not be started before the previous request
-completes. This, in effect, forms a chain of SQEs, which can be arbitrarily
-long. The tail of the chain is denoted by the first SQE that does not have this
-flag set. Chains are not supported across submission boundaries. Even if the
-last SQE in a submission has this flag set, it will still terminate the current
-chain. This flag has no effect on previous SQE submissions, nor does it impact
-SQEs that are outside of the chain tail. This means that multiple chains can be
-executing in parallel, or chains and individual SQEs. Only members inside the
-chain are serialized. A chain of SQEs will be broken if any request in that
-chain ends in error.
-.TP
-.B IOSQE_IO_HARDLINK
-Like
-.B IOSQE_IO_LINK ,
-except the links aren't severed if an error or unexpected result occurs.
-.TP
-.B IOSQE_IO_DRAIN
-When this flag is specified, the SQE will not be started before previously
-submitted SQEs have completed, and new SQEs will not be started before this
-one completes.
-.TP
-.B IOSQE_CQE_SKIP_SUCCESS
-Request that no CQE be generated for this request, if it completes successfully.
-This can be useful in cases where the application doesn't need to know when
-a specific request completed, if it completed successfully.
-.TP
-.B IOSQE_BUFFER_SELECT
-If set, and if the request types supports it, select an IO buffer from the
-indicated buffer group. This can be used with requests that read or receive
-data from a file or socket, where buffer selection is deferred until the kernel
-is ready to transfer data, instead of when the IO is originally submitted. The
-application must also set the
-.I buf_group
-field in the SQE, indicating which previously registered buffer group to select
-a buffer from.
-
-.SH RETURN VALUE
-None
-.SH SEE ALSO
-.BR io_uring_submit (3),
-.BR io_uring_register (3)
-.BR io_uring_register_buffers (3)
-.BR io_uring_register_buf_ring (3)
diff --git a/man/io_uring_sqe_set_flags.3.md b/man/io_uring_sqe_set_flags.3.md
new file mode 100644
index 00000000..dc6a16e4
--- /dev/null
+++ b/man/io_uring_sqe_set_flags.3.md
@@ -0,0 +1,103 @@
+.\" Copyright (C) 2022 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 25, 2022
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_sqe_set_flags
+---
+
+# NAME
+
+io_uring_sqe_set_flags - set flags for submission queue entry
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ void io_uring_sqe_set_flags(struct io_uring_sqe * sqe ,
+ unsigned flags );
+```
+
+# DESCRIPTION
+
+The **io_uring_sqe_set_flags**(3) function allows the caller to change
+the behavior of the submission queue entry by specifying flags. It
+enables the *flags* belonging to the *sqe* submission queue entry param.
+
+*flags* is a bit mask of 0 or more of the following values ORed
+together:
+
+**IOSQE_FIXED_FILE**
+
+: The file descriptor in the SQE refers to the index of a previously
+ registered file or direct file descriptor, not a normal file
+ descriptor.
+
+**IOSQE_ASYNC**
+
+: Normal operation for io_uring is to try and issue an sqe as
+ non-blocking first, and if that fails, execute it in an async manner.
+ To support more efficient overlapped operation of requests that the
+ application knows/assumes will always (or most of the time) block, the
+ application can ask for an sqe to be issued async from the start. Note
+ that this flag immediately causes the SQE to be offloaded to an async
+ helper thread with no initial non-blocking attempt. This may be less
+ efficient and should not be used liberally or without understanding
+ the performance and efficiency tradeoffs.
+
+**IOSQE_IO_LINK**
+
+: When this flag is specified, the SQE forms a link with the next SQE in
+ the submission ring. That next SQE will not be started before the
+ previous request completes. This, in effect, forms a chain of SQEs,
+ which can be arbitrarily long. The tail of the chain is denoted by the
+ first SQE that does not have this flag set. Chains are not supported
+ across submission boundaries. Even if the last SQE in a submission has
+ this flag set, it will still terminate the current chain. This flag
+ has no effect on previous SQE submissions, nor does it impact SQEs
+ that are outside of the chain tail. This means that multiple chains
+ can be executing in parallel, or chains and individual SQEs. Only
+ members inside the chain are serialized. A chain of SQEs will be
+ broken if any request in that chain ends in error.
+
+**IOSQE_IO_HARDLINK**
+
+: Like **IOSQE_IO_LINK ,** except the links aren\'t severed if an error
+ or unexpected result occurs.
+
+**IOSQE_IO_DRAIN**
+
+: When this flag is specified, the SQE will not be started before
+ previously submitted SQEs have completed, and new SQEs will not be
+ started before this one completes.
+
+**IOSQE_CQE_SKIP_SUCCESS**
+
+: Request that no CQE be generated for this request, if it completes
+ successfully. This can be useful in cases where the application
+ doesn\'t need to know when a specific request completed, if it
+ completed successfully.
+
+**IOSQE_BUFFER_SELECT**
+
+: If set, and if the request types supports it, select an IO buffer from
+ the indicated buffer group. This can be used with requests that read
+ or receive data from a file or socket, where buffer selection is
+ deferred until the kernel is ready to transfer data, instead of when
+ the IO is originally submitted. The application must also set the
+ *buf_group* field in the SQE, indicating which previously registered
+ buffer group to select a buffer from.
+
+# RETURN VALUE
+
+None
+
+# SEE ALSO
+
+**io_uring_submit**(3), **io_uring_register**(3)
+**io_uring_register_buffers**(3) **io_uring_register_buf_ring**(3)
diff --git a/man/io_uring_sqpoll.7 b/man/io_uring_sqpoll.7
deleted file mode 100644
index ce24b537..00000000
--- a/man/io_uring_sqpoll.7
+++ /dev/null
@@ -1,259 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_sqpoll 7 "January 18, 2025" "Linux" "Linux Programmer's Manual"
-.SH NAME
-io_uring_sqpoll \- io_uring submission queue polling overview
-.SH DESCRIPTION
-Submission queue polling (SQPOLL) is a mode of operation where an
-io_uring created userspace thread that remains in the kernel monitors
-the submission queue and submits requests on behalf of the application. This eliminates the need for
-the application to make system calls to submit I/O, reducing latency
-and CPU overhead for high-throughput workloads.
-.SS Why use SQPOLL?
-In normal io_uring operation, applications must call
-.BR io_uring_enter (2)
-(typically via
-.BR io_uring_submit (3))
-to notify the kernel of new submissions. While efficient, this still
-incurs system call overhead.
-
-With SQPOLL enabled, the kernel thread continuously polls the
-submission queue for new entries. As soon as the application writes
-an SQE to the ring, the kernel thread picks it up and submits it.
-This provides:
-.IP \(bu 2
-Elimination of submission system call overhead
-.IP \(bu
-Lower and more predictable latency
-.IP \(bu
-Better CPU utilization for high-IOPS workloads
-.PP
-SQPOLL is most beneficial for:
-.IP \(bu 2
-High-throughput storage workloads (NVMe, etc.)
-.IP \(bu
-Latency-sensitive applications
-.IP \(bu
-Workloads with continuous I/O streams
-.IP \(bu
-Applications already running at high CPU utilization
-.SS When SQPOLL may not help
-SQPOLL is not universally beneficial and each use case should be
-benchmarked to determine if it provides value. Situations where
-SQPOLL may not help or may hurt performance:
-.IP \(bu 2
-.B Low-IOPS workloads:
-If the application submits I/O infrequently, the system call overhead
-being saved is negligible, and the polling thread wastes CPU cycles.
-.IP \(bu
-.B CPU-constrained systems:
-The polling thread consumes CPU. If the system is already CPU-bound,
-adding a polling thread may compete with the application for CPU
-resources, reducing overall performance.
-.IP \(bu
-.B Bursty workloads:
-If I/O comes in bursts with idle periods, the polling thread may
-frequently sleep and wake, adding latency when it needs to wake up.
-Regular submission may be more efficient.
-.IP \(bu
-.B Single-threaded applications on single-CPU systems:
-The polling thread and application will compete for the same CPU,
-potentially causing context switches that negate any benefits.
-.IP \(bu
-.B Workloads dominated by completion handling:
-SQPOLL only optimizes submissions. If the application spends most
-of its time processing completions, SQPOLL provides little benefit.
-.PP
-Always benchmark with and without SQPOLL under realistic conditions.
-The performance difference can vary significantly based on hardware,
-kernel version, and workload characteristics.
-.SS Enabling SQPOLL
-SQPOLL is enabled by setting the
-.B IORING_SETUP_SQPOLL
-flag when creating the ring:
-.PP
-.in +4n
-.EX
-struct io_uring ring;
-struct io_uring_params params = {
- .flags = IORING_SETUP_SQPOLL,
- .sq_thread_idle = 2000, /* 2 seconds */
-};
-
-ret = io_uring_queue_init_params(entries, &ring, ¶ms);
-.EE
-.in
-.PP
-The
-.I sq_thread_idle
-field specifies how long (in milliseconds) the kernel thread will
-poll before going to sleep if no submissions are pending. A value of
-0 means the thread never sleeps (uses more CPU but provides lowest
-latency).
-.SS The polling thread lifecycle
-When the ring is created with SQPOLL, a kernel thread is spawned to
-service it. The thread's behavior is:
-.IP 1. 4
-Poll the submission queue for new entries
-.IP 2.
-Submit any new requests found
-.IP 3.
-If no new entries are found for
-.I sq_thread_idle
-milliseconds, go to sleep
-.IP 4.
-Wake up when signaled by the application
-.PP
-The application can check if the thread is sleeping by examining
-.I sq->kflags
-for the
-.B IORING_SQ_NEED_WAKEUP
-flag using
-.BR io_uring_sq_ready (3).
-If set, the application must call
-.BR io_uring_enter (2)
-with
-.B IORING_ENTER_SQ_WAKEUP
-to wake the thread:
-.PP
-.in +4n
-.EX
-/* After adding SQEs */
-io_uring_smp_store_release(ring->sq.ktail, tail);
-
-if (IO_URING_READ_ONCE(*ring->sq.kflags) & IORING_SQ_NEED_WAKEUP)
- io_uring_enter(ring->ring_fd, 0, 0, IORING_ENTER_SQ_WAKEUP, NULL);
-.EE
-.in
-.PP
-The
-.BR io_uring_submit (3)
-function handles this automatically.
-.SS CPU affinity
-By default, the kernel schedules the polling thread on any available
-CPU. For better cache locality and reduced latency, the thread can be
-pinned to a specific CPU:
-.PP
-.in +4n
-.EX
-struct io_uring_params params = {
- .flags = IORING_SETUP_SQPOLL | IORING_SETUP_SQ_AFF,
- .sq_thread_cpu = 3, /* pin to CPU 3 */
- .sq_thread_idle = 1000,
-};
-.EE
-.in
-.PP
-The
-.B IORING_SETUP_SQ_AFF
-flag enables CPU affinity, and
-.I sq_thread_cpu
-specifies which CPU to use.
-.SS Credential requirements
-Creating an SQPOLL ring traditionally required elevated privileges
-because the kernel thread runs on behalf of the application. The
-requirements have evolved:
-.IP \(bu 2
-Kernel 5.11 and earlier: requires
-.B CAP_SYS_ADMIN
-or
-.B CAP_SYS_NICE
-.IP \(bu
-Kernel 5.12 and later: unprivileged users can create SQPOLL rings,
-but the polling thread runs with reduced capabilities
-.IP \(bu
-The
-.B IORING_SETUP_NO_SQARRAY
-flag (kernel 6.6+) can simplify setup for SQPOLL-only rings
-.SS Sharing the polling thread
-Multiple rings can share a single polling thread using
-.BR IORING_SETUP_ATTACH_WQ .
-This reduces resource usage when an application uses multiple rings:
-.PP
-.in +4n
-.EX
-/* Create first ring with SQPOLL */
-struct io_uring_params p1 = { .flags = IORING_SETUP_SQPOLL };
-io_uring_queue_init_params(entries, &ring1, &p1);
-
-/* Create second ring, attach to first ring's thread */
-struct io_uring_params p2 = {
- .flags = IORING_SETUP_SQPOLL | IORING_SETUP_ATTACH_WQ,
- .wq_fd = ring1.ring_fd,
-};
-io_uring_queue_init_params(entries, &ring2, &p2);
-.EE
-.in
-.SS Completion handling
-SQPOLL only affects submissions. Completions are still handled
-normally \(em the application must either:
-.IP \(bu 2
-Poll the completion queue directly (busy-wait)
-.IP \(bu
-Use
-.BR io_uring_enter (2)
-with
-.B IORING_ENTER_GETEVENTS
-to wait for completions
-.IP \(bu
-Use an eventfd for notification
-.PP
-For full polling on both submission and completion, combine SQPOLL
-with completion queue polling using
-.BR io_uring_peek_cqe (3)
-or similar functions.
-.SS Performance considerations
-.IP \(bu 2
-.B CPU usage:
-The polling thread consumes CPU while active. If I/O is sporadic,
-the thread may waste cycles polling an empty queue. Set
-.I sq_thread_idle
-appropriately for your workload.
-.IP \(bu
-.B Idle timeout tradeoff:
-A shorter idle timeout saves CPU but may increase latency when the
-thread needs to wake up. A longer timeout (or 0 for never sleeping)
-uses more CPU but provides consistent low latency.
-.IP \(bu
-.B Batching:
-Even with SQPOLL, batching submissions by adding multiple SQEs before
-updating the tail pointer can improve throughput.
-.IP \(bu
-.B CPU affinity:
-Pinning the polling thread to a CPU near the application's CPU can
-improve cache behavior and reduce cross-CPU communication.
-.SH NOTES
-.IP \(bu 2
-The polling thread is per-ring (unless shared via
-.BR IORING_SETUP_ATTACH_WQ ).
-Creating many SQPOLL rings without sharing can consume significant
-kernel resources.
-.IP \(bu
-SQPOLL rings still require system calls for:
-.RS 4
-.IP \(bu 2
-Waiting for completions (unless busy-polling the CQ)
-.IP \(bu
-Waking the thread when it has gone idle
-.IP \(bu
-Registration operations
-.RE
-.IP \(bu
-The polling thread inherits resource limits and cgroup membership
-from the creating process.
-.IP \(bu
-If the polling thread encounters an error it cannot recover from,
-.B IORING_SQ_CQ_OVERFLOW
-may be set in
-.IR sq->kflags .
-.IP \(bu
-SQPOLL works well in combination with registered files and buffers,
-which further reduce per-I/O overhead.
-.SH SEE ALSO
-.BR io_uring (7),
-.BR io_uring_setup (2),
-.BR io_uring_enter (2),
-.BR io_uring_queue_init_params (3),
-.BR io_uring_register_files (3),
-.BR io_uring_registered_buffers (7)
diff --git a/man/io_uring_sqpoll.7.md b/man/io_uring_sqpoll.7.md
new file mode 100644
index 00000000..d944715f
--- /dev/null
+++ b/man/io_uring_sqpoll.7.md
@@ -0,0 +1,244 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 18, 2025
+footer: Linux
+header: Linux Programmer\'s Manual
+section: 7
+title: io_uring_sqpoll
+---
+
+# NAME
+
+io_uring_sqpoll - io_uring submission queue polling overview
+
+# DESCRIPTION
+
+Submission queue polling (SQPOLL) is a mode of operation where an
+io_uring created userspace thread that remains in the kernel monitors
+the submission queue and submits requests on behalf of the application.
+This eliminates the need for the application to make system calls to
+submit I/O, reducing latency and CPU overhead for high-throughput
+workloads.
+
+## Why use SQPOLL?
+
+In normal io_uring operation, applications must call
+**io_uring_enter**(2) (typically via **io_uring_submit**(3)) to notify
+the kernel of new submissions. While efficient, this still incurs system
+call overhead.
+
+With SQPOLL enabled, the kernel thread continuously polls the submission
+queue for new entries. As soon as the application writes an SQE to the
+ring, the kernel thread picks it up and submits it. This provides:
+
+- Elimination of submission system call overhead
+
+- Lower and more predictable latency
+
+- Better CPU utilization for high-IOPS workloads
+
+SQPOLL is most beneficial for:
+
+- High-throughput storage workloads (NVMe, etc.)
+
+- Latency-sensitive applications
+
+- Workloads with continuous I/O streams
+
+- Applications already running at high CPU utilization
+
+## When SQPOLL may not help
+
+SQPOLL is not universally beneficial and each use case should be
+benchmarked to determine if it provides value. Situations where SQPOLL
+may not help or may hurt performance:
+
+- **Low-IOPS workloads:** If the application submits I/O infrequently,
+ the system call overhead being saved is negligible, and the polling
+ thread wastes CPU cycles.
+
+- **CPU-constrained systems:** The polling thread consumes CPU. If the
+ system is already CPU-bound, adding a polling thread may compete with
+ the application for CPU resources, reducing overall performance.
+
+- **Bursty workloads:** If I/O comes in bursts with idle periods, the
+ polling thread may frequently sleep and wake, adding latency when it
+ needs to wake up. Regular submission may be more efficient.
+
+- **Single-threaded applications on single-CPU systems:** The polling
+ thread and application will compete for the same CPU, potentially
+ causing context switches that negate any benefits.
+
+- **Workloads dominated by completion handling:** SQPOLL only optimizes
+ submissions. If the application spends most of its time processing
+ completions, SQPOLL provides little benefit.
+
+Always benchmark with and without SQPOLL under realistic conditions. The
+performance difference can vary significantly based on hardware, kernel
+version, and workload characteristics.
+
+## Enabling SQPOLL
+
+SQPOLL is enabled by setting the **IORING_SETUP_SQPOLL** flag when
+creating the ring:
+
+``` text
+struct io_uring ring;
+struct io_uring_params params = {
+ .flags = IORING_SETUP_SQPOLL,
+ .sq_thread_idle = 2000, /* 2 seconds */
+};
+
+ret = io_uring_queue_init_params(entries, &ring, ¶ms);
+```
+
+The *sq_thread_idle* field specifies how long (in milliseconds) the
+kernel thread will poll before going to sleep if no submissions are
+pending. A value of 0 means the thread never sleeps (uses more CPU but
+provides lowest latency).
+
+## The polling thread lifecycle
+
+When the ring is created with SQPOLL, a kernel thread is spawned to
+service it. The thread\'s behavior is:
+
+1. Poll the submission queue for new entries
+
+2. Submit any new requests found
+
+3. If no new entries are found for *sq_thread_idle* milliseconds, go to
+ sleep
+
+4. Wake up when signaled by the application
+
+The application can check if the thread is sleeping by examining
+*sq-\>kflags* for the **IORING_SQ_NEED_WAKEUP** flag using
+**io_uring_sq_ready**(3). If set, the application must call
+**io_uring_enter**(2) with **IORING_ENTER_SQ_WAKEUP** to wake the
+thread:
+
+``` text
+/* After adding SQEs */
+io_uring_smp_store_release(ring->sq.ktail, tail);
+
+if (IO_URING_READ_ONCE(*ring->sq.kflags) & IORING_SQ_NEED_WAKEUP)
+ io_uring_enter(ring->ring_fd, 0, 0, IORING_ENTER_SQ_WAKEUP, NULL);
+```
+
+The **io_uring_submit**(3) function handles this automatically.
+
+## CPU affinity
+
+By default, the kernel schedules the polling thread on any available
+CPU. For better cache locality and reduced latency, the thread can be
+pinned to a specific CPU:
+
+``` text
+struct io_uring_params params = {
+ .flags = IORING_SETUP_SQPOLL | IORING_SETUP_SQ_AFF,
+ .sq_thread_cpu = 3, /* pin to CPU 3 */
+ .sq_thread_idle = 1000,
+};
+```
+
+The **IORING_SETUP_SQ_AFF** flag enables CPU affinity, and
+*sq_thread_cpu* specifies which CPU to use.
+
+## Credential requirements
+
+Creating an SQPOLL ring traditionally required elevated privileges
+because the kernel thread runs on behalf of the application. The
+requirements have evolved:
+
+- Kernel 5.11 and earlier: requires **CAP_SYS_ADMIN** or
+ **CAP_SYS_NICE**
+
+- Kernel 5.12 and later: unprivileged users can create SQPOLL rings, but
+ the polling thread runs with reduced capabilities
+
+- The **IORING_SETUP_NO_SQARRAY** flag (kernel 6.6+) can simplify setup
+ for SQPOLL-only rings
+
+## Sharing the polling thread
+
+Multiple rings can share a single polling thread using
+**IORING_SETUP_ATTACH_WQ**. This reduces resource usage when an
+application uses multiple rings:
+
+``` text
+/* Create first ring with SQPOLL */
+struct io_uring_params p1 = { .flags = IORING_SETUP_SQPOLL };
+io_uring_queue_init_params(entries, &ring1, &p1);
+
+/* Create second ring, attach to first ring's thread */
+struct io_uring_params p2 = {
+ .flags = IORING_SETUP_SQPOLL | IORING_SETUP_ATTACH_WQ,
+ .wq_fd = ring1.ring_fd,
+};
+io_uring_queue_init_params(entries, &ring2, &p2);
+```
+
+## Completion handling
+
+SQPOLL only affects submissions. Completions are still handled normally
+--- the application must either:
+
+- Poll the completion queue directly (busy-wait)
+
+- Use **io_uring_enter**(2) with **IORING_ENTER_GETEVENTS** to wait for
+ completions
+
+- Use an eventfd for notification
+
+For full polling on both submission and completion, combine SQPOLL with
+completion queue polling using **io_uring_peek_cqe**(3) or similar
+functions.
+
+## Performance considerations
+
+- **CPU usage:** The polling thread consumes CPU while active. If I/O is
+ sporadic, the thread may waste cycles polling an empty queue. Set
+ *sq_thread_idle* appropriately for your workload.
+
+- **Idle timeout tradeoff:** A shorter idle timeout saves CPU but may
+ increase latency when the thread needs to wake up. A longer timeout
+ (or 0 for never sleeping) uses more CPU but provides consistent low
+ latency.
+
+- **Batching:** Even with SQPOLL, batching submissions by adding
+ multiple SQEs before updating the tail pointer can improve throughput.
+
+- **CPU affinity:** Pinning the polling thread to a CPU near the
+ application\'s CPU can improve cache behavior and reduce cross-CPU
+ communication.
+
+# NOTES
+
+- The polling thread is per-ring (unless shared via
+ **IORING_SETUP_ATTACH_WQ**). Creating many SQPOLL rings without
+ sharing can consume significant kernel resources.
+
+- SQPOLL rings still require system calls for:
+
+ - Waiting for completions (unless busy-polling the CQ)
+
+ - Waking the thread when it has gone idle
+
+ - Registration operations
+
+- The polling thread inherits resource limits and cgroup membership from
+ the creating process.
+
+- If the polling thread encounters an error it cannot recover from,
+ **IORING_SQ_CQ_OVERFLOW** may be set in *sq-\>kflags*.
+
+- SQPOLL works well in combination with registered files and buffers,
+ which further reduce per-I/O overhead.
+
+# SEE ALSO
+
+**io_uring**(7), **io_uring_setup**(2), **io_uring_enter**(2),
+**io_uring_queue_init_params**(3), **io_uring_register_files**(3),
+**io_uring_registered_buffers**(7)
diff --git a/man/io_uring_sqring_wait.3 b/man/io_uring_sqring_wait.3
deleted file mode 100644
index 4d3a5676..00000000
--- a/man/io_uring_sqring_wait.3
+++ /dev/null
@@ -1,34 +0,0 @@
-.\" Copyright (C) 2022 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_sqring_wait 3 "January 25, 2022" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_sqring_wait \- wait for free space in the SQ ring
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_sqring_wait(struct io_uring *" ring ");"
-.fi
-.SH DESCRIPTION
-.PP
-The function
-.BR io_uring_sqring_wait (3)
-allows the caller to wait for space to free up in the SQ ring belonging to the
-.I ring
-param, which happens when the kernel side thread
-has consumed one or more entries. If the SQ ring is currently non-full,
-no action is taken.
-
-This feature can only be used when the ring has been setup with
-.B IORING_SETUP_SQPOLL
-and hence is using an offloaded approach to request submissions.
-
-.SH RETURN VALUE
-On success it returns the free space. If the kernel does not support the
-feature, -EINVAL is returned.
-.SH SEE ALSO
-.BR io_uring_submit (3),
-.BR io_uring_wait_cqe (3),
-.BR io_uring_wait_cqes (3)
diff --git a/man/io_uring_sqring_wait.3.md b/man/io_uring_sqring_wait.3.md
new file mode 100644
index 00000000..5b389300
--- /dev/null
+++ b/man/io_uring_sqring_wait.3.md
@@ -0,0 +1,44 @@
+.\" Copyright (C) 2022 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 25, 2022
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_sqring_wait
+---
+
+# NAME
+
+io_uring_sqring_wait - wait for free space in the SQ ring
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_sqring_wait(struct io_uring * ring );
+```
+
+# DESCRIPTION
+
+The function **io_uring_sqring_wait**(3) allows the caller to wait for
+space to free up in the SQ ring belonging to the *ring* param, which
+happens when the kernel side thread has consumed one or more entries. If
+the SQ ring is currently non-full, no action is taken.
+
+This feature can only be used when the ring has been setup with
+**IORING_SETUP_SQPOLL** and hence is using an offloaded approach to
+request submissions.
+
+# RETURN VALUE
+
+On success it returns the free space. If the kernel does not support the
+feature, -EINVAL is returned.
+
+# SEE ALSO
+
+**io_uring_submit**(3), **io_uring_wait_cqe**(3),
+**io_uring_wait_cqes**(3)
diff --git a/man/io_uring_submit.3 b/man/io_uring_submit.3
deleted file mode 100644
index c7dbbed2..00000000
--- a/man/io_uring_submit.3
+++ /dev/null
@@ -1,51 +0,0 @@
-.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_submit 3 "November 15, 2021" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_submit \- submit requests to the submission queue
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_submit(struct io_uring *" ring ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_submit (3)
-function submits the next events to the submission queue belonging to the
-.IR ring .
-
-After the caller retrieves a submission queue entry (SQE) with
-.BR io_uring_get_sqe (3)
-and prepares the SQE using one of the provided helpers, it can be submitted with
-.BR io_uring_submit (3) .
-
-.SH RETURN VALUE
-On success
-.BR io_uring_submit (3)
-returns the number of submitted submission queue entries, if SQPOLL is not used.
-If SQPOLL is used, the return value may report a higher number of submitted
-entries than actually submitted. If the user requires accurate information
-about how many submission queue entries have been successfully submitted, while
-using SQPOLL, the user must fall back to repeatedly submitting a single submission
-queue entry. On failure it returns
-.BR -errno .
-.SH NOTES
-For any request that passes in data in a struct, that data must remain
-valid until the request has been successfully submitted. It need not remain
-valid until completion. Once a request has been submitted, the in-kernel
-state is stable. Very early kernels (5.4 and earlier) required state to be
-stable until the completion occurred. Applications can test for this
-behavior by inspecting the
-.B IORING_FEAT_SUBMIT_STABLE
-flag passed back from
-.BR io_uring_queue_init_params (3).
-In general, the man pages for the individual prep helpers will have a note
-mentioning this fact as well, if required for the given command.
-.SH SEE ALSO
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit_and_wait (3),
-.BR io_uring_submit_and_wait_timeout (3)
diff --git a/man/io_uring_submit.3.md b/man/io_uring_submit.3.md
new file mode 100644
index 00000000..0bb76b71
--- /dev/null
+++ b/man/io_uring_submit.3.md
@@ -0,0 +1,59 @@
+.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: November 15, 2021
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_submit
+---
+
+# NAME
+
+io_uring_submit - submit requests to the submission queue
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_submit(struct io_uring * ring );
+```
+
+# DESCRIPTION
+
+The **io_uring_submit**(3) function submits the next events to the
+submission queue belonging to the *ring*.
+
+After the caller retrieves a submission queue entry (SQE) with
+**io_uring_get_sqe**(3) and prepares the SQE using one of the provided
+helpers, it can be submitted with **io_uring_submit**(3)**.**
+
+# RETURN VALUE
+
+On success **io_uring_submit**(3) returns the number of submitted
+submission queue entries, if SQPOLL is not used. If SQPOLL is used, the
+return value may report a higher number of submitted entries than
+actually submitted. If the user requires accurate information about how
+many submission queue entries have been successfully submitted, while
+using SQPOLL, the user must fall back to repeatedly submitting a single
+submission queue entry. On failure it returns **-errno**.
+
+# NOTES
+
+For any request that passes in data in a struct, that data must remain
+valid until the request has been successfully submitted. It need not
+remain valid until completion. Once a request has been submitted, the
+in-kernel state is stable. Very early kernels (5.4 and earlier) required
+state to be stable until the completion occurred. Applications can test
+for this behavior by inspecting the **IORING_FEAT_SUBMIT_STABLE** flag
+passed back from **io_uring_queue_init_params**(3). In general, the man
+pages for the individual prep helpers will have a note mentioning this
+fact as well, if required for the given command.
+
+# SEE ALSO
+
+**io_uring_get_sqe**(3), **io_uring_submit_and_wait**(3),
+**io_uring_submit_and_wait_timeout**(3)
diff --git a/man/io_uring_submit_and_get_events.3 b/man/io_uring_submit_and_get_events.3
deleted file mode 100644
index 9e143d1d..00000000
--- a/man/io_uring_submit_and_get_events.3
+++ /dev/null
@@ -1,31 +0,0 @@
-.\" Copyright (C), 2022 dylany
-.\" You may distribute this file under the terms of the GNU Free
-.\" Documentation License.
-.TH io_uring_submit_and_get_events 3 "September 5, 2022" "liburing-2.3" "liburing Manual"
-.SH NAME
-io_uring_submit_and_get_events \- submit requests to the submission queue and flush completions
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_submit_and_get_events(struct io_uring *" ring ");"
-.fi
-
-.SH DESCRIPTION
-The
-.BR io_uring_submit_and_get_events (3)
-function submits the next events to the submission queue as with
-.BR io_uring_submit (3) .
-After submission it will flush CQEs as with
-.BR io_uring_get_events (3) .
-
-The benefit of this function is that it does both with only one system call.
-
-.SH RETURN VALUE
-On success
-.BR io_uring_submit_and_get_events (3)
-returns the number of submitted submission queue entries. On failure it returns
-.BR -errno .
-.SH SEE ALSO
-.BR io_uring_submit (3),
-.BR io_uring_get_events (3)
diff --git a/man/io_uring_submit_and_get_events.3.md b/man/io_uring_submit_and_get_events.3.md
new file mode 100644
index 00000000..f1eb7daf
--- /dev/null
+++ b/man/io_uring_submit_and_get_events.3.md
@@ -0,0 +1,41 @@
+.\" Copyright (C), 2022 dylany
+.\" You may distribute this file under the terms of the GNU Free
+.\" Documentation License.
+---
+date: September 5, 2022
+footer: liburing-2.3
+header: liburing Manual
+section: 3
+title: io_uring_submit_and_get_events
+---
+
+# NAME
+
+io_uring_submit_and_get_events - submit requests to the submission queue
+and flush completions
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_submit_and_get_events(struct io_uring * ring );
+```
+
+# DESCRIPTION
+
+The **io_uring_submit_and_get_events**(3) function submits the next
+events to the submission queue as with **io_uring_submit**(3)**.** After
+submission it will flush CQEs as with **io_uring_get_events**(3)**.**
+
+The benefit of this function is that it does both with only one system
+call.
+
+# RETURN VALUE
+
+On success **io_uring_submit_and_get_events**(3) returns the number of
+submitted submission queue entries. On failure it returns **-errno**.
+
+# SEE ALSO
+
+**io_uring_submit**(3), **io_uring_get_events**(3)
diff --git a/man/io_uring_submit_and_wait.3 b/man/io_uring_submit_and_wait.3
deleted file mode 100644
index 2351f335..00000000
--- a/man/io_uring_submit_and_wait.3
+++ /dev/null
@@ -1,44 +0,0 @@
-.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_submit_and_wait 3 "November 15, 2021" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_submit_and_wait \- submit requests to the submission queue and wait for completion
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_submit_and_wait(struct io_uring *" ring ","
-.BI " unsigned " wait_nr ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_submit_and_wait (3)
-function submits the next requests from the submission queue belonging to the
-.I ring
-and waits for
-.I wait_nr
-completion events.
-
-After the caller retrieves a submission queue entry (SQE) with
-.BR io_uring_get_sqe (3)
-and prepares the SQE, it can be submitted with
-.BR io_uring_submit_and_wait (3) .
-
-Ideally used with a ring setup with
-.BR IORING_SETUP_SINGLE_ISSUER | IORING_SETUP_DEFER_TASKRUN
-as that will greatly reduce the number of context switches that an application
-will see waiting on multiple requests.
-
-.SH RETURN VALUE
-On success
-.BR io_uring_submit_and_wait (3)
-returns the number of submitted submission queue entries. On failure it returns
-.BR -errno .
-.SH SEE ALSO
-.BR io_uring_queue_init_params (3),
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_submit_and_wait_timeout (3)
diff --git a/man/io_uring_submit_and_wait.3.md b/man/io_uring_submit_and_wait.3.md
new file mode 100644
index 00000000..c3ee1f43
--- /dev/null
+++ b/man/io_uring_submit_and_wait.3.md
@@ -0,0 +1,50 @@
+.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: November 15, 2021
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_submit_and_wait
+---
+
+# NAME
+
+io_uring_submit_and_wait - submit requests to the submission queue and
+wait for completion
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_submit_and_wait(struct io_uring * ring ,
+ unsigned wait_nr );
+```
+
+# DESCRIPTION
+
+The **io_uring_submit_and_wait**(3) function submits the next requests
+from the submission queue belonging to the *ring* and waits for
+*wait_nr* completion events.
+
+After the caller retrieves a submission queue entry (SQE) with
+**io_uring_get_sqe**(3) and prepares the SQE, it can be submitted with
+**io_uring_submit_and_wait**(3)**.**
+
+Ideally used with a ring setup with
+**IORING_SETUP_SINGLE_ISSUER**\|**IORING_SETUP_DEFER_TASKRUN** as that
+will greatly reduce the number of context switches that an application
+will see waiting on multiple requests.
+
+# RETURN VALUE
+
+On success **io_uring_submit_and_wait**(3) returns the number of
+submitted submission queue entries. On failure it returns **-errno**.
+
+# SEE ALSO
+
+**io_uring_queue_init_params**(3), **io_uring_get_sqe**(3),
+**io_uring_submit**(3), **io_uring_submit_and_wait_timeout**(3)
diff --git a/man/io_uring_submit_and_wait_min_timeout.3 b/man/io_uring_submit_and_wait_min_timeout.3
deleted file mode 100644
index 6a52806f..00000000
--- a/man/io_uring_submit_and_wait_min_timeout.3
+++ /dev/null
@@ -1,119 +0,0 @@
-.\" Copyright (C) 2024 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_submit_and_wait_min_timeout 3 "Jan 11, 2024" "liburing-2.8" "liburing Manual"
-.SH NAME
-io_uring_submit_and_wait_min_timeout \- submit requests to the submission queue and
-wait for the completion with both batch and normal timeout
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_submit_and_wait_min_timeout(struct io_uring *" ring ","
-.BI " struct io_uring_cqe **" cqe_ptr ","
-.BI " unsigned " wait_nr ","
-.BI " struct __kernel_timespec *" ts ","
-.BI " unsigned int " min_wait_usec ",
-.BI " sigset_t *" sigmask ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_submit_and_wait_min_timeout (3)
-function submits the next requests from the submission queue belonging to the
-.I ring
-and waits for
-.I wait_nr
-completion events, or until the timeout
-.I ts
-expires. The completion events are stored in the
-.I cqe_ptr
-array. If non-zero,
-.I min_wait_usec
-denotes a timeout for the
-.I wait_nr
-batch.
-
-The
-.I sigmask
-specifies the set of signals to block. If set, it is equivalent to atomically
-executing the following calls:
-.PP
-.in +4n
-.EX
-sigset_t origmask;
-
-pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);
-ret = io_uring_submit_and_wait_min_timeout(ring, cqe, wait_nr, ts, min_wait, NULL);
-pthread_sigmask(SIG_SETMASK, &origmask, NULL);
-.EE
-.in
-.PP
-This works like
-.BR io_uring_submit_and_wait_timeout (3)
-with the twist that it applies a minimum timeout for the requested batch size
-of requests to wait for. While
-.BR io_uring_submit_and_wait_timeout (3)
-waits for as long as
-.IR ts
-specifies, or until
-.IR wait_nr
-of request completions have been received, if
-.IR min_wait_usec
-is set, then this is the timeout for the
-.IR wait_nr
-number of requests. If the requested number of completions have been received
-within
-.IR min_wait_usec
-number of microseconds, then the function returns successfully. If that isn't
-the case, once
-.IR min_wait_usec
-time has passed, control is returned if any completions have been posted. If
-no completions have been posted, the kernel switches to a normal wait of up
-to
-.IR ts
-specified amount of time, subtracting the time already waited. If any
-completions are posted after this happens, control is returned immediately to
-the application.
-
-This differs from the normal timeout waiting in that waiting continues post
-the initial timeout, if and only if no completions have been posted. It's meant
-to be used to optimize batch waiting for requests, where the application
-allots a budget of
-.IR min_wait_usec
-amount of time to receive
-.IR wait_nr
-number of completions, but if none are received, then waiting can continue
-without incurring extra context switches or extra kernel/user transitions.
-
-Can be used with any ring, as long as the kernel supports it. Support is
-indicated by checking the
-.BR IORING_FEAT_MIN_TIMEOUT
-feature flag after the ring has been setup. Ideally used with a ring setup
-with
-.BR IORING_SETUP_SINGLE_ISSUER | IORING_SETUP_DEFER_TASKRUN
-as that will greatly reduce the number of context switches that an application
-will see waiting on multiple requests.
-
-Available since 6.12.
-
-.SH RETURN VALUE
-On success
-.BR io_uring_submit_and_wait_min_timeout (3)
-returns the number of submitted submission queue entries. On failure it returns
-.BR -errno .
-If the kernel doesn't support this functionality,
-.BR -EINVAL
-will be returned. See note on the feature flag.
-The most common failure case is not receiving a completion within the specified
-timeout,
-.B -ETIME
-is returned in this case.
-.SH SEE ALSO
-.BR io_uring_queue_init_params (3),
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_submit_and_wait (3),
-.BR io_uring_submit_and_wait_timeout (3),
-.BR io_uring_wait_cqe (3)
diff --git a/man/io_uring_submit_and_wait_min_timeout.3.md b/man/io_uring_submit_and_wait_min_timeout.3.md
new file mode 100644
index 00000000..ff0d3c15
--- /dev/null
+++ b/man/io_uring_submit_and_wait_min_timeout.3.md
@@ -0,0 +1,94 @@
+.\" Copyright (C) 2024 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: Jan 11, 2024
+footer: liburing-2.8
+header: liburing Manual
+section: 3
+title: io_uring_submit_and_wait_min_timeout
+---
+
+# NAME
+
+io_uring_submit_and_wait_min_timeout - submit requests to the submission
+queue and wait for the completion with both batch and normal timeout
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_submit_and_wait_min_timeout(struct io_uring * ring ,
+ struct io_uring_cqe ** cqe_ptr ,
+ unsigned wait_nr ,
+ struct __kernel_timespec * ts ,
+ unsigned int min_wait_usec ,
+ sigset_t * sigmask );
+```
+
+# DESCRIPTION
+
+The **io_uring_submit_and_wait_min_timeout**(3) function submits the
+next requests from the submission queue belonging to the *ring* and
+waits for *wait_nr* completion events, or until the timeout *ts*
+expires. The completion events are stored in the *cqe_ptr* array. If
+non-zero, *min_wait_usec* denotes a timeout for the *wait_nr* batch.
+
+The *sigmask* specifies the set of signals to block. If set, it is
+equivalent to atomically executing the following calls:
+
+``` text
+sigset_t origmask;
+
+pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);
+ret = io_uring_submit_and_wait_min_timeout(ring, cqe, wait_nr, ts, min_wait, NULL);
+pthread_sigmask(SIG_SETMASK, &origmask, NULL);
+```
+
+This works like **io_uring_submit_and_wait_timeout**(3) with the twist
+that it applies a minimum timeout for the requested batch size of
+requests to wait for. While **io_uring_submit_and_wait_timeout**(3)
+waits for as long as *ts* specifies, or until *wait_nr* of request
+completions have been received, if *min_wait_usec* is set, then this is
+the timeout for the *wait_nr* number of requests. If the requested
+number of completions have been received within *min_wait_usec* number
+of microseconds, then the function returns successfully. If that isn\'t
+the case, once *min_wait_usec* time has passed, control is returned if
+any completions have been posted. If no completions have been posted,
+the kernel switches to a normal wait of up to *ts* specified amount of
+time, subtracting the time already waited. If any completions are posted
+after this happens, control is returned immediately to the application.
+
+This differs from the normal timeout waiting in that waiting continues
+post the initial timeout, if and only if no completions have been
+posted. It\'s meant to be used to optimize batch waiting for requests,
+where the application allots a budget of *min_wait_usec* amount of time
+to receive *wait_nr* number of completions, but if none are received,
+then waiting can continue without incurring extra context switches or
+extra kernel/user transitions.
+
+Can be used with any ring, as long as the kernel supports it. Support is
+indicated by checking the **IORING_FEAT_MIN_TIMEOUT** feature flag after
+the ring has been setup. Ideally used with a ring setup with
+**IORING_SETUP_SINGLE_ISSUER**\|**IORING_SETUP_DEFER_TASKRUN** as that
+will greatly reduce the number of context switches that an application
+will see waiting on multiple requests.
+
+Available since 6.12.
+
+# RETURN VALUE
+
+On success **io_uring_submit_and_wait_min_timeout**(3) returns the
+number of submitted submission queue entries. On failure it returns
+**-errno**. If the kernel doesn\'t support this functionality,
+**-EINVAL** will be returned. See note on the feature flag. The most
+common failure case is not receiving a completion within the specified
+timeout, **-ETIME** is returned in this case.
+
+# SEE ALSO
+
+**io_uring_queue_init_params**(3), **io_uring_get_sqe**(3),
+**io_uring_submit**(3), **io_uring_submit_and_wait**(3),
+**io_uring_submit_and_wait_timeout**(3), **io_uring_wait_cqe**(3)
diff --git a/man/io_uring_submit_and_wait_reg.3 b/man/io_uring_submit_and_wait_reg.3
deleted file mode 100644
index fc0bd76a..00000000
--- a/man/io_uring_submit_and_wait_reg.3
+++ /dev/null
@@ -1,64 +0,0 @@
-.\" Copyright (C) 2024 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_submit_and_wait_reg 3 "November 2, 2024" "liburing-2.9" "liburing Manual"
-.SH NAME
-io_uring_submit_and_wait_reg \- Sets up and registers fixed wait regions
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_submit_and_wait_reg(struct io_uring *" ring ","
-.BI " struct io_uring_cqe **"cqe_ptr ","
-.BI " unsigned "wait_nr ","
-.BI " int "reg_index ");"
-.PP
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_submit_and_wait_reg (3)
-submits previously prepared requests in the ring
-.IR ring
-and waits for
-.IR wait_nr
-completions using the registered wait index of
-.IR reg_index .
-Upon successful return, the completion events are stored in the
-.IR cqe_ptr
-array.
-
-This function works like
-.BR io_uring_submit_and_wait_min_timeout (3)
-in that it supports all the features of that helper, but rather than pass in
-all the information in a struct that needs copying, it references a registered
-wait index for which previously registered wait region holds information
-about how the wait should be performed. That includes information such as
-the overall timeout, the minimum timeout to be used, and so forth. See
-.BR io_uring_setup_register_region (3)
-for the details on registered regions, specifically for registered wait
-regions.
-
-Using registered wait regions has less overhead then other wait methods, as
-no copying of data is needed.
-
-It's valid to use this function purely for waiting on events, even if no
-new requests should be submitted.
-
-.SH RETURN VALUE
-On success
-.BR io_uring_submit_and_wait_reg (3)
-returns the number of new requests submitted. On failure it returns
-.BR -errno .
-If the kernel doesn't support this functionality,
-.BR -EINVAL
-will be returned. If no events are submitted and the wait operation times
-out, then
-.BR -ETIME
-will be returned.
-
-.SH SEE ALSO
-.BR io_uring_register_region (3) ,
-.BR io_uring_submit_and_wait_min_timeout (3) ,
-.BR io_uring_submit_and_wait_timeout (3)
diff --git a/man/io_uring_submit_and_wait_reg.3.md b/man/io_uring_submit_and_wait_reg.3.md
new file mode 100644
index 00000000..3aa45197
--- /dev/null
+++ b/man/io_uring_submit_and_wait_reg.3.md
@@ -0,0 +1,62 @@
+.\" Copyright (C) 2024 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: November 2, 2024
+footer: liburing-2.9
+header: liburing Manual
+section: 3
+title: io_uring_submit_and_wait_reg
+---
+
+# NAME
+
+io_uring_submit_and_wait_reg - Sets up and registers fixed wait regions
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_submit_and_wait_reg(struct io_uring * ring ,
+ struct io_uring_cqe **cqe_ptr ,
+ unsigned wait_nr ,
+ int reg_index );
+```
+
+# DESCRIPTION
+
+The **io_uring_submit_and_wait_reg**(3) submits previously prepared
+requests in the ring *ring* and waits for *wait_nr* completions using
+the registered wait index of *reg_index*. Upon successful return, the
+completion events are stored in the *cqe_ptr* array.
+
+This function works like **io_uring_submit_and_wait_min_timeout**(3) in
+that it supports all the features of that helper, but rather than pass
+in all the information in a struct that needs copying, it references a
+registered wait index for which previously registered wait region holds
+information about how the wait should be performed. That includes
+information such as the overall timeout, the minimum timeout to be used,
+and so forth. See **io_uring_setup_register_region**(3) for the details
+on registered regions, specifically for registered wait regions.
+
+Using registered wait regions has less overhead then other wait methods,
+as no copying of data is needed.
+
+It\'s valid to use this function purely for waiting on events, even if
+no new requests should be submitted.
+
+# RETURN VALUE
+
+On success **io_uring_submit_and_wait_reg**(3) returns the number of new
+requests submitted. On failure it returns **-errno**. If the kernel
+doesn\'t support this functionality, **-EINVAL** will be returned. If no
+events are submitted and the wait operation times out, then **-ETIME**
+will be returned.
+
+# SEE ALSO
+
+**io_uring_register_region**(3)**,**
+**io_uring_submit_and_wait_min_timeout**(3)**,**
+**io_uring_submit_and_wait_timeout**(3)
diff --git a/man/io_uring_submit_and_wait_timeout.3 b/man/io_uring_submit_and_wait_timeout.3
deleted file mode 100644
index 74611766..00000000
--- a/man/io_uring_submit_and_wait_timeout.3
+++ /dev/null
@@ -1,74 +0,0 @@
-.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_submit_and_wait_timeout 3 "November 15, 2021" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_submit_and_wait_timeout \- submit requests to the submission queue and
-wait for the completion with timeout
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_submit_and_wait_timeout(struct io_uring *" ring ","
-.BI " struct io_uring_cqe **" cqe_ptr ","
-.BI " unsigned " wait_nr ","
-.BI " struct __kernel_timespec *" ts ","
-.BI " sigset_t *" sigmask ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_submit_and_wait_timeout (3)
-function submits the next requests from the submission queue belonging to the
-.I ring
-and waits for
-.I wait_nr
-completion events, or until the timeout
-.I ts
-expires. The completion events are stored in the
-.I cqe_ptr
-array.
-.PP
-The
-.I sigmask
-specifies the set of signals to block. If set, it is equivalent to atomically
-executing the following calls:
-.PP
-.in +4n
-.EX
-sigset_t origmask;
-
-pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);
-ret = io_uring_submit_and_wait_timeout(ring, cqe, wait_nr, ts, NULL);
-pthread_sigmask(SIG_SETMASK, &origmask, NULL);
-.EE
-.in
-.PP
-After the caller retrieves a submission queue entry (SQE) with
-.BR io_uring_get_sqe (3)
-and prepares the SQE, it can be submitted with
-.BR io_uring_submit_and_wait_timeout (3) .
-
-Ideally used with a ring setup with
-.BR IORING_SETUP_SINGLE_ISSUER | IORING_SETUP_DEFER_TASKRUN
-as that will greatly reduce the number of context switches that an application
-will see waiting on multiple requests.
-
-.SH RETURN VALUE
-On success
-.BR io_uring_submit_and_wait_timeout (3)
-returns the number of submitted submission queue entries. On failure it returns
-.BR -errno .
-Note that in earlier versions of the liburing library, the return value was 0
-on success.
-The most common failure case is not receiving a completion within the specified
-timeout,
-.B -ETIME
-is returned in this case.
-.SH SEE ALSO
-.BR io_uring_queue_init_params (3),
-.BR io_uring_get_sqe (3),
-.BR io_uring_submit (3),
-.BR io_uring_submit_and_wait (3),
-.BR io_uring_wait_cqe (3)
diff --git a/man/io_uring_submit_and_wait_timeout.3.md b/man/io_uring_submit_and_wait_timeout.3.md
new file mode 100644
index 00000000..3dcba2dc
--- /dev/null
+++ b/man/io_uring_submit_and_wait_timeout.3.md
@@ -0,0 +1,70 @@
+.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: November 15, 2021
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_submit_and_wait_timeout
+---
+
+# NAME
+
+io_uring_submit_and_wait_timeout - submit requests to the submission
+queue and wait for the completion with timeout
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_submit_and_wait_timeout(struct io_uring * ring ,
+ struct io_uring_cqe ** cqe_ptr ,
+ unsigned wait_nr ,
+ struct __kernel_timespec * ts ,
+ sigset_t * sigmask );
+```
+
+# DESCRIPTION
+
+The **io_uring_submit_and_wait_timeout**(3) function submits the next
+requests from the submission queue belonging to the *ring* and waits for
+*wait_nr* completion events, or until the timeout *ts* expires. The
+completion events are stored in the *cqe_ptr* array.
+
+The *sigmask* specifies the set of signals to block. If set, it is
+equivalent to atomically executing the following calls:
+
+``` text
+sigset_t origmask;
+
+pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);
+ret = io_uring_submit_and_wait_timeout(ring, cqe, wait_nr, ts, NULL);
+pthread_sigmask(SIG_SETMASK, &origmask, NULL);
+```
+
+After the caller retrieves a submission queue entry (SQE) with
+**io_uring_get_sqe**(3) and prepares the SQE, it can be submitted with
+**io_uring_submit_and_wait_timeout**(3)**.**
+
+Ideally used with a ring setup with
+**IORING_SETUP_SINGLE_ISSUER**\|**IORING_SETUP_DEFER_TASKRUN** as that
+will greatly reduce the number of context switches that an application
+will see waiting on multiple requests.
+
+# RETURN VALUE
+
+On success **io_uring_submit_and_wait_timeout**(3) returns the number of
+submitted submission queue entries. On failure it returns **-errno**.
+Note that in earlier versions of the liburing library, the return value
+was 0 on success. The most common failure case is not receiving a
+completion within the specified timeout, **-ETIME** is returned in this
+case.
+
+# SEE ALSO
+
+**io_uring_queue_init_params**(3), **io_uring_get_sqe**(3),
+**io_uring_submit**(3), **io_uring_submit_and_wait**(3),
+**io_uring_wait_cqe**(3)
diff --git a/man/io_uring_unregister_buf_ring.3 b/man/io_uring_unregister_buf_ring.3
deleted file mode 100644
index ee87e860..00000000
--- a/man/io_uring_unregister_buf_ring.3
+++ /dev/null
@@ -1,30 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_unregister_buf_ring 3 "May 18, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_unregister_buf_ring \- unregister a previously registered buffer ring
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_unregister_buf_ring(struct io_uring *" ring ",
-.BI " int " bgid ");"
-.BI "
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_unregister_buf_ring (3)
-function unregisters a previously registered shared buffer ring indicated by
-.IR bgid .
-
-.SH RETURN VALUE
-On success
-.BR io_uring_unregister_buf_ring (3)
-returns 0. On failure it returns
-.BR -errno .
-.SH SEE ALSO
-.BR io_uring_register_buf_ring (3),
-.BR io_uring_buf_ring_free (3)
diff --git a/man/io_uring_unregister_buf_ring.3.md b/man/io_uring_unregister_buf_ring.3.md
new file mode 100644
index 00000000..054c5d26
--- /dev/null
+++ b/man/io_uring_unregister_buf_ring.3.md
@@ -0,0 +1,40 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: May 18, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_unregister_buf_ring
+---
+
+# NAME
+
+io_uring_unregister_buf_ring - unregister a previously registered buffer
+ring
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_unregister_buf_ring(struct io_uring * ring ,
+ int bgid );
+
+```
+
+# DESCRIPTION
+
+The **io_uring_unregister_buf_ring**(3) function unregisters a
+previously registered shared buffer ring indicated by *bgid*.
+
+# RETURN VALUE
+
+On success **io_uring_unregister_buf_ring**(3) returns 0. On failure it
+returns **-errno**.
+
+# SEE ALSO
+
+**io_uring_register_buf_ring**(3), **io_uring_buf_ring_free**(3)
diff --git a/man/io_uring_unregister_buffers.3 b/man/io_uring_unregister_buffers.3
deleted file mode 100644
index f066679b..00000000
--- a/man/io_uring_unregister_buffers.3
+++ /dev/null
@@ -1,27 +0,0 @@
-.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_unregister_buffers 3 "November 15, 2021" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_unregister_buffers \- unregister buffers for fixed buffer operations
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_unregister_buffers(struct io_uring *" ring ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_unregister_buffers (3)
-function unregisters the fixed buffers previously registered to the
-.IR ring .
-
-.SH RETURN VALUE
-On success
-.BR io_uring_unregister_buffers (3)
-returns 0. On failure it returns
-.BR -errno .
-.SH SEE ALSO
-.BR io_uring_register_buffers (3)
diff --git a/man/io_uring_unregister_buffers.3.md b/man/io_uring_unregister_buffers.3.md
new file mode 100644
index 00000000..cc9ef437
--- /dev/null
+++ b/man/io_uring_unregister_buffers.3.md
@@ -0,0 +1,38 @@
+.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: November 15, 2021
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_unregister_buffers
+---
+
+# NAME
+
+io_uring_unregister_buffers - unregister buffers for fixed buffer
+operations
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_unregister_buffers(struct io_uring * ring );
+```
+
+# DESCRIPTION
+
+The **io_uring_unregister_buffers**(3) function unregisters the fixed
+buffers previously registered to the *ring*.
+
+# RETURN VALUE
+
+On success **io_uring_unregister_buffers**(3) returns 0. On failure it
+returns **-errno**.
+
+# SEE ALSO
+
+**io_uring_register_buffers**(3)
diff --git a/man/io_uring_unregister_files.3 b/man/io_uring_unregister_files.3
deleted file mode 100644
index c468d081..00000000
--- a/man/io_uring_unregister_files.3
+++ /dev/null
@@ -1,27 +0,0 @@
-.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_unregister_files 3 "November 15, 2021" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_unregister_files \- unregister file descriptors
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_unregister_files(struct io_uring *" ring ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_unregister_files (3)
-function unregisters the file descriptors previously registered to the
-.IR ring .
-
-.SH RETURN VALUE
-On success
-.BR io_uring_unregister_files (3)
-returns 0. On failure it returns
-.BR -errno .
-.SH SEE ALSO
-.BR io_uring_register_files (3)
diff --git a/man/io_uring_unregister_files.3.md b/man/io_uring_unregister_files.3.md
new file mode 100644
index 00000000..63434835
--- /dev/null
+++ b/man/io_uring_unregister_files.3.md
@@ -0,0 +1,37 @@
+.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: November 15, 2021
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_unregister_files
+---
+
+# NAME
+
+io_uring_unregister_files - unregister file descriptors
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_unregister_files(struct io_uring * ring );
+```
+
+# DESCRIPTION
+
+The **io_uring_unregister_files**(3) function unregisters the file
+descriptors previously registered to the *ring*.
+
+# RETURN VALUE
+
+On success **io_uring_unregister_files**(3) returns 0. On failure it
+returns **-errno**.
+
+# SEE ALSO
+
+**io_uring_register_files**(3)
diff --git a/man/io_uring_unregister_napi.3 b/man/io_uring_unregister_napi.3
deleted file mode 100644
index f7087ef7..00000000
--- a/man/io_uring_unregister_napi.3
+++ /dev/null
@@ -1,27 +0,0 @@
-.\" Copyright (C) 2022 Stefan Roesch <shr@devkernel.io>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_unregister_napi 3 "November 16, 2022" "liburing-2.4" "liburing Manual"
-.SH NAME
-io_uring_unregister_napi \- unregister NAPI busy poll settings
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_unregister_napi(struct io_uring *" ring ","
-.BI " struct io_uring_napi *" napi)
-.PP
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_unregister_napi (3)
-function unregisters the NAPI busy poll settings for subsequent operations.
-
-.SH RETURN VALUE
-On success
-.BR io_uring_unregister_napi (3)
-return 0. On failure they return
-.BR -errno .
-It also updates the napi structure with the current values.
diff --git a/man/io_uring_unregister_napi.3.md b/man/io_uring_unregister_napi.3.md
new file mode 100644
index 00000000..07b93a7e
--- /dev/null
+++ b/man/io_uring_unregister_napi.3.md
@@ -0,0 +1,35 @@
+.\" Copyright (C) 2022 Stefan Roesch <shr@devkernel.io>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: November 16, 2022
+footer: liburing-2.4
+header: liburing Manual
+section: 3
+title: io_uring_unregister_napi
+---
+
+# NAME
+
+io_uring_unregister_napi - unregister NAPI busy poll settings
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_unregister_napi(struct io_uring * ring ,
+ struct io_uring_napi * napi)
+```
+
+# DESCRIPTION
+
+The **io_uring_unregister_napi**(3) function unregisters the NAPI busy
+poll settings for subsequent operations.
+
+# RETURN VALUE
+
+On success **io_uring_unregister_napi**(3) return 0. On failure they
+return **-errno**. It also updates the napi structure with the current
+values.
diff --git a/man/io_uring_unregister_personality.3 b/man/io_uring_unregister_personality.3
deleted file mode 100644
index 14a808e2..00000000
--- a/man/io_uring_unregister_personality.3
+++ /dev/null
@@ -1,33 +0,0 @@
-.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_unregister_personality 3 "January 18, 2025" "liburing-2.4" "liburing Manual"
-.SH NAME
-io_uring_unregister_personality \- unregister a personality from io_uring
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_unregister_personality(struct io_uring *" ring ", int " id ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_unregister_personality (3)
-function unregisters a previously registered personality from the io_uring
-instance specified by
-.IR ring .
-The
-.I id
-argument is the personality ID returned from a previous call to
-.BR io_uring_register_personality (3).
-
-After unregistering, the personality ID is no longer valid and must not be
-used in future submissions.
-
-.SH RETURN VALUE
-Returns 0 on success. On error, a negative errno value is returned.
-.SH SEE ALSO
-.BR io_uring_register_personality (3),
-.BR io_uring_register (2)
diff --git a/man/io_uring_unregister_personality.3.md b/man/io_uring_unregister_personality.3.md
new file mode 100644
index 00000000..3ac85151
--- /dev/null
+++ b/man/io_uring_unregister_personality.3.md
@@ -0,0 +1,41 @@
+.\" Copyright (C) 2025 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: January 18, 2025
+footer: liburing-2.4
+header: liburing Manual
+section: 3
+title: io_uring_unregister_personality
+---
+
+# NAME
+
+io_uring_unregister_personality - unregister a personality from io_uring
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_unregister_personality(struct io_uring * ring , int id );
+```
+
+# DESCRIPTION
+
+The **io_uring_unregister_personality**(3) function unregisters a
+previously registered personality from the io_uring instance specified
+by *ring*. The *id* argument is the personality ID returned from a
+previous call to **io_uring_register_personality**(3).
+
+After unregistering, the personality ID is no longer valid and must not
+be used in future submissions.
+
+# RETURN VALUE
+
+Returns 0 on success. On error, a negative errno value is returned.
+
+# SEE ALSO
+
+**io_uring_register_personality**(3), **io_uring_register**(2)
diff --git a/man/io_uring_unregister_ring_fd.3 b/man/io_uring_unregister_ring_fd.3
deleted file mode 100644
index 85aca141..00000000
--- a/man/io_uring_unregister_ring_fd.3
+++ /dev/null
@@ -1,32 +0,0 @@
-.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_unregister_ring_fd 3 "March 11, 2022" "liburing-2.2" "liburing Manual"
-.SH NAME
-io_uring_unregister_ring_fd \- unregister a ring file descriptor
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_unregister_ring_fd(struct io_uring *" ring ");"
-.fi
-.SH DESCRIPTION
-.PP
-.BR io_uring_unregister_ring_fd (3)
-unregisters the file descriptor of the ring.
-
-Unregisters a ring descriptor previously registered with the task. This is
-done automatically when
-.BR io_uring_queue_exit (3)
-is called, but can also be done to free up space for new ring registrations.
-For more information on ring descriptor registration, see
-.BR io_uring_register_ring_fd (3)
-
-.SH RETURN VALUE
-Returns 1 on success, indicating that one file descriptor was unregistered, or
-.BR -errno
-on error.
-.SH SEE ALSO
-.BR io_uring_register_ring_fd (3),
-.BR io_uring_register_files (3)
diff --git a/man/io_uring_unregister_ring_fd.3.md b/man/io_uring_unregister_ring_fd.3.md
new file mode 100644
index 00000000..58baca47
--- /dev/null
+++ b/man/io_uring_unregister_ring_fd.3.md
@@ -0,0 +1,43 @@
+.\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: March 11, 2022
+footer: liburing-2.2
+header: liburing Manual
+section: 3
+title: io_uring_unregister_ring_fd
+---
+
+# NAME
+
+io_uring_unregister_ring_fd - unregister a ring file descriptor
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_unregister_ring_fd(struct io_uring * ring );
+```
+
+# DESCRIPTION
+
+**io_uring_unregister_ring_fd**(3) unregisters the file descriptor of
+the ring.
+
+Unregisters a ring descriptor previously registered with the task. This
+is done automatically when **io_uring_queue_exit**(3) is called, but can
+also be done to free up space for new ring registrations. For more
+information on ring descriptor registration, see
+**io_uring_register_ring_fd**(3)
+
+# RETURN VALUE
+
+Returns 1 on success, indicating that one file descriptor was
+unregistered, or **-errno** on error.
+
+# SEE ALSO
+
+**io_uring_register_ring_fd**(3), **io_uring_register_files**(3)
diff --git a/man/io_uring_wait_cqe.3 b/man/io_uring_wait_cqe.3
deleted file mode 100644
index c2fffede..00000000
--- a/man/io_uring_wait_cqe.3
+++ /dev/null
@@ -1,41 +0,0 @@
-.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_wait_cqe 3 "November 15, 2021" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_wait_cqe \- wait for one io_uring completion event
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_wait_cqe(struct io_uring *" ring ","
-.BI " struct io_uring_cqe **" cqe_ptr ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_wait_cqe (3)
-function waits for an IO completion from the queue belonging to the
-.I ring
-param, waiting for it if necessary. If an event is already available in
-the ring when invoked, no waiting will occur. The
-.I cqe_ptr
-param is filled in on success.
-
-After the caller has submitted a request with
-.BR io_uring_submit (3),
-the application can retrieve the completion with
-.BR io_uring_wait_cqe (3).
-
-.SH RETURN VALUE
-On success
-.BR io_uring_wait_cqe (3)
-returns 0 and the cqe_ptr param is filled in. On failure it returns
-.BR -errno .
-The return value indicates the result of waiting for a CQE, and it has no
-relation to the CQE result itself.
-.SH SEE ALSO
-.BR io_uring_submit (3),
-.BR io_uring_wait_cqe_timeout (3),
-.BR io_uring_wait_cqes (3)
diff --git a/man/io_uring_wait_cqe.3.md b/man/io_uring_wait_cqe.3.md
new file mode 100644
index 00000000..1497a657
--- /dev/null
+++ b/man/io_uring_wait_cqe.3.md
@@ -0,0 +1,47 @@
+.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: November 15, 2021
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_wait_cqe
+---
+
+# NAME
+
+io_uring_wait_cqe - wait for one io_uring completion event
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_wait_cqe(struct io_uring * ring ,
+ struct io_uring_cqe ** cqe_ptr );
+```
+
+# DESCRIPTION
+
+The **io_uring_wait_cqe**(3) function waits for an IO completion from
+the queue belonging to the *ring* param, waiting for it if necessary. If
+an event is already available in the ring when invoked, no waiting will
+occur. The *cqe_ptr* param is filled in on success.
+
+After the caller has submitted a request with **io_uring_submit**(3),
+the application can retrieve the completion with
+**io_uring_wait_cqe**(3).
+
+# RETURN VALUE
+
+On success **io_uring_wait_cqe**(3) returns 0 and the cqe_ptr param is
+filled in. On failure it returns **-errno**. The return value indicates
+the result of waiting for a CQE, and it has no relation to the CQE
+result itself.
+
+# SEE ALSO
+
+**io_uring_submit**(3), **io_uring_wait_cqe_timeout**(3),
+**io_uring_wait_cqes**(3)
diff --git a/man/io_uring_wait_cqe_nr.3 b/man/io_uring_wait_cqe_nr.3
deleted file mode 100644
index 9e19098f..00000000
--- a/man/io_uring_wait_cqe_nr.3
+++ /dev/null
@@ -1,49 +0,0 @@
-.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_wait_cqe_nr 3 "November 15, 2021" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_wait_cqe_nr \- wait for one or more io_uring completion events
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_wait_cqe_nr(struct io_uring *" ring ","
-.BI " struct io_uring_cqe **" cqe_ptr ","
-.BI " unsigned " wait_nr ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_wait_cqe_nr (3)
-function returns
-.I wait_nr
-IO completion events from the queue belonging to the
-.I ring
-param, waiting for it if necessary. If the requested number of events are
-already available in the ring when invoked, no waiting will occur. The
-.I cqe_ptr
-param is filled in on success.
-
-After the caller has submitted a request with
-.BR io_uring_submit (3),
-the application can retrieve the completion with
-.BR io_uring_wait_cqe (3).
-
-Ideally used with a ring setup with
-.BR IORING_SETUP_SINGLE_ISSUER | IORING_SETUP_DEFER_TASKRUN
-as that will greatly reduce the number of context switches that an application
-will see waiting on multiple requests.
-
-.SH RETURN VALUE
-On success
-.BR io_uring_wait_cqe_nr (3)
-returns 0 and the cqe_ptr param is filled in. On failure it returns
-.BR -errno .
-The return value indicates the result of waiting for a CQE, and it has no
-relation to the CQE result itself.
-.SH SEE ALSO
-.BR io_uring_queue_init_params (3),
-.BR io_uring_submit (3),
-.BR io_uring_wait_cqes (3)
diff --git a/man/io_uring_wait_cqe_nr.3.md b/man/io_uring_wait_cqe_nr.3.md
new file mode 100644
index 00000000..0871f976
--- /dev/null
+++ b/man/io_uring_wait_cqe_nr.3.md
@@ -0,0 +1,54 @@
+.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: November 15, 2021
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_wait_cqe_nr
+---
+
+# NAME
+
+io_uring_wait_cqe_nr - wait for one or more io_uring completion events
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_wait_cqe_nr(struct io_uring * ring ,
+ struct io_uring_cqe ** cqe_ptr ,
+ unsigned wait_nr );
+```
+
+# DESCRIPTION
+
+The **io_uring_wait_cqe_nr**(3) function returns *wait_nr* IO completion
+events from the queue belonging to the *ring* param, waiting for it if
+necessary. If the requested number of events are already available in
+the ring when invoked, no waiting will occur. The *cqe_ptr* param is
+filled in on success.
+
+After the caller has submitted a request with **io_uring_submit**(3),
+the application can retrieve the completion with
+**io_uring_wait_cqe**(3).
+
+Ideally used with a ring setup with
+**IORING_SETUP_SINGLE_ISSUER**\|**IORING_SETUP_DEFER_TASKRUN** as that
+will greatly reduce the number of context switches that an application
+will see waiting on multiple requests.
+
+# RETURN VALUE
+
+On success **io_uring_wait_cqe_nr**(3) returns 0 and the cqe_ptr param
+is filled in. On failure it returns **-errno**. The return value
+indicates the result of waiting for a CQE, and it has no relation to the
+CQE result itself.
+
+# SEE ALSO
+
+**io_uring_queue_init_params**(3), **io_uring_submit**(3),
+**io_uring_wait_cqes**(3)
diff --git a/man/io_uring_wait_cqe_timeout.3 b/man/io_uring_wait_cqe_timeout.3
deleted file mode 100644
index d4cfe508..00000000
--- a/man/io_uring_wait_cqe_timeout.3
+++ /dev/null
@@ -1,62 +0,0 @@
-.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_wait_cqe_timeout 3 "November 15, 2021" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_wait_cqe_timeout \- wait for one io_uring completion event with timeout
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_wait_cqe_timeout(struct io_uring *" ring ","
-.BI " struct io_uring_cqe **" cqe_ptr ","
-.BI " struct __kernel_timespec *" ts ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_wait_cqe_timeout (3)
-function waits for one IO completion to be available from the queue belonging
-to the
-.I ring
-param, waiting for it if necessary or until the timeout
-.I ts
-expires. If an event is already available in the ring when invoked, no waiting
-will occur.
-
-The
-.I cqe_ptr
-param is filled in on success.
-
-If
-.I ts
-is specified and an older kernel without
-.B IORING_FEAT_EXT_ARG
-is used, the application does not need to call
-.BR io_uring_submit (3)
-before calling
-.BR io_uring_wait_cqes (3).
-For newer kernels with that feature flag set, there is no implied submit
-when waiting for a request.
-
-If
-.I ts
-is
-.B NULL ,
-then this behaves like
-.BR io_uring_wait_cqe (3)
-in that it will wait forever for an event.
-
-.SH RETURN VALUE
-On success
-.BR io_uring_wait_cqe_timeout (3)
-returns 0 and the cqe_ptr param is filled in. On failure it returns
-.BR -errno .
-The return value indicates the result of waiting for a CQE, and it has no
-relation to the CQE result itself. If a timeout occurs, it will return
-.BR -ETIME .
-.SH SEE ALSO
-.BR io_uring_submit (3),
-.BR io_uring_wait_cqes (3),
-.BR io_uring_wait_cqe (3)
diff --git a/man/io_uring_wait_cqe_timeout.3.md b/man/io_uring_wait_cqe_timeout.3.md
new file mode 100644
index 00000000..3ba9f4a0
--- /dev/null
+++ b/man/io_uring_wait_cqe_timeout.3.md
@@ -0,0 +1,56 @@
+.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: November 15, 2021
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_wait_cqe_timeout
+---
+
+# NAME
+
+io_uring_wait_cqe_timeout - wait for one io_uring completion event with
+timeout
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_wait_cqe_timeout(struct io_uring * ring ,
+ struct io_uring_cqe ** cqe_ptr ,
+ struct __kernel_timespec * ts );
+```
+
+# DESCRIPTION
+
+The **io_uring_wait_cqe_timeout**(3) function waits for one IO
+completion to be available from the queue belonging to the *ring* param,
+waiting for it if necessary or until the timeout *ts* expires. If an
+event is already available in the ring when invoked, no waiting will
+occur.
+
+The *cqe_ptr* param is filled in on success.
+
+If *ts* is specified and an older kernel without **IORING_FEAT_EXT_ARG**
+is used, the application does not need to call **io_uring_submit**(3)
+before calling **io_uring_wait_cqes**(3). For newer kernels with that
+feature flag set, there is no implied submit when waiting for a request.
+
+If *ts* is **NULL ,** then this behaves like **io_uring_wait_cqe**(3) in
+that it will wait forever for an event.
+
+# RETURN VALUE
+
+On success **io_uring_wait_cqe_timeout**(3) returns 0 and the cqe_ptr
+param is filled in. On failure it returns **-errno**. The return value
+indicates the result of waiting for a CQE, and it has no relation to the
+CQE result itself. If a timeout occurs, it will return **-ETIME**.
+
+# SEE ALSO
+
+**io_uring_submit**(3), **io_uring_wait_cqes**(3),
+**io_uring_wait_cqe**(3)
diff --git a/man/io_uring_wait_cqes.3 b/man/io_uring_wait_cqes.3
deleted file mode 100644
index 37ea1f08..00000000
--- a/man/io_uring_wait_cqes.3
+++ /dev/null
@@ -1,82 +0,0 @@
-.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_wait_cqes 3 "November 15, 2021" "liburing-2.1" "liburing Manual"
-.SH NAME
-io_uring_wait_cqes \- wait for one or more io_uring completion events
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_wait_cqes(struct io_uring *" ring ","
-.BI " struct io_uring_cqe **" cqe_ptr ","
-.BI " unsigned " wait_nr ","
-.BI " struct __kernel_timespec *" ts ","
-.BI " sigset_t *" sigmask ");
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_wait_cqes (3)
-function returns
-.I wait_nr
-IO completions from the queue belonging to the
-.I ring
-param, waiting for them if necessary or until the timeout
-.I ts
-expires.
-.PP
-The
-.I sigmask
-specifies the set of signals to block. If set, it is equivalent to atomically
-executing the following calls:
-.PP
-.in +4n
-.EX
-sigset_t origmask;
-
-pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);
-ret = io_uring_wait_cqes(ring, cqe, wait_nr, ts, NULL);
-pthread_sigmask(SIG_SETMASK, &origmask, NULL);
-.EE
-.in
-.PP
-The
-.I cqe_ptr
-param is filled in on success with the first CQE. Callers of this function
-should use
-.BR io_uring_for_each_cqe (3)
-to iterate all available CQEs.
-
-If
-.I ts
-is specified and an older kernel without
-.B IORING_FEAT_EXT_ARG
-is used, the application does not need to call
-.BR io_uring_submit (3)
-before calling
-.BR io_uring_wait_cqes (3).
-For newer kernels with that feature flag set, there is no implied submit
-when waiting for a request.
-
-If
-.I ts
-is
-.B NULL ,
-then this behaves like
-.BR io_uring_wait_cqe (3)
-in that it will wait forever for an event.
-
-.SH RETURN VALUE
-On success
-.BR io_uring_wait_cqes (3)
-returns 0 and the cqe_ptr param is filled in. On failure it returns
-.BR -errno .
-If a timeout occurs, it will return
-.BR -ETIME .
-.SH SEE ALSO
-.BR io_uring_submit (3),
-.BR io_uring_for_each_cqe (3),
-.BR io_uring_wait_cqe_timeout (3),
-.BR io_uring_wait_cqe (3)
diff --git a/man/io_uring_wait_cqes.3.md b/man/io_uring_wait_cqes.3.md
new file mode 100644
index 00000000..bbb1ac9e
--- /dev/null
+++ b/man/io_uring_wait_cqes.3.md
@@ -0,0 +1,67 @@
+.\" Copyright (C) 2021 Stefan Roesch <shr@fb.com>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: November 15, 2021
+footer: liburing-2.1
+header: liburing Manual
+section: 3
+title: io_uring_wait_cqes
+---
+
+# NAME
+
+io_uring_wait_cqes - wait for one or more io_uring completion events
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_wait_cqes(struct io_uring * ring ,
+ struct io_uring_cqe ** cqe_ptr ,
+ unsigned wait_nr ,
+ struct __kernel_timespec * ts ,
+ sigset_t * sigmask );
+```
+
+# DESCRIPTION
+
+The **io_uring_wait_cqes**(3) function returns *wait_nr* IO completions
+from the queue belonging to the *ring* param, waiting for them if
+necessary or until the timeout *ts* expires.
+
+The *sigmask* specifies the set of signals to block. If set, it is
+equivalent to atomically executing the following calls:
+
+``` text
+sigset_t origmask;
+
+pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);
+ret = io_uring_wait_cqes(ring, cqe, wait_nr, ts, NULL);
+pthread_sigmask(SIG_SETMASK, &origmask, NULL);
+```
+
+The *cqe_ptr* param is filled in on success with the first CQE. Callers
+of this function should use **io_uring_for_each_cqe**(3) to iterate all
+available CQEs.
+
+If *ts* is specified and an older kernel without **IORING_FEAT_EXT_ARG**
+is used, the application does not need to call **io_uring_submit**(3)
+before calling **io_uring_wait_cqes**(3). For newer kernels with that
+feature flag set, there is no implied submit when waiting for a request.
+
+If *ts* is **NULL ,** then this behaves like **io_uring_wait_cqe**(3) in
+that it will wait forever for an event.
+
+# RETURN VALUE
+
+On success **io_uring_wait_cqes**(3) returns 0 and the cqe_ptr param is
+filled in. On failure it returns **-errno**. If a timeout occurs, it
+will return **-ETIME**.
+
+# SEE ALSO
+
+**io_uring_submit**(3), **io_uring_for_each_cqe**(3),
+**io_uring_wait_cqe_timeout**(3), **io_uring_wait_cqe**(3)
diff --git a/man/io_uring_wait_cqes_min_timeout.3 b/man/io_uring_wait_cqes_min_timeout.3
deleted file mode 100644
index e3d9849d..00000000
--- a/man/io_uring_wait_cqes_min_timeout.3
+++ /dev/null
@@ -1,76 +0,0 @@
-.\" Copyright (C) 2024 Jens Axboe <axboe@kernel.dk>
-.\"
-.\" SPDX-License-Identifier: LGPL-2.0-or-later
-.\"
-.TH io_uring_wait_cqes_min_timeout 3 "Feb 13, 2024" "liburing-2.8" "liburing Manual"
-.SH NAME
-io_uring_wait_cqes_min_timeout \- wait for completions with both batch and normal timeout
-.SH SYNOPSIS
-.nf
-.B #include <liburing.h>
-.PP
-.BI "int io_uring_wait_cqes_min_timeout(struct io_uring *" ring ","
-.BI " struct io_uring_cqe **" cqe_ptr ","
-.BI " unsigned " wait_nr ","
-.BI " struct __kernel_timespec *" ts ","
-.BI " unsigned int " min_wait_usec ",
-.BI " sigset_t *" sigmask ");"
-.fi
-.SH DESCRIPTION
-.PP
-The
-.BR io_uring_wait_cqes_min_timeout (3)
-waits for completions from the submission queue belonging to the
-.I ring
-and waits for
-.I wait_nr
-completion events, or until the timeout
-.I ts
-expires. The completion events are stored in the
-.I cqe_ptr
-array. If non-zero,
-.I min_wait_usec
-denotes a timeout for the
-.I wait_nr
-batch.
-
-The
-.I sigmask
-specifies the set of signals to block. If set, it is equivalent to atomically
-executing the following calls:
-.PP
-.in +4n
-.EX
-sigset_t origmask;
-
-pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);
-ret = io_uring_wait_cqes_min_timeout(ring, cqe, wait_nr, ts, min_wait, NULL);
-pthread_sigmask(SIG_SETMASK, &origmask, NULL);
-.EE
-.in
-.PP
-This works like
-.BR io_uring_submit_and_wait_min_timeout (3)
-except that it doesn't submit requests. See that man page for a description
-for how the min timeout waiting works.
-
-Available since 6.12.
-
-.SH RETURN VALUE
-On success
-.BR io_uring_wait_cqes_min_timeout (3)
-returns the 0.On failure it returns
-.BR -errno .
-If the kernel doesn't support this functionality,
-.BR -EINVAL
-will be returned. See note on the feature flag.
-The most common failure case is not receiving a completion within the specified
-timeout,
-.B -ETIME
-is returned in this case.
-.SH SEE ALSO
-.BR io_uring_wait_cqe (3),
-.BR io_uring_wait_cqes (3),
-.BR io_uring_wait_cqe_timeout (3),
-.BR io_uring_wait_cqes (3),
-.BR io_uring_submit_and_wait_min_timeout (3)
diff --git a/man/io_uring_wait_cqes_min_timeout.3.md b/man/io_uring_wait_cqes_min_timeout.3.md
new file mode 100644
index 00000000..49fc0e9a
--- /dev/null
+++ b/man/io_uring_wait_cqes_min_timeout.3.md
@@ -0,0 +1,68 @@
+.\" Copyright (C) 2024 Jens Axboe <axboe@kernel.dk>
+.\"
+.\" SPDX-License-Identifier: LGPL-2.0-or-later
+.\"
+---
+date: Feb 13, 2024
+footer: liburing-2.8
+header: liburing Manual
+section: 3
+title: io_uring_wait_cqes_min_timeout
+---
+
+# NAME
+
+io_uring_wait_cqes_min_timeout - wait for completions with both batch
+and normal timeout
+
+# SYNOPSIS
+
+``` text
+#include <liburing.h>
+
+ int io_uring_wait_cqes_min_timeout(struct io_uring * ring ,
+ struct io_uring_cqe ** cqe_ptr ,
+ unsigned wait_nr ,
+ struct __kernel_timespec * ts ,
+ unsigned int min_wait_usec ,
+ sigset_t * sigmask );
+```
+
+# DESCRIPTION
+
+The **io_uring_wait_cqes_min_timeout**(3) waits for completions from the
+submission queue belonging to the *ring* and waits for *wait_nr*
+completion events, or until the timeout *ts* expires. The completion
+events are stored in the *cqe_ptr* array. If non-zero, *min_wait_usec*
+denotes a timeout for the *wait_nr* batch.
+
+The *sigmask* specifies the set of signals to block. If set, it is
+equivalent to atomically executing the following calls:
+
+``` text
+sigset_t origmask;
+
+pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);
+ret = io_uring_wait_cqes_min_timeout(ring, cqe, wait_nr, ts, min_wait, NULL);
+pthread_sigmask(SIG_SETMASK, &origmask, NULL);
+```
+
+This works like **io_uring_submit_and_wait_min_timeout**(3) except that
+it doesn\'t submit requests. See that man page for a description for how
+the min timeout waiting works.
+
+Available since 6.12.
+
+# RETURN VALUE
+
+On success **io_uring_wait_cqes_min_timeout**(3) returns the 0.On
+failure it returns **-errno**. If the kernel doesn\'t support this
+functionality, **-EINVAL** will be returned. See note on the feature
+flag. The most common failure case is not receiving a completion within
+the specified timeout, **-ETIME** is returned in this case.
+
+# SEE ALSO
+
+**io_uring_wait_cqe**(3), **io_uring_wait_cqes**(3),
+**io_uring_wait_cqe_timeout**(3), **io_uring_wait_cqes**(3),
+**io_uring_submit_and_wait_min_timeout**(3)
--
2.54.0
^ permalink raw reply related [flat|nested] 9+ messages in thread