diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index 79807db..9b0d6fc 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -1549,6 +1549,12 @@ void blk_plug_device(request_queue_t *q)
 	if (blk_queue_stopped(q))
 		return;
 
+	if (q->request_fn_recursion_limit >= 3) {
+		printk("Cowardly refusing to plug queue due to deep recursion\n");
+		dump_stack();
+		return;
+	}
+
 	if (!test_and_set_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags)) {
 		mod_timer(&q->unplug_timer, jiffies + q->unplug_delay);
 		blk_add_trace_generic(q, NULL, 0, BLK_TA_PLUG);
@@ -1585,7 +1591,15 @@ void __generic_unplug_device(request_queue_t *q)
 	if (!blk_remove_plug(q))
 		return;
 
+	if (q->request_fn_recursion_limit++ >= 5) {
+		printk("Cowardly refusing to unplug queue due to deep recursion");
+		dump_stack();
+		q->request_fn_recursion_limit--;
+		return;
+	}
+
 	q->request_fn(q);
+	q->request_fn_recursion_limit--;
 }
 EXPORT_SYMBOL(__generic_unplug_device);
 
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index ea330d7..8964f77 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -474,6 +474,8 @@ struct request_queue
 	struct request		*orig_bar_rq;
 	unsigned int		bi_size;
 
+	int request_fn_recursion_limit;
+
 	struct mutex		sysfs_lock;
 };
 

