diff options
author | Prasad Joshi <prasadjoshi.linux@gmail.com> | 2012-01-28 01:06:06 -0500 |
---|---|---|
committer | Prasad Joshi <prasadjoshi.linux@gmail.com> | 2012-01-28 01:06:06 -0500 |
commit | 13ced29cb28996a9bc4f68e43ff0c57eafdb1e21 (patch) | |
tree | 7c5b11f5e5124fa4d0642281880b4c558b9e5fec /fs | |
parent | 934eed395d201bf0901ca0c0cc3703b18729d0ce (diff) |
logfs: take write mutex lock during fsync and sync
LogFS uses super->s_write_mutex while writing data to disk. Taking the
same mutex lock in sync and fsync code path solves the following BUG:
------------[ cut here ]------------
kernel BUG at /home/prasad/logfs/dev_bdev.c:134!
Pid: 2387, comm: flush-253:16 Not tainted 3.0.0+ #4 Bochs Bochs
RIP: 0010:[<ffffffffa007deed>] [<ffffffffa007deed>]
bdev_writeseg+0x25d/0x270 [logfs]
Call Trace:
[<ffffffffa007c381>] logfs_open_area+0x91/0x150 [logfs]
[<ffffffff8128dcb2>] ? find_level.clone.9+0x62/0x100
[<ffffffffa007c49c>] __logfs_segment_write.clone.20+0x5c/0x190 [logfs]
[<ffffffff810ef005>] ? mempool_kmalloc+0x15/0x20
[<ffffffff810ef383>] ? mempool_alloc+0x53/0x130
[<ffffffffa007c7a4>] logfs_segment_write+0x1d4/0x230 [logfs]
[<ffffffffa0078f8e>] logfs_write_i0+0x12e/0x190 [logfs]
[<ffffffffa0079300>] __logfs_write_rec+0x140/0x220 [logfs]
[<ffffffffa0079444>] logfs_write_rec+0x64/0xd0 [logfs]
[<ffffffffa00795b6>] __logfs_write_buf+0x106/0x110 [logfs]
[<ffffffffa007a13e>] logfs_write_buf+0x4e/0x80 [logfs]
[<ffffffffa0073e33>] __logfs_writepage+0x23/0x80 [logfs]
[<ffffffffa007410c>] logfs_writepage+0xdc/0x110 [logfs]
[<ffffffff810f5ba7>] __writepage+0x17/0x40
[<ffffffff810f6208>] write_cache_pages+0x208/0x4f0
[<ffffffff810f5b90>] ? set_page_dirty+0x70/0x70
[<ffffffff810f653a>] generic_writepages+0x4a/0x70
[<ffffffff810f75d1>] do_writepages+0x21/0x40
[<ffffffff8116b9d1>] writeback_single_inode+0x101/0x250
[<ffffffff8116bdbd>] writeback_sb_inodes+0xed/0x1c0
[<ffffffff8116c5fb>] writeback_inodes_wb+0x7b/0x1e0
[<ffffffff8116cc23>] wb_writeback+0x4c3/0x530
[<ffffffff814d984d>] ? sub_preempt_count+0x9d/0xd0
[<ffffffff8116cd6b>] wb_do_writeback+0xdb/0x290
[<ffffffff814d984d>] ? sub_preempt_count+0x9d/0xd0
[<ffffffff814d6208>] ? _raw_spin_unlock_irqrestore+0x18/0x40
[<ffffffff8105aa5a>] ? del_timer+0x8a/0x120
[<ffffffff8116cfac>] bdi_writeback_thread+0x8c/0x2e0
[<ffffffff8116cf20>] ? wb_do_writeback+0x290/0x290
[<ffffffff8106d2e6>] kthread+0x96/0xa0
[<ffffffff814de514>] kernel_thread_helper+0x4/0x10
[<ffffffff8106d250>] ? kthread_worker_fn+0x190/0x190
[<ffffffff814de510>] ? gs_change+0xb/0xb
RIP [<ffffffffa007deed>] bdev_writeseg+0x25d/0x270 [logfs]
---[ end trace 0211ad60a57657c4 ]---
Reviewed-by: Joern Engel <joern@logfs.org>
Signed-off-by: Prasad Joshi <prasadjoshi.linux@gmail.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/logfs/file.c | 2 | ||||
-rw-r--r-- | fs/logfs/inode.c | 2 | ||||
-rw-r--r-- | fs/logfs/logfs.h | 2 | ||||
-rw-r--r-- | fs/logfs/readwrite.c | 6 |
4 files changed, 8 insertions, 4 deletions
diff --git a/fs/logfs/file.c b/fs/logfs/file.c index b548c87a86f1..3886cded283c 100644 --- a/fs/logfs/file.c +++ b/fs/logfs/file.c | |||
@@ -230,7 +230,9 @@ int logfs_fsync(struct file *file, loff_t start, loff_t end, int datasync) | |||
230 | return ret; | 230 | return ret; |
231 | 231 | ||
232 | mutex_lock(&inode->i_mutex); | 232 | mutex_lock(&inode->i_mutex); |
233 | logfs_get_wblocks(sb, NULL, WF_LOCK); | ||
233 | logfs_write_anchor(sb); | 234 | logfs_write_anchor(sb); |
235 | logfs_put_wblocks(sb, NULL, WF_LOCK); | ||
234 | mutex_unlock(&inode->i_mutex); | 236 | mutex_unlock(&inode->i_mutex); |
235 | 237 | ||
236 | return 0; | 238 | return 0; |
diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c index 7e441ad5f792..388d7c5a7bed 100644 --- a/fs/logfs/inode.c +++ b/fs/logfs/inode.c | |||
@@ -364,7 +364,9 @@ static void logfs_init_once(void *_li) | |||
364 | 364 | ||
365 | static int logfs_sync_fs(struct super_block *sb, int wait) | 365 | static int logfs_sync_fs(struct super_block *sb, int wait) |
366 | { | 366 | { |
367 | logfs_get_wblocks(sb, NULL, WF_LOCK); | ||
367 | logfs_write_anchor(sb); | 368 | logfs_write_anchor(sb); |
369 | logfs_put_wblocks(sb, NULL, WF_LOCK); | ||
368 | return 0; | 370 | return 0; |
369 | } | 371 | } |
370 | 372 | ||
diff --git a/fs/logfs/logfs.h b/fs/logfs/logfs.h index 398ecff6e548..bb4340850c1b 100644 --- a/fs/logfs/logfs.h +++ b/fs/logfs/logfs.h | |||
@@ -577,6 +577,8 @@ void initialize_block_counters(struct page *page, struct logfs_block *block, | |||
577 | __be64 *array, int page_is_empty); | 577 | __be64 *array, int page_is_empty); |
578 | int logfs_exist_block(struct inode *inode, u64 bix); | 578 | int logfs_exist_block(struct inode *inode, u64 bix); |
579 | int get_page_reserve(struct inode *inode, struct page *page); | 579 | int get_page_reserve(struct inode *inode, struct page *page); |
580 | void logfs_get_wblocks(struct super_block *sb, struct page *page, int lock); | ||
581 | void logfs_put_wblocks(struct super_block *sb, struct page *page, int lock); | ||
580 | extern struct logfs_block_ops indirect_block_ops; | 582 | extern struct logfs_block_ops indirect_block_ops; |
581 | 583 | ||
582 | /* segment.c */ | 584 | /* segment.c */ |
diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c index 6d663e8ea6da..7b10e8aecced 100644 --- a/fs/logfs/readwrite.c +++ b/fs/logfs/readwrite.c | |||
@@ -244,8 +244,7 @@ static void preunlock_page(struct super_block *sb, struct page *page, int lock) | |||
244 | * is waiting for s_write_mutex. We annotate this fact by setting PG_pre_locked | 244 | * is waiting for s_write_mutex. We annotate this fact by setting PG_pre_locked |
245 | * in addition to PG_locked. | 245 | * in addition to PG_locked. |
246 | */ | 246 | */ |
247 | static void logfs_get_wblocks(struct super_block *sb, struct page *page, | 247 | void logfs_get_wblocks(struct super_block *sb, struct page *page, int lock) |
248 | int lock) | ||
249 | { | 248 | { |
250 | struct logfs_super *super = logfs_super(sb); | 249 | struct logfs_super *super = logfs_super(sb); |
251 | 250 | ||
@@ -260,8 +259,7 @@ static void logfs_get_wblocks(struct super_block *sb, struct page *page, | |||
260 | } | 259 | } |
261 | } | 260 | } |
262 | 261 | ||
263 | static void logfs_put_wblocks(struct super_block *sb, struct page *page, | 262 | void logfs_put_wblocks(struct super_block *sb, struct page *page, int lock) |
264 | int lock) | ||
265 | { | 263 | { |
266 | struct logfs_super *super = logfs_super(sb); | 264 | struct logfs_super *super = logfs_super(sb); |
267 | 265 | ||