aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJan Harkes <jaharkes@cs.cmu.edu>2007-07-19 04:48:46 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-19 13:04:48 -0400
commitfe71b5f3871af2c281a08acd4bedd2da25e46bc3 (patch)
treecdd4eafff85d86d5495eb4f7c51cfbdf689ec78a /fs
parent87065519633af79e0577e32a58dcd9cf3c45a8a0 (diff)
coda: cleanup for upcall handling path
Make the code that processes upcall responses more straightforward, uncovered at least one bad assumption. We trusted that vc_inuse would be 0 when upcalls are aborted, however the device may have been reopened. Signed-off-by: Jan Harkes <jaharkes@cs.cmu.edu> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/coda/upcall.c121
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 */
690static int coda_upcall(struct coda_sb_info *sbi, 690static 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
790exit:
796 upc_free(req); 791 upc_free(req);
797 return error; 792 return error;
798} 793}