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