aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/ctree.h5
-rw-r--r--fs/btrfs/extent-tree.c82
-rw-r--r--fs/btrfs/sysfs.c148
-rw-r--r--fs/btrfs/sysfs.h8
4 files changed, 238 insertions, 5 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index c5c888fbf033..f608306b5d88 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1151,6 +1151,9 @@ struct btrfs_space_info {
1151 spinlock_t lock; 1151 spinlock_t lock;
1152 struct rw_semaphore groups_sem; 1152 struct rw_semaphore groups_sem;
1153 wait_queue_head_t wait; 1153 wait_queue_head_t wait;
1154
1155 struct kobject kobj;
1156 struct kobject block_group_kobjs[BTRFS_NR_RAID_TYPES];
1154}; 1157};
1155 1158
1156#define BTRFS_BLOCK_RSV_GLOBAL 1 1159#define BTRFS_BLOCK_RSV_GLOBAL 1
@@ -1526,6 +1529,7 @@ struct btrfs_fs_info {
1526 int thread_pool_size; 1529 int thread_pool_size;
1527 1530
1528 struct kobject super_kobj; 1531 struct kobject super_kobj;
1532 struct kobject *space_info_kobj;
1529 struct completion kobj_unregister; 1533 struct completion kobj_unregister;
1530 int do_barriers; 1534 int do_barriers;
1531 int closing; 1535 int closing;
@@ -3178,6 +3182,7 @@ struct btrfs_block_group_cache *btrfs_lookup_block_group(
3178 struct btrfs_fs_info *info, 3182 struct btrfs_fs_info *info,
3179 u64 bytenr); 3183 u64 bytenr);
3180void btrfs_put_block_group(struct btrfs_block_group_cache *cache); 3184void btrfs_put_block_group(struct btrfs_block_group_cache *cache);
3185int get_block_group_index(struct btrfs_block_group_cache *cache);
3181struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, 3186struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
3182 struct btrfs_root *root, u32 blocksize, 3187 struct btrfs_root *root, u32 blocksize,
3183 u64 parent, u64 root_objectid, 3188 u64 parent, u64 root_objectid,
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index d15b4fc07554..e094d02ea76a 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -35,6 +35,7 @@
35#include "locking.h" 35#include "locking.h"
36#include "free-space-cache.h" 36#include "free-space-cache.h"
37#include "math.h" 37#include "math.h"
38#include "sysfs.h"
38 39
39#undef SCRAMBLE_DELAYED_REFS 40#undef SCRAMBLE_DELAYED_REFS
40 41
@@ -3408,6 +3409,23 @@ int btrfs_extent_readonly(struct btrfs_root *root, u64 bytenr)
3408 return readonly; 3409 return readonly;
3409} 3410}
3410 3411
3412static const char *alloc_name(u64 flags)
3413{
3414 switch (flags) {
3415 case BTRFS_BLOCK_GROUP_METADATA|BTRFS_BLOCK_GROUP_DATA:
3416 return "mixed";
3417 case BTRFS_BLOCK_GROUP_METADATA:
3418 return "metadata";
3419 case BTRFS_BLOCK_GROUP_DATA:
3420 return "data";
3421 case BTRFS_BLOCK_GROUP_SYSTEM:
3422 return "system";
3423 default:
3424 WARN_ON(1);
3425 return "invalid-combination";
3426 };
3427}
3428
3411static int update_space_info(struct btrfs_fs_info *info, u64 flags, 3429static int update_space_info(struct btrfs_fs_info *info, u64 flags,
3412 u64 total_bytes, u64 bytes_used, 3430 u64 total_bytes, u64 bytes_used,
3413 struct btrfs_space_info **space_info) 3431 struct btrfs_space_info **space_info)
@@ -3463,11 +3481,21 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags,
3463 found->chunk_alloc = 0; 3481 found->chunk_alloc = 0;
3464 found->flush = 0; 3482 found->flush = 0;
3465 init_waitqueue_head(&found->wait); 3483 init_waitqueue_head(&found->wait);
3484
3485 ret = kobject_init_and_add(&found->kobj, &space_info_ktype,
3486 info->space_info_kobj, "%s",
3487 alloc_name(found->flags));
3488 if (ret) {
3489 kfree(found);
3490 return ret;
3491 }
3492
3466 *space_info = found; 3493 *space_info = found;
3467 list_add_rcu(&found->list, &info->space_info); 3494 list_add_rcu(&found->list, &info->space_info);
3468 if (flags & BTRFS_BLOCK_GROUP_DATA) 3495 if (flags & BTRFS_BLOCK_GROUP_DATA)
3469 info->data_sinfo = found; 3496 info->data_sinfo = found;
3470 return 0; 3497
3498 return ret;
3471} 3499}
3472 3500
3473static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) 3501static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags)
@@ -6152,11 +6180,29 @@ int __get_raid_index(u64 flags)
6152 return BTRFS_RAID_SINGLE; /* BTRFS_BLOCK_GROUP_SINGLE */ 6180 return BTRFS_RAID_SINGLE; /* BTRFS_BLOCK_GROUP_SINGLE */
6153} 6181}
6154 6182
6155static int get_block_group_index(struct btrfs_block_group_cache *cache) 6183int get_block_group_index(struct btrfs_block_group_cache *cache)
6156{ 6184{
6157 return __get_raid_index(cache->flags); 6185 return __get_raid_index(cache->flags);
6158} 6186}
6159 6187
6188static const char *btrfs_raid_type_names[BTRFS_NR_RAID_TYPES] = {
6189 [BTRFS_RAID_RAID10] = "raid10",
6190 [BTRFS_RAID_RAID1] = "raid1",
6191 [BTRFS_RAID_DUP] = "dup",
6192 [BTRFS_RAID_RAID0] = "raid0",
6193 [BTRFS_RAID_SINGLE] = "single",
6194 [BTRFS_RAID_RAID5] = "raid5",
6195 [BTRFS_RAID_RAID6] = "raid6",
6196};
6197
6198const char *get_raid_name(enum btrfs_raid_types type)
6199{
6200 if (type >= BTRFS_NR_RAID_TYPES)
6201 return NULL;
6202
6203 return btrfs_raid_type_names[type];
6204}
6205
6160enum btrfs_loop_type { 6206enum btrfs_loop_type {
6161 LOOP_CACHING_NOWAIT = 0, 6207 LOOP_CACHING_NOWAIT = 0,
6162 LOOP_CACHING_WAIT = 1, 6208 LOOP_CACHING_WAIT = 1,
@@ -8340,6 +8386,8 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info)
8340 release_global_block_rsv(info); 8386 release_global_block_rsv(info);
8341 8387
8342 while (!list_empty(&info->space_info)) { 8388 while (!list_empty(&info->space_info)) {
8389 int i;
8390
8343 space_info = list_entry(info->space_info.next, 8391 space_info = list_entry(info->space_info.next,
8344 struct btrfs_space_info, 8392 struct btrfs_space_info,
8345 list); 8393 list);
@@ -8350,9 +8398,17 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info)
8350 dump_space_info(space_info, 0, 0); 8398 dump_space_info(space_info, 0, 0);
8351 } 8399 }
8352 } 8400 }
8353 percpu_counter_destroy(&space_info->total_bytes_pinned);
8354 list_del(&space_info->list); 8401 list_del(&space_info->list);
8355 kfree(space_info); 8402 for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) {
8403 struct kobject *kobj;
8404 kobj = &space_info->block_group_kobjs[i];
8405 if (kobj->parent) {
8406 kobject_del(kobj);
8407 kobject_put(kobj);
8408 }
8409 }
8410 kobject_del(&space_info->kobj);
8411 kobject_put(&space_info->kobj);
8356 } 8412 }
8357 return 0; 8413 return 0;
8358} 8414}
@@ -8363,6 +8419,19 @@ static void __link_block_group(struct btrfs_space_info *space_info,
8363 int index = get_block_group_index(cache); 8419 int index = get_block_group_index(cache);
8364 8420
8365 down_write(&space_info->groups_sem); 8421 down_write(&space_info->groups_sem);
8422 if (list_empty(&space_info->block_groups[index])) {
8423 struct kobject *kobj = &space_info->block_group_kobjs[index];
8424 int ret;
8425
8426 kobject_get(&space_info->kobj); /* put in release */
8427 ret = kobject_init_and_add(kobj, &btrfs_raid_ktype,
8428 &space_info->kobj,
8429 get_raid_name(index));
8430 if (ret) {
8431 pr_warn("btrfs: failed to add kobject for block cache. ignoring.\n");
8432 kobject_put(&space_info->kobj);
8433 }
8434 }
8366 list_add_tail(&cache->list, &space_info->block_groups[index]); 8435 list_add_tail(&cache->list, &space_info->block_groups[index]);
8367 up_write(&space_info->groups_sem); 8436 up_write(&space_info->groups_sem);
8368} 8437}
@@ -8803,8 +8872,11 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
8803 * are still on the list after taking the semaphore 8872 * are still on the list after taking the semaphore
8804 */ 8873 */
8805 list_del_init(&block_group->list); 8874 list_del_init(&block_group->list);
8806 if (list_empty(&block_group->space_info->block_groups[index])) 8875 if (list_empty(&block_group->space_info->block_groups[index])) {
8876 kobject_del(&block_group->space_info->block_group_kobjs[index]);
8877 kobject_put(&block_group->space_info->block_group_kobjs[index]);
8807 clear_avail_alloc_bits(root->fs_info, block_group->flags); 8878 clear_avail_alloc_bits(root->fs_info, block_group->flags);
8879 }
8808 up_write(&block_group->space_info->groups_sem); 8880 up_write(&block_group->space_info->groups_sem);
8809 8881
8810 if (block_group->cached == BTRFS_CACHE_STARTED) 8882 if (block_group->cached == BTRFS_CACHE_STARTED)
diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c
index 562e346994d9..e060958a6382 100644
--- a/fs/btrfs/sysfs.c
+++ b/fs/btrfs/sysfs.c
@@ -219,6 +219,140 @@ static const struct attribute_group btrfs_feature_attr_group = {
219 .attrs = btrfs_supported_feature_attrs, 219 .attrs = btrfs_supported_feature_attrs,
220}; 220};
221 221
222static ssize_t btrfs_show_u64(u64 *value_ptr, spinlock_t *lock, char *buf)
223{
224 u64 val;
225 if (lock)
226 spin_lock(lock);
227 val = *value_ptr;
228 if (lock)
229 spin_unlock(lock);
230 return snprintf(buf, PAGE_SIZE, "%llu\n", val);
231}
232
233static ssize_t global_rsv_size_show(struct kobject *kobj,
234 struct kobj_attribute *ka, char *buf)
235{
236 struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent);
237 struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv;
238 return btrfs_show_u64(&block_rsv->size, &block_rsv->lock, buf);
239}
240BTRFS_ATTR(global_rsv_size, 0444, global_rsv_size_show);
241
242static ssize_t global_rsv_reserved_show(struct kobject *kobj,
243 struct kobj_attribute *a, char *buf)
244{
245 struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent);
246 struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv;
247 return btrfs_show_u64(&block_rsv->reserved, &block_rsv->lock, buf);
248}
249BTRFS_ATTR(global_rsv_reserved, 0444, global_rsv_reserved_show);
250
251#define to_space_info(_kobj) container_of(_kobj, struct btrfs_space_info, kobj)
252
253static ssize_t raid_bytes_show(struct kobject *kobj,
254 struct kobj_attribute *attr, char *buf);
255BTRFS_RAID_ATTR(total_bytes, raid_bytes_show);
256BTRFS_RAID_ATTR(used_bytes, raid_bytes_show);
257
258static ssize_t raid_bytes_show(struct kobject *kobj,
259 struct kobj_attribute *attr, char *buf)
260
261{
262 struct btrfs_space_info *sinfo = to_space_info(kobj->parent);
263 struct btrfs_block_group_cache *block_group;
264 int index = kobj - sinfo->block_group_kobjs;
265 u64 val = 0;
266
267 down_read(&sinfo->groups_sem);
268 list_for_each_entry(block_group, &sinfo->block_groups[index], list) {
269 if (&attr->attr == BTRFS_RAID_ATTR_PTR(total_bytes))
270 val += block_group->key.offset;
271 else
272 val += btrfs_block_group_used(&block_group->item);
273 }
274 up_read(&sinfo->groups_sem);
275 return snprintf(buf, PAGE_SIZE, "%llu\n", val);
276}
277
278static struct attribute *raid_attributes[] = {
279 BTRFS_RAID_ATTR_PTR(total_bytes),
280 BTRFS_RAID_ATTR_PTR(used_bytes),
281 NULL
282};
283
284static void release_raid_kobj(struct kobject *kobj)
285{
286 kobject_put(kobj->parent);
287}
288
289struct kobj_type btrfs_raid_ktype = {
290 .sysfs_ops = &kobj_sysfs_ops,
291 .release = release_raid_kobj,
292 .default_attrs = raid_attributes,
293};
294
295#define SPACE_INFO_ATTR(field) \
296static ssize_t btrfs_space_info_show_##field(struct kobject *kobj, \
297 struct kobj_attribute *a, \
298 char *buf) \
299{ \
300 struct btrfs_space_info *sinfo = to_space_info(kobj); \
301 return btrfs_show_u64(&sinfo->field, &sinfo->lock, buf); \
302} \
303BTRFS_ATTR(field, 0444, btrfs_space_info_show_##field)
304
305static ssize_t btrfs_space_info_show_total_bytes_pinned(struct kobject *kobj,
306 struct kobj_attribute *a,
307 char *buf)
308{
309 struct btrfs_space_info *sinfo = to_space_info(kobj);
310 s64 val = percpu_counter_sum(&sinfo->total_bytes_pinned);
311 return snprintf(buf, PAGE_SIZE, "%lld\n", val);
312}
313
314SPACE_INFO_ATTR(flags);
315SPACE_INFO_ATTR(total_bytes);
316SPACE_INFO_ATTR(bytes_used);
317SPACE_INFO_ATTR(bytes_pinned);
318SPACE_INFO_ATTR(bytes_reserved);
319SPACE_INFO_ATTR(bytes_may_use);
320SPACE_INFO_ATTR(disk_used);
321SPACE_INFO_ATTR(disk_total);
322BTRFS_ATTR(total_bytes_pinned, 0444, btrfs_space_info_show_total_bytes_pinned);
323
324static struct attribute *space_info_attrs[] = {
325 BTRFS_ATTR_PTR(flags),
326 BTRFS_ATTR_PTR(total_bytes),
327 BTRFS_ATTR_PTR(bytes_used),
328 BTRFS_ATTR_PTR(bytes_pinned),
329 BTRFS_ATTR_PTR(bytes_reserved),
330 BTRFS_ATTR_PTR(bytes_may_use),
331 BTRFS_ATTR_PTR(disk_used),
332 BTRFS_ATTR_PTR(disk_total),
333 BTRFS_ATTR_PTR(total_bytes_pinned),
334 NULL,
335};
336
337static void space_info_release(struct kobject *kobj)
338{
339 struct btrfs_space_info *sinfo = to_space_info(kobj);
340 percpu_counter_destroy(&sinfo->total_bytes_pinned);
341 kfree(sinfo);
342}
343
344struct kobj_type space_info_ktype = {
345 .sysfs_ops = &kobj_sysfs_ops,
346 .release = space_info_release,
347 .default_attrs = space_info_attrs,
348};
349
350static const struct attribute *allocation_attrs[] = {
351 BTRFS_ATTR_PTR(global_rsv_reserved),
352 BTRFS_ATTR_PTR(global_rsv_size),
353 NULL,
354};
355
222static void btrfs_release_super_kobj(struct kobject *kobj) 356static void btrfs_release_super_kobj(struct kobject *kobj)
223{ 357{
224 struct btrfs_fs_info *fs_info = to_fs_info(kobj); 358 struct btrfs_fs_info *fs_info = to_fs_info(kobj);
@@ -239,6 +373,9 @@ static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj)
239 373
240void btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info) 374void btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info)
241{ 375{
376 sysfs_remove_files(fs_info->space_info_kobj, allocation_attrs);
377 kobject_del(fs_info->space_info_kobj);
378 kobject_put(fs_info->space_info_kobj);
242 kobject_del(&fs_info->super_kobj); 379 kobject_del(&fs_info->super_kobj);
243 kobject_put(&fs_info->super_kobj); 380 kobject_put(&fs_info->super_kobj);
244 wait_for_completion(&fs_info->kobj_unregister); 381 wait_for_completion(&fs_info->kobj_unregister);
@@ -391,6 +528,17 @@ int btrfs_sysfs_add_one(struct btrfs_fs_info *fs_info)
391 if (error) 528 if (error)
392 goto failure; 529 goto failure;
393 530
531 fs_info->space_info_kobj = kobject_create_and_add("allocation",
532 &fs_info->super_kobj);
533 if (!fs_info->space_info_kobj) {
534 error = -ENOMEM;
535 goto failure;
536 }
537
538 error = sysfs_create_files(fs_info->space_info_kobj, allocation_attrs);
539 if (error)
540 goto failure;
541
394 return 0; 542 return 0;
395failure: 543failure:
396 btrfs_sysfs_remove_one(fs_info); 544 btrfs_sysfs_remove_one(fs_info);
diff --git a/fs/btrfs/sysfs.h b/fs/btrfs/sysfs.h
index c49fd25c911f..f3cea3710d44 100644
--- a/fs/btrfs/sysfs.h
+++ b/fs/btrfs/sysfs.h
@@ -22,6 +22,12 @@ static struct kobj_attribute btrfs_attr_##_name = \
22 BTRFS_ATTR_RW(_name, _mode, _show, NULL) 22 BTRFS_ATTR_RW(_name, _mode, _show, NULL)
23#define BTRFS_ATTR_PTR(_name) (&btrfs_attr_##_name.attr) 23#define BTRFS_ATTR_PTR(_name) (&btrfs_attr_##_name.attr)
24 24
25#define BTRFS_RAID_ATTR(_name, _show) \
26static struct kobj_attribute btrfs_raid_attr_##_name = \
27 __INIT_KOBJ_ATTR(_name, 0444, _show, NULL)
28#define BTRFS_RAID_ATTR_PTR(_name) (&btrfs_raid_attr_##_name.attr)
29
30
25struct btrfs_feature_attr { 31struct btrfs_feature_attr {
26 struct kobj_attribute kobj_attr; 32 struct kobj_attribute kobj_attr;
27 enum btrfs_feature_set feature_set; 33 enum btrfs_feature_set feature_set;
@@ -53,4 +59,6 @@ static struct btrfs_feature_attr btrfs_attr_##_name = { \
53 to_btrfs_feature_attr(attr_to_btrfs_attr(a)) 59 to_btrfs_feature_attr(attr_to_btrfs_attr(a))
54char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags); 60char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags);
55extern const char * const btrfs_feature_set_names[3]; 61extern const char * const btrfs_feature_set_names[3];
62extern struct kobj_type space_info_ktype;
63extern struct kobj_type btrfs_raid_ktype;
56#endif /* _BTRFS_SYSFS_H_ */ 64#endif /* _BTRFS_SYSFS_H_ */