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);
Cache object: 0a3705390fb933d6438501c70cc341ac
|