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

📄 map.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/*- * Copyright (c) 1990 Jan-Simon Pendry * Copyright (c) 1990 Imperial College of Science, Technology & Medicine * Copyright (c) 1990, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Jan-Simon Pendry at Imperial College, London. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: map.c,v 5.2.2.1 1992/02/09 15:08:36 jsp beta $ */#ifndef lintstatic char sccsid[] = "@(#)map.c	8.1 (Berkeley) 6/6/93";#endif /* not lint */#include "am.h"/* * Generation Numbers. * * Generation numbers are allocated to every node created * by amd.  When a filehandle is computed and sent to the * kernel, the generation number makes sure that it is safe * to reallocate a node slot even when the kernel has a cached * reference to its old incarnation. * No garbage collection is done, since it is assumed that * there is no way that 2^32 generation numbers could ever * be allocated by a single run of amd - there is simply * not enough cpu time available. */static unsigned int am_gen = 2;	/* Initial generation number */#define new_gen() (am_gen++)am_node **exported_ap = (am_node **) 0;int exported_ap_size = 0;int first_free_map = 0;		/* First available free slot */int last_used_map = -1;		/* Last unavailable used slot */static int timeout_mp_id;	/* Id from last call to timeout *//* * This is the default attributes field which * is copied into every new node to be created. * The individual filesystem fs_init() routines * patch the copy to represent the particular * details for the relevant filesystem type */static struct fattr gen_fattr = {	NFLNK,				/* type */	NFSMODE_LNK | 0777,		/* mode */	1,				/* nlink */	0,				/* uid */	0,				/* gid */	0,				/* size */	4096,				/* blocksize */	0,				/* rdev */	1,				/* blocks */	0,				/* fsid */	0,				/* fileid */	{ 0, 0 },			/* atime */	{ 0, 0 },			/* mtime */	{ 0, 0 },			/* ctime */};/* * Resize exported_ap map */static int exported_ap_realloc_map P((int nsize));static int exported_ap_realloc_map(nsize)int nsize;{#ifdef notdef	/*	 * If a second realloc occasionally causes Amd to die	 * in then include this check.	 */	if (exported_ap_size != 0)	/* XXX */		return 0;#endif	/*	 * this shouldn't happen, but...	 */	if (nsize < 0 || nsize == exported_ap_size)		return 0;	exported_ap = (am_node **) xrealloc((voidp) exported_ap, nsize * sizeof(am_node*));	if (nsize > exported_ap_size)		bzero((char*) (exported_ap+exported_ap_size),			(nsize - exported_ap_size) * sizeof(am_node*));	exported_ap_size = nsize;	return 1;}	/* * The root of the mount tree. */am_node *root_node;/* * Allocate a new mount slot and create * a new node. * Fills in the map number of the node, * but leaves everything else uninitialised. */am_node *exported_ap_alloc(P_void){	am_node *mp, **mpp;	/*	 * First check if there are any slots left, realloc if needed	 */	if (first_free_map >= exported_ap_size)		if (!exported_ap_realloc_map(exported_ap_size + NEXP_AP))			return 0;	/*	 * Grab the next free slot	 */	mpp = exported_ap + first_free_map;	mp = *mpp = ALLOC(am_node);	bzero((char *) mp, sizeof(*mp));	mp->am_mapno = first_free_map++;	/*	 * Update free pointer	 */	while (first_free_map < exported_ap_size && exported_ap[first_free_map])		first_free_map++;	if (first_free_map > last_used_map)		last_used_map = first_free_map - 1;	/*	 * Shrink exported_ap if reasonable	 */	if (last_used_map < exported_ap_size - (NEXP_AP + NEXP_AP_MARGIN))		exported_ap_realloc_map(exported_ap_size - NEXP_AP);#ifdef DEBUG	/*dlog("alloc_exp: last_used_map = %d, first_free_map = %d\n",		last_used_map, first_free_map);*/#endif /* DEBUG */	return mp;}/* * Free a mount slot */void exported_ap_free P((am_node *mp));void exported_ap_free(mp)am_node *mp;{	/*	 * Sanity check	 */	if (!mp)		return;	/*	 * Zero the slot pointer to avoid double free's	 */	exported_ap[mp->am_mapno] = 0;	/*	 * Update the free and last_used indices	 */	if (mp->am_mapno == last_used_map)		while (last_used_map >= 0 && exported_ap[last_used_map] == 0)			--last_used_map;	if (first_free_map > mp->am_mapno)		first_free_map = mp->am_mapno;#ifdef DEBUG	/*dlog("free_exp: last_used_map = %d, first_free_map = %d\n",		last_used_map, first_free_map);*/#endif /* DEBUG */	/*	 * Free the mount node	 */	free((voidp) mp);}/* * Insert mp into the correct place, * where p_mp is its parent node. * A new node gets placed as the youngest sibling * of any other children, and the parent's child * pointer is adjusted to point to the new child node. */void insert_am(mp, p_mp)am_node *mp;am_node *p_mp;{	/*	 * If this is going in at the root then flag it	 * so that it cannot be unmounted by amq.	 */	if (p_mp == root_node)		mp->am_flags |= AMF_ROOT;	/*	 * Fill in n-way links	 */	mp->am_parent = p_mp;	mp->am_osib = p_mp->am_child;	if (mp->am_osib)		mp->am_osib->am_ysib = mp;	p_mp->am_child = mp;}/* * Remove am from its place in the mount tree */void remove_am(mp)am_node *mp;{	/*	 * 1.  Consistency check	 */	if (mp->am_child && mp->am_parent) {		plog(XLOG_WARNING, "children of \"%s\" still exist - deleting anyway", mp->am_path);	}	/*	 * 2.  Update parent's child pointer	 */	if (mp->am_parent && mp->am_parent->am_child == mp)		mp->am_parent->am_child = mp->am_osib;	/*	 * 3.  Unlink from sibling chain	 */	if (mp->am_ysib)		mp->am_ysib->am_osib = mp->am_osib;	if (mp->am_osib)		mp->am_osib->am_ysib = mp->am_ysib;}/* * Compute a new time to live value for a node. */void new_ttl(mp)am_node *mp;{	mp->am_timeo_w = 0;	mp->am_ttl = clocktime();	mp->am_fattr.atime.seconds = mp->am_ttl;	mp->am_ttl += mp->am_timeo;	/* sun's -tl option */}void mk_fattr P((am_node *mp, ftype vntype));void mk_fattr(mp, vntype)am_node *mp;ftype vntype;{	switch (vntype) {	case NFDIR:		mp->am_fattr.type = NFDIR;		mp->am_fattr.mode = NFSMODE_DIR | 0555;		mp->am_fattr.nlink = 2;		mp->am_fattr.size = 512;		break;	case NFLNK:		mp->am_fattr.type = NFLNK;		mp->am_fattr.mode = NFSMODE_LNK | 0777;		mp->am_fattr.nlink = 1;		mp->am_fattr.size = 0;		break;	default:		plog(XLOG_FATAL, "Unknown fattr type %d - ignored", vntype);		break;	}}/* * Initialise an allocated mount node. * It is assumed that the mount node was bzero'd * before getting here so anything that would * be set to zero isn't done here. */void init_map(mp, dir)am_node *mp;char *dir;{	/* mp->am_mapno initalised by exported_ap_alloc */	mp->am_mnt = new_mntfs();	mp->am_name = strdup(dir);	mp->am_path = strdup(dir);	/*mp->am_link = 0;*/	/*mp->am_parent = 0;*/	/*mp->am_ysib = 0;*/	/*mp->am_osib = 0;*/	/*mp->am_child = 0;*/	/*mp->am_flags = 0;*/	/*mp->am_error = 0;*/	mp->am_gen = new_gen();	/*mp->am_pref = 0;*/	mp->am_timeo = am_timeo;	mp->am_attr.status = NFS_OK;	mp->am_fattr = gen_fattr;	mp->am_fattr.fsid = 42;	mp->am_fattr.fileid = 0;	mp->am_fattr.atime.seconds = clocktime();	mp->am_fattr.atime.useconds = 0;	mp->am_fattr.mtime = mp->am_fattr.ctime = mp->am_fattr.atime;	new_ttl(mp);	mp->am_stats.s_mtime = mp->am_fattr.atime.seconds;	/*mp->am_private = 0;*/}/* * Free a mount node. * The node must be already unmounted. */void free_map(mp)am_node *mp;{	remove_am(mp);	if (mp->am_link)		free(mp->am_link);	if (mp->am_name)		free(mp->am_name);	if (mp->am_path)		free(mp->am_path);	if (mp->am_pref)		free(mp->am_pref);	if (mp->am_mnt)		free_mntfs(mp->am_mnt);	exported_ap_free(mp);}/* * Convert from file handle to * automount node. */am_node *fh_to_mp3(fhp, rp, c_or_d)nfs_fh *fhp;int *rp;int c_or_d;{	struct am_fh *fp = (struct am_fh *) fhp;	am_node *ap = 0;	/*	 * Check process id matches	 * If it doesn't then it is probably	 * from an old kernel cached filehandle	 * which is now out of date.	 */	if (fp->fhh_pid != mypid)		goto drop;	/*	 * Make sure the index is valid before	 * exported_ap is referenced.	 */	if (fp->fhh_id < 0 || fp->fhh_id >= exported_ap_size)		goto drop;	/*	 * Get hold of the supposed mount node	 */	ap = exported_ap[fp->fhh_id];	/*	 * If it exists then maybe...	 */	if (ap) {		/*		 * Check the generation number in the node		 * matches the one from the kernel.  If not		 * then the old node has been timed out and		 * a new one allocated.		 */		if (ap->am_gen != fp->fhh_gen) {			ap = 0;			goto drop;		}		/*		 * If the node is hung then locate a new node		 * for it.  This implements the replicated filesystem		 * retries.		 */		if (ap->am_mnt && FSRV_ISDOWN(ap->am_mnt->mf_server) && ap->am_parent) {			int error;			am_node *orig_ap = ap;#ifdef DEBUG			dlog("fh_to_mp3: %s (%s) is hung:- call lookup",					orig_ap->am_path, orig_ap->am_mnt->mf_info);#endif /* DEBUG */			/*			 * Update modify time of parent node.			 * With any luck the kernel will re-stat			 * the child node and get new information.			 */			orig_ap->am_fattr.mtime.seconds = clocktime();			/*			 * Call the parent's lookup routine for an object			 * with the same name.  This may return -1 in error			 * if a mount is in progress.  In any case, if no			 * mount node is returned the error code is propagated			 * to the caller.			 */			if (c_or_d == VLOOK_CREATE) {				ap = (*orig_ap->am_parent->am_mnt->mf_ops->lookuppn)(orig_ap->am_parent,						orig_ap->am_name, &error, c_or_d);			} else {				ap = 0;				error = ESTALE;			}			if (ap == 0) {				if (error < 0 && amd_state == Finishing)					error = ENOENT;				*rp = error;				return 0;			}			/*			 * Update last access to original node.  This			 * avoids timing it out and so sending ESTALE			 * back to the kernel.			 * XXX - Not sure we need this anymore (jsp, 90/10/6).			 */			new_ttl(orig_ap);		}		/*		 * Disallow references to objects being unmounted, unless		 * they are automount points.		 */		if (ap->am_mnt && (ap->am_mnt->mf_flags & MFF_UNMOUNTING) &&				!(ap->am_flags & AMF_ROOT)) {			if (amd_state == Finishing)				*rp = ENOENT;			else				*rp = -1;			return 0;		}		new_ttl(ap);	}drop:	if (!ap || !ap->am_mnt) {		/*		 * If we are shutting down then it is likely		 * that this node has disappeared because of		 * a fast timeout.  To avoid things thrashing		 * just pretend it doesn't exist at all.  If		 * ESTALE is returned, some NFS clients just		 * keep retrying (stupid or what - if it's		 * stale now, what's it going to be in 5 minutes?)		 */		if (amd_state == Finishing)			*rp = ENOENT;		else			*rp = ESTALE;		amd_stats.d_stale++;	}	return ap;}am_node *fh_to_mp(fhp)nfs_fh *fhp;{	int dummy;	return fh_to_mp2(fhp, &dummy);}/* * Convert from automount node to * file handle. */void mp_to_fh(mp, fhp)am_node *mp;struct nfs_fh *fhp;{	struct am_fh *fp = (struct am_fh *) fhp;	/*	 * Take the process id	 */	fp->fhh_pid = mypid;	/*	 * .. the map number	 */	fp->fhh_id = mp->am_mapno;	/*	 * .. and the generation number	 */	fp->fhh_gen = mp->am_gen;	/*	 * .. to make a "unique" triple that will never	 * be reallocated except across reboots (which doesn't matter)	 * or if we are unlucky enough to be given the same	 * pid as a previous amd (very unlikely).	 */}static am_node *find_ap2 P((char *dir, am_node *mp));static am_node *find_ap2(dir, mp)char *dir;am_node *mp;{	if (mp) {		am_node *mp2;		if (strcmp(mp->am_path, dir) == 0)			return mp;		if ((mp->am_mnt->mf_flags & MFF_MOUNTED) &&			strcmp(mp->am_mnt->mf_mount, dir) == 0)			return mp;		mp2 = find_ap2(dir, mp->am_osib);		if (mp2)			return mp2;		return find_ap2(dir, mp->am_child);	}	return 0;}/* * Find the mount node corresponding * to dir.  dir can match either the * automount path or, if the node is * mounted, the mount location. */am_node *find_ap P((char *dir));

⌨️ 快捷键说明

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