📄 srvr_nfs.c
字号:
/* * 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. * * @(#)srvr_nfs.c 8.1 (Berkeley) 6/6/93 * * $Id: srvr_nfs.c,v 5.2.2.1 1992/02/09 15:09:06 jsp beta $ * *//* * NFS server modeling */#include "am.h"#include <netdb.h>#include <rpc/pmap_prot.h>#include "mount.h"extern qelem nfs_srvr_list;qelem nfs_srvr_list = { &nfs_srvr_list, &nfs_srvr_list };typedef struct nfs_private { u_short np_mountd; /* Mount daemon port number */ char np_mountd_inval; /* Port *may* be invalid */ int np_ping; /* Number of failed ping attempts */ time_t np_ttl; /* Time when server is thought dead */ int np_xid; /* RPC transaction id for pings */ int np_error; /* Error during portmap request */} nfs_private;static int np_xid; /* For NFS pings */#define NPXID_ALLOC() (++np_xid)/*#define NPXID_ALLOC() ((++np_xid&0x0fffffff) == 0 ? npxid_gc() : np_xid)*//* * Number of pings allowed to fail before host is declared down * - three-fifths of the allowed mount time...#define MAX_ALLOWED_PINGS ((((ALLOWED_MOUNT_TIME + 5 * AM_PINGER - 1) * 3) / 5) / AM_PINGER) */#define MAX_ALLOWED_PINGS (3 + /* for luck ... */ 1)/* * How often to ping when starting a new server */#define FAST_NFS_PING 3#if (FAST_NFS_PING * MAX_ALLOWED_PINGS) >= ALLOWED_MOUNT_TIME #error: sanity check failed/* you cannot do things this way... sufficient fast pings must be given the chance to fail within the allowed mount time */#endif /* (FAST_NFS_PING * MAX_ALLOWED_PINGS) >= ALLOWED_MOUNT_TIME */static int ping_len;static char ping_buf[sizeof(struct rpc_msg) + 32];/* * Flush any cached data */void flush_srvr_nfs_cache P((void));void flush_srvr_nfs_cache(){ fserver *fs = 0; ITER(fs, fserver, &nfs_srvr_list) { nfs_private *np = (nfs_private *) fs->fs_private; if (np) { np->np_mountd_inval = TRUE; np->np_error = -1; } }}/* * Startup the NFS ping */static void start_ping(P_void);static void start_ping(){ XDR ping_xdr; struct rpc_msg ping_msg; rpc_msg_init(&ping_msg, NFS_PROGRAM, NFS_VERSION, NFSPROC_NULL); /* * Create an XDR endpoint */ xdrmem_create(&ping_xdr, ping_buf, sizeof(ping_buf), XDR_ENCODE); /* * Create the NFS ping message */ if (!xdr_callmsg(&ping_xdr, &ping_msg)) { plog(XLOG_ERROR, "Couldn't create ping RPC message"); going_down(3); } /* * Find out how long it is */ ping_len = xdr_getpos(&ping_xdr); /* * Destroy the XDR endpoint - we don't need it anymore */ xdr_destroy(&ping_xdr);}/* * Called when a portmap reply arrives *//*ARGSUSED*/static void got_portmap P((voidp pkt, int len, struct sockaddr_in *sa, struct sockaddr_in *ia, voidp idv, int done));static void got_portmap(pkt, len, sa, ia, idv, done)voidp pkt;int len;struct sockaddr_in *sa;struct sockaddr_in *ia;voidp idv;int done;{ fserver *fs2 = (fserver *) idv; fserver *fs = 0; /* * Find which fileserver we are talking about */ ITER(fs, fserver, &nfs_srvr_list) if (fs == fs2) break; if (fs == fs2) { u_long port = 0; /* XXX - should be short but protocol is naff */ int error = done ? pickup_rpc_reply(pkt, len, (voidp) &port, xdr_u_long) : -1; nfs_private *np = (nfs_private *) fs->fs_private; if (!error && port) {#ifdef DEBUG dlog("got port (%d) for mountd on %s", port, fs->fs_host);#endif /* DEBUG */ /* * Grab the port number. Portmap sends back * an unsigned long in native ordering, so it * needs converting to a unsigned short in * network ordering. */ np->np_mountd = htons((u_short) port); np->np_mountd_inval = FALSE; np->np_error = 0; } else {#ifdef DEBUG dlog("Error fetching port for mountd on %s", fs->fs_host);#endif /* DEBUG */ /* * Almost certainly no mountd running on remote host */ np->np_error = error ? error : ETIMEDOUT; } if (fs->fs_flags & FSF_WANT) wakeup_srvr(fs); } else if (done) {#ifdef DEBUG dlog("Got portmap for old port request");#endif /* DEBUG */ } else {#ifdef DEBUG dlog("portmap request timed out");#endif /* DEBUG */ }}/* * Obtain portmap information */static int call_portmap P((fserver *fs, AUTH *auth, unsigned long prog, unsigned long vers, unsigned long prot));static int call_portmap(fs, auth, prog, vers, prot)fserver *fs;AUTH *auth;unsigned long prog, vers, prot;{ struct rpc_msg pmap_msg; int len; char iobuf[UDPMSGSIZE]; int error; struct pmap pmap; rpc_msg_init(&pmap_msg, PMAPPROG, PMAPVERS, (unsigned long) 0); pmap.pm_prog = prog; pmap.pm_vers = vers; pmap.pm_prot = prot; pmap.pm_port = 0; len = make_rpc_packet(iobuf, sizeof(iobuf), PMAPPROC_GETPORT, &pmap_msg, (voidp) &pmap, xdr_pmap, auth); if (len > 0) { struct sockaddr_in sin; bzero((voidp) &sin, sizeof(sin)); sin = *fs->fs_ip; sin.sin_port = htons(PMAPPORT); error = fwd_packet(RPC_XID_PORTMAP, (voidp) iobuf, len, &sin, &sin, (voidp) fs, got_portmap); } else { error = -len; } return error;}static void nfs_keepalive P((fserver*));static void recompute_portmap P((fserver *fs));static void recompute_portmap(fs)fserver *fs;{ int error; if (nfs_auth) error = 0; else error = make_nfs_auth(); if (error) { nfs_private *np = (nfs_private *) fs->fs_private; np->np_error = error; } else { call_portmap(fs, nfs_auth, MOUNTPROG, MOUNTVERS, (unsigned long) IPPROTO_UDP); }}/* * This is called when we get a reply to an RPC ping. * The value of id was taken from the nfs_private * structure when the ping was transmitted. *//*ARGSUSED*/static void nfs_pinged P((voidp pkt, int len, struct sockaddr_in *sp, struct sockaddr_in *tsp, voidp idv, int done));static void nfs_pinged(pkt, len, sp, tsp, idv, done)voidp pkt;int len;struct sockaddr_in *sp;struct sockaddr_in *tsp;voidp idv;int done;{ int xid = (int) idv; fserver *fs;#ifdef DEBUG int found_map = 0;#endif /* DEBUG */ if (!done) return; /* * For each node... */ ITER(fs, fserver, &nfs_srvr_list) { nfs_private *np = (nfs_private *) fs->fs_private; if (np->np_xid == xid) { /* * Reset the ping counter. * Update the keepalive timer. * Log what happened. */ if (fs->fs_flags & FSF_DOWN) { fs->fs_flags &= ~FSF_DOWN; if (fs->fs_flags & FSF_VALID) { srvrlog(fs, "is up"); } else { if (np->np_ping > 1) srvrlog(fs, "ok");#ifdef DEBUG else srvrlog(fs, "starts up");#endif fs->fs_flags |= FSF_VALID; }#ifdef notdef /* why ??? */ if (fs->fs_flags & FSF_WANT) wakeup_srvr(fs);#endif /* notdef */ map_flush_srvr(fs); } else { if (fs->fs_flags & FSF_VALID) {#ifdef DEBUG dlog("file server %s type nfs is still up", fs->fs_host);#endif /* DEBUG */ } else { if (np->np_ping > 1) srvrlog(fs, "ok"); fs->fs_flags |= FSF_VALID; } } /* * Adjust ping interval */ untimeout(fs->fs_cid); fs->fs_cid = timeout(fs->fs_pinger, nfs_keepalive, (voidp) fs); /* * Update ttl for this server */ np->np_ttl = clocktime() + (MAX_ALLOWED_PINGS - 1) * FAST_NFS_PING + fs->fs_pinger - 1; /* * New RPC xid... */ np->np_xid = NPXID_ALLOC(); /* * Failed pings is zero... */ np->np_ping = 0; /* * Recompute portmap information if not known */ if (np->np_mountd_inval) recompute_portmap(fs);#ifdef DEBUG
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -