public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] Avoid bio_endio recursion
@ 2008-06-24  5:22 Mikulas Patocka
  2008-06-24  6:08 ` Neil Brown
  2008-06-24  8:07 ` Jens Axboe
  0 siblings, 2 replies; 20+ messages in thread
From: Mikulas Patocka @ 2008-06-24  5:22 UTC (permalink / raw)
  To: linux-kernel; +Cc: axboe

Hi

bio_endio calls bi_end_io callback. In case of stacked devices (raid, dm), 
bio_end_io may call bio_endio again, up to an unspecified length.

The crash because of stack overflow was really observed on sparc64. And 
this recursion was one of the contributing factors (using 9 stack frames 
--- that is 1728 bytes).

This patch removes the recursion.

Mikulas

--

Avoid recursion on bio_endio. bio_endio calls bio->bi_end_io which may in turn
call bio_endio again. When this recursion happens, put the new bio to the queue
and process it later, from the top-level bio_endio.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>

Index: linux-2.6.26-rc5-devel/fs/bio.c
===================================================================
--- linux-2.6.26-rc5-devel.orig/fs/bio.c	2008-06-18 23:48:45.000000000 +0200
+++ linux-2.6.26-rc5-devel/fs/bio.c	2008-06-19 00:15:56.000000000 +0200
@@ -1168,6 +1168,27 @@
   **/
  void bio_endio(struct bio *bio, int error)
  {
+	static DEFINE_PER_CPU(struct bio **, bio_end_queue) = { NULL };
+	struct bio ***bio_end_queue_ptr;
+	struct bio *bio_queue;
+
+	unsigned long flags;
+
+	local_irq_save(flags);
+	bio_end_queue_ptr = &__get_cpu_var(bio_end_queue);
+
+	if (*bio_end_queue_ptr) {
+		**bio_end_queue_ptr = bio;
+		*bio_end_queue_ptr = &bio->bi_next;
+		bio->bi_next = NULL;
+		goto ret;
+	}
+
+	bio_queue = NULL;
+queue_empty_next_bio:
+	*bio_end_queue_ptr = &bio_queue;
+next_bio:
+
  	if (error)
  		clear_bit(BIO_UPTODATE, &bio->bi_flags);
  	else if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
@@ -1175,6 +1196,17 @@

  	if (bio->bi_end_io)
  		bio->bi_end_io(bio, error);
+
+	if (bio_queue) {
+		bio = bio_queue;
+		bio_queue = bio->bi_next;
+		if (!bio_queue) goto queue_empty_next_bio;
+		goto next_bio;
+	}
+	*bio_end_queue_ptr = NULL;
+
+ret:
+	local_irq_restore(flags);
  }

  void bio_pair_release(struct bio_pair *bp)

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2008-07-04  8:30 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-24  5:22 [PATCH 1/2] Avoid bio_endio recursion Mikulas Patocka
2008-06-24  6:08 ` Neil Brown
2008-06-24 14:36   ` Mikulas Patocka
2008-06-24  8:07 ` Jens Axboe
2008-06-24 14:27   ` Mikulas Patocka
2008-06-25  8:24     ` Jens Axboe
2008-06-26  0:13       ` Mikulas Patocka
2008-06-26  7:07         ` Jens Axboe
2008-07-02  4:09           ` Mikulas Patocka
2008-07-02  8:00             ` Alan Cox
2008-07-03 21:03               ` Mikulas Patocka
2008-07-02  8:25             ` Jens Axboe
2008-07-03 21:08               ` Mikulas Patocka
2008-07-03 21:04                 ` Alan Cox
2008-07-03 22:54                   ` Mikulas Patocka
2008-07-03 23:00                     ` Alan Cox
2008-07-03 23:51                       ` Mikulas Patocka
2008-07-03 23:44                         ` Alan Cox
2008-07-04  3:26                           ` Mikulas Patocka
2008-07-04  8:11                             ` Alan Cox

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox