diff options
Diffstat (limited to 'fs/btrfs/dev-replace.c')
-rw-r--r-- | fs/btrfs/dev-replace.c | 64 |
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 | ||
385 | void 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 | |||
393 | static char* btrfs_dev_name(struct btrfs_device *device) | 385 | static 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 | ||
505 | leave: | 506 | leave: |
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, | |||
545 | static void btrfs_rm_dev_replace_blocked(struct btrfs_fs_info *fs_info) | 545 | static 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) | |||
555 | static void btrfs_rm_dev_replace_unblocked(struct btrfs_fs_info *fs_info) | 555 | static 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 | ||
561 | static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info, | 561 | static 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) | |||
961 | void btrfs_dev_replace_read_lock(struct btrfs_dev_replace *dev_replace) | 961 | void 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 | ||
967 | void btrfs_dev_replace_read_unlock(struct btrfs_dev_replace *dev_replace) | 966 | void 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 | ||
986 | void btrfs_dev_replace_write_unlock(struct btrfs_dev_replace *dev_replace) | 983 | void 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 */ | ||
1003 | void 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 | |||
1015 | void btrfs_bio_counter_inc_noblocked(struct btrfs_fs_info *fs_info) | 997 | void 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 | ||
1020 | void btrfs_bio_counter_sub(struct btrfs_fs_info *fs_info, s64 amount) | 1002 | void 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 | ||
1026 | void btrfs_bio_counter_inc_blocked(struct btrfs_fs_info *fs_info) | 1008 | void 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 | } |