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.6 (Berkeley) 05/09/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 * Name is updated by mount(8) after booting. 61 */ 62 #define ROOTNAME "mfs_root" 63 64 mfs_mountroot() 65 { 66 extern struct vnode *rootvp; 67 register struct fs *fs; 68 register struct mount *mp; 69 struct proc *p = curproc; /* XXX */ 70 struct ufsmount *ump; 71 struct mfsnode *mfsp; 72 u_int size; 73 int error; 74 75 /* 76 * Get vnodes for swapdev and rootdev. 77 */ 78 if (bdevvp(swapdev, &swapdev_vp) || bdevvp(rootdev, &rootvp)) 79 panic("mfs_mountroot: can't setup bdevvp's"); 80 81 mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK); 82 bzero((char *)mp, (u_long)sizeof(struct mount)); 83 mp->mnt_op = &mfs_vfsops; 84 mp->mnt_flag = MNT_RDONLY; 85 mfsp = malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK); 86 rootvp->v_data = mfsp; 87 rootvp->v_op = mfs_vnodeop_p; 88 rootvp->v_tag = VT_MFS; 89 mfsp->mfs_baseoff = mfs_rootbase; 90 mfsp->mfs_size = mfs_rootsize; 91 mfsp->mfs_vnode = rootvp; 92 mfsp->mfs_pid = p->p_pid; 93 mfsp->mfs_buflist = (struct buf *)0; 94 if (error = ffs_mountfs(rootvp, mp, p)) { 95 free(mp, M_MOUNT); 96 free(mfsp, M_MFSNODE); 97 return (error); 98 } 99 if (error = vfs_lock(mp)) { 100 (void)ffs_unmount(mp, 0, p); 101 free(mp, M_MOUNT); 102 free(mfsp, M_MFSNODE); 103 return (error); 104 } 105 CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); 106 mp->mnt_flag |= MNT_ROOTFS; 107 mp->mnt_vnodecovered = NULLVP; 108 ump = VFSTOUFS(mp); 109 fs = ump->um_fs; 110 bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt)); 111 fs->fs_fsmnt[0] = '/'; 112 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 113 MNAMELEN); 114 (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 115 &size); 116 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 117 (void)ffs_statfs(mp, &mp->mnt_stat, p); 118 vfs_unlock(mp); 119 inittodr((time_t)0); 120 return (0); 121 } 122 123 /* 124 * This is called early in boot to set the base address and size 125 * of the mini-root. 126 */ 127 mfs_initminiroot(base) 128 caddr_t base; 129 { 130 struct fs *fs = (struct fs *)(base + SBOFF); 131 extern int (*mountroot)(); 132 133 /* check for valid super block */ 134 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || 135 fs->fs_bsize < sizeof(struct fs)) 136 return (0); 137 mountroot = mfs_mountroot; 138 mfs_rootbase = base; 139 mfs_rootsize = fs->fs_fsize * fs->fs_size; 140 rootdev = makedev(255, mfs_minor++); 141 return (mfs_rootsize); 142 } 143 144 /* 145 * VFS Operations. 146 * 147 * mount system call 148 */ 149 /* ARGSUSED */ 150 int 151 mfs_mount(mp, path, data, ndp, p) 152 register struct mount *mp; 153 char *path; 154 caddr_t data; 155 struct nameidata *ndp; 156 struct proc *p; 157 { 158 struct vnode *devvp; 159 struct mfs_args args; 160 struct ufsmount *ump; 161 register struct fs *fs; 162 register struct mfsnode *mfsp; 163 u_int size; 164 int flags, error; 165 166 if (error = copyin(data, (caddr_t)&args, sizeof (struct mfs_args))) 167 return (error); 168 169 /* 170 * If updating, check whether changing from read-only to 171 * read/write; if there is no device name, that's all we do. 172 */ 173 if (mp->mnt_flag & MNT_UPDATE) { 174 ump = VFSTOUFS(mp); 175 fs = ump->um_fs; 176 if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) { 177 flags = WRITECLOSE; 178 if (mp->mnt_flag & MNT_FORCE) 179 flags |= FORCECLOSE; 180 if (vfs_busy(mp)) 181 return (EBUSY); 182 error = ffs_flushfiles(mp, flags, p); 183 vfs_unbusy(mp); 184 if (error) 185 return (error); 186 } 187 if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) 188 fs->fs_ronly = 0; 189 #ifdef EXPORTMFS 190 if (args.fspec == 0) 191 return (vfs_export(mp, &ump->um_export, &args.export)); 192 #endif 193 return (0); 194 } 195 error = getnewvnode(VT_MFS, (struct mount *)0, mfs_vnodeop_p, &devvp); 196 if (error) 197 return (error); 198 devvp->v_type = VBLK; 199 if (checkalias(devvp, makedev(255, mfs_minor++), (struct mount *)0)) 200 panic("mfs_mount: dup dev"); 201 mfsp = (struct mfsnode *)malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK); 202 devvp->v_data = mfsp; 203 mfsp->mfs_baseoff = args.base; 204 mfsp->mfs_size = args.size; 205 mfsp->mfs_vnode = devvp; 206 mfsp->mfs_pid = p->p_pid; 207 mfsp->mfs_buflist = (struct buf *)0; 208 if (error = ffs_mountfs(devvp, mp, p)) { 209 mfsp->mfs_buflist = (struct buf *)-1; 210 vrele(devvp); 211 return (error); 212 } 213 ump = VFSTOUFS(mp); 214 fs = ump->um_fs; 215 (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); 216 bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); 217 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 218 MNAMELEN); 219 (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 220 &size); 221 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 222 (void) mfs_statfs(mp, &mp->mnt_stat, p); 223 return (0); 224 } 225 226 int mfs_pri = PWAIT | PCATCH; /* XXX prob. temp */ 227 228 /* 229 * Used to grab the process and keep it in the kernel to service 230 * memory filesystem I/O requests. 231 * 232 * Loop servicing I/O requests. 233 * Copy the requested data into or out of the memory filesystem 234 * address space. 235 */ 236 /* ARGSUSED */ 237 int 238 mfs_start(mp, flags, p) 239 struct mount *mp; 240 int flags; 241 struct proc *p; 242 { 243 register struct vnode *vp = VFSTOUFS(mp)->um_devvp; 244 register struct mfsnode *mfsp = VTOMFS(vp); 245 register struct buf *bp; 246 register caddr_t base; 247 int error = 0; 248 249 base = mfsp->mfs_baseoff; 250 while (mfsp->mfs_buflist != (struct buf *)(-1)) { 251 while (bp = mfsp->mfs_buflist) { 252 mfsp->mfs_buflist = bp->b_actf; 253 mfs_doio(bp, base); 254 wakeup((caddr_t)bp); 255 } 256 /* 257 * If a non-ignored signal is received, try to unmount. 258 * If that fails, clear the signal (it has been "processed"), 259 * otherwise we will loop here, as tsleep will always return 260 * EINTR/ERESTART. 261 */ 262 if (error = tsleep((caddr_t)vp, mfs_pri, "mfsidl", 0)) 263 if (dounmount(mp, 0, p) != 0) 264 CLRSIG(p, CURSIG(p)); 265 } 266 return (error); 267 } 268 269 /* 270 * Get file system statistics. 271 */ 272 mfs_statfs(mp, sbp, p) 273 struct mount *mp; 274 struct statfs *sbp; 275 struct proc *p; 276 { 277 int error; 278 279 error = ffs_statfs(mp, sbp, p); 280 sbp->f_type = mp->mnt_vfc->vfc_typenum; 281 return (error); 282 } 283