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