Skip to contentSkip to conversation

Correctly release and allocate a new request upon retries

PATCH In review Alan D. Brunelle 3 participants 3 messages Dec 8, 2008 – Dec 9, 2008

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Correctly release and allocate a new request upon retries

Commands needing to be retried require a complete re-initialization.

The test-unit-ready portion of this patch was causing boots to fail on my test machine (as in http://lkml.org/lkml/2008/12/5/161). With this patch in place, the system is booting reliably.

Mike Anderson found the same problem in the hp_hw_start_stop code, and I applied the same solution in cdrom_read_cdda_bpc.

Cc Jens Axboe <[email protected]>
Cc Mike Anderson <[email protected]>
---
 drivers/cdrom/cdrom.c                       |   16 ++++++++++------
 drivers/scsi/device_handler/scsi_dh_hp_sw.c |   12 ++++++++----
 2 files changed, 18 insertions(+), 10 deletions(-)
drivers/cdrom/cdrom.c +10 -6
index d16b024..7d2e91c 100644
@@ -2081,10 +2081,6 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
 	if (!q)
 		return -ENXIO;
 
-	rq = blk_get_request(q, READ, GFP_KERNEL);
-	if (!rq)
-		return -ENOMEM;
-
 	cdi->last_sense = 0;
 
 	while (nframes) {
@@ -2096,9 +2092,17 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
 
 		len = nr * CD_FRAMESIZE_RAW;
 
+		rq = blk_get_request(q, READ, GFP_KERNEL);
+		if (!rq) {
+			ret = -ENOMEM;
+			break;
+		}
+
 		ret = blk_rq_map_user(q, rq, NULL, ubuf, len, GFP_KERNEL);
-		if (ret)
+		if (ret) {
+			blk_put_request(rq);
 			break;
+		}
 
 		rq->cmd[0] = GPCMD_READ_CD;
 		rq->cmd[1] = 1 << 2;
@@ -2124,6 +2128,7 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
 
 		if (blk_rq_unmap_user(bio))
 			ret = -EFAULT;
+		blk_put_request(rq);
 
 		if (ret)
 			break;
@@ -2133,7 +2138,6 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
 		ubuf += len;
 	}
 
-	blk_put_request(rq);
 	return ret;
 }
 
drivers/scsi/device_handler/scsi_dh_hp_sw.c +8 -4
index 9aec4ca..f7da753 100644
@@ -107,6 +107,7 @@ static int hp_sw_tur(struct scsi_device *sdev, struct hp_sw_dh_data *h)
 	struct request *req;
 	int ret;
 
+retry:
 	req = blk_get_request(sdev->request_queue, WRITE, GFP_NOIO);
 	if (!req)
 		return SCSI_DH_RES_TEMP_UNAVAIL;
@@ -121,7 +122,6 @@ static int hp_sw_tur(struct scsi_device *sdev, struct hp_sw_dh_data *h)
 	memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE);
 	req->sense_len = 0;
 
