📄 nfs_subr.c
字号:
#ifndef lintstatic char *sccsid = "@(#)nfs_subr.c 4.6 (ULTRIX) 2/28/91";#endif lint/************************************************************************ * * * Copyright (c) 1986, 1987 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//* * Portions of this software have been licensed to * Digital Equipment Company, Maynard, MA. * Copyright (c) 1986 Sun Microsystems, Inc. ALL RIGHTS RESERVED. *//* * * Modification history: * * 28 Feb 91 -- dws * Clean up for server view of fhandle. * * 27 Feb 91 -- chet * Change nfs_attrcache() calls (yet again). * * 10 Feb 91 -- chet * Change nfs_attrcache() calls (again). * * 29 Jan 91 -- chet * Make kernel RPC calls interruptible. * * 7 Jul 90 -- chet * Change nfs_attrcache() calls. * * 9 Mar 90 -- chet * Change nfs_attrcache() calls for new argument. * Add clearing of rnode in nfs_ginit(). * * 12 Jan 90 -- prs * Added a lockinit of nfsargs lock structure to nfsinit(). * * 08 Dec 89 -- cb * fixed export list corruption bug. Also check for null gp * in makenfsnode(). * * 19 Jul 89 -- cb * modified exportfs() and makefh() to support export options on * directories. * * 15 May 89 -- condylis * Moved specvp call from makenfsnode() to nfs_ginit(). * * 10 Mar 89 -- chet * Added nfs_system_size() routine that returns * "small | medium | large | xlarge"; * use it to size # of client handles. * * 7 Mar 89 -- condylis * Free client handle for a time between RPC timeout cycles * when trying to reach a hard mounted server. * * 28 Feb 89 -- chet * Added scheme to prevent "stale fhandle" messages from * locking out server console. * * 6 Feb 89 -- prs * Added gput() to a return path in exportfs(). * * 1 Sep 88 -- chet * Put a unique transaction ID into rfscall * * 18-Jul-88 -- condylis * Added SMP locking for CLIENT handle table in clget and clfree. * Added nfsinit to initialize NFS SMP locks. Replaced unsafe * modifications of gnodes with calls to SMP gnode primitives. * Added SMP locking of NFS client statistics. * * 10-Jun-88 -- jaw * add parameter to ISSIG for SMP.... this makes going to stop * state atomic. * * 17 Aug 88 -- chet * Clear the group IDs for a root mapped to nobody * * 8 Mar 88 -- chet * exportfs() changes * * 4 Feb 88 -- chet * Change fhtovp() to not return fhandle unless filesystem * is exported. * * 26 Jan 88 -- chet * Fix newname() so that it comes up with a more unique name. * This routine is used by nfs_unlink() when unlinking open files. * * 14 Jan 88 -- chet * Expanded stale file handle messages * * 12-28-87 Tim Burke * Moved u.u_ttyp to u.u_procp->p_ttyp. * * 12-11-87 Robin L. and Larry C. and Ricky P. * Added new kmalloc memory allocation to system. * * 14-Jul-87 -- logcher * Revised logic in exportfs. Fixed declaration of uap * arguments. Added logic to only set m_flags if M_NOFH or * M_EXRONLY and no other flags ar set. Added logic to clear * the M_NOFH and M_EXRONLY flags before setting. This way a * flag is turned off without having to reboot or adb the kernel. * * 17-Jun-87 -- logcher * Changed short cast to an int in exportfs * * 15-Jun-87 -- logcher * Added suser check to exportfs(), cleaned up returns * * 05-May-87 -- logcher * Changed usage of m_exflags to m_flags and added M_EXRONLY * * 02-Mar-87 -- logcher * Merged in diskless changes, added exportfs and check in * fhtovp for root mapping, added check for specvp */#include "../h/param.h"#include "../h/systm.h"#include "../h/user.h"#include "../h/kernel.h"#include "../h/buf.h"#include "../h/proc.h"#include "../h/fs_types.h"#include "../h/mount.h"#include "../h/gnode.h"#include "../h/socket.h"#include "../h/socketvar.h"#include "../h/uio.h"#include "../net/netinet/in.h"#include "../net/rpc/types.h"#include "../net/rpc/xdr.h"#include "../net/rpc/auth.h"#include "../net/rpc/clnt.h"#include "../net/rpc/svc.h"#include "../net/net/if.h"#define NFSSERVER#include "../nfs/nfs.h"#include "../nfs/nfs_clnt.h"#include "../nfs/vfs.h"#include "../nfs/vnode.h"#include "../ufs/fs.h"int do_uprintf = 0;extern struct vnodeops nfs_vnodeops;extern struct gnode_ops *nfs_gnode_ops;extern struct mount_ops *nfs_mount_ops;struct gnode *rfind();extern struct lock_t lk_gnode;/* * Client side utilities *//* * client side statistics */struct { int nclsleeps; /* client handle waits */ int nclgets; /* client handle gets */ int ncalls; /* client requests */ int nbadcalls; /* rpc failures */ int reqs[32]; /* count of each request */} clstat;/* SMP lock for client handle table */struct lock_t lk_nfschtable;/* SMP lock for nfs and rpc statistics */struct lock_t lk_nfsstat;/* Need extern for nfsinit routine */extern struct lock_t lk_nfsbiod;extern struct lock_t lk_nfsdnlc;extern struct lock_t lk_nfsrrok;extern struct lock_t lk_nfsargs;/* lk_rpcxid is used by rpc clients for updating client handle xids *//* (also used by klm_lockmgr.c) */extern struct lock_t lk_rpcxid;#define MINCLIENTS 8#define MAXCLIENTS 36struct chtab { int ch_timesused; bool_t ch_inuse; CLIENT *ch_client;} chtable[MAXCLIENTS];int chtable_max = 0; /* chtable high water mark */int clwanted = 0;/* NFS transaction ID */int nfs_next_xid = 0;struct chtab *clget(mi, cred) struct mntinfo *mi; struct ucred *cred;{ register struct chtab *ch; int retrans; /* * Set client handle table high water mark based on system "size" */ if (!chtable_max) { smp_lock(&lk_nfschtable, LK_RETRY); if (!chtable_max) { chtable_max = 8 * nfs_system_size(); chtable_max = MAX(MINCLIENTS, chtable_max); chtable_max = MIN(MAXCLIENTS, chtable_max); } smp_unlock(&lk_nfschtable); } /* * If soft mount and server is down just try once */ if (!mi->mi_hard && mi->mi_down) { retrans = 1; } else { retrans = mi->mi_retrans; } /* * Find an unused handle or create one if not at limit yet. */ for (;;) { smp_lock(&lk_nfsstat, LK_RETRY); clstat.nclgets++; smp_unlock(&lk_nfsstat); /* SMP lock client handle table during access */ smp_lock(&lk_nfschtable, LK_RETRY); for (ch = chtable; ch < &chtable[chtable_max]; ch++) { if (!ch->ch_inuse) { ch->ch_inuse = TRUE; smp_unlock(&lk_nfschtable); if (ch->ch_client == NULL) { ch->ch_client = clntkudp_create(&mi->mi_addr, NFS_PROGRAM, NFS_VERSION, retrans, cred); if (ch->ch_client == NULL) panic("clget: null client"); } else { clntkudp_init(ch->ch_client, &mi->mi_addr, retrans, cred); } ch->ch_timesused++; return (ch); } } /* * If we got here there are no available handles */ clwanted++; sleep_unlock((caddr_t)chtable, PRIBIO, &lk_nfschtable); smp_lock(&lk_nfsstat, LK_RETRY); clstat.nclsleeps++; smp_unlock(&lk_nfsstat); }}clfree(ch) struct chtab *ch;{ /* SMP lock client handle table during access */ smp_lock(&lk_nfschtable, LK_RETRY); ch->ch_inuse = FALSE; if (clwanted) { clwanted = 0; wakeup((caddr_t)chtable); } smp_unlock(&lk_nfschtable);}char *rpcstatnames[] = { "Success", "Can't encode arguments", "Can't decode result", "Unable to send", "Unable to receive", "Timed out", "Incompatible versions of RPC", "Authentication error", "Program unavailable", "Program/version mismatch", "Procedure unavailable", "Server can't decode arguments", "Remote system error", "Unknown host", "Port mapper failure", "Program not registered", "Failed (unspecified error)", "Unknown protocol", "Interrupted" };char *rfsnames[] = { "null", "getattr", "setattr", "unused", "lookup", "readlink", "read", "unused", "write", "create", "remove", "rename", "link", "symlink", "mkdir", "rmdir", "readdir", "fsstat" };/* * Back off for retransmission timeout, MAXTIMO is in 10ths of a sec */#define MAXTIMO 300#define backoff(tim) ((((tim) << 2) > MAXTIMO) ? MAXTIMO : ((tim) << 2))intrfscall(mi, which, xdrargs, argsp, xdrres, resp, cred) register struct mntinfo *mi; int which; xdrproc_t xdrargs; caddr_t argsp; xdrproc_t xdrres; caddr_t resp; struct ucred *cred;{ struct chtab *cht; CLIENT *client; register enum clnt_stat status; struct rpc_err rpcerr; struct timeval wait; struct ucred *newcred; int timeo; int user_told; bool_t tryagain; int hold_nfs_xid; extern nfs_hardpause(); if (cred == NULL) panic("rfscall: NULL cred"); smp_lock(&lk_nfsstat, LK_RETRY); clstat.ncalls++; clstat.reqs[which]++; smp_unlock(&lk_nfsstat); rpcerr.re_errno = 0; newcred = NULL; timeo = mi->mi_timeo; user_told = 0;retry: cht = clget(mi, cred); client = cht->ch_client; /* NFS transaction ID */ smp_lock(&lk_rpcxid, LK_RETRY); if (!nfs_next_xid) nfs_next_xid = timepick->tv_sec; client->cl_xid = nfs_next_xid++; smp_unlock(&lk_rpcxid); /* * If hard mounted fs, retry call forever unless hard error occurs */ do { tryagain = FALSE; wait.tv_sec = timeo / 10; wait.tv_usec = 100000 * (timeo % 10); status = CLNT_CALL(client, which, xdrargs, argsp, xdrres, resp, wait); switch (status) { case RPC_SUCCESS: break; /* * Unrecoverable errors: give up immediately */ case RPC_AUTHERROR: case RPC_CANTENCODEARGS: case RPC_CANTDECODERES: case RPC_VERSMISMATCH: case RPC_PROGVERSMISMATCH: case RPC_CANTDECODEARGS: break; default: if (mi->mi_hard) { if (mi->mi_int && status == RPC_INTR) { tryagain = FALSE; break; } else { tryagain = TRUE; if (status == RPC_INTR) continue; timeo = backoff(timeo); if (!mi->mi_printed) { mi->mi_printed = 1; mprintf("NFS server %s not responding, still trying\n", mi->mi_hostname); } if (!user_told && u.u_procp->p_ttyp) { user_told = 1; uprintf("NFS server %s not responding, still trying\n", mi->mi_hostname); } /* * Pause to free up the client handle * for a while. (minimum of 1 * second) */ hold_nfs_xid = client->cl_xid;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -