17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5bbf2a467SNagakiran Rajashekar * Common Development and Distribution License (the "License"). 6bbf2a467SNagakiran Rajashekar * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22be6d98b1SNagakiran Rajashekar * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #include <sys/systm.h> 287c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #include <nfs/nfs.h> 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #include <nfs/nfs4.h> 337c478bd9Sstevel@tonic-gate #include <nfs/rnode4.h> 347c478bd9Sstevel@tonic-gate #include <nfs/nfs4_clnt.h> 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate static struct kmem_cache *svnode_cache; 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate struct sv_stats 397c478bd9Sstevel@tonic-gate { 407c478bd9Sstevel@tonic-gate int sv_activate; 417c478bd9Sstevel@tonic-gate int sv_find; 427c478bd9Sstevel@tonic-gate int sv_match; 437c478bd9Sstevel@tonic-gate int sv_inactive; 447c478bd9Sstevel@tonic-gate int sv_exchange; 457c478bd9Sstevel@tonic-gate } sv_stats; 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate static int sv_match(nfs4_fname_t *, nfs4_sharedfh_t *, svnode_t *); 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate /* 507c478bd9Sstevel@tonic-gate * Map a vnode back to the shadow which points to it. This is 517c478bd9Sstevel@tonic-gate * hard now that the vnode is not embedded in the shadow vnode. 527c478bd9Sstevel@tonic-gate */ 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate svnode_t * 567c478bd9Sstevel@tonic-gate vtosv(vnode_t *vp) 577c478bd9Sstevel@tonic-gate { 587c478bd9Sstevel@tonic-gate rnode4_t *rp = VTOR4(vp); 597c478bd9Sstevel@tonic-gate svnode_t *svp, *svp_found = NULL; 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate /* Check to see if it's the master shadow vnode first. */ 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate if (RTOV4(rp) == vp) 647c478bd9Sstevel@tonic-gate return (&rp->r_svnode); 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate mutex_enter(&rp->r_svlock); 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate for (svp = rp->r_svnode.sv_forw; svp != &rp->r_svnode; 697c478bd9Sstevel@tonic-gate svp = svp->sv_forw) 707c478bd9Sstevel@tonic-gate if (svp->sv_r_vnode == vp) { 717c478bd9Sstevel@tonic-gate svp_found = svp; 727c478bd9Sstevel@tonic-gate break; 737c478bd9Sstevel@tonic-gate } 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate mutex_exit(&rp->r_svlock); 767c478bd9Sstevel@tonic-gate ASSERT(svp_found != NULL); 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate return (svp_found); 797c478bd9Sstevel@tonic-gate } 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate /* 827c478bd9Sstevel@tonic-gate * sv_activate - find and activate the shadow vnode for the given 837c478bd9Sstevel@tonic-gate * directory file handle and name. May replace *vpp with a held reference 847c478bd9Sstevel@tonic-gate * to a different vnode, in which case the reference to the previous one is 857c478bd9Sstevel@tonic-gate * released. 867c478bd9Sstevel@tonic-gate */ 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate void 897c478bd9Sstevel@tonic-gate sv_activate(vnode_t **vpp, vnode_t *dvp, nfs4_fname_t **namepp, int newnode) 907c478bd9Sstevel@tonic-gate { 917c478bd9Sstevel@tonic-gate svnode_t *svp; 927c478bd9Sstevel@tonic-gate vnode_t *resvp; 93be6d98b1SNagakiran Rajashekar nfs4_fname_t *svpname; 947c478bd9Sstevel@tonic-gate rnode4_t *rp = VTOR4(*vpp); 95bbf2a467SNagakiran Rajashekar svp = VTOSV(*vpp); 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate ASSERT(namepp != NULL); 987c478bd9Sstevel@tonic-gate ASSERT(*namepp != NULL); 997c478bd9Sstevel@tonic-gate ASSERT(dvp != NULL); 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate sv_stats.sv_activate++; 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate ASSERT(RW_LOCK_HELD(&rp->r_hashq->r_lock)); 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate /* 1067c478bd9Sstevel@tonic-gate * If make_rnode made a new rnode (ie. newnode != 0), then 1077c478bd9Sstevel@tonic-gate * the master vnode was (partially) initialized there. If 1087c478bd9Sstevel@tonic-gate * it was not a new rnode, then it returns the master vnode. 1097c478bd9Sstevel@tonic-gate * Call sv_find to find and/or initialize the shadow 1107c478bd9Sstevel@tonic-gate * vnode. 1117c478bd9Sstevel@tonic-gate */ 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate if (newnode) { 1147c478bd9Sstevel@tonic-gate /* 1157c478bd9Sstevel@tonic-gate * Initialize the shadow vnode. 1167c478bd9Sstevel@tonic-gate */ 1177c478bd9Sstevel@tonic-gate svp->sv_forw = svp->sv_back = svp; 1187c478bd9Sstevel@tonic-gate ASSERT(svp->sv_dfh == NULL); 1197c478bd9Sstevel@tonic-gate svp->sv_dfh = VTOR4(dvp)->r_fh; 1207c478bd9Sstevel@tonic-gate sfh4_hold(svp->sv_dfh); 1217c478bd9Sstevel@tonic-gate ASSERT(svp->sv_name == NULL); 1227c478bd9Sstevel@tonic-gate svp->sv_name = *namepp; 1237c478bd9Sstevel@tonic-gate } else if ((*vpp)->v_type == VREG && !((*vpp)->v_flag & VROOT)) { 1247c478bd9Sstevel@tonic-gate resvp = sv_find(*vpp, dvp, namepp); 1257c478bd9Sstevel@tonic-gate ASSERT(resvp->v_type == VREG); 1267c478bd9Sstevel@tonic-gate VN_RELE(*vpp); 1277c478bd9Sstevel@tonic-gate *vpp = resvp; 128*4151f947SPavel Filipensky } else { 129bbf2a467SNagakiran Rajashekar /* 130*4151f947SPavel Filipensky * No shadow vnodes (i.e. hard links) in this branch. 131*4151f947SPavel Filipensky * If sv_activate() is called for an existing rnode 132*4151f947SPavel Filipensky * (newnode isn't set) but with a new name, the sv_name 133*4151f947SPavel Filipensky * needs to be updated and the old sv_name released. 134bbf2a467SNagakiran Rajashekar * 135bbf2a467SNagakiran Rajashekar * fname mismatches can occur due to server side renames, 136bbf2a467SNagakiran Rajashekar * here is a chance to update the fname in case there is 137bbf2a467SNagakiran Rajashekar * a mismatch. Since this is not a newnode we hold r_svlock 138bbf2a467SNagakiran Rajashekar * to protect sv_name. 139bbf2a467SNagakiran Rajashekar */ 140bbf2a467SNagakiran Rajashekar mutex_enter(&rp->r_svlock); 141be6d98b1SNagakiran Rajashekar svpname = svp->sv_name; 142bbf2a467SNagakiran Rajashekar if (svpname != *namepp) { 143bbf2a467SNagakiran Rajashekar /* 144bbf2a467SNagakiran Rajashekar * Call fn_rele() to release the hold for the 145bbf2a467SNagakiran Rajashekar * previous shadow vnode reference. Don't 146bbf2a467SNagakiran Rajashekar * release the hold on the fname pointed to by 147bbf2a467SNagakiran Rajashekar * namepp as we have new reference to it from 148bbf2a467SNagakiran Rajashekar * this shadow vnode. 149bbf2a467SNagakiran Rajashekar */ 150bbf2a467SNagakiran Rajashekar svp->sv_name = *namepp; 151bbf2a467SNagakiran Rajashekar mutex_exit(&rp->r_svlock); 152bbf2a467SNagakiran Rajashekar fn_rele(&svpname); 153bbf2a467SNagakiran Rajashekar } else { 154bbf2a467SNagakiran Rajashekar mutex_exit(&rp->r_svlock); 155bbf2a467SNagakiran Rajashekar fn_rele(namepp); 156bbf2a467SNagakiran Rajashekar } 1577c478bd9Sstevel@tonic-gate } 1587c478bd9Sstevel@tonic-gate } 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate /* 1617c478bd9Sstevel@tonic-gate * sv_find - find the shadow vnode for the desired name and directory 1627c478bd9Sstevel@tonic-gate * file handle. If one does not exist, then create it. Returns the shadow 1637c478bd9Sstevel@tonic-gate * vnode. The caller is responsible for freeing the reference. 1647c478bd9Sstevel@tonic-gate * Consumes the name reference and nulls it out. 1657c478bd9Sstevel@tonic-gate * 1667c478bd9Sstevel@tonic-gate * Side effects: increments the reference count on the master vnode if the 1677c478bd9Sstevel@tonic-gate * shadow vnode had to be created. 1687c478bd9Sstevel@tonic-gate */ 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate vnode_t * 1717c478bd9Sstevel@tonic-gate sv_find(vnode_t *mvp, vnode_t *dvp, nfs4_fname_t **namepp) 1727c478bd9Sstevel@tonic-gate { 1737c478bd9Sstevel@tonic-gate vnode_t *vp; 1747c478bd9Sstevel@tonic-gate rnode4_t *rp = VTOR4(mvp); 1757c478bd9Sstevel@tonic-gate svnode_t *svp; 176bbf2a467SNagakiran Rajashekar svnode_t *master_svp = VTOSV(mvp); 1777c478bd9Sstevel@tonic-gate rnode4_t *drp = VTOR4(dvp); 1787c478bd9Sstevel@tonic-gate nfs4_fname_t *nm; 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate ASSERT(dvp != NULL); 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate sv_stats.sv_find++; 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate ASSERT(namepp != NULL); 1857c478bd9Sstevel@tonic-gate ASSERT(*namepp != NULL); 1867c478bd9Sstevel@tonic-gate nm = *namepp; 1877c478bd9Sstevel@tonic-gate *namepp = NULL; 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate /* 1907c478bd9Sstevel@tonic-gate * At this point, all we know is that we have an rnode whose 1917c478bd9Sstevel@tonic-gate * file handle matches the file handle of the object we want. 1927c478bd9Sstevel@tonic-gate * We have to verify that component name and the directory 1937c478bd9Sstevel@tonic-gate * match. If so, then we are done. 1947c478bd9Sstevel@tonic-gate * 1957c478bd9Sstevel@tonic-gate * Note: mvp is always the master vnode. 1967c478bd9Sstevel@tonic-gate */ 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate ASSERT(!IS_SHADOW(mvp, rp)); 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate if (sv_match(nm, drp->r_fh, master_svp)) { 2017c478bd9Sstevel@tonic-gate VN_HOLD(mvp); 2027c478bd9Sstevel@tonic-gate fn_rele(&nm); 2037c478bd9Sstevel@tonic-gate return (mvp); 2047c478bd9Sstevel@tonic-gate } 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate /* 2077c478bd9Sstevel@tonic-gate * No match, search through the shadow vnode list. 2087c478bd9Sstevel@tonic-gate * Hold the r_svlock to prevent changes. 2097c478bd9Sstevel@tonic-gate */ 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate mutex_enter(&rp->r_svlock); 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate for (svp = master_svp->sv_forw; svp != master_svp; svp = svp->sv_forw) 2147c478bd9Sstevel@tonic-gate if (sv_match(nm, drp->r_fh, svp)) { 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate /* 2177c478bd9Sstevel@tonic-gate * A matching shadow vnode is found, bump the 2187c478bd9Sstevel@tonic-gate * reference count on it and return it. 2197c478bd9Sstevel@tonic-gate */ 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate vp = SVTOV(svp); 2227c478bd9Sstevel@tonic-gate VN_HOLD(vp); 2237c478bd9Sstevel@tonic-gate fn_rele(&nm); 2247c478bd9Sstevel@tonic-gate mutex_exit(&rp->r_svlock); 2257c478bd9Sstevel@tonic-gate return (vp); 2267c478bd9Sstevel@tonic-gate } 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate /* 2297c478bd9Sstevel@tonic-gate * No match searching the list, go allocate a new shadow 2307c478bd9Sstevel@tonic-gate */ 2317c478bd9Sstevel@tonic-gate svp = kmem_cache_alloc(svnode_cache, KM_SLEEP); 2327c478bd9Sstevel@tonic-gate svp->sv_r_vnode = vn_alloc(KM_SLEEP); 2337c478bd9Sstevel@tonic-gate vp = SVTOV(svp); 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate /* Initialize the vnode */ 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate vn_setops(vp, nfs4_vnodeops); 2387c478bd9Sstevel@tonic-gate vp->v_data = (caddr_t)rp; 2397c478bd9Sstevel@tonic-gate vp->v_vfsp = mvp->v_vfsp; 2407c478bd9Sstevel@tonic-gate ASSERT(nfs4_consistent_type(mvp)); 2417c478bd9Sstevel@tonic-gate vp->v_type = mvp->v_type; 2427c478bd9Sstevel@tonic-gate vp->v_pages = (page_t *)-1; /* No pages, please */ 2437c478bd9Sstevel@tonic-gate vn_exists(vp); 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate /* Initialize the shadow vnode */ 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate svp->sv_dfh = VTOR4(dvp)->r_fh; 2487c478bd9Sstevel@tonic-gate sfh4_hold(svp->sv_dfh); 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate svp->sv_name = nm; 2517c478bd9Sstevel@tonic-gate VN_HOLD(mvp); 2527c478bd9Sstevel@tonic-gate insque(svp, master_svp); 2537c478bd9Sstevel@tonic-gate mutex_exit(&rp->r_svlock); 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate return (vp); 2567c478bd9Sstevel@tonic-gate } 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate /* 2597c478bd9Sstevel@tonic-gate * sv_match - check to see if the shadow vnode matches the desired 2607c478bd9Sstevel@tonic-gate * name and directory file handle. Returns non-zero if there's a match, 2617c478bd9Sstevel@tonic-gate * zero if it's not a match. 2627c478bd9Sstevel@tonic-gate */ 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate static int 2657c478bd9Sstevel@tonic-gate sv_match(nfs4_fname_t *nm, nfs4_sharedfh_t *fhp, svnode_t *svp) 2667c478bd9Sstevel@tonic-gate { 2677c478bd9Sstevel@tonic-gate sv_stats.sv_match++; 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate return (svp->sv_name != NULL && svp->sv_name == nm && 2707c478bd9Sstevel@tonic-gate SFH4_SAME(svp->sv_dfh, fhp)); 2717c478bd9Sstevel@tonic-gate } 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate /* 2747c478bd9Sstevel@tonic-gate * sv_inactive - deactivate a shadow vnode. sv_inactive is called 2757c478bd9Sstevel@tonic-gate * from nfs4_inactive. Whenever a shadow vnode is de-activated, 2767c478bd9Sstevel@tonic-gate * sv_inactive cleans up the mess and releases the reference on the 2777c478bd9Sstevel@tonic-gate * master vnode. 2787c478bd9Sstevel@tonic-gate */ 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate void 2817c478bd9Sstevel@tonic-gate sv_inactive(vnode_t *vp) 2827c478bd9Sstevel@tonic-gate { 2837c478bd9Sstevel@tonic-gate svnode_t *svp; 2847c478bd9Sstevel@tonic-gate rnode4_t *rp; 2857c478bd9Sstevel@tonic-gate vnode_t *mvp; 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate sv_stats.sv_inactive++; 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate svp = VTOSV(vp); 2907c478bd9Sstevel@tonic-gate rp = VTOR4(vp); 2917c478bd9Sstevel@tonic-gate mvp = rp->r_vnode; 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate ASSERT(mvp != vp); 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate /* 2967c478bd9Sstevel@tonic-gate * Remove the shadow vnode from the list. The serialization 2977c478bd9Sstevel@tonic-gate * is provided by the svnode list lock. This could be done 2987c478bd9Sstevel@tonic-gate * with the r_statelock, but that would require more locking 2997c478bd9Sstevel@tonic-gate * in the activation path. 3007c478bd9Sstevel@tonic-gate */ 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate mutex_enter(&rp->r_svlock); 3037c478bd9Sstevel@tonic-gate mutex_enter(&vp->v_lock); 3047c478bd9Sstevel@tonic-gate /* check if someone slipped in while locks were dropped */ 3057c478bd9Sstevel@tonic-gate if (vp->v_count > 1) { 3067c478bd9Sstevel@tonic-gate vp->v_count--; 3077c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 3087c478bd9Sstevel@tonic-gate mutex_exit(&rp->r_svlock); 3097c478bd9Sstevel@tonic-gate return; 3107c478bd9Sstevel@tonic-gate } 3117c478bd9Sstevel@tonic-gate remque(svp); 3127c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 3137c478bd9Sstevel@tonic-gate mutex_exit(&rp->r_svlock); 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate sv_uninit(svp); 3167c478bd9Sstevel@tonic-gate svp->sv_forw = svp->sv_back = NULL; 3177c478bd9Sstevel@tonic-gate kmem_cache_free(svnode_cache, svp); 3187c478bd9Sstevel@tonic-gate vn_invalid(vp); 3197c478bd9Sstevel@tonic-gate vn_free(vp); 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate /* release the reference held by this shadow on the master */ 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate VN_RELE(mvp); 3247c478bd9Sstevel@tonic-gate } 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate /* 3277c478bd9Sstevel@tonic-gate * sv_uninit - free any data structures allocated by the shadow vnode. 3287c478bd9Sstevel@tonic-gate */ 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate void 3317c478bd9Sstevel@tonic-gate sv_uninit(svnode_t *svp) 3327c478bd9Sstevel@tonic-gate { 3337c478bd9Sstevel@tonic-gate if (svp->sv_name != NULL) 3347c478bd9Sstevel@tonic-gate fn_rele(&svp->sv_name); 3357c478bd9Sstevel@tonic-gate if (svp->sv_dfh != NULL) 3367c478bd9Sstevel@tonic-gate sfh4_rele(&svp->sv_dfh); 3377c478bd9Sstevel@tonic-gate } 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate /* 3407c478bd9Sstevel@tonic-gate * sv_exchange - exchange a shadow vnode for the master vnode. This 3417c478bd9Sstevel@tonic-gate * occurs during nfs4_open, since only the master vnode owns the files 3427c478bd9Sstevel@tonic-gate * resources (eg. pages). 3437c478bd9Sstevel@tonic-gate */ 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate void 3467c478bd9Sstevel@tonic-gate sv_exchange(vnode_t **vpp) 3477c478bd9Sstevel@tonic-gate { 3487c478bd9Sstevel@tonic-gate vnode_t *mvp; 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate sv_stats.sv_exchange++; 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate /* RTOV always returns the master vnode */ 3537c478bd9Sstevel@tonic-gate mvp = RTOV4(VTOR4(*vpp)); 3547c478bd9Sstevel@tonic-gate VN_HOLD(mvp) 3557c478bd9Sstevel@tonic-gate VN_RELE(*vpp); 3567c478bd9Sstevel@tonic-gate *vpp = mvp; 3577c478bd9Sstevel@tonic-gate } 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate int 3607c478bd9Sstevel@tonic-gate nfs4_shadow_init(void) 3617c478bd9Sstevel@tonic-gate { 3627c478bd9Sstevel@tonic-gate /* 3637c478bd9Sstevel@tonic-gate * Allocate shadow vnode cache 3647c478bd9Sstevel@tonic-gate */ 3657c478bd9Sstevel@tonic-gate svnode_cache = kmem_cache_create("svnode_cache", 3667c478bd9Sstevel@tonic-gate sizeof (svnode_t), 0, NULL, NULL, NULL, NULL, NULL, 0); 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate return (0); 3697c478bd9Sstevel@tonic-gate } 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate int 3727c478bd9Sstevel@tonic-gate nfs4_shadow_fini(void) 3737c478bd9Sstevel@tonic-gate { 3747c478bd9Sstevel@tonic-gate kmem_cache_destroy(svnode_cache); 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate return (0); 3777c478bd9Sstevel@tonic-gate } 378