mirror of
https://github.com/torvalds/linux.git
synced 2024-12-19 17:41:29 +00:00
f2fs: multidevice: add stats in debugfs
This patch adds per-device stats in debugfs, the examples are as below: mkfs.f2fs -f -c /dev/vdc /dev/vdb mount /dev/vdb /mnt/f2fs/ cat /sys/kernel/debug/f2fs/status Multidevice stats: [seg: inuse dirty full free prefree] #0 5 0 0 4007 0 #1 1 0 0 8191 0 mkfs.f2fs -f -s 2 -c /dev/vdc /dev/vdb mount /dev/vdb /mnt/f2fs cat /sys/kernel/debug/f2fs/status Multidevice stats: [seg: inuse dirty full free prefree] [sec: inuse dirty full free prefree] #0 5 0 0 4005 0 5 0 0 2000 0 #1 1 0 0 8191 0 1 0 0 4095 0 Signed-off-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
parent
6babe00ccd
commit
2d56b4e391
107
fs/f2fs/debug.c
107
fs/f2fs/debug.c
@ -60,6 +60,70 @@ void f2fs_update_sit_info(struct f2fs_sb_info *sbi)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
static void update_multidevice_stats(struct f2fs_sb_info *sbi)
|
||||
{
|
||||
struct f2fs_stat_info *si = F2FS_STAT(sbi);
|
||||
struct f2fs_dev_stats *dev_stats = si->dev_stats;
|
||||
int i, j;
|
||||
|
||||
if (!f2fs_is_multi_device(sbi))
|
||||
return;
|
||||
|
||||
memset(dev_stats, 0, sizeof(struct f2fs_dev_stats) * sbi->s_ndevs);
|
||||
for (i = 0; i < sbi->s_ndevs; i++) {
|
||||
unsigned int start_segno, end_segno;
|
||||
block_t start_blk, end_blk;
|
||||
|
||||
if (i == 0) {
|
||||
start_blk = MAIN_BLKADDR(sbi);
|
||||
end_blk = FDEV(i).end_blk + 1 - SEG0_BLKADDR(sbi);
|
||||
} else {
|
||||
start_blk = FDEV(i).start_blk;
|
||||
end_blk = FDEV(i).end_blk + 1;
|
||||
}
|
||||
|
||||
start_segno = GET_SEGNO(sbi, start_blk);
|
||||
end_segno = GET_SEGNO(sbi, end_blk);
|
||||
|
||||
for (j = start_segno; j < end_segno; j++) {
|
||||
unsigned int seg_blks, sec_blks;
|
||||
|
||||
seg_blks = get_seg_entry(sbi, j)->valid_blocks;
|
||||
|
||||
/* update segment stats */
|
||||
if (IS_CURSEG(sbi, j))
|
||||
dev_stats[i].devstats[0][DEVSTAT_INUSE]++;
|
||||
else if (seg_blks == BLKS_PER_SEG(sbi))
|
||||
dev_stats[i].devstats[0][DEVSTAT_FULL]++;
|
||||
else if (seg_blks != 0)
|
||||
dev_stats[i].devstats[0][DEVSTAT_DIRTY]++;
|
||||
else if (!test_bit(j, FREE_I(sbi)->free_segmap))
|
||||
dev_stats[i].devstats[0][DEVSTAT_FREE]++;
|
||||
else
|
||||
dev_stats[i].devstats[0][DEVSTAT_PREFREE]++;
|
||||
|
||||
if (!__is_large_section(sbi) ||
|
||||
(j % SEGS_PER_SEC(sbi)) != 0)
|
||||
continue;
|
||||
|
||||
sec_blks = get_sec_entry(sbi, j)->valid_blocks;
|
||||
|
||||
/* update section stats */
|
||||
if (IS_CURSEC(sbi, GET_SEC_FROM_SEG(sbi, j)))
|
||||
dev_stats[i].devstats[1][DEVSTAT_INUSE]++;
|
||||
else if (sec_blks == BLKS_PER_SEC(sbi))
|
||||
dev_stats[i].devstats[1][DEVSTAT_FULL]++;
|
||||
else if (sec_blks != 0)
|
||||
dev_stats[i].devstats[1][DEVSTAT_DIRTY]++;
|
||||
else if (!test_bit(GET_SEC_FROM_SEG(sbi, j),
|
||||
FREE_I(sbi)->free_secmap))
|
||||
dev_stats[i].devstats[1][DEVSTAT_FREE]++;
|
||||
else
|
||||
dev_stats[i].devstats[1][DEVSTAT_PREFREE]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void update_general_status(struct f2fs_sb_info *sbi)
|
||||
{
|
||||
struct f2fs_stat_info *si = F2FS_STAT(sbi);
|
||||
@ -214,6 +278,8 @@ static void update_general_status(struct f2fs_sb_info *sbi)
|
||||
si->valid_blks[type] += blks;
|
||||
}
|
||||
|
||||
update_multidevice_stats(sbi);
|
||||
|
||||
for (i = 0; i < MAX_CALL_TYPE; i++)
|
||||
si->cp_call_count[i] = atomic_read(&sbi->cp_call_count[i]);
|
||||
|
||||
@ -498,6 +564,36 @@ static int stat_show(struct seq_file *s, void *v)
|
||||
si->dirty_count);
|
||||
seq_printf(s, " - Prefree: %d\n - Free: %d (%d)\n\n",
|
||||
si->prefree_count, si->free_segs, si->free_secs);
|
||||
if (f2fs_is_multi_device(sbi)) {
|
||||
seq_puts(s, "Multidevice stats:\n");
|
||||
seq_printf(s, " [seg: %8s %8s %8s %8s %8s]",
|
||||
"inuse", "dirty", "full", "free", "prefree");
|
||||
if (__is_large_section(sbi))
|
||||
seq_printf(s, " [sec: %8s %8s %8s %8s %8s]\n",
|
||||
"inuse", "dirty", "full", "free", "prefree");
|
||||
else
|
||||
seq_puts(s, "\n");
|
||||
|
||||
for (i = 0; i < sbi->s_ndevs; i++) {
|
||||
seq_printf(s, " #%-2d %8u %8u %8u %8u %8u", i,
|
||||
si->dev_stats[i].devstats[0][DEVSTAT_INUSE],
|
||||
si->dev_stats[i].devstats[0][DEVSTAT_DIRTY],
|
||||
si->dev_stats[i].devstats[0][DEVSTAT_FULL],
|
||||
si->dev_stats[i].devstats[0][DEVSTAT_FREE],
|
||||
si->dev_stats[i].devstats[0][DEVSTAT_PREFREE]);
|
||||
if (!__is_large_section(sbi)) {
|
||||
seq_puts(s, "\n");
|
||||
continue;
|
||||
}
|
||||
seq_printf(s, " %8u %8u %8u %8u %8u\n",
|
||||
si->dev_stats[i].devstats[1][DEVSTAT_INUSE],
|
||||
si->dev_stats[i].devstats[1][DEVSTAT_DIRTY],
|
||||
si->dev_stats[i].devstats[1][DEVSTAT_FULL],
|
||||
si->dev_stats[i].devstats[1][DEVSTAT_FREE],
|
||||
si->dev_stats[i].devstats[1][DEVSTAT_PREFREE]);
|
||||
}
|
||||
seq_puts(s, "\n");
|
||||
}
|
||||
seq_printf(s, "CP calls: %d (BG: %d)\n",
|
||||
si->cp_call_count[TOTAL_CALL],
|
||||
si->cp_call_count[BACKGROUND]);
|
||||
@ -665,6 +761,7 @@ int f2fs_build_stats(struct f2fs_sb_info *sbi)
|
||||
{
|
||||
struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
|
||||
struct f2fs_stat_info *si;
|
||||
struct f2fs_dev_stats *dev_stats;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
@ -672,6 +769,15 @@ int f2fs_build_stats(struct f2fs_sb_info *sbi)
|
||||
if (!si)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_stats = f2fs_kzalloc(sbi, sizeof(struct f2fs_dev_stats) *
|
||||
sbi->s_ndevs, GFP_KERNEL);
|
||||
if (!dev_stats) {
|
||||
kfree(si);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
si->dev_stats = dev_stats;
|
||||
|
||||
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);
|
||||
@ -724,6 +830,7 @@ void f2fs_destroy_stats(struct f2fs_sb_info *sbi)
|
||||
list_del(&si->stat_list);
|
||||
raw_spin_unlock_irqrestore(&f2fs_stat_lock, flags);
|
||||
|
||||
kfree(si->dev_stats);
|
||||
kfree(si);
|
||||
}
|
||||
|
||||
|
@ -3937,6 +3937,19 @@ void f2fs_destroy_recovery_cache(void);
|
||||
* debug.c
|
||||
*/
|
||||
#ifdef CONFIG_F2FS_STAT_FS
|
||||
enum {
|
||||
DEVSTAT_INUSE,
|
||||
DEVSTAT_DIRTY,
|
||||
DEVSTAT_FULL,
|
||||
DEVSTAT_FREE,
|
||||
DEVSTAT_PREFREE,
|
||||
DEVSTAT_MAX,
|
||||
};
|
||||
|
||||
struct f2fs_dev_stats {
|
||||
unsigned int devstats[2][DEVSTAT_MAX]; /* 0: segs, 1: secs */
|
||||
};
|
||||
|
||||
struct f2fs_stat_info {
|
||||
struct list_head stat_list;
|
||||
struct f2fs_sb_info *sbi;
|
||||
@ -4000,6 +4013,7 @@ struct f2fs_stat_info {
|
||||
unsigned int block_count[2];
|
||||
unsigned int inplace_count;
|
||||
unsigned long long base_mem, cache_mem, page_mem;
|
||||
struct f2fs_dev_stats *dev_stats;
|
||||
};
|
||||
|
||||
static inline struct f2fs_stat_info *F2FS_STAT(struct f2fs_sb_info *sbi)
|
||||
|
Loading…
Reference in New Issue
Block a user