Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+58 −63
Original line number Diff line number Diff line
@@ -693,21 +693,21 @@ static int coda_upcall(struct coda_sb_info *sbi,
{
	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);
		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;
@@ -720,7 +720,7 @@ static int coda_upcall(struct coda_sb_info *sbi,
	((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
@@ -735,7 +735,6 @@ 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) {
		out = (union outputArgs *)req->uc_data;
@@ -744,20 +743,25 @@ static int coda_upcall(struct coda_sb_info *sbi,
		*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;
	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));

	/* 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;
@@ -782,15 +786,6 @@ static int coda_upcall(struct coda_sb_info *sbi,
	/* 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:
	upc_free(req);