1 /* $OpenBSD: mfs_vfsops.c,v 1.63 2024/10/17 09:11:35 claudio 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 struct sigctx ctx; 171 172 while (1) { 173 while (1) { 174 if (mfsp->mfs_shutdown == 1) 175 break; 176 bp = bufq_dequeue(&mfsp->mfs_bufq); 177 if (bp == NULL) 178 break; 179 mfs_doio(mfsp, bp); 180 wakeup(bp); 181 } 182 if (mfsp->mfs_shutdown == 1) 183 break; 184 185 /* 186 * If a non-ignored signal is received, try to unmount. 187 * If that fails, clear the signal (it has been "processed"), 188 * otherwise we will loop here, as tsleep will always return 189 * EINTR/ERESTART. 190 */ 191 if (sleepreturn != 0) { 192 sig = cursig(p, &ctx, 0); 193 if (vfs_busy(mp, VB_WRITE|VB_NOWAIT) || 194 dounmount(mp, (sig == SIGKILL) ? MNT_FORCE : 0, p)) 195 atomic_clearbits_int(&p->p_siglist, 196 sigmask(sig)); 197 sleepreturn = 0; 198 continue; 199 } 200 sleepreturn = tsleep_nsec(vp, PWAIT | PCATCH, "mfsidl", INFSLP); 201 } 202 return (0); 203 } 204 205 /* 206 * check export permission, not supported 207 */ 208 int 209 mfs_checkexp(struct mount *mp, struct mbuf *nam, int *exflagsp, 210 struct ucred **credanonp) 211 { 212 return (EOPNOTSUPP); 213 } 214 215 /* 216 * Memory based filesystem initialization. 217 */ 218 int 219 mfs_init(struct vfsconf *vfsp) 220 { 221 return (ffs_init(vfsp)); 222 } 223