splice and pipes

splice API

splice is a method for moving blocks of data around inside the kernel,without continually transferring them between the kernel and user space.

ssize_tsplice_to_pipe(structpipe_inode_info * pipe, struct splice_pipe_desc * spd)

fill passed data into a pipe

Parameters

structpipe_inode_info*pipe
pipe to fill
structsplice_pipe_desc*spd
data to fill

Description

spd contains a map of pages and len/offset tuples, along withthe struct pipe_buf_operations associated with these pages. Thisfunction will link that data to the pipe.
ssize_tgeneric_file_splice_read(struct file * in, loff_t * ppos, structpipe_inode_info * pipe, size_t len, unsigned int flags)

splice data from file to a pipe

Parameters

structfile*in
file to splice from
loff_t*ppos
position inin
structpipe_inode_info*pipe
pipe to splice to
size_tlen
number of bytes to splice
unsignedintflags
splice modifier flags

Description

Will read pages from given file and fill them into a pipe. Can beused as long as it has more or less sane ->read_iter().
intsplice_from_pipe_feed(structpipe_inode_info * pipe, struct splice_desc * sd, splice_actor * actor)

feed available data from a pipe to a file

Parameters

structpipe_inode_info*pipe
pipe to splice from
structsplice_desc*sd
information toactor
splice_actor*actor
handler that splices the data

Description

This function loops over the pipe and callsactor to do theactual moving of a single struct pipe_buffer to the desireddestination. It returns when there’s no more buffers left inthe pipe or if the requested number of bytes (sd->total_len)have been copied. It returns a positive number (one) if thepipe needs to be filled with more data, zero if the requirednumber of bytes have been copied and -errno on error.

This, together with splice_from_pipe_{begin,end,next}, may beused to implement the functionality of__splice_from_pipe() whenlocking is required around copying the pipe buffers to thedestination.

intsplice_from_pipe_next(structpipe_inode_info * pipe, struct splice_desc * sd)

wait for some data to splice from

Parameters

structpipe_inode_info*pipe
pipe to splice from
structsplice_desc*sd
information about the splice operation

Description

This function will wait for some data and return a positivevalue (one) if pipe buffers are available. It will return zeroor -errno if no more data needs to be spliced.
voidsplice_from_pipe_begin(struct splice_desc * sd)

start splicing from pipe

Parameters

structsplice_desc*sd
information about the splice operation

Description

This function should be called before a loop containingsplice_from_pipe_next() andsplice_from_pipe_feed() toinitialize the necessary fields ofsd.
voidsplice_from_pipe_end(structpipe_inode_info * pipe, struct splice_desc * sd)

finish splicing from pipe

Parameters

structpipe_inode_info*pipe
pipe to splice from
structsplice_desc*sd
information about the splice operation

Description

This function will wake up pipe writers if necessary. It shouldbe called after a loop containingsplice_from_pipe_next() andsplice_from_pipe_feed().
ssize_t__splice_from_pipe(structpipe_inode_info * pipe, struct splice_desc * sd, splice_actor * actor)

splice data from a pipe to given actor

Parameters

structpipe_inode_info*pipe
pipe to splice from
structsplice_desc*sd
information toactor
splice_actor*actor
handler that splices the data

Description

This function does little more than loop over the pipe and callactor to do the actual moving of a single struct pipe_buffer tothe desired destination. See pipe_to_file, pipe_to_sendpage, orpipe_to_user.
ssize_tsplice_from_pipe(structpipe_inode_info * pipe, struct file * out, loff_t * ppos, size_t len, unsigned int flags, splice_actor * actor)

splice data from a pipe to a file

Parameters

structpipe_inode_info*pipe
pipe to splice from
structfile*out
file to splice to
loff_t*ppos
position inout
size_tlen
how many bytes to splice
unsignedintflags
splice modifier flags
splice_actor*actor
handler that splices the data

Description

See __splice_from_pipe. This function locks the pipe inode,otherwise it’s identical to__splice_from_pipe().
ssize_titer_file_splice_write(structpipe_inode_info * pipe, struct file * out, loff_t * ppos, size_t len, unsigned int flags)

splice data from a pipe to a file

Parameters

structpipe_inode_info*pipe
pipe info
structfile*out
file to write to
loff_t*ppos
position inout
size_tlen
number of bytes to splice
unsignedintflags
splice modifier flags

Description

Will either move or copy pages (determined byflags options) fromthe given pipe inode to the given file.This one is ->write_iter-based.
ssize_tgeneric_splice_sendpage(structpipe_inode_info * pipe, struct file * out, loff_t * ppos, size_t len, unsigned int flags)

splice data from a pipe to a socket

Parameters

structpipe_inode_info*pipe
pipe to splice from
structfile*out
socket to write to
loff_t*ppos
position inout
size_tlen
number of bytes to splice
unsignedintflags
splice modifier flags

Description

Will sendlen bytes from the pipe to a network socket. No data copyingis involved.
ssize_tsplice_direct_to_actor(struct file * in, struct splice_desc * sd, splice_direct_actor * actor)

splices data directly between two non-pipes

Parameters

structfile*in
file to splice from
structsplice_desc*sd
actor information on where to splice to
splice_direct_actor*actor
handles the data splicing

Description

This is a special case helper to splice directly between twopoints, without requiring an explicit pipe. Internally an allocatedpipe is cached in the process, and reused during the lifetime ofthat process.
longdo_splice_direct(struct file * in, loff_t * ppos, struct file * out, loff_t * opos, size_t len, unsigned int flags)

splices data directly between two files

Parameters

structfile*in
file to splice from
loff_t*ppos
input file offset
structfile*out
file to splice to
loff_t*opos
output file offset
size_tlen
number of bytes to splice
unsignedintflags
splice modifier flags

Description

For use by do_sendfile(). splice can easily emulate sendfile, butdoing it in the application would incur an extra system call(splice in + splice out, as compared to just sendfile()). So this helpercan splice directly through a process-private pipe.

pipes API

Pipe interfaces are all for in-kernel (builtin image) use. They are notexported for use by modules.

structpipe_buffer

a linux kernel pipe buffer

Definition

struct pipe_buffer {  struct page *page;  unsigned int offset, len;  const struct pipe_buf_operations *ops;  unsigned int flags;  unsigned long private;};

Members

page
the page containing the data for the pipe buffer
offset
offset of data inside thepage
len
length of data inside thepage
ops
operations associated with this buffer. Seepipe_buf_operations.
flags
pipe buffer flags. See above.
private
private data owned by the ops.
structpipe_inode_info

a linux kernel pipe

Definition

