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.26 (Berkeley) 07/03/92 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 ffs_root, 47 ufs_quotactl, 48 mfs_statfs, 49 ffs_sync, 50 ffs_vget, 51 ffs_fhtovp, 52 ffs_vptofh, 53 mfs_init, 54 }; 55 56 /* 57 * Called by main() when mfs is going to be mounted as root. 58 * 59 * Name is updated by mount(8) after booting. 60 */ 61 #define ROOTNAME "mfs_root" 62 63 mfs_mountroot() 64 { 65 extern struct vnode *rootvp; 66 register struct fs *fs; 67 register struct mount *mp; 68 struct proc *p = curproc; /* XXX */ 69 struct ufsmount *ump; 70 struct mfsnode *mfsp; 71 u_int size; 72 int error; 73 74 mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK); 75 mp->mnt_op = &mfs_vfsops; 76 mp->mnt_flag = MNT_RDONLY; 77 mp->mnt_mounth = NULLVP; 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 free(mp, M_MOUNT); 89 free(mfsp, M_MFSNODE); 90 return (error); 91 } 92 if (error = vfs_lock(mp)) { 93 (void)ffs_unmount(mp, 0, p); 94 free(mp, M_MOUNT); 95 free(mfsp, M_MFSNODE); 96 return (error); 97 } 98 rootfs = mp; 99 mp->mnt_next = mp; 100 mp->mnt_prev = mp; 101 mp->mnt_vnodecovered = NULLVP; 102 ump = VFSTOUFS(mp); 103 fs = ump->um_fs; 104 bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt)); 105 fs->fs_fsmnt[0] = '/'; 106 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 107 MNAMELEN); 108 (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 109 &size); 110 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 111 (void)ffs_statfs(mp, &mp->mnt_stat, p); 112 vfs_unlock(mp); 113 inittodr((time_t)0); 114 return (0); 115 } 116 117 /* 118 * This is called early in boot to set the base address and size 119 * of the mini-root. 120 */ 121 mfs_initminiroot(base) 122 caddr_t base; 123 { 124 struct fs *fs = (struct fs *)(base + SBOFF); 125 extern int (*mountroot)(); 126 127 /* check for valid super block */ 128 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || 129 fs->fs_bsize < sizeof(struct fs)) 130 return (0); 131 mountroot = mfs_mountroot; 132 mfs_rootbase = base; 133 mfs_rootsize = fs->fs_fsize * fs->fs_size; 134 rootdev = makedev(255, mfs_minor++); 135 return (mfs_rootsize); 136 } 137 138 /* 139 * VFS Operations. 140 * 141 * mount system call 142 */ 143 /* ARGSUSED */ 144 int 145 mfs_mount(mp, path, data, ndp, p) 146 register struct mount *mp; 147 char *path; 148 caddr_t data; 149 struct nameidata *ndp; 150 struct proc *p; 151 { 152 struct vnode *devvp; 153 struct mfs_args args; 154 struct ufsmount *ump; 155 register struct fs *fs; 156 register struct mfsnode *mfsp; 157 u_int size; 158 int error; 159 160 if (mp->mnt_flag & MNT_UPDATE) { 161 ump = VFSTOUFS(mp); 162 fs = ump->um_fs; 163 if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0) 164 fs->fs_ronly = 0; 165 return (0); 166 } 167 if (error = copyin(data, (caddr_t)&args, sizeof (struct mfs_args))) 168 return (error); 169 error = getnewvnode(VT_MFS, (struct mount *)0, mfs_vnodeop_p, &devvp); 170 if (error) 171 return (error); 172 devvp->v_type = VBLK; 173 if (checkalias(devvp, makedev(255, mfs_minor++), (struct mount *)0)) 174 panic("mfs_mount: dup dev"); 175 mfsp = (struct mfsnode *)malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK); 176 devvp->v_data = mfsp; 177 mfsp->mfs_baseoff = args.base; 178 mfsp->mfs_size = args.size; 179 mfsp->mfs_vnode = devvp; 180 mfsp->mfs_pid = p->p_pid; 181 mfsp->mfs_buflist = (struct buf *)0; 182 if (error = ffs_mountfs(devvp, mp, p)) { 183 mfsp->mfs_buflist = (struct buf *)-1; 184 vrele(devvp); 185 return (error); 186 } 187 ump = VFSTOUFS(mp); 188 fs = ump->um_fs; 189 (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); 190 bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); 191 bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, 192 MNAMELEN); 193 (void) copyinstr(args.name, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 194 &size); 195 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 196 (void) mfs_statfs(mp, &mp->mnt_stat, p); 197 return (0); 198 } 199 200 int mfs_pri = PWAIT | PCATCH; /* XXX prob. temp */ 201 202 /* 203 * Used to grab the process and keep it in the kernel to service 204 * memory filesystem I/O requests. 205 * 206 * Loop servicing I/O requests. 207 * Copy the requested data into or out of the memory filesystem 208 * address space. 209 */ 210 /* ARGSUSED */ 211 int 212 mfs_start(mp, flags, p) 213 struct mount *mp; 214 int flags; 215 struct proc *p; 216 { 217 register struct vnode *vp = VFSTOUFS(mp)->um_devvp; 218 register struct mfsnode *mfsp = VTOMFS(vp); 219 register struct buf *bp; 220 register caddr_t base; 221 int error = 0; 222 223 base = mfsp->mfs_baseoff; 224 while (mfsp->mfs_buflist != (struct buf *)(-1)) { 225 while (bp = mfsp->mfs_buflist) { 226 mfsp->mfs_buflist = bp->av_forw; 227 mfs_doio(bp, base); 228 wakeup((caddr_t)bp); 229 } 230 /* 231 * If a non-ignored signal is received, try to unmount. 232 * If that fails, clear the signal (it has been "processed"), 233 * otherwise we will loop here, as tsleep will always return 234 * EINTR/ERESTART. 235 */ 236 if (error = tsleep((caddr_t)vp, mfs_pri, "mfsidl", 0)) 237 if (dounmount(mp, MNT_NOFORCE, p) != 0) 238 CLRSIG(p, CURSIG(p)); 239 } 240 return (error); 241 } 242 243 /* 244 * Get file system statistics. 245 */ 246 mfs_statfs(mp, sbp, p) 247 struct mount *mp; 248 struct statfs *sbp; 249 struct proc *p; 250 { 251 int error; 252 253 error = ffs_statfs(mp, sbp, p); 254 sbp->f_type = MOUNT_MFS; 255 return (error); 256 } 257