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