aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/block/loop.c10
-rw-r--r--include/linux/loop.h3
2 files changed, 13 insertions, 0 deletions
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index e9d594fd12cb..800aec7927de 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -463,6 +463,7 @@ out:
463 */ 463 */
464static void loop_add_bio(struct loop_device *lo, struct bio *bio) 464static void loop_add_bio(struct loop_device *lo, struct bio *bio)
465{ 465{
466 lo->lo_bio_count++;
466 bio_list_add(&lo->lo_bio_list, bio); 467 bio_list_add(&lo->lo_bio_list, bio);
467} 468}
468 469
@@ -471,6 +472,7 @@ static void loop_add_bio(struct loop_device *lo, struct bio *bio)
471 */ 472 */
472static struct bio *loop_get_bio(struct loop_device *lo) 473static struct bio *loop_get_bio(struct loop_device *lo)
473{ 474{
475 lo->lo_bio_count--;
474 return bio_list_pop(&lo->lo_bio_list); 476 return bio_list_pop(&lo->lo_bio_list);
475} 477}
476 478
@@ -489,6 +491,10 @@ static void loop_make_request(struct request_queue *q, struct bio *old_bio)
489 goto out; 491 goto out;
490 if (unlikely(rw == WRITE && (lo->lo_flags & LO_FLAGS_READ_ONLY))) 492 if (unlikely(rw == WRITE && (lo->lo_flags & LO_FLAGS_READ_ONLY)))
491 goto out; 493 goto out;
494 if (lo->lo_bio_count >= q->nr_congestion_on)
495 wait_event_lock_irq(lo->lo_req_wait,
496 lo->lo_bio_count < q->nr_congestion_off,
497 lo->lo_lock);
492 loop_add_bio(lo, old_bio); 498 loop_add_bio(lo, old_bio);
493 wake_up(&lo->lo_event); 499 wake_up(&lo->lo_event);
494 spin_unlock_irq(&lo->lo_lock); 500 spin_unlock_irq(&lo->lo_lock);
@@ -546,6 +552,8 @@ static int loop_thread(void *data)
546 continue; 552 continue;
547 spin_lock_irq(&lo->lo_lock); 553 spin_lock_irq(&lo->lo_lock);
548 bio = loop_get_bio(lo); 554 bio = loop_get_bio(lo);
555 if (lo->lo_bio_count < lo->lo_queue->nr_congestion_off)
556 wake_up(&lo->lo_req_wait);
549 spin_unlock_irq(&lo->lo_lock); 557 spin_unlock_irq(&lo->lo_lock);
550 558
551 BUG_ON(!bio); 559 BUG_ON(!bio);
@@ -873,6 +881,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
873 lo->transfer = transfer_none; 881 lo->transfer = transfer_none;
874 lo->ioctl = NULL; 882 lo->ioctl = NULL;
875 lo->lo_sizelimit = 0; 883 lo->lo_sizelimit = 0;
884 lo->lo_bio_count = 0;
876 lo->old_gfp_mask = mapping_gfp_mask(mapping); 885 lo->old_gfp_mask = mapping_gfp_mask(mapping);
877 mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS)); 886 mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
878 887
@@ -1660,6 +1669,7 @@ static int loop_add(struct loop_device **l, int i)
1660 lo->lo_number = i; 1669 lo->lo_number = i;
1661 lo->lo_thread = NULL; 1670 lo->lo_thread = NULL;
1662 init_waitqueue_head(&lo->lo_event); 1671 init_waitqueue_head(&lo->lo_event);
1672 init_waitqueue_head(&lo->lo_req_wait);
1663 spin_lock_init(&lo->lo_lock); 1673 spin_lock_init(&lo->lo_lock);
1664 disk->major = LOOP_MAJOR; 1674 disk->major = LOOP_MAJOR;
1665 disk->first_minor = i << part_shift; 1675 disk->first_minor = i << part_shift;
diff --git a/include/linux/loop.h b/include/linux/loop.h
index 6492181bcb1d..460b60fa7adf 100644
--- a/include/linux/loop.h
+++ b/include/linux/loop.h
@@ -53,10 +53,13 @@ struct loop_device {
53 53
54 spinlock_t lo_lock; 54 spinlock_t lo_lock;
55 struct bio_list lo_bio_list; 55 struct bio_list lo_bio_list;
56 unsigned int lo_bio_count;
56 int lo_state; 57 int lo_state;
57 struct mutex lo_ctl_mutex; 58 struct mutex lo_ctl_mutex;
58 struct task_struct *lo_thread; 59 struct task_struct *lo_thread;
59 wait_queue_head_t lo_event; 60 wait_queue_head_t lo_event;
61 /* wait queue for incoming requests */
62 wait_queue_head_t lo_req_wait;
60 63
61 struct request_queue *lo_queue; 64 struct request_queue *lo_queue;
62 struct gendisk *lo_disk; 65 struct gendisk *lo_disk;