diff options
-rw-r--r-- | fs/btrfs/check-integrity.c | 2 | ||||
-rw-r--r-- | fs/btrfs/dev-replace.c | 18 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 5 | ||||
-rw-r--r-- | fs/btrfs/scrub.c | 3 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 2 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 40 | ||||
-rw-r--r-- | fs/btrfs/volumes.h | 18 |
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 | */ | ||
6543 | void 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 | |||
422 | void btrfs_update_commit_device_size(struct btrfs_fs_info *fs_info); | ||
405 | #endif | 423 | #endif |