| PUFFS_OPS(3) | Library Functions Manual | PUFFS_OPS(3) |
puffs_ops — puffs
callback operations
puffs Convenience Library (libpuffs, -lpuffs)
#include
<puffs.h>
int
puffs_fs_statvfs(struct
puffs_usermount *pu, struct statvfs *sbp);
int
puffs_fs_sync(struct puffs_usermount
*pu, int waitfor, const struct
puffs_cred *pcr);
int
puffs_fs_fhtonode(struct
puffs_usermount *pu, void *fid,
size_t fidsize, struct puffs_newinfo
*pni);
int
puffs_fs_nodetofh(struct
puffs_usermount *pu, puffs_cookie_t cookie,
void *fid, size_t *fidsize);
int
puffs_fs_extattrctl(struct
puffs_usermount *pu, int cmd,
puffs_cookie_t cookie, int
flags, int attrnamespace, const
char *attrname);
int
puffs_fs_unmount(struct
puffs_usermount *pu, int flags);
int
puffs_node_lookup(struct
puffs_usermount *pu, puffs_cookie_t opc,
struct puffs_newinfo *pni, const
struct puffs_cn *pcn);
int
puffs_node_create(struct
puffs_usermount *pu, puffs_cookie_t opc,
struct puffs_newinfo *pni, const
struct puffs_cn *pcn, const struct vattr
*vap);
int
puffs_node_mknod(struct
puffs_usermount *pu, puffs_cookie_t opc,
struct puffs_newinfo *pni, const
struct puffs_cn *pcn, const struct vattr
*vap);
int
puffs_node_open(struct puffs_usermount
*pu, puffs_cookie_t opc, int
mode, const struct puffs_cred *pcr);
int
puffs_node_open2(struct
puffs_usermount *pu, puffs_cookie_t opc,
int modep, const struct puffs_cred
*pcr, int *oflags);
int
puffs_node_close(struct
puffs_usermount *pu, puffs_cookie_t opc,
int flags, const struct puffs_cred
*pcr);
int
puffs_node_access(struct
puffs_usermount *pu, puffs_cookie_t opc,
int mode, const struct puffs_cred
*pcr);
int
puffs_node_getattr(struct
puffs_usermount *pu, puffs_cookie_t opc,
struct vattr *vap, const struct
puffs_cred *pcr);
int
puffs_node_setattr(struct
puffs_usermount *pu, puffs_cookie_t opc,
const struct vattr *vap, const struct
puffs_cred *pcr);
int
puffs_node_getattr_ttl(struct
puffs_usermount *pu, puffs_cookie_t opc,
struct vattr *vap, const struct
puffs_cred *pcr, struct timespec *va_ttl);
int
puffs_node_setattr_ttl(struct
puffs_usermount *pu, puffs_cookie_t opc,
struct vattr *vap, const struct
puffs_cred *pcr, struct timespec *va_ttl,
int xflag);
int
puffs_node_pathconf(struct
puffs_usermount *pu, puffs_cookie_t opc,
int name, __register_t
*retval);
int
puffs_node_advlock(struct
puffs_usermount *pu, puffs_cookie_t opc,
void *id, int op,
struct flock *fl, int
flags);
int
puffs_node_poll(struct puffs_usermount
*pu, puffs_cookie_t opc, int
*events);
int
puffs_node_mmap(struct puffs_usermount
*pu, puffs_cookie_t opc, int
flags, const struct puffs_cred *pcr);
int
puffs_node_fsync(struct
puffs_usermount *pu, puffs_cookie_t opc,
const struct puffs_cred *pcr, int
flags, off_t offlo, off_t
offhi);
int
puffs_node_seek(struct puffs_usermount
*pu, puffs_cookie_t opc, off_t
oldoff, off_t newoff, const
struct puffs_cred *pcr);
int
puffs_node_remove(struct
puffs_usermount *pu, puffs_cookie_t opc,
puffs_cookie_t targ, const struct
puffs_cn *pcn);
int
puffs_node_link(struct puffs_usermount
*pu, puffs_cookie_t opc,
puffs_cookie_t targ, const struct
puffs_cn *pcn);
int
puffs_node_rename(struct
puffs_usermount *pu, puffs_cookie_t opc,
puffs_cookie_t src, const struct
puffs_cn *pcn_src, puffs_cookie_t targ_dir,
puffs_cookie_t targ, const struct
puffs_cn *pcn_targ);
int
puffs_node_mkdir(struct
puffs_usermount *pu, puffs_cookie_t opc,
struct puffs_newinfo *pni, const
struct puffs_cn *pcn, const struct vattr
*vap);
int
puffs_node_rmdir(struct
puffs_usermount *pu, puffs_cookie_t opc,
puffs_cookie_t targ, const struct
puffs_cn *pcn);
int
puffs_node_readdir(struct
puffs_usermount *pu, puffs_cookie_t opc,
struct dirent *dent, off_t
*readoff, size_t *reslen, const
struct puffs_cred *pcr, int *eofflag,
off_t *cookies, size_t
*ncookies);
int
puffs_node_symlink(struct
puffs_usermount *pu, puffs_cookie_t opc,
struct puffs_newinfo *pni, const
struct puffs_cn *pcn_src, const struct vattr
*vap, const char *link_target);
int
puffs_node_readlink(struct
puffs_usermount *pu, puffs_cookie_t opc,
const struct puffs_cred *pcr, char
*link, size_t *linklen);
int
puffs_node_read(struct puffs_usermount
*pu, puffs_cookie_t opc, uint8_t
*buf, off_t offset, size_t
*resid, const struct puffs_cred *pcr,
int ioflag);
int
puffs_node_write(struct
puffs_usermount *pu, puffs_cookie_t opc,
uint8_t *buf, off_t offset,
size_t *resid, const struct puffs_cred
*pcr, int ioflag);
int
puffs_node_write2(struct
puffs_usermount *pu, puffs_cookie_t opc,
uint8_t *buf, off_t offset,
size_t *resid, const struct puffs_cred
*pcr, int ioflag, int
xflag);
int
puffs_node_abortop(struct
puffs_usermount *pu, puffs_cookie_t opc,
const struct puffs_cn *pcn);
int
puffs_node_getextattr(struct
puffs_usermount *pu, puffs_cookie_t opc,
int attrnamespace, const char
*attrname, size_t *attrsize,
uint8_t *attr, size_t *resid,
const struct puffs_cred *pcr);
int
puffs_node_setextattr(struct
puffs_usermount *pu, puffs_cookie_t opc,
int attrnamespace, const char
*attrname, uint8_t *attr, size_t
*resid, const struct puffs_cred *pcr);
int
puffs_node_listextattr(struct
puffs_usermount *pu, puffs_cookie_t opc,
int attrnamespace, size_t
*attrssize, uint8_t *attrs,
size_t *resid, int flag,
const struct puffs_cred *pcr);
int
puffs_node_deleteextattr(struct
puffs_usermount *pu, puffs_cookie_t opc,
int attrnamespace, const char
*attrname, const struct puffs_cred *pcr);
int
puffs_node_fallocate(struct
puffs_usermount *pu, puffs_cookie_t opc,
off_t pos, off_t len);
int
puffs_node_fdiscard(struct
puffs_usermount *pu, puffs_cookie_t opc,
off_t pos, off_t len);
int
puffs_node_print(struct
puffs_usermount *pu, puffs_cookie_t opc);
int
puffs_node_reclaim(struct
puffs_usermount *pu, puffs_cookie_t opc);
int
puffs_node_reclaim2(struct
puffs_usermount *pu, puffs_cookie_t opc,
int nlookup);
int
puffs_node_inactive(struct
puffs_usermount *pu, puffs_cookie_t opc);
void
puffs_setback(struct
puffs_cc *pcc, int
op);
void
puffs_newinfo_setcookie(struct
puffs_newinfo *pni,
puffs_cookie_t
cookie);
void
puffs_newinfo_setvtype(struct
puffs_newinfo *pni, enum
vtype vtype);
void
puffs_newinfo_setsize(struct
puffs_newinfo *pni,
voff_t size);
void
puffs_newinfo_setrdev(struct
puffs_newinfo *pni, dev_t
rdev);
void
puffs_newinfo_setva(struct
puffs_newinfo *pni,
struct vattr *vap);
void
puffs_newinfo_setvattl(struct
puffs_newinfo *pni,
struct timespec
*va_ttl);
void
puffs_newinfo_setcnttl(struct
puffs_newinfo *pni,
struct timespec
*cn_ttl);
The operations 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.
All callbacks can be prototyped with the file
system name and operation name using the macro
PUFFSOP_PROTOS(fsname).
puffs_fs_statvfs(pu,
sbp) * 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
puffs_fs_sync(pu,
waitfor, pcr)MNT_WAITMNT_NOWAITMNT_LAZYnode_fsync()
is called with FSYNC_LAZY.The credentials for the initiator of the sync operation are present in 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.
puffs_fs_fhtonode(pu,
fid, fidsize,
pni)EINVAL returned in
case the file handle length is not correct.
This function provides essentially the
same information to the kernel as
puffs_node_lookup().
The information is necessary for creating a new vnode corresponding to
the file handle.
puffs_fs_nodetofh(pu,
cookie, fid,
fidsize)For file systems which want dynamic length file handles, this
function must check if the file handle space indicated by
fidsize is large enough to accommodate the file
handle for the node. If not, it must fill in the correct size and return
E2BIG. In either case, the handle length should
be supplied to the kernel in fidsize. File systems
with static length handles can ignore the size parameter as the kernel
always supplies the correct size buffer.
puffs_fs_unmount(pu,
flags)MNT_FORCE is not honored by the file server, the
kernel will forcibly unmount the file system.These operations operate in the level of individual files. The file cookie is always provided as the second argument 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 “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.
puffs_newinfo_setcookie().
Additionally, the vnode type and size (latter applicable to regular files
only) should be set using
puffs_newinfo_setvtype()
and
puffs_newinfo_setsize(),
respectively. If the located entry is a block device or character device
file, the dev_t for the entry should be set using
puffs_newinfo_setrdev().
If
puffs_init()
was called with PUFFS_KFLAG_CACHE_FS_TTL then
puffs_newinfo_setva(),
puffs_newinfo_setvattl(),
and
puffs_newinfo_setcnttl()
can be called to specify the new node attributes, cached attributes time
to live, and cached name time to live.
The type of operation is found from pcn->pcn_nameiop:
NAMEI_LOOKUPNAMEI_CREATENAMEI_DELETENAMEI_RENAMENAMEI_DELETE).The final component from a pathname lookup usually requires
special treatment. It can be identified by looking at the
pcn->pcn_flags fields for the flag
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.
The return value 0 signals a found node and a nonzero value
signals an errno. As a special case, ENOENT
signals "success" for cases where the lookup operation is
NAMEI_CREATE or
NAMEI_RENAME. Failure in these cases can be
signalled by returning another appropriate error code, for example
EACCESS.
Usually a null-terminated string for the next
pathname component is provided in
pcn->pcn_name. In case the file system is using
the option PUFFS_KFLAG_LOOKUP_FULLPNBUF, the
remainder of the complete pathname under lookup is found in the same
location. pcn->pcn_namelen always specifies the
length of the next component. If operating with a full path, the file
system is allowed to consume more than the next component's length in
node lookup. This is done by setting
pcn->pcn_consume to indicate the amount of
extra
characters in addition to pcn->pcn_namelen
processed.
puffs_node_create(pu,
opc, pni,
pcn, va)puffs_node_mkdir(pu,
opc, pni,
pcn, va)puffs_node_mknod(pu,
opc, pni,
pcn, va)In case of mknod, the device identifier can be found in va->va_rdev.
puffs_node_open(pu,
opc, mode,
pcr)puffs_node_open2(pu,
opc, mode,
pcr, oflags)O_APPEND and O_NONBLOCK.
puffs_node_open2() allows the file system to pass
back information for the file in oflags. The only
implemented flag for now is PUFFS_OPEN_IO_DIRECT
that cause file read/write to bypass the page cache.puffs_node_close(pu,
opc, flags,
pcr)puffs_node_access(pu,
opc, mode,
pcr)PUFFS_VREAD,
PUFFS_VWRITE, and
PUFFS_VEXEC, respectively.puffs_node_getattr(pu,
opc, va,
pcr)puffs_node_getattr_ttl(pu,
opc, va,
pcr, va_ttl)puffs_node_getattr() with cached attribute
time to live specified in va_ttlpuffs_node_setattr(pu,
opc, va,
pcr)PUFFS_VNOVAL (typecast to the field's type!)
contain a valid value.puffs_node_setattr_ttl(pu,
opc, va,
pcr, va_ttl,
xflag)puffs_node_setattr() with cached attribute
time to live specified in va_ttl.
PUFFS_SETATTR_FAF will be set in
xflag for Fire-And-Forget operations.puffs_node_pathconf(pu,
opc, name,
retval)puffs_node_advlock(po,
opc, id,
op, fl,
flags)puffs_node_poll(pu,
opc, events)In case this function returns an error,
POLLERR (or its
select(2) equivalent) will
be delivered to the calling process.
NOTE!
The system call interface for
poll()
contains a timeout parameter. At this level, however, the timeout is not
supplied. In case input does not arrive, the file system should
periodically unblock and return 0 new events to avoid hanging forever.
This will hopefully be better supported by libpuffs in the future.
puffs_node_mmap(pu,
opc, flags,
pcr)puffs_node_fsync(pu,
opc, pcr,
flags, offlo,
offhi)puffs_node_seek(pu,
opc, oldoff,
newoff, pcr)puffs_node_remove(pu,
opc, targ,
pcn)puffs_node_rmdir(pu,
opc, targ,
pcn)It is paramount to note that the file
system may not remove the node data structures at this point, only the
directory entry and prevent lookups from finding the node again. This is
to retain the UNIX open file semantics. The data
may be removed only when
puffs_node_reclaim()
or
puffs_node_reclaim2()
is called for the node, as this assures there are no further users.
puffs_node_link(pu,
opc, targ,
pcn)puffs_node_rename(pu,
src_dir, src,
pcn_src, targ_dir,
targ, pcn_targ)NULL.
It is legal to replace a directory node by another directory
node with the means of rename if the target directory is empty,
otherwise ENOTEMPTY should be returned. All
other types can replace all other types. In case a rename between
incompatible types is attempted, the errors
ENOTDIR or EISDIR should
be returned, depending on the target type.
puffs_node_readdir(pu,
opc, dent,
readoff, reslen,
pcr, eofflag,
cookies, ncookies)puffs_node_readdir() is
called. It should store directories as struct dirent
in the space pointed to by dent. The amount of space
available is given by reslen and before returning it
should be set to the amount of space
remaining
in the buffer. The argument offset is used to
specify the offset to the directory. Its interpretation is up to the file
system and it should be set to signal the continuation point when there is
no more room for the next entry in dent. It is most
performant to return the maximal amount of directory entries each call. It
is easiest to generate directory entries by using
puffs_nextdent(),
which also automatically advances the necessary pointers.
In case end-of-directory is reached, eofflag should be set to one. Note that even a new call to readdir may start where readoff points to end-of-directory.
If the file system supports file handles, the
arguments cookies and
ncookies must be filled out.
cookies is a vector for offsets corresponding to
read offsets. One cookie should be filled out for each directory entry.
The value of the cookie should equal the offset of the
next directory
entry, i.e., which offset should be passed to readdir for the first
entry read to be the entry following the current one.
ncookies is the number of slots for cookies in the
cookie vector upon entry to the function and must be set to the amount
of cookies stored in the vector (i.e., amount of directory entries read)
upon exit. There is always enough space in the cookie vector for the
maximal number of entries that will fit into the directory entry buffer.
For filling out the vector, the helper function
PUFFS_STORE_DCOOKIE(cookies,
ncookies, offset) can be
used. This properly checks against cookies being
NULL. Note that ncookies
must be initialized to zero before the first call to
PUFFS_STORE_DCOOKIE().
puffs_node_symlink(pu,
opc, pni,
pcn_src, va,
link_target)puffs_node_readlink(pu,
opc, pcr,
link, linklen)puffs_node_read(pu,
opc, buf,
offset, resid,
pcr, ioflag)puffs_node_write(pu,
opc, buf,
offset, resid,
pcr, ioflag)puffs_node_write2(pu,
opc, buf,
offset, resid,
pcr, ioflag,
xflag)puffs_node_write() writes data to a file
opc at offset and extend the
file if necessary. The number of octets written is indicated by
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 ioflag PUFFS_IO_APPEND is
specified, the data should be appended to the end of the file.
puffs_node_write2() serves the same purpose as
puffs_node_write() with an additional
xflag in which
PUFFS_WRITE_FAF is set for Fire-And-Forget
operations.puffs_node_fallocate(pu,
opc, pos,
len)puffs_node_fdiscard(pu,
opc, pos,
len)puffs_node_print(pu,
opc)puffs_node_reclaim(pu,
opc)puffs_node_reclaim2(pu,
opc, nlookup)puffs_node_reclaim() with an additional
argument for the number of lookups that have been done on the node (Node
creation is counted as a lookup). This can be used by the file system to
avoid a race condition, where the kernel sends a reclaim while it does not
have received the reply for a lookup. If the file system tracks lookup
count, and compares to nlookup it can detect this
situation and ignore the reclaim.
If the file system maps cookies to
struct puffs_node then the framework will do that
work, and
puffs_node_reclaim()
can be reliably used without the race condition.
puffs_node_abortop(pu,
opc, pcn)puffs_node_inactive(pu,
opc)puffs_node_reclaim() or
puffs_node_reclaim2() is called.puffs_setback(pcc,
op)PUFFS_SETBACK_INACT_N1 and
PUFFS_SETBACK_INACT_N2. These signal that a file
system mounted with PUFFS_KFLAG_IAONDEMAND should
call the file system inactive method for the specified node. The node
number 1 always means the operation cookie opc,
while the node number 2 can be used to specify the second node argument
present in some methods, e.g., remove.puffs_newinfo_setcookie(pni,
cookie)puffs_newinfo_setvtype(pni,
vtype)lookup()
and
fhtonode().puffs_newinfo_setsize(pni,
size)lookup() and
fhtovp().puffs_newinfo_setrdev(pni,
rdev)lookup() and
fhtovp() producing device type nodes.puffs_newinfo_setva(pni,
vap)lookup(),
create(),
mkdir(),
mknod(),
and
symlink(),
if puffs_init() was called with
PUFFS_KFLAG_CACHE_FS_TTL flag set.puffs_newinfo_setvattl(pni,
va_ttl)lookup(),
create(), mkdir(),
mknod(), and symlink(), if
puffs_init() was called with
PUFFS_KFLAG_CACHE_FS_TTL flag set.puffs_newinfo_setcnttl(pni,
cn_ttl)lookup(), create(),
mkdir(), mknod(), and
symlink(), if puffs_init()
was called with PUFFS_KFLAG_CACHE_FS_TTL flag
set.| August 29, 2016 | NetBSD 11.0 |