diff options
author | Prasad Joshi <prasadjoshi.linux@gmail.com> | 2011-10-02 14:16:51 -0400 |
---|---|---|
committer | Prasad Joshi <prasadjoshi.linux@gmail.com> | 2012-01-28 01:08:25 -0500 |
commit | 0bd90387ed5a8abbcf43391b480efdc211721cfe (patch) | |
tree | ce92c57f4a56b601a694a0d50e5b2834065f42c1 /fs | |
parent | ecfd890991a26e70547e025673580923a004c5e4 (diff) |
logfs: Propagate page parameter to __logfs_write_inode
During GC LogFS has to rewrite each valid block to a separate segment.
Rewrite operation reads data from an old segment and writes it to a
newly allocated segment. Since every write operation changes data
block pointers maintained in inode, inode should also be rewritten.
In GC path to avoid AB-BA deadlock LogFS marks a page with
PG_pre_locked in addition to locking the page (PG_locked). The page
lock is ignored iff the page is pre-locked.
LogFS uses a special file called segment file. The segment file
maintains an 8 bytes entry for every segment. It keeps track of erase
count, level etc. for every segment.
Bad things happen with a segment belonging to the segment file is GCed
------------[ cut here ]------------
kernel BUG at /home/prasad/logfs/readwrite.c:297!
invalid opcode: 0000 [#1] SMP
Modules linked in: logfs joydev usbhid hid psmouse e1000 i2c_piix4
serio_raw [last unloaded: logfs]
Pid: 20161, comm: mount Not tainted 3.1.0-rc3+ #3 innotek GmbH
VirtualBox
EIP: 0060:[<f809132a>] EFLAGS: 00010292 CPU: 0
EIP is at logfs_lock_write_page+0x6a/0x70 [logfs]
EAX: 00000027 EBX: f73f5b20 ECX: c16007c8 EDX: 00000094
ESI: 00000000 EDI: e59be6e4 EBP: c7337b28 ESP: c7337b18
DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
Process mount (pid: 20161, ti=c7336000 task=eb323f70 task.ti=c7336000)
Stack:
f8099a3d c7337b24 f73f5b20 00001002 c7337b50 f8091f6d f8099a4d f80994e4
00000003 00000000 c7337b68 00000000 c67e4400 00001000 c7337b80 f80935e5
00000000 00000000 00000000 00000000 e1fcf000 0000000f e59be618 c70bf900
Call Trace:
[<f8091f6d>] logfs_get_write_page.clone.16+0xdd/0x100 [logfs]
[<f80935e5>] logfs_mod_segment_entry+0x55/0x110 [logfs]
[<f809460d>] logfs_get_segment_entry+0x1d/0x20 [logfs]
[<f8091060>] ? logfs_cleanup_journal+0x50/0x50 [logfs]
[<f809521b>] ostore_get_erase_count+0x1b/0x40 [logfs]
[<f80965b8>] logfs_open_area+0xc8/0x150 [logfs]
[<c141a7ec>] ? kmemleak_alloc+0x2c/0x60
[<f809668e>] __logfs_segment_write.clone.16+0x4e/0x1b0 [logfs]
[<c10dd563>] ? mempool_kmalloc+0x13/0x20
[<c10dd563>] ? mempool_kmalloc+0x13/0x20
[<f809696f>] logfs_segment_write+0x17f/0x1d0 [logfs]
[<f8092e8c>] logfs_write_i0+0x11c/0x180 [logfs]
[<f8092f35>] logfs_write_direct+0x45/0x90 [logfs]
[<f80934cd>] __logfs_write_buf+0xbd/0xf0 [logfs]
[<c102900e>] ? kmap_atomic_prot+0x4e/0xe0
[<f809424b>] logfs_write_buf+0x3b/0x60 [logfs]
[<f80947a9>] __logfs_write_inode+0xa9/0x110 [logfs]
[<f8094cb0>] logfs_rewrite_block+0xc0/0x110 [logfs]
[<f8095300>] ? get_mapping_page+0x10/0x60 [logfs]
[<f8095aa0>] ? logfs_load_object_aliases+0x2e0/0x2f0 [logfs]
[<f808e57d>] logfs_gc_segment+0x2ad/0x310 [logfs]
[<f808e62a>] __logfs_gc_once+0x4a/0x80 [logfs]
[<f808ed43>] logfs_gc_pass+0x683/0x6a0 [logfs]
[<f8097a89>] logfs_mount+0x5a9/0x680 [logfs]
[<c1126b21>] mount_fs+0x21/0xd0
[<c10f6f6f>] ? __alloc_percpu+0xf/0x20
[<c113da41>] ? alloc_vfsmnt+0xb1/0x130
[<c113db4b>] vfs_kern_mount+0x4b/0xa0
[<c113e06e>] do_kern_mount+0x3e/0xe0
[<c113f60d>] do_mount+0x34d/0x670
[<c10f2749>] ? strndup_user+0x49/0x70
[<c113fcab>] sys_mount+0x6b/0xa0
[<c142d87c>] syscall_call+0x7/0xb
Code: f8 e8 8b 93 39 c9 8b 45 f8 3e 0f ba 28 00 19 d2 85 d2 74 ca eb d0 0f 0b 8d 45 fc 89 44 24 04 c7 04 24 3d 9a 09 f8 e8 09 92 39 c9 <0f> 0b 8d 74 26 00 55 89 e5 3e 8d 74 26 00 8b 10 80 e6 01 74 09
EIP: [<f809132a>] logfs_lock_write_page+0x6a/0x70 [logfs] SS:ESP 0068:c7337b18
---[ end trace 96e67d5b3aa3d6ca ]---
The patch passes locked page to __logfs_write_inode. It calls function
logfs_get_wblocks() to pre-lock the page. This ensures any further
attempts to lock the page are ignored (esp from get_erase_count).
Acked-by: Joern Engel <joern@logfs.org>
Signed-off-by: Prasad Joshi <prasadjoshi.linux@gmail.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/logfs/dir.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 | 12 |
4 files changed, 9 insertions, 9 deletions
diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c index b7d7f67cee5..b6404898da8 100644 --- a/fs/logfs/dir.c +++ b/fs/logfs/dir.c | |||
@@ -71,7 +71,7 @@ static int write_dir(struct inode *dir, struct logfs_disk_dentry *dd, | |||
71 | 71 | ||
72 | static int write_inode(struct inode *inode) | 72 | static int write_inode(struct inode *inode) |
73 | { | 73 | { |
74 | return __logfs_write_inode(inode, WF_LOCK); | 74 | return __logfs_write_inode(inode, NULL, WF_LOCK); |
75 | } | 75 | } |
76 | 76 | ||
77 | static s64 dir_seek_data(struct inode *inode, s64 pos) | 77 | static s64 dir_seek_data(struct inode *inode, s64 pos) |
diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c index 388d7c5a7be..7c42c132c17 100644 --- a/fs/logfs/inode.c +++ b/fs/logfs/inode.c | |||
@@ -287,7 +287,7 @@ static int logfs_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
287 | if (logfs_inode(inode)->li_flags & LOGFS_IF_STILLBORN) | 287 | if (logfs_inode(inode)->li_flags & LOGFS_IF_STILLBORN) |
288 | return 0; | 288 | return 0; |
289 | 289 | ||
290 | ret = __logfs_write_inode(inode, flags); | 290 | ret = __logfs_write_inode(inode, NULL, flags); |
291 | LOGFS_BUG_ON(ret, inode->i_sb); | 291 | LOGFS_BUG_ON(ret, inode->i_sb); |
292 | return ret; | 292 | return ret; |
293 | } | 293 | } |
diff --git a/fs/logfs/logfs.h b/fs/logfs/logfs.h index bb4340850c1..0dec29887a8 100644 --- a/fs/logfs/logfs.h +++ b/fs/logfs/logfs.h | |||
@@ -528,7 +528,7 @@ void logfs_destroy_inode_cache(void); | |||
528 | void logfs_set_blocks(struct inode *inode, u64 no); | 528 | void logfs_set_blocks(struct inode *inode, u64 no); |
529 | /* these logically belong into inode.c but actually reside in readwrite.c */ | 529 | /* these logically belong into inode.c but actually reside in readwrite.c */ |
530 | int logfs_read_inode(struct inode *inode); | 530 | int logfs_read_inode(struct inode *inode); |
531 | int __logfs_write_inode(struct inode *inode, long flags); | 531 | int __logfs_write_inode(struct inode *inode, struct page *, long flags); |
532 | void logfs_evict_inode(struct inode *inode); | 532 | void logfs_evict_inode(struct inode *inode); |
533 | 533 | ||
534 | /* journal.c */ | 534 | /* journal.c */ |
diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c index 7b10e8aecce..88284c67ba9 100644 --- a/fs/logfs/readwrite.c +++ b/fs/logfs/readwrite.c | |||
@@ -422,7 +422,7 @@ static void inode_write_block(struct logfs_block *block) | |||
422 | if (inode->i_ino == LOGFS_INO_MASTER) | 422 | if (inode->i_ino == LOGFS_INO_MASTER) |
423 | logfs_write_anchor(inode->i_sb); | 423 | logfs_write_anchor(inode->i_sb); |
424 | else { | 424 | else { |
425 | ret = __logfs_write_inode(inode, 0); | 425 | ret = __logfs_write_inode(inode, NULL, 0); |
426 | /* see indirect_write_block comment */ | 426 | /* see indirect_write_block comment */ |
427 | BUG_ON(ret); | 427 | BUG_ON(ret); |
428 | } | 428 | } |
@@ -1629,7 +1629,7 @@ int logfs_rewrite_block(struct inode *inode, u64 bix, u64 ofs, | |||
1629 | if (inode->i_ino == LOGFS_INO_MASTER) | 1629 | if (inode->i_ino == LOGFS_INO_MASTER) |
1630 | logfs_write_anchor(inode->i_sb); | 1630 | logfs_write_anchor(inode->i_sb); |
1631 | else { | 1631 | else { |
1632 | err = __logfs_write_inode(inode, flags); | 1632 | err = __logfs_write_inode(inode, page, flags); |
1633 | } | 1633 | } |
1634 | } | 1634 | } |
1635 | } | 1635 | } |
@@ -1879,7 +1879,7 @@ int logfs_truncate(struct inode *inode, u64 target) | |||
1879 | logfs_get_wblocks(sb, NULL, 1); | 1879 | logfs_get_wblocks(sb, NULL, 1); |
1880 | err = __logfs_truncate(inode, size); | 1880 | err = __logfs_truncate(inode, size); |
1881 | if (!err) | 1881 | if (!err) |
1882 | err = __logfs_write_inode(inode, 0); | 1882 | err = __logfs_write_inode(inode, NULL, 0); |
1883 | logfs_put_wblocks(sb, NULL, 1); | 1883 | logfs_put_wblocks(sb, NULL, 1); |
1884 | } | 1884 | } |
1885 | 1885 | ||
@@ -2119,14 +2119,14 @@ void logfs_set_segment_unreserved(struct super_block *sb, u32 segno, u32 ec) | |||
2119 | ec_level); | 2119 | ec_level); |
2120 | } | 2120 | } |
2121 | 2121 | ||
2122 | int __logfs_write_inode(struct inode *inode, long flags) | 2122 | int __logfs_write_inode(struct inode *inode, struct page *page, long flags) |
2123 | { | 2123 | { |
2124 | struct super_block *sb = inode->i_sb; | 2124 | struct super_block *sb = inode->i_sb; |
2125 | int ret; | 2125 | int ret; |
2126 | 2126 | ||
2127 | logfs_get_wblocks(sb, NULL, flags & WF_LOCK); | 2127 | logfs_get_wblocks(sb, page, flags & WF_LOCK); |
2128 | ret = do_write_inode(inode); | 2128 | ret = do_write_inode(inode); |
2129 | logfs_put_wblocks(sb, NULL, flags & WF_LOCK); | 2129 | logfs_put_wblocks(sb, page, flags & WF_LOCK); |
2130 | return ret; | 2130 | return ret; |
2131 | } | 2131 | } |
2132 | 2132 | ||