union_vnops.c revision 1.65 1 /* $NetBSD: union_vnops.c,v 1.65 2017/04/11 14:25:00 riastradh Exp $ */
2
3 /*
4 * Copyright (c) 1992, 1993, 1994, 1995
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Jan-Simon Pendry.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * @(#)union_vnops.c 8.33 (Berkeley) 7/31/95
35 */
36
37 /*
38 * Copyright (c) 1992, 1993, 1994, 1995 Jan-Simon Pendry.
39 *
40 * This code is derived from software contributed to Berkeley by
41 * Jan-Simon Pendry.
42 *
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
45 * are met:
46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution.
51 * 3. All advertising materials mentioning features or use of this software
52 * must display the following acknowledgement:
53 * This product includes software developed by the University of
54 * California, Berkeley and its contributors.
55 * 4. Neither the name of the University nor the names of its contributors
56 * may be used to endorse or promote products derived from this software
57 * without specific prior written permission.
58 *
59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 * SUCH DAMAGE.
70 *
71 * @(#)union_vnops.c 8.33 (Berkeley) 7/31/95
72 */
73
74 #include <sys/cdefs.h>
75 __KERNEL_RCSID(0, "$NetBSD: union_vnops.c,v 1.65 2017/04/11 14:25:00 riastradh Exp $");
76
77 #include <sys/param.h>
78 #include <sys/systm.h>
79 #include <sys/proc.h>
80 #include <sys/file.h>
81 #include <sys/time.h>
82 #include <sys/stat.h>
83 #include <sys/vnode.h>
84 #include <sys/mount.h>
85 #include <sys/namei.h>
86 #include <sys/malloc.h>
87 #include <sys/buf.h>
88 #include <sys/queue.h>
89 #include <sys/lock.h>
90 #include <sys/kauth.h>
91
92 #include <fs/union/union.h>
93 #include <miscfs/genfs/genfs.h>
94 #include <miscfs/specfs/specdev.h>
95
96 int union_lookup(void *);
97 int union_create(void *);
98 int union_whiteout(void *);
99 int union_mknod(void *);
100 int union_open(void *);
101 int union_close(void *);
102 int union_access(void *);
103 int union_getattr(void *);
104 int union_setattr(void *);
105 int union_read(void *);
106 int union_write(void *);
107 int union_ioctl(void *);
108 int union_poll(void *);
109 int union_revoke(void *);
110 int union_mmap(void *);
111 int union_fsync(void *);
112 int union_seek(void *);
113 int union_remove(void *);
114 int union_link(void *);
115 int union_rename(void *);
116 int union_mkdir(void *);
117 int union_rmdir(void *);
118 int union_symlink(void *);
119 int union_readdir(void *);
120 int union_readlink(void *);
121 int union_abortop(void *);
122 int union_inactive(void *);
123 int union_reclaim(void *);
124 int union_lock(void *);
125 int union_unlock(void *);
126 int union_bmap(void *);
127 int union_print(void *);
128 int union_islocked(void *);
129 int union_pathconf(void *);
130 int union_advlock(void *);
131 int union_strategy(void *);
132 int union_bwrite(void *);
133 int union_getpages(void *);
134 int union_putpages(void *);
135 int union_kqfilter(void *);
136
137 static int union_lookup1(struct vnode *, struct vnode **,
138 struct vnode **, struct componentname *);
139
140
141 /*
142 * Global vfs data structures
143 */
144 int (**union_vnodeop_p)(void *);
145 const struct vnodeopv_entry_desc union_vnodeop_entries[] = {
146 { &vop_default_desc, vn_default_error },
147 { &vop_lookup_desc, union_lookup }, /* lookup */
148 { &vop_create_desc, union_create }, /* create */
149 { &vop_whiteout_desc, union_whiteout }, /* whiteout */
150 { &vop_mknod_desc, union_mknod }, /* mknod */
151 { &vop_open_desc, union_open }, /* open */
152 { &vop_close_desc, union_close }, /* close */
153 { &vop_access_desc, union_access }, /* access */
154 { &vop_getattr_desc, union_getattr }, /* getattr */
155 { &vop_setattr_desc, union_setattr }, /* setattr */
156 { &vop_read_desc, union_read }, /* read */
157 { &vop_write_desc, union_write }, /* write */
158 { &vop_fallocate_desc, genfs_eopnotsupp }, /* fallocate */
159 { &vop_fdiscard_desc, genfs_eopnotsupp }, /* fdiscard */
160 { &vop_ioctl_desc, union_ioctl }, /* ioctl */
161 { &vop_poll_desc, union_poll }, /* select */
162 { &vop_revoke_desc, union_revoke }, /* revoke */
163 { &vop_mmap_desc, union_mmap }, /* mmap */
164 { &vop_fsync_desc, union_fsync }, /* fsync */
165 { &vop_seek_desc, union_seek }, /* seek */
166 { &vop_remove_desc, union_remove }, /* remove */
167 { &vop_link_desc, union_link }, /* link */
168 { &vop_rename_desc, union_rename }, /* rename */
169 { &vop_mkdir_desc, union_mkdir }, /* mkdir */
170 { &vop_rmdir_desc, union_rmdir }, /* rmdir */
171 { &vop_symlink_desc, union_symlink }, /* symlink */
172 { &vop_readdir_desc, union_readdir }, /* readdir */
173 { &vop_readlink_desc, union_readlink }, /* readlink */
174 { &vop_abortop_desc, union_abortop }, /* abortop */
175 { &vop_inactive_desc, union_inactive }, /* inactive */
176 { &vop_reclaim_desc, union_reclaim }, /* reclaim */
177 { &vop_lock_desc, union_lock }, /* lock */
178 { &vop_unlock_desc, union_unlock }, /* unlock */
179 { &vop_bmap_desc, union_bmap }, /* bmap */
180 { &vop_strategy_desc, union_strategy }, /* strategy */
181 { &vop_bwrite_desc, union_bwrite }, /* bwrite */
182 { &vop_print_desc, union_print }, /* print */
183 { &vop_islocked_desc, union_islocked }, /* islocked */
184 { &vop_pathconf_desc, union_pathconf }, /* pathconf */
185 { &vop_advlock_desc, union_advlock }, /* advlock */
186 { &vop_getpages_desc, union_getpages }, /* getpages */
187 { &vop_putpages_desc, union_putpages }, /* putpages */
188 { &vop_kqfilter_desc, union_kqfilter }, /* kqfilter */
189 { NULL, NULL }
190 };
191 const struct vnodeopv_desc union_vnodeop_opv_desc =
192 { &union_vnodeop_p, union_vnodeop_entries };
193
194 #define NODE_IS_SPECIAL(vp) \
195 ((vp)->v_type == VBLK || (vp)->v_type == VCHR || \
196 (vp)->v_type == VSOCK || (vp)->v_type == VFIFO)
197
198 static int
199 union_lookup1(struct vnode *udvp, struct vnode **dvpp, struct vnode **vpp,
200 struct componentname *cnp)
201 {
202 int error;
203 struct vnode *tdvp;
204 struct vnode *dvp;
205 struct mount *mp;
206
207 dvp = *dvpp;
208
209 /*
210 * If stepping up the directory tree, check for going
211 * back across the mount point, in which case do what
212 * lookup would do by stepping back down the mount
213 * hierarchy.
214 */
215 if (cnp->cn_flags & ISDOTDOT) {
216 while ((dvp != udvp) && (dvp->v_vflag & VV_ROOT)) {
217 /*
218 * Don't do the NOCROSSMOUNT check
219 * at this level. By definition,
220 * union fs deals with namespaces, not
221 * filesystems.
222 */
223 tdvp = dvp;
224 *dvpp = dvp = dvp->v_mount->mnt_vnodecovered;
225 VOP_UNLOCK(tdvp);
226 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
227 }
228 }
229
230 error = VOP_LOOKUP(dvp, &tdvp, cnp);
231 if (error)
232 return (error);
233 if (dvp != tdvp) {
234 if (cnp->cn_flags & ISDOTDOT)
235 VOP_UNLOCK(dvp);
236 error = vn_lock(tdvp, LK_EXCLUSIVE);
237 if (cnp->cn_flags & ISDOTDOT)
238 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
239 if (error) {
240 vrele(tdvp);
241 return error;
242 }
243 dvp = tdvp;
244 }
245
246 /*
247 * Lastly check if the current node is a mount point in
248 * which case walk up the mount hierarchy making sure not to
249 * bump into the root of the mount tree (ie. dvp != udvp).
250 */
251 while (dvp != udvp && (dvp->v_type == VDIR) &&
252 (mp = dvp->v_mountedhere)) {
253 if (vfs_busy(mp, NULL))
254 continue;
255 vput(dvp);
256 error = VFS_ROOT(mp, &tdvp);
257 vfs_unbusy(mp, false, NULL);
258 if (error) {
259 return (error);
260 }
261 dvp = tdvp;
262 }
263
264 *vpp = dvp;
265 return (0);
266 }
267
268 int
269 union_lookup(void *v)
270 {
271 struct vop_lookup_v2_args /* {
272 struct vnodeop_desc *a_desc;
273 struct vnode *a_dvp;
274 struct vnode **a_vpp;
275 struct componentname *a_cnp;
276 } */ *ap = v;
277 int error;
278 int uerror, lerror;
279 struct vnode *uppervp, *lowervp;
280 struct vnode *upperdvp, *lowerdvp;
281 struct vnode *dvp = ap->a_dvp;
282 struct union_node *dun = VTOUNION(dvp);
283 struct componentname *cnp = ap->a_cnp;
284 struct union_mount *um = MOUNTTOUNIONMOUNT(dvp->v_mount);
285 kauth_cred_t saved_cred = NULL;
286 int iswhiteout;
287 struct vattr va;
288
289 #ifdef notyet
290 if (cnp->cn_namelen == 3 &&
291 cnp->cn_nameptr[2] == '.' &&
292 cnp->cn_nameptr[1] == '.' &&
293 cnp->cn_nameptr[0] == '.') {
294 dvp = *ap->a_vpp = LOWERVP(ap->a_dvp);
295 if (dvp == NULLVP)
296 return (ENOENT);
297 vref(dvp);
298 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
299 return (0);
300 }
301 #endif
302
303 if ((cnp->cn_flags & ISLASTCN) &&
304 (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
305 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
306 return (EROFS);
307
308 start:
309 upperdvp = dun->un_uppervp;
310 lowerdvp = dun->un_lowervp;
311 uppervp = NULLVP;
312 lowervp = NULLVP;
313 iswhiteout = 0;
314
315 /*
316 * do the lookup in the upper level.
317 * if that level comsumes additional pathnames,
318 * then assume that something special is going
319 * on and just return that vnode.
320 */
321 if (upperdvp != NULLVP) {
322 uerror = union_lookup1(um->um_uppervp, &upperdvp,
323 &uppervp, cnp);
324 if (cnp->cn_consume != 0) {
325 if (uppervp != upperdvp)
326 VOP_UNLOCK(uppervp);
327 *ap->a_vpp = uppervp;
328 return (uerror);
329 }
330 if (uerror == ENOENT || uerror == EJUSTRETURN) {
331 if (cnp->cn_flags & ISWHITEOUT) {
332 iswhiteout = 1;
333 } else if (lowerdvp != NULLVP) {
334 lerror = VOP_GETATTR(upperdvp, &va,
335 cnp->cn_cred);
336 if (lerror == 0 && (va.va_flags & OPAQUE))
337 iswhiteout = 1;
338 }
339 }
340 } else {
341 uerror = ENOENT;
342 }
343
344 /*
345 * in a similar way to the upper layer, do the lookup
346 * in the lower layer. this time, if there is some
347 * component magic going on, then vput whatever we got
348 * back from the upper layer and return the lower vnode
349 * instead.
350 */
351 if (lowerdvp != NULLVP && !iswhiteout) {
352 int nameiop;
353
354 vn_lock(lowerdvp, LK_EXCLUSIVE | LK_RETRY);
355
356 /*
357 * Only do a LOOKUP on the bottom node, since
358 * we won't be making changes to it anyway.
359 */
360 nameiop = cnp->cn_nameiop;
361 cnp->cn_nameiop = LOOKUP;
362 if (um->um_op == UNMNT_BELOW) {
363 saved_cred = cnp->cn_cred;
364 cnp->cn_cred = um->um_cred;
365 }
366
367 /*
368 * we shouldn't have to worry about locking interactions
369 * between the lower layer and our union layer (w.r.t.
370 * `..' processing) because we don't futz with lowervp
371 * locks in the union-node instantiation code path.
372 */
373 lerror = union_lookup1(um->um_lowervp, &lowerdvp,
374 &lowervp, cnp);
375 if (um->um_op == UNMNT_BELOW)
376 cnp->cn_cred = saved_cred;
377 cnp->cn_nameiop = nameiop;
378
379 if (lowervp != lowerdvp)
380 VOP_UNLOCK(lowerdvp);
381
382 if (cnp->cn_consume != 0) {
383 if (uppervp != NULLVP) {
384 if (uppervp == upperdvp)
385 vrele(uppervp);
386 else
387 vput(uppervp);
388 uppervp = NULLVP;
389 }
390 *ap->a_vpp = lowervp;
391 return (lerror);
392 }
393 } else {
394 lerror = ENOENT;
395 if ((cnp->cn_flags & ISDOTDOT) && dun->un_pvp != NULLVP) {
396 lowervp = LOWERVP(dun->un_pvp);
397 if (lowervp != NULLVP) {
398 vref(lowervp);
399 vn_lock(lowervp, LK_EXCLUSIVE | LK_RETRY);
400 lerror = 0;
401 }
402 }
403 }
404
405 /*
406 * EJUSTRETURN is used by underlying filesystems to indicate that
407 * a directory modification op was started successfully.
408 * This will only happen in the upper layer, since
409 * the lower layer only does LOOKUPs.
410 * If this union is mounted read-only, bounce it now.
411 */
412
413 if ((uerror == EJUSTRETURN) && (cnp->cn_flags & ISLASTCN) &&
414 (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
415 ((cnp->cn_nameiop == CREATE) || (cnp->cn_nameiop == RENAME)))
416 uerror = EROFS;
417
418 /*
419 * at this point, we have uerror and lerror indicating
420 * possible errors with the lookups in the upper and lower
421 * layers. additionally, uppervp and lowervp are (locked)
422 * references to existing vnodes in the upper and lower layers.
423 *
424 * there are now three cases to consider.
425 * 1. if both layers returned an error, then return whatever
426 * error the upper layer generated.
427 *
428 * 2. if the top layer failed and the bottom layer succeeded
429 * then two subcases occur.
430 * a. the bottom vnode is not a directory, in which
431 * case just return a new union vnode referencing
432 * an empty top layer and the existing bottom layer.
433 * b. the bottom vnode is a directory, in which case
434 * create a new directory in the top-level and
435 * continue as in case 3.
436 *
437 * 3. if the top layer succeeded then return a new union
438 * vnode referencing whatever the new top layer and
439 * whatever the bottom layer returned.
440 */
441
442 *ap->a_vpp = NULLVP;
443
444
445 /* case 1. */
446 if ((uerror != 0) && (lerror != 0)) {
447 return (uerror);
448 }
449
450 /* case 2. */
451 if (uerror != 0 /* && (lerror == 0) */ ) {
452 if (lowervp->v_type == VDIR) { /* case 2b. */
453 /*
454 * We may be racing another process to make the
455 * upper-level shadow directory. Be careful with
456 * locks/etc!
457 * If we have to create a shadow directory and want
458 * to commit the node we have to restart the lookup
459 * to get the componentname right.
460 */
461 if (upperdvp) {
462 VOP_UNLOCK(upperdvp);
463 uerror = union_mkshadow(um, upperdvp, cnp,
464 &uppervp);
465 vn_lock(upperdvp, LK_EXCLUSIVE | LK_RETRY);
466 if (uerror == 0 && cnp->cn_nameiop != LOOKUP) {
467 vrele(uppervp);
468 if (lowervp != NULLVP)
469 vput(lowervp);
470 goto start;
471 }
472 }
473 if (uerror) {
474 if (lowervp != NULLVP) {
475 vput(lowervp);
476 lowervp = NULLVP;
477 }
478 return (uerror);
479 }
480 }
481 } else { /* uerror == 0 */
482 if (uppervp != upperdvp)
483 VOP_UNLOCK(uppervp);
484 }
485
486 if (lowervp != NULLVP)
487 VOP_UNLOCK(lowervp);
488
489 error = union_allocvp(ap->a_vpp, dvp->v_mount, dvp, upperdvp, cnp,
490 uppervp, lowervp, 1);
491
492 if (error) {
493 if (uppervp != NULLVP)
494 vrele(uppervp);
495 if (lowervp != NULLVP)
496 vrele(lowervp);
497 return error;
498 }
499
500 return 0;
501 }
502
503 int
504 union_create(void *v)
505 {
506 struct vop_create_v3_args /* {
507 struct vnode *a_dvp;
508 struct vnode **a_vpp;
509 struct componentname *a_cnp;
510 struct vattr *a_vap;
511 } */ *ap = v;
512 struct union_node *un = VTOUNION(ap->a_dvp);
513 struct vnode *dvp = un->un_uppervp;
514 struct componentname *cnp = ap->a_cnp;
515
516 if (dvp != NULLVP) {
517 int error;
518 struct vnode *vp;
519 struct mount *mp;
520
521 mp = ap->a_dvp->v_mount;
522
523 vp = NULL;
524 error = VOP_CREATE(dvp, &vp, cnp, ap->a_vap);
525 if (error)
526 return (error);
527
528 error = union_allocvp(ap->a_vpp, mp, NULLVP, NULLVP, cnp, vp,
529 NULLVP, 1);
530 if (error)
531 vrele(vp);
532 return (error);
533 }
534
535 return (EROFS);
536 }
537
538 int
539 union_whiteout(void *v)
540 {
541 struct vop_whiteout_args /* {
542 struct vnode *a_dvp;
543 struct componentname *a_cnp;
544 int a_flags;
545 } */ *ap = v;
546 struct union_node *un = VTOUNION(ap->a_dvp);
547 struct componentname *cnp = ap->a_cnp;
548
549 if (un->un_uppervp == NULLVP)
550 return (EOPNOTSUPP);
551
552 return (VOP_WHITEOUT(un->un_uppervp, cnp, ap->a_flags));
553 }
554
555 int
556 union_mknod(void *v)
557 {
558 struct vop_mknod_v3_args /* {
559 struct vnode *a_dvp;
560 struct vnode **a_vpp;
561 struct componentname *a_cnp;
562 struct vattr *a_vap;
563 } */ *ap = v;
564 struct union_node *un = VTOUNION(ap->a_dvp);
565 struct vnode *dvp = un->un_uppervp;
566 struct componentname *cnp = ap->a_cnp;
567
568 if (dvp != NULLVP) {
569 int error;
570 struct vnode *vp;
571 struct mount *mp;
572
573 mp = ap->a_dvp->v_mount;
574 error = VOP_MKNOD(dvp, &vp, cnp, ap->a_vap);
575 if (error)
576 return (error);
577
578 error = union_allocvp(ap->a_vpp, mp, NULLVP, NULLVP,
579 cnp, vp, NULLVP, 1);
580 if (error)
581 vrele(vp);
582 return (error);
583 }
584
585 return (EROFS);
586 }
587
588 int
589 union_open(void *v)
590 {
591 struct vop_open_args /* {
592 struct vnodeop_desc *a_desc;
593 struct vnode *a_vp;
594 int a_mode;
595 kauth_cred_t a_cred;
596 } */ *ap = v;
597 struct union_node *un = VTOUNION(ap->a_vp);
598 struct vnode *tvp;
599 int mode = ap->a_mode;
600 kauth_cred_t cred = ap->a_cred;
601 struct lwp *l = curlwp;
602 int error;
603
604 /*
605 * If there is an existing upper vp then simply open that.
606 */
607 tvp = un->un_uppervp;
608 if (tvp == NULLVP) {
609 /*
610 * If the lower vnode is being opened for writing, then
611 * copy the file contents to the upper vnode and open that,
612 * otherwise can simply open the lower vnode.
613 */
614 tvp = un->un_lowervp;
615 if ((ap->a_mode & FWRITE) && (tvp->v_type == VREG)) {
616 error = union_copyup(un, (mode&O_TRUNC) == 0, cred, l);
617 if (error == 0)
618 error = VOP_OPEN(un->un_uppervp, mode, cred);
619 if (error == 0) {
620 mutex_enter(un->un_uppervp->v_interlock);
621 un->un_uppervp->v_writecount++;
622 mutex_exit(un->un_uppervp->v_interlock);
623 }
624 return (error);
625 }
626
627 /*
628 * Just open the lower vnode, but check for nodev mount flag
629 */
630 if ((tvp->v_type == VBLK || tvp->v_type == VCHR) &&
631 (ap->a_vp->v_mount->mnt_flag & MNT_NODEV))
632 return ENXIO;
633 un->un_openl++;
634 vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY);
635 error = VOP_OPEN(tvp, mode, cred);
636 VOP_UNLOCK(tvp);
637
638 return (error);
639 }
640 /*
641 * Just open the upper vnode, checking for nodev mount flag first
642 */
643 if ((tvp->v_type == VBLK || tvp->v_type == VCHR) &&
644 (ap->a_vp->v_mount->mnt_flag & MNT_NODEV))
645 return ENXIO;
646
647 error = VOP_OPEN(tvp, mode, cred);
648 if (error == 0 && (ap->a_mode & FWRITE)) {
649 mutex_enter(tvp->v_interlock);
650 tvp->v_writecount++;
651 mutex_exit(tvp->v_interlock);
652 }
653
654 return (error);
655 }
656
657 int
658 union_close(void *v)
659 {
660 struct vop_close_args /* {
661 struct vnode *a_vp;
662 int a_fflag;
663 kauth_cred_t a_cred;
664 } */ *ap = v;
665 struct union_node *un = VTOUNION(ap->a_vp);
666 struct vnode *vp;
667 int error;
668 bool do_lock;
669
670 vp = un->un_uppervp;
671 if (vp != NULLVP) {
672 do_lock = false;
673 } else {
674 KASSERT(un->un_openl > 0);
675 --un->un_openl;
676 vp = un->un_lowervp;
677 do_lock = true;
678 }
679
680 KASSERT(vp != NULLVP);
681 ap->a_vp = vp;
682 if ((ap->a_fflag & FWRITE)) {
683 KASSERT(vp == un->un_uppervp);
684 mutex_enter(vp->v_interlock);
685 vp->v_writecount--;
686 mutex_exit(vp->v_interlock);
687 }
688 if (do_lock)
689 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
690 error = VCALL(vp, VOFFSET(vop_close), ap);
691 if (do_lock)
692 VOP_UNLOCK(vp);
693
694 return error;
695 }
696
697 /*
698 * Check access permission on the union vnode.
699 * The access check being enforced is to check
700 * against both the underlying vnode, and any
701 * copied vnode. This ensures that no additional
702 * file permissions are given away simply because
703 * the user caused an implicit file copy.
704 */
705 int
706 union_access(void *v)
707 {
708 struct vop_access_args /* {
709 struct vnodeop_desc *a_desc;
710 struct vnode *a_vp;
711 int a_mode;
712 kauth_cred_t a_cred;
713 } */ *ap = v;
714 struct vnode *vp = ap->a_vp;
715 struct union_node *un = VTOUNION(vp);
716 int error = EACCES;
717 struct union_mount *um = MOUNTTOUNIONMOUNT(vp->v_mount);
718
719 /*
720 * Disallow write attempts on read-only file systems;
721 * unless the file is a socket, fifo, or a block or
722 * character device resident on the file system.
723 */
724 if (ap->a_mode & VWRITE) {
725 switch (vp->v_type) {
726 case VDIR:
727 case VLNK:
728 case VREG:
729 if (vp->v_mount->mnt_flag & MNT_RDONLY)
730 return (EROFS);
731 break;
732 case VBAD:
733 case VBLK:
734 case VCHR:
735 case VSOCK:
736 case VFIFO:
737 case VNON:
738 default:
739 break;
740 }
741 }
742
743
744 if ((vp = un->un_uppervp) != NULLVP) {
745 ap->a_vp = vp;
746 return (VCALL(vp, VOFFSET(vop_access), ap));
747 }
748
749 if ((vp = un->un_lowervp) != NULLVP) {
750 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
751 ap->a_vp = vp;
752 error = VCALL(vp, VOFFSET(vop_access), ap);
753 if (error == 0) {
754 if (um->um_op == UNMNT_BELOW) {
755 ap->a_cred = um->um_cred;
756 error = VCALL(vp, VOFFSET(vop_access), ap);
757 }
758 }
759 VOP_UNLOCK(vp);
760 if (error)
761 return (error);
762 }
763
764 return (error);
765 }
766
767 /*
768 * We handle getattr only to change the fsid and
769 * track object sizes
770 */
771 int
772 union_getattr(void *v)
773 {
774 struct vop_getattr_args /* {
775 struct vnode *a_vp;
776 struct vattr *a_vap;
777 kauth_cred_t a_cred;
778 } */ *ap = v;
779 int error;
780 struct union_node *un = VTOUNION(ap->a_vp);
781 struct vnode *vp = un->un_uppervp;
782 struct vattr *vap;
783 struct vattr va;
784
785
786 /*
787 * Some programs walk the filesystem hierarchy by counting
788 * links to directories to avoid stat'ing all the time.
789 * This means the link count on directories needs to be "correct".
790 * The only way to do that is to call getattr on both layers
791 * and fix up the link count. The link count will not necessarily
792 * be accurate but will be large enough to defeat the tree walkers.
793 *
794 * To make life more interesting, some filesystems don't keep
795 * track of link counts in the expected way, and return a
796 * link count of `1' for those directories; if either of the
797 * component directories returns a link count of `1', we return a 1.
798 */
799
800 vap = ap->a_vap;
801
802 vp = un->un_uppervp;
803 if (vp != NULLVP) {
804 error = VOP_GETATTR(vp, vap, ap->a_cred);
805 if (error)
806 return (error);
807 mutex_enter(&un->un_lock);
808 union_newsize(ap->a_vp, vap->va_size, VNOVAL);
809 }
810
811 if (vp == NULLVP) {
812 vp = un->un_lowervp;
813 } else if (vp->v_type == VDIR) {
814 vp = un->un_lowervp;
815 if (vp != NULLVP)
816 vap = &va;
817 } else {
818 vp = NULLVP;
819 }
820
821 if (vp != NULLVP) {
822 if (vp == un->un_lowervp)
823 vn_lock(vp, LK_SHARED | LK_RETRY);
824 error = VOP_GETATTR(vp, vap, ap->a_cred);
825 if (vp == un->un_lowervp)
826 VOP_UNLOCK(vp);
827 if (error)
828 return (error);
829 mutex_enter(&un->un_lock);
830 union_newsize(ap->a_vp, VNOVAL, vap->va_size);
831 }
832
833 if ((vap != ap->a_vap) && (vap->va_type == VDIR)) {
834 /*
835 * Link count manipulation:
836 * - If both return "2", return 2 (no subdirs)
837 * - If one or the other return "1", return "1" (ENOCLUE)
838 */
839 if ((ap->a_vap->va_nlink == 2) &&
840 (vap->va_nlink == 2))
841 ;
842 else if (ap->a_vap->va_nlink != 1) {
843 if (vap->va_nlink == 1)
844 ap->a_vap->va_nlink = 1;
845 else
846 ap->a_vap->va_nlink += vap->va_nlink;
847 }
848 }
849 ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsidx.__fsid_val[0];
850 return (0);
851 }
852
853 int
854 union_setattr(void *v)
855 {
856 struct vop_setattr_args /* {
857 struct vnode *a_vp;
858 struct vattr *a_vap;
859 kauth_cred_t a_cred;
860 } */ *ap = v;
861 struct vattr *vap = ap->a_vap;
862 struct vnode *vp = ap->a_vp;
863 struct union_node *un = VTOUNION(vp);
864 bool size_only; /* All but va_size are VNOVAL. */
865 int error;
866
867 size_only = (vap->va_flags == VNOVAL && vap->va_uid == (uid_t)VNOVAL &&
868 vap->va_gid == (gid_t)VNOVAL && vap->va_atime.tv_sec == VNOVAL &&
869 vap->va_mtime.tv_sec == VNOVAL && vap->va_mode == (mode_t)VNOVAL);
870
871 if (!size_only && (vp->v_mount->mnt_flag & MNT_RDONLY))
872 return (EROFS);
873 if (vap->va_size != VNOVAL) {
874 switch (vp->v_type) {
875 case VDIR:
876 return (EISDIR);
877 case VCHR:
878 case VBLK:
879 case VSOCK:
880 case VFIFO:
881 break;
882 case VREG:
883 case VLNK:
884 default:
885 /*
886 * Disallow write attempts if the filesystem is
887 * mounted read-only.
888 */
889 if (vp->v_mount->mnt_flag & MNT_RDONLY)
890 return (EROFS);
891 }
892 }
893
894 /*
895 * Handle case of truncating lower object to zero size,
896 * by creating a zero length upper object. This is to
897 * handle the case of open with O_TRUNC and O_CREAT.
898 */
899 if ((un->un_uppervp == NULLVP) &&
900 /* assert(un->un_lowervp != NULLVP) */
901 (un->un_lowervp->v_type == VREG)) {
902 error = union_copyup(un, (vap->va_size != 0),
903 ap->a_cred, curlwp);
904 if (error)
905 return (error);
906 }
907
908 /*
909 * Try to set attributes in upper layer, ignore size change to zero
910 * for devices to handle O_TRUNC and return read-only filesystem error
911 * otherwise.
912 */
913 if (un->un_uppervp != NULLVP) {
914 error = VOP_SETATTR(un->un_uppervp, vap, ap->a_cred);
915 if ((error == 0) && (vap->va_size != VNOVAL)) {
916 mutex_enter(&un->un_lock);
917 union_newsize(ap->a_vp, vap->va_size, VNOVAL);
918 }
919 } else {
920 KASSERT(un->un_lowervp != NULLVP);
921 if (NODE_IS_SPECIAL(un->un_lowervp)) {
922 if (size_only &&
923 (vap->va_size == 0 || vap->va_size == VNOVAL))
924 error = 0;
925 else
926 error = EROFS;
927 } else {
928 error = EROFS;
929 }
930 }
931
932 return (error);
933 }
934
935 int
936 union_read(void *v)
937 {
938 struct vop_read_args /* {
939 struct vnode *a_vp;
940 struct uio *a_uio;
941 int a_ioflag;
942 kauth_cred_t a_cred;
943 } */ *ap = v;
944 int error;
945 struct vnode *vp = OTHERVP(ap->a_vp);
946 int dolock = (vp == LOWERVP(ap->a_vp));
947
948 if (dolock)
949 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
950 error = VOP_READ(vp, ap->a_uio, ap->a_ioflag, ap->a_cred);
951 if (dolock)
952 VOP_UNLOCK(vp);
953
954 /*
955 * XXX
956 * perhaps the size of the underlying object has changed under
957 * our feet. take advantage of the offset information present
958 * in the uio structure.
959 */
960 if (error == 0) {
961 struct union_node *un = VTOUNION(ap->a_vp);
962 off_t cur = ap->a_uio->uio_offset;
963 off_t usz = VNOVAL, lsz = VNOVAL;
964
965 mutex_enter(&un->un_lock);
966 if (vp == un->un_uppervp) {
967 if (cur > un->un_uppersz)
968 usz = cur;
969 } else {
970 if (cur > un->un_lowersz)
971 lsz = cur;
972 }
973
974 if (usz != VNOVAL || lsz != VNOVAL)
975 union_newsize(ap->a_vp, usz, lsz);
976 else
977 mutex_exit(&un->un_lock);
978 }
979
980 return (error);
981 }
982
983 int
984 union_write(void *v)
985 {
986 struct vop_read_args /* {
987 struct vnode *a_vp;
988 struct uio *a_uio;
989 int a_ioflag;
990 kauth_cred_t a_cred;
991 } */ *ap = v;
992 int error;
993 struct vnode *vp;
994 struct union_node *un = VTOUNION(ap->a_vp);
995
996 vp = UPPERVP(ap->a_vp);
997 if (vp == NULLVP) {
998 vp = LOWERVP(ap->a_vp);
999 if (NODE_IS_SPECIAL(vp)) {
1000 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1001 error = VOP_WRITE(vp, ap->a_uio, ap->a_ioflag,
1002 ap->a_cred);
1003 VOP_UNLOCK(vp);
1004 return error;
1005 }
1006 panic("union: missing upper layer in write");
1007 }
1008
1009 error = VOP_WRITE(vp, ap->a_uio, ap->a_ioflag, ap->a_cred);
1010
1011 /*
1012 * the size of the underlying object may be changed by the
1013 * write.
1014 */
1015 if (error == 0) {
1016 off_t cur = ap->a_uio->uio_offset;
1017
1018 mutex_enter(&un->un_lock);
1019 if (cur > un->un_uppersz)
1020 union_newsize(ap->a_vp, cur, VNOVAL);
1021 else
1022 mutex_exit(&un->un_lock);
1023 }
1024
1025 return (error);
1026 }
1027
1028 int
1029 union_ioctl(void *v)
1030 {
1031 struct vop_ioctl_args /* {
1032 struct vnode *a_vp;
1033 int a_command;
1034 void *a_data;
1035 int a_fflag;
1036 kauth_cred_t a_cred;
1037 } */ *ap = v;
1038 struct vnode *ovp = OTHERVP(ap->a_vp);
1039
1040 ap->a_vp = ovp;
1041 return (VCALL(ovp, VOFFSET(vop_ioctl), ap));
1042 }
1043
1044 int
1045 union_poll(void *v)
1046 {
1047 struct vop_poll_args /* {
1048 struct vnode *a_vp;
1049 int a_events;
1050 } */ *ap = v;
1051 struct vnode *ovp = OTHERVP(ap->a_vp);
1052
1053 ap->a_vp = ovp;
1054 return (VCALL(ovp, VOFFSET(vop_poll), ap));
1055 }
1056
1057 int
1058 union_revoke(void *v)
1059 {
1060 struct vop_revoke_args /* {
1061 struct vnode *a_vp;
1062 int a_flags;
1063 struct proc *a_p;
1064 } */ *ap = v;
1065 struct vnode *vp = ap->a_vp;
1066
1067 if (UPPERVP(vp)) {
1068 mutex_enter(UPPERVP(vp)->v_interlock);
1069 KASSERT(vp->v_interlock == UPPERVP(vp)->v_interlock);
1070 UPPERVP(vp)->v_writecount -= vp->v_writecount;
1071 mutex_exit(UPPERVP(vp)->v_interlock);
1072 VOP_REVOKE(UPPERVP(vp), ap->a_flags);
1073 }
1074 if (LOWERVP(vp))
1075 VOP_REVOKE(LOWERVP(vp), ap->a_flags);
1076 vgone(vp); /* XXXAD?? */
1077 return (0);
1078 }
1079
1080 int
1081 union_mmap(void *v)
1082 {
1083 struct vop_mmap_args /* {
1084 struct vnode *a_vp;
1085 vm_prot_t a_prot;
1086 kauth_cred_t a_cred;
1087 } */ *ap = v;
1088 struct vnode *ovp = OTHERVP(ap->a_vp);
1089
1090 ap->a_vp = ovp;
1091 return (VCALL(ovp, VOFFSET(vop_mmap), ap));
1092 }
1093
1094 int
1095 union_fsync(void *v)
1096 {
1097 struct vop_fsync_args /* {
1098 struct vnode *a_vp;
1099 kauth_cred_t a_cred;
1100 int a_flags;
1101 off_t offhi;
1102 off_t offlo;
1103 } */ *ap = v;
1104 int error = 0;
1105 struct vnode *targetvp;
1106
1107 /*
1108 * If vinvalbuf is calling us, it's a "shallow fsync" -- don't
1109 * bother syncing the underlying vnodes, since (a) they'll be
1110 * fsync'ed when reclaimed and (b) we could deadlock if
1111 * they're locked; otherwise, pass it through to the
1112 * underlying layer.
1113 */
1114 if (ap->a_vp->v_type == VBLK || ap->a_vp->v_type == VCHR) {
1115 error = spec_fsync(v);
1116 if (error)
1117 return error;
1118 }
1119
1120 if (ap->a_flags & FSYNC_RECLAIM)
1121 return 0;
1122
1123 targetvp = OTHERVP(ap->a_vp);
1124 if (targetvp != NULLVP) {
1125 int dolock = (targetvp == LOWERVP(ap->a_vp));
1126
1127 if (dolock)
1128 vn_lock(targetvp, LK_EXCLUSIVE | LK_RETRY);
1129 error = VOP_FSYNC(targetvp, ap->a_cred, ap->a_flags,
1130 ap->a_offlo, ap->a_offhi);
1131 if (dolock)
1132 VOP_UNLOCK(targetvp);
1133 }
1134
1135 return (error);
1136 }
1137
1138 int
1139 union_seek(void *v)
1140 {
1141 struct vop_seek_args /* {
1142 struct vnode *a_vp;
1143 off_t a_oldoff;
1144 off_t a_newoff;
1145 kauth_cred_t a_cred;
1146 } */ *ap = v;
1147 struct vnode *ovp = OTHERVP(ap->a_vp);
1148
1149 ap->a_vp = ovp;
1150 return (VCALL(ovp, VOFFSET(vop_seek), ap));
1151 }
1152
1153 int
1154 union_remove(void *v)
1155 {
1156 struct vop_remove_args /* {
1157 struct vnode *a_dvp;
1158 struct vnode *a_vp;
1159 struct componentname *a_cnp;
1160 } */ *ap = v;
1161 int error;
1162 struct union_node *dun = VTOUNION(ap->a_dvp);
1163 struct union_node *un = VTOUNION(ap->a_vp);
1164 struct componentname *cnp = ap->a_cnp;
1165
1166 if (dun->un_uppervp == NULLVP)
1167 panic("union remove: null upper vnode");
1168
1169 if (un->un_uppervp != NULLVP) {
1170 struct vnode *dvp = dun->un_uppervp;
1171 struct vnode *vp = un->un_uppervp;
1172
1173 /*
1174 * Account for VOP_REMOVE to vrele dvp and vp.
1175 * Note: VOP_REMOVE will unlock dvp and vp.
1176 */
1177 vref(dvp);
1178 vref(vp);
1179 if (union_dowhiteout(un, cnp->cn_cred))
1180 cnp->cn_flags |= DOWHITEOUT;
1181 error = VOP_REMOVE(dvp, vp, cnp);
1182 if (!error)
1183 union_removed_upper(un);
1184 vrele(ap->a_dvp);
1185 vrele(ap->a_vp);
1186 } else {
1187 error = union_mkwhiteout(
1188 MOUNTTOUNIONMOUNT(UNIONTOV(dun)->v_mount),
1189 dun->un_uppervp, ap->a_cnp, un);
1190 vput(ap->a_dvp);
1191 vput(ap->a_vp);
1192 }
1193
1194 return (error);
1195 }
1196
1197 int
1198 union_link(void *v)
1199 {
1200 struct vop_link_v2_args /* {
1201 struct vnode *a_dvp;
1202 struct vnode *a_vp;
1203 struct componentname *a_cnp;
1204 } */ *ap = v;
1205 int error = 0;
1206 struct componentname *cnp = ap->a_cnp;
1207 struct union_node *dun;
1208 struct vnode *vp;
1209 struct vnode *dvp;
1210
1211 dun = VTOUNION(ap->a_dvp);
1212
1213 KASSERT((ap->a_cnp->cn_flags & LOCKPARENT) != 0);
1214
1215 if (ap->a_dvp->v_op != ap->a_vp->v_op) {
1216 vp = ap->a_vp;
1217 } else {
1218 struct union_node *un = VTOUNION(ap->a_vp);
1219 if (un->un_uppervp == NULLVP) {
1220 const bool droplock = (dun->un_uppervp == un->un_dirvp);
1221
1222 /*
1223 * Needs to be copied before we can link it.
1224 */
1225 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY);
1226 if (droplock)
1227 VOP_UNLOCK(dun->un_uppervp);
1228 error = union_copyup(un, 1, cnp->cn_cred, curlwp);
1229 if (droplock) {
1230 vn_lock(dun->un_uppervp,
1231 LK_EXCLUSIVE | LK_RETRY);
1232 /*
1233 * During copyup, we dropped the lock on the
1234 * dir and invalidated any saved namei lookup
1235 * state for the directory we'll be entering
1236 * the link in. We need to re-run the lookup
1237 * in that directory to reset any state needed
1238 * for VOP_LINK.
1239 * Call relookup on the union-layer to reset
1240 * the state.
1241 */
1242 vp = NULLVP;
1243 if (dun->un_uppervp == NULLVP)
1244 panic("union: null upperdvp?");
1245 error = relookup(ap->a_dvp, &vp, ap->a_cnp, 0);
1246 if (error) {
1247 VOP_UNLOCK(ap->a_vp);
1248 return EROFS; /* ? */
1249 }
1250 if (vp != NULLVP) {
1251 /*
1252 * The name we want to create has
1253 * mysteriously appeared (a race?)
1254 */
1255 error = EEXIST;
1256 VOP_UNLOCK(ap->a_vp);
1257 vput(vp);
1258 return (error);
1259 }
1260 }
1261 VOP_UNLOCK(ap->a_vp);
1262 }
1263 vp = un->un_uppervp;
1264 }
1265
1266 dvp = dun->un_uppervp;
1267 if (dvp == NULLVP)
1268 error = EROFS;
1269
1270 if (error)
1271 return (error);
1272
1273 return VOP_LINK(dvp, vp, cnp);
1274 }
1275
1276 int
1277 union_rename(void *v)
1278 {
1279 struct vop_rename_args /* {
1280 struct vnode *a_fdvp;
1281 struct vnode *a_fvp;
1282 struct componentname *a_fcnp;
1283 struct vnode *a_tdvp;
1284 struct vnode *a_tvp;
1285 struct componentname *a_tcnp;
1286 } */ *ap = v;
1287 int error;
1288
1289 struct vnode *fdvp = ap->a_fdvp;
1290 struct vnode *fvp = ap->a_fvp;
1291 struct vnode *tdvp = ap->a_tdvp;
1292 struct vnode *tvp = ap->a_tvp;
1293
1294 /*
1295 * Account for VOP_RENAME to vrele all nodes.
1296 * Note: VOP_RENAME will unlock tdvp.
1297 */
1298
1299 if (fdvp->v_op == union_vnodeop_p) { /* always true */
1300 struct union_node *un = VTOUNION(fdvp);
1301 if (un->un_uppervp == NULLVP) {
1302 /*
1303 * this should never happen in normal
1304 * operation but might if there was
1305 * a problem creating the top-level shadow
1306 * directory.
1307 */
1308 error = EXDEV;
1309 goto bad;
1310 }
1311
1312 fdvp = un->un_uppervp;
1313 vref(fdvp);
1314 }
1315
1316 if (fvp->v_op == union_vnodeop_p) { /* always true */
1317 struct union_node *un = VTOUNION(fvp);
1318 if (un->un_uppervp == NULLVP) {
1319 /* XXX: should do a copyup */
1320 error = EXDEV;
1321 goto bad;
1322 }
1323
1324 if (un->un_lowervp != NULLVP)
1325 ap->a_fcnp->cn_flags |= DOWHITEOUT;
1326
1327 fvp = un->un_uppervp;
1328 vref(fvp);
1329 }
1330
1331 if (tdvp->v_op == union_vnodeop_p) {
1332 struct union_node *un = VTOUNION(tdvp);
1333 if (un->un_uppervp == NULLVP) {
1334 /*
1335 * this should never happen in normal
1336 * operation but might if there was
1337 * a problem creating the top-level shadow
1338 * directory.
1339 */
1340 error = EXDEV;
1341 goto bad;
1342 }
1343
1344 tdvp = un->un_uppervp;
1345 vref(tdvp);
1346 }
1347
1348 if (tvp != NULLVP && tvp->v_op == union_vnodeop_p) {
1349 struct union_node *un = VTOUNION(tvp);
1350
1351 tvp = un->un_uppervp;
1352 if (tvp != NULLVP) {
1353 vref(tvp);
1354 }
1355 }
1356
1357 error = VOP_RENAME(fdvp, fvp, ap->a_fcnp, tdvp, tvp, ap->a_tcnp);
1358 goto out;
1359
1360 bad:
1361 vput(tdvp);
1362 if (tvp != NULLVP)
1363 vput(tvp);
1364 vrele(fdvp);
1365 vrele(fvp);
1366
1367 out:
1368 if (fdvp != ap->a_fdvp) {
1369 vrele(ap->a_fdvp);
1370 }
1371 if (fvp != ap->a_fvp) {
1372 vrele(ap->a_fvp);
1373 }
1374 if (tdvp != ap->a_tdvp) {
1375 vrele(ap->a_tdvp);
1376 }
1377 if (tvp != ap->a_tvp) {
1378 vrele(ap->a_tvp);
1379 }
1380 return (error);
1381 }
1382
1383 int
1384 union_mkdir(void *v)
1385 {
1386 struct vop_mkdir_v3_args /* {
1387 struct vnode *a_dvp;
1388 struct vnode **a_vpp;
1389 struct componentname *a_cnp;
1390 struct vattr *a_vap;
1391 } */ *ap = v;
1392 struct union_node *un = VTOUNION(ap->a_dvp);
1393 struct vnode *dvp = un->un_uppervp;
1394 struct componentname *cnp = ap->a_cnp;
1395
1396 if (dvp != NULLVP) {
1397 int error;
1398 struct vnode *vp;
1399
1400 vp = NULL;
1401 error = VOP_MKDIR(dvp, &vp, cnp, ap->a_vap);
1402 if (error) {
1403 vrele(ap->a_dvp);
1404 return (error);
1405 }
1406
1407 error = union_allocvp(ap->a_vpp, ap->a_dvp->v_mount, ap->a_dvp,
1408 NULLVP, cnp, vp, NULLVP, 1);
1409 if (error)
1410 vrele(vp);
1411 return (error);
1412 }
1413
1414 return (EROFS);
1415 }
1416
1417 int
1418 union_rmdir(void *v)
1419 {
1420 struct vop_rmdir_args /* {
1421 struct vnode *a_dvp;
1422 struct vnode *a_vp;
1423 struct componentname *a_cnp;
1424 } */ *ap = v;
1425 int error;
1426 struct union_node *dun = VTOUNION(ap->a_dvp);
1427 struct union_node *un = VTOUNION(ap->a_vp);
1428 struct componentname *cnp = ap->a_cnp;
1429
1430 if (dun->un_uppervp == NULLVP)
1431 panic("union rmdir: null upper vnode");
1432
1433 error = union_check_rmdir(un, cnp->cn_cred);
1434 if (error) {
1435 vput(ap->a_dvp);
1436 vput(ap->a_vp);
1437 return error;
1438 }
1439
1440 if (un->un_uppervp != NULLVP) {
1441 struct vnode *dvp = dun->un_uppervp;
1442 struct vnode *vp = un->un_uppervp;
1443
1444 /*
1445 * Account for VOP_RMDIR to vrele dvp and vp.
1446 * Note: VOP_RMDIR will unlock dvp and vp.
1447 */
1448 vref(dvp);
1449 vref(vp);
1450 if (union_dowhiteout(un, cnp->cn_cred))
1451 cnp->cn_flags |= DOWHITEOUT;
1452 error = VOP_RMDIR(dvp, vp, ap->a_cnp);
1453 if (!error)
1454 union_removed_upper(un);
1455 vrele(ap->a_dvp);
1456 vrele(ap->a_vp);
1457 } else {
1458 error = union_mkwhiteout(
1459 MOUNTTOUNIONMOUNT(UNIONTOV(dun)->v_mount),
1460 dun->un_uppervp, ap->a_cnp, un);
1461 vput(ap->a_dvp);
1462 vput(ap->a_vp);
1463 }
1464
1465 return (error);
1466 }
1467
1468 int
1469 union_symlink(void *v)
1470 {
1471 struct vop_symlink_v3_args /* {
1472 struct vnode *a_dvp;
1473 struct vnode **a_vpp;
1474 struct componentname *a_cnp;
1475 struct vattr *a_vap;
1476 char *a_target;
1477 } */ *ap = v;
1478 struct union_node *un = VTOUNION(ap->a_dvp);
1479 struct vnode *dvp = un->un_uppervp;
1480 struct componentname *cnp = ap->a_cnp;
1481
1482 if (dvp != NULLVP) {
1483 int error;
1484
1485 error = VOP_SYMLINK(dvp, ap->a_vpp, cnp, ap->a_vap,
1486 ap->a_target);
1487 return (error);
1488 }
1489
1490 return (EROFS);
1491 }
1492
1493 /*
1494 * union_readdir works in concert with getdirentries and
1495 * readdir(3) to provide a list of entries in the unioned
1496 * directories. getdirentries is responsible for walking
1497 * down the union stack. readdir(3) is responsible for
1498 * eliminating duplicate names from the returned data stream.
1499 */
1500 int
1501 union_readdir(void *v)
1502 {
1503 struct vop_readdir_args /* {
1504 struct vnodeop_desc *a_desc;
1505 struct vnode *a_vp;
1506 struct uio *a_uio;
1507 kauth_cred_t a_cred;
1508 int *a_eofflag;
1509 u_long *a_cookies;
1510 int a_ncookies;
1511 } */ *ap = v;
1512 struct union_node *un = VTOUNION(ap->a_vp);
1513 struct vnode *uvp = un->un_uppervp;
1514
1515 if (uvp == NULLVP)
1516 return (0);
1517
1518 ap->a_vp = uvp;
1519 return (VCALL(uvp, VOFFSET(vop_readdir), ap));
1520 }
1521
1522 int
1523 union_readlink(void *v)
1524 {
1525 struct vop_readlink_args /* {
1526 struct vnode *a_vp;
1527 struct uio *a_uio;
1528 kauth_cred_t a_cred;
1529 } */ *ap = v;
1530 int error;
1531 struct vnode *vp = OTHERVP(ap->a_vp);
1532 int dolock = (vp == LOWERVP(ap->a_vp));
1533
1534 if (dolock)
1535 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1536 ap->a_vp = vp;
1537 error = VCALL(vp, VOFFSET(vop_readlink), ap);
1538 if (dolock)
1539 VOP_UNLOCK(vp);
1540
1541 return (error);
1542 }
1543
1544 int
1545 union_abortop(void *v)
1546 {
1547 struct vop_abortop_args /* {
1548 struct vnode *a_dvp;
1549 struct componentname *a_cnp;
1550 } */ *ap = v;
1551
1552 KASSERT(UPPERVP(ap->a_dvp) != NULL);
1553
1554 ap->a_dvp = UPPERVP(ap->a_dvp);
1555 return VCALL(ap->a_dvp, VOFFSET(vop_abortop), ap);
1556 }
1557
1558 int
1559 union_inactive(void *v)
1560 {
1561 struct vop_inactive_v2_args /* {
1562 const struct vnodeop_desc *a_desc;
1563 struct vnode *a_vp;
1564 bool *a_recycle;
1565 } */ *ap = v;
1566 struct vnode *vp = ap->a_vp;
1567 struct union_node *un = VTOUNION(vp);
1568 struct vnode **vpp;
1569
1570 /*
1571 * Do nothing (and _don't_ bypass).
1572 * Wait to vrele lowervp until reclaim,
1573 * so that until then our union_node is in the
1574 * cache and reusable.
1575 *
1576 * NEEDSWORK: Someday, consider inactive'ing
1577 * the lowervp and then trying to reactivate it
1578 * with capabilities (v_id)
1579 * like they do in the name lookup cache code.
1580 * That's too much work for now.
1581 */
1582
1583 if (un->un_dircache != 0) {
1584 for (vpp = un->un_dircache; *vpp != NULLVP; vpp++)
1585 vrele(*vpp);
1586 free(un->un_dircache, M_TEMP);
1587 un->un_dircache = 0;
1588 }
1589
1590 *ap->a_recycle = ((un->un_cflags & UN_CACHED) == 0);
1591
1592 return (0);
1593 }
1594
1595 int
1596 union_reclaim(void *v)
1597 {
1598 struct vop_reclaim_args /* {
1599 struct vnode *a_vp;
1600 } */ *ap = v;
1601
1602 union_freevp(ap->a_vp);
1603
1604 return (0);
1605 }
1606
1607 static int
1608 union_lock1(struct vnode *vp, struct vnode *lockvp, int flags)
1609 {
1610 struct vop_lock_args ap;
1611
1612 if (lockvp == vp) {
1613 ap.a_vp = vp;
1614 ap.a_flags = flags;
1615 return genfs_lock(&ap);
1616 } else
1617 return VOP_LOCK(lockvp, flags);
1618 }
1619
1620 static int
1621 union_unlock1(struct vnode *vp, struct vnode *lockvp)
1622 {
1623 struct vop_unlock_args ap;
1624
1625 if (lockvp == vp) {
1626 ap.a_vp = vp;
1627 return genfs_unlock(&ap);
1628 } else
1629 return VOP_UNLOCK(lockvp);
1630 }
1631
1632 int
1633 union_lock(void *v)
1634 {
1635 struct vop_lock_args /* {
1636 struct vnode *a_vp;
1637 int a_flags;
1638 } */ *ap = v;
1639 struct vnode *vp = ap->a_vp, *lockvp;
1640 struct union_node *un = VTOUNION(vp);
1641 int flags = ap->a_flags;
1642 int error;
1643
1644 if ((flags & LK_NOWAIT) != 0) {
1645 if (!mutex_tryenter(&un->un_lock))
1646 return EBUSY;
1647 lockvp = LOCKVP(vp);
1648 error = union_lock1(vp, lockvp, flags);
1649 mutex_exit(&un->un_lock);
1650 if (error)
1651 return error;
1652 if (mutex_tryenter(vp->v_interlock)) {
1653 error = vdead_check(vp, VDEAD_NOWAIT);
1654 mutex_exit(vp->v_interlock);
1655 } else
1656 error = EBUSY;
1657 if (error)
1658 union_unlock1(vp, lockvp);
1659 return error;
1660 }
1661
1662 mutex_enter(&un->un_lock);
1663 for (;;) {
1664 lockvp = LOCKVP(vp);
1665 mutex_exit(&un->un_lock);
1666 error = union_lock1(vp, lockvp, flags);
1667 if (error != 0)
1668 return error;
1669 mutex_enter(&un->un_lock);
1670 if (lockvp == LOCKVP(vp))
1671 break;
1672 union_unlock1(vp, lockvp);
1673 }
1674 mutex_exit(&un->un_lock);
1675
1676 mutex_enter(vp->v_interlock);
1677 error = vdead_check(vp, VDEAD_NOWAIT);
1678 if (error) {
1679 union_unlock1(vp, lockvp);
1680 error = vdead_check(vp, 0);
1681 KASSERT(error == ENOENT);
1682 }
1683 mutex_exit(vp->v_interlock);
1684 return error;
1685 }
1686
1687 int
1688 union_unlock(void *v)
1689 {
1690 struct vop_unlock_args /* {
1691 struct vnode *a_vp;
1692 int a_flags;
1693 } */ *ap = v;
1694 struct vnode *vp = ap->a_vp, *lockvp;
1695
1696 lockvp = LOCKVP(vp);
1697 union_unlock1(vp, lockvp);
1698
1699 return 0;
1700 }
1701
1702 int
1703 union_bmap(void *v)
1704 {
1705 struct vop_bmap_args /* {
1706 struct vnode *a_vp;
1707 daddr_t a_bn;
1708 struct vnode **a_vpp;
1709 daddr_t *a_bnp;
1710 int *a_runp;
1711 } */ *ap = v;
1712 int error;
1713 struct vnode *vp = OTHERVP(ap->a_vp);
1714 int dolock = (vp == LOWERVP(ap->a_vp));
1715
1716 if (dolock)
1717 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1718 ap->a_vp = vp;
1719 error = VCALL(vp, VOFFSET(vop_bmap), ap);
1720 if (dolock)
1721 VOP_UNLOCK(vp);
1722
1723 return (error);
1724 }
1725
1726 int
1727 union_print(void *v)
1728 {
1729 struct vop_print_args /* {
1730 struct vnode *a_vp;
1731 } */ *ap = v;
1732 struct vnode *vp = ap->a_vp;
1733
1734 printf("\ttag VT_UNION, vp=%p, uppervp=%p, lowervp=%p\n",
1735 vp, UPPERVP(vp), LOWERVP(vp));
1736 if (UPPERVP(vp) != NULLVP)
1737 vprint("union: upper", UPPERVP(vp));
1738 if (LOWERVP(vp) != NULLVP)
1739 vprint("union: lower", LOWERVP(vp));
1740 if (VTOUNION(vp)->un_dircache) {
1741 struct vnode **vpp;
1742 for (vpp = VTOUNION(vp)->un_dircache; *vpp != NULLVP; vpp++)
1743 vprint("dircache:", *vpp);
1744 }
1745
1746 return (0);
1747 }
1748
1749 int
1750 union_islocked(void *v)
1751 {
1752 struct vop_islocked_args /* {
1753 struct vnode *a_vp;
1754 } */ *ap = v;
1755 struct vnode *vp;
1756 struct union_node *un;
1757
1758 un = VTOUNION(ap->a_vp);
1759 mutex_enter(&un->un_lock);
1760 vp = LOCKVP(ap->a_vp);
1761 mutex_exit(&un->un_lock);
1762
1763 if (vp == ap->a_vp)
1764 return genfs_islocked(ap);
1765 else
1766 return VOP_ISLOCKED(vp);
1767 }
1768
1769 int
1770 union_pathconf(void *v)
1771 {
1772 struct vop_pathconf_args /* {
1773 struct vnode *a_vp;
1774 int a_name;
1775 int *a_retval;
1776 } */ *ap = v;
1777 int error;
1778 struct vnode *vp = OTHERVP(ap->a_vp);
1779 int dolock = (vp == LOWERVP(ap->a_vp));
1780
1781 if (dolock)
1782 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1783 ap->a_vp = vp;
1784 error = VCALL(vp, VOFFSET(vop_pathconf), ap);
1785 if (dolock)
1786 VOP_UNLOCK(vp);
1787
1788 return (error);
1789 }
1790
1791 int
1792 union_advlock(void *v)
1793 {
1794 struct vop_advlock_args /* {
1795 struct vnode *a_vp;
1796 void *a_id;
1797 int a_op;
1798 struct flock *a_fl;
1799 int a_flags;
1800 } */ *ap = v;
1801 struct vnode *ovp = OTHERVP(ap->a_vp);
1802
1803 ap->a_vp = ovp;
1804 return (VCALL(ovp, VOFFSET(vop_advlock), ap));
1805 }
1806
1807 int
1808 union_strategy(void *v)
1809 {
1810 struct vop_strategy_args /* {
1811 struct vnode *a_vp;
1812 struct buf *a_bp;
1813 } */ *ap = v;
1814 struct vnode *ovp = OTHERVP(ap->a_vp);
1815 struct buf *bp = ap->a_bp;
1816
1817 KASSERT(ovp != NULLVP);
1818 if (!NODE_IS_SPECIAL(ovp))
1819 KASSERT((bp->b_flags & B_READ) || ovp != LOWERVP(bp->b_vp));
1820
1821 return (VOP_STRATEGY(ovp, bp));
1822 }
1823
1824 int
1825 union_bwrite(void *v)
1826 {
1827 struct vop_bwrite_args /* {
1828 struct vnode *a_vp;
1829 struct buf *a_bp;
1830 } */ *ap = v;
1831 struct vnode *ovp = OTHERVP(ap->a_vp);
1832 struct buf *bp = ap->a_bp;
1833
1834 KASSERT(ovp != NULLVP);
1835 if (!NODE_IS_SPECIAL(ovp))
1836 KASSERT((bp->b_flags & B_READ) || ovp != LOWERVP(bp->b_vp));
1837
1838 return (VOP_BWRITE(ovp, bp));
1839 }
1840
1841 int
1842 union_getpages(void *v)
1843 {
1844 struct vop_getpages_args /* {
1845 struct vnode *a_vp;
1846 voff_t a_offset;
1847 struct vm_page **a_m;
1848 int *a_count;
1849 int a_centeridx;
1850 vm_prot_t a_access_type;
1851 int a_advice;
1852 int a_flags;
1853 } */ *ap = v;
1854 struct vnode *vp = ap->a_vp;
1855
1856 KASSERT(mutex_owned(vp->v_interlock));
1857
1858 if (ap->a_flags & PGO_LOCKED) {
1859 return EBUSY;
1860 }
1861 ap->a_vp = OTHERVP(vp);
1862 KASSERT(vp->v_interlock == ap->a_vp->v_interlock);
1863
1864 /* Just pass the request on to the underlying layer. */
1865 return VCALL(ap->a_vp, VOFFSET(vop_getpages), ap);
1866 }
1867
1868 int
1869 union_putpages(void *v)
1870 {
1871 struct vop_putpages_args /* {
1872 struct vnode *a_vp;
1873 voff_t a_offlo;
1874 voff_t a_offhi;
1875 int a_flags;
1876 } */ *ap = v;
1877 struct vnode *vp = ap->a_vp;
1878
1879 KASSERT(mutex_owned(vp->v_interlock));
1880
1881 ap->a_vp = OTHERVP(vp);
1882 KASSERT(vp->v_interlock == ap->a_vp->v_interlock);
1883
1884 if (ap->a_flags & PGO_RECLAIM) {
1885 mutex_exit(vp->v_interlock);
1886 return 0;
1887 }
1888
1889 /* Just pass the request on to the underlying layer. */
1890 return VCALL(ap->a_vp, VOFFSET(vop_putpages), ap);
1891 }
1892
1893 int
1894 union_kqfilter(void *v)
1895 {
1896 struct vop_kqfilter_args /* {
1897 struct vnode *a_vp;
1898 struct knote *a_kn;
1899 } */ *ap = v;
1900 int error;
1901
1902 /*
1903 * We watch either the upper layer file (if it already exists),
1904 * or the lower layer one. If there is lower layer file only
1905 * at this moment, we will keep watching that lower layer file
1906 * even if upper layer file would be created later on.
1907 */
1908 if (UPPERVP(ap->a_vp))
1909 error = VOP_KQFILTER(UPPERVP(ap->a_vp), ap->a_kn);
1910 else if (LOWERVP(ap->a_vp))
1911 error = VOP_KQFILTER(LOWERVP(ap->a_vp), ap->a_kn);
1912 else {
1913 /* panic? */
1914 error = EOPNOTSUPP;
1915 }
1916
1917 return (error);
1918 }
1919