xref: /freebsd/sys/fs/unionfs/union_vnops.c (revision 2ed053cde55869d3440377d479deb00f42ba1cf8)
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 1992, 1993, 1994, 1995 Jan-Simon Pendry.
5  * Copyright (c) 1992, 1993, 1994, 1995
6  *      The Regents of the University of California.
7  * Copyright (c) 2005, 2006, 2012 Masanori Ozawa <ozawa@ongs.co.jp>, ONGS Inc.
8  * Copyright (c) 2006, 2012 Daichi Goto <daichi@freebsd.org>
9  * All rights reserved.
10  *
11  * This code is derived from software contributed to Berkeley by
12  * Jan-Simon Pendry.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  * 3. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  */
39 
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/conf.h>
43 #include <sys/kernel.h>
44 #include <sys/lock.h>
45 #include <sys/malloc.h>
46 #include <sys/mount.h>
47 #include <sys/mutex.h>
48 #include <sys/namei.h>
49 #include <sys/sysctl.h>
50 #include <sys/vnode.h>
51 #include <sys/kdb.h>
52 #include <sys/fcntl.h>
53 #include <sys/stat.h>
54 #include <sys/dirent.h>
55 #include <sys/proc.h>
56 #include <sys/bio.h>
57 #include <sys/buf.h>
58 
59 #include <fs/unionfs/union.h>
60 
61 #include <machine/atomic.h>
62 
63 #include <vm/vm.h>
64 #include <vm/vm_extern.h>
65 #include <vm/vm_object.h>
66 #include <vm/vnode_pager.h>
67 
68 #if 0
69 #define UNIONFS_INTERNAL_DEBUG(msg, args...)    printf(msg, ## args)
70 #define UNIONFS_IDBG_RENAME
71 #else
72 #define UNIONFS_INTERNAL_DEBUG(msg, args...)
73 #endif
74 
75 #define KASSERT_UNIONFS_VNODE(vp) \
76 	VNASSERT(((vp)->v_op == &unionfs_vnodeops), vp, \
77 	    ("%s: non-unionfs vnode", __func__))
78 
79 static int
unionfs_lookup(struct vop_cachedlookup_args * ap)80 unionfs_lookup(struct vop_cachedlookup_args *ap)
81 {
82 	struct unionfs_node *dunp, *unp;
83 	struct vnode   *dvp, *udvp, *ldvp, *vp, *uvp, *lvp, *dtmpvp;
84 	struct vattr	va;
85 	struct componentname *cnp;
86 	struct thread  *td;
87 	u_long		nameiop;
88 	u_long		cnflags;
89 	int		lockflag;
90 	int		lkflags;
91 	int		error, uerror, lerror;
92 
93 	lockflag = 0;
94 	error = uerror = lerror = ENOENT;
95 	cnp = ap->a_cnp;
96 	nameiop = cnp->cn_nameiop;
97 	cnflags = cnp->cn_flags;
98 	dvp = ap->a_dvp;
99 	dunp = VTOUNIONFS(dvp);
100 	udvp = dunp->un_uppervp;
101 	ldvp = dunp->un_lowervp;
102 	vp = uvp = lvp = NULLVP;
103 	td = curthread;
104 	*(ap->a_vpp) = NULLVP;
105 
106 	UNIONFS_INTERNAL_DEBUG(
107 	    "unionfs_lookup: enter: nameiop=%ld, flags=%lx, path=%s\n",
108 	    nameiop, cnflags, cnp->cn_nameptr);
109 
110 	if (dvp->v_type != VDIR)
111 		return (ENOTDIR);
112 
113 	/*
114 	 * If read-only and op is not LOOKUP, will return EROFS.
115 	 */
116 	if ((cnflags & ISLASTCN) &&
117 	    (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
118 	    LOOKUP != nameiop)
119 		return (EROFS);
120 
121 	/*
122 	 * Note that a lookup is in-flight, and block if another lookup
123 	 * is already in-flight against dvp.  This is done because we may
124 	 * end up dropping dvp's lock to look up a lower vnode or to create
125 	 * a shadow directory, opening up the possibility of parallel lookups
126 	 * against the same directory creating duplicate unionfs vnodes for
127 	 * the same file(s).  Note that if this function encounters an
128 	 * in-progress lookup for the directory, it will block until the
129 	 * lookup is complete and then return ERELOOKUP to allow any
130 	 * existing unionfs vnode to be loaded from the VFS cache.
131 	 * This is really a hack; filesystems that support MNTK_LOOKUP_SHARED
132 	 * (which unionfs currently doesn't) seem to deal with this by using
133 	 * the vfs_hash_* functions to manage a per-mount vnode cache keyed
134 	 * by the inode number (or some roughly equivalent unique ID
135 	 * usually assocated with the storage medium).  It may make sense
136 	 * for unionfs to adopt something similar as a replacement for its
137 	 * current half-baked directory-only cache implementation, particularly
138 	 * if we want to support MNTK_LOOKUP_SHARED here.
139 	 */
140 	error = unionfs_set_in_progress_flag(dvp, UNIONFS_LOOKUP_IN_PROGRESS);
141 	if (error != 0)
142 		return (error);
143 	/*
144 	 * lookup dotdot
145 	 */
146 	if (cnflags & ISDOTDOT) {
147 		if (LOOKUP != nameiop && udvp == NULLVP) {
148 			error = EROFS;
149 			goto unionfs_lookup_return;
150 		}
151 
152 		if (udvp != NULLVP)
153 			dtmpvp = udvp;
154 		else
155 			dtmpvp = ldvp;
156 
157 		unionfs_forward_vop_start(dtmpvp, &lkflags);
158 		error = VOP_LOOKUP(dtmpvp, &vp, cnp);
159 		unionfs_forward_vop_finish(dvp, dtmpvp, lkflags);
160 
161 		/*
162 		 * Drop the lock and reference on vp.  If the lookup was
163 		 * successful, we'll either need to exchange vp's lock and
164 		 * reference for the unionfs parent vnode's lock and
165 		 * reference, or (if dvp was reclaimed) we'll need to drop
166 		 * vp's lock and reference to return early.
167 		 */
168 		if (vp != NULLVP)
169 			vput(vp);
170 		dunp = VTOUNIONFS(dvp);
171 		if (error == 0 && dunp == NULL)
172 			error = ENOENT;
173 
174 		if (error == 0) {
175 			dtmpvp = dunp->un_dvp;
176 			vref(dtmpvp);
177 			VOP_UNLOCK(dvp);
178 			*(ap->a_vpp) = dtmpvp;
179 
180 			vn_lock(dtmpvp, cnp->cn_lkflags | LK_RETRY);
181 
182 			if (VN_IS_DOOMED(dtmpvp)) {
183 				vput(dtmpvp);
184 				*(ap->a_vpp) = NULLVP;
185 				error = ENOENT;
186 			}
187 			vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
188 		}
189 
190 		goto unionfs_lookup_cleanup;
191 	}
192 
193 	/*
194 	 * Lookup lower layer.  We do this before looking up the the upper
195 	 * layer, as we may drop the upper parent directory's lock, and we
196 	 * want to ensure the upper parent remains locked from the point of
197 	 * lookup through any ensuing VOP that may require it to be locked.
198 	 * The cost of this is that we may end up performing an unnecessary
199 	 * lower layer lookup if a whiteout is present in the upper layer.
200 	 */
201 	if (ldvp != NULLVP && !(cnflags & DOWHITEOUT)) {
202 		struct componentname lcn;
203 		bool is_dot;
204 
205 		if (udvp != NULLVP) {
206 			vref(ldvp);
207 			VOP_UNLOCK(dvp);
208 			vn_lock(ldvp, LK_EXCLUSIVE | LK_RETRY);
209 		}
210 
211 		lcn = *cnp;
212 		/* always op is LOOKUP */
213 		lcn.cn_nameiop = LOOKUP;
214 		lcn.cn_flags = cnflags;
215 		is_dot = false;
216 
217 		if (udvp == NULLVP)
218 			unionfs_forward_vop_start(ldvp, &lkflags);
219 		lerror = VOP_LOOKUP(ldvp, &lvp, &lcn);
220 		if (udvp == NULLVP &&
221 		    unionfs_forward_vop_finish(dvp, ldvp, lkflags)) {
222 			if (lvp != NULLVP)
223 				VOP_UNLOCK(lvp);
224 			error =  ENOENT;
225 			goto unionfs_lookup_cleanup;
226 		}
227 
228 		if (udvp == NULLVP)
229 			cnp->cn_flags = lcn.cn_flags;
230 
231 		if (lerror == 0) {
232 			if (ldvp == lvp) {	/* is dot */
233 				vrele(lvp);
234 				*(ap->a_vpp) = dvp;
235 				vref(dvp);
236 				is_dot = true;
237 				error = lerror;
238 			} else if (lvp != NULLVP)
239 				VOP_UNLOCK(lvp);
240 		}
241 
242 		if (udvp != NULLVP) {
243 			vput(ldvp);
244 			vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
245 			if (VN_IS_DOOMED(dvp))
246 				error = ENOENT;
247 		}
248 		if (is_dot)
249 			goto unionfs_lookup_return;
250 		else if (error != 0)
251 			goto unionfs_lookup_cleanup;
252 	}
253 	/*
254 	 * lookup upper layer
255 	 */
256 	if (udvp != NULLVP) {
257 		bool iswhiteout = false;
258 
259 		unionfs_forward_vop_start(udvp, &lkflags);
260 		uerror = VOP_LOOKUP(udvp, &uvp, cnp);
261 		if (unionfs_forward_vop_finish(dvp, udvp, lkflags)) {
262 			if (uvp != NULLVP)
263 				VOP_UNLOCK(uvp);
264 			error = ENOENT;
265 			goto unionfs_lookup_cleanup;
266 		}
267 
268 		if (uerror == 0) {
269 			if (udvp == uvp) {	/* is dot */
270 				if (lvp != NULLVP)
271 					vrele(lvp);
272 				vrele(uvp);
273 				*(ap->a_vpp) = dvp;
274 				vref(dvp);
275 
276 				error = uerror;
277 				goto unionfs_lookup_return;
278 			} else if (uvp != NULLVP)
279 				VOP_UNLOCK(uvp);
280 		}
281 
282 		/* check whiteout */
283 		if ((uerror == ENOENT || uerror == EJUSTRETURN) &&
284 		    (cnp->cn_flags & ISWHITEOUT))
285 			iswhiteout = true;
286 		else if (VOP_GETATTR(udvp, &va, cnp->cn_cred) == 0 &&
287 		    (va.va_flags & OPAQUE))
288 			iswhiteout = true;
289 
290 		if (iswhiteout && lvp != NULLVP) {
291 			vrele(lvp);
292 			lvp = NULLVP;
293 		}
294 
295 #if 0
296 		UNIONFS_INTERNAL_DEBUG(
297 		    "unionfs_lookup: debug: whiteout=%d, path=%s\n",
298 		    iswhiteout, cnp->cn_nameptr);
299 #endif
300 	}
301 
302 	/*
303 	 * check lookup result
304 	 */
305 	if (uvp == NULLVP && lvp == NULLVP) {
306 		error = (udvp != NULLVP ? uerror : lerror);
307 		goto unionfs_lookup_return;
308 	}
309 
310 	/*
311 	 * check vnode type
312 	 */
313 	if (uvp != NULLVP && lvp != NULLVP && uvp->v_type != lvp->v_type) {
314 		vrele(lvp);
315 		lvp = NULLVP;
316 	}
317 
318 	/*
319 	 * check shadow dir
320 	 */
321 	if (uerror != 0 && uerror != EJUSTRETURN && udvp != NULLVP &&
322 	    lerror == 0 && lvp != NULLVP && lvp->v_type == VDIR &&
323 	    !(dvp->v_mount->mnt_flag & MNT_RDONLY) &&
324 	    (1 < cnp->cn_namelen || '.' != *(cnp->cn_nameptr))) {
325 		/* get unionfs vnode in order to create a new shadow dir. */
326 		error = unionfs_nodeget(dvp->v_mount, NULLVP, lvp, dvp, &vp,
327 		    cnp);
328 		if (error != 0)
329 			goto unionfs_lookup_cleanup;
330 
331 		if (LK_SHARED == (cnp->cn_lkflags & LK_TYPE_MASK))
332 			VOP_UNLOCK(vp);
333 		if (LK_EXCLUSIVE != VOP_ISLOCKED(vp)) {
334 			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
335 			lockflag = 1;
336 		}
337 		unp = VTOUNIONFS(vp);
338 		if (unp == NULL)
339 			error = ENOENT;
340 		else
341 			error = unionfs_mkshadowdir(dvp, vp, cnp, td);
342 		if (lockflag != 0)
343 			VOP_UNLOCK(vp);
344 		if (error != 0) {
345 			UNIONFSDEBUG(
346 			    "unionfs_lookup: Unable to create shadow dir.");
347 			if ((cnp->cn_lkflags & LK_TYPE_MASK) == LK_EXCLUSIVE)
348 				vput(vp);
349 			else
350 				vrele(vp);
351 			goto unionfs_lookup_cleanup;
352 		}
353 		/*
354 		 * TODO: Since unionfs_mkshadowdir() relocks udvp after
355 		 * creating the new directory, return ERELOOKUP here?
356 		 */
357 		if ((cnp->cn_lkflags & LK_TYPE_MASK) == LK_SHARED)
358 			vn_lock(vp, LK_SHARED | LK_RETRY);
359 	}
360 	/*
361 	 * get unionfs vnode.
362 	 */
363 	else {
364 		if (uvp != NULLVP)
365 			error = uerror;
366 		else
367 			error = lerror;
368 		if (error != 0)
369 			goto unionfs_lookup_cleanup;
370 		error = unionfs_nodeget(dvp->v_mount, uvp, lvp,
371 		    dvp, &vp, cnp);
372 		if (error != 0) {
373 			UNIONFSDEBUG(
374 			    "unionfs_lookup: Unable to create unionfs vnode.");
375 			goto unionfs_lookup_cleanup;
376 		}
377 	}
378 
379 	if (VN_IS_DOOMED(dvp) || VN_IS_DOOMED(vp)) {
380 		error = ENOENT;
381 		vput(vp);
382 		goto unionfs_lookup_cleanup;
383 	}
384 
385 	*(ap->a_vpp) = vp;
386 
387 	if (cnflags & MAKEENTRY)
388 		cache_enter(dvp, vp, cnp);
389 
390 unionfs_lookup_cleanup:
391 	if (uvp != NULLVP)
392 		vrele(uvp);
393 	if (lvp != NULLVP)
394 		vrele(lvp);
395 
396 	if (error == ENOENT && (cnflags & MAKEENTRY) != 0 &&
397 	    !VN_IS_DOOMED(dvp))
398 		cache_enter(dvp, NULLVP, cnp);
399 
400 unionfs_lookup_return:
401 	unionfs_clear_in_progress_flag(dvp, UNIONFS_LOOKUP_IN_PROGRESS);
402 
403 	UNIONFS_INTERNAL_DEBUG("unionfs_lookup: leave (%d)\n", error);
404 
405 	return (error);
406 }
407 
408 static int
unionfs_create(struct vop_create_args * ap)409 unionfs_create(struct vop_create_args *ap)
410 {
411 	struct unionfs_node *dunp;
412 	struct componentname *cnp;
413 	struct vnode   *udvp;
414 	struct vnode   *vp;
415 	int		error;
416 
417 	UNIONFS_INTERNAL_DEBUG("unionfs_create: enter\n");
418 
419 	KASSERT_UNIONFS_VNODE(ap->a_dvp);
420 
421 	dunp = VTOUNIONFS(ap->a_dvp);
422 	cnp = ap->a_cnp;
423 	udvp = dunp->un_uppervp;
424 	error = EROFS;
425 
426 	if (udvp != NULLVP) {
427 		int lkflags;
428 		bool vp_created = false;
429 		unionfs_forward_vop_start(udvp, &lkflags);
430 		error = VOP_CREATE(udvp, &vp, cnp, ap->a_vap);
431 		if (error == 0)
432 			vp_created = true;
433 		if (__predict_false(unionfs_forward_vop_finish(ap->a_dvp, udvp,
434 		    lkflags)) && error == 0) {
435 			error = ENOENT;
436 		}
437 		if (error == 0) {
438 			VOP_UNLOCK(vp);
439 			error = unionfs_nodeget(ap->a_dvp->v_mount, vp, NULLVP,
440 			    ap->a_dvp, ap->a_vpp, cnp);
441 			vrele(vp);
442 		} else if (vp_created)
443 			vput(vp);
444 	}
445 
446 	UNIONFS_INTERNAL_DEBUG("unionfs_create: leave (%d)\n", error);
447 
448 	return (error);
449 }
450 
451 static int
unionfs_whiteout(struct vop_whiteout_args * ap)452 unionfs_whiteout(struct vop_whiteout_args *ap)
453 {
454 	struct unionfs_node *dunp;
455 	struct componentname *cnp;
456 	struct vnode   *udvp;
457 	int		error;
458 
459 	UNIONFS_INTERNAL_DEBUG("unionfs_whiteout: enter\n");
460 
461 	KASSERT_UNIONFS_VNODE(ap->a_dvp);
462 
463 	dunp = VTOUNIONFS(ap->a_dvp);
464 	cnp = ap->a_cnp;
465 	udvp = dunp->un_uppervp;
466 	error = EOPNOTSUPP;
467 
468 	if (udvp != NULLVP) {
469 		int lkflags;
470 		switch (ap->a_flags) {
471 		case CREATE:
472 		case DELETE:
473 		case LOOKUP:
474 			unionfs_forward_vop_start(udvp, &lkflags);
475 			error = VOP_WHITEOUT(udvp, cnp, ap->a_flags);
476 			unionfs_forward_vop_finish(ap->a_dvp, udvp, lkflags);
477 			break;
478 		default:
479 			error = EINVAL;
480 			break;
481 		}
482 	}
483 
484 	UNIONFS_INTERNAL_DEBUG("unionfs_whiteout: leave (%d)\n", error);
485 
486 	return (error);
487 }
488 
489 static int
unionfs_mknod(struct vop_mknod_args * ap)490 unionfs_mknod(struct vop_mknod_args *ap)
491 {
492 	struct unionfs_node *dunp;
493 	struct componentname *cnp;
494 	struct vnode   *udvp;
495 	struct vnode   *vp;
496 	int		error;
497 
498 	UNIONFS_INTERNAL_DEBUG("unionfs_mknod: enter\n");
499 
500 	KASSERT_UNIONFS_VNODE(ap->a_dvp);
501 
502 	dunp = VTOUNIONFS(ap->a_dvp);
503 	cnp = ap->a_cnp;
504 	udvp = dunp->un_uppervp;
505 	error = EROFS;
506 
507 	if (udvp != NULLVP) {
508 		int lkflags;
509 		bool vp_created = false;
510 		unionfs_forward_vop_start(udvp, &lkflags);
511 		error = VOP_MKNOD(udvp, &vp, cnp, ap->a_vap);
512 		if (error == 0)
513 			vp_created = true;
514 		if (__predict_false(unionfs_forward_vop_finish(ap->a_dvp, udvp,
515 		    lkflags)) && error == 0) {
516 			error = ENOENT;
517 		}
518 		if (error == 0) {
519 			VOP_UNLOCK(vp);
520 			error = unionfs_nodeget(ap->a_dvp->v_mount, vp, NULLVP,
521 			    ap->a_dvp, ap->a_vpp, cnp);
522 			vrele(vp);
523 		} else if (vp_created)
524 			vput(vp);
525 	}
526 
527 	UNIONFS_INTERNAL_DEBUG("unionfs_mknod: leave (%d)\n", error);
528 
529 	return (error);
530 }
531 
532 enum unionfs_lkupgrade {
533 	UNIONFS_LKUPGRADE_SUCCESS, /* lock successfully upgraded */
534 	UNIONFS_LKUPGRADE_ALREADY, /* lock already held exclusive */
535 	UNIONFS_LKUPGRADE_DOOMED   /* lock was upgraded, but vnode reclaimed */
536 };
537 
538 static inline enum unionfs_lkupgrade
unionfs_upgrade_lock(struct vnode * vp)539 unionfs_upgrade_lock(struct vnode *vp)
540 {
541 	ASSERT_VOP_LOCKED(vp, __func__);
542 
543 	if (VOP_ISLOCKED(vp) == LK_EXCLUSIVE)
544 		return (UNIONFS_LKUPGRADE_ALREADY);
545 
546 	if (vn_lock(vp, LK_UPGRADE) != 0) {
547 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
548 		if (VN_IS_DOOMED(vp))
549 			return (UNIONFS_LKUPGRADE_DOOMED);
550 	}
551 	return (UNIONFS_LKUPGRADE_SUCCESS);
552 }
553 
554 static inline void
unionfs_downgrade_lock(struct vnode * vp,enum unionfs_lkupgrade status)555 unionfs_downgrade_lock(struct vnode *vp, enum unionfs_lkupgrade status)
556 {
557 	if (status != UNIONFS_LKUPGRADE_ALREADY)
558 		vn_lock(vp, LK_DOWNGRADE | LK_RETRY);
559 }
560 
561 /*
562  * Exchange the default (upper vnode) lock on a unionfs vnode for the lower
563  * vnode lock, in support of operations that require access to the lower vnode
564  * even when an upper vnode is present.  We don't use vn_lock_pair() to hold
565  * both vnodes at the same time, primarily because the caller may proceed
566  * to issue VOPs to the lower layer which re-lock or perform other operations
567  * which may not be safe in the presence of a locked vnode from another FS.
568  * Moreover, vn_lock_pair()'s deadlock resolution approach can introduce
569  * additional overhead that isn't necessary on these paths.
570  *
571  * vp must be a locked unionfs vnode; the lock state of this vnode is
572  * returned through *lkflags for later use in unionfs_unlock_lvp().
573  *
574  * Returns the locked lower vnode, or NULL if the lower vnode (and therefore
575  * also the unionfs vnode above it) has been doomed.
576  */
577 static struct vnode *
unionfs_lock_lvp(struct vnode * vp,int * lkflags)578 unionfs_lock_lvp(struct vnode *vp, int *lkflags)
579 {
580 	struct unionfs_node *unp;
581 	struct vnode *lvp;
582 
583 	unp = VTOUNIONFS(vp);
584 	lvp = unp->un_lowervp;
585 	ASSERT_VOP_LOCKED(vp, __func__);
586 	ASSERT_VOP_UNLOCKED(lvp, __func__);
587 	*lkflags = VOP_ISLOCKED(vp);
588 	vref(lvp);
589 	VOP_UNLOCK(vp);
590 	vn_lock(lvp, *lkflags | LK_RETRY);
591 	if (VN_IS_DOOMED(lvp)) {
592 		vput(lvp);
593 		lvp = NULLVP;
594 		vn_lock(vp, *lkflags | LK_RETRY);
595 	}
596 	return (lvp);
597 }
598 
599 /*
600  * Undo a previous call to unionfs_lock_lvp(), restoring the default lock
601  * on the unionfs vnode.  This function reloads and returns the vnode
602  * private data for the unionfs vnode, which will be NULL if the unionfs
603  * vnode became doomed while its lock was dropped.  The caller must check
604  * for this case.
605  */
606 static struct unionfs_node *
unionfs_unlock_lvp(struct vnode * vp,struct vnode * lvp,int lkflags)607 unionfs_unlock_lvp(struct vnode *vp, struct vnode *lvp, int lkflags)
608 {
609 	ASSERT_VOP_LOCKED(lvp, __func__);
610 	ASSERT_VOP_UNLOCKED(vp, __func__);
611 	vput(lvp);
612 	vn_lock(vp, lkflags | LK_RETRY);
613 	return (VTOUNIONFS(vp));
614 }
615 
616 static int
unionfs_open(struct vop_open_args * ap)617 unionfs_open(struct vop_open_args *ap)
618 {
619 	struct unionfs_node *unp;
620 	struct unionfs_node_status *unsp;
621 	struct vnode   *vp;
622 	struct vnode   *uvp;
623 	struct vnode   *lvp;
624 	struct vnode   *targetvp;
625 	struct ucred   *cred;
626 	struct thread  *td;
627 	int		error;
628 	int		lkflags;
629 	enum unionfs_lkupgrade lkstatus;
630 	bool		lock_lvp, open_lvp;
631 
632 	UNIONFS_INTERNAL_DEBUG("unionfs_open: enter\n");
633 
634 	KASSERT_UNIONFS_VNODE(ap->a_vp);
635 
636 	error = 0;
637 	vp = ap->a_vp;
638 	targetvp = NULLVP;
639 	cred = ap->a_cred;
640 	td = ap->a_td;
641 	open_lvp = lock_lvp = false;
642 
643 	/*
644 	 * The executable loader path may call this function with vp locked
645 	 * shared.  If the vnode is reclaimed while upgrading, we can't safely
646 	 * use unp or do anything else unionfs- specific.
647 	 */
648 	lkstatus = unionfs_upgrade_lock(vp);
649 	if (lkstatus == UNIONFS_LKUPGRADE_DOOMED) {
650 		error = ENOENT;
651 		goto unionfs_open_cleanup;
652 	}
653 
654 	unp = VTOUNIONFS(vp);
655 	uvp = unp->un_uppervp;
656 	lvp = unp->un_lowervp;
657 	unionfs_get_node_status(unp, td, &unsp);
658 
659 	if (unsp->uns_lower_opencnt > 0 || unsp->uns_upper_opencnt > 0) {
660 		/* vnode is already opend. */
661 		if (unsp->uns_upper_opencnt > 0)
662 			targetvp = uvp;
663 		else
664 			targetvp = lvp;
665 
666 		if (targetvp == lvp &&
667 		    (ap->a_mode & FWRITE) && lvp->v_type == VREG)
668 			targetvp = NULLVP;
669 	}
670 	if (targetvp == NULLVP) {
671 		if (uvp == NULLVP) {
672 			if ((ap->a_mode & FWRITE) && lvp->v_type == VREG) {
673 				error = unionfs_copyfile(vp,
674 				    !(ap->a_mode & O_TRUNC), cred, td);
675 				if (error != 0) {
676 					unp = VTOUNIONFS(vp);
677 					goto unionfs_open_abort;
678 				}
679 				targetvp = uvp = unp->un_uppervp;
680 			} else
681 				targetvp = lvp;
682 		} else
683 			targetvp = uvp;
684 	}
685 
686 	if (targetvp == uvp && uvp->v_type == VDIR && lvp != NULLVP &&
687 	    unsp->uns_lower_opencnt <= 0)
688 		open_lvp = true;
689 	else if (targetvp == lvp && uvp != NULLVP)
690 		lock_lvp = true;
691 
692 	if (lock_lvp) {
693 		unp = NULL;
694 		lvp = unionfs_lock_lvp(vp, &lkflags);
695 		if (lvp == NULLVP) {
696 			error = ENOENT;
697 			goto unionfs_open_abort;
698 		}
699 	} else
700 		unionfs_forward_vop_start(targetvp, &lkflags);
701 
702 	error = VOP_OPEN(targetvp, ap->a_mode, cred, td, ap->a_fp);
703 
704 	if (lock_lvp) {
705 		unp = unionfs_unlock_lvp(vp, lvp, lkflags);
706 		if (unp == NULL && error == 0)
707 			error = ENOENT;
708 	} else if (unionfs_forward_vop_finish(vp, targetvp, lkflags))
709 		error = error ? error : ENOENT;
710 
711 	if (error != 0)
712 		goto unionfs_open_abort;
713 
714 	if (targetvp == uvp) {
715 		if (open_lvp) {
716 			unp = NULL;
717 			lvp = unionfs_lock_lvp(vp, &lkflags);
718 			if (lvp == NULLVP) {
719 				error = ENOENT;
720 				goto unionfs_open_abort;
721 			}
722 			/* open lower for readdir */
723 			error = VOP_OPEN(lvp, FREAD, cred, td, NULL);
724 			unp = unionfs_unlock_lvp(vp, lvp, lkflags);
725 			if (unp == NULL) {
726 				error = error ? error : ENOENT;
727 				goto unionfs_open_abort;
728 			}
729 			if (error != 0) {
730 				unionfs_forward_vop_start(uvp, &lkflags);
731 				VOP_CLOSE(uvp, ap->a_mode, cred, td);
732 				if (unionfs_forward_vop_finish(vp, uvp, lkflags))
733 					unp = NULL;
734 				goto unionfs_open_abort;
735 			}
736 			unsp->uns_node_flag |= UNS_OPENL_4_READDIR;
737 			unsp->uns_lower_opencnt++;
738 		}
739 		unsp->uns_upper_opencnt++;
740 	} else {
741 		unsp->uns_lower_opencnt++;
742 		unsp->uns_lower_openmode = ap->a_mode;
743 	}
744 	vp->v_object = targetvp->v_object;
745 
746 unionfs_open_abort:
747 
748 	if (error != 0 && unp != NULL)
749 		unionfs_tryrem_node_status(unp, unsp);
750 
751 unionfs_open_cleanup:
752 	unionfs_downgrade_lock(vp, lkstatus);
753 
754 	UNIONFS_INTERNAL_DEBUG("unionfs_open: leave (%d)\n", error);
755 
756 	return (error);
757 }
758 
759 static int
unionfs_close(struct vop_close_args * ap)760 unionfs_close(struct vop_close_args *ap)
761 {
762 	struct unionfs_node *unp;
763 	struct unionfs_node_status *unsp;
764 	struct ucred   *cred;
765 	struct thread  *td;
766 	struct vnode   *vp;
767 	struct vnode   *uvp;
768 	struct vnode   *lvp;
769 	struct vnode   *ovp;
770 	int		error;
771 	int		lkflags;
772 	enum unionfs_lkupgrade lkstatus;
773 	bool		lock_lvp;
774 
775 	UNIONFS_INTERNAL_DEBUG("unionfs_close: enter\n");
776 
777 	KASSERT_UNIONFS_VNODE(ap->a_vp);
778 
779 	vp = ap->a_vp;
780 	cred = ap->a_cred;
781 	td = ap->a_td;
782 	error = 0;
783 	lock_lvp = false;
784 
785 	/*
786 	 * If the vnode is reclaimed while upgrading, we can't safely use unp
787 	 * or do anything else unionfs- specific.
788 	 */
789 	lkstatus = unionfs_upgrade_lock(vp);
790 	if (lkstatus == UNIONFS_LKUPGRADE_DOOMED)
791 		goto unionfs_close_cleanup;
792 
793 	unp = VTOUNIONFS(vp);
794 	lvp = unp->un_lowervp;
795 	uvp = unp->un_uppervp;
796 	unsp = unionfs_find_node_status(unp, td);
797 
798 	if (unsp == NULL ||
799 	    (unsp->uns_lower_opencnt <= 0 && unsp->uns_upper_opencnt <= 0)) {
800 #ifdef DIAGNOSTIC
801 		if (unsp != NULL)
802 			printf("unionfs_close: warning: open count is 0\n");
803 #endif
804 		if (uvp != NULLVP)
805 			ovp = uvp;
806 		else
807 			ovp = lvp;
808 	} else if (unsp->uns_upper_opencnt > 0)
809 		ovp = uvp;
810 	else
811 		ovp = lvp;
812 
813 	if (ovp == lvp && uvp != NULLVP) {
814 		lock_lvp = true;
815 		unp = NULL;
816 		lvp = unionfs_lock_lvp(vp, &lkflags);
817 		if (lvp == NULLVP) {
818 			error = ENOENT;
819 			goto unionfs_close_abort;
820 		}
821 	} else
822 		unionfs_forward_vop_start(ovp, &lkflags);
823 
824 	error = VOP_CLOSE(ovp, ap->a_fflag, cred, td);
825 
826 	if (lock_lvp) {
827 		unp = unionfs_unlock_lvp(vp, lvp, lkflags);
828 		if (unp == NULL && error == 0)
829 			error = ENOENT;
830 	} else if (unionfs_forward_vop_finish(vp, ovp, lkflags))
831 		error = error ? error : ENOENT;
832 
833 	if (error != 0)
834 		goto unionfs_close_abort;
835 
836 	vp->v_object = ovp->v_object;
837 
838 	if (ovp == uvp) {
839 		if (unsp != NULL && ((--unsp->uns_upper_opencnt) == 0)) {
840 			if (unsp->uns_node_flag & UNS_OPENL_4_READDIR) {
841 				unp = NULL;
842 				lvp = unionfs_lock_lvp(vp, &lkflags);
843 				if (lvp == NULLVP) {
844 					error = ENOENT;
845 					goto unionfs_close_abort;
846 				}
847 				VOP_CLOSE(lvp, FREAD, cred, td);
848 				unp = unionfs_unlock_lvp(vp, lvp, lkflags);
849 				if (unp == NULL) {
850 					error = ENOENT;
851 					goto unionfs_close_abort;
852 				}
853 				unsp->uns_node_flag &= ~UNS_OPENL_4_READDIR;
854 				unsp->uns_lower_opencnt--;
855 			}
856 			if (unsp->uns_lower_opencnt > 0)
857 				vp->v_object = lvp->v_object;
858 		}
859 	} else if (unsp != NULL)
860 		unsp->uns_lower_opencnt--;
861 
862 unionfs_close_abort:
863 	if (unp != NULL && unsp != NULL)
864 		unionfs_tryrem_node_status(unp, unsp);
865 
866 unionfs_close_cleanup:
867 	unionfs_downgrade_lock(vp, lkstatus);
868 
869 	UNIONFS_INTERNAL_DEBUG("unionfs_close: leave (%d)\n", error);
870 
871 	return (error);
872 }
873 
874 /*
875  * Check the access mode toward shadow file/dir.
876  */
877 static int
unionfs_check_corrected_access(accmode_t accmode,struct vattr * va,struct ucred * cred)878 unionfs_check_corrected_access(accmode_t accmode, struct vattr *va,
879     struct ucred *cred)
880 {
881 	uid_t		uid;	/* upper side vnode's uid */
882 	gid_t		gid;	/* upper side vnode's gid */
883 	u_short		vmode;	/* upper side vnode's mode */
884 	u_short		mask;
885 
886 	mask = 0;
887 	uid = va->va_uid;
888 	gid = va->va_gid;
889 	vmode = va->va_mode;
890 
891 	/* check owner */
892 	if (cred->cr_uid == uid) {
893 		if (accmode & VEXEC)
894 			mask |= S_IXUSR;
895 		if (accmode & VREAD)
896 			mask |= S_IRUSR;
897 		if (accmode & VWRITE)
898 			mask |= S_IWUSR;
899 		return ((vmode & mask) == mask ? 0 : EACCES);
900 	}
901 
902 	/* check group */
903 	if (groupmember(gid, cred)) {
904 		if (accmode & VEXEC)
905 			mask |= S_IXGRP;
906 		if (accmode & VREAD)
907 			mask |= S_IRGRP;
908 		if (accmode & VWRITE)
909 			mask |= S_IWGRP;
910 		return ((vmode & mask) == mask ? 0 : EACCES);
911 	}
912 
913 	/* check other */
914 	if (accmode & VEXEC)
915 		mask |= S_IXOTH;
916 	if (accmode & VREAD)
917 		mask |= S_IROTH;
918 	if (accmode & VWRITE)
919 		mask |= S_IWOTH;
920 
921 	return ((vmode & mask) == mask ? 0 : EACCES);
922 }
923 
924 static int
unionfs_access(struct vop_access_args * ap)925 unionfs_access(struct vop_access_args *ap)
926 {
927 	struct unionfs_mount *ump;
928 	struct unionfs_node *unp;
929 	struct vnode   *uvp;
930 	struct vnode   *lvp;
931 	struct thread  *td;
932 	struct vattr	va;
933 	accmode_t	accmode;
934 	int		error;
935 
936 	UNIONFS_INTERNAL_DEBUG("unionfs_access: enter\n");
937 
938 	KASSERT_UNIONFS_VNODE(ap->a_vp);
939 
940 	ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount);
941 	unp = VTOUNIONFS(ap->a_vp);
942 	uvp = unp->un_uppervp;
943 	lvp = unp->un_lowervp;
944 	td = ap->a_td;
945 	accmode = ap->a_accmode;
946 	error = EACCES;
947 
948 	if ((accmode & VWRITE) &&
949 	    (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)) {
950 		switch (ap->a_vp->v_type) {
951 		case VREG:
952 		case VDIR:
953 		case VLNK:
954 			return (EROFS);
955 		default:
956 			break;
957 		}
958 	}
959 
960 	if (uvp != NULLVP) {
961 		error = VOP_ACCESS(uvp, accmode, ap->a_cred, td);
962 
963 		UNIONFS_INTERNAL_DEBUG("unionfs_access: leave (%d)\n", error);
964 
965 		return (error);
966 	}
967 
968 	if (lvp != NULLVP) {
969 		if (accmode & VWRITE) {
970 			if ((ump->um_uppermp->mnt_flag & MNT_RDONLY) != 0) {
971 				switch (ap->a_vp->v_type) {
972 				case VREG:
973 				case VDIR:
974 				case VLNK:
975 					return (EROFS);
976 				default:
977 					break;
978 				}
979 			} else if (ap->a_vp->v_type == VREG ||
980 			    ap->a_vp->v_type == VDIR) {
981 				/* check shadow file/dir */
982 				if (ump->um_copymode != UNIONFS_TRANSPARENT) {
983 					error = unionfs_create_uppervattr(ump,
984 					    lvp, &va, ap->a_cred, td);
985 					if (error != 0)
986 						return (error);
987 
988 					error = unionfs_check_corrected_access(
989 					    accmode, &va, ap->a_cred);
990 					if (error != 0)
991 						return (error);
992 				}
993 			}
994 			accmode &= ~(VWRITE | VAPPEND);
995 			accmode |= VREAD; /* will copy to upper */
996 		}
997 		error = VOP_ACCESS(lvp, accmode, ap->a_cred, td);
998 	}
999 
1000 	UNIONFS_INTERNAL_DEBUG("unionfs_access: leave (%d)\n", error);
1001 
1002 	return (error);
1003 }
1004 
1005 static int
unionfs_getattr(struct vop_getattr_args * ap)1006 unionfs_getattr(struct vop_getattr_args *ap)
1007 {
1008 	struct unionfs_node *unp;
1009 	struct unionfs_mount *ump;
1010 	struct vnode   *uvp;
1011 	struct vnode   *lvp;
1012 	struct thread  *td;
1013 	struct vattr	va;
1014 	int		error;
1015 
1016 	UNIONFS_INTERNAL_DEBUG("unionfs_getattr: enter\n");
1017 
1018 	KASSERT_UNIONFS_VNODE(ap->a_vp);
1019 
1020 	unp = VTOUNIONFS(ap->a_vp);
1021 	ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount);
1022 	uvp = unp->un_uppervp;
1023 	lvp = unp->un_lowervp;
1024 	td = curthread;
1025 
1026 	if (uvp != NULLVP) {
1027 		if ((error = VOP_GETATTR(uvp, ap->a_vap, ap->a_cred)) == 0)
1028 			ap->a_vap->va_fsid =
1029 			    ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
1030 
1031 		UNIONFS_INTERNAL_DEBUG(
1032 		    "unionfs_getattr: leave mode=%o, uid=%d, gid=%d (%d)\n",
1033 		    ap->a_vap->va_mode, ap->a_vap->va_uid,
1034 		    ap->a_vap->va_gid, error);
1035 
1036 		return (error);
1037 	}
1038 
1039 	error = VOP_GETATTR(lvp, ap->a_vap, ap->a_cred);
1040 
1041 	if (error == 0 && (ump->um_uppermp->mnt_flag & MNT_RDONLY) == 0) {
1042 		/* correct the attr toward shadow file/dir. */
1043 		if (ap->a_vp->v_type == VREG || ap->a_vp->v_type == VDIR) {
1044 			unionfs_create_uppervattr_core(ump, ap->a_vap, &va, td);
1045 			ap->a_vap->va_mode = va.va_mode;
1046 			ap->a_vap->va_uid = va.va_uid;
1047 			ap->a_vap->va_gid = va.va_gid;
1048 		}
1049 	}
1050 
1051 	if (error == 0)
1052 		ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
1053 
1054 	UNIONFS_INTERNAL_DEBUG(
1055 	    "unionfs_getattr: leave mode=%o, uid=%d, gid=%d (%d)\n",
1056 	    ap->a_vap->va_mode, ap->a_vap->va_uid, ap->a_vap->va_gid, error);
1057 
1058 	return (error);
1059 }
1060 
1061 static int
unionfs_setattr(struct vop_setattr_args * ap)1062 unionfs_setattr(struct vop_setattr_args *ap)
1063 {
1064 	struct unionfs_node *unp;
1065 	struct vnode   *uvp;
1066 	struct vnode   *lvp;
1067 	struct thread  *td;
1068 	struct vattr   *vap;
1069 	int		error;
1070 
1071 	UNIONFS_INTERNAL_DEBUG("unionfs_setattr: enter\n");
1072 
1073 	KASSERT_UNIONFS_VNODE(ap->a_vp);
1074 
1075 	error = EROFS;
1076 	unp = VTOUNIONFS(ap->a_vp);
1077 	uvp = unp->un_uppervp;
1078 	lvp = unp->un_lowervp;
1079 	td = curthread;
1080 	vap = ap->a_vap;
1081 
1082 	if ((ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) &&
1083 	    (vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
1084 	     vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
1085 	     vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL))
1086 		return (EROFS);
1087 
1088 	if (uvp == NULLVP && lvp->v_type == VREG) {
1089 		error = unionfs_copyfile(ap->a_vp, (vap->va_size != 0),
1090 		    ap->a_cred, td);
1091 		if (error != 0)
1092 			return (error);
1093 		uvp = unp->un_uppervp;
1094 	}
1095 
1096 	if (uvp != NULLVP) {
1097 		int lkflags;
1098 		unionfs_forward_vop_start(uvp, &lkflags);
1099 		error = VOP_SETATTR(uvp, vap, ap->a_cred);
1100 		unionfs_forward_vop_finish(ap->a_vp, uvp, lkflags);
1101 	}
1102 
1103 	UNIONFS_INTERNAL_DEBUG("unionfs_setattr: leave (%d)\n", error);
1104 
1105 	return (error);
1106 }
1107 
1108 static int
unionfs_read(struct vop_read_args * ap)1109 unionfs_read(struct vop_read_args *ap)
1110 {
1111 	struct unionfs_node *unp;
1112 	struct vnode   *tvp;
1113 	int		error;
1114 
1115 	/* UNIONFS_INTERNAL_DEBUG("unionfs_read: enter\n"); */
1116 
1117 	KASSERT_UNIONFS_VNODE(ap->a_vp);
1118 
1119 	unp = VTOUNIONFS(ap->a_vp);
1120 	tvp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp);
1121 
1122 	error = VOP_READ(tvp, ap->a_uio, ap->a_ioflag, ap->a_cred);
1123 
1124 	/* UNIONFS_INTERNAL_DEBUG("unionfs_read: leave (%d)\n", error); */
1125 
1126 	return (error);
1127 }
1128 
1129 static int
unionfs_write(struct vop_write_args * ap)1130 unionfs_write(struct vop_write_args *ap)
1131 {
1132 	struct unionfs_node *unp;
1133 	struct vnode   *tvp;
1134 	int		error;
1135 	int		lkflags;
1136 
1137 	/* UNIONFS_INTERNAL_DEBUG("unionfs_write: enter\n"); */
1138 
1139 	KASSERT_UNIONFS_VNODE(ap->a_vp);
1140 
1141 	unp = VTOUNIONFS(ap->a_vp);
1142 	tvp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp);
1143 
1144 	unionfs_forward_vop_start(tvp, &lkflags);
1145 	error = VOP_WRITE(tvp, ap->a_uio, ap->a_ioflag, ap->a_cred);
1146 	unionfs_forward_vop_finish(ap->a_vp, tvp, lkflags);
1147 
1148 	/* UNIONFS_INTERNAL_DEBUG("unionfs_write: leave (%d)\n", error); */
1149 
1150 	return (error);
1151 }
1152 
1153 static int
unionfs_ioctl(struct vop_ioctl_args * ap)1154 unionfs_ioctl(struct vop_ioctl_args *ap)
1155 {
1156 	struct unionfs_node *unp;
1157 	struct unionfs_node_status *unsp;
1158 	struct vnode   *ovp;
1159 	int error;
1160 
1161 	UNIONFS_INTERNAL_DEBUG("unionfs_ioctl: enter\n");
1162 
1163 	KASSERT_UNIONFS_VNODE(ap->a_vp);
1164 
1165  	vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY);
1166 	unp = VTOUNIONFS(ap->a_vp);
1167 	unionfs_get_node_status(unp, ap->a_td, &unsp);
1168 	ovp = (unsp->uns_upper_opencnt ? unp->un_uppervp : unp->un_lowervp);
1169 	unionfs_tryrem_node_status(unp, unsp);
1170 	VOP_UNLOCK(ap->a_vp);
1171 
1172 	if (ovp == NULLVP)
1173 		return (EBADF);
1174 
1175 	error = VOP_IOCTL(ovp, ap->a_command, ap->a_data, ap->a_fflag,
1176 	    ap->a_cred, ap->a_td);
1177 
1178 	UNIONFS_INTERNAL_DEBUG("unionfs_ioctl: leave (%d)\n", error);
1179 
1180 	return (error);
1181 }
1182 
1183 static int
unionfs_poll(struct vop_poll_args * ap)1184 unionfs_poll(struct vop_poll_args *ap)
1185 {
1186 	struct unionfs_node *unp;
1187 	struct unionfs_node_status *unsp;
1188 	struct vnode *ovp;
1189 
1190 	KASSERT_UNIONFS_VNODE(ap->a_vp);
1191 
1192  	vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY);
1193 	unp = VTOUNIONFS(ap->a_vp);
1194 	unionfs_get_node_status(unp, ap->a_td, &unsp);
1195 	ovp = (unsp->uns_upper_opencnt ? unp->un_uppervp : unp->un_lowervp);
1196 	unionfs_tryrem_node_status(unp, unsp);
1197 	VOP_UNLOCK(ap->a_vp);
1198 
1199 	if (ovp == NULLVP)
1200 		return (EBADF);
1201 
1202 	return (VOP_POLL(ovp, ap->a_events, ap->a_cred, ap->a_td));
1203 }
1204 
1205 static int
unionfs_fsync(struct vop_fsync_args * ap)1206 unionfs_fsync(struct vop_fsync_args *ap)
1207 {
1208 	struct unionfs_node *unp;
1209 	struct unionfs_node_status *unsp;
1210 	struct vnode *ovp;
1211 	enum unionfs_lkupgrade lkstatus;
1212 	int error, lkflags;
1213 
1214 	KASSERT_UNIONFS_VNODE(ap->a_vp);
1215 
1216 	unp = VTOUNIONFS(ap->a_vp);
1217 	lkstatus = unionfs_upgrade_lock(ap->a_vp);
1218 	if (lkstatus == UNIONFS_LKUPGRADE_DOOMED) {
1219 		unionfs_downgrade_lock(ap->a_vp, lkstatus);
1220 		return (ENOENT);
1221 	}
1222 	unionfs_get_node_status(unp, ap->a_td, &unsp);
1223 	ovp = (unsp->uns_upper_opencnt ? unp->un_uppervp : unp->un_lowervp);
1224 	unionfs_tryrem_node_status(unp, unsp);
1225 
1226 	unionfs_downgrade_lock(ap->a_vp, lkstatus);
1227 
1228 	if (ovp == NULLVP)
1229 		return (EBADF);
1230 
1231 	unionfs_forward_vop_start(ovp, &lkflags);
1232 	error = VOP_FSYNC(ovp, ap->a_waitfor, ap->a_td);
1233 	unionfs_forward_vop_finish(ap->a_vp, ovp, lkflags);
1234 
1235 	return (error);
1236 }
1237 
1238 static int
unionfs_remove(struct vop_remove_args * ap)1239 unionfs_remove(struct vop_remove_args *ap)
1240 {
1241 	char	       *path;
1242 	struct unionfs_node *dunp;
1243 	struct unionfs_node *unp;
1244 	struct unionfs_mount *ump;
1245 	struct vnode   *udvp;
1246 	struct vnode   *uvp;
1247 	struct vnode   *lvp;
1248 	struct componentname *cnp;
1249 	struct thread  *td;
1250 	int		error;
1251 	int		pathlen;
1252 
1253 	UNIONFS_INTERNAL_DEBUG("unionfs_remove: enter\n");
1254 
1255 	KASSERT_UNIONFS_VNODE(ap->a_dvp);
1256 	KASSERT_UNIONFS_VNODE(ap->a_vp);
1257 
1258 	error = 0;
1259 	dunp = VTOUNIONFS(ap->a_dvp);
1260 	udvp = dunp->un_uppervp;
1261 	cnp = ap->a_cnp;
1262 	td = curthread;
1263 
1264 	ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount);
1265 	unp = VTOUNIONFS(ap->a_vp);
1266 	uvp = unp->un_uppervp;
1267 	lvp = unp->un_lowervp;
1268 	path = unp->un_path;
1269 	pathlen = unp->un_pathlen;
1270 
1271 	if (udvp == NULLVP)
1272 		return (EROFS);
1273 
1274 	if (uvp != NULLVP) {
1275 		int udvp_lkflags, uvp_lkflags;
1276 		if (ump == NULL || ump->um_whitemode == UNIONFS_WHITE_ALWAYS ||
1277 		    lvp != NULLVP)
1278 			cnp->cn_flags |= DOWHITEOUT;
1279 		unionfs_forward_vop_start_pair(udvp, &udvp_lkflags,
1280 		    uvp, &uvp_lkflags);
1281 		error = VOP_REMOVE(udvp, uvp, cnp);
1282 		unionfs_forward_vop_finish_pair(ap->a_dvp, udvp, udvp_lkflags,
1283 		    ap->a_vp, uvp, uvp_lkflags);
1284 	} else if (lvp != NULLVP) {
1285 		error = unionfs_mkwhiteout(ap->a_dvp, ap->a_vp, cnp, td,
1286 		    path, pathlen);
1287 	}
1288 
1289 	UNIONFS_INTERNAL_DEBUG("unionfs_remove: leave (%d)\n", error);
1290 
1291 	return (error);
1292 }
1293 
1294 static int
unionfs_link(struct vop_link_args * ap)1295 unionfs_link(struct vop_link_args *ap)
1296 {
1297 	struct unionfs_node *dunp;
1298 	struct unionfs_node *unp;
1299 	struct vnode   *udvp;
1300 	struct vnode   *uvp;
1301 	struct componentname *cnp;
1302 	struct thread  *td;
1303 	int		error;
1304 
1305 	UNIONFS_INTERNAL_DEBUG("unionfs_link: enter\n");
1306 
1307 	KASSERT_UNIONFS_VNODE(ap->a_tdvp);
1308 	KASSERT_UNIONFS_VNODE(ap->a_vp);
1309 
1310 	error = 0;
1311 	dunp = VTOUNIONFS(ap->a_tdvp);
1312 	unp = NULL;
1313 	udvp = dunp->un_uppervp;
1314 	uvp = NULLVP;
1315 	cnp = ap->a_cnp;
1316 	td = curthread;
1317 
1318 	if (udvp == NULLVP)
1319 		return (EROFS);
1320 
1321 	unp = VTOUNIONFS(ap->a_vp);
1322 
1323 	if (unp->un_uppervp == NULLVP) {
1324 		if (ap->a_vp->v_type != VREG)
1325 			return (EOPNOTSUPP);
1326 
1327 		VOP_UNLOCK(ap->a_tdvp);
1328 		error = unionfs_copyfile(ap->a_vp, 1, cnp->cn_cred, td);
1329 		vn_lock(ap->a_tdvp, LK_EXCLUSIVE | LK_RETRY);
1330 		if (error == 0)
1331 			error = ERELOOKUP;
1332 		return (error);
1333 	}
1334 	uvp = unp->un_uppervp;
1335 
1336 	if (error == 0) {
1337 		int udvp_lkflags, uvp_lkflags;
1338 		unionfs_forward_vop_start_pair(udvp, &udvp_lkflags,
1339 		    uvp, &uvp_lkflags);
1340 		error = VOP_LINK(udvp, uvp, cnp);
1341 		unionfs_forward_vop_finish_pair(ap->a_tdvp, udvp, udvp_lkflags,
1342 		    ap->a_vp, uvp, uvp_lkflags);
1343 	}
1344 
1345 	UNIONFS_INTERNAL_DEBUG("unionfs_link: leave (%d)\n", error);
1346 
1347 	return (error);
1348 }
1349 
1350 static int
unionfs_rename(struct vop_rename_args * ap)1351 unionfs_rename(struct vop_rename_args *ap)
1352 {
1353 	struct vnode   *fdvp;
1354 	struct vnode   *fvp;
1355 	struct componentname *fcnp;
1356 	struct vnode   *tdvp;
1357 	struct vnode   *tvp;
1358 	struct componentname *tcnp;
1359 	struct thread  *td;
1360 
1361 	/* rename target vnodes */
1362 	struct vnode   *rfdvp;
1363 	struct vnode   *rfvp;
1364 	struct vnode   *rtdvp;
1365 	struct vnode   *rtvp;
1366 
1367 	struct unionfs_node *unp;
1368 	int		error;
1369 
1370 	UNIONFS_INTERNAL_DEBUG("unionfs_rename: enter\n");
1371 
1372 	error = 0;
1373 	fdvp = ap->a_fdvp;
1374 	fvp = ap->a_fvp;
1375 	fcnp = ap->a_fcnp;
1376 	tdvp = ap->a_tdvp;
1377 	tvp = ap->a_tvp;
1378 	tcnp = ap->a_tcnp;
1379 	td = curthread;
1380 	rfdvp = fdvp;
1381 	rfvp = fvp;
1382 	rtdvp = tdvp;
1383 	rtvp = tvp;
1384 
1385 	/* check for cross device rename */
1386 	if (fvp->v_mount != tdvp->v_mount ||
1387 	    (tvp != NULLVP && fvp->v_mount != tvp->v_mount)) {
1388 		if (fvp->v_op != &unionfs_vnodeops)
1389 			error = ENODEV;
1390 		else
1391 			error = EXDEV;
1392 		goto unionfs_rename_abort;
1393 	}
1394 
1395 	/* Renaming a file to itself has no effect. */
1396 	if (fvp == tvp)
1397 		goto unionfs_rename_abort;
1398 
1399 	KASSERT_UNIONFS_VNODE(tdvp);
1400 	if (tvp != NULLVP)
1401 		KASSERT_UNIONFS_VNODE(tvp);
1402 	if (fdvp != tdvp)
1403 		VI_LOCK(fdvp);
1404 	unp = VTOUNIONFS(fdvp);
1405 	if (unp == NULL) {
1406 		if (fdvp != tdvp)
1407 			VI_UNLOCK(fdvp);
1408 		error = ENOENT;
1409 		goto unionfs_rename_abort;
1410 	}
1411 #ifdef UNIONFS_IDBG_RENAME
1412 	UNIONFS_INTERNAL_DEBUG("fdvp=%p, ufdvp=%p, lfdvp=%p\n",
1413 	    fdvp, unp->un_uppervp, unp->un_lowervp);
1414 #endif
1415 	if (unp->un_uppervp == NULLVP) {
1416 		error = ENODEV;
1417 	} else {
1418 		rfdvp = unp->un_uppervp;
1419 		vref(rfdvp);
1420 	}
1421 	if (fdvp != tdvp)
1422 		VI_UNLOCK(fdvp);
1423 	if (error != 0)
1424 		goto unionfs_rename_abort;
1425 
1426 	VI_LOCK(fvp);
1427 	unp = VTOUNIONFS(fvp);
1428 	if (unp == NULL) {
1429 		VI_UNLOCK(fvp);
1430 		error = ENOENT;
1431 		goto unionfs_rename_abort;
1432 	}
1433 
1434 #ifdef UNIONFS_IDBG_RENAME
1435 	UNIONFS_INTERNAL_DEBUG("fvp=%p, ufvp=%p, lfvp=%p\n",
1436 	    fvp, unp->un_uppervp, unp->un_lowervp);
1437 #endif
1438 	/*
1439 	 * If we only have a lower vnode, copy the source file to the upper
1440 	 * FS so that the rename operation can be issued against the upper FS.
1441 	 */
1442 	if (unp->un_uppervp == NULLVP) {
1443 		bool unlock_fdvp = false, relock_tdvp = false;
1444 		VI_UNLOCK(fvp);
1445 		if (tvp != NULLVP)
1446 			VOP_UNLOCK(tvp);
1447 		if (fvp->v_type == VREG) {
1448 			/*
1449 			 * For regular files, unionfs_copyfile() will expect
1450 			 * fdvp's upper parent directory vnode to be unlocked
1451 			 * and will temporarily lock it.  If fdvp == tdvp, we
1452 			 * should unlock tdvp to avoid recursion on tdvp's
1453 			 * lock.  If fdvp != tdvp, we should also unlock tdvp
1454 			 * to avoid potential deadlock due to holding tdvp's
1455 			 * lock while locking unrelated vnodes associated with
1456 			 * fdvp/fvp.
1457 			 */
1458 			VOP_UNLOCK(tdvp);
1459 			relock_tdvp = true;
1460 		} else if (fvp->v_type == VDIR && tdvp != fdvp) {
1461 			/*
1462 			 * For directories, unionfs_mkshadowdir() will expect
1463 			 * fdvp's upper parent directory vnode to be locked
1464 			 * and will temporarily unlock it.  If fdvp == tdvp,
1465 			 * we can therefore leave tdvp locked.  If fdvp !=
1466 			 * tdvp, we should exchange the lock on tdvp for a
1467 			 * lock on fdvp.
1468 			 */
1469 			VOP_UNLOCK(tdvp);
1470 			unlock_fdvp = true;
1471 			relock_tdvp = true;
1472 			vn_lock(fdvp, LK_EXCLUSIVE | LK_RETRY);
1473 		}
1474 		vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY);
1475 		unp = VTOUNIONFS(fvp);
1476 		if (unp == NULL)
1477 			error = ENOENT;
1478 		else if (unp->un_uppervp == NULLVP) {
1479 			switch (fvp->v_type) {
1480 			case VREG:
1481 				error = unionfs_copyfile(fvp, 1, fcnp->cn_cred, td);
1482 				break;
1483 			case VDIR:
1484 				error = unionfs_mkshadowdir(fdvp, fvp, fcnp, td);
1485 				break;
1486 			default:
1487 				error = ENODEV;
1488 				break;
1489 			}
1490 		}
1491 		VOP_UNLOCK(fvp);
1492 		if (unlock_fdvp)
1493 			VOP_UNLOCK(fdvp);
1494 		if (relock_tdvp)
1495 			vn_lock(tdvp, LK_EXCLUSIVE | LK_RETRY);
1496 		if (tvp != NULLVP)
1497 			vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY);
1498 		/*
1499 		 * Since we've dropped tdvp's lock at some point in the copy
1500 		 * sequence above, force the caller to re-drive the lookup
1501 		 * in case the relationship between tdvp and tvp has changed.
1502 		 */
1503 		if (error == 0)
1504 			error = ERELOOKUP;
1505 		goto unionfs_rename_abort;
1506 	}
1507 
1508 	if (unp->un_lowervp != NULLVP)
1509 		fcnp->cn_flags |= DOWHITEOUT;
1510 	rfvp = unp->un_uppervp;
1511 	vref(rfvp);
1512 
1513 	VI_UNLOCK(fvp);
1514 
1515 	unp = VTOUNIONFS(tdvp);
1516 
1517 #ifdef UNIONFS_IDBG_RENAME
1518 	UNIONFS_INTERNAL_DEBUG("tdvp=%p, utdvp=%p, ltdvp=%p\n",
1519 	    tdvp, unp->un_uppervp, unp->un_lowervp);
1520 #endif
1521 	if (unp->un_uppervp == NULLVP) {
1522 		error = ENODEV;
1523 		goto unionfs_rename_abort;
1524 	}
1525 	rtdvp = unp->un_uppervp;
1526 	vref(rtdvp);
1527 
1528 	if (tvp != NULLVP) {
1529 		unp = VTOUNIONFS(tvp);
1530 		if (unp == NULL) {
1531 			error = ENOENT;
1532 			goto unionfs_rename_abort;
1533 		}
1534 #ifdef UNIONFS_IDBG_RENAME
1535 		UNIONFS_INTERNAL_DEBUG("tvp=%p, utvp=%p, ltvp=%p\n",
1536 		    tvp, unp->un_uppervp, unp->un_lowervp);
1537 #endif
1538 		if (unp->un_uppervp == NULLVP)
1539 			rtvp = NULLVP;
1540 		else {
1541 			if (tvp->v_type == VDIR) {
1542 				error = EINVAL;
1543 				goto unionfs_rename_abort;
1544 			}
1545 			rtvp = unp->un_uppervp;
1546 			vref(rtvp);
1547 		}
1548 	}
1549 
1550 	if (rfvp == rtvp)
1551 		goto unionfs_rename_abort;
1552 
1553 	error = VOP_RENAME(rfdvp, rfvp, fcnp, rtdvp, rtvp, tcnp);
1554 
1555 	if (error == 0) {
1556 		if (rtvp != NULLVP && rtvp->v_type == VDIR)
1557 			cache_purge(tdvp);
1558 		if (fvp->v_type == VDIR && fdvp != tdvp)
1559 			cache_purge(fdvp);
1560 	}
1561 
1562 	if (tdvp != rtdvp)
1563 		vrele(tdvp);
1564 	if (tvp != rtvp && tvp != NULLVP) {
1565 		if (rtvp == NULLVP)
1566 			vput(tvp);
1567 		else
1568 			vrele(tvp);
1569 	}
1570 	if (fdvp != rfdvp)
1571 		vrele(fdvp);
1572 	if (fvp != rfvp)
1573 		vrele(fvp);
1574 
1575 	UNIONFS_INTERNAL_DEBUG("unionfs_rename: leave (%d)\n", error);
1576 
1577 	return (error);
1578 
1579 unionfs_rename_abort:
1580 	vput(tdvp);
1581 	if (tdvp != rtdvp)
1582 		vrele(rtdvp);
1583 	if (tvp != NULLVP) {
1584 		if (tdvp != tvp)
1585 			vput(tvp);
1586 		else
1587 			vrele(tvp);
1588 	}
1589 	if (tvp != rtvp && rtvp != NULLVP)
1590 		vrele(rtvp);
1591 	if (fdvp != rfdvp)
1592 		vrele(rfdvp);
1593 	if (fvp != rfvp)
1594 		vrele(rfvp);
1595 	vrele(fdvp);
1596 	vrele(fvp);
1597 
1598 	UNIONFS_INTERNAL_DEBUG("unionfs_rename: leave (%d)\n", error);
1599 
1600 	return (error);
1601 }
1602 
1603 static int
unionfs_mkdir(struct vop_mkdir_args * ap)1604 unionfs_mkdir(struct vop_mkdir_args *ap)
1605 {
1606 	struct unionfs_node *dunp;
1607 	struct componentname *cnp;
1608 	struct vnode   *dvp;
1609 	struct vnode   *udvp;
1610 	struct vnode   *uvp;
1611 	struct vattr	va;
1612 	int		error;
1613 	int		lkflags;
1614 
1615 	UNIONFS_INTERNAL_DEBUG("unionfs_mkdir: enter\n");
1616 
1617 	KASSERT_UNIONFS_VNODE(ap->a_dvp);
1618 
1619 	error = EROFS;
1620 	dvp = ap->a_dvp;
1621 	dunp = VTOUNIONFS(dvp);
1622 	cnp = ap->a_cnp;
1623 	lkflags = cnp->cn_lkflags;
1624 	udvp = dunp->un_uppervp;
1625 
1626 	if (udvp != NULLVP) {
1627 		/* check opaque */
1628 		if (!(cnp->cn_flags & ISWHITEOUT)) {
1629 			error = VOP_GETATTR(udvp, &va, cnp->cn_cred);
1630 			if (error != 0)
1631 				goto unionfs_mkdir_cleanup;
1632 			if ((va.va_flags & OPAQUE) != 0)
1633 				cnp->cn_flags |= ISWHITEOUT;
1634 		}
1635 
1636 		int udvp_lkflags;
1637 		bool uvp_created = false;
1638 		unionfs_forward_vop_start(udvp, &udvp_lkflags);
1639 		error = VOP_MKDIR(udvp, &uvp, cnp, ap->a_vap);
1640 		if (error == 0)
1641 			uvp_created = true;
1642 		if (__predict_false(unionfs_forward_vop_finish(dvp, udvp,
1643 		    udvp_lkflags)) && error == 0)
1644 			error = ENOENT;
1645 		if (error == 0) {
1646 			VOP_UNLOCK(uvp);
1647 			cnp->cn_lkflags = LK_EXCLUSIVE;
1648 			error = unionfs_nodeget(dvp->v_mount, uvp, NULLVP,
1649 			    dvp, ap->a_vpp, cnp);
1650 			vrele(uvp);
1651 			cnp->cn_lkflags = lkflags;
1652 		} else if (uvp_created)
1653 			vput(uvp);
1654 	}
1655 
1656 unionfs_mkdir_cleanup:
1657 	UNIONFS_INTERNAL_DEBUG("unionfs_mkdir: leave (%d)\n", error);
1658 
1659 	return (error);
1660 }
1661 
1662 static int
unionfs_rmdir(struct vop_rmdir_args * ap)1663 unionfs_rmdir(struct vop_rmdir_args *ap)
1664 {
1665 	struct unionfs_node *dunp;
1666 	struct unionfs_node *unp;
1667 	struct unionfs_mount *ump;
1668 	struct componentname *cnp;
1669 	struct thread  *td;
1670 	struct vnode   *udvp;
1671 	struct vnode   *uvp;
1672 	struct vnode   *lvp;
1673 	int		error;
1674 
1675 	UNIONFS_INTERNAL_DEBUG("unionfs_rmdir: enter\n");
1676 
1677 	KASSERT_UNIONFS_VNODE(ap->a_dvp);
1678 	KASSERT_UNIONFS_VNODE(ap->a_vp);
1679 
1680 	error = 0;
1681 	dunp = VTOUNIONFS(ap->a_dvp);
1682 	unp = VTOUNIONFS(ap->a_vp);
1683 	cnp = ap->a_cnp;
1684 	td = curthread;
1685 	udvp = dunp->un_uppervp;
1686 	uvp = unp->un_uppervp;
1687 	lvp = unp->un_lowervp;
1688 
1689 	if (udvp == NULLVP)
1690 		return (EROFS);
1691 
1692 	if (udvp == uvp)
1693 		return (EOPNOTSUPP);
1694 
1695 	if (uvp != NULLVP) {
1696 		if (lvp != NULLVP) {
1697 			/*
1698 			 * We need to keep dvp and vp's upper vnodes locked
1699 			 * going into the VOP_RMDIR() call, but the empty
1700 			 * directory check also requires the lower vnode lock.
1701 			 * For this third, cross-filesystem lock we use a
1702 			 * similar approach taken by various FS' VOP_RENAME
1703 			 * implementations (which require 2-4 vnode locks).
1704 			 * First we attempt a NOWAIT acquisition, then if
1705 			 * that fails we drops the other two vnode locks,
1706 			 * acquire lvp's lock in the normal fashion to reduce
1707 			 * the likelihood of spinning on it in the future,
1708 			 * then drop, reacquire the other locks, and return
1709 			 * ERELOOKUP to re-drive the lookup in case the dvp->
1710 			 * vp relationship has changed.
1711 			 */
1712 			if (vn_lock(lvp, LK_SHARED | LK_NOWAIT) != 0) {
1713 				VOP_UNLOCK(ap->a_vp);
1714 				VOP_UNLOCK(ap->a_dvp);
1715 				vn_lock(lvp, LK_SHARED | LK_RETRY);
1716 				VOP_UNLOCK(lvp);
1717 				vn_lock(ap->a_dvp, LK_EXCLUSIVE | LK_RETRY);
1718 				vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY);
1719 				return (ERELOOKUP);
1720 			}
1721 			error = unionfs_check_rmdir(ap->a_vp, cnp->cn_cred, td);
1722 			/*
1723 			 * It's possible for a direct operation on the lower FS
1724 			 * to make the lower directory non-empty after we drop
1725 			 * the lock, but it's also possible for the upper-layer
1726 			 * VOP_RMDIR to relock udvp/uvp which would lead to
1727 			 * LOR if we kept lvp locked across that call.
1728 			 */
1729 			VOP_UNLOCK(lvp);
1730 			if (error != 0)
1731 				return (error);
1732 		}
1733 		ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount);
1734 		if (ump->um_whitemode == UNIONFS_WHITE_ALWAYS || lvp != NULLVP)
1735 			cnp->cn_flags |= (DOWHITEOUT | IGNOREWHITEOUT);
1736 		int udvp_lkflags, uvp_lkflags;
1737 		unionfs_forward_vop_start_pair(udvp, &udvp_lkflags,
1738 		    uvp, &uvp_lkflags);
1739 		error = VOP_RMDIR(udvp, uvp, cnp);
1740 		unionfs_forward_vop_finish_pair(ap->a_dvp, udvp, udvp_lkflags,
1741 		    ap->a_vp, uvp, uvp_lkflags);
1742 	} else if (lvp != NULLVP) {
1743 		error = unionfs_mkwhiteout(ap->a_dvp, ap->a_vp, cnp, td,
1744 		    unp->un_path, unp->un_pathlen);
1745 	}
1746 
1747 	if (error == 0) {
1748 		cache_purge(ap->a_dvp);
1749 		cache_purge(ap->a_vp);
1750 	}
1751 
1752 	UNIONFS_INTERNAL_DEBUG("unionfs_rmdir: leave (%d)\n", error);
1753 
1754 	return (error);
1755 }
1756 
1757 static int
unionfs_symlink(struct vop_symlink_args * ap)1758 unionfs_symlink(struct vop_symlink_args *ap)
1759 {
1760 	struct unionfs_node *dunp;
1761 	struct componentname *cnp;
1762 	struct vnode   *udvp;
1763 	struct vnode   *uvp;
1764 	int		error;
1765 	int		lkflags;
1766 
1767 	UNIONFS_INTERNAL_DEBUG("unionfs_symlink: enter\n");
1768 
1769 	KASSERT_UNIONFS_VNODE(ap->a_dvp);
1770 
1771 	error = EROFS;
1772 	dunp = VTOUNIONFS(ap->a_dvp);
1773 	cnp = ap->a_cnp;
1774 	lkflags = cnp->cn_lkflags;
1775 	udvp = dunp->un_uppervp;
1776 
1777 	if (udvp != NULLVP) {
1778 		int udvp_lkflags;
1779 		bool uvp_created = false;
1780 		unionfs_forward_vop_start(udvp, &udvp_lkflags);
1781 		error = VOP_SYMLINK(udvp, &uvp, cnp, ap->a_vap, ap->a_target);
1782 		if (error == 0)
1783 			uvp_created = true;
1784 		if (__predict_false(unionfs_forward_vop_finish(ap->a_dvp, udvp,
1785 		    udvp_lkflags)) && error == 0)
1786 			error = ENOENT;
1787 		if (error == 0) {
1788 			VOP_UNLOCK(uvp);
1789 			cnp->cn_lkflags = LK_EXCLUSIVE;
1790 			error = unionfs_nodeget(ap->a_dvp->v_mount, uvp, NULLVP,
1791 			    ap->a_dvp, ap->a_vpp, cnp);
1792 			vrele(uvp);
1793 			cnp->cn_lkflags = lkflags;
1794 		} else if (uvp_created)
1795 			vput(uvp);
1796 	}
1797 
1798 	UNIONFS_INTERNAL_DEBUG("unionfs_symlink: leave (%d)\n", error);
1799 
1800 	return (error);
1801 }
1802 
1803 static int
unionfs_readdir(struct vop_readdir_args * ap)1804 unionfs_readdir(struct vop_readdir_args *ap)
1805 {
1806 	struct unionfs_node *unp;
1807 	struct unionfs_node_status *unsp;
1808 	struct uio     *uio;
1809 	struct vnode   *vp;
1810 	struct vnode   *uvp;
1811 	struct vnode   *lvp;
1812 	struct thread  *td;
1813 	struct vattr    va;
1814 
1815 	uint64_t	*cookies_bk;
1816 	int		error;
1817 	int		eofflag;
1818 	int		lkflags;
1819 	int		ncookies_bk;
1820 	int		uio_offset_bk;
1821 	enum unionfs_lkupgrade lkstatus;
1822 
1823 	UNIONFS_INTERNAL_DEBUG("unionfs_readdir: enter\n");
1824 
1825 	KASSERT_UNIONFS_VNODE(ap->a_vp);
1826 
1827 	error = 0;
1828 	eofflag = 0;
1829 	uio_offset_bk = 0;
1830 	uio = ap->a_uio;
1831 	uvp = NULLVP;
1832 	lvp = NULLVP;
1833 	td = uio->uio_td;
1834 	ncookies_bk = 0;
1835 	cookies_bk = NULL;
1836 
1837 	vp = ap->a_vp;
1838 	if (vp->v_type != VDIR)
1839 		return (ENOTDIR);
1840 
1841 	/*
1842 	 * If the vnode is reclaimed while upgrading, we can't safely use unp
1843 	 * or do anything else unionfs- specific.
1844 	 */
1845 	lkstatus = unionfs_upgrade_lock(vp);
1846 	if (lkstatus == UNIONFS_LKUPGRADE_DOOMED)
1847 		error = EBADF;
1848 	if (error == 0) {
1849 		unp = VTOUNIONFS(vp);
1850 		uvp = unp->un_uppervp;
1851 		lvp = unp->un_lowervp;
1852 		/* check the open count. unionfs needs open before readdir. */
1853 		unionfs_get_node_status(unp, td, &unsp);
1854 		if ((uvp != NULLVP && unsp->uns_upper_opencnt <= 0) ||
1855 			(lvp != NULLVP && unsp->uns_lower_opencnt <= 0)) {
1856 			unionfs_tryrem_node_status(unp, unsp);
1857 			error = EBADF;
1858 		}
1859 	}
1860 	unionfs_downgrade_lock(vp, lkstatus);
1861 	if (error != 0)
1862 		goto unionfs_readdir_exit;
1863 
1864 	/* check opaque */
1865 	if (uvp != NULLVP && lvp != NULLVP) {
1866 		if ((error = VOP_GETATTR(uvp, &va, ap->a_cred)) != 0)
1867 			goto unionfs_readdir_exit;
1868 		if (va.va_flags & OPAQUE)
1869 			lvp = NULLVP;
1870 	}
1871 
1872 	/* upper only */
1873 	if (uvp != NULLVP && lvp == NULLVP) {
1874 		unionfs_forward_vop_start(uvp, &lkflags);
1875 		error = VOP_READDIR(uvp, uio, ap->a_cred, ap->a_eofflag,
1876 		    ap->a_ncookies, ap->a_cookies);
1877 		if (unionfs_forward_vop_finish(vp, uvp, lkflags))
1878 			error = error ? error : ENOENT;
1879 		else
1880 			unsp->uns_readdir_status = 0;
1881 
1882 		goto unionfs_readdir_exit;
1883 	}
1884 
1885 	/* lower only */
1886 	if (uvp == NULLVP && lvp != NULLVP) {
1887 		unionfs_forward_vop_start(lvp, &lkflags);
1888 		error = VOP_READDIR(lvp, uio, ap->a_cred, ap->a_eofflag,
1889 		    ap->a_ncookies, ap->a_cookies);
1890 		if (unionfs_forward_vop_finish(vp, lvp, lkflags))
1891 			error = error ? error : ENOENT;
1892 		else
1893 			unsp->uns_readdir_status = 2;
1894 
1895 		goto unionfs_readdir_exit;
1896 	}
1897 
1898 	/*
1899 	 * readdir upper and lower
1900 	 */
1901 	KASSERT(uvp != NULLVP, ("unionfs_readdir: null upper vp"));
1902 	KASSERT(lvp != NULLVP, ("unionfs_readdir: null lower vp"));
1903 
1904 	if (uio->uio_offset == 0)
1905 		unsp->uns_readdir_status = 0;
1906 
1907 	if (unsp->uns_readdir_status == 0) {
1908 		/* read upper */
1909 		unionfs_forward_vop_start(uvp, &lkflags);
1910 		error = VOP_READDIR(uvp, uio, ap->a_cred, &eofflag,
1911 				    ap->a_ncookies, ap->a_cookies);
1912 		if (unionfs_forward_vop_finish(vp, uvp, lkflags) && error == 0)
1913 			error = ENOENT;
1914 		if (error != 0 || eofflag == 0)
1915 			goto unionfs_readdir_exit;
1916 		unsp->uns_readdir_status = 1;
1917 
1918 		/*
1919 		 * UFS(and other FS) needs size of uio_resid larger than
1920 		 * DIRBLKSIZ.
1921 		 * size of DIRBLKSIZ equals DEV_BSIZE.
1922 		 * (see: ufs/ufs/ufs_vnops.c ufs_readdir func , ufs/ufs/dir.h)
1923 		 */
1924 		if (uio->uio_resid <= (uio->uio_resid & (DEV_BSIZE -1)))
1925 			goto unionfs_readdir_exit;
1926 
1927 		/*
1928 		 * Backup cookies.
1929 		 * It prepares to readdir in lower.
1930 		 */
1931 		if (ap->a_ncookies != NULL) {
1932 			ncookies_bk = *(ap->a_ncookies);
1933 			*(ap->a_ncookies) = 0;
1934 		}
1935 		if (ap->a_cookies != NULL) {
1936 			cookies_bk = *(ap->a_cookies);
1937 			*(ap->a_cookies) = NULL;
1938 		}
1939 	}
1940 
1941 	/* initialize for readdir in lower */
1942 	if (unsp->uns_readdir_status == 1) {
1943 		unsp->uns_readdir_status = 2;
1944 		/*
1945 		 * Backup uio_offset. See the comment after the
1946 		 * VOP_READDIR call on the lower layer.
1947 		 */
1948 		uio_offset_bk = uio->uio_offset;
1949 		uio->uio_offset = 0;
1950 	}
1951 
1952 	lvp = unionfs_lock_lvp(vp, &lkflags);
1953 	if (lvp == NULL) {
1954 		error = ENOENT;
1955 		goto unionfs_readdir_exit;
1956 	}
1957 
1958 	/* read lower */
1959 	error = VOP_READDIR(lvp, uio, ap->a_cred, ap->a_eofflag,
1960 			    ap->a_ncookies, ap->a_cookies);
1961 
1962 
1963 	unp = unionfs_unlock_lvp(vp, lvp, lkflags);
1964 	if (unp == NULL && error == 0)
1965 		error = ENOENT;
1966 
1967 
1968 	/*
1969 	 * We can't return an uio_offset of 0: this would trigger an
1970 	 * infinite loop, because the next call to unionfs_readdir would
1971 	 * always restart with the upper layer (uio_offset == 0) and
1972 	 * always return some data.
1973 	 *
1974 	 * This happens when the lower layer root directory is removed.
1975 	 * (A root directory deleting of unionfs should not be permitted.
1976 	 *  But current VFS can not do it.)
1977 	 */
1978 	if (uio->uio_offset == 0)
1979 		uio->uio_offset = uio_offset_bk;
1980 
1981 	if (cookies_bk != NULL) {
1982 		/* merge cookies */
1983 		int		size;
1984 		uint64_t         *newcookies, *pos;
1985 
1986 		size = *(ap->a_ncookies) + ncookies_bk;
1987 		newcookies = (uint64_t *) malloc(size * sizeof(*newcookies),
1988 		    M_TEMP, M_WAITOK);
1989 		pos = newcookies;
1990 
1991 		memcpy(pos, cookies_bk, ncookies_bk * sizeof(*newcookies));
1992 		pos += ncookies_bk;
1993 		memcpy(pos, *(ap->a_cookies),
1994 		    *(ap->a_ncookies) * sizeof(*newcookies));
1995 		free(cookies_bk, M_TEMP);
1996 		free(*(ap->a_cookies), M_TEMP);
1997 		*(ap->a_ncookies) = size;
1998 		*(ap->a_cookies) = newcookies;
1999 	}
2000 
2001 unionfs_readdir_exit:
2002 	if (error != 0 && ap->a_eofflag != NULL)
2003 		*(ap->a_eofflag) = 1;
2004 
2005 	UNIONFS_INTERNAL_DEBUG("unionfs_readdir: leave (%d)\n", error);
2006 
2007 	return (error);
2008 }
2009 
2010 static int
unionfs_readlink(struct vop_readlink_args * ap)2011 unionfs_readlink(struct vop_readlink_args *ap)
2012 {
2013 	struct unionfs_node *unp;
2014 	struct vnode   *vp;
2015 	int error;
2016 
2017 	UNIONFS_INTERNAL_DEBUG("unionfs_readlink: enter\n");
2018 
2019 	KASSERT_UNIONFS_VNODE(ap->a_vp);
2020 
2021 	unp = VTOUNIONFS(ap->a_vp);
2022 	vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp);
2023 
2024 	error = VOP_READLINK(vp, ap->a_uio, ap->a_cred);
2025 
2026 	UNIONFS_INTERNAL_DEBUG("unionfs_readlink: leave (%d)\n", error);
2027 
2028 	return (error);
2029 }
2030 
2031 static int
unionfs_getwritemount(struct vop_getwritemount_args * ap)2032 unionfs_getwritemount(struct vop_getwritemount_args *ap)
2033 {
2034 	struct unionfs_node *unp;
2035 	struct vnode   *uvp;
2036 	struct vnode   *vp, *ovp;
2037 	int		error;
2038 
2039 	UNIONFS_INTERNAL_DEBUG("unionfs_getwritemount: enter\n");
2040 
2041 	error = 0;
2042 	vp = ap->a_vp;
2043 	uvp = NULLVP;
2044 
2045 	VI_LOCK(vp);
2046 	unp = VTOUNIONFS(vp);
2047 	if (unp != NULL)
2048 		uvp = unp->un_uppervp;
2049 
2050 	/*
2051 	 * If our node has no upper vnode, check the parent directory.
2052 	 * We may be initiating a write operation that will produce a
2053 	 * new upper vnode through CoW.
2054 	 */
2055 	if (uvp == NULLVP && unp != NULL) {
2056 		ovp = vp;
2057 		vp = unp->un_dvp;
2058 		/*
2059 		 * Only the root vnode should have an empty parent, but it
2060 		 * should not have an empty uppervp, so we shouldn't get here.
2061 		 */
2062 		VNASSERT(vp != NULL, ovp, ("%s: NULL parent vnode", __func__));
2063 		VI_UNLOCK(ovp);
2064 		VI_LOCK(vp);
2065 		unp = VTOUNIONFS(vp);
2066 		if (unp != NULL)
2067 			uvp = unp->un_uppervp;
2068 		if (uvp == NULLVP)
2069 			error = EACCES;
2070 	}
2071 
2072 	if (uvp != NULLVP) {
2073 		vholdnz(uvp);
2074 		VI_UNLOCK(vp);
2075 		error = VOP_GETWRITEMOUNT(uvp, ap->a_mpp);
2076 		vdrop(uvp);
2077 	} else {
2078 		VI_UNLOCK(vp);
2079 		*(ap->a_mpp) = NULL;
2080 	}
2081 
2082 	UNIONFS_INTERNAL_DEBUG("unionfs_getwritemount: leave (%d)\n", error);
2083 
2084 	return (error);
2085 }
2086 
2087 static int
unionfs_inactive(struct vop_inactive_args * ap)2088 unionfs_inactive(struct vop_inactive_args *ap)
2089 {
2090 	ap->a_vp->v_object = NULL;
2091 	vrecycle(ap->a_vp);
2092 	return (0);
2093 }
2094 
2095 static int
unionfs_reclaim(struct vop_reclaim_args * ap)2096 unionfs_reclaim(struct vop_reclaim_args *ap)
2097 {
2098 	/* UNIONFS_INTERNAL_DEBUG("unionfs_reclaim: enter\n"); */
2099 
2100 	unionfs_noderem(ap->a_vp);
2101 
2102 	/* UNIONFS_INTERNAL_DEBUG("unionfs_reclaim: leave\n"); */
2103 
2104 	return (0);
2105 }
2106 
2107 static int
unionfs_print(struct vop_print_args * ap)2108 unionfs_print(struct vop_print_args *ap)
2109 {
2110 	struct unionfs_node *unp;
2111 	/* struct unionfs_node_status *unsp; */
2112 
2113 	unp = VTOUNIONFS(ap->a_vp);
2114 	/* unionfs_get_node_status(unp, curthread, &unsp); */
2115 
2116 	printf("unionfs_vp=%p, uppervp=%p, lowervp=%p\n",
2117 	    ap->a_vp, unp->un_uppervp, unp->un_lowervp);
2118 	/*
2119 	printf("unionfs opencnt: uppervp=%d, lowervp=%d\n",
2120 	    unsp->uns_upper_opencnt, unsp->uns_lower_opencnt);
2121 	*/
2122 
2123 	if (unp->un_uppervp != NULLVP)
2124 		vn_printf(unp->un_uppervp, "unionfs: upper ");
2125 	if (unp->un_lowervp != NULLVP)
2126 		vn_printf(unp->un_lowervp, "unionfs: lower ");
2127 
2128 	return (0);
2129 }
2130 
2131 static int
unionfs_lock(struct vop_lock1_args * ap)2132 unionfs_lock(struct vop_lock1_args *ap)
2133 {
2134 	struct unionfs_node *unp;
2135 	struct vnode   *vp;
2136 	struct vnode   *tvp;
2137 	int		error;
2138 	int		flags;
2139 	bool		lvp_locked;
2140 
2141 	error = 0;
2142 	flags = ap->a_flags;
2143 	vp = ap->a_vp;
2144 
2145 	if (LK_RELEASE == (flags & LK_TYPE_MASK) || !(flags & LK_TYPE_MASK))
2146 		return (VOP_UNLOCK_FLAGS(vp, flags | LK_RELEASE));
2147 
2148 unionfs_lock_restart:
2149 	/*
2150 	 * We currently need the interlock here to ensure we can safely
2151 	 * access the unionfs vnode's private data.  We may be able to
2152 	 * eliminate this extra locking by instead using vfs_smr_enter()
2153 	 * and vn_load_v_data_smr() here in conjunction with an SMR UMA
2154 	 * zone for unionfs nodes.
2155 	 */
2156 	if ((flags & LK_INTERLOCK) == 0)
2157 		VI_LOCK(vp);
2158 	else
2159 		flags &= ~LK_INTERLOCK;
2160 
2161 	unp = VTOUNIONFS(vp);
2162 	if (unp == NULL) {
2163 		VI_UNLOCK(vp);
2164 		ap->a_flags = flags;
2165 		return (vop_stdlock(ap));
2166 	}
2167 
2168 	if (unp->un_uppervp != NULL) {
2169 		tvp = unp->un_uppervp;
2170 		lvp_locked = false;
2171 	} else {
2172 		tvp = unp->un_lowervp;
2173 		lvp_locked = true;
2174 	}
2175 
2176 	/*
2177 	 * During unmount, the root vnode lock may be taken recursively,
2178 	 * because it may share the same v_vnlock field as the vnode covered by
2179 	 * the unionfs mount.  The covered vnode is locked across VFS_UNMOUNT(),
2180 	 * and the same lock may be taken recursively here during vflush()
2181 	 * issued by unionfs_unmount().
2182 	 */
2183 	if ((flags & LK_TYPE_MASK) == LK_EXCLUSIVE &&
2184 	    (vp->v_vflag & VV_ROOT) != 0)
2185 		flags |= LK_CANRECURSE;
2186 
2187 	vholdnz(tvp);
2188 	VI_UNLOCK(vp);
2189 	error = VOP_LOCK(tvp, flags);
2190 	vdrop(tvp);
2191 	if (error == 0 && (lvp_locked || VTOUNIONFS(vp) == NULL)) {
2192 		/*
2193 		 * After dropping the interlock above, there exists a window
2194 		 * in which another thread may acquire the lower vnode lock
2195 		 * and then either doom the unionfs vnode or create an upper
2196 		 * vnode.  In either case, we will effectively be holding the
2197 		 * wrong lock, so we must drop the lower vnode lock and
2198 		 * restart the lock operation.
2199 		 *
2200 		 * If unp is not already NULL, we assume that we can safely
2201 		 * access it because we currently hold lvp's lock.
2202 		 * unionfs_noderem() acquires lvp's lock before freeing
2203 		 * the vnode private data, ensuring it can't be concurrently
2204 		 * freed while we are using it here.  Likewise,
2205 		 * unionfs_node_update() acquires lvp's lock before installing
2206 		 * an upper vnode.  Without those guarantees, we would need to
2207 		 * reacquire the vnode interlock here.
2208 		 * Note that unionfs_noderem() doesn't acquire lvp's lock if
2209 		 * this is the root vnode, but the root vnode should always
2210 		 * have an upper vnode and therefore we should never use its
2211 		 * lower vnode lock here.
2212 		 */
2213 		unp = VTOUNIONFS(vp);
2214 		if (unp == NULL || unp->un_uppervp != NULLVP) {
2215 			VOP_UNLOCK(tvp);
2216 			/*
2217 			 * If we previously held the lock, the upgrade may
2218 			 * have temporarily dropped the lock, in which case
2219 			 * concurrent dooming or copy-up will necessitate
2220 			 * acquiring a different lock.  Since we never held
2221 			 * the new lock, LK_UPGRADE must be cleared here to
2222 			 * avoid triggering a lockmgr panic.
2223 			 */
2224 			if (flags & LK_UPGRADE)
2225 				flags = (flags & ~LK_TYPE_MASK) | LK_EXCLUSIVE;
2226 			VNASSERT((flags & LK_DOWNGRADE) == 0, vp,
2227 			    ("%s: vnode doomed during downgrade", __func__));
2228 			goto unionfs_lock_restart;
2229 		}
2230 	}
2231 
2232 	return (error);
2233 }
2234 
2235 static int
unionfs_unlock(struct vop_unlock_args * ap)2236 unionfs_unlock(struct vop_unlock_args *ap)
2237 {
2238 	struct vnode   *vp;
2239 	struct vnode   *tvp;
2240 	struct unionfs_node *unp;
2241 	int		error;
2242 
2243 	KASSERT_UNIONFS_VNODE(ap->a_vp);
2244 
2245 	vp = ap->a_vp;
2246 
2247 	unp = VTOUNIONFS(vp);
2248 	if (unp == NULL)
2249 		return (vop_stdunlock(ap));
2250 
2251 	tvp = (unp->un_uppervp != NULL ? unp->un_uppervp : unp->un_lowervp);
2252 
2253 	vholdnz(tvp);
2254 	error = VOP_UNLOCK(tvp);
2255 	vdrop(tvp);
2256 
2257 	return (error);
2258 }
2259 
2260 static int
unionfs_pathconf(struct vop_pathconf_args * ap)2261 unionfs_pathconf(struct vop_pathconf_args *ap)
2262 {
2263 	struct unionfs_node *unp;
2264 	struct vnode   *vp;
2265 
2266 	KASSERT_UNIONFS_VNODE(ap->a_vp);
2267 
2268 	unp = VTOUNIONFS(ap->a_vp);
2269 	vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp);
2270 
2271 	return (VOP_PATHCONF(vp, ap->a_name, ap->a_retval));
2272 }
2273 
2274 static int
unionfs_advlock(struct vop_advlock_args * ap)2275 unionfs_advlock(struct vop_advlock_args *ap)
2276 {
2277 	struct unionfs_node *unp;
2278 	struct unionfs_node_status *unsp;
2279 	struct vnode   *vp;
2280 	struct vnode   *uvp;
2281 	struct thread  *td;
2282 	int error;
2283 
2284 	UNIONFS_INTERNAL_DEBUG("unionfs_advlock: enter\n");
2285 
2286 	KASSERT_UNIONFS_VNODE(ap->a_vp);
2287 
2288 	vp = ap->a_vp;
2289 	td = curthread;
2290 
2291 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2292 
2293 	unp = VTOUNIONFS(ap->a_vp);
2294 	uvp = unp->un_uppervp;
2295 
2296 	if (uvp == NULLVP) {
2297 		error = unionfs_copyfile(ap->a_vp, 1, td->td_ucred, td);
2298 		if (error != 0)
2299 			goto unionfs_advlock_abort;
2300 		uvp = unp->un_uppervp;
2301 
2302 		unionfs_get_node_status(unp, td, &unsp);
2303 		if (unsp->uns_lower_opencnt > 0) {
2304 			/* try reopen the vnode */
2305 			error = VOP_OPEN(uvp, unsp->uns_lower_openmode,
2306 				td->td_ucred, td, NULL);
2307 			if (error)
2308 				goto unionfs_advlock_abort;
2309 			unsp->uns_upper_opencnt++;
2310 			VOP_CLOSE(unp->un_lowervp, unsp->uns_lower_openmode,
2311 			    td->td_ucred, td);
2312 			unsp->uns_lower_opencnt--;
2313 		} else
2314 			unionfs_tryrem_node_status(unp, unsp);
2315 	}
2316 
2317 	VOP_UNLOCK(vp);
2318 
2319 	error = VOP_ADVLOCK(uvp, ap->a_id, ap->a_op, ap->a_fl, ap->a_flags);
2320 
2321 	UNIONFS_INTERNAL_DEBUG("unionfs_advlock: leave (%d)\n", error);
2322 
2323 	return error;
2324 
2325 unionfs_advlock_abort:
2326 	VOP_UNLOCK(vp);
2327 
2328 	UNIONFS_INTERNAL_DEBUG("unionfs_advlock: leave (%d)\n", error);
2329 
2330 	return error;
2331 }
2332 
2333 static int
unionfs_strategy(struct vop_strategy_args * ap)2334 unionfs_strategy(struct vop_strategy_args *ap)
2335 {
2336 	struct unionfs_node *unp;
2337 	struct vnode   *vp;
2338 
2339 	KASSERT_UNIONFS_VNODE(ap->a_vp);
2340 
2341 	unp = VTOUNIONFS(ap->a_vp);
2342 	vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp);
2343 
2344 #ifdef DIAGNOSTIC
2345 	if (vp == NULLVP)
2346 		panic("unionfs_strategy: nullvp");
2347 
2348 	if (ap->a_bp->b_iocmd == BIO_WRITE && vp == unp->un_lowervp)
2349 		panic("unionfs_strategy: writing to lowervp");
2350 #endif
2351 
2352 	return (VOP_STRATEGY(vp, ap->a_bp));
2353 }
2354 
2355 static int
unionfs_getacl(struct vop_getacl_args * ap)2356 unionfs_getacl(struct vop_getacl_args *ap)
2357 {
2358 	struct unionfs_node *unp;
2359 	struct vnode   *vp;
2360 	int		error;
2361 
2362 	KASSERT_UNIONFS_VNODE(ap->a_vp);
2363 
2364 	unp = VTOUNIONFS(ap->a_vp);
2365 	vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp);
2366 
2367 	UNIONFS_INTERNAL_DEBUG("unionfs_getacl: enter\n");
2368 
2369 	error = VOP_GETACL(vp, ap->a_type, ap->a_aclp, ap->a_cred, ap->a_td);
2370 
2371 	UNIONFS_INTERNAL_DEBUG("unionfs_getacl: leave (%d)\n", error);
2372 
2373 	return (error);
2374 }
2375 
2376 static int
unionfs_setacl(struct vop_setacl_args * ap)2377 unionfs_setacl(struct vop_setacl_args *ap)
2378 {
2379 	struct unionfs_node *unp;
2380 	struct vnode   *uvp;
2381 	struct vnode   *lvp;
2382 	struct thread  *td;
2383 	int		error;
2384 
2385 	UNIONFS_INTERNAL_DEBUG("unionfs_setacl: enter\n");
2386 
2387 	KASSERT_UNIONFS_VNODE(ap->a_vp);
2388 
2389 	error = EROFS;
2390 	unp = VTOUNIONFS(ap->a_vp);
2391 	uvp = unp->un_uppervp;
2392 	lvp = unp->un_lowervp;
2393 	td = ap->a_td;
2394 
2395 	if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
2396 		return (EROFS);
2397 
2398 	if (uvp == NULLVP && lvp->v_type == VREG) {
2399 		if ((error = unionfs_copyfile(ap->a_vp, 1, ap->a_cred, td)) != 0)
2400 			return (error);
2401 		uvp = unp->un_uppervp;
2402 	}
2403 
2404 	if (uvp != NULLVP) {
2405 		int lkflags;
2406 		unionfs_forward_vop_start(uvp, &lkflags);
2407 		error = VOP_SETACL(uvp, ap->a_type, ap->a_aclp, ap->a_cred, td);
2408 		unionfs_forward_vop_finish(ap->a_vp, uvp, lkflags);
2409 	}
2410 
2411 	UNIONFS_INTERNAL_DEBUG("unionfs_setacl: leave (%d)\n", error);
2412 
2413 	return (error);
2414 }
2415 
2416 static int
unionfs_aclcheck(struct vop_aclcheck_args * ap)2417 unionfs_aclcheck(struct vop_aclcheck_args *ap)
2418 {
2419 	struct unionfs_node *unp;
2420 	struct vnode   *vp;
2421 	int		error;
2422 
2423 	UNIONFS_INTERNAL_DEBUG("unionfs_aclcheck: enter\n");
2424 
2425 	KASSERT_UNIONFS_VNODE(ap->a_vp);
2426 
2427 	unp = VTOUNIONFS(ap->a_vp);
2428 	vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp);
2429 
2430 	error = VOP_ACLCHECK(vp, ap->a_type, ap->a_aclp, ap->a_cred, ap->a_td);
2431 
2432 	UNIONFS_INTERNAL_DEBUG("unionfs_aclcheck: leave (%d)\n", error);
2433 
2434 	return (error);
2435 }
2436 
2437 static int
unionfs_openextattr(struct vop_openextattr_args * ap)2438 unionfs_openextattr(struct vop_openextattr_args *ap)
2439 {
2440 	struct unionfs_node *unp;
2441 	struct vnode   *vp;
2442 	struct vnode   *tvp;
2443 	int		error;
2444 
2445 	KASSERT_UNIONFS_VNODE(ap->a_vp);
2446 
2447 	vp = ap->a_vp;
2448 	unp = VTOUNIONFS(vp);
2449 	tvp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp);
2450 
2451 	if ((tvp == unp->un_uppervp && (unp->un_flag & UNIONFS_OPENEXTU)) ||
2452 	    (tvp == unp->un_lowervp && (unp->un_flag & UNIONFS_OPENEXTL)))
2453 		return (EBUSY);
2454 
2455 	error = VOP_OPENEXTATTR(tvp, ap->a_cred, ap->a_td);
2456 
2457 	if (error == 0) {
2458 		if (vn_lock(vp, LK_UPGRADE) != 0)
2459 			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2460 		if (!VN_IS_DOOMED(vp)) {
2461 			if (tvp == unp->un_uppervp)
2462 				unp->un_flag |= UNIONFS_OPENEXTU;
2463 			else
2464 				unp->un_flag |= UNIONFS_OPENEXTL;
2465 		}
2466 		vn_lock(vp, LK_DOWNGRADE | LK_RETRY);
2467 	}
2468 
2469 	return (error);
2470 }
2471 
2472 static int
unionfs_closeextattr(struct vop_closeextattr_args * ap)2473 unionfs_closeextattr(struct vop_closeextattr_args *ap)
2474 {
2475 	struct unionfs_node *unp;
2476 	struct vnode   *vp;
2477 	struct vnode   *tvp;
2478 	int		error;
2479 
2480 	KASSERT_UNIONFS_VNODE(ap->a_vp);
2481 
2482 	vp = ap->a_vp;
2483 	unp = VTOUNIONFS(vp);
2484 	tvp = NULLVP;
2485 
2486 	if (unp->un_flag & UNIONFS_OPENEXTU)
2487 		tvp = unp->un_uppervp;
2488 	else if (unp->un_flag & UNIONFS_OPENEXTL)
2489 		tvp = unp->un_lowervp;
2490 
2491 	if (tvp == NULLVP)
2492 		return (EOPNOTSUPP);
2493 
2494 	error = VOP_CLOSEEXTATTR(tvp, ap->a_commit, ap->a_cred, ap->a_td);
2495 
2496 	if (error == 0) {
2497 		if (vn_lock(vp, LK_UPGRADE) != 0)
2498 			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2499 		if (!VN_IS_DOOMED(vp)) {
2500 			if (tvp == unp->un_uppervp)
2501 				unp->un_flag &= ~UNIONFS_OPENEXTU;
2502 			else
2503 				unp->un_flag &= ~UNIONFS_OPENEXTL;
2504 		}
2505 		vn_lock(vp, LK_DOWNGRADE | LK_RETRY);
2506 	}
2507 
2508 	return (error);
2509 }
2510 
2511 static int
unionfs_getextattr(struct vop_getextattr_args * ap)2512 unionfs_getextattr(struct vop_getextattr_args *ap)
2513 {
2514 	struct unionfs_node *unp;
2515 	struct vnode   *vp;
2516 
2517 	KASSERT_UNIONFS_VNODE(ap->a_vp);
2518 
2519 	unp = VTOUNIONFS(ap->a_vp);
2520 	vp = NULLVP;
2521 
2522 	if (unp->un_flag & UNIONFS_OPENEXTU)
2523 		vp = unp->un_uppervp;
2524 	else if (unp->un_flag & UNIONFS_OPENEXTL)
2525 		vp = unp->un_lowervp;
2526 
2527 	if (vp == NULLVP)
2528 		return (EOPNOTSUPP);
2529 
2530 	return (VOP_GETEXTATTR(vp, ap->a_attrnamespace, ap->a_name,
2531 	    ap->a_uio, ap->a_size, ap->a_cred, ap->a_td));
2532 }
2533 
2534 static int
unionfs_setextattr(struct vop_setextattr_args * ap)2535 unionfs_setextattr(struct vop_setextattr_args *ap)
2536 {
2537 	struct unionfs_node *unp;
2538 	struct vnode   *uvp;
2539 	struct vnode   *lvp;
2540 	struct vnode   *ovp;
2541 	struct ucred   *cred;
2542 	struct thread  *td;
2543 	int		error;
2544 
2545 	KASSERT_UNIONFS_VNODE(ap->a_vp);
2546 
2547 	error = EROFS;
2548 	unp = VTOUNIONFS(ap->a_vp);
2549 	uvp = unp->un_uppervp;
2550 	lvp = unp->un_lowervp;
2551 	ovp = NULLVP;
2552 	cred = ap->a_cred;
2553 	td = ap->a_td;
2554 
2555 	UNIONFS_INTERNAL_DEBUG("unionfs_setextattr: enter (un_flag=%x)\n",
2556 	    unp->un_flag);
2557 
2558 	if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
2559 		return (EROFS);
2560 
2561 	if (unp->un_flag & UNIONFS_OPENEXTU)
2562 		ovp = unp->un_uppervp;
2563 	else if (unp->un_flag & UNIONFS_OPENEXTL)
2564 		ovp = unp->un_lowervp;
2565 
2566 	if (ovp == NULLVP)
2567 		return (EOPNOTSUPP);
2568 
2569 	if (ovp == lvp && lvp->v_type == VREG) {
2570 		VOP_CLOSEEXTATTR(lvp, 0, cred, td);
2571 		if (uvp == NULLVP &&
2572 		    (error = unionfs_copyfile(ap->a_vp, 1, cred, td)) != 0) {
2573 unionfs_setextattr_reopen:
2574 			unp = VTOUNIONFS(ap->a_vp);
2575 			if (unp != NULL && (unp->un_flag & UNIONFS_OPENEXTL) &&
2576 			    VOP_OPENEXTATTR(lvp, cred, td)) {
2577 #ifdef DIAGNOSTIC
2578 				panic("unionfs: VOP_OPENEXTATTR failed");
2579 #endif
2580 				unp->un_flag &= ~UNIONFS_OPENEXTL;
2581 			}
2582 			goto unionfs_setextattr_abort;
2583 		}
2584 		uvp = unp->un_uppervp;
2585 		if ((error = VOP_OPENEXTATTR(uvp, cred, td)) != 0)
2586 			goto unionfs_setextattr_reopen;
2587 		unp->un_flag &= ~UNIONFS_OPENEXTL;
2588 		unp->un_flag |= UNIONFS_OPENEXTU;
2589 		ovp = uvp;
2590 	}
2591 
2592 	if (ovp == uvp) {
2593 		int lkflags;
2594 		unionfs_forward_vop_start(ovp, &lkflags);
2595 		error = VOP_SETEXTATTR(ovp, ap->a_attrnamespace, ap->a_name,
2596 		    ap->a_uio, cred, td);
2597 		unionfs_forward_vop_finish(ap->a_vp, ovp, lkflags);
2598 	}
2599 
2600 unionfs_setextattr_abort:
2601 	UNIONFS_INTERNAL_DEBUG("unionfs_setextattr: leave (%d)\n", error);
2602 
2603 	return (error);
2604 }
2605 
2606 static int
unionfs_listextattr(struct vop_listextattr_args * ap)2607 unionfs_listextattr(struct vop_listextattr_args *ap)
2608 {
2609 	struct unionfs_node *unp;
2610 	struct vnode *vp;
2611 
2612 	KASSERT_UNIONFS_VNODE(ap->a_vp);
2613 
2614 	unp = VTOUNIONFS(ap->a_vp);
2615 	vp = NULLVP;
2616 
2617 	if (unp->un_flag & UNIONFS_OPENEXTU)
2618 		vp = unp->un_uppervp;
2619 	else if (unp->un_flag & UNIONFS_OPENEXTL)
2620 		vp = unp->un_lowervp;
2621 
2622 	if (vp == NULLVP)
2623 		return (EOPNOTSUPP);
2624 
2625 	return (VOP_LISTEXTATTR(vp, ap->a_attrnamespace, ap->a_uio,
2626 	    ap->a_size, ap->a_cred, ap->a_td));
2627 }
2628 
2629 static int
unionfs_deleteextattr(struct vop_deleteextattr_args * ap)2630 unionfs_deleteextattr(struct vop_deleteextattr_args *ap)
2631 {
2632 	struct unionfs_node *unp;
2633 	struct vnode   *uvp;
2634 	struct vnode   *lvp;
2635 	struct vnode   *ovp;
2636 	struct ucred   *cred;
2637 	struct thread  *td;
2638 	int		error;
2639 
2640 	KASSERT_UNIONFS_VNODE(ap->a_vp);
2641 
2642 	error = EROFS;
2643 	unp = VTOUNIONFS(ap->a_vp);
2644 	uvp = unp->un_uppervp;
2645 	lvp = unp->un_lowervp;
2646 	ovp = NULLVP;
2647 	cred = ap->a_cred;
2648 	td = ap->a_td;
2649 
2650 	UNIONFS_INTERNAL_DEBUG("unionfs_deleteextattr: enter (un_flag=%x)\n",
2651 	    unp->un_flag);
2652 
2653 	if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
2654 		return (EROFS);
2655 
2656 	if (unp->un_flag & UNIONFS_OPENEXTU)
2657 		ovp = unp->un_uppervp;
2658 	else if (unp->un_flag & UNIONFS_OPENEXTL)
2659 		ovp = unp->un_lowervp;
2660 
2661 	if (ovp == NULLVP)
2662 		return (EOPNOTSUPP);
2663 
2664 	if (ovp == lvp && lvp->v_type == VREG) {
2665 		VOP_CLOSEEXTATTR(lvp, 0, cred, td);
2666 		if (uvp == NULLVP &&
2667 		    (error = unionfs_copyfile(ap->a_vp, 1, cred, td)) != 0) {
2668 unionfs_deleteextattr_reopen:
2669 			unp = VTOUNIONFS(ap->a_vp);
2670 			if (unp != NULL && (unp->un_flag & UNIONFS_OPENEXTL) &&
2671 			    VOP_OPENEXTATTR(lvp, cred, td)) {
2672 #ifdef DIAGNOSTIC
2673 				panic("unionfs: VOP_OPENEXTATTR failed");
2674 #endif
2675 				unp->un_flag &= ~UNIONFS_OPENEXTL;
2676 			}
2677 			goto unionfs_deleteextattr_abort;
2678 		}
2679 		uvp = unp->un_uppervp;
2680 		if ((error = VOP_OPENEXTATTR(uvp, cred, td)) != 0)
2681 			goto unionfs_deleteextattr_reopen;
2682 		unp->un_flag &= ~UNIONFS_OPENEXTL;
2683 		unp->un_flag |= UNIONFS_OPENEXTU;
2684 		ovp = uvp;
2685 	}
2686 
2687 	if (ovp == uvp)
2688 		error = VOP_DELETEEXTATTR(ovp, ap->a_attrnamespace, ap->a_name,
2689 		    ap->a_cred, ap->a_td);
2690 
2691 unionfs_deleteextattr_abort:
2692 	UNIONFS_INTERNAL_DEBUG("unionfs_deleteextattr: leave (%d)\n", error);
2693 
2694 	return (error);
2695 }
2696 
2697 static int
unionfs_setlabel(struct vop_setlabel_args * ap)2698 unionfs_setlabel(struct vop_setlabel_args *ap)
2699 {
2700 	struct unionfs_node *unp;
2701 	struct vnode   *uvp;
2702 	struct vnode   *lvp;
2703 	struct thread  *td;
2704 	int		error;
2705 
2706 	UNIONFS_INTERNAL_DEBUG("unionfs_setlabel: enter\n");
2707 
2708 	KASSERT_UNIONFS_VNODE(ap->a_vp);
2709 
2710 	error = EROFS;
2711 	unp = VTOUNIONFS(ap->a_vp);
2712 	uvp = unp->un_uppervp;
2713 	lvp = unp->un_lowervp;
2714 	td = ap->a_td;
2715 
2716 	if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
2717 		return (EROFS);
2718 
2719 	if (uvp == NULLVP && lvp->v_type == VREG) {
2720 		if ((error = unionfs_copyfile(ap->a_vp, 1, ap->a_cred, td)) != 0)
2721 			return (error);
2722 		uvp = unp->un_uppervp;
2723 	}
2724 
2725 	if (uvp != NULLVP)
2726 		error = VOP_SETLABEL(uvp, ap->a_label, ap->a_cred, td);
2727 
2728 	UNIONFS_INTERNAL_DEBUG("unionfs_setlabel: leave (%d)\n", error);
2729 
2730 	return (error);
2731 }
2732 
2733 static int
unionfs_vptofh(struct vop_vptofh_args * ap)2734 unionfs_vptofh(struct vop_vptofh_args *ap)
2735 {
2736 	return (EOPNOTSUPP);
2737 }
2738 
2739 static int
unionfs_add_writecount(struct vop_add_writecount_args * ap)2740 unionfs_add_writecount(struct vop_add_writecount_args *ap)
2741 {
2742 	struct vnode *tvp, *vp;
2743 	struct unionfs_node *unp;
2744 	int error, writerefs __diagused;
2745 
2746 	vp = ap->a_vp;
2747 	unp = VTOUNIONFS(vp);
2748 	tvp = unp->un_uppervp;
2749 	KASSERT(tvp != NULL,
2750 	    ("%s: adding write ref without upper vnode", __func__));
2751 	error = VOP_ADD_WRITECOUNT(tvp, ap->a_inc);
2752 	if (error != 0)
2753 		return (error);
2754 	/*
2755 	 * We need to track the write refs we've passed to the underlying
2756 	 * vnodes so that we can undo them in case we are forcibly unmounted.
2757 	 */
2758 	writerefs = atomic_fetchadd_int(&vp->v_writecount, ap->a_inc);
2759 	/* text refs are bypassed to lowervp */
2760 	VNASSERT(writerefs >= 0, vp,
2761 	    ("%s: invalid write count %d", __func__, writerefs));
2762 	VNASSERT(writerefs + ap->a_inc >= 0, vp,
2763 	    ("%s: invalid write count inc %d + %d", __func__,
2764 	    writerefs, ap->a_inc));
2765 	return (0);
2766 }
2767 
2768 static int
unionfs_vput_pair(struct vop_vput_pair_args * ap)2769 unionfs_vput_pair(struct vop_vput_pair_args *ap)
2770 {
2771 	struct mount *mp;
2772 	struct vnode *dvp, *vp, **vpp, *lvp, *uvp, *tvp, *tdvp, *tempvp;
2773 	struct unionfs_node *dunp, *unp;
2774 	int error, res;
2775 
2776 	dvp = ap->a_dvp;
2777 	vpp = ap->a_vpp;
2778 	vp = NULLVP;
2779 	lvp = NULLVP;
2780 	uvp = NULLVP;
2781 	tvp = NULLVP;
2782 	unp = NULL;
2783 
2784 	dunp = VTOUNIONFS(dvp);
2785 	if (dunp->un_uppervp != NULL)
2786 		tdvp = dunp->un_uppervp;
2787 	else
2788 		tdvp = dunp->un_lowervp;
2789 
2790 	/*
2791 	 * Underlying vnodes should be locked because the encompassing unionfs
2792 	 * node is locked, but will not be referenced, as the reference will
2793 	 * only be on the unionfs node.  Reference them now so that the vput()s
2794 	 * performed by VOP_VPUT_PAIR() will have a reference to drop.
2795 	 */
2796 	vref(tdvp);
2797 
2798 	if (vpp != NULL)
2799 		vp = *vpp;
2800 
2801 	if (vp != NULLVP) {
2802 		unp = VTOUNIONFS(vp);
2803 		uvp = unp->un_uppervp;
2804 		lvp = unp->un_lowervp;
2805 		if (uvp != NULLVP)
2806 			tvp = uvp;
2807 		else
2808 			tvp = lvp;
2809 		vref(tvp);
2810 
2811 		/*
2812 		 * If we're being asked to return a locked child vnode, then
2813 		 * we may need to create a replacement vnode in case the
2814 		 * original is reclaimed while the lock is dropped.  In that
2815 		 * case we'll need to ensure the mount and the underlying
2816 		 * vnodes aren't also recycled during that window.
2817 		 */
2818 		if (!ap->a_unlock_vp) {
2819 			vhold(vp);
2820 			if (uvp != NULLVP)
2821 				vhold(uvp);
2822 			if (lvp != NULLVP)
2823 				vhold(lvp);
2824 			mp = vp->v_mount;
2825 			vfs_ref(mp);
2826 		}
2827 	}
2828 
2829 	ASSERT_VOP_LOCKED(tdvp, __func__);
2830 	ASSERT_VOP_LOCKED(tvp, __func__);
2831 
2832 	if (tdvp == dunp->un_uppervp && tvp != NULLVP && tvp == lvp) {
2833 		vput(tvp);
2834 		vput(tdvp);
2835 		res = 0;
2836 	} else {
2837 		res = VOP_VPUT_PAIR(tdvp, tvp != NULLVP ? &tvp : NULL, true);
2838 	}
2839 
2840 	ASSERT_VOP_UNLOCKED(tdvp, __func__);
2841 	ASSERT_VOP_UNLOCKED(tvp, __func__);
2842 
2843 	/*
2844 	 * VOP_VPUT_PAIR() dropped the references we added to the underlying
2845 	 * vnodes, now drop the caller's reference to the unionfs vnodes.
2846 	 */
2847 	if (vp != NULLVP && ap->a_unlock_vp)
2848 		vrele(vp);
2849 	vrele(dvp);
2850 
2851 	if (vp == NULLVP || ap->a_unlock_vp)
2852 		return (res);
2853 
2854 	/*
2855 	 * We're being asked to return a locked vnode.  At this point, the
2856 	 * underlying vnodes have been unlocked, so vp may have been reclaimed.
2857 	 */
2858 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2859 	if (vp->v_data == NULL && vfs_busy(mp, MBF_NOWAIT) == 0) {
2860 		vput(vp);
2861 		error = unionfs_nodeget(mp, uvp, lvp, dvp, &tempvp, NULL);
2862 		if (error == 0) {
2863 			vn_lock(tempvp, LK_EXCLUSIVE | LK_RETRY);
2864 			*vpp = tempvp;
2865 		} else
2866 			vget(vp, LK_EXCLUSIVE | LK_RETRY);
2867 		vfs_unbusy(mp);
2868 	}
2869 	if (lvp != NULLVP)
2870 		vdrop(lvp);
2871 	if (uvp != NULLVP)
2872 		vdrop(uvp);
2873 	vdrop(vp);
2874 	vfs_rel(mp);
2875 
2876 	return (res);
2877 }
2878 
2879 static int
unionfs_set_text(struct vop_set_text_args * ap)2880 unionfs_set_text(struct vop_set_text_args *ap)
2881 {
2882 	struct vnode *tvp;
2883 	struct unionfs_node *unp;
2884 	int error;
2885 
2886 	/*
2887 	 * We assume text refs are managed against lvp/uvp through the
2888 	 * executable mapping backed by its VM object.  We therefore don't
2889 	 * need to track leased text refs in the case of a forcible unmount.
2890 	 */
2891 	unp = VTOUNIONFS(ap->a_vp);
2892 	ASSERT_VOP_LOCKED(ap->a_vp, __func__);
2893 	tvp = unp->un_uppervp != NULL ? unp->un_uppervp : unp->un_lowervp;
2894 	error = VOP_SET_TEXT(tvp);
2895 	return (error);
2896 }
2897 
2898 static int
unionfs_unset_text(struct vop_unset_text_args * ap)2899 unionfs_unset_text(struct vop_unset_text_args *ap)
2900 {
2901 	struct vnode *tvp;
2902 	struct unionfs_node *unp;
2903 
2904 	ASSERT_VOP_LOCKED(ap->a_vp, __func__);
2905 	unp = VTOUNIONFS(ap->a_vp);
2906 	tvp = unp->un_uppervp != NULL ? unp->un_uppervp : unp->un_lowervp;
2907 	VOP_UNSET_TEXT_CHECKED(tvp);
2908 	return (0);
2909 }
2910 
2911 static int
unionfs_unp_bind(struct vop_unp_bind_args * ap)2912 unionfs_unp_bind(struct vop_unp_bind_args *ap)
2913 {
2914 	struct vnode *tvp;
2915 	struct unionfs_node *unp;
2916 
2917 	ASSERT_VOP_LOCKED(ap->a_vp, __func__);
2918 	unp = VTOUNIONFS(ap->a_vp);
2919 	tvp = unp->un_uppervp != NULL ? unp->un_uppervp : unp->un_lowervp;
2920 	VOP_UNP_BIND(tvp, ap->a_unpcb);
2921 	return (0);
2922 }
2923 
2924 static int
unionfs_unp_connect(struct vop_unp_connect_args * ap)2925 unionfs_unp_connect(struct vop_unp_connect_args *ap)
2926 {
2927 	struct vnode *tvp;
2928 	struct unionfs_node *unp;
2929 
2930 	ASSERT_VOP_LOCKED(ap->a_vp, __func__);
2931 	unp = VTOUNIONFS(ap->a_vp);
2932 	tvp = unp->un_uppervp != NULL ? unp->un_uppervp : unp->un_lowervp;
2933 	VOP_UNP_CONNECT(tvp, ap->a_unpcb);
2934 	return (0);
2935 }
2936 
2937 static int
unionfs_unp_detach(struct vop_unp_detach_args * ap)2938 unionfs_unp_detach(struct vop_unp_detach_args *ap)
2939 {
2940 	struct vnode *tvp;
2941 	struct unionfs_node *unp;
2942 
2943 	tvp = NULL;
2944 	/*
2945 	 * VOP_UNP_DETACH() is not guaranteed to be called with the unionfs
2946 	 * vnode locked, so we take the interlock to prevent a concurrent
2947 	 * unmount from freeing the unionfs private data.
2948 	 */
2949 	VI_LOCK(ap->a_vp);
2950 	unp = VTOUNIONFS(ap->a_vp);
2951 	if (unp != NULL) {
2952 		tvp = unp->un_uppervp != NULL ?
2953 		    unp->un_uppervp : unp->un_lowervp;
2954 		/*
2955 		 * Hold the target vnode to prevent a concurrent unionfs
2956 		 * unmount from causing it to be recycled once the interlock
2957 		 * is dropped.
2958 		 */
2959 		vholdnz(tvp);
2960 	}
2961 	VI_UNLOCK(ap->a_vp);
2962 	if (tvp != NULL) {
2963 		VOP_UNP_DETACH(tvp);
2964 		vdrop(tvp);
2965 	}
2966 	return (0);
2967 }
2968 
2969 struct vop_vector unionfs_vnodeops = {
2970 	.vop_default =		&default_vnodeops,
2971 
2972 	.vop_access =		unionfs_access,
2973 	.vop_aclcheck =		unionfs_aclcheck,
2974 	.vop_advlock =		unionfs_advlock,
2975 	.vop_bmap =		VOP_EOPNOTSUPP,
2976 	.vop_cachedlookup =	unionfs_lookup,
2977 	.vop_close =		unionfs_close,
2978 	.vop_closeextattr =	unionfs_closeextattr,
2979 	.vop_create =		unionfs_create,
2980 	.vop_deleteextattr =	unionfs_deleteextattr,
2981 	.vop_fsync =		unionfs_fsync,
2982 	.vop_getacl =		unionfs_getacl,
2983 	.vop_getattr =		unionfs_getattr,
2984 	.vop_getextattr =	unionfs_getextattr,
2985 	.vop_getwritemount =	unionfs_getwritemount,
2986 	.vop_inactive =		unionfs_inactive,
2987 	.vop_need_inactive =	vop_stdneed_inactive,
2988 	.vop_islocked =		vop_stdislocked,
2989 	.vop_ioctl =		unionfs_ioctl,
2990 	.vop_link =		unionfs_link,
2991 	.vop_listextattr =	unionfs_listextattr,
2992 	.vop_lock1 =		unionfs_lock,
2993 	.vop_lookup =		vfs_cache_lookup,
2994 	.vop_mkdir =		unionfs_mkdir,
2995 	.vop_mknod =		unionfs_mknod,
2996 	.vop_open =		unionfs_open,
2997 	.vop_openextattr =	unionfs_openextattr,
2998 	.vop_pathconf =		unionfs_pathconf,
2999 	.vop_poll =		unionfs_poll,
3000 	.vop_print =		unionfs_print,
3001 	.vop_read =		unionfs_read,
3002 	.vop_readdir =		unionfs_readdir,
3003 	.vop_readlink =		unionfs_readlink,
3004 	.vop_reclaim =		unionfs_reclaim,
3005 	.vop_remove =		unionfs_remove,
3006 	.vop_rename =		unionfs_rename,
3007 	.vop_rmdir =		unionfs_rmdir,
3008 	.vop_setacl =		unionfs_setacl,
3009 	.vop_setattr =		unionfs_setattr,
3010 	.vop_setextattr =	unionfs_setextattr,
3011 	.vop_setlabel =		unionfs_setlabel,
3012 	.vop_strategy =		unionfs_strategy,
3013 	.vop_symlink =		unionfs_symlink,
3014 	.vop_unlock =		unionfs_unlock,
3015 	.vop_whiteout =		unionfs_whiteout,
3016 	.vop_write =		unionfs_write,
3017 	.vop_vptofh =		unionfs_vptofh,
3018 	.vop_add_writecount =	unionfs_add_writecount,
3019 	.vop_vput_pair =	unionfs_vput_pair,
3020 	.vop_set_text =		unionfs_set_text,
3021 	.vop_unset_text = 	unionfs_unset_text,
3022 	.vop_unp_bind =		unionfs_unp_bind,
3023 	.vop_unp_connect =	unionfs_unp_connect,
3024 	.vop_unp_detach =	unionfs_unp_detach,
3025 };
3026 VFS_VOP_VECTOR_REGISTER(unionfs_vnodeops);
3027