struct
puffs_framebuf
*
puffs_framebuf_make(
)
void
puffs_framebuf_destroy(
struct puffs_framebuf *pufbuf
)
void
puffs_framebuf_recycle(
struct puffs_framebuf *pufbuf
)
int
puffs_framebuf_reserve_space(
struct puffs_framebuf *pufbuf
, size_t space
)
int
puffs_framebuf_putdata(
struct puffs_framebuf *pufbuf
const void *data
size_t dlen
)
int
puffs_framebuf_putdata_atoff(
struct puffs_framebuf *pufbuf
size_t offset
const void *data
size_t dlen
)
int
puffs_framebuf_getdata(
struct puffs_framebuf *pufbuf
void *data
size_t dlen
)
int
puffs_framebuf_getdata_atoff(
struct puffs_framebuf *pufbuf
size_t offset
void *data
size_t dlen
)
size_t
puffs_framebuf_telloff(
struct puffs_framebuf *pufbuf
)
size_t
puffs_framebuf_tellsize(
struct puffs_framebuf *pufbuf
)
size_t
puffs_framebuf_remaining(
struct puffs_framebuf *pufbuf
)
int
puffs_framebuf_seekset(
struct puffs_framebuf *pufbuf
, size_t offset
)
int
puffs_framebuf_getwindow(
struct puffs_framebuf *pufbuf
size_t offset
void **winp
size_t *winlen
)
int
puffs_framev_enqueue_cc(
struct puffs_cc *pcc
int fd
struct puffs_framebuf *pufbuf
int flags
)
void
puffs_framev_cb(
struct puffs_usermount *pu
int fd
struct puffs_framebuf *pufbuf
void *arg
int flags
int error
)
void
puffs_framev_enqueue_cb(
struct puffs_usermount *pu
int fd
struct puffs_framebuf *pufbuf
puffs_framebuf_cb fcb
void *fcb_arg
int flags
)
void
puffs_framev_enqueue_justsend(
struct puffs_usermount *pu
int fd
struct
puffs_framebuf
*pufbuf"
int waitreply
int flags
)
void
puffs_framev_enqueue_directsend(
struct puffs_usermount *pu
int fd
struct puffs_framebuf *pufbuf
int flags
)
void
puffs_framev_enqueue_directreceive(
struct puffs_usermount *pu
int fd
struct puffs_framebuf *pufbuf
int flags
)
int
puffs_framev_framebuf_ccpromote(
struct puffs_framebuf *pufbuf
struct puffs_cc *pcc
)
int
puffs_framev_enqueue_waitevent(
struct puffs_cc *pcc
, int fd
, int *what
)
int
puffs_framev_readframe_fn(
struct puffs_usermount *pu
struct puffs_framebuf *pufbuf
int fd
int *done
)
int
puffs_framev_writeframe_fn(
struct puffs_usermount *pu
struct puffs_framebuf *pufbuf
int fd
int *done
)
int
puffs_framev_cmpframe_fn(
struct puffs_usermount *pu
struct puffs_framebuf *cmp1
struct puffs_framebuf *cmp2
int *notresp
)
void
puffs_framev_gotframe_fn(
struct puffs_usermount *pu
struct puffs_framebuf *pufbuf
)
void
puffs_framev_fdnotify_fn(
struct puffs_usermount *pu
int fd
int what
)
void
puffs_framev_init(
struct puffs_usermount *pu
puffs_framev_readframe_fn rfb
puffs_framev_writeframe_fn wfb
puffs_framev_cmpframe_fn cmpfb
puffs_framev_gotframe_fn gotfb
puffs_framev_fdnotify_fn fdnotfn
)
int
puffs_framev_addfd(
struct puffs_usermount *pu
, int fd
, int what
)
int
puffs_framev_enablefd(
struct puffs_usermount *pu
, int fd
, int what
)
int
puffs_framev_disablefd(
struct puffs_usermount *pu
, int fd
, int what
)
int
puffs_framev_removefd(
struct puffs_usermount *pu
, int fd
, int error
)
void
puffs_framev_unmountonclose(
struct puffs_usermount *pu
int fd
int what
)
The file system is entered in three different ways:
puffs_framebuf is used by defining various callbacks and providing I/O descriptors, which are then monitored for activity by the library. A descriptor, when present, can be either enabled or disabled for input and output. If a descriptor is not enabled for a certain direction, the callbacks will not be called even if there were activity on the descriptor. For example, even if a network socket has been added and there is input data in the socket buffer, the read callback will be called only if the socket has been enabled for reading.
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 closed 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.
The following callbacks can be defined, cf.
puffs_framev_init(),
and all are optional.
None of them should block, because this would cause the entire file server
to block.
One option is to make the descriptors non-blocking before adding them.
Better descriptions for each callback are given below.
The buffers of puffs_framebuf 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.
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.
)
NULL
in case no memory was available.
pufbuf
)
pufbuf
)
pufbuf
, space
)
pufbuf
, data
, dlen
)
pufbuf
, offset
, data
, dlen
)
),
except writes data at buffer offset
offset.
It is legal to write past the current end of the buffer.
Does NOT modify the current offset cursor.
pufbuf
, data
, dlen
)
pufbuf
, offset
, data
, dlen
)
pufbuf
)
pufbuf
)
pufbuf
)
pufbuf
, offset
)
pufbuf
, offset
, winp
, winlen
)
)
call operating on the buffer in question.
pcc
, fd
, pufbuf
, flags
)
Usually the buffer is placed at the end of the output queue.
However, if
flags
contains
PUFFS_FBQUEUE_URGENT
,
pufbuf
is placed in the front of the queue to be sent immediately after
the current PDU (if any) has been sent.
pu
, fd
, pufbuf
, fcb
, fcb_arg
, flags
)
)
will be called with the argument
fcb_arg.
The callback function
fcb(
)
is responsible for freeing the buffer.
Returns 0 if the buffer was successfully enqueued (not necessarily
delivered) and non-zero to signal a non-recoverable error.
See
puffs_framev_enqueue_cc()
for
flags.
pu
, pufbuf
, arg
, error
)
pu
, fd
, pufbuf
, waitreply
, flags
)
See
puffs_framev_enqueue_cc()
for
flags.
pcc
, fd
, pufbuf
, flags
)
)
with the exception that the call yields until the frame has been sent.
As opposed to
puffs_framev_enqueue_cc(
),
the routine does not wait for input, but returns immediately after
sending the frame.
See
puffs_framev_enqueue_cc()
for
flags.
pcc
, fd
, pufbuf
, flags
)
See
puffs_framev_enqueue_cc()
for
flags.
pufbuf
, pcc
)
)
or
puffs_framev_enqueue_justsend(
)
to a wait using
pcc
and yield until the result arrives.
The response from the file server for
pufbuf
must not yet have arrived.
If sent with
puffs_framev_enqueue_justsend(
),
the call must be expecting a response.
pcc
, fd
, what
)
PUFFS_FBIO_READ
,
PUFFS_FBIO_WRITE
,
and
PUFFS_FBIO_ERROR
,
specifying read, write and error conditions, respectively.
Error is always checked.
This call does not depend on if the events were previously enabled on the file descriptor - the specified events are always checked regardless.
There is currently no other way to cancel or timeout a call except by removing the file descriptor in question. This may change in the future.
pu
, pufbuf
, fd
, done
)
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.
pu
, pufbuf
, fd
, done
)
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.
It is a good idea to make sure that this function can handle a possible
SIGPIPE
caused by a closed connection.
For example, the file server can opt to trap
SIGPIPE
or, if writing to a socket, call
send()
with the flag
MSG_NOSIGNAL
instead of using
write().
pu
, pufbuf_cmp1
, pufbuf_cmp2
, notresp
)
pu
, pufbuf
)
pu
, fd
, what
)
PUFFS_FBIO_READ
and
PUFFS_FBIO_WRITE
for read and write, respectively.
pu
, rfb
, wfb
, cmpfb
, gotfb
, fdnotfn
)
)
is called.
The framework provides the routines
puffs_framev_removeonclose(
)
and
puffs_framev_unmountonclose(
),
which can be given as
fdnotfn.
The first one removes the file descriptor once both sides are closed
while the second one unmounts the file system and exits the mainloop.
pu
, fd
, what
)
)
or at time when running.
The parameter
what
controls enabling of input and output events and can be a bitwise
combination of
PUFFS_FBIO_READ
and
PUFFS_FBIO_WRITE
.
If not specified, the descriptor will be in a disabled state.
pu
, fd
, error
)
pu
, fd
, error
)
pu
, fd
, error
)
ECONNRESET
is used.
The file system
must
explicitly remove each fd it has added.
A good place to do this is
puffs_framev_fdnotify_fn()
or
puffs_node_reclaim(
),
depending a little on the structure of the file system.
pu
, fd
, what
)
).
It unmounts the file system when both the read and write side are
closed.
It is useful for file systems such as
mount_psshfs(8)
which depend on a single connection.
src/usr.sbin/puffs/mount_psshfs
and
src/usr.sbin/puffs/mount_9p
for the respective usage examples.
errno
to indicate the type of error.