aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/sd.c
diff options
context:
space:
mode:
authorFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2010-07-01 06:49:18 -0400
committerJens Axboe <jaxboe@fusionio.com>2010-08-07 12:23:49 -0400
commitf1126e950d28ff875d96ed6a04a9ff96c7bfc357 (patch)
tree4d7217b91a658c1c8fa31325f39b102377765f21 /drivers/scsi/sd.c
parent28018c242a4ec7017bbbf81d2d3952f820a27118 (diff)
scsi: add sd_unprep_fn to free discard page
This fixes discard page leak by using q->unprep_rq_fn facility. q->unprep_rq_fn is called when all the data buffer (req->bio and scsi_data_buffer) in the request is freed. sd_unprep() uses rq->buffer to free discard page allocated in sd_prepare_discard(). Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r--drivers/scsi/sd.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 86da819c70eb..2d4e3a865f39 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -425,6 +425,7 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq)
425 sector_t sector = bio->bi_sector; 425 sector_t sector = bio->bi_sector;
426 unsigned int nr_sectors = bio_sectors(bio); 426 unsigned int nr_sectors = bio_sectors(bio);
427 unsigned int len; 427 unsigned int len;
428 int ret;
428 struct page *page; 429 struct page *page;
429 430
430 if (sdkp->device->sector_size == 4096) { 431 if (sdkp->device->sector_size == 4096) {
@@ -465,7 +466,15 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq)
465 } 466 }
466 467
467 blk_add_request_payload(rq, page, len); 468 blk_add_request_payload(rq, page, len);
468 return scsi_setup_blk_pc_cmnd(sdp, rq); 469 ret = scsi_setup_blk_pc_cmnd(sdp, rq);
470 rq->buffer = page_address(page);
471 return ret;
472}
473
474static void sd_unprep_fn(struct request_queue *q, struct request *rq)
475{
476 if (rq->cmd_flags & REQ_DISCARD)
477 __free_page(virt_to_page(rq->buffer));
469} 478}
470 479
471/** 480/**
@@ -2242,6 +2251,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
2242 sd_revalidate_disk(gd); 2251 sd_revalidate_disk(gd);
2243 2252
2244 blk_queue_prep_rq(sdp->request_queue, sd_prep_fn); 2253 blk_queue_prep_rq(sdp->request_queue, sd_prep_fn);
2254 blk_queue_unprep_rq(sdp->request_queue, sd_unprep_fn);
2245 2255
2246 gd->driverfs_dev = &sdp->sdev_gendev; 2256 gd->driverfs_dev = &sdp->sdev_gendev;
2247 gd->flags = GENHD_FL_EXT_DEVT; 2257 gd->flags = GENHD_FL_EXT_DEVT;