tfs_attrs.c

来自「操作系统SunOS 4.1.3版本的源码」· C语言 代码 · 共 367 行

C
367
字号
#ifndef lintstatic char sccsid[] = "@(#)tfs_attrs.c 1.1 92/07/30 Copyr 1988 Sun Micro";#endif/* * Copyright (c) 1987 Sun Microsystems, Inc. */#include <nse/param.h>#include <nse/util.h>#include "headers.h"#include "tfs.h"#include "vnode.h"#include "subr.h"#include <signal.h>/* * Routines to get attributes of files.  We maintain a (small) cache of * attributes to avoid redundant fstat's. */#define MAX_ATTRS	3		/* Maximum # of entries in cache */#define ATTR_TIMEOUT	10		/* Time that an attribute buffer					 * allowed to stay in the cache					 * after the last time it is used.					 */typedef struct Attr_cache {	struct pnode	*pnode;	struct nfsfattr	attrs;	long		last_use;	/* Last time these attrs used */	long		flush_time;	/* When these attrs should be					 * flushed from the cache */} *Attr_cache, Attr_cache_rec;static Attr_cache_rec attr_cache[MAX_ATTRS];static int	attr_timeout;static long	use_count;		/* Incremented every time attr					 * cache used */bool_t		attr_cache_on;int		getattrs_of();int		get_realattrs_of();void		fix_attrs();void		set_cached_attrs();static void	get_cached_attrs();void		flush_cached_attrs();bool_t		timeout_attr_cache();void		flush_all_attrs();static void	flush_and_close_fd();void		init_attr_cache();static Attr_cache find_attr_rec();static Attr_cache find_lru_attr();void		fattr_to_nattr();intgetattrs_of(vp, attrs)	struct vnode	*vp;	struct nfsfattr *attrs;{	int		result;	if (result = get_realattrs_of(vp, attrs)) {		return (result);	}#ifdef TFSDEBUG	dprint(tfsdebug, 3,"  getattrs_of => ino %d size %d blocks %d  times: a %d m %d c %d\n",		attrs->na_nodeid, attrs->na_size,		attrs->na_blocks, attrs->na_atime.tv_sec,		attrs->na_mtime.tv_sec, attrs->na_ctime.tv_sec);#endif TFSDEBUG	fix_attrs(vp, attrs);	return(0);}/* * Get the attributes of the vnode 'vp'.  If 'vp' is a directory vnode * without an open file descriptor, open an fd for it (through * change_to_dir.) */intget_realattrs_of(vp, attrs)	struct vnode	*vp;	struct nfsfattr *attrs;{	struct pnode	*pp;	char		name[MAXNAMLEN];	struct stat	statb;	int		fd;	pp = vp->v_pnode;	fd = pp->p_fd;	if (fd != 0) {		use_fd(fd);	}	if (pp->p_have_attrs) {		get_cached_attrs(pp, attrs);		return (0);	}	if (fd == 0) {		if ((pp->p_type == PTYPE_DIR) && (change_to_dir(pp) == 0)) {			fd = pp->p_fd;		} else {			ptoname(pp, name);			if (LSTAT(name, &statb) < 0) {				return (-1);			}			goto have_statb;		}	}	if (fstat(fd, &statb) < 0) {		close_fd(pp);		return (-1);	}have_statb:	fattr_to_nattr(&statb, attrs);	if (attr_cache_on) {		set_cached_attrs(pp, attrs);	}	return (0);}voidfix_attrs(vp, attrs)	struct vnode	*vp;	struct nfsfattr	*attrs;{	struct pnode	*pp;	/*	 * Set the nodeid to the fhandle id.  This is done because 1),	 * nodeids shouldn't change when a file is copied to the front fs	 * by a write operation, and 2), nodeids have to be unique to	 * guarantee that getwd will always work.	 */	attrs->na_nodeid = vp->v_fhid;	if (!IS_WRITEABLE(vp)) {		if (vp->v_back_owner) {			attrs->na_uid = current_user_id();		}		if (vp->v_mtime != 0) {			attrs->na_mtime.tv_sec = vp->v_mtime;		}	}	/*	 * If there are writes pending for this file, then set the file	 * size & mtime to the virtual size & mtime of the file.	 */	pp = vp->v_pnode;	if (pp->p_type == PTYPE_REG && pp->p_needs_write) {		attrs->na_mtime.tv_sec = pp->p_write_time;		attrs->na_size = pp->p_size;	}}voidset_cached_attrs(pp, attrs)	struct pnode	*pp;	struct nfsfattr	*attrs;{	Attr_cache	ac;	if ((pp->p_type == PTYPE_REG) && (!pp->p_needs_write)) {		pp->p_size = attrs->na_size;	}	ac = find_lru_attr();	if (ac->pnode != NULL) {		flush_and_close_fd(ac->pnode);	}	ac->pnode = pp;	BCOPY((char *) attrs, (char *) &ac->attrs, sizeof(struct nfsfattr));	ac->flush_time = get_current_time(FALSE) + attr_timeout;	ac->last_use = use_count++;	pp->p_have_attrs = 1;}static voidget_cached_attrs(pp, attrs)	struct pnode	*pp;	struct nfsfattr *attrs;{	Attr_cache	ac;	ac = find_attr_rec(pp);	BCOPY((char *) &ac->attrs, (char *) attrs, sizeof(struct nfsfattr));	ac->flush_time = get_current_time(FALSE) + attr_timeout;	ac->last_use = use_count++;}voidflush_cached_attrs(pp)	struct pnode	*pp;{	Attr_cache	ac;	if (pp->p_have_attrs) {		ac = find_attr_rec(pp);		ac->pnode = NULL;		pp->p_have_attrs = 0;	}}bool_ttimeout_attr_cache(now)	long		now;{	int		i;	bool_t		more_to_flush = FALSE;	if (!attr_cache_on) {		return (FALSE);	}	for (i = 0; i < MAX_ATTRS; i++) {		if (attr_cache[i].pnode != NULL) {			if (attr_cache[i].flush_time < now) {#ifdef TFSDEBUG{	char		pn[MAXPATHLEN];	ptopn(attr_cache[i].pnode, pn);	dprint(tfsdebug, 3, "flushing attrs of %s (flush_time %u)\n", pn,		attr_cache[i].flush_time);}#endif TFSDEBUG				flush_and_close_fd(attr_cache[i].pnode);				attr_cache[i].pnode = NULL;			} else {				more_to_flush = TRUE;			}		}	}	return (more_to_flush);}voidflush_all_attrs(){	int		i;	for (i = 0; i < MAX_ATTRS; i++) {		if (attr_cache[i].pnode != NULL) {			flush_and_close_fd(attr_cache[i].pnode);			attr_cache[i].pnode = NULL;		}	}}voidinit_attr_cache(){	attr_cache_on = TRUE;	attr_timeout = ATTR_TIMEOUT;}static voidflush_and_close_fd(pp)	struct pnode	*pp;{	pp->p_have_attrs = 0;	if ((pp->p_type == PTYPE_REG) && (pp->p_fd != 0) &&	    (!pp->p_needs_write)) {		close_fd(pp);	}}static Attr_cachefind_attr_rec(pp)	struct pnode	*pp;{	int		i;	for (i = 0; i < MAX_ATTRS; i++) {		if (attr_cache[i].pnode == pp) {			return (&attr_cache[i]);		}	}#ifdef TFSDEBUG	nse_log_message("warning: find_attr_rec could not find attrs!\n");#endif TFSDEBUG	return (NULL);}/* * Find the least recently used attrs. */static Attr_cachefind_lru_attr(){	long		min = attr_cache[0].last_use;	int		min_index = 0;	int		i;	for (i = 0; i < MAX_ATTRS; i++) {		if (attr_cache[i].pnode == NULL) {			return (&attr_cache[i]);		}		if (attr_cache[i].last_use < min) {			min = attr_cache[i].last_use;			min_index = i;		}	}	return (&attr_cache[min_index]);}/* * Convert stat struct information (from stat call) into nfsfattr struct. */voidfattr_to_nattr(fap, na)	struct stat    *fap;	struct nfsfattr *na;{	switch (fap->st_mode & S_IFMT) {	case S_IFDIR:		na->na_type = NFDIR;		break;	case S_IFCHR:		na->na_type = NFCHR;		break;	case S_IFBLK:		na->na_type = NFBLK;		break;	case S_IFREG:		na->na_type = NFREG;		break;	case S_IFLNK:		na->na_type = NFLNK;		break;	case S_IFSOCK:		na->na_type = NFNON;	/* XXX */		break;	default:		na->na_type = NFNON;		break;	}	na->na_nodeid = fap->st_ino;	na->na_fsid = fap->st_dev;	na->na_mode = fap->st_mode;	na->na_nlink = fap->st_nlink;	na->na_uid = fap->st_uid;	na->na_gid = fap->st_gid;	na->na_rdev = fap->st_rdev;	na->na_size = fap->st_size;	na->na_atime.tv_sec = fap->st_atime;	na->na_atime.tv_usec = 0;	na->na_mtime.tv_sec = fap->st_mtime;	na->na_mtime.tv_usec = 0;	na->na_ctime.tv_sec = fap->st_ctime;	na->na_ctime.tv_usec = 0;	na->na_blocksize = MIN(fap->st_blksize, NFS_MAXDATA);	na->na_blocks = fap->st_blocks / (fap->st_blksize / na->na_blocksize);}

⌨️ 快捷键说明

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