2 * Copyright (c) 1994 Jan-Simon Pendry
4 * The Regents of the University of California. All rights reserved.
5 * Copyright (c) 2005, 2006 Masanori Ozawa <ozawa@ongs.co.jp>, ONGS Inc.
6 * Copyright (c) 2006 Daichi Goto <daichi@freebsd.org>
8 * This code is derived from software contributed to Berkeley by
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * @(#)union_subr.c 8.20 (Berkeley) 5/20/95
36 * $FreeBSD: src/sys/fs/unionfs/union_subr.c,v 1.99 2008/01/24 12:34:27 attilio Exp $
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
43 #include <sys/mutex.h>
44 #include <sys/malloc.h>
45 #include <sys/mount.h>
46 #include <sys/namei.h>
48 #include <sys/vnode.h>
49 #include <sys/dirent.h>
50 #include <sys/fcntl.h>
51 #include <sys/filedesc.h>
53 #include <sys/kauth.h>
54 #include <sys/resourcevar.h>
56 #include <fs/unionfs/unionfs.h>
58 MALLOC_DEFINE(M_UNIONFSPATH
, "UNIONFS path", "UNIONFS path private part");
61 * Make a new or get existing unionfs node.
63 * uppervp and lowervp should be unlocked. Because if new unionfs vnode is
64 * locked, uppervp or lowervp is locked too. In order to prevent dead lock,
65 * you should not lock plurality simultaneously.
68 unionfs_nodeget(struct mount
*mp
, struct vnode
*uppervp
,
69 struct vnode
*lowervp
, struct vnode
*dvp
,
70 struct vnode
**vpp
, struct componentname
*cnp
)
72 struct unionfs_mount
*ump
;
73 struct unionfs_node
*unp
;
78 ump
= MOUNTTOUNIONFSMOUNT(mp
);
79 path
= (cnp
? cnp
->cn_nameptr
: NULL
);
81 if (uppervp
== NULLVP
&& lowervp
== NULLVP
)
82 panic("unionfs_nodeget: upper and lower is null");
84 /* If it has no ISLASTCN flag, path check is skipped. */
85 if (cnp
&& !(cnp
->cn_flags
& ISLASTCN
))
88 if ((uppervp
== NULLVP
|| ump
->um_uppervp
!= uppervp
) ||
89 (lowervp
== NULLVP
|| ump
->um_lowervp
!= lowervp
)) {
94 unp
= kmem_zalloc(sizeof(*unp
), KM_SLEEP
);
97 error
= getnewvnode(VT_UNION
, mp
, unionfs_vnodeop_p
, &vp
);
99 kmem_free(unp
, sizeof(*unp
));
104 if (uppervp
!= NULLVP
)
106 if (lowervp
!= NULLVP
)
110 unp
->un_uppervp
= uppervp
;
111 unp
->un_lowervp
= lowervp
;
113 if (uppervp
!= NULLVP
)
114 vp
->v_vnlock
= uppervp
->v_vnlock
;
116 vp
->v_vnlock
= lowervp
->v_vnlock
;
119 unp
->un_path
= (char *)
120 malloc(cnp
->cn_namelen
+1, M_UNIONFSPATH
, M_WAITOK
|M_ZERO
);
121 memcpy(unp
->un_path
, cnp
->cn_nameptr
, cnp
->cn_namelen
);
122 unp
->un_path
[cnp
->cn_namelen
] = '\0';
124 vp
->v_type
= (uppervp
!= NULLVP
? uppervp
->v_type
: lowervp
->v_type
);
126 uvm_vnp_setsize(vp
, 0);
128 if ((uppervp
!= NULLVP
&& ump
->um_uppervp
== uppervp
) &&
129 (lowervp
!= NULLVP
&& ump
->um_lowervp
== lowervp
))
130 vp
->v_vflag
|= VV_ROOT
;
138 * Clean up the unionfs node.
141 unionfs_noderem(struct vnode
*vp
)
143 struct unionfs_mount
*ump
;
144 struct unionfs_node
*unp
;
145 struct unionfs_node_status
*unsp
;
149 ump
= MOUNTTOUNIONFSMOUNT(vp
->v_mount
);
152 * Use the interlock to protect the clearing of v_data to
153 * prevent faults in unionfs_lock().
155 unp
= VTOUNIONFS(vp
);
156 lvp
= unp
->un_lowervp
;
157 uvp
= unp
->un_uppervp
;
158 unp
->un_lowervp
= unp
->un_uppervp
= NULLVP
;
159 vp
->v_vnlock
= &(vp
->v_lock
);
166 if (unp
->un_dvp
!= NULLVP
) {
168 unp
->un_dvp
= NULLVP
;
171 free(unp
->un_path
, M_UNIONFSPATH
);
175 while ((unsp
= LIST_FIRST(&(unp
->un_unshead
))) != NULL
) {
176 LIST_REMOVE(unsp
, uns_list
);
179 kmem_free(unp
, sizeof(*unp
));
183 * Get the unionfs node status.
184 * You need exclusive lock this vnode.
187 unionfs_get_node_status(struct unionfs_node
*unp
,
188 struct unionfs_node_status
**unspp
)
190 struct unionfs_node_status
*unsp
;
194 KASSERT(NULL
!= unspp
);
195 KASSERT(VOP_ISLOCKED(UNIONFSTOV(unp
)) == LK_EXCLUSIVE
);
197 pid
= curproc
->p_pid
;
200 LIST_FOREACH(unsp
, &(unp
->un_unshead
), uns_list
) {
201 if (unsp
->uns_pid
== pid
&& unsp
->uns_lid
== lid
) {
207 /* create a new unionfs node status */
208 unsp
= kmem_zalloc(sizeof(*unsp
), KM_SLEEP
);
211 LIST_INSERT_HEAD(&(unp
->un_unshead
), unsp
, uns_list
);
217 * Remove the unionfs node status, if you can.
218 * You need exclusive lock this vnode.
221 unionfs_tryrem_node_status(struct unionfs_node
*unp
,
222 struct unionfs_node_status
*unsp
)
224 KASSERT(NULL
!= unsp
);
225 KASSERT(VOP_ISLOCKED(UNIONFSTOV(unp
)) == LK_EXCLUSIVE
);
227 if (0 < unsp
->uns_lower_opencnt
|| 0 < unsp
->uns_upper_opencnt
)
230 LIST_REMOVE(unsp
, uns_list
);
231 kmem_free(unsp
, sizeof(*unsp
));
235 * Create upper node attr.
238 unionfs_create_uppervattr_core(struct unionfs_mount
*ump
,
243 uva
->va_type
= lva
->va_type
;
244 uva
->va_atime
= lva
->va_atime
;
245 uva
->va_mtime
= lva
->va_mtime
;
246 uva
->va_ctime
= lva
->va_ctime
;
248 switch (ump
->um_copymode
) {
249 case UNIONFS_TRANSPARENT
:
250 uva
->va_mode
= lva
->va_mode
;
251 uva
->va_uid
= lva
->va_uid
;
252 uva
->va_gid
= lva
->va_gid
;
254 case UNIONFS_MASQUERADE
:
255 if (ump
->um_uid
== lva
->va_uid
) {
256 uva
->va_mode
= lva
->va_mode
& 077077;
257 uva
->va_mode
|= (lva
->va_type
== VDIR
? ump
->um_udir
: ump
->um_ufile
) & 0700;
258 uva
->va_uid
= lva
->va_uid
;
259 uva
->va_gid
= lva
->va_gid
;
261 uva
->va_mode
= (lva
->va_type
== VDIR
? ump
->um_udir
: ump
->um_ufile
);
262 uva
->va_uid
= ump
->um_uid
;
263 uva
->va_gid
= ump
->um_gid
;
266 default: /* UNIONFS_TRADITIONAL */
267 uva
->va_mode
= 0777 & ~curproc
->p_cwdi
->cwdi_cmask
;
268 uva
->va_uid
= ump
->um_uid
;
269 uva
->va_gid
= ump
->um_gid
;
275 * Create upper node attr.
278 unionfs_create_uppervattr(struct unionfs_mount
*ump
,
286 if ((error
= VOP_GETATTR(lvp
, &lva
, cred
)))
289 unionfs_create_uppervattr_core(ump
, &lva
, uva
);
297 * dvp should be locked on entry and will be locked on return.
299 * If an error is returned, *vpp will be invalid, otherwise it will hold a
300 * locked, referenced vnode. If *vpp == dvp then remember that only one
301 * LK_EXCLUSIVE lock is held.
304 unionfs_relookup(struct vnode
*dvp
, struct vnode
**vpp
,
305 struct componentname
*cnp
, struct componentname
*cn
,
306 const char *path
, int pathlen
, u_long nameiop
)
310 cn
->cn_namelen
= pathlen
;
311 cn
->cn_pnbuf
= PNBUF_GET();
312 memcpy(cn
->cn_pnbuf
, path
, pathlen
);
313 cn
->cn_pnbuf
[pathlen
] = '\0';
315 cn
->cn_nameiop
= nameiop
;
316 cn
->cn_flags
= (LOCKPARENT
| LOCKLEAF
| HASBUF
| SAVENAME
| ISLASTCN
);
317 cn
->cn_cred
= cnp
->cn_cred
;
319 cn
->cn_nameptr
= cn
->cn_pnbuf
;
320 cn
->cn_consume
= cnp
->cn_consume
;
322 if (nameiop
== DELETE
)
323 cn
->cn_flags
|= (cnp
->cn_flags
& (DOWHITEOUT
| SAVESTART
));
324 else if (RENAME
== nameiop
)
325 cn
->cn_flags
|= (cnp
->cn_flags
& SAVESTART
);
330 if ((error
= relookup(dvp
, vpp
, cn
))) {
331 PNBUF_PUT(cn
->cn_pnbuf
);
332 cn
->cn_flags
&= ~HASBUF
;
333 vn_lock(dvp
, LK_EXCLUSIVE
| LK_RETRY
);
341 * relookup for CREATE namei operation.
343 * dvp is unionfs vnode. dvp should be locked.
345 * If it called 'unionfs_copyfile' function by unionfs_link etc,
346 * VOP_LOOKUP information is broken.
347 * So it need relookup in order to create link etc.
350 unionfs_relookup_for_create(struct vnode
*dvp
, struct componentname
*cnp
)
355 struct componentname cn
;
357 udvp
= UNIONFSVPTOUPPERVP(dvp
);
360 error
= unionfs_relookup(udvp
, &vp
, cnp
, &cn
, cnp
->cn_nameptr
,
361 strlen(cnp
->cn_nameptr
), CREATE
);
374 if (cn
.cn_flags
& HASBUF
) {
375 PNBUF_PUT(cn
.cn_pnbuf
);
376 cn
.cn_flags
&= ~HASBUF
;
380 cn
.cn_flags
|= (cnp
->cn_flags
& HASBUF
);
381 cnp
->cn_flags
= cn
.cn_flags
;
388 * relookup for DELETE namei operation.
390 * dvp is unionfs vnode. dvp should be locked.
393 unionfs_relookup_for_delete(struct vnode
*dvp
, struct componentname
*cnp
)
398 struct componentname cn
;
400 udvp
= UNIONFSVPTOUPPERVP(dvp
);
403 error
= unionfs_relookup(udvp
, &vp
, cnp
, &cn
, cnp
->cn_nameptr
,
404 strlen(cnp
->cn_nameptr
), DELETE
);
417 if (cn
.cn_flags
& HASBUF
) {
418 PNBUF_PUT(cn
.cn_pnbuf
);
419 cn
.cn_flags
&= ~HASBUF
;
423 cn
.cn_flags
|= (cnp
->cn_flags
& HASBUF
);
424 cnp
->cn_flags
= cn
.cn_flags
;
431 * relookup for RENAME namei operation.
433 * dvp is unionfs vnode. dvp should be locked.
436 unionfs_relookup_for_rename(struct vnode
*dvp
, struct componentname
*cnp
)
441 struct componentname cn
;
443 udvp
= UNIONFSVPTOUPPERVP(dvp
);
446 error
= unionfs_relookup(udvp
, &vp
, cnp
, &cn
, cnp
->cn_nameptr
,
447 strlen(cnp
->cn_nameptr
), RENAME
);
458 if (cn
.cn_flags
& HASBUF
) {
459 PNBUF_PUT(cn
.cn_pnbuf
);
460 cn
.cn_flags
&= ~HASBUF
;
464 cn
.cn_flags
|= (cnp
->cn_flags
& HASBUF
);
465 cnp
->cn_flags
= cn
.cn_flags
;
473 * Update the unionfs_node.
475 * uvp is new locked upper vnode. unionfs vnode's lock will be exchanged to the
476 * uvp's lock and lower's lock will be unlocked.
479 unionfs_node_update(struct unionfs_node
*unp
, struct vnode
*uvp
)
485 vp
= UNIONFSTOV(unp
);
486 lvp
= unp
->un_lowervp
;
491 mutex_enter(&vp
->v_interlock
);
492 unp
->un_uppervp
= uvp
;
493 vp
->v_vnlock
= uvp
->v_vnlock
;
494 lockcnt
= lvp
->v_vnlock
->vl_recursecnt
+
495 rw_write_held(&lvp
->v_vnlock
->vl_lock
);
497 panic("unionfs: no exclusive lock");
498 mutex_exit(&vp
->v_interlock
);
499 for (count
= 1; count
< lockcnt
; count
++)
500 vn_lock(uvp
, LK_EXCLUSIVE
| LK_CANRECURSE
| LK_RETRY
);
504 * Create a new shadow dir.
506 * udvp should be locked on entry and will be locked on return.
508 * If no error returned, unp will be updated.
511 unionfs_mkshadowdir(struct unionfs_mount
*ump
, struct vnode
*udvp
,
512 struct unionfs_node
*unp
, struct componentname
*cnp
)
519 struct componentname cn
;
521 if (unp
->un_uppervp
!= NULLVP
)
524 lvp
= unp
->un_lowervp
;
527 memset(&cn
, 0, sizeof(cn
));
529 if ((error
= VOP_GETATTR(lvp
, &lva
, cnp
->cn_cred
)))
530 goto unionfs_mkshadowdir_abort
;
532 if ((error
= unionfs_relookup(udvp
, &uvp
, cnp
, &cn
, cnp
->cn_nameptr
, cnp
->cn_namelen
, CREATE
)))
533 goto unionfs_mkshadowdir_abort
;
541 goto unionfs_mkshadowdir_free_out
;
544 unionfs_create_uppervattr_core(ump
, &lva
, &va
);
546 error
= VOP_MKDIR(udvp
, &uvp
, &cn
, &va
);
549 unionfs_node_update(unp
, uvp
);
552 * XXX The bug which cannot set uid/gid was corrected.
553 * Ignore errors. XXXNETBSD Why is this done as root?
556 VOP_SETATTR(uvp
, &va
, lwp0
.l_cred
);
559 unionfs_mkshadowdir_free_out
:
560 if (cn
.cn_flags
& HASBUF
) {
561 PNBUF_PUT(cn
.cn_pnbuf
);
562 cn
.cn_flags
&= ~HASBUF
;
565 unionfs_mkshadowdir_abort
:
571 * Create a new whiteout.
573 * dvp should be locked on entry and will be locked on return.
576 unionfs_mkwhiteout(struct vnode
*dvp
, struct componentname
*cnp
, const char *path
)
580 struct componentname cn
;
583 path
= cnp
->cn_nameptr
;
586 if ((error
= unionfs_relookup(dvp
, &wvp
, cnp
, &cn
, path
, strlen(path
), CREATE
)))
589 if (cn
.cn_flags
& HASBUF
) {
590 PNBUF_PUT(cn
.cn_pnbuf
);
591 cn
.cn_flags
&= ~HASBUF
;
601 if (cn
.cn_flags
& HASBUF
) {
602 PNBUF_PUT(cn
.cn_pnbuf
);
603 cn
.cn_flags
&= ~HASBUF
;
610 * Create a new vnode for create a new shadow file.
612 * If an error is returned, *vpp will be invalid, otherwise it will hold a
613 * locked, referenced and opened vnode.
615 * unp is never updated.
618 unionfs_vn_create_on_upper(struct vnode
**vpp
, struct vnode
*udvp
,
619 struct unionfs_node
*unp
, struct vattr
*uvap
)
621 struct unionfs_mount
*ump
;
628 struct componentname cn
;
630 ump
= MOUNTTOUNIONFSMOUNT(UNIONFSTOV(unp
)->v_mount
);
632 lvp
= unp
->un_lowervp
;
633 cred
= kauth_cred_get();
634 fmode
= FFLAGS(O_WRONLY
| O_CREAT
| O_TRUNC
| O_EXCL
);
637 if ((error
= VOP_GETATTR(lvp
, &lva
, cred
)) != 0)
639 unionfs_create_uppervattr_core(ump
, &lva
, uvap
);
641 if (unp
->un_path
== NULL
)
642 panic("unionfs: un_path is null");
644 cn
.cn_namelen
= strlen(unp
->un_path
);
645 cn
.cn_pnbuf
= PNBUF_GET();
646 memcpy(cn
.cn_pnbuf
, unp
->un_path
, cn
.cn_namelen
+ 1);
647 cn
.cn_nameiop
= CREATE
;
648 cn
.cn_flags
= (LOCKPARENT
| LOCKLEAF
| HASBUF
| SAVENAME
| ISLASTCN
);
650 cn
.cn_nameptr
= cn
.cn_pnbuf
;
654 if ((error
= relookup(udvp
, &vp
, &cn
)) != 0)
655 goto unionfs_vn_create_on_upper_free_out2
;
664 goto unionfs_vn_create_on_upper_free_out1
;
667 if ((error
= VOP_CREATE(udvp
, &vp
, &cn
, uvap
)) != 0)
668 goto unionfs_vn_create_on_upper_free_out1
;
670 if ((error
= VOP_OPEN(vp
, fmode
, cred
)) != 0) {
672 goto unionfs_vn_create_on_upper_free_out1
;
677 unionfs_vn_create_on_upper_free_out1
:
680 unionfs_vn_create_on_upper_free_out2
:
681 if (cn
.cn_flags
& HASBUF
) {
682 PNBUF_PUT(cn
.cn_pnbuf
);
683 cn
.cn_flags
&= ~HASBUF
;
690 * Copy from lvp to uvp.
692 * lvp and uvp should be locked and opened on entry and will be locked and
696 unionfs_copyfile_core(struct vnode
*lvp
, struct vnode
*uvp
,
708 memset(&uio
, 0, sizeof(uio
));
709 UIO_SETUP_SYSSPACE(&uio
);
712 buf
= kmem_alloc(MAXBSIZE
, KM_SLEEP
);
717 offset
= uio
.uio_offset
;
722 iov
.iov_len
= MAXBSIZE
;
723 uio
.uio_resid
= iov
.iov_len
;
724 uio
.uio_rw
= UIO_READ
;
726 if ((error
= VOP_READ(lvp
, &uio
, 0, cred
)) != 0)
728 if ((count
= MAXBSIZE
- uio
.uio_resid
) == 0)
732 while (bufoffset
< count
) {
735 iov
.iov_base
= buf
+ bufoffset
;
736 iov
.iov_len
= count
- bufoffset
;
737 uio
.uio_offset
= offset
+ bufoffset
;
738 uio
.uio_resid
= iov
.iov_len
;
739 uio
.uio_rw
= UIO_WRITE
;
741 if ((error
= VOP_WRITE(uvp
, &uio
, 0, cred
)) != 0)
744 bufoffset
+= (count
- bufoffset
) - uio
.uio_resid
;
747 uio
.uio_offset
= offset
+ bufoffset
;
750 kmem_free(buf
, MAXBSIZE
);
756 * Copy file from lower to upper.
758 * If you need copy of the contents, set 1 to docopy. Otherwise, set 0 to
761 * If no error returned, unp will be updated.
764 unionfs_copyfile(struct unionfs_node
*unp
, int docopy
, kauth_cred_t cred
)
772 lvp
= unp
->un_lowervp
;
775 if ((UNIONFSTOV(unp
)->v_mount
->mnt_flag
& MNT_RDONLY
))
777 if (unp
->un_dvp
== NULLVP
)
779 if (unp
->un_uppervp
!= NULLVP
)
781 udvp
= VTOUNIONFS(unp
->un_dvp
)->un_uppervp
;
784 if ((udvp
->v_mount
->mnt_flag
& MNT_RDONLY
))
787 error
= VOP_ACCESS(lvp
, VREAD
, cred
);
791 error
= unionfs_vn_create_on_upper(&uvp
, udvp
, unp
, &uva
);
796 error
= VOP_OPEN(lvp
, FREAD
, cred
);
798 error
= unionfs_copyfile_core(lvp
, uvp
, cred
);
799 VOP_CLOSE(lvp
, FREAD
, cred
);
802 VOP_CLOSE(uvp
, FWRITE
, cred
);
806 /* Reset the attributes. Ignore errors. */
808 VOP_SETATTR(uvp
, &uva
, cred
);
811 unionfs_node_update(unp
, uvp
);
817 * It checks whether vp can rmdir. (check empty)
819 * vp is unionfs vnode.
820 * vp should be locked.
823 unionfs_check_rmdir(struct vnode
*vp
, kauth_cred_t cred
)
832 struct componentname cn
;
834 * The size of buf needs to be larger than DIRBLKSIZ.
842 KASSERT(VOP_ISLOCKED(vp
) == LK_EXCLUSIVE
);
845 uvp
= UNIONFSVPTOUPPERVP(vp
);
846 lvp
= UNIONFSVPTOLOWERVP(vp
);
849 if ((error
= VOP_GETATTR(uvp
, &va
, cred
)) != 0)
851 if (va
.va_flags
& OPAQUE
)
855 if ((error
= VOP_ACCESS(vp
, VEXEC
|VREAD
, cred
)) != 0)
857 if ((error
= VOP_OPEN(vp
, FREAD
, cred
)) != 0)
860 UIO_SETUP_SYSSPACE(&uio
);
861 uio
.uio_rw
= UIO_READ
;
864 while (!error
&& !eofflag
) {
866 iov
.iov_len
= sizeof(buf
);
869 uio
.uio_resid
= iov
.iov_len
;
871 error
= VOP_READDIR(lvp
, &uio
, cred
, &eofflag
, NULL
, NULL
);
875 edp
= (struct dirent
*)&buf
[sizeof(buf
) - uio
.uio_resid
];
876 for (dp
= (struct dirent
*)buf
; !error
&& dp
< edp
;
877 dp
= (struct dirent
*)((char *)dp
+ dp
->d_reclen
)) {
878 if (dp
->d_type
== DT_WHT
||
879 (dp
->d_namlen
== 1 && dp
->d_name
[0] == '.') ||
880 (dp
->d_namlen
== 2 && !memcmp(dp
->d_name
, "..", 2)))
883 cn
.cn_namelen
= dp
->d_namlen
;
885 cn
.cn_nameptr
= dp
->d_name
;
886 cn
.cn_nameiop
= LOOKUP
;
887 cn
.cn_flags
= (LOCKPARENT
| LOCKLEAF
| SAVENAME
| RDONLY
| ISLASTCN
);
892 * check entry in lower.
893 * Sometimes, readdir function returns
896 lookuperr
= VOP_LOOKUP(lvp
, &tvp
, &cn
);
901 continue; /* skip entry */
905 * If it has no exist/whiteout entry in upper,
906 * directory is not empty.
908 cn
.cn_flags
= (LOCKPARENT
| LOCKLEAF
| SAVENAME
| RDONLY
| ISLASTCN
);
909 lookuperr
= VOP_LOOKUP(uvp
, &tvp
, &cn
);
914 /* ignore exist or whiteout entry */
916 (lookuperr
== ENOENT
&& (cn
.cn_flags
& ISWHITEOUT
)))
924 VOP_CLOSE(vp
, FREAD
, cred
);
932 unionfs_checkuppervp(struct vnode
*vp
, const char *fil
, int lno
)
934 struct unionfs_node
*unp
;
936 unp
= VTOUNIONFS(vp
);
939 if (vp
->v_op
!= unionfs_vnodeop_p
) {
940 printf("unionfs_checkuppervp: on non-unionfs-node.\n");
942 kdb_enter(KDB_WHY_UNIONFS
,
943 "unionfs_checkuppervp: on non-unionfs-node.\n");
945 panic("unionfs_checkuppervp");
948 return (unp
->un_uppervp
);
952 unionfs_checklowervp(struct vnode
*vp
, const char *fil
, int lno
)
954 struct unionfs_node
*unp
;
956 unp
= VTOUNIONFS(vp
);
959 if (vp
->v_op
!= unionfs_vnodeop_p
) {
960 printf("unionfs_checklowervp: on non-unionfs-node.\n");
962 kdb_enter(KDB_WHY_UNIONFS
,
963 "unionfs_checklowervp: on non-unionfs-node.\n");
965 panic("unionfs_checklowervp");
968 return (unp
->un_lowervp
);