DragonFly On-Line Manual Pages
PUFFS(3) DragonFly Library Functions Manual PUFFS(3)
NAME
puffs -- Pass-to-Userspace Framework File System development interface
LIBRARY
puffs Convenience Library (libpuffs, -lpuffs)
SYNOPSIS
#include <puffs.h>
struct puffs_usermount *
puffs_init(struct puffs_ops *pops, const char *mntfromname,
const char *puffsname, void *private, uint32_t flags);
int
puffs_mount(struct puffs_usermount *pu, const char *dir, int mntflags,
puffs_cookie_t root_cookie);
int
puffs_getselectable(struct puffs_usermount *pu);
int
puffs_setblockingmode(struct puffs_usermount *pu, int mode);
int
puffs_getstate(struct puffs_usermount *pu);
int
puffs_setstacksize(struct puffs_usermount *pu, size_t stacksize);
void
puffs_setroot(struct puffs_usermount *pu, struct puffs_node *node);
void
puffs_setrootinfo(struct puffs_usermount *pu, enum vtype vt,
vsize_t vsize, dev_t rdev);
struct puffs_node *
puffs_getroot(struct puffs_usermount *pu);
void *
puffs_getspecific(struct puffs_usermount *pu);
void
puffs_setspecific(struct puffs_usermount *pu, void *private);
void
puffs_setmaxreqlen(struct puffs_usermount *pu, size_t maxreqlen);
size_t
puffs_getmaxreqlen(struct puffs_usermount *pu);
void
puffs_setfhsize(struct puffs_usermount *pu, size_t fhsize, int flags);
void
puffs_setncookiehash(struct puffs_usermount *pu, int nhashes);
void
puffs_ml_loop_fn(struct puffs_usermount *pu);
void
puffs_ml_setloopfn(struct puffs_usermount *pu, puffs_ml_loop_fn lfn);
void
puffs_ml_settimeout(struct puffs_usermount *pu, struct timespec *ts);
int
puffs_daemon(struct puffs_usermount *pu, int nochdir, int noclose);
int
puffs_mainloop(struct puffs_usermount *pu);
int
puffs_unmountonsignal(int sig, bool ignoresig);
int
puffs_dispatch_create(struct puffs_usermount *pu,
struct puffs_framebuf *pb, struct puffs_cc **pccp);
int
puffs_dispatch_exec(struct puffs_cc *pcc, struct puffs_framebuf **pbp);
DESCRIPTION
puffs provides a framework for creating file systems as userspace
servers. Operations are transported from the kernel virtual file system
layer to the concrete implementation behind puffs, where they are pro-
cessed and results are sent back to the kernel.
It is possible to use puffs in two different ways. Calling
puffs_mainloop() takes execution context away from the caller and auto-
matically handles all requests by using the callbacks. By using
puffs_framebuf(3) in conjunction with puffs_mainloop(), it is possible to
handle I/O to and from file descriptors. This is suited e.g. for dis-
tributed file servers.
Library operation
Operations on the library always require a pointer to the opaque context
identifier, struct puffs_usermount. It is obtained by calling
puffs_init().
puffs operates using operation callbacks. They can be initialized using
the macro PUFFSOP_SET(pops, fsname, type, opname), which will initialize
the operation puffs_type_opname() in pops to fsname_type_opname(). All
operations are initialized to a default state with the call
PUFFSOP_INIT(pops). All of the VFS routines are mandatory, but all of
the node operations with the exception of puffs_node_lookup() are
optional. However, leaving operations blank will naturally have an
effect on the features available from the file system implementation.
puffs_init(pops, mntfromname, puffsname, private, flags)
Initializes the library context. pops specifies the callback oper-
ations vector. mntfromname is device the file system is mounted
from. This can be for example a block device such as /dev/wd0a or,
if the file system is pseudo file system, the puffs device name can
be given by _PATH_PUFFS. This value is used for example in the
first column of the output of mount(8) and df(1). puffsname is the
file system type. It will always be prepended with the string
"puffs|". If possible, file server binaries should be named using
the format "mount_myfsnamehere" and this value should equal "myfs-
namehere". A file system specific context pointer can optionally
be given in private. This can be retrieved by puffs_getspecific().
Flags for puffs can be given via pflags. Currently the following
flags are supported:
PUFFS_KFLAG_NOCACHE_NAME Do not enter pathname components
into the name cache. This means
that every time the kernel does a
lookup for a componentname, the file
server will be consulted.
PUFFS_KFLAG_NOCACHE_PAGE Do not use the page cache. This
means that all reads and writes to
regular file are propagated to the
file server for handling. This
option makes a difference only for
regular files.
PUFFS_KFLAG_NOCACHE An alias for both
PUFFS_KFLAG_NOCACHE_NAME and
PUFFS_KFLAG_NOCACHE_PAGE.
PUFFS_KFLAG_ALLOPS This flag requests that all opera-
tions are sent to userspace. Nor-
mally the kernel shortcircuits unim-
plemented operations. This flag is
mostly useful for debugging pur-
poses.
PUFFS_KFLAG_WTCACHE Set the file system cache behavior
as write-through. This means that
all writes are immediately issued to
the file server instead of being
flushed in file system sync. This
is useful especially for distributed
file systems.
PUFFS_KFLAG_IAONDEMAND Issue inactive only on demand. If a
file server defines the inactive
method, call it only if the file
server has explicitly requested that
inactive be called for the node in
question. Once inactive has been
called for a node, it will not be
called again unless the request to
call inactive is reissued by the
file server. See puffs_setback() in
puffs_ops(3) for more information.
PUFFS_KFLAG_LOOKUP_FULLPNBUF This flag affects only the parameter
pcn to puffs_node_lookup(). If this
flag is not given, only the next
pathname component under lookup is
found from pcn->pcn_name. If this
flag is given, the full path the
kernel was asked to resolve can be
found from there.
PUFFS_FLAG_BUILDPATH The framework will build a complete
path name, which is supplied with
each operation and can be found from
the pn_po.po_full_pcn field in a
struct puffs_node. The option
assumes that the framework can map a
cookie to a struct puffs_node. See
Cookies for more information on
cookie mapping. See puffs_path(3)
for more information on library
calls involving paths.
PUFFS_FLAG_HASHPATH Calculate a hash of the path into
the path object field po_hash. This
hash value is used by
puffs_path_walkcmp() to avoid doing
a full comparison for every path
equal in length to the one searched
for. Especially if the file system
uses the abovementioned function, it
is a good idea to define this flag.
PUFFS_FLAG_OPDUMP This option makes the framework dump
a textual representation of each
operation before executing it. It
is useful for debugging purposes.
The following functions can be used to query or modify the global state
of the file system. Note, that all calls are not available at all times.
puffs_getselectable(pu)
Returns a handle to do I/O multiplexing with: select(2), poll(2),
and kqueue(2) are all examples of acceptable operations.
puffs_setblockingmode(pu, mode)
Sets the file system upstream access to blocking or non-blocking
mode. Acceptable values for the argument are PUFFSDEV_BLOCK and
PUFFSDEV_NONBLOCK.
This routine can be called only after calling puffs_mount().
puffs_getstate(pu)
Returns the state of the file system. It is maintained by the
framework and is mostly useful for the framework itself. Possible
values are PUFFS_STATE_BEFOREMOUNT, PUFFS_STATE_RUNNING,
PUFFS_STATE_UNMOUNTING and PUFFS_STATE_UNMOUNTED.
puffs_setstacksize(pu, stacksize)
Sets the stack size used when running callbacks. The default is
PUFFS_STACKSIZE_DEFAULT bytes of stack space per request. The min-
imum stacksize is architecture-dependent and can be specified by
using the opaque constant PUFFS_STACKSIZE_MIN.
puffs_setroot(pu, node)
Sets the root node of mount pu to node. Setting the root node is
currently required only if the path framework is used, see
puffs_path(3).
puffs_setrootinfo(pu, vt, vsize, rdev)
The default root node is a directory. In case the file system
wants something different, it can call this function and set the
type, size and possible device type to whatever it wants. This
routine is independent of puffs_setroot().
puffs_getroot(pu)
Returns the root node set earlier.
puffs_getspecific(pu)
Returns the private argument of puffs_init().
puffs_setspecific(pu, private)
Can be used to set the specific data after the call to
puffs_init().
puffs_setmaxreqlen(pu, maxreqlen)
In case the file system desires a maximum buffer length different
from the default, the amount maxreqlen will be requested from the
kernel when the file system is mounted.
It is legal to call this function only between puffs_init() and
puffs_mount().
NOTE This does not currently work.
puffs_getmaxreqlen(pu)
Returns the maximum request length the kernel will need for a sin-
gle request.
NOTE This does not currently work.
puffs_setfhsize(pu, fhsize, flags)
Sets the desired file handle size. This must be called if the file
system wishes to support NFS exporting file systems of the fh*()
family of function calls.
In case all nodes in the file system produce the same length file
handle, it must be supplied as fhsize. In this case, the file sys-
tem may ignore the length parameters in the file handle callback
routines, as the kernel will always pass the correct length buffer.
However, if the file handle size varies according to file, the
argument fhsize defines the maximum size of a file handle for the
file system. In this case the file system must take care of the
handle lengths by itself in the file handle callbacks, see
puffs_ops(3) for more information. Also, the flag
PUFFS_FHFLAG_DYNAMIC must be provided in the argument flags.
In case the file system wants to sanity check its file handle
lengths for the limits of NFS, it can supply PUFFS_FHFLAG_NFSV2 and
PUFFS_FHFLAG_NFSV3 in the flags parameter. It is especially impor-
tant to note that these are not directly the limits specified by
the protocols, as the kernel uses some bytes from the buffer space.
In case the file handles are too large, mount will return an error.
It is legal to call this function only between puffs_init() and
puffs_mount().
puffs_setncookiehash(pu, ncookiehash)
The parameter ncookiehash controls the amount of hash buckets the
kernel has for reverse lookups from cookie to vnode. Technically
the default is enough, but a memory/time tradeoff can be made by
increasing this for file systems which know they will have very
many active files.
It is legal to call this function only between puffs_init() and
puffs_mount().
After the correct setup for the library has been established and the
backend has been initialized the file system is made operational by call-
ing puffs_mount(). After this function returns the file system should
start processing requests.
puffs_mount(pu, dir, mntflags, root_cookie)
pu is the library context pointer from puffs_init(). The argument
dir signifies the mount point and mntflags is the flagset given to
mount(2). The value root_cookie will be used as the cookie for the
file system root node.
Using the built-in eventloop
puffs_ml_loop_fn(pu)
Loop function signature.
puffs_ml_setloopfn(pu, lfn)
Set loop function to lfn. This function is called once each time
the event loop loops. It is not a well-defined interval, but it
can be made fairly regular by setting the loop timeout by
puffs_ml_settimeout().
puffs_ml_settimeout(pu, ts)
Sets the loop timeout to ts or disables it if ts is NULL. This can
be used to roughly control how often the loop callback lfn() is
called
puffs_daemon(pu, nochdir, noclose)
Detach from the console like daemon(3). This call synchronizes
with puffs_mount() and the foreground process does not exit before
the file system mount call has returned from the kernel. Since
this routine internally calls fork, it has to be called before
puffs_mount().
puffs_mainloop(pu, flags)
Handle all requests automatically until the file system is
unmounted. It returns 0 if the file system was successfully
unmounted or -1 if it was killed in action.
In case puffs_framebuf(3) has been initialized, I/O from the rele-
vant descriptors is processed automatically by the eventloop.
puffs_unmountonsignal(signum, ignoresig)
Cause all file servers within the process to initiate unmount upon
receipt of signal signum. This works only for servers which call
puffs_mainloop() and must be called before any server within the
process enters the mainloop. The process signal handler is still
called before starting the unmount procedure. The parameter
ignoresig is provided as a convenience and tells if to install a
signal handler to ignore sig so that the process will not e.g. ter-
minate based on the default action before the file system unmount
can be initiated.
puffs_dispatch_create(pu, pb, pccp)
puffs_dispatch_exec(pcc, pbp)
In case the use of puffs_mainloop() is not possible, requests may
be dispatched manually. However, as this is less efficient than
using the mainloop, it should never be the first preference.
Calling puffs_dispatch_create() creates a dispatch request. The
argument pb should contains a valid request and upon success pccp
will contain a valid request context. This context is passed to
puffs_dispatch_exec() to execute the request. If the request
yielded before completing, the routine returns 0, otherwise 1.
When the routine completes, pcc is made invalid and a pointer to
the processed buffer is placed in pbp. It is the responsibility of
the caller to send the response (if necessary) and destroy the buf-
fer.
See puffs_cc(3) and puffs_framebuf(3) for further information.
Cookies
Every file (regular file, directory, device node, ...) instance is
attached to the kernel using a cookie. A cookie should uniquely map to a
file during its lifetime. If file instances are kept in memory, a simple
strategy is to use the virtual address of the structure describing the
file. The cookie can be recycled when puffs_node_reclaim() is called for
a node.
For some operations (such as building paths) the framework needs to map
the cookie to the framework-level structure describing a file, struct
puffs_node. It is advisable to simply use the struct puffs_node address
as a cookie and store file system specific data in the private portion of
struct puffs_node. The library assumes this by default.
SEE ALSO
mount(2), puffs_cc(3), puffs_cred(3), puffs_flush(3), puffs_framebuf(3),
puffs_node(3), puffs_ops(3), puffs_path(3), refuse(3), puffs(4)
Antti Kantee, "puffs - Pass-to-Userspace Framework File System",
Proceedings of AsiaBSDCon 2007, pp. 29-42, March 2007.
Antti Kantee, Using puffs for Implementing Client-Server Distributed File
Systems, Helsinki University of Technology, Tech Report TKK-TKO-B157,
September 2007.
Antti Kantee and Alistair Crooks, "ReFUSE: Userspace FUSE
Reimplementation Using puffs", EuroBSDCon 2007, September 2007.
Antti Kantee, "Send and Receive of File System Protocols: Userspace
Approach With puffs", Proceedings of AsiaBSDCon 2008, pp. 55-70, March
2008.
HISTORY
An unsupported experimental version of puffs first appeared in
NetBSD 4.0. A stable version appeared in NetBSD 5.0.
AUTHORS
Antti Kantee <pooka@iki.fi>
DragonFly 5.5 February 5, 2012 DragonFly 5.5