aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/dev-replace.c
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2014-09-03 09:35:32 -0400
committerChris Mason <clm@fb.com>2014-09-17 16:38:31 -0400
commit1c43366d3b3f0fa6c6e81aaf3aa18e0550245dad (patch)
treee5800ddfd965032bcd139ff4595e64d3868a6a5c /fs/btrfs/dev-replace.c
parentc7662111c741bc04a7192f2a00aad608cbc0b205 (diff)
Btrfs: fix unprotected assignment of the target device
We didn't protect the assignment of the target device, it might cause the problem that the super block update was skipped because we might find wrong size of the target device during the assignment. Fix it by moving the assignment sentences into the initialization function of the target device. And there is another merit that we can check if the target device is suitable more early. 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.c32
1 files changed, 8 insertions, 24 deletions
diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
index 10dfb41f4c22..72dc02e82945 100644
--- a/fs/btrfs/dev-replace.c
+++ b/fs/btrfs/dev-replace.c
@@ -330,29 +330,19 @@ int btrfs_dev_replace_start(struct btrfs_root *root,
330 return -EINVAL; 330 return -EINVAL;
331 331
332 mutex_lock(&fs_info->volume_mutex); 332 mutex_lock(&fs_info->volume_mutex);
333 ret = btrfs_init_dev_replace_tgtdev(root, args->start.tgtdev_name,
334 &tgt_device);
335 if (ret) {
336 btrfs_err(fs_info, "target device %s is invalid!",
337 args->start.tgtdev_name);
338 mutex_unlock(&fs_info->volume_mutex);
339 return -EINVAL;
340 }
341
342 ret = btrfs_dev_replace_find_srcdev(root, args->start.srcdevid, 333 ret = btrfs_dev_replace_find_srcdev(root, args->start.srcdevid,
343 args->start.srcdev_name, 334 args->start.srcdev_name,
344 &src_device); 335 &src_device);
345 mutex_unlock(&fs_info->volume_mutex);
346 if (ret) { 336 if (ret) {
347 ret = -EINVAL; 337 mutex_unlock(&fs_info->volume_mutex);
348 goto leave_no_lock; 338 return ret;
349 } 339 }
350 340
351 if (tgt_device->total_bytes < src_device->total_bytes) { 341 ret = btrfs_init_dev_replace_tgtdev(root, args->start.tgtdev_name,
352 btrfs_err(fs_info, "target device is smaller than source device!"); 342 src_device, &tgt_device);
353 ret = -EINVAL; 343 mutex_unlock(&fs_info->volume_mutex);
354 goto leave_no_lock; 344 if (ret)
355 } 345 return ret;
356 346
357 btrfs_dev_replace_lock(dev_replace); 347 btrfs_dev_replace_lock(dev_replace);
358 switch (dev_replace->replace_state) { 348 switch (dev_replace->replace_state) {
@@ -380,10 +370,6 @@ int btrfs_dev_replace_start(struct btrfs_root *root,
380 src_device->devid, 370 src_device->devid,
381 rcu_str_deref(tgt_device->name)); 371 rcu_str_deref(tgt_device->name));
382 372
383 tgt_device->total_bytes = src_device->total_bytes;
384 tgt_device->disk_total_bytes = src_device->disk_total_bytes;
385 tgt_device->bytes_used = src_device->bytes_used;
386
387 /* 373 /*
388 * from now on, the writes to the srcdev are all duplicated to 374 * from now on, the writes to the srcdev are all duplicated to
389 * go to the tgtdev as well (refer to btrfs_map_block()). 375 * go to the tgtdev as well (refer to btrfs_map_block()).
@@ -426,9 +412,7 @@ leave:
426 dev_replace->srcdev = NULL; 412 dev_replace->srcdev = NULL;
427 dev_replace->tgtdev = NULL; 413 dev_replace->tgtdev = NULL;
428 btrfs_dev_replace_unlock(dev_replace); 414 btrfs_dev_replace_unlock(dev_replace);
429leave_no_lock: 415 btrfs_destroy_dev_replace_tgtdev(fs_info, tgt_device);
430 if (tgt_device)
431 btrfs_destroy_dev_replace_tgtdev(fs_info, tgt_device);
432 return ret; 416 return ret;
433} 417}
434 418