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

📄 vfs_subr.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
void vgone(vp)	register struct vnode *vp;{	register struct vnode *vq;	struct vnode *vx;	/*	 * If a vgone (or vclean) is already in progress,	 * wait until it is done and return.	 */	if (vp->v_flag & VXLOCK) {		vp->v_flag |= VXWANT;		sleep((caddr_t)vp, PINOD);		return;	}	/*	 * Clean out the filesystem specific data.	 */	vclean(vp, DOCLOSE);	/*	 * Delete from old mount point vnode list, if on one.	 */	if (vp->v_mount != NULL) {		LIST_REMOVE(vp, v_mntvnodes);		vp->v_mount = NULL;	}	/*	 * If special device, remove it from special device alias list.	 */	if (vp->v_type == VBLK || vp->v_type == VCHR) {		if (*vp->v_hashchain == vp) {			*vp->v_hashchain = vp->v_specnext;		} else {			for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {				if (vq->v_specnext != vp)					continue;				vq->v_specnext = vp->v_specnext;				break;			}			if (vq == NULL)				panic("missing bdev");		}		if (vp->v_flag & VALIASED) {			vx = NULL;			for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {				if (vq->v_rdev != vp->v_rdev ||				    vq->v_type != vp->v_type)					continue;				if (vx)					break;				vx = vq;			}			if (vx == NULL)				panic("missing alias");			if (vq == NULL)				vx->v_flag &= ~VALIASED;			vp->v_flag &= ~VALIASED;		}		FREE(vp->v_specinfo, M_VNODE);		vp->v_specinfo = NULL;	}	/*	 * If it is on the freelist and not already at the head,	 * move it to the head of the list. The test of the back	 * pointer and the reference count of zero is because	 * it will be removed from the free list by getnewvnode,	 * but will not have its reference count incremented until	 * after calling vgone. If the reference count were	 * incremented first, vgone would (incorrectly) try to	 * close the previous instance of the underlying object.	 * So, the back pointer is explicitly set to `0xdeadb' in	 * getnewvnode after removing it from the freelist to ensure	 * that we do not try to move it here.	 */	if (vp->v_usecount == 0 &&	    vp->v_freelist.tqe_prev != (struct vnode **)0xdeadb &&	    vnode_free_list.tqh_first != vp) {		TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);		TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist);	}	vp->v_type = VBAD;}/* * Lookup a vnode by device number. */vfinddev(dev, type, vpp)	dev_t dev;	enum vtype type;	struct vnode **vpp;{	register struct vnode *vp;	for (vp = speclisth[SPECHASH(dev)]; vp; vp = vp->v_specnext) {		if (dev != vp->v_rdev || type != vp->v_type)			continue;		*vpp = vp;		return (1);	}	return (0);}/* * Calculate the total number of references to a special device. */vcount(vp)	register struct vnode *vp;{	register struct vnode *vq, *vnext;	int count;loop:	if ((vp->v_flag & VALIASED) == 0)		return (vp->v_usecount);	for (count = 0, vq = *vp->v_hashchain; vq; vq = vnext) {		vnext = vq->v_specnext;		if (vq->v_rdev != vp->v_rdev || vq->v_type != vp->v_type)			continue;		/*		 * Alias, but not in use, so flush it out.		 */		if (vq->v_usecount == 0 && vq != vp) {			vgone(vq);			goto loop;		}		count += vq->v_usecount;	}	return (count);}/* * Print out a description of a vnode. */static char *typename[] =   { "VNON", "VREG", "VDIR", "VBLK", "VCHR", "VLNK", "VSOCK", "VFIFO", "VBAD" };vprint(label, vp)	char *label;	register struct vnode *vp;{	char buf[64];	if (label != NULL)		printf("%s: ", label);	printf("type %s, usecount %d, writecount %d, refcount %d,",		typename[vp->v_type], vp->v_usecount, vp->v_writecount,		vp->v_holdcnt);	buf[0] = '\0';	if (vp->v_flag & VROOT)		strcat(buf, "|VROOT");	if (vp->v_flag & VTEXT)		strcat(buf, "|VTEXT");	if (vp->v_flag & VSYSTEM)		strcat(buf, "|VSYSTEM");	if (vp->v_flag & VXLOCK)		strcat(buf, "|VXLOCK");	if (vp->v_flag & VXWANT)		strcat(buf, "|VXWANT");	if (vp->v_flag & VBWAIT)		strcat(buf, "|VBWAIT");	if (vp->v_flag & VALIASED)		strcat(buf, "|VALIASED");	if (buf[0] != '\0')		printf(" flags (%s)", &buf[1]);	if (vp->v_data == NULL) {		printf("\n");	} else {		printf("\n\t");		VOP_PRINT(vp);	}}#ifdef DEBUG/* * List all of the locked vnodes in the system. * Called when debugging the kernel. */printlockedvnodes(){	register struct mount *mp;	register struct vnode *vp;	printf("Locked vnodes\n");	for (mp = mountlist.tqh_first; mp != NULL; mp = mp->mnt_list.tqe_next) {		for (vp = mp->mnt_vnodelist.lh_first;		     vp != NULL;		     vp = vp->v_mntvnodes.le_next)			if (VOP_ISLOCKED(vp))				vprint((char *)0, vp);	}}#endifint kinfo_vdebug = 1;int kinfo_vgetfailed;#define KINFO_VNODESLOP	10/* * Dump vnode list (via sysctl). * Copyout address of vnode followed by vnode. *//* ARGSUSED */sysctl_vnode(where, sizep)	char *where;	size_t *sizep;{	register struct mount *mp, *nmp;	struct vnode *vp;	register char *bp = where, *savebp;	char *ewhere;	int error;#define VPTRSZ	sizeof (struct vnode *)#define VNODESZ	sizeof (struct vnode)	if (where == NULL) {		*sizep = (numvnodes + KINFO_VNODESLOP) * (VPTRSZ + VNODESZ);		return (0);	}	ewhere = where + *sizep;			for (mp = mountlist.tqh_first; mp != NULL; mp = nmp) {		nmp = mp->mnt_list.tqe_next;		if (vfs_busy(mp))			continue;		savebp = bp;again:		for (vp = mp->mnt_vnodelist.lh_first;		     vp != NULL;		     vp = vp->v_mntvnodes.le_next) {			/*			 * Check that the vp is still associated with			 * this filesystem.  RACE: could have been			 * recycled onto the same filesystem.			 */			if (vp->v_mount != mp) {				if (kinfo_vdebug)					printf("kinfo: vp changed\n");				bp = savebp;				goto again;			}			if (bp + VPTRSZ + VNODESZ > ewhere) {				*sizep = bp - where;				return (ENOMEM);			}			if ((error = copyout((caddr_t)&vp, bp, VPTRSZ)) ||			   (error = copyout((caddr_t)vp, bp + VPTRSZ, VNODESZ)))				return (error);			bp += VPTRSZ + VNODESZ;		}		vfs_unbusy(mp);	}	*sizep = bp - where;	return (0);}/* * Check to see if a filesystem is mounted on a block device. */intvfs_mountedon(vp)	register struct vnode *vp;{	register struct vnode *vq;	if (vp->v_specflags & SI_MOUNTEDON)		return (EBUSY);	if (vp->v_flag & VALIASED) {		for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {			if (vq->v_rdev != vp->v_rdev ||			    vq->v_type != vp->v_type)				continue;			if (vq->v_specflags & SI_MOUNTEDON)				return (EBUSY);		}	}	return (0);}/* * Build hash lists of net addresses and hang them off the mount point. * Called by ufs_mount() to set up the lists of export addresses. */static intvfs_hang_addrlist(mp, nep, argp)	struct mount *mp;	struct netexport *nep;	struct export_args *argp;{	register struct netcred *np;	register struct radix_node_head *rnh;	register int i;	struct radix_node *rn;	struct sockaddr *saddr, *smask = 0;	struct domain *dom;	int error;	if (argp->ex_addrlen == 0) {		if (mp->mnt_flag & MNT_DEFEXPORTED)			return (EPERM);		np = &nep->ne_defexported;		np->netc_exflags = argp->ex_flags;		np->netc_anon = argp->ex_anon;		np->netc_anon.cr_ref = 1;		mp->mnt_flag |= MNT_DEFEXPORTED;		return (0);	}	i = sizeof(struct netcred) + argp->ex_addrlen + argp->ex_masklen;	np = (struct netcred *)malloc(i, M_NETADDR, M_WAITOK);	bzero((caddr_t)np, i);	saddr = (struct sockaddr *)(np + 1);	if (error = copyin(argp->ex_addr, (caddr_t)saddr, argp->ex_addrlen))		goto out;	if (saddr->sa_len > argp->ex_addrlen)		saddr->sa_len = argp->ex_addrlen;	if (argp->ex_masklen) {		smask = (struct sockaddr *)((caddr_t)saddr + argp->ex_addrlen);		error = copyin(argp->ex_addr, (caddr_t)smask, argp->ex_masklen);		if (error)			goto out;		if (smask->sa_len > argp->ex_masklen)			smask->sa_len = argp->ex_masklen;	}	i = saddr->sa_family;	if ((rnh = nep->ne_rtable[i]) == 0) {		/*		 * Seems silly to initialize every AF when most are not		 * used, do so on demand here		 */		for (dom = domains; dom; dom = dom->dom_next)			if (dom->dom_family == i && dom->dom_rtattach) {				dom->dom_rtattach((void **)&nep->ne_rtable[i],					dom->dom_rtoffset);				break;			}		if ((rnh = nep->ne_rtable[i]) == 0) {			error = ENOBUFS;			goto out;		}	}	rn = (*rnh->rnh_addaddr)((caddr_t)saddr, (caddr_t)smask, rnh,		np->netc_rnodes);	if (rn == 0 || np != (struct netcred *)rn) { /* already exists */		error = EPERM;		goto out;	}	np->netc_exflags = argp->ex_flags;	np->netc_anon = argp->ex_anon;	np->netc_anon.cr_ref = 1;	return (0);out:	free(np, M_NETADDR);	return (error);}/* ARGSUSED */static intvfs_free_netcred(rn, w)	struct radix_node *rn;	caddr_t w;{	register struct radix_node_head *rnh = (struct radix_node_head *)w;	(*rnh->rnh_deladdr)(rn->rn_key, rn->rn_mask, rnh);	free((caddr_t)rn, M_NETADDR);	return (0);}	/* * Free the net address hash lists that are hanging off the mount points. */static voidvfs_free_addrlist(nep)	struct netexport *nep;{	register int i;	register struct radix_node_head *rnh;	for (i = 0; i <= AF_MAX; i++)		if (rnh = nep->ne_rtable[i]) {			(*rnh->rnh_walktree)(rnh, vfs_free_netcred,			    (caddr_t)rnh);			free((caddr_t)rnh, M_RTABLE);			nep->ne_rtable[i] = 0;		}}intvfs_export(mp, nep, argp)	struct mount *mp;	struct netexport *nep;	struct export_args *argp;{	int error;	if (argp->ex_flags & MNT_DELEXPORT) {		vfs_free_addrlist(nep);		mp->mnt_flag &= ~(MNT_EXPORTED | MNT_DEFEXPORTED);	}	if (argp->ex_flags & MNT_EXPORTED) {		if (error = vfs_hang_addrlist(mp, nep, argp))			return (error);		mp->mnt_flag |= MNT_EXPORTED;	}	return (0);}struct netcred *vfs_export_lookup(mp, nep, nam)	register struct mount *mp;	struct netexport *nep;	struct mbuf *nam;{	register struct netcred *np;	register struct radix_node_head *rnh;	struct sockaddr *saddr;	np = NULL;	if (mp->mnt_flag & MNT_EXPORTED) {		/*		 * Lookup in the export list first.		 */		if (nam != NULL) {			saddr = mtod(nam, struct sockaddr *);			rnh = nep->ne_rtable[saddr->sa_family];			if (rnh != NULL) {				np = (struct netcred *)					(*rnh->rnh_matchaddr)((caddr_t)saddr,							      rnh);				if (np && np->netc_rnodes->rn_flags & RNF_ROOT)					np = NULL;			}		}		/*		 * If no address match, use the default if it exists.		 */		if (np == NULL && mp->mnt_flag & MNT_DEFEXPORTED)			np = &nep->ne_defexported;	}	return (np);}

⌨️ 快捷键说明

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