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