Synchronize on NetBSD-CVS (2013/12/1 12:00:00 UTC)

- Fix for possible unset uid/gid in toproto
 - Fix for default mtree style
 - Update libelf
 - Importing libexecinfo
 - Resynchronize GCC, mpc, gmp, mpfr
 - build.sh: Replace params with show-params.
     This has been done as the make target has been renamed in the same
     way, while a new target named params has been added. This new
     target generates a file containing all the parameters, instead of
     printing it on the console.
 - Update test48 with new etc/services (Fix by Ben Gras <ben@minix3.org)
     get getservbyport() out of the inner loop

Change-Id: Ie6ad5226fa2621ff9f0dee8782ea48f9443d2091
This commit is contained in:
2014-07-28 17:05:06 +02:00
parent ff10274392
commit 84d9c625bf
4655 changed files with 379308 additions and 151050 deletions
+17 -12
View File
@@ -1,26 +1,31 @@
# $NetBSD: Makefile,v 1.24 2010/12/06 14:50:34 pooka Exp $
# $NetBSD: Makefile,v 1.25 2012/03/21 05:37:43 matt Exp $
#
.include <bsd.own.mk>
USE_FORT?= no # data-driven bugs?
# LSC Until this is fixed
NOGCCERROR=yes
CPPFLAGS+=-isystem ${DESTDIR}/usr/include
USE_FORT?= yes # data-driven bugs?
WARNS= 4
WARNS?= 5
LIB= puffs
SRCS= puffs.c callcontext.c creds.c \
null.c pnode.c \
subr.c \
inode.c link.c misc.c mount.c open.c path.c path_puffs.c \
protect.c read.c stadir.c time.c utility.c table.c
MAN= puffs.3 puffs_cc.3 puffs_cred.3 \
puffs_node.3 puffs_ops.3 puffs_path.3
INCS= puffs.h puffs_msgif.h
subr.c
MAN= puffs.3 puffs_cc.3 puffs_cred.3 puffs_flush.3 \
puffs_framebuf.3 puffs_node.3 puffs_ops.3 puffs_path.3
INCS= puffs.h
INCSDIR= /usr/include
LINTFLAGS+=-S -w
.if defined(__MINIX)
SRCS+= inode.c link.c misc.c mount.c open.c path.c path_puffs.c \
protect.c read.c stadir.c time.c utility.c table.c
CPFFLAGS+=-Dlchown=chown -Dlchmod=chmod
NOGCCERROR=yes
NOCLANGERROR=yes
.endif # defined(__MINIX)
.include <bsd.lib.mk>
+42
View File
@@ -0,0 +1,42 @@
$NetBSD: TODO,v 1.3 2007/07/19 07:48:10 pooka Exp $
Document some possible user-visible changes that may take place.
For a complete list, please dump my brain and excavate.
* figure out what do to with struct vattr, maybe introduce some
vattr-like puffs-specific structure (translation costs?) instead
of direct exposure
* make puffs_node opaque outside the library
* make it possible to cache symlink names and getattr results in
the kernel ... although I'm not as critically concerned with the
kernel caching as I am with userlevel caching
* try to implement a kernel policy for VOP_ACCESS, it's called
very very often - but this requires some kernel caching
+ also try to figure out how to implement it in cases where it's
more difficult to do, e.g. how can we know readdir on sshfs will
fail without actually trying to read the directory? If we fail
readdir itself, it's treated as success
* implement file system layering .. this will most likely bring
massive changes to how the ops vector is handled, for instance.
pcc/pu division should stay quite like the way it is now, but
maybe there will be layer specific ops.
* make puffs more like kernel vfs - or make kernel vfs more like puffs
* decide what to do about setback operations. they kind of violate
the transparency of FAF for op handling
* remove flags parameter to puffs_init and replace with something
more generic
* fix incoming requests to not require memcpy with continuations
(not user-visible?)
* make continuations play with libpthread, lib/36011 (not user-visible?)
* clean up the request dispatching / continuation code (not user-visible?)
+13 -4
View File
@@ -1,4 +1,4 @@
/* $NetBSD: callcontext.c,v 1.23 2008/08/11 16:23:37 pooka Exp $ */
/* $NetBSD: callcontext.c,v 1.27 2011/12/06 21:15:39 skrll Exp $ */
/*
* Copyright (c) 2006, 2007, 2008 Antti Kantee. All Rights Reserved.
@@ -30,7 +30,7 @@
#include <sys/cdefs.h>
#if !defined(lint)
__RCSID("$NetBSD: callcontext.c,v 1.23 2008/08/11 16:23:37 pooka Exp $");
__RCSID("$NetBSD: callcontext.c,v 1.27 2011/12/06 21:15:39 skrll Exp $");
#endif /* !lint */
#include <sys/types.h>
@@ -38,13 +38,13 @@ __RCSID("$NetBSD: callcontext.c,v 1.23 2008/08/11 16:23:37 pooka Exp $");
#include <assert.h>
#include <errno.h>
#include <puffs.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ucontext.h>
#include <unistd.h>
#include "puffs.h"
#include "puffs_priv.h"
#if 0
@@ -78,6 +78,14 @@ puffs_cc_yield(struct puffs_cc *pcc)
assert(puffs_fakecc == 0);
if ((~pcc->pcc_flags & (PCC_BORROWED|PCC_DONE)) == 0) {
pcc->pcc_flags &= ~(PCC_BORROWED|PCC_DONE);
/*
* see the XXX comment in puffs__cc_cont
*/
puffs__cc_destroy(pcc, 1);
setcontext(&pcc->pcc_uc_ret);
}
pcc->pcc_flags &= ~PCC_BORROWED;
/* romanes eunt domus */
@@ -110,7 +118,7 @@ puffs__cc_cont(struct puffs_cc *pcc)
DPRINTF(("puffs__cc_cont: pcc %p, mycc %p\n", pcc, mycc));
/*
* XXX: race between setcontenxt() and recycle if
* XXX: race between setcontext() and recycle if
* we go multithreaded
*/
puffs__cc_destroy(mycc, 1);
@@ -288,6 +296,7 @@ puffs__cc_destroy(struct puffs_cc *pcc, int nonuke)
{
struct puffs_usermount *pu = pcc->pcc_pu;
pcc->pcc_flags &= ~PCC_HASCALLER;
assert(pcc->pcc_flags == 0);
assert(!puffs_fakecc);
+8 -7
View File
@@ -1,4 +1,4 @@
/* $NetBSD: creds.c,v 1.14.12.1 2009/11/28 16:01:03 bouyer Exp $ */
/* $NetBSD: creds.c,v 1.16 2012/03/15 12:49:36 njoly Exp $ */
/*
* Copyright (c) 2006 Antti Kantee. All Rights Reserved.
@@ -29,7 +29,7 @@
#include <sys/cdefs.h>
#if !defined(lint)
__RCSID("$NetBSD: creds.c,v 1.14.12.1 2009/11/28 16:01:03 bouyer Exp $");
__RCSID("$NetBSD: creds.c,v 1.16 2012/03/15 12:49:36 njoly Exp $");
#endif /* !lint */
/*
@@ -40,10 +40,10 @@ __RCSID("$NetBSD: creds.c,v 1.14.12.1 2009/11/28 16:01:03 bouyer Exp $");
#include <sys/param.h>
#include <errno.h>
#include <puffs.h>
#include <stdbool.h>
#include <string.h>
#include "puffs.h"
#include "puffs_priv.h"
#define UUCCRED(a) (a->pkcr_type == PUFFCRED_TYPE_UUC)
@@ -250,10 +250,11 @@ puffs_access_times(uid_t uid, gid_t gid, mode_t mode, int va_utimes_null,
const struct puffs_cred *pcr)
{
if (!puffs_cred_isuid(pcr, uid) && !puffs_cred_isjuggernaut(pcr)
&& (va_utimes_null == 0
|| puffs_access(VNON, mode, uid, gid, PUFFS_VWRITE, pcr) != 0))
if (puffs_cred_isuid(pcr, uid) || puffs_cred_isjuggernaut(pcr))
return 0;
if (va_utimes_null == 0)
return EPERM;
return 0;
return puffs_access(VNON, mode, uid, gid, PUFFS_VWRITE, pcr);
}
File diff suppressed because it is too large Load Diff
+135
View File
@@ -0,0 +1,135 @@
/* $NetBSD: flush.c,v 1.16 2008/08/12 19:44:39 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 ``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.
*/
#include <sys/cdefs.h>
#if !defined(lint)
__RCSID("$NetBSD: flush.c,v 1.16 2008/08/12 19:44:39 pooka Exp $");
#endif /* !lint */
/*
* Flushing / invalidation routines
*/
#include <sys/types.h>
#include <assert.h>
#include <err.h>
#include <errno.h>
#include <puffs.h>
#include <stdio.h>
#include <unistd.h>
#include "puffs_priv.h"
#if 0
int
puffs_inval_namecache_node(struct puffs_usermount *pu, puffs_cookie_t cookie,
const char *name)
{
return EOPNOTSUPP;
}
#endif
static int
doflush(struct puffs_usermount *pu, puffs_cookie_t cookie, int op,
off_t start, off_t end)
{
struct puffs_framebuf *pb;
struct puffs_flush *pf;
size_t winlen;
int rv;
pb = puffs_framebuf_make();
if (pb == NULL)
return ENOMEM;
winlen = sizeof(struct puffs_flush);
if ((rv = puffs_framebuf_getwindow(pb, 0, (void *)&pf, &winlen)) == -1)
goto out;
assert(winlen == sizeof(struct puffs_flush));
pf->pf_req.preq_buflen = sizeof(struct puffs_flush);
pf->pf_req.preq_opclass = PUFFSOP_FLUSH;
pf->pf_req.preq_id = puffs__nextreq(pu);
pf->pf_op = op;
pf->pf_cookie = cookie;
pf->pf_start = start;
pf->pf_end = end;
rv = puffs_framev_enqueue_cc(puffs_cc_getcc(pu),
puffs_getselectable(pu), pb, 0);
out:
puffs_framebuf_destroy(pb);
return rv;
}
int
puffs_inval_namecache_dir(struct puffs_usermount *pu, puffs_cookie_t cookie)
{
return doflush(pu, cookie, PUFFS_INVAL_NAMECACHE_DIR, 0, 0);
}
int
puffs_inval_namecache_all(struct puffs_usermount *pu)
{
return doflush(pu, NULL, PUFFS_INVAL_NAMECACHE_ALL, 0, 0);
}
int
puffs_inval_pagecache_node(struct puffs_usermount *pu, puffs_cookie_t cookie)
{
return doflush(pu, cookie, PUFFS_INVAL_PAGECACHE_NODE_RANGE, 0, 0);
}
int
puffs_inval_pagecache_node_range(struct puffs_usermount *pu,
puffs_cookie_t cookie, off_t start, off_t end)
{
return doflush(pu, cookie, PUFFS_INVAL_PAGECACHE_NODE_RANGE, start,end);
}
int
puffs_flush_pagecache_node(struct puffs_usermount *pu, puffs_cookie_t cookie)
{
return doflush(pu, cookie, PUFFS_FLUSH_PAGECACHE_NODE_RANGE, 0, 0);
}
int
puffs_flush_pagecache_node_range(struct puffs_usermount *pu,
puffs_cookie_t cookie, off_t start, off_t end)
{
return doflush(pu, cookie, PUFFS_FLUSH_PAGECACHE_NODE_RANGE, start,end);
}
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -10,7 +10,7 @@
#include <minix/vfsif.h>
#include "puffs_msgif.h"
#include <fs/puffs/puffs_msgif.h>
EXTERN struct puffs_usermount *global_pu;
-13
View File
@@ -1,13 +0,0 @@
#ifndef _MNTOPTS_H_
#define _MNTOPTS_H_
struct mntopt {
const char *m_option; /* option name */
int m_inverse; /* if a negative option, eg "dev" */
int m_flag; /* bit to set, eg. MNT_RDONLY */
int m_altloc; /* 1 => set bit in altflags */
};
#endif
+151 -59
View File
@@ -1,4 +1,4 @@
/* $NetBSD: null.c,v 1.25 2008/08/12 19:44:39 pooka Exp $ */
/* $NetBSD: null.c,v 1.33 2011/11/25 15:02:02 manu Exp $ */
/*
* Copyright (c) 2007 Antti Kantee. All Rights Reserved.
@@ -27,7 +27,7 @@
#include <sys/cdefs.h>
#if !defined(lint)
__RCSID("$NetBSD: null.c,v 1.25 2008/08/12 19:44:39 pooka Exp $");
__RCSID("$NetBSD: null.c,v 1.33 2011/11/25 15:02:02 manu Exp $");
#endif /* !lint */
/*
@@ -36,19 +36,18 @@ __RCSID("$NetBSD: null.c,v 1.25 2008/08/12 19:44:39 pooka Exp $");
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <assert.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <puffs.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <utime.h>
#include "puffs.h"
PUFFSOP_PROTOS(puffs_null)
@@ -58,30 +57,24 @@ PUFFSOP_PROTOS(puffs_null)
static int
processvattr(const char *path, const struct vattr *va, int regular)
{
struct utimbuf tbuf;
struct timeval tv[2];
/* XXX: -1 == PUFFS_VNOVAL, but shouldn't trust that */
if (va->va_uid != (unsigned)-1 || va->va_gid != (unsigned)-1)
/* FIXME: lchown */
if (chown(path, va->va_uid, va->va_gid) == -1)
if (lchown(path, va->va_uid, va->va_gid) == -1)
return errno;
#ifndef __minix
if (va->va_mode != (unsigned)PUFFS_VNOVAL)
#endif
/* FIXME: lchmod */
if (chmod(path, va->va_mode) == -1)
if (lchmod(path, va->va_mode) == -1)
return errno;
/* sloppy */
if (va->va_atime.tv_sec != PUFFS_VNOVAL
|| va->va_mtime.tv_sec != PUFFS_VNOVAL) {
/* FIXME: nsec too */
tbuf.actime = va->va_atime.tv_sec;
tbuf.modtime = va->va_mtime.tv_sec;
if (va->va_atime.tv_sec != (time_t)PUFFS_VNOVAL
|| va->va_mtime.tv_sec != (time_t)PUFFS_VNOVAL) {
TIMESPEC_TO_TIMEVAL(&tv[0], &va->va_atime);
TIMESPEC_TO_TIMEVAL(&tv[1], &va->va_mtime);
/* FIXME: lutimes */
if (utime(path, &tbuf) == -1)
if (lutimes(path, tv) == -1)
return errno;
}
@@ -174,6 +167,8 @@ puffs_null_setops(struct puffs_ops *pops)
PUFFSOP_SET(pops, puffs_null, fs, statvfs);
PUFFSOP_SETFSNOP(pops, unmount);
PUFFSOP_SETFSNOP(pops, sync);
PUFFSOP_SET(pops, puffs_null, fs, fhtonode);
PUFFSOP_SET(pops, puffs_null, fs, nodetofh);
PUFFSOP_SET(pops, puffs_null, node, lookup);
PUFFSOP_SET(pops, puffs_null, node, create);
@@ -205,6 +200,99 @@ puffs_null_fs_statvfs(struct puffs_usermount *pu, struct statvfs *svfsb)
return 0;
}
/*
* XXX: this is the stupidest crap ever, but:
* getfh() returns the fhandle type, when we are expected to deliver
* the fid type. Just adjust it a bit and stop whining.
*
* Yes, this really really needs fixing. Yes, *REALLY*.
*/
#define FHANDLE_HEADERLEN 8
struct kernfid {
unsigned short fid_len; /* length of data in bytes */
unsigned short fid_reserved; /* compat: historic align */
char fid_data[0]; /* data (variable length) */
};
/*ARGSUSED*/
static void *
fhcmp(struct puffs_usermount *pu, struct puffs_node *pn, void *arg)
{
struct kernfid *kf1, *kf2;
if ((kf1 = pn->pn_data) == NULL)
return NULL;
kf2 = arg;
if (kf1->fid_len != kf2->fid_len)
return NULL;
/*LINTED*/
if (memcmp(kf1, kf2, kf1->fid_len) == 0)
return pn;
return NULL;
}
/*
* This routine only supports file handles which have been issued while
* the server was alive. Not really stable ones, that is.
*/
/*ARGSUSED*/
int
puffs_null_fs_fhtonode(struct puffs_usermount *pu, void *fid, size_t fidsize,
struct puffs_newinfo *pni)
{
struct puffs_node *pn_res;
pn_res = puffs_pn_nodewalk(pu, fhcmp, fid);
if (pn_res == NULL)
return ENOENT;
puffs_newinfo_setcookie(pni, pn_res);
puffs_newinfo_setvtype(pni, pn_res->pn_va.va_type);
puffs_newinfo_setsize(pni, (voff_t)pn_res->pn_va.va_size);
puffs_newinfo_setrdev(pni, pn_res->pn_va.va_rdev);
return 0;
}
/*ARGSUSED*/
int
puffs_null_fs_nodetofh(struct puffs_usermount *pu, puffs_cookie_t opc,
void *fid, size_t *fidsize)
{
struct puffs_node *pn = opc;
struct kernfid *kfid;
void *bounce;
int rv;
rv = 0;
bounce = NULL;
if (*fidsize) {
bounce = malloc(*fidsize + FHANDLE_HEADERLEN);
if (!bounce)
return ENOMEM;
*fidsize += FHANDLE_HEADERLEN;
}
if (getfh(PNPATH(pn), bounce, fidsize) == -1)
rv = errno;
else
memcpy(fid, (uint8_t *)bounce + FHANDLE_HEADERLEN,
*fidsize - FHANDLE_HEADERLEN);
kfid = fid;
if (rv == 0) {
*fidsize = kfid->fid_len;
pn->pn_data = malloc(*fidsize);
if (pn->pn_data == NULL)
abort(); /* lazy */
memcpy(pn->pn_data, fid, *fidsize);
} else {
*fidsize -= FHANDLE_HEADERLEN;
}
free(bounce);
return rv;
}
int
puffs_null_node_lookup(struct puffs_usermount *pu, puffs_cookie_t opc,
struct puffs_newinfo *pni, const struct puffs_cn *pcn)
@@ -319,32 +407,43 @@ puffs_null_node_fsync(struct puffs_usermount *pu, puffs_cookie_t opc,
const struct puffs_cred *pcred, int how,
off_t offlo, off_t offhi)
{
/* FIXME: implement me. */
#if 0
struct puffs_node *pn = opc;
int fd, rv;
int fflags;
struct stat sb;
rv = 0;
fd = writeableopen(PNPATH(pn));
if (fd == -1)
if (stat(PNPATH(pn), &sb) == -1)
return errno;
if (S_ISDIR(sb.st_mode)) {
DIR *dirp;
if ((dirp = opendir(PNPATH(pn))) == 0)
return errno;
fd = dirfd(dirp);
if (fd == -1)
return errno;
if (how & PUFFS_FSYNC_DATAONLY)
fflags = FDATASYNC;
else
fflags = FFILESYNC;
if (how & PUFFS_FSYNC_CACHE)
fflags |= FDISKSYNC;
if (fsync(fd) == -1)
rv = errno;
} else {
fd = writeableopen(PNPATH(pn));
if (fd == -1)
return errno;
if (fsync_range(fd, fflags, offlo, offhi - offlo) == -1)
rv = errno;
if (how & PUFFS_FSYNC_DATAONLY)
fflags = FDATASYNC;
else
fflags = FFILESYNC;
if (how & PUFFS_FSYNC_CACHE)
fflags |= FDISKSYNC;
if (fsync_range(fd, fflags, offlo, offhi - offlo) == -1)
rv = errno;
}
close(fd);
return rv;
#endif
return 0;
}
/*ARGSUSED*/
@@ -354,7 +453,7 @@ puffs_null_node_remove(struct puffs_usermount *pu, puffs_cookie_t opc,
{
struct puffs_node *pn_targ = targ;
if (unlink(PCNPATH(pcn)) == -1)
if (unlink(PNPATH(pn_targ)) == -1)
return errno;
puffs_pn_remove(pn_targ);
@@ -386,7 +485,7 @@ puffs_null_node_rename(struct puffs_usermount *pu, puffs_cookie_t opc,
if (rename(PCNPATH(pcn_src), PCNPATH(pcn_targ)) == -1)
return errno;
if (pn_targ)
if (pn_targ)
puffs_pn_remove(pn_targ);
return 0;
@@ -463,13 +562,13 @@ puffs_null_node_readdir(struct puffs_usermount *pu, puffs_cookie_t opc,
const struct puffs_cred *pcred, int *eofflag, off_t *cookies,
size_t *ncookies)
{
/* TODO: use original code since we have libc from NetBSD */
struct puffs_node *pn = opc;
struct dirent *entry;
struct dirent entry, *result;
DIR *dp;
off_t i;
int rv;
*ncookies = 0;
dp = opendir(PNPATH(pn));
if (dp == NULL)
return errno;
@@ -482,42 +581,35 @@ puffs_null_node_readdir(struct puffs_usermount *pu, puffs_cookie_t opc,
* then we'd need to keep state, which I'm too lazy to keep
*/
while (i--) {
entry = readdir(dp);
if (!entry) {
rv = readdir_r(dp, &entry, &result);
if (rv != 0)
goto out;
if (!result) {
*eofflag = 1;
goto out;
}
}
for (;;) {
/* FIXME: DIRENT_SIZE macro? For now do calculations here */
int namelen;
char* cp;
size_t dirent_size;
rv = readdir_r(dp, &entry, &result);
if (rv != 0)
goto out;
entry = readdir(dp);
if (!entry) {
if (!result) {
*eofflag = 1;
goto out;
}
cp = memchr(entry->d_name, '\0', NAME_MAX);
if (cp == NULL)
namelen = NAME_MAX;
else
namelen = cp - (entry->d_name);
dirent_size = _DIRENT_RECLEN(entry, namelen);
if (dirent_size > *reslen)
if (_DIRENT_SIZE(result) > *reslen)
goto out;
*de = *entry;
strncpy(de->d_name, entry->d_name, namelen);
*reslen -= dirent_size;
*de = *result;
*reslen -= _DIRENT_SIZE(result);
de = _DIRENT_NEXT(de);
(*off)++;
PUFFS_STORE_DCOOKIE(cookies, ncookies, *off);
}
out:
+540
View File
@@ -0,0 +1,540 @@
/* $NetBSD: opdump.c,v 1.36 2012/03/15 02:02:21 joerg Exp $ */
/*
* Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved.
*
* Development of this software was supported by the
* Google Summer of Code program and the Ulla Tuominen Foundation.
* The Google SoC project was mentored by Bill Studenmund.
*
* 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 ``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.
*/
/* Pretty-printing helper routines for VFS/VOP request contents */
/* yes, this is pretty much a mess */
#include <sys/cdefs.h>
#if !defined(lint)
__RCSID("$NetBSD: opdump.c,v 1.36 2012/03/15 02:02:21 joerg Exp $");
#endif /* !lint */
#include <sys/types.h>
#include <sys/time.h>
#include <puffs.h>
#include <puffsdump.h>
#include <stdarg.h>
#include <stdio.h>
#include "puffs_priv.h"
#define DINT " "
const char *puffsdump_vfsop_revmap[] = {
"PUFFS_VFS_MOUNT",
"PUFFS_VFS_START",
"PUFFS_VFS_UNMOUNT",
"PUFFS_VFS_ROOT",
"PUFFS_VFS_QUOTACTL",
"PUFFS_VFS_STATVFS",
"PUFFS_VFS_SYNC",
"PUFFS_VFS_VGET",
"PUFFS_VFS_FHTOVP",
"PUFFS_VFS_VPTOFH",
"PUFFS_VFS_INIT",
"PUFFS_VFS_DONE",
"PUFFS_VFS_SNAPSHOT",
"PUFFS_VFS_EXTATTRCTL",
"PUFFS_VFS_SUSPEND"
};
size_t puffsdump_vfsop_count = __arraycount(puffsdump_vfsop_revmap);
const char *puffsdump_vnop_revmap[] = {
"PUFFS_VN_LOOKUP",
"PUFFS_VN_CREATE",
"PUFFS_VN_MKNOD",
"PUFFS_VN_OPEN",
"PUFFS_VN_CLOSE",
"PUFFS_VN_ACCESS",
"PUFFS_VN_GETATTR",
"PUFFS_VN_SETATTR",
"PUFFS_VN_READ",
"PUFFS_VN_WRITE",
"PUFFS_VN_IOCTL",
"PUFFS_VN_FCNTL",
"PUFFS_VN_POLL",
"PUFFS_VN_KQFILTER",
"PUFFS_VN_REVOKE",
"PUFFS_VN_MMAP",
"PUFFS_VN_FSYNC",
"PUFFS_VN_SEEK",
"PUFFS_VN_REMOVE",
"PUFFS_VN_LINK",
"PUFFS_VN_RENAME",
"PUFFS_VN_MKDIR",
"PUFFS_VN_RMDIR",
"PUFFS_VN_SYMLINK",
"PUFFS_VN_READDIR",
"PUFFS_VN_READLINK",
"PUFFS_VN_ABORTOP",
"PUFFS_VN_INACTIVE",
"PUFFS_VN_RECLAIM",
"PUFFS_VN_LOCK",
"PUFFS_VN_UNLOCK",
"PUFFS_VN_BMAP",
"PUFFS_VN_STRATEGY",
"PUFFS_VN_PRINT",
"PUFFS_VN_ISLOCKED",
"PUFFS_VN_PATHCONF",
"PUFFS_VN_ADVLOCK",
"PUFFS_VN_LEASE",
"PUFFS_VN_WHITEOUT",
"PUFFS_VN_GETPAGES",
"PUFFS_VN_PUTPAGES",
"PUFFS_VN_GETEXTATTR",
"PUFFS_VN_LISTEXTATTR",
"PUFFS_VN_OPENEXTATTR",
"PUFFS_VN_DELETEEXTATTR",
"PUFFS_VN_SETEXTATTR",
"PUFFS_VN_CLOSEEXTATTR",
};
size_t puffsdump_vnop_count = __arraycount(puffsdump_vnop_revmap);
/* XXX! */
const char *puffsdump_cacheop_revmap[] = {
"PUFFS_CACHE_WRITE"
};
const char *puffsdump_errnot_revmap[] = {
"PUFFS_ERR_ERROR",
"PUFFS_ERR_MAKENODE",
"PUFFS_ERR_LOOKUP",
"PUFFS_ERR_READDIR",
"PUFFS_ERR_READLINK",
"PUFFS_ERR_READ",
"PUFFS_ERR_WRITE",
"PUFFS_ERR_VPTOFH",
"PUFFS_ERR_GETEXTATTR",
"PUFFS_ERR_LISTEXTATTR",
};
size_t puffsdump_errnot_count = __arraycount(puffsdump_errnot_revmap);
const char *puffsdump_flush_revmap[] = {
"PUFFS_INVAL_NAMECACHE_NODE",
"PUFFS_INVAL_NAMECACHE_DIR",
"PUFFS_INVAL_NAMECACHE_ALL",
"PUFFS_INVAL_PAGECACHE_NODE_RANGE",
"PUFFS_FLUSH_PAGECACHE_NODE_RANGE",
};
size_t puffsdump_flush_count = __arraycount(puffsdump_flush_revmap);
static __printflike(1, 2) void
mydprintf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
void
puffsdump_req(struct puffs_req *preq)
{
char buf[128];
static struct timeval tv_prev;
struct timeval tv_now, tv;
const char **map;
const char *optype;
size_t maxhandle;
int opclass, isvn = 0;
mydprintf("reqid: %" PRIu64 ", ", preq->preq_id);
opclass = PUFFSOP_OPCLASS(preq->preq_opclass);
switch (opclass) {
case PUFFSOP_VFS:
map = puffsdump_vfsop_revmap;
maxhandle = puffsdump_vfsop_count;
break;
case PUFFSOP_VN:
map = puffsdump_vnop_revmap;
maxhandle = puffsdump_vnop_count;
isvn = 1;
break;
case PUFFSOP_CACHE:
map = puffsdump_cacheop_revmap;
maxhandle = __arraycount(puffsdump_cacheop_revmap);
break;
case PUFFSOP_ERROR:
map = puffsdump_errnot_revmap;
maxhandle = puffsdump_errnot_count;
break;
case PUFFSOP_FLUSH:
map = puffsdump_flush_revmap;
maxhandle = puffsdump_flush_count;
break;
default:
mydprintf("unhandled opclass %d\n", opclass);
return;
}
if (preq->preq_optype < maxhandle) {
optype = map[preq->preq_optype];
} else {
snprintf(buf, sizeof(buf), "UNKNOWN (%d)", preq->preq_optype);
optype = buf;
}
mydprintf("opclass %d%s, optype: %s, "
"cookie: %p,\n" DINT "aux: %p, auxlen: %zu, pid: %d, lwpid: %d\n",
opclass, PUFFSOP_WANTREPLY(preq->preq_opclass) ? "" : " (FAF)",
optype, preq->preq_cookie,
preq->preq_buf, preq->preq_buflen,
preq->preq_pid, preq->preq_lid);
if (isvn) {
switch (preq->preq_optype) {
case PUFFS_VN_LOOKUP:
puffsdump_lookup(preq);
break;
case PUFFS_VN_READ:
case PUFFS_VN_WRITE:
puffsdump_readwrite(preq);
break;
case PUFFS_VN_OPEN:
puffsdump_open(preq);
break;
case PUFFS_VN_REMOVE:
case PUFFS_VN_RMDIR:
case PUFFS_VN_LINK:
puffsdump_targ(preq);
break;
case PUFFS_VN_READDIR:
puffsdump_readdir(preq);
break;
case PUFFS_VN_CREATE:
case PUFFS_VN_MKDIR:
case PUFFS_VN_MKNOD:
case PUFFS_VN_SYMLINK:
puffsdump_create(preq);
break;
case PUFFS_VN_SETATTR:
puffsdump_attr(preq);
break;
default:
break;
}
}
PU_LOCK();
gettimeofday(&tv_now, NULL);
timersub(&tv_now, &tv_prev, &tv);
mydprintf(DINT "since previous call: %lld.%06ld\n",
(long long)tv.tv_sec, (long)tv.tv_usec);
gettimeofday(&tv_prev, NULL);
PU_UNLOCK();
}
void
puffsdump_rv(struct puffs_req *preq)
{
if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN) {
switch (preq->preq_optype) {
case PUFFS_VN_LOOKUP:
puffsdump_lookup_rv(preq);
break;
case PUFFS_VN_CREATE:
case PUFFS_VN_MKDIR:
case PUFFS_VN_MKNOD:
case PUFFS_VN_SYMLINK:
puffsdump_create_rv(preq);
break;
case PUFFS_VN_READ:
case PUFFS_VN_WRITE:
puffsdump_readwrite_rv(preq);
break;
case PUFFS_VN_READDIR:
puffsdump_readdir_rv(preq);
break;
case PUFFS_VN_GETATTR:
puffsdump_attr(preq);
break;
default:
break;
}
}
mydprintf("RV reqid: %" PRIu64 ", result: %d %s\n",
preq->preq_id, preq->preq_rv,
preq->preq_rv ? strerror(preq->preq_rv) : "");
}
/*
* Slightly tedious print-routine so that we get a nice NOVAL instead
* of some tedious output representations for -1, especially (uint64_t)-1
*
* We use typecasting to make this work beyond time_t/dev_t size changes.
*/
static void
dumpattr(struct vattr *vap)
{
const char * const vtypes[] = { VNODE_TYPES };
char buf[128];
/* XXX: better readability. and this is debug, so no cycle-sweat */
#define DEFAULTBUF() snprintf(buf, sizeof(buf), "NOVAL")
mydprintf(DINT "vattr:\n");
mydprintf(DINT DINT "type: %s, ", vtypes[vap->va_type]);
DEFAULTBUF();
if (vap->va_mode != (mode_t)PUFFS_VNOVAL)
snprintf(buf, sizeof(buf), "0%o", vap->va_mode);
mydprintf("mode: %s, ", buf);
DEFAULTBUF();
if (vap->va_nlink != (nlink_t)PUFFS_VNOVAL)
snprintf(buf, sizeof(buf), "%d", vap->va_nlink);
mydprintf("nlink: %s, ", buf);
DEFAULTBUF();
if (vap->va_uid != (uid_t)PUFFS_VNOVAL)
snprintf(buf, sizeof(buf), "%d", vap->va_uid);
mydprintf("uid: %s, ", buf);
DEFAULTBUF();
if (vap->va_gid != (gid_t)PUFFS_VNOVAL)
snprintf(buf, sizeof(buf), "%d", vap->va_gid);
mydprintf("gid: %s\n", buf);
DEFAULTBUF();
if ((unsigned long long)vap->va_fsid!=(unsigned long long)PUFFS_VNOVAL)
snprintf(buf, sizeof(buf), "0x%llx",
(unsigned long long)vap->va_fsid);
mydprintf(DINT DINT "fsid: %s, ", buf);
DEFAULTBUF();
if (vap->va_fileid != (ino_t)PUFFS_VNOVAL)
snprintf(buf, sizeof(buf), "%" PRIu64, vap->va_fileid);
mydprintf("ino: %s, ", buf);
DEFAULTBUF();
if (vap->va_size != (u_quad_t)PUFFS_VNOVAL)
snprintf(buf, sizeof(buf), "%" PRIu64, vap->va_size);
mydprintf("size: %s, ", buf);
DEFAULTBUF();
if (vap->va_blocksize != (long)PUFFS_VNOVAL)
snprintf(buf, sizeof(buf), "%ld", vap->va_blocksize);
mydprintf("bsize: %s\n", buf);
DEFAULTBUF();
if (vap->va_atime.tv_sec != (time_t)PUFFS_VNOVAL)
snprintf(buf, sizeof(buf), "%lld",
(long long)vap->va_atime.tv_sec);
mydprintf(DINT DINT "a.s: %s, ", buf);
DEFAULTBUF();
if (vap->va_atime.tv_nsec != (long)PUFFS_VNOVAL)
snprintf(buf, sizeof(buf), "%ld", vap->va_atime.tv_nsec);
mydprintf("a.ns: %s, ", buf);
DEFAULTBUF();
if (vap->va_mtime.tv_sec != (time_t)PUFFS_VNOVAL)
snprintf(buf, sizeof(buf), "%lld",
(long long)vap->va_mtime.tv_sec);
mydprintf("m.s: %s, ", buf);
DEFAULTBUF();
if (vap->va_mtime.tv_nsec != (long)PUFFS_VNOVAL)
snprintf(buf, sizeof(buf), "%ld", vap->va_mtime.tv_nsec);
mydprintf("m.ns: %s\n", buf);
DEFAULTBUF();
if (vap->va_ctime.tv_sec != (time_t)PUFFS_VNOVAL)
snprintf(buf, sizeof(buf), "%lld",
(long long)vap->va_ctime.tv_sec);
mydprintf(DINT DINT "c.s: %s, ", buf);
DEFAULTBUF();
if (vap->va_ctime.tv_nsec != (long)PUFFS_VNOVAL)
snprintf(buf, sizeof(buf), "%ld", vap->va_ctime.tv_nsec);
mydprintf("c.ns: %s, ", buf);
DEFAULTBUF();
if (vap->va_birthtime.tv_sec != (time_t)PUFFS_VNOVAL)
snprintf(buf, sizeof(buf), "%lld",
(long long)vap->va_birthtime.tv_sec);
mydprintf("b.s: %s, ", buf);
DEFAULTBUF();
if (vap->va_birthtime.tv_nsec != (long)PUFFS_VNOVAL)
snprintf(buf, sizeof(buf), "%ld", vap->va_birthtime.tv_nsec);
mydprintf("b.ns: %s\n", buf);
DEFAULTBUF();
if (vap->va_gen != (u_long)PUFFS_VNOVAL)
snprintf(buf, sizeof(buf), "%lu", vap->va_gen);
mydprintf(DINT DINT "gen: %s, ", buf);
DEFAULTBUF();
if (vap->va_flags != (u_long)PUFFS_VNOVAL)
snprintf(buf, sizeof(buf), "0x%lx", vap->va_flags);
mydprintf("flags: %s, ", buf);
DEFAULTBUF();
if (vap->va_rdev != (dev_t)PUFFS_VNOVAL)
snprintf(buf, sizeof(buf), "0x%llx",
(unsigned long long)vap->va_rdev);
mydprintf("rdev: %s\n", buf);
DEFAULTBUF();
if (vap->va_bytes != (u_quad_t)PUFFS_VNOVAL)
snprintf(buf, sizeof(buf), "%" PRIu64, vap->va_bytes);
mydprintf(DINT DINT "bytes: %s, ", buf);
snprintf(buf, sizeof(buf), "%" PRIu64, vap->va_filerev);
mydprintf("filerev: %s, ", buf);
snprintf(buf, sizeof(buf), "0x%x", vap->va_vaflags);
mydprintf("vaflags: %s\n", buf);
}
void
puffsdump_cookie(puffs_cookie_t c, const char *cookiename)
{
mydprintf("%scookie: at %p\n", cookiename, c);
}
static const char *cn_opnames[] = {
"LOOKUP",
"CREATE",
"DELETE",
"RENAME"
};
void
puffsdump_cn(struct puffs_kcn *pkcn)
{
mydprintf(DINT "puffs_cn: \"%s\", len %zu op %s (flags 0x%x)\n",
pkcn->pkcn_name, pkcn->pkcn_namelen,
cn_opnames[pkcn->pkcn_nameiop & NAMEI_OPMASK],
pkcn->pkcn_flags);
}
void
puffsdump_lookup(struct puffs_req *preq)
{
struct puffs_vnmsg_lookup *lookup_msg = (void *)preq;
puffsdump_cn(&lookup_msg->pvnr_cn);
}
void
puffsdump_lookup_rv(struct puffs_req *preq)
{
struct puffs_vnmsg_lookup *lookup_msg = (void *)preq;
mydprintf(DINT "new %p, type 0x%x, size 0x%"PRIu64", dev 0x%llx\n",
lookup_msg->pvnr_newnode, lookup_msg->pvnr_vtype,
lookup_msg->pvnr_size, (unsigned long long)lookup_msg->pvnr_rdev);
}
void
puffsdump_create(struct puffs_req *preq)
{
/* XXX: wrong type, but we know it fits the slot */
struct puffs_vnmsg_create *create_msg = (void *)preq;
dumpattr(&create_msg->pvnr_va);
}
void
puffsdump_create_rv(struct puffs_req *preq)
{
/* XXX: wrong type, but we know it fits the slot */
struct puffs_vnmsg_create *create_msg = (void *)preq;
mydprintf(DINT "new %p\n", create_msg->pvnr_newnode);
}
void
puffsdump_readwrite(struct puffs_req *preq)
{
struct puffs_vnmsg_rw *rw_msg = (void *)preq;
mydprintf(DINT "offset: %" PRId64 ", resid %zu, ioflag 0x%x\n",
rw_msg->pvnr_offset, rw_msg->pvnr_resid, rw_msg->pvnr_ioflag);
}
void
puffsdump_readwrite_rv(struct puffs_req *preq)
{
struct puffs_vnmsg_rw *rw_msg = (void *)preq;
mydprintf(DINT "resid after op: %zu\n", rw_msg->pvnr_resid);
}
void
puffsdump_readdir_rv(struct puffs_req *preq)
{
struct puffs_vnmsg_readdir *readdir_msg = (void *)preq;
mydprintf(DINT "resid after op: %zu, eofflag %d\n",
readdir_msg->pvnr_resid, readdir_msg->pvnr_eofflag);
}
void
puffsdump_open(struct puffs_req *preq)
{
struct puffs_vnmsg_open *open_msg = (void *)preq;
mydprintf(DINT "mode: 0x%x\n", open_msg->pvnr_mode);
}
void
puffsdump_targ(struct puffs_req *preq)
{
struct puffs_vnmsg_remove *remove_msg = (void *)preq; /* XXX! */
mydprintf(DINT "target cookie: %p\n", remove_msg->pvnr_cookie_targ);
}
void
puffsdump_readdir(struct puffs_req *preq)
{
struct puffs_vnmsg_readdir *readdir_msg = (void *)preq;
mydprintf(DINT "read offset: %" PRId64 "\n", readdir_msg->pvnr_offset);
}
void
puffsdump_attr(struct puffs_req *preq)
{
struct puffs_vnmsg_setgetattr *attr_msg = (void *)preq;
dumpattr(&attr_msg->pvnr_va);
}
+299
View File
@@ -0,0 +1,299 @@
/* $NetBSD: paths.c,v 1.8 2008/08/12 19:44:39 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 ``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.
*/
#include <sys/cdefs.h>
#if !defined(lint)
__RCSID("$NetBSD: paths.c,v 1.8 2008/08/12 19:44:39 pooka Exp $");
#endif /* !lint */
#include <sys/hash.h>
#include <assert.h>
#include <errno.h>
#include <puffs.h>
#include <stdlib.h>
#include "puffs_priv.h"
/*
* Generic routines for pathbuilding code
*/
int
puffs_path_pcnbuild(struct puffs_usermount *pu, struct puffs_cn *pcn,
puffs_cookie_t parent)
{
struct puffs_node *pn_parent = PU_CMAP(pu, parent);
struct puffs_cn pcn_orig;
struct puffs_pathobj po;
int rv;
assert(pn_parent->pn_po.po_path != NULL);
assert(pu->pu_flags & PUFFS_FLAG_BUILDPATH);
if (pu->pu_pathtransform) {
rv = pu->pu_pathtransform(pu, &pn_parent->pn_po, pcn, &po);
if (rv)
return rv;
} else {
po.po_path = pcn->pcn_name;
po.po_len = pcn->pcn_namelen;
}
if (pu->pu_namemod) {
/* XXX: gcc complains if I do assignment */
memcpy(&pcn_orig, pcn, sizeof(pcn_orig));
rv = pu->pu_namemod(pu, &pn_parent->pn_po, pcn);
if (rv)
return rv;
}
rv = pu->pu_pathbuild(pu, &pn_parent->pn_po, &po, 0,
&pcn->pcn_po_full);
puffs_path_buildhash(pu, &pcn->pcn_po_full);
if (pu->pu_pathtransform)
pu->pu_pathfree(pu, &po);
if (pu->pu_namemod && rv)
*pcn = pcn_orig;
return rv;
}
/*
* substitute all (child) patch prefixes. called from nodewalk, which
* in turn is called from rename
*/
void *
puffs_path_prefixadj(struct puffs_usermount *pu, struct puffs_node *pn,
void *arg)
{
struct puffs_pathinfo *pi = arg;
struct puffs_pathobj localpo;
struct puffs_pathobj oldpo;
int rv;
/* can't be a path prefix */
if (pn->pn_po.po_len < pi->pi_old->po_len)
return NULL;
if (pu->pu_pathcmp(pu, &pn->pn_po, pi->pi_old, pi->pi_old->po_len, 1))
return NULL;
/* otherwise we'd have two nodes with an equal path */
assert(pn->pn_po.po_len > pi->pi_old->po_len);
/* found a matching prefix */
rv = pu->pu_pathbuild(pu, pi->pi_new, &pn->pn_po,
pi->pi_old->po_len, &localpo);
/*
* XXX: technically we shouldn't fail, but this is the only
* sensible thing to do here. If the buildpath routine fails,
* we will have paths in an inconsistent state. Should fix this,
* either by having two separate passes or by doing other tricks
* to make an invalid path with BUILDPATHS acceptable.
*/
if (rv != 0)
abort();
/* adjust hash sum */
puffs_path_buildhash(pu, &localpo);
/* out with the old and in with the new */
oldpo = pn->pn_po;
pn->pn_po = localpo;
pu->pu_pathfree(pu, &oldpo);
/* continue the walk */
return NULL;
}
/*
* called from nodewalk, checks for exact match
*/
void *
puffs_path_walkcmp(struct puffs_usermount *pu, struct puffs_node *pn, void *arg)
{
struct puffs_pathobj *po = arg;
struct puffs_pathobj po2;
if (po->po_len != PNPLEN(pn))
return NULL;
/*
* If hashing and the hash doesn't match, we know this is
* definitely not a match. Otherwise check for collisions.
*/
if (pu->pu_flags & PUFFS_FLAG_HASHPATH)
if (pn->pn_po.po_hash != po->po_hash)
return NULL;
po2.po_path = PNPATH(pn);
po2.po_len = PNPLEN(pn);
if (pu->pu_pathcmp(pu, po, &po2, PNPLEN(pn), 0) == 0)
return pn;
return NULL;
}
/*
* Hash sum building routine. Use string hash if the buildpath routine
* is the standard one, otherwise use binary hashes. A bit whimsical
* way to choose the routine, but the binary works for strings also,
* so don't sweat it.
*/
void
puffs_path_buildhash(struct puffs_usermount *pu, struct puffs_pathobj *po)
{
if ((pu->pu_flags & PUFFS_FLAG_HASHPATH) == 0)
return;
if (pu->pu_pathbuild == puffs_stdpath_buildpath)
po->po_hash = hash32_strn(po->po_path, po->po_len,
HASH32_STR_INIT);
else
po->po_hash = hash32_buf(po->po_path, po->po_len,
HASH32_BUF_INIT);
}
/*
* Routines provided to file systems which consider a path a tuple of
* strings and / the component separator.
*/
/*ARGSUSED*/
int
puffs_stdpath_cmppath(struct puffs_usermount *pu, struct puffs_pathobj *c1,
struct puffs_pathobj *c2, size_t clen, int checkprefix)
{
char *p;
int rv;
rv = strncmp(c1->po_path, c2->po_path, clen);
if (rv)
return 1;
if (checkprefix == 0)
return 0;
/* sanity for next step */
if (!(c1->po_len > c2->po_len))
return 1;
/* check if it's really a complete path prefix */
p = c1->po_path;
if ((*(p + clen)) != '/')
return 1;
return 0;
}
/*ARGSUSED*/
int
puffs_stdpath_buildpath(struct puffs_usermount *pu,
const struct puffs_pathobj *po_pre, const struct puffs_pathobj *po_comp,
size_t offset, struct puffs_pathobj *newpath)
{
char *path, *pcomp;
size_t plen, complen;
size_t prelen;
int isdotdot;
complen = po_comp->po_len - offset;
/* seek to correct place & remove all leading '/' from component */
pcomp = po_comp->po_path;
pcomp += offset;
while (*pcomp == '/') {
pcomp++;
complen--;
}
/* todotdot or nottodotdot */
if (complen == 2 && strcmp(pcomp, "..") == 0)
isdotdot = 1;
else
isdotdot = 0;
/*
* Strip trailing components from the preceending component.
* This is an issue only for the root node, which we might want
* to be at path "/" for some file systems.
*/
prelen = po_pre->po_len;
while (prelen > 0 && *((char *)po_pre->po_path + (prelen-1)) == '/') {
assert(isdotdot == 0);
prelen--;
}
if (isdotdot) {
char *slash; /* sweet char of mine */
slash = strrchr(po_pre->po_path, '/');
assert(slash != NULL);
plen = slash - (char *)po_pre->po_path;
/*
* As the converse to not stripping the initial "/" above,
* don't nuke it here either.
*/
if (plen == 0)
plen++;
path = malloc(plen + 1);
if (path == NULL)
return errno;
strlcpy(path, po_pre->po_path, plen+1);
} else {
/* + '/' + '\0' */
plen = prelen + 1 + complen;
path = malloc(plen + 1);
if (path == NULL)
return errno;
strlcpy(path, po_pre->po_path, prelen+1);
strcat(path, "/");
strncat(path, pcomp, complen);
}
newpath->po_path = path;
newpath->po_len = plen;
return 0;
}
/*ARGSUSED*/
void
puffs_stdpath_freepath(struct puffs_usermount *pu, struct puffs_pathobj *po)
{
free(po->po_path);
}
+34 -32
View File
@@ -1,4 +1,4 @@
/* $NetBSD: pnode.c,v 1.10 2008/08/12 19:44:39 pooka Exp $ */
/* $NetBSD: pnode.c,v 1.13 2012/08/16 09:25:43 manu Exp $ */
/*
* Copyright (c) 2006 Antti Kantee. All Rights Reserved.
@@ -27,20 +27,22 @@
#include <sys/cdefs.h>
#if !defined(lint)
__RCSID("$NetBSD: pnode.c,v 1.10 2008/08/12 19:44:39 pooka Exp $");
__RCSID("$NetBSD: pnode.c,v 1.13 2012/08/16 09:25:43 manu Exp $");
#endif /* !lint */
#include <minix/type.h>
#include <sys/types.h>
#include <assert.h>
#include <puffs.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "puffs.h"
#include "puffs_priv.h"
#if defined(__minix)
#include <minix/type.h>
#include "proto.h"
#endif /* defined(__minix) */
/*
* Well, you're probably wondering why this isn't optimized.
@@ -62,6 +64,8 @@ puffs_pn_new(struct puffs_usermount *pu, void *privdata)
LIST_INSERT_HEAD(&pu->pu_pnodelst, pn, pn_entries);
pu->pu_flags |= PUFFS_FLAG_PNCOOKIE;
return pn;
}
@@ -90,8 +94,8 @@ puffs_pn_put(struct puffs_node *pn)
struct puffs_usermount *pu = pn->pn_mnt;
pu->pu_pathfree(pu, &pn->pn_po);
/* Removes either from pu_pnodelst or pu_pnode_removed_lst */
LIST_REMOVE(pn, pn_entries);
if ((pn->pn_flags & PUFFS_NODE_REMOVED) == 0)
LIST_REMOVE(pn, pn_entries);
free(pn);
}
@@ -122,32 +126,6 @@ puffs_pn_nodewalk(struct puffs_usermount *pu, puffs_nodewalk_fn fn, void *arg)
return NULL;
}
void*
puffs_pn_nodeprint(struct puffs_usermount *pu, struct puffs_node *pn, void *arg)
{
/* If arg is specified, print only pnodes with inum (should be only one,
* otherwise - all.
*/
if (arg != NULL) {
ino_t inum = *(ino_t*)arg;
if (pn->pn_va.va_fileid != inum) {
return NULL;
}
}
lpuffs_debug(" ino %ld used %d %s\n", pn->pn_va.va_fileid, pn->pn_count,
pn->pn_po.po_path);
/* If arg specified, it should be the only one pnode to be printed,
* but we walk through the rest of list for debugging purposes.
*/
return NULL;
}
void
puffs_pn_nodeprintall(struct puffs_usermount *pu)
{
puffs_pn_nodewalk(pu, puffs_pn_nodeprint, NULL);
}
struct vattr *
puffs_pn_getvap(struct puffs_node *pn)
{
@@ -221,3 +199,27 @@ puffs_newinfo_setrdev(struct puffs_newinfo *pni, dev_t rdev)
*pni->pni_rdev = rdev;
}
void
puffs_newinfo_setva(struct puffs_newinfo *pni, struct vattr *va)
{
(void)memcpy(pni->pni_va, va, sizeof(struct vattr));
}
void
puffs_newinfo_setvattl(struct puffs_newinfo *pni, struct timespec *va_ttl)
{
pni->pni_va_ttl->tv_sec = va_ttl->tv_sec;
pni->pni_va_ttl->tv_nsec = va_ttl->tv_nsec;
}
void
puffs_newinfo_setcnttl(struct puffs_newinfo *pni, struct timespec *cn_ttl)
{
pni->pni_cn_ttl->tv_sec = cn_ttl->tv_sec;
pni->pni_cn_ttl->tv_nsec = cn_ttl->tv_nsec;
}
+53 -5
View File
@@ -1,4 +1,4 @@
.\" $NetBSD: puffs.3,v 1.42.4.2 2009/10/16 12:07:23 sborrill Exp $
.\" $NetBSD: puffs.3,v 1.58 2013/07/20 21:39:57 wiz Exp $
.\"
.\" Copyright (c) 2006, 2007, 2008 Antti Kantee. All rights reserved.
.\"
@@ -23,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd September 6, 2008
.Dd August 16, 2012
.Dt PUFFS 3
.Os
.Sh NAME
@@ -82,12 +82,14 @@
.Ft int
.Fn puffs_mainloop "struct puffs_usermount *pu"
.Ft int
.Fn puffs_unmountonsignal "int sig" "bool ignoresig"
.Ft int
.Fo puffs_dispatch_create
.Fa "struct puffs_usermount *pu" "struct puffs_framebuf *pb"
.Fa "struct puffs_cc **pccp"
.Fc
.Ft int
.Fn puffs_dispatch_exec .Fa "struct puffs_cc *pcc" "struct puffs_framebuf **pbp"
.Fn puffs_dispatch_exec "struct puffs_cc *pcc" "struct puffs_framebuf **pbp"
.Sh DESCRIPTION
.Nm
provides a framework for creating file systems as userspace servers.
@@ -233,6 +235,34 @@ 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.
.It Dv PUFFS_FLAG_PNCOOKIE
Tell puffs that cookies map to
.Vt struct pnode .
This is automagically set if
.Fn puffs_pn_new
is called.
.It Dv PUFFS_KFLAG_CACHE_FS_TTL
Enforce name and attribute caches based on file system-supplied TTL.
In lookup, create, mknod, mkdir, and symlink, the file system must
update the node attributes, their TTL, and the node name TTL through
.Fn puffs_newinfo_setva ,
.Fn puffs_newinfo_setvattl ,
and
.Fn puffs_newinfo_setcnttl .
.Pp
Additionally,
.Fn puffs_node_getattr_ttl
and
.Fn puffs_node_setattr_ttl
will be called instead of
.Fn puffs_node_getattr
and
.Fn puffs_node_setattr .
.It Dv PUFFS_KFLAG_CACHE_DOTDOT
Never send lookups for
.Dq ..
to the filesystem.
Parent vnodes are all kept active until their children are reclaimed.
.It Dv PUFFS_FLAG_OPDUMP
This option makes the framework dump a textual representation of
each operation before executing it.
@@ -426,6 +456,9 @@ This call synchronizes with
.Fn 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
.Em before
.Fn puffs_mount .
.It Fn 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
@@ -435,6 +468,22 @@ In case
.Xr puffs_framebuf 3
has been initialized, I/O from the relevant descriptors is processed
automatically by the eventloop.
.It Fn puffs_unmountonsignal signum ignoresig
Cause all file servers within the process to initiate unmount upon
receipt of signal
.Ar signum .
This works only for servers which call
.Fn 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
.Ar ignoresig
is provided as a convenience and tells if to install a signal handler
to ignore
.Ar sig
so that the process will not e.g. terminate based on the default action
before the file system unmount can be initiated.
.It Fn puffs_dispatch_create pu pb pccp
.It Fn puffs_dispatch_exec pcc pbp
In case the use of
@@ -500,7 +549,6 @@ to provide an alternative cookie-to-node mapping function.
.Xr puffs_node 3 ,
.Xr puffs_ops 3 ,
.Xr puffs_path 3 ,
.Xr puffs_suspend 3 ,
.Xr refuse 3 ,
.Xr puffs 4
.Rs
@@ -539,4 +587,4 @@ first appeared in
A stable version appeared in
.Nx 5.0 .
.Sh AUTHORS
.An Antti Kantee Aq pooka@iki.fi
.An Antti Kantee Aq Mt pooka@iki.fi
+63 -53
View File
@@ -1,4 +1,4 @@
/* $NetBSD: puffs.c,v 1.92.4.4 2009/10/27 20:37:38 bouyer Exp $ */
/* $NetBSD: puffs.c,v 1.117 2011/11/14 01:27:42 chs Exp $ */
/*
* Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved.
@@ -29,37 +29,41 @@
* SUCH DAMAGE.
*/
/* TODO: We don't support PUFFS_COMFD used in original puffs_mount,
* add it to the docs if any.
*
*/
#include "fs.h"
#include <sys/cdefs.h>
#if !defined(lint)
__RCSID("$NetBSD: puffs.c,v 1.92.4.4 2009/10/27 20:37:38 bouyer Exp $");
__RCSID("$NetBSD: puffs.c,v 1.117 2011/11/14 01:27:42 chs Exp $");
#endif /* !lint */
#include <sys/param.h>
#include <sys/mount.h>
#if defined(__minix)
#include "fs.h"
#include <minix/endpoint.h>
#include <minix/vfsif.h>
#endif /* defined(__minix) */
#include <assert.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <mntopts.h>
#include <paths.h>
#include <puffs.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include "puffs.h"
#include "puffs_priv.h"
/* Most file systems want this for opts, so just give it to them */
const struct mntopt puffsmopts[] = {
MOPT_STDOPTS,
PUFFSMOPT_STD,
MOPT_NULL,
};
#ifdef PUFFS_WITH_THREADS
#include <pthread.h>
pthread_mutex_t pu_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -134,10 +138,11 @@ do { \
opmask[PUFFS_VN_##upper] = 1; \
} while (/*CONSTCOND*/0)
static void
fillvnopmask(struct puffs_ops *pops, uint8_t *opmask)
fillvnopmask(struct puffs_ops *pops, struct puffs_kargs *pa)
{
uint8_t *opmask = pa->pa_vnopmask;
memset(opmask, 0, PUFFS_VN_MAX);
memset(opmask, 0, sizeof(pa->pa_vnopmask));
FILLOP(create, CREATE);
FILLOP(mknod, MKNOD);
@@ -146,7 +151,7 @@ fillvnopmask(struct puffs_ops *pops, uint8_t *opmask)
FILLOP(access, ACCESS);
FILLOP(getattr, GETATTR);
FILLOP(setattr, SETATTR);
FILLOP(poll, POLL); /* XXX: not ready in kernel */
FILLOP(poll, POLL);
FILLOP(mmap, MMAP);
FILLOP(fsync, FSYNC);
FILLOP(seek, SEEK);
@@ -190,8 +195,7 @@ puffs_getstate(struct puffs_usermount *pu)
void
puffs_setstacksize(struct puffs_usermount *pu, size_t ss)
{
size_t minsize;
int psize;
long psize, minsize;
int stackshift;
int bonus;
@@ -199,7 +203,7 @@ puffs_setstacksize(struct puffs_usermount *pu, size_t ss)
psize = sysconf(_SC_PAGESIZE);
minsize = 4*psize;
if (ss < minsize || ss == PUFFS_STACKSIZE_MIN) {
if (ss < (size_t)minsize || ss == PUFFS_STACKSIZE_MIN) {
if (ss != PUFFS_STACKSIZE_MIN)
lpuffs_debug("puffs_setstacksize: adjusting "
"stacksize to minimum %ld\n", minsize);
@@ -414,48 +418,50 @@ int
puffs_mount(struct puffs_usermount *pu, const char *dir, int mntflags,
puffs_cookie_t cookie)
{
endpoint_t src;
int error, ind;
#if defined(__minix)
endpoint_t src;
int error, ind;
pu->pu_kargp->pa_root_cookie = cookie;
pu->pu_kargp->pa_root_cookie = cookie;
src = fs_m_in.m_source;
error = OK;
caller_uid = INVAL_UID; /* To trap errors */
caller_gid = INVAL_GID;
req_nr = fs_m_in.m_type;
src = fs_m_in.m_source;
error = OK;
caller_uid = INVAL_UID; /* To trap errors */
caller_gid = INVAL_GID;
req_nr = fs_m_in.m_type;
if (req_nr < FS_BASE) {
fs_m_in.m_type += FS_BASE;
req_nr = fs_m_in.m_type;
if (req_nr < FS_BASE) {
fs_m_in.m_type += FS_BASE;
req_nr = fs_m_in.m_type;
}
ind = req_nr - FS_BASE;
ind = req_nr - FS_BASE;
assert(ind == REQ_READ_SUPER);
assert(ind == REQ_READ_SUPER);
if (ind < 0 || ind >= NREQS) {
error = EINVAL;
} else {
error = (*fs_call_vec[ind])();
}
if (ind < 0 || ind >= NREQS) {
error = EINVAL;
} else {
error = (*fs_call_vec[ind])();
}
fs_m_out.m_type = error;
fs_m_out.m_type = error;
if (IS_VFS_FS_TRANSID(last_request_transid)) {
/* If a transaction ID was set, reset it */
fs_m_out.m_type = TRNS_ADD_ID(fs_m_out.m_type,
last_request_transid);
last_request_transid);
}
reply(src, &fs_m_out);
reply(src, &fs_m_out);
if (error) {
free(pu->pu_kargp);
pu->pu_kargp = NULL;
errno = error;
return -1;
}
if (error) {
free(pu->pu_kargp);
pu->pu_kargp = NULL;
errno = error;
return -1;
}
PU_SETSTATE(pu, PUFFS_STATE_RUNNING);
return 0;
PU_SETSTATE(pu, PUFFS_STATE_RUNNING);
return 0;
#endif /* defined(__minix) */
}
/*ARGSUSED*/
@@ -484,7 +490,7 @@ _puffs_init(int dummy, struct puffs_ops *pops, const char *mntfromname,
goto failfree;
memset(pargs, 0, sizeof(struct puffs_kargs));
pargs->pa_vers = PUFFSDEVELVERS | PUFFSVERSION;
pargs->pa_vers = PUFFSVERSION;
pargs->pa_flags = PUFFS_FLAG_KERN(pflags);
fillvnopmask(pops, pargs->pa_vnopmask);
puffs_setmntinfo(pu, mntfromname, puffsname);
@@ -495,6 +501,10 @@ _puffs_init(int dummy, struct puffs_ops *pops, const char *mntfromname,
pargs->pa_root_vsize = 0;
pargs->pa_root_rdev = 0;
pargs->pa_maxmsglen = 0;
if (/*CONSTCOND*/ sizeof(time_t) == 4)
pargs->pa_time32 = 1;
else
pargs->pa_time32 = 0;
pu->pu_flags = pflags;
buildpath = pu->pu_flags & PUFFS_FLAG_BUILDPATH; /* XXX */
@@ -513,11 +523,11 @@ _puffs_init(int dummy, struct puffs_ops *pops, const char *mntfromname,
/* defaults for some user-settable translation functions */
pu->pu_cmap = NULL; /* identity translation */
pu->pu_pathbuild = puffs_stdpath_buildpath;
pu->pu_pathfree = puffs_stdpath_freepath;
pu->pu_pathcmp = puffs_stdpath_cmppath;
pu->pu_pathtransform = NULL;
pu->pu_namemod = NULL;
pu->pu_pathbuild = puffs_stdpath_buildpath;
pu->pu_pathfree = puffs_stdpath_freepath;
pu->pu_pathcmp = puffs_stdpath_cmppath;
pu->pu_pathtransform = NULL;
pu->pu_namemod = NULL;
pu->pu_errnotify = puffs_defaulterror;
@@ -538,6 +548,7 @@ _puffs_init(int dummy, struct puffs_ops *pops, const char *mntfromname,
void
puffs_cancel(struct puffs_usermount *pu, int error)
{
assert(puffs_getstate(pu) < PUFFS_STATE_RUNNING);
free(pu);
}
@@ -628,7 +639,6 @@ puffs__theloop(struct puffs_cc *pcc)
* Now we just return to the caller.
*/
}
int
puffs_mainloop(struct puffs_usermount *pu)
{
@@ -669,7 +679,7 @@ puffs_mainloop(struct puffs_usermount *pu)
return 0;
}
#if defined(__minix)
/*===========================================================================*
* sef_local_startup *
*===========================================================================*/
@@ -772,4 +782,4 @@ static void reply(
last_request_transid = 0;
}
#endif /* defined(__minix) */
+86 -108
View File
@@ -1,4 +1,4 @@
/* $NetBSD: puffs.h,v 1.108.4.4 2009/10/27 20:37:38 bouyer Exp $ */
/* $NetBSD: puffs.h,v 1.124 2012/08/16 09:25:44 manu Exp $ */
/*
* Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved.
@@ -35,100 +35,17 @@
#include <sys/param.h>
#include <sys/types.h>
#include <sys/mount.h>
#include <sys/namei.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/time.h>
#include <sys/queue.h>
#include <sys/vnode.h>
#include "puffs_msgif.h"
#include <fs/puffs/puffs_msgif.h>
#include <mntopts.h>
#include <time.h>
#include <stdbool.h>
#include <string.h>
#include <stdint.h>
#include <dirent.h>
/* MINIX forwards */
struct flock;
struct dirent;
/* XXX: from sys/fstypes.h
* Flags for various system call interfaces.
*
* waitfor flags to vfs_sync() and getvfsstat()
*/
#define MNT_WAIT 1 /* synchronously wait for I/O to complete */
#define MNT_NOWAIT 2 /* start all I/O, but do not wait for it */
#define MNT_LAZY 3 /* push data not written by filesystem syncer */
#define MNT_RDONLY 0x00000001 /* read only filesystem */
#define MNT_SYNCHRONOUS 0x00000002 /* file system written synchronously */
#define MNT_NOEXEC 0x00000004 /* can't exec from filesystem */
#define MNT_NOSUID 0x00000008 /* don't honor setuid bits on fs */
#define MNT_NODEV 0x00000010 /* don't interpret special files */
#define MNT_UNION 0x00000020 /* union with underlying filesystem */
#define MNT_ASYNC 0x00000040 /* file system written asynchronously */
#define MNT_NOCOREDUMP 0x00008000 /* don't write core dumps to this FS */
#define MNT_IGNORE 0x00100000 /* don't show entry in df */
#define MNT_LOG 0x02000000 /* Use logging */
#define MNT_NOATIME 0x04000000 /* Never update access times in fs */
#define MNT_SYMPERM 0x20000000 /* recognize symlink permission */
#define MNT_NODEVMTIME 0x40000000 /* Never update mod times for devs */
#define MNT_SOFTDEP 0x80000000 /* Use soft dependencies */
/* XXX from machine/param.h */
#define DEV_BSHIFT 9 /* log2(DEV_BSIZE) */
#define DEV_BSIZE (1 << DEV_BSHIFT)
/* FIXME: move?
* some stuff from sys/dirent.h.
*/
#define DT_UNKNOWN 0
#define DT_FIFO 1
#define DT_CHR 2
#define DT_DIR 4
#define DT_BLK 6
#define DT_REG 8
#define DT_LNK 10
#define DT_SOCK 12
#define DT_WHT 14
/*
* The _DIRENT_ALIGN macro returns the alignment of struct dirent.
* struct direct and struct dirent12 used 4 byte alignment but
* struct dirent uses 8.
*/
/* FIXME: in mfs code sizeof(long) and not d_ino */
#undef _DIRENT_ALIGN
#define _DIRENT_ALIGN(dp) (sizeof((dp)->d_ino) - 1)
/*
* The _DIRENT_NAMEOFF macro returns the offset of the d_name field in
* struct dirent
*/
#define _DIRENT_NAMEOFF(dp) \
((char *)(void *)&(dp)->d_name - (char *)(void *)dp)
/*
* The _DIRENT_RECLEN macro gives the minimum record length which will hold
* a name of size "namlen". This requires the amount of space in struct dirent
* without the d_name field, plus enough space for the name with a terminating
* null byte (namlen+1), rounded up to a the appropriate byte boundary.
*/
/* FIXME */
#undef _DIRENT_RECLEN
#define _DIRENT_RECLEN(dp, namlen) \
((_DIRENT_NAMEOFF(dp) + (namlen) + 1 + _DIRENT_ALIGN(dp)) & \
~_DIRENT_ALIGN(dp))
/*
* The _DIRENT_NEXT macro advances to the next dirent record.
*/
#define _DIRENT_NEXT(dp) ((void *)((char *)(void *)(dp) + (dp)->d_reclen))
/* forwards */
struct puffs_cc;
@@ -162,6 +79,7 @@ struct puffs_kcache {
struct puffs_node {
off_t pn_size;
int pn_flags;
int pn_nlookup;
struct vattr pn_va;
void *pn_data; /* private data */
@@ -172,11 +90,11 @@ struct puffs_node {
LIST_ENTRY(puffs_node) pn_entries;
LIST_HEAD(,puffs_kcache)pn_cacheinfo; /* PUFFS_KFLAG_CACHE */
#if defined(__minix)
/* MINIX fields */
char pn_mountpoint; /* true if mounted on */
int pn_count; /* # times inode used */
#endif /* defined(__minix) */
};
#define PUFFS_NODE_REMOVED 0x01 /* not on entry list */
@@ -199,6 +117,13 @@ struct puffs_usermount;
#define PUFFS_FSYNC_DATAONLY 0x0002
#define PUFFS_FSYNC_CACHE 0x0100
/*
* xflags for setattr_ttl and write2
*/
#define PUFFS_SETATTR_FAF 0x1
#define PUFFS_WRITE_FAF 0x1
#define PUFFS_EXTATTR_LIST_LENPREFIX 1
/*
* Magic constants
*/
@@ -222,6 +147,7 @@ struct puffs_cn {
/* kernel */
#define PUFFSMOPT_NAMECACHE { "namecache", 1, PUFFS_KFLAG_NOCACHE_NAME, 1 }
#define PUFFSMOPT_PAGECACHE { "pagecache", 1, PUFFS_KFLAG_NOCACHE_PAGE, 1 }
#define PUFFSMOPT_ATTRCACHE { "attrcache", 1, PUFFS_KFLAG_NOCACHE_ATTR, 1 }
#define PUFFSMOPT_CACHE { "cache", 1, PUFFS_KFLAG_NOCACHE, 1 }
#define PUFFSMOPT_ALLOPS { "allops", 0, PUFFS_KFLAG_ALLOPS, 1 }
@@ -231,6 +157,7 @@ struct puffs_cn {
#define PUFFSMOPT_STD \
PUFFSMOPT_NAMECACHE, \
PUFFSMOPT_PAGECACHE, \
PUFFSMOPT_ATTRCACHE, \
PUFFSMOPT_CACHE, \
PUFFSMOPT_ALLOPS, \
PUFFSMOPT_DUMP
@@ -247,7 +174,8 @@ struct puffs_ops {
struct puffs_newinfo *);
int (*puffs_fs_nodetofh)(struct puffs_usermount *, puffs_cookie_t,
void *, size_t *);
void (*puffs_fs_suspend)(struct puffs_usermount *, int);
int (*puffs_fs_extattrctl)(struct puffs_usermount *, int,
puffs_cookie_t, int, int, const char *);
int (*puffs_node_lookup)(struct puffs_usermount *,
puffs_cookie_t, struct puffs_newinfo *, const struct puffs_cn *);
@@ -299,7 +227,7 @@ struct puffs_ops {
int (*puffs_node_inactive)(struct puffs_usermount *, puffs_cookie_t);
int (*puffs_node_print)(struct puffs_usermount *, puffs_cookie_t);
int (*puffs_node_pathconf)(struct puffs_usermount *,
puffs_cookie_t, int, int *);
puffs_cookie_t, int, register_t *);
int (*puffs_node_advlock)(struct puffs_usermount *,
puffs_cookie_t, void *, int, struct flock *, int);
int (*puffs_node_read)(struct puffs_usermount *, puffs_cookie_t,
@@ -308,11 +236,27 @@ struct puffs_ops {
uint8_t *, off_t, size_t *, const struct puffs_cred *, int);
int (*puffs_node_abortop)(struct puffs_usermount *, puffs_cookie_t,
const struct puffs_cn *);
int (*puffs_node_getextattr)(struct puffs_usermount *, puffs_cookie_t,
int, const char *, size_t *, uint8_t *, size_t *,
const struct puffs_cred *);
int (*puffs_node_setextattr)(struct puffs_usermount *, puffs_cookie_t,
int, const char *, uint8_t *, size_t *, const struct puffs_cred *);
int (*puffs_node_listextattr)(struct puffs_usermount *, puffs_cookie_t,
int, size_t *, uint8_t *, size_t *, int, const struct puffs_cred *);
int (*puffs_node_deleteextattr)(struct puffs_usermount *,
puffs_cookie_t, int, const char *, const struct puffs_cred *);
int (*puffs_node_getattr_ttl)(struct puffs_usermount *,
puffs_cookie_t, struct vattr *, const struct puffs_cred *,
struct timespec *);
int (*puffs_node_setattr_ttl)(struct puffs_usermount *,
puffs_cookie_t, struct vattr *, const struct puffs_cred *,
struct timespec *, int);
int (*puffs_node_write2)(struct puffs_usermount *, puffs_cookie_t,
uint8_t *, off_t, size_t *, const struct puffs_cred *, int, int);
int (*puffs_node_reclaim2)(struct puffs_usermount *,
puffs_cookie_t, int);
#if 0
/* enable next time this structure is changed */
void *puffs_ops_spare[32];
#endif
void *puffs_ops_spare[28];
};
typedef int (*pu_pathbuild_fn)(struct puffs_usermount *,
@@ -346,7 +290,8 @@ enum {
#define PUFFS_FLAG_BUILDPATH 0x80000000 /* node paths in pnode */
#define PUFFS_FLAG_OPDUMP 0x40000000 /* dump all operations */
#define PUFFS_FLAG_HASHPATH 0x20000000 /* speedup: hash paths */
#define PUFFS_FLAG_MASK 0xe0000000
#define PUFFS_FLAG_PNCOOKIE 0x10000000 /* cookies are pnodes */
#define PUFFS_FLAG_MASK 0xf0000000
#define PUFFS_FLAG_KERN(a) ((a) & PUFFS_KFLAG_MASK)
#define PUFFS_FLAG_LIB(a) ((a) & PUFFS_FLAG_MASK)
@@ -377,7 +322,8 @@ enum {
size_t, struct puffs_newinfo *); \
int fsname##_fs_nodetofh(struct puffs_usermount *, \
puffs_cookie_t, void *, size_t *); \
void fsname##_fs_suspend(struct puffs_usermount *, int); \
int fsname##_fs_extattrctl(struct puffs_usermount *, int, \
puffs_cookie_t, int, int, const char *); \
\
int fsname##_node_lookup(struct puffs_usermount *, \
puffs_cookie_t, struct puffs_newinfo *, \
@@ -437,7 +383,7 @@ enum {
int fsname##_node_print(struct puffs_usermount *, \
puffs_cookie_t); \
int fsname##_node_pathconf(struct puffs_usermount *, \
puffs_cookie_t, int, int *); \
puffs_cookie_t, int, register_t *); \
int fsname##_node_advlock(struct puffs_usermount *, \
puffs_cookie_t, void *, int, struct flock *, int); \
int fsname##_node_read(struct puffs_usermount *, puffs_cookie_t,\
@@ -446,7 +392,31 @@ enum {
puffs_cookie_t, uint8_t *, off_t, size_t *, \
const struct puffs_cred *, int); \
int fsname##_node_abortop(struct puffs_usermount *, \
puffs_cookie_t, const struct puffs_cn *);
puffs_cookie_t, const struct puffs_cn *); \
int fsname##_node_getextattr(struct puffs_usermount *, \
puffs_cookie_t, int, const char *, size_t *, uint8_t *, \
size_t *, const struct puffs_cred *); \
int fsname##_node_setextattr(struct puffs_usermount *, \
puffs_cookie_t, int, const char *, uint8_t *, size_t *, \
const struct puffs_cred *); \
int fsname##_node_listextattr(struct puffs_usermount *, \
puffs_cookie_t, int, size_t *, uint8_t *, size_t *, \
int, const struct puffs_cred *); \
int fsname##_node_deleteextattr(struct puffs_usermount *, \
puffs_cookie_t, int, const char *, \
const struct puffs_cred *); \
int fsname##_node_getattr_ttl(struct puffs_usermount *, \
puffs_cookie_t, struct vattr *, const struct puffs_cred *, \
struct timespec *); \
int fsname##_node_setattr_ttl(struct puffs_usermount *, \
puffs_cookie_t, struct vattr *, const struct puffs_cred *, \
struct timespec *, int); \
int fsname##_node_write2(struct puffs_usermount *, \
puffs_cookie_t, uint8_t *, off_t, size_t *, \
const struct puffs_cred *, int, int); \
int fsname##_node_reclaim2(struct puffs_usermount *, \
puffs_cookie_t, int);
#define PUFFSOP_INIT(ops) \
ops = malloc(sizeof(struct puffs_ops)); \
@@ -458,11 +428,6 @@ enum {
PUFFSOP_PROTOS(puffs_null) /* XXX */
#define PUFFS_DEVEL_LIBVERSION 34
#define puffs_init(a,b,c,d,e) \
_puffs_init(PUFFS_DEVEL_LIBVERSION,a,b,c,d,e)
#define PNPATH(pnode) ((pnode)->pn_po.po_path)
#define PNPLEN(pnode) ((pnode)->pn_po.po_len)
#define PCNPATH(pcnode) ((pcnode)->pcn_po_full.po_path)
@@ -507,14 +472,19 @@ typedef void (*puffs_framev_cb)(struct puffs_usermount *,
__BEGIN_DECLS
#define PUFFS_DEFER ((void *)-1)
struct puffs_usermount *_puffs_init(int, struct puffs_ops *, const char *,
struct puffs_usermount *puffs_init(struct puffs_ops *, const char *,
const char *, void *, uint32_t);
int puffs_mount(struct puffs_usermount *, const char *, int, void*);
int puffs_exit(struct puffs_usermount *, int);
void puffs_cancel(struct puffs_usermount *, int);
int puffs_mainloop(struct puffs_usermount *);
int puffs_daemon(struct puffs_usermount *, int, int);
int puffs_unmountonsignal(int, bool);
int puffs_getselectable(struct puffs_usermount *);
int puffs_setblockingmode(struct puffs_usermount *, int);
int puffs_getstate(struct puffs_usermount *);
void puffs_setstacksize(struct puffs_usermount *, size_t);
@@ -539,6 +509,8 @@ void puffs_setncookiehash(struct puffs_usermount *, int);
struct puffs_pathobj *puffs_getrootpathobj(struct puffs_usermount *);
void puffs_setback(struct puffs_cc *, int);
struct puffs_node *puffs_pn_new(struct puffs_usermount *, void *);
void puffs_pn_remove(struct puffs_node *);
void puffs_pn_put(struct puffs_node *);
@@ -547,11 +519,16 @@ void * puffs_pn_getpriv(struct puffs_node *);
void puffs_pn_setpriv(struct puffs_node *, void *);
struct puffs_pathobj *puffs_pn_getpo(struct puffs_node *);
struct puffs_usermount *puffs_pn_getmnt(struct puffs_node *);
struct timespec *puffs_pn_getvattl(struct puffs_node *);
struct timespec *puffs_pn_getcnttl(struct puffs_node *);
void puffs_newinfo_setcookie(struct puffs_newinfo *, puffs_cookie_t);
void puffs_newinfo_setvtype(struct puffs_newinfo *, enum vtype);
void puffs_newinfo_setsize(struct puffs_newinfo *, voff_t);
void puffs_newinfo_setrdev(struct puffs_newinfo *, dev_t);
void puffs_newinfo_setva(struct puffs_newinfo *, struct vattr *);
void puffs_newinfo_setvattl(struct puffs_newinfo *, struct timespec *);
void puffs_newinfo_setcnttl(struct puffs_newinfo *, struct timespec *);
void *puffs_pn_getmntspecific(struct puffs_node *);
@@ -559,9 +536,6 @@ typedef void * (*puffs_nodewalk_fn)(struct puffs_usermount *,
struct puffs_node *, void *);
void *puffs_pn_nodewalk(struct puffs_usermount *,
puffs_nodewalk_fn, void *);
void *puffs_pn_nodeprint(struct puffs_usermount *pu,
struct puffs_node *pn, void *arg);
void puffs_pn_nodeprintall(struct puffs_usermount *pu);
void puffs_setvattr(struct vattr *, const struct vattr *);
void puffs_vattr_null(struct vattr *);
@@ -677,6 +651,10 @@ void puffs_set_pathfree(struct puffs_usermount *, pu_pathfree_fn);
void puffs_set_namemod(struct puffs_usermount *, pu_namemod_fn);
void puffs_set_errnotify(struct puffs_usermount *, pu_errnotify_fn);
void puffs_kernerr_log(struct puffs_usermount *, uint8_t, int,
const char *, puffs_cookie_t);
__dead void puffs_kernerr_abort(struct puffs_usermount *, uint8_t, int,
const char *, puffs_cookie_t);
void puffs_set_prepost(struct puffs_usermount *,
pu_prepost_fn, pu_prepost_fn);
void puffs_set_cmap(struct puffs_usermount *, pu_cmap_fn);
+3 -2
View File
@@ -1,4 +1,4 @@
.\" $NetBSD: puffs_cc.3,v 1.12.4.1 2009/02/24 03:45:56 snj Exp $
.\" $NetBSD: puffs_cc.3,v 1.14 2009/04/11 16:48:53 wiz Exp $
.\"
.\" Copyright (c) 2007, 2008 Antti Kantee. All rights reserved.
.\"
@@ -83,7 +83,8 @@ own internal bookkeeping.
This cookie should be hooked to the
.Va pcc
so that the correct continuation can be continued when the event it
was waiting for triggers. Alternatively, the
was waiting for triggers.
Alternatively, the
.Xr puffs_framebuf 3
framework and
.Fn puffs_mainloop
+2 -2
View File
@@ -1,4 +1,4 @@
.\" $NetBSD: puffs_cred.3,v 1.3.12.1 2009/02/24 03:45:56 snj Exp $
.\" $NetBSD: puffs_cred.3,v 1.5 2009/04/11 15:36:22 joerg Exp $
.\"
.\" Copyright (c) 2007 Antti Kantee. All rights reserved.
.\"
@@ -34,7 +34,7 @@
.Sh SYNOPSIS
.In puffs.h
.Ft int
.Fn puffs_cred_getuid "const struct puffs_cred *pcr" "uid_t *uid
.Fn puffs_cred_getuid "const struct puffs_cred *pcr" "uid_t *uid"
.Ft int
.Fn puffs_cred_getgid "const struct puffs_cred *pcr" "gid_t *gid"
.Ft int
+113
View File
@@ -0,0 +1,113 @@
.\" $NetBSD: puffs_flush.3,v 1.8 2009/02/20 14:26:56 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 7, 2007
.Dt PUFFS_FLUSH 3
.Os
.Sh NAME
.Nm puffs_flush
.Nd puffs kernel cache flushing and invalidation routines
.Sh LIBRARY
.Lb libpuffs
.Sh SYNOPSIS
.In puffs.h
.Ft int
.Fo puffs_inval_namecache_dir
.Fa "struct puffs_usermount *pu" "puffs_cookie_t cookie"
.Fc
.Ft int
.Fn puffs_inval_namecache_all "struct puffs_usermount *pu"
.Ft int
.Fo puffs_inval_pagecache_node
.Fa "struct puffs_usermount *pu" "puffs_cookie_t cookie"
.Fc
.Ft int
.Fo puffs_inval_pagecache_node_range
.Fa "struct puffs_usermount *pu" "puffs_cookie_t cookie" "off_t start"
.Fa "off_t end"
.Fc
.Ft int
.Fo puffs_flush_pagecache_node
.Fa "struct puffs_usermount *pu" "puffs_cookie_t cookie"
.Fc
.Ft int
.Fo puffs_flush_pagecache_node_range
.Fa "struct puffs_usermount *pu" "puffs_cookie_t cookie" "off_t start"
.Fa "off_t end"
.Fc
.Sh DESCRIPTION
These routines are used inform the kernel that any information it might
have cached is no longer valid.
.Fn puffs_inval_namecache_dir
invalidates the name cache for a given directory.
The argument
.Va cookie
should describe an existing and valid directory cookie for the file
system.
Similarly,
.Fn puffs_inval_namecache_all
invalidates the name cache for the entire file system
(this routine might go away).
.Pp
The cached pages (file contents) for a regular file described by
.Va cookie
are invalidated using
.Fn puffs_inval_pagecache_node .
A specific range can be invalidated using
.Fn puffs_inval_pagecache_node_range
for a platform specific page level granularity.
The offset
.Va start
will be
.Em truncated
to a page boundary while
.Va end
will be
.Em "rounded up"
to the next page boundary.
As a special case, specifying 0 as
.Va end
will invalidate all contents from
.Va start
to the end of the file.
.Pp
It is especially important to note that these routines will not only
invalidate data in the "read cache", but also data in the "write back"
cache (conceptually speaking; in reality they are the same cache), which
has not yet been flushed to the file server.
Therefore any unflushed data will be lost.
.Pp
The counterparts of the invalidation routines are the flushing routines
.Fn puffs_flush_pagecache_node
and
.Fn puffs_flush_pagecache_node_range ,
which force unwritten data from the kernel page cache to be written.
For the flush range version, the same range rules as with the
invalidation routine apply.
The data is flushed asynchronously, i.e. if the routine returns
successfully, all the caller knows is that the data has been queued
for writing.
.Sh SEE ALSO
.Xr puffs 3
+620
View File
@@ -0,0 +1,620 @@
.\" $NetBSD: puffs_framebuf.3,v 1.29 2010/04/01 09:57:00 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 September 6, 2008
.Dt PUFFS_FRAMEBUF 3
.Os
.Sh NAME
.Nm puffs_framebuf
.Nd buffering and event handling for networked file systems
.Sh LIBRARY
.Lb libpuffs
.Sh SYNOPSIS
.In puffs.h
.Ft struct puffs_framebuf *
.Fn puffs_framebuf_make
.Ft void
.Fn puffs_framebuf_destroy "struct puffs_framebuf *pufbuf"
.Ft void
.Fn puffs_framebuf_recycle "struct puffs_framebuf *pufbuf"
.Ft int
.Fn puffs_framebuf_reserve_space "struct puffs_framebuf *pufbuf" "size_t space"
.Ft int
.Fo puffs_framebuf_putdata
.Fa "struct puffs_framebuf *pufbuf" "const void *data" "size_t dlen"
.Fc
.Ft int
.Fo puffs_framebuf_putdata_atoff
.Fa "struct puffs_framebuf *pufbuf" "size_t offset" "const void *data"
.Fa "size_t dlen"
.Fc
.Ft int
.Fo puffs_framebuf_getdata
.Fa "struct puffs_framebuf *pufbuf" "void *data" "size_t dlen"
.Fc
.Ft int
.Fo puffs_framebuf_getdata_atoff
.Fa "struct puffs_framebuf *pufbuf" "size_t offset"
.Fa "void *data" "size_t dlen"
.Fc
.Ft size_t
.Fn puffs_framebuf_telloff "struct puffs_framebuf *pufbuf"
.Ft size_t
.Fn puffs_framebuf_tellsize "struct puffs_framebuf *pufbuf"
.Ft size_t
.Fn puffs_framebuf_remaining "struct puffs_framebuf *pufbuf"
.Ft int
.Fn puffs_framebuf_seekset "struct puffs_framebuf *pufbuf" "size_t offset"
.Ft int
.Fo puffs_framebuf_getwindow
.Fa "struct puffs_framebuf *pufbuf" "size_t offset"
.Fa "void **winp" "size_t *winlen"
.Fc
.Ft int
.Fo puffs_framev_enqueue_cc
.Fa "struct puffs_cc *pcc" "int fd" "struct puffs_framebuf *pufbuf" "int flags"
.Fc
.Ft void
.Fo puffs_framev_cb
.Fa "struct puffs_usermount *pu" "int fd" "struct puffs_framebuf *pufbuf"
.Fa "void *arg" "int flags"
.Fa "int error"
.Fc
.Ft void
.Fo puffs_framev_enqueue_cb
.Fa "struct puffs_usermount *pu" "int fd" "struct puffs_framebuf *pufbuf"
.Fa "puffs_framebuf_cb fcb" "void *fcb_arg" "int flags"
.Fc
.Ft void
.Fo puffs_framev_enqueue_justsend
.Fa "struct puffs_usermount *pu" "int fd" "struct puffs_framebuf *pufbuf"
.Fa "int waitreply" "int flags"
.Fc
.Ft void
.Fo puffs_framev_enqueue_directsend
.Fa "struct puffs_usermount *pu" "int fd" "struct puffs_framebuf *pufbuf"
.Fa "int flags"
.Fc
.Ft void
.Fo puffs_framev_enqueue_directreceive
.Fa "struct puffs_usermount *pu" "int fd" "struct puffs_framebuf *pufbuf"
.Fa "int flags"
.Fc
.Ft int
.Fo puffs_framev_framebuf_ccpromote
.Fa "struct puffs_framebuf *pufbuf" "struct puffs_cc *pcc"
.Fc
.Ft int
.Fn puffs_framev_enqueue_waitevent "struct puffs_cc *pcc" "int fd" "int *what"
.Ft int
.Fo puffs_framev_readframe_fn
.Fa "struct puffs_usermount *pu" "struct puffs_framebuf *pufbuf"
.Fa "int fd" "int *done"
.Fc
.Ft int
.Fo puffs_framev_writeframe_fn
.Fa "struct puffs_usermount *pu" "struct puffs_framebuf *pufbuf"
.Fa "int fd" "int *done"
.Fc
.Ft int
.Fo puffs_framev_cmpframe_fn
.Fa "struct puffs_usermount *pu"
.Fa "struct puffs_framebuf *cmp1" "struct puffs_framebuf *cmp2" "int *notresp"
.Fc
.Ft void
.Fo puffs_framev_gotframe_fn
.Fa "struct puffs_usermount *pu" "struct puffs_framebuf *pufbuf"
.Fc
.Ft void
.Fo puffs_framev_fdnotify_fn
.Fa "struct puffs_usermount *pu" "int fd" "int what"
.Fc
.Ft void
.Fo puffs_framev_init
.Fa "struct puffs_usermount *pu"
.Fa "puffs_framev_readframe_fn rfb" "puffs_framev_writeframe_fn wfb"
.Fa "puffs_framev_cmpframe_fn cmpfb" "puffs_framev_gotframe_fn gotfb"
.Fa "puffs_framev_fdnotify_fn fdnotfn"
.Fc
.Ft int
.Fn puffs_framev_addfd "struct puffs_usermount *pu" "int fd" "int what"
.Ft int
.Fn puffs_framev_enablefd "struct puffs_usermount *pu" "int fd" "int what"
.Ft int
.Fn puffs_framev_disablefd "struct puffs_usermount *pu" "int fd" "int what"
.Ft int
.Fn puffs_framev_removefd "struct puffs_usermount *pu" "int fd" "int error"
.Ft void
.Fo puffs_framev_unmountonclose
.Fa "struct puffs_usermount *pu" "int fd" "int what"
.Fc
.Sh DESCRIPTION
The
.Nm
routines provide buffering and an event loop structured around the
buffers.
It operates on top of the puffs continuation framework,
.Xr puffs_cc 3 ,
and multiplexes execution automatically to an instance whenever
one is runnable.
.Pp
The file system is entered in three different ways:
.Bl -bullet -offset indent
.It
An event arrives from the kernel and the
.Xr puffs_ops 3
callbacks are called to start processing the event.
.It
A file system which has sent out a request receives a response.
Execution is resumed from the place where the file system yielded.
.It
A request from a peer arrives.
A request is an incoming PDU which is not a response to any outstanding
request.
.El
.Pp
.Nm
is used by defining various callbacks and providing I/O descriptors,
which are then monitored for activity by the library.
A descriptor, when present, can be either enabled or disabled for
input and output.
If a descriptor is not enabled for a certain direction, the callbacks
will not be called even if there were activity on the descriptor.
For example, even if a network socket has been added and there is
input data in the socket buffer, the read callback will be called
only if the socket has been enabled for reading.
.Pp
File descriptors are treated like sockets: they have two sides, a read
side and a write side.
The framework determines that one side of the descriptor has been
closed if the supplied I/O callbacks return an error or if the I/O
multiplexing call says a side has been closed.
It is still possible, from the framework perspective, to write to a
file descriptor whose read side is closed.
However, it is not possible to wait for a response on such a file
descriptor.
Conversely, it is possible to read responses from a descriptor whose
write side is closed.
It should be stressed that the implementation underlying the file
descriptor might not support this.
.Pp
The following callbacks can be defined, cf.
.Fn puffs_framev_init ,
and all are optional.
None of them should block, because this would cause the entire file server
to block.
One option is to make the descriptors non-blocking before adding them.
.Bl -tag -width "xfdnotfnx"
.It rfb
Read a frame from the file descriptor onto the specified buffer.
.It wfb
Write a frame from the specified buffer into the file descriptor.
.It cmpfb
Identify if a buffer is the response to the specified buffer.
.It gotfb
Called iff no outstanding request matches the incoming frame.
In other words, this is called when we receive a request from a peer.
.It fdnotfn
Receive notifications about a change-of-state in a file descriptor's
status.
.El
.Pp
Better descriptions for each callback are given below.
.Pp
The buffers of
.Nm
provide automatic memory management of buffers for the file servers.
They provide a cursor to the current buffer offset.
Reading or writing data through the normal routines will advance that cursor.
Additionally, the buffer size is provided to the user.
It represents the maximum offset where data was written.
.Pp
Generally the write functions will fail if the cannot allocate enough
memory to satisfy the buffer length requirements.
Read functions will fail if the amount of data written to the buffer
is not large enough to satisfy the read.
.Bl -tag -width xxxx
.It Fn puffs_framebuf_make
Create a buffer.
Return the address of the buffer or
.Dv NULL
in case no memory was available.
.It Fn puffs_framebuf_destroy pufbuf
Free memory used by buffer.
.It Fn puffs_framebuf_recycle pufbuf
Reset offsets so that buffer can be reused.
Does not free memory or reallocate memory.
.It Fn puffs_framebuf_reserve_space pufbuf space
Make sure that the buffer has
.Ar space
bytes of available memory starting from the current offset.
This is not strictly necessary, but can be used for optimizations
where it is known in advance how much memory will be required.
.It Fn puffs_framebuf_putdata pufbuf data dlen
Write
.Ar dlen
amount of data from the address
.Ar data
into the buffer.
Moves the offset cursor forward
.Ar dlen
bytes.
.It Fn puffs_framebuf_putdata_atoff pufbuf offset data dlen
Like
.Fn puffs_framebuf_putdata ,
except writes data at buffer offset
.Ar offset .
It is legal to write past the current end of the buffer.
Does NOT modify the current offset cursor.
.It Fn puffs_framebuf_getdata pufbuf data dlen
Read
.Ar dlen
bytes of data from the buffer into
.Ar data .
Advances the offset cursor.
.It Fn puffs_framebuf_getdata_atoff pufbuf offset data dlen
Read data from buffer position
.Ar offset .
Does NOT modify the offset cursor.
.It Fn puffs_framebuf_telloff pufbuf
Return the offset into the buffer.
.It Fn puffs_framebuf_tellsize pufbuf
Return the maximum offset where data has been written, i.e. buffer size.
.It Fn puffs_framebuf_remaining pufbuf
Distance from current offset to the end of the buffer, i.e. size-offset.
.It Fn puffs_framebuf_seekset pufbuf offset
Set the offset cursor to the position
.Ar offset .
This does NOT modify the buffer size, but reserves at least
enough memory memory for a write to
.Ar offset
and will fail if memory cannot be allocated.
.It Fn puffs_framebuf_getwindow pufbuf offset winp winlen
Get a direct memory window into the buffer starting from
.Ar offset .
The maximum mapped window size will be
.Ar winlen
bytes, but this routine might return a smaller window and the caller
should always check the actual mapped size after the call.
The window is returned in
.Ar winp .
This function not modify the buffer offset, but it DOES set the buffer
size to
.Ar offset +
.Ar winlen
in case that value is greater than the current size.
The window is valid until the next until the next
.Fn puffs_framebuf
call operating on the buffer in question.
.It Fn puffs_framev_enqueue_cc pcc fd pufbuf flags
Add the buffer
.Ar pufbuf
to outgoing queue of descriptor
.Ar fd
and yield with the continuation
.Ar pcc .
Execution is resumed once a response is received.
Returns 0 if the buffer was successfully enqueued (not necessarily
delivered) and non-zero to signal a non-recoverable error.
.Pp
Usually the buffer is placed at the end of the output queue.
However, if
.Ar flags
contains
.Dv PUFFS_FBQUEUE_URGENT ,
.Ar pufbuf
is placed in the front of the queue to be sent immediately after
the current PDU (if any) has been sent.
.It Fn puffs_framev_enqueue_cb pu fd pufbuf fcb fcb_arg flags
Enqueue the buffer
.Ar pufbuf
for outgoing data and immediately return.
Once a response arrives, the callback
.Fn fcb
will be called with the argument
.Ar fcb_arg .
The callback function
.Fn fcb
is responsible for freeing the buffer.
Returns 0 if the buffer was successfully enqueued (not necessarily
delivered) and non-zero to signal a non-recoverable error.
.Pp
See
.Fn puffs_framev_enqueue_cc
for
.Ar flags .
.It Fn puffs_framev_cb pu pufbuf arg error
Callback function.
Called when a response to a specific request arrives from the server.
If
.Ar error
is non-zero, the framework was unable to obtain a response and the
function should not examine the contents of
.Ar pufbuf ,
only do resource cleanup.
May not block.
.It Fn puffs_framev_enqueue_justsend pu fd pufbuf waitreply flags
Enqueue the buffer
.Ar pufbuf
for outgoing traffic and immediately return.
The parameter
.Ar waitreply
can be used to control if the buffer is to be freed immediately after
sending of if a response is expected and the buffer should be freed
only after the response arrives (receiving an unexpected message from
the server is treated as an error).
Returns 0 if the buffer was successfully enqueued (not necessarily
delivered) and non-zero to signal a non-recoverable error.
.Pp
See
.Fn puffs_framev_enqueue_cc
for
.Ar flags .
.It Fn puffs_framev_enqueue_directsend pcc fd pufbuf flags
Acts like
.Fn puffs_framev_enqueue_justsend
with the exception that the call yields until the frame has been sent.
As opposed to
.Fn puffs_framev_enqueue_cc ,
the routine does not wait for input, but returns immediately after
sending the frame.
.Pp
See
.Fn puffs_framev_enqueue_cc
for
.Ar flags .
.It Fn puffs_framev_enqueue_directreceive pcc fd pufbuf flags
Receive data into
.Ar pufbuf .
This routine yields until a complete frame has been read into
the buffer by the readframe routine.
.Pp
See
.Fn puffs_framev_enqueue_cc
for
.Ar flags .
.It Fn puffs_framev_framebuf_ccpromote pufbuf pcc
Promote the framebuffer
.Ar pufbuf
sent with
.Fn puffs_framev_enqueue_cb
or
.Fn puffs_framev_enqueue_justsend
to a wait using
.Ar pcc
and yield until the result arrives.
The response from the file server for
.Ar pufbuf
must not yet have arrived.
If sent with
.Fn puffs_framev_enqueue_justsend ,
the call must be expecting a response.
.It Fn puffs_framev_enqueue_waitevent pcc fd what
Waits for an event in
.Ar what
to happen on file descriptor
.Ar fd .
The events which happened are returned back in
.Ar what .
The possible events are
.Dv PUFFS_FBIO_READ ,
.Dv PUFFS_FBIO_WRITE ,
and
.Dv PUFFS_FBIO_ERROR ,
specifying read, write and error conditions, respectively.
Error is always checked.
.Pp
This call does not depend on if the events were previously enabled on
the file descriptor - the specified events are always checked
regardless.
.Pp
There is currently no other way to cancel or timeout a call except by
removing the file descriptor in question.
This may change in the future.
.It Fn puffs_framev_readframe_fn pu pufbuf fd done
Callback function.
Read at most one frame from file descriptor
.Ar fd
into the buffer
.Ar pufbuf .
If a complete frame is read, the value pointed to by
.Ar done
must be set to 1.
This function should return 0 on success (even if a complete frame was not
yet read) and a non-zero
.Er errno
to signal a fatal error.
In case a fatal error is returned, the read side of the file descriptor
is marked closed.
This routine will be called with the same buffer argument until a
complete frame has been read.
May not block.
.It Fn puffs_framev_writeframe_fn pu pufbuf fd done
Write the frame contained in
.Ar pufbuf
to the file descriptor
.Ar fd .
In case the entire frame is successfully written,
.Ar *done
should be set to 1.
This function should return 0 on success (even if a complete frame was not
yet written) and a non-zero
.Er errno
to signal a fatal error.
In case a fatal error is returned, the write side of the file descriptor
is marked closed.
This routine will be called with the same buffer argument until the
complete frame has been written.
May not block.
.Pp
It is a good idea to make sure that this function can handle a possible
.Dv SIGPIPE
caused by a closed connection.
For example, the file server can opt to trap
.Dv SIGPIPE
or, if writing to a socket, call
.Fn send
with the flag
.Dv MSG_NOSIGNAL
instead of using
.Fn write .
.It Fn puffs_framev_cmpframe_fn pu pufbuf_cmp1 pufbuf_cmp2 notresp
Compare the file system internal request tags in
.Ar pufbuf_cmp1
and
.Ar pufbuf_cmp2 .
Should return 0 if the tags are equal, 1 if first buffer's tag is
greater than the second and \-1 if it is smaller.
The definitions "greater" and "smaller" are used transparently by
the library, e.g. like
.Xr qsort 3 .
If it can be determined from
.Ar pufbuf_cmp1
that it is not a response to any outstanding request,
.Ar notresp
should be set to non-zero.
This will cause
.Nm
to skip the test of the buffer against the rest of the outstanding
request.
May not block.
.It Fn puffs_framev_gotframe_fn pu pufbuf
Called when no outstanding request matches an incoming frame.
The ownership of
.Ar pufbuf
is transferred to the called function and must be destroyed once
processing is over.
May not block.
.It Fn puffs_framev_fdnotify_fn pu fd what
Is called when the read or write side of the file descriptor
.Ar fd
is closed.
It is called once for each side, the bitmask parameter
.Ar what
specified what is currently closed:
.Dv PUFFS_FBIO_READ
and
.Dv PUFFS_FBIO_WRITE
for read and write, respectively.
.It Fn puffs_framev_init pu rfb wfb cmpfb gotfb fdnotfn
Initializes the given callbacks to the system.
They will be used when
.Fn puffs_mainloop
is called.
The framework provides the routines
.Fn puffs_framev_removeonclose
and
.Fn puffs_framev_unmountonclose ,
which can be given as
.Ar fdnotfn .
The first one removes the file descriptor once both sides are closed
while the second one unmounts the file system and exits the mainloop.
.It Fn puffs_framev_addfd pu fd what
Add file descriptor
.Ar fd
to be handled by the framework.
It is legal to add a file descriptor either before calling
.Fn puffs_mainloop
or at time when running.
The parameter
.Ar what
controls enabling of input and output events and can be a bitwise
combination of
.Dv PUFFS_FBIO_READ
and
.Dv PUFFS_FBIO_WRITE .
If not specified, the descriptor will be in a disabled state.
.It Fn puffs_framev_enablefd pu fd what
Enable events of type
.Ar what
for file descriptor
.Ar fd .
.It Fn puffs_framev_disablefd pu fd what
Disable events of type
.Ar what
for file descriptor
.Ar fd .
.It Fn puffs_framev_removefd pu fd error
Remove file descriptor
.Ar fd
from the list of descriptors handled by the framework.
Removing a file descriptor causes all operations blocked either on
output or input to be released with the error value
.Ar error .
In case 0 is supplied as this parameter,
.Er ECONNRESET
is used.
.Pp
The file system
.Em must
explicitly remove each fd it has added.
A good place to do this is
.Fn puffs_framev_fdnotify_fn
or
.Fn puffs_node_reclaim ,
depending a little on the structure of the file system.
.It Fn puffs_framev_unmountonclose pu fd what
This is library provided convenience routine for
.Fn puffs_framev_fdnotify_fn .
It unmounts the file system when both the read and write side are
closed.
It is useful for file systems such as
.Xr mount_psshfs 8
which depend on a single connection.
.El
.Sh CODE REFERENCES
The current users of
.Nm
in the tree are
.Xr mount_psshfs 8
and
.Xr mount_9p 8 .
See
.Pa src/usr.sbin/puffs/mount_psshfs
and
.Pa src/usr.sbin/puffs/mount_9p
for the respective usage examples.
.Sh RETURN VALUES
These functions generally return \-1 to signal error and set
.Er errno
to indicate the type of error.
.Sh SEE ALSO
.Xr puffs 3 ,
.Xr puffs_cc 3 ,
.Xr puffs_ops 3
.Rs
.%A Antti Kantee
.%D September 2007
.%I Helsinki University of Technology
.%R Tech Report TKK-TKO-B157
.%T Using puffs for Implementing Client-Server Distributed File Systems
.Re
.Rs
.%A Antti Kantee
.%D March 2008
.%J Proceedings of AsiaBSDCon 2008
.%P pp. 55-70
.%T Send and Receive of File System Protocols: Userspace Approach With puffs
.Re
-261
View File
@@ -1,261 +0,0 @@
/* $NetBSD: puffs_msgif.h,v 1.65.20.2 2009/12/14 19:36:57 sborrill Exp $ */
/*
* Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved.
*
* Development of this software was supported by the
* Google Summer of Code program and the Ulla Tuominen Foundation.
* The Google SoC project was mentored by Bill Studenmund.
*
* 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 ``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.
*/
#ifndef _FS_PUFFS_PUFFS_MSGIF_H_
#define _FS_PUFFS_PUFFS_MSGIF_H_
#include <sys/param.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <sys/statvfs.h>
#include <sys/ucred.h>
#include <time.h>
#define PUFFSOP_VFS 0x01 /* kernel-> */
#define PUFFSOP_VN 0x02 /* kernel-> */
#define PUFFSOP_CACHE 0x03 /* only kernel-> */
#define PUFFSOP_ERROR 0x04 /* only kernel-> */
#define PUFFSOP_FLUSH 0x05 /* ->kernel */
#define PUFFSOP_SUSPEND 0x06 /* ->kernel */
#define PUFFSOPFLAG_FAF 0x10 /* fire-and-forget */
#define PUFFSOPFLAG_ISRESPONSE 0x20 /* req is actually a resp */
#define PUFFSOP_OPCMASK 0x07
#define PUFFSOP_OPCLASS(a) ((a) & PUFFSOP_OPCMASK)
#define PUFFSOP_WANTREPLY(a) (((a) & PUFFSOPFLAG_FAF) == 0)
/* XXX: we don't need everything */
enum {
PUFFS_VFS_MOUNT, PUFFS_VFS_START, PUFFS_VFS_UNMOUNT,
PUFFS_VFS_ROOT, PUFFS_VFS_STATVFS, PUFFS_VFS_SYNC,
PUFFS_VFS_VGET, PUFFS_VFS_FHTOVP, PUFFS_VFS_VPTOFH,
PUFFS_VFS_INIT, PUFFS_VFS_DONE, PUFFS_VFS_SNAPSHOT,
PUFFS_VFS_EXTATTCTL, PUFFS_VFS_SUSPEND
};
#define PUFFS_VFS_MAX PUFFS_VFS_EXTATTCTL
/* moreXXX: we don't need everything here either */
enum {
PUFFS_VN_LOOKUP, PUFFS_VN_CREATE, PUFFS_VN_MKNOD,
PUFFS_VN_OPEN, PUFFS_VN_CLOSE, PUFFS_VN_ACCESS,
PUFFS_VN_GETATTR, PUFFS_VN_SETATTR, PUFFS_VN_READ,
PUFFS_VN_WRITE, PUFFS_VN_IOCTL, PUFFS_VN_FCNTL,
PUFFS_VN_POLL, PUFFS_VN_KQFILTER, PUFFS_VN_REVOKE,
PUFFS_VN_MMAP, PUFFS_VN_FSYNC, PUFFS_VN_SEEK,
PUFFS_VN_REMOVE, PUFFS_VN_LINK, PUFFS_VN_RENAME,
PUFFS_VN_MKDIR, PUFFS_VN_RMDIR, PUFFS_VN_SYMLINK,
PUFFS_VN_READDIR, PUFFS_VN_READLINK, PUFFS_VN_ABORTOP,
PUFFS_VN_INACTIVE, PUFFS_VN_RECLAIM, PUFFS_VN_LOCK,
PUFFS_VN_UNLOCK, PUFFS_VN_BMAP, PUFFS_VN_STRATEGY,
PUFFS_VN_PRINT, PUFFS_VN_ISLOCKED, PUFFS_VN_PATHCONF,
PUFFS_VN_ADVLOCK, PUFFS_VN_LEASE, PUFFS_VN_WHITEOUT,
PUFFS_VN_GETPAGES, PUFFS_VN_PUTPAGES, PUFFS_VN_GETEXTATTR,
PUFFS_VN_LISTEXTATTR, PUFFS_VN_OPENEXTATTR, PUFFS_VN_DELETEEXTATTR,
PUFFS_VN_SETEXTATTR
};
#define PUFFS_VN_MAX PUFFS_VN_SETEXTATTR
/*
* These signal invalid parameters the file system returned.
*/
enum {
PUFFS_ERR_MAKENODE, PUFFS_ERR_LOOKUP, PUFFS_ERR_READDIR,
PUFFS_ERR_READLINK, PUFFS_ERR_READ, PUFFS_ERR_WRITE,
PUFFS_ERR_VPTOFH, PUFFS_ERR_ERROR
};
#define PUFFS_ERR_MAX PUFFS_ERR_VPTOFH
#define PUFFSDEVELVERS 0x80000000
#define PUFFSVERSION 26
#define PUFFSNAMESIZE 32
#define PUFFS_TYPEPREFIX "puffs|"
#if 0
#define PUFFS_TYPELEN (_VFS_NAMELEN - (sizeof(PUFFS_TYPEPREFIX)+1))
#define PUFFS_NAMELEN (_VFS_MNAMELEN-1)
#endif
/*
* Just a weak typedef for code clarity. Additionally, we have a
* more appropriate vanity type for puffs:
* <uep> it should be croissant, not cookie.
*/
typedef void *puffs_cookie_t;
typedef puffs_cookie_t puffs_croissant_t;
/* FIXME: move? */
typedef off_t voff_t;
/* other netbsd stuff
* FIXME: move to some other place?
*/
typedef int32_t lwpid_t; /* LWP id */
typedef unsigned long vsize_t;
typedef int vm_prot_t;
typedef uint64_t u_quad_t; /* quads */
/* FIXME: from sys/vnode.h, which is commented. */
/*
* Vnode attributes. A field value of VNOVAL represents a field whose value
* is unavailable (getattr) or which is not to be changed (setattr).
*/
enum vtype { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO, VBAD };
struct vattr {
enum vtype va_type; /* vnode type (for create) */
mode_t va_mode; /* files access mode and type */
nlink_t va_nlink; /* number of references to file */
uid_t va_uid; /* owner user id */
gid_t va_gid; /* owner group id */
long va_fsid; /* file system id (dev for now) */
ino_t va_fileid; /* file id */
u_quad_t va_size; /* file size in bytes */
long va_blocksize; /* blocksize preferred for i/o */
struct timespec va_atime; /* time of last access */
struct timespec va_mtime; /* time of last modification */
struct timespec va_ctime; /* time file changed */
struct timespec va_birthtime; /* time file created */
u_long va_gen; /* generation number of file */
u_long va_flags; /* flags defined for file */
dev_t va_rdev; /* device the special file represents */
u_quad_t va_bytes; /* bytes of disk space held by file */
u_quad_t va_filerev; /* file modification number */
u_int va_vaflags; /* operations flags, see below */
long va_spare; /* remain quad aligned */
};
struct puffs_kargs {
unsigned int pa_vers;
int pa_fd;
uint32_t pa_flags;
size_t pa_maxmsglen;
int pa_nhashbuckets;
size_t pa_fhsize;
int pa_fhflags;
puffs_cookie_t pa_root_cookie;
enum vtype pa_root_vtype;
voff_t pa_root_vsize;
dev_t pa_root_rdev;
struct statvfs pa_svfsb;
char pa_typename[NAME_MAX + 1];
char pa_mntfromname[NAME_MAX + 1];
uint8_t pa_vnopmask[PUFFS_VN_MAX];
};
#define PUFFS_KFLAG_NOCACHE_NAME 0x01 /* don't use name cache */
#define PUFFS_KFLAG_NOCACHE_PAGE 0x02 /* don't use page cache */
#define PUFFS_KFLAG_NOCACHE 0x03 /* no cache whatsoever */
#define PUFFS_KFLAG_ALLOPS 0x04 /* ignore pa_vnopmask */
#define PUFFS_KFLAG_WTCACHE 0x08 /* write-through page cache */
#define PUFFS_KFLAG_IAONDEMAND 0x10 /* inactive only on demand */
#define PUFFS_KFLAG_LOOKUP_FULLPNBUF 0x20 /* full pnbuf in lookup */
#define PUFFS_KFLAG_MASK 0x3f
#define PUFFS_FHFLAG_DYNAMIC 0x01
#define PUFFS_FHFLAG_NFSV2 0x02
#define PUFFS_FHFLAG_NFSV3 0x04
#define PUFFS_FHFLAG_PROTOMASK 0x06
#define PUFFS_FHFLAG_PASSTHROUGH 0x08
#define PUFFS_FHFLAG_MASK 0x0f
#define PUFFS_FHSIZE_MAX 1020 /* XXX: FHANDLE_SIZE_MAX - 4 */
#define PUFFS_SETBACK_INACT_N1 0x01 /* set VOP_INACTIVE for node 1 */
#define PUFFS_SETBACK_INACT_N2 0x02 /* set VOP_INACTIVE for node 2 */
#define PUFFS_SETBACK_NOREF_N1 0x04 /* set pn PN_NOREFS for node 1 */
#define PUFFS_SETBACK_NOREF_N2 0x08 /* set pn PN_NOREFS for node 2 */
#define PUFFS_SETBACK_MASK 0x0f
#define PUFFS_INVAL_NAMECACHE_NODE 0
#define PUFFS_INVAL_NAMECACHE_DIR 1
#define PUFFS_INVAL_NAMECACHE_ALL 2
#define PUFFS_INVAL_PAGECACHE_NODE_RANGE 3
#define PUFFS_FLUSH_PAGECACHE_NODE_RANGE 4
/* keep this for now */
#define PUFFSREQSIZEOP _IOR ('p', 1, size_t)
#define PUFFCRED_TYPE_UUC 1
#define PUFFCRED_TYPE_INTERNAL 2
#define PUFFCRED_CRED_NOCRED 1
#define PUFFCRED_CRED_FSCRED 2
/*
* 2*MAXPHYS is the max size the system will attempt to copy,
* else treated as garbage
*/
#define PUFFS_MSG_MAXSIZE 2*MAXPHYS
#define PUFFS_MSGSTRUCT_MAX 4096 /* XXX: approxkludge */
#define PUFFS_TOMOVE(a,b) (MIN((a), b->pmp_msg_maxsize - PUFFS_MSGSTRUCT_MAX))
/* puffs struct componentname built by kernel */
struct puffs_kcn {
/* args */
uint32_t pkcn_nameiop; /* namei operation */
uint32_t pkcn_flags; /* flags */
char pkcn_name[MAXPATHLEN]; /* nulterminated path component */
size_t pkcn_namelen; /* current component length */
size_t pkcn_consume; /* IN: extra chars server ate */
};
/*
* Credentials for an operation. Can be either struct uucred for
* ops called from a credential context or NOCRED/FSCRED for ops
* called from within the kernel. It is up to the implementation
* if it makes a difference between these two and the super-user.
*/
struct puffs_kcred {
struct uucred pkcr_uuc;
uint8_t pkcr_type;
uint8_t pkcr_internal;
};
#define PUFFCRED_TYPE_UUC 1
#define PUFFCRED_TYPE_INTERNAL 2
#define PUFFCRED_CRED_NOCRED 1
#define PUFFCRED_CRED_FSCRED 2
#endif /* _FS_PUFFS_PUFFS_MSGIF_H_ */
+1 -2
View File
@@ -1,4 +1,4 @@
.\" $NetBSD: puffs_node.3,v 1.3.12.1 2009/02/24 03:45:56 snj Exp $
.\" $NetBSD: puffs_node.3,v 1.5 2009/05/13 22:42:31 wiz Exp $
.\"
.\" Copyright (c) 2007 Antti Kantee. All rights reserved.
.\"
@@ -96,7 +96,6 @@ Free all resources associated with node
.Ar pn .
This is typically called from
.Fn puffs_node_reclaim .
.Pp
.El
.Sh SEE ALSO
.Xr puffs 3
+181 -25
View File
@@ -1,4 +1,4 @@
.\" $NetBSD: puffs_ops.3,v 1.21.4.2 2009/04/12 02:24:16 snj Exp $
.\" $NetBSD: puffs_ops.3,v 1.36 2012/08/16 11:28:38 wiz Exp $
.\"
.\" Copyright (c) 2007 Antti Kantee. All rights reserved.
.\"
@@ -23,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd December 16, 2007
.Dd August 16, 2012
.Dt PUFFS_OPS 3
.Os
.Sh NAME
@@ -48,11 +48,14 @@
.Fc
.Ft int
.Fo puffs_fs_nodetofh
.Fa "struct puffs_usermount *pu" "puffs_cooie_t cookie" "void *fid"
.Fa "struct puffs_usermount *pu" "puffs_cookie_t cookie" "void *fid"
.Fa "size_t *fidsize"
.Fc
.Ft void
.Fn puffs_fs_suspend "struct puffs_usermount *pu" "int status"
.Fo puffs_fs_extattrctl
.Fa "struct puffs_usermount *pu" "int cmd" "puffs_cookie_t cookie" "int flags"
.Fa "int attrnamespace" "const char *attrname"
.Fc
.Ft int
.Fo puffs_fs_unmount
.Fa "struct puffs_usermount *pu" "int flags"
@@ -100,6 +103,16 @@
.Fa "const struct puffs_cred *pcr"
.Fc
.Ft int
.Fo puffs_node_getattr_ttl
.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" "struct vattr *vap"
.Fa "const struct puffs_cred *pcr" "struct timespec *va_ttl"
.Fc
.Ft int
.Fo puffs_node_setattr_ttl
.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" "const struct vattr *vap"
.Fa "const struct puffs_cred *pcr" "struct timespec *va_ttl" "int xflag"
.Fc
.Ft int
.Fo puffs_node_poll
.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" "int *events"
.Fc
@@ -174,12 +187,51 @@
.Fa "off_t offset" "size_t *resid" "const struct puffs_cred *pcr" "int ioflag"
.Fc
.Ft int
.Fo puffs_node_write2
.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" "uint8_t *buf"
.Fa "off_t offset" "size_t *resid" "const struct puffs_cred *pcr" "int ioflag"
.Fa "int xflag"
.Fc
.Ft int
.Fo puffs_node_abortop
.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc"
.Fa "const struct puffs_cn *pcn"
.Fc
.Ft int
.Fo puffs_node_getextattr
.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" "int attrnamespace"
.Fa "const char *attrname" "size_t *attrsize" "uint8_t *attr" "size_t *resid"
.Fa "const struct puffs_cred *pcr"
.Fc
.Ft int
.Fo puffs_node_setextattr
.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" "int attrnamespace"
.Fa "const char *attrname" "uint8_t *attr" "size_t *resid"
.Fa "const struct puffs_cred *pcr"
.Fc
.Ft int
.Fo puffs_node_listextattr
.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" "int attrnamespace"
.Fa "size_t *attrssize" "uint8_t *attrs" "iint flag" "size_t *resid"
.Fa "const struct puffs_cred *pcr"
.Fc
.Ft int
.Fo puffs_node_deleteextattr
.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" "int attrnamespace"
.Fa "const char *attrname"
.Fa "const struct puffs_cred *pcr"
.Fc
.Ft int
.Fn puffs_node_print "struct puffs_usermount *pu" "puffs_cookie_t opc"
.Ft int
.Fo puffs_node_reclaim
.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc"
.Fc
.Ft int
.Fo puffs_node_reclaim2
.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" "int nlookup"
.Fc
.Ft int
.Fo puffs_node_inactive
.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc"
.Fc
@@ -193,6 +245,12 @@
.Fn puffs_newinfo_setsize "struct puffs_newinfo *pni" "voff_t size"
.Ft void
.Fn puffs_newinfo_setrdev "struct puffs_newinfo *pni" "dev_t rdev"
.Ft void
.Fn puffs_newinfo_setva "struct puffs_newinfo *pni" "struct vattr *vap"
.Ft void
.Fn puffs_newinfo_setvattl "struct puffs_newinfo *pni" "struct timespec *va_ttl"
.Ft void
.Fn puffs_newinfo_setcnttl "struct puffs_newinfo *pni" "struct timespec *cn_ttl"
.Sh DESCRIPTION
The operations
.Nm puffs
@@ -242,7 +300,7 @@ Wait for all I/O for complete until returning.
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
i.e., data not written when
.Fn node_fsync
is called with
.Dv FSYNC_LAZY .
@@ -292,11 +350,6 @@ In either case, the handle length should be supplied to the kernel in
.Fa fidsize .
File systems with static length handles can ignore the size parameter as
the kernel always supplies the correct size buffer.
.It Fn puffs_fs_suspend "pu" "status"
Called when file system suspension reaches various phases.
See
.Xr puffs_suspend 3
for more information.
.It Fn puffs_fs_unmount "pu" "flags"
Unmount the file system.
The kernel has assumedly flushed all cached data when this callback
@@ -343,19 +396,31 @@ If the located entry is a block device or character device file,
the dev_t for the entry should be set using
.Fn puffs_newinfo_setrdev .
.Pp
If
.Fn puffs_init
was called with
.Dv PUFFS_KFLAG_CACHE_FS_TTL
then
.Fn puffs_newinfo_setva ,
.Fn puffs_newinfo_setvattl ,
and
.Fn puffs_newinfo_setcnttl
can be called to specify the new node attributes, cached attributes
time to live, and cached name time to live.
.Pp
The type of operation is found from
.Va pcn-\*[Gt]pcn_nameiop :
.Bl -tag -width XPUFFSLOOKUP_LOOKUPX
.It Dv PUFFSLOOKUP_LOOKUP
.Bl -tag -width XNAMEI_LOOKUPX
.It Dv NAMEI_LOOKUP
Normal lookup operation.
.It Dv PUFFSLOOKUP_CREATE
.It Dv NAMEI_CREATE
Lookup to create a node.
.It Dv PUFFSLOOKUP_DELETE
.It Dv NAMEI_DELETE
Lookup for node deletion.
.It Dv PUFFSLOOKUP_RENAME
.It Dv NAMEI_RENAME
Lookup for the target of a rename operation (source will be looked
up using
.Dv PUFFSLOOKUP_DELETE ) .
.Dv NAMEI_DELETE ) .
.El
.Pp
The final component from a pathname lookup usually requires special
@@ -373,9 +438,9 @@ an errno.
As a special case,
.Er ENOENT
signals "success" for cases where the lookup operation is
.Dv PUFFSLOOKUP_CREATE
.Dv NAMEI_CREATE
or
.Dv PUFFSLOOKUP_RENAME .
.Dv NAMEI_RENAME .
Failure in these cases can be signalled by returning another appropriate
error code, for example
.Er EACCESS .
@@ -451,6 +516,11 @@ The attributes of the node specified by
.Fa opc
must be copied to the space pointed by
.Fa va .
.It Fn puffs_node_getattr_ttl "pu" "opc" "va" "pcr" "va_ttl"
Same as
.Fn puffs_node_getattr
with cached attribute time to live specified in
.Fa va_ttl
.It Fn puffs_node_setattr "pu" "opc" "va" "pcr"
The attributes for the node specified by
.Fa opc
@@ -461,6 +531,15 @@ Only fields of
which contain a value different from
.Dv PUFFS_VNOVAL
(typecast to the field's type!) contain a valid value.
.It Fn puffs_node_setattr_ttl "pu" "opc" "va" "pcr" "va_ttl" "xflag"
Same as
.Fn puffs_node_setattr
with cached attribute time to live specified in
.Fa va_ttl .
.Dv PUFFS_SETATTR_FAF
will be set in
.Fa xflag
for Fire-And-Forget operations.
.It Fn puffs_node_poll "pu" "opc" "events"
Poll for events on node
.Ar opc .
@@ -542,6 +621,8 @@ This is to retain the
open file semantics.
The data may be removed only when
.Fn puffs_node_reclaim
or
.Fn puffs_node_reclaim2
is called for the node, as this assures there are no further users.
.It Fn puffs_node_link "pu" "opc" "targ" "pcn"
Create a hard link for the node
@@ -625,12 +706,12 @@ 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
.Em next
directory entry, i.e. which offset should be passed to readdir for
directory entry, i.e., which offset should be passed to readdir for
the first entry read to be the entry following the current one.
.Fa 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.
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
@@ -684,8 +765,10 @@ The parameter
should be set to indicate the amount of request NOT completed.
In the normal case this should be 0.
.It Fn puffs_node_write "pu" "opc" "buf" "offset" "resid" "pcr" "ioflag"
.It Fn puffs_node_write2 "pu" "opc" "buf" "offset" "resid" "pcr" "ioflag" \
"xflag"
.Fn puffs_node_write
Write data to a file
writes data to a file
.Fa opc
at
.Fa offset
@@ -694,24 +777,55 @@ 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
In case the ioflag
.Dv PUFFS_IO_APPEND
is specified, the data should be appended to the end of the file.
.Fn puffs_node_write2
serves the same purpose as
.Fn puffs_node_write
with an additional
.Fa xflag
in which
.Dv PUFFS_WRITE_FAF
is set for Fire-And-Forget operations.
.It Fn puffs_node_print "pu" "opc"
Print information about node. This is used only for kernel-initiated
diagnostic purposes.
Print information about node.
This is used only for kernel-initiated diagnostic purposes.
.It Fn puffs_node_reclaim "pu" "opc"
The kernel will no longer reference the cookie and resources associated
with it may be freed.
In case the file
.Fa opc
has a link count of zero, it may be safely removed now.
.It Fn puffs_node_reclaim2 "pu" "opc" "nlookup"
Same as
.Fn puffs_node_reclaim
with an addditional 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
filesystem to avoid a race condition, where the kernel sends a reclaim
while it does not have received the reply for a lookup.
If the filesystem tracks lookup count, and compares to
.Fa nlookup
it can detect this situation and ignore the reclaim.
.Pp
If the filesystem maps cookies to
.Vt struct puffs_node
then the framework will do that work, and
.Fn puffs_node_reclaim
can be reliabily used without the race condition.
.It Fn puffs_node_abortop "pu" "opc" "pcn"
In case the operation following lookup (e.g., mkdir or remove) is not
executed for some reason, abortop will be issued.
This is useful only for servers which cache state between lookup
and a directory operation and is generally left unimplemented.
.It Fn puffs_node_inactive "pu" "opc"
The node
.Fa opc
has lost its last reference in the kernel.
However, the cookie must still remain valid until
.Fn puffs_node_reclaim
or
.Fn puffs_node_reclaim2
is called.
.It Fn puffs_setback "pcc" "op"
Issue a "setback" operation which will be handled when the request response
@@ -729,7 +843,7 @@ should call the file system inactive method for the specified node.
The node number 1 always means the operation cookie
.Ar opc ,
while the node number 2 can be used to specify the second node argument
present in some methods, e.g. remove.
present in some methods, e.g., remove.
.It Fn puffs_newinfo_setcookie pni cookie
Set cookie for node provided by this method to
.Ar cookie .
@@ -756,6 +870,48 @@ This call is valid only for
and
.Fn fhtovp
producing device type nodes.
.It Fn puffs_newinfo_setva pni vap
Set the attributes for newly created vnode.
This call is valid for
.Fn lookup ,
.Fn create ,
.Fn mkdir ,
.Fn mknod ,
and
.Fn symlink ,
if
.Fn puffs_init
was called with
.Dv PUFFS_KFLAG_CACHE_FS_TTL
flag set.
.It Fn puffs_newinfo_setvattl pni va_ttl
Set cached attribute time to live for newly created vnode.
This call is valid for
.Fn lookup ,
.Fn create ,
.Fn mkdir ,
.Fn mknod ,
and
.Fn symlink ,
if
.Fn puffs_init
was called with
.Dv PUFFS_KFLAG_CACHE_FS_TTL
flag set.
.It Fn puffs_newinfo_setcnttl pni cn_ttl
Set cached name time to live for newly created vnode.
This call is valid for
.Fn lookup ,
.Fn create ,
.Fn mkdir ,
.Fn mknod ,
and
.Fn symlink ,
if
.Fn puffs_init
was called with
.Dv PUFFS_KFLAG_CACHE_FS_TTL
flag set.
.El
.Sh SEE ALSO
.Xr puffs 3 ,
+1 -1
View File
@@ -1,4 +1,4 @@
.\" $NetBSD: puffs_path.3,v 1.3.10.1 2009/02/24 03:45:56 snj Exp $
.\" $NetBSD: puffs_path.3,v 1.4 2009/02/20 14:26:56 pooka Exp $
.\"
.\" Copyright (c) 2007 Antti Kantee. All rights reserved.
.\"
+24 -14
View File
@@ -1,4 +1,4 @@
/* $NetBSD: puffs_priv.h,v 1.41 2008/08/11 16:23:37 pooka Exp $ */
/* $NetBSD: puffs_priv.h,v 1.45 2012/04/18 00:57:22 manu Exp $ */
/*
* Copyright (c) 2006, 2007, 2008 Antti Kantee. All Rights Reserved.
@@ -29,11 +29,15 @@
#define _PUFFS_PRIVATE_H_
#include <sys/types.h>
#include <fs/puffs/puffs_msgif.h>
#if !defined(__minix)
#include <pthread.h>
#endif /* !defined(__minix) */
#include <puffs.h>
#include <ucontext.h>
/* FIXME: fs/puffs/puffs_msgif.h? */
#include "puffs_msgif.h"
#include "puffs.h"
#if defined(__minix)
/* XXX: MINIX */
#define IGN_PERM 0
@@ -47,15 +51,17 @@
#define REQ_READ_SUPER 28
#ifdef PUFFS_WITH_THREADS
#include <pthread.h>
#define NUL(str,l,m) mfs_nul_f(__FILE__,__LINE__,(str), (l), (m))
#else
extern pthread_mutex_t pu_lock;
#define PU_LOCK() pthread_mutex_lock(&pu_lock)
#define PU_UNLOCK() pthread_mutex_unlock(&pu_lock)
#else
#define PU_LOCK()
#define PU_UNLOCK()
#endif
#endif /* defined(__minix) */
#if defined(__minix)
#define PU_LOCK() /* nothing */
#define PU_UNLOCK() /* nothing */
#endif /* defined(__minix) */
#define PU_CMAP(pu, c) (pu->pu_cmap ? pu->pu_cmap(pu,c) : (struct puffs_node*)c)
@@ -128,16 +134,19 @@ struct puffs_usermount {
#define PU_HASKQ 0x0400
#define PU_PUFFSDAEMON 0x0800
#define PU_MAINRESTORE 0x1000
#define PU_DONEXIT 0x2000
#define PU_SETSTATE(pu, s) (pu->pu_state = (s) | (pu->pu_state & ~PU_STATEMASK))
#define PU_SETSFLAG(pu, s) (pu->pu_state |= (s))
#define PU_CLRSFLAG(pu, s) \
(pu->pu_state = ((pu->pu_state &= ~(s)) | (pu->pu_state & PU_STATEMASK)))
(pu->pu_state = ((pu->pu_state & ~(s)) | (pu->pu_state & PU_STATEMASK)))
int pu_dpipe[2];
struct puffs_node *pu_pn_root;
LIST_HEAD(, puffs_node) pu_pnodelst;
#if defined(__minix) // LSC TO KEEP??
LIST_HEAD(, puffs_node) pu_pnode_removed_lst;
#endif /* defined(__minix) */
LIST_HEAD(, puffs_cc) pu_ccmagazin;
TAILQ_HEAD(, puffs_cc) pu_lazyctx;
@@ -162,7 +171,7 @@ struct puffs_usermount {
LIST_HEAD(, puffs_fctrl_io) pu_ios;
LIST_HEAD(, puffs_fctrl_io) pu_ios_rmlist;
struct kevent *pu_evs;
size_t pu_nfds;
size_t pu_nevs;
puffs_ml_loop_fn pu_ml_lfn;
struct timespec pu_ml_timeout;
@@ -217,6 +226,9 @@ struct puffs_newinfo {
enum vtype *pni_vtype;
voff_t *pni_size;
dev_t *pni_rdev;
struct vattr *pni_va;
struct timespec *pni_va_ttl;
struct timespec *pni_cn_ttl;
};
#define PUFFS_MAKEKCRED(to, from) \
@@ -271,6 +283,4 @@ void puffs__fsframe_gotframe(struct puffs_usermount *,
__END_DECLS
#define NUL(str,l,m) mfs_nul_f(__FILE__,__LINE__,(str), (l), (m))
#endif /* _PUFFS_PRIVATE_H_ */
+68
View File
@@ -0,0 +1,68 @@
/* $NetBSD: puffsdump.h,v 1.15 2010/07/11 12:29:08 pooka Exp $ */
/*
* Copyright (c) 2006 Antti Kantee. All Rights Reserved.
*
* Development of this software was supported by the Ulla Tuominen Foundation.
*
* 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 ``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.
*/
#ifndef _PUFFSDUMP_H_
#define _PUFFSDUMP_H_
/*
* Note for callers outside of libpuffs: these are to be used only
* for debug builds. Interfaces are not guaranteed to remain stable.
*/
#include <fs/puffs/puffs_msgif.h>
void puffsdump_req(struct puffs_req *);
void puffsdump_rv(struct puffs_req *);
void puffsdump_cookie(puffs_cookie_t, const char *);
void puffsdump_cn(struct puffs_kcn *);
void puffsdump_readwrite(struct puffs_req *);
void puffsdump_readwrite_rv(struct puffs_req *);
void puffsdump_readdir(struct puffs_req *);
void puffsdump_readdir_rv(struct puffs_req *);
void puffsdump_lookup(struct puffs_req *);
void puffsdump_lookup_rv(struct puffs_req *);
void puffsdump_create(struct puffs_req *);
void puffsdump_create_rv(struct puffs_req *);
void puffsdump_open(struct puffs_req *);
void puffsdump_attr(struct puffs_req *);
void puffsdump_targ(struct puffs_req *);
extern const char *puffsdump_vfsop_revmap[];
extern const char *puffsdump_vnop_revmap[];
extern const char *puffsdump_errnot_revmap[];
extern const char *puffsdump_flush_revmap[];
extern size_t puffsdump_vfsop_count;
extern size_t puffsdump_vnop_count;
extern size_t puffsdump_errnot_count;
extern size_t puffsdump_flush_count;
#endif /* _PUFFSDUMP_H_ */
+241
View File
@@ -0,0 +1,241 @@
/* $NetBSD: requests.c,v 1.24 2013/01/23 20:22:34 riastradh Exp $ */
/*
* Copyright (c) 2007 Antti Kantee. All Rights Reserved.
*
* Development of this software was supported by the
* Research Foundation of Helsinki University of Technology
*
* 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 ``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.
*/
#include <sys/cdefs.h>
#if !defined(lint)
__RCSID("$NetBSD: requests.c,v 1.24 2013/01/23 20:22:34 riastradh Exp $");
#endif /* !lint */
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/queue.h>
#include <sys/socket.h>
#if !defined(__minix)
#include <dev/putter/putter.h>
#endif /* !defined(__minix) */
#include <assert.h>
#include <errno.h>
#include <puffs.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "puffs_priv.h"
/*
* Read a frame from the upstream provider. First read the frame
* length and after this read the actual contents. Yes, optimize
* me some day.
*/
/*ARGSUSED*/
int
puffs__fsframe_read(struct puffs_usermount *pu, struct puffs_framebuf *pb,
int fd, int *done)
{
struct putter_hdr phdr;
void *win;
size_t howmuch, winlen, curoff;
ssize_t n;
int lenstate;
/* How much to read? */
the_next_level:
curoff = puffs_framebuf_telloff(pb);
if (curoff < sizeof(struct putter_hdr)) {
howmuch = sizeof(struct putter_hdr) - curoff;
lenstate = 1;
} else {
puffs_framebuf_getdata_atoff(pb, 0, &phdr, sizeof(phdr));
/*LINTED*/
howmuch = phdr.pth_framelen - curoff;
lenstate = 0;
}
if (puffs_framebuf_reserve_space(pb, howmuch) == -1)
return errno;
/* Read contents */
while (howmuch) {
winlen = howmuch;
curoff = puffs_framebuf_telloff(pb);
if (puffs_framebuf_getwindow(pb, curoff, &win, &winlen) == -1)
return errno;
n = read(fd, win, winlen);
switch (n) {
case 0:
return ECONNRESET;
case -1:
if (errno == EAGAIN)
return 0;
return errno;
default:
howmuch -= n;
puffs_framebuf_seekset(pb, curoff + n);
break;
}
}
if (lenstate)
goto the_next_level;
puffs_framebuf_seekset(pb, 0);
*done = 1;
return 0;
}
/*
* Write a frame upstream
*/
/*ARGSUSED*/
int
puffs__fsframe_write(struct puffs_usermount *pu, struct puffs_framebuf *pb,
int fd, int *done)
{
void *win;
uint64_t flen;
size_t winlen, howmuch, curoff;
ssize_t n;
int rv;
/*
* Finalize it if we haven't written anything yet (or we're still
* attempting to write the first byte)
*
* XXX: this shouldn't be here
*/
if (puffs_framebuf_telloff(pb) == 0) {
struct puffs_req *preq;
winlen = sizeof(struct puffs_req);
rv = puffs_framebuf_getwindow(pb, 0, (void *)&preq, &winlen);
if (rv == -1)
return errno;
preq->preq_pth.pth_framelen = flen = preq->preq_buflen;
} else {
struct putter_hdr phdr;
puffs_framebuf_getdata_atoff(pb, 0, &phdr, sizeof(phdr));
flen = phdr.pth_framelen;
}
/*
* Then write it. Chances are if we are talking to the kernel it'll
* just shlosh in all at once, but if we're e.g. talking to the
* network it might take a few tries.
*/
/*LINTED*/
howmuch = flen - puffs_framebuf_telloff(pb);
while (howmuch) {
winlen = howmuch;
curoff = puffs_framebuf_telloff(pb);
if (puffs_framebuf_getwindow(pb, curoff, &win, &winlen) == -1)
return errno;
/*
* XXX: we know from the framebuf implementation that we
* will always managed to map the entire window. But if
* that changes, this will catch it. Then we can do stuff
* iov stuff instead.
*/
assert(winlen == howmuch);
/* XXX: want NOSIGNAL if writing to a pipe */
#if 0
n = send(fd, win, winlen, MSG_NOSIGNAL);
#else
n = write(fd, win, winlen);
#endif
switch (n) {
case 0:
return ECONNRESET;
case -1:
if (errno == EAGAIN)
return 0;
return errno;
default:
howmuch -= n;
puffs_framebuf_seekset(pb, curoff + n);
break;
}
}
*done = 1;
return 0;
}
/*
* Compare if "pb1" is a response to a previously sent frame pb2.
* More often than not "pb1" is not a response to anything but
* rather a fresh request from the kernel.
*/
/*ARGSUSED*/
int
puffs__fsframe_cmp(struct puffs_usermount *pu,
struct puffs_framebuf *pb1, struct puffs_framebuf *pb2, int *notresp)
{
struct puffs_req *preq1, *preq2;
size_t winlen;
int rv;
/* map incoming preq */
winlen = sizeof(struct puffs_req);
rv = puffs_framebuf_getwindow(pb1, 0, (void *)&preq1, &winlen);
assert(rv == 0); /* frames are always at least puffs_req in size */
assert(winlen == sizeof(struct puffs_req));
/*
* Check if this is not a response in this slot. That's the
* likely case.
*/
if ((preq1->preq_opclass & PUFFSOPFLAG_ISRESPONSE) == 0) {
*notresp = 1;
return 0;
}
/* map second preq */
winlen = sizeof(struct puffs_req);
rv = puffs_framebuf_getwindow(pb2, 0, (void *)&preq2, &winlen);
assert(rv == 0); /* frames are always at least puffs_req in size */
assert(winlen == sizeof(struct puffs_req));
/* then compare: resid equal? */
return preq1->preq_id != preq2->preq_id;
}
void
puffs__fsframe_gotframe(struct puffs_usermount *pu, struct puffs_framebuf *pb)
{
puffs_framebuf_seekset(pb, 0);
puffs__ml_dispatch(pu, pb);
}
+3 -1
View File
@@ -1,2 +1,4 @@
major=0
# $NetBSD: shlib_version,v 1.5 2010/05/21 10:50:52 pooka Exp $
#
major=2
minor=0
+34 -34
View File
@@ -1,4 +1,4 @@
/* $NetBSD: subr.c,v 1.23 2008/08/12 19:44:39 pooka Exp $ */
/* $NetBSD: subr.c,v 1.27 2011/02/17 17:55:36 pooka Exp $ */
/*
* Copyright (c) 2006 Antti Kantee. All Rights Reserved.
@@ -27,25 +27,24 @@
#include <sys/cdefs.h>
#if !defined(lint)
__RCSID("$NetBSD: subr.c,v 1.23 2008/08/12 19:44:39 pooka Exp $");
__RCSID("$NetBSD: subr.c,v 1.27 2011/02/17 17:55:36 pooka Exp $");
#endif /* !lint */
#include <sys/types.h>
#include <sys/dirent.h>
#include <sys/time.h>
#include <sys/vnode.h>
#include <sys/dirent.h>
#include <assert.h>
#include <errno.h>
#include <puffs.h>
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <unistd.h>
#include "puffs.h"
#include "puffs_priv.h"
int
puffs_gendotdent(struct dirent **dent, ino_t id, int dotdot, size_t *reslen)
{
@@ -62,32 +61,17 @@ puffs_nextdent(struct dirent **dent, const char *name, ino_t id, uint8_t dtype,
size_t *reslen)
{
struct dirent *d = *dent;
unsigned int len, reclen;
int o;
char *cp;
/* check if we have enough room for our dent-aligned dirent */
if (_DIRENT_RECLEN(d, strlen(name)) > *reslen)
return 0;
d->d_ino = id;
/* Compute the length of the name */
cp = memchr(name, '\0', NAME_MAX);
if (cp == NULL)
len = NAME_MAX;
else
len = cp - (name);
/* Compute record length */
reclen = offsetof(struct dirent, d_name) + len + 1;
o = (reclen % sizeof(long));
if (o != 0)
reclen += sizeof(long) - o;
d->d_reclen = (unsigned short) reclen;
(void)memcpy(d->d_name, name, (size_t)len);
d->d_name[len] = '\0';
d->d_fileno = id;
d->d_type = dtype;
d->d_namlen = (uint16_t)strlen(name);
(void)memcpy(&d->d_name, name, (size_t)d->d_namlen);
d->d_name[d->d_namlen] = '\0';
d->d_reclen = (uint16_t)_DIRENT_SIZE(d);
*reslen -= d->d_reclen;
*dent = _DIRENT_NEXT(d);
@@ -118,12 +102,13 @@ int
puffs_fsnop_statvfs(struct puffs_usermount *dontuse1, struct statvfs *sbp)
{
/* FIXME: implement me
sbp->f_bsize = sbp->f_frsize = sbp->f_iosize = 512;
sbp->f_bsize = sbp->f_frsize = sbp->f_iosize = DEV_BSIZE;
sbp->f_bfree=sbp->f_bavail=sbp->f_bresvd=sbp->f_blocks = (fsblkcnt_t)0;
sbp->f_ffree=sbp->f_favail=sbp->f_fresvd=sbp->f_files = (fsfilcnt_t)0;
*/
sbp->f_namemax = MAXNAMLEN;
return 0;
}
@@ -177,7 +162,7 @@ puffs_setvattr(struct vattr *vap, const struct vattr *sva)
SETIFVAL(va_nlink, nlink_t);
SETIFVAL(va_uid, uid_t);
SETIFVAL(va_gid, gid_t);
SETIFVAL(va_fsid, long);
SETIFVAL(va_fsid, dev_t);
SETIFVAL(va_size, u_quad_t);
SETIFVAL(va_fileid, ino_t);
SETIFVAL(va_blocksize, long);
@@ -211,7 +196,7 @@ puffs_vattr_null(struct vattr *vap)
vap->va_nlink = (nlink_t)PUFFS_VNOVAL;
vap->va_uid = (uid_t)PUFFS_VNOVAL;
vap->va_gid = (gid_t)PUFFS_VNOVAL;
vap->va_fsid = PUFFS_VNOVAL;
vap->va_fsid = (dev_t)PUFFS_VNOVAL;
vap->va_fileid = (ino_t)PUFFS_VNOVAL;
vap->va_size = (u_quad_t)PUFFS_VNOVAL;
vap->va_blocksize = sysconf(_SC_PAGESIZE);
@@ -289,15 +274,15 @@ puffs_stat2vattr(struct vattr *va, const struct stat *sb)
va->va_fsid = sb->st_dev;
va->va_fileid = sb->st_ino;
va->va_size = sb->st_size;
va->va_blocksize = sb->st_blksize;
va->va_atime = sb->st_atimespec;
va->va_ctime = sb->st_ctimespec;
va->va_mtime = sb->st_mtimespec;
va->va_blocksize = sb->st_blksize;
va->va_birthtime = sb->st_birthtimespec;
va->va_gen = sb->st_gen;
va->va_flags = sb->st_flags;
va->va_rdev = sb->st_rdev;
va->va_bytes = sb->st_blocks * sb->st_blksize;
va->va_bytes = sb->st_blocks << DEV_BSHIFT;
va->va_filerev = 0;
va->va_vaflags = 0;
}
@@ -313,6 +298,21 @@ puffs_addvtype2mode(mode_t mode, enum vtype type)
case VBLK:
mode |= S_IFBLK;
break;
case VSOCK:
mode |= S_IFSOCK;
break;
case VFIFO:
mode |= S_IFIFO;
break;
case VREG:
mode |= S_IFREG;
break;
case VLNK:
mode |= S_IFLNK;
break;
case VDIR:
mode |= S_IFDIR;
break;
default:
break;
}
+49
View File
@@ -0,0 +1,49 @@
/* $NetBSD: suspend.c,v 1.10 2009/12/05 12:13:08 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 ``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.
*/
#include <sys/cdefs.h>
#if !defined(lint)
__RCSID("$NetBSD: suspend.c,v 1.10 2009/12/05 12:13:08 pooka Exp $");
#endif /* !lint */
/*
* File system suspension
*/
#include <sys/types.h>
#include <errno.h>
#include <puffs.h>
/*ARGSUSED*/
int
puffs_fs_suspend(struct puffs_usermount *pu)
{
/* used to be, no longer is. just return error to avoid ABI bump */
return EOPNOTSUPP;
}