Line data Source code
1 : /* $OpenBSD: mfs_vfsops.c,v 1.55 2017/12/11 05:27:40 deraadt 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 : #include <sys/kthread.h>
45 :
46 : #include <ufs/ufs/quota.h>
47 : #include <ufs/ufs/inode.h>
48 : #include <ufs/ufs/ufsmount.h>
49 : #include <ufs/ufs/ufs_extern.h>
50 :
51 : #include <ufs/ffs/fs.h>
52 : #include <ufs/ffs/ffs_extern.h>
53 :
54 : #include <ufs/mfs/mfsnode.h>
55 : #include <ufs/mfs/mfs_extern.h>
56 :
57 : static int mfs_minor; /* used for building internal dev_t */
58 :
59 : /*
60 : * mfs vfs operations.
61 : */
62 : const struct vfsops mfs_vfsops = {
63 : mfs_mount,
64 : mfs_start,
65 : ffs_unmount,
66 : ufs_root,
67 : ufs_quotactl,
68 : ffs_statfs,
69 : ffs_sync,
70 : ffs_vget,
71 : ffs_fhtovp,
72 : ffs_vptofh,
73 : mfs_init,
74 : ffs_sysctl,
75 : mfs_checkexp
76 : };
77 :
78 : /*
79 : * VFS Operations.
80 : *
81 : * mount system call
82 : */
83 : int
84 0 : mfs_mount(struct mount *mp, const char *path, void *data,
85 : struct nameidata *ndp, struct proc *p)
86 : {
87 0 : struct vnode *devvp;
88 0 : struct mfs_args *args = data;
89 : struct ufsmount *ump;
90 : struct fs *fs;
91 : struct mfsnode *mfsp;
92 0 : char fspec[MNAMELEN];
93 : int flags, error;
94 :
95 : /*
96 : * If updating, check whether changing from read-only to
97 : * read/write; if there is no device name, that's all we do.
98 : */
99 0 : if (mp->mnt_flag & MNT_UPDATE) {
100 0 : ump = VFSTOUFS(mp);
101 0 : fs = ump->um_fs;
102 0 : if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
103 : flags = WRITECLOSE;
104 0 : if (mp->mnt_flag & MNT_FORCE)
105 0 : flags |= FORCECLOSE;
106 0 : error = ffs_flushfiles(mp, flags, p);
107 0 : if (error)
108 0 : return (error);
109 : }
110 0 : if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR))
111 0 : fs->fs_ronly = 0;
112 : #ifdef EXPORTMFS
113 : if (args && args->fspec == NULL)
114 : return (vfs_export(mp, &ump->um_export,
115 : &args->export_info));
116 : #endif
117 0 : return (0);
118 : }
119 0 : error = copyinstr(args->fspec, fspec, sizeof(fspec), NULL);
120 0 : if (error)
121 0 : return (error);
122 0 : error = getnewvnode(VT_MFS, NULL, &mfs_vops, &devvp);
123 0 : if (error)
124 0 : return (error);
125 0 : devvp->v_type = VBLK;
126 0 : if (checkalias(devvp, makedev(255, mfs_minor), NULL))
127 0 : panic("mfs_mount: dup dev");
128 0 : mfs_minor++;
129 0 : mfsp = malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK | M_ZERO);
130 0 : devvp->v_data = mfsp;
131 0 : mfsp->mfs_baseoff = args->base;
132 0 : mfsp->mfs_size = args->size;
133 0 : mfsp->mfs_vnode = devvp;
134 0 : mfsp->mfs_tid = p->p_tid;
135 0 : bufq_init(&mfsp->mfs_bufq, BUFQ_FIFO);
136 0 : if ((error = ffs_mountfs(devvp, mp, p)) != 0) {
137 0 : mfsp->mfs_shutdown = 1;
138 0 : vrele(devvp);
139 0 : return (error);
140 : }
141 0 : ump = VFSTOUFS(mp);
142 0 : fs = ump->um_fs;
143 :
144 0 : memset(fs->fs_fsmnt, 0, sizeof(fs->fs_fsmnt));
145 0 : strlcpy(fs->fs_fsmnt, path, sizeof(fs->fs_fsmnt));
146 0 : memcpy(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN);
147 0 : memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN);
148 0 : strlcpy(mp->mnt_stat.f_mntfromname, fspec, MNAMELEN);
149 0 : memset(mp->mnt_stat.f_mntfromspec, 0, MNAMELEN);
150 0 : strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN);
151 0 : memcpy(&mp->mnt_stat.mount_info.mfs_args, args, sizeof(*args));
152 :
153 0 : return (0);
154 0 : }
155 :
156 : /*
157 : * Used to grab the process and keep it in the kernel to service
158 : * memory filesystem I/O requests.
159 : *
160 : * Loop servicing I/O requests.
161 : * Copy the requested data into or out of the memory filesystem
162 : * address space.
163 : */
164 : int
165 0 : mfs_start(struct mount *mp, int flags, struct proc *p)
166 : {
167 0 : struct vnode *vp = VFSTOUFS(mp)->um_devvp;
168 0 : struct mfsnode *mfsp = VTOMFS(vp);
169 : struct buf *bp;
170 : int sleepreturn = 0;
171 :
172 0 : while (1) {
173 0 : while (1) {
174 0 : if (mfsp->mfs_shutdown == 1)
175 : break;
176 0 : bp = bufq_dequeue(&mfsp->mfs_bufq);
177 0 : if (bp == NULL)
178 : break;
179 0 : mfs_doio(mfsp, bp);
180 0 : wakeup(bp);
181 : }
182 0 : 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 0 : if (sleepreturn != 0) {
192 0 : if (vfs_busy(mp, VB_WRITE|VB_NOWAIT) ||
193 0 : dounmount(mp,
194 0 : (CURSIG(p) == SIGKILL) ? MNT_FORCE : 0, p))
195 0 : CLRSIG(p, CURSIG(p));
196 : sleepreturn = 0;
197 0 : continue;
198 : }
199 0 : sleepreturn = tsleep(vp, PWAIT | PCATCH, "mfsidl", 0);
200 : }
201 0 : return (0);
202 : }
203 :
204 : /*
205 : * check export permission, not supported
206 : */
207 : int
208 0 : mfs_checkexp(struct mount *mp, struct mbuf *nam, int *exflagsp,
209 : struct ucred **credanonp)
210 : {
211 0 : return (EOPNOTSUPP);
212 : }
213 :
214 : /*
215 : * Memory based filesystem initialization.
216 : */
217 : int
218 0 : mfs_init(struct vfsconf *vfsp)
219 : {
220 0 : return (ffs_init(vfsp));
221 : }
|