b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * This file and its contents are supplied under the terms of the
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Common Development and Distribution License ("CDDL"), version 1.0.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * You may only use this file in accordance with the terms of version
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * 1.0 of the CDDL.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross *
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * A full copy of the text of the CDDL should have accompanied this
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * source. A copy of the CDDL is also available via the Internet at
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * http://www.illumos.org/license/CDDL.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/types.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/param.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/systm.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/cmn_err.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/cred.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/debug.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/errno.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/t_lock.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/user.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/uio.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/file.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/pathname.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/sysmacros.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/vfs.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/vnode.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/avl.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/stat.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <sys/mode.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <fcntl.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include <unistd.h>
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#include "vncache.h"
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rosskmem_cache_t *vn_cache;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * You can dump this AVL tree with mdb, i.e.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * vncache_avl ::walk avl |::print -s1 vnode_t
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossavl_tree_t vncache_avl;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rosskmutex_t vncache_lock;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Vnode cache.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/* ARGSUSED */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossstatic int
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvn_cache_constructor(void *buf, void *cdrarg, int kmflags)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross struct vnode *vp;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vp = buf;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross bzero(vp, sizeof (*vp));
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross mutex_init(&vp->v_lock, NULL, MUTEX_DEFAULT, NULL);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vp->v_fd = -1;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (0);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/* ARGSUSED */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossstatic void
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvn_cache_destructor(void *buf, void *cdrarg)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross struct vnode *vp;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vp = buf;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross mutex_destroy(&vp->v_lock);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Used by file systems when fs-specific nodes (e.g., ufs inodes) are
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * cached by the file system and vnodes remain associated.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvoid
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvn_recycle(vnode_t *vp)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross ASSERT(vp->v_fd == -1);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vp->v_rdcnt = 0;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vp->v_wrcnt = 0;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (vp->v_path) {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross strfree(vp->v_path);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vp->v_path = NULL;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross }
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Used to reset the vnode fields including those that are directly accessible
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * as well as those which require an accessor function.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross *
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Does not initialize:
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * synchronization objects: v_lock, v_vsd_lock, v_nbllock, v_cv
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * v_data (since FS-nodes and vnodes point to each other and should
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * be updated simultaneously)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * v_op (in case someone needs to make a VOP call on this object)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvoid
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvn_reinit(vnode_t *vp)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vp->v_count = 1;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vp->v_vfsp = NULL;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vp->v_stream = NULL;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vp->v_flag = 0;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vp->v_type = VNON;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vp->v_rdev = NODEV;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vn_recycle(vp);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvnode_t *
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvn_alloc(int kmflag)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vnode_t *vp;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vp = kmem_cache_alloc(vn_cache, kmflag);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (vp != NULL) {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vn_reinit(vp);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross }
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (vp);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvoid
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvn_free(vnode_t *vp)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Some file systems call vn_free() with v_count of zero,
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * some with v_count of 1. In any case, the value should
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * never be anything else.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross ASSERT((vp->v_count == 0) || (vp->v_count == 1));
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (vp->v_path != NULL) {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross strfree(vp->v_path);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vp->v_path = NULL;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross }
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross ASSERT(vp->v_fd != -1);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross (void) close(vp->v_fd);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vp->v_fd = -1;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross kmem_cache_free(vn_cache, vp);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossint
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvncache_cmp(const void *v1, const void *v2)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross const vnode_t *vp1, *vp2;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vp1 = v1;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vp2 = v2;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (vp1->v_st_dev < vp2->v_st_dev)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (-1);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (vp1->v_st_dev > vp2->v_st_dev)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (+1);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (vp1->v_st_ino < vp2->v_st_ino)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (-1);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (vp1->v_st_ino > vp2->v_st_ino)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (+1);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (0);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvnode_t *
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvncache_lookup(struct stat *st)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vnode_t tmp_vn;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vnode_t *vp;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross tmp_vn.v_st_dev = st->st_dev;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross tmp_vn.v_st_ino = st->st_ino;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross mutex_enter(&vncache_lock);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vp = avl_find(&vncache_avl, &tmp_vn, NULL);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (vp != NULL)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vn_hold(vp);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross mutex_exit(&vncache_lock);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (vp);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvnode_t *
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvncache_enter(struct stat *st, vnode_t *dvp, char *name, int fd)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vnode_t *old_vp;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vnode_t *new_vp;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vfs_t *vfs;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross char *vpath;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross avl_index_t where;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross int len;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Fill in v_path
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Note: fsop_root() calls with dvp=NULL
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross len = strlen(name) + 1;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (dvp == NULL) {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vpath = kmem_alloc(len, KM_SLEEP);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross (void) strlcpy(vpath, name, len);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vfs = rootvfs;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross } else {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /* add to length for parent path + "/" */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross len += (strlen(dvp->v_path) + 1);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vpath = kmem_alloc(len, KM_SLEEP);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross (void) snprintf(vpath, len, "%s/%s", dvp->v_path, name);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vfs = dvp->v_vfsp;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross }
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross new_vp = vn_alloc(KM_SLEEP);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross new_vp->v_path = vpath;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross new_vp->v_fd = fd;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross new_vp->v_st_dev = st->st_dev;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross new_vp->v_st_ino = st->st_ino;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross new_vp->v_vfsp = vfs;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross new_vp->v_type = IFTOVT(st->st_mode);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross mutex_enter(&vncache_lock);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross old_vp = avl_find(&vncache_avl, new_vp, &where);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (old_vp != NULL)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vn_hold(old_vp);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross else
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross avl_insert(&vncache_avl, new_vp, where);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross mutex_exit(&vncache_lock);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /* If we lost the race, free new_vp */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (old_vp != NULL) {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vn_free(new_vp);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (old_vp);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross }
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (new_vp);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Called after a successful rename to update v_path
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvoid
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvncache_renamed(vnode_t *vp, vnode_t *to_dvp, char *to_name)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross char *vpath;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross char *ovpath;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross int len;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross len = strlen(to_name) + 1;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /* add to length for parent path + "/" */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross len += (strlen(to_dvp->v_path) + 1);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vpath = kmem_alloc(len, KM_SLEEP);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross (void) snprintf(vpath, len, "%s/%s", to_dvp->v_path, to_name);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross mutex_enter(&vncache_lock);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross ovpath = vp->v_path;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vp->v_path = vpath;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross mutex_exit(&vncache_lock);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross strfree(ovpath);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross/*
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Last reference to this vnode is (possibly) going away.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * This is normally called by vn_rele() when v_count==1.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Note that due to lock order concerns, we have to take
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * the vncache_lock (for the avl tree) and then recheck
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * v_count, which might have gained a ref during the time
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * we did not hold vp->v_lock.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvoid
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvncache_inactive(vnode_t *vp)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross uint_t count;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross mutex_enter(&vncache_lock);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross mutex_enter(&vp->v_lock);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if ((count = vp->v_count) <= 1) {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross /* This is (still) the last ref. */
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross avl_remove(&vncache_avl, vp);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross }
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross mutex_exit(&vp->v_lock);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross mutex_exit(&vncache_lock);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross if (count <= 1) {
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vn_free(vp);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross }
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#pragma init(vncache_init)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossint
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvncache_init(void)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vn_cache = kmem_cache_create("vn_cache", sizeof (struct vnode),
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross VNODE_ALIGN, vn_cache_constructor, vn_cache_destructor, NULL, NULL,
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross NULL, 0);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross avl_create(&vncache_avl,
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross vncache_cmp,
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross sizeof (vnode_t),
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross offsetof(vnode_t, v_avl_node));
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross mutex_init(&vncache_lock, NULL, MUTEX_DEFAULT, NULL);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross return (0);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#pragma fini(vncache_fini)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvoid
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Rossvncache_fini(void)
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross{
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross mutex_destroy(&vncache_lock);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross avl_destroy(&vncache_avl);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross kmem_cache_destroy(vn_cache);
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross}