* [PATCH] [RFC] block: Don't let blk_put_request leak BIOs [not found] ` <20090212184208X.fujita.tomonori@lab.ntt.co.jp> @ 2009-02-12 12:19 ` Boaz Harrosh 2009-02-12 13:49 ` Boaz Harrosh 0 siblings, 1 reply; 5+ messages in thread From: Boaz Harrosh @ 2009-02-12 12:19 UTC (permalink / raw) To: FUJITA Tomonori, jens.axboe; +Cc: James.Bottomley, linux-scsi, linux-kernel If a block ULD had allocated a request and mapped some memory into it, using one of blk_rq_map_xxx routines, but then for some reason failed to execute the request through one of the blk_execute_request routines. Then the associated BIO would leak, unless ULD resorts to low-level loops intimate of block internals. [RFC] This code will also catch situations where LLD failed to complete the request before aborting it. Such situations are a BUG. Should we use WARN_ON_ONCE() in that case. The situation above is possible and can happen normally in memory pressure situations so maybe we should devise a bit-flag that ULD denotes that the request was aborted and only WARN_ON if flag was not set. I'm sending this before any-tests so people can comment on possible pitfalls. Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> --- block/blk-core.c | 16 ++++++++++++++++ drivers/scsi/osd/osd_initiator.c | 17 +---------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index a824e49..eac96c2 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1055,6 +1055,21 @@ void part_round_stats(int cpu, struct hd_struct *part) EXPORT_SYMBOL_GPL(part_round_stats); /* + * If one of the blk_rq_map_xxx() was called but the request was not + * executed by the block layer, then we must release BIOs. Otherwise they + * will leak. + */ +static void _abort_unexecuted_bios(struct request *req) +{ + struct bio *bio; + + while ((bio = req->bio) != NULL) { + req->bio = bio->bi_next; + bio_endio(bio, 0); + } +} + +/* * queue lock must be held */ void __blk_put_request(struct request_queue *q, struct request *req) @@ -1066,6 +1081,7 @@ void __blk_put_request(struct request_queue *q, struct request *req) elv_completed_request(q, req); + _abort_unexecuted_bios(req); /* * Request may not have originated from ll_rw_blk. if not, * it didn't come out of our reserved rq pools diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c index 0bbbf27..8b1cf72 100644 --- a/drivers/scsi/osd/osd_initiator.c +++ b/drivers/scsi/osd/osd_initiator.c @@ -335,20 +335,6 @@ struct osd_request *osd_start_request(struct osd_dev *dev, gfp_t gfp) } EXPORT_SYMBOL(osd_start_request); -/* - * If osd_finalize_request() was called but the request was not executed through - * the block layer, then we must release BIOs. - */ -static void _abort_unexecuted_bios(struct request *rq) -{ - struct bio *bio; - - while ((bio = rq->bio) != NULL) { - rq->bio = bio->bi_next; - bio_endio(bio, 0); - } -} - static void _osd_free_seg(struct osd_request *or __unused, struct _osd_req_data_segment *seg) { @@ -370,11 +356,10 @@ void osd_end_request(struct osd_request *or) if (rq) { if (rq->next_rq) { - _abort_unexecuted_bios(rq->next_rq); blk_put_request(rq->next_rq); + rq->next_rq = NULL; } - _abort_unexecuted_bios(rq); blk_put_request(rq); } _osd_request_free(or); -- 1.6.0.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] [RFC] block: Don't let blk_put_request leak BIOs 2009-02-12 12:19 ` [PATCH] [RFC] block: Don't let blk_put_request leak BIOs Boaz Harrosh @ 2009-02-12 13:49 ` Boaz Harrosh 2009-02-12 13:56 ` Boaz Harrosh 0 siblings, 1 reply; 5+ messages in thread From: Boaz Harrosh @ 2009-02-12 13:49 UTC (permalink / raw) To: jens.axboe, James.Bottomley, FUJITA Tomonori; +Cc: linux-scsi, linux-kernel Boaz Harrosh wrote: > If a block ULD had allocated a request and mapped some memory into it, > using one of blk_rq_map_xxx routines, but then for some reason failed to > execute the request through one of the blk_execute_request routines. > Then the associated BIO would leak, unless ULD resorts to low-level loops > intimate of block internals. > > [RFC] > This code will also catch situations where LLD failed to complete > the request before aborting it. Such situations are a BUG. Should we > use WARN_ON_ONCE() in that case. The situation above is possible and > can happen normally in memory pressure situations so maybe we should > devise a bit-flag that ULD denotes that the request was aborted and > only WARN_ON if flag was not set. > > I'm sending this before any-tests so people can comment on possible > pitfalls. > > Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> > --- I've booted a Linux PC with lots of sata disks, connected an iscsi target, ran OSD tests. It looks like it's working which means request->bio is set to NULL after it is used in the regular path. This needs to sit in Linux next and be tested for a long while. Jens I'll be waiting for your comment and will send a proper patch for the block bits. We will have to time this with James to see when the OSD bits can be submitted after that, then TOMO's patch for un-exporting blk_req_append_bio can be merged. Or maybe it can all go in one patch through scsi? Thanks Boaz ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] [RFC] block: Don't let blk_put_request leak BIOs 2009-02-12 13:49 ` Boaz Harrosh @ 2009-02-12 13:56 ` Boaz Harrosh 2009-02-12 17:27 ` [PATCH 1/2] " Boaz Harrosh 0 siblings, 1 reply; 5+ messages in thread From: Boaz Harrosh @ 2009-02-12 13:56 UTC (permalink / raw) To: jens.axboe, James.Bottomley, FUJITA Tomonori; +Cc: linux-scsi, linux-kernel Boaz Harrosh wrote: > Boaz Harrosh wrote: >> If a block ULD had allocated a request and mapped some memory into it, >> using one of blk_rq_map_xxx routines, but then for some reason failed to >> execute the request through one of the blk_execute_request routines. >> Then the associated BIO would leak, unless ULD resorts to low-level loops >> intimate of block internals. >> >> [RFC] >> This code will also catch situations where LLD failed to complete >> the request before aborting it. Such situations are a BUG. Should we >> use WARN_ON_ONCE() in that case. The situation above is possible and >> can happen normally in memory pressure situations so maybe we should >> devise a bit-flag that ULD denotes that the request was aborted and >> only WARN_ON if flag was not set. >> >> I'm sending this before any-tests so people can comment on possible >> pitfalls. >> >> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> >> --- > > I've booted a Linux PC with lots of sata disks, connected an iscsi > target, ran OSD tests. It looks like it's working which means > request->bio is set to NULL after it is used in the regular path. > > This needs to sit in Linux next and be tested for a long while. > > Jens I'll be waiting for your comment and will send a proper > patch for the block bits. We will have to time this with James > to see when the OSD bits can be submitted after that, then TOMO's > patch for un-exporting blk_req_append_bio can be merged. Or maybe > it can all go in one patch through scsi? > > Thanks > Boaz Spock to soon this patch is shit, I'll look into it Sorry for the noise Boaz ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] [RFC] block: Don't let blk_put_request leak BIOs 2009-02-12 13:56 ` Boaz Harrosh @ 2009-02-12 17:27 ` Boaz Harrosh 2009-02-12 17:30 ` [PATCH 2/2] [RFC] libosd: Don't let osd abuse block internals, now that it's fixed Boaz Harrosh 0 siblings, 1 reply; 5+ messages in thread From: Boaz Harrosh @ 2009-02-12 17:27 UTC (permalink / raw) To: jens.axboe, James.Bottomley, FUJITA Tomonori; +Cc: linux-scsi, linux-kernel If a block ULD had allocated a request and mapped some memory into it, but then for some reason failed to execute the request through one of the blk_execute_request_xxx routines. Then the associated bio would leak, unless ULD resorts to low-level loops intimate of block internals. For this to work I have fixed a couple of places in block/ where request->bio != NULL ownership was not honored. And a small cleanup at sg_io() while at it. [RFC] This code will also catch situations where LLD failed to complete the request before aborting it. Such situations are a BUG. Should we use WARN_ON_ONCE() in that case. The situation above is possible and can happen normally in memory pressure situations so maybe we should devise a bit-flag that ULD denotes that the request was aborted and only WARN_ON if flag was not set. For the duration of linux-next I'm leaving the WARN_ON to catch any problems like found above, and possible memory leaks. Before submission a complimentary patch should remove the WARN_ON. (Or this patch can be rebased) Please comment on possible pitfalls. Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> --- block/blk-core.c | 17 +++++++++++++++++ block/blk-merge.c | 2 ++ block/scsi_ioctl.c | 21 ++++----------------- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index a824e49..3c1f920 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1055,6 +1055,22 @@ void part_round_stats(int cpu, struct hd_struct *part) EXPORT_SYMBOL_GPL(part_round_stats); /* + * If one of the blk_rq_map_xxx() was called but the request was not + * executed by the block layer, then we must release BIOs. Otherwise they + * will leak. + */ +static void _abort_unexecuted_bios(struct request *req) +{ + struct bio *bio; + + WARN_ON(req->bio != NULL); + while (unlikely((bio = req->bio) != NULL)) { + req->bio = bio->bi_next; + bio_endio(bio, 0); + } +} + +/* * queue lock must be held */ void __blk_put_request(struct request_queue *q, struct request *req) @@ -1066,6 +1082,7 @@ void __blk_put_request(struct request_queue *q, struct request *req) elv_completed_request(q, req); + _abort_unexecuted_bios(req); /* * Request may not have originated from ll_rw_blk. if not, * it didn't come out of our reserved rq pools diff --git a/block/blk-merge.c b/block/blk-merge.c index b92f5b0..463e797 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -398,6 +398,8 @@ static int attempt_merge(struct request_queue *q, struct request *req, if (blk_rq_cpu_valid(next)) req->cpu = next->cpu; + /* owner-ship of bio passed from next to req */ + next->bio = NULL; __blk_put_request(q, next); return 1; } diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index ee9c67d..626ee27 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -214,21 +214,10 @@ static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq, return 0; } -/* - * unmap a request that was previously mapped to this sg_io_hdr. handles - * both sg and non-sg sg_io_hdr. - */ -static int blk_unmap_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr) -{ - blk_rq_unmap_user(rq->bio); - blk_put_request(rq); - return 0; -} - static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr, struct bio *bio) { - int r, ret = 0; + int ret = 0; /* * fill in all the output members @@ -253,12 +242,10 @@ static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr, ret = -EFAULT; } - rq->bio = bio; - r = blk_unmap_sghdr_rq(rq, hdr); - if (ret) - r = ret; + blk_rq_unmap_user(bio); + blk_put_request(rq); - return r; + return ret; } static int sg_io(struct request_queue *q, struct gendisk *bd_disk, -- 1.6.0.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/2] [RFC] libosd: Don't let osd abuse block internals, now that it's fixed 2009-02-12 17:27 ` [PATCH 1/2] " Boaz Harrosh @ 2009-02-12 17:30 ` Boaz Harrosh 0 siblings, 0 replies; 5+ messages in thread From: Boaz Harrosh @ 2009-02-12 17:30 UTC (permalink / raw) To: jens.axboe, James.Bottomley, FUJITA Tomonori; +Cc: linux-scsi, linux-kernel blk_put_request will delete any BIOs that where mapped but not executed, so osd_initiator does not have to take care of this situation any more. This patch is dependent on block patch titled: [PATCH 1/2] block: Don't let blk_put_request leak BIOs Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> --- drivers/scsi/osd/osd_initiator.c | 17 +---------------- 1 files changed, 1 insertions(+), 16 deletions(-) diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c index 0bbbf27..8b1cf72 100644 --- a/drivers/scsi/osd/osd_initiator.c +++ b/drivers/scsi/osd/osd_initiator.c @@ -335,20 +335,6 @@ struct osd_request *osd_start_request(struct osd_dev *dev, gfp_t gfp) } EXPORT_SYMBOL(osd_start_request); -/* - * If osd_finalize_request() was called but the request was not executed through - * the block layer, then we must release BIOs. - */ -static void _abort_unexecuted_bios(struct request *rq) -{ - struct bio *bio; - - while ((bio = rq->bio) != NULL) { - rq->bio = bio->bi_next; - bio_endio(bio, 0); - } -} - static void _osd_free_seg(struct osd_request *or __unused, struct _osd_req_data_segment *seg) { @@ -370,11 +356,10 @@ void osd_end_request(struct osd_request *or) if (rq) { if (rq->next_rq) { - _abort_unexecuted_bios(rq->next_rq); blk_put_request(rq->next_rq); + rq->next_rq = NULL; } - _abort_unexecuted_bios(rq); blk_put_request(rq); } _osd_request_free(or); -- 1.6.0.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2009-02-12 17:30 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <4993DCCA.8080508@panasas.com>
[not found] ` <20090212174124S.fujita.tomonori@lab.ntt.co.jp>
[not found] ` <4993E85A.20805@panasas.com>
[not found] ` <20090212184208X.fujita.tomonori@lab.ntt.co.jp>
2009-02-12 12:19 ` [PATCH] [RFC] block: Don't let blk_put_request leak BIOs Boaz Harrosh
2009-02-12 13:49 ` Boaz Harrosh
2009-02-12 13:56 ` Boaz Harrosh
2009-02-12 17:27 ` [PATCH 1/2] " Boaz Harrosh
2009-02-12 17:30 ` [PATCH 2/2] [RFC] libosd: Don't let osd abuse block internals, now that it's fixed Boaz Harrosh
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox