ffs_vfsops.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 1,012 行 · 第 1/2 页

C
1,012
字号
	fs = ump->um_fs;	fs->fs_ronly = ronly;	if (ronly == 0) {		fs->fs_clean <<= 1;		fs->fs_fmod = 1;	}	size = fs->fs_cssize;	blks = howmany(size, fs->fs_fsize);	if (fs->fs_contigsumsize > 0)		size += fs->fs_ncg * sizeof(int32_t);	base = space = malloc((u_long)size, M_UFSMNT, M_WAITOK);	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;		error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,			      cred, &bp);		if (error) {			free(base, M_UFSMNT);			goto out;		}		bcopy(bp->b_data, space, (u_int)size);		fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space;		space += size;		brelse(bp);		bp = NULL;	}	if (fs->fs_contigsumsize > 0) {		fs->fs_maxcluster = lp = (int32_t *)space;		for (i = 0; i < fs->fs_ncg; i++)			*lp++ = fs->fs_contigsumsize;	}	mp->mnt_data = (qaddr_t)ump;	mp->mnt_stat.f_fsid.val[0] = (long)dev;	mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_FFS);	mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;	mp->mnt_flag |= MNT_LOCAL;	ump->um_mountp = mp;	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);	ump->um_savedmaxfilesize = fs->fs_maxfilesize;		/* XXX */	maxfilesize = (u_int64_t)0x80000000 * fs->fs_bsize - 1;	/* XXX */	if (fs->fs_maxfilesize > maxfilesize)			/* XXX */		fs->fs_maxfilesize = maxfilesize;		/* XXX */	return (0);out:	if (bp)		brelse(bp);	(void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, 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. */intffs_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 */		u_int64_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;	flags = 0;	if (mntflags & MNT_FORCE)		flags |= FORCECLOSE;	if ((error = ffs_flushfiles(mp, flags, p)) != 0)		return (error);	ump = VFSTOUFS(mp);	fs = ump->um_fs;	if (fs->fs_ronly == 0 &&	    ffs_cgupdate(ump, MNT_WAIT) == 0 &&	    fs->fs_clean & FS_WASCLEAN) {		fs->fs_clean = FS_ISCLEAN;		(void) ffs_sbupdate(ump, MNT_WAIT);	}	ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;	error = VOP_CLOSE(ump->um_devvp, fs->fs_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. */intffs_flushfiles(mp, flags, p)	register struct mount *mp;	int flags;	struct proc *p;{	extern int doforce;	register struct ufsmount *ump;	int error;	if (!doforce)		flags &= ~FORCECLOSE;	ump = VFSTOUFS(mp);#ifdef QUOTA	if (mp->mnt_flag & MNT_QUOTA) {		int i;		if ((error = vflush(mp, NULLVP, SKIPSYSTEM|flags)) != 0)			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");#ifdef COMPAT_09	sbp->f_type = 1;#else	sbp->f_type = 0;#endif	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(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);		bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);	}	strncpy(sbp->f_fstypename, mp->mnt_op->vfs_name, MFSNAMELEN);	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_cgupdate(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)) != 0)			allerror = error;		vput(vp);	}	/*	 * Force stale file system control information to be flushed.	 */	if ((error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) != 0)		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 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)) != 0) {		*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	{		int i;		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. */	error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),		      (int)fs->fs_bsize, NOCRED, &bp);	if (error) {		/*		 * 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.	 */	error = ufs_vinit(mp, ffs_specop_p, FFS_FIFOOPS, &vp);	if (error) {		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 */intffs_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 *dfs, *fs = mp->um_fs;	register struct buf *bp;	int i, error = 0;	bp = getblk(mp->um_devvp, SBOFF >> (fs->fs_fshift - fs->fs_fsbtodb),	    (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 */	dfs = (struct fs *)bp->b_data;				/* XXX */	if (fs->fs_postblformat == FS_42POSTBLFMT)		/* XXX */		dfs->fs_nrpos = -1;				/* XXX */	if (fs->fs_inodefmt < FS_44INODEFMT) {			/* XXX */		int32_t *lp, tmp;				/* XXX */								/* XXX */		lp = (int32_t *)&dfs->fs_qbmask;		/* XXX */		tmp = lp[4];					/* XXX */		for (i = 4; i > 0; i--)				/* XXX */			lp[i] = lp[i-1];			/* XXX */		lp[0] = tmp;					/* XXX */	}							/* XXX */	dfs->fs_maxfilesize = mp->um_savedmaxfilesize;		/* XXX */	if (waitfor == MNT_WAIT)		error = bwrite(bp);	else		bawrite(bp);	return (error);}intffs_cgupdate(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, allerror = 0;	allerror = ffs_sbupdate(mp, waitfor);	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);	}	if (!allerror && error)		allerror = error;	return (allerror);}

⌨️ 快捷键说明

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