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:
+17
-12
@@ -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>
|
||||
|
||||
@@ -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?)
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -10,7 +10,7 @@
|
||||
|
||||
#include <minix/vfsif.h>
|
||||
|
||||
#include "puffs_msgif.h"
|
||||
#include <fs/puffs/puffs_msgif.h>
|
||||
|
||||
EXTERN struct puffs_usermount *global_pu;
|
||||
|
||||
|
||||
@@ -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
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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,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
@@ -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,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
@@ -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_ */
|
||||
|
||||
@@ -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_ */
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user