xref: /freebsd/sys/fs/unionfs/union_vnops.c (revision 8d20be1e22095c27faf8fe8b2f0d089739cc742e)
1 /*-
2  * Copyright (c) 1992, 1993, 1994, 1995 Jan-Simon Pendry.
3  * Copyright (c) 1992, 1993, 1994, 1995
4  *      The Regents of the University of California.
5  * Copyright (c) 2005, 2006, 2012 Masanori Ozawa <ozawa@ongs.co.jp>, ONGS Inc.
6  * Copyright (c) 2006, 2012 Daichi Goto <daichi@freebsd.org>
7  * All rights reserved.
8  *
9  * This code is derived from software contributed to Berkeley by
10  * Jan-Simon Pendry.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  *	@(#)union_vnops.c	8.32 (Berkeley) 6/23/95
37  * $FreeBSD$
38  *
39  */
40 
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/conf.h>
44 #include <sys/kernel.h>
45 #include <sys/lock.h>
46 #include <sys/malloc.h>
47 #include <sys/mount.h>
48 #include <sys/mutex.h>
49 #include <sys/namei.h>
50 #include <sys/sysctl.h>
51 #include <sys/vnode.h>
52 #include <sys/kdb.h>
53 #include <sys/fcntl.h>
54 #include <sys/stat.h>
55 #include <sys/dirent.h>
56 #include <sys/proc.h>
57 #include <sys/bio.h>
58 #include <sys/buf.h>
59 
60 #include <fs/unionfs/union.h>
61 
62 #include <vm/vm.h>
63 #include <vm/vm_extern.h>
64 #include <vm/vm_object.h>
65 #include <vm/vnode_pager.h>
66 
67 #if 0
68 #define UNIONFS_INTERNAL_DEBUG(msg, args...)    printf(msg, ## args)
69 #define UNIONFS_IDBG_RENAME
70 #else
71 #define UNIONFS_INTERNAL_DEBUG(msg, args...)
72 #endif
73 
74 #define KASSERT_UNIONFS_VNODE(vp) \
75 	KASSERT(((vp)->v_op == &unionfs_vnodeops), \
76 	    ("unionfs: it is not unionfs-vnode"))
77 
78 static int
79 unionfs_lookup(struct vop_cachedlookup_args *ap)
80 {
81 	int		iswhiteout;
82 	int		lockflag;
83 	int		error , uerror, lerror;
84 	u_long		nameiop;
85 	u_long		cnflags, cnflagsbk;
86 	struct unionfs_node *dunp;
87 	struct vnode   *dvp, *udvp, *ldvp, *vp, *uvp, *lvp, *dtmpvp;
88 	struct vattr	va;
89 	struct componentname *cnp;
90 	struct thread  *td;
91 
92 	iswhiteout = 0;
93 	lockflag = 0;
94 	error = uerror = lerror = ENOENT;
95 	cnp = ap->a_cnp;
96 	nameiop = cnp->cn_nameiop;
97 	cnflags = cnp->cn_flags;
98 	dvp = ap->a_dvp;
99 	dunp = VTOUNIONFS(dvp);
100 	udvp = dunp->un_uppervp;
101 	ldvp = dunp->un_lowervp;
102 	vp = uvp = lvp = NULLVP;
103 	td = curthread;
104 	*(ap->a_vpp) = NULLVP;
105 
106 	UNIONFS_INTERNAL_DEBUG("unionfs_lookup: enter: nameiop=%ld, flags=%lx, path=%s\n", nameiop, cnflags, cnp->cn_nameptr);
107 
108 	if (dvp->v_type != VDIR)
109 		return (ENOTDIR);
110 
111 	/*
112 	 * If read-only and op is not LOOKUP, will return EROFS.
113 	 */
114 	if ((cnflags & ISLASTCN) &&
115 	    (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
116 	    LOOKUP != nameiop)
117 		return (EROFS);
118 
119 	/*
120 	 * lookup dotdot
121 	 */
122 	if (cnflags & ISDOTDOT) {
123 		if (LOOKUP != nameiop && udvp == NULLVP)
124 			return (EROFS);
125 
126 		if (udvp != NULLVP) {
127 			dtmpvp = udvp;
128 			if (ldvp != NULLVP)
129 				VOP_UNLOCK(ldvp, LK_RELEASE);
130 		}
131 		else
132 			dtmpvp = ldvp;
133 
134 		error = VOP_LOOKUP(dtmpvp, &vp, cnp);
135 
136 		if (dtmpvp == udvp && ldvp != NULLVP) {
137 			VOP_UNLOCK(udvp, LK_RELEASE);
138 			vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
139 		}
140 
141 		if (error == 0) {
142 			/*
143 			 * Exchange lock and reference from vp to
144 			 * dunp->un_dvp. vp is upper/lower vnode, but it
145 			 * will need to return the unionfs vnode.
146 			 */
147 			if (nameiop == DELETE  || nameiop == RENAME ||
148 			    (cnp->cn_lkflags & LK_TYPE_MASK))
149 				VOP_UNLOCK(vp, LK_RELEASE);
150 			vrele(vp);
151 
152 			VOP_UNLOCK(dvp, LK_RELEASE);
153 			*(ap->a_vpp) = dunp->un_dvp;
154 			vref(dunp->un_dvp);
155 
156 			if (nameiop == DELETE || nameiop == RENAME)
157 				vn_lock(dunp->un_dvp, LK_EXCLUSIVE | LK_RETRY);
158 			else if (cnp->cn_lkflags & LK_TYPE_MASK)
159 				vn_lock(dunp->un_dvp, cnp->cn_lkflags |
160 				    LK_RETRY);
161 
162 			vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
163 		} else if (error == ENOENT && (cnflags & MAKEENTRY) &&
164 		    nameiop != CREATE)
165 			cache_enter(dvp, NULLVP, cnp);
166 
167 		UNIONFS_INTERNAL_DEBUG("unionfs_lookup: leave (%d)\n", error);
168 
169 		return (error);
170 	}
171 
172 	/*
173 	 * lookup upper layer
174 	 */
175 	if (udvp != NULLVP) {
176 		uerror = VOP_LOOKUP(udvp, &uvp, cnp);
177 
178 		if (uerror == 0) {
179 			if (udvp == uvp) {	/* is dot */
180 				vrele(uvp);
181 				*(ap->a_vpp) = dvp;
182 				vref(dvp);
183 
184 				UNIONFS_INTERNAL_DEBUG("unionfs_lookup: leave (%d)\n", uerror);
185 
186 				return (uerror);
187 			}
188 			if (nameiop == DELETE || nameiop == RENAME ||
189 			    (cnp->cn_lkflags & LK_TYPE_MASK))
190 				VOP_UNLOCK(uvp, LK_RELEASE);
191 		}
192 
193 		/* check whiteout */
194 		if (uerror == ENOENT || uerror == EJUSTRETURN)
195 			if (cnp->cn_flags & ISWHITEOUT)
196 				iswhiteout = 1;	/* don't lookup lower */
197 		if (iswhiteout == 0 && ldvp != NULLVP)
198 			if (!VOP_GETATTR(udvp, &va, cnp->cn_cred) &&
199 			    (va.va_flags & OPAQUE))
200 				iswhiteout = 1;	/* don't lookup lower */
201 #if 0
202 		UNIONFS_INTERNAL_DEBUG("unionfs_lookup: debug: whiteout=%d, path=%s\n", iswhiteout, cnp->cn_nameptr);
203 #endif
204 	}
205 
206 	/*
207 	 * lookup lower layer
208 	 */
209 	if (ldvp != NULLVP && !(cnflags & DOWHITEOUT) && iswhiteout == 0) {
210 		/* always op is LOOKUP */
211 		cnp->cn_nameiop = LOOKUP;
212 		cnflagsbk = cnp->cn_flags;
213 		cnp->cn_flags = cnflags;
214 
215 		lerror = VOP_LOOKUP(ldvp, &lvp, cnp);
216 
217 		cnp->cn_nameiop = nameiop;
218 		if (udvp != NULLVP && (uerror == 0 || uerror == EJUSTRETURN))
219 			cnp->cn_flags = cnflagsbk;
220 
221 		if (lerror == 0) {
222 			if (ldvp == lvp) {	/* is dot */
223 				if (uvp != NULLVP)
224 					vrele(uvp);	/* no need? */
225 				vrele(lvp);
226 				*(ap->a_vpp) = dvp;
227 				vref(dvp);
228 
229 				UNIONFS_INTERNAL_DEBUG("unionfs_lookup: leave (%d)\n", lerror);
230 
231 				return (lerror);
232 			}
233 			if (cnp->cn_lkflags & LK_TYPE_MASK)
234 				VOP_UNLOCK(lvp, LK_RELEASE);
235 		}
236 	}
237 
238 	/*
239 	 * check lookup result
240 	 */
241 	if (uvp == NULLVP && lvp == NULLVP) {
242 		UNIONFS_INTERNAL_DEBUG("unionfs_lookup: leave (%d)\n",
243 		    (udvp != NULLVP ? uerror : lerror));
244 		return (udvp != NULLVP ? uerror : lerror);
245 	}
246 
247 	/*
248 	 * check vnode type
249 	 */
250 	if (uvp != NULLVP && lvp != NULLVP && uvp->v_type != lvp->v_type) {
251 		vrele(lvp);
252 		lvp = NULLVP;
253 	}
254 
255 	/*
256 	 * check shadow dir
257 	 */
258 	if (uerror != 0 && uerror != EJUSTRETURN && udvp != NULLVP &&
259 	    lerror == 0 && lvp != NULLVP && lvp->v_type == VDIR &&
260 	    !(dvp->v_mount->mnt_flag & MNT_RDONLY) &&
261 	    (1 < cnp->cn_namelen || '.' != *(cnp->cn_nameptr))) {
262 		/* get unionfs vnode in order to create a new shadow dir. */
263 		error = unionfs_nodeget(dvp->v_mount, NULLVP, lvp, dvp, &vp,
264 		    cnp, td);
265 		if (error != 0)
266 			goto unionfs_lookup_out;
267 
268 		if (LK_SHARED == (cnp->cn_lkflags & LK_TYPE_MASK))
269 			VOP_UNLOCK(vp, LK_RELEASE);
270 		if (LK_EXCLUSIVE != VOP_ISLOCKED(vp)) {
271 			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
272 			lockflag = 1;
273 		}
274 		error = unionfs_mkshadowdir(MOUNTTOUNIONFSMOUNT(dvp->v_mount),
275 		    udvp, VTOUNIONFS(vp), cnp, td);
276 		if (lockflag != 0)
277 			VOP_UNLOCK(vp, LK_RELEASE);
278 		if (error != 0) {
279 			UNIONFSDEBUG("unionfs_lookup: Unable to create shadow dir.");
280 			if ((cnp->cn_lkflags & LK_TYPE_MASK) == LK_EXCLUSIVE)
281 				vput(vp);
282 			else
283 				vrele(vp);
284 			goto unionfs_lookup_out;
285 		}
286 		if ((cnp->cn_lkflags & LK_TYPE_MASK) == LK_SHARED)
287 			vn_lock(vp, LK_SHARED | LK_RETRY);
288 	}
289 	/*
290 	 * get unionfs vnode.
291 	 */
292 	else {
293 		if (uvp != NULLVP)
294 			error = uerror;
295 		else
296 			error = lerror;
297 		if (error != 0)
298 			goto unionfs_lookup_out;
299 		/*
300 		 * get socket vnode.
301 		 */
302 		if (uvp != NULLVP && uvp->v_type == VSOCK) {
303 			vp = uvp;
304 			vref(vp);
305 			if (cnp->cn_lkflags & LK_TYPE_MASK)
306 				vn_lock(vp, cnp->cn_lkflags | LK_RETRY);
307 		}
308 		else if (lvp != NULLVP && lvp->v_type == VSOCK) {
309 			vp = lvp;
310 			vref(vp);
311 			if (cnp->cn_lkflags & LK_TYPE_MASK)
312 				vn_lock(vp, cnp->cn_lkflags | LK_RETRY);
313 		}
314 		/*
315 		 * get unionfs vnode.
316 		 */
317 		else
318 			error = unionfs_nodeget(dvp->v_mount, uvp, lvp,
319 			    dvp, &vp, cnp, td);
320 		if (error != 0) {
321 			UNIONFSDEBUG("unionfs_lookup: Unable to create unionfs vnode.");
322 			goto unionfs_lookup_out;
323 		}
324 		if ((nameiop == DELETE || nameiop == RENAME) &&
325 		    (cnp->cn_lkflags & LK_TYPE_MASK) == 0)
326 			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
327 	}
328 
329 	*(ap->a_vpp) = vp;
330 
331 	if ((cnflags & MAKEENTRY) && vp->v_type != VSOCK)
332 		cache_enter(dvp, vp, cnp);
333 
334 unionfs_lookup_out:
335 	if (uvp != NULLVP)
336 		vrele(uvp);
337 	if (lvp != NULLVP)
338 		vrele(lvp);
339 
340 	if (error == ENOENT && (cnflags & MAKEENTRY) && nameiop != CREATE)
341 		cache_enter(dvp, NULLVP, cnp);
342 
343 	UNIONFS_INTERNAL_DEBUG("unionfs_lookup: leave (%d)\n", error);
344 
345 	return (error);
346 }
347 
348 static int
349 unionfs_create(struct vop_create_args *ap)
350 {
351 	struct unionfs_node *dunp;
352 	struct componentname *cnp;
353 	struct vnode   *udvp;
354 	struct vnode   *vp;
355 	int		error;
356 
357 	UNIONFS_INTERNAL_DEBUG("unionfs_create: enter\n");
358 
359 	KASSERT_UNIONFS_VNODE(ap->a_dvp);
360 
361 	dunp = VTOUNIONFS(ap->a_dvp);
362 	cnp = ap->a_cnp;
363 	udvp = dunp->un_uppervp;
364 	error = EROFS;
365 
366 	if (udvp != NULLVP) {
367 		error = VOP_CREATE(udvp, &vp, cnp, ap->a_vap);
368 		if (error != 0)
369 			goto unionfs_create_abort;
370 
371 		if (vp->v_type == VSOCK)
372 			*(ap->a_vpp) = vp;
373 		else {
374 			VOP_UNLOCK(vp, LK_RELEASE);
375 			error = unionfs_nodeget(ap->a_dvp->v_mount, vp, NULLVP,
376 			    ap->a_dvp, ap->a_vpp, cnp, curthread);
377 			vrele(vp);
378 		}
379 	}
380 
381 unionfs_create_abort:
382 	UNIONFS_INTERNAL_DEBUG("unionfs_create: leave (%d)\n", error);
383 
384 	return (error);
385 }
386 
387 static int
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 		switch (ap->a_flags) {
406 		case CREATE:
407 		case DELETE:
408 		case LOOKUP:
409 			error = VOP_WHITEOUT(udvp, cnp, ap->a_flags);
410 			break;
411 		default:
412 			error = EINVAL;
413 			break;
414 		}
415 	}
416 
417 	UNIONFS_INTERNAL_DEBUG("unionfs_whiteout: leave (%d)\n", error);
418 
419 	return (error);
420 }
421 
422 static int
423 unionfs_mknod(struct vop_mknod_args *ap)
424 {
425 	struct unionfs_node *dunp;
426 	struct componentname *cnp;
427 	struct vnode   *udvp;
428 	struct vnode   *vp;
429 	int		error;
430 
431 	UNIONFS_INTERNAL_DEBUG("unionfs_mknod: enter\n");
432 
433 	KASSERT_UNIONFS_VNODE(ap->a_dvp);
434 
435 	dunp = VTOUNIONFS(ap->a_dvp);
436 	cnp = ap->a_cnp;
437 	udvp = dunp->un_uppervp;
438 	error = EROFS;
439 
440 	if (udvp != NULLVP) {
441 		error = VOP_MKNOD(udvp, &vp, cnp, ap->a_vap);
442 		if (error != 0)
443 			goto unionfs_mknod_abort;
444 
445 		if (vp->v_type == VSOCK)
446 			*(ap->a_vpp) = vp;
447 		else {
448 			VOP_UNLOCK(vp, LK_RELEASE);
449 			error = unionfs_nodeget(ap->a_dvp->v_mount, vp, NULLVP,
450 			    ap->a_dvp, ap->a_vpp, cnp, curthread);
451 			vrele(vp);
452 		}
453 	}
454 
455 unionfs_mknod_abort:
456 	UNIONFS_INTERNAL_DEBUG("unionfs_mknod: leave (%d)\n", error);
457 
458 	return (error);
459 }
460 
461 static int
462 unionfs_open(struct vop_open_args *ap)
463 {
464 	int		error;
465 	struct unionfs_node *unp;
466 	struct unionfs_node_status *unsp;
467 	struct vnode   *uvp;
468 	struct vnode   *lvp;
469 	struct vnode   *targetvp;
470 	struct ucred   *cred;
471 	struct thread  *td;
472 
473 	UNIONFS_INTERNAL_DEBUG("unionfs_open: enter\n");
474 
475 	KASSERT_UNIONFS_VNODE(ap->a_vp);
476 
477 	error = 0;
478 	unp = VTOUNIONFS(ap->a_vp);
479 	uvp = unp->un_uppervp;
480 	lvp = unp->un_lowervp;
481 	targetvp = NULLVP;
482 	cred = ap->a_cred;
483 	td = ap->a_td;
484 
485 	unionfs_get_node_status(unp, td, &unsp);
486 
487 	if (unsp->uns_lower_opencnt > 0 || unsp->uns_upper_opencnt > 0) {
488 		/* vnode is already opend. */
489 		if (unsp->uns_upper_opencnt > 0)
490 			targetvp = uvp;
491 		else
492 			targetvp = lvp;
493 
494 		if (targetvp == lvp &&
495 		    (ap->a_mode & FWRITE) && lvp->v_type == VREG)
496 			targetvp = NULLVP;
497 	}
498 	if (targetvp == NULLVP) {
499 		if (uvp == NULLVP) {
500 			if ((ap->a_mode & FWRITE) && lvp->v_type == VREG) {
501 				error = unionfs_copyfile(unp,
502 				    !(ap->a_mode & O_TRUNC), cred, td);
503 				if (error != 0)
504 					goto unionfs_open_abort;
505 				targetvp = uvp = unp->un_uppervp;
506 			} else
507 				targetvp = lvp;
508 		} else
509 			targetvp = uvp;
510 	}
511 
512 	error = VOP_OPEN(targetvp, ap->a_mode, cred, td, ap->a_fp);
513 	if (error == 0) {
514 		if (targetvp == uvp) {
515 			if (uvp->v_type == VDIR && lvp != NULLVP &&
516 			    unsp->uns_lower_opencnt <= 0) {
517 				/* open lower for readdir */
518 				error = VOP_OPEN(lvp, FREAD, cred, td, NULL);
519 				if (error != 0) {
520 					VOP_CLOSE(uvp, ap->a_mode, cred, td);
521 					goto unionfs_open_abort;
522 				}
523 				unsp->uns_node_flag |= UNS_OPENL_4_READDIR;
524 				unsp->uns_lower_opencnt++;
525 			}
526 			unsp->uns_upper_opencnt++;
527 		} else {
528 			unsp->uns_lower_opencnt++;
529 			unsp->uns_lower_openmode = ap->a_mode;
530 		}
531 		ap->a_vp->v_object = targetvp->v_object;
532 	}
533 
534 unionfs_open_abort:
535 	if (error != 0)
536 		unionfs_tryrem_node_status(unp, unsp);
537 
538 	UNIONFS_INTERNAL_DEBUG("unionfs_open: leave (%d)\n", error);
539 
540 	return (error);
541 }
542 
543 static int
544 unionfs_close(struct vop_close_args *ap)
545 {
546 	int		error;
547 	int		locked;
548 	struct unionfs_node *unp;
549 	struct unionfs_node_status *unsp;
550 	struct ucred   *cred;
551 	struct thread  *td;
552 	struct vnode   *vp;
553 	struct vnode   *ovp;
554 
555 	UNIONFS_INTERNAL_DEBUG("unionfs_close: enter\n");
556 
557 	KASSERT_UNIONFS_VNODE(ap->a_vp);
558 
559 	locked = 0;
560 	vp = ap->a_vp;
561 	unp = VTOUNIONFS(vp);
562 	cred = ap->a_cred;
563 	td = ap->a_td;
564 
565 	if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) {
566 		if (vn_lock(vp, LK_UPGRADE) != 0)
567 			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
568 		locked = 1;
569 	}
570 	unionfs_get_node_status(unp, td, &unsp);
571 
572 	if (unsp->uns_lower_opencnt <= 0 && unsp->uns_upper_opencnt <= 0) {
573 #ifdef DIAGNOSTIC
574 		printf("unionfs_close: warning: open count is 0\n");
575 #endif
576 		if (unp->un_uppervp != NULLVP)
577 			ovp = unp->un_uppervp;
578 		else
579 			ovp = unp->un_lowervp;
580 	} else if (unsp->uns_upper_opencnt > 0)
581 		ovp = unp->un_uppervp;
582 	else
583 		ovp = unp->un_lowervp;
584 
585 	error = VOP_CLOSE(ovp, ap->a_fflag, cred, td);
586 
587 	if (error != 0)
588 		goto unionfs_close_abort;
589 
590 	vp->v_object = ovp->v_object;
591 
592 	if (ovp == unp->un_uppervp) {
593 		unsp->uns_upper_opencnt--;
594 		if (unsp->uns_upper_opencnt == 0) {
595 			if (unsp->uns_node_flag & UNS_OPENL_4_READDIR) {
596 				VOP_CLOSE(unp->un_lowervp, FREAD, cred, td);
597 				unsp->uns_node_flag &= ~UNS_OPENL_4_READDIR;
598 				unsp->uns_lower_opencnt--;
599 			}
600 			if (unsp->uns_lower_opencnt > 0)
601 				vp->v_object = unp->un_lowervp->v_object;
602 		}
603 	} else
604 		unsp->uns_lower_opencnt--;
605 
606 unionfs_close_abort:
607 	unionfs_tryrem_node_status(unp, unsp);
608 
609 	if (locked != 0)
610 		vn_lock(vp, LK_DOWNGRADE | LK_RETRY);
611 
612 	UNIONFS_INTERNAL_DEBUG("unionfs_close: leave (%d)\n", error);
613 
614 	return (error);
615 }
616 
617 /*
618  * Check the access mode toward shadow file/dir.
619  */
620 static int
621 unionfs_check_corrected_access(accmode_t accmode,
622 			     struct vattr *va,
623 			     struct ucred *cred)
624 {
625 	int		count;
626 	uid_t		uid;	/* upper side vnode's uid */
627 	gid_t		gid;	/* upper side vnode's gid */
628 	u_short		vmode;	/* upper side vnode's mode */
629 	u_short		mask;
630 
631 	mask = 0;
632 	uid = va->va_uid;
633 	gid = va->va_gid;
634 	vmode = va->va_mode;
635 
636 	/* check owner */
637 	if (cred->cr_uid == uid) {
638 		if (accmode & VEXEC)
639 			mask |= S_IXUSR;
640 		if (accmode & VREAD)
641 			mask |= S_IRUSR;
642 		if (accmode & VWRITE)
643 			mask |= S_IWUSR;
644 		return ((vmode & mask) == mask ? 0 : EACCES);
645 	}
646 
647 	/* check group */
648 	count = 0;
649 	if (groupmember(gid, cred)) {
650 		if (accmode & VEXEC)
651 			mask |= S_IXGRP;
652 		if (accmode & VREAD)
653 			mask |= S_IRGRP;
654 		if (accmode & VWRITE)
655 			mask |= S_IWGRP;
656 		return ((vmode & mask) == mask ? 0 : EACCES);
657 	}
658 
659 	/* check other */
660 	if (accmode & VEXEC)
661 		mask |= S_IXOTH;
662 	if (accmode & VREAD)
663 		mask |= S_IROTH;
664 	if (accmode & VWRITE)
665 		mask |= S_IWOTH;
666 
667 	return ((vmode & mask) == mask ? 0 : EACCES);
668 }
669 
670 static int
671 unionfs_access(struct vop_access_args *ap)
672 {
673 	struct unionfs_mount *ump;
674 	struct unionfs_node *unp;
675 	struct vnode   *uvp;
676 	struct vnode   *lvp;
677 	struct thread  *td;
678 	struct vattr	va;
679 	accmode_t	accmode;
680 	int		error;
681 
682 	UNIONFS_INTERNAL_DEBUG("unionfs_access: enter\n");
683 
684 	KASSERT_UNIONFS_VNODE(ap->a_vp);
685 
686 	ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount);
687 	unp = VTOUNIONFS(ap->a_vp);
688 	uvp = unp->un_uppervp;
689 	lvp = unp->un_lowervp;
690 	td = ap->a_td;
691 	accmode = ap->a_accmode;
692 	error = EACCES;
693 
694 	if ((accmode & VWRITE) &&
695 	    (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)) {
696 		switch (ap->a_vp->v_type) {
697 		case VREG:
698 		case VDIR:
699 		case VLNK:
700 			return (EROFS);
701 		default:
702 			break;
703 		}
704 	}
705 
706 	if (uvp != NULLVP) {
707 		error = VOP_ACCESS(uvp, accmode, ap->a_cred, td);
708 
709 		UNIONFS_INTERNAL_DEBUG("unionfs_access: leave (%d)\n", error);
710 
711 		return (error);
712 	}
713 
714 	if (lvp != NULLVP) {
715 		if (accmode & VWRITE) {
716 			if (ump->um_uppervp->v_mount->mnt_flag & MNT_RDONLY) {
717 				switch (ap->a_vp->v_type) {
718 				case VREG:
719 				case VDIR:
720 				case VLNK:
721 					return (EROFS);
722 				default:
723 					break;
724 				}
725 			} else if (ap->a_vp->v_type == VREG || ap->a_vp->v_type == VDIR) {
726 				/* check shadow file/dir */
727 				if (ump->um_copymode != UNIONFS_TRANSPARENT) {
728 					error = unionfs_create_uppervattr(ump,
729 					    lvp, &va, ap->a_cred, td);
730 					if (error != 0)
731 						return (error);
732 
733 					error = unionfs_check_corrected_access(
734 					    accmode, &va, ap->a_cred);
735 					if (error != 0)
736 						return (error);
737 				}
738 			}
739 			accmode &= ~(VWRITE | VAPPEND);
740 			accmode |= VREAD; /* will copy to upper */
741 		}
742 		error = VOP_ACCESS(lvp, accmode, ap->a_cred, td);
743 	}
744 
745 	UNIONFS_INTERNAL_DEBUG("unionfs_access: leave (%d)\n", error);
746 
747 	return (error);
748 }
749 
750 static int
751 unionfs_getattr(struct vop_getattr_args *ap)
752 {
753 	int		error;
754 	struct unionfs_node *unp;
755 	struct unionfs_mount *ump;
756 	struct vnode   *uvp;
757 	struct vnode   *lvp;
758 	struct thread  *td;
759 	struct vattr	va;
760 
761 	UNIONFS_INTERNAL_DEBUG("unionfs_getattr: enter\n");
762 
763 	KASSERT_UNIONFS_VNODE(ap->a_vp);
764 
765 	unp = VTOUNIONFS(ap->a_vp);
766 	ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount);
767 	uvp = unp->un_uppervp;
768 	lvp = unp->un_lowervp;
769 	td = curthread;
770 
771 	if (uvp != NULLVP) {
772 		if ((error = VOP_GETATTR(uvp, ap->a_vap, ap->a_cred)) == 0)
773 			ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
774 
775 		UNIONFS_INTERNAL_DEBUG("unionfs_getattr: leave mode=%o, uid=%d, gid=%d (%d)\n",
776 		    ap->a_vap->va_mode, ap->a_vap->va_uid,
777 		    ap->a_vap->va_gid, error);
778 
779 		return (error);
780 	}
781 
782 	error = VOP_GETATTR(lvp, ap->a_vap, ap->a_cred);
783 
784 	if (error == 0 && !(ump->um_uppervp->v_mount->mnt_flag & MNT_RDONLY)) {
785 		/* correct the attr toward shadow file/dir. */
786 		if (ap->a_vp->v_type == VREG || ap->a_vp->v_type == VDIR) {
787 			unionfs_create_uppervattr_core(ump, ap->a_vap, &va, td);
788 			ap->a_vap->va_mode = va.va_mode;
789 			ap->a_vap->va_uid = va.va_uid;
790 			ap->a_vap->va_gid = va.va_gid;
791 		}
792 	}
793 
794 	if (error == 0)
795 		ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
796 
797 	UNIONFS_INTERNAL_DEBUG("unionfs_getattr: leave mode=%o, uid=%d, gid=%d (%d)\n",
798 	    ap->a_vap->va_mode, ap->a_vap->va_uid, ap->a_vap->va_gid, error);
799 
800 	return (error);
801 }
802 
803 static int
804 unionfs_setattr(struct vop_setattr_args *ap)
805 {
806 	int		error;
807 	struct unionfs_node *unp;
808 	struct vnode   *uvp;
809 	struct vnode   *lvp;
810 	struct thread  *td;
811 	struct vattr   *vap;
812 
813 	UNIONFS_INTERNAL_DEBUG("unionfs_setattr: enter\n");
814 
815 	KASSERT_UNIONFS_VNODE(ap->a_vp);
816 
817 	error = EROFS;
818 	unp = VTOUNIONFS(ap->a_vp);
819 	uvp = unp->un_uppervp;
820 	lvp = unp->un_lowervp;
821 	td = curthread;
822 	vap = ap->a_vap;
823 
824 	if ((ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) &&
825 	    (vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
826 	     vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
827 	     vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL))
828 		return (EROFS);
829 
830 	if (uvp == NULLVP && lvp->v_type == VREG) {
831 		error = unionfs_copyfile(unp, (vap->va_size != 0),
832 		    ap->a_cred, td);
833 		if (error != 0)
834 			return (error);
835 		uvp = unp->un_uppervp;
836 	}
837 
838 	if (uvp != NULLVP)
839 		error = VOP_SETATTR(uvp, vap, ap->a_cred);
840 
841 	UNIONFS_INTERNAL_DEBUG("unionfs_setattr: leave (%d)\n", error);
842 
843 	return (error);
844 }
845 
846 static int
847 unionfs_read(struct vop_read_args *ap)
848 {
849 	int		error;
850 	struct unionfs_node *unp;
851 	struct vnode   *tvp;
852 
853 	/* UNIONFS_INTERNAL_DEBUG("unionfs_read: enter\n"); */
854 
855 	KASSERT_UNIONFS_VNODE(ap->a_vp);
856 
857 	unp = VTOUNIONFS(ap->a_vp);
858 	tvp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp);
859 
860 	error = VOP_READ(tvp, ap->a_uio, ap->a_ioflag, ap->a_cred);
861 
862 	/* UNIONFS_INTERNAL_DEBUG("unionfs_read: leave (%d)\n", error); */
863 
864 	return (error);
865 }
866 
867 static int
868 unionfs_write(struct vop_write_args *ap)
869 {
870 	int		error;
871 	struct unionfs_node *unp;
872 	struct vnode   *tvp;
873 
874 	/* UNIONFS_INTERNAL_DEBUG("unionfs_write: enter\n"); */
875 
876 	KASSERT_UNIONFS_VNODE(ap->a_vp);
877 
878 	unp = VTOUNIONFS(ap->a_vp);
879 	tvp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp);
880 
881 	error = VOP_WRITE(tvp, ap->a_uio, ap->a_ioflag, ap->a_cred);
882 
883 	/* UNIONFS_INTERNAL_DEBUG("unionfs_write: leave (%d)\n", error); */
884 
885 	return (error);
886 }
887 
888 static int
889 unionfs_ioctl(struct vop_ioctl_args *ap)
890 {
891 	int error;
892 	struct unionfs_node *unp;
893 	struct unionfs_node_status *unsp;
894 	struct vnode   *ovp;
895 
896 	UNIONFS_INTERNAL_DEBUG("unionfs_ioctl: enter\n");
897 
898 	KASSERT_UNIONFS_VNODE(ap->a_vp);
899 
900  	vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY);
901 	unp = VTOUNIONFS(ap->a_vp);
902 	unionfs_get_node_status(unp, ap->a_td, &unsp);
903 	ovp = (unsp->uns_upper_opencnt ? unp->un_uppervp : unp->un_lowervp);
904 	unionfs_tryrem_node_status(unp, unsp);
905 	VOP_UNLOCK(ap->a_vp, LK_RELEASE);
906 
907 	if (ovp == NULLVP)
908 		return (EBADF);
909 
910 	error = VOP_IOCTL(ovp, ap->a_command, ap->a_data, ap->a_fflag,
911 	    ap->a_cred, ap->a_td);
912 
913 	UNIONFS_INTERNAL_DEBUG("unionfs_ioctl: leave (%d)\n", error);
914 
915 	return (error);
916 }
917 
918 static int
919 unionfs_poll(struct vop_poll_args *ap)
920 {
921 	struct unionfs_node *unp;
922 	struct unionfs_node_status *unsp;
923 	struct vnode   *ovp;
924 
925 	KASSERT_UNIONFS_VNODE(ap->a_vp);
926 
927  	vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY);
928 	unp = VTOUNIONFS(ap->a_vp);
929 	unionfs_get_node_status(unp, ap->a_td, &unsp);
930 	ovp = (unsp->uns_upper_opencnt ? unp->un_uppervp : unp->un_lowervp);
931 	unionfs_tryrem_node_status(unp, unsp);
932 	VOP_UNLOCK(ap->a_vp, LK_RELEASE);
933 
934 	if (ovp == NULLVP)
935 		return (EBADF);
936 
937 	return (VOP_POLL(ovp, ap->a_events, ap->a_cred, ap->a_td));
938 }
939 
940 static int
941 unionfs_fsync(struct vop_fsync_args *ap)
942 {
943 	struct unionfs_node *unp;
944 	struct unionfs_node_status *unsp;
945 	struct vnode   *ovp;
946 
947 	KASSERT_UNIONFS_VNODE(ap->a_vp);
948 
949 	unp = VTOUNIONFS(ap->a_vp);
950 	unionfs_get_node_status(unp, ap->a_td, &unsp);
951 	ovp = (unsp->uns_upper_opencnt ? unp->un_uppervp : unp->un_lowervp);
952 	unionfs_tryrem_node_status(unp, unsp);
953 
954 	if (ovp == NULLVP)
955 		return (EBADF);
956 
957 	return (VOP_FSYNC(ovp, ap->a_waitfor, ap->a_td));
958 }
959 
960 static int
961 unionfs_remove(struct vop_remove_args *ap)
962 {
963 	int		error;
964 	char	       *path;
965 	struct unionfs_node *dunp;
966 	struct unionfs_node *unp;
967 	struct unionfs_mount *ump;
968 	struct vnode   *udvp;
969 	struct vnode   *uvp;
970 	struct vnode   *lvp;
971 	struct vnode   *vp;
972 	struct componentname *cnp;
973 	struct componentname cn;
974 	struct thread  *td;
975 
976 	UNIONFS_INTERNAL_DEBUG("unionfs_remove: enter\n");
977 
978 	KASSERT_UNIONFS_VNODE(ap->a_dvp);
979 
980 	error = 0;
981 	dunp = VTOUNIONFS(ap->a_dvp);
982 	udvp = dunp->un_uppervp;
983 	cnp = ap->a_cnp;
984 	td = curthread;
985 
986 	if (ap->a_vp->v_op != &unionfs_vnodeops) {
987 		if (ap->a_vp->v_type != VSOCK)
988 			return (EINVAL);
989 		ump = NULL;
990 		vp = uvp = lvp = NULLVP;
991 		/* search vnode */
992 		VOP_UNLOCK(ap->a_vp, LK_RELEASE);
993 		error = unionfs_relookup(udvp, &vp, cnp, &cn, td,
994 		    cnp->cn_nameptr, strlen(cnp->cn_nameptr), DELETE);
995 		if (error != 0 && error != ENOENT) {
996 			vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY);
997 			return (error);
998 		}
999 
1000 		if (error == 0 && vp == ap->a_vp) {
1001 			/* target vnode in upper */
1002 			uvp = vp;
1003 			vrele(vp);
1004 			path = NULL;
1005 		} else {
1006 			/* target vnode in lower */
1007 			if (vp != NULLVP) {
1008 				if (udvp == vp)
1009 					vrele(vp);
1010 				else
1011 					vput(vp);
1012 			}
1013 			vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY);
1014 			lvp = ap->a_vp;
1015 			path = ap->a_cnp->cn_nameptr;
1016 		}
1017 	} else {
1018 		ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount);
1019 		unp = VTOUNIONFS(ap->a_vp);
1020 		uvp = unp->un_uppervp;
1021 		lvp = unp->un_lowervp;
1022 		path = unp->un_path;
1023 	}
1024 
1025 	if (udvp == NULLVP)
1026 		return (EROFS);
1027 
1028 	if (uvp != NULLVP) {
1029 		/*
1030 		 * XXX: if the vnode type is VSOCK, it will create whiteout
1031 		 *      after remove.
1032 		 */
1033 		if (ump == NULL || ump->um_whitemode == UNIONFS_WHITE_ALWAYS ||
1034 		    lvp != NULLVP)
1035 			cnp->cn_flags |= DOWHITEOUT;
1036 		error = VOP_REMOVE(udvp, uvp, cnp);
1037 	} else if (lvp != NULLVP)
1038 		error = unionfs_mkwhiteout(udvp, cnp, td, path);
1039 
1040 	UNIONFS_INTERNAL_DEBUG("unionfs_remove: leave (%d)\n", error);
1041 
1042 	return (error);
1043 }
1044 
1045 static int
1046 unionfs_link(struct vop_link_args *ap)
1047 {
1048 	int		error;
1049 	int		needrelookup;
1050 	struct unionfs_node *dunp;
1051 	struct unionfs_node *unp;
1052 	struct vnode   *udvp;
1053 	struct vnode   *uvp;
1054 	struct componentname *cnp;
1055 	struct thread  *td;
1056 
1057 	UNIONFS_INTERNAL_DEBUG("unionfs_link: enter\n");
1058 
1059 	KASSERT_UNIONFS_VNODE(ap->a_tdvp);
1060 	KASSERT_UNIONFS_VNODE(ap->a_vp);
1061 
1062 	error = 0;
1063 	needrelookup = 0;
1064 	dunp = VTOUNIONFS(ap->a_tdvp);
1065 	unp = NULL;
1066 	udvp = dunp->un_uppervp;
1067 	uvp = NULLVP;
1068 	cnp = ap->a_cnp;
1069 	td = curthread;
1070 
1071 	if (udvp == NULLVP)
1072 		return (EROFS);
1073 
1074 	if (ap->a_vp->v_op != &unionfs_vnodeops)
1075 		uvp = ap->a_vp;
1076 	else {
1077 		unp = VTOUNIONFS(ap->a_vp);
1078 
1079 		if (unp->un_uppervp == NULLVP) {
1080 			if (ap->a_vp->v_type != VREG)
1081 				return (EOPNOTSUPP);
1082 
1083 			error = unionfs_copyfile(unp, 1, cnp->cn_cred, td);
1084 			if (error != 0)
1085 				return (error);
1086 			needrelookup = 1;
1087 		}
1088 		uvp = unp->un_uppervp;
1089 	}
1090 
1091 	if (needrelookup != 0)
1092 		error = unionfs_relookup_for_create(ap->a_tdvp, cnp, td);
1093 
1094 	if (error == 0)
1095 		error = VOP_LINK(udvp, uvp, cnp);
1096 
1097 	UNIONFS_INTERNAL_DEBUG("unionfs_link: leave (%d)\n", error);
1098 
1099 	return (error);
1100 }
1101 
1102 static int
1103 unionfs_rename(struct vop_rename_args *ap)
1104 {
1105 	int		error;
1106 	struct vnode   *fdvp;
1107 	struct vnode   *fvp;
1108 	struct componentname *fcnp;
1109 	struct vnode   *tdvp;
1110 	struct vnode   *tvp;
1111 	struct componentname *tcnp;
1112 	struct vnode   *ltdvp;
1113 	struct vnode   *ltvp;
1114 	struct thread  *td;
1115 
1116 	/* rename target vnodes */
1117 	struct vnode   *rfdvp;
1118 	struct vnode   *rfvp;
1119 	struct vnode   *rtdvp;
1120 	struct vnode   *rtvp;
1121 
1122 	int		needrelookup;
1123 	struct unionfs_mount *ump;
1124 	struct unionfs_node *unp;
1125 
1126 	UNIONFS_INTERNAL_DEBUG("unionfs_rename: enter\n");
1127 
1128 	error = 0;
1129 	fdvp = ap->a_fdvp;
1130 	fvp = ap->a_fvp;
1131 	fcnp = ap->a_fcnp;
1132 	tdvp = ap->a_tdvp;
1133 	tvp = ap->a_tvp;
1134 	tcnp = ap->a_tcnp;
1135 	ltdvp = NULLVP;
1136 	ltvp = NULLVP;
1137 	td = curthread;
1138 	rfdvp = fdvp;
1139 	rfvp = fvp;
1140 	rtdvp = tdvp;
1141 	rtvp = tvp;
1142 	needrelookup = 0;
1143 
1144 #ifdef DIAGNOSTIC
1145 	if (!(fcnp->cn_flags & HASBUF) || !(tcnp->cn_flags & HASBUF))
1146 		panic("unionfs_rename: no name");
1147 #endif
1148 
1149 	/* check for cross device rename */
1150 	if (fvp->v_mount != tdvp->v_mount ||
1151 	    (tvp != NULLVP && fvp->v_mount != tvp->v_mount)) {
1152 		if (fvp->v_op != &unionfs_vnodeops)
1153 			error = ENODEV;
1154 		else
1155 			error = EXDEV;
1156 		goto unionfs_rename_abort;
1157 	}
1158 
1159 	/* Renaming a file to itself has no effect. */
1160 	if (fvp == tvp)
1161 		goto unionfs_rename_abort;
1162 
1163 	/*
1164 	 * from/to vnode is unionfs node.
1165 	 */
1166 
1167 	KASSERT_UNIONFS_VNODE(fdvp);
1168 	KASSERT_UNIONFS_VNODE(fvp);
1169 	KASSERT_UNIONFS_VNODE(tdvp);
1170 	if (tvp != NULLVP)
1171 		KASSERT_UNIONFS_VNODE(tvp);
1172 
1173 	unp = VTOUNIONFS(fdvp);
1174 #ifdef UNIONFS_IDBG_RENAME
1175 	UNIONFS_INTERNAL_DEBUG("fdvp=%p, ufdvp=%p, lfdvp=%p\n", fdvp, unp->un_uppervp, unp->un_lowervp);
1176 #endif
1177 	if (unp->un_uppervp == NULLVP) {
1178 		error = ENODEV;
1179 		goto unionfs_rename_abort;
1180 	}
1181 	rfdvp = unp->un_uppervp;
1182 	vref(rfdvp);
1183 
1184 	unp = VTOUNIONFS(fvp);
1185 #ifdef UNIONFS_IDBG_RENAME
1186 	UNIONFS_INTERNAL_DEBUG("fvp=%p, ufvp=%p, lfvp=%p\n", fvp, unp->un_uppervp, unp->un_lowervp);
1187 #endif
1188 	ump = MOUNTTOUNIONFSMOUNT(fvp->v_mount);
1189 	if (unp->un_uppervp == NULLVP) {
1190 		switch (fvp->v_type) {
1191 		case VREG:
1192 			if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0)
1193 				goto unionfs_rename_abort;
1194 			error = unionfs_copyfile(unp, 1, fcnp->cn_cred, td);
1195 			VOP_UNLOCK(fvp, LK_RELEASE);
1196 			if (error != 0)
1197 				goto unionfs_rename_abort;
1198 			break;
1199 		case VDIR:
1200 			if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0)
1201 				goto unionfs_rename_abort;
1202 			error = unionfs_mkshadowdir(ump, rfdvp, unp, fcnp, td);
1203 			VOP_UNLOCK(fvp, LK_RELEASE);
1204 			if (error != 0)
1205 				goto unionfs_rename_abort;
1206 			break;
1207 		default:
1208 			error = ENODEV;
1209 			goto unionfs_rename_abort;
1210 		}
1211 
1212 		needrelookup = 1;
1213 	}
1214 
1215 	if (unp->un_lowervp != NULLVP)
1216 		fcnp->cn_flags |= DOWHITEOUT;
1217 	rfvp = unp->un_uppervp;
1218 	vref(rfvp);
1219 
1220 	unp = VTOUNIONFS(tdvp);
1221 #ifdef UNIONFS_IDBG_RENAME
1222 	UNIONFS_INTERNAL_DEBUG("tdvp=%p, utdvp=%p, ltdvp=%p\n", tdvp, unp->un_uppervp, unp->un_lowervp);
1223 #endif
1224 	if (unp->un_uppervp == NULLVP) {
1225 		error = ENODEV;
1226 		goto unionfs_rename_abort;
1227 	}
1228 	rtdvp = unp->un_uppervp;
1229 	ltdvp = unp->un_lowervp;
1230 	vref(rtdvp);
1231 
1232 	if (tdvp == tvp) {
1233 		rtvp = rtdvp;
1234 		vref(rtvp);
1235 	} else if (tvp != NULLVP) {
1236 		unp = VTOUNIONFS(tvp);
1237 #ifdef UNIONFS_IDBG_RENAME
1238 		UNIONFS_INTERNAL_DEBUG("tvp=%p, utvp=%p, ltvp=%p\n", tvp, unp->un_uppervp, unp->un_lowervp);
1239 #endif
1240 		if (unp->un_uppervp == NULLVP)
1241 			rtvp = NULLVP;
1242 		else {
1243 			if (tvp->v_type == VDIR) {
1244 				error = EINVAL;
1245 				goto unionfs_rename_abort;
1246 			}
1247 			rtvp = unp->un_uppervp;
1248 			ltvp = unp->un_lowervp;
1249 			vref(rtvp);
1250 		}
1251 	}
1252 
1253 	if (rfvp == rtvp)
1254 		goto unionfs_rename_abort;
1255 
1256 	if (needrelookup != 0) {
1257 		if ((error = vn_lock(fdvp, LK_EXCLUSIVE)) != 0)
1258 			goto unionfs_rename_abort;
1259 		error = unionfs_relookup_for_delete(fdvp, fcnp, td);
1260 		VOP_UNLOCK(fdvp, LK_RELEASE);
1261 		if (error != 0)
1262 			goto unionfs_rename_abort;
1263 
1264 		/* Locke of tvp is canceled in order to avoid recursive lock. */
1265 		if (tvp != NULLVP && tvp != tdvp)
1266 			VOP_UNLOCK(tvp, LK_RELEASE);
1267 		error = unionfs_relookup_for_rename(tdvp, tcnp, td);
1268 		if (tvp != NULLVP && tvp != tdvp)
1269 			vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY);
1270 		if (error != 0)
1271 			goto unionfs_rename_abort;
1272 	}
1273 
1274 	error = VOP_RENAME(rfdvp, rfvp, fcnp, rtdvp, rtvp, tcnp);
1275 
1276 	if (error == 0) {
1277 		if (rtvp != NULLVP && rtvp->v_type == VDIR)
1278 			cache_purge(tdvp);
1279 		if (fvp->v_type == VDIR && fdvp != tdvp)
1280 			cache_purge(fdvp);
1281 	}
1282 
1283 	if (ltdvp != NULLVP)
1284 		VOP_UNLOCK(ltdvp, LK_RELEASE);
1285 	if (tdvp != rtdvp)
1286 		vrele(tdvp);
1287 	if (ltvp != NULLVP)
1288 		VOP_UNLOCK(ltvp, LK_RELEASE);
1289 	if (tvp != rtvp && tvp != NULLVP) {
1290 		if (rtvp == NULLVP)
1291 			vput(tvp);
1292 		else
1293 			vrele(tvp);
1294 	}
1295 	if (fdvp != rfdvp)
1296 		vrele(fdvp);
1297 	if (fvp != rfvp)
1298 		vrele(fvp);
1299 
1300 	UNIONFS_INTERNAL_DEBUG("unionfs_rename: leave (%d)\n", error);
1301 
1302 	return (error);
1303 
1304 unionfs_rename_abort:
1305 	vput(tdvp);
1306 	if (tdvp != rtdvp)
1307 		vrele(rtdvp);
1308 	if (tvp != NULLVP) {
1309 		if (tdvp != tvp)
1310 			vput(tvp);
1311 		else
1312 			vrele(tvp);
1313 	}
1314 	if (tvp != rtvp && rtvp != NULLVP)
1315 		vrele(rtvp);
1316 	if (fdvp != rfdvp)
1317 		vrele(rfdvp);
1318 	if (fvp != rfvp)
1319 		vrele(rfvp);
1320 	vrele(fdvp);
1321 	vrele(fvp);
1322 
1323 	UNIONFS_INTERNAL_DEBUG("unionfs_rename: leave (%d)\n", error);
1324 
1325 	return (error);
1326 }
1327 
1328 static int
1329 unionfs_mkdir(struct vop_mkdir_args *ap)
1330 {
1331 	int		error;
1332 	int		lkflags;
1333 	struct unionfs_node *dunp;
1334 	struct componentname *cnp;
1335 	struct thread  *td;
1336 	struct vnode   *udvp;
1337 	struct vnode   *uvp;
1338 	struct vattr	va;
1339 
1340 	UNIONFS_INTERNAL_DEBUG("unionfs_mkdir: enter\n");
1341 
1342 	KASSERT_UNIONFS_VNODE(ap->a_dvp);
1343 
1344 	error = EROFS;
1345 	dunp = VTOUNIONFS(ap->a_dvp);
1346 	cnp = ap->a_cnp;
1347 	lkflags = cnp->cn_lkflags;
1348 	td = curthread;
1349 	udvp = dunp->un_uppervp;
1350 
1351 	if (udvp != NULLVP) {
1352 		/* check opaque */
1353 		if (!(cnp->cn_flags & ISWHITEOUT)) {
1354 			error = VOP_GETATTR(udvp, &va, cnp->cn_cred);
1355 			if (error != 0)
1356 				return (error);
1357 			if (va.va_flags & OPAQUE)
1358 				cnp->cn_flags |= ISWHITEOUT;
1359 		}
1360 
1361 		if ((error = VOP_MKDIR(udvp, &uvp, cnp, ap->a_vap)) == 0) {
1362 			VOP_UNLOCK(uvp, LK_RELEASE);
1363 			cnp->cn_lkflags = LK_EXCLUSIVE;
1364 			error = unionfs_nodeget(ap->a_dvp->v_mount, uvp, NULLVP,
1365 			    ap->a_dvp, ap->a_vpp, cnp, td);
1366 			cnp->cn_lkflags = lkflags;
1367 			vrele(uvp);
1368 		}
1369 	}
1370 
1371 	UNIONFS_INTERNAL_DEBUG("unionfs_mkdir: leave (%d)\n", error);
1372 
1373 	return (error);
1374 }
1375 
1376 static int
1377 unionfs_rmdir(struct vop_rmdir_args *ap)
1378 {
1379 	int		error;
1380 	struct unionfs_node *dunp;
1381 	struct unionfs_node *unp;
1382 	struct unionfs_mount *ump;
1383 	struct componentname *cnp;
1384 	struct thread  *td;
1385 	struct vnode   *udvp;
1386 	struct vnode   *uvp;
1387 	struct vnode   *lvp;
1388 
1389 	UNIONFS_INTERNAL_DEBUG("unionfs_rmdir: enter\n");
1390 
1391 	KASSERT_UNIONFS_VNODE(ap->a_dvp);
1392 	KASSERT_UNIONFS_VNODE(ap->a_vp);
1393 
1394 	error = 0;
1395 	dunp = VTOUNIONFS(ap->a_dvp);
1396 	unp = VTOUNIONFS(ap->a_vp);
1397 	cnp = ap->a_cnp;
1398 	td = curthread;
1399 	udvp = dunp->un_uppervp;
1400 	uvp = unp->un_uppervp;
1401 	lvp = unp->un_lowervp;
1402 
1403 	if (udvp == NULLVP)
1404 		return (EROFS);
1405 
1406 	if (udvp == uvp)
1407 		return (EOPNOTSUPP);
1408 
1409 	if (uvp != NULLVP) {
1410 		if (lvp != NULLVP) {
1411 			error = unionfs_check_rmdir(ap->a_vp, cnp->cn_cred, td);
1412 			if (error != 0)
1413 				return (error);
1414 		}
1415 		ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount);
1416 		if (ump->um_whitemode == UNIONFS_WHITE_ALWAYS || lvp != NULLVP)
1417 			cnp->cn_flags |= DOWHITEOUT;
1418 		error = unionfs_relookup_for_delete(ap->a_dvp, cnp, td);
1419 		if (!error)
1420 			error = VOP_RMDIR(udvp, uvp, cnp);
1421 	}
1422 	else if (lvp != NULLVP)
1423 		error = unionfs_mkwhiteout(udvp, cnp, td, unp->un_path);
1424 
1425 	if (error == 0) {
1426 		cache_purge(ap->a_dvp);
1427 		cache_purge(ap->a_vp);
1428 	}
1429 
1430 	UNIONFS_INTERNAL_DEBUG("unionfs_rmdir: leave (%d)\n", error);
1431 
1432 	return (error);
1433 }
1434 
1435 static int
1436 unionfs_symlink(struct vop_symlink_args *ap)
1437 {
1438 	int		error;
1439 	int		lkflags;
1440 	struct unionfs_node *dunp;
1441 	struct componentname *cnp;
1442 	struct thread  *td;
1443 	struct vnode   *udvp;
1444 	struct vnode   *uvp;
1445 
1446 	UNIONFS_INTERNAL_DEBUG("unionfs_symlink: enter\n");
1447 
1448 	KASSERT_UNIONFS_VNODE(ap->a_dvp);
1449 
1450 	error = EROFS;
1451 	dunp = VTOUNIONFS(ap->a_dvp);
1452 	cnp = ap->a_cnp;
1453 	lkflags = cnp->cn_lkflags;
1454 	td = curthread;
1455 	udvp = dunp->un_uppervp;
1456 
1457 	if (udvp != NULLVP) {
1458 		error = VOP_SYMLINK(udvp, &uvp, cnp, ap->a_vap, ap->a_target);
1459 		if (error == 0) {
1460 			VOP_UNLOCK(uvp, LK_RELEASE);
1461 			cnp->cn_lkflags = LK_EXCLUSIVE;
1462 			error = unionfs_nodeget(ap->a_dvp->v_mount, uvp, NULLVP,
1463 			    ap->a_dvp, ap->a_vpp, cnp, td);
1464 			cnp->cn_lkflags = lkflags;
1465 			vrele(uvp);
1466 		}
1467 	}
1468 
1469 	UNIONFS_INTERNAL_DEBUG("unionfs_symlink: leave (%d)\n", error);
1470 
1471 	return (error);
1472 }
1473 
1474 static int
1475 unionfs_readdir(struct vop_readdir_args *ap)
1476 {
1477 	int		error;
1478 	int		eofflag;
1479 	int		locked;
1480 	int		uio_offset_bk;
1481 	struct unionfs_node *unp;
1482 	struct unionfs_node_status *unsp;
1483 	struct uio     *uio;
1484 	struct vnode   *vp;
1485 	struct vnode   *uvp;
1486 	struct vnode   *lvp;
1487 	struct thread  *td;
1488 	struct vattr    va;
1489 
1490 	int		ncookies_bk;
1491 	u_long         *cookies_bk;
1492 
1493 	UNIONFS_INTERNAL_DEBUG("unionfs_readdir: enter\n");
1494 
1495 	KASSERT_UNIONFS_VNODE(ap->a_vp);
1496 
1497 	error = 0;
1498 	eofflag = 0;
1499 	locked = 0;
1500 	uio_offset_bk = 0;
1501 	uio = ap->a_uio;
1502 	uvp = NULLVP;
1503 	lvp = NULLVP;
1504 	td = uio->uio_td;
1505 	ncookies_bk = 0;
1506 	cookies_bk = NULL;
1507 
1508 	vp = ap->a_vp;
1509 	if (vp->v_type != VDIR)
1510 		return (ENOTDIR);
1511 
1512 	/* check the open count. unionfs needs to open before readdir. */
1513 	if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) {
1514 		if (vn_lock(vp, LK_UPGRADE) != 0)
1515 			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1516 		locked = 1;
1517 	}
1518 	unp = VTOUNIONFS(vp);
1519 	if (unp == NULL)
1520 		error = EBADF;
1521 	else {
1522 		uvp = unp->un_uppervp;
1523 		lvp = unp->un_lowervp;
1524 		unionfs_get_node_status(unp, td, &unsp);
1525 		if ((uvp != NULLVP && unsp->uns_upper_opencnt <= 0) ||
1526 			(lvp != NULLVP && unsp->uns_lower_opencnt <= 0)) {
1527 			unionfs_tryrem_node_status(unp, unsp);
1528 			error = EBADF;
1529 		}
1530 	}
1531 	if (locked)
1532 		vn_lock(vp, LK_DOWNGRADE | LK_RETRY);
1533 	if (error != 0)
1534 		goto unionfs_readdir_exit;
1535 
1536 	/* check opaque */
1537 	if (uvp != NULLVP && lvp != NULLVP) {
1538 		if ((error = VOP_GETATTR(uvp, &va, ap->a_cred)) != 0)
1539 			goto unionfs_readdir_exit;
1540 		if (va.va_flags & OPAQUE)
1541 			lvp = NULLVP;
1542 	}
1543 
1544 	/* upper only */
1545 	if (uvp != NULLVP && lvp == NULLVP) {
1546 		error = VOP_READDIR(uvp, uio, ap->a_cred, ap->a_eofflag,
1547 		    ap->a_ncookies, ap->a_cookies);
1548 		unsp->uns_readdir_status = 0;
1549 
1550 		goto unionfs_readdir_exit;
1551 	}
1552 
1553 	/* lower only */
1554 	if (uvp == NULLVP && lvp != NULLVP) {
1555 		error = VOP_READDIR(lvp, uio, ap->a_cred, ap->a_eofflag,
1556 		    ap->a_ncookies, ap->a_cookies);
1557 		unsp->uns_readdir_status = 2;
1558 
1559 		goto unionfs_readdir_exit;
1560 	}
1561 
1562 	/*
1563 	 * readdir upper and lower
1564 	 */
1565 	KASSERT(uvp != NULLVP, ("unionfs_readdir: null upper vp"));
1566 	KASSERT(lvp != NULLVP, ("unionfs_readdir: null lower vp"));
1567 	if (uio->uio_offset == 0)
1568 		unsp->uns_readdir_status = 0;
1569 
1570 	if (unsp->uns_readdir_status == 0) {
1571 		/* read upper */
1572 		error = VOP_READDIR(uvp, uio, ap->a_cred, &eofflag,
1573 				    ap->a_ncookies, ap->a_cookies);
1574 
1575 		if (error != 0 || eofflag == 0)
1576 			goto unionfs_readdir_exit;
1577 		unsp->uns_readdir_status = 1;
1578 
1579 		/*
1580 		 * UFS(and other FS) needs size of uio_resid larger than
1581 		 * DIRBLKSIZ.
1582 		 * size of DIRBLKSIZ equals DEV_BSIZE.
1583 		 * (see: ufs/ufs/ufs_vnops.c ufs_readdir func , ufs/ufs/dir.h)
1584 		 */
1585 		if (uio->uio_resid <= (uio->uio_resid & (DEV_BSIZE -1)))
1586 			goto unionfs_readdir_exit;
1587 
1588 		/*
1589 		 * Backup cookies.
1590 		 * It prepares to readdir in lower.
1591 		 */
1592 		if (ap->a_ncookies != NULL) {
1593 			ncookies_bk = *(ap->a_ncookies);
1594 			*(ap->a_ncookies) = 0;
1595 		}
1596 		if (ap->a_cookies != NULL) {
1597 			cookies_bk = *(ap->a_cookies);
1598 			*(ap->a_cookies) = NULL;
1599 		}
1600 	}
1601 
1602 	/* initialize for readdir in lower */
1603 	if (unsp->uns_readdir_status == 1) {
1604 		unsp->uns_readdir_status = 2;
1605 		/*
1606 		 * Backup uio_offset. See the comment after the
1607 		 * VOP_READDIR call on the lower layer.
1608 		 */
1609 		uio_offset_bk = uio->uio_offset;
1610 		uio->uio_offset = 0;
1611 	}
1612 
1613 	if (lvp == NULLVP) {
1614 		error = EBADF;
1615 		goto unionfs_readdir_exit;
1616 	}
1617 	/* read lower */
1618 	error = VOP_READDIR(lvp, uio, ap->a_cred, ap->a_eofflag,
1619 			    ap->a_ncookies, ap->a_cookies);
1620 
1621 	/*
1622 	 * We can't return an uio_offset of 0: this would trigger an
1623 	 * infinite loop, because the next call to unionfs_readdir would
1624 	 * always restart with the upper layer (uio_offset == 0) and
1625 	 * always return some data.
1626 	 *
1627 	 * This happens when the lower layer root directory is removed.
1628 	 * (A root directory deleting of unionfs should not be permitted.
1629 	 *  But current VFS can not do it.)
1630 	 */
1631 	if (uio->uio_offset == 0)
1632 		uio->uio_offset = uio_offset_bk;
1633 
1634 	if (cookies_bk != NULL) {
1635 		/* merge cookies */
1636 		int		size;
1637 		u_long         *newcookies, *pos;
1638 
1639 		size = *(ap->a_ncookies) + ncookies_bk;
1640 		newcookies = (u_long *) malloc(size * sizeof(u_long),
1641 		    M_TEMP, M_WAITOK);
1642 		pos = newcookies;
1643 
1644 		memcpy(pos, cookies_bk, ncookies_bk * sizeof(u_long));
1645 		pos += ncookies_bk;
1646 		memcpy(pos, *(ap->a_cookies), *(ap->a_ncookies) * sizeof(u_long));
1647 		free(cookies_bk, M_TEMP);
1648 		free(*(ap->a_cookies), M_TEMP);
1649 		*(ap->a_ncookies) = size;
1650 		*(ap->a_cookies) = newcookies;
1651 	}
1652 
1653 unionfs_readdir_exit:
1654 	if (error != 0 && ap->a_eofflag != NULL)
1655 		*(ap->a_eofflag) = 1;
1656 
1657 	UNIONFS_INTERNAL_DEBUG("unionfs_readdir: leave (%d)\n", error);
1658 
1659 	return (error);
1660 }
1661 
1662 static int
1663 unionfs_readlink(struct vop_readlink_args *ap)
1664 {
1665 	int error;
1666 	struct unionfs_node *unp;
1667 	struct vnode   *vp;
1668 
1669 	UNIONFS_INTERNAL_DEBUG("unionfs_readlink: enter\n");
1670 
1671 	KASSERT_UNIONFS_VNODE(ap->a_vp);
1672 
1673 	unp = VTOUNIONFS(ap->a_vp);
1674 	vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp);
1675 
1676 	error = VOP_READLINK(vp, ap->a_uio, ap->a_cred);
1677 
1678 	UNIONFS_INTERNAL_DEBUG("unionfs_readlink: leave (%d)\n", error);
1679 
1680 	return (error);
1681 }
1682 
1683 static int
1684 unionfs_getwritemount(struct vop_getwritemount_args *ap)
1685 {
1686 	int		error;
1687 	struct vnode   *uvp;
1688 	struct vnode   *vp;
1689 
1690 	UNIONFS_INTERNAL_DEBUG("unionfs_getwritemount: enter\n");
1691 
1692 	error = 0;
1693 	vp = ap->a_vp;
1694 
1695 	if (vp == NULLVP || (vp->v_mount->mnt_flag & MNT_RDONLY))
1696 		return (EACCES);
1697 
1698 	KASSERT_UNIONFS_VNODE(vp);
1699 
1700 	uvp = UNIONFSVPTOUPPERVP(vp);
1701 	if (uvp == NULLVP && VREG == vp->v_type)
1702 		uvp = UNIONFSVPTOUPPERVP(VTOUNIONFS(vp)->un_dvp);
1703 
1704 	if (uvp != NULLVP)
1705 		error = VOP_GETWRITEMOUNT(uvp, ap->a_mpp);
1706 	else {
1707 		VI_LOCK(vp);
1708 		if (vp->v_iflag & VI_FREE)
1709 			error = EOPNOTSUPP;
1710 		else
1711 			error = EACCES;
1712 		VI_UNLOCK(vp);
1713 	}
1714 
1715 	UNIONFS_INTERNAL_DEBUG("unionfs_getwritemount: leave (%d)\n", error);
1716 
1717 	return (error);
1718 }
1719 
1720 static int
1721 unionfs_inactive(struct vop_inactive_args *ap)
1722 {
1723 	ap->a_vp->v_object = NULL;
1724 	vrecycle(ap->a_vp);
1725 	return (0);
1726 }
1727 
1728 static int
1729 unionfs_reclaim(struct vop_reclaim_args *ap)
1730 {
1731 	/* UNIONFS_INTERNAL_DEBUG("unionfs_reclaim: enter\n"); */
1732 
1733 	unionfs_noderem(ap->a_vp, ap->a_td);
1734 
1735 	/* UNIONFS_INTERNAL_DEBUG("unionfs_reclaim: leave\n"); */
1736 
1737 	return (0);
1738 }
1739 
1740 static int
1741 unionfs_print(struct vop_print_args *ap)
1742 {
1743 	struct unionfs_node *unp;
1744 	/* struct unionfs_node_status *unsp; */
1745 
1746 	unp = VTOUNIONFS(ap->a_vp);
1747 	/* unionfs_get_node_status(unp, curthread, &unsp); */
1748 
1749 	printf("unionfs_vp=%p, uppervp=%p, lowervp=%p\n",
1750 	    ap->a_vp, unp->un_uppervp, unp->un_lowervp);
1751 	/*
1752 	printf("unionfs opencnt: uppervp=%d, lowervp=%d\n",
1753 	    unsp->uns_upper_opencnt, unsp->uns_lower_opencnt);
1754 	*/
1755 
1756 	if (unp->un_uppervp != NULLVP)
1757 		vprint("unionfs: upper", unp->un_uppervp);
1758 	if (unp->un_lowervp != NULLVP)
1759 		vprint("unionfs: lower", unp->un_lowervp);
1760 
1761 	return (0);
1762 }
1763 
1764 static int
1765 unionfs_islocked(struct vop_islocked_args *ap)
1766 {
1767 	struct unionfs_node *unp;
1768 
1769 	KASSERT_UNIONFS_VNODE(ap->a_vp);
1770 
1771 	unp = VTOUNIONFS(ap->a_vp);
1772 	if (unp == NULL)
1773 		return (vop_stdislocked(ap));
1774 
1775 	if (unp->un_uppervp != NULLVP)
1776 		return (VOP_ISLOCKED(unp->un_uppervp));
1777 	if (unp->un_lowervp != NULLVP)
1778 		return (VOP_ISLOCKED(unp->un_lowervp));
1779 	return (vop_stdislocked(ap));
1780 }
1781 
1782 static int
1783 unionfs_get_llt_revlock(struct vnode *vp, int flags)
1784 {
1785 	int revlock;
1786 
1787 	revlock = 0;
1788 
1789 	switch (flags & LK_TYPE_MASK) {
1790 	case LK_SHARED:
1791 		if (VOP_ISLOCKED(vp) == LK_EXCLUSIVE)
1792 			revlock = LK_UPGRADE;
1793 		else
1794 			revlock = LK_RELEASE;
1795 		break;
1796 	case LK_EXCLUSIVE:
1797 	case LK_UPGRADE:
1798 		revlock = LK_RELEASE;
1799 		break;
1800 	case LK_DOWNGRADE:
1801 		revlock = LK_UPGRADE;
1802 		break;
1803 	default:
1804 		break;
1805 	}
1806 
1807 	return (revlock);
1808 }
1809 
1810 /*
1811  * The state of an acquired lock is adjusted similarly to
1812  * the time of error generating.
1813  * flags: LK_RELEASE or LK_UPGRADE
1814  */
1815 static void
1816 unionfs_revlock(struct vnode *vp, int flags)
1817 {
1818 	if (flags & LK_RELEASE)
1819 		VOP_UNLOCK(vp, flags);
1820 	else {
1821 		/* UPGRADE */
1822 		if (vn_lock(vp, flags) != 0)
1823 			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1824 	}
1825 }
1826 
1827 static int
1828 unionfs_lock(struct vop_lock1_args *ap)
1829 {
1830 	int		error;
1831 	int		flags;
1832 	int		revlock;
1833 	int		interlock;
1834 	int		uhold;
1835 	struct mount   *mp;
1836 	struct unionfs_mount *ump;
1837 	struct unionfs_node *unp;
1838 	struct vnode   *vp;
1839 	struct vnode   *uvp;
1840 	struct vnode   *lvp;
1841 
1842 	KASSERT_UNIONFS_VNODE(ap->a_vp);
1843 
1844 	error = 0;
1845 	interlock = 1;
1846 	uhold = 0;
1847 	flags = ap->a_flags;
1848 	vp = ap->a_vp;
1849 
1850 	if (LK_RELEASE == (flags & LK_TYPE_MASK) || !(flags & LK_TYPE_MASK))
1851 		return (VOP_UNLOCK(vp, flags | LK_RELEASE));
1852 
1853 	if ((flags & LK_INTERLOCK) == 0)
1854 		VI_LOCK(vp);
1855 
1856 	mp = vp->v_mount;
1857 	if (mp == NULL)
1858 		goto unionfs_lock_null_vnode;
1859 
1860 	ump = MOUNTTOUNIONFSMOUNT(mp);
1861 	unp = VTOUNIONFS(vp);
1862 	if (ump == NULL || unp == NULL)
1863 		goto unionfs_lock_null_vnode;
1864 	lvp = unp->un_lowervp;
1865 	uvp = unp->un_uppervp;
1866 
1867 	if ((revlock = unionfs_get_llt_revlock(vp, flags)) == 0)
1868 		panic("unknown lock type: 0x%x", flags & LK_TYPE_MASK);
1869 
1870 	if ((vp->v_iflag & VI_OWEINACT) != 0)
1871 		flags |= LK_NOWAIT;
1872 
1873 	/*
1874 	 * Sometimes, lower or upper is already exclusive locked.
1875 	 * (ex. vfs_domount: mounted vnode is already locked.)
1876 	 */
1877 	if ((flags & LK_TYPE_MASK) == LK_EXCLUSIVE &&
1878 	    vp == ump->um_rootvp)
1879 		flags |= LK_CANRECURSE;
1880 
1881 	if (lvp != NULLVP) {
1882 		if (uvp != NULLVP && flags & LK_UPGRADE) {
1883 			/* Share Lock is once released and a deadlock is avoided.  */
1884 			VI_LOCK_FLAGS(uvp, MTX_DUPOK);
1885 			vholdl(uvp);
1886 			uhold = 1;
1887 			VI_UNLOCK(vp);
1888 			VOP_UNLOCK(uvp, LK_RELEASE | LK_INTERLOCK);
1889 			VI_LOCK(vp);
1890 			unp = VTOUNIONFS(vp);
1891 			if (unp == NULL) {
1892 				/* vnode is released. */
1893 				VI_UNLOCK(vp);
1894 				VOP_UNLOCK(lvp, LK_RELEASE);
1895 				vdrop(uvp);
1896 				return (EBUSY);
1897 			}
1898 		}
1899 		VI_LOCK_FLAGS(lvp, MTX_DUPOK);
1900 		flags |= LK_INTERLOCK;
1901 		vholdl(lvp);
1902 
1903 		VI_UNLOCK(vp);
1904 		ap->a_flags &= ~LK_INTERLOCK;
1905 
1906 		error = VOP_LOCK(lvp, flags);
1907 
1908 		VI_LOCK(vp);
1909 		unp = VTOUNIONFS(vp);
1910 		if (unp == NULL) {
1911 			/* vnode is released. */
1912 			VI_UNLOCK(vp);
1913 			if (error == 0)
1914 				VOP_UNLOCK(lvp, LK_RELEASE);
1915 			vdrop(lvp);
1916 			if (uhold != 0)
1917 				vdrop(uvp);
1918 			return (vop_stdlock(ap));
1919 		}
1920 	}
1921 
1922 	if (error == 0 && uvp != NULLVP) {
1923 		if (uhold && flags & LK_UPGRADE) {
1924 			flags &= ~LK_TYPE_MASK;
1925 			flags |= LK_EXCLUSIVE;
1926 		}
1927 		VI_LOCK_FLAGS(uvp, MTX_DUPOK);
1928 		flags |= LK_INTERLOCK;
1929 		if (uhold == 0) {
1930 			vholdl(uvp);
1931 			uhold = 1;
1932 		}
1933 
1934 		VI_UNLOCK(vp);
1935 		ap->a_flags &= ~LK_INTERLOCK;
1936 
1937 		error = VOP_LOCK(uvp, flags);
1938 
1939 		VI_LOCK(vp);
1940 		unp = VTOUNIONFS(vp);
1941 		if (unp == NULL) {
1942 			/* vnode is released. */
1943 			VI_UNLOCK(vp);
1944 			if (error == 0)
1945 				VOP_UNLOCK(uvp, LK_RELEASE);
1946 			vdrop(uvp);
1947 			if (lvp != NULLVP) {
1948 				VOP_UNLOCK(lvp, LK_RELEASE);
1949 				vdrop(lvp);
1950 			}
1951 			return (vop_stdlock(ap));
1952 		}
1953 		if (error != 0 && lvp != NULLVP) {
1954 			/* rollback */
1955 			VI_UNLOCK(vp);
1956 			unionfs_revlock(lvp, revlock);
1957 			interlock = 0;
1958 		}
1959 	}
1960 
1961 	if (interlock)
1962 		VI_UNLOCK(vp);
1963 	if (lvp != NULLVP)
1964 		vdrop(lvp);
1965 	if (uhold != 0)
1966 		vdrop(uvp);
1967 
1968 	return (error);
1969 
1970 unionfs_lock_null_vnode:
1971 	ap->a_flags |= LK_INTERLOCK;
1972 	return (vop_stdlock(ap));
1973 }
1974 
1975 static int
1976 unionfs_unlock(struct vop_unlock_args *ap)
1977 {
1978 	int		error;
1979 	int		flags;
1980 	int		mtxlkflag;
1981 	int		uhold;
1982 	struct vnode   *vp;
1983 	struct vnode   *lvp;
1984 	struct vnode   *uvp;
1985 	struct unionfs_node *unp;
1986 
1987 	KASSERT_UNIONFS_VNODE(ap->a_vp);
1988 
1989 	error = 0;
1990 	mtxlkflag = 0;
1991 	uhold = 0;
1992 	flags = ap->a_flags | LK_RELEASE;
1993 	vp = ap->a_vp;
1994 
1995 	if ((flags & LK_INTERLOCK) != 0)
1996 		mtxlkflag = 1;
1997 	else if (mtx_owned(VI_MTX(vp)) == 0) {
1998 		VI_LOCK(vp);
1999 		mtxlkflag = 2;
2000 	}
2001 
2002 	unp = VTOUNIONFS(vp);
2003 	if (unp == NULL)
2004 		goto unionfs_unlock_null_vnode;
2005 	lvp = unp->un_lowervp;
2006 	uvp = unp->un_uppervp;
2007 
2008 	if (lvp != NULLVP) {
2009 		VI_LOCK_FLAGS(lvp, MTX_DUPOK);
2010 		flags |= LK_INTERLOCK;
2011 		vholdl(lvp);
2012 
2013 		VI_UNLOCK(vp);
2014 		ap->a_flags &= ~LK_INTERLOCK;
2015 
2016 		error = VOP_UNLOCK(lvp, flags);
2017 
2018 		VI_LOCK(vp);
2019 	}
2020 
2021 	if (error == 0 && uvp != NULLVP) {
2022 		VI_LOCK_FLAGS(uvp, MTX_DUPOK);
2023 		flags |= LK_INTERLOCK;
2024 		vholdl(uvp);
2025 		uhold = 1;
2026 
2027 		VI_UNLOCK(vp);
2028 		ap->a_flags &= ~LK_INTERLOCK;
2029 
2030 		error = VOP_UNLOCK(uvp, flags);
2031 
2032 		VI_LOCK(vp);
2033 	}
2034 
2035 	VI_UNLOCK(vp);
2036 	if (lvp != NULLVP)
2037 		vdrop(lvp);
2038 	if (uhold != 0)
2039 		vdrop(uvp);
2040 	if (mtxlkflag == 0)
2041 		VI_LOCK(vp);
2042 
2043 	return error;
2044 
2045 unionfs_unlock_null_vnode:
2046 	if (mtxlkflag == 2)
2047 		VI_UNLOCK(vp);
2048 	return (vop_stdunlock(ap));
2049 }
2050 
2051 static int
2052 unionfs_pathconf(struct vop_pathconf_args *ap)
2053 {
2054 	struct unionfs_node *unp;
2055 	struct vnode   *vp;
2056 
2057 	KASSERT_UNIONFS_VNODE(ap->a_vp);
2058 
2059 	unp = VTOUNIONFS(ap->a_vp);
2060 	vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp);
2061 
2062 	return (VOP_PATHCONF(vp, ap->a_name, ap->a_retval));
2063 }
2064 
2065 static int
2066 unionfs_advlock(struct vop_advlock_args *ap)
2067 {
2068 	int error;
2069 	struct unionfs_node *unp;
2070 	struct unionfs_node_status *unsp;
2071 	struct vnode   *vp;
2072 	struct vnode   *uvp;
2073 	struct thread  *td;
2074 
2075 	UNIONFS_INTERNAL_DEBUG("unionfs_advlock: enter\n");
2076 
2077 	KASSERT_UNIONFS_VNODE(ap->a_vp);
2078 
2079 	vp = ap->a_vp;
2080 	td = curthread;
2081 
2082 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2083 
2084 	unp = VTOUNIONFS(ap->a_vp);
2085 	uvp = unp->un_uppervp;
2086 
2087 	if (uvp == NULLVP) {
2088 		error = unionfs_copyfile(unp, 1, td->td_ucred, td);
2089 		if (error != 0)
2090 			goto unionfs_advlock_abort;
2091 		uvp = unp->un_uppervp;
2092 
2093 		unionfs_get_node_status(unp, td, &unsp);
2094 		if (unsp->uns_lower_opencnt > 0) {
2095 			/* try reopen the vnode */
2096 			error = VOP_OPEN(uvp, unsp->uns_lower_openmode,
2097 				td->td_ucred, td, NULL);
2098 			if (error)
2099 				goto unionfs_advlock_abort;
2100 			unsp->uns_upper_opencnt++;
2101 			VOP_CLOSE(unp->un_lowervp, unsp->uns_lower_openmode, td->td_ucred, td);
2102 			unsp->uns_lower_opencnt--;
2103 		} else
2104 			unionfs_tryrem_node_status(unp, unsp);
2105 	}
2106 
2107 	VOP_UNLOCK(vp, LK_RELEASE);
2108 
2109 	error = VOP_ADVLOCK(uvp, ap->a_id, ap->a_op, ap->a_fl, ap->a_flags);
2110 
2111 	UNIONFS_INTERNAL_DEBUG("unionfs_advlock: leave (%d)\n", error);
2112 
2113 	return error;
2114 
2115 unionfs_advlock_abort:
2116 	VOP_UNLOCK(vp, LK_RELEASE);
2117 
2118 	UNIONFS_INTERNAL_DEBUG("unionfs_advlock: leave (%d)\n", error);
2119 
2120 	return error;
2121 }
2122 
2123 static int
2124 unionfs_strategy(struct vop_strategy_args *ap)
2125 {
2126 	struct unionfs_node *unp;
2127 	struct vnode   *vp;
2128 
2129 	KASSERT_UNIONFS_VNODE(ap->a_vp);
2130 
2131 	unp = VTOUNIONFS(ap->a_vp);
2132 	vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp);
2133 
2134 #ifdef DIAGNOSTIC
2135 	if (vp == NULLVP)
2136 		panic("unionfs_strategy: nullvp");
2137 
2138 	if (ap->a_bp->b_iocmd == BIO_WRITE && vp == unp->un_lowervp)
2139 		panic("unionfs_strategy: writing to lowervp");
2140 #endif
2141 
2142 	return (VOP_STRATEGY(vp, ap->a_bp));
2143 }
2144 
2145 static int
2146 unionfs_getacl(struct vop_getacl_args *ap)
2147 {
2148 	int		error;
2149 	struct unionfs_node *unp;
2150 	struct vnode   *vp;
2151 
2152 	KASSERT_UNIONFS_VNODE(ap->a_vp);
2153 
2154 	unp = VTOUNIONFS(ap->a_vp);
2155 	vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp);
2156 
2157 	UNIONFS_INTERNAL_DEBUG("unionfs_getacl: enter\n");
2158 
2159 	error = VOP_GETACL(vp, ap->a_type, ap->a_aclp, ap->a_cred, ap->a_td);
2160 
2161 	UNIONFS_INTERNAL_DEBUG("unionfs_getacl: leave (%d)\n", error);
2162 
2163 	return (error);
2164 }
2165 
2166 static int
2167 unionfs_setacl(struct vop_setacl_args *ap)
2168 {
2169 	int		error;
2170 	struct unionfs_node *unp;
2171 	struct vnode   *uvp;
2172 	struct vnode   *lvp;
2173 	struct thread  *td;
2174 
2175 	UNIONFS_INTERNAL_DEBUG("unionfs_setacl: enter\n");
2176 
2177 	KASSERT_UNIONFS_VNODE(ap->a_vp);
2178 
2179 	error = EROFS;
2180 	unp = VTOUNIONFS(ap->a_vp);
2181 	uvp = unp->un_uppervp;
2182 	lvp = unp->un_lowervp;
2183 	td = ap->a_td;
2184 
2185 	if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
2186 		return (EROFS);
2187 
2188 	if (uvp == NULLVP && lvp->v_type == VREG) {
2189 		if ((error = unionfs_copyfile(unp, 1, ap->a_cred, td)) != 0)
2190 			return (error);
2191 		uvp = unp->un_uppervp;
2192 	}
2193 
2194 	if (uvp != NULLVP)
2195 		error = VOP_SETACL(uvp, ap->a_type, ap->a_aclp, ap->a_cred, td);
2196 
2197 	UNIONFS_INTERNAL_DEBUG("unionfs_setacl: leave (%d)\n", error);
2198 
2199 	return (error);
2200 }
2201 
2202 static int
2203 unionfs_aclcheck(struct vop_aclcheck_args *ap)
2204 {
2205 	int		error;
2206 	struct unionfs_node *unp;
2207 	struct vnode   *vp;
2208 
2209 	UNIONFS_INTERNAL_DEBUG("unionfs_aclcheck: enter\n");
2210 
2211 	KASSERT_UNIONFS_VNODE(ap->a_vp);
2212 
2213 	unp = VTOUNIONFS(ap->a_vp);
2214 	vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp);
2215 
2216 	error = VOP_ACLCHECK(vp, ap->a_type, ap->a_aclp, ap->a_cred, ap->a_td);
2217 
2218 	UNIONFS_INTERNAL_DEBUG("unionfs_aclcheck: leave (%d)\n", error);
2219 
2220 	return (error);
2221 }
2222 
2223 static int
2224 unionfs_openextattr(struct vop_openextattr_args *ap)
2225 {
2226 	int		error;
2227 	struct unionfs_node *unp;
2228 	struct vnode   *vp;
2229 	struct vnode   *tvp;
2230 
2231 	KASSERT_UNIONFS_VNODE(ap->a_vp);
2232 
2233 	vp = ap->a_vp;
2234 	unp = VTOUNIONFS(vp);
2235 	tvp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp);
2236 
2237 	if ((tvp == unp->un_uppervp && (unp->un_flag & UNIONFS_OPENEXTU)) ||
2238 	    (tvp == unp->un_lowervp && (unp->un_flag & UNIONFS_OPENEXTL)))
2239 		return (EBUSY);
2240 
2241 	error = VOP_OPENEXTATTR(tvp, ap->a_cred, ap->a_td);
2242 
2243 	if (error == 0) {
2244 		if (vn_lock(vp, LK_UPGRADE) != 0)
2245 			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2246 		if (tvp == unp->un_uppervp)
2247 			unp->un_flag |= UNIONFS_OPENEXTU;
2248 		else
2249 			unp->un_flag |= UNIONFS_OPENEXTL;
2250 		vn_lock(vp, LK_DOWNGRADE | LK_RETRY);
2251 	}
2252 
2253 	return (error);
2254 }
2255 
2256 static int
2257 unionfs_closeextattr(struct vop_closeextattr_args *ap)
2258 {
2259 	int		error;
2260 	struct unionfs_node *unp;
2261 	struct vnode   *vp;
2262 	struct vnode   *tvp;
2263 
2264 	KASSERT_UNIONFS_VNODE(ap->a_vp);
2265 
2266 	vp = ap->a_vp;
2267 	unp = VTOUNIONFS(vp);
2268 	tvp = NULLVP;
2269 
2270 	if (unp->un_flag & UNIONFS_OPENEXTU)
2271 		tvp = unp->un_uppervp;
2272 	else if (unp->un_flag & UNIONFS_OPENEXTL)
2273 		tvp = unp->un_lowervp;
2274 
2275 	if (tvp == NULLVP)
2276 		return (EOPNOTSUPP);
2277 
2278 	error = VOP_CLOSEEXTATTR(tvp, ap->a_commit, ap->a_cred, ap->a_td);
2279 
2280 	if (error == 0) {
2281 		if (vn_lock(vp, LK_UPGRADE) != 0)
2282 			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2283 		if (tvp == unp->un_uppervp)
2284 			unp->un_flag &= ~UNIONFS_OPENEXTU;
2285 		else
2286 			unp->un_flag &= ~UNIONFS_OPENEXTL;
2287 		vn_lock(vp, LK_DOWNGRADE | LK_RETRY);
2288 	}
2289 
2290 	return (error);
2291 }
2292 
2293 static int
2294 unionfs_getextattr(struct vop_getextattr_args *ap)
2295 {
2296 	struct unionfs_node *unp;
2297 	struct vnode   *vp;
2298 
2299 	KASSERT_UNIONFS_VNODE(ap->a_vp);
2300 
2301 	unp = VTOUNIONFS(ap->a_vp);
2302 	vp = NULLVP;
2303 
2304 	if (unp->un_flag & UNIONFS_OPENEXTU)
2305 		vp = unp->un_uppervp;
2306 	else if (unp->un_flag & UNIONFS_OPENEXTL)
2307 		vp = unp->un_lowervp;
2308 
2309 	if (vp == NULLVP)
2310 		return (EOPNOTSUPP);
2311 
2312 	return (VOP_GETEXTATTR(vp, ap->a_attrnamespace, ap->a_name,
2313 	    ap->a_uio, ap->a_size, ap->a_cred, ap->a_td));
2314 }
2315 
2316 static int
2317 unionfs_setextattr(struct vop_setextattr_args *ap)
2318 {
2319 	int		error;
2320 	struct unionfs_node *unp;
2321 	struct vnode   *uvp;
2322 	struct vnode   *lvp;
2323 	struct vnode   *ovp;
2324 	struct ucred   *cred;
2325 	struct thread  *td;
2326 
2327 	KASSERT_UNIONFS_VNODE(ap->a_vp);
2328 
2329 	error = EROFS;
2330 	unp = VTOUNIONFS(ap->a_vp);
2331 	uvp = unp->un_uppervp;
2332 	lvp = unp->un_lowervp;
2333 	ovp = NULLVP;
2334 	cred = ap->a_cred;
2335 	td = ap->a_td;
2336 
2337 	UNIONFS_INTERNAL_DEBUG("unionfs_setextattr: enter (un_flag=%x)\n", unp->un_flag);
2338 
2339 	if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
2340 		return (EROFS);
2341 
2342 	if (unp->un_flag & UNIONFS_OPENEXTU)
2343 		ovp = unp->un_uppervp;
2344 	else if (unp->un_flag & UNIONFS_OPENEXTL)
2345 		ovp = unp->un_lowervp;
2346 
2347 	if (ovp == NULLVP)
2348 		return (EOPNOTSUPP);
2349 
2350 	if (ovp == lvp && lvp->v_type == VREG) {
2351 		VOP_CLOSEEXTATTR(lvp, 0, cred, td);
2352 		if (uvp == NULLVP &&
2353 		    (error = unionfs_copyfile(unp, 1, cred, td)) != 0) {
2354 unionfs_setextattr_reopen:
2355 			if ((unp->un_flag & UNIONFS_OPENEXTL) &&
2356 			    VOP_OPENEXTATTR(lvp, cred, td)) {
2357 #ifdef DIAGNOSTIC
2358 				panic("unionfs: VOP_OPENEXTATTR failed");
2359 #endif
2360 				unp->un_flag &= ~UNIONFS_OPENEXTL;
2361 			}
2362 			goto unionfs_setextattr_abort;
2363 		}
2364 		uvp = unp->un_uppervp;
2365 		if ((error = VOP_OPENEXTATTR(uvp, cred, td)) != 0)
2366 			goto unionfs_setextattr_reopen;
2367 		unp->un_flag &= ~UNIONFS_OPENEXTL;
2368 		unp->un_flag |= UNIONFS_OPENEXTU;
2369 		ovp = uvp;
2370 	}
2371 
2372 	if (ovp == uvp)
2373 		error = VOP_SETEXTATTR(ovp, ap->a_attrnamespace, ap->a_name,
2374 		    ap->a_uio, cred, td);
2375 
2376 unionfs_setextattr_abort:
2377 	UNIONFS_INTERNAL_DEBUG("unionfs_setextattr: leave (%d)\n", error);
2378 
2379 	return (error);
2380 }
2381 
2382 static int
2383 unionfs_listextattr(struct vop_listextattr_args *ap)
2384 {
2385 	struct unionfs_node *unp;
2386 	struct vnode   *vp;
2387 
2388 	KASSERT_UNIONFS_VNODE(ap->a_vp);
2389 
2390 	unp = VTOUNIONFS(ap->a_vp);
2391 	vp = NULLVP;
2392 
2393 	if (unp->un_flag & UNIONFS_OPENEXTU)
2394 		vp = unp->un_uppervp;
2395 	else if (unp->un_flag & UNIONFS_OPENEXTL)
2396 		vp = unp->un_lowervp;
2397 
2398 	if (vp == NULLVP)
2399 		return (EOPNOTSUPP);
2400 
2401 	return (VOP_LISTEXTATTR(vp, ap->a_attrnamespace, ap->a_uio,
2402 	    ap->a_size, ap->a_cred, ap->a_td));
2403 }
2404 
2405 static int
2406 unionfs_deleteextattr(struct vop_deleteextattr_args *ap)
2407 {
2408 	int		error;
2409 	struct unionfs_node *unp;
2410 	struct vnode   *uvp;
2411 	struct vnode   *lvp;
2412 	struct vnode   *ovp;
2413 	struct ucred   *cred;
2414 	struct thread  *td;
2415 
2416 	KASSERT_UNIONFS_VNODE(ap->a_vp);
2417 
2418 	error = EROFS;
2419 	unp = VTOUNIONFS(ap->a_vp);
2420 	uvp = unp->un_uppervp;
2421 	lvp = unp->un_lowervp;
2422 	ovp = NULLVP;
2423 	cred = ap->a_cred;
2424 	td = ap->a_td;
2425 
2426 	UNIONFS_INTERNAL_DEBUG("unionfs_deleteextattr: enter (un_flag=%x)\n", unp->un_flag);
2427 
2428 	if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
2429 		return (EROFS);
2430 
2431 	if (unp->un_flag & UNIONFS_OPENEXTU)
2432 		ovp = unp->un_uppervp;
2433 	else if (unp->un_flag & UNIONFS_OPENEXTL)
2434 		ovp = unp->un_lowervp;
2435 
2436 	if (ovp == NULLVP)
2437 		return (EOPNOTSUPP);
2438 
2439 	if (ovp == lvp && lvp->v_type == VREG) {
2440 		VOP_CLOSEEXTATTR(lvp, 0, cred, td);
2441 		if (uvp == NULLVP &&
2442 		    (error = unionfs_copyfile(unp, 1, cred, td)) != 0) {
2443 unionfs_deleteextattr_reopen:
2444 			if ((unp->un_flag & UNIONFS_OPENEXTL) &&
2445 			    VOP_OPENEXTATTR(lvp, cred, td)) {
2446 #ifdef DIAGNOSTIC
2447 				panic("unionfs: VOP_OPENEXTATTR failed");
2448 #endif
2449 				unp->un_flag &= ~UNIONFS_OPENEXTL;
2450 			}
2451 			goto unionfs_deleteextattr_abort;
2452 		}
2453 		uvp = unp->un_uppervp;
2454 		if ((error = VOP_OPENEXTATTR(uvp, cred, td)) != 0)
2455 			goto unionfs_deleteextattr_reopen;
2456 		unp->un_flag &= ~UNIONFS_OPENEXTL;
2457 		unp->un_flag |= UNIONFS_OPENEXTU;
2458 		ovp = uvp;
2459 	}
2460 
2461 	if (ovp == uvp)
2462 		error = VOP_DELETEEXTATTR(ovp, ap->a_attrnamespace, ap->a_name,
2463 		    ap->a_cred, ap->a_td);
2464 
2465 unionfs_deleteextattr_abort:
2466 	UNIONFS_INTERNAL_DEBUG("unionfs_deleteextattr: leave (%d)\n", error);
2467 
2468 	return (error);
2469 }
2470 
2471 static int
2472 unionfs_setlabel(struct vop_setlabel_args *ap)
2473 {
2474 	int		error;
2475 	struct unionfs_node *unp;
2476 	struct vnode   *uvp;
2477 	struct vnode   *lvp;
2478 	struct thread  *td;
2479 
2480 	UNIONFS_INTERNAL_DEBUG("unionfs_setlabel: enter\n");
2481 
2482 	KASSERT_UNIONFS_VNODE(ap->a_vp);
2483 
2484 	error = EROFS;
2485 	unp = VTOUNIONFS(ap->a_vp);
2486 	uvp = unp->un_uppervp;
2487 	lvp = unp->un_lowervp;
2488 	td = ap->a_td;
2489 
2490 	if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
2491 		return (EROFS);
2492 
2493 	if (uvp == NULLVP && lvp->v_type == VREG) {
2494 		if ((error = unionfs_copyfile(unp, 1, ap->a_cred, td)) != 0)
2495 			return (error);
2496 		uvp = unp->un_uppervp;
2497 	}
2498 
2499 	if (uvp != NULLVP)
2500 		error = VOP_SETLABEL(uvp, ap->a_label, ap->a_cred, td);
2501 
2502 	UNIONFS_INTERNAL_DEBUG("unionfs_setlabel: leave (%d)\n", error);
2503 
2504 	return (error);
2505 }
2506 
2507 static int
2508 unionfs_vptofh(struct vop_vptofh_args *ap)
2509 {
2510 	return (EOPNOTSUPP);
2511 }
2512 
2513 struct vop_vector unionfs_vnodeops = {
2514 	.vop_default =		&default_vnodeops,
2515 
2516 	.vop_access =		unionfs_access,
2517 	.vop_aclcheck =		unionfs_aclcheck,
2518 	.vop_advlock =		unionfs_advlock,
2519 	.vop_bmap =		VOP_EOPNOTSUPP,
2520 	.vop_cachedlookup =	unionfs_lookup,
2521 	.vop_close =		unionfs_close,
2522 	.vop_closeextattr =	unionfs_closeextattr,
2523 	.vop_create =		unionfs_create,
2524 	.vop_deleteextattr =	unionfs_deleteextattr,
2525 	.vop_fsync =		unionfs_fsync,
2526 	.vop_getacl =		unionfs_getacl,
2527 	.vop_getattr =		unionfs_getattr,
2528 	.vop_getextattr =	unionfs_getextattr,
2529 	.vop_getwritemount =	unionfs_getwritemount,
2530 	.vop_inactive =		unionfs_inactive,
2531 	.vop_islocked =		unionfs_islocked,
2532 	.vop_ioctl =		unionfs_ioctl,
2533 	.vop_link =		unionfs_link,
2534 	.vop_listextattr =	unionfs_listextattr,
2535 	.vop_lock1 =		unionfs_lock,
2536 	.vop_lookup =		vfs_cache_lookup,
2537 	.vop_mkdir =		unionfs_mkdir,
2538 	.vop_mknod =		unionfs_mknod,
2539 	.vop_open =		unionfs_open,
2540 	.vop_openextattr =	unionfs_openextattr,
2541 	.vop_pathconf =		unionfs_pathconf,
2542 	.vop_poll =		unionfs_poll,
2543 	.vop_print =		unionfs_print,
2544 	.vop_read =		unionfs_read,
2545 	.vop_readdir =		unionfs_readdir,
2546 	.vop_readlink =		unionfs_readlink,
2547 	.vop_reclaim =		unionfs_reclaim,
2548 	.vop_remove =		unionfs_remove,
2549 	.vop_rename =		unionfs_rename,
2550 	.vop_rmdir =		unionfs_rmdir,
2551 	.vop_setacl =		unionfs_setacl,
2552 	.vop_setattr =		unionfs_setattr,
2553 	.vop_setextattr =	unionfs_setextattr,
2554 	.vop_setlabel =		unionfs_setlabel,
2555 	.vop_strategy =		unionfs_strategy,
2556 	.vop_symlink =		unionfs_symlink,
2557 	.vop_unlock =		unionfs_unlock,
2558 	.vop_whiteout =		unionfs_whiteout,
2559 	.vop_write =		unionfs_write,
2560 	.vop_vptofh =		unionfs_vptofh,
2561 };
2562