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 + -
显示快捷键?