1 /* 2 * Copyright (c) 1989, 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)mfs_vfsops.c 7.23 (Berkeley) 03/22/92 8 */ 9 10 #include <sys/param.h> 11 #include <sys/time.h> 12 #include <sys/kernel.h> 13 #include <sys/proc.h> 14 #include <sys/buf.h> 15 #include <sys/mount.h> 16 #include <sys/signalvar.h> 17 #include <sys/vnode.h> 18 #include <sys/malloc.h> 19 20 #include <ufs/ufs/quota.h> 21 #include <ufs/ufs/inode.h> 22 #include <ufs/ufs/ufsmount.h> 23 #include <ufs/ufs/ufs_extern.h> 24 25 #include <ufs/ffs/fs.h> 26 #include <ufs/ffs/ffs_extern.h> 27 28 #include <ufs/mfs/mfsnode.h> 29 #include <ufs/mfs/mfs_extern.h> 30 31 caddr_t mfs_rootbase; /* address of mini-root in kernel virtual memory */ 32 u_long mfs_rootsize; /* size of mini-root in bytes */ 33 34 extern struct vnodeops mfs_vnodeops; 35 36 /* 37 * mfs vfs operations. 38 */ 39 struct vfsops mfs_vfsops = { 40 mfs_mount, 41 mfs_start, 42 ffs_unmount, 43 ffs_root, 44 ufs_quotactl, 45 mfs_statfs, 46 ffs_sync, 47 ffs_fhtovp, 48 ffs_vptofh, 49 mfs_init, 50 }; 51 52 /* 53 * Called by main() when mfs is going to be mounted as root. 54 * 55 * Name is updated by mount(8) after booting. 56 */ 57 #define ROOTNAME "root_device" 58 59 mfs_mountroot() 60 { 61 extern struct vnode *rootvp; 62 register struct fs *fs; 63 register struct mount *mp; 64 struct proc *p = curproc; /* XXX */ 65 struct ufsmount *ump; 66 struct mfsnode *mfsp; 67 u_int size; 68 int error; 69 70 mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK); 71 mp->mnt_op = &mfs_vfsops; 72 mp->mnt_flag = MNT_RDONLY; 73 mp->mnt_mounth = NULLVP; 74 mfsp = malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK); 75 rootvp->v_data = mfsp; 76 rootvp->v_op = &mfs_vnodeops; 77 mfsp->mfs_baseoff = mfs_rootbase; 78 mfsp->mfs_size = mfs_rootsize; 79 mfsp->mfs_vnode = rootvp; 80 mfsp->mfs_pid = p->p_pid; 81 mfsp->mfs_buflist = (struct buf *)0; 82 if (error = ffs_mountfs(rootvp, mp, p)) { 83 free(mp, M_MOUNT); 84 free(mfsp, M_MFSNODE); 85 return (error); 86 } 87 if (error = vfs_lock(mp)) { 88 (void)ffs_unmount(mp, 0, p); 89 free(mp, M_MOUNT); 90 free(mfsp, M_MFSNODE); 91 return (error); 92 } 93 rootfs = mp; 94 mp->mnt_next = mp; 95 mp->mnt_prev = mp; 96 mp->mnt_vnodecovered = NULLVP; 97 ump = VFSTOUFS(mp); 98 fs = ump->um_fs; 99 bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt)); 100 fs->fs_fsmnt[0] = '/'; 101 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 102 MNAMELEN); 103 (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 104 &size); 105 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 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 return (mfs_rootsize); 130 } 131 132 /* 133 * VFS Operations. 134 * 135 * mount system call 136 */ 137 /* ARGSUSED */ 138 int 139 mfs_mount(mp, path, data, ndp, p) 140 register struct mount *mp; 141 char *path; 142 caddr_t data; 143 struct nameidata *ndp; 144 struct proc *p; 145 { 146 struct vnode *devvp; 147 struct mfs_args args; 148 struct ufsmount *ump; 149 register struct fs *fs; 150 register struct mfsnode *mfsp; 151 static int mfs_minor; 152 u_int size; 153 int error; 154 155 if (mp->mnt_flag & MNT_UPDATE) { 156 ump = VFSTOUFS(mp); 157 fs = ump->um_fs; 158 if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0) 159 fs->fs_ronly = 0; 160 return (0); 161 } 162 if (error = copyin(data, (caddr_t)&args, sizeof (struct mfs_args))) 163 return (error); 164 error = getnewvnode(VT_MFS, (struct mount *)0, &mfs_vnodeops, &devvp); 165 if (error) 166 return (error); 167 devvp->v_type = VBLK; 168 if (checkalias(devvp, makedev(255, mfs_minor++), (struct mount *)0)) 169 panic("mfs_mount: dup dev"); 170 mfsp = (struct mfsnode *)malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK); 171 devvp->v_data = mfsp; 172 mfsp->mfs_baseoff = args.base; 173 mfsp->mfs_size = args.size; 174 mfsp->mfs_vnode = devvp; 175 mfsp->mfs_pid = p->p_pid; 176 mfsp->mfs_buflist = (struct buf *)0; 177 if (error = ffs_mountfs(devvp, mp, p)) { 178 mfsp->mfs_buflist = (struct buf *)-1; 179 vrele(devvp); 180 return (error); 181 } 182 ump = VFSTOUFS(mp); 183 fs = ump->um_fs; 184 (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); 185 bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); 186 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 187 MNAMELEN); 188 (void) copyinstr(args.name, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 189 &size); 190 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 191 (void) mfs_statfs(mp, &mp->mnt_stat, p); 192 return (0); 193 } 194 195 int mfs_pri = PWAIT | PCATCH; /* XXX prob. temp */ 196 197 /* 198 * Used to grab the process and keep it in the kernel to service 199 * memory filesystem I/O requests. 200 * 201 * Loop servicing I/O requests. 202 * Copy the requested data into or out of the memory filesystem 203 * address space. 204 */ 205 /* ARGSUSED */ 206 int 207 mfs_start(mp, flags, p) 208 struct mount *mp; 209 int flags; 210 struct proc *p; 211 { 212 register struct vnode *vp = VFSTOUFS(mp)->um_devvp; 213 register struct mfsnode *mfsp = VTOMFS(vp); 214 register struct buf *bp; 215 register caddr_t base; 216 int error = 0; 217 218 base = mfsp->mfs_baseoff; 219 while (mfsp->mfs_buflist != (struct buf *)(-1)) { 220 while (bp = mfsp->mfs_buflist) { 221 mfsp->mfs_buflist = bp->av_forw; 222 mfs_doio(bp, base); 223 wakeup((caddr_t)bp); 224 } 225 /* 226 * If a non-ignored signal is received, try to unmount. 227 * If that fails, clear the signal (it has been "processed"), 228 * otherwise we will loop here, as tsleep will always return 229 * EINTR/ERESTART. 230 */ 231 if (error = tsleep((caddr_t)vp, mfs_pri, "mfsidl", 0)) 232 if (dounmount(mp, MNT_NOFORCE, p) != 0) 233 CLRSIG(p, CURSIG(p)); 234 } 235 return (error); 236 } 237 238 /* 239 * Get file system statistics. 240 */ 241 mfs_statfs(mp, sbp, p) 242 struct mount *mp; 243 struct statfs *sbp; 244 struct proc *p; 245 { 246 int error; 247 248 error = ffs_statfs(mp, sbp, p); 249 sbp->f_type = MOUNT_MFS; 250 return (error); 251 } 252