* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * @(#)lfs_vfsops.c 7.17 (Berkeley) %G%
+ * @(#)lfs_vfsops.c 7.31 (Berkeley) %G%
*/
-
#include "param.h"
#include "systm.h"
#include "time.h"
#include "vnode.h"
#include "mount.h"
#include "buf.h"
+#include "ucred.h"
#include "file.h"
#include "disklabel.h"
#include "ioctl.h"
* ufs vfs operations.
*/
int ufs_mount();
+int ufs_start();
int ufs_unmount();
int ufs_root();
int ufs_statfs();
int ufs_sync();
int ufs_fhtovp();
int ufs_vptofh();
+int ufs_init();
struct vfsops ufs_vfsops = {
ufs_mount,
+ ufs_start,
ufs_unmount,
ufs_root,
ufs_statfs,
ufs_sync,
ufs_fhtovp,
- ufs_vptofh
+ ufs_vptofh,
+ ufs_init
};
/*
struct ufsmount mounttab[NMOUNT];
/*
- * Called by vfs_mountroot when ufs is going to be mounted as root
+ * Called by vfs_mountroot when ufs is going to be mounted as root.
*
- * XXX - Need to have a way of figuring the name of the root device
+ * Name is updated by mount(8) after booting.
*/
-#define ROOTNAME "root device"
+#define ROOTNAME "root_device"
ufs_mountroot()
{
mp = (struct mount *)malloc((u_long)sizeof(struct mount),
M_MOUNT, M_WAITOK);
mp->m_op = &ufs_vfsops;
- mp->m_flag = 0;
+ mp->m_flag = M_RDONLY;
mp->m_exroot = 0;
+ mp->m_mounth = (struct vnode *)0;
error = mountfs(rootvp, mp);
if (error) {
free((caddr_t)mp, M_MOUNT);
return (error);
}
- error = vfs_add((struct vnode *)0, mp, 0);
- if (error) {
+ if (error = vfs_lock(mp)) {
(void)ufs_unmount(mp, 0);
free((caddr_t)mp, M_MOUNT);
return (error);
}
+ rootfs = mp;
+ mp->m_next = mp;
+ mp->m_prev = mp;
+ mp->m_vnodecovered = (struct vnode *)0;
ump = VFSTOUFS(mp);
fs = ump->um_fs;
fs->fs_fsmnt[0] = '/';
return (error);
if ((error = getmdev(&devvp, args.fspec, ndp)) != 0)
return (error);
- error = mountfs(devvp, mp);
+ if ((mp->m_flag & M_UPDATE) == 0) {
+ error = mountfs(devvp, mp);
+ } else {
+ ump = VFSTOUFS(mp);
+ fs = ump->um_fs;
+ if (fs->fs_ronly && (mp->m_flag & M_RDONLY) == 0)
+ fs->fs_ronly = 0;
+ /*
+ * Verify that the specified device is the one that
+ * is really being used for the root file system.
+ */
+ if (devvp != ump->um_devvp)
+ error = EINVAL; /* needs translation */
+ }
if (error) {
vrele(devvp);
return (error);
return (error);
}
needclose = 1;
- if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD,
- (struct ucred *)0) != 0)
+ if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED) != 0)
size = DEV_BSIZE;
else {
havepart = 1;
size = dpart.disklab->d_secsize;
}
- if (error = bread(devvp, SBLOCK, SBSIZE, &bp)) {
+ if (error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) {
ump->um_fs = NULL;
goto out;
}
M_WAITOK);
bcopy((caddr_t)bp->b_un.b_addr, (caddr_t)ump->um_fs,
(u_int)fs->fs_sbsize);
+ if (fs->fs_sbsize < SBSIZE)
+ bp->b_flags |= B_INVAL;
brelse(bp);
bp = NULL;
fs = ump->um_fs;
tp = bread(dev, fsbtodb(fs, fs->fs_csaddr + i), size,
fs->fs_dbsize);
#else SECSIZE
- error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, &bp);
+ error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
+ NOCRED, &bp);
if (error) {
free((caddr_t)base, M_SUPERBLK);
goto out;
ump->um_dev = dev;
ump->um_devvp = devvp;
ump->um_qinod = NULL;
+ devvp->v_mounton = mp;
/* Sanity checks for old file systems. XXX */
fs->fs_npsect = MAX(fs->fs_npsect, fs->fs_nsect); /* XXX */
return (0);
out:
if (needclose)
- (void) VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE,
- (struct ucred *)0);
+ (void) VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED);
if (ump->um_fs) {
free((caddr_t)ump->um_fs, M_SUPERBLK);
ump->um_fs = NULL;
return (error);
}
+/*
+ * Make a filesystem operational.
+ * Nothing to do at the moment.
+ */
+/* ARGSUSED */
+ufs_start(mp, flags)
+ struct mount *mp;
+ int flags;
+{
+
+ return (0);
+}
/*
* unmount system call
{
register struct ufsmount *ump;
register struct fs *fs;
- dev_t dev;
int error, ronly;
if (flags & MNT_FORCE)
return (EINVAL);
+ mntflushbuf(mp, 0);
+ if (mntinvalbuf(mp))
+ return (EBUSY);
ump = VFSTOUFS(mp);
- dev = ump->um_dev;
-#ifdef QUOTA
- if ((error = iflush(dev, mp->m_qinod)) && !forcibly)
-#else
- if ((error = iflush(dev)) && !forcibly)
-#endif
+ if (error = vflush(mp, ITOV(ump->um_qinod), flags))
return (error);
#ifdef QUOTA
- (void)closedq(ump);
+ (void) closedq(ump);
/*
- * Here we have to iflush again to get rid of the quota inode.
* A drag, but it would be ugly to cheat, & this doesn't happen often.
*/
- (void)iflush(dev, (struct inode *)NULL);
+ if (vflush(mp, (struct vnode *)NULL, MNT_NOFORCE))
+ panic("ufs_unmount: quota");
#endif
fs = ump->um_fs;
ronly = !fs->fs_ronly;
struct mount *mp;
struct vnode **vpp;
{
- struct inode tip, *ip;
+ register struct inode *ip;
+ struct inode *nip;
+ struct vnode tvp;
int error;
- tip.i_dev = VFSTOUFS(mp)->um_dev;
- tip.i_vnode.v_mount = mp;
- error = iget(&tip, (ino_t)ROOTINO, &ip);
+ tvp.v_mount = mp;
+ ip = VTOI(&tvp);
+ ip->i_vnode = &tvp;
+ ip->i_dev = VFSTOUFS(mp)->um_dev;
+ error = iget(ip, (ino_t)ROOTINO, &nip);
if (error)
return (error);
- *vpp = ITOV(ip);
+ *vpp = ITOV(nip);
return (0);
}
if (fs->fs_magic != FS_MAGIC)
panic("ufs_statfs");
sbp->f_type = MOUNT_UFS;
- sbp->f_flags = mp->m_flag &~ (M_MLOCK|M_MWAIT);
sbp->f_fsize = fs->fs_fsize;
sbp->f_bsize = fs->fs_bsize;
sbp->f_blocks = fs->fs_dsize;
fs->fs_cstotal.cs_nffree;
sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) -
(fs->fs_dsize - sbp->f_bfree);
- if (sbp->f_bavail < 0)
- sbp->f_bavail = 0;
- sbp->f_files = fs->fs_ncg * fs->fs_ipg;
+ sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO;
sbp->f_ffree = fs->fs_cstotal.cs_nifree;
- sbp->f_fsid = mp->m_fsid;
bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
bcopy((caddr_t)ump->um_mntname, (caddr_t)&sbp->f_mntfromname[0],
MNAMELEN);
struct mount *mp;
int waitfor;
{
+ register struct vnode *vp;
register struct inode *ip;
register struct ufsmount *ump = VFSTOUFS(mp);
register struct fs *fs;
- int error = 0;
+ int error, allerror = 0;
static int updlock = 0;
if (syncprt)
/*
* Write back each (modified) inode.
*/
- for (ip = inode; ip < inodeNINODE; ip++) {
- if (ip->i_devvp != ump->um_devvp ||
- (ip->i_flag & ILOCKED) != 0 || ITOV(ip)->v_count == 0 ||
+ for (vp = mp->m_mounth; vp; vp = vp->v_mountf) {
+ ip = VTOI(vp);
+ if ((ip->i_flag & ILOCKED) != 0 || vp->v_count == 0 ||
(ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0)
continue;
- ILOCK(ip);
- VREF(ITOV(ip));
- error = iupdat(ip, &time, &time, waitfor == MNT_WAIT);
- iput(ip);
+ VREF(vp);
+ VOP_LOCK(vp);
+ if (error = VOP_FSYNC(vp, 0, NOCRED, MNT_NOWAIT))
+ allerror = error;
+ vput(vp);
}
updlock = 0;
/*
- * Force stale buffer cache information to be flushed.
+ * Force stale file system control information to be flushed.
*/
- bflush(ump->um_devvp->v_rdev);
- return (error);
+ vflushbuf(ump->um_devvp, waitfor == MNT_WAIT ? B_SYNC : 0);
+ return (allerror);
}
/*
/*
* File handle to vnode
+ *
+ * Have to be really careful about stale file handles:
+ * - check that the inode number is in range
+ * - call iget() to get the locked inode
+ * - check for an unallocated inode (i_mode == 0)
+ * - check that the generation number matches
*/
ufs_fhtovp(mp, fhp, vpp)
- struct mount *mp;
+ register struct mount *mp;
struct fid *fhp;
struct vnode **vpp;
{
register struct ufid *ufhp;
- struct inode tip, *ip;
+ register struct fs *fs;
+ register struct inode *ip;
+ struct inode *nip;
+ struct vnode tvp;
int error;
ufhp = (struct ufid *)fhp;
- tip.i_dev = VFSTOUFS(mp)->um_dev;
- tip.i_vnode.v_mount = mp;
- if (error = iget(&tip, ufhp->ufid_ino, &ip)) {
- *vpp = NULL;
+ fs = VFSTOUFS(mp)->um_fs;
+ if (ufhp->ufid_ino < ROOTINO ||
+ ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) {
+ *vpp = (struct vnode *)0;
+ return (EINVAL);
+ }
+ tvp.v_mount = mp;
+ ip = VTOI(&tvp);
+ ip->i_vnode = &tvp;
+ ip->i_dev = VFSTOUFS(mp)->um_dev;
+ if (error = iget(ip, ufhp->ufid_ino, &nip)) {
+ *vpp = (struct vnode *)0;
return (error);
}
+ ip = nip;
+ if (ip->i_mode == 0) {
+ iput(ip);
+ *vpp = (struct vnode *)0;
+ return (EINVAL);
+ }
if (ip->i_gen != ufhp->ufid_gen) {
iput(ip);
- *vpp = NULL;
+ *vpp = (struct vnode *)0;
return (EINVAL);
}
*vpp = ITOV(ip);
vput(vp);
return (ENOTBLK);
}
- if (major(vp->v_rdev) >= nblkdev)
+ if (major(vp->v_rdev) >= nblkdev) {
+ vput(vp);
return (ENXIO);
+ }
iunlock(VTOI(vp));
*devvpp = vp;
return (0);