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