Web lists-archives.org

[PATCH 1/2] Avoid bio_endio recursion




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@xxxxxxxxxx>

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)
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/