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