IMPORTANT NOTE! This document describes interfaces which are not yet guaranteed to be stable. In case you update your system sources, please recompile everything and fix compilation errors. If your sources are out-of-sync, incorrect operation may result.
puffs
provides a framework for creating file systems as userspace servers.
The in-kernel VFS attachment is controlled through a special device
node,
/dev/puffs
.
This document describes the operations on the device.
People looking to implement file systems should prefer using the
system through the convenience library described in
puffs(3).
Users wanting to access the device node directly should include
the header
sys/fs/puffs/puffs_msgif.h
for relevant definitions.
struct puffs_args {
int pa_vers;
int pa_fd;
unsigned int pa_flags;
size_t pa_maxreqlen;
char pa_name[PUFFSNAMESIZE];
uint8_t pa_vnopmask[PUFFS_VN_MAX];
};
The member pa_vers is currently always 0 and ignored. The pa_fd member is the file descriptor number from opening the device node. pa_flags controls some operations specific to puffs:
PUFFS_KFLAG_ALLOWCTL
PUFFS_KFLAG_NOCACHE
PUFFS_KFLAG_ALLOPS
The
pa_maxreqlen
member signifies the length of the incoming data buffer in userspace.
A good value is
PUFFS_REQ_MAXSIZE
,
which is the maximum the kernel will use.
A minimum value is also enforced, so the value of this field should
be checked after the mount operation to determine the correct buffer
size.
During operation, in case request fetch is attempted with a buffer
too short, the error
E2BIG
will be returned.
The file system type is give in
pa_name.
It will always be prepended by "puffs:" by the kernel.
Finally, the array
pa_vnopmask
specifies which operations are supported by the file system server.
The array is indexed with
PUFFS_VN_FOO
and 0 means vnode operation
FOO
is unimplemented while non-zero means an implemented operation.
This array is ignored if
PUFFS_KFLAG_ALLOPS
is given.
After a successful mount system call, the the ioctl
PUFFSSTARTOP
must be issued through the open device node.
The parameter for this ioctl is the following structure:
struct puffs_startreq {
void *psr_cookie;
struct statvfs psr_sb;
};
The member psr_cookie should be set before calling. This signals the cookie value of the root node of the file system (see puffs(3) for more details on cookie strategies). The value of psr_sb should be filled with the same results as for a regular statvfs call. After successfully executing this operation the file system is active.
PUFFSGETOP
,
processed, and the results pushed back to the kernel using
PUFFSPUTOP
.
Normally the system will block until an event is available for
PUFFSGETOP
,
but it is possible to set the file descriptor into non-blocking
mode, in which case
EWOULDBLOCK
is returned if no event is available.
Asynchronous I/O calls (i.e.,
select(2),
poll(2),
and
kevent(2))
can be issued to be notified of events.
As the argument both get and push use the following structure:
struct puffs_req {
uint64_t preq_id;
uint8_t preq_opclass;
uint8_t preq_optype;
void *preq_cookie;
int preq_rv;
void *preq_aux;
size_t preq_auxlen;
};
The member
preq_id
is used as an identifier in the reply.
It should not be modified during the processing of a
PUFFSGETOP
-
PUFFSPUTOP
sequence.
The members
preq_opclass
and
preq_optype
identify the request; they also are used for typing the data
pointed to by
preq_aux.
Currently the mapping between these two is only documented in
code in
src/lib/libpuffs/puff.c:puffcall()
.
The handling of this will very likely change in the future towards
a more automatic direction.
The length of the buffer given to
PUFFSGETOP
is described by
preq_auxlen
and will be modified by the kernel to indicate how much data
actually was transmitted.
This is for the benefit of calls such as write, which transmit a
variable amount of data.
Similarly, the user server should fill in the amount of data the
kernel must copy for
PUFFSPUTOP
;
most of the time this will be constant for a given operation, but
operations such as read want to adjust it dynamically.
Finally,
preq_rv
is used by the userspace server to fill in the success value of the
operation in question.
In case the macro
PUFFSOP_WANTREPLY()
returns false for
preq_opclass,
a return value is not wanted and
PUFFSPUTOP
should not be issued.
Additionally, an operation of type
PUFFSSIZEOP
is supported, but it is only used by the ioctl and fcntl operations
and will likely go away in the future.
It is not described here.