⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tfs_update.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
{	int		result = 0;	if (vp->v_layer == INVALID_LAYER) {		return (0);	}	if (vp->v_layer < layer) {		/*		 * if vp->v_back_layer < layer, do nothing;		 * vp->v_back_layer > layer impossible		 */		if (vp->v_back_layer == layer) {			vp->v_back_layer = UNKNOWN_LAYER;			vp->v_back_whited_out = FALSE;			if (is_directory) {				return (remove_or_whiteout_file(pvp, vp, layer,								must_set_wo,								is_directory,								wo_listp,								wo_status));			}		}		return (0);	}	if (CHILD_VNODE(vp) != NULL) {		/*		 * This can happen if rmdir removes a directory which		 * contained whiteout vnodes, or if rename moves a		 * directory to a different parent directory.		 */		discard_child_vnodes(vp);	}	if (vp->v_whited_out) {		return (0);	}	if (vp->v_layer == layer) {		if (vp->v_layer > 0) {			update_ctime(pvp, TRUE);		}		if (vp->v_back_layer == INVALID_LAYER && !must_set_wo) {			/*			 * File doesn't exist in back -- throw away			 * the reference to it.			 */			free_vnode(vp);			return (0);		}		if (vp->v_back_layer == UNKNOWN_LAYER) {			return (remove_or_whiteout_file(pvp, vp, layer,							must_set_wo,							is_directory,							wo_listp,							wo_status));		} else if (vp->v_back_whited_out) {			vp->v_layer = vp->v_back_layer;			vp->v_back_layer = UNKNOWN_LAYER;			vp->v_back_whited_out = FALSE;		} else if (IS_WRITEABLE(vp) && *wo_status != WO_SET &&			   *wo_status != WO_FAILED) {			if (result = set_whiteout(pvp, vp, wo_listp)) {				*wo_status = WO_FAILED;			} else {				*wo_status = WO_SET;			}		}	} else {		int		old_layer;		/*		 * vp->v_layer > layer (can happen if a file is removed which		 * is showing through from a read-only layer.)		 */		update_ctime(pvp, TRUE);		old_layer = vp->v_layer;		vp->v_layer = layer;		if (IS_WRITEABLE(vp) && *wo_status != WO_SET &&		    *wo_status != WO_FAILED) {			if (result = set_whiteout(pvp, vp, wo_listp)) {				*wo_status = WO_FAILED;			} else {				*wo_status = WO_SET;			}		}		if (result == 0 && *wo_status != WO_FAILED) {			vp->v_back_layer = old_layer;			vp->v_back_whited_out = FALSE;		} else {			vp->v_layer = old_layer;		}	}	if (result == 0 && *wo_status != WO_FAILED) {		vp->v_whited_out = TRUE;		if (vp->v_pnode != NULL) {			release_pnodes(vp);		}		/*		 * Set v_dir_valid to FALSE in case this was a dir vnode		 * (it may be unwhited-out in the future, in which case we		 * don't want it to appear to be a valid directory.)		 */		vp->v_dir_valid = FALSE;	}	return (result);}/* * Clear the entry for file with vnode 'vp' in the directory 'pvp' at layer * 'layer', and allow the back instance of the file to show through.  If * there is a whiteout entry for the file, clear it. */static intdir_clear_file(pvp, vp, layer, wo_status)	struct vnode	*pvp;	struct vnode	*vp;	int		layer;	Whiteout_status	*wo_status;{	int		result = 0;	if (*wo_status == WO_FAILED) {		return (0);	}	if (vp->v_layer == layer) {		if (!vp->v_whited_out && vp->v_layer > 0) {			update_ctime(pvp, TRUE);		}		if (IS_WRITEABLE(vp) && vp->v_whited_out &&		    *wo_status != WO_CLEARED && *wo_status != WO_FAILED) {			if (result = unwhiteout(pvp, vp)) {				*wo_status = WO_FAILED;			} else {				*wo_status = WO_CLEARED;			}		}		if (*wo_status == WO_FAILED) {			return (result);		}		if (vp->v_back_layer == UNKNOWN_LAYER) {			pvp->v_dir_valid = FALSE;		} else {			/*			 * v_back_layer may be INVALID_LAYER here -- don't			 * release the vnode so that tfs_push will work			 */			vp->v_layer = vp->v_back_layer;			vp->v_whited_out = vp->v_back_whited_out;			vp->v_back_layer = UNKNOWN_LAYER;			vp->v_back_whited_out = FALSE;		}		vp->v_dir_valid = FALSE;		if (vp->v_pnode != NULL && result == 0) {			release_pnodes(vp);		}	} else if (vp->v_layer < layer) {		/*		 * if vp->v_back_layer < layer, do nothing;		 * vp->v_back_layer > layer impossible		 */		if (vp->v_back_layer == layer) {			vp->v_back_layer = UNKNOWN_LAYER;			vp->v_back_whited_out = FALSE;		}	}	/*	 * vp->v_layer > layer impossible, unless this routine called twice	 * on same file	 */	return (result);}/* * This routine is called when a file has been removed and we don't know * whether or not the name exists in another layer further back.  This can * happen when a directory is removed, because more than one layer is * removed.  We can only keep track of two layers for a file with v_layer & * v_back_layer, so when the second layer is removed, the parent directory * needs to be revalidated before we can determine whether or not a * whiteout entry needs to be created. */static intremove_or_whiteout_file(pvp, vp, layer, must_set_wo, is_directory, wo_listp,			wo_status)	struct vnode	*pvp;	struct vnode	*vp;	int		layer;	bool_t		must_set_wo;	bool_t		is_directory;	Nse_whiteout	*wo_listp;	Whiteout_status	*wo_status;{	struct pnode	*pp;	int		result;	switch (*wo_status) {	case WO_SET:		vp->v_layer = layer;		vp->v_whited_out = TRUE;		if (vp->v_pnode != NULL) {			release_pnodes(vp);		}		if (CHILD_VNODE(vp) != NULL) {			discard_child_vnodes(vp);		}		return (0);	case WO_NOT_SET:		vnode_tree_release(vp);		return (0);	case WO_FAILED:		return (0);	default:		/*		 * Make sure that the pnode at 'layer' is not freed		 * by validate_directory as it is being held by		 * update_directory.		 */		pp = get_pnode_at_layer(pvp, layer);		pp->p_refcnt++;		pvp->v_dir_valid = FALSE;		result = validate_directory(pvp);		pp->p_refcnt--;		if (result) {			return (result);		}		if (vp->v_layer == INVALID_LAYER) {			vnode_tree_release(vp);			*wo_status = WO_NOT_SET;			return (0);		} else {			/* vp->v_layer > layer */			return (dir_remove_file(pvp, vp, layer, must_set_wo,						is_directory, wo_listp,						wo_status));		}	}}/* * The pnode for 'pvp' at layer 'layer' has been changed to 'newp'. */static voiddir_forward(pvp, layer, newp)	struct vnode	*pvp;	int		layer;	struct pnode	*newp;{	struct pnode	*pp;	struct pnode	*prev_pp;	struct pnode	*next_pp;	prev_pp = get_pnode_at_layer(pvp, (unsigned) layer - 1);	pp = release_linknode(pvp, prev_pp);	set_next_pnode(pvp, prev_pp, newp, layer - 1);	next_pp = release_linknode(pvp, pp);	free_pnode(pp);	set_next_pnode(pvp, newp, next_pp, layer);	newp->p_refcnt++;}/* * Transfer directory pnodes from vnode 'old_vp' to vnode 'new_vp'. * ('old_vp' may have been freed.) */static voidmove_pnodes(pp, old_vp, new_vp)	struct pnode	*pp;	struct vnode	*old_vp;	struct vnode	*new_vp;{	struct pnode	*next_pp;	int		layer = 0;	if (!has_linknode(old_vp, pp)) {		return;	}	while (pp) {		next_pp = release_linknode(old_vp, pp);		set_next_pnode(new_vp, pp, next_pp, layer);		pp = next_pp;		layer++;	}}/* * Returns vnode pointing to pnode pp which is under the same mountpt as vnode * pvp.  Needed for rename when the source and destination directories are * not the same. */static struct vnode *vnode_of_pnode(pp, pvp)	struct pnode	*pp;	struct vnode	*pvp;{	struct vnode	*rootvp;	struct vnode	*vp2;	struct linknode	*lp;	rootvp = root_vnode_of(pvp);	lp = pp->p_link;	while (lp != NULL) {		vp2 = lp->l_vnode;		if (vp2->v_environ_id == pvp->v_environ_id &&		    root_vnode_of(vp2) == rootvp) {			return (vp2);		}		lp = lp->l_next;	}	return (NULL);}static struct vnode *root_vnode_of(vp)	struct vnode	*vp;{	while (vp != NULL && !vp->v_is_mount_pt) {		vp = PARENT_VNODE(vp);	}	return (vp);}static voiddiscard_child_vnodes(pvp)	struct vnode	*pvp;{	struct vnode	*vp;	struct vnode	*nextvp;	for (vp = CHILD_VNODE(pvp); vp != NULL; vp = nextvp) {		nextvp = NEXT_VNODE(vp);		vnode_tree_release(vp);	}}static voidclear_update_flags(pp)	struct pnode	*pp;{	struct linknode	*lp;	for (lp = pp->p_link; lp != NULL; lp = lp->l_next) {		lp->l_vnode->v_pnode->p_updated = FALSE;	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -