aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libiscsi.c
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2006-05-30 01:37:28 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-06-05 19:12:25 -0400
commit3219e5294150aee7d389e19029f49b44fb6b5c9f (patch)
tree44236fd9f2eb40d5622cadb126e9f2672b129486 /drivers/scsi/libiscsi.c
parent040515f53c09047c76ad074dc6a280984dc84b04 (diff)
[SCSI] iscsi: fix writepsace race
We can race and misset the suspend bit if iscsi_write_space is called then iscsi_send returns with a failure indicating there is no space. To handle this this patch returns a error upwards allowing xmitworker to decide if we need to try and transmit again. For the no write space case xmitworker will not retry, and instead let iscsi_write_space queue it back up if needed (this relies on the work queue code to properly requeue us if needed). Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/libiscsi.c')
-rw-r--r--drivers/scsi/libiscsi.c31
1 files changed, 19 insertions, 12 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 256b87a85978..2673a11a9495 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -513,10 +513,11 @@ EXPORT_SYMBOL_GPL(iscsi_conn_failure);
513static int iscsi_data_xmit(struct iscsi_conn *conn) 513static int iscsi_data_xmit(struct iscsi_conn *conn)
514{ 514{
515 struct iscsi_transport *tt; 515 struct iscsi_transport *tt;
516 int rc = 0;
516 517
517 if (unlikely(conn->suspend_tx)) { 518 if (unlikely(conn->suspend_tx)) {
518 debug_scsi("conn %d Tx suspended!\n", conn->id); 519 debug_scsi("conn %d Tx suspended!\n", conn->id);
519 return 0; 520 return -ENODATA;
520 } 521 }
521 tt = conn->session->tt; 522 tt = conn->session->tt;
522 523
@@ -536,13 +537,15 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
536 BUG_ON(conn->ctask && conn->mtask); 537 BUG_ON(conn->ctask && conn->mtask);
537 538
538 if (conn->ctask) { 539 if (conn->ctask) {
539 if (tt->xmit_cmd_task(conn, conn->ctask)) 540 rc = tt->xmit_cmd_task(conn, conn->ctask);
541 if (rc)
540 goto again; 542 goto again;
541 /* done with this in-progress ctask */ 543 /* done with this in-progress ctask */
542 conn->ctask = NULL; 544 conn->ctask = NULL;
543 } 545 }
544 if (conn->mtask) { 546 if (conn->mtask) {
545 if (tt->xmit_mgmt_task(conn, conn->mtask)) 547 rc = tt->xmit_mgmt_task(conn, conn->mtask);
548 if (rc)
546 goto again; 549 goto again;
547 /* done with this in-progress mtask */ 550 /* done with this in-progress mtask */
548 conn->mtask = NULL; 551 conn->mtask = NULL;
@@ -556,7 +559,8 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
556 list_add_tail(&conn->mtask->running, 559 list_add_tail(&conn->mtask->running,
557 &conn->mgmt_run_list); 560 &conn->mgmt_run_list);
558 spin_unlock_bh(&conn->session->lock); 561 spin_unlock_bh(&conn->session->lock);
559 if (tt->xmit_mgmt_task(conn, conn->mtask)) 562 rc = tt->xmit_mgmt_task(conn, conn->mtask);
563 if (rc)
560 goto again; 564 goto again;
561 } 565 }
562 /* done with this mtask */ 566 /* done with this mtask */
@@ -574,7 +578,8 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
574 if (list_empty(&conn->ctask->running)) 578 if (list_empty(&conn->ctask->running))
575 list_add_tail(&conn->ctask->running, &conn->run_list); 579 list_add_tail(&conn->ctask->running, &conn->run_list);
576 spin_unlock_bh(&conn->session->lock); 580 spin_unlock_bh(&conn->session->lock);
577 if (tt->xmit_cmd_task(conn, conn->ctask)) 581 rc = tt->xmit_cmd_task(conn, conn->ctask);
582 if (rc)
578 goto again; 583 goto again;
579 } 584 }
580 /* done with this ctask */ 585 /* done with this ctask */
@@ -588,32 +593,34 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
588 list_add_tail(&conn->mtask->running, 593 list_add_tail(&conn->mtask->running,
589 &conn->mgmt_run_list); 594 &conn->mgmt_run_list);
590 spin_unlock_bh(&conn->session->lock); 595 spin_unlock_bh(&conn->session->lock);
591 if (tt->xmit_mgmt_task(conn, conn->mtask)) 596 rc = tt->xmit_mgmt_task(conn, conn->mtask);
597 if (rc)
592 goto again; 598 goto again;
593 } 599 }
594 /* done with this mtask */ 600 /* done with this mtask */
595 conn->mtask = NULL; 601 conn->mtask = NULL;
596 } 602 }
597 603
598 return 0; 604 return -ENODATA;
599 605
600again: 606again:
601 if (unlikely(conn->suspend_tx)) 607 if (unlikely(conn->suspend_tx))
602 return 0; 608 return -ENODATA;
603 609
604 return -EAGAIN; 610 return rc;
605} 611}
606 612
607static void iscsi_xmitworker(void *data) 613static void iscsi_xmitworker(void *data)
608{ 614{
609 struct iscsi_conn *conn = data; 615 struct iscsi_conn *conn = data;
610 616 int rc;
611 /* 617 /*
612 * serialize Xmit worker on a per-connection basis. 618 * serialize Xmit worker on a per-connection basis.
613 */ 619 */
614 mutex_lock(&conn->xmitmutex); 620 mutex_lock(&conn->xmitmutex);
615 if (iscsi_data_xmit(conn)) 621 do {
616 scsi_queue_work(conn->session->host, &conn->xmitwork); 622 rc = iscsi_data_xmit(conn);
623 } while (rc >= 0 || rc == -EAGAIN);
617 mutex_unlock(&conn->xmitmutex); 624 mutex_unlock(&conn->xmitmutex);
618} 625}
619 626