diff options
author | Yufen Yu <yuyufen@huawei.com> | 2018-04-08 21:50:44 -0400 |
---|---|---|
committer | Shaohua Li <shli@fb.com> | 2018-04-09 11:41:16 -0400 |
commit | 8c2425932398a160f687534efe71f0ec4b92833e (patch) | |
tree | aa5015eade10a68adf26f927a06164b0d66cfb61 | |
parent | 0ea9924abe125a0c1277484f1a3d512b3f45c320 (diff) |
md/raid1: exit sync request if MD_RECOVERY_INTR is set
We met a sync thread stuck as follows:
raid1_sync_request+0x2c9/0xb50
md_do_sync+0x983/0xfa0
md_thread+0x11c/0x160
kthread+0x111/0x130
ret_from_fork+0x35/0x40
0xffffffffffffffff
At the same time, there is a stuck mdadm thread (mdadm --manage
/dev/md2 --add /dev/sda). It is trying to stop the sync thread:
kthread_stop+0x42/0xf0
md_unregister_thread+0x3a/0x70
md_reap_sync_thread+0x15/0x160
action_store+0x142/0x2a0
md_attr_store+0x6c/0xb0
kernfs_fop_write+0x102/0x180
__vfs_write+0x33/0x170
vfs_write+0xad/0x1a0
SyS_write+0x52/0xc0
do_syscall_64+0x6e/0x190
entry_SYSCALL_64_after_hwframe+0x3d/0xa2
Debug tools show that the sync thread is waiting in raise_barrier(),
until raid1d() end all normal IO bios into bio_end_io_list(introduced
in commit 55ce74d4bfe1). But, raid1d() cannot end these bios if
MD_CHANGE_PENDING bit is set. It needs to get mddev->reconfig_mutex lock
and then clear the bit in md_check_recovery().
However, the lock is holding by mdadm in action_store().
Thus, there is a loop:
mdadm waiting for sync thread to stop, sync thread waiting for
raid1d() to end bios, raid1d() waiting for mdadm to release
mddev->reconfig_mutex lock and then it can end bios.
Fix this by checking MD_RECOVERY_INTR while waiting in raise_barrier(),
so that sync thread can exit while mdadm is stoping the sync thread.
Fixes: 55ce74d4bfe1 ("md/raid1: ensure device failure recorded before write request returns.")
Signed-off-by: Jason Yan <yanaijie@huawei.com>
Signed-off-by: Yufen Yu <yuyufen@huawei.com>
Signed-off-by: Shaohua Li <shli@fb.com>
-rw-r--r-- | drivers/md/raid1.c | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index e2943fb74056..6f624311cec2 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
@@ -854,7 +854,7 @@ static void flush_pending_writes(struct r1conf *conf) | |||
854 | * there is no normal IO happeing. It must arrange to call | 854 | * there is no normal IO happeing. It must arrange to call |
855 | * lower_barrier when the particular background IO completes. | 855 | * lower_barrier when the particular background IO completes. |
856 | */ | 856 | */ |
857 | static void raise_barrier(struct r1conf *conf, sector_t sector_nr) | 857 | static sector_t raise_barrier(struct r1conf *conf, sector_t sector_nr) |
858 | { | 858 | { |
859 | int idx = sector_to_idx(sector_nr); | 859 | int idx = sector_to_idx(sector_nr); |
860 | 860 | ||
@@ -885,13 +885,23 @@ static void raise_barrier(struct r1conf *conf, sector_t sector_nr) | |||
885 | * max resync count which allowed on current I/O barrier bucket. | 885 | * max resync count which allowed on current I/O barrier bucket. |
886 | */ | 886 | */ |
887 | wait_event_lock_irq(conf->wait_barrier, | 887 | wait_event_lock_irq(conf->wait_barrier, |
888 | !conf->array_frozen && | 888 | (!conf->array_frozen && |
889 | !atomic_read(&conf->nr_pending[idx]) && | 889 | !atomic_read(&conf->nr_pending[idx]) && |
890 | atomic_read(&conf->barrier[idx]) < RESYNC_DEPTH, | 890 | atomic_read(&conf->barrier[idx]) < RESYNC_DEPTH) || |
891 | test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery), | ||
891 | conf->resync_lock); | 892 | conf->resync_lock); |
892 | 893 | ||
894 | if (test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery)) { | ||
895 | atomic_dec(&conf->barrier[idx]); | ||
896 | spin_unlock_irq(&conf->resync_lock); | ||
897 | wake_up(&conf->wait_barrier); | ||
898 | return -EINTR; | ||
899 | } | ||
900 | |||
893 | atomic_inc(&conf->nr_sync_pending); | 901 | atomic_inc(&conf->nr_sync_pending); |
894 | spin_unlock_irq(&conf->resync_lock); | 902 | spin_unlock_irq(&conf->resync_lock); |
903 | |||
904 | return 0; | ||
895 | } | 905 | } |
896 | 906 | ||
897 | static void lower_barrier(struct r1conf *conf, sector_t sector_nr) | 907 | static void lower_barrier(struct r1conf *conf, sector_t sector_nr) |
@@ -2662,9 +2672,12 @@ static sector_t raid1_sync_request(struct mddev *mddev, sector_t sector_nr, | |||
2662 | 2672 | ||
2663 | bitmap_cond_end_sync(mddev->bitmap, sector_nr, | 2673 | bitmap_cond_end_sync(mddev->bitmap, sector_nr, |
2664 | mddev_is_clustered(mddev) && (sector_nr + 2 * RESYNC_SECTORS > conf->cluster_sync_high)); | 2674 | mddev_is_clustered(mddev) && (sector_nr + 2 * RESYNC_SECTORS > conf->cluster_sync_high)); |
2665 | r1_bio = raid1_alloc_init_r1buf(conf); | ||
2666 | 2675 | ||
2667 | raise_barrier(conf, sector_nr); | 2676 | |
2677 | if (raise_barrier(conf, sector_nr)) | ||
2678 | return 0; | ||
2679 | |||
2680 | r1_bio = raid1_alloc_init_r1buf(conf); | ||
2668 | 2681 | ||
2669 | rcu_read_lock(); | 2682 | rcu_read_lock(); |
2670 | /* | 2683 | /* |