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

📄 nfs_subs.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
		m1->m_len = len+tlen;		siz -= xfer;		cp += xfer;	}	*mb = m1;	*bpos = mtod(m1, caddr_t)+m1->m_len;	return (0);}/* * Called once to initialize data structures... */nfs_init(){	register int i;	nfsrtt.pos = 0;	rpc_vers = txdr_unsigned(RPC_VER2);	rpc_call = txdr_unsigned(RPC_CALL);	rpc_reply = txdr_unsigned(RPC_REPLY);	rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED);	rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED);	rpc_mismatch = txdr_unsigned(RPC_MISMATCH);	rpc_autherr = txdr_unsigned(RPC_AUTHERR);	rpc_rejectedcred = txdr_unsigned(AUTH_REJECTCRED);	rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX);	rpc_auth_kerb = txdr_unsigned(RPCAUTH_NQNFS);	nfs_vers = txdr_unsigned(NFS_VER2);	nfs_prog = txdr_unsigned(NFS_PROG);	nfs_true = txdr_unsigned(TRUE);	nfs_false = txdr_unsigned(FALSE);	/* Loop thru nfs procids */	for (i = 0; i < NFS_NPROCS; i++)		nfs_procids[i] = txdr_unsigned(i);	/* Ensure async daemons disabled */	for (i = 0; i < NFS_MAXASYNCDAEMON; i++)		nfs_iodwant[i] = (struct proc *)0;	TAILQ_INIT(&nfs_bufq);	nfs_xdrneg1 = txdr_unsigned(-1);	nfs_nhinit();			/* Init the nfsnode table */	nfsrv_init(0);			/* Init server data structures */	nfsrv_initcache();		/* Init the server request cache */	/*	 * Initialize the nqnfs server stuff.	 */	if (nqnfsstarttime == 0) {		nqnfsstarttime = boottime.tv_sec + nqsrv_maxlease			+ nqsrv_clockskew + nqsrv_writeslack;		NQLOADNOVRAM(nqnfsstarttime);		nqnfs_prog = txdr_unsigned(NQNFS_PROG);		nqnfs_vers = txdr_unsigned(NQNFS_VER1);		nqthead.th_head[0] = &nqthead;		nqthead.th_head[1] = &nqthead;		nqfhead = hashinit(NQLCHSZ, M_NQLEASE, &nqfheadhash);	}	/*	 * Initialize reply list and start timer	 */	nfsreqh.r_prev = nfsreqh.r_next = &nfsreqh;	nfs_timer();}/* * Attribute cache routines. * nfs_loadattrcache() - loads or updates the cache contents from attributes *	that are on the mbuf list * nfs_getattrcache() - returns valid attributes if found in cache, returns *	error otherwise *//* * Load the attribute cache (that lives in the nfsnode entry) with * the values on the mbuf list and * Iff vap not NULL *    copy the attributes to *vaper */nfs_loadattrcache(vpp, mdp, dposp, vaper)	struct vnode **vpp;	struct mbuf **mdp;	caddr_t *dposp;	struct vattr *vaper;{	register struct vnode *vp = *vpp;	register struct vattr *vap;	register struct nfsv2_fattr *fp;	extern int (**spec_nfsv2nodeop_p)();	register struct nfsnode *np, *nq, **nhpp;	register long t1;	caddr_t dpos, cp2;	int error = 0, isnq;	struct mbuf *md;	enum vtype vtyp;	u_short vmode;	long rdev;	struct timespec mtime;	struct vnode *nvp;	md = *mdp;	dpos = *dposp;	t1 = (mtod(md, caddr_t) + md->m_len) - dpos;	isnq = (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS);	if (error = nfsm_disct(&md, &dpos, NFSX_FATTR(isnq), t1, &cp2))		return (error);	fp = (struct nfsv2_fattr *)cp2;	vtyp = nfstov_type(fp->fa_type);	vmode = fxdr_unsigned(u_short, fp->fa_mode);	if (vtyp == VNON || vtyp == VREG)		vtyp = IFTOVT(vmode);	if (isnq) {		rdev = fxdr_unsigned(long, fp->fa_nqrdev);		fxdr_nqtime(&fp->fa_nqmtime, &mtime);	} else {		rdev = fxdr_unsigned(long, fp->fa_nfsrdev);		fxdr_nfstime(&fp->fa_nfsmtime, &mtime);	}	/*	 * If v_type == VNON it is a new node, so fill in the v_type,	 * n_mtime fields. Check to see if it represents a special 	 * device, and if so, check for a possible alias. Once the	 * correct vnode has been obtained, fill in the rest of the	 * information.	 */	np = VTONFS(vp);	if (vp->v_type == VNON) {		if (vtyp == VCHR && rdev == 0xffffffff)			vp->v_type = vtyp = VFIFO;		else			vp->v_type = vtyp;		if (vp->v_type == VFIFO) {#ifdef FIFO			extern int (**fifo_nfsv2nodeop_p)();			vp->v_op = fifo_nfsv2nodeop_p;#else			return (EOPNOTSUPP);#endif /* FIFO */		}		if (vp->v_type == VCHR || vp->v_type == VBLK) {			vp->v_op = spec_nfsv2nodeop_p;			if (nvp = checkalias(vp, (dev_t)rdev, vp->v_mount)) {				/*				 * Discard unneeded vnode, but save its nfsnode.				 */				if (nq = np->n_forw)					nq->n_back = np->n_back;				*np->n_back = nq;				nvp->v_data = vp->v_data;				vp->v_data = NULL;				vp->v_op = spec_vnodeop_p;				vrele(vp);				vgone(vp);				/*				 * Reinitialize aliased node.				 */				np->n_vnode = nvp;				nhpp = (struct nfsnode **)nfs_hash(&np->n_fh);				if (nq = *nhpp)					nq->n_back = &np->n_forw;				np->n_forw = nq;				np->n_back = nhpp;				*nhpp = np;				*vpp = vp = nvp;			}		}		np->n_mtime = mtime.ts_sec;	}	vap = &np->n_vattr;	vap->va_type = vtyp;	vap->va_mode = (vmode & 07777);	vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);	vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);	vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);	vap->va_rdev = (dev_t)rdev;	vap->va_mtime = mtime;	vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];	if (isnq) {		fxdr_hyper(&fp->fa_nqsize, &vap->va_size);		vap->va_blocksize = fxdr_unsigned(long, fp->fa_nqblocksize);		fxdr_hyper(&fp->fa_nqbytes, &vap->va_bytes);		vap->va_fileid = fxdr_unsigned(long, fp->fa_nqfileid);		fxdr_nqtime(&fp->fa_nqatime, &vap->va_atime);		vap->va_flags = fxdr_unsigned(u_long, fp->fa_nqflags);		fxdr_nqtime(&fp->fa_nqctime, &vap->va_ctime);		vap->va_gen = fxdr_unsigned(u_long, fp->fa_nqgen);		fxdr_hyper(&fp->fa_nqfilerev, &vap->va_filerev);	} else {		vap->va_size = fxdr_unsigned(u_long, fp->fa_nfssize);		vap->va_blocksize = fxdr_unsigned(long, fp->fa_nfsblocksize);		vap->va_bytes = fxdr_unsigned(long, fp->fa_nfsblocks) * NFS_FABLKSIZE;		vap->va_fileid = fxdr_unsigned(long, fp->fa_nfsfileid);		fxdr_nfstime(&fp->fa_nfsatime, &vap->va_atime);		vap->va_flags = 0;		vap->va_ctime.ts_sec = fxdr_unsigned(long, fp->fa_nfsctime.nfs_sec);		vap->va_ctime.ts_nsec = 0;		vap->va_gen = fxdr_unsigned(u_long, fp->fa_nfsctime.nfs_usec);		vap->va_filerev = 0;	}	if (vap->va_size != np->n_size) {		if (vap->va_type == VREG) {			if (np->n_flag & NMODIFIED) {				if (vap->va_size < np->n_size)					vap->va_size = np->n_size;				else					np->n_size = vap->va_size;			} else				np->n_size = vap->va_size;			vnode_pager_setsize(vp, (u_long)np->n_size);		} else			np->n_size = vap->va_size;	}	np->n_attrstamp = time.tv_sec;	*dposp = dpos;	*mdp = md;	if (vaper != NULL) {		bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(*vap));#ifdef notdef		if ((np->n_flag & NMODIFIED) && np->n_size > vap->va_size)		if (np->n_size > vap->va_size)			vaper->va_size = np->n_size;#endif		if (np->n_flag & NCHG) {			if (np->n_flag & NACC) {				vaper->va_atime.ts_sec = np->n_atim.tv_sec;				vaper->va_atime.ts_nsec =				    np->n_atim.tv_usec * 1000;			}			if (np->n_flag & NUPD) {				vaper->va_mtime.ts_sec = np->n_mtim.tv_sec;				vaper->va_mtime.ts_nsec =				    np->n_mtim.tv_usec * 1000;			}		}	}	return (0);}/* * Check the time stamp * If the cache is valid, copy contents to *vap and return 0 * otherwise return an error */nfs_getattrcache(vp, vaper)	register struct vnode *vp;	struct vattr *vaper;{	register struct nfsnode *np = VTONFS(vp);	register struct vattr *vap;	if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQLOOKLEASE) {		if (!NQNFS_CKCACHABLE(vp, NQL_READ) || np->n_attrstamp == 0) {			nfsstats.attrcache_misses++;			return (ENOENT);		}	} else if ((time.tv_sec - np->n_attrstamp) >= NFS_ATTRTIMEO(np)) {		nfsstats.attrcache_misses++;		return (ENOENT);	}	nfsstats.attrcache_hits++;	vap = &np->n_vattr;	if (vap->va_size != np->n_size) {		if (vap->va_type == VREG) {			if (np->n_flag & NMODIFIED) {				if (vap->va_size < np->n_size)					vap->va_size = np->n_size;				else					np->n_size = vap->va_size;			} else				np->n_size = vap->va_size;			vnode_pager_setsize(vp, (u_long)np->n_size);		} else			np->n_size = vap->va_size;	}	bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(struct vattr));#ifdef notdef	if ((np->n_flag & NMODIFIED) == 0) {		np->n_size = vaper->va_size;		vnode_pager_setsize(vp, (u_long)np->n_size);	} else if (np->n_size > vaper->va_size)	if (np->n_size > vaper->va_size)		vaper->va_size = np->n_size;#endif	if (np->n_flag & NCHG) {		if (np->n_flag & NACC) {			vaper->va_atime.ts_sec = np->n_atim.tv_sec;			vaper->va_atime.ts_nsec = np->n_atim.tv_usec * 1000;		}		if (np->n_flag & NUPD) {			vaper->va_mtime.ts_sec = np->n_mtim.tv_sec;			vaper->va_mtime.ts_nsec = np->n_mtim.tv_usec * 1000;		}	}	return (0);}/* * Set up nameidata for a lookup() call and do it */nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, p)	register struct nameidata *ndp;	fhandle_t *fhp;	int len;	struct nfssvc_sock *slp;	struct mbuf *nam;	struct mbuf **mdp;	caddr_t *dposp;	struct proc *p;{	register int i, rem;	register struct mbuf *md;	register char *fromcp, *tocp;	struct vnode *dp;	int error, rdonly;	struct componentname *cnp = &ndp->ni_cnd;	MALLOC(cnp->cn_pnbuf, char *, len + 1, M_NAMEI, M_WAITOK);	/*	 * Copy the name from the mbuf list to ndp->ni_pnbuf	 * and set the various ndp fields appropriately.	 */	fromcp = *dposp;	tocp = cnp->cn_pnbuf;	md = *mdp;	rem = mtod(md, caddr_t) + md->m_len - fromcp;	cnp->cn_hash = 0;	for (i = 0; i < len; i++) {		while (rem == 0) {			md = md->m_next;			if (md == NULL) {				error = EBADRPC;				goto out;			}			fromcp = mtod(md, caddr_t);			rem = md->m_len;		}		if (*fromcp == '\0' || *fromcp == '/') {			error = EINVAL;			goto out;		}		cnp->cn_hash += (unsigned char)*fromcp;		*tocp++ = *fromcp++;		rem--;	}	*tocp = '\0';	*mdp = md;	*dposp = fromcp;	len = nfsm_rndup(len)-len;	if (len > 0) {		if (rem >= len)			*dposp += len;		else if (error = nfs_adv(mdp, dposp, len, rem))			goto out;	}	ndp->ni_pathlen = tocp - cnp->cn_pnbuf;	cnp->cn_nameptr = cnp->cn_pnbuf;	/*	 * Extract and set starting directory.	 */	if (error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp,	    nam, &rdonly))		goto out;	if (dp->v_type != VDIR) {		vrele(dp);		error = ENOTDIR;		goto out;	}	ndp->ni_startdir = dp;	if (rdonly)		cnp->cn_flags |= (NOCROSSMOUNT | RDONLY);	else		cnp->cn_flags |= NOCROSSMOUNT;	/*	 * And call lookup() to do the real work	 */	cnp->cn_proc = p;	if (error = lookup(ndp))		goto out;	/*	 * Check for encountering a symbolic link	 */	if (cnp->cn_flags & ISSYMLINK) {		if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)			vput(ndp->ni_dvp);		else			vrele(ndp->ni_dvp);		vput(ndp->ni_vp);		ndp->ni_vp = NULL;		error = EINVAL;		goto out;	}	/*	 * Check for saved name request	 */	if (cnp->cn_flags & (SAVENAME | SAVESTART)) {		cnp->cn_flags |= HASBUF;		return (0);	}out:	FREE(cnp->cn_pnbuf, M_NAMEI);	return (error);}/* * A fiddled version of m_adj() that ensures null fill to a long * boundary and only trims off the back end */voidnfsm_adj(mp, len, nul)	struct mbuf *mp;	register int len;	int nul;{	register struct mbuf *m;	register int count, i;	register char *cp;	/*	 * Trim from tail.  Scan the mbuf chain,	 * calculating its length and finding the last mbuf.	 * If the adjustment only affects this mbuf, then just	 * adjust and return.  Otherwise, rescan and truncate	 * after the remaining size.	 */	count = 0;	m = mp;	for (;;) {		count += m->m_len;		if (m->m_next == (struct mbuf *)0)			break;		m = m->m_next;	}	if (m->m_len > len) {		m->m_len -= len;		if (nul > 0) {			cp = mtod(m, caddr_t)+m->m_len-nul;			for (i = 0; i < nul; i++)				*cp++ = '\0';		}		return;	}	count -= len;	if (count < 0)		count = 0;	/*	 * Correct length for chain is "count".	 * Find the mbuf with last data, adjust its length,	 * and toss data from remaining mbufs on chain.	 */	for (m = mp; m; m = m->m_next) {		if (m->m_len >= count) {			m->m_len = count;			if (nul > 0) {				cp = mtod(m, caddr_t)+m->m_len-nul;				for (i = 0; i < nul; i++)					*cp++ = '\0';			}			break;		}		count -= m->m_len;	}	while (m = m->m_next)		m->m_len = 0;}/* * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked) * 	- look up fsid in mount list (if not found ret error) *	- get vp and export rights by calling VFS_FHTOVP() *	- if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon *	- if not lockflag unlock it with VOP_UNLOCK() */nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp)	fhandle_t *fhp;	int lockflag;	struct vnode **vpp;	struct ucred *cred;	struct nfssvc_sock *slp;	struct mbuf *nam;	int *rdonlyp;{	register struct mount *mp;	register struct nfsuid *uidp;	register int i;	struct ucred *credanon;	int error, exflags;	*vpp = (struct vnode *)0;	if ((mp = getvfs(&fhp->fh_fsid)) == NULL)		return (ESTALE);	if (error = VFS_FHTOVP(mp, &fhp->fh_fid, nam, vpp, &exflags, &credanon))		return (error);	/*	 * Check/setup credentials.	 */	if (exflags & MNT_EXKERB) {		uidp = slp->ns_uidh[NUIDHASH(cred->cr_uid)];		while (uidp) {			if (uidp->nu_uid == cred->cr_uid)				break;			uidp = uidp->nu_hnext;		}		if (uidp) {			cred->cr_uid = uidp->nu_cr.cr_uid;			for (i = 0; i < uidp->nu_cr.cr_ngroups; i++)				cred->cr_groups[i] = uidp->nu_cr.cr_groups[i];		} else {			vput(*vpp);			return (NQNFS_AUTHERR);		}	} else if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) {		cred->cr_uid = credanon->cr_uid;		for (i = 0; i < credanon->cr_ngroups && i < NGROUPS; i++)			cred->cr_groups[i] = credanon->cr_groups[i];	}	if (exflags & MNT_EXRDONLY)		*rdonlyp = 1;	else		*rdonlyp = 0;	if (!lockflag)		VOP_UNLOCK(*vpp);	return (0);}/* * This function compares two net addresses by family and returns TRUE * if they are the same host. * If there is any doubt, return FALSE. * The AF_INET family is handled as a special case so that address mbufs * don't need to be saved to store "struct in_addr", which is only 4 bytes. */netaddr_match(family, haddr, nam)	int family;	union nethostaddr *haddr;	struct mbuf *nam;{	register struct sockaddr_in *inetaddr;	switch (family) {	case AF_INET:		inetaddr = mtod(nam, struct sockaddr_in *);		if (inetaddr->sin_family == AF_INET &&		    inetaddr->sin_addr.s_addr == haddr->had_inetaddr)			return (1);		break;#ifdef ISO	case AF_ISO:	    {		register struct sockaddr_iso *isoaddr1, *isoaddr2;		isoaddr1 = mtod(nam, struct sockaddr_iso *);		isoaddr2 = mtod(haddr->had_nam, struct sockaddr_iso *);		if (isoaddr1->siso_family == AF_ISO &&		    isoaddr1->siso_nlen > 0 &&		    isoaddr1->siso_nlen == isoaddr2->siso_nlen &&		    SAME_ISOADDR(isoaddr1, isoaddr2))			return (1);		break;	    }#endif	/* ISO */	default:		break;	};	return (0);}

⌨️ 快捷键说明

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