139018Smckusick /* 263375Sbostic * Copyright (c) 1989, 1990, 1993 363375Sbostic * The Regents of the University of California. All rights reserved. 439018Smckusick * 544536Sbostic * %sccs.include.redist.c% 639018Smckusick * 7*65675Shibler * @(#)mfs_vfsops.c 8.3 (Berkeley) 01/12/94 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 3753534Sheideman 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, 5054661Smckusick ffs_vget, 5151571Smckusick ffs_fhtovp, 5251571Smckusick ffs_vptofh, 5339439Smckusick mfs_init, 5439018Smckusick }; 5539018Smckusick 5639018Smckusick /* 5753043Sralph * Called by main() when mfs is going to be mounted as root. 5853043Sralph * 5953043Sralph * Name is updated by mount(8) after booting. 6053043Sralph */ 6153198Sralph #define ROOTNAME "mfs_root" 6253043Sralph 6353043Sralph mfs_mountroot() 6453043Sralph { 6553043Sralph extern struct vnode *rootvp; 6653043Sralph register struct fs *fs; 6753043Sralph register struct mount *mp; 6853043Sralph struct proc *p = curproc; /* XXX */ 6953043Sralph struct ufsmount *ump; 7053043Sralph struct mfsnode *mfsp; 7153043Sralph u_int size; 7253043Sralph int error; 7353043Sralph 7456333Smckusick /* 7556333Smckusick * Get vnodes for swapdev and rootdev. 7656333Smckusick */ 7756333Smckusick if (bdevvp(swapdev, &swapdev_vp) || bdevvp(rootdev, &rootvp)) 7856333Smckusick panic("mfs_mountroot: can't setup bdevvp's"); 7956333Smckusick 8053043Sralph mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK); 8165243Smckusick bzero((char *)mp, (u_long)sizeof(struct mount)); 8253043Sralph mp->mnt_op = &mfs_vfsops; 8353043Sralph mp->mnt_flag = MNT_RDONLY; 8453043Sralph mfsp = malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK); 8553043Sralph rootvp->v_data = mfsp; 8653534Sheideman rootvp->v_op = mfs_vnodeop_p; 8753198Sralph rootvp->v_tag = VT_MFS; 8853043Sralph mfsp->mfs_baseoff = mfs_rootbase; 8953043Sralph mfsp->mfs_size = mfs_rootsize; 9053043Sralph mfsp->mfs_vnode = rootvp; 9153043Sralph mfsp->mfs_pid = p->p_pid; 9253043Sralph mfsp->mfs_buflist = (struct buf *)0; 9353043Sralph if (error = ffs_mountfs(rootvp, mp, p)) { 9453043Sralph free(mp, M_MOUNT); 9553043Sralph free(mfsp, M_MFSNODE); 9653043Sralph return (error); 9753043Sralph } 9853043Sralph if (error = vfs_lock(mp)) { 9953043Sralph (void)ffs_unmount(mp, 0, p); 10053043Sralph free(mp, M_MOUNT); 10153043Sralph free(mfsp, M_MFSNODE); 10253043Sralph return (error); 10353043Sralph } 10465243Smckusick TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list); 10565243Smckusick mp->mnt_flag |= MNT_ROOTFS; 10653043Sralph mp->mnt_vnodecovered = NULLVP; 10753043Sralph ump = VFSTOUFS(mp); 10853043Sralph fs = ump->um_fs; 10953043Sralph bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt)); 11053043Sralph fs->fs_fsmnt[0] = '/'; 11153043Sralph bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 11253043Sralph MNAMELEN); 11353043Sralph (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 11453043Sralph &size); 11553043Sralph bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 11653043Sralph (void)ffs_statfs(mp, &mp->mnt_stat, p); 11753043Sralph vfs_unlock(mp); 11853043Sralph inittodr((time_t)0); 11953043Sralph return (0); 12053043Sralph } 12153043Sralph 12253043Sralph /* 12353043Sralph * This is called early in boot to set the base address and size 12453043Sralph * of the mini-root. 12553043Sralph */ 12653043Sralph mfs_initminiroot(base) 12753043Sralph caddr_t base; 12853043Sralph { 12953043Sralph struct fs *fs = (struct fs *)(base + SBOFF); 13053043Sralph extern int (*mountroot)(); 13153043Sralph 13253043Sralph /* check for valid super block */ 13353043Sralph if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || 13453043Sralph fs->fs_bsize < sizeof(struct fs)) 13553043Sralph return (0); 13653043Sralph mountroot = mfs_mountroot; 13753043Sralph mfs_rootbase = base; 13853043Sralph mfs_rootsize = fs->fs_fsize * fs->fs_size; 13953198Sralph rootdev = makedev(255, mfs_minor++); 14053043Sralph return (mfs_rootsize); 14153043Sralph } 14253043Sralph 14353043Sralph /* 14439018Smckusick * VFS Operations. 14539018Smckusick * 14639018Smckusick * mount system call 14739018Smckusick */ 14839389Smckusick /* ARGSUSED */ 14951476Sbostic int 15048040Smckusick mfs_mount(mp, path, data, ndp, p) 15140347Smckusick register struct mount *mp; 15239018Smckusick char *path; 15339018Smckusick caddr_t data; 15439018Smckusick struct nameidata *ndp; 15548040Smckusick struct proc *p; 15639018Smckusick { 15739018Smckusick struct vnode *devvp; 15839018Smckusick struct mfs_args args; 15939018Smckusick struct ufsmount *ump; 16039018Smckusick register struct fs *fs; 16139389Smckusick register struct mfsnode *mfsp; 16239018Smckusick u_int size; 16357054Smckusick int flags, error; 16439018Smckusick 165*65675Shibler if (error = copyin(data, (caddr_t)&args, sizeof (struct mfs_args))) 166*65675Shibler return (error); 167*65675Shibler 16857054Smckusick /* 16957054Smckusick * If updating, check whether changing from read-only to 17057054Smckusick * read/write; if there is no device name, that's all we do. 17157054Smckusick */ 17241397Smckusick if (mp->mnt_flag & MNT_UPDATE) { 17339337Smckusick ump = VFSTOUFS(mp); 17439337Smckusick fs = ump->um_fs; 17557054Smckusick if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) { 17657054Smckusick flags = WRITECLOSE; 17757054Smckusick if (mp->mnt_flag & MNT_FORCE) 17857054Smckusick flags |= FORCECLOSE; 17957054Smckusick if (vfs_busy(mp)) 18057054Smckusick return (EBUSY); 18157054Smckusick error = ffs_flushfiles(mp, flags, p); 18257054Smckusick vfs_unbusy(mp); 18357054Smckusick if (error) 18457054Smckusick return (error); 18557054Smckusick } 18657054Smckusick if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) 18739337Smckusick fs->fs_ronly = 0; 188*65675Shibler #ifdef EXPORTMFS 189*65675Shibler if (args.fspec == 0) 190*65675Shibler return (vfs_export(mp, &ump->um_export, &args.export)); 191*65675Shibler #endif 19239337Smckusick return (0); 19339337Smckusick } 19453534Sheideman error = getnewvnode(VT_MFS, (struct mount *)0, mfs_vnodeop_p, &devvp); 19539389Smckusick if (error) 19639018Smckusick return (error); 19739389Smckusick devvp->v_type = VBLK; 19839616Smckusick if (checkalias(devvp, makedev(255, mfs_minor++), (struct mount *)0)) 19939439Smckusick panic("mfs_mount: dup dev"); 20051980Smckusick mfsp = (struct mfsnode *)malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK); 20151980Smckusick devvp->v_data = mfsp; 20239389Smckusick mfsp->mfs_baseoff = args.base; 20339389Smckusick mfsp->mfs_size = args.size; 20439389Smckusick mfsp->mfs_vnode = devvp; 20548040Smckusick mfsp->mfs_pid = p->p_pid; 20639389Smckusick mfsp->mfs_buflist = (struct buf *)0; 20751476Sbostic if (error = ffs_mountfs(devvp, mp, p)) { 20840877Smckusick mfsp->mfs_buflist = (struct buf *)-1; 20939018Smckusick vrele(devvp); 21039018Smckusick return (error); 21139018Smckusick } 21239018Smckusick ump = VFSTOUFS(mp); 21339018Smckusick fs = ump->um_fs; 21439018Smckusick (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); 21539018Smckusick bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); 21641397Smckusick bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 21741397Smckusick MNAMELEN); 218*65675Shibler (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 21940347Smckusick &size); 22041397Smckusick bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 22151476Sbostic (void) mfs_statfs(mp, &mp->mnt_stat, p); 22239018Smckusick return (0); 22339018Smckusick } 22439018Smckusick 22541111Skarels int mfs_pri = PWAIT | PCATCH; /* XXX prob. temp */ 22641111Skarels 22739018Smckusick /* 22839018Smckusick * Used to grab the process and keep it in the kernel to service 22939018Smckusick * memory filesystem I/O requests. 23039018Smckusick * 23139018Smckusick * Loop servicing I/O requests. 23239018Smckusick * Copy the requested data into or out of the memory filesystem 23339018Smckusick * address space. 23439018Smckusick */ 23539018Smckusick /* ARGSUSED */ 23651476Sbostic int 23748040Smckusick mfs_start(mp, flags, p) 23839018Smckusick struct mount *mp; 23939018Smckusick int flags; 24048040Smckusick struct proc *p; 24139018Smckusick { 24239018Smckusick register struct vnode *vp = VFSTOUFS(mp)->um_devvp; 24339389Smckusick register struct mfsnode *mfsp = VTOMFS(vp); 24439018Smckusick register struct buf *bp; 24539018Smckusick register caddr_t base; 24641111Skarels int error = 0; 24739018Smckusick 24839389Smckusick base = mfsp->mfs_baseoff; 24939389Smckusick while (mfsp->mfs_buflist != (struct buf *)(-1)) { 25039389Smckusick while (bp = mfsp->mfs_buflist) { 25156392Smckusick mfsp->mfs_buflist = bp->b_actf; 25239357Smckusick mfs_doio(bp, base); 25339357Smckusick wakeup((caddr_t)bp); 25439357Smckusick } 25544331Skarels /* 25644331Skarels * If a non-ignored signal is received, try to unmount. 25744331Skarels * If that fails, clear the signal (it has been "processed"), 25844331Skarels * otherwise we will loop here, as tsleep will always return 25944331Skarels * EINTR/ERESTART. 26044331Skarels */ 26144331Skarels if (error = tsleep((caddr_t)vp, mfs_pri, "mfsidl", 0)) 26256840Smckusick if (dounmount(mp, 0, p) != 0) 26344331Skarels CLRSIG(p, CURSIG(p)); 26439357Smckusick } 26541111Skarels return (error); 26639018Smckusick } 26739605Smckusick 26839605Smckusick /* 26939605Smckusick * Get file system statistics. 27039605Smckusick */ 27148040Smckusick mfs_statfs(mp, sbp, p) 27239605Smckusick struct mount *mp; 27339605Smckusick struct statfs *sbp; 27448040Smckusick struct proc *p; 27539605Smckusick { 27639605Smckusick int error; 27739605Smckusick 27851476Sbostic error = ffs_statfs(mp, sbp, p); 27939605Smckusick sbp->f_type = MOUNT_MFS; 28039605Smckusick return (error); 28139605Smckusick } 282