aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/dev-replace.c15
-rw-r--r--fs/btrfs/ioctl.c6
-rw-r--r--fs/btrfs/volumes.c48
-rw-r--r--fs/btrfs/volumes.h84
4 files changed, 124 insertions, 29 deletions
diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
index 1be03d85d267..da7ac1432b15 100644
--- a/fs/btrfs/dev-replace.c
+++ b/fs/btrfs/dev-replace.c
@@ -418,7 +418,7 @@ int btrfs_dev_replace_start(struct btrfs_root *root,
418 418
419 /* the disk copy procedure reuses the scrub code */ 419 /* the disk copy procedure reuses the scrub code */
420 ret = btrfs_scrub_dev(fs_info, src_device->devid, 0, 420 ret = btrfs_scrub_dev(fs_info, src_device->devid, 0,
421 src_device->total_bytes, 421 btrfs_device_get_total_bytes(src_device),
422 &dev_replace->scrub_progress, 0, 1); 422 &dev_replace->scrub_progress, 0, 1);
423 423
424 ret = btrfs_dev_replace_finishing(root->fs_info, ret); 424 ret = btrfs_dev_replace_finishing(root->fs_info, ret);
@@ -555,11 +555,12 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
555 memcpy(uuid_tmp, tgt_device->uuid, sizeof(uuid_tmp)); 555 memcpy(uuid_tmp, tgt_device->uuid, sizeof(uuid_tmp));
556 memcpy(tgt_device->uuid, src_device->uuid, sizeof(tgt_device->uuid)); 556 memcpy(tgt_device->uuid, src_device->uuid, sizeof(tgt_device->uuid));
557 memcpy(src_device->uuid, uuid_tmp, sizeof(src_device->uuid)); 557 memcpy(src_device->uuid, uuid_tmp, sizeof(src_device->uuid));
558 tgt_device->total_bytes = src_device->total_bytes; 558 btrfs_device_set_total_bytes(tgt_device, src_device->total_bytes);
559 tgt_device->disk_total_bytes = src_device->disk_total_bytes; 559 btrfs_device_set_disk_total_bytes(tgt_device,
560 src_device->disk_total_bytes);
561 btrfs_device_set_bytes_used(tgt_device, src_device->bytes_used);
560 ASSERT(list_empty(&src_device->resized_list)); 562 ASSERT(list_empty(&src_device->resized_list));
561 tgt_device->commit_total_bytes = src_device->commit_total_bytes; 563 tgt_device->commit_total_bytes = src_device->commit_total_bytes;
562 tgt_device->bytes_used = src_device->bytes_used;
563 tgt_device->commit_bytes_used = src_device->bytes_used; 564 tgt_device->commit_bytes_used = src_device->bytes_used;
564 if (fs_info->sb->s_bdev == src_device->bdev) 565 if (fs_info->sb->s_bdev == src_device->bdev)
565 fs_info->sb->s_bdev = tgt_device->bdev; 566 fs_info->sb->s_bdev = tgt_device->bdev;
@@ -650,6 +651,7 @@ void btrfs_dev_replace_status(struct btrfs_fs_info *fs_info,
650 struct btrfs_ioctl_dev_replace_args *args) 651 struct btrfs_ioctl_dev_replace_args *args)
651{ 652{
652 struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace; 653 struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
654 struct btrfs_device *srcdev;
653 655
654 btrfs_dev_replace_lock(dev_replace); 656 btrfs_dev_replace_lock(dev_replace);
655 /* even if !dev_replace_is_valid, the values are good enough for 657 /* even if !dev_replace_is_valid, the values are good enough for
@@ -672,8 +674,9 @@ void btrfs_dev_replace_status(struct btrfs_fs_info *fs_info,
672 break; 674 break;
673 case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED: 675 case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
674 case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED: 676 case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:
677 srcdev = dev_replace->srcdev;
675 args->status.progress_1000 = div64_u64(dev_replace->cursor_left, 678 args->status.progress_1000 = div64_u64(dev_replace->cursor_left,
676 div64_u64(dev_replace->srcdev->total_bytes, 1000)); 679 div64_u64(btrfs_device_get_total_bytes(srcdev), 1000));
677 break; 680 break;
678 } 681 }
679 btrfs_dev_replace_unlock(dev_replace); 682 btrfs_dev_replace_unlock(dev_replace);
@@ -832,7 +835,7 @@ static int btrfs_dev_replace_continue_on_mount(struct btrfs_fs_info *fs_info)
832 835
833 ret = btrfs_scrub_dev(fs_info, dev_replace->srcdev->devid, 836 ret = btrfs_scrub_dev(fs_info, dev_replace->srcdev->devid,
834 dev_replace->committed_cursor_left, 837 dev_replace->committed_cursor_left,
835 dev_replace->srcdev->total_bytes, 838 btrfs_device_get_total_bytes(dev_replace->srcdev),
836 &dev_replace->scrub_progress, 0, 1); 839 &dev_replace->scrub_progress, 0, 1);
837 ret = btrfs_dev_replace_finishing(fs_info, ret); 840 ret = btrfs_dev_replace_finishing(fs_info, ret);
838 WARN_ON(ret); 841 WARN_ON(ret);
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index f60d1ca389f0..0ff212757b95 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -1553,7 +1553,7 @@ static noinline int btrfs_ioctl_resize(struct file *file,
1553 goto out_free; 1553 goto out_free;
1554 } 1554 }
1555 1555
1556 old_size = device->total_bytes; 1556 old_size = btrfs_device_get_total_bytes(device);
1557 1557
1558 if (mod < 0) { 1558 if (mod < 0) {
1559 if (new_size > old_size) { 1559 if (new_size > old_size) {
@@ -2740,8 +2740,8 @@ static long btrfs_ioctl_dev_info(struct btrfs_root *root, void __user *arg)
2740 } 2740 }
2741 2741
2742 di_args->devid = dev->devid; 2742 di_args->devid = dev->devid;
2743 di_args->bytes_used = dev->bytes_used; 2743 di_args->bytes_used = btrfs_device_get_bytes_used(dev);
2744 di_args->total_bytes = dev->total_bytes; 2744 di_args->total_bytes = btrfs_device_get_total_bytes(dev);
2745 memcpy(di_args->uuid, dev->uuid, sizeof(di_args->uuid)); 2745 memcpy(di_args->uuid, dev->uuid, sizeof(di_args->uuid));
2746 if (dev->name) { 2746 if (dev->name) {
2747 struct rcu_string *name; 2747 struct rcu_string *name;
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 *
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index f79d532fedb0..76600a3fedbe 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -32,6 +32,19 @@ struct btrfs_pending_bios {
32 struct bio *tail; 32 struct bio *tail;
33}; 33};
34 34
35/*
36 * Use sequence counter to get consistent device stat data on
37 * 32-bit processors.
38 */
39#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
40#include <linux/seqlock.h>
41#define __BTRFS_NEED_DEVICE_DATA_ORDERED
42#define btrfs_device_data_ordered_init(device) \
43 seqcount_init(&device->data_seqcount)
44#else
45#define btrfs_device_data_ordered_init(device) do { } while (0)
46#endif
47
35struct btrfs_device { 48struct btrfs_device {
36 struct list_head dev_list; 49 struct list_head dev_list;
37 struct list_head dev_alloc_list; 50 struct list_head dev_alloc_list;
@@ -61,6 +74,10 @@ struct btrfs_device {
61 int can_discard; 74 int can_discard;
62 int is_tgtdev_for_dev_replace; 75 int is_tgtdev_for_dev_replace;
63 76
77#ifdef __BTRFS_NEED_DEVICE_DATA_ORDERED
78 seqcount_t data_seqcount;
79#endif
80
64 /* the internal btrfs device id */ 81 /* the internal btrfs device id */
65 u64 devid; 82 u64 devid;
66 83
@@ -133,6 +150,73 @@ struct btrfs_device {
133 atomic_t dev_stat_values[BTRFS_DEV_STAT_VALUES_MAX]; 150 atomic_t dev_stat_values[BTRFS_DEV_STAT_VALUES_MAX];
134}; 151};
135 152
153/*
154 * If we read those variants at the context of their own lock, we needn't
155 * use the following helpers, reading them directly is safe.
156 */
157#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
158#define BTRFS_DEVICE_GETSET_FUNCS(name) \
159static inline u64 \
160btrfs_device_get_##name(const struct btrfs_device *dev) \
161{ \
162 u64 size; \
163 unsigned int seq; \
164 \
165 do { \
166 seq = read_seqcount_begin(&dev->data_seqcount); \
167 size = dev->name; \
168 } while (read_seqcount_retry(&dev->data_seqcount, seq)); \
169 return size; \
170} \
171 \
172static inline void \
173btrfs_device_set_##name(struct btrfs_device *dev, u64 size) \
174{ \
175 preempt_disable(); \
176 write_seqcount_begin(&dev->data_seqcount); \
177 dev->name = size; \
178 write_seqcount_end(&dev->data_seqcount); \
179 preempt_enable(); \
180}
181#elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPT)
182#define BTRFS_DEVICE_GETSET_FUNCS(name) \
183static inline u64 \
184btrfs_device_get_##name(const struct btrfs_device *dev) \
185{ \
186 u64 size; \
187 \
188 preempt_disable(); \
189 size = dev->name; \
190 preempt_enable(); \
191 return size; \
192} \
193 \
194static inline void \
195btrfs_device_set_##name(struct btrfs_device *dev, u64 size) \
196{ \
197 preempt_disable(); \
198 dev->name = size; \
199 preempt_enable(); \
200}
201#else
202#define BTRFS_DEVICE_GETSET_FUNCS(name) \
203static inline u64 \
204btrfs_device_get_##name(const struct btrfs_device *dev) \
205{ \
206 return dev->name; \
207} \
208 \
209static inline void \
210btrfs_device_set_##name(struct btrfs_device *dev, u64 size) \
211{ \
212 dev->name = size; \
213}
214#endif
215
216BTRFS_DEVICE_GETSET_FUNCS(total_bytes);
217BTRFS_DEVICE_GETSET_FUNCS(disk_total_bytes);
218BTRFS_DEVICE_GETSET_FUNCS(bytes_used);
219
136struct btrfs_fs_devices { 220struct btrfs_fs_devices {
137 u8 fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */ 221 u8 fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */
138 222