📄 ffs_vfsops.c
字号:
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 + -