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

📄 nfs_serv.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
	nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));	nfsm_build(tl, u_long *, NFSX_UNSIGNED);	len = left = cnt;	if (cnt > 0) {		/*		 * Generate the mbuf list with the uio_iov ref. to it.		 */		i = 0;		m = m2 = mb;		MALLOC(iv, struct iovec *,		       ((NFS_MAXDATA+MLEN-1)/MLEN) * sizeof (struct iovec),		       M_TEMP, M_WAITOK);		iv2 = iv;		while (left > 0) {			siz = min(M_TRAILINGSPACE(m), left);			if (siz > 0) {				m->m_len += siz;				iv->iov_base = bpos;				iv->iov_len = siz;				iv++;				i++;				left -= siz;			}			if (left > 0) {				MGET(m, M_WAIT, MT_DATA);				MCLGET(m, M_WAIT);				m->m_len = 0;				m2->m_next = m;				m2 = m;				bpos = mtod(m, caddr_t);			}		}		uiop->uio_iov = iv2;		uiop->uio_iovcnt = i;		uiop->uio_offset = off;		uiop->uio_resid = cnt;		uiop->uio_rw = UIO_READ;		uiop->uio_segflg = UIO_SYSSPACE;		error = VOP_READ(vp, uiop, IO_NODELOCKED, cred);		off = uiop->uio_offset;		FREE((caddr_t)iv2, M_TEMP);		if (error || (error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp))) {			m_freem(mreq);			vput(vp);			nfsm_reply(0);		}	} else		uiop->uio_resid = 0;	vput(vp);	nfsm_srvfillattr;	len -= uiop->uio_resid;	tlen = nfsm_rndup(len);	if (cnt != tlen || tlen != len)		nfsm_adj(mb, cnt-tlen, tlen-len);	*tl = txdr_unsigned(len);	nfsm_srvdone;}/* * nfs write service */nfsrv_write(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 *ivp;	register struct mbuf *mp;	register struct nfsv2_fattr *fp;	struct iovec iv[NFS_MAXIOVEC];	struct vattr va;	register struct vattr *vap = &va;	register u_long *tl;	register long t1;	caddr_t bpos;	int error = 0, rdonly, cache, siz, len, xfer;	int ioflags = IO_SYNC | IO_NODELOCKED;	char *cp2;	struct mbuf *mb, *mb2, *mreq;	struct vnode *vp;	nfsv2fh_t nfh;	fhandle_t *fhp;	struct uio io, *uiop = &io;	off_t off;	u_quad_t frev;	fhp = &nfh.fh_generic;	nfsm_srvmtofh(fhp);	nfsm_dissect(tl, u_long *, 4 * NFSX_UNSIGNED);	if (nfsd->nd_nqlflag == NQL_NOVAL) {		off = (off_t)fxdr_unsigned(u_long, *++tl);		tl += 2;	} else {		fxdr_hyper(tl, &off);		tl += 2;		if (fxdr_unsigned(u_long, *tl++))			ioflags |= IO_APPEND;	}	len = fxdr_unsigned(long, *tl);	if (len > NFS_MAXDATA || len <= 0) {		error = EBADRPC;		nfsm_reply(0);	}	if (dpos == (mtod(md, caddr_t)+md->m_len)) {		mp = md->m_next;		if (mp == NULL) {			error = EBADRPC;			nfsm_reply(0);		}	} else {		mp = md;		siz = dpos-mtod(mp, caddr_t);		mp->m_len -= siz;		NFSMADV(mp, siz);	}	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_WRITE);	if (error = nfsrv_access(vp, VWRITE, cred, rdonly, nfsd->nd_procp)) {		vput(vp);		nfsm_reply(0);	}	uiop->uio_resid = 0;	uiop->uio_rw = UIO_WRITE;	uiop->uio_segflg = UIO_SYSSPACE;	uiop->uio_procp = (struct proc *)0;	/*	 * Do up to NFS_MAXIOVEC mbufs of write each iteration of the	 * loop until done.	 */	while (len > 0 && uiop->uio_resid == 0) {		ivp = iv;		siz = 0;		uiop->uio_iov = ivp;		uiop->uio_iovcnt = 0;		uiop->uio_offset = off;		while (len > 0 && uiop->uio_iovcnt < NFS_MAXIOVEC && mp != NULL) {			ivp->iov_base = mtod(mp, caddr_t);			if (len < mp->m_len)				ivp->iov_len = xfer = len;			else				ivp->iov_len = xfer = mp->m_len;#ifdef notdef			/* Not Yet .. */			if (M_HASCL(mp) && (((u_long)ivp->iov_base) & CLOFSET) == 0)				ivp->iov_op = NULL;	/* what should it be ?? */			else				ivp->iov_op = NULL;#endif			uiop->uio_iovcnt++;			ivp++;			len -= xfer;			siz += xfer;			mp = mp->m_next;		}		if (len > 0 && mp == NULL) {			error = EBADRPC;			vput(vp);			nfsm_reply(0);		}		uiop->uio_resid = siz;		if (error = VOP_WRITE(vp, uiop, ioflags, cred)) {			vput(vp);			nfsm_reply(0);		}		off = uiop->uio_offset;	}	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;	if (nfsd->nd_nqlflag != NQL_NOVAL) {		nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);		txdr_hyper(&vap->va_filerev, tl);	}	nfsm_srvdone;}/* * nfs create service * now does a truncate to 0 length via. setattr if it already exists */nfsrv_create(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;	register struct nfsv2_sattr *sp;	register u_long *tl;	struct nameidata nd;	register caddr_t cp;	register long t1;	caddr_t bpos;	int error = 0, rdev, cache, len, tsize;	char *cp2;	struct mbuf *mb, *mb2, *mreq;	struct vnode *vp;	nfsv2fh_t nfh;	fhandle_t *fhp;	u_quad_t frev;	nd.ni_cnd.cn_nameiop = 0;	fhp = &nfh.fh_generic;	nfsm_srvmtofh(fhp);	nfsm_srvstrsiz(len, NFS_MAXNAMLEN);	nd.ni_cnd.cn_cred = cred;	nd.ni_cnd.cn_nameiop = CREATE;	nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART;	if (error = nfs_namei(&nd, fhp, len, nfsd->nd_slp, nam, &md, &dpos,	    nfsd->nd_procp))		nfsm_reply(0);	VATTR_NULL(vap);	nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_SATTR(nfsd->nd_nqlflag != NQL_NOVAL));	/*	 * Iff doesn't exist, create it	 * otherwise just truncate to 0 length	 *   should I set the mode too ??	 */	if (nd.ni_vp == NULL) {		vap->va_type = IFTOVT(fxdr_unsigned(u_long, sp->sa_mode));		if (vap->va_type == VNON)			vap->va_type = VREG;		vap->va_mode = nfstov_mode(sp->sa_mode);		if (nfsd->nd_nqlflag == NQL_NOVAL)			rdev = fxdr_unsigned(long, sp->sa_nfssize);		else			rdev = fxdr_unsigned(long, sp->sa_nqrdev);		if (vap->va_type == VREG || vap->va_type == VSOCK) {			vrele(nd.ni_startdir);			nqsrv_getl(nd.ni_dvp, NQL_WRITE);			if (error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap))				nfsm_reply(0);			FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI);		} else if (vap->va_type == VCHR || vap->va_type == VBLK ||			vap->va_type == VFIFO) {			if (vap->va_type == VCHR && rdev == 0xffffffff)				vap->va_type = VFIFO;			if (vap->va_type == VFIFO) {#ifndef FIFO				VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);				vput(nd.ni_dvp);				error = ENXIO;				goto out;#endif /* FIFO */			} else if (error = suser(cred, (u_short *)0)) {				VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);				vput(nd.ni_dvp);				goto out;			} else				vap->va_rdev = (dev_t)rdev;			nqsrv_getl(nd.ni_dvp, NQL_WRITE);			if (error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap)) {				vrele(nd.ni_startdir);				nfsm_reply(0);			}			nd.ni_cnd.cn_nameiop = LOOKUP;			nd.ni_cnd.cn_flags &= ~(LOCKPARENT | SAVESTART);			nd.ni_cnd.cn_proc = nfsd->nd_procp;			nd.ni_cnd.cn_cred = nfsd->nd_procp->p_ucred;			if (error = lookup(&nd)) {				free(nd.ni_cnd.cn_pnbuf, M_NAMEI);				nfsm_reply(0);			}			FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI);			if (nd.ni_cnd.cn_flags & ISSYMLINK) {				vrele(nd.ni_dvp);				vput(nd.ni_vp);				VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);				error = EINVAL;				nfsm_reply(0);			}		} else {			VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);			vput(nd.ni_dvp);			error = ENXIO;			goto out;		}		vp = nd.ni_vp;	} else {		vrele(nd.ni_startdir);		free(nd.ni_cnd.cn_pnbuf, M_NAMEI);		vp = nd.ni_vp;		if (nd.ni_dvp == vp)			vrele(nd.ni_dvp);		else			vput(nd.ni_dvp);		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);		if (nfsd->nd_nqlflag == NQL_NOVAL) {			tsize = fxdr_unsigned(long, sp->sa_nfssize);			if (tsize != -1)				vap->va_size = (u_quad_t)tsize;			else				vap->va_size = -1;		} else			fxdr_hyper(&sp->sa_nqsize, &vap->va_size);		if (vap->va_size != -1) {			if (error = nfsrv_access(vp, VWRITE, cred,			    (nd.ni_cnd.cn_flags & RDONLY), nfsd->nd_procp)) {				vput(vp);				nfsm_reply(0);			}			nqsrv_getl(vp, NQL_WRITE);			if (error = VOP_SETATTR(vp, vap, cred, nfsd->nd_procp)) {				vput(vp);				nfsm_reply(0);			}		}	}	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);	}	error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);	vput(vp);	nfsm_reply(NFSX_FH+NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));	nfsm_srvfhtom(fhp);	nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));	nfsm_srvfillattr;	return (error);nfsmout:	if (nd.ni_cnd.cn_nameiop || nd.ni_cnd.cn_flags)		vrele(nd.ni_startdir);	VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);	if (nd.ni_dvp == nd.ni_vp)		vrele(nd.ni_dvp);	else		vput(nd.ni_dvp);	if (nd.ni_vp)		vput(nd.ni_vp);	return (error);out:	vrele(nd.ni_startdir);	free(nd.ni_cnd.cn_pnbuf, M_NAMEI);	nfsm_reply(0);}/* * nfs remove service */nfsrv_remove(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 nameidata nd;	register u_long *tl;	register long t1;	caddr_t bpos;	int error = 0, cache, len;	char *cp2;	struct mbuf *mb, *mreq;	struct vnode *vp;	nfsv2fh_t nfh;	fhandle_t *fhp;	u_quad_t frev;	fhp = &nfh.fh_generic;	nfsm_srvmtofh(fhp);	nfsm_srvstrsiz(len, NFS_MAXNAMLEN);	nd.ni_cnd.cn_cred = cred;	nd.ni_cnd.cn_nameiop = DELETE;	nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;	if (error = nfs_namei(&nd, fhp, len, nfsd->nd_slp, nam, &md, &dpos,	    nfsd->nd_procp))		nfsm_reply(0);	vp = nd.ni_vp;	if (vp->v_type == VDIR &&		(error = suser(cred, (u_short *)0)))		goto out;	/*	 * The root of a mounted filesystem cannot be deleted.	 */	if (vp->v_flag & VROOT) {		error = EBUSY;		goto out;	}	if (vp->v_flag & VTEXT)		(void) vnode_pager_uncache(vp);out:	if (!error) {		nqsrv_getl(nd.ni_dvp, NQL_WRITE);		nqsrv_getl(vp, NQL_WRITE);		error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);	} else {		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);		if (nd.ni_dvp == vp)			vrele(nd.ni_dvp);		else			vput(nd.ni_dvp);		vput(vp);	}	nfsm_reply(0);	nfsm_srvdone;}/* * nfs rename service */nfsrv_rename(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 u_long *tl;	register long t1;	caddr_t bpos;	int error = 0, cache, len, len2;	char *cp2;	struct mbuf *mb, *mreq;	struct nameidata fromnd, tond;	struct vnode *fvp, *tvp, *tdvp;	nfsv2fh_t fnfh, tnfh;	fhandle_t *ffhp, *tfhp;	u_quad_t frev;	uid_t saved_uid;	ffhp = &fnfh.fh_generic;	tfhp = &tnfh.fh_generic;	fromnd.ni_cnd.cn_nameiop = 0;	tond.ni_cnd.cn_nameiop = 0;	nfsm_srvmtofh(ffhp);	nfsm_srvstrsiz(len, NFS_MAXNAMLEN);	/*	 * Remember our original uid so that we can reset cr_uid before	 * the second nfs_namei() call, in case it is remapped.	 */	saved_uid = cred->cr_uid;	fromnd.ni_cnd.cn_cred = cred;	fromnd.ni_cnd.cn_nameiop = DELETE;	fromnd.ni_cnd.cn_flags = WANTPARENT | SAVESTART;	if (error = nfs_namei(&fromnd, ffhp, len, nfsd->nd_slp, nam, &md,	    &dpos, nfsd->nd_procp))		nfsm_reply(0);	fvp = fromnd.ni_vp;	nfsm_srvmtofh(tfhp);	nfsm_strsiz(len2, NFS_MAXNAMLEN);	cred->cr_uid = saved_uid;	tond.ni_cnd.cn_cred = cred;	tond.ni_cnd.cn_nameiop = RENAME;	tond.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART;	if (error = nfs_namei(&tond, tfhp, len2, nfsd->nd_slp, nam, &md,	    &dpos, nfsd->nd_procp)) {		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);		vrele(fromnd.ni_dvp);		vrele(fvp);		goto out1;	}	tdvp = tond.ni_dvp;	tvp = tond.ni_vp;	if (tvp != NULL) {		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {			error = EISDIR;			goto out;		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {			error = ENOTDIR;			goto out;		}		if (tvp->v_type == VDIR && tvp->v_mountedhere) {

⌨️ 快捷键说明

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