]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - fs/f2fs/debug.c
f2fs: show issued flush/discard count
[mirror_ubuntu-bionic-kernel.git] / fs / f2fs / debug.c
CommitLineData
0a8165d7 1/*
902829aa
GKH
2 * f2fs debugging statistics
3 *
4 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com/
6 * Copyright (c) 2012 Linux Foundation
7 * Copyright (c) 2012 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/fs.h>
15#include <linux/backing-dev.h>
902829aa
GKH
16#include <linux/f2fs_fs.h>
17#include <linux/blkdev.h>
18#include <linux/debugfs.h>
19#include <linux/seq_file.h>
20
21#include "f2fs.h"
22#include "node.h"
23#include "segment.h"
24#include "gc.h"
25
26static LIST_HEAD(f2fs_stat_list);
40e1ebe9 27static struct dentry *f2fs_debugfs_root;
66af62ce 28static DEFINE_MUTEX(f2fs_stat_mutex);
902829aa 29
25ca923b 30static void update_general_status(struct f2fs_sb_info *sbi)
902829aa 31{
963d4f7d 32 struct f2fs_stat_info *si = F2FS_STAT(sbi);
902829aa
GKH
33 int i;
34
e1c42045 35 /* validation check of the segment numbers */
5b7ee374
CY
36 si->hit_largest = atomic64_read(&sbi->read_hit_largest);
37 si->hit_cached = atomic64_read(&sbi->read_hit_cached);
38 si->hit_rbtree = atomic64_read(&sbi->read_hit_rbtree);
029e13cc 39 si->hit_total = si->hit_largest + si->hit_cached + si->hit_rbtree;
5b7ee374 40 si->total_ext = atomic64_read(&sbi->total_hit_ext);
7441ccef 41 si->ext_tree = atomic_read(&sbi->total_ext_tree);
c00ba554 42 si->zombie_tree = atomic_read(&sbi->total_zombie_tree);
4bf6fd9f 43 si->ext_node = atomic_read(&sbi->total_ext_node);
902829aa
GKH
44 si->ndirty_node = get_pages(sbi, F2FS_DIRTY_NODES);
45 si->ndirty_dent = get_pages(sbi, F2FS_DIRTY_DENTS);
902829aa 46 si->ndirty_meta = get_pages(sbi, F2FS_DIRTY_META);
33fbd510 47 si->ndirty_data = get_pages(sbi, F2FS_DIRTY_DATA);
5bc994a0 48 si->ndirty_imeta = get_pages(sbi, F2FS_DIRTY_IMETA);
33fbd510
CY
49 si->ndirty_dirs = sbi->ndirty_inode[DIR_INODE];
50 si->ndirty_files = sbi->ndirty_inode[FILE_INODE];
0f18b462 51 si->ndirty_all = sbi->ndirty_inode[DIRTY_META];
8dcf2ff7 52 si->inmem_pages = get_pages(sbi, F2FS_INMEM_PAGES);
26a28a0c 53 si->aw_cnt = atomic_read(&sbi->aw_cnt);
648d50ba 54 si->vw_cnt = atomic_read(&sbi->vw_cnt);
26a28a0c 55 si->max_aw_cnt = atomic_read(&sbi->max_aw_cnt);
648d50ba 56 si->max_vw_cnt = atomic_read(&sbi->max_vw_cnt);
36951b38
CY
57 si->nr_wb_cp_data = get_pages(sbi, F2FS_WB_CP_DATA);
58 si->nr_wb_data = get_pages(sbi, F2FS_WB_DATA);
8b8dd65f
CY
59 if (SM_I(sbi) && SM_I(sbi)->fcc_info) {
60 si->nr_flushed =
61 atomic_read(&SM_I(sbi)->fcc_info->issued_flush);
62 si->nr_flushing =
63 atomic_read(&SM_I(sbi)->fcc_info->issing_flush);
64 }
65 if (SM_I(sbi) && SM_I(sbi)->dcc_info) {
66 si->nr_discarded =
67 atomic_read(&SM_I(sbi)->dcc_info->issued_discard);
68 si->nr_discarding =
69 atomic_read(&SM_I(sbi)->dcc_info->issing_discard);
70 }
902829aa
GKH
71 si->total_count = (int)sbi->user_block_count / sbi->blocks_per_seg;
72 si->rsvd_segs = reserved_segments(sbi);
73 si->overp_segs = overprovision_segments(sbi);
74 si->valid_count = valid_user_blocks(sbi);
f83a2584 75 si->discard_blks = discard_blocks(sbi);
902829aa
GKH
76 si->valid_node_count = valid_node_count(sbi);
77 si->valid_inode_count = valid_inode_count(sbi);
d5e8f6c9 78 si->inline_xattr = atomic_read(&sbi->inline_xattr);
03e14d52
CY
79 si->inline_inode = atomic_read(&sbi->inline_inode);
80 si->inline_dir = atomic_read(&sbi->inline_dir);
a00861db
JK
81 si->append = sbi->im[APPEND_INO].ino_num;
82 si->update = sbi->im[UPDATE_INO].ino_num;
652be551 83 si->orphans = sbi->im[ORPHAN_INO].ino_num;
902829aa
GKH
84 si->utilization = utilization(sbi);
85
86 si->free_segs = free_segments(sbi);
87 si->free_secs = free_sections(sbi);
88 si->prefree_count = prefree_segments(sbi);
89 si->dirty_count = dirty_segments(sbi);
4ef51a8f 90 si->node_pages = NODE_MAPPING(sbi)->nrpages;
9df27d98 91 si->meta_pages = META_MAPPING(sbi)->nrpages;
902829aa 92 si->nats = NM_I(sbi)->nat_cnt;
dd4e4b59
JK
93 si->dirty_nats = NM_I(sbi)->dirty_nat_cnt;
94 si->sits = MAIN_SEGS(sbi);
95 si->dirty_sits = SIT_I(sbi)->dirty_sentries;
b8559dc2
CY
96 si->free_nids = NM_I(sbi)->nid_cnt[FREE_NID_LIST];
97 si->alloc_nids = NM_I(sbi)->nid_cnt[ALLOC_NID_LIST];
902829aa
GKH
98 si->bg_gc = sbi->bg_gc;
99 si->util_free = (int)(free_user_blocks(sbi) >> sbi->log_blocks_per_seg)
100 * 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
101 / 2;
102 si->util_valid = (int)(written_block_count(sbi) >>
103 sbi->log_blocks_per_seg)
104 * 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
105 / 2;
106 si->util_invalid = 50 - si->util_free - si->util_valid;
107 for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_NODE; i++) {
108 struct curseg_info *curseg = CURSEG_I(sbi, i);
109 si->curseg[i] = curseg->segno;
110 si->cursec[i] = curseg->segno / sbi->segs_per_sec;
111 si->curzone[i] = si->cursec[i] / sbi->secs_per_zone;
112 }
113
114 for (i = 0; i < 2; i++) {
115 si->segment_count[i] = sbi->segment_count[i];
116 si->block_count[i] = sbi->block_count[i];
117 }
b9a2c252
CL
118
119 si->inplace_count = atomic_read(&sbi->inplace_count);
902829aa
GKH
120}
121
0a8165d7 122/*
902829aa
GKH
123 * This function calculates BDF of every segments
124 */
125static void update_sit_info(struct f2fs_sb_info *sbi)
126{
963d4f7d 127 struct f2fs_stat_info *si = F2FS_STAT(sbi);
3589a919
JK
128 unsigned long long blks_per_sec, hblks_per_sec, total_vblocks;
129 unsigned long long bimodal, dist;
902829aa
GKH
130 unsigned int segno, vblocks;
131 int ndirty = 0;
132
133 bimodal = 0;
134 total_vblocks = 0;
3519e3f9 135 blks_per_sec = sbi->segs_per_sec * sbi->blocks_per_seg;
902829aa 136 hblks_per_sec = blks_per_sec / 2;
7cd8558b 137 for (segno = 0; segno < MAIN_SEGS(sbi); segno += sbi->segs_per_sec) {
902829aa
GKH
138 vblocks = get_valid_blocks(sbi, segno, sbi->segs_per_sec);
139 dist = abs(vblocks - hblks_per_sec);
140 bimodal += dist * dist;
141
142 if (vblocks > 0 && vblocks < blks_per_sec) {
143 total_vblocks += vblocks;
144 ndirty++;
145 }
146 }
7beb428e 147 dist = div_u64(MAIN_SECS(sbi) * hblks_per_sec * hblks_per_sec, 100);
1d7e10d5 148 si->bimodal = div64_u64(bimodal, dist);
902829aa 149 if (si->dirty_count)
7beb428e 150 si->avg_vblocks = div_u64(total_vblocks, ndirty);
902829aa
GKH
151 else
152 si->avg_vblocks = 0;
153}
154
0a8165d7 155/*
902829aa
GKH
156 * This function calculates memory footprint.
157 */
158static void update_mem_info(struct f2fs_sb_info *sbi)
159{
963d4f7d 160 struct f2fs_stat_info *si = F2FS_STAT(sbi);
902829aa 161 unsigned npages;
8c402946 162 int i;
902829aa
GKH
163
164 if (si->base_mem)
165 goto get_cache;
166
70874fb3
KM
167 /* build stat */
168 si->base_mem = sizeof(struct f2fs_stat_info);
169
170 /* build superblock */
171 si->base_mem += sizeof(struct f2fs_sb_info) + sbi->sb->s_blocksize;
902829aa
GKH
172 si->base_mem += 2 * sizeof(struct f2fs_inode_info);
173 si->base_mem += sizeof(*sbi->ckpt);
523be8a6 174 si->base_mem += sizeof(struct percpu_counter) * NR_COUNT_TYPE;
902829aa
GKH
175
176 /* build sm */
177 si->base_mem += sizeof(struct f2fs_sm_info);
178
179 /* build sit */
180 si->base_mem += sizeof(struct sit_info);
7cd8558b
JK
181 si->base_mem += MAIN_SEGS(sbi) * sizeof(struct seg_entry);
182 si->base_mem += f2fs_bitmap_size(MAIN_SEGS(sbi));
3e025740
JK
183 si->base_mem += 2 * SIT_VBLOCK_MAP_SIZE * MAIN_SEGS(sbi);
184 if (f2fs_discard_en(sbi))
185 si->base_mem += SIT_VBLOCK_MAP_SIZE * MAIN_SEGS(sbi);
60a3b782 186 si->base_mem += SIT_VBLOCK_MAP_SIZE;
902829aa 187 if (sbi->segs_per_sec > 1)
7cd8558b 188 si->base_mem += MAIN_SECS(sbi) * sizeof(struct sec_entry);
902829aa
GKH
189 si->base_mem += __bitmap_size(sbi, SIT_BITMAP);
190
191 /* build free segmap */
192 si->base_mem += sizeof(struct free_segmap_info);
7cd8558b
JK
193 si->base_mem += f2fs_bitmap_size(MAIN_SEGS(sbi));
194 si->base_mem += f2fs_bitmap_size(MAIN_SECS(sbi));
902829aa
GKH
195
196 /* build curseg */
197 si->base_mem += sizeof(struct curseg_info) * NR_CURSEG_TYPE;
09cbfeaf 198 si->base_mem += PAGE_SIZE * NR_CURSEG_TYPE;
902829aa
GKH
199
200 /* build dirty segmap */
201 si->base_mem += sizeof(struct dirty_seglist_info);
7cd8558b
JK
202 si->base_mem += NR_DIRTY_TYPE * f2fs_bitmap_size(MAIN_SEGS(sbi));
203 si->base_mem += f2fs_bitmap_size(MAIN_SECS(sbi));
902829aa 204
e1c42045 205 /* build nm */
902829aa
GKH
206 si->base_mem += sizeof(struct f2fs_nm_info);
207 si->base_mem += __bitmap_size(sbi, NAT_BITMAP);
22ad0b6a 208 si->base_mem += (NM_I(sbi)->nat_bits_blocks << F2FS_BLKSIZE_BITS);
4ac91242
CY
209 si->base_mem += NM_I(sbi)->nat_blocks * NAT_ENTRY_BITMAP_SIZE;
210 si->base_mem += NM_I(sbi)->nat_blocks / 8;
586d1492 211 si->base_mem += NM_I(sbi)->nat_blocks * sizeof(unsigned short);
902829aa 212
9066c6a7
CY
213get_cache:
214 si->cache_mem = 0;
215
902829aa 216 /* build gc */
9066c6a7
CY
217 if (sbi->gc_thread)
218 si->cache_mem += sizeof(struct f2fs_gc_kthread);
219
220 /* build merge flush thread */
b01a9201 221 if (SM_I(sbi)->fcc_info)
9066c6a7 222 si->cache_mem += sizeof(struct flush_cmd_control);
0b54fb84
JK
223 if (SM_I(sbi)->dcc_info)
224 si->cache_mem += sizeof(struct discard_cmd_control);
902829aa 225
902829aa 226 /* free nids */
b8559dc2
CY
227 si->cache_mem += (NM_I(sbi)->nid_cnt[FREE_NID_LIST] +
228 NM_I(sbi)->nid_cnt[ALLOC_NID_LIST]) *
229 sizeof(struct free_nid);
9066c6a7 230 si->cache_mem += NM_I(sbi)->nat_cnt * sizeof(struct nat_entry);
6f0aacbc
JK
231 si->cache_mem += NM_I(sbi)->dirty_nat_cnt *
232 sizeof(struct nat_entry_set);
233 si->cache_mem += si->inmem_pages * sizeof(struct inmem_pages);
652be551 234 for (i = 0; i <= ORPHAN_INO; i++)
67298804 235 si->cache_mem += sbi->im[i].ino_num * sizeof(struct ino_entry);
7441ccef
JK
236 si->cache_mem += atomic_read(&sbi->total_ext_tree) *
237 sizeof(struct extent_tree);
4bf6fd9f
CY
238 si->cache_mem += atomic_read(&sbi->total_ext_node) *
239 sizeof(struct extent_node);
6f0aacbc
JK
240
241 si->page_mem = 0;
242 npages = NODE_MAPPING(sbi)->nrpages;
09cbfeaf 243 si->page_mem += (unsigned long long)npages << PAGE_SHIFT;
6f0aacbc 244 npages = META_MAPPING(sbi)->nrpages;
09cbfeaf 245 si->page_mem += (unsigned long long)npages << PAGE_SHIFT;
902829aa
GKH
246}
247
248static int stat_show(struct seq_file *s, void *v)
249{
145b04e5 250 struct f2fs_stat_info *si;
902829aa
GKH
251 int i = 0;
252 int j;
253
66af62ce 254 mutex_lock(&f2fs_stat_mutex);
145b04e5 255 list_for_each_entry(si, &f2fs_stat_list, stat_list) {
902829aa
GKH
256 update_general_status(si->sbi);
257
8c11a53f
JK
258 seq_printf(s, "\n=====[ partition info(%pg). #%d, %s]=====\n",
259 si->sbi->sb->s_bdev, i++,
260 f2fs_readonly(si->sbi->sb) ? "RO": "RW");
7880ceed
HL
261 seq_printf(s, "[SB: 1] [CP: 2] [SIT: %d] [NAT: %d] ",
262 si->sit_area_segs, si->nat_area_segs);
902829aa
GKH
263 seq_printf(s, "[SSA: %d] [MAIN: %d",
264 si->ssa_area_segs, si->main_area_segs);
265 seq_printf(s, "(OverProv:%d Resv:%d)]\n\n",
266 si->overp_segs, si->rsvd_segs);
f83a2584
YH
267 if (test_opt(si->sbi, DISCARD))
268 seq_printf(s, "Utilization: %u%% (%u valid blocks, %u discard blocks)\n",
269 si->utilization, si->valid_count, si->discard_blks);
270 else
271 seq_printf(s, "Utilization: %u%% (%u valid blocks)\n",
272 si->utilization, si->valid_count);
273
902829aa
GKH
274 seq_printf(s, " - Node: %u (Inode: %u, ",
275 si->valid_node_count, si->valid_inode_count);
276 seq_printf(s, "Other: %u)\n - Data: %u\n",
277 si->valid_node_count - si->valid_inode_count,
278 si->valid_count - si->valid_node_count);
d5e8f6c9
CY
279 seq_printf(s, " - Inline_xattr Inode: %u\n",
280 si->inline_xattr);
0dbdc2ae
JK
281 seq_printf(s, " - Inline_data Inode: %u\n",
282 si->inline_inode);
3289c061
JK
283 seq_printf(s, " - Inline_dentry Inode: %u\n",
284 si->inline_dir);
a00861db
JK
285 seq_printf(s, " - Orphan/Append/Update Inode: %u, %u, %u\n",
286 si->orphans, si->append, si->update);
902829aa
GKH
287 seq_printf(s, "\nMain area: %d segs, %d secs %d zones\n",
288 si->main_area_segs, si->main_area_sections,
289 si->main_area_zones);
290 seq_printf(s, " - COLD data: %d, %d, %d\n",
291 si->curseg[CURSEG_COLD_DATA],
292 si->cursec[CURSEG_COLD_DATA],
293 si->curzone[CURSEG_COLD_DATA]);
294 seq_printf(s, " - WARM data: %d, %d, %d\n",
295 si->curseg[CURSEG_WARM_DATA],
296 si->cursec[CURSEG_WARM_DATA],
297 si->curzone[CURSEG_WARM_DATA]);
298 seq_printf(s, " - HOT data: %d, %d, %d\n",
299 si->curseg[CURSEG_HOT_DATA],
300 si->cursec[CURSEG_HOT_DATA],
301 si->curzone[CURSEG_HOT_DATA]);
302 seq_printf(s, " - Dir dnode: %d, %d, %d\n",
303 si->curseg[CURSEG_HOT_NODE],
304 si->cursec[CURSEG_HOT_NODE],
305 si->curzone[CURSEG_HOT_NODE]);
306 seq_printf(s, " - File dnode: %d, %d, %d\n",
307 si->curseg[CURSEG_WARM_NODE],
308 si->cursec[CURSEG_WARM_NODE],
309 si->curzone[CURSEG_WARM_NODE]);
310 seq_printf(s, " - Indir nodes: %d, %d, %d\n",
311 si->curseg[CURSEG_COLD_NODE],
312 si->cursec[CURSEG_COLD_NODE],
313 si->curzone[CURSEG_COLD_NODE]);
314 seq_printf(s, "\n - Valid: %d\n - Dirty: %d\n",
315 si->main_area_segs - si->dirty_count -
316 si->prefree_count - si->free_segs,
317 si->dirty_count);
318 seq_printf(s, " - Prefree: %d\n - Free: %d (%d)\n\n",
319 si->prefree_count, si->free_segs, si->free_secs);
42190d2a
JK
320 seq_printf(s, "CP calls: %d (BG: %d)\n",
321 si->cp_count, si->bg_cp_count);
902829aa
GKH
322 seq_printf(s, "GC calls: %d (BG: %d)\n",
323 si->call_count, si->bg_gc);
e1235983
CL
324 seq_printf(s, " - data segments : %d (%d)\n",
325 si->data_segs, si->bg_data_segs);
326 seq_printf(s, " - node segments : %d (%d)\n",
327 si->node_segs, si->bg_node_segs);
328 seq_printf(s, "Try to move %d blocks (BG: %d)\n", si->tot_blks,
329 si->bg_data_blks + si->bg_node_blks);
330 seq_printf(s, " - data blocks : %d (%d)\n", si->data_blks,
331 si->bg_data_blks);
332 seq_printf(s, " - node blocks : %d (%d)\n", si->node_blks,
333 si->bg_node_blks);
029e13cc 334 seq_puts(s, "\nExtent Cache:\n");
5b7ee374 335 seq_printf(s, " - Hit Count: L1-1:%llu L1-2:%llu L2:%llu\n",
91c481ff 336 si->hit_largest, si->hit_cached,
029e13cc 337 si->hit_rbtree);
5b7ee374 338 seq_printf(s, " - Hit Ratio: %llu%% (%llu / %llu)\n",
029e13cc 339 !si->total_ext ? 0 :
5b7ee374 340 div64_u64(si->hit_total * 100, si->total_ext),
029e13cc 341 si->hit_total, si->total_ext);
c00ba554
JK
342 seq_printf(s, " - Inner Struct Count: tree: %d(%d), node: %d\n",
343 si->ext_tree, si->zombie_tree, si->ext_node);
6c311ec6 344 seq_puts(s, "\nBalancing F2FS Async:\n");
8b8dd65f
CY
345 seq_printf(s, " - IO (CP: %4d, Data: %4d, Flush: (%4d %4d), "
346 "Discard: (%4d %4d))\n",
dcc9165d 347 si->nr_wb_cp_data, si->nr_wb_data,
8b8dd65f
CY
348 si->nr_flushing, si->nr_flushed,
349 si->nr_discarding, si->nr_discarded);
648d50ba
CY
350 seq_printf(s, " - inmem: %4d, atomic IO: %4d (Max. %4d), "
351 "volatile IO: %4d (Max. %4d)\n",
352 si->inmem_pages, si->aw_cnt, si->max_aw_cnt,
353 si->vw_cnt, si->max_vw_cnt);
35782b23 354 seq_printf(s, " - nodes: %4d in %4d\n",
902829aa 355 si->ndirty_node, si->node_pages);
35782b23 356 seq_printf(s, " - dents: %4d in dirs:%4d (%4d)\n",
0f18b462 357 si->ndirty_dent, si->ndirty_dirs, si->ndirty_all);
35782b23 358 seq_printf(s, " - datas: %4d in files:%4d\n",
33fbd510 359 si->ndirty_data, si->ndirty_files);
35782b23 360 seq_printf(s, " - meta: %4d in %4d\n",
902829aa 361 si->ndirty_meta, si->meta_pages);
35782b23 362 seq_printf(s, " - imeta: %4d\n",
5bc994a0 363 si->ndirty_imeta);
dd4e4b59
JK
364 seq_printf(s, " - NATs: %9d/%9d\n - SITs: %9d/%9d\n",
365 si->dirty_nats, si->nats, si->dirty_sits, si->sits);
b8559dc2
CY
366 seq_printf(s, " - free_nids: %9d, alloc_nids: %9d\n",
367 si->free_nids, si->alloc_nids);
2d219c51
GZ
368 seq_puts(s, "\nDistribution of User Blocks:");
369 seq_puts(s, " [ valid | invalid | free ]\n");
370 seq_puts(s, " [");
902829aa
GKH
371
372 for (j = 0; j < si->util_valid; j++)
2d219c51
GZ
373 seq_putc(s, '-');
374 seq_putc(s, '|');
902829aa
GKH
375
376 for (j = 0; j < si->util_invalid; j++)
2d219c51
GZ
377 seq_putc(s, '-');
378 seq_putc(s, '|');
902829aa
GKH
379
380 for (j = 0; j < si->util_free; j++)
2d219c51
GZ
381 seq_putc(s, '-');
382 seq_puts(s, "]\n\n");
b9a2c252 383 seq_printf(s, "IPU: %u blocks\n", si->inplace_count);
902829aa
GKH
384 seq_printf(s, "SSR: %u blocks in %u segments\n",
385 si->block_count[SSR], si->segment_count[SSR]);
386 seq_printf(s, "LFS: %u blocks in %u segments\n",
387 si->block_count[LFS], si->segment_count[LFS]);
388
389 /* segment usage info */
390 update_sit_info(si->sbi);
391 seq_printf(s, "\nBDF: %u, avg. vblocks: %u\n",
392 si->bimodal, si->avg_vblocks);
393
394 /* memory footprint */
395 update_mem_info(si->sbi);
9edcdabf 396 seq_printf(s, "\nMemory: %llu KB\n",
6f0aacbc 397 (si->base_mem + si->cache_mem + si->page_mem) >> 10);
9edcdabf 398 seq_printf(s, " - static: %llu KB\n",
6f0aacbc 399 si->base_mem >> 10);
9edcdabf 400 seq_printf(s, " - cached: %llu KB\n",
6f0aacbc 401 si->cache_mem >> 10);
9edcdabf 402 seq_printf(s, " - paged : %llu KB\n",
6f0aacbc 403 si->page_mem >> 10);
902829aa 404 }
66af62ce 405 mutex_unlock(&f2fs_stat_mutex);
902829aa
GKH
406 return 0;
407}
408
409static int stat_open(struct inode *inode, struct file *file)
410{
411 return single_open(file, stat_show, inode->i_private);
412}
413
414static const struct file_operations stat_fops = {
05e6ea26 415 .owner = THIS_MODULE,
902829aa
GKH
416 .open = stat_open,
417 .read = seq_read,
418 .llseek = seq_lseek,
419 .release = single_release,
420};
421
4589d25d 422int f2fs_build_stats(struct f2fs_sb_info *sbi)
902829aa
GKH
423{
424 struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
425 struct f2fs_stat_info *si;
426
963d4f7d
GZ
427 si = kzalloc(sizeof(struct f2fs_stat_info), GFP_KERNEL);
428 if (!si)
902829aa
GKH
429 return -ENOMEM;
430
902829aa
GKH
431 si->all_area_segs = le32_to_cpu(raw_super->segment_count);
432 si->sit_area_segs = le32_to_cpu(raw_super->segment_count_sit);
433 si->nat_area_segs = le32_to_cpu(raw_super->segment_count_nat);
434 si->ssa_area_segs = le32_to_cpu(raw_super->segment_count_ssa);
435 si->main_area_segs = le32_to_cpu(raw_super->segment_count_main);
436 si->main_area_sections = le32_to_cpu(raw_super->section_count);
437 si->main_area_zones = si->main_area_sections /
438 le32_to_cpu(raw_super->secs_per_zone);
439 si->sbi = sbi;
963d4f7d 440 sbi->stat_info = si;
66af62ce 441
5b7ee374
CY
442 atomic64_set(&sbi->total_hit_ext, 0);
443 atomic64_set(&sbi->read_hit_rbtree, 0);
444 atomic64_set(&sbi->read_hit_largest, 0);
445 atomic64_set(&sbi->read_hit_cached, 0);
727edac5 446
d5e8f6c9 447 atomic_set(&sbi->inline_xattr, 0);
03e14d52
CY
448 atomic_set(&sbi->inline_inode, 0);
449 atomic_set(&sbi->inline_dir, 0);
b9a2c252 450 atomic_set(&sbi->inplace_count, 0);
03e14d52 451
26a28a0c 452 atomic_set(&sbi->aw_cnt, 0);
648d50ba 453 atomic_set(&sbi->vw_cnt, 0);
26a28a0c 454 atomic_set(&sbi->max_aw_cnt, 0);
648d50ba 455 atomic_set(&sbi->max_vw_cnt, 0);
26a28a0c 456
66af62ce 457 mutex_lock(&f2fs_stat_mutex);
458 list_add_tail(&si->stat_list, &f2fs_stat_list);
459 mutex_unlock(&f2fs_stat_mutex);
460
902829aa
GKH
461 return 0;
462}
463
902829aa
GKH
464void f2fs_destroy_stats(struct f2fs_sb_info *sbi)
465{
963d4f7d 466 struct f2fs_stat_info *si = F2FS_STAT(sbi);
902829aa 467
66af62ce 468 mutex_lock(&f2fs_stat_mutex);
902829aa 469 list_del(&si->stat_list);
66af62ce 470 mutex_unlock(&f2fs_stat_mutex);
471
963d4f7d 472 kfree(si);
902829aa
GKH
473}
474
787c7b8c 475int __init f2fs_create_root_stats(void)
4589d25d 476{
c524723e
YL
477 struct dentry *file;
478
40e1ebe9
YL
479 f2fs_debugfs_root = debugfs_create_dir("f2fs", NULL);
480 if (!f2fs_debugfs_root)
787c7b8c 481 return -ENOMEM;
c524723e 482
40e1ebe9 483 file = debugfs_create_file("status", S_IRUGO, f2fs_debugfs_root,
c524723e 484 NULL, &stat_fops);
7a6c76b1
GZ
485 if (!file) {
486 debugfs_remove(f2fs_debugfs_root);
487 f2fs_debugfs_root = NULL;
787c7b8c 488 return -ENOMEM;
7a6c76b1 489 }
787c7b8c
CY
490
491 return 0;
4589d25d
NJ
492}
493
494void f2fs_destroy_root_stats(void)
902829aa 495{
40e1ebe9 496 if (!f2fs_debugfs_root)
c524723e
YL
497 return;
498
40e1ebe9
YL
499 debugfs_remove_recursive(f2fs_debugfs_root);
500 f2fs_debugfs_root = NULL;
902829aa 501}