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