Skip to content

Commit a0a5567

Browse files
Changman LeeJaegeuk Kim
Changman Lee
authored and
Jaegeuk Kim
committed
f2fs-tools: add f2fstat to print f2fs's status in sec
This tool prints /sys/kernel/debug/f2fs/status in sec so that we can monitor variation of f2fs status. Signed-off-by: Changman Lee <[email protected]> Signed-off-by: Jaegeuk Kim <[email protected]>
1 parent 6da3010 commit a0a5567

File tree

4 files changed

+223
-1
lines changed

4 files changed

+223
-1
lines changed

Makefile.am

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22

33
ACLOCAL_AMFLAGS = -I m4
44

5-
SUBDIRS = man lib mkfs fsck
5+
SUBDIRS = man lib mkfs fsck tools

configure.ac

+1
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ AC_CONFIG_FILES([
8383
lib/Makefile
8484
mkfs/Makefile
8585
fsck/Makefile
86+
tools/Makefile
8687
])
8788

8889
AC_OUTPUT

tools/Makefile.am

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
## Makefile.am
2+
3+
AM_CPPFLAGS = ${libuuid_CFLAGS} -I$(top_srcdir)/include
4+
AM_CFLAGS = -Wall
5+
sbin_PROGRAMS = f2fstat
6+
f2fstat_SOURCES = f2fstat.c
7+
f2fstat_LDADD = ${libuuid_LIBS} $(top_builddir)/lib/libf2fs.la

tools/f2fstat.c

