diff options
author | Ilya Dryomov <idryomov@gmail.com> | 2012-01-16 15:04:47 -0500 |
---|---|---|
committer | Ilya Dryomov <idryomov@gmail.com> | 2012-01-16 15:04:47 -0500 |
commit | f43ffb60fd94e98be02780944e182ade6653b916 (patch) | |
tree | 50cab47a03c223d0641d8fe62805e71f5cffef1a /fs/btrfs/volumes.c | |
parent | c9e9f97bdfb64d06e9520f8e4f37674ac21cc9bc (diff) |
Btrfs: add basic infrastructure for selective balancing
This allows to have a separate set of filters for each chunk type
(data,meta,sys). The code however is generic and switch on chunk type
is only done once.
This commit also adds a type filter: it allows to balance for example
meta and system chunks w/o touching data ones.
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r-- | fs/btrfs/volumes.c | 59 |
1 files changed, 57 insertions, 2 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 9fc06e6bc51a..91bbf6e774c0 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -2102,6 +2102,30 @@ static void unset_balance_control(struct btrfs_fs_info *fs_info) | |||
2102 | kfree(bctl); | 2102 | kfree(bctl); |
2103 | } | 2103 | } |
2104 | 2104 | ||
2105 | static int should_balance_chunk(struct btrfs_root *root, | ||
2106 | struct extent_buffer *leaf, | ||
2107 | struct btrfs_chunk *chunk, u64 chunk_offset) | ||
2108 | { | ||
2109 | struct btrfs_balance_control *bctl = root->fs_info->balance_ctl; | ||
2110 | struct btrfs_balance_args *bargs = NULL; | ||
2111 | u64 chunk_type = btrfs_chunk_type(leaf, chunk); | ||
2112 | |||
2113 | /* type filter */ | ||
2114 | if (!((chunk_type & BTRFS_BLOCK_GROUP_TYPE_MASK) & | ||
2115 | (bctl->flags & BTRFS_BALANCE_TYPE_MASK))) { | ||
2116 | return 0; | ||
2117 | } | ||
2118 | |||
2119 | if (chunk_type & BTRFS_BLOCK_GROUP_DATA) | ||
2120 | bargs = &bctl->data; | ||
2121 | else if (chunk_type & BTRFS_BLOCK_GROUP_SYSTEM) | ||
2122 | bargs = &bctl->sys; | ||
2123 | else if (chunk_type & BTRFS_BLOCK_GROUP_METADATA) | ||
2124 | bargs = &bctl->meta; | ||
2125 | |||
2126 | return 1; | ||
2127 | } | ||
2128 | |||
2105 | static u64 div_factor(u64 num, int factor) | 2129 | static u64 div_factor(u64 num, int factor) |
2106 | { | 2130 | { |
2107 | if (factor == 10) | 2131 | if (factor == 10) |
@@ -2119,10 +2143,13 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info) | |||
2119 | struct btrfs_device *device; | 2143 | struct btrfs_device *device; |
2120 | u64 old_size; | 2144 | u64 old_size; |
2121 | u64 size_to_free; | 2145 | u64 size_to_free; |
2146 | struct btrfs_chunk *chunk; | ||
2122 | struct btrfs_path *path; | 2147 | struct btrfs_path *path; |
2123 | struct btrfs_key key; | 2148 | struct btrfs_key key; |
2124 | struct btrfs_key found_key; | 2149 | struct btrfs_key found_key; |
2125 | struct btrfs_trans_handle *trans; | 2150 | struct btrfs_trans_handle *trans; |
2151 | struct extent_buffer *leaf; | ||
2152 | int slot; | ||
2126 | int ret; | 2153 | int ret; |
2127 | int enospc_errors = 0; | 2154 | int enospc_errors = 0; |
2128 | 2155 | ||
@@ -2179,8 +2206,10 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info) | |||
2179 | break; | 2206 | break; |
2180 | } | 2207 | } |
2181 | 2208 | ||
2182 | btrfs_item_key_to_cpu(path->nodes[0], &found_key, | 2209 | leaf = path->nodes[0]; |
2183 | path->slots[0]); | 2210 | slot = path->slots[0]; |
2211 | btrfs_item_key_to_cpu(leaf, &found_key, slot); | ||
2212 | |||
2184 | if (found_key.objectid != key.objectid) | 2213 | if (found_key.objectid != key.objectid) |
2185 | break; | 2214 | break; |
2186 | 2215 | ||
@@ -2188,7 +2217,14 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info) | |||
2188 | if (found_key.offset == 0) | 2217 | if (found_key.offset == 0) |
2189 | break; | 2218 | break; |
2190 | 2219 | ||
2220 | chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk); | ||
2221 | |||
2222 | ret = should_balance_chunk(chunk_root, leaf, chunk, | ||
2223 | found_key.offset); | ||
2191 | btrfs_release_path(path); | 2224 | btrfs_release_path(path); |
2225 | if (!ret) | ||
2226 | goto loop; | ||
2227 | |||
2192 | ret = btrfs_relocate_chunk(chunk_root, | 2228 | ret = btrfs_relocate_chunk(chunk_root, |
2193 | chunk_root->root_key.objectid, | 2229 | chunk_root->root_key.objectid, |
2194 | found_key.objectid, | 2230 | found_key.objectid, |
@@ -2197,6 +2233,7 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info) | |||
2197 | goto error; | 2233 | goto error; |
2198 | if (ret == -ENOSPC) | 2234 | if (ret == -ENOSPC) |
2199 | enospc_errors++; | 2235 | enospc_errors++; |
2236 | loop: | ||
2200 | key.offset = found_key.offset - 1; | 2237 | key.offset = found_key.offset - 1; |
2201 | } | 2238 | } |
2202 | 2239 | ||
@@ -2227,6 +2264,7 @@ int btrfs_balance(struct btrfs_balance_control *bctl, | |||
2227 | struct btrfs_ioctl_balance_args *bargs) | 2264 | struct btrfs_ioctl_balance_args *bargs) |
2228 | { | 2265 | { |
2229 | struct btrfs_fs_info *fs_info = bctl->fs_info; | 2266 | struct btrfs_fs_info *fs_info = bctl->fs_info; |
2267 | u64 allowed; | ||
2230 | int ret; | 2268 | int ret; |
2231 | 2269 | ||
2232 | if (btrfs_fs_closing(fs_info)) { | 2270 | if (btrfs_fs_closing(fs_info)) { |
@@ -2234,6 +2272,23 @@ int btrfs_balance(struct btrfs_balance_control *bctl, | |||
2234 | goto out; | 2272 | goto out; |
2235 | } | 2273 | } |
2236 | 2274 | ||
2275 | /* | ||
2276 | * In case of mixed groups both data and meta should be picked, | ||
2277 | * and identical options should be given for both of them. | ||
2278 | */ | ||
2279 | allowed = btrfs_super_incompat_flags(fs_info->super_copy); | ||
2280 | if ((allowed & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS) && | ||
2281 | (bctl->flags & (BTRFS_BALANCE_DATA | BTRFS_BALANCE_METADATA))) { | ||
2282 | if (!(bctl->flags & BTRFS_BALANCE_DATA) || | ||
2283 | !(bctl->flags & BTRFS_BALANCE_METADATA) || | ||
2284 | memcmp(&bctl->data, &bctl->meta, sizeof(bctl->data))) { | ||
2285 | printk(KERN_ERR "btrfs: with mixed groups data and " | ||
2286 | "metadata balance options must be the same\n"); | ||
2287 | ret = -EINVAL; | ||
2288 | goto out; | ||
2289 | } | ||
2290 | } | ||
2291 | |||
2237 | set_balance_control(bctl); | 2292 | set_balance_control(bctl); |
2238 | 2293 | ||
2239 | mutex_unlock(&fs_info->balance_mutex); | 2294 | mutex_unlock(&fs_info->balance_mutex); |