aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/dev-replace.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/dev-replace.c')
-rw-r--r--fs/btrfs/dev-replace.c64
1 files changed, 23 insertions, 41 deletions
diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
index dec01970d8c5..2aa48aecc52b 100644
--- a/fs/btrfs/dev-replace.c
+++ b/fs/btrfs/dev-replace.c
@@ -382,14 +382,6 @@ out:
382 return ret; 382 return ret;
383} 383}
384 384
385void btrfs_after_dev_replace_commit(struct btrfs_fs_info *fs_info)
386{
387 struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
388
389 dev_replace->committed_cursor_left =
390 dev_replace->cursor_left_last_write_of_item;
391}
392
393static char* btrfs_dev_name(struct btrfs_device *device) 385static char* btrfs_dev_name(struct btrfs_device *device)
394{ 386{
395 if (!device || test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state)) 387 if (!device || test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state))
@@ -408,11 +400,12 @@ int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info,
408 int ret; 400 int ret;
409 struct btrfs_device *tgt_device = NULL; 401 struct btrfs_device *tgt_device = NULL;
410 struct btrfs_device *src_device = NULL; 402 struct btrfs_device *src_device = NULL;
403 bool need_unlock;
411 404
412 ret = btrfs_find_device_by_devspec(fs_info, srcdevid, 405 src_device = btrfs_find_device_by_devspec(fs_info, srcdevid,
413 srcdev_name, &src_device); 406 srcdev_name);
414 if (ret) 407 if (IS_ERR(src_device))
415 return ret; 408 return PTR_ERR(src_device);
416 409
417 ret = btrfs_init_dev_replace_tgtdev(fs_info, tgtdev_name, 410 ret = btrfs_init_dev_replace_tgtdev(fs_info, tgtdev_name,
418 src_device, &tgt_device); 411 src_device, &tgt_device);
@@ -432,6 +425,7 @@ int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info,
432 return PTR_ERR(trans); 425 return PTR_ERR(trans);
433 } 426 }
434 427
428 need_unlock = true;
435 btrfs_dev_replace_write_lock(dev_replace); 429 btrfs_dev_replace_write_lock(dev_replace);
436 switch (dev_replace->replace_state) { 430 switch (dev_replace->replace_state) {
437 case BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED: 431 case BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED:
@@ -440,6 +434,7 @@ int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info,
440 break; 434 break;
441 case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED: 435 case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
442 case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED: 436 case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:
437 ASSERT(0);
443 ret = BTRFS_IOCTL_DEV_REPLACE_RESULT_ALREADY_STARTED; 438 ret = BTRFS_IOCTL_DEV_REPLACE_RESULT_ALREADY_STARTED;
444 goto leave; 439 goto leave;
445 } 440 }
@@ -470,6 +465,7 @@ int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info,
470 atomic64_set(&dev_replace->num_write_errors, 0); 465 atomic64_set(&dev_replace->num_write_errors, 0);
471 atomic64_set(&dev_replace->num_uncorrectable_read_errors, 0); 466 atomic64_set(&dev_replace->num_uncorrectable_read_errors, 0);
472 btrfs_dev_replace_write_unlock(dev_replace); 467 btrfs_dev_replace_write_unlock(dev_replace);
468 need_unlock = false;
473 469
474 ret = btrfs_sysfs_add_device_link(tgt_device->fs_devices, tgt_device); 470 ret = btrfs_sysfs_add_device_link(tgt_device->fs_devices, tgt_device);
475 if (ret) 471 if (ret)
@@ -481,7 +477,12 @@ int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info,
481 trans = btrfs_start_transaction(root, 0); 477 trans = btrfs_start_transaction(root, 0);
482 if (IS_ERR(trans)) { 478 if (IS_ERR(trans)) {
483 ret = PTR_ERR(trans); 479 ret = PTR_ERR(trans);
480 need_unlock = true;
484 btrfs_dev_replace_write_lock(dev_replace); 481 btrfs_dev_replace_write_lock(dev_replace);
482 dev_replace->replace_state =
483 BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED;
484 dev_replace->srcdev = NULL;
485 dev_replace->tgtdev = NULL;
485 goto leave; 486 goto leave;
486 } 487 }
487 488
@@ -503,9 +504,8 @@ int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info,
503 return ret; 504 return ret;
504 505
505leave: 506leave:
506 dev_replace->srcdev = NULL; 507 if (need_unlock)
507 dev_replace->tgtdev = NULL; 508 btrfs_dev_replace_write_unlock(dev_replace);
508 btrfs_dev_replace_write_unlock(dev_replace);
509 btrfs_destroy_dev_replace_tgtdev(tgt_device); 509 btrfs_destroy_dev_replace_tgtdev(tgt_device);
510 return ret; 510 return ret;
511} 511}
@@ -545,8 +545,8 @@ int btrfs_dev_replace_by_ioctl(struct btrfs_fs_info *fs_info,
545static void btrfs_rm_dev_replace_blocked(struct btrfs_fs_info *fs_info) 545static void btrfs_rm_dev_replace_blocked(struct btrfs_fs_info *fs_info)
546{ 546{
547 set_bit(BTRFS_FS_STATE_DEV_REPLACING, &fs_info->fs_state); 547 set_bit(BTRFS_FS_STATE_DEV_REPLACING, &fs_info->fs_state);
548 wait_event(fs_info->replace_wait, !percpu_counter_sum( 548 wait_event(fs_info->dev_replace.replace_wait, !percpu_counter_sum(
549 &fs_info->bio_counter)); 549 &fs_info->dev_replace.bio_counter));
550} 550}
551 551
552/* 552/*
@@ -555,7 +555,7 @@ static void btrfs_rm_dev_replace_blocked(struct btrfs_fs_info *fs_info)
555static void btrfs_rm_dev_replace_unblocked(struct btrfs_fs_info *fs_info) 555static void btrfs_rm_dev_replace_unblocked(struct btrfs_fs_info *fs_info)
556{ 556{
557 clear_bit(BTRFS_FS_STATE_DEV_REPLACING, &fs_info->fs_state); 557 clear_bit(BTRFS_FS_STATE_DEV_REPLACING, &fs_info->fs_state);
558 wake_up(&fs_info->replace_wait); 558 wake_up(&fs_info->dev_replace.replace_wait);
559} 559}
560 560
561static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info, 561static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
@@ -961,13 +961,10 @@ int btrfs_dev_replace_is_ongoing(struct btrfs_dev_replace *dev_replace)
961void btrfs_dev_replace_read_lock(struct btrfs_dev_replace *dev_replace) 961void btrfs_dev_replace_read_lock(struct btrfs_dev_replace *dev_replace)
962{ 962{
963 read_lock(&dev_replace->lock); 963 read_lock(&dev_replace->lock);
964 atomic_inc(&dev_replace->read_locks);
965} 964}
966 965
967void btrfs_dev_replace_read_unlock(struct btrfs_dev_replace *dev_replace) 966void btrfs_dev_replace_read_unlock(struct btrfs_dev_replace *dev_replace)
968{ 967{
969 ASSERT(atomic_read(&dev_replace->read_locks) > 0);
970 atomic_dec(&dev_replace->read_locks);
971 read_unlock(&dev_replace->lock); 968 read_unlock(&dev_replace->lock);
972} 969}
973 970
@@ -985,7 +982,6 @@ again:
985 982
986void btrfs_dev_replace_write_unlock(struct btrfs_dev_replace *dev_replace) 983void btrfs_dev_replace_write_unlock(struct btrfs_dev_replace *dev_replace)
987{ 984{
988 ASSERT(atomic_read(&dev_replace->blocking_readers) == 0);
989 write_unlock(&dev_replace->lock); 985 write_unlock(&dev_replace->lock);
990} 986}
991 987
@@ -994,45 +990,31 @@ void btrfs_dev_replace_set_lock_blocking(
994 struct btrfs_dev_replace *dev_replace) 990 struct btrfs_dev_replace *dev_replace)
995{ 991{
996 /* only set blocking for read lock */ 992 /* only set blocking for read lock */
997 ASSERT(atomic_read(&dev_replace->read_locks) > 0);
998 atomic_inc(&dev_replace->blocking_readers); 993 atomic_inc(&dev_replace->blocking_readers);
999 read_unlock(&dev_replace->lock); 994 read_unlock(&dev_replace->lock);
1000} 995}
1001 996
1002/* acquire read lock and dec blocking cnt */
1003void btrfs_dev_replace_clear_lock_blocking(
1004 struct btrfs_dev_replace *dev_replace)
1005{
1006 /* only set blocking for read lock */
1007 ASSERT(atomic_read(&dev_replace->read_locks) > 0);
1008 ASSERT(atomic_read(&dev_replace->blocking_readers) > 0);
1009 read_lock(&dev_replace->lock);
1010 /* Barrier implied by atomic_dec_and_test */
1011 if (atomic_dec_and_test(&dev_replace->blocking_readers))
1012 cond_wake_up_nomb(&dev_replace->read_lock_wq);
1013}
1014
1015void btrfs_bio_counter_inc_noblocked(struct btrfs_fs_info *fs_info) 997void btrfs_bio_counter_inc_noblocked(struct btrfs_fs_info *fs_info)
1016{ 998{
1017 percpu_counter_inc(&fs_info->bio_counter); 999 percpu_counter_inc(&fs_info->dev_replace.bio_counter);
1018} 1000}
1019 1001
1020void btrfs_bio_counter_sub(struct btrfs_fs_info *fs_info, s64 amount) 1002void btrfs_bio_counter_sub(struct btrfs_fs_info *fs_info, s64 amount)
1021{ 1003{
1022 percpu_counter_sub(&fs_info->bio_counter, amount); 1004 percpu_counter_sub(&fs_info->dev_replace.bio_counter, amount);
1023 cond_wake_up_nomb(&fs_info->replace_wait); 1005 cond_wake_up_nomb(&fs_info->dev_replace.replace_wait);
1024} 1006}
1025 1007
1026void btrfs_bio_counter_inc_blocked(struct btrfs_fs_info *fs_info) 1008void btrfs_bio_counter_inc_blocked(struct btrfs_fs_info *fs_info)
1027{ 1009{
1028 while (1) { 1010 while (1) {
1029 percpu_counter_inc(&fs_info->bio_counter); 1011 percpu_counter_inc(&fs_info->dev_replace.bio_counter);
1030 if (likely(!test_bit(BTRFS_FS_STATE_DEV_REPLACING, 1012 if (likely(!test_bit(BTRFS_FS_STATE_DEV_REPLACING,
1031 &fs_info->fs_state))) 1013 &fs_info->fs_state)))
1032 break; 1014 break;
1033 1015
1034 btrfs_bio_counter_dec(fs_info); 1016 btrfs_bio_counter_dec(fs_info);
1035 wait_event(fs_info->replace_wait, 1017 wait_event(fs_info->dev_replace.replace_wait,
1036 !test_bit(BTRFS_FS_STATE_DEV_REPLACING, 1018 !test_bit(BTRFS_FS_STATE_DEV_REPLACING,
1037 &fs_info->fs_state)); 1019 &fs_info->fs_state));
1038 } 1020 }