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