xref: /netbsd-src/lib/libpuffs/puffs_framebuf.3 (revision 2980e352a13e8f0b545a366830c411e7a542ada8)
1.\"	$NetBSD: puffs_framebuf.3,v 1.23 2008/01/29 10:15:50 pooka Exp $
2.\"
3.\" Copyright (c) 2007 Antti Kantee.  All rights reserved.
4.\"
5.\" Redistribution and use in source and binary forms, with or without
6.\" modification, are permitted provided that the following conditions
7.\" are met:
8.\" 1. Redistributions of source code must retain the above copyright
9.\"    notice, this list of conditions and the following disclaimer.
10.\" 2. Redistributions in binary form must reproduce the above copyright
11.\"    notice, this list of conditions and the following disclaimer in the
12.\"    documentation and/or other materials provided with the distribution.
13.\"
14.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24.\" SUCH DAMAGE.
25.\"
26.Dd January 29, 2008
27.Dt PUFFS_FRAMEBUF 3
28.Os
29.Sh NAME
30.Nm puffs_framebuf
31.Nd buffering and event handling for networked file systems
32.Sh LIBRARY
33.Lb libpuffs
34.Sh SYNOPSIS
35.In puffs.h
36.Ft struct puffs_framebuf *
37.Fn puffs_framebuf_make
38.Ft void
39.Fn puffs_framebuf_destroy "struct puffs_framebuf *pufbuf"
40.Ft void
41.Fn puffs_framebuf_recycle "struct puffs_framebuf *pufbuf"
42.Ft int
43.Fn puffs_framebuf_reserve_space "struct puffs_framebuf *pufbuf" "size_t space"
44.Ft int
45.Fo puffs_framebuf_putdata
46.Fa "struct puffs_framebuf *pufbuf" "const void *data" "size_t dlen"
47.Fc
48.Ft int
49.Fo puffs_framebuf_putdata_atoff
50.Fa "struct puffs_framebuf *pufbuf" "size_t offset" "const void *data"
51.Fa "size_t dlen"
52.Fc
53.Ft int
54.Fo puffs_framebuf_getdata
55.Fa "struct puffs_framebuf *pufbuf" "void *data" "size_t dlen"
56.Fc
57.Ft int
58.Fo puffs_framebuf_getdata_atoff
59.Fa "struct puffs_framebuf *pufbuf" "size_t offset"
60.Fa "void *data" "size_t dlen"
61.Fc
62.Ft size_t
63.Fn puffs_framebuf_telloff "struct puffs_framebuf *pufbuf"
64.Ft size_t
65.Fn puffs_framebuf_tellsize "struct puffs_framebuf *pufbuf"
66.Ft size_t
67.Fn puffs_framebuf_remaining "struct puffs_framebuf *pufbuf"
68.Ft int
69.Fn puffs_framebuf_seekset "struct puffs_framebuf *pufbuf" "size_t offset"
70.Ft int
71.Fo puffs_framebuf_getwindow
72.Fa "struct puffs_framebuf *pufbuf" "size_t offset"
73.Fa "void **winp" "size_t *winlen"
74.Fc
75.Ft int
76.Fo puffs_framev_enqueue_cc
77.Fa "struct puffs_cc *pcc" "int fd" "struct puffs_framebuf *pufbuf" "int flags"
78.Fc
79.Ft void
80.Fo puffs_framev_cb
81.Fa "struct puffs_usermount *pu" "int fd" "struct puffs_framebuf *pufbuf"
82.Fa "void *arg" "int flags"
83.Fa "int error"
84.Fc
85.Ft void
86.Fo puffs_framev_enqueue_cb
87.Fa "struct puffs_usermount *pu" "int fd" "struct puffs_framebuf *pufbuf"
88.Fa "puffs_framebuf_cb fcb" "void *fcb_arg" "int flags"
89.Fc
90.Ft void
91.Fo puffs_framev_enqueue_justsend
92.Fa "struct puffs_usermount *pu" "int fd "struct puffs_framebuf *pufbuf"
93.Fa "int waitreply" "int flags"
94.Fc
95.Ft void
96.Fo puffs_framev_enqueue_directsend
97.Fa "struct puffs_usermount *pu" "int fd" "struct puffs_framebuf *pufbuf"
98.Fa "int flags"
99.Fc
100.Ft void
101.Fo puffs_framev_enqueue_directreceive
102.Fa "struct puffs_usermount *pu" "int fd" "struct puffs_framebuf *pufbuf"
103.Fa "int flags"
104.Fc
105.Ft int
106.Fo puffs_framev_framebuf_ccpromote
107.Fa "struct puffs_framebuf *pufbuf" "struct puffs_cc *pcc"
108.Fc
109.Ft int
110.Fn puffs_framev_enqueue_waitevent "struct puffs_cc *pcc" "int fd" "int *what"
111.Ft int
112.Fo puffs_framev_readframe_fn
113.Fa "struct puffs_usermount *pu" "struct puffs_framebuf *pufbuf"
114.Fa "int fd" "int *done"
115.Fc
116.Ft int
117.Fo puffs_framev_writeframe_fn
118.Fa "struct puffs_usermount *pu" "struct puffs_framebuf *pufbuf"
119.Fa "int fd" "int *done"
120.Fc
121.Ft int
122.Fo puffs_framev_cmpframe_fn
123.Fa "struct puffs_usermount *pu"
124.Fa "struct puffs_framebuf *cmp1" "struct puffs_framebuf *cmp2" "int *notresp"
125.Fc
126.Ft void
127.Fo puffs_framev_gotframe_fn
128.Fa "struct puffs_usermount *pu" "struct puffs_framebuf *pufbuf"
129.Fc
130.Ft void
131.Fo puffs_framev_fdnotify_fn
132.Fa "struct puffs_usermount *pu" "int fd" "int what"
133.Fc
134.Ft void
135.Fo puffs_framev_init
136.Fa "struct puffs_usermount *pu"
137.Fa "puffs_framev_readframe_fn rfb" "puffs_framev_writeframe_fn wfb"
138.Fa "puffs_framev_cmpframe_fn cmpfb" "puffs_framev_gotframe_fn gotfb"
139.Fa "puffs_framev_fdnotify_fn fdnotfn"
140.Fc
141.Ft int
142.Fn puffs_framev_addfd "struct puffs_usermount *pu" "int fd" "int what"
143.Ft int
144.Fn puffs_framev_enablefd "struct puffs_usermount *pu" "int fd" "int what"
145.Ft int
146.Fn puffs_framev_disablefd "struct puffs_usermount *pu" "int fd" "int what"
147.Ft int
148.Fn puffs_framev_removefd "struct puffs_usermount *pu" "int fd" "int error"
149.Ft void
150.Fo puffs_framev_unmountonclose
151.Fa "struct puffs_usermount *pu" "int fd" "int what"
152.Fc
153.Sh DESCRIPTION
154.Em IMPORTANT NOTE!
155This document describes interfaces which are not yet guaranteed to be
156stable.
157In case you update your system sources, please recompile everything
158and fix compilation errors.
159If your sources are out-of-sync, incorrect operation may result.
160.Pp
161The
162.Nm
163routines provide buffering and an event loop structured around the
164buffers.
165It operates on top of the puffs continuation framework,
166.Xr puffs_cc 3 ,
167and multiplexes execution automatically to an instance whenever
168one is runnable.
169.Pp
170The file system is entered in three different ways:
171.Bl -bullet -offset indent
172.It
173An event arrives from the kernel and the
174.Xr puffs_ops 3
175callbacks are called to start processing the event.
176.It
177A file system which has sent out a request receives a response.
178Execution is resumed from the place where the file system yielded.
179.It
180A request from a peer arrives.
181A request is an incoming PDU which is not a response to any outstanding
182request.
183.El
184.Pp
185.Nm
186is used by defining various callbacks and providing I/O descriptors,
187which are then monitored for activity by the library.
188A descriptor, when present, can be either enabled or disabled for
189input and output.
190If a descriptor is not enabled for a certain direction, the callbacks
191will not be called even if there were activity on the descriptor.
192For example, even if a network socket has been added and there is
193input data in the socket buffer, the read callback will be called
194only if the socket has been enabled for reading.
195.Pp
196File descriptors are treated like sockets: they have two sides, a read
197side and a write side.
198The framework determines that one side of the descriptor has been
199closed if the supplied I/O callbacks return an error or if the I/O
200multiplexing call says a side has been closed.
201It is still possible, from the framework perspective, to write to a
202file descriptor whose read side is closed.
203However, it is not possible to wait for a response on such a file
204descriptor.
205Conversely, it is possible to read responses from a descriptor whose
206write side is closed.
207It should be stressed that the implementation underlying the file
208descriptor might not support this.
209.Pp
210The following callbacks can be defined, cf.
211.Fn puffs_framev_init ,
212and all are optional.
213None of them should block, because this would cause the entire file server
214to block.
215One option is to make the descriptors non-blocking before adding them.
216.Bl -tag -width "xfdnotfnx"
217.It rfb
218Read a frame from the file descriptor onto the specified buffer.
219.It wfb
220Write a frame from the the specified buffer into the file descriptor.
221.It cmpfb
222Identify if a buffer is the response to the specified buffer.
223.It gotfb
224Called iff no outstanding request matches the incoming frame.
225In other words, this is called when we receive a request from a peer.
226.It fdnotfn
227Receive notifications about a change-of-state in a file descriptor's
228status.
229.El
230.Pp
231Better descriptions for each callback are given below.
232.Pp
233The buffers of
234.Nm
235provide automatic memory management of buffers for the file servers.
236They provide a cursor to the current buffer offset.
237Reading or writing data through the normal routines will advance that cursor.
238Additionally, the buffer size is provided to the user.
239It represents the maximum offset where data was written.
240.Pp
241Generally the write functions will fail if the cannot allocate enough
242memory to satisfy the buffer length requirements.
243Read functions will fail if the amount of data written to the buffer
244is not large enough to satisfy the read.
245.Bl -tag -width xxxx
246.It Fn puffs_framebuf_make
247Create a buffer.
248Return the address of the buffer or
249.Dv NULL
250in case no memory was available.
251.It Fn puffs_framebuf_destroy pufbuf
252Free memory used by buffer.
253.It Fn puffs_framebuf_recycle pufbuf
254Reset offsets so that buffer can be reused.
255Does not free memory or reallocate memory.
256.It Fn puffs_framebuf_reserve_space pufbuf space
257Make sure that the buffer has
258.Ar space
259bytes of available memory starting from the current offset.
260This is not strictly necessary, but can be used for optimizations
261where it is known in advance how much memory will be required.
262.It Fn puffs_framebuf_putdata pufbuf data dlen
263Write
264.Ar dlen
265amount of data from the address
266.Ar data
267into the buffer.
268Moves the offset cursor forward
269.Ar dlen
270bytes.
271.It Fn puffs_framebuf_putdata_atoff pufbuf offset data dlen
272Like
273.Fn puffs_framebuf_putdata ,
274except writes data at buffer offset
275.Ar offset .
276It is legal to write past the current end of the buffer.
277Does NOT modify the current offset cursor.
278.It Fn puffs_framebuf_getdata pufbuf data dlen
279Read
280.Ar dlen
281bytes of data from the buffer into
282.Ar data .
283Advances the offset cursor.
284.It Fn puffs_framebuf_getdata_atoff pufbuf offset data dlen
285Read data from buffer position
286.Ar offset .
287Does NOT modify the offset cursor.
288.It Fn puffs_framebuf_telloff pufbuf
289Return the offset into the buffer.
290.It Fn puffs_framebuf_tellsize pufbuf
291Return the maximum offset where data has been written, i.e. buffer size.
292.It Fn puffs_framebuf_remaining pufbuf
293Distance from current offset to the end of the buffer, i.e. size-offset.
294.It Fn puffs_framebuf_seekset pufbuf offset
295Set the offset cursor to the position
296.Ar offset .
297This does NOT modify the buffer size, but reserves at least
298enough memory memory for a write to
299.Ar offset
300and will fail if memory cannot be allocated.
301.It Fn puffs_framebuf_getwindow pufbuf offset winp winlen
302Get a direct memory window into the buffer starting from
303.Ar offset .
304The maximum mapped window size will be
305.Ar winlen
306bytes, but this routine might return a smaller window and the caller
307should always check the actual mapped size after the call.
308The window is returned in
309.Ar winp .
310This function not modify the buffer offset, but it DOES set the buffer
311size to
312.Ar offset +
313.Ar winlen
314in case that value is greater than the current size.
315The window is valid until the next until the next
316.Fn puffs_framebuf
317call operating on the buffer in question.
318.It Fn puffs_framev_enqueue_cc pcc fd pufbuf flags
319Add the buffer
320.Ar pufbuf
321to outgoing queue of descriptor
322.Ar fd
323and yield with the continuation
324.Ar pcc .
325Execution is resumed once a response is received.
326Returns 0 if the buffer was successfully enqueued (not necessarily
327delivered) and non-zero to signal a non-recoverable error.
328.Pp
329Usually the buffer is placed at the end of the output queue.
330However, if
331.Ar flags
332contains
333.Dv PUFFS_FBQUEUE_URGENT ,
334.Ar pufbuf
335is placed in the front of the queue to be sent immediately after
336the current PDU (if any) has been sent.
337.It Fn puffs_framev_enqueue_cb pu fd pufbuf fcb fcb_arg flags
338Enqueue the buffer
339.Ar pufbuf
340for outgoing data and immediately return.
341Once a response arrives, the callback
342.Fn fcb
343will be called with the argument
344.Ar fcb_arg .
345The callback function
346.Fn fcb
347is responsible for freeing the buffer.
348Returns 0 if the buffer was successfully enqueued (not necessarily
349delivered) and non-zero to signal a non-recoverable error.
350.Pp
351See
352.Fn puffs_framev_enqueue_cc
353for
354.Ar flags .
355.It Fn puffs_framev_cb pu pufbuf arg error
356Callback function.
357Called when a response to a specific request arrives from the server.
358If
359.Ar error
360is non-zero, the framework was unable to obtain a response and the
361function should not examine the contents of
362.Ar pufbuf ,
363only do resource cleanup.
364May not block.
365.It Fn puffs_framev_enqueue_justsend pu fd pufbuf waitreply flags
366Enqueue the buffer
367.Ar pufbuf
368for outgoing traffic and immediately return.
369The parameter
370.Ar waitreply
371can be used to control if the buffer is to be freed immediately after
372sending of if a response is expected and the buffer should be freed
373only after the response arrives (receiving an unexpected message from
374the server is treated as an error).
375Returns 0 if the buffer was successfully enqueued (not necessarily
376delivered) and non-zero to signal a non-recoverable error.
377.Pp
378See
379.Fn puffs_framev_enqueue_cc
380for
381.Ar flags .
382.It Fn puffs_framev_enqueue_directsend pcc fd pufbuf flags
383Acts like
384.Fn puffs_framev_enqueue_justsend
385with the exception that the call yields until the frame has been sent.
386As opposed to
387.Fn puffs_framev_enqueue_cc ,
388the routine does not wait for input, but returns immediately after
389sending the frame.
390.Pp
391See
392.Fn puffs_framev_enqueue_cc
393for
394.Ar flags .
395.It Fn puffs_framev_enqueue_directreceive pcc fd pufbuf flags
396Receive data into
397.Ar pufbuf .
398This routine yields until a complete frame has been read into
399the buffer by the readframe routine.
400.Pp
401See
402.Fn puffs_framev_enqueue_cc
403for
404.Ar flags .
405.It Fn puffs_framev_framebuf_ccpromote pufbuf pcc
406Promote the framebuffer
407.Ar pufbuf
408sent with
409.Fn puffs_framev_enqueue_cb
410or
411.Fn puffs_framev_enqueue_justsend
412to a wait using
413.Ar pcc
414and yield until the result arrives.
415The response from the file server for
416.Ar pufbuf
417must not yet have arrived.
418If sent with
419.Fn puffs_framev_enqueue_justsend ,
420the call must be expecting a response.
421.It Fn puffs_framev_enqueue_waitevent pcc fd what
422Waits for an event in
423.Ar what
424to happen on file descriptor
425.Ar fd .
426The events which happened are returned back in
427.Ar what .
428The possible events are
429.Dv PUFFS_FBIO_READ ,
430.Dv PUFFS_FBIO_WRITE ,
431and
432.Dv PUFFS_FBIO_ERROR ,
433specifying read, write and error conditions, respectively.
434Error is always checked.
435.Pp
436This call does not depend on if the events were previously enabled on
437the file descriptor - the specified events are always checked
438regardless.
439.Pp
440There is currently no other way to cancel or timeout a call except by
441removing the file descriptor in question.
442This may change in the future.
443.It Fn puffs_framev_readframe_fn pu pufbuf fd done
444Callback function.
445Read at most one frame from file descriptor
446.Ar fd
447into the buffer
448.Ar pufbuf .
449If a complete frame is read, the value pointed to by
450.Ar done
451must be set to 1.
452This function should return 0 on success (even if a complete frame was not
453yet read) and a non-zero
454.Er errno
455to signal a fatal error.
456In case a fatal error is returned, the read side of the file descriptor
457is marked closed.
458This routine will be called with the same buffer argument until a
459complete frame has been read.
460May not block.
461.It Fn puffs_framev_writeframe_fn pu pufbuf fd done
462Write the frame contained in
463.Ar pufbuf
464to the file descriptor
465.Ar fd .
466In case the entire frame is successfully written,
467.Ar *done
468should be set to 1.
469This function should return 0 on success (even if a complete frame was not
470yet written) and a non-zero
471.Er errno
472to signal a fatal error.
473In case a fatal error is returned, the write side of the file descriptor
474is marked closed.
475This routine will be called with the same buffer argument until the
476complete frame has been written.
477May not block.
478.Pp
479It is a good idea to make sure that this function can handle a possible
480.Dv SIGPIPE
481caused by a closed connection.
482For example, the file server can opt to trap
483.Dv SIGPIPE
484or, if writing to a socket, call
485.Fn send
486with the flag
487.Dv MSG_NOSIGNAL
488instead of using
489.Fn write .
490.It Fn puffs_framev_cmpframe_fn pu pufbuf_cmp1 pufbuf_cmp2 notresp
491Compare the file system internal request tags in
492.Ar pufbuf_cmp1
493and
494.Ar pufbuf_cmp2 .
495Should return 0 if the tags are equal, 1 if first buffer's tag is
496greater than the second and \-1 if it is smaller.
497The definitions "greater" and "smaller" are used transparently by
498the library, e.g. like
499.Xr qsort 3 .
500If it can be determined from
501.Ar pufbuf_cmp1
502that it is not a response to any outstanding request,
503.Ar notresp
504should be set to non-zero.
505This will cause
506.Nm
507to skip the test of the buffer against the rest of the outstanding
508request.
509May not block.
510.It Fn puffs_framev_gotframe_fn pu pufbuf
511Called when no outstanding request matches an incoming frame.
512The ownership of
513.Ar pufbuf
514is transferred to the called function and must be destroyed once
515processing is over.
516May not block.
517.It Fn puffs_framev_fdnotify_fn pu fd what
518Is called when the read or write side of the file descriptor
519.Ar fd
520is closed.
521It is called once for each side, the bitmask parameter
522.Ar what
523specified what is currently closed:
524.Dv PUFFS_FBIO_READ
525and
526.Dv PUFFS_FBIO_WRITE
527for read and write, respectively.
528.It Fn puffs_framev_init pu rfb wfb cmpfb gotfb fdnotfn
529Initializes the given callbacks to the system.
530They will be used when
531.Fn puffs_mainloop
532is called.
533The framework provides the routines
534.Fn puffs_framev_removeonclose
535and
536.Fn puffs_framev_unmountonclose ,
537which can be given as
538.Ar fdnotfn .
539The first one removes the file descriptor once both sides are closed
540while the second one unmounts the file system and exits the mainloop.
541.It Fn puffs_framev_addfd pu fd what
542Add file descriptor
543.Ar fd
544to be handled by the framework.
545It is legal to add a file descriptor either before calling
546.Fn puffs_mainloop
547or at time when running.
548The parameter
549.Ar what
550controls enabling of input and output events and can be a bitwise
551combination of
552.Dv PUFFS_FBIO_READ
553and
554.Dv PUFFS_FBIO_WRITE .
555If not specified, the descriptor will be in a disabled state.
556.It Fn puffs_framev_enablefd pu fd error
557Enable events of type
558.Ar what
559for file descriptor
560.Ar fd .
561.It Fn puffs_framev_disablefd pu fd error
562Disable events of type
563.Ar what
564for file descriptor
565.Ar fd .
566.It Fn puffs_framev_removefd pu fd error
567Remove file descriptor
568.Ar fd
569from the list of descriptors handled by the framework.
570Removing a file descriptor causes all operations blocked either on
571output or input to be released with the error value
572.Ar error .
573In case 0 is supplied as this parameter,
574.Er ECONNRESET
575is used.
576.Pp
577The file system
578.Em must
579explicitly remove each fd it has added.
580A good place to do this is
581.Fn puffs_framev_fdnotify_fn
582or
583.Fn puffs_node_reclaim ,
584depending a little on the structure of the file system.
585.It Fn puffs_framev_unmountonclose pu fd what
586This is library provided convenience routine for
587.Fn puffs_framev_fdnotify_fn .
588It unmounts the file system when both the read and write side are
589closed.
590It is useful for file systems such as
591.Xr mount_psshfs 8
592which depend on a single connection.
593.El
594.Sh CODE REFERENCES
595The current users of
596.Nm
597in the tree are
598.Xr mount_psshfs 8
599and
600.Xr mount_9p 8 .
601See
602.Pa src/usr.sbin/puffs/mount_psshfs
603and
604.Pa src/usr.sbin/puffs/mount_9p
605for the respective usage examples.
606.Sh RETURN VALUES
607These functions generally return \-1 to signal error and set
608.Er errno
609to indicate the type of error.
610.Sh SEE ALSO
611.Xr puffs 3 ,
612.Xr puffs_cc 3 ,
613.Xr puffs_ops 3
614.Rs
615.%A Antti Kantee
616.%D September 2007
617.%I Helsinki University of Technology
618.%R Tech Report TKK-TKO-B157
619.%T Using puffs for Implementing Client-Server Distributed File Systems
620.Re
621