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

📄 afs_ops.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
 * completes. */static void afs_cont P((int rc, int term, voidp closure));static void afs_cont(rc, term, closure)int rc;int term;voidp closure;{	struct continuation *cp = (struct continuation *) closure;	mntfs *mf = cp->mp->am_mnt;	/*	 * Definitely not trying to mount at the moment	 */	mf->mf_flags &= ~MFF_MOUNTING;	/*	 * While we are mounting - try to avoid race conditions	 */	new_ttl(cp->mp);	/*	 * Wakeup anything waiting for this mount	 */	wakeup((voidp) mf);	/*	 * Check for termination signal or exit status...	 */	if (rc || term) {		am_node *xmp;		if (term) {			/*			 * Not sure what to do for an error code.			 */			mf->mf_error = EIO;	/* XXX ? */			mf->mf_flags |= MFF_ERROR;			plog(XLOG_ERROR, "mount for %s got signal %d", cp->mp->am_path, term);		} else {			/*			 * Check for exit status...			 */			mf->mf_error = rc;			mf->mf_flags |= MFF_ERROR;			errno = rc;	/* XXX */			plog(XLOG_ERROR, "%s: mount (afs_cont): %m", cp->mp->am_path);		}		/*		 * If we get here then that attempt didn't work, so		 * move the info vector pointer along by one and		 * call the background mount routine again		 */		amd_stats.d_merr++;		cp->ivec++;		xmp = cp->mp;		(void) afs_bgmount(cp, 0);		assign_error_mntfs(xmp);	} else {		/*		 * The mount worked.		 */		am_mounted(cp->mp);		free_continuation(cp);	}	reschedule_timeout_mp();}/* * Retry a mount *//*ARGSUSED*/static void afs_retry P((int rc, int term, voidp closure));static void afs_retry(rc, term, closure)int rc;int term;voidp closure;{	struct continuation *cp = (struct continuation *) closure;	int error = 0;#ifdef DEBUG	dlog("Commencing retry for mount of %s", cp->mp->am_path);#endif /* DEBUG */	new_ttl(cp->mp);	if ((cp->start + ALLOWED_MOUNT_TIME) < clocktime()) {		/*		 * The entire mount has timed out.		 * Set the error code and skip past		 * all the info vectors so that		 * afs_bgmount will not have any more		 * ways to try the mount, so causing		 * an error.		 */		plog(XLOG_INFO, "mount of \"%s\" has timed out", cp->mp->am_path);		error = ETIMEDOUT;		while (*cp->ivec)			cp->ivec++;	}	if (error || !IN_PROGRESS(cp)) {		(void) afs_bgmount(cp, error);	}	reschedule_timeout_mp();}/* * Try to mount a file system.  Can be called * directly or in a sub-process by run_task */static int try_mount P((voidp mvp));static int try_mount(mvp)voidp mvp;{	/*	 * Mount it!	 */	int error;	am_node *mp = (am_node *) mvp;	mntfs *mf = mp->am_mnt;	/*	 * If the directory is not yet made and	 * it needs to be made, then make it!	 * This may be run in a backgroun process	 * in which case the flag setting won't be	 * noticed later - but it is set anyway	 * just after run_task is called.  It	 * should probably go away totally...	 */	if (!(mf->mf_flags & MFF_MKMNT) && mf->mf_ops->fs_flags & FS_MKMNT) {		error = mkdirs(mf->mf_mount, 0555);		if (!error)			mf->mf_flags |= MFF_MKMNT;	}	error = mount_node(mp);#ifdef DEBUG	if (error > 0) {		errno = error;		dlog("afs call to mount_node failed: %m");	}#endif /* DEBUG */	return error;}/* * Pick a file system to try mounting and * do that in the background if necessary *For each location:	if it is new -defaults then		extract and process		continue;	fi	if it is a cut then		if a location has been tried then			break;		fi		continue;	fi	parse mount location	discard previous mount location if required	find matching mounted filesystem	if not applicable then		this_error = No such file or directory		continue	fi	if the filesystem failed to be mounted then		this_error = error from filesystem	elif the filesystem is mounting or unmounting then		this_error = -1	elif the fileserver is down then		this_error = -1	elif the filesystem is already mounted		this_error = 0		break	fi	if no error on this mount then		this_error = initialise mount point	fi	if no error on this mount and mount is delayed then		this_error = -1	fi	if this_error < 0 then		retry = true	fi	if no error on this mount then		make mount point if required	fi	if no error on this mount then		if mount in background then			run mount in background			return -1		else			this_error = mount in foreground		fi	fi	if an error occured on this mount then		update stats		save error in mount point	fiendfor */static int afs_bgmount P((struct continuation *cp, int mpe));static int afs_bgmount(cp, mpe)struct continuation *cp;int mpe;{	mntfs *mf = cp->mp->am_mnt;	/* Current mntfs */	mntfs *mf_retry = 0;		/* First mntfs which needed retrying */	int this_error = -1;		/* Per-mount error */	int hard_error = -1;	int mp_error = mpe;	/*	 * Try to mount each location.	 * At the end:	 * hard_error == 0 indicates something was mounted.	 * hard_error > 0 indicates everything failed with a hard error	 * hard_error < 0 indicates nothing could be mounted now	 */	for (; this_error && *cp->ivec; cp->ivec++) {		am_ops *p;		am_node *mp = cp->mp;		char *link_dir;		int dont_retry;		if (hard_error < 0)			hard_error = this_error;		this_error = -1;		if (**cp->ivec == '-') {			/*			 * Pick up new defaults			 */			if (cp->auto_opts && *cp->auto_opts)				cp->def_opts = str3cat(cp->def_opts, cp->auto_opts, ";", *cp->ivec+1);			else				cp->def_opts = strealloc(cp->def_opts, *cp->ivec+1);#ifdef DEBUG			dlog("Setting def_opts to \"%s\"", cp->def_opts);#endif /* DEBUG */			continue;		}		/*		 * If a mount has been attempted, and we find		 * a cut then don't try any more locations.		 */		if (strcmp(*cp->ivec, "/") == 0 || strcmp(*cp->ivec, "||") == 0) {			if (cp->tried) {#ifdef DEBUG				dlog("Cut: not trying any more locations for %s",					mp->am_path);#endif /* DEBUG */				break;			}			continue;		}#ifdef SUNOS4_COMPAT#ifdef nomore		/*		 * By default, you only get this bit on SunOS4.		 * If you want this anyway, then define SUNOS4_COMPAT		 * in the relevant "os-blah.h" file.		 *		 * We make the observation that if the local key line contains		 * no '=' signs then either it is sick, or it is a SunOS4-style		 * "host:fs[:link]" line.  In the latter case the am_opts field		 * is also assumed to be in old-style, so you can't mix & match.		 * You can use ${} expansions for the fs and link bits though...		 *		 * Actually, this doesn't really cover all the possibilities for		 * the latest SunOS automounter and it is debatable whether there		 * is any point bothering.		 */		if (strchr(*cp->ivec, '=') == 0)			p = sunos4_match(&cp->fs_opts, *cp->ivec, cp->def_opts, mp->am_path, cp->key, mp->am_parent->am_mnt->mf_info);		else#endif#endif /* SUNOS4_COMPAT */			p = ops_match(&cp->fs_opts, *cp->ivec, cp->def_opts, mp->am_path, cp->key, mp->am_parent->am_mnt->mf_info);		/*		 * Find a mounted filesystem for this node.		 */		mp->am_mnt = mf = realloc_mntfs(mf, p, &cp->fs_opts, cp->fs_opts.opt_fs,			cp->fs_opts.fs_mtab, cp->auto_opts, cp->fs_opts.opt_opts, cp->fs_opts.opt_remopts);		p = mf->mf_ops;#ifdef DEBUG		dlog("Got a hit with %s", p->fs_type);#endif /* DEBUG */		/*		 * Note whether this is a real mount attempt		 */		if (p == &efs_ops) {			plog(XLOG_MAP, "Map entry %s for %s failed to match", *cp->ivec, mp->am_path);			if (this_error <= 0)				this_error = ENOENT;			continue;		} else {			if (cp->fs_opts.fs_mtab) {				plog(XLOG_MAP, "Trying mount of %s on %s fstype %s",					cp->fs_opts.fs_mtab, mp->am_path, p->fs_type);			}			cp->tried = TRUE;		}		this_error = 0;		dont_retry = FALSE;		if (mp->am_link) {			free(mp->am_link);			mp->am_link = 0;		}		link_dir = mf->mf_fo->opt_sublink;		if (link_dir && *link_dir) {			if (*link_dir == '/') {				mp->am_link = strdup(link_dir);			} else {				mp->am_link = str3cat((char *) 0,					mf->mf_fo->opt_fs, "/", link_dir);				normalize_slash(mp->am_link);			}		}		if (mf->mf_error > 0) {			this_error = mf->mf_error;		} else if (mf->mf_flags & (MFF_MOUNTING|MFF_UNMOUNTING)) {			/*			 * Still mounting - retry later			 */#ifdef DEBUG			dlog("Duplicate pending mount fstype %s", p->fs_type);#endif /* DEBUG */			this_error = -1;		} else if (FSRV_ISDOWN(mf->mf_server)) {			/*			 * Would just mount from the same place			 * as a hung mount - so give up			 */#ifdef DEBUG			dlog("%s is already hung - giving up", mf->mf_mount);#endif /* DEBUG */			mp_error = EWOULDBLOCK;			dont_retry = TRUE;			this_error = -1;		} else if (mf->mf_flags & MFF_MOUNTED) {#ifdef DEBUG			dlog("duplicate mount of \"%s\" ...", mf->mf_info);#endif /* DEBUG */			/*			 * Just call mounted()			 */			am_mounted(mp);			this_error = 0;			break;		}		/*		 * Will usually need to play around with the mount nodes		 * file attribute structure.  This must be done here.		 * Try and get things initialised, even if the fileserver		 * is not known to be up.  In the common case this will		 * progress things faster.		 */		if (!this_error) {			/*			 * Fill in attribute fields.			 */			if (mf->mf_ops->fs_flags & FS_DIRECTORY)				mk_fattr(mp, NFDIR);			else				mk_fattr(mp, NFLNK);			mp->am_fattr.fileid = mp->am_gen;			if (p->fs_init)				this_error = (*p->fs_init)(mf);		}		/*		 * Make sure the fileserver is UP before doing any more work		 */		if (!FSRV_ISUP(mf->mf_server)) {#ifdef DEBUG			dlog("waiting for server %s to become available", mf->mf_server->fs_host);#endif			this_error =  -1;		}		if (!this_error && mf->mf_fo->opt_delay) {			/*			 * If there is a delay timer on the mount			 * then don't try to mount if the timer			 * has not expired.			 */			int i = atoi(mf->mf_fo->opt_delay);			if (i > 0 && clocktime() < (cp->start + i)) {#ifdef DEBUG				dlog("Mount of %s delayed by %ds", mf->mf_mount, i - clocktime() + cp->start);#endif /* DEBUG */				this_error = -1;			}		}		if (this_error < 0 && !dont_retry) {			if (!mf_retry)				mf_retry = dup_mntfs(mf);			cp->retry = TRUE;		}		if (!this_error)		if (p->fs_flags & FS_MBACKGROUND) {			mf->mf_flags |= MFF_MOUNTING;	/*XXX*/#ifdef DEBUG			dlog("backgrounding mount of \"%s\"", mf->mf_mount);#endif /* DEBUG */			if (cp->callout) {				untimeout(cp->callout);				cp->callout = 0;			}			run_task(try_mount, (voidp) mp, afs_cont, (voidp) cp);			mf->mf_flags |= MFF_MKMNT;	/* XXX */			if (mf_retry) free_mntfs(mf_retry);			return -1;		} else {#ifdef DEBUG			dlog("foreground mount of \"%s\" ...", mf->mf_info);#endif /* DEBUG */			this_error = try_mount((voidp) mp);			if (this_error < 0) {				if (!mf_retry)					mf_retry = dup_mntfs(mf);				cp->retry = TRUE;			}		}		if (this_error >= 0) {			if (this_error > 0) {				amd_stats.d_merr++;				if (mf != mf_retry) {					mf->mf_error = this_error;					mf->mf_flags |= MFF_ERROR;				}			}			/*			 * Wakeup anything waiting for this mount			 */			wakeup((voidp) mf);		}	}	if (this_error && cp->retry) {		free_mntfs(mf);		mf = cp->mp->am_mnt = mf_retry;		/*		 * Not retrying again (so far)		 */		cp->retry = FALSE;		cp->tried = FALSE;		/*		 * Start at the beginning.		 * Rewind the location vector and		 * reset the default options.		 */		cp->ivec = cp->xivec;		cp->def_opts = strealloc(cp->def_opts, cp->auto_opts);		/*		 * Arrange that afs_bgmount is called		 * after anything else happens.		 */#ifdef DEBUG		dlog("Arranging to retry mount of %s", cp->mp->am_path);#endif /* DEBUG */		sched_task(afs_retry, (voidp) cp, (voidp) mf);		if (cp->callout)			untimeout(cp->callout);		cp->callout = timeout(RETRY_INTERVAL, wakeup, (voidp) mf);		cp->mp->am_ttl = clocktime() + RETRY_INTERVAL;		/*		 * Not done yet - so don't return anything		 */		return -1;	}	if (hard_error < 0 || this_error == 0)		hard_error = this_error;	/*	 * Discard handle on duff filesystem.	 * This should never happen since it	 * should be caught by the case above.	 */	if (mf_retry) {		if (hard_error)			plog(XLOG_ERROR, "discarding a retry mntfs for %s", mf_retry->mf_mount);		free_mntfs(mf_retry);	}	/*	 * If we get here, then either the mount succeeded or	 * there is no more mount information available.	 */	if (hard_error < 0 && mp_error)		hard_error = cp->mp->am_error = mp_error;	if (hard_error > 0) {		/*		 * Set a small(ish) timeout on an error node if		 * the error was not a time out.		 */		switch (hard_error) {		case ETIMEDOUT:		case EWOULDBLOCK:			cp->mp->am_timeo = 5;			break;		default:			cp->mp->am_timeo = 17;			break;		}		new_ttl(cp->mp);	}	/*	 * Make sure that the error value in the mntfs has a	 * reasonable value.	 */	if (mf->mf_error < 0) {		mf->mf_error = hard_error;		if (hard_error)			mf->mf_flags |= MFF_ERROR;	}	/*	 * In any case we don't need the continuation any more	 */	free_continuation(cp);	return hard_error;}/* * Automount interface to RPC lookup routine */static am_node *afs_lookuppn P((am_node *mp, char *fname, int *error_return, int op));static am_node *afs_lookuppn(mp, fname, error_return, op)am_node *mp;char *fname;int *error_return;int op;{#define ereturn(x) { *error_return = x; return 0; }	/*	 * Find the corresponding entry and return	 * the file handle for it.	 */	am_node *ap, *new_mp, *ap_hung;	char *info;			/* Mount info - where to get the file system */	char **ivec, **xivec;		/* Split version of info */	char *auto_opts;		/* Automount options */	int error = 0;			/* Error so far */	char path_name[MAXPATHLEN];	/* General path name buffer */	char *pfname;			/* Path for database lookup */	struct continuation *cp;	/* Continuation structure if we need to mount */	int in_progress = 0;		/* # of (un)mount in progress */	char *dflts;	mntfs *mf;#ifdef DEBUG	dlog("in afs_lookuppn");#endif /* DEBUG */	/*	 * If the server is shutting down	 * then don't return information	 * about the mount point.	 */	if (amd_state == Finishing) {#ifdef DEBUG		if ((mf = mp->am_mnt) == 0 || mf->mf_ops == &dfs_ops)			dlog("%s mount ignored - going down", fname);		else			dlog("%s/%s mount ignored - going down", mp->am_path, fname);#endif /* DEBUG */		ereturn(ENOENT);	}	/*	 * Handle special case of "." and ".."	 */	if (fname[0] == '.') {		if (fname[1] == '\0')

⌨️ 快捷键说明

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