diff options
author | Janne Johansson <jj@cvs.openbsd.org> | 2009-06-03 14:45:57 +0000 |
---|---|---|
committer | Janne Johansson <jj@cvs.openbsd.org> | 2009-06-03 14:45:57 +0000 |
commit | ea9bbf428f51194a52c45ac274c35dba174a741c (patch) | |
tree | 301aa894fd92a097d769b8cac575c8a0fce07329 /sys/nnpfs | |
parent | 0c52879fa54117b2bd312fe5fff17f310dbdb7eb (diff) |
Arla client rename from xfs to nnpfs for later upgrades. Tested on various arches. ok todd@ beck@
Diffstat (limited to 'sys/nnpfs')
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); |