summary refs log tree commit diff
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)
downloadlinux-769ec6e5b7d4a8115447736871be8bffaaba3a7d.tar.gz
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 a1af74f1a1d9..2c58c587a3c6 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;