aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Mahoney <jeffm@suse.com>2013-11-01 13:07:04 -0400
committerChris Mason <clm@fb.com>2014-01-28 16:19:29 -0500
commit6ab0a2029ceaedb78af807871820708b7353e3be (patch)
treeec9684534264d7b6d2cc0e6137ad7c7f851b1e88
parent01e219e8069516cdb98594d417b8bb8d906ed30d (diff)
btrfs: publish allocation data in sysfs
While trying to debug ENOSPC issues, it's helpful to understand what the kernel's view of the available space is. We export this information via ioctl, but sysfs files are more easily used. Signed-off-by: Jeff Mahoney <jeffm@suse.com> Signed-off-by: Josef Bacik <jbacik@fusionio.com> Signed-off-by: Chris Mason <clm@fb.com>
-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_ */