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