diff options
author | Jaegeuk Kim <jaegeuk@kernel.org> | 2014-12-03 20:47:26 -0800 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2014-12-05 09:51:04 -0800 |
commit | 769ec6e5b7d4a8115447736871be8bffaaba3a7d (patch) | |
tree | 94e1062ffee03b4dc980da82c2da4ec06916b997 /fs/f2fs/checkpoint.c | |
parent | 8b26ef98da3387eb57a8a5c1747c6e628948ee0c (diff) | |
download | linux-769ec6e5b7d4a8115447736871be8bffaaba3a7d.tar.bz2 |
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/checkpoint.c')
-rw-r--r-- | fs/f2fs/checkpoint.c | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 20a917b05b99..6a81b73add06 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -304,6 +304,11 @@ static void __add_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type) struct inode_management *im = &sbi->im[type]; struct ino_entry *e; retry: + if (radix_tree_preload(GFP_NOFS)) { + cond_resched(); + goto retry; + } + spin_lock(&im->ino_lock); e = radix_tree_lookup(&im->ino_root, ino); @@ -311,11 +316,13 @@ retry: e = kmem_cache_alloc(ino_entry_slab, GFP_ATOMIC); if (!e) { spin_unlock(&im->ino_lock); + radix_tree_preload_end(); goto retry; } if (radix_tree_insert(&im->ino_root, ino, e)) { spin_unlock(&im->ino_lock); kmem_cache_free(ino_entry_slab, e); + radix_tree_preload_end(); goto retry; } memset(e, 0, sizeof(struct ino_entry)); @@ -326,6 +333,7 @@ retry: im->ino_num++; } spin_unlock(&im->ino_lock); + radix_tree_preload_end(); } static void __remove_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type) |