diff options
-rw-r--r-- | fs/btrfs/ctree.h | 5 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 82 | ||||
-rw-r--r-- | fs/btrfs/sysfs.c | 148 | ||||
-rw-r--r-- | fs/btrfs/sysfs.h | 8 |
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); |
3180 | void btrfs_put_block_group(struct btrfs_block_group_cache *cache); | 3184 | void btrfs_put_block_group(struct btrfs_block_group_cache *cache); |
3185 | int get_block_group_index(struct btrfs_block_group_cache *cache); | ||
3181 | struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | 3186 | struct 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 | ||
3412 | static 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 | |||
3411 | static int update_space_info(struct btrfs_fs_info *info, u64 flags, | 3429 | static 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 | ||
3473 | static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) | 3501 | static 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 | ||
6155 | static int get_block_group_index(struct btrfs_block_group_cache *cache) | 6183 | int 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 | ||
6188 | static 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 | |||
6198 | const 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 | |||
6160 | enum btrfs_loop_type { | 6206 | enum 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 | ||
222 | static 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 | |||
233 | static 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 | } | ||
240 | BTRFS_ATTR(global_rsv_size, 0444, global_rsv_size_show); | ||
241 | |||
242 | static 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 | } | ||
249 | BTRFS_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 | |||
253 | static ssize_t raid_bytes_show(struct kobject *kobj, | ||
254 | struct kobj_attribute *attr, char *buf); | ||
255 | BTRFS_RAID_ATTR(total_bytes, raid_bytes_show); | ||
256 | BTRFS_RAID_ATTR(used_bytes, raid_bytes_show); | ||
257 | |||
258 | static 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 | |||
278 | static struct attribute *raid_attributes[] = { | ||
279 | BTRFS_RAID_ATTR_PTR(total_bytes), | ||
280 | BTRFS_RAID_ATTR_PTR(used_bytes), | ||
281 | NULL | ||
282 | }; | ||
283 | |||
284 | static void release_raid_kobj(struct kobject *kobj) | ||
285 | { | ||
286 | kobject_put(kobj->parent); | ||
287 | } | ||
288 | |||
289 | struct 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) \ | ||
296 | static 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 | } \ | ||
303 | BTRFS_ATTR(field, 0444, btrfs_space_info_show_##field) | ||
304 | |||
305 | static 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 | |||
314 | SPACE_INFO_ATTR(flags); | ||
315 | SPACE_INFO_ATTR(total_bytes); | ||
316 | SPACE_INFO_ATTR(bytes_used); | ||
317 | SPACE_INFO_ATTR(bytes_pinned); | ||
318 | SPACE_INFO_ATTR(bytes_reserved); | ||
319 | SPACE_INFO_ATTR(bytes_may_use); | ||
320 | SPACE_INFO_ATTR(disk_used); | ||
321 | SPACE_INFO_ATTR(disk_total); | ||
322 | BTRFS_ATTR(total_bytes_pinned, 0444, btrfs_space_info_show_total_bytes_pinned); | ||
323 | |||
324 | static 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 | |||
337 | static 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 | |||
344 | struct kobj_type space_info_ktype = { | ||
345 | .sysfs_ops = &kobj_sysfs_ops, | ||
346 | .release = space_info_release, | ||
347 | .default_attrs = space_info_attrs, | ||
348 | }; | ||
349 | |||
350 | static const struct attribute *allocation_attrs[] = { | ||
351 | BTRFS_ATTR_PTR(global_rsv_reserved), | ||
352 | BTRFS_ATTR_PTR(global_rsv_size), | ||
353 | NULL, | ||
354 | }; | ||
355 | |||
222 | static void btrfs_release_super_kobj(struct kobject *kobj) | 356 | static 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 | ||
240 | void btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info) | 374 | void 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; |
395 | failure: | 543 | failure: |
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) \ | ||
26 | static 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 | |||
25 | struct btrfs_feature_attr { | 31 | struct 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)) |
54 | char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags); | 60 | char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags); |
55 | extern const char * const btrfs_feature_set_names[3]; | 61 | extern const char * const btrfs_feature_set_names[3]; |
62 | extern struct kobj_type space_info_ktype; | ||
63 | extern struct kobj_type btrfs_raid_ktype; | ||
56 | #endif /* _BTRFS_SYSFS_H_ */ | 64 | #endif /* _BTRFS_SYSFS_H_ */ |