Commit 064e38aaded5269e573ac1c765284fd65c8ebd13
Exists in
master
and in
20 other branches
Merge git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable
* git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable: Btrfs: Fix oops and use after free during space balancing Btrfs: set device->total_disk_bytes when adding new device
Showing 2 changed files Side-by-side Diff
fs/btrfs/extent-tree.c
... | ... | @@ -2622,7 +2622,18 @@ |
2622 | 2622 | search_start); |
2623 | 2623 | if (block_group && block_group_bits(block_group, data)) { |
2624 | 2624 | down_read(&space_info->groups_sem); |
2625 | - goto have_block_group; | |
2625 | + if (list_empty(&block_group->list) || | |
2626 | + block_group->ro) { | |
2627 | + /* | |
2628 | + * someone is removing this block group, | |
2629 | + * we can't jump into the have_block_group | |
2630 | + * target because our list pointers are not | |
2631 | + * valid | |
2632 | + */ | |
2633 | + btrfs_put_block_group(block_group); | |
2634 | + up_read(&space_info->groups_sem); | |
2635 | + } else | |
2636 | + goto have_block_group; | |
2626 | 2637 | } else if (block_group) { |
2627 | 2638 | btrfs_put_block_group(block_group); |
2628 | 2639 | } |
... | ... | @@ -2656,6 +2667,13 @@ |
2656 | 2667 | * people trying to start a new cluster |
2657 | 2668 | */ |
2658 | 2669 | spin_lock(&last_ptr->refill_lock); |
2670 | + if (last_ptr->block_group && | |
2671 | + (last_ptr->block_group->ro || | |
2672 | + !block_group_bits(last_ptr->block_group, data))) { | |
2673 | + offset = 0; | |
2674 | + goto refill_cluster; | |
2675 | + } | |
2676 | + | |
2659 | 2677 | offset = btrfs_alloc_from_cluster(block_group, last_ptr, |
2660 | 2678 | num_bytes, search_start); |
2661 | 2679 | if (offset) { |
2662 | 2680 | |
... | ... | @@ -2681,10 +2699,17 @@ |
2681 | 2699 | |
2682 | 2700 | last_ptr_loop = 1; |
2683 | 2701 | search_start = block_group->key.objectid; |
2702 | + /* | |
2703 | + * we know this block group is properly | |
2704 | + * in the list because | |
2705 | + * btrfs_remove_block_group, drops the | |
2706 | + * cluster before it removes the block | |
2707 | + * group from the list | |
2708 | + */ | |
2684 | 2709 | goto have_block_group; |
2685 | 2710 | } |
2686 | 2711 | spin_unlock(&last_ptr->lock); |
2687 | - | |
2712 | +refill_cluster: | |
2688 | 2713 | /* |
2689 | 2714 | * this cluster didn't work out, free it and |
2690 | 2715 | * start over |
... | ... | @@ -5968,6 +5993,7 @@ |
5968 | 5993 | { |
5969 | 5994 | struct btrfs_path *path; |
5970 | 5995 | struct btrfs_block_group_cache *block_group; |
5996 | + struct btrfs_free_cluster *cluster; | |
5971 | 5997 | struct btrfs_key key; |
5972 | 5998 | int ret; |
5973 | 5999 | |
... | ... | @@ -5979,6 +6005,21 @@ |
5979 | 6005 | |
5980 | 6006 | memcpy(&key, &block_group->key, sizeof(key)); |
5981 | 6007 | |
6008 | + /* make sure this block group isn't part of an allocation cluster */ | |
6009 | + cluster = &root->fs_info->data_alloc_cluster; | |
6010 | + spin_lock(&cluster->refill_lock); | |
6011 | + btrfs_return_cluster_to_free_space(block_group, cluster); | |
6012 | + spin_unlock(&cluster->refill_lock); | |
6013 | + | |
6014 | + /* | |
6015 | + * make sure this block group isn't part of a metadata | |
6016 | + * allocation cluster | |
6017 | + */ | |
6018 | + cluster = &root->fs_info->meta_alloc_cluster; | |
6019 | + spin_lock(&cluster->refill_lock); | |
6020 | + btrfs_return_cluster_to_free_space(block_group, cluster); | |
6021 | + spin_unlock(&cluster->refill_lock); | |
6022 | + | |
5982 | 6023 | path = btrfs_alloc_path(); |
5983 | 6024 | BUG_ON(!path); |
5984 | 6025 | |
... | ... | @@ -5988,7 +6029,11 @@ |
5988 | 6029 | spin_unlock(&root->fs_info->block_group_cache_lock); |
5989 | 6030 | btrfs_remove_free_space_cache(block_group); |
5990 | 6031 | down_write(&block_group->space_info->groups_sem); |
5991 | - list_del(&block_group->list); | |
6032 | + /* | |
6033 | + * we must use list_del_init so people can check to see if they | |
6034 | + * are still on the list after taking the semaphore | |
6035 | + */ | |
6036 | + list_del_init(&block_group->list); | |
5992 | 6037 | up_write(&block_group->space_info->groups_sem); |
5993 | 6038 | |
5994 | 6039 | spin_lock(&block_group->space_info->lock); |
fs/btrfs/volumes.c
... | ... | @@ -1440,6 +1440,7 @@ |
1440 | 1440 | device->io_align = root->sectorsize; |
1441 | 1441 | device->sector_size = root->sectorsize; |
1442 | 1442 | device->total_bytes = i_size_read(bdev->bd_inode); |
1443 | + device->disk_total_bytes = device->total_bytes; | |
1443 | 1444 | device->dev_root = root->fs_info->dev_root; |
1444 | 1445 | device->bdev = bdev; |
1445 | 1446 | device->in_fs_metadata = 1; |