aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/loop.c38
1 files changed, 35 insertions, 3 deletions
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index fb06ed659212..66cfff79938e 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
@@ -1345,11 +1363,25 @@ static int lo_release(struct gendisk *disk, fmode_t mode)
1345 struct loop_device *lo = disk->private_data; 1363 struct loop_device *lo = disk->private_data;
1346 1364
1347 mutex_lock(&lo->lo_ctl_mutex); 1365 mutex_lock(&lo->lo_ctl_mutex);
1348 --lo->lo_refcnt;
1349 1366
1350 if ((lo->lo_flags & LO_FLAGS_AUTOCLEAR) && !lo->lo_refcnt) 1367 if (--lo->lo_refcnt)
1368 goto out;
1369
1370 if (lo->lo_flags & LO_FLAGS_AUTOCLEAR) {
1371 /*
1372 * In autoclear mode, stop the loop thread
1373 * and remove configuration after last close.
1374 */
1351 loop_clr_fd(lo, NULL); 1375 loop_clr_fd(lo, NULL);
1376 } else {
1377 /*
1378 * Otherwise keep thread (if running) and config,
1379 * but flush possible ongoing bios in thread.
1380 */
1381 loop_flush(lo);
1382 }
1352 1383
1384out:
1353 mutex_unlock(&lo->lo_ctl_mutex); 1385 mutex_unlock(&lo->lo_ctl_mutex);
1354 1386
1355 return 0; 1387 return 0;