xref: /minix/lib/libpuffs/puffs_framebuf.3 (revision 84d9c625)
1.\"	$NetBSD: puffs_framebuf.3,v 1.29 2010/04/01 09:57:00 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 September 6, 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
154The
155.Nm
156routines provide buffering and an event loop structured around the
157buffers.
158It operates on top of the puffs continuation framework,
159.Xr puffs_cc 3 ,
160and multiplexes execution automatically to an instance whenever
161one is runnable.
162.Pp
163The file system is entered in three different ways:
164.Bl -bullet -offset indent
165.It
166An event arrives from the kernel and the
167.Xr puffs_ops 3
168callbacks are called to start processing the event.
169.It
170A file system which has sent out a request receives a response.
171Execution is resumed from the place where the file system yielded.
172.It
173A request from a peer arrives.
174A request is an incoming PDU which is not a response to any outstanding
175request.
176.El
177.Pp
178.Nm
179is used by defining various callbacks and providing I/O descriptors,
180which are then monitored for activity by the library.
181A descriptor, when present, can be either enabled or disabled for
182input and output.
183If a descriptor is not enabled for a certain direction, the callbacks
184will not be called even if there were activity on the descriptor.
185For example, even if a network socket has been added and there is
186input data in the socket buffer, the read callback will be called
187only if the socket has been enabled for reading.
188.Pp
189File descriptors are treated like sockets: they have two sides, a read
190side and a write side.
191The framework determines that one side of the descriptor has been
192closed if the supplied I/O callbacks return an error or if the I/O
193multiplexing call says a side has been closed.
194It is still possible, from the framework perspective, to write to a
195file descriptor whose read side is closed.
196However, it is not possible to wait for a response on such a file
197descriptor.
198Conversely, it is possible to read responses from a descriptor whose
199write side is closed.
200It should be stressed that the implementation underlying the file
201descriptor might not support this.
202.Pp
203The following callbacks can be defined, cf.
204.Fn puffs_framev_init ,
205and all are optional.
206None of them should block, because this would cause the entire file server
207to block.
208One option is to make the descriptors non-blocking before adding them.
209.Bl -tag -width "xfdnotfnx"
210.It rfb
211Read a frame from the file descriptor onto the specified buffer.
212.It wfb
213Write a frame from the specified buffer into the file descriptor.
214.It cmpfb
215Identify if a buffer is the response to the specified buffer.
216.It gotfb
217Called iff no outstanding request matches the incoming frame.
218In other words, this is called when we receive a request from a peer.
219.It fdnotfn
220Receive notifications about a change-of-state in a file descriptor's
221status.
222.El
223.Pp
224Better descriptions for each callback are given below.
225.Pp
226The buffers of
227.Nm
228provide automatic memory management of buffers for the file servers.
229They provide a cursor to the current buffer offset.
230Reading or writing data through the normal routines will advance that cursor.
231Additionally, the buffer size is provided to the user.
232It represents the maximum offset where data was written.
233.Pp
234Generally the write functions will fail if the cannot allocate enough
235memory to satisfy the buffer length requirements.
236Read functions will fail if the amount of data written to the buffer
237is not large enough to satisfy the read.
238.Bl -tag -width xxxx
239.It Fn puffs_framebuf_make
240Create a buffer.
241Return the address of the buffer or
242.Dv NULL
243in case no memory was available.
244.It Fn puffs_framebuf_destroy pufbuf
245Free memory used by buffer.
246.It Fn puffs_framebuf_recycle pufbuf
247Reset offsets so that buffer can be reused.
248Does not free memory or reallocate memory.
249.It Fn puffs_framebuf_reserve_space pufbuf space
250Make sure that the buffer has
251.Ar space
252bytes of available memory starting from the current offset.
253This is not strictly necessary, but can be used for optimizations
254where it is known in advance how much memory will be required.
255.It Fn puffs_framebuf_putdata pufbuf data dlen
256Write
257.Ar dlen
258amount of data from the address
259.Ar data
260into the buffer.
261Moves the offset cursor forward
262.Ar dlen
263bytes.
264.It Fn puffs_framebuf_putdata_atoff pufbuf offset data dlen
265Like
266.Fn puffs_framebuf_putdata ,
267except writes data at buffer offset
268.Ar offset .
269It is legal to write past the current end of the buffer.
270Does NOT modify the current offset cursor.
271.It Fn puffs_framebuf_getdata pufbuf data dlen
272Read
273.Ar dlen
274bytes of data from the buffer into
275.Ar data .
276Advances the offset cursor.
277.It Fn puffs_framebuf_getdata_atoff pufbuf offset data dlen
278Read data from buffer position
279.Ar offset .
280Does NOT modify the offset cursor.
281.It Fn puffs_framebuf_telloff pufbuf
282Return the offset into the buffer.
283.It Fn puffs_framebuf_tellsize pufbuf
284Return the maximum offset where data has been written, i.e. buffer size.
285.It Fn puffs_framebuf_remaining pufbuf
286Distance from current offset to the end of the buffer, i.e. size-offset.
287.It Fn puffs_framebuf_seekset pufbuf offset
288Set the offset cursor to the position
289.Ar offset .
290This does NOT modify the buffer size, but reserves at least
291enough memory memory for a write to
292.Ar offset
293and will fail if memory cannot be allocated.
294.It Fn puffs_framebuf_getwindow pufbuf offset winp winlen
295Get a direct memory window into the buffer starting from
296.Ar offset .
297The maximum mapped window size will be
298.Ar winlen
299bytes, but this routine might return a smaller window and the caller
300should always check the actual mapped size after the call.
301The window is returned in
302.Ar winp .
303This function not modify the buffer offset, but it DOES set the buffer
304size to
305.Ar offset +
306.Ar winlen
307in case that value is greater than the current size.
308The window is valid until the next until the next
309.Fn puffs_framebuf
310call operating on the buffer in question.
311.It Fn puffs_framev_enqueue_cc pcc fd pufbuf flags
312Add the buffer
313.Ar pufbuf
314to outgoing queue of descriptor
315.Ar fd
316and yield with the continuation
317.Ar pcc .
318Execution is resumed once a response is received.
319Returns 0 if the buffer was successfully enqueued (not necessarily
320delivered) and non-zero to signal a non-recoverable error.
321.Pp
322Usually the buffer is placed at the end of the output queue.
323However, if
324.Ar flags
325contains
326.Dv PUFFS_FBQUEUE_URGENT ,
327.Ar pufbuf
328is placed in the front of the queue to be sent immediately after
329the current PDU (if any) has been sent.
330.It Fn puffs_framev_enqueue_cb pu fd pufbuf fcb fcb_arg flags
331Enqueue the buffer
332.Ar pufbuf
333for outgoing data and immediately return.
334Once a response arrives, the callback
335.Fn fcb
336will be called with the argument
337.Ar fcb_arg .
338The callback function
339.Fn fcb
340is responsible for freeing the buffer.
341Returns 0 if the buffer was successfully enqueued (not necessarily
342delivered) and non-zero to signal a non-recoverable error.
343.Pp
344See
345.Fn puffs_framev_enqueue_cc
346for
347.Ar flags .
348.It Fn puffs_framev_cb pu pufbuf arg error
349Callback function.
350Called when a response to a specific request arrives from the server.
351If
352.Ar error
353is non-zero, the framework was unable to obtain a response and the
354function should not examine the contents of
355.Ar pufbuf ,
356only do resource cleanup.
357May not block.
358.It Fn puffs_framev_enqueue_justsend pu fd pufbuf waitreply flags
359Enqueue the buffer
360.Ar pufbuf
361for outgoing traffic and immediately return.
362The parameter
363.Ar waitreply
364can be used to control if the buffer is to be freed immediately after
365sending of if a response is expected and the buffer should be freed
366only after the response arrives (receiving an unexpected message from
367the server is treated as an error).
368Returns 0 if the buffer was successfully enqueued (not necessarily
369delivered) and non-zero to signal a non-recoverable error.
370.Pp
371See
372.Fn puffs_framev_enqueue_cc
373for
374.Ar flags .
375.It Fn puffs_framev_enqueue_directsend pcc fd pufbuf flags
376Acts like
377.Fn puffs_framev_enqueue_justsend
378with the exception that the call yields until the frame has been sent.
379As opposed to
380.Fn puffs_framev_enqueue_cc ,
381the routine does not wait for input, but returns immediately after
382sending the frame.
383.Pp
384See
385.Fn puffs_framev_enqueue_cc
386for
387.Ar flags .
388.It Fn puffs_framev_enqueue_directreceive pcc fd pufbuf flags
389Receive data into
390.Ar pufbuf .
391This routine yields until a complete frame has been read into
392the buffer by the readframe routine.
393.Pp
394See
395.Fn puffs_framev_enqueue_cc
396for
397.Ar flags .
398.It Fn puffs_framev_framebuf_ccpromote pufbuf pcc
399Promote the framebuffer
400.Ar pufbuf
401sent with
402.Fn puffs_framev_enqueue_cb
403or
404.Fn puffs_framev_enqueue_justsend
405to a wait using
406.Ar pcc
407and yield until the result arrives.
408The response from the file server for
409.Ar pufbuf
410must not yet have arrived.
411If sent with
412.Fn puffs_framev_enqueue_justsend ,
413the call must be expecting a response.
414.It Fn puffs_framev_enqueue_waitevent pcc fd what
415Waits for an event in
416.Ar what
417to happen on file descriptor
418.Ar fd .
419The events which happened are returned back in
420.Ar what .
421The possible events are
422.Dv PUFFS_FBIO_READ ,
423.Dv PUFFS_FBIO_WRITE ,
424and
425.Dv PUFFS_FBIO_ERROR ,
426specifying read, write and error conditions, respectively.
427Error is always checked.
428.Pp
429This call does not depend on if the events were previously enabled on
430the file descriptor - the specified events are always checked
431regardless.
432.Pp
433There is currently no other way to cancel or timeout a call except by
434removing the file descriptor in question.
435This may change in the future.
436.It Fn puffs_framev_readframe_fn pu pufbuf fd done
437Callback function.
438Read at most one frame from file descriptor
439.Ar fd
440into the buffer
441.Ar pufbuf .
442If a complete frame is read, the value pointed to by
443.Ar done
444must be set to 1.
445This function should return 0 on success (even if a complete frame was not
446yet read) and a non-zero
447.Er errno
448to signal a fatal error.
449In case a fatal error is returned, the read side of the file descriptor
450is marked closed.
451This routine will be called with the same buffer argument until a
452complete frame has been read.
453May not block.
454.It Fn puffs_framev_writeframe_fn pu pufbuf fd done
455Write the frame contained in
456.Ar pufbuf
457to the file descriptor
458.Ar fd .
459In case the entire frame is successfully written,
460.Ar *done
461should be set to 1.
462This function should return 0 on success (even if a complete frame was not
463yet written) and a non-zero
464.Er errno
465to signal a fatal error.
466In case a fatal error is returned, the write side of the file descriptor
467is marked closed.
468This routine will be called with the same buffer argument until the
469complete frame has been written.
470May not block.
471.Pp
472It is a good idea to make sure that this function can handle a possible
473.Dv SIGPIPE
474caused by a closed connection.
475For example, the file server can opt to trap
476.Dv SIGPIPE
477or, if writing to a socket, call
478.Fn send
479with the flag
480.Dv MSG_NOSIGNAL
481instead of using
482.Fn write .
483.It Fn puffs_framev_cmpframe_fn pu pufbuf_cmp1 pufbuf_cmp2 notresp
484Compare the file system internal request tags in
485.Ar pufbuf_cmp1
486and
487.Ar pufbuf_cmp2 .
488Should return 0 if the tags are equal, 1 if first buffer's tag is
489greater than the second and \-1 if it is smaller.
490The definitions "greater" and "smaller" are used transparently by
491the library, e.g. like
492.Xr qsort 3 .
493If it can be determined from
494.Ar pufbuf_cmp1
495that it is not a response to any outstanding request,
496.Ar notresp
497should be set to non-zero.
498This will cause
499.Nm
500to skip the test of the buffer against the rest of the outstanding
501request.
502May not block.
503.It Fn puffs_framev_gotframe_fn pu pufbuf
504Called when no outstanding request matches an incoming frame.
505The ownership of
506.Ar pufbuf
507is transferred to the called function and must be destroyed once
508processing is over.
509May not block.
510.It Fn puffs_framev_fdnotify_fn pu fd what
511Is called when the read or write side of the file descriptor
512.Ar fd
513is closed.
514It is called once for each side, the bitmask parameter
515.Ar what
516specified what is currently closed:
517.Dv PUFFS_FBIO_READ
518and
519.Dv PUFFS_FBIO_WRITE
520for read and write, respectively.
521.It Fn puffs_framev_init pu rfb wfb cmpfb gotfb fdnotfn
522Initializes the given callbacks to the system.
523They will be used when
524.Fn puffs_mainloop
525is called.
526The framework provides the routines
527.Fn puffs_framev_removeonclose
528and
529.Fn puffs_framev_unmountonclose ,
530which can be given as
531.Ar fdnotfn .
532The first one removes the file descriptor once both sides are closed
533while the second one unmounts the file system and exits the mainloop.
534.It Fn puffs_framev_addfd pu fd what
535Add file descriptor
536.Ar fd
537to be handled by the framework.
538It is legal to add a file descriptor either before calling
539.Fn puffs_mainloop
540or at time when running.
541The parameter
542.Ar what
543controls enabling of input and output events and can be a bitwise
544combination of
545.Dv PUFFS_FBIO_READ
546and
547.Dv PUFFS_FBIO_WRITE .
548If not specified, the descriptor will be in a disabled state.
549.It Fn puffs_framev_enablefd pu fd what
550Enable events of type
551.Ar what
552for file descriptor
553.Ar fd .
554.It Fn puffs_framev_disablefd pu fd what
555Disable events of type
556.Ar what
557for file descriptor
558.Ar fd .
559.It Fn puffs_framev_removefd pu fd error
560Remove file descriptor
561.Ar fd
562from the list of descriptors handled by the framework.
563Removing a file descriptor causes all operations blocked either on
564output or input to be released with the error value
565.Ar error .
566In case 0 is supplied as this parameter,
567.Er ECONNRESET
568is used.
569.Pp
570The file system
571.Em must
572explicitly remove each fd it has added.
573A good place to do this is
574.Fn puffs_framev_fdnotify_fn
575or
576.Fn puffs_node_reclaim ,
577depending a little on the structure of the file system.
578.It Fn puffs_framev_unmountonclose pu fd what
579This is library provided convenience routine for
580.Fn puffs_framev_fdnotify_fn .
581It unmounts the file system when both the read and write side are
582closed.
583It is useful for file systems such as
584.Xr mount_psshfs 8
585which depend on a single connection.
586.El
587.Sh CODE REFERENCES
588The current users of
589.Nm
590in the tree are
591.Xr mount_psshfs 8
592and
593.Xr mount_9p 8 .
594See
595.Pa src/usr.sbin/puffs/mount_psshfs
596and
597.Pa src/usr.sbin/puffs/mount_9p
598for the respective usage examples.
599.Sh RETURN VALUES
600These functions generally return \-1 to signal error and set
601.Er errno
602to indicate the type of error.
603.Sh SEE ALSO
604.Xr puffs 3 ,
605.Xr puffs_cc 3 ,
606.Xr puffs_ops 3
607.Rs
608.%A Antti Kantee
609.%D September 2007
610.%I Helsinki University of Technology
611.%R Tech Report TKK-TKO-B157
612.%T Using puffs for Implementing Client-Server Distributed File Systems
613.Re
614.Rs
615.%A Antti Kantee
616.%D March 2008
617.%J Proceedings of AsiaBSDCon 2008
618.%P pp. 55-70
619.%T Send and Receive of File System Protocols: Userspace Approach With puffs
620.Re
621