|
@@ -463,6 +463,7 @@ out:
|
|
*/
|
|
*/
|
|
static void loop_add_bio(struct loop_device *lo, struct bio *bio)
|
|
static void loop_add_bio(struct loop_device *lo, struct bio *bio)
|
|
{
|
|
{
|
|
|
|
+ lo->lo_bio_count++;
|
|
bio_list_add(&lo->lo_bio_list, bio);
|
|
bio_list_add(&lo->lo_bio_list, bio);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -471,6 +472,7 @@ static void loop_add_bio(struct loop_device *lo, struct bio *bio)
|
|
*/
|
|
*/
|
|
static struct bio *loop_get_bio(struct loop_device *lo)
|
|
static struct bio *loop_get_bio(struct loop_device *lo)
|
|
{
|
|
{
|
|
|
|
+ lo->lo_bio_count--;
|
|
return bio_list_pop(&lo->lo_bio_list);
|
|
return bio_list_pop(&lo->lo_bio_list);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -489,6 +491,10 @@ static void loop_make_request(struct request_queue *q, struct bio *old_bio)
|
|
goto out;
|
|
goto out;
|
|
if (unlikely(rw == WRITE && (lo->lo_flags & LO_FLAGS_READ_ONLY)))
|
|
if (unlikely(rw == WRITE && (lo->lo_flags & LO_FLAGS_READ_ONLY)))
|
|
goto out;
|
|
goto out;
|
|
|
|
+ if (lo->lo_bio_count >= q->nr_congestion_on)
|
|
|
|
+ wait_event_lock_irq(lo->lo_req_wait,
|
|
|
|
+ lo->lo_bio_count < q->nr_congestion_off,
|
|
|
|
+ lo->lo_lock);
|
|
loop_add_bio(lo, old_bio);
|
|
loop_add_bio(lo, old_bio);
|
|
wake_up(&lo->lo_event);
|
|
wake_up(&lo->lo_event);
|
|
spin_unlock_irq(&lo->lo_lock);
|
|
spin_unlock_irq(&lo->lo_lock);
|
|
@@ -546,6 +552,8 @@ static int loop_thread(void *data)
|
|
continue;
|
|
continue;
|
|
spin_lock_irq(&lo->lo_lock);
|
|
spin_lock_irq(&lo->lo_lock);
|
|
bio = loop_get_bio(lo);
|
|
bio = loop_get_bio(lo);
|
|
|
|
+ if (lo->lo_bio_count < lo->lo_queue->nr_congestion_off)
|
|
|
|
+ wake_up(&lo->lo_req_wait);
|
|
spin_unlock_irq(&lo->lo_lock);
|
|
spin_unlock_irq(&lo->lo_lock);
|
|
|
|
|
|
BUG_ON(!bio);
|
|
BUG_ON(!bio);
|
|
@@ -873,6 +881,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
|
|
lo->transfer = transfer_none;
|
|
lo->transfer = transfer_none;
|
|
lo->ioctl = NULL;
|
|
lo->ioctl = NULL;
|
|
lo->lo_sizelimit = 0;
|
|
lo->lo_sizelimit = 0;
|
|
|
|
+ lo->lo_bio_count = 0;
|
|
lo->old_gfp_mask = mapping_gfp_mask(mapping);
|
|
lo->old_gfp_mask = mapping_gfp_mask(mapping);
|
|
mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
|
|
mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
|
|
|
|
|
|
@@ -1660,6 +1669,7 @@ static int loop_add(struct loop_device **l, int i)
|
|
lo->lo_number = i;
|
|
lo->lo_number = i;
|
|
lo->lo_thread = NULL;
|
|
lo->lo_thread = NULL;
|
|
init_waitqueue_head(&lo->lo_event);
|
|
init_waitqueue_head(&lo->lo_event);
|
|
|
|
+ init_waitqueue_head(&lo->lo_req_wait);
|
|
spin_lock_init(&lo->lo_lock);
|
|
spin_lock_init(&lo->lo_lock);
|
|
disk->major = LOOP_MAJOR;
|
|
disk->major = LOOP_MAJOR;
|
|
disk->first_minor = i << part_shift;
|
|
disk->first_minor = i << part_shift;
|