blob: d52926e8a52effa14c446d143add41bc46b9eded [file] [log] [blame]
/***********************************************************
** Copyright (C), 2008-2019, OPPO Mobile Comm Corp., Ltd.
** VENDOR_EDIT
** File: - of2fs_sysfs.c
** Description: f2fs bigdata statistics
**
** Version: 1.0
** Date : 2019/08/14
** Author: yanwu@TECH.Storage.FS.oF2FS, add code for f2fs bigdata statistics
**
** ------------------ Revision History:------------------------
** <author> <data> <version > <desc>
** yanwu 2019/08/14 1.0 add code for f2fs bigdata statistics
****************************************************************/
#include <linux/proc_fs.h>
#include <linux/f2fs_fs.h>
#include <linux/seq_file.h>
#include "f2fs.h"
#include "segment.h"
#include "gc.h"
#include "of2fs_bigdata.h"
/* f2fs big-data statistics */
#define OF2FS_PROC_DEF(_name) \
static int of2fs_##_name##_open(struct inode *inode, struct file *file) \
{ \
return single_open(file, of2fs_##_name##_show, PDE_DATA(inode)); \
} \
\
static const struct file_operations of2fs_##_name##_fops = { \
.owner = THIS_MODULE, \
.open = of2fs_##_name##_open, \
.read = seq_read, \
.write = of2fs_##_name##_write, \
.llseek = seq_lseek, \
.release = single_release, \
};
static int of2fs_base_info_show(struct seq_file *seq, void *p)
{
struct super_block *sb = seq->private;
struct f2fs_sb_info *sbi = F2FS_SB(sb);
/*
* each column indicates: block_count fs_block_count
* free_segment_count reserved_segment_count
* valid_user_blocks
*/
seq_printf(seq, "%llu %llu %u %u %u\n",
le64_to_cpu(sbi->raw_super->block_count),
le64_to_cpu(sbi->raw_super->block_count) - le32_to_cpu(sbi->raw_super->main_blkaddr),
free_segments(sbi), reserved_segments(sbi),
valid_user_blocks(sbi));
return 0;
}
static ssize_t of2fs_base_info_write(struct file *file,
const char __user *buf,
size_t length, loff_t *ppos)
{
return length;
}
static int of2fs_discard_info_show(struct seq_file *seq, void *p)
{
struct super_block *sb = seq->private;
struct f2fs_sb_info *sbi = F2FS_SB(sb);
struct f2fs_bigdata_info *bd = F2FS_BD_STAT(sbi);
/*
* each colum indicates: discard_count discard_blocks undiscard_count
* undiscard_blocks discard_time max_discard_time
*/
bd_lock(sbi);
if (SM_I(sbi)->dcc_info) {
bd->undiscard_count = atomic_read(&SM_I(sbi)->dcc_info->discard_cmd_cnt);
bd->undiscard_blocks = SM_I(sbi)->dcc_info->undiscard_blks;
}
seq_printf(seq, "%u %u %u %u %llu %llu\n", bd->discard_count,
bd->discard_blocks, bd->undiscard_count,
bd->undiscard_blocks, bd->discard_time,
bd->max_discard_time);
bd_unlock(sbi);
return 0;
}
static ssize_t of2fs_discard_info_write(struct file *file,
const char __user *buf,
size_t length, loff_t *ppos)
{
struct seq_file *seq = file->private_data;
struct super_block *sb = seq->private;
struct f2fs_sb_info *sbi = F2FS_SB(sb);
struct f2fs_bigdata_info *bd = F2FS_BD_STAT(sbi);
char buffer[3] = {0};
if (!buf || length > 2 || length <= 0)
return -EINVAL;
if (copy_from_user(&buffer, buf, length))
return -EFAULT;
if (buffer[0] != '0')
return -EINVAL;
bd_lock(sbi);
bd->discard_count = 0;
bd->discard_blocks = 0;
bd->undiscard_count = 0;
bd->undiscard_blocks = 0;
bd->discard_time = 0;
bd->max_discard_time = 0;
bd_unlock(sbi);
return length;
}
static int of2fs_cp_info_show(struct seq_file *seq, void *p)
{
struct super_block *sb = seq->private;
struct f2fs_sb_info *sbi = F2FS_SB(sb);
struct f2fs_bigdata_info *bd = F2FS_BD_STAT(sbi);
/*
* each column indicates: cp_count cp_success_count cp_time max_cp_time
* max_cp_submit_time max_cp_flush_meta_time max_cp_discard_time
*/
bd_lock(sbi);
bd->cp_count = sbi->stat_info->cp_count;
seq_printf(seq, "%u %u %llu %llu %llu %llu %llu\n", bd->cp_count,
bd->cp_success_count, bd->cp_time, bd->max_cp_time,
bd->max_cp_submit_time, bd->max_cp_flush_meta_time,
bd->max_cp_discard_time);
bd_unlock(sbi);
return 0;
}
static ssize_t of2fs_cp_info_write(struct file *file,
const char __user *buf,
size_t length, loff_t *ppos)
{
struct seq_file *seq = file->private_data;
struct super_block *sb = seq->private;
struct f2fs_sb_info *sbi = F2FS_SB(sb);
struct f2fs_bigdata_info *bd = F2FS_BD_STAT(sbi);
char buffer[3] = {0};
if (!buf || length > 2 || length <= 0)
return -EINVAL;
if (copy_from_user(&buffer, buf, length))
return -EFAULT;
if (buffer[0] != '0')
return -EINVAL;
bd_lock(sbi);
bd->cp_count = 0;
bd->cp_success_count = 0;
bd->cp_time = 0;
bd->max_cp_time = 0;
bd->max_cp_submit_time = 0;
bd->max_cp_flush_meta_time = 0;
bd->max_cp_discard_time = 0;
bd_unlock(sbi);
return length;
}
static int of2fs_gc_info_show(struct seq_file *seq, void *p)
{
struct super_block *sb = seq->private;
struct f2fs_sb_info *sbi = F2FS_SB(sb);
struct f2fs_bigdata_info *bd = F2FS_BD_STAT(sbi);
/*
* each column indicates: bggc_cnt bggc_fail_cnt fggc_cnt fggc_fail_cnt
* bggc_data_seg_cnt bggc_data_blk_cnt bggc_node_seg_cnt bggc_node_blk_cnt
* fggc_data_seg_cnt fggc_data_blk_cnt fggc_node_seg_cnt fggc_node_blk_cnt
* node_ssr_cnt data_ssr_cnt node_lfs_cnt data_lfs_cnt data_ipu_cnt
* fggc_time
*/
bd_lock(sbi);
seq_printf(seq, "%u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %llu\n",
bd->gc_count[BG_GC], bd->gc_fail_count[BG_GC],
bd->gc_count[FG_GC], bd->gc_fail_count[FG_GC],
bd->gc_data_segments[BG_GC], bd->gc_data_blocks[BG_GC],
bd->gc_node_segments[BG_GC], bd->gc_node_blocks[BG_GC],
bd->gc_data_segments[FG_GC], bd->gc_data_blocks[FG_GC],
bd->gc_node_segments[FG_GC], bd->gc_node_blocks[FG_GC],
bd->data_alloc_count[SSR], bd->node_alloc_count[SSR],
bd->data_alloc_count[LFS], bd->node_alloc_count[LFS],
bd->data_ipu_count, bd->fggc_time);
bd_unlock(sbi);
return 0;
}
static ssize_t of2fs_gc_info_write(struct file *file,
const char __user *buf,
size_t length, loff_t *ppos)
{
struct seq_file *seq = file->private_data;
struct super_block *sb = seq->private;
struct f2fs_sb_info *sbi = F2FS_SB(sb);
struct f2fs_bigdata_info *bd = F2FS_BD_STAT(sbi);
int i;
char buffer[3] = {0};
if (!buf || length > 2 || length <= 0)
return -EINVAL;
if (copy_from_user(&buffer, buf, length))
return -EFAULT;
if (buffer[0] != '0')
return -EINVAL;
bd_lock(sbi);
for (i = BG_GC; i <= FG_GC; i++) {
bd->gc_count[i] = 0;
bd->gc_fail_count[i] = 0;
bd->gc_data_count[i] = 0;
bd->gc_node_count[i] = 0;
bd->gc_data_segments[i] = 0;
bd->gc_data_blocks[i] = 0;
bd->gc_node_segments[i] = 0;
bd->gc_node_blocks[i] = 0;
}
bd->fggc_time = 0;
for (i = LFS; i <= SSR; i++) {
bd->node_alloc_count[i] = 0;
bd->data_alloc_count[i] = 0;
}
bd->data_ipu_count = 0;
bd_unlock(sbi);
return length;
}
static int of2fs_fsync_info_show(struct seq_file *seq, void *p)
{
struct super_block *sb = seq->private;
struct f2fs_sb_info *sbi = F2FS_SB(sb);
struct f2fs_bigdata_info *bd = F2FS_BD_STAT(sbi);
/*
* eacho column indicates: fsync_reg_file_cnt fsync_dir_cnt fsync_time
* max_fsync_time fsync_wr_file_time max_fsync_wr_file_time
* fsync_cp_time max_fsync_cp_time fsync_sync_node_time
* max_fsync_sync_node_time fsync_flush_time max_fsync_flush_time
*/
bd_lock(sbi);
seq_printf(seq, "%u %u %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu\n",
bd->fsync_reg_file_count, bd->fsync_dir_count, bd->fsync_time,
bd->max_fsync_time, bd->fsync_wr_file_time,
bd->max_fsync_wr_file_time, bd->fsync_cp_time,
bd->max_fsync_cp_time, bd->fsync_sync_node_time,
bd->max_fsync_sync_node_time, bd->fsync_flush_time,
bd->max_fsync_flush_time);
bd_unlock(sbi);
return 0;
}
static ssize_t of2fs_fsync_info_write(struct file *file,
const char __user *buf,
size_t length, loff_t *ppos)
{
struct seq_file *seq = file->private_data;
struct super_block *sb = seq->private;
struct f2fs_sb_info *sbi = F2FS_SB(sb);
struct f2fs_bigdata_info *bd = F2FS_BD_STAT(sbi);
char buffer[3] = {0};
if (!buf || length > 2 || length <= 0)
return -EINVAL;
if (copy_from_user(&buffer, buf, length))
return -EFAULT;
if (buffer[0] != '0')
return -EINVAL;
bd_lock(sbi);
bd->fsync_reg_file_count = 0;
bd->fsync_dir_count = 0;
bd->fsync_time = 0;
bd->max_fsync_time = 0;
bd->fsync_cp_time = 0;
bd->max_fsync_cp_time = 0;
bd->fsync_wr_file_time = 0;
bd->max_fsync_wr_file_time = 0;
bd->fsync_sync_node_time = 0;
bd->max_fsync_sync_node_time = 0;
bd->fsync_flush_time = 0;
bd->max_fsync_flush_time = 0;
bd_unlock(sbi);
return length;
}
static int of2fs_hotcold_info_show(struct seq_file *seq, void *p)
{
struct super_block *sb = seq->private;
struct f2fs_sb_info *sbi = F2FS_SB(sb);
struct f2fs_bigdata_info *bd = F2FS_BD_STAT(sbi);
bd_lock(sbi);
/*
* each colum indicates: hot_data_cnt, warm_data_cnt, cold_data_cnt, hot_node_cnt,
* warm_node_cnt, cold_node_cnt, meta_cp_cnt, meta_sit_cnt, meta_nat_cnt, meta_ssa_cnt,
* directio_cnt, gc_cold_data_cnt, rewrite_hot_data_cnt, rewrite_warm_data_cnt,
* gc_segment_hot_data_cnt, gc_segment_warm_data_cnt, gc_segment_cold_data_cnt,
* gc_segment_hot_node_cnt, gc_segment_warm_node_cnt, gc_segment_cold_node_cnt,
* gc_block_hot_data_cnt, gc_block_warm_data_cnt, gc_block_cold_data_cnt,
* gc_block_hot_node_cnt, gc_block_warm_node_cnt, gc_block_cold_node_cnt
*/
seq_printf(seq, "%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu "
"%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
bd->hotcold_count[HC_HOT_DATA], bd->hotcold_count[HC_WARM_DATA],
bd->hotcold_count[HC_COLD_DATA], bd->hotcold_count[HC_HOT_NODE],
bd->hotcold_count[HC_WARM_NODE], bd->hotcold_count[HC_COLD_NODE],
bd->hotcold_count[HC_META], bd->hotcold_count[HC_META_SB],
bd->hotcold_count[HC_META_CP], bd->hotcold_count[HC_META_SIT],
bd->hotcold_count[HC_META_NAT], bd->hotcold_count[HC_META_SSA],
bd->hotcold_count[HC_DIRECT_IO], bd->hotcold_count[HC_GC_COLD_DATA],
bd->hotcold_count[HC_REWRITE_HOT_DATA],
bd->hotcold_count[HC_REWRITE_WARM_DATA],
bd->hotcold_gc_segments[HC_HOT_DATA],
bd->hotcold_gc_segments[HC_WARM_DATA],
bd->hotcold_gc_segments[HC_COLD_DATA],
bd->hotcold_gc_segments[HC_HOT_NODE],
bd->hotcold_gc_segments[HC_WARM_NODE],
bd->hotcold_gc_segments[HC_COLD_NODE],
bd->hotcold_gc_blocks[HC_HOT_DATA],
bd->hotcold_gc_blocks[HC_WARM_DATA],
bd->hotcold_gc_blocks[HC_COLD_DATA],
bd->hotcold_gc_blocks[HC_HOT_NODE],
bd->hotcold_gc_blocks[HC_WARM_NODE],
bd->hotcold_gc_blocks[HC_COLD_NODE]);
bd_unlock(sbi);
return 0;
}
static ssize_t of2fs_hotcold_info_write(struct file *file,
const char __user *buf,
size_t length, loff_t *ppos)
{
struct seq_file *seq = file->private_data;
struct super_block *sb = seq->private;
struct f2fs_sb_info *sbi = F2FS_SB(sb);
struct f2fs_bigdata_info *bd = F2FS_BD_STAT(sbi);
char buffer[3] = {0};
int i;
if (!buf || length > 2 || length <= 0)
return -EINVAL;
if (copy_from_user(&buffer, buf, length))
return -EFAULT;
if (buffer[0] != '0')
return -EINVAL;
bd_lock(sbi);
for (i = 0; i < NR_HOTCOLD_TYPE; i++)
bd->hotcold_count[i] = 0;
for (i = 0; i < NR_CURSEG; i++) {
bd->hotcold_gc_segments[i] = 0;
bd->hotcold_gc_blocks[i] = 0;
}
bd_unlock(sbi);
return length;
}
OF2FS_PROC_DEF(base_info);
OF2FS_PROC_DEF(discard_info);
OF2FS_PROC_DEF(gc_info);
OF2FS_PROC_DEF(cp_info);
OF2FS_PROC_DEF(fsync_info);
OF2FS_PROC_DEF(hotcold_info);
void f2fs_build_bd_stat(struct f2fs_sb_info *sbi)
{
struct super_block *sb = sbi->sb;
proc_create_data("base_info", S_IRUGO | S_IWUGO, sbi->s_proc,
&of2fs_base_info_fops, sb);
proc_create_data("discard_info", S_IRUGO | S_IWUGO, sbi->s_proc,
&of2fs_discard_info_fops, sb);
proc_create_data("cp_info", S_IRUGO | S_IWUGO, sbi->s_proc,
&of2fs_cp_info_fops, sb);
proc_create_data("gc_info", S_IRUGO | S_IWUGO, sbi->s_proc,
&of2fs_gc_info_fops, sb);
proc_create_data("fsync_info", S_IRUGO | S_IWUGO, sbi->s_proc,
&of2fs_fsync_info_fops, sb);
proc_create_data("hotcold_info", S_IRUGO | S_IWUGO, sbi->s_proc,
&of2fs_hotcold_info_fops, sb);
}
void f2fs_destroy_bd_stat(struct f2fs_sb_info *sbi)
{
remove_proc_entry("base_info", sbi->s_proc);
remove_proc_entry("discard_info", sbi->s_proc);
remove_proc_entry("cp_info", sbi->s_proc);
remove_proc_entry("gc_info", sbi->s_proc);
remove_proc_entry("fsync_info", sbi->s_proc);
remove_proc_entry("hotcold_info", sbi->s_proc);
if (sbi->bd_info) {
kfree(sbi->bd_info);
sbi->bd_info = NULL;
}
}