1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * f2fs sysfs interface
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (c) 2012 Samsung Electronics Co., Ltd.
6*4882a593Smuzhiyun * http://www.samsung.com/
7*4882a593Smuzhiyun * Copyright (c) 2017 Chao Yu <chao@kernel.org>
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun #include <linux/compiler.h>
10*4882a593Smuzhiyun #include <linux/proc_fs.h>
11*4882a593Smuzhiyun #include <linux/f2fs_fs.h>
12*4882a593Smuzhiyun #include <linux/seq_file.h>
13*4882a593Smuzhiyun #include <linux/unicode.h>
14*4882a593Smuzhiyun #include <linux/ioprio.h>
15*4882a593Smuzhiyun #include <linux/sysfs.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #include "f2fs.h"
18*4882a593Smuzhiyun #include "segment.h"
19*4882a593Smuzhiyun #include "gc.h"
20*4882a593Smuzhiyun #include <trace/events/f2fs.h>
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun static struct proc_dir_entry *f2fs_proc_root;
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun /* Sysfs support for f2fs */
25*4882a593Smuzhiyun enum {
26*4882a593Smuzhiyun GC_THREAD, /* struct f2fs_gc_thread */
27*4882a593Smuzhiyun SM_INFO, /* struct f2fs_sm_info */
28*4882a593Smuzhiyun DCC_INFO, /* struct discard_cmd_control */
29*4882a593Smuzhiyun NM_INFO, /* struct f2fs_nm_info */
30*4882a593Smuzhiyun F2FS_SBI, /* struct f2fs_sb_info */
31*4882a593Smuzhiyun #ifdef CONFIG_F2FS_STAT_FS
32*4882a593Smuzhiyun STAT_INFO, /* struct f2fs_stat_info */
33*4882a593Smuzhiyun #endif
34*4882a593Smuzhiyun #ifdef CONFIG_F2FS_FAULT_INJECTION
35*4882a593Smuzhiyun FAULT_INFO_RATE, /* struct f2fs_fault_info */
36*4882a593Smuzhiyun FAULT_INFO_TYPE, /* struct f2fs_fault_info */
37*4882a593Smuzhiyun #endif
38*4882a593Smuzhiyun RESERVED_BLOCKS, /* struct f2fs_sb_info */
39*4882a593Smuzhiyun CPRC_INFO, /* struct ckpt_req_control */
40*4882a593Smuzhiyun ATGC_INFO, /* struct atgc_management */
41*4882a593Smuzhiyun };
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun struct f2fs_attr {
44*4882a593Smuzhiyun struct attribute attr;
45*4882a593Smuzhiyun ssize_t (*show)(struct f2fs_attr *, struct f2fs_sb_info *, char *);
46*4882a593Smuzhiyun ssize_t (*store)(struct f2fs_attr *, struct f2fs_sb_info *,
47*4882a593Smuzhiyun const char *, size_t);
48*4882a593Smuzhiyun int struct_type;
49*4882a593Smuzhiyun int offset;
50*4882a593Smuzhiyun int id;
51*4882a593Smuzhiyun };
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun static ssize_t f2fs_sbi_show(struct f2fs_attr *a,
54*4882a593Smuzhiyun struct f2fs_sb_info *sbi, char *buf);
55*4882a593Smuzhiyun
__struct_ptr(struct f2fs_sb_info * sbi,int struct_type)56*4882a593Smuzhiyun static unsigned char *__struct_ptr(struct f2fs_sb_info *sbi, int struct_type)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun if (struct_type == GC_THREAD)
59*4882a593Smuzhiyun return (unsigned char *)sbi->gc_thread;
60*4882a593Smuzhiyun else if (struct_type == SM_INFO)
61*4882a593Smuzhiyun return (unsigned char *)SM_I(sbi);
62*4882a593Smuzhiyun else if (struct_type == DCC_INFO)
63*4882a593Smuzhiyun return (unsigned char *)SM_I(sbi)->dcc_info;
64*4882a593Smuzhiyun else if (struct_type == NM_INFO)
65*4882a593Smuzhiyun return (unsigned char *)NM_I(sbi);
66*4882a593Smuzhiyun else if (struct_type == F2FS_SBI || struct_type == RESERVED_BLOCKS)
67*4882a593Smuzhiyun return (unsigned char *)sbi;
68*4882a593Smuzhiyun #ifdef CONFIG_F2FS_FAULT_INJECTION
69*4882a593Smuzhiyun else if (struct_type == FAULT_INFO_RATE ||
70*4882a593Smuzhiyun struct_type == FAULT_INFO_TYPE)
71*4882a593Smuzhiyun return (unsigned char *)&F2FS_OPTION(sbi).fault_info;
72*4882a593Smuzhiyun #endif
73*4882a593Smuzhiyun #ifdef CONFIG_F2FS_STAT_FS
74*4882a593Smuzhiyun else if (struct_type == STAT_INFO)
75*4882a593Smuzhiyun return (unsigned char *)F2FS_STAT(sbi);
76*4882a593Smuzhiyun #endif
77*4882a593Smuzhiyun else if (struct_type == CPRC_INFO)
78*4882a593Smuzhiyun return (unsigned char *)&sbi->cprc_info;
79*4882a593Smuzhiyun else if (struct_type == ATGC_INFO)
80*4882a593Smuzhiyun return (unsigned char *)&sbi->am;
81*4882a593Smuzhiyun return NULL;
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun
dirty_segments_show(struct f2fs_attr * a,struct f2fs_sb_info * sbi,char * buf)84*4882a593Smuzhiyun static ssize_t dirty_segments_show(struct f2fs_attr *a,
85*4882a593Smuzhiyun struct f2fs_sb_info *sbi, char *buf)
86*4882a593Smuzhiyun {
87*4882a593Smuzhiyun return sprintf(buf, "%llu\n",
88*4882a593Smuzhiyun (unsigned long long)(dirty_segments(sbi)));
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun
free_segments_show(struct f2fs_attr * a,struct f2fs_sb_info * sbi,char * buf)91*4882a593Smuzhiyun static ssize_t free_segments_show(struct f2fs_attr *a,
92*4882a593Smuzhiyun struct f2fs_sb_info *sbi, char *buf)
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun return sprintf(buf, "%llu\n",
95*4882a593Smuzhiyun (unsigned long long)(free_segments(sbi)));
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun
ovp_segments_show(struct f2fs_attr * a,struct f2fs_sb_info * sbi,char * buf)98*4882a593Smuzhiyun static ssize_t ovp_segments_show(struct f2fs_attr *a,
99*4882a593Smuzhiyun struct f2fs_sb_info *sbi, char *buf)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun return sprintf(buf, "%llu\n",
102*4882a593Smuzhiyun (unsigned long long)(overprovision_segments(sbi)));
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun
lifetime_write_kbytes_show(struct f2fs_attr * a,struct f2fs_sb_info * sbi,char * buf)105*4882a593Smuzhiyun static ssize_t lifetime_write_kbytes_show(struct f2fs_attr *a,
106*4882a593Smuzhiyun struct f2fs_sb_info *sbi, char *buf)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun return sprintf(buf, "%llu\n",
109*4882a593Smuzhiyun (unsigned long long)(sbi->kbytes_written +
110*4882a593Smuzhiyun ((f2fs_get_sectors_written(sbi) -
111*4882a593Smuzhiyun sbi->sectors_written_start) >> 1)));
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun
sb_status_show(struct f2fs_attr * a,struct f2fs_sb_info * sbi,char * buf)114*4882a593Smuzhiyun static ssize_t sb_status_show(struct f2fs_attr *a,
115*4882a593Smuzhiyun struct f2fs_sb_info *sbi, char *buf)
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun return sprintf(buf, "%lx\n", sbi->s_flag);
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun
pending_discard_show(struct f2fs_attr * a,struct f2fs_sb_info * sbi,char * buf)120*4882a593Smuzhiyun static ssize_t pending_discard_show(struct f2fs_attr *a,
121*4882a593Smuzhiyun struct f2fs_sb_info *sbi, char *buf)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun if (!SM_I(sbi)->dcc_info)
124*4882a593Smuzhiyun return -EINVAL;
125*4882a593Smuzhiyun return sprintf(buf, "%llu\n", (unsigned long long)atomic_read(
126*4882a593Smuzhiyun &SM_I(sbi)->dcc_info->discard_cmd_cnt));
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun
features_show(struct f2fs_attr * a,struct f2fs_sb_info * sbi,char * buf)129*4882a593Smuzhiyun static ssize_t features_show(struct f2fs_attr *a,
130*4882a593Smuzhiyun struct f2fs_sb_info *sbi, char *buf)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun int len = 0;
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun if (f2fs_sb_has_encrypt(sbi))
135*4882a593Smuzhiyun len += scnprintf(buf, PAGE_SIZE - len, "%s",
136*4882a593Smuzhiyun "encryption");
137*4882a593Smuzhiyun if (f2fs_sb_has_blkzoned(sbi))
138*4882a593Smuzhiyun len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s",
139*4882a593Smuzhiyun len ? ", " : "", "blkzoned");
140*4882a593Smuzhiyun if (f2fs_sb_has_extra_attr(sbi))
141*4882a593Smuzhiyun len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s",
142*4882a593Smuzhiyun len ? ", " : "", "extra_attr");
143*4882a593Smuzhiyun if (f2fs_sb_has_project_quota(sbi))
144*4882a593Smuzhiyun len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s",
145*4882a593Smuzhiyun len ? ", " : "", "projquota");
146*4882a593Smuzhiyun if (f2fs_sb_has_inode_chksum(sbi))
147*4882a593Smuzhiyun len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s",
148*4882a593Smuzhiyun len ? ", " : "", "inode_checksum");
149*4882a593Smuzhiyun if (f2fs_sb_has_flexible_inline_xattr(sbi))
150*4882a593Smuzhiyun len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s",
151*4882a593Smuzhiyun len ? ", " : "", "flexible_inline_xattr");
152*4882a593Smuzhiyun if (f2fs_sb_has_quota_ino(sbi))
153*4882a593Smuzhiyun len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s",
154*4882a593Smuzhiyun len ? ", " : "", "quota_ino");
155*4882a593Smuzhiyun if (f2fs_sb_has_inode_crtime(sbi))
156*4882a593Smuzhiyun len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s",
157*4882a593Smuzhiyun len ? ", " : "", "inode_crtime");
158*4882a593Smuzhiyun if (f2fs_sb_has_lost_found(sbi))
159*4882a593Smuzhiyun len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s",
160*4882a593Smuzhiyun len ? ", " : "", "lost_found");
161*4882a593Smuzhiyun if (f2fs_sb_has_verity(sbi))
162*4882a593Smuzhiyun len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s",
163*4882a593Smuzhiyun len ? ", " : "", "verity");
164*4882a593Smuzhiyun if (f2fs_sb_has_sb_chksum(sbi))
165*4882a593Smuzhiyun len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s",
166*4882a593Smuzhiyun len ? ", " : "", "sb_checksum");
167*4882a593Smuzhiyun if (f2fs_sb_has_casefold(sbi))
168*4882a593Smuzhiyun len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s",
169*4882a593Smuzhiyun len ? ", " : "", "casefold");
170*4882a593Smuzhiyun if (f2fs_sb_has_readonly(sbi))
171*4882a593Smuzhiyun len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s",
172*4882a593Smuzhiyun len ? ", " : "", "readonly");
173*4882a593Smuzhiyun if (f2fs_sb_has_compression(sbi))
174*4882a593Smuzhiyun len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s",
175*4882a593Smuzhiyun len ? ", " : "", "compression");
176*4882a593Smuzhiyun len += scnprintf(buf + len, PAGE_SIZE - len, "%s%s",
177*4882a593Smuzhiyun len ? ", " : "", "pin_file");
178*4882a593Smuzhiyun len += scnprintf(buf + len, PAGE_SIZE - len, "\n");
179*4882a593Smuzhiyun return len;
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun
current_reserved_blocks_show(struct f2fs_attr * a,struct f2fs_sb_info * sbi,char * buf)182*4882a593Smuzhiyun static ssize_t current_reserved_blocks_show(struct f2fs_attr *a,
183*4882a593Smuzhiyun struct f2fs_sb_info *sbi, char *buf)
184*4882a593Smuzhiyun {
185*4882a593Smuzhiyun return sprintf(buf, "%u\n", sbi->current_reserved_blocks);
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun
unusable_show(struct f2fs_attr * a,struct f2fs_sb_info * sbi,char * buf)188*4882a593Smuzhiyun static ssize_t unusable_show(struct f2fs_attr *a,
189*4882a593Smuzhiyun struct f2fs_sb_info *sbi, char *buf)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun block_t unusable;
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun if (test_opt(sbi, DISABLE_CHECKPOINT))
194*4882a593Smuzhiyun unusable = sbi->unusable_block_count;
195*4882a593Smuzhiyun else
196*4882a593Smuzhiyun unusable = f2fs_get_unusable_blocks(sbi);
197*4882a593Smuzhiyun return sprintf(buf, "%llu\n", (unsigned long long)unusable);
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun
encoding_show(struct f2fs_attr * a,struct f2fs_sb_info * sbi,char * buf)200*4882a593Smuzhiyun static ssize_t encoding_show(struct f2fs_attr *a,
201*4882a593Smuzhiyun struct f2fs_sb_info *sbi, char *buf)
202*4882a593Smuzhiyun {
203*4882a593Smuzhiyun #ifdef CONFIG_UNICODE
204*4882a593Smuzhiyun struct super_block *sb = sbi->sb;
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun if (f2fs_sb_has_casefold(sbi))
207*4882a593Smuzhiyun return snprintf(buf, PAGE_SIZE, "%s (%d.%d.%d)\n",
208*4882a593Smuzhiyun sb->s_encoding->charset,
209*4882a593Smuzhiyun (sb->s_encoding->version >> 16) & 0xff,
210*4882a593Smuzhiyun (sb->s_encoding->version >> 8) & 0xff,
211*4882a593Smuzhiyun sb->s_encoding->version & 0xff);
212*4882a593Smuzhiyun #endif
213*4882a593Smuzhiyun return sprintf(buf, "(none)");
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun
mounted_time_sec_show(struct f2fs_attr * a,struct f2fs_sb_info * sbi,char * buf)216*4882a593Smuzhiyun static ssize_t mounted_time_sec_show(struct f2fs_attr *a,
217*4882a593Smuzhiyun struct f2fs_sb_info *sbi, char *buf)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun return sprintf(buf, "%llu", SIT_I(sbi)->mounted_time);
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun #ifdef CONFIG_F2FS_STAT_FS
moved_blocks_foreground_show(struct f2fs_attr * a,struct f2fs_sb_info * sbi,char * buf)223*4882a593Smuzhiyun static ssize_t moved_blocks_foreground_show(struct f2fs_attr *a,
224*4882a593Smuzhiyun struct f2fs_sb_info *sbi, char *buf)
225*4882a593Smuzhiyun {
226*4882a593Smuzhiyun struct f2fs_stat_info *si = F2FS_STAT(sbi);
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun return sprintf(buf, "%llu\n",
229*4882a593Smuzhiyun (unsigned long long)(si->tot_blks -
230*4882a593Smuzhiyun (si->bg_data_blks + si->bg_node_blks)));
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun
moved_blocks_background_show(struct f2fs_attr * a,struct f2fs_sb_info * sbi,char * buf)233*4882a593Smuzhiyun static ssize_t moved_blocks_background_show(struct f2fs_attr *a,
234*4882a593Smuzhiyun struct f2fs_sb_info *sbi, char *buf)
235*4882a593Smuzhiyun {
236*4882a593Smuzhiyun struct f2fs_stat_info *si = F2FS_STAT(sbi);
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun return sprintf(buf, "%llu\n",
239*4882a593Smuzhiyun (unsigned long long)(si->bg_data_blks + si->bg_node_blks));
240*4882a593Smuzhiyun }
241*4882a593Smuzhiyun
avg_vblocks_show(struct f2fs_attr * a,struct f2fs_sb_info * sbi,char * buf)242*4882a593Smuzhiyun static ssize_t avg_vblocks_show(struct f2fs_attr *a,
243*4882a593Smuzhiyun struct f2fs_sb_info *sbi, char *buf)
244*4882a593Smuzhiyun {
245*4882a593Smuzhiyun struct f2fs_stat_info *si = F2FS_STAT(sbi);
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun si->dirty_count = dirty_segments(sbi);
248*4882a593Smuzhiyun f2fs_update_sit_info(sbi);
249*4882a593Smuzhiyun return sprintf(buf, "%llu\n", (unsigned long long)(si->avg_vblocks));
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun #endif
252*4882a593Smuzhiyun
main_blkaddr_show(struct f2fs_attr * a,struct f2fs_sb_info * sbi,char * buf)253*4882a593Smuzhiyun static ssize_t main_blkaddr_show(struct f2fs_attr *a,
254*4882a593Smuzhiyun struct f2fs_sb_info *sbi, char *buf)
255*4882a593Smuzhiyun {
256*4882a593Smuzhiyun return snprintf(buf, PAGE_SIZE, "%llu\n",
257*4882a593Smuzhiyun (unsigned long long)MAIN_BLKADDR(sbi));
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun
f2fs_sbi_show(struct f2fs_attr * a,struct f2fs_sb_info * sbi,char * buf)260*4882a593Smuzhiyun static ssize_t f2fs_sbi_show(struct f2fs_attr *a,
261*4882a593Smuzhiyun struct f2fs_sb_info *sbi, char *buf)
262*4882a593Smuzhiyun {
263*4882a593Smuzhiyun unsigned char *ptr = NULL;
264*4882a593Smuzhiyun unsigned int *ui;
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun ptr = __struct_ptr(sbi, a->struct_type);
267*4882a593Smuzhiyun if (!ptr)
268*4882a593Smuzhiyun return -EINVAL;
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun if (!strcmp(a->attr.name, "extension_list")) {
271*4882a593Smuzhiyun __u8 (*extlist)[F2FS_EXTENSION_LEN] =
272*4882a593Smuzhiyun sbi->raw_super->extension_list;
273*4882a593Smuzhiyun int cold_count = le32_to_cpu(sbi->raw_super->extension_count);
274*4882a593Smuzhiyun int hot_count = sbi->raw_super->hot_ext_count;
275*4882a593Smuzhiyun int len = 0, i;
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun len += scnprintf(buf + len, PAGE_SIZE - len,
278*4882a593Smuzhiyun "cold file extension:\n");
279*4882a593Smuzhiyun for (i = 0; i < cold_count; i++)
280*4882a593Smuzhiyun len += scnprintf(buf + len, PAGE_SIZE - len, "%s\n",
281*4882a593Smuzhiyun extlist[i]);
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun len += scnprintf(buf + len, PAGE_SIZE - len,
284*4882a593Smuzhiyun "hot file extension:\n");
285*4882a593Smuzhiyun for (i = cold_count; i < cold_count + hot_count; i++)
286*4882a593Smuzhiyun len += scnprintf(buf + len, PAGE_SIZE - len, "%s\n",
287*4882a593Smuzhiyun extlist[i]);
288*4882a593Smuzhiyun return len;
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun if (!strcmp(a->attr.name, "ckpt_thread_ioprio")) {
292*4882a593Smuzhiyun struct ckpt_req_control *cprc = &sbi->cprc_info;
293*4882a593Smuzhiyun int len = 0;
294*4882a593Smuzhiyun int class = IOPRIO_PRIO_CLASS(cprc->ckpt_thread_ioprio);
295*4882a593Smuzhiyun int data = IOPRIO_PRIO_DATA(cprc->ckpt_thread_ioprio);
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun if (class == IOPRIO_CLASS_RT)
298*4882a593Smuzhiyun len += scnprintf(buf + len, PAGE_SIZE - len, "rt,");
299*4882a593Smuzhiyun else if (class == IOPRIO_CLASS_BE)
300*4882a593Smuzhiyun len += scnprintf(buf + len, PAGE_SIZE - len, "be,");
301*4882a593Smuzhiyun else
302*4882a593Smuzhiyun return -EINVAL;
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun len += scnprintf(buf + len, PAGE_SIZE - len, "%d\n", data);
305*4882a593Smuzhiyun return len;
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun #ifdef CONFIG_F2FS_FS_COMPRESSION
309*4882a593Smuzhiyun if (!strcmp(a->attr.name, "compr_written_block"))
310*4882a593Smuzhiyun return sysfs_emit(buf, "%llu\n", sbi->compr_written_block);
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun if (!strcmp(a->attr.name, "compr_saved_block"))
313*4882a593Smuzhiyun return sysfs_emit(buf, "%llu\n", sbi->compr_saved_block);
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun if (!strcmp(a->attr.name, "compr_new_inode"))
316*4882a593Smuzhiyun return sysfs_emit(buf, "%u\n", sbi->compr_new_inode);
317*4882a593Smuzhiyun #endif
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun if (!strcmp(a->attr.name, "gc_segment_mode"))
320*4882a593Smuzhiyun return sysfs_emit(buf, "%u\n", sbi->gc_segment_mode);
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun if (!strcmp(a->attr.name, "gc_reclaimed_segments")) {
323*4882a593Smuzhiyun return sysfs_emit(buf, "%u\n",
324*4882a593Smuzhiyun sbi->gc_reclaimed_segs[sbi->gc_segment_mode]);
325*4882a593Smuzhiyun }
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun ui = (unsigned int *)(ptr + a->offset);
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun return sprintf(buf, "%u\n", *ui);
330*4882a593Smuzhiyun }
331*4882a593Smuzhiyun
__sbi_store(struct f2fs_attr * a,struct f2fs_sb_info * sbi,const char * buf,size_t count)332*4882a593Smuzhiyun static ssize_t __sbi_store(struct f2fs_attr *a,
333*4882a593Smuzhiyun struct f2fs_sb_info *sbi,
334*4882a593Smuzhiyun const char *buf, size_t count)
335*4882a593Smuzhiyun {
336*4882a593Smuzhiyun unsigned char *ptr;
337*4882a593Smuzhiyun unsigned long t;
338*4882a593Smuzhiyun unsigned int *ui;
339*4882a593Smuzhiyun ssize_t ret;
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun ptr = __struct_ptr(sbi, a->struct_type);
342*4882a593Smuzhiyun if (!ptr)
343*4882a593Smuzhiyun return -EINVAL;
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun if (!strcmp(a->attr.name, "extension_list")) {
346*4882a593Smuzhiyun const char *name = strim((char *)buf);
347*4882a593Smuzhiyun bool set = true, hot;
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun if (!strncmp(name, "[h]", 3))
350*4882a593Smuzhiyun hot = true;
351*4882a593Smuzhiyun else if (!strncmp(name, "[c]", 3))
352*4882a593Smuzhiyun hot = false;
353*4882a593Smuzhiyun else
354*4882a593Smuzhiyun return -EINVAL;
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun name += 3;
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun if (*name == '!') {
359*4882a593Smuzhiyun name++;
360*4882a593Smuzhiyun set = false;
361*4882a593Smuzhiyun }
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun if (strlen(name) >= F2FS_EXTENSION_LEN)
364*4882a593Smuzhiyun return -EINVAL;
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun f2fs_down_write(&sbi->sb_lock);
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun ret = f2fs_update_extension_list(sbi, name, hot, set);
369*4882a593Smuzhiyun if (ret)
370*4882a593Smuzhiyun goto out;
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun ret = f2fs_commit_super(sbi, false);
373*4882a593Smuzhiyun if (ret)
374*4882a593Smuzhiyun f2fs_update_extension_list(sbi, name, hot, !set);
375*4882a593Smuzhiyun out:
376*4882a593Smuzhiyun f2fs_up_write(&sbi->sb_lock);
377*4882a593Smuzhiyun return ret ? ret : count;
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun if (!strcmp(a->attr.name, "ckpt_thread_ioprio")) {
381*4882a593Smuzhiyun const char *name = strim((char *)buf);
382*4882a593Smuzhiyun struct ckpt_req_control *cprc = &sbi->cprc_info;
383*4882a593Smuzhiyun int class;
384*4882a593Smuzhiyun long data;
385*4882a593Smuzhiyun int ret;
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun if (!strncmp(name, "rt,", 3))
388*4882a593Smuzhiyun class = IOPRIO_CLASS_RT;
389*4882a593Smuzhiyun else if (!strncmp(name, "be,", 3))
390*4882a593Smuzhiyun class = IOPRIO_CLASS_BE;
391*4882a593Smuzhiyun else
392*4882a593Smuzhiyun return -EINVAL;
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun name += 3;
395*4882a593Smuzhiyun ret = kstrtol(name, 10, &data);
396*4882a593Smuzhiyun if (ret)
397*4882a593Smuzhiyun return ret;
398*4882a593Smuzhiyun if (data >= IOPRIO_BE_NR || data < 0)
399*4882a593Smuzhiyun return -EINVAL;
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun cprc->ckpt_thread_ioprio = IOPRIO_PRIO_VALUE(class, data);
402*4882a593Smuzhiyun if (test_opt(sbi, MERGE_CHECKPOINT)) {
403*4882a593Smuzhiyun ret = set_task_ioprio(cprc->f2fs_issue_ckpt,
404*4882a593Smuzhiyun cprc->ckpt_thread_ioprio);
405*4882a593Smuzhiyun if (ret)
406*4882a593Smuzhiyun return ret;
407*4882a593Smuzhiyun }
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun return count;
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun ui = (unsigned int *)(ptr + a->offset);
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun ret = kstrtoul(skip_spaces(buf), 0, &t);
415*4882a593Smuzhiyun if (ret < 0)
416*4882a593Smuzhiyun return ret;
417*4882a593Smuzhiyun #ifdef CONFIG_F2FS_FAULT_INJECTION
418*4882a593Smuzhiyun if (a->struct_type == FAULT_INFO_TYPE && t >= (1 << FAULT_MAX))
419*4882a593Smuzhiyun return -EINVAL;
420*4882a593Smuzhiyun if (a->struct_type == FAULT_INFO_RATE && t >= UINT_MAX)
421*4882a593Smuzhiyun return -EINVAL;
422*4882a593Smuzhiyun #endif
423*4882a593Smuzhiyun if (a->struct_type == RESERVED_BLOCKS) {
424*4882a593Smuzhiyun spin_lock(&sbi->stat_lock);
425*4882a593Smuzhiyun if (t > (unsigned long)(sbi->user_block_count -
426*4882a593Smuzhiyun F2FS_OPTION(sbi).root_reserved_blocks -
427*4882a593Smuzhiyun sbi->blocks_per_seg *
428*4882a593Smuzhiyun SM_I(sbi)->additional_reserved_segments)) {
429*4882a593Smuzhiyun spin_unlock(&sbi->stat_lock);
430*4882a593Smuzhiyun return -EINVAL;
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun *ui = t;
433*4882a593Smuzhiyun sbi->current_reserved_blocks = min(sbi->reserved_blocks,
434*4882a593Smuzhiyun sbi->user_block_count - valid_user_blocks(sbi));
435*4882a593Smuzhiyun spin_unlock(&sbi->stat_lock);
436*4882a593Smuzhiyun return count;
437*4882a593Smuzhiyun }
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun if (!strcmp(a->attr.name, "discard_granularity")) {
440*4882a593Smuzhiyun if (t == 0 || t > MAX_PLIST_NUM)
441*4882a593Smuzhiyun return -EINVAL;
442*4882a593Smuzhiyun if (t == *ui)
443*4882a593Smuzhiyun return count;
444*4882a593Smuzhiyun *ui = t;
445*4882a593Smuzhiyun return count;
446*4882a593Smuzhiyun }
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun if (!strcmp(a->attr.name, "migration_granularity")) {
449*4882a593Smuzhiyun if (t == 0 || t > sbi->segs_per_sec)
450*4882a593Smuzhiyun return -EINVAL;
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun if (!strcmp(a->attr.name, "trim_sections"))
454*4882a593Smuzhiyun return -EINVAL;
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun if (!strcmp(a->attr.name, "gc_urgent")) {
457*4882a593Smuzhiyun if (t == 0) {
458*4882a593Smuzhiyun sbi->gc_mode = GC_NORMAL;
459*4882a593Smuzhiyun } else if (t == 1) {
460*4882a593Smuzhiyun sbi->gc_mode = GC_URGENT_HIGH;
461*4882a593Smuzhiyun if (sbi->gc_thread) {
462*4882a593Smuzhiyun sbi->gc_thread->gc_wake = 1;
463*4882a593Smuzhiyun wake_up_interruptible_all(
464*4882a593Smuzhiyun &sbi->gc_thread->gc_wait_queue_head);
465*4882a593Smuzhiyun wake_up_discard_thread(sbi, true);
466*4882a593Smuzhiyun }
467*4882a593Smuzhiyun } else if (t == 2) {
468*4882a593Smuzhiyun sbi->gc_mode = GC_URGENT_LOW;
469*4882a593Smuzhiyun } else {
470*4882a593Smuzhiyun return -EINVAL;
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun return count;
473*4882a593Smuzhiyun }
474*4882a593Smuzhiyun if (!strcmp(a->attr.name, "gc_idle")) {
475*4882a593Smuzhiyun if (t == GC_IDLE_CB) {
476*4882a593Smuzhiyun sbi->gc_mode = GC_IDLE_CB;
477*4882a593Smuzhiyun } else if (t == GC_IDLE_GREEDY) {
478*4882a593Smuzhiyun sbi->gc_mode = GC_IDLE_GREEDY;
479*4882a593Smuzhiyun } else if (t == GC_IDLE_AT) {
480*4882a593Smuzhiyun if (!sbi->am.atgc_enabled)
481*4882a593Smuzhiyun return -EINVAL;
482*4882a593Smuzhiyun sbi->gc_mode = GC_IDLE_AT;
483*4882a593Smuzhiyun } else {
484*4882a593Smuzhiyun sbi->gc_mode = GC_NORMAL;
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun return count;
487*4882a593Smuzhiyun }
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun if (!strcmp(a->attr.name, "iostat_enable")) {
490*4882a593Smuzhiyun sbi->iostat_enable = !!t;
491*4882a593Smuzhiyun if (!sbi->iostat_enable)
492*4882a593Smuzhiyun f2fs_reset_iostat(sbi);
493*4882a593Smuzhiyun return count;
494*4882a593Smuzhiyun }
495*4882a593Smuzhiyun
496*4882a593Smuzhiyun if (!strcmp(a->attr.name, "iostat_period_ms")) {
497*4882a593Smuzhiyun if (t < MIN_IOSTAT_PERIOD_MS || t > MAX_IOSTAT_PERIOD_MS)
498*4882a593Smuzhiyun return -EINVAL;
499*4882a593Smuzhiyun spin_lock(&sbi->iostat_lock);
500*4882a593Smuzhiyun sbi->iostat_period_ms = (unsigned int)t;
501*4882a593Smuzhiyun spin_unlock(&sbi->iostat_lock);
502*4882a593Smuzhiyun return count;
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun #ifdef CONFIG_F2FS_FS_COMPRESSION
506*4882a593Smuzhiyun if (!strcmp(a->attr.name, "compr_written_block") ||
507*4882a593Smuzhiyun !strcmp(a->attr.name, "compr_saved_block")) {
508*4882a593Smuzhiyun if (t != 0)
509*4882a593Smuzhiyun return -EINVAL;
510*4882a593Smuzhiyun sbi->compr_written_block = 0;
511*4882a593Smuzhiyun sbi->compr_saved_block = 0;
512*4882a593Smuzhiyun return count;
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun if (!strcmp(a->attr.name, "compr_new_inode")) {
516*4882a593Smuzhiyun if (t != 0)
517*4882a593Smuzhiyun return -EINVAL;
518*4882a593Smuzhiyun sbi->compr_new_inode = 0;
519*4882a593Smuzhiyun return count;
520*4882a593Smuzhiyun }
521*4882a593Smuzhiyun #endif
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun if (!strcmp(a->attr.name, "atgc_candidate_ratio")) {
524*4882a593Smuzhiyun if (t > 100)
525*4882a593Smuzhiyun return -EINVAL;
526*4882a593Smuzhiyun sbi->am.candidate_ratio = t;
527*4882a593Smuzhiyun return count;
528*4882a593Smuzhiyun }
529*4882a593Smuzhiyun
530*4882a593Smuzhiyun if (!strcmp(a->attr.name, "atgc_age_weight")) {
531*4882a593Smuzhiyun if (t > 100)
532*4882a593Smuzhiyun return -EINVAL;
533*4882a593Smuzhiyun sbi->am.age_weight = t;
534*4882a593Smuzhiyun return count;
535*4882a593Smuzhiyun }
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun if (!strcmp(a->attr.name, "gc_segment_mode")) {
538*4882a593Smuzhiyun if (t < MAX_GC_MODE)
539*4882a593Smuzhiyun sbi->gc_segment_mode = t;
540*4882a593Smuzhiyun else
541*4882a593Smuzhiyun return -EINVAL;
542*4882a593Smuzhiyun return count;
543*4882a593Smuzhiyun }
544*4882a593Smuzhiyun
545*4882a593Smuzhiyun if (!strcmp(a->attr.name, "gc_reclaimed_segments")) {
546*4882a593Smuzhiyun if (t != 0)
547*4882a593Smuzhiyun return -EINVAL;
548*4882a593Smuzhiyun sbi->gc_reclaimed_segs[sbi->gc_segment_mode] = 0;
549*4882a593Smuzhiyun return count;
550*4882a593Smuzhiyun }
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun if (!strcmp(a->attr.name, "hot_data_age_threshold")) {
553*4882a593Smuzhiyun if (t == 0 || t >= sbi->warm_data_age_threshold)
554*4882a593Smuzhiyun return -EINVAL;
555*4882a593Smuzhiyun if (t == *ui)
556*4882a593Smuzhiyun return count;
557*4882a593Smuzhiyun *ui = (unsigned int)t;
558*4882a593Smuzhiyun return count;
559*4882a593Smuzhiyun }
560*4882a593Smuzhiyun
561*4882a593Smuzhiyun if (!strcmp(a->attr.name, "warm_data_age_threshold")) {
562*4882a593Smuzhiyun if (t == 0 || t <= sbi->hot_data_age_threshold)
563*4882a593Smuzhiyun return -EINVAL;
564*4882a593Smuzhiyun if (t == *ui)
565*4882a593Smuzhiyun return count;
566*4882a593Smuzhiyun *ui = (unsigned int)t;
567*4882a593Smuzhiyun return count;
568*4882a593Smuzhiyun }
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun if (!strcmp(a->attr.name, "last_age_weight")) {
571*4882a593Smuzhiyun if (t > 100)
572*4882a593Smuzhiyun return -EINVAL;
573*4882a593Smuzhiyun if (t == *ui)
574*4882a593Smuzhiyun return count;
575*4882a593Smuzhiyun *ui = (unsigned int)t;
576*4882a593Smuzhiyun return count;
577*4882a593Smuzhiyun }
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun *ui = (unsigned int)t;
580*4882a593Smuzhiyun
581*4882a593Smuzhiyun return count;
582*4882a593Smuzhiyun }
583*4882a593Smuzhiyun
f2fs_sbi_store(struct f2fs_attr * a,struct f2fs_sb_info * sbi,const char * buf,size_t count)584*4882a593Smuzhiyun static ssize_t f2fs_sbi_store(struct f2fs_attr *a,
585*4882a593Smuzhiyun struct f2fs_sb_info *sbi,
586*4882a593Smuzhiyun const char *buf, size_t count)
587*4882a593Smuzhiyun {
588*4882a593Smuzhiyun ssize_t ret;
589*4882a593Smuzhiyun bool gc_entry = (!strcmp(a->attr.name, "gc_urgent") ||
590*4882a593Smuzhiyun a->struct_type == GC_THREAD);
591*4882a593Smuzhiyun
592*4882a593Smuzhiyun if (gc_entry) {
593*4882a593Smuzhiyun if (!down_read_trylock(&sbi->sb->s_umount))
594*4882a593Smuzhiyun return -EAGAIN;
595*4882a593Smuzhiyun }
596*4882a593Smuzhiyun ret = __sbi_store(a, sbi, buf, count);
597*4882a593Smuzhiyun if (gc_entry)
598*4882a593Smuzhiyun up_read(&sbi->sb->s_umount);
599*4882a593Smuzhiyun
600*4882a593Smuzhiyun return ret;
601*4882a593Smuzhiyun }
602*4882a593Smuzhiyun
f2fs_attr_show(struct kobject * kobj,struct attribute * attr,char * buf)603*4882a593Smuzhiyun static ssize_t f2fs_attr_show(struct kobject *kobj,
604*4882a593Smuzhiyun struct attribute *attr, char *buf)
605*4882a593Smuzhiyun {
606*4882a593Smuzhiyun struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info,
607*4882a593Smuzhiyun s_kobj);
608*4882a593Smuzhiyun struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr);
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun return a->show ? a->show(a, sbi, buf) : 0;
611*4882a593Smuzhiyun }
612*4882a593Smuzhiyun
f2fs_attr_store(struct kobject * kobj,struct attribute * attr,const char * buf,size_t len)613*4882a593Smuzhiyun static ssize_t f2fs_attr_store(struct kobject *kobj, struct attribute *attr,
614*4882a593Smuzhiyun const char *buf, size_t len)
615*4882a593Smuzhiyun {
616*4882a593Smuzhiyun struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info,
617*4882a593Smuzhiyun s_kobj);
618*4882a593Smuzhiyun struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr);
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun return a->store ? a->store(a, sbi, buf, len) : 0;
621*4882a593Smuzhiyun }
622*4882a593Smuzhiyun
f2fs_sb_release(struct kobject * kobj)623*4882a593Smuzhiyun static void f2fs_sb_release(struct kobject *kobj)
624*4882a593Smuzhiyun {
625*4882a593Smuzhiyun struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info,
626*4882a593Smuzhiyun s_kobj);
627*4882a593Smuzhiyun complete(&sbi->s_kobj_unregister);
628*4882a593Smuzhiyun }
629*4882a593Smuzhiyun
630*4882a593Smuzhiyun /*
631*4882a593Smuzhiyun * Note that there are three feature list entries:
632*4882a593Smuzhiyun * 1) /sys/fs/f2fs/features
633*4882a593Smuzhiyun * : shows runtime features supported by in-kernel f2fs along with Kconfig.
634*4882a593Smuzhiyun * - ref. F2FS_FEATURE_RO_ATTR()
635*4882a593Smuzhiyun *
636*4882a593Smuzhiyun * 2) /sys/fs/f2fs/$s_id/features <deprecated>
637*4882a593Smuzhiyun * : shows on-disk features enabled by mkfs.f2fs, used for old kernels. This
638*4882a593Smuzhiyun * won't add new feature anymore, and thus, users should check entries in 3)
639*4882a593Smuzhiyun * instead of this 2).
640*4882a593Smuzhiyun *
641*4882a593Smuzhiyun * 3) /sys/fs/f2fs/$s_id/feature_list
642*4882a593Smuzhiyun * : shows on-disk features enabled by mkfs.f2fs per instance, which follows
643*4882a593Smuzhiyun * sysfs entry rule where each entry should expose single value.
644*4882a593Smuzhiyun * This list covers old feature list provided by 2) and beyond. Therefore,
645*4882a593Smuzhiyun * please add new on-disk feature in this list only.
646*4882a593Smuzhiyun * - ref. F2FS_SB_FEATURE_RO_ATTR()
647*4882a593Smuzhiyun */
f2fs_feature_show(struct f2fs_attr * a,struct f2fs_sb_info * sbi,char * buf)648*4882a593Smuzhiyun static ssize_t f2fs_feature_show(struct f2fs_attr *a,
649*4882a593Smuzhiyun struct f2fs_sb_info *sbi, char *buf)
650*4882a593Smuzhiyun {
651*4882a593Smuzhiyun return sprintf(buf, "supported\n");
652*4882a593Smuzhiyun }
653*4882a593Smuzhiyun
654*4882a593Smuzhiyun #define F2FS_FEATURE_RO_ATTR(_name) \
655*4882a593Smuzhiyun static struct f2fs_attr f2fs_attr_##_name = { \
656*4882a593Smuzhiyun .attr = {.name = __stringify(_name), .mode = 0444 }, \
657*4882a593Smuzhiyun .show = f2fs_feature_show, \
658*4882a593Smuzhiyun }
659*4882a593Smuzhiyun
f2fs_sb_feature_show(struct f2fs_attr * a,struct f2fs_sb_info * sbi,char * buf)660*4882a593Smuzhiyun static ssize_t f2fs_sb_feature_show(struct f2fs_attr *a,
661*4882a593Smuzhiyun struct f2fs_sb_info *sbi, char *buf)
662*4882a593Smuzhiyun {
663*4882a593Smuzhiyun if (F2FS_HAS_FEATURE(sbi, a->id))
664*4882a593Smuzhiyun return sprintf(buf, "supported\n");
665*4882a593Smuzhiyun return sprintf(buf, "unsupported\n");
666*4882a593Smuzhiyun }
667*4882a593Smuzhiyun
668*4882a593Smuzhiyun #define F2FS_SB_FEATURE_RO_ATTR(_name, _feat) \
669*4882a593Smuzhiyun static struct f2fs_attr f2fs_attr_sb_##_name = { \
670*4882a593Smuzhiyun .attr = {.name = __stringify(_name), .mode = 0444 }, \
671*4882a593Smuzhiyun .show = f2fs_sb_feature_show, \
672*4882a593Smuzhiyun .id = F2FS_FEATURE_##_feat, \
673*4882a593Smuzhiyun }
674*4882a593Smuzhiyun
675*4882a593Smuzhiyun #define F2FS_ATTR_OFFSET(_struct_type, _name, _mode, _show, _store, _offset) \
676*4882a593Smuzhiyun static struct f2fs_attr f2fs_attr_##_name = { \
677*4882a593Smuzhiyun .attr = {.name = __stringify(_name), .mode = _mode }, \
678*4882a593Smuzhiyun .show = _show, \
679*4882a593Smuzhiyun .store = _store, \
680*4882a593Smuzhiyun .struct_type = _struct_type, \
681*4882a593Smuzhiyun .offset = _offset \
682*4882a593Smuzhiyun }
683*4882a593Smuzhiyun
684*4882a593Smuzhiyun #define F2FS_RW_ATTR(struct_type, struct_name, name, elname) \
685*4882a593Smuzhiyun F2FS_ATTR_OFFSET(struct_type, name, 0644, \
686*4882a593Smuzhiyun f2fs_sbi_show, f2fs_sbi_store, \
687*4882a593Smuzhiyun offsetof(struct struct_name, elname))
688*4882a593Smuzhiyun
689*4882a593Smuzhiyun #define F2FS_GENERAL_RO_ATTR(name) \
690*4882a593Smuzhiyun static struct f2fs_attr f2fs_attr_##name = __ATTR(name, 0444, name##_show, NULL)
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun #define F2FS_STAT_ATTR(_struct_type, _struct_name, _name, _elname) \
693*4882a593Smuzhiyun static struct f2fs_attr f2fs_attr_##_name = { \
694*4882a593Smuzhiyun .attr = {.name = __stringify(_name), .mode = 0444 }, \
695*4882a593Smuzhiyun .show = f2fs_sbi_show, \
696*4882a593Smuzhiyun .struct_type = _struct_type, \
697*4882a593Smuzhiyun .offset = offsetof(struct _struct_name, _elname), \
698*4882a593Smuzhiyun }
699*4882a593Smuzhiyun
700*4882a593Smuzhiyun F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_urgent_sleep_time,
701*4882a593Smuzhiyun urgent_sleep_time);
702*4882a593Smuzhiyun F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_min_sleep_time, min_sleep_time);
703*4882a593Smuzhiyun F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_max_sleep_time, max_sleep_time);
704*4882a593Smuzhiyun F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_no_gc_sleep_time, no_gc_sleep_time);
705*4882a593Smuzhiyun F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_idle, gc_mode);
706*4882a593Smuzhiyun F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_urgent, gc_mode);
707*4882a593Smuzhiyun F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, reclaim_segments, rec_prefree_segments);
708*4882a593Smuzhiyun F2FS_RW_ATTR(DCC_INFO, discard_cmd_control, max_small_discards, max_discards);
709*4882a593Smuzhiyun F2FS_RW_ATTR(DCC_INFO, discard_cmd_control, discard_granularity, discard_granularity);
710*4882a593Smuzhiyun F2FS_RW_ATTR(RESERVED_BLOCKS, f2fs_sb_info, reserved_blocks, reserved_blocks);
711*4882a593Smuzhiyun F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, batched_trim_sections, trim_sections);
712*4882a593Smuzhiyun F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, ipu_policy, ipu_policy);
713*4882a593Smuzhiyun F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_ipu_util, min_ipu_util);
714*4882a593Smuzhiyun F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_fsync_blocks, min_fsync_blocks);
715*4882a593Smuzhiyun F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_seq_blocks, min_seq_blocks);
716*4882a593Smuzhiyun F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_hot_blocks, min_hot_blocks);
717*4882a593Smuzhiyun F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_ssr_sections, min_ssr_sections);
718*4882a593Smuzhiyun F2FS_RW_ATTR(NM_INFO, f2fs_nm_info, ram_thresh, ram_thresh);
719*4882a593Smuzhiyun F2FS_RW_ATTR(NM_INFO, f2fs_nm_info, ra_nid_pages, ra_nid_pages);
720*4882a593Smuzhiyun F2FS_RW_ATTR(NM_INFO, f2fs_nm_info, dirty_nats_ratio, dirty_nats_ratio);
721*4882a593Smuzhiyun F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, max_victim_search, max_victim_search);
722*4882a593Smuzhiyun F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, migration_granularity, migration_granularity);
723*4882a593Smuzhiyun F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, dir_level, dir_level);
724*4882a593Smuzhiyun F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, cp_interval, interval_time[CP_TIME]);
725*4882a593Smuzhiyun F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, idle_interval, interval_time[REQ_TIME]);
726*4882a593Smuzhiyun F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, discard_idle_interval,
727*4882a593Smuzhiyun interval_time[DISCARD_TIME]);
728*4882a593Smuzhiyun F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_idle_interval, interval_time[GC_TIME]);
729*4882a593Smuzhiyun F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info,
730*4882a593Smuzhiyun umount_discard_timeout, interval_time[UMOUNT_DISCARD_TIMEOUT]);
731*4882a593Smuzhiyun F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, iostat_enable, iostat_enable);
732*4882a593Smuzhiyun F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, iostat_period_ms, iostat_period_ms);
733*4882a593Smuzhiyun F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, readdir_ra, readdir_ra);
734*4882a593Smuzhiyun F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, max_io_bytes, max_io_bytes);
735*4882a593Smuzhiyun F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_pin_file_thresh, gc_pin_file_threshold);
736*4882a593Smuzhiyun F2FS_RW_ATTR(F2FS_SBI, f2fs_super_block, extension_list, extension_list);
737*4882a593Smuzhiyun #ifdef CONFIG_F2FS_FAULT_INJECTION
738*4882a593Smuzhiyun F2FS_RW_ATTR(FAULT_INFO_RATE, f2fs_fault_info, inject_rate, inject_rate);
739*4882a593Smuzhiyun F2FS_RW_ATTR(FAULT_INFO_TYPE, f2fs_fault_info, inject_type, inject_type);
740*4882a593Smuzhiyun #endif
741*4882a593Smuzhiyun F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, data_io_flag, data_io_flag);
742*4882a593Smuzhiyun F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, node_io_flag, node_io_flag);
743*4882a593Smuzhiyun F2FS_RW_ATTR(CPRC_INFO, ckpt_req_control, ckpt_thread_ioprio, ckpt_thread_ioprio);
744*4882a593Smuzhiyun F2FS_GENERAL_RO_ATTR(dirty_segments);
745*4882a593Smuzhiyun F2FS_GENERAL_RO_ATTR(free_segments);
746*4882a593Smuzhiyun F2FS_GENERAL_RO_ATTR(ovp_segments);
747*4882a593Smuzhiyun F2FS_GENERAL_RO_ATTR(lifetime_write_kbytes);
748*4882a593Smuzhiyun F2FS_GENERAL_RO_ATTR(features);
749*4882a593Smuzhiyun F2FS_GENERAL_RO_ATTR(current_reserved_blocks);
750*4882a593Smuzhiyun F2FS_GENERAL_RO_ATTR(unusable);
751*4882a593Smuzhiyun F2FS_GENERAL_RO_ATTR(encoding);
752*4882a593Smuzhiyun F2FS_GENERAL_RO_ATTR(mounted_time_sec);
753*4882a593Smuzhiyun F2FS_GENERAL_RO_ATTR(main_blkaddr);
754*4882a593Smuzhiyun F2FS_GENERAL_RO_ATTR(pending_discard);
755*4882a593Smuzhiyun #ifdef CONFIG_F2FS_STAT_FS
756*4882a593Smuzhiyun F2FS_STAT_ATTR(STAT_INFO, f2fs_stat_info, cp_foreground_calls, cp_count);
757*4882a593Smuzhiyun F2FS_STAT_ATTR(STAT_INFO, f2fs_stat_info, cp_background_calls, bg_cp_count);
758*4882a593Smuzhiyun F2FS_STAT_ATTR(STAT_INFO, f2fs_stat_info, gc_foreground_calls, call_count);
759*4882a593Smuzhiyun F2FS_STAT_ATTR(STAT_INFO, f2fs_stat_info, gc_background_calls, bg_gc);
760*4882a593Smuzhiyun F2FS_GENERAL_RO_ATTR(moved_blocks_background);
761*4882a593Smuzhiyun F2FS_GENERAL_RO_ATTR(moved_blocks_foreground);
762*4882a593Smuzhiyun F2FS_GENERAL_RO_ATTR(avg_vblocks);
763*4882a593Smuzhiyun #endif
764*4882a593Smuzhiyun
765*4882a593Smuzhiyun #ifdef CONFIG_FS_ENCRYPTION
766*4882a593Smuzhiyun F2FS_FEATURE_RO_ATTR(encryption);
767*4882a593Smuzhiyun F2FS_FEATURE_RO_ATTR(test_dummy_encryption_v2);
768*4882a593Smuzhiyun #ifdef CONFIG_UNICODE
769*4882a593Smuzhiyun F2FS_FEATURE_RO_ATTR(encrypted_casefold);
770*4882a593Smuzhiyun #endif
771*4882a593Smuzhiyun #endif /* CONFIG_FS_ENCRYPTION */
772*4882a593Smuzhiyun #ifdef CONFIG_BLK_DEV_ZONED
773*4882a593Smuzhiyun F2FS_FEATURE_RO_ATTR(block_zoned);
774*4882a593Smuzhiyun #endif
775*4882a593Smuzhiyun F2FS_FEATURE_RO_ATTR(atomic_write);
776*4882a593Smuzhiyun F2FS_FEATURE_RO_ATTR(extra_attr);
777*4882a593Smuzhiyun F2FS_FEATURE_RO_ATTR(project_quota);
778*4882a593Smuzhiyun F2FS_FEATURE_RO_ATTR(inode_checksum);
779*4882a593Smuzhiyun F2FS_FEATURE_RO_ATTR(flexible_inline_xattr);
780*4882a593Smuzhiyun F2FS_FEATURE_RO_ATTR(quota_ino);
781*4882a593Smuzhiyun F2FS_FEATURE_RO_ATTR(inode_crtime);
782*4882a593Smuzhiyun F2FS_FEATURE_RO_ATTR(lost_found);
783*4882a593Smuzhiyun #ifdef CONFIG_FS_VERITY
784*4882a593Smuzhiyun F2FS_FEATURE_RO_ATTR(verity);
785*4882a593Smuzhiyun #endif
786*4882a593Smuzhiyun F2FS_FEATURE_RO_ATTR(sb_checksum);
787*4882a593Smuzhiyun #ifdef CONFIG_UNICODE
788*4882a593Smuzhiyun F2FS_FEATURE_RO_ATTR(casefold);
789*4882a593Smuzhiyun #endif
790*4882a593Smuzhiyun F2FS_FEATURE_RO_ATTR(readonly);
791*4882a593Smuzhiyun #ifdef CONFIG_F2FS_FS_COMPRESSION
792*4882a593Smuzhiyun F2FS_FEATURE_RO_ATTR(compression);
793*4882a593Smuzhiyun F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, compr_written_block, compr_written_block);
794*4882a593Smuzhiyun F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, compr_saved_block, compr_saved_block);
795*4882a593Smuzhiyun F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, compr_new_inode, compr_new_inode);
796*4882a593Smuzhiyun #endif
797*4882a593Smuzhiyun F2FS_FEATURE_RO_ATTR(pin_file);
798*4882a593Smuzhiyun
799*4882a593Smuzhiyun /* For ATGC */
800*4882a593Smuzhiyun F2FS_RW_ATTR(ATGC_INFO, atgc_management, atgc_candidate_ratio, candidate_ratio);
801*4882a593Smuzhiyun F2FS_RW_ATTR(ATGC_INFO, atgc_management, atgc_candidate_count, max_candidate_count);
802*4882a593Smuzhiyun F2FS_RW_ATTR(ATGC_INFO, atgc_management, atgc_age_weight, age_weight);
803*4882a593Smuzhiyun F2FS_RW_ATTR(ATGC_INFO, atgc_management, atgc_age_threshold, age_threshold);
804*4882a593Smuzhiyun
805*4882a593Smuzhiyun F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_segment_mode, gc_segment_mode);
806*4882a593Smuzhiyun F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_reclaimed_segments, gc_reclaimed_segs);
807*4882a593Smuzhiyun
808*4882a593Smuzhiyun /* For block age extent cache */
809*4882a593Smuzhiyun F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, hot_data_age_threshold, hot_data_age_threshold);
810*4882a593Smuzhiyun F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, warm_data_age_threshold, warm_data_age_threshold);
811*4882a593Smuzhiyun F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, last_age_weight, last_age_weight);
812*4882a593Smuzhiyun
813*4882a593Smuzhiyun #define ATTR_LIST(name) (&f2fs_attr_##name.attr)
814*4882a593Smuzhiyun static struct attribute *f2fs_attrs[] = {
815*4882a593Smuzhiyun ATTR_LIST(gc_urgent_sleep_time),
816*4882a593Smuzhiyun ATTR_LIST(gc_min_sleep_time),
817*4882a593Smuzhiyun ATTR_LIST(gc_max_sleep_time),
818*4882a593Smuzhiyun ATTR_LIST(gc_no_gc_sleep_time),
819*4882a593Smuzhiyun ATTR_LIST(gc_idle),
820*4882a593Smuzhiyun ATTR_LIST(gc_urgent),
821*4882a593Smuzhiyun ATTR_LIST(reclaim_segments),
822*4882a593Smuzhiyun ATTR_LIST(main_blkaddr),
823*4882a593Smuzhiyun ATTR_LIST(max_small_discards),
824*4882a593Smuzhiyun ATTR_LIST(discard_granularity),
825*4882a593Smuzhiyun ATTR_LIST(pending_discard),
826*4882a593Smuzhiyun ATTR_LIST(batched_trim_sections),
827*4882a593Smuzhiyun ATTR_LIST(ipu_policy),
828*4882a593Smuzhiyun ATTR_LIST(min_ipu_util),
829*4882a593Smuzhiyun ATTR_LIST(min_fsync_blocks),
830*4882a593Smuzhiyun ATTR_LIST(min_seq_blocks),
831*4882a593Smuzhiyun ATTR_LIST(min_hot_blocks),
832*4882a593Smuzhiyun ATTR_LIST(min_ssr_sections),
833*4882a593Smuzhiyun ATTR_LIST(max_victim_search),
834*4882a593Smuzhiyun ATTR_LIST(migration_granularity),
835*4882a593Smuzhiyun ATTR_LIST(dir_level),
836*4882a593Smuzhiyun ATTR_LIST(ram_thresh),
837*4882a593Smuzhiyun ATTR_LIST(ra_nid_pages),
838*4882a593Smuzhiyun ATTR_LIST(dirty_nats_ratio),
839*4882a593Smuzhiyun ATTR_LIST(cp_interval),
840*4882a593Smuzhiyun ATTR_LIST(idle_interval),
841*4882a593Smuzhiyun ATTR_LIST(discard_idle_interval),
842*4882a593Smuzhiyun ATTR_LIST(gc_idle_interval),
843*4882a593Smuzhiyun ATTR_LIST(umount_discard_timeout),
844*4882a593Smuzhiyun ATTR_LIST(iostat_enable),
845*4882a593Smuzhiyun ATTR_LIST(iostat_period_ms),
846*4882a593Smuzhiyun ATTR_LIST(readdir_ra),
847*4882a593Smuzhiyun ATTR_LIST(max_io_bytes),
848*4882a593Smuzhiyun ATTR_LIST(gc_pin_file_thresh),
849*4882a593Smuzhiyun ATTR_LIST(extension_list),
850*4882a593Smuzhiyun #ifdef CONFIG_F2FS_FAULT_INJECTION
851*4882a593Smuzhiyun ATTR_LIST(inject_rate),
852*4882a593Smuzhiyun ATTR_LIST(inject_type),
853*4882a593Smuzhiyun #endif
854*4882a593Smuzhiyun ATTR_LIST(data_io_flag),
855*4882a593Smuzhiyun ATTR_LIST(node_io_flag),
856*4882a593Smuzhiyun ATTR_LIST(ckpt_thread_ioprio),
857*4882a593Smuzhiyun ATTR_LIST(dirty_segments),
858*4882a593Smuzhiyun ATTR_LIST(free_segments),
859*4882a593Smuzhiyun ATTR_LIST(ovp_segments),
860*4882a593Smuzhiyun ATTR_LIST(unusable),
861*4882a593Smuzhiyun ATTR_LIST(lifetime_write_kbytes),
862*4882a593Smuzhiyun ATTR_LIST(features),
863*4882a593Smuzhiyun ATTR_LIST(reserved_blocks),
864*4882a593Smuzhiyun ATTR_LIST(current_reserved_blocks),
865*4882a593Smuzhiyun ATTR_LIST(encoding),
866*4882a593Smuzhiyun ATTR_LIST(mounted_time_sec),
867*4882a593Smuzhiyun #ifdef CONFIG_F2FS_STAT_FS
868*4882a593Smuzhiyun ATTR_LIST(cp_foreground_calls),
869*4882a593Smuzhiyun ATTR_LIST(cp_background_calls),
870*4882a593Smuzhiyun ATTR_LIST(gc_foreground_calls),
871*4882a593Smuzhiyun ATTR_LIST(gc_background_calls),
872*4882a593Smuzhiyun ATTR_LIST(moved_blocks_foreground),
873*4882a593Smuzhiyun ATTR_LIST(moved_blocks_background),
874*4882a593Smuzhiyun ATTR_LIST(avg_vblocks),
875*4882a593Smuzhiyun #endif
876*4882a593Smuzhiyun #ifdef CONFIG_F2FS_FS_COMPRESSION
877*4882a593Smuzhiyun ATTR_LIST(compr_written_block),
878*4882a593Smuzhiyun ATTR_LIST(compr_saved_block),
879*4882a593Smuzhiyun ATTR_LIST(compr_new_inode),
880*4882a593Smuzhiyun #endif
881*4882a593Smuzhiyun /* For ATGC */
882*4882a593Smuzhiyun ATTR_LIST(atgc_candidate_ratio),
883*4882a593Smuzhiyun ATTR_LIST(atgc_candidate_count),
884*4882a593Smuzhiyun ATTR_LIST(atgc_age_weight),
885*4882a593Smuzhiyun ATTR_LIST(atgc_age_threshold),
886*4882a593Smuzhiyun ATTR_LIST(gc_segment_mode),
887*4882a593Smuzhiyun ATTR_LIST(gc_reclaimed_segments),
888*4882a593Smuzhiyun ATTR_LIST(hot_data_age_threshold),
889*4882a593Smuzhiyun ATTR_LIST(warm_data_age_threshold),
890*4882a593Smuzhiyun ATTR_LIST(last_age_weight),
891*4882a593Smuzhiyun NULL,
892*4882a593Smuzhiyun };
893*4882a593Smuzhiyun ATTRIBUTE_GROUPS(f2fs);
894*4882a593Smuzhiyun
895*4882a593Smuzhiyun static struct attribute *f2fs_feat_attrs[] = {
896*4882a593Smuzhiyun #ifdef CONFIG_FS_ENCRYPTION
897*4882a593Smuzhiyun ATTR_LIST(encryption),
898*4882a593Smuzhiyun ATTR_LIST(test_dummy_encryption_v2),
899*4882a593Smuzhiyun #ifdef CONFIG_UNICODE
900*4882a593Smuzhiyun ATTR_LIST(encrypted_casefold),
901*4882a593Smuzhiyun #endif
902*4882a593Smuzhiyun #endif /* CONFIG_FS_ENCRYPTION */
903*4882a593Smuzhiyun #ifdef CONFIG_BLK_DEV_ZONED
904*4882a593Smuzhiyun ATTR_LIST(block_zoned),
905*4882a593Smuzhiyun #endif
906*4882a593Smuzhiyun ATTR_LIST(atomic_write),
907*4882a593Smuzhiyun ATTR_LIST(extra_attr),
908*4882a593Smuzhiyun ATTR_LIST(project_quota),
909*4882a593Smuzhiyun ATTR_LIST(inode_checksum),
910*4882a593Smuzhiyun ATTR_LIST(flexible_inline_xattr),
911*4882a593Smuzhiyun ATTR_LIST(quota_ino),
912*4882a593Smuzhiyun ATTR_LIST(inode_crtime),
913*4882a593Smuzhiyun ATTR_LIST(lost_found),
914*4882a593Smuzhiyun #ifdef CONFIG_FS_VERITY
915*4882a593Smuzhiyun ATTR_LIST(verity),
916*4882a593Smuzhiyun #endif
917*4882a593Smuzhiyun ATTR_LIST(sb_checksum),
918*4882a593Smuzhiyun #ifdef CONFIG_UNICODE
919*4882a593Smuzhiyun ATTR_LIST(casefold),
920*4882a593Smuzhiyun #endif
921*4882a593Smuzhiyun ATTR_LIST(readonly),
922*4882a593Smuzhiyun #ifdef CONFIG_F2FS_FS_COMPRESSION
923*4882a593Smuzhiyun ATTR_LIST(compression),
924*4882a593Smuzhiyun #endif
925*4882a593Smuzhiyun ATTR_LIST(pin_file),
926*4882a593Smuzhiyun NULL,
927*4882a593Smuzhiyun };
928*4882a593Smuzhiyun ATTRIBUTE_GROUPS(f2fs_feat);
929*4882a593Smuzhiyun
930*4882a593Smuzhiyun F2FS_GENERAL_RO_ATTR(sb_status);
931*4882a593Smuzhiyun static struct attribute *f2fs_stat_attrs[] = {
932*4882a593Smuzhiyun ATTR_LIST(sb_status),
933*4882a593Smuzhiyun NULL,
934*4882a593Smuzhiyun };
935*4882a593Smuzhiyun ATTRIBUTE_GROUPS(f2fs_stat);
936*4882a593Smuzhiyun
937*4882a593Smuzhiyun F2FS_SB_FEATURE_RO_ATTR(encryption, ENCRYPT);
938*4882a593Smuzhiyun F2FS_SB_FEATURE_RO_ATTR(block_zoned, BLKZONED);
939*4882a593Smuzhiyun F2FS_SB_FEATURE_RO_ATTR(extra_attr, EXTRA_ATTR);
940*4882a593Smuzhiyun F2FS_SB_FEATURE_RO_ATTR(project_quota, PRJQUOTA);
941*4882a593Smuzhiyun F2FS_SB_FEATURE_RO_ATTR(inode_checksum, INODE_CHKSUM);
942*4882a593Smuzhiyun F2FS_SB_FEATURE_RO_ATTR(flexible_inline_xattr, FLEXIBLE_INLINE_XATTR);
943*4882a593Smuzhiyun F2FS_SB_FEATURE_RO_ATTR(quota_ino, QUOTA_INO);
944*4882a593Smuzhiyun F2FS_SB_FEATURE_RO_ATTR(inode_crtime, INODE_CRTIME);
945*4882a593Smuzhiyun F2FS_SB_FEATURE_RO_ATTR(lost_found, LOST_FOUND);
946*4882a593Smuzhiyun F2FS_SB_FEATURE_RO_ATTR(verity, VERITY);
947*4882a593Smuzhiyun F2FS_SB_FEATURE_RO_ATTR(sb_checksum, SB_CHKSUM);
948*4882a593Smuzhiyun F2FS_SB_FEATURE_RO_ATTR(casefold, CASEFOLD);
949*4882a593Smuzhiyun F2FS_SB_FEATURE_RO_ATTR(compression, COMPRESSION);
950*4882a593Smuzhiyun F2FS_SB_FEATURE_RO_ATTR(readonly, RO);
951*4882a593Smuzhiyun
952*4882a593Smuzhiyun static struct attribute *f2fs_sb_feat_attrs[] = {
953*4882a593Smuzhiyun ATTR_LIST(sb_encryption),
954*4882a593Smuzhiyun ATTR_LIST(sb_block_zoned),
955*4882a593Smuzhiyun ATTR_LIST(sb_extra_attr),
956*4882a593Smuzhiyun ATTR_LIST(sb_project_quota),
957*4882a593Smuzhiyun ATTR_LIST(sb_inode_checksum),
958*4882a593Smuzhiyun ATTR_LIST(sb_flexible_inline_xattr),
959*4882a593Smuzhiyun ATTR_LIST(sb_quota_ino),
960*4882a593Smuzhiyun ATTR_LIST(sb_inode_crtime),
961*4882a593Smuzhiyun ATTR_LIST(sb_lost_found),
962*4882a593Smuzhiyun ATTR_LIST(sb_verity),
963*4882a593Smuzhiyun ATTR_LIST(sb_sb_checksum),
964*4882a593Smuzhiyun ATTR_LIST(sb_casefold),
965*4882a593Smuzhiyun ATTR_LIST(sb_compression),
966*4882a593Smuzhiyun ATTR_LIST(sb_readonly),
967*4882a593Smuzhiyun NULL,
968*4882a593Smuzhiyun };
969*4882a593Smuzhiyun ATTRIBUTE_GROUPS(f2fs_sb_feat);
970*4882a593Smuzhiyun
971*4882a593Smuzhiyun static const struct sysfs_ops f2fs_attr_ops = {
972*4882a593Smuzhiyun .show = f2fs_attr_show,
973*4882a593Smuzhiyun .store = f2fs_attr_store,
974*4882a593Smuzhiyun };
975*4882a593Smuzhiyun
976*4882a593Smuzhiyun static struct kobj_type f2fs_sb_ktype = {
977*4882a593Smuzhiyun .default_groups = f2fs_groups,
978*4882a593Smuzhiyun .sysfs_ops = &f2fs_attr_ops,
979*4882a593Smuzhiyun .release = f2fs_sb_release,
980*4882a593Smuzhiyun };
981*4882a593Smuzhiyun
982*4882a593Smuzhiyun static struct kobj_type f2fs_ktype = {
983*4882a593Smuzhiyun .sysfs_ops = &f2fs_attr_ops,
984*4882a593Smuzhiyun };
985*4882a593Smuzhiyun
986*4882a593Smuzhiyun static struct kset f2fs_kset = {
987*4882a593Smuzhiyun .kobj = {.ktype = &f2fs_ktype},
988*4882a593Smuzhiyun };
989*4882a593Smuzhiyun
990*4882a593Smuzhiyun static struct kobj_type f2fs_feat_ktype = {
991*4882a593Smuzhiyun .default_groups = f2fs_feat_groups,
992*4882a593Smuzhiyun .sysfs_ops = &f2fs_attr_ops,
993*4882a593Smuzhiyun };
994*4882a593Smuzhiyun
995*4882a593Smuzhiyun static struct kobject f2fs_feat = {
996*4882a593Smuzhiyun .kset = &f2fs_kset,
997*4882a593Smuzhiyun };
998*4882a593Smuzhiyun
f2fs_stat_attr_show(struct kobject * kobj,struct attribute * attr,char * buf)999*4882a593Smuzhiyun static ssize_t f2fs_stat_attr_show(struct kobject *kobj,
1000*4882a593Smuzhiyun struct attribute *attr, char *buf)
1001*4882a593Smuzhiyun {
1002*4882a593Smuzhiyun struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info,
1003*4882a593Smuzhiyun s_stat_kobj);
1004*4882a593Smuzhiyun struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr);
1005*4882a593Smuzhiyun
1006*4882a593Smuzhiyun return a->show ? a->show(a, sbi, buf) : 0;
1007*4882a593Smuzhiyun }
1008*4882a593Smuzhiyun
f2fs_stat_attr_store(struct kobject * kobj,struct attribute * attr,const char * buf,size_t len)1009*4882a593Smuzhiyun static ssize_t f2fs_stat_attr_store(struct kobject *kobj, struct attribute *attr,
1010*4882a593Smuzhiyun const char *buf, size_t len)
1011*4882a593Smuzhiyun {
1012*4882a593Smuzhiyun struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info,
1013*4882a593Smuzhiyun s_stat_kobj);
1014*4882a593Smuzhiyun struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr);
1015*4882a593Smuzhiyun
1016*4882a593Smuzhiyun return a->store ? a->store(a, sbi, buf, len) : 0;
1017*4882a593Smuzhiyun }
1018*4882a593Smuzhiyun
f2fs_stat_kobj_release(struct kobject * kobj)1019*4882a593Smuzhiyun static void f2fs_stat_kobj_release(struct kobject *kobj)
1020*4882a593Smuzhiyun {
1021*4882a593Smuzhiyun struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info,
1022*4882a593Smuzhiyun s_stat_kobj);
1023*4882a593Smuzhiyun complete(&sbi->s_stat_kobj_unregister);
1024*4882a593Smuzhiyun }
1025*4882a593Smuzhiyun
1026*4882a593Smuzhiyun static const struct sysfs_ops f2fs_stat_attr_ops = {
1027*4882a593Smuzhiyun .show = f2fs_stat_attr_show,
1028*4882a593Smuzhiyun .store = f2fs_stat_attr_store,
1029*4882a593Smuzhiyun };
1030*4882a593Smuzhiyun
1031*4882a593Smuzhiyun static struct kobj_type f2fs_stat_ktype = {
1032*4882a593Smuzhiyun .default_groups = f2fs_stat_groups,
1033*4882a593Smuzhiyun .sysfs_ops = &f2fs_stat_attr_ops,
1034*4882a593Smuzhiyun .release = f2fs_stat_kobj_release,
1035*4882a593Smuzhiyun };
1036*4882a593Smuzhiyun
f2fs_sb_feat_attr_show(struct kobject * kobj,struct attribute * attr,char * buf)1037*4882a593Smuzhiyun static ssize_t f2fs_sb_feat_attr_show(struct kobject *kobj,
1038*4882a593Smuzhiyun struct attribute *attr, char *buf)
1039*4882a593Smuzhiyun {
1040*4882a593Smuzhiyun struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info,
1041*4882a593Smuzhiyun s_feature_list_kobj);
1042*4882a593Smuzhiyun struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr);
1043*4882a593Smuzhiyun
1044*4882a593Smuzhiyun return a->show ? a->show(a, sbi, buf) : 0;
1045*4882a593Smuzhiyun }
1046*4882a593Smuzhiyun
f2fs_feature_list_kobj_release(struct kobject * kobj)1047*4882a593Smuzhiyun static void f2fs_feature_list_kobj_release(struct kobject *kobj)
1048*4882a593Smuzhiyun {
1049*4882a593Smuzhiyun struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info,
1050*4882a593Smuzhiyun s_feature_list_kobj);
1051*4882a593Smuzhiyun complete(&sbi->s_feature_list_kobj_unregister);
1052*4882a593Smuzhiyun }
1053*4882a593Smuzhiyun
1054*4882a593Smuzhiyun static const struct sysfs_ops f2fs_feature_list_attr_ops = {
1055*4882a593Smuzhiyun .show = f2fs_sb_feat_attr_show,
1056*4882a593Smuzhiyun };
1057*4882a593Smuzhiyun
1058*4882a593Smuzhiyun static struct kobj_type f2fs_feature_list_ktype = {
1059*4882a593Smuzhiyun .default_groups = f2fs_sb_feat_groups,
1060*4882a593Smuzhiyun .sysfs_ops = &f2fs_feature_list_attr_ops,
1061*4882a593Smuzhiyun .release = f2fs_feature_list_kobj_release,
1062*4882a593Smuzhiyun };
1063*4882a593Smuzhiyun
segment_info_seq_show(struct seq_file * seq,void * offset)1064*4882a593Smuzhiyun static int __maybe_unused segment_info_seq_show(struct seq_file *seq,
1065*4882a593Smuzhiyun void *offset)
1066*4882a593Smuzhiyun {
1067*4882a593Smuzhiyun struct super_block *sb = seq->private;
1068*4882a593Smuzhiyun struct f2fs_sb_info *sbi = F2FS_SB(sb);
1069*4882a593Smuzhiyun unsigned int total_segs =
1070*4882a593Smuzhiyun le32_to_cpu(sbi->raw_super->segment_count_main);
1071*4882a593Smuzhiyun int i;
1072*4882a593Smuzhiyun
1073*4882a593Smuzhiyun seq_puts(seq, "format: segment_type|valid_blocks\n"
1074*4882a593Smuzhiyun "segment_type(0:HD, 1:WD, 2:CD, 3:HN, 4:WN, 5:CN)\n");
1075*4882a593Smuzhiyun
1076*4882a593Smuzhiyun for (i = 0; i < total_segs; i++) {
1077*4882a593Smuzhiyun struct seg_entry *se = get_seg_entry(sbi, i);
1078*4882a593Smuzhiyun
1079*4882a593Smuzhiyun if ((i % 10) == 0)
1080*4882a593Smuzhiyun seq_printf(seq, "%-10d", i);
1081*4882a593Smuzhiyun seq_printf(seq, "%d|%-3u", se->type, se->valid_blocks);
1082*4882a593Smuzhiyun if ((i % 10) == 9 || i == (total_segs - 1))
1083*4882a593Smuzhiyun seq_putc(seq, '\n');
1084*4882a593Smuzhiyun else
1085*4882a593Smuzhiyun seq_putc(seq, ' ');
1086*4882a593Smuzhiyun }
1087*4882a593Smuzhiyun
1088*4882a593Smuzhiyun return 0;
1089*4882a593Smuzhiyun }
1090*4882a593Smuzhiyun
segment_bits_seq_show(struct seq_file * seq,void * offset)1091*4882a593Smuzhiyun static int __maybe_unused segment_bits_seq_show(struct seq_file *seq,
1092*4882a593Smuzhiyun void *offset)
1093*4882a593Smuzhiyun {
1094*4882a593Smuzhiyun struct super_block *sb = seq->private;
1095*4882a593Smuzhiyun struct f2fs_sb_info *sbi = F2FS_SB(sb);
1096*4882a593Smuzhiyun unsigned int total_segs =
1097*4882a593Smuzhiyun le32_to_cpu(sbi->raw_super->segment_count_main);
1098*4882a593Smuzhiyun int i, j;
1099*4882a593Smuzhiyun
1100*4882a593Smuzhiyun seq_puts(seq, "format: segment_type|valid_blocks|bitmaps\n"
1101*4882a593Smuzhiyun "segment_type(0:HD, 1:WD, 2:CD, 3:HN, 4:WN, 5:CN)\n");
1102*4882a593Smuzhiyun
1103*4882a593Smuzhiyun for (i = 0; i < total_segs; i++) {
1104*4882a593Smuzhiyun struct seg_entry *se = get_seg_entry(sbi, i);
1105*4882a593Smuzhiyun
1106*4882a593Smuzhiyun seq_printf(seq, "%-10d", i);
1107*4882a593Smuzhiyun seq_printf(seq, "%d|%-3u|", se->type, se->valid_blocks);
1108*4882a593Smuzhiyun for (j = 0; j < SIT_VBLOCK_MAP_SIZE; j++)
1109*4882a593Smuzhiyun seq_printf(seq, " %.2x", se->cur_valid_map[j]);
1110*4882a593Smuzhiyun seq_putc(seq, '\n');
1111*4882a593Smuzhiyun }
1112*4882a593Smuzhiyun return 0;
1113*4882a593Smuzhiyun }
1114*4882a593Smuzhiyun
f2fs_record_iostat(struct f2fs_sb_info * sbi)1115*4882a593Smuzhiyun void f2fs_record_iostat(struct f2fs_sb_info *sbi)
1116*4882a593Smuzhiyun {
1117*4882a593Smuzhiyun unsigned long long iostat_diff[NR_IO_TYPE];
1118*4882a593Smuzhiyun int i;
1119*4882a593Smuzhiyun
1120*4882a593Smuzhiyun if (time_is_after_jiffies(sbi->iostat_next_period))
1121*4882a593Smuzhiyun return;
1122*4882a593Smuzhiyun
1123*4882a593Smuzhiyun /* Need double check under the lock */
1124*4882a593Smuzhiyun spin_lock(&sbi->iostat_lock);
1125*4882a593Smuzhiyun if (time_is_after_jiffies(sbi->iostat_next_period)) {
1126*4882a593Smuzhiyun spin_unlock(&sbi->iostat_lock);
1127*4882a593Smuzhiyun return;
1128*4882a593Smuzhiyun }
1129*4882a593Smuzhiyun sbi->iostat_next_period = jiffies +
1130*4882a593Smuzhiyun msecs_to_jiffies(sbi->iostat_period_ms);
1131*4882a593Smuzhiyun
1132*4882a593Smuzhiyun for (i = 0; i < NR_IO_TYPE; i++) {
1133*4882a593Smuzhiyun iostat_diff[i] = sbi->rw_iostat[i] -
1134*4882a593Smuzhiyun sbi->prev_rw_iostat[i];
1135*4882a593Smuzhiyun sbi->prev_rw_iostat[i] = sbi->rw_iostat[i];
1136*4882a593Smuzhiyun }
1137*4882a593Smuzhiyun spin_unlock(&sbi->iostat_lock);
1138*4882a593Smuzhiyun
1139*4882a593Smuzhiyun trace_f2fs_iostat(sbi, iostat_diff);
1140*4882a593Smuzhiyun }
1141*4882a593Smuzhiyun
iostat_info_seq_show(struct seq_file * seq,void * offset)1142*4882a593Smuzhiyun static int __maybe_unused iostat_info_seq_show(struct seq_file *seq,
1143*4882a593Smuzhiyun void *offset)
1144*4882a593Smuzhiyun {
1145*4882a593Smuzhiyun struct super_block *sb = seq->private;
1146*4882a593Smuzhiyun struct f2fs_sb_info *sbi = F2FS_SB(sb);
1147*4882a593Smuzhiyun time64_t now = ktime_get_real_seconds();
1148*4882a593Smuzhiyun
1149*4882a593Smuzhiyun if (!sbi->iostat_enable)
1150*4882a593Smuzhiyun return 0;
1151*4882a593Smuzhiyun
1152*4882a593Smuzhiyun seq_printf(seq, "time: %-16llu\n", now);
1153*4882a593Smuzhiyun
1154*4882a593Smuzhiyun /* print app write IOs */
1155*4882a593Smuzhiyun seq_puts(seq, "[WRITE]\n");
1156*4882a593Smuzhiyun seq_printf(seq, "app buffered: %-16llu\n",
1157*4882a593Smuzhiyun sbi->rw_iostat[APP_BUFFERED_IO]);
1158*4882a593Smuzhiyun seq_printf(seq, "app direct: %-16llu\n",
1159*4882a593Smuzhiyun sbi->rw_iostat[APP_DIRECT_IO]);
1160*4882a593Smuzhiyun seq_printf(seq, "app mapped: %-16llu\n",
1161*4882a593Smuzhiyun sbi->rw_iostat[APP_MAPPED_IO]);
1162*4882a593Smuzhiyun
1163*4882a593Smuzhiyun /* print fs write IOs */
1164*4882a593Smuzhiyun seq_printf(seq, "fs data: %-16llu\n",
1165*4882a593Smuzhiyun sbi->rw_iostat[FS_DATA_IO]);
1166*4882a593Smuzhiyun seq_printf(seq, "fs node: %-16llu\n",
1167*4882a593Smuzhiyun sbi->rw_iostat[FS_NODE_IO]);
1168*4882a593Smuzhiyun seq_printf(seq, "fs meta: %-16llu\n",
1169*4882a593Smuzhiyun sbi->rw_iostat[FS_META_IO]);
1170*4882a593Smuzhiyun seq_printf(seq, "fs gc data: %-16llu\n",
1171*4882a593Smuzhiyun sbi->rw_iostat[FS_GC_DATA_IO]);
1172*4882a593Smuzhiyun seq_printf(seq, "fs gc node: %-16llu\n",
1173*4882a593Smuzhiyun sbi->rw_iostat[FS_GC_NODE_IO]);
1174*4882a593Smuzhiyun seq_printf(seq, "fs cp data: %-16llu\n",
1175*4882a593Smuzhiyun sbi->rw_iostat[FS_CP_DATA_IO]);
1176*4882a593Smuzhiyun seq_printf(seq, "fs cp node: %-16llu\n",
1177*4882a593Smuzhiyun sbi->rw_iostat[FS_CP_NODE_IO]);
1178*4882a593Smuzhiyun seq_printf(seq, "fs cp meta: %-16llu\n",
1179*4882a593Smuzhiyun sbi->rw_iostat[FS_CP_META_IO]);
1180*4882a593Smuzhiyun
1181*4882a593Smuzhiyun /* print app read IOs */
1182*4882a593Smuzhiyun seq_puts(seq, "[READ]\n");
1183*4882a593Smuzhiyun seq_printf(seq, "app buffered: %-16llu\n",
1184*4882a593Smuzhiyun sbi->rw_iostat[APP_BUFFERED_READ_IO]);
1185*4882a593Smuzhiyun seq_printf(seq, "app direct: %-16llu\n",
1186*4882a593Smuzhiyun sbi->rw_iostat[APP_DIRECT_READ_IO]);
1187*4882a593Smuzhiyun seq_printf(seq, "app mapped: %-16llu\n",
1188*4882a593Smuzhiyun sbi->rw_iostat[APP_MAPPED_READ_IO]);
1189*4882a593Smuzhiyun
1190*4882a593Smuzhiyun /* print fs read IOs */
1191*4882a593Smuzhiyun seq_printf(seq, "fs data: %-16llu\n",
1192*4882a593Smuzhiyun sbi->rw_iostat[FS_DATA_READ_IO]);
1193*4882a593Smuzhiyun seq_printf(seq, "fs gc data: %-16llu\n",
1194*4882a593Smuzhiyun sbi->rw_iostat[FS_GDATA_READ_IO]);
1195*4882a593Smuzhiyun seq_printf(seq, "fs compr_data: %-16llu\n",
1196*4882a593Smuzhiyun sbi->rw_iostat[FS_CDATA_READ_IO]);
1197*4882a593Smuzhiyun seq_printf(seq, "fs node: %-16llu\n",
1198*4882a593Smuzhiyun sbi->rw_iostat[FS_NODE_READ_IO]);
1199*4882a593Smuzhiyun seq_printf(seq, "fs meta: %-16llu\n",
1200*4882a593Smuzhiyun sbi->rw_iostat[FS_META_READ_IO]);
1201*4882a593Smuzhiyun
1202*4882a593Smuzhiyun /* print other IOs */
1203*4882a593Smuzhiyun seq_puts(seq, "[OTHER]\n");
1204*4882a593Smuzhiyun seq_printf(seq, "fs discard: %-16llu\n",
1205*4882a593Smuzhiyun sbi->rw_iostat[FS_DISCARD]);
1206*4882a593Smuzhiyun
1207*4882a593Smuzhiyun return 0;
1208*4882a593Smuzhiyun }
1209*4882a593Smuzhiyun
victim_bits_seq_show(struct seq_file * seq,void * offset)1210*4882a593Smuzhiyun static int __maybe_unused victim_bits_seq_show(struct seq_file *seq,
1211*4882a593Smuzhiyun void *offset)
1212*4882a593Smuzhiyun {
1213*4882a593Smuzhiyun struct super_block *sb = seq->private;
1214*4882a593Smuzhiyun struct f2fs_sb_info *sbi = F2FS_SB(sb);
1215*4882a593Smuzhiyun struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
1216*4882a593Smuzhiyun int i;
1217*4882a593Smuzhiyun
1218*4882a593Smuzhiyun seq_puts(seq, "format: victim_secmap bitmaps\n");
1219*4882a593Smuzhiyun
1220*4882a593Smuzhiyun for (i = 0; i < MAIN_SECS(sbi); i++) {
1221*4882a593Smuzhiyun if ((i % 10) == 0)
1222*4882a593Smuzhiyun seq_printf(seq, "%-10d", i);
1223*4882a593Smuzhiyun seq_printf(seq, "%d", test_bit(i, dirty_i->victim_secmap) ? 1 : 0);
1224*4882a593Smuzhiyun if ((i % 10) == 9 || i == (MAIN_SECS(sbi) - 1))
1225*4882a593Smuzhiyun seq_putc(seq, '\n');
1226*4882a593Smuzhiyun else
1227*4882a593Smuzhiyun seq_putc(seq, ' ');
1228*4882a593Smuzhiyun }
1229*4882a593Smuzhiyun return 0;
1230*4882a593Smuzhiyun }
1231*4882a593Smuzhiyun
f2fs_init_sysfs(void)1232*4882a593Smuzhiyun int __init f2fs_init_sysfs(void)
1233*4882a593Smuzhiyun {
1234*4882a593Smuzhiyun int ret;
1235*4882a593Smuzhiyun
1236*4882a593Smuzhiyun kobject_set_name(&f2fs_kset.kobj, "f2fs");
1237*4882a593Smuzhiyun f2fs_kset.kobj.parent = fs_kobj;
1238*4882a593Smuzhiyun ret = kset_register(&f2fs_kset);
1239*4882a593Smuzhiyun if (ret)
1240*4882a593Smuzhiyun return ret;
1241*4882a593Smuzhiyun
1242*4882a593Smuzhiyun ret = kobject_init_and_add(&f2fs_feat, &f2fs_feat_ktype,
1243*4882a593Smuzhiyun NULL, "features");
1244*4882a593Smuzhiyun if (ret) {
1245*4882a593Smuzhiyun kobject_put(&f2fs_feat);
1246*4882a593Smuzhiyun kset_unregister(&f2fs_kset);
1247*4882a593Smuzhiyun } else {
1248*4882a593Smuzhiyun f2fs_proc_root = proc_mkdir("fs/f2fs", NULL);
1249*4882a593Smuzhiyun }
1250*4882a593Smuzhiyun return ret;
1251*4882a593Smuzhiyun }
1252*4882a593Smuzhiyun
f2fs_exit_sysfs(void)1253*4882a593Smuzhiyun void f2fs_exit_sysfs(void)
1254*4882a593Smuzhiyun {
1255*4882a593Smuzhiyun kobject_put(&f2fs_feat);
1256*4882a593Smuzhiyun kset_unregister(&f2fs_kset);
1257*4882a593Smuzhiyun remove_proc_entry("fs/f2fs", NULL);
1258*4882a593Smuzhiyun f2fs_proc_root = NULL;
1259*4882a593Smuzhiyun }
1260*4882a593Smuzhiyun
f2fs_register_sysfs(struct f2fs_sb_info * sbi)1261*4882a593Smuzhiyun int f2fs_register_sysfs(struct f2fs_sb_info *sbi)
1262*4882a593Smuzhiyun {
1263*4882a593Smuzhiyun struct super_block *sb = sbi->sb;
1264*4882a593Smuzhiyun int err;
1265*4882a593Smuzhiyun
1266*4882a593Smuzhiyun sbi->s_kobj.kset = &f2fs_kset;
1267*4882a593Smuzhiyun init_completion(&sbi->s_kobj_unregister);
1268*4882a593Smuzhiyun err = kobject_init_and_add(&sbi->s_kobj, &f2fs_sb_ktype, NULL,
1269*4882a593Smuzhiyun "%s", sb->s_id);
1270*4882a593Smuzhiyun if (err)
1271*4882a593Smuzhiyun goto put_sb_kobj;
1272*4882a593Smuzhiyun
1273*4882a593Smuzhiyun sbi->s_stat_kobj.kset = &f2fs_kset;
1274*4882a593Smuzhiyun init_completion(&sbi->s_stat_kobj_unregister);
1275*4882a593Smuzhiyun err = kobject_init_and_add(&sbi->s_stat_kobj, &f2fs_stat_ktype,
1276*4882a593Smuzhiyun &sbi->s_kobj, "stat");
1277*4882a593Smuzhiyun if (err)
1278*4882a593Smuzhiyun goto put_stat_kobj;
1279*4882a593Smuzhiyun
1280*4882a593Smuzhiyun sbi->s_feature_list_kobj.kset = &f2fs_kset;
1281*4882a593Smuzhiyun init_completion(&sbi->s_feature_list_kobj_unregister);
1282*4882a593Smuzhiyun err = kobject_init_and_add(&sbi->s_feature_list_kobj,
1283*4882a593Smuzhiyun &f2fs_feature_list_ktype,
1284*4882a593Smuzhiyun &sbi->s_kobj, "feature_list");
1285*4882a593Smuzhiyun if (err)
1286*4882a593Smuzhiyun goto put_feature_list_kobj;
1287*4882a593Smuzhiyun
1288*4882a593Smuzhiyun if (f2fs_proc_root)
1289*4882a593Smuzhiyun sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root);
1290*4882a593Smuzhiyun
1291*4882a593Smuzhiyun if (sbi->s_proc) {
1292*4882a593Smuzhiyun proc_create_single_data("segment_info", S_IRUGO, sbi->s_proc,
1293*4882a593Smuzhiyun segment_info_seq_show, sb);
1294*4882a593Smuzhiyun proc_create_single_data("segment_bits", S_IRUGO, sbi->s_proc,
1295*4882a593Smuzhiyun segment_bits_seq_show, sb);
1296*4882a593Smuzhiyun proc_create_single_data("iostat_info", S_IRUGO, sbi->s_proc,
1297*4882a593Smuzhiyun iostat_info_seq_show, sb);
1298*4882a593Smuzhiyun proc_create_single_data("victim_bits", S_IRUGO, sbi->s_proc,
1299*4882a593Smuzhiyun victim_bits_seq_show, sb);
1300*4882a593Smuzhiyun }
1301*4882a593Smuzhiyun return 0;
1302*4882a593Smuzhiyun put_feature_list_kobj:
1303*4882a593Smuzhiyun kobject_put(&sbi->s_feature_list_kobj);
1304*4882a593Smuzhiyun wait_for_completion(&sbi->s_feature_list_kobj_unregister);
1305*4882a593Smuzhiyun put_stat_kobj:
1306*4882a593Smuzhiyun kobject_put(&sbi->s_stat_kobj);
1307*4882a593Smuzhiyun wait_for_completion(&sbi->s_stat_kobj_unregister);
1308*4882a593Smuzhiyun put_sb_kobj:
1309*4882a593Smuzhiyun kobject_put(&sbi->s_kobj);
1310*4882a593Smuzhiyun wait_for_completion(&sbi->s_kobj_unregister);
1311*4882a593Smuzhiyun return err;
1312*4882a593Smuzhiyun }
1313*4882a593Smuzhiyun
f2fs_unregister_sysfs(struct f2fs_sb_info * sbi)1314*4882a593Smuzhiyun void f2fs_unregister_sysfs(struct f2fs_sb_info *sbi)
1315*4882a593Smuzhiyun {
1316*4882a593Smuzhiyun if (sbi->s_proc) {
1317*4882a593Smuzhiyun remove_proc_entry("iostat_info", sbi->s_proc);
1318*4882a593Smuzhiyun remove_proc_entry("segment_info", sbi->s_proc);
1319*4882a593Smuzhiyun remove_proc_entry("segment_bits", sbi->s_proc);
1320*4882a593Smuzhiyun remove_proc_entry("victim_bits", sbi->s_proc);
1321*4882a593Smuzhiyun remove_proc_entry(sbi->sb->s_id, f2fs_proc_root);
1322*4882a593Smuzhiyun }
1323*4882a593Smuzhiyun
1324*4882a593Smuzhiyun kobject_del(&sbi->s_stat_kobj);
1325*4882a593Smuzhiyun kobject_put(&sbi->s_stat_kobj);
1326*4882a593Smuzhiyun wait_for_completion(&sbi->s_stat_kobj_unregister);
1327*4882a593Smuzhiyun kobject_del(&sbi->s_feature_list_kobj);
1328*4882a593Smuzhiyun kobject_put(&sbi->s_feature_list_kobj);
1329*4882a593Smuzhiyun wait_for_completion(&sbi->s_feature_list_kobj_unregister);
1330*4882a593Smuzhiyun
1331*4882a593Smuzhiyun kobject_del(&sbi->s_kobj);
1332*4882a593Smuzhiyun kobject_put(&sbi->s_kobj);
1333*4882a593Smuzhiyun wait_for_completion(&sbi->s_kobj_unregister);
1334*4882a593Smuzhiyun }
1335