Line data Source code
1 : /*
2 : * Copyright (C) 2007 Oracle. All rights reserved.
3 : *
4 : * This program is free software; you can redistribute it and/or
5 : * modify it under the terms of the GNU General Public
6 : * License v2 as published by the Free Software Foundation.
7 : *
8 : * This program is distributed in the hope that it will be useful,
9 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 : * General Public License for more details.
12 : *
13 : * You should have received a copy of the GNU General Public
14 : * License along with this program; if not, write to the
15 : * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 : * Boston, MA 021110-1307, USA.
17 : */
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/kobject.h>
25 : #include <linux/bug.h>
26 : #include <linux/genhd.h>
27 : #include <linux/debugfs.h>
28 :
29 : #include "ctree.h"
30 : #include "disk-io.h"
31 : #include "transaction.h"
32 : #include "sysfs.h"
33 : #include "volumes.h"
34 :
35 : static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj);
36 :
37 : static u64 get_features(struct btrfs_fs_info *fs_info,
38 : enum btrfs_feature_set set)
39 : {
40 : struct btrfs_super_block *disk_super = fs_info->super_copy;
41 3315 : if (set == FEAT_COMPAT)
42 : return btrfs_super_compat_flags(disk_super);
43 2873 : else if (set == FEAT_COMPAT_RO)
44 : return btrfs_super_compat_ro_flags(disk_super);
45 : else
46 : return btrfs_super_incompat_flags(disk_super);
47 : }
48 :
49 : static void set_features(struct btrfs_fs_info *fs_info,
50 : enum btrfs_feature_set set, u64 features)
51 : {
52 : struct btrfs_super_block *disk_super = fs_info->super_copy;
53 0 : if (set == FEAT_COMPAT)
54 : btrfs_set_super_compat_flags(disk_super, features);
55 0 : else if (set == FEAT_COMPAT_RO)
56 : btrfs_set_super_compat_ro_flags(disk_super, features);
57 : else
58 : btrfs_set_super_incompat_flags(disk_super, features);
59 : }
60 :
61 1989 : static int can_modify_feature(struct btrfs_feature_attr *fa)
62 : {
63 : int val = 0;
64 : u64 set, clear;
65 1989 : switch (fa->feature_set) {
66 : case FEAT_COMPAT:
67 : set = BTRFS_FEATURE_COMPAT_SAFE_SET;
68 : clear = BTRFS_FEATURE_COMPAT_SAFE_CLEAR;
69 : break;
70 : case FEAT_COMPAT_RO:
71 : set = BTRFS_FEATURE_COMPAT_RO_SAFE_SET;
72 : clear = BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR;
73 : break;
74 : case FEAT_INCOMPAT:
75 : set = BTRFS_FEATURE_INCOMPAT_SAFE_SET;
76 : clear = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR;
77 : break;
78 : default:
79 0 : printk(KERN_WARNING "btrfs: sysfs: unknown feature set %d\n",
80 : fa->feature_set);
81 : return 0;
82 : }
83 :
84 1989 : if (set & fa->feature_bit)
85 : val |= 1;
86 : if (clear & fa->feature_bit)
87 : val |= 2;
88 :
89 : return val;
90 : }
91 :
92 0 : static ssize_t btrfs_feature_attr_show(struct kobject *kobj,
93 : struct kobj_attribute *a, char *buf)
94 : {
95 : int val = 0;
96 0 : struct btrfs_fs_info *fs_info = to_fs_info(kobj);
97 0 : struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a);
98 0 : if (fs_info) {
99 0 : u64 features = get_features(fs_info, fa->feature_set);
100 0 : if (features & fa->feature_bit)
101 : val = 1;
102 : } else
103 0 : val = can_modify_feature(fa);
104 :
105 0 : return snprintf(buf, PAGE_SIZE, "%d\n", val);
106 : }
107 :
108 0 : static ssize_t btrfs_feature_attr_store(struct kobject *kobj,
109 : struct kobj_attribute *a,
110 : const char *buf, size_t count)
111 : {
112 0 : struct btrfs_fs_info *fs_info;
113 : struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a);
114 : struct btrfs_trans_handle *trans;
115 : u64 features, set, clear;
116 : unsigned long val;
117 : int ret;
118 :
119 : fs_info = to_fs_info(kobj);
120 0 : if (!fs_info)
121 : return -EPERM;
122 :
123 0 : ret = kstrtoul(skip_spaces(buf), 0, &val);
124 0 : if (ret)
125 0 : return ret;
126 :
127 0 : if (fa->feature_set == FEAT_COMPAT) {
128 : set = BTRFS_FEATURE_COMPAT_SAFE_SET;
129 : clear = BTRFS_FEATURE_COMPAT_SAFE_CLEAR;
130 0 : } else if (fa->feature_set == FEAT_COMPAT_RO) {
131 : set = BTRFS_FEATURE_COMPAT_RO_SAFE_SET;
132 : clear = BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR;
133 : } else {
134 : set = BTRFS_FEATURE_INCOMPAT_SAFE_SET;
135 : clear = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR;
136 : }
137 :
138 : features = get_features(fs_info, fa->feature_set);
139 :
140 : /* Nothing to do */
141 0 : if ((val && (features & fa->feature_bit)) ||
142 0 : (!val && !(features & fa->feature_bit)))
143 0 : return count;
144 :
145 0 : if ((val && !(set & fa->feature_bit)) ||
146 : (!val && !(clear & fa->feature_bit))) {
147 0 : btrfs_info(fs_info,
148 : "%sabling feature %s on mounted fs is not supported.",
149 : val ? "En" : "Dis", fa->kobj_attr.attr.name);
150 0 : return -EPERM;
151 : }
152 :
153 0 : btrfs_info(fs_info, "%s %s feature flag",
154 : val ? "Setting" : "Clearing", fa->kobj_attr.attr.name);
155 :
156 0 : trans = btrfs_start_transaction(fs_info->fs_root, 0);
157 0 : if (IS_ERR(trans))
158 0 : return PTR_ERR(trans);
159 :
160 : spin_lock(&fs_info->super_lock);
161 0 : features = get_features(fs_info, fa->feature_set);
162 0 : if (val)
163 0 : features |= fa->feature_bit;
164 : else
165 0 : features &= ~fa->feature_bit;
166 : set_features(fs_info, fa->feature_set, features);
167 : spin_unlock(&fs_info->super_lock);
168 :
169 0 : ret = btrfs_commit_transaction(trans, fs_info->fs_root);
170 0 : if (ret)
171 0 : return ret;
172 :
173 0 : return count;
174 : }
175 :
176 1989 : static umode_t btrfs_feature_visible(struct kobject *kobj,
177 : struct attribute *attr, int unused)
178 : {
179 1989 : struct btrfs_fs_info *fs_info = to_fs_info(kobj);
180 1989 : umode_t mode = attr->mode;
181 :
182 1989 : if (fs_info) {
183 : struct btrfs_feature_attr *fa;
184 : u64 features;
185 :
186 : fa = attr_to_btrfs_feature_attr(attr);
187 1989 : features = get_features(fs_info, fa->feature_set);
188 :
189 1989 : if (can_modify_feature(fa))
190 221 : mode |= S_IWUSR;
191 1768 : else if (!(features & fa->feature_bit))
192 : mode = 0;
193 : }
194 :
195 1989 : return mode;
196 : }
197 :
198 : BTRFS_FEAT_ATTR_INCOMPAT(mixed_backref, MIXED_BACKREF);
199 : BTRFS_FEAT_ATTR_INCOMPAT(default_subvol, DEFAULT_SUBVOL);
200 : BTRFS_FEAT_ATTR_INCOMPAT(mixed_groups, MIXED_GROUPS);
201 : BTRFS_FEAT_ATTR_INCOMPAT(compress_lzo, COMPRESS_LZO);
202 : BTRFS_FEAT_ATTR_INCOMPAT(big_metadata, BIG_METADATA);
203 : BTRFS_FEAT_ATTR_INCOMPAT(extended_iref, EXTENDED_IREF);
204 : BTRFS_FEAT_ATTR_INCOMPAT(raid56, RAID56);
205 : BTRFS_FEAT_ATTR_INCOMPAT(skinny_metadata, SKINNY_METADATA);
206 : BTRFS_FEAT_ATTR_INCOMPAT(no_holes, NO_HOLES);
207 :
208 : static struct attribute *btrfs_supported_feature_attrs[] = {
209 : BTRFS_FEAT_ATTR_PTR(mixed_backref),
210 : BTRFS_FEAT_ATTR_PTR(default_subvol),
211 : BTRFS_FEAT_ATTR_PTR(mixed_groups),
212 : BTRFS_FEAT_ATTR_PTR(compress_lzo),
213 : BTRFS_FEAT_ATTR_PTR(big_metadata),
214 : BTRFS_FEAT_ATTR_PTR(extended_iref),
215 : BTRFS_FEAT_ATTR_PTR(raid56),
216 : BTRFS_FEAT_ATTR_PTR(skinny_metadata),
217 : BTRFS_FEAT_ATTR_PTR(no_holes),
218 : NULL
219 : };
220 :
221 : static const struct attribute_group btrfs_feature_attr_group = {
222 : .name = "features",
223 : .is_visible = btrfs_feature_visible,
224 : .attrs = btrfs_supported_feature_attrs,
225 : };
226 :
227 0 : static ssize_t btrfs_show_u64(u64 *value_ptr, spinlock_t *lock, char *buf)
228 : {
229 : u64 val;
230 0 : if (lock)
231 : spin_lock(lock);
232 0 : val = *value_ptr;
233 0 : if (lock)
234 : spin_unlock(lock);
235 0 : return snprintf(buf, PAGE_SIZE, "%llu\n", val);
236 : }
237 :
238 0 : static ssize_t global_rsv_size_show(struct kobject *kobj,
239 : struct kobj_attribute *ka, char *buf)
240 : {
241 0 : struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent);
242 : struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv;
243 0 : return btrfs_show_u64(&block_rsv->size, &block_rsv->lock, buf);
244 : }
245 : BTRFS_ATTR(global_rsv_size, 0444, global_rsv_size_show);
246 :
247 0 : static ssize_t global_rsv_reserved_show(struct kobject *kobj,
248 : struct kobj_attribute *a, char *buf)
249 : {
250 0 : struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent);
251 : struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv;
252 0 : return btrfs_show_u64(&block_rsv->reserved, &block_rsv->lock, buf);
253 : }
254 : BTRFS_ATTR(global_rsv_reserved, 0444, global_rsv_reserved_show);
255 :
256 : #define to_space_info(_kobj) container_of(_kobj, struct btrfs_space_info, kobj)
257 : #define to_raid_kobj(_kobj) container_of(_kobj, struct raid_kobject, kobj)
258 :
259 : static ssize_t raid_bytes_show(struct kobject *kobj,
260 : struct kobj_attribute *attr, char *buf);
261 : BTRFS_RAID_ATTR(total_bytes, raid_bytes_show);
262 : BTRFS_RAID_ATTR(used_bytes, raid_bytes_show);
263 :
264 0 : static ssize_t raid_bytes_show(struct kobject *kobj,
265 : struct kobj_attribute *attr, char *buf)
266 :
267 : {
268 0 : struct btrfs_space_info *sinfo = to_space_info(kobj->parent);
269 : struct btrfs_block_group_cache *block_group;
270 0 : int index = to_raid_kobj(kobj)->raid_type;
271 : u64 val = 0;
272 :
273 0 : down_read(&sinfo->groups_sem);
274 0 : list_for_each_entry(block_group, &sinfo->block_groups[index], list) {
275 0 : if (&attr->attr == BTRFS_RAID_ATTR_PTR(total_bytes))
276 0 : val += block_group->key.offset;
277 : else
278 0 : val += btrfs_block_group_used(&block_group->item);
279 : }
280 0 : up_read(&sinfo->groups_sem);
281 0 : return snprintf(buf, PAGE_SIZE, "%llu\n", val);
282 : }
283 :
284 : static struct attribute *raid_attributes[] = {
285 : BTRFS_RAID_ATTR_PTR(total_bytes),
286 : BTRFS_RAID_ATTR_PTR(used_bytes),
287 : NULL
288 : };
289 :
290 1090 : static void release_raid_kobj(struct kobject *kobj)
291 : {
292 1090 : kfree(to_raid_kobj(kobj));
293 1090 : }
294 :
295 : struct kobj_type btrfs_raid_ktype = {
296 : .sysfs_ops = &kobj_sysfs_ops,
297 : .release = release_raid_kobj,
298 : .default_attrs = raid_attributes,
299 : };
300 :
301 : #define SPACE_INFO_ATTR(field) \
302 : static ssize_t btrfs_space_info_show_##field(struct kobject *kobj, \
303 : struct kobj_attribute *a, \
304 : char *buf) \
305 : { \
306 : struct btrfs_space_info *sinfo = to_space_info(kobj); \
307 : return btrfs_show_u64(&sinfo->field, &sinfo->lock, buf); \
308 : } \
309 : BTRFS_ATTR(field, 0444, btrfs_space_info_show_##field)
310 :
311 0 : static ssize_t btrfs_space_info_show_total_bytes_pinned(struct kobject *kobj,
312 : struct kobj_attribute *a,
313 : char *buf)
314 : {
315 : struct btrfs_space_info *sinfo = to_space_info(kobj);
316 0 : s64 val = percpu_counter_sum(&sinfo->total_bytes_pinned);
317 0 : return snprintf(buf, PAGE_SIZE, "%lld\n", val);
318 : }
319 :
320 0 : SPACE_INFO_ATTR(flags);
321 0 : SPACE_INFO_ATTR(total_bytes);
322 0 : SPACE_INFO_ATTR(bytes_used);
323 0 : SPACE_INFO_ATTR(bytes_pinned);
324 0 : SPACE_INFO_ATTR(bytes_reserved);
325 0 : SPACE_INFO_ATTR(bytes_may_use);
326 0 : SPACE_INFO_ATTR(disk_used);
327 0 : SPACE_INFO_ATTR(disk_total);
328 : BTRFS_ATTR(total_bytes_pinned, 0444, btrfs_space_info_show_total_bytes_pinned);
329 :
330 : static struct attribute *space_info_attrs[] = {
331 : BTRFS_ATTR_PTR(flags),
332 : BTRFS_ATTR_PTR(total_bytes),
333 : BTRFS_ATTR_PTR(bytes_used),
334 : BTRFS_ATTR_PTR(bytes_pinned),
335 : BTRFS_ATTR_PTR(bytes_reserved),
336 : BTRFS_ATTR_PTR(bytes_may_use),
337 : BTRFS_ATTR_PTR(disk_used),
338 : BTRFS_ATTR_PTR(disk_total),
339 : BTRFS_ATTR_PTR(total_bytes_pinned),
340 : NULL,
341 : };
342 :
343 657 : static void space_info_release(struct kobject *kobj)
344 : {
345 657 : struct btrfs_space_info *sinfo = to_space_info(kobj);
346 657 : percpu_counter_destroy(&sinfo->total_bytes_pinned);
347 657 : kfree(sinfo);
348 657 : }
349 :
350 : struct kobj_type space_info_ktype = {
351 : .sysfs_ops = &kobj_sysfs_ops,
352 : .release = space_info_release,
353 : .default_attrs = space_info_attrs,
354 : };
355 :
356 : static const struct attribute *allocation_attrs[] = {
357 : BTRFS_ATTR_PTR(global_rsv_reserved),
358 : BTRFS_ATTR_PTR(global_rsv_size),
359 : NULL,
360 : };
361 :
362 0 : static ssize_t btrfs_label_show(struct kobject *kobj,
363 : struct kobj_attribute *a, char *buf)
364 : {
365 : struct btrfs_fs_info *fs_info = to_fs_info(kobj);
366 0 : return snprintf(buf, PAGE_SIZE, "%s\n", fs_info->super_copy->label);
367 : }
368 :
369 0 : static ssize_t btrfs_label_store(struct kobject *kobj,
370 : struct kobj_attribute *a,
371 : const char *buf, size_t len)
372 : {
373 : struct btrfs_fs_info *fs_info = to_fs_info(kobj);
374 : struct btrfs_trans_handle *trans;
375 0 : struct btrfs_root *root = fs_info->fs_root;
376 : int ret;
377 :
378 0 : if (len >= BTRFS_LABEL_SIZE)
379 : return -EINVAL;
380 :
381 0 : trans = btrfs_start_transaction(root, 0);
382 0 : if (IS_ERR(trans))
383 0 : return PTR_ERR(trans);
384 :
385 0 : spin_lock(&root->fs_info->super_lock);
386 0 : strcpy(fs_info->super_copy->label, buf);
387 0 : spin_unlock(&root->fs_info->super_lock);
388 0 : ret = btrfs_commit_transaction(trans, root);
389 :
390 0 : if (!ret)
391 0 : return len;
392 :
393 0 : return ret;
394 : }
395 : BTRFS_ATTR_RW(label, 0644, btrfs_label_show, btrfs_label_store);
396 :
397 0 : static ssize_t btrfs_no_store(struct kobject *kobj,
398 : struct kobj_attribute *a,
399 : const char *buf, size_t len)
400 : {
401 0 : return -EPERM;
402 : }
403 :
404 0 : static ssize_t btrfs_nodesize_show(struct kobject *kobj,
405 : struct kobj_attribute *a, char *buf)
406 : {
407 : struct btrfs_fs_info *fs_info = to_fs_info(kobj);
408 :
409 0 : return snprintf(buf, PAGE_SIZE, "%u\n", fs_info->super_copy->nodesize);
410 : }
411 :
412 : BTRFS_ATTR_RW(nodesize, 0444, btrfs_nodesize_show, btrfs_no_store);
413 :
414 0 : static ssize_t btrfs_sectorsize_show(struct kobject *kobj,
415 : struct kobj_attribute *a, char *buf)
416 : {
417 : struct btrfs_fs_info *fs_info = to_fs_info(kobj);
418 :
419 0 : return snprintf(buf, PAGE_SIZE, "%u\n", fs_info->super_copy->sectorsize);
420 : }
421 :
422 : BTRFS_ATTR_RW(sectorsize, 0444, btrfs_sectorsize_show, btrfs_no_store);
423 :
424 0 : static ssize_t btrfs_clone_alignment_show(struct kobject *kobj,
425 : struct kobj_attribute *a, char *buf)
426 : {
427 : struct btrfs_fs_info *fs_info = to_fs_info(kobj);
428 :
429 0 : return snprintf(buf, PAGE_SIZE, "%u\n", fs_info->super_copy->sectorsize);
430 : }
431 :
432 : BTRFS_ATTR_RW(clone_alignment, 0444, btrfs_clone_alignment_show, btrfs_no_store);
433 :
434 : static struct attribute *btrfs_attrs[] = {
435 : BTRFS_ATTR_PTR(label),
436 : BTRFS_ATTR_PTR(nodesize),
437 : BTRFS_ATTR_PTR(sectorsize),
438 : BTRFS_ATTR_PTR(clone_alignment),
439 : NULL,
440 : };
441 :
442 221 : static void btrfs_release_super_kobj(struct kobject *kobj)
443 : {
444 : struct btrfs_fs_info *fs_info = to_fs_info(kobj);
445 221 : complete(&fs_info->kobj_unregister);
446 221 : }
447 :
448 : static struct kobj_type btrfs_ktype = {
449 : .sysfs_ops = &kobj_sysfs_ops,
450 : .release = btrfs_release_super_kobj,
451 : .default_attrs = btrfs_attrs,
452 : };
453 :
454 : static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj)
455 : {
456 2210 : if (kobj->ktype != &btrfs_ktype)
457 : return NULL;
458 2210 : return container_of(kobj, struct btrfs_fs_info, super_kobj);
459 : }
460 :
461 : #define NUM_FEATURE_BITS 64
462 : static char btrfs_unknown_feature_names[3][NUM_FEATURE_BITS][13];
463 : static struct btrfs_feature_attr btrfs_feature_attrs[3][NUM_FEATURE_BITS];
464 :
465 : static u64 supported_feature_masks[3] = {
466 : [FEAT_COMPAT] = BTRFS_FEATURE_COMPAT_SUPP,
467 : [FEAT_COMPAT_RO] = BTRFS_FEATURE_COMPAT_RO_SUPP,
468 : [FEAT_INCOMPAT] = BTRFS_FEATURE_INCOMPAT_SUPP,
469 : };
470 :
471 1768 : static int addrm_unknown_feature_attrs(struct btrfs_fs_info *fs_info, bool add)
472 : {
473 : int set;
474 :
475 1768 : for (set = 0; set < FEAT_MAX; set++) {
476 : int i;
477 : struct attribute *attrs[2];
478 1326 : struct attribute_group agroup = {
479 : .name = "features",
480 : .attrs = attrs,
481 : };
482 1326 : u64 features = get_features(fs_info, set);
483 1326 : features &= ~supported_feature_masks[set];
484 :
485 1326 : if (!features)
486 1326 : continue;
487 :
488 0 : attrs[1] = NULL;
489 0 : for (i = 0; i < NUM_FEATURE_BITS; i++) {
490 : struct btrfs_feature_attr *fa;
491 :
492 0 : if (!(features & (1ULL << i)))
493 0 : continue;
494 :
495 0 : fa = &btrfs_feature_attrs[set][i];
496 0 : attrs[0] = &fa->kobj_attr.attr;
497 0 : if (add) {
498 : int ret;
499 0 : ret = sysfs_merge_group(&fs_info->super_kobj,
500 : &agroup);
501 0 : if (ret)
502 0 : return ret;
503 : } else
504 0 : sysfs_unmerge_group(&fs_info->super_kobj,
505 : &agroup);
506 : }
507 :
508 : }
509 : return 0;
510 : }
511 :
512 221 : static void __btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info)
513 : {
514 221 : kobject_del(&fs_info->super_kobj);
515 221 : kobject_put(&fs_info->super_kobj);
516 221 : wait_for_completion(&fs_info->kobj_unregister);
517 221 : }
518 :
519 221 : void btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info)
520 : {
521 221 : if (fs_info->space_info_kobj) {
522 221 : sysfs_remove_files(fs_info->space_info_kobj, allocation_attrs);
523 221 : kobject_del(fs_info->space_info_kobj);
524 221 : kobject_put(fs_info->space_info_kobj);
525 : }
526 221 : kobject_del(fs_info->device_dir_kobj);
527 221 : kobject_put(fs_info->device_dir_kobj);
528 221 : addrm_unknown_feature_attrs(fs_info, false);
529 221 : sysfs_remove_group(&fs_info->super_kobj, &btrfs_feature_attr_group);
530 221 : __btrfs_sysfs_remove_one(fs_info);
531 221 : }
532 :
533 : const char * const btrfs_feature_set_names[3] = {
534 : [FEAT_COMPAT] = "compat",
535 : [FEAT_COMPAT_RO] = "compat_ro",
536 : [FEAT_INCOMPAT] = "incompat",
537 : };
538 :
539 0 : char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags)
540 : {
541 : size_t bufsize = 4096; /* safe max, 64 names * 64 bytes */
542 : int len = 0;
543 : int i;
544 : char *str;
545 :
546 : str = kmalloc(bufsize, GFP_KERNEL);
547 0 : if (!str)
548 : return str;
549 :
550 0 : for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) {
551 : const char *name;
552 :
553 0 : if (!(flags & (1ULL << i)))
554 0 : continue;
555 :
556 0 : name = btrfs_feature_attrs[set][i].kobj_attr.attr.name;
557 0 : len += snprintf(str + len, bufsize - len, "%s%s",
558 : len ? "," : "", name);
559 : }
560 :
561 : return str;
562 : }
563 :
564 0 : static void init_feature_attrs(void)
565 : {
566 : struct btrfs_feature_attr *fa;
567 : int set, i;
568 :
569 : BUILD_BUG_ON(ARRAY_SIZE(btrfs_unknown_feature_names) !=
570 : ARRAY_SIZE(btrfs_feature_attrs));
571 : BUILD_BUG_ON(ARRAY_SIZE(btrfs_unknown_feature_names[0]) !=
572 : ARRAY_SIZE(btrfs_feature_attrs[0]));
573 :
574 0 : memset(btrfs_feature_attrs, 0, sizeof(btrfs_feature_attrs));
575 0 : memset(btrfs_unknown_feature_names, 0,
576 : sizeof(btrfs_unknown_feature_names));
577 :
578 0 : for (i = 0; btrfs_supported_feature_attrs[i]; i++) {
579 : struct btrfs_feature_attr *sfa;
580 : struct attribute *a = btrfs_supported_feature_attrs[i];
581 : int bit;
582 : sfa = attr_to_btrfs_feature_attr(a);
583 0 : bit = ilog2(sfa->feature_bit);
584 0 : fa = &btrfs_feature_attrs[sfa->feature_set][bit];
585 :
586 0 : fa->kobj_attr.attr.name = sfa->kobj_attr.attr.name;
587 : }
588 :
589 0 : for (set = 0; set < FEAT_MAX; set++) {
590 0 : for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) {
591 0 : char *name = btrfs_unknown_feature_names[set][i];
592 0 : fa = &btrfs_feature_attrs[set][i];
593 :
594 0 : if (fa->kobj_attr.attr.name)
595 0 : continue;
596 :
597 0 : snprintf(name, 13, "%s:%u",
598 : btrfs_feature_set_names[set], i);
599 :
600 0 : fa->kobj_attr.attr.name = name;
601 0 : fa->kobj_attr.attr.mode = S_IRUGO;
602 0 : fa->feature_set = set;
603 0 : fa->feature_bit = 1ULL << i;
604 : }
605 : }
606 0 : }
607 :
608 7 : int btrfs_kobj_rm_device(struct btrfs_fs_info *fs_info,
609 : struct btrfs_device *one_device)
610 : {
611 : struct hd_struct *disk;
612 : struct kobject *disk_kobj;
613 :
614 7 : if (!fs_info->device_dir_kobj)
615 : return -EINVAL;
616 :
617 7 : if (one_device && one_device->bdev) {
618 7 : disk = one_device->bdev->bd_part;
619 : disk_kobj = &part_to_dev(disk)->kobj;
620 :
621 7 : sysfs_remove_link(fs_info->device_dir_kobj,
622 : disk_kobj->name);
623 : }
624 :
625 : return 0;
626 : }
627 :
628 228 : int btrfs_kobj_add_device(struct btrfs_fs_info *fs_info,
629 : struct btrfs_device *one_device)
630 : {
631 : int error = 0;
632 228 : struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
633 : struct btrfs_device *dev;
634 :
635 228 : if (!fs_info->device_dir_kobj)
636 221 : fs_info->device_dir_kobj = kobject_create_and_add("devices",
637 : &fs_info->super_kobj);
638 :
639 228 : if (!fs_info->device_dir_kobj)
640 : return -ENOMEM;
641 :
642 493 : list_for_each_entry(dev, &fs_devices->devices, dev_list) {
643 : struct hd_struct *disk;
644 : struct kobject *disk_kobj;
645 :
646 265 : if (!dev->bdev)
647 0 : continue;
648 :
649 265 : if (one_device && one_device != dev)
650 10 : continue;
651 :
652 255 : disk = dev->bdev->bd_part;
653 255 : disk_kobj = &part_to_dev(disk)->kobj;
654 :
655 255 : error = sysfs_create_link(fs_info->device_dir_kobj,
656 : disk_kobj, disk_kobj->name);
657 255 : if (error)
658 : break;
659 : }
660 :
661 228 : return error;
662 : }
663 :
664 : /* /sys/fs/btrfs/ entry */
665 : static struct kset *btrfs_kset;
666 :
667 : /* /sys/kernel/debug/btrfs */
668 : static struct dentry *btrfs_debugfs_root_dentry;
669 :
670 : /* Debugging tunables and exported data */
671 : u64 btrfs_debugfs_test;
672 :
673 221 : int btrfs_sysfs_add_one(struct btrfs_fs_info *fs_info)
674 : {
675 : int error;
676 :
677 : init_completion(&fs_info->kobj_unregister);
678 221 : fs_info->super_kobj.kset = btrfs_kset;
679 221 : error = kobject_init_and_add(&fs_info->super_kobj, &btrfs_ktype, NULL,
680 221 : "%pU", fs_info->fsid);
681 221 : if (error)
682 : return error;
683 :
684 221 : error = sysfs_create_group(&fs_info->super_kobj,
685 : &btrfs_feature_attr_group);
686 221 : if (error) {
687 0 : __btrfs_sysfs_remove_one(fs_info);
688 0 : return error;
689 : }
690 :
691 221 : error = addrm_unknown_feature_attrs(fs_info, true);
692 221 : if (error)
693 : goto failure;
694 :
695 221 : error = btrfs_kobj_add_device(fs_info, NULL);
696 221 : if (error)
697 : goto failure;
698 :
699 221 : fs_info->space_info_kobj = kobject_create_and_add("allocation",
700 : &fs_info->super_kobj);
701 221 : if (!fs_info->space_info_kobj) {
702 : error = -ENOMEM;
703 : goto failure;
704 : }
705 :
706 221 : error = sysfs_create_files(fs_info->space_info_kobj, allocation_attrs);
707 221 : if (error)
708 : goto failure;
709 :
710 : return 0;
711 : failure:
712 0 : btrfs_sysfs_remove_one(fs_info);
713 0 : return error;
714 : }
715 :
716 0 : static int btrfs_init_debugfs(void)
717 : {
718 : #ifdef CONFIG_DEBUG_FS
719 0 : btrfs_debugfs_root_dentry = debugfs_create_dir("btrfs", NULL);
720 0 : if (!btrfs_debugfs_root_dentry)
721 : return -ENOMEM;
722 :
723 0 : debugfs_create_u64("test", S_IRUGO | S_IWUGO, btrfs_debugfs_root_dentry,
724 : &btrfs_debugfs_test);
725 : #endif
726 0 : return 0;
727 : }
728 :
729 0 : int btrfs_init_sysfs(void)
730 : {
731 : int ret;
732 :
733 0 : btrfs_kset = kset_create_and_add("btrfs", NULL, fs_kobj);
734 0 : if (!btrfs_kset)
735 : return -ENOMEM;
736 :
737 0 : ret = btrfs_init_debugfs();
738 0 : if (ret)
739 : return ret;
740 :
741 0 : init_feature_attrs();
742 0 : ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_feature_attr_group);
743 :
744 0 : return ret;
745 : }
746 :
747 0 : void btrfs_exit_sysfs(void)
748 : {
749 0 : sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group);
750 0 : kset_unregister(btrfs_kset);
751 0 : debugfs_remove_recursive(btrfs_debugfs_root_dentry);
752 0 : }
753 :
|