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

📄 nfs_serv.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
			error = EXDEV;			goto out;		}	}	if (fvp->v_type == VDIR && fvp->v_mountedhere) {		error = EBUSY;		goto out;	}	if (fvp->v_mount != tdvp->v_mount) {		error = EXDEV;		goto out;	}	if (fvp == tdvp)		error = EINVAL;	/*	 * If source is the same as the destination (that is the	 * same vnode with the same name in the same directory),	 * then there is nothing to do.	 */	if (fvp == tvp && fromnd.ni_dvp == tdvp &&	    fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&	    !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,	      fromnd.ni_cnd.cn_namelen))		error = -1;out:	if (!error) {		nqsrv_getl(fromnd.ni_dvp, NQL_WRITE);		nqsrv_getl(tdvp, NQL_WRITE);		if (tvp)			nqsrv_getl(tvp, NQL_WRITE);		error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,				   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);	} else {		VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);		if (tdvp == tvp)			vrele(tdvp);		else			vput(tdvp);		if (tvp)			vput(tvp);		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);		vrele(fromnd.ni_dvp);		vrele(fvp);	}	vrele(tond.ni_startdir);	FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);out1:	vrele(fromnd.ni_startdir);	FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);	nfsm_reply(0);	return (error);nfsmout:	if (tond.ni_cnd.cn_nameiop || tond.ni_cnd.cn_flags) {		vrele(tond.ni_startdir);		FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);	}	if (fromnd.ni_cnd.cn_nameiop || fromnd.ni_cnd.cn_flags) {		vrele(fromnd.ni_startdir);		FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);		vrele(fromnd.ni_dvp);		vrele(fvp);	}	return (error);}/* * nfs link service */nfsrv_link(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, rdonly, cache, len;	char *cp2;	struct mbuf *mb, *mreq;	struct vnode *vp, *xp;	nfsv2fh_t nfh, dnfh;	fhandle_t *fhp, *dfhp;	u_quad_t frev;	fhp = &nfh.fh_generic;	dfhp = &dnfh.fh_generic;	nfsm_srvmtofh(fhp);	nfsm_srvmtofh(dfhp);	nfsm_srvstrsiz(len, NFS_MAXNAMLEN);	if (error = nfsrv_fhtovp(fhp, FALSE, &vp, cred, nfsd->nd_slp, nam, &rdonly))		nfsm_reply(0);	if (vp->v_type == VDIR && (error = suser(cred, (u_short *)0)))		goto out1;	nd.ni_cnd.cn_cred = cred;	nd.ni_cnd.cn_nameiop = CREATE;	nd.ni_cnd.cn_flags = LOCKPARENT;	if (error = nfs_namei(&nd, dfhp, len, nfsd->nd_slp, nam, &md, &dpos,	    nfsd->nd_procp))		goto out1;	xp = nd.ni_vp;	if (xp != NULL) {		error = EEXIST;		goto out;	}	xp = nd.ni_dvp;	if (vp->v_mount != xp->v_mount)		error = EXDEV;out:	if (!error) {		nqsrv_getl(vp, NQL_WRITE);		nqsrv_getl(xp, NQL_WRITE);		error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);	} else {		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)			vrele(nd.ni_vp);	}out1:	vrele(vp);	nfsm_reply(0);	nfsm_srvdone;}/* * nfs symbolic link service */nfsrv_symlink(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;	struct nameidata nd;	register struct vattr *vap = &va;	register u_long *tl;	register long t1;	struct nfsv2_sattr *sp;	caddr_t bpos;	struct uio io;	struct iovec iv;	int error = 0, cache, len, len2;	char *pathcp, *cp2;	struct mbuf *mb, *mreq;	nfsv2fh_t nfh;	fhandle_t *fhp;	u_quad_t frev;	pathcp = (char *)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;	if (error = nfs_namei(&nd, fhp, len, nfsd->nd_slp, nam, &md, &dpos,	    nfsd->nd_procp))		goto out;	nfsm_strsiz(len2, NFS_MAXPATHLEN);	MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK);	iv.iov_base = pathcp;	iv.iov_len = len2;	io.uio_resid = len2;	io.uio_offset = 0;	io.uio_iov = &iv;	io.uio_iovcnt = 1;	io.uio_segflg = UIO_SYSSPACE;	io.uio_rw = UIO_READ;	io.uio_procp = (struct proc *)0;	nfsm_mtouio(&io, len2);	nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_SATTR(nfsd->nd_nqlflag != NQL_NOVAL));	*(pathcp + len2) = '\0';	if (nd.ni_vp) {		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);		if (nd.ni_dvp == nd.ni_vp)			vrele(nd.ni_dvp);		else			vput(nd.ni_dvp);		vrele(nd.ni_vp);		error = EEXIST;		goto out;	}	VATTR_NULL(vap);	vap->va_mode = fxdr_unsigned(u_short, sp->sa_mode);	nqsrv_getl(nd.ni_dvp, NQL_WRITE);	error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap, pathcp);out:	if (pathcp)		FREE(pathcp, M_TEMP);	nfsm_reply(0);	return (error);nfsmout:	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)		vrele(nd.ni_vp);	if (pathcp)		FREE(pathcp, M_TEMP);	return (error);}/* * nfs mkdir service */nfsrv_mkdir(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_fattr *fp;	struct nameidata nd;	register caddr_t cp;	register u_long *tl;	register long t1;	caddr_t bpos;	int error = 0, cache, len;	char *cp2;	struct mbuf *mb, *mb2, *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 = CREATE;	nd.ni_cnd.cn_flags = LOCKPARENT;	if (error = nfs_namei(&nd, fhp, len, nfsd->nd_slp, nam, &md, &dpos,	    nfsd->nd_procp))		nfsm_reply(0);	nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);	VATTR_NULL(vap);	vap->va_type = VDIR;	vap->va_mode = nfstov_mode(*tl++);	vp = nd.ni_vp;	if (vp != NULL) {		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);		if (nd.ni_dvp == vp)			vrele(nd.ni_dvp);		else			vput(nd.ni_dvp);		vrele(vp);		error = EEXIST;		nfsm_reply(0);	}	nqsrv_getl(nd.ni_dvp, NQL_WRITE);	if (error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap))		nfsm_reply(0);	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);	}	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:	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)		vrele(nd.ni_vp);	return (error);}/* * nfs rmdir service */nfsrv_rmdir(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;	char *cp2;	struct mbuf *mb, *mreq;	struct vnode *vp;	nfsv2fh_t nfh;	fhandle_t *fhp;	struct nameidata nd;	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 = ENOTDIR;		goto out;	}	/*	 * No rmdir "." please.	 */	if (nd.ni_dvp == vp) {		error = EINVAL;		goto out;	}	/*	 * The root of a mounted filesystem cannot be deleted.	 */	if (vp->v_flag & VROOT)		error = EBUSY;out:	if (!error) {		nqsrv_getl(nd.ni_dvp, NQL_WRITE);		nqsrv_getl(vp, NQL_WRITE);		error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);	} else {		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);		if (nd.ni_dvp == nd.ni_vp)			vrele(nd.ni_dvp);		else			vput(nd.ni_dvp);		vput(vp);	}	nfsm_reply(0);	nfsm_srvdone;}/* * nfs readdir service * - mallocs what it thinks is enough to read *	count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR * - calls VOP_READDIR() * - loops around building the reply *	if the output generated exceeds count break out of loop *	The nfsm_clget macro is used here so that the reply will be packed *	tightly in mbuf clusters. * - it only knows that it has encountered eof when the VOP_READDIR() *	reads nothing * - as such one readdir rpc will return eof false although you are there *	and then the next will return eof * - it trims out records with d_fileno == 0 *	this doesn't matter for Unix clients, but they might confuse clients *	for other os'. * NB: It is tempting to set eof to true if the VOP_READDIR() reads less *	than requested, but this may not apply to all filesystems. For *	example, client NFS does not { although it is never remote mounted *	anyhow } *     The alternate call nqnfsrv_readdirlook() does lookups as well. * PS: The NFS protocol spec. does not clarify what the "count" byte *	argument is a count of.. just name strings and file id's or the *	entire reply rpc or ... *	I tried just file name and id sizes and it confused the Sun client, *	so I am using the full rpc size now. The "paranoia.." comment refers *	to including the status longwords that are not a part of the dir. *	"entry" structures, but are in the rpc. */struct flrep {	u_long fl_cachable;	u_long fl_duration;	u_long fl_frev[2];	nfsv2fh_t fl_nfh;	u_long fl_fattr[NFSX_NQFATTR / sizeof (u_long)];};nfsrv_readdir(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 char *bp, *be;	register struct mbuf *mp;	register struct dirent *dp;	register caddr_t cp;	register u_long *tl;	register long t1;	caddr_t bpos;	struct mbuf *mb, *mb2, *mreq, *mp2;	char *cpos, *cend, *cp2, *rbuf;	struct vnode *vp;	nfsv2fh_t nfh;	fhandle_t *fhp;	struct uio io;	struct iovec iv;	int len, nlen, rem, xfer, tsiz, i, error = 0;	int siz, cnt, fullsiz, eofflag, rdonly, cache;	u_quad_t frev;	u_long on, off, toff;	fhp = &nfh.fh_generic;	nfsm_srvmtofh(fhp);	nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED);	toff = fxdr_unsigned(u_long, *tl++);	off = (toff & ~(NFS_DIRBLKSIZ-1));	on = (toff & (NFS_DIRBLKSIZ-1));	cnt = fxdr_unsigned(int, *tl);	siz = ((cnt+NFS_DIRBLKSIZ-1) & ~(NFS_DIRBLKSIZ-1));	if (cnt > NFS_MAXREADDIR)		siz = NFS_MAXREADDIR;	fullsiz = siz;	if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))		nfsm_reply(0);	nqsrv_getl(vp, NQL_READ);	if (error = nfsrv_access(vp, VEXEC, cred, rdonly, nfsd->nd_procp)) {		vput(vp);		nfsm_reply(0);	}	VOP_UNLOCK(vp);	MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);again:	iv.iov_base = rbuf;	iv.iov_len = fullsiz;	io.uio_iov = &iv;	io.uio_iovcnt = 1;	io.uio_offset = (off_t)off;	io.uio_resid = fullsiz;	io.uio_segflg = UIO_SYSSPACE;	io.uio_rw = UIO_READ;	io.uio_procp = (struct proc *)0;	error = VOP_READDIR(vp, &io, cred);	off = (off_t)io.uio_offset;	if (error) {		vrele(vp);		free((caddr_t)rbuf, M_TEMP);		nfsm_reply(0);	}	if (io.uio_resid < fullsiz)		eofflag = 0;	else		eofflag = 1;	if (io.uio_resid) {		siz -= io.uio_resid;		/*		 * If nothing read, return eof		 * rpc reply		 */		if (siz == 0) {			vrele(vp);			nfsm_reply(2*NFSX_UNSIGNED);			nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);			*tl++ = nfs_false;			*tl = nfs_true;			FREE((caddr_t)rbuf, M_TEMP);			return (0);		}	}

⌨️ 快捷键说明

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