diff options
Diffstat (limited to 'fs/btrfs/sysfs.c')
-rw-r--r-- | fs/btrfs/sysfs.c | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index db8917e5b256..2058783373eb 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c | |||
@@ -16,6 +16,242 @@ | |||
16 | * Boston, MA 021110-1307, USA. | 16 | * Boston, MA 021110-1307, USA. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/spinlock.h> | ||
22 | #include <linux/completion.h> | ||
23 | #include <linux/buffer_head.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/kobject.h> | ||
26 | |||
19 | #include "ctree.h" | 27 | #include "ctree.h" |
20 | #include "disk-io.h" | 28 | #include "disk-io.h" |
21 | #include "transaction.h" | 29 | #include "transaction.h" |
30 | |||
31 | static ssize_t root_blocks_used_show(struct btrfs_root *root, char *buf) | ||
32 | { | ||
33 | return snprintf(buf, PAGE_SIZE, "%llu\n", | ||
34 | (unsigned long long)btrfs_root_blocks_used(&root->root_item)); | ||
35 | } | ||
36 | |||
37 | static ssize_t root_block_limit_show(struct btrfs_root *root, char *buf) | ||
38 | { | ||
39 | return snprintf(buf, PAGE_SIZE, "%llu\n", | ||
40 | (unsigned long long)btrfs_root_block_limit(&root->root_item)); | ||
41 | } | ||
42 | |||
43 | static ssize_t super_blocks_used_show(struct btrfs_fs_info *fs, char *buf) | ||
44 | { | ||
45 | return snprintf(buf, PAGE_SIZE, "%llu\n", | ||
46 | (unsigned long long)btrfs_super_blocks_used(fs->disk_super)); | ||
47 | } | ||
48 | |||
49 | static ssize_t super_total_blocks_show(struct btrfs_fs_info *fs, char *buf) | ||
50 | { | ||
51 | return snprintf(buf, PAGE_SIZE, "%llu\n", | ||
52 | (unsigned long long)btrfs_super_total_blocks(fs->disk_super)); | ||
53 | } | ||
54 | |||
55 | static ssize_t super_blocksize_show(struct btrfs_fs_info *fs, char *buf) | ||
56 | { | ||
57 | return snprintf(buf, PAGE_SIZE, "%llu\n", | ||
58 | (unsigned long long)btrfs_super_blocksize(fs->disk_super)); | ||
59 | } | ||
60 | |||
61 | /* this is for root attrs (subvols/snapshots) */ | ||
62 | struct btrfs_root_attr { | ||
63 | struct attribute attr; | ||
64 | ssize_t (*show)(struct btrfs_root *, char *); | ||
65 | ssize_t (*store)(struct btrfs_root *, const char *, size_t); | ||
66 | }; | ||
67 | |||
68 | #define ROOT_ATTR(name, mode, show, store) \ | ||
69 | static struct btrfs_root_attr btrfs_root_attr_##name = __ATTR(name, mode, show, store) | ||
70 | |||
71 | ROOT_ATTR(blocks_used, 0444, root_blocks_used_show, NULL); | ||
72 | ROOT_ATTR(block_limit, 0644, root_block_limit_show, NULL); | ||
73 | |||
74 | static struct attribute *btrfs_root_attrs[] = { | ||
75 | &btrfs_root_attr_blocks_used.attr, | ||
76 | &btrfs_root_attr_block_limit.attr, | ||
77 | NULL, | ||
78 | }; | ||
79 | |||
80 | /* this is for super attrs (actual full fs) */ | ||
81 | struct btrfs_super_attr { | ||
82 | struct attribute attr; | ||
83 | ssize_t (*show)(struct btrfs_fs_info *, char *); | ||
84 | ssize_t (*store)(struct btrfs_fs_info *, const char *, size_t); | ||
85 | }; | ||
86 | |||
87 | #define SUPER_ATTR(name, mode, show, store) \ | ||
88 | static struct btrfs_super_attr btrfs_super_attr_##name = __ATTR(name, mode, show, store) | ||
89 | |||
90 | SUPER_ATTR(blocks_used, 0444, super_blocks_used_show, NULL); | ||
91 | SUPER_ATTR(total_blocks, 0444, super_total_blocks_show, NULL); | ||
92 | SUPER_ATTR(blocksize, 0444, super_blocksize_show, NULL); | ||
93 | |||
94 | static struct attribute *btrfs_super_attrs[] = { | ||
95 | &btrfs_super_attr_blocks_used.attr, | ||
96 | &btrfs_super_attr_total_blocks.attr, | ||
97 | &btrfs_super_attr_blocksize.attr, | ||
98 | NULL, | ||
99 | }; | ||
100 | |||
101 | static ssize_t btrfs_super_attr_show(struct kobject *kobj, | ||
102 | struct attribute *attr, char *buf) | ||
103 | { | ||
104 | struct btrfs_fs_info *fs = container_of(kobj, struct btrfs_fs_info, | ||
105 | super_kobj); | ||
106 | struct btrfs_super_attr *a = container_of(attr, | ||
107 | struct btrfs_super_attr, | ||
108 | attr); | ||
109 | |||
110 | return a->show ? a->show(fs, buf) : 0; | ||
111 | } | ||
112 | |||
113 | static ssize_t btrfs_super_attr_store(struct kobject *kobj, | ||
114 | struct attribute *attr, | ||
115 | const char *buf, size_t len) | ||
116 | { | ||
117 | struct btrfs_fs_info *fs = container_of(kobj, struct btrfs_fs_info, | ||
118 | super_kobj); | ||
119 | struct btrfs_super_attr *a = container_of(attr, | ||
120 | struct btrfs_super_attr, | ||
121 | attr); | ||
122 | |||
123 | return a->store ? a->store(fs, buf, len) : 0; | ||
124 | } | ||
125 | |||
126 | static ssize_t btrfs_root_attr_show(struct kobject *kobj, | ||
127 | struct attribute *attr, char *buf) | ||
128 | { | ||
129 | struct btrfs_root *root = container_of(kobj, struct btrfs_root, | ||
130 | root_kobj); | ||
131 | struct btrfs_root_attr *a = container_of(attr, | ||
132 | struct btrfs_root_attr, | ||
133 | attr); | ||
134 | |||
135 | return a->show ? a->show(root, buf) : 0; | ||
136 | } | ||
137 | |||
138 | static ssize_t btrfs_root_attr_store(struct kobject *kobj, | ||
139 | struct attribute *attr, | ||
140 | const char *buf, size_t len) | ||
141 | { | ||
142 | struct btrfs_root *root = container_of(kobj, struct btrfs_root, | ||
143 | root_kobj); | ||
144 | struct btrfs_root_attr *a = container_of(attr, | ||
145 | struct btrfs_root_attr, | ||
146 | attr); | ||
147 | return a->store ? a->store(root, buf, len) : 0; | ||
148 | } | ||
149 | |||
150 | static void btrfs_super_release(struct kobject *kobj) | ||
151 | { | ||
152 | struct btrfs_fs_info *fs = container_of(kobj, struct btrfs_fs_info, | ||
153 | super_kobj); | ||
154 | complete(&fs->kobj_unregister); | ||
155 | } | ||
156 | |||
157 | static void btrfs_root_release(struct kobject *kobj) | ||
158 | { | ||
159 | struct btrfs_root *root = container_of(kobj, struct btrfs_root, | ||
160 | root_kobj); | ||
161 | complete(&root->kobj_unregister); | ||
162 | } | ||
163 | |||
164 | static struct sysfs_ops btrfs_super_attr_ops = { | ||
165 | .show = btrfs_super_attr_show, | ||
166 | .store = btrfs_super_attr_store, | ||
167 | }; | ||
168 | |||
169 | static struct sysfs_ops btrfs_root_attr_ops = { | ||
170 | .show = btrfs_root_attr_show, | ||
171 | .store = btrfs_root_attr_store, | ||
172 | }; | ||
173 | |||
174 | static struct kobj_type btrfs_root_ktype = { | ||
175 | .default_attrs = btrfs_root_attrs, | ||
176 | .sysfs_ops = &btrfs_root_attr_ops, | ||
177 | .release = btrfs_root_release, | ||
178 | }; | ||
179 | |||
180 | static struct kobj_type btrfs_super_ktype = { | ||
181 | .default_attrs = btrfs_super_attrs, | ||
182 | .sysfs_ops = &btrfs_super_attr_ops, | ||
183 | .release = btrfs_super_release, | ||
184 | }; | ||
185 | |||
186 | static struct kset btrfs_kset = { | ||
187 | .kobj = {.name = "btrfs"}, | ||
188 | }; | ||
189 | |||
190 | int btrfs_sysfs_add_super(struct btrfs_fs_info *fs) | ||
191 | { | ||
192 | int error; | ||
193 | |||
194 | fs->super_kobj.kset = &btrfs_kset; | ||
195 | fs->super_kobj.ktype = &btrfs_super_ktype; | ||
196 | |||
197 | error = kobject_set_name(&fs->super_kobj, "%s", | ||
198 | fs->sb->s_id); | ||
199 | if (error) | ||
200 | goto fail; | ||
201 | |||
202 | error = kobject_register(&fs->super_kobj); | ||
203 | if (error) | ||
204 | goto fail; | ||
205 | |||
206 | return 0; | ||
207 | |||
208 | fail: | ||
209 | printk(KERN_ERR "btrfs: sysfs creation for super failed\n"); | ||
210 | return error; | ||
211 | } | ||
212 | |||
213 | int btrfs_sysfs_add_root(struct btrfs_root *root) | ||
214 | { | ||
215 | int error; | ||
216 | |||
217 | root->root_kobj.ktype = &btrfs_root_ktype; | ||
218 | root->root_kobj.parent = &root->fs_info->super_kobj; | ||
219 | |||
220 | error = kobject_set_name(&root->root_kobj, "%s", root->name); | ||
221 | if (error) { | ||
222 | goto fail; | ||
223 | } | ||
224 | |||
225 | error = kobject_register(&root->root_kobj); | ||
226 | if (error) | ||
227 | goto fail; | ||
228 | |||
229 | return 0; | ||
230 | |||
231 | fail: | ||
232 | printk(KERN_ERR "btrfs: sysfs creation for root failed\n"); | ||
233 | return error; | ||
234 | } | ||
235 | |||
236 | void btrfs_sysfs_del_root(struct btrfs_root *root) | ||
237 | { | ||
238 | kobject_unregister(&root->root_kobj); | ||
239 | wait_for_completion(&root->kobj_unregister); | ||
240 | } | ||
241 | |||
242 | void btrfs_sysfs_del_super(struct btrfs_fs_info *fs) | ||
243 | { | ||
244 | kobject_unregister(&fs->super_kobj); | ||
245 | wait_for_completion(&fs->kobj_unregister); | ||
246 | } | ||
247 | |||
248 | int btrfs_init_sysfs() | ||
249 | { | ||
250 | kobj_set_kset_s(&btrfs_kset, fs_subsys); | ||
251 | return kset_register(&btrfs_kset); | ||
252 | } | ||
253 | |||
254 | void btrfs_exit_sysfs() | ||
255 | { | ||
256 | kset_unregister(&btrfs_kset); | ||
257 | } | ||