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