diff options
Diffstat (limited to 'fs/coda/upcall.c')
-rw-r--r-- | fs/coda/upcall.c | 454 |
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 | ||
43 | static int coda_upcall(struct coda_sb_info *mntinfo, int inSize, int *outSize, | 41 | static int coda_upcall(struct venus_comm *vc, int inSize, int *outSize, |
44 | union inputArgs *buffer); | 42 | union inputArgs *buffer); |
45 | 43 | ||
46 | static void *alloc_upcall(int opcode, int size) | 44 | static 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 | */ |
635 | static void block_signals(sigset_t *old) | ||
636 | { | ||
637 | spin_lock_irq(¤t->sighand->siglock); | ||
638 | *old = current->blocked; | ||
639 | |||
640 | sigfillset(¤t->blocked); | ||
641 | sigdelset(¤t->blocked, SIGKILL); | ||
642 | sigdelset(¤t->blocked, SIGSTOP); | ||
643 | sigdelset(¤t->blocked, SIGINT); | ||
644 | |||
645 | recalc_sigpending(); | ||
646 | spin_unlock_irq(¤t->sighand->siglock); | ||
647 | } | ||
648 | |||
649 | static void unblock_signals(sigset_t *old) | ||
650 | { | ||
651 | spin_lock_irq(¤t->sighand->siglock); | ||
652 | current->blocked = *old; | ||
653 | recalc_sigpending(); | ||
654 | spin_unlock_irq(¤t->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 | ||
644 | static inline void coda_waitfor_upcall(struct upc_req *vmp, | 668 | static 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 | */ |
695 | static int coda_upcall(struct coda_sb_info *sbi, | 723 | static 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 | |||
819 | exit: | ||
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 | ||
839 | int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb) | 858 | int 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 | ||