2 * Mostly platform independent upcall operations to Venus:
7 * Copyright (C) 1996 Peter J. Braam <braam@maths.ox.ac.uk>,
8 * Michael Callahan <callahan@maths.ox.ac.uk>
10 * Redone for Linux 2.1
11 * Copyright (C) 1997 Carnegie Mellon University
13 * Carnegie Mellon University encourages users of this code to contribute
14 * improvements to the Coda project. Contact Peter Braam <coda@cs.cmu.edu>.
17 #include <asm/system.h>
18 #include <asm/segment.h>
19 #include <asm/signal.h>
20 #include <linux/signal.h>
22 #include <linux/types.h>
23 #include <linux/kernel.h>
25 #include <linux/sched.h>
27 #include <linux/stat.h>
28 #include <linux/errno.h>
29 #include <linux/locks.h>
30 #include <linux/string.h>
31 #include <asm/uaccess.h>
32 #include <linux/vmalloc.h>
34 #include <linux/coda.h>
35 #include <linux/coda_linux.h>
36 #include <linux/coda_psdev.h>
37 #include <linux/coda_fs_i.h>
38 #include <linux/coda_cache.h>
39 #include <linux/coda_proc.h>
42 static int coda_upcall(struct coda_sb_info
*mntinfo
, int inSize
, int *outSize
,
43 union inputArgs
*buffer
);
47 CODA_ALLOC(inp, union inputArgs *, insize);\
48 if ( !inp ) { return -ENOMEM; }\
49 outp = (union outputArgs *) (inp);\
50 inp->ih.opcode = (op);\
51 inp->ih.pid = current->pid;\
52 inp->ih.pgid = current->pgrp;\
53 coda_load_creds(&(inp->ih.cred));\
57 static inline int max(int a
, int b
)
65 #define INSIZE(tag) sizeof(struct coda_ ## tag ## _in)
66 #define OUTSIZE(tag) sizeof(struct coda_ ## tag ## _out)
67 #define SIZE(tag) max(INSIZE(tag), OUTSIZE(tag))
71 int venus_rootfid(struct super_block
*sb
, ViceFid
*fidp
)
74 union outputArgs
*outp
;
75 int insize
, outsize
, error
;
81 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
84 printk("coda_get_rootfid: error %d\n", error
);
86 *fidp
= (ViceFid
) outp
->coda_root
.VFid
;
87 CDEBUG(D_SUPER
, "VolumeId: %lx, VnodeId: %lx.\n",
88 fidp
->Volume
, fidp
->Vnode
);
91 if (inp
) CODA_FREE(inp
, insize
);
96 int venus_getattr(struct super_block
*sb
, struct ViceFid
*fid
,
97 struct coda_vattr
*attr
)
100 union outputArgs
*outp
;
101 int insize
, outsize
, error
;
104 insize
= SIZE(getattr
);
106 inp
->coda_getattr
.VFid
= *fid
;
108 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
111 *attr
= outp
->coda_getattr
.attr
;
114 CODA_FREE(inp
, insize
);
119 int venus_setattr(struct super_block
*sb
, struct ViceFid
*fid
,
120 struct coda_vattr
*vattr
)
122 union inputArgs
*inp
;
123 union outputArgs
*outp
;
124 int insize
, outsize
, error
;
126 insize
= SIZE(setattr
);
129 inp
->coda_setattr
.VFid
= *fid
;
130 inp
->coda_setattr
.attr
= *vattr
;
132 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
134 CDEBUG(D_SUPER
, " result %d\n", error
);
135 if ( inp
) CODA_FREE(inp
, insize
);
139 int venus_lookup(struct super_block
*sb
, struct ViceFid
*fid
,
140 const char *name
, int length
, int * type
,
141 struct ViceFid
*resfid
)
143 union inputArgs
*inp
;
144 union outputArgs
*outp
;
145 int insize
, outsize
, error
;
148 offset
= INSIZE(lookup
);
149 insize
= max(offset
+ length
+1, OUTSIZE(lookup
));
152 inp
->coda_lookup
.VFid
= *fid
;
153 inp
->coda_lookup
.name
= offset
;
154 inp
->coda_lookup
.flags
= CLU_CASE_SENSITIVE
;
155 /* send Venus a null terminated string */
156 memcpy((char *)(inp
) + offset
, name
, length
);
157 *((char *)inp
+ offset
+ length
) = '\0';
159 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
162 *resfid
= outp
->coda_lookup
.VFid
;
163 *type
= outp
->coda_lookup
.vtype
;
165 if (inp
) CODA_FREE(inp
, insize
);
171 int venus_release(struct super_block
*sb
, struct ViceFid
*fid
, int flags
,
172 struct coda_cred
*cred
)
174 union inputArgs
*inp
;
175 union outputArgs
*outp
;
176 int insize
, outsize
, error
;
178 insize
= SIZE(close
);
182 memcpy(&(inp
->ih
.cred
), cred
, sizeof(*cred
));
184 printk("CODA: close without valid file creds.\n");
186 inp
->coda_close
.VFid
= *fid
;
187 inp
->coda_close
.flags
= flags
;
189 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
192 CODA_FREE(inp
, insize
);
196 int venus_open(struct super_block
*sb
, struct ViceFid
*fid
,
197 int flags
, ino_t
*ino
, dev_t
*dev
)
199 union inputArgs
*inp
;
200 union outputArgs
*outp
;
201 int insize
, outsize
, error
;
206 inp
->coda_open
.VFid
= *fid
;
207 inp
->coda_open
.flags
= flags
;
209 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
212 *ino
= outp
->coda_open
.inode
;
213 *dev
= outp
->coda_open
.dev
;
220 CODA_FREE(inp
, insize
);
225 int venus_mkdir(struct super_block
*sb
, struct ViceFid
*dirfid
,
226 const char *name
, int length
,
227 struct ViceFid
*newfid
, struct coda_vattr
*attrs
)
229 union inputArgs
*inp
;
230 union outputArgs
*outp
;
231 int insize
, outsize
, error
;
234 offset
= INSIZE(mkdir
);
235 insize
= max(offset
+ length
+ 1, OUTSIZE(mkdir
));
238 inp
->coda_mkdir
.VFid
= *dirfid
;
239 inp
->coda_mkdir
.attr
= *attrs
;
240 inp
->coda_mkdir
.name
= offset
;
241 /* Venus must get null terminated string */
242 memcpy((char *)(inp
) + offset
, name
, length
);
243 *((char *)inp
+ offset
+ length
) = '\0';
245 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
247 *attrs
= outp
->coda_mkdir
.attr
;
248 *newfid
= outp
->coda_mkdir
.VFid
;
251 CODA_FREE(inp
, insize
);
256 int venus_rename(struct super_block
*sb
, struct ViceFid
*old_fid
,
257 struct ViceFid
*new_fid
, size_t old_length
,
258 size_t new_length
, const char *old_name
,
259 const char *new_name
)
261 union inputArgs
*inp
;
262 union outputArgs
*outp
;
263 int insize
, outsize
, error
;
266 offset
= INSIZE(rename
);
267 insize
= max(offset
+ new_length
+ old_length
+ 8,
271 inp
->coda_rename
.sourceFid
= *old_fid
;
272 inp
->coda_rename
.destFid
= *new_fid
;
273 inp
->coda_rename
.srcname
= offset
;
275 /* Venus must receive an null terminated string */
276 s
= ( old_length
& ~0x3) +4; /* round up to word boundary */
277 memcpy((char *)(inp
) + offset
, old_name
, old_length
);
278 *((char *)inp
+ offset
+ old_length
) = '\0';
280 /* another null terminated string for Venus */
282 inp
->coda_rename
.destname
= offset
;
283 s
= ( new_length
& ~0x3) +4; /* round up to word boundary */
284 memcpy((char *)(inp
) + offset
, new_name
, new_length
);
285 *((char *)inp
+ offset
+ new_length
) = '\0';
287 CDEBUG(D_INODE
, "destname in packet: %s\n",
288 (char *)inp
+ (int) inp
->coda_rename
.destname
);
289 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
291 if (inp
) CODA_FREE(inp
, insize
);
295 int venus_create(struct super_block
*sb
, struct ViceFid
*dirfid
,
296 const char *name
, int length
, int excl
, int mode
, int rdev
,
297 struct ViceFid
*newfid
, struct coda_vattr
*attrs
)
299 union inputArgs
*inp
;
300 union outputArgs
*outp
;
301 int insize
, outsize
, error
;
304 offset
= INSIZE(create
);
305 insize
= max(offset
+ length
+ 1, OUTSIZE(create
));
308 inp
->coda_create
.VFid
= *dirfid
;
309 inp
->coda_create
.attr
.va_mode
= mode
;
310 inp
->coda_create
.attr
.va_rdev
= rdev
;
311 inp
->coda_create
.excl
= excl
;
312 inp
->coda_create
.mode
= mode
;
313 inp
->coda_create
.name
= offset
;
315 /* Venus must get null terminated string */
316 memcpy((char *)(inp
) + offset
, name
, length
);
317 *((char *)inp
+ offset
+ length
) = '\0';
319 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
321 *attrs
= outp
->coda_create
.attr
;
322 *newfid
= outp
->coda_create
.VFid
;
325 CODA_FREE(inp
, insize
);
329 int venus_rmdir(struct super_block
*sb
, struct ViceFid
*dirfid
,
330 const char *name
, int length
)
332 union inputArgs
*inp
;
333 union outputArgs
*outp
;
334 int insize
, outsize
, error
;
337 offset
= INSIZE(rmdir
);
338 insize
= max(offset
+ length
+ 1, OUTSIZE(rmdir
));
341 inp
->coda_rmdir
.VFid
= *dirfid
;
342 inp
->coda_rmdir
.name
= offset
;
343 memcpy((char *)(inp
) + offset
, name
, length
);
344 *((char *)inp
+ offset
+ length
) = '\0';
346 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
348 CODA_FREE(inp
, insize
);
352 int venus_remove(struct super_block
*sb
, struct ViceFid
*dirfid
,
353 const char *name
, int length
)
355 union inputArgs
*inp
;
356 union outputArgs
*outp
;
357 int error
=0, insize
, outsize
, offset
;
359 offset
= INSIZE(remove
);
360 insize
= max(offset
+ length
+ 1, OUTSIZE(remove
));
363 inp
->coda_remove
.VFid
= *dirfid
;
364 inp
->coda_remove
.name
= offset
;
365 memcpy((char *)(inp
) + offset
, name
, length
);
366 *((char *)inp
+ offset
+ length
) = '\0';
368 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
370 CODA_FREE(inp
, insize
);
374 int venus_readlink(struct super_block
*sb
, struct ViceFid
*fid
,
375 char *buffer
, int *length
)
377 union inputArgs
*inp
;
378 union outputArgs
*outp
;
379 int insize
, outsize
, error
;
383 insize
= max(INSIZE(readlink
), OUTSIZE(readlink
)+ *length
+ 1);
384 UPARG(CODA_READLINK
);
386 inp
->coda_readlink
.VFid
= *fid
;
388 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
391 retlen
= outp
->coda_readlink
.count
;
392 if ( retlen
> *length
)
395 result
= (char *)outp
+ (int)outp
->coda_readlink
.data
;
396 memcpy(buffer
, result
, retlen
);
397 *(buffer
+ retlen
) = '\0';
400 if (inp
) CODA_FREE(inp
, insize
);
401 CDEBUG(D_INODE
, " result %d\n",error
);
408 int venus_link(struct super_block
*sb
, struct ViceFid
*fid
,
409 struct ViceFid
*dirfid
, const char *name
, int len
)
411 union inputArgs
*inp
;
412 union outputArgs
*outp
;
413 int insize
, outsize
, error
;
416 offset
= INSIZE(link
);
417 insize
= max(offset
+ len
+ 1, OUTSIZE(link
));
420 inp
->coda_link
.sourceFid
= *fid
;
421 inp
->coda_link
.destFid
= *dirfid
;
422 inp
->coda_link
.tname
= offset
;
424 /* make sure strings are null terminated */
425 memcpy((char *)(inp
) + offset
, name
, len
);
426 *((char *)inp
+ offset
+ len
) = '\0';
428 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
431 CODA_FREE(inp
, insize
);
432 CDEBUG(D_INODE
, " result %d\n",error
);
437 int venus_symlink(struct super_block
*sb
, struct ViceFid
*fid
,
438 const char *name
, int len
,
439 const char *symname
, int symlen
)
441 union inputArgs
*inp
;
442 union outputArgs
*outp
;
443 int insize
, outsize
, error
;
446 offset
= INSIZE(symlink
);
447 insize
= max(offset
+ len
+ symlen
+ 8, OUTSIZE(symlink
));
450 /* inp->coda_symlink.attr = *tva; XXXXXX */
451 inp
->coda_symlink
.VFid
= *fid
;
453 /* Round up to word boundary and null terminate */
454 inp
->coda_symlink
.srcname
= offset
;
455 s
= ( symlen
& ~0x3 ) + 4;
456 memcpy((char *)(inp
) + offset
, symname
, symlen
);
457 *((char *)inp
+ offset
+ symlen
) = '\0';
459 /* Round up to word boundary and null terminate */
461 inp
->coda_symlink
.tname
= offset
;
462 s
= (len
& ~0x3) + 4;
463 memcpy((char *)(inp
) + offset
, name
, len
);
464 *((char *)inp
+ offset
+ len
) = '\0';
466 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
469 CODA_FREE(inp
, insize
);
470 CDEBUG(D_INODE
, " result %d\n",error
);
475 int venus_fsync(struct super_block
*sb
, struct ViceFid
*fid
)
477 union inputArgs
*inp
;
478 union outputArgs
*outp
;
479 int insize
, outsize
, error
;
484 inp
->coda_fsync
.VFid
= *fid
;
485 error
= coda_upcall(coda_sbp(sb
), sizeof(union inputArgs
),
489 CODA_FREE(inp
, insize
);
493 int venus_access(struct super_block
*sb
, struct ViceFid
*fid
, int mask
)
495 union inputArgs
*inp
;
496 union outputArgs
*outp
;
497 int insize
, outsize
, error
;
499 insize
= SIZE(access
);
502 inp
->coda_access
.VFid
= *fid
;
503 inp
->coda_access
.flags
= mask
;
505 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
507 if (inp
) CODA_FREE(inp
, insize
);
513 int venus_pioctl(struct super_block
*sb
, struct ViceFid
*fid
,
514 unsigned int cmd
, struct PioctlData
*data
)
516 union inputArgs
*inp
;
517 union outputArgs
*outp
;
518 int insize
, outsize
, error
;
521 insize
= VC_MAXMSGSIZE
;
524 /* build packet for Venus */
525 if (data
->vi
.in_size
> VC_MAXDATASIZE
) {
530 inp
->coda_ioctl
.VFid
= *fid
;
532 /* the cmd field was mutated by increasing its size field to
533 * reflect the path and follow args. We need to subtract that
534 * out before sending the command to Venus. */
535 inp
->coda_ioctl
.cmd
= (cmd
& ~(PIOCPARM_MASK
<< 16));
536 iocsize
= ((cmd
>> 16) & PIOCPARM_MASK
) - sizeof(char *) - sizeof(int);
537 inp
->coda_ioctl
.cmd
|= (iocsize
& PIOCPARM_MASK
) << 16;
539 /* in->coda_ioctl.rwflag = flag; */
540 inp
->coda_ioctl
.len
= data
->vi
.in_size
;
541 inp
->coda_ioctl
.data
= (char *)(INSIZE(ioctl
));
543 /* get the data out of user space */
544 if ( copy_from_user((char*)inp
+ (int)inp
->coda_ioctl
.data
,
545 data
->vi
.in
, data
->vi
.in_size
) ) {
550 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
553 printk("coda_pioctl: Venus returns: %d for %s\n",
554 error
, coda_f2s(fid
));
558 /* Copy out the OUT buffer. */
559 if (outp
->coda_ioctl
.len
> data
->vi
.out_size
) {
560 CDEBUG(D_FILE
, "return len %d <= request len %d\n",
561 outp
->coda_ioctl
.len
,
565 error
= verify_area(VERIFY_WRITE
, data
->vi
.out
,
567 if ( error
) goto exit
;
569 if (copy_to_user(data
->vi
.out
,
570 (char *)outp
+ (int)outp
->coda_ioctl
.data
,
571 data
->vi
.out_size
)) {
579 CODA_FREE(inp
, insize
);
583 int venus_statfs(struct super_block
*sb
, struct statfs
*sfs
)
585 union inputArgs
*inp
;
586 union outputArgs
*outp
;
587 int insize
, outsize
, error
;
589 insize
= max(INSIZE(statfs
), OUTSIZE(statfs
));
592 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
595 sfs
->f_blocks
= outp
->coda_statfs
.stat
.f_blocks
;
596 sfs
->f_bfree
= outp
->coda_statfs
.stat
.f_bfree
;
597 sfs
->f_bavail
= outp
->coda_statfs
.stat
.f_bavail
;
598 sfs
->f_files
= outp
->coda_statfs
.stat
.f_files
;
599 sfs
->f_ffree
= outp
->coda_statfs
.stat
.f_ffree
;
601 printk("coda_statfs: Venus returns: %d\n", error
);
604 if (inp
) CODA_FREE(inp
, insize
);
605 CDEBUG(D_INODE
, " result %d\n",error
);
611 * coda_upcall and coda_downcall routines.
615 static inline unsigned long coda_waitfor_upcall(struct upc_req
*vmp
)
617 DECLARE_WAITQUEUE(wait
, current
);
618 struct timeval begin
= { 0, 0 }, end
= { 0, 0 };
620 vmp
->uc_posttime
= jiffies
;
622 if (coda_upcall_timestamping
)
623 do_gettimeofday(&begin
);
625 add_wait_queue(&vmp
->uc_sleep
, &wait
);
627 if ( coda_hard
== 0 )
628 set_current_state(TASK_INTERRUPTIBLE
);
630 set_current_state(TASK_UNINTERRUPTIBLE
);
633 if ( vmp
->uc_flags
& REQ_WRITE
)
636 if ( !coda_hard
&& signal_pending(current
) ) {
637 /* if this process really wants to die, let it go */
638 if ( sigismember(&(current
->signal
), SIGKILL
) ||
639 sigismember(&(current
->signal
), SIGINT
) )
641 /* signal is present: after timeout always return
642 really smart idea, probably useless ... */
643 if ( jiffies
- vmp
->uc_posttime
> coda_timeout
* HZ
)
649 remove_wait_queue(&vmp
->uc_sleep
, &wait
);
650 current
->state
= TASK_RUNNING
;
652 if (coda_upcall_timestamping
&& begin
.tv_sec
!= 0) {
653 do_gettimeofday(&end
);
655 if (end
.tv_usec
< begin
.tv_usec
) {
656 end
.tv_usec
+= 1000000; end
.tv_sec
--;
658 end
.tv_sec
-= begin
.tv_sec
;
659 end
.tv_usec
-= begin
.tv_usec
;
662 CDEBUG(D_SPECIAL
, "begin: %ld.%06ld, elapsed: %ld.%06ld\n",
663 begin
.tv_sec
, begin
.tv_usec
, end
.tv_sec
, end
.tv_usec
);
665 return ((end
.tv_sec
* 1000000) + end
.tv_usec
);
670 * coda_upcall will return an error in the case of
671 * failed communication with Venus _or_ will peek at Venus
672 * reply and return Venus' error.
674 * As venus has 2 types of errors, normal errors (positive) and internal
675 * errors (negative), normal errors are negated, while internal errors
676 * are all mapped to -EINTR, while showing a nice warning message. (jh)
679 static int coda_upcall(struct coda_sb_info
*sbi
,
680 int inSize
, int *outSize
,
681 union inputArgs
*buffer
)
683 unsigned long runtime
;
684 struct venus_comm
*vcommp
;
685 union outputArgs
*out
;
691 vcommp
= &coda_upc_comm
;
692 if ( !vcommp
->vc_pid
) {
693 printk("No pseudo device in upcall comms at %p\n", vcommp
);
697 /* Format the request message. */
698 CODA_ALLOC(req
,struct upc_req
*,sizeof(struct upc_req
));
699 req
->uc_data
= (void *)buffer
;
701 req
->uc_inSize
= inSize
;
702 req
->uc_outSize
= *outSize
? *outSize
: inSize
;
703 req
->uc_opcode
= ((union inputArgs
*)buffer
)->ih
.opcode
;
704 req
->uc_unique
= ++vcommp
->vc_seq
;
705 init_waitqueue_head(&req
->uc_sleep
);
707 /* Fill in the common input args. */
708 ((union inputArgs
*)buffer
)->ih
.unique
= req
->uc_unique
;
710 /* Append msg to pending queue and poke Venus. */
711 list_add(&(req
->uc_chain
), vcommp
->vc_pending
.prev
);
713 "Proc %d wake Venus for(opc,uniq) =(%d,%d) msg at %p.zzz.\n",
714 current
->pid
, req
->uc_opcode
, req
->uc_unique
, req
);
716 wake_up_interruptible(&vcommp
->vc_waitq
);
717 /* We can be interrupted while we wait for Venus to process
718 * our request. If the interrupt occurs before Venus has read
719 * the request, we dequeue and return. If it occurs after the
720 * read but before the reply, we dequeue, send a signal
721 * message, and return. If it occurs after the reply we ignore
722 * it. In no case do we want to restart the syscall. If it
723 * was interrupted by a venus shutdown (psdev_close), return
726 /* Go to sleep. Wake up on signals only after the timeout. */
727 runtime
= coda_waitfor_upcall(req
);
728 coda_upcall_stats(((union inputArgs
*)buffer
)->ih
.opcode
, runtime
);
730 CDEBUG(D_TIMING
, "opc: %d time: %ld uniq: %d size: %d\n",
731 req
->uc_opcode
, jiffies
- req
->uc_posttime
,
732 req
->uc_unique
, req
->uc_outSize
);
734 "..process %d woken up by Venus for req at %p, data at %p\n",
735 current
->pid
, req
, req
->uc_data
);
736 if (vcommp
->vc_pid
) { /* i.e. Venus is still alive */
737 /* Op went through, interrupt or not... */
738 if (req
->uc_flags
& REQ_WRITE
) {
739 out
= (union outputArgs
*)req
->uc_data
;
740 /* here we map positive Venus errors to kernel errors */
741 if ( out
->oh
.result
< 0 ) {
742 printk("Tell Peter: Venus returns negative error %ld, for oc %ld!\n",
743 out
->oh
.result
, out
->oh
.opcode
);
744 out
->oh
.result
= EINTR
;
746 error
= -out
->oh
.result
;
748 "upcall: (u,o,r) (%ld, %ld, %ld) out at %p\n",
749 out
->oh
.unique
, out
->oh
.opcode
, out
->oh
.result
, out
);
750 *outSize
= req
->uc_outSize
;
753 if ( !(req
->uc_flags
& REQ_READ
) && signal_pending(current
)) {
754 /* Interrupted before venus read it. */
756 "Interrupted before read:(op,un) (%d.%d), flags = %x\n",
757 req
->uc_opcode
, req
->uc_unique
, req
->uc_flags
);
758 list_del(&(req
->uc_chain
));
759 /* perhaps the best way to convince the app to
764 if ( (req
->uc_flags
& REQ_READ
) && signal_pending(current
) ) {
765 /* interrupted after Venus did its read, send signal */
766 union inputArgs
*sig_inputArgs
;
767 struct upc_req
*sig_req
;
770 "Sending Venus a signal: op = %d.%d, flags = %x\n",
771 req
->uc_opcode
, req
->uc_unique
, req
->uc_flags
);
773 list_del(&(req
->uc_chain
));
775 CODA_ALLOC(sig_req
, struct upc_req
*, sizeof (struct upc_req
));
776 CODA_ALLOC((sig_req
->uc_data
), char *, sizeof(struct coda_in_hdr
));
778 sig_inputArgs
= (union inputArgs
*)sig_req
->uc_data
;
779 sig_inputArgs
->ih
.opcode
= CODA_SIGNAL
;
780 sig_inputArgs
->ih
.unique
= req
->uc_unique
;
782 sig_req
->uc_flags
= REQ_ASYNC
;
783 sig_req
->uc_opcode
= sig_inputArgs
->ih
.opcode
;
784 sig_req
->uc_unique
= sig_inputArgs
->ih
.unique
;
785 sig_req
->uc_inSize
= sizeof(struct coda_in_hdr
);
786 sig_req
->uc_outSize
= sizeof(struct coda_in_hdr
);
788 "coda_upcall: enqueing signal msg (%d, %d)\n",
789 sig_req
->uc_opcode
, sig_req
->uc_unique
);
791 /* insert at head of queue! */
792 list_add(&(sig_req
->uc_chain
), &vcommp
->vc_pending
);
793 wake_up_interruptible(&vcommp
->vc_waitq
);
795 printk("Coda: Strange interruption..\n");
798 } else { /* If venus died i.e. !VC_OPEN(vcommp) */
799 printk("coda_upcall: Venus dead on (op,un) (%d.%d) flags %d\n",
800 req
->uc_opcode
, req
->uc_unique
, req
->uc_flags
);
805 CODA_FREE(req
, sizeof(struct upc_req
));
812 The statements below are part of the Coda opportunistic
813 programming -- taken from the Mach/BSD kernel code for Coda.
814 You don't get correct semantics by stating what needs to be
815 done without guaranteeing the invariants needed for it to happen.
816 When will be have time to find out what exactly is going on? (pjb)
821 * There are 7 cases where cache invalidations occur. The semantics
822 * of each is listed here:
824 * CODA_FLUSH -- flush all entries from the name cache and the cnode cache.
825 * CODA_PURGEUSER -- flush all entries from the name cache for a specific user
826 * This call is a result of token expiration.
828 * The next arise as the result of callbacks on a file or directory.
829 * CODA_ZAPFILE -- flush the cached attributes for a file.
831 * CODA_ZAPDIR -- flush the attributes for the dir and
832 * force a new lookup for all the children
836 * The next is a result of Venus detecting an inconsistent file.
837 * CODA_PURGEFID -- flush the attribute for the file
838 * purge it and its children from the dcache
840 * The last allows Venus to replace local fids with global ones
841 * during reintegration.
843 * CODA_REPLACE -- replace one ViceFid with another throughout the name cache */
845 int coda_downcall(int opcode
, union outputArgs
* out
, struct super_block
*sb
)
848 /* Handle invalidation requests. */
849 if ( !sb
|| !sb
->s_root
|| !sb
->s_root
->d_inode
) {
850 printk("coda_downcall: opcode %d, no sb!\n", opcode
);
858 CDEBUG(D_DOWNCALL
, "CODA_FLUSH\n");
859 coda_cache_clear_all(sb
);
860 shrink_dcache_sb(sb
);
861 coda_flag_inode(sb
->s_root
->d_inode
, C_FLUSH
);
865 case CODA_PURGEUSER
: {
866 struct coda_cred
*cred
= &out
->coda_purgeuser
.cred
;
867 CDEBUG(D_DOWNCALL
, "CODA_PURGEUSER\n");
869 printk("PURGEUSER: null cred!\n");
872 clstats(CODA_PURGEUSER
);
873 coda_cache_clear_cred(sb
, cred
);
879 ViceFid
*fid
= &out
->coda_zapdir
.CodaFid
;
880 CDEBUG(D_DOWNCALL
, "zapdir: fid = %s...\n", coda_f2s(fid
));
881 clstats(CODA_ZAPDIR
);
883 inode
= coda_fid_to_inode(fid
, sb
);
885 CDEBUG(D_DOWNCALL
, "zapdir: inode = %ld children flagged\n",
887 coda_flag_inode_children(inode
, C_PURGE
);
888 CDEBUG(D_DOWNCALL
, "zapdir: inode = %ld cache cleared\n", inode
->i_ino
);
889 coda_flag_inode(inode
, C_VATTR
);
891 CDEBUG(D_DOWNCALL
, "zapdir: no inode\n");
896 case CODA_ZAPFILE
: {
898 struct ViceFid
*fid
= &out
->coda_zapfile
.CodaFid
;
899 clstats(CODA_ZAPFILE
);
900 CDEBUG(D_DOWNCALL
, "zapfile: fid = %s\n", coda_f2s(fid
));
901 inode
= coda_fid_to_inode(fid
, sb
);
903 CDEBUG(D_DOWNCALL
, "zapfile: inode = %ld\n", inode
->i_ino
);
904 coda_flag_inode(inode
, C_VATTR
);
906 CDEBUG(D_DOWNCALL
, "zapfile: no inode\n");
910 case CODA_PURGEFID
: {
912 ViceFid
*fid
= &out
->coda_purgefid
.CodaFid
;
913 CDEBUG(D_DOWNCALL
, "purgefid: fid = %s\n", coda_f2s(fid
));
914 clstats(CODA_PURGEFID
);
915 inode
= coda_fid_to_inode(fid
, sb
);
917 CDEBUG(D_DOWNCALL
, "purgefid: inode = %ld\n", inode
->i_ino
);
918 coda_flag_inode_children(inode
, C_PURGE
);
919 coda_purge_dentries(inode
);
921 CDEBUG(D_DOWNCALL
, "purgefid: no inode\n");
925 case CODA_REPLACE
: {
927 ViceFid
*oldfid
= &out
->coda_replace
.OldFid
;
928 ViceFid
*newfid
= &out
->coda_replace
.NewFid
;
929 clstats(CODA_REPLACE
);
930 CDEBUG(D_DOWNCALL
, "CODA_REPLACE\n");
931 inode
= coda_fid_to_inode(oldfid
, sb
);
933 CDEBUG(D_DOWNCALL
, "replacefid: inode = %ld\n", inode
->i_ino
);
934 coda_replace_fid(inode
, oldfid
, newfid
);
936 CDEBUG(D_DOWNCALL
, "purgefid: no inode\n");