diff options
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r-- | fs/btrfs/volumes.c | 75 |
1 files changed, 50 insertions, 25 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 7eda483d7b5a..8db7b14bbae8 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -17,6 +17,7 @@ | |||
17 | */ | 17 | */ |
18 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
19 | #include <linux/bio.h> | 19 | #include <linux/bio.h> |
20 | #include <linux/slab.h> | ||
20 | #include <linux/buffer_head.h> | 21 | #include <linux/buffer_head.h> |
21 | #include <linux/blkdev.h> | 22 | #include <linux/blkdev.h> |
22 | #include <linux/random.h> | 23 | #include <linux/random.h> |
@@ -256,13 +257,13 @@ loop_lock: | |||
256 | wake_up(&fs_info->async_submit_wait); | 257 | wake_up(&fs_info->async_submit_wait); |
257 | 258 | ||
258 | BUG_ON(atomic_read(&cur->bi_cnt) == 0); | 259 | BUG_ON(atomic_read(&cur->bi_cnt) == 0); |
259 | submit_bio(cur->bi_rw, cur); | ||
260 | num_run++; | ||
261 | batch_run++; | ||
262 | 260 | ||
263 | if (bio_rw_flagged(cur, BIO_RW_SYNCIO)) | 261 | if (bio_rw_flagged(cur, BIO_RW_SYNCIO)) |
264 | num_sync_run++; | 262 | num_sync_run++; |
265 | 263 | ||
264 | submit_bio(cur->bi_rw, cur); | ||
265 | num_run++; | ||
266 | batch_run++; | ||
266 | if (need_resched()) { | 267 | if (need_resched()) { |
267 | if (num_sync_run) { | 268 | if (num_sync_run) { |
268 | blk_run_backing_dev(bdi, NULL); | 269 | blk_run_backing_dev(bdi, NULL); |
@@ -325,16 +326,6 @@ loop_lock: | |||
325 | num_sync_run = 0; | 326 | num_sync_run = 0; |
326 | blk_run_backing_dev(bdi, NULL); | 327 | blk_run_backing_dev(bdi, NULL); |
327 | } | 328 | } |
328 | |||
329 | cond_resched(); | ||
330 | if (again) | ||
331 | goto loop; | ||
332 | |||
333 | spin_lock(&device->io_lock); | ||
334 | if (device->pending_bios.head || device->pending_sync_bios.head) | ||
335 | goto loop_lock; | ||
336 | spin_unlock(&device->io_lock); | ||
337 | |||
338 | /* | 329 | /* |
339 | * IO has already been through a long path to get here. Checksumming, | 330 | * IO has already been through a long path to get here. Checksumming, |
340 | * async helper threads, perhaps compression. We've done a pretty | 331 | * async helper threads, perhaps compression. We've done a pretty |
@@ -346,6 +337,16 @@ loop_lock: | |||
346 | * cared about found its way down here. | 337 | * cared about found its way down here. |
347 | */ | 338 | */ |
348 | blk_run_backing_dev(bdi, NULL); | 339 | blk_run_backing_dev(bdi, NULL); |
340 | |||
341 | cond_resched(); | ||
342 | if (again) | ||
343 | goto loop; | ||
344 | |||
345 | spin_lock(&device->io_lock); | ||
346 | if (device->pending_bios.head || device->pending_sync_bios.head) | ||
347 | goto loop_lock; | ||
348 | spin_unlock(&device->io_lock); | ||
349 | |||
349 | done: | 350 | done: |
350 | return 0; | 351 | return 0; |
351 | } | 352 | } |
@@ -365,6 +366,7 @@ static noinline int device_list_add(const char *path, | |||
365 | struct btrfs_device *device; | 366 | struct btrfs_device *device; |
366 | struct btrfs_fs_devices *fs_devices; | 367 | struct btrfs_fs_devices *fs_devices; |
367 | u64 found_transid = btrfs_super_generation(disk_super); | 368 | u64 found_transid = btrfs_super_generation(disk_super); |
369 | char *name; | ||
368 | 370 | ||
369 | fs_devices = find_fsid(disk_super->fsid); | 371 | fs_devices = find_fsid(disk_super->fsid); |
370 | if (!fs_devices) { | 372 | if (!fs_devices) { |
@@ -411,6 +413,12 @@ static noinline int device_list_add(const char *path, | |||
411 | 413 | ||
412 | device->fs_devices = fs_devices; | 414 | device->fs_devices = fs_devices; |
413 | fs_devices->num_devices++; | 415 | fs_devices->num_devices++; |
416 | } else if (strcmp(device->name, path)) { | ||
417 | name = kstrdup(path, GFP_NOFS); | ||
418 | if (!name) | ||
419 | return -ENOMEM; | ||
420 | kfree(device->name); | ||
421 | device->name = name; | ||
414 | } | 422 | } |
415 | 423 | ||
416 | if (found_transid > fs_devices->latest_trans) { | 424 | if (found_transid > fs_devices->latest_trans) { |
@@ -592,7 +600,7 @@ static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices, | |||
592 | goto error_close; | 600 | goto error_close; |
593 | 601 | ||
594 | disk_super = (struct btrfs_super_block *)bh->b_data; | 602 | disk_super = (struct btrfs_super_block *)bh->b_data; |
595 | devid = le64_to_cpu(disk_super->dev_item.devid); | 603 | devid = btrfs_stack_device_id(&disk_super->dev_item); |
596 | if (devid != device->devid) | 604 | if (devid != device->devid) |
597 | goto error_brelse; | 605 | goto error_brelse; |
598 | 606 | ||
@@ -694,7 +702,7 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder, | |||
694 | goto error_close; | 702 | goto error_close; |
695 | } | 703 | } |
696 | disk_super = (struct btrfs_super_block *)bh->b_data; | 704 | disk_super = (struct btrfs_super_block *)bh->b_data; |
697 | devid = le64_to_cpu(disk_super->dev_item.devid); | 705 | devid = btrfs_stack_device_id(&disk_super->dev_item); |
698 | transid = btrfs_super_generation(disk_super); | 706 | transid = btrfs_super_generation(disk_super); |
699 | if (disk_super->label[0]) | 707 | if (disk_super->label[0]) |
700 | printk(KERN_INFO "device label %s ", disk_super->label); | 708 | printk(KERN_INFO "device label %s ", disk_super->label); |
@@ -1135,7 +1143,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) | |||
1135 | root->fs_info->avail_metadata_alloc_bits; | 1143 | root->fs_info->avail_metadata_alloc_bits; |
1136 | 1144 | ||
1137 | if ((all_avail & BTRFS_BLOCK_GROUP_RAID10) && | 1145 | if ((all_avail & BTRFS_BLOCK_GROUP_RAID10) && |
1138 | root->fs_info->fs_devices->rw_devices <= 4) { | 1146 | root->fs_info->fs_devices->num_devices <= 4) { |
1139 | printk(KERN_ERR "btrfs: unable to go below four devices " | 1147 | printk(KERN_ERR "btrfs: unable to go below four devices " |
1140 | "on raid10\n"); | 1148 | "on raid10\n"); |
1141 | ret = -EINVAL; | 1149 | ret = -EINVAL; |
@@ -1143,7 +1151,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) | |||
1143 | } | 1151 | } |
1144 | 1152 | ||
1145 | if ((all_avail & BTRFS_BLOCK_GROUP_RAID1) && | 1153 | if ((all_avail & BTRFS_BLOCK_GROUP_RAID1) && |
1146 | root->fs_info->fs_devices->rw_devices <= 2) { | 1154 | root->fs_info->fs_devices->num_devices <= 2) { |
1147 | printk(KERN_ERR "btrfs: unable to go below two " | 1155 | printk(KERN_ERR "btrfs: unable to go below two " |
1148 | "devices on raid1\n"); | 1156 | "devices on raid1\n"); |
1149 | ret = -EINVAL; | 1157 | ret = -EINVAL; |
@@ -1187,7 +1195,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) | |||
1187 | goto error_close; | 1195 | goto error_close; |
1188 | } | 1196 | } |
1189 | disk_super = (struct btrfs_super_block *)bh->b_data; | 1197 | disk_super = (struct btrfs_super_block *)bh->b_data; |
1190 | devid = le64_to_cpu(disk_super->dev_item.devid); | 1198 | devid = btrfs_stack_device_id(&disk_super->dev_item); |
1191 | dev_uuid = disk_super->dev_item.uuid; | 1199 | dev_uuid = disk_super->dev_item.uuid; |
1192 | device = btrfs_find_device(root, devid, dev_uuid, | 1200 | device = btrfs_find_device(root, devid, dev_uuid, |
1193 | disk_super->fsid); | 1201 | disk_super->fsid); |
@@ -1434,8 +1442,8 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) | |||
1434 | return -EINVAL; | 1442 | return -EINVAL; |
1435 | 1443 | ||
1436 | bdev = open_bdev_exclusive(device_path, 0, root->fs_info->bdev_holder); | 1444 | bdev = open_bdev_exclusive(device_path, 0, root->fs_info->bdev_holder); |
1437 | if (!bdev) | 1445 | if (IS_ERR(bdev)) |
1438 | return -EIO; | 1446 | return PTR_ERR(bdev); |
1439 | 1447 | ||
1440 | if (root->fs_info->fs_devices->seeding) { | 1448 | if (root->fs_info->fs_devices->seeding) { |
1441 | seeding_dev = 1; | 1449 | seeding_dev = 1; |
@@ -2191,9 +2199,9 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | |||
2191 | min_stripes = 2; | 2199 | min_stripes = 2; |
2192 | } | 2200 | } |
2193 | if (type & (BTRFS_BLOCK_GROUP_RAID1)) { | 2201 | if (type & (BTRFS_BLOCK_GROUP_RAID1)) { |
2194 | num_stripes = min_t(u64, 2, fs_devices->rw_devices); | 2202 | if (fs_devices->rw_devices < 2) |
2195 | if (num_stripes < 2) | ||
2196 | return -ENOSPC; | 2203 | return -ENOSPC; |
2204 | num_stripes = 2; | ||
2197 | min_stripes = 2; | 2205 | min_stripes = 2; |
2198 | } | 2206 | } |
2199 | if (type & (BTRFS_BLOCK_GROUP_RAID10)) { | 2207 | if (type & (BTRFS_BLOCK_GROUP_RAID10)) { |
@@ -2209,7 +2217,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | |||
2209 | max_chunk_size = 10 * calc_size; | 2217 | max_chunk_size = 10 * calc_size; |
2210 | min_stripe_size = 64 * 1024 * 1024; | 2218 | min_stripe_size = 64 * 1024 * 1024; |
2211 | } else if (type & BTRFS_BLOCK_GROUP_METADATA) { | 2219 | } else if (type & BTRFS_BLOCK_GROUP_METADATA) { |
2212 | max_chunk_size = 4 * calc_size; | 2220 | max_chunk_size = 256 * 1024 * 1024; |
2213 | min_stripe_size = 32 * 1024 * 1024; | 2221 | min_stripe_size = 32 * 1024 * 1024; |
2214 | } else if (type & BTRFS_BLOCK_GROUP_SYSTEM) { | 2222 | } else if (type & BTRFS_BLOCK_GROUP_SYSTEM) { |
2215 | calc_size = 8 * 1024 * 1024; | 2223 | calc_size = 8 * 1024 * 1024; |
@@ -2237,8 +2245,16 @@ again: | |||
2237 | do_div(calc_size, stripe_len); | 2245 | do_div(calc_size, stripe_len); |
2238 | calc_size *= stripe_len; | 2246 | calc_size *= stripe_len; |
2239 | } | 2247 | } |
2248 | |||
2240 | /* we don't want tiny stripes */ | 2249 | /* we don't want tiny stripes */ |
2241 | calc_size = max_t(u64, min_stripe_size, calc_size); | 2250 | if (!looped) |
2251 | calc_size = max_t(u64, min_stripe_size, calc_size); | ||
2252 | |||
2253 | /* | ||
2254 | * we're about to do_div by the stripe_len so lets make sure | ||
2255 | * we end up with something bigger than a stripe | ||
2256 | */ | ||
2257 | calc_size = max_t(u64, calc_size, stripe_len * 4); | ||
2242 | 2258 | ||
2243 | do_div(calc_size, stripe_len); | 2259 | do_div(calc_size, stripe_len); |
2244 | calc_size *= stripe_len; | 2260 | calc_size *= stripe_len; |
@@ -2538,6 +2554,11 @@ int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset) | |||
2538 | if (!em) | 2554 | if (!em) |
2539 | return 1; | 2555 | return 1; |
2540 | 2556 | ||
2557 | if (btrfs_test_opt(root, DEGRADED)) { | ||
2558 | free_extent_map(em); | ||
2559 | return 0; | ||
2560 | } | ||
2561 | |||
2541 | map = (struct map_lookup *)em->bdev; | 2562 | map = (struct map_lookup *)em->bdev; |
2542 | for (i = 0; i < map->num_stripes; i++) { | 2563 | for (i = 0; i < map->num_stripes; i++) { |
2543 | if (!map->stripes[i].dev->writeable) { | 2564 | if (!map->stripes[i].dev->writeable) { |
@@ -2649,8 +2670,10 @@ again: | |||
2649 | em = lookup_extent_mapping(em_tree, logical, *length); | 2670 | em = lookup_extent_mapping(em_tree, logical, *length); |
2650 | read_unlock(&em_tree->lock); | 2671 | read_unlock(&em_tree->lock); |
2651 | 2672 | ||
2652 | if (!em && unplug_page) | 2673 | if (!em && unplug_page) { |
2674 | kfree(multi); | ||
2653 | return 0; | 2675 | return 0; |
2676 | } | ||
2654 | 2677 | ||
2655 | if (!em) { | 2678 | if (!em) { |
2656 | printk(KERN_CRIT "unable to find logical %llu len %llu\n", | 2679 | printk(KERN_CRIT "unable to find logical %llu len %llu\n", |
@@ -3375,6 +3398,8 @@ int btrfs_read_chunk_tree(struct btrfs_root *root) | |||
3375 | key.type = 0; | 3398 | key.type = 0; |
3376 | again: | 3399 | again: |
3377 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 3400 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
3401 | if (ret < 0) | ||
3402 | goto error; | ||
3378 | while (1) { | 3403 | while (1) { |
3379 | leaf = path->nodes[0]; | 3404 | leaf = path->nodes[0]; |
3380 | slot = path->slots[0]; | 3405 | slot = path->slots[0]; |