aboutsummaryrefslogtreecommitdiffstats
path: root/fs/coda/upcall.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/coda/upcall.c')
-rw-r--r--fs/coda/upcall.c454
1 files changed, 231 insertions, 223 deletions
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
index 5faacdb1a479..e4e766e5557c 100644
--- a/fs/coda/upcall.c
+++ b/fs/coda/upcall.c
@@ -35,12 +35,10 @@
35#include <linux/coda_psdev.h> 35#include <linux/coda_psdev.h>
36#include <linux/coda_fs_i.h> 36#include <linux/coda_fs_i.h>
37#include <linux/coda_cache.h> 37#include <linux/coda_cache.h>
38#include <linux/coda_proc.h>
39 38
40#define upc_alloc() kmalloc(sizeof(struct upc_req), GFP_KERNEL) 39#include "coda_int.h"
41#define upc_free(r) kfree(r)
42 40
43static int coda_upcall(struct coda_sb_info *mntinfo, int inSize, int *outSize, 41static int coda_upcall(struct venus_comm *vc, int inSize, int *outSize,
44 union inputArgs *buffer); 42 union inputArgs *buffer);
45 43
46static void *alloc_upcall(int opcode, int size) 44static void *alloc_upcall(int opcode, int size)
@@ -86,13 +84,9 @@ int venus_rootfid(struct super_block *sb, struct CodaFid *fidp)
86 insize = SIZE(root); 84 insize = SIZE(root);
87 UPARG(CODA_ROOT); 85 UPARG(CODA_ROOT);
88 86
89 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp); 87 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
90 88 if (!error)
91 if (error) {
92 printk("coda_get_rootfid: error %d\n", error);
93 } else {
94 *fidp = outp->coda_root.VFid; 89 *fidp = outp->coda_root.VFid;
95 }
96 90
97 CODA_FREE(inp, insize); 91 CODA_FREE(inp, insize);
98 return error; 92 return error;
@@ -109,9 +103,9 @@ int venus_getattr(struct super_block *sb, struct CodaFid *fid,
109 UPARG(CODA_GETATTR); 103 UPARG(CODA_GETATTR);
110 inp->coda_getattr.VFid = *fid; 104 inp->coda_getattr.VFid = *fid;
111 105
112 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp); 106 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
113 107 if (!error)
114 *attr = outp->coda_getattr.attr; 108 *attr = outp->coda_getattr.attr;
115 109
116 CODA_FREE(inp, insize); 110 CODA_FREE(inp, insize);
117 return error; 111 return error;
@@ -130,7 +124,7 @@ int venus_setattr(struct super_block *sb, struct CodaFid *fid,
130 inp->coda_setattr.VFid = *fid; 124 inp->coda_setattr.VFid = *fid;
131 inp->coda_setattr.attr = *vattr; 125 inp->coda_setattr.attr = *vattr;
132 126
133 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp); 127 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
134 128
135 CODA_FREE(inp, insize); 129 CODA_FREE(inp, insize);
136 return error; 130 return error;
@@ -156,10 +150,11 @@ int venus_lookup(struct super_block *sb, struct CodaFid *fid,
156 memcpy((char *)(inp) + offset, name, length); 150 memcpy((char *)(inp) + offset, name, length);
157 *((char *)inp + offset + length) = '\0'; 151 *((char *)inp + offset + length) = '\0';
158 152
159 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp); 153 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
160 154 if (!error) {
161 *resfid = outp->coda_lookup.VFid; 155 *resfid = outp->coda_lookup.VFid;
162 *type = outp->coda_lookup.vtype; 156 *type = outp->coda_lookup.vtype;
157 }
163 158
164 CODA_FREE(inp, insize); 159 CODA_FREE(inp, insize);
165 return error; 160 return error;
@@ -188,7 +183,7 @@ int venus_store(struct super_block *sb, struct CodaFid *fid, int flags,
188 inp->coda_store.VFid = *fid; 183 inp->coda_store.VFid = *fid;
189 inp->coda_store.flags = flags; 184 inp->coda_store.flags = flags;
190 185
191 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp); 186 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
192 187
193 CODA_FREE(inp, insize); 188 CODA_FREE(inp, insize);
194 return error; 189 return error;
@@ -206,7 +201,7 @@ int venus_release(struct super_block *sb, struct CodaFid *fid, int flags)
206 inp->coda_release.VFid = *fid; 201 inp->coda_release.VFid = *fid;
207 inp->coda_release.flags = flags; 202 inp->coda_release.flags = flags;
208 203
209 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp); 204 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
210 205
211 CODA_FREE(inp, insize); 206 CODA_FREE(inp, insize);
212 return error; 207 return error;
@@ -235,7 +230,7 @@ int venus_close(struct super_block *sb, struct CodaFid *fid, int flags,
235 inp->coda_close.VFid = *fid; 230 inp->coda_close.VFid = *fid;
236 inp->coda_close.flags = flags; 231 inp->coda_close.flags = flags;
237 232
238 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp); 233 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
239 234
240 CODA_FREE(inp, insize); 235 CODA_FREE(inp, insize);
241 return error; 236 return error;
@@ -251,12 +246,12 @@ int venus_open(struct super_block *sb, struct CodaFid *fid,
251 insize = SIZE(open_by_fd); 246 insize = SIZE(open_by_fd);
252 UPARG(CODA_OPEN_BY_FD); 247 UPARG(CODA_OPEN_BY_FD);
253 248
254 inp->coda_open.VFid = *fid; 249 inp->coda_open_by_fd.VFid = *fid;
255 inp->coda_open.flags = flags; 250 inp->coda_open_by_fd.flags = flags;
256 251
257 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp); 252 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
258 253 if (!error)
259 *fh = outp->coda_open_by_fd.fh; 254 *fh = outp->coda_open_by_fd.fh;
260 255
261 CODA_FREE(inp, insize); 256 CODA_FREE(inp, insize);
262 return error; 257 return error;
@@ -281,11 +276,12 @@ int venus_mkdir(struct super_block *sb, struct CodaFid *dirfid,
281 /* Venus must get null terminated string */ 276 /* Venus must get null terminated string */
282 memcpy((char *)(inp) + offset, name, length); 277 memcpy((char *)(inp) + offset, name, length);
283 *((char *)inp + offset + length) = '\0'; 278 *((char *)inp + offset + length) = '\0';
284
285 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
286 279
287 *attrs = outp->coda_mkdir.attr; 280 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
288 *newfid = outp->coda_mkdir.VFid; 281 if (!error) {
282 *attrs = outp->coda_mkdir.attr;
283 *newfid = outp->coda_mkdir.VFid;
284 }
289 285
290 CODA_FREE(inp, insize); 286 CODA_FREE(inp, insize);
291 return error; 287 return error;
@@ -323,7 +319,7 @@ int venus_rename(struct super_block *sb, struct CodaFid *old_fid,
323 memcpy((char *)(inp) + offset, new_name, new_length); 319 memcpy((char *)(inp) + offset, new_name, new_length);
324 *((char *)inp + offset + new_length) = '\0'; 320 *((char *)inp + offset + new_length) = '\0';
325 321
326 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp); 322 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
327 323
328 CODA_FREE(inp, insize); 324 CODA_FREE(inp, insize);
329 return error; 325 return error;
@@ -351,11 +347,12 @@ int venus_create(struct super_block *sb, struct CodaFid *dirfid,
351 /* Venus must get null terminated string */ 347 /* Venus must get null terminated string */
352 memcpy((char *)(inp) + offset, name, length); 348 memcpy((char *)(inp) + offset, name, length);
353 *((char *)inp + offset + length) = '\0'; 349 *((char *)inp + offset + length) = '\0';
354
355 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
356 350
357 *attrs = outp->coda_create.attr; 351 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
358 *newfid = outp->coda_create.VFid; 352 if (!error) {
353 *attrs = outp->coda_create.attr;
354 *newfid = outp->coda_create.VFid;
355 }
359 356
360 CODA_FREE(inp, insize); 357 CODA_FREE(inp, insize);
361 return error; 358 return error;
@@ -377,8 +374,8 @@ int venus_rmdir(struct super_block *sb, struct CodaFid *dirfid,
377 inp->coda_rmdir.name = offset; 374 inp->coda_rmdir.name = offset;
378 memcpy((char *)(inp) + offset, name, length); 375 memcpy((char *)(inp) + offset, name, length);
379 *((char *)inp + offset + length) = '\0'; 376 *((char *)inp + offset + length) = '\0';
380 377
381 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp); 378 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
382 379
383 CODA_FREE(inp, insize); 380 CODA_FREE(inp, insize);
384 return error; 381 return error;
@@ -399,8 +396,8 @@ int venus_remove(struct super_block *sb, struct CodaFid *dirfid,
399 inp->coda_remove.name = offset; 396 inp->coda_remove.name = offset;
400 memcpy((char *)(inp) + offset, name, length); 397 memcpy((char *)(inp) + offset, name, length);
401 *((char *)inp + offset + length) = '\0'; 398 *((char *)inp + offset + length) = '\0';
402 399
403 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp); 400 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
404 401
405 CODA_FREE(inp, insize); 402 CODA_FREE(inp, insize);
406 return error; 403 return error;
@@ -420,19 +417,18 @@ int venus_readlink(struct super_block *sb, struct CodaFid *fid,
420 UPARG(CODA_READLINK); 417 UPARG(CODA_READLINK);
421 418
422 inp->coda_readlink.VFid = *fid; 419 inp->coda_readlink.VFid = *fid;
423 420
424 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp); 421 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
425 422 if (!error) {
426 if (! error) { 423 retlen = outp->coda_readlink.count;
427 retlen = outp->coda_readlink.count;
428 if ( retlen > *length ) 424 if ( retlen > *length )
429 retlen = *length; 425 retlen = *length;
430 *length = retlen; 426 *length = retlen;
431 result = (char *)outp + (long)outp->coda_readlink.data; 427 result = (char *)outp + (long)outp->coda_readlink.data;
432 memcpy(buffer, result, retlen); 428 memcpy(buffer, result, retlen);
433 *(buffer + retlen) = '\0'; 429 *(buffer + retlen) = '\0';
434 } 430 }
435 431
436 CODA_FREE(inp, insize); 432 CODA_FREE(inp, insize);
437 return error; 433 return error;
438} 434}
@@ -458,8 +454,8 @@ int venus_link(struct super_block *sb, struct CodaFid *fid,
458 /* make sure strings are null terminated */ 454 /* make sure strings are null terminated */
459 memcpy((char *)(inp) + offset, name, len); 455 memcpy((char *)(inp) + offset, name, len);
460 *((char *)inp + offset + len) = '\0'; 456 *((char *)inp + offset + len) = '\0';
461 457
462 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp); 458 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
463 459
464 CODA_FREE(inp, insize); 460 CODA_FREE(inp, insize);
465 return error; 461 return error;
@@ -494,7 +490,7 @@ int venus_symlink(struct super_block *sb, struct CodaFid *fid,
494 memcpy((char *)(inp) + offset, name, len); 490 memcpy((char *)(inp) + offset, name, len);
495 *((char *)inp + offset + len) = '\0'; 491 *((char *)inp + offset + len) = '\0';
496 492
497 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp); 493 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
498 494
499 CODA_FREE(inp, insize); 495 CODA_FREE(inp, insize);
500 return error; 496 return error;
@@ -509,9 +505,9 @@ int venus_fsync(struct super_block *sb, struct CodaFid *fid)
509 insize=SIZE(fsync); 505 insize=SIZE(fsync);
510 UPARG(CODA_FSYNC); 506 UPARG(CODA_FSYNC);
511 507
512 inp->coda_fsync.VFid = *fid; 508 inp->coda_fsync.VFid = *fid;
513 error = coda_upcall(coda_sbp(sb), sizeof(union inputArgs), 509 error = coda_upcall(coda_vcp(sb), sizeof(union inputArgs),
514 &outsize, inp); 510 &outsize, inp);
515 511
516 CODA_FREE(inp, insize); 512 CODA_FREE(inp, insize);
517 return error; 513 return error;
@@ -529,7 +525,7 @@ int venus_access(struct super_block *sb, struct CodaFid *fid, int mask)
529 inp->coda_access.VFid = *fid; 525 inp->coda_access.VFid = *fid;
530 inp->coda_access.flags = mask; 526 inp->coda_access.flags = mask;
531 527
532 error = coda_upcall(coda_sbp(sb), insize, &outsize, inp); 528 error = coda_upcall(coda_vcp(sb), insize, &outsize, inp);
533 529
534 CODA_FREE(inp, insize); 530 CODA_FREE(inp, insize);
535 return error; 531 return error;
@@ -578,9 +574,9 @@ int venus_pioctl(struct super_block *sb, struct CodaFid *fid,
578 goto exit; 574 goto exit;
579 } 575 }
580 576
581 error = coda_upcall(coda_sbp(sb), SIZE(ioctl) + data->vi.in_size, 577 error = coda_upcall(coda_vcp(sb), SIZE(ioctl) + data->vi.in_size,
582 &outsize, inp); 578 &outsize, inp);
583 579
584 if (error) { 580 if (error) {
585 printk("coda_pioctl: Venus returns: %d for %s\n", 581 printk("coda_pioctl: Venus returns: %d for %s\n",
586 error, coda_f2s(fid)); 582 error, coda_f2s(fid));
@@ -620,16 +616,13 @@ int venus_statfs(struct dentry *dentry, struct kstatfs *sfs)
620 insize = max_t(unsigned int, INSIZE(statfs), OUTSIZE(statfs)); 616 insize = max_t(unsigned int, INSIZE(statfs), OUTSIZE(statfs));
621 UPARG(CODA_STATFS); 617 UPARG(CODA_STATFS);
622 618
623 error = coda_upcall(coda_sbp(dentry->d_sb), insize, &outsize, inp); 619 error = coda_upcall(coda_vcp(dentry->d_sb), insize, &outsize, inp);
624 620 if (!error) {
625 if (!error) {
626 sfs->f_blocks = outp->coda_statfs.stat.f_blocks; 621 sfs->f_blocks = outp->coda_statfs.stat.f_blocks;
627 sfs->f_bfree = outp->coda_statfs.stat.f_bfree; 622 sfs->f_bfree = outp->coda_statfs.stat.f_bfree;
628 sfs->f_bavail = outp->coda_statfs.stat.f_bavail; 623 sfs->f_bavail = outp->coda_statfs.stat.f_bavail;
629 sfs->f_files = outp->coda_statfs.stat.f_files; 624 sfs->f_files = outp->coda_statfs.stat.f_files;
630 sfs->f_ffree = outp->coda_statfs.stat.f_ffree; 625 sfs->f_ffree = outp->coda_statfs.stat.f_ffree;
631 } else {
632 printk("coda_statfs: Venus returns: %d\n", error);
633 } 626 }
634 627
635 CODA_FREE(inp, insize); 628 CODA_FREE(inp, insize);
@@ -638,96 +631,129 @@ int venus_statfs(struct dentry *dentry, struct kstatfs *sfs)
638 631
639/* 632/*
640 * coda_upcall and coda_downcall routines. 633 * coda_upcall and coda_downcall routines.
641 *
642 */ 634 */
635static void block_signals(sigset_t *old)
636{
637 spin_lock_irq(&current->sighand->siglock);
638 *old = current->blocked;
639
640 sigfillset(&current->blocked);
641 sigdelset(&current->blocked, SIGKILL);
642 sigdelset(&current->blocked, SIGSTOP);
643 sigdelset(&current->blocked, SIGINT);
644
645 recalc_sigpending();
646 spin_unlock_irq(&current->sighand->siglock);
647}
648
649static void unblock_signals(sigset_t *old)
650{
651 spin_lock_irq(&current->sighand->siglock);
652 current->blocked = *old;
653 recalc_sigpending();
654 spin_unlock_irq(&current->sighand->siglock);
655}
656
657/* Don't allow signals to interrupt the following upcalls before venus
658 * has seen them,
659 * - CODA_CLOSE or CODA_RELEASE upcall (to avoid reference count problems)
660 * - CODA_STORE (to avoid data loss)
661 */
662#define CODA_INTERRUPTIBLE(r) (!coda_hard && \
663 (((r)->uc_opcode != CODA_CLOSE && \
664 (r)->uc_opcode != CODA_STORE && \
665 (r)->uc_opcode != CODA_RELEASE) || \
666 (r)->uc_flags & REQ_READ))
643 667
644static inline void coda_waitfor_upcall(struct upc_req *vmp, 668static inline void coda_waitfor_upcall(struct upc_req *req)
645 struct venus_comm *vcommp)
646{ 669{
647 DECLARE_WAITQUEUE(wait, current); 670 DECLARE_WAITQUEUE(wait, current);
671 unsigned long timeout = jiffies + coda_timeout * HZ;
672 sigset_t old;
673 int blocked;
648 674
649 vmp->uc_posttime = jiffies; 675 block_signals(&old);
676 blocked = 1;
650 677
651 add_wait_queue(&vmp->uc_sleep, &wait); 678 add_wait_queue(&req->uc_sleep, &wait);
652 for (;;) { 679 for (;;) {
653 if ( !coda_hard && vmp->uc_opcode != CODA_CLOSE ) 680 if (CODA_INTERRUPTIBLE(req))
654 set_current_state(TASK_INTERRUPTIBLE); 681 set_current_state(TASK_INTERRUPTIBLE);
655 else 682 else
656 set_current_state(TASK_UNINTERRUPTIBLE); 683 set_current_state(TASK_UNINTERRUPTIBLE);
657 684
658 /* venus died */
659 if ( !vcommp->vc_inuse )
660 break;
661
662 /* got a reply */ 685 /* got a reply */
663 if ( vmp->uc_flags & ( REQ_WRITE | REQ_ABORT ) ) 686 if (req->uc_flags & (REQ_WRITE | REQ_ABORT))
664 break; 687 break;
665 688
666 if ( !coda_hard && vmp->uc_opcode != CODA_CLOSE && signal_pending(current) ) { 689 if (blocked && time_after(jiffies, timeout) &&
667 /* if this process really wants to die, let it go */ 690 CODA_INTERRUPTIBLE(req))
668 if ( sigismember(&(current->pending.signal), SIGKILL) || 691 {
669 sigismember(&(current->pending.signal), SIGINT) ) 692 unblock_signals(&old);
670 break; 693 blocked = 0;
671 /* signal is present: after timeout always return 694 }
672 really smart idea, probably useless ... */ 695
673 if ( jiffies - vmp->uc_posttime > coda_timeout * HZ ) 696 if (signal_pending(current)) {
674 break; 697 list_del(&req->uc_chain);
698 break;
675 } 699 }
676 schedule(); 700
701 if (blocked)
702 schedule_timeout(HZ);
703 else
704 schedule();
677 } 705 }
678 remove_wait_queue(&vmp->uc_sleep, &wait); 706 if (blocked)
679 set_current_state(TASK_RUNNING); 707 unblock_signals(&old);
680 708
681 return; 709 remove_wait_queue(&req->uc_sleep, &wait);
710 set_current_state(TASK_RUNNING);
682} 711}
683 712
684 713
685/* 714/*
686 * coda_upcall will return an error in the case of 715 * coda_upcall will return an error in the case of
687 * failed communication with Venus _or_ will peek at Venus 716 * failed communication with Venus _or_ will peek at Venus
688 * reply and return Venus' error. 717 * reply and return Venus' error.
689 * 718 *
690 * As venus has 2 types of errors, normal errors (positive) and internal 719 * As venus has 2 types of errors, normal errors (positive) and internal
691 * errors (negative), normal errors are negated, while internal errors 720 * errors (negative), normal errors are negated, while internal errors
692 * are all mapped to -EINTR, while showing a nice warning message. (jh) 721 * are all mapped to -EINTR, while showing a nice warning message. (jh)
693 *
694 */ 722 */
695static int coda_upcall(struct coda_sb_info *sbi, 723static int coda_upcall(struct venus_comm *vcp,
696 int inSize, int *outSize, 724 int inSize, int *outSize,
697 union inputArgs *buffer) 725 union inputArgs *buffer)
698{ 726{
699 struct venus_comm *vcommp;
700 union outputArgs *out; 727 union outputArgs *out;
701 struct upc_req *req; 728 union inputArgs *sig_inputArgs;
729 struct upc_req *req, *sig_req;
702 int error = 0; 730 int error = 0;
703 731
704 vcommp = sbi->sbi_vcomm; 732 if (!vcp->vc_inuse) {
705 if ( !vcommp->vc_inuse ) { 733 printk(KERN_NOTICE "coda: Venus dead, not sending upcall\n");
706 printk("No pseudo device in upcall comms at %p\n", vcommp); 734 return -ENXIO;
707 return -ENXIO;
708 } 735 }
709 736
710 /* Format the request message. */ 737 /* Format the request message. */
711 req = upc_alloc(); 738 req = kmalloc(sizeof(struct upc_req), GFP_KERNEL);
712 if (!req) { 739 if (!req)
713 printk("Failed to allocate upc_req structure\n");
714 return -ENOMEM; 740 return -ENOMEM;
715 } 741
716 req->uc_data = (void *)buffer; 742 req->uc_data = (void *)buffer;
717 req->uc_flags = 0; 743 req->uc_flags = 0;
718 req->uc_inSize = inSize; 744 req->uc_inSize = inSize;
719 req->uc_outSize = *outSize ? *outSize : inSize; 745 req->uc_outSize = *outSize ? *outSize : inSize;
720 req->uc_opcode = ((union inputArgs *)buffer)->ih.opcode; 746 req->uc_opcode = ((union inputArgs *)buffer)->ih.opcode;
721 req->uc_unique = ++vcommp->vc_seq; 747 req->uc_unique = ++vcp->vc_seq;
722 init_waitqueue_head(&req->uc_sleep); 748 init_waitqueue_head(&req->uc_sleep);
723 749
724 /* Fill in the common input args. */ 750 /* Fill in the common input args. */
725 ((union inputArgs *)buffer)->ih.unique = req->uc_unique; 751 ((union inputArgs *)buffer)->ih.unique = req->uc_unique;
726 752
727 /* Append msg to pending queue and poke Venus. */ 753 /* Append msg to pending queue and poke Venus. */
728 list_add_tail(&(req->uc_chain), &vcommp->vc_pending); 754 list_add_tail(&req->uc_chain, &vcp->vc_pending);
729 755
730 wake_up_interruptible(&vcommp->vc_waitq); 756 wake_up_interruptible(&vcp->vc_waitq);
731 /* We can be interrupted while we wait for Venus to process 757 /* We can be interrupted while we wait for Venus to process
732 * our request. If the interrupt occurs before Venus has read 758 * our request. If the interrupt occurs before Venus has read
733 * the request, we dequeue and return. If it occurs after the 759 * the request, we dequeue and return. If it occurs after the
@@ -738,67 +764,60 @@ static int coda_upcall(struct coda_sb_info *sbi,
738 * ENODEV. */ 764 * ENODEV. */
739 765
740 /* Go to sleep. Wake up on signals only after the timeout. */ 766 /* Go to sleep. Wake up on signals only after the timeout. */
741 coda_waitfor_upcall(req, vcommp); 767 coda_waitfor_upcall(req);
742 768
743 if (vcommp->vc_inuse) { /* i.e. Venus is still alive */ 769 /* Op went through, interrupt or not... */
744 /* Op went through, interrupt or not... */ 770 if (req->uc_flags & REQ_WRITE) {
745 if (req->uc_flags & REQ_WRITE) {
746 out = (union outputArgs *)req->uc_data; 771 out = (union outputArgs *)req->uc_data;
747 /* here we map positive Venus errors to kernel errors */ 772 /* here we map positive Venus errors to kernel errors */
748 error = -out->oh.result; 773 error = -out->oh.result;
749 *outSize = req->uc_outSize; 774 *outSize = req->uc_outSize;
750 goto exit; 775 goto exit;
751 } 776 }
752 if ( !(req->uc_flags & REQ_READ) && signal_pending(current)) { 777
753 /* Interrupted before venus read it. */ 778 error = -EINTR;
754 list_del(&(req->uc_chain)); 779 if ((req->uc_flags & REQ_ABORT) || !signal_pending(current)) {
755 /* perhaps the best way to convince the app to 780 printk(KERN_WARNING "coda: Unexpected interruption.\n");
756 give up? */
757 error = -EINTR;
758 goto exit; 781 goto exit;
759 }
760 if ( (req->uc_flags & REQ_READ) && signal_pending(current) ) {
761 /* interrupted after Venus did its read, send signal */
762 union inputArgs *sig_inputArgs;
763 struct upc_req *sig_req;
764
765 list_del(&(req->uc_chain));
766 error = -ENOMEM;
767 sig_req = upc_alloc();
768 if (!sig_req) goto exit;
769
770 CODA_ALLOC((sig_req->uc_data), char *, sizeof(struct coda_in_hdr));
771 if (!sig_req->uc_data) {
772 upc_free(sig_req);
773 goto exit;
774 }
775
776 error = -EINTR;
777 sig_inputArgs = (union inputArgs *)sig_req->uc_data;
778 sig_inputArgs->ih.opcode = CODA_SIGNAL;
779 sig_inputArgs->ih.unique = req->uc_unique;
780
781 sig_req->uc_flags = REQ_ASYNC;
782 sig_req->uc_opcode = sig_inputArgs->ih.opcode;
783 sig_req->uc_unique = sig_inputArgs->ih.unique;
784 sig_req->uc_inSize = sizeof(struct coda_in_hdr);
785 sig_req->uc_outSize = sizeof(struct coda_in_hdr);
786
787 /* insert at head of queue! */
788 list_add(&(sig_req->uc_chain), &vcommp->vc_pending);
789 wake_up_interruptible(&vcommp->vc_waitq);
790 } else {
791 printk("Coda: Strange interruption..\n");
792 error = -EINTR;
793 }
794 } else { /* If venus died i.e. !VC_OPEN(vcommp) */
795 printk("coda_upcall: Venus dead on (op,un) (%d.%d) flags %d\n",
796 req->uc_opcode, req->uc_unique, req->uc_flags);
797 error = -ENODEV;
798 } 782 }
799 783
800 exit: 784 /* Interrupted before venus read it. */
801 upc_free(req); 785 if (!(req->uc_flags & REQ_READ))
786 goto exit;
787
788 /* Venus saw the upcall, make sure we can send interrupt signal */
789 if (!vcp->vc_inuse) {
790 printk(KERN_INFO "coda: Venus dead, not sending signal.\n");
791 goto exit;
792 }
793
794 error = -ENOMEM;
795 sig_req = kmalloc(sizeof(struct upc_req), GFP_KERNEL);
796 if (!sig_req) goto exit;
797
798 CODA_ALLOC((sig_req->uc_data), char *, sizeof(struct coda_in_hdr));
799 if (!sig_req->uc_data) {
800 kfree(sig_req);
801 goto exit;
802 }
803
804 error = -EINTR;
805 sig_inputArgs = (union inputArgs *)sig_req->uc_data;
806 sig_inputArgs->ih.opcode = CODA_SIGNAL;
807 sig_inputArgs->ih.unique = req->uc_unique;
808
809 sig_req->uc_flags = REQ_ASYNC;
810 sig_req->uc_opcode = sig_inputArgs->ih.opcode;
811 sig_req->uc_unique = sig_inputArgs->ih.unique;
812 sig_req->uc_inSize = sizeof(struct coda_in_hdr);
813 sig_req->uc_outSize = sizeof(struct coda_in_hdr);
814
815 /* insert at head of queue! */
816 list_add(&(sig_req->uc_chain), &vcp->vc_pending);
817 wake_up_interruptible(&vcp->vc_waitq);
818
819exit:
820 kfree(req);
802 return error; 821 return error;
803} 822}
804 823
@@ -838,77 +857,66 @@ static int coda_upcall(struct coda_sb_info *sbi,
838 857
839int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb) 858int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
840{ 859{
860 struct inode *inode = NULL;
861 struct CodaFid *fid, *newfid;
862
841 /* Handle invalidation requests. */ 863 /* Handle invalidation requests. */
842 if ( !sb || !sb->s_root || !sb->s_root->d_inode) 864 if ( !sb || !sb->s_root)
843 return 0; 865 return 0;
844 866
845 switch (opcode) { 867 switch (opcode) {
846 868 case CODA_FLUSH:
847 case CODA_FLUSH : { 869 coda_cache_clear_all(sb);
848 coda_cache_clear_all(sb); 870 shrink_dcache_sb(sb);
849 shrink_dcache_sb(sb); 871 if (sb->s_root->d_inode)
850 coda_flag_inode(sb->s_root->d_inode, C_FLUSH); 872 coda_flag_inode(sb->s_root->d_inode, C_FLUSH);
851 return(0); 873 break;
852 } 874
853 875 case CODA_PURGEUSER:
854 case CODA_PURGEUSER : { 876 coda_cache_clear_all(sb);
855 coda_cache_clear_all(sb); 877 break;
856 return(0); 878
857 } 879 case CODA_ZAPDIR:
858 880 fid = &out->coda_zapdir.CodaFid;
859 case CODA_ZAPDIR : { 881 inode = coda_fid_to_inode(fid, sb);
860 struct inode *inode; 882 if (inode) {
861 struct CodaFid *fid = &out->coda_zapdir.CodaFid; 883 coda_flag_inode_children(inode, C_PURGE);
862 884 coda_flag_inode(inode, C_VATTR);
863 inode = coda_fid_to_inode(fid, sb); 885 }
864 if (inode) { 886 break;
865 coda_flag_inode_children(inode, C_PURGE); 887
866 coda_flag_inode(inode, C_VATTR); 888 case CODA_ZAPFILE:
867 iput(inode); 889 fid = &out->coda_zapfile.CodaFid;
868 } 890 inode = coda_fid_to_inode(fid, sb);
869 891 if (inode)
870 return(0); 892 coda_flag_inode(inode, C_VATTR);
871 } 893 break;
872 894
873 case CODA_ZAPFILE : { 895 case CODA_PURGEFID:
874 struct inode *inode; 896 fid = &out->coda_purgefid.CodaFid;
875 struct CodaFid *fid = &out->coda_zapfile.CodaFid; 897 inode = coda_fid_to_inode(fid, sb);
876 inode = coda_fid_to_inode(fid, sb); 898 if (inode) {
877 if ( inode ) {
878 coda_flag_inode(inode, C_VATTR);
879 iput(inode);
880 }
881 return 0;
882 }
883
884 case CODA_PURGEFID : {
885 struct inode *inode;
886 struct CodaFid *fid = &out->coda_purgefid.CodaFid;
887 inode = coda_fid_to_inode(fid, sb);
888 if ( inode ) {
889 coda_flag_inode_children(inode, C_PURGE); 899 coda_flag_inode_children(inode, C_PURGE);
890 900
891 /* catch the dentries later if some are still busy */ 901 /* catch the dentries later if some are still busy */
892 coda_flag_inode(inode, C_PURGE); 902 coda_flag_inode(inode, C_PURGE);
893 d_prune_aliases(inode); 903 d_prune_aliases(inode);
894 904
895 iput(inode); 905 }
896 } 906 break;
897 return 0; 907
898 } 908 case CODA_REPLACE:
899 909 fid = &out->coda_replace.OldFid;
900 case CODA_REPLACE : { 910 newfid = &out->coda_replace.NewFid;
901 struct inode *inode; 911 inode = coda_fid_to_inode(fid, sb);
902 struct CodaFid *oldfid = &out->coda_replace.OldFid; 912 if (inode)
903 struct CodaFid *newfid = &out->coda_replace.NewFid; 913 coda_replace_fid(inode, fid, newfid);
904 inode = coda_fid_to_inode(oldfid, sb); 914 break;
905 if ( inode ) { 915 }
906 coda_replace_fid(inode, oldfid, newfid); 916
907 iput(inode); 917 if (inode)
908 } 918 iput(inode);
909 return 0; 919
910 } 920 return 0;
911 }
912 return 0;
913} 921}
914 922