union_vnops.c
来自「早期freebsd实现」· C语言 代码 · 共 1,496 行 · 第 1/3 页
C
1,496 行
bad: vrele(fdvp); vrele(fvp); vput(tdvp); if (tvp) vput(tvp); return (error);}intunion_mkdir(ap) struct vop_mkdir_args /* { struct vnode *a_dvp; struct vnode **a_vpp; struct componentname *a_cnp; struct vattr *a_vap; } */ *ap;{ struct union_node *un = VTOUNION(ap->a_dvp); struct vnode *dvp = un->un_uppervp; if (dvp) { int error; struct vnode *vp; FIXUP(un); VREF(dvp); un->un_flags |= UN_KLOCK; vput(ap->a_dvp); error = VOP_MKDIR(dvp, &vp, ap->a_cnp, ap->a_vap); if (error) return (error); error = union_allocvp( ap->a_vpp, ap->a_dvp->v_mount, ap->a_dvp, NULLVP, ap->a_cnp, vp, NULLVP); if (error) vput(vp); return (error); } vput(ap->a_dvp); return (EROFS);}intunion_rmdir(ap) struct vop_rmdir_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_RMDIR(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_symlink(ap) struct vop_symlink_args /* { struct vnode *a_dvp; struct vnode **a_vpp; struct componentname *a_cnp; struct vattr *a_vap; char *a_target; } */ *ap;{ struct union_node *un = VTOUNION(ap->a_dvp); struct vnode *dvp = un->un_uppervp; if (dvp) { 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); error = VOP_SYMLINK(dvp, &vp, ap->a_cnp, ap->a_vap, ap->a_target); *ap->a_vpp = NULLVP; return (error); } vput(ap->a_dvp); return (EROFS);}/* * union_readdir works in concert with getdirentries and * readdir(3) to provide a list of entries in the unioned * directories. getdirentries is responsible for walking * down the union stack. readdir(3) is responsible for * eliminating duplicate names from the returned data stream. */intunion_readdir(ap) struct vop_readdir_args /* { struct vnodeop_desc *a_desc; struct vnode *a_vp; struct uio *a_uio; struct ucred *a_cred; } */ *ap;{ int error = 0; struct union_node *un = VTOUNION(ap->a_vp); if (un->un_uppervp) { FIXUP(un); error = VOP_READDIR(un->un_uppervp, ap->a_uio, ap->a_cred); } return (error);}intunion_readlink(ap) struct vop_readlink_args /* { struct vnode *a_vp; struct uio *a_uio; 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_READLINK(vp, ap->a_uio, ap->a_cred); if (dolock) VOP_UNLOCK(vp); return (error);}intunion_abortop(ap) struct vop_abortop_args /* { struct vnode *a_dvp; struct componentname *a_cnp; } */ *ap;{ int error; struct vnode *vp = OTHERVP(ap->a_dvp); struct union_node *un = VTOUNION(ap->a_dvp); int islocked = un->un_flags & UN_LOCKED; int dolock = (vp == LOWERVP(ap->a_dvp)); 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); return (error);}intunion_inactive(ap) struct vop_inactive_args /* { struct vnode *a_vp; } */ *ap;{ /* * Do nothing (and _don't_ bypass). * Wait to vrele lowervp until reclaim, * so that until then our union_node is in the * cache and reusable. * * NEEDSWORK: Someday, consider inactive'ing * the lowervp and then trying to reactivate it * with capabilities (v_id) * like they do in the name lookup cache code. * That's too much work for now. */#ifdef UNION_DIAGNOSTIC struct union_node *un = VTOUNION(ap->a_vp); if (un->un_flags & UN_LOCKED) panic("union: inactivating locked node");#endif return (0);}intunion_reclaim(ap) struct vop_reclaim_args /* { struct vnode *a_vp; } */ *ap;{ union_freevp(ap->a_vp); return (0);}intunion_lock(ap) struct vop_lock_args *ap;{ struct vnode *vp = ap->a_vp; struct union_node *un;start: while (vp->v_flag & VXLOCK) { vp->v_flag |= VXWANT; sleep((caddr_t)vp, PINOD); } un = VTOUNION(vp); if (un->un_uppervp) { if ((un->un_flags & UN_ULOCK) == 0) { un->un_flags |= UN_ULOCK; VOP_LOCK(un->un_uppervp); }#ifdef DIAGNOSTIC if (un->un_flags & UN_KLOCK) panic("union: dangling upper lock");#endif } if (un->un_flags & UN_LOCKED) {#ifdef DIAGNOSTIC if (curproc && un->un_pid == curproc->p_pid && un->un_pid > -1 && curproc->p_pid > -1) panic("union: locking against myself");#endif un->un_flags |= UN_WANT; sleep((caddr_t) &un->un_flags, PINOD); goto start; }#ifdef DIAGNOSTIC if (curproc) un->un_pid = curproc->p_pid; else un->un_pid = -1;#endif un->un_flags |= UN_LOCKED; return (0);}intunion_unlock(ap) struct vop_lock_args *ap;{ struct union_node *un = VTOUNION(ap->a_vp);#ifdef DIAGNOSTIC if ((un->un_flags & UN_LOCKED) == 0) panic("union: unlock unlocked node"); if (curproc && un->un_pid != curproc->p_pid && curproc->p_pid > -1 && un->un_pid > -1) panic("union: unlocking other process's union node");#endif un->un_flags &= ~UN_LOCKED; if ((un->un_flags & (UN_ULOCK|UN_KLOCK)) == UN_ULOCK) VOP_UNLOCK(un->un_uppervp); un->un_flags &= ~(UN_ULOCK|UN_KLOCK); if (un->un_flags & UN_WANT) { un->un_flags &= ~UN_WANT; wakeup((caddr_t) &un->un_flags); }#ifdef DIAGNOSTIC un->un_pid = 0;#endif return (0);}intunion_bmap(ap) struct vop_bmap_args /* { struct vnode *a_vp; daddr_t a_bn; struct vnode **a_vpp; daddr_t *a_bnp; int *a_runp; } */ *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_BMAP(vp, ap->a_bn, ap->a_vpp, ap->a_bnp, ap->a_runp); if (dolock) VOP_UNLOCK(vp); return (error);}intunion_print(ap) struct vop_print_args /* { struct vnode *a_vp; } */ *ap;{ struct vnode *vp = ap->a_vp; printf("\ttag VT_UNION, vp=%x, uppervp=%x, lowervp=%x\n", vp, UPPERVP(vp), LOWERVP(vp)); return (0);}intunion_islocked(ap) struct vop_islocked_args /* { struct vnode *a_vp; } */ *ap;{ return ((VTOUNION(ap->a_vp)->un_flags & UN_LOCKED) ? 1 : 0);}intunion_pathconf(ap) struct vop_pathconf_args /* { struct vnode *a_vp; int a_name; int *a_retval; } */ *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_PATHCONF(vp, ap->a_name, ap->a_retval); if (dolock) VOP_UNLOCK(vp); return (error);}intunion_advlock(ap) struct vop_advlock_args /* { struct vnode *a_vp; caddr_t a_id; int a_op; struct flock *a_fl; int a_flags; } */ *ap;{ return (VOP_ADVLOCK(OTHERVP(ap->a_vp), ap->a_id, ap->a_op, ap->a_fl, ap->a_flags));}/* * XXX - vop_strategy must be hand coded because it has no * vnode in its arguments. * This goes away with a merged VM/buffer cache. */intunion_strategy(ap) struct vop_strategy_args /* { struct buf *a_bp; } */ *ap;{ struct buf *bp = ap->a_bp; int error; struct vnode *savedvp; savedvp = bp->b_vp; bp->b_vp = OTHERVP(bp->b_vp);#ifdef DIAGNOSTIC if (bp->b_vp == NULLVP) panic("union_strategy: nil vp"); if (((bp->b_flags & B_READ) == 0) && (bp->b_vp == LOWERVP(savedvp))) panic("union_strategy: writing to lowervp");#endif error = VOP_STRATEGY(bp); bp->b_vp = savedvp; return (error);}/* * Global vfs data structures */int (**union_vnodeop_p)();struct vnodeopv_entry_desc union_vnodeop_entries[] = { { &vop_default_desc, vn_default_error }, { &vop_lookup_desc, union_lookup }, /* lookup */ { &vop_create_desc, union_create }, /* create */ { &vop_mknod_desc, union_mknod }, /* mknod */ { &vop_open_desc, union_open }, /* open */ { &vop_close_desc, union_close }, /* close */ { &vop_access_desc, union_access }, /* access */ { &vop_getattr_desc, union_getattr }, /* getattr */ { &vop_setattr_desc, union_setattr }, /* setattr */ { &vop_read_desc, union_read }, /* read */ { &vop_write_desc, union_write }, /* write */ { &vop_ioctl_desc, union_ioctl }, /* ioctl */ { &vop_select_desc, union_select }, /* select */ { &vop_mmap_desc, union_mmap }, /* mmap */ { &vop_fsync_desc, union_fsync }, /* fsync */ { &vop_seek_desc, union_seek }, /* seek */ { &vop_remove_desc, union_remove }, /* remove */ { &vop_link_desc, union_link }, /* link */ { &vop_rename_desc, union_rename }, /* rename */ { &vop_mkdir_desc, union_mkdir }, /* mkdir */ { &vop_rmdir_desc, union_rmdir }, /* rmdir */ { &vop_symlink_desc, union_symlink }, /* symlink */ { &vop_readdir_desc, union_readdir }, /* readdir */ { &vop_readlink_desc, union_readlink }, /* readlink */ { &vop_abortop_desc, union_abortop }, /* abortop */ { &vop_inactive_desc, union_inactive }, /* inactive */ { &vop_reclaim_desc, union_reclaim }, /* reclaim */ { &vop_lock_desc, union_lock }, /* lock */ { &vop_unlock_desc, union_unlock }, /* unlock */ { &vop_bmap_desc, union_bmap }, /* bmap */ { &vop_strategy_desc, union_strategy }, /* strategy */ { &vop_print_desc, union_print }, /* print */ { &vop_islocked_desc, union_islocked }, /* islocked */ { &vop_pathconf_desc, union_pathconf }, /* pathconf */ { &vop_advlock_desc, union_advlock }, /* advlock */#ifdef notdef { &vop_blkatoff_desc, union_blkatoff }, /* blkatoff */ { &vop_valloc_desc, union_valloc }, /* valloc */ { &vop_vfree_desc, union_vfree }, /* vfree */ { &vop_truncate_desc, union_truncate }, /* truncate */ { &vop_update_desc, union_update }, /* update */ { &vop_bwrite_desc, union_bwrite }, /* bwrite */#endif { (struct vnodeop_desc*)NULL, (int(*)())NULL }};struct vnodeopv_desc union_vnodeop_opv_desc = { &union_vnodeop_p, union_vnodeop_entries };
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?