Skip to content

Commit 0bd9038

Browse files
committed
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 [raspberrypi#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+ raspberrypi#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 <[email protected]> Signed-off-by: Prasad Joshi <[email protected]>
1 parent ecfd890 commit 0bd9038

File tree

4 files changed

+9
-9
lines changed

4 files changed

+9
-9
lines changed

fs/logfs/dir.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ static int write_dir(struct inode *dir, struct logfs_disk_dentry *dd,
7171

7272
static int write_inode(struct inode *inode)
7373
{
74-
return __logfs_write_inode(inode, WF_LOCK);
74+
return __logfs_write_inode(inode, NULL, WF_LOCK);
7575
}
7676

7777
static s64 dir_seek_data(struct inode *inode, s64 pos)

fs/logfs/inode.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ static int logfs_write_inode(struct inode *inode, struct writeback_control *wbc)
287287
if (logfs_inode(inode)->li_flags & LOGFS_IF_STILLBORN)
288288
return 0;
289289

290-
ret = __logfs_write_inode(inode, flags);
290+
ret = __logfs_write_inode(inode, NULL, flags);
291291
LOGFS_BUG_ON(ret, inode->i_sb);
292292
return ret;
293293
}

fs/logfs/logfs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,7 @@ void logfs_destroy_inode_cache(void);
528528
void logfs_set_blocks(struct inode *inode, u64 no);
529529
/* these logically belong into inode.c but actually reside in readwrite.c */
530530
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);
532532
void logfs_evict_inode(struct inode *inode);
533533

534534
/* journal.c */

fs/logfs/readwrite.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ static void inode_write_block(struct logfs_block *block)
422422
if (inode->i_ino == LOGFS_INO_MASTER)
423423
logfs_write_anchor(inode->i_sb);
424424
else {
425-
ret = __logfs_write_inode(inode, 0);
425+
ret = __logfs_write_inode(inode, NULL, 0);
426426
/* see indirect_write_block comment */
427427
BUG_ON(ret);
428428
}
@@ -1629,7 +1629,7 @@ int logfs_rewrite_block(struct inode *inode, u64 bix, u64 ofs,
16291629
if (inode->i_ino == LOGFS_INO_MASTER)
16301630
logfs_write_anchor(inode->i_sb);
16311631
else {
1632-
err = __logfs_write_inode(inode, flags);
1632+
err = __logfs_write_inode(inode, page, flags);
16331633
}
16341634
}
16351635
}
@@ -1879,7 +1879,7 @@ int logfs_truncate(struct inode *inode, u64 target)
18791879
logfs_get_wblocks(sb, NULL, 1);
18801880
err = __logfs_truncate(inode, size);
18811881
if (!err)
1882-
err = __logfs_write_inode(inode, 0);
1882+
err = __logfs_write_inode(inode, NULL, 0);
18831883
logfs_put_wblocks(sb, NULL, 1);
18841884
}
18851885

@@ -2119,14 +2119,14 @@ void logfs_set_segment_unreserved(struct super_block *sb, u32 segno, u32 ec)
21192119
ec_level);
21202120
}
21212121

2122-
int __logfs_write_inode(struct inode *inode, long flags)
2122+
int __logfs_write_inode(struct inode *inode, struct page *page, long flags)
21232123
{
21242124
struct super_block *sb = inode->i_sb;
21252125
int ret;
21262126

2127-
logfs_get_wblocks(sb, NULL, flags & WF_LOCK);
2127+
logfs_get_wblocks(sb, page, flags & WF_LOCK);
21282128
ret = do_write_inode(inode);
2129-
logfs_put_wblocks(sb, NULL, flags & WF_LOCK);
2129+
logfs_put_wblocks(sb, page, flags & WF_LOCK);
21302130
return ret;
21312131
}
21322132

0 commit comments

Comments
 (0)