aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/volumes.c
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2014-09-03 09:35:38 -0400
committerChris Mason <clm@fb.com>2014-09-17 16:38:38 -0400
commit7cc8e58d53cd2295c3c1cee7b503bd1790ea4486 (patch)
tree1befd9a2bea8e1808f0fe1b12406c05b3f7dbe2d /fs/btrfs/volumes.c
parent1c1161870c8bcb0d966ebbf1aec05a87a79a4175 (diff)
Btrfs: fix unprotected device's variants on 32bits machine
->total_bytes,->disk_total_bytes,->bytes_used is protected by chunk lock when we change them, but sometimes we read them without any lock, and we might get unexpected value. We fix this problem like inode's i_size. Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r--fs/btrfs/volumes.c48
1 files changed, 28 insertions, 20 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index d8e4a3d1ad89..41da102cdcc0 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -1308,7 +1308,7 @@ again:
1308 1308
1309 if (device->bytes_used > 0) { 1309 if (device->bytes_used > 0) {
1310 u64 len = btrfs_dev_extent_length(leaf, extent); 1310 u64 len = btrfs_dev_extent_length(leaf, extent);
1311 device->bytes_used -= len; 1311 btrfs_device_set_bytes_used(device, device->bytes_used - len);
1312 spin_lock(&root->fs_info->free_chunk_lock); 1312 spin_lock(&root->fs_info->free_chunk_lock);
1313 root->fs_info->free_chunk_space += len; 1313 root->fs_info->free_chunk_space += len;
1314 spin_unlock(&root->fs_info->free_chunk_lock); 1314 spin_unlock(&root->fs_info->free_chunk_lock);
@@ -1462,8 +1462,10 @@ static int btrfs_add_device(struct btrfs_trans_handle *trans,
1462 btrfs_set_device_io_align(leaf, dev_item, device->io_align); 1462 btrfs_set_device_io_align(leaf, dev_item, device->io_align);
1463 btrfs_set_device_io_width(leaf, dev_item, device->io_width); 1463 btrfs_set_device_io_width(leaf, dev_item, device->io_width);
1464 btrfs_set_device_sector_size(leaf, dev_item, device->sector_size); 1464 btrfs_set_device_sector_size(leaf, dev_item, device->sector_size);
1465 btrfs_set_device_total_bytes(leaf, dev_item, device->disk_total_bytes); 1465 btrfs_set_device_total_bytes(leaf, dev_item,
1466 btrfs_set_device_bytes_used(leaf, dev_item, device->bytes_used); 1466 btrfs_device_get_disk_total_bytes(device));
1467 btrfs_set_device_bytes_used(leaf, dev_item,
1468 btrfs_device_get_bytes_used(device));
1467 btrfs_set_device_group(leaf, dev_item, 0); 1469 btrfs_set_device_group(leaf, dev_item, 0);
1468 btrfs_set_device_seek_speed(leaf, dev_item, 0); 1470 btrfs_set_device_seek_speed(leaf, dev_item, 0);
1469 btrfs_set_device_bandwidth(leaf, dev_item, 0); 1471 btrfs_set_device_bandwidth(leaf, dev_item, 0);
@@ -2330,7 +2332,8 @@ int btrfs_init_dev_replace_tgtdev(struct btrfs_root *root, char *device_path,
2330 } 2332 }
2331 2333
2332 2334
2333 if (i_size_read(bdev->bd_inode) < srcdev->total_bytes) { 2335 if (i_size_read(bdev->bd_inode) <
2336 btrfs_device_get_total_bytes(srcdev)) {
2334 btrfs_err(fs_info, "target device is smaller than source device!"); 2337 btrfs_err(fs_info, "target device is smaller than source device!");
2335 ret = -EINVAL; 2338 ret = -EINVAL;
2336 goto error; 2339 goto error;
@@ -2360,11 +2363,11 @@ int btrfs_init_dev_replace_tgtdev(struct btrfs_root *root, char *device_path,
2360 device->io_width = root->sectorsize; 2363 device->io_width = root->sectorsize;
2361 device->io_align = root->sectorsize; 2364 device->io_align = root->sectorsize;
2362 device->sector_size = root->sectorsize; 2365 device->sector_size = root->sectorsize;
2363 device->total_bytes = srcdev->total_bytes; 2366 device->total_bytes = btrfs_device_get_total_bytes(srcdev);
2364 device->disk_total_bytes = srcdev->disk_total_bytes; 2367 device->disk_total_bytes = btrfs_device_get_disk_total_bytes(srcdev);
2368 device->bytes_used = btrfs_device_get_bytes_used(srcdev);
2365 ASSERT(list_empty(&srcdev->resized_list)); 2369 ASSERT(list_empty(&srcdev->resized_list));
2366 device->commit_total_bytes = srcdev->commit_total_bytes; 2370 device->commit_total_bytes = srcdev->commit_total_bytes;
2367 device->bytes_used = srcdev->bytes_used;
2368 device->commit_bytes_used = device->bytes_used; 2371 device->commit_bytes_used = device->bytes_used;
2369 device->dev_root = fs_info->dev_root; 2372 device->dev_root = fs_info->dev_root;
2370 device->bdev = bdev; 2373 device->bdev = bdev;
@@ -2435,8 +2438,10 @@ static noinline int btrfs_update_device(struct btrfs_trans_handle *trans,
2435 btrfs_set_device_io_align(leaf, dev_item, device->io_align); 2438 btrfs_set_device_io_align(leaf, dev_item, device->io_align);
2436 btrfs_set_device_io_width(leaf, dev_item, device->io_width); 2439 btrfs_set_device_io_width(leaf, dev_item, device->io_width);
2437 btrfs_set_device_sector_size(leaf, dev_item, device->sector_size); 2440 btrfs_set_device_sector_size(leaf, dev_item, device->sector_size);
2438 btrfs_set_device_total_bytes(leaf, dev_item, device->disk_total_bytes); 2441 btrfs_set_device_total_bytes(leaf, dev_item,
2439 btrfs_set_device_bytes_used(leaf, dev_item, device->bytes_used); 2442 btrfs_device_get_disk_total_bytes(device));
2443 btrfs_set_device_bytes_used(leaf, dev_item,
2444 btrfs_device_get_bytes_used(device));
2440 btrfs_mark_buffer_dirty(leaf); 2445 btrfs_mark_buffer_dirty(leaf);
2441 2446
2442out: 2447out:
@@ -2464,8 +2469,8 @@ static int __btrfs_grow_device(struct btrfs_trans_handle *trans,
2464 btrfs_set_super_total_bytes(super_copy, old_total + diff); 2469 btrfs_set_super_total_bytes(super_copy, old_total + diff);
2465 device->fs_devices->total_rw_bytes += diff; 2470 device->fs_devices->total_rw_bytes += diff;
2466 2471
2467 device->total_bytes = new_size; 2472 btrfs_device_set_total_bytes(device, new_size);
2468 device->disk_total_bytes = new_size; 2473 btrfs_device_set_disk_total_bytes(device, new_size);
2469 btrfs_clear_space_info_full(device->dev_root->fs_info); 2474 btrfs_clear_space_info_full(device->dev_root->fs_info);
2470 if (list_empty(&device->resized_list)) 2475 if (list_empty(&device->resized_list))
2471 list_add_tail(&device->resized_list, 2476 list_add_tail(&device->resized_list,
@@ -3110,11 +3115,12 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)
3110 /* step one make some room on all the devices */ 3115 /* step one make some room on all the devices */
3111 devices = &fs_info->fs_devices->devices; 3116 devices = &fs_info->fs_devices->devices;
3112 list_for_each_entry(device, devices, dev_list) { 3117 list_for_each_entry(device, devices, dev_list) {
3113 old_size = device->total_bytes; 3118 old_size = btrfs_device_get_total_bytes(device);
3114 size_to_free = div_factor(old_size, 1); 3119 size_to_free = div_factor(old_size, 1);
3115 size_to_free = min(size_to_free, (u64)1 * 1024 * 1024); 3120 size_to_free = min(size_to_free, (u64)1 * 1024 * 1024);
3116 if (!device->writeable || 3121 if (!device->writeable ||
3117 device->total_bytes - device->bytes_used > size_to_free || 3122 btrfs_device_get_total_bytes(device) -
3123 btrfs_device_get_bytes_used(device) > size_to_free ||
3118 device->is_tgtdev_for_dev_replace) 3124 device->is_tgtdev_for_dev_replace)
3119 continue; 3125 continue;
3120 3126
@@ -3920,8 +3926,8 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size)
3920 struct btrfs_key key; 3926 struct btrfs_key key;
3921 struct btrfs_super_block *super_copy = root->fs_info->super_copy; 3927 struct btrfs_super_block *super_copy = root->fs_info->super_copy;
3922 u64 old_total = btrfs_super_total_bytes(super_copy); 3928 u64 old_total = btrfs_super_total_bytes(super_copy);
3923 u64 old_size = device->total_bytes; 3929 u64 old_size = btrfs_device_get_total_bytes(device);
3924 u64 diff = device->total_bytes - new_size; 3930 u64 diff = old_size - new_size;
3925 3931
3926 if (device->is_tgtdev_for_dev_replace) 3932 if (device->is_tgtdev_for_dev_replace)
3927 return -EINVAL; 3933 return -EINVAL;
@@ -3934,7 +3940,7 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size)
3934 3940
3935 lock_chunks(root); 3941 lock_chunks(root);
3936 3942
3937 device->total_bytes = new_size; 3943 btrfs_device_set_total_bytes(device, new_size);
3938 if (device->writeable) { 3944 if (device->writeable) {
3939 device->fs_devices->total_rw_bytes -= diff; 3945 device->fs_devices->total_rw_bytes -= diff;
3940 spin_lock(&root->fs_info->free_chunk_lock); 3946 spin_lock(&root->fs_info->free_chunk_lock);
@@ -4000,7 +4006,7 @@ again:
4000 ret = -ENOSPC; 4006 ret = -ENOSPC;
4001 lock_chunks(root); 4007 lock_chunks(root);
4002 4008
4003 device->total_bytes = old_size; 4009 btrfs_device_set_total_bytes(device, old_size);
4004 if (device->writeable) 4010 if (device->writeable)
4005 device->fs_devices->total_rw_bytes += diff; 4011 device->fs_devices->total_rw_bytes += diff;
4006 spin_lock(&root->fs_info->free_chunk_lock); 4012 spin_lock(&root->fs_info->free_chunk_lock);
@@ -4018,7 +4024,7 @@ again:
4018 } 4024 }
4019 4025
4020 lock_chunks(root); 4026 lock_chunks(root);
4021 device->disk_total_bytes = new_size; 4027 btrfs_device_set_disk_total_bytes(device, new_size);
4022 if (list_empty(&device->resized_list)) 4028 if (list_empty(&device->resized_list))
4023 list_add_tail(&device->resized_list, 4029 list_add_tail(&device->resized_list,
4024 &root->fs_info->fs_devices->resized_devices); 4030 &root->fs_info->fs_devices->resized_devices);
@@ -4429,8 +4435,10 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
4429 if (ret) 4435 if (ret)
4430 goto error_del_extent; 4436 goto error_del_extent;
4431 4437
4432 for (i = 0; i < map->num_stripes; i++) 4438 for (i = 0; i < map->num_stripes; i++) {
4433 map->stripes[i].dev->bytes_used += stripe_size; 4439 num_bytes = map->stripes[i].dev->bytes_used + stripe_size;
4440 btrfs_device_set_bytes_used(map->stripes[i].dev, num_bytes);
4441 }
4434 4442
4435 spin_lock(&extent_root->fs_info->free_chunk_lock); 4443 spin_lock(&extent_root->fs_info->free_chunk_lock);
4436 extent_root->fs_info->free_chunk_space -= (stripe_size * 4444 extent_root->fs_info->free_chunk_space -= (stripe_size *