1818#include "gc.h"
1919
2020static struct proc_dir_entry * f2fs_proc_root ;
21- static struct kset * f2fs_kset ;
2221
2322/* Sysfs support for f2fs */
2423enum {
@@ -41,6 +40,7 @@ struct f2fs_attr {
4140 const char * , size_t );
4241 int struct_type ;
4342 int offset ;
43+ int id ;
4444};
4545
4646static unsigned char * __struct_ptr (struct f2fs_sb_info * sbi , int struct_type )
@@ -76,6 +76,34 @@ static ssize_t lifetime_write_kbytes_show(struct f2fs_attr *a,
7676 BD_PART_WRITTEN (sbi )));
7777}
7878
79+ static ssize_t features_show (struct f2fs_attr * a ,
80+ struct f2fs_sb_info * sbi , char * buf )
81+ {
82+ struct super_block * sb = sbi -> sb ;
83+ int len = 0 ;
84+
85+ if (!sb -> s_bdev -> bd_part )
86+ return snprintf (buf , PAGE_SIZE , "0\n" );
87+
88+ if (f2fs_sb_has_crypto (sb ))
89+ len += snprintf (buf , PAGE_SIZE - len , "%s" ,
90+ "encryption" );
91+ if (f2fs_sb_mounted_blkzoned (sb ))
92+ len += snprintf (buf + len , PAGE_SIZE - len , "%s%s" ,
93+ len ? ", " : "" , "blkzoned" );
94+ if (f2fs_sb_has_extra_attr (sb ))
95+ len += snprintf (buf + len , PAGE_SIZE - len , "%s%s" ,
96+ len ? ", " : "" , "extra_attr" );
97+ if (f2fs_sb_has_project_quota (sb ))
98+ len += snprintf (buf + len , PAGE_SIZE - len , "%s%s" ,
99+ len ? ", " : "" , "projquota" );
100+ if (f2fs_sb_has_inode_chksum (sb ))
101+ len += snprintf (buf + len , PAGE_SIZE - len , "%s%s" ,
102+ len ? ", " : "" , "inode_checksum" );
103+ len += snprintf (buf + len , PAGE_SIZE - len , "\n" );
104+ return len ;
105+ }
106+
79107static ssize_t f2fs_sbi_show (struct f2fs_attr * a ,
80108 struct f2fs_sb_info * sbi , char * buf )
81109{
@@ -155,6 +183,30 @@ static void f2fs_sb_release(struct kobject *kobj)
155183 complete (& sbi -> s_kobj_unregister );
156184}
157185
186+ enum feat_id {
187+ FEAT_CRYPTO = 0 ,
188+ FEAT_BLKZONED ,
189+ FEAT_ATOMIC_WRITE ,
190+ FEAT_EXTRA_ATTR ,
191+ FEAT_PROJECT_QUOTA ,
192+ FEAT_INODE_CHECKSUM ,
193+ };
194+
195+ static ssize_t f2fs_feature_show (struct f2fs_attr * a ,
196+ struct f2fs_sb_info * sbi , char * buf )
197+ {
198+ switch (a -> id ) {
199+ case FEAT_CRYPTO :
200+ case FEAT_BLKZONED :
201+ case FEAT_ATOMIC_WRITE :
202+ case FEAT_EXTRA_ATTR :
203+ case FEAT_PROJECT_QUOTA :
204+ case FEAT_INODE_CHECKSUM :
205+ return snprintf (buf , PAGE_SIZE , "supported\n" );
206+ }
207+ return 0 ;
208+ }
209+
158210#define F2FS_ATTR_OFFSET (_struct_type , _name , _mode , _show , _store , _offset ) \
159211static struct f2fs_attr f2fs_attr_##_name = { \
160212 .attr = {.name = __stringify(_name), .mode = _mode }, \
@@ -172,6 +224,13 @@ static struct f2fs_attr f2fs_attr_##_name = { \
172224#define F2FS_GENERAL_RO_ATTR (name ) \
173225static struct f2fs_attr f2fs_attr_##name = __ATTR(name, 0444, name##_show, NULL)
174226
227+ #define F2FS_FEATURE_RO_ATTR (_name , _id ) \
228+ static struct f2fs_attr f2fs_attr_##_name = { \
229+ .attr = {.name = __stringify(_name), .mode = 0444 }, \
230+ .show = f2fs_feature_show, \
231+ .id = _id, \
232+ }
233+
175234F2FS_RW_ATTR (GC_THREAD , f2fs_gc_kthread , gc_min_sleep_time , min_sleep_time );
176235F2FS_RW_ATTR (GC_THREAD , f2fs_gc_kthread , gc_max_sleep_time , max_sleep_time );
177236F2FS_RW_ATTR (GC_THREAD , f2fs_gc_kthread , gc_no_gc_sleep_time , no_gc_sleep_time );
@@ -196,6 +255,18 @@ F2FS_RW_ATTR(FAULT_INFO_RATE, f2fs_fault_info, inject_rate, inject_rate);
196255F2FS_RW_ATTR (FAULT_INFO_TYPE , f2fs_fault_info , inject_type , inject_type );
197256#endif
198257F2FS_GENERAL_RO_ATTR (lifetime_write_kbytes );
258+ F2FS_GENERAL_RO_ATTR (features );
259+
260+ #ifdef CONFIG_F2FS_FS_ENCRYPTION
261+ F2FS_FEATURE_RO_ATTR (encryption , FEAT_CRYPTO );
262+ #endif
263+ #ifdef CONFIG_BLK_DEV_ZONED
264+ F2FS_FEATURE_RO_ATTR (block_zoned , FEAT_BLKZONED );
265+ #endif
266+ F2FS_FEATURE_RO_ATTR (atomic_write , FEAT_ATOMIC_WRITE );
267+ F2FS_FEATURE_RO_ATTR (extra_attr , FEAT_EXTRA_ATTR );
268+ F2FS_FEATURE_RO_ATTR (project_quota , FEAT_PROJECT_QUOTA );
269+ F2FS_FEATURE_RO_ATTR (inode_checksum , FEAT_INODE_CHECKSUM );
199270
200271#define ATTR_LIST (name ) (&f2fs_attr_##name.attr)
201272static struct attribute * f2fs_attrs [] = {
@@ -222,21 +293,53 @@ static struct attribute *f2fs_attrs[] = {
222293 ATTR_LIST (inject_type ),
223294#endif
224295 ATTR_LIST (lifetime_write_kbytes ),
296+ ATTR_LIST (features ),
225297 ATTR_LIST (reserved_blocks ),
226298 NULL ,
227299};
228300
301+ static struct attribute * f2fs_feat_attrs [] = {
302+ #ifdef CONFIG_F2FS_FS_ENCRYPTION
303+ ATTR_LIST (encryption ),
304+ #endif
305+ #ifdef CONFIG_BLK_DEV_ZONED
306+ ATTR_LIST (block_zoned ),
307+ #endif
308+ ATTR_LIST (atomic_write ),
309+ ATTR_LIST (extra_attr ),
310+ ATTR_LIST (project_quota ),
311+ ATTR_LIST (inode_checksum ),
312+ NULL ,
313+ };
314+
229315static const struct sysfs_ops f2fs_attr_ops = {
230316 .show = f2fs_attr_show ,
231317 .store = f2fs_attr_store ,
232318};
233319
234- static struct kobj_type f2fs_ktype = {
320+ static struct kobj_type f2fs_sb_ktype = {
235321 .default_attrs = f2fs_attrs ,
236322 .sysfs_ops = & f2fs_attr_ops ,
237323 .release = f2fs_sb_release ,
238324};
239325
326+ static struct kobj_type f2fs_ktype = {
327+ .sysfs_ops = & f2fs_attr_ops ,
328+ };
329+
330+ static struct kset f2fs_kset = {
331+ .kobj = {.ktype = & f2fs_ktype },
332+ };
333+
334+ static struct kobj_type f2fs_feat_ktype = {
335+ .default_attrs = f2fs_feat_attrs ,
336+ .sysfs_ops = & f2fs_attr_ops ,
337+ };
338+
339+ static struct kobject f2fs_feat = {
340+ .kset = & f2fs_kset ,
341+ };
342+
240343static int segment_info_seq_show (struct seq_file * seq , void * offset )
241344{
242345 struct super_block * sb = seq -> private ;
@@ -306,25 +409,43 @@ F2FS_PROC_FILE_DEF(segment_bits);
306409
307410int __init f2fs_init_sysfs (void )
308411{
309- f2fs_proc_root = proc_mkdir ( "fs/f2fs" , NULL ) ;
412+ int ret ;
310413
311- f2fs_kset = kset_create_and_add ("f2fs" , NULL , fs_kobj );
312- if (!f2fs_kset )
313- return - ENOMEM ;
314- return 0 ;
414+ kobject_set_name (& f2fs_kset .kobj , "f2fs" );
415+ f2fs_kset .kobj .parent = fs_kobj ;
416+ ret = kset_register (& f2fs_kset );
417+ if (ret )
418+ return ret ;
419+
420+ ret = kobject_init_and_add (& f2fs_feat , & f2fs_feat_ktype ,
421+ NULL , "features" );
422+ if (ret )
423+ kset_unregister (& f2fs_kset );
424+ else
425+ f2fs_proc_root = proc_mkdir ("fs/f2fs" , NULL );
426+ return ret ;
315427}
316428
317429void f2fs_exit_sysfs (void )
318430{
319- kset_unregister (f2fs_kset );
431+ kobject_put (& f2fs_feat );
432+ kset_unregister (& f2fs_kset );
320433 remove_proc_entry ("fs/f2fs" , NULL );
434+ f2fs_proc_root = NULL ;
321435}
322436
323437int f2fs_register_sysfs (struct f2fs_sb_info * sbi )
324438{
325439 struct super_block * sb = sbi -> sb ;
326440 int err ;
327441
442+ sbi -> s_kobj .kset = & f2fs_kset ;
443+ init_completion (& sbi -> s_kobj_unregister );
444+ err = kobject_init_and_add (& sbi -> s_kobj , & f2fs_sb_ktype , NULL ,
445+ "%s" , sb -> s_id );
446+ if (err )
447+ return err ;
448+
328449 if (f2fs_proc_root )
329450 sbi -> s_proc = proc_mkdir (sb -> s_id , f2fs_proc_root );
330451
@@ -334,32 +455,15 @@ int f2fs_register_sysfs(struct f2fs_sb_info *sbi)
334455 proc_create_data ("segment_bits" , S_IRUGO , sbi -> s_proc ,
335456 & f2fs_seq_segment_bits_fops , sb );
336457 }
337-
338- sbi -> s_kobj .kset = f2fs_kset ;
339- init_completion (& sbi -> s_kobj_unregister );
340- err = kobject_init_and_add (& sbi -> s_kobj , & f2fs_ktype , NULL ,
341- "%s" , sb -> s_id );
342- if (err )
343- goto err_out ;
344458 return 0 ;
345- err_out :
346- if (sbi -> s_proc ) {
347- remove_proc_entry ("segment_info" , sbi -> s_proc );
348- remove_proc_entry ("segment_bits" , sbi -> s_proc );
349- remove_proc_entry (sb -> s_id , f2fs_proc_root );
350- }
351- return err ;
352459}
353460
354461void f2fs_unregister_sysfs (struct f2fs_sb_info * sbi )
355462{
356- kobject_del (& sbi -> s_kobj );
357- kobject_put (& sbi -> s_kobj );
358- wait_for_completion (& sbi -> s_kobj_unregister );
359-
360463 if (sbi -> s_proc ) {
361464 remove_proc_entry ("segment_info" , sbi -> s_proc );
362465 remove_proc_entry ("segment_bits" , sbi -> s_proc );
363466 remove_proc_entry (sbi -> sb -> s_id , f2fs_proc_root );
364467 }
468+ kobject_del (& sbi -> s_kobj );
365469}
0 commit comments