xref: /OK3568_Linux_fs/kernel/fs/nilfs2/sysfs.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * sysfs.c - sysfs support implementation.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2005-2014 Nippon Telegraph and Telephone Corporation.
6*4882a593Smuzhiyun  * Copyright (C) 2014 HGST, Inc., a Western Digital Company.
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * Written by Vyacheslav Dubeyko <Vyacheslav.Dubeyko@hgst.com>
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include <linux/kobject.h>
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #include "nilfs.h"
14*4882a593Smuzhiyun #include "mdt.h"
15*4882a593Smuzhiyun #include "sufile.h"
16*4882a593Smuzhiyun #include "cpfile.h"
17*4882a593Smuzhiyun #include "sysfs.h"
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun /* /sys/fs/<nilfs>/ */
20*4882a593Smuzhiyun static struct kset *nilfs_kset;
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #define NILFS_SHOW_TIME(time_t_val, buf) ({ \
23*4882a593Smuzhiyun 		struct tm res; \
24*4882a593Smuzhiyun 		int count = 0; \
25*4882a593Smuzhiyun 		time64_to_tm(time_t_val, 0, &res); \
26*4882a593Smuzhiyun 		res.tm_year += 1900; \
27*4882a593Smuzhiyun 		res.tm_mon += 1; \
28*4882a593Smuzhiyun 		count = scnprintf(buf, PAGE_SIZE, \
29*4882a593Smuzhiyun 				    "%ld-%.2d-%.2d %.2d:%.2d:%.2d\n", \
30*4882a593Smuzhiyun 				    res.tm_year, res.tm_mon, res.tm_mday, \
31*4882a593Smuzhiyun 				    res.tm_hour, res.tm_min, res.tm_sec);\
32*4882a593Smuzhiyun 		count; \
33*4882a593Smuzhiyun })
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun #define NILFS_DEV_INT_GROUP_OPS(name, parent_name) \
36*4882a593Smuzhiyun static ssize_t nilfs_##name##_attr_show(struct kobject *kobj, \
37*4882a593Smuzhiyun 					struct attribute *attr, char *buf) \
38*4882a593Smuzhiyun { \
39*4882a593Smuzhiyun 	struct the_nilfs *nilfs = container_of(kobj->parent, \
40*4882a593Smuzhiyun 						struct the_nilfs, \
41*4882a593Smuzhiyun 						ns_##parent_name##_kobj); \
42*4882a593Smuzhiyun 	struct nilfs_##name##_attr *a = container_of(attr, \
43*4882a593Smuzhiyun 						struct nilfs_##name##_attr, \
44*4882a593Smuzhiyun 						attr); \
45*4882a593Smuzhiyun 	return a->show ? a->show(a, nilfs, buf) : 0; \
46*4882a593Smuzhiyun } \
47*4882a593Smuzhiyun static ssize_t nilfs_##name##_attr_store(struct kobject *kobj, \
48*4882a593Smuzhiyun 					 struct attribute *attr, \
49*4882a593Smuzhiyun 					 const char *buf, size_t len) \
50*4882a593Smuzhiyun { \
51*4882a593Smuzhiyun 	struct the_nilfs *nilfs = container_of(kobj->parent, \
52*4882a593Smuzhiyun 						struct the_nilfs, \
53*4882a593Smuzhiyun 						ns_##parent_name##_kobj); \
54*4882a593Smuzhiyun 	struct nilfs_##name##_attr *a = container_of(attr, \
55*4882a593Smuzhiyun 						struct nilfs_##name##_attr, \
56*4882a593Smuzhiyun 						attr); \
57*4882a593Smuzhiyun 	return a->store ? a->store(a, nilfs, buf, len) : 0; \
58*4882a593Smuzhiyun } \
59*4882a593Smuzhiyun static const struct sysfs_ops nilfs_##name##_attr_ops = { \
60*4882a593Smuzhiyun 	.show	= nilfs_##name##_attr_show, \
61*4882a593Smuzhiyun 	.store	= nilfs_##name##_attr_store, \
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun #define NILFS_DEV_INT_GROUP_TYPE(name, parent_name) \
65*4882a593Smuzhiyun static void nilfs_##name##_attr_release(struct kobject *kobj) \
66*4882a593Smuzhiyun { \
67*4882a593Smuzhiyun 	struct nilfs_sysfs_##parent_name##_subgroups *subgroups = container_of(kobj, \
68*4882a593Smuzhiyun 						struct nilfs_sysfs_##parent_name##_subgroups, \
69*4882a593Smuzhiyun 						sg_##name##_kobj); \
70*4882a593Smuzhiyun 	complete(&subgroups->sg_##name##_kobj_unregister); \
71*4882a593Smuzhiyun } \
72*4882a593Smuzhiyun static struct kobj_type nilfs_##name##_ktype = { \
73*4882a593Smuzhiyun 	.default_attrs	= nilfs_##name##_attrs, \
74*4882a593Smuzhiyun 	.sysfs_ops	= &nilfs_##name##_attr_ops, \
75*4882a593Smuzhiyun 	.release	= nilfs_##name##_attr_release, \
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun #define NILFS_DEV_INT_GROUP_FNS(name, parent_name) \
79*4882a593Smuzhiyun static int nilfs_sysfs_create_##name##_group(struct the_nilfs *nilfs) \
80*4882a593Smuzhiyun { \
81*4882a593Smuzhiyun 	struct kobject *parent; \
82*4882a593Smuzhiyun 	struct kobject *kobj; \
83*4882a593Smuzhiyun 	struct completion *kobj_unregister; \
84*4882a593Smuzhiyun 	struct nilfs_sysfs_##parent_name##_subgroups *subgroups; \
85*4882a593Smuzhiyun 	int err; \
86*4882a593Smuzhiyun 	subgroups = nilfs->ns_##parent_name##_subgroups; \
87*4882a593Smuzhiyun 	kobj = &subgroups->sg_##name##_kobj; \
88*4882a593Smuzhiyun 	kobj_unregister = &subgroups->sg_##name##_kobj_unregister; \
89*4882a593Smuzhiyun 	parent = &nilfs->ns_##parent_name##_kobj; \
90*4882a593Smuzhiyun 	kobj->kset = nilfs_kset; \
91*4882a593Smuzhiyun 	init_completion(kobj_unregister); \
92*4882a593Smuzhiyun 	err = kobject_init_and_add(kobj, &nilfs_##name##_ktype, parent, \
93*4882a593Smuzhiyun 				    #name); \
94*4882a593Smuzhiyun 	if (err) \
95*4882a593Smuzhiyun 		kobject_put(kobj); \
96*4882a593Smuzhiyun 	return err; \
97*4882a593Smuzhiyun } \
98*4882a593Smuzhiyun static void nilfs_sysfs_delete_##name##_group(struct the_nilfs *nilfs) \
99*4882a593Smuzhiyun { \
100*4882a593Smuzhiyun 	kobject_put(&nilfs->ns_##parent_name##_subgroups->sg_##name##_kobj); \
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun /************************************************************************
104*4882a593Smuzhiyun  *                        NILFS snapshot attrs                          *
105*4882a593Smuzhiyun  ************************************************************************/
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun static ssize_t
nilfs_snapshot_inodes_count_show(struct nilfs_snapshot_attr * attr,struct nilfs_root * root,char * buf)108*4882a593Smuzhiyun nilfs_snapshot_inodes_count_show(struct nilfs_snapshot_attr *attr,
109*4882a593Smuzhiyun 				 struct nilfs_root *root, char *buf)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%llu\n",
112*4882a593Smuzhiyun 			(unsigned long long)atomic64_read(&root->inodes_count));
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun static ssize_t
nilfs_snapshot_blocks_count_show(struct nilfs_snapshot_attr * attr,struct nilfs_root * root,char * buf)116*4882a593Smuzhiyun nilfs_snapshot_blocks_count_show(struct nilfs_snapshot_attr *attr,
117*4882a593Smuzhiyun 				 struct nilfs_root *root, char *buf)
118*4882a593Smuzhiyun {
119*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%llu\n",
120*4882a593Smuzhiyun 			(unsigned long long)atomic64_read(&root->blocks_count));
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun static const char snapshot_readme_str[] =
124*4882a593Smuzhiyun 	"The group contains details about mounted snapshot.\n\n"
125*4882a593Smuzhiyun 	"(1) inodes_count\n\tshow number of inodes for snapshot.\n\n"
126*4882a593Smuzhiyun 	"(2) blocks_count\n\tshow number of blocks for snapshot.\n\n";
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun static ssize_t
nilfs_snapshot_README_show(struct nilfs_snapshot_attr * attr,struct nilfs_root * root,char * buf)129*4882a593Smuzhiyun nilfs_snapshot_README_show(struct nilfs_snapshot_attr *attr,
130*4882a593Smuzhiyun 			    struct nilfs_root *root, char *buf)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, snapshot_readme_str);
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun NILFS_SNAPSHOT_RO_ATTR(inodes_count);
136*4882a593Smuzhiyun NILFS_SNAPSHOT_RO_ATTR(blocks_count);
137*4882a593Smuzhiyun NILFS_SNAPSHOT_RO_ATTR(README);
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun static struct attribute *nilfs_snapshot_attrs[] = {
140*4882a593Smuzhiyun 	NILFS_SNAPSHOT_ATTR_LIST(inodes_count),
141*4882a593Smuzhiyun 	NILFS_SNAPSHOT_ATTR_LIST(blocks_count),
142*4882a593Smuzhiyun 	NILFS_SNAPSHOT_ATTR_LIST(README),
143*4882a593Smuzhiyun 	NULL,
144*4882a593Smuzhiyun };
145*4882a593Smuzhiyun 
nilfs_snapshot_attr_show(struct kobject * kobj,struct attribute * attr,char * buf)146*4882a593Smuzhiyun static ssize_t nilfs_snapshot_attr_show(struct kobject *kobj,
147*4882a593Smuzhiyun 					struct attribute *attr, char *buf)
148*4882a593Smuzhiyun {
149*4882a593Smuzhiyun 	struct nilfs_root *root =
150*4882a593Smuzhiyun 			container_of(kobj, struct nilfs_root, snapshot_kobj);
151*4882a593Smuzhiyun 	struct nilfs_snapshot_attr *a =
152*4882a593Smuzhiyun 			container_of(attr, struct nilfs_snapshot_attr, attr);
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 	return a->show ? a->show(a, root, buf) : 0;
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun 
nilfs_snapshot_attr_store(struct kobject * kobj,struct attribute * attr,const char * buf,size_t len)157*4882a593Smuzhiyun static ssize_t nilfs_snapshot_attr_store(struct kobject *kobj,
158*4882a593Smuzhiyun 					 struct attribute *attr,
159*4882a593Smuzhiyun 					 const char *buf, size_t len)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun 	struct nilfs_root *root =
162*4882a593Smuzhiyun 			container_of(kobj, struct nilfs_root, snapshot_kobj);
163*4882a593Smuzhiyun 	struct nilfs_snapshot_attr *a =
164*4882a593Smuzhiyun 			container_of(attr, struct nilfs_snapshot_attr, attr);
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	return a->store ? a->store(a, root, buf, len) : 0;
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun 
nilfs_snapshot_attr_release(struct kobject * kobj)169*4882a593Smuzhiyun static void nilfs_snapshot_attr_release(struct kobject *kobj)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun 	struct nilfs_root *root = container_of(kobj, struct nilfs_root,
172*4882a593Smuzhiyun 						snapshot_kobj);
173*4882a593Smuzhiyun 	complete(&root->snapshot_kobj_unregister);
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun static const struct sysfs_ops nilfs_snapshot_attr_ops = {
177*4882a593Smuzhiyun 	.show	= nilfs_snapshot_attr_show,
178*4882a593Smuzhiyun 	.store	= nilfs_snapshot_attr_store,
179*4882a593Smuzhiyun };
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun static struct kobj_type nilfs_snapshot_ktype = {
182*4882a593Smuzhiyun 	.default_attrs	= nilfs_snapshot_attrs,
183*4882a593Smuzhiyun 	.sysfs_ops	= &nilfs_snapshot_attr_ops,
184*4882a593Smuzhiyun 	.release	= nilfs_snapshot_attr_release,
185*4882a593Smuzhiyun };
186*4882a593Smuzhiyun 
nilfs_sysfs_create_snapshot_group(struct nilfs_root * root)187*4882a593Smuzhiyun int nilfs_sysfs_create_snapshot_group(struct nilfs_root *root)
188*4882a593Smuzhiyun {
189*4882a593Smuzhiyun 	struct the_nilfs *nilfs;
190*4882a593Smuzhiyun 	struct kobject *parent;
191*4882a593Smuzhiyun 	int err;
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	nilfs = root->nilfs;
194*4882a593Smuzhiyun 	parent = &nilfs->ns_dev_subgroups->sg_mounted_snapshots_kobj;
195*4882a593Smuzhiyun 	root->snapshot_kobj.kset = nilfs_kset;
196*4882a593Smuzhiyun 	init_completion(&root->snapshot_kobj_unregister);
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 	if (root->cno == NILFS_CPTREE_CURRENT_CNO) {
199*4882a593Smuzhiyun 		err = kobject_init_and_add(&root->snapshot_kobj,
200*4882a593Smuzhiyun 					    &nilfs_snapshot_ktype,
201*4882a593Smuzhiyun 					    &nilfs->ns_dev_kobj,
202*4882a593Smuzhiyun 					    "current_checkpoint");
203*4882a593Smuzhiyun 	} else {
204*4882a593Smuzhiyun 		err = kobject_init_and_add(&root->snapshot_kobj,
205*4882a593Smuzhiyun 					    &nilfs_snapshot_ktype,
206*4882a593Smuzhiyun 					    parent,
207*4882a593Smuzhiyun 					    "%llu", root->cno);
208*4882a593Smuzhiyun 	}
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 	if (err)
211*4882a593Smuzhiyun 		kobject_put(&root->snapshot_kobj);
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 	return err;
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun 
nilfs_sysfs_delete_snapshot_group(struct nilfs_root * root)216*4882a593Smuzhiyun void nilfs_sysfs_delete_snapshot_group(struct nilfs_root *root)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun 	kobject_put(&root->snapshot_kobj);
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun /************************************************************************
222*4882a593Smuzhiyun  *                    NILFS mounted snapshots attrs                     *
223*4882a593Smuzhiyun  ************************************************************************/
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun static const char mounted_snapshots_readme_str[] =
226*4882a593Smuzhiyun 	"The mounted_snapshots group contains group for\n"
227*4882a593Smuzhiyun 	"every mounted snapshot.\n";
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun static ssize_t
nilfs_mounted_snapshots_README_show(struct nilfs_mounted_snapshots_attr * attr,struct the_nilfs * nilfs,char * buf)230*4882a593Smuzhiyun nilfs_mounted_snapshots_README_show(struct nilfs_mounted_snapshots_attr *attr,
231*4882a593Smuzhiyun 				    struct the_nilfs *nilfs, char *buf)
232*4882a593Smuzhiyun {
233*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, mounted_snapshots_readme_str);
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun NILFS_MOUNTED_SNAPSHOTS_RO_ATTR(README);
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun static struct attribute *nilfs_mounted_snapshots_attrs[] = {
239*4882a593Smuzhiyun 	NILFS_MOUNTED_SNAPSHOTS_ATTR_LIST(README),
240*4882a593Smuzhiyun 	NULL,
241*4882a593Smuzhiyun };
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun NILFS_DEV_INT_GROUP_OPS(mounted_snapshots, dev);
244*4882a593Smuzhiyun NILFS_DEV_INT_GROUP_TYPE(mounted_snapshots, dev);
245*4882a593Smuzhiyun NILFS_DEV_INT_GROUP_FNS(mounted_snapshots, dev);
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun /************************************************************************
248*4882a593Smuzhiyun  *                      NILFS checkpoints attrs                         *
249*4882a593Smuzhiyun  ************************************************************************/
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun static ssize_t
nilfs_checkpoints_checkpoints_number_show(struct nilfs_checkpoints_attr * attr,struct the_nilfs * nilfs,char * buf)252*4882a593Smuzhiyun nilfs_checkpoints_checkpoints_number_show(struct nilfs_checkpoints_attr *attr,
253*4882a593Smuzhiyun 					    struct the_nilfs *nilfs,
254*4882a593Smuzhiyun 					    char *buf)
255*4882a593Smuzhiyun {
256*4882a593Smuzhiyun 	__u64 ncheckpoints;
257*4882a593Smuzhiyun 	struct nilfs_cpstat cpstat;
258*4882a593Smuzhiyun 	int err;
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	down_read(&nilfs->ns_segctor_sem);
261*4882a593Smuzhiyun 	err = nilfs_cpfile_get_stat(nilfs->ns_cpfile, &cpstat);
262*4882a593Smuzhiyun 	up_read(&nilfs->ns_segctor_sem);
263*4882a593Smuzhiyun 	if (err < 0) {
264*4882a593Smuzhiyun 		nilfs_err(nilfs->ns_sb, "unable to get checkpoint stat: err=%d",
265*4882a593Smuzhiyun 			  err);
266*4882a593Smuzhiyun 		return err;
267*4882a593Smuzhiyun 	}
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 	ncheckpoints = cpstat.cs_ncps;
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%llu\n", ncheckpoints);
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun static ssize_t
nilfs_checkpoints_snapshots_number_show(struct nilfs_checkpoints_attr * attr,struct the_nilfs * nilfs,char * buf)275*4882a593Smuzhiyun nilfs_checkpoints_snapshots_number_show(struct nilfs_checkpoints_attr *attr,
276*4882a593Smuzhiyun 					struct the_nilfs *nilfs,
277*4882a593Smuzhiyun 					char *buf)
278*4882a593Smuzhiyun {
279*4882a593Smuzhiyun 	__u64 nsnapshots;
280*4882a593Smuzhiyun 	struct nilfs_cpstat cpstat;
281*4882a593Smuzhiyun 	int err;
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	down_read(&nilfs->ns_segctor_sem);
284*4882a593Smuzhiyun 	err = nilfs_cpfile_get_stat(nilfs->ns_cpfile, &cpstat);
285*4882a593Smuzhiyun 	up_read(&nilfs->ns_segctor_sem);
286*4882a593Smuzhiyun 	if (err < 0) {
287*4882a593Smuzhiyun 		nilfs_err(nilfs->ns_sb, "unable to get checkpoint stat: err=%d",
288*4882a593Smuzhiyun 			  err);
289*4882a593Smuzhiyun 		return err;
290*4882a593Smuzhiyun 	}
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun 	nsnapshots = cpstat.cs_nsss;
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%llu\n", nsnapshots);
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun static ssize_t
nilfs_checkpoints_last_seg_checkpoint_show(struct nilfs_checkpoints_attr * attr,struct the_nilfs * nilfs,char * buf)298*4882a593Smuzhiyun nilfs_checkpoints_last_seg_checkpoint_show(struct nilfs_checkpoints_attr *attr,
299*4882a593Smuzhiyun 					    struct the_nilfs *nilfs,
300*4882a593Smuzhiyun 					    char *buf)
301*4882a593Smuzhiyun {
302*4882a593Smuzhiyun 	__u64 last_cno;
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	spin_lock(&nilfs->ns_last_segment_lock);
305*4882a593Smuzhiyun 	last_cno = nilfs->ns_last_cno;
306*4882a593Smuzhiyun 	spin_unlock(&nilfs->ns_last_segment_lock);
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%llu\n", last_cno);
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun static ssize_t
nilfs_checkpoints_next_checkpoint_show(struct nilfs_checkpoints_attr * attr,struct the_nilfs * nilfs,char * buf)312*4882a593Smuzhiyun nilfs_checkpoints_next_checkpoint_show(struct nilfs_checkpoints_attr *attr,
313*4882a593Smuzhiyun 					struct the_nilfs *nilfs,
314*4882a593Smuzhiyun 					char *buf)
315*4882a593Smuzhiyun {
316*4882a593Smuzhiyun 	__u64 cno;
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	down_read(&nilfs->ns_segctor_sem);
319*4882a593Smuzhiyun 	cno = nilfs->ns_cno;
320*4882a593Smuzhiyun 	up_read(&nilfs->ns_segctor_sem);
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%llu\n", cno);
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun static const char checkpoints_readme_str[] =
326*4882a593Smuzhiyun 	"The checkpoints group contains attributes that describe\n"
327*4882a593Smuzhiyun 	"details about volume's checkpoints.\n\n"
328*4882a593Smuzhiyun 	"(1) checkpoints_number\n\tshow number of checkpoints on volume.\n\n"
329*4882a593Smuzhiyun 	"(2) snapshots_number\n\tshow number of snapshots on volume.\n\n"
330*4882a593Smuzhiyun 	"(3) last_seg_checkpoint\n"
331*4882a593Smuzhiyun 	"\tshow checkpoint number of the latest segment.\n\n"
332*4882a593Smuzhiyun 	"(4) next_checkpoint\n\tshow next checkpoint number.\n\n";
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun static ssize_t
nilfs_checkpoints_README_show(struct nilfs_checkpoints_attr * attr,struct the_nilfs * nilfs,char * buf)335*4882a593Smuzhiyun nilfs_checkpoints_README_show(struct nilfs_checkpoints_attr *attr,
336*4882a593Smuzhiyun 				struct the_nilfs *nilfs, char *buf)
337*4882a593Smuzhiyun {
338*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, checkpoints_readme_str);
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun NILFS_CHECKPOINTS_RO_ATTR(checkpoints_number);
342*4882a593Smuzhiyun NILFS_CHECKPOINTS_RO_ATTR(snapshots_number);
343*4882a593Smuzhiyun NILFS_CHECKPOINTS_RO_ATTR(last_seg_checkpoint);
344*4882a593Smuzhiyun NILFS_CHECKPOINTS_RO_ATTR(next_checkpoint);
345*4882a593Smuzhiyun NILFS_CHECKPOINTS_RO_ATTR(README);
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun static struct attribute *nilfs_checkpoints_attrs[] = {
348*4882a593Smuzhiyun 	NILFS_CHECKPOINTS_ATTR_LIST(checkpoints_number),
349*4882a593Smuzhiyun 	NILFS_CHECKPOINTS_ATTR_LIST(snapshots_number),
350*4882a593Smuzhiyun 	NILFS_CHECKPOINTS_ATTR_LIST(last_seg_checkpoint),
351*4882a593Smuzhiyun 	NILFS_CHECKPOINTS_ATTR_LIST(next_checkpoint),
352*4882a593Smuzhiyun 	NILFS_CHECKPOINTS_ATTR_LIST(README),
353*4882a593Smuzhiyun 	NULL,
354*4882a593Smuzhiyun };
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun NILFS_DEV_INT_GROUP_OPS(checkpoints, dev);
357*4882a593Smuzhiyun NILFS_DEV_INT_GROUP_TYPE(checkpoints, dev);
358*4882a593Smuzhiyun NILFS_DEV_INT_GROUP_FNS(checkpoints, dev);
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun /************************************************************************
361*4882a593Smuzhiyun  *                        NILFS segments attrs                          *
362*4882a593Smuzhiyun  ************************************************************************/
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun static ssize_t
nilfs_segments_segments_number_show(struct nilfs_segments_attr * attr,struct the_nilfs * nilfs,char * buf)365*4882a593Smuzhiyun nilfs_segments_segments_number_show(struct nilfs_segments_attr *attr,
366*4882a593Smuzhiyun 				     struct the_nilfs *nilfs,
367*4882a593Smuzhiyun 				     char *buf)
368*4882a593Smuzhiyun {
369*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%lu\n", nilfs->ns_nsegments);
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun static ssize_t
nilfs_segments_blocks_per_segment_show(struct nilfs_segments_attr * attr,struct the_nilfs * nilfs,char * buf)373*4882a593Smuzhiyun nilfs_segments_blocks_per_segment_show(struct nilfs_segments_attr *attr,
374*4882a593Smuzhiyun 					struct the_nilfs *nilfs,
375*4882a593Smuzhiyun 					char *buf)
376*4882a593Smuzhiyun {
377*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%lu\n", nilfs->ns_blocks_per_segment);
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun static ssize_t
nilfs_segments_clean_segments_show(struct nilfs_segments_attr * attr,struct the_nilfs * nilfs,char * buf)381*4882a593Smuzhiyun nilfs_segments_clean_segments_show(struct nilfs_segments_attr *attr,
382*4882a593Smuzhiyun 				    struct the_nilfs *nilfs,
383*4882a593Smuzhiyun 				    char *buf)
384*4882a593Smuzhiyun {
385*4882a593Smuzhiyun 	unsigned long ncleansegs;
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 	down_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem);
388*4882a593Smuzhiyun 	ncleansegs = nilfs_sufile_get_ncleansegs(nilfs->ns_sufile);
389*4882a593Smuzhiyun 	up_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem);
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%lu\n", ncleansegs);
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun static ssize_t
nilfs_segments_dirty_segments_show(struct nilfs_segments_attr * attr,struct the_nilfs * nilfs,char * buf)395*4882a593Smuzhiyun nilfs_segments_dirty_segments_show(struct nilfs_segments_attr *attr,
396*4882a593Smuzhiyun 				    struct the_nilfs *nilfs,
397*4882a593Smuzhiyun 				    char *buf)
398*4882a593Smuzhiyun {
399*4882a593Smuzhiyun 	struct nilfs_sustat sustat;
400*4882a593Smuzhiyun 	int err;
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun 	down_read(&nilfs->ns_segctor_sem);
403*4882a593Smuzhiyun 	err = nilfs_sufile_get_stat(nilfs->ns_sufile, &sustat);
404*4882a593Smuzhiyun 	up_read(&nilfs->ns_segctor_sem);
405*4882a593Smuzhiyun 	if (err < 0) {
406*4882a593Smuzhiyun 		nilfs_err(nilfs->ns_sb, "unable to get segment stat: err=%d",
407*4882a593Smuzhiyun 			  err);
408*4882a593Smuzhiyun 		return err;
409*4882a593Smuzhiyun 	}
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%llu\n", sustat.ss_ndirtysegs);
412*4882a593Smuzhiyun }
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun static const char segments_readme_str[] =
415*4882a593Smuzhiyun 	"The segments group contains attributes that describe\n"
416*4882a593Smuzhiyun 	"details about volume's segments.\n\n"
417*4882a593Smuzhiyun 	"(1) segments_number\n\tshow number of segments on volume.\n\n"
418*4882a593Smuzhiyun 	"(2) blocks_per_segment\n\tshow number of blocks in segment.\n\n"
419*4882a593Smuzhiyun 	"(3) clean_segments\n\tshow count of clean segments.\n\n"
420*4882a593Smuzhiyun 	"(4) dirty_segments\n\tshow count of dirty segments.\n\n";
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun static ssize_t
nilfs_segments_README_show(struct nilfs_segments_attr * attr,struct the_nilfs * nilfs,char * buf)423*4882a593Smuzhiyun nilfs_segments_README_show(struct nilfs_segments_attr *attr,
424*4882a593Smuzhiyun 			    struct the_nilfs *nilfs,
425*4882a593Smuzhiyun 			    char *buf)
426*4882a593Smuzhiyun {
427*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, segments_readme_str);
428*4882a593Smuzhiyun }
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun NILFS_SEGMENTS_RO_ATTR(segments_number);
431*4882a593Smuzhiyun NILFS_SEGMENTS_RO_ATTR(blocks_per_segment);
432*4882a593Smuzhiyun NILFS_SEGMENTS_RO_ATTR(clean_segments);
433*4882a593Smuzhiyun NILFS_SEGMENTS_RO_ATTR(dirty_segments);
434*4882a593Smuzhiyun NILFS_SEGMENTS_RO_ATTR(README);
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun static struct attribute *nilfs_segments_attrs[] = {
437*4882a593Smuzhiyun 	NILFS_SEGMENTS_ATTR_LIST(segments_number),
438*4882a593Smuzhiyun 	NILFS_SEGMENTS_ATTR_LIST(blocks_per_segment),
439*4882a593Smuzhiyun 	NILFS_SEGMENTS_ATTR_LIST(clean_segments),
440*4882a593Smuzhiyun 	NILFS_SEGMENTS_ATTR_LIST(dirty_segments),
441*4882a593Smuzhiyun 	NILFS_SEGMENTS_ATTR_LIST(README),
442*4882a593Smuzhiyun 	NULL,
443*4882a593Smuzhiyun };
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun NILFS_DEV_INT_GROUP_OPS(segments, dev);
446*4882a593Smuzhiyun NILFS_DEV_INT_GROUP_TYPE(segments, dev);
447*4882a593Smuzhiyun NILFS_DEV_INT_GROUP_FNS(segments, dev);
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun /************************************************************************
450*4882a593Smuzhiyun  *                        NILFS segctor attrs                           *
451*4882a593Smuzhiyun  ************************************************************************/
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun static ssize_t
nilfs_segctor_last_pseg_block_show(struct nilfs_segctor_attr * attr,struct the_nilfs * nilfs,char * buf)454*4882a593Smuzhiyun nilfs_segctor_last_pseg_block_show(struct nilfs_segctor_attr *attr,
455*4882a593Smuzhiyun 				    struct the_nilfs *nilfs,
456*4882a593Smuzhiyun 				    char *buf)
457*4882a593Smuzhiyun {
458*4882a593Smuzhiyun 	sector_t last_pseg;
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun 	spin_lock(&nilfs->ns_last_segment_lock);
461*4882a593Smuzhiyun 	last_pseg = nilfs->ns_last_pseg;
462*4882a593Smuzhiyun 	spin_unlock(&nilfs->ns_last_segment_lock);
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%llu\n",
465*4882a593Smuzhiyun 			(unsigned long long)last_pseg);
466*4882a593Smuzhiyun }
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun static ssize_t
nilfs_segctor_last_seg_sequence_show(struct nilfs_segctor_attr * attr,struct the_nilfs * nilfs,char * buf)469*4882a593Smuzhiyun nilfs_segctor_last_seg_sequence_show(struct nilfs_segctor_attr *attr,
470*4882a593Smuzhiyun 					struct the_nilfs *nilfs,
471*4882a593Smuzhiyun 					char *buf)
472*4882a593Smuzhiyun {
473*4882a593Smuzhiyun 	u64 last_seq;
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun 	spin_lock(&nilfs->ns_last_segment_lock);
476*4882a593Smuzhiyun 	last_seq = nilfs->ns_last_seq;
477*4882a593Smuzhiyun 	spin_unlock(&nilfs->ns_last_segment_lock);
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%llu\n", last_seq);
480*4882a593Smuzhiyun }
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun static ssize_t
nilfs_segctor_last_seg_checkpoint_show(struct nilfs_segctor_attr * attr,struct the_nilfs * nilfs,char * buf)483*4882a593Smuzhiyun nilfs_segctor_last_seg_checkpoint_show(struct nilfs_segctor_attr *attr,
484*4882a593Smuzhiyun 					struct the_nilfs *nilfs,
485*4882a593Smuzhiyun 					char *buf)
486*4882a593Smuzhiyun {
487*4882a593Smuzhiyun 	__u64 last_cno;
488*4882a593Smuzhiyun 
489*4882a593Smuzhiyun 	spin_lock(&nilfs->ns_last_segment_lock);
490*4882a593Smuzhiyun 	last_cno = nilfs->ns_last_cno;
491*4882a593Smuzhiyun 	spin_unlock(&nilfs->ns_last_segment_lock);
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%llu\n", last_cno);
494*4882a593Smuzhiyun }
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun static ssize_t
nilfs_segctor_current_seg_sequence_show(struct nilfs_segctor_attr * attr,struct the_nilfs * nilfs,char * buf)497*4882a593Smuzhiyun nilfs_segctor_current_seg_sequence_show(struct nilfs_segctor_attr *attr,
498*4882a593Smuzhiyun 					struct the_nilfs *nilfs,
499*4882a593Smuzhiyun 					char *buf)
500*4882a593Smuzhiyun {
501*4882a593Smuzhiyun 	u64 seg_seq;
502*4882a593Smuzhiyun 
503*4882a593Smuzhiyun 	down_read(&nilfs->ns_segctor_sem);
504*4882a593Smuzhiyun 	seg_seq = nilfs->ns_seg_seq;
505*4882a593Smuzhiyun 	up_read(&nilfs->ns_segctor_sem);
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%llu\n", seg_seq);
508*4882a593Smuzhiyun }
509*4882a593Smuzhiyun 
510*4882a593Smuzhiyun static ssize_t
nilfs_segctor_current_last_full_seg_show(struct nilfs_segctor_attr * attr,struct the_nilfs * nilfs,char * buf)511*4882a593Smuzhiyun nilfs_segctor_current_last_full_seg_show(struct nilfs_segctor_attr *attr,
512*4882a593Smuzhiyun 					 struct the_nilfs *nilfs,
513*4882a593Smuzhiyun 					 char *buf)
514*4882a593Smuzhiyun {
515*4882a593Smuzhiyun 	__u64 segnum;
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun 	down_read(&nilfs->ns_segctor_sem);
518*4882a593Smuzhiyun 	segnum = nilfs->ns_segnum;
519*4882a593Smuzhiyun 	up_read(&nilfs->ns_segctor_sem);
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%llu\n", segnum);
522*4882a593Smuzhiyun }
523*4882a593Smuzhiyun 
524*4882a593Smuzhiyun static ssize_t
nilfs_segctor_next_full_seg_show(struct nilfs_segctor_attr * attr,struct the_nilfs * nilfs,char * buf)525*4882a593Smuzhiyun nilfs_segctor_next_full_seg_show(struct nilfs_segctor_attr *attr,
526*4882a593Smuzhiyun 				 struct the_nilfs *nilfs,
527*4882a593Smuzhiyun 				 char *buf)
528*4882a593Smuzhiyun {
529*4882a593Smuzhiyun 	__u64 nextnum;
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun 	down_read(&nilfs->ns_segctor_sem);
532*4882a593Smuzhiyun 	nextnum = nilfs->ns_nextnum;
533*4882a593Smuzhiyun 	up_read(&nilfs->ns_segctor_sem);
534*4882a593Smuzhiyun 
535*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%llu\n", nextnum);
536*4882a593Smuzhiyun }
537*4882a593Smuzhiyun 
538*4882a593Smuzhiyun static ssize_t
nilfs_segctor_next_pseg_offset_show(struct nilfs_segctor_attr * attr,struct the_nilfs * nilfs,char * buf)539*4882a593Smuzhiyun nilfs_segctor_next_pseg_offset_show(struct nilfs_segctor_attr *attr,
540*4882a593Smuzhiyun 					struct the_nilfs *nilfs,
541*4882a593Smuzhiyun 					char *buf)
542*4882a593Smuzhiyun {
543*4882a593Smuzhiyun 	unsigned long pseg_offset;
544*4882a593Smuzhiyun 
545*4882a593Smuzhiyun 	down_read(&nilfs->ns_segctor_sem);
546*4882a593Smuzhiyun 	pseg_offset = nilfs->ns_pseg_offset;
547*4882a593Smuzhiyun 	up_read(&nilfs->ns_segctor_sem);
548*4882a593Smuzhiyun 
549*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%lu\n", pseg_offset);
550*4882a593Smuzhiyun }
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun static ssize_t
nilfs_segctor_next_checkpoint_show(struct nilfs_segctor_attr * attr,struct the_nilfs * nilfs,char * buf)553*4882a593Smuzhiyun nilfs_segctor_next_checkpoint_show(struct nilfs_segctor_attr *attr,
554*4882a593Smuzhiyun 					struct the_nilfs *nilfs,
555*4882a593Smuzhiyun 					char *buf)
556*4882a593Smuzhiyun {
557*4882a593Smuzhiyun 	__u64 cno;
558*4882a593Smuzhiyun 
559*4882a593Smuzhiyun 	down_read(&nilfs->ns_segctor_sem);
560*4882a593Smuzhiyun 	cno = nilfs->ns_cno;
561*4882a593Smuzhiyun 	up_read(&nilfs->ns_segctor_sem);
562*4882a593Smuzhiyun 
563*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%llu\n", cno);
564*4882a593Smuzhiyun }
565*4882a593Smuzhiyun 
566*4882a593Smuzhiyun static ssize_t
nilfs_segctor_last_seg_write_time_show(struct nilfs_segctor_attr * attr,struct the_nilfs * nilfs,char * buf)567*4882a593Smuzhiyun nilfs_segctor_last_seg_write_time_show(struct nilfs_segctor_attr *attr,
568*4882a593Smuzhiyun 					struct the_nilfs *nilfs,
569*4882a593Smuzhiyun 					char *buf)
570*4882a593Smuzhiyun {
571*4882a593Smuzhiyun 	time64_t ctime;
572*4882a593Smuzhiyun 
573*4882a593Smuzhiyun 	down_read(&nilfs->ns_segctor_sem);
574*4882a593Smuzhiyun 	ctime = nilfs->ns_ctime;
575*4882a593Smuzhiyun 	up_read(&nilfs->ns_segctor_sem);
576*4882a593Smuzhiyun 
577*4882a593Smuzhiyun 	return NILFS_SHOW_TIME(ctime, buf);
578*4882a593Smuzhiyun }
579*4882a593Smuzhiyun 
580*4882a593Smuzhiyun static ssize_t
nilfs_segctor_last_seg_write_time_secs_show(struct nilfs_segctor_attr * attr,struct the_nilfs * nilfs,char * buf)581*4882a593Smuzhiyun nilfs_segctor_last_seg_write_time_secs_show(struct nilfs_segctor_attr *attr,
582*4882a593Smuzhiyun 					    struct the_nilfs *nilfs,
583*4882a593Smuzhiyun 					    char *buf)
584*4882a593Smuzhiyun {
585*4882a593Smuzhiyun 	time64_t ctime;
586*4882a593Smuzhiyun 
587*4882a593Smuzhiyun 	down_read(&nilfs->ns_segctor_sem);
588*4882a593Smuzhiyun 	ctime = nilfs->ns_ctime;
589*4882a593Smuzhiyun 	up_read(&nilfs->ns_segctor_sem);
590*4882a593Smuzhiyun 
591*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%llu\n", ctime);
592*4882a593Smuzhiyun }
593*4882a593Smuzhiyun 
594*4882a593Smuzhiyun static ssize_t
nilfs_segctor_last_nongc_write_time_show(struct nilfs_segctor_attr * attr,struct the_nilfs * nilfs,char * buf)595*4882a593Smuzhiyun nilfs_segctor_last_nongc_write_time_show(struct nilfs_segctor_attr *attr,
596*4882a593Smuzhiyun 					 struct the_nilfs *nilfs,
597*4882a593Smuzhiyun 					 char *buf)
598*4882a593Smuzhiyun {
599*4882a593Smuzhiyun 	time64_t nongc_ctime;
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun 	down_read(&nilfs->ns_segctor_sem);
602*4882a593Smuzhiyun 	nongc_ctime = nilfs->ns_nongc_ctime;
603*4882a593Smuzhiyun 	up_read(&nilfs->ns_segctor_sem);
604*4882a593Smuzhiyun 
605*4882a593Smuzhiyun 	return NILFS_SHOW_TIME(nongc_ctime, buf);
606*4882a593Smuzhiyun }
607*4882a593Smuzhiyun 
608*4882a593Smuzhiyun static ssize_t
nilfs_segctor_last_nongc_write_time_secs_show(struct nilfs_segctor_attr * attr,struct the_nilfs * nilfs,char * buf)609*4882a593Smuzhiyun nilfs_segctor_last_nongc_write_time_secs_show(struct nilfs_segctor_attr *attr,
610*4882a593Smuzhiyun 						struct the_nilfs *nilfs,
611*4882a593Smuzhiyun 						char *buf)
612*4882a593Smuzhiyun {
613*4882a593Smuzhiyun 	time64_t nongc_ctime;
614*4882a593Smuzhiyun 
615*4882a593Smuzhiyun 	down_read(&nilfs->ns_segctor_sem);
616*4882a593Smuzhiyun 	nongc_ctime = nilfs->ns_nongc_ctime;
617*4882a593Smuzhiyun 	up_read(&nilfs->ns_segctor_sem);
618*4882a593Smuzhiyun 
619*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%llu\n", nongc_ctime);
620*4882a593Smuzhiyun }
621*4882a593Smuzhiyun 
622*4882a593Smuzhiyun static ssize_t
nilfs_segctor_dirty_data_blocks_count_show(struct nilfs_segctor_attr * attr,struct the_nilfs * nilfs,char * buf)623*4882a593Smuzhiyun nilfs_segctor_dirty_data_blocks_count_show(struct nilfs_segctor_attr *attr,
624*4882a593Smuzhiyun 					    struct the_nilfs *nilfs,
625*4882a593Smuzhiyun 					    char *buf)
626*4882a593Smuzhiyun {
627*4882a593Smuzhiyun 	u32 ndirtyblks;
628*4882a593Smuzhiyun 
629*4882a593Smuzhiyun 	down_read(&nilfs->ns_segctor_sem);
630*4882a593Smuzhiyun 	ndirtyblks = atomic_read(&nilfs->ns_ndirtyblks);
631*4882a593Smuzhiyun 	up_read(&nilfs->ns_segctor_sem);
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%u\n", ndirtyblks);
634*4882a593Smuzhiyun }
635*4882a593Smuzhiyun 
636*4882a593Smuzhiyun static const char segctor_readme_str[] =
637*4882a593Smuzhiyun 	"The segctor group contains attributes that describe\n"
638*4882a593Smuzhiyun 	"segctor thread activity details.\n\n"
639*4882a593Smuzhiyun 	"(1) last_pseg_block\n"
640*4882a593Smuzhiyun 	"\tshow start block number of the latest segment.\n\n"
641*4882a593Smuzhiyun 	"(2) last_seg_sequence\n"
642*4882a593Smuzhiyun 	"\tshow sequence value of the latest segment.\n\n"
643*4882a593Smuzhiyun 	"(3) last_seg_checkpoint\n"
644*4882a593Smuzhiyun 	"\tshow checkpoint number of the latest segment.\n\n"
645*4882a593Smuzhiyun 	"(4) current_seg_sequence\n\tshow segment sequence counter.\n\n"
646*4882a593Smuzhiyun 	"(5) current_last_full_seg\n"
647*4882a593Smuzhiyun 	"\tshow index number of the latest full segment.\n\n"
648*4882a593Smuzhiyun 	"(6) next_full_seg\n"
649*4882a593Smuzhiyun 	"\tshow index number of the full segment index to be used next.\n\n"
650*4882a593Smuzhiyun 	"(7) next_pseg_offset\n"
651*4882a593Smuzhiyun 	"\tshow offset of next partial segment in the current full segment.\n\n"
652*4882a593Smuzhiyun 	"(8) next_checkpoint\n\tshow next checkpoint number.\n\n"
653*4882a593Smuzhiyun 	"(9) last_seg_write_time\n"
654*4882a593Smuzhiyun 	"\tshow write time of the last segment in human-readable format.\n\n"
655*4882a593Smuzhiyun 	"(10) last_seg_write_time_secs\n"
656*4882a593Smuzhiyun 	"\tshow write time of the last segment in seconds.\n\n"
657*4882a593Smuzhiyun 	"(11) last_nongc_write_time\n"
658*4882a593Smuzhiyun 	"\tshow write time of the last segment not for cleaner operation "
659*4882a593Smuzhiyun 	"in human-readable format.\n\n"
660*4882a593Smuzhiyun 	"(12) last_nongc_write_time_secs\n"
661*4882a593Smuzhiyun 	"\tshow write time of the last segment not for cleaner operation "
662*4882a593Smuzhiyun 	"in seconds.\n\n"
663*4882a593Smuzhiyun 	"(13) dirty_data_blocks_count\n"
664*4882a593Smuzhiyun 	"\tshow number of dirty data blocks.\n\n";
665*4882a593Smuzhiyun 
666*4882a593Smuzhiyun static ssize_t
nilfs_segctor_README_show(struct nilfs_segctor_attr * attr,struct the_nilfs * nilfs,char * buf)667*4882a593Smuzhiyun nilfs_segctor_README_show(struct nilfs_segctor_attr *attr,
668*4882a593Smuzhiyun 			  struct the_nilfs *nilfs, char *buf)
669*4882a593Smuzhiyun {
670*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, segctor_readme_str);
671*4882a593Smuzhiyun }
672*4882a593Smuzhiyun 
673*4882a593Smuzhiyun NILFS_SEGCTOR_RO_ATTR(last_pseg_block);
674*4882a593Smuzhiyun NILFS_SEGCTOR_RO_ATTR(last_seg_sequence);
675*4882a593Smuzhiyun NILFS_SEGCTOR_RO_ATTR(last_seg_checkpoint);
676*4882a593Smuzhiyun NILFS_SEGCTOR_RO_ATTR(current_seg_sequence);
677*4882a593Smuzhiyun NILFS_SEGCTOR_RO_ATTR(current_last_full_seg);
678*4882a593Smuzhiyun NILFS_SEGCTOR_RO_ATTR(next_full_seg);
679*4882a593Smuzhiyun NILFS_SEGCTOR_RO_ATTR(next_pseg_offset);
680*4882a593Smuzhiyun NILFS_SEGCTOR_RO_ATTR(next_checkpoint);
681*4882a593Smuzhiyun NILFS_SEGCTOR_RO_ATTR(last_seg_write_time);
682*4882a593Smuzhiyun NILFS_SEGCTOR_RO_ATTR(last_seg_write_time_secs);
683*4882a593Smuzhiyun NILFS_SEGCTOR_RO_ATTR(last_nongc_write_time);
684*4882a593Smuzhiyun NILFS_SEGCTOR_RO_ATTR(last_nongc_write_time_secs);
685*4882a593Smuzhiyun NILFS_SEGCTOR_RO_ATTR(dirty_data_blocks_count);
686*4882a593Smuzhiyun NILFS_SEGCTOR_RO_ATTR(README);
687*4882a593Smuzhiyun 
688*4882a593Smuzhiyun static struct attribute *nilfs_segctor_attrs[] = {
689*4882a593Smuzhiyun 	NILFS_SEGCTOR_ATTR_LIST(last_pseg_block),
690*4882a593Smuzhiyun 	NILFS_SEGCTOR_ATTR_LIST(last_seg_sequence),
691*4882a593Smuzhiyun 	NILFS_SEGCTOR_ATTR_LIST(last_seg_checkpoint),
692*4882a593Smuzhiyun 	NILFS_SEGCTOR_ATTR_LIST(current_seg_sequence),
693*4882a593Smuzhiyun 	NILFS_SEGCTOR_ATTR_LIST(current_last_full_seg),
694*4882a593Smuzhiyun 	NILFS_SEGCTOR_ATTR_LIST(next_full_seg),
695*4882a593Smuzhiyun 	NILFS_SEGCTOR_ATTR_LIST(next_pseg_offset),
696*4882a593Smuzhiyun 	NILFS_SEGCTOR_ATTR_LIST(next_checkpoint),
697*4882a593Smuzhiyun 	NILFS_SEGCTOR_ATTR_LIST(last_seg_write_time),
698*4882a593Smuzhiyun 	NILFS_SEGCTOR_ATTR_LIST(last_seg_write_time_secs),
699*4882a593Smuzhiyun 	NILFS_SEGCTOR_ATTR_LIST(last_nongc_write_time),
700*4882a593Smuzhiyun 	NILFS_SEGCTOR_ATTR_LIST(last_nongc_write_time_secs),
701*4882a593Smuzhiyun 	NILFS_SEGCTOR_ATTR_LIST(dirty_data_blocks_count),
702*4882a593Smuzhiyun 	NILFS_SEGCTOR_ATTR_LIST(README),
703*4882a593Smuzhiyun 	NULL,
704*4882a593Smuzhiyun };
705*4882a593Smuzhiyun 
706*4882a593Smuzhiyun NILFS_DEV_INT_GROUP_OPS(segctor, dev);
707*4882a593Smuzhiyun NILFS_DEV_INT_GROUP_TYPE(segctor, dev);
708*4882a593Smuzhiyun NILFS_DEV_INT_GROUP_FNS(segctor, dev);
709*4882a593Smuzhiyun 
710*4882a593Smuzhiyun /************************************************************************
711*4882a593Smuzhiyun  *                        NILFS superblock attrs                        *
712*4882a593Smuzhiyun  ************************************************************************/
713*4882a593Smuzhiyun 
714*4882a593Smuzhiyun static ssize_t
nilfs_superblock_sb_write_time_show(struct nilfs_superblock_attr * attr,struct the_nilfs * nilfs,char * buf)715*4882a593Smuzhiyun nilfs_superblock_sb_write_time_show(struct nilfs_superblock_attr *attr,
716*4882a593Smuzhiyun 				     struct the_nilfs *nilfs,
717*4882a593Smuzhiyun 				     char *buf)
718*4882a593Smuzhiyun {
719*4882a593Smuzhiyun 	time64_t sbwtime;
720*4882a593Smuzhiyun 
721*4882a593Smuzhiyun 	down_read(&nilfs->ns_sem);
722*4882a593Smuzhiyun 	sbwtime = nilfs->ns_sbwtime;
723*4882a593Smuzhiyun 	up_read(&nilfs->ns_sem);
724*4882a593Smuzhiyun 
725*4882a593Smuzhiyun 	return NILFS_SHOW_TIME(sbwtime, buf);
726*4882a593Smuzhiyun }
727*4882a593Smuzhiyun 
728*4882a593Smuzhiyun static ssize_t
nilfs_superblock_sb_write_time_secs_show(struct nilfs_superblock_attr * attr,struct the_nilfs * nilfs,char * buf)729*4882a593Smuzhiyun nilfs_superblock_sb_write_time_secs_show(struct nilfs_superblock_attr *attr,
730*4882a593Smuzhiyun 					 struct the_nilfs *nilfs,
731*4882a593Smuzhiyun 					 char *buf)
732*4882a593Smuzhiyun {
733*4882a593Smuzhiyun 	time64_t sbwtime;
734*4882a593Smuzhiyun 
735*4882a593Smuzhiyun 	down_read(&nilfs->ns_sem);
736*4882a593Smuzhiyun 	sbwtime = nilfs->ns_sbwtime;
737*4882a593Smuzhiyun 	up_read(&nilfs->ns_sem);
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%llu\n", sbwtime);
740*4882a593Smuzhiyun }
741*4882a593Smuzhiyun 
742*4882a593Smuzhiyun static ssize_t
nilfs_superblock_sb_write_count_show(struct nilfs_superblock_attr * attr,struct the_nilfs * nilfs,char * buf)743*4882a593Smuzhiyun nilfs_superblock_sb_write_count_show(struct nilfs_superblock_attr *attr,
744*4882a593Smuzhiyun 				      struct the_nilfs *nilfs,
745*4882a593Smuzhiyun 				      char *buf)
746*4882a593Smuzhiyun {
747*4882a593Smuzhiyun 	unsigned int sbwcount;
748*4882a593Smuzhiyun 
749*4882a593Smuzhiyun 	down_read(&nilfs->ns_sem);
750*4882a593Smuzhiyun 	sbwcount = nilfs->ns_sbwcount;
751*4882a593Smuzhiyun 	up_read(&nilfs->ns_sem);
752*4882a593Smuzhiyun 
753*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%u\n", sbwcount);
754*4882a593Smuzhiyun }
755*4882a593Smuzhiyun 
756*4882a593Smuzhiyun static ssize_t
nilfs_superblock_sb_update_frequency_show(struct nilfs_superblock_attr * attr,struct the_nilfs * nilfs,char * buf)757*4882a593Smuzhiyun nilfs_superblock_sb_update_frequency_show(struct nilfs_superblock_attr *attr,
758*4882a593Smuzhiyun 					    struct the_nilfs *nilfs,
759*4882a593Smuzhiyun 					    char *buf)
760*4882a593Smuzhiyun {
761*4882a593Smuzhiyun 	unsigned int sb_update_freq;
762*4882a593Smuzhiyun 
763*4882a593Smuzhiyun 	down_read(&nilfs->ns_sem);
764*4882a593Smuzhiyun 	sb_update_freq = nilfs->ns_sb_update_freq;
765*4882a593Smuzhiyun 	up_read(&nilfs->ns_sem);
766*4882a593Smuzhiyun 
767*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%u\n", sb_update_freq);
768*4882a593Smuzhiyun }
769*4882a593Smuzhiyun 
770*4882a593Smuzhiyun static ssize_t
nilfs_superblock_sb_update_frequency_store(struct nilfs_superblock_attr * attr,struct the_nilfs * nilfs,const char * buf,size_t count)771*4882a593Smuzhiyun nilfs_superblock_sb_update_frequency_store(struct nilfs_superblock_attr *attr,
772*4882a593Smuzhiyun 					    struct the_nilfs *nilfs,
773*4882a593Smuzhiyun 					    const char *buf, size_t count)
774*4882a593Smuzhiyun {
775*4882a593Smuzhiyun 	unsigned int val;
776*4882a593Smuzhiyun 	int err;
777*4882a593Smuzhiyun 
778*4882a593Smuzhiyun 	err = kstrtouint(skip_spaces(buf), 0, &val);
779*4882a593Smuzhiyun 	if (err) {
780*4882a593Smuzhiyun 		nilfs_err(nilfs->ns_sb, "unable to convert string: err=%d",
781*4882a593Smuzhiyun 			  err);
782*4882a593Smuzhiyun 		return err;
783*4882a593Smuzhiyun 	}
784*4882a593Smuzhiyun 
785*4882a593Smuzhiyun 	if (val < NILFS_SB_FREQ) {
786*4882a593Smuzhiyun 		val = NILFS_SB_FREQ;
787*4882a593Smuzhiyun 		nilfs_warn(nilfs->ns_sb,
788*4882a593Smuzhiyun 			   "superblock update frequency cannot be lesser than 10 seconds");
789*4882a593Smuzhiyun 	}
790*4882a593Smuzhiyun 
791*4882a593Smuzhiyun 	down_write(&nilfs->ns_sem);
792*4882a593Smuzhiyun 	nilfs->ns_sb_update_freq = val;
793*4882a593Smuzhiyun 	up_write(&nilfs->ns_sem);
794*4882a593Smuzhiyun 
795*4882a593Smuzhiyun 	return count;
796*4882a593Smuzhiyun }
797*4882a593Smuzhiyun 
798*4882a593Smuzhiyun static const char sb_readme_str[] =
799*4882a593Smuzhiyun 	"The superblock group contains attributes that describe\n"
800*4882a593Smuzhiyun 	"superblock's details.\n\n"
801*4882a593Smuzhiyun 	"(1) sb_write_time\n\tshow previous write time of super block "
802*4882a593Smuzhiyun 	"in human-readable format.\n\n"
803*4882a593Smuzhiyun 	"(2) sb_write_time_secs\n\tshow previous write time of super block "
804*4882a593Smuzhiyun 	"in seconds.\n\n"
805*4882a593Smuzhiyun 	"(3) sb_write_count\n\tshow write count of super block.\n\n"
806*4882a593Smuzhiyun 	"(4) sb_update_frequency\n"
807*4882a593Smuzhiyun 	"\tshow/set interval of periodical update of superblock (in seconds).\n\n"
808*4882a593Smuzhiyun 	"\tYou can set preferable frequency of superblock update by command:\n\n"
809*4882a593Smuzhiyun 	"\t'echo <val> > /sys/fs/<nilfs>/<dev>/superblock/sb_update_frequency'\n";
810*4882a593Smuzhiyun 
811*4882a593Smuzhiyun static ssize_t
nilfs_superblock_README_show(struct nilfs_superblock_attr * attr,struct the_nilfs * nilfs,char * buf)812*4882a593Smuzhiyun nilfs_superblock_README_show(struct nilfs_superblock_attr *attr,
813*4882a593Smuzhiyun 				struct the_nilfs *nilfs, char *buf)
814*4882a593Smuzhiyun {
815*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, sb_readme_str);
816*4882a593Smuzhiyun }
817*4882a593Smuzhiyun 
818*4882a593Smuzhiyun NILFS_SUPERBLOCK_RO_ATTR(sb_write_time);
819*4882a593Smuzhiyun NILFS_SUPERBLOCK_RO_ATTR(sb_write_time_secs);
820*4882a593Smuzhiyun NILFS_SUPERBLOCK_RO_ATTR(sb_write_count);
821*4882a593Smuzhiyun NILFS_SUPERBLOCK_RW_ATTR(sb_update_frequency);
822*4882a593Smuzhiyun NILFS_SUPERBLOCK_RO_ATTR(README);
823*4882a593Smuzhiyun 
824*4882a593Smuzhiyun static struct attribute *nilfs_superblock_attrs[] = {
825*4882a593Smuzhiyun 	NILFS_SUPERBLOCK_ATTR_LIST(sb_write_time),
826*4882a593Smuzhiyun 	NILFS_SUPERBLOCK_ATTR_LIST(sb_write_time_secs),
827*4882a593Smuzhiyun 	NILFS_SUPERBLOCK_ATTR_LIST(sb_write_count),
828*4882a593Smuzhiyun 	NILFS_SUPERBLOCK_ATTR_LIST(sb_update_frequency),
829*4882a593Smuzhiyun 	NILFS_SUPERBLOCK_ATTR_LIST(README),
830*4882a593Smuzhiyun 	NULL,
831*4882a593Smuzhiyun };
832*4882a593Smuzhiyun 
833*4882a593Smuzhiyun NILFS_DEV_INT_GROUP_OPS(superblock, dev);
834*4882a593Smuzhiyun NILFS_DEV_INT_GROUP_TYPE(superblock, dev);
835*4882a593Smuzhiyun NILFS_DEV_INT_GROUP_FNS(superblock, dev);
836*4882a593Smuzhiyun 
837*4882a593Smuzhiyun /************************************************************************
838*4882a593Smuzhiyun  *                        NILFS device attrs                            *
839*4882a593Smuzhiyun  ************************************************************************/
840*4882a593Smuzhiyun 
841*4882a593Smuzhiyun static
nilfs_dev_revision_show(struct nilfs_dev_attr * attr,struct the_nilfs * nilfs,char * buf)842*4882a593Smuzhiyun ssize_t nilfs_dev_revision_show(struct nilfs_dev_attr *attr,
843*4882a593Smuzhiyun 				struct the_nilfs *nilfs,
844*4882a593Smuzhiyun 				char *buf)
845*4882a593Smuzhiyun {
846*4882a593Smuzhiyun 	struct nilfs_super_block **sbp = nilfs->ns_sbp;
847*4882a593Smuzhiyun 	u32 major = le32_to_cpu(sbp[0]->s_rev_level);
848*4882a593Smuzhiyun 	u16 minor = le16_to_cpu(sbp[0]->s_minor_rev_level);
849*4882a593Smuzhiyun 
850*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%d.%d\n", major, minor);
851*4882a593Smuzhiyun }
852*4882a593Smuzhiyun 
853*4882a593Smuzhiyun static
nilfs_dev_blocksize_show(struct nilfs_dev_attr * attr,struct the_nilfs * nilfs,char * buf)854*4882a593Smuzhiyun ssize_t nilfs_dev_blocksize_show(struct nilfs_dev_attr *attr,
855*4882a593Smuzhiyun 				 struct the_nilfs *nilfs,
856*4882a593Smuzhiyun 				 char *buf)
857*4882a593Smuzhiyun {
858*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%u\n", nilfs->ns_blocksize);
859*4882a593Smuzhiyun }
860*4882a593Smuzhiyun 
861*4882a593Smuzhiyun static
nilfs_dev_device_size_show(struct nilfs_dev_attr * attr,struct the_nilfs * nilfs,char * buf)862*4882a593Smuzhiyun ssize_t nilfs_dev_device_size_show(struct nilfs_dev_attr *attr,
863*4882a593Smuzhiyun 				    struct the_nilfs *nilfs,
864*4882a593Smuzhiyun 				    char *buf)
865*4882a593Smuzhiyun {
866*4882a593Smuzhiyun 	struct nilfs_super_block **sbp = nilfs->ns_sbp;
867*4882a593Smuzhiyun 	u64 dev_size = le64_to_cpu(sbp[0]->s_dev_size);
868*4882a593Smuzhiyun 
869*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%llu\n", dev_size);
870*4882a593Smuzhiyun }
871*4882a593Smuzhiyun 
872*4882a593Smuzhiyun static
nilfs_dev_free_blocks_show(struct nilfs_dev_attr * attr,struct the_nilfs * nilfs,char * buf)873*4882a593Smuzhiyun ssize_t nilfs_dev_free_blocks_show(struct nilfs_dev_attr *attr,
874*4882a593Smuzhiyun 				   struct the_nilfs *nilfs,
875*4882a593Smuzhiyun 				   char *buf)
876*4882a593Smuzhiyun {
877*4882a593Smuzhiyun 	sector_t free_blocks = 0;
878*4882a593Smuzhiyun 
879*4882a593Smuzhiyun 	nilfs_count_free_blocks(nilfs, &free_blocks);
880*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%llu\n",
881*4882a593Smuzhiyun 			(unsigned long long)free_blocks);
882*4882a593Smuzhiyun }
883*4882a593Smuzhiyun 
884*4882a593Smuzhiyun static
nilfs_dev_uuid_show(struct nilfs_dev_attr * attr,struct the_nilfs * nilfs,char * buf)885*4882a593Smuzhiyun ssize_t nilfs_dev_uuid_show(struct nilfs_dev_attr *attr,
886*4882a593Smuzhiyun 			    struct the_nilfs *nilfs,
887*4882a593Smuzhiyun 			    char *buf)
888*4882a593Smuzhiyun {
889*4882a593Smuzhiyun 	struct nilfs_super_block **sbp = nilfs->ns_sbp;
890*4882a593Smuzhiyun 
891*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%pUb\n", sbp[0]->s_uuid);
892*4882a593Smuzhiyun }
893*4882a593Smuzhiyun 
894*4882a593Smuzhiyun static
nilfs_dev_volume_name_show(struct nilfs_dev_attr * attr,struct the_nilfs * nilfs,char * buf)895*4882a593Smuzhiyun ssize_t nilfs_dev_volume_name_show(struct nilfs_dev_attr *attr,
896*4882a593Smuzhiyun 				    struct the_nilfs *nilfs,
897*4882a593Smuzhiyun 				    char *buf)
898*4882a593Smuzhiyun {
899*4882a593Smuzhiyun 	struct nilfs_super_block **sbp = nilfs->ns_sbp;
900*4882a593Smuzhiyun 
901*4882a593Smuzhiyun 	return scnprintf(buf, sizeof(sbp[0]->s_volume_name), "%s\n",
902*4882a593Smuzhiyun 			 sbp[0]->s_volume_name);
903*4882a593Smuzhiyun }
904*4882a593Smuzhiyun 
905*4882a593Smuzhiyun static const char dev_readme_str[] =
906*4882a593Smuzhiyun 	"The <device> group contains attributes that describe file system\n"
907*4882a593Smuzhiyun 	"partition's details.\n\n"
908*4882a593Smuzhiyun 	"(1) revision\n\tshow NILFS file system revision.\n\n"
909*4882a593Smuzhiyun 	"(2) blocksize\n\tshow volume block size in bytes.\n\n"
910*4882a593Smuzhiyun 	"(3) device_size\n\tshow volume size in bytes.\n\n"
911*4882a593Smuzhiyun 	"(4) free_blocks\n\tshow count of free blocks on volume.\n\n"
912*4882a593Smuzhiyun 	"(5) uuid\n\tshow volume's UUID.\n\n"
913*4882a593Smuzhiyun 	"(6) volume_name\n\tshow volume's name.\n\n";
914*4882a593Smuzhiyun 
nilfs_dev_README_show(struct nilfs_dev_attr * attr,struct the_nilfs * nilfs,char * buf)915*4882a593Smuzhiyun static ssize_t nilfs_dev_README_show(struct nilfs_dev_attr *attr,
916*4882a593Smuzhiyun 				     struct the_nilfs *nilfs,
917*4882a593Smuzhiyun 				     char *buf)
918*4882a593Smuzhiyun {
919*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, dev_readme_str);
920*4882a593Smuzhiyun }
921*4882a593Smuzhiyun 
922*4882a593Smuzhiyun NILFS_DEV_RO_ATTR(revision);
923*4882a593Smuzhiyun NILFS_DEV_RO_ATTR(blocksize);
924*4882a593Smuzhiyun NILFS_DEV_RO_ATTR(device_size);
925*4882a593Smuzhiyun NILFS_DEV_RO_ATTR(free_blocks);
926*4882a593Smuzhiyun NILFS_DEV_RO_ATTR(uuid);
927*4882a593Smuzhiyun NILFS_DEV_RO_ATTR(volume_name);
928*4882a593Smuzhiyun NILFS_DEV_RO_ATTR(README);
929*4882a593Smuzhiyun 
930*4882a593Smuzhiyun static struct attribute *nilfs_dev_attrs[] = {
931*4882a593Smuzhiyun 	NILFS_DEV_ATTR_LIST(revision),
932*4882a593Smuzhiyun 	NILFS_DEV_ATTR_LIST(blocksize),
933*4882a593Smuzhiyun 	NILFS_DEV_ATTR_LIST(device_size),
934*4882a593Smuzhiyun 	NILFS_DEV_ATTR_LIST(free_blocks),
935*4882a593Smuzhiyun 	NILFS_DEV_ATTR_LIST(uuid),
936*4882a593Smuzhiyun 	NILFS_DEV_ATTR_LIST(volume_name),
937*4882a593Smuzhiyun 	NILFS_DEV_ATTR_LIST(README),
938*4882a593Smuzhiyun 	NULL,
939*4882a593Smuzhiyun };
940*4882a593Smuzhiyun 
nilfs_dev_attr_show(struct kobject * kobj,struct attribute * attr,char * buf)941*4882a593Smuzhiyun static ssize_t nilfs_dev_attr_show(struct kobject *kobj,
942*4882a593Smuzhiyun 				    struct attribute *attr, char *buf)
943*4882a593Smuzhiyun {
944*4882a593Smuzhiyun 	struct the_nilfs *nilfs = container_of(kobj, struct the_nilfs,
945*4882a593Smuzhiyun 						ns_dev_kobj);
946*4882a593Smuzhiyun 	struct nilfs_dev_attr *a = container_of(attr, struct nilfs_dev_attr,
947*4882a593Smuzhiyun 						attr);
948*4882a593Smuzhiyun 
949*4882a593Smuzhiyun 	return a->show ? a->show(a, nilfs, buf) : 0;
950*4882a593Smuzhiyun }
951*4882a593Smuzhiyun 
nilfs_dev_attr_store(struct kobject * kobj,struct attribute * attr,const char * buf,size_t len)952*4882a593Smuzhiyun static ssize_t nilfs_dev_attr_store(struct kobject *kobj,
953*4882a593Smuzhiyun 				    struct attribute *attr,
954*4882a593Smuzhiyun 				    const char *buf, size_t len)
955*4882a593Smuzhiyun {
956*4882a593Smuzhiyun 	struct the_nilfs *nilfs = container_of(kobj, struct the_nilfs,
957*4882a593Smuzhiyun 						ns_dev_kobj);
958*4882a593Smuzhiyun 	struct nilfs_dev_attr *a = container_of(attr, struct nilfs_dev_attr,
959*4882a593Smuzhiyun 						attr);
960*4882a593Smuzhiyun 
961*4882a593Smuzhiyun 	return a->store ? a->store(a, nilfs, buf, len) : 0;
962*4882a593Smuzhiyun }
963*4882a593Smuzhiyun 
nilfs_dev_attr_release(struct kobject * kobj)964*4882a593Smuzhiyun static void nilfs_dev_attr_release(struct kobject *kobj)
965*4882a593Smuzhiyun {
966*4882a593Smuzhiyun 	struct the_nilfs *nilfs = container_of(kobj, struct the_nilfs,
967*4882a593Smuzhiyun 						ns_dev_kobj);
968*4882a593Smuzhiyun 	complete(&nilfs->ns_dev_kobj_unregister);
969*4882a593Smuzhiyun }
970*4882a593Smuzhiyun 
971*4882a593Smuzhiyun static const struct sysfs_ops nilfs_dev_attr_ops = {
972*4882a593Smuzhiyun 	.show	= nilfs_dev_attr_show,
973*4882a593Smuzhiyun 	.store	= nilfs_dev_attr_store,
974*4882a593Smuzhiyun };
975*4882a593Smuzhiyun 
976*4882a593Smuzhiyun static struct kobj_type nilfs_dev_ktype = {
977*4882a593Smuzhiyun 	.default_attrs	= nilfs_dev_attrs,
978*4882a593Smuzhiyun 	.sysfs_ops	= &nilfs_dev_attr_ops,
979*4882a593Smuzhiyun 	.release	= nilfs_dev_attr_release,
980*4882a593Smuzhiyun };
981*4882a593Smuzhiyun 
nilfs_sysfs_create_device_group(struct super_block * sb)982*4882a593Smuzhiyun int nilfs_sysfs_create_device_group(struct super_block *sb)
983*4882a593Smuzhiyun {
984*4882a593Smuzhiyun 	struct the_nilfs *nilfs = sb->s_fs_info;
985*4882a593Smuzhiyun 	size_t devgrp_size = sizeof(struct nilfs_sysfs_dev_subgroups);
986*4882a593Smuzhiyun 	int err;
987*4882a593Smuzhiyun 
988*4882a593Smuzhiyun 	nilfs->ns_dev_subgroups = kzalloc(devgrp_size, GFP_KERNEL);
989*4882a593Smuzhiyun 	if (unlikely(!nilfs->ns_dev_subgroups)) {
990*4882a593Smuzhiyun 		err = -ENOMEM;
991*4882a593Smuzhiyun 		nilfs_err(sb, "unable to allocate memory for device group");
992*4882a593Smuzhiyun 		goto failed_create_device_group;
993*4882a593Smuzhiyun 	}
994*4882a593Smuzhiyun 
995*4882a593Smuzhiyun 	nilfs->ns_dev_kobj.kset = nilfs_kset;
996*4882a593Smuzhiyun 	init_completion(&nilfs->ns_dev_kobj_unregister);
997*4882a593Smuzhiyun 	err = kobject_init_and_add(&nilfs->ns_dev_kobj, &nilfs_dev_ktype, NULL,
998*4882a593Smuzhiyun 				    "%s", sb->s_id);
999*4882a593Smuzhiyun 	if (err)
1000*4882a593Smuzhiyun 		goto cleanup_dev_kobject;
1001*4882a593Smuzhiyun 
1002*4882a593Smuzhiyun 	err = nilfs_sysfs_create_mounted_snapshots_group(nilfs);
1003*4882a593Smuzhiyun 	if (err)
1004*4882a593Smuzhiyun 		goto cleanup_dev_kobject;
1005*4882a593Smuzhiyun 
1006*4882a593Smuzhiyun 	err = nilfs_sysfs_create_checkpoints_group(nilfs);
1007*4882a593Smuzhiyun 	if (err)
1008*4882a593Smuzhiyun 		goto delete_mounted_snapshots_group;
1009*4882a593Smuzhiyun 
1010*4882a593Smuzhiyun 	err = nilfs_sysfs_create_segments_group(nilfs);
1011*4882a593Smuzhiyun 	if (err)
1012*4882a593Smuzhiyun 		goto delete_checkpoints_group;
1013*4882a593Smuzhiyun 
1014*4882a593Smuzhiyun 	err = nilfs_sysfs_create_superblock_group(nilfs);
1015*4882a593Smuzhiyun 	if (err)
1016*4882a593Smuzhiyun 		goto delete_segments_group;
1017*4882a593Smuzhiyun 
1018*4882a593Smuzhiyun 	err = nilfs_sysfs_create_segctor_group(nilfs);
1019*4882a593Smuzhiyun 	if (err)
1020*4882a593Smuzhiyun 		goto delete_superblock_group;
1021*4882a593Smuzhiyun 
1022*4882a593Smuzhiyun 	return 0;
1023*4882a593Smuzhiyun 
1024*4882a593Smuzhiyun delete_superblock_group:
1025*4882a593Smuzhiyun 	nilfs_sysfs_delete_superblock_group(nilfs);
1026*4882a593Smuzhiyun 
1027*4882a593Smuzhiyun delete_segments_group:
1028*4882a593Smuzhiyun 	nilfs_sysfs_delete_segments_group(nilfs);
1029*4882a593Smuzhiyun 
1030*4882a593Smuzhiyun delete_checkpoints_group:
1031*4882a593Smuzhiyun 	nilfs_sysfs_delete_checkpoints_group(nilfs);
1032*4882a593Smuzhiyun 
1033*4882a593Smuzhiyun delete_mounted_snapshots_group:
1034*4882a593Smuzhiyun 	nilfs_sysfs_delete_mounted_snapshots_group(nilfs);
1035*4882a593Smuzhiyun 
1036*4882a593Smuzhiyun cleanup_dev_kobject:
1037*4882a593Smuzhiyun 	kobject_put(&nilfs->ns_dev_kobj);
1038*4882a593Smuzhiyun 	kfree(nilfs->ns_dev_subgroups);
1039*4882a593Smuzhiyun 
1040*4882a593Smuzhiyun failed_create_device_group:
1041*4882a593Smuzhiyun 	return err;
1042*4882a593Smuzhiyun }
1043*4882a593Smuzhiyun 
nilfs_sysfs_delete_device_group(struct the_nilfs * nilfs)1044*4882a593Smuzhiyun void nilfs_sysfs_delete_device_group(struct the_nilfs *nilfs)
1045*4882a593Smuzhiyun {
1046*4882a593Smuzhiyun 	nilfs_sysfs_delete_mounted_snapshots_group(nilfs);
1047*4882a593Smuzhiyun 	nilfs_sysfs_delete_checkpoints_group(nilfs);
1048*4882a593Smuzhiyun 	nilfs_sysfs_delete_segments_group(nilfs);
1049*4882a593Smuzhiyun 	nilfs_sysfs_delete_superblock_group(nilfs);
1050*4882a593Smuzhiyun 	nilfs_sysfs_delete_segctor_group(nilfs);
1051*4882a593Smuzhiyun 	kobject_del(&nilfs->ns_dev_kobj);
1052*4882a593Smuzhiyun 	kobject_put(&nilfs->ns_dev_kobj);
1053*4882a593Smuzhiyun 	kfree(nilfs->ns_dev_subgroups);
1054*4882a593Smuzhiyun }
1055*4882a593Smuzhiyun 
1056*4882a593Smuzhiyun /************************************************************************
1057*4882a593Smuzhiyun  *                        NILFS feature attrs                           *
1058*4882a593Smuzhiyun  ************************************************************************/
1059*4882a593Smuzhiyun 
nilfs_feature_revision_show(struct kobject * kobj,struct attribute * attr,char * buf)1060*4882a593Smuzhiyun static ssize_t nilfs_feature_revision_show(struct kobject *kobj,
1061*4882a593Smuzhiyun 					    struct attribute *attr, char *buf)
1062*4882a593Smuzhiyun {
1063*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, "%d.%d\n",
1064*4882a593Smuzhiyun 			NILFS_CURRENT_REV, NILFS_MINOR_REV);
1065*4882a593Smuzhiyun }
1066*4882a593Smuzhiyun 
1067*4882a593Smuzhiyun static const char features_readme_str[] =
1068*4882a593Smuzhiyun 	"The features group contains attributes that describe NILFS file\n"
1069*4882a593Smuzhiyun 	"system driver features.\n\n"
1070*4882a593Smuzhiyun 	"(1) revision\n\tshow current revision of NILFS file system driver.\n";
1071*4882a593Smuzhiyun 
nilfs_feature_README_show(struct kobject * kobj,struct attribute * attr,char * buf)1072*4882a593Smuzhiyun static ssize_t nilfs_feature_README_show(struct kobject *kobj,
1073*4882a593Smuzhiyun 					 struct attribute *attr,
1074*4882a593Smuzhiyun 					 char *buf)
1075*4882a593Smuzhiyun {
1076*4882a593Smuzhiyun 	return snprintf(buf, PAGE_SIZE, features_readme_str);
1077*4882a593Smuzhiyun }
1078*4882a593Smuzhiyun 
1079*4882a593Smuzhiyun NILFS_FEATURE_RO_ATTR(revision);
1080*4882a593Smuzhiyun NILFS_FEATURE_RO_ATTR(README);
1081*4882a593Smuzhiyun 
1082*4882a593Smuzhiyun static struct attribute *nilfs_feature_attrs[] = {
1083*4882a593Smuzhiyun 	NILFS_FEATURE_ATTR_LIST(revision),
1084*4882a593Smuzhiyun 	NILFS_FEATURE_ATTR_LIST(README),
1085*4882a593Smuzhiyun 	NULL,
1086*4882a593Smuzhiyun };
1087*4882a593Smuzhiyun 
1088*4882a593Smuzhiyun static const struct attribute_group nilfs_feature_attr_group = {
1089*4882a593Smuzhiyun 	.name = "features",
1090*4882a593Smuzhiyun 	.attrs = nilfs_feature_attrs,
1091*4882a593Smuzhiyun };
1092*4882a593Smuzhiyun 
nilfs_sysfs_init(void)1093*4882a593Smuzhiyun int __init nilfs_sysfs_init(void)
1094*4882a593Smuzhiyun {
1095*4882a593Smuzhiyun 	int err;
1096*4882a593Smuzhiyun 
1097*4882a593Smuzhiyun 	nilfs_kset = kset_create_and_add(NILFS_ROOT_GROUP_NAME, NULL, fs_kobj);
1098*4882a593Smuzhiyun 	if (!nilfs_kset) {
1099*4882a593Smuzhiyun 		err = -ENOMEM;
1100*4882a593Smuzhiyun 		nilfs_err(NULL, "unable to create sysfs entry: err=%d", err);
1101*4882a593Smuzhiyun 		goto failed_sysfs_init;
1102*4882a593Smuzhiyun 	}
1103*4882a593Smuzhiyun 
1104*4882a593Smuzhiyun 	err = sysfs_create_group(&nilfs_kset->kobj, &nilfs_feature_attr_group);
1105*4882a593Smuzhiyun 	if (unlikely(err)) {
1106*4882a593Smuzhiyun 		nilfs_err(NULL, "unable to create feature group: err=%d", err);
1107*4882a593Smuzhiyun 		goto cleanup_sysfs_init;
1108*4882a593Smuzhiyun 	}
1109*4882a593Smuzhiyun 
1110*4882a593Smuzhiyun 	return 0;
1111*4882a593Smuzhiyun 
1112*4882a593Smuzhiyun cleanup_sysfs_init:
1113*4882a593Smuzhiyun 	kset_unregister(nilfs_kset);
1114*4882a593Smuzhiyun 
1115*4882a593Smuzhiyun failed_sysfs_init:
1116*4882a593Smuzhiyun 	return err;
1117*4882a593Smuzhiyun }
1118*4882a593Smuzhiyun 
nilfs_sysfs_exit(void)1119*4882a593Smuzhiyun void nilfs_sysfs_exit(void)
1120*4882a593Smuzhiyun {
1121*4882a593Smuzhiyun 	sysfs_remove_group(&nilfs_kset->kobj, &nilfs_feature_attr_group);
1122*4882a593Smuzhiyun 	kset_unregister(nilfs_kset);
1123*4882a593Smuzhiyun }
1124