union_vnops.c revision 1.26 1 /* $NetBSD: union_vnops.c,v 1.26 2008/01/16 10:10:18 ad Exp $ */
2
3 /*
4 * Copyright (c) 1992, 1993, 1994, 1995
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Jan-Simon Pendry.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * @(#)union_vnops.c 8.33 (Berkeley) 7/31/95
35 */
36
37 /*
38 * Copyright (c) 1992, 1993, 1994, 1995 Jan-Simon Pendry.
39 *
40 * This code is derived from software contributed to Berkeley by
41 * Jan-Simon Pendry.
42 *
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
45 * are met:
46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution.
51 * 3. All advertising materials mentioning features or use of this software
52 * must display the following acknowledgement:
53 * This product includes software developed by the University of
54 * California, Berkeley and its contributors.
55 * 4. Neither the name of the University nor the names of its contributors
56 * may be used to endorse or promote products derived from this software
57 * without specific prior written permission.
58 *
59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 * SUCH DAMAGE.
70 *
71 * @(#)union_vnops.c 8.33 (Berkeley) 7/31/95
72 */
73
74 #include <sys/cdefs.h>
75 __KERNEL_RCSID(0, "$NetBSD: union_vnops.c,v 1.26 2008/01/16 10:10:18 ad Exp $");
76
77 #include <sys/param.h>
78 #include <sys/systm.h>
79 #include <sys/proc.h>
80 #include <sys/file.h>
81 #include <sys/time.h>
82 #include <sys/stat.h>
83 #include <sys/vnode.h>
84 #include <sys/mount.h>
85 #include <sys/namei.h>
86 #include <sys/malloc.h>
87 #include <sys/buf.h>
88 #include <sys/queue.h>
89 #include <sys/lock.h>
90 #include <sys/kauth.h>
91
92 #include <fs/union/union.h>
93 #include <miscfs/genfs/genfs.h>
94
95 int union_lookup(void *);
96 int union_create(void *);
97 int union_whiteout(void *);
98 int union_mknod(void *);
99 int union_open(void *);
100 int union_close(void *);
101 int union_access(void *);
102 int union_getattr(void *);
103 int union_setattr(void *);
104 int union_read(void *);
105 int union_write(void *);
106 int union_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); /* XXXAD?? */
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))
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 union_node *dun;
1232 struct vnode *vp;
1233 struct vnode *dvp;
1234
1235 dun = VTOUNION(ap->a_dvp);
1236
1237 #ifdef DIAGNOSTIC
1238 if (!(ap->a_cnp->cn_flags & LOCKPARENT)) {
1239 printf("union_link called without LOCKPARENT set!\n");
1240 error = EIO; /* need some error code for "caller is a bozo" */
1241 } else
1242 #endif
1243
1244
1245 if (ap->a_dvp->v_op != ap->a_vp->v_op) {
1246 vp = ap->a_vp;
1247 } else {
1248 struct union_node *un = VTOUNION(ap->a_vp);
1249 if (un->un_uppervp == NULLVP) {
1250 /*
1251 * Needs to be copied before we can link it.
1252 */
1253 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY);
1254 if (dun->un_uppervp == un->un_dirvp) {
1255 dun->un_flags &= ~UN_ULOCK;
1256 VOP_UNLOCK(dun->un_uppervp, 0);
1257 }
1258 error = union_copyup(un, 1, cnp->cn_cred, curlwp);
1259 if (dun->un_uppervp == un->un_dirvp) {
1260 /*
1261 * During copyup, we dropped the lock on the
1262 * dir and invalidated any saved namei lookup
1263 * state for the directory we'll be entering
1264 * the link in. We need to re-run the lookup
1265 * in that directory to reset any state needed
1266 * for VOP_LINK.
1267 * Call relookup on the union-layer to reset
1268 * the state.
1269 */
1270 vp = NULLVP;
1271 if (dun->un_uppervp == NULLVP)
1272 panic("union: null upperdvp?");
1273 error = relookup(ap->a_dvp, &vp, ap->a_cnp);
1274 if (error) {
1275 VOP_UNLOCK(ap->a_vp, 0);
1276 return EROFS; /* ? */
1277 }
1278 if (vp != NULLVP) {
1279 /*
1280 * The name we want to create has
1281 * mysteriously appeared (a race?)
1282 */
1283 error = EEXIST;
1284 VOP_UNLOCK(ap->a_vp, 0);
1285 vput(ap->a_dvp);
1286 vput(vp);
1287 return (error);
1288 }
1289 }
1290 VOP_UNLOCK(ap->a_vp, 0);
1291 }
1292 vp = un->un_uppervp;
1293 }
1294
1295 dvp = dun->un_uppervp;
1296 if (dvp == NULLVP)
1297 error = EROFS;
1298
1299 if (error) {
1300 vput(ap->a_dvp);
1301 return (error);
1302 }
1303
1304 FIXUP(dun);
1305 VREF(dvp);
1306 dun->un_flags |= UN_KLOCK;
1307 vput(ap->a_dvp);
1308
1309 return (VOP_LINK(dvp, vp, cnp));
1310 }
1311
1312 int
1313 union_rename(v)
1314 void *v;
1315 {
1316 struct vop_rename_args /* {
1317 struct vnode *a_fdvp;
1318 struct vnode *a_fvp;
1319 struct componentname *a_fcnp;
1320 struct vnode *a_tdvp;
1321 struct vnode *a_tvp;
1322 struct componentname *a_tcnp;
1323 } */ *ap = v;
1324 int error;
1325
1326 struct vnode *fdvp = ap->a_fdvp;
1327 struct vnode *fvp = ap->a_fvp;
1328 struct vnode *tdvp = ap->a_tdvp;
1329 struct vnode *tvp = ap->a_tvp;
1330
1331 if (fdvp->v_op == union_vnodeop_p) { /* always true */
1332 struct union_node *un = VTOUNION(fdvp);
1333 if (un->un_uppervp == NULLVP) {
1334 /*
1335 * this should never happen in normal
1336 * operation but might if there was
1337 * a problem creating the top-level shadow
1338 * directory.
1339 */
1340 error = EXDEV;
1341 goto bad;
1342 }
1343
1344 fdvp = un->un_uppervp;
1345 VREF(fdvp);
1346 }
1347
1348 if (fvp->v_op == union_vnodeop_p) { /* always true */
1349 struct union_node *un = VTOUNION(fvp);
1350 if (un->un_uppervp == NULLVP) {
1351 /* XXX: should do a copyup */
1352 error = EXDEV;
1353 goto bad;
1354 }
1355
1356 if (un->un_lowervp != NULLVP)
1357 ap->a_fcnp->cn_flags |= DOWHITEOUT;
1358
1359 fvp = un->un_uppervp;
1360 VREF(fvp);
1361 }
1362
1363 if (tdvp->v_op == union_vnodeop_p) {
1364 struct union_node *un = VTOUNION(tdvp);
1365 if (un->un_uppervp == NULLVP) {
1366 /*
1367 * this should never happen in normal
1368 * operation but might if there was
1369 * a problem creating the top-level shadow
1370 * directory.
1371 */
1372 error = EXDEV;
1373 goto bad;
1374 }
1375
1376 tdvp = un->un_uppervp;
1377 VREF(tdvp);
1378 un->un_flags |= UN_KLOCK;
1379 vput(ap->a_tdvp);
1380 }
1381
1382 if (tvp != NULLVP && tvp->v_op == union_vnodeop_p) {
1383 struct union_node *un = VTOUNION(tvp);
1384
1385 tvp = un->un_uppervp;
1386 if (tvp != NULLVP) {
1387 VREF(tvp);
1388 un->un_flags |= UN_KLOCK;
1389 }
1390 vput(ap->a_tvp);
1391 }
1392
1393 error = VOP_RENAME(fdvp, fvp, ap->a_fcnp, tdvp, tvp, ap->a_tcnp);
1394 goto out;
1395
1396 bad:
1397 vput(tdvp);
1398 if (tvp != NULLVP)
1399 vput(tvp);
1400 vrele(fdvp);
1401 vrele(fvp);
1402
1403 out:
1404 if (fdvp != ap->a_fdvp) {
1405 vrele(ap->a_fdvp);
1406 }
1407 if (fvp != ap->a_fvp) {
1408 vrele(ap->a_fvp);
1409 }
1410 return (error);
1411 }
1412
1413 int
1414 union_mkdir(v)
1415 void *v;
1416 {
1417 struct vop_mkdir_args /* {
1418 struct vnode *a_dvp;
1419 struct vnode **a_vpp;
1420 struct componentname *a_cnp;
1421 struct vattr *a_vap;
1422 } */ *ap = v;
1423 struct union_node *un = VTOUNION(ap->a_dvp);
1424 struct vnode *dvp = un->un_uppervp;
1425 struct componentname *cnp = ap->a_cnp;
1426
1427 if (dvp != NULLVP) {
1428 int error;
1429 struct vnode *vp;
1430
1431 FIXUP(un);
1432 VREF(dvp);
1433 un->un_flags |= UN_KLOCK;
1434 VOP_UNLOCK(ap->a_dvp, 0);
1435 error = VOP_MKDIR(dvp, &vp, cnp, ap->a_vap);
1436 if (error) {
1437 vrele(ap->a_dvp);
1438 return (error);
1439 }
1440
1441 error = union_allocvp(ap->a_vpp, ap->a_dvp->v_mount, ap->a_dvp,
1442 NULLVP, cnp, vp, NULLVP, 1);
1443 if (error)
1444 vput(vp);
1445 vrele(ap->a_dvp);
1446 return (error);
1447 }
1448
1449 vput(ap->a_dvp);
1450 return (EROFS);
1451 }
1452
1453 int
1454 union_rmdir(v)
1455 void *v;
1456 {
1457 struct vop_rmdir_args /* {
1458 struct vnode *a_dvp;
1459 struct vnode *a_vp;
1460 struct componentname *a_cnp;
1461 } */ *ap = v;
1462 int error;
1463 struct union_node *dun = VTOUNION(ap->a_dvp);
1464 struct union_node *un = VTOUNION(ap->a_vp);
1465 struct componentname *cnp = ap->a_cnp;
1466
1467 if (dun->un_uppervp == NULLVP)
1468 panic("union rmdir: null upper vnode");
1469
1470 if (un->un_uppervp != NULLVP) {
1471 struct vnode *dvp = dun->un_uppervp;
1472 struct vnode *vp = un->un_uppervp;
1473
1474 FIXUP(dun);
1475 VREF(dvp);
1476 dun->un_flags |= UN_KLOCK;
1477 vput(ap->a_dvp);
1478 FIXUP(un);
1479 VREF(vp);
1480 un->un_flags |= UN_KLOCK;
1481 vput(ap->a_vp);
1482
1483 if (union_dowhiteout(un, cnp->cn_cred))
1484 cnp->cn_flags |= DOWHITEOUT;
1485 error = VOP_RMDIR(dvp, vp, ap->a_cnp);
1486 if (!error)
1487 union_removed_upper(un);
1488 } else {
1489 FIXUP(dun);
1490 error = union_mkwhiteout(
1491 MOUNTTOUNIONMOUNT(UNIONTOV(dun)->v_mount),
1492 dun->un_uppervp, ap->a_cnp, un->un_path);
1493 vput(ap->a_dvp);
1494 vput(ap->a_vp);
1495 }
1496
1497 return (error);
1498 }
1499
1500 int
1501 union_symlink(v)
1502 void *v;
1503 {
1504 struct vop_symlink_args /* {
1505 struct vnode *a_dvp;
1506 struct vnode **a_vpp;
1507 struct componentname *a_cnp;
1508 struct vattr *a_vap;
1509 char *a_target;
1510 } */ *ap = v;
1511 struct union_node *un = VTOUNION(ap->a_dvp);
1512 struct vnode *dvp = un->un_uppervp;
1513 struct componentname *cnp = ap->a_cnp;
1514
1515 if (dvp != NULLVP) {
1516 int error;
1517
1518 FIXUP(un);
1519 VREF(dvp);
1520 un->un_flags |= UN_KLOCK;
1521 vput(ap->a_dvp);
1522 error = VOP_SYMLINK(dvp, ap->a_vpp, cnp, ap->a_vap,
1523 ap->a_target);
1524 return (error);
1525 }
1526
1527 vput(ap->a_dvp);
1528 return (EROFS);
1529 }
1530
1531 /*
1532 * union_readdir works in concert with getdirentries and
1533 * readdir(3) to provide a list of entries in the unioned
1534 * directories. getdirentries is responsible for walking
1535 * down the union stack. readdir(3) is responsible for
1536 * eliminating duplicate names from the returned data stream.
1537 */
1538 int
1539 union_readdir(v)
1540 void *v;
1541 {
1542 struct vop_readdir_args /* {
1543 struct vnodeop_desc *a_desc;
1544 struct vnode *a_vp;
1545 struct uio *a_uio;
1546 kauth_cred_t a_cred;
1547 int *a_eofflag;
1548 u_long *a_cookies;
1549 int a_ncookies;
1550 } */ *ap = v;
1551 struct union_node *un = VTOUNION(ap->a_vp);
1552 struct vnode *uvp = un->un_uppervp;
1553
1554 if (uvp == NULLVP)
1555 return (0);
1556
1557 FIXUP(un);
1558 ap->a_vp = uvp;
1559 return (VCALL(uvp, VOFFSET(vop_readdir), ap));
1560 }
1561
1562 int
1563 union_readlink(v)
1564 void *v;
1565 {
1566 struct vop_readlink_args /* {
1567 struct vnode *a_vp;
1568 struct uio *a_uio;
1569 kauth_cred_t a_cred;
1570 } */ *ap = v;
1571 int error;
1572 struct vnode *vp = OTHERVP(ap->a_vp);
1573 int dolock = (vp == LOWERVP(ap->a_vp));
1574
1575 if (dolock)
1576 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1577 else
1578 FIXUP(VTOUNION(ap->a_vp));
1579 ap->a_vp = vp;
1580 error = VCALL(vp, VOFFSET(vop_readlink), ap);
1581 if (dolock)
1582 VOP_UNLOCK(vp, 0);
1583
1584 return (error);
1585 }
1586
1587 int
1588 union_abortop(v)
1589 void *v;
1590 {
1591 struct vop_abortop_args /* {
1592 struct vnode *a_dvp;
1593 struct componentname *a_cnp;
1594 } */ *ap = v;
1595 int error;
1596 struct vnode *vp = OTHERVP(ap->a_dvp);
1597 struct union_node *un = VTOUNION(ap->a_dvp);
1598 int islocked = un->un_flags & UN_LOCKED;
1599 int dolock = (vp == LOWERVP(ap->a_dvp));
1600
1601 if (islocked) {
1602 if (dolock)
1603 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1604 else
1605 FIXUP(VTOUNION(ap->a_dvp));
1606 }
1607 ap->a_dvp = vp;
1608 error = VCALL(vp, VOFFSET(vop_abortop), ap);
1609 if (islocked && dolock)
1610 VOP_UNLOCK(vp, 0);
1611
1612 return (error);
1613 }
1614
1615 int
1616 union_inactive(v)
1617 void *v;
1618 {
1619 struct vop_inactive_args /* {
1620 const struct vnodeop_desc *a_desc;
1621 struct vnode *a_vp;
1622 bool *a_recycle;
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 *ap->a_recycle = ((un->un_flags & UN_CACHED) == 0);
1649 VOP_UNLOCK(vp, 0);
1650
1651 return (0);
1652 }
1653
1654 int
1655 union_reclaim(v)
1656 void *v;
1657 {
1658 struct vop_reclaim_args /* {
1659 struct vnode *a_vp;
1660 } */ *ap = v;
1661
1662 union_freevp(ap->a_vp);
1663
1664 return (0);
1665 }
1666
1667 int
1668 union_lock(v)
1669 void *v;
1670 {
1671 struct vop_lock_args /* {
1672 struct vnode *a_vp;
1673 int a_flags;
1674 } */ *ap = v;
1675 struct vnode *vp = ap->a_vp;
1676 int flags = ap->a_flags;
1677 struct union_node *un;
1678 int error;
1679
1680 /* XXX unionfs can't handle shared locks yet */
1681 if ((flags & LK_TYPE_MASK) == LK_SHARED) {
1682 flags = LK_EXCLUSIVE | (flags & ~LK_TYPE_MASK);
1683 }
1684
1685 genfs_nolock(ap);
1686 /*
1687 * Need to do real lockmgr-style locking here.
1688 * in the mean time, draining won't work quite right,
1689 * which could lead to a few race conditions.
1690 * the following test was here, but is not quite right, we
1691 * still need to take the lock:
1692 if ((flags & LK_TYPE_MASK) == LK_DRAIN)
1693 return (0);
1694 */
1695 flags &= ~LK_INTERLOCK;
1696
1697 un = VTOUNION(vp);
1698 start:
1699 un = VTOUNION(vp);
1700
1701 if (un->un_uppervp != NULLVP) {
1702 if (((un->un_flags & UN_ULOCK) == 0) &&
1703 (vp->v_usecount != 0)) {
1704 /*
1705 * We MUST always use the order of: take upper
1706 * vp lock, manipulate union node flags, drop
1707 * upper vp lock. This code must not be an
1708 */
1709 error = vn_lock(un->un_uppervp, flags);
1710 if (error)
1711 return (error);
1712 un->un_flags |= UN_ULOCK;
1713 }
1714 #ifdef DIAGNOSTIC
1715 if (un->un_flags & UN_KLOCK) {
1716 vprint("union: dangling klock", vp);
1717 panic("union: dangling upper lock (%p)", vp);
1718 }
1719 #endif
1720 }
1721
1722 /* XXX ignores LK_NOWAIT */
1723 if (un->un_flags & UN_LOCKED) {
1724 #ifdef DIAGNOSTIC
1725 if (curproc && un->un_pid == curproc->p_pid &&
1726 un->un_pid > -1 && curproc->p_pid > -1)
1727 panic("union: locking against myself");
1728 #endif
1729 un->un_flags |= UN_WANTED;
1730 tsleep(&un->un_flags, PINOD, "unionlk2", 0);
1731 goto start;
1732 }
1733
1734 #ifdef DIAGNOSTIC
1735 if (curproc)
1736 un->un_pid = curproc->p_pid;
1737 else
1738 un->un_pid = -1;
1739 #endif
1740
1741 un->un_flags |= UN_LOCKED;
1742 return (0);
1743 }
1744
1745 /*
1746 * When operations want to vput() a union node yet retain a lock on
1747 * the upper vnode (say, to do some further operations like link(),
1748 * mkdir(), ...), they set UN_KLOCK on the union node, then call
1749 * vput() which calls VOP_UNLOCK() and comes here. union_unlock()
1750 * unlocks the union node (leaving the upper vnode alone), clears the
1751 * KLOCK flag, and then returns to vput(). The caller then does whatever
1752 * is left to do with the upper vnode, and ensures that it gets unlocked.
1753 *
1754 * If UN_KLOCK isn't set, then the upper vnode is unlocked here.
1755 */
1756 int
1757 union_unlock(v)
1758 void *v;
1759 {
1760 struct vop_unlock_args /* {
1761 struct vnode *a_vp;
1762 int a_flags;
1763 } */ *ap = v;
1764 struct union_node *un = VTOUNION(ap->a_vp);
1765
1766 #ifdef DIAGNOSTIC
1767 if ((un->un_flags & UN_LOCKED) == 0)
1768 panic("union: unlock unlocked node");
1769 if (curproc && un->un_pid != curproc->p_pid &&
1770 curproc->p_pid > -1 && un->un_pid > -1)
1771 panic("union: unlocking other process's union node");
1772 #endif
1773
1774 un->un_flags &= ~UN_LOCKED;
1775
1776 if ((un->un_flags & (UN_ULOCK|UN_KLOCK)) == UN_ULOCK)
1777 VOP_UNLOCK(un->un_uppervp, 0);
1778
1779 un->un_flags &= ~(UN_ULOCK|UN_KLOCK);
1780
1781 if (un->un_flags & UN_WANTED) {
1782 un->un_flags &= ~UN_WANTED;
1783 wakeup( &un->un_flags);
1784 }
1785
1786 #ifdef DIAGNOSTIC
1787 un->un_pid = 0;
1788 #endif
1789 genfs_nounlock(ap);
1790
1791 return (0);
1792 }
1793
1794 int
1795 union_bmap(v)
1796 void *v;
1797 {
1798 struct vop_bmap_args /* {
1799 struct vnode *a_vp;
1800 daddr_t a_bn;
1801 struct vnode **a_vpp;
1802 daddr_t *a_bnp;
1803 int *a_runp;
1804 } */ *ap = v;
1805 int error;
1806 struct vnode *vp = OTHERVP(ap->a_vp);
1807 int dolock = (vp == LOWERVP(ap->a_vp));
1808
1809 if (dolock)
1810 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1811 else
1812 FIXUP(VTOUNION(ap->a_vp));
1813 ap->a_vp = vp;
1814 error = VCALL(vp, VOFFSET(vop_bmap), ap);
1815 if (dolock)
1816 VOP_UNLOCK(vp, 0);
1817
1818 return (error);
1819 }
1820
1821 int
1822 union_print(v)
1823 void *v;
1824 {
1825 struct vop_print_args /* {
1826 struct vnode *a_vp;
1827 } */ *ap = v;
1828 struct vnode *vp = ap->a_vp;
1829
1830 printf("\ttag VT_UNION, vp=%p, uppervp=%p, lowervp=%p\n",
1831 vp, UPPERVP(vp), LOWERVP(vp));
1832 if (UPPERVP(vp) != NULLVP)
1833 vprint("union: upper", UPPERVP(vp));
1834 if (LOWERVP(vp) != NULLVP)
1835 vprint("union: lower", LOWERVP(vp));
1836 if (VTOUNION(vp)->un_dircache) {
1837 struct vnode **vpp;
1838 for (vpp = VTOUNION(vp)->un_dircache; *vpp != NULLVP; vpp++)
1839 vprint("dircache:", *vpp);
1840 }
1841
1842 return (0);
1843 }
1844
1845 int
1846 union_islocked(v)
1847 void *v;
1848 {
1849 struct vop_islocked_args /* {
1850 struct vnode *a_vp;
1851 } */ *ap = v;
1852
1853 return ((VTOUNION(ap->a_vp)->un_flags & UN_LOCKED) ? 1 : 0);
1854 }
1855
1856 int
1857 union_pathconf(v)
1858 void *v;
1859 {
1860 struct vop_pathconf_args /* {
1861 struct vnode *a_vp;
1862 int a_name;
1863 int *a_retval;
1864 } */ *ap = v;
1865 int error;
1866 struct vnode *vp = OTHERVP(ap->a_vp);
1867 int dolock = (vp == LOWERVP(ap->a_vp));
1868
1869 if (dolock)
1870 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1871 else
1872 FIXUP(VTOUNION(ap->a_vp));
1873 ap->a_vp = vp;
1874 error = VCALL(vp, VOFFSET(vop_pathconf), ap);
1875 if (dolock)
1876 VOP_UNLOCK(vp, 0);
1877
1878 return (error);
1879 }
1880
1881 int
1882 union_advlock(v)
1883 void *v;
1884 {
1885 struct vop_advlock_args /* {
1886 struct vnode *a_vp;
1887 void *a_id;
1888 int a_op;
1889 struct flock *a_fl;
1890 int a_flags;
1891 } */ *ap = v;
1892 struct vnode *ovp = OTHERVP(ap->a_vp);
1893
1894 ap->a_vp = ovp;
1895 return (VCALL(ovp, VOFFSET(vop_advlock), ap));
1896 }
1897
1898
1899 /*
1900 * XXX - vop_strategy must be hand coded because it has no
1901 * vnode in its arguments.
1902 * This goes away with a merged VM/buffer cache.
1903 */
1904 int
1905 union_strategy(v)
1906 void *v;
1907 {
1908 struct vop_strategy_args /* {
1909 struct vnode *a_vp;
1910 struct buf *a_bp;
1911 } */ *ap = v;
1912 struct vnode *ovp = OTHERVP(ap->a_vp);
1913 struct buf *bp = ap->a_bp;
1914
1915 #ifdef DIAGNOSTIC
1916 if (ovp == NULLVP)
1917 panic("union_strategy: nil vp");
1918 if (((bp->b_flags & B_READ) == 0) &&
1919 (ovp == LOWERVP(bp->b_vp)))
1920 panic("union_strategy: writing to lowervp");
1921 #endif
1922
1923 return (VOP_STRATEGY(ovp, bp));
1924 }
1925
1926 int
1927 union_getpages(v)
1928 void *v;
1929 {
1930 struct vop_getpages_args /* {
1931 struct vnode *a_vp;
1932 voff_t a_offset;
1933 struct vm_page **a_m;
1934 int *a_count;
1935 int a_centeridx;
1936 vm_prot_t a_access_type;
1937 int a_advice;
1938 int a_flags;
1939 } */ *ap = v;
1940 struct vnode *vp = ap->a_vp;
1941 int error;
1942
1943 /*
1944 * just pass the request on to the underlying layer.
1945 */
1946
1947 if (ap->a_flags & PGO_LOCKED) {
1948 return EBUSY;
1949 }
1950 ap->a_vp = OTHERVP(vp);
1951 mutex_exit(&vp->v_interlock);
1952 mutex_enter(&ap->a_vp->v_interlock);
1953 error = VCALL(ap->a_vp, VOFFSET(vop_getpages), ap);
1954 return error;
1955 }
1956
1957 int
1958 union_putpages(v)
1959 void *v;
1960 {
1961 struct vop_putpages_args /* {
1962 struct vnode *a_vp;
1963 voff_t a_offlo;
1964 voff_t a_offhi;
1965 int a_flags;
1966 } */ *ap = v;
1967 struct vnode *vp = ap->a_vp;
1968 int error;
1969
1970 /*
1971 * just pass the request on to the underlying layer.
1972 */
1973
1974 ap->a_vp = OTHERVP(vp);
1975 mutex_exit(&vp->v_interlock);
1976 if (ap->a_flags & PGO_RECLAIM) {
1977 return 0;
1978 }
1979 mutex_enter(&ap->a_vp->v_interlock);
1980 error = VCALL(ap->a_vp, VOFFSET(vop_putpages), ap);
1981 return error;
1982 }
1983
1984 int
1985 union_kqfilter(void *v)
1986 {
1987 struct vop_kqfilter_args /* {
1988 struct vnode *a_vp;
1989 struct knote *a_kn;
1990 } */ *ap = v;
1991 int error;
1992
1993 /*
1994 * We watch either the upper layer file (if it already exists),
1995 * or the lower layer one. If there is lower layer file only
1996 * at this moment, we will keep watching that lower layer file
1997 * even if upper layer file would be created later on.
1998 */
1999 if (UPPERVP(ap->a_vp))
2000 error = VOP_KQFILTER(UPPERVP(ap->a_vp), ap->a_kn);
2001 else if (LOWERVP(ap->a_vp))
2002 error = VOP_KQFILTER(LOWERVP(ap->a_vp), ap->a_kn);
2003 else {
2004 /* panic? */
2005 error = EOPNOTSUPP;
2006 }
2007
2008 return (error);
2009 }
2010