@@ -60,6 +60,70 @@ void f2fs_update_sit_info(struct f2fs_sb_info *sbi)
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 );
@@ -214,6 +278,8 @@ static void update_general_status(struct f2fs_sb_info *sbi)
214
278
si -> valid_blks [type ] += blks ;
215
279
}
216
280
281
+ update_multidevice_stats (sbi );
282
+
217
283
for (i = 0 ; i < MAX_CALL_TYPE ; i ++ )
218
284
si -> cp_call_count [i ] = atomic_read (& sbi -> cp_call_count [i ]);
219
285
@@ -498,6 +564,36 @@ static int stat_show(struct seq_file *s, void *v)
498
564
si -> dirty_count );
499
565
seq_printf (s , " - Prefree: %d\n - Free: %d (%d)\n\n" ,
500
566
si -> prefree_count , si -> free_segs , si -> free_secs );
567
+ if (f2fs_is_multi_device (sbi )) {
568
+ seq_puts (s , "Multidevice stats:\n" );
569
+ seq_printf (s , " [seg: %8s %8s %8s %8s %8s]" ,
570
+ "inuse" , "dirty" , "full" , "free" , "prefree" );
571
+ if (__is_large_section (sbi ))
572
+ seq_printf (s , " [sec: %8s %8s %8s %8s %8s]\n" ,
573
+ "inuse" , "dirty" , "full" , "free" , "prefree" );
574
+ else
575
+ seq_puts (s , "\n" );
576
+
577
+ for (i = 0 ; i < sbi -> s_ndevs ; i ++ ) {
578
+ seq_printf (s , " #%-2d %8u %8u %8u %8u %8u" , i ,
579
+ si -> dev_stats [i ].devstats [0 ][DEVSTAT_INUSE ],
580
+ si -> dev_stats [i ].devstats [0 ][DEVSTAT_DIRTY ],
581
+ si -> dev_stats [i ].devstats [0 ][DEVSTAT_FULL ],
582
+ si -> dev_stats [i ].devstats [0 ][DEVSTAT_FREE ],
583
+ si -> dev_stats [i ].devstats [0 ][DEVSTAT_PREFREE ]);
584
+ if (!__is_large_section (sbi )) {
585
+ seq_puts (s , "\n" );
586
+ continue ;
587
+ }
588
+ seq_printf (s , " %8u %8u %8u %8u %8u\n" ,
589
+ si -> dev_stats [i ].devstats [1 ][DEVSTAT_INUSE ],
590
+ si -> dev_stats [i ].devstats [1 ][DEVSTAT_DIRTY ],
591
+ si -> dev_stats [i ].devstats [1 ][DEVSTAT_FULL ],
592
+ si -> dev_stats [i ].devstats [1 ][DEVSTAT_FREE ],
593
+ si -> dev_stats [i ].devstats [1 ][DEVSTAT_PREFREE ]);
594
+ }
595
+ seq_puts (s , "\n" );
596
+ }
501
597
seq_printf (s , "CP calls: %d (BG: %d)\n" ,
502
598
si -> cp_call_count [TOTAL_CALL ],
503
599
si -> cp_call_count [BACKGROUND ]);
@@ -665,13 +761,23 @@ int f2fs_build_stats(struct f2fs_sb_info *sbi)
665
761
{
666
762
struct f2fs_super_block * raw_super = F2FS_RAW_SUPER (sbi );
667
763
struct f2fs_stat_info * si ;
764
+ struct f2fs_dev_stats * dev_stats ;
668
765
unsigned long flags ;
669
766
int i ;
670
767
671
768
si = f2fs_kzalloc (sbi , sizeof (struct f2fs_stat_info ), GFP_KERNEL );
672
769
if (!si )
673
770
return - ENOMEM ;
674
771
772
+ dev_stats = f2fs_kzalloc (sbi , sizeof (struct f2fs_dev_stats ) *
773
+ sbi -> s_ndevs , GFP_KERNEL );
774
+ if (!dev_stats ) {
775
+ kfree (si );
776
+ return - ENOMEM ;
777
+ }
778
+
779
+ si -> dev_stats = dev_stats ;
780
+
675
781
si -> all_area_segs = le32_to_cpu (raw_super -> segment_count );
676
782
si -> sit_area_segs = le32_to_cpu (raw_super -> segment_count_sit );
677
783
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)
724
830
list_del (& si -> stat_list );
725
831
raw_spin_unlock_irqrestore (& f2fs_stat_lock , flags );
726
832
833
+ kfree (si -> dev_stats );
727
834
kfree (si );
728
835
}
729
836
0 commit comments