public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [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