Commit fe71b5f3 authored by Jan Harkes's avatar Jan Harkes Committed by Linus Torvalds

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: default avatarJan Harkes <jaharkes@cs.cmu.edu>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 87065519
...@@ -693,21 +693,21 @@ static int coda_upcall(struct coda_sb_info *sbi, ...@@ -693,21 +693,21 @@ static int coda_upcall(struct coda_sb_info *sbi,
{ {
struct venus_comm *vcommp; struct venus_comm *vcommp;
union outputArgs *out; union outputArgs *out;
struct upc_req *req; union inputArgs *sig_inputArgs;
struct upc_req *req, *sig_req;
int error = 0; int error = 0;
vcommp = sbi->sbi_vcomm; vcommp = sbi->sbi_vcomm;
if ( !vcommp->vc_inuse ) { if (!vcommp->vc_inuse) {
printk("No pseudo device in upcall comms at %p\n", vcommp); printk(KERN_NOTICE "coda: Venus dead, not sending upcall\n");
return -ENXIO; return -ENXIO;
} }
/* Format the request message. */ /* Format the request message. */
req = upc_alloc(); req = upc_alloc();
if (!req) { if (!req)
printk("Failed to allocate upc_req structure\n");
return -ENOMEM; return -ENOMEM;
}
req->uc_data = (void *)buffer; req->uc_data = (void *)buffer;
req->uc_flags = 0; req->uc_flags = 0;
req->uc_inSize = inSize; req->uc_inSize = inSize;
...@@ -720,7 +720,7 @@ static int coda_upcall(struct coda_sb_info *sbi, ...@@ -720,7 +720,7 @@ static int coda_upcall(struct coda_sb_info *sbi,
((union inputArgs *)buffer)->ih.unique = req->uc_unique; ((union inputArgs *)buffer)->ih.unique = req->uc_unique;
/* Append msg to pending queue and poke Venus. */ /* 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); wake_up_interruptible(&vcommp->vc_waitq);
/* We can be interrupted while we wait for Venus to process /* We can be interrupted while we wait for Venus to process
...@@ -735,7 +735,6 @@ static int coda_upcall(struct coda_sb_info *sbi, ...@@ -735,7 +735,6 @@ static int coda_upcall(struct coda_sb_info *sbi,
/* Go to sleep. Wake up on signals only after the timeout. */ /* Go to sleep. Wake up on signals only after the timeout. */
coda_waitfor_upcall(req); coda_waitfor_upcall(req);
if (vcommp->vc_inuse) { /* i.e. Venus is still alive */
/* Op went through, interrupt or not... */ /* Op went through, interrupt or not... */
if (req->uc_flags & REQ_WRITE) { if (req->uc_flags & REQ_WRITE) {
out = (union outputArgs *)req->uc_data; out = (union outputArgs *)req->uc_data;
...@@ -744,20 +743,25 @@ static int coda_upcall(struct coda_sb_info *sbi, ...@@ -744,20 +743,25 @@ static int coda_upcall(struct coda_sb_info *sbi,
*outSize = req->uc_outSize; *outSize = req->uc_outSize;
goto exit; 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; 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)); 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; error = -ENOMEM;
sig_req = upc_alloc(); sig_req = upc_alloc();
if (!sig_req) goto exit; if (!sig_req) goto exit;
...@@ -782,17 +786,8 @@ static int coda_upcall(struct coda_sb_info *sbi, ...@@ -782,17 +786,8 @@ static int coda_upcall(struct coda_sb_info *sbi,
/* insert at head of queue! */ /* insert at head of queue! */
list_add(&(sig_req->uc_chain), &vcommp->vc_pending); list_add(&(sig_req->uc_chain), &vcommp->vc_pending);
wake_up_interruptible(&vcommp->vc_waitq); 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: exit:
upc_free(req); upc_free(req);
return error; return error;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment