243 lines
5.2 KiB
C
243 lines
5.2 KiB
C
|
|
/* @(#)vfs.c 1.1 92/07/30 SMI */
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/user.h>
|
|
#include <sys/uio.h>
|
|
#include <sys/file.h>
|
|
#include <sys/vfs.h>
|
|
#undef KERNEL
|
|
#include <sys/socket.h>
|
|
#include "boot/systm.h"
|
|
#define KERNEL
|
|
#undef NFS
|
|
#include <sys/mount.h>
|
|
#undef KERNEL
|
|
#include <sys/pathname.h>
|
|
#define KERNEL
|
|
#include "boot/vnode.h"
|
|
#ifdef UFS
|
|
#include "boot/inode.h"
|
|
#endif
|
|
#include <sys/bootconf.h>
|
|
|
|
#include <stand/saio.h>
|
|
|
|
#undef u
|
|
struct user u;
|
|
static struct proc _p;
|
|
|
|
/*
|
|
* vfs global data
|
|
*/
|
|
struct vnode *rootdir; /* pointer to root vnode */
|
|
|
|
struct vfs *rootvfs; /* pointer to root vfs. This is */
|
|
/* also the head of the vfs list */
|
|
/*
|
|
* Convert mode formats to vnode types
|
|
*/
|
|
enum vtype mftovt_tab[] = {
|
|
VFIFO, VCHR, VDIR, VBLK, VREG, VLNK, VSOCK, VBAD
|
|
};
|
|
|
|
static int dump_debug = 10;
|
|
extern struct vfssw *getfstype();
|
|
|
|
|
|
/*
|
|
* vfs_mountroot is called by main (boot.c) to
|
|
* mount the root filesystem.
|
|
*/
|
|
void
|
|
vfs_mountroot()
|
|
{
|
|
register int error;
|
|
struct vfssw *vsw;
|
|
|
|
u.u_error = 0;
|
|
|
|
if (rootvfs != (struct vfs *)0) {
|
|
printf("root on %s fstype %s\n",
|
|
rootfs.bo_name, rootfs.bo_fstype);
|
|
return;
|
|
}
|
|
/*
|
|
* Setup credentials
|
|
*/
|
|
u.u_procp = &_p;
|
|
u.u_cred = crget();
|
|
u.u_uid = 0; /* root user */
|
|
u.u_gid = 1; /* root group */
|
|
u.u_groups[0] = 1; /* root group */
|
|
u.u_groups[1] = -1; /* end of groups */
|
|
u.u_groups[2] = -1; /* end of groups */
|
|
u.u_groups[3] = -1; /* end of groups */
|
|
u.u_groups[4] = -1; /* end of groups */
|
|
u.u_groups[5] = -1; /* end of groups */
|
|
u.u_groups[6] = -1; /* end of groups */
|
|
u.u_groups[7] = -1; /* end of groups */
|
|
|
|
u.u_ruid = 0; /* root user */
|
|
u.u_rgid = 1; /* root group */
|
|
u.u_groups[1] = -1; /* end of groups */
|
|
|
|
rootvfs = (struct vfs *)kmem_alloc(sizeof (struct vfs));
|
|
vsw = getfstype("root", rootfs.bo_fstype);
|
|
if (vsw) {
|
|
VFS_INIT(rootvfs, vsw->vsw_ops, (caddr_t)0);
|
|
error = VFS_MOUNTROOT(rootvfs, &rootvp, rootfs.bo_name);
|
|
} else {
|
|
|
|
/*
|
|
* Step through the filesystem types til we find one that
|
|
* will mount a root filesystem.
|
|
* If error panic.
|
|
*/
|
|
for (vsw = vfssw; vsw <= &vfssw[MOUNT_MAXTYPE]; vsw++){
|
|
if (vsw->vsw_ops) {
|
|
VFS_INIT(rootvfs, vsw->vsw_ops, (caddr_t)0);
|
|
error = VFS_MOUNTROOT(rootvfs, &rootvp,
|
|
rootfs.bo_name);
|
|
if (!error) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (error) {
|
|
printf("Boot: unable to mount root (error 0x%x)\n", error);
|
|
kmem_free(rootvfs, sizeof (struct vfs));
|
|
rootvfs = (struct vfs *)0;
|
|
u.u_error = error;
|
|
return;
|
|
} else {
|
|
#ifdef DUMP_DEBUG
|
|
dprint(dump_debug, 6,
|
|
"vfs_mountroot: mounted root rootvfs 0x%x\n",
|
|
rootvfs);
|
|
#endif /* DUMP_DEBUG */
|
|
}
|
|
|
|
/*
|
|
* Get vnode for '/'.
|
|
* Setup rootdir, u.u_rdir and u.u_cdir to point to it.
|
|
* These are used by lookuppn so that it knows where
|
|
* to start from '/' or '.'.
|
|
*/
|
|
error = VFS_ROOT(rootvfs, &rootdir);
|
|
if (error) {
|
|
printf("Boot: cannot get root vnode (error 0x%x)\n", error);
|
|
u.u_error = error;
|
|
return;
|
|
}
|
|
u.u_cdir = rootdir;
|
|
VN_HOLD(u.u_cdir);
|
|
/*
|
|
* I needed the root vnode here.
|
|
*/
|
|
u.u_rdir = rootdir;
|
|
rootfs.bo_vp = rootvp;
|
|
(void) strcpy(rootfs.bo_fstype, vsw->vsw_name);
|
|
rootfs.bo_size = 0;
|
|
rootfs.bo_flags = BO_VALID;
|
|
|
|
printf("root on %s fstype %s\n", rootfs.bo_name, rootfs.bo_fstype);
|
|
|
|
}
|
|
|
|
/*
|
|
* vfs_add is called by a specific filesystem's mount routine to add
|
|
* the new vfs into the vfs list and to cover the mounted on vnode.
|
|
* The vfs is also locked so that lookuppn will not venture into the
|
|
* covered vnodes subtree.
|
|
* coveredvp is zero if this is the root.
|
|
*/
|
|
int
|
|
vfs_add(coveredvp, vfsp, mflag)
|
|
register struct vnode *coveredvp;
|
|
register struct vfs *vfsp;
|
|
int mflag;
|
|
{
|
|
register int error;
|
|
|
|
error = vfs_lock(vfsp);
|
|
if (error)
|
|
return (error);
|
|
if (coveredvp != (struct vnode *)0) {
|
|
/*
|
|
* Return EBUSY if the covered vp is already mounted on.
|
|
*/
|
|
if (coveredvp->v_vfsmountedhere != (struct vfs *)0) {
|
|
printf("Boot: root vnode busy\n");
|
|
vfs_unlock(vfsp);
|
|
return (EBUSY);
|
|
}
|
|
/*
|
|
* Put the new vfs on the vfs list after root.
|
|
* Point the covered vnode at the new vfs so lookuppn
|
|
* (vfs_lookup.c) can work its way into the new file system.
|
|
*/
|
|
vfsp->vfs_next = rootvfs->vfs_next;
|
|
rootvfs->vfs_next = vfsp;
|
|
coveredvp->v_vfsmountedhere = vfsp;
|
|
} else {
|
|
dprint(dump_debug, 6, "vfs_add: real root\n");
|
|
/*
|
|
* This is the root of the whole world.
|
|
*/
|
|
rootvfs = vfsp;
|
|
vfsp->vfs_next = (struct vfs *)0;
|
|
}
|
|
vfsp->vfs_vnodecovered = coveredvp;
|
|
if (mflag & M_RDONLY) {
|
|
vfsp->vfs_flag |= VFS_RDONLY;
|
|
} else {
|
|
vfsp->vfs_flag &= ~VFS_RDONLY;
|
|
}
|
|
if (mflag & M_NOSUID) {
|
|
vfsp->vfs_flag |= VFS_NOSUID;
|
|
} else {
|
|
vfsp->vfs_flag &= ~VFS_NOSUID;
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* Lock a filesystem to prevent access to it while mounting and unmounting.
|
|
* Returns error if already locked.
|
|
* XXX This totally inadequate for unmount right now - srk
|
|
*/
|
|
int
|
|
vfs_lock(vfsp)
|
|
register struct vfs *vfsp;
|
|
{
|
|
|
|
if (vfsp->vfs_flag & VFS_MLOCK)
|
|
return (EBUSY);
|
|
vfsp->vfs_flag |= VFS_MLOCK;
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* Unlock a locked filesystem.
|
|
* Panics if not locked
|
|
*/
|
|
void
|
|
vfs_unlock(vfsp)
|
|
register struct vfs *vfsp;
|
|
{
|
|
|
|
if ((vfsp->vfs_flag & VFS_MLOCK) == 0)
|
|
panic("vfs_unlock");
|
|
vfsp->vfs_flag &= ~VFS_MLOCK;
|
|
/*
|
|
* Wake anybody waiting for the lock to clear
|
|
*/
|
|
if (vfsp->vfs_flag & VFS_MWAIT) {
|
|
vfsp->vfs_flag &= ~VFS_MWAIT;
|
|
wakeup((caddr_t)vfsp);
|
|
}
|
|
}
|