diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-01-25 15:34:27 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-01-25 15:34:27 -0500 |
commit | 74790147fb4e9b71083a62a525ab283a275d63b7 (patch) | |
tree | 2805293e7f1806ce2fd804255f868ab94edeae88 /fs/f2fs/gc.c | |
parent | f6dcf8e747a0723ace5275334bacfcd88ab39333 (diff) | |
parent | 949db153b6466c6f7cad5a427ecea94985927311 (diff) |
Merge 3.8-rc5 into char-misc-next
This pulls in all of the 3.8-rc5 fixes into this branch so we can test easier.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/f2fs/gc.c')
-rw-r--r-- | fs/f2fs/gc.c | 68 |
1 files changed, 27 insertions, 41 deletions
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index b0ec721e984a..c386910dacc5 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c | |||
@@ -78,7 +78,7 @@ static int gc_thread_func(void *data) | |||
78 | 78 | ||
79 | sbi->bg_gc++; | 79 | sbi->bg_gc++; |
80 | 80 | ||
81 | if (f2fs_gc(sbi, 1) == GC_NONE) | 81 | if (f2fs_gc(sbi) == GC_NONE) |
82 | wait_ms = GC_THREAD_NOGC_SLEEP_TIME; | 82 | wait_ms = GC_THREAD_NOGC_SLEEP_TIME; |
83 | else if (wait_ms == GC_THREAD_NOGC_SLEEP_TIME) | 83 | else if (wait_ms == GC_THREAD_NOGC_SLEEP_TIME) |
84 | wait_ms = GC_THREAD_MAX_SLEEP_TIME; | 84 | wait_ms = GC_THREAD_MAX_SLEEP_TIME; |
@@ -424,7 +424,11 @@ next_step: | |||
424 | } | 424 | } |
425 | 425 | ||
426 | /* | 426 | /* |
427 | * Calculate start block index that this node page contains | 427 | * Calculate start block index indicating the given node offset. |
428 | * Be careful, caller should give this node offset only indicating direct node | ||
429 | * blocks. If any node offsets, which point the other types of node blocks such | ||
430 | * as indirect or double indirect node blocks, are given, it must be a caller's | ||
431 | * bug. | ||
428 | */ | 432 | */ |
429 | block_t start_bidx_of_node(unsigned int node_ofs) | 433 | block_t start_bidx_of_node(unsigned int node_ofs) |
430 | { | 434 | { |
@@ -651,62 +655,44 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, unsigned int segno, | |||
651 | return ret; | 655 | return ret; |
652 | } | 656 | } |
653 | 657 | ||
654 | int f2fs_gc(struct f2fs_sb_info *sbi, int nGC) | 658 | int f2fs_gc(struct f2fs_sb_info *sbi) |
655 | { | 659 | { |
656 | unsigned int segno; | ||
657 | int old_free_secs, cur_free_secs; | ||
658 | int gc_status, nfree; | ||
659 | struct list_head ilist; | 660 | struct list_head ilist; |
661 | unsigned int segno, i; | ||
660 | int gc_type = BG_GC; | 662 | int gc_type = BG_GC; |
663 | int gc_status = GC_NONE; | ||
661 | 664 | ||
662 | INIT_LIST_HEAD(&ilist); | 665 | INIT_LIST_HEAD(&ilist); |
663 | gc_more: | 666 | gc_more: |
664 | nfree = 0; | 667 | if (!(sbi->sb->s_flags & MS_ACTIVE)) |
665 | gc_status = GC_NONE; | 668 | goto stop; |
666 | 669 | ||
667 | if (has_not_enough_free_secs(sbi)) | 670 | if (has_not_enough_free_secs(sbi)) |
668 | old_free_secs = reserved_sections(sbi); | 671 | gc_type = FG_GC; |
669 | else | ||
670 | old_free_secs = free_sections(sbi); | ||
671 | |||
672 | while (sbi->sb->s_flags & MS_ACTIVE) { | ||
673 | int i; | ||
674 | if (has_not_enough_free_secs(sbi)) | ||
675 | gc_type = FG_GC; | ||
676 | 672 | ||
677 | cur_free_secs = free_sections(sbi) + nfree; | 673 | if (!__get_victim(sbi, &segno, gc_type, NO_CHECK_TYPE)) |
674 | goto stop; | ||
678 | 675 | ||
679 | /* We got free space successfully. */ | 676 | for (i = 0; i < sbi->segs_per_sec; i++) { |
680 | if (nGC < cur_free_secs - old_free_secs) | 677 | /* |
681 | break; | 678 | * do_garbage_collect will give us three gc_status: |
682 | 679 | * GC_ERROR, GC_DONE, and GC_BLOCKED. | |
683 | if (!__get_victim(sbi, &segno, gc_type, NO_CHECK_TYPE)) | 680 | * If GC is finished uncleanly, we have to return |
681 | * the victim to dirty segment list. | ||
682 | */ | ||
683 | gc_status = do_garbage_collect(sbi, segno + i, &ilist, gc_type); | ||
684 | if (gc_status != GC_DONE) | ||
684 | break; | 685 | break; |
685 | |||
686 | for (i = 0; i < sbi->segs_per_sec; i++) { | ||
687 | /* | ||
688 | * do_garbage_collect will give us three gc_status: | ||
689 | * GC_ERROR, GC_DONE, and GC_BLOCKED. | ||
690 | * If GC is finished uncleanly, we have to return | ||
691 | * the victim to dirty segment list. | ||
692 | */ | ||
693 | gc_status = do_garbage_collect(sbi, segno + i, | ||
694 | &ilist, gc_type); | ||
695 | if (gc_status != GC_DONE) | ||
696 | goto stop; | ||
697 | nfree++; | ||
698 | } | ||
699 | } | 686 | } |
700 | stop: | 687 | if (has_not_enough_free_secs(sbi)) { |
701 | if (has_not_enough_free_secs(sbi) || gc_status == GC_BLOCKED) { | ||
702 | write_checkpoint(sbi, (gc_status == GC_BLOCKED), false); | 688 | write_checkpoint(sbi, (gc_status == GC_BLOCKED), false); |
703 | if (nfree) | 689 | if (has_not_enough_free_secs(sbi)) |
704 | goto gc_more; | 690 | goto gc_more; |
705 | } | 691 | } |
692 | stop: | ||
706 | mutex_unlock(&sbi->gc_mutex); | 693 | mutex_unlock(&sbi->gc_mutex); |
707 | 694 | ||
708 | put_gc_inode(&ilist); | 695 | put_gc_inode(&ilist); |
709 | BUG_ON(!list_empty(&ilist)); | ||
710 | return gc_status; | 696 | return gc_status; |
711 | } | 697 | } |
712 | 698 | ||
@@ -715,7 +701,7 @@ void build_gc_manager(struct f2fs_sb_info *sbi) | |||
715 | DIRTY_I(sbi)->v_ops = &default_v_ops; | 701 | DIRTY_I(sbi)->v_ops = &default_v_ops; |
716 | } | 702 | } |
717 | 703 | ||
718 | int create_gc_caches(void) | 704 | int __init create_gc_caches(void) |
719 | { | 705 | { |
720 | winode_slab = f2fs_kmem_cache_create("f2fs_gc_inodes", | 706 | winode_slab = f2fs_kmem_cache_create("f2fs_gc_inodes", |
721 | sizeof(struct inode_entry), NULL); | 707 | sizeof(struct inode_entry), NULL); |