diff options
Diffstat (limited to 'fs/f2fs/gc.c')
-rw-r--r-- | fs/f2fs/gc.c | 42 |
1 files changed, 21 insertions, 21 deletions
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 14961593e93c..35f9b1a196aa 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c | |||
@@ -76,7 +76,9 @@ static int gc_thread_func(void *data) | |||
76 | else | 76 | else |
77 | wait_ms = increase_sleep_time(wait_ms); | 77 | wait_ms = increase_sleep_time(wait_ms); |
78 | 78 | ||
79 | #ifdef CONFIG_F2FS_STAT_FS | ||
79 | sbi->bg_gc++; | 80 | sbi->bg_gc++; |
81 | #endif | ||
80 | 82 | ||
81 | /* if return value is not zero, no victim was selected */ | 83 | /* if return value is not zero, no victim was selected */ |
82 | if (f2fs_gc(sbi)) | 84 | if (f2fs_gc(sbi)) |
@@ -89,23 +91,28 @@ int start_gc_thread(struct f2fs_sb_info *sbi) | |||
89 | { | 91 | { |
90 | struct f2fs_gc_kthread *gc_th; | 92 | struct f2fs_gc_kthread *gc_th; |
91 | dev_t dev = sbi->sb->s_bdev->bd_dev; | 93 | dev_t dev = sbi->sb->s_bdev->bd_dev; |
94 | int err = 0; | ||
92 | 95 | ||
93 | if (!test_opt(sbi, BG_GC)) | 96 | if (!test_opt(sbi, BG_GC)) |
94 | return 0; | 97 | goto out; |
95 | gc_th = kmalloc(sizeof(struct f2fs_gc_kthread), GFP_KERNEL); | 98 | gc_th = kmalloc(sizeof(struct f2fs_gc_kthread), GFP_KERNEL); |
96 | if (!gc_th) | 99 | if (!gc_th) { |
97 | return -ENOMEM; | 100 | err = -ENOMEM; |
101 | goto out; | ||
102 | } | ||
98 | 103 | ||
99 | sbi->gc_thread = gc_th; | 104 | sbi->gc_thread = gc_th; |
100 | init_waitqueue_head(&sbi->gc_thread->gc_wait_queue_head); | 105 | init_waitqueue_head(&sbi->gc_thread->gc_wait_queue_head); |
101 | sbi->gc_thread->f2fs_gc_task = kthread_run(gc_thread_func, sbi, | 106 | sbi->gc_thread->f2fs_gc_task = kthread_run(gc_thread_func, sbi, |
102 | "f2fs_gc-%u:%u", MAJOR(dev), MINOR(dev)); | 107 | "f2fs_gc-%u:%u", MAJOR(dev), MINOR(dev)); |
103 | if (IS_ERR(gc_th->f2fs_gc_task)) { | 108 | if (IS_ERR(gc_th->f2fs_gc_task)) { |
109 | err = PTR_ERR(gc_th->f2fs_gc_task); | ||
104 | kfree(gc_th); | 110 | kfree(gc_th); |
105 | sbi->gc_thread = NULL; | 111 | sbi->gc_thread = NULL; |
106 | return -ENOMEM; | ||
107 | } | 112 | } |
108 | return 0; | 113 | |
114 | out: | ||
115 | return err; | ||
109 | } | 116 | } |
110 | 117 | ||
111 | void stop_gc_thread(struct f2fs_sb_info *sbi) | 118 | void stop_gc_thread(struct f2fs_sb_info *sbi) |
@@ -234,14 +241,14 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi, | |||
234 | { | 241 | { |
235 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); | 242 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); |
236 | struct victim_sel_policy p; | 243 | struct victim_sel_policy p; |
237 | unsigned int secno; | 244 | unsigned int secno, max_cost; |
238 | int nsearched = 0; | 245 | int nsearched = 0; |
239 | 246 | ||
240 | p.alloc_mode = alloc_mode; | 247 | p.alloc_mode = alloc_mode; |
241 | select_policy(sbi, gc_type, type, &p); | 248 | select_policy(sbi, gc_type, type, &p); |
242 | 249 | ||
243 | p.min_segno = NULL_SEGNO; | 250 | p.min_segno = NULL_SEGNO; |
244 | p.min_cost = get_max_cost(sbi, &p); | 251 | p.min_cost = max_cost = get_max_cost(sbi, &p); |
245 | 252 | ||
246 | mutex_lock(&dirty_i->seglist_lock); | 253 | mutex_lock(&dirty_i->seglist_lock); |
247 | 254 | ||
@@ -280,7 +287,7 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi, | |||
280 | p.min_cost = cost; | 287 | p.min_cost = cost; |
281 | } | 288 | } |
282 | 289 | ||
283 | if (cost == get_max_cost(sbi, &p)) | 290 | if (cost == max_cost) |
284 | continue; | 291 | continue; |
285 | 292 | ||
286 | if (nsearched++ >= MAX_VICTIM_SEARCH) { | 293 | if (nsearched++ >= MAX_VICTIM_SEARCH) { |
@@ -288,8 +295,8 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi, | |||
288 | break; | 295 | break; |
289 | } | 296 | } |
290 | } | 297 | } |
291 | got_it: | ||
292 | if (p.min_segno != NULL_SEGNO) { | 298 | if (p.min_segno != NULL_SEGNO) { |
299 | got_it: | ||
293 | if (p.alloc_mode == LFS) { | 300 | if (p.alloc_mode == LFS) { |
294 | secno = GET_SECNO(sbi, p.min_segno); | 301 | secno = GET_SECNO(sbi, p.min_segno); |
295 | if (gc_type == FG_GC) | 302 | if (gc_type == FG_GC) |
@@ -314,28 +321,21 @@ static const struct victim_selection default_v_ops = { | |||
314 | 321 | ||
315 | static struct inode *find_gc_inode(nid_t ino, struct list_head *ilist) | 322 | static struct inode *find_gc_inode(nid_t ino, struct list_head *ilist) |
316 | { | 323 | { |
317 | struct list_head *this; | ||
318 | struct inode_entry *ie; | 324 | struct inode_entry *ie; |
319 | 325 | ||
320 | list_for_each(this, ilist) { | 326 | list_for_each_entry(ie, ilist, list) |
321 | ie = list_entry(this, struct inode_entry, list); | ||
322 | if (ie->inode->i_ino == ino) | 327 | if (ie->inode->i_ino == ino) |
323 | return ie->inode; | 328 | return ie->inode; |
324 | } | ||
325 | return NULL; | 329 | return NULL; |
326 | } | 330 | } |
327 | 331 | ||
328 | static void add_gc_inode(struct inode *inode, struct list_head *ilist) | 332 | static void add_gc_inode(struct inode *inode, struct list_head *ilist) |
329 | { | 333 | { |
330 | struct list_head *this; | 334 | struct inode_entry *new_ie; |
331 | struct inode_entry *new_ie, *ie; | ||
332 | 335 | ||
333 | list_for_each(this, ilist) { | 336 | if (inode == find_gc_inode(inode->i_ino, ilist)) { |
334 | ie = list_entry(this, struct inode_entry, list); | 337 | iput(inode); |
335 | if (ie->inode == inode) { | 338 | return; |
336 | iput(inode); | ||
337 | return; | ||
338 | } | ||
339 | } | 339 | } |
340 | repeat: | 340 | repeat: |
341 | new_ie = kmem_cache_alloc(winode_slab, GFP_NOFS); | 341 | new_ie = kmem_cache_alloc(winode_slab, GFP_NOFS); |