• Y
    md: refactor idle/frozen_sync_thread() · 1ade24b6
    Yu Kuai 提交于
    hulk inclusion
    category: bugfix
    bugzilla: https://gitee.com/openeuler/kernel/issues/I6OMCC
    CVE: NA
    
    --------------------------------
    
    Our test found a following deadlock in raid10:
    
    1) Issue a normal write, and such write failed:
    
      raid10_end_write_request
       set_bit(R10BIO_WriteError, &r10_bio->state)
       one_write_done
        reschedule_retry
    
      // later from md thread
      raid10d
       handle_write_completed
        list_add(&r10_bio->retry_list, &conf->bio_end_io_list)
    
      // later from md thread
      raid10d
       if (!test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags))
        list_move(conf->bio_end_io_list.prev, &tmp)
        r10_bio = list_first_entry(&tmp, struct r10bio, retry_list)
        raid_end_bio_io(r10_bio)
    
    Dependency chain 1: normal io is waiting for updating superblock
    
    2) Trigger a recovery:
    
      raid10_sync_request
       raise_barrier
    
    Dependency chain 2: sync thread is waiting for normal io
    
    3) echo idle/frozen to sync_action:
    
      action_store
       mddev_lock
        md_unregister_thread
         kthread_stop
    
    Dependency chain 3: drop 'reconfig_mutex' is waiting for sync thread
    
    4) md thread can't update superblock:
    
      raid10d
       md_check_recovery
        if (mddev_trylock(mddev))
         md_update_sb
    
    Dependency chain 4: update superblock is waiting for 'reconfig_mutex'
    
    Hence cyclic dependency exist, in order to fix the problem, we must
    break one of them. Dependency 1 and 2 can't be broken because they are
    foundation design. Dependency 4 may be possible if it can be guaranteed
    that no io can be inflight, however, this requires a new mechanism which
    seems complex. Dependency 3 is a good choice, because idle/frozen only
    requires sync thread to finish, which can be done asynchronously that is
    already implemented, and 'reconfig_mutex' is not needed anymore.
    
    This patch switch 'idle' and 'frozen' to wait sync thread to be done
    asynchronously, and this patch also add a sequence counter to record how
    many times sync thread is done, so that 'idle' won't keep waiting on new
    started sync thread.
    Signed-off-by: NYu Kuai <yukuai3@huawei.com>
    Reviewed-by: NHou Tao <houtao1@huawei.com>
    Signed-off-by: NJialin Zhang <zhangjialin11@huawei.com>
    1ade24b6
md.h 28.6 KB