]> err.no Git - linux-2.6/commitdiff
coda: cleanup for upcall handling path
authorJan Harkes <jaharkes@cs.cmu.edu>
Thu, 19 Jul 2007 08:48:46 +0000 (01:48 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Thu, 19 Jul 2007 17:04:48 +0000 (10:04 -0700)
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>
fs/coda/upcall.c

index a44ca4155fd5aeb96403d189c6141a868c07d395..44332efa841171155afe21a4fd127a09102ffe47 100644 (file)
@@ -687,27 +687,27 @@ static inline void coda_waitfor_upcall(struct upc_req *vmp)
  * are all mapped to -EINTR, while showing a nice warning message. (jh)
  * 
  */
-static int coda_upcall(struct coda_sb_info *sbi, 
-               int inSize, int *outSize, 
-               union inputArgs *buffer) 
+static int coda_upcall(struct coda_sb_info *sbi,
+                      int inSize, int *outSize,
+                      union inputArgs *buffer)
 {
        struct venus_comm *vcommp;
        union outputArgs *out;
-       struct upc_req *req;
+       union inputArgs *sig_inputArgs;
+       struct upc_req *req, *sig_req;
        int error = 0;
 
        vcommp = sbi->sbi_vcomm;
-       if ( !vcommp->vc_inuse ) {
-               printk("No pseudo device in upcall comms at %p\n", vcommp);
-                return -ENXIO;
+       if (!vcommp->vc_inuse) {
+               printk(KERN_NOTICE "coda: Venus dead, not sending upcall\n");
+               return -ENXIO;
        }
 
        /* Format the request message. */
        req = upc_alloc();
-       if (!req) {
-               printk("Failed to allocate upc_req structure\n");
+       if (!req)
                return -ENOMEM;
-       }
+
        req->uc_data = (void *)buffer;
        req->uc_flags = 0;
        req->uc_inSize = inSize;
@@ -715,13 +715,13 @@ static int coda_upcall(struct coda_sb_info *sbi,
        req->uc_opcode = ((union inputArgs *)buffer)->ih.opcode;
        req->uc_unique = ++vcommp->vc_seq;
        init_waitqueue_head(&req->uc_sleep);
-       
+
        /* Fill in the common input args. */
        ((union inputArgs *)buffer)->ih.unique = req->uc_unique;
 
        /* Append msg to pending queue and poke Venus. */
-       list_add_tail(&(req->uc_chain), &vcommp->vc_pending);
-        
+       list_add_tail(&req->uc_chain, &vcommp->vc_pending);
+
        wake_up_interruptible(&vcommp->vc_waitq);
        /* We can be interrupted while we wait for Venus to process
         * our request.  If the interrupt occurs before Venus has read
@@ -735,64 +735,59 @@ static int coda_upcall(struct coda_sb_info *sbi,
        /* Go to sleep.  Wake up on signals only after the timeout. */
        coda_waitfor_upcall(req);
 
-       if (vcommp->vc_inuse) {      /* i.e. Venus is still alive */
-           /* Op went through, interrupt or not... */
-           if (req->uc_flags & REQ_WRITE) {
+       /* Op went through, interrupt or not... */
+       if (req->uc_flags & REQ_WRITE) {
                out = (union outputArgs *)req->uc_data;
                /* here we map positive Venus errors to kernel errors */
                error = -out->oh.result;
                *outSize = req->uc_outSize;
                goto exit;
-           }
-           if ( !(req->uc_flags & REQ_READ) && signal_pending(current)) { 
-               /* Interrupted before venus read it. */
-               list_del(&(req->uc_chain));
-               /* perhaps the best way to convince the app to
-                  give up? */
-               error = -EINTR;
+       }
+
+       error = -EINTR;
+       if ((req->uc_flags & REQ_ABORT) || !signal_pending(current)) {
+               printk(KERN_WARNING "coda: Unexpected interruption.\n");
                goto exit;
-           } 
-           if ( (req->uc_flags & REQ_READ) && signal_pending(current) ) {
-                   /* interrupted after Venus did its read, send signal */
-                   union inputArgs *sig_inputArgs;
-                   struct upc_req *sig_req;
-                   
-                   list_del(&(req->uc_chain));
-                   error = -ENOMEM;
-                   sig_req = upc_alloc();
-                   if (!sig_req) goto exit;
-
-                   CODA_ALLOC((sig_req->uc_data), char *, sizeof(struct coda_in_hdr));
-                   if (!sig_req->uc_data) {
-                       upc_free(sig_req);
-                       goto exit;
-                   }
-                   
-                   error = -EINTR;
-                   sig_inputArgs = (union inputArgs *)sig_req->uc_data;
-                   sig_inputArgs->ih.opcode = CODA_SIGNAL;
-                   sig_inputArgs->ih.unique = req->uc_unique;
-                   
-                   sig_req->uc_flags = REQ_ASYNC;
-                   sig_req->uc_opcode = sig_inputArgs->ih.opcode;
-                   sig_req->uc_unique = sig_inputArgs->ih.unique;
-                   sig_req->uc_inSize = sizeof(struct coda_in_hdr);
-                   sig_req->uc_outSize = sizeof(struct coda_in_hdr);
-                   
-                   /* insert at head of queue! */
-                   list_add(&(sig_req->uc_chain), &vcommp->vc_pending);
-                   wake_up_interruptible(&vcommp->vc_waitq);
-           } else {
-                   printk("Coda: Strange interruption..\n");
-                   error = -EINTR;
-           }
-       } else {        /* If venus died i.e. !VC_OPEN(vcommp) */
-               printk("coda_upcall: Venus dead on (op,un) (%d.%d) flags %d\n",
-                      req->uc_opcode, req->uc_unique, req->uc_flags);
-               error = -ENODEV;
        }
 
- exit:
+       list_del(&(req->uc_chain));
+
+       /* Interrupted before venus read it. */
+       if (!(req->uc_flags & REQ_READ))
+               goto exit;
+
+       /* Venus saw the upcall, make sure we can send interrupt signal */
+       if (!vcommp->vc_inuse) {
+               printk(KERN_INFO "coda: Venus dead, not sending signal.\n");
+               goto exit;
+       }
+
+       error = -ENOMEM;
+       sig_req = upc_alloc();
+       if (!sig_req) goto exit;
+
+       CODA_ALLOC((sig_req->uc_data), char *, sizeof(struct coda_in_hdr));
+       if (!sig_req->uc_data) {
+               upc_free(sig_req);
+               goto exit;
+       }
+
+       error = -EINTR;
+       sig_inputArgs = (union inputArgs *)sig_req->uc_data;
+       sig_inputArgs->ih.opcode = CODA_SIGNAL;
+       sig_inputArgs->ih.unique = req->uc_unique;
+
+       sig_req->uc_flags = REQ_ASYNC;
+       sig_req->uc_opcode = sig_inputArgs->ih.opcode;
+       sig_req->uc_unique = sig_inputArgs->ih.unique;
+       sig_req->uc_inSize = sizeof(struct coda_in_hdr);
+       sig_req->uc_outSize = sizeof(struct coda_in_hdr);
+
+       /* insert at head of queue! */
+       list_add(&(sig_req->uc_chain), &vcommp->vc_pending);
+       wake_up_interruptible(&vcommp->vc_waitq);
+
+exit:
        upc_free(req);
        return error;
 }