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

📄 afs_ops.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
			return mp;	/* "." is the current node */		if (fname[1] == '.' && fname[2] == '\0') {			if (mp->am_parent) {#ifdef DEBUG				dlog(".. in %s gives %s", mp->am_path, mp->am_parent->am_path);#endif /* DEBUG */				return mp->am_parent;	/* ".." is the parent node */			}			ereturn(ESTALE);		}	}	/*	 * Check for valid key name.	 * If it is invalid then pretend it doesn't exist.	 */	if (!valid_key(fname)) {		plog(XLOG_WARNING, "Key \"%s\" contains a disallowed character", fname);		ereturn(ENOENT);	}	/*	 * Expand key name.	 * fname is now a private copy.	 */	fname = expand_key(fname);	for (ap_hung = 0, ap = mp->am_child; ap; ap = ap->am_osib) {		/*		 * Otherwise search children of this node		 */		if (FSTREQ(ap->am_name, fname)) {			mf = ap->am_mnt;			if (ap->am_error) {				error = ap->am_error;				continue;			}			/*			 * If the error code is undefined then it must be			 * in progress.			 */			if (mf->mf_error < 0)				goto in_progrss;			/*			 * Check for a hung node			 */			if (FSRV_ISDOWN(mf->mf_server)) {#ifdef DEBUG				dlog("server hung");#endif /* DEBUG */				error = ap->am_error;				ap_hung = ap;				continue;			}			/*			 * If there was a previous error with this node			 * then return that error code.			 */			if (mf->mf_flags & MFF_ERROR) {				error = mf->mf_error;				continue;			}			if (!(mf->mf_flags & MFF_MOUNTED) /*|| (mf->mf_flags & MFF_UNMOUNTING)*/) {in_progrss:				/*				 * If the fs is not mounted or it is unmounting then there				 * is a background (un)mount in progress.  In this case				 * we just drop the RPC request (return nil) and				 * wait for a retry, by which time the (un)mount may				 * have completed.				 */#ifdef DEBUG				dlog("ignoring mount of %s in %s -- in progress",					fname, mf->mf_mount);#endif /* DEBUG */				in_progress++;				continue;			}			/*			 * Otherwise we have a hit: return the current mount point.			 */#ifdef DEBUG			dlog("matched %s in %s", fname, ap->am_path);#endif /* DEBUG */			free(fname);			return ap;		}	}	if (in_progress) {#ifdef DEBUG		dlog("Waiting while %d mount(s) in progress", in_progress);#endif /* DEBUG */		free(fname);		ereturn(-1);	}	/*	 * If an error occured then return it.	 */	if (error) {#ifdef DEBUG		errno = error; /* XXX */		dlog("Returning error: %m", error);#endif /* DEBUG */		free(fname);		ereturn(error);	}	/*	 * If doing a delete then don't create again!	 */	switch (op) {	case VLOOK_DELETE:		ereturn(ENOENT);		break;	case VLOOK_CREATE:		break;	default:		plog(XLOG_FATAL, "Unknown op to afs_lookuppn: 0x%x", op);		ereturn(EINVAL);		break;	}	/*	 * If the server is going down then just return,	 * don't try to mount any more file systems	 */	if ((int)amd_state >= (int)Finishing) {#ifdef DEBUG		dlog("not found - server going down anyway");#endif /* DEBUG */		free(fname);		ereturn(ENOENT);	}	/*	 * If we get there then this is a reference to an,	 * as yet, unknown name so we need to search the mount	 * map for it.	 */	if (mp->am_pref) {		sprintf(path_name, "%s%s", mp->am_pref, fname);		pfname = path_name;	} else {		pfname = fname;	}	mf = mp->am_mnt;#ifdef DEBUG	dlog("will search map info in %s to find %s", mf->mf_info, pfname);#endif /* DEBUG */	/*	 * Consult the oracle for some mount information.	 * info is malloc'ed and belongs to this routine.	 * It ends up being free'd in free_continuation().	 *	 * Note that this may return -1 indicating that information	 * is not yet available.	 */	error = mapc_search((mnt_map*) mf->mf_private, pfname, &info);	if (error) {		if (error > 0)			plog(XLOG_MAP, "No map entry for %s", pfname);		else			plog(XLOG_MAP, "Waiting on map entry for %s", pfname);		free(fname);		ereturn(error);	}#ifdef DEBUG	dlog("mount info is %s", info);#endif /* DEBUG */	/*	 * Split info into an argument vector.	 * The vector is malloc'ed and belongs to	 * this routine.  It is free'd in free_continuation()	 */	xivec = ivec = strsplit(info, ' ', '\"');	/*	 * Default error code...	 */	if (ap_hung)		error = EWOULDBLOCK;	else		error = ENOENT;	/*	 * Allocate a new map	 */	new_mp = exported_ap_alloc();	if (new_mp == 0) {		free((voidp) xivec);		free((voidp) info);		free((voidp) fname);		ereturn(ENOSPC);	}	if (mf->mf_auto)		auto_opts = mf->mf_auto;	else		auto_opts = "";	auto_opts = strdup(auto_opts);#ifdef DEBUG	dlog("searching for /defaults entry");#endif /* DEBUG */	if (mapc_search((mnt_map*) mf->mf_private, "/defaults", &dflts) == 0) {	  	char *dfl;		char **rvec;#ifdef DEBUG		dlog("/defaults gave %s", dflts);#endif /* DEBUG */		if (*dflts == '-')			dfl = dflts+1;		else			dfl = dflts;		/*		 * Chop the defaults up		 */		rvec = strsplit(dfl, ' ', '\"');		/*		 * Extract first value		 */		dfl = rvec[0];		/*		 * If there were any values at all...		 */		if (dfl) {			/*			 * Log error if there were other values			 */			if (rvec[1]) {#ifdef DEBUG				dlog("/defaults chopped into %s", dfl);#endif /* DEBUG */				plog(XLOG_USER, "More than a single value for /defaults in %s", mf->mf_info);			}			/*			 * Prepend to existing defaults if they exist,			 * otherwise just use these defaults.			 */			if (*auto_opts && *dfl) {				char *nopts = (char *) xmalloc(strlen(auto_opts)+strlen(dfl)+2);				sprintf(nopts, "%s;%s", dfl, auto_opts);				free(auto_opts);				auto_opts = nopts;			} else if (*dfl) {				auto_opts = strealloc(auto_opts, dfl);			}		}		free(dflts);		/*		 * Don't need info vector any more		 */		free((voidp) rvec);	}	/*	 * Fill it in	 */	init_map(new_mp, fname);	/*	 * Put it in the table	 */	insert_am(new_mp, mp);	/*	 * Fill in some other fields,	 * path and mount point.	 *	 * bugfix: do not prepend old am_path if direct map	 *         <wls@astro.umd.edu> William Sebok	 */	new_mp->am_path = str3cat(new_mp->am_path,		mf->mf_ops == &dfs_ops ? "" : mp->am_path,		*fname == '/' ? "" : "/", fname);#ifdef DEBUG	dlog("setting path to %s", new_mp->am_path);#endif /* DEBUG */	/*	 * Take private copy of pfname	 */	pfname = strdup(pfname);	/*	 * Construct a continuation	 */	cp = ALLOC(continuation);	cp->mp = new_mp;	cp->xivec = xivec;	cp->ivec = ivec;	cp->info = info;	cp->key = pfname;	cp->auto_opts = auto_opts;	cp->retry = FALSE;	cp->tried = FALSE;	cp->start = clocktime();	cp->def_opts = strdup(auto_opts);	bzero((voidp) &cp->fs_opts, sizeof(cp->fs_opts));	/*	 * Try and mount the file system	 * If this succeeds immediately (possible	 * for a ufs file system) then return	 * the attributes, otherwise just	 * return an error.	 */	error = afs_bgmount(cp, error);	reschedule_timeout_mp();	if (!error) {		free(fname);		return new_mp;	}	if (error && (cp->mp->am_mnt->mf_ops == &efs_ops))		cp->mp->am_error = error;	assign_error_mntfs(new_mp);	free(fname);	ereturn(error);#undef ereturn}/* * Locate next node in sibling list which is mounted * and is not an error node. */static am_node *next_nonerror_node P((am_node *xp));static am_node *next_nonerror_node(xp)am_node *xp;{	mntfs *mf;	/*	 * Bug report (7/12/89) from Rein Tollevik <rein@ifi.uio.no>	 * Fixes a race condition when mounting direct automounts.	 * Also fixes a problem when doing a readdir on a directory	 * containing hung automounts.	 */	while (xp &&	       (!(mf = xp->am_mnt) ||			/* No mounted filesystem */	        mf->mf_error != 0 ||			/* There was a mntfs error */	        xp->am_error != 0 ||			/* There was a mount error */	        !(mf->mf_flags & MFF_MOUNTED) ||	/* The fs is not mounted */	        (mf->mf_server->fs_flags & FSF_DOWN))	/* The fs may be down */		)		xp = xp->am_osib;	return xp;}static int afs_readdir P((am_node *mp, nfscookie cookie, struct dirlist *dp, struct entry *ep, int count));static int afs_readdir(mp, cookie, dp, ep, count)am_node *mp;nfscookie cookie;struct dirlist *dp;struct entry *ep;int count;{	unsigned int gen = *(unsigned int*) cookie;	am_node *xp;	dp->eof = FALSE;	if (gen == 0) {		/*		 * In the default instance (which is used to		 * start a search) we return "." and "..".		 *		 * This assumes that the count is big enough		 * to allow both "." and ".." to be returned in		 * a single packet.  If it isn't (which would		 * be fairly unbelievable) then tough.		 */#ifdef DEBUG		dlog("default search");#endif /* DEBUG */		/*		 * Check for enough room.  This is extremely		 * approximate but is more than enough space.		 * Really need 2 times:		 * 	4byte fileid		 * 	4byte cookie		 * 	4byte name length		 * 	4byte name		 * plus the dirlist structure		 */		if (count <			(2 * (2 * (sizeof(*ep) + sizeof("..") + 4)					+ sizeof(*dp))))			return EINVAL;		xp = next_nonerror_node(mp->am_child);		dp->entries = ep;		/* construct "." */		ep[0].fileid = mp->am_gen;		ep[0].name = ".";		ep[0].nextentry = &ep[1];		*(unsigned int *) ep[0].cookie = 0;		/* construct ".." */		if (mp->am_parent)			ep[1].fileid = mp->am_parent->am_gen;		else			ep[1].fileid = mp->am_gen;		ep[1].name = "..";		ep[1].nextentry = 0;		*(unsigned int *) ep[1].cookie =			xp ? xp->am_gen : ~(unsigned int)0;		if (!xp) dp->eof = TRUE;		return 0;	}#ifdef DEBUG	dlog("real child");#endif /* DEBUG */	if (gen == ~(unsigned int)0) {#ifdef DEBUG		dlog("End of readdir in %s", mp->am_path);#endif /* DEBUG */		dp->eof = TRUE;		dp->entries = 0;		return 0;	}	xp = mp->am_child;	while (xp && xp->am_gen != gen)		xp = xp->am_osib;	if (xp) {		int nbytes = count / 2;		/* conservative */		int todo = MAX_READDIR_ENTRIES;		dp->entries = ep;		do {			am_node *xp_next = next_nonerror_node(xp->am_osib);			if (xp_next) {				*(unsigned int *) ep->cookie = xp_next->am_gen;			} else {				*(unsigned int *) ep->cookie = ~(unsigned int)0;				dp->eof = TRUE;			}			ep->fileid = xp->am_gen;			ep->name = xp->am_name;			nbytes -= sizeof(*ep) + strlen(xp->am_name) + 1;			xp = xp_next;			if (nbytes > 0 && !dp->eof && todo > 1) {				ep->nextentry = ep + 1;				ep++;				--todo;			} else {				todo = 0;			}		} while (todo > 0);		ep->nextentry = 0;		return 0;	}	return ESTALE;}static am_node *dfs_readlink P((am_node *mp, int *error_return));static am_node *dfs_readlink(mp, error_return)am_node *mp;int *error_return;{	am_node *xp;	int rc = 0;	xp = next_nonerror_node(mp->am_child);	if (!xp) {		if (!mp->am_mnt->mf_private)			afs_mkcacheref(mp->am_mnt);	/* XXX */		xp = afs_lookuppn(mp, mp->am_path+1, &rc, VLOOK_CREATE);	}	if (xp) {		new_ttl(xp);	/* (7/12/89) from Rein Tollevik */		return xp;	}	if (amd_state == Finishing)		rc = ENOENT;	*error_return = rc;	return 0;}/* * Ops structure */am_ops root_ops = {	"root",	0, /* root_match */	0, /* root_init */	root_mount,	0,	afs_umount,	0,	afs_lookuppn,	afs_readdir,	0, /* root_readlink */	0, /* root_mounted */	0, /* root_umounted */	find_afs_srvr,	FS_NOTIMEOUT|FS_AMQINFO|FS_DIRECTORY};am_ops afs_ops = {	"auto",	afs_match,	0, /* afs_init */	afs_mount,	0,	afs_umount,	0,	afs_lookuppn,	afs_readdir,	0, /* afs_readlink */	0, /* afs_mounted */	afs_umounted,	find_afs_srvr,	FS_AMQINFO|FS_DIRECTORY};am_ops toplvl_ops = {	"toplvl",	afs_match,	0, /* afs_init */	toplvl_mount,	0,	toplvl_umount,	0,	afs_lookuppn,	afs_readdir,	0, /* toplvl_readlink */	toplvl_mounted,	0, /* toplvl_umounted */	find_afs_srvr,	FS_MKMNT|FS_NOTIMEOUT|FS_BACKGROUND|FS_AMQINFO|FS_DIRECTORY};am_ops dfs_ops = {	"direct",	afs_match,	0, /* dfs_init */	toplvl_mount,	0,	toplvl_umount,	0,	efs_lookuppn,	efs_readdir,	dfs_readlink,	toplvl_mounted,	0, /* afs_umounted */	find_afs_srvr,	FS_MKMNT|FS_NOTIMEOUT|FS_BACKGROUND|FS_AMQINFO};#ifdef HAS_UNION_FSam_ops union_ops = {	"union",	afs_match,	0, /* afs_init */	toplvl_mount,	0,	toplvl_umount,	0,	afs_lookuppn,	afs_readdir,	0, /* toplvl_readlink */	union_mounted,	0, /* toplvl_umounted */	find_afs_srvr,	FS_MKMNT|FS_NOTIMEOUT|FS_BACKGROUND|FS_AMQINFO|FS_DIRECTORY};#endif /* HAS_UNION_FS */

⌨️ 快捷键说明

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