diff options
author | Dan Williams <dan.j.williams@intel.com> | 2008-09-15 20:58:43 -0700 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2008-09-15 20:58:43 -0700 |
commit | 313a4a82f130e6668ba0f4550200662e168aa945 (patch) | |
tree | 56f6b17ba26b00684153bbbc976dd1c1f825b122 /managemon.c | |
parent | 4795982e68f72ef44bd29c9883e5f6291088a3e1 (diff) | |
download | mdadm-313a4a82f130e6668ba0f4550200662e168aa945.tar.gz |
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.c | 17 |
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; |