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