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