X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=fs%2Fbtrfs%2Fextent-tree.c;h=07204bf601edac25ad2757bbd7c85961eeabc56c;hb=d683477020be2036d6c2d7d2cd3ffac4f2acbd6c;hp=171312d51799e358843216c945a18dee6d3a8790;hpb=d1a343a0231ea34db16ab6773809f2874bcabcf8;p=uclinux-h8%2Flinux.git diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 171312d51799..07204bf601ed 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -4227,6 +4227,24 @@ out: space_info->chunk_alloc = 0; spin_unlock(&space_info->lock); mutex_unlock(&fs_info->chunk_mutex); + /* + * When we allocate a new chunk we reserve space in the chunk block + * reserve to make sure we can COW nodes/leafs in the chunk tree or + * add new nodes/leafs to it if we end up needing to do it when + * inserting the chunk item and updating device items as part of the + * second phase of chunk allocation, performed by + * btrfs_finish_chunk_alloc(). So make sure we don't accumulate a + * large number of new block groups to create in our transaction + * handle's new_bgs list to avoid exhausting the chunk block reserve + * in extreme cases - like having a single transaction create many new + * block groups when starting to write out the free space caches of all + * the block groups that were made dirty during the lifetime of the + * transaction. + */ + if (trans->chunk_bytes_reserved >= (2 * 1024 * 1024ull)) { + btrfs_create_pending_block_groups(trans, trans->root); + btrfs_trans_release_chunk_metadata(trans); + } return ret; }