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