aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/dev-replace.c
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2014-09-03 09:35:33 -0400
committerChris Mason <clm@fb.com>2014-09-17 16:38:33 -0400
commit935e5cc935bcbf9b3d0dd59fed7dbc0f2ebca6bc (patch)
tree2489d657687317839ab01cd1c617356851839726 /fs/btrfs/dev-replace.c
parent1c43366d3b3f0fa6c6e81aaf3aa18e0550245dad (diff)
Btrfs: fix wrong disk size when writing super blocks
total_size will be changed when resizing a device, and disk_total_size will be changed if resizing is successful. Meanwhile, the on-disk super blocks of the previous transaction might not be updated. Considering the consistency of the metadata in the previous transaction, We should use the size in the previous transaction to check if the super block is beyond the boundary of the device. Fix it. Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/dev-replace.c')
-rw-r--r--fs/btrfs/dev-replace.c18
1 files changed, 18 insertions, 0 deletions
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;