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