xref: /freebsd/sys/fs/unionfs/union_subr.c (revision 19261079)
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 1994 Jan-Simon Pendry
5  * Copyright (c) 1994
6  *	The Regents of the University of California.  All rights reserved.
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  *
10  * This code is derived from software contributed to Berkeley by
11  * Jan-Simon Pendry.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  * 3. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  *	@(#)union_subr.c	8.20 (Berkeley) 5/20/95
38  * $FreeBSD$
39  */
40 
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
44 #include <sys/ktr.h>
45 #include <sys/lock.h>
46 #include <sys/mutex.h>
47 #include <sys/malloc.h>
48 #include <sys/mount.h>
49 #include <sys/namei.h>
50 #include <sys/proc.h>
51 #include <sys/vnode.h>
52 #include <sys/dirent.h>
53 #include <sys/fcntl.h>
54 #include <sys/filedesc.h>
55 #include <sys/stat.h>
56 #include <sys/sysctl.h>
57 #include <sys/taskqueue.h>
58 #include <sys/resourcevar.h>
59 
60 #include <security/mac/mac_framework.h>
61 
62 #include <vm/uma.h>
63 
64 #include <fs/unionfs/union.h>
65 
66 #define NUNIONFSNODECACHE 16
67 
68 static MALLOC_DEFINE(M_UNIONFSHASH, "UNIONFS hash", "UNIONFS hash table");
69 MALLOC_DEFINE(M_UNIONFSNODE, "UNIONFS node", "UNIONFS vnode private part");
70 MALLOC_DEFINE(M_UNIONFSPATH, "UNIONFS path", "UNIONFS path private part");
71 
72 static struct task unionfs_deferred_rele_task;
73 static struct mtx unionfs_deferred_rele_lock;
74 static STAILQ_HEAD(, unionfs_node) unionfs_deferred_rele_list =
75     STAILQ_HEAD_INITIALIZER(unionfs_deferred_rele_list);
76 static TASKQUEUE_DEFINE_THREAD(unionfs_rele);
77 
78 unsigned int unionfs_ndeferred = 0;
79 SYSCTL_UINT(_vfs, OID_AUTO, unionfs_ndeferred, CTLFLAG_RD,
80     &unionfs_ndeferred, 0, "unionfs deferred vnode release");
81 
82 static void unionfs_deferred_rele(void *, int);
83 
84 /*
85  * Initialize
86  */
87 int
88 unionfs_init(struct vfsconf *vfsp)
89 {
90 	UNIONFSDEBUG("unionfs_init\n");	/* printed during system boot */
91 	TASK_INIT(&unionfs_deferred_rele_task, 0, unionfs_deferred_rele, NULL);
92 	mtx_init(&unionfs_deferred_rele_lock, "uniondefr", NULL, MTX_DEF);
93 	return (0);
94 }
95 
96 /*
97  * Uninitialize
98  */
99 int
100 unionfs_uninit(struct vfsconf *vfsp)
101 {
102 	taskqueue_quiesce(taskqueue_unionfs_rele);
103 	taskqueue_free(taskqueue_unionfs_rele);
104 	mtx_destroy(&unionfs_deferred_rele_lock);
105 	return (0);
106 }
107 
108 static void
109 unionfs_deferred_rele(void *arg __unused, int pending __unused)
110 {
111 	STAILQ_HEAD(, unionfs_node) local_rele_list;
112 	struct unionfs_node *unp, *tunp;
113 	unsigned int ndeferred;
114 
115 	ndeferred = 0;
116 	STAILQ_INIT(&local_rele_list);
117 	mtx_lock(&unionfs_deferred_rele_lock);
118 	STAILQ_CONCAT(&local_rele_list, &unionfs_deferred_rele_list);
119 	mtx_unlock(&unionfs_deferred_rele_lock);
120 	STAILQ_FOREACH_SAFE(unp, &local_rele_list, un_rele, tunp) {
121 		++ndeferred;
122 		MPASS(unp->un_dvp != NULL);
123 		vrele(unp->un_dvp);
124 		free(unp, M_UNIONFSNODE);
125 	}
126 
127 	/* We expect this function to be single-threaded, thus no atomic */
128 	unionfs_ndeferred += ndeferred;
129 }
130 
131 static struct unionfs_node_hashhead *
132 unionfs_get_hashhead(struct vnode *dvp, char *path)
133 {
134 	struct unionfs_node *unp;
135 	int		count;
136 	char		hash;
137 
138 	hash = 0;
139 	unp = VTOUNIONFS(dvp);
140 	if (path != NULL) {
141 		for (count = 0; path[count]; count++)
142 			hash += path[count];
143 	}
144 
145 	return (&(unp->un_hashtbl[hash & (unp->un_hashmask)]));
146 }
147 
148 /*
149  * Get the cached vnode.
150  */
151 static struct vnode *
152 unionfs_get_cached_vnode(struct vnode *uvp, struct vnode *lvp,
153     struct vnode *dvp, char *path)
154 {
155 	struct unionfs_node_hashhead *hd;
156 	struct unionfs_node *unp;
157 	struct vnode *vp;
158 
159 	KASSERT((uvp == NULLVP || uvp->v_type == VDIR),
160 	    ("unionfs_get_cached_vnode: v_type != VDIR"));
161 	KASSERT((lvp == NULLVP || lvp->v_type == VDIR),
162 	    ("unionfs_get_cached_vnode: v_type != VDIR"));
163 
164 	VI_LOCK(dvp);
165 	hd = unionfs_get_hashhead(dvp, path);
166 	LIST_FOREACH(unp, hd, un_hash) {
167 		if (!strcmp(unp->un_path, path)) {
168 			vp = UNIONFSTOV(unp);
169 			VI_LOCK_FLAGS(vp, MTX_DUPOK);
170 			VI_UNLOCK(dvp);
171 			vp->v_iflag &= ~VI_OWEINACT;
172 			if (VN_IS_DOOMED(vp) ||
173 			    ((vp->v_iflag & VI_DOINGINACT) != 0)) {
174 				VI_UNLOCK(vp);
175 				vp = NULLVP;
176 			} else
177 				VI_UNLOCK(vp);
178 			return (vp);
179 		}
180 	}
181 	VI_UNLOCK(dvp);
182 
183 	return (NULLVP);
184 }
185 
186 /*
187  * Add the new vnode into cache.
188  */
189 static struct vnode *
190 unionfs_ins_cached_vnode(struct unionfs_node *uncp,
191     struct vnode *dvp, char *path)
192 {
193 	struct unionfs_node_hashhead *hd;
194 	struct unionfs_node *unp;
195 	struct vnode *vp;
196 
197 	KASSERT((uncp->un_uppervp==NULLVP || uncp->un_uppervp->v_type==VDIR),
198 	    ("unionfs_ins_cached_vnode: v_type != VDIR"));
199 	KASSERT((uncp->un_lowervp==NULLVP || uncp->un_lowervp->v_type==VDIR),
200 	    ("unionfs_ins_cached_vnode: v_type != VDIR"));
201 
202 	VI_LOCK(dvp);
203 	hd = unionfs_get_hashhead(dvp, path);
204 	LIST_FOREACH(unp, hd, un_hash) {
205 		if (!strcmp(unp->un_path, path)) {
206 			vp = UNIONFSTOV(unp);
207 			VI_LOCK_FLAGS(vp, MTX_DUPOK);
208 			vp->v_iflag &= ~VI_OWEINACT;
209 			if (VN_IS_DOOMED(vp) ||
210 			    ((vp->v_iflag & VI_DOINGINACT) != 0)) {
211 				LIST_INSERT_HEAD(hd, uncp, un_hash);
212 				VI_UNLOCK(vp);
213 				vp = NULLVP;
214 			} else
215 				VI_UNLOCK(vp);
216 			VI_UNLOCK(dvp);
217 			return (vp);
218 		}
219 	}
220 
221 	LIST_INSERT_HEAD(hd, uncp, un_hash);
222 	VI_UNLOCK(dvp);
223 
224 	return (NULLVP);
225 }
226 
227 /*
228  * Remove the vnode.
229  */
230 static void
231 unionfs_rem_cached_vnode(struct unionfs_node *unp, struct vnode *dvp)
232 {
233 	KASSERT((unp != NULL), ("unionfs_rem_cached_vnode: null node"));
234 	KASSERT((dvp != NULLVP),
235 	    ("unionfs_rem_cached_vnode: null parent vnode"));
236 	KASSERT((unp->un_hash.le_prev != NULL),
237 	    ("unionfs_rem_cached_vnode: null hash"));
238 
239 	VI_LOCK(dvp);
240 	LIST_REMOVE(unp, un_hash);
241 	unp->un_hash.le_next = NULL;
242 	unp->un_hash.le_prev = NULL;
243 	VI_UNLOCK(dvp);
244 }
245 
246 /*
247  * Make a new or get existing unionfs node.
248  *
249  * uppervp and lowervp should be unlocked. Because if new unionfs vnode is
250  * locked, uppervp or lowervp is locked too. In order to prevent dead lock,
251  * you should not lock plurality simultaneously.
252  */
253 int
254 unionfs_nodeget(struct mount *mp, struct vnode *uppervp,
255     struct vnode *lowervp, struct vnode *dvp, struct vnode **vpp,
256     struct componentname *cnp, struct thread *td)
257 {
258 	char	       *path;
259 	struct unionfs_mount *ump;
260 	struct unionfs_node *unp;
261 	struct vnode   *vp;
262 	int		error;
263 	int		lkflags;
264 	enum vtype	vt;
265 
266 	ump = MOUNTTOUNIONFSMOUNT(mp);
267 	lkflags = (cnp ? cnp->cn_lkflags : 0);
268 	path = (cnp ? cnp->cn_nameptr : NULL);
269 	*vpp = NULLVP;
270 
271 	if (uppervp == NULLVP && lowervp == NULLVP)
272 		panic("unionfs_nodeget: upper and lower is null");
273 
274 	vt = (uppervp != NULLVP ? uppervp->v_type : lowervp->v_type);
275 
276 	/* If it has no ISLASTCN flag, path check is skipped. */
277 	if (cnp && !(cnp->cn_flags & ISLASTCN))
278 		path = NULL;
279 
280 	/* check the cache */
281 	if (path != NULL && dvp != NULLVP && vt == VDIR) {
282 		vp = unionfs_get_cached_vnode(uppervp, lowervp, dvp, path);
283 		if (vp != NULLVP) {
284 			vref(vp);
285 			*vpp = vp;
286 			goto unionfs_nodeget_out;
287 		}
288 	}
289 
290 	if ((uppervp == NULLVP || ump->um_uppervp != uppervp) ||
291 	    (lowervp == NULLVP || ump->um_lowervp != lowervp)) {
292 		/* dvp will be NULLVP only in case of root vnode. */
293 		if (dvp == NULLVP)
294 			return (EINVAL);
295 	}
296 	unp = malloc(sizeof(struct unionfs_node),
297 	    M_UNIONFSNODE, M_WAITOK | M_ZERO);
298 
299 	error = getnewvnode("unionfs", mp, &unionfs_vnodeops, &vp);
300 	if (error != 0) {
301 		free(unp, M_UNIONFSNODE);
302 		return (error);
303 	}
304 	error = insmntque(vp, mp);	/* XXX: Too early for mpsafe fs */
305 	if (error != 0) {
306 		free(unp, M_UNIONFSNODE);
307 		return (error);
308 	}
309 	if (dvp != NULLVP)
310 		vref(dvp);
311 	if (uppervp != NULLVP)
312 		vref(uppervp);
313 	if (lowervp != NULLVP)
314 		vref(lowervp);
315 
316 	if (vt == VDIR)
317 		unp->un_hashtbl = hashinit(NUNIONFSNODECACHE, M_UNIONFSHASH,
318 		    &(unp->un_hashmask));
319 
320 	unp->un_vnode = vp;
321 	unp->un_uppervp = uppervp;
322 	unp->un_lowervp = lowervp;
323 	unp->un_dvp = dvp;
324 	if (uppervp != NULLVP)
325 		vp->v_vnlock = uppervp->v_vnlock;
326 	else
327 		vp->v_vnlock = lowervp->v_vnlock;
328 
329 	if (path != NULL) {
330 		unp->un_path = malloc(cnp->cn_namelen + 1,
331 		    M_UNIONFSPATH, M_WAITOK | M_ZERO);
332 		bcopy(cnp->cn_nameptr, unp->un_path, cnp->cn_namelen);
333 		unp->un_path[cnp->cn_namelen] = '\0';
334 		unp->un_pathlen = cnp->cn_namelen;
335 	}
336 	vp->v_type = vt;
337 	vp->v_data = unp;
338 
339 	if ((uppervp != NULLVP && ump->um_uppervp == uppervp) &&
340 	    (lowervp != NULLVP && ump->um_lowervp == lowervp))
341 		vp->v_vflag |= VV_ROOT;
342 
343 	if (path != NULL && dvp != NULLVP && vt == VDIR)
344 		*vpp = unionfs_ins_cached_vnode(unp, dvp, path);
345 	if ((*vpp) != NULLVP) {
346 		if (dvp != NULLVP)
347 			vrele(dvp);
348 		if (uppervp != NULLVP)
349 			vrele(uppervp);
350 		if (lowervp != NULLVP)
351 			vrele(lowervp);
352 
353 		unp->un_uppervp = NULLVP;
354 		unp->un_lowervp = NULLVP;
355 		unp->un_dvp = NULLVP;
356 		vrele(vp);
357 		vp = *vpp;
358 		vref(vp);
359 	} else
360 		*vpp = vp;
361 
362 unionfs_nodeget_out:
363 	if (lkflags & LK_TYPE_MASK)
364 		vn_lock(vp, lkflags | LK_RETRY);
365 
366 	return (0);
367 }
368 
369 /*
370  * Clean up the unionfs node.
371  */
372 void
373 unionfs_noderem(struct vnode *vp, struct thread *td)
374 {
375 	struct unionfs_node *unp, *unp_t1, *unp_t2;
376 	struct unionfs_node_hashhead *hd;
377 	struct unionfs_node_status *unsp, *unsp_tmp;
378 	struct vnode   *lvp;
379 	struct vnode   *uvp;
380 	struct vnode   *dvp;
381 	int		count;
382 
383 	/*
384 	 * Use the interlock to protect the clearing of v_data to
385 	 * prevent faults in unionfs_lock().
386 	 */
387 	VI_LOCK(vp);
388 	unp = VTOUNIONFS(vp);
389 	lvp = unp->un_lowervp;
390 	uvp = unp->un_uppervp;
391 	dvp = unp->un_dvp;
392 	unp->un_lowervp = unp->un_uppervp = NULLVP;
393 	vp->v_vnlock = &(vp->v_lock);
394 	vp->v_data = NULL;
395 	vp->v_object = NULL;
396 	if (vp->v_writecount > 0) {
397 		if (uvp != NULL)
398 			VOP_ADD_WRITECOUNT(uvp, -vp->v_writecount);
399 		else if (lvp != NULL)
400 			VOP_ADD_WRITECOUNT(lvp, -vp->v_writecount);
401 	} else if (vp->v_writecount < 0)
402 		vp->v_writecount = 0;
403 	VI_UNLOCK(vp);
404 
405 	if (lvp != NULLVP)
406 		VOP_UNLOCK(lvp);
407 	if (uvp != NULLVP)
408 		VOP_UNLOCK(uvp);
409 
410 	if (dvp != NULLVP && unp->un_hash.le_prev != NULL)
411 		unionfs_rem_cached_vnode(unp, dvp);
412 
413 	if (lockmgr(vp->v_vnlock, LK_EXCLUSIVE, VI_MTX(vp)) != 0)
414 		panic("the lock for deletion is unacquirable.");
415 
416 	if (lvp != NULLVP)
417 		vrele(lvp);
418 	if (uvp != NULLVP)
419 		vrele(uvp);
420 	if (unp->un_path != NULL) {
421 		free(unp->un_path, M_UNIONFSPATH);
422 		unp->un_path = NULL;
423 		unp->un_pathlen = 0;
424 	}
425 
426 	if (unp->un_hashtbl != NULL) {
427 		for (count = 0; count <= unp->un_hashmask; count++) {
428 			hd = unp->un_hashtbl + count;
429 			LIST_FOREACH_SAFE(unp_t1, hd, un_hash, unp_t2) {
430 				LIST_REMOVE(unp_t1, un_hash);
431 				unp_t1->un_hash.le_next = NULL;
432 				unp_t1->un_hash.le_prev = NULL;
433 			}
434 		}
435 		hashdestroy(unp->un_hashtbl, M_UNIONFSHASH, unp->un_hashmask);
436 	}
437 
438 	LIST_FOREACH_SAFE(unsp, &(unp->un_unshead), uns_list, unsp_tmp) {
439 		LIST_REMOVE(unsp, uns_list);
440 		free(unsp, M_TEMP);
441 	}
442 	if (dvp != NULLVP) {
443 		mtx_lock(&unionfs_deferred_rele_lock);
444 		STAILQ_INSERT_TAIL(&unionfs_deferred_rele_list, unp, un_rele);
445 		mtx_unlock(&unionfs_deferred_rele_lock);
446 		taskqueue_enqueue(taskqueue_unionfs_rele,
447 		    &unionfs_deferred_rele_task);
448 	} else
449 		free(unp, M_UNIONFSNODE);
450 }
451 
452 /*
453  * Get the unionfs node status.
454  * You need exclusive lock this vnode.
455  */
456 void
457 unionfs_get_node_status(struct unionfs_node *unp, struct thread *td,
458     struct unionfs_node_status **unspp)
459 {
460 	struct unionfs_node_status *unsp;
461 	pid_t pid;
462 
463 	pid = td->td_proc->p_pid;
464 
465 	KASSERT(NULL != unspp, ("null pointer"));
466 	ASSERT_VOP_ELOCKED(UNIONFSTOV(unp), "unionfs_get_node_status");
467 
468 	LIST_FOREACH(unsp, &(unp->un_unshead), uns_list) {
469 		if (unsp->uns_pid == pid) {
470 			*unspp = unsp;
471 			return;
472 		}
473 	}
474 
475 	/* create a new unionfs node status */
476 	unsp = malloc(sizeof(struct unionfs_node_status),
477 	    M_TEMP, M_WAITOK | M_ZERO);
478 
479 	unsp->uns_pid = pid;
480 	LIST_INSERT_HEAD(&(unp->un_unshead), unsp, uns_list);
481 
482 	*unspp = unsp;
483 }
484 
485 /*
486  * Remove the unionfs node status, if you can.
487  * You need exclusive lock this vnode.
488  */
489 void
490 unionfs_tryrem_node_status(struct unionfs_node *unp,
491     struct unionfs_node_status *unsp)
492 {
493 	KASSERT(NULL != unsp, ("null pointer"));
494 	ASSERT_VOP_ELOCKED(UNIONFSTOV(unp), "unionfs_get_node_status");
495 
496 	if (0 < unsp->uns_lower_opencnt || 0 < unsp->uns_upper_opencnt)
497 		return;
498 
499 	LIST_REMOVE(unsp, uns_list);
500 	free(unsp, M_TEMP);
501 }
502 
503 /*
504  * Create upper node attr.
505  */
506 void
507 unionfs_create_uppervattr_core(struct unionfs_mount *ump, struct vattr *lva,
508     struct vattr *uva, struct thread *td)
509 {
510 	VATTR_NULL(uva);
511 	uva->va_type = lva->va_type;
512 	uva->va_atime = lva->va_atime;
513 	uva->va_mtime = lva->va_mtime;
514 	uva->va_ctime = lva->va_ctime;
515 
516 	switch (ump->um_copymode) {
517 	case UNIONFS_TRANSPARENT:
518 		uva->va_mode = lva->va_mode;
519 		uva->va_uid = lva->va_uid;
520 		uva->va_gid = lva->va_gid;
521 		break;
522 	case UNIONFS_MASQUERADE:
523 		if (ump->um_uid == lva->va_uid) {
524 			uva->va_mode = lva->va_mode & 077077;
525 			uva->va_mode |= (lva->va_type == VDIR ?
526 			    ump->um_udir : ump->um_ufile) & 0700;
527 			uva->va_uid = lva->va_uid;
528 			uva->va_gid = lva->va_gid;
529 		} else {
530 			uva->va_mode = (lva->va_type == VDIR ?
531 			    ump->um_udir : ump->um_ufile);
532 			uva->va_uid = ump->um_uid;
533 			uva->va_gid = ump->um_gid;
534 		}
535 		break;
536 	default:		/* UNIONFS_TRADITIONAL */
537 		uva->va_mode = 0777 & ~td->td_proc->p_pd->pd_cmask;
538 		uva->va_uid = ump->um_uid;
539 		uva->va_gid = ump->um_gid;
540 		break;
541 	}
542 }
543 
544 /*
545  * Create upper node attr.
546  */
547 int
548 unionfs_create_uppervattr(struct unionfs_mount *ump, struct vnode *lvp,
549     struct vattr *uva, struct ucred *cred, struct thread *td)
550 {
551 	struct vattr	lva;
552 	int		error;
553 
554 	if ((error = VOP_GETATTR(lvp, &lva, cred)))
555 		return (error);
556 
557 	unionfs_create_uppervattr_core(ump, &lva, uva, td);
558 
559 	return (error);
560 }
561 
562 /*
563  * relookup
564  *
565  * dvp should be locked on entry and will be locked on return.
566  *
567  * If an error is returned, *vpp will be invalid, otherwise it will hold a
568  * locked, referenced vnode. If *vpp == dvp then remember that only one
569  * LK_EXCLUSIVE lock is held.
570  */
571 int
572 unionfs_relookup(struct vnode *dvp, struct vnode **vpp,
573     struct componentname *cnp, struct componentname *cn, struct thread *td,
574     char *path, int pathlen, u_long nameiop)
575 {
576 	int error;
577 
578 	cn->cn_namelen = pathlen;
579 	cn->cn_pnbuf = path;
580 	cn->cn_nameiop = nameiop;
581 	cn->cn_flags = (LOCKPARENT | LOCKLEAF | HASBUF | SAVENAME | ISLASTCN);
582 	cn->cn_lkflags = LK_EXCLUSIVE;
583 	cn->cn_thread = td;
584 	cn->cn_cred = cnp->cn_cred;
585 	cn->cn_nameptr = cn->cn_pnbuf;
586 
587 	if (nameiop == DELETE)
588 		cn->cn_flags |= (cnp->cn_flags & (DOWHITEOUT | SAVESTART));
589 	else if (RENAME == nameiop)
590 		cn->cn_flags |= (cnp->cn_flags & SAVESTART);
591 	else if (nameiop == CREATE)
592 		cn->cn_flags |= NOCACHE;
593 
594 	vref(dvp);
595 	VOP_UNLOCK(dvp);
596 
597 	if ((error = relookup(dvp, vpp, cn))) {
598 		vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
599 	} else
600 		vrele(dvp);
601 
602 	KASSERT((cn->cn_flags & HASBUF) != 0,
603 	    ("%s: HASBUF cleared", __func__));
604 	KASSERT((cn->cn_flags & SAVENAME) != 0,
605 	    ("%s: SAVENAME cleared", __func__));
606 	KASSERT(cn->cn_pnbuf == path, ("%s: cn_pnbuf changed", __func__));
607 
608 	return (error);
609 }
610 
611 /*
612  * relookup for CREATE namei operation.
613  *
614  * dvp is unionfs vnode. dvp should be locked.
615  *
616  * If it called 'unionfs_copyfile' function by unionfs_link etc,
617  * VOP_LOOKUP information is broken.
618  * So it need relookup in order to create link etc.
619  */
620 int
621 unionfs_relookup_for_create(struct vnode *dvp, struct componentname *cnp,
622     struct thread *td)
623 {
624 	struct vnode *udvp;
625 	struct vnode *vp;
626 	struct componentname cn;
627 	int error;
628 
629 	udvp = UNIONFSVPTOUPPERVP(dvp);
630 	vp = NULLVP;
631 
632 	error = unionfs_relookup(udvp, &vp, cnp, &cn, td, cnp->cn_nameptr,
633 	    cnp->cn_namelen, CREATE);
634 	if (error)
635 		return (error);
636 
637 	if (vp != NULLVP) {
638 		if (udvp == vp)
639 			vrele(vp);
640 		else
641 			vput(vp);
642 
643 		error = EEXIST;
644 	}
645 
646 	return (error);
647 }
648 
649 /*
650  * relookup for DELETE namei operation.
651  *
652  * dvp is unionfs vnode. dvp should be locked.
653  */
654 int
655 unionfs_relookup_for_delete(struct vnode *dvp, struct componentname *cnp,
656     struct thread *td)
657 {
658 	struct vnode *udvp;
659 	struct vnode *vp;
660 	struct componentname cn;
661 	int error;
662 
663 	udvp = UNIONFSVPTOUPPERVP(dvp);
664 	vp = NULLVP;
665 
666 	error = unionfs_relookup(udvp, &vp, cnp, &cn, td, cnp->cn_nameptr,
667 	    cnp->cn_namelen, DELETE);
668 	if (error)
669 		return (error);
670 
671 	if (vp == NULLVP)
672 		error = ENOENT;
673 	else {
674 		if (udvp == vp)
675 			vrele(vp);
676 		else
677 			vput(vp);
678 	}
679 
680 	return (error);
681 }
682 
683 /*
684  * relookup for RENAME namei operation.
685  *
686  * dvp is unionfs vnode. dvp should be locked.
687  */
688 int
689 unionfs_relookup_for_rename(struct vnode *dvp, struct componentname *cnp,
690     struct thread *td)
691 {
692 	struct vnode *udvp;
693 	struct vnode *vp;
694 	struct componentname cn;
695 	int error;
696 
697 	udvp = UNIONFSVPTOUPPERVP(dvp);
698 	vp = NULLVP;
699 
700 	error = unionfs_relookup(udvp, &vp, cnp, &cn, td, cnp->cn_nameptr,
701 	    cnp->cn_namelen, RENAME);
702 	if (error)
703 		return (error);
704 
705 	if (vp != NULLVP) {
706 		if (udvp == vp)
707 			vrele(vp);
708 		else
709 			vput(vp);
710 	}
711 
712 	return (error);
713 }
714 
715 /*
716  * Update the unionfs_node.
717  *
718  * uvp is new locked upper vnode. unionfs vnode's lock will be exchanged to the
719  * uvp's lock and lower's lock will be unlocked.
720  */
721 static void
722 unionfs_node_update(struct unionfs_node *unp, struct vnode *uvp,
723     struct thread *td)
724 {
725 	struct vnode   *vp;
726 	struct vnode   *lvp;
727 	struct vnode   *dvp;
728 	unsigned	count, lockrec;
729 
730 	vp = UNIONFSTOV(unp);
731 	lvp = unp->un_lowervp;
732 	ASSERT_VOP_ELOCKED(lvp, "unionfs_node_update");
733 	dvp = unp->un_dvp;
734 
735 	/*
736 	 * lock update
737 	 */
738 	VI_LOCK(vp);
739 	unp->un_uppervp = uvp;
740 	vp->v_vnlock = uvp->v_vnlock;
741 	VI_UNLOCK(vp);
742 	lockrec = lvp->v_vnlock->lk_recurse;
743 	for (count = 0; count < lockrec; count++)
744 		vn_lock(uvp, LK_EXCLUSIVE | LK_CANRECURSE | LK_RETRY);
745 
746 	/*
747 	 * cache update
748 	 */
749 	if (unp->un_path != NULL && dvp != NULLVP && vp->v_type == VDIR) {
750 		static struct unionfs_node_hashhead *hd;
751 
752 		VI_LOCK(dvp);
753 		hd = unionfs_get_hashhead(dvp, unp->un_path);
754 		LIST_REMOVE(unp, un_hash);
755 		LIST_INSERT_HEAD(hd, unp, un_hash);
756 		VI_UNLOCK(dvp);
757 	}
758 }
759 
760 /*
761  * Create a new shadow dir.
762  *
763  * udvp should be locked on entry and will be locked on return.
764  *
765  * If no error returned, unp will be updated.
766  */
767 int
768 unionfs_mkshadowdir(struct unionfs_mount *ump, struct vnode *udvp,
769     struct unionfs_node *unp, struct componentname *cnp, struct thread *td)
770 {
771 	struct vnode   *lvp;
772 	struct vnode   *uvp;
773 	struct vattr	va;
774 	struct vattr	lva;
775 	struct nameidata nd;
776 	struct mount   *mp;
777 	struct ucred   *cred;
778 	struct ucred   *credbk;
779 	struct uidinfo *rootinfo;
780 	int		error;
781 
782 	if (unp->un_uppervp != NULLVP)
783 		return (EEXIST);
784 
785 	lvp = unp->un_lowervp;
786 	uvp = NULLVP;
787 	credbk = cnp->cn_cred;
788 
789 	/* Authority change to root */
790 	rootinfo = uifind((uid_t)0);
791 	cred = crdup(cnp->cn_cred);
792 	/*
793 	 * The calls to chgproccnt() are needed to compensate for change_ruid()
794 	 * calling chgproccnt().
795 	 */
796 	chgproccnt(cred->cr_ruidinfo, 1, 0);
797 	change_euid(cred, rootinfo);
798 	change_ruid(cred, rootinfo);
799 	change_svuid(cred, (uid_t)0);
800 	uifree(rootinfo);
801 	cnp->cn_cred = cred;
802 
803 	memset(&nd.ni_cnd, 0, sizeof(struct componentname));
804 	NDPREINIT(&nd);
805 
806 	if ((error = VOP_GETATTR(lvp, &lva, cnp->cn_cred)))
807 		goto unionfs_mkshadowdir_abort;
808 
809 	if ((error = unionfs_relookup(udvp, &uvp, cnp, &nd.ni_cnd, td,
810 	    cnp->cn_nameptr, cnp->cn_namelen, CREATE)))
811 		goto unionfs_mkshadowdir_abort;
812 	if (uvp != NULLVP) {
813 		if (udvp == uvp)
814 			vrele(uvp);
815 		else
816 			vput(uvp);
817 
818 		error = EEXIST;
819 		goto unionfs_mkshadowdir_abort;
820 	}
821 
822 	if ((error = vn_start_write(udvp, &mp, V_WAIT | PCATCH)))
823 		goto unionfs_mkshadowdir_abort;
824 	unionfs_create_uppervattr_core(ump, &lva, &va, td);
825 
826 	error = VOP_MKDIR(udvp, &uvp, &nd.ni_cnd, &va);
827 
828 	if (!error) {
829 		unionfs_node_update(unp, uvp, td);
830 
831 		/*
832 		 * XXX The bug which cannot set uid/gid was corrected.
833 		 * Ignore errors.
834 		 */
835 		va.va_type = VNON;
836 		VOP_SETATTR(uvp, &va, nd.ni_cnd.cn_cred);
837 	}
838 	vn_finished_write(mp);
839 
840 unionfs_mkshadowdir_abort:
841 	cnp->cn_cred = credbk;
842 	chgproccnt(cred->cr_ruidinfo, -1, 0);
843 	crfree(cred);
844 
845 	return (error);
846 }
847 
848 /*
849  * Create a new whiteout.
850  *
851  * dvp should be locked on entry and will be locked on return.
852  */
853 int
854 unionfs_mkwhiteout(struct vnode *dvp, struct componentname *cnp,
855     struct thread *td, char *path, int pathlen)
856 {
857 	struct vnode   *wvp;
858 	struct nameidata nd;
859 	struct mount   *mp;
860 	int		error;
861 
862 	wvp = NULLVP;
863 	NDPREINIT(&nd);
864 	if ((error = unionfs_relookup(dvp, &wvp, cnp, &nd.ni_cnd, td, path,
865 	    pathlen, CREATE))) {
866 		return (error);
867 	}
868 	if (wvp != NULLVP) {
869 		if (dvp == wvp)
870 			vrele(wvp);
871 		else
872 			vput(wvp);
873 
874 		return (EEXIST);
875 	}
876 
877 	if ((error = vn_start_write(dvp, &mp, V_WAIT | PCATCH)))
878 		goto unionfs_mkwhiteout_free_out;
879 	error = VOP_WHITEOUT(dvp, &nd.ni_cnd, CREATE);
880 
881 	vn_finished_write(mp);
882 
883 unionfs_mkwhiteout_free_out:
884 	return (error);
885 }
886 
887 /*
888  * Create a new vnode for create a new shadow file.
889  *
890  * If an error is returned, *vpp will be invalid, otherwise it will hold a
891  * locked, referenced and opened vnode.
892  *
893  * unp is never updated.
894  */
895 static int
896 unionfs_vn_create_on_upper(struct vnode **vpp, struct vnode *udvp,
897     struct unionfs_node *unp, struct vattr *uvap, struct thread *td)
898 {
899 	struct unionfs_mount *ump;
900 	struct vnode   *vp;
901 	struct vnode   *lvp;
902 	struct ucred   *cred;
903 	struct vattr	lva;
904 	struct nameidata nd;
905 	int		fmode;
906 	int		error;
907 
908 	ump = MOUNTTOUNIONFSMOUNT(UNIONFSTOV(unp)->v_mount);
909 	vp = NULLVP;
910 	lvp = unp->un_lowervp;
911 	cred = td->td_ucred;
912 	fmode = FFLAGS(O_WRONLY | O_CREAT | O_TRUNC | O_EXCL);
913 	error = 0;
914 
915 	if ((error = VOP_GETATTR(lvp, &lva, cred)) != 0)
916 		return (error);
917 	unionfs_create_uppervattr_core(ump, &lva, uvap, td);
918 
919 	if (unp->un_path == NULL)
920 		panic("unionfs: un_path is null");
921 
922 	nd.ni_cnd.cn_namelen = unp->un_pathlen;
923 	nd.ni_cnd.cn_pnbuf = unp->un_path;
924 	nd.ni_cnd.cn_nameiop = CREATE;
925 	nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | HASBUF | SAVENAME |
926 	    ISLASTCN;
927 	nd.ni_cnd.cn_lkflags = LK_EXCLUSIVE;
928 	nd.ni_cnd.cn_thread = td;
929 	nd.ni_cnd.cn_cred = cred;
930 	nd.ni_cnd.cn_nameptr = nd.ni_cnd.cn_pnbuf;
931 	NDPREINIT(&nd);
932 
933 	vref(udvp);
934 	if ((error = relookup(udvp, &vp, &nd.ni_cnd)) != 0)
935 		goto unionfs_vn_create_on_upper_free_out2;
936 	vrele(udvp);
937 
938 	if (vp != NULLVP) {
939 		if (vp == udvp)
940 			vrele(vp);
941 		else
942 			vput(vp);
943 		error = EEXIST;
944 		goto unionfs_vn_create_on_upper_free_out1;
945 	}
946 
947 	if ((error = VOP_CREATE(udvp, &vp, &nd.ni_cnd, uvap)) != 0)
948 		goto unionfs_vn_create_on_upper_free_out1;
949 
950 	if ((error = VOP_OPEN(vp, fmode, cred, td, NULL)) != 0) {
951 		vput(vp);
952 		goto unionfs_vn_create_on_upper_free_out1;
953 	}
954 	error = VOP_ADD_WRITECOUNT(vp, 1);
955 	CTR3(KTR_VFS, "%s: vp %p v_writecount increased to %d",
956 	    __func__, vp, vp->v_writecount);
957 	if (error == 0) {
958 		*vpp = vp;
959 	} else {
960 		VOP_CLOSE(vp, fmode, cred, td);
961 	}
962 
963 unionfs_vn_create_on_upper_free_out1:
964 	VOP_UNLOCK(udvp);
965 
966 unionfs_vn_create_on_upper_free_out2:
967 	KASSERT((nd.ni_cnd.cn_flags & HASBUF) != 0,
968 	    ("%s: HASBUF cleared", __func__));
969 	KASSERT((nd.ni_cnd.cn_flags & SAVENAME) != 0,
970 	    ("%s: SAVENAME cleared", __func__));
971 	KASSERT(nd.ni_cnd.cn_pnbuf == unp->un_path,
972 	    ("%s: cn_pnbuf changed", __func__));
973 
974 	return (error);
975 }
976 
977 /*
978  * Copy from lvp to uvp.
979  *
980  * lvp and uvp should be locked and opened on entry and will be locked and
981  * opened on return.
982  */
983 static int
984 unionfs_copyfile_core(struct vnode *lvp, struct vnode *uvp,
985     struct ucred *cred, struct thread *td)
986 {
987 	char           *buf;
988 	struct uio	uio;
989 	struct iovec	iov;
990 	off_t		offset;
991 	int		count;
992 	int		error;
993 	int		bufoffset;
994 
995 	error = 0;
996 	memset(&uio, 0, sizeof(uio));
997 
998 	uio.uio_td = td;
999 	uio.uio_segflg = UIO_SYSSPACE;
1000 	uio.uio_offset = 0;
1001 
1002 	buf = malloc(MAXBSIZE, M_TEMP, M_WAITOK);
1003 
1004 	while (error == 0) {
1005 		offset = uio.uio_offset;
1006 
1007 		uio.uio_iov = &iov;
1008 		uio.uio_iovcnt = 1;
1009 		iov.iov_base = buf;
1010 		iov.iov_len = MAXBSIZE;
1011 		uio.uio_resid = iov.iov_len;
1012 		uio.uio_rw = UIO_READ;
1013 
1014 		if ((error = VOP_READ(lvp, &uio, 0, cred)) != 0)
1015 			break;
1016 		if ((count = MAXBSIZE - uio.uio_resid) == 0)
1017 			break;
1018 
1019 		bufoffset = 0;
1020 		while (bufoffset < count) {
1021 			uio.uio_iov = &iov;
1022 			uio.uio_iovcnt = 1;
1023 			iov.iov_base = buf + bufoffset;
1024 			iov.iov_len = count - bufoffset;
1025 			uio.uio_offset = offset + bufoffset;
1026 			uio.uio_resid = iov.iov_len;
1027 			uio.uio_rw = UIO_WRITE;
1028 
1029 			if ((error = VOP_WRITE(uvp, &uio, 0, cred)) != 0)
1030 				break;
1031 
1032 			bufoffset += (count - bufoffset) - uio.uio_resid;
1033 		}
1034 
1035 		uio.uio_offset = offset + bufoffset;
1036 	}
1037 
1038 	free(buf, M_TEMP);
1039 
1040 	return (error);
1041 }
1042 
1043 /*
1044  * Copy file from lower to upper.
1045  *
1046  * If you need copy of the contents, set 1 to docopy. Otherwise, set 0 to
1047  * docopy.
1048  *
1049  * If no error returned, unp will be updated.
1050  */
1051 int
1052 unionfs_copyfile(struct unionfs_node *unp, int docopy, struct ucred *cred,
1053     struct thread *td)
1054 {
1055 	struct mount   *mp;
1056 	struct vnode   *udvp;
1057 	struct vnode   *lvp;
1058 	struct vnode   *uvp;
1059 	struct vattr	uva;
1060 	int		error;
1061 
1062 	lvp = unp->un_lowervp;
1063 	uvp = NULLVP;
1064 
1065 	if ((UNIONFSTOV(unp)->v_mount->mnt_flag & MNT_RDONLY))
1066 		return (EROFS);
1067 	if (unp->un_dvp == NULLVP)
1068 		return (EINVAL);
1069 	if (unp->un_uppervp != NULLVP)
1070 		return (EEXIST);
1071 	udvp = VTOUNIONFS(unp->un_dvp)->un_uppervp;
1072 	if (udvp == NULLVP)
1073 		return (EROFS);
1074 	if ((udvp->v_mount->mnt_flag & MNT_RDONLY))
1075 		return (EROFS);
1076 
1077 	error = VOP_ACCESS(lvp, VREAD, cred, td);
1078 	if (error != 0)
1079 		return (error);
1080 
1081 	if ((error = vn_start_write(udvp, &mp, V_WAIT | PCATCH)) != 0)
1082 		return (error);
1083 	error = unionfs_vn_create_on_upper(&uvp, udvp, unp, &uva, td);
1084 	if (error != 0) {
1085 		vn_finished_write(mp);
1086 		return (error);
1087 	}
1088 
1089 	if (docopy != 0) {
1090 		error = VOP_OPEN(lvp, FREAD, cred, td, NULL);
1091 		if (error == 0) {
1092 			error = unionfs_copyfile_core(lvp, uvp, cred, td);
1093 			VOP_CLOSE(lvp, FREAD, cred, td);
1094 		}
1095 	}
1096 	VOP_CLOSE(uvp, FWRITE, cred, td);
1097 	VOP_ADD_WRITECOUNT_CHECKED(uvp, -1);
1098 	CTR3(KTR_VFS, "%s: vp %p v_writecount decreased to %d",
1099 	    __func__, uvp, uvp->v_writecount);
1100 
1101 	vn_finished_write(mp);
1102 
1103 	if (error == 0) {
1104 		/* Reset the attributes. Ignore errors. */
1105 		uva.va_type = VNON;
1106 		VOP_SETATTR(uvp, &uva, cred);
1107 	}
1108 
1109 	unionfs_node_update(unp, uvp, td);
1110 
1111 	return (error);
1112 }
1113 
1114 /*
1115  * It checks whether vp can rmdir. (check empty)
1116  *
1117  * vp is unionfs vnode.
1118  * vp should be locked.
1119  */
1120 int
1121 unionfs_check_rmdir(struct vnode *vp, struct ucred *cred, struct thread *td)
1122 {
1123 	struct vnode   *uvp;
1124 	struct vnode   *lvp;
1125 	struct vnode   *tvp;
1126 	struct dirent  *dp;
1127 	struct dirent  *edp;
1128 	struct componentname cn;
1129 	struct iovec	iov;
1130 	struct uio	uio;
1131 	struct vattr	va;
1132 	int		error;
1133 	int		eofflag;
1134 	int		lookuperr;
1135 
1136 	/*
1137 	 * The size of buf needs to be larger than DIRBLKSIZ.
1138 	 */
1139 	char		buf[256 * 6];
1140 
1141 	ASSERT_VOP_ELOCKED(vp, "unionfs_check_rmdir");
1142 
1143 	eofflag = 0;
1144 	uvp = UNIONFSVPTOUPPERVP(vp);
1145 	lvp = UNIONFSVPTOLOWERVP(vp);
1146 
1147 	/* check opaque */
1148 	if ((error = VOP_GETATTR(uvp, &va, cred)) != 0)
1149 		return (error);
1150 	if (va.va_flags & OPAQUE)
1151 		return (0);
1152 
1153 	/* open vnode */
1154 #ifdef MAC
1155 	if ((error = mac_vnode_check_open(cred, vp, VEXEC|VREAD)) != 0)
1156 		return (error);
1157 #endif
1158 	if ((error = VOP_ACCESS(vp, VEXEC|VREAD, cred, td)) != 0)
1159 		return (error);
1160 	if ((error = VOP_OPEN(vp, FREAD, cred, td, NULL)) != 0)
1161 		return (error);
1162 
1163 	uio.uio_rw = UIO_READ;
1164 	uio.uio_segflg = UIO_SYSSPACE;
1165 	uio.uio_td = td;
1166 	uio.uio_offset = 0;
1167 
1168 #ifdef MAC
1169 	error = mac_vnode_check_readdir(td->td_ucred, lvp);
1170 #endif
1171 	while (!error && !eofflag) {
1172 		iov.iov_base = buf;
1173 		iov.iov_len = sizeof(buf);
1174 		uio.uio_iov = &iov;
1175 		uio.uio_iovcnt = 1;
1176 		uio.uio_resid = iov.iov_len;
1177 
1178 		error = VOP_READDIR(lvp, &uio, cred, &eofflag, NULL, NULL);
1179 		if (error != 0)
1180 			break;
1181 		if (eofflag == 0 && uio.uio_resid == sizeof(buf)) {
1182 #ifdef DIAGNOSTIC
1183 			panic("bad readdir response from lower FS.");
1184 #endif
1185 			break;
1186 		}
1187 
1188 		edp = (struct dirent*)&buf[sizeof(buf) - uio.uio_resid];
1189 		for (dp = (struct dirent*)buf; !error && dp < edp;
1190 		     dp = (struct dirent*)((caddr_t)dp + dp->d_reclen)) {
1191 			if (dp->d_type == DT_WHT || dp->d_fileno == 0 ||
1192 			    (dp->d_namlen == 1 && dp->d_name[0] == '.') ||
1193 			    (dp->d_namlen == 2 && !bcmp(dp->d_name, "..", 2)))
1194 				continue;
1195 
1196 			cn.cn_namelen = dp->d_namlen;
1197 			cn.cn_pnbuf = NULL;
1198 			cn.cn_nameptr = dp->d_name;
1199 			cn.cn_nameiop = LOOKUP;
1200 			cn.cn_flags = LOCKPARENT | LOCKLEAF | SAVENAME |
1201 			    RDONLY | ISLASTCN;
1202 			cn.cn_lkflags = LK_EXCLUSIVE;
1203 			cn.cn_thread = td;
1204 			cn.cn_cred = cred;
1205 
1206 			/*
1207 			 * check entry in lower.
1208 			 * Sometimes, readdir function returns
1209 			 * wrong entry.
1210 			 */
1211 			lookuperr = VOP_LOOKUP(lvp, &tvp, &cn);
1212 
1213 			if (!lookuperr)
1214 				vput(tvp);
1215 			else
1216 				continue; /* skip entry */
1217 
1218 			/*
1219 			 * check entry
1220 			 * If it has no exist/whiteout entry in upper,
1221 			 * directory is not empty.
1222 			 */
1223 			cn.cn_flags = LOCKPARENT | LOCKLEAF | SAVENAME |
1224 			    RDONLY | ISLASTCN;
1225 			lookuperr = VOP_LOOKUP(uvp, &tvp, &cn);
1226 
1227 			if (!lookuperr)
1228 				vput(tvp);
1229 
1230 			/* ignore exist or whiteout entry */
1231 			if (!lookuperr ||
1232 			    (lookuperr == ENOENT && (cn.cn_flags & ISWHITEOUT)))
1233 				continue;
1234 
1235 			error = ENOTEMPTY;
1236 		}
1237 	}
1238 
1239 	/* close vnode */
1240 	VOP_CLOSE(vp, FREAD, cred, td);
1241 
1242 	return (error);
1243 }
1244 
1245 #ifdef DIAGNOSTIC
1246 
1247 struct vnode   *
1248 unionfs_checkuppervp(struct vnode *vp, char *fil, int lno)
1249 {
1250 	struct unionfs_node *unp;
1251 
1252 	unp = VTOUNIONFS(vp);
1253 
1254 #ifdef notyet
1255 	if (vp->v_op != unionfs_vnodeop_p) {
1256 		printf("unionfs_checkuppervp: on non-unionfs-node.\n");
1257 #ifdef KDB
1258 		kdb_enter(KDB_WHY_UNIONFS,
1259 		    "unionfs_checkuppervp: on non-unionfs-node.\n");
1260 #endif
1261 		panic("unionfs_checkuppervp");
1262 	}
1263 #endif
1264 	return (unp->un_uppervp);
1265 }
1266 
1267 struct vnode   *
1268 unionfs_checklowervp(struct vnode *vp, char *fil, int lno)
1269 {
1270 	struct unionfs_node *unp;
1271 
1272 	unp = VTOUNIONFS(vp);
1273 
1274 #ifdef notyet
1275 	if (vp->v_op != unionfs_vnodeop_p) {
1276 		printf("unionfs_checklowervp: on non-unionfs-node.\n");
1277 #ifdef KDB
1278 		kdb_enter(KDB_WHY_UNIONFS,
1279 		    "unionfs_checklowervp: on non-unionfs-node.\n");
1280 #endif
1281 		panic("unionfs_checklowervp");
1282 	}
1283 #endif
1284 	return (unp->un_lowervp);
1285 }
1286 #endif
1287