Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Chao Yu and committed by
Jaegeuk Kim
2d56b4e3 6babe00c

+121
+107
fs/f2fs/debug.c
··· 60 60 } 61 61 62 62 #ifdef CONFIG_DEBUG_FS 63 + static void update_multidevice_stats(struct f2fs_sb_info *sbi) 64 + { 65 + struct f2fs_stat_info *si = F2FS_STAT(sbi); 66 + struct f2fs_dev_stats *dev_stats = si->dev_stats; 67 + int i, j; 68 + 69 + if (!f2fs_is_multi_device(sbi)) 70 + return; 71 + 72 + memset(dev_stats, 0, sizeof(struct f2fs_dev_stats) * sbi->s_ndevs); 73 + for (i = 0; i < sbi->s_ndevs; i++) { 74 + unsigned int start_segno, end_segno; 75 + block_t start_blk, end_blk; 76 + 77 + if (i == 0) { 78 + start_blk = MAIN_BLKADDR(sbi); 79 + end_blk = FDEV(i).end_blk + 1 - SEG0_BLKADDR(sbi); 80 + } else { 81 + start_blk = FDEV(i).start_blk; 82 + end_blk = FDEV(i).end_blk + 1; 83 + } 84 + 85 + start_segno = GET_SEGNO(sbi, start_blk); 86 + end_segno = GET_SEGNO(sbi, end_blk); 87 + 88 + for (j = start_segno; j < end_segno; j++) { 89 + unsigned int seg_blks, sec_blks; 90 + 91 + seg_blks = get_seg_entry(sbi, j)->valid_blocks; 92 + 93 + /* update segment stats */ 94 + if (IS_CURSEG(sbi, j)) 95 + dev_stats[i].devstats[0][DEVSTAT_INUSE]++; 96 + else if (seg_blks == BLKS_PER_SEG(sbi)) 97 + dev_stats[i].devstats[0][DEVSTAT_FULL]++; 98 + else if (seg_blks != 0) 99 + dev_stats[i].devstats[0][DEVSTAT_DIRTY]++; 100 + else if (!test_bit(j, FREE_I(sbi)->free_segmap)) 101 + dev_stats[i].devstats[0][DEVSTAT_FREE]++; 102 + else 103 + dev_stats[i].devstats[0][DEVSTAT_PREFREE]++; 104 + 105 + if (!__is_large_section(sbi) || 106 + (j % SEGS_PER_SEC(sbi)) != 0) 107 + continue; 108 + 109 + sec_blks = get_sec_entry(sbi, j)->valid_blocks; 110 + 111 + /* update section stats */ 112 + if (IS_CURSEC(sbi, GET_SEC_FROM_SEG(sbi, j))) 113 + dev_stats[i].devstats[1][DEVSTAT_INUSE]++; 114 + else if (sec_blks == BLKS_PER_SEC(sbi)) 115 + dev_stats[i].devstats[1][DEVSTAT_FULL]++; 116 + else if (sec_blks != 0) 117 + dev_stats[i].devstats[1][DEVSTAT_DIRTY]++; 118 + else if (!test_bit(GET_SEC_FROM_SEG(sbi, j), 119 + FREE_I(sbi)->free_secmap)) 120 + dev_stats[i].devstats[1][DEVSTAT_FREE]++; 121 + else 122 + dev_stats[i].devstats[1][DEVSTAT_PREFREE]++; 123 + } 124 + } 125 + } 126 + 63 127 static void update_general_status(struct f2fs_sb_info *sbi) 64 128 { 65 129 struct f2fs_stat_info *si = F2FS_STAT(sbi); ··· 277 213 si->dirty_seg[type]++; 278 214 si->valid_blks[type] += blks; 279 215 } 216 + 217 + update_multidevice_stats(sbi); 280 218 281 219 for (i = 0; i < MAX_CALL_TYPE; i++) 282 220 si->cp_call_count[i] = atomic_read(&sbi->cp_call_count[i]); ··· 564 498 si->dirty_count); 565 499 seq_printf(s, " - Prefree: %d\n - Free: %d (%d)\n\n", 566 500 si->prefree_count, si->free_segs, si->free_secs); 501 + if (f2fs_is_multi_device(sbi)) { 502 + seq_puts(s, "Multidevice stats:\n"); 503 + seq_printf(s, " [seg: %8s %8s %8s %8s %8s]", 504 + "inuse", "dirty", "full", "free", "prefree"); 505 + if (__is_large_section(sbi)) 506 + seq_printf(s, " [sec: %8s %8s %8s %8s %8s]\n", 507 + "inuse", "dirty", "full", "free", "prefree"); 508 + else 509 + seq_puts(s, "\n"); 510 + 511 + for (i = 0; i < sbi->s_ndevs; i++) { 512 + seq_printf(s, " #%-2d %8u %8u %8u %8u %8u", i, 513 + si->dev_stats[i].devstats[0][DEVSTAT_INUSE], 514 + si->dev_stats[i].devstats[0][DEVSTAT_DIRTY], 515 + si->dev_stats[i].devstats[0][DEVSTAT_FULL], 516 + si->dev_stats[i].devstats[0][DEVSTAT_FREE], 517 + si->dev_stats[i].devstats[0][DEVSTAT_PREFREE]); 518 + if (!__is_large_section(sbi)) { 519 + seq_puts(s, "\n"); 520 + continue; 521 + } 522 + seq_printf(s, " %8u %8u %8u %8u %8u\n", 523 + si->dev_stats[i].devstats[1][DEVSTAT_INUSE], 524 + si->dev_stats[i].devstats[1][DEVSTAT_DIRTY], 525 + si->dev_stats[i].devstats[1][DEVSTAT_FULL], 526 + si->dev_stats[i].devstats[1][DEVSTAT_FREE], 527 + si->dev_stats[i].devstats[1][DEVSTAT_PREFREE]); 528 + } 529 + seq_puts(s, "\n"); 530 + } 567 531 seq_printf(s, "CP calls: %d (BG: %d)\n", 568 532 si->cp_call_count[TOTAL_CALL], 569 533 si->cp_call_count[BACKGROUND]); ··· 761 665 { 762 666 struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); 763 667 struct f2fs_stat_info *si; 668 + struct f2fs_dev_stats *dev_stats; 764 669 unsigned long flags; 765 670 int i; 766 671 767 672 si = f2fs_kzalloc(sbi, sizeof(struct f2fs_stat_info), GFP_KERNEL); 768 673 if (!si) 769 674 return -ENOMEM; 675 + 676 + dev_stats = f2fs_kzalloc(sbi, sizeof(struct f2fs_dev_stats) * 677 + sbi->s_ndevs, GFP_KERNEL); 678 + if (!dev_stats) { 679 + kfree(si); 680 + return -ENOMEM; 681 + } 682 + 683 + si->dev_stats = dev_stats; 770 684 771 685 si->all_area_segs = le32_to_cpu(raw_super->segment_count); 772 686 si->sit_area_segs = le32_to_cpu(raw_super->segment_count_sit); ··· 830 724 list_del(&si->stat_list); 831 725 raw_spin_unlock_irqrestore(&f2fs_stat_lock, flags); 832 726 727 + kfree(si->dev_stats); 833 728 kfree(si); 834 729 } 835 730
+14
fs/f2fs/f2fs.h
··· 3937 3937 * debug.c 3938 3938 */ 3939 3939 #ifdef CONFIG_F2FS_STAT_FS 3940 + enum { 3941 + DEVSTAT_INUSE, 3942 + DEVSTAT_DIRTY, 3943 + DEVSTAT_FULL, 3944 + DEVSTAT_FREE, 3945 + DEVSTAT_PREFREE, 3946 + DEVSTAT_MAX, 3947 + }; 3948 + 3949 + struct f2fs_dev_stats { 3950 + unsigned int devstats[2][DEVSTAT_MAX]; /* 0: segs, 1: secs */ 3951 + }; 3952 + 3940 3953 struct f2fs_stat_info { 3941 3954 struct list_head stat_list; 3942 3955 struct f2fs_sb_info *sbi; ··· 4013 4000 unsigned int block_count[2]; 4014 4001 unsigned int inplace_count; 4015 4002 unsigned long long base_mem, cache_mem, page_mem; 4003 + struct f2fs_dev_stats *dev_stats; 4016 4004 }; 4017 4005 4018 4006 static inline struct f2fs_stat_info *F2FS_STAT(struct f2fs_sb_info *sbi)