io_uring_prep_splice(3)

πŸ“¦
version 2.14 Β· 3 versions
, in alpine 3.22, alpine 3.23, alpine 3.24, centos-stream 10, centos-stream 9, debian trixie, fedora 43, fedora 44, nixpkgs unstable, opensuse-leap 16.0, ubuntu noble, ubuntu questing, ubuntu resolute

✨ io_uring_prep_splice β€” the liburing girlies' guide πŸ’…

okay so bestie, you're in the liburing manual, section 3, and today's main character is io_uring_prep_splice(3). yes that's a mouthful. yes it's iconic. let's go πŸ¦‹


🌸 NAME 🌸

io_uring_prep_splice β€” get an splice request all set up and ready to slay


✨ SYNOPSIS ✨

#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);

like. look at all those parameters. she's got range πŸ’œ


πŸ’– DESCRIPTION πŸ’–

So io_uring_prep_splice(3) prepares a splice request. Basically it takes your submission queue entry, your sqe, and sets it up so that the input is the file descriptor fd_in at offset off_in, and it splices that data over to the file descriptor fd_out at offset off_out. πŸ’«

Then nbytes bytes of data should get spliced between those two descriptors. And splice_flags are the modifier flags for the operation β€” peep splice(2) for the generic splice flags, she's got the lore.

Now, if fd_out is a descriptor you've already registered, you can set IOSQE_FIXED_FILE in the SQE to say so. And for the input file, there's this io_uring-specific one: SPLICE_F_FD_IN_FIXED can be set in splice_flags, and then you pass fd_in as a registered file descriptor offset. cute, right? πŸŽ€

Here's the rules for the offsets, and ngl these matter:

  • 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, and that file offset gets incremented by however many bytes were 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.

And the same exact rules apply to fd_out and off_out. no cap. πŸ‘‘

So yeah β€” this function prepares an async splice(2) request. Go read that man page for the details, she knows things.


πŸ’€ RETURN VALUE πŸ’€

None. literally nothing. she returns void, bestie, it's giving mysterious. πŸ™ˆ


😭 ERRORS 😭

The CQE res field will contain the result of the operation. Check the related man page for what values are possible.

And here's the thing that trips people up: synchronous system calls return -1 on failure and set errno to the actual error value, but io_uring never uses errno. Instead it returns the negated errno directly in the CQE res field. periodt. πŸ’…


🌈 SEE ALSO 🌈


🧚 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.

so like. don't come for her when that happens. it's a kernel thing. πŸ’€


okay that's the whole page, you ate that 🫢 this was liburing-2.2, dated March 13, 2022 β€” mwah, go splice something gorgeous, ily, bye bestie β­πŸ’–βœ¨

πŸ“¦ where this page comes from