1 /* 2 * Copyright (c) 1989, 1990, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)mfs_vfsops.c 8.8 (Berkeley) 05/10/95 8 */ 9 10 #include <sys/param.h> 11 #include <sys/systm.h> 12 #include <sys/time.h> 13 #include <sys/kernel.h> 14 #include <sys/proc.h> 15 #include <sys/buf.h> 16 #include <sys/mount.h> 17 #include <sys/signalvar.h> 18 #include <sys/vnode.h> 19 #include <sys/malloc.h> 20 21 #include <ufs/ufs/quota.h> 22 #include <ufs/ufs/inode.h> 23 #include <ufs/ufs/ufsmount.h> 24 #include <ufs/ufs/ufs_extern.h> 25 26 #include <ufs/ffs/fs.h> 27 #include <ufs/ffs/ffs_extern.h> 28 29 #include <ufs/mfs/mfsnode.h> 30 #include <ufs/mfs/mfs_extern.h> 31 32 caddr_t mfs_rootbase; /* address of mini-root in kernel virtual memory */ 33 u_long mfs_rootsize; /* size of mini-root in bytes */ 34 35 static int mfs_minor; /* used for building internal dev_t */ 36 37 extern int (**mfs_vnodeop_p)(); 38 39 /* 40 * mfs vfs operations. 41 */ 42 struct vfsops mfs_vfsops = { 43 mfs_mount, 44 mfs_start, 45 ffs_unmount, 46 ufs_root, 47 ufs_quotactl, 48 mfs_statfs, 49 ffs_sync, 50 ffs_vget, 51 ffs_fhtovp, 52 ffs_vptofh, 53 mfs_init, 54 ffs_sysctl, 55 }; 56 57 /* 58 * Called by main() when mfs is going to be mounted as root. 59 */ 60 mfs_mountroot() 61 { 62 extern struct vnode *rootvp; 63 struct fs *fs; 64 struct mount *mp; 65 struct proc *p = curproc; /* XXX */ 66 struct ufsmount *ump; 67 struct mfsnode *mfsp; 68 int error; 69 70 /* 71 * Get vnodes for swapdev and rootdev. 72 */ 73 if (bdevvp(swapdev, &swapdev_vp) || bdevvp(rootdev, &rootvp)) 74 panic("mfs_mountroot: can't setup bdevvp's"); 75 76 if (error = vfs_rootmountalloc("mfs", "mfs_root", &mp)) 77 return (error); 78 mfsp = malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK); 79 rootvp->v_data = mfsp; 80 rootvp->v_op = mfs_vnodeop_p; 81 rootvp->v_tag = VT_MFS; 82 mfsp->mfs_baseoff = mfs_rootbase; 83 mfsp->mfs_size = mfs_rootsize; 84 mfsp->mfs_vnode = rootvp; 85 mfsp->mfs_pid = p->p_pid; 86 mfsp->mfs_buflist = (struct buf *)0; 87 if (error = ffs_mountfs(rootvp, mp, p)) { 88 mp->mnt_vfc->vfc_refcount--; 89 free(mp, M_MOUNT); 90 free(mfsp, M_MFSNODE); 91 return (error); 92 } 93 if (error = vfs_lock(mp)) { 94 (void)ffs_unmount(mp, 0, p); 95 mp->mnt_vfc->vfc_refcount--; 96 free(mp, M_MOUNT); 97 free(mfsp, M_MFSNODE); 98 return (error); 99 } 100 CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); 101 ump = VFSTOUFS(mp); 102 fs = ump->um_fs; 103 (void) copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0); 104 (void)ffs_statfs(mp, &mp->mnt_stat, p); 105 vfs_unlock(mp); 106 inittodr((time_t)0); 107 return (0); 108 } 109 110 /* 111 * This is called early in boot to set the base address and size 112 * of the mini-root. 113 */ 114 mfs_initminiroot(base) 115 caddr_t base; 116 { 117 struct fs *fs = (struct fs *)(base + SBOFF); 118 extern int (*mountroot)(); 119 120 /* check for valid super block */ 121 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || 122 fs->fs_bsize < sizeof(struct fs)) 123 return (0); 124 mountroot = mfs_mountroot; 125 mfs_rootbase = base; 126 mfs_rootsize = fs->fs_fsize * fs->fs_size; 127 rootdev = makedev(255, mfs_minor++); 128 return (mfs_rootsize); 129 } 130 131 /* 132 * VFS Operations. 133 * 134 * mount system call 135 */ 136 /* ARGSUSED */ 137 int 138 mfs_mount(mp, path, data, ndp, p) 139 register struct mount *mp; 140 char *path; 141 caddr_t data; 142 struct nameidata *ndp; 143 struct proc *p; 144 { 145 struct vnode *devvp; 146 struct mfs_args args; 147 struct ufsmount *ump; 148 register struct fs *fs; 149 register struct mfsnode *mfsp; 150 u_int size; 151 int flags, error; 152 153 if (error = copyin(data, (caddr_t)&args, sizeof (struct mfs_args))) 154 return (error); 155 156 /* 157 * If updating, check whether changing from read-only to 158 * read/write; if there is no device name, that's all we do. 159 */ 160 if (mp->mnt_flag & MNT_UPDATE) { 161 ump = VFSTOUFS(mp); 162 fs = ump->um_fs; 163 if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) { 164 flags = WRITECLOSE; 165 if (mp->mnt_flag & MNT_FORCE) 166 flags |= FORCECLOSE; 167 if (vfs_busy(mp)) 168 return (EBUSY); 169 error = ffs_flushfiles(mp, flags, p); 170 vfs_unbusy(mp); 171 if (error) 172 return (error); 173 } 174 if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) 175 fs->fs_ronly = 0; 176 #ifdef EXPORTMFS 177 if (args.fspec == 0) 178 return (vfs_export(mp, &ump->um_export, &args.export)); 179 #endif 180 return (0); 181 } 182 error = getnewvnode(VT_MFS, (struct mount *)0, mfs_vnodeop_p, &devvp); 183 if (error) 184 return (error); 185 devvp->v_type = VBLK; 186 if (checkalias(devvp, makedev(255, mfs_minor++), (struct mount *)0)) 187 panic("mfs_mount: dup dev"); 188 mfsp = (struct mfsnode *)malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK); 189 devvp->v_data = mfsp; 190 mfsp->mfs_baseoff = args.base; 191 mfsp->mfs_size = args.size; 192 mfsp->mfs_vnode = devvp; 193 mfsp->mfs_pid = p->p_pid; 194 mfsp->mfs_buflist = (struct buf *)0; 195 if (error = ffs_mountfs(devvp, mp, p)) { 196 mfsp->mfs_buflist = (struct buf *)-1; 197 vrele(devvp); 198 return (error); 199 } 200 ump = VFSTOUFS(mp); 201 fs = ump->um_fs; 202 (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); 203 bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); 204 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 205 MNAMELEN); 206 (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 207 &size); 208 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 209 (void) mfs_statfs(mp, &mp->mnt_stat, p); 210 return (0); 211 } 212 213 int mfs_pri = PWAIT | PCATCH; /* XXX prob. temp */ 214 215 /* 216 * Used to grab the process and keep it in the kernel to service 217 * memory filesystem I/O requests. 218 * 219 * Loop servicing I/O requests. 220 * Copy the requested data into or out of the memory filesystem 221 * address space. 222 */ 223 /* ARGSUSED */ 224 int 225 mfs_start(mp, flags, p) 226 struct mount *mp; 227 int flags; 228 struct proc *p; 229 { 230 register struct vnode *vp = VFSTOUFS(mp)->um_devvp; 231 register struct mfsnode *mfsp = VTOMFS(vp); 232 register struct buf *bp; 233 register caddr_t base; 234 int error = 0; 235 236 base = mfsp->mfs_baseoff; 237 while (mfsp->mfs_buflist != (struct buf *)(-1)) { 238 while (bp = mfsp->mfs_buflist) { 239 mfsp->mfs_buflist = bp->b_actf; 240 mfs_doio(bp, base); 241 wakeup((caddr_t)bp); 242 } 243 /* 244 * If a non-ignored signal is received, try to unmount. 245 * If that fails, clear the signal (it has been "processed"), 246 * otherwise we will loop here, as tsleep will always return 247 * EINTR/ERESTART. 248 */ 249 if (error = tsleep((caddr_t)vp, mfs_pri, "mfsidl", 0)) 250 if (dounmount(mp, 0, p) != 0) 251 CLRSIG(p, CURSIG(p)); 252 } 253 return (error); 254 } 255 256 /* 257 * Get file system statistics. 258 */ 259 mfs_statfs(mp, sbp, p) 260 struct mount *mp; 261 struct statfs *sbp; 262 struct proc *p; 263 { 264 int error; 265 266 error = ffs_statfs(mp, sbp, p); 267 sbp->f_type = mp->mnt_vfc->vfc_typenum; 268 return (error); 269 } 270