diff options
-rw-r--r-- | fs/btrfs/ctree.h | 3 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 1 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 28 | ||||
-rw-r--r-- | fs/btrfs/super.c | 12 |
4 files changed, 42 insertions, 2 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index ad96495dedc5..213535f45da2 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -881,6 +881,9 @@ struct btrfs_fs_info { | |||
881 | u64 metadata_alloc_profile; | 881 | u64 metadata_alloc_profile; |
882 | u64 system_alloc_profile; | 882 | u64 system_alloc_profile; |
883 | 883 | ||
884 | unsigned data_chunk_allocations; | ||
885 | unsigned metadata_ratio; | ||
886 | |||
884 | void *bdev_holder; | 887 | void *bdev_holder; |
885 | }; | 888 | }; |
886 | 889 | ||
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index a6b83744b05d..44c94d808e2b 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -1604,6 +1604,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1604 | fs_info->btree_inode = new_inode(sb); | 1604 | fs_info->btree_inode = new_inode(sb); |
1605 | fs_info->btree_inode->i_ino = 1; | 1605 | fs_info->btree_inode->i_ino = 1; |
1606 | fs_info->btree_inode->i_nlink = 1; | 1606 | fs_info->btree_inode->i_nlink = 1; |
1607 | fs_info->metadata_ratio = 8; | ||
1607 | 1608 | ||
1608 | fs_info->thread_pool_size = min_t(unsigned long, | 1609 | fs_info->thread_pool_size = min_t(unsigned long, |
1609 | num_online_cpus() + 2, 8); | 1610 | num_online_cpus() + 2, 8); |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 178df4c67de4..2895a8373232 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -1918,15 +1918,29 @@ void btrfs_delalloc_free_space(struct btrfs_root *root, struct inode *inode, | |||
1918 | spin_unlock(&info->lock); | 1918 | spin_unlock(&info->lock); |
1919 | } | 1919 | } |
1920 | 1920 | ||
1921 | static void force_metadata_allocation(struct btrfs_fs_info *info) | ||
1922 | { | ||
1923 | struct list_head *head = &info->space_info; | ||
1924 | struct btrfs_space_info *found; | ||
1925 | |||
1926 | rcu_read_lock(); | ||
1927 | list_for_each_entry_rcu(found, head, list) { | ||
1928 | if (found->flags & BTRFS_BLOCK_GROUP_METADATA) | ||
1929 | found->force_alloc = 1; | ||
1930 | } | ||
1931 | rcu_read_unlock(); | ||
1932 | } | ||
1933 | |||
1921 | static int do_chunk_alloc(struct btrfs_trans_handle *trans, | 1934 | static int do_chunk_alloc(struct btrfs_trans_handle *trans, |
1922 | struct btrfs_root *extent_root, u64 alloc_bytes, | 1935 | struct btrfs_root *extent_root, u64 alloc_bytes, |
1923 | u64 flags, int force) | 1936 | u64 flags, int force) |
1924 | { | 1937 | { |
1925 | struct btrfs_space_info *space_info; | 1938 | struct btrfs_space_info *space_info; |
1939 | struct btrfs_fs_info *fs_info = extent_root->fs_info; | ||
1926 | u64 thresh; | 1940 | u64 thresh; |
1927 | int ret = 0; | 1941 | int ret = 0; |
1928 | 1942 | ||
1929 | mutex_lock(&extent_root->fs_info->chunk_mutex); | 1943 | mutex_lock(&fs_info->chunk_mutex); |
1930 | 1944 | ||
1931 | flags = btrfs_reduce_alloc_profile(extent_root, flags); | 1945 | flags = btrfs_reduce_alloc_profile(extent_root, flags); |
1932 | 1946 | ||
@@ -1958,6 +1972,18 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, | |||
1958 | } | 1972 | } |
1959 | spin_unlock(&space_info->lock); | 1973 | spin_unlock(&space_info->lock); |
1960 | 1974 | ||
1975 | /* | ||
1976 | * if we're doing a data chunk, go ahead and make sure that | ||
1977 | * we keep a reasonable number of metadata chunks allocated in the | ||
1978 | * FS as well. | ||
1979 | */ | ||
1980 | if (flags & BTRFS_BLOCK_GROUP_DATA) { | ||
1981 | fs_info->data_chunk_allocations++; | ||
1982 | if (!(fs_info->data_chunk_allocations % | ||
1983 | fs_info->metadata_ratio)) | ||
1984 | force_metadata_allocation(fs_info); | ||
1985 | } | ||
1986 | |||
1961 | ret = btrfs_alloc_chunk(trans, extent_root, flags); | 1987 | ret = btrfs_alloc_chunk(trans, extent_root, flags); |
1962 | if (ret) | 1988 | if (ret) |
1963 | space_info->full = 1; | 1989 | space_info->full = 1; |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 9744af9d71e9..30c9a8ca2a54 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -68,7 +68,7 @@ enum { | |||
68 | Opt_degraded, Opt_subvol, Opt_device, Opt_nodatasum, Opt_nodatacow, | 68 | Opt_degraded, Opt_subvol, Opt_device, Opt_nodatasum, Opt_nodatacow, |
69 | Opt_max_extent, Opt_max_inline, Opt_alloc_start, Opt_nobarrier, | 69 | Opt_max_extent, Opt_max_inline, Opt_alloc_start, Opt_nobarrier, |
70 | Opt_ssd, Opt_thread_pool, Opt_noacl, Opt_compress, Opt_notreelog, | 70 | Opt_ssd, Opt_thread_pool, Opt_noacl, Opt_compress, Opt_notreelog, |
71 | Opt_flushoncommit, Opt_err, | 71 | Opt_ratio, Opt_flushoncommit, Opt_err, |
72 | }; | 72 | }; |
73 | 73 | ||
74 | static match_table_t tokens = { | 74 | static match_table_t tokens = { |
@@ -87,6 +87,7 @@ static match_table_t tokens = { | |||
87 | {Opt_noacl, "noacl"}, | 87 | {Opt_noacl, "noacl"}, |
88 | {Opt_notreelog, "notreelog"}, | 88 | {Opt_notreelog, "notreelog"}, |
89 | {Opt_flushoncommit, "flushoncommit"}, | 89 | {Opt_flushoncommit, "flushoncommit"}, |
90 | {Opt_ratio, "metadata_ratio=%d"}, | ||
90 | {Opt_err, NULL}, | 91 | {Opt_err, NULL}, |
91 | }; | 92 | }; |
92 | 93 | ||
@@ -234,6 +235,15 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) | |||
234 | printk(KERN_INFO "btrfs: turning on flush-on-commit\n"); | 235 | printk(KERN_INFO "btrfs: turning on flush-on-commit\n"); |
235 | btrfs_set_opt(info->mount_opt, FLUSHONCOMMIT); | 236 | btrfs_set_opt(info->mount_opt, FLUSHONCOMMIT); |
236 | break; | 237 | break; |
238 | case Opt_ratio: | ||
239 | intarg = 0; | ||
240 | match_int(&args[0], &intarg); | ||
241 | if (intarg) { | ||
242 | info->metadata_ratio = intarg; | ||
243 | printk(KERN_INFO "btrfs: metadata ratio %d\n", | ||
244 | info->metadata_ratio); | ||
245 | } | ||
246 | break; | ||
237 | default: | 247 | default: |
238 | break; | 248 | break; |
239 | } | 249 | } |