📄 nfs_server.c
字号:
#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 + -