public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] loop: Flush possible running bios when loop device is released.
@ 2008-12-11 20:37 Milan Broz
  2008-12-12  3:22 ` Andrew Morton
  2008-12-12 11:43 ` Jens Axboe
  0 siblings, 2 replies; 5+ messages in thread
From: Milan Broz @ 2008-12-11 20:37 UTC (permalink / raw)
  To: Linux Kernel Mailing List; +Cc: Jens Axboe, Andrew Morton, Alasdair G Kergon

Flush possible running bios when loop device is released.

When there are still queued bios and reference count
drops to zero, loop device must flush all queued bios.

Otherwise it can lead to situation that caller
closes the device, but some bios are still running
and endio() function call later oopses when uses
unallocated mempool.

This happens for example when running dm-crypt over loop,
here is typical oops backtrace:

 Oops: 0000 [#1] PREEMPT SMP
 EIP is at mempool_free+0x12/0x6b
...
 crypt_dec_pending+0x50/0x54 [dm_crypt]
 crypt_endio+0x9f/0xa7 [dm_crypt]
 crypt_endio+0x0/0xa7 [dm_crypt]
 bio_endio+0x2b/0x2e
 loop_thread+0x37a/0x3b1
 do_lo_send_aops+0x0/0x165
 autoremove_wake_function+0x0/0x33
 loop_thread+0x0/0x3b1
 kthread+0x3b/0x61
 kthread+0x0/0x61
 kernel_thread_helper+0x7/0x10

(But crash is reproducible with different dm targets 
running over loop device too.)

Patch fixes it by flushing the bios in release call,
reusing the flush mechanism for switching backing store.

Signed-off-by: Milan Broz <mbroz@redhat.com>
---
 drivers/block/loop.c |   17 ++++++++++++++++-
 1 files changed, 16 insertions(+), 1 deletions(-)

diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 5c4ee70..0ccf2ae 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -624,20 +624,33 @@ static int loop_switch(struct loop_device *lo, struct file *file)
 }
 
 /*
+ * Helper to flush the IOs in loop, but keeping loop thread running
+ */
+static int loop_flush(struct loop_device *lo)
+{
+	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 (!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);
 }
 
@@ -1347,6 +1360,8 @@ static int lo_release(struct gendisk *disk, fmode_t mode)
 
 	if ((lo->lo_flags & LO_FLAGS_AUTOCLEAR) && !lo->lo_refcnt)
 		loop_clr_fd(lo, NULL);
+	else if (!lo->lo_refcnt && lo->lo_thread)
+		loop_flush(lo);
 
 	mutex_unlock(&lo->lo_ctl_mutex);
 



^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2008-12-12 13:46 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-12-11 20:37 [PATCH] loop: Flush possible running bios when loop device is released Milan Broz
2008-12-12  3:22 ` Andrew Morton
2008-12-12 11:43 ` Jens Axboe
2008-12-12 13:43   ` [PATCH v2] " Milan Broz
2008-12-12 13:46     ` Jens Axboe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox