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