Commit f1126e95 authored by FUJITA Tomonori's avatar FUJITA Tomonori Committed by Jens Axboe

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: default avatarFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Signed-off-by: default avatarJens Axboe <jaxboe@fusionio.com>
parent 28018c24
...@@ -425,6 +425,7 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) ...@@ -425,6 +425,7 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq)
sector_t sector = bio->bi_sector; sector_t sector = bio->bi_sector;
unsigned int nr_sectors = bio_sectors(bio); unsigned int nr_sectors = bio_sectors(bio);
unsigned int len; unsigned int len;
int ret;
struct page *page; struct page *page;
if (sdkp->device->sector_size == 4096) { if (sdkp->device->sector_size == 4096) {
...@@ -465,7 +466,15 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) ...@@ -465,7 +466,15 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq)
} }
blk_add_request_payload(rq, page, len); blk_add_request_payload(rq, page, len);
return scsi_setup_blk_pc_cmnd(sdp, rq); ret = scsi_setup_blk_pc_cmnd(sdp, rq);
rq->buffer = page_address(page);
return ret;
}
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));
} }
/** /**
...@@ -2242,6 +2251,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie) ...@@ -2242,6 +2251,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
sd_revalidate_disk(gd); sd_revalidate_disk(gd);
blk_queue_prep_rq(sdp->request_queue, sd_prep_fn); blk_queue_prep_rq(sdp->request_queue, sd_prep_fn);
blk_queue_unprep_rq(sdp->request_queue, sd_unprep_fn);
gd->driverfs_dev = &sdp->sdev_gendev; gd->driverfs_dev = &sdp->sdev_gendev;
gd->flags = GENHD_FL_EXT_DEVT; gd->flags = GENHD_FL_EXT_DEVT;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment