debug.c 17.4 KB
Newer Older
C
Chao Yu 已提交
1
// SPDX-License-Identifier: GPL-2.0
J
Jaegeuk Kim 已提交
2
/*
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 * f2fs debugging statistics
 *
 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
 *             http://www.samsung.com/
 * Copyright (c) 2012 Linux Foundation
 * Copyright (c) 2012 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 */

#include <linux/fs.h>
#include <linux/backing-dev.h>
#include <linux/f2fs_fs.h>
#include <linux/blkdev.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>

#include "f2fs.h"
#include "node.h"
#include "segment.h"
#include "gc.h"

static LIST_HEAD(f2fs_stat_list);
24
static struct dentry *f2fs_debugfs_root;
25
static DEFINE_MUTEX(f2fs_stat_mutex);
26

27
static void update_general_status(struct f2fs_sb_info *sbi)
28
{
29
	struct f2fs_stat_info *si = F2FS_STAT(sbi);
30 31
	int i;

A
arter97 已提交
32
	/* validation check of the segment numbers */
33 34 35
	si->hit_largest = atomic64_read(&sbi->read_hit_largest);
	si->hit_cached = atomic64_read(&sbi->read_hit_cached);
	si->hit_rbtree = atomic64_read(&sbi->read_hit_rbtree);
36
	si->hit_total = si->hit_largest + si->hit_cached + si->hit_rbtree;
37
	si->total_ext = atomic64_read(&sbi->total_hit_ext);
38
	si->ext_tree = atomic_read(&sbi->total_ext_tree);
J
Jaegeuk Kim 已提交
39
	si->zombie_tree = atomic_read(&sbi->total_zombie_tree);
40
	si->ext_node = atomic_read(&sbi->total_ext_node);
41 42 43
	si->ndirty_node = get_pages(sbi, F2FS_DIRTY_NODES);
	si->ndirty_dent = get_pages(sbi, F2FS_DIRTY_DENTS);
	si->ndirty_meta = get_pages(sbi, F2FS_DIRTY_META);
C
Chao Yu 已提交
44
	si->ndirty_data = get_pages(sbi, F2FS_DIRTY_DATA);
45
	si->ndirty_qdata = get_pages(sbi, F2FS_DIRTY_QDATA);
C
Chao Yu 已提交
46
	si->ndirty_imeta = get_pages(sbi, F2FS_DIRTY_IMETA);
C
Chao Yu 已提交
47 48
	si->ndirty_dirs = sbi->ndirty_inode[DIR_INODE];
	si->ndirty_files = sbi->ndirty_inode[FILE_INODE];
49
	si->nquota_files = sbi->nquota_files;
50
	si->ndirty_all = sbi->ndirty_inode[DIRTY_META];
51
	si->inmem_pages = get_pages(sbi, F2FS_INMEM_PAGES);
52
	si->aw_cnt = atomic_read(&sbi->aw_cnt);
53
	si->vw_cnt = atomic_read(&sbi->vw_cnt);
54
	si->max_aw_cnt = atomic_read(&sbi->max_aw_cnt);
55
	si->max_vw_cnt = atomic_read(&sbi->max_vw_cnt);
56 57
	si->nr_wb_cp_data = get_pages(sbi, F2FS_WB_CP_DATA);
	si->nr_wb_data = get_pages(sbi, F2FS_WB_DATA);
C
Chao Yu 已提交
58 59 60 61 62
	if (SM_I(sbi) && SM_I(sbi)->fcc_info) {
		si->nr_flushed =
			atomic_read(&SM_I(sbi)->fcc_info->issued_flush);
		si->nr_flushing =
			atomic_read(&SM_I(sbi)->fcc_info->issing_flush);
C
Chao Yu 已提交
63 64
		si->flush_list_empty =
			llist_empty(&SM_I(sbi)->fcc_info->issue_list);
C
Chao Yu 已提交
65 66 67 68 69 70
	}
	if (SM_I(sbi) && SM_I(sbi)->dcc_info) {
		si->nr_discarded =
			atomic_read(&SM_I(sbi)->dcc_info->issued_discard);
		si->nr_discarding =
			atomic_read(&SM_I(sbi)->dcc_info->issing_discard);
C
Chao Yu 已提交
71 72
		si->nr_discard_cmd =
			atomic_read(&SM_I(sbi)->dcc_info->discard_cmd_cnt);
C
Chao Yu 已提交
73
		si->undiscard_blks = SM_I(sbi)->dcc_info->undiscard_blks;
C
Chao Yu 已提交
74
	}
75 76 77 78
	si->total_count = (int)sbi->user_block_count / sbi->blocks_per_seg;
	si->rsvd_segs = reserved_segments(sbi);
	si->overp_segs = overprovision_segments(sbi);
	si->valid_count = valid_user_blocks(sbi);
79
	si->discard_blks = discard_blocks(sbi);
80 81
	si->valid_node_count = valid_node_count(sbi);
	si->valid_inode_count = valid_inode_count(sbi);
C
Chao Yu 已提交
82
	si->inline_xattr = atomic_read(&sbi->inline_xattr);
83 84
	si->inline_inode = atomic_read(&sbi->inline_inode);
	si->inline_dir = atomic_read(&sbi->inline_dir);
85 86
	si->append = sbi->im[APPEND_INO].ino_num;
	si->update = sbi->im[UPDATE_INO].ino_num;
J
Jaegeuk Kim 已提交
87
	si->orphans = sbi->im[ORPHAN_INO].ino_num;
88 89 90 91 92 93
	si->utilization = utilization(sbi);

	si->free_segs = free_segments(sbi);
	si->free_secs = free_sections(sbi);
	si->prefree_count = prefree_segments(sbi);
	si->dirty_count = dirty_segments(sbi);
94
	si->node_pages = NODE_MAPPING(sbi)->nrpages;
G
Gu Zheng 已提交
95
	si->meta_pages = META_MAPPING(sbi)->nrpages;
96
	si->nats = NM_I(sbi)->nat_cnt;
97 98 99
	si->dirty_nats = NM_I(sbi)->dirty_nat_cnt;
	si->sits = MAIN_SEGS(sbi);
	si->dirty_sits = SIT_I(sbi)->dirty_sentries;
C
Chao Yu 已提交
100
	si->free_nids = NM_I(sbi)->nid_cnt[FREE_NID];
101
	si->avail_nids = NM_I(sbi)->available_nids;
C
Chao Yu 已提交
102
	si->alloc_nids = NM_I(sbi)->nid_cnt[PREALLOC_NID];
103
	si->bg_gc = sbi->bg_gc;
104 105
	si->skipped_atomic_files[BG_GC] = sbi->skipped_atomic_files[BG_GC];
	si->skipped_atomic_files[FG_GC] = sbi->skipped_atomic_files[FG_GC];
106 107 108 109 110 111 112 113 114 115 116
	si->util_free = (int)(free_user_blocks(sbi) >> sbi->log_blocks_per_seg)
		* 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
		/ 2;
	si->util_valid = (int)(written_block_count(sbi) >>
						sbi->log_blocks_per_seg)
		* 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
		/ 2;
	si->util_invalid = 50 - si->util_free - si->util_valid;
	for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_NODE; i++) {
		struct curseg_info *curseg = CURSEG_I(sbi, i);
		si->curseg[i] = curseg->segno;
117 118
		si->cursec[i] = GET_SEC_FROM_SEG(sbi, curseg->segno);
		si->curzone[i] = GET_ZONE_FROM_SEC(sbi, si->cursec[i]);
119 120 121 122 123 124
	}

	for (i = 0; i < 2; i++) {
		si->segment_count[i] = sbi->segment_count[i];
		si->block_count[i] = sbi->block_count[i];
	}
125 126

	si->inplace_count = atomic_read(&sbi->inplace_count);
127 128
}

J
Jaegeuk Kim 已提交
129
/*
130 131 132 133
 * This function calculates BDF of every segments
 */
static void update_sit_info(struct f2fs_sb_info *sbi)
{
134
	struct f2fs_stat_info *si = F2FS_STAT(sbi);
135 136
	unsigned long long blks_per_sec, hblks_per_sec, total_vblocks;
	unsigned long long bimodal, dist;
137 138 139 140 141
	unsigned int segno, vblocks;
	int ndirty = 0;

	bimodal = 0;
	total_vblocks = 0;
142
	blks_per_sec = BLKS_PER_SEC(sbi);
143
	hblks_per_sec = blks_per_sec / 2;
144
	for (segno = 0; segno < MAIN_SEGS(sbi); segno += sbi->segs_per_sec) {
145
		vblocks = get_valid_blocks(sbi, segno, true);
146 147 148 149 150 151 152 153
		dist = abs(vblocks - hblks_per_sec);
		bimodal += dist * dist;

		if (vblocks > 0 && vblocks < blks_per_sec) {
			total_vblocks += vblocks;
			ndirty++;
		}
	}
154
	dist = div_u64(MAIN_SECS(sbi) * hblks_per_sec * hblks_per_sec, 100);
C
Chao Yu 已提交
155
	si->bimodal = div64_u64(bimodal, dist);
156
	if (si->dirty_count)
157
		si->avg_vblocks = div_u64(total_vblocks, ndirty);
158 159 160 161
	else
		si->avg_vblocks = 0;
}

J
Jaegeuk Kim 已提交
162
/*
163 164 165 166
 * This function calculates memory footprint.
 */
static void update_mem_info(struct f2fs_sb_info *sbi)
{
167
	struct f2fs_stat_info *si = F2FS_STAT(sbi);
168
	unsigned npages;
169
	int i;
170 171 172 173

	if (si->base_mem)
		goto get_cache;

174 175 176 177 178
	/* build stat */
	si->base_mem = sizeof(struct f2fs_stat_info);

	/* build superblock */
	si->base_mem += sizeof(struct f2fs_sb_info) + sbi->sb->s_blocksize;
179 180 181 182 183 184 185 186
	si->base_mem += 2 * sizeof(struct f2fs_inode_info);
	si->base_mem += sizeof(*sbi->ckpt);

	/* build sm */
	si->base_mem += sizeof(struct f2fs_sm_info);

	/* build sit */
	si->base_mem += sizeof(struct sit_info);
187 188
	si->base_mem += MAIN_SEGS(sbi) * sizeof(struct seg_entry);
	si->base_mem += f2fs_bitmap_size(MAIN_SEGS(sbi));
189
	si->base_mem += 2 * SIT_VBLOCK_MAP_SIZE * MAIN_SEGS(sbi);
190
	si->base_mem += SIT_VBLOCK_MAP_SIZE * MAIN_SEGS(sbi);
J
Jaegeuk Kim 已提交
191
	si->base_mem += SIT_VBLOCK_MAP_SIZE;
192
	if (sbi->segs_per_sec > 1)
193
		si->base_mem += MAIN_SECS(sbi) * sizeof(struct sec_entry);
194 195 196 197
	si->base_mem += __bitmap_size(sbi, SIT_BITMAP);

	/* build free segmap */
	si->base_mem += sizeof(struct free_segmap_info);
198 199
	si->base_mem += f2fs_bitmap_size(MAIN_SEGS(sbi));
	si->base_mem += f2fs_bitmap_size(MAIN_SECS(sbi));
200 201 202

	/* build curseg */
	si->base_mem += sizeof(struct curseg_info) * NR_CURSEG_TYPE;
203
	si->base_mem += PAGE_SIZE * NR_CURSEG_TYPE;
204 205 206

	/* build dirty segmap */
	si->base_mem += sizeof(struct dirty_seglist_info);
207 208
	si->base_mem += NR_DIRTY_TYPE * f2fs_bitmap_size(MAIN_SEGS(sbi));
	si->base_mem += f2fs_bitmap_size(MAIN_SECS(sbi));
209

A
arter97 已提交
210
	/* build nm */
211 212
	si->base_mem += sizeof(struct f2fs_nm_info);
	si->base_mem += __bitmap_size(sbi, NAT_BITMAP);
213
	si->base_mem += (NM_I(sbi)->nat_bits_blocks << F2FS_BLKSIZE_BITS);
214 215
	si->base_mem += NM_I(sbi)->nat_blocks *
				f2fs_bitmap_size(NAT_ENTRY_PER_BLOCK);
C
Chao Yu 已提交
216
	si->base_mem += NM_I(sbi)->nat_blocks / 8;
217
	si->base_mem += NM_I(sbi)->nat_blocks * sizeof(unsigned short);
218

219 220 221
get_cache:
	si->cache_mem = 0;

222
	/* build gc */
223 224 225 226
	if (sbi->gc_thread)
		si->cache_mem += sizeof(struct f2fs_gc_kthread);

	/* build merge flush thread */
227
	if (SM_I(sbi)->fcc_info)
228
		si->cache_mem += sizeof(struct flush_cmd_control);
C
Chao Yu 已提交
229
	if (SM_I(sbi)->dcc_info) {
230
		si->cache_mem += sizeof(struct discard_cmd_control);
C
Chao Yu 已提交
231 232 233
		si->cache_mem += sizeof(struct discard_cmd) *
			atomic_read(&SM_I(sbi)->dcc_info->discard_cmd_cnt);
	}
234 235

	/* free nids */
C
Chao Yu 已提交
236 237
	si->cache_mem += (NM_I(sbi)->nid_cnt[FREE_NID] +
				NM_I(sbi)->nid_cnt[PREALLOC_NID]) *
C
Chao Yu 已提交
238
				sizeof(struct free_nid);
239
	si->cache_mem += NM_I(sbi)->nat_cnt * sizeof(struct nat_entry);
240 241 242
	si->cache_mem += NM_I(sbi)->dirty_nat_cnt *
					sizeof(struct nat_entry_set);
	si->cache_mem += si->inmem_pages * sizeof(struct inmem_pages);
243
	for (i = 0; i < MAX_INO_ENTRY; i++)
244
		si->cache_mem += sbi->im[i].ino_num * sizeof(struct ino_entry);
245 246
	si->cache_mem += atomic_read(&sbi->total_ext_tree) *
						sizeof(struct extent_tree);
247 248
	si->cache_mem += atomic_read(&sbi->total_ext_node) *
						sizeof(struct extent_node);
249 250 251

	si->page_mem = 0;
	npages = NODE_MAPPING(sbi)->nrpages;
252
	si->page_mem += (unsigned long long)npages << PAGE_SHIFT;
253
	npages = META_MAPPING(sbi)->nrpages;
254
	si->page_mem += (unsigned long long)npages << PAGE_SHIFT;
255 256 257 258
}

