From: Greg KH <gregkh@linuxfoundation.org>
To: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org,
viro@zeniv.linux.org.uk, arnd@arndb.de, tytso@mit.edu,
chur.lee@samsung.com, cm224.lee@samsung.com,
jooyoung.hwang@samsung.com
Subject: [PATCH 2/3] f2fs: move statistics code into one file
Date: Tue, 23 Oct 2012 11:22:41 -0700 [thread overview]
Message-ID: <20121023182241.GC6096@kroah.com> (raw)
In-Reply-To: <20121023182055.GA6096@kroah.com>
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
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();
next prev parent reply other threads:[~2012-10-23 18:22 UTC|newest]
Thread overview: 60+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-10-23 2:21 [PATCH 00/16 v2] f2fs: introduce flash-friendly file system Jaegeuk Kim
2012-10-23 2:25 ` [PATCH 01/16 v2] f2fs: add document Jaegeuk Kim
2012-10-23 11:41 ` Vyacheslav Dubeyko
2012-10-25 22:14 ` Jaegeuk Kim
2012-10-23 2:26 ` [PATCH 02/16 v2] f2fs: add on-disk layout Jaegeuk Kim
2012-10-23 3:46 ` NeilBrown
2012-10-23 6:30 ` Jaegeuk Kim
2012-10-23 6:47 ` Marco Stornelli
2012-10-23 7:08 ` Jaegeuk Kim
2012-10-24 11:25 ` Vyacheslav Dubeyko
2012-10-26 3:31 ` Jaegeuk Kim
2012-10-26 8:18 ` Arnd Bergmann
2012-10-26 8:31 ` Jaegeuk Kim
2012-10-26 12:48 ` Vyacheslav Dubeyko
2012-10-26 13:13 ` Jaegeuk Kim
2012-10-23 2:26 ` [PATCH 03/16 v2] f2fs: add superblock and major in-memory structure Jaegeuk Kim
2012-10-27 13:58 ` Vyacheslav Dubeyko
2012-10-23 2:27 ` [PATCH 04/16 v2] f2fs: add super block operations Jaegeuk Kim
2012-10-23 6:51 ` Marco Stornelli
2012-10-23 7:09 ` Jaegeuk Kim
2012-10-28 12:08 ` Vyacheslav Dubeyko
2012-10-23 2:28 ` [PATCH 05/16 v2] f2fs: add checkpoint operations Jaegeuk Kim
2012-10-23 2:28 ` [PATCH 06/16 v2] f2fs: add node operations Jaegeuk Kim
2012-10-23 2:28 ` [PATCH 07/16 v2] f2fs: add segment operations Jaegeuk Kim
2012-10-23 3:02 ` Max Filippov
2012-10-23 3:23 ` Jaegeuk Kim
2012-10-23 2:29 ` [PATCH 08/16 v2] f2fs: add file operations Jaegeuk Kim
2012-10-23 6:58 ` Marco Stornelli
2012-10-23 7:31 ` Jaegeuk Kim
2012-10-23 7:39 ` Marco Stornelli
2012-10-23 2:29 ` [PATCH 09/16 v2] f2fs: add address space operations for data Jaegeuk Kim
2012-10-23 2:30 ` [PATCH 10/16 v2] f2fs: add core inode operations Jaegeuk Kim
2012-10-23 2:30 ` [PATCH 11/16 v2] f2fs: add inode operations for special inodes Jaegeuk Kim
2012-10-23 7:01 ` Marco Stornelli
2012-10-23 7:46 ` Jaegeuk Kim
2012-10-23 8:20 ` Marco Stornelli
2012-10-23 8:49 ` Jaegeuk Kim
2012-10-23 9:35 ` Marco Stornelli
2012-10-23 2:31 ` [PATCH 12/16 v2] f2fs: add core directory operations Jaegeuk Kim
2012-10-23 2:31 ` [PATCH 13/16 v2] f2fs: add xattr and acl functionalities Jaegeuk Kim
2012-10-23 2:32 ` [PATCH 14/16 v2] f2fs: add garbage collection functions Jaegeuk Kim
2012-10-23 2:32 ` [PATCH 15/16 v2] f2fs: add recovery routines for roll-forward Jaegeuk Kim
2012-10-23 2:33 ` [PATCH 16/16 v2] f2fs: update Kconfig and Makefile Jaegeuk Kim
2012-10-23 3:04 ` Greg KH
2012-10-23 3:21 ` Jaegeuk Kim
2012-10-23 18:20 ` [PATCH 0/3] f2fs: move proc files to debugfs Greg KH
2012-10-23 18:21 ` [PATCH 1/3] f2fs: gc.h: make should_do_checkpoint() inline Greg KH
2012-10-23 18:22 ` Greg KH [this message]
2012-10-23 18:23 ` [PATCH 3/3] f2fs: move proc files to debugfs Greg KH
2012-10-23 19:20 ` [PATCH 3/3 v2] " Greg KH
2012-10-23 19:11 ` [PATCH 0/3] " Greg KH
2012-10-25 8:12 ` Jaegeuk Kim
2012-10-23 18:26 ` [PATCH 00/16 v2] f2fs: introduce flash-friendly file system Greg KH
2012-10-23 18:57 ` Greg KH
2012-10-23 23:18 ` Jaegeuk Kim
2012-10-24 3:02 ` 'Greg KH'
2012-10-24 5:35 ` Jaegeuk Kim
2012-10-23 23:14 ` Jaegeuk Kim
2012-10-24 3:01 ` 'Greg KH'
2012-10-24 5:34 ` Jaegeuk Kim
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20121023182241.GC6096@kroah.com \
--to=gregkh@linuxfoundation.org \
--cc=arnd@arndb.de \
--cc=chur.lee@samsung.com \
--cc=cm224.lee@samsung.com \
--cc=jaegeuk.kim@samsung.com \
--cc=jooyoung.hwang@samsung.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=tytso@mit.edu \
--cc=viro@zeniv.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).