1 // SPDX-License-Identifier: GPL-2.0
3 * Simple file system for zoned block devices exposing zones as files.
5 * Copyright (C) 2022 Western Digital Corporation or its affiliates.
8 #include <linux/seq_file.h>
9 #include <linux/blkdev.h>
13 struct zonefs_sysfs_attr
{
14 struct attribute attr
;
15 ssize_t (*show
)(struct zonefs_sb_info
*sbi
, char *buf
);
18 #define ZONEFS_SYSFS_ATTR_RO(name) \
19 static struct zonefs_sysfs_attr zonefs_sysfs_attr_##name = __ATTR_RO(name)
21 #define ATTR_LIST(name) &zonefs_sysfs_attr_##name.attr
23 static ssize_t
zonefs_sysfs_attr_show(struct kobject
*kobj
,
24 struct attribute
*attr
, char *buf
)
26 struct zonefs_sb_info
*sbi
=
27 container_of(kobj
, struct zonefs_sb_info
, s_kobj
);
28 struct zonefs_sysfs_attr
*zonefs_attr
=
29 container_of(attr
, struct zonefs_sysfs_attr
, attr
);
31 if (!zonefs_attr
->show
)
34 return zonefs_attr
->show(sbi
, buf
);
37 static ssize_t
max_wro_seq_files_show(struct zonefs_sb_info
*sbi
, char *buf
)
39 return sysfs_emit(buf
, "%u\n", sbi
->s_max_wro_seq_files
);
41 ZONEFS_SYSFS_ATTR_RO(max_wro_seq_files
);
43 static ssize_t
nr_wro_seq_files_show(struct zonefs_sb_info
*sbi
, char *buf
)
45 return sysfs_emit(buf
, "%d\n", atomic_read(&sbi
->s_wro_seq_files
));
47 ZONEFS_SYSFS_ATTR_RO(nr_wro_seq_files
);
49 static ssize_t
max_active_seq_files_show(struct zonefs_sb_info
*sbi
, char *buf
)
51 return sysfs_emit(buf
, "%u\n", sbi
->s_max_active_seq_files
);
53 ZONEFS_SYSFS_ATTR_RO(max_active_seq_files
);
55 static ssize_t
nr_active_seq_files_show(struct zonefs_sb_info
*sbi
, char *buf
)
57 return sysfs_emit(buf
, "%d\n", atomic_read(&sbi
->s_active_seq_files
));
59 ZONEFS_SYSFS_ATTR_RO(nr_active_seq_files
);
61 static struct attribute
*zonefs_sysfs_attrs
[] = {
62 ATTR_LIST(max_wro_seq_files
),
63 ATTR_LIST(nr_wro_seq_files
),
64 ATTR_LIST(max_active_seq_files
),
65 ATTR_LIST(nr_active_seq_files
),
68 ATTRIBUTE_GROUPS(zonefs_sysfs
);
70 static void zonefs_sysfs_sb_release(struct kobject
*kobj
)
72 struct zonefs_sb_info
*sbi
=
73 container_of(kobj
, struct zonefs_sb_info
, s_kobj
);
75 complete(&sbi
->s_kobj_unregister
);
78 static const struct sysfs_ops zonefs_sysfs_attr_ops
= {
79 .show
= zonefs_sysfs_attr_show
,
82 static const struct kobj_type zonefs_sb_ktype
= {
83 .default_groups
= zonefs_sysfs_groups
,
84 .sysfs_ops
= &zonefs_sysfs_attr_ops
,
85 .release
= zonefs_sysfs_sb_release
,
88 static struct kobject
*zonefs_sysfs_root
;
90 int zonefs_sysfs_register(struct super_block
*sb
)
92 struct zonefs_sb_info
*sbi
= ZONEFS_SB(sb
);
95 super_set_sysfs_name_id(sb
);
96 init_completion(&sbi
->s_kobj_unregister
);
97 ret
= kobject_init_and_add(&sbi
->s_kobj
, &zonefs_sb_ktype
,
98 zonefs_sysfs_root
, "%s", sb
->s_id
);
100 kobject_put(&sbi
->s_kobj
);
101 wait_for_completion(&sbi
->s_kobj_unregister
);
105 sbi
->s_sysfs_registered
= true;
110 void zonefs_sysfs_unregister(struct super_block
*sb
)
112 struct zonefs_sb_info
*sbi
= ZONEFS_SB(sb
);
114 if (!sbi
|| !sbi
->s_sysfs_registered
)
117 kobject_del(&sbi
->s_kobj
);
118 kobject_put(&sbi
->s_kobj
);
119 wait_for_completion(&sbi
->s_kobj_unregister
);
122 int __init
zonefs_sysfs_init(void)
124 zonefs_sysfs_root
= kobject_create_and_add("zonefs", fs_kobj
);
125 if (!zonefs_sysfs_root
)
131 void zonefs_sysfs_exit(void)
133 kobject_put(zonefs_sysfs_root
);
134 zonefs_sysfs_root
= NULL
;