static int stat_show(struct seq_file *s, void *v)
{
259
	struct f2fs_stat_info *si;
260 261 262
	int i = 0;
	int j;

263
	mutex_lock(&f2fs_stat_mutex);
264
	list_for_each_entry(si, &f2fs_stat_list, stat_list) {
265 266
		update_general_status(si->sbi);

J
Jaegeuk Kim 已提交
267
		seq_printf(s, "\n=====[ partition info(%pg). #%d, %s, CP: %s]=====\n",
J
Jaegeuk Kim 已提交
268
			si->sbi->sb->s_bdev, i++,
J
Jaegeuk Kim 已提交
269 270
			f2fs_readonly(si->sbi->sb) ? "RO": "RW",
			f2fs_cp_error(si->sbi) ? "Error": "Good");
271 272
		seq_printf(s, "[SB: 1] [CP: 2] [SIT: %d] [NAT: %d] ",
			   si->sit_area_segs, si->nat_area_segs);
273 274 275 276
		seq_printf(s, "[SSA: %d] [MAIN: %d",
			   si->ssa_area_segs, si->main_area_segs);
		seq_printf(s, "(OverProv:%d Resv:%d)]\n\n",
			   si->overp_segs, si->rsvd_segs);
277 278 279 280 281 282 283
		if (test_opt(si->sbi, DISCARD))
			seq_printf(s, "Utilization: %u%% (%u valid blocks, %u discard blocks)\n",
				si->utilization, si->valid_count, si->discard_blks);
		else
			seq_printf(s, "Utilization: %u%% (%u valid blocks)\n",
				si->utilization, si->valid_count);

284 285 286 287 288
		seq_printf(s, "  - Node: %u (Inode: %u, ",
			   si->valid_node_count, si->valid_inode_count);
		seq_printf(s, "Other: %u)\n  - Data: %u\n",
			   si->valid_node_count - si->valid_inode_count,
			   si->valid_count - si->valid_node_count);
C
Chao Yu 已提交
289 290
		seq_printf(s, "  - Inline_xattr Inode: %u\n",
			   si->inline_xattr);
291 292
		seq_printf(s, "  - Inline_data Inode: %u\n",
			   si->inline_inode);
293 294
		seq_printf(s, "  - Inline_dentry Inode: %u\n",
			   si->inline_dir);
295 296
		seq_printf(s, "  - Orphan/Append/Update Inode: %u, %u, %u\n",
			   si->orphans, si->append, si->update);
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
		seq_printf(s, "\nMain area: %d segs, %d secs %d zones\n",
			   si->main_area_segs, si->main_area_sections,
			   si->main_area_zones);
		seq_printf(s, "  - COLD  data: %d, %d, %d\n",
			   si->curseg[CURSEG_COLD_DATA],
			   si->cursec[CURSEG_COLD_DATA],
			   si->curzone[CURSEG_COLD_DATA]);
		seq_printf(s, "  - WARM  data: %d, %d, %d\n",
			   si->curseg[CURSEG_WARM_DATA],
			   si->cursec[CURSEG_WARM_DATA],
			   si->curzone[CURSEG_WARM_DATA]);
		seq_printf(s, "  - HOT   data: %d, %d, %d\n",
			   si->curseg[CURSEG_HOT_DATA],
			   si->cursec[CURSEG_HOT_DATA],
			   si->curzone[CURSEG_HOT_DATA]);
		seq_printf(s, "  - Dir   dnode: %d, %d, %d\n",
			   si->curseg[CURSEG_HOT_NODE],
			   si->cursec[CURSEG_HOT_NODE],
			   si->curzone[CURSEG_HOT_NODE]);
		seq_printf(s, "  - File   dnode: %d, %d, %d\n",
			   si->curseg[CURSEG_WARM_NODE],
			   si->cursec[CURSEG_WARM_NODE],
			   si->curzone[CURSEG_WARM_NODE]);
		seq_printf(s, "  - Indir nodes: %d, %d, %d\n",
			   si->curseg[CURSEG_COLD_NODE],
			   si->cursec[CURSEG_COLD_NODE],
			   si->curzone[CURSEG_COLD_NODE]);
		seq_printf(s, "\n  - Valid: %d\n  - Dirty: %d\n",
			   si->main_area_segs - si->dirty_count -
			   si->prefree_count - si->free_segs,
			   si->dirty_count);
		seq_printf(s, "  - Prefree: %d\n  - Free: %d (%d)\n\n",
			   si->prefree_count, si->free_segs, si->free_secs);
330 331
		seq_printf(s, "CP calls: %d (BG: %d)\n",
				si->cp_count, si->bg_cp_count);
332 333
		seq_printf(s, "GC calls: %d (BG: %d)\n",
			   si->call_count, si->bg_gc);
334 335 336 337 338 339 340 341 342 343
		seq_printf(s, "  - data segments : %d (%d)\n",
				si->data_segs, si->bg_data_segs);
		seq_printf(s, "  - node segments : %d (%d)\n",
				si->node_segs, si->bg_node_segs);
		seq_printf(s, "Try to move %d blocks (BG: %d)\n", si->tot_blks,
				si->bg_data_blks + si->bg_node_blks);
		seq_printf(s, "  - data blocks : %d (%d)\n", si->data_blks,
				si->bg_data_blks);
		seq_printf(s, "  - node blocks : %d (%d)\n", si->node_blks,
				si->bg_node_blks);
344 345 346 347
		seq_printf(s, "Skipped : atomic write %llu (%llu)\n",
				si->skipped_atomic_files[BG_GC] +
				si->skipped_atomic_files[FG_GC],
				si->skipped_atomic_files[BG_GC]);
348
		seq_puts(s, "\nExtent Cache:\n");
349
		seq_printf(s, "  - Hit Count: L1-1:%llu L1-2:%llu L2:%llu\n",
350
				si->hit_largest, si->hit_cached,
351
				si->hit_rbtree);
352
		seq_printf(s, "  - Hit Ratio: %llu%% (%llu / %llu)\n",
353
				!si->total_ext ? 0 :
354
				div64_u64(si->hit_total * 100, si->total_ext),
355
				si->hit_total, si->total_ext);
J
Jaegeuk Kim 已提交
356 357
		seq_printf(s, "  - Inner Struct Count: tree: %d(%d), node: %d\n",
				si->ext_tree, si->zombie_tree, si->ext_node);
C
Chris Fries 已提交
358
		seq_puts(s, "\nBalancing F2FS Async:\n");
C
Chao Yu 已提交
359
		seq_printf(s, "  - IO (CP: %4d, Data: %4d, Flush: (%4d %4d %4d), "
C
Chao Yu 已提交
360
			"Discard: (%4d %4d)) cmd: %4d undiscard:%4u\n",
361
			   si->nr_wb_cp_data, si->nr_wb_data,
C
Chao Yu 已提交
362
			   si->nr_flushing, si->nr_flushed,
C
Chao Yu 已提交
363
			   si->flush_list_empty,
C
Chao Yu 已提交
364
			   si->nr_discarding, si->nr_discarded,
C
Chao Yu 已提交
365
			   si->nr_discard_cmd, si->undiscard_blks);
366 367 368 369
		seq_printf(s, "  - inmem: %4d, atomic IO: %4d (Max. %4d), "
			"volatile IO: %4d (Max. %4d)\n",
			   si->inmem_pages, si->aw_cnt, si->max_aw_cnt,
			   si->vw_cnt, si->max_vw_cnt);
370
		seq_printf(s, "  - nodes: %4d in %4d\n",
371
			   si->ndirty_node, si->node_pages);
372
		seq_printf(s, "  - dents: %4d in dirs:%4d (%4d)\n",
373
			   si->ndirty_dent, si->ndirty_dirs, si->ndirty_all);
374
		seq_printf(s, "  - datas: %4d in files:%4d\n",
C
Chao Yu 已提交
375
			   si->ndirty_data, si->ndirty_files);
376 377
		seq_printf(s, "  - quota datas: %4d in quota files:%4d\n",
			   si->ndirty_qdata, si->nquota_files);
378
		seq_printf(s, "  - meta: %4d in %4d\n",
379
			   si->ndirty_meta, si->meta_pages);
380
		seq_printf(s, "  - imeta: %4d\n",
C
Chao Yu 已提交
381
			   si->ndirty_imeta);
382 383
		seq_printf(s, "  - NATs: %9d/%9d\n  - SITs: %9d/%9d\n",
			   si->dirty_nats, si->nats, si->dirty_sits, si->sits);
384 385
		seq_printf(s, "  - free_nids: %9d/%9d\n  - alloc_nids: %9d\n",
			   si->free_nids, si->avail_nids, si->alloc_nids);
386 387 388
		seq_puts(s, "\nDistribution of User Blocks:");
		seq_puts(s, " [ valid | invalid | free ]\n");
		seq_puts(s, "  [");
389 390

		for (j = 0; j < si->util_valid; j++)
391 392
			seq_putc(s, '-');
		seq_putc(s, '|');
393 394

		for (j = 0; j < si->util_invalid; j++)
395 396
			seq_putc(s, '-');
		seq_putc(s, '|');
397 398

		for (j = 0; j < si->util_free; j++)
399 400
			seq_putc(s, '-');
		seq_puts(s, "]\n\n");
401
		seq_printf(s, "IPU: %u blocks\n", si->inplace_count);
402 403 404 405 406 407 408 409 410 411 412 413
		seq_printf(s, "SSR: %u blocks in %u segments\n",
			   si->block_count[SSR], si->segment_count[SSR]);
		seq_printf(s, "LFS: %u blocks in %u segments\n",
			   si->block_count[LFS], si->segment_count[LFS]);

		/* segment usage info */
		update_sit_info(si->sbi);
		seq_printf(s, "\nBDF: %u, avg. vblocks: %u\n",
			   si->bimodal, si->avg_vblocks);

		/* memory footprint */
		update_mem_info(si->sbi);
C
Chao Yu 已提交
414
		seq_printf(s, "\nMemory: %llu KB\n",
415
			(si->base_mem + si->cache_mem + si->page_mem) >> 10);
C
Chao Yu 已提交
416
		seq_printf(s, "  - static: %llu KB\n",
417
				si->base_mem >> 10);
C
Chao Yu 已提交
418
		seq_printf(s, "  - cached: %llu KB\n",
419
				si->cache_mem >> 10);
C
Chao Yu 已提交
420
		seq_printf(s, "  - paged : %llu KB\n",
421
				si->page_mem >> 10);
422
	}
423
	mutex_unlock(&f2fs_stat_mutex);
424 425 426 427 428 429 430 431 432
	return 0;
}

