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

📄 nfs_server.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
#ifndef lintstatic	char	*sccsid = "@(#)nfs_server.c	4.5	(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 *	Cleanup for server view of fhandle. * * 27 Feb 91 -- chet *	Fix filesystem timestamping. * *  9 Nov 90 -- prs *	Don't call VOP_BREAD unless vnode refers to a *	UFS file in rfs_read(). * * 27 Aug 90 -- chet *	Changed locking protocol for rfs_link. * * 25 Aug 90 -- chet *	Fixed remove's use of duplicate request cache. *	Move svckudp_dupdone() call  in rfs_dispatch(). * * 12 Jan 90 -- prs *	Moved lockinit of nfsargs to nfs_subr. * * 14 Nov 89 -- prs *	Fixed null pointer reference problem in rfs_dispatch(). * * 28 Feb 89 -- chet *      Fix use of duplicate request cache for rfs_remove and *      rfs_symlink * * 22 Aug 88 -- condylis for cb *	Added gfs_unlock in rfs_mkdir after VOP_LOOKUP call. * * 17 Aug 88 -- chet *	Set ruid and rgid fields in server daemon's u area * * 13 Mar 88 -- chet *	Get rid of nobody variable and change rdonly macro. *	Fhtovp() now does root mapping and exported fs check. * * 4 Feb 88 -- chet for cb *	add fifo mode fix to rfs_create(). * * 26 Jan 88 -- chet *	Modified trailer portion of stale fhandle messages * * 12-11-87	Robin L. and Larry C. and Ricky P. *	Added new kmalloc memory allocation to system. * * 11 Nov 87 -- chet *	Added defensive check for non-directories to rfs_lookup(). * * 14 Jul 87 -- cb *	Changed mknod interface. * * 19 May 87 -- logcher *	Changed soreserve back from 24000 to 65000 since SB_MAX  *	is now 65K * * 13 May 87 -- williams  *	Changes soreserve from 65000 to 24000 because the max socket * 	size has been dropped from 64k to 32k.   This should be set *	back to 65000 once the socket code is debugged. * * 11 May 87 -- chet *	Changed server action routines to use new server duplicate *	transaction cache interface routines. * * 05-May-87 -- logcher *	Changed usage of m_exflags to m_flags. * * 10-Apr-87 -- logcher *	Added Larry Palmer's to modify soreserve_size * * 02-Mar-87 -- logcher *	Merged in diskless changes, added export read-only to *	rdonly macro, added check in rfs_lookup to not give  *	out fhandle if NOFH flag set, added code to allow mknod *	for non-regular files  */#include "../h/param.h"#include "../h/mount.h"#include "../h/systm.h"#include "../h/user.h"#include "../h/buf.h"#include "../h/uio.h"#include "../h/file.h"#include "../h/socketvar.h"#include "../h/socket.h"#include "../h/errno.h"#include "../h/gnode.h"#include "../h/mbuf.h"#include "../h/fs_types.h"#include "../h/kernel.h"#include "../h/cpudata.h"#include "../net/netinet/in.h"#include "../net/rpc/types.h"#include "../net/rpc/auth.h"#include "../net/rpc/auth_unix.h"#include "../net/rpc/svc.h"#include "../net/rpc/xdr.h"#define  NFSSERVER#include "../nfs/nfs.h"#include "../nfs/nfs_clnt.h"#include "../nfs/vfs.h"#include "../nfs/vnode.h"#include "../ufs/fs.h"	/* WARNING: BEWARE of future UFS define */extern char *rfsnames[];struct nfs_dupstat {	int writes;	int creates;	int removes;	int links;	int symlinks;	int mkdirs;	int rmdirs;	int renames;	int setattrs;	int throwaways;} nfs_dupstats;int nfs_n_daemons = 0;	/* number of running NFS daemon processes *//* * rpc service program version range supported */#define	VERSIONMIN	2#define	VERSIONMAX	2/* * Returns true iff filesystem for a given fsid is  *	exported read-only and mounted read-only * */#define rdonly(gp, xpd) (((xpd)->x_flags & M_EXRONLY) || ISREADONLY(gp->g_mp))struct vnode	*fhtovp();struct file	*getsock();void		svcerr_progvers();void		rfs_dispatch();extern struct export *exported;struct lock_t lk_nfsargs;extern struct lock_t lk_gnode;extern struct lock_t lk_nfsstat;extern struct lock_t lk_nfsbiod;	/* used for count of biods and nfsds */struct {        int     ncalls;         /* number of calls received */        int     nbadcalls;      /* calls that failed */        int     reqs[32];       /* count for each request */} svstat;int soreserve_size = 65000;/* * NFS Server system call. * Does all of the work of running an NFS server. * sock is the fd of an open UDP socket. */nfs_svc(){	struct a {		int     sock;	} *uap = (struct a *)u.u_ap;	struct gnode	*rdir;	struct gnode	*cdir;	struct socket   *so;	struct file	*fp;	SVCXPRT *xprt;	u_long	vers;	int	error; 	fp = getsock(uap->sock);	if (fp == 0) {		u.u_error = EBADF;		return;	}	so = (struct socket *)fp->f_data;	/*	 *	Allocate extra space for this socket, to minimize	 *	lost requests for NFS.  We don't want everyone to do	 *	this, so do it here, rather than in udp_usrreq().	 */	error = soreserve(so, soreserve_size, 		soreserve_size + 2 *(sizeof(struct sockaddr)));	if (error)	{		u.u_error = error;		return;	}	/*	 * Be sure that rdir (the server's root vnode) is set.	 * Save the current directory and restore it again when	 * the call terminates.  rfs_lookup uses u.u_cdir for lookupname.	 */	rdir = u.u_rdir;	cdir = u.u_cdir;	if (rdir == (struct gnode *)0) {		u.u_rdir = u.u_cdir;	}	xprt = svckudp_create(so, NFS_PORT);	smp_lock(&lk_nfsbiod, LK_RETRY); 	/* same lock used for biod count	*/	++nfs_n_daemons; /* increment running server count */	smp_unlock(&lk_nfsbiod);	for (vers = VERSIONMIN; vers <= VERSIONMAX; vers++) {		(void) svc_register(xprt, NFS_PROGRAM, vers, rfs_dispatch,		    FALSE);	}	if (setjmp(&u.u_qsave)) {		/* shut the service down when the last daemon exits */		smp_lock(&lk_nfsbiod, LK_RETRY);		if (--nfs_n_daemons <= 0) {			for (vers = VERSIONMIN; vers <= VERSIONMAX; vers++) {				svc_unregister(NFS_PROGRAM, vers);			}			smp_unlock(&lk_nfsbiod);			SVC_DESTROY(xprt);		} else 			smp_unlock(&lk_nfsbiod);		u.u_error = EINTR;	} else {		svc_run(xprt);  /* never returns */	}	u.u_rdir = rdir;	u.u_cdir = cdir;}/* * Get file handle system call. * Takes open file descriptor and returns a file handle for it. */nfs_getfh(){	register struct a {		int	fdes1;		int	fdes2;		fhandle_t	*fhp;	} *uap = (struct a*)u.u_ap;	register struct file *fp1, *fp2;	fhandle_t fh;	struct vnode *vp1, *vp2;	if (!suser()) {		return;	}	fp1 = getf(uap->fdes1);	if (fp1 == NULL) {		return;	}	fp2 = getf(uap->fdes2);	if (fp2 == NULL) {		return;	}	vp1 = (struct vnode *)fp1->f_data;	vp2 = (struct vnode *)fp2->f_data;	gfs_lock(vp1);	if (vp1 != vp2)		gfs_lock(vp2);	u.u_error = makefh(&fh, vp1, vp2->g_number, vp2->g_gennum);	gfs_unlock(vp1);	if (vp1 != vp2)		gfs_unlock(vp2);	if (!u.u_error) {		u.u_error =		    copyout((caddr_t)&fh, (caddr_t)uap->fhp, sizeof(fh));	}	return;}	/* * These are the interface routines for the server side of the * Networked File System.  See the NFS protocol specification * for a description of this interface. *//* * Get file attributes. * Returns the current attributes of the file with the given fhandle. */intrfs_getattr(fhp, ns, req, xprt, xpd)	fhandle_t *fhp;	register struct nfsattrstat *ns;	struct svc_req *req;	SVCXPRT *xprt;	struct exportdata *xpd;{	register int error = 0;	register struct vnode *vp;	struct vattr va;	vp = fhtovp(fhp, xprt, RFS_GETATTR, xpd);	if (vp == NULL) {		ns->ns_status = NFSERR_STALE;		return(ESTALE);	}	error = VOP_GETATTR(vp, &va, u.u_cred);	if (!error) {		vattr_to_nattr(&va, &ns->ns_attr);	}	ns->ns_status = puterrno(error);	gput(vp);	return(0);}/* * Set file attributes. * Sets the attributes of the file with the given fhandle.  Returns * the new attributes. */intrfs_setattr(args, ns, req, xprt, xpd)	struct nfssaargs *args;	register struct nfsattrstat *ns;	struct svc_req *req;	SVCXPRT *xprt;	struct exportdata *xpd;{	register int error = 0;	register struct vnode *vp;	struct vattr va;	struct timeval duptime;	int dupmark;	vp = fhtovp(&args->saa_fh, xprt, RFS_SETATTR, xpd);	if (vp == NULL) {		ns->ns_status = NFSERR_STALE;		return(ESTALE);	}	if (rdonly(vp,xpd)) {		error = EROFS;	} else {		if (svckudp_dup(req, &duptime, &dupmark) &&			duptime.tv_sec == vp->g_ctime.tv_sec &&			duptime.tv_usec == vp->g_ctime.tv_usec)				++nfs_dupstats.setattrs;		else {			sattr_to_vattr(&args->saa_sa, &va);			error = VOP_SETATTR(vp, &va, u.u_cred);		}		if (!error) {			error = VOP_GETATTR(vp, &va, u.u_cred);			if (!error) {				vattr_to_nattr(&va, &ns->ns_attr);			}		}		if (error) {			svckudp_dupsave(req, *timepick, DUP_FAIL);		} else {			svckudp_dupsave(req, vp->g_ctime, DUP_DONE);		}	}	ns->ns_status = puterrno(error);	gput(vp);	return (0);}/* * Directory lookup. * Returns an fhandle and file attributes for file name in a directory. */intrfs_lookup(da, dr, req, xprt, xpd)	struct nfsdiropargs *da;	register struct  nfsdiropres *dr;	struct svc_req *req;	SVCXPRT *xprt;	struct exportdata *xpd;{	register int error = 0;	register struct vnode *dvp;	struct vnode *vp;	struct vattr va;	dvp = fhtovp(&da->da_fhandle, xprt, RFS_LOOKUP, xpd);	if (dvp == NULL) {		dr->dr_status = NFSERR_STALE;		return(ESTALE);	}	/* Make sure that we are positioned at a directory */	if ((dvp->g_mode & GFMT) != GFDIR) { 		dr->dr_status = NFSERR_NOTDIR;		gput(dvp); 		return(0);	}	/* 	 * Check if NOFH flag set from /etc/exports 	 * and giving out root inode 	 *//* 	if ((dvp->g_mp->m_flags & M_NOFH) && dvp->g_number == ROOTINO) { 		dr->dr_status = NFSERR_PERM;		gput(dvp); 		return(0); 	}*/ 	/*	 * do lookup.	 */	error = VOP_LOOKUP(dvp, da->da_name, &vp, u.u_cred);	gfs_unlock(dvp);	if (error) {		vp = (struct vnode *)0;	} else {		/* 	 	 * Check if NOFH flag set from /etc/exports 		 * and giving out root inode 	 	 *//*		if ((vp->g_mp->m_flags & M_NOFH) && vp->g_number == ROOTINO) {			dr->dr_status = NFSERR_PERM;			grele(dvp);			grele(vp);			return(0);		}*/		gfs_lock(vp);		error = VOP_GETATTR(vp, &va, u.u_cred);		if (!error) {			vattr_to_nattr(&va, &dr->dr_attr);			error = makefh(&dr->dr_fhandle, vp, 				       da->da_fhandle.fh_eno,				       da->da_fhandle.fh_egen);		}		gfs_unlock(vp);	}	dr->dr_status = puterrno(error);	grele(dvp);	if (vp) {		grele(vp);	}	return(0);}/* * Read symbolic link. * Returns the string in the symbolic link at the given fhandle. */intrfs_readlink(fhp, rl, req, xprt, xpd)	fhandle_t *fhp;	register struct nfsrdlnres *rl;	struct svc_req *req;	SVCXPRT *xprt;	struct exportdata *xpd;{	register int error = 0;	struct iovec iov;	struct uio uio;	struct vnode *vp;	vp = fhtovp(fhp, xprt, RFS_READLINK, xpd);	if (vp == NULL) {		rl->rl_status = NFSERR_STALE;		return(ESTALE);	}	/*	 * Allocate data for pathname.  This will be freed by rfs_rlfree.	 */	kmem_alloc(rl->rl_data, char *, MAXPATHLEN, KM_NFS);	/*	 * Set up io vector to read sym link data	 */	iov.iov_base = rl->rl_data;	iov.iov_len = NFS_MAXPATHLEN;	uio.uio_iov = &iov;	uio.uio_iovcnt = 1;	uio.uio_segflg = UIO_SYSSPACE;	uio.uio_offset = 0;	uio.uio_resid = NFS_MAXPATHLEN;	/*	 * read link	 */	error = VOP_READLINK(vp, &uio, u.u_cred);	/*	 * Clean up	 */	if (error) {			kmem_free(rl->rl_data, KM_NFS);		rl->rl_count = 0;		rl->rl_data = NULL;	} else {		rl->rl_count = NFS_MAXPATHLEN - uio.uio_resid;	}	rl->rl_status = puterrno(error);	gput(vp);	return(0);}/* * Free data allocated by rfs_readlink */rfs_rlfree(rl)	struct nfsrdlnres *rl;{	if (rl->rl_data) {		kmem_free(rl->rl_data, KM_NFS);	}}/* * Read data. * Returns some data read from the file at the given fhandle. */intrfs_read(ra, rr, req, xprt, xpd)	struct nfsreadargs *ra;	register struct nfsrdresult *rr;	struct svc_req *req;	SVCXPRT *xprt;	struct exportdata *xpd;{	register int error = 0;	struct vnode *vp;	struct iovec iov;	struct uio uio;	int offset, fsbsize;	struct buf *bp;	rr->rr_data = NULL;	rr->rr_count = 0;	vp = fhtovp(&ra->ra_fhandle, xprt, RFS_READ, xpd);	if (vp == NULL) {		rr->rr_status = NFSERR_STALE;		return(ESTALE);	}	/*	 * This is a kludge to allow reading of files created	 * with no read permission.  The owner of the file

⌨️ 快捷键说明

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