460 lines
14 KiB
Groff
460 lines
14 KiB
Groff
.\" $NetBSD: puffs_framebuf.3,v 1.7 2007/05/20 16:24:37 pooka Exp $
|
|
.\"
|
|
.\" Copyright (c) 2007 Antti Kantee. All rights reserved.
|
|
.\"
|
|
.\" Redistribution and use in source and binary forms, with or without
|
|
.\" modification, are permitted provided that the following conditions
|
|
.\" are met:
|
|
.\" 1. Redistributions of source code must retain the above copyright
|
|
.\" notice, this list of conditions and the following disclaimer.
|
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
|
.\" notice, this list of conditions and the following disclaimer in the
|
|
.\" documentation and/or other materials provided with the distribution.
|
|
.\"
|
|
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
.\" SUCH DAMAGE.
|
|
.\"
|
|
.Dd May 16, 2007
|
|
.Dt PUFFS_FRAMEBUF 3
|
|
.Os
|
|
.Sh NAME
|
|
.Nm puffs_framebuf
|
|
.Nd buffering and event handling for networked file systems
|
|
.Sh LIBRARY
|
|
.Lb libpuffs
|
|
.Sh SYNOPSIS
|
|
.In puffs.h
|
|
.Ft struct puffs_framebuf *
|
|
.Fn puffs_framebuf_make
|
|
.Ft void
|
|
.Fn puffs_framebuf_destroy "struct puffs_framebuf *pufbuf"
|
|
.Ft void
|
|
.Fn puffs_framebuf_recycle "struct puffs_framebuf *pufbuf"
|
|
.Ft int
|
|
.Fn puffs_framebuf_reserve_space "struct puffs_framebuf *pufbuf" "size_t space"
|
|
.Ft int
|
|
.Fo puffs_framebuf_putdata
|
|
.Fa "struct puffs_framebuf *pufbuf" "const void *data" "size_t dlen"
|
|
.Fc
|
|
.Ft int
|
|
.Fo puffs_framebuf_putdata_atoff
|
|
.Fa "struct puffs_framebuf *pufbuf" "size_t offset" "const void *data"
|
|
.Fa "size_t dlen"
|
|
.Fc
|
|
.Ft int
|
|
.Fo puffs_framebuf_getdata
|
|
.Fa "struct puffs_framebuf *pufbuf" "void *data" "size_t dlen"
|
|
.Fc
|
|
.Ft int
|
|
.Fo puffs_framebuf_getdata_atoff
|
|
.Fa "struct puffs_framebuf *pufbuf" "size_t offset"
|
|
.Fa "void *data" "size_t dlen"
|
|
.Fc
|
|
.Ft size_t
|
|
.Fn puffs_framebuf_telloff "struct puffs_framebuf *pufbuf"
|
|
.Ft size_t
|
|
.Fn puffs_framebuf_tellsize "struct puffs_framebuf *pufbuf"
|
|
.Ft size_t
|
|
.Fn puffs_framebuf_remaining "struct puffs_framebuf *pufbuf"
|
|
.Ft int
|
|
.Fn puffs_framebuf_seekset "struct puffs_framebuf *pufbuf" "size_t offset"
|
|
.Ft int
|
|
.Fo puffs_framebuf_getwindow
|
|
.Fa "struct puffs_framebuf *pufbuf" "size_t offset"
|
|
.Fa "void **winp" "size_t *winlen"
|
|
.Fc
|
|
.Ft int
|
|
.Fo puffs_framev_enqueue_cc
|
|
.Fa "struct puffs_cc *pcc" "struct puffs_framebuf *pufbuf"
|
|
.Fc
|
|
.Ft void
|
|
.Fo puffs_framev_cb
|
|
.Fa "struct puffs_usermount *pu" "struct puffs_framebuf *pufbuf" "void *arg"
|
|
.Fa "int error"
|
|
.Fc
|
|
.Ft void
|
|
.Fo puffs_framev_enqueue_cb
|
|
.Fa "struct puffs_usermount *pu" "struct puffs_framebuf *pufbuf"
|
|
.Fa "puffs_framebuf_cb fcb" "void *fcb_arg"
|
|
.Fc
|
|
.Ft void
|
|
.Fo puffs_framev_enqueue_justsend
|
|
.Fa "struct puffs_usermount *pu" "struct puffs_framebuf *pufbuf" "int waitreply"
|
|
.Fc
|
|
.Ft int
|
|
.Fo puffs_framev_readframe_fn
|
|
.Fa "struct puffs_usermount *pu" "struct puffs_framebuf *pufbuf"
|
|
.Fa "int fd" "int *done"
|
|
.Fc
|
|
.Ft int
|
|
.Fo puffs_framev_writeframe_fn
|
|
.Fa "struct puffs_usermount *pu" "struct puffs_framebuf *pufbuf"
|
|
.Fa "int fd" "int *done"
|
|
.Fc
|
|
.Ft int
|
|
.Fo puffs_framev_cmpframe_fn
|
|
.Fa "struct puffs_usermount *pu"
|
|
.Fa "struct puffs_framebuf *cmp1" "struct puffs_framebuf *cmp2"
|
|
.Fc
|
|
.Ft int
|
|
.Fo puffs_framev_fdnotify_fn
|
|
.Fa "struct puffs_usermount *pu" "int fd" "int what"
|
|
.Fc
|
|
.Ft int
|
|
.Fo puffs_framev_init
|
|
.Fa "struct puffs_usermount *pu"
|
|
.Fa "puffs_framebuf_readframe_fn rfb" "puffs_framebuf_writeframe_fn wfb"
|
|
.Fa "puffs_framebuf_cmpframe_fn cmpfb"
|
|
.Fa "puffs_framebuf_fdnotify_fn fdnotfn"
|
|
.Fc
|
|
.Ft int
|
|
.Fn puffs_framev_addfd "struct puffs_usermount *pu" "int fd"
|
|
.Ft int
|
|
.Fn puffs_framev_removefd "struct puffs_usermount *pu" "int fd" "int error"
|
|
.Ft void
|
|
.Fo puffs_framev_unmountonclose
|
|
.Fa "struct puffs_usermount *pu" "int fd" "int what"
|
|
.Fc
|
|
.Sh DESCRIPTION
|
|
.Em IMPORTANT NOTE!
|
|
This document describes interfaces which are not yet guaranteed to be
|
|
stable.
|
|
In case you update your system sources, please recompile everything
|
|
and fix complation errors.
|
|
If your sources are out-of-sync, incorrect operation may result.
|
|
.Pp
|
|
The
|
|
.Nm
|
|
routines provide buffering and an event loop structured around the
|
|
buffers.
|
|
It operates on top of the puffs continuation framework,
|
|
.Xr puffs_cc 3 ,
|
|
and multiplexes execution automatically to an instance whenever
|
|
one is runnable.
|
|
Currently only request-response type "client pull" protocols are
|
|
supported, but support for protocols which also feature "server
|
|
push" type messaging may be added at a later date.
|
|
.Pp
|
|
The file system is entered in two different ways:
|
|
.Bl -bullet -offset indent
|
|
.It
|
|
An event arrives from the kernel and the
|
|
.Xr puffs_ops 3
|
|
callbacks are called to start processing the event.
|
|
.It
|
|
A file system which has sent out a request receives a response.
|
|
Execution is resumed from the place where the file system yielded.
|
|
.El
|
|
.Pp
|
|
For a file server to use
|
|
.Nm ,
|
|
it must implemented three different routines:
|
|
.Bl -tag -width "xcmpfbx"
|
|
.It rfb
|
|
Read a frame onto the specified buffer.
|
|
.It wfb
|
|
Write a frame from the specified buffer.
|
|
.It cmpfb
|
|
Identify if a buffer is the response to the specified buffer.
|
|
.El
|
|
.Pp
|
|
Additionally, a fourth optional one called
|
|
.Fn fdnotfn
|
|
may be specified.
|
|
It is used as a notify callback from the event loop to the file server
|
|
when the event loop detects that the write or read side of the file
|
|
descriptor has been closed.
|
|
See
|
|
.Fn puffs_framev_fdnotify_fn
|
|
for more information.
|
|
.Pp
|
|
File descriptors are treated like sockets: they have two sides, a read
|
|
side and a write side.
|
|
The framework determines that one side of the descriptor has been
|
|
close if the supplied I/O callbacks return an error or if the I/O
|
|
multiplexing call says a side has been closed.
|
|
It is still possible, from the framework perspective, to write to a
|
|
file descriptor whose read side is closed.
|
|
However, it is not possible to wait for a response on such a file
|
|
descriptor.
|
|
Conversely, it is possible to read responses from a descriptor whose
|
|
write side is closed.
|
|
It should be stressed that the implementation underlying the file
|
|
descriptor might not support this.
|
|
.Pp
|
|
The buffers of
|
|
.Nm
|
|
provide automatic memory management of buffers for the file servers.
|
|
They provide a cursor to the current buffer offset.
|
|
Reading or writing data through the normal routines will advance that cursor.
|
|
Additionally, the buffer size is provided to the user.
|
|
It represents the maximum offset where data was written.
|
|
.Pp
|
|
Generally the write functions will fail if the cannot allocate enough
|
|
memory to satisfy the buffer length requirements.
|
|
Read functions will fail if the amount of data written to the buffer
|
|
is not large enough to satisfy the read.
|
|
.Bl -tag -width xxxx
|
|
.It Fn puffs_framebuf_make
|
|
Create a buffer.
|
|
Return the address of the buffer or
|
|
.Dv NULL
|
|
in case no memory was available.
|
|
.It Fn puffs_framebuf_destroy pufbuf
|
|
Free memory used by buffer.
|
|
.It Fn puffs_framebuf_recycle pufbuf
|
|
Reset offsets so that buffer can be reused.
|
|
Does not free memory or reallocate memory.
|
|
.It Fn puffs_framebuf_reserver_space pufbuf space
|
|
Make sure that the buffer has
|
|
.Ar space
|
|
bytes of available memory starting from the current offset.
|
|
This is not strictly necessary, but can be used for optimizations
|
|
where it is known in advance how much memory will be required.
|
|
.It Fn puffs_framebuf_putdata pufbuf data dlen
|
|
Write
|
|
.Ar dlen
|
|
amount of data from the address
|
|
.Ar data
|
|
into the buffer.
|
|
Moves the offset cursor forward
|
|
.Ar dlen
|
|
bytes.
|
|
.It Fn puffs_framebuf_putdata_atoff pufbuf offset data dlen
|
|
Like
|
|
.Fn puffs_framebuf_putdata ,
|
|
except writes data at buffer offset
|
|
.Ar offset .
|
|
It is legal to write past the current end of the buffer.
|
|
Does NOT modify the current offset cursor.
|
|
.It Fn puffs_framebuf_getdata pufbuf data dlen
|
|
Read
|
|
.Ar dlen
|
|
bytes of data from the buffer into
|
|
.Ar data .
|
|
Advances the offset cursor.
|
|
.It Fn puffs_framebuf_getdata_atoff pufbuf offset data dlen
|
|
Read data from buffer position
|
|
.Ar offset .
|
|
Does NOT modify the offset cursor.
|
|
.It Fn puffs_framebuf_telloff pufbuf
|
|
Return the offset into the buffer.
|
|
.It Fn puffs_framebuf_tellsize pufbuf
|
|
Return the maximum offset where data has been written, i.e. buffer size.
|
|
.It Fn puffs_framebuf_remaining pufbuf
|
|
Distance from current offset to the end of the buffer, i.e. size-offset.
|
|
.It Fn puffs_framebuf_seekset pufbuf offset
|
|
Set the offset cursor to the position
|
|
.Ar offset .
|
|
This does NOT modify the buffer size, but reserves at least
|
|
enough memory memory for a write to
|
|
.Ar offset
|
|
and will fail if memory cannot be allocated.
|
|
.It Fn puffs_framebuf_getwindow pufbuf offset winp winlen
|
|
Get a direct memory window into the buffer starting from
|
|
.Ar offset .
|
|
The maximum mapped window size will be
|
|
.Ar winlen
|
|
bytes, but this routine might return a smaller window and the caller
|
|
should always check the actual mapped size after the call.
|
|
The window is returned in
|
|
.Ar winp .
|
|
This function not modify the buffer offset, but it DOES set the buffer
|
|
size to
|
|
.Ar offset +
|
|
.Ar winlen
|
|
in case that value is greater than the current size.
|
|
The window is valid until the next until the next
|
|
.Fn puffs_framebuf
|
|
call operating on the buffer in question.
|
|
.It Fn puffs_framev_enqueue_cc pcc pufbuf
|
|
Add the buffer
|
|
.Ar pufbuf
|
|
to outgoing queue and yield with the continuation
|
|
.Ar pcc .
|
|
Execution is resumed once a response is received.
|
|
Returns 0 if the buffer was succesfully enqueued (not necessarily
|
|
delivered) and non-zero to signal a non-recoverable error.
|
|
.It Fn puffs_framev_cb pu pufbuf arg error
|
|
Callback function.
|
|
Called when a response to a specific request arrives from the server.
|
|
If
|
|
.Ar error
|
|
is non-zero, the framework was unable to obtain a response and the
|
|
function should not examine the contents of
|
|
.Ar pufbuf ,
|
|
only do resource cleanup.
|
|
May not block.
|
|
.It Fn puffs_framev_enqueue_cb pu pufbuf fcb fcb_arg
|
|
Enqueue the buffer
|
|
.Ar pufbuf
|
|
for outgoing data and immediately return.
|
|
Once a response arrives, the callback
|
|
.Fn fcb
|
|
will be called with the argument
|
|
.Ar fcb_arg .
|
|
The callback function
|
|
.Fn fcb
|
|
is responsible for freeing the buffer.
|
|
Returns 0 if the buffer was succesfully enqueued (not necessarily
|
|
delivered) and non-zero to signal a non-recoverable error.
|
|
.It Fn puffs_framev_enqueue_justsend pu pufbuf waitreply
|
|
Enqueue the buffer
|
|
.Ar pufbuf
|
|
for outgoing traffic and immediately return.
|
|
The parameter
|
|
.Ar waitreply
|
|
can be used to control if the buffer is to be freed immediately after
|
|
sending of if a response is expected and the buffer should be freed
|
|
only after the response arrives (receiving an unexpected message from
|
|
the server is treated as an error).
|
|
Returns 0 if the buffer was succesfully enqueued (not necessarily
|
|
delivered) and non-zero to signal a non-recoverable error.
|
|
.It Fn puffs_framev_readframe_fn pu pufbuf fd done
|
|
Callback function.
|
|
Read at most one frame from file descriptor
|
|
.Ar fd
|
|
into the buffer
|
|
.Ar pufbuf.
|
|
If a complete frame is read, the value pointed to by
|
|
.Ar done
|
|
must be set to 1.
|
|
This function should return 0 on success (even if a complete frame was not
|
|
yet read) and a non-zero
|
|
.Er errno
|
|
to signal a fatal error.
|
|
In case a fatal error is returned, the read side of the file descriptor
|
|
is marked closed.
|
|
This routine will be called with the same buffer argument until a
|
|
complete frame has been read.
|
|
May not block.
|
|
.It Fn puffs_framev_writeframe_fn pu pufbuf fd done
|
|
Write the frame contained in
|
|
.Ar pufbuf
|
|
to the file descriptor
|
|
.Ar fd .
|
|
In case the entire frame is succesfully written,
|
|
.Ar *done
|
|
should be set to 1.
|
|
This function should return 0 on success (even if a complete frame was not
|
|
yet written) and a non-zero
|
|
.Er errno
|
|
to signal a fatal error.
|
|
In case a fatal error is returned, the write side of the file descriptor
|
|
is marked closed.
|
|
This routine will be called with the same buffer argument until the
|
|
complete frame has been written.
|
|
May not block.
|
|
.Pp
|
|
It is a good idea to make sure that this function can handle a possible
|
|
.Dv SIGPIPE
|
|
caused by a closed connection.
|
|
For example, the file server can opt to trap
|
|
.Dv SIGPIPE
|
|
or, if writing to a socket, call
|
|
.Fn send
|
|
with the flag
|
|
.Dv MSG_NOSIGNAL
|
|
instead of using
|
|
.Fn write .
|
|
.It Fn puffs_framev_cmpframe_fn pu pufbuf_cmp1 pufbuf_cmp2
|
|
Compare the file system internal request tags in
|
|
.Ar pufbuf_cmp1
|
|
and
|
|
.Ar pufbuf_cmp2 .
|
|
Should return 0 if the tags are equal, 1 if first buffer's tag is
|
|
greater than the second and \-1 if it is smaller.
|
|
The definitions "greater" and "smaller" are used transparently by
|
|
the library, e.g. like
|
|
.Xr qsort 3 .
|
|
May not block.
|
|
.It Fn puffs_framev_fdnotify_fn pu fd what
|
|
Is called when the read- or write side of the file descriptor
|
|
.Ar fd
|
|
is closed.
|
|
It is called once for each side, the bitmask parameter
|
|
.Ar what
|
|
specified what is currently closed:
|
|
.Dv PUFFS_FBGONE_READ
|
|
and
|
|
.Dv PUFFS_FBGONE_WRITE
|
|
for read and write, respectively.
|
|
It is possible to test for both using
|
|
.Fn PUFFS_FBGONE_BOTH what .
|
|
.It Fn puffs_framev_init pu rfb wfb cmpfb fdnotfn
|
|
Initializes the given callbacks to the system.
|
|
They will be used when
|
|
.Fn puffs_mainloop
|
|
is called.
|
|
.Ar rfb ,
|
|
.Ar wfb
|
|
and
|
|
.Ar cmpfb
|
|
are mandatory.
|
|
If
|
|
.Ar fdnotfn
|
|
is not given, a routine which calls
|
|
.Fn puffs_framev_removefd
|
|
when both sides are closed is used.
|
|
.It Fn puffs_framev_addfd pu fd
|
|
Add file descriptor
|
|
.Ar fd
|
|
to be handled by the framework.
|
|
It is legal to add a file descriptor either before calling
|
|
.Fn puffs_mainloop
|
|
or at time when running.
|
|
.It Fn puffs_framev_removefd pu fd error
|
|
Remove file descriptor
|
|
.Ar fd
|
|
from the list of descriptors handled by the framework.
|
|
Removing a file descriptor causes all operations blocked either on
|
|
output or input to be released with the error value
|
|
.Ar error .
|
|
In case 0 is supplied as this parameter,
|
|
.Er ECONNRESET
|
|
is used.
|
|
.Pp
|
|
The file system
|
|
.B must
|
|
explicitly remove each fd it has added.
|
|
A good place to do this is
|
|
.Fn puffs_framev_fdnotify_fn .
|
|
.It Fn puffs_framev_unmountonclose pu fd what
|
|
This is library provided convinience routine for
|
|
.Fn puffs_framev_fdnotify_fn .
|
|
It unmounts the file system when both the read and write side are
|
|
closed.
|
|
It is useful for file systems, such as
|
|
.Xr mount_psshfs 8 ,
|
|
which depend on a single connection.
|
|
.El
|
|
.Sh CODE REFERENCES
|
|
The current users of
|
|
.Nm
|
|
in the tree are
|
|
.Xr mount_psshfs 8
|
|
and
|
|
.Xr mount_9p 8 .
|
|
See
|
|
.Pa src/usr.sbin/puffs/mount_psshfs
|
|
and
|
|
.Pa src/usr.sbin/puffs/mount_9p
|
|
for the respective usage examples.
|
|
.Sh RETURN VALUES
|
|
These functions generally return \-1 to signal error and set
|
|
.Er errno
|
|
to indicate the type of error.
|
|
.Sh SEE ALSO
|
|
.Xr puffs 3 ,
|
|
.Xr puffs_cc 3 ,
|
|
.Xr puffs_ops 3
|