*
*/
+#define ARRAY_DIRTY 1
+#define ARRAY_BUSY 2
static int read_and_act(struct active_array *a)
{
unsigned long long sync_completed;
int check_reshape = 0;
int deactivate = 0;
struct mdinfo *mdi;
- int dirty = 0;
+ int ret = 0;
int count = 0;
a->next_state = bad_word;
if (a->curr_state == write_pending) {
a->container->ss->set_array_state(a, 0);
a->next_state = active;
- dirty = 1;
+ ret |= ARRAY_DIRTY;
}
if (a->curr_state == active_idle) {
/* Set array to 'clean' FIRST, then mark clean
* in the metadata
*/
a->next_state = clean;
- dirty = 1;
+ ret |= ARRAY_DIRTY;
}
if (a->curr_state == clean) {
a->container->ss->set_array_state(a, 1);
if (a->curr_state == active ||
a->curr_state == suspended ||
a->curr_state == bad_word)
- dirty = 1;
+ ret |= ARRAY_DIRTY;
if (a->curr_state == readonly) {
/* Well, I'm ready to handle things. If readonly
* wasn't requested, transition to read-auto.
a->next_state = read_auto; /* array is clean */
else {
a->next_state = active; /* Now active for recovery etc */
- dirty = 1;
+ ret |= ARRAY_DIRTY;
}
}
}
a->container->ss->set_disk(a, mdi->disk.raid_disk,
mdi->curr_state);
check_degraded = 1;
- mdi->next_state |= DS_UNBLOCK;
+ if (mdi->curr_state & DS_BLOCKED)
+ mdi->next_state |= DS_UNBLOCK;
if (a->curr_state == read_auto) {
a->container->ss->set_array_state(a, 0);
a->next_state = active;
if ((mdi->next_state & DS_REMOVE) && mdi->state_fd >= 0) {
int remove_result;
- /* the kernel may not be able to immediately remove the
- * disk, we can simply wait until the next event to try
- * again.
+ /* The kernel may not be able to immediately remove the
+ * disk. In that case we wait a little while and
+ * try again.
*/
remove_result = write_attr("remove", mdi->state_fd);
if (remove_result > 0) {
close(mdi->state_fd);
close(mdi->recovery_fd);
mdi->state_fd = -1;
- }
+ } else
+ ret |= ARRAY_BUSY;
}
if (mdi->next_state & DS_INSYNC) {
write_attr("+in_sync", mdi->state_fd);
if (deactivate)
a->container = NULL;
- return dirty;
+ return ret;
}
static struct mdinfo *
struct timespec ts;
ts.tv_sec = 24*3600;
ts.tv_nsec = 0;
- if (*aap == NULL) {
+ if (*aap == NULL || container->retry_soon) {
/* just waiting to get O_EXCL access */
ts.tv_sec = 0;
ts.tv_nsec = 20000000ULL;
#ifdef DEBUG
dprint_wake_reasons(&rfds);
#endif
-
+ container->retry_soon = 0;
}
if (update_queue) {
rv = 0;
dirty_arrays = 0;
for (a = *aap; a ; a = a->next) {
- int is_dirty;
if (a->replaces && !discard_this) {
struct active_array **ap;
signal_manager();
}
if (a->container && !a->to_remove) {
- is_dirty = read_and_act(a);
+ int ret = read_and_act(a);
rv |= 1;
- dirty_arrays += is_dirty;
+ dirty_arrays += !!(ret & ARRAY_DIRTY);
/* when terminating stop manipulating the array after it
* is clean, but make sure read_and_act() is given a
* chance to handle 'active_idle'
*/
- if (sigterm && !is_dirty)
+ if (sigterm && !(ret & ARRAY_DIRTY))
a->container = NULL; /* stop touching this array */
+ if (ret & ARRAY_BUSY)
+ container->retry_soon = 1;
}
}