ad65ee01790f172e4fb50720c592814b1a06e876
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 #define upc_alloc() kmalloc(sizeof(struct upc_req), GFP_KERNEL)
41 #define upc_free(r) kfree(r)
43 static int coda_upcall(struct coda_sb_info
*mntinfo
, int inSize
, int *outSize
,
44 union inputArgs
*buffer
);
46 static void *alloc_upcall(int opcode
, int size
)
50 CODA_ALLOC(inp
, union inputArgs
*, size
);
52 return ERR_PTR(-ENOMEM
);
54 inp
->ih
.opcode
= opcode
;
55 inp
->ih
.pid
= current
->pid
;
56 inp
->ih
.pgid
= process_group(current
);
57 #ifdef CONFIG_CODA_FS_OLD_API
58 memset(&inp
->ih
.cred
, 0, sizeof(struct coda_cred
));
59 inp
->ih
.cred
.cr_fsuid
= current
->fsuid
;
61 inp
->ih
.uid
= current
->fsuid
;
68 inp = (union inputArgs *)alloc_upcall(op, insize); \
69 if (IS_ERR(inp)) { return PTR_ERR(inp); }\
70 outp = (union outputArgs *)(inp); \
74 #define INSIZE(tag) sizeof(struct coda_ ## tag ## _in)
75 #define OUTSIZE(tag) sizeof(struct coda_ ## tag ## _out)
76 #define SIZE(tag) max_t(unsigned int, INSIZE(tag), OUTSIZE(tag))
80 int venus_rootfid(struct super_block
*sb
, struct CodaFid
*fidp
)
83 union outputArgs
*outp
;
84 int insize
, outsize
, error
;
89 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
92 printk("coda_get_rootfid: error %d\n", error
);
94 *fidp
= outp
->coda_root
.VFid
;
97 CODA_FREE(inp
, insize
);
101 int venus_getattr(struct super_block
*sb
, struct CodaFid
*fid
,
102 struct coda_vattr
*attr
)
104 union inputArgs
*inp
;
105 union outputArgs
*outp
;
106 int insize
, outsize
, error
;
108 insize
= SIZE(getattr
);
110 inp
->coda_getattr
.VFid
= *fid
;
112 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
114 *attr
= outp
->coda_getattr
.attr
;
116 CODA_FREE(inp
, insize
);
120 int venus_setattr(struct super_block
*sb
, struct CodaFid
*fid
,
121 struct coda_vattr
*vattr
)
123 union inputArgs
*inp
;
124 union outputArgs
*outp
;
125 int insize
, outsize
, error
;
127 insize
= SIZE(setattr
);
130 inp
->coda_setattr
.VFid
= *fid
;
131 inp
->coda_setattr
.attr
= *vattr
;
133 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
135 CODA_FREE(inp
, insize
);
139 int venus_lookup(struct super_block
*sb
, struct CodaFid
*fid
,
140 const char *name
, int length
, int * type
,
141 struct CodaFid
*resfid
)
143 union inputArgs
*inp
;
144 union outputArgs
*outp
;
145 int insize
, outsize
, error
;
148 offset
= INSIZE(lookup
);
149 insize
= max_t(unsigned int, 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
);
161 *resfid
= outp
->coda_lookup
.VFid
;
162 *type
= outp
->coda_lookup
.vtype
;
164 CODA_FREE(inp
, insize
);
168 int venus_store(struct super_block
*sb
, struct CodaFid
*fid
, int flags
,
171 union inputArgs
*inp
;
172 union outputArgs
*outp
;
173 int insize
, outsize
, error
;
174 #ifdef CONFIG_CODA_FS_OLD_API
175 struct coda_cred cred
= { 0, };
179 insize
= SIZE(store
);
182 #ifdef CONFIG_CODA_FS_OLD_API
183 memcpy(&(inp
->ih
.cred
), &cred
, sizeof(cred
));
188 inp
->coda_store
.VFid
= *fid
;
189 inp
->coda_store
.flags
= flags
;
191 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
193 CODA_FREE(inp
, insize
);
197 int venus_release(struct super_block
*sb
, struct CodaFid
*fid
, int flags
)
199 union inputArgs
*inp
;
200 union outputArgs
*outp
;
201 int insize
, outsize
, error
;
203 insize
= SIZE(release
);
206 inp
->coda_release
.VFid
= *fid
;
207 inp
->coda_release
.flags
= flags
;
209 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
211 CODA_FREE(inp
, insize
);
215 int venus_close(struct super_block
*sb
, struct CodaFid
*fid
, int flags
,
218 union inputArgs
*inp
;
219 union outputArgs
*outp
;
220 int insize
, outsize
, error
;
221 #ifdef CONFIG_CODA_FS_OLD_API
222 struct coda_cred cred
= { 0, };
226 insize
= SIZE(release
);
229 #ifdef CONFIG_CODA_FS_OLD_API
230 memcpy(&(inp
->ih
.cred
), &cred
, sizeof(cred
));
235 inp
->coda_close
.VFid
= *fid
;
236 inp
->coda_close
.flags
= flags
;
238 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
240 CODA_FREE(inp
, insize
);
244 int venus_open(struct super_block
*sb
, struct CodaFid
*fid
,
245 int flags
, struct file
**fh
)
247 union inputArgs
*inp
;
248 union outputArgs
*outp
;
249 int insize
, outsize
, error
;
251 insize
= SIZE(open_by_fd
);
252 UPARG(CODA_OPEN_BY_FD
);
254 inp
->coda_open_by_fd
.VFid
= *fid
;
255 inp
->coda_open_by_fd
.flags
= flags
;
257 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
259 *fh
= outp
->coda_open_by_fd
.fh
;
261 CODA_FREE(inp
, insize
);
265 int venus_mkdir(struct super_block
*sb
, struct CodaFid
*dirfid
,
266 const char *name
, int length
,
267 struct CodaFid
*newfid
, struct coda_vattr
*attrs
)
269 union inputArgs
*inp
;
270 union outputArgs
*outp
;
271 int insize
, outsize
, error
;
274 offset
= INSIZE(mkdir
);
275 insize
= max_t(unsigned int, offset
+ length
+ 1, OUTSIZE(mkdir
));
278 inp
->coda_mkdir
.VFid
= *dirfid
;
279 inp
->coda_mkdir
.attr
= *attrs
;
280 inp
->coda_mkdir
.name
= offset
;
281 /* Venus must get null terminated string */
282 memcpy((char *)(inp
) + offset
, name
, length
);
283 *((char *)inp
+ offset
+ length
) = '\0';
285 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
287 *attrs
= outp
->coda_mkdir
.attr
;
288 *newfid
= outp
->coda_mkdir
.VFid
;
290 CODA_FREE(inp
, insize
);
295 int venus_rename(struct super_block
*sb
, struct CodaFid
*old_fid
,
296 struct CodaFid
*new_fid
, size_t old_length
,
297 size_t new_length
, const char *old_name
,
298 const char *new_name
)
300 union inputArgs
*inp
;
301 union outputArgs
*outp
;
302 int insize
, outsize
, error
;
305 offset
= INSIZE(rename
);
306 insize
= max_t(unsigned int, offset
+ new_length
+ old_length
+ 8,
310 inp
->coda_rename
.sourceFid
= *old_fid
;
311 inp
->coda_rename
.destFid
= *new_fid
;
312 inp
->coda_rename
.srcname
= offset
;
314 /* Venus must receive an null terminated string */
315 s
= ( old_length
& ~0x3) +4; /* round up to word boundary */
316 memcpy((char *)(inp
) + offset
, old_name
, old_length
);
317 *((char *)inp
+ offset
+ old_length
) = '\0';
319 /* another null terminated string for Venus */
321 inp
->coda_rename
.destname
= offset
;
322 s
= ( new_length
& ~0x3) +4; /* round up to word boundary */
323 memcpy((char *)(inp
) + offset
, new_name
, new_length
);
324 *((char *)inp
+ offset
+ new_length
) = '\0';
326 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
328 CODA_FREE(inp
, insize
);
332 int venus_create(struct super_block
*sb
, struct CodaFid
*dirfid
,
333 const char *name
, int length
, int excl
, int mode
,
334 struct CodaFid
*newfid
, struct coda_vattr
*attrs
)
336 union inputArgs
*inp
;
337 union outputArgs
*outp
;
338 int insize
, outsize
, error
;
341 offset
= INSIZE(create
);
342 insize
= max_t(unsigned int, offset
+ length
+ 1, OUTSIZE(create
));
345 inp
->coda_create
.VFid
= *dirfid
;
346 inp
->coda_create
.attr
.va_mode
= mode
;
347 inp
->coda_create
.excl
= excl
;
348 inp
->coda_create
.mode
= mode
;
349 inp
->coda_create
.name
= offset
;
351 /* Venus must get null terminated string */
352 memcpy((char *)(inp
) + offset
, name
, length
);
353 *((char *)inp
+ offset
+ length
) = '\0';
355 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
357 *attrs
= outp
->coda_create
.attr
;
358 *newfid
= outp
->coda_create
.VFid
;
360 CODA_FREE(inp
, insize
);
364 int venus_rmdir(struct super_block
*sb
, struct CodaFid
*dirfid
,
365 const char *name
, int length
)
367 union inputArgs
*inp
;
368 union outputArgs
*outp
;
369 int insize
, outsize
, error
;
372 offset
= INSIZE(rmdir
);
373 insize
= max_t(unsigned int, offset
+ length
+ 1, OUTSIZE(rmdir
));
376 inp
->coda_rmdir
.VFid
= *dirfid
;
377 inp
->coda_rmdir
.name
= offset
;
378 memcpy((char *)(inp
) + offset
, name
, length
);
379 *((char *)inp
+ offset
+ length
) = '\0';
381 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
383 CODA_FREE(inp
, insize
);
387 int venus_remove(struct super_block
*sb
, struct CodaFid
*dirfid
,
388 const char *name
, int length
)
390 union inputArgs
*inp
;
391 union outputArgs
*outp
;
392 int error
=0, insize
, outsize
, offset
;
394 offset
= INSIZE(remove
);
395 insize
= max_t(unsigned int, offset
+ length
+ 1, OUTSIZE(remove
));
398 inp
->coda_remove
.VFid
= *dirfid
;
399 inp
->coda_remove
.name
= offset
;
400 memcpy((char *)(inp
) + offset
, name
, length
);
401 *((char *)inp
+ offset
+ length
) = '\0';
403 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
405 CODA_FREE(inp
, insize
);
409 int venus_readlink(struct super_block
*sb
, struct CodaFid
*fid
,
410 char *buffer
, int *length
)
412 union inputArgs
*inp
;
413 union outputArgs
*outp
;
414 int insize
, outsize
, error
;
418 insize
= max_t(unsigned int,
419 INSIZE(readlink
), OUTSIZE(readlink
)+ *length
+ 1);
420 UPARG(CODA_READLINK
);
422 inp
->coda_readlink
.VFid
= *fid
;
424 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
427 retlen
= outp
->coda_readlink
.count
;
428 if ( retlen
> *length
)
431 result
= (char *)outp
+ (long)outp
->coda_readlink
.data
;
432 memcpy(buffer
, result
, retlen
);
433 *(buffer
+ retlen
) = '\0';
436 CODA_FREE(inp
, insize
);
442 int venus_link(struct super_block
*sb
, struct CodaFid
*fid
,
443 struct CodaFid
*dirfid
, const char *name
, int len
)
445 union inputArgs
*inp
;
446 union outputArgs
*outp
;
447 int insize
, outsize
, error
;
450 offset
= INSIZE(link
);
451 insize
= max_t(unsigned int, offset
+ len
+ 1, OUTSIZE(link
));
454 inp
->coda_link
.sourceFid
= *fid
;
455 inp
->coda_link
.destFid
= *dirfid
;
456 inp
->coda_link
.tname
= offset
;
458 /* make sure strings are null terminated */
459 memcpy((char *)(inp
) + offset
, name
, len
);
460 *((char *)inp
+ offset
+ len
) = '\0';
462 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
464 CODA_FREE(inp
, insize
);
468 int venus_symlink(struct super_block
*sb
, struct CodaFid
*fid
,
469 const char *name
, int len
,
470 const char *symname
, int symlen
)
472 union inputArgs
*inp
;
473 union outputArgs
*outp
;
474 int insize
, outsize
, error
;
477 offset
= INSIZE(symlink
);
478 insize
= max_t(unsigned int, offset
+ len
+ symlen
+ 8, OUTSIZE(symlink
));
481 /* inp->coda_symlink.attr = *tva; XXXXXX */
482 inp
->coda_symlink
.VFid
= *fid
;
484 /* Round up to word boundary and null terminate */
485 inp
->coda_symlink
.srcname
= offset
;
486 s
= ( symlen
& ~0x3 ) + 4;
487 memcpy((char *)(inp
) + offset
, symname
, symlen
);
488 *((char *)inp
+ offset
+ symlen
) = '\0';
490 /* Round up to word boundary and null terminate */
492 inp
->coda_symlink
.tname
= offset
;
493 s
= (len
& ~0x3) + 4;
494 memcpy((char *)(inp
) + offset
, name
, len
);
495 *((char *)inp
+ offset
+ len
) = '\0';
497 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
499 CODA_FREE(inp
, insize
);
503 int venus_fsync(struct super_block
*sb
, struct CodaFid
*fid
)
505 union inputArgs
*inp
;
506 union outputArgs
*outp
;
507 int insize
, outsize
, error
;
512 inp
->coda_fsync
.VFid
= *fid
;
513 error
= coda_upcall(coda_sbp(sb
), sizeof(union inputArgs
),
516 CODA_FREE(inp
, insize
);
520 int venus_access(struct super_block
*sb
, struct CodaFid
*fid
, int mask
)
522 union inputArgs
*inp
;
523 union outputArgs
*outp
;
524 int insize
, outsize
, error
;
526 insize
= SIZE(access
);
529 inp
->coda_access
.VFid
= *fid
;
530 inp
->coda_access
.flags
= mask
;
532 error
= coda_upcall(coda_sbp(sb
), insize
, &outsize
, inp
);
534 CODA_FREE(inp
, insize
);
539 int venus_pioctl(struct super_block
*sb
, struct CodaFid
*fid
,
540 unsigned int cmd
, struct PioctlData
*data
)
542 union inputArgs
*inp
;
543 union outputArgs
*outp
;
544 int insize
, outsize
, error
;
547 insize
= VC_MAXMSGSIZE
;
550 /* build packet for Venus */
551 if (data
->vi
.in_size
> VC_MAXDATASIZE
) {
556 if (data
->vi
.out_size
> VC_MAXDATASIZE
) {
561 inp
->coda_ioctl
.VFid
= *fid
;
563 /* the cmd field was mutated by increasing its size field to
564 * reflect the path and follow args. We need to subtract that
565 * out before sending the command to Venus. */
566 inp
->coda_ioctl
.cmd
= (cmd
& ~(PIOCPARM_MASK
<< 16));
567 iocsize
= ((cmd
>> 16) & PIOCPARM_MASK
) - sizeof(char *) - sizeof(int);
568 inp
->coda_ioctl
.cmd
|= (iocsize
& PIOCPARM_MASK
) << 16;
570 /* in->coda_ioctl.rwflag = flag; */
571 inp
->coda_ioctl
.len
= data
->vi
.in_size
;
572 inp
->coda_ioctl
.data
= (char *)(INSIZE(ioctl
));
574 /* get the data out of user space */
575 if ( copy_from_user((char*)inp
+ (long)inp
->coda_ioctl
.data
,
576 data
->vi
.in
, data
->vi
.in_size
) ) {
581 error
= coda_upcall(coda_sbp(sb
), SIZE(ioctl
) + data
->vi
.in_size
,
585 printk("coda_pioctl: Venus returns: %d for %s\n",
586 error
, coda_f2s(fid
));
590 if (outsize
< (long)outp
->coda_ioctl
.data
+ outp
->coda_ioctl
.len
) {
595 /* Copy out the OUT buffer. */
596 if (outp
->coda_ioctl
.len
> data
->vi
.out_size
) {
601 /* Copy out the OUT buffer. */
602 if (copy_to_user(data
->vi
.out
,
603 (char *)outp
+ (long)outp
->coda_ioctl
.data
,
604 outp
->coda_ioctl
.len
)) {
610 CODA_FREE(inp
, insize
);
614 int venus_statfs(struct dentry
*dentry
, struct kstatfs
*sfs
)
616 union inputArgs
*inp
;
617 union outputArgs
*outp
;
618 int insize
, outsize
, error
;
620 insize
= max_t(unsigned int, INSIZE(statfs
), OUTSIZE(statfs
));
623 error
= coda_upcall(coda_sbp(dentry
->d_sb
), insize
, &outsize
, inp
);
626 sfs
->f_blocks
= outp
->coda_statfs
.stat
.f_blocks
;
627 sfs
->f_bfree
= outp
->coda_statfs
.stat
.f_bfree
;
628 sfs
->f_bavail
= outp
->coda_statfs
.stat
.f_bavail
;
629 sfs
->f_files
= outp
->coda_statfs
.stat
.f_files
;
630 sfs
->f_ffree
= outp
->coda_statfs
.stat
.f_ffree
;
632 printk("coda_statfs: Venus returns: %d\n", error
);
635 CODA_FREE(inp
, insize
);
640 * coda_upcall and coda_downcall routines.
642 static void block_signals(sigset_t
*old
)
644 spin_lock_irq(¤t
->sighand
->siglock
);
645 *old
= current
->blocked
;
647 sigfillset(¤t
->blocked
);
648 sigdelset(¤t
->blocked
, SIGKILL
);
649 sigdelset(¤t
->blocked
, SIGSTOP
);
650 sigdelset(¤t
->blocked
, SIGINT
);
653 spin_unlock_irq(¤t
->sighand
->siglock
);
656 static void unblock_signals(sigset_t
*old
)
658 spin_lock_irq(¤t
->sighand
->siglock
);
659 current
->blocked
= *old
;
661 spin_unlock_irq(¤t
->sighand
->siglock
);
664 /* Don't allow signals to interrupt the following upcalls before venus
666 * - CODA_CLOSE or CODA_RELEASE upcall (to avoid reference count problems)
667 * - CODA_STORE (to avoid data loss)
669 #define CODA_INTERRUPTIBLE(r) (!coda_hard && \
670 (((r)->uc_opcode != CODA_CLOSE && \
671 (r)->uc_opcode != CODA_STORE && \
672 (r)->uc_opcode != CODA_RELEASE) || \
673 (r)->uc_flags & REQ_READ))
675 static inline void coda_waitfor_upcall(struct upc_req
*req
)
677 DECLARE_WAITQUEUE(wait
, current
);
678 unsigned long timeout
= jiffies
+ coda_timeout
* HZ
;
685 add_wait_queue(&req
->uc_sleep
, &wait
);
687 if (CODA_INTERRUPTIBLE(req
))
688 set_current_state(TASK_INTERRUPTIBLE
);
690 set_current_state(TASK_UNINTERRUPTIBLE
);
693 if (req
->uc_flags
& (REQ_WRITE
| REQ_ABORT
))
696 if (blocked
&& time_after(jiffies
, timeout
) &&
697 CODA_INTERRUPTIBLE(req
))
699 unblock_signals(&old
);
703 if (signal_pending(current
)) {
704 list_del(&req
->uc_chain
);
709 schedule_timeout(HZ
);
714 unblock_signals(&old
);
716 remove_wait_queue(&req
->uc_sleep
, &wait
);
717 set_current_state(TASK_RUNNING
);
722 * coda_upcall will return an error in the case of
723 * failed communication with Venus _or_ will peek at Venus
724 * reply and return Venus' error.
726 * As venus has 2 types of errors, normal errors (positive) and internal
727 * errors (negative), normal errors are negated, while internal errors
728 * are all mapped to -EINTR, while showing a nice warning message. (jh)
731 static int coda_upcall(struct coda_sb_info
*sbi
,
732 int inSize
, int *outSize
,
733 union inputArgs
*buffer
)
735 struct venus_comm
*vcommp
;
736 union outputArgs
*out
;
737 union inputArgs
*sig_inputArgs
;
738 struct upc_req
*req
, *sig_req
;
741 vcommp
= sbi
->sbi_vcomm
;
742 if (!vcommp
->vc_inuse
) {
743 printk(KERN_NOTICE
"coda: Venus dead, not sending upcall\n");
747 /* Format the request message. */
752 req
->uc_data
= (void *)buffer
;
754 req
->uc_inSize
= inSize
;
755 req
->uc_outSize
= *outSize
? *outSize
: inSize
;
756 req
->uc_opcode
= ((union inputArgs
*)buffer
)->ih
.opcode
;
757 req
->uc_unique
= ++vcommp
->vc_seq
;
758 init_waitqueue_head(&req
->uc_sleep
);
760 /* Fill in the common input args. */
761 ((union inputArgs
*)buffer
)->ih
.unique
= req
->uc_unique
;
763 /* Append msg to pending queue and poke Venus. */
764 list_add_tail(&req
->uc_chain
, &vcommp
->vc_pending
);
766 wake_up_interruptible(&vcommp
->vc_waitq
);
767 /* We can be interrupted while we wait for Venus to process
768 * our request. If the interrupt occurs before Venus has read
769 * the request, we dequeue and return. If it occurs after the
770 * read but before the reply, we dequeue, send a signal
771 * message, and return. If it occurs after the reply we ignore
772 * it. In no case do we want to restart the syscall. If it
773 * was interrupted by a venus shutdown (psdev_close), return
776 /* Go to sleep. Wake up on signals only after the timeout. */
777 coda_waitfor_upcall(req
);
779 /* Op went through, interrupt or not... */
780 if (req
->uc_flags
& REQ_WRITE
) {
781 out
= (union outputArgs
*)req
->uc_data
;
782 /* here we map positive Venus errors to kernel errors */
783 error
= -out
->oh
.result
;
784 *outSize
= req
->uc_outSize
;
789 if ((req
->uc_flags
& REQ_ABORT
) || !signal_pending(current
)) {
790 printk(KERN_WARNING
"coda: Unexpected interruption.\n");
794 /* Interrupted before venus read it. */
795 if (!(req
->uc_flags
& REQ_READ
))
798 /* Venus saw the upcall, make sure we can send interrupt signal */
799 if (!vcommp
->vc_inuse
) {
800 printk(KERN_INFO
"coda: Venus dead, not sending signal.\n");
805 sig_req
= upc_alloc();
806 if (!sig_req
) goto exit
;
808 CODA_ALLOC((sig_req
->uc_data
), char *, sizeof(struct coda_in_hdr
));
809 if (!sig_req
->uc_data
) {
815 sig_inputArgs
= (union inputArgs
*)sig_req
->uc_data
;
816 sig_inputArgs
->ih
.opcode
= CODA_SIGNAL
;
817 sig_inputArgs
->ih
.unique
= req
->uc_unique
;
819 sig_req
->uc_flags
= REQ_ASYNC
;
820 sig_req
->uc_opcode
= sig_inputArgs
->ih
.opcode
;
821 sig_req
->uc_unique
= sig_inputArgs
->ih
.unique
;
822 sig_req
->uc_inSize
= sizeof(struct coda_in_hdr
);
823 sig_req
->uc_outSize
= sizeof(struct coda_in_hdr
);
825 /* insert at head of queue! */
826 list_add(&(sig_req
->uc_chain
), &vcommp
->vc_pending
);
827 wake_up_interruptible(&vcommp
->vc_waitq
);
835 The statements below are part of the Coda opportunistic
836 programming -- taken from the Mach/BSD kernel code for Coda.
837 You don't get correct semantics by stating what needs to be
838 done without guaranteeing the invariants needed for it to happen.
839 When will be have time to find out what exactly is going on? (pjb)
844 * There are 7 cases where cache invalidations occur. The semantics
845 * of each is listed here:
847 * CODA_FLUSH -- flush all entries from the name cache and the cnode cache.
848 * CODA_PURGEUSER -- flush all entries from the name cache for a specific user
849 * This call is a result of token expiration.
851 * The next arise as the result of callbacks on a file or directory.
852 * CODA_ZAPFILE -- flush the cached attributes for a file.
854 * CODA_ZAPDIR -- flush the attributes for the dir and
855 * force a new lookup for all the children
859 * The next is a result of Venus detecting an inconsistent file.
860 * CODA_PURGEFID -- flush the attribute for the file
861 * purge it and its children from the dcache
863 * The last allows Venus to replace local fids with global ones
864 * during reintegration.
866 * CODA_REPLACE -- replace one CodaFid with another throughout the name cache */
868 int coda_downcall(int opcode
, union outputArgs
* out
, struct super_block
*sb
)
870 /* Handle invalidation requests. */
871 if ( !sb
|| !sb
->s_root
|| !sb
->s_root
->d_inode
)
877 coda_cache_clear_all(sb
);
878 shrink_dcache_sb(sb
);
879 coda_flag_inode(sb
->s_root
->d_inode
, C_FLUSH
);
883 case CODA_PURGEUSER
: {
884 coda_cache_clear_all(sb
);
890 struct CodaFid
*fid
= &out
->coda_zapdir
.CodaFid
;
892 inode
= coda_fid_to_inode(fid
, sb
);
894 coda_flag_inode_children(inode
, C_PURGE
);
895 coda_flag_inode(inode
, C_VATTR
);
902 case CODA_ZAPFILE
: {
904 struct CodaFid
*fid
= &out
->coda_zapfile
.CodaFid
;
905 inode
= coda_fid_to_inode(fid
, sb
);
907 coda_flag_inode(inode
, C_VATTR
);
913 case CODA_PURGEFID
: {
915 struct CodaFid
*fid
= &out
->coda_purgefid
.CodaFid
;
916 inode
= coda_fid_to_inode(fid
, sb
);
918 coda_flag_inode_children(inode
, C_PURGE
);
920 /* catch the dentries later if some are still busy */
921 coda_flag_inode(inode
, C_PURGE
);
922 d_prune_aliases(inode
);
929 case CODA_REPLACE
: {
931 struct CodaFid
*oldfid
= &out
->coda_replace
.OldFid
;
932 struct CodaFid
*newfid
= &out
->coda_replace
.NewFid
;
933 inode
= coda_fid_to_inode(oldfid
, sb
);
935 coda_replace_fid(inode
, oldfid
, newfid
);
This page took 0.051563 seconds and 4 git commands to generate.