Deleted Added
full compact
union_vnops.c (140181) union_vnops.c (140196)
1/*-
2 * Copyright (c) 1992, 1993, 1994, 1995 Jan-Simon Pendry.
3 * Copyright (c) 1992, 1993, 1994, 1995
4 * The Regents of the University of California. All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Jan-Simon Pendry.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)union_vnops.c 8.32 (Berkeley) 6/23/95
1/*-
2 * Copyright (c) 1992, 1993, 1994, 1995 Jan-Simon Pendry.
3 * Copyright (c) 1992, 1993, 1994, 1995
4 * The Regents of the University of California. All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Jan-Simon Pendry.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)union_vnops.c 8.32 (Berkeley) 6/23/95
34 * $FreeBSD: head/sys/fs/unionfs/union_vnops.c 140181 2005-01-13 12:25:19Z phk $
34 * $FreeBSD: head/sys/fs/unionfs/union_vnops.c 140196 2005-01-13 18:59:48Z phk $
35 */
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/fcntl.h>
40#include <sys/stat.h>
41#include <sys/kernel.h>
42#include <sys/vnode.h>
43#include <sys/mount.h>
44#include <sys/namei.h>
45#include <sys/malloc.h>
46#include <sys/bio.h>
47#include <sys/buf.h>
48#include <sys/lock.h>
49#include <sys/sysctl.h>
50#include <sys/unistd.h>
51#include <sys/acl.h>
52#include <sys/event.h>
53#include <sys/extattr.h>
54#include <sys/mac.h>
55#include <fs/unionfs/union.h>
56
57#include <vm/vm.h>
58#include <vm/vnode_pager.h>
59
60#include <vm/vm_page.h>
61#include <vm/vm_object.h>
62
63int uniondebug = 0;
64
65#if UDEBUG_ENABLED
66SYSCTL_INT(_vfs, OID_AUTO, uniondebug, CTLFLAG_RW, &uniondebug, 0, "");
67#else
68SYSCTL_INT(_vfs, OID_AUTO, uniondebug, CTLFLAG_RD, &uniondebug, 0, "");
69#endif
70
71static vop_access_t union_access;
72static vop_aclcheck_t union_aclcheck;
73static vop_advlock_t union_advlock;
74static vop_close_t union_close;
75static vop_closeextattr_t union_closeextattr;
76static vop_create_t union_create;
77static vop_createvobject_t union_createvobject;
78static vop_deleteextattr_t union_deleteextattr;
79static vop_destroyvobject_t union_destroyvobject;
80static vop_fsync_t union_fsync;
81static vop_getacl_t union_getacl;
82static vop_getattr_t union_getattr;
83static vop_getextattr_t union_getextattr;
84static vop_getvobject_t union_getvobject;
85static vop_inactive_t union_inactive;
86static vop_ioctl_t union_ioctl;
87static vop_lease_t union_lease;
88static vop_link_t union_link;
89static vop_listextattr_t union_listextattr;
90static vop_lookup_t union_lookup;
91static int union_lookup1(struct vnode *udvp, struct vnode **dvp,
92 struct vnode **vpp,
93 struct componentname *cnp);
94static vop_mkdir_t union_mkdir;
95static vop_mknod_t union_mknod;
96static vop_open_t union_open;
97static vop_openextattr_t union_openextattr;
98static vop_pathconf_t union_pathconf;
99static vop_print_t union_print;
100static vop_read_t union_read;
101static vop_readdir_t union_readdir;
102static vop_readlink_t union_readlink;
103static vop_getwritemount_t union_getwritemount;
104static vop_reclaim_t union_reclaim;
105static vop_remove_t union_remove;
106static vop_rename_t union_rename;
107static vop_rmdir_t union_rmdir;
108static vop_poll_t union_poll;
109static vop_setacl_t union_setacl;
110static vop_setattr_t union_setattr;
111static vop_setlabel_t union_setlabel;
112static vop_setextattr_t union_setextattr;
113static vop_strategy_t union_strategy;
114static vop_symlink_t union_symlink;
115static vop_whiteout_t union_whiteout;
116static vop_write_t union_write;
117
118static __inline
119struct vnode *
120union_lock_upper(struct union_node *un, struct thread *td)
121{
122 struct vnode *uppervp;
123
124 if ((uppervp = un->un_uppervp) != NULL) {
125 VREF(uppervp);
126 vn_lock(uppervp, LK_EXCLUSIVE | LK_CANRECURSE | LK_RETRY, td);
127 }
128 KASSERT((uppervp == NULL || vrefcnt(uppervp) > 0), ("uppervp usecount is 0"));
129 return(uppervp);
130}
131
132static __inline
133void
134union_unlock_upper(struct vnode *uppervp, struct thread *td)
135{
136 vput(uppervp);
137}
138
139static __inline
140struct vnode *
141union_lock_other(struct union_node *un, struct thread *td)
142{
143 struct vnode *vp;
144
145 if (un->un_uppervp != NULL) {
146 vp = union_lock_upper(un, td);
147 } else if ((vp = un->un_lowervp) != NULL) {
148 VREF(vp);
149 vn_lock(vp, LK_EXCLUSIVE | LK_CANRECURSE | LK_RETRY, td);
150 }
151 return(vp);
152}
153
154static __inline
155void
156union_unlock_other(struct vnode *vp, struct thread *td)
157{
158 vput(vp);
159}
160
161/*
162 * union_lookup:
163 *
164 * udvp must be exclusively locked on call and will remain
165 * exclusively locked on return. This is the mount point
166 * for our filesystem.
167 *
168 * dvp Our base directory, locked and referenced.
169 * The passed dvp will be dereferenced and unlocked on return
170 * and a new dvp will be returned which is locked and
171 * referenced in the same variable.
172 *
173 * vpp is filled in with the result if no error occured,
174 * locked and ref'd.
175 *
176 * If an error is returned, *vpp is set to NULLVP. If no
177 * error occurs, *vpp is returned with a reference and an
178 * exclusive lock.
179 */
180
181static int
182union_lookup1(udvp, pdvp, vpp, cnp)
183 struct vnode *udvp;
184 struct vnode **pdvp;
185 struct vnode **vpp;
186 struct componentname *cnp;
187{
188 int error;
189 struct thread *td = cnp->cn_thread;
190 struct vnode *dvp = *pdvp;
191 struct vnode *tdvp;
192 struct mount *mp;
193
194 /*
195 * If stepping up the directory tree, check for going
196 * back across the mount point, in which case do what
197 * lookup would do by stepping back down the mount
198 * hierarchy.
199 */
200 if (cnp->cn_flags & ISDOTDOT) {
201 while ((dvp != udvp) && (dvp->v_vflag & VV_ROOT)) {
202 /*
203 * Don't do the NOCROSSMOUNT check
204 * at this level. By definition,
205 * union fs deals with namespaces, not
206 * filesystems.
207 */
208 tdvp = dvp;
209 dvp = dvp->v_mount->mnt_vnodecovered;
210 VREF(dvp);
211 vput(tdvp);
212 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
213 }
214 }
215
216 /*
217 * Set return dvp to be the upperdvp 'parent directory.
218 */
219 *pdvp = dvp;
220
221 /*
222 * If the VOP_LOOKUP() call generates an error, tdvp is invalid and
223 * no changes will have been made to dvp, so we are set to return.
224 */
225
226 error = VOP_LOOKUP(dvp, &tdvp, cnp);
227 if (error) {
228 UDEBUG(("dvp %p error %d flags %lx\n", dvp, error, cnp->cn_flags));
229 *vpp = NULL;
230 return (error);
231 }
232
233 /*
234 * The parent directory will have been unlocked, unless lookup
235 * found the last component or if dvp == tdvp (tdvp must be locked).
236 *
237 * We want our dvp to remain locked and ref'd. We also want tdvp
238 * to remain locked and ref'd.
239 */
240 UDEBUG(("parentdir %p result %p flag %lx\n", dvp, tdvp, cnp->cn_flags));
241
242 if (dvp != tdvp && (cnp->cn_flags & ISLASTCN) == 0)
243 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
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 * We use dvp as a temporary variable here, it is no longer related
251 * to the dvp above. However, we have to ensure that both *pdvp and
252 * tdvp are locked on return.
253 */
254
255 dvp = tdvp;
256 while (
257 dvp != udvp &&
258 (dvp->v_type == VDIR) &&
259 (mp = dvp->v_mountedhere)
260 ) {
261 int relock_pdvp = 0;
262
263 if (vfs_busy(mp, 0, 0, td))
264 continue;
265
266 if (dvp == *pdvp)
267 relock_pdvp = 1;
268 vput(dvp);
269 dvp = NULL;
270 error = VFS_ROOT(mp, &dvp, td);
271
272 vfs_unbusy(mp, td);
273
274 if (relock_pdvp)
275 vn_lock(*pdvp, LK_EXCLUSIVE | LK_RETRY, td);
276
277 if (error) {
278 *vpp = NULL;
279 return (error);
280 }
281 }
282 *vpp = dvp;
283 return (0);
284}
285
286static int
287union_lookup(ap)
288 struct vop_lookup_args /* {
289 struct vnodeop_desc *a_desc;
290 struct vnode *a_dvp;
291 struct vnode **a_vpp;
292 struct componentname *a_cnp;
293 } */ *ap;
294{
295 int error;
296 int uerror, lerror;
297 struct vnode *uppervp, *lowervp;
298 struct vnode *upperdvp, *lowerdvp;
299 struct vnode *dvp = ap->a_dvp; /* starting dir */
300 struct union_node *dun = VTOUNION(dvp); /* associated union node */
301 struct componentname *cnp = ap->a_cnp;
302 struct thread *td = cnp->cn_thread;
303 int lockparent = cnp->cn_flags & LOCKPARENT;
304 struct union_mount *um = MOUNTTOUNIONMOUNT(dvp->v_mount);
305 struct ucred *saved_cred = NULL;
306 int iswhiteout;
307 struct vattr va;
308
309 *ap->a_vpp = NULLVP;
310
311 /*
312 * Disallow write attempts to the filesystem mounted read-only.
313 */
314 if ((cnp->cn_flags & ISLASTCN) &&
315 (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
316 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
317 return (EROFS);
318 }
319
320 /*
321 * For any lookups we do, always return with the parent locked.
322 */
323 cnp->cn_flags |= LOCKPARENT;
324
325 lowerdvp = dun->un_lowervp;
326 uppervp = NULLVP;
327 lowervp = NULLVP;
328 iswhiteout = 0;
329
330 uerror = ENOENT;
331 lerror = ENOENT;
332
333 /*
334 * Get a private lock on uppervp and a reference, effectively
335 * taking it out of the union_node's control.
336 *
337 * We must lock upperdvp while holding our lock on dvp
338 * to avoid a deadlock.
339 */
340 upperdvp = union_lock_upper(dun, td);
341
342 /*
343 * Do the lookup in the upper level.
344 * If that level consumes additional pathnames,
345 * then assume that something special is going
346 * on and just return that vnode.
347 */
348 if (upperdvp != NULLVP) {
349 /*
350 * We do not have to worry about the DOTDOT case, we've
351 * already unlocked dvp.
352 */
353 UDEBUG(("A %p\n", upperdvp));
354
355 /*
356 * Do the lookup. We must supply a locked and referenced
357 * upperdvp to the function and will get a new locked and
358 * referenced upperdvp back, with the old having been
359 * dereferenced.
360 *
361 * If an error is returned, uppervp will be NULLVP. If no
362 * error occurs, uppervp will be the locked and referenced.
363 * Return vnode, or possibly NULL, depending on what is being
364 * requested. It is possible that the returned uppervp
365 * will be the same as upperdvp.
366 */
367 uerror = union_lookup1(um->um_uppervp, &upperdvp, &uppervp, cnp);
368 UDEBUG((
369 "uerror %d upperdvp %p %d/%d, uppervp %p ref=%d/lck=%d\n",
370 uerror,
371 upperdvp,
372 vrefcnt(upperdvp),
373 VOP_ISLOCKED(upperdvp, NULL),
374 uppervp,
375 (uppervp ? vrefcnt(uppervp) : -99),
376 (uppervp ? VOP_ISLOCKED(uppervp, NULL) : -99)
377 ));
378
379 /*
380 * Disallow write attempts to the filesystem mounted read-only.
381 */
382 if (uerror == EJUSTRETURN && (cnp->cn_flags & ISLASTCN) &&
383 (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
384 (cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME)) {
385 error = EROFS;
386 goto out;
387 }
388
389 /*
390 * Special case: If cn_consume != 0 then skip out. The result
391 * of the lookup is transfered to our return variable. If
392 * an error occured we have to throw away the results.
393 */
394
395 if (cnp->cn_consume != 0) {
396 if ((error = uerror) == 0) {
397 *ap->a_vpp = uppervp;
398 uppervp = NULL;
399 }
400 goto out;
401 }
402
403 /*
404 * Calculate whiteout, fall through.
405 */
406
407 if (uerror == ENOENT || uerror == EJUSTRETURN) {
408 if (cnp->cn_flags & ISWHITEOUT) {
409 iswhiteout = 1;
410 } else if (lowerdvp != NULLVP) {
411 int terror;
412
413 terror = VOP_GETATTR(upperdvp, &va,
414 cnp->cn_cred, cnp->cn_thread);
415 if (terror == 0 && (va.va_flags & OPAQUE))
416 iswhiteout = 1;
417 }
418 }
419 }
420
421 /*
422 * In a similar way to the upper layer, do the lookup
423 * in the lower layer. This time, if there is some
424 * component magic going on, then vput whatever we got
425 * back from the upper layer and return the lower vnode
426 * instead.
427 */
428
429 if (lowerdvp != NULLVP && !iswhiteout) {
430 int nameiop;
431
432 UDEBUG(("B %p\n", lowerdvp));
433
434 /*
435 * Force only LOOKUPs on the lower node, since
436 * we won't be making changes to it anyway.
437 */
438 nameiop = cnp->cn_nameiop;
439 cnp->cn_nameiop = LOOKUP;
440 if (um->um_op == UNMNT_BELOW) {
441 saved_cred = cnp->cn_cred;
442 cnp->cn_cred = um->um_cred;
443 }
444
445 /*
446 * We shouldn't have to worry about locking interactions
447 * between the lower layer and our union layer (w.r.t.
448 * `..' processing) because we don't futz with lowervp
449 * locks in the union-node instantiation code path.
450 *
451 * union_lookup1() requires lowervp to be locked on entry,
452 * and it will be unlocked on return. The ref count will
453 * not change. On return lowervp doesn't represent anything
454 * to us so we NULL it out.
455 */
456 VREF(lowerdvp);
457 vn_lock(lowerdvp, LK_EXCLUSIVE | LK_RETRY, td);
458 lerror = union_lookup1(um->um_lowervp, &lowerdvp, &lowervp, cnp);
459 if (lowerdvp == lowervp)
460 vrele(lowerdvp);
461 else
462 vput(lowerdvp);
463 lowerdvp = NULL; /* lowerdvp invalid after vput */
464
465 if (um->um_op == UNMNT_BELOW)
466 cnp->cn_cred = saved_cred;
467 cnp->cn_nameiop = nameiop;
468
469 if (cnp->cn_consume != 0 || lerror == EACCES) {
470 if ((error = lerror) == 0) {
471 *ap->a_vpp = lowervp;
472 lowervp = NULL;
473 }
474 goto out;
475 }
476 } else {
477 UDEBUG(("C %p\n", lowerdvp));
478 if ((cnp->cn_flags & ISDOTDOT) && dun->un_pvp != NULLVP) {
479 if ((lowervp = LOWERVP(dun->un_pvp)) != NULL) {
480 VREF(lowervp);
481 vn_lock(lowervp, LK_EXCLUSIVE | LK_RETRY, td);
482 lerror = 0;
483 }
484 }
485 }
486
487 /*
488 * Ok. Now we have uerror, uppervp, upperdvp, lerror, and lowervp.
489 *
490 * 1. If both layers returned an error, select the upper layer.
491 *
492 * 2. If the upper layer failed and the bottom layer succeeded,
493 * two subcases occur:
494 *
495 * a. The bottom vnode is not a directory, in which case
496 * just return a new union vnode referencing an
497 * empty top layer and the existing bottom layer.
498 *
499 * b. The bottom vnode is a directory, in which case
500 * create a new directory in the top layer and
501 * and fall through to case 3.
502 *
503 * 3. If the top layer succeeded, then return a new union
504 * vnode referencing whatever the new top layer and
505 * whatever the bottom layer returned.
506 */
507
508 /* case 1. */
509 if ((uerror != 0) && (lerror != 0)) {
510 error = uerror;
511 goto out;
512 }
513
514 /* case 2. */
515 if (uerror != 0 /* && (lerror == 0) */ ) {
516 if (lowervp->v_type == VDIR) { /* case 2b. */
517 KASSERT(uppervp == NULL, ("uppervp unexpectedly non-NULL"));
518 /*
519 * Oops, uppervp has a problem, we may have to shadow.
520 */
521 uerror = union_mkshadow(um, upperdvp, cnp, &uppervp);
522 if (uerror) {
523 error = uerror;
524 goto out;
525 }
526 }
527 }
528
529 /*
530 * Must call union_allocvp() with both the upper and lower vnodes
531 * referenced and the upper vnode locked. ap->a_vpp is returned
532 * referenced and locked. lowervp, uppervp, and upperdvp are
533 * absorbed by union_allocvp() whether it succeeds or fails.
534 *
535 * upperdvp is the parent directory of uppervp which may be
536 * different, depending on the path, from dvp->un_uppervp. That's
537 * why it is a separate argument. Note that it must be unlocked.
538 *
539 * dvp must be locked on entry to the call and will be locked on
540 * return.
541 */
542
543 if (uppervp && uppervp != upperdvp)
544 VOP_UNLOCK(uppervp, 0, td);
545 if (lowervp)
546 VOP_UNLOCK(lowervp, 0, td);
547 if (upperdvp)
548 VOP_UNLOCK(upperdvp, 0, td);
549
550 error = union_allocvp(ap->a_vpp, dvp->v_mount, dvp, upperdvp, cnp,
551 uppervp, lowervp, 1);
552
553 UDEBUG(("Create %p = %p %p refs=%d\n", *ap->a_vpp, uppervp, lowervp, (*ap->a_vpp) ? vrefcnt(*ap->a_vpp) : -99));
554
555 uppervp = NULL;
556 upperdvp = NULL;
557 lowervp = NULL;
558
559 /*
560 * Termination Code
561 *
562 * - put away any extra junk laying around. Note that lowervp
563 * (if not NULL) will never be the same as *ap->a_vp and
564 * neither will uppervp, because when we set that state we
565 * NULL-out lowervp or uppervp. On the otherhand, upperdvp
566 * may match uppervp or *ap->a_vpp.
567 *
568 * - relock/unlock dvp if appropriate.
569 */
570
571out:
572 if (upperdvp) {
573 if (upperdvp == uppervp || upperdvp == *ap->a_vpp)
574 vrele(upperdvp);
575 else
576 vput(upperdvp);
577 }
578
579 if (uppervp)
580 vput(uppervp);
581
582 if (lowervp)
583 vput(lowervp);
584
585 /*
586 * Restore LOCKPARENT state
587 */
588
589 if (!lockparent)
590 cnp->cn_flags &= ~LOCKPARENT;
591
592 UDEBUG(("Out %d vpp %p/%d lower %p upper %p\n", error, *ap->a_vpp,
593 ((*ap->a_vpp) ? vrefcnt(*ap->a_vpp) : -99),
594 lowervp, uppervp));
595
596 if (error == 0 || error == EJUSTRETURN) {
597 /*
598 * dvp lock state, determine whether to relock dvp.
599 * We are expected to unlock dvp unless:
600 *
601 * - there was an error (other than EJUSTRETURN), or
602 * - we hit the last component and lockparent is true
603 */
604 if (*ap->a_vpp != dvp) {
605 if (!lockparent || (cnp->cn_flags & ISLASTCN) == 0)
606 VOP_UNLOCK(dvp, 0, td);
607 }
608
609 if (cnp->cn_namelen == 1 &&
610 cnp->cn_nameptr[0] == '.' &&
611 *ap->a_vpp != dvp) {
612#ifdef DIAGNOSTIC
613 vprint("union_lookup: vp", *ap->a_vpp);
614 vprint("union_lookup: dvp", dvp);
615#endif
616 panic("union_lookup returning . (%p) != startdir (%p)",
617 *ap->a_vpp, dvp);
618 }
619 }
620
621 return (error);
622}
623
624/*
625 * union_create:
626 *
627 * a_dvp is locked on entry and remains locked on return. a_vpp is returned
628 * locked if no error occurs, otherwise it is garbage.
629 */
630
631static int
632union_create(ap)
633 struct vop_create_args /* {
634 struct vnode *a_dvp;
635 struct vnode **a_vpp;
636 struct componentname *a_cnp;
637 struct vattr *a_vap;
638 } */ *ap;
639{
640 struct union_node *dun = VTOUNION(ap->a_dvp);
641 struct componentname *cnp = ap->a_cnp;
642 struct thread *td = cnp->cn_thread;
643 struct vnode *dvp;
644 int error = EROFS;
645
646 if ((dvp = union_lock_upper(dun, td)) != NULL) {
647 struct vnode *vp;
648 struct mount *mp;
649
650 error = VOP_CREATE(dvp, &vp, cnp, ap->a_vap);
651 if (error == 0) {
652 mp = ap->a_dvp->v_mount;
653 VOP_UNLOCK(vp, 0, td);
654 UDEBUG(("ALLOCVP-1 FROM %p REFS %d\n", vp, vrefcnt(vp)));
655 error = union_allocvp(ap->a_vpp, mp, NULLVP, NULLVP,
656 cnp, vp, NULLVP, 1);
657 UDEBUG(("ALLOCVP-2B FROM %p REFS %d\n", *ap->a_vpp, vrefcnt(vp)));
658 }
659 union_unlock_upper(dvp, td);
660 }
661 return (error);
662}
663
664static int
665union_whiteout(ap)
666 struct vop_whiteout_args /* {
667 struct vnode *a_dvp;
668 struct componentname *a_cnp;
669 int a_flags;
670 } */ *ap;
671{
672 struct union_node *un = VTOUNION(ap->a_dvp);
673 struct componentname *cnp = ap->a_cnp;
674 struct vnode *uppervp;
675 int error;
676
677 switch (ap->a_flags) {
678 case CREATE:
679 case DELETE:
680 uppervp = union_lock_upper(un, cnp->cn_thread);
681 if (uppervp != NULLVP) {
682 error = VOP_WHITEOUT(un->un_uppervp, cnp, ap->a_flags);
683 union_unlock_upper(uppervp, cnp->cn_thread);
684 } else
685 error = EOPNOTSUPP;
686 break;
687 case LOOKUP:
688 error = EOPNOTSUPP;
689 break;
690 default:
691 panic("union_whiteout: unknown op");
692 }
693 return (error);
694}
695
696/*
697 * union_mknod:
698 *
699 * a_dvp is locked on entry and should remain locked on return.
700 * a_vpp is garbagre whether an error occurs or not.
701 */
702
703static int
704union_mknod(ap)
705 struct vop_mknod_args /* {
706 struct vnode *a_dvp;
707 struct vnode **a_vpp;
708 struct componentname *a_cnp;
709 struct vattr *a_vap;
710 } */ *ap;
711{
712 struct union_node *dun = VTOUNION(ap->a_dvp);
713 struct componentname *cnp = ap->a_cnp;
714 struct vnode *dvp;
715 int error = EROFS;
716
717 if ((dvp = union_lock_upper(dun, cnp->cn_thread)) != NULL) {
718 error = VOP_MKNOD(dvp, ap->a_vpp, cnp, ap->a_vap);
719 union_unlock_upper(dvp, cnp->cn_thread);
720 }
721 return (error);
722}
723
724/*
725 * union_open:
726 *
727 * run open VOP. When opening the underlying vnode we have to mimic
728 * vn_open(). What we *really* need to do to avoid screwups if the
729 * open semantics change is to call vn_open(). For example, ufs blows
730 * up if you open a file but do not vmio it prior to writing.
731 */
732
733static int
734union_open(ap)
735 struct vop_open_args /* {
736 struct vnodeop_desc *a_desc;
737 struct vnode *a_vp;
738 int a_mode;
739 struct ucred *a_cred;
740 struct thread *a_td;
741 } */ *ap;
742{
743 struct union_node *un = VTOUNION(ap->a_vp);
744 struct vnode *tvp;
745 int mode = ap->a_mode;
746 struct ucred *cred = ap->a_cred;
747 struct thread *td = ap->a_td;
748 int error = 0;
749 int tvpisupper = 1;
750
751 /*
752 * If there is an existing upper vp then simply open that.
753 * The upper vp takes precedence over the lower vp. When opening
754 * a lower vp for writing copy it to the uppervp and then open the
755 * uppervp.
756 *
757 * At the end of this section tvp will be left locked.
758 */
759 if ((tvp = union_lock_upper(un, td)) == NULLVP) {
760 /*
761 * If the lower vnode is being opened for writing, then
762 * copy the file contents to the upper vnode and open that,
763 * otherwise can simply open the lower vnode.
764 */
765 tvp = un->un_lowervp;
766 if ((ap->a_mode & FWRITE) && (tvp->v_type == VREG)) {
767 int docopy = !(mode & O_TRUNC);
768 error = union_copyup(un, docopy, cred, td);
769 tvp = union_lock_upper(un, td);
770 } else {
771 un->un_openl++;
772 VREF(tvp);
773 vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY, td);
774 tvpisupper = 0;
775 }
776 }
777
778 /*
779 * We are holding the correct vnode, open it.
780 */
781
782 if (error == 0)
783 error = VOP_OPEN(tvp, mode, cred, td, -1);
784
785 /*
786 * This is absolutely necessary or UFS will blow up.
787 */
788 if (error == 0 && vn_canvmio(tvp) == TRUE)
789 error = VOP_CREATEVOBJECT(tvp, cred, td);
790
791 /*
792 * Release any locks held.
793 */
794 if (tvpisupper) {
795 if (tvp)
796 union_unlock_upper(tvp, td);
797 } else {
798 vput(tvp);
799 }
800 return (error);
801}
802
803/*
804 * union_close:
805 *
806 * It is unclear whether a_vp is passed locked or unlocked. Whatever
807 * the case we do not change it.
808 */
809
810static int
811union_close(ap)
812 struct vop_close_args /* {
813 struct vnode *a_vp;
814 int a_fflag;
815 struct ucred *a_cred;
816 struct thread *a_td;
817 } */ *ap;
818{
819 struct union_node *un = VTOUNION(ap->a_vp);
820 struct vnode *vp;
821
822 if ((vp = un->un_uppervp) == NULLVP) {
823#ifdef UNION_DIAGNOSTIC
824 if (un->un_openl <= 0)
825 panic("union: un_openl cnt");
826#endif
827 --un->un_openl;
828 vp = un->un_lowervp;
829 }
830 ap->a_vp = vp;
831 return (VOP_CLOSE_AP(ap));
832}
833
834/*
835 * Check access permission on the union vnode.
836 * The access check being enforced is to check
837 * against both the underlying vnode, and any
838 * copied vnode. This ensures that no additional
839 * file permissions are given away simply because
840 * the user caused an implicit file copy.
841 */
842static int
843union_access(ap)
844 struct vop_access_args /* {
845 struct vnodeop_desc *a_desc;
846 struct vnode *a_vp;
847 int a_mode;
848 struct ucred *a_cred;
849 struct thread *a_td;
850 } */ *ap;
851{
852 struct union_node *un = VTOUNION(ap->a_vp);
853 struct thread *td = ap->a_td;
854 int error = EACCES;
855 struct vnode *vp;
856
857 /*
858 * Disallow write attempts on filesystems mounted read-only.
859 */
860 if ((ap->a_mode & VWRITE) &&
861 (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)) {
862 switch (ap->a_vp->v_type) {
863 case VREG:
864 case VDIR:
865 case VLNK:
866 return (EROFS);
867 default:
868 break;
869 }
870 }
871
872 if ((vp = union_lock_upper(un, td)) != NULLVP) {
873 ap->a_vp = vp;
874 error = VOP_ACCESS_AP(ap);
875 union_unlock_upper(vp, td);
876 return(error);
877 }
878
879 if ((vp = un->un_lowervp) != NULLVP) {
880 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
881 ap->a_vp = vp;
882
883 /*
884 * Remove VWRITE from a_mode if our mount point is RW, because
885 * we want to allow writes and lowervp may be read-only.
886 */
887 if ((un->un_vnode->v_mount->mnt_flag & MNT_RDONLY) == 0)
888 ap->a_mode &= ~VWRITE;
889
890 error = VOP_ACCESS_AP(ap);
891 if (error == 0) {
892 struct union_mount *um;
893
894 um = MOUNTTOUNIONMOUNT(un->un_vnode->v_mount);
895
896 if (um->um_op == UNMNT_BELOW) {
897 ap->a_cred = um->um_cred;
898 error = VOP_ACCESS_AP(ap);
899 }
900 }
901 VOP_UNLOCK(vp, 0, td);
902 }
903 return(error);
904}
905
906/*
907 * We handle getattr only to change the fsid and
908 * track object sizes
909 *
910 * It's not clear whether VOP_GETATTR is to be
911 * called with the vnode locked or not. stat() calls
912 * it with (vp) locked, and fstat() calls it with
913 * (vp) unlocked.
914 *
915 * Because of this we cannot use our normal locking functions
916 * if we do not intend to lock the main a_vp node. At the moment
917 * we are running without any specific locking at all, but beware
918 * to any programmer that care must be taken if locking is added
919 * to this function.
920 */
921
922static int
923union_getattr(ap)
924 struct vop_getattr_args /* {
925 struct vnode *a_vp;
926 struct vattr *a_vap;
927 struct ucred *a_cred;
928 struct thread *a_td;
929 } */ *ap;
930{
931 int error;
932 struct union_node *un = VTOUNION(ap->a_vp);
933 struct union_mount *um = MOUNTTOUNIONMOUNT(ap->a_vp->v_mount);
934 struct vnode *vp;
935 struct vattr *vap;
936 struct vattr va;
937
938 /*
939 * Some programs walk the filesystem hierarchy by counting
940 * links to directories to avoid stat'ing all the time.
941 * This means the link count on directories needs to be "correct".
942 * The only way to do that is to call getattr on both layers
943 * and fix up the link count. The link count will not necessarily
944 * be accurate but will be large enough to defeat the tree walkers.
945 */
946
947 vap = ap->a_vap;
948
949 if ((vp = un->un_uppervp) != NULLVP) {
950 error = VOP_GETATTR(vp, vap, ap->a_cred, ap->a_td);
951 if (error)
952 return (error);
953 /* XXX isn't this dangerous without a lock? */
954 union_newsize(ap->a_vp, vap->va_size, VNOVAL);
955 }
956
957 if (vp == NULLVP) {
958 vp = un->un_lowervp;
959 } else if (vp->v_type == VDIR && un->un_lowervp != NULLVP) {
960 vp = un->un_lowervp;
961 vap = &va;
962 } else {
963 vp = NULLVP;
964 }
965
966 if (vp != NULLVP) {
967 error = VOP_GETATTR(vp, vap, ap->a_cred, ap->a_td);
968 if (error)
969 return (error);
970 /* XXX isn't this dangerous without a lock? */
971 union_newsize(ap->a_vp, VNOVAL, vap->va_size);
972 }
973
974 if (ap->a_vap->va_fsid == um->um_upperdev)
975 ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
976
977 if ((vap != ap->a_vap) && (vap->va_type == VDIR))
978 ap->a_vap->va_nlink += vap->va_nlink;
979 return (0);
980}
981
982static int
983union_setattr(ap)
984 struct vop_setattr_args /* {
985 struct vnode *a_vp;
986 struct vattr *a_vap;
987 struct ucred *a_cred;
988 struct thread *a_td;
989 } */ *ap;
990{
991 struct union_node *un = VTOUNION(ap->a_vp);
992 struct thread *td = ap->a_td;
993 struct vattr *vap = ap->a_vap;
994 struct vnode *uppervp;
995 int error;
996
997 /*
998 * Disallow write attempts on filesystems mounted read-only.
999 */
1000 if ((ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) &&
1001 (vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
1002 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
1003 vap->va_mtime.tv_sec != VNOVAL ||
1004 vap->va_mode != (mode_t)VNOVAL)) {
1005 return (EROFS);
1006 }
1007
1008 /*
1009 * Handle case of truncating lower object to zero size
1010 * by creating a zero length upper object. This is to
1011 * handle the case of open with O_TRUNC and O_CREAT.
1012 */
1013 if (un->un_uppervp == NULLVP && (un->un_lowervp->v_type == VREG)) {
1014 error = union_copyup(un, (ap->a_vap->va_size != 0),
1015 ap->a_cred, ap->a_td);
1016 if (error)
1017 return (error);
1018 }
1019
1020 /*
1021 * Try to set attributes in upper layer,
1022 * otherwise return read-only filesystem error.
1023 */
1024 error = EROFS;
1025 if ((uppervp = union_lock_upper(un, td)) != NULLVP) {
1026 error = VOP_SETATTR(un->un_uppervp, ap->a_vap,
1027 ap->a_cred, ap->a_td);
1028 if ((error == 0) && (ap->a_vap->va_size != VNOVAL))
1029 union_newsize(ap->a_vp, ap->a_vap->va_size, VNOVAL);
1030 union_unlock_upper(uppervp, td);
1031 }
1032 return (error);
1033}
1034
1035static int
1036union_read(ap)
1037 struct vop_read_args /* {
1038 struct vnode *a_vp;
1039 struct uio *a_uio;
1040 int a_ioflag;
1041 struct ucred *a_cred;
1042 } */ *ap;
1043{
1044 struct union_node *un = VTOUNION(ap->a_vp);
1045 struct thread *td = ap->a_uio->uio_td;
1046 struct vnode *uvp;
1047 int error;
1048
1049 uvp = union_lock_other(un, td);
1050 KASSERT(uvp != NULL, ("union_read: backing vnode missing!"));
1051
1052 error = VOP_READ(uvp, ap->a_uio, ap->a_ioflag, ap->a_cred);
1053 union_unlock_other(uvp, td);
1054
1055 /*
1056 * XXX
1057 * Perhaps the size of the underlying object has changed under
1058 * our feet. Take advantage of the offset information present
1059 * in the uio structure.
1060 */
1061 if (error == 0) {
1062 struct union_node *un = VTOUNION(ap->a_vp);
1063 off_t cur = ap->a_uio->uio_offset;
1064
1065 if (uvp == un->un_uppervp) {
1066 if (cur > un->un_uppersz)
1067 union_newsize(ap->a_vp, cur, VNOVAL);
1068 } else {
1069 if (cur > un->un_lowersz)
1070 union_newsize(ap->a_vp, VNOVAL, cur);
1071 }
1072 }
1073 return (error);
1074}
1075
1076static int
1077union_write(ap)
1078 struct vop_write_args /* {
1079 struct vnode *a_vp;
1080 struct uio *a_uio;
1081 int a_ioflag;
1082 struct ucred *a_cred;
1083 } */ *ap;
1084{
1085 struct union_node *un = VTOUNION(ap->a_vp);
1086 struct thread *td = ap->a_uio->uio_td;
1087 struct vnode *uppervp;
1088 int error;
1089
1090 if ((uppervp = union_lock_upper(un, td)) == NULLVP)
1091 panic("union: missing upper layer in write");
1092
1093 error = VOP_WRITE(uppervp, ap->a_uio, ap->a_ioflag, ap->a_cred);
1094
1095 /*
1096 * The size of the underlying object may be changed by the
1097 * write.
1098 */
1099 if (error == 0) {
1100 off_t cur = ap->a_uio->uio_offset;
1101
1102 if (cur > un->un_uppersz)
1103 union_newsize(ap->a_vp, cur, VNOVAL);
1104 }
1105 union_unlock_upper(uppervp, td);
1106 return (error);
1107}
1108
1109static int
1110union_lease(ap)
1111 struct vop_lease_args /* {
1112 struct vnode *a_vp;
1113 struct thread *a_td;
1114 struct ucred *a_cred;
1115 int a_flag;
1116 } */ *ap;
1117{
1118 struct vnode *ovp = OTHERVP(ap->a_vp);
1119
1120 ap->a_vp = ovp;
1121 return (VOP_LEASE_AP(ap));
1122}
1123
1124static int
1125union_ioctl(ap)
1126 struct vop_ioctl_args /* {
1127 struct vnode *a_vp;
1128 u_long a_command;
1129 caddr_t a_data;
1130 int a_fflag;
1131 struct ucred *a_cred;
1132 struct thread *a_td;
1133 } */ *ap;
1134{
1135 struct vnode *ovp = OTHERVP(ap->a_vp);
1136
1137 ap->a_vp = ovp;
1138 return (VOP_IOCTL_AP(ap));
1139}
1140
1141static int
1142union_poll(ap)
1143 struct vop_poll_args /* {
1144 struct vnode *a_vp;
1145 int a_events;
1146 struct ucred *a_cred;
1147 struct thread *a_td;
1148 } */ *ap;
1149{
1150 struct vnode *ovp = OTHERVP(ap->a_vp);
1151
1152 ap->a_vp = ovp;
1153 return (VOP_POLL_AP(ap));
1154}
1155
1156static int
1157union_fsync(ap)
1158 struct vop_fsync_args /* {
1159 struct vnode *a_vp;
1160 struct ucred *a_cred;
1161 int a_waitfor;
1162 struct thread *a_td;
1163 } */ *ap;
1164{
1165 int error = 0;
1166 struct thread *td = ap->a_td;
1167 struct vnode *targetvp;
1168 struct union_node *un = VTOUNION(ap->a_vp);
1169
1170 if ((targetvp = union_lock_other(un, td)) != NULLVP) {
1171 error = VOP_FSYNC(targetvp, ap->a_waitfor, td);
1172 union_unlock_other(targetvp, td);
1173 }
1174
1175 return (error);
1176}
1177
1178/*
1179 * union_remove:
1180 *
1181 * Remove the specified cnp. The dvp and vp are passed to us locked
1182 * and must remain locked on return.
1183 */
1184
1185static int
1186union_remove(ap)
1187 struct vop_remove_args /* {
1188 struct vnode *a_dvp;
1189 struct vnode *a_vp;
1190 struct componentname *a_cnp;
1191 } */ *ap;
1192{
1193 struct union_node *dun = VTOUNION(ap->a_dvp);
1194 struct union_node *un = VTOUNION(ap->a_vp);
1195 struct componentname *cnp = ap->a_cnp;
1196 struct thread *td = cnp->cn_thread;
1197 struct vnode *uppervp;
1198 struct vnode *upperdvp;
1199 int error;
1200
1201 if ((upperdvp = union_lock_upper(dun, td)) == NULLVP)
1202 panic("union remove: null upper vnode");
1203
1204 if ((uppervp = union_lock_upper(un, td)) != NULLVP) {
1205 if (union_dowhiteout(un, cnp->cn_cred, td))
1206 cnp->cn_flags |= DOWHITEOUT;
1207 if (cnp->cn_flags & DOWHITEOUT) /* XXX fs corruption */
1208 error = EOPNOTSUPP;
1209 else
1210 error = VOP_REMOVE(upperdvp, uppervp, cnp);
1211 if (!error)
1212 union_removed_upper(un);
1213 union_unlock_upper(uppervp, td);
1214 } else {
1215 error = union_mkwhiteout(
1216 MOUNTTOUNIONMOUNT(ap->a_dvp->v_mount),
1217 upperdvp, ap->a_cnp, un->un_path);
1218 }
1219 union_unlock_upper(upperdvp, td);
1220 return (error);
1221}
1222
1223/*
1224 * union_link:
1225 *
1226 * tdvp and vp will be locked on entry.
1227 * tdvp and vp should remain locked on return.
1228 */
1229
1230static int
1231union_link(ap)
1232 struct vop_link_args /* {
1233 struct vnode *a_tdvp;
1234 struct vnode *a_vp;
1235 struct componentname *a_cnp;
1236 } */ *ap;
1237{
1238 struct componentname *cnp = ap->a_cnp;
1239 struct thread *td = cnp->cn_thread;
1240 struct union_node *dun = VTOUNION(ap->a_tdvp);
1241 struct vnode *vp;
1242 struct vnode *tdvp;
1243 int error = 0;
1244
1245 if (ap->a_tdvp->v_op != ap->a_vp->v_op) {
1246 vp = ap->a_vp;
1247 } else {
1248 struct union_node *tun = VTOUNION(ap->a_vp);
1249
1250 if (tun->un_uppervp == NULLVP) {
1251#if 0
1252 if (dun->un_uppervp == tun->un_dirvp) {
1253 if (dun->un_flags & UN_ULOCK) {
1254 dun->un_flags &= ~UN_ULOCK;
1255 VOP_UNLOCK(dun->un_uppervp, 0, td);
1256 }
1257 }
1258#endif
1259 error = union_copyup(tun, 1, cnp->cn_cred, td);
1260#if 0
1261 if (dun->un_uppervp == tun->un_dirvp) {
1262 vn_lock(dun->un_uppervp,
1263 LK_EXCLUSIVE | LK_RETRY, td);
1264 dun->un_flags |= UN_ULOCK;
1265 }
1266#endif
1267 if (error)
1268 return (error);
1269 }
1270 vp = tun->un_uppervp;
1271 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1272 }
1273
1274 /*
1275 * Make sure upper is locked, then unlock the union directory we were
1276 * called with to avoid a deadlock while we are calling VOP_LINK() on
1277 * the upper (with tdvp locked and vp not locked). Our ap->a_tdvp
1278 * is expected to be locked on return.
1279 */
1280
1281 if ((tdvp = union_lock_upper(dun, td)) == NULLVP)
1282 return (EROFS);
1283
1284 VOP_UNLOCK(ap->a_tdvp, 0, td); /* unlock calling node */
1285 error = VOP_LINK(tdvp, vp, cnp); /* call link on upper */
1286
1287 /*
1288 * Unlock tun->un_uppervp if we locked it above.
1289 */
1290 if (ap->a_tdvp->v_op == ap->a_vp->v_op)
1291 VOP_UNLOCK(vp, 0, td);
1292 /*
1293 * We have to unlock tdvp prior to relocking our calling node in
1294 * order to avoid a deadlock. We also have to unlock ap->a_vp
1295 * before relocking the directory, but then we have to relock
1296 * ap->a_vp as our caller expects.
1297 */
1298 VOP_UNLOCK(ap->a_vp, 0, td);
1299 union_unlock_upper(tdvp, td);
1300 vn_lock(ap->a_tdvp, LK_EXCLUSIVE | LK_RETRY, td);
1301 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, td);
1302 return (error);
1303}
1304
1305static int
1306union_rename(ap)
1307 struct vop_rename_args /* {
1308 struct vnode *a_fdvp;
1309 struct vnode *a_fvp;
1310 struct componentname *a_fcnp;
1311 struct vnode *a_tdvp;
1312 struct vnode *a_tvp;
1313 struct componentname *a_tcnp;
1314 } */ *ap;
1315{
1316 int error;
1317 struct vnode *fdvp = ap->a_fdvp;
1318 struct vnode *fvp = ap->a_fvp;
1319 struct vnode *tdvp = ap->a_tdvp;
1320 struct vnode *tvp = ap->a_tvp;
1321
1322 /*
1323 * Figure out what fdvp to pass to our upper or lower vnode. If we
1324 * replace the fdvp, release the original one and ref the new one.
1325 */
1326
1327 if (fdvp->v_op == &union_vnodeops) { /* always true */
1328 struct union_node *un = VTOUNION(fdvp);
1329 if (un->un_uppervp == NULLVP) {
1330 /*
1331 * this should never happen in normal
1332 * operation but might if there was
1333 * a problem creating the top-level shadow
1334 * directory.
1335 */
1336 error = EXDEV;
1337 goto bad;
1338 }
1339 fdvp = un->un_uppervp;
1340 VREF(fdvp);
1341 vrele(ap->a_fdvp);
1342 }
1343
1344 /*
1345 * Figure out what fvp to pass to our upper or lower vnode. If we
1346 * replace the fvp, release the original one and ref the new one.
1347 */
1348
1349 if (fvp->v_op == &union_vnodeops) { /* always true */
1350 struct union_node *un = VTOUNION(fvp);
1351#if 0
1352 struct union_mount *um = MOUNTTOUNIONMOUNT(fvp->v_mount);
1353#endif
1354
1355 if (un->un_uppervp == NULLVP) {
1356 switch(fvp->v_type) {
1357 case VREG:
1358 vn_lock(un->un_vnode, LK_EXCLUSIVE | LK_RETRY, ap->a_fcnp->cn_thread);
1359 error = union_copyup(un, 1, ap->a_fcnp->cn_cred, ap->a_fcnp->cn_thread);
1360 VOP_UNLOCK(un->un_vnode, 0, ap->a_fcnp->cn_thread);
1361 if (error)
1362 goto bad;
1363 break;
1364 case VDIR:
1365 /*
1366 * XXX not yet.
1367 *
1368 * There is only one way to rename a directory
1369 * based in the lowervp, and that is to copy
1370 * the entire directory hierarchy. Otherwise
1371 * it would not last across a reboot.
1372 */
1373#if 0
1374 vrele(fvp);
1375 fvp = NULL;
1376 vn_lock(fdvp, LK_EXCLUSIVE | LK_RETRY, ap->a_fcnp->cn_thread);
1377 error = union_mkshadow(um, fdvp,
1378 ap->a_fcnp, &un->un_uppervp);
1379 VOP_UNLOCK(fdvp, 0, ap->a_fcnp->cn_thread);
1380 if (un->un_uppervp)
1381 VOP_UNLOCK(un->un_uppervp, 0, ap->a_fcnp->cn_thread);
1382 if (error)
1383 goto bad;
1384 break;
1385#endif
1386 default:
1387 error = EXDEV;
1388 goto bad;
1389 }
1390 }
1391
1392 if (un->un_lowervp != NULLVP)
1393 ap->a_fcnp->cn_flags |= DOWHITEOUT;
1394 fvp = un->un_uppervp;
1395 VREF(fvp);
1396 vrele(ap->a_fvp);
1397 }
1398
1399 /*
1400 * Figure out what tdvp (destination directory) to pass to the
1401 * lower level. If we replace it with uppervp, we need to vput the
1402 * old one. The exclusive lock is transfered to what we will pass
1403 * down in the VOP_RENAME() and we replace uppervp with a simple
1404 * reference.
1405 */
1406
1407 if (tdvp->v_op == &union_vnodeops) {
1408 struct union_node *un = VTOUNION(tdvp);
1409
1410 if (un->un_uppervp == NULLVP) {
1411 /*
1412 * This should never happen in normal
1413 * operation but might if there was
1414 * a problem creating the top-level shadow
1415 * directory.
1416 */
1417 error = EXDEV;
1418 goto bad;
1419 }
1420
1421 /*
1422 * New tdvp is a lock and reference on uppervp.
1423 * Put away the old tdvp.
1424 */
1425 tdvp = union_lock_upper(un, ap->a_tcnp->cn_thread);
1426 vput(ap->a_tdvp);
1427 }
1428
1429 /*
1430 * Figure out what tvp (destination file) to pass to the
1431 * lower level.
1432 *
1433 * If the uppervp file does not exist, put away the (wrong)
1434 * file and change tvp to NULL.
1435 */
1436
1437 if (tvp != NULLVP && tvp->v_op == &union_vnodeops) {
1438 struct union_node *un = VTOUNION(tvp);
1439
1440 tvp = union_lock_upper(un, ap->a_tcnp->cn_thread);
1441 vput(ap->a_tvp);
1442 /* note: tvp may be NULL */
1443 }
1444
1445 /*
1446 * VOP_RENAME() releases/vputs prior to returning, so we have no
1447 * cleanup to do.
1448 */
1449
1450 return (VOP_RENAME(fdvp, fvp, ap->a_fcnp, tdvp, tvp, ap->a_tcnp));
1451
1452 /*
1453 * Error. We still have to release / vput the various elements.
1454 */
1455
1456bad:
1457 vrele(fdvp);
1458 if (fvp)
1459 vrele(fvp);
1460 vput(tdvp);
1461 if (tvp != NULLVP) {
1462 if (tvp != tdvp)
1463 vput(tvp);
1464 else
1465 vrele(tvp);
1466 }
1467 return (error);
1468}
1469
1470static int
1471union_mkdir(ap)
1472 struct vop_mkdir_args /* {
1473 struct vnode *a_dvp;
1474 struct vnode **a_vpp;
1475 struct componentname *a_cnp;
1476 struct vattr *a_vap;
1477 } */ *ap;
1478{
1479 struct union_node *dun = VTOUNION(ap->a_dvp);
1480 struct componentname *cnp = ap->a_cnp;
1481 struct thread *td = cnp->cn_thread;
1482 struct vnode *upperdvp;
1483 int error = EROFS;
1484
1485 if ((upperdvp = union_lock_upper(dun, td)) != NULLVP) {
1486 struct vnode *vp;
1487
1488 error = VOP_MKDIR(upperdvp, &vp, cnp, ap->a_vap);
1489 union_unlock_upper(upperdvp, td);
1490
1491 if (error == 0) {
1492 VOP_UNLOCK(vp, 0, td);
1493 UDEBUG(("ALLOCVP-2 FROM %p REFS %d\n", vp, vrefcnt(vp)));
1494 error = union_allocvp(ap->a_vpp, ap->a_dvp->v_mount,
1495 ap->a_dvp, NULLVP, cnp, vp, NULLVP, 1);
1496 UDEBUG(("ALLOCVP-2B FROM %p REFS %d\n", *ap->a_vpp, vrefcnt(vp)));
1497 }
1498 }
1499 return (error);
1500}
1501
1502static int
1503union_rmdir(ap)
1504 struct vop_rmdir_args /* {
1505 struct vnode *a_dvp;
1506 struct vnode *a_vp;
1507 struct componentname *a_cnp;
1508 } */ *ap;
1509{
1510 struct union_node *dun = VTOUNION(ap->a_dvp);
1511 struct union_node *un = VTOUNION(ap->a_vp);
1512 struct componentname *cnp = ap->a_cnp;
1513 struct thread *td = cnp->cn_thread;
1514 struct vnode *upperdvp;
1515 struct vnode *uppervp;
1516 int error;
1517
1518 if ((upperdvp = union_lock_upper(dun, td)) == NULLVP)
1519 panic("union rmdir: null upper vnode");
1520
1521 if ((uppervp = union_lock_upper(un, td)) != NULLVP) {
1522 if (union_dowhiteout(un, cnp->cn_cred, td))
1523 cnp->cn_flags |= DOWHITEOUT;
1524 if (cnp->cn_flags & DOWHITEOUT) /* XXX fs corruption */
1525 error = EOPNOTSUPP;
1526 else
1527 error = VOP_RMDIR(upperdvp, uppervp, ap->a_cnp);
1528 if (!error)
1529 union_removed_upper(un);
1530 union_unlock_upper(uppervp, td);
1531 } else {
1532 error = union_mkwhiteout(
1533 MOUNTTOUNIONMOUNT(ap->a_dvp->v_mount),
1534 dun->un_uppervp, ap->a_cnp, un->un_path);
1535 }
1536 union_unlock_upper(upperdvp, td);
1537 return (error);
1538}
1539
1540/*
1541 * union_symlink:
1542 *
1543 * dvp is locked on entry and remains locked on return. a_vpp is garbage
1544 * (unused).
1545 */
1546
1547static int
1548union_symlink(ap)
1549 struct vop_symlink_args /* {
1550 struct vnode *a_dvp;
1551 struct vnode **a_vpp;
1552 struct componentname *a_cnp;
1553 struct vattr *a_vap;
1554 char *a_target;
1555 } */ *ap;
1556{
1557 struct union_node *dun = VTOUNION(ap->a_dvp);
1558 struct componentname *cnp = ap->a_cnp;
1559 struct thread *td = cnp->cn_thread;
1560 struct vnode *dvp;
1561 int error = EROFS;
1562
1563 if ((dvp = union_lock_upper(dun, td)) != NULLVP) {
1564 error = VOP_SYMLINK(dvp, ap->a_vpp, cnp, ap->a_vap,
1565 ap->a_target);
1566 union_unlock_upper(dvp, td);
1567 }
1568 return (error);
1569}
1570
1571/*
1572 * union_readdir ()works in concert with getdirentries() and
1573 * readdir(3) to provide a list of entries in the unioned
1574 * directories. getdirentries() is responsible for walking
1575 * down the union stack. readdir(3) is responsible for
1576 * eliminating duplicate names from the returned data stream.
1577 */
1578static int
1579union_readdir(ap)
1580 struct vop_readdir_args /* {
1581 struct vnode *a_vp;
1582 struct uio *a_uio;
1583 struct ucred *a_cred;
1584 int *a_eofflag;
1585 u_long *a_cookies;
1586 int a_ncookies;
1587 } */ *ap;
1588{
1589 struct union_node *un = VTOUNION(ap->a_vp);
1590 struct thread *td = ap->a_uio->uio_td;
1591 struct vnode *uvp;
1592 int error = 0;
1593
1594 if ((uvp = union_lock_upper(un, td)) != NULLVP) {
1595 ap->a_vp = uvp;
1596 error = VOP_READDIR_AP(ap);
1597 union_unlock_upper(uvp, td);
1598 }
1599 return(error);
1600}
1601
1602static int
1603union_readlink(ap)
1604 struct vop_readlink_args /* {
1605 struct vnode *a_vp;
1606 struct uio *a_uio;
1607 struct ucred *a_cred;
1608 } */ *ap;
1609{
1610 int error;
1611 struct union_node *un = VTOUNION(ap->a_vp);
1612 struct uio *uio = ap->a_uio;
1613 struct thread *td = uio->uio_td;
1614 struct vnode *vp;
1615
1616 vp = union_lock_other(un, td);
1617 KASSERT(vp != NULL, ("union_readlink: backing vnode missing!"));
1618
1619 ap->a_vp = vp;
1620 error = VOP_READLINK_AP(ap);
1621 union_unlock_other(vp, td);
1622
1623 return (error);
1624}
1625
1626static int
1627union_getwritemount(ap)
1628 struct vop_getwritemount_args /* {
1629 struct vnode *a_vp;
1630 struct mount **a_mpp;
1631 } */ *ap;
1632{
1633 struct vnode *vp = ap->a_vp;
1634 struct vnode *uvp = UPPERVP(vp);
1635
1636 if (uvp == NULL) {
1637 VI_LOCK(vp);
1638 if (vp->v_iflag & VI_FREE) {
1639 VI_UNLOCK(vp);
1640 return (EOPNOTSUPP);
1641 }
1642 VI_UNLOCK(vp);
1643 return (EACCES);
1644 }
1645 return(VOP_GETWRITEMOUNT(uvp, ap->a_mpp));
1646}
1647
1648/*
1649 * union_inactive:
1650 *
1651 * Called with the vnode locked. We are expected to unlock the vnode.
1652 */
1653
1654static int
1655union_inactive(ap)
1656 struct vop_inactive_args /* {
1657 struct vnode *a_vp;
1658 struct thread *a_td;
1659 } */ *ap;
1660{
1661 struct vnode *vp = ap->a_vp;
1662 struct thread *td = ap->a_td;
1663 struct union_node *un = VTOUNION(vp);
1664
1665 /*
1666 * Do nothing (and _don't_ bypass).
1667 * Wait to vrele lowervp until reclaim,
1668 * so that until then our union_node is in the
1669 * cache and reusable.
1670 *
1671 */
1672
1673 if (un->un_dircache != NULL)
1674 union_dircache_free(un);
1675
1676#if 0
1677 if ((un->un_flags & UN_ULOCK) && un->un_uppervp) {
1678 un->un_flags &= ~UN_ULOCK;
1679 VOP_UNLOCK(un->un_uppervp, 0, td);
1680 }
1681#endif
1682
1683 VOP_UNLOCK(vp, 0, td);
1684
1685 if ((un->un_flags & UN_CACHED) == 0)
1686 vgone(vp);
1687
1688 return (0);
1689}
1690
1691static int
1692union_reclaim(ap)
1693 struct vop_reclaim_args /* {
1694 struct vnode *a_vp;
1695 } */ *ap;
1696{
1697 union_freevp(ap->a_vp);
1698
1699 return (0);
1700}
1701
1702/*
1703 * unionvp do not hold a VM object and there is no need to create one for
1704 * upper or lower vp because it is done in the union_open()
1705 */
1706static int
1707union_createvobject(ap)
1708 struct vop_createvobject_args /* {
1709 struct vnode *vp;
1710 struct ucred *cred;
1711 struct thread *td;
1712 } */ *ap;
1713{
1714 struct vnode *vp = ap->a_vp;
1715
1716 vp->v_vflag |= VV_OBJBUF;
1717 return (0);
1718}
1719
1720/*
1721 * We have nothing to destroy and this operation shouldn't be bypassed.
1722 */
1723static int
1724union_destroyvobject(ap)
1725 struct vop_destroyvobject_args /* {
1726 struct vnode *vp;
1727 } */ *ap;
1728{
1729 struct vnode *vp = ap->a_vp;
1730
1731 vp->v_vflag &= ~VV_OBJBUF;
1732 return (0);
1733}
1734
1735/*
1736 * Get VM object from the upper or lower vp
1737 */
1738static int
1739union_getvobject(ap)
1740 struct vop_getvobject_args /* {
1741 struct vnode *vp;
1742 struct vm_object **objpp;
1743 } */ *ap;
1744{
1745 struct vnode *ovp = OTHERVP(ap->a_vp);
1746
1747 if (ovp == NULL)
1748 return EINVAL;
1749 return (VOP_GETVOBJECT(ovp, ap->a_objpp));
1750}
1751
1752static int
1753union_print(ap)
1754 struct vop_print_args /* {
1755 struct vnode *a_vp;
1756 } */ *ap;
1757{
1758 struct vnode *vp = ap->a_vp;
1759
1760 printf("\tvp=%p, uppervp=%p, lowervp=%p\n",
1761 vp, UPPERVP(vp), LOWERVP(vp));
1762 if (UPPERVP(vp) != NULLVP)
1763 vprint("union: upper", UPPERVP(vp));
1764 if (LOWERVP(vp) != NULLVP)
1765 vprint("union: lower", LOWERVP(vp));
1766
1767 return (0);
1768}
1769
1770static int
1771union_pathconf(ap)
1772 struct vop_pathconf_args /* {
1773 struct vnode *a_vp;
1774 int a_name;
1775 int *a_retval;
1776 } */ *ap;
1777{
1778 int error;
1779 struct thread *td = curthread; /* XXX */
1780 struct union_node *un = VTOUNION(ap->a_vp);
1781 struct vnode *vp;
1782
1783 vp = union_lock_other(un, td);
1784 KASSERT(vp != NULL, ("union_pathconf: backing vnode missing!"));
1785
1786 ap->a_vp = vp;
1787 error = VOP_PATHCONF_AP(ap);
1788 union_unlock_other(vp, td);
1789
1790 return (error);
1791}
1792
1793static int
1794union_advlock(ap)
1795 struct vop_advlock_args /* {
1796 struct vnode *a_vp;
1797 caddr_t a_id;
1798 int a_op;
1799 struct flock *a_fl;
1800 int a_flags;
1801 } */ *ap;
1802{
1803 register struct vnode *ovp = OTHERVP(ap->a_vp);
1804
1805 ap->a_vp = ovp;
1806 return (VOP_ADVLOCK_AP(ap));
1807}
1808
1809
1810/*
1811 * XXX - vop_strategy must be hand coded because it has no
1812 * YYY - and it is not coherent with anything
1813 *
1814 * vnode in its arguments.
1815 * This goes away with a merged VM/buffer cache.
1816 */
1817static int
1818union_strategy(ap)
1819 struct vop_strategy_args /* {
1820 struct vnode *a_vp;
1821 struct buf *a_bp;
1822 } */ *ap;
1823{
1824 struct buf *bp = ap->a_bp;
1825 struct vnode *othervp = OTHERVP(ap->a_vp);
1826
1827#ifdef DIAGNOSTIC
1828 if (othervp == NULLVP)
1829 panic("union_strategy: nil vp");
1830 if ((bp->b_iocmd == BIO_WRITE) &&
1831 (othervp == LOWERVP(ap->a_vp)))
1832 panic("union_strategy: writing to lowervp");
1833#endif
1834 return (VOP_STRATEGY(othervp, bp));
1835}
1836
1837static int
1838union_getacl(ap)
1839 struct vop_getacl_args /* {
1840 struct vnode *a_vp;
1841 acl_type_t a_type;
1842 struct acl *a_aclp;
1843 struct ucred *a_cred;
1844 struct thread *a_td;
1845 } */ *ap;
1846{
1847 int error;
1848 struct union_node *un = VTOUNION(ap->a_vp);
1849 struct vnode *vp;
1850
1851 vp = union_lock_other(un, ap->a_td);
1852 ap->a_vp = vp;
1853 error = VOP_GETACL_AP(ap);
1854 union_unlock_other(vp, ap->a_td);
1855
1856 return (error);
1857}
1858
1859static int
1860union_setacl(ap)
1861 struct vop_setacl_args /* {
1862 struct vnode *a_vp;
1863 acl_type_t a_type;
1864 struct acl *a_aclp;
1865 struct ucred *a_cred;
1866 struct thread *a_td;
1867 } */ *ap;
1868{
1869 int error;
1870 struct union_node *un = VTOUNION(ap->a_vp);
1871 struct vnode *vp;
1872
1873 vp = union_lock_other(un, ap->a_td);
1874 ap->a_vp = vp;
1875 error = VOP_SETACL_AP(ap);
1876 union_unlock_other(vp, ap->a_td);
1877
1878 return (error);
1879}
1880
1881static int
1882union_aclcheck(ap)
1883 struct vop_aclcheck_args /* {
1884 struct vnode *a_vp;
1885 acl_type_t a_type;
1886 struct acl *a_aclp;
1887 struct ucred *a_cred;
1888 struct thread *a_td;
1889 } */ *ap;
1890{
1891 struct vnode *ovp = OTHERVP(ap->a_vp);
1892
1893 ap->a_vp = ovp;
1894 return (VOP_ACLCHECK_AP(ap));
1895}
1896
1897static int
1898union_closeextattr(ap)
1899 struct vop_closeextattr_args /* {
1900 struct vnode *a_vp;
1901 int a_commit;
1902 struct ucred *a_cred;
1903 struct thread *a_td;
1904 } */ *ap;
1905{
1906 int error;
1907 struct union_node *un = VTOUNION(ap->a_vp);
1908 struct vnode *vp;
1909
1910 vp = union_lock_other(un, ap->a_td);
1911 ap->a_vp = vp;
1912 error = VOP_CLOSEEXTATTR_AP(ap);
1913 union_unlock_other(vp, ap->a_td);
1914
1915 return (error);
1916}
1917
1918static int
1919union_getextattr(ap)
1920 struct vop_getextattr_args /* {
1921 struct vnode *a_vp;
1922 int a_attrnamespace;
1923 const char *a_name;
1924 struct uio *a_uio;
1925 size_t *a_size;
1926 struct ucred *a_cred;
1927 struct thread *a_td;
1928 } */ *ap;
1929{
1930 int error;
1931 struct union_node *un = VTOUNION(ap->a_vp);
1932 struct vnode *vp;
1933
1934 vp = union_lock_other(un, ap->a_td);
1935 ap->a_vp = vp;
1936 error = VOP_GETEXTATTR_AP(ap);
1937 union_unlock_other(vp, ap->a_td);
1938
1939 return (error);
1940}
1941
1942static int
1943union_listextattr(ap)
1944 struct vop_listextattr_args /* {
1945 struct vnode *a_vp;
1946 int a_attrnamespace;
1947 struct uio *a_uio;
1948 size_t *a_size;
1949 struct ucred *a_cred;
1950 struct thread *a_td;
1951 } */ *ap;
1952{
1953 int error;
1954 struct union_node *un = VTOUNION(ap->a_vp);
1955 struct vnode *vp;
1956
1957 vp = union_lock_other(un, ap->a_td);
1958 ap->a_vp = vp;
1959 error = VOP_LISTEXTATTR_AP(ap);
1960 union_unlock_other(vp, ap->a_td);
1961
1962 return (error);
1963}
1964
1965static int
1966union_openextattr(ap)
1967 struct vop_openextattr_args /* {
1968 struct vnode *a_vp;
1969 struct ucred *a_cred;
1970 struct thread *a_td;
1971 } */ *ap;
1972{
1973 int error;
1974 struct union_node *un = VTOUNION(ap->a_vp);
1975 struct vnode *vp;
1976
1977 vp = union_lock_other(un, ap->a_td);
1978 ap->a_vp = vp;
1979 error = VOP_OPENEXTATTR_AP(ap);
1980 union_unlock_other(vp, ap->a_td);
1981
1982 return (error);
1983}
1984
1985static int
1986union_deleteextattr(ap)
1987 struct vop_deleteextattr_args /* {
1988 struct vnode *a_vp;
1989 int a_attrnamespace;
1990 const char *a_name;
1991 struct ucred *a_cred;
1992 struct thread *a_td;
1993 } */ *ap;
1994{
1995 int error;
1996 struct union_node *un = VTOUNION(ap->a_vp);
1997 struct vnode *vp;
1998
1999 vp = union_lock_other(un, ap->a_td);
2000 ap->a_vp = vp;
2001 error = VOP_DELETEEXTATTR_AP(ap);
2002 union_unlock_other(vp, ap->a_td);
2003
2004 return (error);
2005}
2006
2007static int
2008union_setextattr(ap)
2009 struct vop_setextattr_args /* {
2010 struct vnode *a_vp;
2011 int a_attrnamespace;
2012 const char *a_name;
2013 struct uio *a_uio;
2014 struct ucred *a_cred;
2015 struct thread *a_td;
2016 } */ *ap;
2017{
2018 int error;
2019 struct union_node *un = VTOUNION(ap->a_vp);
2020 struct vnode *vp;
2021
2022 vp = union_lock_other(un, ap->a_td);
2023 ap->a_vp = vp;
2024 error = VOP_SETEXTATTR_AP(ap);
2025 union_unlock_other(vp, ap->a_td);
2026
2027 return (error);
2028}
2029
2030static int
2031union_setlabel(ap)
2032 struct vop_setlabel_args /* {
2033 struct vnode *a_vp;
2034 struct label *a_label;
2035 struct ucred *a_cred;
2036 struct thread *a_td;
2037 } */ *ap;
2038{
2039 int error;
2040 struct union_node *un = VTOUNION(ap->a_vp);
2041 struct vnode *vp;
2042
2043 vp = union_lock_other(un, ap->a_td);
2044 ap->a_vp = vp;
2045 error = VOP_SETLABEL_AP(ap);
2046 union_unlock_other(vp, ap->a_td);
2047
2048 return (error);
2049}
2050
2051/*
2052 * Global vfs data structures
2053 */
2054struct vop_vector union_vnodeops = {
2055 .vop_default = &default_vnodeops,
35 */
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/fcntl.h>
40#include <sys/stat.h>
41#include <sys/kernel.h>
42#include <sys/vnode.h>
43#include <sys/mount.h>
44#include <sys/namei.h>
45#include <sys/malloc.h>
46#include <sys/bio.h>
47#include <sys/buf.h>
48#include <sys/lock.h>
49#include <sys/sysctl.h>
50#include <sys/unistd.h>
51#include <sys/acl.h>
52#include <sys/event.h>
53#include <sys/extattr.h>
54#include <sys/mac.h>
55#include <fs/unionfs/union.h>
56
57#include <vm/vm.h>
58#include <vm/vnode_pager.h>
59
60#include <vm/vm_page.h>
61#include <vm/vm_object.h>
62
63int uniondebug = 0;
64
65#if UDEBUG_ENABLED
66SYSCTL_INT(_vfs, OID_AUTO, uniondebug, CTLFLAG_RW, &uniondebug, 0, "");
67#else
68SYSCTL_INT(_vfs, OID_AUTO, uniondebug, CTLFLAG_RD, &uniondebug, 0, "");
69#endif
70
71static vop_access_t union_access;
72static vop_aclcheck_t union_aclcheck;
73static vop_advlock_t union_advlock;
74static vop_close_t union_close;
75static vop_closeextattr_t union_closeextattr;
76static vop_create_t union_create;
77static vop_createvobject_t union_createvobject;
78static vop_deleteextattr_t union_deleteextattr;
79static vop_destroyvobject_t union_destroyvobject;
80static vop_fsync_t union_fsync;
81static vop_getacl_t union_getacl;
82static vop_getattr_t union_getattr;
83static vop_getextattr_t union_getextattr;
84static vop_getvobject_t union_getvobject;
85static vop_inactive_t union_inactive;
86static vop_ioctl_t union_ioctl;
87static vop_lease_t union_lease;
88static vop_link_t union_link;
89static vop_listextattr_t union_listextattr;
90static vop_lookup_t union_lookup;
91static int union_lookup1(struct vnode *udvp, struct vnode **dvp,
92 struct vnode **vpp,
93 struct componentname *cnp);
94static vop_mkdir_t union_mkdir;
95static vop_mknod_t union_mknod;
96static vop_open_t union_open;
97static vop_openextattr_t union_openextattr;
98static vop_pathconf_t union_pathconf;
99static vop_print_t union_print;
100static vop_read_t union_read;
101static vop_readdir_t union_readdir;
102static vop_readlink_t union_readlink;
103static vop_getwritemount_t union_getwritemount;
104static vop_reclaim_t union_reclaim;
105static vop_remove_t union_remove;
106static vop_rename_t union_rename;
107static vop_rmdir_t union_rmdir;
108static vop_poll_t union_poll;
109static vop_setacl_t union_setacl;
110static vop_setattr_t union_setattr;
111static vop_setlabel_t union_setlabel;
112static vop_setextattr_t union_setextattr;
113static vop_strategy_t union_strategy;
114static vop_symlink_t union_symlink;
115static vop_whiteout_t union_whiteout;
116static vop_write_t union_write;
117
118static __inline
119struct vnode *
120union_lock_upper(struct union_node *un, struct thread *td)
121{
122 struct vnode *uppervp;
123
124 if ((uppervp = un->un_uppervp) != NULL) {
125 VREF(uppervp);
126 vn_lock(uppervp, LK_EXCLUSIVE | LK_CANRECURSE | LK_RETRY, td);
127 }
128 KASSERT((uppervp == NULL || vrefcnt(uppervp) > 0), ("uppervp usecount is 0"));
129 return(uppervp);
130}
131
132static __inline
133void
134union_unlock_upper(struct vnode *uppervp, struct thread *td)
135{
136 vput(uppervp);
137}
138
139static __inline
140struct vnode *
141union_lock_other(struct union_node *un, struct thread *td)
142{
143 struct vnode *vp;
144
145 if (un->un_uppervp != NULL) {
146 vp = union_lock_upper(un, td);
147 } else if ((vp = un->un_lowervp) != NULL) {
148 VREF(vp);
149 vn_lock(vp, LK_EXCLUSIVE | LK_CANRECURSE | LK_RETRY, td);
150 }
151 return(vp);
152}
153
154static __inline
155void
156union_unlock_other(struct vnode *vp, struct thread *td)
157{
158 vput(vp);
159}
160
161/*
162 * union_lookup:
163 *
164 * udvp must be exclusively locked on call and will remain
165 * exclusively locked on return. This is the mount point
166 * for our filesystem.
167 *
168 * dvp Our base directory, locked and referenced.
169 * The passed dvp will be dereferenced and unlocked on return
170 * and a new dvp will be returned which is locked and
171 * referenced in the same variable.
172 *
173 * vpp is filled in with the result if no error occured,
174 * locked and ref'd.
175 *
176 * If an error is returned, *vpp is set to NULLVP. If no
177 * error occurs, *vpp is returned with a reference and an
178 * exclusive lock.
179 */
180
181static int
182union_lookup1(udvp, pdvp, vpp, cnp)
183 struct vnode *udvp;
184 struct vnode **pdvp;
185 struct vnode **vpp;
186 struct componentname *cnp;
187{
188 int error;
189 struct thread *td = cnp->cn_thread;
190 struct vnode *dvp = *pdvp;
191 struct vnode *tdvp;
192 struct mount *mp;
193
194 /*
195 * If stepping up the directory tree, check for going
196 * back across the mount point, in which case do what
197 * lookup would do by stepping back down the mount
198 * hierarchy.
199 */
200 if (cnp->cn_flags & ISDOTDOT) {
201 while ((dvp != udvp) && (dvp->v_vflag & VV_ROOT)) {
202 /*
203 * Don't do the NOCROSSMOUNT check
204 * at this level. By definition,
205 * union fs deals with namespaces, not
206 * filesystems.
207 */
208 tdvp = dvp;
209 dvp = dvp->v_mount->mnt_vnodecovered;
210 VREF(dvp);
211 vput(tdvp);
212 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
213 }
214 }
215
216 /*
217 * Set return dvp to be the upperdvp 'parent directory.
218 */
219 *pdvp = dvp;
220
221 /*
222 * If the VOP_LOOKUP() call generates an error, tdvp is invalid and
223 * no changes will have been made to dvp, so we are set to return.
224 */
225
226 error = VOP_LOOKUP(dvp, &tdvp, cnp);
227 if (error) {
228 UDEBUG(("dvp %p error %d flags %lx\n", dvp, error, cnp->cn_flags));
229 *vpp = NULL;
230 return (error);
231 }
232
233 /*
234 * The parent directory will have been unlocked, unless lookup
235 * found the last component or if dvp == tdvp (tdvp must be locked).
236 *
237 * We want our dvp to remain locked and ref'd. We also want tdvp
238 * to remain locked and ref'd.
239 */
240 UDEBUG(("parentdir %p result %p flag %lx\n", dvp, tdvp, cnp->cn_flags));
241
242 if (dvp != tdvp && (cnp->cn_flags & ISLASTCN) == 0)
243 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
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 * We use dvp as a temporary variable here, it is no longer related
251 * to the dvp above. However, we have to ensure that both *pdvp and
252 * tdvp are locked on return.
253 */
254
255 dvp = tdvp;
256 while (
257 dvp != udvp &&
258 (dvp->v_type == VDIR) &&
259 (mp = dvp->v_mountedhere)
260 ) {
261 int relock_pdvp = 0;
262
263 if (vfs_busy(mp, 0, 0, td))
264 continue;
265
266 if (dvp == *pdvp)
267 relock_pdvp = 1;
268 vput(dvp);
269 dvp = NULL;
270 error = VFS_ROOT(mp, &dvp, td);
271
272 vfs_unbusy(mp, td);
273
274 if (relock_pdvp)
275 vn_lock(*pdvp, LK_EXCLUSIVE | LK_RETRY, td);
276
277 if (error) {
278 *vpp = NULL;
279 return (error);
280 }
281 }
282 *vpp = dvp;
283 return (0);
284}
285
286static int
287union_lookup(ap)
288 struct vop_lookup_args /* {
289 struct vnodeop_desc *a_desc;
290 struct vnode *a_dvp;
291 struct vnode **a_vpp;
292 struct componentname *a_cnp;
293 } */ *ap;
294{
295 int error;
296 int uerror, lerror;
297 struct vnode *uppervp, *lowervp;
298 struct vnode *upperdvp, *lowerdvp;
299 struct vnode *dvp = ap->a_dvp; /* starting dir */
300 struct union_node *dun = VTOUNION(dvp); /* associated union node */
301 struct componentname *cnp = ap->a_cnp;
302 struct thread *td = cnp->cn_thread;
303 int lockparent = cnp->cn_flags & LOCKPARENT;
304 struct union_mount *um = MOUNTTOUNIONMOUNT(dvp->v_mount);
305 struct ucred *saved_cred = NULL;
306 int iswhiteout;
307 struct vattr va;
308
309 *ap->a_vpp = NULLVP;
310
311 /*
312 * Disallow write attempts to the filesystem mounted read-only.
313 */
314 if ((cnp->cn_flags & ISLASTCN) &&
315 (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
316 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
317 return (EROFS);
318 }
319
320 /*
321 * For any lookups we do, always return with the parent locked.
322 */
323 cnp->cn_flags |= LOCKPARENT;
324
325 lowerdvp = dun->un_lowervp;
326 uppervp = NULLVP;
327 lowervp = NULLVP;
328 iswhiteout = 0;
329
330 uerror = ENOENT;
331 lerror = ENOENT;
332
333 /*
334 * Get a private lock on uppervp and a reference, effectively
335 * taking it out of the union_node's control.
336 *
337 * We must lock upperdvp while holding our lock on dvp
338 * to avoid a deadlock.
339 */
340 upperdvp = union_lock_upper(dun, td);
341
342 /*
343 * Do the lookup in the upper level.
344 * If that level consumes additional pathnames,
345 * then assume that something special is going
346 * on and just return that vnode.
347 */
348 if (upperdvp != NULLVP) {
349 /*
350 * We do not have to worry about the DOTDOT case, we've
351 * already unlocked dvp.
352 */
353 UDEBUG(("A %p\n", upperdvp));
354
355 /*
356 * Do the lookup. We must supply a locked and referenced
357 * upperdvp to the function and will get a new locked and
358 * referenced upperdvp back, with the old having been
359 * dereferenced.
360 *
361 * If an error is returned, uppervp will be NULLVP. If no
362 * error occurs, uppervp will be the locked and referenced.
363 * Return vnode, or possibly NULL, depending on what is being
364 * requested. It is possible that the returned uppervp
365 * will be the same as upperdvp.
366 */
367 uerror = union_lookup1(um->um_uppervp, &upperdvp, &uppervp, cnp);
368 UDEBUG((
369 "uerror %d upperdvp %p %d/%d, uppervp %p ref=%d/lck=%d\n",
370 uerror,
371 upperdvp,
372 vrefcnt(upperdvp),
373 VOP_ISLOCKED(upperdvp, NULL),
374 uppervp,
375 (uppervp ? vrefcnt(uppervp) : -99),
376 (uppervp ? VOP_ISLOCKED(uppervp, NULL) : -99)
377 ));
378
379 /*
380 * Disallow write attempts to the filesystem mounted read-only.
381 */
382 if (uerror == EJUSTRETURN && (cnp->cn_flags & ISLASTCN) &&
383 (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
384 (cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME)) {
385 error = EROFS;
386 goto out;
387 }
388
389 /*
390 * Special case: If cn_consume != 0 then skip out. The result
391 * of the lookup is transfered to our return variable. If
392 * an error occured we have to throw away the results.
393 */
394
395 if (cnp->cn_consume != 0) {
396 if ((error = uerror) == 0) {
397 *ap->a_vpp = uppervp;
398 uppervp = NULL;
399 }
400 goto out;
401 }
402
403 /*
404 * Calculate whiteout, fall through.
405 */
406
407 if (uerror == ENOENT || uerror == EJUSTRETURN) {
408 if (cnp->cn_flags & ISWHITEOUT) {
409 iswhiteout = 1;
410 } else if (lowerdvp != NULLVP) {
411 int terror;
412
413 terror = VOP_GETATTR(upperdvp, &va,
414 cnp->cn_cred, cnp->cn_thread);
415 if (terror == 0 && (va.va_flags & OPAQUE))
416 iswhiteout = 1;
417 }
418 }
419 }
420
421 /*
422 * In a similar way to the upper layer, do the lookup
423 * in the lower layer. This time, if there is some
424 * component magic going on, then vput whatever we got
425 * back from the upper layer and return the lower vnode
426 * instead.
427 */
428
429 if (lowerdvp != NULLVP && !iswhiteout) {
430 int nameiop;
431
432 UDEBUG(("B %p\n", lowerdvp));
433
434 /*
435 * Force only LOOKUPs on the lower node, since
436 * we won't be making changes to it anyway.
437 */
438 nameiop = cnp->cn_nameiop;
439 cnp->cn_nameiop = LOOKUP;
440 if (um->um_op == UNMNT_BELOW) {
441 saved_cred = cnp->cn_cred;
442 cnp->cn_cred = um->um_cred;
443 }
444
445 /*
446 * We shouldn't have to worry about locking interactions
447 * between the lower layer and our union layer (w.r.t.
448 * `..' processing) because we don't futz with lowervp
449 * locks in the union-node instantiation code path.
450 *
451 * union_lookup1() requires lowervp to be locked on entry,
452 * and it will be unlocked on return. The ref count will
453 * not change. On return lowervp doesn't represent anything
454 * to us so we NULL it out.
455 */
456 VREF(lowerdvp);
457 vn_lock(lowerdvp, LK_EXCLUSIVE | LK_RETRY, td);
458 lerror = union_lookup1(um->um_lowervp, &lowerdvp, &lowervp, cnp);
459 if (lowerdvp == lowervp)
460 vrele(lowerdvp);
461 else
462 vput(lowerdvp);
463 lowerdvp = NULL; /* lowerdvp invalid after vput */
464
465 if (um->um_op == UNMNT_BELOW)
466 cnp->cn_cred = saved_cred;
467 cnp->cn_nameiop = nameiop;
468
469 if (cnp->cn_consume != 0 || lerror == EACCES) {
470 if ((error = lerror) == 0) {
471 *ap->a_vpp = lowervp;
472 lowervp = NULL;
473 }
474 goto out;
475 }
476 } else {
477 UDEBUG(("C %p\n", lowerdvp));
478 if ((cnp->cn_flags & ISDOTDOT) && dun->un_pvp != NULLVP) {
479 if ((lowervp = LOWERVP(dun->un_pvp)) != NULL) {
480 VREF(lowervp);
481 vn_lock(lowervp, LK_EXCLUSIVE | LK_RETRY, td);
482 lerror = 0;
483 }
484 }
485 }
486
487 /*
488 * Ok. Now we have uerror, uppervp, upperdvp, lerror, and lowervp.
489 *
490 * 1. If both layers returned an error, select the upper layer.
491 *
492 * 2. If the upper layer failed and the bottom layer succeeded,
493 * two subcases occur:
494 *
495 * a. The bottom vnode is not a directory, in which case
496 * just return a new union vnode referencing an
497 * empty top layer and the existing bottom layer.
498 *
499 * b. The bottom vnode is a directory, in which case
500 * create a new directory in the top layer and
501 * and fall through to case 3.
502 *
503 * 3. If the top layer succeeded, then return a new union
504 * vnode referencing whatever the new top layer and
505 * whatever the bottom layer returned.
506 */
507
508 /* case 1. */
509 if ((uerror != 0) && (lerror != 0)) {
510 error = uerror;
511 goto out;
512 }
513
514 /* case 2. */
515 if (uerror != 0 /* && (lerror == 0) */ ) {
516 if (lowervp->v_type == VDIR) { /* case 2b. */
517 KASSERT(uppervp == NULL, ("uppervp unexpectedly non-NULL"));
518 /*
519 * Oops, uppervp has a problem, we may have to shadow.
520 */
521 uerror = union_mkshadow(um, upperdvp, cnp, &uppervp);
522 if (uerror) {
523 error = uerror;
524 goto out;
525 }
526 }
527 }
528
529 /*
530 * Must call union_allocvp() with both the upper and lower vnodes
531 * referenced and the upper vnode locked. ap->a_vpp is returned
532 * referenced and locked. lowervp, uppervp, and upperdvp are
533 * absorbed by union_allocvp() whether it succeeds or fails.
534 *
535 * upperdvp is the parent directory of uppervp which may be
536 * different, depending on the path, from dvp->un_uppervp. That's
537 * why it is a separate argument. Note that it must be unlocked.
538 *
539 * dvp must be locked on entry to the call and will be locked on
540 * return.
541 */
542
543 if (uppervp && uppervp != upperdvp)
544 VOP_UNLOCK(uppervp, 0, td);
545 if (lowervp)
546 VOP_UNLOCK(lowervp, 0, td);
547 if (upperdvp)
548 VOP_UNLOCK(upperdvp, 0, td);
549
550 error = union_allocvp(ap->a_vpp, dvp->v_mount, dvp, upperdvp, cnp,
551 uppervp, lowervp, 1);
552
553 UDEBUG(("Create %p = %p %p refs=%d\n", *ap->a_vpp, uppervp, lowervp, (*ap->a_vpp) ? vrefcnt(*ap->a_vpp) : -99));
554
555 uppervp = NULL;
556 upperdvp = NULL;
557 lowervp = NULL;
558
559 /*
560 * Termination Code
561 *
562 * - put away any extra junk laying around. Note that lowervp
563 * (if not NULL) will never be the same as *ap->a_vp and
564 * neither will uppervp, because when we set that state we
565 * NULL-out lowervp or uppervp. On the otherhand, upperdvp
566 * may match uppervp or *ap->a_vpp.
567 *
568 * - relock/unlock dvp if appropriate.
569 */
570
571out:
572 if (upperdvp) {
573 if (upperdvp == uppervp || upperdvp == *ap->a_vpp)
574 vrele(upperdvp);
575 else
576 vput(upperdvp);
577 }
578
579 if (uppervp)
580 vput(uppervp);
581
582 if (lowervp)
583 vput(lowervp);
584
585 /*
586 * Restore LOCKPARENT state
587 */
588
589 if (!lockparent)
590 cnp->cn_flags &= ~LOCKPARENT;
591
592 UDEBUG(("Out %d vpp %p/%d lower %p upper %p\n", error, *ap->a_vpp,
593 ((*ap->a_vpp) ? vrefcnt(*ap->a_vpp) : -99),
594 lowervp, uppervp));
595
596 if (error == 0 || error == EJUSTRETURN) {
597 /*
598 * dvp lock state, determine whether to relock dvp.
599 * We are expected to unlock dvp unless:
600 *
601 * - there was an error (other than EJUSTRETURN), or
602 * - we hit the last component and lockparent is true
603 */
604 if (*ap->a_vpp != dvp) {
605 if (!lockparent || (cnp->cn_flags & ISLASTCN) == 0)
606 VOP_UNLOCK(dvp, 0, td);
607 }
608
609 if (cnp->cn_namelen == 1 &&
610 cnp->cn_nameptr[0] == '.' &&
611 *ap->a_vpp != dvp) {
612#ifdef DIAGNOSTIC
613 vprint("union_lookup: vp", *ap->a_vpp);
614 vprint("union_lookup: dvp", dvp);
615#endif
616 panic("union_lookup returning . (%p) != startdir (%p)",
617 *ap->a_vpp, dvp);
618 }
619 }
620
621 return (error);
622}
623
624/*
625 * union_create:
626 *
627 * a_dvp is locked on entry and remains locked on return. a_vpp is returned
628 * locked if no error occurs, otherwise it is garbage.
629 */
630
631static int
632union_create(ap)
633 struct vop_create_args /* {
634 struct vnode *a_dvp;
635 struct vnode **a_vpp;
636 struct componentname *a_cnp;
637 struct vattr *a_vap;
638 } */ *ap;
639{
640 struct union_node *dun = VTOUNION(ap->a_dvp);
641 struct componentname *cnp = ap->a_cnp;
642 struct thread *td = cnp->cn_thread;
643 struct vnode *dvp;
644 int error = EROFS;
645
646 if ((dvp = union_lock_upper(dun, td)) != NULL) {
647 struct vnode *vp;
648 struct mount *mp;
649
650 error = VOP_CREATE(dvp, &vp, cnp, ap->a_vap);
651 if (error == 0) {
652 mp = ap->a_dvp->v_mount;
653 VOP_UNLOCK(vp, 0, td);
654 UDEBUG(("ALLOCVP-1 FROM %p REFS %d\n", vp, vrefcnt(vp)));
655 error = union_allocvp(ap->a_vpp, mp, NULLVP, NULLVP,
656 cnp, vp, NULLVP, 1);
657 UDEBUG(("ALLOCVP-2B FROM %p REFS %d\n", *ap->a_vpp, vrefcnt(vp)));
658 }
659 union_unlock_upper(dvp, td);
660 }
661 return (error);
662}
663
664static int
665union_whiteout(ap)
666 struct vop_whiteout_args /* {
667 struct vnode *a_dvp;
668 struct componentname *a_cnp;
669 int a_flags;
670 } */ *ap;
671{
672 struct union_node *un = VTOUNION(ap->a_dvp);
673 struct componentname *cnp = ap->a_cnp;
674 struct vnode *uppervp;
675 int error;
676
677 switch (ap->a_flags) {
678 case CREATE:
679 case DELETE:
680 uppervp = union_lock_upper(un, cnp->cn_thread);
681 if (uppervp != NULLVP) {
682 error = VOP_WHITEOUT(un->un_uppervp, cnp, ap->a_flags);
683 union_unlock_upper(uppervp, cnp->cn_thread);
684 } else
685 error = EOPNOTSUPP;
686 break;
687 case LOOKUP:
688 error = EOPNOTSUPP;
689 break;
690 default:
691 panic("union_whiteout: unknown op");
692 }
693 return (error);
694}
695
696/*
697 * union_mknod:
698 *
699 * a_dvp is locked on entry and should remain locked on return.
700 * a_vpp is garbagre whether an error occurs or not.
701 */
702
703static int
704union_mknod(ap)
705 struct vop_mknod_args /* {
706 struct vnode *a_dvp;
707 struct vnode **a_vpp;
708 struct componentname *a_cnp;
709 struct vattr *a_vap;
710 } */ *ap;
711{
712 struct union_node *dun = VTOUNION(ap->a_dvp);
713 struct componentname *cnp = ap->a_cnp;
714 struct vnode *dvp;
715 int error = EROFS;
716
717 if ((dvp = union_lock_upper(dun, cnp->cn_thread)) != NULL) {
718 error = VOP_MKNOD(dvp, ap->a_vpp, cnp, ap->a_vap);
719 union_unlock_upper(dvp, cnp->cn_thread);
720 }
721 return (error);
722}
723
724/*
725 * union_open:
726 *
727 * run open VOP. When opening the underlying vnode we have to mimic
728 * vn_open(). What we *really* need to do to avoid screwups if the
729 * open semantics change is to call vn_open(). For example, ufs blows
730 * up if you open a file but do not vmio it prior to writing.
731 */
732
733static int
734union_open(ap)
735 struct vop_open_args /* {
736 struct vnodeop_desc *a_desc;
737 struct vnode *a_vp;
738 int a_mode;
739 struct ucred *a_cred;
740 struct thread *a_td;
741 } */ *ap;
742{
743 struct union_node *un = VTOUNION(ap->a_vp);
744 struct vnode *tvp;
745 int mode = ap->a_mode;
746 struct ucred *cred = ap->a_cred;
747 struct thread *td = ap->a_td;
748 int error = 0;
749 int tvpisupper = 1;
750
751 /*
752 * If there is an existing upper vp then simply open that.
753 * The upper vp takes precedence over the lower vp. When opening
754 * a lower vp for writing copy it to the uppervp and then open the
755 * uppervp.
756 *
757 * At the end of this section tvp will be left locked.
758 */
759 if ((tvp = union_lock_upper(un, td)) == NULLVP) {
760 /*
761 * If the lower vnode is being opened for writing, then
762 * copy the file contents to the upper vnode and open that,
763 * otherwise can simply open the lower vnode.
764 */
765 tvp = un->un_lowervp;
766 if ((ap->a_mode & FWRITE) && (tvp->v_type == VREG)) {
767 int docopy = !(mode & O_TRUNC);
768 error = union_copyup(un, docopy, cred, td);
769 tvp = union_lock_upper(un, td);
770 } else {
771 un->un_openl++;
772 VREF(tvp);
773 vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY, td);
774 tvpisupper = 0;
775 }
776 }
777
778 /*
779 * We are holding the correct vnode, open it.
780 */
781
782 if (error == 0)
783 error = VOP_OPEN(tvp, mode, cred, td, -1);
784
785 /*
786 * This is absolutely necessary or UFS will blow up.
787 */
788 if (error == 0 && vn_canvmio(tvp) == TRUE)
789 error = VOP_CREATEVOBJECT(tvp, cred, td);
790
791 /*
792 * Release any locks held.
793 */
794 if (tvpisupper) {
795 if (tvp)
796 union_unlock_upper(tvp, td);
797 } else {
798 vput(tvp);
799 }
800 return (error);
801}
802
803/*
804 * union_close:
805 *
806 * It is unclear whether a_vp is passed locked or unlocked. Whatever
807 * the case we do not change it.
808 */
809
810static int
811union_close(ap)
812 struct vop_close_args /* {
813 struct vnode *a_vp;
814 int a_fflag;
815 struct ucred *a_cred;
816 struct thread *a_td;
817 } */ *ap;
818{
819 struct union_node *un = VTOUNION(ap->a_vp);
820 struct vnode *vp;
821
822 if ((vp = un->un_uppervp) == NULLVP) {
823#ifdef UNION_DIAGNOSTIC
824 if (un->un_openl <= 0)
825 panic("union: un_openl cnt");
826#endif
827 --un->un_openl;
828 vp = un->un_lowervp;
829 }
830 ap->a_vp = vp;
831 return (VOP_CLOSE_AP(ap));
832}
833
834/*
835 * Check access permission on the union vnode.
836 * The access check being enforced is to check
837 * against both the underlying vnode, and any
838 * copied vnode. This ensures that no additional
839 * file permissions are given away simply because
840 * the user caused an implicit file copy.
841 */
842static int
843union_access(ap)
844 struct vop_access_args /* {
845 struct vnodeop_desc *a_desc;
846 struct vnode *a_vp;
847 int a_mode;
848 struct ucred *a_cred;
849 struct thread *a_td;
850 } */ *ap;
851{
852 struct union_node *un = VTOUNION(ap->a_vp);
853 struct thread *td = ap->a_td;
854 int error = EACCES;
855 struct vnode *vp;
856
857 /*
858 * Disallow write attempts on filesystems mounted read-only.
859 */
860 if ((ap->a_mode & VWRITE) &&
861 (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)) {
862 switch (ap->a_vp->v_type) {
863 case VREG:
864 case VDIR:
865 case VLNK:
866 return (EROFS);
867 default:
868 break;
869 }
870 }
871
872 if ((vp = union_lock_upper(un, td)) != NULLVP) {
873 ap->a_vp = vp;
874 error = VOP_ACCESS_AP(ap);
875 union_unlock_upper(vp, td);
876 return(error);
877 }
878
879 if ((vp = un->un_lowervp) != NULLVP) {
880 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
881 ap->a_vp = vp;
882
883 /*
884 * Remove VWRITE from a_mode if our mount point is RW, because
885 * we want to allow writes and lowervp may be read-only.
886 */
887 if ((un->un_vnode->v_mount->mnt_flag & MNT_RDONLY) == 0)
888 ap->a_mode &= ~VWRITE;
889
890 error = VOP_ACCESS_AP(ap);
891 if (error == 0) {
892 struct union_mount *um;
893
894 um = MOUNTTOUNIONMOUNT(un->un_vnode->v_mount);
895
896 if (um->um_op == UNMNT_BELOW) {
897 ap->a_cred = um->um_cred;
898 error = VOP_ACCESS_AP(ap);
899 }
900 }
901 VOP_UNLOCK(vp, 0, td);
902 }
903 return(error);
904}
905
906/*
907 * We handle getattr only to change the fsid and
908 * track object sizes
909 *
910 * It's not clear whether VOP_GETATTR is to be
911 * called with the vnode locked or not. stat() calls
912 * it with (vp) locked, and fstat() calls it with
913 * (vp) unlocked.
914 *
915 * Because of this we cannot use our normal locking functions
916 * if we do not intend to lock the main a_vp node. At the moment
917 * we are running without any specific locking at all, but beware
918 * to any programmer that care must be taken if locking is added
919 * to this function.
920 */
921
922static int
923union_getattr(ap)
924 struct vop_getattr_args /* {
925 struct vnode *a_vp;
926 struct vattr *a_vap;
927 struct ucred *a_cred;
928 struct thread *a_td;
929 } */ *ap;
930{
931 int error;
932 struct union_node *un = VTOUNION(ap->a_vp);
933 struct union_mount *um = MOUNTTOUNIONMOUNT(ap->a_vp->v_mount);
934 struct vnode *vp;
935 struct vattr *vap;
936 struct vattr va;
937
938 /*
939 * Some programs walk the filesystem hierarchy by counting
940 * links to directories to avoid stat'ing all the time.
941 * This means the link count on directories needs to be "correct".
942 * The only way to do that is to call getattr on both layers
943 * and fix up the link count. The link count will not necessarily
944 * be accurate but will be large enough to defeat the tree walkers.
945 */
946
947 vap = ap->a_vap;
948
949 if ((vp = un->un_uppervp) != NULLVP) {
950 error = VOP_GETATTR(vp, vap, ap->a_cred, ap->a_td);
951 if (error)
952 return (error);
953 /* XXX isn't this dangerous without a lock? */
954 union_newsize(ap->a_vp, vap->va_size, VNOVAL);
955 }
956
957 if (vp == NULLVP) {
958 vp = un->un_lowervp;
959 } else if (vp->v_type == VDIR && un->un_lowervp != NULLVP) {
960 vp = un->un_lowervp;
961 vap = &va;
962 } else {
963 vp = NULLVP;
964 }
965
966 if (vp != NULLVP) {
967 error = VOP_GETATTR(vp, vap, ap->a_cred, ap->a_td);
968 if (error)
969 return (error);
970 /* XXX isn't this dangerous without a lock? */
971 union_newsize(ap->a_vp, VNOVAL, vap->va_size);
972 }
973
974 if (ap->a_vap->va_fsid == um->um_upperdev)
975 ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
976
977 if ((vap != ap->a_vap) && (vap->va_type == VDIR))
978 ap->a_vap->va_nlink += vap->va_nlink;
979 return (0);
980}
981
982static int
983union_setattr(ap)
984 struct vop_setattr_args /* {
985 struct vnode *a_vp;
986 struct vattr *a_vap;
987 struct ucred *a_cred;
988 struct thread *a_td;
989 } */ *ap;
990{
991 struct union_node *un = VTOUNION(ap->a_vp);
992 struct thread *td = ap->a_td;
993 struct vattr *vap = ap->a_vap;
994 struct vnode *uppervp;
995 int error;
996
997 /*
998 * Disallow write attempts on filesystems mounted read-only.
999 */
1000 if ((ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) &&
1001 (vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
1002 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
1003 vap->va_mtime.tv_sec != VNOVAL ||
1004 vap->va_mode != (mode_t)VNOVAL)) {
1005 return (EROFS);
1006 }
1007
1008 /*
1009 * Handle case of truncating lower object to zero size
1010 * by creating a zero length upper object. This is to
1011 * handle the case of open with O_TRUNC and O_CREAT.
1012 */
1013 if (un->un_uppervp == NULLVP && (un->un_lowervp->v_type == VREG)) {
1014 error = union_copyup(un, (ap->a_vap->va_size != 0),
1015 ap->a_cred, ap->a_td);
1016 if (error)
1017 return (error);
1018 }
1019
1020 /*
1021 * Try to set attributes in upper layer,
1022 * otherwise return read-only filesystem error.
1023 */
1024 error = EROFS;
1025 if ((uppervp = union_lock_upper(un, td)) != NULLVP) {
1026 error = VOP_SETATTR(un->un_uppervp, ap->a_vap,
1027 ap->a_cred, ap->a_td);
1028 if ((error == 0) && (ap->a_vap->va_size != VNOVAL))
1029 union_newsize(ap->a_vp, ap->a_vap->va_size, VNOVAL);
1030 union_unlock_upper(uppervp, td);
1031 }
1032 return (error);
1033}
1034
1035static int
1036union_read(ap)
1037 struct vop_read_args /* {
1038 struct vnode *a_vp;
1039 struct uio *a_uio;
1040 int a_ioflag;
1041 struct ucred *a_cred;
1042 } */ *ap;
1043{
1044 struct union_node *un = VTOUNION(ap->a_vp);
1045 struct thread *td = ap->a_uio->uio_td;
1046 struct vnode *uvp;
1047 int error;
1048
1049 uvp = union_lock_other(un, td);
1050 KASSERT(uvp != NULL, ("union_read: backing vnode missing!"));
1051
1052 error = VOP_READ(uvp, ap->a_uio, ap->a_ioflag, ap->a_cred);
1053 union_unlock_other(uvp, td);
1054
1055 /*
1056 * XXX
1057 * Perhaps the size of the underlying object has changed under
1058 * our feet. Take advantage of the offset information present
1059 * in the uio structure.
1060 */
1061 if (error == 0) {
1062 struct union_node *un = VTOUNION(ap->a_vp);
1063 off_t cur = ap->a_uio->uio_offset;
1064
1065 if (uvp == un->un_uppervp) {
1066 if (cur > un->un_uppersz)
1067 union_newsize(ap->a_vp, cur, VNOVAL);
1068 } else {
1069 if (cur > un->un_lowersz)
1070 union_newsize(ap->a_vp, VNOVAL, cur);
1071 }
1072 }
1073 return (error);
1074}
1075
1076static int
1077union_write(ap)
1078 struct vop_write_args /* {
1079 struct vnode *a_vp;
1080 struct uio *a_uio;
1081 int a_ioflag;
1082 struct ucred *a_cred;
1083 } */ *ap;
1084{
1085 struct union_node *un = VTOUNION(ap->a_vp);
1086 struct thread *td = ap->a_uio->uio_td;
1087 struct vnode *uppervp;
1088 int error;
1089
1090 if ((uppervp = union_lock_upper(un, td)) == NULLVP)
1091 panic("union: missing upper layer in write");
1092
1093 error = VOP_WRITE(uppervp, ap->a_uio, ap->a_ioflag, ap->a_cred);
1094
1095 /*
1096 * The size of the underlying object may be changed by the
1097 * write.
1098 */
1099 if (error == 0) {
1100 off_t cur = ap->a_uio->uio_offset;
1101
1102 if (cur > un->un_uppersz)
1103 union_newsize(ap->a_vp, cur, VNOVAL);
1104 }
1105 union_unlock_upper(uppervp, td);
1106 return (error);
1107}
1108
1109static int
1110union_lease(ap)
1111 struct vop_lease_args /* {
1112 struct vnode *a_vp;
1113 struct thread *a_td;
1114 struct ucred *a_cred;
1115 int a_flag;
1116 } */ *ap;
1117{
1118 struct vnode *ovp = OTHERVP(ap->a_vp);
1119
1120 ap->a_vp = ovp;
1121 return (VOP_LEASE_AP(ap));
1122}
1123
1124static int
1125union_ioctl(ap)
1126 struct vop_ioctl_args /* {
1127 struct vnode *a_vp;
1128 u_long a_command;
1129 caddr_t a_data;
1130 int a_fflag;
1131 struct ucred *a_cred;
1132 struct thread *a_td;
1133 } */ *ap;
1134{
1135 struct vnode *ovp = OTHERVP(ap->a_vp);
1136
1137 ap->a_vp = ovp;
1138 return (VOP_IOCTL_AP(ap));
1139}
1140
1141static int
1142union_poll(ap)
1143 struct vop_poll_args /* {
1144 struct vnode *a_vp;
1145 int a_events;
1146 struct ucred *a_cred;
1147 struct thread *a_td;
1148 } */ *ap;
1149{
1150 struct vnode *ovp = OTHERVP(ap->a_vp);
1151
1152 ap->a_vp = ovp;
1153 return (VOP_POLL_AP(ap));
1154}
1155
1156static int
1157union_fsync(ap)
1158 struct vop_fsync_args /* {
1159 struct vnode *a_vp;
1160 struct ucred *a_cred;
1161 int a_waitfor;
1162 struct thread *a_td;
1163 } */ *ap;
1164{
1165 int error = 0;
1166 struct thread *td = ap->a_td;
1167 struct vnode *targetvp;
1168 struct union_node *un = VTOUNION(ap->a_vp);
1169
1170 if ((targetvp = union_lock_other(un, td)) != NULLVP) {
1171 error = VOP_FSYNC(targetvp, ap->a_waitfor, td);
1172 union_unlock_other(targetvp, td);
1173 }
1174
1175 return (error);
1176}
1177
1178/*
1179 * union_remove:
1180 *
1181 * Remove the specified cnp. The dvp and vp are passed to us locked
1182 * and must remain locked on return.
1183 */
1184
1185static int
1186union_remove(ap)
1187 struct vop_remove_args /* {
1188 struct vnode *a_dvp;
1189 struct vnode *a_vp;
1190 struct componentname *a_cnp;
1191 } */ *ap;
1192{
1193 struct union_node *dun = VTOUNION(ap->a_dvp);
1194 struct union_node *un = VTOUNION(ap->a_vp);
1195 struct componentname *cnp = ap->a_cnp;
1196 struct thread *td = cnp->cn_thread;
1197 struct vnode *uppervp;
1198 struct vnode *upperdvp;
1199 int error;
1200
1201 if ((upperdvp = union_lock_upper(dun, td)) == NULLVP)
1202 panic("union remove: null upper vnode");
1203
1204 if ((uppervp = union_lock_upper(un, td)) != NULLVP) {
1205 if (union_dowhiteout(un, cnp->cn_cred, td))
1206 cnp->cn_flags |= DOWHITEOUT;
1207 if (cnp->cn_flags & DOWHITEOUT) /* XXX fs corruption */
1208 error = EOPNOTSUPP;
1209 else
1210 error = VOP_REMOVE(upperdvp, uppervp, cnp);
1211 if (!error)
1212 union_removed_upper(un);
1213 union_unlock_upper(uppervp, td);
1214 } else {
1215 error = union_mkwhiteout(
1216 MOUNTTOUNIONMOUNT(ap->a_dvp->v_mount),
1217 upperdvp, ap->a_cnp, un->un_path);
1218 }
1219 union_unlock_upper(upperdvp, td);
1220 return (error);
1221}
1222
1223/*
1224 * union_link:
1225 *
1226 * tdvp and vp will be locked on entry.
1227 * tdvp and vp should remain locked on return.
1228 */
1229
1230static int
1231union_link(ap)
1232 struct vop_link_args /* {
1233 struct vnode *a_tdvp;
1234 struct vnode *a_vp;
1235 struct componentname *a_cnp;
1236 } */ *ap;
1237{
1238 struct componentname *cnp = ap->a_cnp;
1239 struct thread *td = cnp->cn_thread;
1240 struct union_node *dun = VTOUNION(ap->a_tdvp);
1241 struct vnode *vp;
1242 struct vnode *tdvp;
1243 int error = 0;
1244
1245 if (ap->a_tdvp->v_op != ap->a_vp->v_op) {
1246 vp = ap->a_vp;
1247 } else {
1248 struct union_node *tun = VTOUNION(ap->a_vp);
1249
1250 if (tun->un_uppervp == NULLVP) {
1251#if 0
1252 if (dun->un_uppervp == tun->un_dirvp) {
1253 if (dun->un_flags & UN_ULOCK) {
1254 dun->un_flags &= ~UN_ULOCK;
1255 VOP_UNLOCK(dun->un_uppervp, 0, td);
1256 }
1257 }
1258#endif
1259 error = union_copyup(tun, 1, cnp->cn_cred, td);
1260#if 0
1261 if (dun->un_uppervp == tun->un_dirvp) {
1262 vn_lock(dun->un_uppervp,
1263 LK_EXCLUSIVE | LK_RETRY, td);
1264 dun->un_flags |= UN_ULOCK;
1265 }
1266#endif
1267 if (error)
1268 return (error);
1269 }
1270 vp = tun->un_uppervp;
1271 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1272 }
1273
1274 /*
1275 * Make sure upper is locked, then unlock the union directory we were
1276 * called with to avoid a deadlock while we are calling VOP_LINK() on
1277 * the upper (with tdvp locked and vp not locked). Our ap->a_tdvp
1278 * is expected to be locked on return.
1279 */
1280
1281 if ((tdvp = union_lock_upper(dun, td)) == NULLVP)
1282 return (EROFS);
1283
1284 VOP_UNLOCK(ap->a_tdvp, 0, td); /* unlock calling node */
1285 error = VOP_LINK(tdvp, vp, cnp); /* call link on upper */
1286
1287 /*
1288 * Unlock tun->un_uppervp if we locked it above.
1289 */
1290 if (ap->a_tdvp->v_op == ap->a_vp->v_op)
1291 VOP_UNLOCK(vp, 0, td);
1292 /*
1293 * We have to unlock tdvp prior to relocking our calling node in
1294 * order to avoid a deadlock. We also have to unlock ap->a_vp
1295 * before relocking the directory, but then we have to relock
1296 * ap->a_vp as our caller expects.
1297 */
1298 VOP_UNLOCK(ap->a_vp, 0, td);
1299 union_unlock_upper(tdvp, td);
1300 vn_lock(ap->a_tdvp, LK_EXCLUSIVE | LK_RETRY, td);
1301 vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY, td);
1302 return (error);
1303}
1304
1305static int
1306union_rename(ap)
1307 struct vop_rename_args /* {
1308 struct vnode *a_fdvp;
1309 struct vnode *a_fvp;
1310 struct componentname *a_fcnp;
1311 struct vnode *a_tdvp;
1312 struct vnode *a_tvp;
1313 struct componentname *a_tcnp;
1314 } */ *ap;
1315{
1316 int error;
1317 struct vnode *fdvp = ap->a_fdvp;
1318 struct vnode *fvp = ap->a_fvp;
1319 struct vnode *tdvp = ap->a_tdvp;
1320 struct vnode *tvp = ap->a_tvp;
1321
1322 /*
1323 * Figure out what fdvp to pass to our upper or lower vnode. If we
1324 * replace the fdvp, release the original one and ref the new one.
1325 */
1326
1327 if (fdvp->v_op == &union_vnodeops) { /* always true */
1328 struct union_node *un = VTOUNION(fdvp);
1329 if (un->un_uppervp == NULLVP) {
1330 /*
1331 * this should never happen in normal
1332 * operation but might if there was
1333 * a problem creating the top-level shadow
1334 * directory.
1335 */
1336 error = EXDEV;
1337 goto bad;
1338 }
1339 fdvp = un->un_uppervp;
1340 VREF(fdvp);
1341 vrele(ap->a_fdvp);
1342 }
1343
1344 /*
1345 * Figure out what fvp to pass to our upper or lower vnode. If we
1346 * replace the fvp, release the original one and ref the new one.
1347 */
1348
1349 if (fvp->v_op == &union_vnodeops) { /* always true */
1350 struct union_node *un = VTOUNION(fvp);
1351#if 0
1352 struct union_mount *um = MOUNTTOUNIONMOUNT(fvp->v_mount);
1353#endif
1354
1355 if (un->un_uppervp == NULLVP) {
1356 switch(fvp->v_type) {
1357 case VREG:
1358 vn_lock(un->un_vnode, LK_EXCLUSIVE | LK_RETRY, ap->a_fcnp->cn_thread);
1359 error = union_copyup(un, 1, ap->a_fcnp->cn_cred, ap->a_fcnp->cn_thread);
1360 VOP_UNLOCK(un->un_vnode, 0, ap->a_fcnp->cn_thread);
1361 if (error)
1362 goto bad;
1363 break;
1364 case VDIR:
1365 /*
1366 * XXX not yet.
1367 *
1368 * There is only one way to rename a directory
1369 * based in the lowervp, and that is to copy
1370 * the entire directory hierarchy. Otherwise
1371 * it would not last across a reboot.
1372 */
1373#if 0
1374 vrele(fvp);
1375 fvp = NULL;
1376 vn_lock(fdvp, LK_EXCLUSIVE | LK_RETRY, ap->a_fcnp->cn_thread);
1377 error = union_mkshadow(um, fdvp,
1378 ap->a_fcnp, &un->un_uppervp);
1379 VOP_UNLOCK(fdvp, 0, ap->a_fcnp->cn_thread);
1380 if (un->un_uppervp)
1381 VOP_UNLOCK(un->un_uppervp, 0, ap->a_fcnp->cn_thread);
1382 if (error)
1383 goto bad;
1384 break;
1385#endif
1386 default:
1387 error = EXDEV;
1388 goto bad;
1389 }
1390 }
1391
1392 if (un->un_lowervp != NULLVP)
1393 ap->a_fcnp->cn_flags |= DOWHITEOUT;
1394 fvp = un->un_uppervp;
1395 VREF(fvp);
1396 vrele(ap->a_fvp);
1397 }
1398
1399 /*
1400 * Figure out what tdvp (destination directory) to pass to the
1401 * lower level. If we replace it with uppervp, we need to vput the
1402 * old one. The exclusive lock is transfered to what we will pass
1403 * down in the VOP_RENAME() and we replace uppervp with a simple
1404 * reference.
1405 */
1406
1407 if (tdvp->v_op == &union_vnodeops) {
1408 struct union_node *un = VTOUNION(tdvp);
1409
1410 if (un->un_uppervp == NULLVP) {
1411 /*
1412 * This should never happen in normal
1413 * operation but might if there was
1414 * a problem creating the top-level shadow
1415 * directory.
1416 */
1417 error = EXDEV;
1418 goto bad;
1419 }
1420
1421 /*
1422 * New tdvp is a lock and reference on uppervp.
1423 * Put away the old tdvp.
1424 */
1425 tdvp = union_lock_upper(un, ap->a_tcnp->cn_thread);
1426 vput(ap->a_tdvp);
1427 }
1428
1429 /*
1430 * Figure out what tvp (destination file) to pass to the
1431 * lower level.
1432 *
1433 * If the uppervp file does not exist, put away the (wrong)
1434 * file and change tvp to NULL.
1435 */
1436
1437 if (tvp != NULLVP && tvp->v_op == &union_vnodeops) {
1438 struct union_node *un = VTOUNION(tvp);
1439
1440 tvp = union_lock_upper(un, ap->a_tcnp->cn_thread);
1441 vput(ap->a_tvp);
1442 /* note: tvp may be NULL */
1443 }
1444
1445 /*
1446 * VOP_RENAME() releases/vputs prior to returning, so we have no
1447 * cleanup to do.
1448 */
1449
1450 return (VOP_RENAME(fdvp, fvp, ap->a_fcnp, tdvp, tvp, ap->a_tcnp));
1451
1452 /*
1453 * Error. We still have to release / vput the various elements.
1454 */
1455
1456bad:
1457 vrele(fdvp);
1458 if (fvp)
1459 vrele(fvp);
1460 vput(tdvp);
1461 if (tvp != NULLVP) {
1462 if (tvp != tdvp)
1463 vput(tvp);
1464 else
1465 vrele(tvp);
1466 }
1467 return (error);
1468}
1469
1470static int
1471union_mkdir(ap)
1472 struct vop_mkdir_args /* {
1473 struct vnode *a_dvp;
1474 struct vnode **a_vpp;
1475 struct componentname *a_cnp;
1476 struct vattr *a_vap;
1477 } */ *ap;
1478{
1479 struct union_node *dun = VTOUNION(ap->a_dvp);
1480 struct componentname *cnp = ap->a_cnp;
1481 struct thread *td = cnp->cn_thread;
1482 struct vnode *upperdvp;
1483 int error = EROFS;
1484
1485 if ((upperdvp = union_lock_upper(dun, td)) != NULLVP) {
1486 struct vnode *vp;
1487
1488 error = VOP_MKDIR(upperdvp, &vp, cnp, ap->a_vap);
1489 union_unlock_upper(upperdvp, td);
1490
1491 if (error == 0) {
1492 VOP_UNLOCK(vp, 0, td);
1493 UDEBUG(("ALLOCVP-2 FROM %p REFS %d\n", vp, vrefcnt(vp)));
1494 error = union_allocvp(ap->a_vpp, ap->a_dvp->v_mount,
1495 ap->a_dvp, NULLVP, cnp, vp, NULLVP, 1);
1496 UDEBUG(("ALLOCVP-2B FROM %p REFS %d\n", *ap->a_vpp, vrefcnt(vp)));
1497 }
1498 }
1499 return (error);
1500}
1501
1502static int
1503union_rmdir(ap)
1504 struct vop_rmdir_args /* {
1505 struct vnode *a_dvp;
1506 struct vnode *a_vp;
1507 struct componentname *a_cnp;
1508 } */ *ap;
1509{
1510 struct union_node *dun = VTOUNION(ap->a_dvp);
1511 struct union_node *un = VTOUNION(ap->a_vp);
1512 struct componentname *cnp = ap->a_cnp;
1513 struct thread *td = cnp->cn_thread;
1514 struct vnode *upperdvp;
1515 struct vnode *uppervp;
1516 int error;
1517
1518 if ((upperdvp = union_lock_upper(dun, td)) == NULLVP)
1519 panic("union rmdir: null upper vnode");
1520
1521 if ((uppervp = union_lock_upper(un, td)) != NULLVP) {
1522 if (union_dowhiteout(un, cnp->cn_cred, td))
1523 cnp->cn_flags |= DOWHITEOUT;
1524 if (cnp->cn_flags & DOWHITEOUT) /* XXX fs corruption */
1525 error = EOPNOTSUPP;
1526 else
1527 error = VOP_RMDIR(upperdvp, uppervp, ap->a_cnp);
1528 if (!error)
1529 union_removed_upper(un);
1530 union_unlock_upper(uppervp, td);
1531 } else {
1532 error = union_mkwhiteout(
1533 MOUNTTOUNIONMOUNT(ap->a_dvp->v_mount),
1534 dun->un_uppervp, ap->a_cnp, un->un_path);
1535 }
1536 union_unlock_upper(upperdvp, td);
1537 return (error);
1538}
1539
1540/*
1541 * union_symlink:
1542 *
1543 * dvp is locked on entry and remains locked on return. a_vpp is garbage
1544 * (unused).
1545 */
1546
1547static int
1548union_symlink(ap)
1549 struct vop_symlink_args /* {
1550 struct vnode *a_dvp;
1551 struct vnode **a_vpp;
1552 struct componentname *a_cnp;
1553 struct vattr *a_vap;
1554 char *a_target;
1555 } */ *ap;
1556{
1557 struct union_node *dun = VTOUNION(ap->a_dvp);
1558 struct componentname *cnp = ap->a_cnp;
1559 struct thread *td = cnp->cn_thread;
1560 struct vnode *dvp;
1561 int error = EROFS;
1562
1563 if ((dvp = union_lock_upper(dun, td)) != NULLVP) {
1564 error = VOP_SYMLINK(dvp, ap->a_vpp, cnp, ap->a_vap,
1565 ap->a_target);
1566 union_unlock_upper(dvp, td);
1567 }
1568 return (error);
1569}
1570
1571/*
1572 * union_readdir ()works in concert with getdirentries() and
1573 * readdir(3) to provide a list of entries in the unioned
1574 * directories. getdirentries() is responsible for walking
1575 * down the union stack. readdir(3) is responsible for
1576 * eliminating duplicate names from the returned data stream.
1577 */
1578static int
1579union_readdir(ap)
1580 struct vop_readdir_args /* {
1581 struct vnode *a_vp;
1582 struct uio *a_uio;
1583 struct ucred *a_cred;
1584 int *a_eofflag;
1585 u_long *a_cookies;
1586 int a_ncookies;
1587 } */ *ap;
1588{
1589 struct union_node *un = VTOUNION(ap->a_vp);
1590 struct thread *td = ap->a_uio->uio_td;
1591 struct vnode *uvp;
1592 int error = 0;
1593
1594 if ((uvp = union_lock_upper(un, td)) != NULLVP) {
1595 ap->a_vp = uvp;
1596 error = VOP_READDIR_AP(ap);
1597 union_unlock_upper(uvp, td);
1598 }
1599 return(error);
1600}
1601
1602static int
1603union_readlink(ap)
1604 struct vop_readlink_args /* {
1605 struct vnode *a_vp;
1606 struct uio *a_uio;
1607 struct ucred *a_cred;
1608 } */ *ap;
1609{
1610 int error;
1611 struct union_node *un = VTOUNION(ap->a_vp);
1612 struct uio *uio = ap->a_uio;
1613 struct thread *td = uio->uio_td;
1614 struct vnode *vp;
1615
1616 vp = union_lock_other(un, td);
1617 KASSERT(vp != NULL, ("union_readlink: backing vnode missing!"));
1618
1619 ap->a_vp = vp;
1620 error = VOP_READLINK_AP(ap);
1621 union_unlock_other(vp, td);
1622
1623 return (error);
1624}
1625
1626static int
1627union_getwritemount(ap)
1628 struct vop_getwritemount_args /* {
1629 struct vnode *a_vp;
1630 struct mount **a_mpp;
1631 } */ *ap;
1632{
1633 struct vnode *vp = ap->a_vp;
1634 struct vnode *uvp = UPPERVP(vp);
1635
1636 if (uvp == NULL) {
1637 VI_LOCK(vp);
1638 if (vp->v_iflag & VI_FREE) {
1639 VI_UNLOCK(vp);
1640 return (EOPNOTSUPP);
1641 }
1642 VI_UNLOCK(vp);
1643 return (EACCES);
1644 }
1645 return(VOP_GETWRITEMOUNT(uvp, ap->a_mpp));
1646}
1647
1648/*
1649 * union_inactive:
1650 *
1651 * Called with the vnode locked. We are expected to unlock the vnode.
1652 */
1653
1654static int
1655union_inactive(ap)
1656 struct vop_inactive_args /* {
1657 struct vnode *a_vp;
1658 struct thread *a_td;
1659 } */ *ap;
1660{
1661 struct vnode *vp = ap->a_vp;
1662 struct thread *td = ap->a_td;
1663 struct union_node *un = VTOUNION(vp);
1664
1665 /*
1666 * Do nothing (and _don't_ bypass).
1667 * Wait to vrele lowervp until reclaim,
1668 * so that until then our union_node is in the
1669 * cache and reusable.
1670 *
1671 */
1672
1673 if (un->un_dircache != NULL)
1674 union_dircache_free(un);
1675
1676#if 0
1677 if ((un->un_flags & UN_ULOCK) && un->un_uppervp) {
1678 un->un_flags &= ~UN_ULOCK;
1679 VOP_UNLOCK(un->un_uppervp, 0, td);
1680 }
1681#endif
1682
1683 VOP_UNLOCK(vp, 0, td);
1684
1685 if ((un->un_flags & UN_CACHED) == 0)
1686 vgone(vp);
1687
1688 return (0);
1689}
1690
1691static int
1692union_reclaim(ap)
1693 struct vop_reclaim_args /* {
1694 struct vnode *a_vp;
1695 } */ *ap;
1696{
1697 union_freevp(ap->a_vp);
1698
1699 return (0);
1700}
1701
1702/*
1703 * unionvp do not hold a VM object and there is no need to create one for
1704 * upper or lower vp because it is done in the union_open()
1705 */
1706static int
1707union_createvobject(ap)
1708 struct vop_createvobject_args /* {
1709 struct vnode *vp;
1710 struct ucred *cred;
1711 struct thread *td;
1712 } */ *ap;
1713{
1714 struct vnode *vp = ap->a_vp;
1715
1716 vp->v_vflag |= VV_OBJBUF;
1717 return (0);
1718}
1719
1720/*
1721 * We have nothing to destroy and this operation shouldn't be bypassed.
1722 */
1723static int
1724union_destroyvobject(ap)
1725 struct vop_destroyvobject_args /* {
1726 struct vnode *vp;
1727 } */ *ap;
1728{
1729 struct vnode *vp = ap->a_vp;
1730
1731 vp->v_vflag &= ~VV_OBJBUF;
1732 return (0);
1733}
1734
1735/*
1736 * Get VM object from the upper or lower vp
1737 */
1738static int
1739union_getvobject(ap)
1740 struct vop_getvobject_args /* {
1741 struct vnode *vp;
1742 struct vm_object **objpp;
1743 } */ *ap;
1744{
1745 struct vnode *ovp = OTHERVP(ap->a_vp);
1746
1747 if (ovp == NULL)
1748 return EINVAL;
1749 return (VOP_GETVOBJECT(ovp, ap->a_objpp));
1750}
1751
1752static int
1753union_print(ap)
1754 struct vop_print_args /* {
1755 struct vnode *a_vp;
1756 } */ *ap;
1757{
1758 struct vnode *vp = ap->a_vp;
1759
1760 printf("\tvp=%p, uppervp=%p, lowervp=%p\n",
1761 vp, UPPERVP(vp), LOWERVP(vp));
1762 if (UPPERVP(vp) != NULLVP)
1763 vprint("union: upper", UPPERVP(vp));
1764 if (LOWERVP(vp) != NULLVP)
1765 vprint("union: lower", LOWERVP(vp));
1766
1767 return (0);
1768}
1769
1770static int
1771union_pathconf(ap)
1772 struct vop_pathconf_args /* {
1773 struct vnode *a_vp;
1774 int a_name;
1775 int *a_retval;
1776 } */ *ap;
1777{
1778 int error;
1779 struct thread *td = curthread; /* XXX */
1780 struct union_node *un = VTOUNION(ap->a_vp);
1781 struct vnode *vp;
1782
1783 vp = union_lock_other(un, td);
1784 KASSERT(vp != NULL, ("union_pathconf: backing vnode missing!"));
1785
1786 ap->a_vp = vp;
1787 error = VOP_PATHCONF_AP(ap);
1788 union_unlock_other(vp, td);
1789
1790 return (error);
1791}
1792
1793static int
1794union_advlock(ap)
1795 struct vop_advlock_args /* {
1796 struct vnode *a_vp;
1797 caddr_t a_id;
1798 int a_op;
1799 struct flock *a_fl;
1800 int a_flags;
1801 } */ *ap;
1802{
1803 register struct vnode *ovp = OTHERVP(ap->a_vp);
1804
1805 ap->a_vp = ovp;
1806 return (VOP_ADVLOCK_AP(ap));
1807}
1808
1809
1810/*
1811 * XXX - vop_strategy must be hand coded because it has no
1812 * YYY - and it is not coherent with anything
1813 *
1814 * vnode in its arguments.
1815 * This goes away with a merged VM/buffer cache.
1816 */
1817static int
1818union_strategy(ap)
1819 struct vop_strategy_args /* {
1820 struct vnode *a_vp;
1821 struct buf *a_bp;
1822 } */ *ap;
1823{
1824 struct buf *bp = ap->a_bp;
1825 struct vnode *othervp = OTHERVP(ap->a_vp);
1826
1827#ifdef DIAGNOSTIC
1828 if (othervp == NULLVP)
1829 panic("union_strategy: nil vp");
1830 if ((bp->b_iocmd == BIO_WRITE) &&
1831 (othervp == LOWERVP(ap->a_vp)))
1832 panic("union_strategy: writing to lowervp");
1833#endif
1834 return (VOP_STRATEGY(othervp, bp));
1835}
1836
1837static int
1838union_getacl(ap)
1839 struct vop_getacl_args /* {
1840 struct vnode *a_vp;
1841 acl_type_t a_type;
1842 struct acl *a_aclp;
1843 struct ucred *a_cred;
1844 struct thread *a_td;
1845 } */ *ap;
1846{
1847 int error;
1848 struct union_node *un = VTOUNION(ap->a_vp);
1849 struct vnode *vp;
1850
1851 vp = union_lock_other(un, ap->a_td);
1852 ap->a_vp = vp;
1853 error = VOP_GETACL_AP(ap);
1854 union_unlock_other(vp, ap->a_td);
1855
1856 return (error);
1857}
1858
1859static int
1860union_setacl(ap)
1861 struct vop_setacl_args /* {
1862 struct vnode *a_vp;
1863 acl_type_t a_type;
1864 struct acl *a_aclp;
1865 struct ucred *a_cred;
1866 struct thread *a_td;
1867 } */ *ap;
1868{
1869 int error;
1870 struct union_node *un = VTOUNION(ap->a_vp);
1871 struct vnode *vp;
1872
1873 vp = union_lock_other(un, ap->a_td);
1874 ap->a_vp = vp;
1875 error = VOP_SETACL_AP(ap);
1876 union_unlock_other(vp, ap->a_td);
1877
1878 return (error);
1879}
1880
1881static int
1882union_aclcheck(ap)
1883 struct vop_aclcheck_args /* {
1884 struct vnode *a_vp;
1885 acl_type_t a_type;
1886 struct acl *a_aclp;
1887 struct ucred *a_cred;
1888 struct thread *a_td;
1889 } */ *ap;
1890{
1891 struct vnode *ovp = OTHERVP(ap->a_vp);
1892
1893 ap->a_vp = ovp;
1894 return (VOP_ACLCHECK_AP(ap));
1895}
1896
1897static int
1898union_closeextattr(ap)
1899 struct vop_closeextattr_args /* {
1900 struct vnode *a_vp;
1901 int a_commit;
1902 struct ucred *a_cred;
1903 struct thread *a_td;
1904 } */ *ap;
1905{
1906 int error;
1907 struct union_node *un = VTOUNION(ap->a_vp);
1908 struct vnode *vp;
1909
1910 vp = union_lock_other(un, ap->a_td);
1911 ap->a_vp = vp;
1912 error = VOP_CLOSEEXTATTR_AP(ap);
1913 union_unlock_other(vp, ap->a_td);
1914
1915 return (error);
1916}
1917
1918static int
1919union_getextattr(ap)
1920 struct vop_getextattr_args /* {
1921 struct vnode *a_vp;
1922 int a_attrnamespace;
1923 const char *a_name;
1924 struct uio *a_uio;
1925 size_t *a_size;
1926 struct ucred *a_cred;
1927 struct thread *a_td;
1928 } */ *ap;
1929{
1930 int error;
1931 struct union_node *un = VTOUNION(ap->a_vp);
1932 struct vnode *vp;
1933
1934 vp = union_lock_other(un, ap->a_td);
1935 ap->a_vp = vp;
1936 error = VOP_GETEXTATTR_AP(ap);
1937 union_unlock_other(vp, ap->a_td);
1938
1939 return (error);
1940}
1941
1942static int
1943union_listextattr(ap)
1944 struct vop_listextattr_args /* {
1945 struct vnode *a_vp;
1946 int a_attrnamespace;
1947 struct uio *a_uio;
1948 size_t *a_size;
1949 struct ucred *a_cred;
1950 struct thread *a_td;
1951 } */ *ap;
1952{
1953 int error;
1954 struct union_node *un = VTOUNION(ap->a_vp);
1955 struct vnode *vp;
1956
1957 vp = union_lock_other(un, ap->a_td);
1958 ap->a_vp = vp;
1959 error = VOP_LISTEXTATTR_AP(ap);
1960 union_unlock_other(vp, ap->a_td);
1961
1962 return (error);
1963}
1964
1965static int
1966union_openextattr(ap)
1967 struct vop_openextattr_args /* {
1968 struct vnode *a_vp;
1969 struct ucred *a_cred;
1970 struct thread *a_td;
1971 } */ *ap;
1972{
1973 int error;
1974 struct union_node *un = VTOUNION(ap->a_vp);
1975 struct vnode *vp;
1976
1977 vp = union_lock_other(un, ap->a_td);
1978 ap->a_vp = vp;
1979 error = VOP_OPENEXTATTR_AP(ap);
1980 union_unlock_other(vp, ap->a_td);
1981
1982 return (error);
1983}
1984
1985static int
1986union_deleteextattr(ap)
1987 struct vop_deleteextattr_args /* {
1988 struct vnode *a_vp;
1989 int a_attrnamespace;
1990 const char *a_name;
1991 struct ucred *a_cred;
1992 struct thread *a_td;
1993 } */ *ap;
1994{
1995 int error;
1996 struct union_node *un = VTOUNION(ap->a_vp);
1997 struct vnode *vp;
1998
1999 vp = union_lock_other(un, ap->a_td);
2000 ap->a_vp = vp;
2001 error = VOP_DELETEEXTATTR_AP(ap);
2002 union_unlock_other(vp, ap->a_td);
2003
2004 return (error);
2005}
2006
2007static int
2008union_setextattr(ap)
2009 struct vop_setextattr_args /* {
2010 struct vnode *a_vp;
2011 int a_attrnamespace;
2012 const char *a_name;
2013 struct uio *a_uio;
2014 struct ucred *a_cred;
2015 struct thread *a_td;
2016 } */ *ap;
2017{
2018 int error;
2019 struct union_node *un = VTOUNION(ap->a_vp);
2020 struct vnode *vp;
2021
2022 vp = union_lock_other(un, ap->a_td);
2023 ap->a_vp = vp;
2024 error = VOP_SETEXTATTR_AP(ap);
2025 union_unlock_other(vp, ap->a_td);
2026
2027 return (error);
2028}
2029
2030static int
2031union_setlabel(ap)
2032 struct vop_setlabel_args /* {
2033 struct vnode *a_vp;
2034 struct label *a_label;
2035 struct ucred *a_cred;
2036 struct thread *a_td;
2037 } */ *ap;
2038{
2039 int error;
2040 struct union_node *un = VTOUNION(ap->a_vp);
2041 struct vnode *vp;
2042
2043 vp = union_lock_other(un, ap->a_td);
2044 ap->a_vp = vp;
2045 error = VOP_SETLABEL_AP(ap);
2046 union_unlock_other(vp, ap->a_td);
2047
2048 return (error);
2049}
2050
2051/*
2052 * Global vfs data structures
2053 */
2054struct vop_vector union_vnodeops = {
2055 .vop_default = &default_vnodeops,
2056
2056 .vop_access = union_access,
2057 .vop_aclcheck = union_aclcheck,
2058 .vop_advlock = union_advlock,
2059 .vop_bmap = VOP_EOPNOTSUPP,
2060 .vop_close = union_close,
2061 .vop_closeextattr = union_closeextattr,
2062 .vop_create = union_create,
2063 .vop_createvobject = union_createvobject,
2064 .vop_deleteextattr = union_deleteextattr,
2065 .vop_destroyvobject = union_destroyvobject,
2066 .vop_fsync = union_fsync,
2057 .vop_access = union_access,
2058 .vop_aclcheck = union_aclcheck,
2059 .vop_advlock = union_advlock,
2060 .vop_bmap = VOP_EOPNOTSUPP,
2061 .vop_close = union_close,
2062 .vop_closeextattr = union_closeextattr,
2063 .vop_create = union_create,
2064 .vop_createvobject = union_createvobject,
2065 .vop_deleteextattr = union_deleteextattr,
2066 .vop_destroyvobject = union_destroyvobject,
2067 .vop_fsync = union_fsync,
2067 .vop_getattr = union_getattr,
2068 .vop_getacl = union_getacl,
2068 .vop_getacl = union_getacl,
2069 .vop_getextattr = union_getextattr,
2070 .vop_getvobject = union_getvobject,
2069 .vop_getattr = union_getattr,
2070 .vop_getextattr = union_getextattr,
2071 .vop_getvobject = union_getvobject,
2072 .vop_getwritemount = union_getwritemount,
2071 .vop_inactive = union_inactive,
2072 .vop_ioctl = union_ioctl,
2073 .vop_lease = union_lease,
2074 .vop_link = union_link,
2075 .vop_listextattr = union_listextattr,
2076 .vop_lookup = union_lookup,
2077 .vop_mkdir = union_mkdir,
2078 .vop_mknod = union_mknod,
2079 .vop_open = union_open,
2080 .vop_openextattr = union_openextattr,
2081 .vop_pathconf = union_pathconf,
2082 .vop_poll = union_poll,
2083 .vop_print = union_print,
2084 .vop_read = union_read,
2085 .vop_readdir = union_readdir,
2086 .vop_readlink = union_readlink,
2073 .vop_inactive = union_inactive,
2074 .vop_ioctl = union_ioctl,
2075 .vop_lease = union_lease,
2076 .vop_link = union_link,
2077 .vop_listextattr = union_listextattr,
2078 .vop_lookup = union_lookup,
2079 .vop_mkdir = union_mkdir,
2080 .vop_mknod = union_mknod,
2081 .vop_open = union_open,
2082 .vop_openextattr = union_openextattr,
2083 .vop_pathconf = union_pathconf,
2084 .vop_poll = union_poll,
2085 .vop_print = union_print,
2086 .vop_read = union_read,
2087 .vop_readdir = union_readdir,
2088 .vop_readlink = union_readlink,
2087 .vop_getwritemount = union_getwritemount,
2088 .vop_reclaim = union_reclaim,
2089 .vop_remove = union_remove,
2090 .vop_rename = union_rename,
2091 .vop_rmdir = union_rmdir,
2092 .vop_setacl = union_setacl,
2093 .vop_setattr = union_setattr,
2089 .vop_reclaim = union_reclaim,
2090 .vop_remove = union_remove,
2091 .vop_rename = union_rename,
2092 .vop_rmdir = union_rmdir,
2093 .vop_setacl = union_setacl,
2094 .vop_setattr = union_setattr,
2094 .vop_setextattr = union_setextattr,
2095 .vop_setextattr = union_setextattr,
2095 .vop_setlabel = union_setlabel,
2096 .vop_strategy = union_strategy,
2097 .vop_symlink = union_symlink,
2098 .vop_whiteout = union_whiteout,
2099 .vop_write = union_write,
2100};
2096 .vop_setlabel = union_setlabel,
2097 .vop_strategy = union_strategy,
2098 .vop_symlink = union_symlink,
2099 .vop_whiteout = union_whiteout,
2100 .vop_write = union_write,
2101};