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