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