aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/loop.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/loop.c')
-rw-r--r--drivers/block/loop.c39
1 files changed, 36 insertions, 3 deletions
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index fb06ed659212..edbaac6c0573 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -624,20 +624,38 @@ static int loop_switch(struct loop_device *lo, struct file *file)
624} 624}
625 625
626/* 626/*
627 * Helper to flush the IOs in loop, but keeping loop thread running
628 */
629static int loop_flush(struct loop_device *lo)
630{
631 /* loop not yet configured, no running thread, nothing to flush */
632 if (!lo->lo_thread)
633 return 0;
634
635 return loop_switch(lo, NULL);
636}
637
638/*
627 * Do the actual switch; called from the BIO completion routine 639 * Do the actual switch; called from the BIO completion routine
628 */ 640 */
629static void do_loop_switch(struct loop_device *lo, struct switch_request *p) 641static void do_loop_switch(struct loop_device *lo, struct switch_request *p)
630{ 642{
631 struct file *file = p->file; 643 struct file *file = p->file;
632 struct file *old_file = lo->lo_backing_file; 644 struct file *old_file = lo->lo_backing_file;
633 struct address_space *mapping = file->f_mapping; 645 struct address_space *mapping;
646
647 /* if no new file, only flush of queued bios requested */
648 if (!file)
649 goto out;
634 650
651 mapping = file->f_mapping;
635 mapping_set_gfp_mask(old_file->f_mapping, lo->old_gfp_mask); 652 mapping_set_gfp_mask(old_file->f_mapping, lo->old_gfp_mask);
636 lo->lo_backing_file = file; 653 lo->lo_backing_file = file;
637 lo->lo_blocksize = S_ISBLK(mapping->host->i_mode) ? 654 lo->lo_blocksize = S_ISBLK(mapping->host->i_mode) ?
638 mapping->host->i_bdev->bd_block_size : PAGE_SIZE; 655 mapping->host->i_bdev->bd_block_size : PAGE_SIZE;
639 lo->old_gfp_mask = mapping_gfp_mask(mapping); 656 lo->old_gfp_mask = mapping_gfp_mask(mapping);
640 mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS)); 657 mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
658out:
641 complete(&p->wait); 659 complete(&p->wait);
642} 660}
643 661
@@ -901,6 +919,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
901 919
902 kthread_stop(lo->lo_thread); 920 kthread_stop(lo->lo_thread);
903 921
922 lo->lo_queue->unplug_fn = NULL;
904 lo->lo_backing_file = NULL; 923 lo->lo_backing_file = NULL;
905 924
906 loop_release_xfer(lo); 925 loop_release_xfer(lo);
@@ -1345,11 +1364,25 @@ static int lo_release(struct gendisk *disk, fmode_t mode)
1345 struct loop_device *lo = disk->private_data; 1364 struct loop_device *lo = disk->private_data;
1346 1365
1347 mutex_lock(&lo->lo_ctl_mutex); 1366 mutex_lock(&lo->lo_ctl_mutex);
1348 --lo->lo_refcnt;
1349 1367
1350 if ((lo->lo_flags & LO_FLAGS_AUTOCLEAR) && !lo->lo_refcnt) 1368 if (--lo->lo_refcnt)
1369 goto out;
1370
1371 if (lo->lo_flags & LO_FLAGS_AUTOCLEAR) {
1372 /*
1373 * In autoclear mode, stop the loop thread
1374 * and remove configuration after last close.
1375 */
1351 loop_clr_fd(lo, NULL); 1376 loop_clr_fd(lo, NULL);
1377 } else {
1378 /*
1379 * Otherwise keep thread (if running) and config,
1380 * but flush possible ongoing bios in thread.
1381 */
1382 loop_flush(lo);
1383 }
1352 1384
1385out:
1353 mutex_unlock(&lo->lo_ctl_mutex); 1386 mutex_unlock(&lo->lo_ctl_mutex);
1354 1387
1355 return 0; 1388 return 0;