Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 47 additions & 13 deletions drivers/md/md.c
Original file line number Diff line number Diff line change
Expand Up @@ -4822,9 +4822,42 @@ metadata_store(struct mddev *mddev, const char *buf, size_t len)
static struct md_sysfs_entry md_metadata =
__ATTR_PREALLOC(metadata_version, S_IRUGO|S_IWUSR, metadata_show, metadata_store);

static bool rdev_needs_recovery(struct md_rdev *rdev, sector_t sectors)
{
return rdev->raid_disk >= 0 &&
!test_bit(Journal, &rdev->flags) &&
!test_bit(Faulty, &rdev->flags) &&
!test_bit(In_sync, &rdev->flags) &&
rdev->recovery_offset < sectors;
}

static enum sync_action md_get_active_sync_action(struct mddev *mddev)
{
struct md_rdev *rdev;
bool is_recover = false;

if (mddev->resync_offset < MaxSector)
return ACTION_RESYNC;

if (mddev->reshape_position != MaxSector)
return ACTION_RESHAPE;

rcu_read_lock();
rdev_for_each_rcu(rdev, mddev) {
if (rdev_needs_recovery(rdev, MaxSector)) {
is_recover = true;
break;
}
}
rcu_read_unlock();

return is_recover ? ACTION_RECOVER : ACTION_IDLE;
}

enum sync_action md_sync_action(struct mddev *mddev)
{
unsigned long recovery = mddev->recovery;
enum sync_action active_action;

/*
* frozen has the highest priority, means running sync_thread will be
Expand All @@ -4848,8 +4881,17 @@ enum sync_action md_sync_action(struct mddev *mddev)
!test_bit(MD_RECOVERY_NEEDED, &recovery))
return ACTION_IDLE;

if (test_bit(MD_RECOVERY_RESHAPE, &recovery) ||
mddev->reshape_position != MaxSector)
/*
* Check if any sync operation (resync/recover/reshape) is
* currently active. This ensures that only one sync operation
* can run at a time. Returns the type of active operation, or
* ACTION_IDLE if none are active.
*/
active_action = md_get_active_sync_action(mddev);
if (active_action != ACTION_IDLE)
return active_action;

if (test_bit(MD_RECOVERY_RESHAPE, &recovery))
return ACTION_RESHAPE;

if (test_bit(MD_RECOVERY_RECOVER, &recovery))
Expand Down Expand Up @@ -8959,11 +9001,7 @@ static sector_t md_sync_position(struct mddev *mddev, enum sync_action action)
start = MaxSector;
rcu_read_lock();
rdev_for_each_rcu(rdev, mddev)
if (rdev->raid_disk >= 0 &&
!test_bit(Journal, &rdev->flags) &&
!test_bit(Faulty, &rdev->flags) &&
!test_bit(In_sync, &rdev->flags) &&
rdev->recovery_offset < start)
if (rdev_needs_recovery(rdev, start))
start = rdev->recovery_offset;
rcu_read_unlock();

Expand Down Expand Up @@ -9322,12 +9360,8 @@ void md_do_sync(struct md_thread *thread)
test_bit(MD_RECOVERY_RECOVER, &mddev->recovery)) {
rcu_read_lock();
rdev_for_each_rcu(rdev, mddev)
if (rdev->raid_disk >= 0 &&
mddev->delta_disks >= 0 &&
!test_bit(Journal, &rdev->flags) &&
!test_bit(Faulty, &rdev->flags) &&
!test_bit(In_sync, &rdev->flags) &&
rdev->recovery_offset < mddev->curr_resync)
if (mddev->delta_disks >= 0 &&
rdev_needs_recovery(rdev, mddev->curr_resync))
rdev->recovery_offset = mddev->curr_resync;
rcu_read_unlock();
}
Expand Down
Loading