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

📄 nfs_serv.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Copyright (c) 1989, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Rick Macklem at The University of Guelph. * * 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. * *	@(#)nfs_serv.c	8.3 (Berkeley) 1/12/94 *//* * nfs version 2 server calls to vnode ops * - these routines generally have 3 phases *   1 - break down and validate rpc request in mbuf list *   2 - do the vnode ops for the request *       (surprisingly ?? many are very similar to syscalls in vfs_syscalls.c) *   3 - build the rpc reply in an mbuf list *   nb: *	- do not mix the phases, since the nfsm_?? macros can return failures *	  on a bad rpc or similar and do not do any vrele() or vput()'s * *      - the nfsm_reply() macro generates an nfs rpc reply with the nfs *	error number iff error != 0 whereas *	returning an error from the server function implies a fatal error *	such as a badly constructed rpc request that should be dropped without *	a reply. */#include <sys/param.h>#include <sys/systm.h>#include <sys/proc.h>#include <sys/file.h>#include <sys/namei.h>#include <sys/vnode.h>#include <sys/mount.h>#include <sys/mbuf.h>#include <sys/dirent.h>#include <sys/stat.h>#include <vm/vm.h>#include <nfs/nfsv2.h>#include <nfs/rpcv2.h>#include <nfs/nfs.h>#include <nfs/xdr_subs.h>#include <nfs/nfsm_subs.h>#include <nfs/nqnfs.h>/* Defs */#define	TRUE	1#define	FALSE	0/* Global vars */extern u_long nfs_procids[NFS_NPROCS];extern u_long nfs_xdrneg1;extern u_long nfs_false, nfs_true;nfstype nfs_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON,		      NFCHR, NFNON };/* * nqnfs access service */nqnfsrv_access(nfsd, mrep, md, dpos, cred, nam, mrq)	struct nfsd *nfsd;	struct mbuf *mrep, *md;	caddr_t dpos;	struct ucred *cred;	struct mbuf *nam, **mrq;{	struct vnode *vp;	nfsv2fh_t nfh;	fhandle_t *fhp;	register u_long *tl;	register long t1;	caddr_t bpos;	int error = 0, rdonly, cache, mode = 0;	char *cp2;	struct mbuf *mb, *mreq;	u_quad_t frev;	fhp = &nfh.fh_generic;	nfsm_srvmtofh(fhp);	nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);	if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))		nfsm_reply(0);	if (*tl++ == nfs_true)		mode |= VREAD;	if (*tl++ == nfs_true)		mode |= VWRITE;	if (*tl == nfs_true)		mode |= VEXEC;	error = nfsrv_access(vp, mode, cred, rdonly, nfsd->nd_procp);	vput(vp);	nfsm_reply(0);	nfsm_srvdone;}/* * nfs getattr service */nfsrv_getattr(nfsd, mrep, md, dpos, cred, nam, mrq)	struct nfsd *nfsd;	struct mbuf *mrep, *md;	caddr_t dpos;	struct ucred *cred;	struct mbuf *nam, **mrq;{	register struct nfsv2_fattr *fp;	struct vattr va;	register struct vattr *vap = &va;	struct vnode *vp;	nfsv2fh_t nfh;	fhandle_t *fhp;	register u_long *tl;	register long t1;	caddr_t bpos;	int error = 0, rdonly, cache;	char *cp2;	struct mbuf *mb, *mb2, *mreq;	u_quad_t frev;	fhp = &nfh.fh_generic;	nfsm_srvmtofh(fhp);	if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))		nfsm_reply(0);	nqsrv_getl(vp, NQL_READ);	error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);	vput(vp);	nfsm_reply(NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));	nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));	nfsm_srvfillattr;	nfsm_srvdone;}/* * nfs setattr service */nfsrv_setattr(nfsd, mrep, md, dpos, cred, nam, mrq)	struct nfsd *nfsd;	struct mbuf *mrep, *md;	caddr_t dpos;	struct ucred *cred;	struct mbuf *nam, **mrq;{	struct vattr va;	register struct vattr *vap = &va;	register struct nfsv2_sattr *sp;	register struct nfsv2_fattr *fp;	struct vnode *vp;	nfsv2fh_t nfh;	fhandle_t *fhp;	register u_long *tl;	register long t1;	caddr_t bpos;	int error = 0, rdonly, cache;	char *cp2;	struct mbuf *mb, *mb2, *mreq;	u_quad_t frev, frev2;	fhp = &nfh.fh_generic;	nfsm_srvmtofh(fhp);	nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_SATTR(nfsd->nd_nqlflag != NQL_NOVAL));	if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))		nfsm_reply(0);	nqsrv_getl(vp, NQL_WRITE);	VATTR_NULL(vap);	/*	 * Nah nah nah nah na nah	 * There is a bug in the Sun client that puts 0xffff in the mode	 * field of sattr when it should put in 0xffffffff. The u_short	 * doesn't sign extend.	 * --> check the low order 2 bytes for 0xffff	 */	if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff)		vap->va_mode = nfstov_mode(sp->sa_mode);	if (sp->sa_uid != nfs_xdrneg1)		vap->va_uid = fxdr_unsigned(uid_t, sp->sa_uid);	if (sp->sa_gid != nfs_xdrneg1)		vap->va_gid = fxdr_unsigned(gid_t, sp->sa_gid);	if (nfsd->nd_nqlflag == NQL_NOVAL) {		if (sp->sa_nfssize != nfs_xdrneg1)			vap->va_size = fxdr_unsigned(u_quad_t, sp->sa_nfssize);		if (sp->sa_nfsatime.nfs_sec != nfs_xdrneg1) {#ifdef notyet			fxdr_nfstime(&sp->sa_nfsatime, &vap->va_atime);#else			vap->va_atime.ts_sec =				fxdr_unsigned(long, sp->sa_nfsatime.nfs_sec);			vap->va_atime.ts_nsec = 0;#endif		}		if (sp->sa_nfsmtime.nfs_sec != nfs_xdrneg1)			fxdr_nfstime(&sp->sa_nfsmtime, &vap->va_mtime);	} else {		fxdr_hyper(&sp->sa_nqsize, &vap->va_size);		fxdr_nqtime(&sp->sa_nqatime, &vap->va_atime);		fxdr_nqtime(&sp->sa_nqmtime, &vap->va_mtime);		vap->va_flags = fxdr_unsigned(u_long, sp->sa_nqflags);	}	/*	 * If the size is being changed write acces is required, otherwise	 * just check for a read only file system.	 */	if (vap->va_size == ((u_quad_t)((quad_t) -1))) {		if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {			error = EROFS;			goto out;		}	} else {		if (vp->v_type == VDIR) {			error = EISDIR;			goto out;		} else if (error = nfsrv_access(vp, VWRITE, cred, rdonly,			nfsd->nd_procp))			goto out;	}	if (error = VOP_SETATTR(vp, vap, cred, nfsd->nd_procp)) {		vput(vp);		nfsm_reply(0);	}	error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);out:	vput(vp);	nfsm_reply(NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL) + 2*NFSX_UNSIGNED);	nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));	nfsm_srvfillattr;	if (nfsd->nd_nqlflag != NQL_NOVAL) {		nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);		txdr_hyper(&frev2, tl);	}	nfsm_srvdone;}/* * nfs lookup rpc */nfsrv_lookup(nfsd, mrep, md, dpos, cred, nam, mrq)	struct nfsd *nfsd;	struct mbuf *mrep, *md;	caddr_t dpos;	struct ucred *cred;	struct mbuf *nam, **mrq;{	register struct nfsv2_fattr *fp;	struct nameidata nd;	struct vnode *vp;	nfsv2fh_t nfh;	fhandle_t *fhp;	register caddr_t cp;	register u_long *tl;	register long t1;	caddr_t bpos;	int error = 0, cache, duration2, cache2, len;	char *cp2;	struct mbuf *mb, *mb2, *mreq;	struct vattr va, *vap = &va;	u_quad_t frev, frev2;	fhp = &nfh.fh_generic;	duration2 = 0;	if (nfsd->nd_nqlflag != NQL_NOVAL) {		nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);		duration2 = fxdr_unsigned(int, *tl);	}	nfsm_srvmtofh(fhp);	nfsm_srvstrsiz(len, NFS_MAXNAMLEN);	nd.ni_cnd.cn_cred = cred;	nd.ni_cnd.cn_nameiop = LOOKUP;	nd.ni_cnd.cn_flags = LOCKLEAF | SAVESTART;	if (error = nfs_namei(&nd, fhp, len, nfsd->nd_slp, nam, &md, &dpos,	    nfsd->nd_procp))		nfsm_reply(0);	nqsrv_getl(nd.ni_startdir, NQL_READ);	vrele(nd.ni_startdir);	FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI);	vp = nd.ni_vp;	bzero((caddr_t)fhp, sizeof(nfh));	fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;	if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) {		vput(vp);		nfsm_reply(0);	}	if (duration2)		(void) nqsrv_getlease(vp, &duration2, NQL_READ, nfsd,			nam, &cache2, &frev2, cred);	error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);	vput(vp);	nfsm_reply(NFSX_FH + NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL) + 5*NFSX_UNSIGNED);	if (nfsd->nd_nqlflag != NQL_NOVAL) {		if (duration2) {			nfsm_build(tl, u_long *, 5*NFSX_UNSIGNED);			*tl++ = txdr_unsigned(NQL_READ);			*tl++ = txdr_unsigned(cache2);			*tl++ = txdr_unsigned(duration2);			txdr_hyper(&frev2, tl);		} else {			nfsm_build(tl, u_long *, NFSX_UNSIGNED);			*tl = 0;		}	}	nfsm_srvfhtom(fhp);	nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));	nfsm_srvfillattr;	nfsm_srvdone;}/* * nfs readlink service */nfsrv_readlink(nfsd, mrep, md, dpos, cred, nam, mrq)	struct nfsd *nfsd;	struct mbuf *mrep, *md;	caddr_t dpos;	struct ucred *cred;	struct mbuf *nam, **mrq;{	struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN];	register struct iovec *ivp = iv;	register struct mbuf *mp;	register u_long *tl;	register long t1;	caddr_t bpos;	int error = 0, rdonly, cache, i, tlen, len;	char *cp2;	struct mbuf *mb, *mb2, *mp2, *mp3, *mreq;	struct vnode *vp;	nfsv2fh_t nfh;	fhandle_t *fhp;	struct uio io, *uiop = &io;	u_quad_t frev;	fhp = &nfh.fh_generic;	nfsm_srvmtofh(fhp);	len = 0;	i = 0;	while (len < NFS_MAXPATHLEN) {		MGET(mp, M_WAIT, MT_DATA);		MCLGET(mp, M_WAIT);		mp->m_len = NFSMSIZ(mp);		if (len == 0)			mp3 = mp2 = mp;		else {			mp2->m_next = mp;			mp2 = mp;		}		if ((len+mp->m_len) > NFS_MAXPATHLEN) {			mp->m_len = NFS_MAXPATHLEN-len;			len = NFS_MAXPATHLEN;		} else			len += mp->m_len;		ivp->iov_base = mtod(mp, caddr_t);		ivp->iov_len = mp->m_len;		i++;		ivp++;	}	uiop->uio_iov = iv;	uiop->uio_iovcnt = i;	uiop->uio_offset = 0;	uiop->uio_resid = len;	uiop->uio_rw = UIO_READ;	uiop->uio_segflg = UIO_SYSSPACE;	uiop->uio_procp = (struct proc *)0;	if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly)) {		m_freem(mp3);		nfsm_reply(0);	}	if (vp->v_type != VLNK) {		error = EINVAL;		goto out;	}	nqsrv_getl(vp, NQL_READ);	error = VOP_READLINK(vp, uiop, cred);out:	vput(vp);	if (error)		m_freem(mp3);	nfsm_reply(NFSX_UNSIGNED);	if (uiop->uio_resid > 0) {		len -= uiop->uio_resid;		tlen = nfsm_rndup(len);		nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len);	}	nfsm_build(tl, u_long *, NFSX_UNSIGNED);	*tl = txdr_unsigned(len);	mb->m_next = mp3;	nfsm_srvdone;}/* * nfs read service */nfsrv_read(nfsd, mrep, md, dpos, cred, nam, mrq)	struct nfsd *nfsd;	struct mbuf *mrep, *md;	caddr_t dpos;	struct ucred *cred;	struct mbuf *nam, **mrq;{	register struct iovec *iv;	struct iovec *iv2;	register struct mbuf *m;	register struct nfsv2_fattr *fp;	register u_long *tl;	register long t1;	caddr_t bpos;	int error = 0, rdonly, cache, i, cnt, len, left, siz, tlen;	char *cp2;	struct mbuf *mb, *mb2, *mreq;	struct mbuf *m2;	struct vnode *vp;	nfsv2fh_t nfh;	fhandle_t *fhp;	struct uio io, *uiop = &io;	struct vattr va, *vap = &va;	off_t off;	u_quad_t frev;	fhp = &nfh.fh_generic;	nfsm_srvmtofh(fhp);	if (nfsd->nd_nqlflag == NQL_NOVAL) {		nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);		off = (off_t)fxdr_unsigned(u_long, *tl);	} else {		nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);		fxdr_hyper(tl, &off);	}	nfsm_srvstrsiz(cnt, NFS_MAXDATA);	if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))		nfsm_reply(0);	if (vp->v_type != VREG) {		error = (vp->v_type == VDIR) ? EISDIR : EACCES;		vput(vp);		nfsm_reply(0);	}	nqsrv_getl(vp, NQL_READ);	if ((error = nfsrv_access(vp, VREAD, cred, rdonly, nfsd->nd_procp)) &&	    (error = nfsrv_access(vp, VEXEC, cred, rdonly, nfsd->nd_procp))) {		vput(vp);		nfsm_reply(0);	}	if (error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp)) {		vput(vp);		nfsm_reply(0);	}	if (off >= vap->va_size)		cnt = 0;	else if ((off + cnt) > vap->va_size)		cnt = nfsm_rndup(vap->va_size - off);	nfsm_reply(NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL)+NFSX_UNSIGNED+nfsm_rndup(cnt));

⌨️ 快捷键说明

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