coda_psdev.c revision 1.11 1 1.11 matt /* $NetBSD: coda_psdev.c,v 1.11 1999/09/18 05:31:42 matt Exp $ */
2 1.2 rvb
3 1.1 rvb /*
4 1.2 rvb *
5 1.2 rvb * Coda: an Experimental Distributed File System
6 1.2 rvb * Release 3.1
7 1.2 rvb *
8 1.2 rvb * Copyright (c) 1987-1998 Carnegie Mellon University
9 1.2 rvb * All Rights Reserved
10 1.2 rvb *
11 1.2 rvb * Permission to use, copy, modify and distribute this software and its
12 1.2 rvb * documentation is hereby granted, provided that both the copyright
13 1.2 rvb * notice and this permission notice appear in all copies of the
14 1.2 rvb * software, derivative works or modified versions, and any portions
15 1.2 rvb * thereof, and that both notices appear in supporting documentation, and
16 1.2 rvb * that credit is given to Carnegie Mellon University in all documents
17 1.2 rvb * and publicity pertaining to direct or indirect use of this code or its
18 1.2 rvb * derivatives.
19 1.2 rvb *
20 1.2 rvb * CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS,
21 1.2 rvb * SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS
22 1.2 rvb * FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON
23 1.2 rvb * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
24 1.2 rvb * RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF
25 1.2 rvb * ANY DERIVATIVE WORK.
26 1.2 rvb *
27 1.2 rvb * Carnegie Mellon encourages users of this software to return any
28 1.2 rvb * improvements or extensions that they make, and to grant Carnegie
29 1.2 rvb * Mellon the rights to redistribute these changes without encumbrance.
30 1.2 rvb *
31 1.4 rvb * @(#) coda/coda_psdev.c,v 1.1.1.1 1998/08/29 21:26:45 rvb Exp $
32 1.2 rvb */
33 1.1 rvb
34 1.1 rvb /*
35 1.1 rvb * Mach Operating System
36 1.1 rvb * Copyright (c) 1989 Carnegie-Mellon University
37 1.1 rvb * All rights reserved. The CMU software License Agreement specifies
38 1.1 rvb * the terms and conditions for use and redistribution.
39 1.1 rvb */
40 1.1 rvb
41 1.1 rvb /*
42 1.1 rvb * This code was written for the Coda file system at Carnegie Mellon
43 1.1 rvb * University. Contributers include David Steere, James Kistler, and
44 1.1 rvb * M. Satyanarayanan. */
45 1.1 rvb
46 1.1 rvb /* These routines define the psuedo device for communication between
47 1.1 rvb * Coda's Venus and Minicache in Mach 2.6. They used to be in cfs_subr.c,
48 1.1 rvb * but I moved them to make it easier to port the Minicache without
49 1.1 rvb * porting coda. -- DCS 10/12/94
50 1.1 rvb */
51 1.1 rvb
52 1.1 rvb /*
53 1.1 rvb * HISTORY
54 1.4 rvb * $Log: coda_psdev.c,v $
55 1.11 matt * Revision 1.11 1999/09/18 05:31:42 matt
56 1.11 matt * Make this compile on alpha again.
57 1.11 matt *
58 1.10 rvb * Revision 1.10 1999/04/29 22:20:42 rvb
59 1.10 rvb * Typo/braino?
60 1.10 rvb *
61 1.10 rvb * Revision 1.9 1998/11/11 19:22:08 rvb
62 1.10 rvb * Lookup now passes up an extra flag. But old veni will
63 1.10 rvb * be ok; new veni will check /dev/cfs0 to make sure that a new
64 1.10 rvb * kernel is running.
65 1.9 rvb * Also, a bug in vc_nb_close iff CODA_SIGNAL's were seen has been
66 1.9 rvb * fixed.
67 1.9 rvb *
68 1.9 rvb * Revision 1.8 1998/11/09 16:36:16 rvb
69 1.9 rvb * Change the way unmounting happens to guarantee that the
70 1.9 rvb * client programs are allowed to finish up (coda_call is
71 1.9 rvb * forced to complete) and release their locks. Thus there
72 1.8 rvb * is a reasonable chance that the vflush implicit in the
73 1.8 rvb * unmount will not get hung on held locks.
74 1.8 rvb *
75 1.8 rvb * Revision 1.7 1998/09/28 17:55:22 rvb
76 1.8 rvb * I want to distinguish from DEBUG printouts and CODA_VERBOSE printouts.
77 1.7 rvb * The latter are normal informational messages that are sometimes
78 1.7 rvb * interesting to view.
79 1.7 rvb *
80 1.7 rvb * Revision 1.6 1998/09/26 15:24:46 tv
81 1.7 rvb * DIAGNOSTIC -> DEBUG for all non-panic messages. DIAGNOSTIC is only for
82 1.6 tv * sanity checks and should not turn on any messages not already printed
83 1.6 tv * without it.
84 1.6 tv *
85 1.6 tv * Revision 1.5 1998/09/25 15:01:13 rvb
86 1.6 tv * Conditionalize "stray" printouts under DIAGNOSTIC and DEBUG.
87 1.5 rvb * Make files compile if DEBUG is on (from Alan Barrett). Finally,
88 1.5 rvb * make coda an lkm.
89 1.5 rvb *
90 1.4 rvb * Revision 1.4 1998/09/15 02:02:59 rvb
91 1.4 rvb * Final piece of rename cfs->coda
92 1.4 rvb *
93 1.4 rvb * Revision 1.3 1998/09/12 15:05:48 rvb
94 1.3 rvb * Change cfs/CFS in symbols, strings and constants to coda/CODA
95 1.3 rvb * to avoid fs conflicts.
96 1.3 rvb *
97 1.2 rvb * Revision 1.2 1998/09/08 17:12:47 rvb
98 1.2 rvb * Pass2 complete
99 1.2 rvb *
100 1.1 rvb * Revision 1.1.1.1 1998/08/29 21:26:45 rvb
101 1.1 rvb * Very Preliminary Coda
102 1.1 rvb *
103 1.1 rvb * Revision 1.9 1998/08/28 18:12:17 rvb
104 1.1 rvb * Now it also works on FreeBSD -current. This code will be
105 1.1 rvb * committed to the FreeBSD -current and NetBSD -current
106 1.1 rvb * trees. It will then be tailored to the particular platform
107 1.1 rvb * by flushing conditional code.
108 1.1 rvb *
109 1.1 rvb * Revision 1.8 1998/08/18 17:05:15 rvb
110 1.1 rvb * Don't use __RCSID now
111 1.1 rvb *
112 1.1 rvb * Revision 1.7 1998/08/18 16:31:41 rvb
113 1.1 rvb * Sync the code for NetBSD -current; test on 1.3 later
114 1.1 rvb *
115 1.1 rvb * Revision 1.8 1998/06/09 23:30:42 rvb
116 1.1 rvb * Try to allow ^C -- take 1
117 1.1 rvb *
118 1.1 rvb * Revision 1.5.2.8 98/01/23 11:21:04 rvb
119 1.1 rvb * Sync with 2.2.5
120 1.1 rvb *
121 1.1 rvb * Revision 1.5.2.7 98/01/22 22:22:21 rvb
122 1.3 rvb * sync 1.2 and 1.3
123 1.1 rvb *
124 1.1 rvb * Revision 1.5.2.6 98/01/22 13:11:24 rvb
125 1.1 rvb * Move make_coda_node ctlfid later so vfsp is known; work on ^c and ^z
126 1.1 rvb *
127 1.1 rvb * Revision 1.5.2.5 97/12/16 22:01:27 rvb
128 1.1 rvb * Oops add cfs_subr.h cfs_venus.h; sync with peter
129 1.1 rvb *
130 1.1 rvb * Revision 1.5.2.4 97/12/16 12:40:05 rvb
131 1.3 rvb * Sync with 1.3
132 1.1 rvb *
133 1.1 rvb * Revision 1.5.2.3 97/12/10 14:08:24 rvb
134 1.1 rvb * Fix O_ flags; check result in coda_call
135 1.1 rvb *
136 1.1 rvb * Revision 1.5.2.2 97/12/10 11:40:24 rvb
137 1.1 rvb * No more ody
138 1.1 rvb *
139 1.1 rvb * Revision 1.5.2.1 97/12/06 17:41:20 rvb
140 1.1 rvb * Sync with peters coda.h
141 1.1 rvb *
142 1.1 rvb * Revision 1.5 97/12/05 10:39:16 rvb
143 1.1 rvb * Read CHANGES
144 1.1 rvb *
145 1.1 rvb * Revision 1.4.18.9 97/12/05 08:58:07 rvb
146 1.1 rvb * peter found this one
147 1.1 rvb *
148 1.1 rvb * Revision 1.4.18.8 97/11/26 15:28:57 rvb
149 1.1 rvb * Cant make downcall pbuf == union cfs_downcalls yet
150 1.1 rvb *
151 1.1 rvb * Revision 1.4.18.7 97/11/25 09:40:49 rvb
152 1.1 rvb * Final cfs_venus.c w/o macros, but one locking bug
153 1.1 rvb *
154 1.1 rvb * Revision 1.4.18.6 97/11/20 11:46:41 rvb
155 1.1 rvb * Capture current cfs_venus
156 1.1 rvb *
157 1.1 rvb * Revision 1.4.18.5 97/11/18 10:27:15 rvb
158 1.1 rvb * cfs_nbsd.c is DEAD!!!; integrated into cfs_vf/vnops.c
159 1.1 rvb * cfs_nb_foo and cfs_foo are joined
160 1.1 rvb *
161 1.1 rvb * Revision 1.4.18.4 97/11/13 22:02:59 rvb
162 1.1 rvb * pass2 cfs_NetBSD.h mt
163 1.1 rvb *
164 1.1 rvb * Revision 1.4.18.3 97/11/12 12:09:38 rvb
165 1.1 rvb * reorg pass1
166 1.1 rvb *
167 1.1 rvb * Revision 1.4.18.2 97/10/29 16:06:09 rvb
168 1.1 rvb * Kill DYING
169 1.1 rvb *
170 1.1 rvb * Revision 1.4.18.1 1997/10/28 23:10:15 rvb
171 1.1 rvb * >64Meg; venus can be killed!
172 1.1 rvb *
173 1.1 rvb * Revision 1.4 1996/12/12 22:10:58 bnoble
174 1.1 rvb * Fixed the "downcall invokes venus operation" deadlock in all known cases.
175 1.1 rvb * There may be more
176 1.1 rvb *
177 1.1 rvb * Revision 1.3 1996/11/13 04:14:20 bnoble
178 1.1 rvb * Merging BNOBLE_WORK_6_20_96 into main line
179 1.1 rvb *
180 1.1 rvb * Revision 1.2.8.1 1996/08/22 14:25:04 bnoble
181 1.1 rvb * Added a return code from vc_nb_close
182 1.1 rvb *
183 1.1 rvb * Revision 1.2 1996/01/02 16:56:58 bnoble
184 1.3 rvb * Added support for Coda MiniCache and raw inode calls (final commit)
185 1.1 rvb *
186 1.1 rvb * Revision 1.1.2.1 1995/12/20 01:57:24 bnoble
187 1.1 rvb * Added CODA-specific files
188 1.1 rvb *
189 1.1 rvb * Revision 1.1 1995/03/14 20:52:15 bnoble
190 1.1 rvb * Initial revision
191 1.1 rvb *
192 1.1 rvb */
193 1.3 rvb
194 1.1 rvb /* These routines are the device entry points for Venus. */
195 1.5 rvb
196 1.5 rvb extern int coda_nc_initialized; /* Set if cache has been initialized */
197 1.5 rvb
198 1.3 rvb #ifdef _LKM
199 1.5 rvb #define NVCODA 4
200 1.5 rvb #else
201 1.1 rvb #include <vcoda.h>
202 1.1 rvb #endif
203 1.1 rvb
204 1.1 rvb #include <sys/param.h>
205 1.1 rvb #include <sys/systm.h>
206 1.1 rvb #include <sys/kernel.h>
207 1.1 rvb #include <sys/malloc.h>
208 1.1 rvb #include <sys/proc.h>
209 1.1 rvb #include <sys/mount.h>
210 1.1 rvb #include <sys/file.h>
211 1.1 rvb #include <sys/ioctl.h>
212 1.4 rvb #include <sys/poll.h>
213 1.4 rvb #include <sys/select.h>
214 1.4 rvb
215 1.4 rvb #include <coda/coda.h>
216 1.5 rvb #include <coda/cnode.h>
217 1.1 rvb #include <coda/coda_namecache.h>
218 1.2 rvb #include <coda/coda_io.h>
219 1.2 rvb #include <coda/coda_psdev.h>
220 1.3 rvb
221 1.8 rvb #define CTL_C
222 1.8 rvb
223 1.8 rvb int coda_psdev_print_entry = 0;
224 1.8 rvb static
225 1.8 rvb int outstanding_upcalls = 0;
226 1.8 rvb int coda_call_sleep = PZERO - 1;
227 1.8 rvb #ifdef CTL_C
228 1.3 rvb int coda_pcatch = PCATCH;
229 1.3 rvb #else
230 1.1 rvb #endif
231 1.3 rvb
232 1.1 rvb #define ENTRY if(coda_psdev_print_entry) myprintf(("Entered %s\n",__FUNCTION__))
233 1.1 rvb
234 1.1 rvb void vcodaattach(int n);
235 1.1 rvb
236 1.1 rvb struct vmsg {
237 1.1 rvb struct queue vm_chain;
238 1.1 rvb caddr_t vm_data;
239 1.1 rvb u_short vm_flags;
240 1.1 rvb u_short vm_inSize; /* Size is at most 5000 bytes */
241 1.1 rvb u_short vm_outSize;
242 1.1 rvb u_short vm_opcode; /* copied from data to save ptr lookup */
243 1.1 rvb int vm_unique;
244 1.1 rvb caddr_t vm_sleep; /* Not used by Mach. */
245 1.1 rvb };
246 1.1 rvb
247 1.1 rvb #define VM_READ 1
248 1.3 rvb #define VM_WRITE 2
249 1.1 rvb #define VM_INTR 4
250 1.3 rvb
251 1.1 rvb /* vcodaattach: do nothing */
252 1.1 rvb void
253 1.1 rvb vcodaattach(n)
254 1.1 rvb int n;
255 1.1 rvb {
256 1.1 rvb }
257 1.1 rvb
258 1.1 rvb /*
259 1.1 rvb * These functions are written for NetBSD.
260 1.1 rvb */
261 1.1 rvb int
262 1.1 rvb vc_nb_open(dev, flag, mode, p)
263 1.1 rvb dev_t dev;
264 1.1 rvb int flag;
265 1.1 rvb int mode;
266 1.1 rvb struct proc *p; /* NetBSD only */
267 1.1 rvb {
268 1.1 rvb register struct vcomm *vcp;
269 1.3 rvb
270 1.1 rvb ENTRY;
271 1.1 rvb
272 1.3 rvb if (minor(dev) >= NVCODA || minor(dev) < 0)
273 1.3 rvb return(ENXIO);
274 1.1 rvb
275 1.3 rvb if (!coda_nc_initialized)
276 1.1 rvb coda_nc_init();
277 1.1 rvb
278 1.1 rvb vcp = &coda_mnttbl[minor(dev)].mi_vcomm;
279 1.1 rvb if (VC_OPEN(vcp))
280 1.1 rvb return(EBUSY);
281 1.1 rvb
282 1.1 rvb bzero(&(vcp->vc_selproc), sizeof (struct selinfo));
283 1.1 rvb INIT_QUEUE(vcp->vc_requests);
284 1.3 rvb INIT_QUEUE(vcp->vc_replys);
285 1.3 rvb MARK_VC_OPEN(vcp);
286 1.1 rvb
287 1.1 rvb coda_mnttbl[minor(dev)].mi_vfsp = NULL;
288 1.1 rvb coda_mnttbl[minor(dev)].mi_rootvp = NULL;
289 1.1 rvb
290 1.1 rvb return(0);
291 1.1 rvb }
292 1.1 rvb
293 1.1 rvb int
294 1.1 rvb vc_nb_close (dev, flag, mode, p)
295 1.1 rvb dev_t dev;
296 1.1 rvb int flag;
297 1.1 rvb int mode;
298 1.9 rvb struct proc *p;
299 1.3 rvb {
300 1.1 rvb register struct vcomm *vcp;
301 1.1 rvb register struct vmsg *vmp, *nvmp = NULL;
302 1.1 rvb struct coda_mntinfo *mi;
303 1.1 rvb int err;
304 1.3 rvb
305 1.1 rvb ENTRY;
306 1.1 rvb
307 1.3 rvb if (minor(dev) >= NVCODA || minor(dev) < 0)
308 1.1 rvb return(ENXIO);
309 1.1 rvb
310 1.1 rvb mi = &coda_mnttbl[minor(dev)];
311 1.1 rvb vcp = &(mi->mi_vcomm);
312 1.1 rvb
313 1.1 rvb if (!VC_OPEN(vcp))
314 1.1 rvb panic("vcclose: not open");
315 1.1 rvb
316 1.1 rvb /* prevent future operations on this vfs from succeeding by auto-
317 1.1 rvb * unmounting any vfs mounted via this device. This frees user or
318 1.1 rvb * sysadm from having to remember where all mount points are located.
319 1.8 rvb * Put this before WAKEUPs to avoid queuing new messages between
320 1.8 rvb * the WAKEUP and the unmount (which can happen if we're unlucky)
321 1.8 rvb */
322 1.8 rvb if (!mi->mi_rootvp) {
323 1.1 rvb /* just a simple open/close w no mount */
324 1.8 rvb MARK_VC_CLOSED(vcp);
325 1.8 rvb return 0;
326 1.8 rvb }
327 1.8 rvb
328 1.8 rvb /* Let unmount know this is for real */
329 1.8 rvb VTOC(mi->mi_rootvp)->c_flags |= C_UNMOUNTING;
330 1.1 rvb if (vfs_busy(mi->mi_vfsp, 0, 0))
331 1.1 rvb return (EBUSY);
332 1.1 rvb coda_unmounting(mi->mi_vfsp);
333 1.1 rvb
334 1.10 rvb /* Wakeup clients so they can return. */
335 1.1 rvb for (vmp = (struct vmsg *)GETNEXT(vcp->vc_requests);
336 1.9 rvb !EOQ(vmp, vcp->vc_requests);
337 1.1 rvb vmp = nvmp)
338 1.1 rvb {
339 1.3 rvb nvmp = (struct vmsg *)GETNEXT(vmp->vm_chain);
340 1.3 rvb /* Free signal request messages and don't wakeup cause
341 1.3 rvb no one is waiting. */
342 1.1 rvb if (vmp->vm_opcode == CODA_SIGNAL) {
343 1.1 rvb CODA_FREE((caddr_t)vmp->vm_data, (u_int)VC_IN_NO_DATA);
344 1.8 rvb CODA_FREE((caddr_t)vmp, (u_int)sizeof(struct vmsg));
345 1.1 rvb continue;
346 1.1 rvb }
347 1.8 rvb outstanding_upcalls++;
348 1.1 rvb wakeup(&vmp->vm_sleep);
349 1.1 rvb }
350 1.1 rvb
351 1.1 rvb for (vmp = (struct vmsg *)GETNEXT(vcp->vc_replys);
352 1.8 rvb !EOQ(vmp, vcp->vc_replys);
353 1.1 rvb vmp = (struct vmsg *)GETNEXT(vmp->vm_chain))
354 1.1 rvb {
355 1.8 rvb outstanding_upcalls++;
356 1.1 rvb wakeup(&vmp->vm_sleep);
357 1.8 rvb }
358 1.8 rvb
359 1.8 rvb MARK_VC_CLOSED(vcp);
360 1.8 rvb
361 1.8 rvb if (outstanding_upcalls) {
362 1.8 rvb #ifdef CODA_VERBOSE
363 1.8 rvb printf("presleep: outstanding_upcalls = %d\n", outstanding_upcalls);
364 1.8 rvb (void) tsleep(&outstanding_upcalls, coda_call_sleep, "coda_umount", 0);
365 1.8 rvb printf("postsleep: outstanding_upcalls = %d\n", outstanding_upcalls);
366 1.8 rvb #else
367 1.8 rvb (void) tsleep(&outstanding_upcalls, coda_call_sleep, "coda_umount", 0);
368 1.8 rvb #endif
369 1.8 rvb }
370 1.8 rvb
371 1.8 rvb err = dounmount(mi->mi_vfsp, flag, p);
372 1.1 rvb if (err)
373 1.1 rvb myprintf(("Error %d unmounting vfs in vcclose(%d)\n",
374 1.1 rvb err, minor(dev)));
375 1.1 rvb return 0;
376 1.1 rvb }
377 1.1 rvb
378 1.1 rvb int
379 1.1 rvb vc_nb_read(dev, uiop, flag)
380 1.1 rvb dev_t dev;
381 1.1 rvb struct uio *uiop;
382 1.1 rvb int flag;
383 1.1 rvb {
384 1.1 rvb register struct vcomm * vcp;
385 1.1 rvb register struct vmsg *vmp;
386 1.1 rvb int error = 0;
387 1.3 rvb
388 1.1 rvb ENTRY;
389 1.1 rvb
390 1.3 rvb if (minor(dev) >= NVCODA || minor(dev) < 0)
391 1.1 rvb return(ENXIO);
392 1.1 rvb
393 1.1 rvb vcp = &coda_mnttbl[minor(dev)].mi_vcomm;
394 1.1 rvb /* Get message at head of request queue. */
395 1.1 rvb if (EMPTY(vcp->vc_requests))
396 1.1 rvb return(0); /* Nothing to read */
397 1.1 rvb
398 1.1 rvb vmp = (struct vmsg *)GETNEXT(vcp->vc_requests);
399 1.1 rvb
400 1.1 rvb /* Move the input args into userspace */
401 1.1 rvb uiop->uio_rw = UIO_READ;
402 1.1 rvb error = uiomove(vmp->vm_data, vmp->vm_inSize, uiop);
403 1.1 rvb if (error) {
404 1.1 rvb myprintf(("vcread: error (%d) on uiomove\n", error));
405 1.5 rvb error = EINVAL;
406 1.1 rvb }
407 1.1 rvb
408 1.1 rvb #ifdef OLD_DIAGNOSTIC
409 1.1 rvb if (vmp->vm_chain.forw == 0 || vmp->vm_chain.back == 0)
410 1.1 rvb panic("vc_nb_read: bad chain");
411 1.1 rvb #endif
412 1.1 rvb
413 1.1 rvb REMQUE(vmp->vm_chain);
414 1.3 rvb
415 1.3 rvb /* If request was a signal, free up the message and don't
416 1.1 rvb enqueue it in the reply queue. */
417 1.1 rvb if (vmp->vm_opcode == CODA_SIGNAL) {
418 1.3 rvb if (codadebug)
419 1.3 rvb myprintf(("vcread: signal msg (%d, %d)\n",
420 1.1 rvb vmp->vm_opcode, vmp->vm_unique));
421 1.1 rvb CODA_FREE((caddr_t)vmp->vm_data, (u_int)VC_IN_NO_DATA);
422 1.1 rvb CODA_FREE((caddr_t)vmp, (u_int)sizeof(struct vmsg));
423 1.1 rvb return(error);
424 1.1 rvb }
425 1.1 rvb
426 1.1 rvb vmp->vm_flags |= VM_READ;
427 1.1 rvb INSQUE(vmp->vm_chain, vcp->vc_replys);
428 1.1 rvb
429 1.1 rvb return(error);
430 1.1 rvb }
431 1.1 rvb
432 1.1 rvb int
433 1.1 rvb vc_nb_write(dev, uiop, flag)
434 1.1 rvb dev_t dev;
435 1.1 rvb struct uio *uiop;
436 1.1 rvb int flag;
437 1.3 rvb {
438 1.1 rvb register struct vcomm * vcp;
439 1.1 rvb register struct vmsg *vmp;
440 1.1 rvb struct coda_out_hdr *out;
441 1.1 rvb u_long seq;
442 1.1 rvb u_long opcode;
443 1.1 rvb int buf[2];
444 1.1 rvb int error = 0;
445 1.3 rvb
446 1.1 rvb ENTRY;
447 1.1 rvb
448 1.3 rvb if (minor(dev) >= NVCODA || minor(dev) < 0)
449 1.1 rvb return(ENXIO);
450 1.1 rvb
451 1.1 rvb vcp = &coda_mnttbl[minor(dev)].mi_vcomm;
452 1.1 rvb
453 1.1 rvb /* Peek at the opcode, unique without transfering the data. */
454 1.1 rvb uiop->uio_rw = UIO_WRITE;
455 1.1 rvb error = uiomove((caddr_t)buf, sizeof(int) * 2, uiop);
456 1.1 rvb if (error) {
457 1.1 rvb myprintf(("vcwrite: error (%d) on uiomove\n", error));
458 1.1 rvb return(EINVAL);
459 1.1 rvb }
460 1.1 rvb
461 1.3 rvb opcode = buf[0];
462 1.1 rvb seq = buf[1];
463 1.1 rvb
464 1.1 rvb if (codadebug)
465 1.1 rvb myprintf(("vcwrite got a call for %ld.%ld\n", opcode, seq));
466 1.1 rvb
467 1.1 rvb if (DOWNCALL(opcode)) {
468 1.1 rvb union outputArgs pbuf;
469 1.3 rvb
470 1.1 rvb /* get the rest of the data. */
471 1.1 rvb uiop->uio_rw = UIO_WRITE;
472 1.1 rvb error = uiomove((caddr_t)&pbuf.coda_purgeuser.oh.result, sizeof(pbuf) - (sizeof(int)*2), uiop);
473 1.1 rvb if (error) {
474 1.1 rvb myprintf(("vcwrite: error (%d) on uiomove (Op %ld seq %ld)\n",
475 1.1 rvb error, opcode, seq));
476 1.1 rvb return(EINVAL);
477 1.1 rvb }
478 1.1 rvb
479 1.1 rvb return handleDownCall(opcode, &pbuf);
480 1.1 rvb }
481 1.1 rvb
482 1.1 rvb /* Look for the message on the (waiting for) reply queue. */
483 1.1 rvb for (vmp = (struct vmsg *)GETNEXT(vcp->vc_replys);
484 1.1 rvb !EOQ(vmp, vcp->vc_replys);
485 1.1 rvb vmp = (struct vmsg *)GETNEXT(vmp->vm_chain))
486 1.1 rvb {
487 1.1 rvb if (vmp->vm_unique == seq) break;
488 1.3 rvb }
489 1.1 rvb
490 1.1 rvb if (EOQ(vmp, vcp->vc_replys)) {
491 1.1 rvb if (codadebug)
492 1.1 rvb myprintf(("vcwrite: msg (%ld, %ld) not found\n", opcode, seq));
493 1.1 rvb
494 1.1 rvb return(ESRCH);
495 1.1 rvb }
496 1.1 rvb
497 1.1 rvb /* Remove the message from the reply queue */
498 1.3 rvb REMQUE(vmp->vm_chain);
499 1.1 rvb
500 1.1 rvb /* move data into response buffer. */
501 1.1 rvb out = (struct coda_out_hdr *)vmp->vm_data;
502 1.1 rvb /* Don't need to copy opcode and uniquifier. */
503 1.11 matt
504 1.11 matt /* get the rest of the data. */
505 1.1 rvb if (vmp->vm_outSize < uiop->uio_resid) {
506 1.1 rvb myprintf(("vcwrite: more data than asked for (%d < %lu)\n",
507 1.1 rvb vmp->vm_outSize, (unsigned long) uiop->uio_resid));
508 1.1 rvb wakeup(&vmp->vm_sleep); /* Notify caller of the error. */
509 1.1 rvb return(EINVAL);
510 1.1 rvb }
511 1.1 rvb
512 1.1 rvb buf[0] = uiop->uio_resid; /* Save this value. */
513 1.1 rvb uiop->uio_rw = UIO_WRITE;
514 1.1 rvb error = uiomove((caddr_t) &out->result, vmp->vm_outSize - (sizeof(int) * 2), uiop);
515 1.1 rvb if (error) {
516 1.1 rvb myprintf(("vcwrite: error (%d) on uiomove (op %ld seq %ld)\n",
517 1.1 rvb error, opcode, seq));
518 1.1 rvb return(EINVAL);
519 1.1 rvb }
520 1.1 rvb
521 1.1 rvb /* I don't think these are used, but just in case. */
522 1.1 rvb /* XXX - aren't these two already correct? -bnoble */
523 1.1 rvb out->opcode = opcode;
524 1.1 rvb out->unique = seq;
525 1.1 rvb vmp->vm_outSize = buf[0]; /* Amount of data transferred? */
526 1.1 rvb vmp->vm_flags |= VM_WRITE;
527 1.1 rvb wakeup(&vmp->vm_sleep);
528 1.1 rvb
529 1.1 rvb return(0);
530 1.1 rvb }
531 1.1 rvb
532 1.5 rvb int
533 1.1 rvb vc_nb_ioctl(dev, cmd, addr, flag, p)
534 1.1 rvb dev_t dev;
535 1.1 rvb u_long cmd;
536 1.1 rvb caddr_t addr;
537 1.1 rvb int flag;
538 1.1 rvb struct proc *p;
539 1.1 rvb {
540 1.3 rvb ENTRY;
541 1.3 rvb
542 1.3 rvb switch(cmd) {
543 1.1 rvb case CODARESIZE: {
544 1.1 rvb struct coda_resize *data = (struct coda_resize *)addr;
545 1.3 rvb return(coda_nc_resize(data->hashsize, data->heapsize, IS_DOWNCALL));
546 1.3 rvb break;
547 1.3 rvb }
548 1.1 rvb case CODASTATS:
549 1.1 rvb if (coda_nc_use) {
550 1.1 rvb coda_nc_gather_stats();
551 1.1 rvb return(0);
552 1.1 rvb } else {
553 1.3 rvb return(ENODEV);
554 1.3 rvb }
555 1.3 rvb break;
556 1.1 rvb case CODAPRINT:
557 1.1 rvb if (coda_nc_use) {
558 1.1 rvb print_coda_nc();
559 1.1 rvb return(0);
560 1.1 rvb } else {
561 1.9 rvb return(ENODEV);
562 1.9 rvb }
563 1.9 rvb break;
564 1.9 rvb case CIOC_KERNEL_VERSION:
565 1.9 rvb switch (*(u_int *)addr) {
566 1.9 rvb case 0:
567 1.9 rvb *(u_int *)addr = coda_kernel_version;
568 1.9 rvb return 0;
569 1.9 rvb break;
570 1.9 rvb case 1:
571 1.9 rvb case 2:
572 1.9 rvb if (coda_kernel_version != *(u_int *)addr)
573 1.9 rvb return ENOENT;
574 1.9 rvb else
575 1.9 rvb return 0;
576 1.9 rvb default:
577 1.1 rvb return ENOENT;
578 1.1 rvb }
579 1.1 rvb break;
580 1.1 rvb default :
581 1.1 rvb return(EINVAL);
582 1.1 rvb break;
583 1.1 rvb }
584 1.1 rvb }
585 1.1 rvb
586 1.1 rvb int
587 1.1 rvb vc_nb_poll(dev, events, p)
588 1.1 rvb dev_t dev;
589 1.1 rvb int events;
590 1.1 rvb struct proc *p;
591 1.1 rvb {
592 1.1 rvb register struct vcomm *vcp;
593 1.1 rvb int event_msk = 0;
594 1.3 rvb
595 1.1 rvb ENTRY;
596 1.1 rvb
597 1.3 rvb if (minor(dev) >= NVCODA || minor(dev) < 0)
598 1.1 rvb return(ENXIO);
599 1.1 rvb
600 1.1 rvb vcp = &coda_mnttbl[minor(dev)].mi_vcomm;
601 1.1 rvb
602 1.1 rvb event_msk = events & (POLLIN|POLLRDNORM);
603 1.1 rvb if (!event_msk)
604 1.1 rvb return(0);
605 1.1 rvb
606 1.1 rvb if (!EMPTY(vcp->vc_requests))
607 1.1 rvb return(events & (POLLIN|POLLRDNORM));
608 1.1 rvb
609 1.1 rvb selrecord(p, &(vcp->vc_selproc));
610 1.1 rvb
611 1.1 rvb return(0);
612 1.1 rvb }
613 1.1 rvb
614 1.3 rvb /*
615 1.1 rvb * Statistics
616 1.1 rvb */
617 1.1 rvb struct coda_clstat coda_clstat;
618 1.1 rvb
619 1.1 rvb /*
620 1.1 rvb * Key question: whether to sleep interuptably or uninteruptably when
621 1.1 rvb * waiting for Venus. The former seems better (cause you can ^C a
622 1.1 rvb * job), but then GNU-EMACS completion breaks. Use tsleep with no
623 1.1 rvb * timeout, and no longjmp happens. But, when sleeping
624 1.1 rvb * "uninterruptibly", we don't get told if it returns abnormally
625 1.1 rvb * (e.g. kill -9).
626 1.3 rvb */
627 1.3 rvb
628 1.1 rvb int
629 1.1 rvb coda_call(mntinfo, inSize, outSize, buffer)
630 1.1 rvb struct coda_mntinfo *mntinfo; int inSize; int *outSize; caddr_t buffer;
631 1.1 rvb {
632 1.1 rvb struct vcomm *vcp;
633 1.1 rvb struct vmsg *vmp;
634 1.4 rvb int error;
635 1.1 rvb #ifdef CTL_C
636 1.4 rvb struct proc *p = curproc;
637 1.1 rvb sigset_t psig_omask;
638 1.1 rvb int i;
639 1.1 rvb psig_omask = p->p_siglist; /* array assignment */
640 1.1 rvb #endif
641 1.1 rvb if (mntinfo == NULL) {
642 1.1 rvb /* Unlikely, but could be a race condition with a dying warden */
643 1.1 rvb return ENODEV;
644 1.1 rvb }
645 1.3 rvb
646 1.3 rvb vcp = &(mntinfo->mi_vcomm);
647 1.1 rvb
648 1.1 rvb coda_clstat.ncalls++;
649 1.1 rvb coda_clstat.reqs[((struct coda_in_hdr *)buffer)->opcode]++;
650 1.1 rvb
651 1.3 rvb if (!VC_OPEN(vcp))
652 1.1 rvb return(ENODEV);
653 1.1 rvb
654 1.1 rvb CODA_ALLOC(vmp,struct vmsg *,sizeof(struct vmsg));
655 1.1 rvb /* Format the request message. */
656 1.1 rvb vmp->vm_data = buffer;
657 1.1 rvb vmp->vm_flags = 0;
658 1.3 rvb vmp->vm_inSize = inSize;
659 1.1 rvb vmp->vm_outSize
660 1.3 rvb = *outSize ? *outSize : inSize; /* |buffer| >= inSize */
661 1.1 rvb vmp->vm_opcode = ((struct coda_in_hdr *)buffer)->opcode;
662 1.1 rvb vmp->vm_unique = ++vcp->vc_seq;
663 1.1 rvb if (codadebug)
664 1.1 rvb myprintf(("Doing a call for %d.%d\n",
665 1.3 rvb vmp->vm_opcode, vmp->vm_unique));
666 1.1 rvb
667 1.1 rvb /* Fill in the common input args. */
668 1.1 rvb ((struct coda_in_hdr *)buffer)->unique = vmp->vm_unique;
669 1.1 rvb
670 1.1 rvb /* Append msg to request queue and poke Venus. */
671 1.1 rvb INSQUE(vmp->vm_chain, vcp->vc_requests);
672 1.1 rvb selwakeup(&(vcp->vc_selproc));
673 1.1 rvb
674 1.1 rvb /* We can be interrupted while we wait for Venus to process
675 1.1 rvb * our request. If the interrupt occurs before Venus has read
676 1.1 rvb * the request, we dequeue and return. If it occurs after the
677 1.1 rvb * read but before the reply, we dequeue, send a signal
678 1.1 rvb * message, and return. If it occurs after the reply we ignore
679 1.1 rvb * it. In no case do we want to restart the syscall. If it
680 1.1 rvb * was interrupted by a venus shutdown (vcclose), return
681 1.1 rvb * ENODEV. */
682 1.3 rvb
683 1.1 rvb /* Ignore return, We have to check anyway */
684 1.1 rvb #ifdef CTL_C
685 1.1 rvb /* This is work in progress. Setting coda_pcatch lets tsleep reawaken
686 1.1 rvb on a ^c or ^z. The problem is that emacs sets certain interrupts
687 1.1 rvb as SA_RESTART. This means that we should exit sleep handle the
688 1.1 rvb "signal" and then go to sleep again. Mostly this is done by letting
689 1.1 rvb the syscall complete and be restarted. We are not idempotent and
690 1.1 rvb can not do this. A better solution is necessary.
691 1.3 rvb */
692 1.1 rvb i = 0;
693 1.1 rvb do {
694 1.1 rvb error = tsleep(&vmp->vm_sleep, (coda_call_sleep|coda_pcatch), "coda_call", hz*2);
695 1.7 rvb if (error == 0)
696 1.3 rvb break;
697 1.5 rvb else if (error == EWOULDBLOCK) {
698 1.4 rvb #ifdef CODA_VERBOSE
699 1.4 rvb printf("coda_call: tsleep TIMEOUT %d sec\n", 2+2*i);
700 1.7 rvb #endif
701 1.3 rvb } else if (sigismember(&p->p_siglist, SIGIO)) {
702 1.5 rvb sigaddset(&p->p_sigmask, SIGIO);
703 1.8 rvb #ifdef CODA_VERBOSE
704 1.8 rvb printf("coda_call: tsleep returns %d SIGIO, cnt %d\n", error, i);
705 1.8 rvb #endif
706 1.8 rvb } else if (sigismember(&p->p_siglist, SIGALRM)) {
707 1.8 rvb sigaddset(&p->p_sigmask, SIGALRM);
708 1.1 rvb #ifdef CODA_VERBOSE
709 1.4 rvb printf("coda_call: tsleep returns %d SIGALRM, cnt %d\n", error, i);
710 1.4 rvb #endif
711 1.4 rvb } else {
712 1.4 rvb sigset_t tmp;
713 1.7 rvb tmp = p->p_siglist; /* array assignment */
714 1.3 rvb sigminusset(&p->p_sigmask, &tmp);
715 1.4 rvb
716 1.4 rvb #ifdef CODA_VERBOSE
717 1.4 rvb printf("coda_call: tsleep returns %d, cnt %d\n", error, i);
718 1.4 rvb printf("coda_call: siglist = %x.%x.%x.%x, sigmask = %x.%x.%x.%x, mask %x.%x.%x.%x\n",
719 1.4 rvb p->p_siglist.__bits[0], p->p_siglist.__bits[1],
720 1.4 rvb p->p_siglist.__bits[2], p->p_siglist.__bits[3],
721 1.5 rvb p->p_sigmask.__bits[0], p->p_sigmask.__bits[1],
722 1.1 rvb p->p_sigmask.__bits[2], p->p_sigmask.__bits[3],
723 1.5 rvb tmp.__bits[0], tmp.__bits[1], tmp.__bits[2], tmp.__bits[3]);
724 1.4 rvb #endif
725 1.4 rvb break;
726 1.4 rvb #ifdef notyet
727 1.4 rvb sigminusset(&p->p_sigmask, &p->p_siglist);
728 1.4 rvb printf("coda_call: siglist = %x.%x.%x.%x, sigmask = %x.%x.%x.%x\n",
729 1.4 rvb p->p_siglist.__bits[0], p->p_siglist.__bits[1],
730 1.5 rvb p->p_siglist.__bits[2], p->p_siglist.__bits[3],
731 1.1 rvb p->p_sigmask.__bits[0], p->p_sigmask.__bits[1],
732 1.8 rvb p->p_sigmask.__bits[2], p->p_sigmask.__bits[3]);
733 1.4 rvb #endif
734 1.1 rvb }
735 1.3 rvb } while (error && i++ < 128 && VC_OPEN(vcp));
736 1.1 rvb p->p_siglist = psig_omask; /* array assignment */
737 1.1 rvb #else
738 1.1 rvb (void) tsleep(&vmp->vm_sleep, coda_call_sleep, "coda_call", 0);
739 1.1 rvb #endif
740 1.1 rvb if (VC_OPEN(vcp)) { /* Venus is still alive */
741 1.1 rvb /* Op went through, interrupt or not... */
742 1.1 rvb if (vmp->vm_flags & VM_WRITE) {
743 1.1 rvb error = 0;
744 1.1 rvb *outSize = vmp->vm_outSize;
745 1.1 rvb }
746 1.7 rvb
747 1.7 rvb else if (!(vmp->vm_flags & VM_READ)) {
748 1.7 rvb /* Interrupted before venus read it. */
749 1.5 rvb #ifdef CODA_VERBOSE
750 1.5 rvb if (1)
751 1.1 rvb #else
752 1.1 rvb if (codadebug)
753 1.1 rvb #endif
754 1.1 rvb myprintf(("interrupted before read: op = %d.%d, flags = %x\n",
755 1.1 rvb vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags));
756 1.1 rvb REMQUE(vmp->vm_chain);
757 1.1 rvb error = EINTR;
758 1.1 rvb }
759 1.1 rvb
760 1.1 rvb else {
761 1.3 rvb /* (!(vmp->vm_flags & VM_WRITE)) means interrupted after
762 1.1 rvb upcall started */
763 1.1 rvb /* Interrupted after start of upcall, send venus a signal */
764 1.7 rvb struct coda_in_hdr *dog;
765 1.7 rvb struct vmsg *svmp;
766 1.7 rvb
767 1.5 rvb #ifdef CODA_VERBOSE
768 1.5 rvb if (1)
769 1.1 rvb #else
770 1.1 rvb if (codadebug)
771 1.1 rvb #endif
772 1.1 rvb myprintf(("Sending Venus a signal: op = %d.%d, flags = %x\n",
773 1.1 rvb vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags));
774 1.1 rvb
775 1.3 rvb REMQUE(vmp->vm_chain);
776 1.1 rvb error = EINTR;
777 1.3 rvb
778 1.3 rvb CODA_ALLOC(svmp, struct vmsg *, sizeof (struct vmsg));
779 1.1 rvb
780 1.1 rvb CODA_ALLOC((svmp->vm_data), char *, sizeof (struct coda_in_hdr));
781 1.3 rvb dog = (struct coda_in_hdr *)svmp->vm_data;
782 1.1 rvb
783 1.3 rvb svmp->vm_flags = 0;
784 1.3 rvb dog->opcode = svmp->vm_opcode = CODA_SIGNAL;
785 1.1 rvb dog->unique = svmp->vm_unique = vmp->vm_unique;
786 1.3 rvb svmp->vm_inSize = sizeof (struct coda_in_hdr);
787 1.3 rvb /*??? rvb */ svmp->vm_outSize = sizeof (struct coda_in_hdr);
788 1.1 rvb
789 1.1 rvb if (codadebug)
790 1.1 rvb myprintf(("coda_call: enqueing signal msg (%d, %d)\n",
791 1.1 rvb svmp->vm_opcode, svmp->vm_unique));
792 1.1 rvb
793 1.1 rvb /* insert at head of queue! */
794 1.1 rvb INSQUE(svmp->vm_chain, vcp->vc_requests);
795 1.1 rvb selwakeup(&(vcp->vc_selproc));
796 1.1 rvb }
797 1.3 rvb }
798 1.1 rvb
799 1.1 rvb else { /* If venus died (!VC_OPEN(vcp)) */
800 1.1 rvb if (codadebug)
801 1.1 rvb myprintf(("vcclose woke op %d.%d flags %d\n",
802 1.1 rvb vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags));
803 1.1 rvb
804 1.3 rvb error = ENODEV;
805 1.8 rvb }
806 1.8 rvb
807 1.8 rvb CODA_FREE(vmp, sizeof(struct vmsg));
808 1.1 rvb
809 1.1 rvb if (outstanding_upcalls > 0 && (--outstanding_upcalls == 0))
810 1.3 rvb wakeup(&outstanding_upcalls);
811 1.1 rvb
812 1.1 rvb if (!error)
813 1.4 rvb error = ((struct coda_out_hdr *)buffer)->result;
814 return(error);
815 }
816
817