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

📄 nfs_ops.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: nfs_ops.c,v 5.2.2.2 1992/05/31 16:35:05 jsp Exp $ */#ifndef lintstatic char sccsid[] = "@(#)nfs_ops.c	8.1 (Berkeley) 6/6/93";#endif /* not lint */#include "am.h"#include <sys/stat.h>#ifdef HAS_NFS#define NFS#define NFSCLIENT#ifdef NFS_3typedef nfs_fh fhandle_t;#endif /* NFS_3 */#ifdef NFS_HDR#include NFS_HDR#endif /* NFS_HDR */#include <sys/mount.h>#include "mount.h"/* * Network file system *//* * Convert from nfsstat to UN*X error code */#define unx_error(e)	((int)(e))/* * The NFS layer maintains a cache of file handles. * This is *fundamental* to the implementation and * also allows quick remounting when a filesystem * is accessed soon after timing out. * * The NFS server layer knows to flush this cache * when a server goes down so avoiding stale handles. * * Each cache entry keeps a hard reference to * the corresponding server.  This ensures that * the server keepalive information is maintained. * * The copy of the sockaddr_in here is taken so * that the port can be twiddled to talk to mountd * instead of portmap or the NFS server as used * elsewhere. * The port# is flushed if a server goes down. * The IP address is never flushed - we assume * that the address of a mounted machine never * changes.  If it does, then you have other * problems... */typedef struct fh_cache fh_cache;struct fh_cache {	qelem	fh_q;			/* List header */	voidp	fh_wchan;		/* Wait channel */	int	fh_error;		/* Valid data? */	int	fh_id;			/* Unique id */	int	fh_cid;			/* Callout id */	struct fhstatus fh_handle;	/* Handle on filesystem */	struct sockaddr_in fh_sin;	/* Address of mountd */	fserver *fh_fs;			/* Server holding filesystem */	char	*fh_path;		/* Filesystem on host */};/* * FH_TTL is the time a file handle will remain in the cache since * last being used.  If the file handle becomes invalid, then it * will be flushed anyway. */#define	FH_TTL		(5 * 60)		/* five minutes */#define	FH_TTL_ERROR	(30)			/* 30 seconds */static int fh_id = 0;#define	FHID_ALLOC()	(++fh_id)extern qelem fh_head;qelem fh_head = { &fh_head, &fh_head };static int call_mountd P((fh_cache*, unsigned long, fwd_fun, voidp));AUTH *nfs_auth;static fh_cache *find_nfs_fhandle_cache P((voidp idv, int done));static fh_cache *find_nfs_fhandle_cache(idv, done)voidp idv;int done;{	fh_cache *fp, *fp2 = 0;	int id = (int) idv;	ITER(fp, fh_cache, &fh_head) {		if (fp->fh_id == id) {			fp2 = fp;			break;		}	}#ifdef DEBUG	if (fp2) {		dlog("fh cache gives fp %#x, fs %s", fp2, fp2->fh_path);	} else {		dlog("fh cache search failed");	}#endif /* DEBUG */	if (fp2 && !done) {		fp2->fh_error = ETIMEDOUT;		return 0;	}	return fp2;}/* * Called when a filehandle appears */static void got_nfs_fh P((voidp pkt, int len, struct sockaddr_in *sa,				struct sockaddr_in *ia, voidp idv, int done));static void got_nfs_fh(pkt, len, sa, ia, idv, done)voidp pkt;int len;struct sockaddr_in *sa, *ia;voidp idv;int done;{	fh_cache *fp = find_nfs_fhandle_cache(idv, done);	if (fp) {		fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &fp->fh_handle, xdr_fhstatus);		if (!fp->fh_error) {#ifdef DEBUG			dlog("got filehandle for %s:%s", fp->fh_fs->fs_host, fp->fh_path);#endif /* DEBUG */			/*			 * Wakeup anything sleeping on this filehandle			 */			if (fp->fh_wchan) {#ifdef DEBUG				dlog("Calling wakeup on %#x", fp->fh_wchan);#endif /* DEBUG */				wakeup(fp->fh_wchan);			}		}	}}void flush_nfs_fhandle_cache P((fserver *fs));void flush_nfs_fhandle_cache(fs)fserver *fs;{	fh_cache *fp;	ITER(fp, fh_cache, &fh_head) {		if (fp->fh_fs == fs || fs == 0) {			fp->fh_sin.sin_port = (u_short) 0;			fp->fh_error = -1;		}	}}static void discard_fh P((fh_cache *fp));static void discard_fh(fp)fh_cache *fp;{	rem_que(&fp->fh_q);#ifdef DEBUG	dlog("Discarding filehandle for %s:%s", fp->fh_fs->fs_host, fp->fh_path);#endif /* DEBUG */	free_srvr(fp->fh_fs);	free((voidp) fp->fh_path);	free((voidp) fp);}/* * Determine the file handle for a node */static int prime_nfs_fhandle_cache P((char *path, fserver *fs, struct fhstatus *fhbuf, voidp wchan));static int prime_nfs_fhandle_cache(path, fs, fhbuf, wchan)char *path;fserver *fs;struct fhstatus *fhbuf;voidp wchan;{	fh_cache *fp, *fp_save = 0;	int error;	int reuse_id = FALSE;#ifdef DEBUG	dlog("Searching cache for %s:%s", fs->fs_host, path);#endif /* DEBUG */	/*	 * First search the cache	 */	ITER(fp, fh_cache, &fh_head) {		if (fs == fp->fh_fs && strcmp(path, fp->fh_path) == 0) {			switch (fp->fh_error) {			case 0:				error = fp->fh_error = unx_error(fp->fh_handle.fhs_status);				if (error == 0) {					if (fhbuf)						bcopy((voidp) &fp->fh_handle, (voidp) fhbuf,							sizeof(fp->fh_handle));					if (fp->fh_cid)						untimeout(fp->fh_cid);					fp->fh_cid = timeout(FH_TTL, discard_fh, (voidp) fp);				} else if (error == EACCES) {					/*					 * Now decode the file handle return code.					 */					plog(XLOG_INFO, "Filehandle denied for \"%s:%s\"",						fs->fs_host, path);				} else {					errno = error;	/* XXX */					plog(XLOG_INFO, "Filehandle error for \"%s:%s\": %m",						fs->fs_host, path);				}				/*				 * The error was returned from the remote mount daemon.				 * Policy: this error will be cached for now...				 */				return error;			case -1:				/*				 * Still thinking about it, but we can re-use.				 */				fp_save = fp;				reuse_id = TRUE;				break;			default:				/*				 * Return the error.				 * Policy: make sure we recompute if required again				 * in case this was caused by a network failure.				 * This can thrash mountd's though...  If you find				 * your mountd going slowly then:				 * 1.  Add a fork() loop to main.				 * 2.  Remove the call to innetgr() and don't use				 *     netgroups, especially if you don't use YP.				 */				error = fp->fh_error;				fp->fh_error = -1;				return error;			}			break;		}	}	/*	 * Not in cache	 */	if (fp_save) {		fp = fp_save;		/*		 * Re-use existing slot		 */		untimeout(fp->fh_cid);		free_srvr(fp->fh_fs);		free(fp->fh_path);	} else {		fp = ALLOC(fh_cache);		bzero((voidp) fp, sizeof(*fp));		ins_que(&fp->fh_q, &fh_head);	}	if (!reuse_id)		fp->fh_id = FHID_ALLOC();	fp->fh_wchan = wchan;	fp->fh_error = -1;	fp->fh_cid = timeout(FH_TTL, discard_fh, (voidp) fp);	/*	 * If the address has changed then don't try to re-use the	 * port information	 */	if (fp->fh_sin.sin_addr.s_addr != fs->fs_ip->sin_addr.s_addr) {		fp->fh_sin = *fs->fs_ip;		fp->fh_sin.sin_port = 0;	}	fp->fh_fs = dup_srvr(fs);	fp->fh_path = strdup(path);	error = call_mountd(fp, MOUNTPROC_MNT, got_nfs_fh, wchan);	if (error) {		/*		 * Local error - cache for a short period		 * just to prevent thrashing.		 */		untimeout(fp->fh_cid);		fp->fh_cid = timeout(error < 0 ? 2 * ALLOWED_MOUNT_TIME : FH_TTL_ERROR,						discard_fh, (voidp) fp);		fp->fh_error = error;	} else {		error = fp->fh_error;	}	return error;}int make_nfs_auth P((void)){#ifdef HAS_NFS_QUALIFIED_NAMES	/*	 * From: Chris Metcalf <metcalf@masala.lcs.mit.edu>	 * Use hostd, not just hostname.  Note that uids	 * and gids and the gidlist are type *int* and not the	 * system uid_t and gid_t types.	 */	static int group_wheel = 0;	nfs_auth = authunix_create(hostd, 0, 0, 1, &group_wheel);#else	nfs_auth = authunix_create_default();#endif	if (!nfs_auth)		return ENOBUFS;	return 0;}static int call_mountd P((fh_cache *fp, u_long proc, fwd_fun f, voidp wchan));static int call_mountd(fp, proc, f, wchan)fh_cache *fp;u_long proc;fwd_fun f;voidp wchan;{	struct rpc_msg mnt_msg;	int len;	char iobuf[8192];	int error;	if (!nfs_auth) {		error = make_nfs_auth();		if (error)			return error;	}	if (fp->fh_sin.sin_port == 0) {		u_short port;		error = nfs_srvr_port(fp->fh_fs, &port, wchan);		if (error)			return error;		fp->fh_sin.sin_port = port;	}	rpc_msg_init(&mnt_msg, MOUNTPROG, MOUNTVERS, (unsigned long) 0);	len = make_rpc_packet(iobuf, sizeof(iobuf), proc,			&mnt_msg, (voidp) &fp->fh_path, xdr_nfspath,  nfs_auth);	if (len > 0) {		error = fwd_packet(MK_RPC_XID(RPC_XID_MOUNTD, fp->fh_id),			(voidp) iobuf, len, &fp->fh_sin, &fp->fh_sin, (voidp) fp->fh_id, f);	} else {		error = -len;	}/* * It may be the case that we're sending to the wrong MOUNTD port.  This * occurs if mountd is restarted on the server after the port has been * looked up and stored in the filehandle cache somewhere.  The correct * solution, if we're going to cache port numbers is to catch the ICMP * port unreachable reply from the server and cause the portmap request * to be redone.  The quick solution here is to invalidate the MOUNTD * port. */      fp->fh_sin.sin_port = 0;	return error;

⌨️ 快捷键说明

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