1ae98043fSRyusuke Konishi // SPDX-License-Identifier: GPL-2.0+
2aebe17f6SVyacheslav Dubeyko /*
394ee1d91SRyusuke Konishi * Sysfs support implementation.
4aebe17f6SVyacheslav Dubeyko *
5aebe17f6SVyacheslav Dubeyko * Copyright (C) 2005-2014 Nippon Telegraph and Telephone Corporation.
6aebe17f6SVyacheslav Dubeyko * Copyright (C) 2014 HGST, Inc., a Western Digital Company.
7aebe17f6SVyacheslav Dubeyko *
8aebe17f6SVyacheslav Dubeyko * Written by Vyacheslav Dubeyko <Vyacheslav.Dubeyko@hgst.com>
9aebe17f6SVyacheslav Dubeyko */
10aebe17f6SVyacheslav Dubeyko
11aebe17f6SVyacheslav Dubeyko #include <linux/kobject.h>
12aebe17f6SVyacheslav Dubeyko
13aebe17f6SVyacheslav Dubeyko #include "nilfs.h"
14aebe17f6SVyacheslav Dubeyko #include "mdt.h"
15aebe17f6SVyacheslav Dubeyko #include "sufile.h"
16aebe17f6SVyacheslav Dubeyko #include "cpfile.h"
17aebe17f6SVyacheslav Dubeyko #include "sysfs.h"
18aebe17f6SVyacheslav Dubeyko
19aebe17f6SVyacheslav Dubeyko /* /sys/fs/<nilfs>/ */
20aebe17f6SVyacheslav Dubeyko static struct kset *nilfs_kset;
21aebe17f6SVyacheslav Dubeyko
22caa05d49SVyacheslav Dubeyko #define NILFS_DEV_INT_GROUP_OPS(name, parent_name) \
23caa05d49SVyacheslav Dubeyko static ssize_t nilfs_##name##_attr_show(struct kobject *kobj, \
24caa05d49SVyacheslav Dubeyko struct attribute *attr, char *buf) \
25caa05d49SVyacheslav Dubeyko { \
26caa05d49SVyacheslav Dubeyko struct the_nilfs *nilfs = container_of(kobj->parent, \
27caa05d49SVyacheslav Dubeyko struct the_nilfs, \
28caa05d49SVyacheslav Dubeyko ns_##parent_name##_kobj); \
29caa05d49SVyacheslav Dubeyko struct nilfs_##name##_attr *a = container_of(attr, \
30caa05d49SVyacheslav Dubeyko struct nilfs_##name##_attr, \
31caa05d49SVyacheslav Dubeyko attr); \
32caa05d49SVyacheslav Dubeyko return a->show ? a->show(a, nilfs, buf) : 0; \
33caa05d49SVyacheslav Dubeyko } \
34caa05d49SVyacheslav Dubeyko static ssize_t nilfs_##name##_attr_store(struct kobject *kobj, \
35caa05d49SVyacheslav Dubeyko struct attribute *attr, \
36caa05d49SVyacheslav Dubeyko const char *buf, size_t len) \
37caa05d49SVyacheslav Dubeyko { \
38caa05d49SVyacheslav Dubeyko struct the_nilfs *nilfs = container_of(kobj->parent, \
39caa05d49SVyacheslav Dubeyko struct the_nilfs, \
40caa05d49SVyacheslav Dubeyko ns_##parent_name##_kobj); \
41caa05d49SVyacheslav Dubeyko struct nilfs_##name##_attr *a = container_of(attr, \
42caa05d49SVyacheslav Dubeyko struct nilfs_##name##_attr, \
43caa05d49SVyacheslav Dubeyko attr); \
44caa05d49SVyacheslav Dubeyko return a->store ? a->store(a, nilfs, buf, len) : 0; \
45caa05d49SVyacheslav Dubeyko } \
46caa05d49SVyacheslav Dubeyko static const struct sysfs_ops nilfs_##name##_attr_ops = { \
47caa05d49SVyacheslav Dubeyko .show = nilfs_##name##_attr_show, \
48caa05d49SVyacheslav Dubeyko .store = nilfs_##name##_attr_store, \
49facb9ec5SRyusuke Konishi }
50caa05d49SVyacheslav Dubeyko
51caa05d49SVyacheslav Dubeyko #define NILFS_DEV_INT_GROUP_TYPE(name, parent_name) \
52caa05d49SVyacheslav Dubeyko static void nilfs_##name##_attr_release(struct kobject *kobj) \
53caa05d49SVyacheslav Dubeyko { \
54dbc6e7d4SNanyong Sun struct nilfs_sysfs_##parent_name##_subgroups *subgroups = container_of(kobj, \
55dbc6e7d4SNanyong Sun struct nilfs_sysfs_##parent_name##_subgroups, \
56dbc6e7d4SNanyong Sun sg_##name##_kobj); \
57caa05d49SVyacheslav Dubeyko complete(&subgroups->sg_##name##_kobj_unregister); \
58caa05d49SVyacheslav Dubeyko } \
59caa05d49SVyacheslav Dubeyko static struct kobj_type nilfs_##name##_ktype = { \
60a6b9a614SGreg Kroah-Hartman .default_groups = nilfs_##name##_groups, \
61caa05d49SVyacheslav Dubeyko .sysfs_ops = &nilfs_##name##_attr_ops, \
62caa05d49SVyacheslav Dubeyko .release = nilfs_##name##_attr_release, \
63facb9ec5SRyusuke Konishi }
64caa05d49SVyacheslav Dubeyko
65caa05d49SVyacheslav Dubeyko #define NILFS_DEV_INT_GROUP_FNS(name, parent_name) \
66dd70edbdSVyacheslav Dubeyko static int nilfs_sysfs_create_##name##_group(struct the_nilfs *nilfs) \
67caa05d49SVyacheslav Dubeyko { \
68caa05d49SVyacheslav Dubeyko struct kobject *parent; \
69caa05d49SVyacheslav Dubeyko struct kobject *kobj; \
70caa05d49SVyacheslav Dubeyko struct completion *kobj_unregister; \
71caa05d49SVyacheslav Dubeyko struct nilfs_sysfs_##parent_name##_subgroups *subgroups; \
72caa05d49SVyacheslav Dubeyko int err; \
73caa05d49SVyacheslav Dubeyko subgroups = nilfs->ns_##parent_name##_subgroups; \
74caa05d49SVyacheslav Dubeyko kobj = &subgroups->sg_##name##_kobj; \
75caa05d49SVyacheslav Dubeyko kobj_unregister = &subgroups->sg_##name##_kobj_unregister; \
76caa05d49SVyacheslav Dubeyko parent = &nilfs->ns_##parent_name##_kobj; \
77caa05d49SVyacheslav Dubeyko kobj->kset = nilfs_kset; \
78caa05d49SVyacheslav Dubeyko init_completion(kobj_unregister); \
79caa05d49SVyacheslav Dubeyko err = kobject_init_and_add(kobj, &nilfs_##name##_ktype, parent, \
80caa05d49SVyacheslav Dubeyko #name); \
81caa05d49SVyacheslav Dubeyko if (err) \
8224f8cb1eSNanyong Sun kobject_put(kobj); \
83caa05d49SVyacheslav Dubeyko return err; \
84caa05d49SVyacheslav Dubeyko } \
85dd70edbdSVyacheslav Dubeyko static void nilfs_sysfs_delete_##name##_group(struct the_nilfs *nilfs) \
86caa05d49SVyacheslav Dubeyko { \
87a3e18125SNanyong Sun kobject_put(&nilfs->ns_##parent_name##_subgroups->sg_##name##_kobj); \
88caa05d49SVyacheslav Dubeyko }
89caa05d49SVyacheslav Dubeyko
90caa05d49SVyacheslav Dubeyko /************************************************************************
91a5a7332aSVyacheslav Dubeyko * NILFS snapshot attrs *
92a5a7332aSVyacheslav Dubeyko ************************************************************************/
93a5a7332aSVyacheslav Dubeyko
94a5a7332aSVyacheslav Dubeyko static ssize_t
nilfs_snapshot_inodes_count_show(struct nilfs_snapshot_attr * attr,struct nilfs_root * root,char * buf)95a5a7332aSVyacheslav Dubeyko nilfs_snapshot_inodes_count_show(struct nilfs_snapshot_attr *attr,
96a5a7332aSVyacheslav Dubeyko struct nilfs_root *root, char *buf)
97a5a7332aSVyacheslav Dubeyko {
983bcd6c5bSQing Wang return sysfs_emit(buf, "%llu\n",
99a5a7332aSVyacheslav Dubeyko (unsigned long long)atomic64_read(&root->inodes_count));
100a5a7332aSVyacheslav Dubeyko }
101a5a7332aSVyacheslav Dubeyko
102a5a7332aSVyacheslav Dubeyko static ssize_t
nilfs_snapshot_blocks_count_show(struct nilfs_snapshot_attr * attr,struct nilfs_root * root,char * buf)103a5a7332aSVyacheslav Dubeyko nilfs_snapshot_blocks_count_show(struct nilfs_snapshot_attr *attr,
104a5a7332aSVyacheslav Dubeyko struct nilfs_root *root, char *buf)
105a5a7332aSVyacheslav Dubeyko {
1063bcd6c5bSQing Wang return sysfs_emit(buf, "%llu\n",
107a5a7332aSVyacheslav Dubeyko (unsigned long long)atomic64_read(&root->blocks_count));
108a5a7332aSVyacheslav Dubeyko }
109a5a7332aSVyacheslav Dubeyko
110a5a7332aSVyacheslav Dubeyko static const char snapshot_readme_str[] =
111a5a7332aSVyacheslav Dubeyko "The group contains details about mounted snapshot.\n\n"
112a5a7332aSVyacheslav Dubeyko "(1) inodes_count\n\tshow number of inodes for snapshot.\n\n"
113a5a7332aSVyacheslav Dubeyko "(2) blocks_count\n\tshow number of blocks for snapshot.\n\n";
114a5a7332aSVyacheslav Dubeyko
115a5a7332aSVyacheslav Dubeyko static ssize_t
nilfs_snapshot_README_show(struct nilfs_snapshot_attr * attr,struct nilfs_root * root,char * buf)116a5a7332aSVyacheslav Dubeyko nilfs_snapshot_README_show(struct nilfs_snapshot_attr *attr,
117a5a7332aSVyacheslav Dubeyko struct nilfs_root *root, char *buf)
118a5a7332aSVyacheslav Dubeyko {
1193bcd6c5bSQing Wang return sysfs_emit(buf, snapshot_readme_str);
120a5a7332aSVyacheslav Dubeyko }
121a5a7332aSVyacheslav Dubeyko
122a5a7332aSVyacheslav Dubeyko NILFS_SNAPSHOT_RO_ATTR(inodes_count);
123a5a7332aSVyacheslav Dubeyko NILFS_SNAPSHOT_RO_ATTR(blocks_count);
124a5a7332aSVyacheslav Dubeyko NILFS_SNAPSHOT_RO_ATTR(README);
125a5a7332aSVyacheslav Dubeyko
126a5a7332aSVyacheslav Dubeyko static struct attribute *nilfs_snapshot_attrs[] = {
127a5a7332aSVyacheslav Dubeyko NILFS_SNAPSHOT_ATTR_LIST(inodes_count),
128a5a7332aSVyacheslav Dubeyko NILFS_SNAPSHOT_ATTR_LIST(blocks_count),
129a5a7332aSVyacheslav Dubeyko NILFS_SNAPSHOT_ATTR_LIST(README),
130a5a7332aSVyacheslav Dubeyko NULL,
131a5a7332aSVyacheslav Dubeyko };
132a6b9a614SGreg Kroah-Hartman ATTRIBUTE_GROUPS(nilfs_snapshot);
133a5a7332aSVyacheslav Dubeyko
nilfs_snapshot_attr_show(struct kobject * kobj,struct attribute * attr,char * buf)134a5a7332aSVyacheslav Dubeyko static ssize_t nilfs_snapshot_attr_show(struct kobject *kobj,
135a5a7332aSVyacheslav Dubeyko struct attribute *attr, char *buf)
136a5a7332aSVyacheslav Dubeyko {
137a5a7332aSVyacheslav Dubeyko struct nilfs_root *root =
138a5a7332aSVyacheslav Dubeyko container_of(kobj, struct nilfs_root, snapshot_kobj);
139a5a7332aSVyacheslav Dubeyko struct nilfs_snapshot_attr *a =
140a5a7332aSVyacheslav Dubeyko container_of(attr, struct nilfs_snapshot_attr, attr);
141a5a7332aSVyacheslav Dubeyko
142a5a7332aSVyacheslav Dubeyko return a->show ? a->show(a, root, buf) : 0;
143a5a7332aSVyacheslav Dubeyko }
144a5a7332aSVyacheslav Dubeyko
nilfs_snapshot_attr_store(struct kobject * kobj,struct attribute * attr,const char * buf,size_t len)145a5a7332aSVyacheslav Dubeyko static ssize_t nilfs_snapshot_attr_store(struct kobject *kobj,
146a5a7332aSVyacheslav Dubeyko struct attribute *attr,
147a5a7332aSVyacheslav Dubeyko const char *buf, size_t len)
148a5a7332aSVyacheslav Dubeyko {
149a5a7332aSVyacheslav Dubeyko struct nilfs_root *root =
150a5a7332aSVyacheslav Dubeyko container_of(kobj, struct nilfs_root, snapshot_kobj);
151a5a7332aSVyacheslav Dubeyko struct nilfs_snapshot_attr *a =
152a5a7332aSVyacheslav Dubeyko container_of(attr, struct nilfs_snapshot_attr, attr);
153a5a7332aSVyacheslav Dubeyko
154a5a7332aSVyacheslav Dubeyko return a->store ? a->store(a, root, buf, len) : 0;
155a5a7332aSVyacheslav Dubeyko }
156a5a7332aSVyacheslav Dubeyko
nilfs_snapshot_attr_release(struct kobject * kobj)157a5a7332aSVyacheslav Dubeyko static void nilfs_snapshot_attr_release(struct kobject *kobj)
158a5a7332aSVyacheslav Dubeyko {
159a5a7332aSVyacheslav Dubeyko struct nilfs_root *root = container_of(kobj, struct nilfs_root,
160a5a7332aSVyacheslav Dubeyko snapshot_kobj);
161a5a7332aSVyacheslav Dubeyko complete(&root->snapshot_kobj_unregister);
162a5a7332aSVyacheslav Dubeyko }
163a5a7332aSVyacheslav Dubeyko
164a5a7332aSVyacheslav Dubeyko static const struct sysfs_ops nilfs_snapshot_attr_ops = {
165a5a7332aSVyacheslav Dubeyko .show = nilfs_snapshot_attr_show,
166a5a7332aSVyacheslav Dubeyko .store = nilfs_snapshot_attr_store,
167a5a7332aSVyacheslav Dubeyko };
168a5a7332aSVyacheslav Dubeyko
169a5a7332aSVyacheslav Dubeyko static struct kobj_type nilfs_snapshot_ktype = {
170a6b9a614SGreg Kroah-Hartman .default_groups = nilfs_snapshot_groups,
171a5a7332aSVyacheslav Dubeyko .sysfs_ops = &nilfs_snapshot_attr_ops,
172a5a7332aSVyacheslav Dubeyko .release = nilfs_snapshot_attr_release,
173a5a7332aSVyacheslav Dubeyko };
174a5a7332aSVyacheslav Dubeyko
nilfs_sysfs_create_snapshot_group(struct nilfs_root * root)175a5a7332aSVyacheslav Dubeyko int nilfs_sysfs_create_snapshot_group(struct nilfs_root *root)
176a5a7332aSVyacheslav Dubeyko {
177a5a7332aSVyacheslav Dubeyko struct the_nilfs *nilfs;
178a5a7332aSVyacheslav Dubeyko struct kobject *parent;
179a5a7332aSVyacheslav Dubeyko int err;
180a5a7332aSVyacheslav Dubeyko
181a5a7332aSVyacheslav Dubeyko nilfs = root->nilfs;
182a5a7332aSVyacheslav Dubeyko parent = &nilfs->ns_dev_subgroups->sg_mounted_snapshots_kobj;
183a5a7332aSVyacheslav Dubeyko root->snapshot_kobj.kset = nilfs_kset;
184a5a7332aSVyacheslav Dubeyko init_completion(&root->snapshot_kobj_unregister);
185a5a7332aSVyacheslav Dubeyko
186a5a7332aSVyacheslav Dubeyko if (root->cno == NILFS_CPTREE_CURRENT_CNO) {
187a5a7332aSVyacheslav Dubeyko err = kobject_init_and_add(&root->snapshot_kobj,
188a5a7332aSVyacheslav Dubeyko &nilfs_snapshot_ktype,
189a5a7332aSVyacheslav Dubeyko &nilfs->ns_dev_kobj,
190a5a7332aSVyacheslav Dubeyko "current_checkpoint");
191a5a7332aSVyacheslav Dubeyko } else {
192a5a7332aSVyacheslav Dubeyko err = kobject_init_and_add(&root->snapshot_kobj,
193a5a7332aSVyacheslav Dubeyko &nilfs_snapshot_ktype,
194a5a7332aSVyacheslav Dubeyko parent,
195a5a7332aSVyacheslav Dubeyko "%llu", root->cno);
196a5a7332aSVyacheslav Dubeyko }
197a5a7332aSVyacheslav Dubeyko
198a5a7332aSVyacheslav Dubeyko if (err)
199b2fe39c2SNanyong Sun kobject_put(&root->snapshot_kobj);
200a5a7332aSVyacheslav Dubeyko
201b2fe39c2SNanyong Sun return err;
202a5a7332aSVyacheslav Dubeyko }
203a5a7332aSVyacheslav Dubeyko
nilfs_sysfs_delete_snapshot_group(struct nilfs_root * root)204a5a7332aSVyacheslav Dubeyko void nilfs_sysfs_delete_snapshot_group(struct nilfs_root *root)
205a5a7332aSVyacheslav Dubeyko {
20617243e1cSNanyong Sun kobject_put(&root->snapshot_kobj);
207a5a7332aSVyacheslav Dubeyko }
208a5a7332aSVyacheslav Dubeyko
209a5a7332aSVyacheslav Dubeyko /************************************************************************
210a2ecb791SVyacheslav Dubeyko * NILFS mounted snapshots attrs *
211a2ecb791SVyacheslav Dubeyko ************************************************************************/
212a2ecb791SVyacheslav Dubeyko
213a2ecb791SVyacheslav Dubeyko static const char mounted_snapshots_readme_str[] =
214a2ecb791SVyacheslav Dubeyko "The mounted_snapshots group contains group for\n"
215a2ecb791SVyacheslav Dubeyko "every mounted snapshot.\n";
216a2ecb791SVyacheslav Dubeyko
217a2ecb791SVyacheslav Dubeyko static ssize_t
nilfs_mounted_snapshots_README_show(struct nilfs_mounted_snapshots_attr * attr,struct the_nilfs * nilfs,char * buf)218a2ecb791SVyacheslav Dubeyko nilfs_mounted_snapshots_README_show(struct nilfs_mounted_snapshots_attr *attr,
219a2ecb791SVyacheslav Dubeyko struct the_nilfs *nilfs, char *buf)
220a2ecb791SVyacheslav Dubeyko {
2213bcd6c5bSQing Wang return sysfs_emit(buf, mounted_snapshots_readme_str);
222a2ecb791SVyacheslav Dubeyko }
223a2ecb791SVyacheslav Dubeyko
224a2ecb791SVyacheslav Dubeyko NILFS_MOUNTED_SNAPSHOTS_RO_ATTR(README);
225a2ecb791SVyacheslav Dubeyko
226a2ecb791SVyacheslav Dubeyko static struct attribute *nilfs_mounted_snapshots_attrs[] = {
227a2ecb791SVyacheslav Dubeyko NILFS_MOUNTED_SNAPSHOTS_ATTR_LIST(README),
228a2ecb791SVyacheslav Dubeyko NULL,
229a2ecb791SVyacheslav Dubeyko };
230a6b9a614SGreg Kroah-Hartman ATTRIBUTE_GROUPS(nilfs_mounted_snapshots);
231a2ecb791SVyacheslav Dubeyko
232a2ecb791SVyacheslav Dubeyko NILFS_DEV_INT_GROUP_OPS(mounted_snapshots, dev);
233a2ecb791SVyacheslav Dubeyko NILFS_DEV_INT_GROUP_TYPE(mounted_snapshots, dev);
234a2ecb791SVyacheslav Dubeyko NILFS_DEV_INT_GROUP_FNS(mounted_snapshots, dev);
235a2ecb791SVyacheslav Dubeyko
236a2ecb791SVyacheslav Dubeyko /************************************************************************
23702a0ba1cSVyacheslav Dubeyko * NILFS checkpoints attrs *
23802a0ba1cSVyacheslav Dubeyko ************************************************************************/
23902a0ba1cSVyacheslav Dubeyko
24002a0ba1cSVyacheslav Dubeyko static ssize_t
nilfs_checkpoints_checkpoints_number_show(struct nilfs_checkpoints_attr * attr,struct the_nilfs * nilfs,char * buf)24102a0ba1cSVyacheslav Dubeyko nilfs_checkpoints_checkpoints_number_show(struct nilfs_checkpoints_attr *attr,
24202a0ba1cSVyacheslav Dubeyko struct the_nilfs *nilfs,
24302a0ba1cSVyacheslav Dubeyko char *buf)
24402a0ba1cSVyacheslav Dubeyko {
24502a0ba1cSVyacheslav Dubeyko __u64 ncheckpoints;
24602a0ba1cSVyacheslav Dubeyko struct nilfs_cpstat cpstat;
24702a0ba1cSVyacheslav Dubeyko int err;
24802a0ba1cSVyacheslav Dubeyko
24902a0ba1cSVyacheslav Dubeyko down_read(&nilfs->ns_segctor_sem);
25002a0ba1cSVyacheslav Dubeyko err = nilfs_cpfile_get_stat(nilfs->ns_cpfile, &cpstat);
25102a0ba1cSVyacheslav Dubeyko up_read(&nilfs->ns_segctor_sem);
25202a0ba1cSVyacheslav Dubeyko if (err < 0) {
253a1d0747aSJoe Perches nilfs_err(nilfs->ns_sb, "unable to get checkpoint stat: err=%d",
254a1d0747aSJoe Perches err);
25502a0ba1cSVyacheslav Dubeyko return err;
25602a0ba1cSVyacheslav Dubeyko }
25702a0ba1cSVyacheslav Dubeyko
25802a0ba1cSVyacheslav Dubeyko ncheckpoints = cpstat.cs_ncps;
25902a0ba1cSVyacheslav Dubeyko
2603bcd6c5bSQing Wang return sysfs_emit(buf, "%llu\n", ncheckpoints);
26102a0ba1cSVyacheslav Dubeyko }
26202a0ba1cSVyacheslav Dubeyko
26302a0ba1cSVyacheslav Dubeyko static ssize_t
nilfs_checkpoints_snapshots_number_show(struct nilfs_checkpoints_attr * attr,struct the_nilfs * nilfs,char * buf)26402a0ba1cSVyacheslav Dubeyko nilfs_checkpoints_snapshots_number_show(struct nilfs_checkpoints_attr *attr,
26502a0ba1cSVyacheslav Dubeyko struct the_nilfs *nilfs,
26602a0ba1cSVyacheslav Dubeyko char *buf)
26702a0ba1cSVyacheslav Dubeyko {
26802a0ba1cSVyacheslav Dubeyko __u64 nsnapshots;
26902a0ba1cSVyacheslav Dubeyko struct nilfs_cpstat cpstat;
27002a0ba1cSVyacheslav Dubeyko int err;
27102a0ba1cSVyacheslav Dubeyko
27202a0ba1cSVyacheslav Dubeyko down_read(&nilfs->ns_segctor_sem);
27302a0ba1cSVyacheslav Dubeyko err = nilfs_cpfile_get_stat(nilfs->ns_cpfile, &cpstat);
27402a0ba1cSVyacheslav Dubeyko up_read(&nilfs->ns_segctor_sem);
27502a0ba1cSVyacheslav Dubeyko if (err < 0) {
276a1d0747aSJoe Perches nilfs_err(nilfs->ns_sb, "unable to get checkpoint stat: err=%d",
277a1d0747aSJoe Perches err);
27802a0ba1cSVyacheslav Dubeyko return err;
27902a0ba1cSVyacheslav Dubeyko }
28002a0ba1cSVyacheslav Dubeyko
28102a0ba1cSVyacheslav Dubeyko nsnapshots = cpstat.cs_nsss;
28202a0ba1cSVyacheslav Dubeyko
2833bcd6c5bSQing Wang return sysfs_emit(buf, "%llu\n", nsnapshots);
28402a0ba1cSVyacheslav Dubeyko }
28502a0ba1cSVyacheslav Dubeyko
28602a0ba1cSVyacheslav Dubeyko static ssize_t
nilfs_checkpoints_last_seg_checkpoint_show(struct nilfs_checkpoints_attr * attr,struct the_nilfs * nilfs,char * buf)28702a0ba1cSVyacheslav Dubeyko nilfs_checkpoints_last_seg_checkpoint_show(struct nilfs_checkpoints_attr *attr,
28802a0ba1cSVyacheslav Dubeyko struct the_nilfs *nilfs,
28902a0ba1cSVyacheslav Dubeyko char *buf)
29002a0ba1cSVyacheslav Dubeyko {
29102a0ba1cSVyacheslav Dubeyko __u64 last_cno;
29202a0ba1cSVyacheslav Dubeyko
29302a0ba1cSVyacheslav Dubeyko spin_lock(&nilfs->ns_last_segment_lock);
29402a0ba1cSVyacheslav Dubeyko last_cno = nilfs->ns_last_cno;
29502a0ba1cSVyacheslav Dubeyko spin_unlock(&nilfs->ns_last_segment_lock);
29602a0ba1cSVyacheslav Dubeyko
2973bcd6c5bSQing Wang return sysfs_emit(buf, "%llu\n", last_cno);
29802a0ba1cSVyacheslav Dubeyko }
29902a0ba1cSVyacheslav Dubeyko
30002a0ba1cSVyacheslav Dubeyko static ssize_t
nilfs_checkpoints_next_checkpoint_show(struct nilfs_checkpoints_attr * attr,struct the_nilfs * nilfs,char * buf)30102a0ba1cSVyacheslav Dubeyko nilfs_checkpoints_next_checkpoint_show(struct nilfs_checkpoints_attr *attr,
30202a0ba1cSVyacheslav Dubeyko struct the_nilfs *nilfs,
30302a0ba1cSVyacheslav Dubeyko char *buf)
30402a0ba1cSVyacheslav Dubeyko {
30502a0ba1cSVyacheslav Dubeyko __u64 cno;
30602a0ba1cSVyacheslav Dubeyko
307ad980c9aSRyusuke Konishi down_read(&nilfs->ns_segctor_sem);
30802a0ba1cSVyacheslav Dubeyko cno = nilfs->ns_cno;
309ad980c9aSRyusuke Konishi up_read(&nilfs->ns_segctor_sem);
31002a0ba1cSVyacheslav Dubeyko
3113bcd6c5bSQing Wang return sysfs_emit(buf, "%llu\n", cno);
31202a0ba1cSVyacheslav Dubeyko }
31302a0ba1cSVyacheslav Dubeyko
31402a0ba1cSVyacheslav Dubeyko static const char checkpoints_readme_str[] =
31502a0ba1cSVyacheslav Dubeyko "The checkpoints group contains attributes that describe\n"
31602a0ba1cSVyacheslav Dubeyko "details about volume's checkpoints.\n\n"
31702a0ba1cSVyacheslav Dubeyko "(1) checkpoints_number\n\tshow number of checkpoints on volume.\n\n"
31802a0ba1cSVyacheslav Dubeyko "(2) snapshots_number\n\tshow number of snapshots on volume.\n\n"
31902a0ba1cSVyacheslav Dubeyko "(3) last_seg_checkpoint\n"
32002a0ba1cSVyacheslav Dubeyko "\tshow checkpoint number of the latest segment.\n\n"
32102a0ba1cSVyacheslav Dubeyko "(4) next_checkpoint\n\tshow next checkpoint number.\n\n";
32202a0ba1cSVyacheslav Dubeyko
32302a0ba1cSVyacheslav Dubeyko static ssize_t
nilfs_checkpoints_README_show(struct nilfs_checkpoints_attr * attr,struct the_nilfs * nilfs,char * buf)32402a0ba1cSVyacheslav Dubeyko nilfs_checkpoints_README_show(struct nilfs_checkpoints_attr *attr,
32502a0ba1cSVyacheslav Dubeyko struct the_nilfs *nilfs, char *buf)
32602a0ba1cSVyacheslav Dubeyko {
3273bcd6c5bSQing Wang return sysfs_emit(buf, checkpoints_readme_str);
32802a0ba1cSVyacheslav Dubeyko }
32902a0ba1cSVyacheslav Dubeyko
33002a0ba1cSVyacheslav Dubeyko NILFS_CHECKPOINTS_RO_ATTR(checkpoints_number);
33102a0ba1cSVyacheslav Dubeyko NILFS_CHECKPOINTS_RO_ATTR(snapshots_number);
33202a0ba1cSVyacheslav Dubeyko NILFS_CHECKPOINTS_RO_ATTR(last_seg_checkpoint);
33302a0ba1cSVyacheslav Dubeyko NILFS_CHECKPOINTS_RO_ATTR(next_checkpoint);
33402a0ba1cSVyacheslav Dubeyko NILFS_CHECKPOINTS_RO_ATTR(README);
33502a0ba1cSVyacheslav Dubeyko
33602a0ba1cSVyacheslav Dubeyko static struct attribute *nilfs_checkpoints_attrs[] = {
33702a0ba1cSVyacheslav Dubeyko NILFS_CHECKPOINTS_ATTR_LIST(checkpoints_number),
33802a0ba1cSVyacheslav Dubeyko NILFS_CHECKPOINTS_ATTR_LIST(snapshots_number),
33902a0ba1cSVyacheslav Dubeyko NILFS_CHECKPOINTS_ATTR_LIST(last_seg_checkpoint),
34002a0ba1cSVyacheslav Dubeyko NILFS_CHECKPOINTS_ATTR_LIST(next_checkpoint),
34102a0ba1cSVyacheslav Dubeyko NILFS_CHECKPOINTS_ATTR_LIST(README),
34202a0ba1cSVyacheslav Dubeyko NULL,
34302a0ba1cSVyacheslav Dubeyko };
344a6b9a614SGreg Kroah-Hartman ATTRIBUTE_GROUPS(nilfs_checkpoints);
34502a0ba1cSVyacheslav Dubeyko
34602a0ba1cSVyacheslav Dubeyko NILFS_DEV_INT_GROUP_OPS(checkpoints, dev);
34702a0ba1cSVyacheslav Dubeyko NILFS_DEV_INT_GROUP_TYPE(checkpoints, dev);
34802a0ba1cSVyacheslav Dubeyko NILFS_DEV_INT_GROUP_FNS(checkpoints, dev);
34902a0ba1cSVyacheslav Dubeyko
35002a0ba1cSVyacheslav Dubeyko /************************************************************************
351ef43d5cdSVyacheslav Dubeyko * NILFS segments attrs *
352ef43d5cdSVyacheslav Dubeyko ************************************************************************/
353ef43d5cdSVyacheslav Dubeyko
354ef43d5cdSVyacheslav Dubeyko static ssize_t
nilfs_segments_segments_number_show(struct nilfs_segments_attr * attr,struct the_nilfs * nilfs,char * buf)355ef43d5cdSVyacheslav Dubeyko nilfs_segments_segments_number_show(struct nilfs_segments_attr *attr,
356ef43d5cdSVyacheslav Dubeyko struct the_nilfs *nilfs,
357ef43d5cdSVyacheslav Dubeyko char *buf)
358ef43d5cdSVyacheslav Dubeyko {
3593bcd6c5bSQing Wang return sysfs_emit(buf, "%lu\n", nilfs->ns_nsegments);
360ef43d5cdSVyacheslav Dubeyko }
361ef43d5cdSVyacheslav Dubeyko
362ef43d5cdSVyacheslav Dubeyko static ssize_t
nilfs_segments_blocks_per_segment_show(struct nilfs_segments_attr * attr,struct the_nilfs * nilfs,char * buf)363ef43d5cdSVyacheslav Dubeyko nilfs_segments_blocks_per_segment_show(struct nilfs_segments_attr *attr,
364ef43d5cdSVyacheslav Dubeyko struct the_nilfs *nilfs,
365ef43d5cdSVyacheslav Dubeyko char *buf)
366ef43d5cdSVyacheslav Dubeyko {
3673bcd6c5bSQing Wang return sysfs_emit(buf, "%lu\n", nilfs->ns_blocks_per_segment);
368ef43d5cdSVyacheslav Dubeyko }
369ef43d5cdSVyacheslav Dubeyko
370ef43d5cdSVyacheslav Dubeyko static ssize_t
nilfs_segments_clean_segments_show(struct nilfs_segments_attr * attr,struct the_nilfs * nilfs,char * buf)371ef43d5cdSVyacheslav Dubeyko nilfs_segments_clean_segments_show(struct nilfs_segments_attr *attr,
372ef43d5cdSVyacheslav Dubeyko struct the_nilfs *nilfs,
373ef43d5cdSVyacheslav Dubeyko char *buf)
374ef43d5cdSVyacheslav Dubeyko {
375ef43d5cdSVyacheslav Dubeyko unsigned long ncleansegs;
376ef43d5cdSVyacheslav Dubeyko
377ef43d5cdSVyacheslav Dubeyko down_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem);
378ef43d5cdSVyacheslav Dubeyko ncleansegs = nilfs_sufile_get_ncleansegs(nilfs->ns_sufile);
379ef43d5cdSVyacheslav Dubeyko up_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem);
380ef43d5cdSVyacheslav Dubeyko
3813bcd6c5bSQing Wang return sysfs_emit(buf, "%lu\n", ncleansegs);
382ef43d5cdSVyacheslav Dubeyko }
383ef43d5cdSVyacheslav Dubeyko
384ef43d5cdSVyacheslav Dubeyko static ssize_t
nilfs_segments_dirty_segments_show(struct nilfs_segments_attr * attr,struct the_nilfs * nilfs,char * buf)385ef43d5cdSVyacheslav Dubeyko nilfs_segments_dirty_segments_show(struct nilfs_segments_attr *attr,
386ef43d5cdSVyacheslav Dubeyko struct the_nilfs *nilfs,
387ef43d5cdSVyacheslav Dubeyko char *buf)
388ef43d5cdSVyacheslav Dubeyko {
389ef43d5cdSVyacheslav Dubeyko struct nilfs_sustat sustat;
390ef43d5cdSVyacheslav Dubeyko int err;
391ef43d5cdSVyacheslav Dubeyko
392ef43d5cdSVyacheslav Dubeyko down_read(&nilfs->ns_segctor_sem);
393ef43d5cdSVyacheslav Dubeyko err = nilfs_sufile_get_stat(nilfs->ns_sufile, &sustat);
394ef43d5cdSVyacheslav Dubeyko up_read(&nilfs->ns_segctor_sem);
395ef43d5cdSVyacheslav Dubeyko if (err < 0) {
396a1d0747aSJoe Perches nilfs_err(nilfs->ns_sb, "unable to get segment stat: err=%d",
397a1d0747aSJoe Perches err);
398ef43d5cdSVyacheslav Dubeyko return err;
399ef43d5cdSVyacheslav Dubeyko }
400ef43d5cdSVyacheslav Dubeyko
4013bcd6c5bSQing Wang return sysfs_emit(buf, "%llu\n", sustat.ss_ndirtysegs);
402ef43d5cdSVyacheslav Dubeyko }
403ef43d5cdSVyacheslav Dubeyko
404ef43d5cdSVyacheslav Dubeyko static const char segments_readme_str[] =
405ef43d5cdSVyacheslav Dubeyko "The segments group contains attributes that describe\n"
406ef43d5cdSVyacheslav Dubeyko "details about volume's segments.\n\n"
407ef43d5cdSVyacheslav Dubeyko "(1) segments_number\n\tshow number of segments on volume.\n\n"
408ef43d5cdSVyacheslav Dubeyko "(2) blocks_per_segment\n\tshow number of blocks in segment.\n\n"
409ef43d5cdSVyacheslav Dubeyko "(3) clean_segments\n\tshow count of clean segments.\n\n"
410ef43d5cdSVyacheslav Dubeyko "(4) dirty_segments\n\tshow count of dirty segments.\n\n";
411ef43d5cdSVyacheslav Dubeyko
412ef43d5cdSVyacheslav Dubeyko static ssize_t
nilfs_segments_README_show(struct nilfs_segments_attr * attr,struct the_nilfs * nilfs,char * buf)413ef43d5cdSVyacheslav Dubeyko nilfs_segments_README_show(struct nilfs_segments_attr *attr,
414ef43d5cdSVyacheslav Dubeyko struct the_nilfs *nilfs,
415ef43d5cdSVyacheslav Dubeyko char *buf)
416ef43d5cdSVyacheslav Dubeyko {
4173bcd6c5bSQing Wang return sysfs_emit(buf, segments_readme_str);
418ef43d5cdSVyacheslav Dubeyko }
419ef43d5cdSVyacheslav Dubeyko
420ef43d5cdSVyacheslav Dubeyko NILFS_SEGMENTS_RO_ATTR(segments_number);
421ef43d5cdSVyacheslav Dubeyko NILFS_SEGMENTS_RO_ATTR(blocks_per_segment);
422ef43d5cdSVyacheslav Dubeyko NILFS_SEGMENTS_RO_ATTR(clean_segments);
423ef43d5cdSVyacheslav Dubeyko NILFS_SEGMENTS_RO_ATTR(dirty_segments);
424ef43d5cdSVyacheslav Dubeyko NILFS_SEGMENTS_RO_ATTR(README);
425ef43d5cdSVyacheslav Dubeyko
426ef43d5cdSVyacheslav Dubeyko static struct attribute *nilfs_segments_attrs[] = {
427ef43d5cdSVyacheslav Dubeyko NILFS_SEGMENTS_ATTR_LIST(segments_number),
428ef43d5cdSVyacheslav Dubeyko NILFS_SEGMENTS_ATTR_LIST(blocks_per_segment),
429ef43d5cdSVyacheslav Dubeyko NILFS_SEGMENTS_ATTR_LIST(clean_segments),
430ef43d5cdSVyacheslav Dubeyko NILFS_SEGMENTS_ATTR_LIST(dirty_segments),
431ef43d5cdSVyacheslav Dubeyko NILFS_SEGMENTS_ATTR_LIST(README),
432ef43d5cdSVyacheslav Dubeyko NULL,
433ef43d5cdSVyacheslav Dubeyko };
434a6b9a614SGreg Kroah-Hartman ATTRIBUTE_GROUPS(nilfs_segments);
435ef43d5cdSVyacheslav Dubeyko
436ef43d5cdSVyacheslav Dubeyko NILFS_DEV_INT_GROUP_OPS(segments, dev);
437ef43d5cdSVyacheslav Dubeyko NILFS_DEV_INT_GROUP_TYPE(segments, dev);
438ef43d5cdSVyacheslav Dubeyko NILFS_DEV_INT_GROUP_FNS(segments, dev);
439ef43d5cdSVyacheslav Dubeyko
440ef43d5cdSVyacheslav Dubeyko /************************************************************************
441abc968dbSVyacheslav Dubeyko * NILFS segctor attrs *
442abc968dbSVyacheslav Dubeyko ************************************************************************/
443abc968dbSVyacheslav Dubeyko
444abc968dbSVyacheslav Dubeyko static ssize_t
nilfs_segctor_last_pseg_block_show(struct nilfs_segctor_attr * attr,struct the_nilfs * nilfs,char * buf)445abc968dbSVyacheslav Dubeyko nilfs_segctor_last_pseg_block_show(struct nilfs_segctor_attr *attr,
446abc968dbSVyacheslav Dubeyko struct the_nilfs *nilfs,
447abc968dbSVyacheslav Dubeyko char *buf)
448abc968dbSVyacheslav Dubeyko {
449abc968dbSVyacheslav Dubeyko sector_t last_pseg;
450abc968dbSVyacheslav Dubeyko
451abc968dbSVyacheslav Dubeyko spin_lock(&nilfs->ns_last_segment_lock);
452abc968dbSVyacheslav Dubeyko last_pseg = nilfs->ns_last_pseg;
453abc968dbSVyacheslav Dubeyko spin_unlock(&nilfs->ns_last_segment_lock);
454abc968dbSVyacheslav Dubeyko
4553bcd6c5bSQing Wang return sysfs_emit(buf, "%llu\n",
456abc968dbSVyacheslav Dubeyko (unsigned long long)last_pseg);
457abc968dbSVyacheslav Dubeyko }
458abc968dbSVyacheslav Dubeyko
459abc968dbSVyacheslav Dubeyko static ssize_t
nilfs_segctor_last_seg_sequence_show(struct nilfs_segctor_attr * attr,struct the_nilfs * nilfs,char * buf)460abc968dbSVyacheslav Dubeyko nilfs_segctor_last_seg_sequence_show(struct nilfs_segctor_attr *attr,
461abc968dbSVyacheslav Dubeyko struct the_nilfs *nilfs,
462abc968dbSVyacheslav Dubeyko char *buf)
463abc968dbSVyacheslav Dubeyko {
464abc968dbSVyacheslav Dubeyko u64 last_seq;
465abc968dbSVyacheslav Dubeyko
466abc968dbSVyacheslav Dubeyko spin_lock(&nilfs->ns_last_segment_lock);
467abc968dbSVyacheslav Dubeyko last_seq = nilfs->ns_last_seq;
468abc968dbSVyacheslav Dubeyko spin_unlock(&nilfs->ns_last_segment_lock);
469abc968dbSVyacheslav Dubeyko
4703bcd6c5bSQing Wang return sysfs_emit(buf, "%llu\n", last_seq);
471abc968dbSVyacheslav Dubeyko }
472abc968dbSVyacheslav Dubeyko
473abc968dbSVyacheslav Dubeyko static ssize_t
nilfs_segctor_last_seg_checkpoint_show(struct nilfs_segctor_attr * attr,struct the_nilfs * nilfs,char * buf)474abc968dbSVyacheslav Dubeyko nilfs_segctor_last_seg_checkpoint_show(struct nilfs_segctor_attr *attr,
475abc968dbSVyacheslav Dubeyko struct the_nilfs *nilfs,
476abc968dbSVyacheslav Dubeyko char *buf)
477abc968dbSVyacheslav Dubeyko {
478abc968dbSVyacheslav Dubeyko __u64 last_cno;
479abc968dbSVyacheslav Dubeyko
480abc968dbSVyacheslav Dubeyko spin_lock(&nilfs->ns_last_segment_lock);
481abc968dbSVyacheslav Dubeyko last_cno = nilfs->ns_last_cno;
482abc968dbSVyacheslav Dubeyko spin_unlock(&nilfs->ns_last_segment_lock);
483abc968dbSVyacheslav Dubeyko
4843bcd6c5bSQing Wang return sysfs_emit(buf, "%llu\n", last_cno);
485abc968dbSVyacheslav Dubeyko }
486abc968dbSVyacheslav Dubeyko
487abc968dbSVyacheslav Dubeyko static ssize_t
nilfs_segctor_current_seg_sequence_show(struct nilfs_segctor_attr * attr,struct the_nilfs * nilfs,char * buf)488abc968dbSVyacheslav Dubeyko nilfs_segctor_current_seg_sequence_show(struct nilfs_segctor_attr *attr,
489abc968dbSVyacheslav Dubeyko struct the_nilfs *nilfs,
490abc968dbSVyacheslav Dubeyko char *buf)
491abc968dbSVyacheslav Dubeyko {
492abc968dbSVyacheslav Dubeyko u64 seg_seq;
493abc968dbSVyacheslav Dubeyko
494ad980c9aSRyusuke Konishi down_read(&nilfs->ns_segctor_sem);
495abc968dbSVyacheslav Dubeyko seg_seq = nilfs->ns_seg_seq;
496ad980c9aSRyusuke Konishi up_read(&nilfs->ns_segctor_sem);
497abc968dbSVyacheslav Dubeyko
4983bcd6c5bSQing Wang return sysfs_emit(buf, "%llu\n", seg_seq);
499abc968dbSVyacheslav Dubeyko }
500abc968dbSVyacheslav Dubeyko
501abc968dbSVyacheslav Dubeyko static ssize_t
nilfs_segctor_current_last_full_seg_show(struct nilfs_segctor_attr * attr,struct the_nilfs * nilfs,char * buf)502abc968dbSVyacheslav Dubeyko nilfs_segctor_current_last_full_seg_show(struct nilfs_segctor_attr *attr,
503abc968dbSVyacheslav Dubeyko struct the_nilfs *nilfs,
504abc968dbSVyacheslav Dubeyko char *buf)
505abc968dbSVyacheslav Dubeyko {
506abc968dbSVyacheslav Dubeyko __u64 segnum;
507abc968dbSVyacheslav Dubeyko
508ad980c9aSRyusuke Konishi down_read(&nilfs->ns_segctor_sem);
509abc968dbSVyacheslav Dubeyko segnum = nilfs->ns_segnum;
510ad980c9aSRyusuke Konishi up_read(&nilfs->ns_segctor_sem);
511abc968dbSVyacheslav Dubeyko
5123bcd6c5bSQing Wang return sysfs_emit(buf, "%llu\n", segnum);
513abc968dbSVyacheslav Dubeyko }
514abc968dbSVyacheslav Dubeyko
515abc968dbSVyacheslav Dubeyko static ssize_t
nilfs_segctor_next_full_seg_show(struct nilfs_segctor_attr * attr,struct the_nilfs * nilfs,char * buf)516abc968dbSVyacheslav Dubeyko nilfs_segctor_next_full_seg_show(struct nilfs_segctor_attr *attr,
517abc968dbSVyacheslav Dubeyko struct the_nilfs *nilfs,
518abc968dbSVyacheslav Dubeyko char *buf)
519abc968dbSVyacheslav Dubeyko {
520abc968dbSVyacheslav Dubeyko __u64 nextnum;
521abc968dbSVyacheslav Dubeyko
522ad980c9aSRyusuke Konishi down_read(&nilfs->ns_segctor_sem);
523abc968dbSVyacheslav Dubeyko nextnum = nilfs->ns_nextnum;
524ad980c9aSRyusuke Konishi up_read(&nilfs->ns_segctor_sem);
525abc968dbSVyacheslav Dubeyko
5263bcd6c5bSQing Wang return sysfs_emit(buf, "%llu\n", nextnum);
527abc968dbSVyacheslav Dubeyko }
528abc968dbSVyacheslav Dubeyko
529abc968dbSVyacheslav Dubeyko static ssize_t
nilfs_segctor_next_pseg_offset_show(struct nilfs_segctor_attr * attr,struct the_nilfs * nilfs,char * buf)530abc968dbSVyacheslav Dubeyko nilfs_segctor_next_pseg_offset_show(struct nilfs_segctor_attr *attr,
531abc968dbSVyacheslav Dubeyko struct the_nilfs *nilfs,
532abc968dbSVyacheslav Dubeyko char *buf)
533abc968dbSVyacheslav Dubeyko {
534abc968dbSVyacheslav Dubeyko unsigned long pseg_offset;
535abc968dbSVyacheslav Dubeyko
536ad980c9aSRyusuke Konishi down_read(&nilfs->ns_segctor_sem);
537abc968dbSVyacheslav Dubeyko pseg_offset = nilfs->ns_pseg_offset;
538ad980c9aSRyusuke Konishi up_read(&nilfs->ns_segctor_sem);
539abc968dbSVyacheslav Dubeyko
5403bcd6c5bSQing Wang return sysfs_emit(buf, "%lu\n", pseg_offset);
541abc968dbSVyacheslav Dubeyko }
542abc968dbSVyacheslav Dubeyko
543abc968dbSVyacheslav Dubeyko static ssize_t
nilfs_segctor_next_checkpoint_show(struct nilfs_segctor_attr * attr,struct the_nilfs * nilfs,char * buf)544abc968dbSVyacheslav Dubeyko nilfs_segctor_next_checkpoint_show(struct nilfs_segctor_attr *attr,
545abc968dbSVyacheslav Dubeyko struct the_nilfs *nilfs,
546abc968dbSVyacheslav Dubeyko char *buf)
547abc968dbSVyacheslav Dubeyko {
548abc968dbSVyacheslav Dubeyko __u64 cno;
549abc968dbSVyacheslav Dubeyko
550ad980c9aSRyusuke Konishi down_read(&nilfs->ns_segctor_sem);
551abc968dbSVyacheslav Dubeyko cno = nilfs->ns_cno;
552ad980c9aSRyusuke Konishi up_read(&nilfs->ns_segctor_sem);
553abc968dbSVyacheslav Dubeyko
5543bcd6c5bSQing Wang return sysfs_emit(buf, "%llu\n", cno);
555abc968dbSVyacheslav Dubeyko }
556abc968dbSVyacheslav Dubeyko
557abc968dbSVyacheslav Dubeyko static ssize_t
nilfs_segctor_last_seg_write_time_show(struct nilfs_segctor_attr * attr,struct the_nilfs * nilfs,char * buf)558abc968dbSVyacheslav Dubeyko nilfs_segctor_last_seg_write_time_show(struct nilfs_segctor_attr *attr,
559abc968dbSVyacheslav Dubeyko struct the_nilfs *nilfs,
560abc968dbSVyacheslav Dubeyko char *buf)
561abc968dbSVyacheslav Dubeyko {
562fb04b91bSArnd Bergmann time64_t ctime;
563abc968dbSVyacheslav Dubeyko
564ad980c9aSRyusuke Konishi down_read(&nilfs->ns_segctor_sem);
565abc968dbSVyacheslav Dubeyko ctime = nilfs->ns_ctime;
566ad980c9aSRyusuke Konishi up_read(&nilfs->ns_segctor_sem);
567abc968dbSVyacheslav Dubeyko
568776797f1SAndy Shevchenko return sysfs_emit(buf, "%ptTs\n", &ctime);
569abc968dbSVyacheslav Dubeyko }
570abc968dbSVyacheslav Dubeyko
571abc968dbSVyacheslav Dubeyko static ssize_t
nilfs_segctor_last_seg_write_time_secs_show(struct nilfs_segctor_attr * attr,struct the_nilfs * nilfs,char * buf)572abc968dbSVyacheslav Dubeyko nilfs_segctor_last_seg_write_time_secs_show(struct nilfs_segctor_attr *attr,
573abc968dbSVyacheslav Dubeyko struct the_nilfs *nilfs,
574abc968dbSVyacheslav Dubeyko char *buf)
575abc968dbSVyacheslav Dubeyko {
576fb04b91bSArnd Bergmann time64_t ctime;
577abc968dbSVyacheslav Dubeyko
578ad980c9aSRyusuke Konishi down_read(&nilfs->ns_segctor_sem);
579abc968dbSVyacheslav Dubeyko ctime = nilfs->ns_ctime;
580ad980c9aSRyusuke Konishi up_read(&nilfs->ns_segctor_sem);
581abc968dbSVyacheslav Dubeyko
5823bcd6c5bSQing Wang return sysfs_emit(buf, "%llu\n", ctime);
583abc968dbSVyacheslav Dubeyko }
584abc968dbSVyacheslav Dubeyko
585abc968dbSVyacheslav Dubeyko static ssize_t
nilfs_segctor_last_nongc_write_time_show(struct nilfs_segctor_attr * attr,struct the_nilfs * nilfs,char * buf)586abc968dbSVyacheslav Dubeyko nilfs_segctor_last_nongc_write_time_show(struct nilfs_segctor_attr *attr,
587abc968dbSVyacheslav Dubeyko struct the_nilfs *nilfs,
588abc968dbSVyacheslav Dubeyko char *buf)
589abc968dbSVyacheslav Dubeyko {
590fb04b91bSArnd Bergmann time64_t nongc_ctime;
591abc968dbSVyacheslav Dubeyko
592ad980c9aSRyusuke Konishi down_read(&nilfs->ns_segctor_sem);
593abc968dbSVyacheslav Dubeyko nongc_ctime = nilfs->ns_nongc_ctime;
594ad980c9aSRyusuke Konishi up_read(&nilfs->ns_segctor_sem);
595abc968dbSVyacheslav Dubeyko
596776797f1SAndy Shevchenko return sysfs_emit(buf, "%ptTs\n", &nongc_ctime);
597abc968dbSVyacheslav Dubeyko }
598abc968dbSVyacheslav Dubeyko
599abc968dbSVyacheslav Dubeyko static ssize_t
nilfs_segctor_last_nongc_write_time_secs_show(struct nilfs_segctor_attr * attr,struct the_nilfs * nilfs,char * buf)600abc968dbSVyacheslav Dubeyko nilfs_segctor_last_nongc_write_time_secs_show(struct nilfs_segctor_attr *attr,
601abc968dbSVyacheslav Dubeyko struct the_nilfs *nilfs,
602abc968dbSVyacheslav Dubeyko char *buf)
603abc968dbSVyacheslav Dubeyko {
604fb04b91bSArnd Bergmann time64_t nongc_ctime;
605abc968dbSVyacheslav Dubeyko
606ad980c9aSRyusuke Konishi down_read(&nilfs->ns_segctor_sem);
607abc968dbSVyacheslav Dubeyko nongc_ctime = nilfs->ns_nongc_ctime;
608ad980c9aSRyusuke Konishi up_read(&nilfs->ns_segctor_sem);
609abc968dbSVyacheslav Dubeyko
6103bcd6c5bSQing Wang return sysfs_emit(buf, "%llu\n", nongc_ctime);
611abc968dbSVyacheslav Dubeyko }
612abc968dbSVyacheslav Dubeyko
613abc968dbSVyacheslav Dubeyko static ssize_t
nilfs_segctor_dirty_data_blocks_count_show(struct nilfs_segctor_attr * attr,struct the_nilfs * nilfs,char * buf)614abc968dbSVyacheslav Dubeyko nilfs_segctor_dirty_data_blocks_count_show(struct nilfs_segctor_attr *attr,
615abc968dbSVyacheslav Dubeyko struct the_nilfs *nilfs,
616abc968dbSVyacheslav Dubeyko char *buf)
617abc968dbSVyacheslav Dubeyko {
618abc968dbSVyacheslav Dubeyko u32 ndirtyblks;
619abc968dbSVyacheslav Dubeyko
620ad980c9aSRyusuke Konishi down_read(&nilfs->ns_segctor_sem);
621abc968dbSVyacheslav Dubeyko ndirtyblks = atomic_read(&nilfs->ns_ndirtyblks);
622ad980c9aSRyusuke Konishi up_read(&nilfs->ns_segctor_sem);
623abc968dbSVyacheslav Dubeyko
6243bcd6c5bSQing Wang return sysfs_emit(buf, "%u\n", ndirtyblks);
625abc968dbSVyacheslav Dubeyko }
626abc968dbSVyacheslav Dubeyko
627abc968dbSVyacheslav Dubeyko static const char segctor_readme_str[] =
628abc968dbSVyacheslav Dubeyko "The segctor group contains attributes that describe\n"
629abc968dbSVyacheslav Dubeyko "segctor thread activity details.\n\n"
630abc968dbSVyacheslav Dubeyko "(1) last_pseg_block\n"
631abc968dbSVyacheslav Dubeyko "\tshow start block number of the latest segment.\n\n"
632abc968dbSVyacheslav Dubeyko "(2) last_seg_sequence\n"
633abc968dbSVyacheslav Dubeyko "\tshow sequence value of the latest segment.\n\n"
634abc968dbSVyacheslav Dubeyko "(3) last_seg_checkpoint\n"
635abc968dbSVyacheslav Dubeyko "\tshow checkpoint number of the latest segment.\n\n"
636abc968dbSVyacheslav Dubeyko "(4) current_seg_sequence\n\tshow segment sequence counter.\n\n"
637abc968dbSVyacheslav Dubeyko "(5) current_last_full_seg\n"
638abc968dbSVyacheslav Dubeyko "\tshow index number of the latest full segment.\n\n"
639abc968dbSVyacheslav Dubeyko "(6) next_full_seg\n"
640abc968dbSVyacheslav Dubeyko "\tshow index number of the full segment index to be used next.\n\n"
641abc968dbSVyacheslav Dubeyko "(7) next_pseg_offset\n"
642abc968dbSVyacheslav Dubeyko "\tshow offset of next partial segment in the current full segment.\n\n"
643abc968dbSVyacheslav Dubeyko "(8) next_checkpoint\n\tshow next checkpoint number.\n\n"
644abc968dbSVyacheslav Dubeyko "(9) last_seg_write_time\n"
645abc968dbSVyacheslav Dubeyko "\tshow write time of the last segment in human-readable format.\n\n"
646abc968dbSVyacheslav Dubeyko "(10) last_seg_write_time_secs\n"
647abc968dbSVyacheslav Dubeyko "\tshow write time of the last segment in seconds.\n\n"
648abc968dbSVyacheslav Dubeyko "(11) last_nongc_write_time\n"
649abc968dbSVyacheslav Dubeyko "\tshow write time of the last segment not for cleaner operation "
650abc968dbSVyacheslav Dubeyko "in human-readable format.\n\n"
651abc968dbSVyacheslav Dubeyko "(12) last_nongc_write_time_secs\n"
652abc968dbSVyacheslav Dubeyko "\tshow write time of the last segment not for cleaner operation "
653abc968dbSVyacheslav Dubeyko "in seconds.\n\n"
654abc968dbSVyacheslav Dubeyko "(13) dirty_data_blocks_count\n"
655abc968dbSVyacheslav Dubeyko "\tshow number of dirty data blocks.\n\n";
656abc968dbSVyacheslav Dubeyko
657abc968dbSVyacheslav Dubeyko static ssize_t
nilfs_segctor_README_show(struct nilfs_segctor_attr * attr,struct the_nilfs * nilfs,char * buf)658abc968dbSVyacheslav Dubeyko nilfs_segctor_README_show(struct nilfs_segctor_attr *attr,
659abc968dbSVyacheslav Dubeyko struct the_nilfs *nilfs, char *buf)
660abc968dbSVyacheslav Dubeyko {
6613bcd6c5bSQing Wang return sysfs_emit(buf, segctor_readme_str);
662abc968dbSVyacheslav Dubeyko }
663abc968dbSVyacheslav Dubeyko
664abc968dbSVyacheslav Dubeyko NILFS_SEGCTOR_RO_ATTR(last_pseg_block);
665abc968dbSVyacheslav Dubeyko NILFS_SEGCTOR_RO_ATTR(last_seg_sequence);
666abc968dbSVyacheslav Dubeyko NILFS_SEGCTOR_RO_ATTR(last_seg_checkpoint);
667abc968dbSVyacheslav Dubeyko NILFS_SEGCTOR_RO_ATTR(current_seg_sequence);
668abc968dbSVyacheslav Dubeyko NILFS_SEGCTOR_RO_ATTR(current_last_full_seg);
669abc968dbSVyacheslav Dubeyko NILFS_SEGCTOR_RO_ATTR(next_full_seg);
670abc968dbSVyacheslav Dubeyko NILFS_SEGCTOR_RO_ATTR(next_pseg_offset);
671abc968dbSVyacheslav Dubeyko NILFS_SEGCTOR_RO_ATTR(next_checkpoint);
672abc968dbSVyacheslav Dubeyko NILFS_SEGCTOR_RO_ATTR(last_seg_write_time);
673abc968dbSVyacheslav Dubeyko NILFS_SEGCTOR_RO_ATTR(last_seg_write_time_secs);
674abc968dbSVyacheslav Dubeyko NILFS_SEGCTOR_RO_ATTR(last_nongc_write_time);
675abc968dbSVyacheslav Dubeyko NILFS_SEGCTOR_RO_ATTR(last_nongc_write_time_secs);
676abc968dbSVyacheslav Dubeyko NILFS_SEGCTOR_RO_ATTR(dirty_data_blocks_count);
677abc968dbSVyacheslav Dubeyko NILFS_SEGCTOR_RO_ATTR(README);
678abc968dbSVyacheslav Dubeyko
679abc968dbSVyacheslav Dubeyko static struct attribute *nilfs_segctor_attrs[] = {
680abc968dbSVyacheslav Dubeyko NILFS_SEGCTOR_ATTR_LIST(last_pseg_block),
681abc968dbSVyacheslav Dubeyko NILFS_SEGCTOR_ATTR_LIST(last_seg_sequence),
682abc968dbSVyacheslav Dubeyko NILFS_SEGCTOR_ATTR_LIST(last_seg_checkpoint),
683abc968dbSVyacheslav Dubeyko NILFS_SEGCTOR_ATTR_LIST(current_seg_sequence),
684abc968dbSVyacheslav Dubeyko NILFS_SEGCTOR_ATTR_LIST(current_last_full_seg),
685abc968dbSVyacheslav Dubeyko NILFS_SEGCTOR_ATTR_LIST(next_full_seg),
686abc968dbSVyacheslav Dubeyko NILFS_SEGCTOR_ATTR_LIST(next_pseg_offset),
687abc968dbSVyacheslav Dubeyko NILFS_SEGCTOR_ATTR_LIST(next_checkpoint),
688abc968dbSVyacheslav Dubeyko NILFS_SEGCTOR_ATTR_LIST(last_seg_write_time),
689abc968dbSVyacheslav Dubeyko NILFS_SEGCTOR_ATTR_LIST(last_seg_write_time_secs),
690abc968dbSVyacheslav Dubeyko NILFS_SEGCTOR_ATTR_LIST(last_nongc_write_time),
691abc968dbSVyacheslav Dubeyko NILFS_SEGCTOR_ATTR_LIST(last_nongc_write_time_secs),
692abc968dbSVyacheslav Dubeyko NILFS_SEGCTOR_ATTR_LIST(dirty_data_blocks_count),
693abc968dbSVyacheslav Dubeyko NILFS_SEGCTOR_ATTR_LIST(README),
694abc968dbSVyacheslav Dubeyko NULL,
695abc968dbSVyacheslav Dubeyko };
696a6b9a614SGreg Kroah-Hartman ATTRIBUTE_GROUPS(nilfs_segctor);
697abc968dbSVyacheslav Dubeyko
698abc968dbSVyacheslav Dubeyko NILFS_DEV_INT_GROUP_OPS(segctor, dev);
699abc968dbSVyacheslav Dubeyko NILFS_DEV_INT_GROUP_TYPE(segctor, dev);
700abc968dbSVyacheslav Dubeyko NILFS_DEV_INT_GROUP_FNS(segctor, dev);
701abc968dbSVyacheslav Dubeyko
702abc968dbSVyacheslav Dubeyko /************************************************************************
703caa05d49SVyacheslav Dubeyko * NILFS superblock attrs *
704caa05d49SVyacheslav Dubeyko ************************************************************************/
705caa05d49SVyacheslav Dubeyko
706caa05d49SVyacheslav Dubeyko static ssize_t
nilfs_superblock_sb_write_time_show(struct nilfs_superblock_attr * attr,struct the_nilfs * nilfs,char * buf)707caa05d49SVyacheslav Dubeyko nilfs_superblock_sb_write_time_show(struct nilfs_superblock_attr *attr,
708caa05d49SVyacheslav Dubeyko struct the_nilfs *nilfs,
709caa05d49SVyacheslav Dubeyko char *buf)
710caa05d49SVyacheslav Dubeyko {
711fb04b91bSArnd Bergmann time64_t sbwtime;
712caa05d49SVyacheslav Dubeyko
713caa05d49SVyacheslav Dubeyko down_read(&nilfs->ns_sem);
714caa05d49SVyacheslav Dubeyko sbwtime = nilfs->ns_sbwtime;
715caa05d49SVyacheslav Dubeyko up_read(&nilfs->ns_sem);
716caa05d49SVyacheslav Dubeyko
717776797f1SAndy Shevchenko return sysfs_emit(buf, "%ptTs\n", &sbwtime);
718caa05d49SVyacheslav Dubeyko }
719caa05d49SVyacheslav Dubeyko
720caa05d49SVyacheslav Dubeyko static ssize_t
nilfs_superblock_sb_write_time_secs_show(struct nilfs_superblock_attr * attr,struct the_nilfs * nilfs,char * buf)721caa05d49SVyacheslav Dubeyko nilfs_superblock_sb_write_time_secs_show(struct nilfs_superblock_attr *attr,
722caa05d49SVyacheslav Dubeyko struct the_nilfs *nilfs,
723caa05d49SVyacheslav Dubeyko char *buf)
724caa05d49SVyacheslav Dubeyko {
725fb04b91bSArnd Bergmann time64_t sbwtime;
726caa05d49SVyacheslav Dubeyko
727caa05d49SVyacheslav Dubeyko down_read(&nilfs->ns_sem);
728caa05d49SVyacheslav Dubeyko sbwtime = nilfs->ns_sbwtime;
729caa05d49SVyacheslav Dubeyko up_read(&nilfs->ns_sem);
730caa05d49SVyacheslav Dubeyko
7313bcd6c5bSQing Wang return sysfs_emit(buf, "%llu\n", sbwtime);
732caa05d49SVyacheslav Dubeyko }
733caa05d49SVyacheslav Dubeyko
734caa05d49SVyacheslav Dubeyko static ssize_t
nilfs_superblock_sb_write_count_show(struct nilfs_superblock_attr * attr,struct the_nilfs * nilfs,char * buf)735caa05d49SVyacheslav Dubeyko nilfs_superblock_sb_write_count_show(struct nilfs_superblock_attr *attr,
736caa05d49SVyacheslav Dubeyko struct the_nilfs *nilfs,
737caa05d49SVyacheslav Dubeyko char *buf)
738caa05d49SVyacheslav Dubeyko {
7390c6c44cbSRyusuke Konishi unsigned int sbwcount;
740caa05d49SVyacheslav Dubeyko
741caa05d49SVyacheslav Dubeyko down_read(&nilfs->ns_sem);
742caa05d49SVyacheslav Dubeyko sbwcount = nilfs->ns_sbwcount;
743caa05d49SVyacheslav Dubeyko up_read(&nilfs->ns_sem);
744caa05d49SVyacheslav Dubeyko
7453bcd6c5bSQing Wang return sysfs_emit(buf, "%u\n", sbwcount);
746caa05d49SVyacheslav Dubeyko }
747caa05d49SVyacheslav Dubeyko
748caa05d49SVyacheslav Dubeyko static ssize_t
nilfs_superblock_sb_update_frequency_show(struct nilfs_superblock_attr * attr,struct the_nilfs * nilfs,char * buf)749caa05d49SVyacheslav Dubeyko nilfs_superblock_sb_update_frequency_show(struct nilfs_superblock_attr *attr,
750caa05d49SVyacheslav Dubeyko struct the_nilfs *nilfs,
751caa05d49SVyacheslav Dubeyko char *buf)
752caa05d49SVyacheslav Dubeyko {
7530c6c44cbSRyusuke Konishi unsigned int sb_update_freq;
754caa05d49SVyacheslav Dubeyko
755caa05d49SVyacheslav Dubeyko down_read(&nilfs->ns_sem);
756caa05d49SVyacheslav Dubeyko sb_update_freq = nilfs->ns_sb_update_freq;
757caa05d49SVyacheslav Dubeyko up_read(&nilfs->ns_sem);
758caa05d49SVyacheslav Dubeyko
7593bcd6c5bSQing Wang return sysfs_emit(buf, "%u\n", sb_update_freq);
760caa05d49SVyacheslav Dubeyko }
761caa05d49SVyacheslav Dubeyko
762caa05d49SVyacheslav Dubeyko static ssize_t
nilfs_superblock_sb_update_frequency_store(struct nilfs_superblock_attr * attr,struct the_nilfs * nilfs,const char * buf,size_t count)763caa05d49SVyacheslav Dubeyko nilfs_superblock_sb_update_frequency_store(struct nilfs_superblock_attr *attr,
764caa05d49SVyacheslav Dubeyko struct the_nilfs *nilfs,
765caa05d49SVyacheslav Dubeyko const char *buf, size_t count)
766caa05d49SVyacheslav Dubeyko {
7670c6c44cbSRyusuke Konishi unsigned int val;
768caa05d49SVyacheslav Dubeyko int err;
769caa05d49SVyacheslav Dubeyko
770caa05d49SVyacheslav Dubeyko err = kstrtouint(skip_spaces(buf), 0, &val);
771caa05d49SVyacheslav Dubeyko if (err) {
772a1d0747aSJoe Perches nilfs_err(nilfs->ns_sb, "unable to convert string: err=%d",
773a1d0747aSJoe Perches err);
774caa05d49SVyacheslav Dubeyko return err;
775caa05d49SVyacheslav Dubeyko }
776caa05d49SVyacheslav Dubeyko
777caa05d49SVyacheslav Dubeyko if (val < NILFS_SB_FREQ) {
778caa05d49SVyacheslav Dubeyko val = NILFS_SB_FREQ;
779a1d0747aSJoe Perches nilfs_warn(nilfs->ns_sb,
780feee880fSRyusuke Konishi "superblock update frequency cannot be lesser than 10 seconds");
781caa05d49SVyacheslav Dubeyko }
782caa05d49SVyacheslav Dubeyko
783caa05d49SVyacheslav Dubeyko down_write(&nilfs->ns_sem);
784caa05d49SVyacheslav Dubeyko nilfs->ns_sb_update_freq = val;
785caa05d49SVyacheslav Dubeyko up_write(&nilfs->ns_sem);
786caa05d49SVyacheslav Dubeyko
787caa05d49SVyacheslav Dubeyko return count;
788caa05d49SVyacheslav Dubeyko }
789caa05d49SVyacheslav Dubeyko
790caa05d49SVyacheslav Dubeyko static const char sb_readme_str[] =
791caa05d49SVyacheslav Dubeyko "The superblock group contains attributes that describe\n"
792caa05d49SVyacheslav Dubeyko "superblock's details.\n\n"
793caa05d49SVyacheslav Dubeyko "(1) sb_write_time\n\tshow previous write time of super block "
794caa05d49SVyacheslav Dubeyko "in human-readable format.\n\n"
795caa05d49SVyacheslav Dubeyko "(2) sb_write_time_secs\n\tshow previous write time of super block "
796caa05d49SVyacheslav Dubeyko "in seconds.\n\n"
797caa05d49SVyacheslav Dubeyko "(3) sb_write_count\n\tshow write count of super block.\n\n"
798caa05d49SVyacheslav Dubeyko "(4) sb_update_frequency\n"
799caa05d49SVyacheslav Dubeyko "\tshow/set interval of periodical update of superblock (in seconds).\n\n"
800caa05d49SVyacheslav Dubeyko "\tYou can set preferable frequency of superblock update by command:\n\n"
801caa05d49SVyacheslav Dubeyko "\t'echo <val> > /sys/fs/<nilfs>/<dev>/superblock/sb_update_frequency'\n";
802caa05d49SVyacheslav Dubeyko
803caa05d49SVyacheslav Dubeyko static ssize_t
nilfs_superblock_README_show(struct nilfs_superblock_attr * attr,struct the_nilfs * nilfs,char * buf)804caa05d49SVyacheslav Dubeyko nilfs_superblock_README_show(struct nilfs_superblock_attr *attr,
805caa05d49SVyacheslav Dubeyko struct the_nilfs *nilfs, char *buf)
806caa05d49SVyacheslav Dubeyko {
8073bcd6c5bSQing Wang return sysfs_emit(buf, sb_readme_str);
808caa05d49SVyacheslav Dubeyko }
809caa05d49SVyacheslav Dubeyko
810caa05d49SVyacheslav Dubeyko NILFS_SUPERBLOCK_RO_ATTR(sb_write_time);
811caa05d49SVyacheslav Dubeyko NILFS_SUPERBLOCK_RO_ATTR(sb_write_time_secs);
812caa05d49SVyacheslav Dubeyko NILFS_SUPERBLOCK_RO_ATTR(sb_write_count);
813caa05d49SVyacheslav Dubeyko NILFS_SUPERBLOCK_RW_ATTR(sb_update_frequency);
814caa05d49SVyacheslav Dubeyko NILFS_SUPERBLOCK_RO_ATTR(README);
815caa05d49SVyacheslav Dubeyko
816caa05d49SVyacheslav Dubeyko static struct attribute *nilfs_superblock_attrs[] = {
817caa05d49SVyacheslav Dubeyko NILFS_SUPERBLOCK_ATTR_LIST(sb_write_time),
818caa05d49SVyacheslav Dubeyko NILFS_SUPERBLOCK_ATTR_LIST(sb_write_time_secs),
819caa05d49SVyacheslav Dubeyko NILFS_SUPERBLOCK_ATTR_LIST(sb_write_count),
820caa05d49SVyacheslav Dubeyko NILFS_SUPERBLOCK_ATTR_LIST(sb_update_frequency),
821caa05d49SVyacheslav Dubeyko NILFS_SUPERBLOCK_ATTR_LIST(README),
822caa05d49SVyacheslav Dubeyko NULL,
823caa05d49SVyacheslav Dubeyko };
824a6b9a614SGreg Kroah-Hartman ATTRIBUTE_GROUPS(nilfs_superblock);
825caa05d49SVyacheslav Dubeyko
826caa05d49SVyacheslav Dubeyko NILFS_DEV_INT_GROUP_OPS(superblock, dev);
827caa05d49SVyacheslav Dubeyko NILFS_DEV_INT_GROUP_TYPE(superblock, dev);
828caa05d49SVyacheslav Dubeyko NILFS_DEV_INT_GROUP_FNS(superblock, dev);
829caa05d49SVyacheslav Dubeyko
830aebe17f6SVyacheslav Dubeyko /************************************************************************
831da7141fbSVyacheslav Dubeyko * NILFS device attrs *
832da7141fbSVyacheslav Dubeyko ************************************************************************/
833da7141fbSVyacheslav Dubeyko
834da7141fbSVyacheslav Dubeyko static
nilfs_dev_revision_show(struct nilfs_dev_attr * attr,struct the_nilfs * nilfs,char * buf)835da7141fbSVyacheslav Dubeyko ssize_t nilfs_dev_revision_show(struct nilfs_dev_attr *attr,
836da7141fbSVyacheslav Dubeyko struct the_nilfs *nilfs,
837da7141fbSVyacheslav Dubeyko char *buf)
838da7141fbSVyacheslav Dubeyko {
839*8c6e43b3SRyusuke Konishi struct nilfs_super_block *raw_sb;
840*8c6e43b3SRyusuke Konishi u32 major;
841*8c6e43b3SRyusuke Konishi u16 minor;
842*8c6e43b3SRyusuke Konishi
843*8c6e43b3SRyusuke Konishi down_read(&nilfs->ns_sem);
844*8c6e43b3SRyusuke Konishi raw_sb = nilfs->ns_sbp[0];
845*8c6e43b3SRyusuke Konishi major = le32_to_cpu(raw_sb->s_rev_level);
846*8c6e43b3SRyusuke Konishi minor = le16_to_cpu(raw_sb->s_minor_rev_level);
847*8c6e43b3SRyusuke Konishi up_read(&nilfs->ns_sem);
848da7141fbSVyacheslav Dubeyko
8493bcd6c5bSQing Wang return sysfs_emit(buf, "%d.%d\n", major, minor);
850da7141fbSVyacheslav Dubeyko }
851da7141fbSVyacheslav Dubeyko
852da7141fbSVyacheslav Dubeyko static
nilfs_dev_blocksize_show(struct nilfs_dev_attr * attr,struct the_nilfs * nilfs,char * buf)853da7141fbSVyacheslav Dubeyko ssize_t nilfs_dev_blocksize_show(struct nilfs_dev_attr *attr,
854da7141fbSVyacheslav Dubeyko struct the_nilfs *nilfs,
855da7141fbSVyacheslav Dubeyko char *buf)
856da7141fbSVyacheslav Dubeyko {
8573bcd6c5bSQing Wang return sysfs_emit(buf, "%u\n", nilfs->ns_blocksize);
858da7141fbSVyacheslav Dubeyko }
859da7141fbSVyacheslav Dubeyko
860da7141fbSVyacheslav Dubeyko static
nilfs_dev_device_size_show(struct nilfs_dev_attr * attr,struct the_nilfs * nilfs,char * buf)861da7141fbSVyacheslav Dubeyko ssize_t nilfs_dev_device_size_show(struct nilfs_dev_attr *attr,
862da7141fbSVyacheslav Dubeyko struct the_nilfs *nilfs,
863da7141fbSVyacheslav Dubeyko char *buf)
864da7141fbSVyacheslav Dubeyko {
865*8c6e43b3SRyusuke Konishi struct nilfs_super_block *raw_sb;
866*8c6e43b3SRyusuke Konishi u64 dev_size;
867*8c6e43b3SRyusuke Konishi
868*8c6e43b3SRyusuke Konishi down_read(&nilfs->ns_sem);
869*8c6e43b3SRyusuke Konishi raw_sb = nilfs->ns_sbp[0];
870*8c6e43b3SRyusuke Konishi dev_size = le64_to_cpu(raw_sb->s_dev_size);
871*8c6e43b3SRyusuke Konishi up_read(&nilfs->ns_sem);
872da7141fbSVyacheslav Dubeyko
8733bcd6c5bSQing Wang return sysfs_emit(buf, "%llu\n", dev_size);
874da7141fbSVyacheslav Dubeyko }
875da7141fbSVyacheslav Dubeyko
876da7141fbSVyacheslav Dubeyko static
nilfs_dev_free_blocks_show(struct nilfs_dev_attr * attr,struct the_nilfs * nilfs,char * buf)877da7141fbSVyacheslav Dubeyko ssize_t nilfs_dev_free_blocks_show(struct nilfs_dev_attr *attr,
878da7141fbSVyacheslav Dubeyko struct the_nilfs *nilfs,
879da7141fbSVyacheslav Dubeyko char *buf)
880da7141fbSVyacheslav Dubeyko {
881da7141fbSVyacheslav Dubeyko sector_t free_blocks = 0;
882da7141fbSVyacheslav Dubeyko
883da7141fbSVyacheslav Dubeyko nilfs_count_free_blocks(nilfs, &free_blocks);
8843bcd6c5bSQing Wang return sysfs_emit(buf, "%llu\n",
885da7141fbSVyacheslav Dubeyko (unsigned long long)free_blocks);
886da7141fbSVyacheslav Dubeyko }
887da7141fbSVyacheslav Dubeyko
888da7141fbSVyacheslav Dubeyko static
nilfs_dev_uuid_show(struct nilfs_dev_attr * attr,struct the_nilfs * nilfs,char * buf)889da7141fbSVyacheslav Dubeyko ssize_t nilfs_dev_uuid_show(struct nilfs_dev_attr *attr,
890da7141fbSVyacheslav Dubeyko struct the_nilfs *nilfs,
891da7141fbSVyacheslav Dubeyko char *buf)
892da7141fbSVyacheslav Dubeyko {
893*8c6e43b3SRyusuke Konishi struct nilfs_super_block *raw_sb;
894*8c6e43b3SRyusuke Konishi ssize_t len;
895da7141fbSVyacheslav Dubeyko
896*8c6e43b3SRyusuke Konishi down_read(&nilfs->ns_sem);
897*8c6e43b3SRyusuke Konishi raw_sb = nilfs->ns_sbp[0];
898*8c6e43b3SRyusuke Konishi len = sysfs_emit(buf, "%pUb\n", raw_sb->s_uuid);
899*8c6e43b3SRyusuke Konishi up_read(&nilfs->ns_sem);
900*8c6e43b3SRyusuke Konishi
901*8c6e43b3SRyusuke Konishi return len;
902da7141fbSVyacheslav Dubeyko }
903da7141fbSVyacheslav Dubeyko
904da7141fbSVyacheslav Dubeyko static
nilfs_dev_volume_name_show(struct nilfs_dev_attr * attr,struct the_nilfs * nilfs,char * buf)905da7141fbSVyacheslav Dubeyko ssize_t nilfs_dev_volume_name_show(struct nilfs_dev_attr *attr,
906da7141fbSVyacheslav Dubeyko struct the_nilfs *nilfs,
907da7141fbSVyacheslav Dubeyko char *buf)
908da7141fbSVyacheslav Dubeyko {
909*8c6e43b3SRyusuke Konishi struct nilfs_super_block *raw_sb;
910*8c6e43b3SRyusuke Konishi ssize_t len;
911da7141fbSVyacheslav Dubeyko
912*8c6e43b3SRyusuke Konishi down_read(&nilfs->ns_sem);
913*8c6e43b3SRyusuke Konishi raw_sb = nilfs->ns_sbp[0];
914*8c6e43b3SRyusuke Konishi len = scnprintf(buf, sizeof(raw_sb->s_volume_name), "%s\n",
915*8c6e43b3SRyusuke Konishi raw_sb->s_volume_name);
916*8c6e43b3SRyusuke Konishi up_read(&nilfs->ns_sem);
917*8c6e43b3SRyusuke Konishi
918*8c6e43b3SRyusuke Konishi return len;
919da7141fbSVyacheslav Dubeyko }
920da7141fbSVyacheslav Dubeyko
921da7141fbSVyacheslav Dubeyko static const char dev_readme_str[] =
922da7141fbSVyacheslav Dubeyko "The <device> group contains attributes that describe file system\n"
923da7141fbSVyacheslav Dubeyko "partition's details.\n\n"
924da7141fbSVyacheslav Dubeyko "(1) revision\n\tshow NILFS file system revision.\n\n"
925da7141fbSVyacheslav Dubeyko "(2) blocksize\n\tshow volume block size in bytes.\n\n"
926da7141fbSVyacheslav Dubeyko "(3) device_size\n\tshow volume size in bytes.\n\n"
927da7141fbSVyacheslav Dubeyko "(4) free_blocks\n\tshow count of free blocks on volume.\n\n"
928da7141fbSVyacheslav Dubeyko "(5) uuid\n\tshow volume's UUID.\n\n"
929da7141fbSVyacheslav Dubeyko "(6) volume_name\n\tshow volume's name.\n\n";
930da7141fbSVyacheslav Dubeyko
nilfs_dev_README_show(struct nilfs_dev_attr * attr,struct the_nilfs * nilfs,char * buf)931da7141fbSVyacheslav Dubeyko static ssize_t nilfs_dev_README_show(struct nilfs_dev_attr *attr,
932da7141fbSVyacheslav Dubeyko struct the_nilfs *nilfs,
933da7141fbSVyacheslav Dubeyko char *buf)
934da7141fbSVyacheslav Dubeyko {
9353bcd6c5bSQing Wang return sysfs_emit(buf, dev_readme_str);
936da7141fbSVyacheslav Dubeyko }
937da7141fbSVyacheslav Dubeyko
938da7141fbSVyacheslav Dubeyko NILFS_DEV_RO_ATTR(revision);
939da7141fbSVyacheslav Dubeyko NILFS_DEV_RO_ATTR(blocksize);
940da7141fbSVyacheslav Dubeyko NILFS_DEV_RO_ATTR(device_size);
941da7141fbSVyacheslav Dubeyko NILFS_DEV_RO_ATTR(free_blocks);
942da7141fbSVyacheslav Dubeyko NILFS_DEV_RO_ATTR(uuid);
943da7141fbSVyacheslav Dubeyko NILFS_DEV_RO_ATTR(volume_name);
944da7141fbSVyacheslav Dubeyko NILFS_DEV_RO_ATTR(README);
945da7141fbSVyacheslav Dubeyko
946da7141fbSVyacheslav Dubeyko static struct attribute *nilfs_dev_attrs[] = {
947da7141fbSVyacheslav Dubeyko NILFS_DEV_ATTR_LIST(revision),
948da7141fbSVyacheslav Dubeyko NILFS_DEV_ATTR_LIST(blocksize),
949da7141fbSVyacheslav Dubeyko NILFS_DEV_ATTR_LIST(device_size),
950da7141fbSVyacheslav Dubeyko NILFS_DEV_ATTR_LIST(free_blocks),
951da7141fbSVyacheslav Dubeyko NILFS_DEV_ATTR_LIST(uuid),
952da7141fbSVyacheslav Dubeyko NILFS_DEV_ATTR_LIST(volume_name),
953da7141fbSVyacheslav Dubeyko NILFS_DEV_ATTR_LIST(README),
954da7141fbSVyacheslav Dubeyko NULL,
955da7141fbSVyacheslav Dubeyko };
956a6b9a614SGreg Kroah-Hartman ATTRIBUTE_GROUPS(nilfs_dev);
957da7141fbSVyacheslav Dubeyko
nilfs_dev_attr_show(struct kobject * kobj,struct attribute * attr,char * buf)958da7141fbSVyacheslav Dubeyko static ssize_t nilfs_dev_attr_show(struct kobject *kobj,
959da7141fbSVyacheslav Dubeyko struct attribute *attr, char *buf)
960da7141fbSVyacheslav Dubeyko {
961da7141fbSVyacheslav Dubeyko struct the_nilfs *nilfs = container_of(kobj, struct the_nilfs,
962da7141fbSVyacheslav Dubeyko ns_dev_kobj);
963da7141fbSVyacheslav Dubeyko struct nilfs_dev_attr *a = container_of(attr, struct nilfs_dev_attr,
964da7141fbSVyacheslav Dubeyko attr);
965da7141fbSVyacheslav Dubeyko
966da7141fbSVyacheslav Dubeyko return a->show ? a->show(a, nilfs, buf) : 0;
967da7141fbSVyacheslav Dubeyko }
968da7141fbSVyacheslav Dubeyko
nilfs_dev_attr_store(struct kobject * kobj,struct attribute * attr,const char * buf,size_t len)969da7141fbSVyacheslav Dubeyko static ssize_t nilfs_dev_attr_store(struct kobject *kobj,
970da7141fbSVyacheslav Dubeyko struct attribute *attr,
971da7141fbSVyacheslav Dubeyko const char *buf, size_t len)
972da7141fbSVyacheslav Dubeyko {
973da7141fbSVyacheslav Dubeyko struct the_nilfs *nilfs = container_of(kobj, struct the_nilfs,
974da7141fbSVyacheslav Dubeyko ns_dev_kobj);
975da7141fbSVyacheslav Dubeyko struct nilfs_dev_attr *a = container_of(attr, struct nilfs_dev_attr,
976da7141fbSVyacheslav Dubeyko attr);
977da7141fbSVyacheslav Dubeyko
978da7141fbSVyacheslav Dubeyko return a->store ? a->store(a, nilfs, buf, len) : 0;
979da7141fbSVyacheslav Dubeyko }
980da7141fbSVyacheslav Dubeyko
nilfs_dev_attr_release(struct kobject * kobj)981da7141fbSVyacheslav Dubeyko static void nilfs_dev_attr_release(struct kobject *kobj)
982da7141fbSVyacheslav Dubeyko {
983da7141fbSVyacheslav Dubeyko struct the_nilfs *nilfs = container_of(kobj, struct the_nilfs,
984da7141fbSVyacheslav Dubeyko ns_dev_kobj);
985da7141fbSVyacheslav Dubeyko complete(&nilfs->ns_dev_kobj_unregister);
986da7141fbSVyacheslav Dubeyko }
987da7141fbSVyacheslav Dubeyko
988da7141fbSVyacheslav Dubeyko static const struct sysfs_ops nilfs_dev_attr_ops = {
989da7141fbSVyacheslav Dubeyko .show = nilfs_dev_attr_show,
990da7141fbSVyacheslav Dubeyko .store = nilfs_dev_attr_store,
991da7141fbSVyacheslav Dubeyko };
992da7141fbSVyacheslav Dubeyko
993da7141fbSVyacheslav Dubeyko static struct kobj_type nilfs_dev_ktype = {
994a6b9a614SGreg Kroah-Hartman .default_groups = nilfs_dev_groups,
995da7141fbSVyacheslav Dubeyko .sysfs_ops = &nilfs_dev_attr_ops,
996da7141fbSVyacheslav Dubeyko .release = nilfs_dev_attr_release,
997da7141fbSVyacheslav Dubeyko };
998da7141fbSVyacheslav Dubeyko
nilfs_sysfs_create_device_group(struct super_block * sb)999da7141fbSVyacheslav Dubeyko int nilfs_sysfs_create_device_group(struct super_block *sb)
1000da7141fbSVyacheslav Dubeyko {
1001da7141fbSVyacheslav Dubeyko struct the_nilfs *nilfs = sb->s_fs_info;
1002caa05d49SVyacheslav Dubeyko size_t devgrp_size = sizeof(struct nilfs_sysfs_dev_subgroups);
1003da7141fbSVyacheslav Dubeyko int err;
1004da7141fbSVyacheslav Dubeyko
1005caa05d49SVyacheslav Dubeyko nilfs->ns_dev_subgroups = kzalloc(devgrp_size, GFP_KERNEL);
1006caa05d49SVyacheslav Dubeyko if (unlikely(!nilfs->ns_dev_subgroups)) {
1007caa05d49SVyacheslav Dubeyko err = -ENOMEM;
1008a1d0747aSJoe Perches nilfs_err(sb, "unable to allocate memory for device group");
1009caa05d49SVyacheslav Dubeyko goto failed_create_device_group;
1010caa05d49SVyacheslav Dubeyko }
1011caa05d49SVyacheslav Dubeyko
1012da7141fbSVyacheslav Dubeyko nilfs->ns_dev_kobj.kset = nilfs_kset;
1013da7141fbSVyacheslav Dubeyko init_completion(&nilfs->ns_dev_kobj_unregister);
1014da7141fbSVyacheslav Dubeyko err = kobject_init_and_add(&nilfs->ns_dev_kobj, &nilfs_dev_ktype, NULL,
1015da7141fbSVyacheslav Dubeyko "%s", sb->s_id);
1016da7141fbSVyacheslav Dubeyko if (err)
10175f5dec07SNanyong Sun goto cleanup_dev_kobject;
1018caa05d49SVyacheslav Dubeyko
1019a2ecb791SVyacheslav Dubeyko err = nilfs_sysfs_create_mounted_snapshots_group(nilfs);
1020caa05d49SVyacheslav Dubeyko if (err)
1021caa05d49SVyacheslav Dubeyko goto cleanup_dev_kobject;
1022da7141fbSVyacheslav Dubeyko
1023a2ecb791SVyacheslav Dubeyko err = nilfs_sysfs_create_checkpoints_group(nilfs);
1024a2ecb791SVyacheslav Dubeyko if (err)
1025a2ecb791SVyacheslav Dubeyko goto delete_mounted_snapshots_group;
1026a2ecb791SVyacheslav Dubeyko
102702a0ba1cSVyacheslav Dubeyko err = nilfs_sysfs_create_segments_group(nilfs);
102802a0ba1cSVyacheslav Dubeyko if (err)
102902a0ba1cSVyacheslav Dubeyko goto delete_checkpoints_group;
103002a0ba1cSVyacheslav Dubeyko
1031ef43d5cdSVyacheslav Dubeyko err = nilfs_sysfs_create_superblock_group(nilfs);
1032ef43d5cdSVyacheslav Dubeyko if (err)
1033ef43d5cdSVyacheslav Dubeyko goto delete_segments_group;
1034ef43d5cdSVyacheslav Dubeyko
1035abc968dbSVyacheslav Dubeyko err = nilfs_sysfs_create_segctor_group(nilfs);
1036abc968dbSVyacheslav Dubeyko if (err)
1037abc968dbSVyacheslav Dubeyko goto delete_superblock_group;
1038abc968dbSVyacheslav Dubeyko
1039da7141fbSVyacheslav Dubeyko return 0;
1040da7141fbSVyacheslav Dubeyko
1041abc968dbSVyacheslav Dubeyko delete_superblock_group:
1042abc968dbSVyacheslav Dubeyko nilfs_sysfs_delete_superblock_group(nilfs);
1043abc968dbSVyacheslav Dubeyko
1044ef43d5cdSVyacheslav Dubeyko delete_segments_group:
1045ef43d5cdSVyacheslav Dubeyko nilfs_sysfs_delete_segments_group(nilfs);
1046ef43d5cdSVyacheslav Dubeyko
104702a0ba1cSVyacheslav Dubeyko delete_checkpoints_group:
104802a0ba1cSVyacheslav Dubeyko nilfs_sysfs_delete_checkpoints_group(nilfs);
104902a0ba1cSVyacheslav Dubeyko
1050a2ecb791SVyacheslav Dubeyko delete_mounted_snapshots_group:
1051a2ecb791SVyacheslav Dubeyko nilfs_sysfs_delete_mounted_snapshots_group(nilfs);
1052a2ecb791SVyacheslav Dubeyko
1053caa05d49SVyacheslav Dubeyko cleanup_dev_kobject:
10545f5dec07SNanyong Sun kobject_put(&nilfs->ns_dev_kobj);
1055caa05d49SVyacheslav Dubeyko kfree(nilfs->ns_dev_subgroups);
1056caa05d49SVyacheslav Dubeyko
1057da7141fbSVyacheslav Dubeyko failed_create_device_group:
1058da7141fbSVyacheslav Dubeyko return err;
1059da7141fbSVyacheslav Dubeyko }
1060da7141fbSVyacheslav Dubeyko
nilfs_sysfs_delete_device_group(struct the_nilfs * nilfs)1061da7141fbSVyacheslav Dubeyko void nilfs_sysfs_delete_device_group(struct the_nilfs *nilfs)
1062da7141fbSVyacheslav Dubeyko {
1063a2ecb791SVyacheslav Dubeyko nilfs_sysfs_delete_mounted_snapshots_group(nilfs);
106402a0ba1cSVyacheslav Dubeyko nilfs_sysfs_delete_checkpoints_group(nilfs);
1065ef43d5cdSVyacheslav Dubeyko nilfs_sysfs_delete_segments_group(nilfs);
1066caa05d49SVyacheslav Dubeyko nilfs_sysfs_delete_superblock_group(nilfs);
1067abc968dbSVyacheslav Dubeyko nilfs_sysfs_delete_segctor_group(nilfs);
1068da7141fbSVyacheslav Dubeyko kobject_del(&nilfs->ns_dev_kobj);
10698fd0c1b0SPavel Skripkin kobject_put(&nilfs->ns_dev_kobj);
1070caa05d49SVyacheslav Dubeyko kfree(nilfs->ns_dev_subgroups);
1071da7141fbSVyacheslav Dubeyko }
1072da7141fbSVyacheslav Dubeyko
1073da7141fbSVyacheslav Dubeyko /************************************************************************
1074aebe17f6SVyacheslav Dubeyko * NILFS feature attrs *
1075aebe17f6SVyacheslav Dubeyko ************************************************************************/
1076aebe17f6SVyacheslav Dubeyko
nilfs_feature_revision_show(struct kobject * kobj,struct attribute * attr,char * buf)1077aebe17f6SVyacheslav Dubeyko static ssize_t nilfs_feature_revision_show(struct kobject *kobj,
1078aebe17f6SVyacheslav Dubeyko struct attribute *attr, char *buf)
1079aebe17f6SVyacheslav Dubeyko {
10803bcd6c5bSQing Wang return sysfs_emit(buf, "%d.%d\n",
1081aebe17f6SVyacheslav Dubeyko NILFS_CURRENT_REV, NILFS_MINOR_REV);
1082aebe17f6SVyacheslav Dubeyko }
1083aebe17f6SVyacheslav Dubeyko
1084aebe17f6SVyacheslav Dubeyko static const char features_readme_str[] =
1085aebe17f6SVyacheslav Dubeyko "The features group contains attributes that describe NILFS file\n"
1086aebe17f6SVyacheslav Dubeyko "system driver features.\n\n"
1087aebe17f6SVyacheslav Dubeyko "(1) revision\n\tshow current revision of NILFS file system driver.\n";
1088aebe17f6SVyacheslav Dubeyko
nilfs_feature_README_show(struct kobject * kobj,struct attribute * attr,char * buf)1089aebe17f6SVyacheslav Dubeyko static ssize_t nilfs_feature_README_show(struct kobject *kobj,
1090aebe17f6SVyacheslav Dubeyko struct attribute *attr,
1091aebe17f6SVyacheslav Dubeyko char *buf)
1092aebe17f6SVyacheslav Dubeyko {
10933bcd6c5bSQing Wang return sysfs_emit(buf, features_readme_str);
1094aebe17f6SVyacheslav Dubeyko }
1095aebe17f6SVyacheslav Dubeyko
1096aebe17f6SVyacheslav Dubeyko NILFS_FEATURE_RO_ATTR(revision);
1097aebe17f6SVyacheslav Dubeyko NILFS_FEATURE_RO_ATTR(README);
1098aebe17f6SVyacheslav Dubeyko
1099aebe17f6SVyacheslav Dubeyko static struct attribute *nilfs_feature_attrs[] = {
1100aebe17f6SVyacheslav Dubeyko NILFS_FEATURE_ATTR_LIST(revision),
1101aebe17f6SVyacheslav Dubeyko NILFS_FEATURE_ATTR_LIST(README),
1102aebe17f6SVyacheslav Dubeyko NULL,
1103aebe17f6SVyacheslav Dubeyko };
1104aebe17f6SVyacheslav Dubeyko
1105aebe17f6SVyacheslav Dubeyko static const struct attribute_group nilfs_feature_attr_group = {
1106aebe17f6SVyacheslav Dubeyko .name = "features",
1107aebe17f6SVyacheslav Dubeyko .attrs = nilfs_feature_attrs,
1108aebe17f6SVyacheslav Dubeyko };
1109aebe17f6SVyacheslav Dubeyko
nilfs_sysfs_init(void)1110aebe17f6SVyacheslav Dubeyko int __init nilfs_sysfs_init(void)
1111aebe17f6SVyacheslav Dubeyko {
1112aebe17f6SVyacheslav Dubeyko int err;
1113aebe17f6SVyacheslav Dubeyko
1114aebe17f6SVyacheslav Dubeyko nilfs_kset = kset_create_and_add(NILFS_ROOT_GROUP_NAME, NULL, fs_kobj);
1115aebe17f6SVyacheslav Dubeyko if (!nilfs_kset) {
1116aebe17f6SVyacheslav Dubeyko err = -ENOMEM;
1117a1d0747aSJoe Perches nilfs_err(NULL, "unable to create sysfs entry: err=%d", err);
1118aebe17f6SVyacheslav Dubeyko goto failed_sysfs_init;
1119aebe17f6SVyacheslav Dubeyko }
1120aebe17f6SVyacheslav Dubeyko
1121aebe17f6SVyacheslav Dubeyko err = sysfs_create_group(&nilfs_kset->kobj, &nilfs_feature_attr_group);
1122aebe17f6SVyacheslav Dubeyko if (unlikely(err)) {
1123a1d0747aSJoe Perches nilfs_err(NULL, "unable to create feature group: err=%d", err);
1124aebe17f6SVyacheslav Dubeyko goto cleanup_sysfs_init;
1125aebe17f6SVyacheslav Dubeyko }
1126aebe17f6SVyacheslav Dubeyko
1127aebe17f6SVyacheslav Dubeyko return 0;
1128aebe17f6SVyacheslav Dubeyko
1129aebe17f6SVyacheslav Dubeyko cleanup_sysfs_init:
1130aebe17f6SVyacheslav Dubeyko kset_unregister(nilfs_kset);
1131aebe17f6SVyacheslav Dubeyko
1132aebe17f6SVyacheslav Dubeyko failed_sysfs_init:
1133aebe17f6SVyacheslav Dubeyko return err;
1134aebe17f6SVyacheslav Dubeyko }
1135aebe17f6SVyacheslav Dubeyko
nilfs_sysfs_exit(void)1136aebe17f6SVyacheslav Dubeyko void nilfs_sysfs_exit(void)
1137aebe17f6SVyacheslav Dubeyko {
1138aebe17f6SVyacheslav Dubeyko sysfs_remove_group(&nilfs_kset->kobj, &nilfs_feature_attr_group);
1139aebe17f6SVyacheslav Dubeyko kset_unregister(nilfs_kset);
1140aebe17f6SVyacheslav Dubeyko }
1141