+214
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
#include <stdio.h>
2+
#include <unistd.h>
3+
#include <stdlib.h>
4+
#include <string.h>
5+
#include <fcntl.h>
6+
7+
#ifdef DEBUG
8+
#define dbg(fmt, args...) printf(fmt, __VA_ARGS__);
9+
#else
10+
#define dbg(fmt, args...)
11+
#endif
12+
13+
/*
14+
* f2fs status
15+
*/
16+
#define F2FS_STATUS "/sys/kernel/debug/f2fs/status"
17+
18+
unsigned long util;
19+
unsigned long used_node_blks;
20+
unsigned long used_data_blks;
21+
//unsigned long inline_inode;
22+
23+
unsigned long free_segs;
24+
unsigned long valid_segs;
25+
unsigned long dirty_segs;
26+
unsigned long prefree_segs;
27+
28+
unsigned long gc;
29+
unsigned long bg_gc;
30+
unsigned long gc_data_blks;
31+
unsigned long gc_node_blks;
32+
33+
//unsigned long extent_hit_ratio;
34+
35+
unsigned long dirty_node;
36+
unsigned long dirty_dents;
37+
unsigned long dirty_meta;
38+
unsigned long nat_caches;
39+
unsigned long dirty_sit;
40+
41+
unsigned long free_nids;
42+
43+
unsigned long ssr_blks;
44+
unsigned long lfs_blks;
45+
46+
47+
struct options {
48+
int delay;
49+
int interval;
50+
};
51+
52+
struct mm_table {
53+
const char *name;
54+
unsigned long *val;
55+
};
56+
57+
static int compare_mm_table(const void *a, const void *b)
58+
{
59+
dbg("[COMPARE] %s, %s\n", ((struct mm_table *)a)->name, ((struct mm_table *)b)->name);
60+
return strcmp(((struct mm_table *)a)->name, ((struct mm_table *)b)->name);
61+
}
62+
63+
static inline void remove_newline(char **head)
64+
{
65+
again:
66+
if (**head == '\n') {
67+
*head = *head + 1;
68+
goto again;
69+
}
70+
}
71+
72+
void f2fstat(void)
73+
{
74+
int fd;
75+
int ret;
76+
char keyname[32];
77+
char buf[4096];
78+
struct mm_table key = { keyname, NULL };
79+
struct mm_table *found;
80+
int f2fstat_table_cnt;
81+
char *head, *tail;
82+
83+
static struct mm_table f2fstat_table[] = {
84+
{ " - Data", &used_data_blks },
85+
{ " - Dirty", &dirty_segs },
86+
{ " - Free", &free_segs },
87+
{ " - NATs", &nat_caches },
88+
{ " - Node", &used_node_blks },
89+
{ " - Prefree", &prefree_segs },
90+
{ " - SITs", &dirty_sit },
91+
{ " - Valid", &valid_segs },
92+
{ " - dents", &dirty_dents },
93+
{ " - meta", &dirty_meta },
94+
{ " - nodes", &dirty_node },
95+
{ "GC calls", &gc },
96+
{ "LFS", &lfs_blks },
97+
{ "SSR", &ssr_blks },
98+
{ "Utilization", &util },
99+
};
100+
101+
f2fstat_table_cnt = sizeof(f2fstat_table)/sizeof(struct mm_table);
102+
103+
fd = open(F2FS_STATUS, O_RDONLY);
104+
if (fd < 0) {
105+
perror("open " F2FS_STATUS);
106+
exit(EXIT_FAILURE);
107+
}
108+
109+
ret = read(fd, buf, 4096);
110+
if (ret < 0) {
111+
perror("read " F2FS_STATUS);
112+
exit(EXIT_FAILURE);
113+
}
114+
buf[ret] = '\0';
115+
116+
head = buf;
117+
for (;;) {
118+
remove_newline(&head);
119+
tail = strchr(head, ':');
120+
if (!tail)
121+
break;
122+
*tail = '\0';
123+
if (strlen(head) >= sizeof(keyname)) {
124+
dbg("[OVER] %s\n", head);
125+
*tail = ':';
126+
tail = strchr(head, '\n');
127+
head = tail + 1;
128+
continue;
129+
}
130+
131+
strcpy(keyname, head);
132+
133+
found = bsearch(&key, f2fstat_table, f2fstat_table_cnt, sizeof(struct mm_table), compare_mm_table);
134+
dbg("[RESULT] %s (%s)\n", head, (found) ? "O" : "X");
135+
head = tail + 1;
136+
if (!found)
137+
goto nextline;
138+
139+
*(found->val) = strtoul(head, &tail, 10);
140+
nextline:
141+
tail = strchr(head, '\n');
142+
if (!tail)
143+
break;
144+
head = tail + 1;
145+
}
146+
147+
close(fd);
148+
}
149+
150+
void usage(void)
151+
{
152+
printf("Usage: f2fstat [option]\n"
153+
" -d delay (secs)\n"
154+
" -i interval of head info\n");
155+
exit(EXIT_FAILURE);
156+
}
157+
158+
void parse_option(int argc, char *argv[], struct options *opt)
159+
{
160+
char option;
161+
const char *option_string = "d:i:h";
162+
163+
while ((option = getopt(argc, argv, option_string)) != EOF) {
164+
switch (option) {
165+
case 'd':
166+
opt->delay = atoi(optarg);
167+
break;
168+
case 'i':
169+
opt->interval = atoi(optarg);
170+
break;
171+
default:
172+
usage();
173+
break;
174+
}
175+
}
176+
}
177+
178+
void print_head(void)
179+
{
180+
printf("---utilization--- -----------main area-------- ---balancing async-- -gc- ---alloc---\n");
181+
printf("util node data free valid dirty prefree node dent meta sit gc ssr lfs\n");
182+
}
183+
184+
int main(int argc, char *argv[])
185+
{
186+
char format[] = "%3ld %6ld %6ld %6ld %6ld %6ld %6ld %5ld %5ld %3ld %3ld %5ld %6ld %6ld\n";
187+
int head_interval;
188+
struct options opt = {
189+
.delay = 1,
190+
.interval = 20,
191+
};
192+
193+
parse_option(argc, argv, &opt);
194+
head_interval = opt.interval;
195+
196+
print_head();
197+
while (1) {
198+
if (head_interval-- == 0) {
199+
print_head();
200+
head_interval = opt.interval;
201+
}
202+
203+
f2fstat();
204+
205+
printf(format, util, used_node_blks, used_data_blks,
206+
free_segs, valid_segs, dirty_segs, prefree_segs,
207+
dirty_node, dirty_dents, dirty_meta, dirty_sit,
208+
gc, ssr_blks, lfs_blks);
209+
210+
sleep(opt.delay);
211+
}
212+
213+
return 0;
214+
}

0 commit comments

Comments
 (0)