summaryrefslogtreecommitdiffstats
path: root/managemon.c
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2008-09-15 20:58:43 -0700
committerDan Williams <dan.j.williams@intel.com>2008-09-15 20:58:43 -0700
commit313a4a82f130e6668ba0f4550200662e168aa945 (patch)
tree56f6b17ba26b00684153bbbc976dd1c1f825b122 /managemon.c
parent4795982e68f72ef44bd29c9883e5f6291088a3e1 (diff)
downloadmdadm-313a4a82f130e6668ba0f4550200662e168aa945.tar.gz
mdadm-313a4a82f130e6668ba0f4550200662e168aa945.tar.xz
mdadm-313a4a82f130e6668ba0f4550200662e168aa945.zip
ping_manager() to prevent 'add' before 'remove' completes
It is currently possible to remove a device and re-add it without the manager noticing, i.e. without detecting a mdstat->devcnt container->devcnt mismatch. Introduce ping_manager() to arrange for mdmon to run manage_container() prior to mdadm dropping the exclusive open() on the container. Despite these precautions sysfs_read() may still fail. If this happens invalidate container->devcnt to ensure manage_container() runs at the next event. Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'managemon.c')
-rw-r--r--managemon.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/managemon.c b/managemon.c
index fc34d77..fc5da71 100644
--- a/managemon.c
+++ b/managemon.c
@@ -265,8 +265,11 @@ static void manage_container(struct mdstat_ent *mdstat,
* These need to be remove from, or added to, the array
*/
mdi = sysfs_read(-1, mdstat->devnum, GET_DEVS);
- if (!mdi)
+ if (!mdi) {
+ /* invalidate the current count so we can try again */
+ container->devcnt = -1;
return;
+ }
/* check for removals */
for (cdp = &container->devs; *cdp; ) {
@@ -525,14 +528,15 @@ static void handle_message(struct supertype *container, struct metadata_update *
struct metadata_update *mu;
- if (msg->len == 0) {
- int cnt;
-
+ if (msg->len <= 0)
while (update_queue_pending || update_queue) {
check_update_queue(container);
usleep(15*1000);
}
+ if (msg->len == 0) { /* ping_monitor */
+ int cnt;
+
cnt = monitor_loop_cnt;
if (cnt & 1)
cnt += 2; /* wait until next pselect */
@@ -542,6 +546,11 @@ static void handle_message(struct supertype *container, struct metadata_update *
while (monitor_loop_cnt - cnt < 0)
usleep(10 * 1000);
+ } else if (msg->len == -1) { /* ping_manager */
+ struct mdstat_ent *mdstat = mdstat_read(1, 0);
+
+ manage(mdstat, container);
+ free_mdstat(mdstat);
} else {
mu = malloc(sizeof(*mu));
mu->len = msg->len;