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