diff options
| -rw-r--r-- | fs/coda/upcall.c | 121 |
1 files changed, 58 insertions, 63 deletions
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c index a44ca4155fd5..44332efa8411 100644 --- a/fs/coda/upcall.c +++ b/fs/coda/upcall.c | |||
| @@ -687,27 +687,27 @@ static inline void coda_waitfor_upcall(struct upc_req *vmp) | |||
| 687 | * are all mapped to -EINTR, while showing a nice warning message. (jh) | 687 | * are all mapped to -EINTR, while showing a nice warning message. (jh) |
| 688 | * | 688 | * |
| 689 | */ | 689 | */ |
| 690 | static int coda_upcall(struct coda_sb_info *sbi, | 690 | static int coda_upcall(struct coda_sb_info *sbi, |
| 691 | int inSize, int *outSize, | 691 | int inSize, int *outSize, |
| 692 | union inputArgs *buffer) | 692 | union inputArgs *buffer) |
| 693 | { | 693 | { |
| 694 | struct venus_comm *vcommp; | 694 | struct venus_comm *vcommp; |
| 695 | union outputArgs *out; | 695 | union outputArgs *out; |
| 696 | struct upc_req *req; | 696 | union inputArgs *sig_inputArgs; |
| 697 | struct upc_req *req, *sig_req; | ||
| 697 | int error = 0; | 698 | int error = 0; |
| 698 | 699 | ||
| 699 | vcommp = sbi->sbi_vcomm; | 700 | vcommp = sbi->sbi_vcomm; |
| 700 | if ( !vcommp->vc_inuse ) { | 701 | if (!vcommp->vc_inuse) { |
| 701 | printk("No pseudo device in upcall comms at %p\n", vcommp); | 702 | printk(KERN_NOTICE "coda: Venus dead, not sending upcall\n"); |
| 702 | return -ENXIO; | 703 | return -ENXIO; |
| 703 | } | 704 | } |
| 704 | 705 | ||
| 705 | /* Format the request message. */ | 706 | /* Format the request message. */ |
| 706 | req = upc_alloc(); | 707 | req = upc_alloc(); |
| 707 | if (!req) { | 708 | if (!req) |
| 708 | printk("Failed to allocate upc_req structure\n"); | ||
| 709 | return -ENOMEM; | 709 | return -ENOMEM; |
| 710 | } | 710 | |
| 711 | req->uc_data = (void *)buffer; | 711 | req->uc_data = (void *)buffer; |
| 712 | req->uc_flags = 0; | 712 | req->uc_flags = 0; |
| 713 | req->uc_inSize = inSize; | 713 | req->uc_inSize = inSize; |
| @@ -715,13 +715,13 @@ static int coda_upcall(struct coda_sb_info *sbi, | |||
| 715 | req->uc_opcode = ((union inputArgs *)buffer)->ih.opcode; | 715 | req->uc_opcode = ((union inputArgs *)buffer)->ih.opcode; |
| 716 | req->uc_unique = ++vcommp->vc_seq; | 716 | req->uc_unique = ++vcommp->vc_seq; |
| 717 | init_waitqueue_head(&req->uc_sleep); | 717 | init_waitqueue_head(&req->uc_sleep); |
| 718 | 718 | ||
| 719 | /* Fill in the common input args. */ | 719 | /* Fill in the common input args. */ |
| 720 | ((union inputArgs *)buffer)->ih.unique = req->uc_unique; | 720 | ((union inputArgs *)buffer)->ih.unique = req->uc_unique; |
| 721 | 721 | ||
| 722 | /* Append msg to pending queue and poke Venus. */ | 722 | /* Append msg to pending queue and poke Venus. */ |
| 723 | list_add_tail(&(req->uc_chain), &vcommp->vc_pending); | 723 | list_add_tail(&req->uc_chain, &vcommp->vc_pending); |
| 724 | 724 | ||
| 725 | wake_up_interruptible(&vcommp->vc_waitq); | 725 | wake_up_interruptible(&vcommp->vc_waitq); |
| 726 | /* We can be interrupted while we wait for Venus to process | 726 | /* We can be interrupted while we wait for Venus to process |
| 727 | * our request. If the interrupt occurs before Venus has read | 727 | * our request. If the interrupt occurs before Venus has read |
| @@ -735,64 +735,59 @@ static int coda_upcall(struct coda_sb_info *sbi, | |||
| 735 | /* Go to sleep. Wake up on signals only after the timeout. */ | 735 | /* Go to sleep. Wake up on signals only after the timeout. */ |
| 736 | coda_waitfor_upcall(req); | 736 | coda_waitfor_upcall(req); |
| 737 | 737 | ||
| 738 | if (vcommp->vc_inuse) { /* i.e. Venus is still alive */ | 738 | /* Op went through, interrupt or not... */ |
| 739 | /* Op went through, interrupt or not... */ | 739 | if (req->uc_flags & REQ_WRITE) { |
| 740 | if (req->uc_flags & REQ_WRITE) { | ||
| 741 | out = (union outputArgs *)req->uc_data; | 740 | out = (union outputArgs *)req->uc_data; |
| 742 | /* here we map positive Venus errors to kernel errors */ | 741 | /* here we map positive Venus errors to kernel errors */ |
| 743 | error = -out->oh.result; | 742 | error = -out->oh.result; |
| 744 | *outSize = req->uc_outSize; | 743 | *outSize = req->uc_outSize; |
| 745 | goto exit; | 744 | goto exit; |
| 746 | } | 745 | } |
| 747 | if ( !(req->uc_flags & REQ_READ) && signal_pending(current)) { | 746 | |
| 748 | /* Interrupted before venus read it. */ | 747 | error = -EINTR; |
| 749 | list_del(&(req->uc_chain)); | 748 | if ((req->uc_flags & REQ_ABORT) || !signal_pending(current)) { |
| 750 | /* perhaps the best way to convince the app to | 749 | printk(KERN_WARNING "coda: Unexpected interruption.\n"); |
| 751 | give up? */ | ||
| 752 | error = -EINTR; | ||
| 753 | goto exit; | 750 | goto exit; |
| 754 | } | ||
| 755 | if ( (req->uc_flags & REQ_READ) && signal_pending(current) ) { | ||
| 756 | /* interrupted after Venus did its read, send signal */ | ||
| 757 | union inputArgs *sig_inputArgs; | ||
| 758 | struct upc_req *sig_req; | ||
| 759 | |||
| 760 | list_del(&(req->uc_chain)); | ||
| 761 | error = -ENOMEM; | ||
| 762 | sig_req = upc_alloc(); | ||
| 763 | if (!sig_req) goto exit; | ||
| 764 | |||
| 765 | CODA_ALLOC((sig_req->uc_data), char *, sizeof(struct coda_in_hdr)); | ||
| 766 | if (!sig_req->uc_data) { | ||
| 767 | upc_free(sig_req); | ||
| 768 | goto exit; | ||
| 769 | } | ||
| 770 | |||
| 771 | error = -EINTR; | ||
| 772 | sig_inputArgs = (union inputArgs *)sig_req->uc_data; | ||
| 773 | sig_inputArgs->ih.opcode = CODA_SIGNAL; | ||
| 774 | sig_inputArgs->ih.unique = req->uc_unique; | ||
| 775 | |||
| 776 | sig_req->uc_flags = REQ_ASYNC; | ||
| 777 | sig_req->uc_opcode = sig_inputArgs->ih.opcode; | ||
| 778 | sig_req->uc_unique = sig_inputArgs->ih.unique; | ||
| 779 | sig_req->uc_inSize = sizeof(struct coda_in_hdr); | ||
| 780 | sig_req->uc_outSize = sizeof(struct coda_in_hdr); | ||
| 781 | |||
| 782 | /* insert at head of queue! */ | ||
| 783 | list_add(&(sig_req->uc_chain), &vcommp->vc_pending); | ||
| 784 | wake_up_interruptible(&vcommp->vc_waitq); | ||
| 785 | } else { | ||
| 786 | printk("Coda: Strange interruption..\n"); | ||
| 787 | error = -EINTR; | ||
| 788 | } | ||
| 789 | } else { /* If venus died i.e. !VC_OPEN(vcommp) */ | ||
| 790 | printk("coda_upcall: Venus dead on (op,un) (%d.%d) flags %d\n", | ||
| 791 | req->uc_opcode, req->uc_unique, req->uc_flags); | ||
| 792 | error = -ENODEV; | ||
| 793 | } | 751 | } |
| 794 | 752 | ||
| 795 | exit: | 753 | list_del(&(req->uc_chain)); |
| 754 | |||
| 755 | /* Interrupted before venus read it. */ | ||
| 756 | if (!(req->uc_flags & REQ_READ)) | ||
| 757 | goto exit; | ||
| 758 | |||
| 759 | /* Venus saw the upcall, make sure we can send interrupt signal */ | ||
| 760 | if (!vcommp->vc_inuse) { | ||
| 761 | printk(KERN_INFO "coda: Venus dead, not sending signal.\n"); | ||
| 762 | goto exit; | ||
| 763 | } | ||
| 764 | |||
| 765 | error = -ENOMEM; | ||
| 766 | sig_req = upc_alloc(); | ||
| 767 | if (!sig_req) goto exit; | ||
| 768 | |||
| 769 | CODA_ALLOC((sig_req->uc_data), char *, sizeof(struct coda_in_hdr)); | ||
| 770 | if (!sig_req->uc_data) { | ||
| 771 | upc_free(sig_req); | ||
| 772 | goto exit; | ||
| 773 | } | ||
| 774 | |||
| 775 | error = -EINTR; | ||
| 776 | sig_inputArgs = (union inputArgs *)sig_req->uc_data; | ||
| 777 | sig_inputArgs->ih.opcode = CODA_SIGNAL; | ||
| 778 | sig_inputArgs->ih.unique = req->uc_unique; | ||
| 779 | |||
| 780 | sig_req->uc_flags = REQ_ASYNC; | ||
| 781 | sig_req->uc_opcode = sig_inputArgs->ih.opcode; | ||
| 782 | sig_req->uc_unique = sig_inputArgs->ih.unique; | ||
| 783 | sig_req->uc_inSize = sizeof(struct coda_in_hdr); | ||
| 784 | sig_req->uc_outSize = sizeof(struct coda_in_hdr); | ||
| 785 | |||
| 786 | /* insert at head of queue! */ | ||
| 787 | list_add(&(sig_req->uc_chain), &vcommp->vc_pending); | ||
| 788 | wake_up_interruptible(&vcommp->vc_waitq); | ||
| 789 | |||
| 790 | exit: | ||
| 796 | upc_free(req); | 791 | upc_free(req); |
| 797 | return error; | 792 | return error; |
| 798 | } | 793 | } |
