1.\" $NetBSD: puffs.3,v 1.46 2009/02/20 14:26:56 pooka Exp $ 2.\" 3.\" Copyright (c) 2006, 2007, 2008 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 December 12, 2008 27.Dt PUFFS 3 28.Os 29.Sh NAME 30.Nm puffs 31.Nd Pass-to-Userspace Framework File System development interface 32.Sh LIBRARY 33.Lb libpuffs 34.Sh SYNOPSIS 35.In puffs.h 36.Ft struct puffs_usermount * 37.Fo puffs_init 38.Fa "struct puffs_ops *pops" "const char *mntfromname" "const char *puffsname" 39.Fa "void *private" "uint32_t flags" 40.Fc 41.Ft int 42.Fo puffs_mount 43.Fa "struct puffs_usermount *pu" "const char *dir" "int mntflags" 44.Fa "puffs_cookie_t root_cookie" 45.Fc 46.Ft int 47.Fn puffs_getselectable "struct puffs_usermount *pu" 48.Ft int 49.Fn puffs_setblockingmode "struct puffs_usermount *pu" "int mode" 50.Ft int 51.Fn puffs_getstate "struct puffs_usermount *pu" 52.Ft int 53.Fn puffs_setstacksize "struct puffs_usermount *pu" "size_t stacksize" 54.Ft void 55.Fn puffs_setroot "struct puffs_usermount *pu" "struct puffs_node *node" 56.Ft void 57.Fo puffs_setrootinfo 58.Fa "struct puffs_usermount *pu" "enum vtype vt" "vsize_t vsize" "dev_t rdev" 59.Fc 60.Ft struct puffs_node * 61.Fn puffs_getroot "struct puffs_usermount *pu" 62.Ft void * 63.Fn puffs_getspecific "struct puffs_usermount *pu" 64.Ft void 65.Fn puffs_setspecific "struct puffs_usermount *pu" "void *private" 66.Ft void 67.Fn puffs_setmaxreqlen "struct puffs_usermount *pu" "size_t maxreqlen" 68.Ft size_t 69.Fn puffs_getmaxreqlen "struct puffs_usermount *pu" 70.Ft void 71.Fn puffs_setfhsize "struct puffs_usermount *pu" "size_t fhsize" "int flags" 72.Ft void 73.Fn puffs_setncookiehash "struct puffs_usermount *pu" "int nhashes" 74.Ft void 75.Fn puffs_ml_loop_fn "struct puffs_usermount *pu" 76.Ft void 77.Fn puffs_ml_setloopfn "struct puffs_usermount *pu" "puffs_ml_loop_fn lfn" 78.Ft void 79.Fn puffs_ml_settimeout "struct puffs_usermount *pu" "struct timespec *ts" 80.Ft int 81.Fn puffs_daemon "struct puffs_usermount *pu" "int nochdir" "int noclose" 82.Ft int 83.Fn puffs_mainloop "struct puffs_usermount *pu" 84.Ft int 85.Fo puffs_dispatch_create 86.Fa "struct puffs_usermount *pu" "struct puffs_framebuf *pb" 87.Fa "struct puffs_cc **pccp" 88.Fc 89.Ft int 90.Fn puffs_dispatch_exec "struct puffs_cc *pcc" "struct puffs_framebuf **pbp" 91.Sh DESCRIPTION 92.Nm 93provides a framework for creating file systems as userspace servers. 94Operations are transported from the kernel virtual file system layer 95to the concrete implementation behind 96.Nm , 97where they are processed and results are sent back to the kernel. 98.Pp 99It is possible to use 100.Nm 101in two different ways. 102Calling 103.Fn puffs_mainloop 104takes execution context away from the caller and automatically handles 105all requests by using the callbacks. 106By using 107.Xr puffs_framebuf 3 108in conjuction with 109.Fn puffs_mainloop , 110it is possible to handle I/O to and from file descriptors. 111This is suited e.g. for distributed file servers. 112.Ss Library operation 113Operations on the library always require a pointer to the opaque context 114identifier, 115.Va struct puffs_usermount . 116It is obtained by calling 117.Fn puffs_init . 118.Pp 119.Nm 120operates using operation callbacks. 121They can be initialized using the macro 122.Fn PUFFSOP_SET pops fsname type opname , 123which will initialize the operation 124.Fn puffs_type_opname 125in 126.Fa pops 127to 128.Fn fsname_type_opname . 129All operations are initialized to a default state with the call 130.Fn PUFFSOP_INIT pops . 131All of the VFS routines are mandatory, but all of the node operations 132with the exception of 133.Fn puffs_node_lookup 134are optional. 135However, leaving operations blank will naturally have an effect on the 136features available from the file system implementation. 137.Bl -tag -width xxxx 138.It Fn puffs_init pops mntfromname puffsname private flags 139Initializes the library context. 140.Ar pops 141specifies the callback operations vector. 142.Ar mntfromname 143is device the file system is mounted from. 144This can be for example a block device such as 145.Pa /dev/wd0a 146or, if the file system is pseudo file system, the 147.Nm 148device name can be given by 149.Dv _PATH_PUFFS . 150This value is used for example in the first column of the output of 151.Xr mount 8 152and 153.Xr df 1 . 154.Ar puffsname 155is the file system type. 156It will always be prepended with the string "puffs|". 157If possible, file server binaries should be named using the format 158"mount_myfsnamehere" and this value should equal "myfsnamehere". 159A file system specific context pointer can optionally be given in 160.Ar private . 161This can be retrieved by 162.Fn puffs_getspecific . 163Flags for 164.Nm 165can be given via 166.Fa pflags . 167Currently the following flags are supported: 168.Bl -tag -width "XPUFFS_KFLAG_LOOKUP_FULLPNBUF" 169.It Dv PUFFS_KFLAG_NOCACHE_NAME 170Do not enter pathname components into the name cache. 171This means that every time the kernel does a lookup for a 172componentname, the file server will be consulted. 173.It Dv PUFFS_KFLAG_NOCACHE_PAGE 174Do not use the page cache. 175This means that all reads and writes to regular file are 176propagated to the file server for handling. 177This option makes a difference only for regular files. 178.It Dv PUFFS_KFLAG_NOCACHE 179An alias for both 180.Dv PUFFS_KFLAG_NOCACHE_NAME 181and 182.Dv PUFFS_KFLAG_NOCACHE_PAGE . 183.It Dv PUFFS_KFLAG_ALLOPS 184This flag requests that all operations are sent to userspace. 185Normally the kernel shortcircuits unimplemented operations. 186This flag is mostly useful for debugging purposes. 187.It Dv PUFFS_KFLAG_WTCACHE 188Set the file system cache behavior as write-through. 189This means that all writes are immediately issued to the file server 190instead of being flushed in file system sync. 191This is useful especially for distributed file systems. 192.It Dv PUFFS_KFLAG_IAONDEMAND 193Issue inactive only on demand. 194If a file server defines the inactive method, call it only if the file 195server has explicitly requested that inactive be called for the 196node in question. 197Once inactive has been called for a node, it will not be called 198again unless the request to call inactive is reissued by the file server. 199See 200.Fn puffs_setback 201in 202.Xr puffs_ops 3 203for more information. 204.It Dv PUFFS_KFLAG_LOOKUP_FULLPNBUF 205This flag affects only the parameter 206.Ar pcn to 207.Fn puffs_node_lookup . 208If this flag is not given, only the next pathname component under 209lookup is found from 210.Ar pcn-\*[Gt]pcn_name . 211If this flag is given, the full path the kernel was 212asked to resolve can be found from there. 213.It Dv PUFFS_FLAG_BUILDPATH 214The framework will build a complete path name, which is supplied 215with each operation and can be found from the 216.Va pn_po.po_full_pcn 217field in a 218.Vt struct puffs_node . 219The option assumes that the framework can map a cookie to a 220.Vt struct puffs_node . 221See 222.Sx Cookies 223for more information on cookie mapping. 224See 225.Xr puffs_path 3 226for more information on library calls involving paths. 227.It Dv PUFFS_FLAG_HASHPATH 228Calculate a hash of the path into the path object field 229.Va po_hash . 230This hash value is used by 231.Fn puffs_path_walkcmp 232to avoid doing a full comparison for every path equal in length to 233the one searched for. 234Especially if the file system uses the abovementioned function, it 235is a good idea to define this flag. 236.It Dv PUFFS_FLAG_OPDUMP 237This option makes the framework dump a textual representation of 238each operation before executing it. 239It is useful for debugging purposes. 240.El 241.El 242.Pp 243The following functions can be used to query or modify the global 244state of the file system. 245Note, that all calls are not available at all times. 246.Bl -tag -width xxxx 247.It Fn puffs_getselectable "pu" 248Returns a handle to do I/O multiplexing with: 249.Xr select 2 , 250.Xr poll 2 , 251and 252.Xr kqueue 2 253are all examples of acceptable operations. 254.It Fn puffs_setblockingmode "pu" "mode" 255Sets the file system upstream access to blocking or non-blocking mode. 256Acceptable values for the argument are 257.Dv PUFFSDEV_BLOCK 258and 259.Dv PUFFSDEV_NONBLOCK . 260.Pp 261This routine can be called only after calling 262.Fn puffs_mount . 263.It Fn puffs_getstate "pu" 264Returns the state of the file system. 265It is maintained by the framework and is mostly useful for the framework 266itself. 267Possible values are 268.Dv PUFFS_STATE_BEFOREMOUNT , 269.Dv PUFFS_STATE_RUNNING , 270.Dv PUFFS_STATE_UNMOUNTING 271and 272.Dv PUFFS_STATE_UNMOUNTED . 273.It Fn puffs_setstacksize "pu" "stacksize" 274Sets the stack size used when running callbacks. 275The default is 276.Dv PUFFS_STACKSIZE_DEFAULT 277bytes of stack space per request. 278The minimum stacksize is architecture-dependent and can be specified 279by using the opaque constant 280.Dv PUFFS_STACKSIZE_MIN . 281.It Fn puffs_setroot "pu" "node" 282Sets the root node of mount 283.Fa pu 284to 285.Fa "node" . 286Setting the root node is currently required only if the path 287framework is used, see 288.Xr puffs_path 3 . 289.It Fn puffs_setrootinfo pu vt vsize rdev 290The default root node is a directory. 291In case the file system wants something different, it can call this 292function and set the type, size and possible device type to whatever 293it wants. 294This routine is independent of 295.Fn puffs_setroot . 296.It Fn puffs_getroot "pu" 297Returns the root node set earlier. 298.It Fn puffs_getspecific "pu" 299Returns the 300.Fa private 301argument of 302.Fn puffs_init . 303.It Fn puffs_setspecific "pu" "private" 304Can be used to set the specific data after the call to 305.Fn puffs_init . 306.It Fn puffs_setmaxreqlen "pu" "maxreqlen" 307In case the file system desires a maximum buffer length different from 308the default, the amount 309.Fa maxreqlen 310will be requested from the kernel when the file system is mounted. 311.Pp 312It is legal to call this function only between 313.Fn puffs_init 314and 315.Fn puffs_mount . 316.Pp 317.Em NOTE 318This does not currently work. 319.It Fn puffs_getmaxreqlen "pu" 320Returns the maximum request length the kernel will need for a single 321request. 322.Pp 323.Em NOTE 324This does not currently work. 325.It Fn puffs_setfhsize "pu" "fhsize" "flags" 326Sets the desired file handle size. 327This must be called if the file system wishes to support NFS exporting 328file systems of the 329.Fn fh* 330family of function calls. 331.Pp 332In case all nodes in the file system produce the same length file handle, 333it must be supplied as 334.Fa fhsize . 335In this case, the file system may ignore the length parameters in the 336file handle callback routines, as the kernel will always pass the 337correct length buffer. 338However, if the file handle size varies according to file, the argument 339.Fa fhsize 340defines the maximum size of a file handle for the file system. 341In this case the file system must take care of the handle lengths by 342itself in the file handle callbacks, see 343.Xr puffs_ops 3 344for more information. 345Also, the flag 346.Dv PUFFS_FHFLAG_DYNAMIC 347must be provided in the argument 348.Fa flags . 349.Pp 350In case the file system wants to sanity check its file handle lengths 351for the limits of NFS, it can supply 352.Dv PUFFS_FHFLAG_NFSV2 353and 354.Dv PUFFS_FHFLAG_NFSV3 355in the 356.Fa flags 357parameter. 358It is especially important to note that these are not directly the 359limits specified by the protocols, as the kernel uses some bytes from 360the buffer space. 361In case the file handles are too large, mount will return an error. 362.Pp 363It is legal to call this function only between 364.Fn puffs_init 365and 366.Fn puffs_mount . 367.It Fn puffs_setncookiehash "pu" "ncookiehash" 368The parameter 369.Fa ncookiehash 370controls the amount of hash buckets the kernel has for reverse lookups 371from cookie to vnode. 372Technically the default is enough, but a memory/time tradeoff can be 373made by increasing this for file systems which know they will have 374very many active files. 375.Pp 376It is legal to call this function only between 377.Fn puffs_init 378and 379.Fn puffs_mount . 380.El 381.Pp 382After the correct setup for the library has been established and the 383backend has been initialized the file system is made operational by calling 384.Fn puffs_mount . 385After this function returns the file system should start processing requests. 386.Bl -tag -width xxxx 387.It Fn puffs_mount pu dir mntflags root_cookie 388.Ar pu 389is the library context pointer from 390.Fn puffs_init . 391The argument 392.Fa dir 393signifies the mount point and 394.Fa mntflags 395is the flagset given to 396.Xr mount 2 . 397The value 398.Ar root_cookie 399will be used as the cookie for the file system root node. 400.El 401.Ss Using the built-in eventloop 402.Bl -tag -width xxxx 403.It Fn puffs_ml_loop_fn pu 404Loop function signature. 405.It Fn puffs_ml_setloopfn pu lfn 406Set loop function to 407.Ar lfn . 408This function is called once each time the event loop loops. 409It is not a well-defined interval, but it can be made fairly regular 410by setting the loop timeout by 411.Fn puffs_ml_settimeout . 412.It Fn puffs_ml_settimeout pu ts 413Sets the loop timeout to 414.Ar ts 415or disables it if 416.Ar ts 417is 418.Dv NULL . 419This can be used to roughly control how often the loop callback 420.Fn lfn 421is called 422.It Fn puffs_daemon pu nochdir noclose 423Detach from the console like 424.Fn daemon 3 . 425This call synchronizes with 426.Fn puffs_mount 427and the foreground process does not exit before the file system mount 428call has returned from the kernel. 429Since this routine internally calls fork, it has to be called 430.Em before 431.Fn puffs_mount . 432.It Fn puffs_mainloop pu flags 433Handle all requests automatically until the file system is unmounted. 434It returns 0 if the file system was successfully unmounted or \-1 if it 435was killed in action. 436.Pp 437In case 438.Xr puffs_framebuf 3 439has been initialized, I/O from the relevant descriptors is processed 440automatically by the eventloop. 441.It Fn puffs_dispatch_create pu pb pccp 442.It Fn puffs_dispatch_exec pcc pbp 443In case the use of 444.Fn puffs_mainloop 445is not possible, requests may be dispatched manually. 446However, as this is less efficient than using the mainloop, 447it should never be the first preference. 448.Pp 449Calling 450.Fn puffs_dispatch_create 451creates a dispatch request. 452The argument 453.Ar pb 454should contains a valid request and upon success 455.Ar pccp 456will contain a valid request context. 457This context is passed to 458.Fn puffs_dispatch_exec 459to execute the request. 460If the request yielded before completing, the routine returns 0, 461otherwise 1. 462When the routine completes, 463.Ar pcc 464is made invalid and a pointer to the processed buffer is placed in 465.Ar pbp . 466It is the responsibility of the caller to send the response (if 467necessary) and destroy the buffer. 468.Pp 469See 470.Xr puffs_cc 3 471and 472.Xr puffs_framebuf 3 473for further information. 474.El 475.Ss Cookies 476Every file (regular file, directory, device node, ...) instance is 477attached to the kernel using a cookie. 478A cookie should uniquely map to a file during its lifetime. 479If file instances are kept in memory, a simple strategy is to use 480the virtual address of the structure describing the file. 481The cookie can be recycled when 482.Fn puffs_node_reclaim 483is called for a node. 484.Pp 485For some operations (such as building paths) the framework needs to map 486the cookie to the framework-level structure describing a file, 487.Vt struct puffs_node . 488It is advisable to simply use the 489.Vt struct puffs_node 490address as a cookie and store file system specific data in the private 491portion of 492.Vt struct puffs_node . 493The library assumes this by default. 494If it is not desirable, the file system implementation can call 495.Fn puffs_set_cookiemap 496to provide an alternative cookie-to-node mapping function. 497.Sh SEE ALSO 498.Xr mount 2 , 499.Xr puffs_cc 3 , 500.Xr puffs_cred 3 , 501.Xr puffs_flush 3 , 502.Xr puffs_framebuf 3 , 503.Xr puffs_node 3 , 504.Xr puffs_ops 3 , 505.Xr puffs_path 3 , 506.Xr puffs_suspend 3 , 507.Xr refuse 3 , 508.Xr puffs 4 509.Rs 510.%A Antti Kantee 511.%D March 2007 512.%J Proceedings of AsiaBSDCon 2007 513.%P pp. 29-42 514.%T puffs - Pass-to-Userspace Framework File System 515.Re 516.Rs 517.%A Antti Kantee 518.%D September 2007 519.%I Helsinki University of Technology 520.%R Tech Report TKK-TKO-B157 521.%T Using puffs for Implementing Client-Server Distributed File Systems 522.Re 523.Rs 524.%A Antti Kantee 525.%A Alistair Crooks 526.%D September 2007 527.%J EuroBSDCon 2007 528.%T ReFUSE: Userspace FUSE Reimplementation Using puffs 529.Re 530.Rs 531.%A Antti Kantee 532.%D March 2008 533.%J Proceedings of AsiaBSDCon 2008 534.%P pp. 55-70 535.%T Send and Receive of File System Protocols: Userspace Approach With puffs 536.Re 537.Sh HISTORY 538An unsupported experimental version of 539.Nm 540first appeared in 541.Nx 4.0 . 542A stable version appeared in 543.Nx 5.0 . 544.Sh AUTHORS 545.An Antti Kantee Aq pooka@iki.fi 546