Commit 0fd62b86 authored by Neil Brown's avatar Neil Brown

Make sure all changes to md/array_state are notified.

Changes in md/array_state could be of interest to a monitoring
program.  So make sure all changes trigger a notification.

Exceptions:
   changing active_idle to active is not reported because it
      is frequent and not interesting.
   changing active to active_idle is only reported on arrays
      with externally managed metadata, as it is not interesting
      otherwise.
Signed-off-by: default avatarNeil Brown <neilb@suse.de>
parent c7d0c941
...@@ -236,6 +236,11 @@ All md devices contain: ...@@ -236,6 +236,11 @@ All md devices contain:
writing the word for the desired state, however some states writing the word for the desired state, however some states
cannot be explicitly set, and some transitions are not allowed. cannot be explicitly set, and some transitions are not allowed.
Select/poll works on this file. All changes except between
active_idle and active (which can be frequent and are not
very interesting) are notified. active->active_idle is
reported if the metadata is externally managed.
clear clear
No devices, no size, no level No devices, no size, no level
Writing is equivalent to STOP_ARRAY ioctl Writing is equivalent to STOP_ARRAY ioctl
......
...@@ -2716,8 +2716,10 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len) ...@@ -2716,8 +2716,10 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
} }
if (err) if (err)
return err; return err;
else else {
sysfs_notify(&mddev->kobj, NULL, "array_state");
return len; return len;
}
} }
static struct md_sysfs_entry md_array_state = static struct md_sysfs_entry md_array_state =
__ATTR(array_state, S_IRUGO|S_IWUSR, array_state_show, array_state_store); __ATTR(array_state, S_IRUGO|S_IWUSR, array_state_show, array_state_store);
...@@ -3408,7 +3410,11 @@ static void md_safemode_timeout(unsigned long data) ...@@ -3408,7 +3410,11 @@ static void md_safemode_timeout(unsigned long data)
{ {
mddev_t *mddev = (mddev_t *) data; mddev_t *mddev = (mddev_t *) data;
mddev->safemode = 1; if (!atomic_read(&mddev->writes_pending)) {
mddev->safemode = 1;
if (mddev->external)
sysfs_notify(&mddev->kobj, NULL, "array_state");
}
md_wakeup_thread(mddev->thread); md_wakeup_thread(mddev->thread);
} }
...@@ -3675,6 +3681,7 @@ static int do_md_run(mddev_t * mddev) ...@@ -3675,6 +3681,7 @@ static int do_md_run(mddev_t * mddev)
mddev->changed = 1; mddev->changed = 1;
md_new_event(mddev); md_new_event(mddev);
sysfs_notify(&mddev->kobj, NULL, "array_state");
kobject_uevent(&mddev->gendisk->dev.kobj, KOBJ_CHANGE); kobject_uevent(&mddev->gendisk->dev.kobj, KOBJ_CHANGE);
return 0; return 0;
} }
...@@ -3709,6 +3716,8 @@ static int restart_array(mddev_t *mddev) ...@@ -3709,6 +3716,8 @@ static int restart_array(mddev_t *mddev)
md_wakeup_thread(mddev->thread); md_wakeup_thread(mddev->thread);
md_wakeup_thread(mddev->sync_thread); md_wakeup_thread(mddev->sync_thread);
err = 0; err = 0;
sysfs_notify(&mddev->kobj, NULL, "array_state");
} else } else
err = -EINVAL; err = -EINVAL;
...@@ -3879,6 +3888,7 @@ static int do_md_stop(mddev_t * mddev, int mode) ...@@ -3879,6 +3888,7 @@ static int do_md_stop(mddev_t * mddev, int mode)
mdname(mddev)); mdname(mddev));
err = 0; err = 0;
md_new_event(mddev); md_new_event(mddev);
sysfs_notify(&mddev->kobj, NULL, "array_state");
out: out:
return err; return err;
} }
...@@ -4876,8 +4886,9 @@ static int md_ioctl(struct inode *inode, struct file *file, ...@@ -4876,8 +4886,9 @@ static int md_ioctl(struct inode *inode, struct file *file,
mddev->ro && mddev->pers) { mddev->ro && mddev->pers) {
if (mddev->ro == 2) { if (mddev->ro == 2) {
mddev->ro = 0; mddev->ro = 0;
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); sysfs_notify(&mddev->kobj, NULL, "array_state");
md_wakeup_thread(mddev->thread); set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
md_wakeup_thread(mddev->thread);
} else { } else {
err = -EROFS; err = -EROFS;
...@@ -5516,6 +5527,7 @@ void md_done_sync(mddev_t *mddev, int blocks, int ok) ...@@ -5516,6 +5527,7 @@ void md_done_sync(mddev_t *mddev, int blocks, int ok)
*/ */
void md_write_start(mddev_t *mddev, struct bio *bi) void md_write_start(mddev_t *mddev, struct bio *bi)
{ {
int did_change = 0;
if (bio_data_dir(bi) != WRITE) if (bio_data_dir(bi) != WRITE)
return; return;
...@@ -5526,6 +5538,7 @@ void md_write_start(mddev_t *mddev, struct bio *bi) ...@@ -5526,6 +5538,7 @@ void md_write_start(mddev_t *mddev, struct bio *bi)
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
md_wakeup_thread(mddev->thread); md_wakeup_thread(mddev->thread);
md_wakeup_thread(mddev->sync_thread); md_wakeup_thread(mddev->sync_thread);
did_change = 1;
} }
atomic_inc(&mddev->writes_pending); atomic_inc(&mddev->writes_pending);
if (mddev->safemode == 1) if (mddev->safemode == 1)
...@@ -5536,10 +5549,12 @@ void md_write_start(mddev_t *mddev, struct bio *bi) ...@@ -5536,10 +5549,12 @@ void md_write_start(mddev_t *mddev, struct bio *bi)
mddev->in_sync = 0; mddev->in_sync = 0;
set_bit(MD_CHANGE_CLEAN, &mddev->flags); set_bit(MD_CHANGE_CLEAN, &mddev->flags);
md_wakeup_thread(mddev->thread); md_wakeup_thread(mddev->thread);
did_change = 1;
} }
spin_unlock_irq(&mddev->write_lock); spin_unlock_irq(&mddev->write_lock);
sysfs_notify(&mddev->kobj, NULL, "array_state");
} }
if (did_change)
sysfs_notify(&mddev->kobj, NULL, "array_state");
wait_event(mddev->sb_wait, wait_event(mddev->sb_wait,
!test_bit(MD_CHANGE_CLEAN, &mddev->flags) && !test_bit(MD_CHANGE_CLEAN, &mddev->flags) &&
!test_bit(MD_CHANGE_PENDING, &mddev->flags)); !test_bit(MD_CHANGE_PENDING, &mddev->flags));
...@@ -5991,18 +6006,22 @@ void md_check_recovery(mddev_t *mddev) ...@@ -5991,18 +6006,22 @@ void md_check_recovery(mddev_t *mddev)
int spares = 0; int spares = 0;
if (!mddev->external) { if (!mddev->external) {
int did_change = 0;
spin_lock_irq(&mddev->write_lock); spin_lock_irq(&mddev->write_lock);
if (mddev->safemode && if (mddev->safemode &&
!atomic_read(&mddev->writes_pending) && !atomic_read(&mddev->writes_pending) &&
!mddev->in_sync && !mddev->in_sync &&
mddev->recovery_cp == MaxSector) { mddev->recovery_cp == MaxSector) {
mddev->in_sync = 1; mddev->in_sync = 1;
did_change = 1;
if (mddev->persistent) if (mddev->persistent)
set_bit(MD_CHANGE_CLEAN, &mddev->flags); set_bit(MD_CHANGE_CLEAN, &mddev->flags);
} }
if (mddev->safemode == 1) if (mddev->safemode == 1)
mddev->safemode = 0; mddev->safemode = 0;
spin_unlock_irq(&mddev->write_lock); spin_unlock_irq(&mddev->write_lock);
if (did_change)
sysfs_notify(&mddev->kobj, NULL, "array_state");
} }
if (mddev->flags) if (mddev->flags)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment