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

📄 tfs_update.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef lintstatic char sccsid[] = "@(#)tfs_update.c 1.1 92/07/30 Copyr 1988 Sun Micro";#endif/* * Copyright (c) 1987 Sun Microsystems, Inc. */#include <nse/param.h>#include "headers.h"#include "vnode.h"#include "tfs.h"#include "subr.h"/* * Whiteout entries should be set/unset only once if multiple * vnodes have a pointers to a pnode. */typedef enum {	WO_UNKNOWN, WO_SET, WO_NOT_SET, WO_FAILED, WO_CLEARED} Whiteout_status;/* * Routines which update directories.  These routines maintain the * v_layer and v_back_layer fields in vnodes, which let us know if a * whiteout entry needs to be created when a file is removed. */int		update_directory();static int	dir_rename_file();static int	dir_add_file();static int	dir_remove_file();static int	dir_clear_file();static int	remove_or_whiteout_file();static void	dir_forward();static void	move_pnodes();static struct vnode *vnode_of_pnode();static struct vnode *root_vnode_of();static void	discard_child_vnodes();static void	clear_update_flags();/* * Routines which update directories. *//* * The directory with pnode 'pp' has changed state.  Make sure that all * vnodes with pointers to this pnode are updated.  'name' is the name of * the file added/removed/cleared, and 'type' is the type of * modification that occurred. *//* VARARGS3 */intupdate_directory(pp, name, type, arg1, arg2, arg3, arg4)	struct pnode	*pp;	char		*name;	int		type;	char		*arg1;	char		*arg2;	char		*arg3;	char		*arg4;{	struct linknode	*lp;	struct linknode	*lp_next;	struct vnode	*pvp;	struct vnode	*vp;	int		result;	int		err = 0;	Whiteout_status	wo_status = WO_UNKNOWN;	Whiteout_status	wo_status2 = WO_UNKNOWN;	char		nam[MAXNAMLEN];	/*	 * 'name' may be freed.	 */	if (name) {		strcpy(nam, name);	}	for (lp = pp->p_link; lp != NULL; lp = lp_next) {		/*		 * lp may be freed, so determine lp_next now		 */		lp_next = lp->l_next;		pvp = lp->l_vnode;		if (pvp->v_pnode->p_swapped && pvp->v_dir_valid &&		    type != DIR_FLUSH) {			/*			 * Swapping in a directory changes the linknodes,			 * so iterate through the linknode list again.			 */#ifdef TFSDEBUG			dprint(tfsdebug, 4,			       "update_directory: calling swap_in\n");#endif TFSDEBUG			swap_in_directory(pvp->v_pnode);			lp_next = pp->p_link;			continue;		}		if (name) {			vp = find_vnode(pvp, nam);		}		result = 0;		switch (type) {		case DIR_ADD_FILE:			if (vp == NULL) {				vp = create_vnode(pvp, nam, (long) 0);			}			result = dir_add_file(pvp, vp, lp->l_layer,					      &wo_status);			/*			 * If we just added a file to a previously empty			 * directory, put the dir. in the swap queue.			 * XXX should do the same for rename			 */			if (result == 0 && !pvp->v_pnode->p_in_queue &&			    pvp->v_back_owner) {				swqueue_add_pnode(pvp->v_pnode);				lp_next = pp->p_link;				continue;			}			break;		case DIR_REMOVE_FILE:			if (vp != NULL) {				result = dir_remove_file(pvp, vp, lp->l_layer,							 (bool_t) arg1,							 (bool_t) arg2,							 (Nse_whiteout *) arg3,							 &wo_status);			}			break;		case DIR_CLEAR_FILE:			if (vp != NULL) {				result = dir_clear_file(pvp, vp, lp->l_layer,							&wo_status);			}			break;		case DIR_RENAME_FILE:			result = dir_rename_file(pvp, vp, lp->l_layer, pp,						 (struct pnode *) arg1, arg2,						 (bool_t) arg3, (bool_t) arg4,						 &wo_status, &wo_status2);			break;		case DIR_UTIME_FILE:			if (vp != NULL) {				vp->v_mtime = (long) arg1;			}			break;		case DIR_FLUSH:			update_ctime(pvp, TRUE);			vnode_tree_flush(pvp);			break;		case DIR_FORWARD:			dir_forward(pvp, lp->l_layer, (struct pnode *) arg1);			break;		}		if (result != 0 && err == 0) {			err = result;		}	}	if (type == DIR_REMOVE_FILE || type == DIR_CLEAR_FILE ||	    type == DIR_RENAME_FILE) {		clear_update_flags(pp);	}	return (err);}/* * 'vp' is the old vnode of a file that was renamed from directory 'pvp' * at layer 'layer' into the directory 'new_parentp' with new name * 'new_name'.  We preserve the nodeid of the file on rename, and also * preserve the parent-child relationship of vnodes if we are renaming * a directory. */static intdir_rename_file(pvp, vp, layer, old_parentp, new_parentp, new_name,		must_set_wo, is_directory, wo_status, wo_status2)	struct vnode	*pvp;	struct vnode	*vp;	int		layer;	struct pnode	*old_parentp;	struct pnode	*new_parentp;	char		*new_name;	bool_t		must_set_wo;	bool_t		is_directory;	Whiteout_status	*wo_status;	Whiteout_status	*wo_status2;{	struct vnode	*newpvp;	struct vnode	*nvp;	struct vnode	*childvp = NULL;	long		nodeid = 0;	struct pnode	*pp = NULL;	bool_t		dir_valid;	int		old_dir_layer = INVALID_LAYER;	int		result;	if (new_parentp == old_parentp) {		newpvp = pvp;	} else {		newpvp = vnode_of_pnode(new_parentp, pvp);	}	if (vp != NULL) {		if (!vp->v_whited_out) {			/*			 * Assign a new fhandle for the vnode, so that if it			 * becomes a whiteout vnode and is later unwhited-out,			 * two vnodes won't end up with the same fhandle.			 */			nodeid = vp->v_fhid;			fhandle_remove(vp);			vp->v_fhid = ++next_fhandle;			fhandle_insert(vp);			if (is_directory) {				old_dir_layer = vp->v_layer;			}		}		if (newpvp != NULL) {			childvp = CHILD_VNODE(vp);			CHILD_VNODE(vp) = NULL;			pp = vp->v_pnode;			vp->v_pnode = NULL;			dir_valid = vp->v_dir_valid;			if (is_directory) {				new_parentp = newpvp->v_pnode;			}		}		if (result = dir_remove_file(pvp, vp, layer, must_set_wo,					is_directory, (Nse_whiteout *) NULL,					wo_status)) {			if (pp != NULL) {				vp->v_pnode = pp;			}			if (childvp != NULL) {				CHILD_VNODE(vp) = childvp;			}			return (result);		}	}	if (newpvp == NULL) {		return (0);	}	if (newpvp->v_pnode->p_swapped) {		swap_in_directory(newpvp->v_pnode);	}	nvp = find_vnode(newpvp, new_name);	if (nvp == NULL) {		nvp = create_vnode(newpvp, new_name, nodeid);	} else if (nodeid != 0) {		fhandle_remove(nvp);		nvp->v_fhid = nodeid;		fhandle_insert(nvp);	}	if (pp != NULL) {		if (PARENT_PNODE(pp) != new_parentp ||		    !NSE_STREQ(pp->p_name, new_name)) {			rename_pnode(pp, new_parentp, new_name);		}		if (nvp->v_pnode != NULL) {			release_pnodes(nvp);		}		if (pp->p_type == PTYPE_DIR) {			move_pnodes(pp, vp, nvp);		}		nvp->v_pnode = pp;	}	nvp->v_dont_flush = TRUE;	result = dir_add_file(newpvp, nvp, layer, wo_status2);	if (result == 0 && is_directory && old_dir_layer < layer) {		result = dir_add_file(newpvp, nvp, old_dir_layer, wo_status2);	}	nvp->v_dont_flush = FALSE;	if (childvp != NULL) {		CHILD_VNODE(nvp) = childvp;		while (childvp != NULL) {			PARENT_VNODE(childvp) = nvp;			childvp = NEXT_VNODE(childvp);		}		if (dir_valid && nvp->v_pnode != NULL) {			nvp->v_dir_valid = TRUE;		}	}	if (result != 0) {		vnode_tree_flush(nvp);	}	return (result);}/* * 'vp' is the vnode for a file that was added to the directory 'pvp' at * layer 'layer'. */static intdir_add_file(pvp, vp, layer, wo_status)	struct vnode	*pvp;	struct vnode	*vp;	int		layer;	Whiteout_status	*wo_status;{	int		back_layer;	bool_t		back_wo;	int		result = 0;	if (vp->v_layer < layer) {		if (vp->v_back_layer >= layer) {			vp->v_back_layer = layer;			vp->v_back_whited_out = FALSE;		}		return (0);	}	if ((vp->v_layer == INVALID_LAYER) || (vp->v_layer > layer)) {		back_layer = vp->v_layer;		back_wo = vp->v_whited_out;		if (!vp->v_dont_flush) {			vnode_tree_flush(vp);		}		vp->v_back_layer = back_layer;		vp->v_back_whited_out = back_wo;		vp->v_layer = layer;	} else {	/* vp->v_layer == layer */		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;			}		}	}	vp->v_whited_out = FALSE;	return (result);}/* * A file with vnode 'vp' was removed from the directory 'pvp' at layer * 'layer'.  Update the directory accordingly.  May need to whiteout * the file if it would show through from a back fs.  If 'must_set_wo' is * TRUE, always whiteout the file that was removed, even if it doesn't * exist in a back fs. */static intdir_remove_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;

⌨️ 快捷键说明

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