summaryrefslogtreecommitdiffstats
path: root/fs/f2fs/gc.c
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk@kernel.org>2014-12-03 20:47:26 -0800
committerJaegeuk Kim <jaegeuk@kernel.org>2014-12-05 09:51:04 -0800
commit769ec6e5b7d4a8115447736871be8bffaaba3a7d (patch)
tree94e1062ffee03b4dc980da82c2da4ec06916b997 /fs/f2fs/gc.c
parent8b26ef98da3387eb57a8a5c1747c6e628948ee0c (diff)
f2fs: call radix_tree_preload before radix_tree_insert
This patch tries to fix: BUG: using smp_processor_id() in preemptible [00000000] code: f2fs_gc-254:0/384 (radix_tree_node_alloc+0x14/0x74) from [<c033d8a0>] (radix_tree_insert+0x110/0x200) (radix_tree_insert+0x110/0x200) from [<c02e8264>] (gc_data_segment+0x340/0x52c) (gc_data_segment+0x340/0x52c) from [<c02e8658>] (f2fs_gc+0x208/0x400) (f2fs_gc+0x208/0x400) from [<c02e8a98>] (gc_thread_func+0x248/0x28c) (gc_thread_func+0x248/0x28c) from [<c0139944>] (kthread+0xa0/0xac) (kthread+0xa0/0xac) from [<c0105ef8>] (ret_from_fork+0x14/0x3c) The reason is that f2fs calls radix_tree_insert under enabled preemption. So, before calling it, we need to call radix_tree_preload. Otherwise, we should use _GFP_WAIT for the radix tree, and use mutex or semaphore to cover the radix tree operations. Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'fs/f2fs/gc.c')
-rw-r--r--fs/f2fs/gc.c6
1 files changed, 2 insertions, 4 deletions
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index a1af74f1a1d..2c58c587a3c 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -351,7 +351,6 @@ static struct inode *find_gc_inode(struct gc_inode_list *gc_list, nid_t ino)
static void add_gc_inode(struct gc_inode_list *gc_list, struct inode *inode)
{
struct inode_entry *new_ie;
- int ret;
if (inode == find_gc_inode(gc_list, inode->i_ino)) {
iput(inode);
@@ -361,8 +360,7 @@ retry:
new_ie = f2fs_kmem_cache_alloc(winode_slab, GFP_NOFS);
new_ie->inode = inode;
- ret = radix_tree_insert(&gc_list->iroot, inode->i_ino, new_ie);
- if (ret) {
+ if (radix_tree_insert(&gc_list->iroot, inode->i_ino, new_ie)) {
kmem_cache_free(winode_slab, new_ie);
goto retry;
}
@@ -703,7 +701,7 @@ int f2fs_gc(struct f2fs_sb_info *sbi)
struct cp_control cpc;
struct gc_inode_list gc_list = {
.ilist = LIST_HEAD_INIT(gc_list.ilist),
- .iroot = RADIX_TREE_INIT(GFP_ATOMIC),
+ .iroot = RADIX_TREE_INIT(GFP_NOFS),
};
cpc.reason = test_opt(sbi, FASTBOOT) ? CP_UMOUNT : CP_SYNC;