139018Smckusick /* 241111Skarels * Copyright (c) 1989, 1990 The Regents of the University of California. 339018Smckusick * All rights reserved. 439018Smckusick * 544536Sbostic * %sccs.include.redist.c% 639018Smckusick * 7*53534Sheideman * @(#)mfs_vfsops.c 7.25 (Berkeley) 05/14/92 839018Smckusick */ 939018Smckusick 1051476Sbostic #include <sys/param.h> 1153198Sralph #include <sys/systm.h> 1251476Sbostic #include <sys/time.h> 1351476Sbostic #include <sys/kernel.h> 1451476Sbostic #include <sys/proc.h> 1551476Sbostic #include <sys/buf.h> 1651476Sbostic #include <sys/mount.h> 1751476Sbostic #include <sys/signalvar.h> 1851476Sbostic #include <sys/vnode.h> 1951980Smckusick #include <sys/malloc.h> 2039018Smckusick 2151476Sbostic #include <ufs/ufs/quota.h> 2251476Sbostic #include <ufs/ufs/inode.h> 2351476Sbostic #include <ufs/ufs/ufsmount.h> 2451476Sbostic #include <ufs/ufs/ufs_extern.h> 2547571Skarels 2651476Sbostic #include <ufs/ffs/fs.h> 2751476Sbostic #include <ufs/ffs/ffs_extern.h> 2851476Sbostic 2951476Sbostic #include <ufs/mfs/mfsnode.h> 3051476Sbostic #include <ufs/mfs/mfs_extern.h> 3151476Sbostic 3253043Sralph caddr_t mfs_rootbase; /* address of mini-root in kernel virtual memory */ 3353043Sralph u_long mfs_rootsize; /* size of mini-root in bytes */ 3453043Sralph 3553198Sralph static int mfs_minor; /* used for building internal dev_t */ 3653198Sralph 37*53534Sheideman extern int (**mfs_vnodeop_p)(); 3839018Smckusick 3939018Smckusick /* 4039018Smckusick * mfs vfs operations. 4139018Smckusick */ 4239018Smckusick struct vfsops mfs_vfsops = { 4339018Smckusick mfs_mount, 4439018Smckusick mfs_start, 4551476Sbostic ffs_unmount, 4651571Smckusick ffs_root, 4741311Smckusick ufs_quotactl, 4839605Smckusick mfs_statfs, 4951476Sbostic ffs_sync, 5051571Smckusick ffs_fhtovp, 5151571Smckusick ffs_vptofh, 5239439Smckusick mfs_init, 5339018Smckusick }; 5439018Smckusick 5539018Smckusick /* 5653043Sralph * Called by main() when mfs is going to be mounted as root. 5753043Sralph * 5853043Sralph * Name is updated by mount(8) after booting. 5953043Sralph */ 6053198Sralph #define ROOTNAME "mfs_root" 6153043Sralph 6253043Sralph mfs_mountroot() 6353043Sralph { 6453043Sralph extern struct vnode *rootvp; 6553043Sralph register struct fs *fs; 6653043Sralph register struct mount *mp; 6753043Sralph struct proc *p = curproc; /* XXX */ 6853043Sralph struct ufsmount *ump; 6953043Sralph struct mfsnode *mfsp; 7053043Sralph u_int size; 7153043Sralph int error; 7253043Sralph 7353043Sralph mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK); 7453043Sralph mp->mnt_op = &mfs_vfsops; 7553043Sralph mp->mnt_flag = MNT_RDONLY; 7653043Sralph mp->mnt_mounth = NULLVP; 7753043Sralph mfsp = malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK); 7853043Sralph rootvp->v_data = mfsp; 79*53534Sheideman rootvp->v_op = mfs_vnodeop_p; 8053198Sralph rootvp->v_tag = VT_MFS; 8153043Sralph mfsp->mfs_baseoff = mfs_rootbase; 8253043Sralph mfsp->mfs_size = mfs_rootsize; 8353043Sralph mfsp->mfs_vnode = rootvp; 8453043Sralph mfsp->mfs_pid = p->p_pid; 8553043Sralph mfsp->mfs_buflist = (struct buf *)0; 8653043Sralph if (error = ffs_mountfs(rootvp, mp, p)) { 8753043Sralph free(mp, M_MOUNT); 8853043Sralph free(mfsp, M_MFSNODE); 8953043Sralph return (error); 9053043Sralph } 9153043Sralph if (error = vfs_lock(mp)) { 9253043Sralph (void)ffs_unmount(mp, 0, p); 9353043Sralph free(mp, M_MOUNT); 9453043Sralph free(mfsp, M_MFSNODE); 9553043Sralph return (error); 9653043Sralph } 9753043Sralph rootfs = mp; 9853043Sralph mp->mnt_next = mp; 9953043Sralph mp->mnt_prev = mp; 10053043Sralph mp->mnt_vnodecovered = NULLVP; 10153043Sralph ump = VFSTOUFS(mp); 10253043Sralph fs = ump->um_fs; 10353043Sralph bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt)); 10453043Sralph fs->fs_fsmnt[0] = '/'; 10553043Sralph bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 10653043Sralph MNAMELEN); 10753043Sralph (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 10853043Sralph &size); 10953043Sralph bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 11053043Sralph (void)ffs_statfs(mp, &mp->mnt_stat, p); 11153043Sralph vfs_unlock(mp); 11253043Sralph inittodr((time_t)0); 11353043Sralph return (0); 11453043Sralph } 11553043Sralph 11653043Sralph /* 11753043Sralph * This is called early in boot to set the base address and size 11853043Sralph * of the mini-root. 11953043Sralph */ 12053043Sralph mfs_initminiroot(base) 12153043Sralph caddr_t base; 12253043Sralph { 12353043Sralph struct fs *fs = (struct fs *)(base + SBOFF); 12453043Sralph extern int (*mountroot)(); 12553043Sralph 12653043Sralph /* check for valid super block */ 12753043Sralph if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || 12853043Sralph fs->fs_bsize < sizeof(struct fs)) 12953043Sralph return (0); 13053043Sralph mountroot = mfs_mountroot; 13153043Sralph mfs_rootbase = base; 13253043Sralph mfs_rootsize = fs->fs_fsize * fs->fs_size; 13353198Sralph rootdev = makedev(255, mfs_minor++); 13453043Sralph return (mfs_rootsize); 13553043Sralph } 13653043Sralph 13753043Sralph /* 13839018Smckusick * VFS Operations. 13939018Smckusick * 14039018Smckusick * mount system call 14139018Smckusick */ 14239389Smckusick /* ARGSUSED */ 14351476Sbostic int 14448040Smckusick mfs_mount(mp, path, data, ndp, p) 14540347Smckusick register struct mount *mp; 14639018Smckusick char *path; 14739018Smckusick caddr_t data; 14839018Smckusick struct nameidata *ndp; 14948040Smckusick struct proc *p; 15039018Smckusick { 15139018Smckusick struct vnode *devvp; 15239018Smckusick struct mfs_args args; 15339018Smckusick struct ufsmount *ump; 15439018Smckusick register struct fs *fs; 15539389Smckusick register struct mfsnode *mfsp; 15639018Smckusick u_int size; 15739018Smckusick int error; 15839018Smckusick 15941397Smckusick if (mp->mnt_flag & MNT_UPDATE) { 16039337Smckusick ump = VFSTOUFS(mp); 16139337Smckusick fs = ump->um_fs; 16241397Smckusick if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0) 16339337Smckusick fs->fs_ronly = 0; 16439337Smckusick return (0); 16539337Smckusick } 16639018Smckusick if (error = copyin(data, (caddr_t)&args, sizeof (struct mfs_args))) 16739018Smckusick return (error); 168*53534Sheideman error = getnewvnode(VT_MFS, (struct mount *)0, mfs_vnodeop_p, &devvp); 16939389Smckusick if (error) 17039018Smckusick return (error); 17139389Smckusick devvp->v_type = VBLK; 17239616Smckusick if (checkalias(devvp, makedev(255, mfs_minor++), (struct mount *)0)) 17339439Smckusick panic("mfs_mount: dup dev"); 17451980Smckusick mfsp = (struct mfsnode *)malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK); 17551980Smckusick devvp->v_data = mfsp; 17639389Smckusick mfsp->mfs_baseoff = args.base; 17739389Smckusick mfsp->mfs_size = args.size; 17839389Smckusick mfsp->mfs_vnode = devvp; 17948040Smckusick mfsp->mfs_pid = p->p_pid; 18039389Smckusick mfsp->mfs_buflist = (struct buf *)0; 18151476Sbostic if (error = ffs_mountfs(devvp, mp, p)) { 18240877Smckusick mfsp->mfs_buflist = (struct buf *)-1; 18339018Smckusick vrele(devvp); 18439018Smckusick return (error); 18539018Smckusick } 18639018Smckusick ump = VFSTOUFS(mp); 18739018Smckusick fs = ump->um_fs; 18839018Smckusick (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); 18939018Smckusick bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); 19041397Smckusick bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 19141397Smckusick MNAMELEN); 19241397Smckusick (void) copyinstr(args.name, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 19340347Smckusick &size); 19441397Smckusick bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 19551476Sbostic (void) mfs_statfs(mp, &mp->mnt_stat, p); 19639018Smckusick return (0); 19739018Smckusick } 19839018Smckusick 19941111Skarels int mfs_pri = PWAIT | PCATCH; /* XXX prob. temp */ 20041111Skarels 20139018Smckusick /* 20239018Smckusick * Used to grab the process and keep it in the kernel to service 20339018Smckusick * memory filesystem I/O requests. 20439018Smckusick * 20539018Smckusick * Loop servicing I/O requests. 20639018Smckusick * Copy the requested data into or out of the memory filesystem 20739018Smckusick * address space. 20839018Smckusick */ 20939018Smckusick /* ARGSUSED */ 21051476Sbostic int 21148040Smckusick mfs_start(mp, flags, p) 21239018Smckusick struct mount *mp; 21339018Smckusick int flags; 21448040Smckusick struct proc *p; 21539018Smckusick { 21639018Smckusick register struct vnode *vp = VFSTOUFS(mp)->um_devvp; 21739389Smckusick register struct mfsnode *mfsp = VTOMFS(vp); 21839018Smckusick register struct buf *bp; 21939018Smckusick register caddr_t base; 22041111Skarels int error = 0; 22139018Smckusick 22239389Smckusick base = mfsp->mfs_baseoff; 22339389Smckusick while (mfsp->mfs_buflist != (struct buf *)(-1)) { 22439389Smckusick while (bp = mfsp->mfs_buflist) { 22539389Smckusick mfsp->mfs_buflist = bp->av_forw; 22639357Smckusick mfs_doio(bp, base); 22739357Smckusick wakeup((caddr_t)bp); 22839357Smckusick } 22944331Skarels /* 23044331Skarels * If a non-ignored signal is received, try to unmount. 23144331Skarels * If that fails, clear the signal (it has been "processed"), 23244331Skarels * otherwise we will loop here, as tsleep will always return 23344331Skarels * EINTR/ERESTART. 23444331Skarels */ 23544331Skarels if (error = tsleep((caddr_t)vp, mfs_pri, "mfsidl", 0)) 23648040Smckusick if (dounmount(mp, MNT_NOFORCE, p) != 0) 23744331Skarels CLRSIG(p, CURSIG(p)); 23839357Smckusick } 23941111Skarels return (error); 24039018Smckusick } 24139605Smckusick 24239605Smckusick /* 24339605Smckusick * Get file system statistics. 24439605Smckusick */ 24548040Smckusick mfs_statfs(mp, sbp, p) 24639605Smckusick struct mount *mp; 24739605Smckusick struct statfs *sbp; 24848040Smckusick struct proc *p; 24939605Smckusick { 25039605Smckusick int error; 25139605Smckusick 25251476Sbostic error = ffs_statfs(mp, sbp, p); 25339605Smckusick sbp->f_type = MOUNT_MFS; 25439605Smckusick return (error); 25539605Smckusick } 256