aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVyacheslav Dubeyko <Vyacheslav.Dubeyko@hgst.com>2014-08-08 17:20:42 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-08-08 18:57:20 -0400
commitcaa05d49dfd7fe04820ba8b7e424343d5426a7f3 (patch)
treedb3d3a85b97d9cbedf982e323771c0f1ad634b5f
parentda7141fb78db915680616e15677539fc8140cf53 (diff)
nilfs2: add /sys/fs/nilfs2/<device>/superblock group
This patch adds creation of /sys/fs/nilfs2/<device>/superblock group. The superblock group contains attributes that describe superblock's details: (1) sb_write_time - show previous write time of super block in human-readable format. (2) sb_write_time_secs - show previous write time of super block in seconds. (3) sb_write_count - show write count of super block. (4) sb_update_frequency - show/set interval of periodical update of superblock (in seconds). You can set preferable frequency of superblock update by command: echo <value> > /sys/fs/nilfs2/<device>/superblock/sb_update_frequency Signed-off-by: Vyacheslav Dubeyko <Vyacheslav.Dubeyko@hgst.com> Cc: Vyacheslav Dubeyko <slava@dubeyko.com> Cc: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> Cc: Michael L. Semon <mlsemon35@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--Documentation/ABI/testing/sysfs-fs-nilfs233
-rw-r--r--fs/nilfs2/sysfs.c218
-rw-r--r--fs/nilfs2/sysfs.h19
-rw-r--r--fs/nilfs2/the_nilfs.c1
-rw-r--r--fs/nilfs2/the_nilfs.h8
5 files changed, 277 insertions, 2 deletions
diff --git a/Documentation/ABI/testing/sysfs-fs-nilfs2 b/Documentation/ABI/testing/sysfs-fs-nilfs2
index 0a521d03539a..e9b4c61aa88a 100644
--- a/Documentation/ABI/testing/sysfs-fs-nilfs2
+++ b/Documentation/ABI/testing/sysfs-fs-nilfs2
@@ -56,3 +56,36 @@ Date: April 2014
56Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com> 56Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
57Description: 57Description:
58 Describe attributes of /sys/fs/nilfs2/<device> group. 58 Describe attributes of /sys/fs/nilfs2/<device> group.
59
60What: /sys/fs/nilfs2/<device>/superblock/sb_write_time
61Date: April 2014
62Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
63Description:
64 Show last write time of super block in human-readable
65 format.
66
67What: /sys/fs/nilfs2/<device>/superblock/sb_write_time_secs
68Date: April 2014
69Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
70Description:
71 Show last write time of super block in seconds.
72
73What: /sys/fs/nilfs2/<device>/superblock/sb_write_count
74Date: April 2014
75Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
76Description:
77 Show current write count of super block.
78
79What: /sys/fs/nilfs2/<device>/superblock/sb_update_frequency
80Date: April 2014
81Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
82Description:
83 Show/Set interval of periodical update of superblock
84 (in seconds).
85
86What: /sys/fs/nilfs2/<device>/superblock/README
87Date: April 2014
88Contact: "Vyacheslav Dubeyko" <slava@dubeyko.com>
89Description:
90 Describe attributes of /sys/fs/nilfs2/<device>/superblock
91 group.
diff --git a/fs/nilfs2/sysfs.c b/fs/nilfs2/sysfs.c
index 780d0f5bbe88..239f239da8ae 100644
--- a/fs/nilfs2/sysfs.c
+++ b/fs/nilfs2/sysfs.c
@@ -41,6 +41,202 @@ static struct kset *nilfs_kset;
41 count; \ 41 count; \
42}) 42})
43 43
44#define NILFS_DEV_INT_GROUP_OPS(name, parent_name) \
45static ssize_t nilfs_##name##_attr_show(struct kobject *kobj, \
46 struct attribute *attr, char *buf) \
47{ \
48 struct the_nilfs *nilfs = container_of(kobj->parent, \
49 struct the_nilfs, \
50 ns_##parent_name##_kobj); \
51 struct nilfs_##name##_attr *a = container_of(attr, \
52 struct nilfs_##name##_attr, \
53 attr); \
54 return a->show ? a->show(a, nilfs, buf) : 0; \
55} \
56static ssize_t nilfs_##name##_attr_store(struct kobject *kobj, \
57 struct attribute *attr, \
58 const char *buf, size_t len) \
59{ \
60 struct the_nilfs *nilfs = container_of(kobj->parent, \
61 struct the_nilfs, \
62 ns_##parent_name##_kobj); \
63 struct nilfs_##name##_attr *a = container_of(attr, \
64 struct nilfs_##name##_attr, \
65 attr); \
66 return a->store ? a->store(a, nilfs, buf, len) : 0; \
67} \
68static const struct sysfs_ops nilfs_##name##_attr_ops = { \
69 .show = nilfs_##name##_attr_show, \
70 .store = nilfs_##name##_attr_store, \
71};
72
73#define NILFS_DEV_INT_GROUP_TYPE(name, parent_name) \
74static void nilfs_##name##_attr_release(struct kobject *kobj) \
75{ \
76 struct nilfs_sysfs_##parent_name##_subgroups *subgroups; \
77 struct the_nilfs *nilfs = container_of(kobj->parent, \
78 struct the_nilfs, \
79 ns_##parent_name##_kobj); \
80 subgroups = nilfs->ns_##parent_name##_subgroups; \
81 complete(&subgroups->sg_##name##_kobj_unregister); \
82} \
83static struct kobj_type nilfs_##name##_ktype = { \
84 .default_attrs = nilfs_##name##_attrs, \
85 .sysfs_ops = &nilfs_##name##_attr_ops, \
86 .release = nilfs_##name##_attr_release, \
87};
88
89#define NILFS_DEV_INT_GROUP_FNS(name, parent_name) \
90int nilfs_sysfs_create_##name##_group(struct the_nilfs *nilfs) \
91{ \
92 struct kobject *parent; \
93 struct kobject *kobj; \
94 struct completion *kobj_unregister; \
95 struct nilfs_sysfs_##parent_name##_subgroups *subgroups; \
96 int err; \
97 subgroups = nilfs->ns_##parent_name##_subgroups; \
98 kobj = &subgroups->sg_##name##_kobj; \
99 kobj_unregister = &subgroups->sg_##name##_kobj_unregister; \
100 parent = &nilfs->ns_##parent_name##_kobj; \
101 kobj->kset = nilfs_kset; \
102 init_completion(kobj_unregister); \
103 err = kobject_init_and_add(kobj, &nilfs_##name##_ktype, parent, \
104 #name); \
105 if (err) \
106 return err; \
107 return 0; \
108} \
109void nilfs_sysfs_delete_##name##_group(struct the_nilfs *nilfs) \
110{ \
111 kobject_del(&nilfs->ns_##parent_name##_subgroups->sg_##name##_kobj); \
112}
113
114/************************************************************************
115 * NILFS superblock attrs *
116 ************************************************************************/
117
118static ssize_t
119nilfs_superblock_sb_write_time_show(struct nilfs_superblock_attr *attr,
120 struct the_nilfs *nilfs,
121 char *buf)
122{
123 time_t sbwtime;
124
125 down_read(&nilfs->ns_sem);
126 sbwtime = nilfs->ns_sbwtime;
127 up_read(&nilfs->ns_sem);
128
129 return NILFS_SHOW_TIME(sbwtime, buf);
130}
131
132static ssize_t
133nilfs_superblock_sb_write_time_secs_show(struct nilfs_superblock_attr *attr,
134 struct the_nilfs *nilfs,
135 char *buf)
136{
137 time_t sbwtime;
138
139 down_read(&nilfs->ns_sem);
140 sbwtime = nilfs->ns_sbwtime;
141 up_read(&nilfs->ns_sem);
142
143 return snprintf(buf, PAGE_SIZE, "%llu\n", (unsigned long long)sbwtime);
144}
145
146static ssize_t
147nilfs_superblock_sb_write_count_show(struct nilfs_superblock_attr *attr,
148 struct the_nilfs *nilfs,
149 char *buf)
150{
151 unsigned sbwcount;
152
153 down_read(&nilfs->ns_sem);
154 sbwcount = nilfs->ns_sbwcount;
155 up_read(&nilfs->ns_sem);
156
157 return snprintf(buf, PAGE_SIZE, "%u\n", sbwcount);
158}
159
160static ssize_t
161nilfs_superblock_sb_update_frequency_show(struct nilfs_superblock_attr *attr,
162 struct the_nilfs *nilfs,
163 char *buf)
164{
165 unsigned sb_update_freq;
166
167 down_read(&nilfs->ns_sem);
168 sb_update_freq = nilfs->ns_sb_update_freq;
169 up_read(&nilfs->ns_sem);
170
171 return snprintf(buf, PAGE_SIZE, "%u\n", sb_update_freq);
172}
173
174static ssize_t
175nilfs_superblock_sb_update_frequency_store(struct nilfs_superblock_attr *attr,
176 struct the_nilfs *nilfs,
177 const char *buf, size_t count)
178{
179 unsigned val;
180 int err;
181
182 err = kstrtouint(skip_spaces(buf), 0, &val);
183 if (err) {
184 printk(KERN_ERR "NILFS: unable to convert string: err=%d\n",
185 err);
186 return err;
187 }
188
189 if (val < NILFS_SB_FREQ) {
190 val = NILFS_SB_FREQ;
191 printk(KERN_WARNING "NILFS: superblock update frequency cannot be lesser than 10 seconds\n");
192 }
193
194 down_write(&nilfs->ns_sem);
195 nilfs->ns_sb_update_freq = val;
196 up_write(&nilfs->ns_sem);
197
198 return count;
199}
200
201static const char sb_readme_str[] =
202 "The superblock group contains attributes that describe\n"
203 "superblock's details.\n\n"
204 "(1) sb_write_time\n\tshow previous write time of super block "
205 "in human-readable format.\n\n"
206 "(2) sb_write_time_secs\n\tshow previous write time of super block "
207 "in seconds.\n\n"
208 "(3) sb_write_count\n\tshow write count of super block.\n\n"
209 "(4) sb_update_frequency\n"
210 "\tshow/set interval of periodical update of superblock (in seconds).\n\n"
211 "\tYou can set preferable frequency of superblock update by command:\n\n"
212 "\t'echo <val> > /sys/fs/<nilfs>/<dev>/superblock/sb_update_frequency'\n";
213
214static ssize_t
215nilfs_superblock_README_show(struct nilfs_superblock_attr *attr,
216 struct the_nilfs *nilfs, char *buf)
217{
218 return snprintf(buf, PAGE_SIZE, sb_readme_str);
219}
220
221NILFS_SUPERBLOCK_RO_ATTR(sb_write_time);
222NILFS_SUPERBLOCK_RO_ATTR(sb_write_time_secs);
223NILFS_SUPERBLOCK_RO_ATTR(sb_write_count);
224NILFS_SUPERBLOCK_RW_ATTR(sb_update_frequency);
225NILFS_SUPERBLOCK_RO_ATTR(README);
226
227static struct attribute *nilfs_superblock_attrs[] = {
228 NILFS_SUPERBLOCK_ATTR_LIST(sb_write_time),
229 NILFS_SUPERBLOCK_ATTR_LIST(sb_write_time_secs),
230 NILFS_SUPERBLOCK_ATTR_LIST(sb_write_count),
231 NILFS_SUPERBLOCK_ATTR_LIST(sb_update_frequency),
232 NILFS_SUPERBLOCK_ATTR_LIST(README),
233 NULL,
234};
235
236NILFS_DEV_INT_GROUP_OPS(superblock, dev);
237NILFS_DEV_INT_GROUP_TYPE(superblock, dev);
238NILFS_DEV_INT_GROUP_FNS(superblock, dev);
239
44/************************************************************************ 240/************************************************************************
45 * NILFS device attrs * 241 * NILFS device attrs *
46 ************************************************************************/ 242 ************************************************************************/
@@ -189,24 +385,44 @@ static struct kobj_type nilfs_dev_ktype = {
189int nilfs_sysfs_create_device_group(struct super_block *sb) 385int nilfs_sysfs_create_device_group(struct super_block *sb)
190{ 386{
191 struct the_nilfs *nilfs = sb->s_fs_info; 387 struct the_nilfs *nilfs = sb->s_fs_info;
388 size_t devgrp_size = sizeof(struct nilfs_sysfs_dev_subgroups);
192 int err; 389 int err;
193 390
391 nilfs->ns_dev_subgroups = kzalloc(devgrp_size, GFP_KERNEL);
392 if (unlikely(!nilfs->ns_dev_subgroups)) {
393 err = -ENOMEM;
394 printk(KERN_ERR "NILFS: unable to allocate memory for device group\n");
395 goto failed_create_device_group;
396 }
397
194 nilfs->ns_dev_kobj.kset = nilfs_kset; 398 nilfs->ns_dev_kobj.kset = nilfs_kset;
195 init_completion(&nilfs->ns_dev_kobj_unregister); 399 init_completion(&nilfs->ns_dev_kobj_unregister);
196 err = kobject_init_and_add(&nilfs->ns_dev_kobj, &nilfs_dev_ktype, NULL, 400 err = kobject_init_and_add(&nilfs->ns_dev_kobj, &nilfs_dev_ktype, NULL,
197 "%s", sb->s_id); 401 "%s", sb->s_id);
198 if (err) 402 if (err)
199 goto failed_create_device_group; 403 goto free_dev_subgroups;
404
405 err = nilfs_sysfs_create_superblock_group(nilfs);
406 if (err)
407 goto cleanup_dev_kobject;
200 408
201 return 0; 409 return 0;
202 410
411cleanup_dev_kobject:
412 kobject_del(&nilfs->ns_dev_kobj);
413
414free_dev_subgroups:
415 kfree(nilfs->ns_dev_subgroups);
416
203failed_create_device_group: 417failed_create_device_group:
204 return err; 418 return err;
205} 419}
206 420
207void nilfs_sysfs_delete_device_group(struct the_nilfs *nilfs) 421void nilfs_sysfs_delete_device_group(struct the_nilfs *nilfs)
208{ 422{
423 nilfs_sysfs_delete_superblock_group(nilfs);
209 kobject_del(&nilfs->ns_dev_kobj); 424 kobject_del(&nilfs->ns_dev_kobj);
425 kfree(nilfs->ns_dev_subgroups);
210} 426}
211 427
212/************************************************************************ 428/************************************************************************
diff --git a/fs/nilfs2/sysfs.h b/fs/nilfs2/sysfs.h
index 2353b28c2796..1d76af59238c 100644
--- a/fs/nilfs2/sysfs.h
+++ b/fs/nilfs2/sysfs.h
@@ -24,6 +24,17 @@
24 24
25#define NILFS_ROOT_GROUP_NAME "nilfs2" 25#define NILFS_ROOT_GROUP_NAME "nilfs2"
26 26
27/*
28 * struct nilfs_sysfs_dev_subgroups - device subgroup kernel objects
29 * @sg_superblock_kobj: /sys/fs/<nilfs>/<device>/superblock
30 * @sg_superblock_kobj_unregister: completion state
31 */
32struct nilfs_sysfs_dev_subgroups {
33 /* /sys/fs/<nilfs>/<device>/superblock */
34 struct kobject sg_superblock_kobj;
35 struct completion sg_superblock_kobj_unregister;
36};
37
27#define NILFS_COMMON_ATTR_STRUCT(name) \ 38#define NILFS_COMMON_ATTR_STRUCT(name) \
28struct nilfs_##name##_attr { \ 39struct nilfs_##name##_attr { \
29 struct attribute attr; \ 40 struct attribute attr; \
@@ -45,6 +56,7 @@ struct nilfs_##name##_attr { \
45}; 56};
46 57
47NILFS_DEV_ATTR_STRUCT(dev); 58NILFS_DEV_ATTR_STRUCT(dev);
59NILFS_DEV_ATTR_STRUCT(superblock);
48 60
49#define NILFS_ATTR(type, name, mode, show, store) \ 61#define NILFS_ATTR(type, name, mode, show, store) \
50 static struct nilfs_##type##_attr nilfs_##type##_attr_##name = \ 62 static struct nilfs_##type##_attr nilfs_##type##_attr_##name = \
@@ -73,9 +85,16 @@ NILFS_DEV_ATTR_STRUCT(dev);
73#define NILFS_DEV_RW_ATTR(name) \ 85#define NILFS_DEV_RW_ATTR(name) \
74 NILFS_RW_ATTR(dev, name) 86 NILFS_RW_ATTR(dev, name)
75 87
88#define NILFS_SUPERBLOCK_RO_ATTR(name) \
89 NILFS_RO_ATTR(superblock, name)
90#define NILFS_SUPERBLOCK_RW_ATTR(name) \
91 NILFS_RW_ATTR(superblock, name)
92
76#define NILFS_FEATURE_ATTR_LIST(name) \ 93#define NILFS_FEATURE_ATTR_LIST(name) \
77 (&nilfs_feature_attr_##name.attr) 94 (&nilfs_feature_attr_##name.attr)
78#define NILFS_DEV_ATTR_LIST(name) \ 95#define NILFS_DEV_ATTR_LIST(name) \
79 (&nilfs_dev_attr_##name.attr) 96 (&nilfs_dev_attr_##name.attr)
97#define NILFS_SUPERBLOCK_ATTR_LIST(name) \
98 (&nilfs_superblock_attr_##name.attr)
80 99
81#endif /* _NILFS_SYSFS_H */ 100#endif /* _NILFS_SYSFS_H */
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
index 8ba8229ba076..59d50088b886 100644
--- a/fs/nilfs2/the_nilfs.c
+++ b/fs/nilfs2/the_nilfs.c
@@ -85,6 +85,7 @@ struct the_nilfs *alloc_nilfs(struct block_device *bdev)
85 nilfs->ns_cptree = RB_ROOT; 85 nilfs->ns_cptree = RB_ROOT;
86 spin_lock_init(&nilfs->ns_cptree_lock); 86 spin_lock_init(&nilfs->ns_cptree_lock);
87 init_rwsem(&nilfs->ns_segctor_sem); 87 init_rwsem(&nilfs->ns_segctor_sem);
88 nilfs->ns_sb_update_freq = NILFS_SB_FREQ;
88 89
89 return nilfs; 90 return nilfs;
90} 91}
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h
index 34bc7bd57b0b..7fe822307f98 100644
--- a/fs/nilfs2/the_nilfs.h
+++ b/fs/nilfs2/the_nilfs.h
@@ -33,6 +33,7 @@
33#include <linux/slab.h> 33#include <linux/slab.h>
34 34
35struct nilfs_sc_info; 35struct nilfs_sc_info;
36struct nilfs_sysfs_dev_subgroups;
36 37
37/* the_nilfs struct */ 38/* the_nilfs struct */
38enum { 39enum {
@@ -54,6 +55,7 @@ enum {
54 * @ns_sbwcount: write count of super block 55 * @ns_sbwcount: write count of super block
55 * @ns_sbsize: size of valid data in super block 56 * @ns_sbsize: size of valid data in super block
56 * @ns_mount_state: file system state 57 * @ns_mount_state: file system state
58 * @ns_sb_update_freq: interval of periodical update of superblocks (in seconds)
57 * @ns_seg_seq: segment sequence counter 59 * @ns_seg_seq: segment sequence counter
58 * @ns_segnum: index number of the latest full segment. 60 * @ns_segnum: index number of the latest full segment.
59 * @ns_nextnum: index number of the full segment index to be used next 61 * @ns_nextnum: index number of the full segment index to be used next
@@ -97,6 +99,7 @@ enum {
97 * @ns_crc_seed: seed value of CRC32 calculation 99 * @ns_crc_seed: seed value of CRC32 calculation
98 * @ns_dev_kobj: /sys/fs/<nilfs>/<device> 100 * @ns_dev_kobj: /sys/fs/<nilfs>/<device>
99 * @ns_dev_kobj_unregister: completion state 101 * @ns_dev_kobj_unregister: completion state
102 * @ns_dev_subgroups: <device> subgroups pointer
100 */ 103 */
101struct the_nilfs { 104struct the_nilfs {
102 unsigned long ns_flags; 105 unsigned long ns_flags;
@@ -116,6 +119,7 @@ struct the_nilfs {
116 unsigned ns_sbwcount; 119 unsigned ns_sbwcount;
117 unsigned ns_sbsize; 120 unsigned ns_sbsize;
118 unsigned ns_mount_state; 121 unsigned ns_mount_state;
122 unsigned ns_sb_update_freq;
119 123
120 /* 124 /*
121 * Following fields are dedicated to a writable FS-instance. 125 * Following fields are dedicated to a writable FS-instance.
@@ -194,6 +198,7 @@ struct the_nilfs {
194 /* /sys/fs/<nilfs>/<device> */ 198 /* /sys/fs/<nilfs>/<device> */
195 struct kobject ns_dev_kobj; 199 struct kobject ns_dev_kobj;
196 struct completion ns_dev_kobj_unregister; 200 struct completion ns_dev_kobj_unregister;
201 struct nilfs_sysfs_dev_subgroups *ns_dev_subgroups;
197}; 202};
198 203
199#define THE_NILFS_FNS(bit, name) \ 204#define THE_NILFS_FNS(bit, name) \
@@ -260,7 +265,8 @@ struct nilfs_root {
260static inline int nilfs_sb_need_update(struct the_nilfs *nilfs) 265static inline int nilfs_sb_need_update(struct the_nilfs *nilfs)
261{ 266{
262 u64 t = get_seconds(); 267 u64 t = get_seconds();
263 return t < nilfs->ns_sbwtime || t > nilfs->ns_sbwtime + NILFS_SB_FREQ; 268 return t < nilfs->ns_sbwtime ||
269 t > nilfs->ns_sbwtime + nilfs->ns_sb_update_freq;
264} 270}
265 271
266static inline int nilfs_sb_will_flip(struct the_nilfs *nilfs) 272static inline int nilfs_sb_will_flip(struct the_nilfs *nilfs)