diff options
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r-- | fs/btrfs/volumes.c | 66 |
1 files changed, 44 insertions, 22 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index ffeed6d6326f..6104676857f5 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include "rcu-string.h" | 40 | #include "rcu-string.h" |
41 | #include "math.h" | 41 | #include "math.h" |
42 | #include "dev-replace.h" | 42 | #include "dev-replace.h" |
43 | #include "sysfs.h" | ||
43 | 44 | ||
44 | static int init_first_rw_device(struct btrfs_trans_handle *trans, | 45 | static int init_first_rw_device(struct btrfs_trans_handle *trans, |
45 | struct btrfs_root *root, | 46 | struct btrfs_root *root, |
@@ -554,12 +555,14 @@ static struct btrfs_fs_devices *clone_fs_devices(struct btrfs_fs_devices *orig) | |||
554 | * This is ok to do without rcu read locked because we hold the | 555 | * This is ok to do without rcu read locked because we hold the |
555 | * uuid mutex so nothing we touch in here is going to disappear. | 556 | * uuid mutex so nothing we touch in here is going to disappear. |
556 | */ | 557 | */ |
557 | name = rcu_string_strdup(orig_dev->name->str, GFP_NOFS); | 558 | if (orig_dev->name) { |
558 | if (!name) { | 559 | name = rcu_string_strdup(orig_dev->name->str, GFP_NOFS); |
559 | kfree(device); | 560 | if (!name) { |
560 | goto error; | 561 | kfree(device); |
562 | goto error; | ||
563 | } | ||
564 | rcu_assign_pointer(device->name, name); | ||
561 | } | 565 | } |
562 | rcu_assign_pointer(device->name, name); | ||
563 | 566 | ||
564 | list_add(&device->dev_list, &fs_devices->devices); | 567 | list_add(&device->dev_list, &fs_devices->devices); |
565 | device->fs_devices = fs_devices; | 568 | device->fs_devices = fs_devices; |
@@ -1680,6 +1683,9 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) | |||
1680 | if (device->bdev) | 1683 | if (device->bdev) |
1681 | device->fs_devices->open_devices--; | 1684 | device->fs_devices->open_devices--; |
1682 | 1685 | ||
1686 | /* remove sysfs entry */ | ||
1687 | btrfs_kobj_rm_device(root->fs_info, device); | ||
1688 | |||
1683 | call_rcu(&device->rcu, free_device); | 1689 | call_rcu(&device->rcu, free_device); |
1684 | 1690 | ||
1685 | num_devices = btrfs_super_num_devices(root->fs_info->super_copy) - 1; | 1691 | num_devices = btrfs_super_num_devices(root->fs_info->super_copy) - 1; |
@@ -2143,9 +2149,14 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) | |||
2143 | total_bytes = btrfs_super_num_devices(root->fs_info->super_copy); | 2149 | total_bytes = btrfs_super_num_devices(root->fs_info->super_copy); |
2144 | btrfs_set_super_num_devices(root->fs_info->super_copy, | 2150 | btrfs_set_super_num_devices(root->fs_info->super_copy, |
2145 | total_bytes + 1); | 2151 | total_bytes + 1); |
2152 | |||
2153 | /* add sysfs device entry */ | ||
2154 | btrfs_kobj_add_device(root->fs_info, device); | ||
2155 | |||
2146 | mutex_unlock(&root->fs_info->fs_devices->device_list_mutex); | 2156 | mutex_unlock(&root->fs_info->fs_devices->device_list_mutex); |
2147 | 2157 | ||
2148 | if (seeding_dev) { | 2158 | if (seeding_dev) { |
2159 | char fsid_buf[BTRFS_UUID_UNPARSED_SIZE]; | ||
2149 | ret = init_first_rw_device(trans, root, device); | 2160 | ret = init_first_rw_device(trans, root, device); |
2150 | if (ret) { | 2161 | if (ret) { |
2151 | btrfs_abort_transaction(trans, root, ret); | 2162 | btrfs_abort_transaction(trans, root, ret); |
@@ -2156,6 +2167,14 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) | |||
2156 | btrfs_abort_transaction(trans, root, ret); | 2167 | btrfs_abort_transaction(trans, root, ret); |
2157 | goto error_trans; | 2168 | goto error_trans; |
2158 | } | 2169 | } |
2170 | |||
2171 | /* Sprouting would change fsid of the mounted root, | ||
2172 | * so rename the fsid on the sysfs | ||
2173 | */ | ||
2174 | snprintf(fsid_buf, BTRFS_UUID_UNPARSED_SIZE, "%pU", | ||
2175 | root->fs_info->fsid); | ||
2176 | if (kobject_rename(&root->fs_info->super_kobj, fsid_buf)) | ||
2177 | goto error_trans; | ||
2159 | } else { | 2178 | } else { |
2160 | ret = btrfs_add_device(trans, root, device); | 2179 | ret = btrfs_add_device(trans, root, device); |
2161 | if (ret) { | 2180 | if (ret) { |
@@ -2205,6 +2224,7 @@ error_trans: | |||
2205 | unlock_chunks(root); | 2224 | unlock_chunks(root); |
2206 | btrfs_end_transaction(trans, root); | 2225 | btrfs_end_transaction(trans, root); |
2207 | rcu_string_free(device->name); | 2226 | rcu_string_free(device->name); |
2227 | btrfs_kobj_rm_device(root->fs_info, device); | ||
2208 | kfree(device); | 2228 | kfree(device); |
2209 | error: | 2229 | error: |
2210 | blkdev_put(bdev, FMODE_EXCL); | 2230 | blkdev_put(bdev, FMODE_EXCL); |
@@ -2543,9 +2563,6 @@ static int btrfs_relocate_chunk(struct btrfs_root *root, | |||
2543 | remove_extent_mapping(em_tree, em); | 2563 | remove_extent_mapping(em_tree, em); |
2544 | write_unlock(&em_tree->lock); | 2564 | write_unlock(&em_tree->lock); |
2545 | 2565 | ||
2546 | kfree(map); | ||
2547 | em->bdev = NULL; | ||
2548 | |||
2549 | /* once for the tree */ | 2566 | /* once for the tree */ |
2550 | free_extent_map(em); | 2567 | free_extent_map(em); |
2551 | /* once for us */ | 2568 | /* once for us */ |
@@ -4301,9 +4318,11 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | |||
4301 | 4318 | ||
4302 | em = alloc_extent_map(); | 4319 | em = alloc_extent_map(); |
4303 | if (!em) { | 4320 | if (!em) { |
4321 | kfree(map); | ||
4304 | ret = -ENOMEM; | 4322 | ret = -ENOMEM; |
4305 | goto error; | 4323 | goto error; |
4306 | } | 4324 | } |
4325 | set_bit(EXTENT_FLAG_FS_MAPPING, &em->flags); | ||
4307 | em->bdev = (struct block_device *)map; | 4326 | em->bdev = (struct block_device *)map; |
4308 | em->start = start; | 4327 | em->start = start; |
4309 | em->len = num_bytes; | 4328 | em->len = num_bytes; |
@@ -4346,7 +4365,6 @@ error_del_extent: | |||
4346 | /* One for the tree reference */ | 4365 | /* One for the tree reference */ |
4347 | free_extent_map(em); | 4366 | free_extent_map(em); |
4348 | error: | 4367 | error: |
4349 | kfree(map); | ||
4350 | kfree(devices_info); | 4368 | kfree(devices_info); |
4351 | return ret; | 4369 | return ret; |
4352 | } | 4370 | } |
@@ -4558,7 +4576,6 @@ void btrfs_mapping_tree_free(struct btrfs_mapping_tree *tree) | |||
4558 | write_unlock(&tree->map_tree.lock); | 4576 | write_unlock(&tree->map_tree.lock); |
4559 | if (!em) | 4577 | if (!em) |
4560 | break; | 4578 | break; |
4561 | kfree(em->bdev); | ||
4562 | /* once for us */ | 4579 | /* once for us */ |
4563 | free_extent_map(em); | 4580 | free_extent_map(em); |
4564 | /* once for the tree */ | 4581 | /* once for the tree */ |
@@ -5362,6 +5379,15 @@ int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree, | |||
5362 | return 0; | 5379 | return 0; |
5363 | } | 5380 | } |
5364 | 5381 | ||
5382 | static inline void btrfs_end_bbio(struct btrfs_bio *bbio, struct bio *bio, int err) | ||
5383 | { | ||
5384 | if (likely(bbio->flags & BTRFS_BIO_ORIG_BIO_SUBMITTED)) | ||
5385 | bio_endio_nodec(bio, err); | ||
5386 | else | ||
5387 | bio_endio(bio, err); | ||
5388 | kfree(bbio); | ||
5389 | } | ||
5390 | |||
5365 | static void btrfs_end_bio(struct bio *bio, int err) | 5391 | static void btrfs_end_bio(struct bio *bio, int err) |
5366 | { | 5392 | { |
5367 | struct btrfs_bio *bbio = bio->bi_private; | 5393 | struct btrfs_bio *bbio = bio->bi_private; |
@@ -5402,12 +5428,6 @@ static void btrfs_end_bio(struct bio *bio, int err) | |||
5402 | bio = bbio->orig_bio; | 5428 | bio = bbio->orig_bio; |
5403 | } | 5429 | } |
5404 | 5430 | ||
5405 | /* | ||
5406 | * We have original bio now. So increment bi_remaining to | ||
5407 | * account for it in endio | ||
5408 | */ | ||
5409 | atomic_inc(&bio->bi_remaining); | ||
5410 | |||
5411 | bio->bi_private = bbio->private; | 5431 | bio->bi_private = bbio->private; |
5412 | bio->bi_end_io = bbio->end_io; | 5432 | bio->bi_end_io = bbio->end_io; |
5413 | btrfs_io_bio(bio)->mirror_num = bbio->mirror_num; | 5433 | btrfs_io_bio(bio)->mirror_num = bbio->mirror_num; |
@@ -5424,9 +5444,8 @@ static void btrfs_end_bio(struct bio *bio, int err) | |||
5424 | set_bit(BIO_UPTODATE, &bio->bi_flags); | 5444 | set_bit(BIO_UPTODATE, &bio->bi_flags); |
5425 | err = 0; | 5445 | err = 0; |
5426 | } | 5446 | } |
5427 | kfree(bbio); | ||
5428 | 5447 | ||
5429 | bio_endio(bio, err); | 5448 | btrfs_end_bbio(bbio, bio, err); |
5430 | } else if (!is_orig_bio) { | 5449 | } else if (!is_orig_bio) { |
5431 | bio_put(bio); | 5450 | bio_put(bio); |
5432 | } | 5451 | } |
@@ -5589,12 +5608,15 @@ static void bbio_error(struct btrfs_bio *bbio, struct bio *bio, u64 logical) | |||
5589 | { | 5608 | { |
5590 | atomic_inc(&bbio->error); | 5609 | atomic_inc(&bbio->error); |
5591 | if (atomic_dec_and_test(&bbio->stripes_pending)) { | 5610 | if (atomic_dec_and_test(&bbio->stripes_pending)) { |
5611 | /* Shoud be the original bio. */ | ||
5612 | WARN_ON(bio != bbio->orig_bio); | ||
5613 | |||
5592 | bio->bi_private = bbio->private; | 5614 | bio->bi_private = bbio->private; |
5593 | bio->bi_end_io = bbio->end_io; | 5615 | bio->bi_end_io = bbio->end_io; |
5594 | btrfs_io_bio(bio)->mirror_num = bbio->mirror_num; | 5616 | btrfs_io_bio(bio)->mirror_num = bbio->mirror_num; |
5595 | bio->bi_iter.bi_sector = logical >> 9; | 5617 | bio->bi_iter.bi_sector = logical >> 9; |
5596 | kfree(bbio); | 5618 | |
5597 | bio_endio(bio, -EIO); | 5619 | btrfs_end_bbio(bbio, bio, -EIO); |
5598 | } | 5620 | } |
5599 | } | 5621 | } |
5600 | 5622 | ||
@@ -5681,6 +5703,7 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio, | |||
5681 | BUG_ON(!bio); /* -ENOMEM */ | 5703 | BUG_ON(!bio); /* -ENOMEM */ |
5682 | } else { | 5704 | } else { |
5683 | bio = first_bio; | 5705 | bio = first_bio; |
5706 | bbio->flags |= BTRFS_BIO_ORIG_BIO_SUBMITTED; | ||
5684 | } | 5707 | } |
5685 | 5708 | ||
5686 | submit_stripe_bio(root, bbio, bio, | 5709 | submit_stripe_bio(root, bbio, bio, |
@@ -5822,6 +5845,7 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key, | |||
5822 | return -ENOMEM; | 5845 | return -ENOMEM; |
5823 | } | 5846 | } |
5824 | 5847 | ||
5848 | set_bit(EXTENT_FLAG_FS_MAPPING, &em->flags); | ||
5825 | em->bdev = (struct block_device *)map; | 5849 | em->bdev = (struct block_device *)map; |
5826 | em->start = logical; | 5850 | em->start = logical; |
5827 | em->len = length; | 5851 | em->len = length; |
@@ -5846,7 +5870,6 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key, | |||
5846 | map->stripes[i].dev = btrfs_find_device(root->fs_info, devid, | 5870 | map->stripes[i].dev = btrfs_find_device(root->fs_info, devid, |
5847 | uuid, NULL); | 5871 | uuid, NULL); |
5848 | if (!map->stripes[i].dev && !btrfs_test_opt(root, DEGRADED)) { | 5872 | if (!map->stripes[i].dev && !btrfs_test_opt(root, DEGRADED)) { |
5849 | kfree(map); | ||
5850 | free_extent_map(em); | 5873 | free_extent_map(em); |
5851 | return -EIO; | 5874 | return -EIO; |
5852 | } | 5875 | } |
@@ -5854,7 +5877,6 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key, | |||
5854 | map->stripes[i].dev = | 5877 | map->stripes[i].dev = |
5855 | add_missing_dev(root, devid, uuid); | 5878 | add_missing_dev(root, devid, uuid); |
5856 | if (!map->stripes[i].dev) { | 5879 | if (!map->stripes[i].dev) { |
5857 | kfree(map); | ||
5858 | free_extent_map(em); | 5880 | free_extent_map(em); |
5859 | return -EIO; | 5881 | return -EIO; |
5860 | } | 5882 | } |