1 /*
2 * Copyright (c) 1989 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)mfs_vnops.c 7.22 (Berkeley) 4/16/91
34 */
35
36 #include "sys/param.h"
37 #include "sys/file.h"
38 #include "sys/time.h"
39 #include "uio.h"
40 #include "sys/errno.h" /* for inlines */
41 #include "systm.h"
42 #include "proc.h"
43 #include "buf.h"
44
45 #include "vnode.h"
46 #include "mfs_node.h"
47
48 #include "prototypes.h"
49
50 /*
51 * mfs vnode operations.
52 */
53 struct vnodeops mfs_vnodeops = {
54 mfs_lookup, /* lookup */
55 mfs_create, /* create */
56 mfs_mknod, /* mknod */
57 mfs_open, /* open */
58 mfs_close, /* close */
59 mfs_access, /* access */
60 mfs_getattr, /* getattr */
61 mfs_setattr, /* setattr */
62 mfs_read, /* read */
63 mfs_write, /* write */
64 mfs_ioctl, /* ioctl */
65 mfs_select, /* select */
66 mfs_mmap, /* mmap */
67 mfs_fsync, /* fsync */
68 mfs_seek, /* seek */
69 mfs_remove, /* remove */
70 mfs_link, /* link */
71 mfs_rename, /* rename */
72 mfs_mkdir, /* mkdir */
73 mfs_rmdir, /* rmdir */
74 mfs_symlink, /* symlink */
75 mfs_readdir, /* readdir */
76 mfs_readlink, /* readlink */
77 mfs_abortop, /* abortop */
78 mfs_inactive, /* inactive */
79 mfs_reclaim, /* reclaim */
80 mfs_lock, /* lock */
81 mfs_unlock, /* unlock */
82 mfs_bmap, /* bmap */
83 mfs_strategy, /* strategy */
84 mfs_print, /* print */
85 mfs_islocked, /* islocked */
86 mfs_advlock, /* advlock */
87 };
88
89 /*
90 * Vnode Operations.
91 *
92 * Open called to allow memory filesystem to initialize and
93 * validate before actual IO. Record our process identifier
94 * so we can tell when we are doing I/O to ourself.
95 */
96 /* ARGSUSED */
mfs_open(vp,mode,cred,p)97 mfs_open(vp, mode, cred, p)
98 register struct vnode *vp;
99 int mode;
100 struct ucred *cred;
101 struct proc *p;
102 {
103
104 if (vp->v_type != VBLK) {
105 panic("mfs_ioctl not VBLK");
106 /* NOTREACHED */
107 }
108 return (0);
109 }
110
111 /*
112 * Ioctl operation.
113 */
114 /* ARGSUSED */
115 mfs_ioctl(vp, com, data, fflag, cred, p)
116 struct vnode *vp;
117 int com;
118 caddr_t data;
119 int fflag;
120 struct ucred *cred;
121 struct proc *p;
122 {
123
124 return (-1);
125 }
126
127 /*
128 * Pass I/O requests to the memory filesystem process.
129 */
mfs_strategy(bp)130 mfs_strategy(bp)
131 register struct buf *bp;
132 {
133 register struct mfsnode *mfsp;
134 struct vnode *vp;
135 struct proc *p = curproc; /* XXX */
136
137 if (spec_find(bp->b_dev, VBLK, &vp) || vp->v_usecount == 0)
138 panic("mfs_strategy: bad dev");
139 mfsp = VTOMFS(vp);
140 if (mfsp->mfs_pid == p->p_pid) {
141 mfs_doio(bp, mfsp->mfs_baseoff);
142 } else {
143 bp->av_forw = mfsp->mfs_buflist;
144 mfsp->mfs_buflist = bp;
145 wakeup((caddr_t)vp);
146 }
147 return (0);
148 }
149
150 /*
151 * Memory file system I/O.
152 *
153 * Trivial since buffer has already been mapping into KVA space.
154 */
mfs_doio(bp,base)155 mfs_doio(bp, base)
156 register struct buf *bp;
157 caddr_t base;
158 {
159 base += (bp->b_blkno << DEV_BSHIFT);
160 if (bp->b_flags & B_READ)
161 bp->b_error = copyin(curproc, base, bp->b_un.b_addr, bp->b_bcount);
162 else
163 bp->b_error = copyout(curproc, bp->b_un.b_addr, base, bp->b_bcount);
164 if (bp->b_error)
165 bp->b_flags |= B_ERROR;
166 biodone(bp);
167 }
168
169 /*
170 * This is a noop, simply returning what one has been given.
171 */
172 mfs_bmap(vp, bn, vpp, bnp)
173 struct vnode *vp;
174 daddr_t bn;
175 struct vnode **vpp;
176 daddr_t *bnp;
177 {
178
179 if (vpp != NULL)
180 *vpp = vp;
181 if (bnp != NULL)
182 *bnp = bn;
183 return (0);
184 }
185
186 /*
187 * Memory filesystem close routine
188 */
189 /* ARGSUSED */
mfs_close(vp,flag,cred,p)190 mfs_close(vp, flag, cred, p)
191 register struct vnode *vp;
192 int flag;
193 struct ucred *cred;
194 struct proc *p;
195 {
196 register struct mfsnode *mfsp = VTOMFS(vp);
197 register struct buf *bp;
198
199 /*
200 * Finish any pending I/O requests.
201 */
202 while (bp = mfsp->mfs_buflist) {
203 mfsp->mfs_buflist = bp->av_forw;
204 mfs_doio(bp, mfsp->mfs_baseoff);
205 wakeup((caddr_t)bp);
206 }
207 /*
208 * On last close of a memory filesystem
209 * we must invalidate any in core blocks, so that
210 * we can, free up its vnode.
211 */
212 vflushbuf(vp, 0, 0);
213 if (vinvalbuf(vp, 1))
214 return (0);
215 /*
216 * There should be no way to have any more uses of this
217 * vnode, so if we find any other uses, it is a panic.
218 */
219 if (vp->v_usecount > 1)
220 printf("mfs_close: ref count %d > 1\n", vp->v_usecount);
221 if (vp->v_usecount > 1 || mfsp->mfs_buflist)
222 panic("mfs_close");
223 /*
224 * Send a request to the filesystem server to exit.
225 */
226 mfsp->mfs_buflist = (struct buf *)(-1);
227 wakeup((caddr_t)vp);
228 return (0);
229 }
230
231 /*
232 * Memory filesystem inactive routine
233 */
234 /* ARGSUSED */
235 mfs_inactive(vp, p)
236 struct vnode *vp;
237 struct proc *p;
238 {
239
240 if (VTOMFS(vp)->mfs_buflist != (struct buf *)(-1))
241 panic("mfs_inactive: not inactive");
242 return (0);
243 }
244
245 /*
246 * Print out the contents of an mfsnode.
247 */
248 mfs_print(vp)
249 struct vnode *vp;
250 {
251 register struct mfsnode *mfsp = VTOMFS(vp);
252
253 printf("tag VT_MFS, pid %d, base %d, size %d\n", mfsp->mfs_pid,
254 mfsp->mfs_baseoff, mfsp->mfs_size);
255 }
256
257 /*
258 * Block device bad operation
259 */
mfs_badop()260 mfs_badop()
261 {
262
263 panic("mfs_badop called\n");
264 /* NOTREACHED */
265 }
266