[PATCH] scsi: unify the error handling of the prep functions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This can be applied to the block's for-2.6.36.

=
From: FUJITA Tomonori <fujita.tomonori@xxxxxxxxxxxxx>
Subject: [PATCH] scsi: unify the error handling of the prep functions

This unifies the error handling of the prep functions (and fix the
leak of a page allocated for discard in the case of BLKPREP_KILL or
BLK_PREP_DEFER).

The error handling of the prep path is very messy. Some errors are
handled in the prep functions while some are in scsi_prep_return().

Let's handle all the errors in scsi_prep_return().

Signed-off-by: FUJITA Tomonori <fujita.tomonori@xxxxxxxxxxxxx>
---
 drivers/scsi/scsi_lib.c |   26 +++++++++++++-------------
 drivers/scsi/sd.c       |    6 ++++--
 2 files changed, 17 insertions(+), 15 deletions(-)

diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index ee83619..f9b3f7b 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1008,14 +1008,7 @@ int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask)
 	}
 
 	return BLKPREP_OK ;
-
 err_exit:
-	scsi_release_buffers(cmd);
-	if (error == BLKPREP_KILL)
-		scsi_put_command(cmd);
-	else /* BLKPREP_DEFER */
-		scsi_unprep_request(cmd->request);
-
 	return error;
 }
 EXPORT_SYMBOL(scsi_init_io);
@@ -1177,6 +1170,17 @@ int scsi_prep_state_check(struct scsi_device *sdev, struct request *req)
 }
 EXPORT_SYMBOL(scsi_prep_state_check);
 
+static void scsi_prep_error(struct request *req)
+{
+	struct scsi_cmnd *cmd = req->special;
+
+	if (!cmd)
+		return;
+
+	scsi_release_buffers(cmd);
+	scsi_unprep_request(req);
+}
+
 int scsi_prep_return(struct request_queue *q, struct request *req, int ret)
 {
 	struct scsi_device *sdev = q->queuedata;
@@ -1185,14 +1189,10 @@ int scsi_prep_return(struct request_queue *q, struct request *req, int ret)
 	case BLKPREP_KILL:
 		req->errors = DID_NO_CONNECT << 16;
 		/* release the command and kill it */
-		if (req->special) {
-			struct scsi_cmnd *cmd = req->special;
-			scsi_release_buffers(cmd);
-			scsi_put_command(cmd);
-			req->special = NULL;
-		}
+		scsi_prep_error(req);
 		break;
 	case BLKPREP_DEFER:
+		scsi_prep_error(req);
 		/*
 		 * If we defer, the blk_peek_request() returns NULL, but the
 		 * queue must be restarted, so we plug here if no returning
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index aa6b48b..88ba0c5 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -473,8 +473,10 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq)
 
 static void sd_unprep_fn(struct request_queue *q, struct request *rq)
 {
-	if (rq->cmd_flags & REQ_DISCARD)
-		__free_page(virt_to_page(rq->buffer));
+	if (rq->cmd_flags & REQ_DISCARD) {
+		free_page((unsigned long)rq->buffer);
+		rq->buffer = NULL;
+	}
 }
 
 /**
-- 
1.6.5

--
dm-devel mailing list
dm-devel@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/dm-devel


[Index of Archives]     [DM Crypt]     [Fedora Desktop]     [ATA RAID]     [Fedora Marketing]     [Fedora Packaging]     [Fedora SELinux]     [Yosemite Discussion]     [KDE Users]     [Fedora Docs]

  Powered by Linux