Move file system and node callbacks into their own manual page.

Improve markup and descriptions a bit (not completely finished yet).
This commit is contained in:
pooka 2007-04-16 19:16:02 +00:00
parent 8aefa8aa0c
commit aaf5af07be
3 changed files with 463 additions and 351 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.14 2007/03/22 17:38:09 pooka Exp $
# $NetBSD: Makefile,v 1.15 2007/04/16 19:16:02 pooka Exp $
#
.include <bsd.own.mk>
@ -9,7 +9,8 @@ LIB= puffs
SRCS= puffs.c callcontext.c creds.c flush.c null.c opdump.c \
paths.c pnode.c requests.c subr.c suspend.c
MAN= puffs.3 puffs_cc.3 puffs_cred.3 puffs_flush.3 \
puffs_node.3 puffs_path.3 puffs_req.3 puffs_suspend.3
puffs_node.3 puffs_ops.3 puffs_path.3 puffs_req.3 \
puffs_suspend.3
INCS= puffs.h puffsdump.h
INCSDIR= /usr/include
LINTFLAGS+=-S -w

View File

@ -1,4 +1,4 @@
.\" $NetBSD: puffs.3,v 1.18 2007/04/16 16:37:02 pooka Exp $
.\" $NetBSD: puffs.3,v 1.19 2007/04/16 19:16:02 pooka Exp $
.\"
.\" Copyright (c) 2006, 2007 Antti Kantee. All rights reserved.
.\"
@ -74,116 +74,6 @@
.Fn puffs_setfhsize "struct puffs_usermount *pu" "size_t fhsize" "int flags"
.Ft void
.Fn puffs_setncookiehash "struct puffs_usermount *pu" "int nhashes"
.Ft int
.Fn puffs_fs_unmount "struct puffs_cc *pcc" "int flags" "pid_t pid"
.Ft int
.Fo puffs_fs_statvfs
.Fa "struct puffs_cc *pcc" "struct statvfs *sbp" "pid_t pid"
.Fc
.Ft int
.Fo puffs_fs_sync
.Fa "struct puffs_cc *pcc" "int waitfor" "const struct puffs_cred *cred"
.Fa "pid_t pid"
.Fc
.Ft int
.Fo puffs_node_lookup
.Fa "struct puffs_cc *pcc" "void *opc" "void **newnode"
.Fa "enum vtype *newtype" "voff_t *newsize" "dev_t *newrdev"
.Fa "const struct puffs_cn *pcn"
.Fc
.Ft int
.Fo puffs_node_getattr
.Fa "struct puffs_cc *pcc" "void *opc" "struct vattr *va"
.Fa "const struct puffs_cred *pcr" "pid_t pid"
.Fc
.Ft int
.Fo puffs_node_setattr
.Fa "struct puffs_cc *pcc" "void *opc" "const struct vattr *va"
.Fa "const struct puffs_cred *pcr" "pid_t pid"
.Fc
.Ft int
.Fo puffs_node_create
.Fa "struct puffs_cc *pcc" "void *opc" "void **newnode"
.Fa "const struct puffs_cn *pcn" "const struct vattr *va"
.Fc
.Ft int
.Fo puffs_node_remove
.Fa "struct puffs_cc *pcc" "void *opc" "void *targ"
.Fa "const struct puffs_cn *pcn"
.Fc
.Ft int
.Fo puffs_node_mkdir
.Fa "struct puffs_cc *pcc" "void *opc" "void **newnode"
.Fa "const struct puffs_cn *pcn" "const struct vattr *va"
.Fc
.Ft int
.Fo puffs_node_rmdir
.Fa "struct puffs_cc *pcc" "void *opc" "void *targ"
.Fa "const struct puffs_cn *pcn"
.Fc
.Ft int
.Fo puffs_node_readdir
.Fa "struct puffs_cc *pcc" "void *opc" "struct dirent *dent"
.Fa "const struct puffs_cred *pcr" "off_t *readoff" "size_t *reslen"
.Fc
.Ft int
.Fo puffs_node_rename
.Fa "struct puffs_cc *pcc" "void *opc" "void *src"
.Fa "const struct puffs_cn *pcn_src" "void *targ_dir" "void *targ"
.Fa "const struct puffs_cn *pcn_targ"
.Fc
.Ft int
.Fo puffs_node_link
.Fa "struct puffs_cc *pcc" "void *opc" "void *targ"
.Fa "const struct puffs_cn *pcn"
.Fc
.Ft int
.Fo puffs_node_symlink
.Fa "struct puffs_cc *pcc" "void *opc" "void **newnode"
.Fa "const struct puffs_cn *pcn_src" "const struct vattr *va"
.Fa "const char *link_target"
.Fc
.Ft int
.Fo puffs_node_readlink
.Fa "struct puffs_cc *pcc" "void *opc" "const struct puffs_cred *cred"
.Fa "char *link" "size_t *linklen"
.Fc
.Ft int
.Fo puffs_node_mknod
.Fa "struct puffs_cc *pcc" "void *opc" "void **newnode"
.Fa "const struct puffs_cn *pcn" "const struct vattr *va"
.Fc
.Ft int
.Fo puffs_node_open
.Fa "struct puffs_cc *pcc" "void *opc" "int flags"
.Fa "const struct puffs_cred *pcr" "pid_t pid"
.Fc
.Ft int
.Fo puffs_node_close
.Fa "struct puffs_cc *pcc" "void *opc" "int flags"
.Fa "const struct puffs_cred *pcr" "pid_t pid"
.Fc
.Ft int
.Fo puffs_node_access
.Fa "struct puffs_cc *pcc" "void *opc" "int mode"
.Fa "const struct puffs_cred *pcr" "pid_t pid"
.Fc
.Ft int
.Fo puffs_node_read
.Fa "struct puffs_cc *pcc" "void *opc" "uint8_t *buf"
.Fa "off_t offset" "size_t *resid" "const struct puffs_cred *pcr" "int ioflag"
.Fc
.Ft int
.Fo puffs_node_write
.Fa "struct puffs_cc *pcc" "void *opc" "uint8_t *buf"
.Fa "off_t offset" "size_t *resid" "const struct puffs_cred *pcr" "int ioflag"
.Fc
.Ft int
.Fn puffs_node_reclaim "struct puffs_cc *pcc" "void *opc" "pid_t pid"
.Ft int
.Fo puffs_node_inactive
.Fa "struct puffs_cc *pcc" "void *opc" "pid_t pid" "int *refcount"
.Fc
.Sh DESCRIPTION
.Em IMPORTANT NOTE!
This document describes interfaces which are not yet guaranteed to be
@ -379,7 +269,9 @@ However, if the file handle size varies according to file, the argument
.Fa 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.
itself in the file handle callbacks, see
.Xr puffs_ops 3
for more information.
Also, the flag
.Dv PUFFS_FHFLAG_DYNAMIC
must be provided in the argument
@ -461,248 +353,12 @@ The library assumes this by default.
If it is not desireable, the file system implementation can call
.Fn puffs_set_cookiemap
to provide an alternative cookie-to-node mapping function.
.Ss File system callbacks
The callbacks do all the actual work in implementing the file system.
Currently they are fairly close to the vfs and vnode operations in
the kernel but with simplified operation.
This section describes the calls which relate to the file system
itself.
.Pp
All callbacks can be prototyped with the file system name and operation
name using the macro
.Fn PUFFSOP_PROTOS fsname .
.Pp
.Fn puffs_fs_statvfs
should fill in the following fields of
.Fa sbp :
.Bd -literal
* unsigned long f_bsize; file system block size
* unsigned long f_frsize; fundamental file system block size
* fsblkcnt_t f_blocks; number of blocks in file system,
* (in units of f_frsize)
*
* fsblkcnt_t f_bfree; free blocks avail in file system
* fsblkcnt_t f_bavail; free blocks avail to non-root
* fsblkcnt_t f_bresvd; blocks reserved for root
*
* fsfilcnt_t f_files; total file nodes in file system
* fsfilcnt_t f_ffree; free file nodes in file system
* fsfilcnt_t f_favail; free file nodes avail to non-root
* fsfilcnt_t f_fresvd; file nodes reserved for root
.Ed
The process requiring this information is given by
.Fa pid .
.Pp
The file system should be sychronized to storage when
.Fn puffs_fs_sync
is called.
The
.Fa waitfor
parameter should handled similarly as inside the kernel.
.Pp
The file system should be unmounted when
.Fn puffs_fs_unmount
is called.
If the flag
.Dv MNT_FORCE
is not honored, the kernel will proceed to forcibly unmount the file system
despite this.
.Ss Node callbacks
These operations operate in the level of individual files.
The file cookie is always provided as the second argument
.Fa opc .
If the operation is for a file, it will be the cookie of the file.
The case the operation involves a directory (such as
.Dq create file in directory ) ,
the cookie will be for the directory.
Some operations take additional cookies to describe the rest of
the operands.
The return value 0 signals success, else an appropriate errno value
should be returned.
Please note that neither this list nor the descriptions are complete.
.Pp
The
.Fn puffs_node_lookup
function is used to locate nodes.
The implementation should match the name in
.Fa pcn
against the existing entries in the directory provided by the cookie.
If found, the cookie for the located node should be returned in
.Fa newnode .
Additionally, the type and size (latter applicable to regular files only)
should be returned in
.Fa newtype
and
.Fa newsize ,
respectively.
If the located entry is a block device or character device file,
the dev_t for the entry should be returned in
.Fa newrdev .
Otherwise, 0 signals a found node and a nonzero value signals an errno.
As a special case,
.Er ENOENT
signals success for cases where the lookup operation is
.Dv PUFFSLOOKUP_CREATE
or
.Dv PUFFSLOOKUP_RENAME .
Failure in these cases can be signalled by returning another appropriate
error code, for example
.Er EACCESS .
.Pp
.Fn puffs_node_getattr
fills out a struct vattr pointed to by
.Fa va .
.Pp
.Fn puffs_node_setattr
sets the attributes in
.Fa va .
Instead of setting everything according to that file, only fields which
are not marked
.Dv VNOVAL
should be set.
.Pp
A file node is created in the directory specified by the cookie when
.Fn puffs_node_create
is called.
The attributes are specified by
.Fa va
and the cookie for the newly created node should be returned in
.Fa newnode .
Similarly,
.Fn puffs_node_mkdir
creates a directory.
.Pp
.Fn puffs_node_remove
removes the file
.Fa targ
from the directory indicated by the cookie.
Similarly,
.Fn puffs_node_rmdir
removes a directory.
The name of the directory entry to remove is described by
.Fa pcn .
.Pp
To read directory entries,
.Fn puffs_node_readdir
is called.
It should store directories as struct dirents in the space pointed to by
.Fa dent .
The amount of space available is given by
.Fa reslen
and before returning it should be set to the amount of space
.Em remaining
in the buffer.
The argument
.Fa offset
is used to specify the offset to the directory.
Its intepretation is up to the file systme and it should be set to
signal the continuation point when there is no more room for the next
entry in
.Fa dent .
It is most performant to return the maximal amount of directory
entries each call.
In case the directory was exhausted, the parameters should not be
modified to signal end-of-directory.
.Pp
A node rename is done by calling
.Fn puffs_node_rename .
If the destination file cookie is non-null, it must be removed
and the new entry overwritten atomically.
The directory entry names to be used are described by the
struct puffs_cn's (cf. create and remove).
.Pp
A hard link is created by
.Fn puffs_node_link .
In practice this means adding a directory entry described by
.Fa pcn
to the cookied directory and the entry pointing to the target node.
.Pp
A symbolic link in turn is created by
.Fn puffs_node_symlink .
It is similar to creating a regular file, except that
.Fa link_target
specifies the target of the link which should be set for the link.
.Pp
To read the target of a symbolic link,
.Fa puffs_node_readlink
is called.
The path in the link target should be copied to
.Fa link
and the length without the terminating nul set in
.Fa linklen .
.Pp
A device node is created using
.Fn puffs_node_mknod .
The only difference to creating a normal file is that the attribute
struct contains the device identifier in
.Fa va-\*[Gt]va_rdev .
.Pp
Files are opened with a call to
.Fn puffs_node_open .
Most of the time this can be left unimplemented, unless special
resource allocation is required.
.Pp
.Fn puffs_node_close
releases all the resources allocated by
.Fn puffs_node_open .
.Pp
To check if access of type
.Va mode
to a file is allowed,
.Fn puffs_node_access
is called.
This controls file access, not e.g.
.Fn puffs_node_open .
.Pp
.Fn puffs_node_read
reads the contents of a file.
It will gather the data from
.Fa offset
in the file and read the number
.Fa resid
octets.
The buffer is guaranteed to have this much space.
The amount of data requested by
.Fa resid
should be read, except in the case of eof-of-file or an error.
The parameter
.Fa resid
should be set to indicate the amount of request NOT completed.
In the normal case this should be 0.
.Pp
.Fn puffs_node_write
writes data to a file at
.Fa offset
extending the file if necessary.
The number of octets written is indicated by
.Fa resid ;
everything must be written or an error will be generated.
The parameter must be set to indicate the amount of data NOT written.
In case the flag
.Dv PUFFS_IO_APPEND
is specified, the data should be appended to the end of the file.
.Pp
.Fn puffs_node_reclaim
signals that the cookie will no longer be referenced without a further
call to
.Fn puffs_node_lookup .
This information can be used to free resources and specifically release
a file for which no directory entries remain.
.Pp
.Fn puffs_node_inactive
signals that the kernel has released its last reference to the node.
However, the cookie must still remain valid until
.Fn puffs_node_reclaim
is called.
The file system should return its internal reference count on the file
(usually number of links to the file) in
.Fa refcount .
If this is zero, the kernel will call reclaim immediately.
.Sh SEE ALSO
.Xr puffs_cc 3 ,
.Xr puffs_cred 3 ,
.Xr puffs_flush 3 ,
.Xr puffs_node 3 ,
.Xr puffs_ops 3 ,
.Xr puffs_path 3 ,
.Xr puffs_req 3 ,
.Xr puffs_suspend 3 ,