-retry:
 	ret = blk_execute_rq(req->q, NULL, req, 1);
 	if (ret == -EIO) {
 		if (req->sense_len > 0) {
@@ -136,8 +136,10 @@ retry:
 		h->path_state = HP_SW_PATH_ACTIVE;
 		ret = SCSI_DH_OK;
 	}
-	if (ret == SCSI_DH_IMM_RETRY)
+	if (ret == SCSI_DH_IMM_RETRY) {
+		blk_put_request(req);
 		goto retry;
+	}
 	if (ret == SCSI_DH_DEV_OFFLINED) {
 		h->path_state = HP_SW_PATH_PASSIVE;
 		ret = SCSI_DH_OK;
@@ -200,6 +202,7 @@ static int hp_sw_start_stop(struct scsi_device *sdev, struct hp_sw_dh_data *h)
 	struct request *req;
 	int ret, retry;
 
+retry:
 	req = blk_get_request(sdev->request_queue, WRITE, GFP_NOIO);
 	if (!req)
 		return SCSI_DH_RES_TEMP_UNAVAIL;
@@ -216,7 +219,6 @@ static int hp_sw_start_stop(struct scsi_device *sdev, struct hp_sw_dh_data *h)
 	req->sense_len = 0;
 	retry = h->retries;
 
-retry:
 	ret = blk_execute_rq(req->q, NULL, req, 1);
 	if (ret == -EIO) {
 		if (req->sense_len > 0) {
@@ -231,8 +233,10 @@ retry:
 		ret = SCSI_DH_OK;
 
 	if (ret == SCSI_DH_RETRY) {
-		if (--retry)
+		if (--retry) {
+			blk_put_request(req);
 			goto retry;
+		}
 		ret = SCSI_DH_IO;
 	}
 
Signature · 1 line
1.5.6.3
#1 lore raw
Quoted 8 lines · Alan D. Brunelle

Commands needing to be retried require a complete re-initialization.

The test-unit-ready portion of this patch was causing boots to fail on my test machine (as in http://lkml.org/lkml/2008/12/5/161). With this patch in place, the system is booting reliably.

Mike Anderson found the same problem in the hp_hw_start_stop code, and I applied the same solution in cdrom_read_cdda_bpc.

Thanks Alan, applied for 2.6.28.

Signature · 1 line
Jens Axboe
#2 lore raw
In reply to Alan D. Brunelle
Quoted 66 lines · On Mon, 08 Dec 2008 09:24:05 -0500 "Alan D. Brunelle" <[email protected]>…

Commands needing to be retried require a complete re-initialization.

The test-unit-ready portion of this patch was causing boots to fail on my test machine (as in http://lkml.org/lkml/2008/12/5/161). With this patch in place, the system is booting reliably.

Mike Anderson found the same problem in the hp_hw_start_stop code, and I applied the same solution in cdrom_read_cdda_bpc.

Cc Jens Axboe <[email protected]>
Cc Mike Anderson <[email protected]>
---
 drivers/cdrom/cdrom.c                       |   16 ++++++++++------
 drivers/scsi/device_handler/scsi_dh_hp_sw.c |   12 ++++++++----
 2 files changed, 18 insertions(+), 10 deletions(-)
drivers/scsi/device_handler/scsi_dh_hp_sw.c +5 -3
index 9aec4ca..f7da753 100644
@@ -107,6 +107,7 @@ static int hp_sw_tur(struct scsi_device *sdev, struct hp_sw_dh_data *h)
 	struct request *req;
 	int ret;
 
+retry:
 	req = blk_get_request(sdev->request_queue, WRITE, GFP_NOIO);
 	if (!req)
 		return SCSI_DH_RES_TEMP_UNAVAIL;
@@ -121,7 +122,6 @@ static int hp_sw_tur(struct scsi_device *sdev, struct hp_sw_dh_data *h)
 	memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE);
 	req->sense_len = 0;
 
-retry:
 	ret = blk_execute_rq(req->q, NULL, req, 1);
 	if (ret == -EIO) {
 		if (req->sense_len > 0) {
@@ -136,8 +136,10 @@ retry:
 		h->path_state = HP_SW_PATH_ACTIVE;
 		ret = SCSI_DH_OK;
 	}
-	if (ret == SCSI_DH_IMM_RETRY)
+	if (ret == SCSI_DH_IMM_RETRY) {
+		blk_put_request(req);
 		goto retry;
+	}
 	if (ret == SCSI_DH_DEV_OFFLINED) {
 		h->path_state = HP_SW_PATH_PASSIVE;
 		ret = SCSI_DH_OK;
@@ -200,6 +202,7 @@ static int hp_sw_start_stop(struct scsi_device *sdev, struct hp_sw_dh_data *h)
 	struct request *req;
 	int ret, retry;
 
+retry:
 	req = blk_get_request(sdev->request_queue, WRITE, GFP_NOIO);
 	if (!req)
 		return SCSI_DH_RES_TEMP_UNAVAIL;
@@ -216,7 +219,6 @@ static int hp_sw_start_stop(struct scsi_device *sdev, struct hp_sw_dh_data *h)
 	req->sense_len = 0;
 	retry = h->retries;
 
-retry:
 	ret = blk_execute_rq(req->q, NULL, req, 1);
 	if (ret == -EIO) {
 		if (req->sense_len > 0) {

drivers/scsi/device_handler/scsi_dh_hp_sw.c retry: · line 241

Quoted 10 lines
drivers/scsi/device_handler/scsi_dh_hp_sw.c +3 -1
@@ -231,8 +233,10 @@ retry:
 		ret = SCSI_DH_OK;
 
 	if (ret == SCSI_DH_RETRY) {
-		if (--retry)
+		if (--retry) {
+			blk_put_request(req);
 			goto retry;
+		}
 		ret = SCSI_DH_IO;
 	}

Looks like the majority of the usage of blk_get_request/blk_execute_rq/blk_put_request can be simply replaced with scsi_execute()? The problem is that scsi_execute doesn't return all the information about errors?