From 0dc43a69915ffdca1aa2d4631a4778630579c7a5 Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Tue, 6 Jul 2010 16:47:28 -0400 Subject: [RHEL6 PATCH 5/6] scsi: fix leak in scsi_setup_discard_cmnd error path BZ 610054 Posted for inclussion in linux-2.6-block's 'for-2.6.36': http://marc.info/?l=linux-scsi&m=127842482308698&w=2 This minimalist patch is less invassive than a fix proposed by Tomo: http://marc.info/?l=linux-scsi&m=127830246929556&w=2 So far both Jens Axboe and James Bottomley have been non-committal on a fix even though the leak is both obvious and easily fixed. For RHEL6 it'd be best to avoid Tomo's crafty SCSI prep error handling changes (especially given that the implementation conflicts with James' "rules" for SCSI prep/unprep). Author: Mike Snitzer Currently, a discard request's page will not get cleaned up in the scsi_setup_discard_cmnd error path. A scsi_setup_discard_cmnd return other than BLKPREP_OK will not cause a discard request to get completely cleaned up (scsi_prep_return will not set REQ_DONTPREP unless BLKPREP_OK was returned). This fix eliminates the leak while preserving the rule that: Unprep is only called if the request gets prepped (meaning a return BLKPREP_OK). Defer or kill assume there's no teardown to do, so any allocation must be reversed before returning them. Signed-off-by: Mike Snitzer diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index c748bbd..a8abe65 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -466,13 +466,19 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) blk_add_request_payload(rq, page, len); ret = scsi_setup_blk_pc_cmnd(sdp, rq); rq->buffer = page_address(page); + if (ret != BLKPREP_OK) { + __free_page(page); + rq->buffer = NULL; + } return ret; } static void sd_unprep_fn(struct request_queue *q, struct request *rq) { - if (rq->cmd_flags & REQ_DISCARD) + if (rq->cmd_flags & REQ_DISCARD) { __free_page(virt_to_page(rq->buffer)); + rq->buffer = NULL; + } } /** -- 1.6.6.1