455
lib/libpuffs/puffs_ops.3 Normal file
View File

@ -0,0 +1,455 @@
.\" $NetBSD: puffs_ops.3,v 1.1 2007/04/16 19:16:02 pooka Exp $
.\"
.\" Copyright (c) 2007 Antti Kantee. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd April 16, 2007
.Dt PUFFS_OPS 3
.Os
.Sh NAME
.Nm puffs_ops
.Nd puffs callback operations
.Sh LIBRARY
.Lb libpuffs
.Sh SYNOPSIS
.In puffs.h
.Ft int
.Fo puffs_fs_statvfs
.Fa "struct puffs_cc *pcc" "struct statvfs *sbp" "pid_t pid"
.Fc
.Ft int
.Fo puffs_fs_sync
.Fa "struct puffs_cc *pcc" "int waitfor" "const struct puffs_cred *pcr"
.Fa "pid_t pid"
.Fc
.Ft int
.Fn puffs_fs_unmount "struct puffs_cc *pcc" "int flags" "pid_t pid"
.Ft int
.Fo puffs_node_lookup
.Fa "struct puffs_cc *pcc" "void *opc" "void **newnode"
.Fa "enum vtype *newtype" "voff_t *newsize" "dev_t *newrdev"
.Fa "const struct puffs_cn *pcn"
.Fc
.Ft int
.Fo puffs_node_getattr
.Fa "struct puffs_cc *pcc" "void *opc" "struct vattr *va"
.Fa "const struct puffs_cred *pcr" "pid_t pid"
.Fc
.Ft int
.Fo puffs_node_setattr
.Fa "struct puffs_cc *pcc" "void *opc" "const struct vattr *va"
.Fa "const struct puffs_cred *pcr" "pid_t pid"
.Fc
.Ft int
.Fo puffs_node_create
.Fa "struct puffs_cc *pcc" "void *opc" "void **newnode"
.Fa "const struct puffs_cn *pcn" "const struct vattr *va"
.Fc
.Ft int
.Fo puffs_node_remove
.Fa "struct puffs_cc *pcc" "void *opc" "void *targ"
.Fa "const struct puffs_cn *pcn"
.Fc
.Ft int
.Fo puffs_node_mkdir
.Fa "struct puffs_cc *pcc" "void *opc" "void **newnode"
.Fa "const struct puffs_cn *pcn" "const struct vattr *va"
.Fc
.Ft int
.Fo puffs_node_rmdir
.Fa "struct puffs_cc *pcc" "void *opc" "void *targ"
.Fa "const struct puffs_cn *pcn"
.Fc
.Ft int
.Fo puffs_node_readdir
.Fa "struct puffs_cc *pcc" "void *opc" "struct dirent *dent"
.Fa "const struct puffs_cred *pcr" "off_t *readoff" "size_t *reslen"
.Fc
.Ft int
.Fo puffs_node_rename
.Fa "struct puffs_cc *pcc" "void *opc" "void *src"
.Fa "const struct puffs_cn *pcn_src" "void *targ_dir" "void *targ"
.Fa "const struct puffs_cn *pcn_targ"
.Fc
.Ft int
.Fo puffs_node_link
.Fa "struct puffs_cc *pcc" "void *opc" "void *targ"
.Fa "const struct puffs_cn *pcn"
.Fc
.Ft int
.Fo puffs_node_symlink
.Fa "struct puffs_cc *pcc" "void *opc" "void **newnode"
.Fa "const struct puffs_cn *pcn_src" "const struct vattr *va"
.Fa "const char *link_target"
.Fc
.Ft int
.Fo puffs_node_readlink
.Fa "struct puffs_cc *pcc" "void *opc" "const struct puffs_cred *pcr"
.Fa "char *link" "size_t *linklen"
.Fc
.Ft int
.Fo puffs_node_mknod
.Fa "struct puffs_cc *pcc" "void *opc" "void **newnode"
.Fa "const struct puffs_cn *pcn" "const struct vattr *va"
.Fc
.Ft int
.Fo puffs_node_open
.Fa "struct puffs_cc *pcc" "void *opc" "int flags"
.Fa "const struct puffs_cred *pcr" "pid_t pid"
.Fc
.Ft int
.Fo puffs_node_close
.Fa "struct puffs_cc *pcc" "void *opc" "int flags"
.Fa "const struct puffs_cred *pcr" "pid_t pid"
.Fc
.Ft int
.Fo puffs_node_access
.Fa "struct puffs_cc *pcc" "void *opc" "int mode"
.Fa "const struct puffs_cred *pcr" "pid_t pid"
.Fc
.Ft int
.Fo puffs_node_read
.Fa "struct puffs_cc *pcc" "void *opc" "uint8_t *buf"
.Fa "off_t offset" "size_t *resid" "const struct puffs_cred *pcr" "int ioflag"
.Fc
.Ft int
.Fo puffs_node_write
.Fa "struct puffs_cc *pcc" "void *opc" "uint8_t *buf"
.Fa "off_t offset" "size_t *resid" "const struct puffs_cred *pcr" "int ioflag"
.Fc
.Ft int
.Fn puffs_node_reclaim "struct puffs_cc *pcc" "void *opc" "pid_t pid"
.Ft int
.Fo puffs_node_inactive
.Fa "struct puffs_cc *pcc" "void *opc" "pid_t pid" "int *refcount"
.Fc
.Sh DESCRIPTION
.Em 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 complation errors.
If your sources are out-of-sync, incorrect operation may result.
The interfaces in this document will most likely be hugely simplified
in later versions or made transparent to the implementation.
.Pp
The operations
.Nm puffs
requires to function can be divided into two categories: file system
callbacks and node callbacks.
The former affect the entire file system while the latter are targeted
at a file or a directory and a file.
They are roughly equivalent to the vfs and vnode operations in the
kernel.
.Pp
All callbacks can be prototyped with the file system name and operation
name using the macro
.Fn PUFFSOP_PROTOS fsname .
.Ss File system callbacks (puffs_fs)
.Bl -tag -width xxxx
.It Fn puffs_fs_statvfs "pcc" "sbp" "pid"
The following fields of the argument
.Fa sbp
need to be filled:
.Bd -literal
* unsigned long f_bsize; file system block size
* unsigned long f_frsize; fundamental file system block size
* fsblkcnt_t f_blocks; number of blocks in file system,
* (in units of f_frsize)
*
* fsblkcnt_t f_bfree; free blocks avail in file system
* fsblkcnt_t f_bavail; free blocks avail to non-root
* fsblkcnt_t f_bresvd; blocks reserved for root
* fsfilcnt_t f_files; total file nodes in file system
* fsfilcnt_t f_ffree; free file nodes in file system
* fsfilcnt_t f_favail; free file nodes avail to non-root
* fsfilcnt_t f_fresvd; file nodes reserved for root
.Ed
The process requiring this information is given by
.Fa pid .
.It Fn puffs_fs_sync "pcc" "waitfor" "pcr" "pid"
All the dirty buffers that have been cached at the file server
level including metadata should be committed to stable storage.
The
.Fa waitfor
parameter affects the operation.
Possible values are:
.Bl -tag -width XMNT_NOWAITX
.It Dv MNT_WAIT
Wait for all I/O for complete until returning.
.It Dv MNT_NOWAIT
Initiate I/O, but do not wait for completion.
.It Dv MNT_LAZY
Synchorize data not synchoronized by the file system syncer,
i.e. data not written when
.Fn node_fsync
is called with
.Dv FSYNC_LAZY .
.El
.Pp
The credentials for the initiator of the sync operation are present in
.Fa pcr
and will usually be either file system or kernel credentials, but might
also be user credentials.
However, most of the time it is advisable to sync regardless of the
credentials of the caller.
.It Fn puffs_fs_unmount "pcc" "flags" "pid"
Unmount the file system.
The kernel has assumedly flushed all cached data when this callback
is executed.
If the file system cannot currently be safely be unmounted, for whatever
reason, the kernel will honor an error value and not forcibly unmount.
However, if the flag
.Dv MNT_FORCE
is not honored by the file server, the kernel will forcibly unmount
the file system.
.El
.Ss Node callbacks
These operations operate in the level of individual files.
The file cookie is always provided as the second argument
.Fa opc .
If the operation is for a file, it will be the cookie of the file.
The case the operation involves a directory (such as
.Dq create file in directory ) ,
the cookie will be for the directory.
Some operations take additional cookies to describe the rest of
the operands.
The return value 0 signals success, else an appropriate errno value
should be returned.
Please note that neither this list nor the descriptions are complete.
.Bl -tag -width xxxx
.It Fn puffs_node_lookup "pcc" "opc" "newnode" "newtype" "newsize" "newrdev" "pcn"
This function is used to locate nodes, or in other words translate
pathname components to file system data structures.
The implementation should match the name in
.Fa pcn
against the existing entries in the directory provided by the cookie
.Fa opc .
If found, the cookie for the located node should be returned in
.Fa newnode .
Additionally, the type and size (latter applicable to regular files only)
should be returned in
.Fa newtype
and
.Fa newsize ,
respectively.
If the located entry is a block device or character device file,
the dev_t for the entry should be returned in
.Fa newrdev .
.Pp
The type of operation is found from
.Va pcn->pcn_nameiop :
.Bl -tag -width XPUFFSLOOKUP_LOOKUPX
.It Dv PUFFSLOOKUP_LOOKUP
Normal lookup operation.
.It Dv PUFFSLOOKUP_CREATE
Lookup to create a node.
.It Dv PUFFSLOOKUP_DELETE
Lookup for node deletion.
.It Dv PUFFSLOOKUP_RENAME
Lookup for the target of a rename operation (source will be looked
up using
.Dv PUFFSLOOKUP_DELETE ).
.El
.Pp
The final component from a pathname lookup usually requires special
treatment.
It can be identified by looking at the
.Va pcn->pcn_flags
fields for the flag
.Dv PUFFSLOOKUP_ISLASTCN .
For example, in most cases the lookup operation will want to check if
a delete, rename or create operation has enough credentials to perform
the operation.
.Pp
The return value 0 signals a found node and a nonzero value signals
an errno.
As a special case,
.Er ENOENT
signals "success" for cases where the lookup operation is
.Dv PUFFSLOOKUP_CREATE
or
.Dv PUFFSLOOKUP_RENAME .
Failure in these cases can be signalled by returning another appropriate
error code, for example
.Er EACCESS .
.It Fn puffs_node_getattr "pcc" "opc" "va" "pcr" "pid"
The attributes of the node specified by
.Fa opc
must be copied to the space pointed by
.Fa va .
.It Fn puffs_node_setattr "pcc" "opc" "va" "pcr" "pid"
The attributes for the node specified by
.Fa opc
must be set to those contained in
.Fa va .
Only fields of
.Fa va
which contain a value different from
.Dv PUFFS_VNOVAL
(typecast to the field's type!) contain a valid value.
.El
.Pp
A file node is created in the directory specified by the cookie when
.Fn puffs_node_create
is called.
The attributes are specified by
.Fa va
and the cookie for the newly created node should be returned in
.Fa newnode .
Similarly,
.Fn puffs_node_mkdir
creates a directory.
.Pp
.Fn puffs_node_remove
removes the file
.Fa targ
from the directory indicated by the cookie.
Similarly,
.Fn puffs_node_rmdir
removes a directory.
The name of the directory entry to remove is described by
.Fa pcn .
.Pp
To read directory entries,
.Fn puffs_node_readdir
is called.
It should store directories as struct dirents in the space pointed to by
.Fa dent .
The amount of space available is given by
.Fa reslen
and before returning it should be set to the amount of space
.Em remaining
in the buffer.
The argument
.Fa offset
is used to specify the offset to the directory.
Its intepretation is up to the file systme and it should be set to
signal the continuation point when there is no more room for the next
entry in
.Fa dent .
It is most performant to return the maximal amount of directory
entries each call.
In case the directory was exhausted, the parameters should not be
modified to signal end-of-directory.
.Pp
A node rename is done by calling
.Fn puffs_node_rename .
If the destination file cookie is non-null, it must be removed
and the new entry overwritten atomically.
The directory entry names to be used are described by the
struct puffs_cn's (cf. create and remove).
.Pp
A hard link is created by
.Fn puffs_node_link .
In practice this means adding a directory entry described by
.Fa pcn
to the cookied directory and the entry pointing to the target node.
.Pp
A symbolic link in turn is created by
.Fn puffs_node_symlink .
It is similar to creating a regular file, except that
.Fa link_target
specifies the target of the link which should be set for the link.
.Pp
To read the target of a symbolic link,
.Fa puffs_node_readlink
is called.
The path in the link target should be copied to
.Fa link
and the length without the terminating nul set in
.Fa linklen .
.Pp
A device node is created using
.Fn puffs_node_mknod .
The only difference to creating a normal file is that the attribute
struct contains the device identifier in
.Fa va-\*[Gt]va_rdev .
.Pp
Files are opened with a call to
.Fn puffs_node_open .
Most of the time this can be left unimplemented, unless special
resource allocation is required.
.Pp
.Fn puffs_node_close
releases all the resources allocated by
.Fn puffs_node_open .
.Pp
To check if access of type
.Va mode
to a file is allowed,
.Fn puffs_node_access
is called.
This controls file access, not e.g.
.Fn puffs_node_open .
.Pp
.Fn puffs_node_read
reads the contents of a file.
It will gather the data from
.Fa offset
in the file and read the number
.Fa resid
octets.
The buffer is guaranteed to have this much space.
The amount of data requested by
.Fa resid
should be read, except in the case of eof-of-file or an error.
The parameter
.Fa resid
should be set to indicate the amount of request NOT completed.
In the normal case this should be 0.
.Pp
.Fn puffs_node_write
writes data to a file at
.Fa offset
extending the file if necessary.
The number of octets written is indicated by
.Fa resid ;
everything must be written or an error will be generated.
The parameter must be set to indicate the amount of data NOT written.
In case the flag
.Dv PUFFS_IO_APPEND
is specified, the data should be appended to the end of the file.
.Pp
.Fn puffs_node_reclaim
signals that the cookie will no longer be referenced without a further
call to
.Fn puffs_node_lookup .
This information can be used to free resources and specifically release
a file for which no directory entries remain.
.Pp
.Fn puffs_node_inactive
signals that the kernel has released its last reference to the node.
However, the cookie must still remain valid until
.Fn puffs_node_reclaim
is called.
The file system should return its internal reference count on the file
(usually number of links to the file) in
.Fa refcount .
If this is zero, the kernel will call reclaim immediately.
.Sh SEE ALSO
.Xr puffs 3 ,
.Xr vfsops 9 ,
.Xr vnodeops 9