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

📄 nfs_vnops.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
			(error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,			 ap->a_p, 1)) == EINTR)			return (error);	}	nfsstats.rpccnt[NFSPROC_SETATTR]++;	isnq = (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS);	nfsm_reqhead(vp, NFSPROC_SETATTR, NFSX_FH+NFSX_SATTR(isnq));	nfsm_fhtom(vp);	nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR(isnq));	if (vap->va_mode == (u_short)-1)		sp->sa_mode = VNOVAL;	else		sp->sa_mode = vtonfs_mode(vp->v_type, vap->va_mode);	if (vap->va_uid == (uid_t)-1)		sp->sa_uid = VNOVAL;	else		sp->sa_uid = txdr_unsigned(vap->va_uid);	if (vap->va_gid == (gid_t)-1)		sp->sa_gid = VNOVAL;	else		sp->sa_gid = txdr_unsigned(vap->va_gid);	if (isnq) {		txdr_hyper(&vap->va_size, &sp->sa_nqsize);		txdr_nqtime(&vap->va_atime, &sp->sa_nqatime);		txdr_nqtime(&vap->va_mtime, &sp->sa_nqmtime);		sp->sa_nqflags = txdr_unsigned(vap->va_flags);		sp->sa_nqrdev = VNOVAL;	} else {		sp->sa_nfssize = txdr_unsigned(vap->va_size);		txdr_nfstime(&vap->va_atime, &sp->sa_nfsatime);		txdr_nfstime(&vap->va_mtime, &sp->sa_nfsmtime);	}	nfsm_request(vp, NFSPROC_SETATTR, ap->a_p, ap->a_cred);	nfsm_loadattr(vp, (struct vattr *)0);	if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) &&	    NQNFS_CKCACHABLE(vp, NQL_WRITE)) {		nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED);		fxdr_hyper(tl, &frev);		if (frev > np->n_brev)			np->n_brev = frev;	}	nfsm_reqdone;	if (error) {		np->n_size = np->n_vattr.va_size = tsize;		vnode_pager_setsize(vp, (u_long)np->n_size);	}	return (error);}/* * nfs lookup call, one step at a time... * First look in cache * If not found, unlock the directory nfsnode and do the rpc */intnfs_lookup(ap)	struct vop_lookup_args /* {		struct vnodeop_desc *a_desc;		struct vnode *a_dvp;		struct vnode **a_vpp;		struct componentname *a_cnp;	} */ *ap;{	register struct componentname *cnp = ap->a_cnp;	register struct vnode *dvp = ap->a_dvp;	register struct vnode **vpp = ap->a_vpp;	register int flags = cnp->cn_flags;	register struct vnode *vdp;	register u_long *tl;	register caddr_t cp;	register long t1, t2;	struct nfsmount *nmp;	caddr_t bpos, dpos, cp2;	time_t reqtime;	struct mbuf *mreq, *mrep, *md, *mb, *mb2;	struct vnode *newvp;	long len;	nfsv2fh_t *fhp;	struct nfsnode *np;	int lockparent, wantparent, error = 0;	int nqlflag, cachable;	u_quad_t frev;	*vpp = NULL;	if (dvp->v_type != VDIR)		return (ENOTDIR);	lockparent = flags & LOCKPARENT;	wantparent = flags & (LOCKPARENT|WANTPARENT);	nmp = VFSTONFS(dvp->v_mount);	np = VTONFS(dvp);	if ((error = cache_lookup(dvp, vpp, cnp)) && error != ENOENT) {		struct vattr vattr;		int vpid;		vdp = *vpp;		vpid = vdp->v_id;		/*		 * See the comment starting `Step through' in ufs/ufs_lookup.c		 * for an explanation of the locking protocol		 */		if (dvp == vdp) {			VREF(vdp);			error = 0;		} else			error = vget(vdp, 1);		if (!error) {			if (vpid == vdp->v_id) {			   if (nmp->nm_flag & NFSMNT_NQNFS) {				if ((nmp->nm_flag & NFSMNT_NQLOOKLEASE) == 0) {					nfsstats.lookupcache_hits++;					if (cnp->cn_nameiop != LOOKUP &&					    (flags & ISLASTCN))					    cnp->cn_flags |= SAVENAME;					return (0);			        } else if (NQNFS_CKCACHABLE(dvp, NQL_READ)) {					if (np->n_lrev != np->n_brev ||					    (np->n_flag & NMODIFIED)) {						np->n_direofoffset = 0;						cache_purge(dvp);						error = nfs_vinvalbuf(dvp, 0,						    cnp->cn_cred, cnp->cn_proc,						    1);						if (error == EINTR)							return (error);						np->n_brev = np->n_lrev;					} else {						nfsstats.lookupcache_hits++;						if (cnp->cn_nameiop != LOOKUP &&						    (flags & ISLASTCN))						    cnp->cn_flags |= SAVENAME;						return (0);					}				}			   } else if (!VOP_GETATTR(vdp, &vattr, cnp->cn_cred, cnp->cn_proc) &&			       vattr.va_ctime.ts_sec == VTONFS(vdp)->n_ctime) {				nfsstats.lookupcache_hits++;				if (cnp->cn_nameiop != LOOKUP &&				    (flags & ISLASTCN))					cnp->cn_flags |= SAVENAME;				return (0);			   }			   cache_purge(vdp);			}			vrele(vdp);		}		*vpp = NULLVP;	}	error = 0;	nfsstats.lookupcache_misses++;	nfsstats.rpccnt[NFSPROC_LOOKUP]++;	len = cnp->cn_namelen;	nfsm_reqhead(dvp, NFSPROC_LOOKUP, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len));	/*	 * For nqnfs optionally piggyback a getlease request for the name	 * being looked up.	 */	if (nmp->nm_flag & NFSMNT_NQNFS) {		nfsm_build(tl, u_long *, NFSX_UNSIGNED);		if ((nmp->nm_flag & NFSMNT_NQLOOKLEASE) &&		    ((cnp->cn_flags & MAKEENTRY) &&		    (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))))			*tl = txdr_unsigned(nmp->nm_leaseterm);		else			*tl = 0;	}	nfsm_fhtom(dvp);	nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);	reqtime = time.tv_sec;	nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred);nfsmout:	if (error) {		if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) &&		    (flags & ISLASTCN) && error == ENOENT)			error = EJUSTRETURN;		if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))			cnp->cn_flags |= SAVENAME;		return (error);	}	if (nmp->nm_flag & NFSMNT_NQNFS) {		nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);		if (*tl) {			nqlflag = fxdr_unsigned(int, *tl);			nfsm_dissect(tl, u_long *, 4*NFSX_UNSIGNED);			cachable = fxdr_unsigned(int, *tl++);			reqtime += fxdr_unsigned(int, *tl++);			fxdr_hyper(tl, &frev);		} else			nqlflag = 0;	}	nfsm_dissect(fhp, nfsv2fh_t *, NFSX_FH);	/*	 * Handle RENAME case...	 */	if (cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) {		if (!bcmp(np->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) {			m_freem(mrep);			return (EISDIR);		}		if (error = nfs_nget(dvp->v_mount, fhp, &np)) {			m_freem(mrep);			return (error);		}		newvp = NFSTOV(np);		if (error =		    nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) {			vrele(newvp);			m_freem(mrep);			return (error);		}		*vpp = newvp;		m_freem(mrep);		cnp->cn_flags |= SAVENAME;		return (0);	}	if (!bcmp(np->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) {		VREF(dvp);		newvp = dvp;	} else {		if (error = nfs_nget(dvp->v_mount, fhp, &np)) {			m_freem(mrep);			return (error);		}		newvp = NFSTOV(np);	}	if (error = nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) {		vrele(newvp);		m_freem(mrep);		return (error);	}	m_freem(mrep);	*vpp = newvp;	if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))		cnp->cn_flags |= SAVENAME;	if ((cnp->cn_flags & MAKEENTRY) &&	    (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) {		if ((nmp->nm_flag & NFSMNT_NQNFS) == 0)			np->n_ctime = np->n_vattr.va_ctime.ts_sec;		else if (nqlflag && reqtime > time.tv_sec)			nqnfs_clientlease(nmp, np, nqlflag, cachable, reqtime,				frev);		cache_enter(dvp, *vpp, cnp);	}	return (0);}/* * nfs read call. * Just call nfs_bioread() to do the work. */intnfs_read(ap)	struct vop_read_args /* {		struct vnode *a_vp;		struct uio *a_uio;		int  a_ioflag;		struct ucred *a_cred;	} */ *ap;{	register struct vnode *vp = ap->a_vp;	if (vp->v_type != VREG)		return (EPERM);	return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred));}/* * nfs readlink call */intnfs_readlink(ap)	struct vop_readlink_args /* {		struct vnode *a_vp;		struct uio *a_uio;		struct ucred *a_cred;	} */ *ap;{	register struct vnode *vp = ap->a_vp;	if (vp->v_type != VLNK)		return (EPERM);	return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred));}/* * Do a readlink rpc. * Called by nfs_doio() from below the buffer cache. */intnfs_readlinkrpc(vp, uiop, cred)	register struct vnode *vp;	struct uio *uiop;	struct ucred *cred;{	register u_long *tl;	register caddr_t cp;	register long t1;	caddr_t bpos, dpos, cp2;	int error = 0;	struct mbuf *mreq, *mrep, *md, *mb, *mb2;	long len;	nfsstats.rpccnt[NFSPROC_READLINK]++;	nfsm_reqhead(vp, NFSPROC_READLINK, NFSX_FH);	nfsm_fhtom(vp);	nfsm_request(vp, NFSPROC_READLINK, uiop->uio_procp, cred);	nfsm_strsiz(len, NFS_MAXPATHLEN);	nfsm_mtouio(uiop, len);	nfsm_reqdone;	return (error);}/* * nfs read rpc call * Ditto above */intnfs_readrpc(vp, uiop, cred)	register struct vnode *vp;	struct uio *uiop;	struct ucred *cred;{	register u_long *tl;	register caddr_t cp;	register long t1;	caddr_t bpos, dpos, cp2;	int error = 0;	struct mbuf *mreq, *mrep, *md, *mb, *mb2;	struct nfsmount *nmp;	long len, retlen, tsiz;	nmp = VFSTONFS(vp->v_mount);	tsiz = uiop->uio_resid;	if (uiop->uio_offset + tsiz > 0xffffffff &&	    (nmp->nm_flag & NFSMNT_NQNFS) == 0)		return (EFBIG);	while (tsiz > 0) {		nfsstats.rpccnt[NFSPROC_READ]++;		len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;		nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH+NFSX_UNSIGNED*3);		nfsm_fhtom(vp);		nfsm_build(tl, u_long *, NFSX_UNSIGNED*3);		if (nmp->nm_flag & NFSMNT_NQNFS) {			txdr_hyper(&uiop->uio_offset, tl);			*(tl + 2) = txdr_unsigned(len);		} else {			*tl++ = txdr_unsigned(uiop->uio_offset);			*tl++ = txdr_unsigned(len);			*tl = 0;		}		nfsm_request(vp, NFSPROC_READ, uiop->uio_procp, cred);		nfsm_loadattr(vp, (struct vattr *)0);		nfsm_strsiz(retlen, nmp->nm_rsize);		nfsm_mtouio(uiop, retlen);		m_freem(mrep);		if (retlen < len)			tsiz = 0;		else			tsiz -= len;	}nfsmout:	return (error);}/* * nfs write call */intnfs_writerpc(vp, uiop, cred, ioflags)	register struct vnode *vp;	struct uio *uiop;	struct ucred *cred;	int ioflags;{	register u_long *tl;	register caddr_t cp;	register long t1;	caddr_t bpos, dpos, cp2;	int error = 0;	struct mbuf *mreq, *mrep, *md, *mb, *mb2;	struct nfsmount *nmp;	struct nfsnode *np = VTONFS(vp);	u_quad_t frev;	long len, tsiz;	nmp = VFSTONFS(vp->v_mount);	tsiz = uiop->uio_resid;	if (uiop->uio_offset + tsiz > 0xffffffff &&	    (nmp->nm_flag & NFSMNT_NQNFS) == 0)		return (EFBIG);	while (tsiz > 0) {		nfsstats.rpccnt[NFSPROC_WRITE]++;		len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz;		nfsm_reqhead(vp, NFSPROC_WRITE,			NFSX_FH+NFSX_UNSIGNED*4+nfsm_rndup(len));		nfsm_fhtom(vp);		nfsm_build(tl, u_long *, NFSX_UNSIGNED * 4);		if (nmp->nm_flag & NFSMNT_NQNFS) {			txdr_hyper(&uiop->uio_offset, tl);			tl += 2;			if (ioflags & IO_APPEND)				*tl++ = txdr_unsigned(1);			else				*tl++ = 0;		} else {			*++tl = txdr_unsigned(uiop->uio_offset);			tl += 2;		}		*tl = txdr_unsigned(len);		nfsm_uiotom(uiop, len);		nfsm_request(vp, NFSPROC_WRITE, uiop->uio_procp, cred);		nfsm_loadattr(vp, (struct vattr *)0);		if (nmp->nm_flag & NFSMNT_MYWRITE)			VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime.ts_sec;		else if ((nmp->nm_flag & NFSMNT_NQNFS) &&			 NQNFS_CKCACHABLE(vp, NQL_WRITE)) {			nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED);			fxdr_hyper(tl, &frev);			if (frev > np->n_brev)				np->n_brev = frev;		}		m_freem(mrep);		tsiz -= len;	}nfsmout:	if (error)		uiop->uio_resid = tsiz;	return (error);}/* * nfs mknod call * This is a kludge. Use a create rpc but with the IFMT bits of the mode * set to specify the file type and the size field for rdev. *//* ARGSUSED */intnfs_mknod(ap)	struct vop_mknod_args /* {		struct vnode *a_dvp;		struct vnode **a_vpp;		struct componentname *a_cnp;		struct vattr *a_vap;	} */ *ap;{	register struct vnode *dvp = ap->a_dvp;	register struct vattr *vap = ap->a_vap;	register struct componentname *cnp = ap->a_cnp;	register struct nfsv2_sattr *sp;	register u_long *tl;	register caddr_t cp;	register long t1, t2;	struct vnode *newvp;	struct vattr vattr;	char *cp2;	caddr_t bpos, dpos;	int error = 0, isnq;	struct mbuf *mreq, *mrep, *md, *mb, *mb2;	u_long rdev;	isnq = (VFSTONFS(dvp->v_mount)->nm_flag & NFSMNT_NQNFS);	if (vap->va_type == VCHR || vap->va_type == VBLK)		rdev = txdr_unsigned(vap->va_rdev);#ifdef FIFO	else if (vap->va_type == VFIFO)		rdev = 0xffffffff;#endif /* FIFO */	else {		VOP_ABORTOP(dvp, cnp);		vput(dvp);		return (EOPNOTSUPP);	}	if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) {		VOP_ABORTOP(dvp, cnp);		vput(dvp);		return (error);	}	nfsstats.rpccnt[NFSPROC_CREATE]++;	nfsm_reqhead(dvp, NFSPROC_CREATE,	  NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)+NFSX_SATTR(isnq));	nfsm_fhtom(dvp);	nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);	nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR(isnq));	sp->sa_mode = vtonfs_mode(vap->va_type, vap->va_mode);	sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid);	sp->sa_gid = txdr_unsigned(vattr.va_gid);	if (isnq) {		sp->sa_nqrdev = rdev;		sp->sa_nqflags = 0;		txdr_nqtime(&vap->va_atime, &sp->sa_nqatime);		txdr_nqtime(&vap->va_mtime, &sp->sa_nqmtime);	} else {		sp->sa_nfssize = rdev;		txdr_nfstime(&vap->va_atime, &sp->sa_nfsatime);		txdr_nfstime(&vap->va_mtime, &sp->sa_nfsmtime);	}	nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred);	nfsm_mtofh(dvp, newvp);	nfsm_reqdone;

⌨️ 快捷键说明

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