aboutsummaryrefslogtreecommitdiffstats
diff options
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-10-23 10:19:56 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-10-23 10:19:56 -0700
commit825b3256d8898c7f5d407d0ad4804e42080d924c (patch)
tree90aeef8e7d802e2e2594491333845939a3989b67
parentca46ec3e9c4635d9f2235ceab459619373f238b5 (diff)
downloadpatches-825b3256d8898c7f5d407d0ad4804e42080d924c.tar.gz
f2fs work
-rw-r--r--f2fs-gc.h-make-should_do_checkpoint-inline.patch26
-rw-r--r--f2fs-move-statistics-code-into-one-file.patch956
-rw-r--r--f2fs_debug10
-rw-r--r--series5
4 files changed, 986 insertions, 11 deletions
diff --git a/f2fs-gc.h-make-should_do_checkpoint-inline.patch b/f2fs-gc.h-make-should_do_checkpoint-inline.patch
new file mode 100644
index 00000000000000..20c4278ce5b4b8
--- /dev/null
+++ b/f2fs-gc.h-make-should_do_checkpoint-inline.patch
@@ -0,0 +1,26 @@
+From foo@baz Tue Oct 23 09:44:29 PDT 2012
+Date: Tue, 23 Oct 2012 09:44:29 -0700
+To: Greg KH <gregkh@linuxfoundation.org>
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Subject: f2fs: gc.h: make should_do_checkpoint() inline
+
+This should be an inline function, not a "real" function. Now other files can
+properly include gc.h.
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/f2fs/gc.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/f2fs/gc.h
++++ b/fs/f2fs/gc.h
+@@ -191,7 +191,7 @@ static inline int is_idle(struct f2fs_sb
+ return !(rl->count[BLK_RW_SYNC]) && !(rl->count[BLK_RW_ASYNC]);
+ }
+
+-static bool should_do_checkpoint(struct f2fs_sb_info *sbi)
++static inline bool should_do_checkpoint(struct f2fs_sb_info *sbi)
+ {
+ unsigned int pages_per_sec = sbi->segs_per_sec *
+ (1 << sbi->log_blocks_per_seg);
diff --git a/f2fs-move-statistics-code-into-one-file.patch b/f2fs-move-statistics-code-into-one-file.patch
new file mode 100644
index 00000000000000..3540d3728f25c3
--- /dev/null
+++ b/f2fs-move-statistics-code-into-one-file.patch
@@ -0,0 +1,956 @@
+From foo@baz Tue Oct 23 10:11:17 PDT 2012
+Date: Tue, 23 Oct 2012 10:11:17 -0700
+To: Greg KH <gregkh@linuxfoundation.org>
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Subject: f2fs: move statistics code into one file
+
+This moves all of the procfs statistics code into one file, debug.c and removes
+the #ifdefs from the core f2fs code when calling statistic functions.
+
+This will make it more obvious how to move from procfs to debugfs, no
+functionality was changed here at all.
+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/f2fs/Makefile | 1
+ fs/f2fs/debug.c | 414 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ fs/f2fs/f2fs.h | 25 ++-
+ fs/f2fs/gc.c | 373 -------------------------------------------------
+ fs/f2fs/super.c | 21 --
+ 5 files changed, 442 insertions(+), 392 deletions(-)
+
+--- a/fs/f2fs/Makefile
++++ b/fs/f2fs/Makefile
+@@ -2,5 +2,6 @@ obj-$(CONFIG_F2FS_FS) += f2fs.o
+
+ f2fs-y := dir.o file.o inode.o namei.o hash.o super.o
+ f2fs-y += checkpoint.o gc.o data.o node.o segment.o recovery.o
++f2fs-$(CONFIG_F2FS_STAT_FS) += debug.o
+ f2fs-$(CONFIG_F2FS_FS_XATTR) += xattr.o
+ f2fs-$(CONFIG_F2FS_FS_POSIX_ACL) += acl.o
+--- /dev/null
++++ b/fs/f2fs/debug.c
+@@ -0,0 +1,414 @@
++/**
++ * f2fs debugging statistics
++ *
++ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
++ * http://www.samsung.com/
++ * Copyright (c) 2012 Linux Foundation
++ * Copyright (c) 2012 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/fs.h>
++#include <linux/backing-dev.h>
++#include <linux/proc_fs.h>
++#include <linux/f2fs_fs.h>
++#include <linux/blkdev.h>
++
++#include "f2fs.h"
++#include "node.h"
++#include "segment.h"
++#include "gc.h"
++
++static LIST_HEAD(f2fs_stat_list);
++static struct proc_dir_entry *f2fs_proc_root;
++
++
++void f2fs_update_stat(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_gc_info *gc_i = sbi->gc_info;
++ struct f2fs_stat_info *si = gc_i->stat_info;
++ int i;
++
++ /* valid check of the segment numbers */
++ si->hit_ext = sbi->read_hit_ext;
++ si->total_ext = sbi->total_hit_ext;
++ si->ndirty_node = get_pages(sbi, F2FS_DIRTY_NODES);
++ si->ndirty_dent = get_pages(sbi, F2FS_DIRTY_DENTS);
++ si->ndirty_dirs = sbi->n_dirty_dirs;
++ si->ndirty_meta = get_pages(sbi, F2FS_DIRTY_META);
++ si->total_count = (int)sbi->user_block_count / sbi->blocks_per_seg;
++ si->rsvd_segs = reserved_segments(sbi);
++ si->overp_segs = overprovision_segments(sbi);
++ si->valid_count = valid_user_blocks(sbi);
++ si->valid_node_count = valid_node_count(sbi);
++ si->valid_inode_count = valid_inode_count(sbi);
++ si->utilization = utilization(sbi);
++
++ si->free_segs = free_segments(sbi);
++ si->free_secs = free_sections(sbi);
++ si->prefree_count = prefree_segments(sbi);
++ si->dirty_count = dirty_segments(sbi);
++ si->node_pages = sbi->node_inode->i_mapping->nrpages;
++ si->meta_pages = sbi->meta_inode->i_mapping->nrpages;
++ si->nats = NM_I(sbi)->nat_cnt;
++ si->sits = SIT_I(sbi)->dirty_sentries;
++ si->fnids = NM_I(sbi)->fcnt;
++ si->bg_gc = sbi->bg_gc;
++ si->util_free = (int)(free_user_blocks(sbi) >> sbi->log_blocks_per_seg)
++ * 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
++ / 2;
++ si->util_valid = (int)(written_block_count(sbi) >>
++ sbi->log_blocks_per_seg)
++ * 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
++ / 2;
++ si->util_invalid = 50 - si->util_free - si->util_valid;
++ for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_NODE; i++) {
++ struct curseg_info *curseg = CURSEG_I(sbi, i);
++ si->curseg[i] = curseg->segno;
++ si->cursec[i] = curseg->segno / sbi->segs_per_sec;
++ si->curzone[i] = si->cursec[i] / sbi->secs_per_zone;
++ }
++
++ for (i = 0; i < 2; i++) {
++ si->segment_count[i] = sbi->segment_count[i];
++ si->block_count[i] = sbi->block_count[i];
++ }
++}
++
++/**
++ * This function calculates BDF of every segments
++ */
++static void f2fs_update_gc_metric(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_gc_info *gc_i = sbi->gc_info;
++ struct f2fs_stat_info *si = gc_i->stat_info;
++ unsigned int blks_per_sec, hblks_per_sec, total_vblocks, bimodal, dist;
++ struct sit_info *sit_i = SIT_I(sbi);
++ unsigned int segno, vblocks;
++ int ndirty = 0;
++
++ bimodal = 0;
++ total_vblocks = 0;
++ blks_per_sec = sbi->segs_per_sec * (1 << sbi->log_blocks_per_seg);
++ hblks_per_sec = blks_per_sec / 2;
++ mutex_lock(&sit_i->sentry_lock);
++ for (segno = 0; segno < TOTAL_SEGS(sbi); segno += sbi->segs_per_sec) {
++ vblocks = get_valid_blocks(sbi, segno, sbi->segs_per_sec);
++ dist = abs(vblocks - hblks_per_sec);
++ bimodal += dist * dist;
++
++ if (vblocks > 0 && vblocks < blks_per_sec) {
++ total_vblocks += vblocks;
++ ndirty++;
++ }
++ }
++ mutex_unlock(&sit_i->sentry_lock);
++ dist = sbi->total_sections * hblks_per_sec * hblks_per_sec / 100;
++ si->bimodal = bimodal / dist;
++ if (si->dirty_count)
++ si->avg_vblocks = total_vblocks / ndirty;
++ else
++ si->avg_vblocks = 0;
++}
++
++static int f2fs_read_gc(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ struct f2fs_gc_info *gc_i, *next;
++ struct f2fs_stat_info *si;
++ char *buf = page;
++ int i = 0;
++
++ list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
++ int j;
++ si = gc_i->stat_info;
++
++ mutex_lock(&si->stat_list);
++ if (!si->sbi) {
++ mutex_unlock(&si->stat_list);
++ continue;
++ }
++ f2fs_update_stat(si->sbi);
++
++ buf += sprintf(buf, "=====[ partition info. #%d ]=====\n", i++);
++ buf += sprintf(buf, "[SB: 1] [CP: 2] [NAT: %d] [SIT: %d] ",
++ si->nat_area_segs, si->sit_area_segs);
++ buf += sprintf(buf, "[SSA: %d] [MAIN: %d",
++ si->ssa_area_segs, si->main_area_segs);
++ buf += sprintf(buf, "(OverProv:%d Resv:%d)]\n\n",
++ si->overp_segs, si->rsvd_segs);
++ buf += sprintf(buf, "Utilization: %d%% (%d valid blocks)\n",
++ si->utilization, si->valid_count);
++ buf += sprintf(buf, " - Node: %u (Inode: %u, ",
++ si->valid_node_count, si->valid_inode_count);
++ buf += sprintf(buf, "Other: %u)\n - Data: %u\n",
++ si->valid_node_count - si->valid_inode_count,
++ si->valid_count - si->valid_node_count);
++ buf += sprintf(buf, "\nMain area: %d segs, %d secs %d zones\n",
++ si->main_area_segs, si->main_area_sections,
++ si->main_area_zones);
++ buf += sprintf(buf, " - COLD data: %d, %d, %d\n",
++ si->curseg[CURSEG_COLD_DATA],
++ si->cursec[CURSEG_COLD_DATA],
++ si->curzone[CURSEG_COLD_DATA]);
++ buf += sprintf(buf, " - WARM data: %d, %d, %d\n",
++ si->curseg[CURSEG_WARM_DATA],
++ si->cursec[CURSEG_WARM_DATA],
++ si->curzone[CURSEG_WARM_DATA]);
++ buf += sprintf(buf, " - HOT data: %d, %d, %d\n",
++ si->curseg[CURSEG_HOT_DATA],
++ si->cursec[CURSEG_HOT_DATA],
++ si->curzone[CURSEG_HOT_DATA]);
++ buf += sprintf(buf, " - Dir dnode: %d, %d, %d\n",
++ si->curseg[CURSEG_HOT_NODE],
++ si->cursec[CURSEG_HOT_NODE],
++ si->curzone[CURSEG_HOT_NODE]);
++ buf += sprintf(buf, " - File dnode: %d, %d, %d\n",
++ si->curseg[CURSEG_WARM_NODE],
++ si->cursec[CURSEG_WARM_NODE],
++ si->curzone[CURSEG_WARM_NODE]);
++ buf += sprintf(buf, " - Indir nodes: %d, %d, %d\n",
++ si->curseg[CURSEG_COLD_NODE],
++ si->cursec[CURSEG_COLD_NODE],
++ si->curzone[CURSEG_COLD_NODE]);
++ buf += sprintf(buf, "\n - Valid: %d\n - Dirty: %d\n",
++ si->main_area_segs - si->dirty_count -
++ si->prefree_count - si->free_segs,
++ si->dirty_count);
++ buf += sprintf(buf, " - Prefree: %d\n - Free: %d (%d)\n\n",
++ si->prefree_count,
++ si->free_segs,
++ si->free_secs);
++ buf += sprintf(buf, "GC calls: %d (BG: %d)\n",
++ si->call_count, si->bg_gc);
++ buf += sprintf(buf, " - data segments : %d\n", si->data_segs);
++ buf += sprintf(buf, " - node segments : %d\n", si->node_segs);
++ buf += sprintf(buf, "Try to move %d blocks\n", si->tot_blks);
++ buf += sprintf(buf, " - data blocks : %d\n", si->data_blks);
++ buf += sprintf(buf, " - node blocks : %d\n", si->node_blks);
++ buf += sprintf(buf, "\nExtent Hit Ratio: %d / %d\n",
++ si->hit_ext, si->total_ext);
++ buf += sprintf(buf, "\nBalancing F2FS Async:\n");
++ buf += sprintf(buf, " - nodes %4d in %4d\n",
++ si->ndirty_node, si->node_pages);
++ buf += sprintf(buf, " - dents %4d in dirs:%4d\n",
++ si->ndirty_dent, si->ndirty_dirs);
++ buf += sprintf(buf, " - meta %4d in %4d\n",
++ si->ndirty_meta, si->meta_pages);
++ buf += sprintf(buf, " - NATs %5d > %lu\n",
++ si->nats, NM_WOUT_THRESHOLD);
++ buf += sprintf(buf, " - SITs: %5d\n - free_nids: %5d\n",
++ si->sits, si->fnids);
++ buf += sprintf(buf, "\nDistribution of User Blocks:");
++ buf += sprintf(buf, " [ valid | invalid | free ]\n");
++ buf += sprintf(buf, " [");
++ for (j = 0; j < si->util_valid; j++)
++ buf += sprintf(buf, "-");
++ buf += sprintf(buf, "|");
++ for (j = 0; j < si->util_invalid; j++)
++ buf += sprintf(buf, "-");
++ buf += sprintf(buf, "|");
++ for (j = 0; j < si->util_free; j++)
++ buf += sprintf(buf, "-");
++ buf += sprintf(buf, "]\n\n");
++ buf += sprintf(buf, "SSR: %u blocks in %u segments\n",
++ si->block_count[SSR], si->segment_count[SSR]);
++ buf += sprintf(buf, "LFS: %u blocks in %u segments\n",
++ si->block_count[LFS], si->segment_count[LFS]);
++ mutex_unlock(&si->stat_list);
++ }
++ return buf - page;
++}
++
++static int f2fs_read_sit(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ struct f2fs_gc_info *gc_i, *next;
++ struct f2fs_stat_info *si;
++ char *buf = page;
++
++ list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
++ si = gc_i->stat_info;
++
++ mutex_lock(&si->stat_list);
++ if (!si->sbi) {
++ mutex_unlock(&si->stat_list);
++ continue;
++ }
++ f2fs_update_gc_metric(si->sbi);
++
++ buf += sprintf(buf, "BDF: %u, avg. vblocks: %u\n",
++ si->bimodal, si->avg_vblocks);
++ mutex_unlock(&si->stat_list);
++ }
++ return buf - page;
++}
++
++static int f2fs_read_mem(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ struct f2fs_gc_info *gc_i, *next;
++ struct f2fs_stat_info *si;
++ char *buf = page;
++
++ list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
++ struct f2fs_sb_info *sbi = gc_i->stat_info->sbi;
++ unsigned npages;
++ unsigned base_mem = 0, cache_mem = 0;
++
++ si = gc_i->stat_info;
++ mutex_lock(&si->stat_list);
++ if (!si->sbi) {
++ mutex_unlock(&si->stat_list);
++ continue;
++ }
++ base_mem += sizeof(struct f2fs_sb_info) + sbi->sb->s_blocksize;
++ base_mem += 2 * sizeof(struct f2fs_inode_info);
++ base_mem += sizeof(*sbi->ckpt);
++
++ /* build sm */
++ base_mem += sizeof(struct f2fs_sm_info);
++
++ /* build sit */
++ base_mem += sizeof(struct sit_info);
++ base_mem += TOTAL_SEGS(sbi) * sizeof(struct seg_entry);
++ base_mem += f2fs_bitmap_size(TOTAL_SEGS(sbi));
++ base_mem += 2 * SIT_VBLOCK_MAP_SIZE * TOTAL_SEGS(sbi);
++ if (sbi->segs_per_sec > 1)
++ base_mem += sbi->total_sections *
++ sizeof(struct sec_entry);
++ base_mem += __bitmap_size(sbi, SIT_BITMAP);
++
++ /* build free segmap */
++ base_mem += sizeof(struct free_segmap_info);
++ base_mem += f2fs_bitmap_size(TOTAL_SEGS(sbi));
++ base_mem += f2fs_bitmap_size(sbi->total_sections);
++
++ /* build curseg */
++ base_mem += sizeof(struct curseg_info) * NR_CURSEG_TYPE;
++ base_mem += PAGE_CACHE_SIZE * NR_CURSEG_TYPE;
++
++ /* build dirty segmap */
++ base_mem += sizeof(struct dirty_seglist_info);
++ base_mem += NR_DIRTY_TYPE * f2fs_bitmap_size(TOTAL_SEGS(sbi));
++ base_mem += 2 * f2fs_bitmap_size(TOTAL_SEGS(sbi));
++
++ /* buld nm */
++ base_mem += sizeof(struct f2fs_nm_info);
++ base_mem += __bitmap_size(sbi, NAT_BITMAP);
++
++ /* build gc */
++ base_mem += sizeof(struct f2fs_gc_info);
++ base_mem += sizeof(struct f2fs_gc_kthread);
++
++ /* free nids */
++ cache_mem += NM_I(sbi)->fcnt;
++ cache_mem += NM_I(sbi)->nat_cnt;
++ npages = sbi->node_inode->i_mapping->nrpages;
++ cache_mem += npages << PAGE_CACHE_SHIFT;
++ npages = sbi->meta_inode->i_mapping->nrpages;
++ cache_mem += npages << PAGE_CACHE_SHIFT;
++ cache_mem += sbi->n_orphans * sizeof(struct orphan_inode_entry);
++ cache_mem += sbi->n_dirty_dirs * sizeof(struct dir_inode_entry);
++
++ buf += sprintf(buf, "%u KB = static: %u + cached: %u\n",
++ (base_mem + cache_mem) >> 10,
++ base_mem >> 10,
++ cache_mem >> 10);
++ mutex_unlock(&si->stat_list);
++ }
++ return buf - page;
++}
++
++static int init_stats(struct f2fs_sb_info *sbi)
++{
++ struct f2fs_stat_info *si;
++ struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
++ struct f2fs_gc_info *gc_i = sbi->gc_info;
++
++ gc_i->stat_info = kzalloc(sizeof(struct f2fs_stat_info),
++ GFP_KERNEL);
++ if (!gc_i->stat_info)
++ return -ENOMEM;
++ si = gc_i->stat_info;
++ mutex_init(&si->stat_list);
++ list_add_tail(&gc_i->stat_list, &f2fs_stat_list);
++
++ si->all_area_segs = le32_to_cpu(raw_super->segment_count);
++ si->sit_area_segs = le32_to_cpu(raw_super->segment_count_sit);
++ si->nat_area_segs = le32_to_cpu(raw_super->segment_count_nat);
++ si->ssa_area_segs = le32_to_cpu(raw_super->segment_count_ssa);
++ si->main_area_segs = le32_to_cpu(raw_super->segment_count_main);
++ si->main_area_sections = le32_to_cpu(raw_super->section_count);
++ si->main_area_zones = si->main_area_sections /
++ le32_to_cpu(raw_super->secs_per_zone);
++ si->sbi = sbi;
++ return 0;
++}
++
++void f2fs_destroy_gci_stats(struct f2fs_gc_info *gc_i)
++{
++ struct f2fs_stat_info *si = gc_i->stat_info;
++
++ list_del(&gc_i->stat_list);
++ mutex_lock(&si->stat_list);
++ si->sbi = NULL;
++ mutex_unlock(&si->stat_list);
++ kfree(gc_i->stat_info);
++}
++
++int f2fs_stat_init(struct super_block *sb, struct f2fs_sb_info *sbi)
++{
++ struct proc_dir_entry *entry;
++ int retval;
++
++ if (!f2fs_proc_root)
++ f2fs_proc_root = proc_mkdir("fs/f2fs", NULL);
++
++ sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root);
++
++ retval = init_stats(sbi);
++ if (retval)
++ return retval;
++
++ entry = create_proc_entry("f2fs_stat", 0, sbi->s_proc);
++ if (!entry)
++ return -ENOMEM;
++ entry->read_proc = f2fs_read_gc;
++ entry->write_proc = NULL;
++
++ entry = create_proc_entry("f2fs_sit_stat", 0, sbi->s_proc);
++ if (!entry) {
++ remove_proc_entry("f2fs_stat", sbi->s_proc);
++ return -ENOMEM;
++ }
++ entry->read_proc = f2fs_read_sit;
++ entry->write_proc = NULL;
++ entry = create_proc_entry("f2fs_mem_stat", 0, sbi->s_proc);
++ if (!entry) {
++ remove_proc_entry("f2fs_sit_stat", sbi->s_proc);
++ remove_proc_entry("f2fs_stat", sbi->s_proc);
++ return -ENOMEM;
++ }
++ entry->read_proc = f2fs_read_mem;
++ entry->write_proc = NULL;
++ return 0;
++}
++
++void f2fs_stat_exit(struct super_block *sb, struct f2fs_sb_info *sbi)
++{
++ if (sbi->s_proc) {
++ remove_proc_entry("f2fs_stat", sbi->s_proc);
++ remove_proc_entry("f2fs_sit_stat", sbi->s_proc);
++ remove_proc_entry("f2fs_mem_stat", sbi->s_proc);
++ remove_proc_entry(sb->s_id, f2fs_proc_root);
++ }
++}
++
++void f2fs_remove_stats(void)
++{
++ remove_proc_entry("fs/f2fs", NULL);
++}
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -953,12 +953,6 @@ int start_gc_thread(struct f2fs_sb_info
+ void stop_gc_thread(struct f2fs_sb_info *);
+ block_t start_bidx_of_node(unsigned int);
+ int f2fs_gc(struct f2fs_sb_info *, int);
+-#ifdef CONFIG_F2FS_STAT_FS
+-void f2fs_update_stat(struct f2fs_sb_info *);
+-void f2fs_update_gc_metric(struct f2fs_sb_info *);
+-int f2fs_stat_init(struct f2fs_sb_info *);
+-void f2fs_stat_exit(struct f2fs_sb_info *);
+-#endif
+ int build_gc_manager(struct f2fs_sb_info *);
+ void destroy_gc_manager(struct f2fs_sb_info *);
+ int create_gc_caches(void);
+@@ -970,6 +964,25 @@ void destroy_gc_caches(void);
+ void recover_fsync_data(struct f2fs_sb_info *);
+ bool space_for_roll_forward(struct f2fs_sb_info *);
+
++/**
++ * debug.c
++ */
++#ifdef CONFIG_F2FS_STAT_FS
++void f2fs_update_stat(struct f2fs_sb_info *);
++int f2fs_stat_init(struct super_block *sb, struct f2fs_sb_info *);
++void f2fs_stat_exit(struct super_block *sb, struct f2fs_sb_info *);
++void f2fs_destroy_gci_stats(struct f2fs_gc_info *gc_i);
++void f2fs_remove_stats(void);
++#else
++static inline void f2fs_update_stat(struct f2fs_sb_info *sbi) { }
++static inline int f2fs_stat_init(struct super_block *sb,
++ struct f2fs_sb_info *sbi) { return 0; }
++static inline void f2fs_stat_exit(struct super_block *sb,
++ struct f2fs_sb_info *sbi) { }
++static inline void f2fs_destroy_gci_stats(struct f2fs_gc_info *gc_i) { }
++static inline void f2fs_remove_stats(void) { }
++#endif
++
+ extern const struct file_operations f2fs_dir_operations;
+ extern const struct file_operations f2fs_file_operations;
+ extern const struct inode_operations f2fs_file_inode_operations;
+--- a/fs/f2fs/gc.c
++++ b/fs/f2fs/gc.c
+@@ -24,7 +24,6 @@
+ #include "segment.h"
+ #include "gc.h"
+
+-static LIST_HEAD(f2fs_stat_list);
+ static struct kmem_cache *winode_slab;
+
+ static int gc_thread_func(void *data)
+@@ -727,350 +726,10 @@ stop:
+ return gc_status;
+ }
+
+-#ifdef CONFIG_F2FS_STAT_FS
+-void f2fs_update_stat(struct f2fs_sb_info *sbi)
+-{
+- struct f2fs_gc_info *gc_i = sbi->gc_info;
+- struct f2fs_stat_info *si = gc_i->stat_info;
+- int i;
+-
+- /* valid check of the segment numbers */
+- si->hit_ext = sbi->read_hit_ext;
+- si->total_ext = sbi->total_hit_ext;
+- si->ndirty_node = get_pages(sbi, F2FS_DIRTY_NODES);
+- si->ndirty_dent = get_pages(sbi, F2FS_DIRTY_DENTS);
+- si->ndirty_dirs = sbi->n_dirty_dirs;
+- si->ndirty_meta = get_pages(sbi, F2FS_DIRTY_META);
+- si->total_count = (int)sbi->user_block_count / sbi->blocks_per_seg;
+- si->rsvd_segs = reserved_segments(sbi);
+- si->overp_segs = overprovision_segments(sbi);
+- si->valid_count = valid_user_blocks(sbi);
+- si->valid_node_count = valid_node_count(sbi);
+- si->valid_inode_count = valid_inode_count(sbi);
+- si->utilization = utilization(sbi);
+-
+- si->free_segs = free_segments(sbi);
+- si->free_secs = free_sections(sbi);
+- si->prefree_count = prefree_segments(sbi);
+- si->dirty_count = dirty_segments(sbi);
+- si->node_pages = sbi->node_inode->i_mapping->nrpages;
+- si->meta_pages = sbi->meta_inode->i_mapping->nrpages;
+- si->nats = NM_I(sbi)->nat_cnt;
+- si->sits = SIT_I(sbi)->dirty_sentries;
+- si->fnids = NM_I(sbi)->fcnt;
+- si->bg_gc = sbi->bg_gc;
+- si->util_free = (int)(free_user_blocks(sbi) >> sbi->log_blocks_per_seg)
+- * 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
+- / 2;
+- si->util_valid = (int)(written_block_count(sbi) >>
+- sbi->log_blocks_per_seg)
+- * 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
+- / 2;
+- si->util_invalid = 50 - si->util_free - si->util_valid;
+- for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_NODE; i++) {
+- struct curseg_info *curseg = CURSEG_I(sbi, i);
+- si->curseg[i] = curseg->segno;
+- si->cursec[i] = curseg->segno / sbi->segs_per_sec;
+- si->curzone[i] = si->cursec[i] / sbi->secs_per_zone;
+- }
+-
+- for (i = 0; i < 2; i++) {
+- si->segment_count[i] = sbi->segment_count[i];
+- si->block_count[i] = sbi->block_count[i];
+- }
+-}
+-
+-/**
+- * This function calculates BDF of every segments
+- */
+-void f2fs_update_gc_metric(struct f2fs_sb_info *sbi)
+-{
+- struct f2fs_gc_info *gc_i = sbi->gc_info;
+- struct f2fs_stat_info *si = gc_i->stat_info;
+- unsigned int blks_per_sec, hblks_per_sec, total_vblocks, bimodal, dist;
+- struct sit_info *sit_i = SIT_I(sbi);
+- unsigned int segno, vblocks;
+- int ndirty = 0;
+-
+- bimodal = 0;
+- total_vblocks = 0;
+- blks_per_sec = sbi->segs_per_sec * (1 << sbi->log_blocks_per_seg);
+- hblks_per_sec = blks_per_sec / 2;
+- mutex_lock(&sit_i->sentry_lock);
+- for (segno = 0; segno < TOTAL_SEGS(sbi); segno += sbi->segs_per_sec) {
+- vblocks = get_valid_blocks(sbi, segno, sbi->segs_per_sec);
+- dist = abs(vblocks - hblks_per_sec);
+- bimodal += dist * dist;
+-
+- if (vblocks > 0 && vblocks < blks_per_sec) {
+- total_vblocks += vblocks;
+- ndirty++;
+- }
+- }
+- mutex_unlock(&sit_i->sentry_lock);
+- dist = sbi->total_sections * hblks_per_sec * hblks_per_sec / 100;
+- si->bimodal = bimodal / dist;
+- if (si->dirty_count)
+- si->avg_vblocks = total_vblocks / ndirty;
+- else
+- si->avg_vblocks = 0;
+-}
+-
+-static int f2fs_read_gc(char *page, char **start, off_t off,
+- int count, int *eof, void *data)
+-{
+- struct f2fs_gc_info *gc_i, *next;
+- struct f2fs_stat_info *si;
+- char *buf = page;
+- int i = 0;
+-
+- list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
+- int j;
+- si = gc_i->stat_info;
+-
+- mutex_lock(&si->stat_list);
+- if (!si->sbi) {
+- mutex_unlock(&si->stat_list);
+- continue;
+- }
+- f2fs_update_stat(si->sbi);
+-
+- buf += sprintf(buf, "=====[ partition info. #%d ]=====\n", i++);
+- buf += sprintf(buf, "[SB: 1] [CP: 2] [NAT: %d] [SIT: %d] ",
+- si->nat_area_segs, si->sit_area_segs);
+- buf += sprintf(buf, "[SSA: %d] [MAIN: %d",
+- si->ssa_area_segs, si->main_area_segs);
+- buf += sprintf(buf, "(OverProv:%d Resv:%d)]\n\n",
+- si->overp_segs, si->rsvd_segs);
+- buf += sprintf(buf, "Utilization: %d%% (%d valid blocks)\n",
+- si->utilization, si->valid_count);
+- buf += sprintf(buf, " - Node: %u (Inode: %u, ",
+- si->valid_node_count, si->valid_inode_count);
+- buf += sprintf(buf, "Other: %u)\n - Data: %u\n",
+- si->valid_node_count - si->valid_inode_count,
+- si->valid_count - si->valid_node_count);
+- buf += sprintf(buf, "\nMain area: %d segs, %d secs %d zones\n",
+- si->main_area_segs, si->main_area_sections,
+- si->main_area_zones);
+- buf += sprintf(buf, " - COLD data: %d, %d, %d\n",
+- si->curseg[CURSEG_COLD_DATA],
+- si->cursec[CURSEG_COLD_DATA],
+- si->curzone[CURSEG_COLD_DATA]);
+- buf += sprintf(buf, " - WARM data: %d, %d, %d\n",
+- si->curseg[CURSEG_WARM_DATA],
+- si->cursec[CURSEG_WARM_DATA],
+- si->curzone[CURSEG_WARM_DATA]);
+- buf += sprintf(buf, " - HOT data: %d, %d, %d\n",
+- si->curseg[CURSEG_HOT_DATA],
+- si->cursec[CURSEG_HOT_DATA],
+- si->curzone[CURSEG_HOT_DATA]);
+- buf += sprintf(buf, " - Dir dnode: %d, %d, %d\n",
+- si->curseg[CURSEG_HOT_NODE],
+- si->cursec[CURSEG_HOT_NODE],
+- si->curzone[CURSEG_HOT_NODE]);
+- buf += sprintf(buf, " - File dnode: %d, %d, %d\n",
+- si->curseg[CURSEG_WARM_NODE],
+- si->cursec[CURSEG_WARM_NODE],
+- si->curzone[CURSEG_WARM_NODE]);
+- buf += sprintf(buf, " - Indir nodes: %d, %d, %d\n",
+- si->curseg[CURSEG_COLD_NODE],
+- si->cursec[CURSEG_COLD_NODE],
+- si->curzone[CURSEG_COLD_NODE]);
+- buf += sprintf(buf, "\n - Valid: %d\n - Dirty: %d\n",
+- si->main_area_segs - si->dirty_count -
+- si->prefree_count - si->free_segs,
+- si->dirty_count);
+- buf += sprintf(buf, " - Prefree: %d\n - Free: %d (%d)\n\n",
+- si->prefree_count,
+- si->free_segs,
+- si->free_secs);
+- buf += sprintf(buf, "GC calls: %d (BG: %d)\n",
+- si->call_count, si->bg_gc);
+- buf += sprintf(buf, " - data segments : %d\n", si->data_segs);
+- buf += sprintf(buf, " - node segments : %d\n", si->node_segs);
+- buf += sprintf(buf, "Try to move %d blocks\n", si->tot_blks);
+- buf += sprintf(buf, " - data blocks : %d\n", si->data_blks);
+- buf += sprintf(buf, " - node blocks : %d\n", si->node_blks);
+- buf += sprintf(buf, "\nExtent Hit Ratio: %d / %d\n",
+- si->hit_ext, si->total_ext);
+- buf += sprintf(buf, "\nBalancing F2FS Async:\n");
+- buf += sprintf(buf, " - nodes %4d in %4d\n",
+- si->ndirty_node, si->node_pages);
+- buf += sprintf(buf, " - dents %4d in dirs:%4d\n",
+- si->ndirty_dent, si->ndirty_dirs);
+- buf += sprintf(buf, " - meta %4d in %4d\n",
+- si->ndirty_meta, si->meta_pages);
+- buf += sprintf(buf, " - NATs %5d > %lu\n",
+- si->nats, NM_WOUT_THRESHOLD);
+- buf += sprintf(buf, " - SITs: %5d\n - free_nids: %5d\n",
+- si->sits, si->fnids);
+- buf += sprintf(buf, "\nDistribution of User Blocks:");
+- buf += sprintf(buf, " [ valid | invalid | free ]\n");
+- buf += sprintf(buf, " [");
+- for (j = 0; j < si->util_valid; j++)
+- buf += sprintf(buf, "-");
+- buf += sprintf(buf, "|");
+- for (j = 0; j < si->util_invalid; j++)
+- buf += sprintf(buf, "-");
+- buf += sprintf(buf, "|");
+- for (j = 0; j < si->util_free; j++)
+- buf += sprintf(buf, "-");
+- buf += sprintf(buf, "]\n\n");
+- buf += sprintf(buf, "SSR: %u blocks in %u segments\n",
+- si->block_count[SSR], si->segment_count[SSR]);
+- buf += sprintf(buf, "LFS: %u blocks in %u segments\n",
+- si->block_count[LFS], si->segment_count[LFS]);
+- mutex_unlock(&si->stat_list);
+- }
+- return buf - page;
+-}
+-
+-static int f2fs_read_sit(char *page, char **start, off_t off,
+- int count, int *eof, void *data)
+-{
+- struct f2fs_gc_info *gc_i, *next;
+- struct f2fs_stat_info *si;
+- char *buf = page;
+-
+- list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
+- si = gc_i->stat_info;
+-
+- mutex_lock(&si->stat_list);
+- if (!si->sbi) {
+- mutex_unlock(&si->stat_list);
+- continue;
+- }
+- f2fs_update_gc_metric(si->sbi);
+-
+- buf += sprintf(buf, "BDF: %u, avg. vblocks: %u\n",
+- si->bimodal, si->avg_vblocks);
+- mutex_unlock(&si->stat_list);
+- }
+- return buf - page;
+-}
+-
+-static int f2fs_read_mem(char *page, char **start, off_t off,
+- int count, int *eof, void *data)
+-{
+- struct f2fs_gc_info *gc_i, *next;
+- struct f2fs_stat_info *si;
+- char *buf = page;
+-
+- list_for_each_entry_safe(gc_i, next, &f2fs_stat_list, stat_list) {
+- struct f2fs_sb_info *sbi = gc_i->stat_info->sbi;
+- unsigned npages;
+- unsigned base_mem = 0, cache_mem = 0;
+-
+- si = gc_i->stat_info;
+- mutex_lock(&si->stat_list);
+- if (!si->sbi) {
+- mutex_unlock(&si->stat_list);
+- continue;
+- }
+- base_mem += sizeof(struct f2fs_sb_info) + sbi->sb->s_blocksize;
+- base_mem += 2 * sizeof(struct f2fs_inode_info);
+- base_mem += sizeof(*sbi->ckpt);
+-
+- /* build sm */
+- base_mem += sizeof(struct f2fs_sm_info);
+-
+- /* build sit */
+- base_mem += sizeof(struct sit_info);
+- base_mem += TOTAL_SEGS(sbi) * sizeof(struct seg_entry);
+- base_mem += f2fs_bitmap_size(TOTAL_SEGS(sbi));
+- base_mem += 2 * SIT_VBLOCK_MAP_SIZE * TOTAL_SEGS(sbi);
+- if (sbi->segs_per_sec > 1)
+- base_mem += sbi->total_sections *
+- sizeof(struct sec_entry);
+- base_mem += __bitmap_size(sbi, SIT_BITMAP);
+-
+- /* build free segmap */
+- base_mem += sizeof(struct free_segmap_info);
+- base_mem += f2fs_bitmap_size(TOTAL_SEGS(sbi));
+- base_mem += f2fs_bitmap_size(sbi->total_sections);
+-
+- /* build curseg */
+- base_mem += sizeof(struct curseg_info) * NR_CURSEG_TYPE;
+- base_mem += PAGE_CACHE_SIZE * NR_CURSEG_TYPE;
+-
+- /* build dirty segmap */
+- base_mem += sizeof(struct dirty_seglist_info);
+- base_mem += NR_DIRTY_TYPE * f2fs_bitmap_size(TOTAL_SEGS(sbi));
+- base_mem += 2 * f2fs_bitmap_size(TOTAL_SEGS(sbi));
+-
+- /* buld nm */
+- base_mem += sizeof(struct f2fs_nm_info);
+- base_mem += __bitmap_size(sbi, NAT_BITMAP);
+-
+- /* build gc */
+- base_mem += sizeof(struct f2fs_gc_info);
+- base_mem += sizeof(struct f2fs_gc_kthread);
+-
+- /* free nids */
+- cache_mem += NM_I(sbi)->fcnt;
+- cache_mem += NM_I(sbi)->nat_cnt;
+- npages = sbi->node_inode->i_mapping->nrpages;
+- cache_mem += npages << PAGE_CACHE_SHIFT;
+- npages = sbi->meta_inode->i_mapping->nrpages;
+- cache_mem += npages << PAGE_CACHE_SHIFT;
+- cache_mem += sbi->n_orphans * sizeof(struct orphan_inode_entry);
+- cache_mem += sbi->n_dirty_dirs * sizeof(struct dir_inode_entry);
+-
+- buf += sprintf(buf, "%u KB = static: %u + cached: %u\n",
+- (base_mem + cache_mem) >> 10,
+- base_mem >> 10,
+- cache_mem >> 10);
+- mutex_unlock(&si->stat_list);
+- }
+- return buf - page;
+-}
+-
+-int f2fs_stat_init(struct f2fs_sb_info *sbi)
+-{
+- struct proc_dir_entry *entry;
+-
+- entry = create_proc_entry("f2fs_stat", 0, sbi->s_proc);
+- if (!entry)
+- return -ENOMEM;
+- entry->read_proc = f2fs_read_gc;
+- entry->write_proc = NULL;
+-
+- entry = create_proc_entry("f2fs_sit_stat", 0, sbi->s_proc);
+- if (!entry) {
+- remove_proc_entry("f2fs_stat", sbi->s_proc);
+- return -ENOMEM;
+- }
+- entry->read_proc = f2fs_read_sit;
+- entry->write_proc = NULL;
+- entry = create_proc_entry("f2fs_mem_stat", 0, sbi->s_proc);
+- if (!entry) {
+- remove_proc_entry("f2fs_sit_stat", sbi->s_proc);
+- remove_proc_entry("f2fs_stat", sbi->s_proc);
+- return -ENOMEM;
+- }
+- entry->read_proc = f2fs_read_mem;
+- entry->write_proc = NULL;
+- return 0;
+-}
+-
+-void f2fs_stat_exit(struct f2fs_sb_info *sbi)
+-{
+- if (sbi->s_proc) {
+- remove_proc_entry("f2fs_stat", sbi->s_proc);
+- remove_proc_entry("f2fs_sit_stat", sbi->s_proc);
+- remove_proc_entry("f2fs_mem_stat", sbi->s_proc);
+- }
+-}
+-#endif
+-
+ int build_gc_manager(struct f2fs_sb_info *sbi)
+ {
+ struct f2fs_gc_info *gc_i;
+ struct f2fs_checkpoint *ckp = F2FS_CKPT(sbi);
+-#ifdef CONFIG_F2FS_STAT_FS
+- struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
+- struct f2fs_stat_info *si;
+-#endif
+
+ gc_i = kzalloc(sizeof(struct f2fs_gc_info), GFP_KERNEL);
+ if (!gc_i)
+@@ -1082,44 +741,18 @@ int build_gc_manager(struct f2fs_sb_info
+
+ DIRTY_I(sbi)->v_ops = &default_v_ops;
+
+-#ifdef CONFIG_F2FS_STAT_FS
+- gc_i->stat_info = kzalloc(sizeof(struct f2fs_stat_info),
+- GFP_KERNEL);
+- if (!gc_i->stat_info)
+- return -ENOMEM;
+- si = gc_i->stat_info;
+- mutex_init(&si->stat_list);
+- list_add_tail(&gc_i->stat_list, &f2fs_stat_list);
+-
+- si->all_area_segs = le32_to_cpu(raw_super->segment_count);
+- si->sit_area_segs = le32_to_cpu(raw_super->segment_count_sit);
+- si->nat_area_segs = le32_to_cpu(raw_super->segment_count_nat);
+- si->ssa_area_segs = le32_to_cpu(raw_super->segment_count_ssa);
+- si->main_area_segs = le32_to_cpu(raw_super->segment_count_main);
+- si->main_area_sections = le32_to_cpu(raw_super->section_count);
+- si->main_area_zones = si->main_area_sections /
+- le32_to_cpu(raw_super->secs_per_zone);
+- si->sbi = sbi;
+-#endif
+ return 0;
+ }
+
+ void destroy_gc_manager(struct f2fs_sb_info *sbi)
+ {
+ struct f2fs_gc_info *gc_i = sbi->gc_info;
+-#ifdef CONFIG_F2FS_STAT_FS
+- struct f2fs_stat_info *si = gc_i->stat_info;
+-#endif
++
+ if (!gc_i)
+ return;
+
+-#ifdef CONFIG_F2FS_STAT_FS
+- list_del(&gc_i->stat_list);
+- mutex_lock(&si->stat_list);
+- si->sbi = NULL;
+- mutex_unlock(&si->stat_list);
+- kfree(gc_i->stat_info);
+-#endif
++ f2fs_destroy_gci_stats(gc_i);
++
+ sbi->gc_info = NULL;
+ kfree(gc_i);
+ }
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -26,7 +26,6 @@
+ #include "xattr.h"
+
+ static struct kmem_cache *f2fs_inode_cachep;
+-static struct proc_dir_entry *f2fs_proc_root;
+
+ enum {
+ Opt_gc_background_off,
+@@ -97,12 +96,7 @@ static void f2fs_put_super(struct super_
+ {
+ struct f2fs_sb_info *sbi = F2FS_SB(sb);
+
+-#ifdef CONFIG_F2FS_STAT_FS
+- if (sbi->s_proc) {
+- f2fs_stat_exit(sbi);
+- remove_proc_entry(sb->s_id, f2fs_proc_root);
+- }
+-#endif
++ f2fs_stat_exit(sb, sbi);
+ stop_gc_thread(sbi);
+
+ write_checkpoint(sbi, false, true);
+@@ -486,13 +480,9 @@ static int f2fs_fill_super(struct super_
+ if (start_gc_thread(sbi))
+ goto fail;
+
+-#ifdef CONFIG_F2FS_STAT_FS
+- if (f2fs_proc_root) {
+- sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root);
+- if (f2fs_stat_init(sbi))
+- goto fail;
+- }
+-#endif
++ if (f2fs_stat_init(sb, sbi))
++ goto fail;
++
+ return 0;
+ fail:
+ stop_gc_thread(sbi);
+@@ -566,7 +556,6 @@ static int __init init_f2fs_fs(void)
+ if (register_filesystem(&f2fs_fs_type))
+ return -EBUSY;
+
+- f2fs_proc_root = proc_mkdir("fs/f2fs", NULL);
+ return 0;
+ fail:
+ return -ENOMEM;
+@@ -574,7 +563,7 @@ fail:
+
+ static void __exit exit_f2fs_fs(void)
+ {
+- remove_proc_entry("fs/f2fs", NULL);
++ f2fs_remove_stats();
+ unregister_filesystem(&f2fs_fs_type);
+ destroy_checkpoint_caches();
+ destroy_gc_caches();
diff --git a/f2fs_debug b/f2fs_debug
deleted file mode 100644
index dbf72f53e18775..00000000000000
--- a/f2fs_debug
+++ /dev/null
@@ -1,10 +0,0 @@
----
- fs/f2fs/debug.c | 3 +++
- 1 file changed, 3 insertions(+)
-
---- /dev/null
-+++ b/fs/f2fs/debug.c
-@@ -0,0 +1,3 @@
-+
-+
-+
diff --git a/series b/series
index 9f270488f2acb6..6621c362199af1 100644
--- a/series
+++ b/series
@@ -16,7 +16,10 @@ f14
f15
f16
-f2fs_debug
+f2fs-gc.h-make-should_do_checkpoint-inline.patch
+f2fs-move-statistics-code-into-one-file.patch
+
+
time-don-t-inline-export_symbol-functions.patch
gregkh/gkh-version.patch