139018Smckusick /* 266804Sbostic * Copyright (c) 1989, 1990, 1993, 1994 363375Sbostic * The Regents of the University of California. All rights reserved. 439018Smckusick * 544536Sbostic * %sccs.include.redist.c% 639018Smckusick * 7*69583Smckusick * @(#)mfs_vfsops.c 8.10 (Berkeley) 05/20/95 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, 4666804Sbostic ufs_root, 4741311Smckusick ufs_quotactl, 4839605Smckusick mfs_statfs, 4951476Sbostic ffs_sync, 5054661Smckusick ffs_vget, 5151571Smckusick ffs_fhtovp, 5251571Smckusick ffs_vptofh, 5339439Smckusick mfs_init, 5468679Smckusick ffs_sysctl, 5539018Smckusick }; 5639018Smckusick 5739018Smckusick /* 5853043Sralph * Called by main() when mfs is going to be mounted as root. 5953043Sralph */ 6053043Sralph mfs_mountroot() 6153043Sralph { 6253043Sralph extern struct vnode *rootvp; 6369367Smckusick struct fs *fs; 6469367Smckusick struct mount *mp; 6553043Sralph struct proc *p = curproc; /* XXX */ 6653043Sralph struct ufsmount *ump; 6753043Sralph struct mfsnode *mfsp; 6853043Sralph int error; 6953043Sralph 7056333Smckusick /* 7156333Smckusick * Get vnodes for swapdev and rootdev. 7256333Smckusick */ 7369374Smckusick if ((error = bdevvp(swapdev, &swapdev_vp)) || 7469374Smckusick (error = bdevvp(rootdev, &rootvp))) { 7569374Smckusick printf("mfs_mountroot: can't setup bdevvp's"); 7669374Smckusick return (error); 7769374Smckusick } 7869367Smckusick if (error = vfs_rootmountalloc("mfs", "mfs_root", &mp)) 7969367Smckusick return (error); 8053043Sralph mfsp = malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK); 8153043Sralph rootvp->v_data = mfsp; 8253534Sheideman rootvp->v_op = mfs_vnodeop_p; 8353198Sralph rootvp->v_tag = VT_MFS; 8453043Sralph mfsp->mfs_baseoff = mfs_rootbase; 8553043Sralph mfsp->mfs_size = mfs_rootsize; 8653043Sralph mfsp->mfs_vnode = rootvp; 8753043Sralph mfsp->mfs_pid = p->p_pid; 8853043Sralph mfsp->mfs_buflist = (struct buf *)0; 8953043Sralph if (error = ffs_mountfs(rootvp, mp, p)) { 9069367Smckusick mp->mnt_vfc->vfc_refcount--; 91*69583Smckusick vfs_unbusy(mp, p); 9253043Sralph free(mp, M_MOUNT); 9353043Sralph free(mfsp, M_MFSNODE); 9453043Sralph return (error); 9553043Sralph } 96*69583Smckusick simple_lock(&mountlist_slock); 9769317Smckusick CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); 98*69583Smckusick simple_unlock(&mountlist_slock); 9953043Sralph ump = VFSTOUFS(mp); 10053043Sralph fs = ump->um_fs; 10169367Smckusick (void) copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0); 10253043Sralph (void)ffs_statfs(mp, &mp->mnt_stat, p); 103*69583Smckusick vfs_unbusy(mp, p); 10453043Sralph inittodr((time_t)0); 10553043Sralph return (0); 10653043Sralph } 10753043Sralph 10853043Sralph /* 10953043Sralph * This is called early in boot to set the base address and size 11053043Sralph * of the mini-root. 11153043Sralph */ 11253043Sralph mfs_initminiroot(base) 11353043Sralph caddr_t base; 11453043Sralph { 11553043Sralph struct fs *fs = (struct fs *)(base + SBOFF); 11653043Sralph extern int (*mountroot)(); 11753043Sralph 11853043Sralph /* check for valid super block */ 11953043Sralph if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || 12053043Sralph fs->fs_bsize < sizeof(struct fs)) 12153043Sralph return (0); 12253043Sralph mountroot = mfs_mountroot; 12353043Sralph mfs_rootbase = base; 12453043Sralph mfs_rootsize = fs->fs_fsize * fs->fs_size; 12553198Sralph rootdev = makedev(255, mfs_minor++); 12653043Sralph return (mfs_rootsize); 12753043Sralph } 12853043Sralph 12953043Sralph /* 13039018Smckusick * VFS Operations. 13139018Smckusick * 13239018Smckusick * mount system call 13339018Smckusick */ 13439389Smckusick /* ARGSUSED */ 13551476Sbostic int 13648040Smckusick mfs_mount(mp, path, data, ndp, p) 13740347Smckusick register struct mount *mp; 13839018Smckusick char *path; 13939018Smckusick caddr_t data; 14039018Smckusick struct nameidata *ndp; 14148040Smckusick struct proc *p; 14239018Smckusick { 14339018Smckusick struct vnode *devvp; 14439018Smckusick struct mfs_args args; 14539018Smckusick struct ufsmount *ump; 14639018Smckusick register struct fs *fs; 14739389Smckusick register struct mfsnode *mfsp; 14839018Smckusick u_int size; 14957054Smckusick int flags, error; 15039018Smckusick 15165675Shibler if (error = copyin(data, (caddr_t)&args, sizeof (struct mfs_args))) 15265675Shibler return (error); 15365675Shibler 15457054Smckusick /* 15557054Smckusick * If updating, check whether changing from read-only to 15657054Smckusick * read/write; if there is no device name, that's all we do. 15757054Smckusick */ 15841397Smckusick if (mp->mnt_flag & MNT_UPDATE) { 15939337Smckusick ump = VFSTOUFS(mp); 16039337Smckusick fs = ump->um_fs; 16157054Smckusick if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) { 16257054Smckusick flags = WRITECLOSE; 16357054Smckusick if (mp->mnt_flag & MNT_FORCE) 16457054Smckusick flags |= FORCECLOSE; 165*69583Smckusick if (error = ffs_flushfiles(mp, flags, p)) 16657054Smckusick return (error); 16757054Smckusick } 16857054Smckusick if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) 16939337Smckusick fs->fs_ronly = 0; 17065675Shibler #ifdef EXPORTMFS 17165675Shibler if (args.fspec == 0) 17265675Shibler return (vfs_export(mp, &ump->um_export, &args.export)); 17365675Shibler #endif 17439337Smckusick return (0); 17539337Smckusick } 17653534Sheideman error = getnewvnode(VT_MFS, (struct mount *)0, mfs_vnodeop_p, &devvp); 17739389Smckusick if (error) 17839018Smckusick return (error); 17939389Smckusick devvp->v_type = VBLK; 18039616Smckusick if (checkalias(devvp, makedev(255, mfs_minor++), (struct mount *)0)) 18139439Smckusick panic("mfs_mount: dup dev"); 18251980Smckusick mfsp = (struct mfsnode *)malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK); 18351980Smckusick devvp->v_data = mfsp; 18439389Smckusick mfsp->mfs_baseoff = args.base; 18539389Smckusick mfsp->mfs_size = args.size; 18639389Smckusick mfsp->mfs_vnode = devvp; 18748040Smckusick mfsp->mfs_pid = p->p_pid; 18839389Smckusick mfsp->mfs_buflist = (struct buf *)0; 18951476Sbostic if (error = ffs_mountfs(devvp, mp, p)) { 19040877Smckusick mfsp->mfs_buflist = (struct buf *)-1; 19139018Smckusick vrele(devvp); 19239018Smckusick return (error); 19339018Smckusick } 19439018Smckusick ump = VFSTOUFS(mp); 19539018Smckusick fs = ump->um_fs; 19639018Smckusick (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); 19739018Smckusick bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); 19841397Smckusick bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 19941397Smckusick MNAMELEN); 20065675Shibler (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 20140347Smckusick &size); 20241397Smckusick bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 20351476Sbostic (void) mfs_statfs(mp, &mp->mnt_stat, p); 20439018Smckusick return (0); 20539018Smckusick } 20639018Smckusick 20741111Skarels int mfs_pri = PWAIT | PCATCH; /* XXX prob. temp */ 20841111Skarels 20939018Smckusick /* 21039018Smckusick * Used to grab the process and keep it in the kernel to service 21139018Smckusick * memory filesystem I/O requests. 21239018Smckusick * 21339018Smckusick * Loop servicing I/O requests. 21439018Smckusick * Copy the requested data into or out of the memory filesystem 21539018Smckusick * address space. 21639018Smckusick */ 21739018Smckusick /* ARGSUSED */ 21851476Sbostic int 21948040Smckusick mfs_start(mp, flags, p) 22039018Smckusick struct mount *mp; 22139018Smckusick int flags; 22248040Smckusick struct proc *p; 22339018Smckusick { 22439018Smckusick register struct vnode *vp = VFSTOUFS(mp)->um_devvp; 22539389Smckusick register struct mfsnode *mfsp = VTOMFS(vp); 22639018Smckusick register struct buf *bp; 22739018Smckusick register caddr_t base; 22841111Skarels int error = 0; 22939018Smckusick 23039389Smckusick base = mfsp->mfs_baseoff; 23139389Smckusick while (mfsp->mfs_buflist != (struct buf *)(-1)) { 23239389Smckusick while (bp = mfsp->mfs_buflist) { 23356392Smckusick mfsp->mfs_buflist = bp->b_actf; 23439357Smckusick mfs_doio(bp, base); 23539357Smckusick wakeup((caddr_t)bp); 23639357Smckusick } 23744331Skarels /* 23844331Skarels * If a non-ignored signal is received, try to unmount. 23944331Skarels * If that fails, clear the signal (it has been "processed"), 24044331Skarels * otherwise we will loop here, as tsleep will always return 24144331Skarels * EINTR/ERESTART. 24244331Skarels */ 24344331Skarels if (error = tsleep((caddr_t)vp, mfs_pri, "mfsidl", 0)) 24456840Smckusick if (dounmount(mp, 0, p) != 0) 24544331Skarels CLRSIG(p, CURSIG(p)); 24639357Smckusick } 24741111Skarels return (error); 24839018Smckusick } 24939605Smckusick 25039605Smckusick /* 25139605Smckusick * Get file system statistics. 25239605Smckusick */ 25348040Smckusick mfs_statfs(mp, sbp, p) 25439605Smckusick struct mount *mp; 25539605Smckusick struct statfs *sbp; 25648040Smckusick struct proc *p; 25739605Smckusick { 25839605Smckusick int error; 25939605Smckusick 26051476Sbostic error = ffs_statfs(mp, sbp, p); 26168679Smckusick sbp->f_type = mp->mnt_vfc->vfc_typenum; 26239605Smckusick return (error); 26339605Smckusick } 264