Commit 8c2a3ca20f6233677ac3222c6506174010eb414f
Committed by
Chris Mason
1 parent
90290e1982
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
Btrfs: space leak tracepoints
This in addition to a script in my btrfs-tracing tree will help track down space leaks when we're getting space left over in block groups on umount. Thanks, Signed-off-by: Josef Bacik <josef@redhat.com>
Showing 5 changed files with 119 additions and 20 deletions Side-by-side Diff
fs/btrfs/delayed-inode.c
... | ... | @@ -595,8 +595,12 @@ |
595 | 595 | |
596 | 596 | num_bytes = btrfs_calc_trans_metadata_size(root, 1); |
597 | 597 | ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes); |
598 | - if (!ret) | |
598 | + if (!ret) { | |
599 | + trace_btrfs_space_reservation(root->fs_info, "delayed_item", | |
600 | + item->key.objectid, | |
601 | + num_bytes, 1); | |
599 | 602 | item->bytes_reserved = num_bytes; |
603 | + } | |
600 | 604 | |
601 | 605 | return ret; |
602 | 606 | } |
... | ... | @@ -610,6 +614,9 @@ |
610 | 614 | return; |
611 | 615 | |
612 | 616 | rsv = &root->fs_info->delayed_block_rsv; |
617 | + trace_btrfs_space_reservation(root->fs_info, "delayed_item", | |
618 | + item->key.objectid, item->bytes_reserved, | |
619 | + 0); | |
613 | 620 | btrfs_block_rsv_release(root, rsv, |
614 | 621 | item->bytes_reserved); |
615 | 622 | } |
... | ... | @@ -624,7 +631,7 @@ |
624 | 631 | struct btrfs_block_rsv *dst_rsv; |
625 | 632 | u64 num_bytes; |
626 | 633 | int ret; |
627 | - int release = false; | |
634 | + bool release = false; | |
628 | 635 | |
629 | 636 | src_rsv = trans->block_rsv; |
630 | 637 | dst_rsv = &root->fs_info->delayed_block_rsv; |
631 | 638 | |
... | ... | @@ -651,8 +658,13 @@ |
651 | 658 | */ |
652 | 659 | if (ret == -EAGAIN) |
653 | 660 | ret = -ENOSPC; |
654 | - if (!ret) | |
661 | + if (!ret) { | |
655 | 662 | node->bytes_reserved = num_bytes; |
663 | + trace_btrfs_space_reservation(root->fs_info, | |
664 | + "delayed_inode", | |
665 | + btrfs_ino(inode), | |
666 | + num_bytes, 1); | |
667 | + } | |
656 | 668 | return ret; |
657 | 669 | } else if (src_rsv == &root->fs_info->delalloc_block_rsv) { |
658 | 670 | spin_lock(&BTRFS_I(inode)->lock); |
659 | 671 | |
660 | 672 | |
661 | 673 | |
... | ... | @@ -707,11 +719,17 @@ |
707 | 719 | * reservation here. I think it may be time for a documentation page on |
708 | 720 | * how block rsvs. work. |
709 | 721 | */ |
710 | - if (!ret) | |
722 | + if (!ret) { | |
723 | + trace_btrfs_space_reservation(root->fs_info, "delayed_inode", | |
724 | + btrfs_ino(inode), num_bytes, 1); | |
711 | 725 | node->bytes_reserved = num_bytes; |
726 | + } | |
712 | 727 | |
713 | - if (release) | |
728 | + if (release) { | |
729 | + trace_btrfs_space_reservation(root->fs_info, "delalloc", | |
730 | + btrfs_ino(inode), num_bytes, 0); | |
714 | 731 | btrfs_block_rsv_release(root, src_rsv, num_bytes); |
732 | + } | |
715 | 733 | |
716 | 734 | return ret; |
717 | 735 | } |
... | ... | @@ -725,6 +743,8 @@ |
725 | 743 | return; |
726 | 744 | |
727 | 745 | rsv = &root->fs_info->delayed_block_rsv; |
746 | + trace_btrfs_space_reservation(root->fs_info, "delayed_inode", | |
747 | + node->inode_id, node->bytes_reserved, 0); | |
728 | 748 | btrfs_block_rsv_release(root, rsv, |
729 | 749 | node->bytes_reserved); |
730 | 750 | node->bytes_reserved = 0; |
... | ... | @@ -1372,13 +1392,6 @@ |
1372 | 1392 | goto release_node; |
1373 | 1393 | } |
1374 | 1394 | |
1375 | - ret = btrfs_delayed_item_reserve_metadata(trans, root, delayed_item); | |
1376 | - /* | |
1377 | - * we have reserved enough space when we start a new transaction, | |
1378 | - * so reserving metadata failure is impossible | |
1379 | - */ | |
1380 | - BUG_ON(ret); | |
1381 | - | |
1382 | 1395 | delayed_item->key.objectid = btrfs_ino(dir); |
1383 | 1396 | btrfs_set_key_type(&delayed_item->key, BTRFS_DIR_INDEX_KEY); |
1384 | 1397 | delayed_item->key.offset = index; |
... | ... | @@ -1390,6 +1403,14 @@ |
1390 | 1403 | dir_item->name_len = cpu_to_le16(name_len); |
1391 | 1404 | dir_item->type = type; |
1392 | 1405 | memcpy((char *)(dir_item + 1), name, name_len); |
1406 | + | |
1407 | + ret = btrfs_delayed_item_reserve_metadata(trans, root, delayed_item); | |
1408 | + /* | |
1409 | + * we have reserved enough space when we start a new transaction, | |
1410 | + * so reserving metadata failure is impossible | |
1411 | + */ | |
1412 | + BUG_ON(ret); | |
1413 | + | |
1393 | 1414 | |
1394 | 1415 | mutex_lock(&delayed_node->mutex); |
1395 | 1416 | ret = __btrfs_add_delayed_insertion_item(delayed_node, delayed_item); |
fs/btrfs/extent-tree.c
... | ... | @@ -3310,6 +3310,8 @@ |
3310 | 3310 | return -ENOSPC; |
3311 | 3311 | } |
3312 | 3312 | data_sinfo->bytes_may_use += bytes; |
3313 | + trace_btrfs_space_reservation(root->fs_info, "space_info", | |
3314 | + (u64)data_sinfo, bytes, 1); | |
3313 | 3315 | spin_unlock(&data_sinfo->lock); |
3314 | 3316 | |
3315 | 3317 | return 0; |
... | ... | @@ -3329,6 +3331,8 @@ |
3329 | 3331 | data_sinfo = BTRFS_I(inode)->space_info; |
3330 | 3332 | spin_lock(&data_sinfo->lock); |
3331 | 3333 | data_sinfo->bytes_may_use -= bytes; |
3334 | + trace_btrfs_space_reservation(root->fs_info, "space_info", | |
3335 | + (u64)data_sinfo, bytes, 0); | |
3332 | 3336 | spin_unlock(&data_sinfo->lock); |
3333 | 3337 | } |
3334 | 3338 | |
... | ... | @@ -3686,6 +3690,10 @@ |
3686 | 3690 | if (used <= space_info->total_bytes) { |
3687 | 3691 | if (used + orig_bytes <= space_info->total_bytes) { |
3688 | 3692 | space_info->bytes_may_use += orig_bytes; |
3693 | + trace_btrfs_space_reservation(root->fs_info, | |
3694 | + "space_info", | |
3695 | + (u64)space_info, | |
3696 | + orig_bytes, 1); | |
3689 | 3697 | ret = 0; |
3690 | 3698 | } else { |
3691 | 3699 | /* |
... | ... | @@ -3753,6 +3761,10 @@ |
3753 | 3761 | |
3754 | 3762 | if (used + num_bytes < space_info->total_bytes + avail) { |
3755 | 3763 | space_info->bytes_may_use += orig_bytes; |
3764 | + trace_btrfs_space_reservation(root->fs_info, | |
3765 | + "space_info", | |
3766 | + (u64)space_info, | |
3767 | + orig_bytes, 1); | |
3756 | 3768 | ret = 0; |
3757 | 3769 | } else { |
3758 | 3770 | wait_ordered = true; |
... | ... | @@ -3859,7 +3871,8 @@ |
3859 | 3871 | spin_unlock(&block_rsv->lock); |
3860 | 3872 | } |
3861 | 3873 | |
3862 | -static void block_rsv_release_bytes(struct btrfs_block_rsv *block_rsv, | |
3874 | +static void block_rsv_release_bytes(struct btrfs_fs_info *fs_info, | |
3875 | + struct btrfs_block_rsv *block_rsv, | |
3863 | 3876 | struct btrfs_block_rsv *dest, u64 num_bytes) |
3864 | 3877 | { |
3865 | 3878 | struct btrfs_space_info *space_info = block_rsv->space_info; |
... | ... | @@ -3895,6 +3908,9 @@ |
3895 | 3908 | if (num_bytes) { |
3896 | 3909 | spin_lock(&space_info->lock); |
3897 | 3910 | space_info->bytes_may_use -= num_bytes; |
3911 | + trace_btrfs_space_reservation(fs_info, "space_info", | |
3912 | + (u64)space_info, | |
3913 | + num_bytes, 0); | |
3898 | 3914 | space_info->reservation_progress++; |
3899 | 3915 | spin_unlock(&space_info->lock); |
3900 | 3916 | } |
... | ... | @@ -4051,7 +4067,8 @@ |
4051 | 4067 | if (global_rsv->full || global_rsv == block_rsv || |
4052 | 4068 | block_rsv->space_info != global_rsv->space_info) |
4053 | 4069 | global_rsv = NULL; |
4054 | - block_rsv_release_bytes(block_rsv, global_rsv, num_bytes); | |
4070 | + block_rsv_release_bytes(root->fs_info, block_rsv, global_rsv, | |
4071 | + num_bytes); | |
4055 | 4072 | } |
4056 | 4073 | |
4057 | 4074 | /* |
4058 | 4075 | |
... | ... | @@ -4110,11 +4127,15 @@ |
4110 | 4127 | num_bytes = sinfo->total_bytes - num_bytes; |
4111 | 4128 | block_rsv->reserved += num_bytes; |
4112 | 4129 | sinfo->bytes_may_use += num_bytes; |
4130 | + trace_btrfs_space_reservation(fs_info, "space_info", | |
4131 | + (u64)sinfo, num_bytes, 1); | |
4113 | 4132 | } |
4114 | 4133 | |
4115 | 4134 | if (block_rsv->reserved >= block_rsv->size) { |
4116 | 4135 | num_bytes = block_rsv->reserved - block_rsv->size; |
4117 | 4136 | sinfo->bytes_may_use -= num_bytes; |
4137 | + trace_btrfs_space_reservation(fs_info, "space_info", | |
4138 | + (u64)sinfo, num_bytes, 0); | |
4118 | 4139 | sinfo->reservation_progress++; |
4119 | 4140 | block_rsv->reserved = block_rsv->size; |
4120 | 4141 | block_rsv->full = 1; |
... | ... | @@ -4149,7 +4170,8 @@ |
4149 | 4170 | |
4150 | 4171 | static void release_global_block_rsv(struct btrfs_fs_info *fs_info) |
4151 | 4172 | { |
4152 | - block_rsv_release_bytes(&fs_info->global_block_rsv, NULL, (u64)-1); | |
4173 | + block_rsv_release_bytes(fs_info, &fs_info->global_block_rsv, NULL, | |
4174 | + (u64)-1); | |
4153 | 4175 | WARN_ON(fs_info->delalloc_block_rsv.size > 0); |
4154 | 4176 | WARN_ON(fs_info->delalloc_block_rsv.reserved > 0); |
4155 | 4177 | WARN_ON(fs_info->trans_block_rsv.size > 0); |
... | ... | @@ -4166,6 +4188,8 @@ |
4166 | 4188 | if (!trans->bytes_reserved) |
4167 | 4189 | return; |
4168 | 4190 | |
4191 | + trace_btrfs_space_reservation(root->fs_info, "transaction", (u64)trans, | |
4192 | + trans->bytes_reserved, 0); | |
4169 | 4193 | btrfs_block_rsv_release(root, trans->block_rsv, trans->bytes_reserved); |
4170 | 4194 | trans->bytes_reserved = 0; |
4171 | 4195 | } |
... | ... | @@ -4183,6 +4207,8 @@ |
4183 | 4207 | * when we are truly done with the orphan item. |
4184 | 4208 | */ |
4185 | 4209 | u64 num_bytes = btrfs_calc_trans_metadata_size(root, 1); |
4210 | + trace_btrfs_space_reservation(root->fs_info, "orphan", | |
4211 | + btrfs_ino(inode), num_bytes, 1); | |
4186 | 4212 | return block_rsv_migrate_bytes(src_rsv, dst_rsv, num_bytes); |
4187 | 4213 | } |
4188 | 4214 | |
... | ... | @@ -4190,6 +4216,8 @@ |
4190 | 4216 | { |
4191 | 4217 | struct btrfs_root *root = BTRFS_I(inode)->root; |
4192 | 4218 | u64 num_bytes = btrfs_calc_trans_metadata_size(root, 1); |
4219 | + trace_btrfs_space_reservation(root->fs_info, "orphan", | |
4220 | + btrfs_ino(inode), num_bytes, 0); | |
4193 | 4221 | btrfs_block_rsv_release(root, root->orphan_block_rsv, num_bytes); |
4194 | 4222 | } |
4195 | 4223 | |
4196 | 4224 | |
... | ... | @@ -4370,8 +4398,13 @@ |
4370 | 4398 | if (dropped) |
4371 | 4399 | to_free += btrfs_calc_trans_metadata_size(root, dropped); |
4372 | 4400 | |
4373 | - if (to_free) | |
4401 | + if (to_free) { | |
4374 | 4402 | btrfs_block_rsv_release(root, block_rsv, to_free); |
4403 | + trace_btrfs_space_reservation(root->fs_info, | |
4404 | + "delalloc", | |
4405 | + btrfs_ino(inode), | |
4406 | + to_free, 0); | |
4407 | + } | |
4375 | 4408 | return ret; |
4376 | 4409 | } |
4377 | 4410 | |
... | ... | @@ -4383,6 +4416,9 @@ |
4383 | 4416 | BTRFS_I(inode)->reserved_extents += nr_extents; |
4384 | 4417 | spin_unlock(&BTRFS_I(inode)->lock); |
4385 | 4418 | |
4419 | + if (to_reserve) | |
4420 | + trace_btrfs_space_reservation(root->fs_info,"delalloc", | |
4421 | + btrfs_ino(inode), to_reserve, 1); | |
4386 | 4422 | block_rsv_add_bytes(block_rsv, to_reserve, 1); |
4387 | 4423 | |
4388 | 4424 | return 0; |
... | ... | @@ -4412,6 +4448,8 @@ |
4412 | 4448 | if (dropped > 0) |
4413 | 4449 | to_free += btrfs_calc_trans_metadata_size(root, dropped); |
4414 | 4450 | |
4451 | + trace_btrfs_space_reservation(root->fs_info, "delalloc", | |
4452 | + btrfs_ino(inode), to_free, 0); | |
4415 | 4453 | btrfs_block_rsv_release(root, &root->fs_info->delalloc_block_rsv, |
4416 | 4454 | to_free); |
4417 | 4455 | } |
... | ... | @@ -4666,7 +4704,10 @@ |
4666 | 4704 | cache->reserved += num_bytes; |
4667 | 4705 | space_info->bytes_reserved += num_bytes; |
4668 | 4706 | if (reserve == RESERVE_ALLOC) { |
4669 | - BUG_ON(space_info->bytes_may_use < num_bytes); | |
4707 | + trace_btrfs_space_reservation(cache->fs_info, | |
4708 | + "space_info", | |
4709 | + (u64)space_info, | |
4710 | + num_bytes, 0); | |
4670 | 4711 | space_info->bytes_may_use -= num_bytes; |
4671 | 4712 | } |
4672 | 4713 | } |
4673 | 4714 | |
... | ... | @@ -6126,10 +6167,11 @@ |
6126 | 6167 | return ERR_PTR(-ENOSPC); |
6127 | 6168 | } |
6128 | 6169 | |
6129 | -static void unuse_block_rsv(struct btrfs_block_rsv *block_rsv, u32 blocksize) | |
6170 | +static void unuse_block_rsv(struct btrfs_fs_info *fs_info, | |
6171 | + struct btrfs_block_rsv *block_rsv, u32 blocksize) | |
6130 | 6172 | { |
6131 | 6173 | block_rsv_add_bytes(block_rsv, blocksize, 0); |
6132 | - block_rsv_release_bytes(block_rsv, NULL, 0); | |
6174 | + block_rsv_release_bytes(fs_info, block_rsv, NULL, 0); | |
6133 | 6175 | } |
6134 | 6176 | |
6135 | 6177 | /* |
... | ... | @@ -6159,7 +6201,7 @@ |
6159 | 6201 | ret = btrfs_reserve_extent(trans, root, blocksize, blocksize, |
6160 | 6202 | empty_size, hint, (u64)-1, &ins, 0); |
6161 | 6203 | if (ret) { |
6162 | - unuse_block_rsv(block_rsv, blocksize); | |
6204 | + unuse_block_rsv(root->fs_info, block_rsv, blocksize); | |
6163 | 6205 | return ERR_PTR(ret); |
6164 | 6206 | } |
6165 | 6207 |
fs/btrfs/inode-map.c
... | ... | @@ -438,6 +438,8 @@ |
438 | 438 | trans->bytes_reserved); |
439 | 439 | if (ret) |
440 | 440 | goto out; |
441 | + trace_btrfs_space_reservation(root->fs_info, "ino_cache", (u64)trans, | |
442 | + trans->bytes_reserved, 1); | |
441 | 443 | again: |
442 | 444 | inode = lookup_free_ino_inode(root, path); |
443 | 445 | if (IS_ERR(inode) && PTR_ERR(inode) != -ENOENT) { |
... | ... | @@ -498,6 +500,8 @@ |
498 | 500 | out_put: |
499 | 501 | iput(inode); |
500 | 502 | out_release: |
503 | + trace_btrfs_space_reservation(root->fs_info, "ino_cache", (u64)trans, | |
504 | + trans->bytes_reserved, 0); | |
501 | 505 | btrfs_block_rsv_release(root, trans->block_rsv, trans->bytes_reserved); |
502 | 506 | out: |
503 | 507 | trans->block_rsv = rsv; |
fs/btrfs/transaction.c
include/trace/events/btrfs.h
... | ... | @@ -55,6 +55,8 @@ |
55 | 55 | { BTRFS_BLOCK_GROUP_DUP, "DUP"}, \ |
56 | 56 | { BTRFS_BLOCK_GROUP_RAID10, "RAID10"} |
57 | 57 | |
58 | +#define BTRFS_UUID_SIZE 16 | |
59 | + | |
58 | 60 | TRACE_EVENT(btrfs_transaction_commit, |
59 | 61 | |
60 | 62 | TP_PROTO(struct btrfs_root *root), |
... | ... | @@ -630,6 +632,34 @@ |
630 | 632 | __entry->buf_level, |
631 | 633 | (unsigned long long)__entry->cow_start, |
632 | 634 | __entry->cow_level) |
635 | +); | |
636 | + | |
637 | +TRACE_EVENT(btrfs_space_reservation, | |
638 | + | |
639 | + TP_PROTO(struct btrfs_fs_info *fs_info, char *type, u64 val, | |
640 | + u64 bytes, int reserve), | |
641 | + | |
642 | + TP_ARGS(fs_info, type, val, bytes, reserve), | |
643 | + | |
644 | + TP_STRUCT__entry( | |
645 | + __array( u8, fsid, BTRFS_UUID_SIZE ) | |
646 | + __string( type, type ) | |
647 | + __field( u64, val ) | |
648 | + __field( u64, bytes ) | |
649 | + __field( int, reserve ) | |
650 | + ), | |
651 | + | |
652 | + TP_fast_assign( | |
653 | + memcpy(__entry->fsid, fs_info->fsid, BTRFS_UUID_SIZE); | |
654 | + __assign_str(type, type); | |
655 | + __entry->val = val; | |
656 | + __entry->bytes = bytes; | |
657 | + __entry->reserve = reserve; | |
658 | + ), | |
659 | + | |
660 | + TP_printk("%pU: %s: %Lu %s %Lu", __entry->fsid, __get_str(type), | |
661 | + __entry->val, __entry->reserve ? "reserve" : "release", | |
662 | + __entry->bytes) | |
633 | 663 | ); |
634 | 664 | |
635 | 665 | DECLARE_EVENT_CLASS(btrfs__reserved_extent, |