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