1 /* $OpenBSD: mfs_vnops.c,v 1.62 2024/10/18 05:52:33 miod Exp $ */
2 /* $NetBSD: mfs_vnops.c,v 1.8 1996/03/17 02:16:32 christos Exp $ */
3
4 /*
5 * Copyright (c) 1989, 1993
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_vnops.c 8.5 (Berkeley) 7/28/94
33 */
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/time.h>
38 #include <sys/kernel.h>
39 #include <sys/proc.h>
40 #include <sys/buf.h>
41 #include <sys/vnode.h>
42 #include <sys/malloc.h>
43 #include <sys/mount.h>
44 #include <sys/specdev.h>
45
46 #include <ufs/mfs/mfsnode.h>
47 #include <ufs/mfs/mfs_extern.h>
48
49 /* mfs vnode operations. */
50 const struct vops mfs_vops = {
51 .vop_lookup = vop_generic_badop,
52 .vop_create = vop_generic_badop,
53 .vop_mknod = vop_generic_badop,
54 .vop_open = mfs_open,
55 .vop_close = mfs_close,
56 .vop_access = vop_generic_badop,
57 .vop_getattr = vop_generic_badop,
58 .vop_setattr = vop_generic_badop,
59 .vop_read = vop_generic_badop,
60 .vop_write = vop_generic_badop,
61 .vop_ioctl = mfs_ioctl,
62 .vop_kqfilter = vop_generic_badop,
63 .vop_revoke = vop_generic_revoke,
64 .vop_fsync = spec_fsync,
65 .vop_remove = vop_generic_badop,
66 .vop_link = vop_generic_badop,
67 .vop_rename = vop_generic_badop,
68 .vop_mkdir = vop_generic_badop,
69 .vop_rmdir = vop_generic_badop,
70 .vop_symlink = vop_generic_badop,
71 .vop_readdir = vop_generic_badop,
72 .vop_readlink = vop_generic_badop,
73 .vop_abortop = vop_generic_badop,
74 .vop_inactive = mfs_inactive,
75 .vop_reclaim = mfs_reclaim,
76 .vop_lock = nullop,
77 .vop_unlock = nullop,
78 .vop_islocked = nullop,
79 .vop_bmap = vop_generic_bmap,
80 .vop_strategy = mfs_strategy,
81 .vop_print = mfs_print,
82 .vop_pathconf = vop_generic_badop,
83 .vop_advlock = vop_generic_badop,
84 .vop_bwrite = vop_generic_bwrite
85 };
86
87 /*
88 * Vnode Operations.
89 *
90 * Open called to allow memory filesystem to initialize and
91 * validate before actual IO. Record our process identifier
92 * so we can tell when we are doing I/O to ourself.
93 */
94 int
mfs_open(void * v)95 mfs_open(void *v)
96 {
97 #ifdef DIAGNOSTIC
98 struct vop_open_args *ap = v;
99
100 if (ap->a_vp->v_type != VBLK) {
101 panic("mfs_open not VBLK");
102 }
103 #endif
104 return (0);
105 }
106
107 /*
108 * Ioctl operation.
109 */
110 int
mfs_ioctl(void * v)111 mfs_ioctl(void *v)
112 {
113
114 return (ENOTTY);
115 }
116
117 /*
118 * Pass I/O requests to the memory filesystem process.
119 */
120 int
mfs_strategy(void * v)121 mfs_strategy(void *v)
122 {
123 struct vop_strategy_args *ap = v;
124 struct buf *bp = ap->a_bp;
125 struct mfsnode *mfsp;
126 struct vnode *vp = ap->a_vp;
127
128 if (vp->v_type != VBLK || vp->v_usecount == 0)
129 panic("mfs_strategy: bad dev");
130
131 mfsp = VTOMFS(vp);
132 if (mfsp->mfs_tid == curproc->p_tid) {
133 mfs_doio(mfsp, bp);
134 } else {
135 bufq_queue(&mfsp->mfs_bufq, bp);
136 wakeup(vp);
137 }
138 return (0);
139 }
140
141 /*
142 * Memory file system I/O.
143 */
144 void
mfs_doio(struct mfsnode * mfsp,struct buf * bp)145 mfs_doio(struct mfsnode *mfsp, struct buf *bp)
146 {
147 caddr_t base;
148 long offset = bp->b_blkno << DEV_BSHIFT;
149 int s;
150
151 if (bp->b_bcount > mfsp->mfs_size - offset)
152 bp->b_bcount = mfsp->mfs_size - offset;
153
154 base = mfsp->mfs_baseoff + offset;
155 if (bp->b_flags & B_READ)
156 bp->b_error = copyin(base, bp->b_data, bp->b_bcount);
157 else
158 bp->b_error = copyout(bp->b_data, base, bp->b_bcount);
159 if (bp->b_error)
160 bp->b_flags |= B_ERROR;
161 else
162 bp->b_resid = 0;
163 s = splbio();
164 biodone(bp);
165 splx(s);
166 }
167
168 /*
169 * Memory filesystem close routine
170 */
171 int
mfs_close(void * v)172 mfs_close(void *v)
173 {
174 struct vop_close_args *ap = v;
175 struct vnode *vp = ap->a_vp;
176 struct mfsnode *mfsp = VTOMFS(vp);
177 struct buf *bp;
178 int error;
179
180 /*
181 * Finish any pending I/O requests.
182 */
183 while (1) {
184 bp = bufq_dequeue(&mfsp->mfs_bufq);
185 if (bp == NULL)
186 break;
187 mfs_doio(mfsp, bp);
188 wakeup(bp);
189 }
190
191 /*
192 * On last close of a memory filesystem we must invalidate any in
193 * core blocks, so that we can free up its vnode.
194 */
195 error = vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 0, INFSLP);
196 if (error != 0)
197 return (error);
198
199 #ifdef DIAGNOSTIC
200 /*
201 * There should be no way to have any more buffers on this vnode.
202 */
203 if (bufq_peek(&mfsp->mfs_bufq))
204 printf("mfs_close: dirty buffers\n");
205 #endif
206
207 /*
208 * Send a request to the filesystem server to exit.
209 */
210 mfsp->mfs_shutdown = 1;
211 wakeup(vp);
212 return (0);
213 }
214
215 /*
216 * Memory filesystem inactive routine
217 */
218 int
mfs_inactive(void * v)219 mfs_inactive(void *v)
220 {
221 struct vop_inactive_args *ap = v;
222 #ifdef DIAGNOSTIC
223 struct mfsnode *mfsp = VTOMFS(ap->a_vp);
224
225 if (mfsp->mfs_shutdown && bufq_peek(&mfsp->mfs_bufq))
226 panic("mfs_inactive: not inactive");
227 #endif
228 VOP_UNLOCK(ap->a_vp);
229 return (0);
230 }
231
232 /*
233 * Reclaim a memory filesystem devvp so that it can be reused.
234 */
235 int
mfs_reclaim(void * v)236 mfs_reclaim(void *v)
237 {
238 struct vop_reclaim_args *ap = v;
239 struct vnode *vp = ap->a_vp;
240 struct mfsnode *mfsp = VTOMFS(vp);
241
242 bufq_destroy(&mfsp->mfs_bufq);
243
244 free(vp->v_data, M_MFSNODE, sizeof(struct mfsnode));
245 vp->v_data = NULL;
246 return (0);
247 }
248
249 /*
250 * Print out the contents of an mfsnode.
251 */
252 int
mfs_print(void * v)253 mfs_print(void *v)
254 {
255 #if defined(DEBUG) || defined(DIAGNOSTIC) || defined(VFSLCKDEBUG)
256 struct vop_print_args *ap = v;
257 struct mfsnode *mfsp = VTOMFS(ap->a_vp);
258
259 printf("tag VT_MFS, tid %d, base %p, size %ld\n", mfsp->mfs_tid,
260 mfsp->mfs_baseoff, mfsp->mfs_size);
261 #endif
262 return (0);
263 }
264