diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/btrfs/volumes.c | 481 | ||||
| -rw-r--r-- | fs/btrfs/volumes.h | 1 |
2 files changed, 177 insertions, 305 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 45c592a7335..ab55bfc31a0 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
| @@ -2268,262 +2268,204 @@ static int btrfs_add_system_chunk(struct btrfs_trans_handle *trans, | |||
| 2268 | return 0; | 2268 | return 0; |
| 2269 | } | 2269 | } |
| 2270 | 2270 | ||
| 2271 | static noinline u64 chunk_bytes_by_type(u64 type, u64 calc_size, | 2271 | /* |
| 2272 | int num_stripes, int sub_stripes) | 2272 | * sort the devices in descending order by max_avail, total_avail |
| 2273 | */ | ||
| 2274 | static int btrfs_cmp_device_info(const void *a, const void *b) | ||
| 2273 | { | 2275 | { |
| 2274 | if (type & (BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_DUP)) | 2276 | const struct btrfs_device_info *di_a = a; |
| 2275 | return calc_size; | 2277 | const struct btrfs_device_info *di_b = b; |
| 2276 | else if (type & BTRFS_BLOCK_GROUP_RAID10) | 2278 | |
| 2277 | return calc_size * (num_stripes / sub_stripes); | 2279 | if (di_a->max_avail > di_b->max_avail) |
| 2278 | else | 2280 | return -1; |
| 2279 | return calc_size * num_stripes; | 2281 | if (di_a->max_avail < di_b->max_avail) |
| 2282 | return 1; | ||
| 2283 | if (di_a->total_avail > di_b->total_avail) | ||
| 2284 | return -1; | ||
| 2285 | if (di_a->total_avail < di_b->total_avail) | ||
| 2286 | return 1; | ||
| 2287 | return 0; | ||
| 2280 | } | 2288 | } |
| 2281 | 2289 | ||
| 2282 | static int __btrfs_calc_nstripes(struct btrfs_fs_devices *fs_devices, u64 type, | 2290 | static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, |
| 2283 | int *num_stripes, int *min_stripes, | 2291 | struct btrfs_root *extent_root, |
| 2284 | int *sub_stripes) | 2292 | struct map_lookup **map_ret, |
| 2293 | u64 *num_bytes_out, u64 *stripe_size_out, | ||
| 2294 | u64 start, u64 type) | ||
| 2285 | { | 2295 | { |
| 2286 | *num_stripes = 1; | 2296 | struct btrfs_fs_info *info = extent_root->fs_info; |
| 2287 | *min_stripes = 1; | 2297 | struct btrfs_fs_devices *fs_devices = info->fs_devices; |
| 2288 | *sub_stripes = 0; | 2298 | struct list_head *cur; |
| 2299 | struct map_lookup *map = NULL; | ||
| 2300 | struct extent_map_tree *em_tree; | ||
| 2301 | struct extent_map *em; | ||
| 2302 | struct btrfs_device_info *devices_info = NULL; | ||
| 2303 | u64 total_avail; | ||
| 2304 | int num_stripes; /* total number of stripes to allocate */ | ||
| 2305 | int sub_stripes; /* sub_stripes info for map */ | ||
| 2306 | int dev_stripes; /* stripes per dev */ | ||
| 2307 | int devs_max; /* max devs to use */ | ||
| 2308 | int devs_min; /* min devs needed */ | ||
| 2309 | int devs_increment; /* ndevs has to be a multiple of this */ | ||
| 2310 | int ncopies; /* how many copies to data has */ | ||
| 2311 | int ret; | ||
| 2312 | u64 max_stripe_size; | ||
| 2313 | u64 max_chunk_size; | ||
| 2314 | u64 stripe_size; | ||
| 2315 | u64 num_bytes; | ||
| 2316 | int ndevs; | ||
| 2317 | int i; | ||
| 2318 | int j; | ||
| 2289 | 2319 | ||
| 2290 | if (type & (BTRFS_BLOCK_GROUP_RAID0)) { | 2320 | if ((type & BTRFS_BLOCK_GROUP_RAID1) && |
| 2291 | *num_stripes = fs_devices->rw_devices; | 2321 | (type & BTRFS_BLOCK_GROUP_DUP)) { |
| 2292 | *min_stripes = 2; | 2322 | WARN_ON(1); |
| 2293 | } | 2323 | type &= ~BTRFS_BLOCK_GROUP_DUP; |
| 2294 | if (type & (BTRFS_BLOCK_GROUP_DUP)) { | ||
| 2295 | *num_stripes = 2; | ||
| 2296 | *min_stripes = 2; | ||
| 2297 | } | ||
| 2298 | if (type & (BTRFS_BLOCK_GROUP_RAID1)) { | ||
| 2299 | if (fs_devices->rw_devices < 2) | ||
| 2300 | return -ENOSPC; | ||
| 2301 | *num_stripes = 2; | ||
| 2302 | *min_stripes = 2; | ||
| 2303 | } | ||
| 2304 | if (type & (BTRFS_BLOCK_GROUP_RAID10)) { | ||
| 2305 | *num_stripes = fs_devices->rw_devices; | ||
| 2306 | if (*num_stripes < 4) | ||
| 2307 | return -ENOSPC; | ||
| 2308 | *num_stripes &= ~(u32)1; | ||
| 2309 | *sub_stripes = 2; | ||
| 2310 | *min_stripes = 4; | ||
| 2311 | } | 2324 | } |
| 2312 | 2325 | ||
| 2313 | return 0; | 2326 | if (list_empty(&fs_devices->alloc_list)) |
| 2314 | } | 2327 | return -ENOSPC; |
| 2315 | 2328 | ||
| 2316 | static u64 __btrfs_calc_stripe_size(struct btrfs_fs_devices *fs_devices, | 2329 | sub_stripes = 1; |
| 2317 | u64 proposed_size, u64 type, | 2330 | dev_stripes = 1; |
| 2318 | int num_stripes, int small_stripe) | 2331 | devs_increment = 1; |
| 2319 | { | 2332 | ncopies = 1; |
| 2320 | int min_stripe_size = 1 * 1024 * 1024; | 2333 | devs_max = 0; /* 0 == as many as possible */ |
| 2321 | u64 calc_size = proposed_size; | 2334 | devs_min = 1; |
| 2322 | u64 max_chunk_size = calc_size; | ||
| 2323 | int ncopies = 1; | ||
| 2324 | 2335 | ||
| 2325 | if (type & (BTRFS_BLOCK_GROUP_RAID1 | | 2336 | /* |
| 2326 | BTRFS_BLOCK_GROUP_DUP | | 2337 | * define the properties of each RAID type. |
| 2327 | BTRFS_BLOCK_GROUP_RAID10)) | 2338 | * FIXME: move this to a global table and use it in all RAID |
| 2339 | * calculation code | ||
| 2340 | */ | ||
| 2341 | if (type & (BTRFS_BLOCK_GROUP_DUP)) { | ||
| 2342 | dev_stripes = 2; | ||
| 2328 | ncopies = 2; | 2343 | ncopies = 2; |
| 2344 | devs_max = 1; | ||
| 2345 | } else if (type & (BTRFS_BLOCK_GROUP_RAID0)) { | ||
| 2346 | devs_min = 2; | ||
| 2347 | } else if (type & (BTRFS_BLOCK_GROUP_RAID1)) { | ||
| 2348 | devs_increment = 2; | ||
| 2349 | ncopies = 2; | ||
| 2350 | devs_max = 2; | ||
| 2351 | devs_min = 2; | ||
| 2352 | } else if (type & (BTRFS_BLOCK_GROUP_RAID10)) { | ||
| 2353 | sub_stripes = 2; | ||
| 2354 | devs_increment = 2; | ||
| 2355 | ncopies = 2; | ||
| 2356 | devs_min = 4; | ||
| 2357 | } else { | ||
| 2358 | devs_max = 1; | ||
| 2359 | } | ||
| 2329 | 2360 | ||
| 2330 | if (type & BTRFS_BLOCK_GROUP_DATA) { | 2361 | if (type & BTRFS_BLOCK_GROUP_DATA) { |
| 2331 | max_chunk_size = 10 * calc_size; | 2362 | max_stripe_size = 1024 * 1024 * 1024; |
| 2332 | min_stripe_size = 64 * 1024 * 1024; | 2363 | max_chunk_size = 10 * max_stripe_size; |
| 2333 | } else if (type & BTRFS_BLOCK_GROUP_METADATA) { | 2364 | } else if (type & BTRFS_BLOCK_GROUP_METADATA) { |
| 2334 | max_chunk_size = 256 * 1024 * 1024; | 2365 | max_stripe_size = 256 * 1024 * 1024; |
| 2335 | min_stripe_size = 32 * 1024 * 1024; | 2366 | max_chunk_size = max_stripe_size; |
| 2336 | } else if (type & BTRFS_BLOCK_GROUP_SYSTEM) { | 2367 | } else if (type & BTRFS_BLOCK_GROUP_SYSTEM) { |
| 2337 | calc_size = 8 * 1024 * 1024; | 2368 | max_stripe_size = 8 * 1024 * 1024; |
| 2338 | max_chunk_size = calc_size * 2; | 2369 | max_chunk_size = 2 * max_stripe_size; |
| 2339 | min_stripe_size = 1 * 1024 * 1024; | 2370 | } else { |
| 2371 | printk(KERN_ERR "btrfs: invalid chunk type 0x%llx requested\n", | ||
| 2372 | type); | ||
| 2373 | BUG_ON(1); | ||
| 2340 | } | 2374 | } |
| 2341 | 2375 | ||
| 2342 | /* we don't want a chunk larger than 10% of writeable space */ | 2376 | /* we don't want a chunk larger than 10% of writeable space */ |
| 2343 | max_chunk_size = min(div_factor(fs_devices->total_rw_bytes, 1), | 2377 | max_chunk_size = min(div_factor(fs_devices->total_rw_bytes, 1), |
| 2344 | max_chunk_size); | 2378 | max_chunk_size); |
| 2345 | 2379 | ||
| 2346 | if (calc_size * num_stripes > max_chunk_size * ncopies) { | 2380 | devices_info = kzalloc(sizeof(*devices_info) * fs_devices->rw_devices, |
| 2347 | calc_size = max_chunk_size * ncopies; | 2381 | GFP_NOFS); |
| 2348 | do_div(calc_size, num_stripes); | 2382 | if (!devices_info) |
| 2349 | do_div(calc_size, BTRFS_STRIPE_LEN); | 2383 | return -ENOMEM; |
| 2350 | calc_size *= BTRFS_STRIPE_LEN; | ||
| 2351 | } | ||
| 2352 | 2384 | ||
| 2353 | /* we don't want tiny stripes */ | 2385 | cur = fs_devices->alloc_list.next; |
| 2354 | if (!small_stripe) | ||
| 2355 | calc_size = max_t(u64, min_stripe_size, calc_size); | ||
| 2356 | 2386 | ||
| 2357 | /* | 2387 | /* |
| 2358 | * we're about to do_div by the BTRFS_STRIPE_LEN so lets make sure | 2388 | * in the first pass through the devices list, we gather information |
| 2359 | * we end up with something bigger than a stripe | 2389 | * about the available holes on each device. |
| 2360 | */ | 2390 | */ |
| 2361 | calc_size = max_t(u64, calc_size, BTRFS_STRIPE_LEN); | 2391 | ndevs = 0; |
| 2362 | 2392 | while (cur != &fs_devices->alloc_list) { | |
| 2363 | do_div(calc_size, BTRFS_STRIPE_LEN); | 2393 | struct btrfs_device *device; |
| 2364 | calc_size *= BTRFS_STRIPE_LEN; | 2394 | u64 max_avail; |
| 2365 | 2395 | u64 dev_offset; | |
| 2366 | return calc_size; | ||
| 2367 | } | ||
| 2368 | 2396 | ||
| 2369 | static struct map_lookup *__shrink_map_lookup_stripes(struct map_lookup *map, | 2397 | device = list_entry(cur, struct btrfs_device, dev_alloc_list); |
| 2370 | int num_stripes) | ||
| 2371 | { | ||
| 2372 | struct map_lookup *new; | ||
| 2373 | size_t len = map_lookup_size(num_stripes); | ||
| 2374 | |||
| 2375 | BUG_ON(map->num_stripes < num_stripes); | ||
| 2376 | |||
| 2377 | if (map->num_stripes == num_stripes) | ||
| 2378 | return map; | ||
| 2379 | |||
| 2380 | new = kmalloc(len, GFP_NOFS); | ||
| 2381 | if (!new) { | ||
| 2382 | /* just change map->num_stripes */ | ||
| 2383 | map->num_stripes = num_stripes; | ||
| 2384 | return map; | ||
| 2385 | } | ||
| 2386 | |||
| 2387 | memcpy(new, map, len); | ||
| 2388 | new->num_stripes = num_stripes; | ||
| 2389 | kfree(map); | ||
| 2390 | return new; | ||
| 2391 | } | ||
| 2392 | |||
| 2393 | /* | ||
| 2394 | * helper to allocate device space from btrfs_device_info, in which we stored | ||
| 2395 | * max free space information of every device. It is used when we can not | ||
| 2396 | * allocate chunks by default size. | ||
| 2397 | * | ||
| 2398 | * By this helper, we can allocate a new chunk as larger as possible. | ||
| 2399 | */ | ||
| 2400 | static int __btrfs_alloc_tiny_space(struct btrfs_trans_handle *trans, | ||
| 2401 | struct btrfs_fs_devices *fs_devices, | ||
| 2402 | struct btrfs_device_info *devices, | ||
| 2403 | int nr_device, u64 type, | ||
| 2404 | struct map_lookup **map_lookup, | ||
| 2405 | int min_stripes, u64 *stripe_size) | ||
| 2406 | { | ||
| 2407 | int i, index, sort_again = 0; | ||
| 2408 | int min_devices = min_stripes; | ||
| 2409 | u64 max_avail, min_free; | ||
| 2410 | struct map_lookup *map = *map_lookup; | ||
| 2411 | int ret; | ||
| 2412 | 2398 | ||
| 2413 | if (nr_device < min_stripes) | 2399 | cur = cur->next; |
| 2414 | return -ENOSPC; | ||
| 2415 | 2400 | ||
| 2416 | btrfs_descending_sort_devices(devices, nr_device); | 2401 | if (!device->writeable) { |
| 2402 | printk(KERN_ERR | ||
| 2403 | "btrfs: read-only device in alloc_list\n"); | ||
| 2404 | WARN_ON(1); | ||
| 2405 | continue; | ||
| 2406 | } | ||
| 2417 | 2407 | ||
| 2418 | max_avail = devices[0].max_avail; | 2408 | if (!device->in_fs_metadata) |
| 2419 | if (!max_avail) | 2409 | continue; |
| 2420 | return -ENOSPC; | ||
| 2421 | 2410 | ||
| 2422 | for (i = 0; i < nr_device; i++) { | 2411 | if (device->total_bytes > device->bytes_used) |
| 2423 | /* | 2412 | total_avail = device->total_bytes - device->bytes_used; |
| 2424 | * if dev_offset = 0, it means the free space of this device | 2413 | else |
| 2425 | * is less than what we need, and we didn't search max avail | 2414 | total_avail = 0; |
| 2426 | * extent on this device, so do it now. | 2415 | /* avail is off by max(alloc_start, 1MB), but that is the same |
| 2416 | * for all devices, so it doesn't hurt the sorting later on | ||
| 2427 | */ | 2417 | */ |
| 2428 | if (!devices[i].dev_offset) { | ||
| 2429 | ret = find_free_dev_extent(trans, devices[i].dev, | ||
| 2430 | max_avail, | ||
| 2431 | &devices[i].dev_offset, | ||
| 2432 | &devices[i].max_avail); | ||
| 2433 | if (ret != 0 && ret != -ENOSPC) | ||
| 2434 | return ret; | ||
| 2435 | sort_again = 1; | ||
| 2436 | } | ||
| 2437 | } | ||
| 2438 | 2418 | ||
| 2439 | /* we update the max avail free extent of each devices, sort again */ | 2419 | ret = find_free_dev_extent(trans, device, |
| 2440 | if (sort_again) | 2420 | max_stripe_size * dev_stripes, |
| 2441 | btrfs_descending_sort_devices(devices, nr_device); | 2421 | &dev_offset, &max_avail); |
| 2442 | 2422 | if (ret && ret != -ENOSPC) | |
| 2443 | if (type & BTRFS_BLOCK_GROUP_DUP) | 2423 | goto error; |
| 2444 | min_devices = 1; | ||
| 2445 | 2424 | ||
| 2446 | if (!devices[min_devices - 1].max_avail) | 2425 | if (ret == 0) |
| 2447 | return -ENOSPC; | 2426 | max_avail = max_stripe_size * dev_stripes; |
| 2448 | 2427 | ||
| 2449 | max_avail = devices[min_devices - 1].max_avail; | 2428 | if (max_avail < BTRFS_STRIPE_LEN * dev_stripes) |
| 2450 | if (type & BTRFS_BLOCK_GROUP_DUP) | 2429 | continue; |
| 2451 | do_div(max_avail, 2); | ||
| 2452 | 2430 | ||
| 2453 | max_avail = __btrfs_calc_stripe_size(fs_devices, max_avail, type, | 2431 | devices_info[ndevs].dev_offset = dev_offset; |
| 2454 | min_stripes, 1); | 2432 | devices_info[ndevs].max_avail = max_avail; |
| 2455 | if (type & BTRFS_BLOCK_GROUP_DUP) | 2433 | devices_info[ndevs].total_avail = total_avail; |
| 2456 | min_free = max_avail * 2; | 2434 | devices_info[ndevs].dev = device; |
| 2457 | else | 2435 | ++ndevs; |
| 2458 | min_free = max_avail; | 2436 | } |
| 2459 | 2437 | ||
| 2460 | if (min_free > devices[min_devices - 1].max_avail) | 2438 | /* |
| 2461 | return -ENOSPC; | 2439 | * now sort the devices by hole size / available space |
| 2440 | */ | ||
| 2441 | sort(devices_info, ndevs, sizeof(struct btrfs_device_info), | ||
| 2442 | btrfs_cmp_device_info, NULL); | ||
| 2462 | 2443 | ||
| 2463 | map = __shrink_map_lookup_stripes(map, min_stripes); | 2444 | /* round down to number of usable stripes */ |
| 2464 | *stripe_size = max_avail; | 2445 | ndevs -= ndevs % devs_increment; |
| 2465 | 2446 | ||
| 2466 | index = 0; | 2447 | if (ndevs < devs_increment * sub_stripes || ndevs < devs_min) { |
| 2467 | for (i = 0; i < min_stripes; i++) { | 2448 | ret = -ENOSPC; |
| 2468 | map->stripes[i].dev = devices[index].dev; | 2449 | goto error; |
| 2469 | map->stripes[i].physical = devices[index].dev_offset; | ||
| 2470 | if (type & BTRFS_BLOCK_GROUP_DUP) { | ||
| 2471 | i++; | ||
| 2472 | map->stripes[i].dev = devices[index].dev; | ||
| 2473 | map->stripes[i].physical = devices[index].dev_offset + | ||
| 2474 | max_avail; | ||
| 2475 | } | ||
| 2476 | index++; | ||
| 2477 | } | 2450 | } |
| 2478 | *map_lookup = map; | ||
| 2479 | |||
| 2480 | return 0; | ||
| 2481 | } | ||
| 2482 | 2451 | ||
| 2483 | static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | 2452 | if (devs_max && ndevs > devs_max) |
| 2484 | struct btrfs_root *extent_root, | 2453 | ndevs = devs_max; |
| 2485 | struct map_lookup **map_ret, | 2454 | /* |
| 2486 | u64 *num_bytes, u64 *stripe_size, | 2455 | * the primary goal is to maximize the number of stripes, so use as many |
| 2487 | u64 start, u64 type) | 2456 | * devices as possible, even if the stripes are not maximum sized. |
| 2488 | { | 2457 | */ |
| 2489 | struct btrfs_fs_info *info = extent_root->fs_info; | 2458 | stripe_size = devices_info[ndevs-1].max_avail; |
| 2490 | struct btrfs_device *device = NULL; | 2459 | num_stripes = ndevs * dev_stripes; |
| 2491 | struct btrfs_fs_devices *fs_devices = info->fs_devices; | ||
| 2492 | struct list_head *cur; | ||
| 2493 | struct map_lookup *map; | ||
| 2494 | struct extent_map_tree *em_tree; | ||
| 2495 | struct extent_map *em; | ||
| 2496 | struct btrfs_device_info *devices_info; | ||
| 2497 | struct list_head private_devs; | ||
| 2498 | u64 calc_size = 1024 * 1024 * 1024; | ||
| 2499 | u64 min_free; | ||
| 2500 | u64 avail; | ||
| 2501 | u64 dev_offset; | ||
| 2502 | int num_stripes; | ||
| 2503 | int min_stripes; | ||
| 2504 | int sub_stripes; | ||
| 2505 | int min_devices; /* the min number of devices we need */ | ||
| 2506 | int i; | ||
| 2507 | int ret; | ||
| 2508 | int index; | ||
| 2509 | 2460 | ||
| 2510 | if ((type & BTRFS_BLOCK_GROUP_RAID1) && | 2461 | if (stripe_size * num_stripes > max_chunk_size * ncopies) { |
| 2511 | (type & BTRFS_BLOCK_GROUP_DUP)) { | 2462 | stripe_size = max_chunk_size * ncopies; |
| 2512 | WARN_ON(1); | 2463 | do_div(stripe_size, num_stripes); |
| 2513 | type &= ~BTRFS_BLOCK_GROUP_DUP; | ||
| 2514 | } | 2464 | } |
| 2515 | if (list_empty(&fs_devices->alloc_list)) | ||
| 2516 | return -ENOSPC; | ||
| 2517 | |||
| 2518 | ret = __btrfs_calc_nstripes(fs_devices, type, &num_stripes, | ||
| 2519 | &min_stripes, &sub_stripes); | ||
| 2520 | if (ret) | ||
| 2521 | return ret; | ||
| 2522 | 2465 | ||
| 2523 | devices_info = kzalloc(sizeof(*devices_info) * fs_devices->rw_devices, | 2466 | do_div(stripe_size, dev_stripes); |
| 2524 | GFP_NOFS); | 2467 | do_div(stripe_size, BTRFS_STRIPE_LEN); |
| 2525 | if (!devices_info) | 2468 | stripe_size *= BTRFS_STRIPE_LEN; |
| 2526 | return -ENOMEM; | ||
| 2527 | 2469 | ||
| 2528 | map = kmalloc(map_lookup_size(num_stripes), GFP_NOFS); | 2470 | map = kmalloc(map_lookup_size(num_stripes), GFP_NOFS); |
| 2529 | if (!map) { | 2471 | if (!map) { |
| @@ -2532,85 +2474,12 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | |||
| 2532 | } | 2474 | } |
| 2533 | map->num_stripes = num_stripes; | 2475 | map->num_stripes = num_stripes; |
| 2534 | 2476 | ||
| 2535 | cur = fs_devices->alloc_list.next; | 2477 | for (i = 0; i < ndevs; ++i) { |
| 2536 | index = 0; | 2478 | for (j = 0; j < dev_stripes; ++j) { |
| 2537 | i = 0; | 2479 | int s = i * dev_stripes + j; |
| 2538 | 2480 | map->stripes[s].dev = devices_info[i].dev; | |
| 2539 | calc_size = __btrfs_calc_stripe_size(fs_devices, calc_size, type, | 2481 | map->stripes[s].physical = devices_info[i].dev_offset + |
| 2540 | num_stripes, 0); | 2482 | j * stripe_size; |
| 2541 | |||
| 2542 | if (type & BTRFS_BLOCK_GROUP_DUP) { | ||
| 2543 | min_free = calc_size * 2; | ||
| 2544 | min_devices = 1; | ||
| 2545 | } else { | ||
| 2546 | min_free = calc_size; | ||
| 2547 | min_devices = min_stripes; | ||
| 2548 | } | ||
| 2549 | |||
| 2550 | INIT_LIST_HEAD(&private_devs); | ||
| 2551 | while (index < num_stripes) { | ||
| 2552 | device = list_entry(cur, struct btrfs_device, dev_alloc_list); | ||
| 2553 | BUG_ON(!device->writeable); | ||
| 2554 | if (device->total_bytes > device->bytes_used) | ||
| 2555 | avail = device->total_bytes - device->bytes_used; | ||
| 2556 | else | ||
| 2557 | avail = 0; | ||
| 2558 | cur = cur->next; | ||
| 2559 | |||
| 2560 | if (device->in_fs_metadata && avail >= min_free) { | ||
| 2561 | ret = find_free_dev_extent(trans, device, min_free, | ||
| 2562 | &devices_info[i].dev_offset, | ||
| 2563 | &devices_info[i].max_avail); | ||
| 2564 | if (ret == 0) { | ||
| 2565 | list_move_tail(&device->dev_alloc_list, | ||
| 2566 | &private_devs); | ||
| 2567 | map->stripes[index].dev = device; | ||
| 2568 | map->stripes[index].physical = | ||
| 2569 | devices_info[i].dev_offset; | ||
| 2570 | index++; | ||
| 2571 | if (type & BTRFS_BLOCK_GROUP_DUP) { | ||
| 2572 | map->stripes[index].dev = device; | ||
| 2573 | map->stripes[index].physical = | ||
| 2574 | devices_info[i].dev_offset + | ||
| 2575 | calc_size; | ||
| 2576 | index++; | ||
| 2577 | } | ||
| 2578 | } else if (ret != -ENOSPC) | ||
| 2579 | goto error; | ||
| 2580 | |||
| 2581 | devices_info[i].dev = device; | ||
| 2582 | i++; | ||
| 2583 | } else if (device->in_fs_metadata && | ||
| 2584 | avail >= BTRFS_STRIPE_LEN) { | ||
| 2585 | devices_info[i].dev = device; | ||
| 2586 | devices_info[i].max_avail = avail; | ||
| 2587 | i++; | ||
| 2588 | } | ||
| 2589 | |||
| 2590 | if (cur == &fs_devices->alloc_list) | ||
| 2591 | break; | ||
| 2592 | } | ||
| 2593 | |||
| 2594 | list_splice(&private_devs, &fs_devices->alloc_list); | ||
| 2595 | if (index < num_stripes) { | ||
| 2596 | if (index >= min_stripes) { | ||
| 2597 | num_stripes = index; | ||
| 2598 | if (type & (BTRFS_BLOCK_GROUP_RAID10)) { | ||
| 2599 | num_stripes /= sub_stripes; | ||
| 2600 | num_stripes *= sub_stripes; | ||
| 2601 | } | ||
| 2602 | |||
| 2603 | map = __shrink_map_lookup_stripes(map, num_stripes); | ||
| 2604 | } else if (i >= min_devices) { | ||
| 2605 | ret = __btrfs_alloc_tiny_space(trans, fs_devices, | ||
| 2606 | devices_info, i, type, | ||
| 2607 | &map, min_stripes, | ||
| 2608 | &calc_size); | ||
| 2609 | if (ret) | ||
| 2610 | goto error; | ||
| 2611 | } else { | ||
| 2612 | ret = -ENOSPC; | ||
| 2613 | goto error; | ||
| 2614 | } | 2483 | } |
| 2615 | } | 2484 | } |
| 2616 | map->sector_size = extent_root->sectorsize; | 2485 | map->sector_size = extent_root->sectorsize; |
| @@ -2621,11 +2490,12 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | |||
| 2621 | map->sub_stripes = sub_stripes; | 2490 | map->sub_stripes = sub_stripes; |
| 2622 | 2491 | ||
| 2623 | *map_ret = map; | 2492 | *map_ret = map; |
| 2624 | *stripe_size = calc_size; | 2493 | num_bytes = stripe_size * (num_stripes / ncopies); |
| 2625 | *num_bytes = chunk_bytes_by_type(type, calc_size, | 2494 | |
| 2626 | map->num_stripes, sub_stripes); | 2495 | *stripe_size_out = stripe_size; |
| 2496 | *num_bytes_out = num_bytes; | ||
| 2627 | 2497 | ||
| 2628 | trace_btrfs_chunk_alloc(info->chunk_root, map, start, *num_bytes); | 2498 | trace_btrfs_chunk_alloc(info->chunk_root, map, start, num_bytes); |
| 2629 | 2499 | ||
| 2630 | em = alloc_extent_map(GFP_NOFS); | 2500 | em = alloc_extent_map(GFP_NOFS); |
| 2631 | if (!em) { | 2501 | if (!em) { |
| @@ -2634,7 +2504,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | |||
| 2634 | } | 2504 | } |
| 2635 | em->bdev = (struct block_device *)map; | 2505 | em->bdev = (struct block_device *)map; |
| 2636 | em->start = start; | 2506 | em->start = start; |
| 2637 | em->len = *num_bytes; | 2507 | em->len = num_bytes; |
| 2638 | em->block_start = 0; | 2508 | em->block_start = 0; |
| 2639 | em->block_len = em->len; | 2509 | em->block_len = em->len; |
| 2640 | 2510 | ||
| @@ -2647,20 +2517,21 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | |||
| 2647 | 2517 | ||
| 2648 | ret = btrfs_make_block_group(trans, extent_root, 0, type, | 2518 | ret = btrfs_make_block_group(trans, extent_root, 0, type, |
| 2649 | BTRFS_FIRST_CHUNK_TREE_OBJECTID, | 2519 | BTRFS_FIRST_CHUNK_TREE_OBJECTID, |
| 2650 | start, *num_bytes); | 2520 | start, num_bytes); |
| 2651 | BUG_ON(ret); | 2521 | BUG_ON(ret); |
| 2652 | 2522 | ||
| 2653 | index = 0; | 2523 | for (i = 0; i < map->num_stripes; ++i) { |
| 2654 | while (index < map->num_stripes) { | 2524 | struct btrfs_device *device; |
| 2655 | device = map->stripes[index].dev; | 2525 | u64 dev_offset; |
| 2656 | dev_offset = map->stripes[index].physical; | 2526 | |
| 2527 | device = map->stripes[i].dev; | ||
| 2528 | dev_offset = map->stripes[i].physical; | ||
| 2657 | 2529 | ||
| 2658 | ret = btrfs_alloc_dev_extent(trans, device, | 2530 | ret = btrfs_alloc_dev_extent(trans, device, |
| 2659 | info->chunk_root->root_key.objectid, | 2531 | info->chunk_root->root_key.objectid, |
| 2660 | BTRFS_FIRST_CHUNK_TREE_OBJECTID, | 2532 | BTRFS_FIRST_CHUNK_TREE_OBJECTID, |
| 2661 | start, dev_offset, calc_size); | 2533 | start, dev_offset, stripe_size); |
| 2662 | BUG_ON(ret); | 2534 | BUG_ON(ret); |
| 2663 | index++; | ||
| 2664 | } | 2535 | } |
| 2665 | 2536 | ||
| 2666 | kfree(devices_info); | 2537 | kfree(devices_info); |
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index b502f01f79e..37ae6e2126a 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h | |||
| @@ -144,6 +144,7 @@ struct btrfs_device_info { | |||
| 144 | struct btrfs_device *dev; | 144 | struct btrfs_device *dev; |
| 145 | u64 dev_offset; | 145 | u64 dev_offset; |
| 146 | u64 max_avail; | 146 | u64 max_avail; |
| 147 | u64 total_avail; | ||
| 147 | }; | 148 | }; |
| 148 | 149 | ||
| 149 | struct map_lookup { | 150 | struct map_lookup { |
