4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 * Copyright (c) 2017 by Delphix. All rights reserved.
30 #include <sys/systm.h>
31 #include <sys/cmn_err.h>
36 #include <nfs/rnode4.h>
37 #include <nfs/nfs4_clnt.h>
39 static struct kmem_cache
*svnode_cache
;
50 static int sv_match(nfs4_fname_t
*, nfs4_sharedfh_t
*, svnode_t
*);
53 * Map a vnode back to the shadow which points to it. This is
54 * hard now that the vnode is not embedded in the shadow vnode.
61 rnode4_t
*rp
= VTOR4(vp
);
62 svnode_t
*svp
, *svp_found
= NULL
;
64 /* Check to see if it's the master shadow vnode first. */
67 return (&rp
->r_svnode
);
69 mutex_enter(&rp
->r_svlock
);
71 for (svp
= rp
->r_svnode
.sv_forw
; svp
!= &rp
->r_svnode
;
73 if (svp
->sv_r_vnode
== vp
) {
78 mutex_exit(&rp
->r_svlock
);
79 ASSERT(svp_found
!= NULL
);
85 * sv_activate - find and activate the shadow vnode for the given
86 * directory file handle and name. May replace *vpp with a held reference
87 * to a different vnode, in which case the reference to the previous one is
92 sv_activate(vnode_t
**vpp
, vnode_t
*dvp
, nfs4_fname_t
**namepp
, int newnode
)
96 nfs4_fname_t
*svpname
;
97 rnode4_t
*rp
= VTOR4(*vpp
);
100 ASSERT(namepp
!= NULL
);
101 ASSERT(*namepp
!= NULL
);
104 sv_stats
.sv_activate
++;
106 ASSERT(RW_LOCK_HELD(&rp
->r_hashq
->r_lock
));
109 * If make_rnode made a new rnode (ie. newnode != 0), then
110 * the master vnode was (partially) initialized there. If
111 * it was not a new rnode, then it returns the master vnode.
112 * Call sv_find to find and/or initialize the shadow
118 * Initialize the shadow vnode.
120 svp
->sv_forw
= svp
->sv_back
= svp
;
121 ASSERT(svp
->sv_dfh
== NULL
);
122 svp
->sv_dfh
= VTOR4(dvp
)->r_fh
;
123 sfh4_hold(svp
->sv_dfh
);
124 ASSERT(svp
->sv_name
== NULL
);
125 svp
->sv_name
= *namepp
;
126 } else if ((*vpp
)->v_type
== VREG
&& !((*vpp
)->v_flag
& VROOT
)) {
127 resvp
= sv_find(*vpp
, dvp
, namepp
);
128 ASSERT(resvp
->v_type
== VREG
);
133 * No shadow vnodes (i.e. hard links) in this branch.
134 * If sv_activate() is called for an existing rnode
135 * (newnode isn't set) but with a new name, the sv_name
136 * needs to be updated and the old sv_name released.
138 * fname mismatches can occur due to server side renames,
139 * here is a chance to update the fname in case there is
140 * a mismatch. Since this is not a newnode we hold r_svlock
141 * to protect sv_name.
143 mutex_enter(&rp
->r_svlock
);
144 svpname
= svp
->sv_name
;
145 if (svpname
!= *namepp
) {
147 * Call fn_rele() to release the hold for the
148 * previous shadow vnode reference. Don't
149 * release the hold on the fname pointed to by
150 * namepp as we have new reference to it from
153 svp
->sv_name
= *namepp
;
154 mutex_exit(&rp
->r_svlock
);
157 mutex_exit(&rp
->r_svlock
);
164 * sv_find - find the shadow vnode for the desired name and directory
165 * file handle. If one does not exist, then create it. Returns the shadow
166 * vnode. The caller is responsible for freeing the reference.
167 * Consumes the name reference and nulls it out.
169 * Side effects: increments the reference count on the master vnode if the
170 * shadow vnode had to be created.
174 sv_find(vnode_t
*mvp
, vnode_t
*dvp
, nfs4_fname_t
**namepp
)
177 rnode4_t
*rp
= VTOR4(mvp
);
179 svnode_t
*master_svp
= VTOSV(mvp
);
180 rnode4_t
*drp
= VTOR4(dvp
);
187 ASSERT(namepp
!= NULL
);
188 ASSERT(*namepp
!= NULL
);
193 * At this point, all we know is that we have an rnode whose
194 * file handle matches the file handle of the object we want.
195 * We have to verify that component name and the directory
196 * match. If so, then we are done.
198 * Note: mvp is always the master vnode.
201 ASSERT(!IS_SHADOW(mvp
, rp
));
203 if (sv_match(nm
, drp
->r_fh
, master_svp
)) {
210 * No match, search through the shadow vnode list.
211 * Hold the r_svlock to prevent changes.
214 mutex_enter(&rp
->r_svlock
);
216 for (svp
= master_svp
->sv_forw
; svp
!= master_svp
; svp
= svp
->sv_forw
)
217 if (sv_match(nm
, drp
->r_fh
, svp
)) {
220 * A matching shadow vnode is found, bump the
221 * reference count on it and return it.
227 mutex_exit(&rp
->r_svlock
);
232 * No match searching the list, go allocate a new shadow
234 svp
= kmem_cache_alloc(svnode_cache
, KM_SLEEP
);
235 svp
->sv_r_vnode
= vn_alloc(KM_SLEEP
);
238 /* Initialize the vnode */
240 vn_setops(vp
, &nfs4_vnodeops
);
241 vp
->v_data
= (caddr_t
)rp
;
242 vp
->v_vfsp
= mvp
->v_vfsp
;
243 ASSERT(nfs4_consistent_type(mvp
));
244 vp
->v_type
= mvp
->v_type
;
247 /* Initialize the shadow vnode */
249 svp
->sv_dfh
= VTOR4(dvp
)->r_fh
;
250 sfh4_hold(svp
->sv_dfh
);
254 insque(svp
, master_svp
);
255 mutex_exit(&rp
->r_svlock
);
261 * sv_match - check to see if the shadow vnode matches the desired
262 * name and directory file handle. Returns non-zero if there's a match,
263 * zero if it's not a match.
267 sv_match(nfs4_fname_t
*nm
, nfs4_sharedfh_t
*fhp
, svnode_t
*svp
)
271 return (svp
->sv_name
!= NULL
&& svp
->sv_name
== nm
&&
272 SFH4_SAME(svp
->sv_dfh
, fhp
));
276 * sv_inactive - deactivate a shadow vnode. sv_inactive is called
277 * from nfs4_inactive. Whenever a shadow vnode is de-activated,
278 * sv_inactive cleans up the mess and releases the reference on the
283 sv_inactive(vnode_t
*vp
)
289 sv_stats
.sv_inactive
++;
298 * Remove the shadow vnode from the list. The serialization
299 * is provided by the svnode list lock. This could be done
300 * with the r_statelock, but that would require more locking
301 * in the activation path.
304 mutex_enter(&rp
->r_svlock
);
305 mutex_enter(&vp
->v_lock
);
306 /* check if someone slipped in while locks were dropped */
307 if (vp
->v_count
> 1) {
309 mutex_exit(&vp
->v_lock
);
310 mutex_exit(&rp
->r_svlock
);
314 mutex_exit(&vp
->v_lock
);
315 mutex_exit(&rp
->r_svlock
);
318 svp
->sv_forw
= svp
->sv_back
= NULL
;
319 kmem_cache_free(svnode_cache
, svp
);
323 /* release the reference held by this shadow on the master */
329 * sv_uninit - free any data structures allocated by the shadow vnode.
333 sv_uninit(svnode_t
*svp
)
335 if (svp
->sv_name
!= NULL
)
336 fn_rele(&svp
->sv_name
);
337 if (svp
->sv_dfh
!= NULL
)
338 sfh4_rele(&svp
->sv_dfh
);
342 * sv_exchange - exchange a shadow vnode for the master vnode. This
343 * occurs during nfs4_open, since only the master vnode owns the files
344 * resources (eg. pages).
348 sv_exchange(vnode_t
**vpp
)
352 sv_stats
.sv_exchange
++;
354 /* RTOV always returns the master vnode */
355 mvp
= RTOV4(VTOR4(*vpp
));
362 nfs4_shadow_init(void)
365 * Allocate shadow vnode cache
367 svnode_cache
= kmem_cache_create("svnode_cache",
368 sizeof (svnode_t
), 0, NULL
, NULL
, NULL
, NULL
, NULL
, 0);
374 nfs4_shadow_fini(void)
376 kmem_cache_destroy(svnode_cache
);