union_vnops.c
来自「早期freebsd实现」· C语言 代码 · 共 1,496 行 · 第 1/3 页
C
1,496 行
(void) VOP_OPEN(un->un_uppervp, FREAD, cred, p); } un->un_openl = 0; if (error == 0) error = VOP_OPEN(un->un_uppervp, mode, cred, p); return (error); } /* * Just open the lower vnode */ un->un_openl++; VOP_LOCK(tvp); error = VOP_OPEN(tvp, mode, cred, p); VOP_UNLOCK(tvp); return (error); } FIXUP(un); error = VOP_OPEN(tvp, mode, cred, p); return (error);}intunion_close(ap) struct vop_close_args /* { struct vnode *a_vp; int a_fflag; struct ucred *a_cred; struct proc *a_p; } */ *ap;{ struct union_node *un = VTOUNION(ap->a_vp); struct vnode *vp; if (un->un_uppervp) { vp = un->un_uppervp; } else {#ifdef UNION_DIAGNOSTIC if (un->un_openl <= 0) panic("union: un_openl cnt");#endif --un->un_openl; vp = un->un_lowervp; } return (VOP_CLOSE(vp, ap->a_fflag, ap->a_cred, ap->a_p));}/* * Check access permission on the union vnode. * The access check being enforced is to check * against both the underlying vnode, and any * copied vnode. This ensures that no additional * file permissions are given away simply because * the user caused an implicit file copy. */intunion_access(ap) struct vop_access_args /* { struct vnodeop_desc *a_desc; struct vnode *a_vp; int a_mode; struct ucred *a_cred; struct proc *a_p; } */ *ap;{ struct union_node *un = VTOUNION(ap->a_vp); int error = EACCES; struct vnode *vp; if (vp = un->un_uppervp) { FIXUP(un); return (VOP_ACCESS(vp, ap->a_mode, ap->a_cred, ap->a_p)); } if (vp = un->un_lowervp) { 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); } return (error);}/* * We handle getattr only to change the fsid. */intunion_getattr(ap) struct vop_getattr_args /* { struct vnode *a_vp; struct vattr *a_vap; struct ucred *a_cred; struct proc *a_p; } */ *ap;{ int error; struct union_node *un = VTOUNION(ap->a_vp); struct vnode *vp = un->un_uppervp; struct vattr *vap; struct vattr va; /* * 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) { FIXUP(un); error = VOP_GETATTR(vp, vap, ap->a_cred, ap->a_p); if (error) return (error); } 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, vap, ap->a_cred, ap->a_p); VOP_UNLOCK(vp); if (error) return (error); } 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);}intunion_setattr(ap) struct vop_setattr_args /* { struct vnode *a_vp; struct vattr *a_vap; struct ucred *a_cred; struct proc *a_p; } */ *ap;{ struct union_node *un = VTOUNION(ap->a_vp); int error; /* * 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); } else { error = EROFS; } return (error);}intunion_read(ap) struct vop_read_args /* { struct vnode *a_vp; struct uio *a_uio; int a_ioflag; struct ucred *a_cred; } */ *ap;{ int error; struct vnode *vp = OTHERVP(ap->a_vp); int dolock = (vp == LOWERVP(ap->a_vp)); 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); return (error);}intunion_write(ap) struct vop_read_args /* { struct vnode *a_vp; struct uio *a_uio; int a_ioflag; struct ucred *a_cred; } */ *ap;{ int error; struct vnode *vp = OTHERVP(ap->a_vp); int dolock = (vp == LOWERVP(ap->a_vp)); 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); return (error);}intunion_ioctl(ap) struct vop_ioctl_args /* { struct vnode *a_vp; int a_command; caddr_t a_data; int a_fflag; struct ucred *a_cred; struct proc *a_p; } */ *ap;{ return (VOP_IOCTL(OTHERVP(ap->a_vp), ap->a_command, ap->a_data, ap->a_fflag, ap->a_cred, ap->a_p));}intunion_select(ap) struct vop_select_args /* { struct vnode *a_vp; int a_which; int a_fflags; struct ucred *a_cred; struct proc *a_p; } */ *ap;{ return (VOP_SELECT(OTHERVP(ap->a_vp), ap->a_which, ap->a_fflags, ap->a_cred, ap->a_p));}intunion_mmap(ap) struct vop_mmap_args /* { struct vnode *a_vp; int a_fflags; struct ucred *a_cred; struct proc *a_p; } */ *ap;{ return (VOP_MMAP(OTHERVP(ap->a_vp), ap->a_fflags, ap->a_cred, ap->a_p));}intunion_fsync(ap) struct vop_fsync_args /* { struct vnode *a_vp; struct ucred *a_cred; int a_waitfor; struct proc *a_p; } */ *ap;{ int error = 0; struct vnode *targetvp = OTHERVP(ap->a_vp); if (targetvp) { 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) VOP_UNLOCK(targetvp); } return (error);}intunion_seek(ap) struct vop_seek_args /* { struct vnode *a_vp; off_t a_oldoff; off_t a_newoff; struct ucred *a_cred; } */ *ap;{ return (VOP_SEEK(OTHERVP(ap->a_vp), ap->a_oldoff, ap->a_newoff, ap->a_cred));}intunion_remove(ap) struct vop_remove_args /* { struct vnode *a_dvp; struct vnode *a_vp; struct componentname *a_cnp; } */ *ap;{ int error; struct union_node *dun = VTOUNION(ap->a_dvp); struct union_node *un = VTOUNION(ap->a_vp); if (dun->un_uppervp && un->un_uppervp) { 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); error = VOP_REMOVE(dvp, vp, ap->a_cnp); if (!error) union_removed_upper(un); /* * XXX: should create a whiteout here */ } else { /* * XXX: should create a whiteout here */ vput(ap->a_dvp); vput(ap->a_vp); error = EROFS; } return (error);}intunion_link(ap) struct vop_link_args /* { struct vnode *a_vp; struct vnode *a_tdvp; 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; FIXUP(dun); VREF(dvp); dun->un_flags |= UN_KLOCK; vput(ap->a_vp); FIXUP(un); VREF(vp); vrele(ap->a_tdvp); error = VOP_LINK(dvp, vp, ap->a_cnp); } else { /* * XXX: need to copy to upper layer * and do the link there. */ vput(ap->a_vp); vrele(ap->a_tdvp); error = EROFS; } return (error);}intunion_rename(ap) struct vop_rename_args /* { struct vnode *a_fdvp; struct vnode *a_fvp; struct componentname *a_fcnp; struct vnode *a_tdvp; struct vnode *a_tvp; struct componentname *a_tcnp; } */ *ap;{ int error; struct vnode *fdvp = ap->a_fdvp; struct vnode *fvp = ap->a_fvp; struct vnode *tdvp = ap->a_tdvp; struct vnode *tvp = ap->a_tvp; if (fdvp->v_op == union_vnodeop_p) { /* always true */ struct union_node *un = VTOUNION(fdvp); if (un->un_uppervp == NULLVP) { error = EROFS; goto bad; } FIXUP(un); fdvp = un->un_uppervp; VREF(fdvp); vrele(ap->a_fdvp); } if (fvp->v_op == union_vnodeop_p) { /* always true */ struct union_node *un = VTOUNION(fvp); if (un->un_uppervp == NULLVP) { error = EROFS; goto bad; } FIXUP(un); fvp = un->un_uppervp; VREF(fvp); vrele(ap->a_fvp); } if (tdvp->v_op == union_vnodeop_p) { struct union_node *un = VTOUNION(tdvp); if (un->un_uppervp == NULLVP) { error = EROFS; goto bad; } tdvp = un->un_uppervp; VREF(tdvp); un->un_flags |= UN_KLOCK; vput(ap->a_tdvp); } if (tvp && 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; vput(ap->a_tvp); } return (VOP_RENAME(fdvp, fvp, ap->a_fcnp, tdvp, tvp, ap->a_tcnp));
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?