Make metadata updates from manage to monitor 'synchronous'

A metadata update may modify the data structure of the metadata
including freeing things, so it is not safe of the manager to touch
the metadata while an update is pending in the monitor.
So When an update has been submitted, don't do anything else in the
manager until it is complete.

Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
NeilBrown 2008-08-19 14:55:03 +10:00
parent 01f157d74a
commit 3c00ffbe98
1 changed files with 25 additions and 18 deletions

View File

@ -218,15 +218,6 @@ static void queue_metadata_update(struct metadata_update *mu)
*qp = mu;
}
void wait_update_handled(void)
{
/* Wait for any pending update to be handled by monitor.
* i.e. wait until update_queue is NULL
*/
while (update_queue)
usleep(100 * 1000);
}
static void manage_container(struct mdstat_ent *mdstat,
struct supertype *container)
{
@ -272,7 +263,7 @@ static void manage_member(struct mdstat_ent *mdstat,
struct metadata_update *updates = NULL;
struct mdinfo *newdev;
struct active_array *newa;
wait_update_handled();
a->check_degraded = 0;
/* The array may not be degraded, this is just a good time
@ -467,13 +458,20 @@ static void handle_message(struct supertype *container, struct metadata_update *
struct metadata_update *mu;
if (msg->len == 0) {
int cnt = monitor_loop_cnt;
int cnt;
while (update_queue_pending || update_queue) {
check_update_queue(container);
usleep(15*1000);
}
cnt = monitor_loop_cnt;
if (cnt & 1)
cnt += 2; /* wait until next pselect */
else
cnt += 3; /* wait for 2 pselects */
wakeup_monitor();
wait_update_handled();
while (monitor_loop_cnt - cnt < 0)
usleep(10 * 1000);
} else {
@ -536,20 +534,29 @@ void do_manager(struct supertype *container)
if (exit_now)
exit(0);
mdstat = mdstat_read(1, 0);
/* Can only 'manage' things if 'monitor' is not making
* structural changes to metadata, so need to check
* update_queue
*/
if (update_queue == NULL) {
mdstat = mdstat_read(1, 0);
manage(mdstat, container);
manage(mdstat, container);
read_sock(container);
free_mdstat(mdstat);
read_sock(container);
free_mdstat(mdstat);
}
remove_old();
check_update_queue(container);
manager_ready = 1;
mdstat_wait_fd(container->sock, &set);
if (update_queue == NULL)
mdstat_wait_fd(container->sock, &set);
else
/* If an update is happening, just wait for signal */
pselect(0, NULL, NULL, NULL, NULL, &set);
} while(1);
}