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