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