struct pipe_inode_info {  struct mutex mutex;  wait_queue_head_t rd_wait, wr_wait;  unsigned int head;  unsigned int tail;  unsigned int max_usage;  unsigned int ring_size;#ifdef CONFIG_WATCH_QUEUE;  bool note_loss;#endif;  unsigned int nr_accounted;  unsigned int readers;  unsigned int writers;  unsigned int files;  unsigned int r_counter;  unsigned int w_counter;  struct page *tmp_page;  struct fasync_struct *fasync_readers;  struct fasync_struct *fasync_writers;  struct pipe_buffer *bufs;  struct user_struct *user;#ifdef CONFIG_WATCH_QUEUE;  struct watch_queue *watch_queue;#endif;};

Members

mutex
mutex protecting the whole thing
rd_wait
reader wait point in case of empty pipe
wr_wait
writer wait point in case of full pipe
head
The point of buffer production
tail
The point of buffer consumption
max_usage
The maximum number of slots that may be used in the ring
ring_size
total number of buffers (should be a power of 2)
note_loss
The next read() should insert a data-lost message
nr_accounted
The amount this pipe accounts for in user->pipe_bufs
readers
number of current readers of this pipe
writers
number of current writers of this pipe
files
number of struct file referring this pipe (protected by ->i_lock)
r_counter
reader counter
w_counter
writer counter
tmp_page
cached released page
fasync_readers
reader side fasync
fasync_writers
writer side fasync
bufs
the circular array of pipe buffers
user
the user who created this pipe
watch_queue
If this pipe is a watch_queue, this is the stuff for that
boolpipe_empty(unsigned int head, unsigned int tail)

Return true if the pipe is empty

Parameters

unsignedinthead
The pipe ring head pointer
unsignedinttail
The pipe ring tail pointer
unsigned intpipe_occupancy(unsigned int head, unsigned int tail)

Return number of slots used in the pipe

Parameters

unsignedinthead
The pipe ring head pointer
unsignedinttail
The pipe ring tail pointer
boolpipe_full(unsigned int head, unsigned int tail, unsigned int limit)

Return true if the pipe is full

Parameters

unsignedinthead
The pipe ring head pointer
unsignedinttail
The pipe ring tail pointer
unsignedintlimit
The maximum amount of slots available.
unsigned intpipe_space_for_user(unsigned int head, unsigned int tail, structpipe_inode_info * pipe)

Return number of slots available to userspace

Parameters

unsignedinthead
The pipe ring head pointer
unsignedinttail
The pipe ring tail pointer
structpipe_inode_info*pipe
The pipe info structure
boolpipe_buf_get(structpipe_inode_info * pipe, structpipe_buffer * buf)

get a reference to a pipe_buffer

Parameters

structpipe_inode_info*pipe
the pipe that the buffer belongs to
structpipe_buffer*buf
the buffer to get a reference to

Return

true if the reference was successfully obtained.

voidpipe_buf_release(structpipe_inode_info * pipe, structpipe_buffer * buf)

put a reference to a pipe_buffer

Parameters

structpipe_inode_info*pipe
the pipe that the buffer belongs to
structpipe_buffer*buf
the buffer to put a reference to
intpipe_buf_confirm(structpipe_inode_info * pipe, structpipe_buffer * buf)

verify contents of the pipe buffer

Parameters

structpipe_inode_info*pipe
the pipe that the buffer belongs to
structpipe_buffer*buf
the buffer to confirm
boolpipe_buf_try_steal(structpipe_inode_info * pipe, structpipe_buffer * buf)

attempt to take ownership of a pipe_buffer

Parameters

structpipe_inode_info*pipe
the pipe that the buffer belongs to
structpipe_buffer*buf
the buffer to attempt to steal
boolgeneric_pipe_buf_try_steal(structpipe_inode_info * pipe, structpipe_buffer * buf)

attempt to take ownership of apipe_buffer

Parameters

structpipe_inode_info*pipe
the pipe that the buffer belongs to
structpipe_buffer*buf
the buffer to attempt to steal

Description

This function attempts to steal thestructpage attached tobuf. If successful, this function returns 0 and returns withthe page locked. The caller may then reuse the page for whateverhe wishes; the typical use is insertion into a different filepage cache.
boolgeneric_pipe_buf_get(structpipe_inode_info * pipe, structpipe_buffer * buf)

get a reference to astructpipe_buffer

Parameters

structpipe_inode_info*pipe
the pipe that the buffer belongs to
structpipe_buffer*buf
the buffer to get a reference to

Description

This function grabs an extra reference tobuf. It’s used inin the tee() system call, when we duplicate the buffers in onepipe into another.
voidgeneric_pipe_buf_release(structpipe_inode_info * pipe, structpipe_buffer * buf)

put a reference to astructpipe_buffer

Parameters

structpipe_inode_info*pipe
the pipe that the buffer belongs to
structpipe_buffer*buf
the buffer to put a reference to

Description

This function releases a reference tobuf.