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

📄 ffs_vfsops.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	ump->um_dev = dev;	ump->um_devvp = devvp;	ump->um_nindir = fs->fs_nindir;	ump->um_bptrtodb = fs->fs_fsbtodb;	ump->um_seqinc = fs->fs_frag;	for (i = 0; i < MAXQUOTAS; i++)		ump->um_quotas[i] = NULLVP;	devvp->v_specflags |= SI_MOUNTEDON;	ffs_oldfscompat(fs);	return (0);out:	if (bp)		brelse(bp);	(void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);	if (ump) {		free(ump->um_fs, M_UFSMNT);		free(ump, M_UFSMNT);		mp->mnt_data = (qaddr_t)0;	}	return (error);}/* * Sanity checks for old file systems. * * XXX - goes away some day. */ffs_oldfscompat(fs)	struct fs *fs;{	int i;	fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect);	/* XXX */	fs->fs_interleave = max(fs->fs_interleave, 1);		/* XXX */	if (fs->fs_postblformat == FS_42POSTBLFMT)		/* XXX */		fs->fs_nrpos = 8;				/* XXX */	if (fs->fs_inodefmt < FS_44INODEFMT) {			/* XXX */		quad_t sizepb = fs->fs_bsize;			/* XXX */								/* XXX */		fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1;	/* XXX */		for (i = 0; i < NIADDR; i++) {			/* XXX */			sizepb *= NINDIR(fs);			/* XXX */			fs->fs_maxfilesize += sizepb;		/* XXX */		}						/* XXX */		fs->fs_qbmask = ~fs->fs_bmask;			/* XXX */		fs->fs_qfmask = ~fs->fs_fmask;			/* XXX */	}							/* XXX */	return (0);}/* * unmount system call */intffs_unmount(mp, mntflags, p)	struct mount *mp;	int mntflags;	struct proc *p;{	register struct ufsmount *ump;	register struct fs *fs;	int error, flags, ronly;	flags = 0;	if (mntflags & MNT_FORCE) {		if (mp->mnt_flag & MNT_ROOTFS)			return (EINVAL);		flags |= FORCECLOSE;	}	if (error = ffs_flushfiles(mp, flags, p))		return (error);	ump = VFSTOUFS(mp);	fs = ump->um_fs;	ronly = !fs->fs_ronly;	ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;	error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE,		NOCRED, p);	vrele(ump->um_devvp);	free(fs->fs_csp[0], M_UFSMNT);	free(fs, M_UFSMNT);	free(ump, M_UFSMNT);	mp->mnt_data = (qaddr_t)0;	mp->mnt_flag &= ~MNT_LOCAL;	return (error);}/* * Flush out all the files in a filesystem. */ffs_flushfiles(mp, flags, p)	register struct mount *mp;	int flags;	struct proc *p;{	extern int doforce;	register struct ufsmount *ump;	int i, error;	if (!doforce)		flags &= ~FORCECLOSE;	ump = VFSTOUFS(mp);#ifdef QUOTA	if (mp->mnt_flag & MNT_QUOTA) {		if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags))			return (error);		for (i = 0; i < MAXQUOTAS; i++) {			if (ump->um_quotas[i] == NULLVP)				continue;			quotaoff(p, mp, i);		}		/*		 * Here we fall through to vflush again to ensure		 * that we have gotten rid of all the system vnodes.		 */	}#endif	error = vflush(mp, NULLVP, flags);	return (error);}/* * Get file system statistics. */intffs_statfs(mp, sbp, p)	struct mount *mp;	register struct statfs *sbp;	struct proc *p;{	register struct ufsmount *ump;	register struct fs *fs;	ump = VFSTOUFS(mp);	fs = ump->um_fs;	if (fs->fs_magic != FS_MAGIC)		panic("ffs_statfs");	sbp->f_type = MOUNT_UFS;	sbp->f_bsize = fs->fs_fsize;	sbp->f_iosize = fs->fs_bsize;	sbp->f_blocks = fs->fs_dsize;	sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +		fs->fs_cstotal.cs_nffree;	sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) -		(fs->fs_dsize - sbp->f_bfree);	sbp->f_files =  fs->fs_ncg * fs->fs_ipg - ROOTINO;	sbp->f_ffree = fs->fs_cstotal.cs_nifree;	if (sbp != &mp->mnt_stat) {		bcopy((caddr_t)mp->mnt_stat.f_mntonname,			(caddr_t)&sbp->f_mntonname[0], MNAMELEN);		bcopy((caddr_t)mp->mnt_stat.f_mntfromname,			(caddr_t)&sbp->f_mntfromname[0], MNAMELEN);	}	return (0);}/* * Go through the disk queues to initiate sandbagged IO; * go through the inodes to write those that have been modified; * initiate the writing of the super block if it has been modified. * * Note: we are always called with the filesystem marked `MPBUSY'. */intffs_sync(mp, waitfor, cred, p)	struct mount *mp;	int waitfor;	struct ucred *cred;	struct proc *p;{	register struct vnode *vp;	register struct inode *ip;	register struct ufsmount *ump = VFSTOUFS(mp);	register struct fs *fs;	int error, allerror = 0;	fs = ump->um_fs;	/*	 * Write back modified superblock.	 * Consistency check that the superblock	 * is still in the buffer cache.	 */	if (fs->fs_fmod != 0) {		if (fs->fs_ronly != 0) {		/* XXX */			printf("fs = %s\n", fs->fs_fsmnt);			panic("update: rofs mod");		}		fs->fs_fmod = 0;		fs->fs_time = time.tv_sec;		allerror = ffs_sbupdate(ump, waitfor);	}	/*	 * Write back each (modified) inode.	 */loop:	for (vp = mp->mnt_vnodelist.lh_first;	     vp != NULL;	     vp = vp->v_mntvnodes.le_next) {		/*		 * If the vnode that we are about to sync is no longer		 * associated with this mount point, start over.		 */		if (vp->v_mount != mp)			goto loop;		if (VOP_ISLOCKED(vp))			continue;		ip = VTOI(vp);		if ((ip->i_flag &		    (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&		    vp->v_dirtyblkhd.lh_first == NULL)			continue;		if (vget(vp, 1))			goto loop;		if (error = VOP_FSYNC(vp, cred, waitfor, p))			allerror = error;		vput(vp);	}	/*	 * Force stale file system control information to be flushed.	 */	if (error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p))		allerror = error;#ifdef QUOTA	qsync(mp);#endif	return (allerror);}/* * Look up a FFS dinode number to find its incore vnode, otherwise read it * in from disk.  If it is in core, wait for the lock bit to clear, then * return the inode locked.  Detection and handling of mount points must be * done by the calling routine. */intffs_vget(mp, ino, vpp)	struct mount *mp;	ino_t ino;	struct vnode **vpp;{	register struct fs *fs;	register struct inode *ip;	struct ufsmount *ump;	struct buf *bp;	struct vnode *vp;	dev_t dev;	int i, type, error;	ump = VFSTOUFS(mp);	dev = ump->um_dev;	if ((*vpp = ufs_ihashget(dev, ino)) != NULL)		return (0);	/* Allocate a new vnode/inode. */	if (error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp)) {		*vpp = NULL;		return (error);	}	type = ump->um_devvp->v_tag == VT_MFS ? M_MFSNODE : M_FFSNODE; /* XXX */	MALLOC(ip, struct inode *, sizeof(struct inode), type, M_WAITOK);	bzero((caddr_t)ip, sizeof(struct inode));	vp->v_data = ip;	ip->i_vnode = vp;	ip->i_fs = fs = ump->um_fs;	ip->i_dev = dev;	ip->i_number = ino;#ifdef QUOTA	for (i = 0; i < MAXQUOTAS; i++)		ip->i_dquot[i] = NODQUOT;#endif	/*	 * Put it onto its hash chain and lock it so that other requests for	 * this inode will block if they arrive while we are sleeping waiting	 * for old data structures to be purged or for the contents of the	 * disk portion of this inode to be read.	 */	ufs_ihashins(ip);	/* Read in the disk contents for the inode, copy into the inode. */	if (error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),	    (int)fs->fs_bsize, NOCRED, &bp)) {		/*		 * The inode does not contain anything useful, so it would		 * be misleading to leave it on its hash chain. With mode		 * still zero, it will be unlinked and returned to the free		 * list by vput().		 */		vput(vp);		brelse(bp);		*vpp = NULL;		return (error);	}	ip->i_din = *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino));	brelse(bp);	/*	 * Initialize the vnode from the inode, check for aliases.	 * Note that the underlying vnode may have changed.	 */	if (error = ufs_vinit(mp, ffs_specop_p, FFS_FIFOOPS, &vp)) {		vput(vp);		*vpp = NULL;		return (error);	}	/*	 * Finish inode initialization now that aliasing has been resolved.	 */	ip->i_devvp = ump->um_devvp;	VREF(ip->i_devvp);	/*	 * Set up a generation number for this inode if it does not	 * already have one. This should only happen on old filesystems.	 */	if (ip->i_gen == 0) {		if (++nextgennumber < (u_long)time.tv_sec)			nextgennumber = time.tv_sec;		ip->i_gen = nextgennumber;		if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)			ip->i_flag |= IN_MODIFIED;	}	/*	 * Ensure that uid and gid are correct. This is a temporary	 * fix until fsck has been changed to do the update.	 */	if (fs->fs_inodefmt < FS_44INODEFMT) {		/* XXX */		ip->i_uid = ip->i_din.di_ouid;		/* XXX */		ip->i_gid = ip->i_din.di_ogid;		/* XXX */	}						/* XXX */	*vpp = vp;	return (0);}/* * File handle to vnode * * Have to be really careful about stale file handles: * - check that the inode number is valid * - call ffs_vget() to get the locked inode * - check for an unallocated inode (i_mode == 0) * - check that the given client host has export rights and return *   those rights via. exflagsp and credanonp */intffs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)	register struct mount *mp;	struct fid *fhp;	struct mbuf *nam;	struct vnode **vpp;	int *exflagsp;	struct ucred **credanonp;{	register struct ufid *ufhp;	struct fs *fs;	ufhp = (struct ufid *)fhp;	fs = VFSTOUFS(mp)->um_fs;	if (ufhp->ufid_ino < ROOTINO ||	    ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg)		return (ESTALE);	return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp));}/* * Vnode pointer to File handle *//* ARGSUSED */ffs_vptofh(vp, fhp)	struct vnode *vp;	struct fid *fhp;{	register struct inode *ip;	register struct ufid *ufhp;	ip = VTOI(vp);	ufhp = (struct ufid *)fhp;	ufhp->ufid_len = sizeof(struct ufid);	ufhp->ufid_ino = ip->i_number;	ufhp->ufid_gen = ip->i_gen;	return (0);}/* * Write a superblock and associated information back to disk. */intffs_sbupdate(mp, waitfor)	struct ufsmount *mp;	int waitfor;{	register struct fs *fs = mp->um_fs;	register struct buf *bp;	int blks;	caddr_t space;	int i, size, error = 0;	bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize, 0, 0);	bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);	/* Restore compatibility to old file systems.		   XXX */	if (fs->fs_postblformat == FS_42POSTBLFMT)		/* XXX */		((struct fs *)bp->b_data)->fs_nrpos = -1;	/* XXX */	if (waitfor == MNT_WAIT)		error = bwrite(bp);	else		bawrite(bp);	blks = howmany(fs->fs_cssize, fs->fs_fsize);	space = (caddr_t)fs->fs_csp[0];	for (i = 0; i < blks; i += fs->fs_frag) {		size = fs->fs_bsize;		if (i + fs->fs_frag > blks)			size = (blks - i) * fs->fs_fsize;		bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i),		    size, 0, 0);		bcopy(space, bp->b_data, (u_int)size);		space += size;		if (waitfor == MNT_WAIT)			error = bwrite(bp);		else			bawrite(bp);	}	return (error);}

⌨️ 快捷键说明

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