X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/e2a2f3a732c54c31e87edb0d0a789e899c13ad24..6f40eb2413dc2c3e11abe6633bcc5c8517de8637:/usr/src/sys/miscfs/union/union_vnops.c diff --git a/usr/src/sys/miscfs/union/union_vnops.c b/usr/src/sys/miscfs/union/union_vnops.c index 9a2e2483bd..01fd61a70c 100644 --- a/usr/src/sys/miscfs/union/union_vnops.c +++ b/usr/src/sys/miscfs/union/union_vnops.c @@ -8,7 +8,7 @@ * * %sccs.include.redist.c% * - * @(#)union_vnops.c 2.1 (Berkeley) %G% + * @(#)union_vnops.c 8.13 (Berkeley) %G% */ #include @@ -22,19 +22,38 @@ #include #include #include -#include "union.h" +#include +#include + +#define FIXUP(un) { \ + if (((un)->un_flags & UN_ULOCK) == 0) { \ + union_fixup(un); \ + } \ +} + +static void +union_fixup(un) + struct union_node *un; +{ + + VOP_LOCK(un->un_uppervp); + un->un_flags |= UN_ULOCK; +} static int -union_lookup1(udvp, dvp, vpp, cnp) +union_lookup1(udvp, dvpp, vpp, cnp) struct vnode *udvp; - struct vnode *dvp; + struct vnode **dvpp; struct vnode **vpp; struct componentname *cnp; { int error; struct vnode *tdvp; + struct vnode *dvp; struct mount *mp; + dvp = *dvpp; + /* * If stepping up the directory tree, check for going * back across the mount point, in which case do what @@ -42,18 +61,15 @@ union_lookup1(udvp, dvp, vpp, cnp) * hierarchy. */ if (cnp->cn_flags & ISDOTDOT) { - for (;;) { + while ((dvp != udvp) && (dvp->v_flag & VROOT)) { /* * Don't do the NOCROSSMOUNT check * at this level. By definition, * union fs deals with namespaces, not * filesystems. */ - if ((dvp->v_flag & VROOT) == 0) - break; - tdvp = dvp; - dvp = dvp->v_mount->mnt_vnodecovered; + *dvpp = dvp = dvp->v_mount->mnt_vnodecovered; vput(tdvp); VREF(dvp); VOP_LOCK(dvp); @@ -120,6 +136,7 @@ union_lookup(ap) int lockparent = cnp->cn_flags & LOCKPARENT; int rdonly = cnp->cn_flags & RDONLY; struct union_mount *um = MOUNTTOUNIONMOUNT(dvp->v_mount); + struct ucred *saved_cred; cnp->cn_flags |= LOCKPARENT; @@ -134,8 +151,9 @@ union_lookup(ap) * then assume that something special is going * on and just return that vnode. */ - if (upperdvp) { - uerror = union_lookup1(um->um_uppervp, upperdvp, + if (upperdvp != NULLVP) { + FIXUP(dun); + uerror = union_lookup1(um->um_uppervp, &upperdvp, &uppervp, cnp); /*if (uppervp == upperdvp) dun->un_flags |= UN_KLOCK;*/ @@ -157,7 +175,7 @@ union_lookup(ap) * back from the upper layer and return the lower vnode * instead. */ - if (lowerdvp) { + if (lowerdvp != NULLVP) { int nameiop; VOP_LOCK(lowerdvp); @@ -168,15 +186,21 @@ union_lookup(ap) */ nameiop = cnp->cn_nameiop; cnp->cn_nameiop = LOOKUP; - lerror = union_lookup1(um->um_lowervp, lowerdvp, + if (um->um_op == UNMNT_BELOW) { + saved_cred = cnp->cn_cred; + cnp->cn_cred = um->um_cred; + } + lerror = union_lookup1(um->um_lowervp, &lowerdvp, &lowervp, cnp); + if (um->um_op == UNMNT_BELOW) + cnp->cn_cred = saved_cred; cnp->cn_nameiop = nameiop; if (lowervp != lowerdvp) VOP_UNLOCK(lowerdvp); if (cnp->cn_consume != 0) { - if (uppervp) { + if (uppervp != NULLVP) { if (uppervp == upperdvp) vrele(uppervp); else @@ -236,7 +260,7 @@ union_lookup(ap) dun->un_flags |= UN_ULOCK; if (uerror) { - if (lowervp) { + if (lowervp != NULLVP) { vput(lowervp); lowervp = NULLVP; } @@ -245,16 +269,16 @@ union_lookup(ap) } } - if (lowervp) + if (lowervp != NULLVP) VOP_UNLOCK(lowervp); error = union_allocvp(ap->a_vpp, dvp->v_mount, dvp, upperdvp, cnp, uppervp, lowervp); if (error) { - if (uppervp) + if (uppervp != NULLVP) vput(uppervp); - if (lowervp) + if (lowervp != NULLVP) vrele(lowervp); } else { if (*ap->a_vpp != dvp) @@ -277,10 +301,12 @@ union_create(ap) struct union_node *un = VTOUNION(ap->a_dvp); struct vnode *dvp = un->un_uppervp; - if (dvp) { + if (dvp != NULLVP) { int error; struct vnode *vp; + FIXUP(un); + VREF(dvp); un->un_flags |= UN_KLOCK; vput(ap->a_dvp); @@ -317,10 +343,12 @@ union_mknod(ap) struct union_node *un = VTOUNION(ap->a_dvp); struct vnode *dvp = un->un_uppervp; - if (dvp) { + if (dvp != NULLVP) { int error; struct vnode *vp; + FIXUP(un); + VREF(dvp); un->un_flags |= UN_KLOCK; vput(ap->a_dvp); @@ -328,7 +356,7 @@ union_mknod(ap) if (error) return (error); - if (vp) { + if (vp != NULLVP) { error = union_allocvp( ap->a_vpp, ap->a_dvp->v_mount, @@ -376,75 +404,7 @@ union_open(ap) */ tvp = un->un_lowervp; if ((ap->a_mode & FWRITE) && (tvp->v_type == VREG)) { - struct vnode *vp; - int i; - - /* - * Open the named file in the upper layer. Note that - * the file may have come into existence *since* the - * lookup was done, since the upper layer may really - * be a loopback mount of some other filesystem... - * so open the file with exclusive create and barf if - * it already exists. - * XXX - perhaps should re-lookup the node (once more - * with feeling) and simply open that. Who knows. - */ - error = union_vn_create(&vp, un, p); - if (error) - return (error); - - /* at this point, uppervp is locked */ - un->un_uppervp = vp; /* XXX */ - un->un_flags |= UN_ULOCK; - - /* - * Now, if the file is being opened with truncation, - * then the (new) upper vnode is ready to fly, - * otherwise the data from the lower vnode must be - * copied to the upper layer first. This only works - * for regular files (check is made above). - */ - if ((mode & O_TRUNC) == 0) { - /* - * XXX - should not ignore errors - * from VOP_CLOSE - */ - VOP_LOCK(tvp); - error = VOP_OPEN(tvp, FREAD, cred, p); - if (error == 0) { - error = union_copyfile(p, cred, - tvp, un->un_uppervp); - VOP_UNLOCK(tvp); - (void) VOP_CLOSE(tvp, FREAD); - } else { - VOP_UNLOCK(tvp); - } - - un->un_flags &= ~UN_ULOCK; - VOP_UNLOCK(un->un_uppervp); - union_vn_close(un->un_uppervp, FWRITE, cred, p); - VOP_LOCK(un->un_uppervp); - un->un_flags |= UN_ULOCK; - - if (!error) - uprintf("union: copied up %s\n", - un->un_path); - } - - /* - * Subsequent IOs will go to the top layer, so - * call close on the lower vnode and open on the - * upper vnode to ensure that the filesystem keeps - * its references counts right. This doesn't do - * the right thing with (cred) and (FREAD) though. - * Ignoring error returns is not righ, either. - */ - for (i = 0; i < un->un_openl; i++) { - (void) VOP_CLOSE(tvp, FREAD); - (void) VOP_OPEN(un->un_uppervp, FREAD, cred, p); - } - un->un_openl = 0; - + error = union_copyup(un, (mode&O_TRUNC) == 0, cred, p); if (error == 0) error = VOP_OPEN(un->un_uppervp, mode, cred, p); return (error); @@ -461,6 +421,8 @@ union_open(ap) return (error); } + FIXUP(un); + error = VOP_OPEN(tvp, mode, cred, p); return (error); @@ -478,7 +440,7 @@ union_close(ap) struct union_node *un = VTOUNION(ap->a_vp); struct vnode *vp; - if (un->un_uppervp) { + if (un->un_uppervp != NULLVP) { vp = un->un_uppervp; } else { #ifdef UNION_DIAGNOSTIC @@ -511,25 +473,35 @@ union_access(ap) } */ *ap; { struct union_node *un = VTOUNION(ap->a_vp); - int error = 0; + int error = EACCES; struct vnode *vp; - if (vp = un->un_lowervp) { + if ((vp = un->un_uppervp) != NULLVP) { + FIXUP(un); + return (VOP_ACCESS(vp, ap->a_mode, ap->a_cred, ap->a_p)); + } + + if ((vp = un->un_lowervp) != NULLVP) { VOP_LOCK(vp); error = VOP_ACCESS(vp, ap->a_mode, ap->a_cred, ap->a_p); + if (error == 0) { + struct union_mount *um = MOUNTTOUNIONMOUNT(vp->v_mount); + + if (um->um_op == UNMNT_BELOW) + error = VOP_ACCESS(vp, ap->a_mode, + um->um_cred, ap->a_p); + } VOP_UNLOCK(vp); if (error) return (error); } - if (vp = un->un_uppervp) - error = VOP_ACCESS(vp, ap->a_mode, ap->a_cred, ap->a_p); - return (error); } /* - * We handle getattr only to change the fsid. + * We handle getattr only to change the fsid and + * track object sizes */ int union_getattr(ap) @@ -541,17 +513,64 @@ union_getattr(ap) } */ *ap; { int error; - struct vnode *vp = OTHERVP(ap->a_vp); - int dolock = (vp == LOWERVP(ap->a_vp)); + struct union_node *un = VTOUNION(ap->a_vp); + struct vnode *vp = un->un_uppervp; + struct vattr *vap; + struct vattr va; - if (dolock) + + /* + * Some programs walk the filesystem hierarchy by counting + * links to directories to avoid stat'ing all the time. + * This means the link count on directories needs to be "correct". + * The only way to do that is to call getattr on both layers + * and fix up the link count. The link count will not necessarily + * be accurate but will be large enough to defeat the tree walkers. + */ + + vap = ap->a_vap; + + vp = un->un_uppervp; + if (vp != NULLVP) { + /* + * It's not clear whether VOP_GETATTR is to be + * called with the vnode locked or not. stat() calls + * it with (vp) locked, and fstat calls it with + * (vp) unlocked. + * In the mean time, compensate here by checking + * the union_node's lock flag. + */ + if (un->un_flags & UN_LOCKED) + FIXUP(un); + + error = VOP_GETATTR(vp, vap, ap->a_cred, ap->a_p); + if (error) + return (error); + union_newsize(ap->a_vp, vap->va_size, VNOVAL); + } + + if (vp == NULLVP) { + vp = un->un_lowervp; + } else if (vp->v_type == VDIR) { + vp = un->un_lowervp; + vap = &va; + } else { + vp = NULLVP; + } + + if (vp != NULLVP) { VOP_LOCK(vp); - error = VOP_GETATTR(vp, ap->a_vap, ap->a_cred, ap->a_p); - if (dolock) + error = VOP_GETATTR(vp, vap, ap->a_cred, ap->a_p); VOP_UNLOCK(vp); + if (error) + return (error); + union_newsize(ap->a_vp, VNOVAL, vap->va_size); + } - /* Requires that arguments be restored. */ - ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0]; + if ((vap != ap->a_vap) && (vap->va_type == VDIR)) + ap->a_vap->va_nlink += vap->va_nlink; + + vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0]; return (0); } @@ -567,15 +586,41 @@ union_setattr(ap) struct union_node *un = VTOUNION(ap->a_vp); int error; - if (un->un_uppervp) { + /* + * Handle case of truncating lower object to zero size, + * by creating a zero length upper object. This is to + * handle the case of open with O_TRUNC and O_CREAT. + */ + if ((un->un_uppervp == NULLVP) && + /* assert(un->un_lowervp != NULLVP) */ + (un->un_lowervp->v_type == VREG) && + (ap->a_vap->va_size == 0)) { + struct vnode *vp; + + error = union_vn_create(&vp, un, ap->a_p); + if (error) + return (error); + + /* at this point, uppervp is locked */ + union_newupper(un, vp); + + VOP_UNLOCK(vp); + union_vn_close(un->un_uppervp, FWRITE, ap->a_cred, ap->a_p); + VOP_LOCK(vp); + un->un_flags |= UN_ULOCK; + } + + /* + * Try to set attributes in upper layer, + * otherwise return read-only filesystem error. + */ + if (un->un_uppervp != NULLVP) { + FIXUP(un); error = VOP_SETATTR(un->un_uppervp, ap->a_vap, ap->a_cred, ap->a_p); + if ((error == 0) && (ap->a_vap->va_size != VNOVAL)) + union_newsize(ap->a_vp, ap->a_vap->va_size, VNOVAL); } else { - /* - * XXX should do a copyfile (perhaps only if - * the file permission change, which would not - * track va_ctime correctly). - */ error = EROFS; } @@ -597,10 +642,31 @@ union_read(ap) if (dolock) VOP_LOCK(vp); + else + FIXUP(VTOUNION(ap->a_vp)); error = VOP_READ(vp, ap->a_uio, ap->a_ioflag, ap->a_cred); if (dolock) VOP_UNLOCK(vp); + /* + * XXX + * perhaps the size of the underlying object has changed under + * our feet. take advantage of the offset information present + * in the uio structure. + */ + if (error == 0) { + struct union_node *un = VTOUNION(ap->a_vp); + off_t cur = ap->a_uio->uio_offset; + + if (vp == un->un_uppervp) { + if (cur > un->un_uppersz) + union_newsize(ap->a_vp, cur, VNOVAL); + } else { + if (cur > un->un_lowersz) + union_newsize(ap->a_vp, VNOVAL, cur); + } + } + return (error); } @@ -619,10 +685,29 @@ union_write(ap) if (dolock) VOP_LOCK(vp); + else + FIXUP(VTOUNION(ap->a_vp)); error = VOP_WRITE(vp, ap->a_uio, ap->a_ioflag, ap->a_cred); if (dolock) VOP_UNLOCK(vp); + /* + * the size of the underlying object may be changed by the + * write. + */ + if (error == 0) { + struct union_node *un = VTOUNION(ap->a_vp); + off_t cur = ap->a_uio->uio_offset; + + if (vp == un->un_uppervp) { + if (cur > un->un_uppersz) + union_newsize(ap->a_vp, cur, VNOVAL); + } else { + if (cur > un->un_lowersz) + union_newsize(ap->a_vp, VNOVAL, cur); + } + } + return (error); } @@ -683,11 +768,13 @@ union_fsync(ap) int error = 0; struct vnode *targetvp = OTHERVP(ap->a_vp); - if (targetvp) { + if (targetvp != NULLVP) { int dolock = (targetvp == LOWERVP(ap->a_vp)); if (dolock) VOP_LOCK(targetvp); + else + FIXUP(VTOUNION(ap->a_vp)); error = VOP_FSYNC(targetvp, ap->a_cred, ap->a_waitfor, ap->a_p); if (dolock) @@ -722,13 +809,15 @@ union_remove(ap) struct union_node *dun = VTOUNION(ap->a_dvp); struct union_node *un = VTOUNION(ap->a_vp); - if (dun->un_uppervp && un->un_uppervp) { + if (dun->un_uppervp != NULLVP && un->un_uppervp != NULLVP) { struct vnode *dvp = dun->un_uppervp; struct vnode *vp = un->un_uppervp; + FIXUP(dun); VREF(dvp); dun->un_flags |= UN_KLOCK; vput(ap->a_dvp); + FIXUP(un); VREF(vp); un->un_flags |= UN_KLOCK; vput(ap->a_vp); @@ -760,32 +849,49 @@ union_link(ap) struct componentname *a_cnp; } */ *ap; { - int error; - struct union_node *dun = VTOUNION(ap->a_vp); - struct union_node *un = VTOUNION(ap->a_tdvp); - - if (dun->un_uppervp && un->un_uppervp) { - struct vnode *dvp = dun->un_uppervp; - struct vnode *vp = un->un_uppervp; + int error = 0; + struct union_node *un; + struct vnode *vp; + struct vnode *tdvp; - VREF(dvp); - dun->un_flags |= UN_KLOCK; - vput(ap->a_vp); - VREF(vp); - vrele(ap->a_tdvp); + un = VTOUNION(ap->a_vp); - error = VOP_LINK(dvp, vp, ap->a_cnp); + if (ap->a_vp->v_op != ap->a_tdvp->v_op) { + tdvp = ap->a_tdvp; } else { - /* - * XXX: need to copy to upper layer - * and do the link there. - */ - vput(ap->a_vp); - vrele(ap->a_tdvp); + struct union_node *tdun = VTOUNION(ap->a_tdvp); + if (tdun->un_uppervp == NULLVP) { + VOP_LOCK(ap->a_tdvp); + if (un->un_uppervp == tdun->un_dirvp) { + un->un_flags &= ~UN_ULOCK; + VOP_UNLOCK(un->un_uppervp); + } + error = union_copyup(tdun, 1, ap->a_cnp->cn_cred, + ap->a_cnp->cn_proc); + if (un->un_uppervp == tdun->un_dirvp) { + VOP_LOCK(un->un_uppervp); + un->un_flags |= UN_ULOCK; + } + VOP_UNLOCK(ap->a_tdvp); + } + tdvp = tdun->un_uppervp; + } + + vp = un->un_uppervp; + if (vp == NULLVP) error = EROFS; + + if (error) { + vput(ap->a_vp); + return (error); } - return (error); + FIXUP(un); + VREF(vp); + un->un_flags |= UN_KLOCK; + vput(ap->a_vp); + + return (VOP_LINK(vp, tdvp, ap->a_cnp)); } int @@ -833,6 +939,12 @@ union_rename(ap) if (tdvp->v_op == union_vnodeop_p) { struct union_node *un = VTOUNION(tdvp); if (un->un_uppervp == NULLVP) { + /* + * this should never happen in normal + * operation but might if there was + * a problem creating the top-level shadow + * directory. + */ error = EROFS; goto bad; } @@ -843,16 +955,14 @@ union_rename(ap) vput(ap->a_tdvp); } - if (tvp && tvp->v_op == union_vnodeop_p) { + if (tvp != NULLVP && tvp->v_op == union_vnodeop_p) { struct union_node *un = VTOUNION(tvp); - if (un->un_uppervp == NULLVP) { - error = EROFS; - goto bad; - } tvp = un->un_uppervp; - VREF(tvp); - un->un_flags |= UN_KLOCK; + if (tvp != NULLVP) { + VREF(tvp); + un->un_flags |= UN_KLOCK; + } vput(ap->a_tvp); } @@ -862,7 +972,7 @@ bad: vrele(fdvp); vrele(fvp); vput(tdvp); - if (tvp) + if (tvp != NULLVP) vput(tvp); return (error); @@ -880,10 +990,11 @@ union_mkdir(ap) struct union_node *un = VTOUNION(ap->a_dvp); struct vnode *dvp = un->un_uppervp; - if (dvp) { + if (dvp != NULLVP) { int error; struct vnode *vp; + FIXUP(un); VREF(dvp); un->un_flags |= UN_KLOCK; vput(ap->a_dvp); @@ -920,13 +1031,15 @@ union_rmdir(ap) struct union_node *dun = VTOUNION(ap->a_dvp); struct union_node *un = VTOUNION(ap->a_vp); - if (dun->un_uppervp && un->un_uppervp) { + if (dun->un_uppervp != NULLVP && un->un_uppervp != NULLVP) { struct vnode *dvp = dun->un_uppervp; struct vnode *vp = un->un_uppervp; + FIXUP(dun); VREF(dvp); dun->un_flags |= UN_KLOCK; vput(ap->a_dvp); + FIXUP(un); VREF(vp); un->un_flags |= UN_KLOCK; vput(ap->a_vp); @@ -963,11 +1076,12 @@ union_symlink(ap) struct union_node *un = VTOUNION(ap->a_dvp); struct vnode *dvp = un->un_uppervp; - if (dvp) { + if (dvp != NULLVP) { int error; struct vnode *vp; struct mount *mp = ap->a_dvp->v_mount; + FIXUP(un); VREF(dvp); un->un_flags |= UN_KLOCK; vput(ap->a_dvp); @@ -1000,8 +1114,10 @@ union_readdir(ap) int error = 0; struct union_node *un = VTOUNION(ap->a_vp); - if (un->un_uppervp) + if (un->un_uppervp != NULLVP) { + FIXUP(un); error = VOP_READDIR(un->un_uppervp, ap->a_uio, ap->a_cred); + } return (error); } @@ -1020,6 +1136,8 @@ union_readlink(ap) if (dolock) VOP_LOCK(vp); + else + FIXUP(VTOUNION(ap->a_vp)); error = VOP_READLINK(vp, ap->a_uio, ap->a_cred); if (dolock) VOP_UNLOCK(vp); @@ -1040,8 +1158,12 @@ union_abortop(ap) int islocked = un->un_flags & UN_LOCKED; int dolock = (vp == LOWERVP(ap->a_dvp)); - if (islocked && dolock) - VOP_LOCK(vp); + if (islocked) { + if (dolock) + VOP_LOCK(vp); + else + FIXUP(VTOUNION(ap->a_dvp)); + } error = VOP_ABORTOP(vp, ap->a_cnp); if (islocked && dolock) VOP_UNLOCK(vp); @@ -1055,6 +1177,7 @@ union_inactive(ap) struct vnode *a_vp; } */ *ap; { + struct union_node *un = VTOUNION(ap->a_vp); /* * Do nothing (and _don't_ bypass). @@ -1070,12 +1193,15 @@ union_inactive(ap) */ #ifdef UNION_DIAGNOSTIC - struct union_node *un = VTOUNION(ap->a_vp); - if (un->un_flags & UN_LOCKED) panic("union: inactivating locked node"); + if (un->un_flags & UN_ULOCK) + panic("union: inactivating w/locked upper node"); #endif + if ((un->un_flags & UN_CACHED) == 0) + vgone(ap->a_vp); + return (0); } @@ -1085,31 +1211,9 @@ union_reclaim(ap) struct vnode *a_vp; } */ *ap; { - struct vnode *vp = ap->a_vp; - struct union_node *un = VTOUNION(vp); - struct vnode *uppervp = un->un_uppervp; - struct vnode *lowervp = un->un_lowervp; - struct vnode *dirvp = un->un_dirvp; - char *path = un->un_path; - /* - * Note: in vop_reclaim, vp->v_op == dead_vnodeop_p, - * so we can't call VOPs on ourself. - */ - /* After this assignment, this node will not be re-used. */ - un->un_uppervp = NULLVP; - un->un_lowervp = NULLVP; - un->un_dirvp = NULLVP; - un->un_path = NULL; - union_freevp(vp); - if (uppervp) - vrele(uppervp); - if (lowervp) - vrele(lowervp); - if (dirvp) - vrele(dirvp); - if (path) - free(path, M_TEMP); + union_freevp(ap->a_vp); + return (0); } @@ -1117,12 +1221,21 @@ int union_lock(ap) struct vop_lock_args *ap; { - struct union_node *un = VTOUNION(ap->a_vp); + struct vnode *vp = ap->a_vp; + struct union_node *un; - if (un->un_uppervp) { +start: + while (vp->v_flag & VXLOCK) { + vp->v_flag |= VXWANT; + sleep((caddr_t)vp, PINOD); + } + + un = VTOUNION(vp); + + if (un->un_uppervp != NULLVP) { if ((un->un_flags & UN_ULOCK) == 0) { - VOP_LOCK(un->un_uppervp); un->un_flags |= UN_ULOCK; + VOP_LOCK(un->un_uppervp); } #ifdef DIAGNOSTIC if (un->un_flags & UN_KLOCK) @@ -1130,7 +1243,7 @@ union_lock(ap) #endif } - while (un->un_flags & UN_LOCKED) { + if (un->un_flags & UN_LOCKED) { #ifdef DIAGNOSTIC if (curproc && un->un_pid == curproc->p_pid && un->un_pid > -1 && curproc->p_pid > -1) @@ -1138,8 +1251,8 @@ union_lock(ap) #endif un->un_flags |= UN_WANT; sleep((caddr_t) &un->un_flags, PINOD); + goto start; } - un->un_flags |= UN_LOCKED; #ifdef DIAGNOSTIC if (curproc) @@ -1148,6 +1261,7 @@ union_lock(ap) un->un_pid = -1; #endif + un->un_flags |= UN_LOCKED; return (0); } @@ -1200,6 +1314,8 @@ union_bmap(ap) if (dolock) VOP_LOCK(vp); + else + FIXUP(VTOUNION(ap->a_vp)); error = VOP_BMAP(vp, ap->a_bn, ap->a_vpp, ap->a_bnp, ap->a_runp); if (dolock) VOP_UNLOCK(vp); @@ -1244,6 +1360,8 @@ union_pathconf(ap) if (dolock) VOP_LOCK(vp); + else + FIXUP(VTOUNION(ap->a_vp)); error = VOP_PATHCONF(vp, ap->a_name, ap->a_retval); if (dolock) VOP_UNLOCK(vp);