1 /* $OpenBSD: mfs_vfsops.c,v 1.60 2021/03/04 09:02:38 mpi Exp $ */ 2 /* $NetBSD: mfs_vfsops.c,v 1.10 1996/02/09 22:31:28 christos Exp $ */ 3 4 /* 5 * Copyright (c) 1989, 1990, 1993, 1994 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * @(#)mfs_vfsops.c 8.4 (Berkeley) 4/16/94 33 */ 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/time.h> 38 #include <sys/proc.h> 39 #include <sys/buf.h> 40 #include <sys/mount.h> 41 #include <sys/signalvar.h> 42 #include <sys/vnode.h> 43 #include <sys/malloc.h> 44 45 #include <ufs/ufs/quota.h> 46 #include <ufs/ufs/inode.h> 47 #include <ufs/ufs/ufsmount.h> 48 #include <ufs/ufs/ufs_extern.h> 49 50 #include <ufs/ffs/fs.h> 51 #include <ufs/ffs/ffs_extern.h> 52 53 #include <ufs/mfs/mfsnode.h> 54 #include <ufs/mfs/mfs_extern.h> 55 56 static int mfs_minor; /* used for building internal dev_t */ 57 58 /* 59 * mfs vfs operations. 60 */ 61 const struct vfsops mfs_vfsops = { 62 .vfs_mount = mfs_mount, 63 .vfs_start = mfs_start, 64 .vfs_unmount = ffs_unmount, 65 .vfs_root = ufs_root, 66 .vfs_quotactl = ufs_quotactl, 67 .vfs_statfs = ffs_statfs, 68 .vfs_sync = ffs_sync, 69 .vfs_vget = ffs_vget, 70 .vfs_fhtovp = ffs_fhtovp, 71 .vfs_vptofh = ffs_vptofh, 72 .vfs_init = mfs_init, 73 .vfs_sysctl = ffs_sysctl, 74 .vfs_checkexp = mfs_checkexp, 75 }; 76 77 /* 78 * VFS Operations. 79 * 80 * mount system call 81 */ 82 int 83 mfs_mount(struct mount *mp, const char *path, void *data, 84 struct nameidata *ndp, struct proc *p) 85 { 86 struct vnode *devvp; 87 struct mfs_args *args = data; 88 struct ufsmount *ump; 89 struct fs *fs; 90 struct mfsnode *mfsp; 91 char fspec[MNAMELEN]; 92 int flags, error; 93 94 /* 95 * If updating, check whether changing from read-only to 96 * read/write; if there is no device name, that's all we do. 97 */ 98 if (mp->mnt_flag & MNT_UPDATE) { 99 ump = VFSTOUFS(mp); 100 fs = ump->um_fs; 101 if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) { 102 flags = WRITECLOSE; 103 if (mp->mnt_flag & MNT_FORCE) 104 flags |= FORCECLOSE; 105 error = ffs_flushfiles(mp, flags, p); 106 if (error) 107 return (error); 108 } 109 if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) 110 fs->fs_ronly = 0; 111 #ifdef EXPORTMFS 112 if (args && args->fspec == NULL) 113 return (vfs_export(mp, &ump->um_export, 114 &args->export_info)); 115 #endif 116 return (0); 117 } 118 error = copyinstr(args->fspec, fspec, sizeof(fspec), NULL); 119 if (error) 120 return (error); 121 error = getnewvnode(VT_MFS, NULL, &mfs_vops, &devvp); 122 if (error) 123 return (error); 124 devvp->v_type = VBLK; 125 if (checkalias(devvp, makedev(255, mfs_minor), NULL)) 126 panic("mfs_mount: dup dev"); 127 mfs_minor++; 128 mfsp = malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK | M_ZERO); 129 devvp->v_data = mfsp; 130 mfsp->mfs_baseoff = args->base; 131 mfsp->mfs_size = args->size; 132 mfsp->mfs_vnode = devvp; 133 mfsp->mfs_tid = p->p_tid; 134 bufq_init(&mfsp->mfs_bufq, BUFQ_FIFO); 135 if ((error = ffs_mountfs(devvp, mp, p)) != 0) { 136 mfsp->mfs_shutdown = 1; 137 vrele(devvp); 138 return (error); 139 } 140 ump = VFSTOUFS(mp); 141 fs = ump->um_fs; 142 143 memset(fs->fs_fsmnt, 0, sizeof(fs->fs_fsmnt)); 144 strlcpy(fs->fs_fsmnt, path, sizeof(fs->fs_fsmnt)); 145 memcpy(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN); 146 memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN); 147 strlcpy(mp->mnt_stat.f_mntfromname, fspec, MNAMELEN); 148 memset(mp->mnt_stat.f_mntfromspec, 0, MNAMELEN); 149 strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN); 150 memcpy(&mp->mnt_stat.mount_info.mfs_args, args, sizeof(*args)); 151 152 return (0); 153 } 154 155 /* 156 * Used to grab the process and keep it in the kernel to service 157 * memory filesystem I/O requests. 158 * 159 * Loop servicing I/O requests. 160 * Copy the requested data into or out of the memory filesystem 161 * address space. 162 */ 163 int 164 mfs_start(struct mount *mp, int flags, struct proc *p) 165 { 166 struct vnode *vp = VFSTOUFS(mp)->um_devvp; 167 struct mfsnode *mfsp = VTOMFS(vp); 168 struct buf *bp; 169 int sleepreturn = 0, sig; 170 171 while (1) { 172 while (1) { 173 if (mfsp->mfs_shutdown == 1) 174 break; 175 bp = bufq_dequeue(&mfsp->mfs_bufq); 176 if (bp == NULL) 177 break; 178 mfs_doio(mfsp, bp); 179 wakeup(bp); 180 } 181 if (mfsp->mfs_shutdown == 1) 182 break; 183 184 /* 185 * If a non-ignored signal is received, try to unmount. 186 * If that fails, clear the signal (it has been "processed"), 187 * otherwise we will loop here, as tsleep will always return 188 * EINTR/ERESTART. 189 */ 190 if (sleepreturn != 0) { 191 sig = cursig(p); 192 if (vfs_busy(mp, VB_WRITE|VB_NOWAIT) || 193 dounmount(mp, (sig == SIGKILL) ? MNT_FORCE : 0, p)) 194 CLRSIG(p, sig); 195 sleepreturn = 0; 196 continue; 197 } 198 sleepreturn = tsleep_nsec(vp, PWAIT | PCATCH, "mfsidl", INFSLP); 199 } 200 return (0); 201 } 202 203 /* 204 * check export permission, not supported 205 */ 206 int 207 mfs_checkexp(struct mount *mp, struct mbuf *nam, int *exflagsp, 208 struct ucred **credanonp) 209 { 210 return (EOPNOTSUPP); 211 } 212 213 /* 214 * Memory based filesystem initialization. 215 */ 216 int 217 mfs_init(struct vfsconf *vfsp) 218 { 219 return (ffs_init(vfsp)); 220 } 221