diff options
author | Ilya Dryomov <idryomov@gmail.com> | 2012-01-16 15:04:48 -0500 |
---|---|---|
committer | Ilya Dryomov <idryomov@gmail.com> | 2012-01-16 15:04:48 -0500 |
commit | 94e60d5a5c4b98a32b1077dec88df09ada712376 (patch) | |
tree | 149b9c9f68b64c7aa6e4b07bf12940a6e27591ca /fs/btrfs/volumes.c | |
parent | 409d404b461afa9738619f249fd7f62a366b68c2 (diff) |
Btrfs: devid subset filter
Select chunks which have at least one byte of at least one stripe
located on a device with devid X in a given [pstart,pend) physical
address range.
This filter only works when devid filter is turned on.
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r-- | fs/btrfs/volumes.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 9ff5cd09a256..c60071a448a5 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -2167,6 +2167,46 @@ static int chunk_devid_filter(struct extent_buffer *leaf, | |||
2167 | return 1; | 2167 | return 1; |
2168 | } | 2168 | } |
2169 | 2169 | ||
2170 | /* [pstart, pend) */ | ||
2171 | static int chunk_drange_filter(struct extent_buffer *leaf, | ||
2172 | struct btrfs_chunk *chunk, | ||
2173 | u64 chunk_offset, | ||
2174 | struct btrfs_balance_args *bargs) | ||
2175 | { | ||
2176 | struct btrfs_stripe *stripe; | ||
2177 | int num_stripes = btrfs_chunk_num_stripes(leaf, chunk); | ||
2178 | u64 stripe_offset; | ||
2179 | u64 stripe_length; | ||
2180 | int factor; | ||
2181 | int i; | ||
2182 | |||
2183 | if (!(bargs->flags & BTRFS_BALANCE_ARGS_DEVID)) | ||
2184 | return 0; | ||
2185 | |||
2186 | if (btrfs_chunk_type(leaf, chunk) & (BTRFS_BLOCK_GROUP_DUP | | ||
2187 | BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10)) | ||
2188 | factor = 2; | ||
2189 | else | ||
2190 | factor = 1; | ||
2191 | factor = num_stripes / factor; | ||
2192 | |||
2193 | for (i = 0; i < num_stripes; i++) { | ||
2194 | stripe = btrfs_stripe_nr(chunk, i); | ||
2195 | if (btrfs_stripe_devid(leaf, stripe) != bargs->devid) | ||
2196 | continue; | ||
2197 | |||
2198 | stripe_offset = btrfs_stripe_offset(leaf, stripe); | ||
2199 | stripe_length = btrfs_chunk_length(leaf, chunk); | ||
2200 | do_div(stripe_length, factor); | ||
2201 | |||
2202 | if (stripe_offset < bargs->pend && | ||
2203 | stripe_offset + stripe_length > bargs->pstart) | ||
2204 | return 0; | ||
2205 | } | ||
2206 | |||
2207 | return 1; | ||
2208 | } | ||
2209 | |||
2170 | static int should_balance_chunk(struct btrfs_root *root, | 2210 | static int should_balance_chunk(struct btrfs_root *root, |
2171 | struct extent_buffer *leaf, | 2211 | struct extent_buffer *leaf, |
2172 | struct btrfs_chunk *chunk, u64 chunk_offset) | 2212 | struct btrfs_chunk *chunk, u64 chunk_offset) |
@@ -2206,6 +2246,12 @@ static int should_balance_chunk(struct btrfs_root *root, | |||
2206 | return 0; | 2246 | return 0; |
2207 | } | 2247 | } |
2208 | 2248 | ||
2249 | /* drange filter, makes sense only with devid filter */ | ||
2250 | if ((bargs->flags & BTRFS_BALANCE_ARGS_DRANGE) && | ||
2251 | chunk_drange_filter(leaf, chunk, chunk_offset, bargs)) { | ||
2252 | return 0; | ||
2253 | } | ||
2254 | |||
2209 | return 1; | 2255 | return 1; |
2210 | } | 2256 | } |
2211 | 2257 | ||