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/nnpfs_node-bsd.c | |
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/nnpfs_node-bsd.c')
-rw-r--r-- | sys/nnpfs/nnpfs_node-bsd.c | 801 |
1 files changed, 801 insertions, 0 deletions
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; +} |