aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/check-integrity.c2
-rw-r--r--fs/btrfs/dev-replace.c18
-rw-r--r--fs/btrfs/disk-io.c5
-rw-r--r--fs/btrfs/scrub.c3
-rw-r--r--fs/btrfs/transaction.c2
-rw-r--r--fs/btrfs/volumes.c40
-rw-r--r--fs/btrfs/volumes.h18
7 files changed, 83 insertions, 5 deletions
diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c
index e0033c843ce7..cb7f3fe9c9f6 100644
--- a/fs/btrfs/check-integrity.c
+++ b/fs/btrfs/check-integrity.c
@@ -807,7 +807,7 @@ static int btrfsic_process_superblock_dev_mirror(
807 807
808 /* super block bytenr is always the unmapped device bytenr */ 808 /* super block bytenr is always the unmapped device bytenr */
809 dev_bytenr = btrfs_sb_offset(superblock_mirror_num); 809 dev_bytenr = btrfs_sb_offset(superblock_mirror_num);
810 if (dev_bytenr + BTRFS_SUPER_INFO_SIZE > device->total_bytes) 810 if (dev_bytenr + BTRFS_SUPER_INFO_SIZE > device->commit_total_bytes)
811 return -1; 811 return -1;
812 bh = __bread(superblock_bdev, dev_bytenr / 4096, 812 bh = __bread(superblock_bdev, dev_bytenr / 4096,
813 BTRFS_SUPER_INFO_SIZE); 813 BTRFS_SUPER_INFO_SIZE);
diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
index 72dc02e82945..7877b0fc6a8d 100644
--- a/fs/btrfs/dev-replace.c
+++ b/fs/btrfs/dev-replace.c
@@ -168,6 +168,8 @@ no_valid_dev_replace_entry_found:
168 dev_replace->srcdev->total_bytes; 168 dev_replace->srcdev->total_bytes;
169 dev_replace->tgtdev->disk_total_bytes = 169 dev_replace->tgtdev->disk_total_bytes =
170 dev_replace->srcdev->disk_total_bytes; 170 dev_replace->srcdev->disk_total_bytes;
171 dev_replace->tgtdev->commit_total_bytes =
172 dev_replace->srcdev->commit_total_bytes;
171 dev_replace->tgtdev->bytes_used = 173 dev_replace->tgtdev->bytes_used =
172 dev_replace->srcdev->bytes_used; 174 dev_replace->srcdev->bytes_used;
173 } 175 }
@@ -329,6 +331,20 @@ int btrfs_dev_replace_start(struct btrfs_root *root,
329 args->start.tgtdev_name[0] == '\0') 331 args->start.tgtdev_name[0] == '\0')
330 return -EINVAL; 332 return -EINVAL;
331 333
334 /*
335 * Here we commit the transaction to make sure commit_total_bytes
336 * of all the devices are updated.
337 */
338 trans = btrfs_attach_transaction(root);
339 if (!IS_ERR(trans)) {
340 ret = btrfs_commit_transaction(trans, root);
341 if (ret)
342 return ret;
343 } else if (PTR_ERR(trans) != -ENOENT) {
344 return PTR_ERR(trans);
345 }
346
347 /* the disk copy procedure reuses the scrub code */
332 mutex_lock(&fs_info->volume_mutex); 348 mutex_lock(&fs_info->volume_mutex);
333 ret = btrfs_dev_replace_find_srcdev(root, args->start.srcdevid, 349 ret = btrfs_dev_replace_find_srcdev(root, args->start.srcdevid,
334 args->start.srcdev_name, 350 args->start.srcdev_name,
@@ -539,6 +555,8 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
539 memcpy(src_device->uuid, uuid_tmp, sizeof(src_device->uuid)); 555 memcpy(src_device->uuid, uuid_tmp, sizeof(src_device->uuid));
540 tgt_device->total_bytes = src_device->total_bytes; 556 tgt_device->total_bytes = src_device->total_bytes;
541 tgt_device->disk_total_bytes = src_device->disk_total_bytes; 557 tgt_device->disk_total_bytes = src_device->disk_total_bytes;
558 ASSERT(list_empty(&src_device->resized_list));
559 tgt_device->commit_total_bytes = src_device->commit_total_bytes;
542 tgt_device->bytes_used = src_device->bytes_used; 560 tgt_device->bytes_used = src_device->bytes_used;
543 if (fs_info->sb->s_bdev == src_device->bdev) 561 if (fs_info->sb->s_bdev == src_device->bdev)
544 fs_info->sb->s_bdev = tgt_device->bdev; 562 fs_info->sb->s_bdev = tgt_device->bdev;
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index dbd792754b27..0cd18b725554 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -3127,7 +3127,8 @@ static int write_dev_supers(struct btrfs_device *device,
3127 3127
3128 for (i = 0; i < max_mirrors; i++) { 3128 for (i = 0; i < max_mirrors; i++) {
3129 bytenr = btrfs_sb_offset(i); 3129 bytenr = btrfs_sb_offset(i);
3130 if (bytenr + BTRFS_SUPER_INFO_SIZE >= device->total_bytes) 3130 if (bytenr + BTRFS_SUPER_INFO_SIZE >=
3131 device->commit_total_bytes)
3131 break; 3132 break;
3132 3133
3133 if (wait) { 3134 if (wait) {
@@ -3444,7 +3445,7 @@ static int write_all_supers(struct btrfs_root *root, int max_mirrors)
3444 btrfs_set_stack_device_type(dev_item, dev->type); 3445 btrfs_set_stack_device_type(dev_item, dev->type);
3445 btrfs_set_stack_device_id(dev_item, dev->devid); 3446 btrfs_set_stack_device_id(dev_item, dev->devid);
3446 btrfs_set_stack_device_total_bytes(dev_item, 3447 btrfs_set_stack_device_total_bytes(dev_item,
3447 dev->disk_total_bytes); 3448 dev->commit_total_bytes);
3448 btrfs_set_stack_device_bytes_used(dev_item, dev->bytes_used); 3449 btrfs_set_stack_device_bytes_used(dev_item, dev->bytes_used);
3449 btrfs_set_stack_device_io_align(dev_item, dev->io_align); 3450 btrfs_set_stack_device_io_align(dev_item, dev->io_align);
3450 btrfs_set_stack_device_io_width(dev_item, dev->io_width); 3451 btrfs_set_stack_device_io_width(dev_item, dev->io_width);
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index 72c8981e7c0a..9d80e37044db 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -2840,7 +2840,8 @@ static noinline_for_stack int scrub_supers(struct scrub_ctx *sctx,
2840 2840
2841 for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) { 2841 for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
2842 bytenr = btrfs_sb_offset(i); 2842 bytenr = btrfs_sb_offset(i);
2843 if (bytenr + BTRFS_SUPER_INFO_SIZE > scrub_dev->total_bytes) 2843 if (bytenr + BTRFS_SUPER_INFO_SIZE >
2844 scrub_dev->commit_total_bytes)
2844 break; 2845 break;
2845 2846
2846 ret = scrub_pages(sctx, bytenr, BTRFS_SUPER_INFO_SIZE, bytenr, 2847 ret = scrub_pages(sctx, bytenr, BTRFS_SUPER_INFO_SIZE, bytenr,
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index e336646508fe..2f7c0bef4043 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -1868,6 +1868,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
1868 memcpy(root->fs_info->super_for_commit, root->fs_info->super_copy, 1868 memcpy(root->fs_info->super_for_commit, root->fs_info->super_copy,
1869 sizeof(*root->fs_info->super_copy)); 1869 sizeof(*root->fs_info->super_copy));
1870 1870
1871 btrfs_update_commit_device_size(root->fs_info);
1872
1871 spin_lock(&root->fs_info->trans_lock); 1873 spin_lock(&root->fs_info->trans_lock);
1872 cur_trans->state = TRANS_STATE_UNBLOCKED; 1874 cur_trans->state = TRANS_STATE_UNBLOCKED;
1873 root->fs_info->running_transaction = NULL; 1875 root->fs_info->running_transaction = NULL;
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 1646659f2800..7b5c04259a6e 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -74,6 +74,7 @@ static struct btrfs_fs_devices *__alloc_fs_devices(void)
74 mutex_init(&fs_devs->device_list_mutex); 74 mutex_init(&fs_devs->device_list_mutex);
75 75
76 INIT_LIST_HEAD(&fs_devs->devices); 76 INIT_LIST_HEAD(&fs_devs->devices);
77 INIT_LIST_HEAD(&fs_devs->resized_devices);
77 INIT_LIST_HEAD(&fs_devs->alloc_list); 78 INIT_LIST_HEAD(&fs_devs->alloc_list);
78 INIT_LIST_HEAD(&fs_devs->list); 79 INIT_LIST_HEAD(&fs_devs->list);
79 80
@@ -154,6 +155,7 @@ static struct btrfs_device *__alloc_device(void)
154 155
155 INIT_LIST_HEAD(&dev->dev_list); 156 INIT_LIST_HEAD(&dev->dev_list);
156 INIT_LIST_HEAD(&dev->dev_alloc_list); 157 INIT_LIST_HEAD(&dev->dev_alloc_list);
158 INIT_LIST_HEAD(&dev->resized_list);
157 159
158 spin_lock_init(&dev->io_lock); 160 spin_lock_init(&dev->io_lock);
159 161
@@ -2168,6 +2170,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
2168 device->sector_size = root->sectorsize; 2170 device->sector_size = root->sectorsize;
2169 device->total_bytes = i_size_read(bdev->bd_inode); 2171 device->total_bytes = i_size_read(bdev->bd_inode);
2170 device->disk_total_bytes = device->total_bytes; 2172 device->disk_total_bytes = device->total_bytes;
2173 device->commit_total_bytes = device->total_bytes;
2171 device->dev_root = root->fs_info->dev_root; 2174 device->dev_root = root->fs_info->dev_root;
2172 device->bdev = bdev; 2175 device->bdev = bdev;
2173 device->in_fs_metadata = 1; 2176 device->in_fs_metadata = 1;
@@ -2364,6 +2367,8 @@ int btrfs_init_dev_replace_tgtdev(struct btrfs_root *root, char *device_path,
2364 device->sector_size = root->sectorsize; 2367 device->sector_size = root->sectorsize;
2365 device->total_bytes = srcdev->total_bytes; 2368 device->total_bytes = srcdev->total_bytes;
2366 device->disk_total_bytes = srcdev->disk_total_bytes; 2369 device->disk_total_bytes = srcdev->disk_total_bytes;
2370 ASSERT(list_empty(&srcdev->resized_list));
2371 device->commit_total_bytes = srcdev->commit_total_bytes;
2367 device->bytes_used = srcdev->bytes_used; 2372 device->bytes_used = srcdev->bytes_used;
2368 device->dev_root = fs_info->dev_root; 2373 device->dev_root = fs_info->dev_root;
2369 device->bdev = bdev; 2374 device->bdev = bdev;
@@ -2448,6 +2453,7 @@ static int __btrfs_grow_device(struct btrfs_trans_handle *trans,
2448{ 2453{
2449 struct btrfs_super_block *super_copy = 2454 struct btrfs_super_block *super_copy =
2450 device->dev_root->fs_info->super_copy; 2455 device->dev_root->fs_info->super_copy;
2456 struct btrfs_fs_devices *fs_devices;
2451 u64 old_total = btrfs_super_total_bytes(super_copy); 2457 u64 old_total = btrfs_super_total_bytes(super_copy);
2452 u64 diff = new_size - device->total_bytes; 2458 u64 diff = new_size - device->total_bytes;
2453 2459
@@ -2457,12 +2463,17 @@ static int __btrfs_grow_device(struct btrfs_trans_handle *trans,
2457 device->is_tgtdev_for_dev_replace) 2463 device->is_tgtdev_for_dev_replace)
2458 return -EINVAL; 2464 return -EINVAL;
2459 2465
2466 fs_devices = device->dev_root->fs_info->fs_devices;
2467
2460 btrfs_set_super_total_bytes(super_copy, old_total + diff); 2468 btrfs_set_super_total_bytes(super_copy, old_total + diff);
2461 device->fs_devices->total_rw_bytes += diff; 2469 device->fs_devices->total_rw_bytes += diff;
2462 2470
2463 device->total_bytes = new_size; 2471 device->total_bytes = new_size;
2464 device->disk_total_bytes = new_size; 2472 device->disk_total_bytes = new_size;
2465 btrfs_clear_space_info_full(device->dev_root->fs_info); 2473 btrfs_clear_space_info_full(device->dev_root->fs_info);
2474 if (list_empty(&device->resized_list))
2475 list_add_tail(&device->resized_list,
2476 &fs_devices->resized_devices);
2466 2477
2467 return btrfs_update_device(trans, device); 2478 return btrfs_update_device(trans, device);
2468} 2479}
@@ -4011,8 +4022,11 @@ again:
4011 } 4022 }
4012 4023
4013 lock_chunks(root); 4024 lock_chunks(root);
4014
4015 device->disk_total_bytes = new_size; 4025 device->disk_total_bytes = new_size;
4026 if (list_empty(&device->resized_list))
4027 list_add_tail(&device->resized_list,
4028 &root->fs_info->fs_devices->resized_devices);
4029
4016 /* Now btrfs_update_device() will change the on-disk size. */ 4030 /* Now btrfs_update_device() will change the on-disk size. */
4017 ret = btrfs_update_device(trans, device); 4031 ret = btrfs_update_device(trans, device);
4018 if (ret) { 4032 if (ret) {
@@ -5993,6 +6007,7 @@ static void fill_device_from_item(struct extent_buffer *leaf,
5993 device->devid = btrfs_device_id(leaf, dev_item); 6007 device->devid = btrfs_device_id(leaf, dev_item);
5994 device->disk_total_bytes = btrfs_device_total_bytes(leaf, dev_item); 6008 device->disk_total_bytes = btrfs_device_total_bytes(leaf, dev_item);
5995 device->total_bytes = device->disk_total_bytes; 6009 device->total_bytes = device->disk_total_bytes;
6010 device->commit_total_bytes = device->disk_total_bytes;
5996 device->bytes_used = btrfs_device_bytes_used(leaf, dev_item); 6011 device->bytes_used = btrfs_device_bytes_used(leaf, dev_item);
5997 device->type = btrfs_device_type(leaf, dev_item); 6012 device->type = btrfs_device_type(leaf, dev_item);
5998 device->io_align = btrfs_device_io_align(leaf, dev_item); 6013 device->io_align = btrfs_device_io_align(leaf, dev_item);
@@ -6520,3 +6535,26 @@ int btrfs_scratch_superblock(struct btrfs_device *device)
6520 6535
6521 return 0; 6536 return 0;
6522} 6537}
6538
6539/*
6540 * Update the size of all devices, which is used for writing out the
6541 * super blocks.
6542 */
6543void btrfs_update_commit_device_size(struct btrfs_fs_info *fs_info)
6544{
6545 struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
6546 struct btrfs_device *curr, *next;
6547
6548 if (list_empty(&fs_devices->resized_devices))
6549 return;
6550
6551 mutex_lock(&fs_devices->device_list_mutex);
6552 lock_chunks(fs_info->dev_root);
6553 list_for_each_entry_safe(curr, next, &fs_devices->resized_devices,
6554 resized_list) {
6555 list_del_init(&curr->resized_list);
6556 curr->commit_total_bytes = curr->disk_total_bytes;
6557 }
6558 unlock_chunks(fs_info->dev_root);
6559 mutex_unlock(&fs_devices->device_list_mutex);
6560}
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index e15f2886d33e..b30d018fa359 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -87,6 +87,21 @@ struct btrfs_device {
87 /* physical drive uuid (or lvm uuid) */ 87 /* physical drive uuid (or lvm uuid) */
88 u8 uuid[BTRFS_UUID_SIZE]; 88 u8 uuid[BTRFS_UUID_SIZE];
89 89
90 /*
91 * size of the device on the current transaction
92 *
93 * This variant is update when committing the transaction,
94 * and protected by device_list_mutex
95 */
96 u64 commit_total_bytes;
97
98 /*
99 * used to manage the device which is resized
100 *
101 * It is protected by chunk_lock.
102 */
103 struct list_head resized_list;
104
90 /* for sending down flush barriers */ 105 /* for sending down flush barriers */
91 int nobarriers; 106 int nobarriers;
92 struct bio *flush_bio; 107 struct bio *flush_bio;
@@ -136,6 +151,7 @@ struct btrfs_fs_devices {
136 struct mutex device_list_mutex; 151 struct mutex device_list_mutex;
137 struct list_head devices; 152 struct list_head devices;
138 153
154 struct list_head resized_devices;
139 /* devices not currently being allocated */ 155 /* devices not currently being allocated */
140 struct list_head alloc_list; 156 struct list_head alloc_list;
141 struct list_head list; 157 struct list_head list;
@@ -402,4 +418,6 @@ static inline void btrfs_dev_stat_reset(struct btrfs_device *dev,
402{ 418{
403 btrfs_dev_stat_set(dev, index, 0); 419 btrfs_dev_stat_set(dev, index, 0);
404} 420}
421
422void btrfs_update_commit_device_size(struct btrfs_fs_info *fs_info);
405#endif 423#endif