From: Sascha Wildner Date: Tue, 15 Jan 2019 03:44:42 +0000 (+0100) Subject: kernel: Remove puffs(4), putter(9) and associated libs and utilities. X-Git-Tag: v5.7.0~606 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/ee3ebee6341d385ab1e8f63b026efd8eeb72a25f kernel: Remove puffs(4), putter(9) and associated libs and utilities. All of these were originally pushed and hooked into the build in non- working condition so that they would not go stale break building. The hope was that someone would pick up the work and fix the remaining issues, which never materialized. This has led to more harm than good, with people occasionally assuming that this code is functional. Also, the existence of /usr/include/fuse.h might lead configure checks into believing that we have a working implementation. --- diff --git a/Makefile_upgrade.inc b/Makefile_upgrade.inc index 2d8c503700..53134a4df2 100644 --- a/Makefile_upgrade.inc +++ b/Makefile_upgrade.inc @@ -3448,6 +3448,54 @@ TO_REMOVE+=/etc/devd/uath.conf TO_REMOVE+=/usr/include/bus/u4b/usb_compat_linux.h TO_REMOVE+=/usr/sbin/kgmon TO_REMOVE+=/usr/share/man/man8/kgmon.8.gz +TO_REMOVE+=/boot/kernel/puffs.ko +TO_REMOVE+=/boot/kernel/putter.ko +TO_REMOVE+=/usr/include/dev/misc/putter +TO_REMOVE+=/usr/include/fuse.h +TO_REMOVE+=/usr/include/fuse_opt.h +TO_REMOVE+=/usr/include/puffs.h +TO_REMOVE+=/usr/include/puffsdump.h +TO_REMOVE+=/usr/include/vfs/puffs +TO_REMOVE+=/usr/lib/libpuffs.a +TO_REMOVE+=/usr/lib/libpuffs.so +TO_REMOVE+=/usr/lib/libpuffs.so.3 +TO_REMOVE+=/usr/lib/librefuse.a +TO_REMOVE+=/usr/lib/librefuse.so +TO_REMOVE+=/usr/lib/librefuse.so.3 +TO_REMOVE+=/usr/lib/profile/libpuffs.a +TO_REMOVE+=/usr/lib/profile/librefuse.a +TO_REMOVE+=/usr/sbin/mount_psshfs +TO_REMOVE+=/usr/share/examples/puffs +TO_REMOVE+=/usr/share/man/man3/fuse_main.3.gz +TO_REMOVE+=/usr/share/man/man3/fuse_opt_add_arg.3.gz +TO_REMOVE+=/usr/share/man/man3/fuse_opt_parse.3.gz +TO_REMOVE+=/usr/share/man/man3/fuse_setup.3.gz +TO_REMOVE+=/usr/share/man/man3/fuse_teardown.3.gz +TO_REMOVE+=/usr/share/man/man3/puffs.3.gz +TO_REMOVE+=/usr/share/man/man3/puffs_cc.3.gz +TO_REMOVE+=/usr/share/man/man3/puffs_cred.3.gz +TO_REMOVE+=/usr/share/man/man3/puffs_flush.3.gz +TO_REMOVE+=/usr/share/man/man3/puffs_framebuf.3.gz +TO_REMOVE+=/usr/share/man/man3/puffs_fuse_node_create.3.gz +TO_REMOVE+=/usr/share/man/man3/puffs_fuse_node_getattr.3.gz +TO_REMOVE+=/usr/share/man/man3/puffs_fuse_node_link.3.gz +TO_REMOVE+=/usr/share/man/man3/puffs_fuse_node_mkdir.3.gz +TO_REMOVE+=/usr/share/man/man3/puffs_fuse_node_mknod.3.gz +TO_REMOVE+=/usr/share/man/man3/puffs_fuse_node_open.3.gz +TO_REMOVE+=/usr/share/man/man3/puffs_fuse_node_read.3.gz +TO_REMOVE+=/usr/share/man/man3/puffs_fuse_node_readdir.3.gz +TO_REMOVE+=/usr/share/man/man3/puffs_fuse_node_readlink.3.gz +TO_REMOVE+=/usr/share/man/man3/puffs_fuse_node_rename.3.gz +TO_REMOVE+=/usr/share/man/man3/puffs_fuse_node_rmdir.3.gz +TO_REMOVE+=/usr/share/man/man3/puffs_fuse_node_symlink.3.gz +TO_REMOVE+=/usr/share/man/man3/puffs_fuse_node_write.3.gz +TO_REMOVE+=/usr/share/man/man3/puffs_node.3.gz +TO_REMOVE+=/usr/share/man/man3/puffs_ops.3.gz +TO_REMOVE+=/usr/share/man/man3/puffs_path.3.gz +TO_REMOVE+=/usr/share/man/man3/refuse.3.gz +TO_REMOVE+=/usr/share/man/man4/puffs.4.gz +TO_REMOVE+=/usr/share/man/man8/mount_psshfs.8.gz +TO_REMOVE+=/usr/share/man/man9/putter.9.gz .if !defined(WANT_INSTALLER) TO_REMOVE+=/usr/sbin/dfuibe_installer diff --git a/UPDATING b/UPDATING index ef20c5c1dd..ae066786bb 100644 --- a/UPDATING +++ b/UPDATING @@ -12,6 +12,13 @@ + UPGRADING DRAGONFLY FROM 5.4 TO LATER VERSIONS + +-----------------------------------------------------------------------+ +PUFFS, PUTTER AND LIBREFUSE REMOVED +----------------------------------- + +The puffs(4)/putter(4) subsystem has been removed, along with librefuse, +libpuffs, and the mount_psshfs(8) utility. All of these have never been +working correctly. + FFS_ROOT OPTION REMOVED ----------------------- diff --git a/etc/mtree/BSD.include.dist b/etc/mtree/BSD.include.dist index a340562792..be5b4df547 100644 --- a/etc/mtree/BSD.include.dist +++ b/etc/mtree/BSD.include.dist @@ -273,8 +273,6 @@ .. ppi .. - putter - .. .. netif wi @@ -520,8 +518,6 @@ .. ntfs .. - puffs - .. smbfs .. tmpfs diff --git a/etc/mtree/BSD.usr.dist b/etc/mtree/BSD.usr.dist index 521ff22799..dbaf2cffa4 100644 --- a/etc/mtree/BSD.usr.dist +++ b/etc/mtree/BSD.usr.dist @@ -249,10 +249,6 @@ .. printing .. - puffs - pnullfs - .. - .. rconfig .. scsi_target diff --git a/gnu/usr.bin/groff/tmac/mdoc.local b/gnu/usr.bin/groff/tmac/mdoc.local index 52c483363c..31a4bd15c1 100644 --- a/gnu/usr.bin/groff/tmac/mdoc.local +++ b/gnu/usr.bin/groff/tmac/mdoc.local @@ -56,9 +56,7 @@ .ds doc-str-Lb-libnetgraph Netgraph User Library (libnetgraph, \-lnetgraph) .ds doc-str-Lb-libposix1e POSIX.1e Security API Library (libposix1e, \-lposix1e) .ds doc-str-Lb-libprop Property Container Object Library (libprop, \-lprop) -.ds doc-str-Lb-libpuffs puffs Convenience Library (libpuffs, \-lpuffs) .ds doc-str-Lb-libradius RADIUS Client and Server Library (libradius, \-lradius) -.ds doc-str-Lb-librefuse File System in Userspace Convenience Library (librefuse, \-lrefuse) .ds doc-str-Lb-librpcsvc RPC Service Library (librpcsvc, \-lrpcsvc) .ds doc-str-Lb-libsdp Bluetooth Service Discovery Protocol Library (libsdp, \-lsdp) .ds doc-str-Lb-libstand Standalone Applications Library (libstand, \-lstand) diff --git a/include/Makefile b/include/Makefile index 6fef985ce4..5cd05d5dd2 100644 --- a/include/Makefile +++ b/include/Makefile @@ -56,7 +56,7 @@ LSUBDIRS= \ bus/cam bus/pccard bus/pci bus/isa bus/ppbus bus/smbus bus/u4b \ dev/disk/dm \ dev/disk/mpt/mpilib \ - dev/misc/lpt dev/misc/ppi dev/misc/putter \ + dev/misc/lpt dev/misc/ppi \ dev/netif/wi \ dev/raid/ciss dev/raid/mfi \ dev/smbus/smb \ @@ -85,7 +85,7 @@ LSUBDIRS= \ netgraph7/pptpgre netgraph7/rfc1490 netgraph7/socket \ netgraph7/tcpmss netgraph7/tee netgraph7/tty netgraph7/vjc \ netproto/802_11 netproto/mpls netproto/smb \ - vfs/isofs/cd9660 vfs/puffs \ + vfs/isofs/cd9660 \ vfs/msdosfs vfs/nfs vfs/ntfs \ vfs/smbfs vfs/udf vfs/ufs vfs/hammer vfs/hammer2 \ vfs/autofs vfs/tmpfs diff --git a/lib/Makefile b/lib/Makefile index 79a1cab543..5257ec99a8 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -83,8 +83,6 @@ SUBDIR= ${SUBDIR_ORDERED} \ libpcap \ libposix1e \ libprop \ - libpuffs \ - librefuse \ librpcsvc \ libsdp \ ${_libsm} \ diff --git a/lib/libpuffs/Makefile b/lib/libpuffs/Makefile deleted file mode 100644 index 75bf701f1c..0000000000 --- a/lib/libpuffs/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# $NetBSD: Makefile,v 1.24 2010/12/06 14:50:34 pooka Exp $ -# - -WARNS= 2 - -LIB= puffs - -SRCS= puffs.c callcontext.c creds.c dispatcher.c flush.c \ - framebuf.c null.c opdump.c paths.c pnode.c requests.c \ - subr.c suspend.c -MAN= puffs.3 puffs_cc.3 puffs_cred.3 puffs_flush.3 \ - puffs_framebuf.3 puffs_node.3 puffs_ops.3 puffs_path.3 -INCS= puffs.h puffsdump.h -CFLAGS+= -I${.CURDIR}/../../sbin/mount - -.include diff --git a/lib/libpuffs/TODO b/lib/libpuffs/TODO deleted file mode 100644 index 0a5e3e28e9..0000000000 --- a/lib/libpuffs/TODO +++ /dev/null @@ -1,42 +0,0 @@ - $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?) diff --git a/lib/libpuffs/callcontext.c b/lib/libpuffs/callcontext.c deleted file mode 100644 index 2322a427a4..0000000000 --- a/lib/libpuffs/callcontext.c +++ /dev/null @@ -1,362 +0,0 @@ -/* $NetBSD: callcontext.c,v 1.25 2011/03/04 09:47:47 yamt Exp $ */ - -/* - * Copyright (c) 2006, 2007, 2008 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 -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "puffs.h" -#include "puffs_priv.h" - -#if 0 -#define DPRINTF(x) printf x -#else -#define DPRINTF(x) -#endif - -/* - * Set the following to 1 to not handle each request on a separate - * stack. This is highly volatile kludge, therefore no external - * interface. - */ -int puffs_fakecc; - -/* - * user stuff - */ - -/* - * So, we need to get back to where we came from. This can happen in two - * different ways: - * 1) PCC_MLCONT is set, in which case we need to go to the mainloop - * 2) It is not set, and we simply jump to pcc_uc_ret. - */ -void -puffs_cc_yield(struct puffs_cc *pcc) -{ - struct puffs_cc *jumpcc; - int rv; - - assert(puffs_fakecc == 0); - - pcc->pcc_flags &= ~PCC_BORROWED; - - /* romanes eunt domus */ - DPRINTF(("puffs_cc_yield: ")); - if ((pcc->pcc_flags & PCC_MLCONT) == 0) { - DPRINTF(("no mlcont, pcc %p\n", pcc)); - swapcontext(&pcc->pcc_uc, &pcc->pcc_uc_ret); - } else { - DPRINTF(("mlcont, pcc %p\n", pcc)); - pcc->pcc_flags &= ~PCC_MLCONT; - rv = puffs__cc_create(pcc->pcc_pu, puffs__theloop, &jumpcc); - if (rv) - abort(); /* p-p-p-pa-pa-panic (XXX: fixme) */ - swapcontext(&pcc->pcc_uc, &jumpcc->pcc_uc); - DPRINTF(("puffs_cc_yield: post swap pcc %p\n", pcc)); - } -} - -/* - * Internal continue routine. This has slightly different semantics. - * We simply make our cc available in the freelist and jump to the - * indicated pcc. - */ -void -puffs__cc_cont(struct puffs_cc *pcc) -{ - struct puffs_cc *mycc; - - mycc = puffs_cc_getcc(pcc->pcc_pu); - DPRINTF(("puffs__cc_cont: pcc %p, mycc %p\n", pcc, mycc)); - - /* - * XXX: race between setcontext() and recycle if - * we go multithreaded - */ - puffs__cc_destroy(mycc, 1); - pcc->pcc_flags |= PCC_MLCONT; - setcontext(&pcc->pcc_uc); -} - -void -puffs_cc_continue(struct puffs_cc *pcc) -{ - - /* ramble on */ - DPRINTF(("puffs_cc_continue: pcc %p\n", pcc)); - if (puffs_fakecc) { - pcc->pcc_func(pcc->pcc_farg); - } else { - swapcontext(&pcc->pcc_uc_ret, &pcc->pcc_uc); - } -} - -/* - * "Borrows" pcc, *NOT* called from pcc owner. Acts like continue. - * So the idea is to use this, give something the context back to - * run to completion and then jump back to where ever this was called - * from after the op dispatching is complete (or if the pcc decides to - * yield again). - */ -void -puffs__goto(struct puffs_cc *loanpcc) -{ - - loanpcc->pcc_flags |= PCC_BORROWED; - - swapcontext(&loanpcc->pcc_uc_ret, &loanpcc->pcc_uc); -} - -void -puffs_cc_schedule(struct puffs_cc *pcc) -{ - struct puffs_usermount *pu = pcc->pcc_pu; - - assert(pu->pu_state & PU_INLOOP); - TAILQ_INSERT_TAIL(&pu->pu_sched, pcc, pcc_schedent); -} - -int -puffs_cc_getcaller(struct puffs_cc *pcc, pid_t *pid, lwpid_t *lid) -{ - - if ((pcc->pcc_flags & PCC_HASCALLER) == 0) { - errno = ESRCH; - return -1; - } - - if (pid) - *pid = pcc->pcc_pid; - if (lid) - *lid = pcc->pcc_lid; - return 0; -} - -static struct puffs_cc fakecc; - -static struct puffs_cc * -slowccalloc(struct puffs_usermount *pu) -{ - struct puffs_cc *volatile pcc; - void *sp; - size_t stacksize = 1<pu_cc_stackshift; - size_t stackalign; - long psize = sysconf(_SC_PAGESIZE); - - if (puffs_fakecc) - return &fakecc; - - /* - * Emulate MAP_ALIGNED(pu->pu_cc_stackshift) by allocating stacksize*2 - * bytes and unmapping extra pages - */ - sp = mmap(NULL, stacksize * 2, PROT_READ|PROT_WRITE, - MAP_ANON|MAP_PRIVATE, -1, 0); - if (sp == MAP_FAILED) - return NULL; - stackalign = ((uintptr_t)sp) & (stacksize-1); - if (stackalign != 0) { - munmap(sp, stacksize - stackalign); - sp = (uint8_t *)sp + stacksize - stackalign; - munmap((uint8_t *)sp + stacksize, stackalign); - } else { - munmap((uint8_t *)sp + stacksize, stacksize); - } - - pcc = sp; - memset(pcc, 0, sizeof(struct puffs_cc)); - - mprotect((uint8_t *)sp + psize, (size_t)psize, PROT_NONE); - - /* initialize both ucontext's */ - if (getcontext(&pcc->pcc_uc) == -1) { - munmap(pcc, stacksize); - return NULL; - } - if (getcontext(&pcc->pcc_uc_ret) == -1) { - munmap(pcc, stacksize); - return NULL; - } - - return pcc; -} - -int -puffs__cc_create(struct puffs_usermount *pu, puffs_ccfunc func, - struct puffs_cc **pccp) -{ - struct puffs_cc *pcc; - size_t stacksize = 1<pu_cc_stackshift; - stack_t *st; - - /* Do we have a cached copy? */ - if (pu->pu_cc_nstored == 0) { - pcc = slowccalloc(pu); - if (pcc == NULL) - return -1; - pcc->pcc_pu = pu; - DPRINTF(("puffs__cc_create: allocated pcc %p\n", pcc)); - } else { - pcc = LIST_FIRST(&pu->pu_ccmagazin); - assert(pcc != NULL); - - LIST_REMOVE(pcc, pcc_rope); - pu->pu_cc_nstored--; - DPRINTF(("puffs__cc_create: magazin pcc %p\n", pcc)); - } - assert(pcc->pcc_pu == pu); - - if (puffs_fakecc) { - pcc->pcc_func = func; - pcc->pcc_farg = pcc; - } else { - /* link context */ - pcc->pcc_uc.uc_link = &pcc->pcc_uc_ret; - - /* setup stack - * - * XXX: I guess this should theoretically be preserved by - * swapcontext(). However, it gets lost. So reinit it. - */ - st = &pcc->pcc_uc.uc_stack; - st->ss_sp = (void *)pcc; - st->ss_size = stacksize; - st->ss_flags = 0; - - /* - * Give us an initial context to jump to. - * - * Our manual page says that portable code shouldn't - * rely on being able to pass pointers through makecontext(). - * kjk says that NetBSD code doesn't need to worry about this. - * uwe says it would be like putting a "keep away from - * children" sign on a box of toys. - */ - makecontext(&pcc->pcc_uc, (void *)func, 1, (uintptr_t)pcc); - } - - *pccp = pcc; - return 0; -} - -void -puffs__cc_setcaller(struct puffs_cc *pcc, pid_t pid, lwpid_t lid) -{ - - pcc->pcc_pid = pid; - pcc->pcc_lid = lid; - pcc->pcc_flags |= PCC_HASCALLER; -} - -static void -cc_free(struct puffs_cc *pcc) -{ - struct puffs_usermount *pu = pcc->pcc_pu; - size_t stacksize = 1<pu_cc_stackshift; - - DPRINTF(("invalidating pcc %p\n", pcc)); - assert(!puffs_fakecc); - munmap(pcc, stacksize); -} - -void -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); - - /* not over limit? stuff away in the store, otherwise nuke */ - if (nonuke || pu->pu_cc_nstored < PUFFS_CCMAXSTORE) { - pcc->pcc_pb = NULL; - DPRINTF(("puffs__cc_destroy: storing pcc %p\n", pcc)); - LIST_INSERT_HEAD(&pu->pu_ccmagazin, pcc, pcc_rope); - pu->pu_cc_nstored++; - } else { - cc_free(pcc); - } -} - -void -puffs__cc_exit(struct puffs_usermount *pu) -{ - struct puffs_cc *pcc; - - while ((pcc = LIST_FIRST(&pu->pu_ccmagazin)) != NULL) { - LIST_REMOVE(pcc, pcc_rope); - cc_free(pcc); - } -} - -struct puffs_cc * -puffs_cc_getcc(struct puffs_usermount *pu) -{ - size_t stacksize = 1<pu_cc_stackshift; - uintptr_t bottom; - - if (puffs_fakecc) - return &fakecc; - - bottom = ((uintptr_t)&bottom) & ~(stacksize-1); - return (struct puffs_cc *)bottom; -} - -int -puffs__cc_savemain(struct puffs_usermount *pu) -{ - - if (puffs_fakecc) - return 0; - - PU_CLRSFLAG(pu, PU_MAINRESTORE); - return getcontext(&pu->pu_mainctx); -} - -int -puffs__cc_restoremain(struct puffs_usermount *pu) -{ - - if (puffs_fakecc) - return 0; - - puffs__cc_destroy(puffs_cc_getcc(pu), 1); - PU_SETSFLAG(pu, PU_MAINRESTORE); - return setcontext(&pu->pu_mainctx); -} diff --git a/lib/libpuffs/creds.c b/lib/libpuffs/creds.c deleted file mode 100644 index 8a31503665..0000000000 --- a/lib/libpuffs/creds.c +++ /dev/null @@ -1,254 +0,0 @@ -/* $NetBSD: creds.c,v 1.15 2009/11/20 14:23:54 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. - */ - -/* - * Interface for dealing with credits. - */ - -#include -#include - -#include -#include -#include - -#include "puffs.h" -#include "puffs_priv.h" - -#define UUCCRED(a) (a->pkcr_type == PUFFCRED_TYPE_UUC) -#define INTCRED(a) (a->pkcr_type == PUFFCRED_TYPE_INTERNAL) - -int -puffs_cred_getuid(const struct puffs_cred *pcr, uid_t *ruid) -{ - PUFFS_MAKEKCRED(pkcr, pcr); - - if (!UUCCRED(pkcr)) { - errno = EOPNOTSUPP; - return -1; - } - *ruid = pkcr->pkcr_uuc.cr_uid; - - return 0; -} - -int -puffs_cred_getgid(const struct puffs_cred *pcr, gid_t *rgid) -{ - PUFFS_MAKEKCRED(pkcr, pcr); - - if (!UUCCRED(pkcr)) { - errno = EOPNOTSUPP; - return -1; - } - *rgid = pkcr->pkcr_uuc.cr_gid; - - return 0; -} - -int -puffs_cred_getgroups(const struct puffs_cred *pcr, gid_t *rgids, short *ngids) -{ - PUFFS_MAKEKCRED(pkcr, pcr); - size_t ncopy; - - if (!UUCCRED(pkcr)) { - errno = EOPNOTSUPP; - *ngids = 0; - return -1; - } - - ncopy = MIN(*ngids, pkcr->pkcr_uuc.cr_ngroups); - (void)memcpy(rgids, pkcr->pkcr_uuc.cr_groups, sizeof(gid_t) * ncopy); - *ngids = (short)ncopy; - - return 0; -} - -bool -puffs_cred_isuid(const struct puffs_cred *pcr, uid_t uid) -{ - PUFFS_MAKEKCRED(pkcr, pcr); - - return UUCCRED(pkcr) && pkcr->pkcr_uuc.cr_uid == uid; -} - -bool -puffs_cred_hasgroup(const struct puffs_cred *pcr, gid_t gid) -{ - PUFFS_MAKEKCRED(pkcr, pcr); - short i; - - if (!UUCCRED(pkcr)) - return false; - - if (pkcr->pkcr_uuc.cr_gid == gid) - return true; - for (i = 0; i < pkcr->pkcr_uuc.cr_ngroups; i++) - if (pkcr->pkcr_uuc.cr_groups[i] == gid) - return true; - - return false; -} - -bool -puffs_cred_isregular(const struct puffs_cred *pcr) -{ - PUFFS_MAKEKCRED(pkcr, pcr); - - return UUCCRED(pkcr); -} - -bool -puffs_cred_iskernel(const struct puffs_cred *pcr) -{ - PUFFS_MAKEKCRED(pkcr, pcr); - - return INTCRED(pkcr) && pkcr->pkcr_internal == PUFFCRED_CRED_NOCRED; -} - -bool -puffs_cred_isfs(const struct puffs_cred *pcr) -{ - PUFFS_MAKEKCRED(pkcr, pcr); - - return INTCRED(pkcr) && pkcr->pkcr_internal == PUFFCRED_CRED_FSCRED; -} - -bool -puffs_cred_isjuggernaut(const struct puffs_cred *pcr) -{ - - return puffs_cred_isuid(pcr, 0) || puffs_cred_iskernel(pcr) - || puffs_cred_isfs(pcr); -} - -/* - * Generic routine for checking file access rights. Modeled after - * vaccess() in the kernel. - */ -int -puffs_access(enum vtype type, mode_t file_mode, uid_t uid, gid_t gid, - mode_t acc_mode, const struct puffs_cred *pcr) -{ - mode_t mask; - - /* megapower */ - if (puffs_cred_iskernel(pcr) || puffs_cred_isfs(pcr)) - return 0; - - /* superuser, allow all except exec if *ALL* exec bits are unset */ - if (puffs_cred_isuid(pcr, 0)) { - if ((acc_mode & PUFFS_VEXEC) && type != VDIR && - (file_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0) - return EACCES; - return 0; - } - - mask = 0; - /* owner */ - if (puffs_cred_isuid(pcr, uid)) { - if (acc_mode & PUFFS_VEXEC) - mask |= S_IXUSR; - if (acc_mode & PUFFS_VREAD) - mask |= S_IRUSR; - if (acc_mode & PUFFS_VWRITE) - mask |= S_IWUSR; - /* group */ - } else if (puffs_cred_hasgroup(pcr, gid)) { - if (acc_mode & PUFFS_VEXEC) - mask |= S_IXGRP; - if (acc_mode & PUFFS_VREAD) - mask |= S_IRGRP; - if (acc_mode & PUFFS_VWRITE) - mask |= S_IWGRP; - /* other */ - } else { - if (acc_mode & PUFFS_VEXEC) - mask |= S_IXOTH; - if (acc_mode & PUFFS_VREAD) - mask |= S_IROTH; - if (acc_mode & PUFFS_VWRITE) - mask |= S_IWOTH; - } - - if ((file_mode & mask) == mask) - return 0; - else - return EACCES; -} - -int -puffs_access_chown(uid_t owner, gid_t group, uid_t newowner, gid_t newgroup, - const struct puffs_cred *pcr) -{ - - if (newowner == (uid_t)PUFFS_VNOVAL) - newowner = owner; - if (newgroup == (gid_t)PUFFS_VNOVAL) - newgroup = group; - - if ((!puffs_cred_isuid(pcr, owner) || newowner != owner || - ((newgroup != group && !puffs_cred_hasgroup(pcr, newgroup)))) - && !puffs_cred_isjuggernaut(pcr)) - return EPERM; - - return 0; -} - -int -puffs_access_chmod(uid_t owner, gid_t group, enum vtype type, mode_t mode, - const struct puffs_cred *pcr) -{ - - if (!puffs_cred_isuid(pcr, owner) && !puffs_cred_isjuggernaut(pcr)) - return EPERM; - - if (!puffs_cred_isjuggernaut(pcr)) { - if (type != VDIR && (mode & S_ISTXT)) - return EFTYPE; - if (!puffs_cred_hasgroup(pcr, group) && (mode & S_ISGID)) - return EPERM; - } - - return 0; -} - -int -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)) - return EPERM; - - return 0; -} diff --git a/lib/libpuffs/dispatcher.c b/lib/libpuffs/dispatcher.c deleted file mode 100644 index 7242bd1881..0000000000 --- a/lib/libpuffs/dispatcher.c +++ /dev/null @@ -1,1103 +0,0 @@ -/* $NetBSD: dispatcher.c,v 1.36 2011/07/04 08:07:30 manu Exp $ */ - -/* - * Copyright (c) 2006, 2007, 2008 Antti Kantee. All Rights Reserved. - * - * Development of this software was supported by the - * Ulla Tuominen Foundation, the Finnish Cultural Foundation and - * 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 -#include - -#include -#include -#include -#include -#include -#include - -#include "puffs.h" -#include "puffsdump.h" -#include "puffs_priv.h" - -static void dispatch(struct puffs_cc *); - -/* for our eyes only */ -void -puffs__ml_dispatch(struct puffs_usermount *pu, struct puffs_framebuf *pb) -{ - struct puffs_cc *pcc = puffs_cc_getcc(pu); - struct puffs_req *preq; - - pcc->pcc_pb = pb; - pcc->pcc_flags |= PCC_MLCONT; - dispatch(pcc); - - /* Put result to kernel sendqueue if necessary */ - preq = puffs__framebuf_getdataptr(pcc->pcc_pb); - if (PUFFSOP_WANTREPLY(preq->preq_opclass)) { - if (pu->pu_flags & PUFFS_FLAG_OPDUMP) - puffsdump_rv(preq); - - puffs_framev_enqueue_justsend(pu, pu->pu_fd, - pcc->pcc_pb, 0, 0); - } else { - puffs_framebuf_destroy(pcc->pcc_pb); - } - - /* who needs information when you're living on borrowed time? */ - if (pcc->pcc_flags & PCC_BORROWED) { - puffs_cc_yield(pcc); /* back to borrow source */ - } - pcc->pcc_flags = 0; -} - -/* public, but not really tested and only semi-supported */ -int -puffs_dispatch_create(struct puffs_usermount *pu, struct puffs_framebuf *pb, - struct puffs_cc **pccp) -{ - struct puffs_cc *pcc; - - if (puffs__cc_create(pu, dispatch, &pcc) == -1) - return -1; - - pcc->pcc_pb = pb; - *pccp = pcc; - - return 0; -} - -int -puffs_dispatch_exec(struct puffs_cc *pcc, struct puffs_framebuf **pbp) -{ - int rv; - - puffs_cc_continue(pcc); - - if (pcc->pcc_flags & PCC_DONE) { - rv = 1; - *pbp = pcc->pcc_pb; - pcc->pcc_flags = 0; - puffs__cc_destroy(pcc, 0); - } else { - rv = 0; - } - - return rv; -} - -static void -dispatch(struct puffs_cc *pcc) -{ - struct puffs_usermount *pu = pcc->pcc_pu; - struct puffs_ops *pops = &pu->pu_ops; - struct puffs_req *preq = puffs__framebuf_getdataptr(pcc->pcc_pb); - void *auxbuf; /* help with typecasting */ - puffs_cookie_t opcookie; - int error = 0, buildpath; - - /* XXX: smaller hammer, please */ - if ((PUFFSOP_OPCLASS(preq->preq_opclass == PUFFSOP_VFS && - preq->preq_optype == PUFFS_VFS_VPTOFH)) || - (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN && - (preq->preq_optype == PUFFS_VN_READDIR - || preq->preq_optype == PUFFS_VN_READ))) { - if (puffs_framebuf_reserve_space(pcc->pcc_pb, - PUFFS_MSG_MAXSIZE) == -1) - error = errno; - preq = puffs__framebuf_getdataptr(pcc->pcc_pb); - } - - auxbuf = preq; - opcookie = preq->preq_cookie; - - assert((pcc->pcc_flags & PCC_DONE) == 0); - - buildpath = pu->pu_flags & PUFFS_FLAG_BUILDPATH; - preq->preq_setbacks = 0; - - if (pu->pu_flags & PUFFS_FLAG_OPDUMP) - puffsdump_req(preq); - - puffs__cc_setcaller(pcc, preq->preq_pid, preq->preq_lid); - - /* pre-operation */ - if (pu->pu_oppre) - pu->pu_oppre(pu); - - if (error) - goto out; - - /* Execute actual operation */ - if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VFS) { - switch (preq->preq_optype) { - case PUFFS_VFS_UNMOUNT: - { - struct puffs_vfsmsg_unmount *auxt = auxbuf; - - PU_SETSTATE(pu, PUFFS_STATE_UNMOUNTING); - error = pops->puffs_fs_unmount(pu, auxt->pvfsr_flags); - if (!error) - PU_SETSTATE(pu, PUFFS_STATE_UNMOUNTED); - else - PU_SETSTATE(pu, PUFFS_STATE_RUNNING); - break; - } - - case PUFFS_VFS_STATVFS: - { - struct puffs_vfsmsg_statvfs *auxt = auxbuf; - - error = pops->puffs_fs_statvfs(pu, &auxt->pvfsr_sb); - break; - } - - case PUFFS_VFS_SYNC: - { - struct puffs_vfsmsg_sync *auxt = auxbuf; - - error = pops->puffs_fs_sync(pu, - auxt->pvfsr_waitfor); - break; - } - - case PUFFS_VFS_FHTOVP: - { - struct puffs_vfsmsg_fhtonode *auxt = auxbuf; - struct puffs_newinfo pni; - - pni.pni_cookie = &auxt->pvfsr_fhcookie; - pni.pni_vtype = &auxt->pvfsr_vtype; - pni.pni_size = &auxt->pvfsr_size; - - error = pops->puffs_fs_fhtonode(pu, auxt->pvfsr_data, - auxt->pvfsr_dsize, &pni); - - break; - } - - case PUFFS_VFS_VPTOFH: - { - struct puffs_vfsmsg_nodetofh *auxt = auxbuf; - - error = pops->puffs_fs_nodetofh(pu, - auxt->pvfsr_fhcookie, auxt->pvfsr_data, - &auxt->pvfsr_dsize); - - break; - } - - case PUFFS_VFS_EXTATTRCTL: - { - struct puffs_vfsmsg_extattrctl *auxt = auxbuf; - const char *attrname; - int flags; - - if (pops->puffs_fs_extattrctl == NULL) { - error = EOPNOTSUPP; - break; - } - - if (auxt->pvfsr_flags & PUFFS_EXTATTRCTL_HASATTRNAME) - attrname = auxt->pvfsr_attrname; - else - attrname = NULL; - - flags = auxt->pvfsr_flags & PUFFS_EXTATTRCTL_HASNODE; - error = pops->puffs_fs_extattrctl(pu, auxt->pvfsr_cmd, - opcookie, flags, - auxt->pvfsr_attrnamespace, attrname); - break; - } - - default: - /* - * I guess the kernel sees this one coming - */ - error = EINVAL; - break; - } - - /* XXX: audit return values */ - /* XXX: sync with kernel */ - } else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN) { - switch (preq->preq_optype) { - case PUFFS_VN_LOOKUP: - { - struct puffs_vnmsg_lookup *auxt = auxbuf; - struct puffs_newinfo pni; - struct puffs_cn pcn; - - pcn.pcn_pkcnp = &auxt->pvnr_cn; - PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred); - pni.pni_cookie = &auxt->pvnr_newnode; - pni.pni_vtype = &auxt->pvnr_vtype; - pni.pni_size = &auxt->pvnr_size; - - if (buildpath) { - error = puffs_path_pcnbuild(pu, &pcn, opcookie); - if (error) - break; - } - - /* lookup *must* be present */ - error = pops->puffs_node_lookup(pu, opcookie, - &pni, &pcn); - - if (buildpath) { - if (error) { - pu->pu_pathfree(pu, &pcn.pcn_po_full); - } else { - struct puffs_node *pn; - - /* - * did we get a new node or a - * recycled node? - */ - pn = PU_CMAP(pu, auxt->pvnr_newnode); - if (pn->pn_po.po_path == NULL) - pn->pn_po = pcn.pcn_po_full; - else - pu->pu_pathfree(pu, - &pcn.pcn_po_full); - } - } - - break; - } - - case PUFFS_VN_LOOKUPDOTDOT: - { - struct puffs_kcn kcn = { - .pkcn_name = "..", - .pkcn_namelen = 2, - }; - struct puffs_vnmsg_lookupdotdot *auxt = auxbuf; - struct puffs_newinfo pni; - struct puffs_cn pcn; - - pcn.pcn_pkcnp = &kcn; - PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cred); - pni.pni_cookie = &auxt->pvnr_newnode; - pni.pni_vtype = NULL; - pni.pni_size = NULL; - - if (buildpath) { - error = puffs_path_pcnbuild(pu, &pcn, opcookie); - if (error) - break; - } - - /* lookup *must* be present */ - error = pops->puffs_node_lookupdotdot(pu, opcookie, - &pni, &pcn); - - if (buildpath) { - if (error) { - pu->pu_pathfree(pu, &pcn.pcn_po_full); - } else { - struct puffs_node *pn; - - /* - * did we get a new node or a - * recycled node? - */ - pn = PU_CMAP(pu, auxt->pvnr_newnode); - if (pn->pn_po.po_path == NULL) - pn->pn_po = pcn.pcn_po_full; - else - pu->pu_pathfree(pu, - &pcn.pcn_po_full); - } - } - break; - } - - case PUFFS_VN_CREATE: - { - struct puffs_vnmsg_create *auxt = auxbuf; - struct puffs_newinfo pni; - struct puffs_cn pcn; - - if (pops->puffs_node_create == NULL) { - error = 0; - break; - } - - pcn.pcn_pkcnp = &auxt->pvnr_cn; - PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred); - - memset(&pni, 0, sizeof(pni)); - pni.pni_cookie = &auxt->pvnr_newnode; - - if (buildpath) { - error = puffs_path_pcnbuild(pu, &pcn, opcookie); - if (error) - break; - } - - error = pops->puffs_node_create(pu, - opcookie, &pni, &pcn, &auxt->pvnr_va); - - if (buildpath) { - if (error) { - pu->pu_pathfree(pu, &pcn.pcn_po_full); - } else { - struct puffs_node *pn; - - pn = PU_CMAP(pu, auxt->pvnr_newnode); - pn->pn_po = pcn.pcn_po_full; - } - } - - break; - } - - case PUFFS_VN_MKNOD: - { - struct puffs_vnmsg_mknod *auxt = auxbuf; - struct puffs_newinfo pni; - struct puffs_cn pcn; - - if (pops->puffs_node_mknod == NULL) { - error = 0; - break; - } - - pcn.pcn_pkcnp = &auxt->pvnr_cn; - PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred); - - memset(&pni, 0, sizeof(pni)); - pni.pni_cookie = &auxt->pvnr_newnode; - - if (buildpath) { - error = puffs_path_pcnbuild(pu, &pcn, opcookie); - if (error) - break; - } - - error = pops->puffs_node_mknod(pu, - opcookie, &pni, &pcn, &auxt->pvnr_va); - - if (buildpath) { - if (error) { - pu->pu_pathfree(pu, &pcn.pcn_po_full); - } else { - struct puffs_node *pn; - - pn = PU_CMAP(pu, auxt->pvnr_newnode); - pn->pn_po = pcn.pcn_po_full; - } - } - - break; - } - - case PUFFS_VN_OPEN: - { - struct puffs_vnmsg_open *auxt = auxbuf; - PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); - - if (pops->puffs_node_open == NULL) { - error = 0; - break; - } - - error = pops->puffs_node_open(pu, - opcookie, auxt->pvnr_mode, pcr); - break; - } - - case PUFFS_VN_CLOSE: - { - struct puffs_vnmsg_close *auxt = auxbuf; - - if (pops->puffs_node_close == NULL) { - error = 0; - break; - } - - error = pops->puffs_node_close(pu, - opcookie, auxt->pvnr_fflag); - break; - } - - case PUFFS_VN_ACCESS: - { - struct puffs_vnmsg_access *auxt = auxbuf; - PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); - - if (pops->puffs_node_access == NULL) { - error = 0; - break; - } - - error = pops->puffs_node_access(pu, - opcookie, auxt->pvnr_mode, pcr); - break; - } - - case PUFFS_VN_GETATTR: - { - struct puffs_vnmsg_getattr *auxt = auxbuf; - PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); - - if (pops->puffs_node_getattr == NULL) { - error = EOPNOTSUPP; - break; - } - - error = pops->puffs_node_getattr(pu, - opcookie, &auxt->pvnr_va, pcr); - break; - } - - case PUFFS_VN_SETATTR: - { - struct puffs_vnmsg_setattr *auxt = auxbuf; - PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); - - if (pops->puffs_node_setattr == NULL) { - error = EOPNOTSUPP; - break; - } - - error = pops->puffs_node_setattr(pu, - opcookie, &auxt->pvnr_va, pcr); - break; - } - - case PUFFS_VN_MMAP: - { - struct puffs_vnmsg_mmap *auxt = auxbuf; - PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); - - if (pops->puffs_node_mmap == NULL) { - error = 0; - break; - } - - error = pops->puffs_node_mmap(pu, - opcookie, auxt->pvnr_prot, pcr); - break; - } - - case PUFFS_VN_FSYNC: - { - struct puffs_vnmsg_fsync *auxt = auxbuf; - - if (pops->puffs_node_fsync == NULL) { - error = 0; - break; - } - - error = pops->puffs_node_fsync(pu, opcookie, - auxt->pvnr_flags); - break; - } - - case PUFFS_VN_SEEK: - { - struct puffs_vnmsg_seek *auxt = auxbuf; - PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); - - if (pops->puffs_node_seek == NULL) { - error = 0; - break; - } - - error = pops->puffs_node_seek(pu, - opcookie, auxt->pvnr_oldoff, - auxt->pvnr_newoff, pcr); - break; - } - - case PUFFS_VN_REMOVE: - { - struct puffs_vnmsg_remove *auxt = auxbuf; - struct puffs_cn pcn; - if (pops->puffs_node_remove == NULL) { - error = 0; - break; - } - - pcn.pcn_pkcnp = &auxt->pvnr_cn; - PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred); - - error = pops->puffs_node_remove(pu, - opcookie, auxt->pvnr_cookie_targ, &pcn); - break; - } - - case PUFFS_VN_LINK: - { - struct puffs_vnmsg_link *auxt = auxbuf; - struct puffs_cn pcn; - if (pops->puffs_node_link == NULL) { - error = 0; - break; - } - - pcn.pcn_pkcnp = &auxt->pvnr_cn; - PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred); - - if (buildpath) { - error = puffs_path_pcnbuild(pu, &pcn, opcookie); - if (error) - break; - } - - error = pops->puffs_node_link(pu, - opcookie, auxt->pvnr_cookie_targ, &pcn); - if (buildpath) - pu->pu_pathfree(pu, &pcn.pcn_po_full); - - break; - } - - case PUFFS_VN_RENAME: - { - struct puffs_vnmsg_rename *auxt = auxbuf; - struct puffs_cn pcn_src, pcn_targ; - struct puffs_node *pn_src; - - if (pops->puffs_node_rename == NULL) { - error = 0; - break; - } - - pcn_src.pcn_pkcnp = &auxt->pvnr_cn_src; - PUFFS_KCREDTOCRED(pcn_src.pcn_cred, - &auxt->pvnr_cn_src_cred); - - pcn_targ.pcn_pkcnp = &auxt->pvnr_cn_targ; - PUFFS_KCREDTOCRED(pcn_targ.pcn_cred, - &auxt->pvnr_cn_targ_cred); - - if (buildpath) { - pn_src = auxt->pvnr_cookie_src; - pcn_src.pcn_po_full = pn_src->pn_po; - - error = puffs_path_pcnbuild(pu, &pcn_targ, - auxt->pvnr_cookie_targdir); - if (error) - break; - } - - error = pops->puffs_node_rename(pu, - opcookie, auxt->pvnr_cookie_src, - &pcn_src, auxt->pvnr_cookie_targdir, - auxt->pvnr_cookie_targ, &pcn_targ); - - if (buildpath) { - if (error) { - pu->pu_pathfree(pu, - &pcn_targ.pcn_po_full); - } else { - struct puffs_pathinfo pi; - struct puffs_pathobj po_old; - - /* handle this node */ - po_old = pn_src->pn_po; - pn_src->pn_po = pcn_targ.pcn_po_full; - - if (pn_src->pn_va.va_type != VDIR) { - pu->pu_pathfree(pu, &po_old); - break; - } - - /* handle all child nodes for DIRs */ - pi.pi_old = &pcn_src.pcn_po_full; - pi.pi_new = &pcn_targ.pcn_po_full; - - PU_LOCK(); - if (puffs_pn_nodewalk(pu, - puffs_path_prefixadj, &pi) != NULL) - error = ENOMEM; - PU_UNLOCK(); - pu->pu_pathfree(pu, &po_old); - } - } - break; - } - - case PUFFS_VN_MKDIR: - { - struct puffs_vnmsg_mkdir *auxt = auxbuf; - struct puffs_newinfo pni; - struct puffs_cn pcn; - - if (pops->puffs_node_mkdir == NULL) { - error = 0; - break; - } - - pcn.pcn_pkcnp = &auxt->pvnr_cn; - PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred); - - memset(&pni, 0, sizeof(pni)); - pni.pni_cookie = &auxt->pvnr_newnode; - - if (buildpath) { - error = puffs_path_pcnbuild(pu, &pcn, opcookie); - if (error) - break; - } - - error = pops->puffs_node_mkdir(pu, - opcookie, &pni, &pcn, &auxt->pvnr_va); - - if (buildpath) { - if (error) { - pu->pu_pathfree(pu, &pcn.pcn_po_full); - } else { - struct puffs_node *pn; - - pn = PU_CMAP(pu, auxt->pvnr_newnode); - pn->pn_po = pcn.pcn_po_full; - } - } - - break; - } - - case PUFFS_VN_RMDIR: - { - struct puffs_vnmsg_rmdir *auxt = auxbuf; - struct puffs_cn pcn; - if (pops->puffs_node_rmdir == NULL) { - error = 0; - break; - } - - pcn.pcn_pkcnp = &auxt->pvnr_cn; - PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred); - - error = pops->puffs_node_rmdir(pu, - opcookie, auxt->pvnr_cookie_targ, &pcn); - break; - } - - case PUFFS_VN_SYMLINK: - { - struct puffs_vnmsg_symlink *auxt = auxbuf; - struct puffs_newinfo pni; - struct puffs_cn pcn; - - if (pops->puffs_node_symlink == NULL) { - error = 0; - break; - } - - pcn.pcn_pkcnp = &auxt->pvnr_cn; - PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred); - - memset(&pni, 0, sizeof(pni)); - pni.pni_cookie = &auxt->pvnr_newnode; - - if (buildpath) { - error = puffs_path_pcnbuild(pu, &pcn, opcookie); - if (error) - break; - } - - error = pops->puffs_node_symlink(pu, - opcookie, &pni, &pcn, - &auxt->pvnr_va, auxt->pvnr_link); - - if (buildpath) { - if (error) { - pu->pu_pathfree(pu, &pcn.pcn_po_full); - } else { - struct puffs_node *pn; - - pn = PU_CMAP(pu, auxt->pvnr_newnode); - pn->pn_po = pcn.pcn_po_full; - } - } - - break; - } - - case PUFFS_VN_READDIR: - { - struct puffs_vnmsg_readdir *auxt = auxbuf; - PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); - struct dirent *dent; - off_t *cookies; - size_t res, origcookies; - - if (pops->puffs_node_readdir == NULL) { - error = 0; - break; - } - - if (auxt->pvnr_ncookies) { - /* LINTED: pvnr_data is __aligned() */ - cookies = (off_t *)auxt->pvnr_data; - origcookies = auxt->pvnr_ncookies; - } else { - cookies = NULL; - origcookies = 0; - } - /* LINTED: dentoff is aligned in the kernel */ - dent = (struct dirent *) - (auxt->pvnr_data + auxt->pvnr_dentoff); - - res = auxt->pvnr_resid; - error = pops->puffs_node_readdir(pu, - opcookie, dent, &auxt->pvnr_offset, - &auxt->pvnr_resid, pcr, &auxt->pvnr_eofflag, - cookies, &auxt->pvnr_ncookies); - - /* much easier to track non-working NFS */ - assert(auxt->pvnr_ncookies <= origcookies); - - /* need to move a bit more */ - preq->preq_buflen = sizeof(struct puffs_vnmsg_readdir) - + auxt->pvnr_dentoff + (res - auxt->pvnr_resid); - break; - } - - case PUFFS_VN_READLINK: - { - struct puffs_vnmsg_readlink *auxt = auxbuf; - PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); - - if (pops->puffs_node_readlink == NULL) { - error = EOPNOTSUPP; - break; - } - - /*LINTED*/ - error = pops->puffs_node_readlink(pu, opcookie, pcr, - auxt->pvnr_link, &auxt->pvnr_linklen); - break; - } - - case PUFFS_VN_RECLAIM: - { - - if (pops->puffs_node_reclaim == NULL) { - error = 0; - break; - } - - error = pops->puffs_node_reclaim(pu, opcookie); - break; - } - - case PUFFS_VN_INACTIVE: - { - - if (pops->puffs_node_inactive == NULL) { - error = EOPNOTSUPP; - break; - } - - error = pops->puffs_node_inactive(pu, opcookie); - break; - } - - case PUFFS_VN_PATHCONF: - { - struct puffs_vnmsg_pathconf *auxt = auxbuf; - if (pops->puffs_node_pathconf == NULL) { - error = 0; - break; - } - - error = pops->puffs_node_pathconf(pu, - opcookie, auxt->pvnr_name, - &auxt->pvnr_retval); - break; - } - - case PUFFS_VN_ADVLOCK: - { - struct puffs_vnmsg_advlock *auxt = auxbuf; - if (pops->puffs_node_advlock == NULL) { - error = 0; - break; - } - - error = pops->puffs_node_advlock(pu, - opcookie, auxt->pvnr_id, auxt->pvnr_op, - &auxt->pvnr_fl, auxt->pvnr_flags); - break; - } - - case PUFFS_VN_PRINT: - { - if (pops->puffs_node_print == NULL) { - error = 0; - break; - } - - error = pops->puffs_node_print(pu, - opcookie); - break; - } - - case PUFFS_VN_ABORTOP: - { - struct puffs_vnmsg_abortop *auxt = auxbuf; - struct puffs_cn pcn; - - if (pops->puffs_node_abortop == NULL) { - error = 0; - break; - } - - pcn.pcn_pkcnp = &auxt->pvnr_cn; - PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred); - - error = pops->puffs_node_abortop(pu, opcookie, &pcn); - - break; - } - - case PUFFS_VN_READ: - { - struct puffs_vnmsg_read *auxt = auxbuf; - PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); - size_t res; - - if (pops->puffs_node_read == NULL) { - error = EIO; - break; - } - - res = auxt->pvnr_resid; - error = pops->puffs_node_read(pu, - opcookie, auxt->pvnr_data, - auxt->pvnr_offset, &auxt->pvnr_resid, - pcr, auxt->pvnr_ioflag); - - /* need to move a bit more */ - preq->preq_buflen = sizeof(struct puffs_vnmsg_read) - + (res - auxt->pvnr_resid); - break; - } - - case PUFFS_VN_WRITE: - { - struct puffs_vnmsg_write *auxt = auxbuf; - PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); - - if (pops->puffs_node_write == NULL) { - error = EIO; - break; - } - - error = pops->puffs_node_write(pu, - opcookie, auxt->pvnr_data, - auxt->pvnr_offset, &auxt->pvnr_resid, - pcr, auxt->pvnr_ioflag); - - /* don't need to move data back to the kernel */ - preq->preq_buflen = sizeof(struct puffs_vnmsg_write); - break; - } - - case PUFFS_VN_POLL: - { - struct puffs_vnmsg_poll *auxt = auxbuf; - - if (pops->puffs_node_poll == NULL) { - error = 0; - - /* emulate genfs_poll() */ - auxt->pvnr_events &= (POLLIN | POLLOUT - | POLLRDNORM | POLLWRNORM); - - break; - } - - error = pops->puffs_node_poll(pu, - opcookie, &auxt->pvnr_events); - break; - } - - case PUFFS_VN_GETEXTATTR: - { - struct puffs_vnmsg_getextattr *auxt = auxbuf; - PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); - size_t res, *resp, *sizep; - uint8_t *data; - - if (pops->puffs_node_getextattr == NULL) { - error = EOPNOTSUPP; - break; - } - - if (auxt->pvnr_datasize) - sizep = &auxt->pvnr_datasize; - else - sizep = NULL; - - res = auxt->pvnr_resid; - if (res > 0) { - data = auxt->pvnr_data; - resp = &auxt->pvnr_resid; - } else { - data = NULL; - resp = NULL; - } - - error = pops->puffs_node_getextattr(pu, - opcookie, auxt->pvnr_attrnamespace, - auxt->pvnr_attrname, sizep, data, resp, pcr); - - /* need to move a bit more? */ - preq->preq_buflen = - sizeof(struct puffs_vnmsg_getextattr) - + (res - auxt->pvnr_resid); - break; - } - - case PUFFS_VN_SETEXTATTR: - { - struct puffs_vnmsg_setextattr *auxt = auxbuf; - PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); - size_t *resp; - uint8_t *data; - - if (pops->puffs_node_setextattr == NULL) { - error = EOPNOTSUPP; - break; - } - - if (auxt->pvnr_resid > 0) { - data = auxt->pvnr_data; - resp = &auxt->pvnr_resid; - } else { - data = NULL; - resp = NULL; - } - - error = pops->puffs_node_setextattr(pu, - opcookie, auxt->pvnr_attrnamespace, - auxt->pvnr_attrname, data, resp, pcr); - break; - } - - case PUFFS_VN_LISTEXTATTR: - { - struct puffs_vnmsg_listextattr *auxt = auxbuf; - PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); - size_t res, *resp, *sizep; - int flag; - uint8_t *data; - - if (pops->puffs_node_listextattr == NULL) { - error = EOPNOTSUPP; - break; - } - - if (auxt->pvnr_datasize) - sizep = &auxt->pvnr_datasize; - else - sizep = NULL; - - res = auxt->pvnr_resid; - if (res > 0) { - data = auxt->pvnr_data; - resp = &auxt->pvnr_resid; - } else { - data = NULL; - resp = NULL; - } - - res = auxt->pvnr_resid; - flag = auxt->pvnr_flag; - error = pops->puffs_node_listextattr(pu, - opcookie, auxt->pvnr_attrnamespace, - sizep, data, resp, flag, pcr); - - /* need to move a bit more? */ - preq->preq_buflen = - sizeof(struct puffs_vnmsg_listextattr) - + (res - auxt->pvnr_resid); - break; - } - - case PUFFS_VN_DELETEEXTATTR: - { - struct puffs_vnmsg_deleteextattr *auxt = auxbuf; - PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); - - if (pops->puffs_node_deleteextattr == NULL) { - error = EOPNOTSUPP; - break; - } - - error = pops->puffs_node_deleteextattr(pu, - opcookie, auxt->pvnr_attrnamespace, - auxt->pvnr_attrname, pcr); - break; - } - - default: - printf("inval op %d\n", preq->preq_optype); - error = EINVAL; - break; - } - -#if 0 - /* not issued by kernel currently */ - } else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_CACHE) { - struct puffs_cacheinfo *pci = (void *)preq; - - if (pu->pu_ops.puffs_cache_write) { - pu->pu_ops.puffs_cache_write(pu, preq->preq_cookie, - pci->pcache_nruns, pci->pcache_runs); - } - error = 0; -#endif - - } else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_ERROR) { - struct puffs_error *perr = (void *)preq; - - pu->pu_errnotify(pu, preq->preq_optype, - perr->perr_error, perr->perr_str, preq->preq_cookie); - error = 0; - } else { - /* - * I guess the kernel sees this one coming also - */ - error = EINVAL; - } - - out: - preq->preq_rv = error; - - if (pu->pu_oppost) - pu->pu_oppost(pu); - - pcc->pcc_flags |= PCC_DONE; -} diff --git a/lib/libpuffs/flush.c b/lib/libpuffs/flush.c deleted file mode 100644 index cf149f2100..0000000000 --- a/lib/libpuffs/flush.c +++ /dev/null @@ -1,130 +0,0 @@ -/* $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. - */ - -/* - * Flushing / invalidation routines - */ - -#include - -#include -#include -#include -#include -#include - -#include "puffs.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); -} diff --git a/lib/libpuffs/framebuf.c b/lib/libpuffs/framebuf.c deleted file mode 100644 index 0d40ed7bc6..0000000000 --- a/lib/libpuffs/framebuf.c +++ /dev/null @@ -1,1066 +0,0 @@ -/* $NetBSD: framebuf.c,v 1.30 2010/01/12 18:42:38 pooka Exp $ */ - -/* - * Copyright (c) 2007 Antti Kantee. All Rights Reserved. - * - * Development of this software was supported by the - * Finnish Cultural 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. - */ - -/* - * The event portion of this code is a twisty maze of pointers, - * flags, yields and continues. Sincere aplogies. - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "puffs.h" -#include "puffs_priv.h" - -struct puffs_framebuf { - struct puffs_cc *pcc; /* pcc to continue with */ - /* OR */ - puffs_framev_cb fcb; /* non-blocking callback */ - void *fcb_arg; /* argument for previous */ - - uint8_t *buf; /* buffer base */ - size_t len; /* total length */ - - size_t offset; /* cursor, telloff() */ - size_t maxoff; /* maximum offset for data, tellsize() */ - - volatile int rv; /* errno value */ - - int istat; - - TAILQ_ENTRY(puffs_framebuf) pfb_entries; -}; -#define ISTAT_NODESTROY 0x01 /* indestructible by framebuf_destroy() */ -#define ISTAT_INTERNAL 0x02 /* never leaves library */ -#define ISTAT_NOREPLY 0x04 /* nuke after sending */ -#define ISTAT_DIRECT 0x08 /* receive directly, no moveinfo */ - -#define ISTAT_ONQUEUE ISTAT_NODESTROY /* alias */ - -#define PUFBUF_INCRALLOC 4096 -#define PUFBUF_REMAIN(p) (p->len - p->offset) - -/* for poll/kqueue */ -struct puffs_fbevent { - struct puffs_cc *pcc; - int what; - volatile int rv; - - LIST_ENTRY(puffs_fbevent) pfe_entries; -}; - -static struct puffs_fctrl_io * -getfiobyfd(struct puffs_usermount *pu, int fd) -{ - struct puffs_fctrl_io *fio; - - LIST_FOREACH(fio, &pu->pu_ios, fio_entries) - if (fio->io_fd == fd) - return fio; - return NULL; -} - -struct puffs_framebuf * -puffs_framebuf_make(void) -{ - struct puffs_framebuf *pufbuf; - - pufbuf = malloc(sizeof(struct puffs_framebuf)); - if (pufbuf == NULL) - return NULL; - memset(pufbuf, 0, sizeof(struct puffs_framebuf)); - - pufbuf->buf = malloc(PUFBUF_INCRALLOC); - if (pufbuf->buf == NULL) { - free(pufbuf); - return NULL; - } - pufbuf->len = PUFBUF_INCRALLOC; - - puffs_framebuf_recycle(pufbuf); - return pufbuf; -} - -void -puffs_framebuf_destroy(struct puffs_framebuf *pufbuf) -{ - - assert((pufbuf->istat & ISTAT_NODESTROY) == 0); - - free(pufbuf->buf); - free(pufbuf); -} - -void -puffs_framebuf_recycle(struct puffs_framebuf *pufbuf) -{ - - assert((pufbuf->istat & ISTAT_NODESTROY) == 0); - - pufbuf->offset = 0; - pufbuf->maxoff = 0; - pufbuf->istat = 0; -} - -static int -reservespace(struct puffs_framebuf *pufbuf, size_t off, size_t wantsize) -{ - size_t incr; - void *nd; - - if (off <= pufbuf->len && pufbuf->len - off >= wantsize) - return 0; - - for (incr = PUFBUF_INCRALLOC; - pufbuf->len + incr < off + wantsize; - incr += PUFBUF_INCRALLOC) - continue; - - nd = realloc(pufbuf->buf, pufbuf->len + incr); - if (nd == NULL) - return -1; - - pufbuf->buf = nd; - pufbuf->len += incr; - - return 0; -} - -int -puffs_framebuf_dup(struct puffs_framebuf *pb, struct puffs_framebuf **pbp) -{ - struct puffs_framebuf *newpb; - - newpb = puffs_framebuf_make(); - if (newpb == NULL) { - errno = ENOMEM; - return -1; - } - memcpy(newpb, pb, sizeof(struct puffs_framebuf)); - - newpb->buf = NULL; - newpb->len = 0; - if (reservespace(newpb, 0, pb->maxoff) == -1) { - puffs_framebuf_destroy(newpb); - return -1; - } - - memcpy(newpb->buf, pb->buf, pb->maxoff); - newpb->istat = 0; - *pbp = newpb; - - return 0; -} - -int -puffs_framebuf_reserve_space(struct puffs_framebuf *pufbuf, size_t wantsize) -{ - - return reservespace(pufbuf, pufbuf->offset, wantsize); -} - -int -puffs_framebuf_putdata(struct puffs_framebuf *pufbuf, - const void *data, size_t dlen) -{ - - if (PUFBUF_REMAIN(pufbuf) < dlen) - if (puffs_framebuf_reserve_space(pufbuf, dlen) == -1) - return -1; - - memcpy(pufbuf->buf + pufbuf->offset, data, dlen); - pufbuf->offset += dlen; - - if (pufbuf->offset > pufbuf->maxoff) - pufbuf->maxoff = pufbuf->offset; - - return 0; -} - -int -puffs_framebuf_putdata_atoff(struct puffs_framebuf *pufbuf, size_t offset, - const void *data, size_t dlen) -{ - - if (reservespace(pufbuf, offset, dlen) == -1) - return -1; - - memcpy(pufbuf->buf + offset, data, dlen); - - if (offset + dlen > pufbuf->maxoff) - pufbuf->maxoff = offset + dlen; - - return 0; -} - -int -puffs_framebuf_getdata(struct puffs_framebuf *pufbuf, void *data, size_t dlen) -{ - - if (pufbuf->maxoff < pufbuf->offset + dlen) { - errno = ENOBUFS; - return -1; - } - - memcpy(data, pufbuf->buf + pufbuf->offset, dlen); - pufbuf->offset += dlen; - - return 0; -} - -int -puffs_framebuf_getdata_atoff(struct puffs_framebuf *pufbuf, size_t offset, - void *data, size_t dlen) -{ - - if (pufbuf->maxoff < offset + dlen) { - errno = ENOBUFS; - return -1; - } - - memcpy(data, pufbuf->buf + offset, dlen); - return 0; -} - -size_t -puffs_framebuf_telloff(struct puffs_framebuf *pufbuf) -{ - - return pufbuf->offset; -} - -size_t -puffs_framebuf_tellsize(struct puffs_framebuf *pufbuf) -{ - - return pufbuf->maxoff; -} - -size_t -puffs_framebuf_remaining(struct puffs_framebuf *pufbuf) -{ - - return puffs_framebuf_tellsize(pufbuf) - puffs_framebuf_telloff(pufbuf); -} - -int -puffs_framebuf_seekset(struct puffs_framebuf *pufbuf, size_t newoff) -{ - - if (reservespace(pufbuf, newoff, 0) == -1) - return -1; - - pufbuf->offset = newoff; - return 0; -} - -int -puffs_framebuf_getwindow(struct puffs_framebuf *pufbuf, size_t winoff, - void **data, size_t *dlen) -{ - size_t winlen; - -#ifdef WINTESTING - winlen = MIN(*dlen, 32); -#else - winlen = *dlen; -#endif - - if (reservespace(pufbuf, winoff, winlen) == -1) - return -1; - - *data = pufbuf->buf + winoff; - if (pufbuf->maxoff < winoff + winlen) - pufbuf->maxoff = winoff + winlen; - - return 0; -} - -void * -puffs__framebuf_getdataptr(struct puffs_framebuf *pufbuf) -{ - - return pufbuf->buf; -} - -static void -errnotify(struct puffs_usermount *pu, struct puffs_framebuf *pufbuf, int error) -{ - - pufbuf->rv = error; - if (pufbuf->pcc) { - puffs__goto(pufbuf->pcc); - } else if (pufbuf->fcb) { - pufbuf->istat &= ~ISTAT_NODESTROY; - pufbuf->fcb(pu, pufbuf, pufbuf->fcb_arg, error); - } else { - pufbuf->istat &= ~ISTAT_NODESTROY; - puffs_framebuf_destroy(pufbuf); - } -} - -#define GETFIO(fd) \ -do { \ - fio = getfiobyfd(pu, fd); \ - if (fio == NULL) { \ - errno = EINVAL; \ - return -1; \ - } \ - if (fio->stat & FIO_WRGONE) { \ - errno = ESHUTDOWN; \ - return -1; \ - } \ -} while (/*CONSTCOND*/0) - -int -puffs_framev_enqueue_cc(struct puffs_cc *pcc, int fd, - struct puffs_framebuf *pufbuf, int flags) -{ - struct puffs_usermount *pu = pcc->pcc_pu; - struct puffs_fctrl_io *fio; - - /* - * Technically we shouldn't allow this if RDGONE, but it's - * difficult to trap write close without allowing writes. - * And besides, there's probably a disconnect sequence in - * the protocol, so unexpectedly getting a closed fd is - * most likely an error condition. - */ - GETFIO(fd); - - pufbuf->pcc = pcc; - pufbuf->fcb = NULL; - pufbuf->fcb_arg = NULL; - - pufbuf->offset = 0; - pufbuf->istat |= ISTAT_NODESTROY; - - if (flags & PUFFS_FBQUEUE_URGENT) - TAILQ_INSERT_HEAD(&fio->snd_qing, pufbuf, pfb_entries); - else - TAILQ_INSERT_TAIL(&fio->snd_qing, pufbuf, pfb_entries); - - puffs_cc_yield(pcc); - if (pufbuf->rv) { - pufbuf->istat &= ~ISTAT_NODESTROY; - errno = pufbuf->rv; - return -1; - } - - return 0; -} - -int -puffs_framev_enqueue_cb(struct puffs_usermount *pu, int fd, - struct puffs_framebuf *pufbuf, puffs_framev_cb fcb, void *arg, - int flags) -{ - struct puffs_fctrl_io *fio; - - /* see enqueue_cc */ - GETFIO(fd); - - pufbuf->pcc = NULL; - pufbuf->fcb = fcb; - pufbuf->fcb_arg = arg; - - pufbuf->offset = 0; - pufbuf->istat |= ISTAT_NODESTROY; - - if (flags & PUFFS_FBQUEUE_URGENT) - TAILQ_INSERT_HEAD(&fio->snd_qing, pufbuf, pfb_entries); - else - TAILQ_INSERT_TAIL(&fio->snd_qing, pufbuf, pfb_entries); - - return 0; -} - -int -puffs_framev_enqueue_justsend(struct puffs_usermount *pu, int fd, - struct puffs_framebuf *pufbuf, int reply, int flags) -{ - struct puffs_fctrl_io *fio; - - assert((pufbuf->istat & ISTAT_INTERNAL) == 0); - - GETFIO(fd); - - pufbuf->pcc = NULL; - pufbuf->fcb = NULL; - pufbuf->fcb_arg = NULL; - - pufbuf->offset = 0; - pufbuf->istat |= ISTAT_NODESTROY; - if (!reply) - pufbuf->istat |= ISTAT_NOREPLY; - - if (flags & PUFFS_FBQUEUE_URGENT) - TAILQ_INSERT_HEAD(&fio->snd_qing, pufbuf, pfb_entries); - else - TAILQ_INSERT_TAIL(&fio->snd_qing, pufbuf, pfb_entries); - - return 0; -} - -/* ARGSUSED */ -int -puffs_framev_enqueue_directreceive(struct puffs_cc *pcc, int fd, - struct puffs_framebuf *pufbuf, int flags /* used in the future */) -{ - struct puffs_usermount *pu = pcc->pcc_pu; - struct puffs_fctrl_io *fio; - - assert((pufbuf->istat & ISTAT_INTERNAL) == 0); - - fio = getfiobyfd(pu, fd); - if (fio == NULL) { - errno = EINVAL; - return -1; - } - - /* XXX: should have cur_in queue */ - assert(fio->cur_in == NULL); - fio->cur_in = pufbuf; - - pufbuf->pcc = pcc; - pufbuf->fcb = NULL; - pufbuf->fcb_arg = NULL; - - pufbuf->offset = 0; - pufbuf->istat |= ISTAT_NODESTROY | ISTAT_DIRECT; - - puffs_cc_yield(pcc); - pufbuf->istat &= ~ISTAT_NODESTROY; /* XXX: not the right place */ - if (pufbuf->rv) { - errno = pufbuf->rv; - return -1; - } - - return 0; -} - -int -puffs_framev_enqueue_directsend(struct puffs_cc *pcc, int fd, - struct puffs_framebuf *pufbuf, int flags) -{ - struct puffs_usermount *pu = pcc->pcc_pu; - struct puffs_fctrl_io *fio; - - assert((pufbuf->istat & ISTAT_INTERNAL) == 0); - - if (flags & PUFFS_FBQUEUE_URGENT) - abort(); /* EOPNOTSUPP for now */ - - GETFIO(fd); - - pufbuf->pcc = pcc; - pufbuf->fcb = NULL; - pufbuf->fcb_arg = NULL; - - pufbuf->offset = 0; - pufbuf->istat |= ISTAT_NODESTROY | ISTAT_DIRECT; - - TAILQ_INSERT_TAIL(&fio->snd_qing, pufbuf, pfb_entries); - - puffs_cc_yield(pcc); - if (pufbuf->rv) { - pufbuf->istat &= ~ISTAT_NODESTROY; - errno = pufbuf->rv; - return -1; - } - - return 0; -} - -int -puffs_framev_framebuf_ccpromote(struct puffs_framebuf *pufbuf, - struct puffs_cc *pcc) -{ - - if ((pufbuf->istat & ISTAT_ONQUEUE) == 0) { - errno = EBUSY; - return -1; - } - - pufbuf->pcc = pcc; - pufbuf->fcb = NULL; - pufbuf->fcb_arg = NULL; - pufbuf->istat &= ~ISTAT_NOREPLY; - - puffs_cc_yield(pcc); - - return 0; -} - -int -puffs_framev_enqueue_waitevent(struct puffs_cc *pcc, int fd, int *what) -{ - struct puffs_usermount *pu = pcc->pcc_pu; - struct puffs_fctrl_io *fio; - struct puffs_fbevent feb; - struct kevent kev; - int rv, svwhat; - - svwhat = *what; - - if (*what == 0) { - errno = EINVAL; - return -1; - } - - fio = getfiobyfd(pu, fd); - if (fio == NULL) { - errno = EINVAL; - return -1; - } - - feb.pcc = pcc; - feb.what = *what & (PUFFS_FBIO_READ|PUFFS_FBIO_WRITE|PUFFS_FBIO_ERROR); - - if (*what & PUFFS_FBIO_READ) - if ((fio->stat & FIO_ENABLE_R) == 0) - EV_SET(&kev, fd, EVFILT_READ, EV_ENABLE, - 0, 0, fio); - - rv = kevent(pu->pu_kq, &kev, 1, NULL, 0, NULL); - if (rv != 0) - return errno; - - if (*what & PUFFS_FBIO_READ) - fio->rwait++; - if (*what & PUFFS_FBIO_WRITE) - fio->wwait++; - - LIST_INSERT_HEAD(&fio->ev_qing, &feb, pfe_entries); - puffs_cc_yield(pcc); - - assert(svwhat == *what); - - if (*what & PUFFS_FBIO_READ) { - fio->rwait--; - if (fio->rwait == 0 && (fio->stat & FIO_ENABLE_R) == 0) { - EV_SET(&kev, fd, EVFILT_READ, EV_DISABLE, - 0, 0, fio); - rv = kevent(pu->pu_kq, &kev, 1, NULL, 0, NULL); -#if 0 - if (rv != 0) - /* XXXXX oh dear */; -#endif - } - } - if (*what & PUFFS_FBIO_WRITE) - fio->wwait--; - - if (feb.rv == 0) { - *what = feb.what; - rv = 0; - } else { - *what = PUFFS_FBIO_ERROR; - errno = feb.rv; - rv = -1; - } - - return rv; -} - -void -puffs__framev_notify(struct puffs_fctrl_io *fio, int what) -{ - struct puffs_fbevent *fbevp; - - restart: - LIST_FOREACH(fbevp, &fio->ev_qing, pfe_entries) { - if (fbevp->what & what) { - fbevp->what = what; - fbevp->rv = 0; - LIST_REMOVE(fbevp, pfe_entries); - puffs_cc_continue(fbevp->pcc); - goto restart; - } - } -} - -static struct puffs_framebuf * -findbuf(struct puffs_usermount *pu, struct puffs_framectrl *fctrl, - struct puffs_fctrl_io *fio, struct puffs_framebuf *findme) -{ - struct puffs_framebuf *cand; - int notresp = 0; - - TAILQ_FOREACH(cand, &fio->res_qing, pfb_entries) - if (fctrl->cmpfb(pu, findme, cand, ¬resp) == 0 || notresp) - break; - - assert(!(notresp && cand == NULL)); - if (notresp || cand == NULL) - return NULL; - - TAILQ_REMOVE(&fio->res_qing, cand, pfb_entries); - return cand; -} - -void -puffs__framebuf_moveinfo(struct puffs_framebuf *from, struct puffs_framebuf *to) -{ - - assert(from->istat & ISTAT_INTERNAL); - - /* migrate buffer */ - free(to->buf); - to->buf = from->buf; - - /* migrate buffer info */ - to->len = from->len; - to->offset = from->offset; - to->maxoff = from->maxoff; - - from->buf = NULL; - from->len = 0; -} - -void -puffs__framev_input(struct puffs_usermount *pu, struct puffs_framectrl *fctrl, - struct puffs_fctrl_io *fio) -{ - struct puffs_framebuf *pufbuf, *appbuf; - int rv, complete; - - while ((fio->stat & FIO_DEAD) == 0 && (fio->stat & FIO_ENABLE_R)) { - if ((pufbuf = fio->cur_in) == NULL) { - pufbuf = puffs_framebuf_make(); - if (pufbuf == NULL) - return; - pufbuf->istat |= ISTAT_INTERNAL; - fio->cur_in = pufbuf; - } - - complete = 0; - rv = fctrl->rfb(pu, pufbuf, fio->io_fd, &complete); - - /* error */ - if (rv) { - puffs__framev_readclose(pu, fio, rv); - fio->cur_in = NULL; - return; - } - - /* partial read, come back to fight another day */ - if (complete == 0) - break; - - /* else: full read, process */ - fio->cur_in = NULL; - if ((pufbuf->istat & ISTAT_DIRECT) == 0) { - appbuf = findbuf(pu, fctrl, fio, pufbuf); - - /* - * No request for this frame? If fs implements - * gotfb, give frame to that. Otherwise drop it. - */ - if (appbuf == NULL) { - if (fctrl->gotfb) { - pufbuf->istat &= ~ISTAT_INTERNAL; - fctrl->gotfb(pu, pufbuf); - } else { - puffs_framebuf_destroy(pufbuf); - } - continue; - } - - puffs__framebuf_moveinfo(pufbuf, appbuf); - puffs_framebuf_destroy(pufbuf); - } else { - appbuf = pufbuf; - } - appbuf->istat &= ~ISTAT_NODESTROY; - - if (appbuf->pcc) { - puffs__cc_cont(appbuf->pcc); - } else if (appbuf->fcb) { - appbuf->fcb(pu, appbuf, appbuf->fcb_arg, 0); - } else { - puffs_framebuf_destroy(appbuf); - } - - /* hopeless romantics, here we go again */ - } -} - -int -puffs__framev_output(struct puffs_usermount *pu, struct puffs_framectrl *fctrl, - struct puffs_fctrl_io *fio) -{ - struct puffs_framebuf *pufbuf; - int rv, complete, done; - - if (fio->stat & FIO_DEAD) - return 0; - - for (pufbuf = TAILQ_FIRST(&fio->snd_qing), done = 0; - pufbuf && (fio->stat & FIO_DEAD) == 0 && fio->stat & FIO_ENABLE_W; - pufbuf = TAILQ_FIRST(&fio->snd_qing)) { - complete = 0; - rv = fctrl->wfb(pu, pufbuf, fio->io_fd, &complete); - - if (rv) { - puffs__framev_writeclose(pu, fio, rv); - done = 1; - break; - } - - /* partial write */ - if (complete == 0) - return done; - - /* else, complete write */ - TAILQ_REMOVE(&fio->snd_qing, pufbuf, pfb_entries); - - /* can't wait for result if we can't read */ - if (fio->stat & FIO_RDGONE) { - errnotify(pu, pufbuf, ENXIO); - done = 1; - } else if ((pufbuf->istat & ISTAT_DIRECT)) { - pufbuf->istat &= ~ISTAT_NODESTROY; - done = 1; - puffs__cc_cont(pufbuf->pcc); - } else if ((pufbuf->istat & ISTAT_NOREPLY) == 0) { - TAILQ_INSERT_TAIL(&fio->res_qing, pufbuf, - pfb_entries); - } else { - pufbuf->istat &= ~ISTAT_NODESTROY; - puffs_framebuf_destroy(pufbuf); - } - - /* omstart! */ - } - - return done; -} - -int -puffs__framev_addfd_ctrl(struct puffs_usermount *pu, int fd, int what, - struct puffs_framectrl *pfctrl) -{ - struct puffs_fctrl_io *fio; - struct kevent *newevs; - struct kevent kev[2]; - size_t nevs; - int rv, readenable; - - nevs = pu->pu_nevs+2; - newevs = realloc(pu->pu_evs, nevs*sizeof(struct kevent)); - if (newevs == NULL) - return -1; - pu->pu_evs = newevs; - - fio = malloc(sizeof(struct puffs_fctrl_io)); - if (fio == NULL) - return -1; - memset(fio, 0, sizeof(struct puffs_fctrl_io)); - fio->io_fd = fd; - fio->cur_in = NULL; - fio->fctrl = pfctrl; - TAILQ_INIT(&fio->snd_qing); - TAILQ_INIT(&fio->res_qing); - LIST_INIT(&fio->ev_qing); - - readenable = 0; - if ((what & PUFFS_FBIO_READ) == 0) - readenable = EV_DISABLE; - - if (pu->pu_state & PU_INLOOP) { - EV_SET(&kev[0], fd, EVFILT_READ, - EV_ADD|readenable, 0, 0, fio); - EV_SET(&kev[1], fd, EVFILT_WRITE, - EV_ADD|EV_DISABLE, 0, 0, fio); - rv = kevent(pu->pu_kq, kev, 2, NULL, 0, NULL); - if (rv == -1) { - free(fio); - return -1; - } - } - if (what & PUFFS_FBIO_READ) - fio->stat |= FIO_ENABLE_R; - if (what & PUFFS_FBIO_WRITE) - fio->stat |= FIO_ENABLE_W; - - LIST_INSERT_HEAD(&pu->pu_ios, fio, fio_entries); - pu->pu_nevs = nevs; - - return 0; -} - -int -puffs_framev_addfd(struct puffs_usermount *pu, int fd, int what) -{ - - return puffs__framev_addfd_ctrl(pu, fd, what, - &pu->pu_framectrl[PU_FRAMECTRL_USER]); -} - -/* - * XXX: the following en/disable should be coalesced and executed - * only during the actual kevent call. So feel free to fix if - * threatened by mindblowing boredom. - */ - -int -puffs_framev_enablefd(struct puffs_usermount *pu, int fd, int what) -{ - struct kevent kev; - struct puffs_fctrl_io *fio; - int rv = 0; - - assert((what & (PUFFS_FBIO_READ | PUFFS_FBIO_WRITE)) != 0); - - fio = getfiobyfd(pu, fd); - if (fio == NULL) { - errno = ENXIO; - return -1; - } - - /* write is enabled in the event loop if there is output */ - if (what & PUFFS_FBIO_READ && fio->rwait == 0) { - EV_SET(&kev, fd, EVFILT_READ, EV_ENABLE, 0, 0, fio); - rv = kevent(pu->pu_kq, &kev, 1, NULL, 0, NULL); - } - - if (rv == 0) { - if (what & PUFFS_FBIO_READ) - fio->stat |= FIO_ENABLE_R; - if (what & PUFFS_FBIO_WRITE) - fio->stat |= FIO_ENABLE_W; - } - - return rv; -} - -int -puffs_framev_disablefd(struct puffs_usermount *pu, int fd, int what) -{ - struct kevent kev[2]; - struct puffs_fctrl_io *fio; - size_t i; - int rv; - - assert((what & (PUFFS_FBIO_READ | PUFFS_FBIO_WRITE)) != 0); - - fio = getfiobyfd(pu, fd); - if (fio == NULL) { - errno = ENXIO; - return -1; - } - - i = 0; - if (what & PUFFS_FBIO_READ && fio->rwait == 0) { - EV_SET(&kev[0], fd, - EVFILT_READ, EV_DISABLE, 0, 0, fio); - i++; - } - if (what & PUFFS_FBIO_WRITE && fio->stat & FIO_WR && fio->wwait == 0) { - EV_SET(&kev[1], fd, - EVFILT_WRITE, EV_DISABLE, 0, 0, fio); - i++; - } - if (i) - rv = kevent(pu->pu_kq, kev, i, NULL, 0, NULL); - else - rv = 0; - - if (rv == 0) { - if (what & PUFFS_FBIO_READ) - fio->stat &= ~FIO_ENABLE_R; - if (what & PUFFS_FBIO_WRITE) - fio->stat &= ~FIO_ENABLE_W; - } - - return rv; -} - -void -puffs__framev_readclose(struct puffs_usermount *pu, - struct puffs_fctrl_io *fio, int error) -{ - struct puffs_framebuf *pufbuf; - struct kevent kev; - int notflag; - - if (fio->stat & FIO_RDGONE || fio->stat & FIO_DEAD) - return; - fio->stat |= FIO_RDGONE; - - if (fio->cur_in) { - if ((fio->cur_in->istat & ISTAT_DIRECT) == 0) { - puffs_framebuf_destroy(fio->cur_in); - fio->cur_in = NULL; - } else { - errnotify(pu, fio->cur_in, error); - } - } - - while ((pufbuf = TAILQ_FIRST(&fio->res_qing)) != NULL) { - TAILQ_REMOVE(&fio->res_qing, pufbuf, pfb_entries); - errnotify(pu, pufbuf, error); - } - - EV_SET(&kev, fio->io_fd, EVFILT_READ, EV_DELETE, 0, 0, 0); - (void) kevent(pu->pu_kq, &kev, 1, NULL, 0, NULL); - - notflag = PUFFS_FBIO_READ; - if (fio->stat & FIO_WRGONE) - notflag |= PUFFS_FBIO_WRITE; - - if (fio->fctrl->fdnotfn) - fio->fctrl->fdnotfn(pu, fio->io_fd, notflag); -} - -void -puffs__framev_writeclose(struct puffs_usermount *pu, - struct puffs_fctrl_io *fio, int error) -{ - struct puffs_framebuf *pufbuf; - struct kevent kev; - int notflag; - - if (fio->stat & FIO_WRGONE || fio->stat & FIO_DEAD) - return; - fio->stat |= FIO_WRGONE; - - while ((pufbuf = TAILQ_FIRST(&fio->snd_qing)) != NULL) { - TAILQ_REMOVE(&fio->snd_qing, pufbuf, pfb_entries); - errnotify(pu, pufbuf, error); - } - - EV_SET(&kev, fio->io_fd, EVFILT_WRITE, EV_DELETE, 0, 0, 0); - (void) kevent(pu->pu_kq, &kev, 1, NULL, 0, NULL); - - notflag = PUFFS_FBIO_WRITE; - if (fio->stat & FIO_RDGONE) - notflag |= PUFFS_FBIO_READ; - - if (fio->fctrl->fdnotfn) - fio->fctrl->fdnotfn(pu, fio->io_fd, notflag); -} - -static int -removefio(struct puffs_usermount *pu, struct puffs_fctrl_io *fio, int error) -{ - struct puffs_fbevent *fbevp; - - LIST_REMOVE(fio, fio_entries); - if (pu->pu_state & PU_INLOOP) { - puffs__framev_readclose(pu, fio, error); - puffs__framev_writeclose(pu, fio, error); - } - - while ((fbevp = LIST_FIRST(&fio->ev_qing)) != NULL) { - fbevp->rv = error; - LIST_REMOVE(fbevp, pfe_entries); - puffs__goto(fbevp->pcc); - } - - /* don't bother with realloc */ - pu->pu_nevs -= 2; - - /* don't free us yet, might have some references in event arrays */ - fio->stat |= FIO_DEAD; - LIST_INSERT_HEAD(&pu->pu_ios_rmlist, fio, fio_entries); - - return 0; - -} - -int -puffs_framev_removefd(struct puffs_usermount *pu, int fd, int error) -{ - struct puffs_fctrl_io *fio; - - fio = getfiobyfd(pu, fd); - if (fio == NULL) { - errno = ENXIO; - return -1; - } - - return removefio(pu, fio, error ? error : ECONNRESET); -} - -void -puffs_framev_removeonclose(struct puffs_usermount *pu, int fd, int what) -{ - - if (what == (PUFFS_FBIO_READ | PUFFS_FBIO_WRITE)) - (void) puffs_framev_removefd(pu, fd, ECONNRESET); -} - -void -puffs_framev_unmountonclose(struct puffs_usermount *pu, int fd, int what) -{ - - /* XXX & X: unmount is non-sensible */ - puffs_framev_removeonclose(pu, fd, what); - if (what == (PUFFS_FBIO_READ | PUFFS_FBIO_WRITE)) - PU_SETSTATE(pu, PUFFS_STATE_UNMOUNTED); -} - -void -puffs_framev_init(struct puffs_usermount *pu, - puffs_framev_readframe_fn rfb, puffs_framev_writeframe_fn wfb, - puffs_framev_cmpframe_fn cmpfb, puffs_framev_gotframe_fn gotfb, - puffs_framev_fdnotify_fn fdnotfn) -{ - struct puffs_framectrl *pfctrl; - - pfctrl = &pu->pu_framectrl[PU_FRAMECTRL_USER]; - pfctrl->rfb = rfb; - pfctrl->wfb = wfb; - pfctrl->cmpfb = cmpfb; - pfctrl->gotfb = gotfb; - pfctrl->fdnotfn = fdnotfn; -} - -void -puffs__framev_exit(struct puffs_usermount *pu) -{ - struct puffs_fctrl_io *fio; - - while ((fio = LIST_FIRST(&pu->pu_ios)) != NULL) - removefio(pu, fio, ENXIO); - free(pu->pu_evs); - - /* closing pu->pu_kq takes care of puffsfd */ -} diff --git a/lib/libpuffs/hash.h b/lib/libpuffs/hash.h deleted file mode 100644 index 45041abb02..0000000000 --- a/lib/libpuffs/hash.h +++ /dev/null @@ -1,103 +0,0 @@ -/* $NetBSD: hash.h,v 1.6 2008/04/28 20:24:10 martin Exp $ */ - -/*- - * Copyright (c) 2001 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Luke Mewburn. - * - * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _SYS_HASH_H_ -#define _SYS_HASH_H_ - -#include -#ifdef __HAVE_MACHINE_HASH_H -#include -#endif - - -#ifndef __HAVE_HASH32_BUF /* not overridden by MD hash */ - -#define HASH32_BUF_INIT 5381 - -/* - * uint32_t - * hash32_buf(const void *bf, size_t len, uint32_t hash) - * return a 32 bit hash of the binary buffer buf (size len), - * seeded with an initial hash value of hash (usually HASH32_BUF_INIT). - */ -static __inline uint32_t -hash32_buf(const void *bf, size_t len, uint32_t hash) -{ - const uint8_t *s = bf; - - while (len-- != 0) /* "nemesi": k=257, r=r*257 */ - hash = hash * 257 + *s++; - return (hash * 257); -} -#endif /* __HAVE_HASH32_BUF */ - - -#ifndef __HAVE_HASH32_STR /* not overridden by MD hash */ - -#define HASH32_STR_INIT 5381 -/* - * uint32_t - * hash32_str(const void *bf, uint32_t hash) - * return a 32 bit hash of NUL terminated ASCII string buf, - * seeded with an initial hash value of hash (usually HASH32_STR_INIT). - */ -static __inline uint32_t -hash32_str(const void *bf, uint32_t hash) -{ - const uint8_t *s = bf; - uint8_t c; - - while ((c = *s++) != 0) - hash = hash * 33 + c; /* "perl": k=33, r=r+r/32 */ - return (hash + (hash >> 5)); -} - -/* - * uint32_t - * hash32_strn(const void *bf, size_t len, uint32_t hash) - * return a 32 bit hash of NUL terminated ASCII string buf up to - * a maximum of len bytes, - * seeded with an initial hash value of hash (usually HASH32_STR_INIT). - */ -static __inline uint32_t -hash32_strn(const void *bf, size_t len, uint32_t hash) -{ - const uint8_t *s = bf; - uint8_t c; - - while ((c = *s++) != 0 && len-- != 0) - hash = hash * 33 + c; /* "perl": k=33, r=r+r/32 */ - return (hash + (hash >> 5)); -} -#endif /* __HAVE_HASH32_STR */ - - -#endif /* !_SYS_HASH_H_ */ diff --git a/lib/libpuffs/null.c b/lib/libpuffs/null.c deleted file mode 100644 index a36a24ab33..0000000000 --- a/lib/libpuffs/null.c +++ /dev/null @@ -1,654 +0,0 @@ -/* $NetBSD: null.c,v 1.30 2011/06/27 12:06:19 manu 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. - */ - -/* - * A "nullfs" using puffs, i.e. maps one location in the hierarchy - * to another using standard system calls. - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "puffs.h" - -PUFFSOP_PROTOS(puffs_null) - -/* - * set attributes to what is specified. XXX: no rollback in case of failure - */ -static int -processvattr(const char *path, const struct vattr *va, int regular) -{ - struct timeval tv[2]; - - /* XXX: -1 == PUFFS_VNOVAL, but shouldn't trust that */ - if (va->va_uid != (unsigned)-1 || va->va_gid != (unsigned)-1) - if (lchown(path, va->va_uid, va->va_gid) == -1) - return errno; - - if (va->va_mode != (unsigned)PUFFS_VNOVAL) - if (lchmod(path, va->va_mode) == -1) - return errno; - - /* sloppy */ - 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); - - if (lutimes(path, tv) == -1) - return errno; - } - - if (regular && va->va_size != (u_quad_t)PUFFS_VNOVAL) - if (truncate(path, (off_t)va->va_size) == -1) - return errno; - - return 0; -} - -/* - * Kludge to open files which aren't writable *any longer*. This kinda - * works because the vfs layer does validation checks based on the file's - * permissions to allow writable opening before opening them. However, - * the problem arises if we want to create a file, write to it (cache), - * adjust permissions and then flush the file. - */ -static int -writeableopen(const char *path) -{ - struct stat sb; - mode_t origmode; - int sverr = 0; - int fd; - - fd = open(path, O_WRONLY); - if (fd == -1) { - if (errno == EACCES) { - if (stat(path, &sb) == -1) - return -1; - origmode = sb.st_mode & ALLPERMS; - - if (chmod(path, 0200) == -1) - return -1; - - fd = open(path, O_WRONLY); - if (fd == -1) - sverr = errno; - - chmod(path, origmode); - if (sverr) - errno = sverr; - } else - return -1; - } - - return fd; -} - -/*ARGSUSED*/ -static void * -inodecmp(struct puffs_usermount *pu, struct puffs_node *pn, void *arg) -{ - ino_t *cmpino = arg; - - if (pn->pn_va.va_fileid == *cmpino) - return pn; - return NULL; -} - -static int -makenode(struct puffs_usermount *pu, struct puffs_newinfo *pni, - const struct puffs_cn *pcn, const struct vattr *va, int regular) -{ - struct puffs_node *pn; - struct stat sb; - int rv; - - if ((rv = processvattr(PCNPATH(pcn), va, regular)) != 0) - return rv; - - pn = puffs_pn_new(pu, NULL); - if (!pn) - return ENOMEM; - puffs_setvattr(&pn->pn_va, va); - - if (lstat(PCNPATH(pcn), &sb) == -1) - return errno; - puffs_stat2vattr(&pn->pn_va, &sb); - - puffs_newinfo_setcookie(pni, pn); - return 0; -} - -/* This should be called first and overridden from the file system */ -void -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); - PUFFSOP_SET(pops, puffs_null, node, mknod); - PUFFSOP_SET(pops, puffs_null, node, getattr); - PUFFSOP_SET(pops, puffs_null, node, setattr); - PUFFSOP_SET(pops, puffs_null, node, fsync); - PUFFSOP_SET(pops, puffs_null, node, remove); - PUFFSOP_SET(pops, puffs_null, node, link); - PUFFSOP_SET(pops, puffs_null, node, rename); - PUFFSOP_SET(pops, puffs_null, node, mkdir); - PUFFSOP_SET(pops, puffs_null, node, rmdir); - PUFFSOP_SET(pops, puffs_null, node, symlink); - PUFFSOP_SET(pops, puffs_null, node, readlink); - PUFFSOP_SET(pops, puffs_null, node, readdir); - PUFFSOP_SET(pops, puffs_null, node, read); - PUFFSOP_SET(pops, puffs_null, node, write); - PUFFSOP_SET(pops, puffs_genfs, node, reclaim); -} - -/*ARGSUSED*/ -int -puffs_null_fs_statvfs(struct puffs_usermount *pu, struct statvfs *svfsb) -{ - - if (statvfs(PNPATH(puffs_getroot(pu)), svfsb) == -1) - return errno; - - return 0; -} - -/*ARGSUSED*/ -static void * -fhcmp(struct puffs_usermount *pu, struct puffs_node *pn, void *arg) -{ - struct fid *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; - - if (fidsize != sizeof(struct fid)) - return EINVAL; - - 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); - 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; - fhandle_t fh; - int rv; - - if (*fidsize != sizeof(struct fid)) - return EINVAL; - - rv = 0; - if (getfh(PNPATH(pn), &fh) == -1) - rv = errno; - if (rv == 0) { - *(struct fid *)fid = fh.fh_fid; - pn->pn_data = malloc(*fidsize); - if (pn->pn_data == NULL) - abort(); /* lazy */ - memcpy(pn->pn_data, fid, *fidsize); - } - - return rv; -} - -int -puffs_null_node_lookup(struct puffs_usermount *pu, puffs_cookie_t opc, - struct puffs_newinfo *pni, const struct puffs_cn *pcn) -{ - struct puffs_node *pn = opc, *pn_res; - struct stat sb; - int rv; - - assert(pn->pn_va.va_type == VDIR); - - /* - * Note to whoever is copypasting this: you must first check - * if the node is there and only then do nodewalk. Alternatively - * you could make sure that you don't return unlinked/rmdir'd - * nodes in some other fashion - */ - rv = lstat(PCNPATH(pcn), &sb); - if (rv) - return errno; - - /* XXX2: nodewalk is a bit too slow here */ - pn_res = puffs_pn_nodewalk(pu, inodecmp, &sb.st_ino); - - if (pn_res == NULL) { - pn_res = puffs_pn_new(pu, NULL); - if (pn_res == NULL) - return ENOMEM; - puffs_stat2vattr(&pn_res->pn_va, &sb); - } - - 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); - - return 0; -} - -int -puffs_null_node_lookupdotdot(struct puffs_usermount *pu, puffs_cookie_t opc, - struct puffs_newinfo *pni, const struct puffs_cn *pcn) -{ - return puffs_null_node_lookup(pu, opc, pni, pcn); -} - -/*ARGSUSED*/ -int -puffs_null_node_create(struct puffs_usermount *pu, puffs_cookie_t opc, - struct puffs_newinfo *pni, const struct puffs_cn *pcn, - const struct vattr *va) -{ - int fd, rv; - - fd = open(PCNPATH(pcn), O_RDWR | O_CREAT | O_TRUNC); - if (fd == -1) - return errno; - close(fd); - - rv = makenode(pu, pni, pcn, va, 1); - if (rv) - unlink(PCNPATH(pcn)); - return rv; -} - -/*ARGSUSED*/ -int -puffs_null_node_mknod(struct puffs_usermount *pu, puffs_cookie_t opc, - struct puffs_newinfo *pni, const struct puffs_cn *pcn, - const struct vattr *va) -{ - mode_t mode; - int rv; - - mode = puffs_addvtype2mode(va->va_mode, va->va_type); - switch (va->va_type) { - case VFIFO: - if (mkfifo(PCNPATH(pcn), mode) == -1) - return errno; - break; - case VCHR: - case VBLK: - return ENOTSUP; - default: - return EINVAL; - } - - rv = makenode(pu, pni, pcn, va, 0); - if (rv) - unlink(PCNPATH(pcn)); - return rv; -} - -/*ARGSUSED*/ -int -puffs_null_node_getattr(struct puffs_usermount *pu, puffs_cookie_t opc, - struct vattr *va, const struct puffs_cred *pcred) -{ - struct puffs_node *pn = opc; - struct stat sb; - - if (lstat(PNPATH(pn), &sb) == -1) - return errno; - puffs_stat2vattr(va, &sb); - - return 0; -} - -/*ARGSUSED*/ -int -puffs_null_node_setattr(struct puffs_usermount *pu, puffs_cookie_t opc, - const struct vattr *va, const struct puffs_cred *pcred) -{ - struct puffs_node *pn = opc; - int rv; - - rv = processvattr(PNPATH(pn), va, pn->pn_va.va_type == VREG); - if (rv) - return rv; - - puffs_setvattr(&pn->pn_va, va); - - return 0; -} - -/*ARGSUSED*/ -int -puffs_null_node_fsync(struct puffs_usermount *pu, puffs_cookie_t opc, - int how) -{ - struct puffs_node *pn = opc; - int fd, rv; - struct stat sb; - - rv = 0; - if (stat(PNPATH(pn), &sb) == -1) - return errno; - if (S_ISDIR(sb.st_mode)) { - DIR *dirp; - if ((dirp = opendir(PNPATH(pn))) == NULL) - return errno; - fd = dirfd(dirp); - if (fd == -1) - return errno; - } else { - fd = writeableopen(PNPATH(pn)); - if (fd == -1) - return errno; - } - - if (fsync(fd) == -1) - rv = errno; - - close(fd); - - return rv; -} - -/*ARGSUSED*/ -int -puffs_null_node_remove(struct puffs_usermount *pu, puffs_cookie_t opc, - puffs_cookie_t targ, const struct puffs_cn *pcn) -{ - struct puffs_node *pn_targ = targ; - - if (unlink(PNPATH(pn_targ)) == -1) - return errno; - puffs_pn_remove(pn_targ); - - return 0; -} - -/*ARGSUSED*/ -int -puffs_null_node_link(struct puffs_usermount *pu, puffs_cookie_t opc, - puffs_cookie_t targ, const struct puffs_cn *pcn) -{ - struct puffs_node *pn_targ = targ; - - if (link(PNPATH(pn_targ), PCNPATH(pcn)) == -1) - return errno; - - return 0; -} - -/*ARGSUSED*/ -int -puffs_null_node_rename(struct puffs_usermount *pu, puffs_cookie_t opc, - puffs_cookie_t src, const struct puffs_cn *pcn_src, - puffs_cookie_t targ_dir, puffs_cookie_t targ, - const struct puffs_cn *pcn_targ) -{ - - if (rename(PCNPATH(pcn_src), PCNPATH(pcn_targ)) == -1) - return errno; - - return 0; -} - -/*ARGSUSED*/ -int -puffs_null_node_mkdir(struct puffs_usermount *pu, puffs_cookie_t opc, - struct puffs_newinfo *pni, const struct puffs_cn *pcn, - const struct vattr *va) -{ - int rv; - - if (mkdir(PCNPATH(pcn), va->va_mode) == -1) - return errno; - - rv = makenode(pu, pni, pcn, va, 0); - if (rv) - rmdir(PCNPATH(pcn)); - return rv; -} - -/*ARGSUSED*/ -int -puffs_null_node_rmdir(struct puffs_usermount *pu, puffs_cookie_t opc, - puffs_cookie_t targ, const struct puffs_cn *pcn) -{ - struct puffs_node *pn_targ = targ; - - if (rmdir(PNPATH(pn_targ)) == -1) - return errno; - puffs_pn_remove(pn_targ); - - return 0; -} - -/*ARGSUSED*/ -int -puffs_null_node_symlink(struct puffs_usermount *pu, puffs_cookie_t opc, - struct puffs_newinfo *pni, const struct puffs_cn *pcn, - const struct vattr *va, const char *linkname) -{ - int rv; - - if (symlink(linkname, PCNPATH(pcn)) == -1) - return errno; - - rv = makenode(pu, pni, pcn, va, 0); - if (rv) - unlink(PCNPATH(pcn)); - return rv; -} - -/*ARGSUSED*/ -int -puffs_null_node_readlink(struct puffs_usermount *pu, puffs_cookie_t opc, - const struct puffs_cred *pcred, char *linkname, size_t *linklen) -{ - struct puffs_node *pn = opc; - ssize_t rv; - - rv = readlink(PNPATH(pn), linkname, *linklen); - if (rv == -1) - return errno; - - *linklen = rv; - return 0; -} - -/*ARGSUSED*/ -int -puffs_null_node_readdir(struct puffs_usermount *pu, puffs_cookie_t opc, - struct dirent *de, off_t *off, size_t *reslen, - const struct puffs_cred *pcred, int *eofflag, off_t *cookies, - size_t *ncookies) -{ - struct puffs_node *pn = opc; - struct dirent entry, *result; - DIR *dp; - off_t i; - int rv; - - *ncookies = 0; - dp = opendir(PNPATH(pn)); - if (dp == NULL) - return errno; - - rv = 0; - i = *off; - - /* - * XXX: need to do trickery here, telldir/seekdir would be nice, but - * then we'd need to keep state, which I'm too lazy to keep - */ - while (i--) { - rv = readdir_r(dp, &entry, &result); - if (rv != 0) - goto out; - - if (!result) { - *eofflag = 1; - goto out; - } - } - - for (;;) { - rv = readdir_r(dp, &entry, &result); - if (rv != 0) - goto out; - - if (!result) { - *eofflag = 1; - goto out; - } - - if (_DIRENT_DIRSIZ(result) > *reslen) - goto out; - - *de = *result; - *reslen -= _DIRENT_DIRSIZ(result); - de = _DIRENT_NEXT(de); - - (*off)++; - PUFFS_STORE_DCOOKIE(cookies, ncookies, *off); - } - - out: - closedir(dp); - return 0; -} - -/*ARGSUSED*/ -int -puffs_null_node_read(struct puffs_usermount *pu, puffs_cookie_t opc, - uint8_t *buf, off_t offset, size_t *buflen, - const struct puffs_cred *pcred, int ioflag) -{ - struct puffs_node *pn = opc; - ssize_t n; - off_t off; - int fd, rv; - - rv = 0; - fd = open(PNPATH(pn), O_RDONLY); - if (fd == -1) - return errno; - off = lseek(fd, offset, SEEK_SET); - if (off == -1) { - rv = errno; - goto out; - } - - n = read(fd, buf, *buflen); - if (n == -1) - rv = errno; - else - *buflen -= n; - - out: - close(fd); - return rv; -} - -/*ARGSUSED*/ -int -puffs_null_node_write(struct puffs_usermount *pu, puffs_cookie_t opc, - uint8_t *buf, off_t offset, size_t *buflen, - const struct puffs_cred *pcred, int ioflag) -{ - struct puffs_node *pn = opc; - ssize_t n; - off_t off; - int fd, rv; - - rv = 0; - fd = writeableopen(PNPATH(pn)); - if (fd == -1) - return errno; - - off = lseek(fd, offset, SEEK_SET); - if (off == -1) { - rv = errno; - goto out; - } - - n = write(fd, buf, *buflen); - if (n == -1) - rv = errno; - else - *buflen -= n; - - out: - close(fd); - return rv; -} diff --git a/lib/libpuffs/opdump.c b/lib/libpuffs/opdump.c deleted file mode 100644 index b21e29ae58..0000000000 --- a/lib/libpuffs/opdump.c +++ /dev/null @@ -1,515 +0,0 @@ -/* $NetBSD: opdump.c,v 1.35 2010/08/20 16:35:05 pooka 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 -#include -#include - -#include -#include -#include -#include - -#include "puffs.h" -#include "puffsdump.h" -#include "puffs_priv.h" - -#ifndef __arraycount -#define __arraycount(__x) (sizeof(__x) / sizeof(__x[0])) -#endif - -#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 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) -{ - 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: %d, ", 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), "%ju", (uintmax_t)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_gen != (u_long)PUFFS_VNOVAL) - snprintf(buf, sizeof(buf), "%ju", (uintmax_t)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_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); -} - -void -puffsdump_cn(struct puffs_kcn *pkcn) -{ - - mydprintf(DINT "puffs_cn: \"%s\", len %zu\n", - pkcn->pkcn_name, pkcn->pkcn_namelen); -} - -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); -} diff --git a/lib/libpuffs/paths.c b/lib/libpuffs/paths.c deleted file mode 100644 index 18fc67ac3d..0000000000 --- a/lib/libpuffs/paths.c +++ /dev/null @@ -1,293 +0,0 @@ -/* $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 -#include -#include - -#include "puffs.h" -#include "puffs_priv.h" -#include "hash.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); -} diff --git a/lib/libpuffs/pnode.c b/lib/libpuffs/pnode.c deleted file mode 100644 index 5cc4f84653..0000000000 --- a/lib/libpuffs/pnode.c +++ /dev/null @@ -1,167 +0,0 @@ -/* $NetBSD: pnode.c,v 1.10 2008/08/12 19:44:39 pooka Exp $ */ - -/* - * Copyright (c) 2006 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 - -#include -#include -#include -#include - -#include "puffs.h" -#include "puffs_priv.h" - -/* - * Well, you're probably wondering why this isn't optimized. - * The reason is simple: my available time is not optimized for - * size ... so please be patient ;) - */ -struct puffs_node * -puffs_pn_new(struct puffs_usermount *pu, void *privdata) -{ - struct puffs_node *pn; - - pn = calloc(1, sizeof(struct puffs_node)); - if (pn == NULL) - return NULL; - - pn->pn_data = privdata; - pn->pn_mnt = pu; - puffs_vattr_null(&pn->pn_va); - - LIST_INSERT_HEAD(&pu->pu_pnodelst, pn, pn_entries); - - return pn; -} - -void -puffs_pn_remove(struct puffs_node *pn) -{ - - LIST_REMOVE(pn, pn_entries); - pn->pn_flags |= PUFFS_NODE_REMOVED; -} - -void -puffs_pn_put(struct puffs_node *pn) -{ - struct puffs_usermount *pu = pn->pn_mnt; - - pu->pu_pathfree(pu, &pn->pn_po); - if ((pn->pn_flags & PUFFS_NODE_REMOVED) == 0) - LIST_REMOVE(pn, pn_entries); - free(pn); -} - -/* walk list, rv can be used either to halt or to return a value */ -void * -puffs_pn_nodewalk(struct puffs_usermount *pu, puffs_nodewalk_fn fn, void *arg) -{ - struct puffs_node *pn_cur, *pn_next; - void *rv; - - pn_cur = LIST_FIRST(&pu->pu_pnodelst); - while (pn_cur) { - pn_next = LIST_NEXT(pn_cur, pn_entries); - rv = fn(pu, pn_cur, arg); - if (rv) - return rv; - pn_cur = pn_next; - } - - return NULL; -} - -struct vattr * -puffs_pn_getvap(struct puffs_node *pn) -{ - - return &pn->pn_va; -} - -void * -puffs_pn_getpriv(struct puffs_node *pn) -{ - - return pn->pn_data; -} - -void -puffs_pn_setpriv(struct puffs_node *pn, void *priv) -{ - - pn->pn_data = priv; -} - -struct puffs_pathobj * -puffs_pn_getpo(struct puffs_node *pn) -{ - - return &pn->pn_po; -} - -struct puffs_usermount * -puffs_pn_getmnt(struct puffs_node *pn) -{ - - return pn->pn_mnt; -} - -/* convenience / shortcut */ -void * -puffs_pn_getmntspecific(struct puffs_node *pn) -{ - - return pn->pn_mnt->pu_privdata; -} - -/* - * newnode parameters - */ -void -puffs_newinfo_setcookie(struct puffs_newinfo *pni, puffs_cookie_t cookie) -{ - - assert(pni->pni_cookie != NULL); - *pni->pni_cookie = cookie; -} - -void -puffs_newinfo_setvtype(struct puffs_newinfo *pni, enum vtype vt) -{ - - if (pni->pni_vtype != NULL) - *pni->pni_vtype = vt; -} - -void -puffs_newinfo_setsize(struct puffs_newinfo *pni, voff_t size) -{ - - if (pni->pni_size != NULL) - *pni->pni_size = size; -} diff --git a/lib/libpuffs/puffs.3 b/lib/libpuffs/puffs.3 deleted file mode 100644 index 985cf23139..0000000000 --- a/lib/libpuffs/puffs.3 +++ /dev/null @@ -1,563 +0,0 @@ -.\" $NetBSD: puffs.3,v 1.47 2010/01/12 18:42:38 pooka Exp $ -.\" -.\" Copyright (c) 2006, 2007, 2008 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 February 5, 2012 -.Dt PUFFS 3 -.Os -.Sh NAME -.Nm puffs -.Nd Pass-to-Userspace Framework File System development interface -.Sh LIBRARY -.Lb libpuffs -.Sh SYNOPSIS -.In puffs.h -.Ft struct puffs_usermount * -.Fo puffs_init -.Fa "struct puffs_ops *pops" "const char *mntfromname" "const char *puffsname" -.Fa "void *private" "uint32_t flags" -.Fc -.Ft int -.Fo puffs_mount -.Fa "struct puffs_usermount *pu" "const char *dir" "int mntflags" -.Fa "puffs_cookie_t root_cookie" -.Fc -.Ft int -.Fn puffs_getselectable "struct puffs_usermount *pu" -.Ft int -.Fn puffs_setblockingmode "struct puffs_usermount *pu" "int mode" -.Ft int -.Fn puffs_getstate "struct puffs_usermount *pu" -.Ft int -.Fn puffs_setstacksize "struct puffs_usermount *pu" "size_t stacksize" -.Ft void -.Fn puffs_setroot "struct puffs_usermount *pu" "struct puffs_node *node" -.Ft void -.Fo puffs_setrootinfo -.Fa "struct puffs_usermount *pu" "enum vtype vt" "vsize_t vsize" "dev_t rdev" -.Fc -.Ft struct puffs_node * -.Fn puffs_getroot "struct puffs_usermount *pu" -.Ft void * -.Fn puffs_getspecific "struct puffs_usermount *pu" -.Ft void -.Fn puffs_setspecific "struct puffs_usermount *pu" "void *private" -.Ft void -.Fn puffs_setmaxreqlen "struct puffs_usermount *pu" "size_t maxreqlen" -.Ft size_t -.Fn puffs_getmaxreqlen "struct puffs_usermount *pu" -.Ft void -.Fn puffs_setfhsize "struct puffs_usermount *pu" "size_t fhsize" "int flags" -.Ft void -.Fn puffs_setncookiehash "struct puffs_usermount *pu" "int nhashes" -.Ft void -.Fn puffs_ml_loop_fn "struct puffs_usermount *pu" -.Ft void -.Fn puffs_ml_setloopfn "struct puffs_usermount *pu" "puffs_ml_loop_fn lfn" -.Ft void -.Fn puffs_ml_settimeout "struct puffs_usermount *pu" "struct timespec *ts" -.Ft int -.Fn puffs_daemon "struct puffs_usermount *pu" "int nochdir" "int noclose" -.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 "struct puffs_cc *pcc" "struct puffs_framebuf **pbp" -.Sh DESCRIPTION -.Nm -provides a framework for creating file systems as userspace servers. -Operations are transported from the kernel virtual file system layer -to the concrete implementation behind -.Nm , -where they are processed and results are sent back to the kernel. -.Pp -It is possible to use -.Nm -in two different ways. -Calling -.Fn puffs_mainloop -takes execution context away from the caller and automatically handles -all requests by using the callbacks. -By using -.Xr puffs_framebuf 3 -in conjunction with -.Fn puffs_mainloop , -it is possible to handle I/O to and from file descriptors. -This is suited e.g. for distributed file servers. -.Ss Library operation -Operations on the library always require a pointer to the opaque context -identifier, -.Va struct puffs_usermount . -It is obtained by calling -.Fn puffs_init . -.Pp -.Nm -operates using operation callbacks. -They can be initialized using the macro -.Fn PUFFSOP_SET pops fsname type opname , -which will initialize the operation -.Fn puffs_type_opname -in -.Fa pops -to -.Fn fsname_type_opname . -All operations are initialized to a default state with the call -.Fn PUFFSOP_INIT pops . -All of the VFS routines are mandatory, but all of the node operations -with the exception of -.Fn puffs_node_lookup -are optional. -However, leaving operations blank will naturally have an effect on the -features available from the file system implementation. -.Bl -tag -width xxxx -.It Fn puffs_init pops mntfromname puffsname private flags -Initializes the library context. -.Ar pops -specifies the callback operations vector. -.Ar mntfromname -is device the file system is mounted from. -This can be for example a block device such as -.Pa /dev/wd0a -or, if the file system is pseudo file system, the -.Nm -device name can be given by -.Dv _PATH_PUFFS . -This value is used for example in the first column of the output of -.Xr mount 8 -and -.Xr df 1 . -.Ar puffsname -is the file system type. -It will always be prepended with the string "puffs|". -If possible, file server binaries should be named using the format -"mount_myfsnamehere" and this value should equal "myfsnamehere". -A file system specific context pointer can optionally be given in -.Ar private . -This can be retrieved by -.Fn puffs_getspecific . -Flags for -.Nm -can be given via -.Fa pflags . -Currently the following flags are supported: -.Bl -tag -width "XPUFFS_KFLAG_LOOKUP_FULLPNBUF" -.It Dv PUFFS_KFLAG_NOCACHE_NAME -Do not enter pathname components into the name cache. -This means that every time the kernel does a lookup for a -componentname, the file server will be consulted. -.It Dv PUFFS_KFLAG_NOCACHE_PAGE -Do not use the page cache. -This means that all reads and writes to regular file are -propagated to the file server for handling. -This option makes a difference only for regular files. -.It Dv PUFFS_KFLAG_NOCACHE -An alias for both -.Dv PUFFS_KFLAG_NOCACHE_NAME -and -.Dv PUFFS_KFLAG_NOCACHE_PAGE . -.It Dv PUFFS_KFLAG_ALLOPS -This flag requests that all operations are sent to userspace. -Normally the kernel shortcircuits unimplemented operations. -This flag is mostly useful for debugging purposes. -.It Dv PUFFS_KFLAG_WTCACHE -Set the file system cache behavior as write-through. -This means that all writes are immediately issued to the file server -instead of being flushed in file system sync. -This is useful especially for distributed file systems. -.It Dv PUFFS_KFLAG_IAONDEMAND -Issue inactive only on demand. -If a file server defines the inactive method, call it only if the file -server has explicitly requested that inactive be called for the -node in question. -Once inactive has been called for a node, it will not be called -again unless the request to call inactive is reissued by the file server. -See -.Fn puffs_setback -in -.Xr puffs_ops 3 -for more information. -.It Dv PUFFS_KFLAG_LOOKUP_FULLPNBUF -This flag affects only the parameter -.Ar pcn to -.Fn puffs_node_lookup . -If this flag is not given, only the next pathname component under -lookup is found from -.Ar pcn-\*[Gt]pcn_name . -If this flag is given, the full path the kernel was -asked to resolve can be found from there. -.It Dv PUFFS_FLAG_BUILDPATH -The framework will build a complete path name, which is supplied -with each operation and can be found from the -.Va pn_po.po_full_pcn -field in a -.Vt struct puffs_node . -The option assumes that the framework can map a cookie to a -.Vt struct puffs_node . -See -.Sx Cookies -for more information on cookie mapping. -See -.Xr puffs_path 3 -for more information on library calls involving paths. -.It Dv PUFFS_FLAG_HASHPATH -Calculate a hash of the path into the path object field -.Va po_hash . -This hash value is used by -.Fn puffs_path_walkcmp -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_OPDUMP -This option makes the framework dump a textual representation of -each operation before executing it. -It is useful for debugging purposes. -.El -.El -.Pp -The following functions can be used to query or modify the global -state of the file system. -Note, that all calls are not available at all times. -.Bl -tag -width xxxx -.It Fn puffs_getselectable "pu" -Returns a handle to do I/O multiplexing with: -.Xr select 2 , -.Xr poll 2 , -and -.Xr kqueue 2 -are all examples of acceptable operations. -.It Fn puffs_setblockingmode "pu" "mode" -Sets the file system upstream access to blocking or non-blocking mode. -Acceptable values for the argument are -.Dv PUFFSDEV_BLOCK -and -.Dv PUFFSDEV_NONBLOCK . -.Pp -This routine can be called only after calling -.Fn puffs_mount . -.It Fn puffs_getstate "pu" -Returns the state of the file system. -It is maintained by the framework and is mostly useful for the framework -itself. -Possible values are -.Dv PUFFS_STATE_BEFOREMOUNT , -.Dv PUFFS_STATE_RUNNING , -.Dv PUFFS_STATE_UNMOUNTING -and -.Dv PUFFS_STATE_UNMOUNTED . -.It Fn puffs_setstacksize "pu" "stacksize" -Sets the stack size used when running callbacks. -The default is -.Dv PUFFS_STACKSIZE_DEFAULT -bytes of stack space per request. -The minimum stacksize is architecture-dependent and can be specified -by using the opaque constant -.Dv PUFFS_STACKSIZE_MIN . -.It Fn puffs_setroot "pu" "node" -Sets the root node of mount -.Fa pu -to -.Fa "node" . -Setting the root node is currently required only if the path -framework is used, see -.Xr puffs_path 3 . -.It Fn puffs_setrootinfo pu vt vsize rdev -The default root node is a directory. -In case the file system wants something different, it can call this -function and set the type, size and possible device type to whatever -it wants. -This routine is independent of -.Fn puffs_setroot . -.It Fn puffs_getroot "pu" -Returns the root node set earlier. -.It Fn puffs_getspecific "pu" -Returns the -.Fa private -argument of -.Fn puffs_init . -.It Fn puffs_setspecific "pu" "private" -Can be used to set the specific data after the call to -.Fn puffs_init . -.It Fn puffs_setmaxreqlen "pu" "maxreqlen" -In case the file system desires a maximum buffer length different from -the default, the amount -.Fa maxreqlen -will be requested from the kernel when the file system is mounted. -.Pp -It is legal to call this function only between -.Fn puffs_init -and -.Fn puffs_mount . -.Pp -.Em NOTE -This does not currently work. -.It Fn puffs_getmaxreqlen "pu" -Returns the maximum request length the kernel will need for a single -request. -.Pp -.Em NOTE -This does not currently work. -.It Fn puffs_setfhsize "pu" "fhsize" "flags" -Sets the desired file handle size. -This must be called if the file system wishes to support NFS exporting -file systems of the -.Fn fh* -family of function calls. -.Pp -In case all nodes in the file system produce the same length file handle, -it must be supplied as -.Fa fhsize . -In this case, the file system may ignore the length parameters in the -file handle callback routines, as the kernel will always pass the -correct length buffer. -However, if the file handle size varies according to file, the argument -.Fa fhsize -defines the maximum size of a file handle for the file system. -In this case the file system must take care of the handle lengths by -itself in the file handle callbacks, see -.Xr puffs_ops 3 -for more information. -Also, the flag -.Dv PUFFS_FHFLAG_DYNAMIC -must be provided in the argument -.Fa flags . -.Pp -In case the file system wants to sanity check its file handle lengths -for the limits of NFS, it can supply -.Dv PUFFS_FHFLAG_NFSV2 -and -.Dv PUFFS_FHFLAG_NFSV3 -in the -.Fa flags -parameter. -It is especially important to note that these are not directly the -limits specified by the protocols, as the kernel uses some bytes from -the buffer space. -In case the file handles are too large, mount will return an error. -.Pp -It is legal to call this function only between -.Fn puffs_init -and -.Fn puffs_mount . -.It Fn puffs_setncookiehash "pu" "ncookiehash" -The parameter -.Fa ncookiehash -controls the amount of hash buckets the kernel has for reverse lookups -from cookie to vnode. -Technically the default is enough, but a memory/time tradeoff can be -made by increasing this for file systems which know they will have -very many active files. -.Pp -It is legal to call this function only between -.Fn puffs_init -and -.Fn puffs_mount . -.El -.Pp -After the correct setup for the library has been established and the -backend has been initialized the file system is made operational by calling -.Fn puffs_mount . -After this function returns the file system should start processing requests. -.Bl -tag -width xxxx -.It Fn puffs_mount pu dir mntflags root_cookie -.Ar pu -is the library context pointer from -.Fn puffs_init . -The argument -.Fa dir -signifies the mount point and -.Fa mntflags -is the flagset given to -.Xr mount 2 . -The value -.Ar root_cookie -will be used as the cookie for the file system root node. -.El -.Ss Using the built-in eventloop -.Bl -tag -width xxxx -.It Fn puffs_ml_loop_fn pu -Loop function signature. -.It Fn puffs_ml_setloopfn pu lfn -Set loop function to -.Ar lfn . -This function is called once each time the event loop loops. -It is not a well-defined interval, but it can be made fairly regular -by setting the loop timeout by -.Fn puffs_ml_settimeout . -.It Fn puffs_ml_settimeout pu ts -Sets the loop timeout to -.Ar ts -or disables it if -.Ar ts -is -.Dv NULL . -This can be used to roughly control how often the loop callback -.Fn lfn -is called -.It Fn puffs_daemon pu nochdir noclose -Detach from the console like -.Fn daemon 3 . -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 -was killed in action. -.Pp -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 -.Fn puffs_mainloop -is not possible, requests may be dispatched manually. -However, as this is less efficient than using the mainloop, -it should never be the first preference. -.Pp -Calling -.Fn puffs_dispatch_create -creates a dispatch request. -The argument -.Ar pb -should contains a valid request and upon success -.Ar pccp -will contain a valid request context. -This context is passed to -.Fn puffs_dispatch_exec -to execute the request. -If the request yielded before completing, the routine returns 0, -otherwise 1. -When the routine completes, -.Ar pcc -is made invalid and a pointer to the processed buffer is placed in -.Ar pbp . -It is the responsibility of the caller to send the response (if -necessary) and destroy the buffer. -.Pp -See -.Xr puffs_cc 3 -and -.Xr puffs_framebuf 3 -for further information. -.El -.Ss Cookies -Every file (regular file, directory, device node, ...) instance is -attached to the kernel using a cookie. -A cookie should uniquely map to a file during its lifetime. -If file instances are kept in memory, a simple strategy is to use -the virtual address of the structure describing the file. -The cookie can be recycled when -.Fn puffs_node_reclaim -is called for a node. -.Pp -For some operations (such as building paths) the framework needs to map -the cookie to the framework-level structure describing a file, -.Vt struct puffs_node . -It is advisable to simply use the -.Vt struct puffs_node -address as a cookie and store file system specific data in the private -portion of -.Vt struct puffs_node . -The library assumes this by default. -.\"If it is not desirable, the file system implementation can call -.\".Fn puffs_set_cookiemap -.\"to provide an alternative cookie-to-node mapping function. -.Sh SEE ALSO -.Xr mount 2 , -.Xr puffs_cc 3 , -.Xr puffs_cred 3 , -.Xr puffs_flush 3 , -.Xr puffs_framebuf 3 , -.Xr puffs_node 3 , -.Xr puffs_ops 3 , -.Xr puffs_path 3 , -.\".Xr puffs_suspend 3 , -.Xr refuse 3 , -.Xr puffs 4 -.Rs -.%A Antti Kantee -.%D March 2007 -.%J Proceedings of AsiaBSDCon 2007 -.%P pp. 29-42 -.%T puffs - Pass-to-Userspace Framework File System -.Re -.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 -.%A Alistair Crooks -.%D September 2007 -.%J EuroBSDCon 2007 -.%T ReFUSE: Userspace FUSE Reimplementation Using puffs -.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 -.Sh HISTORY -An unsupported experimental version of -.Nm -first appeared in -.Nx 4.0 . -A stable version appeared in -.Nx 5.0 . -.Sh AUTHORS -.An Antti Kantee Aq Mt pooka@iki.fi diff --git a/lib/libpuffs/puffs.c b/lib/libpuffs/puffs.c deleted file mode 100644 index b9e0fffde1..0000000000 --- a/lib/libpuffs/puffs.c +++ /dev/null @@ -1,1020 +0,0 @@ -/* $NetBSD: puffs.c,v 1.116 2011/05/03 13:16:47 manu 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. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#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, -}; - -pthread_mutex_t pu_lock = PTHREAD_MUTEX_INITIALIZER; - -#define FILLOP(lower, upper) \ -do { \ - if (pops->puffs_node_##lower) \ - opmask[PUFFS_VN_##upper] = 1; \ -} while (/*CONSTCOND*/0) -static void -fillvnopmask(struct puffs_ops *pops, struct puffs_kargs *pa) -{ - uint8_t *opmask = pa->pa_vnopmask; - - memset(opmask, 0, sizeof(pa->pa_vnopmask)); - - FILLOP(create, CREATE); - FILLOP(mknod, MKNOD); - FILLOP(open, OPEN); - FILLOP(close, CLOSE); - FILLOP(access, ACCESS); - FILLOP(getattr, GETATTR); - FILLOP(setattr, SETATTR); - FILLOP(poll, POLL); - FILLOP(mmap, MMAP); - FILLOP(fsync, FSYNC); - FILLOP(seek, SEEK); - FILLOP(remove, REMOVE); - FILLOP(link, LINK); - FILLOP(rename, RENAME); - FILLOP(mkdir, MKDIR); - FILLOP(rmdir, RMDIR); - FILLOP(symlink, SYMLINK); - FILLOP(readdir, READDIR); - FILLOP(readlink, READLINK); - FILLOP(reclaim, RECLAIM); - FILLOP(inactive, INACTIVE); - FILLOP(print, PRINT); - FILLOP(read, READ); - FILLOP(write, WRITE); - FILLOP(advlock, ADVLOCK); - FILLOP(abortop, ABORTOP); - FILLOP(pathconf, PATHCONF); - - FILLOP(getextattr, GETEXTATTR); - FILLOP(setextattr, SETEXTATTR); - FILLOP(listextattr, LISTEXTATTR); - FILLOP(deleteextattr, DELETEEXTATTR); -} -#undef FILLOP - -/* - * Go over all framev entries and write everything we can. This is - * mostly for the benefit of delivering "unmount" to the kernel. - */ -static void -finalpush(struct puffs_usermount *pu) -{ - struct puffs_fctrl_io *fio; - - LIST_FOREACH(fio, &pu->pu_ios, fio_entries) { - if (fio->stat & FIO_WRGONE) - continue; - - puffs__framev_output(pu, fio->fctrl, fio); - } -} - -/*ARGSUSED*/ -void -puffs_kernerr_abort(struct puffs_usermount *pu, uint8_t type, - int error, const char *str, puffs_cookie_t cookie) -{ - - fprintf(stderr, "abort: type %d, error %d, cookie %p (%s)\n", - type, error, cookie, str); - abort(); -} - -/*ARGSUSED*/ -void -puffs_kernerr_log(struct puffs_usermount *pu, uint8_t type, - int error, const char *str, puffs_cookie_t cookie) -{ - - syslog(LOG_WARNING, "kernel: type %d, error %d, cookie %p (%s)\n", - type, error, cookie, str); -} - -int -puffs_getselectable(struct puffs_usermount *pu) -{ - - return pu->pu_fd; -} - -uint64_t -puffs__nextreq(struct puffs_usermount *pu) -{ - uint64_t rv; - - PU_LOCK(); - rv = pu->pu_nextreq++ | (uint64_t)1<<63; - PU_UNLOCK(); - - return rv; -} - -int -puffs_setblockingmode(struct puffs_usermount *pu, int mode) -{ - int rv, x; - - assert(puffs_getstate(pu) == PUFFS_STATE_RUNNING); - - if (mode != PUFFSDEV_BLOCK && mode != PUFFSDEV_NONBLOCK) { - errno = EINVAL; - return -1; - } - - x = mode; - rv = ioctl(pu->pu_fd, FIONBIO, &x); - - if (rv == 0) { - if (mode == PUFFSDEV_BLOCK) - pu->pu_state &= ~PU_ASYNCFD; - else - pu->pu_state |= PU_ASYNCFD; - } - - return rv; -} - -int -puffs_getstate(struct puffs_usermount *pu) -{ - - return pu->pu_state & PU_STATEMASK; -} - -void -puffs_setstacksize(struct puffs_usermount *pu, size_t ss) -{ - long psize, minsize; - int stackshift; - int bonus; - - assert(puffs_getstate(pu) == PUFFS_STATE_BEFOREMOUNT); - - psize = sysconf(_SC_PAGESIZE); - minsize = 4*psize; - if (ss < (size_t)minsize || ss == PUFFS_STACKSIZE_MIN) { - if (ss != PUFFS_STACKSIZE_MIN) - fprintf(stderr, "puffs_setstacksize: adjusting " - "stacksize to minimum %ld\n", minsize); - ss = 4*psize; - } - - stackshift = -1; - bonus = 0; - while (ss) { - if (ss & 0x1) - bonus++; - ss >>= 1; - stackshift++; - } - if (bonus > 1) { - stackshift++; - fprintf(stderr, "puffs_setstacksize: using next power of two: " - "%d\n", 1<pu_cc_stackshift = stackshift; -} - -struct puffs_pathobj * -puffs_getrootpathobj(struct puffs_usermount *pu) -{ - struct puffs_node *pnr; - - pnr = pu->pu_pn_root; - if (pnr == NULL) { - errno = ENOENT; - return NULL; - } - - return &pnr->pn_po; -} - -void -puffs_setroot(struct puffs_usermount *pu, struct puffs_node *pn) -{ - - pu->pu_pn_root = pn; -} - -struct puffs_node * -puffs_getroot(struct puffs_usermount *pu) -{ - - return pu->pu_pn_root; -} - -void -puffs_setrootinfo(struct puffs_usermount *pu, enum vtype vt, - vsize_t vsize, dev_t rdev) -{ - struct puffs_kargs *pargs = pu->pu_kargp; - - if (puffs_getstate(pu) != PUFFS_STATE_BEFOREMOUNT) { - warnx("puffs_setrootinfo: call has effect only " - "before mount\n"); - return; - } - - pargs->pa_root_vtype = vt; - pargs->pa_root_vsize = vsize; - pargs->pa_root_rdev = rdev; -} - -void * -puffs_getspecific(struct puffs_usermount *pu) -{ - - return pu->pu_privdata; -} - -void -puffs_setspecific(struct puffs_usermount *pu, void *privdata) -{ - - pu->pu_privdata = privdata; -} - -void -puffs_setmntinfo(struct puffs_usermount *pu, - const char *mntfromname, const char *puffsname) -{ - struct puffs_kargs *pargs = pu->pu_kargp; - - (void)strlcpy(pargs->pa_mntfromname, mntfromname, - sizeof(pargs->pa_mntfromname)); - (void)strlcpy(pargs->pa_typename, puffsname, - sizeof(pargs->pa_typename)); -} - -size_t -puffs_getmaxreqlen(struct puffs_usermount *pu) -{ - - return pu->pu_maxreqlen; -} - -void -puffs_setmaxreqlen(struct puffs_usermount *pu, size_t reqlen) -{ - - if (puffs_getstate(pu) != PUFFS_STATE_BEFOREMOUNT) - warnx("puffs_setmaxreqlen: call has effect only " - "before mount\n"); - - pu->pu_kargp->pa_maxmsglen = reqlen; -} - -void -puffs_setfhsize(struct puffs_usermount *pu, size_t fhsize, int flags) -{ - - if (puffs_getstate(pu) != PUFFS_STATE_BEFOREMOUNT) - warnx("puffs_setfhsize: call has effect only before mount\n"); - - pu->pu_kargp->pa_fhsize = fhsize; - pu->pu_kargp->pa_fhflags = flags; -} - -void -puffs_setncookiehash(struct puffs_usermount *pu, int nhash) -{ - - if (puffs_getstate(pu) != PUFFS_STATE_BEFOREMOUNT) - warnx("puffs_setfhsize: call has effect only before mount\n"); - - pu->pu_kargp->pa_nhashbuckets = nhash; -} - -void -puffs_set_pathbuild(struct puffs_usermount *pu, pu_pathbuild_fn fn) -{ - - pu->pu_pathbuild = fn; -} - -void -puffs_set_pathtransform(struct puffs_usermount *pu, pu_pathtransform_fn fn) -{ - - pu->pu_pathtransform = fn; -} - -void -puffs_set_pathcmp(struct puffs_usermount *pu, pu_pathcmp_fn fn) -{ - - pu->pu_pathcmp = fn; -} - -void -puffs_set_pathfree(struct puffs_usermount *pu, pu_pathfree_fn fn) -{ - - pu->pu_pathfree = fn; -} - -void -puffs_set_namemod(struct puffs_usermount *pu, pu_namemod_fn fn) -{ - - pu->pu_namemod = fn; -} - -void -puffs_set_errnotify(struct puffs_usermount *pu, pu_errnotify_fn fn) -{ - - pu->pu_errnotify = fn; -} - -void -puffs_set_cmap(struct puffs_usermount *pu, pu_cmap_fn fn) -{ - - pu->pu_cmap = fn; -} - -void -puffs_ml_setloopfn(struct puffs_usermount *pu, puffs_ml_loop_fn lfn) -{ - - pu->pu_ml_lfn = lfn; -} - -void -puffs_ml_settimeout(struct puffs_usermount *pu, struct timespec *ts) -{ - - if (ts == NULL) { - pu->pu_ml_timep = NULL; - } else { - pu->pu_ml_timeout = *ts; - pu->pu_ml_timep = &pu->pu_ml_timeout; - } -} - -void -puffs_set_prepost(struct puffs_usermount *pu, - pu_prepost_fn pre, pu_prepost_fn pst) -{ - - pu->pu_oppre = pre; - pu->pu_oppost = pst; -} - -void -puffs_setback(struct puffs_cc *pcc, int whatback) -{ - struct puffs_req *preq = puffs__framebuf_getdataptr(pcc->pcc_pb); - - assert(PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN && ( - preq->preq_optype == PUFFS_VN_OPEN || - preq->preq_optype == PUFFS_VN_MMAP || - preq->preq_optype == PUFFS_VN_REMOVE || - preq->preq_optype == PUFFS_VN_RMDIR || - preq->preq_optype == PUFFS_VN_INACTIVE)); - - preq->preq_setbacks |= whatback & PUFFS_SETBACK_MASK; -} - -int -puffs_daemon(struct puffs_usermount *pu, int nochdir, int noclose) -{ - long int n; - int parent, value, fd; - - if (pipe(pu->pu_dpipe) == -1) - return -1; - - switch (fork()) { - case -1: - return -1; - case 0: - parent = 0; - break; - default: - parent = 1; - break; - } - pu->pu_state |= PU_PUFFSDAEMON; - - if (parent) { - close(pu->pu_dpipe[1]); - n = read(pu->pu_dpipe[0], &value, sizeof(int)); - if (n == -1) - err(1, "puffs_daemon"); - if (n != sizeof(value)) - errx(1, "puffs_daemon got %ld bytes", n); - if (value) { - errno = value; - err(1, "puffs_daemon"); - } - exit(0); - } else { - if (setsid() == -1) - goto fail; - - if (!nochdir) - chdir("/"); - - if (!noclose) { - fd = open(_PATH_DEVNULL, O_RDWR, 0); - if (fd == -1) - goto fail; - dup2(fd, STDIN_FILENO); - dup2(fd, STDOUT_FILENO); - dup2(fd, STDERR_FILENO); - if (fd > STDERR_FILENO) - close(fd); - } - return 0; - } - - fail: - n = write(pu->pu_dpipe[1], &errno, sizeof(int)); - assert(n == 4); - return -1; -} - -static void -shutdaemon(struct puffs_usermount *pu, int error) -{ - ssize_t n; - - n = write(pu->pu_dpipe[1], &error, sizeof(int)); - assert(n == 4); - close(pu->pu_dpipe[0]); - close(pu->pu_dpipe[1]); - pu->pu_state &= ~PU_PUFFSDAEMON; -} - -int -puffs_mount(struct puffs_usermount *pu, const char *dir, int mntflags, - puffs_cookie_t cookie) -{ - struct stat sb; - int rv, fd, sverrno; - char *comfd; - - pu->pu_kargp->pa_root_cookie = cookie; - - /* XXXkludgehere */ - /* kauth doesn't provide this service any longer */ - if (geteuid() != 0) - mntflags |= MNT_NOSUID | MNT_NODEV; - - /* - * Undocumented... Well, documented only here. - * - * This is used for imaginative purposes. If the env variable is - * set, puffs_mount() doesn't do the regular mount procedure. - * Rather, it crams the mount data down the comfd and sets comfd as - * the puffs descriptor. - * - * This shouldn't be used unless you can read my mind ( ... or write - * it, not to mention execute it, but that's starting to get silly). - */ - if ((comfd = getenv("PUFFS_COMFD")) != NULL) { - size_t len; - - if (sscanf(comfd, "%d", &pu->pu_fd) != 1) { - errno = EINVAL; - rv = -1; - goto out; - } - /* check that what we got at least resembles an fd */ - if (fcntl(pu->pu_fd, F_GETFL) == -1) { - rv = -1; - goto out; - } - -#define allwrite(buf, len) \ -do { \ - ssize_t al_rv; \ - al_rv = write(pu->pu_fd, buf, len); \ - if ((size_t)al_rv != len) { \ - if (al_rv != -1) \ - errno = EIO; \ - rv = -1; \ - goto out; \ - } \ -} while (/*CONSTCOND*/0) - len = strlen(dir)+1; - allwrite(&len, sizeof(len)); - allwrite(dir, len); - len = strlen(pu->pu_kargp->pa_mntfromname)+1; - allwrite(&len, sizeof(len)); - allwrite(pu->pu_kargp->pa_mntfromname, len); - allwrite(&mntflags, sizeof(mntflags)); - len = sizeof(*pu->pu_kargp); - allwrite(&len, sizeof(len)); - allwrite(pu->pu_kargp, sizeof(*pu->pu_kargp)); - allwrite(&pu->pu_flags, sizeof(pu->pu_flags)); -#undef allwrite - - rv = 0; - } else { - char rp[MAXPATHLEN]; - - if (realpath(dir, rp) == NULL) { - rv = -1; - goto out; - } - - if (strcmp(dir, rp) != 0) { - warnx("puffs_mount: \"%s\" is a relative path.", dir); - warnx("puffs_mount: using \"%s\" instead.", rp); - } - - fd = open(_PATH_PUFFS, O_RDWR); - if (fd == -1) { - warnx("puffs_mount: cannot open %s", _PATH_PUFFS); - rv = -1; - goto out; - } - if (fd <= 2) - warnx("puffs_mount: device fd %d (<= 2), sure this is " - "what you want?", fd); - - pu->pu_fd = fd; - rv = fstat(fd, &sb); - if (rv == -1) { - warnx("puffs_mount: putter device stat failed"); - goto out; - } - pu->pu_kargp->pa_minor = minor(sb.st_rdev); - - if ((rv = mount(MOUNT_PUFFS, rp, mntflags, - pu->pu_kargp)) == -1) - goto out; - } - - PU_SETSTATE(pu, PUFFS_STATE_RUNNING); - - out: - if (rv != 0) - sverrno = errno; - else - sverrno = 0; - free(pu->pu_kargp); - pu->pu_kargp = NULL; - - if (pu->pu_state & PU_PUFFSDAEMON) - shutdaemon(pu, sverrno); - - errno = sverrno; - return rv; -} - -struct puffs_usermount * -puffs_init(struct puffs_ops *pops, const char *mntfromname, - const char *puffsname, void *priv, uint32_t pflags) -{ - struct puffs_usermount *pu; - struct puffs_kargs *pargs; - int sverrno; - - if (puffsname == PUFFS_DEFER) - puffsname = "n/a"; - if (mntfromname == PUFFS_DEFER) - mntfromname = "n/a"; - if (priv == PUFFS_DEFER) - priv = NULL; - - pu = malloc(sizeof(struct puffs_usermount)); - if (pu == NULL) - goto failfree; - memset(pu, 0, sizeof(struct puffs_usermount)); - - pargs = pu->pu_kargp = malloc(sizeof(struct puffs_kargs)); - if (pargs == NULL) - goto failfree; - memset(pargs, 0, sizeof(struct puffs_kargs)); - - pargs->pa_vers = PUFFSVERSION; - pargs->pa_flags = PUFFS_FLAG_KERN(pflags); - fillvnopmask(pops, pargs); - puffs_setmntinfo(pu, mntfromname, puffsname); - - puffs_zerostatvfs(&pargs->pa_svfsb); - pargs->pa_root_cookie = NULL; - pargs->pa_root_vtype = VDIR; - 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; - pu->pu_ops = *pops; - free(pops); /* XXX */ - - pu->pu_privdata = priv; - pu->pu_cc_stackshift = PUFFS_CC_STACKSHIFT_DEFAULT; - LIST_INIT(&pu->pu_pnodelst); - LIST_INIT(&pu->pu_ios); - LIST_INIT(&pu->pu_ios_rmlist); - LIST_INIT(&pu->pu_ccmagazin); - TAILQ_INIT(&pu->pu_sched); - - pu->pu_framectrl[PU_FRAMECTRL_FS].rfb = puffs__fsframe_read; - pu->pu_framectrl[PU_FRAMECTRL_FS].wfb = puffs__fsframe_write; - pu->pu_framectrl[PU_FRAMECTRL_FS].cmpfb = puffs__fsframe_cmp; - pu->pu_framectrl[PU_FRAMECTRL_FS].gotfb = puffs__fsframe_gotframe; - pu->pu_framectrl[PU_FRAMECTRL_FS].fdnotfn = puffs_framev_unmountonclose; - - /* 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_errnotify = puffs_kernerr_log; - - PU_SETSTATE(pu, PUFFS_STATE_BEFOREMOUNT); - - return pu; - - failfree: - /* can't unmount() from here for obvious reasons */ - sverrno = errno; - free(pu); - errno = sverrno; - return NULL; -} - -void -puffs_cancel(struct puffs_usermount *pu, int error) -{ - - assert(puffs_getstate(pu) < PUFFS_STATE_RUNNING); - shutdaemon(pu, error); - free(pu); -} - -/*ARGSUSED1*/ -int -puffs_exit(struct puffs_usermount *pu, int unused /* strict compat */) -{ - struct puffs_framebuf *pb; - struct puffs_req *preq; - void *winp; - size_t winlen; - int sverrno; - - pb = puffs_framebuf_make(); - if (pb == NULL) { - errno = ENOMEM; - return -1; - } - - winlen = sizeof(struct puffs_req); - if (puffs_framebuf_getwindow(pb, 0, &winp, &winlen) == -1) { - sverrno = errno; - puffs_framebuf_destroy(pb); - errno = sverrno; - return -1; - } - preq = winp; - - preq->preq_buflen = sizeof(struct puffs_req); - preq->preq_opclass = PUFFSOP_UNMOUNT; - preq->preq_id = puffs__nextreq(pu); - - puffs_framev_enqueue_justsend(pu, puffs_getselectable(pu), pb, 1, 0); - - return 0; -} - -/* no sigset_t static intializer */ -static int sigs[NSIG] = { 0, }; -static int sigcatch = 0; - -int -puffs_unmountonsignal(int sig, bool sigignore) -{ - - if (sig < 0 || sig >= (int)NSIG) { - errno = EINVAL; - return -1; - } - if (sigignore) - if (signal(sig, SIG_IGN) == SIG_ERR) - return -1; - - if (!sigs[sig]) - sigcatch++; - sigs[sig] = 1; - - return 0; -} - -/* - * Actual mainloop. This is called from a context which can block. - * It is called either from puffs_mainloop (indirectly, via - * puffs_cc_continue() or from puffs_cc_yield()). - */ -void -puffs__theloop(struct puffs_cc *pcc) -{ - struct puffs_usermount *pu = pcc->pcc_pu; - struct puffs_framectrl *pfctrl; - struct puffs_fctrl_io *fio; - struct kevent *curev; - size_t nchanges; - int ndone; - - while (puffs_getstate(pu) != PUFFS_STATE_UNMOUNTED) { - - /* - * Schedule existing requests. - */ - while ((pcc = TAILQ_FIRST(&pu->pu_sched)) != NULL) { - TAILQ_REMOVE(&pu->pu_sched, pcc, pcc_schedent); - puffs__goto(pcc); - } - - if (pu->pu_ml_lfn) - pu->pu_ml_lfn(pu); - - /* XXX: can we still do these optimizations? */ -#if 0 - /* - * Do this here, because: - * a) loopfunc might generate some results - * b) it's still "after" event handling (except for round 1) - */ - if (puffs_req_putput(ppr) == -1) - goto out; - puffs_req_resetput(ppr); - - /* micro optimization: skip kevent syscall if possible */ - if (pu->pu_nfds == 1 && pu->pu_ml_timep == NULL - && (pu->pu_state & PU_ASYNCFD) == 0) { - pfctrl = XXX->fctrl; - puffs_framev_input(pu, pfctrl, XXX); - continue; - } -#endif - - /* else: do full processing */ - /* Don't bother worrying about O(n) for now */ - LIST_FOREACH(fio, &pu->pu_ios, fio_entries) { - if (fio->stat & FIO_WRGONE) - continue; - - pfctrl = fio->fctrl; - - /* - * Try to write out everything to avoid the - * need for enabling EVFILT_WRITE. The likely - * case is that we can fit everything into the - * socket buffer. - */ - puffs__framev_output(pu, pfctrl, fio); - } - - /* - * Build list of which to enable/disable in writecheck. - */ - nchanges = 0; - LIST_FOREACH(fio, &pu->pu_ios, fio_entries) { - if (fio->stat & FIO_WRGONE) - continue; - - /* en/disable write checks for kqueue as needed */ - assert((FIO_EN_WRITE(fio) && FIO_RM_WRITE(fio)) == 0); - if (FIO_EN_WRITE(fio)) { - EV_SET(&pu->pu_evs[nchanges], fio->io_fd, - EVFILT_WRITE, EV_ENABLE, 0, 0, - fio); - fio->stat |= FIO_WR; - nchanges++; - } - if (FIO_RM_WRITE(fio)) { - EV_SET(&pu->pu_evs[nchanges], fio->io_fd, - EVFILT_WRITE, EV_DISABLE, 0, 0, - fio); - fio->stat &= ~FIO_WR; - nchanges++; - } - } - - ndone = kevent(pu->pu_kq, pu->pu_evs, nchanges, - pu->pu_evs, pu->pu_nevs, pu->pu_ml_timep); - - if (ndone == -1) { - if (errno != EINTR) - break; - else - continue; - } - - /* uoptimize */ - if (ndone == 0) - continue; - - /* iterate over the results */ - for (curev = pu->pu_evs; ndone--; curev++) { - int what; - -#if 0 - /* get & possibly dispatch events from kernel */ - if (curev->ident == puffsfd) { - if (puffs_req_handle(pgr, ppr, 0) == -1) - goto out; - continue; - } -#endif - - fio = (void *)curev->udata; - if (__predict_true(fio != NULL)) - pfctrl = fio->fctrl; - else - pfctrl = NULL; - if (curev->flags & EV_ERROR) { - assert(curev->filter == EVFILT_WRITE); - fio->stat &= ~FIO_WR; - - /* XXX: how to know if it's a transient error */ - puffs__framev_writeclose(pu, fio, - (int)curev->data); - puffs__framev_notify(fio, PUFFS_FBIO_ERROR); - continue; - } - - what = 0; - if (curev->filter == EVFILT_READ) { - puffs__framev_input(pu, pfctrl, fio); - what |= PUFFS_FBIO_READ; - } - - else if (curev->filter == EVFILT_WRITE) { - puffs__framev_output(pu, pfctrl, fio); - what |= PUFFS_FBIO_WRITE; - } - - else if (__predict_false(curev->filter==EVFILT_SIGNAL)){ - if ((pu->pu_state & PU_DONEXIT) == 0) { - PU_SETSFLAG(pu, PU_DONEXIT); - puffs_exit(pu, 0); - } - } - if (what) - puffs__framev_notify(fio, what); - } - - /* - * Really free fd's now that we don't have references - * to them. - */ - while ((fio = LIST_FIRST(&pu->pu_ios_rmlist)) != NULL) { - LIST_REMOVE(fio, fio_entries); - free(fio); - } - } - - if (puffs__cc_restoremain(pu) == -1) - warn("cannot restore main context. impending doom"); -} -int -puffs_mainloop(struct puffs_usermount *pu) -{ - struct puffs_fctrl_io *fio; - struct puffs_cc *pcc; - struct kevent *curev; - size_t nevs; - int sverrno, i; - - assert(puffs_getstate(pu) >= PUFFS_STATE_RUNNING); - - pu->pu_kq = kqueue(); - if (pu->pu_kq == -1) - goto out; - pu->pu_state |= PU_HASKQ; - - puffs_setblockingmode(pu, PUFFSDEV_NONBLOCK); - if (puffs__framev_addfd_ctrl(pu, puffs_getselectable(pu), - PUFFS_FBIO_READ | PUFFS_FBIO_WRITE, - &pu->pu_framectrl[PU_FRAMECTRL_FS]) == -1) - goto out; - - nevs = pu->pu_nevs + sigcatch; - curev = realloc(pu->pu_evs, nevs * sizeof(struct kevent)); - if (curev == NULL) - goto out; - pu->pu_evs = curev; - pu->pu_nevs = nevs; - - LIST_FOREACH(fio, &pu->pu_ios, fio_entries) { - EV_SET(curev, fio->io_fd, EVFILT_READ, EV_ADD, - 0, 0, fio); - curev++; - EV_SET(curev, fio->io_fd, EVFILT_WRITE, EV_ADD | EV_DISABLE, - 0, 0, fio); - curev++; - } - for (i = 0; i < NSIG; i++) { - if (sigs[i]) { - EV_SET(curev, i, EVFILT_SIGNAL, EV_ADD | EV_ENABLE, - 0, 0, 0); - curev++; - } - } - assert(curev - pu->pu_evs == (ssize_t)pu->pu_nevs); - if (kevent(pu->pu_kq, pu->pu_evs, pu->pu_nevs, NULL, 0, NULL) == -1) - goto out; - - pu->pu_state |= PU_INLOOP; - - /* - * Create alternate execution context and jump to it. Note - * that we come "out" of savemain twice. Where we come out - * of it depends on the architecture. If the return address is - * stored on the stack, we jump out from puffs_cc_continue(), - * for a register return address from puffs__cc_savemain(). - * PU_MAINRESTORE makes sure we DTRT in both cases. - */ - if (puffs__cc_create(pu, puffs__theloop, &pcc) == -1) { - goto out; - } - if (puffs__cc_savemain(pu) == -1) { - goto out; - } - if ((pu->pu_state & PU_MAINRESTORE) == 0) - puffs_cc_continue(pcc); - - finalpush(pu); - errno = 0; - - out: - /* store the real error for a while */ - sverrno = errno; - - errno = sverrno; - if (errno) - return -1; - else - return 0; -} diff --git a/lib/libpuffs/puffs.h b/lib/libpuffs/puffs.h deleted file mode 100644 index 2a7bc6602b..0000000000 --- a/lib/libpuffs/puffs.h +++ /dev/null @@ -1,687 +0,0 @@ -/* $NetBSD: puffs.h,v 1.118 2011/07/04 08:07:30 manu 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 _PUFFS_H_ -#define _PUFFS_H_ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -/* XXXDF */ -#define _PATH_PUFFS "/dev/putter" -#define MOUNT_PUFFS "puffs" /* Pass-to-Userspace filesystem */ - -/* forwards */ -struct puffs_cc; - -struct puffs_getreq; -struct puffs_cred; -struct puffs_newinfo; - -/* paths */ -struct puffs_pathobj { - void *po_path; - size_t po_len; - uint32_t po_hash; -}; - -/* for prefix rename */ -struct puffs_pathinfo { - struct puffs_pathobj *pi_old; - struct puffs_pathobj *pi_new; -}; - -/* describes one segment cached in the kernel */ -struct puffs_kcache { - off_t pkc_start; - off_t pkc_end; - - LIST_ENTRY(puffs_kcache) pkc_entries; -}; - -/* XXX: might disappear from here into a private header */ -struct puffs_node { - off_t pn_size; - int pn_flags; - struct vattr pn_va; - - void *pn_data; /* private data */ - - struct puffs_pathobj pn_po; /* PUFFS_FLAG_BUILDPATH */ - - struct puffs_usermount *pn_mnt; - LIST_ENTRY(puffs_node) pn_entries; - - LIST_HEAD(,puffs_kcache)pn_cacheinfo; /* PUFFS_KFLAG_CACHE */ - - void *pn_spare[4]; -}; -#define PUFFS_NODE_REMOVED 0x01 /* not on entry list */ - - -struct puffs_usermount; - -/* - * megaXXX: these are values from inside _KERNEL - * need to work on the translation for ALL the necessary values. - */ -#define PUFFS_VNOVAL (-1) - -#define PUFFS_IO_APPEND 0x020 -#define PUFFS_IO_NDELAY 0x100 - -#define PUFFS_VEXEC 01 -#define PUFFS_VWRITE 02 -#define PUFFS_VREAD 04 - -#define PUFFS_FSYNC_DATAONLY 0x0002 -#define PUFFS_FSYNC_CACHE 0x0100 - -#define PUFFS_EXTATTR_LIST_LENPREFIX 1 -/* - * Magic constants - */ -#define PUFFS_CC_STACKSHIFT_DEFAULT 18 - -struct puffs_cn { - struct puffs_kcn *pcn_pkcnp; /* kernel input */ - struct puffs_cred *pcn_cred; /* cred used for lookup */ - - struct puffs_pathobj pcn_po_full; /* PUFFS_FLAG_BUILDPATH */ -}; -#define pcn_name pcn_pkcnp->pkcn_name -#define pcn_namelen pcn_pkcnp->pkcn_namelen - -/* - * Puffs options to mount - */ -/* 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 } - -/* libpuffs */ -#define PUFFSMOPT_DUMP { "dump", 0, PUFFS_FLAG_OPDUMP, 1 } - -#define PUFFSMOPT_STD \ - PUFFSMOPT_NAMECACHE, \ - PUFFSMOPT_PAGECACHE, \ - PUFFSMOPT_ATTRCACHE, \ - PUFFSMOPT_CACHE, \ - PUFFSMOPT_ALLOPS, \ - PUFFSMOPT_DUMP - -extern const struct mntopt puffsmopts[]; /* puffs.c */ - -/* callbacks for operations */ -struct puffs_ops { - int (*puffs_fs_unmount)(struct puffs_usermount *, int); - int (*puffs_fs_statvfs)(struct puffs_usermount *, struct statvfs *); - int (*puffs_fs_sync)(struct puffs_usermount *, int); - int (*puffs_fs_fhtonode)(struct puffs_usermount *, void *, size_t, - struct puffs_newinfo *); - int (*puffs_fs_nodetofh)(struct puffs_usermount *, puffs_cookie_t, - void *, size_t *); - 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 *); - int (*puffs_node_lookupdotdot)(struct puffs_usermount *, - puffs_cookie_t, struct puffs_newinfo *, const struct puffs_cn *); - int (*puffs_node_create)(struct puffs_usermount *, - puffs_cookie_t, struct puffs_newinfo *, const struct puffs_cn *, - const struct vattr *); - int (*puffs_node_mknod)(struct puffs_usermount *, - puffs_cookie_t, struct puffs_newinfo *, const struct puffs_cn *, - const struct vattr *); - int (*puffs_node_open)(struct puffs_usermount *, - puffs_cookie_t, int, const struct puffs_cred *); - int (*puffs_node_close)(struct puffs_usermount *, - puffs_cookie_t, int); - int (*puffs_node_access)(struct puffs_usermount *, - puffs_cookie_t, int, const struct puffs_cred *); - int (*puffs_node_getattr)(struct puffs_usermount *, - puffs_cookie_t, struct vattr *, const struct puffs_cred *); - int (*puffs_node_setattr)(struct puffs_usermount *, - puffs_cookie_t, const struct vattr *, const struct puffs_cred *); - int (*puffs_node_poll)(struct puffs_usermount *, puffs_cookie_t, int *); - int (*puffs_node_mmap)(struct puffs_usermount *, - puffs_cookie_t, vm_prot_t, const struct puffs_cred *); - int (*puffs_node_fsync)(struct puffs_usermount *, - puffs_cookie_t, int); - int (*puffs_node_seek)(struct puffs_usermount *, - puffs_cookie_t, off_t, off_t, const struct puffs_cred *); - int (*puffs_node_remove)(struct puffs_usermount *, - puffs_cookie_t, puffs_cookie_t, const struct puffs_cn *); - int (*puffs_node_link)(struct puffs_usermount *, - puffs_cookie_t, puffs_cookie_t, const struct puffs_cn *); - int (*puffs_node_rename)(struct puffs_usermount *, - puffs_cookie_t, puffs_cookie_t, const struct puffs_cn *, - puffs_cookie_t, puffs_cookie_t, const struct puffs_cn *); - int (*puffs_node_mkdir)(struct puffs_usermount *, - puffs_cookie_t, struct puffs_newinfo *, const struct puffs_cn *, - const struct vattr *); - int (*puffs_node_rmdir)(struct puffs_usermount *, - puffs_cookie_t, puffs_cookie_t, const struct puffs_cn *); - int (*puffs_node_symlink)(struct puffs_usermount *, - puffs_cookie_t, struct puffs_newinfo *, const struct puffs_cn *, - const struct vattr *, - const char *); - int (*puffs_node_readdir)(struct puffs_usermount *, - puffs_cookie_t, struct dirent *, off_t *, size_t *, - const struct puffs_cred *, int *, off_t *, size_t *); - int (*puffs_node_readlink)(struct puffs_usermount *, - puffs_cookie_t, const struct puffs_cred *, char *, size_t *); - int (*puffs_node_reclaim)(struct puffs_usermount *, puffs_cookie_t); - 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, 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, - uint8_t *, off_t, size_t *, const struct puffs_cred *, int); - int (*puffs_node_write)(struct puffs_usermount *, puffs_cookie_t, - 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 *); - - void *puffs_ops_spare[32]; -}; - -typedef int (*pu_pathbuild_fn)(struct puffs_usermount *, - const struct puffs_pathobj *, - const struct puffs_pathobj *, size_t, - struct puffs_pathobj *); -typedef int (*pu_pathtransform_fn)(struct puffs_usermount *, - const struct puffs_pathobj *, - const struct puffs_cn *, - struct puffs_pathobj *); -typedef int (*pu_pathcmp_fn)(struct puffs_usermount *, struct puffs_pathobj *, - struct puffs_pathobj *, size_t, int); -typedef void (*pu_pathfree_fn)(struct puffs_usermount *, - struct puffs_pathobj *); -typedef int (*pu_namemod_fn)(struct puffs_usermount *, - struct puffs_pathobj *, struct puffs_cn *); - -typedef void (*pu_errnotify_fn)(struct puffs_usermount *, - uint8_t, int, const char *, puffs_cookie_t); - -typedef void (*pu_prepost_fn)(struct puffs_usermount *); - -typedef struct puffs_node *(*pu_cmap_fn)(struct puffs_usermount *, - puffs_cookie_t); - -enum { - PUFFS_STATE_BEFOREMOUNT, PUFFS_STATE_RUNNING, - PUFFS_STATE_UNMOUNTING, PUFFS_STATE_UNMOUNTED -}; - -#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_KERN(a) ((a) & PUFFS_KFLAG_MASK) -#define PUFFS_FLAG_LIB(a) ((a) & PUFFS_FLAG_MASK) - -/* blocking mode argument */ -#define PUFFSDEV_BLOCK 0 -#define PUFFSDEV_NONBLOCK 1 - -#define PUFFS_STACKSIZE_DEFAULT (1<puffs_##fsornode##_##opname = fsname##_##fsornode##_##opname -#define PUFFSOP_SETFSNOP(ops, opname) \ - (ops)->puffs_fs_##opname = puffs_fsnop_##opname - -PUFFSOP_PROTOS(puffs_null) /* XXX */ - -#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) -#define PCNPLEN(pcnode) ((pcnode)->pcn_po_full.po_len) - -#define PUFFS_STORE_DCOOKIE(cp, ncp, off) \ -if (cp) { \ - *((cp)++) = off; \ - (*(ncp))++; \ -} - -/* mainloop */ -typedef void (*puffs_ml_loop_fn)(struct puffs_usermount *); - -/* framebuf stuff */ -struct puffs_framebuf; -typedef int (*puffs_framev_readframe_fn)(struct puffs_usermount *, - struct puffs_framebuf *, - int, int *); -typedef int (*puffs_framev_writeframe_fn)(struct puffs_usermount *, - struct puffs_framebuf *, - int, int *); -typedef int (*puffs_framev_cmpframe_fn)(struct puffs_usermount *, - struct puffs_framebuf *, - struct puffs_framebuf *, - int *); -typedef void (*puffs_framev_fdnotify_fn)(struct puffs_usermount *, int, int); -typedef void (*puffs_framev_gotframe_fn)(struct puffs_usermount *, - struct puffs_framebuf *); -typedef void (*puffs_framev_cb)(struct puffs_usermount *, - struct puffs_framebuf *, - void *, int); -#define PUFFS_FBIO_READ 0x01 -#define PUFFS_FBIO_WRITE 0x02 -#define PUFFS_FBIO_ERROR 0x04 - -#define PUFFS_FBQUEUE_URGENT 0x01 - - -__BEGIN_DECLS - -#define PUFFS_DEFER ((void *)-1) -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); - -void puffs_ml_setloopfn(struct puffs_usermount *, puffs_ml_loop_fn); -void puffs_ml_settimeout(struct puffs_usermount *, struct timespec *); - -void puffs_setroot(struct puffs_usermount *, - struct puffs_node *); -struct puffs_node *puffs_getroot(struct puffs_usermount *); -void puffs_setrootinfo(struct puffs_usermount *, - enum vtype, vsize_t, dev_t); - -void *puffs_getspecific(struct puffs_usermount *); -void puffs_setspecific(struct puffs_usermount *, void *); -void puffs_setmaxreqlen(struct puffs_usermount *, size_t); -size_t puffs_getmaxreqlen(struct puffs_usermount *); -void puffs_setfhsize(struct puffs_usermount *, size_t, int); -void puffs_setmntinfo(struct puffs_usermount *, - const char *, const char *); - -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 *); -struct vattr *puffs_pn_getvap(struct puffs_node *); -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 *); - -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_pn_getmntspecific(struct puffs_node *); - -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_setvattr(struct vattr *, const struct vattr *); -void puffs_vattr_null(struct vattr *); - -void puffs_null_setops(struct puffs_ops *); - -int puffs_dispatch_create(struct puffs_usermount *, - struct puffs_framebuf *, - struct puffs_cc **); -int puffs_dispatch_exec(struct puffs_cc *, - struct puffs_framebuf **); - -/* - * generic/dummy routines applicable for some file systems - */ -int puffs_fsnop_unmount(struct puffs_usermount *, int); -int puffs_fsnop_statvfs(struct puffs_usermount *, struct statvfs *); -void puffs_zerostatvfs(struct statvfs *); -int puffs_fsnop_sync(struct puffs_usermount *, int waitfor); - -int puffs_genfs_node_getattr(struct puffs_usermount *, puffs_cookie_t, - struct vattr *, const struct puffs_cred *); -int puffs_genfs_node_reclaim(struct puffs_usermount *, puffs_cookie_t); - -/* - * Subroutine stuff - */ - -int puffs_gendotdent(struct dirent **, ino_t, int, size_t *); -int puffs_nextdent(struct dirent **, const char *, ino_t, - uint8_t, size_t *); -int puffs_vtype2dt(enum vtype); -enum vtype puffs_mode2vt(mode_t); -void puffs_stat2vattr(struct vattr *va, const struct stat *); -mode_t puffs_addvtype2mode(mode_t, enum vtype); - - -/* - * credentials & permissions - */ - -/* Credential fetch */ -int puffs_cred_getuid(const struct puffs_cred *, uid_t *); -int puffs_cred_getgid(const struct puffs_cred *, gid_t *); -int puffs_cred_getgroups(const struct puffs_cred *, gid_t *, short *); - -/* Credential check */ -bool puffs_cred_isuid(const struct puffs_cred *, uid_t); -bool puffs_cred_hasgroup(const struct puffs_cred *, gid_t); -bool puffs_cred_isregular(const struct puffs_cred *); -bool puffs_cred_iskernel(const struct puffs_cred *); -bool puffs_cred_isfs(const struct puffs_cred *); -bool puffs_cred_isjuggernaut(const struct puffs_cred *); - -/* misc */ -int puffs_access(enum vtype, mode_t, uid_t, gid_t, mode_t, - const struct puffs_cred *); -int puffs_access_chown(uid_t, gid_t, uid_t, gid_t, - const struct puffs_cred *); -int puffs_access_chmod(uid_t, gid_t, enum vtype, mode_t, - const struct puffs_cred *); -int puffs_access_times(uid_t, gid_t, mode_t, int, - const struct puffs_cred *); - - -/* - * Call Context interfaces relevant for user. - */ - -void puffs_cc_yield(struct puffs_cc *); -void puffs_cc_continue(struct puffs_cc *); -void puffs_cc_schedule(struct puffs_cc *); -int puffs_cc_getcaller(struct puffs_cc *,pid_t *,lwpid_t *); -struct puffs_cc *puffs_cc_getcc(struct puffs_usermount *); - -/* - * Flushing / invalidation routines - */ - -int puffs_inval_namecache_dir(struct puffs_usermount *, puffs_cookie_t); -int puffs_inval_namecache_all(struct puffs_usermount *); - -int puffs_inval_pagecache_node(struct puffs_usermount *, puffs_cookie_t); -int puffs_inval_pagecache_node_range(struct puffs_usermount *, - puffs_cookie_t, off_t, off_t); -int puffs_flush_pagecache_node(struct puffs_usermount *, puffs_cookie_t); -int puffs_flush_pagecache_node_range(struct puffs_usermount *, - puffs_cookie_t, off_t, off_t); - -/* - * Path constructicons - */ - -int puffs_stdpath_buildpath(struct puffs_usermount *, - const struct puffs_pathobj *, - const struct puffs_pathobj *, size_t, - struct puffs_pathobj *); -int puffs_stdpath_cmppath(struct puffs_usermount *, struct puffs_pathobj *, - struct puffs_pathobj *, size_t, int); -void puffs_stdpath_freepath(struct puffs_usermount *,struct puffs_pathobj *); - -void *puffs_path_walkcmp(struct puffs_usermount *, - struct puffs_node *, void *); -void *puffs_path_prefixadj(struct puffs_usermount *, - struct puffs_node *, void *); -int puffs_path_pcnbuild(struct puffs_usermount *, - struct puffs_cn *, void *); -void puffs_path_buildhash(struct puffs_usermount *, struct puffs_pathobj *); -void puffs_set_pathbuild(struct puffs_usermount *, pu_pathbuild_fn); void puffs_set_pathtransform(struct puffs_usermount *, pu_pathtransform_fn); -void puffs_set_pathcmp(struct puffs_usermount *, pu_pathcmp_fn); -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); -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); - -/* - * Suspension - */ - -int puffs_fs_suspend(struct puffs_usermount *); - -/* - * Frame buffering - */ - -void puffs_framev_init(struct puffs_usermount *, - puffs_framev_readframe_fn, - puffs_framev_writeframe_fn, - puffs_framev_cmpframe_fn, - puffs_framev_gotframe_fn, - puffs_framev_fdnotify_fn); - -struct puffs_framebuf *puffs_framebuf_make(void); -void puffs_framebuf_destroy(struct puffs_framebuf *); -int puffs_framebuf_dup(struct puffs_framebuf *, - struct puffs_framebuf **); -void puffs_framebuf_recycle(struct puffs_framebuf *); -int puffs_framebuf_reserve_space(struct puffs_framebuf *, - size_t); - -int puffs_framebuf_putdata(struct puffs_framebuf *, const void *, size_t); -int puffs_framebuf_putdata_atoff(struct puffs_framebuf *, size_t, - const void *, size_t); -int puffs_framebuf_getdata(struct puffs_framebuf *, void *, size_t); -int puffs_framebuf_getdata_atoff(struct puffs_framebuf *, size_t, - void *, size_t); - -size_t puffs_framebuf_telloff(struct puffs_framebuf *); -size_t puffs_framebuf_tellsize(struct puffs_framebuf *); -size_t puffs_framebuf_remaining(struct puffs_framebuf *); -int puffs_framebuf_seekset(struct puffs_framebuf *, size_t); -int puffs_framebuf_getwindow(struct puffs_framebuf *, size_t, - void **, size_t *); - -int puffs_framev_enqueue_cc(struct puffs_cc *, int, - struct puffs_framebuf *, int); -int puffs_framev_enqueue_cb(struct puffs_usermount *, int, - struct puffs_framebuf *, - puffs_framev_cb, void *, int); -int puffs_framev_enqueue_justsend(struct puffs_usermount *, int, - struct puffs_framebuf *, int, int); -int puffs_framev_enqueue_directreceive(struct puffs_cc *, int, - struct puffs_framebuf *, int); -int puffs_framev_enqueue_directsend(struct puffs_cc *, int, - struct puffs_framebuf *, int); -int puffs_framev_enqueue_waitevent(struct puffs_cc *, int, int *); -int puffs_framev_framebuf_ccpromote(struct puffs_framebuf *, - struct puffs_cc *); - -int puffs_framev_addfd(struct puffs_usermount *, int, int); -int puffs_framev_enablefd(struct puffs_usermount *, int, int); -int puffs_framev_disablefd(struct puffs_usermount *, int, int); -int puffs_framev_removefd(struct puffs_usermount *, int, int); -void puffs_framev_removeonclose(struct puffs_usermount *, int, int); -void puffs_framev_unmountonclose(struct puffs_usermount *, int, int); - -__END_DECLS - -#endif /* _PUFFS_H_ */ diff --git a/lib/libpuffs/puffs_cc.3 b/lib/libpuffs/puffs_cc.3 deleted file mode 100644 index 10f8d711bf..0000000000 --- a/lib/libpuffs/puffs_cc.3 +++ /dev/null @@ -1,93 +0,0 @@ -.\" $NetBSD: puffs_cc.3,v 1.14 2009/04/11 16:48:53 wiz Exp $ -.\" -.\" Copyright (c) 2007, 2008 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 February 5, 2012 -.Dt PUFFS_CC 3 -.Os -.Sh NAME -.Nm puffs_cc -.Nd puffs continuation routines -.Sh LIBRARY -.Lb libpuffs -.Sh SYNOPSIS -.In puffs.h -.Ft void -.Fn puffs_cc_yield "struct puffs_cc *pcc" -.Ft void -.Fn puffs_cc_continue "struct puffs_cc *pcc" -.Ft void -.Fn puffs_cc_schedule "struct puffs_cc *pcc" -.Ft struct puffs_cc * -.Fn puffs_cc_getcc "struct puffs_usermount *pu" -.Sh DESCRIPTION -These routines are used for the cooperative multitasking suite present -in puffs. -.Bl -tag -width xxxx -.It Fn puffs_cc_yield "pcc" -Suspend and save the current execution context and return control -to the previous point. -In practice, from the file system author perspective, control returns -back to where either the mainloop or where -.Fn puffs_dispatch_exec -was called from. -.It Fn puffs_cc_continue pcc -Will suspend current execution and return control to where it was -before calling -.Fn puffs_cc_yield . -This is rarely called directly but rather through -.Fn puffs_dispatch_exec . -.It Fn puffs_cc_schedule "pcc" -Schedule a continuation. -As opposed to -.Fn puffs_cc_continue -this call returns immediately. -.Fa pcc -will be scheduled sometime in the future. -.It Fn puffs_cc_getcc "pu" -Returns the current pcc or -.Dv NULL -if this is the main thread. -.Em NOTE : -The argument -.Ar pu -will most likely disappear at some point. -.El -.Pp -Before calling -.Fn puffs_cc_yield -a file system will typically want to record some cookie value into its -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 -.Xr puffs_framebuf 3 -framework and -.Fn puffs_mainloop -can be used for handling this automatically. -.Sh SEE ALSO -.Xr puffs 3 , -.Xr puffs_framebuf 3 diff --git a/lib/libpuffs/puffs_cred.3 b/lib/libpuffs/puffs_cred.3 deleted file mode 100644 index 21659a172d..0000000000 --- a/lib/libpuffs/puffs_cred.3 +++ /dev/null @@ -1,167 +0,0 @@ -.\" $NetBSD: puffs_cred.3,v 1.5 2009/04/11 15:36:22 joerg 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 February 5, 2012 -.Dt PUFFS_CRED 3 -.Os -.Sh NAME -.Nm puffs_cred -.Nd puffs credential and access control routines -.Sh LIBRARY -.Lb libpuffs -.Sh SYNOPSIS -.In puffs.h -.Ft int -.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 -.Fo puffs_cred_getgroups -.Fa "const struct puffs_cred *pcr" "gid_t *gids" "short *ngids" -.Fc -.Pp -.Ft bool -.Fn puffs_cred_isuid "const struct puffs_cred *pcr" "uid_t uid" -.Ft bool -.Fn puffs_cred_hasgroup "const struct puffs_cred *pcr" "gid_t gid" -.Ft bool -.Fn puffs_cred_iskernel "const struct puffs_cred *pcr" -.Ft bool -.Fn puffs_cred_isfs "const struct puffs_cred *pcr" -.Ft bool -.Fn puffs_cred_isjuggernaut "const struct puffs_cred *pcr" -.Pp -.Ft int -.Fo puffs_access -.Fa "enum vtype type" "mode_t file_mode" "uid_t owner" "gid_t group" -.Fa "mode_t access_mode" "const struct puffs_cred *pcr" -.Fc -.Ft int -.Fo puffs_access_chown -.Fa "uid_t owner" "gid_t group" "uid_t newowner" "gid_t newgroup" -.Fa "const struct puffs_cred *pcr" -.Fc -.Ft int -.Fo puffs_access_chmod -.Fa "uid_t owner" "gid_t group" "enum vtype type" "mode_t newmode" -.Fa "const struct puffs_cred *pcr" -.Fc -.Ft int -.Fo puffs_access_times -.Fa "uid_t owner" "gid_t group" "mode_t file_mode" "int va_utimes_null" -.Fa "const struct puffs_cred *pcr" -.Fc -.Sh DESCRIPTION -These functions can be used to check operation credentials and perform -access control. -The structure -.Vt struct puffs_cred -can contain two types of credentials: ones belonging to users and -ones belonging to the kernel. -The latter is further divided into generic kernel credentials and -file system credentials. -The general rule is that these should be treated as more powerful -than superuser credentials, but the file system is free to treat -them as it sees fit. -.Ss Credentials -The -.Fn puffs_cred_get -family of functions fetch the uid or gid(s) from the given credential -cookie. -They return 0 for success or \-1 for an error and set -.Va errno . -An error happens when the credentials represent kernel or file system -credentials and do not contain an uid or gid(s). -.Pp -For -.Fn puffs_cred_getgroups , -the argument -.Fa gids -should point to an array with room for -.Fa *ngids -elements. -.Pp -The -.Fn puffs_cred_is -family of functions return 1 if the truth value of the function for -.Fa pcr -is true and 0 if it is false. -The function -.Fn puffs_cred_isjuggernaut -is true if -.Fa pcr -describes superuser, kernel or file system credentials. -.Ss Access Control -To help the programmers task of emulating normal kernel file system -access control semantics, several helper functions are provided to -check if access is allowed. -They return 0 if access should be permitted or an errno value to -indicate that access should be denied with the returned value. -.Pp -.Fn puffs_access -is equivalent to the kernel -.Fn vaccess -function. -The arguments specify current information of the file to be -tested with the exception of -.Fa access_mode , -which is a combination of -.Dv PUFFS_VREAD , -.Dv PUFFS_VWRITE -and -.Dv PUFFS_VEXEC -indicating the desired file access mode. -.Pp -The rest of the functions provide UFS semantics for operations. -.Fn puffs_access_chown -checks if it is permissible to chown a file with the current uid -and gid to the new uid and gid with the credentials of -.Fa pcr . -.Pp -.Fn puffs_access_chmod -checks against permission to chmod a file of type -.Fa type -to the mode -.Fa newmode . -.Pp -Finally, -.Fn puffs_access_times -checks if it is allowable to update the timestamps of a file. -The argument -.Fa va_utimes_null -signals if the flags -.Dv VA_UTIMES_NULL -was set in -.Fa va_vaflags -of -.Va struct vattr . -If coming from a path where this information is unavailable, passing -0 as this argument restricts the permission of modification to the -owner and superuser. -Otherwise the function checks for write permissions to the node and -returns success if the caller has write permissions. -.Sh SEE ALSO -.Xr puffs 3 , -.Xr vnode 9 diff --git a/lib/libpuffs/puffs_flush.3 b/lib/libpuffs/puffs_flush.3 deleted file mode 100644 index bfcad3bded..0000000000 --- a/lib/libpuffs/puffs_flush.3 +++ /dev/null @@ -1,113 +0,0 @@ -.\" $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 February 5, 2012 -.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 diff --git a/lib/libpuffs/puffs_framebuf.3 b/lib/libpuffs/puffs_framebuf.3 deleted file mode 100644 index b165d72f38..0000000000 --- a/lib/libpuffs/puffs_framebuf.3 +++ /dev/null @@ -1,620 +0,0 @@ -.\" $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 February 5, 2012 -.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_framev_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 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 user of -.Nm -in the tree is -.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 diff --git a/lib/libpuffs/puffs_node.3 b/lib/libpuffs/puffs_node.3 deleted file mode 100644 index e0faa1c650..0000000000 --- a/lib/libpuffs/puffs_node.3 +++ /dev/null @@ -1,101 +0,0 @@ -.\" $NetBSD: puffs_node.3,v 1.5 2009/05/13 22:42:31 wiz 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 February 5, 2012 -.Dt PUFFS_NODE 3 -.Os -.Sh NAME -.Nm puffs_node -.Nd puffs node routines -.Sh LIBRARY -.Lb libpuffs -.Sh SYNOPSIS -.In puffs.h -.Ft struct puffs_node * -.Fn puffs_pn_new "struct puffs_usermount *pu" "void *priv" -.Ft void * -.Fo puffs_nodewalk_fn -.Fa "struct puffs_usermount *pu" "struct puffs_node *pn" "void *arg" -.Fc -.Ft void * -.Fo puffs_pn_nodewalk -.Fa "struct puffs_usermount *pu" "puffs_nodewalk_fn nwfn" "void *arg" -.Fc -.Ft void -.Fn puffs_pn_remove "struct puffs_node *pn" -.Ft void -.Fn puffs_pn_put "struct puffs_node *pn" -.Sh DESCRIPTION -.Bl -tag -width xxxx -.It Fn puffs_pn_new pu priv -Create a new node and attach it to the mountpoint -.Ar pu . -The argument -.Ar priv -can be used for associating file system specific data with the new -node and will not be accessed by puffs. -.It Fn puffs_nodewalk_fn pu pn arg -A callback for -.Fn puffs_pn_nodewalk . -The list of nodes is iterated in the argument -.Ar pn -and the argument -.Ar arg -is the argument given to -.Fn puffs_pn_nodewalk . -.It Fn puffs_pn_nodewalk pu nwfn arg -Walk all nodes associted with the mountpoint -.Ar pu -and call -.Fn nwfn -for them. -The walk is aborted if -.Fn puffs_nodewalk_fn -returns a value which is not -.Dv NULL . -This value is also returned this function. -In case the whole set of nodes is traversed, -.Dv NULL -is returned. -This function is useful for example in handling the -.Fn puffs_fs_sync -callback, when cached data for every node should be flushed to stable -storage. -.It Fn puffs_pn_remove pn -Signal that a node has been removed from the file system, but do not -yet release resources associated with the node. -This will prevent the nodewalk functions from accessing the node. -If necessary, this is usually called from -.Fn puffs_node_remove -and -.Fn puffs_node_rmdir . -.It Fn puffs_pn_put pn -Free all resources associated with node -.Ar pn . -This is typically called from -.Fn puffs_node_reclaim . -.El -.Sh SEE ALSO -.Xr puffs 3 diff --git a/lib/libpuffs/puffs_ops.3 b/lib/libpuffs/puffs_ops.3 deleted file mode 100644 index 9f39b922f5..0000000000 --- a/lib/libpuffs/puffs_ops.3 +++ /dev/null @@ -1,782 +0,0 @@ -.\" $NetBSD: puffs_ops.3,v 1.29 2011/07/04 08:07:30 manu 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 February 5, 2012 -.Dt PUFFS_OPS 3 -.Os -.Sh NAME -.Nm puffs_ops -.Nd puffs callback operations -.Sh LIBRARY -.Lb libpuffs -.Sh SYNOPSIS -.In puffs.h -.Ft int -.Fo puffs_fs_statvfs -.Fa "struct puffs_usermount *pu" "struct statvfs *sbp" -.Fc -.Ft int -.Fo puffs_fs_sync -.Fa "struct puffs_usermount *pu" "int waitfor" "const struct puffs_cred *pcr" -.Fc -.Ft int -.Fo puffs_fs_fhtonode -.Fa "struct puffs_usermount *pu" "void *fid" "size_t fidsize" -.Fa "struct puffs_newinfo *pni" -.Fc -.Ft int -.Fo puffs_fs_nodetofh -.Fa "struct puffs_usermount *pu" "puffs_cookie_t cookie" "void *fid" -.Fa "size_t *fidsize" -.Fc -.Ft void -.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" -.Fc -.Ft int -.Fo puffs_node_lookup -.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" -.Fa "struct puffs_newinfo *pni" "const struct puffs_cn *pcn" -.Fc -.Ft int -.Fo puffs_node_create -.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" -.Fa "struct puffs_newinfo *pni" "const struct puffs_cn *pcn" -.Fa "const struct vattr *vap" -.Fc -.Ft int -.Fo puffs_node_mknod -.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" -.Fa "struct puffs_newinfo *pni" "const struct puffs_cn *pcn" -.Fa "const struct vattr *vap" -.Fc -.Ft int -.Fo puffs_node_open -.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" "int mode" -.Fa "const struct puffs_cred *pcr" -.Fc -.Ft int -.Fo puffs_node_close -.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" "int flags" -.Fa "const struct puffs_cred *pcr" -.Fc -.Ft int -.Fo puffs_node_access -.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" "int mode" -.Fa "const struct puffs_cred *pcr" -.Fc -.Ft int -.Fo puffs_node_getattr -.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" "struct vattr *vap" -.Fa "const struct puffs_cred *pcr" -.Fc -.Ft int -.Fo puffs_node_setattr -.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" "const struct vattr *vap" -.Fa "const struct puffs_cred *pcr" -.Fc -.Ft int -.Fo puffs_node_poll -.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" "int *events" -.Fc -.Ft int -.Fo puffs_node_mmap -.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" "int flags" -.Fa "const struct puffs_cred *pcr" -.Fc -.Ft int -.Fo puffs_node_fsync -.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" -.Fa "int flags" -.Fc -.Ft int -.Fo puffs_node_seek -.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" "off_t oldoff" -.Fa "off_t newoff" "const struct puffs_cred *pcr" -.Fc -.Ft int -.Fo puffs_node_remove -.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" "puffs_cookie_t targ" -.Fa "const struct puffs_cn *pcn" -.Fc -.Ft int -.Fo puffs_node_link -.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" "puffs_cookie_t targ" -.Fa "const struct puffs_cn *pcn" -.Fc -.Ft int -.Fo puffs_node_rename -.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" "puffs_cookie_t src" -.Fa "const struct puffs_cn *pcn_src" "puffs_cookie_t targ_dir" -.Fa "puffs_cookie_t targ" "const struct puffs_cn *pcn_targ" -.Fc -.Ft int -.Fo puffs_node_mkdir -.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" -.Fa "struct puffs_newinfo *pni" "const struct puffs_cn *pcn" -.Fa "const struct vattr *vap" -.Fc -.Ft int -.Fo puffs_node_rmdir -.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" "puffs_cookie_t targ" -.Fa "const struct puffs_cn *pcn" -.Fc -.Ft int -.Fo puffs_node_readdir -.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" "struct dirent *dent" -.Fa "off_t *readoff" "size_t *reslen" "const struct puffs_cred *pcr" -.Fa "int *eofflag" "off_t *cookies" "size_t *ncookies" -.Fc -.Ft int -.Fo puffs_node_symlink -.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" -.Fa "struct puffs_newinfo *pni" -.Fa "const struct puffs_cn *pcn_src" "const struct vattr *vap" -.Fa "const char *link_target" -.Fc -.Ft int -.Fo puffs_node_readlink -.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" -.Fa "const struct puffs_cred *pcr" "char *link" "size_t *linklen" -.Fc -.Ft int -.Fo puffs_node_read -.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" -.Fc -.Ft int -.Fo puffs_node_write -.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" -.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" "int 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_inactive -.Fa "struct puffs_usermount *pu" "puffs_cookie_t opc" -.Fc -.Ft void -.Fn puffs_setback "struct puffs_cc *pcc" "int op" -.Ft void -.Fn puffs_newinfo_setcookie "struct puffs_newinfo *pni" "puffs_cookie_t cookie" -.Ft void -.Fn puffs_newinfo_setvtype "struct puffs_newinfo *pni" "enum vtype vtype" -.Ft void -.Fn puffs_newinfo_setsize "struct puffs_newinfo *pni" "voff_t size" -.Sh DESCRIPTION -The operations -.Nm puffs -requires to function can be divided into two categories: file system -callbacks and node callbacks. -The former affect the entire file system while the latter are targeted -at a file or a directory and a file. -They are roughly equivalent to the vfs and vnode operations in the -kernel. -.Pp -All callbacks can be prototyped with the file system name and operation -name using the macro -.Fn PUFFSOP_PROTOS fsname . -.Ss File system callbacks (puffs_fs) -.Bl -tag -width xxxx -.It Fn puffs_fs_statvfs "pu" "sbp" -The following fields of the argument -.Fa sbp -need to be filled: -.Bd -literal - * unsigned long f_bsize; file system block size - * unsigned long f_frsize; fundamental file system block size - * fsblkcnt_t f_blocks; number of blocks in file system, - * (in units of f_frsize) - * - * fsblkcnt_t f_bfree; free blocks avail in file system - * fsblkcnt_t f_bavail; free blocks avail to non-root - * fsblkcnt_t f_bresvd; blocks reserved for root - - * fsfilcnt_t f_files; total file nodes in file system - * fsfilcnt_t f_ffree; free file nodes in file system - * fsfilcnt_t f_favail; free file nodes avail to non-root - * fsfilcnt_t f_fresvd; file nodes reserved for root - -.Ed -.It Fn puffs_fs_sync "pu" "waitfor" "pcr" -All the dirty buffers that have been cached at the file server -level including metadata should be committed to stable storage. -The -.Fa waitfor -parameter affects the operation. -Possible values are: -.Bl -tag -width XMNT_NOWAITX -.It Dv MNT_WAIT -Wait for all I/O for complete until returning. -.It Dv MNT_NOWAIT -Initiate I/O, but do not wait for completion. -.It Dv MNT_LAZY -Synchorize data not synchoronized by the file system syncer, -i.e. data not written when -.Fn puffs_node_fsync -is called with -.Dv FSYNC_LAZY . -.El -.Pp -The credentials for the initiator of the sync operation are present in -.Fa pcr -and will usually be either file system or kernel credentials, but might -also be user credentials. -However, most of the time it is advisable to sync regardless of the -credentials of the caller. -.It Fn puffs_fs_fhtonode "pu" "fid" "fidsize" "pni" -Translates a file handle -.Fa fid -to a node. -The parameter -.Fa fidsize -indicates how large the file handle is. -In case the file system's handles are static length, this parameter can -be ignored as the kernel guarantees all file handles passed to the file -server are of correct length. -For dynamic length handles the field should be examined and -.Er EINVAL -returned in case the file handle length is not correct. -.Pp -This function provides essentially the same information to the kernel as -.Fn puffs_node_lookup . -The information is necessary for creating a new vnode corresponding to -the file handle. -.It Fn puffs_fs_nodetofh "pu" "cookie" "fid" "fidsize" -Create a file handle from the node described by -.Fa cookie . -The file handle should contain enough information to reliably identify -the node even after reboots and the pathname/inode being replaced by -another file. -If this is not possible, it is up to the author of the file system to -act responsibly and decide if the file system can support file handles -at all. -.Pp -For file systems which want dynamic length file handles, this function -must check if the file handle space indicated by -.Fa fidsize -is large enough to accommodate the file handle for the node. -If not, it must fill in the correct size and return -.Er E2BIG . -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_unmount "pu" "flags" -Unmount the file system. -The kernel has assumedly flushed all cached data when this callback -is executed. -If the file system cannot currently be safely be unmounted, for whatever -reason, the kernel will honor an error value and not forcibly unmount. -However, if the flag -.Dv MNT_FORCE -is not honored by the file server, the kernel will forcibly unmount -the file system. -.El -.Ss Node callbacks -These operations operate in the level of individual files. -The file cookie is always provided as the second argument -.Fa opc . -If the operation is for a file, it will be the cookie of the file. -The case the operation involves a directory (such as -.Dq create file in directory ) , -the cookie will be for the directory. -Some operations take additional cookies to describe the rest of -the operands. -The return value 0 signals success, else an appropriate errno value -should be returned. -Please note that neither this list nor the descriptions are complete. -.Bl -tag -width xxxx -.It Fn puffs_node_lookup "pu" "opc" "pni" "pcn" -This function is used to locate nodes, or in other words translate -pathname components to file system data structures. -The implementation should match the name in -.Fa pcn -against the existing entries in the directory provided by the cookie -.Fa opc . -If found, the cookie for the located node should be set in -.Fa pni -using -.Fn puffs_newinfo_setcookie . -Additionally, the vnode type and size (latter applicable to regular files only) -should be set using -.Fn puffs_newinfo_setvtype -and -.Fn puffs_newinfo_setsize , -respectively. -.Pp -The type of operation is found from -.Va pcn-\*[Gt]pcn_nameiop : -.Bl -tag -width XNAMEI_LOOKUPX -.It Dv NAMEI_LOOKUP -Normal lookup operation. -.It Dv NAMEI_CREATE -Lookup to create a node. -.It Dv NAMEI_DELETE -Lookup for node deletion. -.It Dv NAMEI_RENAME -Lookup for the target of a rename operation (source will be looked -up using -.Dv NAMEI_DELETE ) . -.El -.Pp -The final component from a pathname lookup usually requires special -treatment. -It can be identified by looking at the -.Va pcn-\*[Gt]pcn_flags -fields for the flag -.Dv PUFFSLOOKUP_ISLASTCN . -For example, in most cases the lookup operation will want to check if -a delete, rename or create operation has enough credentials to perform -the operation. -.Pp -The return value 0 signals a found node and a nonzero value signals -an errno. -As a special case, -.Er ENOENT -signals "success" for cases where the lookup operation is -.Dv NAMEI_CREATE -or -.Dv NAMEI_RENAME . -Failure in these cases can be signalled by returning another appropriate -error code, for example -.Er EACCESS . -.Pp -Usually a null-terminated string for the next pathname component is -provided in -.Ar pcn-\*[Gt]pcn_name . -In case the file system is using the option -.Dv PUFFS_KFLAG_LOOKUP_FULLPNBUF , -the remainder of the complete pathname under lookup is found in -the same location. -.Ar pcn-\*[Gt]pcn_namelen -always specifies the length of the next component. -If operating with a full path, the file system is allowed to consume -more than the next component's length in node lookup. -This is done by setting -.Ar pcn-\*[Gt]pcn_consume -to indicate the amount of -.Em extra -characters in addition to -.Ar pcn-\*[Gt]pcn_namelen -processed. -.It Fn puffs_node_create "pu" "opc" "pni" "pcn" "va" -.It Fn puffs_node_mkdir "pu" "opc" "pni" "pcn" "va" -.It Fn puffs_node_mknod "pu" "opc" "pni" "pcn" "va" -A file node is created in the directory denoted by the cookie -.Fa opc -by any of the above callbacks. -The name of the new file can be found from -.Fa pcn -and the attributes are specified by -.Fa va -and the cookie for the newly created node should be set in -.Fa pni . -The only difference between these three is that they create a regular -file, directory and device special file, respectively. -.Pp -In case of mknod, the device identifier can be found in -.Fa va-\*[Gt]va_rdev . -.It Fn puffs_node_open "pu" "opc" "mode" "pcr" -Open the node denoted by the cookie -.Fa opc . -The parameter -.Fa mode -specifies the flags that -.Xr open 2 -was called with, e.g. -.Dv O_APPEND -and -.Dv O_NONBLOCK . -.It Fn puffs_node_close "pu" "opc" "flags" "pcr" -Close a node. -The parameter -.Fa flags -parameter describes the flags that the file was opened with. -.It Fn puffs_node_access "pu" "opc" "mode" "pcr" -Check if the credentials of -.Fa pcr -have the right to perform the operation specified by -.Fa mode -onto the node -.Fa opc . -The argument -.Fa mode -can specify read, write or execute by -.Dv PUFFS_VREAD , -.Dv PUFFS_VWRITE , -and -.Dv PUFFS_VEXEC , -respectively. -.It Fn puffs_node_getattr "pu" "opc" "va" "pcr" -The attributes of the node specified by -.Fa opc -must be copied to the space pointed by -.Fa va . -.It Fn puffs_node_setattr "pu" "opc" "va" "pcr" -The attributes for the node specified by -.Fa opc -must be set to those contained in -.Fa va . -Only fields of -.Fa va -which contain a value different from -.Dv PUFFS_VNOVAL -(typecast to the field's type!) contain a valid value. -.It Fn puffs_node_poll "pu" "opc" "events" -Poll for events on node -.Ar opc . -If -.Xr poll 2 -events specified in -.Ar events -are available, the function should set the bitmask to match available -events and return immediately. -Otherwise, the function should block (yield) until some events in -.Ar events -become available and only then set the -.Ar events -bitmask and return. -.Pp -In case this function returns an error, -.Dv POLLERR -(or its -.Xr select 2 -equivalent) will be delivered to the calling process. -.Pp -.Em NOTE! -The system call interface for -.Fn poll -contains a timeout parameter. -At this level, however, the timeout is not supplied. -In case input does not arrive, the file system should periodically -unblock and return 0 new events to avoid hanging forever. -This will hopefully be better supported by libpuffs in the future. -.It Fn puffs_node_mmap "pu" "opc" "flags" "pcr" -Called when a regular file is being memory mapped by -.Xr mmap 2 . -.Fa flags -is currently always 0. -.It Fn puffs_node_fsync "pu" "opc" "pcr" "flags" "offlo" "offhi" -Sychronize a node's contents onto stable storage. -This is necessary only if the file server caches some information -before committing it. -The parameter -.Fa flags -specifies the minimum level of sychronization required (XXX: they are -not yet available). -The parameters -.Fa offlo -and -.Fa offhi -specify the data offsets requiring to be synced. -A high offset of 0 means sync from -.Fa offlo -to the end of the file. -.It Fn puffs_node_seek "pu" "opc" "oldoff" "newoff" "pcr" -Test if the node -.Ar opc -is seekable to the location -.Ar newoff . -The argument -.Ar oldoff -specifies the offset we are starting the seek from. -Most file systems dealing only with regular will choose to not -implement this. -However, it is useful for example in cases where files are -unseekable streams. -.It Fn puffs_node_remove "pu" "opc" "targ" "pcn" -.It Fn puffs_node_rmdir "pu" "opc" "targ" "pcn" -Remove the node -.Fa targ -from the directory indicated by -.Fa opc . -The directory entry name to be removed is provided by -.Fa pcn . -The rmdir operation removes only directories, while the remove -operation removes all other types except directories. -.Pp -It is paramount to note that the file system may not remove the -node data structures at this point, only the directory entry and prevent -lookups from finding the node again. -This is to retain the -.Ux -open file semantics. -The data may be removed only when -.Fn puffs_node_reclaim -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 -.Fa targ -into the directory -.Fa opc . -The argument -.Fa pcn -provides the directory entry name for the new link. -.It Fn puffs_node_rename "pu" "src_dir" "src" "pcn_src" "targ_dir" "targ" "pcn_targ" -Rename the node -.Fa src -with the name specified by -.Fa pcn_src -from the directory -.Fa src_dir . -The target directory and target name are given by -.Fa targ_dir -and -.Fa pcn_targ , -respectively. -.Em If -the target node already exists, it is specified by -.Fa targ -and must be replaced atomically. -Otherwise -.Fa targ -is gives as -.Dv NULL . -.Pp -It is legal to replace a directory node by another directory node with -the means of rename if the target directory is empty, otherwise -.Er ENOTEMPTY -should be returned. -All other types can replace all other types. -In case a rename between incompatible types is attempted, the errors -.Er ENOTDIR -or -.Er EISDIR -should be returned, depending on the target type. -.It Fn puffs_node_readdir "pu" "opc" "dent" "readoff" "reslen" "pcr" "eofflag" "cookies" "ncookies" -To read directory entries, -.Fn puffs_node_readdir -is called. -It should store directories as -.Va struct dirent -in the space pointed to by -.Fa dent . -The amount of space available is given by -.Fa reslen -and before returning it should be set to the amount of space -.Em remaining -in the buffer. -The argument -.Fa offset -is used to specify the offset to the directory. -Its interpretation is up to the file system and it should be set to -signal the continuation point when there is no more room for the next -entry in -.Fa dent . -It is most performant to return the maximal amount of directory -entries each call. -It is easiest to generate directory entries by using -.Fn puffs_nextdent , -which also automatically advances the necessary pointers. -.Pp -In case end-of-directory is reached, -.Fa eofflag -should be set to one. -Note that even a new call to readdir may start where -.Fa readoff -points to end-of-directory. -.Pp -If the file system supports file handles, the arguments -.Fa cookies -and -.Fa ncookies -must be filled out. -.Fa cookies -is a vector for offsets corresponding to read offsets. -One cookie should be filled out for each directory entry. -The value of the cookie should equal the offset of the -.Em next -directory entry, i.e. which offset should be passed to readdir for -the first entry read to be the entry following the current one. -.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. -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 -.Fn PUFFS_STORE_DCOOKIE cookies ncookies offset -can be used. -This properly checks against -.Fa cookies -being -.Dv NULL . -Note that -.Fa ncookies -must be initialized to zero before the first call to -.Fn PUFFS_STORE_DCOOKIE . -.It Fn puffs_node_symlink "pu" "opc" "pni" "pcn_src" "va" "link_target" -Create a symbolic link into the directory -.Fa opc -with the name in -.Fa pcn_src -and the initial attributes in -.Fa va . -The argument -.Ar link_target -contains a null-terminated string for the link target. -The created node cookie should be set in -.Fa pni . -.It Fn puffs_node_readlink "pu" "opc" "pcr" "link" "linklen" -Read the target of a symbolic link -.Fa opc . -The result is placed in the buffer pointed to by -.Fa link . -This buffer's length is given in -.Fa linklen -and it must be updated to reflect the real link length. -A terminating nul character should not be put into the buffer and -.Em "must not" -be included in the link length. -.It Fn puffs_node_read "pu" "opc" "buf" "offset" "resid" "pcr" "ioflag" -Read the contents of a file -.Fa opc . -It will gather the data from -.Fa offset -in the file and read the number -.Fa resid -octets. -The buffer is guaranteed to have this much space. -The amount of data requested by -.Fa resid -should be read, except in the case of eof-of-file or an error. -The parameter -.Fa resid -should be set to indicate the amount of request NOT completed. -In the normal case this should be 0. -.It Fn puffs_node_write "pu" "opc" "buf" "offset" "resid" "pcr" "ioflag" -.Fn puffs_node_write -Write data to a file -.Fa opc -at -.Fa offset -and extend the file if necessary. -The number of octets written is indicated by -.Fa resid ; -everything must be written or an error will be generated. -The parameter must be set to indicate the amount of data NOT written. -In case the flag -.Dv PUFFS_IO_APPEND -is specified, the data should be appended to the end of the file. -.It Fn puffs_node_print "pu" "opc" -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_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 -is called. -.It Fn puffs_setback "pcc" "op" -Issue a "setback" operation which will be handled when the request response -is returned to the kernel. -Currently this can be only called from mmap, open, remove and rmdir. -The valid parameters for -.Ar op -are -.Dv PUFFS_SETBACK_INACT_N1 -and -.Dv PUFFS_SETBACK_INACT_N2 . -These signal that a file system mounted with -.Dv PUFFS_KFLAG_IAONDEMAND -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. -.It Fn puffs_newinfo_setcookie pni cookie -Set cookie for node provided by this method to -.Ar cookie . -.It Fn puffs_newinfo_setvtype pni vtype -Set the type of the newly located node to -.Ar vtype . -This call is valid only for -.Fn lookup -and -.Fn fhtonode . -.It Fn puffs_newinfo_setsize pni size -Set the size of the newly located node to -.Ar size . -If left unset, the value defaults to 0. -This call is valid only for -.Fn lookup -and -.Fn fhtovp . -.El -.Sh SEE ALSO -.Xr puffs 3 -.\".Xr vfsops 9 , -.\".Xr vnodeops 9 diff --git a/lib/libpuffs/puffs_path.3 b/lib/libpuffs/puffs_path.3 deleted file mode 100644 index 7b0e025b11..0000000000 --- a/lib/libpuffs/puffs_path.3 +++ /dev/null @@ -1,125 +0,0 @@ -.\" $NetBSD: puffs_path.3,v 1.4 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 February 5, 2012 -.Dt PUFFS_PATH 3 -.Os -.Sh NAME -.Nm puffs_path -.Nd puffs pathbuilding routines -.Sh LIBRARY -.Lb libpuffs -.Sh SYNOPSIS -.In puffs.h -.Ft int -.Fo pu_pathbuild_fn -.Fa "struct puffs_usermount *pu" "const struct puffs_pathobj *po_dir" -.Fa "const struct puffs_pathobj *po_comp" "size_t offset" -.Fa "struct puffs_pathobj *po_new" -.Fc -.Ft int -.Fo pu_pathtransform_fn -.Fa "struct puffs_usermount *pu" "const struct puffs_pathobj *po_base" -.Fa "const struct puffs_cn *pcn" "struct puffs_pathobj *po_new" -.Fc -.Ft int -.Fo pu_pathcmp_fn -.Fa "struct puffs_usermount *pu" "struct puffs_pathobj *po1" -.Fa "struct puffs_pathobj *po2" "size_t checklen" "int checkprefix" -.Fc -.Ft void -.Fn pu_pathfree_fn "struct puffs_usermount *pu" "struct puffs_pathobj *po" -.Ft int -.Fo pu_namemod_fn -.Fa "struct puffs_usermount *pu" "struct puffs_pathobj *po_dir" -.Fa "struct puffs_cn *pcn" -.Fc -.Ft struct puffs_pathobj * -.Fn puffs_getrootpathobj "struct puffs_usermount *pu" -.Sh DESCRIPTION -The puffs library has the ability to provide full pathnames for backends -which require them. -Normal file systems should be constructed without the file system -node tied to a file name and should not used routines described herein. -An example of a file system where the backend requires filenames is -.Xr mount_psshfs 8 . -.Pp -The features described here are enabled by passing -.Dv PUFFS_FLAG_BUILDPATH -to -.Fn puffs_init . -This facility requires to use puffs nodes to store the contents of the -pathname. -Either the address of the operation cookie must directly be that of the -puffs node, or -.Fn puffs_set_cmap -must be used to set a mapping function from the cookie to the puffs -node associated with the cookie. -Finally, the root node for the file system must be set using -.Fn puffs_setroot -and the root path object retrieved using -.Fn puffs_getrootpathobj -and initialized. -.Pp -There are two different places a filename can be retrieved from. -It is available for each puffs node after the node has been registered -with the framework, i.e. -.Em after -the routine creating the node returns. -In other words, there is a window between the node is created and -when the pathname is available and multithreaded file systems must -take this into account. -The second place where a pathname is available is from the componentname -.Vt struct puffs_pcn -in operations which are passed one. -These can be retrieved using the convenience macros -.Fn PNPATH -and -.Fn PCNPATH -for node and componentname, respectively. -The type of object they return is -.Vt void * . -.Pp -By default the framework manages "regular" filenames, which consist -of directory names separated by "/" and a final component. -If the file system wishes to use pathnames of this format, all it -has to do it enable the feature. -Everything else, including bookkeeping for node and directory renames, -is done by the library. -The callback routines described next provide the ability to build -non-standard pathnames. -A -.Fn pu_foo_fn -callback is set using the -.Fn puffs_set_foo -routine. -.Pp -This manual page is still unfinished. -Please take a number and wait in line. -.Sh SEE ALSO -.Xr puffs 3 , -.Xr puffs_node 3 , -.Xr mount_psshfs 8 -.\".Xr mount_sysctlfs 8 diff --git a/lib/libpuffs/puffs_priv.h b/lib/libpuffs/puffs_priv.h deleted file mode 100644 index 72b6673045..0000000000 --- a/lib/libpuffs/puffs_priv.h +++ /dev/null @@ -1,258 +0,0 @@ -/* $NetBSD: puffs_priv.h,v 1.44 2011/06/20 09:11:17 mrg Exp $ */ - -/* - * Copyright (c) 2006, 2007, 2008 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. - */ - -#ifndef _PUFFS_PRIVATE_H_ -#define _PUFFS_PRIVATE_H_ - -#include -#include - -#include -#include - -#include "puffs.h" - -extern pthread_mutex_t pu_lock; -#define PU_LOCK() pthread_mutex_lock(&pu_lock) -#define PU_UNLOCK() pthread_mutex_unlock(&pu_lock) - -#define PU_CMAP(pu, c) (pu->pu_cmap ? pu->pu_cmap(pu,c) : (struct puffs_node*)c) - -struct puffs_framectrl { - puffs_framev_readframe_fn rfb; - puffs_framev_writeframe_fn wfb; - puffs_framev_cmpframe_fn cmpfb; - puffs_framev_gotframe_fn gotfb; - puffs_framev_fdnotify_fn fdnotfn; -}; - -struct puffs_fctrl_io { - struct puffs_framectrl *fctrl; - - int io_fd; - int stat; - - int rwait; - int wwait; - - struct puffs_framebuf *cur_in; - - TAILQ_HEAD(, puffs_framebuf) snd_qing; /* queueing to be sent */ - TAILQ_HEAD(, puffs_framebuf) res_qing; /* q'ing for rescue */ - LIST_HEAD(, puffs_fbevent) ev_qing; /* q'ing for events */ - - LIST_ENTRY(puffs_fctrl_io) fio_entries; -}; -#define FIO_WR 0x01 -#define FIO_WRGONE 0x02 -#define FIO_RDGONE 0x04 -#define FIO_DEAD 0x08 -#define FIO_ENABLE_R 0x10 -#define FIO_ENABLE_W 0x20 - -#define FIO_EN_WRITE(fio) \ - (!(fio->stat & FIO_WR) \ - && ((!TAILQ_EMPTY(&fio->snd_qing) \ - && (fio->stat & FIO_ENABLE_W)) \ - || fio->wwait)) - -#define FIO_RM_WRITE(fio) \ - ((fio->stat & FIO_WR) \ - && (((TAILQ_EMPTY(&fio->snd_qing) \ - || (fio->stat & FIO_ENABLE_W) == 0)) \ - && (fio->wwait == 0))) - - -/* - * usermount: describes one file system instance - */ -struct puffs_usermount { - struct puffs_ops pu_ops; - - int pu_fd; - size_t pu_maxreqlen; - - uint32_t pu_flags; - int pu_cc_stackshift; - - ucontext_t pu_mainctx; -#define PUFFS_CCMAXSTORE 32 - int pu_cc_nstored; - - int pu_kq; - int pu_state; -#define PU_STATEMASK 0x00ff -#define PU_INLOOP 0x0100 -#define PU_ASYNCFD 0x0200 -#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))) - int pu_dpipe[2]; - - struct puffs_node *pu_pn_root; - - LIST_HEAD(, puffs_node) pu_pnodelst; - - LIST_HEAD(, puffs_cc) pu_ccmagazin; - TAILQ_HEAD(, puffs_cc) pu_lazyctx; - TAILQ_HEAD(, puffs_cc) pu_sched; - - pu_cmap_fn pu_cmap; - - pu_pathbuild_fn pu_pathbuild; - pu_pathtransform_fn pu_pathtransform; - pu_pathcmp_fn pu_pathcmp; - pu_pathfree_fn pu_pathfree; - pu_namemod_fn pu_namemod; - - pu_errnotify_fn pu_errnotify; - - pu_prepost_fn pu_oppre; - pu_prepost_fn pu_oppost; - - struct puffs_framectrl pu_framectrl[2]; -#define PU_FRAMECTRL_FS 0 -#define PU_FRAMECTRL_USER 1 - LIST_HEAD(, puffs_fctrl_io) pu_ios; - LIST_HEAD(, puffs_fctrl_io) pu_ios_rmlist; - struct kevent *pu_evs; - size_t pu_nevs; - - puffs_ml_loop_fn pu_ml_lfn; - struct timespec pu_ml_timeout; - struct timespec *pu_ml_timep; - - struct puffs_kargs *pu_kargp; - - uint64_t pu_nextreq; - void *pu_privdata; -}; - -/* call context */ - -struct puffs_cc; -typedef void (*puffs_ccfunc)(struct puffs_cc *); - -struct puffs_cc { - struct puffs_usermount *pcc_pu; - struct puffs_framebuf *pcc_pb; - - /* real cc */ - union { - struct { - ucontext_t uc; /* "continue" */ - ucontext_t uc_ret; /* "yield" */ - } real; - struct { - puffs_ccfunc func; - void *farg; - } fake; - } pcc_u; - - pid_t pcc_pid; - lwpid_t pcc_lid; - - int pcc_flags; - - TAILQ_ENTRY(puffs_cc) pcc_schedent; - LIST_ENTRY(puffs_cc) pcc_rope; -}; -#define pcc_uc pcc_u.real.uc -#define pcc_uc_ret pcc_u.real.uc_ret -#define pcc_func pcc_u.fake.func -#define pcc_farg pcc_u.fake.farg -#define PCC_DONE 0x01 -#define PCC_BORROWED 0x02 -#define PCC_HASCALLER 0x04 -#define PCC_MLCONT 0x08 - -struct puffs_newinfo { - void **pni_cookie; - enum vtype *pni_vtype; - voff_t *pni_size; -}; - -#define PUFFS_MAKEKCRED(to, from) \ - /*LINTED: tnilxnaht, the cast is ok */ \ - const struct puffs_kcred *to = (const void *)from -#define PUFFS_MAKECRED(to, from) \ - /*LINTED: tnilxnaht, the cast is ok */ \ - const struct puffs_cred *to = (const void *)from -#define PUFFS_KCREDTOCRED(to, from) \ - /*LINTED: tnilxnaht, the cast is ok */ \ - to = (void *)from - -__BEGIN_DECLS - -void puffs__framev_input(struct puffs_usermount *, struct puffs_framectrl *, - struct puffs_fctrl_io *); -int puffs__framev_output(struct puffs_usermount *, struct puffs_framectrl*, - struct puffs_fctrl_io *); -void puffs__framev_exit(struct puffs_usermount *); -void puffs__framev_readclose(struct puffs_usermount *, - struct puffs_fctrl_io *, int); -void puffs__framev_writeclose(struct puffs_usermount *, - struct puffs_fctrl_io *, int); -void puffs__framev_notify(struct puffs_fctrl_io *, int); -void *puffs__framebuf_getdataptr(struct puffs_framebuf *); -int puffs__framev_addfd_ctrl(struct puffs_usermount *, int, int, - struct puffs_framectrl *); -void puffs__framebuf_moveinfo(struct puffs_framebuf *, - struct puffs_framebuf *); - -void puffs__theloop(struct puffs_cc *); -void puffs__ml_dispatch(struct puffs_usermount *, struct puffs_framebuf *); - -int puffs__cc_create(struct puffs_usermount *, puffs_ccfunc, - struct puffs_cc **); -void puffs__cc_cont(struct puffs_cc *); -void puffs__cc_destroy(struct puffs_cc *, int); -void puffs__cc_setcaller(struct puffs_cc *, pid_t, lwpid_t); -void puffs__goto(struct puffs_cc *); -int puffs__cc_savemain(struct puffs_usermount *); -int puffs__cc_restoremain(struct puffs_usermount *); -void puffs__cc_exit(struct puffs_usermount *); - -int puffs__fsframe_read(struct puffs_usermount *, struct puffs_framebuf *, - int, int *); -int puffs__fsframe_write(struct puffs_usermount *, struct puffs_framebuf *, - int, int *); -int puffs__fsframe_cmp(struct puffs_usermount *, struct puffs_framebuf *, - struct puffs_framebuf *, int *); -void puffs__fsframe_gotframe(struct puffs_usermount *, - struct puffs_framebuf *); - -uint64_t puffs__nextreq(struct puffs_usermount *pu); - -__END_DECLS - -#endif /* _PUFFS_PRIVATE_H_ */ diff --git a/lib/libpuffs/puffsdump.h b/lib/libpuffs/puffsdump.h deleted file mode 100644 index 0a8de301cd..0000000000 --- a/lib/libpuffs/puffsdump.h +++ /dev/null @@ -1,68 +0,0 @@ -/* $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 - -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_ */ diff --git a/lib/libpuffs/requests.c b/lib/libpuffs/requests.c deleted file mode 100644 index 19dcd46cea..0000000000 --- a/lib/libpuffs/requests.c +++ /dev/null @@ -1,234 +0,0 @@ -/* $NetBSD: requests.c,v 1.23 2008/01/29 14:54:08 pooka 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 -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include "puffs.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); -} diff --git a/lib/libpuffs/subr.c b/lib/libpuffs/subr.c deleted file mode 100644 index 4e1f4c39a6..0000000000 --- a/lib/libpuffs/subr.c +++ /dev/null @@ -1,326 +0,0 @@ -/* $NetBSD: subr.c,v 1.27 2011/02/17 17:55:36 pooka Exp $ */ - -/* - * Copyright (c) 2006 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 -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "puffs.h" -#include "puffs_priv.h" - -#ifndef MAXNAMLEN -#define MAXNAMLEN 255 -#endif - -int -puffs_gendotdent(struct dirent **dent, ino_t id, int dotdot, size_t *reslen) -{ - const char *name; - - assert(dotdot == 0 || dotdot == 1); - name = dotdot == 0 ? "." : ".."; - - return puffs_nextdent(dent, name, id, DT_DIR, reslen); -} - -int -puffs_nextdent(struct dirent **dent, const char *name, ino_t id, uint8_t dtype, - size_t *reslen) -{ - struct dirent *d = *dent; - size_t reclen; - - /* check if we have enough room for our dent-aligned dirent */ - reclen = _DIRENT_RECLEN(strlen(name)); - if (reclen > *reslen) - return 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'; - - *reslen -= reclen; - *dent = _DIRENT_NEXT(d); - - return 1; -} - -/*ARGSUSED*/ -int -puffs_fsnop_unmount(struct puffs_usermount *dontuse1, int dontuse2) -{ - - /* would you like to see puffs rule again, my friend? */ - return 0; -} - -/*ARGSUSED*/ -int -puffs_fsnop_sync(struct puffs_usermount *dontuse1, int dontuse2) -{ - - return 0; -} - -/*ARGSUSED*/ -int -puffs_fsnop_statvfs(struct puffs_usermount *dontuse1, struct statvfs *sbp) -{ - - memset(sbp, 0, sizeof(*sbp)); - - /* XXXDF - * sbp->f_iosize - */ - sbp->f_bsize = sbp->f_frsize = DEV_BSIZE; - - /* XXXDF - * sbp->f_bresvd - * sbp->f_fresvd - */ - sbp->f_bfree=sbp->f_bavail=sbp->f_blocks = (fsblkcnt_t)0; - sbp->f_ffree=sbp->f_favail=sbp->f_files = (fsfilcnt_t)0; - - sbp->f_namemax = MAXNAMLEN; - - return 0; -} - -/*ARGSUSED3*/ -int -puffs_genfs_node_getattr(struct puffs_usermount *pu, puffs_cookie_t opc, - struct vattr *va, const struct puffs_cred *pcr) -{ - struct puffs_node *pn = PU_CMAP(pu, opc); - - memcpy(va, &pn->pn_va, sizeof(struct vattr)); - return 0; -} - -/* - * Just put the node, don't do anything else. Don't use this if - * your fs needs more cleanup. - */ -/*ARGSUSED2*/ -int -puffs_genfs_node_reclaim(struct puffs_usermount *pu, puffs_cookie_t opc) -{ - - puffs_pn_put(PU_CMAP(pu, opc)); - - return 0; -} - -/* - * Just a wrapper to make calling the above nicer without having to pass - * NULLs from application code - */ -void -puffs_zerostatvfs(struct statvfs *sbp) -{ - - puffs_fsnop_statvfs(NULL, sbp); -} - -/* - * Set vattr values for those applicable (i.e. not PUFFS_VNOVAL). - */ -void -puffs_setvattr(struct vattr *vap, const struct vattr *sva) -{ - -#define SETIFVAL(a, t) if (sva->a != (t)PUFFS_VNOVAL) vap->a = sva->a - if (sva->va_type != VNON) - vap->va_type = sva->va_type; - SETIFVAL(va_mode, mode_t); - SETIFVAL(va_nlink, nlink_t); - SETIFVAL(va_uid, uid_t); - SETIFVAL(va_gid, gid_t); - SETIFVAL(va_fsid, dev_t); - SETIFVAL(va_size, u_quad_t); - SETIFVAL(va_fileid, ino_t); - SETIFVAL(va_blocksize, long); - SETIFVAL(va_atime.tv_sec, time_t); - SETIFVAL(va_ctime.tv_sec, time_t); - SETIFVAL(va_mtime.tv_sec, time_t); - SETIFVAL(va_atime.tv_nsec, long); - SETIFVAL(va_ctime.tv_nsec, long); - SETIFVAL(va_mtime.tv_nsec, long); - SETIFVAL(va_gen, u_long); - SETIFVAL(va_flags, u_long); - SETIFVAL(va_rmajor, int); - SETIFVAL(va_rminor, int); - SETIFVAL(va_bytes, u_quad_t); -#undef SETIFVAL - /* ignore va->va_vaflags */ -} - -void -puffs_vattr_null(struct vattr *vap) -{ - - vap->va_type = VNON; - - /* - * Assign individually so that it is safe even if size and - * sign of each member are varied. - */ - vap->va_mode = (mode_t)PUFFS_VNOVAL; - vap->va_nlink = (nlink_t)PUFFS_VNOVAL; - vap->va_uid = (uid_t)PUFFS_VNOVAL; - vap->va_gid = (gid_t)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); - vap->va_atime.tv_sec = - vap->va_mtime.tv_sec = - vap->va_ctime.tv_sec = PUFFS_VNOVAL; - vap->va_atime.tv_nsec = - vap->va_mtime.tv_nsec = - vap->va_ctime.tv_nsec = PUFFS_VNOVAL; - vap->va_rmajor = PUFFS_VNOVAL; - vap->va_rminor = PUFFS_VNOVAL; - vap->va_bytes = (u_quad_t)PUFFS_VNOVAL; - - vap->va_flags = 0; - vap->va_gen = 0; - vap->va_vaflags = 0; -} - -static int vdmap[] = { - DT_UNKNOWN, /* VNON */ - DT_REG, /* VREG */ - DT_DIR, /* VDIR */ - DT_BLK, /* VBLK */ - DT_CHR, /* VCHR */ - DT_LNK, /* VLNK */ - DT_SOCK, /* VSUCK*/ - DT_FIFO, /* VFIFO*/ - DT_UNKNOWN /* VBAD */ -}; -/* XXX: DT_WHT ? */ -int -puffs_vtype2dt(enum vtype vt) -{ - - if ((int)vt >= VNON && vt < (sizeof(vdmap)/sizeof(vdmap[0]))) - return vdmap[vt]; - - return DT_UNKNOWN; -} - -enum vtype -puffs_mode2vt(mode_t mode) -{ - - switch (mode & S_IFMT) { - case S_IFIFO: - return VFIFO; - case S_IFCHR: - return VCHR; - case S_IFDIR: - return VDIR; - case S_IFBLK: - return VBLK; - case S_IFREG: - return VREG; - case S_IFLNK: - return VLNK; - case S_IFSOCK: - return VSOCK; - default: - return VBAD; /* XXX: not really true, but ... */ - } -} - -void -puffs_stat2vattr(struct vattr *va, const struct stat *sb) -{ - - memset(va, 0, sizeof(struct vattr)); - va->va_type = puffs_mode2vt(sb->st_mode); - va->va_mode = sb->st_mode; - va->va_nlink = sb->st_nlink; - va->va_uid = sb->st_uid; - va->va_gid = sb->st_gid; - 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_gen = sb->st_gen; - va->va_flags = sb->st_flags; - va->va_bytes = sb->st_blocks << DEV_BSHIFT; - va->va_filerev = 0; - va->va_vaflags = 0; -} - -mode_t -puffs_addvtype2mode(mode_t mode, enum vtype type) -{ - - switch (type) { - case VCHR: - mode |= S_IFCHR; - break; - 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; - } - - return mode; -} diff --git a/lib/libpuffs/suspend.c b/lib/libpuffs/suspend.c deleted file mode 100644 index 936a580182..0000000000 --- a/lib/libpuffs/suspend.c +++ /dev/null @@ -1,45 +0,0 @@ -/* $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. - */ - -/* - * File system suspension - */ - -#include - -#include - -#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; -} diff --git a/lib/librefuse/Makefile b/lib/librefuse/Makefile deleted file mode 100644 index 8b7a3669e0..0000000000 --- a/lib/librefuse/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -# $NetBSD: Makefile,v 1.8 2007/11/05 13:41:52 pooka Exp $ - -LIB= refuse - -SRCS= refuse.c refuse_opt.c -MAN= refuse.3 -WARNS= 2 -INCS= fuse.h fuse_opt.h - -MLINKS= refuse.3 fuse_main.3 \ - refuse.3 fuse_opt_add_arg.3 \ - refuse.3 fuse_opt_parse.3 \ - refuse.3 fuse_setup.3 \ - refuse.3 fuse_teardown.3 \ - refuse.3 puffs_fuse_node_create.3 \ - refuse.3 puffs_fuse_node_getattr.3 \ - refuse.3 puffs_fuse_node_link.3 \ - refuse.3 puffs_fuse_node_mkdir.3 \ - refuse.3 puffs_fuse_node_mknod.3 \ - refuse.3 puffs_fuse_node_open.3 \ - refuse.3 puffs_fuse_node_read.3 \ - refuse.3 puffs_fuse_node_readdir.3 \ - refuse.3 puffs_fuse_node_readlink.3 \ - refuse.3 puffs_fuse_node_rename.3 \ - refuse.3 puffs_fuse_node_rmdir.3 \ - refuse.3 puffs_fuse_node_symlink.3 \ - refuse.3 puffs_fuse_node_write.3 - -.ifdef DEBUG -CFLAGS+= -g -DFUSE_OPT_DEBUG -.endif - -.include diff --git a/lib/librefuse/TODO b/lib/librefuse/TODO deleted file mode 100644 index 918d38b1f1..0000000000 --- a/lib/librefuse/TODO +++ /dev/null @@ -1,25 +0,0 @@ - $NetBSD: TODO,v 1.3 2007/05/03 21:02:54 agc Exp $ - -To Do -===== -address all XXX -implement all fuse_opt -implement proper lookup (pending some libpuffs stuff) -support fuse_mt (i.e. worker threads, but that'll probably be smarter - to do inside of libpuffs) -support fuse_ll (i.e. "raw" vfs/vnode export) -implement all sorts of compat tweaks to appease various file systems -do proper implementations of dirfillers -statfs - some fuse file systems want struct statfs and we only have - statvfs available natively - -Done -==== -statvfs -sync -WARNS=4 -address lint -special directory handling in open() -Finish off manual page -fuse_setup -fuse_teardown diff --git a/lib/librefuse/fuse.h b/lib/librefuse/fuse.h deleted file mode 100644 index 53ce3ef301..0000000000 --- a/lib/librefuse/fuse.h +++ /dev/null @@ -1,193 +0,0 @@ -/* $NetBSD: fuse.h,v 1.21 2008/08/01 15:54:09 dillo Exp $ */ - -/* - * Copyright (c) 2007 Alistair Crooks. 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. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * 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 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 FUSE_H_ -#define FUSE_H_ 20070123 - -/* set the default version to use for the fuse interface */ -/* this value determines the API to be used */ -#ifndef FUSE_USE_VERSION -#define FUSE_USE_VERSION 26 -#endif - -#include - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct fuse; -struct fuse_args; /* XXXsupportme */ - -struct fuse_file_info { - int32_t flags; - uint32_t fh_old; - int32_t writepage; - uint32_t direct_io:1; - uint32_t keep_cache:1; - uint32_t flush:1; - uint32_t padding:29; - uint64_t fh; - uint64_t lock_owner; -}; - -struct fuse_conn_info { - uint32_t proto_major; - uint32_t proto_minor; - uint32_t async_read; - uint32_t max_write; - uint32_t max_readahead; - uint32_t reserved[27]; -}; - -/* equivalent'ish of puffs_cc */ -struct fuse_context { - struct fuse *fuse; - uid_t uid; - gid_t gid; - pid_t pid; - void *private_data; -}; - -/** - * Argument list - */ -struct fuse_args { - int argc; - char **argv; - int allocated; -}; - -/** - * Initializer for 'struct fuse_args' - */ -#define FUSE_ARGS_INIT(argc, argv) { argc, argv, 0 } - -typedef struct puffs_fuse_dirh *fuse_dirh_t; - -typedef int (*fuse_fill_dir_t)(void *, const char *, const struct stat *, off_t); -typedef int (*fuse_dirfil_t)(fuse_dirh_t, const char *, int, ino_t); - -#define FUSE_VERSION 26 -#define FUSE_MAJOR_VERSION 2 -#define FUSE_MINOR_VERSION 6 - -/* - * These operations shadow those in puffs_usermount, and are used - * as a table of callbacks to make when file system requests come - * in. - * - * NOTE: keep same order as fuse - */ -struct fuse_operations { - int (*getattr)(const char *, struct stat *); - int (*readlink)(const char *, char *, size_t); - int (*getdir)(const char *, fuse_dirh_t, fuse_dirfil_t); - int (*mknod)(const char *, mode_t, dev_t); - int (*mkdir)(const char *, mode_t); - int (*unlink)(const char *); - int (*rmdir)(const char *); - int (*symlink)(const char *, const char *); - int (*rename)(const char *, const char *); - int (*link)(const char *, const char *); - int (*chmod)(const char *, mode_t); - int (*chown)(const char *, uid_t, gid_t); - int (*truncate)(const char *, off_t); - int (*utime)(const char *, struct utimbuf *); - int (*open)(const char *, struct fuse_file_info *); - int (*read)(const char *, char *, size_t, off_t, struct fuse_file_info *); - int (*write)(const char *, const char *, size_t, off_t, struct fuse_file_info *); - int (*statfs)(const char *, struct statvfs *); - int (*flush)(const char *, struct fuse_file_info *); - int (*release)(const char *, struct fuse_file_info *); - int (*fsync)(const char *, int, struct fuse_file_info *); - int (*setxattr)(const char *, const char *, const char *, size_t, int); - int (*getxattr)(const char *, const char *, char *, size_t); - int (*listxattr)(const char *, char *, size_t); - int (*removexattr)(const char *, const char *); - int (*opendir)(const char *, struct fuse_file_info *); - int (*readdir)(const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *); - int (*releasedir)(const char *, struct fuse_file_info *); - int (*fsyncdir)(const char *, int, struct fuse_file_info *); - void *(*init)(struct fuse_conn_info *); - void (*destroy)(void *); - int (*access)(const char *, int); - int (*create)(const char *, mode_t, struct fuse_file_info *); - int (*ftruncate)(const char *, off_t, struct fuse_file_info *); - int (*fgetattr)(const char *, struct stat *, struct fuse_file_info *); - int (*lock)(const char *, struct fuse_file_info *, int, struct flock *); - int (*utimens)(const char *, const struct timespec *); - int (*bmap)(const char *, size_t , uint64_t *); -}; - - -struct fuse_chan *fuse_mount(const char *, struct fuse_args *); -struct fuse *fuse_new(struct fuse_chan *, struct fuse_args *, - const struct fuse_operations *, size_t, void *); - -int fuse_main_real(int, char **, const struct fuse_operations *, size_t, void *); -int fuse_loop(struct fuse *); -struct fuse_context *fuse_get_context(void); -void fuse_exit(struct fuse *); -void fuse_destroy(struct fuse *); - -void fuse_unmount(const char *, struct fuse_chan *); - -struct fuse *fuse_setup(int, char **, const struct fuse_operations *, - size_t, char **, int *, int *); -void fuse_teardown(struct fuse *, char *); - -#if FUSE_USE_VERSION == 22 -#define fuse_unmount fuse_unmount_compat22 -#endif - -void fuse_unmount_compat22(const char *); - -#if FUSE_USE_VERSION >= 26 -#define fuse_main(argc, argv, op, arg) \ - fuse_main_real(argc, argv, op, sizeof(*(op)), arg) -#define fuse_setup fuse_setup26 -#else -#define fuse_main(argc, argv, op) \ - fuse_main_real(argc, argv, op, sizeof(*(op)), NULL) -#endif - -struct fuse *fuse_setup26(int, char **, const struct fuse_operations *, - size_t, char **, int *, void *); - -#ifdef __cplusplus -} -#endif - -#include - -#endif diff --git a/lib/librefuse/fuse_opt.h b/lib/librefuse/fuse_opt.h deleted file mode 100644 index efc9c63441..0000000000 --- a/lib/librefuse/fuse_opt.h +++ /dev/null @@ -1,70 +0,0 @@ -/* $NetBSD: fuse_opt.h,v 1.5 2009/04/19 22:25:29 christos Exp $ */ - -/* - * Copyright (c) 2007 Alistair Crooks. 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. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * 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 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 _FUSE_OPT_H_ -#define _FUSE_OPT_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - FUSE_OPT_KEY_OPT = -1, - FUSE_OPT_KEY_NONOPT = -2, - FUSE_OPT_KEY_KEEP = -3, - FUSE_OPT_KEY_DISCARD = -4 -}; - -struct fuse_opt { - const char *templ; - int32_t offset; - int32_t value; -}; - -#define FUSE_OPT_KEY(templ, key) { templ, -1U, key } -#define FUSE_OPT_END { .templ = NULL } - -typedef int (*fuse_opt_proc_t)(void *, const char *, int, struct fuse_args *); - - -int fuse_opt_add_arg(struct fuse_args *, const char *); -struct fuse_args *fuse_opt_deep_copy_args(int, char **); -void fuse_opt_free_args(struct fuse_args *); -int fuse_opt_insert_arg(struct fuse_args *, int, const char *); -int fuse_opt_add_opt(char **, const char *); -int fuse_opt_parse(struct fuse_args *, void *, - const struct fuse_opt *, fuse_opt_proc_t); -int fuse_opt_match(const struct fuse_opt *, const char *); - -#ifdef __cplusplus -} -#endif - -#endif /* _FUSE_OPT_H_ */ diff --git a/lib/librefuse/refuse.3 b/lib/librefuse/refuse.3 deleted file mode 100644 index 1dde502bc6..0000000000 --- a/lib/librefuse/refuse.3 +++ /dev/null @@ -1,243 +0,0 @@ -.\" $NetBSD: refuse.3,v 1.7 2007/11/08 17:08:46 pooka Exp $ -.\" -.\" Copyright (c) 2007 Alistair Crooks. 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. -.\" 3. The name of the author may not be used to endorse or promote -.\" products derived from this software without specific prior written -.\" permission. -.\" -.\" 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 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 February 5, 2012 -.Dt REFUSE 3 -.Os -.Sh NAME -.Nm refuse -.Nd Re-implementation of a file system in userspace system -.Sh LIBRARY -.Lb librefuse -.Sh SYNOPSIS -.In fuse.h -.Ft int -.Fo fuse_main -.Fa "int argc" "char **argv" "const struct fuse_operations *" -.Fc -.Ft int -.Fo fuse_opt_add_arg -.Fa "struct fuse_args *args" "const char *arg" -.Fc -.Ft int -.Fo fuse_opt_parse -.Fa "struct fuse_args *args" "void *userdata" -.Fa "const struct fuse_opt *descriptions" "fuse_opt_proc_t processingfunc" -.Fc -.Ft int -.Fo fuse_teardown -.Fa "struct fuse *fuse" "char *mountpoint" -.Fc -.Ft struct fuse * -.Fo fuse_setup -.Fa "int argc" "char **argv" "const struct fuse_operations *ops" -.Fa "size_t opssize" "char **mountpoint" "int *multithreaded" "int *fd" -.Fc -.Ft int -.Fo puffs_fuse_node_getattr -.Fa "const char *path" "struct stat *attrs" -.Fc -.Ft int -.Fo puffs_fuse_node_readlink -.Fa "const char *path" "char *output" "size_t outlen" -.Fc -.Ft int -.Fo puffs_fuse_node_mknod -.Fa "const char *path" "mode_t permissions" "dev_t devicenumber" -.Fc -.Ft int -.Fo puffs_fuse_node_mkdir -.Fa "const char *path" "mode_t permissions" -.Fc -.\".Ft int -.\".Fo puffs_fuse_unlink -.\".Fa "const char *path" -.\".Fc -.Ft int -.Fo puffs_fuse_node_rmdir -.Fa "const char *path" -.Fc -.Ft int -.Fo puffs_fuse_node_symlink -.Fa "const char *path" "const char *target" -.Fc -.Ft int -.Fo puffs_fuse_node_rename -.Fa "const char *from" "const char *to" -.Fc -.Ft int -.Fo puffs_fuse_node_link -.Fa "const char *from" "const char *to" -.Fc -.\".Ft int -.\".Fo puffs_fuse_node_chmod -.\".Fa "const char *path" "mode_t permissions" -.\".Fc -.\".Ft int -.\".Fo puffs_fuse_node_own -.\".Fa "const char *path" "uid_t owner" "gid_t group" -.\".Fc -.\".Ft int -.\".Fo puffs_fuse_node_truncate -.\".Fa "const char *path" "off_t newsize" -.\".Fc -.\".Ft int -.\".Fo puffs_fuse_node_utime -.\".Fa "const char *path" "struct utimbuf *newtimes" -.\".Fc -.Ft int -.Fo puffs_fuse_node_open -.Fa "const char *path" "struct fuse_file_info *fileinfo" -.Fc -.Ft int -.Fo puffs_fuse_node_read -.Fa "const char *path" "char *buffer" "size_t bufferlen" "off_t startoffset" -.Fa "struct fuse_file_info *fileinfo" -.Fc -.Ft int -.Fo puffs_fuse_node_write -.Fa "const char *path" "char *buffer" "size_t bufferlen" "off_t startoffset" -.Fa "struct fuse_file_info *fileinfo" -.Fc -.\".Ft int -.\".Fo puffs_fuse_fs_statfs -.\".Fa "const char *path" "struct statvfs *vfsinfo" -.\".Fc -.\".Ft int -.\".Fo puffs_fuse_node_flush -.\".Fa "const char *path" "struct fuse_file_info *fileinfo" -.\".Fc -.\".Ft int -.\".Fo puffs_fuse_node_fsync -.\".Fa "const char *path" "int flags" "struct fuse_file_info *fileinfo" -.\".Fc -.\".Ft int -.\".Fo puffs_fuse_node_setxattr -.\".Fa "const char *path" "const char *attrname" "const char *attrvalue" -.\".Fa "size_t attrsize" "int flags" -.\".Fc -.\".Ft int -.\".Fo puffs_fuse_node_getxattr -.\".Fa "const char *path" "const char *attrname" "const char *attrvalue" -.\".Fa "size_t attrvaluesize" -.\".Fc -.\".Ft int -.\".Fo puffs_fuse_node_listxattr -.\".Fa "const char *path" "const char *attrname" -.\".Fa "size_t attrvaluesize" -.\".Fc -.\".Ft int -.\".Fo puffs_fuse_node_removexattr -.\".Fa "const char *path" "const char *attrname" -.\".Fc -.\".Ft int -.\".Fo puffs_fuse_node_opendir -.\".Fa "const char *path" "struct fuse_file_info *fileinfo" -.\".Fc -.Ft int -.Fo puffs_fuse_node_readdir -.Fa "const char *path" "void *data" "fuse_fill_dir_t fillinfo" -.Fa "off_t offset" "struct fuse_file_info *fileinfo" -.Fc -.\".Ft int -.\".Fo puffs_fuse_node_releasedir -.\".Fa "const char *path" "struct fuse_file_info *fileinfo" -.\".Fc -.\".Ft int -.\".Fo puffs_fuse_node_fsyncdir -.\".Fa "const char *path" "int flags" "struct fuse_file_info *fileinfo" -.\".Fc -.\".Ft void * -.\".Fo puffs_fuse_fs_init -.\".Fa "struct fuse_conn_info *connectioninfo" -.\".Fc -.\".Ft void -.\".Fo puffs_fuse_node_destroy -.\".Fa "void *connection" -.\".Fc -.\".Ft int -.\".Fo puffs_fuse_node_access -.\".Fa "const char *path" "int accesstype" -.\".Fc -.Ft int -.Fo puffs_fuse_node_create -.Fa "const char *path" "mode_t permissions" "struct fuse_file_info *fileinfo" -.Fc -.\".Ft int -.\".Fo puffs_fuse_node_ftruncate -.\".Fa "const char *path" "off_t offset" "struct fuse_file_info *fileinfo" -.\".Fc -.\".Ft int -.\".Fo puffs_fuse_node_fgetattr -.\".Fa "const char *path" "struct stat *attrs" "struct fuse_file_info *fileinfo" -.\".Fc -.\".Ft int -.\".Fo puffs_fuse_node_lock -.\".Fa "const char *path" "struct fuse_file_info *fileinfo" -.\".Fa "int locktype" "struct flock *lockinfo" -.\".Fc -.\".Ft int -.\".Fo puffs_fuse_node_utimens -.\".Fa "const char *path" "const struct timespec *newtimes" -.\".Fc -.\".Ft int -.\".Fo puffs_fuse_node_bmap -.\".Fa "const char *path" "size_t mapsize" "uint64_t offset" -.\".Fc -.Sh DESCRIPTION -.Nm -is a reimplementation of the file system in user space subsystem. -Operations are transported from the kernel virtual file system layer -to the concrete implementation behind -.Nm , -where they are processed and results are sent back to the kernel. -.Pp -It uses the framework provided by the -.Xr puffs 3 -subsystem, and, through that, the kernel interface provided by -.Xr puffs 4 . -.Sh SEE ALSO -.Xr puffs 3 , -.Xr puffs 4 -.Rs -.%A Antti Kantee -.%A Alistair Crooks -.%D September 2007 -.%J EuroBSDCon 2007 -.%T ReFUSE: Userspace FUSE Reimplementation Using puffs -.Re -.Sh HISTORY -An unsupported experimental version of -.Nm -first appeared in -.Nx 5.0 . -.Sh AUTHORS -.An Alistair Crooks Aq Mt agc@NetBSD.org -.An Antti Kantee Aq Mt pooka@NetBSD.org -.Sh BUGS -Many, legion, but well-loved. diff --git a/lib/librefuse/refuse.c b/lib/librefuse/refuse.c deleted file mode 100644 index 4e29a3d7ab..0000000000 --- a/lib/librefuse/refuse.c +++ /dev/null @@ -1,1437 +0,0 @@ -/* $NetBSD: refuse.c,v 1.94 2011/07/09 17:16:46 tron Exp $ */ - -/* - * Copyright (c) 2007 Alistair Crooks. All rights reserved. - * 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. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * 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 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 - -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef MULTITHREADED_REFUSE -#include -#endif - -#include "fuse.h" - -typedef uint64_t fuse_ino_t; - -struct fuse_config { - uid_t uid; - gid_t gid; - mode_t umask; - double entry_timeout; - double negative_timeout; - double attr_timeout; - double ac_attr_timeout; - int ac_attr_timeout_set; - int debug; - int hard_remove; - int use_ino; - int readdir_ino; - int set_mode; - int set_uid; - int set_gid; - int direct_io; - int kernel_cache; - int auto_cache; - int intr; - int intr_signal; -}; - -struct fuse_chan { - const char *dir; - struct fuse_args *args; - struct puffs_usermount *pu; - int dead; -}; - -/* this is the private fuse structure */ -struct fuse { - struct fuse_chan *fc; /* fuse channel pointer */ - struct fuse_operations op; /* switch table of operations */ - int compat; /* compat level - - * not used in puffs_fuse */ - struct node **name_table; - size_t name_table_size; - struct node **id_table; - size_t id_table_size; - fuse_ino_t ctr; - unsigned int generation; - unsigned int hidectr; - pthread_mutex_t lock; - pthread_rwlock_t tree_lock; - void *user_data; - struct fuse_config conf; - int intr_installed; -}; - -struct puffs_fuse_dirh { - void *dbuf; - struct dirent *d; - - size_t reslen; - size_t bufsize; -}; - -struct refusenode { - struct fuse_file_info file_info; - struct puffs_fuse_dirh dirh; - int opencount; - int flags; -}; -#define RN_ROOT 0x01 -#define RN_OPEN 0x02 /* XXX: could just use opencount */ - -static int fuse_setattr(struct fuse *, struct puffs_node *, - const char *, const struct vattr *); - -static struct puffs_node * -newrn(struct puffs_usermount *pu) -{ - struct puffs_node *pn; - struct refusenode *rn; - - if ((rn = calloc(1, sizeof(*rn))) == NULL) { - err(EXIT_FAILURE, "newrn"); - } - pn = puffs_pn_new(pu, rn); - - return pn; -} - -static void -nukern(struct puffs_node *pn) -{ - struct refusenode *rn = pn->pn_data; - - free(rn->dirh.dbuf); - free(rn); - puffs_pn_put(pn); -} - -/* XXX - not threadsafe */ -static ino_t fakeino = 3; - -/***************** start of pthread context routines ************************/ - -/* - * Notes on fuse_context: - * we follow fuse's lead and use the pthread specific information to hold - * a reference to the fuse_context structure for this thread. - */ -#ifdef MULTITHREADED_REFUSE -static pthread_mutex_t context_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_key_t context_key; -static unsigned long context_refc; -#endif - -/* return the fuse_context struct related to this thread */ -struct fuse_context * -fuse_get_context(void) -{ -#ifdef MULTITHREADED_REFUSE - struct fuse_context *ctxt; - - if ((ctxt = pthread_getspecific(context_key)) == NULL) { - if ((ctxt = calloc(1, sizeof(struct fuse_context))) == NULL) { - abort(); - } - pthread_setspecific(context_key, ctxt); - } - return ctxt; -#else - static struct fuse_context fcon; - - return &fcon; -#endif -} - -/* used as a callback function */ -#ifdef MULTITHREADED_REFUSE -static void -free_context(void *ctxt) -{ - free(ctxt); -} -#endif - -/* - * Create the pthread key. The reason for the complexity is to - * enable use of multiple fuse instances within a single process. - */ -static int -create_context_key(void) -{ -#ifdef MULTITHREADED_REFUSE - int rv; - - rv = pthread_mutex_lock(&context_mutex); - assert(rv == 0); - - if (context_refc == 0) { - if (pthread_key_create(&context_key, free_context) != 0) { - warnx("create_context_key: pthread_key_create failed"); - pthread_mutex_unlock(&context_mutex); - return 0; - } - } - context_refc += 1; - pthread_mutex_unlock(&context_mutex); - return 1; -#else - return 1; -#endif -} - -static void -delete_context_key(void) -{ -#ifdef MULTITHREADED_REFUSE - pthread_mutex_lock(&context_mutex); - /* If we are the last fuse instances using the key, delete it */ - if (--context_refc == 0) { - free(pthread_getspecific(context_key)); - pthread_key_delete(context_key); - } - pthread_mutex_unlock(&context_mutex); -#endif -} - -/* set the uid and gid of the calling process in the current fuse context */ -static void -set_fuse_context_uid_gid(const struct puffs_cred *cred) -{ - struct fuse_context *fusectx; - uid_t uid; - gid_t gid; - - fusectx = fuse_get_context(); - if (puffs_cred_getuid(cred, &uid) == 0) { - fusectx->uid = uid; - } - if (puffs_cred_getgid(cred, &gid) == 0) { - fusectx->gid = gid; - } -} - -/* set the pid of the calling process in the current fuse context */ -static void -set_fuse_context_pid(struct puffs_usermount *pu) -{ - struct puffs_cc *pcc = puffs_cc_getcc(pu); - struct fuse_context *fusectx; - - fusectx = fuse_get_context(); - puffs_cc_getcaller(pcc, &fusectx->pid, NULL); -} - -/***************** end of pthread context routines ************************/ - -#define DIR_CHUNKSIZE 4096 -static int -fill_dirbuf(struct puffs_fuse_dirh *dh, const char *name, ino_t dino, - uint8_t dtype) -{ - - /* initial? */ - if (dh->bufsize == 0) { - if ((dh->dbuf = calloc(1, DIR_CHUNKSIZE)) == NULL) { - abort(); - } - dh->d = dh->dbuf; - dh->reslen = dh->bufsize = DIR_CHUNKSIZE; - } - - if (puffs_nextdent(&dh->d, name, dino, dtype, &dh->reslen)) { - return 0; - } - - /* try to increase buffer space */ - dh->dbuf = realloc(dh->dbuf, dh->bufsize + DIR_CHUNKSIZE); - if (dh->dbuf == NULL) { - abort(); - } - dh->d = (void *)((uint8_t *)dh->dbuf + (dh->bufsize - dh->reslen)); - dh->reslen += DIR_CHUNKSIZE; - dh->bufsize += DIR_CHUNKSIZE; - - return !puffs_nextdent(&dh->d, name, dino, dtype, &dh->reslen); -} - -/* ARGSUSED3 */ -/* XXX: I have no idea how "off" is supposed to be used */ -static int -puffs_fuse_fill_dir(void *buf, const char *name, - const struct stat *stbuf, off_t off) -{ - struct puffs_fuse_dirh *deh = buf; - ino_t dino; - uint8_t dtype; - - if (stbuf == NULL) { - dtype = DT_UNKNOWN; - dino = fakeino++; - } else { - dtype = puffs_vtype2dt(puffs_mode2vt(stbuf->st_mode)); - dino = stbuf->st_ino; - - /* - * Some FUSE file systems like to always use 0 as the - * inode number. Our readdir() doesn't like to show - * directory entries with inode number 0 ==> workaround. - */ - if (dino == 0) { - dino = fakeino++; - } - } - - return fill_dirbuf(deh, name, dino, dtype); -} - -static int -puffs_fuse_dirfil(fuse_dirh_t h, const char *name, int type, ino_t ino) -{ - ino_t dino; - int dtype; - - if ((dtype = type) == 0) { - dtype = DT_UNKNOWN; - } - - dino = (ino) ? ino : fakeino++; - - return fill_dirbuf(h, name, dino, dtype); -} - -/* place the refuse file system name into `name' */ -static void -set_refuse_mount_name(char **argv, char *name, size_t size) -{ - char *slash; - - if (argv == NULL || *argv == NULL) { - (void) strlcpy(name, "refuse", size); - } else { - if ((slash = strrchr(*argv, '/')) == NULL) { - slash = *argv; - } else { - slash += 1; - } - if (strncmp(*argv, "refuse:", 7) == 0) { - /* we've already done this */ - (void) strlcpy(name, *argv, size); - } else { - (void) snprintf(name, size, "refuse:%s", slash); - } - } -} - - -/* this function exposes struct fuse to userland */ -static struct fuse * -fuse_setup_real(int argc, char **argv, const struct fuse_operations *ops, - size_t size, char **mountpoint, int *multithreaded, int *fd, - void *user_data) -{ - struct fuse_chan *fc; - struct fuse_args *args; - struct fuse *fuse; - char name[64]; - int i; - - /* set up the proper name */ - set_refuse_mount_name(argv, name, sizeof(name)); - - /* grab the pthread context key */ - if (!create_context_key()) { - return NULL; - } - - /* stuff name into fuse_args */ - args = fuse_opt_deep_copy_args(argc, argv); - if (args->argc > 0) { - free(args->argv[0]); - } - if ((args->argv[0] = strdup(name)) == NULL) { - fuse_opt_free_args(args); - return NULL; - } - - /* count back from the end over arguments starting with '-' */ - for (i = argc - 1 ; i > 0 && *argv[i] == '-' ; --i) { - } - - fc = fuse_mount(*mountpoint = argv[i], args); - fuse = fuse_new(fc, args, ops, size, user_data); - - fuse_opt_free_args(args); - free(args); - - /* XXX - wait for puffs to become multi-threaded */ - if (multithreaded) { - *multithreaded = 0; - } - - /* XXX - this is unused */ - if (fd) { - *fd = 0; - } - - return fuse; -} - -#ifdef fuse_setup -#undef fuse_setup -#endif - -struct fuse * -fuse_setup(int argc, char **argv, const struct fuse_operations *ops, - size_t size, char **mountpoint, int *multithreaded, int *fd) -{ - return fuse_setup_real(argc, argv, ops, size, mountpoint, - multithreaded, fd, NULL); -} - -struct fuse * -fuse_setup26(int argc, char **argv, const struct fuse_operations *ops, - size_t size, char **mountpoint, int *multithreaded, void *user_data) -{ - return fuse_setup_real(argc, argv, ops, size, mountpoint, - multithreaded, NULL, user_data); -} - -#define FUSE_ERR_UNLINK(fuse, file) if (fuse->op.unlink) fuse->op.unlink(file) -#define FUSE_ERR_RMDIR(fuse, dir) if (fuse->op.rmdir) fuse->op.rmdir(dir) - -/* ARGSUSED1 */ -static int -fuse_getattr(struct fuse *fuse, struct puffs_node *pn, const char *path, - struct vattr *va) -{ - struct stat st; - int ret; - - if (fuse->op.getattr == NULL) { - return ENOSYS; - } - - /* wrap up return code */ - memset(&st, 0, sizeof(st)); - ret = (*fuse->op.getattr)(path, &st); - - if (ret == 0) { - if (st.st_blksize == 0) - st.st_blksize = DEV_BSIZE; - puffs_stat2vattr(va, &st); - } - - return -ret; -} - -/* utility function to set various elements of the attribute */ -static int -fuse_setattr(struct fuse *fuse, struct puffs_node *pn, const char *path, - const struct vattr *va) -{ - struct refusenode *rn = pn->pn_data; - mode_t mode; - uid_t uid; - gid_t gid; - int error, ret; - - error = 0; - - mode = va->va_mode; - uid = va->va_uid; - gid = va->va_gid; - - if (mode != (mode_t)PUFFS_VNOVAL) { - ret = 0; - - if (fuse->op.chmod == NULL) { - error = -ENOSYS; - } else { - ret = fuse->op.chmod(path, mode); - if (ret) - error = ret; - } - } - if (uid != (uid_t)PUFFS_VNOVAL || gid != (gid_t)PUFFS_VNOVAL) { - ret = 0; - - if (fuse->op.chown == NULL) { - error = -ENOSYS; - } else { - ret = fuse->op.chown(path, uid, gid); - if (ret) - error = ret; - } - } - if (va->va_atime.tv_sec != (time_t)PUFFS_VNOVAL - || va->va_mtime.tv_sec != (long)PUFFS_VNOVAL) { - ret = 0; - - if (fuse->op.utimens) { - struct timespec tv[2]; - - tv[0].tv_sec = va->va_atime.tv_sec; - tv[0].tv_nsec = va->va_atime.tv_nsec; - tv[1].tv_sec = va->va_mtime.tv_sec; - tv[1].tv_nsec = va->va_mtime.tv_nsec; - - ret = fuse->op.utimens(path, tv); - } else if (fuse->op.utime) { - struct utimbuf timbuf; - - timbuf.actime = va->va_atime.tv_sec; - timbuf.modtime = va->va_mtime.tv_sec; - - ret = fuse->op.utime(path, &timbuf); - } else { - error = -ENOSYS; - } - - if (ret) - error = ret; - } - if (va->va_size != (u_quad_t)PUFFS_VNOVAL) { - ret = 0; - - if (fuse->op.truncate) { - ret = fuse->op.truncate(path, (off_t)va->va_size); - } else if (fuse->op.ftruncate) { - ret = fuse->op.ftruncate(path, (off_t)va->va_size, - &rn->file_info); - } else { - error = -ENOSYS; - } - - if (ret) - error = ret; - } - /* XXX: no reflection with reality */ - puffs_setvattr(&pn->pn_va, va); - - return -error; - -} - -static int -fuse_newnode(struct puffs_usermount *pu, const char *path, - const struct vattr *va, struct fuse_file_info *fi, - struct puffs_newinfo *pni, struct puffs_node **pn_new) -{ - struct puffs_node *pn; - struct refusenode *rn; - struct vattr newva; - struct fuse *fuse; - - fuse = puffs_getspecific(pu); - - /* fix up nodes */ - pn = newrn(pu); - if (pn == NULL) { - if (va->va_type == VDIR) { - FUSE_ERR_RMDIR(fuse, path); - } else { - FUSE_ERR_UNLINK(fuse, path); - } - return ENOMEM; - } - fuse_setattr(fuse, pn, path, va); - if (fuse_getattr(fuse, pn, path, &newva) == 0) - puffs_setvattr(&pn->pn_va, &newva); - - rn = pn->pn_data; - if (fi) - memcpy(&rn->file_info, fi, sizeof(struct fuse_file_info)); - - puffs_newinfo_setcookie(pni, pn); - if (pn_new) - *pn_new = pn; - - return 0; -} - - -/* operation wrappers start here */ - -/* lookup the path */ -/* ARGSUSED1 */ -static int -puffs_fuse_node_lookup(struct puffs_usermount *pu, void *opc, - struct puffs_newinfo *pni, const struct puffs_cn *pcn) -{ - struct puffs_node *pn_res; - struct stat st; - struct fuse *fuse; - const char *path = PCNPATH(pcn); - int ret; - - fuse = puffs_getspecific(pu); - - set_fuse_context_uid_gid(pcn->pcn_cred); - - ret = fuse->op.getattr(path, &st); - - if (ret != 0) { - return -ret; - } - - /* XXX: fiXXXme unconst */ - pn_res = puffs_pn_nodewalk(pu, puffs_path_walkcmp, - __DECONST(struct puffs_pathobj *, &pcn->pcn_po_full)); - if (pn_res == NULL) { - pn_res = newrn(pu); - if (pn_res == NULL) - return errno; - puffs_stat2vattr(&pn_res->pn_va, &st); - } - - 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); - - return 0; -} - -/* get attributes for the path name */ -/* ARGSUSED3 */ -static int -puffs_fuse_node_getattr(struct puffs_usermount *pu, void *opc, struct vattr *va, - const struct puffs_cred *pcr) -{ - struct puffs_node *pn = opc; - struct fuse *fuse; - const char *path = PNPATH(pn); - - fuse = puffs_getspecific(pu); - - set_fuse_context_uid_gid(pcr); - - return fuse_getattr(fuse, pn, path, va); -} - -/* read the contents of the symbolic link */ -/* ARGSUSED2 */ -static int -puffs_fuse_node_readlink(struct puffs_usermount *pu, void *opc, - const struct puffs_cred *cred, char *linkname, size_t *linklen) -{ - struct puffs_node *pn = opc; - struct fuse *fuse; - const char *path = PNPATH(pn), *p; - int ret; - - fuse = puffs_getspecific(pu); - if (fuse->op.readlink == NULL) { - return ENOSYS; - } - - set_fuse_context_uid_gid(cred); - - /* wrap up return code */ - ret = (*fuse->op.readlink)(path, linkname, *linklen); - - if (ret == 0) { - p = memchr(linkname, '\0', *linklen); - if (!p) - return EINVAL; - - *linklen = p - linkname; - } - - return -ret; -} - -/* make the special node */ -/* ARGSUSED1 */ -static int -puffs_fuse_node_mknod(struct puffs_usermount *pu, void *opc, - struct puffs_newinfo *pni, const struct puffs_cn *pcn, - const struct vattr *va) -{ - struct fuse *fuse; - mode_t mode; - const char *path = PCNPATH(pcn); - int ret; - - fuse = puffs_getspecific(pu); - if (fuse->op.mknod == NULL) { - return ENOSYS; - } - - set_fuse_context_uid_gid(pcn->pcn_cred); - - /* wrap up return code */ - mode = puffs_addvtype2mode(va->va_mode, va->va_type); - ret = (*fuse->op.mknod)(path, mode, 0); - - if (ret == 0) { - ret = fuse_newnode(pu, path, va, NULL, pni, NULL); - } - - return -ret; -} - -/* make a directory */ -/* ARGSUSED1 */ -static int -puffs_fuse_node_mkdir(struct puffs_usermount *pu, void *opc, - struct puffs_newinfo *pni, const struct puffs_cn *pcn, - const struct vattr *va) -{ - struct fuse *fuse; - mode_t mode = va->va_mode; - const char *path = PCNPATH(pcn); - int ret; - - fuse = puffs_getspecific(pu); - - set_fuse_context_uid_gid(pcn->pcn_cred); - - if (fuse->op.mkdir == NULL) { - return ENOSYS; - } - - /* wrap up return code */ - ret = (*fuse->op.mkdir)(path, mode); - - if (ret == 0) { - ret = fuse_newnode(pu, path, va, NULL, pni, NULL); - } - - return -ret; -} - -/* - * create a regular file - * - * since linux/fuse sports using mknod for creating regular files - * instead of having a separate call for it in some versions, if - * we don't have create, just jump to op->mknod. - */ -/*ARGSUSED1*/ -static int -puffs_fuse_node_create(struct puffs_usermount *pu, void *opc, - struct puffs_newinfo *pni, const struct puffs_cn *pcn, - const struct vattr *va) -{ - struct fuse *fuse; - struct fuse_file_info fi; - struct puffs_node *pn; - mode_t mode = va->va_mode; - const char *path = PCNPATH(pcn); - int ret, created; - - fuse = puffs_getspecific(pu); - - set_fuse_context_uid_gid(pcn->pcn_cred); - - created = 0; - if (fuse->op.create) { - ret = fuse->op.create(path, mode | S_IFREG, &fi); - if (ret == 0) - created = 1; - - } else if (fuse->op.mknod) { - ret = fuse->op.mknod(path, mode | S_IFREG, 0); - - } else { - ret = -ENOSYS; - } - - if (ret == 0) { - ret = fuse_newnode(pu, path, va, &fi, pni, &pn); - - /* sweet.. create also open the file */ - if (created) { - struct refusenode *rn; - - rn = pn->pn_data; - rn->flags |= RN_OPEN; - rn->opencount++; - } - } - - return -ret; -} - -/* remove the directory entry */ -/* ARGSUSED1 */ -static int -puffs_fuse_node_remove(struct puffs_usermount *pu, void *opc, void *targ, - const struct puffs_cn *pcn) -{ - struct puffs_node *pn_targ = targ; - struct fuse *fuse; - const char *path = PNPATH(pn_targ); - int ret; - - fuse = puffs_getspecific(pu); - - set_fuse_context_uid_gid(pcn->pcn_cred); - - if (fuse->op.unlink == NULL) { - return ENOSYS; - } - - /* wrap up return code */ - ret = (*fuse->op.unlink)(path); - - return -ret; -} - -/* remove the directory */ -/* ARGSUSED1 */ -static int -puffs_fuse_node_rmdir(struct puffs_usermount *pu, void *opc, void *targ, - const struct puffs_cn *pcn) -{ - struct puffs_node *pn_targ = targ; - struct fuse *fuse; - const char *path = PNPATH(pn_targ); - int ret; - - fuse = puffs_getspecific(pu); - - set_fuse_context_uid_gid(pcn->pcn_cred); - - if (fuse->op.rmdir == NULL) { - return ENOSYS; - } - - /* wrap up return code */ - ret = (*fuse->op.rmdir)(path); - - return -ret; -} - -/* create a symbolic link */ -/* ARGSUSED1 */ -static int -puffs_fuse_node_symlink(struct puffs_usermount *pu, void *opc, - struct puffs_newinfo *pni, const struct puffs_cn *pcn_src, - const struct vattr *va, const char *link_target) -{ - struct fuse *fuse; - const char *path = PCNPATH(pcn_src); - int ret; - - fuse = puffs_getspecific(pu); - - set_fuse_context_uid_gid(pcn_src->pcn_cred); - - if (fuse->op.symlink == NULL) { - return ENOSYS; - } - - /* wrap up return code */ - ret = fuse->op.symlink(link_target, path); - - if (ret == 0) { - ret = fuse_newnode(pu, path, va, NULL, pni, NULL); - } - - return -ret; -} - -/* rename a directory entry */ -/* ARGSUSED1 */ -static int -puffs_fuse_node_rename(struct puffs_usermount *pu, void *opc, void *src, - const struct puffs_cn *pcn_src, void *targ_dir, void *targ, - const struct puffs_cn *pcn_targ) -{ - struct fuse *fuse; - const char *path_src = PCNPATH(pcn_src); - const char *path_dest = PCNPATH(pcn_targ); - int ret; - - fuse = puffs_getspecific(pu); - - set_fuse_context_uid_gid(pcn_targ->pcn_cred); - - if (fuse->op.rename == NULL) { - return ENOSYS; - } - - ret = fuse->op.rename(path_src, path_dest); - - if (ret == 0) { - } - - return -ret; -} - -/* create a link in the file system */ -/* ARGSUSED1 */ -static int -puffs_fuse_node_link(struct puffs_usermount *pu, void *opc, void *targ, - const struct puffs_cn *pcn) -{ - struct puffs_node *pn = targ; - struct fuse *fuse; - int ret; - - fuse = puffs_getspecific(pu); - - set_fuse_context_uid_gid(pcn->pcn_cred); - - if (fuse->op.link == NULL) { - return ENOSYS; - } - - /* wrap up return code */ - ret = (*fuse->op.link)(PNPATH(pn), PCNPATH(pcn)); - - return -ret; -} - -/* - * fuse's regular interface provides chmod(), chown(), utimes() - * and truncate() + some variations, so try to fit the square block - * in the circle hole and the circle block .... something like that - */ -/* ARGSUSED3 */ -static int -puffs_fuse_node_setattr(struct puffs_usermount *pu, void *opc, - const struct vattr *va, const struct puffs_cred *pcr) -{ - struct puffs_node *pn = opc; - struct fuse *fuse; - const char *path = PNPATH(pn); - - fuse = puffs_getspecific(pu); - - set_fuse_context_uid_gid(pcr); - - return fuse_setattr(fuse, pn, path, va); -} - -/* ARGSUSED2 */ -static int -puffs_fuse_node_open(struct puffs_usermount *pu, void *opc, int mode, - const struct puffs_cred *cred) -{ - struct puffs_node *pn = opc; - struct refusenode *rn = pn->pn_data; - struct fuse_file_info *fi = &rn->file_info; - struct fuse *fuse; - const char *path = PNPATH(pn); - - fuse = puffs_getspecific(pu); - - set_fuse_context_uid_gid(cred); - - /* if open, don't open again, lest risk nuking file private info */ - if (rn->flags & RN_OPEN) { - rn->opencount++; - return 0; - } - - /* OFLAGS(), need to convert FREAD/FWRITE to O_RD/WR */ - fi->flags = (mode & ~(O_CREAT | O_EXCL | O_TRUNC)) - 1; - - if (pn->pn_va.va_type == VDIR) { - if (fuse->op.opendir) - fuse->op.opendir(path, fi); - } else { - if (fuse->op.open) - fuse->op.open(path, fi); - } - - rn->flags |= RN_OPEN; - rn->opencount++; - - return 0; -} - -/* ARGSUSED2 */ -static int -puffs_fuse_node_close(struct puffs_usermount *pu, void *opc, int fflag) -{ - struct puffs_node *pn = opc; - struct refusenode *rn = pn->pn_data; - struct fuse *fuse; - struct fuse_file_info *fi; - const char *path = PNPATH(pn); - int ret; - - fuse = puffs_getspecific(pu); - fi = &rn->file_info; - ret = 0; - -#ifdef XXXDF - set_fuse_context_uid_gid(pcr); -#endif - - if (rn->flags & RN_OPEN) { - if (pn->pn_va.va_type == VDIR) { - if (fuse->op.releasedir) - ret = fuse->op.releasedir(path, fi); - } else { - if (fuse->op.release) - ret = fuse->op.release(path, fi); - } - } - rn->flags &= ~RN_OPEN; - rn->opencount--; - - return ret; -} - -/* read some more from the file */ -/* ARGSUSED5 */ -static int -puffs_fuse_node_read(struct puffs_usermount *pu, void *opc, uint8_t *buf, - off_t offset, size_t *resid, const struct puffs_cred *pcr, - int ioflag) -{ - struct puffs_node *pn = opc; - struct refusenode *rn = pn->pn_data; - struct fuse *fuse; - const char *path = PNPATH(pn); - size_t maxread; - int ret; - - fuse = puffs_getspecific(pu); - if (fuse->op.read == NULL) { - return ENOSYS; - } - - set_fuse_context_uid_gid(pcr); - - maxread = *resid; - if (maxread > pn->pn_va.va_size - offset) { - /*LINTED*/ - maxread = pn->pn_va.va_size - offset; - } - if (maxread == 0) - return 0; - - ret = (*fuse->op.read)(path, (char *)buf, maxread, offset, - &rn->file_info); - - if (ret > 0) { - *resid -= ret; - ret = 0; - } - - return -ret; -} - -/* write to the file */ -/* ARGSUSED0 */ -static int -puffs_fuse_node_write(struct puffs_usermount *pu, void *opc, uint8_t *buf, - off_t offset, size_t *resid, const struct puffs_cred *pcr, - int ioflag) -{ - struct puffs_node *pn = opc; - struct refusenode *rn = pn->pn_data; - struct fuse *fuse; - const char *path = PNPATH(pn); - int ret; - - fuse = puffs_getspecific(pu); - if (fuse->op.write == NULL) { - return ENOSYS; - } - - set_fuse_context_uid_gid(pcr); - - if (ioflag & PUFFS_IO_APPEND) - offset = pn->pn_va.va_size; - - ret = (*fuse->op.write)(path, (char *)buf, *resid, offset, - &rn->file_info); - - if (ret > 0) { - if ((uint64_t)(offset + ret) > pn->pn_va.va_size) - pn->pn_va.va_size = offset + ret; - *resid -= ret; - ret = 0; - } - - return -ret; -} - - -/* ARGSUSED3 */ -static int -puffs_fuse_node_readdir(struct puffs_usermount *pu, void *opc, - struct dirent *dent, off_t *readoff, size_t *reslen, - const struct puffs_cred *pcr, int *eofflag, - off_t *cookies, size_t *ncookies) -{ - struct puffs_node *pn = opc; - struct refusenode *rn = pn->pn_data; - struct puffs_fuse_dirh *dirh; - struct fuse *fuse; - struct dirent *fromdent; - const char *path = PNPATH(pn); - int ret; - - fuse = puffs_getspecific(pu); - if (fuse->op.readdir == NULL && fuse->op.getdir == NULL) { - return ENOSYS; - } - - set_fuse_context_uid_gid(pcr); - - if (pn->pn_va.va_type != VDIR) - return ENOTDIR; - - dirh = &rn->dirh; - - /* - * if we are starting from the beginning, slurp entire directory - * into our buffers - */ - if (*readoff == 0) { - /* free old buffers */ - free(dirh->dbuf); - memset(dirh, 0, sizeof(struct puffs_fuse_dirh)); - - if (fuse->op.readdir) - ret = fuse->op.readdir(path, dirh, puffs_fuse_fill_dir, - 0, &rn->file_info); - else - ret = fuse->op.getdir(path, dirh, puffs_fuse_dirfil); - if (ret) - return -ret; - } - - /* now, stuff results into the kernel buffers */ - while (*readoff < (off_t)(dirh->bufsize - dirh->reslen)) { - /*LINTED*/ - fromdent = (struct dirent *)((uint8_t *)dirh->dbuf + *readoff); - - if (*reslen < _DIRENT_DIRSIZ(fromdent)) - break; - - memcpy(dent, fromdent, _DIRENT_DIRSIZ(fromdent)); - *readoff += _DIRENT_DIRSIZ(fromdent); - *reslen -= _DIRENT_DIRSIZ(fromdent); - - dent = _DIRENT_NEXT(dent); - } - - return 0; -} - -/* ARGSUSED */ -static int -puffs_fuse_node_reclaim(struct puffs_usermount *pu, void *opc) -{ - struct puffs_node *pn = opc; - - nukern(pn); - return 0; -} - -/* ARGSUSED1 */ -static int -puffs_fuse_fs_unmount(struct puffs_usermount *pu, int flags) -{ - struct fuse *fuse; - - fuse = puffs_getspecific(pu); - if (fuse->op.destroy == NULL) { - return 0; - } - (*fuse->op.destroy)(fuse); - return 0; -} - -/* ARGSUSED0 */ -static int -puffs_fuse_fs_sync(struct puffs_usermount *pu, int flags) -{ -#ifdef XXXDF - set_fuse_context_uid_gid(cr); -#endif - return 0; -} - -/* ARGSUSED2 */ -static int -puffs_fuse_fs_statvfs(struct puffs_usermount *pu, struct statvfs *svfsb) -{ - struct fuse *fuse; - int ret; - - fuse = puffs_getspecific(pu); - if (fuse->op.statfs == NULL) { - if ((ret = statvfs(PNPATH(puffs_getroot(pu)), svfsb)) == -1) { - return errno; - } - } else { - ret = fuse->op.statfs(PNPATH(puffs_getroot(pu)), svfsb); - } - - return -ret; -} - - -/* End of puffs_fuse operations */ -/* ARGSUSED3 */ -int -fuse_main_real(int argc, char **argv, const struct fuse_operations *ops, - size_t size, void *userdata) -{ - struct fuse *fuse; - char *mountpoint; - int multithreaded; - int fd; - - fuse = fuse_setup_real(argc, argv, ops, size, &mountpoint, - &multithreaded, &fd, userdata); - - return fuse_loop(fuse); -} - -/* - * XXX: just defer the operation until fuse_new() when we have more - * info on our hands. The real beef is why's this separate in fuse in - * the first place? - */ -/* ARGSUSED1 */ -struct fuse_chan * -fuse_mount(const char *dir, struct fuse_args *args) -{ - struct fuse_chan *fc; - char name[64]; - - if ((fc = calloc(1, sizeof(*fc))) == NULL) { - err(EXIT_FAILURE, "fuse_mount"); - } - fc->dead = 0; - - if ((fc->dir = strdup(dir)) == NULL) { - err(EXIT_FAILURE, "fuse_mount"); - } - - /* - * we need to deep copy the args struct - some fuse file - * systems "clean up" the argument vector for "security - * reasons" - */ - fc->args = fuse_opt_deep_copy_args(args->argc, args->argv); - - if (args->argc > 0) { - set_refuse_mount_name(args->argv, name, sizeof(name)); - if ((args->argv[0] = strdup(name)) == NULL) - err(1, "fuse_mount"); - } - - return fc; -} - -/* ARGSUSED1 */ -struct fuse * -fuse_new(struct fuse_chan *fc, struct fuse_args *args, - const struct fuse_operations *ops, size_t size, void *userdata) -{ - struct puffs_usermount *pu; - struct fuse_context *fusectx; - struct puffs_pathobj *po_root; - struct puffs_node *pn_root; - struct puffs_ops *pops; - struct refusenode *rn_root; - struct statvfs svfsb; - struct stat st; - struct fuse *fuse; - extern int puffs_fakecc; - char name[64]; - char *argv0; - - if ((fuse = calloc(1, sizeof(*fuse))) == NULL) { - err(EXIT_FAILURE, "fuse_new"); - } - - /* copy fuse ops to their own structure */ - (void) memcpy(&fuse->op, ops, sizeof(fuse->op)); - - fusectx = fuse_get_context(); - fusectx->fuse = fuse; - fusectx->uid = 0; - fusectx->gid = 0; - fusectx->pid = 0; - fusectx->private_data = userdata; - - fuse->fc = fc; - - if (fuse->op.init != NULL) - fusectx->private_data = fuse->op.init(NULL); /* XXX */ - - /* initialise the puffs operations structure */ - PUFFSOP_INIT(pops); - - PUFFSOP_SET(pops, puffs_fuse, fs, sync); - PUFFSOP_SET(pops, puffs_fuse, fs, statvfs); - PUFFSOP_SET(pops, puffs_fuse, fs, unmount); - - /* - * XXX: all of these don't possibly need to be - * unconditionally set - */ - PUFFSOP_SET(pops, puffs_fuse, node, lookup); - PUFFSOP_SET(pops, puffs_fuse, node, getattr); - PUFFSOP_SET(pops, puffs_fuse, node, setattr); - PUFFSOP_SET(pops, puffs_fuse, node, readdir); - PUFFSOP_SET(pops, puffs_fuse, node, readlink); - PUFFSOP_SET(pops, puffs_fuse, node, mknod); - PUFFSOP_SET(pops, puffs_fuse, node, create); - PUFFSOP_SET(pops, puffs_fuse, node, remove); - PUFFSOP_SET(pops, puffs_fuse, node, mkdir); - PUFFSOP_SET(pops, puffs_fuse, node, rmdir); - PUFFSOP_SET(pops, puffs_fuse, node, symlink); - PUFFSOP_SET(pops, puffs_fuse, node, rename); - PUFFSOP_SET(pops, puffs_fuse, node, link); - PUFFSOP_SET(pops, puffs_fuse, node, open); - PUFFSOP_SET(pops, puffs_fuse, node, close); - PUFFSOP_SET(pops, puffs_fuse, node, read); - PUFFSOP_SET(pops, puffs_fuse, node, write); - PUFFSOP_SET(pops, puffs_fuse, node, reclaim); - - argv0 = (*args->argv[0] == 0x0) ? fc->args->argv[0] : args->argv[0]; - set_refuse_mount_name(&argv0, name, sizeof(name)); - - puffs_fakecc = 1; /* XXX */ - pu = puffs_init(pops, _PATH_PUFFS, name, fuse, - PUFFS_FLAG_BUILDPATH - | PUFFS_FLAG_HASHPATH - | PUFFS_KFLAG_NOCACHE); - if (pu == NULL) { - err(EXIT_FAILURE, "puffs_init"); - } - fc->pu = pu; - - pn_root = newrn(pu); - puffs_setroot(pu, pn_root); - rn_root = pn_root->pn_data; - rn_root->flags |= RN_ROOT; - - po_root = puffs_getrootpathobj(pu); - if ((po_root->po_path = strdup("/")) == NULL) - err(1, "fuse_new"); - po_root->po_len = 1; - puffs_path_buildhash(pu, po_root); - - /* sane defaults */ - puffs_vattr_null(&pn_root->pn_va); - pn_root->pn_va.va_type = VDIR; - pn_root->pn_va.va_mode = 0755; - if (fuse->op.getattr) - if (fuse->op.getattr(po_root->po_path, &st) == 0) - puffs_stat2vattr(&pn_root->pn_va, &st); - assert(pn_root->pn_va.va_type == VDIR); - - puffs_set_prepost(pu, set_fuse_context_pid, NULL); - - puffs_zerostatvfs(&svfsb); - if (puffs_mount(pu, fc->dir, MNT_NODEV | MNT_NOSUID, pn_root) == -1) { - err(EXIT_FAILURE, "puffs_mount: directory \"%s\"", fc->dir); - } - - return fuse; -} - -int -fuse_loop(struct fuse *fuse) -{ - - return puffs_mainloop(fuse->fc->pu); -} - -void -fuse_destroy(struct fuse *fuse) -{ - - /* - * TODO: needs to assert the fs is quiescent, i.e. no other - * threads exist - */ - - delete_context_key(); - /* XXXXXX: missing stuff */ - free(fuse); -} - -void -fuse_exit(struct fuse *fuse) -{ - - /* XXX: puffs_exit() is WRONG */ - if (fuse->fc->dead == 0) - puffs_exit(fuse->fc->pu, 1); - fuse->fc->dead = 1; -} - -/* - * XXX: obviously not the most perfect of functions, but needs some - * puffs tweaking for a better tomorrow - */ -/*ARGSUSED*/ -void -fuse_unmount(const char *mp, struct fuse_chan *fc) -{ - - /* XXX: puffs_exit() is WRONG */ - if (fc->dead == 0) - puffs_exit(fc->pu, 1); - fc->dead = 1; -} - -/*ARGSUSED*/ -void -fuse_unmount_compat22(const char *mp) -{ - - return; -} - -/* The next function "exposes" struct fuse to userland. Not much -* that we can do about this, as we're conforming to a defined -* interface. */ - -void -fuse_teardown(struct fuse *fuse, char *mountpoint) -{ - fuse_unmount(mountpoint, fuse->fc); - fuse_destroy(fuse); -} diff --git a/lib/librefuse/refuse_opt.c b/lib/librefuse/refuse_opt.c deleted file mode 100644 index 59c67beaca..0000000000 --- a/lib/librefuse/refuse_opt.c +++ /dev/null @@ -1,366 +0,0 @@ -/* $NetBSD: refuse_opt.c,v 1.15 2011/03/01 11:23:42 soda Exp $ */ - -/*- - * Copyright (c) 2007 Juan Romero Pardines. - * 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 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. - */ - -/* - * TODO: - * * -oblah,foo... works, but the options are not enabled. - * * -ofoo=%s (accepts a string) or -ofoo=%u (int) is not - * supported for now. - * * void *data: how is it used? I think it's used to enable - * options or pass values for the matching options. - */ - -#include - -#include -#include -#include -#include - -#include "fuse.h" -#include "fuse_opt.h" - -#ifdef FUSE_OPT_DEBUG -#define DPRINTF(x) do { printf x; } while ( /* CONSTCOND */ 0) -#else -#define DPRINTF(x) -#endif - -enum { - KEY_HELP, - KEY_VERBOSE, - KEY_VERSION -}; - -struct fuse_opt_option { - const struct fuse_opt *fop; - char *option; - int key; - void *data; -}; - -static int fuse_opt_popt(struct fuse_opt_option *, const struct fuse_opt *); -static int fuse_opt_realloc_args(struct fuse_args *args, int nargc); - -/* - * Public API. - * - * The following functions always return 0: - * - * int fuse_opt_add_opt(char **, const char *); - * - * We implement the next ones: - * - * int fuse_opt_add_arg(struct fuse_args *, const char *); - * void fuse_opt_free_args(struct fuse_args *); - * int fuse_opt_insert_arg(struct fuse_args *, const char *); - * int fuse_opt_match(const struct fuse_opt *, const char *); - * int fuse_opt_parse(struct fuse_args *, void *, - * const struct fuse_opt *, fuse_opt_proc_t); - * - */ - -/* ARGSUSED */ -int -fuse_opt_add_arg(struct fuse_args *args, const char *arg) -{ - - fuse_opt_realloc_args(args, args->argc + 1); - DPRINTF(("%s: arguments passed: [arg:%s]\n", __func__, arg)); - if ((args->argv[args->argc++] = strdup(arg)) == NULL) - err(1, "fuse_opt_add_arg"); - args->argv[args->argc] = NULL; - return 0; -} - -struct fuse_args * -fuse_opt_deep_copy_args(int argc, char **argv) -{ - struct fuse_args *ap; - int i; - - if ((ap = malloc(sizeof(*ap))) == NULL) - err(1, "_fuse_deep_copy_args"); - /* deep copy args structure into channel args */ - ap->allocated = ((argc / 10) + 1) * 10; - - if ((ap->argv = calloc((size_t)ap->allocated, - sizeof(*ap->argv))) == NULL) - err(1, "_fuse_deep_copy_args"); - - for (i = 0; i < argc; i++) { - if ((ap->argv[i] = strdup(argv[i])) == NULL) - err(1, "_fuse_deep_copy_args"); - } - ap->argv[ap->argc = i] = NULL; - return ap; -} - -static int -fuse_opt_realloc_args(struct fuse_args *args, int nargc) -{ - struct fuse_args *ap; - - if (args->allocated == 0) { - ap = fuse_opt_deep_copy_args(args->argc, args->argv); - args->argv = ap->argv; - args->argc = ap->argc; - args->allocated = ap->allocated; - (void) free(ap); - } else if (args->allocated < nargc) { - void *a; - int na = nargc + 10; - - if ((a = realloc(args->argv, na * sizeof(*args->argv))) == NULL) - return -1; - - args->argv = a; - args->allocated = na; - } - - return 0; -} - -void -fuse_opt_free_args(struct fuse_args *ap) -{ - int i; - - for (i = 0; i < ap->argc; i++) { - free(ap->argv[i]); - } - free(ap->argv); - ap->argv = NULL; - ap->allocated = ap->argc = 0; -} - -/* ARGSUSED */ -int -fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg) -{ - int i; - - DPRINTF(("%s: arguments passed: [pos=%d] [arg=%s]\n", - __func__, pos, arg)); - fuse_opt_realloc_args(args, args->argc + 1); - - for (i = args->argc++; i > pos; --i) { - args->argv[i] = args->argv[i - 1]; - } - if ((args->argv[pos] = strdup(arg)) == NULL) - err(1, "fuse_opt_insert_arg"); - args->argv[args->argc] = NULL; - return 0; -} - -/* ARGSUSED */ -int fuse_opt_add_opt(char **opts, const char *opt) -{ - DPRINTF(("%s: arguments passed: [opts=%s] [opt=%s]\n", - __func__, *opts, opt)); - return 0; -} - -/* - * Returns 0 if opt was matched with any option from opts, - * otherwise returns 1. - */ -int -fuse_opt_match(const struct fuse_opt *opts, const char *opt) -{ - while (opts++) { - if (strcmp(opt, opts->templ) == 0) - return 0; - } - - return 1; -} - -/* - * Returns 0 if foo->option was matched with any option from opts, - * and sets the following on match: - * - * * foo->key is set to the foo->fop->value if offset == -1. - * * foo->fop points to the matched struct opts. - * - * otherwise returns 1. - */ -static int -fuse_opt_popt(struct fuse_opt_option *foo, const struct fuse_opt *opts) -{ - int i, found = 0; - char *match; - - if (!foo->option) { - (void)fprintf(stderr, "fuse: missing argument after -o\n"); - return 1; - } - /* - * iterate over argv and opts to see - * if there's a match with any template. - */ - for (match = strtok(foo->option, ","); - match; match = strtok(NULL, ",")) { - - DPRINTF(("%s: specified option='%s'\n", __func__, match)); - found = 0; - - for (i = 0; opts && opts->templ; opts++, i++) { - - DPRINTF(("%s: opts->templ='%s' opts->offset=%d " - "opts->value=%d\n", __func__, opts->templ, - opts->offset, opts->value)); - - /* option is ok */ - if (strcmp(match, opts->templ) == 0) { - DPRINTF(("%s: option matched='%s'\n", - __func__, match)); - found++; - /* - * our fop pointer now points - * to the matched struct opts. - */ - foo->fop = opts; - /* - * assign default key value, necessary for - * KEY_HELP, KEY_VERSION and KEY_VERBOSE. - */ - if (foo->fop->offset == -1) - foo->key = foo->fop->value; - /* reset counter */ - opts -= i; - break; - } - } - /* invalid option */ - if (!found) { - (void)fprintf(stderr, "fuse: '%s' is not a " - "valid option\n", match); - return 1; - } - } - - return 0; -} - -/* ARGSUSED1 */ -int -fuse_opt_parse(struct fuse_args *args, void *data, - const struct fuse_opt *opts, fuse_opt_proc_t proc) -{ - struct fuse_opt_option foo; - char *buf; - int i, rv = 0; - - if (!args || !args->argv || !args->argc || !proc) - return 0; - - foo.data = data; - if (args->argc == 1) - return proc(foo.data, *args->argv, FUSE_OPT_KEY_OPT, args); - - /* the real loop to process the arguments */ - for (i = 1; i < args->argc; i++) { - - /* assign current argv string */ - foo.option = buf = args->argv[i]; - - /* argvn != -foo... */ - if (buf[0] != '-') { - - foo.key = FUSE_OPT_KEY_NONOPT; - rv = proc(foo.data, foo.option, foo.key, args); - if (rv != 0) - break; - - /* -o was specified... */ - } else if (buf[0] == '-' && buf[1] == 'o') { - - /* -oblah,foo... */ - if (buf[2]) { - /* skip -o */ - foo.option = args->argv[i] + 2; - /* -o blah,foo... */ - } else { - /* - * skip current argv and pass to the - * next one to parse the options. - */ - ++i; - foo.option = args->argv[i]; - } - - rv = fuse_opt_popt(&foo, opts); - if (rv != 0) - break; - - /* help/version/verbose argument */ - } else if (buf[0] == '-' && buf[1] != 'o') { - /* - * check if the argument matches - * with any template in opts. - */ - rv = fuse_opt_popt(&foo, opts); - if (rv != 0) { - break; - } else { - DPRINTF(("%s: foo.fop->templ='%s' " - "foo.fop->offset: %d " - "foo.fop->value: %d\n", - __func__, foo.fop->templ, - foo.fop->offset, foo.fop->value)); - - /* argument needs to be discarded */ - if (foo.key == FUSE_OPT_KEY_DISCARD) { - rv = 1; - break; - } - - /* process help/version argument */ - if (foo.key != KEY_VERBOSE && - foo.key != FUSE_OPT_KEY_KEEP) { - rv = proc(foo.data, foo.option, - foo.key, args); - break; - } else { - /* process verbose argument */ - rv = proc(foo.data, foo.option, - foo.key, args); - if (rv != 0) - break; - } - } - /* unknown option, how could that happen? */ - } else { - DPRINTF(("%s: unknown option\n", __func__)); - rv = 1; - break; - } - } - - return rv; -} diff --git a/share/examples/puffs/pnullfs/Makefile b/share/examples/puffs/pnullfs/Makefile deleted file mode 100644 index 289f927746..0000000000 --- a/share/examples/puffs/pnullfs/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -PROG= pnullfs -LDADD+= -lpuffs -lutil -DPADD+= ${LIBPUFFS} ${LIBUTIL} - -WARNS= 2 - -NOMAN= 1 - -DEBUG_FLAGS=-g -O0 - -.include diff --git a/share/examples/puffs/pnullfs/pnullfs.c b/share/examples/puffs/pnullfs/pnullfs.c deleted file mode 100644 index 511907fac8..0000000000 --- a/share/examples/puffs/pnullfs/pnullfs.c +++ /dev/null @@ -1,121 +0,0 @@ -/* $NetBSD: pnullfs.c,v 1.18 2008/11/26 14:03:48 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. - */ - -/* - * pnullfs: puffs nullfs example - */ - -#include -#include -#include -#include -#include - -static void usage(void); - -static void -usage() -{ - - errx(1, "usage: %s [-s] [-o mntopts] nullpath mountpath", - getprogname()); -} - -int -main(int argc, char *argv[]) -{ - struct puffs_usermount *pu; - struct puffs_ops *pops; - struct puffs_pathobj *po_root; - struct puffs_node *pn_root; - struct stat sb; - int mntflags, pflags; - int ch; - int detach; - - setprogname(argv[0]); - - if (argc < 3) - usage(); - - pflags = mntflags = 0; - detach = 1; - while ((ch = getopt(argc, argv, "o:s")) != -1) { - switch (ch) { - case 'o': - getmntopts(optarg, puffsmopts, &mntflags, &pflags); - break; - case 's': - detach = 0; - break; - } - } - pflags |= PUFFS_FLAG_BUILDPATH; - argv += optind; - argc -= optind; - - if (pflags & PUFFS_FLAG_OPDUMP) - detach = 0; - - if (argc != 2) - usage(); - - if (lstat(argv[0], &sb) == -1) - err(1, "stat %s", argv[0]); - if ((sb.st_mode & S_IFDIR) == 0) - errx(1, "%s is not a directory", argv[0]); - - PUFFSOP_INIT(pops); - puffs_null_setops(pops); - - if ((pu = puffs_init(pops, argv[0], "pnullfs", NULL, pflags)) == NULL) - err(1, "init"); - - pn_root = puffs_pn_new(pu, NULL); - if (pn_root == NULL) - err(1, "puffs_pn_new"); - puffs_setroot(pu, pn_root); - puffs_setfhsize(pu, 0, PUFFS_FHFLAG_PASSTHROUGH); - - po_root = puffs_getrootpathobj(pu); - if (po_root == NULL) - err(1, "getrootpathobj"); - po_root->po_path = argv[0]; - po_root->po_len = strlen(argv[0]); - puffs_stat2vattr(&pn_root->pn_va, &sb); - - if (detach) - if (puffs_daemon(pu, 1, 1) == -1) - err(1, "puffs_daemon"); - - if (puffs_mount(pu, argv[1], mntflags, pn_root) == -1) - err(1, "puffs_mount"); - if (puffs_mainloop(pu) == -1) - err(1, "mainloop"); - - return 0; -} diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index e3d4afa70c..3a4915a2ce 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -249,7 +249,6 @@ MAN= aac.4 \ pt.4 \ pty.4 \ puc.4 \ - puffs.4 \ radeonkms.4 \ ral.4 \ random.4 \ diff --git a/share/man/man4/puffs.4 b/share/man/man4/puffs.4 deleted file mode 100644 index e0454404c1..0000000000 --- a/share/man/man4/puffs.4 +++ /dev/null @@ -1,61 +0,0 @@ -.\" $NetBSD: puffs.4,v 1.10 2009/11/22 18:36:16 pooka Exp $ -.\" -.\" Copyright (c) 2009 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 February 5, 2012 -.Dt PUFFS 4 -.Os -.Sh NAME -.Nm puffs -.Nd Pass-to-Userspace Framework File System -.Sh SYNOPSIS -.Cd "options PUFFS" -.Cd "pseudo-device putter" -.Sh DESCRIPTION -.Nm -provides a framework for creating file systems as userspace servers. -The in-kernel VFS attachment is controlled through a special device -node, -.Pa /dev/puffs . -People looking to implement file systems should use the -system through the convenience library described in -.Xr puffs 3 . -.Ss Termination -A -.Nm -file system can be unmounted regularly using -.Xr umount 8 . -The file system will automatically be unmounted in case the userspace -server is killed or the control file descriptor closed. -.Sh SEE ALSO -.Xr puffs 3 -.Sh HISTORY -An unsupported experimental version of -.Nm -first appeared in -.Nx 4.0 . -A stable version appeared in -.Nx 5.0 . -.Sh AUTHORS -.An Antti Kantee Aq Mt pooka@iki.fi diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile index 0bea28608b..bfed4232a7 100644 --- a/share/man/man9/Makefile +++ b/share/man/man9/Makefile @@ -145,7 +145,6 @@ MAN= accept_filter.9 \ physio.9 \ priv.9 \ prop_copyin_ioctl.9 \ - putter.9 \ resettodr.9 \ rman.9 \ rtalloc.9 \ diff --git a/share/man/man9/putter.9 b/share/man/man9/putter.9 deleted file mode 100644 index b5d0483c4b..0000000000 --- a/share/man/man9/putter.9 +++ /dev/null @@ -1,48 +0,0 @@ -.\" $NetBSD: putter.9,v 1.3 2009/05/18 12:27:22 wiz Exp $ -.\" -.\" Copyright (c) 2007 The NetBSD Foundation, Inc. -.\" 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 February 5, 2012 -.Dt PUTTER 9 -.Os -.Sh NAME -.Nm putter -.Nd Pass-to-Userspace Transporter -.Sh DESCRIPTION -The -.Nm -subsystem is used for request-response handling of userspace components. -It currently provides routines for associating a file descriptor -with a subsystem data structure instance and I/O routines. -Users of the facility must fill out the callbacks in -.Va struct putter_ops -to integrate with -.Nm . -.Sh SEE ALSO -.\".Xr pud 4 , -.Xr puffs 4 -.Sh BUGS -Under construction. -Interfaces may and will change. diff --git a/share/mk/bsd.libnames.mk b/share/mk/bsd.libnames.mk index b920d0ceeb..5eaa39e6b7 100644 --- a/share/mk/bsd.libnames.mk +++ b/share/mk/bsd.libnames.mk @@ -74,9 +74,7 @@ LIBPANEL?= ${DESTDIR}${LIBDIR}/priv/libprivate_panel.a LIBPCAP?= ${DESTDIR}${LIBDIR}/libpcap.a LIBPOSIX1E?= ${DESTDIR}${LIBDIR}/libposix1e.a LIBPROP?= ${DESTDIR}${LIBDIR}/libprop.a -LIBPUFFS?= ${DESTDIR}${LIBDIR}/libpuffs.a LIBRADIUS?= ${DESTDIR}${LIBDIR}/libradius.a -LIBREFUSE?= ${DESTDIR}${LIBDIR}/librefuse.a LIBRPCSVC?= ${DESTDIR}${LIBDIR}/librpcsvc.a LIBRT?= ${DESTDIR}${LIBDIR}/librt.a LIBSBUF?= ${DESTDIR}${LIBDIR}/libsbuf.a diff --git a/sys/conf/files b/sys/conf/files index 02bb23a74a..625ff698c6 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1179,7 +1179,6 @@ bus/ppbus/ppb_msq.c optional ppbus bus/ppbus/ppbconf.c optional ppbus dev/misc/ppi/ppi.c optional ppi dev/misc/pps/pps.c optional pps -dev/misc/putter/putter.c optional putter dev/disk/vpo/vpo.c optional vpo dev/disk/vpo/vpoio.c optional vpo dev/crypto/rndtest/rndtest.c optional rndtest @@ -2005,12 +2004,6 @@ vfs/hammer2/zlib/hammer2_zlib_zutil.c optional hammer2 vfs/hammer2/zlib/hammer2_zlib_inftrees.c optional hammer2 vfs/hammer2/zlib/hammer2_zlib_inffast.c optional hammer2 vfs/hammer2/zlib/hammer2_zlib_trees.c optional hammer2 -vfs/puffs/puffs_io.c optional puffs -vfs/puffs/puffs_msgif.c optional puffs -vfs/puffs/puffs_node.c optional puffs -vfs/puffs/puffs_subr.c optional puffs -vfs/puffs/puffs_vfsops.c optional puffs -vfs/puffs/puffs_vnops.c optional puffs vfs/tmpfs/tmpfs_fifoops.c optional tmpfs vfs/tmpfs/tmpfs_subr.c optional tmpfs vfs/tmpfs/tmpfs_vfsops.c optional tmpfs diff --git a/sys/conf/options b/sys/conf/options index 75c7b63a5d..0e3e943676 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -97,7 +97,6 @@ MSDOSFS opt_dontuse.h NTFS opt_dontuse.h NULLFS opt_dontuse.h PROCFS opt_dontuse.h -PUFFS opt_dontuse.h SMBFS opt_dontuse.h TMPFS opt_dontuse.h UDF opt_dontuse.h diff --git a/sys/config/LINT64 b/sys/config/LINT64 index c1db0db7ea..f53e7c5b29 100644 --- a/sys/config/LINT64 +++ b/sys/config/LINT64 @@ -467,7 +467,6 @@ options MSDOSFS #MS DOS filesystem options NTFS #NT filesystem options NULLFS #NULL filesystem options PROCFS #Process filesystem -options PUFFS #Userspace file systems (e.g. ntfs-3g & sshfs) options SMBFS #SMB/CIFS filesystem options TMPFS #Temporary filesystem options UDF #UDF filesystem @@ -717,7 +716,6 @@ pseudo-device pty # Pseudo ttys pseudo-device gzip # Exec gzipped a.out's pseudo-device md # Memory/malloc disk pseudo-device vn # File image "disks" -pseudo-device putter # for puffs and pud pseudo-device snp # Snoop device - to look at pty/vty/etc.. pseudo-device ccd 4 # Concatenated disk driver diff --git a/sys/dev/misc/Makefile b/sys/dev/misc/Makefile index 968c4d97cd..8343967252 100644 --- a/sys/dev/misc/Makefile +++ b/sys/dev/misc/Makefile @@ -1,5 +1,5 @@ SUBDIR= amdsbwd cmx cpuctl dcons ecc ichwd ipmi joy kbdmux led lpbb \ - nmdm pcfclock putter snp syscons tbridge coremctl dimm aperf + nmdm pcfclock snp syscons tbridge coremctl dimm aperf .if ${MACHINE_ARCH} == "x86_64" SUBDIR+=efirt diff --git a/sys/dev/misc/putter/Makefile b/sys/dev/misc/putter/Makefile deleted file mode 100644 index e037dbe2f6..0000000000 --- a/sys/dev/misc/putter/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -KMOD= putter -SRCS= putter.c - -#DEBUG_FLAGS+= -DPUTTERDEBUG - -.include diff --git a/sys/dev/misc/putter/putter.c b/sys/dev/misc/putter/putter.c deleted file mode 100644 index 64fcb4b82e..0000000000 --- a/sys/dev/misc/putter/putter.c +++ /dev/null @@ -1,533 +0,0 @@ -/* $NetBSD: putter.c,v 1.31 2011/02/06 14:29:25 haad Exp $ */ - -/* - * Copyright (c) 2006, 2007 Antti Kantee. All Rights Reserved. - * - * Development of this software was supported by the - * Ulla Tuominen Foundation and the Finnish Cultural Foundation and 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. - */ - -/* - * Pass-to-Userspace TransporTER: generic kernel-user request-response - * transport interface. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -static MALLOC_DEFINE(M_PUTTER, "putter", "Putter device data"); - -/* - * Device routines. These are for when /dev/putter is initially - * opened before it has been cloned. - */ - -static d_open_t puttercdopen; -static d_read_t putter_fop_read; -static d_write_t putter_fop_write; -static d_ioctl_t putter_fop_ioctl; -static d_close_t putter_fop_close; -static d_kqfilter_t putter_fop_kqfilter; - -DEVFS_DEFINE_CLONE_BITMAP(putter); - -/* dev */ -static struct dev_ops putter_ops = { - { "putter", 0, 0 }, - .d_open = puttercdopen, - .d_close = putter_fop_close, - .d_read = putter_fop_read, - .d_write = putter_fop_write, - .d_ioctl = putter_fop_ioctl, - .d_kqfilter = putter_fop_kqfilter, -}; - -#if 0 -/* - * Configuration data. - * - * This is static-size for now. Will be redone for devfs. - */ - -#define PUTTER_CONFSIZE 16 - -static struct putter_config { - int pc_minor; - int (*pc_config)(int, int, int); -} putterconf[PUTTER_CONFSIZE]; - -static int -putter_configure(dev_t dev, int flags, int fmt, int fd) -{ - struct putter_config *pc; - - /* are we the catch-all node? */ - if (minor(dev) == PUTTER_MINOR_WILDCARD - || minor(dev) == PUTTER_MINOR_COMPAT) - return 0; - - /* nopes? try to configure us */ - for (pc = putterconf; pc->pc_config; pc++) - if (minor(dev) == pc->pc_minor) - return pc->pc_config(fd, flags, fmt); - return ENXIO; -} - -int -putter_register(putter_config_fn pcfn, int minor) -{ - int i; - - for (i = 0; i < PUTTER_CONFSIZE; i++) - if (putterconf[i].pc_config == NULL) - break; - if (i == PUTTER_CONFSIZE) - return EBUSY; - - putterconf[i].pc_minor = minor; - putterconf[i].pc_config = pcfn; - return 0; -} -#endif - -/* - * putter instance structures. these are always allocated and freed - * from the context of the transport user. - */ -struct putter_instance { - pid_t pi_pid; - int pi_idx; - struct kqinfo pi_kq; - - void *pi_private; - struct putter_ops *pi_pop; - - uint8_t *pi_curput; - size_t pi_curres; - void *pi_curopaq; - - TAILQ_ENTRY(putter_instance) pi_entries; -}; -#define PUTTER_EMBRYO ((void *)-1) /* before attach */ -#define PUTTER_DEAD ((void *)-2) /* after detach */ - -static TAILQ_HEAD(, putter_instance) putter_ilist - = TAILQ_HEAD_INITIALIZER(putter_ilist); - -#ifdef DEBUG -#ifndef PUTTERDEBUG -#define PUTTERDEBUG -#endif -#endif - -#ifdef PUTTERDEBUG -int putterdebug = 0; -#define DPRINTF(x) if (putterdebug > 0) kprintf x -#define DPRINTF_VERBOSE(x) if (putterdebug > 1) kprintf x -#else -#define DPRINTF(x) -#define DPRINTF_VERBOSE(x) -#endif - -/* - * public init / deinit - */ - -/* protects both the list and the contents of the list elements */ -static struct spinlock pi_mtx = SPINLOCK_INITIALIZER(&pi_mtx, "pi_mtx"); - -/* - * fd routines, for cloner - */ - -static int -putter_fop_read(struct dev_read_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct putter_instance *pi = dev->si_drv1; - struct uio *uio = ap->a_uio; - size_t origres, moved; - int error; - - if (pi->pi_private == PUTTER_EMBRYO || pi->pi_private == PUTTER_DEAD) { - kprintf("putter_fop_read: private %d not inited\n", pi->pi_idx); - return ENOENT; - } - - if (pi->pi_curput == NULL) { - error = pi->pi_pop->pop_getout(pi->pi_private, uio->uio_resid, - ap->a_ioflag & IO_NDELAY, &pi->pi_curput, - &pi->pi_curres, &pi->pi_curopaq); - if (error) { - return error; - } - } - - origres = uio->uio_resid; - error = uiomove(pi->pi_curput, pi->pi_curres, uio); - moved = origres - uio->uio_resid; - DPRINTF(("putter_fop_read (%p): moved %zu bytes from %p, error %d\n", - pi, moved, pi->pi_curput, error)); - - KKASSERT(pi->pi_curres >= moved); - pi->pi_curres -= moved; - pi->pi_curput += moved; - - if (pi->pi_curres == 0) { - pi->pi_pop->pop_releaseout(pi->pi_private, - pi->pi_curopaq, error); - pi->pi_curput = NULL; - } - - return error; -} - -static int -putter_fop_write(struct dev_write_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct putter_instance *pi = dev->si_drv1; - struct uio *uio = ap->a_uio; - struct putter_hdr pth; - uint8_t *buf; - size_t frsize; - int error; - - DPRINTF(("putter_fop_write (%p): writing response, resid %zu\n", - pi->pi_private, uio->uio_resid)); - - if (pi->pi_private == PUTTER_EMBRYO || pi->pi_private == PUTTER_DEAD) { - kprintf("putter_fop_write: putter %d not inited\n", pi->pi_idx); - return ENOENT; - } - - error = uiomove((char *)&pth, sizeof(struct putter_hdr), uio); - if (error) { - return error; - } - - /* Sorry mate, the kernel doesn't buffer. */ - frsize = pth.pth_framelen - sizeof(struct putter_hdr); - if (uio->uio_resid < frsize) { - return EINVAL; - } - - buf = kmalloc(frsize + sizeof(struct putter_hdr), M_PUTTER, M_WAITOK); - memcpy(buf, &pth, sizeof(pth)); - error = uiomove(buf+sizeof(struct putter_hdr), frsize, uio); - if (error == 0) { - pi->pi_pop->pop_dispatch(pi->pi_private, - (struct putter_hdr *)buf); - } - kfree(buf, M_PUTTER); - - return error; -} - -/* - * device close = forced unmount. - * - * unmounting is a frightfully complex operation to avoid races - */ -static int -putter_fop_close(struct dev_close_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct putter_instance *pi = dev->si_drv1; - int rv; - - DPRINTF(("putter_fop_close: device closed\n")); - - restart: - spin_lock(&pi_mtx); - /* - * First check if the driver was never born. In that case - * remove the instance from the list. If mount is attempted later, - * it will simply fail. - */ - if (pi->pi_private == PUTTER_EMBRYO) { - TAILQ_REMOVE(&putter_ilist, pi, pi_entries); - spin_unlock(&pi_mtx); - - DPRINTF(("putter_fop_close: data associated with dev %i was " - "embryonic\n", dev->si_uminor)); - - goto out; - } - - /* - * Next, analyze if unmount was called and the instance is dead. - * In this case we can just free the structure and go home, it - * was removed from the list by putter_rmprivate(). - */ - if (pi->pi_private == PUTTER_DEAD) { - spin_unlock(&pi_mtx); - - DPRINTF(("putter_fop_close: putter associated with dev %d " - "dead, freeing\n", pi->pi_idx)); - - goto out; - } - - /* - * So we have a reference. Proceed to unravel the - * underlying driver. - */ - spin_unlock(&pi_mtx); - - /* hmm? suspicious locking? */ - while ((rv = pi->pi_pop->pop_close(pi->pi_private)) == ERESTART) - goto restart; - - out: - /* - * Finally, release the instance information. It was already - * removed from the list by putter_rmprivate() and we know it's - * dead, so no need to lock. - */ - kfree(pi, M_PUTTER); - - return 0; -} - -static int -putter_fop_ioctl(struct dev_ioctl_args *ap) -{ - - /* - * work already done in sys_ioctl(). skip sanity checks to enable - * setting non-blocking fd on an embryotic driver. - */ - if (ap->a_cmd == FIONBIO) - return 0; - - return EINVAL; -} - -/* kqueue stuff */ - -static void -filt_putterdetach(struct knote *kn) -{ - struct putter_instance *pi = (void *)kn->kn_hook; - struct klist *klist; - - klist = &pi->pi_kq.ki_note; - knote_remove(klist, kn); -} - -static int -filt_putter_rd(struct knote *kn, long hint) -{ - struct putter_instance *pi = (void *)kn->kn_hook; - int error, rv; - - error = 0; - spin_lock(&pi_mtx); - if (pi->pi_private == PUTTER_EMBRYO || pi->pi_private == PUTTER_DEAD) - error = 1; - spin_unlock(&pi_mtx); - if (error) { - return 0; - } - - kn->kn_data = pi->pi_pop->pop_waitcount(pi->pi_private); - rv = kn->kn_data != 0; - return rv; -} - -static int -filt_putter_wr(struct knote *kn, long hint) -{ - /* Writing is always OK */ - kn->kn_data = 0; - return 1; -} - -static struct filterops putter_filtops_rd = - { FILTEROP_ISFD, NULL, filt_putterdetach, filt_putter_rd }; -static struct filterops putter_filtops_wr = - { FILTEROP_ISFD, NULL, filt_putterdetach, filt_putter_wr }; - -static int -putter_fop_kqfilter(struct dev_kqfilter_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct putter_instance *pi = dev->si_drv1; - struct knote *kn = ap->a_kn; - struct klist *klist; - - switch (kn->kn_filter) { - case EVFILT_READ: - kn->kn_fop = &putter_filtops_rd; - kn->kn_hook = (char *)pi; - break; - case EVFILT_WRITE: - kn->kn_fop = &putter_filtops_wr; - kn->kn_hook = (char *)pi; - break; - default: - ap->a_result = EOPNOTSUPP; - return 0; - } - - klist = &pi->pi_kq.ki_note; - knote_insert(klist, kn); - - return 0; -} - -int -puttercdopen(struct dev_open_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct putter_instance *pi; - - pi = kmalloc(sizeof(struct putter_instance), M_PUTTER, - M_WAITOK | M_ZERO); - dev->si_drv1 = pi; - - pi->pi_pid = curproc->p_pid; - pi->pi_idx = dev->si_uminor; - pi->pi_curput = NULL; - pi->pi_curres = 0; - pi->pi_curopaq = NULL; - pi->pi_private = PUTTER_EMBRYO; - - spin_lock(&pi_mtx); - TAILQ_INSERT_TAIL(&putter_ilist, pi, pi_entries); - spin_unlock(&pi_mtx); - - DPRINTF(("puttercdopen: registered embryonic pmp for pid: %d\n", - pi->pi_pid)); - return 0; -} - - -/* - * Set the private structure for the file descriptor. This is - * typically done immediately when the counterpart has knowledge - * about the private structure's address and the file descriptor - * (e.g. vfs mount routine). - * - * We only want to make sure that the caller had the right to open the - * device, we don't so much care about which context it gets in case - * the same process opened multiple (since they are equal at this point). - */ -struct putter_instance * -putter_attach(pid_t pid, int minor, void *ppriv, struct putter_ops *pop) -{ - struct putter_instance *pi = NULL; - - spin_lock(&pi_mtx); - TAILQ_FOREACH(pi, &putter_ilist, pi_entries) { - if (pi->pi_pid == pid && pi->pi_idx == minor && - pi->pi_private == PUTTER_EMBRYO) { - pi->pi_private = ppriv; - pi->pi_pop = pop; - break; - } - } - spin_unlock(&pi_mtx); - - DPRINTF(("putter_setprivate: pi at %p (%d/%d)\n", pi, - pi ? pi->pi_pid : 0, pi ? pi->pi_idx : 0)); - - return pi; -} - -/* - * Remove fp <-> private mapping. - */ -void -putter_detach(struct putter_instance *pi) -{ - - spin_lock(&pi_mtx); - TAILQ_REMOVE(&putter_ilist, pi, pi_entries); - pi->pi_private = PUTTER_DEAD; - spin_unlock(&pi_mtx); - - DPRINTF(("putter_nukebypmp: nuked %p\n", pi)); -} - -void -putter_notify(struct putter_instance *pi) -{ - - KNOTE(&pi->pi_kq.ki_note, 0); -} - -static int -putter_clone(struct dev_clone_args *ap) -{ - int minor; - - minor = devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(putter), 0); - ap->a_dev = make_only_dev(&putter_ops, minor, UID_ROOT, GID_WHEEL, 0600, - "putter%d", minor); - return 0; -} - -static int -putter_modevent(module_t mod, int type, void *data) -{ - switch (type) { - case MOD_LOAD: - make_autoclone_dev(&putter_ops, &DEVFS_CLONE_BITMAP(putter), - putter_clone, UID_ROOT, GID_WHEEL, 0600, "putter"); - break; - case MOD_UNLOAD: - devfs_clone_handler_del("putter"); - dev_ops_remove_all(&putter_ops); - devfs_clone_bitmap_uninit(&DEVFS_CLONE_BITMAP(putter)); - break; - default: - break; - } - return (0); -} - -static moduledata_t putter_mod = { - "putter", - putter_modevent, - NULL -}; -DECLARE_MODULE(putter, putter_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); -MODULE_VERSION(putter, 1); diff --git a/sys/dev/misc/putter/putter.h b/sys/dev/misc/putter/putter.h deleted file mode 100644 index 432c3688b8..0000000000 --- a/sys/dev/misc/putter/putter.h +++ /dev/null @@ -1,40 +0,0 @@ -/* $NetBSD: putter.h,v 1.1 2007/11/12 16:39:33 pooka 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. - */ - -#ifndef _DEV_PUTTER_PUTTER_H_ -#define _DEV_PUTTER_PUTTER_H_ - -#include - -struct putter_hdr { - uint64_t pth_framelen; -}; - -#endif /* _SYS_PUTTER_PUTTER_H_ */ diff --git a/sys/dev/misc/putter/putter_sys.h b/sys/dev/misc/putter/putter_sys.h deleted file mode 100644 index d05b0198fe..0000000000 --- a/sys/dev/misc/putter/putter_sys.h +++ /dev/null @@ -1,68 +0,0 @@ -/* $NetBSD: putter_sys.h,v 1.3 2007/11/20 18:35:22 pooka 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. - */ - -#ifndef _DEV_PUTTER_PUTTERSYS_H_ -#define _DEV_PUTTER_PUTTERSYS_H_ - -#include -#include - -#include - -/* - * Configuration data. - * - * Users of putter currently must be registered statically. This sucks, - * I know, but what are you going to do since you need static allocation - * for /dev nodes anyway. Ok, we could be slightly more forgiving about - * this, but let's just wait for devfs for now. - */ -#define PUTTER_MINOR_WILDCARD 0 -#define PUTTER_MINOR_PUD 1 -#define PUTTER_MINOR_COMPAT 0x7ffff /* will die sometime soon */ - -struct putter_ops { - int (*pop_getout)(void *, size_t, int, uint8_t **,size_t *,void **); - void (*pop_releaseout)(void *, void *, int); - size_t (*pop_waitcount)(void *); - int (*pop_dispatch)(void *, struct putter_hdr *); - int (*pop_close)(void *); -}; - -typedef int (*putter_config_fn)(int, int, int); - -struct putter_instance; -struct putter_instance *putter_attach(pid_t, int, void *, - struct putter_ops *); -void putter_detach(struct putter_instance *); -void putter_notify(struct putter_instance *); -int putter_register(putter_config_fn, int); - -#endif /* _DEV_PUTTER_PUTTERSYS_H_ */ diff --git a/sys/sys/param.h b/sys/sys/param.h index 2beff21a91..da1e0ac5c8 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -191,9 +191,10 @@ * 500400 - 5.4 release * 500500 - 5.5 development * 500501 - reallocarray() added to libc + * 500502 - puffs etc. removed */ #undef __DragonFly_version -#define __DragonFly_version 500501 /* propagated to newvers */ +#define __DragonFly_version 500502 /* propagated to newvers */ #include diff --git a/sys/vfs/Makefile b/sys/vfs/Makefile index e818b340e7..5459457253 100644 --- a/sys/vfs/Makefile +++ b/sys/vfs/Makefile @@ -1,7 +1,7 @@ # Makefile for vfs modules # -SUBDIR=fifofs msdosfs nfs procfs puffs \ +SUBDIR= fifofs msdosfs nfs procfs \ hpfs ntfs smbfs isofs mfs udf \ nullfs hammer tmpfs autofs diff --git a/sys/vfs/puffs/Makefile b/sys/vfs/puffs/Makefile deleted file mode 100644 index f5765eaaac..0000000000 --- a/sys/vfs/puffs/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -KMOD= puffs -SRCS= puffs_msgif.c puffs_node.c puffs_subr.c \ - puffs_vfsops.c puffs_vnops.c puffs_io.c - -#DEBUG_FLAGS+= -DPUFFSDEBUG - -.include diff --git a/sys/vfs/puffs/puffs_io.c b/sys/vfs/puffs/puffs_io.c deleted file mode 100644 index 0f51fb271b..0000000000 --- a/sys/vfs/puffs/puffs_io.c +++ /dev/null @@ -1,587 +0,0 @@ -/* $NetBSD: puffs_vnops.c,v 1.154 2011/07/04 08:07:30 manu 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define RWARGS(cont, iofl, move, offset, creds) \ - (cont)->pvnr_ioflag = (iofl); \ - (cont)->pvnr_resid = (move); \ - (cont)->pvnr_offset = (offset); \ - puffs_credcvt(&(cont)->pvnr_cred, creds) - -int -puffs_directread(struct vnode *vp, struct uio *uio, int ioflag, - struct ucred *cred) -{ - PUFFS_MSG_VARS(vn, read); - struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); - size_t tomove, argsize; - int error; - - KKASSERT(vp->v_type == VREG); - - if (uio->uio_offset < 0) - return EINVAL; - if (uio->uio_resid == 0) - return 0; - - read_msg = NULL; - error = 0; - - /* std sanity */ - if (uio->uio_resid == 0) - return 0; - if (uio->uio_offset < 0) - return EINVAL; - - /* - * in case it's not a regular file or we're operating - * uncached, do read in the old-fashioned style, - * i.e. explicit read operations - */ - - tomove = PUFFS_TOMOVE(uio->uio_resid, pmp); - argsize = sizeof(struct puffs_vnmsg_read); - puffs_msgmem_alloc(argsize + tomove, &park_read, - (void *)&read_msg, 1); - - error = 0; - while (uio->uio_resid > 0) { - tomove = PUFFS_TOMOVE(uio->uio_resid, pmp); - memset(read_msg, 0, argsize); /* XXX: touser KASSERT */ - RWARGS(read_msg, ioflag, tomove, - uio->uio_offset, cred); - puffs_msg_setinfo(park_read, PUFFSOP_VN, - PUFFS_VN_READ, VPTOPNC(vp)); - puffs_msg_setdelta(park_read, tomove); - - PUFFS_MSG_ENQUEUEWAIT2(pmp, park_read, vp->v_data, - NULL, error); - error = checkerr(pmp, error, __func__); - if (error) - break; - - if (read_msg->pvnr_resid > tomove) { - puffs_senderr(pmp, PUFFS_ERR_READ, - E2BIG, "resid grew", VPTOPNC(vp)); - error = EPROTO; - break; - } - - error = uiomove(read_msg->pvnr_data, - tomove - read_msg->pvnr_resid, uio); - - /* - * in case the file is out of juice, resid from - * userspace is != 0. and the error-case is - * quite obvious - */ - if (error || read_msg->pvnr_resid) - break; - } - - puffs_msgmem_release(park_read); - - return error; -} - -int -puffs_directwrite(struct vnode *vp, struct uio *uio, int ioflag, - struct ucred *cred) -{ - PUFFS_MSG_VARS(vn, write); - struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); - size_t tomove, argsize; - int error, uflags; - - KKASSERT(vp->v_type == VREG); - - if (uio->uio_offset < 0) - return EINVAL; - if (uio->uio_resid == 0) - return 0; - - error = uflags = 0; - write_msg = NULL; - - /* tomove is non-increasing */ - tomove = PUFFS_TOMOVE(uio->uio_resid, pmp); - argsize = sizeof(struct puffs_vnmsg_write) + tomove; - puffs_msgmem_alloc(argsize, &park_write, (void *)&write_msg,1); - - while (uio->uio_resid > 0) { - /* move data to buffer */ - tomove = PUFFS_TOMOVE(uio->uio_resid, pmp); - memset(write_msg, 0, argsize); /* XXX: touser KASSERT */ - RWARGS(write_msg, ioflag, tomove, - uio->uio_offset, cred); - error = uiomove(write_msg->pvnr_data, tomove, uio); - if (error) - break; - - /* move buffer to userspace */ - puffs_msg_setinfo(park_write, PUFFSOP_VN, - PUFFS_VN_WRITE, VPTOPNC(vp)); - PUFFS_MSG_ENQUEUEWAIT2(pmp, park_write, vp->v_data, - NULL, error); - error = checkerr(pmp, error, __func__); - if (error) - break; - - if (write_msg->pvnr_resid > tomove) { - puffs_senderr(pmp, PUFFS_ERR_WRITE, - E2BIG, "resid grew", VPTOPNC(vp)); - error = EPROTO; - break; - } - - if (PUFFS_USE_PAGECACHE(pmp)) - KKASSERT(vp->v_filesize >= uio->uio_offset); - - /* didn't move everything? bad userspace. bail */ - if (write_msg->pvnr_resid != 0) { - error = EIO; - break; - } - } - puffs_msgmem_release(park_write); - - return error; -} - -static void -puffs_iodone(struct bio *bio) -{ - bio->bio_flags = 0; - bpdone(bio->bio_buf, 0); -} - -int -puffs_bioread(struct vnode *vp, struct uio *uio, int ioflag, - struct ucred *cred) -{ - int biosize = vp->v_mount->mnt_stat.f_iosize; - struct buf *bp; - struct vattr vattr; - off_t lbn, loffset, fsize; - size_t n; - int boff; - int error = 0; - - KKASSERT(uio->uio_rw == UIO_READ); - KKASSERT(vp->v_type == VREG); - - if (uio->uio_offset < 0) - return EINVAL; - if (uio->uio_resid == 0) - return 0; - - /* - * Cache consistency can only be maintained approximately. - * - * GETATTR is called to synchronize the file size. - * - * NOTE: In the normal case the attribute cache is not - * cleared which means GETATTR may use cached data and - * not immediately detect changes made on the server. - */ - - error = VOP_GETATTR(vp, &vattr); - if (error) - return error; - - /* - * Loop until uio exhausted or we hit EOF - */ - do { - bp = NULL; - - lbn = uio->uio_offset / biosize; - boff = uio->uio_offset & (biosize - 1); - loffset = lbn * biosize; - fsize = puffs_meta_getsize(vp); - - if (loffset + boff >= fsize) { - n = 0; - break; - } - bp = getblk(vp, loffset, biosize, 0, 0); - - if (bp == NULL) - return EINTR; - - /* - * If B_CACHE is not set, we must issue the read. If this - * fails, we return an error. - */ - if ((bp->b_flags & B_CACHE) == 0) { - bp->b_cmd = BUF_CMD_READ; - bp->b_bio2.bio_done = puffs_iodone; - bp->b_bio2.bio_flags |= BIO_SYNC; - vfs_busy_pages(vp, bp); - error = puffs_doio(vp, &bp->b_bio2, uio->uio_td); - if (error) { - brelse(bp); - return error; - } - } - - /* - * on is the offset into the current bp. Figure out how many - * bytes we can copy out of the bp. Note that bcount is - * NOT DEV_BSIZE aligned. - * - * Then figure out how many bytes we can copy into the uio. - */ - n = biosize - boff; - if (n > uio->uio_resid) - n = uio->uio_resid; - if (loffset + boff + n > fsize) - n = fsize - loffset - boff; - - if (n > 0) - error = uiomove(bp->b_data + boff, n, uio); - if (bp) - brelse(bp); - } while (error == 0 && uio->uio_resid > 0 && n > 0); - - return error; -} - -int -puffs_biowrite(struct vnode *vp, struct uio *uio, int ioflag, - struct ucred *cred) -{ - int biosize = vp->v_mount->mnt_stat.f_iosize; - struct buf *bp; - struct vattr vattr; - off_t loffset, fsize; - int boff, bytes; - int error = 0; - int bcount; - int trivial; - - KKASSERT(uio->uio_rw == UIO_WRITE); - KKASSERT(vp->v_type == VREG); - - if (uio->uio_offset < 0) - return EINVAL; - if (uio->uio_resid == 0) - return 0; - - /* - * If IO_APPEND then load uio_offset. We restart here if we cannot - * get the append lock. - * - * We need to obtain exclusize lock if we intend to modify file size - * in order to guarentee the append point with multiple contending - * writers. - */ - if (ioflag & IO_APPEND) { - /* XXXDF relock if necessary */ - KKASSERT(vn_islocked(vp) == LK_EXCLUSIVE); - error = VOP_GETATTR(vp, &vattr); - if (error) - return error; - uio->uio_offset = puffs_meta_getsize(vp); - } - - do { - boff = uio->uio_offset & (biosize-1); - loffset = uio->uio_offset - boff; - bytes = (int)szmin((unsigned)(biosize - boff), uio->uio_resid); -again: - /* - * Handle direct append and file extension cases, calculate - * unaligned buffer size. When extending B_CACHE will be - * set if possible. See UIO_NOCOPY note below. - */ - fsize = puffs_meta_getsize(vp); - if (uio->uio_offset + bytes > fsize) { - trivial = (uio->uio_segflg != UIO_NOCOPY && - uio->uio_offset <= fsize); - puffs_meta_setsize(vp, uio->uio_offset + bytes, - trivial); - } - bp = getblk(vp, loffset, biosize, 0, 0); - if (bp == NULL) { - error = EINTR; - break; - } - - /* - * Actual bytes in buffer which we care about - */ - if (loffset + biosize < fsize) - bcount = biosize; - else - bcount = (int)(fsize - loffset); - - /* - * Avoid a read by setting B_CACHE where the data we - * intend to write covers the entire buffer. Note - * that the buffer may have been set to B_CACHE by - * puffs_meta_setsize() above or otherwise inherited the - * flag, but if B_CACHE isn't set the buffer may be - * uninitialized and must be zero'd to accomodate - * future seek+write's. - * - * See the comments in kern/vfs_bio.c's getblk() for - * more information. - * - * When doing a UIO_NOCOPY write the buffer is not - * overwritten and we cannot just set B_CACHE unconditionally - * for full-block writes. - */ - if (boff == 0 && bytes == biosize && - uio->uio_segflg != UIO_NOCOPY) { - bp->b_flags |= B_CACHE; - bp->b_flags &= ~(B_ERROR | B_INVAL); - } - - /* - * b_resid may be set due to file EOF if we extended out. - * The NFS bio code will zero the difference anyway so - * just acknowledged the fact and set b_resid to 0. - */ - if ((bp->b_flags & B_CACHE) == 0) { - bp->b_cmd = BUF_CMD_READ; - bp->b_bio2.bio_done = puffs_iodone; - bp->b_bio2.bio_flags |= BIO_SYNC; - vfs_busy_pages(vp, bp); - error = puffs_doio(vp, &bp->b_bio2, uio->uio_td); - if (error) { - brelse(bp); - break; - } - bp->b_resid = 0; - } - - /* - * If dirtyend exceeds file size, chop it down. This should - * not normally occur but there is an append race where it - * might occur XXX, so we log it. - * - * If the chopping creates a reverse-indexed or degenerate - * situation with dirtyoff/end, we 0 both of them. - */ - if (bp->b_dirtyend > bcount) { - kprintf("PUFFS append race @%08llx:%d\n", - (long long)bp->b_bio2.bio_offset, - bp->b_dirtyend - bcount); - bp->b_dirtyend = bcount; - } - - if (bp->b_dirtyoff >= bp->b_dirtyend) - bp->b_dirtyoff = bp->b_dirtyend = 0; - - /* - * If the new write will leave a contiguous dirty - * area, just update the b_dirtyoff and b_dirtyend, - * otherwise force a write rpc of the old dirty area. - * - * While it is possible to merge discontiguous writes due to - * our having a B_CACHE buffer ( and thus valid read data - * for the hole), we don't because it could lead to - * significant cache coherency problems with multiple clients, - * especially if locking is implemented later on. - * - * as an optimization we could theoretically maintain - * a linked list of discontinuous areas, but we would still - * have to commit them separately so there isn't much - * advantage to it except perhaps a bit of asynchronization. - */ - if (bp->b_dirtyend > 0 && - (boff > bp->b_dirtyend || - (boff + bytes) < bp->b_dirtyoff) - ) { - if (bwrite(bp) == EINTR) { - error = EINTR; - break; - } - goto again; - } - - error = uiomove(bp->b_data + boff, bytes, uio); - - /* - * Since this block is being modified, it must be written - * again and not just committed. Since write clustering does - * not work for the stage 1 data write, only the stage 2 - * commit rpc, we have to clear B_CLUSTEROK as well. - */ - bp->b_flags &= ~(B_NEEDCOMMIT | B_CLUSTEROK); - - if (error) { - brelse(bp); - break; - } - - /* - * Only update dirtyoff/dirtyend if not a degenerate - * condition. - * - * The underlying VM pages have been marked valid by - * virtue of acquiring the bp. Because the entire buffer - * is marked dirty we do not have to worry about cleaning - * out the related dirty bits (and wouldn't really know - * how to deal with byte ranges anyway) - */ - if (bytes) { - if (bp->b_dirtyend > 0) { - bp->b_dirtyoff = imin(boff, bp->b_dirtyoff); - bp->b_dirtyend = imax(boff + bytes, - bp->b_dirtyend); - } else { - bp->b_dirtyoff = boff; - bp->b_dirtyend = boff + bytes; - } - } - - if (ioflag & IO_SYNC) { - if (ioflag & IO_INVAL) - bp->b_flags |= B_NOCACHE; - error = bwrite(bp); - if (error) - break; - } else { - bdwrite(bp); - } - } while (uio->uio_resid > 0 && bytes > 0); - - return error; -} - -int -puffs_doio(struct vnode *vp, struct bio *bio, struct thread *td) -{ - struct buf *bp = bio->bio_buf; - struct ucred *cred; - struct uio *uiop; - struct uio uio; - struct iovec io; - size_t n; - int error = 0; - - if (td != NULL && td->td_proc != NULL) - cred = td->td_proc->p_ucred; - else - cred = proc0.p_ucred; - - uiop = &uio; - uiop->uio_iov = &io; - uiop->uio_iovcnt = 1; - uiop->uio_segflg = UIO_SYSSPACE; - uiop->uio_td = td; - - /* - * clear B_ERROR and B_INVAL state prior to initiating the I/O. We - * do this here so we do not have to do it in all the code that - * calls us. - */ - bp->b_flags &= ~(B_ERROR | B_INVAL); - - KASSERT(bp->b_cmd != BUF_CMD_DONE, - ("puffs_doio: bp %p already marked done!", bp)); - - if (bp->b_cmd == BUF_CMD_READ) { - io.iov_len = uiop->uio_resid = (size_t)bp->b_bcount; - io.iov_base = bp->b_data; - uiop->uio_rw = UIO_READ; - - uiop->uio_offset = bio->bio_offset; - error = puffs_directread(vp, uiop, 0, cred); - if (error == 0 && uiop->uio_resid) { - n = (size_t)bp->b_bcount - uiop->uio_resid; - bzero(bp->b_data + n, bp->b_bcount - n); - uiop->uio_resid = 0; - } - if (error) { - bp->b_flags |= B_ERROR; - bp->b_error = error; - } - bp->b_resid = uiop->uio_resid; - } else { - KKASSERT(bp->b_cmd == BUF_CMD_WRITE); - if (bio->bio_offset + bp->b_dirtyend > puffs_meta_getsize(vp)) - bp->b_dirtyend = puffs_meta_getsize(vp) - - bio->bio_offset; - - if (bp->b_dirtyend > bp->b_dirtyoff) { - io.iov_len = uiop->uio_resid = bp->b_dirtyend - - bp->b_dirtyoff; - uiop->uio_offset = bio->bio_offset + bp->b_dirtyoff; - io.iov_base = (char *)bp->b_data + bp->b_dirtyoff; - uiop->uio_rw = UIO_WRITE; - - error = puffs_directwrite(vp, uiop, 0, cred); - - if (error == EINTR - || (!error && (bp->b_flags & B_NEEDCOMMIT))) { - crit_enter(); - bp->b_flags &= ~(B_INVAL|B_NOCACHE); - if ((bp->b_flags & B_PAGING) == 0) - bdirty(bp); - if (error) - bp->b_flags |= B_EINTR; - crit_exit(); - } else { - if (error) { - bp->b_flags |= B_ERROR; - bp->b_error = error; - } - bp->b_dirtyoff = bp->b_dirtyend = 0; - } - bp->b_resid = uiop->uio_resid; - } else { - bp->b_resid = 0; - } - } - - biodone(bio); - KKASSERT(bp->b_cmd == BUF_CMD_DONE); - if (bp->b_flags & B_EINTR) - return (EINTR); - if (bp->b_flags & B_ERROR) - return (bp->b_error ? bp->b_error : EIO); - return (0); -} diff --git a/sys/vfs/puffs/puffs_msgif.c b/sys/vfs/puffs/puffs_msgif.c deleted file mode 100644 index 24a4871180..0000000000 --- a/sys/vfs/puffs/puffs_msgif.c +++ /dev/null @@ -1,1199 +0,0 @@ -/* $NetBSD: puffs_msgif.c,v 1.87 2011/07/03 08:57:43 mrg 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/* - * waitq data structures - */ - -/* - * While a request is going to userspace, park the caller within the - * kernel. This is the kernel counterpart of "struct puffs_req". - */ -struct puffs_msgpark { - struct puffs_req *park_preq; /* req followed by buf */ - - size_t park_copylen; /* userspace copylength */ - size_t park_maxlen; /* max size in comeback */ - - struct puffs_req *park_creq; /* non-compat preq */ - size_t park_creqlen; /* non-compat preq len */ - - parkdone_fn park_done; /* "biodone" a'la puffs */ - void *park_donearg; - - int park_flags; - int park_refcount; - - struct cv park_cv; - struct lock park_mtx; - - TAILQ_ENTRY(puffs_msgpark) park_entries; -}; -#define PARKFLAG_WAITERGONE 0x01 -#define PARKFLAG_DONE 0x02 -#define PARKFLAG_ONQUEUE1 0x04 -#define PARKFLAG_ONQUEUE2 0x08 -#define PARKFLAG_CALL 0x10 -#define PARKFLAG_WANTREPLY 0x20 -#define PARKFLAG_HASERROR 0x40 - -static struct objcache *parkpc; -#ifdef PUFFSDEBUG -static int totalpark; -#endif - -static boolean_t -makepark(void *obj, void *privdata, int flags) -{ - struct puffs_msgpark *park = obj; - - lockinit(&park->park_mtx, "puffs park_mtx", 0, 0); - cv_init(&park->park_cv, "puffsrpl"); - - return TRUE; -} - -static void -nukepark(void *obj, void *privdata) -{ - struct puffs_msgpark *park = obj; - - cv_destroy(&park->park_cv); - lockuninit(&park->park_mtx); -} - -void -puffs_msgif_init(void) -{ - - parkpc = objcache_create_mbacked(M_PUFFS, sizeof(struct puffs_msgpark), - 0, 0, makepark, nukepark, NULL); -} - -void -puffs_msgif_destroy(void) -{ - - objcache_destroy(parkpc); -} - -static struct puffs_msgpark * -puffs_msgpark_alloc(int waitok) -{ - struct puffs_msgpark *park; - - park = objcache_get(parkpc, waitok ? M_WAITOK : M_NOWAIT); - if (park == NULL) - return park; - - park->park_refcount = 1; - park->park_preq = park->park_creq = NULL; - park->park_flags = PARKFLAG_WANTREPLY; - -#ifdef PUFFSDEBUG - totalpark++; -#endif - - return park; -} - -static void -puffs_msgpark_reference(struct puffs_msgpark *park) -{ - - KKASSERT(lockstatus(&park->park_mtx, curthread) == LK_EXCLUSIVE); - park->park_refcount++; -} - -/* - * Release reference to park structure. - */ -static void -puffs_msgpark_release1(struct puffs_msgpark *park, int howmany) -{ - struct puffs_req *preq = park->park_preq; - struct puffs_req *creq = park->park_creq; - int refcnt; - - KKASSERT(lockstatus(&park->park_mtx, curthread) == LK_EXCLUSIVE); - refcnt = park->park_refcount -= howmany; - lockmgr(&park->park_mtx, LK_RELEASE); - - KKASSERT(refcnt >= 0); - - if (refcnt == 0) { - if (preq) - kfree(preq, M_PUFFS); -#if 1 - if (creq) - kfree(creq, M_PUFFS); -#endif - objcache_put(parkpc, park); - -#ifdef PUFFSDEBUG - totalpark--; -#endif - } -} -#define puffs_msgpark_release(a) puffs_msgpark_release1(a, 1) - -#ifdef PUFFSDEBUG -static void -parkdump(struct puffs_msgpark *park) -{ - - DPRINTF_VERBOSE(("park %p, preq %p, id %" PRIu64 "\n" - "\tcopy %zu, max %zu - done: %p/%p\n" - "\tflags 0x%08x, refcount %d, cv/mtx: %p/%p\n", - park, park->park_preq, park->park_preq->preq_id, - park->park_copylen, park->park_maxlen, - park->park_done, park->park_donearg, - park->park_flags, park->park_refcount, - &park->park_cv, &park->park_mtx)); -} - -static void -parkqdump(struct puffs_wq *q, int dumpall) -{ - struct puffs_msgpark *park; - int total = 0; - - TAILQ_FOREACH(park, q, park_entries) { - if (dumpall) - parkdump(park); - total++; - } - DPRINTF_VERBOSE(("puffs waitqueue at %p dumped, %d total\n", q, total)); - -} -#endif /* PUFFSDEBUG */ - -/* - * A word about locking in the park structures: the lock protects the - * fields of the *park* structure (not preq) and acts as an interlock - * in cv operations. The lock is always internal to this module and - * callers do not need to worry about it. - */ - -int -puffs_msgmem_alloc(size_t len, struct puffs_msgpark **ppark, void **mem, - int cansleep) -{ - struct puffs_msgpark *park; - void *m; - - m = kmalloc(len, M_PUFFS, M_ZERO | (cansleep ? M_WAITOK : M_NOWAIT)); - if (m == NULL) { - KKASSERT(cansleep == 0); - return ENOMEM; - } - - park = puffs_msgpark_alloc(cansleep); - if (park == NULL) { - KKASSERT(cansleep == 0); - kfree(m, M_PUFFS); - return ENOMEM; - } - - park->park_preq = m; - park->park_maxlen = park->park_copylen = len; - - *ppark = park; - *mem = m; - - return 0; -} - -void -puffs_msgmem_release(struct puffs_msgpark *park) -{ - - if (park == NULL) - return; - - lockmgr(&park->park_mtx, LK_EXCLUSIVE); - puffs_msgpark_release(park); -} - -void -puffs_msg_setfaf(struct puffs_msgpark *park) -{ - - KKASSERT((park->park_flags & PARKFLAG_CALL) == 0); - park->park_flags &= ~PARKFLAG_WANTREPLY; -} - -void -puffs_msg_setdelta(struct puffs_msgpark *park, size_t delta) -{ - - KKASSERT(delta < park->park_maxlen); /* "<=" wouldn't make sense */ - park->park_copylen = park->park_maxlen - delta; -} - -void -puffs_msg_setinfo(struct puffs_msgpark *park, int class, int type, - puffs_cookie_t ck) -{ - - park->park_preq->preq_opclass = PUFFSOP_OPCLASS(class); - park->park_preq->preq_optype = type; - park->park_preq->preq_cookie = ck; -} - -void -puffs_msg_setcall(struct puffs_msgpark *park, parkdone_fn donefn, void *donearg) -{ - - KKASSERT(park->park_flags & PARKFLAG_WANTREPLY); - park->park_done = donefn; - park->park_donearg = donearg; - park->park_flags |= PARKFLAG_CALL; -} - -/* - * kernel-user-kernel waitqueues - */ - -static uint64_t -puffs_getmsgid(struct puffs_mount *pmp) -{ - uint64_t rv; - - lockmgr(&pmp->pmp_lock, LK_EXCLUSIVE); - rv = pmp->pmp_nextmsgid++; - lockmgr(&pmp->pmp_lock, LK_RELEASE); - - return rv; -} - -/* - * A word about reference counting of parks. A reference must be taken - * when accessing a park and additionally when it is on a queue. So - * when taking it off a queue and releasing the access reference, the - * reference count is generally decremented by 2. - */ - -void -puffs_msg_enqueue(struct puffs_mount *pmp, struct puffs_msgpark *park) -{ - struct thread *td = curthread; - struct puffs_req *preq; - sigset_t ss; - - /* - * Some clients reuse a park, so reset some flags. We might - * want to provide a caller-side interface for this and add - * a few more invariant checks here, but this will do for now. - */ - KKASSERT(pmp != NULL && park != NULL); - park->park_flags &= ~(PARKFLAG_DONE | PARKFLAG_HASERROR); - KKASSERT((park->park_flags & PARKFLAG_WAITERGONE) == 0); - - preq = park->park_preq; - - preq->preq_buflen = park->park_maxlen; - KKASSERT(preq->preq_id == 0 - || (preq->preq_opclass & PUFFSOPFLAG_ISRESPONSE)); - - if ((park->park_flags & PARKFLAG_WANTREPLY) == 0) - preq->preq_opclass |= PUFFSOPFLAG_FAF; - else - preq->preq_id = puffs_getmsgid(pmp); - - /* fill in caller information */ - if (td->td_proc == NULL || td->td_lwp == NULL) { - DPRINTF_VERBOSE(("puffs_msg_enqueue: no process\n")); - preq->preq_pid = 1; - preq->preq_lid = 0; - goto noproc; - } - preq->preq_pid = td->td_proc->p_pid; - preq->preq_lid = td->td_lwp->lwp_tid; - - /* - * To support cv_sig, yet another movie: check if there are signals - * pending and we are issueing a non-FAF. If so, return an error - * directly UNLESS we are issueing INACTIVE/RECLAIM. In that case, - * convert it to a FAF, fire off to the file server and return - * an error. Yes, this is bordering disgusting. Barfbags are on me. - */ - ss = lwp_sigpend(td->td_lwp); - SIGSETNAND(ss, td->td_lwp->lwp_sigmask); - if (__predict_false((park->park_flags & PARKFLAG_WANTREPLY) - && (park->park_flags & PARKFLAG_CALL) == 0 - && SIGNOTEMPTY(ss))) { - - /* - * see the comment about signals in puffs_msg_wait. - */ - if (SIGISMEMBER(ss, SIGINT) || - SIGISMEMBER(ss, SIGTERM) || - SIGISMEMBER(ss, SIGKILL) || - SIGISMEMBER(ss, SIGHUP) || - SIGISMEMBER(ss, SIGQUIT)) { - park->park_flags |= PARKFLAG_HASERROR; - preq->preq_rv = EINTR; - if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN - && (preq->preq_optype == PUFFS_VN_INACTIVE - || preq->preq_optype == PUFFS_VN_RECLAIM)) { - park->park_preq->preq_opclass |= - PUFFSOPFLAG_FAF; - park->park_flags &= ~PARKFLAG_WANTREPLY; - DPRINTF_VERBOSE(("puffs_msg_enqueue: " - "converted to FAF %p\n", park)); - } else { - return; - } - } - } - - noproc: - lockmgr(&pmp->pmp_lock, LK_EXCLUSIVE); - if (pmp->pmp_status != PUFFSTAT_RUNNING) { - lockmgr(&pmp->pmp_lock, LK_RELEASE); - park->park_flags |= PARKFLAG_HASERROR; - preq->preq_rv = ENXIO; - return; - } - -#ifdef PUFFSDEBUG - parkqdump(&pmp->pmp_msg_touser, puffsdebug > 1); - parkqdump(&pmp->pmp_msg_replywait, puffsdebug > 1); -#endif - - /* - * Note: we don't need to lock park since we have the only - * reference to it at this point. - */ - TAILQ_INSERT_TAIL(&pmp->pmp_msg_touser, park, park_entries); - park->park_flags |= PARKFLAG_ONQUEUE1; - pmp->pmp_msg_touser_count++; - park->park_refcount++; - lockmgr(&pmp->pmp_lock, LK_RELEASE); - - cv_broadcast(&pmp->pmp_msg_waiter_cv); - putter_notify(pmp->pmp_pi); - - DPRINTF_VERBOSE(("touser: req %" PRIu64 ", preq: %p, park: %p, " - "c/t: 0x%x/0x%x, f: 0x%x\n", preq->preq_id, preq, park, - preq->preq_opclass, preq->preq_optype, park->park_flags)); -} - -int -puffs_msg_wait(struct puffs_mount *pmp, struct puffs_msgpark *park) -{ - struct puffs_req *preq = park->park_preq; /* XXX: hmmm */ -#ifdef XXXDF - struct lwp *l = curthread->td_lwp; - struct proc *p = curthread->td_proc; - sigset_t ss; - sigset_t oss; -#endif - int error = 0; - int rv; - - KKASSERT(pmp != NULL && park != NULL); - - /* - * block unimportant signals. - * - * The set of "important" signals here was chosen to be same as - * nfs interruptible mount. - */ -#ifdef XXXDF - SIGFILLSET(ss); - SIGDELSET(ss, SIGINT); - SIGDELSET(ss, SIGTERM); - SIGDELSET(ss, SIGKILL); - SIGDELSET(ss, SIGHUP); - SIGDELSET(ss, SIGQUIT); - lockmgr(p->p_lock, LK_EXCLUSIVE); - sigprocmask1(l, SIG_BLOCK, &ss, &oss); - lockmgr(p->p_lock, LK_RELEASE); -#endif - - lockmgr(&pmp->pmp_lock, LK_EXCLUSIVE); - puffs_mp_reference(pmp); - lockmgr(&pmp->pmp_lock, LK_RELEASE); - - lockmgr(&park->park_mtx, LK_EXCLUSIVE); - /* did the response beat us to the wait? */ - if (__predict_false((park->park_flags & PARKFLAG_DONE) - || (park->park_flags & PARKFLAG_HASERROR))) { - rv = park->park_preq->preq_rv; - lockmgr(&park->park_mtx, LK_RELEASE); - goto skipwait; - } - - if ((park->park_flags & PARKFLAG_WANTREPLY) == 0 - || (park->park_flags & PARKFLAG_CALL)) { - lockmgr(&park->park_mtx, LK_RELEASE); - rv = 0; - goto skipwait; - } - - error = cv_wait_sig(&park->park_cv, &park->park_mtx); - DPRINTF_VERBOSE(("puffs_touser: waiter for %p woke up with %d\n", - park, error)); - if (error) { - park->park_flags |= PARKFLAG_WAITERGONE; - if (park->park_flags & PARKFLAG_DONE) { - rv = preq->preq_rv; - lockmgr(&park->park_mtx, LK_RELEASE); - } else { - /* - * ok, we marked it as going away, but - * still need to do queue ops. take locks - * in correct order. - * - * We don't want to release our reference - * if it's on replywait queue to avoid error - * to file server. putop() code will DTRT. - */ - lockmgr(&park->park_mtx, LK_RELEASE); - lockmgr(&pmp->pmp_lock, LK_EXCLUSIVE); - lockmgr(&park->park_mtx, LK_EXCLUSIVE); - - /* - * Still on queue1? We can safely remove it - * without any consequences since the file - * server hasn't seen it. "else" we need to - * wait for the response and just ignore it - * to avoid signalling an incorrect error to - * the file server. - */ - if (park->park_flags & PARKFLAG_ONQUEUE1) { - TAILQ_REMOVE(&pmp->pmp_msg_touser, - park, park_entries); - puffs_msgpark_release(park); - pmp->pmp_msg_touser_count--; - park->park_flags &= ~PARKFLAG_ONQUEUE1; - } else { - lockmgr(&park->park_mtx, LK_RELEASE); - } - lockmgr(&pmp->pmp_lock, LK_RELEASE); - - rv = EINTR; - } - } else { - rv = preq->preq_rv; - lockmgr(&park->park_mtx, LK_RELEASE); - } - - skipwait: - lockmgr(&pmp->pmp_lock, LK_EXCLUSIVE); - puffs_mp_release(pmp); - lockmgr(&pmp->pmp_lock, LK_RELEASE); - -#ifdef XXXDF - lockmgr(p->p_lock, LK_EXCLUSIVE); - sigprocmask1(l, SIG_SETMASK, &oss, NULL); - lockmgr(p->p_lock, LK_RELEASE); -#endif - - return rv; -} - -/* - * XXX: this suuuucks. Hopefully I'll get rid of this lossage once - * the whole setback-nonsense gets fixed. - */ -int -puffs_msg_wait2(struct puffs_mount *pmp, struct puffs_msgpark *park, - struct puffs_node *pn1, struct puffs_node *pn2) -{ - struct puffs_req *preq; - int rv; - - rv = puffs_msg_wait(pmp, park); - - preq = park->park_preq; - if (pn1 && preq->preq_setbacks & PUFFS_SETBACK_INACT_N1) - pn1->pn_stat |= PNODE_DOINACT; - if (pn2 && preq->preq_setbacks & PUFFS_SETBACK_INACT_N2) - pn2->pn_stat |= PNODE_DOINACT; - - if (pn1 && preq->preq_setbacks & PUFFS_SETBACK_NOREF_N1) - pn1->pn_stat |= PNODE_NOREFS; - if (pn2 && preq->preq_setbacks & PUFFS_SETBACK_NOREF_N2) - pn2->pn_stat |= PNODE_NOREFS; - - return rv; - -} - -/* - * XXX: lazy bum. please, for the love of foie gras, fix me. - * This should *NOT* depend on setfaf. Also "memcpy" could - * be done more nicely. - */ -void -puffs_msg_sendresp(struct puffs_mount *pmp, struct puffs_req *origpreq, int rv) -{ - struct puffs_msgpark *park; - struct puffs_req *preq; - - puffs_msgmem_alloc(sizeof(struct puffs_req), &park, (void *)&preq, 1); - puffs_msg_setfaf(park); /* XXXXXX: avoids reqid override */ - - memcpy(preq, origpreq, sizeof(struct puffs_req)); - preq->preq_rv = rv; - preq->preq_opclass |= PUFFSOPFLAG_ISRESPONSE; - - puffs_msg_enqueue(pmp, park); - puffs_msgmem_release(park); -} - -/* - * Get next request in the outgoing queue. "maxsize" controls the - * size the caller can accommodate and "nonblock" signals if this - * should block while waiting for input. Handles all locking internally. - */ -int -puffs_msgif_getout(void *this, size_t maxsize, int nonblock, - uint8_t **data, size_t *dlen, void **parkptr) -{ - struct puffs_mount *pmp = this; - struct puffs_msgpark *park = NULL; - struct puffs_req *preq = NULL; - int error; - - error = 0; - lockmgr(&pmp->pmp_lock, LK_EXCLUSIVE); - puffs_mp_reference(pmp); - for (;;) { - /* RIP? */ - if (pmp->pmp_status != PUFFSTAT_RUNNING) { - error = ENXIO; - break; - } - - /* need platinum yendorian express card? */ - if (TAILQ_EMPTY(&pmp->pmp_msg_touser)) { - DPRINTF_VERBOSE(("puffs_getout: no outgoing op, ")); - if (nonblock) { - DPRINTF_VERBOSE(("returning EWOULDBLOCK\n")); - error = EWOULDBLOCK; - break; - } - DPRINTF_VERBOSE(("waiting ...\n")); - - error = cv_wait_sig(&pmp->pmp_msg_waiter_cv, - &pmp->pmp_lock); - if (error) - break; - else - continue; - } - - park = TAILQ_FIRST(&pmp->pmp_msg_touser); - if (park == NULL) - continue; - - lockmgr(&park->park_mtx, LK_EXCLUSIVE); - puffs_msgpark_reference(park); - - DPRINTF_VERBOSE(("puffs_getout: found park at %p, ", park)); - - /* If it's a goner, don't process any furher */ - if (park->park_flags & PARKFLAG_WAITERGONE) { - DPRINTF_VERBOSE(("waitergone!\n")); - puffs_msgpark_release(park); - continue; - } - preq = park->park_preq; - -#if 0 - /* check size */ - /* - * XXX: this check is not valid for now, we don't know - * the size of the caller's input buffer. i.e. this - * will most likely go away - */ - if (maxsize < preq->preq_frhdr.pfr_len) { - DPRINTF(("buffer too small\n")); - puffs_msgpark_release(park); - error = E2BIG; - break; - } -#endif - - DPRINTF_VERBOSE(("returning\n")); - - /* - * Ok, we found what we came for. Release it from the - * outgoing queue but do not unlock. We will unlock - * only after we "releaseout" it to avoid complications: - * otherwise it is (theoretically) possible for userland - * to race us into "put" before we have a change to put - * this baby on the receiving queue. - */ - TAILQ_REMOVE(&pmp->pmp_msg_touser, park, park_entries); - KKASSERT(park->park_flags & PARKFLAG_ONQUEUE1); - park->park_flags &= ~PARKFLAG_ONQUEUE1; - lockmgr(&park->park_mtx, LK_RELEASE); - - pmp->pmp_msg_touser_count--; - KKASSERT(pmp->pmp_msg_touser_count >= 0); - - break; - } - puffs_mp_release(pmp); - lockmgr(&pmp->pmp_lock, LK_RELEASE); - - if (error == 0) { - *data = (uint8_t *)preq; - preq->preq_pth.pth_framelen = park->park_copylen; - *dlen = preq->preq_pth.pth_framelen; - *parkptr = park; - } - - return error; -} - -/* - * Release outgoing structure. Now, depending on the success of the - * outgoing send, it is either going onto the result waiting queue - * or the death chamber. - */ -void -puffs_msgif_releaseout(void *this, void *parkptr, int status) -{ - struct puffs_mount *pmp = this; - struct puffs_msgpark *park = parkptr; - - DPRINTF_VERBOSE(("puffs_releaseout: returning park %p, errno %d: " , - park, status)); - lockmgr(&pmp->pmp_lock, LK_EXCLUSIVE); - lockmgr(&park->park_mtx, LK_EXCLUSIVE); - if (park->park_flags & PARKFLAG_WANTREPLY) { - if (status == 0) { - DPRINTF_VERBOSE(("enqueue replywait\n")); - TAILQ_INSERT_TAIL(&pmp->pmp_msg_replywait, park, - park_entries); - park->park_flags |= PARKFLAG_ONQUEUE2; - } else { - DPRINTF_VERBOSE(("error path!\n")); - park->park_preq->preq_rv = status; - park->park_flags |= PARKFLAG_DONE; - cv_signal(&park->park_cv); - } - puffs_msgpark_release(park); - } else { - DPRINTF_VERBOSE(("release\n")); - puffs_msgpark_release1(park, 2); - } - lockmgr(&pmp->pmp_lock, LK_RELEASE); -} - -size_t -puffs_msgif_waitcount(void *this) -{ - struct puffs_mount *pmp = this; - size_t rv; - - lockmgr(&pmp->pmp_lock, LK_EXCLUSIVE); - rv = pmp->pmp_msg_touser_count; - lockmgr(&pmp->pmp_lock, LK_RELEASE); - - return rv; -} - -/* - * XXX: locking with this one? - */ -static void -puffsop_msg(void *this, struct puffs_req *preq) -{ - struct puffs_mount *pmp = this; - struct putter_hdr *pth = &preq->preq_pth; - struct puffs_msgpark *park; - int wgone; - - lockmgr(&pmp->pmp_lock, LK_EXCLUSIVE); - - /* Locate waiter */ - TAILQ_FOREACH(park, &pmp->pmp_msg_replywait, park_entries) { - if (park->park_preq->preq_id == preq->preq_id) - break; - } - if (park == NULL) { - DPRINTF_VERBOSE(("puffsop_msg: no request: %" PRIu64 "\n", - preq->preq_id)); - lockmgr(&pmp->pmp_lock, LK_RELEASE); - return; /* XXX send error */ - } - - lockmgr(&park->park_mtx, LK_EXCLUSIVE); - puffs_msgpark_reference(park); - if (pth->pth_framelen > park->park_maxlen) { - DPRINTF_VERBOSE(("puffsop_msg: invalid buffer length: " - "%" PRIu64 " (req %" PRIu64 ", \n", pth->pth_framelen, - preq->preq_id)); - park->park_preq->preq_rv = EPROTO; - cv_signal(&park->park_cv); - puffs_msgpark_release1(park, 2); - lockmgr(&pmp->pmp_lock, LK_RELEASE); - return; /* XXX: error */ - } - wgone = park->park_flags & PARKFLAG_WAITERGONE; - - KKASSERT(park->park_flags & PARKFLAG_ONQUEUE2); - TAILQ_REMOVE(&pmp->pmp_msg_replywait, park, park_entries); - park->park_flags &= ~PARKFLAG_ONQUEUE2; - lockmgr(&pmp->pmp_lock, LK_RELEASE); - - if (wgone) { - DPRINTF_VERBOSE(("puffsop_msg: bad service - waiter gone for " - "park %p\n", park)); - } else { - memcpy(park->park_preq, preq, pth->pth_framelen); - - if (park->park_flags & PARKFLAG_CALL) { - DPRINTF_VERBOSE(("puffsop_msg: call for %p, arg %p\n", - park->park_preq, park->park_donearg)); - park->park_done(pmp, preq, park->park_donearg); - } - } - - if (!wgone) { - DPRINTF_VERBOSE(("puffs_putop: flagging done for " - "park %p\n", park)); - cv_signal(&park->park_cv); - } - - park->park_flags |= PARKFLAG_DONE; - puffs_msgpark_release1(park, 2); -} - -static void -puffsop_flush(struct puffs_mount *pmp, struct puffs_flush *pf) -{ - struct vnode *vp; -#ifdef XXXDF - voff_t offlo, offhi; - int rv, flags = 0; -#endif - int rv; - - KKASSERT(pf->pf_req.preq_pth.pth_framelen == sizeof(struct puffs_flush)); - - /* XXX: slurry */ - if (pf->pf_op == PUFFS_INVAL_NAMECACHE_ALL) { -#ifdef XXXDF - cache_purgevfs(PMPTOMP(pmp)); - rv = 0; -#endif - rv = ENOTSUP; - goto out; - } - - /* - * Get vnode, don't lock it. Namecache is protected by its own lock - * and we have a reference to protect against premature harvesting. - * - * The node we want here might be locked and the op is in - * userspace waiting for us to complete ==> deadlock. Another - * reason we need to eventually bump locking to userspace, as we - * will need to lock the node if we wish to do flushes. - */ - rv = puffs_cookie2vnode(pmp, pf->pf_cookie, 0, &vp); - if (rv) { - if (rv == PUFFS_NOSUCHCOOKIE) - rv = ENOENT; - goto out; - } - - switch (pf->pf_op) { -#if 0 - /* not quite ready, yet */ - case PUFFS_INVAL_NAMECACHE_NODE: - struct componentname *pf_cn; - char *name; - /* get comfortab^Wcomponentname */ - pf_cn = kmem_alloc(componentname); - memset(pf_cn, 0, sizeof(struct componentname)); - break; - -#endif - case PUFFS_INVAL_NAMECACHE_DIR: - if (vp->v_type != VDIR) { - rv = EINVAL; - break; - } -#ifdef XXXDF - /* deadlocks, needs its own kernel thread */ - cache_purge(vp); -#endif - break; - -#ifdef XXXDF - case PUFFS_INVAL_PAGECACHE_NODE_RANGE: - flags = PGO_FREE; - /*FALLTHROUGH*/ - case PUFFS_FLUSH_PAGECACHE_NODE_RANGE: - if (flags == 0) - flags = PGO_CLEANIT; - - if (pf->pf_end > vp->v_size || vp->v_type != VREG) { - rv = EINVAL; - break; - } - - offlo = trunc_page(pf->pf_start); - offhi = round_page(pf->pf_end); - if (offhi != 0 && offlo >= offhi) { - rv = EINVAL; - break; - } - - lockmgr(&vp->v_uobj.vmobjlock, LK_EXCLUSIVE); - rv = VOP_PUTPAGES(vp, offlo, offhi, flags); - break; -#endif - - default: - rv = EINVAL; - } - - vput(vp); - - out: - puffs_msg_sendresp(pmp, &pf->pf_req, rv); -} - -int -puffs_msgif_dispatch(void *this, struct putter_hdr *pth) -{ - struct puffs_mount *pmp = this; - struct puffs_req *preq = (struct puffs_req *)pth; - struct puffs_sopreq *psopr; - - if (pth->pth_framelen < sizeof(struct puffs_req)) { - puffs_msg_sendresp(pmp, preq, EINVAL); /* E2SMALL */ - return 0; - } - - switch (PUFFSOP_OPCLASS(preq->preq_opclass)) { - case PUFFSOP_VN: - case PUFFSOP_VFS: - DPRINTF_VERBOSE(("dispatch: vn/vfs message 0x%x\n", - preq->preq_optype)); - puffsop_msg(pmp, preq); - break; - - case PUFFSOP_FLUSH: /* process in sop thread */ - { - struct puffs_flush *pf; - - DPRINTF(("dispatch: flush 0x%x\n", preq->preq_optype)); - - if (preq->preq_pth.pth_framelen != sizeof(struct puffs_flush)) { - puffs_msg_sendresp(pmp, preq, EINVAL); /* E2SMALL */ - break; - } - pf = (struct puffs_flush *)preq; - - psopr = kmalloc(sizeof(*psopr), M_PUFFS, M_WAITOK); - memcpy(&psopr->psopr_pf, pf, sizeof(*pf)); - psopr->psopr_sopreq = PUFFS_SOPREQ_FLUSH; - - lockmgr(&pmp->pmp_sopmtx, LK_EXCLUSIVE); - if (pmp->pmp_sopthrcount == 0) { - lockmgr(&pmp->pmp_sopmtx, LK_RELEASE); - kfree(psopr, M_PUFFS); - puffs_msg_sendresp(pmp, preq, ENXIO); - } else { - TAILQ_INSERT_TAIL(&pmp->pmp_sopreqs, - psopr, psopr_entries); - cv_signal(&pmp->pmp_sopcv); - lockmgr(&pmp->pmp_sopmtx, LK_RELEASE); - } - break; - } - - case PUFFSOP_UNMOUNT: /* process in sop thread */ - { - - DPRINTF(("dispatch: unmount 0x%x\n", preq->preq_optype)); - - psopr = kmalloc(sizeof(*psopr), M_PUFFS, M_WAITOK); - psopr->psopr_preq = *preq; - psopr->psopr_sopreq = PUFFS_SOPREQ_UNMOUNT; - - lockmgr(&pmp->pmp_sopmtx, LK_EXCLUSIVE); - if (pmp->pmp_sopthrcount == 0) { - lockmgr(&pmp->pmp_sopmtx, LK_RELEASE); - kfree(psopr, M_PUFFS); - puffs_msg_sendresp(pmp, preq, ENXIO); - } else { - TAILQ_INSERT_TAIL(&pmp->pmp_sopreqs, - psopr, psopr_entries); - cv_signal(&pmp->pmp_sopcv); - lockmgr(&pmp->pmp_sopmtx, LK_RELEASE); - } - break; - } - - default: - DPRINTF(("dispatch: invalid class 0x%x\n", preq->preq_opclass)); - puffs_msg_sendresp(pmp, preq, EOPNOTSUPP); - break; - } - - return 0; -} - -/* - * Work loop for thread processing all ops from server which - * cannot safely be handled in caller context. This includes - * everything which might need a lock currently "held" by the file - * server, i.e. a long-term kernel lock which will be released only - * once the file server acknowledges a request - */ -void -puffs_sop_thread(void *arg) -{ - struct puffs_mount *pmp = arg; - struct mount *mp = PMPTOMP(pmp); - struct puffs_sopreq *psopr; - boolean_t keeprunning; - boolean_t unmountme = FALSE; - - lockmgr(&pmp->pmp_sopmtx, LK_EXCLUSIVE); - for (keeprunning = TRUE; keeprunning; ) { - while ((psopr = TAILQ_FIRST(&pmp->pmp_sopreqs)) == NULL) - cv_wait(&pmp->pmp_sopcv, &pmp->pmp_sopmtx); - TAILQ_REMOVE(&pmp->pmp_sopreqs, psopr, psopr_entries); - lockmgr(&pmp->pmp_sopmtx, LK_RELEASE); - - switch (psopr->psopr_sopreq) { - case PUFFS_SOPREQSYS_EXIT: - keeprunning = FALSE; - break; - case PUFFS_SOPREQ_FLUSH: - puffsop_flush(pmp, &psopr->psopr_pf); - break; - case PUFFS_SOPREQ_UNMOUNT: - puffs_msg_sendresp(pmp, &psopr->psopr_preq, 0); - - unmountme = TRUE; - keeprunning = FALSE; - - break; - } - - kfree(psopr, M_PUFFS); - lockmgr(&pmp->pmp_sopmtx, LK_EXCLUSIVE); - } - - /* - * Purge remaining ops. - */ - while ((psopr = TAILQ_FIRST(&pmp->pmp_sopreqs)) != NULL) { - TAILQ_REMOVE(&pmp->pmp_sopreqs, psopr, psopr_entries); - lockmgr(&pmp->pmp_sopmtx, LK_RELEASE); - puffs_msg_sendresp(pmp, &psopr->psopr_preq, ENXIO); - kfree(psopr, M_PUFFS); - lockmgr(&pmp->pmp_sopmtx, LK_EXCLUSIVE); - } - - pmp->pmp_sopthrcount--; - cv_broadcast(&pmp->pmp_sopcv); - lockmgr(&pmp->pmp_sopmtx, LK_RELEASE); /* not allowed to access fs after this */ - - /* - * If unmount was requested, we can now safely do it here, since - * our context is dead from the point-of-view of puffs_unmount() - * and we are just another thread. dounmount() makes internally - * sure that VFS_UNMOUNT() isn't called reentrantly and that it - * is eventually completed. - */ - if (unmountme) { - dounmount(mp, MNT_FORCE, 0); - } - - kthread_exit(); -} - -int -puffs_msgif_close(void *this) -{ - struct puffs_mount *pmp = this; - struct mount *mp = PMPTOMP(pmp); - - lockmgr(&pmp->pmp_lock, LK_EXCLUSIVE); - puffs_mp_reference(pmp); - - /* - * Free the waiting callers before proceeding any further. - * The syncer might be jogging around in this file system - * currently. If we allow it to go to the userspace of no - * return while trying to get the syncer lock, well ... - */ - puffs_userdead(pmp); - - /* - * Make sure someone from puffs_unmount() isn't currently in - * userspace. If we don't take this precautionary step, - * they might notice that the mountpoint has disappeared - * from under them once they return. Especially note that we - * cannot simply test for an unmounter before calling - * dounmount(), since it might be possible that that particular - * invocation of unmount was called without MNT_FORCE. Here we - * *must* make sure unmount succeeds. Also, restart is necessary - * since pmp isn't locked. We might end up with PUTTER_DEAD after - * restart and exit from there. - */ - if (pmp->pmp_unmounting) { - cv_wait(&pmp->pmp_unmounting_cv, &pmp->pmp_lock); - puffs_mp_release(pmp); - lockmgr(&pmp->pmp_lock, LK_RELEASE); - DPRINTF(("puffs_fop_close: unmount was in progress for pmp %p, " - "restart\n", pmp)); - return ERESTART; - } - - /* Won't access pmp from here anymore */ - puffs_mp_release(pmp); - lockmgr(&pmp->pmp_lock, LK_RELEASE); - - /* Detach from VFS. */ - dounmount(mp, MNT_FORCE, 0); - - return 0; -} - -/* - * We're dead, kaput, RIP, slightly more than merely pining for the - * fjords, belly-up, fallen, lifeless, finished, expired, gone to meet - * our maker, ceased to be, etcetc. YASD. It's a dead FS! - * - * Caller must hold puffs mutex. - */ -void -puffs_userdead(struct puffs_mount *pmp) -{ - struct puffs_msgpark *park, *park_next; - - /* - * Mark filesystem status as dying so that operations don't - * attempt to march to userspace any longer. - */ - pmp->pmp_status = PUFFSTAT_DYING; - - /* signal waiters on REQUEST TO file server queue */ - for (park = TAILQ_FIRST(&pmp->pmp_msg_touser); park; park = park_next) { - lockmgr(&park->park_mtx, LK_EXCLUSIVE); - puffs_msgpark_reference(park); - park_next = TAILQ_NEXT(park, park_entries); - - KKASSERT(park->park_flags & PARKFLAG_ONQUEUE1); - TAILQ_REMOVE(&pmp->pmp_msg_touser, park, park_entries); - park->park_flags &= ~PARKFLAG_ONQUEUE1; - pmp->pmp_msg_touser_count--; - - /* - * Even though waiters on QUEUE1 are removed in touser() - * in case of WAITERGONE, it is still possible for us to - * get raced here due to having to retake locks in said - * touser(). In the race case simply "ignore" the item - * on the queue and move on to the next one. - */ - if (park->park_flags & PARKFLAG_WAITERGONE) { - KKASSERT((park->park_flags & PARKFLAG_CALL) == 0); - KKASSERT(park->park_flags & PARKFLAG_WANTREPLY); - puffs_msgpark_release(park); - - } else { - park->park_preq->preq_rv = ENXIO; - - if (park->park_flags & PARKFLAG_CALL) { - park->park_done(pmp, park->park_preq, - park->park_donearg); - puffs_msgpark_release1(park, 2); - } else if ((park->park_flags & PARKFLAG_WANTREPLY)==0) { - puffs_msgpark_release1(park, 2); - } else { - park->park_preq->preq_rv = ENXIO; - cv_signal(&park->park_cv); - puffs_msgpark_release(park); - } - } - } - - /* signal waiters on RESPONSE FROM file server queue */ - for (park=TAILQ_FIRST(&pmp->pmp_msg_replywait); park; park=park_next) { - lockmgr(&park->park_mtx, LK_EXCLUSIVE); - puffs_msgpark_reference(park); - park_next = TAILQ_NEXT(park, park_entries); - - KKASSERT(park->park_flags & PARKFLAG_ONQUEUE2); - KKASSERT(park->park_flags & PARKFLAG_WANTREPLY); - - TAILQ_REMOVE(&pmp->pmp_msg_replywait, park, park_entries); - park->park_flags &= ~PARKFLAG_ONQUEUE2; - - if (park->park_flags & PARKFLAG_WAITERGONE) { - KKASSERT((park->park_flags & PARKFLAG_CALL) == 0); - puffs_msgpark_release(park); - } else { - park->park_preq->preq_rv = ENXIO; - if (park->park_flags & PARKFLAG_CALL) { - park->park_done(pmp, park->park_preq, - park->park_donearg); - puffs_msgpark_release1(park, 2); - } else { - cv_signal(&park->park_cv); - puffs_msgpark_release(park); - } - } - } - - cv_broadcast(&pmp->pmp_msg_waiter_cv); -} diff --git a/sys/vfs/puffs/puffs_msgif.h b/sys/vfs/puffs/puffs_msgif.h deleted file mode 100644 index 7d9454a3e5..0000000000 --- a/sys/vfs/puffs/puffs_msgif.h +++ /dev/null @@ -1,677 +0,0 @@ -/* $NetBSD: puffs_msgif.h,v 1.76 2011/07/04 08:07:30 manu 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define _VFS_NAMELEN MFSNAMELEN -#define _VFS_MNAMELEN MNAMELEN - -typedef off_t voff_t; -typedef off_t vsize_t; - -#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 PUFFSOP_UNMOUNT 0x07 /* ->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) - -enum { - 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 -}; -#define PUFFS_VFS_MAX PUFFS_VFS_SUSPEND - -enum { - PUFFS_VN_LOOKUP, PUFFS_VN_LOOKUPDOTDOT, - 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 - /* NOTE: If you add an op, decrement PUFFS_VN_SPARE accordingly */ -}; -#define PUFFS_VN_MAX PUFFS_VN_CLOSEEXTATTR -#define PUFFS_VN_SPARE 31 - -/* - * These signal invalid parameters the file system returned. - */ -enum { - 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 -}; -#define PUFFS_ERR_MAX PUFFS_ERR_LISTEXTATTR - -#define PUFFSVERSION 30 -#define PUFFSNAMESIZE 32 - -#define PUFFS_TYPEPREFIX "puffs|" - -#define PUFFS_TYPELEN (_VFS_NAMELEN - (sizeof(PUFFS_TYPEPREFIX)+1)) -#define PUFFS_NAMELEN (_VFS_MNAMELEN-1) - -/* - * Just a weak typedef for code clarity. Additionally, we have a - * more appropriate vanity type for puffs: - * it should be croissant, not cookie. - */ -typedef void *puffs_cookie_t; -typedef puffs_cookie_t puffs_croissant_t; - -struct puffs_kargs { - unsigned int pa_vers; - int pa_minor; - - uint32_t pa_flags; - - size_t pa_maxmsglen; - int pa_nhashbuckets; - - size_t pa_fhsize; - int pa_fhflags; - - uint8_t pa_vnopmask[PUFFS_VN_MAX + PUFFS_VN_SPARE]; - - char pa_typename[_VFS_NAMELEN]; - char pa_mntfromname[_VFS_MNAMELEN]; - - puffs_cookie_t pa_root_cookie; - enum vtype pa_root_vtype; - voff_t pa_root_vsize; - union { - dev_t dev; - uint64_t container; - } devunion; - - struct statvfs pa_svfsb; - - uint32_t pa_time32; - - uint32_t pa_spare[127]; -}; -#define pa_root_rdev devunion.dev - -#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_MASK 0x3f -#define PUFFS_KFLAG_NOCACHE_ATTR 0x40 /* no attrib cache (unused) */ - -#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 /* FHANDLE_SIZE_MAX - 4 */ - -struct puffs_req { - struct putter_hdr preq_pth; - - uint64_t preq_id; - puffs_cookie_t preq_cookie; - - uint16_t preq_opclass; - uint16_t preq_optype; - int preq_rv; - - uint32_t preq_setbacks; - - /* Who is making the call? Eventually host id is also needed. */ - pid_t preq_pid; - lwpid_t preq_lid; - - /* - * the following helper pads the struct size to md alignment - * multiple (should size_t not cut it). it makes sure that - * whatever comes after this struct is aligned - */ - size_t preq_buflen; - uint8_t preq_buf[0] __aligned(ALIGNBYTES+1); -}; - -#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 - -/* - * Flush operation. This can be used to invalidate: - * 1) name cache for one node - * 2) name cache for all children - * 3) name cache for the entire mount - * 4) page cache for a set of ranges in one node - * 5) page cache for one entire node - * - * It can be used to flush: - * 1) page cache for a set of ranges in one node - * 2) page cache for one entire node - */ - -struct puffs_flush { - struct puffs_req pf_req; - - puffs_cookie_t pf_cookie; - - int pf_op; - off_t pf_start; - off_t pf_end; -}; -#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 - -/* - * 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 xucred 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 - -/* - * 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 /* approximate */ - -#define PUFFS_EXTNAMELEN NAME_MAX /* currently same as EXTATTR_MAXNAMELEN */ - -#define PUFFS_TOMOVE(a,b) (MIN((a), b->pmp_msg_maxsize - PUFFS_MSGSTRUCT_MAX)) - -/* puffs struct componentname built by kernel */ -struct puffs_kcn { - char pkcn_name[NAME_MAX + 1]; /* nulterminated path component */ - size_t pkcn_namelen; /* current component length */ -}; - - -/* - * Next come the individual requests. They are all subclassed from - * puffs_req and contain request-specific fields in addition. Note - * that there are some requests which have to handle arbitrary-length - * buffers. - * - * The division is the following: puffs_req is to be touched only - * by generic routines while the other stuff is supposed to be - * modified only by specific routines. - */ - -/* - * aux structures for vfs operations. - */ -struct puffs_vfsmsg_unmount { - struct puffs_req pvfsr_pr; - - int pvfsr_flags; -}; - -struct puffs_vfsmsg_statvfs { - struct puffs_req pvfsr_pr; - - struct statvfs pvfsr_sb; -}; - -struct puffs_vfsmsg_sync { - struct puffs_req pvfsr_pr; - - int pvfsr_waitfor; -}; - -struct puffs_vfsmsg_fhtonode { - struct puffs_req pvfsr_pr; - - void *pvfsr_fhcookie; /* IN */ - enum vtype pvfsr_vtype; /* IN */ - voff_t pvfsr_size; /* IN */ - dev_t pvfsr_rdev; /* IN */ - - size_t pvfsr_dsize; /* OUT */ - uint8_t pvfsr_data[0] /* OUT, XXX */ - __aligned(ALIGNBYTES+1); -}; - -struct puffs_vfsmsg_nodetofh { - struct puffs_req pvfsr_pr; - - void *pvfsr_fhcookie; /* OUT */ - - size_t pvfsr_dsize; /* OUT/IN */ - uint8_t pvfsr_data[0] /* IN, XXX */ - __aligned(ALIGNBYTES+1); -}; - -struct puffs_vfsmsg_suspend { - struct puffs_req pvfsr_pr; - - int pvfsr_status; -}; -#define PUFFS_SUSPEND_START 0 -#define PUFFS_SUSPEND_SUSPENDED 1 -#define PUFFS_SUSPEND_RESUME 2 -#define PUFFS_SUSPEND_ERROR 3 - -#define PUFFS_EXTATTRCTL_HASNODE 0x01 -#define PUFFS_EXTATTRCTL_HASATTRNAME 0x02 -struct puffs_vfsmsg_extattrctl { - struct puffs_req pvfsr_pr; - - int pvfsr_cmd; /* OUT */ - int pvfsr_attrnamespace; /* OUT */ - int pvfsr_flags; /* OUT */ - char pvfsr_attrname[PUFFS_EXTNAMELEN]; /* OUT */ -}; - -/* - * aux structures for vnode operations. - */ - -struct puffs_vnmsg_lookup { - struct puffs_req pvn_pr; - - struct puffs_kcn pvnr_cn; /* OUT */ - struct puffs_kcred pvnr_cn_cred; /* OUT */ - - puffs_cookie_t pvnr_newnode; /* IN */ - enum vtype pvnr_vtype; /* IN */ - voff_t pvnr_size; /* IN */ - dev_t pvnr_rdev; /* IN */ -}; - -struct puffs_vnmsg_lookupdotdot { - struct puffs_req pvn_pr; - - struct puffs_kcred pvnr_cred; /* OUT */ - - puffs_cookie_t pvnr_newnode; /* IN */ -}; - -struct puffs_vnmsg_create { - struct puffs_req pvn_pr; - - struct puffs_kcn pvnr_cn; /* OUT */ - struct puffs_kcred pvnr_cn_cred; /* OUT */ - - struct vattr pvnr_va; /* OUT */ - puffs_cookie_t pvnr_newnode; /* IN */ -}; - -struct puffs_vnmsg_mknod { - struct puffs_req pvn_pr; - - struct puffs_kcn pvnr_cn; /* OUT */ - struct puffs_kcred pvnr_cn_cred; /* OUT */ - - struct vattr pvnr_va; /* OUT */ - puffs_cookie_t pvnr_newnode; /* IN */ -}; - -struct puffs_vnmsg_open { - struct puffs_req pvn_pr; - - struct puffs_kcred pvnr_cred; /* OUT */ - int pvnr_mode; /* OUT */ -}; - -struct puffs_vnmsg_close { - struct puffs_req pvn_pr; - - int pvnr_fflag; /* OUT */ -}; - -struct puffs_vnmsg_access { - struct puffs_req pvn_pr; - - struct puffs_kcred pvnr_cred; /* OUT */ - int pvnr_mode; /* OUT */ -}; - -#define puffs_vnmsg_setattr puffs_vnmsg_setgetattr -#define puffs_vnmsg_getattr puffs_vnmsg_setgetattr -struct puffs_vnmsg_setgetattr { - struct puffs_req pvn_pr; - - struct puffs_kcred pvnr_cred; /* OUT */ - struct vattr pvnr_va; /* IN/OUT (op depend) */ -}; - -#define puffs_vnmsg_read puffs_vnmsg_rw -#define puffs_vnmsg_write puffs_vnmsg_rw -struct puffs_vnmsg_rw { - struct puffs_req pvn_pr; - - struct puffs_kcred pvnr_cred; /* OUT */ - off_t pvnr_offset; /* OUT */ - size_t pvnr_resid; /* IN/OUT */ - int pvnr_ioflag; /* OUT */ - - uint8_t pvnr_data[0]; /* IN/OUT (wr/rd) */ -}; - -#define puffs_vnmsg_ioctl puffs_vnreq_fcnioctl -#define puffs_vnmsg_fcntl puffs_vnreq_fcnioctl -struct puffs_vnmsg_fcnioctl { - struct puffs_req pvn_pr; - - struct puffs_kcred pvnr_cred; - u_long pvnr_command; - pid_t pvnr_pid; - int pvnr_fflag; - - void *pvnr_data; - size_t pvnr_datalen; - int pvnr_copyback; -}; - -struct puffs_vnmsg_poll { - struct puffs_req pvn_pr; - - int pvnr_events; /* IN/OUT */ -}; - -struct puffs_vnmsg_fsync { - struct puffs_req pvn_pr; - - int pvnr_flags; /* OUT */ -}; - -struct puffs_vnmsg_seek { - struct puffs_req pvn_pr; - - struct puffs_kcred pvnr_cred; /* OUT */ - off_t pvnr_oldoff; /* OUT */ - off_t pvnr_newoff; /* OUT */ -}; - -struct puffs_vnmsg_remove { - struct puffs_req pvn_pr; - - struct puffs_kcn pvnr_cn; /* OUT */ - struct puffs_kcred pvnr_cn_cred; /* OUT */ - - puffs_cookie_t pvnr_cookie_targ; /* OUT */ -}; - -struct puffs_vnmsg_mkdir { - struct puffs_req pvn_pr; - - struct puffs_kcn pvnr_cn; /* OUT */ - struct puffs_kcred pvnr_cn_cred; /* OUT */ - - struct vattr pvnr_va; /* OUT */ - puffs_cookie_t pvnr_newnode; /* IN */ -}; - -struct puffs_vnmsg_rmdir { - struct puffs_req pvn_pr; - - struct puffs_kcn pvnr_cn; /* OUT */ - struct puffs_kcred pvnr_cn_cred; /* OUT */ - - puffs_cookie_t pvnr_cookie_targ; /* OUT */ -}; - -struct puffs_vnmsg_link { - struct puffs_req pvn_pr; - - struct puffs_kcn pvnr_cn; /* OUT */ - struct puffs_kcred pvnr_cn_cred; /* OUT */ - - puffs_cookie_t pvnr_cookie_targ; /* OUT */ -}; - -struct puffs_vnmsg_rename { - struct puffs_req pvn_pr; - - struct puffs_kcn pvnr_cn_src; /* OUT */ - struct puffs_kcred pvnr_cn_src_cred; /* OUT */ - struct puffs_kcn pvnr_cn_targ; /* OUT */ - struct puffs_kcred pvnr_cn_targ_cred; /* OUT */ - - puffs_cookie_t pvnr_cookie_src; /* OUT */ - puffs_cookie_t pvnr_cookie_targ; /* OUT */ - puffs_cookie_t pvnr_cookie_targdir; /* OUT */ -}; - -struct puffs_vnmsg_symlink { - struct puffs_req pvn_pr; - - struct puffs_kcn pvnr_cn; /* OUT */ - struct puffs_kcred pvnr_cn_cred; /* OUT */ - - struct vattr pvnr_va; /* OUT */ - puffs_cookie_t pvnr_newnode; /* IN */ - char pvnr_link[MAXPATHLEN]; /* OUT */ -}; - -struct puffs_vnmsg_readdir { - struct puffs_req pvn_pr; - - struct puffs_kcred pvnr_cred; /* OUT */ - off_t pvnr_offset; /* IN/OUT */ - size_t pvnr_resid; /* IN/OUT */ - size_t pvnr_ncookies; /* IN/OUT */ - int pvnr_eofflag; /* IN */ - - size_t pvnr_dentoff; /* OUT */ - uint8_t pvnr_data[0] /* IN */ - __aligned(ALIGNBYTES+1); -}; - -struct puffs_vnmsg_readlink { - struct puffs_req pvn_pr; - - struct puffs_kcred pvnr_cred; /* OUT */ - size_t pvnr_linklen; /* IN */ - char pvnr_link[MAXPATHLEN]; /* IN */ -}; - -struct puffs_vnmsg_reclaim { - struct puffs_req pvn_pr; -}; - -struct puffs_vnmsg_inactive { - struct puffs_req pvn_pr; -}; - -struct puffs_vnmsg_print { - struct puffs_req pvn_pr; - - /* empty */ -}; - -struct puffs_vnmsg_pathconf { - struct puffs_req pvn_pr; - - int pvnr_name; /* OUT */ - register_t pvnr_retval; /* IN */ -}; - -struct puffs_vnmsg_advlock { - struct puffs_req pvn_pr; - - struct flock pvnr_fl; /* OUT */ - void *pvnr_id; /* OUT */ - int pvnr_op; /* OUT */ - int pvnr_flags; /* OUT */ -}; - -struct puffs_vnmsg_mmap { - struct puffs_req pvn_pr; - - vm_prot_t pvnr_prot; /* OUT */ - struct puffs_kcred pvnr_cred; /* OUT */ -}; - -struct puffs_vnmsg_abortop { - struct puffs_req pvn_pr; - - struct puffs_kcn pvnr_cn; /* OUT */ - struct puffs_kcred pvnr_cn_cred; /* OUT */ -}; - -struct puffs_vnmsg_getextattr { - struct puffs_req pvn_pr; - - int pvnr_attrnamespace; /* OUT */ - char pvnr_attrname[PUFFS_EXTNAMELEN];/* OUT */ - - struct puffs_kcred pvnr_cred; /* OUT */ - size_t pvnr_datasize; /* IN */ - - size_t pvnr_resid; /* IN/OUT */ - uint8_t pvnr_data[0] /* IN */ - __aligned(ALIGNBYTES+1); -}; - -struct puffs_vnmsg_setextattr { - struct puffs_req pvn_pr; - - int pvnr_attrnamespace; /* OUT */ - char pvnr_attrname[PUFFS_EXTNAMELEN];/* OUT */ - - struct puffs_kcred pvnr_cred; /* OUT */ - - size_t pvnr_resid; /* IN/OUT */ - uint8_t pvnr_data[0] /* OUT */ - __aligned(ALIGNBYTES+1); -}; - -struct puffs_vnmsg_listextattr { - struct puffs_req pvn_pr; - - int pvnr_attrnamespace; /* OUT */ - - struct puffs_kcred pvnr_cred; /* OUT */ - size_t pvnr_datasize; /* IN */ - - size_t pvnr_resid; /* IN/OUT */ - int pvnr_flag; /* OUT */ - uint8_t pvnr_data[0] /* IN */ - __aligned(ALIGNBYTES+1); -}; - -struct puffs_vnmsg_deleteextattr { - struct puffs_req pvn_pr; - - int pvnr_attrnamespace; /* OUT */ - char pvnr_attrname[PUFFS_EXTNAMELEN];/* OUT */ - - struct puffs_kcred pvnr_cred; /* OUT */ -}; - -/* - * For cache reports. Everything is always out-out-out, no replies - */ - -struct puffs_cacherun { - off_t pcache_runstart; - off_t pcache_runend; -}; - -/* cache info. old used for write now */ -struct puffs_cacheinfo { - struct puffs_req pcache_pr; - - int pcache_type; - size_t pcache_nruns; - struct puffs_cacherun pcache_runs[0]; -}; -#define PCACHE_TYPE_READ 0 -#define PCACHE_TYPE_WRITE 1 - -/* - * Error notification. Always outgoing, no response, no remorse. - */ -struct puffs_error { - struct puffs_req perr_pr; - - int perr_error; - char perr_str[256]; -}; - -#endif /* _FS_PUFFS_PUFFS_MSGIF_H_ */ diff --git a/sys/vfs/puffs/puffs_node.c b/sys/vfs/puffs/puffs_node.c deleted file mode 100644 index f6bdea8b30..0000000000 --- a/sys/vfs/puffs/puffs_node.c +++ /dev/null @@ -1,458 +0,0 @@ -/* $NetBSD: puffs_node.c,v 1.19 2011/06/30 20:09:41 wiz Exp $ */ - -/* - * Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved. - * - * Development of this software was supported by the - * Google Summer of Code program, the Ulla Tuominen Foundation - * and the Finnish Cultural 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. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -static __inline struct puffs_node_hashlist - *puffs_cookie2hashlist(struct puffs_mount *, puffs_cookie_t); -static struct puffs_node *puffs_cookie2pnode(struct puffs_mount *, - puffs_cookie_t); - -/* - * Grab a vnode, intialize all the puffs-dependent stuff. - */ -int -puffs_getvnode(struct mount *mp, puffs_cookie_t ck, enum vtype type, - voff_t vsize, struct vnode **vpp) -{ - struct puffs_mount *pmp; - struct puffs_newcookie *pnc; - struct vnode *vp; - struct puffs_node *pnode; - struct puffs_node_hashlist *plist; - int error; - - pmp = MPTOPUFFSMP(mp); - - error = EPROTO; - if (type <= VNON || type >= VBAD) { - puffs_senderr(pmp, PUFFS_ERR_MAKENODE, EINVAL, - "bad node type", ck); - goto bad; - } - if (type == VBLK || type == VCHR) { - puffs_senderr(pmp, PUFFS_ERR_MAKENODE, EINVAL, - "device nodes are not supported", ck); - goto bad; - } - if (vsize == VNOVAL) { - puffs_senderr(pmp, PUFFS_ERR_MAKENODE, EINVAL, - "VNOVAL is not a valid size", ck); - goto bad; - } - - /* XXX Add VT_PUFFS */ - error = getnewvnode(VT_SYNTH, mp, &vp, 0, 0); - if (error) { - goto bad; - } - vp->v_type = type; - - /* - * Creation should not fail after this point. Or if it does, - * care must be taken so that VOP_INACTIVE() isn't called. - */ - - /* dances based on vnode type. almost ufs_vinit(), but not quite */ - switch (type) { - case VFIFO: - vp->v_ops = &mp->mnt_vn_fifo_ops; - break; - - case VREG: - if (PUFFS_USE_PAGECACHE(pmp)) - vinitvmio(vp, vsize, mp->mnt_stat.f_iosize, -1); - break; - - case VDIR: - case VLNK: - case VSOCK: - break; - default: - panic("puffs_getvnode: invalid vtype %d", type); - } - - pnode = kmalloc(sizeof(struct puffs_node), M_PUFFS, M_ZERO | M_WAITOK); - - pnode->pn_cookie = ck; - pnode->pn_refcount = 1; - - /* insert cookie on list, take off of interlock list */ - lockinit(&pnode->pn_mtx, "puffs pn_mtx", 0, 0); -#ifdef XXXDF - selinit(&pnode->pn_sel); - knlist_init(); -#endif - plist = puffs_cookie2hashlist(pmp, ck); - lockmgr(&pmp->pmp_lock, LK_EXCLUSIVE); - LIST_INSERT_HEAD(plist, pnode, pn_hashent); - if (ck != pmp->pmp_root_cookie) { - LIST_FOREACH(pnc, &pmp->pmp_newcookie, pnc_entries) { - if (pnc->pnc_cookie == ck) { - LIST_REMOVE(pnc, pnc_entries); - kfree(pnc, M_PUFFS); - break; - } - } - KKASSERT(pnc != NULL); - } - lockmgr(&pmp->pmp_lock, LK_RELEASE); - - vp->v_data = pnode; - vp->v_type = type; - pnode->pn_vp = vp; - pnode->pn_serversize = vsize; - - *vpp = vp; - - DPRINTF(("new vnode at %p, pnode %p, cookie %p\n", vp, - pnode, pnode->pn_cookie)); - - return 0; - - bad: - /* remove staging cookie from list */ - if (ck != pmp->pmp_root_cookie) { - lockmgr(&pmp->pmp_lock, LK_EXCLUSIVE); - LIST_FOREACH(pnc, &pmp->pmp_newcookie, pnc_entries) { - if (pnc->pnc_cookie == ck) { - LIST_REMOVE(pnc, pnc_entries); - kfree(pnc, M_PUFFS); - break; - } - } - KKASSERT(pnc != NULL); - lockmgr(&pmp->pmp_lock, LK_RELEASE); - } - - return error; -} - -/* new node creating for creative vop ops (create, symlink, mkdir, mknod) */ -int -puffs_newnode(struct mount *mp, struct vnode *dvp, struct vnode **vpp, - puffs_cookie_t ck, enum vtype type) -{ - struct puffs_mount *pmp = MPTOPUFFSMP(mp); - struct puffs_newcookie *pnc; - struct vnode *vp; - int error; - - /* userspace probably has this as a NULL op */ - if (ck == NULL) { - error = EOPNOTSUPP; - return error; - } - - /* - * Check for previous node with the same designation. - * Explicitly check the root node cookie, since it might be - * reclaimed from the kernel when this check is made. - */ - lockmgr(&pmp->pmp_lock, LK_EXCLUSIVE); - if (ck == pmp->pmp_root_cookie - || puffs_cookie2pnode(pmp, ck) != NULL) { - lockmgr(&pmp->pmp_lock, LK_RELEASE); - puffs_senderr(pmp, PUFFS_ERR_MAKENODE, EEXIST, - "cookie exists", ck); - return EPROTO; - } - - LIST_FOREACH(pnc, &pmp->pmp_newcookie, pnc_entries) { - if (pnc->pnc_cookie == ck) { - lockmgr(&pmp->pmp_lock, LK_RELEASE); - puffs_senderr(pmp, PUFFS_ERR_MAKENODE, EEXIST, - "newcookie exists", ck); - return EPROTO; - } - } - pnc = kmalloc(sizeof(struct puffs_newcookie), M_PUFFS, M_WAITOK); - pnc->pnc_cookie = ck; - LIST_INSERT_HEAD(&pmp->pmp_newcookie, pnc, pnc_entries); - lockmgr(&pmp->pmp_lock, LK_RELEASE); - - error = puffs_getvnode(dvp->v_mount, ck, type, 0, &vp); - if (error) - return error; - *vpp = vp; - - return 0; -} - -void -puffs_putvnode(struct vnode *vp) -{ - struct puffs_node *pnode; - - pnode = VPTOPP(vp); - -#ifdef DIAGNOSTIC - if (vp->v_tag != VT_SYNTH) - panic("puffs_putvnode: %p not a puffs vnode", vp); -#endif - - puffs_releasenode(pnode); - vp->v_data = NULL; - - return; -} - -static __inline struct puffs_node_hashlist * -puffs_cookie2hashlist(struct puffs_mount *pmp, puffs_cookie_t ck) -{ - uint32_t hash; - - hash = fnv_32_buf(&ck, sizeof(void *), FNV1_32_INIT); - return &pmp->pmp_pnodehash[hash % pmp->pmp_npnodehash]; -} - -/* - * Translate cookie to puffs_node. Caller must hold pmp_lock - * and it will be held upon return. - */ -static struct puffs_node * -puffs_cookie2pnode(struct puffs_mount *pmp, puffs_cookie_t ck) -{ - struct puffs_node_hashlist *plist; - struct puffs_node *pnode; - - plist = puffs_cookie2hashlist(pmp, ck); - LIST_FOREACH(pnode, plist, pn_hashent) { - if (pnode->pn_cookie == ck) - break; - } - - return pnode; -} - -/* - * Make sure root vnode exists and reference it. Does NOT lock. - */ -static int -puffs_makeroot(struct puffs_mount *pmp) -{ - struct vnode *vp; - int rv; - - /* - * pmp_lock must be held if vref()'ing or vrele()'ing the - * root vnode. the latter is controlled by puffs_inactive(). - * - * pmp_root is set here and cleared in puffs_reclaim(). - */ - retry: - vp = pmp->pmp_root; - if (vp) { - if (vget(vp, LK_EXCLUSIVE) == 0) - return 0; - } - - /* - * So, didn't have the magic root vnode available. - * No matter, grab another and stuff it with the cookie. - */ - if ((rv = puffs_getvnode(pmp->pmp_mp, pmp->pmp_root_cookie, - pmp->pmp_root_vtype, pmp->pmp_root_vsize, &vp))) - return rv; - - /* - * Someone magically managed to race us into puffs_getvnode? - * Put our previous new vnode back and retry. - */ - lockmgr(&pmp->pmp_lock, LK_EXCLUSIVE); - if (pmp->pmp_root) { - struct puffs_node *pnode = VPTOPP(vp); - - LIST_REMOVE(pnode, pn_hashent); - lockmgr(&pmp->pmp_lock, LK_RELEASE); - puffs_putvnode(vp); - goto retry; - } - - /* store cache */ - vsetflags(vp, VROOT); - pmp->pmp_root = vp; - vref(vp); - lockmgr(&pmp->pmp_lock, LK_RELEASE); - - return 0; -} - -/* - * Locate the in-kernel vnode based on the cookie received given - * from userspace. Returns a vnode, if found, NULL otherwise. - * The parameter "lock" control whether to lock the possible or - * not. Locking always might cause us to lock against ourselves - * in situations where we want the vnode but don't care for the - * vnode lock, e.g. file server issued putpages. - */ -int -puffs_cookie2vnode(struct puffs_mount *pmp, puffs_cookie_t ck, - int willcreate, struct vnode **vpp) -{ - struct puffs_node *pnode; - struct puffs_newcookie *pnc; - struct vnode *vp; - int rv; - - /* - * Handle root in a special manner, since we want to make sure - * pmp_root is properly set. - */ - if (ck == pmp->pmp_root_cookie) { - if ((rv = puffs_makeroot(pmp))) - return rv; - *vpp = pmp->pmp_root; - return 0; - } - - lockmgr(&pmp->pmp_lock, LK_EXCLUSIVE); - pnode = puffs_cookie2pnode(pmp, ck); - if (pnode == NULL) { - if (willcreate) { - pnc = kmalloc(sizeof(struct puffs_newcookie), - M_PUFFS, M_WAITOK); - pnc->pnc_cookie = ck; - LIST_INSERT_HEAD(&pmp->pmp_newcookie, pnc, pnc_entries); - } - lockmgr(&pmp->pmp_lock, LK_RELEASE); - return PUFFS_NOSUCHCOOKIE; - } - vp = pnode->pn_vp; - vhold(vp); - lockmgr(&pmp->pmp_lock, LK_RELEASE); - - rv = vget(vp, LK_EXCLUSIVE); - vdrop(vp); - if (rv) - return rv; - - *vpp = vp; - return 0; -} - -void -puffs_updatenode(struct puffs_node *pn, int flags) -{ - struct timespec ts; - - if (flags == 0) - return; - - nanotime(&ts); - - if (flags & PUFFS_UPDATEATIME) { - pn->pn_mc_atime = ts; - pn->pn_stat |= PNODE_METACACHE_ATIME; - } - if (flags & PUFFS_UPDATECTIME) { - pn->pn_mc_ctime = ts; - pn->pn_stat |= PNODE_METACACHE_CTIME; - } - if (flags & PUFFS_UPDATEMTIME) { - pn->pn_mc_mtime = ts; - pn->pn_stat |= PNODE_METACACHE_MTIME; - } -} - -int -puffs_meta_setsize(struct vnode *vp, off_t nsize, int trivial) -{ - struct puffs_node *pn = VPTOPP(vp); - struct puffs_mount *pmp = VPTOPUFFSMP(vp); - int biosize = vp->v_mount->mnt_stat.f_iosize; - off_t osize; - int error; - - osize = puffs_meta_getsize(vp); - pn->pn_mc_size = nsize; - if (pn->pn_serversize != nsize) - pn->pn_stat |= PNODE_METACACHE_SIZE; - else - pn->pn_stat &= ~PNODE_METACACHE_SIZE; - - if (!PUFFS_USE_PAGECACHE(pmp)) - return 0; - - if (nsize < osize) { - error = nvtruncbuf(vp, nsize, biosize, -1, 0); - } else { - error = nvextendbuf(vp, osize, nsize, - biosize, biosize, -1, -1, - trivial); - } - - return error; -} - -/* - * Add reference to node. - * mutex held on entry and return - */ -void -puffs_referencenode(struct puffs_node *pn) -{ - - KKASSERT(lockstatus(&pn->pn_mtx, curthread) == LK_EXCLUSIVE); - pn->pn_refcount++; -} - -/* - * Release pnode structure which dealing with references to the - * puffs_node instead of the vnode. Can't use vref()/vrele() on - * the vnode there, since that causes the lovely VOP_INACTIVE(), - * which in turn causes the lovely deadlock when called by the one - * who is supposed to handle it. - */ -void -puffs_releasenode(struct puffs_node *pn) -{ - - lockmgr(&pn->pn_mtx, LK_EXCLUSIVE); - if (--pn->pn_refcount == 0) { - lockmgr(&pn->pn_mtx, LK_RELEASE); - lockuninit(&pn->pn_mtx); -#ifdef XXXDF - seldestroy(&pn->pn_sel); -#endif - kfree(pn, M_PUFFS); - } else { - lockmgr(&pn->pn_mtx, LK_RELEASE); - } -} diff --git a/sys/vfs/puffs/puffs_subr.c b/sys/vfs/puffs/puffs_subr.c deleted file mode 100644 index f69fc6a091..0000000000 --- a/sys/vfs/puffs/puffs_subr.c +++ /dev/null @@ -1,189 +0,0 @@ -/* $NetBSD: puffs_subr.c,v 1.66 2008/11/16 19:34:30 pooka Exp $ */ - -/* - * Copyright (c) 2006, 2007 Antti Kantee. All Rights Reserved. - * - * Development of this software was supported by the - * Ulla Tuominen Foundation and the Finnish Cultural 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -MALLOC_DEFINE(M_PUFFS, "puffs", "PUFFS"); - -#ifdef PUFFSDEBUG -int puffsdebug = 1; -#endif - -void -puffs_makecn(struct puffs_kcn *pkcn, struct puffs_kcred *pkcr, - const struct namecache *ncp, struct ucred *cred) -{ - KKASSERT(ncp->nc_nlen < sizeof(pkcn->pkcn_name)); - pkcn->pkcn_namelen = ncp->nc_nlen; - strlcpy(pkcn->pkcn_name, ncp->nc_name, sizeof(pkcn->pkcn_name)); - - puffs_credcvt(pkcr, cred); -} - -/* - * Convert given credentials to struct puffs_kcred for userspace. - */ -void -puffs_credcvt(struct puffs_kcred *pkcr, struct ucred *cred) -{ - - memset(pkcr, 0, sizeof(struct puffs_kcred)); - - if (cred == NOCRED || cred == FSCRED) { - pkcr->pkcr_type = PUFFCRED_TYPE_INTERNAL; - if (cred == NOCRED) - pkcr->pkcr_internal = PUFFCRED_CRED_NOCRED; - if (cred == FSCRED) - pkcr->pkcr_internal = PUFFCRED_CRED_FSCRED; - } else { - pkcr->pkcr_type = PUFFCRED_TYPE_UUC; - cru2x(cred, &pkcr->pkcr_uuc); - } -} - -void -puffs_parkdone_asyncbioread(struct puffs_mount *pmp, - struct puffs_req *preq, void *arg) -{ - struct puffs_vnmsg_read *read_msg = (void *)preq; - struct buf *bp = arg; - size_t moved; - - DPRINTF(("%s\n", __func__)); - - bp->b_error = checkerr(pmp, preq->preq_rv, __func__); - if (bp->b_error == 0) { - if (read_msg->pvnr_resid > bp->b_bcount) { - puffs_senderr(pmp, PUFFS_ERR_READ, E2BIG, - "resid grew", preq->preq_cookie); - bp->b_error = E2BIG; - } else { - moved = bp->b_bcount - read_msg->pvnr_resid; - bp->b_resid = read_msg->pvnr_resid; - - memcpy(bp->b_data, read_msg->pvnr_data, moved); - } - } - - bpdone(bp, 0); -} - -void -puffs_parkdone_asyncbiowrite(struct puffs_mount *pmp, - struct puffs_req *preq, void *arg) -{ - struct puffs_vnmsg_write *write_msg = (void *)preq; - struct buf *bp = arg; - - DPRINTF(("%s\n", __func__)); - - bp->b_error = checkerr(pmp, preq->preq_rv, __func__); - if (bp->b_error == 0) { - if (write_msg->pvnr_resid > bp->b_bcount) { - puffs_senderr(pmp, PUFFS_ERR_WRITE, E2BIG, - "resid grew", preq->preq_cookie); - bp->b_error = E2BIG; - } else { - bp->b_resid = write_msg->pvnr_resid; - } - } - - bpdone(bp, 0); -} - -/* XXX: userspace can leak kernel resources */ -void -puffs_parkdone_poll(struct puffs_mount *pmp, struct puffs_req *preq, void *arg) -{ - struct puffs_vnmsg_poll *poll_msg = (void *)preq; - struct puffs_node *pn = arg; - int revents, error; - - error = checkerr(pmp, preq->preq_rv, __func__); - if (error) - revents = poll_msg->pvnr_events; - else - revents = POLLERR; - - lockmgr(&pn->pn_mtx, LK_EXCLUSIVE); - pn->pn_revents |= revents; - lockmgr(&pn->pn_mtx, LK_RELEASE); - -#ifdef XXXDF - selnotify(&pn->pn_sel, revents, 0); -#endif - - puffs_releasenode(pn); -} - -void -puffs_mp_reference(struct puffs_mount *pmp) -{ - - KKASSERT(lockstatus(&pmp->pmp_lock, curthread) == LK_EXCLUSIVE); - pmp->pmp_refcount++; -} - -void -puffs_mp_release(struct puffs_mount *pmp) -{ - - KKASSERT(lockstatus(&pmp->pmp_lock, curthread) == LK_EXCLUSIVE); - if (--pmp->pmp_refcount == 0) - cv_broadcast(&pmp->pmp_refcount_cv); -} - -void -puffs_senderr(struct puffs_mount *pmp, int type, int error, - const char *str, puffs_cookie_t ck) -{ - struct puffs_msgpark *park; - struct puffs_error *perr; - - puffs_msgmem_alloc(sizeof(struct puffs_error), &park, (void *)&perr, 1); - puffs_msg_setfaf(park); - puffs_msg_setinfo(park, PUFFSOP_ERROR, type, ck); - - perr->perr_error = error; - strlcpy(perr->perr_str, str, sizeof(perr->perr_str)); - - puffs_msg_enqueue(pmp, park); - puffs_msgmem_release(park); -} diff --git a/sys/vfs/puffs/puffs_sys.h b/sys/vfs/puffs/puffs_sys.h deleted file mode 100644 index dc49859e81..0000000000 --- a/sys/vfs/puffs/puffs_sys.h +++ /dev/null @@ -1,329 +0,0 @@ -/* $NetBSD: puffs_sys.h,v 1.77 2011/01/11 14:04:54 kefren 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. - */ - -#ifndef _PUFFS_SYS_H_ -#define _PUFFS_SYS_H_ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -MALLOC_DECLARE(M_PUFFS); - -extern struct vop_ops puffs_vnode_vops; -extern struct vop_ops puffs_fifo_vops; - -#ifdef DEBUG -#ifndef PUFFSDEBUG -#define PUFFSDEBUG -#endif -#endif - -#ifdef PUFFSDEBUG -extern int puffsdebug; /* puffs_subr.c */ -#define DPRINTF(x) if (puffsdebug > 0) kprintf x -#define DPRINTF_VERBOSE(x) if (puffsdebug > 1) kprintf x -#else -#define DPRINTF(x) -#define DPRINTF_VERBOSE(x) -#endif - -#define MPTOPUFFSMP(mp) ((struct puffs_mount *)((mp)->mnt_data)) -#define PMPTOMP(pmp) (pmp->pmp_mp) -#define VPTOPP(vp) ((struct puffs_node *)(vp)->v_data) -#define VPTOPNC(vp) (((struct puffs_node *)(vp)->v_data)->pn_cookie) -#define VPTOPUFFSMP(vp) MPTOPUFFSMP((vp)->v_mount) - -/* we don't pass the kernel overlay to userspace */ -#define PUFFS_TOFHSIZE(s) ((s)==0 ? (s) : (s)+4) -#define PUFFS_FROMFHSIZE(s) ((s)==0 ? (s) : (s)-4) - -#define ALLOPS(pmp) (pmp->pmp_flags & PUFFS_KFLAG_ALLOPS) -#define EXISTSOP(pmp, op) \ - (ALLOPS(pmp) || ((pmp)->pmp_vnopmask[PUFFS_VN_##op])) - -#define PUFFS_USE_NAMECACHE(pmp) \ - (((pmp)->pmp_flags & PUFFS_KFLAG_NOCACHE_NAME) == 0) -#define PUFFS_USE_PAGECACHE(pmp) \ - (((pmp)->pmp_flags & PUFFS_KFLAG_NOCACHE_PAGE) == 0) - -#define PUFFS_WCACHEINFO(pmp) 0 - -struct puffs_newcookie { - puffs_cookie_t pnc_cookie; - - LIST_ENTRY(puffs_newcookie) pnc_entries; -}; - -enum puffs_sopreqtype { - PUFFS_SOPREQSYS_EXIT, - PUFFS_SOPREQ_FLUSH, - PUFFS_SOPREQ_UNMOUNT, -}; - -struct puffs_sopreq { - union { - struct puffs_req preq; - struct puffs_flush pf; - } psopr_u; - - enum puffs_sopreqtype psopr_sopreq; - TAILQ_ENTRY(puffs_sopreq) psopr_entries; -}; -#define psopr_preq psopr_u.preq -#define psopr_pf psopr_u.pf - -TAILQ_HEAD(puffs_wq, puffs_msgpark); -LIST_HEAD(puffs_node_hashlist, puffs_node); -struct puffs_mount { - struct lock pmp_lock; - - struct puffs_kargs pmp_args; -#define pmp_flags pmp_args.pa_flags -#define pmp_vnopmask pmp_args.pa_vnopmask - - struct puffs_wq pmp_msg_touser; - int pmp_msg_touser_count; - struct cv pmp_msg_waiter_cv; - size_t pmp_msg_maxsize; - - struct puffs_wq pmp_msg_replywait; - - struct puffs_node_hashlist *pmp_pnodehash; - int pmp_npnodehash; - - LIST_HEAD(, puffs_newcookie) pmp_newcookie; - - struct mount *pmp_mp; - - struct vnode *pmp_root; - puffs_cookie_t pmp_root_cookie; - enum vtype pmp_root_vtype; - vsize_t pmp_root_vsize; - dev_t pmp_root_rdev; - - struct putter_instance *pmp_pi; - - unsigned int pmp_refcount; - struct cv pmp_refcount_cv; - - struct cv pmp_unmounting_cv; - uint8_t pmp_unmounting; - - uint8_t pmp_status; - uint8_t pmp_suspend; - - uint8_t *pmp_curput; - size_t pmp_curres; - void *pmp_curopaq; - - uint64_t pmp_nextmsgid; - - struct lock pmp_sopmtx; - struct cv pmp_sopcv; - int pmp_sopthrcount; - TAILQ_HEAD(, puffs_sopreq) pmp_sopreqs; -}; - -#define PUFFSTAT_BEFOREINIT 0 -#define PUFFSTAT_MOUNTING 1 -#define PUFFSTAT_RUNNING 2 -#define PUFFSTAT_DYING 3 /* Do you want your possessions identified? */ - - -#define PNODE_NOREFS 0x01 /* no backend reference */ -#define PNODE_DYING 0x02 /* NOREFS + inactive */ -#define PNODE_FAF 0x04 /* issue all operations as FAF */ -#define PNODE_DOINACT 0x08 /* if inactive-on-demand, call inactive */ - -#define PNODE_METACACHE_ATIME 0x10 /* cache atime metadata */ -#define PNODE_METACACHE_CTIME 0x20 /* cache atime metadata */ -#define PNODE_METACACHE_MTIME 0x40 /* cache atime metadata */ -#define PNODE_METACACHE_SIZE 0x80 /* cache atime metadata */ -#define PNODE_METACACHE_MASK 0xf0 - -struct puffs_node { - struct lock pn_mtx; - int pn_refcount; - - puffs_cookie_t pn_cookie; /* userspace pnode cookie */ - struct vnode *pn_vp; /* backpointer to vnode */ - uint32_t pn_stat; /* node status */ - -#ifdef XXXDF - struct selinfo pn_sel; /* for selecting on the node */ -#endif - short pn_revents; /* available events */ - - /* metacache */ - struct timespec pn_mc_atime; - struct timespec pn_mc_ctime; - struct timespec pn_mc_mtime; - u_quad_t pn_mc_size; - - voff_t pn_serversize; - - struct lockf pn_lockf; - - LIST_ENTRY(puffs_node) pn_hashent; -}; - -typedef void (*parkdone_fn)(struct puffs_mount *, struct puffs_req *, void *); - -struct puffs_msgpark; -void puffs_msgif_init(void); -void puffs_msgif_destroy(void); -int puffs_msgmem_alloc(size_t, struct puffs_msgpark **, void **, int); -void puffs_msgmem_release(struct puffs_msgpark *); - -void puffs_sop_thread(void *); - -void puffs_msg_setfaf(struct puffs_msgpark *); -void puffs_msg_setdelta(struct puffs_msgpark *, size_t); -void puffs_msg_setinfo(struct puffs_msgpark *, int, int, puffs_cookie_t); -void puffs_msg_setcall(struct puffs_msgpark *, parkdone_fn, void *); - -void puffs_msg_enqueue(struct puffs_mount *, struct puffs_msgpark *); -int puffs_msg_wait(struct puffs_mount *, struct puffs_msgpark *); -int puffs_msg_wait2(struct puffs_mount *, struct puffs_msgpark *, - struct puffs_node *, struct puffs_node *); - -void puffs_msg_sendresp(struct puffs_mount *, struct puffs_req *, int); - -int puffs_getvnode(struct mount *, puffs_cookie_t, enum vtype, - voff_t, struct vnode **); -int puffs_newnode(struct mount *, struct vnode *, struct vnode **, - puffs_cookie_t, enum vtype); -void puffs_putvnode(struct vnode *); - -void puffs_releasenode(struct puffs_node *); -void puffs_referencenode(struct puffs_node *); - -#define PUFFS_NOSUCHCOOKIE (-1) -int puffs_cookie2vnode(struct puffs_mount *, puffs_cookie_t, int, - struct vnode **); -void puffs_makecn(struct puffs_kcn *, struct puffs_kcred *, - const struct namecache *, struct ucred *); -void puffs_credcvt(struct puffs_kcred *, struct ucred *); - -void puffs_parkdone_asyncbioread(struct puffs_mount *, - struct puffs_req *, void *); -void puffs_parkdone_asyncbiowrite(struct puffs_mount *, - struct puffs_req *, void *); -void puffs_parkdone_poll(struct puffs_mount *, struct puffs_req *, void *); - -void puffs_mp_reference(struct puffs_mount *); -void puffs_mp_release(struct puffs_mount *); - -void puffs_gop_size(struct vnode *, off_t, off_t *, int); -void puffs_gop_markupdate(struct vnode *, int); - -void puffs_senderr(struct puffs_mount *, int, int, const char *, - puffs_cookie_t); - -void puffs_updatenode(struct puffs_node *, int); -#define PUFFS_UPDATEATIME 0x01 -#define PUFFS_UPDATECTIME 0x02 -#define PUFFS_UPDATEMTIME 0x04 - -int puffs_meta_setsize(struct vnode *, off_t, int); - -void puffs_userdead(struct puffs_mount *); - -int puffs_directread(struct vnode *, struct uio *, int, struct ucred *); -int puffs_directwrite(struct vnode *, struct uio *, int, struct ucred *); -int puffs_bioread(struct vnode *, struct uio *, int, struct ucred *); -int puffs_biowrite(struct vnode *, struct uio *, int, struct ucred *); -int puffs_doio(struct vnode *vp, struct bio *bio, struct thread *td); - - -/* for putter */ -int puffs_msgif_getout(void *, size_t, int, uint8_t **, size_t *, void **); -void puffs_msgif_releaseout(void *, void *, int); -int puffs_msgif_dispatch(void *, struct putter_hdr *); -size_t puffs_msgif_waitcount(void *); -int puffs_msgif_close(void *); - -static __inline off_t -puffs_meta_getsize(struct vnode *vp) -{ - struct puffs_node *pn = VPTOPP(vp); - - if ((pn->pn_stat & PNODE_METACACHE_SIZE) != 0) - return pn->pn_mc_size; - return pn->pn_serversize; -} - -static __inline int -checkerr(struct puffs_mount *pmp, int error, const char *str) -{ - - if (error < 0 || error > ELAST) { - puffs_senderr(pmp, PUFFS_ERR_ERROR, error, str, NULL); - error = EPROTO; - } - - return error; -} - -#define PUFFS_MSG_VARS(type, a) \ - struct puffs_##type##msg_##a *a##_msg; \ - struct puffs_msgpark *park_##a = NULL - -#define PUFFS_MSG_ALLOC(type, a) \ - puffs_msgmem_alloc(sizeof(struct puffs_##type##msg_##a), \ - &park_##a, (void *)& a##_msg, 1) - -#define PUFFS_MSG_RELEASE(a) \ -do { \ - if (park_##a) puffs_msgmem_release(park_##a); \ -} while (/*CONSTCOND*/0) - -#define PUFFS_MSG_ENQUEUEWAIT(pmp, park, var) \ -do { \ - puffs_msg_enqueue(pmp, park); \ - var = puffs_msg_wait(pmp, park); \ -} while (/*CONSTCOND*/0) - -#define PUFFS_MSG_ENQUEUEWAIT2(pmp, park, vp1, vp2, var) \ -do { \ - puffs_msg_enqueue(pmp, park); \ - var = puffs_msg_wait2(pmp, park, vp1, vp2); \ -} while (/*CONSTCOND*/0) - -#endif /* _PUFFS_SYS_H_ */ diff --git a/sys/vfs/puffs/puffs_vfsops.c b/sys/vfs/puffs/puffs_vfsops.c deleted file mode 100644 index 23357916e4..0000000000 --- a/sys/vfs/puffs/puffs_vfsops.c +++ /dev/null @@ -1,822 +0,0 @@ -/* $NetBSD: puffs_vfsops.c,v 1.96 2011/06/12 03:35:54 rmind 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include - -#ifndef PUFFS_PNODEBUCKETS -#define PUFFS_PNODEBUCKETS 256 -#endif -#ifndef PUFFS_MAXPNODEBUCKETS -#define PUFFS_MAXPNODEBUCKETS 8192 -#endif -int puffs_pnodebuckets_default = PUFFS_PNODEBUCKETS; -int puffs_maxpnodebuckets = PUFFS_MAXPNODEBUCKETS; - -#define BUCKETALLOC(a) (sizeof(struct puffs_pnode_hashlist *) * (a)) - -#ifndef __arraycount -#define __arraycount(__x) (sizeof(__x) / sizeof(__x[0])) -#endif - -SYSCTL_NODE(_vfs, OID_AUTO, puffs, CTLFLAG_RW, 0, "PUFFS filesystem"); - -static int puffs_use_pagecache = 0; -SYSCTL_INT(_vfs_puffs, OID_AUTO, pagecache, CTLFLAG_RW, &puffs_use_pagecache, - 0, "Enable page cache"); - -static struct putter_ops puffs_putter = { - .pop_getout = puffs_msgif_getout, - .pop_releaseout = puffs_msgif_releaseout, - .pop_waitcount = puffs_msgif_waitcount, - .pop_dispatch = puffs_msgif_dispatch, - .pop_close = puffs_msgif_close, -}; - -static int -puffs_vfsop_mount(struct mount *mp, char *path, char *data, - struct ucred *cred) -{ - struct puffs_mount *pmp = NULL; - struct puffs_kargs *args, kargs; - char *p; - int error = 0, i; - pid_t mntpid = curproc->p_pid; - - /* update is not supported currently */ - if (mp->mnt_flag & MNT_UPDATE) - return EOPNOTSUPP; - - /* - * We need the file system name - */ - if (!data) - return EINVAL; - - copyin(data, &kargs, sizeof(kargs)); - args = &kargs; - - if (args->pa_vers != PUFFSVERSION) { - kprintf("puffs_mount: development version mismatch: " - "kernel %d, lib %d\n", PUFFSVERSION, args->pa_vers); - error = EINVAL; - goto out; - } - - if ((args->pa_flags & ~PUFFS_KFLAG_MASK) != 0) { - kprintf("puffs_mount: invalid KFLAGs 0x%x\n", args->pa_flags); - error = EINVAL; - goto out; - } - if ((args->pa_fhflags & ~PUFFS_FHFLAG_MASK) != 0) { - kprintf("puffs_mount: invalid FHFLAGs 0x%x\n", args->pa_fhflags); - error = EINVAL; - goto out; - } - - for (i = 0; i < __arraycount(args->pa_spare); i++) { - if (args->pa_spare[i] != 0) { - kprintf("puffs_mount: pa_spare[%d] = 0x%x\n", - i, args->pa_spare[i]); - error = EINVAL; - goto out; - } - } - - /* use dummy value for passthrough */ - if (args->pa_fhflags & PUFFS_FHFLAG_PASSTHROUGH) - args->pa_fhsize = MAXFIDSZ; - - /* sanitize file handle length */ - if (PUFFS_TOFHSIZE(args->pa_fhsize) > sizeof(struct fid)) { - kprintf("puffs_mount: handle size %zu too large\n", - args->pa_fhsize); - error = EINVAL; - goto out; - } - /* sanity check file handle max sizes */ - if (args->pa_fhsize && args->pa_fhflags & PUFFS_FHFLAG_PROTOMASK) { - size_t kfhsize = PUFFS_TOFHSIZE(args->pa_fhsize); - - if (args->pa_fhflags & PUFFS_FHFLAG_NFSV2) { - if (kfhsize > NFSX_FH(0)) { - kprintf("puffs_mount: fhsize larger than " - "NFSv2 max %d\n", - PUFFS_FROMFHSIZE(NFSX_V2FH)); - error = EINVAL; - goto out; - } - } - - if (args->pa_fhflags & PUFFS_FHFLAG_NFSV3) { - if (kfhsize > NFSX_FH(1)) { - kprintf("puffs_mount: fhsize larger than " - "NFSv3 max %d\n", - PUFFS_FROMFHSIZE(NFSX_V3FHMAX)); - error = EINVAL; - goto out; - } - } - } - - /* don't allow non-printing characters (like my sweet umlauts.. snif) */ - args->pa_typename[sizeof(args->pa_typename)-1] = '\0'; - for (p = args->pa_typename; *p; p++) - if (*p < ' ' || *p > '~') - *p = '.'; - - args->pa_mntfromname[sizeof(args->pa_mntfromname)-1] = '\0'; - for (p = args->pa_mntfromname; *p; p++) - if (*p < ' ' || *p > '~') - *p = '.'; - - /* build real name */ - bzero(mp->mnt_stat.f_fstypename, MFSNAMELEN); - (void)strlcpy(mp->mnt_stat.f_fstypename, PUFFS_TYPEPREFIX, MFSNAMELEN); - (void)strlcat(mp->mnt_stat.f_fstypename, args->pa_typename, MFSNAMELEN); - - bzero(mp->mnt_stat.f_mntfromname, MNAMELEN); - strlcpy(mp->mnt_stat.f_mntfromname, args->pa_mntfromname, MFSNAMELEN); - bzero(mp->mnt_stat.f_mntonname, MNAMELEN); - copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN, NULL); - - /* inform user server if it got the max request size it wanted */ - if (args->pa_maxmsglen == 0 || args->pa_maxmsglen > PUFFS_MSG_MAXSIZE) - args->pa_maxmsglen = PUFFS_MSG_MAXSIZE; - else if (args->pa_maxmsglen < 2*PUFFS_MSGSTRUCT_MAX) - args->pa_maxmsglen = 2*PUFFS_MSGSTRUCT_MAX; - - if (args->pa_nhashbuckets == 0) - args->pa_nhashbuckets = puffs_pnodebuckets_default; - if (args->pa_nhashbuckets < 1) - args->pa_nhashbuckets = 1; - if (args->pa_nhashbuckets > PUFFS_MAXPNODEBUCKETS) { - args->pa_nhashbuckets = puffs_maxpnodebuckets; - kprintf("puffs_mount: using %d hash buckets. " - "adjust puffs_maxpnodebuckets for more\n", - puffs_maxpnodebuckets); - } - - mp->mnt_stat.f_iosize = DEV_BSIZE; - mp->mnt_stat.f_bsize = DEV_BSIZE; - mp->mnt_vstat.f_frsize = DEV_BSIZE; - mp->mnt_vstat.f_bsize = DEV_BSIZE; - mp->mnt_vstat.f_namemax = args->pa_svfsb.f_namemax; - - pmp = kmalloc(sizeof(struct puffs_mount), M_PUFFS, M_ZERO | M_WAITOK); - - mp->mnt_flag &= ~MNT_LOCAL; /* we don't really know, so ... */ - mp->mnt_data = (qaddr_t)pmp; - -#if 0 - /* - * XXX: puffs code is MPSAFE. However, VFS really isn't. - * Currently, there is nothing which protects an inode from - * reclaim while there are threads inside the file system. - * This means that in the event of a server crash, an MPSAFE - * mount is likely to end up accessing invalid memory. For the - * non-mpsafe case, the kernel lock, general structure of - * puffs and pmp_refcount protect the threads during escape. - * - * Fixing this will require: - * a) fixing vfs - * OR - * b) adding a small sleep to puffs_msgif_close() between - * userdead() and dounmount(). - * (well, this isn't really a fix, but would solve - * 99.999% of the race conditions). - * - * Also, in the event of "b", unmount -f should be used, - * like with any other file system, sparingly and only when - * it is "known" to be safe. - */ - mp->mnt_iflags |= IMNT_MPSAFE; -#endif - - pmp->pmp_status = PUFFSTAT_MOUNTING; - pmp->pmp_mp = mp; - pmp->pmp_msg_maxsize = args->pa_maxmsglen; - pmp->pmp_args = *args; - - if (puffs_use_pagecache == 0) - pmp->pmp_flags |= PUFFS_KFLAG_NOCACHE_PAGE; - - pmp->pmp_npnodehash = args->pa_nhashbuckets; - pmp->pmp_pnodehash = kmalloc(BUCKETALLOC(pmp->pmp_npnodehash), - M_PUFFS, M_WAITOK); - for (i = 0; i < pmp->pmp_npnodehash; i++) - LIST_INIT(&pmp->pmp_pnodehash[i]); - LIST_INIT(&pmp->pmp_newcookie); - - /* - * Inform the fileops processing code that we have a mountpoint. - * If it doesn't know about anyone with our pid/fd having the - * device open, punt - */ - if ((pmp->pmp_pi - = putter_attach(mntpid, args->pa_minor, pmp, &puffs_putter)) == NULL) { - error = ENOENT; - goto out; - } - - /* XXX: check parameters */ - pmp->pmp_root_cookie = args->pa_root_cookie; - pmp->pmp_root_vtype = args->pa_root_vtype; - pmp->pmp_root_vsize = args->pa_root_vsize; - pmp->pmp_root_rdev = args->pa_root_rdev; - - lockinit(&pmp->pmp_lock, "puffs pmp_lock", 0, 0); - lockinit(&pmp->pmp_sopmtx, "puffs pmp_sopmtx", 0, 0); - cv_init(&pmp->pmp_msg_waiter_cv, "puffsget"); - cv_init(&pmp->pmp_refcount_cv, "puffsref"); - cv_init(&pmp->pmp_unmounting_cv, "puffsum"); - cv_init(&pmp->pmp_sopcv, "puffsop"); - TAILQ_INIT(&pmp->pmp_msg_touser); - TAILQ_INIT(&pmp->pmp_msg_replywait); - TAILQ_INIT(&pmp->pmp_sopreqs); - - if ((error = kthread_create(puffs_sop_thread, pmp, NULL, - "puffsop")) != 0) - goto out; - pmp->pmp_sopthrcount = 1; - - DPRINTF(("puffs_mount: mount point at %p, puffs specific at %p\n", - mp, MPTOPUFFSMP(mp))); - - vfs_getnewfsid(mp); - - vfs_add_vnodeops(mp, &puffs_vnode_vops, &mp->mnt_vn_norm_ops); - vfs_add_vnodeops(mp, &puffs_fifo_vops, &mp->mnt_vn_fifo_ops); - - out: - if (error && pmp && pmp->pmp_pi) - putter_detach(pmp->pmp_pi); - if (error && pmp && pmp->pmp_pnodehash) - kfree(pmp->pmp_pnodehash, M_PUFFS); - if (error && pmp) - kfree(pmp, M_PUFFS); - return error; -} - -static int -puffs_vfsop_unmount(struct mount *mp, int mntflags) -{ - PUFFS_MSG_VARS(vfs, unmount); - struct puffs_mount *pmp; - int error, force; - - error = 0; - force = mntflags & MNT_FORCE; - pmp = MPTOPUFFSMP(mp); - - DPRINTF(("puffs_unmount: detach filesystem from vfs, current " - "status 0x%x\n", pmp->pmp_status)); - - /* - * flush all the vnodes. VOP_RECLAIM() takes care that the - * root vnode does not get flushed until unmount. The - * userspace root node cookie is stored in the mount - * structure, so we can always re-instantiate a root vnode, - * should userspace unmount decide it doesn't want to - * cooperate. - */ - error = vflush(mp, 1, force ? FORCECLOSE : 0); - if (error) - goto out; - - /* - * If we are not DYING, we should ask userspace's opinion - * about the situation - */ - lockmgr(&pmp->pmp_lock, LK_EXCLUSIVE); - if (pmp->pmp_status != PUFFSTAT_DYING) { - pmp->pmp_unmounting = 1; - lockmgr(&pmp->pmp_lock, LK_RELEASE); - - PUFFS_MSG_ALLOC(vfs, unmount); - puffs_msg_setinfo(park_unmount, - PUFFSOP_VFS, PUFFS_VFS_UNMOUNT, NULL); - unmount_msg->pvfsr_flags = mntflags; - - PUFFS_MSG_ENQUEUEWAIT(pmp, park_unmount, error); - PUFFS_MSG_RELEASE(unmount); - - error = checkerr(pmp, error, __func__); - DPRINTF(("puffs_unmount: error %d force %d\n", error, force)); - - lockmgr(&pmp->pmp_lock, LK_EXCLUSIVE); - pmp->pmp_unmounting = 0; - cv_broadcast(&pmp->pmp_unmounting_cv); - } - - /* - * if userspace cooperated or we really need to die, - * screw what userland thinks and just die. - */ - if (error == 0 || force) { - struct puffs_sopreq *psopr; - - /* tell waiters & other resources to go unwait themselves */ - puffs_userdead(pmp); - putter_detach(pmp->pmp_pi); - - /* - * Wait until there are no more users for the mount resource. - * Notice that this is hooked against transport_close - * and return from touser. In an ideal world, it would - * be hooked against final return from all operations. - * But currently it works well enough, since nobody - * does weird blocking voodoo after return from touser(). - */ - while (pmp->pmp_refcount != 0) - cv_wait(&pmp->pmp_refcount_cv, &pmp->pmp_lock); - lockmgr(&pmp->pmp_lock, LK_RELEASE); - - /* - * Release kernel thread now that there is nothing - * it would be wanting to lock. - */ - psopr = kmalloc(sizeof(*psopr), M_PUFFS, M_WAITOK); - psopr->psopr_sopreq = PUFFS_SOPREQSYS_EXIT; - lockmgr(&pmp->pmp_sopmtx, LK_EXCLUSIVE); - if (pmp->pmp_sopthrcount == 0) { - lockmgr(&pmp->pmp_sopmtx, LK_RELEASE); - kfree(psopr, M_PUFFS); - lockmgr(&pmp->pmp_sopmtx, LK_EXCLUSIVE); - KKASSERT(pmp->pmp_sopthrcount == 0); - } else { - TAILQ_INSERT_TAIL(&pmp->pmp_sopreqs, - psopr, psopr_entries); - cv_signal(&pmp->pmp_sopcv); - } - while (pmp->pmp_sopthrcount > 0) - cv_wait(&pmp->pmp_sopcv, &pmp->pmp_sopmtx); - lockmgr(&pmp->pmp_sopmtx, LK_RELEASE); - - /* free resources now that we hopefully have no waiters left */ - cv_destroy(&pmp->pmp_unmounting_cv); - cv_destroy(&pmp->pmp_refcount_cv); - cv_destroy(&pmp->pmp_msg_waiter_cv); - cv_destroy(&pmp->pmp_sopcv); - lockuninit(&pmp->pmp_lock); - lockuninit(&pmp->pmp_sopmtx); - - kfree(pmp->pmp_pnodehash, M_PUFFS); - kfree(pmp, M_PUFFS); - error = 0; - } else { - lockmgr(&pmp->pmp_lock, LK_RELEASE); - } - - out: - DPRINTF(("puffs_unmount: return %d\n", error)); - return error; -} - -/* - * This doesn't need to travel to userspace - */ -static int -puffs_vfsop_root(struct mount *mp, struct vnode **vpp) -{ - struct puffs_mount *pmp = MPTOPUFFSMP(mp); - int rv; - - rv = puffs_cookie2vnode(pmp, pmp->pmp_root_cookie, 1, vpp); - KKASSERT(rv != PUFFS_NOSUCHCOOKIE); - - return rv; -} - -static int -puffs_vfsop_statvfs(struct mount *mp, struct statvfs *sbp, struct ucred *cred) -{ - PUFFS_MSG_VARS(vfs, statvfs); - struct puffs_mount *pmp; - int error = 0; - - pmp = MPTOPUFFSMP(mp); - - /* - * If we are mounting, it means that the userspace counterpart - * is calling mount(2), but mount(2) also calls statvfs. So - * requesting statvfs from userspace would mean a deadlock. - * Compensate. - */ - if (__predict_false(pmp->pmp_status == PUFFSTAT_MOUNTING)) - return EINPROGRESS; - - PUFFS_MSG_ALLOC(vfs, statvfs); - puffs_msg_setinfo(park_statvfs, PUFFSOP_VFS, PUFFS_VFS_STATVFS, NULL); - - PUFFS_MSG_ENQUEUEWAIT(pmp, park_statvfs, error); - error = checkerr(pmp, error, __func__); - statvfs_msg->pvfsr_sb.f_bsize = DEV_BSIZE; - - /* - * Try to produce a sensible result even in the event - * of userspace error. - * - * XXX: cache the copy in non-error case - */ - if (!error) { - (void)memcpy(sbp, &statvfs_msg->pvfsr_sb, - sizeof(struct statvfs)); - } else { - (void)memcpy(sbp, &mp->mnt_stat, - sizeof(struct statvfs)); - } - - PUFFS_MSG_RELEASE(statvfs); - return error; -} - -#ifdef XXXDF -static int -pageflush(struct mount *mp, kauth_cred_t cred, int waitfor) -{ - struct puffs_node *pn; - struct vnode *vp, *mvp; - int error, rv; - - error = 0; - - /* Allocate a marker vnode. */ - if ((mvp = vnalloc(mp)) == NULL) - return ENOMEM; - - /* - * Sync all cached data from regular vnodes (which are not - * currently locked, see below). After this we call VFS_SYNC - * for the fs server, which should handle data and metadata for - * all the nodes it knows to exist. - */ - lockmgr(&mntvnode_lock, LK_EXCLUSIVE); - loop: - for (vp = TAILQ_FIRST(&mp->mnt_vnodelist); vp; vp = vunmark(mvp)) { - vmark(mvp, vp); - if (vp->v_mount != mp || vismarker(vp)) - continue; - - lockmgr(&vp->v_interlock, LK_EXCLUSIVE); - pn = VPTOPP(vp); - if (vp->v_type != VREG || UVM_OBJ_IS_CLEAN(&vp->v_uobj)) { - lockmgr(&vp->v_interlock, LK_RELEASE); - continue; - } - - lockmgr(&mntvnode_lock, LK_RELEASE); - - /* - * Here we try to get a reference to the vnode and to - * lock it. This is mostly cargo-culted, but I will - * offer an explanation to why I believe this might - * actually do the right thing. - * - * If the vnode is a goner, we quite obviously don't need - * to sync it. - * - * If the vnode was busy, we don't need to sync it because - * this is never called with MNT_WAIT except from - * dounmount(), when we are wait-flushing all the dirty - * vnodes through other routes in any case. So there, - * sync() doesn't actually sync. Happy now? - */ - rv = vget(vp, LK_EXCLUSIVE | LK_NOWAIT); - if (rv) { - lockmgr(&mntvnode_lock, LK_EXCLUSIVE); - if (rv == ENOENT) { - (void)vunmark(mvp); - goto loop; - } - continue; - } - - /* hmm.. is the FAF thing entirely sensible? */ - if (waitfor == MNT_LAZY) { - lockmgr(&vp->v_interlock, LK_EXCLUSIVE); - pn->pn_stat |= PNODE_FAF; - lockmgr(&vp->v_interlock, LK_RELEASE); - } - rv = VOP_FSYNC(vp, cred, waitfor, 0, 0); - if (waitfor == MNT_LAZY) { - lockmgr(&vp->v_interlock, LK_EXCLUSIVE); - pn->pn_stat &= ~PNODE_FAF; - lockmgr(&vp->v_interlock, LK_RELEASE); - } - if (rv) - error = rv; - vput(vp); - lockmgr(&mntvnode_lock, LK_EXCLUSIVE); - } - lockmgr(&mntvnode_lock, LK_RELEASE); - vnfree(mvp); - - return error; -} -#endif - -static int -puffs_vfsop_sync(struct mount *mp, int waitfor) -{ - PUFFS_MSG_VARS(vfs, sync); - struct puffs_mount *pmp = MPTOPUFFSMP(mp); - int error, rv; - -#ifdef XXXDF - error = pageflush(mp, cred, waitfor); -#endif - - /* sync fs */ - PUFFS_MSG_ALLOC(vfs, sync); - sync_msg->pvfsr_waitfor = waitfor; - puffs_msg_setinfo(park_sync, PUFFSOP_VFS, PUFFS_VFS_SYNC, NULL); - - PUFFS_MSG_ENQUEUEWAIT(pmp, park_sync, rv); - error = checkerr(pmp, rv, __func__); - - PUFFS_MSG_RELEASE(sync); - DPRINTF(("puffs_vfsop_sync: result %d\n", error)); - return error; -} - -#ifdef XXXDF -static int -puffs_vfsop_fhtovp(struct mount *mp, struct vnode *rootvp, struct fid *fhp, - struct vnode **vpp) -{ - PUFFS_MSG_VARS(vfs, fhtonode); - struct puffs_mount *pmp = MPTOPUFFSMP(mp); - struct vnode *vp; - void *fhdata; - size_t argsize, fhlen; - int error; - - if (pmp->pmp_args.pa_fhsize == 0) - return EOPNOTSUPP; - - if (pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_PASSTHROUGH) { - fhlen = fhp->fid_len; - fhdata = fhp; - } else { - fhlen = PUFFS_FROMFHSIZE(fhp->fid_len); - fhdata = fhp->fid_data; - - if (pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_DYNAMIC) { - if (pmp->pmp_args.pa_fhsize < fhlen) - return EINVAL; - } else { - if (pmp->pmp_args.pa_fhsize != fhlen) - return EINVAL; - } - } - - argsize = sizeof(struct puffs_vfsmsg_fhtonode) + fhlen; - puffs_msgmem_alloc(argsize, &park_fhtonode, (void *)&fhtonode_msg, 1); - fhtonode_msg->pvfsr_dsize = fhlen; - memcpy(fhtonode_msg->pvfsr_data, fhdata, fhlen); - puffs_msg_setinfo(park_fhtonode, PUFFSOP_VFS, PUFFS_VFS_FHTOVP, NULL); - - PUFFS_MSG_ENQUEUEWAIT(pmp, park_fhtonode, error); - error = checkerr(pmp, error, __func__); - if (error) - goto out; - - error = puffs_cookie2vnode(pmp, fhtonode_msg->pvfsr_fhcookie, 1,1,&vp); - DPRINTF(("puffs_fhtovp: got cookie %p, existing vnode %p\n", - fhtonode_msg->pvfsr_fhcookie, vp)); - if (error == PUFFS_NOSUCHCOOKIE) { - error = puffs_getvnode(mp, fhtonode_msg->pvfsr_fhcookie, - fhtonode_msg->pvfsr_vtype, fhtonode_msg->pvfsr_size, - fhtonode_msg->pvfsr_rdev, &vp); - if (error) - goto out; - } else if (error) { - goto out; - } - - *vpp = vp; - out: - puffs_msgmem_release(park_fhtonode); - return error; -} - -static int -puffs_vfsop_vptofh(struct vnode *vp, struct fid *fhp) -{ - PUFFS_MSG_VARS(vfs, nodetofh); - struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); - size_t argsize, fhlen; - int error; - - if (pmp->pmp_args.pa_fhsize == 0) - return EOPNOTSUPP; - - /* if file handles are static len, we can test len immediately */ - if (((pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_DYNAMIC) == 0) - && ((pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_PASSTHROUGH) == 0) - && (PUFFS_FROMFHSIZE(*fh_size) < pmp->pmp_args.pa_fhsize)) { - *fh_size = PUFFS_TOFHSIZE(pmp->pmp_args.pa_fhsize); - return E2BIG; - } - - if (pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_PASSTHROUGH) - fhlen = *fh_size; - else - fhlen = PUFFS_FROMFHSIZE(*fh_size); - - argsize = sizeof(struct puffs_vfsmsg_nodetofh) + fhlen; - puffs_msgmem_alloc(argsize, &park_nodetofh, (void *)&nodetofh_msg, 1); - nodetofh_msg->pvfsr_fhcookie = VPTOPNC(vp); - nodetofh_msg->pvfsr_dsize = fhlen; - puffs_msg_setinfo(park_nodetofh, PUFFSOP_VFS, PUFFS_VFS_VPTOFH, NULL); - - PUFFS_MSG_ENQUEUEWAIT(pmp, park_nodetofh, error); - error = checkerr(pmp, error, __func__); - - if (pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_PASSTHROUGH) - fhlen = nodetofh_msg->pvfsr_dsize; - else if (pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_DYNAMIC) - fhlen = PUFFS_TOFHSIZE(nodetofh_msg->pvfsr_dsize); - else - fhlen = PUFFS_TOFHSIZE(pmp->pmp_args.pa_fhsize); - - if (error) { - if (error == E2BIG) - *fh_size = fhlen; - goto out; - } - - if (fhlen > FHANDLE_SIZE_MAX) { - puffs_senderr(pmp, PUFFS_ERR_VPTOFH, E2BIG, - "file handle too big", VPTOPNC(vp)); - error = EPROTO; - goto out; - } - - if (*fh_size < fhlen) { - *fh_size = fhlen; - error = E2BIG; - goto out; - } - *fh_size = fhlen; - - if (fhp) { - if (pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_PASSTHROUGH) { - memcpy(fhp, nodetofh_msg->pvfsr_data, fhlen); - } else { - fhp->fid_len = *fh_size; - memcpy(fhp->fid_data, nodetofh_msg->pvfsr_data, - nodetofh_msg->pvfsr_dsize); - } - } - - out: - puffs_msgmem_release(park_nodetofh); - return error; -} -#endif - -static int -puffs_vfsop_start(struct mount *mp, int flags) -{ - struct puffs_mount *pmp = MPTOPUFFSMP(mp); - - KKASSERT(pmp->pmp_status == PUFFSTAT_MOUNTING); - pmp->pmp_status = PUFFSTAT_RUNNING; - - return 0; -} - -static int -puffs_vfsop_init(struct vfsconf *vfc) -{ - - puffs_msgif_init(); - return 0; -} - -static int -puffs_vfsop_uninit(struct vfsconf *vfc) -{ - - puffs_msgif_destroy(); - return 0; -} - -#ifdef XXXDF -static int -puffs_vfsop_extattrctl(struct mount *mp, int cmd, struct vnode *vp, - int attrnamespace, const char *attrname, struct ucred *cred) -{ - PUFFS_MSG_VARS(vfs, extattrctl); - struct puffs_mount *pmp = MPTOPUFFSMP(mp); - struct puffs_node *pnp; - puffs_cookie_t pnc; - int error, flags; - - if (vp) { - /* doesn't make sense for puffs servers */ - if (vp->v_mount != mp) - return EXDEV; - pnp = VPTOPP(vp); - pnc = pnp->pn_cookie; - flags = PUFFS_EXTATTRCTL_HASNODE; - } else { - pnp = pnc = NULL; - flags = 0; - } - - PUFFS_MSG_ALLOC(vfs, extattrctl); - extattrctl_msg->pvfsr_cmd = cmd; - extattrctl_msg->pvfsr_attrnamespace = attrnamespace; - extattrctl_msg->pvfsr_flags = flags; - if (attrname) { - strlcpy(extattrctl_msg->pvfsr_attrname, attrname, - sizeof(extattrctl_msg->pvfsr_attrname)); - extattrctl_msg->pvfsr_flags |= PUFFS_EXTATTRCTL_HASATTRNAME; - } - puffs_msg_setinfo(park_extattrctl, - PUFFSOP_VFS, PUFFS_VFS_EXTATTRCTL, pnc); - - puffs_msg_enqueue(pmp, park_extattrctl); - if (vp) { - lockmgr(&pnp->pn_mtx, LK_EXCLUSIVE); - puffs_referencenode(pnp); - lockmgr(&pnp->pn_mtx, LK_RELEASE); - VOP_UNLOCK(vp); - } - error = puffs_msg_wait2(pmp, park_extattrctl, pnp, NULL); - PUFFS_MSG_RELEASE(extattrctl); - if (vp) { - puffs_releasenode(pnp); - } - - return checkerr(pmp, error, __func__); -} -#endif - -static struct vfsops puffs_vfsops = { - .vfs_mount = puffs_vfsop_mount, - .vfs_unmount = puffs_vfsop_unmount, - .vfs_root = puffs_vfsop_root, - .vfs_statvfs = puffs_vfsop_statvfs, - .vfs_sync = puffs_vfsop_sync, -#ifdef XXXFD - .vfs_fhtovp = puffs_vfsop_fhtovp, - .vfs_vptofh = puffs_vfsop_vptofh, - .vfs_extattrctl = puffs_vfsop_extattrctl, -#endif - .vfs_start = puffs_vfsop_start, - .vfs_init = puffs_vfsop_init, - .vfs_uninit = puffs_vfsop_uninit, -}; - -VFS_SET(puffs_vfsops, puffs, 0); -MODULE_DEPEND(puffs, putter, 1, 1, 1); diff --git a/sys/vfs/puffs/puffs_vnops.c b/sys/vfs/puffs/puffs_vnops.c deleted file mode 100644 index e8446c0e02..0000000000 --- a/sys/vfs/puffs/puffs_vnops.c +++ /dev/null @@ -1,1541 +0,0 @@ -/* $NetBSD: puffs_vnops.c,v 1.154 2011/07/04 08:07:30 manu 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -int (**puffs_vnodeop_p)(void *); - -#define ERROUT(err) \ -do { \ - error = err; \ - goto out; \ -} while (/*CONSTCOND*/0) - -static int callremove(struct puffs_mount *, puffs_cookie_t, puffs_cookie_t, - struct namecache *, struct ucred *); -static int callrmdir(struct puffs_mount *, puffs_cookie_t, puffs_cookie_t, - struct namecache *, struct ucred *); -static void callinactive(struct puffs_mount *, puffs_cookie_t, int); -static void callreclaim(struct puffs_mount *, puffs_cookie_t); -static int flushvncache(struct vnode *, int); - - -#define PUFFS_ABORT_LOOKUP 1 -#define PUFFS_ABORT_CREATE 2 -#define PUFFS_ABORT_MKNOD 3 -#define PUFFS_ABORT_MKDIR 4 -#define PUFFS_ABORT_SYMLINK 5 - -/* - * Press the pani^Wabort button! Kernel resource allocation failed. - */ -static void -puffs_abortbutton(struct puffs_mount *pmp, int what, - puffs_cookie_t dck, puffs_cookie_t ck, - struct namecache *ncp, struct ucred *cred) -{ - - switch (what) { - case PUFFS_ABORT_CREATE: - case PUFFS_ABORT_MKNOD: - case PUFFS_ABORT_SYMLINK: - callremove(pmp, dck, ck, ncp, cred); - break; - case PUFFS_ABORT_MKDIR: - callrmdir(pmp, dck, ck, ncp, cred); - break; - } - - callinactive(pmp, ck, 0); - callreclaim(pmp, ck); -} - -/* - * Begin vnode operations. - * - * A word from the keymaster about locks: generally we don't want - * to use the vnode locks at all: it creates an ugly dependency between - * the userlandia file server and the kernel. But we'll play along with - * the kernel vnode locks for now. However, even currently we attempt - * to release locks as early as possible. This is possible for some - * operations which a) don't need a locked vnode after the userspace op - * and b) return with the vnode unlocked. Theoretically we could - * unlock-do op-lock for others and order the graph in userspace, but I - * don't want to think of the consequences for the time being. - */ -static int -puffs_vnop_lookup(struct vop_nresolve_args *ap) -{ - PUFFS_MSG_VARS(vn, lookup); - struct puffs_mount *pmp = MPTOPUFFSMP(ap->a_dvp->v_mount); - struct nchandle *nch = ap->a_nch; - struct namecache *ncp = nch->ncp; - struct ucred *cred = ap->a_cred; - struct vnode *vp = NULL, *dvp = ap->a_dvp; - struct puffs_node *dpn; - int error; - - DPRINTF(("puffs_lookup: \"%s\", parent vnode %p\n", - ncp->nc_name, dvp)); - - PUFFS_MSG_ALLOC(vn, lookup); - puffs_makecn(&lookup_msg->pvnr_cn, &lookup_msg->pvnr_cn_cred, - ncp, cred); - - puffs_msg_setinfo(park_lookup, PUFFSOP_VN, - PUFFS_VN_LOOKUP, VPTOPNC(dvp)); - PUFFS_MSG_ENQUEUEWAIT2(pmp, park_lookup, dvp->v_data, NULL, error); - DPRINTF(("puffs_lookup: return of the userspace, part %d\n", error)); - if (error) { - error = checkerr(pmp, error, __func__); - if (error == ENOENT) - cache_setvp(nch, NULL); - goto out; - } - - /* - * Check that we don't get our parent node back, that would cause - * a pretty obvious deadlock. - */ - dpn = VPTOPP(dvp); - if (lookup_msg->pvnr_newnode == dpn->pn_cookie) { - puffs_senderr(pmp, PUFFS_ERR_LOOKUP, EINVAL, - "lookup produced parent cookie", lookup_msg->pvnr_newnode); - error = EPROTO; - goto out; - } - - error = puffs_cookie2vnode(pmp, lookup_msg->pvnr_newnode, 1, &vp); - if (error == PUFFS_NOSUCHCOOKIE) { - error = puffs_getvnode(dvp->v_mount, - lookup_msg->pvnr_newnode, lookup_msg->pvnr_vtype, - lookup_msg->pvnr_size, &vp); - if (error) { - puffs_abortbutton(pmp, PUFFS_ABORT_LOOKUP, VPTOPNC(dvp), - lookup_msg->pvnr_newnode, ncp, cred); - goto out; - } - } else if (error) { - puffs_abortbutton(pmp, PUFFS_ABORT_LOOKUP, VPTOPNC(dvp), - lookup_msg->pvnr_newnode, ncp, cred); - goto out; - } - - out: - if (!error && vp != NULL) { - vn_unlock(vp); - cache_setvp(nch, vp); - vrele(vp); - } - DPRINTF(("puffs_lookup: returning %d\n", error)); - PUFFS_MSG_RELEASE(lookup); - return error; -} - -static int -puffs_vnop_lookupdotdot(struct vop_nlookupdotdot_args *ap) -{ - PUFFS_MSG_VARS(vn, lookupdotdot); - struct puffs_mount *pmp = MPTOPUFFSMP(ap->a_dvp->v_mount); - struct ucred *cred = ap->a_cred; - struct vnode *vp, *dvp = ap->a_dvp; - struct puffs_node *dpn; - int error; - - *ap->a_vpp = NULL; - - DPRINTF(("puffs_lookupdotdot: vnode %p\n", dvp)); - - PUFFS_MSG_ALLOC(vn, lookupdotdot); - puffs_credcvt(&lookupdotdot_msg->pvnr_cred, cred); - - puffs_msg_setinfo(park_lookupdotdot, PUFFSOP_VN, - PUFFS_VN_LOOKUPDOTDOT, VPTOPNC(dvp)); - PUFFS_MSG_ENQUEUEWAIT2(pmp, park_lookupdotdot, dvp->v_data, NULL, - error); - DPRINTF(("puffs_lookupdotdot: return of the userspace, part %d\n", - error)); - if (error) { - error = checkerr(pmp, error, __func__); - goto out; - } - - /* - * Check that we don't get our node back, that would cause - * a pretty obvious deadlock. - */ - dpn = VPTOPP(dvp); - if (lookupdotdot_msg->pvnr_newnode == dpn->pn_cookie) { - puffs_senderr(pmp, PUFFS_ERR_LOOKUP, EINVAL, - "lookupdotdot produced the same cookie", - lookupdotdot_msg->pvnr_newnode); - error = EPROTO; - goto out; - } - - error = puffs_cookie2vnode(pmp, lookupdotdot_msg->pvnr_newnode, - 1, &vp); - if (error == PUFFS_NOSUCHCOOKIE) { - error = puffs_getvnode(dvp->v_mount, - lookupdotdot_msg->pvnr_newnode, VDIR, 0, &vp); - if (error) { - puffs_abortbutton(pmp, PUFFS_ABORT_LOOKUP, VPTOPNC(dvp), - lookupdotdot_msg->pvnr_newnode, NULL, cred); - goto out; - } - } else if (error) { - puffs_abortbutton(pmp, PUFFS_ABORT_LOOKUP, VPTOPNC(dvp), - lookupdotdot_msg->pvnr_newnode, NULL, cred); - goto out; - } - - *ap->a_vpp = vp; - vn_unlock(vp); - - out: - DPRINTF(("puffs_lookupdotdot: returning %d %p\n", error, *ap->a_vpp)); - PUFFS_MSG_RELEASE(lookupdotdot); - return error; -} - -static int -puffs_vnop_create(struct vop_ncreate_args *ap) -{ - PUFFS_MSG_VARS(vn, create); - struct vnode *dvp = ap->a_dvp; - struct vattr *vap = ap->a_vap; - struct puffs_node *dpn = VPTOPP(dvp); - struct nchandle *nch = ap->a_nch; - struct namecache *ncp = nch->ncp; - struct ucred *cred = ap->a_cred; - struct mount *mp = dvp->v_mount; - struct puffs_mount *pmp = MPTOPUFFSMP(mp); - int error; - - if (!EXISTSOP(pmp, CREATE)) - return EOPNOTSUPP; - - DPRINTF(("puffs_create: dvp %p, name: %s\n", - dvp, ncp->nc_name)); - - if (vap->va_type != VREG && vap->va_type != VSOCK) - return EINVAL; - - if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) { - DPRINTF(("puffs_vnop_create: EAGAIN on ncp %p %s\n", - ncp, ncp->nc_name)); - return EAGAIN; - } - - PUFFS_MSG_ALLOC(vn, create); - puffs_makecn(&create_msg->pvnr_cn, &create_msg->pvnr_cn_cred, - ncp, cred); - create_msg->pvnr_va = *ap->a_vap; - puffs_msg_setinfo(park_create, PUFFSOP_VN, - PUFFS_VN_CREATE, VPTOPNC(dvp)); - PUFFS_MSG_ENQUEUEWAIT2(pmp, park_create, dvp->v_data, NULL, error); - - error = checkerr(pmp, error, __func__); - if (error) - goto out; - - error = puffs_newnode(mp, dvp, ap->a_vpp, - create_msg->pvnr_newnode, vap->va_type); - if (error) - puffs_abortbutton(pmp, PUFFS_ABORT_CREATE, dpn->pn_cookie, - create_msg->pvnr_newnode, ncp, cred); - - out: - DPRINTF(("puffs_create: return %d\n", error)); - vput(dvp); - if (!error) { - cache_setunresolved(nch); - cache_setvp(nch, *ap->a_vpp); - } - PUFFS_MSG_RELEASE(create); - return error; -} - -static int -puffs_vnop_mknod(struct vop_nmknod_args *ap) -{ - PUFFS_MSG_VARS(vn, mknod); - struct vnode *dvp = ap->a_dvp; - struct vattr *vap = ap->a_vap; - struct puffs_node *dpn = VPTOPP(dvp); - struct nchandle *nch = ap->a_nch; - struct namecache *ncp = nch->ncp; - struct ucred *cred = ap->a_cred; - struct mount *mp = dvp->v_mount; - struct puffs_mount *pmp = MPTOPUFFSMP(mp); - int error; - - if (!EXISTSOP(pmp, MKNOD)) - return EOPNOTSUPP; - - DPRINTF(("puffs_mknod: dvp %p, name: %s\n", - dvp, ncp->nc_name)); - - if (vap->va_type != VFIFO) - return EINVAL; - - if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) { - DPRINTF(("puffs_vnop_mknod: EAGAIN on ncp %p %s\n", - ncp, ncp->nc_name)); - return EAGAIN; - } - - PUFFS_MSG_ALLOC(vn, mknod); - puffs_makecn(&mknod_msg->pvnr_cn, &mknod_msg->pvnr_cn_cred, - ncp, cred); - mknod_msg->pvnr_va = *ap->a_vap; - puffs_msg_setinfo(park_mknod, PUFFSOP_VN, - PUFFS_VN_MKNOD, VPTOPNC(dvp)); - - PUFFS_MSG_ENQUEUEWAIT2(pmp, park_mknod, dvp->v_data, NULL, error); - - error = checkerr(pmp, error, __func__); - if (error) - goto out; - - error = puffs_newnode(mp, dvp, ap->a_vpp, - mknod_msg->pvnr_newnode, vap->va_type); - if (error) - puffs_abortbutton(pmp, PUFFS_ABORT_MKNOD, dpn->pn_cookie, - mknod_msg->pvnr_newnode, ncp, cred); - - out: - vput(dvp); - if (!error) { - cache_setunresolved(nch); - cache_setvp(nch, *ap->a_vpp); - } - PUFFS_MSG_RELEASE(mknod); - return error; -} - -static int -puffs_vnop_open(struct vop_open_args *ap) -{ - PUFFS_MSG_VARS(vn, open); - struct vnode *vp = ap->a_vp; - struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); - int mode = ap->a_mode; - int error; - - DPRINTF(("puffs_open: vp %p, mode 0x%x\n", vp, mode)); - - if (vp->v_type == VREG && mode & FWRITE && !EXISTSOP(pmp, WRITE)) - ERROUT(EROFS); - - if (!EXISTSOP(pmp, OPEN)) - ERROUT(0); - - PUFFS_MSG_ALLOC(vn, open); - open_msg->pvnr_mode = mode; - puffs_credcvt(&open_msg->pvnr_cred, ap->a_cred); - puffs_msg_setinfo(park_open, PUFFSOP_VN, - PUFFS_VN_OPEN, VPTOPNC(vp)); - - PUFFS_MSG_ENQUEUEWAIT2(pmp, park_open, vp->v_data, NULL, error); - error = checkerr(pmp, error, __func__); - - out: - DPRINTF(("puffs_open: returning %d\n", error)); - PUFFS_MSG_RELEASE(open); - if (error) - return error; - return vop_stdopen(ap); -} - -static int -puffs_vnop_close(struct vop_close_args *ap) -{ - PUFFS_MSG_VARS(vn, close); - struct vnode *vp = ap->a_vp; - struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); - - vn_lock(vp, LK_UPGRADE | LK_RETRY); - - if (!EXISTSOP(pmp, CLOSE)) - return vop_stdclose(ap); - - PUFFS_MSG_ALLOC(vn, close); - puffs_msg_setfaf(park_close); - close_msg->pvnr_fflag = ap->a_fflag; - puffs_msg_setinfo(park_close, PUFFSOP_VN, - PUFFS_VN_CLOSE, VPTOPNC(vp)); - - puffs_msg_enqueue(pmp, park_close); - PUFFS_MSG_RELEASE(close); - return vop_stdclose(ap); -} - -static int -puffs_vnop_access(struct vop_access_args *ap) -{ - PUFFS_MSG_VARS(vn, access); - struct vnode *vp = ap->a_vp; - struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); - int mode = ap->a_mode; - int error; - - if (mode & VWRITE) { - switch (vp->v_type) { - case VDIR: - case VLNK: - case VREG: - if ((vp->v_mount->mnt_flag & MNT_RDONLY) - || !EXISTSOP(pmp, WRITE)) - return EROFS; - break; - default: - break; - } - } - - if (!EXISTSOP(pmp, ACCESS)) - return 0; - - PUFFS_MSG_ALLOC(vn, access); - access_msg->pvnr_mode = ap->a_mode; - puffs_credcvt(&access_msg->pvnr_cred, ap->a_cred); - puffs_msg_setinfo(park_access, PUFFSOP_VN, - PUFFS_VN_ACCESS, VPTOPNC(vp)); - - PUFFS_MSG_ENQUEUEWAIT2(pmp, park_access, vp->v_data, NULL, error); - error = checkerr(pmp, error, __func__); - PUFFS_MSG_RELEASE(access); - - return error; -} - -static int -puffs_vnop_getattr(struct vop_getattr_args *ap) -{ - PUFFS_MSG_VARS(vn, getattr); - struct vnode *vp = ap->a_vp; - struct mount *mp = vp->v_mount; - struct puffs_mount *pmp = MPTOPUFFSMP(mp); - struct vattr *vap, *rvap; - struct puffs_node *pn = VPTOPP(vp); - int error = 0; - - if (vp->v_type == VBLK || vp->v_type == VCHR) - return ENOTSUP; - - vap = ap->a_vap; - - PUFFS_MSG_ALLOC(vn, getattr); - vattr_null(&getattr_msg->pvnr_va); - puffs_credcvt(&getattr_msg->pvnr_cred, curproc->p_ucred); - puffs_msg_setinfo(park_getattr, PUFFSOP_VN, - PUFFS_VN_GETATTR, VPTOPNC(vp)); - - PUFFS_MSG_ENQUEUEWAIT2(pmp, park_getattr, vp->v_data, NULL, error); - error = checkerr(pmp, error, __func__); - if (error) - goto out; - - rvap = &getattr_msg->pvnr_va; - - (void) memcpy(vap, rvap, sizeof(struct vattr)); - vap->va_fsid = mp->mnt_stat.f_fsid.val[0]; - - if (pn->pn_stat & PNODE_METACACHE_ATIME) - vap->va_atime = pn->pn_mc_atime; - if (pn->pn_stat & PNODE_METACACHE_CTIME) - vap->va_ctime = pn->pn_mc_ctime; - if (pn->pn_stat & PNODE_METACACHE_MTIME) - vap->va_mtime = pn->pn_mc_mtime; - if (pn->pn_stat & PNODE_METACACHE_SIZE) { - vap->va_size = pn->pn_mc_size; - } else { - if (rvap->va_size != VNOVAL - && vp->v_type != VBLK && vp->v_type != VCHR) { - pn->pn_serversize = rvap->va_size; - if (vp->v_type == VREG) - puffs_meta_setsize(vp, rvap->va_size, 0); - } - } - - out: - PUFFS_MSG_RELEASE(getattr); - return error; -} - -#define SETATTR_CHSIZE 0x01 -#define SETATTR_ASYNC 0x02 -static int -dosetattr(struct vnode *vp, struct vattr *vap, struct ucred *cred, int flags) -{ - PUFFS_MSG_VARS(vn, setattr); - struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); - struct puffs_node *pn = VPTOPP(vp); - int error = 0; - - if ((vp->v_mount->mnt_flag & MNT_RDONLY) && - (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL - || vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL - || vap->va_mode != (mode_t)VNOVAL)) - return EROFS; - - if ((vp->v_mount->mnt_flag & MNT_RDONLY) - && vp->v_type == VREG && vap->va_size != VNOVAL) - return EROFS; - - /* - * Flush metacache first. If we are called with some explicit - * parameters, treat them as information overriding metacache - * information. - */ - if (pn->pn_stat & PNODE_METACACHE_MASK) { - if ((pn->pn_stat & PNODE_METACACHE_ATIME) - && vap->va_atime.tv_sec == VNOVAL) - vap->va_atime = pn->pn_mc_atime; - if ((pn->pn_stat & PNODE_METACACHE_CTIME) - && vap->va_ctime.tv_sec == VNOVAL) - vap->va_ctime = pn->pn_mc_ctime; - if ((pn->pn_stat & PNODE_METACACHE_MTIME) - && vap->va_mtime.tv_sec == VNOVAL) - vap->va_mtime = pn->pn_mc_mtime; - if ((pn->pn_stat & PNODE_METACACHE_SIZE) - && vap->va_size == VNOVAL) - vap->va_size = pn->pn_mc_size; - - pn->pn_stat &= ~PNODE_METACACHE_MASK; - } - - PUFFS_MSG_ALLOC(vn, setattr); - (void)memcpy(&setattr_msg->pvnr_va, vap, sizeof(struct vattr)); - puffs_credcvt(&setattr_msg->pvnr_cred, cred); - puffs_msg_setinfo(park_setattr, PUFFSOP_VN, - PUFFS_VN_SETATTR, VPTOPNC(vp)); - if (flags & SETATTR_ASYNC) - puffs_msg_setfaf(park_setattr); - - puffs_msg_enqueue(pmp, park_setattr); - if ((flags & SETATTR_ASYNC) == 0) - error = puffs_msg_wait2(pmp, park_setattr, vp->v_data, NULL); - PUFFS_MSG_RELEASE(setattr); - if ((flags & SETATTR_ASYNC) == 0) { - error = checkerr(pmp, error, __func__); - if (error) - return error; - } else { - error = 0; - } - - if (vap->va_size != VNOVAL) { - pn->pn_serversize = vap->va_size; - if (flags & SETATTR_CHSIZE) - puffs_meta_setsize(vp, vap->va_size, 0); - } - - return 0; -} - -static int -puffs_vnop_setattr(struct vop_setattr_args *ap) -{ - return dosetattr(ap->a_vp, ap->a_vap, ap->a_cred, SETATTR_CHSIZE); -} - -static __inline int -doinact(struct puffs_mount *pmp, int iaflag) -{ - - if (EXISTSOP(pmp, INACTIVE)) - if (pmp->pmp_flags & PUFFS_KFLAG_IAONDEMAND) - if (iaflag || ALLOPS(pmp)) - return 1; - else - return 0; - else - return 1; - else - return 0; -} - -static void -callinactive(struct puffs_mount *pmp, puffs_cookie_t ck, int iaflag) -{ - int error; - PUFFS_MSG_VARS(vn, inactive); - - if (doinact(pmp, iaflag)) { - PUFFS_MSG_ALLOC(vn, inactive); - puffs_msg_setinfo(park_inactive, PUFFSOP_VN, - PUFFS_VN_INACTIVE, ck); - - PUFFS_MSG_ENQUEUEWAIT(pmp, park_inactive, error); - PUFFS_MSG_RELEASE(inactive); - } -} - -/* XXX: callinactive can't setback */ -static int -puffs_vnop_inactive(struct vop_inactive_args *ap) -{ - PUFFS_MSG_VARS(vn, inactive); - struct vnode *vp = ap->a_vp; - struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); - struct puffs_node *pnode = VPTOPP(vp); - - flushvncache(vp, MNT_NOWAIT); - - if (doinact(pmp, pnode->pn_stat & PNODE_DOINACT)) { - /* - * do not wait for reply from userspace, otherwise it may - * deadlock. - */ - - PUFFS_MSG_ALLOC(vn, inactive); - puffs_msg_setfaf(park_inactive); - puffs_msg_setinfo(park_inactive, PUFFSOP_VN, - PUFFS_VN_INACTIVE, VPTOPNC(vp)); - - puffs_msg_enqueue(pmp, park_inactive); - PUFFS_MSG_RELEASE(inactive); - } - pnode->pn_stat &= ~PNODE_DOINACT; - - /* - * file server thinks it's gone? then don't be afraid care, - * node's life was already all it would ever be - */ - if (pnode->pn_stat & PNODE_NOREFS) { - pnode->pn_stat |= PNODE_DYING; - vrecycle(vp); - } - - return 0; -} - -static void -callreclaim(struct puffs_mount *pmp, puffs_cookie_t ck) -{ - PUFFS_MSG_VARS(vn, reclaim); - - if (!EXISTSOP(pmp, RECLAIM)) - return; - - PUFFS_MSG_ALLOC(vn, reclaim); - puffs_msg_setfaf(park_reclaim); - puffs_msg_setinfo(park_reclaim, PUFFSOP_VN, PUFFS_VN_RECLAIM, ck); - - puffs_msg_enqueue(pmp, park_reclaim); - PUFFS_MSG_RELEASE(reclaim); -} - -/* - * always FAF, we don't really care if the server wants to fail to - * reclaim the node or not - */ -static int -puffs_vnop_reclaim(struct vop_reclaim_args *ap) -{ - struct vnode *vp = ap->a_vp; - struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); - struct puffs_node *pnode = VPTOPP(vp); - boolean_t notifyserver = TRUE; - - vinvalbuf(vp, V_SAVE, 0, 0); - - /* - * first things first: check if someone is trying to reclaim the - * root vnode. do not allow that to travel to userspace. - * Note that we don't need to take the lock similarly to - * puffs_root(), since there is only one of us. - */ - if (vp->v_flag & VROOT) { - lockmgr(&pmp->pmp_lock, LK_EXCLUSIVE); - KKASSERT(pmp->pmp_root != NULL); - pmp->pmp_root = NULL; - lockmgr(&pmp->pmp_lock, LK_RELEASE); - notifyserver = FALSE; - } - - /* - * purge info from kernel before issueing FAF, since we - * don't really know when we'll get around to it after - * that and someone might race us into node creation - */ - lockmgr(&pmp->pmp_lock, LK_EXCLUSIVE); - LIST_REMOVE(pnode, pn_hashent); - lockmgr(&pmp->pmp_lock, LK_RELEASE); - - if (notifyserver) - callreclaim(MPTOPUFFSMP(vp->v_mount), VPTOPNC(vp)); - - puffs_putvnode(vp); - vp->v_data = NULL; - - return 0; -} - -#define CSIZE sizeof(**ap->a_cookies) -static int -puffs_vnop_readdir(struct vop_readdir_args *ap) -{ - PUFFS_MSG_VARS(vn, readdir); - struct vnode *vp = ap->a_vp; - struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); - size_t argsize, tomove, cookiemem, cookiesmax; - struct uio *uio = ap->a_uio; - size_t howmuch, resid; - int error; - - if (!EXISTSOP(pmp, READDIR)) - return EOPNOTSUPP; - - /* - * ok, so we need: resid + cookiemem = maxreq - * => resid + cookiesize * (resid/minsize) = maxreq - * => resid + cookiesize/minsize * resid = maxreq - * => (cookiesize/minsize + 1) * resid = maxreq - * => resid = maxreq / (cookiesize/minsize + 1) - * - * Since cookiesize <= minsize and we're not very big on floats, - * we approximate that to be 1. Therefore: - * - * resid = maxreq / 2; - * - * Well, at least we didn't have to use differential equations - * or the Gram-Schmidt process. - * - * (yes, I'm very afraid of this) - */ - KKASSERT(CSIZE <= _DIRENT_RECLEN(1)); - - if (ap->a_cookies) { - KKASSERT(ap->a_ncookies != NULL); - if (pmp->pmp_args.pa_fhsize == 0) - return EOPNOTSUPP; - resid = PUFFS_TOMOVE(uio->uio_resid, pmp) / 2; - cookiesmax = resid/_DIRENT_RECLEN(1); - cookiemem = ALIGN(cookiesmax*CSIZE); /* play safe */ - } else { - resid = PUFFS_TOMOVE(uio->uio_resid, pmp); - cookiesmax = 0; - cookiemem = 0; - } - - argsize = sizeof(struct puffs_vnmsg_readdir); - tomove = resid + cookiemem; - puffs_msgmem_alloc(argsize + tomove, &park_readdir, - (void *)&readdir_msg, 1); - - puffs_credcvt(&readdir_msg->pvnr_cred, ap->a_cred); - readdir_msg->pvnr_offset = uio->uio_offset; - readdir_msg->pvnr_resid = resid; - readdir_msg->pvnr_ncookies = cookiesmax; - readdir_msg->pvnr_eofflag = 0; - readdir_msg->pvnr_dentoff = cookiemem; - puffs_msg_setinfo(park_readdir, PUFFSOP_VN, - PUFFS_VN_READDIR, VPTOPNC(vp)); - puffs_msg_setdelta(park_readdir, tomove); - - PUFFS_MSG_ENQUEUEWAIT2(pmp, park_readdir, vp->v_data, NULL, error); - error = checkerr(pmp, error, __func__); - if (error) - goto out; - - /* userspace is cheating? */ - if (readdir_msg->pvnr_resid > resid) { - puffs_senderr(pmp, PUFFS_ERR_READDIR, E2BIG, - "resid grew", VPTOPNC(vp)); - ERROUT(EPROTO); - } - if (readdir_msg->pvnr_ncookies > cookiesmax) { - puffs_senderr(pmp, PUFFS_ERR_READDIR, E2BIG, - "too many cookies", VPTOPNC(vp)); - ERROUT(EPROTO); - } - - /* check eof */ - if (readdir_msg->pvnr_eofflag) - *ap->a_eofflag = 1; - - /* bouncy-wouncy with the directory data */ - howmuch = resid - readdir_msg->pvnr_resid; - - /* force eof if no data was returned (getcwd() needs this) */ - if (howmuch == 0) { - *ap->a_eofflag = 1; - goto out; - } - - error = uiomove(readdir_msg->pvnr_data + cookiemem, howmuch, uio); - if (error) - goto out; - - /* provide cookies to caller if so desired */ - if (ap->a_cookies) { - *ap->a_cookies = kmalloc(readdir_msg->pvnr_ncookies*CSIZE, - M_TEMP, M_WAITOK); - *ap->a_ncookies = readdir_msg->pvnr_ncookies; - memcpy(*ap->a_cookies, readdir_msg->pvnr_data, - *ap->a_ncookies*CSIZE); - } - - /* next readdir starts here */ - uio->uio_offset = readdir_msg->pvnr_offset; - - out: - puffs_msgmem_release(park_readdir); - return error; -} -#undef CSIZE - -static int -flushvncache(struct vnode *vp, int waitfor) -{ - struct puffs_node *pn = VPTOPP(vp); - struct vattr va; - int error = 0; - - /* flush out information from our metacache, see vop_setattr */ - if (pn->pn_stat & PNODE_METACACHE_MASK - && (pn->pn_stat & PNODE_DYING) == 0) { - vattr_null(&va); - error = dosetattr(vp, &va, FSCRED, SETATTR_CHSIZE | - (waitfor == MNT_NOWAIT ? 0 : SETATTR_ASYNC)); - if (error) - return error; - } - - /* - * flush pages to avoid being overly dirty - */ - vfsync(vp, waitfor, 0, NULL, NULL); - - return error; -} - -static int -puffs_vnop_fsync(struct vop_fsync_args *ap) -{ - PUFFS_MSG_VARS(vn, fsync); - struct vnode *vp = ap->a_vp; - int waitfor = ap->a_waitfor; - struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); - struct puffs_node *pn = VPTOPP(vp); - int error, dofaf; - - error = flushvncache(vp, waitfor); - if (error) - return error; - - /* - * HELLO! We exit already here if the user server does not - * support fsync OR if we should call fsync for a node which - * has references neither in the kernel or the fs server. - * Otherwise we continue to issue fsync() forward. - */ - if (!EXISTSOP(pmp, FSYNC) || (pn->pn_stat & PNODE_DYING)) - return 0; - - dofaf = (waitfor & MNT_WAIT) == 0 || (waitfor & MNT_LAZY) != 0; - - PUFFS_MSG_ALLOC(vn, fsync); - if (dofaf) - puffs_msg_setfaf(park_fsync); - - fsync_msg->pvnr_flags = ap->a_flags; - puffs_msg_setinfo(park_fsync, PUFFSOP_VN, - PUFFS_VN_FSYNC, VPTOPNC(vp)); - - PUFFS_MSG_ENQUEUEWAIT2(pmp, park_fsync, vp->v_data, NULL, error); - PUFFS_MSG_RELEASE(fsync); - - error = checkerr(pmp, error, __func__); - - return error; -} - -static int -callremove(struct puffs_mount *pmp, puffs_cookie_t dck, puffs_cookie_t ck, - struct namecache *ncp, struct ucred *cred) -{ - PUFFS_MSG_VARS(vn, remove); - int error; - - PUFFS_MSG_ALLOC(vn, remove); - remove_msg->pvnr_cookie_targ = ck; - puffs_makecn(&remove_msg->pvnr_cn, &remove_msg->pvnr_cn_cred, - ncp, cred); - puffs_msg_setinfo(park_remove, PUFFSOP_VN, PUFFS_VN_REMOVE, dck); - - PUFFS_MSG_ENQUEUEWAIT(pmp, park_remove, error); - PUFFS_MSG_RELEASE(remove); - - return checkerr(pmp, error, __func__); -} - -/* - * XXX: can't use callremove now because can't catch setbacks with - * it due to lack of a pnode argument. - */ -static int -puffs_vnop_remove(struct vop_nremove_args *ap) -{ - PUFFS_MSG_VARS(vn, remove); - struct vnode *dvp = ap->a_dvp; - struct vnode *vp; - struct puffs_node *dpn = VPTOPP(dvp); - struct puffs_node *pn; - struct nchandle *nch = ap->a_nch; - struct namecache *ncp = nch->ncp; - struct ucred *cred = ap->a_cred; - struct mount *mp = dvp->v_mount; - struct puffs_mount *pmp = MPTOPUFFSMP(mp); - int error; - - if (!EXISTSOP(pmp, REMOVE)) - return EOPNOTSUPP; - - error = vget(dvp, LK_EXCLUSIVE); - if (error != 0) { - DPRINTF(("puffs_vnop_remove: EAGAIN on parent vnode %p %s\n", - dvp, ncp->nc_name)); - return EAGAIN; - } - - error = cache_vget(nch, cred, LK_EXCLUSIVE, &vp); - if (error != 0) { - DPRINTF(("puffs_vnop_remove: cache_vget error: %p %s\n", - dvp, ncp->nc_name)); - return EAGAIN; - } - if (vp->v_type == VDIR) { - error = EISDIR; - goto out; - } - - pn = VPTOPP(vp); - PUFFS_MSG_ALLOC(vn, remove); - remove_msg->pvnr_cookie_targ = VPTOPNC(vp); - puffs_makecn(&remove_msg->pvnr_cn, &remove_msg->pvnr_cn_cred, - ncp, cred); - puffs_msg_setinfo(park_remove, PUFFSOP_VN, - PUFFS_VN_REMOVE, VPTOPNC(dvp)); - - puffs_msg_enqueue(pmp, park_remove); - error = puffs_msg_wait2(pmp, park_remove, dpn, pn); - - PUFFS_MSG_RELEASE(remove); - - error = checkerr(pmp, error, __func__); - - out: - vput(dvp); - vn_unlock(vp); - if (error == 0) - cache_unlink(nch); - vrele(vp); - return error; -} - -static int -puffs_vnop_mkdir(struct vop_nmkdir_args *ap) -{ - PUFFS_MSG_VARS(vn, mkdir); - struct vnode *dvp = ap->a_dvp; - struct puffs_node *dpn = VPTOPP(dvp); - struct nchandle *nch = ap->a_nch; - struct namecache *ncp = nch->ncp; - struct ucred *cred = ap->a_cred; - struct mount *mp = dvp->v_mount; - struct puffs_mount *pmp = MPTOPUFFSMP(mp); - int error; - - if (!EXISTSOP(pmp, MKDIR)) - return EOPNOTSUPP; - - if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) { - DPRINTF(("puffs_vnop_mkdir: EAGAIN on ncp %p %s\n", - ncp, ncp->nc_name)); - return EAGAIN; - } - - PUFFS_MSG_ALLOC(vn, mkdir); - puffs_makecn(&mkdir_msg->pvnr_cn, &mkdir_msg->pvnr_cn_cred, - ncp, cred); - mkdir_msg->pvnr_va = *ap->a_vap; - puffs_msg_setinfo(park_mkdir, PUFFSOP_VN, - PUFFS_VN_MKDIR, VPTOPNC(dvp)); - - PUFFS_MSG_ENQUEUEWAIT2(pmp, park_mkdir, dvp->v_data, NULL, error); - - error = checkerr(pmp, error, __func__); - if (error) - goto out; - - error = puffs_newnode(mp, dvp, ap->a_vpp, - mkdir_msg->pvnr_newnode, VDIR); - if (error) - puffs_abortbutton(pmp, PUFFS_ABORT_MKDIR, dpn->pn_cookie, - mkdir_msg->pvnr_newnode, ncp, cred); - - out: - vput(dvp); - if (!error) { - cache_setunresolved(nch); - cache_setvp(nch, *ap->a_vpp); - } - PUFFS_MSG_RELEASE(mkdir); - return error; -} - -static int -callrmdir(struct puffs_mount *pmp, puffs_cookie_t dck, puffs_cookie_t ck, - struct namecache *ncp, struct ucred *cred) -{ - PUFFS_MSG_VARS(vn, rmdir); - int error; - - PUFFS_MSG_ALLOC(vn, rmdir); - rmdir_msg->pvnr_cookie_targ = ck; - puffs_makecn(&rmdir_msg->pvnr_cn, &rmdir_msg->pvnr_cn_cred, - ncp, cred); - puffs_msg_setinfo(park_rmdir, PUFFSOP_VN, PUFFS_VN_RMDIR, dck); - - PUFFS_MSG_ENQUEUEWAIT(pmp, park_rmdir, error); - PUFFS_MSG_RELEASE(rmdir); - - return checkerr(pmp, error, __func__); -} - -static int -puffs_vnop_rmdir(struct vop_nrmdir_args *ap) -{ - PUFFS_MSG_VARS(vn, rmdir); - struct vnode *dvp = ap->a_dvp; - struct vnode *vp; - struct puffs_node *dpn = VPTOPP(dvp); - struct puffs_node *pn; - struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount); - struct nchandle *nch = ap->a_nch; - struct namecache *ncp = nch->ncp; - struct ucred *cred = ap->a_cred; - int error; - - if (!EXISTSOP(pmp, RMDIR)) - return EOPNOTSUPP; - - error = vget(dvp, LK_EXCLUSIVE); - if (error != 0) { - DPRINTF(("puffs_vnop_rmdir: EAGAIN on parent vnode %p %s\n", - dvp, ncp->nc_name)); - return EAGAIN; - } - error = cache_vget(nch, cred, LK_EXCLUSIVE, &vp); - if (error != 0) { - DPRINTF(("puffs_vnop_rmdir: cache_vget error: %p %s\n", - dvp, ncp->nc_name)); - return EAGAIN; - } - if (vp->v_type != VDIR) { - error = ENOTDIR; - goto out; - } - - pn = VPTOPP(vp); - PUFFS_MSG_ALLOC(vn, rmdir); - rmdir_msg->pvnr_cookie_targ = VPTOPNC(vp); - puffs_makecn(&rmdir_msg->pvnr_cn, &rmdir_msg->pvnr_cn_cred, - ncp, cred); - puffs_msg_setinfo(park_rmdir, PUFFSOP_VN, - PUFFS_VN_RMDIR, VPTOPNC(dvp)); - - puffs_msg_enqueue(pmp, park_rmdir); - error = puffs_msg_wait2(pmp, park_rmdir, dpn, pn); - - PUFFS_MSG_RELEASE(rmdir); - - error = checkerr(pmp, error, __func__); - - out: - vput(dvp); - vn_unlock(vp); - if (error == 0) - cache_unlink(nch); - vrele(vp); - return error; -} - -static int -puffs_vnop_link(struct vop_nlink_args *ap) -{ - PUFFS_MSG_VARS(vn, link); - struct vnode *dvp = ap->a_dvp; - struct vnode *vp = ap->a_vp; - struct puffs_node *dpn = VPTOPP(dvp); - struct puffs_node *pn = VPTOPP(vp); - struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount); - struct nchandle *nch = ap->a_nch; - struct namecache *ncp = nch->ncp; - struct ucred *cred = ap->a_cred; - int error; - - if (!EXISTSOP(pmp, LINK)) - return EOPNOTSUPP; - - if (vp->v_mount != dvp->v_mount) - return EXDEV; - - if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) { - DPRINTF(("puffs_vnop_link: EAGAIN on ncp %p %s\n", - ncp, ncp->nc_name)); - return EAGAIN; - } - - PUFFS_MSG_ALLOC(vn, link); - link_msg->pvnr_cookie_targ = VPTOPNC(vp); - puffs_makecn(&link_msg->pvnr_cn, &link_msg->pvnr_cn_cred, - ncp, cred); - puffs_msg_setinfo(park_link, PUFFSOP_VN, - PUFFS_VN_LINK, VPTOPNC(dvp)); - - puffs_msg_enqueue(pmp, park_link); - error = puffs_msg_wait2(pmp, park_link, dpn, pn); - - PUFFS_MSG_RELEASE(link); - - error = checkerr(pmp, error, __func__); - - /* - * XXX: stay in touch with the cache. I don't like this, but - * don't have a better solution either. See also puffs_rename(). - */ - if (error == 0) { - puffs_updatenode(pn, PUFFS_UPDATECTIME); - } - - vput(dvp); - if (error == 0) { - cache_setunresolved(nch); - cache_setvp(nch, vp); - } - return error; -} - -static int -puffs_vnop_symlink(struct vop_nsymlink_args *ap) -{ - PUFFS_MSG_VARS(vn, symlink); - struct vnode *dvp = ap->a_dvp; - struct puffs_node *dpn = VPTOPP(dvp); - struct mount *mp = dvp->v_mount; - struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount); - struct nchandle *nch = ap->a_nch; - struct namecache *ncp = nch->ncp; - struct ucred *cred = ap->a_cred; - int error; - - if (!EXISTSOP(pmp, SYMLINK)) - return EOPNOTSUPP; - - if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) { - DPRINTF(("puffs_vnop_symlink: EAGAIN on ncp %p %s\n", - ncp, ncp->nc_name)); - return EAGAIN; - } - - *ap->a_vpp = NULL; - - PUFFS_MSG_ALLOC(vn, symlink); - puffs_makecn(&symlink_msg->pvnr_cn, &symlink_msg->pvnr_cn_cred, - ncp, cred); - symlink_msg->pvnr_va = *ap->a_vap; - (void)strlcpy(symlink_msg->pvnr_link, ap->a_target, - sizeof(symlink_msg->pvnr_link)); - puffs_msg_setinfo(park_symlink, PUFFSOP_VN, - PUFFS_VN_SYMLINK, VPTOPNC(dvp)); - - PUFFS_MSG_ENQUEUEWAIT2(pmp, park_symlink, dvp->v_data, NULL, error); - - error = checkerr(pmp, error, __func__); - if (error) - goto out; - - error = puffs_newnode(mp, dvp, ap->a_vpp, - symlink_msg->pvnr_newnode, VLNK); - if (error) - puffs_abortbutton(pmp, PUFFS_ABORT_SYMLINK, dpn->pn_cookie, - symlink_msg->pvnr_newnode, ncp, cred); - - out: - vput(dvp); - PUFFS_MSG_RELEASE(symlink); - if (!error) { - cache_setunresolved(nch); - cache_setvp(nch, *ap->a_vpp); - } - return error; -} - -static int -puffs_vnop_readlink(struct vop_readlink_args *ap) -{ - PUFFS_MSG_VARS(vn, readlink); - struct vnode *vp = ap->a_vp; - struct puffs_mount *pmp = MPTOPUFFSMP(ap->a_vp->v_mount); - size_t linklen; - int error; - - if (!EXISTSOP(pmp, READLINK)) - return EOPNOTSUPP; - - PUFFS_MSG_ALLOC(vn, readlink); - puffs_credcvt(&readlink_msg->pvnr_cred, ap->a_cred); - linklen = sizeof(readlink_msg->pvnr_link); - readlink_msg->pvnr_linklen = linklen; - puffs_msg_setinfo(park_readlink, PUFFSOP_VN, - PUFFS_VN_READLINK, VPTOPNC(vp)); - - PUFFS_MSG_ENQUEUEWAIT2(pmp, park_readlink, vp->v_data, NULL, error); - error = checkerr(pmp, error, __func__); - if (error) - goto out; - - /* bad bad user file server */ - if (readlink_msg->pvnr_linklen > linklen) { - puffs_senderr(pmp, PUFFS_ERR_READLINK, E2BIG, - "linklen too big", VPTOPNC(ap->a_vp)); - error = EPROTO; - goto out; - } - - error = uiomove(readlink_msg->pvnr_link, readlink_msg->pvnr_linklen, - ap->a_uio); - out: - PUFFS_MSG_RELEASE(readlink); - return error; -} - -static int -puffs_vnop_rename(struct vop_nrename_args *ap) -{ - PUFFS_MSG_VARS(vn, rename); - struct nchandle *fnch = ap->a_fnch; - struct nchandle *tnch = ap->a_tnch; - struct vnode *fdvp = ap->a_fdvp; - struct vnode *fvp = fnch->ncp->nc_vp; - struct vnode *tdvp = ap->a_tdvp; - struct vnode *tvp = tnch->ncp->nc_vp; - struct ucred *cred = ap->a_cred; - struct puffs_mount *pmp = MPTOPUFFSMP(fdvp->v_mount); - int error; - - if (!EXISTSOP(pmp, RENAME)) - return EOPNOTSUPP; - - error = vget(tdvp, LK_EXCLUSIVE); - if (error != 0) { - DPRINTF(("puffs_vnop_rename: EAGAIN on tdvp vnode %p %s\n", - tdvp, tnch->ncp->nc_name)); - return EAGAIN; - } - if (tvp != NULL) { - error = vget(tvp, LK_EXCLUSIVE); - if (error != 0) { - DPRINTF(("puffs_vnop_rename: EAGAIN on tvp vnode %p %s\n", - tvp, tnch->ncp->nc_name)); - vput(tdvp); - return EAGAIN; - } - } - - if ((fvp->v_mount != tdvp->v_mount) || - (tvp && (fvp->v_mount != tvp->v_mount))) { - error = EXDEV; - goto out; - } - - if (tvp) { - if (fvp->v_type == VDIR && tvp->v_type != VDIR) { - error = ENOTDIR; - goto out; - } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { - error = EISDIR; - goto out; - } - } - - PUFFS_MSG_ALLOC(vn, rename); - rename_msg->pvnr_cookie_src = VPTOPNC(fvp); - rename_msg->pvnr_cookie_targdir = VPTOPNC(tdvp); - if (tvp) - rename_msg->pvnr_cookie_targ = VPTOPNC(tvp); - else - rename_msg->pvnr_cookie_targ = NULL; - puffs_makecn(&rename_msg->pvnr_cn_src, &rename_msg->pvnr_cn_src_cred, - fnch->ncp, cred); - puffs_makecn(&rename_msg->pvnr_cn_targ, &rename_msg->pvnr_cn_targ_cred, - tnch->ncp, cred); - puffs_msg_setinfo(park_rename, PUFFSOP_VN, - PUFFS_VN_RENAME, VPTOPNC(fdvp)); - - PUFFS_MSG_ENQUEUEWAIT2(pmp, park_rename, fdvp->v_data, NULL, error); - PUFFS_MSG_RELEASE(rename); - error = checkerr(pmp, error, __func__); - - if (error == 0) - puffs_updatenode(VPTOPP(fvp), PUFFS_UPDATECTIME); - - out: - if (tvp != NULL) - vn_unlock(tvp); - if (tdvp != tvp) - vn_unlock(tdvp); - if (error == 0) - cache_rename(fnch, tnch); - if (tvp != NULL) - vrele(tvp); - vrele(tdvp); - - return error; -} - -static int -puffs_vnop_read(struct vop_read_args *ap) -{ - struct vnode *vp = ap->a_vp; - struct uio *uio = ap->a_uio; - int ioflag = ap->a_ioflag; - struct ucred * cred = ap->a_cred; - struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); - int error; - - if (!EXISTSOP(pmp, READ)) - return EOPNOTSUPP; - - if (vp->v_type == VDIR) - return EISDIR; - else if (vp->v_type != VREG) - return EINVAL; - - if (PUFFS_USE_PAGECACHE(pmp)) - error = puffs_bioread(vp, uio, ioflag, cred); - else - error = puffs_directread(vp, uio, ioflag, cred); - - return error; -} - -static int -puffs_vnop_write(struct vop_write_args *ap) -{ - struct vnode *vp = ap->a_vp; - struct uio *uio = ap->a_uio; - int ioflag = ap->a_ioflag; - struct ucred * cred = ap->a_cred; - struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); - int error; - - if (!EXISTSOP(pmp, WRITE)) - return EOPNOTSUPP; - - if (vp->v_type == VDIR) - return EISDIR; - else if (vp->v_type != VREG) - return EINVAL; - - if (PUFFS_USE_PAGECACHE(pmp)) - error = puffs_biowrite(vp, uio, ioflag, cred); - else - error = puffs_directwrite(vp, uio, ioflag, cred); - - return error; -} - -static int -puffs_vnop_print(struct vop_print_args *ap) -{ - PUFFS_MSG_VARS(vn, print); - struct vnode *vp = ap->a_vp; - struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); - struct puffs_node *pn = VPTOPP(vp); - int error; - - /* kernel portion */ - kprintf("tag VT_PUFFS, vnode %p, puffs node: %p,\n" - "\tuserspace cookie: %p", vp, pn, pn->pn_cookie); - if (vp->v_type == VFIFO) - fifo_printinfo(vp); - kprintf("\n"); - - /* userspace portion */ - if (EXISTSOP(pmp, PRINT)) { - PUFFS_MSG_ALLOC(vn, print); - puffs_msg_setinfo(park_print, PUFFSOP_VN, - PUFFS_VN_PRINT, VPTOPNC(vp)); - PUFFS_MSG_ENQUEUEWAIT2(pmp, park_print, vp->v_data, - NULL, error); - PUFFS_MSG_RELEASE(print); - } - - return 0; -} - -static int -puffs_vnop_pathconf(struct vop_pathconf_args *ap) -{ - PUFFS_MSG_VARS(vn, pathconf); - struct vnode *vp = ap->a_vp; - struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); - int error; - - if (!EXISTSOP(pmp, PATHCONF)) - return EOPNOTSUPP; - - PUFFS_MSG_ALLOC(vn, pathconf); - pathconf_msg->pvnr_name = ap->a_name; - puffs_msg_setinfo(park_pathconf, PUFFSOP_VN, - PUFFS_VN_PATHCONF, VPTOPNC(vp)); - PUFFS_MSG_ENQUEUEWAIT2(pmp, park_pathconf, vp->v_data, NULL, error); - error = checkerr(pmp, error, __func__); - if (!error) - *ap->a_retval = pathconf_msg->pvnr_retval; - PUFFS_MSG_RELEASE(pathconf); - - return error; -} - -static int -puffs_vnop_advlock(struct vop_advlock_args *ap) -{ - PUFFS_MSG_VARS(vn, advlock); - struct vnode *vp = ap->a_vp; - struct puffs_node *pn = VPTOPP(vp); - struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); - int error; - - if (!EXISTSOP(pmp, ADVLOCK)) - return lf_advlock(ap, &pn->pn_lockf, vp->v_filesize); - - PUFFS_MSG_ALLOC(vn, advlock); - (void)memcpy(&advlock_msg->pvnr_fl, ap->a_fl, - sizeof(advlock_msg->pvnr_fl)); - advlock_msg->pvnr_id = ap->a_id; - advlock_msg->pvnr_op = ap->a_op; - advlock_msg->pvnr_flags = ap->a_flags; - puffs_msg_setinfo(park_advlock, PUFFSOP_VN, - PUFFS_VN_ADVLOCK, VPTOPNC(vp)); - PUFFS_MSG_ENQUEUEWAIT2(pmp, park_advlock, vp->v_data, NULL, error); - error = checkerr(pmp, error, __func__); - PUFFS_MSG_RELEASE(advlock); - - return error; -} - -static int -puffs_vnop_bmap(struct vop_bmap_args *ap) -{ - if (ap->a_doffsetp != NULL) - *ap->a_doffsetp = ap->a_loffset; - if (ap->a_runp != NULL) - *ap->a_runp = 0; - if (ap->a_runb != NULL) - *ap->a_runb = 0; - return (0); -} - -static int -puffs_vnop_mmap(struct vop_mmap_args *ap) -{ - return EINVAL; -} - - -static int -puffs_vnop_strategy(struct vop_strategy_args *ap) -{ - return puffs_doio(ap->a_vp, ap->a_bio, curthread); -} - -struct vop_ops puffs_fifo_vops = { - .vop_default = fifo_vnoperate, - .vop_access = puffs_vnop_access, - .vop_getattr = puffs_vnop_getattr, - .vop_setattr = puffs_vnop_setattr, - .vop_inactive = puffs_vnop_inactive, - .vop_reclaim = puffs_vnop_reclaim, - .vop_print = puffs_vnop_print, -}; - -struct vop_ops puffs_vnode_vops = { - .vop_default = vop_defaultop, - .vop_nresolve = puffs_vnop_lookup, - .vop_nlookupdotdot = puffs_vnop_lookupdotdot, - .vop_ncreate = puffs_vnop_create, - .vop_nmkdir = puffs_vnop_mkdir, - .vop_nrmdir = puffs_vnop_rmdir, - .vop_nremove = puffs_vnop_remove, - .vop_nrename = puffs_vnop_rename, - .vop_nlink = puffs_vnop_link, - .vop_nsymlink = puffs_vnop_symlink, - .vop_nmknod = puffs_vnop_mknod, - .vop_access = puffs_vnop_access, - .vop_getattr = puffs_vnop_getattr, - .vop_setattr = puffs_vnop_setattr, - .vop_readdir = puffs_vnop_readdir, - .vop_open = puffs_vnop_open, - .vop_close = puffs_vnop_close, - .vop_read = puffs_vnop_read, - .vop_write = puffs_vnop_write, - .vop_readlink = puffs_vnop_readlink, - .vop_advlock = puffs_vnop_advlock, - .vop_bmap = puffs_vnop_bmap, - .vop_mmap = puffs_vnop_mmap, - .vop_strategy = puffs_vnop_strategy, - .vop_getpages = vop_stdgetpages, - .vop_putpages = vop_stdputpages, - .vop_fsync = puffs_vnop_fsync, - .vop_inactive = puffs_vnop_inactive, - .vop_reclaim = puffs_vnop_reclaim, - .vop_pathconf = puffs_vnop_pathconf, - .vop_print = puffs_vnop_print, -}; diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index 4d88a545b0..d3fbd8efe2 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -84,7 +84,6 @@ SUBDIR= 802_11 \ prefix \ procctl \ pstat \ - puffs \ pw \ pwd_mkdb \ quot \ diff --git a/usr.sbin/puffs/Makefile b/usr.sbin/puffs/Makefile deleted file mode 100644 index 0d538dc739..0000000000 --- a/usr.sbin/puffs/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -SUBDIR= mount_psshfs - -.include diff --git a/usr.sbin/puffs/Makefile.inc b/usr.sbin/puffs/Makefile.inc deleted file mode 100644 index 1f5b79aa2c..0000000000 --- a/usr.sbin/puffs/Makefile.inc +++ /dev/null @@ -1,3 +0,0 @@ -WARNS?= 2 - -.include "../Makefile.inc" diff --git a/usr.sbin/puffs/mount_psshfs/Makefile b/usr.sbin/puffs/mount_psshfs/Makefile deleted file mode 100644 index ea03912a9b..0000000000 --- a/usr.sbin/puffs/mount_psshfs/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -PROG= mount_psshfs -SRCS= psshfs.c fs.c node.c psbuf.c subr.c -MAN= mount_psshfs.8 - -LDADD+= -lpuffs -lutil -DPADD+= ${LIBPUFFS} ${LIBUTIL} - -.include diff --git a/usr.sbin/puffs/mount_psshfs/fs.c b/usr.sbin/puffs/mount_psshfs/fs.c deleted file mode 100644 index 90979b701f..0000000000 --- a/usr.sbin/puffs/mount_psshfs/fs.c +++ /dev/null @@ -1,276 +0,0 @@ -/* $NetBSD: fs.c,v 1.24 2011/06/22 04:03:23 mrg Exp $ */ - -/* - * Copyright (c) 2006-2009 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 -#include -#include -#include -#include -#include -#include - -#include "psshfs.h" -#include "sftp_proto.h" - -#define DO_IO(fname, a1, a2, a3, a4, rv) \ -do { \ - puffs_framebuf_seekset(a2, 0); \ - *(a4) = 0; \ - rv = fname(a1, a2, a3, a4); \ - if (rv) { \ - return rv ? rv : EPROTO; \ - } \ -} while (/*CONSTCOND*/0) - -#define reterr(str, rv) \ -do { \ - fprintf str; \ - return rv; \ -} while (/*CONSTCOND*/0) - -/* openssh extensions */ -static const struct extunit { - const char *ext; - const char *val; - int extflag; -} exttable[] = { -{ - "posix-rename@openssh.com", - "1", - SFTP_EXT_POSIX_RENAME, -},{ - "statvfs@openssh.com", - "2", - SFTP_EXT_STATVFS, -},{ - "fstatvfs@openssh.com", - "2", - SFTP_EXT_FSTATVFS, -},{ - NULL, - NULL, - 0 -}}; - -int -psshfs_handshake(struct puffs_usermount *pu, int fd) -{ - struct psshfs_ctx *pctx = puffs_getspecific(pu); - struct puffs_framebuf *pb; - struct puffs_pathobj *po_root; - struct puffs_node *pn_root; - struct vattr va, *rva; - const struct extunit *extu; - char *rootpath; - char *ext, *val; - uint32_t count; - int rv, done; - - pb = psbuf_makeout(); - psbuf_put_1(pb, SSH_FXP_INIT); - psbuf_put_4(pb, SFTP_PROTOVERSION); - DO_IO(psbuf_write, pu, pb, fd, &done, rv); - - puffs_framebuf_recycle(pb); - DO_IO(psbuf_read, pu, pb, fd, &done, rv); - if (psbuf_get_type(pb) != SSH_FXP_VERSION) - reterr((stderr, "invalid server response: %d", - psbuf_get_type(pb)), EPROTO); - pctx->protover = psbuf_get_reqid(pb); - - /* - * Check out which extensions are available. Currently - * we are only interested in the openssh statvfs extension. - */ - for (;;) { - if (psbuf_get_str(pb, &ext, NULL) != 0) - break; - if (psbuf_get_str(pb, &val, NULL) != 0) - break; - - for (extu = exttable; extu->ext; extu++) - if (strcmp(ext, extu->ext) == 0 - && strcmp(val, extu->val) == 0) - pctx->extensions |= extu->extflag; - } - - /* scope out our rootpath */ - psbuf_recycleout(pb); - psbuf_put_1(pb, SSH_FXP_REALPATH); - psbuf_put_4(pb, NEXTREQ(pctx)); - psbuf_put_str(pb, pctx->mountpath); - DO_IO(psbuf_write, pu, pb, fd, &done, rv); - - puffs_framebuf_recycle(pb); - DO_IO(psbuf_read, pu, pb, fd, &done, rv); - if (psbuf_get_type(pb) != SSH_FXP_NAME) - reterr((stderr, "invalid server realpath response for \"%s\"", - pctx->mountpath), EPROTO); - if (psbuf_get_4(pb, &count) == -1) - reterr((stderr, "invalid realpath response: count"), EPROTO); - if (psbuf_get_str(pb, &rootpath, NULL) == -1) - reterr((stderr, "invalid realpath response: rootpath"), EPROTO); - - /* stat the rootdir so that we know it's a dir */ - psbuf_recycleout(pb); - psbuf_req_str(pb, SSH_FXP_LSTAT, NEXTREQ(pctx), rootpath); - DO_IO(psbuf_write, pu, pb, fd, &done, rv); - - puffs_framebuf_recycle(pb); - DO_IO(psbuf_read, pu, pb, fd, &done, rv); - - rv = psbuf_expect_attrs(pb, &va); - if (rv) - reterr((stderr, "couldn't stat rootpath"), rv); - puffs_framebuf_destroy(pb); - - if (puffs_mode2vt(va.va_mode) != VDIR) - reterr((stderr, "remote path (%s) not a directory", rootpath), - ENOTDIR); - - pn_root = puffs_getroot(pu); - rva = &pn_root->pn_va; - puffs_setvattr(rva, &va); - - po_root = puffs_getrootpathobj(pu); - if (po_root == NULL) - err(1, "getrootpathobj"); - po_root->po_path = rootpath; - po_root->po_len = strlen(rootpath); - - return 0; -} - -int -psshfs_fs_statvfs(struct puffs_usermount *pu, struct statvfs *sbp) -{ - PSSHFSAUTOVAR(pu); - uint64_t tmpval; - uint8_t type; - - memset(sbp, 0, sizeof(*sbp)); - sbp->f_bsize = sbp->f_frsize = 512; - - if ((pctx->extensions & SFTP_EXT_STATVFS) == 0) - goto out; - - psbuf_req_str(pb, SSH_FXP_EXTENDED, reqid, "statvfs@openssh.com"); - psbuf_put_str(pb, pctx->mountpath); - GETRESPONSE(pb, pctx->sshfd); - - type = psbuf_get_type(pb); - if (type != SSH_FXP_EXTENDED_REPLY) { - /* use the default */ - goto out; - } - - psbuf_get_8(pb, &tmpval); - sbp->f_bsize = tmpval; - psbuf_get_8(pb, &tmpval); - sbp->f_frsize = tmpval; - psbuf_get_8(pb, &sbp->f_blocks); - psbuf_get_8(pb, &sbp->f_bfree); - psbuf_get_8(pb, &sbp->f_bavail); - psbuf_get_8(pb, &sbp->f_files); - psbuf_get_8(pb, &sbp->f_ffree); - psbuf_get_8(pb, &sbp->f_favail); - - psbuf_get_8(pb, &tmpval); /* fsid */ - psbuf_get_8(pb, &tmpval); /* flag */ - psbuf_get_8(pb, &tmpval); - sbp->f_namemax = tmpval; - -#ifdef XXXDF - sbp->f_bresvd = sbp->f_bfree - sbp->f_bavail; - sbp->f_fresvd = sbp->f_ffree - sbp->f_favail; -#endif - - out: - PSSHFSRETURN(rv); -} - -int -psshfs_fs_unmount(struct puffs_usermount *pu, int flags) -{ - struct psshfs_ctx *pctx = puffs_getspecific(pu); - - kill(pctx->sshpid, SIGTERM); - close(pctx->sshfd); - if (pctx->numconnections == 2) { - kill(pctx->sshpid_data, SIGTERM); - close(pctx->sshfd_data); - } - - return 0; -} - -int -psshfs_fs_nodetofh(struct puffs_usermount *pu, puffs_cookie_t cookie, - void *fid, size_t *fidsize) -{ - struct psshfs_ctx *pctx = puffs_getspecific(pu); - struct puffs_node *pn = cookie; - struct psshfs_node *psn = pn->pn_data; - struct psshfs_fid *pf = fid; - - pf->mounttime = pctx->mounttime; - pf->node = pn; - - psn->stat |= PSN_HASFH; - - return 0; -} - -int -psshfs_fs_fhtonode(struct puffs_usermount *pu, void *fid, size_t fidsize, - struct puffs_newinfo *pni) -{ - struct psshfs_ctx *pctx = puffs_getspecific(pu); - struct psshfs_fid *pf = fid; - struct puffs_node *pn = pf->node; - struct psshfs_node *psn; - int rv; - - if (pf->mounttime != pctx->mounttime) - return EINVAL; - if (pn == NULL) - return EINVAL; - psn = pn->pn_data; - if ((psn->stat & PSN_HASFH) == 0) - return EINVAL; - - /* update node attributes */ - rv = getnodeattr(pu, pn, NULL); - if (rv) - return EINVAL; - - puffs_newinfo_setcookie(pni, pn); - puffs_newinfo_setvtype(pni, pn->pn_va.va_type); - puffs_newinfo_setsize(pni, pn->pn_va.va_size); - - return 0; -} diff --git a/usr.sbin/puffs/mount_psshfs/mount_psshfs.8 b/usr.sbin/puffs/mount_psshfs/mount_psshfs.8 deleted file mode 100644 index c20ae97eb7..0000000000 --- a/usr.sbin/puffs/mount_psshfs/mount_psshfs.8 +++ /dev/null @@ -1,204 +0,0 @@ -.\" $NetBSD: mount_psshfs.8,v 1.24 2010/02/03 17:16:29 pooka Exp $ -.\" -.\" Copyright (c) 2007-2009 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 February 5, 2012 -.Dt MOUNT_PSSHFS 8 -.Os -.Sh NAME -.Nm mount_psshfs -.Nd sshfs implementation for puffs -.Sh SYNOPSIS -.Nm -.Op Ar options -.Ar user@host[:path] -.Ar mount_point -.Sh DESCRIPTION -The -.Nm -utility can be used to mount a file system using the ssh sftp -subprotocol, making a remote directory hierarchy appear in the -local directory tree. -This functionality is commonly known as -.Em sshfs . -.Pp -The mandatory parameters are the target host name and local mount -point. -The target host parameter can optionally contain a username whose -credentials will be used by the remote sshd, and a relative or -absolute path for the remote mount point's root. -If no user is given, the credentials of the user issuing the mount -command are used. -If no path is given, the user's home directory on the remote machine -will be used. -.Pp -The following command line options are available: -.Bl -tag -width xxx -.It Fl c Ar nconnect -Opens -.Ar nconnect -connections to the server. -Currently, the value has to be 1 or 2. -If 2 is specified, a second connection is opened for the reading -and writing of data, while directory operations are performed on -their own connection. -This can greatly increase directory operation performance (ls, -mkdir, etc.) if -.Nm -completely saturates the available bandwidth by doing bulk data copying. -The default is 1. -.It Fl e -Makes the mounted file system NFS exportable. -If this option is used, it is very important to understand that -.Nm -can not provide complete support for NFS due to the limitations in -the backend. -Files are valid only for the time that -.Nm -is running and in the event of e.g. a server crash, all client retries -to access files will fail. -.It Fl F Ar configfile -Pass a configuration file to -.Xr ssh 1 . -This will make it ignore the system-wide -.Pa /etc/ssh/ssh_config -configuration file and use -.Pa configfile -instead of -.Pa ~/.ssh/config . -.It Fl g Ar manglegid -Converts remote -.Ar manglegid -to the effective gid of the file server and vice versa. -See -.Fl u . -.It Fl o Ar [no]option -This flag can be used to give standard mount options and options -to puffs. -.It Fl O Ar sshopt=value -Pass an option to -.Xr ssh 1 , -for example -.Fl O Ar Port=22 . -For a list of valid options, see -.Xr ssh_config 5 . -.It Fl p -Preserve connection. -This option makes -.Nm -to try to reconnect to the server if the connection fails. -The option is very experimental and does not preserve open files -or retry current requests and should generally only be used if the -trade-offs are well understood. -.It Fl r Ar max_reads -Limits maximum outstanding read requests for each node to -.Ar max_reads . -This can be used to improve interactive performance on low-bandwidth links -when also performing bulk data reads. -.It Fl s -This flag can be used to make the program stay on top. -The default is to detach from the terminal and run in the background. -.It Fl t Ar timeout -By default -.Nm -caches directory contents and node attributes for 30 seconds before -re-fetching from the server to check if anything has changed on -the server. -This option is used to adjust the timeout period to -.Ar timeout -seconds. -A value 0 means the cache is never valid and \-1 means it is -valid indefinitely. -It is possible to force a re-read regardless of timeout status by sending -.Dv SIGHUP -to the -.Nm -process. -.Pp -Note: the file system will still free nodes when requested by the -kernel and will lose all cached information in doing so. -How frequently this happens depends on system activity and the total -number of available vnodes in the system (kern.maxvnodes). -.It Fl u Ar mangleuid -Converts remote -.Ar mangleuid -to the effective uid of the file server and vice versa. -.\"This is a simple special case of the functionality of -.\".Xr mount_umap 8 . -For example: you mount remote me@darkmoon as the local user "me". -If the uid of "me" on the local system is 101 and on -darkmoon it is 202, you would use -.Fl u -.Ar 202 -to see files owned by 202 on darkmoon as owned by 101 when browsing the -mount point. -Apart from the cosmetic effect, this makes things like -"chown me file" work. -See -.Fl g . -.El -.Sh EXAMPLES -The following example illustrates how to mount the directory -.Em /usr -on server -.Em bigiron -as user -.Em abc -on local directory -.Em /mnt -with ssh transport compression enabled: -.Bd -literal -offset indent -mount_psshfs -O Compression=yes abc@bigiron:/usr /mnt -.Ed -.Pp -It is possible to use -.Xr fstab 5 -for psshfs mounts, with SSH public key authentication: -.Pp -.Dl "abc@bigiron:/usr /mnt psshfs rw,noauto,-O=BatchMode=yes,-O=IdentityFile=/root/.ssh/id_rsa,-t=-1" -.Sh SEE ALSO -.Xr sftp 1 , -.Xr puffs 3 , -.Xr puffs 4 , -.Xr fstab 5 , -.Xr ssh_config 5 , -.Xr mount 8 , -.Xr sshd 8 -.Sh HISTORY -The -.Nm -utility first appeared in -.Nx 5.0 . -It was inspired by FUSE sshfs. -.Sh CAVEATS -Permissions are not handled. -Do not expect the file system to behave except for a single user. -.Pp -Depending on if the server supports the -.Xr sftp 1 -stavfs protocol extension, -free disk space may be displayed for the mount by -.Xr df 1 . -This information reflects the status at the server's mountpoint -and may differ for subdirectories under the mount root. diff --git a/usr.sbin/puffs/mount_psshfs/node.c b/usr.sbin/puffs/mount_psshfs/node.c deleted file mode 100644 index e5573ed350..0000000000 --- a/usr.sbin/puffs/mount_psshfs/node.c +++ /dev/null @@ -1,926 +0,0 @@ -/* $NetBSD: node.c,v 1.62 2010/10/29 16:13:51 pooka Exp $ */ - -/* - * Copyright (c) 2006-2009 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 -#include -#include -#include - -#include "psshfs.h" -#include "sftp_proto.h" - -int -psshfs_node_lookup(struct puffs_usermount *pu, puffs_cookie_t opc, - struct puffs_newinfo *pni, const struct puffs_cn *pcn) -{ - struct psshfs_ctx *pctx = puffs_getspecific(pu); - struct puffs_node *pn_dir = opc; - struct psshfs_node *psn, *psn_dir = pn_dir->pn_data; - struct puffs_node *pn; - struct psshfs_dir *pd; - struct vattr va; - int rv; - - rv = sftp_readdir(pu, pctx, pn_dir); - if (rv) { - if (rv != EPERM) - return rv; - - /* - * Can't read the directory. We still might be - * able to find the node with getattr in -r+x dirs - */ - rv = getpathattr(pu, PCNPATH(pcn), &va); - if (rv) - return rv; - - /* guess */ - if (va.va_type == VDIR) - va.va_nlink = 2; - else - va.va_nlink = 1; - - pn = allocnode(pu, pn_dir, pcn->pcn_name, &va); - psn = pn->pn_data; - psn->attrread = time(NULL); - } else { - pd = lookup(psn_dir->dir, psn_dir->dentnext, pcn->pcn_name); - if (!pd) { - return ENOENT; - } - - if (pd->entry) - pn = pd->entry; - else - pd->entry = pn = makenode(pu, pn_dir, pd, &pd->va); - - /* - * sure sure we have fresh attributes. most likely we will - * have them cached. we might not if we go through: - * create - reclaim - lookup (this). - */ - rv = getnodeattr(pu, pn, PCNPATH(pcn)); - if (rv) - return rv; - - psn = pn->pn_data; - } - - psn->stat &= ~PSN_RECLAIMED; - - puffs_newinfo_setcookie(pni, pn); - puffs_newinfo_setvtype(pni, pn->pn_va.va_type); - puffs_newinfo_setsize(pni, pn->pn_va.va_size); - - return 0; -} - -int -psshfs_node_lookupdotdot(struct puffs_usermount *pu, puffs_cookie_t opc, - struct puffs_newinfo *pni, const struct puffs_cn *pcn) -{ - struct puffs_node *pn_dir = opc; - struct psshfs_node *psn, *psn_dir = pn_dir->pn_data; - - psn = psn_dir->parent->pn_data; - psn->stat &= ~PSN_RECLAIMED; - - puffs_newinfo_setcookie(pni, psn_dir->parent); - puffs_newinfo_setvtype(pni, VDIR); - return 0; -} - -int -psshfs_node_getattr(struct puffs_usermount *pu, puffs_cookie_t opc, - struct vattr *vap, const struct puffs_cred *pcr) -{ - struct puffs_node *pn = opc; - int rv; - - rv = getnodeattr(pu, pn, NULL); - if (rv) - return rv; - - memcpy(vap, &pn->pn_va, sizeof(struct vattr)); - - return 0; -} - -int -psshfs_node_setattr(struct puffs_usermount *pu, puffs_cookie_t opc, - const struct vattr *va, const struct puffs_cred *pcr) -{ - PSSHFSAUTOVAR(pu); - struct vattr kludgeva; - struct puffs_node *pn = opc; - - psbuf_req_str(pb, SSH_FXP_SETSTAT, reqid, PNPATH(pn)); - - memcpy(&kludgeva, va, sizeof(struct vattr)); - - /* XXX: kludge due to openssh server implementation */ - if (va->va_atime.tv_sec != PUFFS_VNOVAL - && va->va_mtime.tv_sec == PUFFS_VNOVAL) { - if (pn->pn_va.va_mtime.tv_sec != PUFFS_VNOVAL) - kludgeva.va_mtime.tv_sec = pn->pn_va.va_mtime.tv_sec; - else - kludgeva.va_mtime.tv_sec = va->va_atime.tv_sec; - } - if (va->va_mtime.tv_sec != PUFFS_VNOVAL - && va->va_atime.tv_sec == PUFFS_VNOVAL) { - if (pn->pn_va.va_atime.tv_sec != PUFFS_VNOVAL) - kludgeva.va_atime.tv_sec = pn->pn_va.va_atime.tv_sec; - else - kludgeva.va_atime.tv_sec = va->va_mtime.tv_sec; - } - - psbuf_put_vattr(pb, &kludgeva, pctx); - GETRESPONSE(pb, pctx->sshfd); - - rv = psbuf_expect_status(pb); - if (rv == 0) - puffs_setvattr(&pn->pn_va, &kludgeva); - - out: - PSSHFSRETURN(rv); -} - -int -psshfs_node_create(struct puffs_usermount *pu, puffs_cookie_t opc, - struct puffs_newinfo *pni, const struct puffs_cn *pcn, - const struct vattr *va) -{ - PSSHFSAUTOVAR(pu); - struct puffs_node *pn = opc; - struct puffs_node *pn_new; - char *fhand = NULL; - uint32_t fhandlen; - - /* Create node on server first */ - psbuf_req_str(pb, SSH_FXP_OPEN, reqid, PCNPATH(pcn)); - psbuf_put_4(pb, SSH_FXF_WRITE | SSH_FXF_CREAT | SSH_FXF_TRUNC); - psbuf_put_vattr(pb, va, pctx); - GETRESPONSE(pb, pctx->sshfd); - rv = psbuf_expect_handle(pb, &fhand, &fhandlen); - if (rv) - goto out; - - /* - * Do *not* create the local node before getting a response - * from the server. Otherwise we might screw up consistency, - * namely that the node can be looked up before create has - * returned (mind you, the kernel will unlock the directory - * before the create call from userspace returns). - */ - pn_new = allocnode(pu, pn, pcn->pcn_name, va); - if (!pn_new) { - struct puffs_framebuf *pb2 = psbuf_makeout(); - reqid = NEXTREQ(pctx); - psbuf_req_str(pb2, SSH_FXP_REMOVE, reqid, PCNPATH(pcn)); - JUSTSEND(pb2, pctx->sshfd); - rv = ENOMEM; - } - - if (pn_new) - puffs_newinfo_setcookie(pni, pn_new); - - reqid = NEXTREQ(pctx); - psbuf_recycleout(pb); - psbuf_req_data(pb, SSH_FXP_CLOSE, reqid, fhand, fhandlen); - JUSTSEND(pb, pctx->sshfd); - free(fhand); - return rv; - - out: - free(fhand); - PSSHFSRETURN(rv); -} - -/* - * Open a file handle. This is used for read and write. We do not - * wait here for the success or failure of this operation. This is - * because otherwise opening and closing file handles would block - * reading potentially cached information. Rather, we defer the wait - * to read/write and therefore allow cached access without a wait. - * - * If we have not yet succesfully opened a type of handle, we do wait - * here. Also, if a lazy open fails, we revert back to the same - * state of waiting. - */ -int -psshfs_node_open(struct puffs_usermount *pu, puffs_cookie_t opc, int mode, - const struct puffs_cred *pcr) -{ - struct puffs_cc *pcc = puffs_cc_getcc(pu); - struct psshfs_ctx *pctx = puffs_getspecific(pu); - struct puffs_framebuf *pb, *pb2; - struct vattr va; - struct puffs_node *pn = opc; - struct psshfs_node *psn = pn->pn_data; - uint32_t reqid; - int didread, didwrite; - int rv = 0; - - if (pn->pn_va.va_type == VDIR) - return 0; - - puffs_setback(pcc, PUFFS_SETBACK_INACT_N1); - puffs_vattr_null(&va); - didread = didwrite = 0; - if (mode & FREAD && psn->fhand_r == NULL && psn->lazyopen_r == NULL) { - pb = psbuf_makeout(); - - reqid = NEXTREQ(pctx); - psbuf_req_str(pb, SSH_FXP_OPEN, reqid, PNPATH(pn)); - psbuf_put_4(pb, SSH_FXF_READ); - psbuf_put_vattr(pb, &va, pctx); - - if (puffs_framev_enqueue_cb(pu, pctx->sshfd_data, pb, - lazyopen_rresp, psn, 0) == -1) { - rv = errno; - puffs_framebuf_destroy(pb); - goto out; - } - - psn->lazyopen_r = pb; - didread = 1; - } - if (mode & FWRITE && psn->fhand_w == NULL && psn->lazyopen_w == NULL) { - pb2 = psbuf_makeout(); - - reqid = NEXTREQ(pctx); - psbuf_req_str(pb2, SSH_FXP_OPEN, reqid, PNPATH(pn)); - psbuf_put_4(pb2, SSH_FXF_WRITE); - psbuf_put_vattr(pb2, &va, pctx); - - if (puffs_framev_enqueue_cb(pu, pctx->sshfd_data, pb2, - lazyopen_wresp, psn, 0) == -1) { - rv = errno; - puffs_framebuf_destroy(pb2); - goto out; - } - - psn->lazyopen_w = pb2; - didwrite = 1; - } - psn->stat &= ~PSN_HANDLECLOSE; - - out: - /* wait? */ - if (didread && (psn->stat & PSN_DOLAZY_R) == 0) { - assert(psn->lazyopen_r); - - rv = puffs_framev_framebuf_ccpromote(psn->lazyopen_r, pcc); - lazyopen_rresp(pu, psn->lazyopen_r, psn, rv); - if (psn->fhand_r) { - psn->stat |= PSN_DOLAZY_R; - } else { - if (psn->lazyopen_err_r) - return psn->lazyopen_err_r; - return EINVAL; - } - } - - /* wait? */ - if (didwrite && (psn->stat & PSN_DOLAZY_W) == 0) { - assert(psn->lazyopen_w); - - rv = puffs_framev_framebuf_ccpromote(psn->lazyopen_w, pcc); - lazyopen_wresp(pu, psn->lazyopen_w, psn, rv); - if (psn->fhand_w) { - psn->stat |= PSN_DOLAZY_W; - } else { - if (psn->lazyopen_err_w) - return psn->lazyopen_err_w; - return EINVAL; - } - } - - return rv; -} - -int -psshfs_node_inactive(struct puffs_usermount *pu, puffs_cookie_t opc) -{ - struct puffs_node *pn = opc; - - closehandles(pu, pn->pn_data, HANDLE_READ | HANDLE_WRITE); - return 0; -} - -int -psshfs_node_readdir(struct puffs_usermount *pu, puffs_cookie_t opc, - struct dirent *dent, off_t *readoff, size_t *reslen, - const struct puffs_cred *pcr, int *eofflag, - off_t *cookies, size_t *ncookies) -{ - struct puffs_cc *pcc = puffs_cc_getcc(pu); - struct psshfs_ctx *pctx = puffs_getspecific(pu); - struct puffs_node *pn = opc; - struct psshfs_node *psn = pn->pn_data; - struct psshfs_dir *pd; - size_t i; - int rv, set_readdir; - - restart: - if (psn->stat & PSN_READDIR) { - struct psshfs_wait pw; - - set_readdir = 0; - pw.pw_cc = pcc; - pw.pw_type = PWTYPE_READDIR; - TAILQ_INSERT_TAIL(&psn->pw, &pw, pw_entries); - puffs_cc_yield(pcc); - goto restart; - } else { - psn->stat |= PSN_READDIR; - set_readdir = 1; - } - - *ncookies = 0; - rv = sftp_readdir(pu, pctx, pn); - if (rv) { - goto out; - } - - /* find next dirent */ - for (i = *readoff;;i++) { - if (i >= psn->dentnext) - goto out; - pd = &psn->dir[i]; - if (pd->valid) - break; - } - - for (;;) { - *readoff = i; - if (!puffs_nextdent(&dent, pd->entryname, - pd->va.va_fileid, puffs_vtype2dt(pd->va.va_type), reslen)) { - rv = 0; - goto out; - } - - /* find next entry, store possible nfs key */ - do { - if (++i >= psn->dentnext) - goto out; - pd = &psn->dir[i]; - } while (pd->valid == 0); - PUFFS_STORE_DCOOKIE(cookies, ncookies, (off_t)i); - } - - out: - if (rv == 0) { - if (i >= psn->dentnext) - *eofflag = 1; - - *readoff = i; - } - - if (set_readdir) { - struct psshfs_wait *pw; - - /* all will likely run to completion because of cache */ - TAILQ_FOREACH(pw, &psn->pw, pw_entries) { - assert(pw->pw_type == PWTYPE_READDIR); - puffs_cc_schedule(pw->pw_cc); - TAILQ_REMOVE(&psn->pw, pw, pw_entries); - } - - psn->stat &= ~PSN_READDIR; - } - - return rv; -} - -int -psshfs_node_read(struct puffs_usermount *pu, puffs_cookie_t opc, uint8_t *buf, - off_t offset, size_t *resid, const struct puffs_cred *pcr, - int ioflag) -{ - PSSHFSAUTOVAR(pu); - struct puffs_node *pn = opc; - struct psshfs_node *psn = pn->pn_data; - struct psshfs_wait *pwp; - uint32_t readlen; - - if (pn->pn_va.va_type == VDIR) { - rv = EISDIR; - goto farout; - } - - /* check that a lazyopen didn't fail */ - if (!psn->fhand_r && !psn->lazyopen_r) { - rv = psn->lazyopen_err_r; - goto farout; - } - - /* if someone is already waiting for the lazyopen, "just" wait */ - if (psn->stat & PSN_LAZYWAIT_R) { - struct psshfs_wait pw; - - assert(psn->lazyopen_r); - - pw.pw_cc = pcc; - pw.pw_type = PWTYPE_READ1; - TAILQ_INSERT_TAIL(&psn->pw, &pw, pw_entries); - puffs_cc_yield(pcc); - } - - /* if lazyopening, wait for the result */ - if (psn->lazyopen_r) { - psn->stat |= PSN_LAZYWAIT_R; - rv = puffs_framev_framebuf_ccpromote(psn->lazyopen_r, pcc); - lazyopen_rresp(pu, psn->lazyopen_r, psn, rv); - - /* schedule extra waiters */ - TAILQ_FOREACH(pwp, &psn->pw, pw_entries) - if (pwp->pw_type == PWTYPE_READ1) { - puffs_cc_schedule(pwp->pw_cc); - TAILQ_REMOVE(&psn->pw, pwp, pw_entries); - } - psn->stat &= ~PSN_LAZYWAIT_R; - - if ((rv = psn->lazyopen_err_r) != 0) - goto farout; - } - - /* if there is still no handle, just refuse to live with this */ - if (!psn->fhand_r) { - rv = EINVAL; - goto farout; - } - - readlen = *resid; - psbuf_req_data(pb, SSH_FXP_READ, reqid, psn->fhand_r, psn->fhand_r_len); - psbuf_put_8(pb, offset); - psbuf_put_4(pb, readlen); - - /* - * Do this *after* accessing the file, the handle might not - * exist after blocking. - */ - if (max_reads && ++psn->readcount > max_reads) { - struct psshfs_wait pw; - - pw.pw_cc = pcc; - pw.pw_type = PWTYPE_READ2; - TAILQ_INSERT_TAIL(&psn->pw, &pw, pw_entries); - puffs_cc_yield(pcc); - } - - GETRESPONSE(pb, pctx->sshfd_data); - - rv = psbuf_do_data(pb, buf, &readlen); - if (rv == 0) - *resid -= readlen; - - out: - if (max_reads && --psn->readcount >= max_reads) { - TAILQ_FOREACH(pwp, &psn->pw, pw_entries) - if (pwp->pw_type == PWTYPE_READ2) - break; - assert(pwp != NULL); - puffs_cc_schedule(pwp->pw_cc); - TAILQ_REMOVE(&psn->pw, pwp, pw_entries); - } - - farout: - /* check if we need a lazyclose */ - if (psn->stat & PSN_HANDLECLOSE && psn->fhand_r) { - TAILQ_FOREACH(pwp, &psn->pw, pw_entries) - if (pwp->pw_type == PWTYPE_READ1) - break; - if (pwp == NULL) - closehandles(pu, psn, HANDLE_READ); - } - PSSHFSRETURN(rv); -} - -/* XXX: we should getattr for size */ -int -psshfs_node_write(struct puffs_usermount *pu, puffs_cookie_t opc, uint8_t *buf, - off_t offset, size_t *resid, const struct puffs_cred *cred, - int ioflag) -{ - PSSHFSAUTOVAR(pu); - struct psshfs_wait *pwp; - struct puffs_node *pn = opc; - struct psshfs_node *psn = pn->pn_data; - uint32_t writelen; - - if (pn->pn_va.va_type == VDIR) { - rv = EISDIR; - goto out; - } - - /* check that a lazyopen didn't fail */ - if (!psn->fhand_w && !psn->lazyopen_w) { - rv = psn->lazyopen_err_w; - goto out; - } - - if (psn->stat & PSN_LAZYWAIT_W) { - struct psshfs_wait pw; - - assert(psn->lazyopen_w); - - pw.pw_cc = pcc; - pw.pw_type = PWTYPE_WRITE; - TAILQ_INSERT_TAIL(&psn->pw, &pw, pw_entries); - puffs_cc_yield(pcc); - } - - /* - * If lazyopening, wait for the result. - * There can still be more than oen writer at a time in case - * the kernel issues write FAFs. - */ - if (psn->lazyopen_w) { - psn->stat |= PSN_LAZYWAIT_W; - rv = puffs_framev_framebuf_ccpromote(psn->lazyopen_w, pcc); - lazyopen_wresp(pu, psn->lazyopen_w, psn, rv); - - /* schedule extra waiters */ - TAILQ_FOREACH(pwp, &psn->pw, pw_entries) - if (pwp->pw_type == PWTYPE_WRITE) { - puffs_cc_schedule(pwp->pw_cc); - TAILQ_REMOVE(&psn->pw, pwp, pw_entries); - } - psn->stat &= ~PSN_LAZYWAIT_W; - - if ((rv = psn->lazyopen_err_w) != 0) - goto out; - } - - if (!psn->fhand_w) { - abort(); - rv = EINVAL; - goto out; - } - - writelen = *resid; - psbuf_req_data(pb, SSH_FXP_WRITE, reqid, psn->fhand_w,psn->fhand_w_len); - psbuf_put_8(pb, offset); - psbuf_put_data(pb, buf, writelen); - GETRESPONSE(pb, pctx->sshfd_data); - - rv = psbuf_expect_status(pb); - if (rv == 0) - *resid = 0; - - if (pn->pn_va.va_size < (uint64_t)offset + writelen) - pn->pn_va.va_size = offset + writelen; - - out: - /* check if we need a lazyclose */ - if (psn->stat & PSN_HANDLECLOSE && psn->fhand_w) { - TAILQ_FOREACH(pwp, &psn->pw, pw_entries) - if (pwp->pw_type == PWTYPE_WRITE) - break; - if (pwp == NULL) - closehandles(pu, psn, HANDLE_WRITE); - } - PSSHFSRETURN(rv); -} - -int -psshfs_node_readlink(struct puffs_usermount *pu, puffs_cookie_t opc, - const struct puffs_cred *cred, char *linkvalue, size_t *linklen) -{ - PSSHFSAUTOVAR(pu); - struct puffs_node *pn = opc; - struct psshfs_node *psn = pn->pn_data; - uint32_t count; - - if (pctx->protover < 3) { - rv = EOPNOTSUPP; - goto out; - } - - /* - * check if we can use a cached version - * - * XXX: we might end up reading the same link multiple times - * from the server if we get many requests at once, but that's - * quite harmless as this routine is reentrant. - */ - if (psn->symlink && !REFRESHTIMEOUT(pctx, time(NULL) - psn->slread)) - goto copy; - - if (psn->symlink) { - free(psn->symlink); - psn->symlink = NULL; - psn->slread = 0; - } - - psbuf_req_str(pb, SSH_FXP_READLINK, reqid, PNPATH(pn)); - GETRESPONSE(pb, pctx->sshfd); - - rv = psbuf_expect_name(pb, &count); - if (rv) - goto out; - if (count != 1) { - rv = EPROTO; - goto out; - } - - rv = psbuf_get_str(pb, &psn->symlink, NULL); - if (rv) - goto out; - psn->slread = time(NULL); - - copy: - *linklen = strlen(psn->symlink); - (void) memcpy(linkvalue, psn->symlink, *linklen); - - out: - PSSHFSRETURN(rv); -} - -static int -doremove(struct puffs_usermount *pu, struct puffs_node *pn_dir, - struct puffs_node *pn, const char *name) -{ - PSSHFSAUTOVAR(pu); - int op; - - if (pn->pn_va.va_type == VDIR) - op = SSH_FXP_RMDIR; - else - op = SSH_FXP_REMOVE; - - psbuf_req_str(pb, op, reqid, PNPATH(pn)); - GETRESPONSE(pb, pctx->sshfd); - - rv = psbuf_expect_status(pb); - if (rv == 0) - nukenode(pn, name, 0); - - out: - PSSHFSRETURN(rv); -} - -int -psshfs_node_remove(struct puffs_usermount *pu, puffs_cookie_t opc, - puffs_cookie_t targ, const struct puffs_cn *pcn) -{ - struct puffs_node *pn_targ = targ; - int rv; - - assert(pn_targ->pn_va.va_type != VDIR); - - rv = doremove(pu, opc, targ, pcn->pcn_name); - if (rv == 0) - puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N2); - - return rv; -} - -int -psshfs_node_rmdir(struct puffs_usermount *pu, puffs_cookie_t opc, - puffs_cookie_t targ, const struct puffs_cn *pcn) -{ - struct puffs_node *pn_targ = targ; - int rv; - - assert(pn_targ->pn_va.va_type == VDIR); - - rv = doremove(pu, opc, targ, pcn->pcn_name); - if (rv == 0) - puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N2); - - return rv; -} - -int -psshfs_node_mkdir(struct puffs_usermount *pu, puffs_cookie_t opc, - struct puffs_newinfo *pni, const struct puffs_cn *pcn, - const struct vattr *va) -{ - PSSHFSAUTOVAR(pu); - struct puffs_node *pn = opc; - struct puffs_node *pn_new; - - psbuf_req_str(pb, SSH_FXP_MKDIR, reqid, PCNPATH(pcn)); - psbuf_put_vattr(pb, va, pctx); - GETRESPONSE(pb, pctx->sshfd); - - rv = psbuf_expect_status(pb); - if (rv) - goto out; - - pn_new = allocnode(pu, pn, pcn->pcn_name, va); - if (pn_new) { - puffs_newinfo_setcookie(pni, pn_new); - } else { - struct puffs_framebuf *pb2 = psbuf_makeout(); - reqid = NEXTREQ(pctx); - psbuf_recycleout(pb2); - psbuf_req_str(pb2, SSH_FXP_RMDIR, reqid, PCNPATH(pcn)); - JUSTSEND(pb2, pctx->sshfd); - rv = ENOMEM; - } - - out: - PSSHFSRETURN(rv); -} - -int -psshfs_node_link(struct puffs_usermount *pu, puffs_cookie_t opc, - puffs_cookie_t targ, const struct puffs_cn *pcn) -{ - PSSHFSAUTOVAR(pu); - struct puffs_node *pn = opc; - struct puffs_node *pn_targ = targ; - - if (pctx->protover < 3) { - rv = EOPNOTSUPP; - goto out; - } - - psbuf_req_str(pb, SSH_FXP_EXTENDED, reqid, "hardlink@openssh.com"); - psbuf_put_str(pb, PNPATH(pn_targ)); - psbuf_put_str(pb, PCNPATH(pcn)); - - GETRESPONSE(pb, pctx->sshfd); - rv = psbuf_expect_status(pb); - - if (rv == 0) { - struct psshfs_node *psn; - - /* Force refresh of attributes */ - psn = pn_targ->pn_data; - psn->attrread = 0; - - /* Force refresh of dirents */ - psn = pn->pn_data; - if (psn->dir) - psn->dentread = 0; - } - - out: - PSSHFSRETURN(rv); -} - -int -psshfs_node_symlink(struct puffs_usermount *pu, puffs_cookie_t opc, - struct puffs_newinfo *pni, const struct puffs_cn *pcn, - const struct vattr *va, const char *link_target) -{ - PSSHFSAUTOVAR(pu); - struct puffs_node *pn = opc; - struct puffs_node *pn_new; - - if (pctx->protover < 3) { - rv = EOPNOTSUPP; - goto out; - } - - /* - * XXX: ietf says: source, target. openssh says: ietf who? - * Let's go with openssh and build quirk tables later if we care - */ - psbuf_req_str(pb, SSH_FXP_SYMLINK, reqid, link_target); - psbuf_put_str(pb, PCNPATH(pcn)); - GETRESPONSE(pb, pctx->sshfd); - - rv = psbuf_expect_status(pb); - if (rv) - goto out; - - pn_new = allocnode(pu, pn, pcn->pcn_name, va); - if (pn_new) { - puffs_newinfo_setcookie(pni, pn_new); - } else { - struct puffs_framebuf *pb2 = psbuf_makeout(); - reqid = NEXTREQ(pctx); - psbuf_recycleout(pb2); - psbuf_req_str(pb2, SSH_FXP_REMOVE, reqid, PCNPATH(pcn)); - JUSTSEND(pb2, pctx->sshfd); - rv = ENOMEM; - } - - out: - PSSHFSRETURN(rv); -} - -int -psshfs_node_rename(struct puffs_usermount *pu, puffs_cookie_t opc, - puffs_cookie_t src, const struct puffs_cn *pcn_src, - puffs_cookie_t targ_dir, puffs_cookie_t targ, - const struct puffs_cn *pcn_targ) -{ - PSSHFSAUTOVAR(pu); - struct puffs_node *pn_sf = src; - struct puffs_node *pn_td = targ_dir, *pn_tf = targ; - struct psshfs_node *psn_src = pn_sf->pn_data; - struct psshfs_node *psn_targdir = pn_td->pn_data; - - if (pctx->protover < 2) { - rv = EOPNOTSUPP; - goto out; - } - - if (pn_tf) { - rv = doremove(pu, targ_dir, pn_tf, pcn_targ->pcn_name); - if (rv) - goto out; - } - - psbuf_req_str(pb, SSH_FXP_RENAME, reqid, PCNPATH(pcn_src)); - psbuf_put_str(pb, PCNPATH(pcn_targ)); - GETRESPONSE(pb, pctx->sshfd); - - rv = psbuf_expect_status(pb); - if (rv == 0) { - struct psshfs_dir *pd; - - /* - * XXX: interfaces didn't quite work with rename.. - * the song remains the same. go figure .. ;) - */ - nukenode(pn_sf, pcn_src->pcn_name, 0); - pd = direnter(pn_td, pcn_targ->pcn_name); - pd->entry = pn_sf; - puffs_setvattr(&pd->va, &pn_sf->pn_va); - - if (opc != targ_dir) { - psn_targdir->childcount++; - psn_src->parent = pn_td; - if (pn_sf->pn_va.va_type == VDIR) - pn_td->pn_va.va_nlink++; - } - } - - out: - PSSHFSRETURN(rv); -} - -/* - * So this file system happened to be written in such a way that - * lookup for ".." is hard if we lose the in-memory node. We'd - * need to recreate the entire directory structure from the root - * node up to the ".." node we're looking up. - * - * And since our entire fs structure is purely fictional (i.e. it's - * only in-memory, not fetchable from the server), the easiest way - * to deal with it is to not allow nodes with children to be - * reclaimed. - * - * If a node with children is being attempted to be reclaimed, we - * just mark it "reclaimed" but leave it as is until all its children - * have been reclaimed. If a lookup for that node is done meanwhile, - * it will be found by lookup() and we just remove the "reclaimed" - * bit. - */ -int -psshfs_node_reclaim(struct puffs_usermount *pu, puffs_cookie_t opc) -{ - struct puffs_node *pn = opc, *pn_next, *pn_root; - struct psshfs_node *psn = pn->pn_data; - - /* - * don't reclaim if we have file handle issued, otherwise - * we can't do fhtonode - */ - if (psn->stat & PSN_HASFH) - return 0; - - psn->stat |= PSN_RECLAIMED; - pn_root = puffs_getroot(pu); - for (; pn != pn_root; pn = pn_next) { - psn = pn->pn_data; - if ((psn->stat & PSN_RECLAIMED) == 0 || psn->childcount != 0) - break; - - pn_next = psn->parent; - doreclaim(pn); - } - - return 0; -} diff --git a/usr.sbin/puffs/mount_psshfs/psbuf.c b/usr.sbin/puffs/mount_psshfs/psbuf.c deleted file mode 100644 index f7cb1958d2..0000000000 --- a/usr.sbin/puffs/mount_psshfs/psbuf.c +++ /dev/null @@ -1,595 +0,0 @@ -/* $NetBSD: psbuf.c,v 1.18 2010/01/08 10:53:31 pooka Exp $ */ - -/* - * Copyright (c) 2006-2009 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. - */ - -/* - * buffering functions for network input/output. slightly different - * from the average joe buffer routines, as is usually the case ... - * these use efuns for now. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "psshfs.h" -#include "sftp_proto.h" -#include "util_compat.h" - -#define FAILRV(x) do { int rv; if ((rv=x)) return (rv); } while (/*CONSTCOND*/0) -#define READSTATE_LENGTH(off) (off < 4) - -#define SFTP_LENOFF 0 -#define SFTP_TYPEOFF 4 -#define SFTP_REQIDOFF 5 - -#define CHECK(v) if (!(v)) abort() - -#define HTOBE16(x) (x) = htobe16((uint16_t)(x)) -#define HTOBE32(x) (x) = htobe32((uint32_t)(x)) -#define HTOBE64(x) (x) = htobe64((uint64_t)(x)) -#define BE16TOH(x) (x) = be16toh((uint16_t)(x)) -#define BE32TOH(x) (x) = be32toh((uint32_t)(x)) -#define BE64TOH(x) (x) = be64toh((uint64_t)(x)) - -uint8_t -psbuf_get_type(struct puffs_framebuf *pb) -{ - uint8_t type; - - puffs_framebuf_getdata_atoff(pb, SFTP_TYPEOFF, &type, 1); - return type; -} - -uint32_t -psbuf_get_len(struct puffs_framebuf *pb) -{ - uint32_t len; - - puffs_framebuf_getdata_atoff(pb, SFTP_LENOFF, &len, 4); - return be32toh(len); -} - -uint32_t -psbuf_get_reqid(struct puffs_framebuf *pb) -{ - uint32_t req; - - puffs_framebuf_getdata_atoff(pb, SFTP_REQIDOFF, &req, 4); - return be32toh(req); -} - -#define CUROFF(pb) (puffs_framebuf_telloff(pb)) -int -psbuf_read(struct puffs_usermount *pu, struct puffs_framebuf *pb, - int fd, int *done) -{ - void *win; - ssize_t n; - size_t howmuch, winlen; - int lenstate; - - the_next_level: - if ((lenstate = READSTATE_LENGTH(CUROFF(pb)))) - howmuch = 4 - CUROFF(pb); - else - howmuch = psbuf_get_len(pb) - (CUROFF(pb) - 4); - - if (puffs_framebuf_reserve_space(pb, howmuch) == -1) - return errno; - - while (howmuch) { - winlen = howmuch; - if (puffs_framebuf_getwindow(pb, CUROFF(pb), &win, &winlen)==-1) - return errno; - n = recv(fd, win, winlen, MSG_NOSIGNAL); - switch (n) { - case 0: - return ECONNRESET; - case -1: - if (errno == EAGAIN) - return 0; - return errno; - default: - howmuch -= n; - puffs_framebuf_seekset(pb, CUROFF(pb) + n); - break; - } - } - - if (!lenstate) { - /* XXX: initial exchange shorter.. but don't worry, be happy */ - puffs_framebuf_seekset(pb, 9); - *done = 1; - return 0; - } else - goto the_next_level; -} - -int -psbuf_write(struct puffs_usermount *pu, struct puffs_framebuf *pb, - int fd, int *done) -{ - void *win; - ssize_t n; - size_t winlen, howmuch; - - /* finalize buffer.. could be elsewhere ... */ - if (CUROFF(pb) == 0) { - uint32_t len; - - len = htobe32(puffs_framebuf_tellsize(pb) - 4); - puffs_framebuf_putdata_atoff(pb, 0, &len, 4); - } - - howmuch = puffs_framebuf_tellsize(pb) - CUROFF(pb); - while (howmuch) { - winlen = howmuch; - if (puffs_framebuf_getwindow(pb, CUROFF(pb), &win, &winlen)==-1) - return errno; - n = send(fd, win, winlen, MSG_NOSIGNAL); - switch (n) { - case 0: - return ECONNRESET; - case -1: - if (errno == EAGAIN) - return 0; - return errno; - default: - howmuch -= n; - puffs_framebuf_seekset(pb, CUROFF(pb) + n); - break; - } - } - - *done = 1; - return 0; -} -#undef CUROFF - -int -psbuf_cmp(struct puffs_usermount *pu, - struct puffs_framebuf *cmp1, struct puffs_framebuf *cmp2, int *notresp) -{ - - return psbuf_get_reqid(cmp1) != psbuf_get_reqid(cmp2); -} - -struct puffs_framebuf * -psbuf_makeout(void) -{ - struct puffs_framebuf *pb; - - pb = puffs_framebuf_make(); - puffs_framebuf_seekset(pb, 4); - return pb; -} - -void -psbuf_recycleout(struct puffs_framebuf *pb) -{ - - puffs_framebuf_recycle(pb); - puffs_framebuf_seekset(pb, 4); -} - -void -psbuf_put_1(struct puffs_framebuf *pb, uint8_t val) -{ - int rv; - - rv = puffs_framebuf_putdata(pb, &val, 1); - CHECK(rv == 0); -} - -void -psbuf_put_2(struct puffs_framebuf *pb, uint16_t val) -{ - int rv; - - HTOBE16(val); - rv = puffs_framebuf_putdata(pb, &val, 2); - CHECK(rv == 0); -} - -void -psbuf_put_4(struct puffs_framebuf *pb, uint32_t val) -{ - int rv; - - HTOBE32(val); - rv = puffs_framebuf_putdata(pb, &val, 4); - CHECK(rv == 0); -} - -void -psbuf_put_8(struct puffs_framebuf *pb, uint64_t val) -{ - int rv; - - HTOBE64(val); - rv = puffs_framebuf_putdata(pb, &val, 8); - CHECK(rv == 0); -} - -void -psbuf_put_data(struct puffs_framebuf *pb, const void *data, uint32_t dlen) -{ - int rv; - - psbuf_put_4(pb, dlen); - rv = puffs_framebuf_putdata(pb, data, dlen); - CHECK(rv == 0); -} - -void -psbuf_put_str(struct puffs_framebuf *pb, const char *str) -{ - - psbuf_put_data(pb, str, strlen(str)); -} - -void -psbuf_put_vattr(struct puffs_framebuf *pb, const struct vattr *va, - const struct psshfs_ctx *pctx) -{ - uint32_t flags; - uint32_t theuid = -1, thegid = -1; - flags = 0; - - if (va->va_size != (uint64_t)PUFFS_VNOVAL) - flags |= SSH_FILEXFER_ATTR_SIZE; - if (va->va_uid != (uid_t)PUFFS_VNOVAL) { - theuid = va->va_uid; - if (pctx->domangleuid && theuid == pctx->myuid) - theuid = pctx->mangleuid; - flags |= SSH_FILEXFER_ATTR_UIDGID; - } - if (va->va_gid != (gid_t)PUFFS_VNOVAL) { - thegid = va->va_gid; - if (pctx->domanglegid && thegid == pctx->mygid) - thegid = pctx->manglegid; - flags |= SSH_FILEXFER_ATTR_UIDGID; - } - if (va->va_mode != (mode_t)PUFFS_VNOVAL) - flags |= SSH_FILEXFER_ATTR_PERMISSIONS; - - if (va->va_atime.tv_sec != PUFFS_VNOVAL) - flags |= SSH_FILEXFER_ATTR_ACCESSTIME; - - psbuf_put_4(pb, flags); - if (flags & SSH_FILEXFER_ATTR_SIZE) - psbuf_put_8(pb, va->va_size); - if (flags & SSH_FILEXFER_ATTR_UIDGID) { - psbuf_put_4(pb, theuid); - psbuf_put_4(pb, thegid); - } - if (flags & SSH_FILEXFER_ATTR_PERMISSIONS) - psbuf_put_4(pb, va->va_mode); - - /* XXX: this is totally wrong for protocol v3, see OpenSSH */ - if (flags & SSH_FILEXFER_ATTR_ACCESSTIME) { - psbuf_put_4(pb, va->va_atime.tv_sec); - psbuf_put_4(pb, va->va_mtime.tv_sec); - } -} - -#define ERETURN(rv) return ((rv) == -1 ? errno : 0) - -int -psbuf_get_1(struct puffs_framebuf *pb, uint8_t *val) -{ - - ERETURN(puffs_framebuf_getdata(pb, val, 1)); -} - -int -psbuf_get_2(struct puffs_framebuf *pb, uint16_t *val) -{ - int rv; - - rv = puffs_framebuf_getdata(pb, val, 2); - BE16TOH(*val); - - ERETURN(rv); -} - -int -psbuf_get_4(struct puffs_framebuf *pb, uint32_t *val) -{ - int rv; - - rv = puffs_framebuf_getdata(pb, val, 4); - BE32TOH(*val); - - ERETURN(rv); -} - -int -psbuf_get_8(struct puffs_framebuf *pb, uint64_t *val) -{ - int rv; - - rv = puffs_framebuf_getdata(pb, val, 8); - BE64TOH(*val); - - ERETURN(rv); -} - -int -psbuf_get_str(struct puffs_framebuf *pb, char **strp, uint32_t *strlenp) -{ - char *str; - uint32_t len; - - FAILRV(psbuf_get_4(pb, &len)); - - if (puffs_framebuf_remaining(pb) < len) - return EPROTO; - - str = emalloc(len+1); - puffs_framebuf_getdata(pb, str, len); - str[len] = '\0'; - *strp = str; - - if (strlenp) - *strlenp = len; - - return 0; -} - -int -psbuf_get_vattr(struct puffs_framebuf *pb, struct vattr *vap) -{ - uint32_t flags; - uint32_t val; - uint32_t tmpval; - - puffs_vattr_null(vap); - - FAILRV(psbuf_get_4(pb, &flags)); - - if (flags & SSH_FILEXFER_ATTR_SIZE) { - FAILRV(psbuf_get_8(pb, &vap->va_size)); - vap->va_bytes = vap->va_size; - } - if (flags & SSH_FILEXFER_ATTR_UIDGID) { - FAILRV(psbuf_get_4(pb, &vap->va_uid)); - FAILRV(psbuf_get_4(pb, &vap->va_gid)); - } - if (flags & SSH_FILEXFER_ATTR_PERMISSIONS) { - FAILRV(psbuf_get_4(pb, &tmpval)); - vap->va_mode = tmpval; - vap->va_type = puffs_mode2vt(vap->va_mode); - } - if (flags & SSH_FILEXFER_ATTR_ACCESSTIME) { - /* - * XXX: this is utterly wrong if we want to speak - * protocol version 3, but it seems like the - * "internet standard" for doing this - */ - FAILRV(psbuf_get_4(pb, &val)); - vap->va_atime.tv_sec = val; - FAILRV(psbuf_get_4(pb, &val)); - vap->va_mtime.tv_sec = val; - /* make ctime the same as mtime */ - vap->va_ctime.tv_sec = val; - - vap->va_atime.tv_nsec = 0; - vap->va_ctime.tv_nsec = 0; - vap->va_mtime.tv_nsec = 0; - } - - return 0; -} - -/* - * Buffer content helpers. Caller frees all data. - */ - -/* - * error mapping.. most are not expected for a file system, but - * should help with diagnosing a possible error - */ -static int emap[] = { - 0, /* OK */ - 0, /* EOF */ - ENOENT, /* NO_SUCH_FILE */ - EPERM, /* PERMISSION_DENIED */ - EIO, /* FAILURE */ - EBADMSG, /* BAD_MESSAGE */ - ENOTCONN, /* NO_CONNECTION */ - ECONNRESET, /* CONNECTION_LOST */ - EOPNOTSUPP, /* OP_UNSUPPORTED */ - EINVAL, /* INVALID_HANDLE */ - ENXIO, /* NO_SUCH_PATH */ - EEXIST, /* FILE_ALREADY_EXISTS */ - ENODEV /* WRITE_PROTECT */ -}; -#define NERRORS ((int)(sizeof(emap) / sizeof(emap[0]))) - -static int -sftperr_to_errno(int error) -{ - - if (!error) - return 0; - - if (error >= NERRORS || error < 0) - return EPROTO; - - return emap[error]; -} - -#define INVALRESPONSE EPROTO - -static int -expectcode(struct puffs_framebuf *pb, int value) -{ - uint32_t error; - uint8_t type; - - type = psbuf_get_type(pb); - if (type == value) - return 0; - - if (type != SSH_FXP_STATUS) - return INVALRESPONSE; - - FAILRV(psbuf_get_4(pb, &error)); - - return sftperr_to_errno(error); -} - -#define CHECKCODE(pb,val) \ -do { \ - int rv; \ - rv = expectcode(pb, val); \ - if (rv) \ - return rv; \ -} while (/*CONSTCOND*/0) - -int -psbuf_expect_status(struct puffs_framebuf *pb) -{ - uint32_t error; - - if (psbuf_get_type(pb) != SSH_FXP_STATUS) - return INVALRESPONSE; - - FAILRV(psbuf_get_4(pb, &error)); - - return sftperr_to_errno(error); -} - -int -psbuf_expect_handle(struct puffs_framebuf *pb, char **hand, uint32_t *handlen) -{ - - CHECKCODE(pb, SSH_FXP_HANDLE); - FAILRV(psbuf_get_str(pb, hand, handlen)); - - return 0; -} - -/* no memory allocation, direct copy */ -int -psbuf_do_data(struct puffs_framebuf *pb, uint8_t *data, uint32_t *dlen) -{ - void *win; - size_t bufoff, winlen; - uint32_t len, dataoff; - - if (psbuf_get_type(pb) != SSH_FXP_DATA) { - uint32_t val; - - if (psbuf_get_type(pb) != SSH_FXP_STATUS) - return INVALRESPONSE; - - if (psbuf_get_4(pb, &val) != 0) - return INVALRESPONSE; - - if (val != SSH_FX_EOF) - return sftperr_to_errno(val); - - *dlen = 0; - return 0; - } - if (psbuf_get_4(pb, &len) != 0) - return INVALRESPONSE; - - if (*dlen < len) - return EINVAL; - - *dlen = 0; - - dataoff = 0; - while (dataoff < len) { - winlen = len-dataoff; - bufoff = puffs_framebuf_telloff(pb); - if (puffs_framebuf_getwindow(pb, bufoff, - &win, &winlen) == -1) - return EINVAL; - if (winlen == 0) - break; - - memcpy(data + dataoff, win, winlen); - dataoff += winlen; - } - - *dlen = dataoff; - - return 0; -} - -int -psbuf_expect_name(struct puffs_framebuf *pb, uint32_t *count) -{ - - CHECKCODE(pb, SSH_FXP_NAME); - FAILRV(psbuf_get_4(pb, count)); - - return 0; -} - -int -psbuf_expect_attrs(struct puffs_framebuf *pb, struct vattr *vap) -{ - - CHECKCODE(pb, SSH_FXP_ATTRS); - FAILRV(psbuf_get_vattr(pb, vap)); - - return 0; -} - -/* - * More helpers: larger-scale put functions - */ - -void -psbuf_req_data(struct puffs_framebuf *pb, int type, uint32_t reqid, - const void *data, uint32_t dlen) -{ - - psbuf_put_1(pb, type); - psbuf_put_4(pb, reqid); - psbuf_put_data(pb, data, dlen); -} - -void -psbuf_req_str(struct puffs_framebuf *pb, int type, uint32_t reqid, - const char *str) -{ - - psbuf_req_data(pb, type, reqid, str, strlen(str)); -} diff --git a/usr.sbin/puffs/mount_psshfs/psshfs.c b/usr.sbin/puffs/mount_psshfs/psshfs.c deleted file mode 100644 index a09d52c137..0000000000 --- a/usr.sbin/puffs/mount_psshfs/psshfs.c +++ /dev/null @@ -1,442 +0,0 @@ -/* $NetBSD: psshfs.c,v 1.63 2011/05/19 15:07:16 riastradh Exp $ */ - -/* - * Copyright (c) 2006-2009 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. - */ - -/* - * psshfs: puffs sshfs - * - * psshfs implements sshfs functionality on top of puffs making it - * possible to mount a filesystme through the sftp service. - * - * psshfs can execute multiple operations in "parallel" by using the - * puffs_cc framework for continuations. - * - * Concurrency control is handled currently by vnode locking (this - * will change in the future). Context switch locations are easy to - * find by grepping for puffs_framebuf_enqueue_cc(). - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "psshfs.h" -#include "util_compat.h" - -static int pssh_connect(struct puffs_usermount *, int); -static void psshfs_loopfn(struct puffs_usermount *); -static void usage(void); -static void add_ssharg(char ***, int *, const char *); -static void psshfs_notify(struct puffs_usermount *, int, int); - -#define SSH_PATH "/usr/bin/ssh" - -unsigned int max_reads; -static int sighup; - -static void -add_ssharg(char ***sshargs, int *nargs, const char *arg) -{ - - *sshargs = realloc(*sshargs, (*nargs + 2) * sizeof(char*)); - if (!*sshargs) - err(1, "realloc"); - (*sshargs)[(*nargs)++] = estrdup(arg); - (*sshargs)[*nargs] = NULL; -} - -static void -usage(void) -{ - - fprintf(stderr, "usage: %s " - "[-ceprst] [-F configfile] [-O sshopt=value] [-o opts] " - "user@host:path mountpath\n", - getprogname()); - exit(1); -} - -static void -takehup(int sig) -{ - - sighup = 1; -} - -int -main(int argc, char *argv[]) -{ - struct psshfs_ctx pctx; - struct puffs_usermount *pu; - struct puffs_ops *pops; - struct psshfs_node *root = &pctx.psn_root; - struct puffs_node *pn_root; - puffs_framev_fdnotify_fn notfn; - struct vattr *rva; - char **sshargs; - char *userhost; - char *hostpath; - int mntflags, pflags, ch; - int detach; - int exportfs, refreshival, numconnections; - int nargs; - - setprogname(argv[0]); - puffs_unmountonsignal(SIGINT, true); - puffs_unmountonsignal(SIGTERM, true); - - if (argc < 3) - usage(); - - memset(&pctx, 0, sizeof(pctx)); - mntflags = pflags = exportfs = nargs = 0; - numconnections = 1; - detach = 1; - refreshival = DEFAULTREFRESH; - notfn = puffs_framev_unmountonclose; - sshargs = NULL; - add_ssharg(&sshargs, &nargs, SSH_PATH); - add_ssharg(&sshargs, &nargs, "-axs"); - add_ssharg(&sshargs, &nargs, "-oClearAllForwardings=yes"); - - while ((ch = getopt(argc, argv, "c:eF:g:o:O:pr:st:u:")) != -1) { - switch (ch) { - case 'c': - numconnections = atoi(optarg); - if (numconnections < 1 || numconnections > 2) { - fprintf(stderr, "%s: only 1 or 2 connections " - "permitted currently\n", getprogname()); - usage(); - /*NOTREACHED*/ - } - break; - case 'e': - exportfs = 1; - break; - case 'F': - add_ssharg(&sshargs, &nargs, "-F"); - add_ssharg(&sshargs, &nargs, optarg); - break; - case 'g': - pctx.domanglegid = 1; - pctx.manglegid = atoi(optarg); - if (pctx.manglegid == (gid_t)-1) - errx(1, "-1 not allowed for -g"); - pctx.mygid = getegid(); - break; - case 'O': - add_ssharg(&sshargs, &nargs, "-o"); - add_ssharg(&sshargs, &nargs, optarg); - break; - case 'o': - getmntopts(optarg, puffsmopts, &mntflags, &pflags); - break; - case 'p': - notfn = psshfs_notify; - break; - case 'r': - max_reads = atoi(optarg); - break; - case 's': - detach = 0; - break; - case 't': - refreshival = atoi(optarg); - if (refreshival < 0 && refreshival != -1) - errx(1, "invalid timeout %d", refreshival); - break; - case 'u': - pctx.domangleuid = 1; - pctx.mangleuid = atoi(optarg); - if (pctx.mangleuid == (uid_t)-1) - errx(1, "-1 not allowed for -u"); - pctx.myuid = geteuid(); - break; - default: - usage(); - /*NOTREACHED*/ - } - } - argc -= optind; - argv += optind; - - if (pflags & PUFFS_FLAG_OPDUMP) - detach = 0; - pflags |= PUFFS_FLAG_BUILDPATH; - pflags |= PUFFS_KFLAG_WTCACHE | PUFFS_KFLAG_IAONDEMAND; - - if (argc != 2) - usage(); - - PUFFSOP_INIT(pops); - - PUFFSOP_SET(pops, psshfs, fs, unmount); - PUFFSOP_SETFSNOP(pops, sync); /* XXX */ - PUFFSOP_SET(pops, psshfs, fs, statvfs); - PUFFSOP_SET(pops, psshfs, fs, nodetofh); - PUFFSOP_SET(pops, psshfs, fs, fhtonode); - - PUFFSOP_SET(pops, psshfs, node, lookup); - PUFFSOP_SET(pops, psshfs, node, create); - PUFFSOP_SET(pops, psshfs, node, open); - PUFFSOP_SET(pops, psshfs, node, inactive); - PUFFSOP_SET(pops, psshfs, node, readdir); - PUFFSOP_SET(pops, psshfs, node, getattr); - PUFFSOP_SET(pops, psshfs, node, setattr); - PUFFSOP_SET(pops, psshfs, node, mkdir); - PUFFSOP_SET(pops, psshfs, node, remove); - PUFFSOP_SET(pops, psshfs, node, readlink); - PUFFSOP_SET(pops, psshfs, node, rmdir); - PUFFSOP_SET(pops, psshfs, node, link); - PUFFSOP_SET(pops, psshfs, node, symlink); - PUFFSOP_SET(pops, psshfs, node, rename); - PUFFSOP_SET(pops, psshfs, node, read); - PUFFSOP_SET(pops, psshfs, node, write); - PUFFSOP_SET(pops, psshfs, node, reclaim); - - pu = puffs_init(pops, argv[0], "psshfs", &pctx, pflags); - if (pu == NULL) - err(1, "puffs_init"); - - pctx.mounttime = time(NULL); - pctx.refreshival = refreshival; - pctx.numconnections = numconnections; - - userhost = argv[0]; - hostpath = strchr(userhost, ':'); - if (hostpath) { - *hostpath++ = '\0'; - pctx.mountpath = hostpath; - } else - pctx.mountpath = "."; - - add_ssharg(&sshargs, &nargs, argv[0]); - add_ssharg(&sshargs, &nargs, "sftp"); - pctx.sshargs = sshargs; - - pctx.nextino = 2; - memset(root, 0, sizeof(struct psshfs_node)); - TAILQ_INIT(&root->pw); - pn_root = puffs_pn_new(pu, root); - if (pn_root == NULL) - return errno; - puffs_setroot(pu, pn_root); - - puffs_framev_init(pu, psbuf_read, psbuf_write, psbuf_cmp, NULL, notfn); - - signal(SIGHUP, takehup); - puffs_ml_setloopfn(pu, psshfs_loopfn); - if (pssh_connect(pu, PSSHFD_META) == -1) - err(1, "can't connect meta"); - if (puffs_framev_addfd(pu, pctx.sshfd, - PUFFS_FBIO_READ | PUFFS_FBIO_WRITE) == -1) - err(1, "framebuf addfd meta"); - if (numconnections == 2) { - if (pssh_connect(pu, PSSHFD_DATA) == -1) - err(1, "can't connect data"); - if (puffs_framev_addfd(pu, pctx.sshfd_data, - PUFFS_FBIO_READ | PUFFS_FBIO_WRITE) == -1) - err(1, "framebuf addfd data"); - } else { - pctx.sshfd_data = pctx.sshfd; - } - - if (exportfs) - puffs_setfhsize(pu, sizeof(struct psshfs_fid), - PUFFS_FHFLAG_NFSV2 | PUFFS_FHFLAG_NFSV3); - - rva = &pn_root->pn_va; - rva->va_fileid = pctx.nextino++; - - /* - * For root link count, just guess something ridiculously high. - * Guessing too high has no known adverse effects, but fts(3) - * doesn't like too low values. This guess will be replaced - * with the real value when readdir is first called for - * the root directory. - */ - rva->va_nlink = 8811; - - if (detach) - if (puffs_daemon(pu, 1, 1) == -1) - err(1, "puffs_daemon"); - - if (puffs_mount(pu, argv[1], mntflags, puffs_getroot(pu)) == -1) - err(1, "puffs_mount"); - if (puffs_setblockingmode(pu, PUFFSDEV_NONBLOCK) == -1) - err(1, "setblockingmode"); - - if (puffs_mainloop(pu) == -1) - err(1, "mainloop"); - puffs_exit(pu, 1); - - return 0; -} - -#define RETRY_MAX 100 - -void -psshfs_notify(struct puffs_usermount *pu, int fd, int what) -{ - struct psshfs_ctx *pctx = puffs_getspecific(pu); - int nretry, which, newfd, dummy; - - if (fd == pctx->sshfd) { - which = PSSHFD_META; - } else { - assert(fd == pctx->sshfd_data); - which = PSSHFD_DATA; - } - - if (puffs_getstate(pu) != PUFFS_STATE_RUNNING) - return; - - if (what != (PUFFS_FBIO_READ | PUFFS_FBIO_WRITE)) { - puffs_framev_removefd(pu, fd, ECONNRESET); - return; - } - close(fd); - - /* deal with zmobies, beware of half-eaten brain */ - while (waitpid(-1, &dummy, WNOHANG) > 0) - continue; - - for (nretry = 0;;nretry++) { - if ((newfd = pssh_connect(pu, which)) == -1) - goto retry2; - - if (puffs_framev_addfd(pu, newfd, - PUFFS_FBIO_READ | PUFFS_FBIO_WRITE) == -1) - goto retry1; - - break; - retry1: - fprintf(stderr, "reconnect failed... "); - close(newfd); - retry2: - if (nretry < RETRY_MAX) { - fprintf(stderr, "retry (%d left)\n", RETRY_MAX-nretry); - sleep(nretry); - } else { - fprintf(stderr, "retry count exceeded, going south\n"); - exit(1); /* XXXXXXX */ - } - } -} - -static int -pssh_connect(struct puffs_usermount *pu, int which) -{ - struct psshfs_ctx *pctx = puffs_getspecific(pu); - char * const *sshargs = pctx->sshargs; - int fds[2]; - pid_t pid; - int dnfd, x; - int *sshfd; - pid_t *sshpid; - - if (which == PSSHFD_META) { - sshfd = &pctx->sshfd; - sshpid = &pctx->sshpid; - } else { - assert(which == PSSHFD_DATA); - sshfd = &pctx->sshfd_data; - sshpid = &pctx->sshpid_data; - } - - if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == -1) - return -1; - - pid = fork(); - switch (pid) { - case -1: - return -1; - /*NOTREACHED*/ - case 0: /* child */ - if (dup2(fds[0], STDIN_FILENO) == -1) - err(1, "child dup2"); - if (dup2(fds[0], STDOUT_FILENO) == -1) - err(1, "child dup2"); - close(fds[0]); - close(fds[1]); - - dnfd = open(_PATH_DEVNULL, O_RDWR); - if (dnfd != -1) - dup2(dnfd, STDERR_FILENO); - - execvp(sshargs[0], sshargs); - /*NOTREACHED*/ - break; - default: - *sshpid = pid; - *sshfd = fds[1]; - close(fds[0]); - break; - } - - if (psshfs_handshake(pu, *sshfd) != 0) - errx(1, "handshake failed, server does not support sftp?"); - x = 1; - if (ioctl(*sshfd, FIONBIO, &x) == -1) - err(1, "nonblocking descriptor %d", which); - - return *sshfd; -} - -static void * -invalone(struct puffs_usermount *pu, struct puffs_node *pn, void *arg) -{ - struct psshfs_node *psn = pn->pn_data; - - psn->attrread = 0; - psn->dentread = 0; - psn->slread = 0; - - return NULL; -} - -static void -psshfs_loopfn(struct puffs_usermount *pu) -{ - - if (sighup) { - puffs_pn_nodewalk(pu, invalone, NULL); - sighup = 0; - } -} diff --git a/usr.sbin/puffs/mount_psshfs/psshfs.h b/usr.sbin/puffs/mount_psshfs/psshfs.h deleted file mode 100644 index b3f8cb2e40..0000000000 --- a/usr.sbin/puffs/mount_psshfs/psshfs.h +++ /dev/null @@ -1,248 +0,0 @@ -/* $NetBSD: psshfs.h,v 1.40 2010/04/01 02:34:09 pooka Exp $ */ - -/* - * Copyright (c) 2006-2009 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. - */ - -#ifndef PSSHFS_H_ -#define PSSHFS_H_ - -#include - -#include - -extern unsigned int max_reads; - -/* - * Later protocol versions would have some advantages (such as link count - * supported directly as a part of stat), but since proto version 3 seems - * to be the only widely available version, let's not try to jump through - * too many hoops to be compatible with all versions. - */ -#define SFTP_PROTOVERSION 3 - -/* extensions, held in psshfs_ctx extensions */ -#define SFTP_EXT_POSIX_RENAME 0x01 -#define SFTP_EXT_STATVFS 0x02 -#define SFTP_EXT_FSTATVFS 0x04 - -#define DEFAULTREFRESH 30 -#define REFRESHTIMEOUT(pctx, t) \ - (!(pctx)->refreshival || ((pctx->refreshival!=-1) && ((t)>pctx->refreshival))) - -PUFFSOP_PROTOS(psshfs); - -#define NEXTREQ(pctx) ((pctx->nextreq)++) -#define PSSHFSAUTOVAR(pu) \ - struct puffs_cc *pcc = puffs_cc_getcc(pu); \ - struct psshfs_ctx *pctx = puffs_getspecific(pu); \ - uint32_t reqid = NEXTREQ(pctx); \ - struct puffs_framebuf *pb = psbuf_makeout(); \ - int rv = 0 - -#define PSSHFSRETURN(rv) \ - puffs_framebuf_destroy(pb); \ - return (rv) - -#define GETRESPONSE(pb, fd) \ -do { \ - if (puffs_framev_enqueue_cc(pcc, fd, pb, 0) == -1) { \ - rv = errno; \ - goto out; \ - } \ -} while (/*CONSTCOND*/0) - -#define JUSTSEND(pb,fd) \ -do { \ - if (puffs_framev_enqueue_justsend(pu, fd, pb, 1, 0) == -1) { \ - rv = errno; \ - goto out; \ - } \ -} while (/*CONSTCOND*/0) - -#define SENDCB(pb, fd, f, a) \ -do { \ - if (puffs_framev_enqueue_cb(pu, fd, pb, f, a, 0) == -1) { \ - rv = errno; \ - goto out; \ - } \ -} while (/*CONSTCOND*/0) - -struct psshfs_dir { - int valid; - struct puffs_node *entry; - - char *entryname; - struct vattr va; - time_t attrread; -}; - -struct psshfs_fid { - time_t mounttime; - struct puffs_node *node; -}; - -struct psshfs_wait { - struct puffs_cc *pw_cc; - int pw_type; - TAILQ_ENTRY(psshfs_wait) pw_entries; -}; -#define PWTYPE_READDIR 1 -#define PWTYPE_READ1 2 -#define PWTYPE_READ2 3 -#define PWTYPE_WRITE 4 - -struct psshfs_node { - struct puffs_node *parent; - - struct psshfs_dir *dir; /* only valid if we're of type VDIR */ - - size_t denttot; - size_t dentnext; - time_t dentread; - int childcount; - - int stat; - unsigned readcount; - - time_t attrread; - char *symlink; - time_t slread; - - char *fhand_r; - char *fhand_w; - uint32_t fhand_r_len; - uint32_t fhand_w_len; - struct puffs_framebuf *lazyopen_r; - struct puffs_framebuf *lazyopen_w; - int lazyopen_err_r, lazyopen_err_w; - - TAILQ_HEAD(, psshfs_wait) pw; -}; -#define PSN_RECLAIMED 0x01 -#define PSN_HASFH 0x02 -#define PSN_READDIR 0x04 -#define PSN_DOLAZY_R 0x08 -#define PSN_DOLAZY_W 0x10 -#define PSN_LAZYWAIT_R 0x20 -#define PSN_LAZYWAIT_W 0x40 -#define PSN_HANDLECLOSE 0x80 - -#define HANDLE_READ 0x1 -#define HANDLE_WRITE 0x2 - -struct psshfs_ctx { - int numconnections; - int sshfd; - int sshfd_data; - pid_t sshpid; - pid_t sshpid_data; - - const char *mountpath; - char **sshargs; - - int protover; - int extensions; - - uint32_t nextreq; - - struct puffs_framebuf *curpb; - - struct psshfs_node psn_root; - ino_t nextino; - - int canexport; - time_t mounttime; - - int refreshival; - - int domangleuid, domanglegid; - uid_t mangleuid, myuid; - gid_t manglegid, mygid; -}; -#define PSSHFD_META 0 -#define PSSHFD_DATA 1 - -int psshfs_handshake(struct puffs_usermount *, int); - -int psbuf_read(struct puffs_usermount *, struct puffs_framebuf *,int,int*); -int psbuf_write(struct puffs_usermount *, struct puffs_framebuf *,int,int*); -int psbuf_cmp(struct puffs_usermount *, - struct puffs_framebuf *, struct puffs_framebuf *, int *); - -struct puffs_framebuf *psbuf_makeout(void); -void psbuf_recycleout(struct puffs_framebuf *); - -void psbuf_put_1(struct puffs_framebuf *, uint8_t); -void psbuf_put_2(struct puffs_framebuf *, uint16_t); -void psbuf_put_4(struct puffs_framebuf *, uint32_t); -void psbuf_put_8(struct puffs_framebuf *, uint64_t); -void psbuf_put_str(struct puffs_framebuf *, const char *); -void psbuf_put_data(struct puffs_framebuf *, const void *, uint32_t); -void psbuf_put_vattr(struct puffs_framebuf *, const struct vattr *, - const struct psshfs_ctx *); - -uint8_t psbuf_get_type(struct puffs_framebuf *); -uint32_t psbuf_get_len(struct puffs_framebuf *); -uint32_t psbuf_get_reqid(struct puffs_framebuf *); - -int psbuf_get_1(struct puffs_framebuf *, uint8_t *); -int psbuf_get_2(struct puffs_framebuf *, uint16_t *); -int psbuf_get_4(struct puffs_framebuf *, uint32_t *); -int psbuf_get_8(struct puffs_framebuf *, uint64_t *); -int psbuf_get_str(struct puffs_framebuf *, char **, uint32_t *); -int psbuf_get_vattr(struct puffs_framebuf *, struct vattr *); - -int psbuf_expect_status(struct puffs_framebuf *); -int psbuf_expect_handle(struct puffs_framebuf *, char **, uint32_t *); -int psbuf_expect_name(struct puffs_framebuf *, uint32_t *); -int psbuf_expect_attrs(struct puffs_framebuf *, struct vattr *); - -int psbuf_do_data(struct puffs_framebuf *, uint8_t *, uint32_t *); - -void psbuf_req_data(struct puffs_framebuf *, int, uint32_t, - const void *, uint32_t); -void psbuf_req_str(struct puffs_framebuf *, int, uint32_t, const char *); - -int sftp_readdir(struct puffs_usermount *, struct psshfs_ctx *, - struct puffs_node *); - -struct psshfs_dir *lookup(struct psshfs_dir *, size_t, const char *); -struct puffs_node *makenode(struct puffs_usermount *, struct puffs_node *, - const struct psshfs_dir *, const struct vattr *); -struct puffs_node *allocnode(struct puffs_usermount *, struct puffs_node *, - const char *, const struct vattr *); -struct psshfs_dir *direnter(struct puffs_node *, const char *); -void nukenode(struct puffs_node *, const char *, int); -void doreclaim(struct puffs_node *); -int getpathattr(struct puffs_usermount *, const char *, struct vattr *); -int getnodeattr(struct puffs_usermount *, struct puffs_node *, const char *); - -void closehandles(struct puffs_usermount *, struct psshfs_node *, int); -void lazyopen_rresp(struct puffs_usermount *, struct puffs_framebuf *, - void *, int); -void lazyopen_wresp(struct puffs_usermount *, struct puffs_framebuf *, - void *, int); - -#endif /* PSSHFS_H_ */ diff --git a/usr.sbin/puffs/mount_psshfs/sftp_proto.h b/usr.sbin/puffs/mount_psshfs/sftp_proto.h deleted file mode 100644 index eeaca14e99..0000000000 --- a/usr.sbin/puffs/mount_psshfs/sftp_proto.h +++ /dev/null @@ -1,122 +0,0 @@ -/* $NetBSD: sftp_proto.h,v 1.2 2007/06/06 01:55:03 pooka Exp $ */ - -/* - * Copyright (c) 2006 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. - */ - -/* - * copypaste from draft-ietf-secsh-filexfer-03.txt - * - * XXX: we only implement protocol version 03. We should *definitely* - * support a later version, since it maps to the vnode interface much - * better. the problem is that most sftp servers only implement v3 - * and I don't currently have the energy to deal with compat-fuddling - * in the code. - */ - -#ifndef PSSHFS_SFTPPROTO_H_ -#define PSSHFS_SFTPPROTO_H_ - -/* 3 General Packet Format */ - -#define SSH_FXP_INIT 1 -#define SSH_FXP_VERSION 2 -#define SSH_FXP_OPEN 3 -#define SSH_FXP_CLOSE 4 -#define SSH_FXP_READ 5 -#define SSH_FXP_WRITE 6 -#define SSH_FXP_LSTAT 7 -#define SSH_FXP_FSTAT 8 -#define SSH_FXP_SETSTAT 9 -#define SSH_FXP_FSETSTAT 10 -#define SSH_FXP_OPENDIR 11 -#define SSH_FXP_READDIR 12 -#define SSH_FXP_REMOVE 13 -#define SSH_FXP_MKDIR 14 -#define SSH_FXP_RMDIR 15 -#define SSH_FXP_REALPATH 16 -#define SSH_FXP_STAT 17 -#define SSH_FXP_RENAME 18 -#define SSH_FXP_READLINK 19 -#define SSH_FXP_SYMLINK 20 - -#define SSH_FXP_STATUS 101 -#define SSH_FXP_HANDLE 102 -#define SSH_FXP_DATA 103 -#define SSH_FXP_NAME 104 -#define SSH_FXP_ATTRS 105 - -#define SSH_FXP_EXTENDED 200 -#define SSH_FXP_EXTENDED_REPLY 201 - -/* 5.1 Flags */ - -/* XXX: UIDGID is obsoleted *AND NOT VALID* for version 3 of the protocol */ -#define SSH_FILEXFER_ATTR_SIZE 0x00000001 -#define SSH_FILEXFER_ATTR_UIDGID 0x00000002 -#define SSH_FILEXFER_ATTR_PERMISSIONS 0x00000004 -#define SSH_FILEXFER_ATTR_ACCESSTIME 0x00000008 -#define SSH_FILEXFER_ATTR_CREATETIME 0x00000010 -#define SSH_FILEXFER_ATTR_MODIFYTIME 0x00000020 -#define SSH_FILEXFER_ATTR_ACL 0x00000040 -#define SSH_FILEXFER_ATTR_OWNERGROUP 0x00000080 -#define SSH_FILEXFER_ATTR_EXTENDED 0x80000000 - -/* 5.2 Type */ - -#define SSH_FILEXFER_TYPE_REGULAR 1 -#define SSH_FILEXFER_TYPE_DIRECTORY 2 -#define SSH_FILEXFER_TYPE_SYMLINK 3 -#define SSH_FILEXFER_TYPE_SPECIAL 4 -#define SSH_FILEXFER_TYPE_UNKNOWN 5 - - -/* 6.3 Opening, Creating, and Closing Files */ - -#define SSH_FXF_READ 0x00000001 -#define SSH_FXF_WRITE 0x00000002 -#define SSH_FXF_APPEND 0x00000004 -#define SSH_FXF_CREAT 0x00000008 -#define SSH_FXF_TRUNC 0x00000010 -#define SSH_FXF_EXCL 0x00000020 -#define SSH_FXF_TEXT 0x00000040 - - -/* 7. Responses from the Server to the Client */ - -#define SSH_FX_OK 0 -#define SSH_FX_EOF 1 -#define SSH_FX_NO_SUCH_FILE 2 -#define SSH_FX_PERMISSION_DENIED 3 -#define SSH_FX_FAILURE 4 -#define SSH_FX_BAD_MESSAGE 5 -#define SSH_FX_NO_CONNECTION 6 -#define SSH_FX_CONNECTION_LOST 7 -#define SSH_FX_OP_UNSUPPORTED 8 -#define SSH_FX_INVALID_HANDLE 9 -#define SSH_FX_NO_SUCH_PATH 10 -#define SSH_FX_FILE_ALREADY_EXISTS 11 -#define SSH_FX_WRITE_PROTECT 12 - -#endif /* PSSHFS_SFTPPROTO_H_ */ diff --git a/usr.sbin/puffs/mount_psshfs/subr.c b/usr.sbin/puffs/mount_psshfs/subr.c deleted file mode 100644 index 99f41115ff..0000000000 --- a/usr.sbin/puffs/mount_psshfs/subr.c +++ /dev/null @@ -1,545 +0,0 @@ -/* $NetBSD: subr.c,v 1.50 2010/04/01 02:34:09 pooka Exp $ */ - -/* - * Copyright (c) 2006 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 -#include -#include -#include -#include -#include - -#include "psshfs.h" -#include "sftp_proto.h" -#include "util_compat.h" - -static void -freedircache(struct psshfs_dir *base, size_t count) -{ - size_t i; - - for (i = 0; i < count; i++) { - free(base[i].entryname); - base[i].entryname = NULL; - } - - free(base); -} - -#define ENTRYCHUNK 16 -static void -allocdirs(struct psshfs_node *psn) -{ - size_t oldtot = psn->denttot; - - psn->denttot += ENTRYCHUNK; - psn->dir = erealloc(psn->dir, - psn->denttot * sizeof(struct psshfs_dir)); - memset(psn->dir + oldtot, 0, ENTRYCHUNK * sizeof(struct psshfs_dir)); -} - -static void -setpnva(struct puffs_usermount *pu, struct puffs_node *pn, - const struct vattr *vap) -{ - struct psshfs_ctx *pctx = puffs_getspecific(pu); - struct psshfs_node *psn = pn->pn_data; - struct vattr modva; - - /* - * Check if the file was modified from below us. - * If so, invalidate page cache. This is the only - * sensible place we can do this in. - */ - if (pn->pn_va.va_mtime.tv_sec != PUFFS_VNOVAL) - if (pn->pn_va.va_mtime.tv_sec != vap->va_mtime.tv_sec - && pn->pn_va.va_type == VREG) - puffs_inval_pagecache_node(pu, pn); - - modva = *vap; - if (pctx->domangleuid && modva.va_uid == pctx->mangleuid) - modva.va_uid = pctx->myuid; - if (pctx->domanglegid && modva.va_gid == pctx->manglegid) - modva.va_gid = pctx->mygid; - - puffs_setvattr(&pn->pn_va, &modva); - psn->attrread = time(NULL); -} - -struct psshfs_dir * -lookup(struct psshfs_dir *bdir, size_t ndir, const char *name) -{ - struct psshfs_dir *test; - size_t i; - - for (i = 0; i < ndir; i++) { - test = &bdir[i]; - if (test->valid != 1) - continue; - if (strcmp(test->entryname, name) == 0) - return test; - } - - return NULL; -} - -static struct psshfs_dir * -lookup_by_entry(struct psshfs_dir *bdir, size_t ndir, struct puffs_node *entry) -{ - struct psshfs_dir *test; - size_t i; - - for (i = 0; i < ndir; i++) { - test = &bdir[i]; - if (test->valid != 1) - continue; - if (test->entry == entry) - return test; - } - - return NULL; -} - - -void -closehandles(struct puffs_usermount *pu, struct psshfs_node *psn, int which) -{ - struct psshfs_ctx *pctx = puffs_getspecific(pu); - struct puffs_framebuf *pb1, *pb2; - uint32_t reqid; - - if (psn->fhand_r && (which & HANDLE_READ)) { - assert(psn->lazyopen_r == NULL); - - pb1 = psbuf_makeout(); - reqid = NEXTREQ(pctx); - psbuf_req_data(pb1, SSH_FXP_CLOSE, reqid, - psn->fhand_r, psn->fhand_r_len); - puffs_framev_enqueue_justsend(pu, pctx->sshfd_data, pb1, 1, 0); - free(psn->fhand_r); - psn->fhand_r = NULL; - } - - if (psn->fhand_w && (which & HANDLE_WRITE)) { - assert(psn->lazyopen_w == NULL); - - pb2 = psbuf_makeout(); - reqid = NEXTREQ(pctx); - psbuf_req_data(pb2, SSH_FXP_CLOSE, reqid, - psn->fhand_w, psn->fhand_w_len); - puffs_framev_enqueue_justsend(pu, pctx->sshfd_data, pb2, 1, 0); - free(psn->fhand_w); - psn->fhand_w = NULL; - } - - psn->stat |= PSN_HANDLECLOSE; -} - -void -lazyopen_rresp(struct puffs_usermount *pu, struct puffs_framebuf *pb, - void *arg, int error) -{ - struct psshfs_node *psn = arg; - - /* XXX: this is not enough */ - if (psn->stat & PSN_RECLAIMED) { - error = ENOENT; - goto moreout; - } - if (error) - goto out; - - error = psbuf_expect_handle(pb, &psn->fhand_r, &psn->fhand_r_len); - - out: - psn->lazyopen_err_r = error; - psn->lazyopen_r = NULL; - if (error) - psn->stat &= ~PSN_DOLAZY_R; - if (psn->stat & PSN_HANDLECLOSE && (psn->stat & PSN_LAZYWAIT_R) == 0) - closehandles(pu, psn, HANDLE_READ); - moreout: - puffs_framebuf_destroy(pb); -} - -void -lazyopen_wresp(struct puffs_usermount *pu, struct puffs_framebuf *pb, - void *arg, int error) -{ - struct psshfs_node *psn = arg; - - /* XXX: this is not enough */ - if (psn->stat & PSN_RECLAIMED) { - error = ENOENT; - goto moreout; - } - if (error) - goto out; - - error = psbuf_expect_handle(pb, &psn->fhand_w, &psn->fhand_w_len); - - out: - psn->lazyopen_err_w = error; - psn->lazyopen_w = NULL; - if (error) - psn->stat &= ~PSN_DOLAZY_W; - if (psn->stat & PSN_HANDLECLOSE && (psn->stat & PSN_LAZYWAIT_W) == 0) - closehandles(pu, psn, HANDLE_WRITE); - moreout: - puffs_framebuf_destroy(pb); -} - -struct readdirattr { - struct psshfs_node *psn; - int idx; - char entryname[MAXPATHLEN+1]; -}; - -int -getpathattr(struct puffs_usermount *pu, const char *path, struct vattr *vap) -{ - PSSHFSAUTOVAR(pu); - - psbuf_req_str(pb, SSH_FXP_LSTAT, reqid, path); - GETRESPONSE(pb, pctx->sshfd); - - rv = psbuf_expect_attrs(pb, vap); - - out: - PSSHFSRETURN(rv); -} - -int -getnodeattr(struct puffs_usermount *pu, struct puffs_node *pn, const char *path) -{ - struct psshfs_ctx *pctx = puffs_getspecific(pu); - struct psshfs_node *psn = pn->pn_data; - struct vattr va; - int rv; - - if (!psn->attrread || REFRESHTIMEOUT(pctx, time(NULL)-psn->attrread)) { - rv = getpathattr(pu, path ? path : PNPATH(pn), &va); - if (rv) - return rv; - - setpnva(pu, pn, &va); - } - - return 0; -} - -int -sftp_readdir(struct puffs_usermount *pu, struct psshfs_ctx *pctx, - struct puffs_node *pn) -{ - struct puffs_cc *pcc = puffs_cc_getcc(pu); - struct psshfs_node *psn = pn->pn_data; - struct psshfs_dir *olddir, *testd; - struct puffs_framebuf *pb; - uint32_t reqid = NEXTREQ(pctx); - uint32_t count, dhandlen; - int tmpval; - char *dhand = NULL; - size_t nent; - char *longname = NULL; - size_t idx; - int rv; - - assert(pn->pn_va.va_type == VDIR); - idx = 0; - olddir = psn->dir; - nent = psn->dentnext; - - if (psn->dir && psn->dentread - && !REFRESHTIMEOUT(pctx, time(NULL) - psn->dentread)) - return 0; - - if (psn->dentread) { - if ((rv = puffs_inval_namecache_dir(pu, pn))) - warn("readdir: dcache inval fail %p", pn); - } - - pb = psbuf_makeout(); - psbuf_req_str(pb, SSH_FXP_OPENDIR, reqid, PNPATH(pn)); - if (puffs_framev_enqueue_cc(pcc, pctx->sshfd, pb, 0) == -1) { - rv = errno; - goto wayout; - } - rv = psbuf_expect_handle(pb, &dhand, &dhandlen); - if (rv) - goto wayout; - - /* - * Well, the following is O(n^2), so feel free to improve if it - * gets too taxing on your system. - */ - - /* - * note: for the "getattr in batch" to work, this must be before - * the attribute-getting. Otherwise times for first entries in - * large directories might expire before the directory itself and - * result in one-by-one attribute fetching. - */ - psn->dentread = time(NULL); - - psn->dentnext = 0; - psn->denttot = 0; - psn->dir = NULL; - - for (;;) { - reqid = NEXTREQ(pctx); - psbuf_recycleout(pb); - psbuf_req_data(pb, SSH_FXP_READDIR, reqid, dhand, dhandlen); - GETRESPONSE(pb, pctx->sshfd); - - /* check for EOF */ - if (psbuf_get_type(pb) == SSH_FXP_STATUS) { - rv = psbuf_expect_status(pb); - goto out; - } - rv = psbuf_expect_name(pb, &count); - if (rv) - goto out; - - for (; count--; idx++) { - if (idx == psn->denttot) - allocdirs(psn); - if ((rv = psbuf_get_str(pb, - &psn->dir[idx].entryname, NULL))) - goto out; - if ((rv = psbuf_get_str(pb, &longname, NULL)) != 0) - goto out; - if ((rv = psbuf_get_vattr(pb, &psn->dir[idx].va)) != 0) - goto out; - if (sscanf(longname, "%*s%d", - &tmpval) != 1) { - rv = EPROTO; - goto out; - } - psn->dir[idx].va.va_nlink = tmpval; - free(longname); - longname = NULL; - - /* - * In case of DOT, copy the attributes (mostly - * because we want the link count for the root dir). - */ - if (strcmp(psn->dir[idx].entryname, ".") == 0) { - setpnva(pu, pn, &psn->dir[idx].va); - } - - /* - * Check if we already have a psshfs_dir for the - * name we are processing. If so, use the old one. - * If not, create a new one - */ - testd = lookup(olddir, nent, psn->dir[idx].entryname); - if (testd) { - psn->dir[idx].entry = testd->entry; - /* - * Has entry. Update attributes to what - * we just got from the server. - */ - if (testd->entry) { - setpnva(pu, testd->entry, - &psn->dir[idx].va); - psn->dir[idx].va.va_fileid - = testd->entry->pn_va.va_fileid; - - /* - * No entry. This can happen in two cases: - * 1) the file was created "behind our back" - * on the server - * 2) we do two readdirs before we instantiate - * the node (or run with -t 0). - * - * Cache attributes from the server in - * case we want to instantiate this node - * soon. Also preserve the old inode number - * which was given when the dirent was created. - */ - } else { - psn->dir[idx].va.va_fileid - = testd->va.va_fileid; - testd->va = psn->dir[idx].va; - } - - /* No previous entry? Initialize this one. */ - } else { - psn->dir[idx].entry = NULL; - psn->dir[idx].va.va_fileid = pctx->nextino++; - } - psn->dir[idx].attrread = psn->dentread; - psn->dir[idx].valid = 1; - } - } - - out: - /* XXX: rv */ - psn->dentnext = idx; - freedircache(olddir, nent); - - reqid = NEXTREQ(pctx); - psbuf_recycleout(pb); - psbuf_req_data(pb, SSH_FXP_CLOSE, reqid, dhand, dhandlen); - puffs_framev_enqueue_justsend(pu, pctx->sshfd, pb, 1, 0); - free(dhand); - free(longname); - - return rv; - - wayout: - free(dhand); - PSSHFSRETURN(rv); -} - -struct puffs_node * -makenode(struct puffs_usermount *pu, struct puffs_node *parent, - const struct psshfs_dir *pd, const struct vattr *vap) -{ - struct psshfs_node *psn_parent = parent->pn_data; - struct psshfs_node *psn; - struct puffs_node *pn; - - psn = emalloc(sizeof(struct psshfs_node)); - memset(psn, 0, sizeof(struct psshfs_node)); - - pn = puffs_pn_new(pu, psn); - if (!pn) { - free(psn); - return NULL; - } - setpnva(pu, pn, &pd->va); - setpnva(pu, pn, vap); - psn->attrread = pd->attrread; - - psn->parent = parent; - psn_parent->childcount++; - - TAILQ_INIT(&psn->pw); - - return pn; -} - -struct puffs_node * -allocnode(struct puffs_usermount *pu, struct puffs_node *parent, - const char *entryname, const struct vattr *vap) -{ - struct psshfs_ctx *pctx = puffs_getspecific(pu); - struct psshfs_dir *pd; - struct puffs_node *pn; - - pd = direnter(parent, entryname); - - pd->va.va_fileid = pctx->nextino++; - if (vap->va_type == VDIR) { - pd->va.va_nlink = 2; - parent->pn_va.va_nlink++; - } else { - pd->va.va_nlink = 1; - } - - pn = makenode(pu, parent, pd, vap); - if (pn) { - pd->va.va_fileid = pn->pn_va.va_fileid; - pd->entry = pn; - } - - return pn; -} - -struct psshfs_dir * -direnter(struct puffs_node *parent, const char *entryname) -{ - struct psshfs_node *psn_parent = parent->pn_data; - struct psshfs_dir *pd; - int i; - - /* create directory entry */ - if (psn_parent->denttot == psn_parent->dentnext) - allocdirs(psn_parent); - - i = psn_parent->dentnext; - pd = &psn_parent->dir[i]; - pd->entryname = estrdup(entryname); - pd->valid = 1; - pd->attrread = 0; - puffs_vattr_null(&pd->va); - psn_parent->dentnext++; - - return pd; -} - -void -doreclaim(struct puffs_node *pn) -{ - struct psshfs_node *psn = pn->pn_data; - struct psshfs_node *psn_parent; - struct psshfs_dir *dent; - - psn_parent = psn->parent->pn_data; - psn_parent->childcount--; - - /* - * Null out entry from directory. Do not treat a missing entry - * as an invariant error, since the node might be removed from - * under us, and we might do a readdir before the reclaim resulting - * in no directory entry in the parent directory. - */ - dent = lookup_by_entry(psn_parent->dir, psn_parent->dentnext, pn); - if (dent) - dent->entry = NULL; - - if (pn->pn_va.va_type == VDIR) { - freedircache(psn->dir, psn->dentnext); - psn->denttot = psn->dentnext = 0; - } - if (psn->symlink) - free(psn->symlink); - - puffs_pn_put(pn); -} - -void -nukenode(struct puffs_node *node, const char *entryname, int reclaim) -{ - struct psshfs_node *psn, *psn_parent; - struct psshfs_dir *pd; - - psn = node->pn_data; - psn_parent = psn->parent->pn_data; - pd = lookup(psn_parent->dir, psn_parent->dentnext, entryname); - assert(pd != NULL); - pd->valid = 0; - free(pd->entryname); - pd->entryname = NULL; - - if (node->pn_va.va_type == VDIR) - psn->parent->pn_va.va_nlink--; - - if (reclaim) - doreclaim(node); -} diff --git a/usr.sbin/puffs/mount_psshfs/util_compat.h b/usr.sbin/puffs/mount_psshfs/util_compat.h deleted file mode 100644 index a551cbd4e4..0000000000 --- a/usr.sbin/puffs/mount_psshfs/util_compat.h +++ /dev/null @@ -1,61 +0,0 @@ -/*- - * Copyright (c) 2006 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Christos Zoulas. - * - * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 -#include -#include -#include -#include - -static inline char * -estrdup(const char *s) -{ - char *d = strdup(s); - if (d == NULL) - err(1, "Cannot copy string"); - return d; -} - -static inline void * -emalloc(size_t n) -{ - void *p = malloc(n); - if (p == NULL) - err(1, "Cannot allocate %zu bytes", n); - return p; -} - -static inline void * -erealloc(void *p, size_t n) -{ - void *q = realloc(p, n); - if (q == NULL) - err(1, "Cannot re-allocate %zu bytes", n); - return q; -}