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

📄 ufs_namei.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
#ifndef lintstatic	char	*sccsid = "@(#)ufs_namei.c	4.4	(ULTRIX)	2/28/91";#endif lint/************************************************************************ *									* *			Copyright (c) 1986,87,88,89 by			* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//* ------------------------------------------------------------------------ * Modification History: /sys/fs/ufs/ufs_namei.c * * 27 Feb 91 -- chet *	Fix filesystem timestamping. * * 22-Jan-91 - prs *      Added fast symbolic link support. * * 10 May 90 -- prs *	Passed the expected g_id to ggrab() to avoid a deadly embrace *	for stale cache entries. * * 17 Jan 90 -- prs *	Fixed pathname resolution logic in POSIX mode. * * 14 Dec 89 -- prs *	Removed nc_time logic, which protects namei from *	panic conditions if time "goes backwards". * * 14 Nov 89 -- prs *	Added logic which removed trailing slashes from a pathname *	before ENOENT error condition detection. * * 20 Oct 89 -- prs *	Preserved locking protocoll when DELETE and last component *	of pathname is "..". * * 04 Oct 89 -- prs *	Prevented the addition of mounted on gnodes to the *	name cache. This change favors UFS lookups. * * 18 Aug 89 -- prs *	Fixed syncronization between LOOKUP and DELETE operations. * * 02 Aug 89 -- prs *	Nulled ncp if gnode was reused, and branching to *	findslot. * * 24 Jul 89 -- prs *	Restructured ufs_namei(). * * 6 Mar 89 -- condylis *	Changed gput to grele for starting directory when ufs_namei() of *	.. crosses a mount point. * * 08 Dec 88 -- prs *	Changed EEXIST return code in checkpath() to EINVAL. * * 28 Jul 88 -- prs *	SMP - System call turn on. * * 19 May 88 -- prs *	SMP - Added namecahce locks. * * 07 Mar 88 -- prs *    Removed parity bit check for I18N. * * 14 Jul 87 -- cb *	Fixed lock bug, encountered when mounting ufs filesystems on  *	an nfs root, and referencing a symbolic link starting at "/". * * 08 May 87 -- logcher *	Remove extra rdev sync since added to ufs_gget(), *	and removed setting rdev to null on filesystems. * * 23 Oct 86 -- chet *	Add arg to ufs_bmap() call * * 11 Sep 86 -- koehler *	added support for local under remote fs * * 14 Oct 85 -- Reilly *	Modified a comment * * 09 Sep 85 -- Reilly *	Modified to handle the new 4.3BSD namei code. * * 26 Oct 84 -- jrs *	Add code for nami cacheing *	Derived from 4.2BSD, labeled: *		ufs_nami.c 6.11	84/07/07 * * ----------------------------------------------------------------------- */#include "../h/param.h"#include "../h/systm.h"#include "../h/gnode_common.h"#include "../ufs/ufs_inode.h"#include "../h/gnode.h"#include "../ufs/fs.h"#include "../h/mount.h"#include "../h/dir.h"#include "../h/user.h"#include "../h/buf.h"#include "../h/conf.h"#include "../h/uio.h"#include "../h/kernel.h"#include "../h/fs_types.h"#include "../h/proc.h"#include "../h/exec.h"/* * Convert a pathname into a pointer to a locked inode, * with side effects usable in creating and removing files. * This is a very central and rather complicated routine. * * The segflg defines whether the name is to be copied from user * space or kernel space. * * The flag argument is (LOOKUP, CREATE, DELETE) depending on whether * the name is to be (looked up, created, deleted).  If flag has * LOCKPARENT or'ed into it and the target of the pathname exists, * namei returns both the target and its parent directory locked.  * If the file system is not maintained in a strict tree hierarchy, * this can result in a deadlock situation.  When creating and * LOCKPARENT is specified, the target may not be ".".  When deleting * and LOCKPARENT is specified, the target may be ".", but the caller * must check to insure it does an grele and gput instead of two gputs. * * The FOLLOW flag is set when symbolic links are to be followed * when they occur at the end of the name translation process. * * Name caching works as follows: * *	names found by directory scans are retained in a cache *	for future reference.  It is managed LRU, so frequently *	used names will hang around.  Cache is indexed by hash value *	obtained from (ino,dev,name) where ino & dev refer to the *	directory containing name. * *	For simplicity (and economy of storage), names longer than *	some (small) maximum length are not cached, they occur *	infrequently in any case, and are almost never of interest. * *	Upon reaching the last segment of a path, if the reference *	is for DELETE, or NOCACHE is set (rewrite), and the *	name is located in the cache, it will be dropped. * *	We must be sure never to enter the name ".." into the cache *	because of the extremely kludgey way that rename() alters *	".." in a situation like *		mv a/x b/x *	where x is a directory, and x/.. is the ".." in question. * * Overall outline of namei: * *	copy in name *	get starting directory * dirloop: *	check accessibility of directory * dirloop2: *	copy next component of name to ndp->ni_dent *	handle degenerate case where name is null string *	look for name in cache, if found, then if at end of path *	and deleting or creating, drop it, else to haveino *	search for name in directory, to found or notfound * notfound: *	if creating, return locked directory, leaving info on avail. slots *	else return error * found: *	if at end of path and deleting, return information to allow delete *	if at end of path and rewriting (create and LOCKPARENT), lock target *	  inode and return info to allow rewrite *	if .. and on mounted filesys, look in mount table for parent *	if not at end, if neither creating nor deleting, add name to cache * haveino: *	if symbolic link, massage name in buffer and continue at dirloop *	if more components of name, do next level at dirloop *	return the answer as locked inode * * NOTE: (LOOKUP | LOCKPARENT) currently returns the parent inode, *	 but unlocked. *//* * GFS expects sfs's to gput the pdir when passed and that the * returned gnode is locked and has the reference count incremented */int old_namei = 0;struct gnode *ufs_namei(ndp)	register struct nameidata *ndp;{	register char *cp;		/* pointer into pathname argument *//* these variables refer to things which must be freed or unlocked */	register struct gnode *dp = 0;	/* the directory we are searching */	register struct nch *ncp;	/* cache slot for entry */	register struct mount *mp;	/* file system that directory is in */	register struct buf *bp = 0;	/* a buffer of directory entries */	register struct direct *ep;	/* the current directory entry */	int entryoffsetinblock;		/* offset of ep in bp's buffer *//* these variables hold information about the search for a slot */	enum {NONE, COMPACT, FOUND} slotstatus;	int slotoffset = -1;		/* offset of area with free space */	int slotsize;			/* size of area at slotoffset */	int slotfreespace;		/* amount of space free in slot */	int slotneeded;			/* size of the entry we're seeking *//* */	int numdirpasses;		/* strategy for directory search */	int endsearch;			/* offset to end directory search */	int prevoff;			/* ndp->ni_offset of previous entry */	struct gnode *pdp;		/* saved dp during symlink work */	struct gnode *sdp;		/* saved dp if nomount and hit mp */	int i;	int lockparent;	int docache;	int makeentry;			/* != 0 if name to be added to cache */	unsigned hash;			/* value of name hash for entry */	union nchash *nhp;		/* cache chain head for entry */	int isdotdot;			/* != 0 if current name is ".." */	int flag;			/* op ie, LOOKUP, CREATE, or DELETE */	off_t enduseful;		/* pointer past last used dir slot */	int nomount;	int cacheid;                    /* save from name cache entry... */	char *tcp;			/* temp cp for removal of trailing 					   slashes */	int trailing_slashes = 0;	/* Set if only trailing slashes remain					   in path */		lockparent = ndp->ni_nameiop & LOCKPARENT;	nomount = ndp->ni_nameiop & NOMOUNT;	docache = (ndp->ni_nameiop & NOCACHE) ^ NOCACHE;	flag = ndp->ni_nameiop &~ (LOCKPARENT|NOCACHE|FOLLOW|NOMOUNT);	if (old_namei)		docache = docache & (nomount == 0 & flag == CREATE);	if (flag == DELETE || lockparent)		docache = 0;	dp = ndp->ni_pdir;	cp = ndp->ni_cp;	while(*cp && (*cp == '/'))		cp++;	ndp->ni_endoff = 0;	/*	 * We come to dirloop to search a new directory.	 * The directory must be locked so that it can be	 * gput, and fs must be already set to dp->i_fs.	 */dirloop:	/*	 * Check accessiblity of directory.	 */	if ((dp->g_mode&GFMT) != GFDIR) {		u.u_error = ENOTDIR;		goto bad;	}	if (access(dp, GEXEC))		goto bad;dirloop2:	/*	 * Copy next component of name to ndp->ni_dent.	 */	hash = 0;	for (i = 0; *cp != 0 && *cp != '/'; cp++) {		if (i >= MAXNAMLEN) {			u.u_error = ENAMETOOLONG;			goto bad;		}		/*		 * Remove parity bit check for I18N.		 */ /*  *		if (*cp & 0200)  *			if ((*cp&0377) == ('/'|0200) || flag != DELETE) {  *				u.u_error = EINVAL;  *				goto bad;  *			}  */		ndp->ni_dent.d_name[i++] = *cp;		hash += (unsigned char)*cp * i;	}	ndp->ni_dent.d_namlen = i;	ndp->ni_dent.d_name[i] = '\0';	/*	 * Remove trailing slashes from cp. Note	 * This will only be performed on last	 * component of pathname.	 */	if (u.u_procp->p_progenv == A_POSIX) {		tcp = cp;		while ((*tcp != 0) && (*tcp == '/')) {			trailing_slashes++;			tcp++;		}		if (*tcp == 0) {			if (flag == CREATE || flag == DELETE)				cp = tcp;		} else			trailing_slashes = 0;	}	isdotdot = (i == 2 &&		ndp->ni_dent.d_name[0] == '.' && ndp->ni_dent.d_name[1] == '.');	makeentry = 1;	if (*cp == '\0' && docache == 0)		makeentry = 0;	/*	 * Check for degenerate name (e.g. / or "")	 * which is a way of talking about a directory,	 * e.g. like "/." or ".".	 */	if (ndp->ni_dent.d_name[0] == '\0') {		if (flag != LOOKUP || lockparent) {			u.u_error = EISDIR;			goto bad;		}		dp->g_flag &= ~GINCOMPLETE;		ndp->ni_cp = cp;		return (dp);	}	/*	 * We now have a segment name to search for, and a directory to search.	 *	 * Before tediously performing a linear scan of the directory,	 * check the name cache to see if the directory/name pair	 * we are looking for is known already.  We don't do this	 * if the segment name is long, simply so the cache can avoid	 * holding long names (which would either waste space, or	 * add greatly to the complexity).	 */	if (ndp->ni_dent.d_namlen > NCHNAMLEN) {		nchstats.ncs_too_long++;		makeentry = 0;	} else {		nchstats.ncs_looks++;	        smp_lock(&lk_namecache, LK_RETRY);		nhp = &nchash[NHASH(hash, dp->g_number, dp->g_dev)];		for (ncp = nhp->nch_forw; ncp != (struct nch *)nhp;		    ncp = ncp->nc_forw) {			if (ncp->nc_ino == dp->g_number &&			    (!makeentry ? 1 : ncp->nc_id) &&			    ncp->nc_dev == dp->g_dev &&			    ncp->nc_nlen == ndp->ni_dent.d_namlen &&			    !bcmp(ncp->nc_name, ndp->ni_dent.d_name,				ncp->nc_nlen))				break;		}		if (ncp == (struct nch *)nhp) {			/*			 * Did not find component in cache.			 */			nchstats.ncs_miss++;			ncp = NULL;		} else {			if (!makeentry) {				/*				 * Remove this entry from cache. Per order				 * of the caller.				 */				nchstats.ncs_gp_reused++;				/* goto expunge_cache; */			} else if (ncp->nc_id != ncp->nc_ip->g_id) {				/*				 * gp stored in cache entry was reused by GFS.				 * Expunge from cache because gp no longer				 * is valid.				 */				nchstats.ncs_del_leaf++;				/* goto expunge_cache; */			} else {				/*				 * move this slot to end of LRU				 * chain, if not already there				 */				if (ncp->nc_nxt) {						/* remove from LRU chain */					*ncp->nc_prev = ncp->nc_nxt;					ncp->nc_nxt->nc_prev = ncp->nc_prev;						/* and replace at end of it */					ncp->nc_nxt = NULL;					ncp->nc_prev = nchtail;					*nchtail = ncp;					nchtail = &ncp->nc_nxt;				}				/*				 * Save some stuff from the name cache entry				 * in case it gets reused after we unlock the				 * cache.				 */				cacheid = ncp->nc_id;				/*				 * Get the next inode in the path.				 * We expect dp to be locked and refed, and				 * pdp to be unlocked and unrefed.				 */				pdp = dp;				if (!isdotdot || dp != u.u_rdir)					dp = ncp->nc_ip;				smp_unlock(&lk_namecache);				if (dp == NULL)					panic("ufs_namei: null cache ino");				if (pdp == dp) {

⌨️ 快捷键说明

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