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/signal.h>
19 #include <linux/signal.h>
21 #include <linux/types.h>
22 #include <linux/kernel.h>
24 #include <linux/time.h>
26 #include <linux/file.h>
27 #include <linux/stat.h>
28 #include <linux/errno.h>
29 #include <linux/string.h>
30 #include <asm/uaccess.h>
31 #include <linux/vmalloc.h>
32 #include <linux/vfs.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>
41 #define upc_alloc() kmalloc(sizeof(struct upc_req), GFP_KERNEL)
42 #define upc_free(r) kfree(r)
44 static int coda_upcall(struct coda_sb_info
*mntinfo
, int inSize
, int *outSize
,
45 union inputArgs
*buffer
);
47 static void *alloc_upcall(int opcode
, int size
)
51 CODA_ALLOC(inp
, union inputArgs
*, size
);
53 return ERR_PTR(-ENOMEM
);
55 inp
->ih
.opcode
= opcode
;
56 inp
->ih
.pid
= current
->pid
;
57 inp
->ih
.pgid
= current
->pgrp
;
58 coda_load_creds(&(inp
->ih
.cred
));
65 inp = (union inputArgs *)alloc_upcall(op, insize); \
66 if (IS_ERR(inp)) { return PTR_ERR(inp); }\
67 outp = (union outputArgs *)(inp); \
71 #define INSIZE(tag) sizeof(struct coda_ ## tag ## _in)
72 #define OUTSIZE(tag) sizeof(struct coda_ ## tag ## _out)
73 #define SIZE(tag) max_t(unsigned int, INSIZE(tag), OUTSIZE(tag))
77 int venus_rootfid(struct super_block
*sb
, ViceFid
*fidp
)
80 union outputArgs
*outp
;
81 int insize
, outsize
, error
;
86 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
89 printk("coda_get_rootfid: error %d\n", error
);
91 *fidp
= (ViceFid
) outp
->coda_root
.VFid
;
94 CODA_FREE(inp
, insize
);
98 int venus_getattr(struct super_block
*sb
, struct ViceFid
*fid
,
99 struct coda_vattr
*attr
)
101 union inputArgs
*inp
;
102 union outputArgs
*outp
;
103 int insize
, outsize
, error
;
105 insize
= SIZE(getattr
);
107 inp
->coda_getattr
.VFid
= *fid
;
109 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
111 *attr
= outp
->coda_getattr
.attr
;
113 CODA_FREE(inp
, insize
);
117 int venus_setattr(struct super_block
*sb
, struct ViceFid
*fid
,
118 struct coda_vattr
*vattr
)
120 union inputArgs
*inp
;
121 union outputArgs
*outp
;
122 int insize
, outsize
, error
;
124 insize
= SIZE(setattr
);
127 inp
->coda_setattr
.VFid
= *fid
;
128 inp
->coda_setattr
.attr
= *vattr
;
130 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
132 CODA_FREE(inp
, insize
);
136 int venus_lookup(struct super_block
*sb
, struct ViceFid
*fid
,
137 const char *name
, int length
, int * type
,
138 struct ViceFid
*resfid
)
140 union inputArgs
*inp
;
141 union outputArgs
*outp
;
142 int insize
, outsize
, error
;
145 offset
= INSIZE(lookup
);
146 insize
= max_t(unsigned int, offset
+ length
+1, OUTSIZE(lookup
));
149 inp
->coda_lookup
.VFid
= *fid
;
150 inp
->coda_lookup
.name
= offset
;
151 inp
->coda_lookup
.flags
= CLU_CASE_SENSITIVE
;
152 /* send Venus a null terminated string */
153 memcpy((char *)(inp
) + offset
, name
, length
);
154 *((char *)inp
+ offset
+ length
) = '\0';
156 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
158 *resfid
= outp
->coda_lookup
.VFid
;
159 *type
= outp
->coda_lookup
.vtype
;
161 CODA_FREE(inp
, insize
);
165 int venus_store(struct super_block
*sb
, struct ViceFid
*fid
, int flags
,
166 struct coda_cred
*cred
)
168 union inputArgs
*inp
;
169 union outputArgs
*outp
;
170 int insize
, outsize
, error
;
172 insize
= SIZE(store
);
175 memcpy(&(inp
->ih
.cred
), cred
, sizeof(*cred
));
177 inp
->coda_store
.VFid
= *fid
;
178 inp
->coda_store
.flags
= flags
;
180 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
182 CODA_FREE(inp
, insize
);
186 int venus_release(struct super_block
*sb
, struct ViceFid
*fid
, int flags
)
188 union inputArgs
*inp
;
189 union outputArgs
*outp
;
190 int insize
, outsize
, error
;
192 insize
= SIZE(release
);
195 inp
->coda_release
.VFid
= *fid
;
196 inp
->coda_release
.flags
= flags
;
198 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
200 CODA_FREE(inp
, insize
);
204 int venus_close(struct super_block
*sb
, struct ViceFid
*fid
, int flags
,
205 struct coda_cred
*cred
)
207 union inputArgs
*inp
;
208 union outputArgs
*outp
;
209 int insize
, outsize
, error
;
211 insize
= SIZE(release
);
214 memcpy(&(inp
->ih
.cred
), cred
, sizeof(*cred
));
216 inp
->coda_close
.VFid
= *fid
;
217 inp
->coda_close
.flags
= flags
;
219 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
221 CODA_FREE(inp
, insize
);
225 int venus_open(struct super_block
*sb
, struct ViceFid
*fid
,
226 int flags
, struct file
**fh
)
228 union inputArgs
*inp
;
229 union outputArgs
*outp
;
230 int insize
, outsize
, error
;
232 insize
= SIZE(open_by_fd
);
233 UPARG(CODA_OPEN_BY_FD
);
235 inp
->coda_open
.VFid
= *fid
;
236 inp
->coda_open
.flags
= flags
;
238 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
240 *fh
= outp
->coda_open_by_fd
.fh
;
242 CODA_FREE(inp
, insize
);
246 int venus_mkdir(struct super_block
*sb
, struct ViceFid
*dirfid
,
247 const char *name
, int length
,
248 struct ViceFid
*newfid
, struct coda_vattr
*attrs
)
250 union inputArgs
*inp
;
251 union outputArgs
*outp
;
252 int insize
, outsize
, error
;
255 offset
= INSIZE(mkdir
);
256 insize
= max_t(unsigned int, offset
+ length
+ 1, OUTSIZE(mkdir
));
259 inp
->coda_mkdir
.VFid
= *dirfid
;
260 inp
->coda_mkdir
.attr
= *attrs
;
261 inp
->coda_mkdir
.name
= offset
;
262 /* Venus must get null terminated string */
263 memcpy((char *)(inp
) + offset
, name
, length
);
264 *((char *)inp
+ offset
+ length
) = '\0';
266 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
268 *attrs
= outp
->coda_mkdir
.attr
;
269 *newfid
= outp
->coda_mkdir
.VFid
;
271 CODA_FREE(inp
, insize
);
276 int venus_rename(struct super_block
*sb
, struct ViceFid
*old_fid
,
277 struct ViceFid
*new_fid
, size_t old_length
,
278 size_t new_length
, const char *old_name
,
279 const char *new_name
)
281 union inputArgs
*inp
;
282 union outputArgs
*outp
;
283 int insize
, outsize
, error
;
286 offset
= INSIZE(rename
);
287 insize
= max_t(unsigned int, offset
+ new_length
+ old_length
+ 8,
291 inp
->coda_rename
.sourceFid
= *old_fid
;
292 inp
->coda_rename
.destFid
= *new_fid
;
293 inp
->coda_rename
.srcname
= offset
;
295 /* Venus must receive an null terminated string */
296 s
= ( old_length
& ~0x3) +4; /* round up to word boundary */
297 memcpy((char *)(inp
) + offset
, old_name
, old_length
);
298 *((char *)inp
+ offset
+ old_length
) = '\0';
300 /* another null terminated string for Venus */
302 inp
->coda_rename
.destname
= offset
;
303 s
= ( new_length
& ~0x3) +4; /* round up to word boundary */
304 memcpy((char *)(inp
) + offset
, new_name
, new_length
);
305 *((char *)inp
+ offset
+ new_length
) = '\0';
307 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
309 CODA_FREE(inp
, insize
);
313 int venus_create(struct super_block
*sb
, struct ViceFid
*dirfid
,
314 const char *name
, int length
, int excl
, int mode
, dev_t rdev
,
315 struct ViceFid
*newfid
, struct coda_vattr
*attrs
)
317 union inputArgs
*inp
;
318 union outputArgs
*outp
;
319 int insize
, outsize
, error
;
322 offset
= INSIZE(create
);
323 insize
= max_t(unsigned int, offset
+ length
+ 1, OUTSIZE(create
));
326 inp
->coda_create
.VFid
= *dirfid
;
327 inp
->coda_create
.attr
.va_mode
= mode
;
328 inp
->coda_create
.attr
.va_rdev
= rdev
;
329 inp
->coda_create
.excl
= excl
;
330 inp
->coda_create
.mode
= mode
;
331 inp
->coda_create
.name
= offset
;
333 /* Venus must get null terminated string */
334 memcpy((char *)(inp
) + offset
, name
, length
);
335 *((char *)inp
+ offset
+ length
) = '\0';
337 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
339 *attrs
= outp
->coda_create
.attr
;
340 *newfid
= outp
->coda_create
.VFid
;
342 CODA_FREE(inp
, insize
);
346 int venus_rmdir(struct super_block
*sb
, struct ViceFid
*dirfid
,
347 const char *name
, int length
)
349 union inputArgs
*inp
;
350 union outputArgs
*outp
;
351 int insize
, outsize
, error
;
354 offset
= INSIZE(rmdir
);
355 insize
= max_t(unsigned int, offset
+ length
+ 1, OUTSIZE(rmdir
));
358 inp
->coda_rmdir
.VFid
= *dirfid
;
359 inp
->coda_rmdir
.name
= offset
;
360 memcpy((char *)(inp
) + offset
, name
, length
);
361 *((char *)inp
+ offset
+ length
) = '\0';
363 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
365 CODA_FREE(inp
, insize
);
369 int venus_remove(struct super_block
*sb
, struct ViceFid
*dirfid
,
370 const char *name
, int length
)
372 union inputArgs
*inp
;
373 union outputArgs
*outp
;
374 int error
=0, insize
, outsize
, offset
;
376 offset
= INSIZE(remove
);
377 insize
= max_t(unsigned int, offset
+ length
+ 1, OUTSIZE(remove
));
380 inp
->coda_remove
.VFid
= *dirfid
;
381 inp
->coda_remove
.name
= offset
;
382 memcpy((char *)(inp
) + offset
, name
, length
);
383 *((char *)inp
+ offset
+ length
) = '\0';
385 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
387 CODA_FREE(inp
, insize
);
391 int venus_readlink(struct super_block
*sb
, struct ViceFid
*fid
,
392 char *buffer
, int *length
)
394 union inputArgs
*inp
;
395 union outputArgs
*outp
;
396 int insize
, outsize
, error
;
400 insize
= max_t(unsigned int,
401 INSIZE(readlink
), OUTSIZE(readlink
)+ *length
+ 1);
402 UPARG(CODA_READLINK
);
404 inp
->coda_readlink
.VFid
= *fid
;
406 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
409 retlen
= outp
->coda_readlink
.count
;
410 if ( retlen
> *length
)
413 result
= (char *)outp
+ (long)outp
->coda_readlink
.data
;
414 memcpy(buffer
, result
, retlen
);
415 *(buffer
+ retlen
) = '\0';
418 CODA_FREE(inp
, insize
);
424 int venus_link(struct super_block
*sb
, struct ViceFid
*fid
,
425 struct ViceFid
*dirfid
, const char *name
, int len
)
427 union inputArgs
*inp
;
428 union outputArgs
*outp
;
429 int insize
, outsize
, error
;
432 offset
= INSIZE(link
);
433 insize
= max_t(unsigned int, offset
+ len
+ 1, OUTSIZE(link
));
436 inp
->coda_link
.sourceFid
= *fid
;
437 inp
->coda_link
.destFid
= *dirfid
;
438 inp
->coda_link
.tname
= offset
;
440 /* make sure strings are null terminated */
441 memcpy((char *)(inp
) + offset
, name
, len
);
442 *((char *)inp
+ offset
+ len
) = '\0';
444 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
446 CODA_FREE(inp
, insize
);
450 int venus_symlink(struct super_block
*sb
, struct ViceFid
*fid
,
451 const char *name
, int len
,
452 const char *symname
, int symlen
)
454 union inputArgs
*inp
;
455 union outputArgs
*outp
;
456 int insize
, outsize
, error
;
459 offset
= INSIZE(symlink
);
460 insize
= max_t(unsigned int, offset
+ len
+ symlen
+ 8, OUTSIZE(symlink
));
463 /* inp->coda_symlink.attr = *tva; XXXXXX */
464 inp
->coda_symlink
.VFid
= *fid
;
466 /* Round up to word boundary and null terminate */
467 inp
->coda_symlink
.srcname
= offset
;
468 s
= ( symlen
& ~0x3 ) + 4;
469 memcpy((char *)(inp
) + offset
, symname
, symlen
);
470 *((char *)inp
+ offset
+ symlen
) = '\0';
472 /* Round up to word boundary and null terminate */
474 inp
->coda_symlink
.tname
= offset
;
475 s
= (len
& ~0x3) + 4;
476 memcpy((char *)(inp
) + offset
, name
, len
);
477 *((char *)inp
+ offset
+ len
) = '\0';
479 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
481 CODA_FREE(inp
, insize
);
485 int venus_fsync(struct super_block
*sb
, struct ViceFid
*fid
)
487 union inputArgs
*inp
;
488 union outputArgs
*outp
;
489 int insize
, outsize
, error
;
494 inp
->coda_fsync
.VFid
= *fid
;
495 error
= coda_upcall(coda_sbp(sb
), sizeof(union inputArgs
),
498 CODA_FREE(inp
, insize
);
502 int venus_access(struct super_block
*sb
, struct ViceFid
*fid
, int mask
)
504 union inputArgs
*inp
;
505 union outputArgs
*outp
;
506 int insize
, outsize
, error
;
508 insize
= SIZE(access
);
511 inp
->coda_access
.VFid
= *fid
;
512 inp
->coda_access
.flags
= mask
;
514 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
516 CODA_FREE(inp
, insize
);
521 int venus_pioctl(struct super_block
*sb
, struct ViceFid
*fid
,
522 unsigned int cmd
, struct PioctlData
*data
)
524 union inputArgs
*inp
;
525 union outputArgs
*outp
;
526 int insize
, outsize
, error
;
529 insize
= VC_MAXMSGSIZE
;
532 /* build packet for Venus */
533 if (data
->vi
.in_size
> VC_MAXDATASIZE
) {
538 inp
->coda_ioctl
.VFid
= *fid
;
540 /* the cmd field was mutated by increasing its size field to
541 * reflect the path and follow args. We need to subtract that
542 * out before sending the command to Venus. */
543 inp
->coda_ioctl
.cmd
= (cmd
& ~(PIOCPARM_MASK
<< 16));
544 iocsize
= ((cmd
>> 16) & PIOCPARM_MASK
) - sizeof(char *) - sizeof(int);
545 inp
->coda_ioctl
.cmd
|= (iocsize
& PIOCPARM_MASK
) << 16;
547 /* in->coda_ioctl.rwflag = flag; */
548 inp
->coda_ioctl
.len
= data
->vi
.in_size
;
549 inp
->coda_ioctl
.data
= (char *)(INSIZE(ioctl
));
551 /* get the data out of user space */
552 if ( copy_from_user((char*)inp
+ (long)inp
->coda_ioctl
.data
,
553 data
->vi
.in
, data
->vi
.in_size
) ) {
558 error
= coda_upcall(coda_sbp(sb
), SIZE(ioctl
) + data
->vi
.in_size
,
562 printk("coda_pioctl: Venus returns: %d for %s\n",
563 error
, coda_f2s(fid
));
567 /* Copy out the OUT buffer. */
568 if (outp
->coda_ioctl
.len
> data
->vi
.out_size
) {
571 error
= verify_area(VERIFY_WRITE
, data
->vi
.out
,
573 if ( error
) goto exit
;
575 if (copy_to_user(data
->vi
.out
,
576 (char *)outp
+ (long)outp
->coda_ioctl
.data
,
577 data
->vi
.out_size
)) {
584 CODA_FREE(inp
, insize
);
588 int venus_statfs(struct super_block
*sb
, struct kstatfs
*sfs
)
590 union inputArgs
*inp
;
591 union outputArgs
*outp
;
592 int insize
, outsize
, error
;
594 insize
= max_t(unsigned int, INSIZE(statfs
), OUTSIZE(statfs
));
597 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
600 sfs
->f_blocks
= outp
->coda_statfs
.stat
.f_blocks
;
601 sfs
->f_bfree
= outp
->coda_statfs
.stat
.f_bfree
;
602 sfs
->f_bavail
= outp
->coda_statfs
.stat
.f_bavail
;
603 sfs
->f_files
= outp
->coda_statfs
.stat
.f_files
;
604 sfs
->f_ffree
= outp
->coda_statfs
.stat
.f_ffree
;
606 printk("coda_statfs: Venus returns: %d\n", error
);
609 CODA_FREE(inp
, insize
);
614 * coda_upcall and coda_downcall routines.
618 static inline void coda_waitfor_upcall(struct upc_req
*vmp
,
619 struct venus_comm
*vcommp
)
621 DECLARE_WAITQUEUE(wait
, current
);
623 vmp
->uc_posttime
= jiffies
;
625 add_wait_queue(&vmp
->uc_sleep
, &wait
);
627 if ( !coda_hard
&& vmp
->uc_opcode
!= CODA_CLOSE
)
628 set_current_state(TASK_INTERRUPTIBLE
);
630 set_current_state(TASK_UNINTERRUPTIBLE
);
633 if ( !vcommp
->vc_inuse
)
637 if ( vmp
->uc_flags
& ( REQ_WRITE
| REQ_ABORT
) )
640 if ( !coda_hard
&& vmp
->uc_opcode
!= CODA_CLOSE
&& signal_pending(current
) ) {
641 /* if this process really wants to die, let it go */
642 if ( sigismember(&(current
->pending
.signal
), SIGKILL
) ||
643 sigismember(&(current
->pending
.signal
), SIGINT
) )
645 /* signal is present: after timeout always return
646 really smart idea, probably useless ... */
647 if ( jiffies
- vmp
->uc_posttime
> coda_timeout
* HZ
)
652 remove_wait_queue(&vmp
->uc_sleep
, &wait
);
653 set_current_state(TASK_RUNNING
);
660 * coda_upcall will return an error in the case of
661 * failed communication with Venus _or_ will peek at Venus
662 * reply and return Venus' error.
664 * As venus has 2 types of errors, normal errors (positive) and internal
665 * errors (negative), normal errors are negated, while internal errors
666 * are all mapped to -EINTR, while showing a nice warning message. (jh)
669 static int coda_upcall(struct coda_sb_info
*sbi
,
670 int inSize
, int *outSize
,
671 union inputArgs
*buffer
)
673 struct venus_comm
*vcommp
;
674 union outputArgs
*out
;
678 vcommp
= sbi
->sbi_vcomm
;
679 if ( !vcommp
->vc_inuse
) {
680 printk("No pseudo device in upcall comms at %p\n", vcommp
);
684 /* Format the request message. */
687 printk("Failed to allocate upc_req structure\n");
690 req
->uc_data
= (void *)buffer
;
692 req
->uc_inSize
= inSize
;
693 req
->uc_outSize
= *outSize
? *outSize
: inSize
;
694 req
->uc_opcode
= ((union inputArgs
*)buffer
)->ih
.opcode
;
695 req
->uc_unique
= ++vcommp
->vc_seq
;
696 init_waitqueue_head(&req
->uc_sleep
);
698 /* Fill in the common input args. */
699 ((union inputArgs
*)buffer
)->ih
.unique
= req
->uc_unique
;
701 /* Append msg to pending queue and poke Venus. */
702 list_add(&(req
->uc_chain
), vcommp
->vc_pending
.prev
);
704 wake_up_interruptible(&vcommp
->vc_waitq
);
705 /* We can be interrupted while we wait for Venus to process
706 * our request. If the interrupt occurs before Venus has read
707 * the request, we dequeue and return. If it occurs after the
708 * read but before the reply, we dequeue, send a signal
709 * message, and return. If it occurs after the reply we ignore
710 * it. In no case do we want to restart the syscall. If it
711 * was interrupted by a venus shutdown (psdev_close), return
714 /* Go to sleep. Wake up on signals only after the timeout. */
715 coda_waitfor_upcall(req
, vcommp
);
717 if (vcommp
->vc_inuse
) { /* i.e. Venus is still alive */
718 /* Op went through, interrupt or not... */
719 if (req
->uc_flags
& REQ_WRITE
) {
720 out
= (union outputArgs
*)req
->uc_data
;
721 /* here we map positive Venus errors to kernel errors */
722 error
= -out
->oh
.result
;
723 *outSize
= req
->uc_outSize
;
726 if ( !(req
->uc_flags
& REQ_READ
) && signal_pending(current
)) {
727 /* Interrupted before venus read it. */
728 list_del(&(req
->uc_chain
));
729 /* perhaps the best way to convince the app to
734 if ( (req
->uc_flags
& REQ_READ
) && signal_pending(current
) ) {
735 /* interrupted after Venus did its read, send signal */
736 union inputArgs
*sig_inputArgs
;
737 struct upc_req
*sig_req
;
739 list_del(&(req
->uc_chain
));
741 sig_req
= upc_alloc();
742 if (!sig_req
) goto exit
;
744 CODA_ALLOC((sig_req
->uc_data
), char *, sizeof(struct coda_in_hdr
));
745 if (!sig_req
->uc_data
) {
751 sig_inputArgs
= (union inputArgs
*)sig_req
->uc_data
;
752 sig_inputArgs
->ih
.opcode
= CODA_SIGNAL
;
753 sig_inputArgs
->ih
.unique
= req
->uc_unique
;
755 sig_req
->uc_flags
= REQ_ASYNC
;
756 sig_req
->uc_opcode
= sig_inputArgs
->ih
.opcode
;
757 sig_req
->uc_unique
= sig_inputArgs
->ih
.unique
;
758 sig_req
->uc_inSize
= sizeof(struct coda_in_hdr
);
759 sig_req
->uc_outSize
= sizeof(struct coda_in_hdr
);
761 /* insert at head of queue! */
762 list_add(&(sig_req
->uc_chain
), &vcommp
->vc_pending
);
763 wake_up_interruptible(&vcommp
->vc_waitq
);
765 printk("Coda: Strange interruption..\n");
768 } else { /* If venus died i.e. !VC_OPEN(vcommp) */
769 printk("coda_upcall: Venus dead on (op,un) (%d.%d) flags %d\n",
770 req
->uc_opcode
, req
->uc_unique
, req
->uc_flags
);
780 The statements below are part of the Coda opportunistic
781 programming -- taken from the Mach/BSD kernel code for Coda.
782 You don't get correct semantics by stating what needs to be
783 done without guaranteeing the invariants needed for it to happen.
784 When will be have time to find out what exactly is going on? (pjb)
789 * There are 7 cases where cache invalidations occur. The semantics
790 * of each is listed here:
792 * CODA_FLUSH -- flush all entries from the name cache and the cnode cache.
793 * CODA_PURGEUSER -- flush all entries from the name cache for a specific user
794 * This call is a result of token expiration.
796 * The next arise as the result of callbacks on a file or directory.
797 * CODA_ZAPFILE -- flush the cached attributes for a file.
799 * CODA_ZAPDIR -- flush the attributes for the dir and
800 * force a new lookup for all the children
804 * The next is a result of Venus detecting an inconsistent file.
805 * CODA_PURGEFID -- flush the attribute for the file
806 * purge it and its children from the dcache
808 * The last allows Venus to replace local fids with global ones
809 * during reintegration.
811 * CODA_REPLACE -- replace one ViceFid with another throughout the name cache */
813 int coda_downcall(int opcode
, union outputArgs
* out
, struct super_block
*sb
)
815 /* Handle invalidation requests. */
816 if ( !sb
|| !sb
->s_root
|| !sb
->s_root
->d_inode
)
822 coda_cache_clear_all(sb
, NULL
);
823 shrink_dcache_sb(sb
);
824 coda_flag_inode(sb
->s_root
->d_inode
, C_FLUSH
);
828 case CODA_PURGEUSER
: {
829 struct coda_cred
*cred
= &out
->coda_purgeuser
.cred
;
831 printk("PURGEUSER: null cred!\n");
834 coda_cache_clear_all(sb
, cred
);
840 ViceFid
*fid
= &out
->coda_zapdir
.CodaFid
;
842 inode
= coda_fid_to_inode(fid
, sb
);
844 coda_flag_inode_children(inode
, C_PURGE
);
845 coda_flag_inode(inode
, C_VATTR
);
852 case CODA_ZAPFILE
: {
854 struct ViceFid
*fid
= &out
->coda_zapfile
.CodaFid
;
855 inode
= coda_fid_to_inode(fid
, sb
);
857 coda_flag_inode(inode
, C_VATTR
);
863 case CODA_PURGEFID
: {
865 ViceFid
*fid
= &out
->coda_purgefid
.CodaFid
;
866 inode
= coda_fid_to_inode(fid
, sb
);
868 coda_flag_inode_children(inode
, C_PURGE
);
870 /* catch the dentries later if some are still busy */
871 coda_flag_inode(inode
, C_PURGE
);
872 d_prune_aliases(inode
);
879 case CODA_REPLACE
: {
881 ViceFid
*oldfid
= &out
->coda_replace
.OldFid
;
882 ViceFid
*newfid
= &out
->coda_replace
.NewFid
;
883 inode
= coda_fid_to_inode(oldfid
, sb
);
885 coda_replace_fid(inode
, oldfid
, newfid
);