summaryrefslogtreecommitdiff
path: root/sys/nnpfs
diff options
context:
space:
mode:
authorJanne Johansson <jj@cvs.openbsd.org>2009-06-03 14:45:57 +0000
committerJanne Johansson <jj@cvs.openbsd.org>2009-06-03 14:45:57 +0000
commitea9bbf428f51194a52c45ac274c35dba174a741c (patch)
tree301aa894fd92a097d769b8cac575c8a0fce07329 /sys/nnpfs
parent0c52879fa54117b2bd312fe5fff17f310dbdb7eb (diff)
Arla client rename from xfs to nnpfs for later upgrades. Tested on various arches. ok todd@ beck@
Diffstat (limited to 'sys/nnpfs')
-rw-r--r--sys/nnpfs/afssysdefs.h103
-rw-r--r--sys/nnpfs/nnnpfs.h1
-rw-r--r--sys/nnpfs/nnpfs_attr.h126
-rw-r--r--sys/nnpfs/nnpfs_common-bsd.c112
-rw-r--r--sys/nnpfs/nnpfs_common.h79
-rw-r--r--sys/nnpfs/nnpfs_config.h1665
-rw-r--r--sys/nnpfs/nnpfs_deb.c55
-rw-r--r--sys/nnpfs/nnpfs_deb.h60
-rw-r--r--sys/nnpfs/nnpfs_debug.h61
-rw-r--r--sys/nnpfs/nnpfs_dev-bsd.c154
-rw-r--r--sys/nnpfs/nnpfs_dev-common.c736
-rw-r--r--sys/nnpfs/nnpfs_dev.h162
-rw-r--r--sys/nnpfs/nnpfs_extern.h55
-rw-r--r--sys/nnpfs/nnpfs_fs.h99
-rw-r--r--sys/nnpfs/nnpfs_global.h8
-rw-r--r--sys/nnpfs/nnpfs_locl.h424
-rw-r--r--sys/nnpfs/nnpfs_message.c525
-rw-r--r--sys/nnpfs/nnpfs_message.h491
-rw-r--r--sys/nnpfs/nnpfs_msg_locl.h87
-rw-r--r--sys/nnpfs/nnpfs_node-bsd.c801
-rw-r--r--sys/nnpfs/nnpfs_node.c140
-rw-r--r--sys/nnpfs/nnpfs_node.h161
-rw-r--r--sys/nnpfs/nnpfs_pioctl.h204
-rw-r--r--sys/nnpfs/nnpfs_queue.h91
-rw-r--r--sys/nnpfs/nnpfs_syscalls-common.c672
-rw-r--r--sys/nnpfs/nnpfs_syscalls-dummy.c10
-rw-r--r--sys/nnpfs/nnpfs_syscalls.h92
-rw-r--r--sys/nnpfs/nnpfs_vfsops-bsd.c528
-rw-r--r--sys/nnpfs/nnpfs_vfsops-bsd.h103
-rw-r--r--sys/nnpfs/nnpfs_vfsops-common.c286
-rw-r--r--sys/nnpfs/nnpfs_vfsops-openbsd.c190
-rw-r--r--sys/nnpfs/nnpfs_vfsops.h75
-rw-r--r--sys/nnpfs/nnpfs_vnodeops-bsd.c1537
-rw-r--r--sys/nnpfs/nnpfs_vnodeops-common.c1146
-rw-r--r--sys/nnpfs/nnpfs_vnodeops.h220
-rw-r--r--sys/nnpfs/nnpfs_vopdefs.h72
36 files changed, 11331 insertions, 0 deletions
diff --git a/sys/nnpfs/afssysdefs.h b/sys/nnpfs/afssysdefs.h
new file mode 100644
index 00000000000..9f109af40b3
--- /dev/null
+++ b/sys/nnpfs/afssysdefs.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $Id: afssysdefs.h,v 1.1 2009/06/03 14:45:54 jj Exp $ */
+
+/*
+ * This section is for machines using single entry point AFS syscalls!
+ * and/or
+ * This section is for machines using multiple entry point AFS syscalls!
+ *
+ * SunOS 4 is an example of single entry point and sgi of multiple
+ * entry point syscalls.
+ */
+
+#if SunOS == 40
+#define AFS_SYSCALL 31
+#endif
+
+#if SunOS >= 50 && SunOS < 57
+#define AFS_SYSCALL 105
+#endif
+
+#if SunOS >= 57
+#define AFS_SYSCALL 73
+#endif
+
+#if SunOS >= 58
+#define AFS_SYSCALL 65
+#endif
+
+#if defined(__hpux)
+#define AFS_SYSCALL 50
+#define AFS_SYSCALL2 49
+#define AFS_SYSCALL3 48
+#endif
+
+#if defined(_AIX)
+/* _AIX is too weird */
+#endif
+
+#if defined(__sgi)
+#define AFS_PIOCTL (64+1000)
+#define AFS_SETPAG (65+1000)
+#endif
+
+#if defined(__osf__)
+#define AFS_SYSCALL 232
+#define AFS_SYSCALL2 258
+#endif
+
+#if defined(__ultrix)
+#define AFS_SYSCALL 31
+#endif
+
+#if defined(__NetBSD__)
+#define AFS_SYSCALL 210
+#endif
+
+#if defined(__FreeBSD__)
+#define AFS_SYSCALL 339
+#endif
+
+#if defined(__OpenBSD__)
+#define AFS_SYSCALL 208
+#endif
+
+#ifdef __APPLE__ /* MacOS X */
+#define AFS_SYSCALL 230
+#endif
+
+#ifdef SYS_afs_syscall
+#define AFS_SYSCALL3 SYS_afs_syscall
+#endif
diff --git a/sys/nnpfs/nnnpfs.h b/sys/nnpfs/nnnpfs.h
new file mode 100644
index 00000000000..4a30a7ca340
--- /dev/null
+++ b/sys/nnpfs/nnnpfs.h
@@ -0,0 +1 @@
+#define NNNPFS 2 /* maximum number of filesystems on a single device */
diff --git a/sys/nnpfs/nnpfs_attr.h b/sys/nnpfs/nnpfs_attr.h
new file mode 100644
index 00000000000..c5734ee7bf3
--- /dev/null
+++ b/sys/nnpfs/nnpfs_attr.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 1998, 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $arla: nnpfs_attr.h,v 1.12 2002/09/07 10:46:15 lha Exp $ */
+
+#ifndef _NNPFS_ATTR_H
+#define _NNPFS_ATTR_H
+
+#define XA_V_NONE 0
+#define XA_V_MODE (1 << 0)
+#define XA_V_NLINK (1 << 1)
+#define XA_V_SIZE (1 << 2)
+#define XA_V_UID (1 << 3)
+#define XA_V_GID (1 << 4)
+#define XA_V_ATIME (1 << 5)
+#define XA_V_MTIME (1 << 6)
+#define XA_V_CTIME (1 << 7)
+#define XA_V_FILEID (1 << 8)
+#define XA_V_TYPE (1 << 9)
+
+#define NNPFS_FILE_NON 1
+#define NNPFS_FILE_REG 2
+#define NNPFS_FILE_DIR 3
+#define NNPFS_FILE_BLK 4
+#define NNPFS_FILE_CHR 5
+#define NNPFS_FILE_LNK 6
+#define NNPFS_FILE_SOCK 7
+#define NNPFS_FILE_FIFO 8
+#define NNPFS_FILE_BAD 9
+
+#define XA_CLEAR(xa_p) \
+ ((xa_p)->valid = XA_V_NONE)
+#define XA_SET_MODE(xa_p, value) \
+ (((xa_p)->valid) |= XA_V_MODE, ((xa_p)->xa_mode) = value)
+#define XA_SET_NLINK(xa_p, value) \
+ (((xa_p)->valid) |= XA_V_NLINK, ((xa_p)->xa_nlink) = value)
+#define XA_SET_SIZE(xa_p, value) \
+ (((xa_p)->valid) |= XA_V_SIZE, ((xa_p)->xa_size) = value)
+#define XA_SET_UID(xa_p, value) \
+ (((xa_p)->valid) |= XA_V_UID, ((xa_p)->xa_uid) = value)
+#define XA_SET_GID(xa_p, value) \
+ (((xa_p)->valid) |= XA_V_GID, ((xa_p)->xa_gid) = value)
+#define XA_SET_ATIME(xa_p, value) \
+ (((xa_p)->valid) |= XA_V_ATIME, ((xa_p)->xa_atime) = value)
+#define XA_SET_MTIME(xa_p, value) \
+ (((xa_p)->valid) |= XA_V_MTIME, ((xa_p)->xa_mtime) = value)
+#define XA_SET_CTIME(xa_p, value) \
+ (((xa_p)->valid) |= XA_V_CTIME, ((xa_p)->xa_ctime) = value)
+#define XA_SET_FILEID(xa_p, value) \
+ (((xa_p)->valid) |= XA_V_FILEID, ((xa_p)->xa_fileid) = value)
+#define XA_SET_TYPE(xa_p, value) \
+ (((xa_p)->valid) |= XA_V_TYPE, ((xa_p)->xa_type) = value)
+
+
+#define XA_VALID_MODE(xa_p) \
+ (((xa_p)->valid) & XA_V_MODE)
+#define XA_VALID_NLINK(xa_p) \
+ (((xa_p)->valid) & XA_V_NLINK)
+#define XA_VALID_SIZE(xa_p) \
+ (((xa_p)->valid) & XA_V_SIZE)
+#define XA_VALID_UID(xa_p) \
+ (((xa_p)->valid) & XA_V_UID)
+#define XA_VALID_GID(xa_p) \
+ (((xa_p)->valid) & XA_V_GID)
+#define XA_VALID_ATIME(xa_p) \
+ (((xa_p)->valid) & XA_V_ATIME)
+#define XA_VALID_MTIME(xa_p) \
+ (((xa_p)->valid) & XA_V_MTIME)
+#define XA_VALID_CTIME(xa_p) \
+ (((xa_p)->valid) & XA_V_CTIME)
+#define XA_VALID_FILEID(xa_p) \
+ (((xa_p)->valid) & XA_V_FILEID)
+#define XA_VALID_TYPE(xa_p) \
+ (((xa_p)->valid) & XA_V_TYPE)
+
+struct nnpfs_attr {
+ uint32_t valid;
+ uint32_t xa_mode;
+
+ uint32_t xa_nlink;
+ uint32_t xa_size;
+
+ uint32_t xa_uid;
+ uint32_t xa_gid;
+
+ uint32_t xa_atime;
+ uint32_t xa_mtime;
+
+ uint32_t xa_ctime;
+ uint32_t xa_fileid;
+
+ uint32_t xa_type;
+ uint32_t pad1;
+};
+
+#endif /* _NNPFS_ATTR_H */
diff --git a/sys/nnpfs/nnpfs_common-bsd.c b/sys/nnpfs/nnpfs_common-bsd.c
new file mode 100644
index 00000000000..d57b357d32e
--- /dev/null
+++ b/sys/nnpfs/nnpfs_common-bsd.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 1995 - 2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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 <nnpfs/nnpfs_locl.h>
+#include <nnpfs/nnpfs_common.h>
+#include <nnpfs/nnpfs_deb.h>
+
+RCSID("$arla: nnpfs_common-bsd.c,v 1.25 2002/12/18 16:32:03 lha Exp $");
+
+#ifdef MALLOC_DEFINE
+MALLOC_DEFINE(M_NNPFS, "nnpfs-misc", "nnpfs misc");
+MALLOC_DEFINE(M_NNPFS_NODE, "nnpfs-node", "nnpfs node");
+MALLOC_DEFINE(M_NNPFS_LINK, "nnpfs-link", "nnpfs link");
+MALLOC_DEFINE(M_NNPFS_MSG, "nnpfs-msg", "nnpfs msg");
+#endif
+
+#ifdef NNPFS_DEBUG
+static u_int nnpfs_allocs;
+static u_int nnpfs_frees;
+
+void *
+nnpfs_alloc(u_int size, nnpfs_malloc_type type)
+{
+ void *ret;
+
+ nnpfs_allocs++;
+ NNPFSDEB(XDEBMEM, ("nnpfs_alloc: nnpfs_allocs - nnpfs_frees %d\n",
+ nnpfs_allocs - nnpfs_frees));
+
+ ret = malloc(size, type, M_WAITOK);
+ return ret;
+}
+
+void
+nnpfs_free(void *ptr, u_int size, nnpfs_malloc_type type)
+{
+ nnpfs_frees++;
+ free(ptr, type);
+}
+
+#endif /* NNPFS_DEBUG */
+
+int
+nnpfs_suser(d_thread_t *p)
+{
+#if defined(HAVE_TWO_ARGUMENT_SUSER)
+#ifdef __OpenBSD__
+ return suser (p, SUSER_NOACCT);
+#else
+ return suser (nnpfs_proc_to_cred(p), NULL);
+#endif
+#else
+ return suser (p);
+#endif
+}
+
+/*
+ * Print a `dev_t' in some readable format
+ */
+
+#ifdef HAVE_KERNEL_DEVTONAME
+
+const char *
+nnpfs_devtoname_r (dev_t dev, char *buf, size_t sz)
+{
+ return devtoname (dev);
+}
+
+#else /* !HAVE_KERNEL_DEVTONAME */
+
+const char *
+nnpfs_devtoname_r (dev_t dev, char *buf, size_t sz)
+{
+#ifdef HAVE_KERNEL_SNPRINTF
+ snprintf (buf, sz, "%u/%u", major(dev), minor(dev));
+ return buf;
+#else
+ return "<unknown device>";
+#endif
+}
+
+#endif /* HAVE_KERNEL_DEVTONAME */
diff --git a/sys/nnpfs/nnpfs_common.h b/sys/nnpfs/nnpfs_common.h
new file mode 100644
index 00000000000..af04dd740c7
--- /dev/null
+++ b/sys/nnpfs/nnpfs_common.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $arla: nnpfs_common.h,v 1.19 2002/12/18 12:32:10 lha Exp $ */
+
+#ifndef _nnpfs_common_h
+#define _nnpfs_common_h
+
+#if defined(MALLOC_DECLARE)
+MALLOC_DECLARE(M_NNPFS);
+MALLOC_DECLARE(M_NNPFS_NODE);
+MALLOC_DECLARE(M_NNPFS_LINK);
+MALLOC_DECLARE(M_NNPFS_MSG);
+#elif !defined(M_NNPFS)
+#define M_NNPFS M_TEMP
+#define M_NNPFS_NODE M_TEMP
+#define M_NNPFS_LINK M_TEMP
+#define M_NNPFS_MSG M_TEMP
+#endif
+
+
+#ifdef NNPFS_DEBUG
+void *nnpfs_alloc(u_int size, nnpfs_malloc_type type);
+void nnpfs_free(void *, u_int size, nnpfs_malloc_type type);
+#else
+#ifdef __osf__
+#define nnpfs_alloc(a,t) malloc((a), BUCKETINDEX(a), t, M_WAITOK)
+#else
+#define nnpfs_alloc(a,t) malloc((a), t, M_WAITOK)
+#endif
+#define nnpfs_free(a, size,t) free(a, t)
+#endif /* NNPFS_DEBUG */
+
+int nnpfs_suser(d_thread_t *p);
+
+#ifndef HAVE_KERNEL_MEMCPY
+void *
+memcpy (void *s1, const void *s2, size_t n);
+#endif
+
+const char *
+nnpfs_devtoname_r (dev_t dev, char *buf, size_t sz);
+
+#ifndef HAVE_KERNEL_STRLCPY
+size_t
+strlcpy (char *dst, const char *src, size_t dst_sz);
+#endif
+
+#endif /* _nnpfs_common_h */
diff --git a/sys/nnpfs/nnpfs_config.h b/sys/nnpfs/nnpfs_config.h
new file mode 100644
index 00000000000..68ee3f692c1
--- /dev/null
+++ b/sys/nnpfs/nnpfs_config.h
@@ -0,0 +1,1665 @@
+/* include/config.h. Generated by configure. */
+/* include/config.h.in. Generated from configure.in by autoheader. */
+
+#ifndef OPENSSL_DES_LIBDES_COMPATIBILITY
+#define OPENSSL_DES_LIBDES_COMPATIBILITY 1
+#endif
+
+#ifndef RCSID
+#define RCSID(msg)
+#endif
+
+/* Maximum values on all known systems */
+#define MaxHostNameLen (64+4)
+#define MaxPathLen (1024+4)
+
+
+
+/* Define if realloc(NULL) doesn't work. */
+/* #undef BROKEN_REALLOC */
+
+/* define if you can include both dirent.h and sys/dir.h */
+#define DIRENT_AND_SYS_DIR_H 1
+
+/* define if DIRSIZ is defined in dirent.h */
+/* #undef DIRSIZ_IN_DIRENT_H */
+
+/* define if DIRSIZ is defined in sys/dir.h */
+#define DIRSIZ_IN_SYS_DIR_H 1
+
+/* how should ntohl be done? */
+#define EFF_NTOHL ntohl
+
+/* define if sys/param.h defines the endiness */
+#define ENDIANESS_IN_SYS_PARAM_H 1
+
+/* define if DIRSIZ is defined in sys/dirent.h */
+/* #undef GENERIC_DIRSIZ_IN_SYS_DIRENT_H */
+
+/* define if prototype of gethostbyaddr is compatible with struct hostent
+ *gethostbyaddr(const void *, size_t, int) */
+/* #undef GETHOSTBYADDR_PROTO_COMPATIBLE */
+
+/* define if prototype of gethostbyname is compatible with struct hostent
+ *gethostbyname(const char *) */
+#define GETHOSTBYNAME_PROTO_COMPATIBLE 1
+
+/* define if prototype of getservbyname is compatible with struct servent
+ *getservbyname(const char *, const char *) */
+#define GETSERVBYNAME_PROTO_COMPATIBLE 1
+
+/* define if prototype of getsockname is compatible with int getsockname(int,
+ struct sockaddr*, socklen_t*) */
+#define GETSOCKNAME_PROTO_COMPATIBLE 1
+
+/* Define if you have the `altzone' variable. */
+/* #undef HAVE_ALTZONE */
+
+/* define if your system declares altzone */
+/* #undef HAVE_ALTZONE_DECLARATION */
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the <arpa/nameser.h> header file. */
+#define HAVE_ARPA_NAMESER_H 1
+
+/* Define to 1 if you have the `asnprintf' function. */
+/* #undef HAVE_ASNPRINTF */
+
+/* Define to 1 if you have the `asprintf' function. */
+#define HAVE_ASPRINTF 1
+
+/* Define to 1 if you have the `atexit' function. */
+#define HAVE_ATEXIT 1
+
+/* Define to 1 if you have the `bool' function. */
+/* #undef HAVE_BOOL */
+
+/* Define to 1 if you have the `bswap16' function. */
+/* #undef HAVE_BSWAP16 */
+
+/* Define to 1 if you have the `bswap32' function. */
+/* #undef HAVE_BSWAP32 */
+
+/* Define to 1 if you have the `cgetent' function. */
+#define HAVE_CGETENT 1
+
+/* Define if you have the function `chown'. */
+#define HAVE_CHOWN 1
+
+/* Define to 1 if you have the <com_err.h> header file. */
+#define HAVE_COM_ERR_H 1
+
+/* Define to 1 if you have the <config.h> header file. */
+/* #undef HAVE_CONFIG_H */
+
+/* Define if you have the function `copyhostent'. */
+/* #undef HAVE_COPYHOSTENT */
+
+/* Define to 1 if you have the `crypt' function. */
+#define HAVE_CRYPT 1
+
+/* Define to 1 if you have the <crypt.h> header file. */
+/* #undef HAVE_CRYPT_H */
+
+/* Define if you have the function `daemon'. */
+#define HAVE_DAEMON 1
+
+/* define if you have a berkeley db1/2 library */
+#define HAVE_DB1 1
+
+/* define if you have a berkeley db3/4 library */
+/* #undef HAVE_DB3 */
+
+/* Define to 1 if you have the <db3/db.h> header file. */
+/* #undef HAVE_DB3_DB_H */
+
+/* Define to 1 if you have the <db4/db.h> header file. */
+/* #undef HAVE_DB4_DB_H */
+
+/* Define to 1 if you have the `dbm_firstkey' function. */
+#define HAVE_DBM_FIRSTKEY 1
+
+/* Define to 1 if you have the <dbm.h> header file. */
+#define HAVE_DBM_H 1
+
+/* Define to 1 if you have the `dbopen' function. */
+#define HAVE_DBOPEN 1
+
+/* Define to 1 if you have the <db_185.h> header file. */
+/* #undef HAVE_DB_185_H */
+
+/* Define to 1 if you have the `db_create' function. */
+/* #undef HAVE_DB_CREATE */
+
+/* Define to 1 if you have the <db.h> header file. */
+#define HAVE_DB_H 1
+
+/* define if you have ndbm compat in db */
+/* #undef HAVE_DB_NDBM */
+
+/* Define if you have struct setgroups_args */
+/* #undef HAVE_DEF_STRUCT_SETGROUPS_ARGS */
+
+/* Define if you have struct sys_setgroups_args */
+#define HAVE_DEF_STRUCT_SYS_SETGROUPS_ARGS 1
+
+/* define if devfs_register takes eleven arguments */
+/* #undef HAVE_DEVFS_REGISTER_ELEVEN_ARGS */
+
+/* define if you have a function dget_locked */
+/* #undef HAVE_DGET_LOCKED */
+
+/* Define to 1 if you have the <dirent.h> header file. */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the `dn_expand' function. */
+#define HAVE_DN_EXPAND 1
+
+/* define if d_alloc_root takes two arguments */
+/* #undef HAVE_D_ALLOC_ROOT_TWO_ARGS */
+
+/* define if d_delete in struct dentry_operations returns void */
+/* #undef HAVE_D_DELETE_VOID */
+
+/* Define if you have the function `ecalloc'. */
+/* #undef HAVE_ECALLOC */
+
+/* Define to 1 if you have the <elflib/nlist.h> header file. */
+/* #undef HAVE_ELFLIB_NLIST_H */
+
+/* Define to 1 if you have the `el_init' function. */
+/* #undef HAVE_EL_INIT */
+
+/* Define if you have the function `emalloc'. */
+/* #undef HAVE_EMALLOC */
+
+/* define if your system declares environ */
+/* #undef HAVE_ENVIRON_DECLARATION */
+
+/* Define if you have the function `erealloc'. */
+/* #undef HAVE_EREALLOC */
+
+/* Define if you have the function `err'. */
+#define HAVE_ERR 1
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define if you have the function `errx'. */
+#define HAVE_ERRX 1
+
+/* Define to 1 if you have the <err.h> header file. */
+#define HAVE_ERR_H 1
+
+/* Define if you have the function `estrdup'. */
+/* #undef HAVE_ESTRDUP */
+
+/* Define to 1 if you have the <et/com_err.h> header file. */
+/* #undef HAVE_ET_COM_ERR_H */
+
+/* Define if you have the function `fchown'. */
+#define HAVE_FCHOWN 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the `fhopen' function. */
+#define HAVE_FHOPEN 1
+
+/* define if filldir_t takes a dt_type argument */
+/* #undef HAVE_FILLDIR_T_DT_TYPE */
+
+/* Define if you have the function `flock'. */
+#define HAVE_FLOCK 1
+
+/* Define if you have the function `fnmatch'. */
+#define HAVE_FNMATCH 1
+
+/* Define to 1 if you have the <fnmatch.h> header file. */
+#define HAVE_FNMATCH_H 1
+
+/* define if lockmgr takes four arguments */
+/* #undef HAVE_FOUR_ARGUMENT_LOCKMGR */
+
+/* define if vfs_busy takes four arguments */
+/* #undef HAVE_FOUR_ARGUMENT_VFS_BUSY */
+
+/* define if vfs_name_hash takes four arguments */
+/* #undef HAVE_FOUR_ARGUMENT_VFS_NAME_HASH */
+
+/* if vfs_object_create takes four arguments */
+/* #undef HAVE_FOUR_ARGUMENT_VFS_OBJECT_CREATE */
+
+/* Define to 1 if you have the `freeaddrinfo' function. */
+#define HAVE_FREEADDRINFO 1
+
+/* Define if you have the function `freehostent'. */
+/* #undef HAVE_FREEHOSTENT */
+
+/* Define to 1 if you have the `gai_strerror' function. */
+#define HAVE_GAI_STRERROR 1
+
+/* Define to 1 if you have the <gdbm/ndbm.h> header file. */
+/* #undef HAVE_GDBM_NDBM_H */
+
+/* Define to 1 if you have the `getaddrinfo' function. */
+#define HAVE_GETADDRINFO 1
+
+/* Define to 1 if you have the `getattrlist' function. */
+/* #undef HAVE_GETATTRLIST */
+
+/* Define to 1 if you have the `getconfattr' function. */
+/* #undef HAVE_GETCONFATTR */
+
+/* Define if you have the function `getcwd'. */
+#define HAVE_GETCWD 1
+
+/* Define if you have the function `getdtablesize'. */
+#define HAVE_GETDTABLESIZE 1
+
+/* Define if you have the function `getegid'. */
+#define HAVE_GETEGID 1
+
+/* Define if you have the function `geteuid'. */
+#define HAVE_GETEUID 1
+
+/* Define to 1 if you have the `getfh' function. */
+#define HAVE_GETFH 1
+
+/* Define if you have the function `getgid'. */
+#define HAVE_GETGID 1
+
+/* Define to 1 if you have the `gethostbyname' function. */
+#define HAVE_GETHOSTBYNAME 1
+
+/* Define to 1 if you have the `gethostbyname2' function. */
+#define HAVE_GETHOSTBYNAME2 1
+
+/* Define if you have the function `gethostname'. */
+#define HAVE_GETHOSTNAME 1
+
+/* Define if you have the function `getifaddrs'. */
+#define HAVE_GETIFADDRS 1
+
+/* Define if you have the function `getipnodebyaddr'. */
+/* #undef HAVE_GETIPNODEBYADDR */
+
+/* Define if you have the function `getipnodebyname'. */
+/* #undef HAVE_GETIPNODEBYNAME */
+
+/* Define to 1 if you have the `getlogin' function. */
+#define HAVE_GETLOGIN 1
+
+/* Define to 1 if you have the `getnameinfo' function. */
+#define HAVE_GETNAMEINFO 1
+
+/* Define if you have the function `getopt'. */
+#define HAVE_GETOPT 1
+
+/* Define to 1 if you have the `getpagesize' function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define to 1 if you have the `getprogname' function. */
+/* #undef HAVE_GETPROGNAME */
+
+/* Define to 1 if you have the `getrlimit' function. */
+#define HAVE_GETRLIMIT 1
+
+/* Define to 1 if you have the `getrusage' function. */
+#define HAVE_GETRUSAGE 1
+
+/* Define to 1 if you have the `getsockopt' function. */
+#define HAVE_GETSOCKOPT 1
+
+/* Define to 1 if you have the `getspnam' function. */
+/* #undef HAVE_GETSPNAM */
+
+/* Define if you have the function `gettimeofday'. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define if you have the function `getuid'. */
+#define HAVE_GETUID 1
+
+/* Define if you have the function `getusershell'. */
+#define HAVE_GETUSERSHELL 1
+
+/* define if you have a glibc-based system */
+/* #undef HAVE_GLIBC */
+
+/* define if you have a glob() that groks GLOB_BRACE, GLOB_NOCHECK,
+ GLOB_QUOTE, GLOB_TILDE, and GLOB_LIMIT */
+#define HAVE_GLOB 1
+
+/* Define to 1 if you have the <glob.h> header file. */
+#define HAVE_GLOB_H 1
+
+/* Define to 1 if you have the <grp.h> header file. */
+#define HAVE_GRP_H 1
+
+/* Define to 1 if you have the `hstrerror' function. */
+#define HAVE_HSTRERROR 1
+
+/* Define if you have the `h_errlist' variable. */
+#define HAVE_H_ERRLIST 1
+
+/* define if your system declares h_errlist */
+/* #undef HAVE_H_ERRLIST_DECLARATION */
+
+/* Define if you have the `h_errno' variable. */
+#define HAVE_H_ERRNO 1
+
+/* define if your system declares h_errno */
+#define HAVE_H_ERRNO_DECLARATION 1
+
+/* Define if you have the `h_nerr' variable. */
+#define HAVE_H_NERR 1
+
+/* define if your system declares h_nerr */
+/* #undef HAVE_H_NERR_DECLARATION */
+
+/* Define to 1 if you have the <ifaddrs.h> header file. */
+#define HAVE_IFADDRS_H 1
+
+/* Define if you have the in6addr_loopback variable */
+#define HAVE_IN6ADDR_LOOPBACK 1
+
+/* define */
+#define HAVE_INET_ATON 1
+
+/* define */
+#define HAVE_INET_NTOP 1
+
+/* define */
+#define HAVE_INET_PTON 1
+
+/* Define if you have the function `initgroups'. */
+#define HAVE_INITGROUPS 1
+
+/* Define to 1 if you have the `initstate' function. */
+#define HAVE_INITSTATE 1
+
+/* define if you have a function init_MUTEX */
+/* #undef HAVE_INIT_MUTEX */
+
+/* define if you have a init_waitqueue_head */
+/* #undef HAVE_INIT_WAITQUEUE_HEAD */
+
+/* Define if you have the function `innetgr'. */
+#define HAVE_INNETGR 1
+
+/* Define to 1 if you have the `int16' function. */
+/* #undef HAVE_INT16 */
+
+/* Define to 1 if you have the `int16_t' function. */
+#define HAVE_INT16_T 1
+
+/* Define to 1 if you have the `int32' function. */
+/* #undef HAVE_INT32 */
+
+/* Define to 1 if you have the `int32_t' function. */
+#define HAVE_INT32_T 1
+
+/* Define to 1 if you have the `int64_t' function. */
+#define HAVE_INT64_T 1
+
+/* Define to 1 if you have the `int8_t' function. */
+#define HAVE_INT8_T 1
+
+/* Define to 1 if you have the `intptr_t' function. */
+/* #undef HAVE_INTPTR_T */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define if you have IPv6. */
+#define HAVE_IPV6 1
+
+/* Define if you have the function `iruserok'. */
+#define HAVE_IRUSEROK 1
+
+/* Define to 1 if you have the `issetugid' function. */
+#define HAVE_ISSETUGID 1
+
+/* Define to 1 if you have the `kernel_aout_sysent' function. */
+/* #undef HAVE_KERNEL_AOUT_SYSENT */
+
+/* Define to 1 if you have the `kernel_cache_purgevfs' function. */
+#define HAVE_KERNEL_CACHE_PURGEVFS 1
+
+/* Define to 1 if you have the `kernel_cdevsw_add' function. */
+/* #undef HAVE_KERNEL_CDEVSW_ADD */
+
+/* Define to 1 if you have the `kernel_debuglockmgr' function. */
+/* #undef HAVE_KERNEL_DEBUGLOCKMGR */
+
+/* Define to 1 if you have the `kernel_devtoname' function. */
+/* #undef HAVE_KERNEL_DEVTONAME */
+
+/* Define to 1 if you have the `kernel_doforce' function. */
+#define HAVE_KERNEL_DOFORCE 1
+
+/* Define to 1 if you have the `kernel_genfs_mmap' function. */
+/* #undef HAVE_KERNEL_GENFS_MMAP */
+
+/* Define to 1 if you have the `kernel_genfs_revoke' function. */
+/* #undef HAVE_KERNEL_GENFS_REVOKE */
+
+/* Define to 1 if you have the `kernel_lf_advlock' function. */
+#define HAVE_KERNEL_LF_ADVLOCK 1
+
+/* Define to 1 if you have the `kernel_lockmgr' function. */
+#define HAVE_KERNEL_LOCKMGR 1
+
+/* Define to 1 if you have the `kernel_lockstatus' function. */
+#define HAVE_KERNEL_LOCKSTATUS 1
+
+/* Define to 1 if you have the `kernel_memcpy' function. */
+#define HAVE_KERNEL_MEMCPY 1
+
+/* Define to 1 if you have the `kernel_namei_hash' function. */
+/* #undef HAVE_KERNEL_NAMEI_HASH */
+
+/* Define to 1 if you have the `kernel_nosys' function. */
+/* #undef HAVE_KERNEL_NOSYS */
+
+/* Define to 1 if you have the `kernel_snprintf' function. */
+#define HAVE_KERNEL_SNPRINTF 1
+
+/* Define to 1 if you have the `kernel_strlcpy' function. */
+#define HAVE_KERNEL_STRLCPY 1
+
+/* Define to 1 if you have the `kernel_sys_lkmnosys' function. */
+#define HAVE_KERNEL_SYS_LKMNOSYS 1
+
+/* Define to 1 if you have the `kernel_sys_nosys' function. */
+#define HAVE_KERNEL_SYS_NOSYS 1
+
+/* Define to 1 if you have the `kernel_udev2dev' function. */
+/* #undef HAVE_KERNEL_UDEV2DEV */
+
+/* Define to 1 if you have the `kernel_uma_zfree_arg' function. */
+/* #undef HAVE_KERNEL_UMA_ZFREE_ARG */
+
+/* define if we only can include uvm headers */
+/* #undef HAVE_KERNEL_UVM_ONLY */
+
+/* Define to 1 if you have the `kernel_vfs_add_vnodeops' function. */
+/* #undef HAVE_KERNEL_VFS_ADD_VNODEOPS */
+
+/* Define to 1 if you have the `kernel_vfs_attach' function. */
+/* #undef HAVE_KERNEL_VFS_ATTACH */
+
+/* Define to 1 if you have the `kernel_vfs_cache_lookup' function. */
+/* #undef HAVE_KERNEL_VFS_CACHE_LOOKUP */
+
+/* Define to 1 if you have the `kernel_vfs_deallocate_syncvnode' function. */
+/* #undef HAVE_KERNEL_VFS_DEALLOCATE_SYNCVNODE */
+
+/* Define to 1 if you have the `kernel_vfs_getnewfsid' function. */
+#define HAVE_KERNEL_VFS_GETNEWFSID 1
+
+/* Define to 1 if you have the `kernel_vfs_getvfs' function. */
+#define HAVE_KERNEL_VFS_GETVFS 1
+
+/* Define to 1 if you have the `kernel_vfs_object_create' function. */
+/* #undef HAVE_KERNEL_VFS_OBJECT_CREATE */
+
+/* Define to 1 if you have the `kernel_vfs_opv_init' function. */
+#define HAVE_KERNEL_VFS_OPV_INIT 1
+
+/* Define to 1 if you have the `kernel_vfs_opv_init_default' function. */
+#define HAVE_KERNEL_VFS_OPV_INIT_DEFAULT 1
+
+/* Define to 1 if you have the `kernel_vfs_opv_init_explicit' function. */
+#define HAVE_KERNEL_VFS_OPV_INIT_EXPLICIT 1
+
+/* Define to 1 if you have the `kernel_vfs_register' function. */
+#define HAVE_KERNEL_VFS_REGISTER 1
+
+/* Define to 1 if you have the `kernel_vgonel' function. */
+#define HAVE_KERNEL_VGONEL 1
+
+/* Define to 1 if you have the `kernel_vnode_pager_generic_getpages' function.
+ */
+/* #undef HAVE_KERNEL_VNODE_PAGER_GENERIC_GETPAGES */
+
+/* Define to 1 if you have the `kernel_vnode_pager_generic_putpages' function.
+ */
+/* #undef HAVE_KERNEL_VNODE_PAGER_GENERIC_PUTPAGES */
+
+/* Define to 1 if you have the `kernel_vnode_pager_setsize' function. */
+/* #undef HAVE_KERNEL_VNODE_PAGER_SETSIZE */
+
+/* Define to 1 if you have the `kernel_vop_revoke' function. */
+/* #undef HAVE_KERNEL_VOP_REVOKE */
+
+/* Define to 1 if you have the `kernel_vop_stdpathconf' function. */
+/* #undef HAVE_KERNEL_VOP_STDPATHCONF */
+
+/* Define to 1 if you have the `kernel_zfree' function. */
+/* #undef HAVE_KERNEL_ZFREE */
+
+/* Define to 1 if you have the `kernel_zfreei' function. */
+/* #undef HAVE_KERNEL_ZFREEI */
+
+/* define if you have kerberos 4 */
+/* #undef HAVE_KRB4 */
+
+/* define if you have kerberos 5 */
+#define HAVE_KRB5 1
+
+/* define if you have kerberos 4 compat */
+/* #undef HAVE_KRB5_COMPAT_KRB4 */
+
+/* Define to 1 if you have the `krb_afslog_uid' function. */
+/* #undef HAVE_KRB_AFSLOG_UID */
+
+/* define if you have krb_get_default_principal */
+/* #undef HAVE_KRB_GET_DEFAULT_PRINCIPAL */
+
+/* define if you have krb_get_default_tkt_root */
+/* #undef HAVE_KRB_GET_DEFAULT_TKT_ROOT */
+
+/* define if you have krb_get_err_text */
+/* #undef HAVE_KRB_GET_ERR_TEXT */
+
+/* define if you have krb_kdctimeofday */
+/* #undef HAVE_KRB_KDCTIMEOFDAY */
+
+/* define if you have a struct krb_principal */
+/* #undef HAVE_KRB_PRINCIPAL */
+
+/* Define to 1 if you have the <ktypes.h> header file. */
+/* #undef HAVE_KTYPES_H */
+
+/* Define to 1 if you have the <kvm.h> header file. */
+#define HAVE_KVM_H 1
+
+/* Define to 1 if you have the <libelf/nlist.h> header file. */
+/* #undef HAVE_LIBELF_NLIST_H */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <linux/devfs_fs.h> header file. */
+/* #undef HAVE_LINUX_DEVFS_FS_H */
+
+/* Define to 1 if you have the <linux/devfs_fs_kernel.h> header file. */
+/* #undef HAVE_LINUX_DEVFS_FS_KERNEL_H */
+
+/* Define to 1 if you have the `linux_kernel_int16_t' function. */
+/* #undef HAVE_LINUX_KERNEL_INT16_T */
+
+/* Define to 1 if you have the `linux_kernel_int32_t' function. */
+/* #undef HAVE_LINUX_KERNEL_INT32_T */
+
+/* Define to 1 if you have the `linux_kernel_int64_t' function. */
+/* #undef HAVE_LINUX_KERNEL_INT64_T */
+
+/* Define to 1 if you have the `linux_kernel_int8_t' function. */
+/* #undef HAVE_LINUX_KERNEL_INT8_T */
+
+/* Define to 1 if you have the `linux_kernel_uint16_t' function. */
+/* #undef HAVE_LINUX_KERNEL_UINT16_T */
+
+/* Define to 1 if you have the `linux_kernel_uint32_t' function. */
+/* #undef HAVE_LINUX_KERNEL_UINT32_T */
+
+/* Define to 1 if you have the `linux_kernel_uint64_t' function. */
+/* #undef HAVE_LINUX_KERNEL_UINT64_T */
+
+/* Define to 1 if you have the `linux_kernel_uint8_t' function. */
+/* #undef HAVE_LINUX_KERNEL_UINT8_T */
+
+/* Define to 1 if you have the <linux/stddef.h> header file. */
+/* #undef HAVE_LINUX_STDDEF_H */
+
+/* define if you have a function list_del_init */
+/* #undef HAVE_LIST_DEL_INIT */
+
+/* define if there exists a localtime_r */
+#define HAVE_LOCALTIME_R 1
+
+/* Define to 1 if the system has the type `long long'. */
+#define HAVE_LONG_LONG 1
+
+/* Define if you have the function `lstat'. */
+#define HAVE_LSTAT 1
+
+/* Define to 1 if you have the <machine/asm.h> header file. */
+#define HAVE_MACHINE_ASM_H 1
+
+/* Define to 1 if you have the <machine/regdef.h> header file. */
+/* #undef HAVE_MACHINE_REGDEF_H */
+
+/* Define to 1 if you have the <mach/alpha/asm.h> header file. */
+/* #undef HAVE_MACH_ALPHA_ASM_H */
+
+/* Define if you have the function `memmove'. */
+#define HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <miscfs/genfs/genfs.h> header file. */
+/* #undef HAVE_MISCFS_GENFS_GENFS_H */
+
+/* Define to 1 if you have the <miscfs/syncfs/syncfs.h> header file. */
+/* #undef HAVE_MISCFS_SYNCFS_SYNCFS_H */
+
+/* Define if you have the function `mkstemp'. */
+#define HAVE_MKSTEMP 1
+
+/* Define to 1 if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* define if you have a ndbm library */
+#define HAVE_NDBM 1
+
+/* Define to 1 if you have the <ndbm.h> header file. */
+#define HAVE_NDBM_H 1
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define to 1 if you have the <netinet6/in6.h> header file. */
+/* #undef HAVE_NETINET6_IN6_H */
+
+/* Define to 1 if you have the <netinet6/in6_var.h> header file. */
+#define HAVE_NETINET6_IN6_VAR_H 1
+
+/* Define to 1 if you have the <netinet/in6.h> header file. */
+/* #undef HAVE_NETINET_IN6_H */
+
+/* Define to 1 if you have the <netinet/in6_machtypes.h> header file. */
+/* #undef HAVE_NETINET_IN6_MACHTYPES_H */
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the <netinet/in_systm.h> header file. */
+#define HAVE_NETINET_IN_SYSTM_H 1
+
+/* Define to 1 if you have the <netinet/ip.h> header file. */
+#define HAVE_NETINET_IP_H 1
+
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+#define HAVE_NETINET_TCP_H 1
+
+/* Define to 1 if you have the <net/if_dl.h> header file. */
+#define HAVE_NET_IF_DL_H 1
+
+/* Define to 1 if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H 1
+
+/* Define to 1 if you have the <net/if_types.h> header file. */
+#define HAVE_NET_IF_TYPES_H 1
+
+/* Define if NDBM really is DB (creates files *.db) */
+#define HAVE_NEW_DB 1
+
+/* Define to 1 if you have the <nlist.h> header file. */
+#define HAVE_NLIST_H 1
+
+/* Define to 1 if you have the `off64_t' function. */
+/* #undef HAVE_OFF64_T */
+
+/* define if lockstatus takes one argument */
+#define HAVE_ONE_ARGUMENT_LOCKSTATUS 1
+
+/* define if vget takes one argument */
+/* #undef HAVE_ONE_ARGUMENT_VGET */
+
+/* define if VOP_LOCK takes one argument */
+/* #undef HAVE_ONE_ARGUMENT_VOP_LOCK */
+
+/* Define to 1 if you have the `on_exit' function. */
+/* #undef HAVE_ON_EXIT */
+
+/* define if your system declares optarg */
+#define HAVE_OPTARG_DECLARATION 1
+
+/* define if your system declares opterr */
+#define HAVE_OPTERR_DECLARATION 1
+
+/* define if your system declares optind */
+#define HAVE_OPTIND_DECLARATION 1
+
+/* define if your system declares optopt */
+#define HAVE_OPTOPT_DECLARATION 1
+
+/* Define if you have the `optreset' variable. */
+#define HAVE_OPTRESET 1
+
+/* define if your system declares optreset */
+#define HAVE_OPTRESET_DECLARATION 1
+
+/* Define to 1 if you have the <paths.h> header file. */
+#define HAVE_PATHS_H 1
+
+/* Define to 1 if you have the `pidfile' function. */
+#define HAVE_PIDFILE 1
+
+/* define if you have sigaction */
+#define HAVE_POSIX_SIGNALS 1
+
+/* Define to 1 if you have the `pthread_create' function. */
+/* #undef HAVE_PTHREAD_CREATE */
+
+/* Define if you have the function `putenv'. */
+#define HAVE_PUTENV 1
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define to 1 if you have the `random' function. */
+#define HAVE_RANDOM 1
+
+/* Define if you have the function `rcmd'. */
+#define HAVE_RCMD 1
+
+/* define if you have a function readline */
+#define HAVE_READLINE 1
+
+/* Define if you have the function `readv'. */
+#define HAVE_READV 1
+
+/* Define if you have the function `recvmsg'. */
+#define HAVE_RECVMSG 1
+
+/* Define to 1 if you have the <regdef.h> header file. */
+/* #undef HAVE_REGDEF_H */
+
+/* Define to 1 if you have the `register_t' function. */
+#define HAVE_REGISTER_T 1
+
+/* define? */
+/* #undef HAVE_REPAIRABLE_HTONL */
+
+/* Define to 1 if you have the <resolv.h> header file. */
+#define HAVE_RESOLV_H 1
+
+/* Define to 1 if you have the `res_init' function. */
+#define HAVE_RES_INIT 1
+
+/* Define to 1 if you have the `res_nsearch' function. */
+/* #undef HAVE_RES_NSEARCH */
+
+/* Define to 1 if you have the `res_search' function. */
+#define HAVE_RES_SEARCH 1
+
+/* Define to 1 if you have the <rpcsvc/dbm.h> header file. */
+/* #undef HAVE_RPCSVC_DBM_H */
+
+/* Define to 1 if you have the <rpcsvc/ypclnt.h> header file. */
+#define HAVE_RPCSVC_YPCLNT_H 1
+
+/* Define to 1 if the system has the type `sa_family_t'. */
+#define HAVE_SA_FAMILY_T 1
+
+/* Define if you have the function `sendmsg'. */
+#define HAVE_SENDMSG 1
+
+/* Define to 1 if you have the `setattrlist' function. */
+/* #undef HAVE_SETATTRLIST */
+
+/* Define if you have the function `setegid'. */
+#define HAVE_SETEGID 1
+
+/* Define if you have the function `setenv'. */
+#define HAVE_SETENV 1
+
+/* Define if you have the function `seteuid'. */
+#define HAVE_SETEUID 1
+
+/* Define to 1 if you have the `setlogin' function. */
+#define HAVE_SETLOGIN 1
+
+/* Define to 1 if you have the `setprogname' function. */
+/* #undef HAVE_SETPROGNAME */
+
+/* Define to 1 if you have the `setsockopt' function. */
+#define HAVE_SETSOCKOPT 1
+
+/* Define to 1 if you have the `setstate' function. */
+#define HAVE_SETSTATE 1
+
+/* Define to 1 if you have the <shadow.h> header file. */
+/* #undef HAVE_SHADOW_H */
+
+/* define if ubc_lookup takes six arguments */
+/* #undef HAVE_SIX_ARGUMENT_UBC_LOOKUP */
+
+/* define if you have a working snprintf */
+#define HAVE_SNPRINTF 1
+
+/* Define to 1 if you have the `socket' function. */
+#define HAVE_SOCKET 1
+
+/* Define to 1 if the system has the type `socklen_t'. */
+#define HAVE_SOCKLEN_T 1
+
+/* Define to 1 if you have the `ssize_t' function. */
+#define HAVE_SSIZE_T 1
+
+/* Define to 1 if you have the <standards.h> header file. */
+/* #undef HAVE_STANDARDS_H */
+
+/* Define to 1 if you have the `statvfs' function. */
+/* #undef HAVE_STATVFS */
+
+/* Define to 1 if you have the <stdint.h> header file. */
+/* #undef HAVE_STDINT_H */
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* We always have <stds.h>, needed by rxkad */
+#define HAVE_STDS_H 1
+
+/* Define if you have the function `strcasecmp'. */
+#define HAVE_STRCASECMP 1
+
+/* Define if you have the function `strdup'. */
+#define HAVE_STRDUP 1
+
+/* Define if you have the function `strerror'. */
+#define HAVE_STRERROR 1
+
+/* Define if you have the function `strftime'. */
+#define HAVE_STRFTIME 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the function `strlcat'. */
+#define HAVE_STRLCAT 1
+
+/* Define if you have the function `strlcpy'. */
+#define HAVE_STRLCPY 1
+
+/* Define if you have the function `strlwr'. */
+/* #undef HAVE_STRLWR */
+
+/* Define if you have the function `strncasecmp'. */
+#define HAVE_STRNCASECMP 1
+
+/* Define if you have the function `strndup'. */
+/* #undef HAVE_STRNDUP */
+
+/* Define if you have the function `strnlen'. */
+/* #undef HAVE_STRNLEN */
+
+/* Define if you have the function `strptime'. */
+#define HAVE_STRPTIME 1
+
+/* Define if you have the function `strsep'. */
+#define HAVE_STRSEP 1
+
+/* Define if you have the function `strsep_copy'. */
+/* #undef HAVE_STRSEP_COPY */
+
+/* Define to 1 if you have the `strsvis' function. */
+/* #undef HAVE_STRSVIS */
+
+/* Define if you have the function `strtok_r'. */
+#define HAVE_STRTOK_R 1
+
+/* Define to 1 if you have the `strtoll' function. */
+#define HAVE_STRTOLL 1
+
+/* Define to 1 if you have the `strtoq' function. */
+#define HAVE_STRTOQ 1
+
+/* Define to 1 if the system has the type `struct addrinfo'. */
+#define HAVE_STRUCT_ADDRINFO 1
+
+/* Define if struct cdevsw has field d_bmaj */
+/* #undef HAVE_STRUCT_CDEVSW_D_BMAJ */
+
+/* Define if struct cdevsw has field d_bogoparms */
+/* #undef HAVE_STRUCT_CDEVSW_D_BOGOPARMS */
+
+/* Define if struct cdevsw has field d_bogoreset */
+/* #undef HAVE_STRUCT_CDEVSW_D_BOGORESET */
+
+/* Define if struct cdevsw has field d_devtotty */
+/* #undef HAVE_STRUCT_CDEVSW_D_DEVTOTTY */
+
+/* Define if struct cdevsw has field d_kqfilter */
+/* #undef HAVE_STRUCT_CDEVSW_D_KQFILTER */
+
+/* Define if struct cdevsw has field d_maxio */
+/* #undef HAVE_STRUCT_CDEVSW_D_MAXIO */
+
+/* Define if struct cdevsw has field d_psize */
+/* #undef HAVE_STRUCT_CDEVSW_D_PSIZE */
+
+/* Define if struct cdevsw has field d_reset */
+/* #undef HAVE_STRUCT_CDEVSW_D_RESET */
+
+/* Define if struct cdevsw has field d_spare */
+/* #undef HAVE_STRUCT_CDEVSW_D_SPARE */
+
+/* Define if struct cdevsw has field d_stop */
+/* #undef HAVE_STRUCT_CDEVSW_D_STOP */
+
+/* Define if struct componentname has field cn_hash */
+#define HAVE_STRUCT_COMPONENTNAME_CN_HASH 1
+
+/* Define if struct dirent has field d_type. */
+#define HAVE_STRUCT_DIRENT_D_TYPE 1
+
+/* Define to 1 if the system has the type `struct ifaddrs'. */
+#define HAVE_STRUCT_IFADDRS 1
+
+/* Define if struct inode_operations has field default_file_ops */
+/* #undef HAVE_STRUCT_INODE_OPERATIONS_DEFAULT_FILE_OPS */
+
+/* Define to 1 if the system has the type `struct iovec'. */
+#define HAVE_STRUCT_IOVEC 1
+
+/* Define if struct mount has field mnt_syncer */
+#define HAVE_STRUCT_MOUNT_MNT_SYNCER 1
+
+/* Define if struct mount has field m_info */
+/* #undef HAVE_STRUCT_MOUNT_M_INFO */
+
+/* Define to 1 if the system has the type `struct msghdr'. */
+#define HAVE_STRUCT_MSGHDR 1
+
+/* Define if struct proc has field p_sigctx. */
+/* #undef HAVE_STRUCT_PROC_P_SIGCTX */
+
+/* Define if struct proc has field p_sigmask. */
+#define HAVE_STRUCT_PROC_P_SIGMASK 1
+
+/* Define to 1 if the system has the type `struct sockaddr'. */
+#define HAVE_STRUCT_SOCKADDR 1
+
+/* Define if struct sockaddr_in has field sin_len. */
+#define HAVE_STRUCT_SOCKADDR_IN_SIN_LEN 1
+
+/* Define if struct sockaddr has field sa_len. */
+#define HAVE_STRUCT_SOCKADDR_SA_LEN 1
+
+/* Define to 1 if the system has the type `struct sockaddr_storage'. */
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
+
+/* define if you have struct spwd */
+/* #undef HAVE_STRUCT_SPWD */
+
+/* Define if struct super_operations has field notify_change */
+/* #undef HAVE_STRUCT_SUPER_OPERATIONS_NOTIFY_CHANGE */
+
+/* Define if struct sysent has field sy_flags */
+/* #undef HAVE_STRUCT_SYSENT_SY_FLAGS */
+
+/* Define if struct sysent has field sy_info */
+/* #undef HAVE_STRUCT_SYSENT_SY_INFO */
+
+/* Define if struct task_struct has field pending */
+/* #undef HAVE_STRUCT_TASK_STRUCT_PENDING */
+
+/* Define if struct tm has field tm_gmtoff. */
+#define HAVE_STRUCT_TM_TM_GMTOFF 1
+
+/* Define if struct tm has field tm_zone. */
+#define HAVE_STRUCT_TM_TM_ZONE 1
+
+/* Define if struct uio has field uio_procp */
+#define HAVE_STRUCT_UIO_UIO_PROCP 1
+
+/* Define if struct vfsconf has field vfc_mountroot */
+/* #undef HAVE_STRUCT_VFSCONF_VFC_MOUNTROOT */
+
+/* Define if struct vfsconf has field vfc_refcount */
+#define HAVE_STRUCT_VFSCONF_VFC_REFCOUNT 1
+
+/* Define if struct vfsops has field vfs_checkexp */
+#define HAVE_STRUCT_VFSOPS_VFS_CHECKEXP 1
+
+/* Define if struct vfsops has field vfs_done */
+/* #undef HAVE_STRUCT_VFSOPS_VFS_DONE */
+
+/* Define if struct vfsops has field vfs_freevfs */
+/* #undef HAVE_STRUCT_VFSOPS_VFS_FREEVFS */
+
+/* Define if struct vfsops has field vfs_mount */
+#define HAVE_STRUCT_VFSOPS_VFS_MOUNT 1
+
+/* Define if struct vfsops has field vfs_mountroot */
+/* #undef HAVE_STRUCT_VFSOPS_VFS_MOUNTROOT */
+
+/* Define if struct vfsops has field vfs_name */
+/* #undef HAVE_STRUCT_VFSOPS_VFS_NAME */
+
+/* Define if struct vfsops has field vfs_oid */
+/* #undef HAVE_STRUCT_VFSOPS_VFS_OID */
+
+/* Define if struct vfsops has field vfs_opv_descs */
+/* #undef HAVE_STRUCT_VFSOPS_VFS_OPV_DESCS */
+
+/* Define if struct vfsops has field vfs_reinit */
+/* #undef HAVE_STRUCT_VFSOPS_VFS_REINIT */
+
+/* Define if struct vfsops has field vfs_smoothsync */
+/* #undef HAVE_STRUCT_VFSOPS_VFS_SMOOTHSYNC */
+
+/* Define if struct vfsops has field vfs_swapvp */
+/* #undef HAVE_STRUCT_VFSOPS_VFS_SWAPVP */
+
+/* Define if struct vfsops has field vfs_uninit */
+/* #undef HAVE_STRUCT_VFSOPS_VFS_UNINIT */
+
+/* Define if struct ViceIoctl has field in */
+/* #undef HAVE_STRUCT_VICEIOCTL_IN */
+
+/* Define if struct vop_fsync_args has field a_flags */
+/* #undef HAVE_STRUCT_VOP_FSYNC_ARGS_A_FLAGS */
+
+/* Define if struct vop_getpages_args has field a_offset */
+/* #undef HAVE_STRUCT_VOP_GETPAGES_ARGS_A_OFFSET */
+
+/* Define if struct vop_putpages_args has field a_sync */
+/* #undef HAVE_STRUCT_VOP_PUTPAGES_ARGS_A_SYNC */
+
+/* define if struct winsize is declared in sys/termios.h */
+#define HAVE_STRUCT_WINSIZE 1
+
+/* Define to 1 if you have the `strunvis' function. */
+#define HAVE_STRUNVIS 1
+
+/* Define if you have the function `strupr'. */
+/* #undef HAVE_STRUPR */
+
+/* Define to 1 if you have the `strvis' function. */
+#define HAVE_STRVIS 1
+
+/* Define to 1 if you have the `strvisx' function. */
+#define HAVE_STRVISX 1
+
+/* Define to 1 if you have the `svis' function. */
+/* #undef HAVE_SVIS */
+
+/* Define if you have the function `swab'. */
+#define HAVE_SWAB 1
+
+/* Define to 1 if you have the `sysconf' function. */
+#define HAVE_SYSCONF 1
+
+/* Define to 1 if you have the `sysctl' function. */
+#define HAVE_SYSCTL 1
+
+/* Define to 1 if you have the `syslog' function. */
+#define HAVE_SYSLOG 1
+
+/* Define to 1 if you have the <syslog.h> header file. */
+#define HAVE_SYSLOG_H 1
+
+/* Define to 1 if you have the <sys/attr.h> header file. */
+/* #undef HAVE_SYS_ATTR_H */
+
+/* Define to 1 if you have the <sys/bitypes.h> header file. */
+/* #undef HAVE_SYS_BITYPES_H */
+
+/* Define to 1 if you have the <sys/bswap.h> header file. */
+/* #undef HAVE_SYS_BSWAP_H */
+
+/* Define to 1 if you have the <sys/cdefs.h> header file. */
+#define HAVE_SYS_CDEFS_H 1
+
+/* Define to 1 if you have the <sys/dir.h> header file. */
+#define HAVE_SYS_DIR_H 1
+
+/* Define to 1 if you have the <sys/file.h> header file. */
+#define HAVE_SYS_FILE_H 1
+
+/* Define to 1 if you have the <sys/inttypes.h> header file. */
+/* #undef HAVE_SYS_INTTYPES_H */
+
+/* Define to 1 if you have the <sys/ioccom.h> header file. */
+#define HAVE_SYS_IOCCOM_H 1
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/libkern.h> header file. */
+/* #undef HAVE_SYS_LIBKERN_H */
+
+/* Define to 1 if you have the <sys/lkm.h> header file. */
+#define HAVE_SYS_LKM_H 1
+
+/* Define to 1 if you have the <sys/lock.h> header file. */
+#define HAVE_SYS_LOCK_H 1
+
+/* Define to 1 if you have the <sys/mkdev.h> header file. */
+/* #undef HAVE_SYS_MKDEV_H */
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#define HAVE_SYS_MMAN_H 1
+
+/* Define to 1 if you have the <sys/module.h> header file. */
+/* #undef HAVE_SYS_MODULE_H */
+
+/* Define to 1 if you have the <sys/mount.h> header file. */
+#define HAVE_SYS_MOUNT_H 1
+
+/* Define to 1 if you have the <sys/mutex.h> header file. */
+/* #undef HAVE_SYS_MUTEX_H */
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/poll.h> header file. */
+#define HAVE_SYS_POLL_H 1
+
+/* Define to 1 if you have the <sys/prctl.h> header file. */
+/* #undef HAVE_SYS_PRCTL_H */
+
+/* Define to 1 if you have the <sys/proc.h> header file. */
+#define HAVE_SYS_PROC_H 1
+
+/* Define to 1 if you have the <sys/queue.h> header file. */
+#define HAVE_SYS_QUEUE_H 1
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define to 1 if you have the <sys/selinfo.h> header file. */
+/* #undef HAVE_SYS_SELINFO_H */
+
+/* Define to 1 if you have the <sys/signalvar.h> header file. */
+#define HAVE_SYS_SIGNALVAR_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+#define HAVE_SYS_SOCKIO_H 1
+
+/* Define to 1 if you have the <sys/statfs.h> header file. */
+/* #undef HAVE_SYS_STATFS_H */
+
+/* Define to 1 if you have the <sys/statvfs.h> header file. */
+/* #undef HAVE_SYS_STATVFS_H */
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/syscallargs.h> header file. */
+#define HAVE_SYS_SYSCALLARGS_H 1
+
+/* Define to 1 if you have the <sys/sysctl.h> header file. */
+#define HAVE_SYS_SYSCTL_H 1
+
+/* Define to 1 if you have the <sys/sysent.h> header file. */
+/* #undef HAVE_SYS_SYSENT_H */
+
+/* Define to 1 if you have the <sys/sysproto.h> header file. */
+/* #undef HAVE_SYS_SYSPROTO_H */
+
+/* Define to 1 if you have the <sys/systm.h> header file. */
+/* #undef HAVE_SYS_SYSTM_H */
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/tty.h> header file. */
+#define HAVE_SYS_TTY_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/ubc.h> header file. */
+/* #undef HAVE_SYS_UBC_H */
+
+/* Define to 1 if you have the <sys/uio.h> header file. */
+#define HAVE_SYS_UIO_H 1
+
+/* Define to 1 if you have the <sys/user.h> header file. */
+#define HAVE_SYS_USER_H 1
+
+/* Define to 1 if you have the <sys/utsname.h> header file. */
+#define HAVE_SYS_UTSNAME_H 1
+
+/* Define to 1 if you have the <sys/vfs.h> header file. */
+/* #undef HAVE_SYS_VFS_H */
+
+/* Define to 1 if you have the <sys/vfs_proto.h> header file. */
+/* #undef HAVE_SYS_VFS_PROTO_H */
+
+/* Define to 1 if you have the <sys/vnode.h> header file. */
+#define HAVE_SYS_VNODE_H 1
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define to 1 if you have the `tf_init' function. */
+/* #undef HAVE_TF_INIT */
+
+/* Define to 1 if you have the `tgetent' function. */
+#define HAVE_TGETENT 1
+
+/* define if selrecord takes three arguments */
+/* #undef HAVE_THREE_ARGUMENT_SELRECORD */
+
+/* define if vfs_busy takes three arguments */
+/* #undef HAVE_THREE_ARGUMENT_VFS_BUSY */
+
+/* define if vfs_name_hash takes three arguments */
+/* #undef HAVE_THREE_ARGUMENT_VFS_NAME_HASH */
+
+/* define if vget takes three arguments */
+#define HAVE_THREE_ARGUMENT_VGET 1
+
+/* define if VOP_LOCK takes three arguments */
+#define HAVE_THREE_ARGUMENT_VOP_LOCK 1
+
+/* Define to 1 if you have the `thr_yield' function. */
+/* #undef HAVE_THR_YIELD */
+
+/* Define if you have the `timezone' variable. */
+#define HAVE_TIMEZONE 1
+
+/* define if your system declares timezone */
+#define HAVE_TIMEZONE_DECLARATION 1
+
+/* define if lockstatus takes two arguments */
+/* #undef HAVE_TWO_ARGUMENT_LOCKSTATUS */
+
+/* define if suser takes two arguments */
+#define HAVE_TWO_ARGUMENT_SUSER 1
+
+/* define if vfs_getnewfsid takes two arguments */
+/* #undef HAVE_TWO_ARGUMENT_VFS_GETNEWFSID */
+
+/* define if vfs_busy takes two arguments */
+#define HAVE_TWO_ARGUMENT_VFS_BUSY 1
+
+/* define if vget takes two arguments */
+/* #undef HAVE_TWO_ARGUMENT_VGET */
+
+/* define if VOP_LOCK takes two arguments */
+/* #undef HAVE_TWO_ARGUMENT_VOP_LOCK */
+
+/* Define to 1 if you have the `uint16_t' function. */
+#define HAVE_UINT16_T 1
+
+/* Define to 1 if you have the `uint32_t' function. */
+#define HAVE_UINT32_T 1
+
+/* Define to 1 if you have the `uint64_t' function. */
+#define HAVE_UINT64_T 1
+
+/* Define to 1 if you have the `uint8_t' function. */
+#define HAVE_UINT8_T 1
+
+/* Define to 1 if you have the `uintptr_t' function. */
+/* #undef HAVE_UINTPTR_T */
+
+/* Define to 1 if you have the `uname' function. */
+#define HAVE_UNAME 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the function `unsetenv'. */
+#define HAVE_UNSETENV 1
+
+/* Define to 1 if you have the `unvis' function. */
+#define HAVE_UNVIS 1
+
+/* Define to 1 if you have the <userconf.h> header file. */
+/* #undef HAVE_USERCONF_H */
+
+/* Define to 1 if you have the <usersec.h> header file. */
+/* #undef HAVE_USERSEC_H */
+
+/* Define to 1 if you have the <util.h> header file. */
+#define HAVE_UTIL_H 1
+
+/* Define to 1 if you have the <uvm/uvm_extern.h> header file. */
+#define HAVE_UVM_UVM_EXTERN_H 1
+
+/* Define to 1 if you have the `u_int16' function. */
+/* #undef HAVE_U_INT16 */
+
+/* Define to 1 if you have the `u_int16_t' function. */
+#define HAVE_U_INT16_T 1
+
+/* Define to 1 if you have the `u_int32' function. */
+/* #undef HAVE_U_INT32 */
+
+/* Define to 1 if you have the `u_int32_t' function. */
+#define HAVE_U_INT32_T 1
+
+/* Define to 1 if you have the `u_int64_t' function. */
+#define HAVE_U_INT64_T 1
+
+/* Define to 1 if you have the `u_int8_t' function. */
+#define HAVE_U_INT8_T 1
+
+/* Define to 1 if you have the `vasnprintf' function. */
+/* #undef HAVE_VASNPRINTF */
+
+/* Define to 1 if you have the `vasprintf' function. */
+#define HAVE_VASPRINTF 1
+
+/* Define if you have the function `verr'. */
+#define HAVE_VERR 1
+
+/* Define if you have the function `verrx'. */
+#define HAVE_VERRX 1
+
+/* Define to 1 if you have the `vis' function. */
+#define HAVE_VIS 1
+
+/* Define to 1 if you have the <vis.h> header file. */
+#define HAVE_VIS_H 1
+
+/* Define to 1 if you have the <vm/uma.h> header file. */
+/* #undef HAVE_VM_UMA_H */
+
+/* Define to 1 if you have the <vm/vm_extern.h> header file. */
+/* #undef HAVE_VM_VM_EXTERN_H */
+
+/* Define to 1 if you have the <vm/vm.h> header file. */
+/* #undef HAVE_VM_VM_H */
+
+/* Define to 1 if you have the <vm/vm_object.h> header file. */
+/* #undef HAVE_VM_VM_OBJECT_H */
+
+/* Define to 1 if you have the <vm/vm_pager.h> header file. */
+/* #undef HAVE_VM_VM_PAGER_H */
+
+/* Define to 1 if you have the <vm/vm_zone.h> header file. */
+/* #undef HAVE_VM_VM_ZONE_H */
+
+/* Define to 1 if you have the <vm/vnode_pager.h> header file. */
+/* #undef HAVE_VM_VNODE_PAGER_H */
+
+/* define if you have a vop_t */
+/* #undef HAVE_VOP_T */
+
+/* define if you have a working vsnprintf */
+#define HAVE_VSNPRINTF 1
+
+/* Define if you have the function `vsyslog'. */
+#define HAVE_VSYSLOG 1
+
+/* Define if you have the function `vwarn'. */
+#define HAVE_VWARN 1
+
+/* Define if you have the function `vwarnx'. */
+#define HAVE_VWARNX 1
+
+/* define if you have a wait_queue_head_t */
+/* #undef HAVE_WAIT_QUEUE_HEAD_T */
+
+/* define if you have a wait_queue_task_list */
+/* #undef HAVE_WAIT_QUEUE_TASK_LIST */
+
+/* Define if you have the function `warn'. */
+#define HAVE_WARN 1
+
+/* Define if you have the function `warnx'. */
+#define HAVE_WARNX 1
+
+/* Define to 1 if you have the <winsock.h> header file. */
+/* #undef HAVE_WINSOCK_H */
+
+/* Define if you have the function `writev'. */
+#define HAVE_WRITEV 1
+
+/* define if struct winsize has ws_xpixel */
+#define HAVE_WS_XPIXEL 1
+
+/* define if struct winsize has ws_ypixel */
+#define HAVE_WS_YPIXEL 1
+
+/* Define if you have the `_res' variable. */
+#define HAVE__RES 1
+
+/* define if your system declares _res */
+#define HAVE__RES_DECLARATION 1
+
+/* define if your compiler has __attribute__ */
+#define HAVE___ATTRIBUTE__ 1
+
+/* define if your compiler has __FUNCTION__ */
+#define HAVE___FUNCTION__ 1
+
+/* Define if you have the `__progname' variable. */
+#define HAVE___PROGNAME 1
+
+/* define if your system declares __progname */
+/* #undef HAVE___PROGNAME_DECLARATION */
+
+/* define this if on Irix6.4 or higher */
+/* #undef IRIX_64 */
+
+/* define if you have kerberos */
+#define KERBEROS 1
+
+/* define if the system is missing a prototype for asnprintf() */
+#define NEED_ASNPRINTF_PROTO 1
+
+/* define if the system is missing a prototype for asprintf() */
+/* #undef NEED_ASPRINTF_PROTO */
+
+/* define if the system is missing a prototype for crypt() */
+/* #undef NEED_CRYPT_PROTO */
+
+/* define if the system is missing a prototype for gethostname() */
+/* #undef NEED_GETHOSTNAME_PROTO */
+
+/* define if the system is missing a prototype for getusershell() */
+/* #undef NEED_GETUSERSHELL_PROTO */
+
+/* define if the system is missing a prototype for glob() */
+/* #undef NEED_GLOB_PROTO */
+
+/* define if the system is missing a prototype for hstrerror() */
+/* #undef NEED_HSTRERROR_PROTO */
+
+/* define if the system is missing a prototype for inet_aton() */
+/* #undef NEED_INET_ATON_PROTO */
+
+/* define if the system is missing a prototype for issignal() */
+/* #undef NEED_ISSIGNAL_PROTO */
+
+/* define if the system is missing a prototype for mkstemp() */
+/* #undef NEED_MKSTEMP_PROTO */
+
+/* define if the system is missing a prototype for select() */
+/* #undef NEED_SELECT_PROTO */
+
+/* define if the system is missing a prototype for setenv() */
+/* #undef NEED_SETENV_PROTO */
+
+/* libsl need sl_apropos */
+/* #undef NEED_SLCOMPAT_SL_APROPOS */
+
+/* define if the system is missing a prototype for snprintf() */
+/* #undef NEED_SNPRINTF_PROTO */
+
+/* define if the system is missing a prototype for strncmp() */
+#define NEED_STRNCMP_PROTO 1
+
+/* define if the system is missing a prototype for strndup() */
+#define NEED_STRNDUP_PROTO 1
+
+/* define if the system is missing a prototype for strsep() */
+/* #undef NEED_STRSEP_PROTO */
+
+/* define if the system is missing a prototype for strsvis() */
+/* #undef NEED_STRSVIS_PROTO */
+
+/* define if the system is missing a prototype for strtok_r() */
+/* #undef NEED_STRTOK_R_PROTO */
+
+/* define if the system is missing a prototype for strunvis() */
+/* #undef NEED_STRUNVIS_PROTO */
+
+/* define if the system is missing a prototype for strvisx() */
+/* #undef NEED_STRVISX_PROTO */
+
+/* define if the system is missing a prototype for strvis() */
+/* #undef NEED_STRVIS_PROTO */
+
+/* define if the system is missing a prototype for svis() */
+/* #undef NEED_SVIS_PROTO */
+
+/* define if the system is missing a prototype for ubc_pushdirty() */
+#define NEED_UBC_PUSHDIRTY_PROTO 1
+
+/* define if the system is missing a prototype for unsetenv() */
+/* #undef NEED_UNSETENV_PROTO */
+
+/* define if the system is missing a prototype for unvis() */
+/* #undef NEED_UNVIS_PROTO */
+
+/* define if the system is missing a prototype for vasnprintf() */
+#define NEED_VASNPRINTF_PROTO 1
+
+/* define if the system is missing a prototype for vasprintf() */
+/* #undef NEED_VASPRINTF_PROTO */
+
+/* define if the system is missing a prototype for vgonel() */
+/* #undef NEED_VGONEL_PROTO */
+
+/* define if you need 32 bit compat pioctl */
+/* #undef NEED_VICEIOCTL32 */
+
+/* define if the system is missing a prototype for vis() */
+/* #undef NEED_VIS_PROTO */
+
+/* define if the system is missing a prototype for vn_writechk() */
+/* #undef NEED_VN_WRITECHK_PROTO */
+
+/* define if the system is missing a prototype for vsnprintf() */
+/* #undef NEED_VSNPRINTF_PROTO */
+
+/* define if prototype of openlog is compatible with void openlog(const char
+ *, int, int) */
+#define OPENLOG_PROTO_COMPATIBLE 1
+
+/* Name of package */
+#define PACKAGE "arla"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "arla-drinkers@stacken.kth.se"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "arla"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "arla 0.36pre29"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "arla"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "0.36pre29"
+
+/* Define if getlogin has POSIX flavour (and not BSD). */
+/* #undef POSIX_GETLOGIN */
+
+/* define this if your as understands .register */
+/* #undef PROG_AS_UNDERSTANDS_REGISTER */
+
+/* Define if you have the readline package. */
+/* #undef READLINE */
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Version number of package */
+#define VERSION "0.36pre29"
+
+/* Define if signal handlers return void. */
+#define VOID_RETSIGTYPE 1
+
+/* define if target is big endian */
+/* #undef WORDS_BIGENDIAN */
+
+/* Define to 1 if the X Window System is missing or not being used. */
+/* #undef X_DISPLAY_MISSING */
+
+/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
+ `char[]'. */
+#define YYTEXT_POINTER 1
+
+
+/*
+ * Defining this enables us to get the definition of `sigset_t' and
+ * other importatnt definitions on Solaris.
+ */
+
+#ifndef __EXTENSIONS__
+#define __EXTENSIONS__
+#endif
+
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef gid_t */
+
+/* Define as `__inline' if that's what the C compiler calls it, or to nothing
+ if it is not supported. */
+/* #undef inline */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef pid_t */
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef uid_t */
+
+
+#if !(defined(USING_ASM) || defined(_KERNEL) || defined(__KERNEL__) || defined(_LKM) || defined(KERNEL))
+#if ENDIANESS_IN_SYS_PARAM_H
+# include <sys/types.h>
+# include <sys/param.h>
+# if BYTE_ORDER == BIG_ENDIAN
+# define WORDS_BIGENDIAN 1
+# endif
+#endif
+#endif
+
+
+#ifdef VOID_RETSIGTYPE
+#define SIGRETURN(x) return
+#else
+#define SIGRETURN(x) return (RETSIGTYPE)(x)
+#endif
+
+#ifdef BROKEN_REALLOC
+#define realloc(X, Y) isoc_realloc((X), (Y))
+#define isoc_realloc(X, Y) ((X) ? realloc((X), (Y)) : malloc(Y))
+#endif
diff --git a/sys/nnpfs/nnpfs_deb.c b/sys/nnpfs/nnpfs_deb.c
new file mode 100644
index 00000000000..af9f33102ff
--- /dev/null
+++ b/sys/nnpfs/nnpfs_deb.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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 <nnpfs/nnpfs_deb.h>
+#include <nnpfs/nnpfs_debug.h>
+
+/* $arla: nnpfs_deb.c,v 1.15 2002/09/07 10:45:03 lha Exp $ */
+
+/* X is on */
+#define X(y) y
+/* and x is off */
+#define x(y) 0
+
+unsigned int nnpfsdeb = (0 |
+ x(XDEBDEV) |
+ x(XDEBMSG) |
+ x(XDEBDNLC) |
+ x(XDEBNODE) |
+ x(XDEBVNOPS) |
+ x(XDEBVFOPS) |
+ x(XDEBLKM) |
+ x(XDEBSYS) |
+ x(XDEBMEM) |
+ 0
+);
diff --git a/sys/nnpfs/nnpfs_deb.h b/sys/nnpfs/nnpfs_deb.h
new file mode 100644
index 00000000000..ecffe9e99f6
--- /dev/null
+++ b/sys/nnpfs/nnpfs_deb.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $arla: nnpfs_deb.h,v 1.11 2002/09/07 10:45:59 lha Exp $ */
+
+#ifndef _nnpfs_deb_h
+#define _nnpfs_deb_h
+
+#include <nnpfs/nnpfs_debug.h>
+
+#define HAVE_XDEBDEV
+#define HAVE_XDEBMSG
+#define HAVE_XDEBDNLC
+#define HAVE_XDEBNODE
+#define HAVE_XDEBVNOPS
+#define HAVE_XDEBVFOPS
+#define HAVE_XDEBLKM
+#define HAVE_XDEBSYS
+#define HAVE_XDEBMEM
+#define HAVE_XDEBSYS
+
+extern unsigned int nnpfsdeb;
+
+#ifdef NNPFS_DEBUG
+#define NNPFSDEB(mask, args) do { if (mask&nnpfsdeb) printf args; } while (0)
+#else
+#define NNPFSDEB(mask, args) do { ; } while (0)
+#endif
+
+#endif /* _nnpfs_deb_h */
diff --git a/sys/nnpfs/nnpfs_debug.h b/sys/nnpfs/nnpfs_debug.h
new file mode 100644
index 00000000000..6a0525aa90e
--- /dev/null
+++ b/sys/nnpfs/nnpfs_debug.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $arla: nnpfs_debug.h,v 1.5 2002/09/14 09:56:01 tol Exp $ */
+
+#ifndef __NNPFS_DEBUG_H
+#define __NNPFS_DEBUG_H
+
+/*
+ * These are GLOBAL nnpfs debugging masks
+ *
+ * Define HAVE_XDEB in your local nnpfs_deb.h if
+ * you want your fs to handle the debugging flags.
+ */
+
+/* Masks for the debug macro */
+#define XDEBDEV 0x00000001 /* device handling */
+#define XDEBMSG 0x00000002 /* message sending */
+#define XDEBDNLC 0x00000004 /* name cache */
+#define XDEBNODE 0x00000008 /* nnpfs nodes */
+#define XDEBVNOPS 0x00000010 /* vnode operations */
+#define XDEBVFOPS 0x00000020 /* vfs operations */
+#define XDEBLKM 0x00000040 /* LKM handling */
+#define XDEBSYS 0x00000080 /* syscalls */
+#define XDEBMEM 0x00000100 /* memory allocation */
+#define XDEBREADDIR 0x00000200 /* readdir (linux) */
+#define XDEBLOCK 0x00000400 /* locking (linux) */
+#define XDEBCACHE 0x00000800 /* Cache handeling (linux) */
+#define XDEBREF 0x00001000 /* track reference count */
+
+#endif
diff --git a/sys/nnpfs/nnpfs_dev-bsd.c b/sys/nnpfs/nnpfs_dev-bsd.c
new file mode 100644
index 00000000000..bf9ee336f18
--- /dev/null
+++ b/sys/nnpfs/nnpfs_dev-bsd.c
@@ -0,0 +1,154 @@
+/* $OpenBSD: nnpfs_dev-bsd.c,v 1.1 2009/06/03 14:45:54 jj Exp $
+
+ * Copyright (c) 2004 Bob Beck
+ * Copyright (c) 1995 - 2003 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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 <nnpfs/nnpfs_locl.h>
+#include <nnpfs/nnpfs_message.h>
+#include <nnpfs/nnpfs_msg_locl.h>
+#include <nnpfs/nnpfs_fs.h>
+#include <nnpfs/nnpfs_dev.h>
+#include <nnpfs/nnpfs_deb.h>
+
+int
+nnpfs_devopen(dev_t dev, int flag, int devtype, d_thread_t *proc)
+{
+ NNPFSDEB(XDEBDEV, ("nnpfsopen dev = %d.%d, flag = %d, devtype = %d\n",
+ major(dev), minor(dev), flag, devtype));
+ return nnpfs_devopen_common(dev);
+}
+
+int
+nnpfs_devclose(dev_t dev, int flag, int devtype, d_thread_t *p)
+{
+ NNPFSDEB(XDEBDEV, ("nnpfs_devclose dev = %d(%d), flag = 0x%x\n",
+ major(dev), minor(dev), flag));
+
+ return nnpfs_devclose_common(dev, p);
+}
+
+int
+nnpfs_devioctl(dev_t dev, u_long cmd, caddr_t data, int flags, d_thread_t *p)
+{
+ NNPFSDEB(XDEBDEV, ("nnpfs_devioctl dev = %d.%d, cmd = %lu, "
+ "data = %lx, flags = %x\n", major(dev), minor(dev),
+ (unsigned long)cmd, (unsigned long)data, flags));
+ return ENOTTY;
+}
+
+int
+nnpfs_devpoll(dev_t dev, int events, d_thread_t * p)
+{
+ struct nnpfs_channel *chan = &nnpfs_channel[minor(dev)];
+
+ NNPFSDEB(XDEBDEV, ("nnpfs_devpoll dev = %d(%d), events = 0x%x\n",
+ major(dev), minor(dev), events));
+
+ if ((events & (POLLIN | POLLRDNORM)) == 0)
+ return 0; /* only supports read */
+
+ if (!nnpfs_emptyq(&chan->messageq))
+ return (events & (POLLIN | POLLRDNORM));
+
+ selrecord (p, &chan->selinfo);
+
+ return 0;
+}
+
+void
+nnpfs_select_wakeup(struct nnpfs_channel *chan)
+{
+ selwakeup (&chan->selinfo);
+}
+
+/*
+ * Install and uninstall device.
+ */
+
+struct cdevsw nnpfs_dev = {
+ nnpfs_devopen,
+ nnpfs_devclose,
+ nnpfs_devread,
+ nnpfs_devwrite,
+ nnpfs_devioctl,
+ (dev_type_stop((*))) enodev,
+ 0,
+ nnpfs_devpoll,
+ (dev_type_mmap((*))) enodev,
+ 0
+};
+
+int
+nnpfs_install_device(void)
+{
+ int i;
+
+ for (i = 0; i < NNNPFS; i++) {
+ NNPFSDEB(XDEBDEV, ("before initq(messageq and sleepq)\n"));
+ nnpfs_initq(&nnpfs_channel[i].messageq);
+ nnpfs_initq(&nnpfs_channel[i].sleepq);
+ nnpfs_channel[i].status = 0;
+ }
+ return 0;
+}
+
+int
+nnpfs_uninstall_device(void)
+{
+ int i;
+ struct nnpfs_channel *chan;
+ int ret = 0;
+
+ for (i = 0; i < NNNPFS; i++) {
+ chan = &nnpfs_channel[i];
+ if (chan->status & CHANNEL_OPENED)
+ nnpfs_devclose(makedev(0, i), 0, 0, NULL);
+ }
+
+ NNPFSDEB(XDEBLKM, ("nnpfs_uninstall_device error %d\n", ret));
+ return ret;
+}
+
+int
+nnpfs_stat_device(void)
+{
+ return nnpfs_uprintf_device();
+}
+
+int
+nnpfs_is_nnpfs_dev(dev_t dev)
+{
+ return major(dev) <= nchrdev &&
+ cdevsw[major(dev)].d_open == nnpfs_devopen &&
+ minor(dev) >= 0 && minor(dev) < NNNPFS;
+}
diff --git a/sys/nnpfs/nnpfs_dev-common.c b/sys/nnpfs/nnpfs_dev-common.c
new file mode 100644
index 00000000000..455e7cec9ce
--- /dev/null
+++ b/sys/nnpfs/nnpfs_dev-common.c
@@ -0,0 +1,736 @@
+/*
+ * Copyright (c) 1995 - 2003 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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 <nnpfs/nnpfs_locl.h>
+#include <nnpfs/nnpfs_message.h>
+#include <nnpfs/nnpfs_msg_locl.h>
+#include <nnpfs/nnpfs_fs.h>
+#include <nnpfs/nnpfs_dev.h>
+#include <nnpfs/nnpfs_deb.h>
+
+RCSID("$arla: nnpfs_dev-common.c,v 1.61 2003/07/15 16:25:42 lha Exp $");
+
+struct nnpfs_channel nnpfs_channel[NNNPFS];
+
+void
+nnpfs_initq(struct nnpfs_link *q)
+{
+ q->next = q;
+ q->prev = q;
+}
+
+/* Is this queue empty? */
+int
+nnpfs_emptyq(const struct nnpfs_link *q)
+{
+ return q->next == q;
+}
+
+/* Is this link on any queue? Link *must* be inited! */
+int
+nnpfs_onq(const struct nnpfs_link *link)
+{
+ return link->next != NULL || link->prev != NULL;
+}
+
+/* Append q with p */
+void
+nnpfs_appendq(struct nnpfs_link *q, struct nnpfs_link *p)
+{
+ p->next = q;
+ p->prev = q->prev;
+ p->prev->next = p;
+ q->prev = p;
+}
+
+/* remove `p' from its queue */
+void
+nnpfs_outq(struct nnpfs_link *p)
+{
+ p->next->prev = p->prev;
+ p->prev->next = p->next;
+ p->next = p->prev = NULL;
+}
+
+/*
+ * Only allow one open.
+ */
+int
+nnpfs_devopen_common(dev_t dev)
+{
+ struct nnpfs_channel *chan;
+
+ if (minor(dev) < 0 || minor(dev) >= NNNPFS)
+ return ENXIO;
+
+ chan = &nnpfs_channel[minor(dev)];
+
+ /* Only allow one reader/writer */
+ if (chan->status & CHANNEL_OPENED) {
+ NNPFSDEB(XDEBDEV, ("nnpfs_devopen: already open\n"));
+ return EBUSY;
+ } else {
+ chan->status |= CHANNEL_OPENED;
+ }
+
+ chan->message_buffer = nnpfs_alloc(MAX_XMSG_SIZE, M_NNPFS_MSG);
+
+ /* initialize the queues if they have not been initialized before */
+ nnpfs_initq(&chan->sleepq);
+ nnpfs_initq(&chan->messageq);
+
+ return 0;
+}
+
+#if defined(HAVE_TWO_ARGUMENT_VFS_BUSY)
+#define nnpfs_vfs_busy(mp, flags, lock, proc) vfs_busy((mp), (flags))
+#define nnpfs_vfs_unbusy(mp, proc) vfs_unbusy((mp))
+#elif defined(HAVE_THREE_ARGUMENT_VFS_BUSY)
+#define nnpfs_vfs_busy(mp, flags, lock, proc) vfs_busy((mp), (flags), (lock))
+#define nnpfs_vfs_unbusy(mp, proc) vfs_unbusy((mp))
+#elif defined(HAVE_FOUR_ARGUMENT_VFS_BUSY)
+#define nnpfs_vfs_busy(mp, flags, lock, proc) vfs_busy((mp), (flags), (lock), (proc))
+#define nnpfs_vfs_unbusy(mp, proc) vfs_unbusy((mp), (proc))
+#elif defined(__osf__)
+#define nnpfs_vfs_busy(mp, flags, lock, proc) (0)
+#define nnpfs_vfs_unbusy(mp, proc) (0)
+#else
+#define nnpfs_vfs_busy(mp, flags, lock, proc) vfs_busy((mp))
+#define nnpfs_vfs_unbusy(mp, proc) vfs_unbusy((mp))
+#endif
+
+/*
+ * Wakeup all sleepers and cleanup.
+ */
+int
+nnpfs_devclose_common(dev_t dev, d_thread_t *proc)
+{
+ struct nnpfs_channel *chan = &nnpfs_channel[minor(dev)];
+ struct nnpfs_link *first;
+
+ /* Sanity check, paranoia? */
+ if (!(chan->status & CHANNEL_OPENED))
+ panic("nnpfs_devclose never opened?");
+
+ chan->status &= ~CHANNEL_OPENED;
+
+ /* No one is going to read those messages so empty queue! */
+ while (!nnpfs_emptyq(&chan->messageq)) {
+ NNPFSDEB(XDEBDEV, ("before outq(messageq)\n"));
+
+ first = chan->messageq.next;
+ nnpfs_outq(first);
+ if (first->error_or_size != 0)
+ nnpfs_free(first, first->error_or_size, M_NNPFS_LINK);
+
+ NNPFSDEB(XDEBDEV, ("after outq(messageq)\n"));
+ }
+
+ /* Wakeup those waiting for replies that will never arrive. */
+ while (!nnpfs_emptyq(&chan->sleepq)) {
+ NNPFSDEB(XDEBDEV, ("before outq(sleepq)\n"));
+ first = chan->sleepq.next;
+ nnpfs_outq(first);
+ first->error_or_size = ENODEV;
+ wakeup((caddr_t) first);
+ NNPFSDEB(XDEBDEV, ("after outq(sleepq)\n"));
+ }
+
+ if (chan->status & CHANNEL_WAITING)
+ wakeup((caddr_t) chan);
+
+ if (chan->message_buffer) {
+ nnpfs_free(chan->message_buffer, MAX_XMSG_SIZE, M_NNPFS_MSG);
+ chan->message_buffer = NULL;
+ }
+
+ /*
+ * Free all nnpfs nodes.
+ */
+
+ if (nnpfs[minor(dev)].mp != NULL) {
+ if (nnpfs_vfs_busy(nnpfs[minor(dev)].mp, VB_READ|VB_WAIT, NULL, proc)) {
+ NNPFSDEB(XDEBNODE, ("nnpfs_dev_close: vfs_busy() --> BUSY\n"));
+ return EBUSY;
+ }
+ free_all_nnpfs_nodes(&nnpfs[minor(dev)], FORCECLOSE, 0);
+
+ nnpfs_vfs_unbusy(nnpfs[minor(dev)].mp, proc);
+ }
+
+ return 0;
+}
+
+#ifdef NNPFS_DEBUG
+/*
+ * debugging glue for CURSIG
+ */
+
+static long
+nnpfs_cursig (d_thread_t *p)
+{
+#if defined(__osf__)
+ thread_t th = current_thread();
+ struct np_uthread *npu = thread_to_np_uthread(th);
+ return CURSIG(p,npu);
+#elif defined(HAVE_FREEBSD_THREAD)
+#ifndef CURSIG
+ return 0; /* XXX we would like to use sig_ffs, but that isn't
+ * exported */
+#else
+ return CURSIG(p->td_proc);
+#endif
+#else
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 106130000
+ return 0; /* XXX CURSIG operates on a struct lwp */
+#else
+ return CURSIG(p);
+#endif
+#endif
+}
+#endif
+
+/*
+ * Move messages from kernel to user space.
+ */
+
+int
+nnpfs_devread(dev_t dev, struct uio * uiop, int ioflag)
+{
+ struct nnpfs_channel *chan = &nnpfs_channel[minor(dev)];
+ struct nnpfs_link *first;
+ int error = 0;
+#ifdef NNPFS_DEBUG
+ char devname[64];
+#endif
+
+ NNPFSDEB(XDEBDEV, ("nnpfs_devread dev = %s\n",
+ nnpfs_devtoname_r(dev, devname, sizeof(devname))));
+
+ NNPFSDEB(XDEBDEV, ("nnpfs_devread: m = %lx, m->prev = %lx, m->next = %lx\n",
+ (unsigned long)&chan->messageq,
+ (unsigned long)chan->messageq.prev,
+ (unsigned long)chan->messageq.next));
+
+#ifdef HAVE_FREEBSD_THREAD
+ chan->proc = nnpfs_uio_to_thread(uiop);
+#else
+ chan->proc = nnpfs_uio_to_proc(uiop);
+#endif
+
+ again:
+
+ if (!nnpfs_emptyq (&chan->messageq)) {
+ while (!nnpfs_emptyq (&chan->messageq)) {
+ /* Remove message */
+ first = chan->messageq.next;
+ NNPFSDEB(XDEBDEV, ("nnpfs_devread: first = %lx, "
+ "first->prev = %lx, first->next = %lx\n",
+ (unsigned long)first,
+ (unsigned long)first->prev,
+ (unsigned long)first->next));
+
+ NNPFSDEB(XDEBDEV, ("nnpfs_devread: message->size = %u\n",
+ first->message->size));
+
+ if (first->message->size > uiop->uio_resid)
+ break;
+
+ error = uiomove((caddr_t) first->message, first->message->size,
+ uiop);
+ if (error)
+ break;
+
+ nnpfs_outq(first);
+
+ if (first->error_or_size != 0)
+ nnpfs_free(first, first->error_or_size, M_NNPFS_LINK);
+ }
+ } else {
+ chan->status |= CHANNEL_WAITING;
+ if (tsleep((caddr_t) chan, (PZERO + 1) | PCATCH, "nnpfsread", 0)) {
+#ifdef HAVE_FREEBSD_THREAD
+ NNPFSDEB(XDEBMSG,
+ ("caught signal nnpfs_devread: %ld\n",
+ nnpfs_cursig(nnpfs_uio_to_thread(uiop))));
+#else
+ NNPFSDEB(XDEBMSG,
+ ("caught signal nnpfs_devread: %ld\n",
+ nnpfs_cursig(nnpfs_uio_to_proc(uiop))));
+#endif
+ error = EINTR;
+ } else if ((chan->status & CHANNEL_WAITING) == 0) {
+ goto again;
+ } else
+ error = EIO;
+ }
+
+ NNPFSDEB(XDEBDEV, ("nnpfs_devread done error = %d\n", error));
+
+ return error;
+}
+
+/*
+ * Move messages from user space to kernel space,
+ * wakeup sleepers, insert new data in VFS.
+ */
+int
+nnpfs_devwrite(dev_t dev, struct uio *uiop, int ioflag)
+{
+ struct nnpfs_channel *chan = &nnpfs_channel[minor(dev)];
+ char *p;
+ int error;
+ u_int cnt;
+ struct nnpfs_message_header *msg_buf;
+#ifdef NNPFS_DEBUG
+ char devname[64];
+#endif
+
+ NNPFSDEB(XDEBDEV, ("nnpfs_devwrite dev = %s\n",
+ nnpfs_devtoname_r (dev, devname, sizeof(devname))));
+
+#ifdef HAVE_FREEBSD_THREAD
+ chan->proc = nnpfs_uio_to_thread(uiop);
+#else
+ chan->proc = nnpfs_uio_to_proc(uiop);
+#endif
+ cnt = uiop->uio_resid;
+ error = uiomove((caddr_t) chan->message_buffer, MAX_XMSG_SIZE, uiop);
+ if (error != 0)
+ return error;
+
+ cnt -= uiop->uio_resid;
+
+ /*
+ * This thread handles the received message.
+ */
+ for (p = (char *)chan->message_buffer;
+ cnt > 0;
+ p += msg_buf->size, cnt -= msg_buf->size) {
+#ifdef HAVE_FREEBSD_THREAD
+ d_thread_t *pp = nnpfs_uio_to_thread(uiop);
+#else
+ d_thread_t *pp = nnpfs_uio_to_proc(uiop);
+#endif
+
+ msg_buf = (struct nnpfs_message_header *)p;
+ error = nnpfs_message_receive (minor(dev),
+ msg_buf,
+ msg_buf->size,
+ pp);
+ }
+ NNPFSDEB(XDEBDEV, ("nnpfs_devwrite error = %d\n", error));
+ return error;
+}
+
+/*
+ * Send a message to user space.
+ */
+int
+nnpfs_message_send(int fd, struct nnpfs_message_header * message, u_int size)
+{
+ struct nnpfs_channel *chan = &nnpfs_channel[fd];
+ struct {
+ struct nnpfs_link this_message;
+ struct nnpfs_message_header msg;
+ } *t;
+
+ NNPFSDEB(XDEBMSG, ("nnpfs_message_send opcode = %d\n", message->opcode));
+
+ if (!(chan->status & CHANNEL_OPENED)) /* No receiver? */
+ return ENODEV;
+
+ /* Prepare message and copy it later */
+ message->size = size;
+ message->sequence_num = chan->nsequence++;
+
+ t = nnpfs_alloc(sizeof(t->this_message) + size, M_NNPFS);
+ t->this_message.error_or_size = sizeof(t->this_message) + size;
+ bcopy(message, &t->msg, size);
+
+ t->this_message.message = &t->msg;
+ nnpfs_appendq(&chan->messageq, &t->this_message);
+ if (chan->status & CHANNEL_WAITING) {
+ chan->status &= ~CHANNEL_WAITING;
+ wakeup((caddr_t) chan);
+ }
+ nnpfs_select_wakeup(chan);
+
+ return 0;
+}
+
+#if defined(SWEXIT)
+#define NNPFS_P_EXIT SWEXIT
+#elif defined(P_WEXIT)
+#define NNPFS_P_EXIT P_WEXIT
+#else
+#error what is your exit named ?
+#endif
+
+#if defined(HAVE_STRUCT_PROC_P_SIGMASK) || defined(HAVE_STRUCT_PROC_P_SIGCTX) || defined(HAVE_STRUCT_PROC_P_SIGWAITMASK) || defined(__osf__) || defined(HAVE_FREEBSD_THREAD)
+static void
+nnpfs_block_sigset (sigset_t *sigset)
+{
+
+#if defined(__sigaddset)
+#define nnpfs_sig_block(ss,signo) __sigaddset((ss), (signo))
+#elif defined(SIGADDSET)
+#define nnpfs_sig_block(ss,signo) SIGADDSET(*(ss), (signo))
+#else
+#define nnpfs_sig_block(ss,signo) *(ss) |= sigmask(signo)
+#endif
+
+ nnpfs_sig_block(sigset, SIGIO);
+ nnpfs_sig_block(sigset, SIGALRM);
+ nnpfs_sig_block(sigset, SIGVTALRM);
+ nnpfs_sig_block(sigset, SIGCHLD);
+#ifdef SIGINFO
+ nnpfs_sig_block(sigset, SIGINFO);
+#endif
+#undef nnpfs_sig_block
+}
+#endif
+
+/*
+ * Send a message to user space and wait for reply.
+ */
+
+int
+nnpfs_message_rpc(int fd, struct nnpfs_message_header * message, u_int size,
+ d_thread_t *proc)
+{
+ int ret;
+ struct nnpfs_channel *chan = &nnpfs_channel[fd];
+ struct nnpfs_link *this_message;
+ struct nnpfs_link *this_process;
+ struct nnpfs_message_header *msg;
+#if defined(HAVE_STRUCT_PROC_P_SIGMASK) || defined(HAVE_STRUCT_PROC_P_SIGCTX) || defined(__osf__) || defined(HAVE_FREEBSD_THREAD)
+ sigset_t oldsigmask;
+#endif
+ int catch;
+
+ NNPFSDEB(XDEBMSG, ("nnpfs_message_rpc opcode = %d\n", message->opcode));
+
+ if (proc == NULL) {
+#ifdef HAVE_FREEBSD_THREAD
+ proc = nnpfs_curthread();
+#else
+ proc = nnpfs_curproc();
+#endif
+ }
+ if (!(chan->status & CHANNEL_OPENED)) /* No receiver? */
+ return ENODEV;
+
+#ifdef HAVE_FREEBSD_THREAD
+ if (chan->proc != NULL && chan->proc->td_proc != NULL &&
+ proc->td_proc->p_pid == chan->proc->td_proc->p_pid) {
+ printf("nnpfs_message_rpc: deadlock avoided "
+ "pid = %u == %u\n", proc->td_proc->p_pid, chan->proc->td_proc->p_pid);
+#else
+ if (chan->proc != NULL && proc->p_pid == chan->proc->p_pid) {
+ printf("nnpfs_message_rpc: deadlock avoided "
+ "pid = %u == %u\n", proc->p_pid, chan->proc->p_pid);
+#endif
+#if 0
+ psignal (proc, SIGABRT);
+#endif
+ return EDEADLK;
+ }
+
+ if (size < sizeof(struct nnpfs_message_wakeup)) {
+ printf("NNPFS PANIC Error: Message to small to receive wakeup, opcode = %d\n", message->opcode);
+ return ENOMEM;
+ }
+ this_message = nnpfs_alloc(sizeof(struct nnpfs_link), M_NNPFS_LINK);
+ this_process = nnpfs_alloc(sizeof(struct nnpfs_link), M_NNPFS_LINK);
+ msg = nnpfs_alloc(size, M_NNPFS_MSG);
+ bcopy(message, msg, size);
+
+ msg->size = size;
+ msg->sequence_num = chan->nsequence++;
+ this_message->error_or_size = 0;
+ this_message->message = msg;
+ this_process->message = msg;
+ nnpfs_appendq(&chan->messageq, this_message);
+ nnpfs_appendq(&chan->sleepq, this_process);
+ nnpfs_select_wakeup(chan);
+ this_process->error_or_size = 0;
+
+ if (chan->status & CHANNEL_WAITING) {
+ chan->status &= ~CHANNEL_WAITING;
+ wakeup((caddr_t) chan);
+ }
+
+ /*
+ * Remove signals from the sigmask so no IO will wake us up from
+ * tsleep(). We don't want to wake up from since program (emacs,
+ * bash & co can't handle them.
+ */
+
+#ifdef HAVE_FREEBSD_THREAD
+ /* FreeBSD 5.1 */
+ oldsigmask = proc->td_sigmask;
+ nnpfs_block_sigset (&proc->td_sigmask);
+#elif HAVE_STRUCT_PROC_P_SIGMASK
+ /* NetBSD 1.5, Darwin 1.3, FreeBSD 4.3, 5.0, OpenBSD 2.8 */
+ oldsigmask = proc->p_sigmask;
+ nnpfs_block_sigset (&proc->p_sigmask);
+#elif defined(HAVE_STRUCT_PROC_P_SIGCTX)
+ /* NetBSD 1.6 */
+ oldsigmask = proc->p_sigctx.ps_sigmask;
+ nnpfs_block_sigset (&proc->p_sigctx.ps_sigmask);
+#elif defined(HAVE_STRUCT_PROC_P_SIGWAITMASK)
+ /* OSF 4.0 */
+ oldsigmask = proc->p_sigwaitmask;
+ nnpfs_block_sigset (&proc->p_sigwaitmask);
+#elif defined(__osf__)
+ /* OSF 5.0 */
+ oldsigmask = u.u_sigmask;
+ nnpfs_block_sigset (&u.u_sigmask);
+#endif
+
+ /*
+ * if we are exiting we should not try to catch signals, since
+ * there might not be enough context left in the process to handle
+ * signal delivery, and besides, most BSD-variants ignore all
+ * signals while closing anyway.
+ */
+
+ catch = 0;
+#ifdef HAVE_FREEBSD_THREAD
+ if (!(proc->td_proc->p_flag & NNPFS_P_EXIT))
+#else
+ if (!(proc->p_flag & NNPFS_P_EXIT))
+#endif
+ catch |= PCATCH;
+
+ /*
+ * We have to check if we have a receiver here too because the
+ * daemon could have terminated before we sleep. This seems to
+ * happen sometimes when rebooting. */
+
+ if (!(chan->status & CHANNEL_OPENED)) {
+ NNPFSDEB(XDEBMSG, ("nnpfs_message_rpc: channel went away\n"));
+ this_process->error_or_size = EINTR;
+ } else if ((ret = tsleep((caddr_t) this_process,
+ (PZERO + 1) | catch, "nnpfs", 0)) != 0) {
+ NNPFSDEB(XDEBMSG, ("caught signal (%d): %ld\n",
+ ret, nnpfs_cursig(proc)));
+ this_process->error_or_size = EINTR;
+ }
+
+#ifdef HAVE_FREEBSD_THREAD
+ proc->td_sigmask = oldsigmask;
+#elif HAVE_STRUCT_PROC_P_SIGMASK
+ proc->p_sigmask = oldsigmask;
+#elif defined(HAVE_STRUCT_PROC_P_SIGCTX)
+ proc->p_sigctx.ps_sigmask = oldsigmask;
+#elif defined(HAVE_STRUCT_PROC_P_SIGWAITMASK)
+ proc->p_sigwaitmask = oldsigmask;
+#elif defined(__osf__)
+ u.u_sigmask = oldsigmask;
+#endif
+
+ /*
+ * Caught signal, got reply message or device was closed.
+ * Need to clean up both messageq and sleepq.
+ */
+ if (nnpfs_onq(this_message)) {
+ nnpfs_outq(this_message);
+ }
+ if (nnpfs_onq(this_process)) {
+ nnpfs_outq(this_process);
+ }
+ ret = this_process->error_or_size;
+
+ NNPFSDEB(XDEBMSG, ("nnpfs_message_rpc this_process->error_or_size = %d\n",
+ this_process->error_or_size));
+ NNPFSDEB(XDEBMSG, ("nnpfs_message_rpc opcode ((nnpfs_message_wakeup*)(this_process->message))->error = %d\n", ((struct nnpfs_message_wakeup *) (this_process->message))->error));
+
+ bcopy(msg, message, size);
+
+ nnpfs_free(this_message, sizeof(*this_message), M_NNPFS_LINK);
+ nnpfs_free(this_process, sizeof(*this_process), M_NNPFS_LINK);
+ nnpfs_free(msg, size, M_NNPFS_MSG);
+
+ return ret;
+}
+
+/*
+ * For each message type there is a message handler
+ * that implements its action, nnpfs_message_receive
+ * invokes the correct function.
+ */
+int
+nnpfs_message_receive(int fd,
+ struct nnpfs_message_header *message,
+ u_int size,
+ d_thread_t *p)
+{
+ NNPFSDEB(XDEBMSG, ("nnpfs_message_receive opcode = %d\n", message->opcode));
+
+ /* Dispatch and coerce message type */
+ switch (message->opcode) {
+ case NNPFS_MSG_WAKEUP:
+ return nnpfs_message_wakeup(fd,
+ (struct nnpfs_message_wakeup *) message,
+ message->size,
+ p);
+ case NNPFS_MSG_WAKEUP_DATA:
+ return nnpfs_message_wakeup_data(fd,
+ (struct nnpfs_message_wakeup_data *) message,
+ message->size,
+ p);
+ case NNPFS_MSG_INSTALLROOT:
+ return nnpfs_message_installroot(fd,
+ (struct nnpfs_message_installroot *) message,
+ message->size,
+ p);
+ case NNPFS_MSG_INSTALLNODE:
+ return nnpfs_message_installnode(fd,
+ (struct nnpfs_message_installnode *) message,
+ message->size,
+ p);
+ case NNPFS_MSG_INSTALLATTR:
+ return nnpfs_message_installattr(fd,
+ (struct nnpfs_message_installattr *) message,
+ message->size,
+ p);
+ case NNPFS_MSG_INSTALLDATA:
+ return nnpfs_message_installdata(fd,
+ (struct nnpfs_message_installdata *) message,
+ message->size,
+ p);
+ case NNPFS_MSG_INVALIDNODE:
+ return nnpfs_message_invalidnode(fd,
+ (struct nnpfs_message_invalidnode *) message,
+ message->size,
+ p);
+ case NNPFS_MSG_UPDATEFID:
+ return nnpfs_message_updatefid(fd,
+ (struct nnpfs_message_updatefid *)message,
+ message->size,
+ p);
+ case NNPFS_MSG_GC_NODES:
+ return nnpfs_message_gc_nodes(fd,
+ (struct nnpfs_message_gc_nodes *)message,
+ message->size,
+ p);
+ case NNPFS_MSG_VERSION:
+ return nnpfs_message_version(fd,
+ (struct nnpfs_message_version *)message,
+ message->size,
+ p);
+ default:
+ printf("NNPFS PANIC Warning nnpfs_dev: Unknown message opcode == %d\n",
+ message->opcode);
+ return EINVAL;
+ }
+}
+
+int
+nnpfs_message_wakeup(int fd,
+ struct nnpfs_message_wakeup *message,
+ u_int size,
+ d_thread_t *p)
+{
+ struct nnpfs_channel *chan = &nnpfs_channel[fd];
+ struct nnpfs_link *sleepq = &chan->sleepq;
+ struct nnpfs_link *t = chan->sleepq.next; /* Really first in q */
+
+ NNPFSDEB(XDEBMSG, ("nnpfs_message_wakeup error: %d\n", message->error));
+
+ for (; t != sleepq; t = t->next)
+ if (t->message->sequence_num == message->sleepers_sequence_num) {
+ if (t->message->size < size) {
+ printf("NNPFS PANIC Error: Could not wakeup requestor with opcode = %d properly, to small receive buffer.\n", t->message->opcode);
+ t->error_or_size = ENOMEM;
+ } else
+ bcopy(message, t->message, size);
+
+ wakeup((caddr_t) t);
+ break;
+ }
+
+ return 0;
+}
+
+int
+nnpfs_message_wakeup_data(int fd,
+ struct nnpfs_message_wakeup_data * message,
+ u_int size,
+ d_thread_t *p)
+{
+ struct nnpfs_channel *chan = &nnpfs_channel[fd];
+ struct nnpfs_link *sleepq = &chan->sleepq;
+ struct nnpfs_link *t = chan->sleepq.next; /* Really first in q */
+
+ NNPFSDEB(XDEBMSG, ("nnpfs_message_wakeup_data error: %d\n", message->error));
+
+ for (; t != sleepq; t = t->next)
+ if (t->message->sequence_num == message->sleepers_sequence_num) {
+ if (t->message->size < size) {
+ printf("NNPFS PANIC Error: Could not wakeup requestor with opcode = %d properly, to small receive buffer.\n", t->message->opcode);
+ t->error_or_size = ENOMEM;
+ } else
+ bcopy(message, t->message, size);
+ wakeup((caddr_t) t);
+ break;
+ }
+ return 0;
+}
+
+/*
+ *
+ */
+int
+nnpfs_uprintf_device(void)
+{
+#if 0
+ int i;
+
+ for (i = 0; i < NNNPFS; i++) {
+ uprintf("nnpfs_channel[%d] = {\n", i);
+ uprintf("messageq.next = %lx ", nnpfs_channel[i].messageq.next);
+ uprintf("messageq.prev = %lx ", nnpfs_channel[i].messageq.prev);
+ uprintf("sleepq.next = %lx ", nnpfs_channel[i].sleepq.next);
+ uprintf("sleepq.prev = %lx ", nnpfs_channel[i].sleepq.prev);
+ uprintf("nsequence = %d status = %d\n",
+ nnpfs_channel[i].nsequence,
+ nnpfs_channel[i].status);
+ uprintf("}\n");
+ }
+#endif
+ return 0;
+}
diff --git a/sys/nnpfs/nnpfs_dev.h b/sys/nnpfs/nnpfs_dev.h
new file mode 100644
index 00000000000..a588bf0b178
--- /dev/null
+++ b/sys/nnpfs/nnpfs_dev.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $arla: nnpfs_dev.h,v 1.19 2003/01/19 20:53:52 lha Exp $ */
+
+#ifndef _nnpfs_dev_h
+#define _nnpfs_dev_h
+
+/*
+ * Queues of nnpfs_links hold outbound messages and processes sleeping
+ * for replies. The last field is used to return error to sleepers and
+ * to keep record of memory to be deallocated when messages have been
+ * delivered or dropped.
+ */
+
+struct nnpfs_link {
+ struct nnpfs_link *prev, *next;
+ struct nnpfs_message_header *message;
+ u_int error_or_size; /* error on sleepq and size on
+ * messageq */
+};
+
+struct nnpfs_channel {
+ struct nnpfs_link messageq; /* Messages not yet read */
+ struct nnpfs_link sleepq; /* Waiting for reply message */
+ u_int nsequence;
+#ifdef __osf__
+ sel_queue_t sel_q;
+#else
+ struct selinfo selinfo;
+#endif
+ struct nnpfs_message_header *message_buffer;
+ int status;
+#define CHANNEL_OPENED 0x1
+#define CHANNEL_WAITING 0x2
+ d_thread_t *proc;
+};
+
+extern struct nnpfs_channel nnpfs_channel[NNNPFS];
+
+/*
+ * These are variant dependent
+ */
+
+void nnpfs_select_wakeup(struct nnpfs_channel *);
+
+int nnpfs_install_device(void);
+int nnpfs_uninstall_device(void);
+
+int nnpfs_install_filesys(void);
+int nnpfs_may_uninstall_filesys(void);
+int nnpfs_uninstall_filesys(void);
+
+int nnpfs_stat_filesys(void);
+int nnpfs_stat_device(void);
+
+/*
+ * And these should be generic
+ */
+
+void
+nnpfs_initq(struct nnpfs_link *q);
+
+int
+nnpfs_emptyq(const struct nnpfs_link *q);
+
+int
+nnpfs_onq(const struct nnpfs_link *link);
+
+void
+nnpfs_appendq(struct nnpfs_link *q, struct nnpfs_link *p);
+
+void
+nnpfs_outq(struct nnpfs_link *p);
+
+int
+nnpfs_devopen_common(dev_t dev);
+
+#ifndef __osf__ /* XXX - we should do the same for osf */
+int nnpfs_devopen(dev_t dev, int flag, int devtype, d_thread_t *proc);
+int nnpfs_devclose(dev_t dev, int flag, int devtype, d_thread_t *proc);
+int nnpfs_devioctl(dev_t dev, u_long cmd, caddr_t data, int flags,
+ d_thread_t *p);
+#ifdef HAVE_THREE_ARGUMENT_SELRECORD
+int nnpfs_devselect(dev_t dev, int which, void *wql, d_thread_t *p);
+#else
+int nnpfs_devselect(dev_t dev, int which, d_thread_t *p);
+#endif
+int nnpfs_devpoll(dev_t dev, int events, d_thread_t *p);
+#endif /* ! __osf__ */
+
+int
+nnpfs_devclose_common(dev_t dev, d_thread_t *p);
+
+int
+nnpfs_devread(dev_t dev, struct uio * uiop, int ioflag);
+
+int
+nnpfs_devwrite(dev_t dev, struct uio *uiop, int ioflag);
+
+int
+nnpfs_message_send(int fd, struct nnpfs_message_header * message, u_int size);
+
+int
+nnpfs_message_rpc(int fd, struct nnpfs_message_header * message, u_int size,
+ d_thread_t *p);
+
+int
+nnpfs_message_receive(int fd,
+ struct nnpfs_message_header *message,
+ u_int size,
+ d_thread_t *p);
+
+int
+nnpfs_message_wakeup(int fd,
+ struct nnpfs_message_wakeup *message,
+ u_int size,
+ d_thread_t *p);
+
+int
+nnpfs_message_wakeup_data(int fd,
+ struct nnpfs_message_wakeup_data * message,
+ u_int size,
+ d_thread_t *p);
+
+int
+nnpfs_uprintf_device(void);
+
+int
+nnpfs_is_nnpfs_dev (dev_t dev);
+
+#endif /* _nnpfs_dev_h */
diff --git a/sys/nnpfs/nnpfs_extern.h b/sys/nnpfs/nnpfs_extern.h
new file mode 100644
index 00000000000..31a8f013e65
--- /dev/null
+++ b/sys/nnpfs/nnpfs_extern.h
@@ -0,0 +1,55 @@
+/* $OpenBSD: nnpfs_extern.h,v 1.1 2009/06/03 14:45:54 jj Exp $ */
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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 _NNPFS_NNPFS_EXTERN_H_
+#define _NNPFS_NNPFS_EXTERN_H_
+
+#ifdef _KERNEL
+
+int nnpfs_devopen(dev_t dev, int flags, int devtype, struct proc * p);
+int nnpfs_devclose(dev_t dev, int flags, int devtype, struct proc * p);
+int nnpfs_devread(dev_t dev, struct uio * uiop, int ioflag);
+int nnpfs_devwrite(dev_t dev, struct uio *uiop, int ioflag);
+int nnpfs_devioctl(dev_t dev, u_long cmd, caddr_t data, int flags,
+ struct proc * p);
+int nnpfs_devpoll(dev_t dev, int events, struct proc * p);
+
+#endif /* _KERNEL */
+
+#endif
diff --git a/sys/nnpfs/nnpfs_fs.h b/sys/nnpfs/nnpfs_fs.h
new file mode 100644
index 00000000000..34cb2540fef
--- /dev/null
+++ b/sys/nnpfs/nnpfs_fs.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $arla: nnpfs_fs.h,v 1.22 2002/12/19 09:49:19 lha Exp $ */
+
+#ifndef _nnpfs_h
+#define _nnpfs_h
+
+#include <sys/types.h>
+
+#include <nnpfs/nnpfs_common.h>
+#include <nnpfs/nnpfs_node.h>
+#include <nnpfs/nnpfs_attr.h>
+
+#define NNNPFS 2 /* maximal number of filesystems on a single device */
+
+/*
+ * Filesystem struct.
+ */
+
+struct nnpfs {
+ u_int status; /* Inited, opened or mounted */
+#define NNPFS_MOUNTED 0x1
+ struct mount *mp;
+ struct nnpfs_node *root;
+ u_int nnodes;
+ int fd;
+ struct nnpfs_nodelist_head nodehead;
+};
+
+#ifdef __osf__
+#ifdef HAVE_STRUCT_MOUNT_M_INFO
+#define VFS_TO_NNPFS(v) ((struct nnpfs *) ((v)->m_info))
+#define VFS_ASSIGN(v, val) do { (v)->m_info = (void *) (val); } while (0)
+#else
+#define VFS_TO_NNPFS(v) ((struct nnpfs *) ((v)->m_data))
+#define VFS_ASSIGN(v, val) do { (v)->m_data = (void *) (val); } while (0)
+#endif
+#else
+#define VFS_TO_NNPFS(v) ((struct nnpfs *) ((v)->mnt_data))
+#define VFS_ASSIGN(v, val) do { (v)->mnt_data = (void *) (val); } while (0)
+#endif
+#define NNPFS_TO_VFS(x) ((x)->mp)
+
+#define NNPFS_FROM_VNODE(vp) VFS_TO_NNPFS((vp)->v_mount)
+#define NNPFS_FROM_XNODE(xp) NNPFS_FROM_VNODE(XNODE_TO_VNODE(xp))
+
+extern struct nnpfs nnpfs[];
+
+extern struct vnodeops nnpfs_vnodeops;
+
+int new_nnpfs_node(struct nnpfs *, struct nnpfs_msg_node *, struct nnpfs_node **,
+ d_thread_t *);
+void free_nnpfs_node(struct nnpfs_node *);
+int free_all_nnpfs_nodes(struct nnpfs *, int, int);
+
+int nnpfs_dnlc_enter(struct vnode *, nnpfs_componentname *, struct vnode *);
+int nnpfs_dnlc_enter_name(struct vnode *, const char *, struct vnode *);
+void nnpfs_dnlc_purge_mp(struct mount *);
+void nnpfs_dnlc_purge(struct vnode *);
+int nnpfs_dnlc_lookup(struct vnode *, nnpfs_componentname *, struct vnode **);
+int nnpfs_dnlc_lookup_name(struct vnode *, const char *, struct vnode **);
+
+void vattr2nnpfs_attr(const struct vattr *, struct nnpfs_attr *);
+void nnpfs_attr2vattr(const struct nnpfs_attr *, struct vattr *, int);
+
+int nnpfs_has_pag(const struct nnpfs_node *, nnpfs_pag_t);
+
+#endif /* _nnpfs_h */
diff --git a/sys/nnpfs/nnpfs_global.h b/sys/nnpfs/nnpfs_global.h
new file mode 100644
index 00000000000..bc956bf40a1
--- /dev/null
+++ b/sys/nnpfs/nnpfs_global.h
@@ -0,0 +1,8 @@
+#ifndef __NNPFS_GLOBAL_H
+#define __NNPFS_GLOBAL_H
+
+#ifndef RCSID
+#define RCSID(msg)
+#endif /* RCSID */
+
+#endif /* __NNPFS_GLOBAL_H */
diff --git a/sys/nnpfs/nnpfs_locl.h b/sys/nnpfs/nnpfs_locl.h
new file mode 100644
index 00000000000..8107315235a
--- /dev/null
+++ b/sys/nnpfs/nnpfs_locl.h
@@ -0,0 +1,424 @@
+/*
+ * Copyright (c) 1995 - 2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $arla: nnpfs_locl.h,v 1.72 2003/02/15 16:40:00 lha Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#else
+#include <nnpfs/nnpfs_config.h>
+#endif
+
+#ifndef RCSID
+#define RCSID(x)
+#endif
+
+#ifdef __osf__
+
+#ifdef __GNUC__
+#define asm __foo_asm
+#endif
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/uio.h>
+#include <machine/cpu.h>
+#include <sys/conf.h>
+#include <sys/sysconfig.h>
+#include <sys/file.h>
+#include <sys/malloc.h>
+#include <sys/poll.h>
+#include <sys/ioctl.h>
+#include <sys/fcntl.h>
+#include <sys/vfs_proto.h>
+#include <io/common/devdriver.h>
+#include <vm/vm_page.h>
+#include <vm/vm_vppage.h>
+#include <vm/vm_ubc.h>
+
+typedef short int16_t;
+typedef unsigned short uint16_t;
+typedef int int32_t;
+typedef unsigned int uint32_t;
+
+#define VT_AFS VT_ADDON
+#define MOUNT_NNPFS MOUNT_PC
+
+typedef struct nameidata nnpfs_componentname;
+
+/* XXX this is gross, but makes the code considerably more readable */
+#if 0
+#define componentname nameidata
+#endif
+
+#define cn_nameptr ni_ptr
+#define cn_namelen ni_namelen
+#define cn_hash ni_hash
+#define cn_cred ni_cred
+#define cn_nameiop ni_nameiop
+#define cn_flags ni_flags
+
+#define mnt_stat m_stat
+#define mnt_flag m_flag
+
+#define NDINIT(ndp, op, flags, segflg, namep, p) \
+ (ndp)->ni_nameiop = (op) | (flags); \
+ (ndp)->ni_segflg = segflg; \
+ (ndp)->ni_dirp = namep;
+
+#define LOCKLEAF 0
+
+#define FFLAGS(mode) ((mode) - FOPEN)
+
+/* 4.4BSD vput does VOP_UNLOCK + vrele, but it seems as if we only
+ should do a vrele here */
+#define vput(VP) vrele(VP)
+
+#define nnpfs_uio_to_proc(uiop) (u.u_procp)
+#define nnpfs_cnp_to_proc(cnp) (u.u_procp)
+#define nnpfs_proc_to_cred(p) ((p)->p_rcred)
+#define nnpfs_proc_to_euid(p) ((p)->p_rcred->cr_uid)
+
+#define nnpfs_curproc() (u.u_procp)
+
+#define nnpfs_vop_read VOP_READ
+#define nnpfs_vop_write VOP_WRITE
+#define nnpfs_vop_getattr(t, attr, cred, proc, error) VOP_GETATTR((t), (attr), (cred), (error))
+#define nnpfs_vop_access(dvp, mode, cred, proc, error) VOP_ACCESS((dvp), (mode), (cred), (error))
+
+struct vop_generic_args;
+
+typedef u_long va_size_t;
+
+#else /* !__osf__ */
+
+typedef struct componentname nnpfs_componentname;
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/proc.h>
+#include <sys/filedesc.h>
+#include <sys/kernel.h>
+#ifdef HAVE_SYS_MODULE_H
+#include <sys/module.h>
+#endif
+#include <sys/systm.h>
+#include <sys/fcntl.h>
+#ifdef HAVE_SYS_SYSPROTO_H
+#include <sys/sysproto.h>
+#endif
+#include <sys/conf.h>
+#include <sys/mount.h>
+#include <sys/exec.h>
+#ifdef HAVE_SYS_SYSENT_H
+#include <sys/sysent.h>
+#endif
+#ifdef HAVE_SYS_LKM_H
+#include <sys/lkm.h>
+#endif
+#ifdef HAVE_SYS_LOCK_H
+#include <sys/lock.h>
+#endif
+#ifdef HAVE_SYS_MUTEX_H
+#include <sys/mutex.h>
+#endif
+#include <sys/vnode.h>
+#include <sys/errno.h>
+#include <sys/file.h>
+#include <sys/namei.h>
+#include <sys/dirent.h>
+#include <sys/ucred.h>
+#include <sys/selinfo.h>
+#include <sys/uio.h>
+#ifdef HAVE_SYS_POLL_H
+#include <sys/poll.h>
+#endif
+#ifdef HAVE_SYS_SIGNALVAR_H
+#include <sys/signalvar.h>
+#endif
+#ifdef HAVE_SYS_INTTYPES_H
+#include <sys/inttypes.h>
+#endif
+#include <sys/syscall.h>
+#include <sys/queue.h>
+#include <sys/malloc.h>
+#ifdef HAVE_SYS_SYSCALLARGS_H
+#include <sys/syscallargs.h>
+#endif
+#ifdef HAVE_SYS_ATTR_H
+#include <sys/attr.h>
+#endif
+
+#ifdef HAVE_MISCFS_GENFS_GENFS_H
+#include <miscfs/genfs/genfs.h>
+#endif
+#ifdef HAVE_MISCFS_SYNCFS_SYNCFS_H
+#include <miscfs/syncfs/syncfs.h>
+#endif
+#ifndef HAVE_KERNEL_UVM_ONLY
+#ifdef HAVE_VM_VM_H
+#include <vm/vm.h>
+#endif
+#ifdef HAVE_VM_VM_EXTERN_H
+#include <vm/vm_extern.h>
+#endif
+#ifdef HAVE_VM_VM_ZONE_H
+#include <vm/vm_zone.h>
+#endif
+#ifdef HAVE_VM_VM_OBJECT_H
+#include <vm/vm_object.h>
+#endif
+#endif
+#ifdef HAVE_UVM_UVM_EXTERN_H
+#include <uvm/uvm_extern.h>
+#endif
+#ifdef HAVE_VM_UMA_H
+#include <vm/uma.h>
+#endif
+
+#if defined(__APPLE__)
+#include <machine/machine_routines.h>
+#include <mach/machine/vm_types.h>
+#include <sys/ubc.h>
+void cache_purge(struct vnode *);
+int cache_lookup(struct vnode *, struct vnode **, struct componentname *);
+void cache_enter(struct vnode *, struct vnode *, struct componentname *);
+void cache_purgevfs(struct mount *);
+#endif
+
+#define nnpfs_vop_read(t, uio, ioflag, cred, error) (error) = VOP_READ((t), (uio), (ioflag), (cred))
+#define nnpfs_vop_write(t, uio, ioflag, cred, error) (error) = VOP_WRITE((t), (uio), (ioflag), (cred))
+#define nnpfs_vop_getattr(t, attr, cred, proc, error) (error) = VOP_GETATTR((t), (attr), (cred), (proc))
+#define nnpfs_vop_access(dvp, mode, cred, proc, error) (error) = VOP_ACCESS((dvp), (mode), (cred), (proc))
+
+typedef u_quad_t va_size_t;
+
+#endif /* !__osf__ */
+
+#ifdef __FreeBSD_version
+#if __FreeBSD_version < 400000
+# error This version is unsupported
+#elif __FreeBSD_version < 440001 || (__FreeBSD_version >= 500000 && __FreeBSD_version < 500023)
+typedef struct proc d_thread_t;
+#elif __FreeBSD_version == 500023
+# define HAVE_FREEBSD_THREAD
+typedef struct thread d_thread_t;
+#elif __FreeBSD_version >= 500024
+# define HAVE_FREEBSD_THREAD
+#endif
+typedef d_thread_t syscall_d_thread_t;
+#define syscall_thread_to_thread(x) (x)
+#else /* !__FreeBSD_version */
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 106130000
+typedef struct lwp syscall_d_thread_t;
+#define syscall_thread_to_thread(x) ((x)->l_proc)
+#else
+typedef struct proc syscall_d_thread_t;
+#define syscall_thread_to_thread(x) (x)
+#endif
+typedef struct proc d_thread_t;
+#endif /* !__FreeBSD_version */
+
+#ifdef VV_ROOT
+#define NNPFS_MAKE_VROOT(v) ((v)->v_vflag |= VV_ROOT) /* FreeBSD 5 */
+#else
+#define NNPFS_MAKE_VROOT(v) ((v)->v_flag |= VROOT)
+#endif
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 105280000
+#include <miscfs/genfs/genfs.h>
+#include <miscfs/genfs/genfs_node.h>
+
+struct genfs_ops nnpfs_genfsops;
+#endif
+
+
+#if defined(HAVE_FREEBSD_THREAD)
+#define nnpfs_uio_to_thread(uiop) ((uiop)->uio_td)
+#define nnpfs_cnp_to_thread(cnp) ((cnp)->cn_thread)
+#define nnpfs_thread_to_cred(td) ((td)->td_proc->p_ucred)
+#define nnpfs_thread_to_euid(td) ((td)->td_proc->p_ucred->cr_uid)
+#else
+#define nnpfs_uio_to_proc(uiop) ((uiop)->uio_procp)
+#define nnpfs_cnp_to_proc(cnp) ((cnp)->cn_proc)
+#define nnpfs_proc_to_cred(p) ((p)->p_ucred)
+#define nnpfs_proc_to_euid(p) ((p)->p_ucred->cr_uid)
+#endif
+
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 500043
+extern const char *VT_AFS;
+#endif
+
+#if defined(__FreeBSD__)
+typedef void * nnpfs_malloc_type;
+#elif defined(__NetBSD__) && __NetBSD_Version__ >= 106140000 /* 1.6N */
+typedef struct malloc_type * nnpfs_malloc_type;
+#else
+typedef int nnpfs_malloc_type;
+#endif
+
+#ifdef __APPLE__
+#define nnpfs_curproc() (current_proc())
+#else
+#if defined(HAVE_FREEBSD_THREAD)
+#define nnpfs_curthread() (curthread)
+#else
+#define nnpfs_curproc() (curproc)
+#endif
+#endif
+
+#ifdef __osf__
+#define nnpfs_pushdirty(vp, cred, p)
+#else
+void nnpfs_pushdirty(struct vnode *, struct ucred *, d_thread_t *);
+#endif
+
+
+#if defined(HAVE_UINTPTR_T) /* c99 enviroment */
+#define nnpfs_uintptr_t uintptr_t
+#else
+#if defined(_LP64) || defined(alpha) || defined(__alpha__) || defined(__sparc64__) || defined(__sparcv9__)
+#define nnpfs_uintptr_t unsigned long long
+#else /* !LP64 */
+#define nnpfs_uintptr_t unsigned long
+#endif /* LP64 */
+#endif
+
+/*
+ * XXX
+ */
+
+#ifndef SCARG
+#if defined(__FreeBSD_version) && __FreeBSD_version > 500042
+#define SCARG(a, b) ((a)->b)
+#define syscallarg(x) x
+#else
+#define SCARG(a, b) ((a)->b.datum)
+#define syscallarg(x) union { x datum; register_t pad; }
+#endif /* __FreeBSD_version */
+#endif /* SCARG */
+
+#ifndef syscallarg
+#define syscallarg(x) x
+#endif
+
+#ifndef HAVE_REGISTER_T
+typedef int register_t;
+#endif
+
+/* malloc(9) waits by default, freebsd post 5.0 choose to remove the flag */
+#ifndef M_WAITOK
+#define M_WAITOK 0
+#endif
+
+#if defined(HAVE_DEF_STRUCT_SETGROUPS_ARGS)
+#define nnpfs_setgroups_args setgroups_args
+#elif defined(HAVE_DEF_STRUCT_SYS_SETGROUPS_ARGS)
+#define nnpfs_setgroups_args sys_setgroups_args
+#elif __osf__
+struct nnpfs_setgroups_args {
+ syscallarg(int) gidsetsize;
+ syscallarg(gid_t) *gidset;
+};
+#elif defined(__APPLE__)
+struct nnpfs_setgroups_args{
+ syscallarg(u_int) gidsetsize;
+ syscallarg(gid_t) *gidset;
+};
+#else
+#error what is you setgroups named ?
+#endif
+
+
+#ifdef HAVE_KERNEL_VFS_GETVFS
+#define nnpfs_vfs_getvfs vfs_getvfs
+#else
+#define nnpfs_vfs_getvfs getvfs
+#endif
+
+#ifdef HAVE_FOUR_ARGUMENT_VFS_OBJECT_CREATE
+#define nnpfs_vfs_object_create(vp,proc,ucred) vfs_object_create(vp,proc,ucred,TRUE)
+#else
+#define nnpfs_vfs_object_create(vp,proc,ucred) vfs_object_create(vp,proc,ucred)
+#endif
+
+#if defined(UVM) || (defined(__NetBSD__) && __NetBSD_Version__ >= 105280000)
+#define nnpfs_set_vp_size(vp, sz) uvm_vnp_setsize(vp, sz)
+#elif HAVE_KERNEL_VNODE_PAGER_SETSIZE
+#define nnpfs_set_vp_size(vp, sz) vnode_pager_setsize(vp, sz)
+#elif defined(__APPLE__)
+#define nnpfs_set_vp_size(vp, sz) ubc_setsize(vp, sz)
+#else
+#define nnpfs_set_vp_size(vp, sz)
+#endif
+
+/* namei flag */
+#ifdef LOCKLEAF
+#define NNPFS_LOCKLEAF LOCKLEAF
+#else
+#define NNPFS_LOCKLEAF 0
+#endif
+
+#ifdef NEED_VGONEL_PROTO
+void vgonel (struct vnode *vp, d_thread_t *p);
+#endif
+
+#ifdef NEED_ISSIGNAL_PROTO
+int issignal (d_thread_t *);
+#endif
+
+#ifdef NEED_STRNCMP_PROTO
+int strncmp (const char *, const char *, size_t);
+#endif
+
+#ifdef NEED_VN_WRITECHK_PROTO
+int vn_writechk (struct vnode *);
+#endif
+
+#ifdef NEED_UBC_PUSHDIRTY_PROTO
+int ubc_pushdirty (struct vnode *);
+#endif
+
+#include <nnpfs/nnpfs_syscalls.h>
+
+/*
+ * The VOP table
+ *
+ * What VOPs do we have today ?
+ */
+
+#define NNPFS_VOP_DEF(n) \
+ struct vop_##n##_args; \
+ int nnpfs_##n(struct vop_##n##_args *);
+
+#include "nnpfs/nnpfs_vopdefs.h"
diff --git a/sys/nnpfs/nnpfs_message.c b/sys/nnpfs/nnpfs_message.c
new file mode 100644
index 00000000000..12f07ccdd5c
--- /dev/null
+++ b/sys/nnpfs/nnpfs_message.c
@@ -0,0 +1,525 @@
+/*
+ * Copyright (c) 1995 - 2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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 <nnpfs/nnpfs_locl.h>
+#include <nnpfs/nnpfs_deb.h>
+#include <nnpfs/nnpfs_fs.h>
+#include <nnpfs/nnpfs_message.h>
+#include <nnpfs/nnpfs_msg_locl.h>
+#include <nnpfs/nnpfs_syscalls.h>
+#include <nnpfs/nnpfs_vfsops.h>
+#include <nnpfs/nnpfs_vnodeops.h>
+#include <nnpfs/nnpfs_dev.h>
+
+RCSID("$arla: nnpfs_message.c,v 1.84 2003/06/02 18:25:20 lha Exp $");
+
+static void
+send_inactive_node(int fd, nnpfs_handle *handle)
+{
+ struct nnpfs_message_inactivenode msg;
+
+ msg.header.opcode = NNPFS_MSG_INACTIVENODE;
+ msg.handle = *handle;
+ msg.flag = NNPFS_NOREFS | NNPFS_DELETE;
+ nnpfs_message_send(fd, &msg.header, sizeof(msg));
+}
+
+
+int
+nnpfs_message_installroot(int fd,
+ struct nnpfs_message_installroot * message,
+ u_int size,
+ d_thread_t *p)
+{
+ int error = 0;
+
+ NNPFSDEB(XDEBMSG, ("nnpfs_message_installroot (%d,%d,%d,%d)\n",
+ message->node.handle.a,
+ message->node.handle.b,
+ message->node.handle.c,
+ message->node.handle.d));
+
+ if (nnpfs[fd].root != NULL) {
+ printf("NNPFS PANIC WARNING! nnpfs_message_installroot: called again!\n");
+ error = EBUSY;
+ } else {
+ error = new_nnpfs_node(&nnpfs[fd], &message->node, &nnpfs[fd].root, p);
+ if (error)
+ return error;
+ NNPFS_MAKE_VROOT(nnpfs[fd].root->vn);
+ }
+ return error;
+}
+
+int
+nnpfs_message_installnode(int fd,
+ struct nnpfs_message_installnode * message,
+ u_int size,
+ d_thread_t *p)
+{
+ int error = 0;
+ struct nnpfs_node *n, *dp;
+
+ NNPFSDEB(XDEBMSG, ("nnpfs_message_installnode (%d,%d,%d,%d)\n",
+ message->node.handle.a,
+ message->node.handle.b,
+ message->node.handle.c,
+ message->node.handle.d));
+
+retry:
+ dp = nnpfs_node_find(&nnpfs[fd].nodehead, &message->parent_handle);
+ if (dp) {
+ struct vnode *t_vnode = XNODE_TO_VNODE(dp);
+
+ NNPFSDEB(XDEBMSG, ("nnpfs_message_installnode: t_vnode = %lx\n",
+ (unsigned long)t_vnode));
+
+ if (nnpfs_do_vget(t_vnode, 0 /* LK_SHARED */, p))
+ goto retry;
+
+ error = new_nnpfs_node(&nnpfs[fd], &message->node, &n, p);
+ if (error) {
+ vrele (t_vnode);
+ return error;
+ }
+
+ nnpfs_dnlc_enter_name(t_vnode,
+ message->name,
+ XNODE_TO_VNODE(n));
+ vrele (XNODE_TO_VNODE(n));
+ vrele (t_vnode);
+ } else {
+ printf("NNPFS PANIC WARNING! nnpfs_message_installnode: no parent\n");
+ error = ENOENT;
+ }
+ NNPFSDEB(XDEBMSG, ("return: nnpfs_message_installnode: %d\n", error));
+
+ return error;
+}
+
+int
+nnpfs_message_installattr(int fd,
+ struct nnpfs_message_installattr * message,
+ u_int size,
+ d_thread_t *p)
+{
+ int error = 0;
+ struct nnpfs_node *t;
+
+ NNPFSDEB(XDEBMSG, ("nnpfs_message_installattr (%d,%d,%d,%d) \n",
+ message->node.handle.a,
+ message->node.handle.b,
+ message->node.handle.c,
+ message->node.handle.d));
+
+ t = nnpfs_node_find(&nnpfs[fd].nodehead, &message->node.handle);
+ if (t != 0) {
+ t->tokens = message->node.tokens;
+ if ((t->tokens & NNPFS_DATA_MASK) && DATA_FROM_XNODE(t) == NULL) {
+ printf ("nnpfs_message_installattr: tokens and no data\n");
+ t->tokens &= ~NNPFS_DATA_MASK;
+ }
+ nnpfs_attr2vattr(&message->node.attr, &t->attr, 0);
+ if ((t->flags & NNPFS_VMOPEN) == 0)
+ nnpfs_set_vp_size(XNODE_TO_VNODE(t), t->attr.va_size);
+ bcopy(message->node.id, t->id, sizeof(t->id));
+ bcopy(message->node.rights, t->rights, sizeof(t->rights));
+ t->anonrights = message->node.anonrights;
+ } else {
+ NNPFSDEB(XDEBMSG, ("nnpfs_message_installattr: no such node\n"));
+ }
+
+ return error;
+}
+
+int
+nnpfs_message_installdata(int fd,
+ struct nnpfs_message_installdata * message,
+ u_int size,
+ d_thread_t *p)
+{
+ struct nnpfs_node *t;
+ int error = 0;
+
+ NNPFSDEB(XDEBMSG, ("nnpfs_message_installdata (%d,%d,%d,%d)\n",
+ message->node.handle.a,
+ message->node.handle.b,
+ message->node.handle.c,
+ message->node.handle.d));
+
+retry:
+ t = nnpfs_node_find(&nnpfs[fd].nodehead, &message->node.handle);
+ if (t != NULL) {
+ struct nnpfs_fhandle_t *fh =
+ (struct nnpfs_fhandle_t *)&message->cache_handle;
+ struct vnode *t_vnode = XNODE_TO_VNODE(t);
+ struct vnode *vp;
+
+ message->cache_name[sizeof(message->cache_name)-1] = '\0';
+ NNPFSDEB(XDEBMSG, ("cache_name = '%s'\n", message->cache_name));
+
+ if (nnpfs_do_vget(t_vnode, 0 /* LK_SHARED */, p))
+ goto retry;
+
+ if (message->flag & NNPFS_ID_HANDLE_VALID) {
+ error = nnpfs_fhlookup (p, fh, &vp);
+ } else {
+ error = EINVAL;
+ }
+ if (error != 0) {
+#ifdef __osf__
+ struct nameidata *ndp = &u.u_nd;
+#else
+ struct nameidata nd;
+ struct nameidata *ndp = &nd;
+#endif
+
+ NNPFSDEB(XDEBMSG,
+ ("nnpfs_message_installdata: fhlookup failed: %d, "
+ "opening by name\n", error));
+
+ NDINIT(ndp, LOOKUP, FOLLOW | NNPFS_LOCKLEAF, UIO_SYSSPACE,
+ message->cache_name, p);
+ error = namei(ndp);
+ vp = ndp->ni_vp;
+ }
+
+ if (error == 0) {
+#ifndef __osf__
+ nnpfs_vfs_unlock(vp, p);
+#endif
+ if (DATA_FROM_XNODE(t))
+ vrele(DATA_FROM_XNODE(t));
+ DATA_FROM_XNODE(t) = vp;
+
+ NNPFSDEB(XDEBMSG, ("nnpfs_message_installdata: t = %lx;"
+ " tokens = %x\n",
+ (unsigned long)t, message->node.tokens));
+
+ t->tokens = message->node.tokens;
+ nnpfs_attr2vattr(&message->node.attr, &t->attr, 1);
+ if ((t->flags & NNPFS_VMOPEN) == 0)
+ nnpfs_set_vp_size(XNODE_TO_VNODE(t), t->attr.va_size);
+ if (XNODE_TO_VNODE(t)->v_type == VDIR
+ && (message->flag & NNPFS_ID_INVALID_DNLC))
+ nnpfs_dnlc_purge (XNODE_TO_VNODE(t));
+ bcopy(message->node.id, t->id, sizeof(t->id));
+ bcopy(message->node.rights, t->rights, sizeof(t->rights));
+ t->anonrights = message->node.anonrights;
+ t->offset = message->offset;
+#if 0
+ if (message->flag & NNPFS_ID_AFSDIR)
+ t->flags |= NNPFS_AFSDIR;
+#endif
+ } else {
+ printf("NNPFS PANIC WARNING! nnpfs_message_installdata failed!\n");
+ printf("Reason: lookup failed on cache file '%s', error = %d\n",
+ message->cache_name, error);
+ }
+ vrele (t_vnode);
+ } else {
+ printf("NNPFS PANIC WARNING! nnpfs_message_installdata failed\n");
+ printf("Reason: No node to install the data into!\n");
+ error = ENOENT;
+ }
+
+ return error;
+}
+
+#ifdef __osf__
+#define nnpfs_writecount v_wrcnt
+#else
+#define nnpfs_writecount v_writecount
+#endif
+
+int
+nnpfs_message_invalidnode(int fd,
+ struct nnpfs_message_invalidnode * message,
+ u_int size,
+ d_thread_t *p)
+{
+ int error = 0;
+ struct nnpfs_node *t;
+
+ NNPFSDEB(XDEBMSG, ("nnpfs_message_invalidnode (%d,%d,%d,%d)\n",
+ message->handle.a,
+ message->handle.b,
+ message->handle.c,
+ message->handle.d));
+
+#ifdef __APPLE__
+ retry:
+#endif
+ t = nnpfs_node_find(&nnpfs[fd].nodehead, &message->handle);
+ if (t != 0) {
+ struct vnode *vp = XNODE_TO_VNODE(t);
+
+ /* If open for writing, return immediately. Last close:er wins! */
+ if (vp->v_usecount >= 0 && vp->nnpfs_writecount >= 1)
+ return 0;
+
+#ifdef __FreeBSD__
+ {
+ vm_object_t obj = vp->v_object;
+
+ if (obj != NULL
+ && (obj->ref_count != 0
+#ifdef OBJ_MIGHTBEDIRTY
+ || (obj->flags & OBJ_MIGHTBEDIRTY) != 0
+#endif
+ ))
+ return 0;
+
+ }
+#endif /* __FreeBSD__ */
+
+ /* If node is in use, mark as stale */
+ if (vp->v_usecount > 0 && vp->v_type != VDIR) {
+#ifdef __APPLE__
+ if (vget(vp, 0, p))
+ goto retry;
+
+ if (UBCISVALID(vp) && !ubc_isinuse(vp, 1)) {
+ ubc_setsize(vp, 0);
+ vrele(vp);
+ } else {
+ vrele(vp);
+ t->flags |= NNPFS_STALE;
+ return 0;
+ }
+#else
+ t->flags |= NNPFS_STALE;
+ return 0;
+#endif
+ }
+
+ if (DATA_FROM_XNODE(t)) {
+ vrele(DATA_FROM_XNODE(t));
+ DATA_FROM_XNODE(t) = (struct vnode *) 0;
+ }
+ NNPFS_TOKEN_CLEAR(t, ~0,
+ NNPFS_OPEN_MASK | NNPFS_ATTR_MASK |
+ NNPFS_DATA_MASK | NNPFS_LOCK_MASK);
+ /* Dir changed, must invalidate DNLC. */
+ if (vp->v_type == VDIR)
+ nnpfs_dnlc_purge(vp);
+ if (vp->v_usecount == 0) {
+#ifndef __osf__
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_message_invalidnode: vrecycle\n"));
+ vrecycle(vp, p);
+#else
+ /* XXX */
+#endif /* __osf__ */
+ }
+ } else {
+ NNPFSDEB(XDEBMSG, ("nnpfs_message_invalidnode: no such node\n"));
+ send_inactive_node(fd, &message->handle);
+ error = ENOENT;
+ }
+
+ return error;
+}
+
+int
+nnpfs_message_updatefid(int fd,
+ struct nnpfs_message_updatefid * message,
+ u_int size,
+ d_thread_t *p)
+{
+ int error = 0;
+
+ NNPFSDEB(XDEBMSG, ("nnpfs_message_updatefid (%d,%d,%d,%d) (%d,%d,%d,%d)\n",
+ message->old_handle.a,
+ message->old_handle.b,
+ message->old_handle.c,
+ message->old_handle.d,
+ message->new_handle.a,
+ message->new_handle.b,
+ message->new_handle.c,
+ message->new_handle.d));
+
+ error = nnpfs_update_handle(&nnpfs[fd].nodehead,
+ &message->old_handle,
+ &message->new_handle);
+ if (error)
+ printf ("NNPFS PANIC WARNING! nnpfs_message_updatefid: %d\n", error);
+ return error;
+}
+
+#if __osf__
+
+/*
+ * Try to clean out nodes for the userland daemon
+ */
+
+static void
+gc_vnode (struct vnode *vp,
+ d_thread_t *p)
+{
+ /* This node is on the freelist */
+ if (vp->v_usecount <= 0) {
+
+ /* DIAGNOSTIC */
+ if (vp->v_usecount < 0) {
+ vprint("vrele: bad ref count", vp);
+ panic("vrele: ref cnt");
+ }
+
+ NNPFSDEB(XDEBMSG, ("nnpfs_message_gc: success\n"));
+
+ vgone(vp, VX_NOSLEEP, NULL);
+ } else {
+ NNPFSDEB(XDEBMSG, ("nnpfs_message_gc: used\n"));
+ }
+
+}
+
+
+#else /* !__osf__ */
+
+/*
+ * Try to clean out nodes for the userland daemon
+ */
+
+static void
+gc_vnode (struct vnode *vp,
+ d_thread_t *p)
+{
+#ifdef HAVE_SYS_MUTEX_H
+ mtx_lock(&vp->v_interlock);
+#else
+ simple_lock(&vp->v_interlock);
+#endif
+
+ /* This node is on the freelist */
+ if (vp->v_usecount <= 0) {
+#if __FreeBSD__
+ vm_object_t obj;
+
+ obj = vp->v_object;
+
+ if (obj != NULL
+ && (obj->ref_count != 0
+#ifdef OBJ_MIGHTBEDIRTY
+ || (obj->flags & OBJ_MIGHTBEDIRTY) != 0
+#endif
+ )) {
+#ifdef HAVE_SYS_MUTEX_H
+ mtx_unlock(&vp->v_interlock);
+#else
+ simple_unlock (&vp->v_interlock);
+#endif
+ return;
+ }
+#endif /* __FreeBSD__ */
+
+#ifdef DIAGNOSTIC
+ if (vp->v_usecount < 0 || vp->v_writecount != 0) {
+ vprint("vrele: bad ref count", vp);
+ panic("vrele: ref cnt");
+ }
+#endif /* DIAGNOSTIC */
+
+ NNPFSDEB(XDEBMSG, ("nnpfs_message_gc: success\n"));
+
+#ifdef HAVE_KERNEL_VGONEL
+ vgonel (vp, p);
+#else
+#ifdef HAVE_SYS_MUTEX_H
+ mtx_unlock(&vp->v_interlock);
+#else
+ simple_unlock(&vp->v_interlock);
+#endif
+ vgone (vp);
+#endif
+
+ } else {
+#ifdef HAVE_SYS_MUTEX_H
+ mtx_unlock(&vp->v_interlock);
+#else
+ simple_unlock(&vp->v_interlock);
+#endif
+ NNPFSDEB(XDEBMSG, ("nnpfs_message_gc: used\n"));
+ }
+
+}
+
+#endif
+
+int
+nnpfs_message_gc_nodes(int fd,
+ struct nnpfs_message_gc_nodes *message,
+ u_int size,
+ d_thread_t *p)
+{
+ struct nnpfs_node *node;
+ int i;
+
+ NNPFSDEB(XDEBMSG, ("nnpfs_message_gc\n"));
+
+ for (i = 0; i < message->len; i++) {
+ node = nnpfs_node_find (&nnpfs[fd].nodehead, &message->handle[i]);
+ if (node)
+ gc_vnode(XNODE_TO_VNODE(node), p);
+ else {
+ NNPFSDEB(XDEBMSG, ("nnpfs_message_gc_nodes: no such node\n"));
+ send_inactive_node(fd, &message->handle[i]);
+ }
+ }
+
+ return 0;
+}
+
+
+/*
+ * Probe what version of nnpfs this support
+ */
+
+int
+nnpfs_message_version(int fd,
+ struct nnpfs_message_version *message,
+ u_int size,
+ d_thread_t *p)
+{
+ struct nnpfs_message_wakeup msg;
+ int ret;
+
+ ret = NNPFS_VERSION;
+
+ msg.header.opcode = NNPFS_MSG_WAKEUP;
+ msg.sleepers_sequence_num = message->header.sequence_num;
+ msg.error = ret;
+
+ return nnpfs_message_send(fd,
+ (struct nnpfs_message_header *) &msg, sizeof(msg));
+}
diff --git a/sys/nnpfs/nnpfs_message.h b/sys/nnpfs/nnpfs_message.h
new file mode 100644
index 00000000000..e07d92bd277
--- /dev/null
+++ b/sys/nnpfs/nnpfs_message.h
@@ -0,0 +1,491 @@
+/*
+ * Copyright (c) 1995 - 2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $arla: nnpfs_message.h,v 1.55 2002/09/27 09:43:21 lha Exp $ */
+
+#ifndef _xmsg_h
+#define _xmsg_h
+
+/* bump this for any incompatible changes */
+
+#define NNPFS_VERSION 18
+
+#include <nnpfs/nnpfs_attr.h>
+
+/* Temporary hack? */
+#define MAX_XMSG_SIZE (1024*64)
+
+typedef uint32_t nnpfs_pag_t;
+
+/*
+ * The nnpfs_cred, if pag == 0, use uid
+ */
+typedef struct nnpfs_cred {
+ uint32_t uid;
+ nnpfs_pag_t pag;
+} nnpfs_cred;
+
+typedef uint32_t nnpfs_locktype_t;
+typedef uint32_t nnpfs_lockid_t;
+
+
+#define MAXHANDLE (4*4)
+#define MAXRIGHTS 8
+
+#define NNPFS_ANONYMOUSID 32766
+
+typedef struct nnpfs_handle {
+ uint32_t a, b, c, d;
+} nnpfs_handle;
+
+#define nnpfs_handle_eq(p, q) \
+((p)->a == (q)->a && (p)->b == (q)->b && (p)->c == (q)->c && (p)->d == (q)->d)
+
+/*
+ * This should be the maximum size of any `file handle'
+ */
+
+#define CACHEHANDLESIZE 80
+
+typedef struct nnpfs_cache_handle {
+ u_char data[CACHEHANDLESIZE];
+} nnpfs_cache_handle;
+
+/*
+ * Tokens that apply to nodes, open modes and attributes. Shared
+ * reading might be used for exec and exclusive write for remove.
+ */
+#define NNPFS_OPEN_MASK 0x000f
+#define NNPFS_OPEN_NR 0x0001 /* Normal reading, data might change */
+#define NNPFS_OPEN_SR 0x0002 /* Shared reading, data won't change */
+#define NNPFS_OPEN_NW 0x0004 /* Normal writing, multiple writers */
+#define NNPFS_OPEN_EW 0x0008 /* Exclusive writing (open really) */
+
+#define NNPFS_ATTR_MASK 0x0030
+#define NNPFS_ATTR_R 0x0010 /* Attributes valid */
+#define NNPFS_ATTR_W 0x0020 /* Attributes valid and modifiable */
+
+/*
+ * Tokens that apply to node data.
+ */
+#define NNPFS_DATA_MASK 0x00c0
+#define NNPFS_DATA_R 0x0040 /* Data valid */
+#define NNPFS_DATA_W 0x0080 /* Data valid and modifiable */
+#define NNPFS_LOCK_MASK 0x0300
+#define NNPFS_LOCK_R 0x0100 /* Data Shared locks */
+#define NNPFS_LOCK_W 0x0200 /* Data Exclusive locks */
+
+#define NNPFS_ATTR_VALID NNPFS_ATTR_R
+#define NNPFS_DATA_VALID NNPFS_DATA_W
+
+/* nnpfs_node.flags
+ * The lower 16 bit flags are reserved for common nnpfs flags
+ * The upper 16 bit flags are reserved for operating system dependent
+ * flags.
+ */
+
+#define NNPFS_DATA_DIRTY 0x0001
+#define NNPFS_ATTR_DIRTY 0x0002
+#define NNPFS_AFSDIR 0x0004
+#define NNPFS_STALE 0x0008
+#define NNPFS_XDELETED 0x0010
+#define NNPFS_VMOPEN 0x0020
+
+/*
+ * Token match macros, NNPFS_TOKEN_GOT is depricated and
+ * NNPFS_TOKEN_GOT_* should be used instead.
+ */
+
+/* Are necessary tokens available? */
+#define NNPFS_TOKEN_GOT(xn, tok) ((xn)->tokens & (tok)) /* deprecated */
+#define NNPFS_TOKEN_GOT_ANY(xn, tok) ((xn)->tokens & (tok)) /* at least one must match */
+#define NNPFS_TOKEN_GOT_ALL(xn, tok) (((xn)->tokens & (tok)) == (tok)) /* all tokens must match */
+#define NNPFS_TOKEN_SET(xn, tok, mask) ((xn)->tokens |= ((tok) & (mask)))
+#define NNPFS_TOKEN_CLEAR(xn, tok, mask) ((xn)->tokens &= ~((tok) & (mask)))
+
+/* definitions for the rights fields */
+#define NNPFS_RIGHT_R 0x01 /* may read? */
+#define NNPFS_RIGHT_W 0x02 /* may write? */
+#define NNPFS_RIGHT_X 0x04 /* may execute? */
+
+/* Max name length passed in nnpfs messages */
+
+#define NNPFS_MAX_NAME 256
+#define NNPFS_MAX_SYMLINK_CONTENT 2048
+
+struct nnpfs_msg_node {
+ nnpfs_handle handle;
+ uint32_t tokens;
+ uint32_t pad1;
+ struct nnpfs_attr attr;
+ nnpfs_pag_t id[MAXRIGHTS];
+ u_char rights[MAXRIGHTS];
+ u_char anonrights;
+ uint16_t pad2;
+ uint32_t pad3;
+};
+
+/*
+ * Messages passed through the nnpfs_dev.
+ */
+struct nnpfs_message_header {
+ uint32_t size;
+ uint32_t opcode;
+ uint32_t sequence_num; /* Private */
+ uint32_t pad1;
+};
+
+/*
+ * Used by putdata flag
+ */
+enum { NNPFS_READ = 0x01,
+ NNPFS_WRITE = 0x02,
+ NNPFS_NONBLOCK = 0x04,
+ NNPFS_APPEND = 0x08,
+ NNPFS_FSYNC = 0x10};
+
+/*
+ * Flags for inactivenode
+ */
+enum { NNPFS_NOREFS = 1, NNPFS_DELETE = 2 };
+
+/*
+ * Flags for installdata
+ */
+
+enum { NNPFS_ID_INVALID_DNLC = 0x01, NNPFS_ID_AFSDIR = 0x02,
+ NNPFS_ID_HANDLE_VALID = 0x04 };
+
+/*
+ * Defined message types and their opcodes.
+ */
+#define NNPFS_MSG_VERSION 0
+#define NNPFS_MSG_WAKEUP 1
+
+#define NNPFS_MSG_GETROOT 2
+#define NNPFS_MSG_INSTALLROOT 3
+
+#define NNPFS_MSG_GETNODE 4
+#define NNPFS_MSG_INSTALLNODE 5
+
+#define NNPFS_MSG_GETATTR 6
+#define NNPFS_MSG_INSTALLATTR 7
+
+#define NNPFS_MSG_GETDATA 8
+#define NNPFS_MSG_INSTALLDATA 9
+
+#define NNPFS_MSG_INACTIVENODE 10
+#define NNPFS_MSG_INVALIDNODE 11
+ /* XXX Must handle dropped/revoked tokens better */
+
+#define NNPFS_MSG_OPEN 12
+
+#define NNPFS_MSG_PUTDATA 13
+#define NNPFS_MSG_PUTATTR 14
+
+/* Directory manipulating messages. */
+#define NNPFS_MSG_CREATE 15
+#define NNPFS_MSG_MKDIR 16
+#define NNPFS_MSG_LINK 17
+#define NNPFS_MSG_SYMLINK 18
+
+#define NNPFS_MSG_REMOVE 19
+#define NNPFS_MSG_RMDIR 20
+
+#define NNPFS_MSG_RENAME 21
+
+#define NNPFS_MSG_PIOCTL 22
+#define NNPFS_MSG_WAKEUP_DATA 23
+
+#define NNPFS_MSG_UPDATEFID 24
+
+#define NNPFS_MSG_ADVLOCK 25
+
+#define NNPFS_MSG_GC_NODES 26
+
+#define NNPFS_MSG_COUNT 27
+
+/* NNPFS_MESSAGE_VERSION */
+struct nnpfs_message_version {
+ struct nnpfs_message_header header;
+ uint32_t ret;
+};
+
+/* NNPFS_MESSAGE_WAKEUP */
+struct nnpfs_message_wakeup {
+ struct nnpfs_message_header header;
+ uint32_t sleepers_sequence_num; /* Where to send wakeup */
+ uint32_t error; /* Return value */
+};
+
+/* NNPFS_MESSAGE_GETROOT */
+struct nnpfs_message_getroot {
+ struct nnpfs_message_header header;
+ struct nnpfs_cred cred;
+};
+
+/* NNPFS_MESSAGE_INSTALLROOT */
+struct nnpfs_message_installroot {
+ struct nnpfs_message_header header;
+ struct nnpfs_msg_node node;
+};
+
+/* NNPFS_MESSAGE_GETNODE */
+struct nnpfs_message_getnode {
+ struct nnpfs_message_header header;
+ struct nnpfs_cred cred;
+ nnpfs_handle parent_handle;
+ char name[NNPFS_MAX_NAME];
+};
+
+/* NNPFS_MESSAGE_INSTALLNODE */
+struct nnpfs_message_installnode {
+ struct nnpfs_message_header header;
+ nnpfs_handle parent_handle;
+ char name[NNPFS_MAX_NAME];
+ struct nnpfs_msg_node node;
+};
+
+/* NNPFS_MESSAGE_GETATTR */
+struct nnpfs_message_getattr {
+ struct nnpfs_message_header header;
+ struct nnpfs_cred cred;
+ nnpfs_handle handle;
+};
+
+/* NNPFS_MESSAGE_INSTALLATTR */
+struct nnpfs_message_installattr {
+ struct nnpfs_message_header header;
+ struct nnpfs_msg_node node;
+};
+
+/* NNPFS_MESSAGE_GETDATA */
+struct nnpfs_message_getdata {
+ struct nnpfs_message_header header;
+ struct nnpfs_cred cred;
+ nnpfs_handle handle;
+ uint32_t tokens;
+ uint32_t pad1;
+ uint32_t offset;
+ uint32_t pad2;
+};
+
+/* NNPFS_MESSAGE_INSTALLDATA */
+struct nnpfs_message_installdata {
+ struct nnpfs_message_header header;
+ struct nnpfs_msg_node node;
+ char cache_name[NNPFS_MAX_NAME];
+ struct nnpfs_cache_handle cache_handle;
+ uint32_t flag;
+ uint32_t pad1;
+ uint32_t offset;
+ uint32_t pad2;
+};
+
+/* NNPFS_MSG_INACTIVENODE */
+struct nnpfs_message_inactivenode {
+ struct nnpfs_message_header header;
+ nnpfs_handle handle;
+ uint32_t flag;
+ uint32_t pad1;
+};
+
+/* NNPFS_MSG_INVALIDNODE */
+struct nnpfs_message_invalidnode {
+ struct nnpfs_message_header header;
+ nnpfs_handle handle;
+};
+
+/* NNPFS_MSG_OPEN */
+struct nnpfs_message_open {
+ struct nnpfs_message_header header;
+ struct nnpfs_cred cred;
+ nnpfs_handle handle;
+ uint32_t tokens;
+ uint32_t pad1;
+};
+
+/* NNPFS_MSG_PUTDATA */
+struct nnpfs_message_putdata {
+ struct nnpfs_message_header header;
+ nnpfs_handle handle;
+ struct nnpfs_attr attr; /* XXX ??? */
+ struct nnpfs_cred cred;
+ uint32_t flag;
+ uint32_t pad1;
+};
+
+/* NNPFS_MSG_PUTATTR */
+struct nnpfs_message_putattr {
+ struct nnpfs_message_header header;
+ nnpfs_handle handle;
+ struct nnpfs_attr attr;
+ struct nnpfs_cred cred;
+};
+
+/* NNPFS_MSG_CREATE */
+struct nnpfs_message_create {
+ struct nnpfs_message_header header;
+ nnpfs_handle parent_handle;
+ char name[NNPFS_MAX_NAME];
+ struct nnpfs_attr attr;
+ uint32_t mode;
+ uint32_t pad1;
+ struct nnpfs_cred cred;
+};
+
+/* NNPFS_MSG_MKDIR */
+struct nnpfs_message_mkdir {
+ struct nnpfs_message_header header;
+ nnpfs_handle parent_handle;
+ char name[NNPFS_MAX_NAME];
+ struct nnpfs_attr attr;
+ struct nnpfs_cred cred;
+};
+
+/* NNPFS_MSG_LINK */
+struct nnpfs_message_link {
+ struct nnpfs_message_header header;
+ nnpfs_handle parent_handle;
+ char name[NNPFS_MAX_NAME];
+ nnpfs_handle from_handle;
+ struct nnpfs_cred cred;
+};
+
+/* NNPFS_MSG_SYMLINK */
+struct nnpfs_message_symlink {
+ struct nnpfs_message_header header;
+ nnpfs_handle parent_handle;
+ char name[NNPFS_MAX_NAME];
+ char contents[NNPFS_MAX_SYMLINK_CONTENT];
+ struct nnpfs_attr attr;
+ struct nnpfs_cred cred;
+};
+
+/* NNPFS_MSG_REMOVE */
+struct nnpfs_message_remove {
+ struct nnpfs_message_header header;
+ nnpfs_handle parent_handle;
+ char name[NNPFS_MAX_NAME];
+ struct nnpfs_cred cred;
+};
+
+/* NNPFS_MSG_RMDIR */
+struct nnpfs_message_rmdir {
+ struct nnpfs_message_header header;
+ nnpfs_handle parent_handle;
+ char name[NNPFS_MAX_NAME];
+ struct nnpfs_cred cred;
+};
+
+/* NNPFS_MSG_RENAME */
+struct nnpfs_message_rename {
+ struct nnpfs_message_header header;
+ nnpfs_handle old_parent_handle;
+ char old_name[NNPFS_MAX_NAME];
+ nnpfs_handle new_parent_handle;
+ char new_name[NNPFS_MAX_NAME];
+ struct nnpfs_cred cred;
+};
+
+#define NNPFS_MSG_MAX_DATASIZE 2048
+
+/* NNPFS_MSG_PIOCTL */
+struct nnpfs_message_pioctl {
+ struct nnpfs_message_header header;
+ uint32_t opcode ;
+ uint32_t pad1;
+ nnpfs_cred cred;
+ uint32_t insize;
+ uint32_t outsize;
+ char msg[NNPFS_MSG_MAX_DATASIZE];
+ nnpfs_handle handle;
+};
+
+
+/* NNPFS_MESSAGE_WAKEUP_DATA */
+struct nnpfs_message_wakeup_data {
+ struct nnpfs_message_header header;
+ uint32_t sleepers_sequence_num; /* Where to send wakeup */
+ uint32_t error; /* Return value */
+ uint32_t len;
+ uint32_t pad1;
+ char msg[NNPFS_MSG_MAX_DATASIZE];
+};
+
+/* NNPFS_MESSAGE_UPDATEFID */
+struct nnpfs_message_updatefid {
+ struct nnpfs_message_header header;
+ nnpfs_handle old_handle;
+ nnpfs_handle new_handle;
+};
+
+/* NNPFS_MESSAGE_ADVLOCK */
+struct nnpfs_message_advlock {
+ struct nnpfs_message_header header;
+ nnpfs_handle handle;
+ struct nnpfs_cred cred;
+ nnpfs_locktype_t locktype;
+#define NNPFS_WR_LOCK 1 /* Write lock */
+#define NNPFS_RD_LOCK 2 /* Read lock */
+#define NNPFS_UN_LOCK 3 /* Unlock */
+#define NNPFS_BR_LOCK 4 /* Break lock (inform that we don't want the lock) */
+ nnpfs_lockid_t lockid;
+};
+
+/* NNPFS_MESSAGE_GC_NODES */
+struct nnpfs_message_gc_nodes {
+ struct nnpfs_message_header header;
+#define NNPFS_GC_NODES_MAX_HANDLE 50
+ uint32_t len;
+ uint32_t pad1;
+ nnpfs_handle handle[NNPFS_GC_NODES_MAX_HANDLE];
+};
+
+#if 0
+struct nnpfs_name {
+ u_int16_t name;
+ char name[1];
+};
+#endif
+
+struct nnpfs_message_bulkgetnode {
+ struct nnpfs_message_header header;
+ nnpfs_handle parent_handle;
+ uint32_t flags;
+#define NNPFS_BGN_LAZY 0x1
+ uint32_t numnodes;
+ struct nnpfs_handle handles[1];
+};
+
+#endif /* _xmsg_h */
diff --git a/sys/nnpfs/nnpfs_msg_locl.h b/sys/nnpfs/nnpfs_msg_locl.h
new file mode 100644
index 00000000000..d3be0f9548f
--- /dev/null
+++ b/sys/nnpfs/nnpfs_msg_locl.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $arla: nnpfs_msg_locl.h,v 1.6 2002/09/07 10:46:05 lha Exp $ */
+
+#ifndef _nnpfs_msg_locl_h
+#define _nnpfs_msg_locl_h
+
+int
+nnpfs_message_installroot(int fd,
+ struct nnpfs_message_installroot * message,
+ u_int size,
+ d_thread_t *p);
+
+int
+nnpfs_message_installnode(int fd,
+ struct nnpfs_message_installnode * message,
+ u_int size,
+ d_thread_t *p);
+
+int
+nnpfs_message_installattr(int fd,
+ struct nnpfs_message_installattr * message,
+ u_int size,
+ d_thread_t *p);
+
+int
+nnpfs_message_installdata(int fd,
+ struct nnpfs_message_installdata * message,
+ u_int size,
+ d_thread_t *p);
+
+int
+nnpfs_message_invalidnode(int fd,
+ struct nnpfs_message_invalidnode * message,
+ u_int size,
+ d_thread_t *p);
+
+int
+nnpfs_message_updatefid(int fd,
+ struct nnpfs_message_updatefid * message,
+ u_int size,
+ d_thread_t *p);
+
+int
+nnpfs_message_gc_nodes(int fd,
+ struct nnpfs_message_gc_nodes * message,
+ u_int size,
+ d_thread_t *p);
+
+int
+nnpfs_message_version(int fd,
+ struct nnpfs_message_version *message,
+ u_int size,
+ d_thread_t *p);
+
+#endif /* _nnpfs_msg_locl_h */
diff --git a/sys/nnpfs/nnpfs_node-bsd.c b/sys/nnpfs/nnpfs_node-bsd.c
new file mode 100644
index 00000000000..1f6ace40860
--- /dev/null
+++ b/sys/nnpfs/nnpfs_node-bsd.c
@@ -0,0 +1,801 @@
+/*
+ * Copyright (c) 1995 - 2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/queue.h>
+#include <nnpfs/nnpfs_locl.h>
+#include <nnpfs/nnpfs_common.h>
+#include <nnpfs/nnpfs_fs.h>
+#include <nnpfs/nnpfs_deb.h>
+#include <nnpfs/nnpfs_vnodeops.h>
+
+RCSID("$arla: nnpfs_node-bsd.c,v 1.70 2003/02/28 02:01:06 lha Exp $");
+
+extern vop_t **nnpfs_vnodeop_p;
+
+#ifndef LK_NOPAUSE
+#define LK_NOPAUSE 0
+#endif
+
+/*
+ * Allocate a new vnode with handle `handle' in `mp' and return it in
+ * `vpp'. Return 0 or error.
+ */
+
+int
+nnpfs_getnewvnode(struct nnpfs *nnpfsp, struct vnode **vpp,
+ struct nnpfs_handle *handle)
+{
+ struct nnpfs_node *result, *check;
+ int error;
+
+ error = getnewvnode(VT_NNPFS, NNPFS_TO_VFS(nnpfsp), nnpfs_vnodeop_p, vpp);
+ if (error)
+ return error;
+
+ result = nnpfs_alloc(sizeof(*result), M_NNPFS_NODE);
+ bzero(result, sizeof(*result));
+
+ (*vpp)->v_data = result;
+ result->vn = *vpp;
+
+ result->handle = *handle;
+ result->flags = 0;
+ result->tokens = 0;
+ result->offset = 0;
+#if defined(HAVE_KERNEL_LOCKMGR) || defined(HAVE_KERNEL_DEBUGLOCKMGR)
+ lockinit (&result->lock, PVFS, "nnpfs_lock", 0, LK_NOPAUSE);
+#else
+ result->vnlocks = 0;
+#endif
+ result->anonrights = 0;
+ result->rd_cred = NULL;
+ result->wr_cred = NULL;
+
+#if defined(__NetBSD_Version__) && __NetBSD_Version__ >= 105280000
+ genfs_node_init(*vpp, &nnpfs_genfsops);
+#endif
+
+ check = nnpfs_node_find(&nnpfsp->nodehead, handle);
+ if (check) {
+ vput(*vpp);
+ *vpp = result->vn;
+ return 0;
+ }
+
+ nnpfs_insert(&nnpfs->nodehead, result);
+
+ return 0;
+}
+
+/*
+ * Create a new nnpfs_node and make a vget
+ *
+ * Also prevents creation of duplicates. This happens
+ * whenever there are more than one name to a file,
+ * "." and ".." are common cases. */
+
+int
+new_nnpfs_node(struct nnpfs *nnpfsp,
+ struct nnpfs_msg_node *node,
+ struct nnpfs_node **xpp,
+ d_thread_t *p)
+{
+ struct nnpfs_node *result;
+
+ NNPFSDEB(XDEBNODE, ("new_nnpfs_node (%d,%d,%d,%d)\n",
+ node->handle.a,
+ node->handle.b,
+ node->handle.c,
+ node->handle.d));
+
+retry:
+ /* Does not allow duplicates */
+ result = nnpfs_node_find(&nnpfsp->nodehead, &node->handle);
+ if (result == 0) {
+ int error;
+ struct vnode *v;
+
+ error = nnpfs_getnewvnode(nnpfsp, &v, &node->handle);
+ if (error)
+ return error;
+
+ result = VNODE_TO_XNODE(v);
+ result->anonrights = node->anonrights;
+
+ nnpfsp->nnodes++;
+ } else {
+ /* Node is already cached */
+ if(nnpfs_do_vget(XNODE_TO_VNODE(result), 0, p))
+ goto retry;
+ }
+
+ /* Init other fields */
+ nnpfs_attr2vattr(&node->attr, &result->attr, 1);
+ result->vn->v_type = result->attr.va_type;
+ result->tokens = node->tokens;
+ bcopy(node->id, result->id, sizeof(result->id));
+ bcopy(node->rights, result->rights, sizeof(result->rights));
+
+#ifdef __APPLE__
+ if (result->vn->v_type == VREG && (!UBCINFOEXISTS(result->vn)))
+ ubc_info_init(result->vn);
+#endif
+
+ *xpp = result;
+ NNPFSDEB(XDEBNODE, ("return: new_nnpfs_node\n"));
+ return 0;
+}
+
+void
+free_nnpfs_node(struct nnpfs_node *node)
+{
+ struct nnpfs *nnpfsp = NNPFS_FROM_XNODE(node);
+
+ NNPFSDEB(XDEBNODE, ("free_nnpfs_node(%lx) (%d,%d,%d,%d)\n",
+ (unsigned long)node,
+ node->handle.a,
+ node->handle.b,
+ node->handle.c,
+ node->handle.d));
+
+ /* XXX Really need to put back dirty data first. */
+
+ if (DATA_FROM_XNODE(node)) {
+ vrele(DATA_FROM_XNODE(node));
+ DATA_FROM_XNODE(node) = NULL;
+ }
+ nnpfsp->nnodes--;
+ XNODE_TO_VNODE(node)->v_data = NULL;
+ if (node->rd_cred) {
+ crfree (node->rd_cred);
+ node->rd_cred = NULL;
+ }
+ if (node->wr_cred) {
+ crfree (node->wr_cred);
+ node->wr_cred = NULL;
+ }
+
+ nnpfs_free(node, sizeof(*node), M_NNPFS_NODE);
+
+ NNPFSDEB(XDEBNODE, ("free_nnpfs_node done\n"));
+}
+
+/*
+ * FreeBSD 4.4 and newer changed to API to vflush around June 2001
+ */
+
+static int
+nnpfs_vflush(struct mount *mp, int flags)
+{
+#if __FreeBSD__ && __FreeBSD_version > 430000
+ return vflush(mp, 0, flags);
+#else
+ return vflush(mp, NULL, flags);
+#endif
+}
+
+int
+free_all_nnpfs_nodes(struct nnpfs *nnpfsp, int flags, int unmountp)
+{
+ int error = 0;
+ struct mount *mp = NNPFS_TO_VFS(nnpfsp);
+
+ if (mp == NULL) {
+ NNPFSDEB(XDEBNODE, ("free_all_nnpfs_nodes already freed\n"));
+ return 0;
+ }
+
+ NNPFSDEB(XDEBNODE, ("free_all_nnpfs_nodes starting\n"));
+
+ nnpfs_dnlc_purge_mp(mp);
+
+ if (nnpfsp->root) {
+ NNPFSDEB(XDEBNODE, ("free_all_nnpfs_nodes now removing root\n"));
+
+ vgone(XNODE_TO_VNODE(nnpfsp->root));
+ nnpfsp->root = NULL;
+ }
+
+ NNPFSDEB(XDEBNODE, ("free_all_nnpfs_nodes root removed\n"));
+ NNPFSDEB(XDEBNODE, ("free_all_nnpfs_nodes now killing all remaining nodes\n"));
+
+ /*
+ * If we have a syncer vnode, release it (to emulate dounmount)
+ * and the create it again when if we are going to need it.
+ */
+
+#ifdef HAVE_STRUCT_MOUNT_MNT_SYNCER
+ if (!unmountp) {
+ if (mp->mnt_syncer != NULL) {
+#ifdef HAVE_KERNEL_VFS_DEALLOCATE_SYNCVNODE
+ vfs_deallocate_syncvnode(mp);
+#else
+ /*
+ * FreeBSD and OpenBSD uses different semantics,
+ * FreeBSD does vrele, and OpenBSD does vgone.
+ */
+#if defined(__OpenBSD__)
+ vgone(mp->mnt_syncer);
+#elif defined(__FreeBSD__)
+ vrele(mp->mnt_syncer);
+#else
+#error what os do you use ?
+#endif
+ mp->mnt_syncer = NULL;
+#endif
+ }
+ }
+#endif
+ error = nnpfs_vflush(mp, flags);
+#ifdef HAVE_STRUCT_MOUNT_MNT_SYNCER
+ if (!unmountp) {
+ NNPFSDEB(XDEBNODE, ("free_all_nnpfs_nodes not flushing syncer vnode\n"));
+ if (mp->mnt_syncer == NULL)
+ if (vfs_allocate_syncvnode(mp))
+ panic("failed to allocate syncer node when nnpfs daemon died");
+ }
+#endif
+
+ if (error) {
+ NNPFSDEB(XDEBNODE, ("xfree_all_nnpfs_nodes: vflush() error == %d\n",
+ error));
+ return error;
+ }
+
+ NNPFSDEB(XDEBNODE, ("free_all_nnpfs_nodes done\n"));
+ return error;
+}
+
+void
+vattr2nnpfs_attr(const struct vattr *va, struct nnpfs_attr *xa)
+{
+ bzero(xa, sizeof(*xa));
+ if (va->va_mode != (mode_t)VNOVAL)
+ XA_SET_MODE(xa, va->va_mode);
+ if (va->va_nlink != VNOVAL)
+ XA_SET_NLINK(xa, va->va_nlink);
+ if (va->va_size != VNOVAL)
+ XA_SET_SIZE(xa, va->va_size);
+ if (va->va_uid != VNOVAL)
+ XA_SET_UID(xa, va->va_uid);
+ if (va->va_gid != VNOVAL)
+ XA_SET_GID(xa, va->va_gid);
+ if (va->va_atime.tv_sec != VNOVAL)
+ XA_SET_ATIME(xa, va->va_atime.tv_sec);
+ if (va->va_mtime.tv_sec != VNOVAL)
+ XA_SET_MTIME(xa, va->va_mtime.tv_sec);
+ if (va->va_ctime.tv_sec != VNOVAL)
+ XA_SET_CTIME(xa, va->va_ctime.tv_sec);
+ if (va->va_fileid != VNOVAL)
+ XA_SET_FILEID(xa, va->va_fileid);
+ switch (va->va_type) {
+ case VNON:
+ xa->xa_type = NNPFS_FILE_NON;
+ break;
+ case VREG:
+ xa->xa_type = NNPFS_FILE_REG;
+ break;
+ case VDIR:
+ xa->xa_type = NNPFS_FILE_DIR;
+ break;
+ case VBLK:
+ xa->xa_type = NNPFS_FILE_BLK;
+ break;
+ case VCHR:
+ xa->xa_type = NNPFS_FILE_CHR;
+ break;
+ case VLNK:
+ xa->xa_type = NNPFS_FILE_LNK;
+ break;
+ case VSOCK:
+ xa->xa_type = NNPFS_FILE_SOCK;
+ break;
+ case VFIFO:
+ xa->xa_type = NNPFS_FILE_FIFO;
+ break;
+ case VBAD:
+ xa->xa_type = NNPFS_FILE_BAD;
+ break;
+ default:
+ panic("nnpfs_attr2attr: bad value");
+ }
+}
+
+#define SET_TIMEVAL(X, S, N) do { (X)->tv_sec = (S); (X)->tv_nsec = (N); } while(0)
+
+void
+nnpfs_attr2vattr(const struct nnpfs_attr *xa, struct vattr *va, int clear_node)
+{
+ if (clear_node)
+ VATTR_NULL(va);
+ if (XA_VALID_MODE(xa))
+ va->va_mode = xa->xa_mode;
+ if (XA_VALID_NLINK(xa))
+ va->va_nlink = xa->xa_nlink;
+ if (XA_VALID_SIZE(xa)) {
+ va->va_size = xa->xa_size;
+ va->va_bytes = va->va_size;
+ }
+ if (XA_VALID_UID(xa))
+ va->va_uid = xa->xa_uid;
+ if (XA_VALID_GID(xa))
+ va->va_gid = xa->xa_gid;
+ if (XA_VALID_ATIME(xa)) {
+ SET_TIMEVAL(&va->va_atime, xa->xa_atime, 0);
+ }
+ if (XA_VALID_MTIME(xa)) {
+ SET_TIMEVAL(&va->va_mtime, xa->xa_mtime, 0);
+ }
+ if (XA_VALID_CTIME(xa)) {
+ SET_TIMEVAL(&va->va_ctime, xa->xa_ctime, 0);
+ }
+ if (XA_VALID_FILEID(xa)) {
+ va->va_fileid = xa->xa_fileid;
+ }
+ if (XA_VALID_TYPE(xa)) {
+ switch (xa->xa_type) {
+ case NNPFS_FILE_NON:
+ va->va_type = VNON;
+ break;
+ case NNPFS_FILE_REG:
+ va->va_type = VREG;
+ break;
+ case NNPFS_FILE_DIR:
+ va->va_type = VDIR;
+ break;
+ case NNPFS_FILE_BLK:
+ va->va_type = VBLK;
+ break;
+ case NNPFS_FILE_CHR:
+ va->va_type = VCHR;
+ break;
+ case NNPFS_FILE_LNK:
+ va->va_type = VLNK;
+ break;
+ case NNPFS_FILE_SOCK:
+ va->va_type = VSOCK;
+ break;
+ case NNPFS_FILE_FIFO:
+ va->va_type = VFIFO;
+ break;
+ case NNPFS_FILE_BAD:
+ va->va_type = VBAD;
+ break;
+ default:
+ panic("nnpfs_attr2vattr: bad value");
+ }
+ }
+ va->va_flags = 0;
+ va->va_blocksize = 8192;
+}
+
+/*
+ * A single entry DNLC for systems for handling long names that don't
+ * get put into the system DNLC.
+ */
+
+struct long_entry {
+ struct vnode *dvp, *vp;
+ char name[MAXNAMLEN + 1];
+ size_t len;
+ u_long dvpid, vpid;
+};
+
+static struct long_entry tbl;
+
+/*
+ * Nuke the `tbl'
+ */
+
+static void
+tbl_clear (void)
+{
+ tbl.dvp = tbl.vp = NULL;
+ tbl.name[0] = '\0';
+ tbl.len = 0;
+ tbl.dvpid = tbl.vpid = 0;
+}
+
+/*
+ * Set the entry in the `tbl'
+ */
+
+static void
+tbl_enter (size_t len, const char *name, struct vnode *dvp, struct vnode *vp)
+{
+ tbl.len = len;
+ bcopy(name, tbl.name, len);
+ tbl.dvp = dvp;
+ tbl.vp = vp;
+ tbl.dvpid = dvp->v_id;
+ tbl.vpid = vp->v_id;
+}
+
+/*
+ * Lookup in tbl (`dvp', `name', `len') and return result in `res'.
+ * Return -1 if successful, otherwise 0.
+ */
+
+static int
+tbl_lookup (struct componentname *cnp,
+ struct vnode *dvp,
+ struct vnode **res)
+{
+ if (tbl.dvp == dvp
+ && tbl.len == cnp->cn_namelen
+ && strncmp(tbl.name, cnp->cn_nameptr, tbl.len) == 0
+ && tbl.dvpid == tbl.dvp->v_id
+ && tbl.vpid == tbl.vp->v_id) {
+
+ *res = tbl.vp;
+ return -1;
+ } else
+ return 0;
+}
+
+/*
+ * Store a componentname in the DNLC
+ */
+
+int
+nnpfs_dnlc_enter(struct vnode *dvp,
+ nnpfs_componentname *cnp,
+ struct vnode *vp)
+{
+ NNPFSDEB(XDEBDNLC, ("nnpfs_dnlc_enter_cnp(%lx, %lx, %lx)\n",
+ (unsigned long)dvp,
+ (unsigned long)cnp,
+ (unsigned long)vp));
+ NNPFSDEB(XDEBDNLC, ("nnpfs_dnlc_enter: v_id = %lu\n", (u_long)dvp->v_id));
+
+ NNPFSDEB(XDEBDNLC, ("nnpfs_dnlc_enter: calling cache_enter:"
+ "dvp = %lx, vp = %lx, cnp = (%s, %ld), "
+ "nameiop = %lu, flags = %lx\n",
+ (unsigned long)dvp,
+ (unsigned long)vp,
+ cnp->cn_nameptr, cnp->cn_namelen,
+ cnp->cn_nameiop, cnp->cn_flags));
+
+#ifdef NCHNAMLEN
+ if (cnp->cn_namelen <= NCHNAMLEN)
+#endif
+ {
+ /*
+ * This is to make sure there's no negative entry already in the dnlc
+ */
+ u_long save_nameiop;
+ u_long save_flags;
+ struct vnode *dummy;
+
+ save_nameiop = cnp->cn_nameiop;
+ save_flags = cnp->cn_flags;
+ cnp->cn_nameiop = CREATE;
+ cnp->cn_flags &= ~MAKEENTRY;
+
+/*
+ * The version number here is not entirely correct, but it's conservative.
+ * The real change is sys/kern/vfs_cache:1.20
+ */
+
+#if __NetBSD_Version__ >= 104120000 || OpenBSD > 200211
+ if (cache_lookup(dvp, &dummy, cnp) != -1) {
+ nnpfs_vfs_unlock(dummy, nnpfs_cnp_to_proc(cnp));
+ printf ("NNPFS PANIC WARNING! nnpfs_dnlc_enter: %s already in cache\n",
+ cnp->cn_nameptr);
+ }
+#else
+ if (cache_lookup(dvp, &dummy, cnp) != 0) {
+ printf ("NNPFS PANIC WARNING! nnpfs_dnlc_enter: %s already in cache\n",
+ cnp->cn_nameptr);
+ }
+#endif
+
+
+ cnp->cn_nameiop = save_nameiop;
+ cnp->cn_flags = save_flags;
+ cache_enter(dvp, vp, cnp);
+ }
+
+ if (vp != NULL)
+ tbl_enter (cnp->cn_namelen, cnp->cn_nameptr, dvp, vp);
+
+ return 0;
+}
+
+
+static void
+nnpfs_cnp_init (struct componentname *cn,
+ const char *name,
+ d_thread_t *proc, struct ucred *cred,
+ int nameiop)
+{
+ bzero(cn, sizeof(*cn));
+ cn->cn_nameptr = (char *)name;
+ cn->cn_namelen = strlen(name);
+ cn->cn_flags = 0;
+#if __APPLE__
+ {
+ const unsigned char *p;
+ int i;
+
+ cn->cn_hash = 0;
+ for (p = cn->cn_nameptr, i = 1; *p; ++p, ++i)
+ cn->cn_hash += *p * i;
+ }
+#elif defined(HAVE_KERNEL_NAMEI_HASH)
+ {
+ const char *cp = name + cn->cn_namelen;
+ cn->cn_hash = namei_hash(name, &cp);
+ }
+#elif defined(HAVE_STRUCT_COMPONENTNAME_CN_HASH)
+ {
+ const unsigned char *p;
+
+ cn->cn_hash = 0;
+ for (p = cn->cn_nameptr; *p; ++p)
+ cn->cn_hash += *p;
+ }
+#endif
+ cn->cn_nameiop = nameiop;
+#ifdef HAVE_FREEBSD_THREAD
+ cn->cn_thread = proc;
+#else
+ cn->cn_proc = proc;
+#endif
+ cn->cn_cred = cred;
+}
+
+
+/*
+ * Store (dvp, name, vp) in the DNLC
+ */
+
+int
+nnpfs_dnlc_enter_name(struct vnode *dvp,
+ const char *name,
+ struct vnode *vp)
+{
+ struct componentname cn;
+
+ NNPFSDEB(XDEBDNLC, ("nnpfs_dnlc_enter_name(%lx, \"%s\", %lx)\n",
+ (unsigned long)dvp,
+ name,
+ (unsigned long)vp));
+
+ nnpfs_cnp_init (&cn, name, NULL, NULL, LOOKUP);
+ return nnpfs_dnlc_enter (dvp, &cn, vp);
+}
+
+/*
+ * Lookup (dvp, cnp) in the DNLC and return the result in `res'.
+ * Return the result from cache_lookup.
+ */
+
+static int
+nnpfs_dnlc_lookup_int(struct vnode *dvp,
+ nnpfs_componentname *cnp,
+ struct vnode **res)
+{
+ int error;
+ u_long saved_flags;
+
+ NNPFSDEB(XDEBDNLC, ("nnpfs_dnlc_lookup(%lx, \"%s\")\n",
+ (unsigned long)dvp, cnp->cn_nameptr));
+
+ NNPFSDEB(XDEBDNLC, ("nnpfs_dnlc_lookup: v_id = %lu\n", (u_long)dvp->v_id));
+
+ NNPFSDEB(XDEBDNLC, ("nnpfs_dnlc_lookup: calling cache_lookup:"
+ "dvp = %lx, cnp = (%s, %ld), flags = %lx\n",
+ (unsigned long)dvp,
+ cnp->cn_nameptr, cnp->cn_namelen,
+ cnp->cn_flags));
+
+ saved_flags = cnp->cn_flags;
+ cnp->cn_flags |= MAKEENTRY | LOCKPARENT | ISLASTCN;
+
+ error = cache_lookup(dvp, res, cnp);
+
+ cnp->cn_flags = saved_flags;
+
+ NNPFSDEB(XDEBDNLC, ("nnpfs_dnlc_lookup: cache_lookup returned. "
+ "error = %d, *res = %lx\n", error,
+ (unsigned long)*res));
+ return error;
+}
+
+/*
+ * do the last (and locking protocol) portion of xnlc_lookup
+ *
+ * return:
+ * -1 for successful
+ * 0 for failed
+ */
+
+static int
+nnpfs_dnlc_lock(struct vnode *dvp,
+ nnpfs_componentname *cnp,
+ struct vnode **res)
+{
+ int error = 0;
+
+ /*
+ * Try to handle the (complex) BSD locking protocol.
+ */
+
+ if (*res == dvp) { /* "." */
+ VREF(dvp);
+ } else if (cnp->cn_flags & ISDOTDOT) { /* ".." */
+ u_long vpid = dvp->v_id;
+
+#ifdef HAVE_FREEBSD_THREAD
+ nnpfs_vfs_unlock(dvp, nnpfs_cnp_to_thread(cnp));
+ error = nnpfs_do_vget(*res, LK_EXCLUSIVE, nnpfs_cnp_to_thread(cnp));
+ nnpfs_vfs_writelock(dvp, nnpfs_cnp_to_thread(cnp));
+#else
+ nnpfs_vfs_unlock(dvp, nnpfs_cnp_to_proc(cnp));
+ error = nnpfs_do_vget(*res, LK_EXCLUSIVE, nnpfs_cnp_to_proc(cnp));
+ nnpfs_vfs_writelock(dvp, nnpfs_cnp_to_proc(cnp));
+#endif
+
+ if (error == 0 && dvp->v_id != vpid) {
+ vput(*res);
+ return 0;
+ }
+ } else {
+#ifdef HAVE_FREEBSD_THREAD
+ error = nnpfs_do_vget(*res, LK_EXCLUSIVE, nnpfs_cnp_to_thread(cnp));
+#else
+ error = nnpfs_do_vget(*res, LK_EXCLUSIVE, nnpfs_cnp_to_proc(cnp));
+#endif
+ }
+
+ if (error == 0)
+ return -1;
+ else
+ return 0;
+}
+
+/*
+ * Lookup (`dvp', `cnp') in the DNLC (and the local cache).
+ *
+ * Return -1 if successful, 0 if not and ENOENT if the entry is known
+ * not to exist.
+ *
+ * On modern NetBSD, cache_lookup has been changed to return 0 for
+ * successful and -1 for not.
+ * (see the comment above for version information).
+ */
+
+#if __NetBSD_Version__ >= 104120000 || defined(__OpenBSD__)
+
+int
+nnpfs_dnlc_lookup(struct vnode *dvp,
+ nnpfs_componentname *cnp,
+ struct vnode **res)
+{
+ int error = nnpfs_dnlc_lookup_int (dvp, cnp, res);
+
+ if (error == 0)
+ return -1;
+ else if (error == ENOENT)
+ return error;
+
+ error = tbl_lookup (cnp, dvp, res);
+
+ if (error != -1)
+ return error;
+
+ return nnpfs_dnlc_lock (dvp, cnp, res);
+}
+
+#else /* ! __NetBSD_Version__ >= 104120000 && ! OpenBSD > 200211 */
+
+int
+nnpfs_dnlc_lookup(struct vnode *dvp,
+ nnpfs_componentname *cnp,
+ struct vnode **res)
+{
+ int error = nnpfs_dnlc_lookup_int (dvp, cnp, res);
+
+ if (error == 0)
+ error = tbl_lookup (cnp, dvp, res);
+
+ if (error != -1)
+ return error;
+
+ return nnpfs_dnlc_lock (dvp, cnp, res);
+}
+
+#endif /* __NetBSD_Version__ >= 104120000 || OpenBSD > 200211 */
+
+/*
+ * Remove one entry from the DNLC
+ */
+
+void
+nnpfs_dnlc_purge (struct vnode *vp)
+{
+ NNPFSDEB(XDEBDNLC, ("nnpfs_dnlc_purge\n"));
+
+ if (tbl.dvp == vp || tbl.vp == vp)
+ tbl_clear ();
+
+ cache_purge(vp);
+}
+
+/*
+ * Remove all entries belong to `mp' from the DNLC
+ */
+
+void
+nnpfs_dnlc_purge_mp(struct mount *mp)
+{
+ NNPFSDEB(XDEBDNLC, ("nnpfs_dnlc_purge_mp()\n"));
+
+ tbl_clear ();
+ cache_purgevfs(mp);
+}
+
+/*
+ * Returns 1 if pag has any rights set in the node
+ */
+
+int
+nnpfs_has_pag(const struct nnpfs_node *xn, nnpfs_pag_t pag)
+{
+ int i;
+
+ for (i = 0; i < MAXRIGHTS; i++)
+ if (xn->id[i] == pag)
+ return 1;
+
+ return 0;
+}
+
+void
+nnpfs_update_write_cred(struct nnpfs_node *xn, struct ucred *cred)
+{
+ if (xn->wr_cred)
+ crfree (xn->wr_cred);
+ crhold (cred);
+ xn->wr_cred = cred;
+}
+
+void
+nnpfs_update_read_cred(struct nnpfs_node *xn, struct ucred *cred)
+{
+ if (xn->rd_cred)
+ crfree (xn->rd_cred);
+ crhold (cred);
+ xn->rd_cred = cred;
+}
diff --git a/sys/nnpfs/nnpfs_node.c b/sys/nnpfs/nnpfs_node.c
new file mode 100644
index 00000000000..805a6a46e9b
--- /dev/null
+++ b/sys/nnpfs/nnpfs_node.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2002 - 2003, Stockholms Universitet
+ * (Stockholm University, Stockholm Sweden)
+ * 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. Neither the name of the university nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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 <nnpfs/nnpfs_locl.h>
+#include <nnpfs/nnpfs_common.h>
+#include <nnpfs/nnpfs_fs.h>
+#include <nnpfs/nnpfs_deb.h>
+#include <nnpfs/nnpfs_node.h>
+#include <nnpfs/nnpfs_vnodeops.h>
+#include <nnpfs/nnpfs_queue.h>
+
+RCSID("$arla: nnpfs_node.c,v 1.3 2003/02/06 12:56:09 lha Exp $");
+
+#define nnpfs_hash(node) \
+ (((node)->a+(node)->b+(node)->c+(node)->d) % XN_HASHSIZE)
+
+/*
+ * Init the nnp node storage system
+ */
+
+void
+nnfs_init_head(struct nnpfs_nodelist_head *head)
+{
+ int i;
+
+ for (i = 0; i < XN_HASHSIZE; i++)
+ NNPQUEUE_INIT(&head->nh_nodelist[i]);
+}
+
+/*
+ * Tries to purge all nodes from the hashtable. Nodes that unpurgeable
+ * (still used nodes) are given to proc for special termination
+ * (conversion to dead node).
+ */
+
+void
+nnpfs_node_purge(struct nnpfs_nodelist_head *head,
+ void (*func)(struct nnpfs_node *))
+{
+ panic("nnpfs_node_purge");
+}
+
+/*
+ * nnpfs_node_find returns the node with the handle `handlep'.
+ */
+
+struct nnpfs_node *
+nnpfs_node_find(struct nnpfs_nodelist_head *head, nnpfs_handle *handlep)
+{
+ struct nh_node_list *h;
+ struct nnpfs_node *nn;
+
+ h = &head->nh_nodelist[nnpfs_hash(handlep)];
+
+ NNPQUEUE_FOREACH(nn, h, nn_hash) {
+ if (nnpfs_handle_eq(handlep, &nn->handle))
+ break;
+ }
+
+ return nn;
+}
+
+/*
+ * Remove the node `node' from the node storage system.
+ */
+
+void
+nnpfs_remove_node(struct nnpfs_nodelist_head *head, struct nnpfs_node *node)
+{
+ struct nh_node_list *h;
+
+ h = &head->nh_nodelist[nnpfs_hash(&node->handle)];
+ NNPQUEUE_REMOVE(node, h, nn_hash);
+}
+
+/*
+ * Add the node `node' from the node storage system.
+ */
+
+void
+nnpfs_insert(struct nnpfs_nodelist_head *head, struct nnpfs_node *node)
+{
+ struct nh_node_list *h;
+
+ h = &head->nh_nodelist[nnpfs_hash(&node->handle)];
+ NNPQUEUE_INSERT_HEAD(h, node, nn_hash);
+}
+
+/*
+ * Update `old_handlep' in the node list `head' to `new_handlep'.
+ */
+
+int
+nnpfs_update_handle(struct nnpfs_nodelist_head *head,
+ nnpfs_handle *old_handlep, nnpfs_handle *new_handlep)
+{
+ struct nnpfs_node *node;
+
+ node = nnpfs_node_find(head, new_handlep);
+ if (node)
+ return EEXIST;
+ node = nnpfs_node_find(head, old_handlep);
+ if (node == NULL)
+ return ENOENT;
+ nnpfs_remove_node(head, node);
+ node->handle = *new_handlep;
+ nnpfs_insert(head, node);
+
+ return 0;
+}
diff --git a/sys/nnpfs/nnpfs_node.h b/sys/nnpfs/nnpfs_node.h
new file mode 100644
index 00000000000..7747536073f
--- /dev/null
+++ b/sys/nnpfs/nnpfs_node.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 1995 - 2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $arla: nnpfs_node.h,v 1.33 2003/01/25 18:48:28 lha Exp $ */
+
+#ifndef _nnpfs_xnode_h
+#define _nnpfs_xnode_h
+
+#include <sys/types.h>
+#include <sys/time.h>
+#ifdef HAVE_KERNEL_LF_ADVLOCK
+#include <sys/lockf.h>
+#endif
+
+#include <nnpfs/nnpfs_attr.h>
+#include <nnpfs/nnpfs_message.h>
+#include <nnpfs/nnpfs_queue.h>
+
+#ifdef __APPLE__
+typedef struct lock__bsd__ nnpfs_vnode_lock;
+#else
+typedef struct lock nnpfs_vnode_lock;
+#endif
+
+struct nnpfs_node {
+#if defined(__NetBSD_Version__) && __NetBSD_Version__ >= 105280000
+ struct genfs_node gnode;
+#endif
+ struct vnode *vn;
+ struct vnode *data;
+ struct vattr attr;
+ uint32_t offset;
+ u_int flags;
+ u_int tokens;
+ nnpfs_handle handle;
+ nnpfs_pag_t id[MAXRIGHTS];
+ u_char rights[MAXRIGHTS];
+ u_char anonrights;
+#if defined(HAVE_KERNEL_LOCKMGR) || defined(HAVE_KERNEL_DEBUGLOCKMGR)
+ nnpfs_vnode_lock lock;
+#else
+ int vnlocks;
+#endif
+#ifdef HAVE_KERNEL_LF_ADVLOCK
+ struct lockf *lockf;
+#endif
+ struct ucred *rd_cred;
+ struct ucred *wr_cred;
+ NNPQUEUE_ENTRY(nnpfs_node) nn_hash;
+};
+
+#define XN_HASHSIZE 101
+
+NNPQUEUE_HEAD(nh_node_list, nnpfs_node);
+
+struct nnpfs_nodelist_head {
+ struct nh_node_list nh_nodelist[XN_HASHSIZE];
+};
+
+void nnfs_init_head(struct nnpfs_nodelist_head *);
+void nnpfs_node_purge(struct nnpfs_nodelist_head *,
+ void (*func)(struct nnpfs_node *));
+struct nnpfs_node *
+ nnpfs_node_find(struct nnpfs_nodelist_head *, nnpfs_handle *);
+void nnpfs_remove_node(struct nnpfs_nodelist_head *, struct nnpfs_node *);
+void nnpfs_insert(struct nnpfs_nodelist_head *, struct nnpfs_node *);
+int nnpfs_update_handle(struct nnpfs_nodelist_head *, nnpfs_handle *,
+ nnpfs_handle *);
+
+
+struct nnpfs;
+
+int nnpfs_getnewvnode(struct nnpfs *nnpfsp, struct vnode **vpp,
+ struct nnpfs_handle *handle);
+
+
+#define DATA_FROM_VNODE(vp) DATA_FROM_XNODE(VNODE_TO_XNODE(vp))
+
+#define DATA_FROM_XNODE(xp) ((xp)->data)
+
+#define XNODE_TO_VNODE(xp) ((xp)->vn)
+#define VNODE_TO_XNODE(vp) ((struct nnpfs_node *) (vp)->v_data)
+
+#if defined(HAVE_ONE_ARGUMENT_VGET)
+#define nnpfs_do_vget(vp, lockflag, proc) vget((vp))
+#elif defined(HAVE_TWO_ARGUMENT_VGET)
+#define nnpfs_do_vget(vp, lockflag, proc) vget((vp), (lockflag))
+#elif defined(HAVE_THREE_ARGUMENT_VGET)
+#define nnpfs_do_vget(vp, lockflag, proc) vget((vp), (lockflag), (proc))
+#else
+#error what kind of vget
+#endif
+
+#ifndef HAVE_VOP_T
+typedef int vop_t (void *);
+#endif
+
+#ifdef LK_INTERLOCK
+#define HAVE_LK_INTERLOCK
+#else
+#define LK_INTERLOCK 0
+#endif
+
+#ifdef LK_RETRY
+#define HAVE_LK_RETRY
+#else
+#define LK_RETRY 0
+#endif
+
+/*
+ * This is compat code for older vfs that have a
+ * vget that only takes an integer (really boolean) argument
+ * that the returned vnode will be returned locked
+ */
+
+#ifdef LK_EXCLUSIVE
+#define HAVE_LK_EXCLUSIVE 1
+#else
+#define LK_EXCLUSIVE 1
+#endif
+
+#ifdef LK_SHARED
+#define HAVE_LK_SHARED 1
+#else
+#define LK_SHARED 1
+#endif
+
+void nnpfs_update_write_cred(struct nnpfs_node *, struct ucred *);
+void nnpfs_update_read_cred(struct nnpfs_node *, struct ucred *);
+
+#endif /* _nnpfs_xnode_h */
diff --git a/sys/nnpfs/nnpfs_pioctl.h b/sys/nnpfs/nnpfs_pioctl.h
new file mode 100644
index 00000000000..2ffa9a2ed75
--- /dev/null
+++ b/sys/nnpfs/nnpfs_pioctl.h
@@ -0,0 +1,204 @@
+/* $OpenBSD: nnpfs_pioctl.h,v 1.1 2009/06/03 14:45:54 jj Exp $ */
+/*
+ * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Kungliga Tekniska
+ * Högskolan and its contributors.
+ *
+ * 4. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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 _NNPFS_NNPFS_PIOCTL_H_
+#define _NNPFS_NNPFS_PIOCTL_H_
+
+/*
+ */
+
+#define AFSCALL_PIOCTL 20
+#define AFSCALL_SETPAG 21
+#define AFSCALL_PROBE 22
+
+#ifndef _VICEIOCTL
+#define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl))
+#endif /* _VICEIOCTL */
+
+/*
+ * ioctls
+ */
+
+#define VIOCCLOSEWAIT _VICEIOCTL(1)
+#define VIOCABORT _VICEIOCTL(2)
+#define VIOIGETCELL _VICEIOCTL(3)
+
+/*
+ * pioctls
+ */
+
+#define VIOCSETAL _VICEIOCTL(1)
+#define VIOCGETAL _VICEIOCTL(2)
+#define VIOCSETTOK _VICEIOCTL(3)
+#define VIOCGETVOLSTAT _VICEIOCTL(4)
+#define VIOCSETVOLSTAT _VICEIOCTL(5)
+#define VIOCFLUSH _VICEIOCTL(6)
+#define VIOCSTAT _VICEIOCTL(7)
+#define VIOCGETTOK _VICEIOCTL(8)
+#define VIOCUNLOG _VICEIOCTL(9)
+#define VIOCCKSERV _VICEIOCTL(10)
+#define VIOCCKBACK _VICEIOCTL(11)
+#define VIOCCKCONN _VICEIOCTL(12)
+#define VIOCGETTIME _VICEIOCTL(13)
+#define VIOCWHEREIS _VICEIOCTL(14)
+#define VIOCPREFETCH _VICEIOCTL(15)
+#define VIOCNOP _VICEIOCTL(16)
+#define VIOCENGROUP _VICEIOCTL(17)
+#define VIOCDISGROUP _VICEIOCTL(18)
+#define VIOCLISTGROUPS _VICEIOCTL(19)
+#define VIOCACCESS _VICEIOCTL(20)
+#define VIOCUNPAG _VICEIOCTL(21)
+#define VIOCGETFID _VICEIOCTL(22)
+#define VIOCWAITFOREVER _VICEIOCTL(23)
+#define VIOCSETCACHESIZE _VICEIOCTL(24)
+#define VIOCFLUSHCB _VICEIOCTL(25)
+#define VIOCNEWCELL _VICEIOCTL(26)
+#define VIOCGETCELL _VICEIOCTL(27)
+#define VIOC_AFS_DELETE_MT_PT _VICEIOCTL(28)
+#define VIOC_AFS_STAT_MT_PT _VICEIOCTL(29)
+#define VIOC_FILE_CELL_NAME _VICEIOCTL(30)
+#define VIOC_GET_WS_CELL _VICEIOCTL(31)
+#define VIOC_AFS_MARINER_HOST _VICEIOCTL(32)
+#define VIOC_GET_PRIMARY_CELL _VICEIOCTL(33)
+#define VIOC_VENUSLOG _VICEIOCTL(34)
+#define VIOC_GETCELLSTATUS _VICEIOCTL(35)
+#define VIOC_SETCELLSTATUS _VICEIOCTL(36)
+#define VIOC_FLUSHVOLUME _VICEIOCTL(37)
+#define VIOC_AFS_SYSNAME _VICEIOCTL(38)
+#define VIOC_EXPORTAFS _VICEIOCTL(39)
+#define VIOCGETCACHEPARAMS _VICEIOCTL(40)
+#define VIOCCONNECTMODE _VICEIOCTL(41)
+#define VIOCGETVCXSTATUS _VICEIOCTL(41)
+#define VIOC_SETSPREFS33 _VICEIOCTL(42)
+#define VIOC_GETSPREFS _VICEIOCTL(43)
+#define VIOC_GAG _VICEIOCTL(44)
+#define VIOC_TWIDDLE _VICEIOCTL(45)
+#define VIOC_SETSPREFS _VICEIOCTL(46)
+#define VIOC_STORBEHIND _VICEIOCTL(47)
+#define VIOC_GCPAGS _VICEIOCTL(48)
+#define VIOC_GETINITPARAMS _VICEIOCTL(49)
+#define VIOC_GETCPREFS _VICEIOCTL(50)
+#define VIOC_SETCPREFS _VICEIOCTL(51)
+#define VIOC_FLUSHMOUNT _VICEIOCTL(52)
+#define VIOC_RXSTATPROC _VICEIOCTL(53)
+#define VIOC_RXSTATPEER _VICEIOCTL(54)
+
+#define VIOC_GETRXKCRYPT _VICEIOCTL(55)
+#define VIOC_SETRXKCRYPT _VICEIOCTL(56)
+
+/* arla specific */
+
+#define VIOC_FPRIOSTATUS _VICEIOCTL(57)
+#define VIOC_FHGET _VICEIOCTL(58)
+#define VIOC_FHOPEN _VICEIOCTL(59)
+#define VIOC_NNPFSDEBUG _VICEIOCTL(60)
+#define VIOC_NNPFSDEBUG _VICEIOCTL(60)
+#define VIOC_ARLADEBUG _VICEIOCTL(61)
+#define VIOC_AVIATOR _VICEIOCTL(62)
+#define VIOC_NNPFSDEBUG_PRINT _VICEIOCTL(63)
+#define VIOC_CALCULATE_CACHE _VICEIOCTL(64)
+#define VIOC_BREAKCALLBACK _VICEIOCTL(65)
+#define VIOC_PREFETCHTAPE _VICEIOCTL(66)
+#define VIOC_RESIDENCY_CMD _VICEIOCTL(67)
+
+/*
+ * GETCELLSTATUS flags
+ */
+
+#define CELLSTATUS_PRIMARY 0x01 /* this is the `primary' cell */
+#define CELLSTATUS_SETUID 0x02 /* setuid honored for this cell */
+#define CELLSTATUS_OBSOLETE_VL 0x04 /* uses obsolete VL servers */
+
+/*
+ * VIOCCONNECTMODE arguments
+ */
+
+#define CONNMODE_PROBE 0
+#define CONNMODE_CONN 1
+#define CONNMODE_FETCH 2
+#define CONNMODE_DISCONN 3
+#define CONNMODE_PARCONNECTED 4
+
+/*
+ * The struct for VIOC_FPRIOSTATUS
+ */
+
+#define FPRIO_MAX 100
+#define FPRIO_MIN 0
+#define FPRIO_DEFAULT FPRIO_MAX
+
+#define FPRIO_GET 0
+#define FPRIO_SET 1
+#define FPRIO_GETMAX 2
+#define FPRIO_SETMAX 3
+
+struct vioc_fprio {
+ int16_t cmd;
+ int16_t prio;
+ int32_t Cell;
+ int32_t Volume;
+ int32_t Vnode;
+ int32_t Unique;
+};
+
+/*
+ * Flags for VIOCCKSERV
+ */
+
+#define CKSERV_DONTPING 1
+#define CKSERV_FSONLY 2
+
+#define CKSERV_MAXSERVERS 16 /* limitation of VIOCCKSERV number of
+ returned servers */
+
+struct ViceIoctl {
+ caddr_t in, out;
+ short in_size;
+ short out_size;
+};
+
+struct ClearToken {
+ int32_t AuthHandle;
+ char HandShakeKey[8];
+ int32_t ViceId;
+ int32_t BeginTimestamp;
+ int32_t EndTimestamp;
+};
+
+#endif
diff --git a/sys/nnpfs/nnpfs_queue.h b/sys/nnpfs/nnpfs_queue.h
new file mode 100644
index 00000000000..bbe4e94097e
--- /dev/null
+++ b/sys/nnpfs/nnpfs_queue.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2002, Stockholms Universitet
+ * (Stockholm University, Stockholm Sweden)
+ * 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. Neither the name of the university nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+ */
+
+/* $arla: nnpfs_queue.h,v 1.1 2002/11/28 06:24:23 lha Exp $ */
+
+/* Inspirered by the queue macros in BSD. */
+
+#ifndef NNPFS_QUEUE_H
+#define NNPFS_QUEUE_H 1
+
+/* Define a head. */
+#define NNPQUEUE_HEAD(name, type) \
+struct name { \
+ struct type *nnpq_first; \
+ struct type **nnpq_last; \
+}
+
+/* Defining a entry. */
+#define NNPQUEUE_ENTRY(type) \
+struct { \
+ struct type *nnpq_next, **nnpq_prev; \
+}
+
+/* Is the queue empty. */
+#define NNPQUEUE_EMPTY(head) \
+ ((head)->nnpq_first == NULL)
+
+/* Init head. */
+#define NNPQUEUE_INIT(head) do { \
+ (head)->nnpq_first = NULL; \
+ (head)->nnpq_last = &(head)->nnpq_first; \
+} while (0)
+
+/* Insert elm after listelm, field is named. */
+#define NNPQUEUE_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.nnpq_next = (head)->nnpq_first) != NULL) \
+ (head)->nnpq_first->field.nnpq_prev = \
+ &(elm)->field.nnpq_next; \
+ else \
+ (head)->nnpq_last = &(elm)->field.nnpq_next; \
+ (head)->nnpq_first = (elm); \
+ (elm)->field.nnpq_prev = &(head)->nnpq_first; \
+} while (0)
+
+/* Remove an entry. */
+#define NNPQUEUE_REMOVE(elm,head,field) do { \
+ if (((elm)->field.nnpq_next) != NULL) \
+ (elm)->field.nnpq_next->field.nnpq_prev = \
+ (elm)->field.nnpq_prev; \
+ else \
+ (head)->nnpq_last = (elm)->field.nnpq_prev; \
+ *(elm)->field.nnpq_prev = (elm)->field.nnpq_next; \
+} while(0)
+
+/* Iterate over the list. */
+#define NNPQUEUE_FOREACH(var,head,field) \
+ for ((var) = ((head)->nnpq_first); \
+ (var); \
+ (var) = ((var)->field.nnpq_next))
+
+#endif /* NNPFS_QUEUE_H */
diff --git a/sys/nnpfs/nnpfs_syscalls-common.c b/sys/nnpfs/nnpfs_syscalls-common.c
new file mode 100644
index 00000000000..cfe06490fe4
--- /dev/null
+++ b/sys/nnpfs/nnpfs_syscalls-common.c
@@ -0,0 +1,672 @@
+/*
+ * Copyright (c) 1995 - 2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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 <nnpfs/nnpfs_locl.h>
+
+RCSID("$arla: nnpfs_syscalls-common.c,v 1.72 2003/01/19 20:53:49 lha Exp $");
+
+/*
+ * NNPFS system calls.
+ */
+
+#include <nnpfs/nnpfs_syscalls.h>
+#include <nnpfs/nnpfs_message.h>
+#include <nnpfs/nnpfs_fs.h>
+#include <nnpfs/nnpfs_dev.h>
+#include <nnpfs/nnpfs_node.h>
+#include <nnpfs/nnpfs_vfsops.h>
+#include <nnpfs/nnpfs_deb.h>
+
+/* Misc syscalls */
+#ifdef HAVE_SYS_IOCCOM_H
+#include <sys/ioccom.h>
+#elif defined(HAVE_SYS_IOCTL_H)
+#include <sys/ioctl.h>
+#endif
+/*
+ * XXX - horrible kludge. If we are openbsd and not building an lkm,
+ * then use their headerfile.
+ */
+#if (defined(__OpenBSD__) || defined(__NetBSD__)) && !defined(_LKM)
+#define NNPFS_NOT_LKM 1
+#elif defined(__FreeBSD__) && !defined(KLD_MODULE)
+#define NNPFS_NOT_LKM 1
+#endif
+
+#ifdef NNPFS_NOT_LKM
+#include <nnpfs/nnpfs_pioctl.h>
+#else
+#include <kafs.h>
+#endif
+
+int (*old_setgroups_func)(syscall_d_thread_t *p, void *v, register_t *retval);
+
+#if defined(__FreeBSD__) && __FreeBSD_version >= 500026
+/*
+ * XXX This is wrong
+ */
+static struct ucred *
+nnpfs_crcopy(struct ucred *cr)
+{
+ struct ucred *ncr;
+
+ if (crshared(cr)) {
+ ncr = crdup(cr);
+ crfree(cr);
+ return ncr;
+ }
+ return cr;
+}
+#else
+#define nnpfs_crcopy crcopy
+#endif
+
+
+/*
+ * the syscall entry point
+ */
+
+#ifdef NNPFS_NOT_LKM
+int
+sys_nnpfspioctl(syscall_d_thread_t *proc, void *varg, register_t *return_value)
+#else
+int
+nnpfspioctl(syscall_d_thread_t *proc, void *varg, register_t *return_value)
+#endif
+{
+#ifdef NNPFS_NOT_LKM
+ struct sys_nnpfspioctl_args *arg = (struct sys_nnpfspioctl_args *) varg;
+#else
+ struct sys_pioctl_args *arg = (struct sys_pioctl_args *) varg;
+#endif
+ int error = EINVAL;
+
+ switch (SCARG(arg, operation)) {
+ case AFSCALL_PIOCTL:
+ error = nnpfs_pioctl_call(syscall_thread_to_thread(proc),
+ varg, return_value);
+ break;
+ case AFSCALL_SETPAG:
+#ifdef HAVE_FREEBSD_THREAD
+ error = nnpfs_setpag_call(&nnpfs_thread_to_cred(proc));
+#else
+ error = nnpfs_setpag_call(&nnpfs_proc_to_cred(syscall_thread_to_thread(proc)));
+#endif
+ break;
+ default:
+ NNPFSDEB(XDEBSYS, ("Unimplemeted nnpfspioctl: %d\n",
+ SCARG(arg, operation)));
+ error = EINVAL;
+ break;
+ }
+
+ return error;
+}
+
+/*
+ * Def pag:
+ * 33536 <= g0 <= 34560
+ * 32512 <= g1 <= 48896
+ */
+
+#define NNPFS_PAG1_LLIM 33536
+#define NNPFS_PAG1_ULIM 34560
+#define NNPFS_PAG2_LLIM 32512
+#define NNPFS_PAG2_ULIM 48896
+
+static gid_t pag_part_one = NNPFS_PAG1_LLIM;
+static gid_t pag_part_two = NNPFS_PAG2_LLIM;
+
+/*
+ * Is `cred' member of a PAG?
+ */
+
+static int
+nnpfs_is_pag(struct ucred *cred)
+{
+ /* The first group is the gid of the user ? */
+
+ if (cred->cr_ngroups >= 3 &&
+ cred->cr_groups[1] >= NNPFS_PAG1_LLIM &&
+ cred->cr_groups[1] <= NNPFS_PAG1_ULIM &&
+ cred->cr_groups[2] >= NNPFS_PAG2_LLIM &&
+ cred->cr_groups[2] <= NNPFS_PAG2_ULIM)
+ return 1;
+ else
+ return 0;
+}
+
+/*
+ * Return the pag used by `cred'
+ */
+
+nnpfs_pag_t
+nnpfs_get_pag(struct ucred *cred)
+{
+ if (nnpfs_is_pag(cred)) {
+
+ return (((cred->cr_groups[1] << 16) & 0xFFFF0000) |
+ ((cred->cr_groups[2] & 0x0000FFFF)));
+
+ } else
+ return cred->cr_uid; /* XXX */
+}
+
+/*
+ * Set the pag in `ret_cred' and return a new cred.
+ */
+
+static int
+store_pag (struct ucred **ret_cred, gid_t part1, gid_t part2)
+{
+ struct ucred *cred = *ret_cred;
+
+ if (!nnpfs_is_pag (cred)) {
+ int i;
+
+ if (cred->cr_ngroups + 2 >= NGROUPS)
+ return E2BIG;
+
+ cred = nnpfs_crcopy (cred);
+
+ for (i = cred->cr_ngroups - 1; i > 0; i--) {
+ cred->cr_groups[i + 2] = cred->cr_groups[i];
+ }
+ cred->cr_ngroups += 2;
+ } else {
+ cred = nnpfs_crcopy (cred);
+ }
+ cred->cr_groups[1] = part1;
+ cred->cr_groups[2] = part2;
+ *ret_cred = cred;
+
+ return 0;
+}
+
+/*
+ * Acquire a new pag in `ret_cred'
+ */
+
+int
+nnpfs_setpag_call(struct ucred **ret_cred)
+{
+ int ret;
+
+ ret = store_pag (ret_cred, pag_part_one, pag_part_two++);
+ if (ret)
+ return ret;
+
+ if (pag_part_two > NNPFS_PAG2_ULIM) {
+ pag_part_one++;
+ pag_part_two = NNPFS_PAG2_LLIM;
+ }
+ return 0;
+}
+
+#ifndef NNPFS_NOT_LKM
+/*
+ * remove a pag
+ */
+
+static int
+nnpfs_unpag (struct ucred *cred)
+{
+ while (nnpfs_is_pag (cred)) {
+ int i;
+
+ for (i = 0; i < cred->cr_ngroups - 2; ++i)
+ cred->cr_groups[i] = cred->cr_groups[i+2];
+ cred->cr_ngroups -= 2;
+ }
+ return 0;
+}
+
+/*
+ * A wrapper around setgroups that preserves the pag.
+ */
+
+int
+nnpfs_setgroups (syscall_d_thread_t *p,
+ void *varg,
+ register_t *retval)
+{
+ struct nnpfs_setgroups_args *uap = (struct nnpfs_setgroups_args *)varg;
+#ifdef HAVE_FREEBSD_THREAD
+ struct ucred **cred = &nnpfs_thread_to_cred(p);
+#else
+ struct ucred **cred = &nnpfs_proc_to_cred(syscall_thread_to_thread(p));
+#endif
+
+ if (nnpfs_is_pag (*cred)) {
+ gid_t part1, part2;
+ int ret;
+
+ if (SCARG(uap,gidsetsize) + 2 > NGROUPS)
+ return EINVAL;
+
+ part1 = (*cred)->cr_groups[1];
+ part2 = (*cred)->cr_groups[2];
+ ret = (*old_setgroups_func) (p, uap, retval);
+ if (ret)
+ return ret;
+ return store_pag (cred, part1, part2);
+ } else {
+ int ret;
+
+ ret = (*old_setgroups_func) (p, uap, retval);
+ /* don't support setting a PAG */
+ if (nnpfs_is_pag (*cred)) {
+ nnpfs_unpag (*cred);
+ return EINVAL;
+ }
+ return ret;
+ }
+}
+#endif /* !NNPFS_NOT_LKM */
+
+/*
+ * Return the vnode corresponding to `pathptr'
+ */
+
+static int
+lookup_node (const char *pathptr,
+ int follow_links_p,
+ struct vnode **res,
+ d_thread_t *proc)
+{
+ int error;
+ char path[MAXPATHLEN];
+#ifdef __osf__
+ struct nameidata *ndp = &u.u_nd;
+#else
+ struct nameidata nd, *ndp = &nd;
+#endif
+ struct vnode *vp;
+ size_t count;
+
+ NNPFSDEB(XDEBSYS, ("nnpfs_syscall: looking up: %lx\n",
+ (unsigned long)pathptr));
+
+ error = copyinstr((char *) pathptr, path, MAXPATHLEN, &count);
+
+ NNPFSDEB(XDEBSYS, ("nnpfs_syscall: looking up: %s, error: %d\n", path, error));
+
+ if (error)
+ return error;
+
+ NDINIT(ndp, LOOKUP,
+ follow_links_p ? FOLLOW : 0,
+ UIO_SYSSPACE, path, proc);
+
+ error = namei(ndp);
+
+ if (error != 0) {
+ NNPFSDEB(XDEBSYS, ("nnpfs_syscall: error during namei: %d\n", error));
+ return EINVAL;
+ }
+
+ vp = ndp->ni_vp;
+
+ *res = vp;
+ return 0;
+}
+
+/*
+ * implement nnpfs fhget in a way that should be compatible with the native
+ * getfh
+ */
+
+static int
+getfh_compat (d_thread_t *p,
+ struct ViceIoctl *vice_ioctl,
+ struct vnode *vp)
+{
+ /* This is to be same as getfh */
+ fhandle_t fh;
+ int error;
+
+ bzero((caddr_t)&fh, sizeof(fh));
+ fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
+#if __osf__
+ VFS_VPTOFH(vp, &fh.fh_fid, error);
+#else
+ error = VFS_VPTOFH(vp, &fh.fh_fid);
+#endif
+ if (error)
+ return error;
+
+ if (vice_ioctl->out_size < sizeof(fh))
+ return EINVAL;
+
+ return copyout((caddr_t)&fh, vice_ioctl->out, sizeof (fh));
+}
+
+/*
+ * implement nnpfs fhget by combining (dev, ino, generation)
+ */
+
+#ifndef __OpenBSD__
+static int
+trad_fhget (d_thread_t *p,
+ struct ViceIoctl *vice_ioctl,
+ struct vnode *vp)
+{
+ int error;
+ struct mount *mnt;
+ struct vattr vattr;
+ size_t len;
+ struct nnpfs_fhandle_t nnpfs_handle;
+ struct nnpfs_fh_args fh_args;
+
+#ifdef HAVE_FREEBSD_THREAD
+ nnpfs_vop_getattr(vp, &vattr, nnpfs_thread_to_cred(p), p, error);
+#else
+ nnpfs_vop_getattr(vp, &vattr, nnpfs_proc_to_cred(p), p, error);
+#endif
+ if (error)
+ return error;
+
+ mnt = vp->v_mount;
+
+ SCARG(&fh_args, fsid) = mnt->mnt_stat.f_fsid;
+ SCARG(&fh_args, fileid) = vattr.va_fileid;
+ SCARG(&fh_args, gen) = vattr.va_gen;
+
+ nnpfs_handle.len = sizeof(fh_args);
+ memcpy (nnpfs_handle.fhdata, &fh_args, sizeof(fh_args));
+ len = sizeof(nnpfs_handle);
+
+ if (vice_ioctl->out_size < len)
+ return EINVAL;
+
+ error = copyout (&nnpfs_handle, vice_ioctl->out, len);
+ if (error) {
+ NNPFSDEB(XDEBSYS, ("fhget_call: copyout failed: %d\n", error));
+ }
+ return error;
+}
+#endif /* ! __OpenBSD__ */
+
+/*
+ * return file handle of `vp' in vice_ioctl->out
+ * vp is vrele:d
+ */
+
+static int
+fhget_call (d_thread_t *p,
+ struct ViceIoctl *vice_ioctl,
+ struct vnode *vp)
+{
+ int error;
+
+ NNPFSDEB(XDEBSYS, ("fhget_call\n"));
+
+ if (vp == NULL)
+ return EBADF;
+
+#if defined(__APPLE__) || defined(__osf__)
+ error = EINVAL; /* XXX: Leaks vnodes if fhget/fhopen is used */
+ goto out;
+#endif
+
+ error = nnpfs_suser (p);
+ if (error)
+ goto out;
+
+#if (defined(HAVE_GETFH) && defined(HAVE_FHOPEN)) || defined(__osf__)
+ error = getfh_compat (p, vice_ioctl, vp);
+#else
+ error = trad_fhget (p, vice_ioctl, vp);
+#endif /* HAVE_GETFH && HAVE_FHOPEN */
+out:
+ vrele(vp);
+ return error;
+}
+
+/*
+ * open the file specified in `vice_ioctl->in'
+ */
+
+static int
+fhopen_call (d_thread_t *p,
+ struct ViceIoctl *vice_ioctl,
+ struct vnode *vp,
+ int flags,
+ register_t *retval)
+{
+
+ NNPFSDEB(XDEBSYS, ("fhopen_call: flags = %d\n", flags));
+
+ if (vp != NULL) {
+ vrele (vp);
+ return EINVAL;
+ }
+
+#if defined(__APPLE__) || defined(__osf__)
+ return EINVAL; /* XXX: Leaks vnodes if fhget/fhopen is used */
+#endif
+
+ return nnpfs_fhopen (p,
+ (struct nnpfs_fhandle_t *)vice_ioctl->in,
+ flags,
+ retval);
+}
+
+/*
+ * Send the pioctl to arlad
+ */
+
+static int
+remote_pioctl (d_thread_t *p,
+ struct sys_pioctl_args *arg,
+ struct ViceIoctl *vice_ioctl,
+ struct vnode *vp)
+{
+ int error = 0;
+ struct nnpfs_message_pioctl *msg = NULL;
+ struct nnpfs_message_wakeup_data *msg2;
+
+ msg = malloc(sizeof(*msg), M_TEMP, M_WAITOK | M_ZERO);
+ if (msg == NULL) {
+ error = ENOMEM;
+ goto done;
+ }
+
+ if (vp != NULL) {
+ struct nnpfs_node *xn;
+
+ if (vp->v_tag != VT_NNPFS) {
+ NNPFSDEB(XDEBSYS, ("nnpfs_syscall: file is not in afs\n"));
+ vrele(vp);
+ error = EINVAL;
+ goto done;
+ }
+
+ xn = VNODE_TO_XNODE(vp);
+
+ msg->handle = xn->handle;
+ vrele(vp);
+ }
+
+ if (vice_ioctl->in_size < 0) {
+ printf("nnpfs: remote pioctl: got a negative data size: opcode: %d",
+ SCARG(arg, a_opcode));
+ error = EINVAL;
+ goto done;
+ }
+
+ if (vice_ioctl->in_size > NNPFS_MSG_MAX_DATASIZE) {
+ printf("nnpfs_pioctl_call: got a humongous in packet: opcode: %d",
+ SCARG(arg, a_opcode));
+ error = EINVAL;
+ goto done;
+ }
+ if (vice_ioctl->in_size != 0) {
+ error = copyin(vice_ioctl->in, msg->msg, vice_ioctl->in_size);
+ if (error)
+ goto done;
+ }
+
+ msg->header.opcode = NNPFS_MSG_PIOCTL;
+ msg->header.size = sizeof(*msg);
+ msg->opcode = SCARG(arg, a_opcode);
+
+ msg->insize = vice_ioctl->in_size;
+ msg->outsize = vice_ioctl->out_size;
+#ifdef HAVE_FREEBSD_THREAD
+ msg->cred.uid = nnpfs_thread_to_euid(p);
+ msg->cred.pag = nnpfs_get_pag(nnpfs_thread_to_cred(p));
+#else
+ msg->cred.uid = nnpfs_proc_to_euid(p);
+ msg->cred.pag = nnpfs_get_pag(nnpfs_proc_to_cred(p));
+#endif
+
+ error = nnpfs_message_rpc(0, &(msg->header), sizeof(*msg), p); /* XXX */
+ msg2 = (struct nnpfs_message_wakeup_data *) msg;
+
+ if (error == 0)
+ error = msg2->error;
+ if (error == ENODEV)
+ error = EINVAL;
+
+ if (error == 0 && msg2->header.opcode == NNPFS_MSG_WAKEUP_DATA) {
+ int len;
+
+ len = msg2->len;
+ if (len > vice_ioctl->out_size)
+ len = vice_ioctl->out_size;
+ if (len > NNPFS_MSG_MAX_DATASIZE)
+ len = NNPFS_MSG_MAX_DATASIZE;
+ if (len < 0)
+ len = 0;
+
+ error = copyout(msg2->msg, vice_ioctl->out, len);
+ }
+ done:
+ free(msg, M_TEMP);
+ return error;
+}
+
+static int
+nnpfs_debug (d_thread_t *p,
+ struct ViceIoctl *vice_ioctl)
+{
+ int32_t flags;
+ int error;
+
+ if (vice_ioctl->in_size != 0) {
+ if (vice_ioctl->in_size < sizeof(int32_t))
+ return EINVAL;
+
+ error = nnpfs_suser (p);
+ if (error)
+ return error;
+
+ error = copyin (vice_ioctl->in,
+ &flags,
+ sizeof(flags));
+ if (error)
+ return error;
+
+ nnpfsdeb = flags;
+ }
+
+ if (vice_ioctl->out_size != 0) {
+ if (vice_ioctl->out_size < sizeof(int32_t))
+ return EINVAL;
+
+ error = copyout (&nnpfsdeb,
+ vice_ioctl->out,
+ sizeof(int32_t));
+ if (error)
+ return error;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Handle `pioctl'
+ */
+
+int
+nnpfs_pioctl_call(d_thread_t *proc,
+ struct sys_pioctl_args *arg,
+ register_t *return_value)
+{
+ int error;
+ struct ViceIoctl vice_ioctl;
+ char *pathptr;
+ struct vnode *vp = NULL;
+
+ NNPFSDEB(XDEBSYS, ("nnpfs_syscall(%d, %lx, %d, %lx, %d)\n",
+ SCARG(arg, operation),
+ (unsigned long)SCARG(arg, a_pathP),
+ SCARG(arg, a_opcode),
+ (unsigned long)SCARG(arg, a_paramsP),
+ SCARG(arg, a_followSymlinks)));
+
+ /* Copy in the data structure for us */
+
+ error = copyin(SCARG(arg, a_paramsP),
+ &vice_ioctl,
+ sizeof(vice_ioctl));
+
+ if (error)
+ return error;
+
+ pathptr = SCARG(arg, a_pathP);
+
+ if (pathptr != NULL) {
+ error = lookup_node (pathptr, SCARG(arg, a_followSymlinks), &vp,
+ proc);
+ if(error)
+ return error;
+ }
+
+ switch (SCARG(arg, a_opcode)) {
+ case VIOC_FHGET :
+ return fhget_call (proc, &vice_ioctl, vp);
+ case VIOC_FHOPEN :
+ return fhopen_call (proc, &vice_ioctl, vp,
+ SCARG(arg, a_followSymlinks), return_value);
+ case VIOC_NNPFSDEBUG :
+ if (vp != NULL)
+ vrele (vp);
+ return nnpfs_debug (proc, &vice_ioctl);
+ default :
+ NNPFSDEB(XDEBSYS, ("a_opcode = %x\n", SCARG(arg, a_opcode)));
+ return remote_pioctl (proc, arg, &vice_ioctl, vp);
+ }
+}
diff --git a/sys/nnpfs/nnpfs_syscalls-dummy.c b/sys/nnpfs/nnpfs_syscalls-dummy.c
new file mode 100644
index 00000000000..8685070aa82
--- /dev/null
+++ b/sys/nnpfs/nnpfs_syscalls-dummy.c
@@ -0,0 +1,10 @@
+/*
+ * This code released into public domain by Artur Grabowski <art@openbsd.org>
+ */
+#include <nnpfs/nnpfs_locl.h>
+
+int
+sys_nnpfspioctl(struct proc *proc, void *varg, register_t *retval)
+{
+ return ENOSYS;
+}
diff --git a/sys/nnpfs/nnpfs_syscalls.h b/sys/nnpfs/nnpfs_syscalls.h
new file mode 100644
index 00000000000..5b5d01a4ce3
--- /dev/null
+++ b/sys/nnpfs/nnpfs_syscalls.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $arla: nnpfs_syscalls.h,v 1.29 2003/01/19 20:53:54 lha Exp $ */
+
+#ifndef __nnpfs_syscalls
+#define __nnpfs_syscalls
+
+#include <nnpfs/nnpfs_common.h>
+#include <nnpfs/nnpfs_message.h>
+
+#include <nnpfs/afssysdefs.h>
+
+struct sys_pioctl_args {
+ syscallarg(int) operation;
+ syscallarg(char *) a_pathP;
+ syscallarg(int) a_opcode;
+ syscallarg(struct ViceIoctl *) a_paramsP;
+ syscallarg(int) a_followSymlinks;
+};
+
+#define NNPFS_FHMAXDATA 40
+
+struct nnpfs_fhandle_t {
+ u_short len;
+ u_short pad;
+ char fhdata[NNPFS_FHMAXDATA];
+};
+
+struct nnpfs_fh_args {
+ syscallarg(fsid_t) fsid;
+ syscallarg(long) fileid;
+ syscallarg(long) gen;
+};
+
+int nnpfs_install_syscalls(void);
+int nnpfs_uninstall_syscalls(void);
+int nnpfs_stat_syscalls(void);
+nnpfs_pag_t nnpfs_get_pag(struct ucred *);
+
+int nnpfs_setpag_call(struct ucred **ret_cred);
+int nnpfs_pioctl_call(d_thread_t *proc,
+ struct sys_pioctl_args *args,
+ register_t *return_value);
+
+int nnpfspioctl(syscall_d_thread_t *proc, void *varg, register_t *retval);
+
+int nnpfs_setgroups(syscall_d_thread_t *p, void *varg, register_t *retval);
+
+extern int (*old_setgroups_func)(syscall_d_thread_t *, void *, register_t *);
+extern int nnpfs_syscall_num; /* The old syscall number */
+
+
+#ifndef HAVE_KERNEL_SYS_LKMNOSYS
+#define sys_lkmnosys nosys
+#endif
+
+#ifndef SYS_MAXSYSCALL
+#define SYS_MAXSYSCALL nsysent
+#endif
+
+#endif /* __nnpfs_syscalls */
diff --git a/sys/nnpfs/nnpfs_vfsops-bsd.c b/sys/nnpfs/nnpfs_vfsops-bsd.c
new file mode 100644
index 00000000000..2e29829aa27
--- /dev/null
+++ b/sys/nnpfs/nnpfs_vfsops-bsd.c
@@ -0,0 +1,528 @@
+/*
+ * Copyright (c) 1995 - 2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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 <nnpfs/nnpfs_locl.h>
+
+RCSID("$arla: nnpfs_vfsops-bsd.c,v 1.72 2002/12/19 10:30:17 lha Exp $");
+
+/*
+ * NNPFS vfs operations.
+ */
+
+#include <nnpfs/nnpfs_common.h>
+#include <nnpfs/nnpfs_message.h>
+#include <nnpfs/nnpfs_fs.h>
+#include <nnpfs/nnpfs_dev.h>
+#include <nnpfs/nnpfs_deb.h>
+#include <nnpfs/nnpfs_vfsops.h>
+#include <nnpfs/nnpfs_vfsops-bsd.h>
+#include <nnpfs/nnpfs_vnodeops.h>
+
+int
+nnpfs_mount_caddr(struct mount *mp,
+ const char *user_path,
+ caddr_t user_data,
+ struct nameidata *ndp,
+ d_thread_t *p)
+{
+ return nnpfs_mount_common(mp, user_path, user_data, ndp, p);
+}
+
+int
+nnpfs_start(struct mount * mp, int flags, d_thread_t * p)
+{
+ NNPFSDEB(XDEBVFOPS, ("nnpfs_start mp = %lx, flags = %d, proc = %lx\n",
+ (unsigned long)mp, flags, (unsigned long)p));
+ return 0;
+}
+
+
+int
+nnpfs_unmount(struct mount * mp, int mntflags, d_thread_t *p)
+{
+ NNPFSDEB(XDEBVFOPS, ("nnpfs_umount: mp = %lx, mntflags = %d, proc = %lx\n",
+ (unsigned long)mp, mntflags, (unsigned long)p));
+ return nnpfs_unmount_common(mp, mntflags);
+}
+
+int
+nnpfs_root(struct mount *mp, struct vnode **vpp)
+{
+ NNPFSDEB(XDEBVFOPS, ("nnpfs_root mp = %lx\n", (unsigned long)mp));
+#ifdef HAVE_FREEBSD_THREAD
+ return nnpfs_root_common(mp, vpp, nnpfs_curthread(), nnpfs_curthread()->td_proc->p_ucred);
+#else
+ return nnpfs_root_common(mp, vpp, nnpfs_curproc(), nnpfs_curproc()->p_ucred);
+#endif
+}
+
+int
+nnpfs_quotactl(struct mount *mp, int cmd, uid_t uid, caddr_t arg, d_thread_t *p)
+{
+ NNPFSDEB(XDEBVFOPS, ("nnpfs_quotactl: mp = %lx, cmd = %d, uid = %u, "
+ "arg = %lx, proc = %lx\n",
+ (unsigned long)mp, cmd, uid,
+ (unsigned long)arg, (unsigned long)p));
+ return EOPNOTSUPP;
+}
+
+int
+nnpfs_statfs(struct mount *mp, struct statfs *sbp, d_thread_t *p)
+{
+ NNPFSDEB(XDEBVFOPS, ("nnpfs_statfs: mp = %lx, sbp = %lx, proc = %lx\n",
+ (unsigned long)mp,
+ (unsigned long)sbp,
+ (unsigned long)p));
+ bcopy(&mp->mnt_stat, sbp, sizeof(*sbp));
+ return 0;
+}
+
+int
+nnpfs_sync(struct mount *mp, int waitfor, struct ucred *cred, d_thread_t *p)
+{
+ NNPFSDEB(XDEBVFOPS, ("nnpfs_sync: mp = %lx, waitfor = %d, "
+ "cred = %lx, proc = %lx\n",
+ (unsigned long)mp,
+ waitfor,
+ (unsigned long)cred,
+ (unsigned long)p));
+ return 0;
+}
+
+int
+nnpfs_vget(struct mount * mp,
+#ifdef __APPLE__
+ void *ino,
+#else
+ ino_t ino,
+#endif
+ struct vnode ** vpp)
+{
+ NNPFSDEB(XDEBVFOPS, ("nnpfs_vget\n"));
+ return EOPNOTSUPP;
+}
+
+static int
+common_fhtovp(struct mount * mp,
+ struct fid * fhp,
+ struct vnode ** vpp)
+{
+#ifdef ARLA_KNFS
+ struct netcred *np = NULL;
+ struct nnpfs_node *xn;
+ struct vnode *vp;
+ nnpfs_handle handle;
+ int error;
+
+ NNPFSDEB(XDEBVFOPS, ("nnpfs_fhtovp\n"));
+
+ if (fhp->fid_len != 16) {
+ printf("nnpfs_fhtovp: *PANIC* got a invalid length of a fid\n");
+ return EINVAL;
+ }
+
+ memcpy(&handle, fhp->fid_data, sizeof(handle));
+ NNPFSDEB(XDEBVFOPS, ("nnpfs_fhtovp: fid: %d.%d.%d.%d\n",
+ handle.a, handle.d, handle.c, handle.d));
+
+ NNPFSDEB(XDEBVFOPS, ("nnpfs_fhtovp: nnpfs_vnode_find\n"));
+ xn = nnpfs_node_find(&nnpfs[0].nodehead, &handle);
+
+ if (xn == NULL) {
+ struct nnpfs_message_getattr msg;
+
+ error = nnpfs_getnewvnode(nnpfs[0].mp, &vp, &handle);
+ if (error)
+ return error;
+
+ nnpfs_do_vget(vp, 0, curproc);
+
+ } else {
+ /* XXX access ? */
+ vp = XNODE_TO_VNODE(xn);
+
+ /* XXX wrong ? (we tell arla below) */
+ if (vp->v_usecount <= 0)
+ nnpfs_do_vget(vp, 0, curproc);
+ else
+ VREF(vp);
+ error = 0;
+ }
+
+ *vpp = vp;
+
+ if (error == 0) {
+ NNPFSDEB(XDEBVFOPS, ("nnpfs_fhtovp done\n"));
+
+ /*
+ * XXX tell arla about this node is hold by nfsd.
+ * There need to be code in nnpfs_write too.
+ */
+ } else
+ NNPFSDEB(XDEBVFOPS, ("nnpfs_fhtovp failed (%d)\n", error));
+
+ return error;
+#else /* !ARLA_KNFS */
+ return EOPNOTSUPP;
+#endif /* !ARLA_KNFS */
+}
+
+/* new style fhtovp */
+
+#ifdef HAVE_STRUCT_VFSOPS_VFS_CHECKEXP
+int
+nnpfs_fhtovp(struct mount * mp,
+ struct fid * fhp,
+ struct vnode ** vpp)
+{
+ return common_fhtovp (mp, fhp, vpp);
+}
+
+#else /* !HAVE_STRUCT_VFSOPS_VFS_CHECKEXP */
+
+/* old style fhtovp */
+
+int
+nnpfs_fhtovp(struct mount * mp,
+ struct fid * fhp,
+ struct mbuf * nam,
+ struct vnode ** vpp,
+ int *exflagsp,
+ struct ucred ** credanonp)
+{
+ static struct ucred fhtovpcred;
+ int error;
+
+ /* XXX: Should see if we is exported to this client */
+#if 0
+ np = vfs_export_lookup(mp, &ump->um_export, nam);
+ if (np == NULL)
+ return EACCES;
+#endif
+ error = common_fhtovp(mp, fhp, vpp);
+ if (error == 0) {
+ fhtovpcred.cr_uid = 0;
+ fhtovpcred.cr_gid = 0;
+ fhtovpcred.cr_ngroups = 0;
+
+#ifdef MNT_EXPUBLIC
+ *exflagsp = MNT_EXPUBLIC;
+#else
+ *exflagsp = 0;
+#endif
+ *credanonp = &fhtovpcred;
+ }
+ return error;
+}
+#endif /* !HAVE_STRUCT_VFSOPS_VFS_CHECKEXP */
+
+int
+nnpfs_checkexp (struct mount *mp,
+#ifdef __FreeBSD__
+ struct sockaddr *nam,
+#else
+ struct mbuf *nam,
+#endif
+ int *exflagsp,
+ struct ucred **credanonp)
+{
+ NNPFSDEB(XDEBVFOPS, ("nnpfs_checkexp\n"));
+
+#if 0
+ np = vfs_export_lookup(mp, &ump->um_export, nam);
+ if (np == NULL)
+ return EACCES;
+#endif
+ return 0;
+}
+
+int
+nnpfs_vptofh(struct vnode * vp,
+ struct fid * fhp)
+{
+#ifdef ARLA_KNFS
+ struct nnpfs_node *xn;
+ NNPFSDEB(XDEBVFOPS, ("nnpfs_vptofh\n"));
+
+ if (MAXFIDSZ < 16)
+ return EOPNOTSUPP;
+
+ xn = VNODE_TO_XNODE(vp);
+
+ if (xn == NULL)
+ return EINVAL;
+
+ fhp->fid_len = 16;
+ memcpy(fhp->fid_data, &xn->handle, 16);
+
+ return 0;
+#else
+ NNPFSDEB(XDEBVFOPS, ("nnpfs_vptofh\n"));
+ return EOPNOTSUPP;
+#endif
+}
+
+/*
+ * nnpfs complete dead vnodes implementation.
+ *
+ * this is because the dead_vnodeops_p is _not_ filesystem, but rather
+ * a part of the vfs-layer.
+ */
+
+int
+nnpfs_dead_lookup(struct vop_lookup_args * ap)
+ /* struct vop_lookup_args {
+ struct vnodeop_desc *a_desc;
+ struct vnode *a_dvp;
+ struct vnode **a_vpp;
+ struct componentname *a_cnp;
+}; */
+{
+ *ap->a_vpp = NULL;
+ return ENOTDIR;
+}
+
+/*
+ * Given `fsid', `fileid', and `gen', return in `vpp' a locked and
+ * ref'ed vnode from that file system with that id and generation.
+ * All is done in the context of `proc'. Returns 0 if successful, and
+ * error otherwise.
+ */
+
+int
+nnpfs_fhlookup (d_thread_t *proc,
+ struct nnpfs_fhandle_t *fhp,
+ struct vnode **vpp)
+{
+ int error;
+ struct mount *mp;
+#if !(defined(HAVE_GETFH) && defined(HAVE_FHOPEN))
+ struct ucred *cred = proc->p_ucred;
+ struct vattr vattr;
+ fsid_t fsid;
+ struct nnpfs_fh_args *fh_args = (struct nnpfs_fh_args *)fhp->fhdata;
+
+ NNPFSDEB(XDEBVFOPS, ("nnpfs_fhlookup (nnpfs)\n"));
+
+ error = nnpfs_suser (proc);
+ if (error)
+ return EPERM;
+
+ if (fhp->len < sizeof(struct nnpfs_fh_args))
+ return EINVAL;
+
+ fsid = SCARG(fh_args, fsid);
+
+ mp = nnpfs_vfs_getvfs (&fsid);
+ if (mp == NULL)
+ return ENXIO;
+
+#ifdef __APPLE__
+ {
+ uint32_t ino = SCARG(fh_args, fileid);
+ error = VFS_VGET(mp, &ino, vpp);
+ }
+#else
+ error = VFS_VGET(mp, SCARG(fh_args, fileid), vpp);
+#endif
+
+ if (error)
+ return error;
+
+ if (*vpp == NULL)
+ return ENOENT;
+
+ error = VOP_GETATTR(*vpp, &vattr, cred, proc);
+ if (error) {
+ vput(*vpp);
+ return error;
+ }
+
+ if (vattr.va_gen != SCARG(fh_args, gen)) {
+ vput(*vpp);
+ return ENOENT;
+ }
+#else /* HAVE_GETFH && HAVE_FHOPEN */
+ {
+ fhandle_t *fh = (fhandle_t *) fhp;
+
+ NNPFSDEB(XDEBVFOPS, ("nnpfs_fhlookup (native)\n"));
+
+ mp = nnpfs_vfs_getvfs (&fh->fh_fsid);
+ if (mp == NULL)
+ return ESTALE;
+
+ if ((error = VFS_FHTOVP(mp, &fh->fh_fid, vpp)) != 0) {
+ *vpp = NULL;
+ return error;
+ }
+ }
+#endif /* HAVE_GETFH && HAVE_FHOPEN */
+
+#ifdef HAVE_KERNEL_VFS_OBJECT_CREATE
+ if ((*vpp)->v_type == VREG && (*vpp)->v_object == NULL)
+#ifdef HAVE_FREEBSD_THREAD
+ nnpfs_vfs_object_create (*vpp, proc, proc->td_proc->p_ucred);
+#else
+ nnpfs_vfs_object_create (*vpp, proc, proc->p_ucred);
+#endif
+#elif __APPLE__
+ if ((*vpp)->v_type == VREG && (!UBCINFOEXISTS(*vpp))) {
+ ubc_info_init(*vpp);
+ }
+ ubc_hold(*vpp);
+#endif
+ return 0;
+}
+
+
+
+/*
+ * Perform an open operation on the vnode identified by a `nnpfs_fhandle_t'
+ * (see nnpfs_fhlookup) with flags `user_flags'. Returns 0 or
+ * error. If successful, the file descriptor is returned in `retval'.
+ */
+
+extern struct fileops vnops; /* sometimes declared in <file.h> */
+
+int
+nnpfs_fhopen (d_thread_t *proc,
+ struct nnpfs_fhandle_t *fhp,
+ int user_flags,
+ register_t *retval)
+{
+ int error;
+ struct vnode *vp;
+#ifdef HAVE_FREEBSD_THREAD
+ struct ucred *cred = proc->td_proc->p_ucred;
+#else
+ struct ucred *cred = proc->p_ucred;
+#endif
+ int flags = FFLAGS(user_flags);
+ int index;
+ struct file *fp;
+ int mode;
+ struct nnpfs_fhandle_t fh;
+
+ NNPFSDEB(XDEBVFOPS, ("nnpfs_fhopen: flags = %d\n", user_flags));
+
+ error = copyin (fhp, &fh, sizeof(fh));
+ if (error)
+ return error;
+
+ error = nnpfs_fhlookup (proc, &fh, &vp);
+ NNPFSDEB(XDEBVFOPS, ("nnpfs_fhlookup returned %d\n", error));
+ if (error)
+ return error;
+
+ switch (vp->v_type) {
+ case VDIR :
+ case VREG :
+ break;
+ case VLNK :
+ error = EMLINK;
+ goto out;
+ default :
+ error = EOPNOTSUPP;
+ goto out;
+ }
+
+ mode = 0;
+ if (flags & FWRITE) {
+ switch (vp->v_type) {
+ case VREG :
+ break;
+ case VDIR :
+ error = EISDIR;
+ goto out;
+ default :
+ error = EOPNOTSUPP;
+ goto out;
+ }
+
+ error = vn_writechk (vp);
+ if (error)
+ goto out;
+
+ mode |= VWRITE;
+ }
+ if (flags & FREAD)
+ mode |= VREAD;
+
+ if (mode) {
+ error = VOP_ACCESS(vp, mode, cred, proc);
+ if (error)
+ goto out;
+ }
+
+ error = VOP_OPEN(vp, flags, cred, proc);
+ if (error)
+ goto out;
+
+ error = falloc(proc, &fp, &index);
+ if (error)
+ goto out;
+
+ if (flags & FWRITE)
+ vp->v_writecount++;
+
+#if defined(__FreeBSD_version) && __FreeBSD_version >= 300000
+ if (vp->v_type == VREG) {
+#ifdef HAVE_FREEBSD_THREAD
+ error = nnpfs_vfs_object_create(vp, proc, proc->td_proc->p_ucred);
+#else
+ error = nnpfs_vfs_object_create(vp, proc, proc->p_ucred);
+#endif
+ if (error)
+ goto out;
+ }
+#endif
+
+ fp->f_flag = flags & FMASK;
+ fp->f_type = DTYPE_VNODE;
+ fp->f_ops = &vnops;
+ fp->f_data = (caddr_t)vp;
+ nnpfs_vfs_unlock(vp, proc);
+ *retval = index;
+#ifdef FILE_UNUSE
+ FILE_UNUSE(fp, proc);
+#endif
+#ifdef __APPLE__
+ *fdflags(proc, index) &= ~UF_RESERVED;
+#endif
+ return 0;
+out:
+ NNPFSDEB(XDEBVFOPS, ("nnpfs_fhopen: error = %d\n", error));
+ vput(vp);
+ return error;
+}
diff --git a/sys/nnpfs/nnpfs_vfsops-bsd.h b/sys/nnpfs/nnpfs_vfsops-bsd.h
new file mode 100644
index 00000000000..1d67f3d764b
--- /dev/null
+++ b/sys/nnpfs/nnpfs_vfsops-bsd.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $arla: nnpfs_vfsops-bsd.h,v 1.14 2002/09/07 10:46:09 lha Exp $ */
+
+#ifndef _nnpfs_vfsops_bsd_h
+#define _nnpfs_vfsops_bsd_h
+
+int
+nnpfs_mount_caddr(struct mount *mp, const char *user_path, caddr_t user_data,
+ struct nameidata *ndp, d_thread_t *p);
+
+int
+nnpfs_start(struct mount * mp, int flags, d_thread_t * p);
+
+int
+nnpfs_unmount(struct mount * mp, int mntflags, d_thread_t *p);
+
+int
+nnpfs_root(struct mount *mp, struct vnode **vpp);
+
+int
+nnpfs_quotactl(struct mount *mp, int cmd, uid_t uid, caddr_t arg, d_thread_t *p);
+
+int
+nnpfs_statfs(struct mount *mp, struct statfs *sbp, d_thread_t *p);
+
+int
+nnpfs_sync(struct mount *mp, int waitfor, struct ucred *cred, d_thread_t *p);
+
+int
+nnpfs_vget(struct mount * mp,
+#ifdef __APPLE__
+ void *ino,
+#else
+ ino_t ino,
+#endif
+ struct vnode ** vpp);
+
+#ifdef HAVE_STRUCT_VFSOPS_VFS_CHECKEXP
+int
+nnpfs_fhtovp(struct mount * mp,
+ struct fid * fhp,
+ struct vnode ** vpp);
+#else
+int
+nnpfs_fhtovp(struct mount * mp,
+ struct fid * fhp,
+ struct mbuf * nam,
+ struct vnode ** vpp,
+ int *exflagsp,
+ struct ucred ** credanonp);
+#endif
+
+struct mbuf;
+int
+nnpfs_checkexp (struct mount *mp,
+#ifdef __FreeBSD__
+ struct sockaddr *nam,
+#else
+ struct mbuf *nam,
+#endif
+ int *exflagsp,
+ struct ucred **credanonp);
+
+int
+nnpfs_vptofh(struct vnode * vp,
+ struct fid * fhp);
+
+int
+nnpfs_dead_lookup(struct vop_lookup_args * ap);
+
+#endif /* _nnpfs_vfsops_bsd_h */
diff --git a/sys/nnpfs/nnpfs_vfsops-common.c b/sys/nnpfs/nnpfs_vfsops-common.c
new file mode 100644
index 00000000000..a3a992453bd
--- /dev/null
+++ b/sys/nnpfs/nnpfs_vfsops-common.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 1995 - 2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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 <nnpfs/nnpfs_locl.h>
+
+RCSID("$arla: nnpfs_vfsops-common.c,v 1.40 2003/06/02 18:26:40 lha Exp $");
+
+/*
+ * NNPFS vfs operations.
+ */
+
+#include <nnpfs/nnpfs_common.h>
+#include <nnpfs/nnpfs_message.h>
+#include <nnpfs/nnpfs_fs.h>
+#include <nnpfs/nnpfs_dev.h>
+#include <nnpfs/nnpfs_deb.h>
+#include <nnpfs/nnpfs_syscalls.h>
+#include <nnpfs/nnpfs_vfsops.h>
+
+#ifdef HAVE_KERNEL_UDEV2DEV
+#define VA_RDEV_TO_DEV(x) udev2dev(x, 0) /* XXX what is the 0 */
+#else
+#define VA_RDEV_TO_DEV(x) x
+#endif
+
+
+struct nnpfs nnpfs[NNNPFS];
+
+/*
+ * path and data is in system memory
+ */
+
+int
+nnpfs_mount_common_sys(struct mount *mp,
+ const char *path,
+ void *data,
+ struct nameidata *ndp,
+ d_thread_t *p)
+{
+ struct vnode *devvp;
+ dev_t dev;
+ int error;
+ struct vattr vat;
+
+ NNPFSDEB(XDEBVFOPS, ("nnpfs_mount: "
+ "struct mount mp = %lx path = '%s' data = '%s'\n",
+ (unsigned long)mp, path, (char *)data));
+
+#ifdef ARLA_KNFS
+ NNPFSDEB(XDEBVFOPS, ("nnpfs_mount: mount flags = %x\n", mp->mnt_flag));
+
+ /*
+ * mountd(8) flushes all export entries when it starts
+ * right now we ignore it (but should not)
+ */
+
+ if (mp->mnt_flag & MNT_UPDATE ||
+ mp->mnt_flag & MNT_DELEXPORT) {
+
+ NNPFSDEB(XDEBVFOPS,
+ ("nnpfs_mount: ignoring MNT_UPDATE or MNT_DELEXPORT\n"));
+ return 0;
+ }
+#endif
+
+ NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, data, p);
+ error = namei(ndp);
+ if (error) {
+ NNPFSDEB(XDEBVFOPS, ("namei failed, errno = %d\n", error));
+ return error;
+ }
+
+ devvp = ndp->ni_vp;
+
+ if (devvp->v_type != VCHR) {
+ vput(devvp);
+ NNPFSDEB(XDEBVFOPS, ("not VCHR (%d)\n", devvp->v_type));
+ return ENXIO;
+ }
+#if defined(__osf__)
+ VOP_GETATTR(devvp, &vat, ndp->ni_cred, error);
+#elif defined(HAVE_FREEBSD_THREAD)
+ error = VOP_GETATTR(devvp, &vat, p->td_proc->p_ucred, p);
+#else
+ error = VOP_GETATTR(devvp, &vat, p->p_ucred, p);
+#endif
+ vput(devvp);
+ if (error) {
+ NNPFSDEB(XDEBVFOPS, ("VOP_GETATTR failed, error = %d\n", error));
+ return error;
+ }
+
+ dev = VA_RDEV_TO_DEV(vat.va_rdev);
+
+ NNPFSDEB(XDEBVFOPS, ("dev = %d.%d\n", major(dev), minor(dev)));
+
+ if (!nnpfs_is_nnpfs_dev (dev)) {
+ NNPFSDEB(XDEBVFOPS, ("%s is not a nnpfs device\n", (char *)data));
+ return ENXIO;
+ }
+
+ if (nnpfs[minor(dev)].status & NNPFS_MOUNTED)
+ return EBUSY;
+
+ nnpfs[minor(dev)].status = NNPFS_MOUNTED;
+ nnpfs[minor(dev)].mp = mp;
+ nnpfs[minor(dev)].root = 0;
+ nnpfs[minor(dev)].nnodes = 0;
+ nnpfs[minor(dev)].fd = minor(dev);
+
+ nnfs_init_head(&nnpfs[minor(dev)].nodehead);
+
+ VFS_ASSIGN(mp, &nnpfs[minor(dev)]);
+#if defined(HAVE_KERNEL_VFS_GETNEWFSID)
+#if defined(HAVE_TWO_ARGUMENT_VFS_GETNEWFSID)
+ vfs_getnewfsid(mp, MOUNT_AFS);
+#else
+ vfs_getnewfsid(mp);
+#endif /* HAVE_TWO_ARGUMENT_VFS_GETNEWFSID */
+#endif /* HAVE_KERNEL_VFS_GETNEWFSID */
+
+ mp->mnt_stat.f_bsize = DEV_BSIZE;
+#ifndef __osf__
+ mp->mnt_stat.f_iosize = DEV_BSIZE;
+ mp->mnt_stat.f_owner = 0;
+#endif
+ mp->mnt_stat.f_blocks = 4711 * 4711;
+ mp->mnt_stat.f_bfree = 4711 * 4711;
+ mp->mnt_stat.f_bavail = 4711 * 4711;
+ mp->mnt_stat.f_files = 4711;
+ mp->mnt_stat.f_ffree = 4711;
+ mp->mnt_stat.f_flags = mp->mnt_flag;
+
+#ifdef __osf__
+ mp->mnt_stat.f_fsid.val[0] = dev;
+ mp->mnt_stat.f_fsid.val[1] = MOUNT_NNPFS;
+
+ mp->m_stat.f_mntonname = malloc(strlen(path) + 1, M_PATHNAME, M_WAITOK);
+ strcpy(mp->m_stat.f_mntonname, path);
+
+ mp->m_stat.f_mntfromname = malloc(sizeof("arla"), M_PATHNAME, M_WAITOK);
+ strcpy(mp->m_stat.f_mntfromname, "arla");
+#else /* __osf__ */
+ strncpy(mp->mnt_stat.f_mntonname,
+ path,
+ sizeof(mp->mnt_stat.f_mntonname));
+
+ strncpy(mp->mnt_stat.f_mntfromname,
+ data,
+ sizeof(mp->mnt_stat.f_mntfromname));
+
+ strncpy(mp->mnt_stat.f_fstypename,
+ "nnpfs",
+ sizeof(mp->mnt_stat.f_fstypename));
+#endif /* __osf__ */
+
+ return 0;
+}
+
+int
+nnpfs_mount_common(struct mount *mp,
+ const char *user_path,
+ void *user_data,
+ struct nameidata *ndp,
+ d_thread_t *p)
+{
+ char *path = NULL;
+ char *data = NULL;
+ size_t count;
+ int error = 0;
+
+ data = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
+ if (data == NULL) {
+ error = ENOMEM;
+ goto done;
+ }
+ path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
+ if (path == NULL) {
+ error = ENOMEM;
+ goto done;
+ }
+
+ error = copyinstr(user_path, path, MAXPATHLEN, &count);
+ if (error)
+ goto done;
+
+ error = copyinstr(user_data, data, MAXPATHLEN, &count);
+ if (error)
+ goto done;
+ error = nnpfs_mount_common_sys (mp, path, data, ndp, p);
+done:
+ free(data, M_TEMP);
+ free(path, M_TEMP);
+ return(error);
+}
+
+#ifdef HAVE_KERNEL_DOFORCE
+extern int doforce;
+#endif
+
+int
+nnpfs_unmount_common(struct mount *mp, int mntflags)
+{
+ struct nnpfs *nnpfsp = VFS_TO_NNPFS(mp);
+ int flags = 0;
+ int error;
+
+ if (mntflags & MNT_FORCE) {
+#ifdef HAVE_KERNEL_DOFORCE
+ if (!doforce)
+ return EINVAL;
+#endif
+ flags |= FORCECLOSE;
+ }
+
+ error = free_all_nnpfs_nodes(nnpfsp, flags, 1);
+ if (error)
+ return error;
+
+ nnpfsp->status = 0;
+ NNPFS_TO_VFS(nnpfsp) = NULL;
+ return 0;
+}
+
+int
+nnpfs_root_common(struct mount *mp, struct vnode **vpp,
+ d_thread_t *proc, struct ucred *cred)
+{
+ struct nnpfs *nnpfsp = VFS_TO_NNPFS(mp);
+ struct nnpfs_message_getroot msg;
+ int error;
+
+ do {
+ if (nnpfsp->root != NULL) {
+ *vpp = XNODE_TO_VNODE(nnpfsp->root);
+ nnpfs_do_vget(*vpp, LK_EXCLUSIVE, proc);
+ return 0;
+ }
+ msg.header.opcode = NNPFS_MSG_GETROOT;
+ msg.cred.uid = cred->cr_uid;
+ msg.cred.pag = nnpfs_get_pag(cred);
+ error = nnpfs_message_rpc(nnpfsp->fd, &msg.header, sizeof(msg), proc);
+ if (error == 0)
+ error = ((struct nnpfs_message_wakeup *) & msg)->error;
+ } while (error == 0);
+ /*
+ * Failed to get message through, need to pretend that all went well
+ * and return a fake dead vnode to be able to unmount.
+ */
+
+ if ((error = nnpfs_make_dead_vnode(mp, vpp)))
+ return error;
+
+ NNPFS_MAKE_VROOT(*vpp);
+ return 0;
+}
diff --git a/sys/nnpfs/nnpfs_vfsops-openbsd.c b/sys/nnpfs/nnpfs_vfsops-openbsd.c
new file mode 100644
index 00000000000..e5a99b731c7
--- /dev/null
+++ b/sys/nnpfs/nnpfs_vfsops-openbsd.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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 <nnpfs/nnpfs_locl.h>
+
+RCSID("$arla: nnpfs_vfsops-openbsd.c,v 1.16 2003/06/02 18:26:50 lha Exp $");
+
+#include <nnpfs/nnpfs_common.h>
+#include <nnpfs/nnpfs_message.h>
+#include <nnpfs/nnpfs_fs.h>
+#include <nnpfs/nnpfs_dev.h>
+#include <nnpfs/nnpfs_deb.h>
+#include <nnpfs/nnpfs_vfsops.h>
+#include <nnpfs/nnpfs_vfsops-bsd.h>
+#include <nnpfs/nnpfs_vnodeops.h>
+
+static vop_t **nnpfs_dead_vnodeop_p;
+
+int
+nnpfs_make_dead_vnode(struct mount *mp, struct vnode **vpp)
+{
+ NNPFSDEB(XDEBNODE, ("make_dead_vnode mp = %lx\n",
+ (unsigned long)mp));
+
+ return getnewvnode(VT_NON, mp, nnpfs_dead_vnodeop_p, vpp);
+}
+
+static struct vnodeopv_entry_desc nnpfs_dead_vnodeop_entries[] = {
+ {&vop_default_desc, (vop_t *) nnpfs_eopnotsupp},
+ {&vop_lookup_desc, (vop_t *) nnpfs_dead_lookup},
+ {&vop_reclaim_desc, (vop_t *) nnpfs_returnzero},
+ {&vop_lock_desc, (vop_t *) vop_generic_lock},
+ {&vop_unlock_desc, (vop_t *) vop_generic_unlock},
+ {&vop_islocked_desc,(vop_t *) vop_generic_islocked},
+ {NULL, NULL}};
+
+static struct vnodeopv_desc nnpfs_dead_vnodeop_opv_desc =
+{&nnpfs_dead_vnodeop_p, nnpfs_dead_vnodeop_entries};
+
+extern struct vnodeopv_desc nnpfs_vnodeop_opv_desc;
+
+static int
+nnpfs_init(struct vfsconf *vfs)
+{
+ NNPFSDEB(XDEBVFOPS, ("nnpfs_init\n"));
+ vfs_opv_init_explicit(&nnpfs_vnodeop_opv_desc);
+ vfs_opv_init_default(&nnpfs_vnodeop_opv_desc);
+ vfs_opv_init_explicit(&nnpfs_dead_vnodeop_opv_desc);
+ vfs_opv_init_default(&nnpfs_dead_vnodeop_opv_desc);
+ return 0;
+}
+
+const struct vfsops nnpfs_vfsops = {
+#ifdef HAVE_STRUCT_VFSOPS_VFS_MOUNT
+ nnpfs_mount_common,
+#else
+ nnpfs_mount_caddr,
+#endif
+ nnpfs_start,
+ nnpfs_unmount,
+ nnpfs_root,
+ nnpfs_quotactl,
+ nnpfs_statfs,
+ nnpfs_sync,
+ nnpfs_vget,
+ nnpfs_fhtovp,
+ nnpfs_vptofh,
+ nnpfs_init,
+ NULL,
+#ifdef HAVE_STRUCT_VFSOPS_VFS_CHECKEXP
+ nnpfs_checkexp, /* checkexp */
+#endif
+};
+
+static struct vfsconf nnpfs_vfc = {
+ &nnpfs_vfsops,
+ "nnpfs",
+ 0,
+ 0,
+ 0,
+ NULL
+};
+
+#ifndef HAVE_KERNEL_VFS_REGISTER
+
+static int
+vfs_register (struct vfsconf *vfs)
+{
+ struct vfsconf *vfsp;
+ struct vfsconf **vfspp;
+
+ /* Check if filesystem already known */
+ for (vfspp = &vfsconf, vfsp = vfsconf;
+ vfsp;
+ vfspp = &vfsp->vfc_next, vfsp = vfsp->vfc_next)
+ if (strcmp(vfsp->vfc_name, vfs->vfc_name) == 0)
+ return (EEXIST);
+
+ maxvfsconf++;
+
+ /* Add to the end of the list */
+ *vfspp = vfs;
+
+ vfs->vfc_next = NULL;
+
+ /* Call vfs_init() */
+ NNPFSDEB(XDEBVFOPS, ("calling vfs_init\n"));
+ (*(vfs->vfc_vfsops->vfs_init)) (vfs);
+
+ /* done! */
+
+ return 0;
+}
+
+static int
+vfs_unregister (struct vfsconf *vfs)
+{
+ struct vfsconf *vfsp;
+ struct vfsconf **vfspp;
+
+ /* Find our vfsconf struct */
+ for (vfspp = &vfsconf, vfsp = vfsconf;
+ vfsp;
+ vfspp = &vfsp->vfc_next, vfsp = vfsp->vfc_next)
+ if (strcmp(vfsp->vfc_name, vfs->vfc_name) == 0)
+ break;
+
+ if (!vfsp) /* Not found */
+ return (ENOENT);
+
+ if (vfsp->vfc_refcount) /* In use */
+ return (EBUSY);
+
+ /* Remove from list and free */
+ *vfspp = vfsp->vfc_next;
+
+ maxvfsconf--;
+
+ return 0;
+}
+
+#endif
+
+int
+nnpfs_install_filesys(void)
+{
+ return vfs_register (&nnpfs_vfc);
+}
+
+int
+nnpfs_uninstall_filesys(void)
+{
+ return vfs_unregister (&nnpfs_vfc);
+}
+
+int
+nnpfs_stat_filesys (void)
+{
+ return 0;
+}
diff --git a/sys/nnpfs/nnpfs_vfsops.h b/sys/nnpfs/nnpfs_vfsops.h
new file mode 100644
index 00000000000..717745bb98d
--- /dev/null
+++ b/sys/nnpfs/nnpfs_vfsops.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $arla: nnpfs_vfsops.h,v 1.17 2003/06/02 18:27:10 lha Exp $ */
+
+#ifndef _nnpfs_vfsops_h
+#define _nnpfs_vfsops_h
+
+int
+nnpfs_mount_common(struct mount *mp,
+ const char *user_path,
+ void *user_data,
+ struct nameidata *ndp,
+ d_thread_t *p);
+
+int
+nnpfs_mount_common_sys(struct mount *mp,
+ const char *path,
+ void *data,
+ struct nameidata *ndp,
+ d_thread_t *p);
+
+int
+nnpfs_unmount_common(struct mount *mp, int mntflags);
+
+int
+nnpfs_root_common(struct mount *mp,
+ struct vnode **vpp,
+ d_thread_t *proc,
+ struct ucred *cred);
+
+int
+nnpfs_fhlookup (d_thread_t *proc,
+ struct nnpfs_fhandle_t *fhp,
+ struct vnode **vpp);
+
+int
+nnpfs_fhopen (d_thread_t *proc,
+ struct nnpfs_fhandle_t *fhp,
+ int flags,
+ register_t *retval);
+
+int nnpfs_make_dead_vnode(struct mount *mp, struct vnode **vpp);
+
+#endif /* _nnpfs_vfsops_h */
diff --git a/sys/nnpfs/nnpfs_vnodeops-bsd.c b/sys/nnpfs/nnpfs_vnodeops-bsd.c
new file mode 100644
index 00000000000..7e740d3f8f5
--- /dev/null
+++ b/sys/nnpfs/nnpfs_vnodeops-bsd.c
@@ -0,0 +1,1537 @@
+/*
+ * Copyright (c) 1995 - 2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * NNPFS operations.
+ */
+
+#ifdef __APPLE__
+#define MACH_KERNEL 1
+#endif
+
+#include <nnpfs/nnpfs_locl.h>
+#include <nnpfs/nnpfs_message.h>
+#include <nnpfs/nnpfs_common.h>
+#include <nnpfs/nnpfs_fs.h>
+#include <nnpfs/nnpfs_dev.h>
+#include <nnpfs/nnpfs_deb.h>
+#include <nnpfs/nnpfs_syscalls.h>
+#include <nnpfs/nnpfs_vnodeops.h>
+#ifdef HAVE_VM_VNODE_PAGER_H
+#include <vm/vnode_pager.h>
+#endif
+
+#include <sys/pool.h>
+
+RCSID("$arla: nnpfs_vnodeops-bsd.c,v 1.123 2003/02/15 16:40:36 lha Exp $");
+
+/*
+ * vnode functions
+ */
+
+#ifdef HAVE_VOP_OPEN
+int
+nnpfs_open(struct vop_open_args * ap)
+ /*
+ struct vop_open {
+ struct vnode *vp;
+ int mode;
+ struct ucred *cred;
+ struct proc *p;
+ }; */
+{
+#ifdef HAVE_FREEBSD_THREAD
+ return nnpfs_open_common (ap->a_vp, ap->a_mode, ap->a_cred, ap->a_td);
+#else
+ return nnpfs_open_common (ap->a_vp, ap->a_mode, ap->a_cred, ap->a_p);
+#endif
+}
+#endif /* HAVE_VOP_OPEN */
+
+#ifdef HAVE_VOP_FSYNC
+int
+nnpfs_fsync(struct vop_fsync_args * ap)
+ /*
+ vop_fsync {
+ struct vnode *vp;
+ struct ucred *cred;
+ int waitfor;
+ struct proc *p;
+}; */
+{
+#ifdef HAVE_STRUCT_VOP_FSYNC_ARGS_A_FLAGS
+ return nnpfs_fsync_common(ap->a_vp, ap->a_cred, ap->a_flags, ap->a_p);
+#else
+#ifdef HAVE_FREEBSD_THREAD
+ return nnpfs_fsync_common(ap->a_vp, ap->a_cred, ap->a_waitfor, ap->a_td);
+#else
+ return nnpfs_fsync_common(ap->a_vp, ap->a_cred, ap->a_waitfor, ap->a_p);
+#endif
+#endif
+}
+#endif /* HAVE_VOP_FSYNC */
+
+#ifdef HAVE_VOP_CLOSE
+int
+nnpfs_close(struct vop_close_args * ap)
+ /* vop_close {
+ IN struct vnode *vp;
+ IN int fflag;
+ IN struct ucred *cred;
+ IN struct proc *p;
+ }; */
+{
+#ifdef HAVE_FREEBSD_THREAD
+ return nnpfs_close_common(ap->a_vp, ap->a_fflag, ap->a_td, ap->a_cred);
+#else
+ return nnpfs_close_common(ap->a_vp, ap->a_fflag, ap->a_p, ap->a_cred);
+#endif
+}
+#endif /* HAVE_VOP_CLOSE */
+
+#ifdef HAVE_VOP_READ
+int
+nnpfs_read(struct vop_read_args * ap)
+ /* vop_read {
+ IN struct vnode *vp;
+ INOUT struct uio *uio;
+ IN int ioflag;
+ IN struct ucred *cred;
+ }; */
+{
+ return nnpfs_read_common(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred);
+}
+#endif /* HAVE_VOP_READ */
+
+#ifdef HAVE_VOP_WRITE
+int
+nnpfs_write(struct vop_write_args * ap)
+ /* vop_write {
+ IN struct vnode *vp;
+ INOUT struct uio *uio;
+ IN int ioflag;
+ IN struct ucred *cred;
+ }; */
+{
+ return nnpfs_write_common(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred);
+}
+#endif /* HAVE_VOP_WRITE */
+
+#ifdef HAVE_VOP_IOCTL
+int
+nnpfs_ioctl(struct vop_ioctl_args * ap)
+ /* struct vnode *vp,
+ int com,
+ caddr_t data,
+ int flag,
+ struct ucred *cred) */
+{
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_ioctl\n"));
+
+ return EOPNOTSUPP;
+}
+#endif /* HAVE_VOP_IOCTL */
+
+#ifdef HAVE_VOP_SELECT
+int
+nnpfs_select(struct vop_select_args * ap)
+ /* struct vnode *vp,
+ int which,
+ struct ucred *cred ) */
+{
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_select\n"));
+
+ return EOPNOTSUPP;
+}
+#endif /* HAVE_VOP_SELECT */
+
+#ifdef HAVE_VOP_SEEK
+int
+nnpfs_seek(struct vop_seek_args * ap)
+ /*
+struct vop_seek_args {
+ struct vnodeop_desc *a_desc;
+ struct vnode *a_vp;
+ off_t a_oldoff;
+ off_t a_newoff;
+ struct ucred *a_cred;
+};
+*/
+{
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_seek\n"));
+ return 0;
+}
+#endif /* HAVE_VOP_SEEK */
+
+#ifdef HAVE_VOP_POLL
+int
+nnpfs_poll(struct vop_poll_args * ap)
+ /* vop_poll {
+ IN struct vnode *vp;
+ IN int events;
+ IN struct proc *p;
+ }; */
+{
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_poll\n"));
+ return EOPNOTSUPP;
+}
+#endif /* HAVE_VOP_POLL */
+
+#ifdef HAVE_VOP_GETATTR
+int
+nnpfs_getattr(struct vop_getattr_args * ap)
+ /* struct vnode *vp,
+ struct vattr *vap,
+ struct ucred *cred,
+ struct proc *p) */
+{
+#ifdef HAVE_FREEBSD_THREAD
+ return nnpfs_getattr_common(ap->a_vp, ap->a_vap, ap->a_cred, ap->a_td);
+#else
+ return nnpfs_getattr_common(ap->a_vp, ap->a_vap, ap->a_cred, ap->a_p);
+#endif
+}
+#endif /* HAVE_VOP_GETATTR */
+
+#ifdef HAVE_VOP_SETATTR
+int
+nnpfs_setattr(struct vop_setattr_args * ap)
+ /* struct vnode *vp,
+ struct vattr *vap,
+ struct ucred *cred,
+ struct proc *p)
+ */
+{
+#ifdef HAVE_FREEBSD_THREAD
+ return nnpfs_setattr_common(ap->a_vp, ap->a_vap, ap->a_cred, ap->a_td);
+#else
+ return nnpfs_setattr_common(ap->a_vp, ap->a_vap, ap->a_cred, ap->a_p);
+#endif
+}
+#endif /* HAVE_VOP_SETATTR */
+
+#ifdef HAVE_VOP_ACCESS
+int
+nnpfs_access(struct vop_access_args * ap)
+ /*
+struct vnode *vp,
+ int mode,
+ struct ucred *cred,
+ struct proc *p)
+ */
+{
+#ifdef HAVE_FREEBSD_THREAD
+ return nnpfs_access_common(ap->a_vp, ap->a_mode, ap->a_cred, ap->a_td);
+#else
+ return nnpfs_access_common(ap->a_vp, ap->a_mode, ap->a_cred, ap->a_p);
+#endif
+}
+#endif /* HAVE_VOP_ACCESS */
+
+#ifdef HAVE_VOP_LOOKUP
+int
+nnpfs_lookup(struct vop_lookup_args * ap)
+ /* struct vop_lookup_args {
+ struct vnodeop_desc *a_desc;
+ struct vnode *a_dvp;
+ struct vnode **a_vpp;
+ struct componentname *a_cnp;
+}; */
+{
+ struct componentname *cnp = ap->a_cnp;
+ int error;
+ int lockparent = (cnp->cn_flags & (LOCKPARENT | ISLASTCN))
+ == (LOCKPARENT | ISLASTCN);
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_lookup: (%s, %ld), nameiop = %lu, flags = %lu\n",
+ cnp->cn_nameptr,
+ cnp->cn_namelen,
+ cnp->cn_nameiop,
+ cnp->cn_flags));
+
+#ifdef PDIRUNLOCK
+ cnp->cn_flags &= ~PDIRUNLOCK;
+#endif
+
+ error = nnpfs_lookup_common(ap->a_dvp, cnp, ap->a_vpp);
+
+ if (error == ENOENT
+ && (cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME)
+ && (cnp->cn_flags & ISLASTCN)) {
+ error = EJUSTRETURN;
+ }
+
+ if (cnp->cn_nameiop != LOOKUP && cnp->cn_flags & ISLASTCN)
+ cnp->cn_flags |= SAVENAME;
+
+ if (error == 0 || error == EJUSTRETURN) {
+ if (ap->a_dvp == *(ap->a_vpp)) {
+ /* if we looked up ourself, do nothing */
+ } else if (!(cnp->cn_flags & ISLASTCN) || !lockparent) {
+ /* if we isn't last component and is isn't requested,
+ * return parent unlocked */
+#ifdef HAVE_FREEBSD_THREAD
+ nnpfs_vfs_unlock (ap->a_dvp, nnpfs_cnp_to_thread(cnp));
+#else
+ nnpfs_vfs_unlock (ap->a_dvp, nnpfs_cnp_to_proc(cnp));
+#endif
+#ifdef PDIRUNLOCK
+ cnp->cn_flags |= PDIRUNLOCK;
+#endif
+ }
+ } else {
+ /* in case of a error do nothing */
+ }
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_lookup: error = %d\n", error));
+
+ return error;
+}
+#endif /* HAVE_VOP_LOOKUP */
+
+#ifdef HAVE_VOP_CACHEDLOOKUP
+int
+nnpfs_cachedlookup(struct vop_cachedlookup_args * ap)
+ /* struct vop_cachedlookup_args {
+ struct vnodeop_desc *a_desc;
+ struct vnode *a_dvp;
+ struct vnode **a_vpp;
+ struct componentname *a_cnp;
+}; */
+{
+ return nnpfs_lookup((struct vop_lookup_args *)ap);
+}
+#endif /* HAVE_VOP_CACHEDLOOKUP */
+
+/*
+ * whatever clean-ups are needed for a componentname.
+ */
+
+static void
+cleanup_cnp (struct componentname *cnp, int error)
+{
+ if (error != 0 || (cnp->cn_flags & SAVESTART) == 0) {
+#if defined(HAVE_KERNEL_ZFREEI)
+ zfreei(namei_zone, cnp->cn_pnbuf);
+ cnp->cn_flags &= ~HASBUF;
+#elif defined(HAVE_KERNEL_UMA_ZFREE_ARG)
+ uma_zfree_arg(namei_zone, cnp->cn_pnbuf, NULL);
+ cnp->cn_flags &= ~HASBUF;
+#elif defined(FREE_ZONE)
+ FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
+#elif defined(HAVE_KERNEL_ZFREE)
+ zfree(namei_zone, cnp->cn_pnbuf);
+ cnp->cn_flags &= ~HASBUF;
+#elif defined(PNBUF_PUT)
+ PNBUF_PUT(cnp->cn_pnbuf);
+#else
+ pool_put(&namei_pool, cnp->cn_pnbuf);
+#endif
+ }
+}
+
+#ifdef HAVE_VOP_CREATE
+int
+nnpfs_create(struct vop_create_args *ap)
+{
+ struct vnode *dvp = ap->a_dvp;
+ struct componentname *cnp = ap->a_cnp;
+ const char *name = cnp->cn_nameptr;
+ struct ucred *cred = cnp->cn_cred;
+#ifdef HAVE_FREEBSD_THREAD
+ d_thread_t *p = nnpfs_cnp_to_thread(cnp);
+#else
+ d_thread_t *p = nnpfs_cnp_to_proc(cnp);
+#endif
+ int error;
+
+ error = nnpfs_create_common(dvp, name, ap->a_vap, cred, p);
+
+ if (error == 0) {
+ error = nnpfs_lookup_common(dvp, cnp, ap->a_vpp);
+ }
+
+ cleanup_cnp (cnp, error);
+
+#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
+ vput (dvp);
+#endif
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_create: error = %d\n", error));
+
+ return error;
+}
+#endif /* HAVE_VOP_CREATE */
+
+#ifdef HAVE_VOP_REMOVE
+int
+nnpfs_remove(struct vop_remove_args * ap)
+ /* struct vnode *dvp,
+ struct vnode *vp,
+ struct componentname *cnp */
+{
+ struct componentname *cnp = ap->a_cnp;
+ struct vnode *dvp = ap->a_dvp;
+ struct vnode *vp = ap->a_vp;
+
+#ifdef HAVE_FREEBSD_THREAD
+ int error = nnpfs_remove_common(dvp, vp, cnp->cn_nameptr,
+ cnp->cn_cred, nnpfs_cnp_to_thread(cnp));
+#else
+ int error = nnpfs_remove_common(dvp, vp, cnp->cn_nameptr,
+ cnp->cn_cred, nnpfs_cnp_to_proc(cnp));
+#endif
+
+ cleanup_cnp (cnp, error);
+
+#if !defined(__FreeBSD__) || __FreeBSD_version < 300000
+ if (dvp == vp)
+ vrele(vp);
+ else
+ vput(vp);
+ vput(dvp);
+#endif
+
+#ifdef __APPLE__
+ if (error == 0) {
+ if (UBCINFOEXISTS(vp)) {
+ ubc_setsize(vp, 0);
+ ubc_release(vp);
+ ubc_uncache(vp);
+ }
+ }
+#endif
+
+ return error;
+}
+#endif /* HAVE_VOP_REMOVE */
+
+#ifdef HAVE_VOP_RENAME
+int
+nnpfs_rename(struct vop_rename_args * ap)
+ /* vop_rename {
+ IN WILLRELE struct vnode *fdvp;
+ IN WILLRELE struct vnode *fvp;
+ IN struct componentname *fcnp;
+ IN WILLRELE struct vnode *tdvp;
+ IN WILLRELE struct vnode *tvp;
+ IN struct componentname *tcnp;
+ }; */
+{
+ struct vnode *tdvp = ap->a_tdvp;
+ struct vnode *tvp = ap->a_tvp;
+ struct vnode *fdvp = ap->a_fdvp;
+ struct vnode *fvp = ap->a_fvp;
+
+ int error = nnpfs_rename_common(fdvp,
+ fvp,
+ ap->a_fcnp->cn_nameptr,
+ tdvp,
+ tvp,
+ ap->a_tcnp->cn_nameptr,
+ ap->a_tcnp->cn_cred,
+#ifdef HAVE_FREEBSD_THREAD
+ nnpfs_cnp_to_thread (ap->a_fcnp));
+#else
+ nnpfs_cnp_to_proc (ap->a_fcnp));
+#endif
+ if(tdvp == tvp)
+ vrele(tdvp);
+ else
+ vput(tdvp);
+ if(tvp)
+ vput(tvp);
+ vrele(fdvp);
+ vrele(fvp);
+ return error;
+}
+#endif /* HAVE_VOP_RENAME */
+
+#ifdef HAVE_VOP_MKDIR
+int
+nnpfs_mkdir(struct vop_mkdir_args * ap)
+ /* struct vnode *dvp,
+ char *nm,
+ struct vattr *va,
+ struct vnode **vpp,
+ struct ucred *cred) */
+{
+ struct vnode *dvp = ap->a_dvp;
+ struct componentname *cnp = ap->a_cnp;
+ const char *name = cnp->cn_nameptr;
+ struct ucred *cred = cnp->cn_cred;
+#ifdef HAVE_FREEBSD_THREAD
+ d_thread_t *p = nnpfs_cnp_to_thread(cnp);
+#else
+ d_thread_t *p = nnpfs_cnp_to_proc(cnp);
+#endif
+ int error;
+
+ error = nnpfs_mkdir_common(dvp, name, ap->a_vap, cred, p);
+
+ if (error == 0)
+ error = nnpfs_lookup_common(dvp, cnp, ap->a_vpp);
+
+ cleanup_cnp (cnp, error);
+
+#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)
+ vput(dvp);
+#endif
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_mkdir: error = %d\n", error));
+
+ return error;
+}
+#endif /* HAVE_VOP_MKDIR */
+
+#ifdef HAVE_VOP_RMDIR
+int
+nnpfs_rmdir(struct vop_rmdir_args * ap)
+ /* struct vnode *dvp,
+ struct vnode *vp,
+ struct componentname *cnp */
+{
+ struct componentname *cnp = ap->a_cnp;
+ struct vnode *dvp = ap->a_dvp;
+ struct vnode *vp = ap->a_vp;
+ int error = nnpfs_rmdir_common(ap->a_dvp, ap->a_vp,
+ cnp->cn_nameptr,
+ cnp->cn_cred,
+#ifdef HAVE_FREEBSD_THREAD
+ nnpfs_cnp_to_thread(cnp));
+#else
+ nnpfs_cnp_to_proc(cnp));
+#endif
+
+ cleanup_cnp (cnp, error);
+#if !defined(__FreeBSD__) || __FreeBSD_version < 300000
+ if (dvp == vp)
+ vrele(vp);
+ else
+ vput(vp);
+ vput(dvp);
+#endif
+
+ return error;
+}
+#endif /* HAVE_VOP_RMDIR */
+
+#ifdef HAVE_VOP_READDIR
+
+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
+typedef u_long nnpfs_cookie_t;
+#elif defined(__NetBSD__)
+typedef off_t nnpfs_cookie_t;
+#else
+#error dunno want kind of cookies you have
+#endif
+
+int
+nnpfs_readdir(struct vop_readdir_args * ap)
+ /* struct vnode *vp,
+ struct uio *uiop,
+ struct ucred *cred) */
+{
+ int error;
+ off_t off;
+
+ off = ap->a_uio->uio_offset;
+
+ error = nnpfs_readdir_common(ap->a_vp, ap->a_uio, ap->a_cred,
+#ifdef HAVE_FREEBSD_THREAD
+ nnpfs_uio_to_thread (ap->a_uio),
+#else
+ nnpfs_uio_to_proc (ap->a_uio),
+#endif
+ ap->a_eofflag);
+
+ if (!error && ap->a_ncookies != NULL) {
+ struct uio *uio = ap->a_uio;
+ const struct dirent *dp, *dp_start, *dp_end;
+ int ncookies;
+ nnpfs_cookie_t *cookies, *cookiep;
+
+ if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
+ panic("nnpfs_readdir: mail arla-drinkers and tell them to bake burned cookies");
+ dp = (const struct dirent *)
+ ((const char *)uio->uio_iov->iov_base - (uio->uio_offset - off));
+
+ dp_end = (const struct dirent *) uio->uio_iov->iov_base;
+ for (dp_start = dp, ncookies = 0;
+ dp < dp_end;
+ dp = (const struct dirent *)((const char *) dp + dp->d_reclen)) {
+ if (dp->d_reclen <= 0)
+ break;
+ ncookies++;
+ }
+
+ cookies = malloc(ncookies * sizeof(nnpfs_cookie_t), M_TEMP, M_WAITOK);
+ for (dp = dp_start, cookiep = cookies;
+ dp < dp_end;
+ dp = (const struct dirent *)((const char *) dp + dp->d_reclen)) {
+ if (dp->d_reclen <= 0)
+ break;
+ off += dp->d_reclen;
+ *cookiep++ = off;
+ }
+ *ap->a_cookies = cookies;
+ *ap->a_ncookies = ncookies;
+ }
+ return error;
+}
+#endif /* HAVE_VOP_READDIR */
+
+#ifdef HAVE_VOP_LINK
+int
+nnpfs_link(struct vop_link_args * ap)
+ /*
+ WILLRELE struct vnode *tdvp;
+ struct vnode *vp;
+ struct componentname *cnp;
+ */
+{
+ struct componentname *cnp = ap->a_cnp;
+ struct vnode *vp = ap->a_vp;
+ struct vnode *dvp;
+#ifdef HAVE_FREEBSD_THREAD
+ d_thread_t *p = cnp->cn_thread;
+#else
+ d_thread_t *p = cnp->cn_proc;
+#endif
+ int error;
+
+#if defined (__OpenBSD__) || defined(__NetBSD__)
+ dvp = ap->a_dvp;
+#elif defined(__FreeBSD__) || defined(__APPLE__)
+ dvp = ap->a_tdvp;
+#else
+#error what kind of BSD is this?
+#endif
+
+ if (vp->v_type == VDIR) {
+#ifdef HAVE_VOP_ABORTOP
+ VOP_ABORTOP(dvp, cnp);
+#endif
+ error = EPERM;
+ goto out;
+ }
+ if (dvp->v_mount != vp->v_mount) {
+#ifdef HAVE_VOP_ABORTOP
+ VOP_ABORTOP(dvp, cnp);
+#endif
+ error = EXDEV;
+ goto out;
+ }
+ /* FreeBSD 5.0 doesn't need to lock the vnode in VOP_LINK */
+#if !defined(__FreeBSD_version) || __FreeBSD_version < 500043
+
+ if (dvp != vp && (error = nnpfs_vfs_writelock(vp, p))) {
+#ifdef HAVE_VOP_ABORTOP
+ VOP_ABORTOP(dvp, cnp);
+#endif
+ goto out;
+ }
+#endif /* defined(__FreeBSD_version) || __FreeBSD_version < 500043 */
+
+ error = nnpfs_link_common(
+ dvp,
+ vp,
+ cnp->cn_nameptr,
+ cnp->cn_cred,
+#ifdef HAVE_FREEBSD_THREAD
+ nnpfs_cnp_to_thread (cnp));
+#else
+ nnpfs_cnp_to_proc (cnp));
+#endif
+
+ cleanup_cnp (cnp, error);
+
+ if (dvp != vp)
+ nnpfs_vfs_unlock(vp, p);
+
+out:
+#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)
+ vput(dvp);
+#endif
+
+ return error;
+}
+#endif /* HAVE_VOP_LINK */
+
+#ifdef HAVE_VOP_SYMLINK
+int
+nnpfs_symlink(struct vop_symlink_args * ap)
+ /*
+ IN WILLRELE struct vnode *dvp;
+ OUT WILLRELE struct vnode **vpp;
+ IN struct componentname *cnp;
+ IN struct vattr *vap;
+ IN char *target;
+ */
+{
+ struct componentname *cnp = ap->a_cnp;
+ struct vnode *dvp = ap->a_dvp;
+ struct vnode **vpp = ap->a_vpp;
+
+ int error = nnpfs_symlink_common(dvp,
+ vpp,
+ cnp,
+ ap->a_vap,
+ ap->a_target);
+
+ if (error == 0) {
+ error = nnpfs_lookup_common(dvp, cnp, vpp);
+ if (error == 0)
+ vput (*vpp);
+ }
+ cleanup_cnp (cnp, error);
+#if !defined(__FreeBSD__)
+ vput(dvp);
+#endif
+ return error;
+}
+#endif /* HAVE_VOP_SYMLINK */
+
+
+#ifdef HAVE_VOP_READLINK
+int
+nnpfs_readlink(struct vop_readlink_args * ap)
+ /* struct vnode *vp,
+ struct uio *uiop,
+ struct ucred *cred) */
+{
+ return nnpfs_readlink_common(ap->a_vp, ap->a_uio, ap->a_cred);
+}
+#endif /* HAVE_VOP_READLINK */
+
+#ifdef HAVE_VOP_INACTIVE
+int
+nnpfs_inactive(struct vop_inactive_args * ap)
+ /*struct vnode *vp,
+ struct ucred *cred)*/
+{
+#ifdef HAVE_FREEBSD_THREAD
+ return nnpfs_inactive_common(ap->a_vp, nnpfs_curthread());
+#else
+ return nnpfs_inactive_common(ap->a_vp, nnpfs_curproc());
+#endif
+}
+#endif /* HAVE_VOP_INACTICE */
+
+#ifdef HAVE_VOP_RECLAIM
+int
+nnpfs_reclaim(struct vop_reclaim_args * ap)
+ /*struct vop_reclaim_args {
+ struct vnodeop_desc *a_desc;
+ struct vnode *a_vp;
+};*/
+{
+ struct vnode *vp = ap->a_vp;
+ int ret;
+
+ ret = nnpfs_reclaim_common(vp);
+ vp->v_data = NULL;
+ return ret;
+}
+#endif /* HAVE_VOP_RECLAIM */
+
+/*
+ * Do lock, unlock, and islocked with lockmgr if we have it.
+ */
+
+#if defined(HAVE_KERNEL_LOCKMGR) || defined(HAVE_KERNEL_DEBUGLOCKMGR)
+
+#ifdef HAVE_VOP_LOCK
+int
+nnpfs_lock(struct vop_lock_args * ap)
+{
+ struct vnode *vp = ap->a_vp;
+ struct nnpfs_node *xn = VNODE_TO_XNODE(vp);
+ nnpfs_vnode_lock *l = &xn->lock;
+ int flags = ap->a_flags;
+ int ret;
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_lock: %lx, flags 0x%x\n",
+ (unsigned long)vp, flags));
+
+ if (l == NULL)
+ panic("nnpfs_lock: lock NULL");
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_lock before: lk flags: %d share: %d "
+ "wait: %d excl: %d holder: 0x%llx\n",
+ l->lk_flags, l->lk_sharecount, l->lk_waitcount,
+ l->lk_exclusivecount,
+ (unsigned long long)
+ (nnpfs_uintptr_t)l->lk_lockholder));
+
+#ifndef DEBUG_LOCKS
+#ifdef HAVE_FOUR_ARGUMENT_LOCKMGR
+#ifdef HAVE_FREEBSD_THREAD
+ ret = lockmgr(l, flags, &vp->v_interlock, ap->a_td);
+#else
+ ret = lockmgr(l, flags, &vp->v_interlock, ap->a_p);
+#endif
+#else
+ ret = lockmgr(l, flags, NULL);
+#endif
+#else
+#ifdef HAVE_FREEBSD_THREAD
+ ret = debuglockmgr(l, flags, &vp->v_interlock, ap->a_td,
+ "nnpfs_lock", ap->a_vp->filename, ap->a_vp->line);
+#else
+ ret = debuglockmgr(l, flags, &vp->v_interlock, ap->a_p,
+ "nnpfs_lock", ap->a_vp->filename, ap->a_vp->line);
+#endif
+#endif
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_lock: lk flags: %d share: %d "
+ "wait: %d excl: %d holder: 0x%llx\n",
+ l->lk_flags, l->lk_sharecount, l->lk_waitcount,
+ l->lk_exclusivecount,
+ (unsigned long long)
+ (nnpfs_uintptr_t)l->lk_lockholder));
+ return ret;
+}
+#endif /* HAVE_VOP_LOCK */
+
+#ifdef HAVE_VOP_UNLOCK
+int
+nnpfs_unlock(struct vop_unlock_args * ap)
+{
+ struct vnode *vp = ap->a_vp;
+ struct nnpfs_node *xn = VNODE_TO_XNODE(vp);
+ nnpfs_vnode_lock *l = &xn->lock;
+ int flags = ap->a_flags;
+ int ret;
+
+ if (l == NULL)
+ panic("nnpfs_unlock: lock NULL");
+
+ NNPFSDEB(XDEBVNOPS,
+ ("nnpfs_unlock: %lx, flags 0x%x, l %lx, ap %lx\n",
+ (unsigned long)vp, flags,
+ (unsigned long)l,
+ (unsigned long)ap));
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_unlock: lk flags: %d share: %d "
+ "wait: %d excl: %d holder: 0x%lld\n",
+ l->lk_flags, l->lk_sharecount, l->lk_waitcount,
+ l->lk_exclusivecount,
+ (unsigned long long)
+ (nnpfs_uintptr_t)l->lk_lockholder));
+#ifndef DEBUG_LOCKS
+#ifdef HAVE_FOUR_ARGUMENT_LOCKMGR
+#ifdef HAVE_FREEBSD_THREAD
+ ret = lockmgr (l, flags | LK_RELEASE, &vp->v_interlock, ap->a_td);
+#else
+ ret = lockmgr (l, flags | LK_RELEASE, &vp->v_interlock, ap->a_p);
+#endif
+#else
+ ret = lockmgr (l, flags | LK_RELEASE, NULL);
+#endif
+#else
+#ifdef HAVE_FREEBSD_THREAD
+ ret = debuglockmgr (l, flags | LK_RELEASE, &vp->v_interlock, ap->a_td,
+ "nnpfs_lock", ap->a_vp->filename, ap->a_vp->line);
+#else
+ ret = debuglockmgr (l, flags | LK_RELEASE, &vp->v_interlock, ap->a_p,
+ "nnpfs_lock", ap->a_vp->filename, ap->a_vp->line);
+#endif
+#endif
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_unlock: return %d\n", ret));
+ return ret;
+}
+#endif /* HAVE_VOP_UNLOCK */
+
+#ifdef HAVE_VOP_ISLOCKED
+int
+nnpfs_islocked (struct vop_islocked_args *ap)
+{
+ struct vnode *vp = ap->a_vp;
+ struct nnpfs_node *xn = VNODE_TO_XNODE(vp);
+ nnpfs_vnode_lock *l = &xn->lock;
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_islocked: %lx\n",
+ (unsigned long)vp));
+
+#if defined(HAVE_TWO_ARGUMENT_LOCKSTATUS)
+#ifdef HAVE_FREEBSD_THREAD
+ return lockstatus (l, ap->a_td);
+#else
+ return lockstatus (l, ap->a_p);
+#endif
+#elif defined(HAVE_ONE_ARGUMENT_LOCKSTATUS)
+ return lockstatus (l);
+#else
+#error what lockstatus?
+#endif
+}
+#endif /* HAVE_VOP_ISLOCKED */
+
+#else /* !HAVE_KERNEL_LOCKMGR && !HAVE_KERNEL_DEBUGLOCKMGR */
+
+#ifdef HAVE_VOP_LOCK
+int
+nnpfs_lock(struct vop_lock_args * ap)
+{
+ struct vnode *vp = ap->a_vp;
+ struct nnpfs_node *xn = VNODE_TO_XNODE(vp);
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_lock: %lx, %d\n",
+ (unsigned long)vp, xn->vnlocks));
+
+ while (vp->v_flag & VXLOCK) {
+ vp->v_flag |= VXWANT;
+ (void) tsleep((caddr_t)vp, PINOD, "nnpfs_vnlock", 0);
+ }
+ if (vp->v_tag == VT_NON)
+ return (ENOENT);
+ ++xn->vnlocks;
+ return 0;
+}
+#endif /* HAVE_VOP_LOCK */
+
+#ifdef HAVE_VOP_UNLOCK
+int
+nnpfs_unlock(struct vop_unlock_args * ap)
+{
+ struct vnode *vp = ap->a_vp;
+ struct nnpfs_node *xn = VNODE_TO_XNODE(vp);
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_unlock: %lx, %d\n",
+ (unsigned long)vp, xn->vnlocks));
+
+ --xn->vnlocks;
+ if (xn->vnlocks < 0) {
+ printf ("PANIC: nnpfs_unlock: unlocking unlocked\n");
+ xn->vnlocks = 0;
+ }
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_unlock: return\n"));
+
+ return 0;
+}
+#endif /* HAVE_VOP_UNLOCK */
+
+#ifdef HAVE_VOP_ISLOCKED
+int
+nnpfs_islocked (struct vop_islocked_args *ap)
+{
+ struct vnode *vp = ap->a_vp;
+ struct nnpfs_node *xn = VNODE_TO_XNODE(vp);
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_islocked: %lx, %d\n",
+ (unsigned long)vp, xn->vnlocks));
+
+ return xn->vnlocks;
+}
+#endif /* HAVE_VOP_ISLOCKED */
+#endif /* !HAVE_KERNEL_LOCKMGR */
+
+#ifdef HAVE_VOP_ABORTOP
+int
+nnpfs_abortop (struct vop_abortop_args *ap)
+ /* struct vnode *dvp;
+ struct componentname *cnp; */
+{
+ struct componentname *cnp = ap->a_cnp;
+
+ if ((cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
+#if defined(HAVE_KERNEL_ZFREEI)
+ zfreei(namei_zone, cnp->cn_pnbuf);
+ ap->a_cnp->cn_flags &= ~HASBUF;
+#elif defined(HAVE_KERNEL_UMA_ZFREE_ARG)
+ uma_zfree_arg(namei_zone, cnp->cn_pnbuf, NULL);
+ cnp->cn_flags &= ~HASBUF;
+#elif defined(FREE_ZONE)
+ FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
+#elif defined(HAVE_KERNEL_ZFREE)
+ zfree(namei_zone, cnp->cn_pnbuf);
+ ap->a_cnp->cn_flags &= ~HASBUF;
+#elif defined(PNBUF_PUT)
+ PNBUF_PUT(cnp->cn_pnbuf);
+#else
+ pool_put(&namei_pool, cnp->cn_pnbuf);
+#endif
+ return 0;
+}
+#endif /* HAVE_VOP_ABORTOP */
+
+#ifdef HAVE_VOP_MMAP
+int
+nnpfs_mmap(struct vop_mmap_args *ap)
+ /*
+ IN struct vnode *vp;
+ IN int fflags;
+ IN struct ucred *cred;
+ IN struct proc *p;
+ */
+{
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_mmap\n"));
+#ifdef HAVE_KERNEL_GENFS_MMAP
+ return genfs_mmap(ap);
+#else
+ return EOPNOTSUPP;
+#endif
+}
+#endif /* HAVE_VOP_MMAP */
+
+#ifdef HAVE_VOP_BMAP
+int
+nnpfs_bmap(struct vop_bmap_args *ap)
+ /* IN struct vnode *vp;
+ IN daddr64_t bn;
+ OUT struct vnode **vpp;
+ IN daddr64_t *bnp;
+ OUT int *runp;
+ OUT int *runb;
+ */
+{
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_bmap\n"));
+ return EOPNOTSUPP;
+}
+#endif /* HAVE_VOP_BMAP */
+
+#ifdef HAVE_VOP_GETPAGES
+
+static size_t
+get_pages_endlength (struct vop_getpages_args *ap)
+{
+#ifdef HAVE_STRUCT_VOP_GETPAGES_ARGS_A_OFFSET
+ /* NetBSD ubc */
+ return (ap->a_offset << PAGE_SHIFT) + *ap->a_count * PAGE_SIZE;
+#else
+ return (ap->a_reqpage << PAGE_SHIFT) + ap->a_count * PAGE_SIZE;
+#endif
+}
+
+int
+nnpfs_getpages (struct vop_getpages_args *ap)
+ /* Old BSD
+ IN struct vnode *vp;
+ IN vm_page_t *m;
+ IN int count;
+ IN int reqpage;
+ IN vm_ooffset_t offset;
+ */
+ /* NetBSD UBC
+ IN struct vnode *vp;
+ IN voff_t offset;
+ IN vm_page_t *m;
+ IN int *count;
+ IN int centeridx;
+ IN vm_prot_t access_type;
+ IN int advice;
+ IN int flags;
+ */
+{
+ int error;
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_getpages\n"));
+
+#if HAVE_KERNEL_VNODE_PAGER_GENERIC_GETPAGES
+ error = vnode_pager_generic_getpages (ap->a_vp, ap->a_m,
+ ap->a_count, ap->a_reqpage);
+#else
+ error = nnpfs_data_valid (ap->a_vp, VNODE_TO_XNODE(ap->a_vp)->rd_cred,
+ nnpfs_curproc(), NNPFS_DATA_R,
+ get_pages_endlength(ap));
+ if (error == 0)
+ error = VOP_GETPAGES(DATA_FROM_VNODE(ap->a_vp),
+ ap->a_offset, ap->a_m,
+ ap->a_count, ap->a_centeridx, ap->a_access_type,
+ ap->a_advice, ap->a_flags);
+#endif
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_getpages = %d\n", error));
+ return error;
+}
+#endif /* HAVE_VOP_GETPAGES */
+
+#ifdef HAVE_VOP_PUTPAGES
+int
+nnpfs_putpages (struct vop_putpages_args *ap)
+ /* Old BSD
+ IN struct vnode *vp;
+ IN vm_page_t *m;
+ IN int count;
+ IN int sync;
+ IN int *rtvals;
+ IN vm_ooffset_t offset;
+ */
+ /* NetBSD UBC (>= 1.5Y)
+ IN struct vnode *vp;
+ IN voff_t offlo;
+ IN voff_t offhi;
+ IN int flags;
+ */
+{
+ struct vnode *vp = ap->a_vp;
+ struct nnpfs_node *xn = VNODE_TO_XNODE(vp);
+ struct vnode *t = DATA_FROM_XNODE(xn);
+ int error;
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_putpages\n"));
+
+ if (t == NULL)
+ return 0;
+
+#ifdef HAVE_STRUCT_VOP_PUTPAGES_ARGS_A_SYNC /* FreeBSD-style */
+ xn->flags |= NNPFS_DATA_DIRTY;
+
+ return VOP_PUTPAGES(t, ap->a_m, ap->a_count, ap->a_sync, ap->a_rtvals,
+ ap->a_offset);
+#else /* NetBSD-style */
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 105250000
+ /* XXX should only walk over those pages that is requested */
+ if (vp->v_type == VREG && ap->a_flags & PGO_CLEANIT) {
+ struct uvm_object *uobj = &t->v_uobj;
+ struct vm_page *pg;
+ int dirty = 0;
+
+ pg = TAILQ_FIRST(&uobj->memq);
+
+ while (pg && !dirty) {
+ dirty = pmap_is_modified(pg) || (pg->flags & PG_CLEAN) == 0;
+ pg = TAILQ_NEXT(pg, fq.queues.listq);
+ }
+
+ if (dirty)
+ xn->flags |= NNPFS_DATA_DIRTY;
+ }
+
+ return VOP_PUTPAGES(t, ap->a_offlo, ap->a_offhi, ap->a_flags);
+#else
+ xn->flags |= NNPFS_DATA_DIRTY;
+ return VOP_PUTPAGES(t, ap->a_m, ap->a_count, ap->a_flags, ap->a_rtvals);
+#endif
+#endif /* HAVE_STRUCT_VOP_PUTPAGES_ARGS_A_SYNC */
+}
+#endif /* HAVE_VOP_PUTPAGES */
+
+#ifdef HAVE_VOP_CMP
+int
+nnpfs_cmp(struct vnode * vp1, struct vnode * vp2)
+{
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_cmp\n"));
+ return EOPNOTSUPP;
+}
+#endif /* HAVE_VOP_CMP */
+
+#ifdef HAVE_VOP_REALVP
+int
+nnpfs_realvp(struct vnode * vp,
+ struct vnode ** vpp)
+{
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_realvp\n"));
+ return EOPNOTSUPP;
+}
+#endif /* HAVE_VOP_REALVP */
+
+#ifdef HAVE_VOP_CNTL
+int
+nnpfs_cntl(struct vnode * vp,
+ int cmd,
+ caddr_t idata,
+ caddr_t odata,
+ int iflag,
+ int oflag)
+{
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_cntl\n"));
+ return EOPNOTSUPP;
+}
+#endif /* HAVE_VOP_CNTL */
+
+#ifdef HAVE_VOP_PRINT
+int
+nnpfs_print (struct vop_print_args *v)
+{
+ struct vop_print_args *ap = v;
+ nnpfs_printnode_common (ap->a_vp);
+ return 0;
+}
+#endif
+
+#ifdef HAVE_VOP_ADVLOCK
+int
+nnpfs_advlock(struct vop_advlock_args *v)
+{
+ struct vop_advlock_args *ap = v;
+#if defined(HAVE_KERNEL_LF_ADVLOCK) && !defined(__APPLE__)
+ struct nnpfs_node *xn = VNODE_TO_XNODE(ap->a_vp);
+
+ return (lf_advlock(&xn->lockf, xn->attr.va_size, ap->a_id, ap->a_op,
+ ap->a_fl, ap->a_flags));
+#else
+ return EOPNOTSUPP;
+#endif
+}
+#endif /* HAVE_VOP_ADVOCK */
+
+#ifdef HAVE_VOP_REVOKE
+int
+nnpfs_revoke(struct vop_revoke_args *v)
+{
+#if defined(HAVE_KERNEL_GENFS_REVOKE)
+ return genfs_revoke (v);
+#elif defined(HAVE_KERNEL_VOP_REVOKE)
+ return vop_revoke (v);
+#else
+ return EOPNOTSUPP;
+#endif
+}
+#endif /* HAVE_VOP_REVOKE */
+
+#ifdef HAVE_VOP_PAGEIN
+int
+nnpfs_pagein(struct vop_pagein_args *ap)
+{
+#ifdef __APPLE__
+ struct uio uio;
+ struct iovec iov;
+ int ret;
+
+ kernel_upl_map(kernel_map, ap->a_pl, &iov.iov_base);
+ iov.iov_base+=ap->a_pl_offset;
+ iov.iov_len=ap->a_size;
+
+ uio.uio_iov=&iov;
+ uio.uio_iovcnt=1;
+ uio.uio_offset=ap->a_f_offset;
+ uio.uio_resid=ap->a_size;
+ uio.uio_segflg=UIO_SYSSPACE; /* XXX what is it? */
+ uio.uio_rw=UIO_READ;
+ uio.uio_procp=nnpfs_curproc();
+
+ ret = VOP_READ(ap->a_vp, &uio, 0, ap->a_cred);
+
+ /* Zero out rest of last page if there wasn't enough data in the file */
+ if (ret == 0 && uio.uio_resid > 0)
+ bzero(iov.iov_base, uio.uio_resid);
+
+ kernel_upl_unmap(kernel_map, ap->a_pl);
+
+ if (ret) {
+ kernel_upl_abort_range(ap->a_pl, ap->a_pl_offset, ap->a_size,
+ UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
+ } else {
+ kernel_upl_commit_range(ap->a_pl, ap->a_pl_offset, ap->a_size,
+ UPL_COMMIT_CLEAR_DIRTY | UPL_COMMIT_FREE_ON_EMPTY,
+ UPL_GET_INTERNAL_PAGE_LIST(ap->a_pl));
+ }
+
+ return ret;
+#else
+#error pagein on non apple ?
+#endif
+}
+
+#endif
+
+#ifdef HAVE_VOP_PAGEOUT
+int
+nnpfs_pageout(struct vop_pageout_args *ap)
+{
+#ifdef __APPLE__
+ struct uio uio;
+ struct iovec iov;
+ int ret;
+
+ kernel_upl_map(kernel_map, ap->a_pl, &iov.iov_base);
+ iov.iov_base+=ap->a_pl_offset;
+ iov.iov_len=ap->a_size;
+
+ uio.uio_iov=&iov;
+ uio.uio_iovcnt=1;
+ uio.uio_offset=ap->a_f_offset;
+ uio.uio_resid=ap->a_size;
+ uio.uio_segflg=UIO_SYSSPACE; /* XXX what is it? */
+ uio.uio_rw=UIO_WRITE;
+ uio.uio_procp=nnpfs_curproc();
+
+ ret = VOP_WRITE(ap->a_vp, &uio, 0, ap->a_cred);
+
+ kernel_upl_unmap(kernel_map, ap->a_pl);
+
+ if (ret) {
+ kernel_upl_abort_range(ap->a_pl, ap->a_pl_offset, ap->a_size,
+ UPL_ABORT_FREE_ON_EMPTY);
+ } else {
+ kernel_upl_commit_range(ap->a_pl, ap->a_pl_offset, ap->a_size,
+ UPL_COMMIT_CLEAR_DIRTY | UPL_COMMIT_FREE_ON_EMPTY,
+ UPL_GET_INTERNAL_PAGE_LIST(ap->a_pl));
+ }
+
+ return ret;
+#else
+#error pageout on non apple ?
+#endif
+}
+#endif
+
+#ifdef HAVE_VOP_CREATEVOBJECT
+int
+nnpfs_createvobject(struct vop_createvobject_args *ap)
+/*
+struct vop_createvobject_args {
+ struct vnode *vp;
+ struct ucred *cred;
+ struct proc *p;
+};
+ */
+{
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_createvobject\n"));
+
+ return vop_stdcreatevobject (ap);
+}
+#endif /* HAVE_VOP_CREATEVOBJECT */
+
+#ifdef HAVE_VOP_DESTROYVOBJECT
+int
+nnpfs_destroyvobject(struct vop_destroyvobject_args *ap)
+/*
+struct vop_destroyvobject_args {
+ struct vnode *vp;
+};
+ */
+{
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_destroyvobject\n"));
+
+ return vop_stddestroyvobject (ap);
+}
+#endif /* HAVE_VOP_DESTROYVOBJECT */
+
+#ifdef HAVE_VOP_GETVOBJECT
+int
+nnpfs_getvobject(struct vop_getvobject_args *ap)
+/*
+struct vop_getvobject_args {
+ struct vnode *vp;
+ struct vm_object **objpp;
+};
+ */
+{
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_getvobject\n"));
+
+ return vop_stdgetvobject (ap);
+}
+#endif /* HAVE_VOP_GETVOBJECT */
+
+#ifdef HAVE_VOP_PATHCONF
+int
+nnpfs_pathconf(struct vop_pathconf_args *ap)
+/*
+struct vop_pathconf_args {
+ struct vnodeop_desc *a_desc;
+ struct vnode *a_vp;
+ int a_name;
+};
+*/
+{
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_pathconf\n"));
+
+#ifdef HAVE_KERNEL_VOP_STDPATHCONF
+ return vop_stdpathconf(ap);
+#else
+ return EOPNOTSUPP;
+#endif
+}
+#endif
+
+
+
+vop_t **nnpfs_vnodeop_p;
+
+int
+nnpfs_eopnotsupp (struct vop_generic_args *ap)
+{
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_eopnotsupp %s\n", ap->a_desc->vdesc_name));
+ return EOPNOTSUPP;
+}
+
+int
+nnpfs_returnzero (struct vop_generic_args *ap)
+{
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_returnzero %s\n", ap->a_desc->vdesc_name));
+ return 0;
+}
+
+void
+nnpfs_pushdirty(struct vnode *vp, struct ucred *cred, d_thread_t *p)
+{
+#if defined(__NetBSD_Version__) && __NetBSD_Version__ >= 105280000
+ VOP_PUTPAGES(vp, 0, 0, PGO_ALLPAGES|PGO_SYNCIO|PGO_CLEANIT);
+#elif defined(__APPLE__)
+ ubc_pushdirty(vp);
+#endif
+}
+
+
+
+static struct vnodeopv_entry_desc nnpfs_vnodeop_entries[] = {
+ {&vop_default_desc, (vop_t *) nnpfs_eopnotsupp},
+#ifdef HAVE_VOP_LOOKUP
+#ifdef HAVE_KERNEL_VFS_CACHE_LOOKUP
+ {&vop_lookup_desc, (vop_t *) vfs_cache_lookup },
+#else
+ {&vop_lookup_desc, (vop_t *) nnpfs_lookup },
+#endif
+#endif
+#ifdef HAVE_VOP_CACHEDLOOKUP
+ {&vop_cachedlookup_desc, (vop_t *) nnpfs_cachedlookup },
+#endif
+#ifdef HAVE_VOP_OPEN
+ {&vop_open_desc, (vop_t *) nnpfs_open },
+#endif
+#ifdef HAVE_VOP_FSYNC
+ {&vop_fsync_desc, (vop_t *) nnpfs_fsync },
+#endif
+#ifdef HAVE_VOP_CLOSE
+ {&vop_close_desc, (vop_t *) nnpfs_close },
+#endif
+#ifdef HAVE_VOP_READ
+ {&vop_read_desc, (vop_t *) nnpfs_read },
+#endif
+#ifdef HAVE_VOP_WRITE
+ {&vop_write_desc, (vop_t *) nnpfs_write },
+#endif
+#ifdef HAVE_VOP_MMAP
+ {&vop_mmap_desc, (vop_t *) nnpfs_mmap },
+#endif
+#ifdef HAVE_VOP_BMAP
+ {&vop_bmap_desc, (vop_t *) nnpfs_bmap },
+#endif
+#ifdef HAVE_VOP_IOCTL
+ {&vop_ioctl_desc, (vop_t *) nnpfs_ioctl },
+#endif
+#ifdef HAVE_VOP_SELECT
+ {&vop_select_desc, (vop_t *) nnpfs_select },
+#endif
+#ifdef HAVE_VOP_SEEK
+ {&vop_seek_desc, (vop_t *) nnpfs_seek },
+#endif
+#ifdef HAVE_VOP_POLL
+ {&vop_poll_desc, (vop_t *) nnpfs_poll },
+#endif
+#ifdef HAVE_VOP_GETATTR
+ {&vop_getattr_desc, (vop_t *) nnpfs_getattr },
+#endif
+#ifdef HAVE_VOP_SETATTR
+ {&vop_setattr_desc, (vop_t *) nnpfs_setattr },
+#endif
+#ifdef HAVE_VOP_ACCESS
+ {&vop_access_desc, (vop_t *) nnpfs_access },
+#endif
+#ifdef HAVE_VOP_CREATE
+ {&vop_create_desc, (vop_t *) nnpfs_create },
+#endif
+#ifdef HAVE_VOP_REMOVE
+ {&vop_remove_desc, (vop_t *) nnpfs_remove },
+#endif
+#ifdef HAVE_VOP_LINK
+ {&vop_link_desc, (vop_t *) nnpfs_link },
+#endif
+#ifdef HAVE_VOP_RENAME
+ {&vop_rename_desc, (vop_t *) nnpfs_rename },
+#endif
+#ifdef HAVE_VOP_MKDIR
+ {&vop_mkdir_desc, (vop_t *) nnpfs_mkdir },
+#endif
+#ifdef HAVE_VOP_RMDIR
+ {&vop_rmdir_desc, (vop_t *) nnpfs_rmdir },
+#endif
+#ifdef HAVE_VOP_READDIR
+ {&vop_readdir_desc, (vop_t *) nnpfs_readdir },
+#endif
+#ifdef HAVE_VOP_SYMLINK
+ {&vop_symlink_desc, (vop_t *) nnpfs_symlink },
+#endif
+#ifdef HAVE_VOP_READLINK
+ {&vop_readlink_desc, (vop_t *) nnpfs_readlink },
+#endif
+#ifdef HAVE_VOP_INACTIVE
+ {&vop_inactive_desc, (vop_t *) nnpfs_inactive },
+#endif
+#ifdef HAVE_VOP_RECLAIM
+ {&vop_reclaim_desc, (vop_t *) nnpfs_reclaim },
+#endif
+#ifdef HAVE_VOP_LOCK
+ {&vop_lock_desc, (vop_t *) nnpfs_lock },
+#endif
+#ifdef HAVE_VOP_UNLOCK
+ {&vop_unlock_desc, (vop_t *) nnpfs_unlock },
+#endif
+#ifdef HAVE_VOP_ISLOCKED
+ {&vop_islocked_desc, (vop_t *) nnpfs_islocked },
+#endif
+#ifdef HAVE_VOP_ABORTOP
+ {&vop_abortop_desc, (vop_t *) nnpfs_abortop },
+#endif
+#ifdef HAVE_VOP_GETPAGES
+ {&vop_getpages_desc, (vop_t *) nnpfs_getpages },
+#endif
+#ifdef HAVE_VOP_PUTPAGES
+ {&vop_putpages_desc, (vop_t *) nnpfs_putpages },
+#endif
+#ifdef HAVE_VOP_REVOKE
+ {&vop_revoke_desc, (vop_t *) nnpfs_revoke },
+#endif
+#ifdef HAVE_VOP_PRINT
+ {&vop_print_desc, (vop_t *) nnpfs_print},
+#endif
+#ifdef HAVE_VOP_ADVLOCK
+ {&vop_advlock_desc, (vop_t *) nnpfs_advlock },
+#endif
+#ifdef HAVE_VOP_PAGEIN
+ {&vop_pagein_desc, (vop_t *) nnpfs_pagein },
+#endif
+#ifdef HAVE_VOP_PAGEOUT
+ {&vop_pageout_desc, (vop_t *) nnpfs_pageout },
+#endif
+#ifdef HAVE_VOP_CREATEVOBJECT
+ {&vop_createvobject_desc, (vop_t *) nnpfs_createvobject },
+#endif
+#ifdef HAVE_VOP_DESTROYVOBJECT
+ {&vop_destroyvobject_desc, (vop_t *) nnpfs_destroyvobject },
+#endif
+#ifdef HAVE_VOP_GETVOBJECT
+ {&vop_getvobject_desc, (vop_t *) nnpfs_getvobject },
+#endif
+#ifdef HAVE_VOP_PATHCONF
+ {&vop_pathconf_desc, (vop_t *) nnpfs_pathconf },
+#endif
+ {(struct vnodeop_desc *) NULL, (int (*) (void *)) NULL}
+};
+
+struct vnodeopv_desc nnpfs_vnodeop_opv_desc =
+{&nnpfs_vnodeop_p, nnpfs_vnodeop_entries};
+
+#ifdef VNODEOP_SET
+VNODEOP_SET(nnpfs_vnodeop_opv_desc);
+#endif
diff --git a/sys/nnpfs/nnpfs_vnodeops-common.c b/sys/nnpfs/nnpfs_vnodeops-common.c
new file mode 100644
index 00000000000..e8ed71842e9
--- /dev/null
+++ b/sys/nnpfs/nnpfs_vnodeops-common.c
@@ -0,0 +1,1146 @@
+/*
+ * Copyright (c) 1995 - 2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ */
+
+/*
+ * NNPFS operations.
+ */
+
+#include <nnpfs/nnpfs_locl.h>
+#include <nnpfs/nnpfs_message.h>
+#include <nnpfs/nnpfs_common.h>
+#include <nnpfs/nnpfs_fs.h>
+#include <nnpfs/nnpfs_dev.h>
+#include <nnpfs/nnpfs_deb.h>
+#include <nnpfs/nnpfs_syscalls.h>
+#include <nnpfs/nnpfs_vnodeops.h>
+
+RCSID("$arla: nnpfs_vnodeops-common.c,v 1.94 2003/01/27 11:58:50 lha Exp $");
+
+static void
+nnpfs_handle_stale(struct nnpfs_node *xn)
+{
+#if __APPLE__
+ struct vnode *vp = XNODE_TO_VNODE(xn);
+#endif
+
+ if ((xn->flags & NNPFS_STALE) == 0)
+ return;
+
+#if __APPLE__
+ if (UBCISVALID(vp) && !ubc_isinuse(vp, 1)) {
+ xn->flags &= ~NNPFS_STALE;
+ ubc_setsize(vp, 0);
+ NNPFS_TOKEN_CLEAR(xn, ~0,
+ NNPFS_OPEN_MASK | NNPFS_ATTR_MASK |
+ NNPFS_DATA_MASK | NNPFS_LOCK_MASK);
+ }
+#endif
+}
+
+int
+nnpfs_open_valid(struct vnode *vp, struct ucred *cred, d_thread_t *p,
+ u_int tok)
+{
+ struct nnpfs *nnpfsp = NNPFS_FROM_VNODE(vp);
+ struct nnpfs_node *xn = VNODE_TO_XNODE(vp);
+ int error = 0;
+
+ NNPFSDEB(XDEBVFOPS, ("nnpfs_open_valid\n"));
+
+ nnpfs_handle_stale(xn);
+
+ do {
+ if (!NNPFS_TOKEN_GOT(xn, tok)) {
+ struct nnpfs_message_open msg;
+
+ msg.header.opcode = NNPFS_MSG_OPEN;
+ msg.cred.uid = cred->cr_uid;
+ msg.cred.pag = nnpfs_get_pag(cred);
+ msg.handle = xn->handle;
+ msg.tokens = tok;
+
+ error = nnpfs_message_rpc(nnpfsp->fd, &msg.header, sizeof(msg), p);
+
+ if (error == 0)
+ error = ((struct nnpfs_message_wakeup *) & msg)->error;
+ } else {
+ goto done;
+ }
+ } while (error == 0);
+
+done:
+ NNPFSDEB(XDEBVFOPS, ("nnpfs_open_valid: error = %d\n", error));
+
+ return error;
+}
+
+int
+nnpfs_attr_valid(struct vnode *vp, struct ucred *cred, d_thread_t *p,
+ u_int tok)
+{
+ struct nnpfs *nnpfsp = NNPFS_FROM_VNODE(vp);
+ struct nnpfs_node *xn = VNODE_TO_XNODE(vp);
+ int error = 0;
+ nnpfs_pag_t pag = nnpfs_get_pag(cred);
+
+ do {
+ if (!NNPFS_TOKEN_GOT(xn, tok) || !nnpfs_has_pag(xn, pag)) {
+ struct nnpfs_message_getattr msg;
+
+ msg.header.opcode = NNPFS_MSG_GETATTR;
+ msg.cred.uid = cred->cr_uid;
+ msg.cred.pag = pag;
+ msg.handle = xn->handle;
+ error = nnpfs_message_rpc(nnpfsp->fd, &msg.header, sizeof(msg), p);
+ if (error == 0)
+ error = ((struct nnpfs_message_wakeup *) & msg)->error;
+ } else {
+ goto done;
+ }
+ } while (error == 0);
+
+done:
+ return error;
+}
+
+int
+nnpfs_data_valid(struct vnode *vp, struct ucred *cred, d_thread_t *p,
+ u_int tok, uint32_t want_offset)
+{
+ struct nnpfs *nnpfsp = NNPFS_FROM_VNODE(vp);
+ struct nnpfs_node *xn = VNODE_TO_XNODE(vp);
+ int error = 0;
+ uint32_t offset;
+ struct nnpfs_message_getdata msg;
+
+ do {
+ offset = want_offset;
+ if (NNPFS_TOKEN_GOT(xn, tok|NNPFS_ATTR_R) && offset > xn->attr.va_size) {
+ offset = xn->attr.va_size;
+ }
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_data_valid: offset: want %ld has %ld, "
+ "tokens: want %lx has %lx length: %ld\n",
+ (long) offset, (long) xn->offset,
+ (long) tok, (long) xn->tokens,
+ (long) xn->attr.va_size));
+
+ if (NNPFS_TOKEN_GOT(xn, tok)) {
+ if (offset <= xn->offset || xn->attr.va_type == VDIR) {
+ break;
+ }
+ }
+
+ msg.header.opcode = NNPFS_MSG_GETDATA;
+ msg.cred.uid = cred->cr_uid;
+ msg.cred.pag = nnpfs_get_pag(cred);
+ msg.handle = xn->handle;
+ msg.tokens = tok;
+ msg.offset = offset;
+
+ error = nnpfs_message_rpc(nnpfsp->fd, &msg.header, sizeof(msg), p);
+
+ if (error == 0)
+ error = ((struct nnpfs_message_wakeup *) & msg)->error;
+
+ } while (error == 0);
+
+ return error;
+}
+
+int
+nnpfs_open_common(struct vnode *vp,
+ int mode,
+ struct ucred *cred,
+ d_thread_t *p)
+{
+ struct nnpfs_node *xn = VNODE_TO_XNODE(vp);
+ int ret;
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_open\n"));
+
+ if (mode & FWRITE) {
+ ret = nnpfs_open_valid(vp, cred, p, NNPFS_OPEN_NW);
+ } else {
+ ret = nnpfs_open_valid(vp, cred, p, NNPFS_OPEN_NR);
+ }
+
+ /* always update the read cred */
+
+ if (mode & FWRITE)
+ nnpfs_update_write_cred(xn, cred);
+ nnpfs_update_read_cred(xn, cred);
+
+ return ret;
+}
+
+static int
+do_fsync(struct nnpfs *nnpfsp,
+ struct nnpfs_node *xn,
+ struct ucred *cred,
+ d_thread_t *p,
+ u_int flag)
+{
+ int error;
+ struct nnpfs_message_putdata msg;
+
+ msg.header.opcode = NNPFS_MSG_PUTDATA;
+ if (cred != NOCRED) {
+ msg.cred.uid = cred->cr_uid;
+ msg.cred.pag = nnpfs_get_pag(cred);
+ } else {
+ msg.cred.uid = 0;
+ msg.cred.pag = NNPFS_ANONYMOUSID;
+ }
+ msg.handle = xn->handle;
+ vattr2nnpfs_attr(&xn->attr, &msg.attr);
+ msg.flag = flag;
+
+ error = nnpfs_message_rpc(nnpfsp->fd, &msg.header, sizeof(msg), p);
+
+ if (error == 0)
+ error = ((struct nnpfs_message_wakeup *) & msg)->error;
+
+ if (error == 0)
+ xn->flags &= ~NNPFS_DATA_DIRTY;
+
+ return error;
+}
+
+int
+nnpfs_fsync_common(struct vnode *vp, struct ucred *cred,
+ int waitfor, d_thread_t *proc)
+{
+ struct nnpfs *nnpfsp = NNPFS_FROM_VNODE(vp);
+ struct nnpfs_node *xn = VNODE_TO_XNODE(vp);
+ int error = 0;
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_fsync: %lx\n", (unsigned long)vp));
+
+ /*
+ * It seems that fsync is sometimes called after reclaiming a node.
+ * In that case we just look happy.
+ */
+
+ if (xn == NULL) {
+ printf("NNPFS PANIC WARNING! nnpfs_fsync called after reclaiming!\n");
+ return 0;
+ }
+
+ nnpfs_pushdirty(vp, cred, proc);
+
+ if (xn->flags & NNPFS_DATA_DIRTY) {
+#ifdef FSYNC_RECLAIM
+ /* writing back the data from this vnode failed */
+ if (waitfor & FSYNC_RECLAIM) {
+ printf("nnpfs_fsync: data lost, failed to write back\n");
+ xn->flags &= ~NNPFS_DATA_DIRTY;
+ return 0;
+ }
+#endif
+ error = do_fsync(nnpfsp, xn, cred, proc, NNPFS_WRITE | NNPFS_FSYNC);
+ }
+
+ return error;
+}
+
+int
+nnpfs_close_common(struct vnode *vp, int fflag,
+ d_thread_t *proc, struct ucred *cred)
+{
+ struct nnpfs *nnpfsp = NNPFS_FROM_VNODE(vp);
+ struct nnpfs_node *xn = VNODE_TO_XNODE(vp);
+ int error = 0;
+
+ NNPFSDEB(XDEBVNOPS,
+ ("nnpfs_close cred = %lx, fflag = %x, xn->flags = %x\n",
+ (unsigned long)cred, fflag, xn->flags));
+
+ if (vp->v_type == VREG)
+ nnpfs_pushdirty(vp, cred, proc);
+
+ if (fflag & FWRITE && xn->flags & NNPFS_DATA_DIRTY)
+ error = do_fsync(nnpfsp, xn, cred, proc, NNPFS_WRITE);
+
+ return error;
+}
+
+size_t
+nnpfs_uio_end_length (struct uio *uio)
+{
+#ifdef DIAGNOSTIC
+ size_t sz = 0;
+ int i;
+
+ for (i = 0; i < uio->uio_iovcnt; i++)
+ sz += uio->uio_iov[i].iov_len;
+ if (sz != uio->uio_resid)
+ panic("nnpfs_uio_end_length");
+#endif
+ return uio->uio_offset + uio->uio_resid;
+}
+
+
+int
+nnpfs_read_common(struct vnode *vp, struct uio *uio, int ioflag,
+ struct ucred *cred)
+{
+ int error = 0;
+ int i;
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_read\n"));
+
+ nnpfs_update_read_cred(VNODE_TO_XNODE(vp), cred);
+
+#ifdef HAVE_FREEBSD_THREAD
+ error = nnpfs_data_valid(vp, cred, nnpfs_uio_to_thread(uio), NNPFS_DATA_R,
+ nnpfs_uio_end_length(uio));
+#else
+ error = nnpfs_data_valid(vp, cred, nnpfs_uio_to_proc(uio), NNPFS_DATA_R,
+ nnpfs_uio_end_length(uio));
+#endif
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_read: iovcnt: %d\n", uio->uio_iovcnt));
+ for (i = 0; i < uio->uio_iovcnt; i++)
+ NNPFSDEB(XDEBVNOPS, (" base: %lx len: %lu\n",
+ (unsigned long)uio->uio_iov[i].iov_base,
+ (unsigned long)uio->uio_iov[i].iov_len));
+
+ if (error == 0) {
+ struct vnode *t = DATA_FROM_VNODE(vp);
+
+#ifdef HAVE_FREEBSD_THREAD
+ nnpfs_vfs_readlock(t, nnpfs_uio_to_thread(uio));
+ nnpfs_vop_read(t, uio, ioflag, cred, error);
+ nnpfs_vfs_unlock(t, nnpfs_uio_to_thread(uio));
+#else
+ nnpfs_vfs_readlock(t, nnpfs_uio_to_proc(uio));
+ nnpfs_vop_read(t, uio, ioflag, cred, error);
+ nnpfs_vfs_unlock(t, nnpfs_uio_to_proc(uio));
+#endif
+ }
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_read offset: %lu resid: %lu\n",
+ (unsigned long)uio->uio_offset,
+ (unsigned long)uio->uio_resid));
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_read error: %d\n", error));
+
+ return error;
+}
+
+int
+nnpfs_write_common(struct vnode *vp, struct uio *uiop, int ioflag,
+ struct ucred *cred)
+{
+ struct nnpfs_node *xn = VNODE_TO_XNODE(vp);
+ int error = 0;
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_write\n"));
+
+ nnpfs_update_write_cred(xn, cred);
+
+#ifdef HAVE_FREEBSD_THREAD
+ error = nnpfs_data_valid(vp, cred, nnpfs_uio_to_thread(uiop), NNPFS_DATA_W,
+ VNODE_TO_XNODE(vp)->attr.va_size);
+#else
+ error = nnpfs_data_valid(vp, cred, nnpfs_uio_to_proc(uiop), NNPFS_DATA_W,
+ VNODE_TO_XNODE(vp)->attr.va_size);
+#endif
+
+ if (error == 0) {
+ struct vnode *t = DATA_FROM_XNODE(xn);
+ struct vattr sub_attr;
+ int error2 = 0;
+
+ #ifdef HAVE_FREEBSD_THREAD
+ nnpfs_vfs_writelock(t, nnpfs_uio_to_thread(uiop));
+ nnpfs_vop_write(t, uiop, ioflag, cred, error);
+ VNODE_TO_XNODE(vp)->flags |= NNPFS_DATA_DIRTY;
+ nnpfs_vop_getattr(t, &sub_attr, cred, nnpfs_uio_to_thread(uiop), error2);
+ #else
+ nnpfs_vfs_writelock(t, nnpfs_uio_to_proc(uiop));
+ nnpfs_vop_write(t, uiop, ioflag, cred, error);
+ VNODE_TO_XNODE(vp)->flags |= NNPFS_DATA_DIRTY;
+ nnpfs_vop_getattr(t, &sub_attr, cred, nnpfs_uio_to_proc(uiop), error2);
+ #endif
+
+ if (error2 == 0) {
+ xn->attr.va_size = sub_attr.va_size;
+ xn->attr.va_bytes = sub_attr.va_size;
+ xn->attr.va_mtime = sub_attr.va_mtime;
+ nnpfs_set_vp_size(vp, sub_attr.va_size);
+ xn->offset = sub_attr.va_size;
+ }
+#ifdef HAVE_FREEBSD_THREAD
+ nnpfs_vfs_unlock(t, nnpfs_uio_to_thread(uiop));
+#else
+ nnpfs_vfs_unlock(t, nnpfs_uio_to_proc(uiop));
+#endif
+ }
+
+ return error;
+}
+
+int
+nnpfs_getattr_common(struct vnode *vp, struct vattr *vap,
+ struct ucred *cred, d_thread_t *p)
+{
+ int error = 0;
+
+ struct nnpfs_node *xn = VNODE_TO_XNODE(vp);
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_getattr\n"));
+
+ error = nnpfs_attr_valid(vp, cred, p, NNPFS_ATTR_R);
+ if (error == 0)
+ *vap = xn->attr;
+ return error;
+}
+
+int
+nnpfs_setattr_common(struct vnode *vp, struct vattr *vap,
+ struct ucred *cred, d_thread_t *p)
+{
+ struct nnpfs *nnpfsp = NNPFS_FROM_VNODE(vp);
+ struct nnpfs_node *xn = VNODE_TO_XNODE(vp);
+ int error = 0;
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_setattr\n"));
+
+#define CHECK_NNPFSATTR(A, cast) (vap->A == cast VNOVAL || vap->A == xn->attr.A)
+ if (CHECK_NNPFSATTR(va_mode,(mode_t)) &&
+ CHECK_NNPFSATTR(va_nlink,(short)) &&
+ CHECK_NNPFSATTR(va_size,(va_size_t)) &&
+ CHECK_NNPFSATTR(va_uid,(uid_t)) &&
+ CHECK_NNPFSATTR(va_gid,(gid_t)) &&
+ CHECK_NNPFSATTR(va_mtime.tv_sec,(unsigned int)) &&
+ CHECK_NNPFSATTR(va_fileid,(long)) &&
+ CHECK_NNPFSATTR(va_type,(enum vtype)))
+ return 0; /* Nothing to do */
+#undef CHECK_NNPFSATTR
+
+ if (NNPFS_TOKEN_GOT(xn, NNPFS_ATTR_W)) {
+ /* Update attributes and mark them dirty. */
+ VNODE_TO_XNODE(vp)->flags |= NNPFS_ATTR_DIRTY;
+ error = EINVAL; /* XXX not yet implemented */
+ goto done;
+ } else {
+ struct nnpfs_message_putattr msg;
+
+ msg.header.opcode = NNPFS_MSG_PUTATTR;
+ if (cred != NOCRED) {
+ msg.cred.uid = cred->cr_uid;
+ msg.cred.pag = nnpfs_get_pag(cred);
+ } else {
+ msg.cred.uid = 0;
+ msg.cred.pag = NNPFS_ANONYMOUSID;
+ }
+ msg.handle = xn->handle;
+ vattr2nnpfs_attr(vap, &msg.attr);
+ if (NNPFS_TOKEN_GOT(xn, NNPFS_DATA_R)) {
+ if (vp->v_type == VREG) {
+ if (vap->va_size != (va_size_t)VNOVAL)
+ XA_SET_SIZE(&msg.attr, vap->va_size);
+ else
+ XA_SET_SIZE(&msg.attr, xn->attr.va_size);
+#ifdef __APPLE__
+ /* XXX needed ? */
+ if (UBCINFOEXISTS(vp))
+ ubc_setsize(vp, msg.attr.xa_size);
+#endif
+ }
+ if (vap->va_mtime.tv_sec != (unsigned int)VNOVAL)
+ XA_SET_MTIME(&msg.attr, vap->va_mtime.tv_sec);
+ else
+ XA_SET_MTIME(&msg.attr, xn->attr.va_mtime.tv_sec);
+ }
+
+ NNPFS_TOKEN_CLEAR(xn, NNPFS_ATTR_VALID, NNPFS_ATTR_MASK);
+ error = nnpfs_message_rpc(nnpfsp->fd, &msg.header, sizeof(msg), p);
+ if (error == 0)
+ error = ((struct nnpfs_message_wakeup *) & msg)->error;
+ }
+
+done:
+ return error;
+}
+
+static int
+check_rights (u_char rights, int mode)
+{
+ int error = 0;
+
+ if (mode & VREAD)
+ if ((rights & NNPFS_RIGHT_R) == 0)
+ error = EACCES;
+ if (mode & VWRITE)
+ if ((rights & NNPFS_RIGHT_W) == 0)
+ error = EACCES;
+ if (mode & VEXEC)
+ if ((rights & NNPFS_RIGHT_X) == 0)
+ error = EACCES;
+ return error;
+}
+
+int
+nnpfs_access_common(struct vnode *vp, int mode, struct ucred *cred,
+ d_thread_t *p)
+{
+ int error = 0;
+ nnpfs_pag_t pag = nnpfs_get_pag(cred);
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_access mode = 0%o\n", mode));
+
+ error = nnpfs_attr_valid(vp, cred, p, NNPFS_ATTR_R);
+ if (error == 0) {
+ struct nnpfs_node *xn = VNODE_TO_XNODE(vp);
+ int i;
+
+ error = check_rights (xn->anonrights, mode);
+
+ if (error == 0)
+ goto done;
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_access anonaccess failed\n"));
+
+ error = EACCES; /* default to EACCES if pag isn't in xn->id */
+
+ for (i = 0; i < MAXRIGHTS; i++)
+ if (xn->id[i] == pag) {
+ error = check_rights (xn->rights[i], mode);
+ break;
+ }
+ }
+
+done:
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_access(0%o) = %d\n", mode, error));
+
+ return error;
+}
+
+int
+nnpfs_lookup_common(struct vnode *dvp,
+ nnpfs_componentname *cnp,
+ struct vnode **vpp)
+{
+ struct nnpfs_message_getnode msg;
+ struct nnpfs *nnpfsp = NNPFS_FROM_VNODE(dvp);
+ struct nnpfs_node *d = VNODE_TO_XNODE(dvp);
+ int error = 0;
+#ifdef HAVE_FREEBSD_THREAD
+ d_thread_t *proc = nnpfs_cnp_to_thread(cnp);
+ struct ucred *cred = nnpfs_thread_to_cred(proc);
+#else
+ d_thread_t *proc = nnpfs_cnp_to_proc(cnp);
+ struct ucred *cred = nnpfs_proc_to_cred(proc);
+#endif
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_lookup_common: enter\n"));
+
+ *vpp = NULL;
+
+ if (cnp->cn_namelen >= NNPFS_MAX_NAME)
+ return ENAMETOOLONG;
+
+ if (dvp->v_type != VDIR)
+ return ENOTDIR;
+
+ if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
+ *vpp = dvp;
+ VREF(*vpp);
+ return 0;
+ }
+
+ do {
+ nnpfs_vop_access(dvp, VEXEC, cred, proc, error);
+ if (error != 0)
+ goto done;
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_lookup_common: dvp = %lx\n",
+ (unsigned long) dvp));
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_lookup_common: cnp = %lx, "
+ "cnp->cn_nameiop = %d\n",
+ (unsigned long) cnp, (int)cnp->cn_nameiop));
+
+
+ error = nnpfs_dnlc_lookup(dvp, cnp, vpp);
+ if (error == 0) {
+
+ /*
+ * Doesn't quite work.
+ */
+
+#if 0
+ if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME)
+ && (cnp->cn_flags & ISLASTCN)) {
+ error = EJUSTRETURN;
+ goto done;
+ }
+#endif
+
+ msg.header.opcode = NNPFS_MSG_GETNODE;
+ if (cnp->cn_cred != NOCRED) {
+ msg.cred.uid = cnp->cn_cred->cr_uid;
+ msg.cred.pag = nnpfs_get_pag(cnp->cn_cred);
+ } else {
+ msg.cred.uid = 0;
+ msg.cred.pag = NNPFS_ANONYMOUSID;
+ }
+ msg.parent_handle = d->handle;
+ memcpy(msg.name, cnp->cn_nameptr, cnp->cn_namelen);
+ msg.name[cnp->cn_namelen] = '\0';
+ error = nnpfs_message_rpc(nnpfsp->fd, &msg.header,
+ sizeof(msg), proc);
+ if (error == 0)
+ error = ((struct nnpfs_message_wakeup *) & msg)->error;
+ if(error == ENOENT && cnp->cn_nameiop != CREATE) {
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_lookup: neg cache %lx (%s, %ld)\n",
+ (unsigned long)dvp,
+ cnp->cn_nameptr, cnp->cn_namelen));
+ nnpfs_dnlc_enter (dvp, cnp, NULL);
+ }
+ } else if (error == -1) {
+ error = 0;
+ goto done;
+ }
+ } while (error == 0);
+
+done:
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_lookup_common: return error = %d\n", error));
+ return error;
+}
+
+int
+nnpfs_create_common(struct vnode *dvp,
+ const char *name,
+ struct vattr *vap,
+ struct ucred *cred,
+ d_thread_t *p)
+{
+ struct nnpfs *nnpfsp = NNPFS_FROM_VNODE(dvp);
+ struct nnpfs_node *xn = VNODE_TO_XNODE(dvp);
+ int error = 0;
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_create: (%lx, %s)\n",
+ (unsigned long)dvp, name));
+ {
+ struct nnpfs_message_create msg;
+
+ msg.header.opcode = NNPFS_MSG_CREATE;
+ msg.parent_handle = xn->handle;
+ if (strlcpy(msg.name, name, sizeof(msg.name)) >= NNPFS_MAX_NAME)
+ return ENAMETOOLONG;
+ vattr2nnpfs_attr(vap, &msg.attr);
+
+ msg.mode = 0; /* XXX - mode */
+ if (cred != NOCRED) {
+ msg.cred.uid = cred->cr_uid;
+ msg.cred.pag = nnpfs_get_pag(cred);
+ } else {
+ msg.cred.uid = 0;
+ msg.cred.pag = NNPFS_ANONYMOUSID;
+ }
+
+
+ error = nnpfs_message_rpc(nnpfsp->fd, &msg.header, sizeof(msg), p);
+
+ if (error == 0)
+ error = ((struct nnpfs_message_wakeup *) & msg)->error;
+ }
+
+#if 0
+ if (error == EEXIST)
+ error = 0;
+#endif
+
+ return error;
+}
+
+int
+nnpfs_remove_common(struct vnode *dvp,
+ struct vnode *vp,
+ const char *name,
+ struct ucred *cred,
+ d_thread_t *p)
+{
+ struct nnpfs *nnpfsp = NNPFS_FROM_VNODE(dvp);
+ struct nnpfs_node *xn = VNODE_TO_XNODE(dvp);
+ struct nnpfs_message_remove msg;
+ int error;
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_remove: %s\n", name));
+
+ msg.header.opcode = NNPFS_MSG_REMOVE;
+ msg.parent_handle = xn->handle;
+ msg.cred.uid = cred->cr_uid;
+ msg.cred.pag = nnpfs_get_pag(cred);
+
+ if (strlcpy(msg.name, name, sizeof(msg.name)) >= NNPFS_MAX_NAME)
+ error = ENAMETOOLONG;
+ else
+ error = nnpfs_message_rpc(nnpfsp->fd, &msg.header, sizeof(msg), p);
+ if (error == 0)
+ error = ((struct nnpfs_message_wakeup *) &msg)->error;
+
+ if (error == 0)
+ nnpfs_dnlc_purge (vp);
+
+ return error;
+}
+
+int
+nnpfs_rename_common(struct vnode *fdvp,
+ struct vnode *fvp,
+ const char *fname,
+ struct vnode *tdvp,
+ struct vnode *tvp,
+ const char *tname,
+ struct ucred *cred,
+ d_thread_t *p)
+{
+ struct nnpfs *nnpfsp = NNPFS_FROM_VNODE(fdvp);
+ int error;
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_rename: %s %s\n", fname, tname));
+
+ if ((fvp->v_mount != tdvp->v_mount)
+ || (tvp && (fvp->v_mount != tvp->v_mount))) {
+ return EXDEV;
+ }
+
+ {
+ struct nnpfs_message_rename msg;
+
+ msg.header.opcode = NNPFS_MSG_RENAME;
+ msg.old_parent_handle = VNODE_TO_XNODE(fdvp)->handle;
+ if (strlcpy(msg.old_name, fname, sizeof(msg.old_name)) >= NNPFS_MAX_NAME)
+ return ENAMETOOLONG;
+ msg.new_parent_handle = VNODE_TO_XNODE(tdvp)->handle;
+ if (strlcpy(msg.new_name, tname, sizeof(msg.new_name)) >= NNPFS_MAX_NAME)
+ return ENAMETOOLONG;
+ msg.cred.uid = cred->cr_uid;
+ msg.cred.pag = nnpfs_get_pag(cred);
+ error = nnpfs_message_rpc(nnpfsp->fd, &msg.header, sizeof(msg), p);
+ if (error == 0)
+ error = ((struct nnpfs_message_wakeup *) &msg)->error;
+
+ }
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_rename: error = %d\n", error));
+
+ return error;
+}
+
+int
+nnpfs_mkdir_common(struct vnode *dvp,
+ const char *name,
+ struct vattr *vap,
+ struct ucred *cred,
+ d_thread_t *p)
+{
+ struct nnpfs *nnpfsp = NNPFS_FROM_VNODE(dvp);
+ struct nnpfs_node *xn = VNODE_TO_XNODE(dvp);
+ int error = 0;
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_mkdir: %s\n", name));
+ {
+ struct nnpfs_message_mkdir msg;
+
+ msg.header.opcode = NNPFS_MSG_MKDIR;
+ msg.parent_handle = xn->handle;
+ if (strlcpy(msg.name, name, sizeof(msg.name)) >= NNPFS_MAX_NAME)
+ return ENAMETOOLONG;
+ vattr2nnpfs_attr(vap, &msg.attr);
+ if (cred != NOCRED) {
+ msg.cred.uid = cred->cr_uid;
+ msg.cred.pag = nnpfs_get_pag(cred);
+ } else {
+ msg.cred.uid = 0;
+ msg.cred.pag = NNPFS_ANONYMOUSID;
+ }
+ error = nnpfs_message_rpc(nnpfsp->fd, &msg.header, sizeof(msg), p);
+ if (error == 0)
+ error = ((struct nnpfs_message_wakeup *) & msg)->error;
+ }
+
+ return error;
+}
+
+int
+nnpfs_rmdir_common(struct vnode *dvp,
+ struct vnode *vp,
+ const char *name,
+ struct ucred *cred,
+ d_thread_t *p)
+{
+ struct nnpfs *nnpfsp = NNPFS_FROM_VNODE(dvp);
+ struct nnpfs_node *xn = VNODE_TO_XNODE(dvp);
+ struct nnpfs_message_rmdir msg;
+ int error;
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_rmdir: %s\n", name));
+
+ msg.header.opcode = NNPFS_MSG_RMDIR;
+ msg.parent_handle = xn->handle;
+ msg.cred.uid = cred->cr_uid;
+ msg.cred.pag = nnpfs_get_pag(cred);
+ if (strlcpy(msg.name, name, sizeof(msg.name)) >= NNPFS_MAX_NAME)
+ error = ENAMETOOLONG;
+ else
+ error = nnpfs_message_rpc(nnpfsp->fd, &msg.header, sizeof(msg), p);
+ if (error == 0)
+ error = ((struct nnpfs_message_wakeup *) &msg)->error;
+
+ if (error == 0)
+ nnpfs_dnlc_purge (vp);
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_rmdir error: %d\n", error));
+
+ return error;
+}
+
+int
+nnpfs_readdir_common(struct vnode *vp,
+ struct uio *uiop,
+ struct ucred *cred,
+ d_thread_t *p,
+ int *eofflag)
+{
+ int error = 0;
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_readdir\n"));
+
+ if(eofflag)
+ *eofflag = 0;
+#ifdef HAVE_FREEBSD_THREAD
+ error = nnpfs_data_valid(vp, cred, nnpfs_uio_to_thread(uiop), NNPFS_DATA_R,
+ nnpfs_uio_end_length(uiop));
+#else
+ error = nnpfs_data_valid(vp, cred, nnpfs_uio_to_proc(uiop), NNPFS_DATA_R,
+ nnpfs_uio_end_length(uiop));
+#endif
+ if (error == 0) {
+ struct vnode *t = DATA_FROM_VNODE(vp);
+
+#ifdef HAVE_FREEBSD_THREAD
+ nnpfs_vfs_readlock(t, nnpfs_uio_to_thread(uiop));
+#else
+ nnpfs_vfs_readlock(t, nnpfs_uio_to_proc(uiop));
+#endif
+ nnpfs_vop_read(t, uiop, 0, cred, error);
+ if (eofflag) {
+ struct vattr t_attr;
+ int error2;
+
+#ifdef HAVE_FREEBSD_THREAD
+ nnpfs_vop_getattr(t, &t_attr, cred, nnpfs_uio_to_thread(uiop), error2);
+#else
+ nnpfs_vop_getattr(t, &t_attr, cred, nnpfs_uio_to_proc(uiop), error2);
+#endif
+ if (error2 == 0)
+ *eofflag = t_attr.va_size <= uiop->uio_offset;
+ }
+#ifdef HAVE_FREEBSD_THREAD
+ nnpfs_vfs_unlock(t, nnpfs_uio_to_thread(uiop));
+#else
+ nnpfs_vfs_unlock(t, nnpfs_uio_to_proc(uiop));
+#endif
+ }
+ return error;
+}
+
+int
+nnpfs_link_common(struct vnode *dvp,
+ struct vnode *vp,
+ const char *name,
+ struct ucred *cred,
+ d_thread_t *p)
+{
+ struct nnpfs *nnpfsp = NNPFS_FROM_VNODE(dvp);
+ struct nnpfs_node *xn = VNODE_TO_XNODE(dvp);
+ struct nnpfs_node *xn2 = VNODE_TO_XNODE(vp);
+ struct nnpfs_message_link msg;
+ int error = 0;
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_link: %s\n", name));
+
+ msg.header.opcode = NNPFS_MSG_LINK;
+ msg.parent_handle = xn->handle;
+ msg.from_handle = xn2->handle;
+ if (strlcpy(msg.name, name, sizeof(msg.name)) >= NNPFS_MAX_NAME)
+ return ENAMETOOLONG;
+ msg.cred.uid = cred->cr_uid;
+ msg.cred.pag = nnpfs_get_pag(cred);
+
+ error = nnpfs_message_rpc(nnpfsp->fd, &msg.header, sizeof(msg), p);
+ if (error == 0)
+ error = ((struct nnpfs_message_wakeup *) & msg)->error;
+
+ return error;
+}
+
+int
+nnpfs_symlink_common(struct vnode *dvp,
+ struct vnode **vpp,
+ nnpfs_componentname *cnp,
+ struct vattr *vap,
+ char *target)
+{
+ struct nnpfs *nnpfsp = NNPFS_FROM_VNODE(dvp);
+ struct nnpfs_node *xn = VNODE_TO_XNODE(dvp);
+#ifdef HAVE_FREEBSD_THREAD
+ d_thread_t *proc = nnpfs_cnp_to_thread(cnp);
+ struct ucred *cred = nnpfs_thread_to_cred(proc);
+#else
+ d_thread_t *proc = nnpfs_cnp_to_proc(cnp);
+ struct ucred *cred = nnpfs_proc_to_cred(proc);
+#endif
+ struct nnpfs_message_symlink *msg = NULL;
+ const char *name = cnp->cn_nameptr;
+ int error = 0;
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_symlink: %s\n", name));
+
+ msg = malloc(sizeof(*msg), M_TEMP, M_WAITOK | M_ZERO);
+ if (msg == NULL) {
+ error = ENOMEM;
+ goto done;
+ }
+
+ msg->header.opcode = NNPFS_MSG_SYMLINK;
+ msg->parent_handle = xn->handle;
+ vattr2nnpfs_attr(vap, &msg->attr);
+ msg->cred.uid = cred->cr_uid;
+ msg->cred.pag = nnpfs_get_pag(cred);
+ if (strlcpy (msg->contents, target, sizeof(msg->contents)) >= NNPFS_MAX_SYMLINK_CONTENT) {
+ error = ENAMETOOLONG;
+ goto done;
+ }
+ if (strlcpy(msg->name, name, sizeof(msg->name)) >= NNPFS_MAX_NAME) {
+ error = ENAMETOOLONG;
+ goto done;
+ }
+ error = nnpfs_message_rpc(nnpfsp->fd, &msg->header, sizeof(*msg), proc);
+ if (error == 0)
+ error = ((struct nnpfs_message_wakeup *) msg)->error;
+
+ done:
+ free(msg, M_TEMP);
+ return error;
+}
+
+int
+nnpfs_readlink_common(struct vnode *vp, struct uio *uiop, struct ucred *cred)
+{
+ int error = 0;
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_readlink\n"));
+
+#ifdef HAVE_FREEBSD_THREAD
+ error = nnpfs_data_valid(vp, cred, nnpfs_uio_to_thread(uiop), NNPFS_DATA_R,
+ nnpfs_uio_end_length(uiop));
+#else
+ error = nnpfs_data_valid(vp, cred, nnpfs_uio_to_proc(uiop), NNPFS_DATA_R,
+ nnpfs_uio_end_length(uiop));
+#endif
+ if (error == 0) {
+ struct vnode *t = DATA_FROM_VNODE(vp);
+
+#ifdef HAVE_FREEBSD_THREAD
+ nnpfs_vfs_readlock(t, nnpfs_uio_to_thread(uiop));
+ nnpfs_vop_read(t, uiop, 0, cred, error);
+ nnpfs_vfs_unlock(t, nnpfs_uio_to_thread(uiop));
+#else
+ nnpfs_vfs_readlock(t, nnpfs_uio_to_proc(uiop));
+ nnpfs_vop_read(t, uiop, 0, cred, error);
+ nnpfs_vfs_unlock(t, nnpfs_uio_to_proc(uiop));
+#endif
+ }
+ return error;
+}
+
+int
+nnpfs_inactive_common(struct vnode *vp, d_thread_t *p)
+{
+ int error;
+ struct nnpfs_node *xn = VNODE_TO_XNODE(vp);
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_inactive, %lx\n",
+ (unsigned long)vp));
+
+ /*
+ * This seems rather bogus, but sometimes we get an already
+ * cleaned node to be made inactive. Just ignoring it seems safe.
+ */
+
+ if (xn == NULL) {
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_inactive: clean node\n"));
+ return 0;
+ }
+
+ /* xn->wr_cred not set -> NOCRED */
+
+ if (vp->v_type == VREG)
+ nnpfs_pushdirty(vp, xn->wr_cred, p);
+
+ error = nnpfs_fsync_common(vp, xn->wr_cred, /* XXX */ 0, p);
+ if (error) {
+ printf ("nnpfs_inactive: failed writing back data: %d\n", error);
+ xn->flags &= ~NNPFS_DATA_DIRTY;
+ }
+
+ /* If this node is no longer valid, recycle immediately. */
+ if (!NNPFS_TOKEN_GOT(xn, NNPFS_ATTR_R | NNPFS_ATTR_W)
+ || (xn->flags & NNPFS_STALE) == NNPFS_STALE)
+ {
+#ifndef __osf__
+ nnpfs_vfs_unlock(vp, p);
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_inactive: vrecycle\n"));
+ vrecycle(vp, p);
+#else /* __osf__ */
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_inactive: vp = %lx vp->v_usecount= %d\n",
+ (unsigned long)vp, vp?vp->v_usecount:0));
+#endif /* __osf__ */
+ } else {
+#ifndef __osf__
+ nnpfs_vfs_unlock(vp, p);
+#endif
+ xn->flags &= ~NNPFS_STALE;
+ }
+
+ NNPFSDEB(XDEBVNOPS, ("return: nnpfs_inactive\n"));
+
+ return 0;
+}
+
+int
+nnpfs_reclaim_common(struct vnode *vp)
+{
+ struct nnpfs_message_inactivenode msg;
+ struct nnpfs *nnpfsp = NNPFS_FROM_VNODE(vp);
+ struct nnpfs_node *xn = VNODE_TO_XNODE(vp);
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_reclaim: %lx\n",
+ (unsigned long)vp));
+
+ NNPFS_TOKEN_CLEAR(xn,
+ ~0,
+ NNPFS_OPEN_MASK | NNPFS_ATTR_MASK |
+ NNPFS_DATA_MASK | NNPFS_LOCK_MASK);
+ /* Release, data if we still have it. */
+ if (DATA_FROM_XNODE(xn) != 0) {
+ vrele(DATA_FROM_XNODE(xn));
+ DATA_FROM_XNODE(xn) = 0;
+ }
+
+ nnpfs_remove_node(&nnpfsp->nodehead, xn);
+
+ msg.header.opcode = NNPFS_MSG_INACTIVENODE;
+ msg.handle = xn->handle;
+ msg.flag = NNPFS_NOREFS | NNPFS_DELETE;
+ nnpfs_message_send(nnpfsp->fd, &msg.header, sizeof(msg));
+
+ nnpfs_dnlc_purge(vp);
+ free_nnpfs_node(xn);
+ return 0;
+}
+
+/*
+ *
+ */
+
+#if 0
+
+int
+nnpfs_advlock_common(struct vnode *dvp,
+ int locktype,
+ unsigned long lockid, /* XXX this good ? */
+ struct ucred *cred)
+{
+ struct nnpfs *nnpfsp = NNPFS_FROM_VNODE(dvp);
+ struct nnpfs_node *xn = VNODE_TO_XNODE(dvp);
+ int error = 0;
+
+ NNPFSDEB(XDEBVNOPS, ("nnpfs_advlock\n"));
+ {
+ struct nnpfs_message_advlock msg;
+
+ msg.header.opcode = NNPFS_MSG_ADVLOCK;
+ msg.handle = xn->handle;
+ msg.locktype = locktype;
+ msg.lockid = lockid;
+
+ if (cred != NOCRED) {
+ msg.cred.uid = cred->cr_uid;
+ msg.cred.pag = nnpfs_get_pag(cred);
+ } else {
+ msg.cred.uid = 0;
+ msg.cred.pag = NNPFS_ANONYMOUSID;
+ }
+ error = nnpfs_message_rpc(nnpfsp->fd, &msg.header, sizeof(msg), p);
+ if (error == 0)
+ error = ((struct nnpfs_message_wakeup *) & msg)->error;
+ }
+
+ if (error == 0) {
+
+ /* sleep until woken */
+
+ } else {
+
+ /* die */
+ }
+
+ return error;
+}
+
+#endif
+
+/*
+ *
+ */
+
+void
+nnpfs_printnode_common (struct vnode *vp)
+{
+ struct nnpfs_node *xn = VNODE_TO_XNODE(vp);
+
+ printf ("xnode: fid: %d.%d.%d.%d\n",
+ xn->handle.a, xn->handle.b, xn->handle.c, xn->handle.d);
+ printf ("\tattr: %svalid\n",
+ NNPFS_TOKEN_GOT(xn, NNPFS_ATTR_VALID) ? "": "in");
+ printf ("\tdata: %svalid\n",
+ NNPFS_TOKEN_GOT(xn, NNPFS_DATA_VALID) ? "": "in");
+ printf ("\tflags: 0x%x\n", xn->flags);
+ printf ("\toffset: %d\n", xn->offset);
+}
diff --git a/sys/nnpfs/nnpfs_vnodeops.h b/sys/nnpfs/nnpfs_vnodeops.h
new file mode 100644
index 00000000000..552734db621
--- /dev/null
+++ b/sys/nnpfs/nnpfs_vnodeops.h
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 1995 - 2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $arla: nnpfs_vnodeops.h,v 1.25 2002/09/07 10:46:12 lha Exp $ */
+
+#ifndef _nnpfs_vnodeops_h
+#define _nnpfs_vnodeops_h
+
+/*
+ * nnpfs_vfs_readlock
+ * nnpfs_vfs_writelock
+ * nnpfs_vfs_unlock
+ */
+
+#ifdef __osf__ /* XXX - what about VN_LOCK? */
+
+#define nnpfs_vfs_readlock(vp, proc) VREF((vp))
+#define nnpfs_vfs_writelock(vp, proc) VREF((vp))
+#define nnpfs_vfs_unlock(vp, proc) vrele((vp))
+
+/* XXX - should this do anything? */
+
+#define nnpfs_vfs_vn_lock(vp, flags, proc) (0)
+
+#elif defined(HAVE_TWO_ARGUMENT_VOP_LOCK)
+
+#define nnpfs_vfs_readlock(vp, proc) vn_lock((vp), LK_SHARED | LK_RETRY)
+#define nnpfs_vfs_writelock(vp, proc) vn_lock((vp), LK_EXCLUSIVE | LK_RETRY)
+#define nnpfs_vfs_unlock(vp, proc) VOP_UNLOCK((vp), 0)
+#define nnpfs_vfs_vn_lock(vp, flags, proc) vn_lock((vp), (flags))
+
+#elif defined(HAVE_THREE_ARGUMENT_VOP_LOCK)
+
+#define nnpfs_vfs_readlock(vp, proc) vn_lock((vp), LK_SHARED | LK_RETRY, (proc))
+#define nnpfs_vfs_writelock(vp, proc) vn_lock((vp), LK_EXCLUSIVE | LK_RETRY, (proc))
+#define nnpfs_vfs_unlock(vp, proc) VOP_UNLOCK((vp), 0, (proc))
+#define nnpfs_vfs_vn_lock(vp, flags, proc) vn_lock((vp), (flags), (proc))
+
+#elif defined(HAVE_ONE_ARGUMENT_VOP_LOCK)
+
+#define nnpfs_vfs_readlock(vp, proc) VOP_LOCK((vp))
+#define nnpfs_vfs_writelock(vp, proc) VOP_LOCK((vp))
+#define nnpfs_vfs_unlock(vp, proc) VOP_UNLOCK((vp))
+
+/* XXX - should this do anything? */
+
+#define nnpfs_vfs_vn_lock(vp, flags, proc) (0)
+
+#else
+
+#error what kind of VOP_LOCK?
+
+#endif
+
+int
+nnpfs_open_valid(struct vnode *vp, struct ucred *cred, d_thread_t *p,
+ u_int tok);
+
+int
+nnpfs_attr_valid(struct vnode *vp, struct ucred *cred, d_thread_t *p,
+ u_int tok);
+
+int
+nnpfs_fetch_rights(struct vnode *vp, struct ucred *cred, d_thread_t *p);
+
+int
+nnpfs_data_valid(struct vnode *vp, struct ucred *cred, d_thread_t *p,
+ u_int tok, uint32_t offset);
+
+int
+nnpfs_open_common(struct vnode *vp,
+ int mode,
+ struct ucred *cred,
+ d_thread_t *p);
+
+int
+nnpfs_fsync_common(struct vnode *vp, struct ucred *cred,
+ int waitfor, d_thread_t *proc);
+
+int
+nnpfs_close_common(struct vnode *vp, int fflag,
+ d_thread_t *proc, struct ucred *cred);
+
+int
+nnpfs_read_common(struct vnode *vp, struct uio *uio, int ioflag,
+ struct ucred *cred);
+
+int
+nnpfs_write_common(struct vnode *vp, struct uio *uiop, int ioflag,
+ struct ucred *cred);
+
+int
+nnpfs_getattr_common(struct vnode *vp, struct vattr *vap,
+ struct ucred *cred, d_thread_t *p);
+
+int
+nnpfs_setattr_common(struct vnode *vp, struct vattr *vap,
+ struct ucred *cred, d_thread_t *p);
+
+int
+nnpfs_access_common(struct vnode *vp, int mode,
+ struct ucred *cred, d_thread_t *p);
+
+int
+nnpfs_lookup_common(struct vnode *dvp,
+ nnpfs_componentname *cnp,
+ struct vnode **vpp);
+
+int
+nnpfs_create_common(struct vnode *dvp,
+ const char *name,
+ struct vattr *vap,
+ struct ucred *cred,
+ d_thread_t *p);
+
+int
+nnpfs_remove_common(struct vnode *dvp,
+ struct vnode *vp,
+ const char *name,
+ struct ucred *cred,
+ d_thread_t *p);
+
+int
+nnpfs_rename_common(struct vnode *fdvp,
+ struct vnode *fvp,
+ const char *fname,
+ struct vnode *tdvp,
+ struct vnode *tvp,
+ const char *tname,
+ struct ucred *cred,
+ d_thread_t *p);
+
+int
+nnpfs_mkdir_common(struct vnode *dvp,
+ const char *name,
+ struct vattr *vap,
+ struct ucred *cred,
+ d_thread_t *p);
+
+int
+nnpfs_rmdir_common(struct vnode *dvp,
+ struct vnode *vp,
+ const char *name,
+ struct ucred *cred,
+ d_thread_t *p);
+
+int
+nnpfs_readdir_common(struct vnode *vp,
+ struct uio *uiop,
+ struct ucred *cred,
+ d_thread_t *p,
+ int *eofflag);
+
+int
+nnpfs_link_common(struct vnode *dvp,
+ struct vnode *vp,
+ const char *name,
+ struct ucred *cred,
+ d_thread_t *p);
+
+int
+nnpfs_symlink_common(struct vnode *dvp,
+ struct vnode **vpp,
+ nnpfs_componentname *cnp,
+ struct vattr *vap,
+ char *target);
+
+int
+nnpfs_readlink_common(struct vnode *vp, struct uio *uiop, struct ucred *cred);
+
+int
+nnpfs_inactive_common(struct vnode *vp, d_thread_t *p);
+
+int
+nnpfs_reclaim_common(struct vnode *vp);
+
+int
+nnpfs_eopnotsupp (struct vop_generic_args *ap);
+
+int
+nnpfs_returnzero (struct vop_generic_args *ap);
+
+void
+nnpfs_printnode_common (struct vnode *vp);
+
+size_t
+nnpfs_uio_end_length (struct uio *uio);
+
+
+#endif /* _nnpfs_vnodeops_h */
diff --git a/sys/nnpfs/nnpfs_vopdefs.h b/sys/nnpfs/nnpfs_vopdefs.h
new file mode 100644
index 00000000000..0082f332faf
--- /dev/null
+++ b/sys/nnpfs/nnpfs_vopdefs.h
@@ -0,0 +1,72 @@
+#define HAVE_VOP_ISLOCKED 1
+NNPFS_VOP_DEF(islocked);
+#define HAVE_VOP_LOOKUP 1
+NNPFS_VOP_DEF(lookup);
+#define HAVE_VOP_CREATE 1
+NNPFS_VOP_DEF(create);
+#define HAVE_VOP_MKNOD 1
+NNPFS_VOP_DEF(mknod);
+#define HAVE_VOP_OPEN 1
+NNPFS_VOP_DEF(open);
+#define HAVE_VOP_CLOSE 1
+NNPFS_VOP_DEF(close);
+#define HAVE_VOP_ACCESS 1
+NNPFS_VOP_DEF(access);
+#define HAVE_VOP_GETATTR 1
+NNPFS_VOP_DEF(getattr);
+#define HAVE_VOP_SETATTR 1
+NNPFS_VOP_DEF(setattr);
+#define HAVE_VOP_READ 1
+NNPFS_VOP_DEF(read);
+#define HAVE_VOP_WRITE 1
+NNPFS_VOP_DEF(write);
+#define HAVE_VOP_IOCTL 1
+NNPFS_VOP_DEF(ioctl);
+#define HAVE_VOP_POLL 1
+NNPFS_VOP_DEF(poll);
+#define HAVE_VOP_KQFILTER 1
+NNPFS_VOP_DEF(kqfilter);
+#define HAVE_VOP_REVOKE 1
+NNPFS_VOP_DEF(revoke);
+#define HAVE_VOP_FSYNC 1
+NNPFS_VOP_DEF(fsync);
+#define HAVE_VOP_REMOVE 1
+NNPFS_VOP_DEF(remove);
+#define HAVE_VOP_LINK 1
+NNPFS_VOP_DEF(link);
+#define HAVE_VOP_RENAME 1
+NNPFS_VOP_DEF(rename);
+#define HAVE_VOP_MKDIR 1
+NNPFS_VOP_DEF(mkdir);
+#define HAVE_VOP_RMDIR 1
+NNPFS_VOP_DEF(rmdir);
+#define HAVE_VOP_SYMLINK 1
+NNPFS_VOP_DEF(symlink);
+#define HAVE_VOP_READDIR 1
+NNPFS_VOP_DEF(readdir);
+#define HAVE_VOP_READLINK 1
+NNPFS_VOP_DEF(readlink);
+#define HAVE_VOP_ABORTOP 1
+NNPFS_VOP_DEF(abortop);
+#define HAVE_VOP_INACTIVE 1
+NNPFS_VOP_DEF(inactive);
+#define HAVE_VOP_RECLAIM 1
+NNPFS_VOP_DEF(reclaim);
+#define HAVE_VOP_LOCK 1
+NNPFS_VOP_DEF(lock);
+#define HAVE_VOP_UNLOCK 1
+NNPFS_VOP_DEF(unlock);
+#define HAVE_VOP_BMAP 1
+NNPFS_VOP_DEF(bmap);
+#define HAVE_VOP_PRINT 1
+NNPFS_VOP_DEF(print);
+#define HAVE_VOP_PATHCONF 1
+NNPFS_VOP_DEF(pathconf);
+#define HAVE_VOP_ADVLOCK 1
+NNPFS_VOP_DEF(advlock);
+#define HAVE_VOP_REALLOCBLKS 1
+NNPFS_VOP_DEF(reallocblks);
+#define HAVE_VOP_STRATEGY 1
+NNPFS_VOP_DEF(strategy);
+#define HAVE_VOP_BWRITE 1
+NNPFS_VOP_DEF(bwrite);