blob: 86437977568291ecccf1eb00da42e54bb56b95d7 [file] [log] [blame]
Changman Leea0a55672014-01-10 17:44:59 +09001#include <stdio.h>
2#include <unistd.h>
3#include <stdlib.h>
4#include <string.h>
5#include <fcntl.h>
Changman Lee28d45d02014-01-29 13:36:54 +09006#include <libgen.h>
Changman Leea0a55672014-01-10 17:44:59 +09007
8#ifdef DEBUG
9#define dbg(fmt, args...) printf(fmt, __VA_ARGS__);
10#else
11#define dbg(fmt, args...)
12#endif
13
14/*
15 * f2fs status
16 */
17#define F2FS_STATUS "/sys/kernel/debug/f2fs/status"
18
Changman Lee4ff74002014-02-06 16:37:53 +090019#define KEY_NODE 0x00000001
20#define KEY_META 0x00000010
21
Changman Leea0a55672014-01-10 17:44:59 +090022unsigned long util;
23unsigned long used_node_blks;
24unsigned long used_data_blks;
25//unsigned long inline_inode;
26
27unsigned long free_segs;
28unsigned long valid_segs;
29unsigned long dirty_segs;
30unsigned long prefree_segs;
31
Changman Leeb7906af2014-02-13 15:13:22 +090032unsigned long gc, bg_gc;
33unsigned long cp;
Changman Leea0a55672014-01-10 17:44:59 +090034unsigned long gc_data_blks;
35unsigned long gc_node_blks;
36
37//unsigned long extent_hit_ratio;
38
Changman Lee4ff74002014-02-06 16:37:53 +090039unsigned long dirty_node, node_kb;
Changman Leea0a55672014-01-10 17:44:59 +090040unsigned long dirty_dents;
Changman Lee4ff74002014-02-06 16:37:53 +090041unsigned long dirty_meta, meta_kb;
Changman Leea0a55672014-01-10 17:44:59 +090042unsigned long nat_caches;
43unsigned long dirty_sit;
44
45unsigned long free_nids;
46
47unsigned long ssr_blks;
48unsigned long lfs_blks;
Changman Lee4ff74002014-02-06 16:37:53 +090049unsigned long memory_kb;
Changman Leea0a55672014-01-10 17:44:59 +090050
51struct options {
52 int delay;
53 int interval;
Changman Lee28d45d02014-01-29 13:36:54 +090054 char partname[32];
Changman Leea0a55672014-01-10 17:44:59 +090055};
56
57struct mm_table {
58 const char *name;
59 unsigned long *val;
Changman Lee4ff74002014-02-06 16:37:53 +090060 int flag;
Changman Leea0a55672014-01-10 17:44:59 +090061};
62
63static int compare_mm_table(const void *a, const void *b)
64{
65 dbg("[COMPARE] %s, %s\n", ((struct mm_table *)a)->name, ((struct mm_table *)b)->name);
66 return strcmp(((struct mm_table *)a)->name, ((struct mm_table *)b)->name);
67}
68
69static inline void remove_newline(char **head)
70{
71again:
72 if (**head == '\n') {
73 *head = *head + 1;
74 goto again;
75 }
76}
77
Changman Lee28d45d02014-01-29 13:36:54 +090078void f2fstat(struct options *opt)
Changman Leea0a55672014-01-10 17:44:59 +090079{
80 int fd;
81 int ret;
82 char keyname[32];
83 char buf[4096];
84 struct mm_table key = { keyname, NULL };
85 struct mm_table *found;
86 int f2fstat_table_cnt;
87 char *head, *tail;
Changman Lee28d45d02014-01-29 13:36:54 +090088 int found_cnt = 0;
Changman Leea0a55672014-01-10 17:44:59 +090089
90 static struct mm_table f2fstat_table[] = {
Changman Lee4ff74002014-02-06 16:37:53 +090091 { " - Data", &used_data_blks, 0 },
92 { " - Dirty", &dirty_segs, 0 },
93 { " - Free", &free_segs, 0 },
94 { " - NATs", &nat_caches, 0 },
95 { " - Node", &used_node_blks, 0 },
96 { " - Prefree", &prefree_segs, 0 },
97 { " - SITs", &dirty_sit, 0 },
98 { " - Valid", &valid_segs, 0 },
99 { " - dents", &dirty_dents, 0 },
Changman Leec15df222014-02-13 15:13:23 +0900100 { " - free_nids", &free_nids, 0 },
Changman Lee4ff74002014-02-06 16:37:53 +0900101 { " - meta", &dirty_meta, KEY_META },
102 { " - nodes", &dirty_node, KEY_NODE },
Changman Leeb7906af2014-02-13 15:13:22 +0900103 { "CP calls", &cp, 0 },
Changman Lee4ff74002014-02-06 16:37:53 +0900104 { "GC calls", &gc, 0 },
105 { "LFS", &lfs_blks, 0 },
106 { "Memory", &memory_kb, 0 },
107 { "SSR", &ssr_blks, 0 },
108 { "Utilization", &util, 0 },
Changman Leea0a55672014-01-10 17:44:59 +0900109 };
110
111 f2fstat_table_cnt = sizeof(f2fstat_table)/sizeof(struct mm_table);
112
113 fd = open(F2FS_STATUS, O_RDONLY);
114 if (fd < 0) {
115 perror("open " F2FS_STATUS);
116 exit(EXIT_FAILURE);
117 }
118
119 ret = read(fd, buf, 4096);
120 if (ret < 0) {
121 perror("read " F2FS_STATUS);
122 exit(EXIT_FAILURE);
123 }
124 buf[ret] = '\0';
125
126 head = buf;
Changman Lee28d45d02014-01-29 13:36:54 +0900127
128 if (opt->partname[0] != '\0') {
129 head = strstr(buf, opt->partname);
130 if (head == NULL)
131 exit(EXIT_FAILURE);
132 }
133
Changman Leea0a55672014-01-10 17:44:59 +0900134 for (;;) {
135 remove_newline(&head);
136 tail = strchr(head, ':');
137 if (!tail)
138 break;
139 *tail = '\0';
140 if (strlen(head) >= sizeof(keyname)) {
141 dbg("[OVER] %s\n", head);
142 *tail = ':';
143 tail = strchr(head, '\n');
144 head = tail + 1;
145 continue;
146 }
147
148 strcpy(keyname, head);
149
150 found = bsearch(&key, f2fstat_table, f2fstat_table_cnt, sizeof(struct mm_table), compare_mm_table);
151 dbg("[RESULT] %s (%s)\n", head, (found) ? "O" : "X");
152 head = tail + 1;
153 if (!found)
154 goto nextline;
155
156 *(found->val) = strtoul(head, &tail, 10);
Changman Lee4ff74002014-02-06 16:37:53 +0900157 if (found->flag) {
158 int npages;
159 tail = strstr(head, "in");
160 head = tail + 2;
161 npages = strtoul(head, &tail, 10);
162 switch (found->flag & (KEY_NODE | KEY_META)) {
163 case KEY_NODE:
164 node_kb = npages * 4;
165 break;
166 case KEY_META:
167 meta_kb = npages * 4;
168 break;
169 }
170 }
Changman Lee28d45d02014-01-29 13:36:54 +0900171 if (++found_cnt == f2fstat_table_cnt)
172 break;
Changman Leea0a55672014-01-10 17:44:59 +0900173nextline:
174 tail = strchr(head, '\n');
175 if (!tail)
176 break;
177 head = tail + 1;
178 }
179
180 close(fd);
181}
182
183void usage(void)
184{
185 printf("Usage: f2fstat [option]\n"
186 " -d delay (secs)\n"
Changman Lee28d45d02014-01-29 13:36:54 +0900187 " -i interval of head info\n"
188 " -p partition name (e.g. /dev/sda3)\n");
Changman Leea0a55672014-01-10 17:44:59 +0900189 exit(EXIT_FAILURE);
190}
191
192void parse_option(int argc, char *argv[], struct options *opt)
193{
194 char option;
Changman Lee28d45d02014-01-29 13:36:54 +0900195 const char *option_string = "d:i:p:h";
Changman Leea0a55672014-01-10 17:44:59 +0900196
197 while ((option = getopt(argc, argv, option_string)) != EOF) {
198 switch (option) {
199 case 'd':
200 opt->delay = atoi(optarg);
201 break;
202 case 'i':
203 opt->interval = atoi(optarg);
204 break;
Changman Lee28d45d02014-01-29 13:36:54 +0900205 case 'p':
206 strcpy(opt->partname, basename(optarg));
207 break;
Changman Leea0a55672014-01-10 17:44:59 +0900208 default:
209 usage();
210 break;
211 }
212 }
213}
214
Jaegeuk Kimd83693c2014-09-19 03:35:53 +0900215void __make_head(char *head, int index, int i, int len)
Changman Leea0a55672014-01-10 17:44:59 +0900216{
Jaegeuk Kimd83693c2014-09-19 03:35:53 +0900217 char name_h[5][20] = {"main segments", "page/slab caches", "cp/gc", "blks", "memory"};
218 int half = (len - strlen(name_h[i])) / 2;
219
220 *(head + index) = '|';
221 index++;
222 memset(head + index, '-', half);
223 index += half;
224 strcpy(head + index, name_h[i]);
225 index += strlen(name_h[i]);
226 memset(head + index, '-', half);
227}
228
229void print_head(char *res)
230{
231 char *ptr, *ptr_buf;
232 char buf[1024], head[1024];
233 char name[20][10] = {"util", "node", "data", "free", "valid", "dirty", "prefree", "node", "dent", "meta",
234 "sit", "nat", "fnid", "cp", "gc", "ssr", "lfs", "total", "node", "meta"};
235 int i, len, prev_index = 0;
236
237 ptr_buf = buf;
238 memset(buf, ' ', 1024);
239 memset(head, ' ', 1024);
240
241 for (i = 0; i < 20; i++) {
242 ptr = (i == 0) ? strtok(res, " ") : strtok(NULL, " ");
243 strncpy(ptr_buf, name[i], strlen(name[i]));
244 if (i == 1) {
245 prev_index = ptr_buf - buf - 1;
246 } else if (i == 7) {
247 len = (ptr_buf - buf) - 1 - prev_index;
248 __make_head(head, prev_index, 0, len);
249 prev_index = ptr_buf - buf - 1;
250 } else if (i == 13) {
251 len = (ptr_buf - buf) - 1 - prev_index;
252 __make_head(head, prev_index, 1, len);
253 prev_index = ptr_buf - buf - 1;
254 } else if (i == 15) {
255 len = (ptr_buf - buf) - 1 - prev_index;
256 __make_head(head, prev_index, 2, len);
257 prev_index = ptr_buf - buf - 1;
258 } else if (i == 17) {
259 len = (ptr_buf - buf) - 1 - prev_index;
260 __make_head(head, prev_index, 3, len);
261 prev_index = ptr_buf - buf - 1;
262 }
263
264 len = strlen(ptr);
265 ptr_buf += (len > strlen(name[i]) ? len : strlen(name[i])) + 1;
266 }
267
268 len = (ptr_buf - buf) - 1 - prev_index;
269 __make_head(head, prev_index, 4, len);
270
271 *ptr_buf = 0;
272 *(head + (ptr_buf - buf - 1)) = '|';
273 *(head + (ptr_buf - buf)) = 0;
274 fprintf(stderr, "%s\n%s\n", head, buf);
Changman Leea0a55672014-01-10 17:44:59 +0900275}
276
277int main(int argc, char *argv[])
278{
Jaegeuk Kimd83693c2014-09-19 03:35:53 +0900279 char format[] = "%4ld %4ld %4ld %4ld %5ld %5ld %7ld %4ld %4ld %4ld %3ld %3ld %4ld %2ld %2ld %3ld %3ld %5ld %4ld %4ld";
280 char buf[1024], tmp[1024];
Changman Leea0a55672014-01-10 17:44:59 +0900281 int head_interval;
282 struct options opt = {
283 .delay = 1,
284 .interval = 20,
Changman Lee28d45d02014-01-29 13:36:54 +0900285 .partname = { 0, },
Changman Leea0a55672014-01-10 17:44:59 +0900286 };
287
288 parse_option(argc, argv, &opt);
289 head_interval = opt.interval;
290
Changman Leea0a55672014-01-10 17:44:59 +0900291 while (1) {
Jaegeuk Kimd83693c2014-09-19 03:35:53 +0900292 memset(buf, 0, 1024);
Changman Lee28d45d02014-01-29 13:36:54 +0900293 f2fstat(&opt);
Jaegeuk Kimd83693c2014-09-19 03:35:53 +0900294 sprintf(buf, format, util, used_node_blks, used_data_blks,
Changman Lee4ff74002014-02-06 16:37:53 +0900295 free_segs, valid_segs, dirty_segs, prefree_segs,
Changman Leec15df222014-02-13 15:13:23 +0900296 dirty_node, dirty_dents, dirty_meta, dirty_sit, nat_caches, free_nids,
Changman Leeb7906af2014-02-13 15:13:22 +0900297 cp, gc, ssr_blks, lfs_blks, memory_kb, node_kb, meta_kb);
Changman Leea0a55672014-01-10 17:44:59 +0900298
Jaegeuk Kimd83693c2014-09-19 03:35:53 +0900299 strcpy(tmp, buf);
300 if (head_interval == opt.interval)
301 print_head(tmp);
302 if (head_interval-- == 0)
303 head_interval = opt.interval;
304
305 fprintf(stderr, "%s\n", buf);
306
Changman Leea0a55672014-01-10 17:44:59 +0900307 sleep(opt.delay);
308 }
309
310 return 0;
311}