summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Brown <neilb@notabene.brown>2008-06-28 08:31:44 +1000
committerNeil Brown <neilb@notabene.brown>2008-06-28 08:31:44 +1000
commit526647320e696f434647f38421a6ecf65b859c43 (patch)
treeaa6bf13e6aa766051ba32a8b64157f4adf9fcd3e
parenta99ac97113d5bc25ddc4d17f404c2024ac6c57f9 (diff)
Make sure all changes to md/dev-XX/state are notified
The important state change happens during an interrupt in md_error. So just set a flag there and call sysfs_notify later in process context. Signed-off-by: Neil Brown <neilb@suse.de>
-rw-r--r--Documentation/md.txt10
-rw-r--r--drivers/md/md.c14
-rw-r--r--include/linux/raid/md_k.h3
3 files changed, 26 insertions, 1 deletions
diff --git a/Documentation/md.txt b/Documentation/md.txt
index eb6e69e3732..e06cc59437e 100644
--- a/Documentation/md.txt
+++ b/Documentation/md.txt
@@ -297,6 +297,10 @@ Each directory contains:
writemostly - device will only be subject to read
requests if there are no other options.
This applies only to raid1 arrays.
+ blocked - device has failed, metadata is "external",
+ and the failure hasn't been acknowledged yet.
+ Writes that would write to this device if
+ it were not faulty are blocked.
spare - device is working, but not a full member.
This includes spares that are in the process
of being recovered to
@@ -306,6 +310,12 @@ Each directory contains:
Writing "remove" removes the device from the array.
Writing "writemostly" sets the writemostly flag.
Writing "-writemostly" clears the writemostly flag.
+ Writing "blocked" sets the "blocked" flag.
+ Writing "-blocked" clear the "blocked" flag and allows writes
+ to complete.
+
+ This file responds to select/poll. Any change to 'faulty'
+ or 'blocked' causes an event.
errors
An approximate count of read errors that have been detected on
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 60d4cad88c2..dc99d95a1b6 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1886,6 +1886,8 @@ state_store(mdk_rdev_t *rdev, const char *buf, size_t len)
err = 0;
}
+ if (!err)
+ sysfs_notify(&rdev->kobj, NULL, "state");
return err ? err : len;
}
static struct rdev_sysfs_entry rdev_state =
@@ -1979,7 +1981,8 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
if (err) {
rdev->raid_disk = -1;
return err;
- }
+ } else
+ sysfs_notify(&rdev->kobj, NULL, "state");
sprintf(nm, "rd%d", rdev->raid_disk);
if (sysfs_create_link(&rdev->mddev->kobj, &rdev->kobj, nm))
printk(KERN_WARNING
@@ -1996,6 +1999,7 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
clear_bit(Faulty, &rdev->flags);
clear_bit(WriteMostly, &rdev->flags);
set_bit(In_sync, &rdev->flags);
+ sysfs_notify(&rdev->kobj, NULL, "state");
}
return len;
}
@@ -3525,6 +3529,7 @@ static int do_md_run(mddev_t * mddev)
return -EINVAL;
}
}
+ sysfs_notify(&rdev->kobj, NULL, "state");
}
md_probe(mddev->unit, NULL, NULL);
@@ -4256,6 +4261,8 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
}
if (err)
export_rdev(rdev);
+ else
+ sysfs_notify(&rdev->kobj, NULL, "state");
md_update_sb(mddev, 1);
if (mddev->degraded)
@@ -5115,6 +5122,7 @@ void md_error(mddev_t *mddev, mdk_rdev_t *rdev)
mddev->pers->error_handler(mddev,rdev);
if (mddev->degraded)
set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
+ set_bit(StateChanged, &rdev->flags);
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
md_wakeup_thread(mddev->thread);
@@ -6037,6 +6045,10 @@ void md_check_recovery(mddev_t *mddev)
if (mddev->flags)
md_update_sb(mddev, 0);
+ rdev_for_each(rdev, rtmp, mddev)
+ if (test_and_clear_bit(StateChanged, &rdev->flags))
+ sysfs_notify(&rdev->kobj, NULL, "state");
+
if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) &&
!test_bit(MD_RECOVERY_DONE, &mddev->recovery)) {
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
index 62aa9c9a6dd..df30c439587 100644
--- a/include/linux/raid/md_k.h
+++ b/include/linux/raid/md_k.h
@@ -87,6 +87,9 @@ struct mdk_rdev_s
#define Blocked 8 /* An error occured on an externally
* managed array, don't allow writes
* until it is cleared */
+#define StateChanged 9 /* Faulty or Blocked has changed during
+ * interrupt, so it needs to be
+ * notified by the thread */
wait_queue_head_t blocked_wait;
int desc_nr; /* descriptor index in the superblock */