static int stat_open(struct inode *inode, struct file *file)
{
	return single_open(file, stat_show, inode->i_private);
}

static const struct file_operations stat_fops = {
433
	.owner = THIS_MODULE,
434 435 436 437 438 439
	.open = stat_open,
	.read = seq_read,
	.llseek = seq_lseek,
	.release = single_release,
};

440
int f2fs_build_stats(struct f2fs_sb_info *sbi)
441 442 443 444
{
	struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
	struct f2fs_stat_info *si;

C
Chao Yu 已提交
445
	si = f2fs_kzalloc(sbi, sizeof(struct f2fs_stat_info), GFP_KERNEL);
446
	if (!si)
447 448 449 450 451 452 453 454 455 456 457
		return -ENOMEM;

	si->all_area_segs = le32_to_cpu(raw_super->segment_count);
	si->sit_area_segs = le32_to_cpu(raw_super->segment_count_sit);
	si->nat_area_segs = le32_to_cpu(raw_super->segment_count_nat);
	si->ssa_area_segs = le32_to_cpu(raw_super->segment_count_ssa);
	si->main_area_segs = le32_to_cpu(raw_super->segment_count_main);
	si->main_area_sections = le32_to_cpu(raw_super->section_count);
	si->main_area_zones = si->main_area_sections /
				le32_to_cpu(raw_super->secs_per_zone);
	si->sbi = sbi;
458
	sbi->stat_info = si;
459

460 461 462 463
	atomic64_set(&sbi->total_hit_ext, 0);
	atomic64_set(&sbi->read_hit_rbtree, 0);
	atomic64_set(&sbi->read_hit_largest, 0);
	atomic64_set(&sbi->read_hit_cached, 0);
464

C
Chao Yu 已提交
465
	atomic_set(&sbi->inline_xattr, 0);
466 467
	atomic_set(&sbi->inline_inode, 0);
	atomic_set(&sbi->inline_dir, 0);
468
	atomic_set(&sbi->inplace_count, 0);
469

470
	atomic_set(&sbi->aw_cnt, 0);
471
	atomic_set(&sbi->vw_cnt, 0);
472
	atomic_set(&sbi->max_aw_cnt, 0);
473
	atomic_set(&sbi->max_vw_cnt, 0);
474

475 476 477 478
	mutex_lock(&f2fs_stat_mutex);
	list_add_tail(&si->stat_list, &f2fs_stat_list);
	mutex_unlock(&f2fs_stat_mutex);

479 480 481 482 483
	return 0;
}

void f2fs_destroy_stats(struct f2fs_sb_info *sbi)
{
484
	struct f2fs_stat_info *si = F2FS_STAT(sbi);
485

486
	mutex_lock(&f2fs_stat_mutex);
487
	list_del(&si->stat_list);
488 489
	mutex_unlock(&f2fs_stat_mutex);

490
	kfree(si);
491 492
}

493
int __init f2fs_create_root_stats(void)
494
{
495 496
	struct dentry *file;

497 498
	f2fs_debugfs_root = debugfs_create_dir("f2fs", NULL);
	if (!f2fs_debugfs_root)
499
		return -ENOMEM;
500

501
	file = debugfs_create_file("status", S_IRUGO, f2fs_debugfs_root,
502
			NULL, &stat_fops);
503 504 505
	if (!file) {
		debugfs_remove(f2fs_debugfs_root);
		f2fs_debugfs_root = NULL;
506
		return -ENOMEM;
507
	}
508 509

	return 0;
510 511 512
}

void f2fs_destroy_root_stats(void)
513
{
514
	if (!f2fs_debugfs_root)
515 516
		return;

517 518
	debugfs_remove_recursive(f2fs_debugfs_root);
	f2fs_debugfs_root = NULL;
519
}