From 8a9c17f60a0e7f32fa5b6a8e64ec861e61a5246e Mon Sep 17 00:00:00 2001 From: Jan-Simon Pendry Date: Sat, 7 May 1994 20:19:51 -0800 Subject: [PATCH] keep track of vnode size changes. SCCS-vsn: sys/miscfs/union/union_subr.c 8.7 SCCS-vsn: sys/miscfs/union/union.h 8.4 SCCS-vsn: sys/miscfs/union/union_vnops.c 8.10 --- usr/src/sys/miscfs/union/union.h | 5 ++- usr/src/sys/miscfs/union/union_subr.c | 48 +++++++++++++++++++++++++- usr/src/sys/miscfs/union/union_vnops.c | 45 ++++++++++++++++++++++-- 3 files changed, 94 insertions(+), 4 deletions(-) diff --git a/usr/src/sys/miscfs/union/union.h b/usr/src/sys/miscfs/union/union.h index f60545fc05..11cbab1e18 100644 --- a/usr/src/sys/miscfs/union/union.h +++ b/usr/src/sys/miscfs/union/union.h @@ -8,7 +8,7 @@ * * %sccs.include.redist.c% * - * @(#)union.h 8.3 (Berkeley) %G% + * @(#)union.h 8.4 (Berkeley) %G% */ struct union_args { @@ -52,6 +52,8 @@ struct union_node { int un_hash; /* saved un_path hash value */ int un_openl; /* # of opens on lowervp */ unsigned int un_flags; + off_t un_uppersz; /* size of upper object */ + off_t un_lowersz; /* size of lower object */ #ifdef DIAGNOSTIC pid_t un_pid; #endif @@ -79,6 +81,7 @@ extern void union_removed_upper __P((struct union_node *un)); extern struct vnode *union_lowervp __P((struct vnode *)); extern void union_newlower __P((struct union_node *, struct vnode *)); extern void union_newupper __P((struct union_node *, struct vnode *)); +extern void union_newsize __P((struct vnode *, off_t, off_t)); #define MOUNTTOUNIONMOUNT(mp) ((struct union_mount *)((mp)->mnt_data)) #define VTOUNION(vp) ((struct union_node *)(vp)->v_data) diff --git a/usr/src/sys/miscfs/union/union_subr.c b/usr/src/sys/miscfs/union/union_subr.c index 1149caa319..f71072cb01 100644 --- a/usr/src/sys/miscfs/union/union_subr.c +++ b/usr/src/sys/miscfs/union/union_subr.c @@ -8,7 +8,7 @@ * * %sccs.include.redist.c% * - * @(#)union_subr.c 8.6 (Berkeley) %G% + * @(#)union_subr.c 8.7 (Berkeley) %G% */ #include @@ -22,6 +22,7 @@ #include #include #include +#include /* for vnode_pager_setsize */ #include #ifdef DIAGNOSTIC @@ -127,6 +128,7 @@ union_updatevp(un, uppervp, lowervp) } } un->un_lowervp = lowervp; + un->un_lowersz = VNOVAL; } if (un->un_uppervp != uppervp) { @@ -134,6 +136,7 @@ union_updatevp(un, uppervp, lowervp) vrele(un->un_uppervp); un->un_uppervp = uppervp; + un->un_uppersz = VNOVAL; } if (docache && (ohash != nhash)) { @@ -162,6 +165,47 @@ union_newupper(un, uppervp) union_updatevp(un, uppervp, un->un_lowervp); } +/* + * Keep track of size changes in the underlying vnodes. + * If the size changes, then callback to the vm layer + * giving priority to the upper layer size. + */ +void +union_newsize(vp, uppersz, lowersz) + struct vnode *vp; + off_t uppersz, lowersz; +{ + struct union_node *un; + off_t sz; + + /* only interested in regular files */ + if (vp->v_type != VREG) + return; + + un = VTOUNION(vp); + sz = VNOVAL; + + if ((uppersz != VNOVAL) && (un->un_uppersz != uppersz)) { + un->un_uppersz = uppersz; + if (sz == VNOVAL) + sz = un->un_uppersz; + } + + if ((lowersz != VNOVAL) && (un->un_lowersz != lowersz)) { + un->un_lowersz = lowersz; + if (sz == VNOVAL) + sz = un->un_lowersz; + } + + if (sz != VNOVAL) { +#ifdef UNION_DIAGNOSTIC + printf("union: %s size now %ld\n", + uppersz != VNOVAL ? "upper" : "lower", (long) sz); +#endif + vnode_pager_setsize(vp, sz); + } +} + /* * allocate a union_node/vnode pair. the vnode is * referenced and locked. the new vnode is returned @@ -398,7 +442,9 @@ loop: un = VTOUNION(*vpp); un->un_vnode = *vpp; un->un_uppervp = uppervp; + un->un_uppersz = VNOVAL; un->un_lowervp = lowervp; + un->un_lowersz = VNOVAL; un->un_openl = 0; un->un_flags = UN_LOCKED; if (un->un_uppervp) diff --git a/usr/src/sys/miscfs/union/union_vnops.c b/usr/src/sys/miscfs/union/union_vnops.c index b147412715..f165b98132 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 8.9 (Berkeley) %G% + * @(#)union_vnops.c 8.10 (Berkeley) %G% */ #include @@ -570,7 +570,8 @@ union_access(ap) } /* - * We handle getattr only to change the fsid. + * We handle getattr only to change the fsid and + * track object sizes */ int union_getattr(ap) @@ -615,6 +616,7 @@ union_getattr(ap) 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) { @@ -632,6 +634,7 @@ union_getattr(ap) VOP_UNLOCK(vp); if (error) return (error); + union_newsize(ap->a_vp, VNOVAL, vap->va_size); } if ((vap != ap->a_vap) && (vap->va_type == VDIR)) @@ -685,6 +688,8 @@ union_setattr(ap) 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 { error = EROFS; } @@ -713,6 +718,25 @@ union_read(ap) 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); } @@ -737,6 +761,23 @@ union_write(ap) 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); } -- 2.20.1