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