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 <linux/signal.h>
19 #include <linux/sched.h>
20 #include <linux/types.h>
21 #include <linux/kernel.h>
23 #include <linux/time.h>
25 #include <linux/file.h>
26 #include <linux/stat.h>
27 #include <linux/errno.h>
28 #include <linux/string.h>
29 #include <asm/uaccess.h>
30 #include <linux/vmalloc.h>
31 #include <linux/vfs.h>
33 #include <linux/coda.h>
34 #include <linux/coda_linux.h>
35 #include <linux/coda_psdev.h>
36 #include <linux/coda_fs_i.h>
37 #include <linux/coda_cache.h>
38 #include <linux/coda_proc.h>
40 static int coda_upcall(struct coda_sb_info
*mntinfo
, int inSize
, int *outSize
,
41 union inputArgs
*buffer
);
43 static void *alloc_upcall(int opcode
, int size
)
47 CODA_ALLOC(inp
, union inputArgs
*, size
);
49 return ERR_PTR(-ENOMEM
);
51 inp
->ih
.opcode
= opcode
;
52 inp
->ih
.pid
= current
->pid
;
53 inp
->ih
.pgid
= process_group(current
);
54 #ifdef CONFIG_CODA_FS_OLD_API
55 memset(&inp
->ih
.cred
, 0, sizeof(struct coda_cred
));
56 inp
->ih
.cred
.cr_fsuid
= current
->fsuid
;
58 inp
->ih
.uid
= current
->fsuid
;
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
, struct CodaFid
*fidp
)
80 union outputArgs
*outp
;
81 int insize
, outsize
, error
;
86 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
88 *fidp
= outp
->coda_root
.VFid
;
90 CODA_FREE(inp
, insize
);
94 int venus_getattr(struct super_block
*sb
, struct CodaFid
*fid
,
95 struct coda_vattr
*attr
)
98 union outputArgs
*outp
;
99 int insize
, outsize
, error
;
101 insize
= SIZE(getattr
);
103 inp
->coda_getattr
.VFid
= *fid
;
105 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
107 *attr
= outp
->coda_getattr
.attr
;
109 CODA_FREE(inp
, insize
);
113 int venus_setattr(struct super_block
*sb
, struct CodaFid
*fid
,
114 struct coda_vattr
*vattr
)
116 union inputArgs
*inp
;
117 union outputArgs
*outp
;
118 int insize
, outsize
, error
;
120 insize
= SIZE(setattr
);
123 inp
->coda_setattr
.VFid
= *fid
;
124 inp
->coda_setattr
.attr
= *vattr
;
126 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
128 CODA_FREE(inp
, insize
);
132 int venus_lookup(struct super_block
*sb
, struct CodaFid
*fid
,
133 const char *name
, int length
, int * type
,
134 struct CodaFid
*resfid
)
136 union inputArgs
*inp
;
137 union outputArgs
*outp
;
138 int insize
, outsize
, error
;
141 offset
= INSIZE(lookup
);
142 insize
= max_t(unsigned int, offset
+ length
+1, OUTSIZE(lookup
));
145 inp
->coda_lookup
.VFid
= *fid
;
146 inp
->coda_lookup
.name
= offset
;
147 inp
->coda_lookup
.flags
= CLU_CASE_SENSITIVE
;
148 /* send Venus a null terminated string */
149 memcpy((char *)(inp
) + offset
, name
, length
);
150 *((char *)inp
+ offset
+ length
) = '\0';
152 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
154 *resfid
= outp
->coda_lookup
.VFid
;
155 *type
= outp
->coda_lookup
.vtype
;
158 CODA_FREE(inp
, insize
);
162 int venus_store(struct super_block
*sb
, struct CodaFid
*fid
, int flags
,
165 union inputArgs
*inp
;
166 union outputArgs
*outp
;
167 int insize
, outsize
, error
;
168 #ifdef CONFIG_CODA_FS_OLD_API
169 struct coda_cred cred
= { 0, };
173 insize
= SIZE(store
);
176 #ifdef CONFIG_CODA_FS_OLD_API
177 memcpy(&(inp
->ih
.cred
), &cred
, sizeof(cred
));
182 inp
->coda_store
.VFid
= *fid
;
183 inp
->coda_store
.flags
= flags
;
185 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
187 CODA_FREE(inp
, insize
);
191 int venus_release(struct super_block
*sb
, struct CodaFid
*fid
, int flags
)
193 union inputArgs
*inp
;
194 union outputArgs
*outp
;
195 int insize
, outsize
, error
;
197 insize
= SIZE(release
);
200 inp
->coda_release
.VFid
= *fid
;
201 inp
->coda_release
.flags
= flags
;
203 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
205 CODA_FREE(inp
, insize
);
209 int venus_close(struct super_block
*sb
, struct CodaFid
*fid
, int flags
,
212 union inputArgs
*inp
;
213 union outputArgs
*outp
;
214 int insize
, outsize
, error
;
215 #ifdef CONFIG_CODA_FS_OLD_API
216 struct coda_cred cred
= { 0, };
220 insize
= SIZE(release
);
223 #ifdef CONFIG_CODA_FS_OLD_API
224 memcpy(&(inp
->ih
.cred
), &cred
, sizeof(cred
));
229 inp
->coda_close
.VFid
= *fid
;
230 inp
->coda_close
.flags
= flags
;
232 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
234 CODA_FREE(inp
, insize
);
238 int venus_open(struct super_block
*sb
, struct CodaFid
*fid
,
239 int flags
, struct file
**fh
)
241 union inputArgs
*inp
;
242 union outputArgs
*outp
;
243 int insize
, outsize
, error
;
245 insize
= SIZE(open_by_fd
);
246 UPARG(CODA_OPEN_BY_FD
);
248 inp
->coda_open_by_fd
.VFid
= *fid
;
249 inp
->coda_open_by_fd
.flags
= flags
;
251 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
253 *fh
= outp
->coda_open_by_fd
.fh
;
255 CODA_FREE(inp
, insize
);
259 int venus_mkdir(struct super_block
*sb
, struct CodaFid
*dirfid
,
260 const char *name
, int length
,
261 struct CodaFid
*newfid
, struct coda_vattr
*attrs
)
263 union inputArgs
*inp
;
264 union outputArgs
*outp
;
265 int insize
, outsize
, error
;
268 offset
= INSIZE(mkdir
);
269 insize
= max_t(unsigned int, offset
+ length
+ 1, OUTSIZE(mkdir
));
272 inp
->coda_mkdir
.VFid
= *dirfid
;
273 inp
->coda_mkdir
.attr
= *attrs
;
274 inp
->coda_mkdir
.name
= offset
;
275 /* Venus must get null terminated string */
276 memcpy((char *)(inp
) + offset
, name
, length
);
277 *((char *)inp
+ offset
+ length
) = '\0';
279 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
281 *attrs
= outp
->coda_mkdir
.attr
;
282 *newfid
= outp
->coda_mkdir
.VFid
;
285 CODA_FREE(inp
, insize
);
290 int venus_rename(struct super_block
*sb
, struct CodaFid
*old_fid
,
291 struct CodaFid
*new_fid
, size_t old_length
,
292 size_t new_length
, const char *old_name
,
293 const char *new_name
)
295 union inputArgs
*inp
;
296 union outputArgs
*outp
;
297 int insize
, outsize
, error
;
300 offset
= INSIZE(rename
);
301 insize
= max_t(unsigned int, offset
+ new_length
+ old_length
+ 8,
305 inp
->coda_rename
.sourceFid
= *old_fid
;
306 inp
->coda_rename
.destFid
= *new_fid
;
307 inp
->coda_rename
.srcname
= offset
;
309 /* Venus must receive an null terminated string */
310 s
= ( old_length
& ~0x3) +4; /* round up to word boundary */
311 memcpy((char *)(inp
) + offset
, old_name
, old_length
);
312 *((char *)inp
+ offset
+ old_length
) = '\0';
314 /* another null terminated string for Venus */
316 inp
->coda_rename
.destname
= offset
;
317 s
= ( new_length
& ~0x3) +4; /* round up to word boundary */
318 memcpy((char *)(inp
) + offset
, new_name
, new_length
);
319 *((char *)inp
+ offset
+ new_length
) = '\0';
321 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
323 CODA_FREE(inp
, insize
);
327 int venus_create(struct super_block
*sb
, struct CodaFid
*dirfid
,
328 const char *name
, int length
, int excl
, int mode
,
329 struct CodaFid
*newfid
, struct coda_vattr
*attrs
)
331 union inputArgs
*inp
;
332 union outputArgs
*outp
;
333 int insize
, outsize
, error
;
336 offset
= INSIZE(create
);
337 insize
= max_t(unsigned int, offset
+ length
+ 1, OUTSIZE(create
));
340 inp
->coda_create
.VFid
= *dirfid
;
341 inp
->coda_create
.attr
.va_mode
= mode
;
342 inp
->coda_create
.excl
= excl
;
343 inp
->coda_create
.mode
= mode
;
344 inp
->coda_create
.name
= offset
;
346 /* Venus must get null terminated string */
347 memcpy((char *)(inp
) + offset
, name
, length
);
348 *((char *)inp
+ offset
+ length
) = '\0';
350 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
352 *attrs
= outp
->coda_create
.attr
;
353 *newfid
= outp
->coda_create
.VFid
;
356 CODA_FREE(inp
, insize
);
360 int venus_rmdir(struct super_block
*sb
, struct CodaFid
*dirfid
,
361 const char *name
, int length
)
363 union inputArgs
*inp
;
364 union outputArgs
*outp
;
365 int insize
, outsize
, error
;
368 offset
= INSIZE(rmdir
);
369 insize
= max_t(unsigned int, offset
+ length
+ 1, OUTSIZE(rmdir
));
372 inp
->coda_rmdir
.VFid
= *dirfid
;
373 inp
->coda_rmdir
.name
= offset
;
374 memcpy((char *)(inp
) + offset
, name
, length
);
375 *((char *)inp
+ offset
+ length
) = '\0';
377 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
379 CODA_FREE(inp
, insize
);
383 int venus_remove(struct super_block
*sb
, struct CodaFid
*dirfid
,
384 const char *name
, int length
)
386 union inputArgs
*inp
;
387 union outputArgs
*outp
;
388 int error
=0, insize
, outsize
, offset
;
390 offset
= INSIZE(remove
);
391 insize
= max_t(unsigned int, offset
+ length
+ 1, OUTSIZE(remove
));
394 inp
->coda_remove
.VFid
= *dirfid
;
395 inp
->coda_remove
.name
= offset
;
396 memcpy((char *)(inp
) + offset
, name
, length
);
397 *((char *)inp
+ offset
+ length
) = '\0';
399 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
401 CODA_FREE(inp
, insize
);
405 int venus_readlink(struct super_block
*sb
, struct CodaFid
*fid
,
406 char *buffer
, int *length
)
408 union inputArgs
*inp
;
409 union outputArgs
*outp
;
410 int insize
, outsize
, error
;
414 insize
= max_t(unsigned int,
415 INSIZE(readlink
), OUTSIZE(readlink
)+ *length
+ 1);
416 UPARG(CODA_READLINK
);
418 inp
->coda_readlink
.VFid
= *fid
;
420 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
422 retlen
= outp
->coda_readlink
.count
;
423 if ( retlen
> *length
)
426 result
= (char *)outp
+ (long)outp
->coda_readlink
.data
;
427 memcpy(buffer
, result
, retlen
);
428 *(buffer
+ retlen
) = '\0';
431 CODA_FREE(inp
, insize
);
437 int venus_link(struct super_block
*sb
, struct CodaFid
*fid
,
438 struct CodaFid
*dirfid
, const char *name
, int len
)
440 union inputArgs
*inp
;
441 union outputArgs
*outp
;
442 int insize
, outsize
, error
;
445 offset
= INSIZE(link
);
446 insize
= max_t(unsigned int, offset
+ len
+ 1, OUTSIZE(link
));
449 inp
->coda_link
.sourceFid
= *fid
;
450 inp
->coda_link
.destFid
= *dirfid
;
451 inp
->coda_link
.tname
= offset
;
453 /* make sure strings are null terminated */
454 memcpy((char *)(inp
) + offset
, name
, len
);
455 *((char *)inp
+ offset
+ len
) = '\0';
457 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
459 CODA_FREE(inp
, insize
);
463 int venus_symlink(struct super_block
*sb
, struct CodaFid
*fid
,
464 const char *name
, int len
,
465 const char *symname
, int symlen
)
467 union inputArgs
*inp
;
468 union outputArgs
*outp
;
469 int insize
, outsize
, error
;
472 offset
= INSIZE(symlink
);
473 insize
= max_t(unsigned int, offset
+ len
+ symlen
+ 8, OUTSIZE(symlink
));
476 /* inp->coda_symlink.attr = *tva; XXXXXX */
477 inp
->coda_symlink
.VFid
= *fid
;
479 /* Round up to word boundary and null terminate */
480 inp
->coda_symlink
.srcname
= offset
;
481 s
= ( symlen
& ~0x3 ) + 4;
482 memcpy((char *)(inp
) + offset
, symname
, symlen
);
483 *((char *)inp
+ offset
+ symlen
) = '\0';
485 /* Round up to word boundary and null terminate */
487 inp
->coda_symlink
.tname
= offset
;
488 s
= (len
& ~0x3) + 4;
489 memcpy((char *)(inp
) + offset
, name
, len
);
490 *((char *)inp
+ offset
+ len
) = '\0';
492 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
494 CODA_FREE(inp
, insize
);
498 int venus_fsync(struct super_block
*sb
, struct CodaFid
*fid
)
500 union inputArgs
*inp
;
501 union outputArgs
*outp
;
502 int insize
, outsize
, error
;
507 inp
->coda_fsync
.VFid
= *fid
;
508 error
= coda_upcall(coda_sbp(sb
), sizeof(union inputArgs
),
511 CODA_FREE(inp
, insize
);
515 int venus_access(struct super_block
*sb
, struct CodaFid
*fid
, int mask
)
517 union inputArgs
*inp
;
518 union outputArgs
*outp
;
519 int insize
, outsize
, error
;
521 insize
= SIZE(access
);
524 inp
->coda_access
.VFid
= *fid
;
525 inp
->coda_access
.flags
= mask
;
527 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
529 CODA_FREE(inp
, insize
);
534 int venus_pioctl(struct super_block
*sb
, struct CodaFid
*fid
,
535 unsigned int cmd
, struct PioctlData
*data
)
537 union inputArgs
*inp
;
538 union outputArgs
*outp
;
539 int insize
, outsize
, error
;
542 insize
= VC_MAXMSGSIZE
;
545 /* build packet for Venus */
546 if (data
->vi
.in_size
> VC_MAXDATASIZE
) {
551 if (data
->vi
.out_size
> VC_MAXDATASIZE
) {
556 inp
->coda_ioctl
.VFid
= *fid
;
558 /* the cmd field was mutated by increasing its size field to
559 * reflect the path and follow args. We need to subtract that
560 * out before sending the command to Venus. */
561 inp
->coda_ioctl
.cmd
= (cmd
& ~(PIOCPARM_MASK
<< 16));
562 iocsize
= ((cmd
>> 16) & PIOCPARM_MASK
) - sizeof(char *) - sizeof(int);
563 inp
->coda_ioctl
.cmd
|= (iocsize
& PIOCPARM_MASK
) << 16;
565 /* in->coda_ioctl.rwflag = flag; */
566 inp
->coda_ioctl
.len
= data
->vi
.in_size
;
567 inp
->coda_ioctl
.data
= (char *)(INSIZE(ioctl
));
569 /* get the data out of user space */
570 if ( copy_from_user((char*)inp
+ (long)inp
->coda_ioctl
.data
,
571 data
->vi
.in
, data
->vi
.in_size
) ) {
576 error
= coda_upcall(coda_sbp(sb
), SIZE(ioctl
) + data
->vi
.in_size
,
580 printk("coda_pioctl: Venus returns: %d for %s\n",
581 error
, coda_f2s(fid
));
585 if (outsize
< (long)outp
->coda_ioctl
.data
+ outp
->coda_ioctl
.len
) {
590 /* Copy out the OUT buffer. */
591 if (outp
->coda_ioctl
.len
> data
->vi
.out_size
) {
596 /* Copy out the OUT buffer. */
597 if (copy_to_user(data
->vi
.out
,
598 (char *)outp
+ (long)outp
->coda_ioctl
.data
,
599 outp
->coda_ioctl
.len
)) {
605 CODA_FREE(inp
, insize
);
609 int venus_statfs(struct dentry
*dentry
, struct kstatfs
*sfs
)
611 union inputArgs
*inp
;
612 union outputArgs
*outp
;
613 int insize
, outsize
, error
;
615 insize
= max_t(unsigned int, INSIZE(statfs
), OUTSIZE(statfs
));
618 error
= coda_upcall(coda_sbp(dentry
->d_sb
), insize
, &outsize
, inp
);
620 sfs
->f_blocks
= outp
->coda_statfs
.stat
.f_blocks
;
621 sfs
->f_bfree
= outp
->coda_statfs
.stat
.f_bfree
;
622 sfs
->f_bavail
= outp
->coda_statfs
.stat
.f_bavail
;
623 sfs
->f_files
= outp
->coda_statfs
.stat
.f_files
;
624 sfs
->f_ffree
= outp
->coda_statfs
.stat
.f_ffree
;
627 CODA_FREE(inp
, insize
);
632 * coda_upcall and coda_downcall routines.
634 static void block_signals(sigset_t
*old
)
636 spin_lock_irq(¤t
->sighand
->siglock
);
637 *old
= current
->blocked
;
639 sigfillset(¤t
->blocked
);
640 sigdelset(¤t
->blocked
, SIGKILL
);
641 sigdelset(¤t
->blocked
, SIGSTOP
);
642 sigdelset(¤t
->blocked
, SIGINT
);
645 spin_unlock_irq(¤t
->sighand
->siglock
);
648 static void unblock_signals(sigset_t
*old
)
650 spin_lock_irq(¤t
->sighand
->siglock
);
651 current
->blocked
= *old
;
653 spin_unlock_irq(¤t
->sighand
->siglock
);
656 /* Don't allow signals to interrupt the following upcalls before venus
658 * - CODA_CLOSE or CODA_RELEASE upcall (to avoid reference count problems)
659 * - CODA_STORE (to avoid data loss)
661 #define CODA_INTERRUPTIBLE(r) (!coda_hard && \
662 (((r)->uc_opcode != CODA_CLOSE && \
663 (r)->uc_opcode != CODA_STORE && \
664 (r)->uc_opcode != CODA_RELEASE) || \
665 (r)->uc_flags & REQ_READ))
667 static inline void coda_waitfor_upcall(struct upc_req
*req
)
669 DECLARE_WAITQUEUE(wait
, current
);
670 unsigned long timeout
= jiffies
+ coda_timeout
* HZ
;
677 add_wait_queue(&req
->uc_sleep
, &wait
);
679 if (CODA_INTERRUPTIBLE(req
))
680 set_current_state(TASK_INTERRUPTIBLE
);
682 set_current_state(TASK_UNINTERRUPTIBLE
);
685 if (req
->uc_flags
& (REQ_WRITE
| REQ_ABORT
))
688 if (blocked
&& time_after(jiffies
, timeout
) &&
689 CODA_INTERRUPTIBLE(req
))
691 unblock_signals(&old
);
695 if (signal_pending(current
)) {
696 list_del(&req
->uc_chain
);
701 schedule_timeout(HZ
);
706 unblock_signals(&old
);
708 remove_wait_queue(&req
->uc_sleep
, &wait
);
709 set_current_state(TASK_RUNNING
);
714 * coda_upcall will return an error in the case of
715 * failed communication with Venus _or_ will peek at Venus
716 * reply and return Venus' error.
718 * As venus has 2 types of errors, normal errors (positive) and internal
719 * errors (negative), normal errors are negated, while internal errors
720 * are all mapped to -EINTR, while showing a nice warning message. (jh)
723 static int coda_upcall(struct coda_sb_info
*sbi
,
724 int inSize
, int *outSize
,
725 union inputArgs
*buffer
)
727 struct venus_comm
*vcommp
;
728 union outputArgs
*out
;
729 union inputArgs
*sig_inputArgs
;
730 struct upc_req
*req
, *sig_req
;
733 vcommp
= sbi
->sbi_vcomm
;
734 if (!vcommp
->vc_inuse
) {
735 printk(KERN_NOTICE
"coda: Venus dead, not sending upcall\n");
739 /* Format the request message. */
740 req
= kmalloc(sizeof(struct upc_req
), GFP_KERNEL
);
744 req
->uc_data
= (void *)buffer
;
746 req
->uc_inSize
= inSize
;
747 req
->uc_outSize
= *outSize
? *outSize
: inSize
;
748 req
->uc_opcode
= ((union inputArgs
*)buffer
)->ih
.opcode
;
749 req
->uc_unique
= ++vcommp
->vc_seq
;
750 init_waitqueue_head(&req
->uc_sleep
);
752 /* Fill in the common input args. */
753 ((union inputArgs
*)buffer
)->ih
.unique
= req
->uc_unique
;
755 /* Append msg to pending queue and poke Venus. */
756 list_add_tail(&req
->uc_chain
, &vcommp
->vc_pending
);
758 wake_up_interruptible(&vcommp
->vc_waitq
);
759 /* We can be interrupted while we wait for Venus to process
760 * our request. If the interrupt occurs before Venus has read
761 * the request, we dequeue and return. If it occurs after the
762 * read but before the reply, we dequeue, send a signal
763 * message, and return. If it occurs after the reply we ignore
764 * it. In no case do we want to restart the syscall. If it
765 * was interrupted by a venus shutdown (psdev_close), return
768 /* Go to sleep. Wake up on signals only after the timeout. */
769 coda_waitfor_upcall(req
);
771 /* Op went through, interrupt or not... */
772 if (req
->uc_flags
& REQ_WRITE
) {
773 out
= (union outputArgs
*)req
->uc_data
;
774 /* here we map positive Venus errors to kernel errors */
775 error
= -out
->oh
.result
;
776 *outSize
= req
->uc_outSize
;
781 if ((req
->uc_flags
& REQ_ABORT
) || !signal_pending(current
)) {
782 printk(KERN_WARNING
"coda: Unexpected interruption.\n");
786 /* Interrupted before venus read it. */
787 if (!(req
->uc_flags
& REQ_READ
))
790 /* Venus saw the upcall, make sure we can send interrupt signal */
791 if (!vcommp
->vc_inuse
) {
792 printk(KERN_INFO
"coda: Venus dead, not sending signal.\n");
797 sig_req
= kmalloc(sizeof(struct upc_req
), GFP_KERNEL
);
798 if (!sig_req
) goto exit
;
800 CODA_ALLOC((sig_req
->uc_data
), char *, sizeof(struct coda_in_hdr
));
801 if (!sig_req
->uc_data
) {
807 sig_inputArgs
= (union inputArgs
*)sig_req
->uc_data
;
808 sig_inputArgs
->ih
.opcode
= CODA_SIGNAL
;
809 sig_inputArgs
->ih
.unique
= req
->uc_unique
;
811 sig_req
->uc_flags
= REQ_ASYNC
;
812 sig_req
->uc_opcode
= sig_inputArgs
->ih
.opcode
;
813 sig_req
->uc_unique
= sig_inputArgs
->ih
.unique
;
814 sig_req
->uc_inSize
= sizeof(struct coda_in_hdr
);
815 sig_req
->uc_outSize
= sizeof(struct coda_in_hdr
);
817 /* insert at head of queue! */
818 list_add(&(sig_req
->uc_chain
), &vcommp
->vc_pending
);
819 wake_up_interruptible(&vcommp
->vc_waitq
);
827 The statements below are part of the Coda opportunistic
828 programming -- taken from the Mach/BSD kernel code for Coda.
829 You don't get correct semantics by stating what needs to be
830 done without guaranteeing the invariants needed for it to happen.
831 When will be have time to find out what exactly is going on? (pjb)
836 * There are 7 cases where cache invalidations occur. The semantics
837 * of each is listed here:
839 * CODA_FLUSH -- flush all entries from the name cache and the cnode cache.
840 * CODA_PURGEUSER -- flush all entries from the name cache for a specific user
841 * This call is a result of token expiration.
843 * The next arise as the result of callbacks on a file or directory.
844 * CODA_ZAPFILE -- flush the cached attributes for a file.
846 * CODA_ZAPDIR -- flush the attributes for the dir and
847 * force a new lookup for all the children
851 * The next is a result of Venus detecting an inconsistent file.
852 * CODA_PURGEFID -- flush the attribute for the file
853 * purge it and its children from the dcache
855 * The last allows Venus to replace local fids with global ones
856 * during reintegration.
858 * CODA_REPLACE -- replace one CodaFid with another throughout the name cache */
860 int coda_downcall(int opcode
, union outputArgs
* out
, struct super_block
*sb
)
862 /* Handle invalidation requests. */
863 if ( !sb
|| !sb
->s_root
|| !sb
->s_root
->d_inode
)
869 coda_cache_clear_all(sb
);
870 shrink_dcache_sb(sb
);
871 coda_flag_inode(sb
->s_root
->d_inode
, C_FLUSH
);
875 case CODA_PURGEUSER
: {
876 coda_cache_clear_all(sb
);
882 struct CodaFid
*fid
= &out
->coda_zapdir
.CodaFid
;
884 inode
= coda_fid_to_inode(fid
, sb
);
886 coda_flag_inode_children(inode
, C_PURGE
);
887 coda_flag_inode(inode
, C_VATTR
);
894 case CODA_ZAPFILE
: {
896 struct CodaFid
*fid
= &out
->coda_zapfile
.CodaFid
;
897 inode
= coda_fid_to_inode(fid
, sb
);
899 coda_flag_inode(inode
, C_VATTR
);
905 case CODA_PURGEFID
: {
907 struct CodaFid
*fid
= &out
->coda_purgefid
.CodaFid
;
908 inode
= coda_fid_to_inode(fid
, sb
);
910 coda_flag_inode_children(inode
, C_PURGE
);
912 /* catch the dentries later if some are still busy */
913 coda_flag_inode(inode
, C_PURGE
);
914 d_prune_aliases(inode
);
921 case CODA_REPLACE
: {
923 struct CodaFid
*oldfid
= &out
->coda_replace
.OldFid
;
924 struct CodaFid
*newfid
= &out
->coda_replace
.NewFid
;
925 inode
= coda_fid_to_inode(oldfid
, sb
);
927 coda_replace_fid(inode
, oldfid
, newfid
);