Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 123306
b: refs/heads/master
c: 14f2793
h: refs/heads/master
v: v3
  • Loading branch information
Milan Broz authored and Jens Axboe committed Dec 29, 2008
1 parent 6356c50 commit 333ec27
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 4 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 10e5b64415ae9a0ba81dd1f1036d14dfdae9308c
refs/heads/master: 14f2793958bd7878db2dc0309ed4525d6b7f1b72
38 changes: 35 additions & 3 deletions trunk/drivers/block/loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -623,21 +623,39 @@ static int loop_switch(struct loop_device *lo, struct file *file)
return 0;
}

/*
* Helper to flush the IOs in loop, but keeping loop thread running
*/
static int loop_flush(struct loop_device *lo)
{
/* loop not yet configured, no running thread, nothing to flush */
if (!lo->lo_thread)
return 0;

return loop_switch(lo, NULL);
}

/*
* Do the actual switch; called from the BIO completion routine
*/
static void do_loop_switch(struct loop_device *lo, struct switch_request *p)
{
struct file *file = p->file;
struct file *old_file = lo->lo_backing_file;
struct address_space *mapping = file->f_mapping;
struct address_space *mapping;

/* if no new file, only flush of queued bios requested */
if (!file)
goto out;

mapping = file->f_mapping;
mapping_set_gfp_mask(old_file->f_mapping, lo->old_gfp_mask);
lo->lo_backing_file = file;
lo->lo_blocksize = S_ISBLK(mapping->host->i_mode) ?
mapping->host->i_bdev->bd_block_size : PAGE_SIZE;
lo->old_gfp_mask = mapping_gfp_mask(mapping);
mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
out:
complete(&p->wait);
}

Expand Down Expand Up @@ -1345,11 +1363,25 @@ static int lo_release(struct gendisk *disk, fmode_t mode)
struct loop_device *lo = disk->private_data;

mutex_lock(&lo->lo_ctl_mutex);
--lo->lo_refcnt;

if ((lo->lo_flags & LO_FLAGS_AUTOCLEAR) && !lo->lo_refcnt)
if (--lo->lo_refcnt)
goto out;

if (lo->lo_flags & LO_FLAGS_AUTOCLEAR) {
/*
* In autoclear mode, stop the loop thread
* and remove configuration after last close.
*/
loop_clr_fd(lo, NULL);
} else {
/*
* Otherwise keep thread (if running) and config,
* but flush possible ongoing bios in thread.
*/
loop_flush(lo);
}

out:
mutex_unlock(&lo->lo_ctl_mutex);

return 0;
Expand Down

0 comments on commit 333ec27

Please sign in to comment.